Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
56 commits
Select commit Hold shift + click to select a range
8e20927
Adds tests for ensuring the output from the optimizing compiler. Add …
DBooots Mar 2, 2026
844d8df
Initial implementation of Three-Address Code interim representation. …
DBooots Mar 2, 2026
cd2448f
Clean up IR building code. Ensure IRInstructions remember the source …
DBooots Mar 6, 2026
3f609ff
Align IRInstruction property names and accessibility. Add interfaces …
DBooots Mar 6, 2026
1344914
Add concept of Extended Basic Blocks to help with future analysis and…
DBooots Mar 7, 2026
28410f0
Add abstract IRVariableBase class so that IRTemp can share some commo…
DBooots Mar 7, 2026
171b2bc
Add methods to, outside of executing an opcode, invoke the same math …
DBooots Mar 7, 2026
a53f7b3
Add convenience constructor for compilation exceptions arising from I…
DBooots Mar 7, 2026
131a4a9
Add constant folding pass. This reduces any constant expressions to t…
DBooots Mar 7, 2026
cd3104f
Add constant folding for built-in scalar function calls. This require…
DBooots Mar 7, 2026
2f11d21
Add infrastructure for automatic inclusion of optimization passes usi…
DBooots Mar 7, 2026
159e068
Move the InterimCPU ownership to IROptimizer to share resources acros…
DBooots Mar 7, 2026
2a71ecc
Add suffix replacement pass. This replaces all ship: suffixes that ca…
DBooots Mar 7, 2026
eb11e29
Store variable and constant source line and column so that (theoretic…
DBooots Mar 8, 2026
25b2897
Offload optimization steps from Compiler. Add a new IRCodePart repres…
DBooots Mar 8, 2026
c4da4df
Add nonsequential label capability to BasicBlocks to account for weir…
DBooots Mar 8, 2026
8f0ee70
Implement arg tests.
DBooots Mar 8, 2026
3a5cf78
Fix stack underflow when storing parameters.
DBooots Mar 8, 2026
6651a5f
Rewrite IRCodePart and the flow from Compiler to Optimizer to enable …
DBooots Mar 8, 2026
048d5bb
Give BasicBlocks unique IDs across the entire compilation, rather tha…
DBooots Mar 8, 2026
60c4458
Add concept of dominance to basic blocks. This will be key for determ…
DBooots Mar 8, 2026
cb8e5c6
Introduce IRParameter as a special type of IRValue, for instances whe…
DBooots Mar 8, 2026
294900f
Add Dead Code Elimination pass. This pass eliminates any basic blocks…
DBooots Mar 9, 2026
f727550
Adjust file structure and namespaces to be cleaner. Adjust numbering …
DBooots Mar 9, 2026
4d59836
Outline planned sorting of optimization passes.
DBooots Mar 9, 2026
91f179a
Clean up code for DCE and downgrade it to IHolisticOptimizationPass.
DBooots Mar 9, 2026
b0b85b9
Add methods for storing variable at local, global, or ambiguous scope…
DBooots Mar 10, 2026
80e6cc3
Add X/X=1 simplification to the constant folding pass. This will say …
DBooots Mar 10, 2026
0afa7aa
Add set access to IRInstruction interfaces, as well as indexing for I…
DBooots Mar 11, 2026
cf88539
Make ConstantFolding.AttemptReduction publicly accessible to allow la…
DBooots Mar 11, 2026
a435ddb
Provide a method for overwriting the source location of an instructio…
DBooots Mar 11, 2026
336ac48
Add a static utility class to make further passes that search the ins…
DBooots Mar 11, 2026
a879ba8
Implement equality checking for IR values and instructions. Instructi…
DBooots Mar 12, 2026
c86d308
Fix binary instructions losing appropriate commutative status when th…
DBooots Mar 12, 2026
852ece8
Add an argument marker to the stack before running a unit test progra…
DBooots Mar 12, 2026
73dee51
Force clobber builtins as necessary.
DBooots Mar 12, 2026
60624a6
Add a peephole optimization pass. This pass makes various small optim…
DBooots Mar 12, 2026
b6bb80c
Add property to enumerate which blocks are dominated by a BasicBlock.
DBooots Mar 12, 2026
ef43c4c
Implement scope awareness for BasicBlocks. Class IRScope should not b…
DBooots Mar 12, 2026
9dbea38
Add pass to remove unnecessary scope pushes and pops. This also remov…
DBooots Mar 12, 2026
dfaa8ad
Implement scope awareness into IRVariableBase so that variables are c…
DBooots Mar 12, 2026
bd24143
Finish peephole optimization pass by implementing lex indexing shortc…
DBooots Mar 12, 2026
281d3ae
Clean up and restructure IRCodePart and its child classes.
DBooots Mar 12, 2026
5040e46
Fix opcodebranch where the jump is relative instead of a label. Fix e…
DBooots Mar 13, 2026
567a7ae
Fix IRCodePart behaviour for triggers. It turns out they aren't just …
DBooots Mar 13, 2026
04ca8ce
Harmonize IRVariableBase and subclass equality, hashing, and string o…
DBooots Mar 13, 2026
58f6e52
Make IRAssignment more strict by knowing the exact variable (with sco…
DBooots Mar 13, 2026
898bd3a
Improve debug string readability.
DBooots Mar 13, 2026
5b42033
Fix collection changed while enumerating exception.
DBooots Mar 13, 2026
023de41
Fix infinite loop when dumping the tree where there is a loop contained.
DBooots Mar 13, 2026
c59ce69
Fix equality not working between constants.
DBooots Mar 14, 2026
b59a7b0
Add constant propagation pass. This pass replaces local variables wit…
DBooots Mar 14, 2026
7cfbd79
Patch scopes losing ancestry when an unused scope is collapsed.
DBooots Mar 14, 2026
b094ce3
Add return type indicator to FunctionAttribute and tag all kOS functi…
DBooots Mar 17, 2026
8faf614
Fix Structure not counting as a valid return type.
DBooots Mar 17, 2026
9402dce
Add methods to check if functions are invariant and to get their retu…
DBooots Mar 17, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
63 changes: 63 additions & 0 deletions kerboscript_tests/integration/constantPropagation.ks
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
@lazyGlobal OFF.

global a is 5.
global _false is false.

local b is 2.
local c is 4.
local d is 7.
local h is false.

print("test"). // The assignments should happen after this line.

print(b+c). // 6
print(h). // False

global function func {
print(b+c). // 6
print(b+d). // 9
print(b+a). // 7
set h to true.
}

func().

{
local i is 10.
print(i). // 10
print(i+c). // 14
}

print(h). // True

set h to false.

print(h). // False

lock e to a + b.

print(e). // 7
set b to 1.
print(e). // 6

lock g to c + d.
print(g). // 11
set d to 5.
print(g). // 9

when _false then {
set c to 10.
}

print(b+c). // 5

set b to 1.
set b to b + d.

print(b). // 6

until b = 1 {
set b to b - 1.
}

print(b). // 1
5 changes: 5 additions & 0 deletions kerboscript_tests/integration/operators.ks
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,8 @@ print(1 = 1).
print(1 <> 2).
print(true and true).
print(true or false).
print("A" + "b").
print(a * 0).
print(a ^ 0).
print(arcTan2(0,1)).
print(abs(-1)).
21 changes: 21 additions & 0 deletions kerboscript_tests/integration/operators_invalid.ks
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@

set a to 0.

print(+ 1).
print(- (-1)).
print(not false).
print(defined a).

print(1 + 2).
print(2 * 3).
print(4 / 2).
print(3 ^ 2).
print(2 > 1).
print(2 >= 1).
print(1 < 2).
print(1 <= 2).
print(1 = 1).
print(1 <> 2).
print(true and true).
print(true or false).
print(1 + false).
51 changes: 51 additions & 0 deletions kerboscript_tests/integration/peepholeOptimizations.ks
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
parameter a is TRUE.
parameter c is 3.
parameter x is 2.
parameter z is 5.

print("test":typename()).
// v() is unavailable in unit testing.
//local v1 is v(1,2,3).
//local v2 is v(3,4,5).
// Multiplying scalars will work equally well.
local v1 is 2.
local v2 is 3.

print(vectorDotProduct(v1,v2)). // =6
print(vdot(v1,v2)). // =6

if not a {
print("Don't print this.").
}

if not (not a) {
print("Print this.").
}

print(c*x+c*z). // = 21
print(c*x+z*c). // = 21
print(x*c+c*z). // = 21
print(x*c+z*c). // = 21

print(-x+z). // = 3
print(x+-z). // = -3

print(x--z). // = 7

print(x^z/x). // = 16
print(z^4/z). // = 125

print(x^z*x). // = 64
print(z^4*z). // = 3125

print(x^z*x^c). // = 256

print(x^z/x^c). // = 4

print(z^3/z). // = 25

print(z*z*z). // = 125

print(z^3/z*z). // = 125

print(x^2*x^z/x*x^3). // = 512
5 changes: 5 additions & 0 deletions kerboscript_tests/integration/suffixReplacement.ks
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
@CLOBBERBUILTINS OFF.
set airspeed to 100. // Clobber the built-in so that this value is pulled after replacement.
print(CONSTANT:g0).
print(CONSTANT():pi).
print(SHIP:airspeed).
5 changes: 4 additions & 1 deletion src/kOS.Safe.Test/Execution/BaseIntegrationTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ public abstract class BaseIntegrationTest
private SafeSharedObjects shared;
private Screen screen;
private string baseDir;
protected virtual OptimizationLevel OptimizationLevel => OptimizationLevel.None;

private string FindKerboscriptTests()
{
Expand Down Expand Up @@ -86,12 +87,14 @@ protected void RunScript(string fileName)
IsCalledFromRun = false,
FuncManager = shared.FunctionManager,
BindManager = shared.BindingMgr,
AllowClobberBuiltins = SafeHouse.Config.AllowClobberBuiltIns
AllowClobberBuiltins = SafeHouse.Config.AllowClobberBuiltIns,
OptimizationLevel = OptimizationLevel
});
cpu.Boot();

screen.ClearOutput();

cpu.PushArgumentStack(new KOSArgMarkerType());
cpu.GetCurrentContext().AddParts(compiled);
}

Expand Down
210 changes: 210 additions & 0 deletions src/kOS.Safe.Test/Execution/OptimizationTest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,210 @@
using System;
using NUnit.Framework;
using kOS.Safe.Compilation;
using kOS.Safe.Exceptions;

namespace kOS.Safe.Test.Execution
{
[TestFixture]
public class OptimizationTest : BaseIntegrationTest
{
protected override OptimizationLevel OptimizationLevel => OptimizationLevel.Minimal;

[Test]
public void TestBasic()
{
// Tests that the bare minimum works

RunScript("integration/basic.ks");
RunSingleStep();
AssertOutput(
"text"
);
}

[Test]
public void TestVars()
{
// Tests that basic variable assignment and reference works

RunScript("integration/vars.ks");
RunSingleStep();
AssertOutput(
"1",
"2",
"3"
);
}

[Test]
public void TestFunc()
{
// Tests that basic no-args function calls work

RunScript("integration/func.ks");
RunSingleStep();
AssertOutput(
"a"
);
}

[Test]
public void TestFuncArgs()
{
// Tests that explicit and default function parameters work

RunScript("integration/func_args.ks");
RunSingleStep();
AssertOutput(
"0",
"1",
"2",
"3"
);
}

[Test]
public void TestOperators()
{
// Test that all the basic operators work

RunScript("integration/operators.ks");
RunSingleStep();
AssertOutput(
"1",
"1",
"True",
"True",
"3",
"6",
"2",
"9",
"True",
"True",
"True",
"True",
"True",
"True",
"True",
"True",
"Ab",
"0",
"1",
"0",
"1"
);
}

[Test]
[ExpectedException(typeof(KOSCompileException))]
public void TestOperatorsException()
{
// Test that an invalid operation throws a compile error during constant folding
RunScript("integration/operators_invalid.ks");
RunSingleStep();
}

[Test]
public void TestLock()
{
// Test that locks in the same file works
RunScript("integration/lock.ks");
RunSingleStep();
AssertOutput(
"3",
"4",
"5"
);
}

[Test]
public void TestSuffixes()
{
// Test that various suffix and index combinations work for getting and setting
RunScript("integration/suffixes.ks");
RunSingleStep();
RunSingleStep();
AssertOutput(
"0",
"1",
"2",
"3",
"0",
"False"
);
}

[Test]
public void TestSuffixReplacement()
{
// Test that certain suffixes are replaced
RunScript("integration/suffixReplacement.ks");
RunSingleStep();
AssertOutput(
"9.80665",
"3.14159265358979",
"100"
);
}


[Test]
public void TestPeepholeOptimizations()
{
// Test that certain suffixes are replaced
RunScript("integration/peepholeOptimizations.ks");
RunSingleStep();
AssertOutput(
"String",
"6",
"6",
"Print this.",
"21",
"21",
"21",
"21",
"3",
"-3",
"7",
"16",
"125",
"64",
"3125",
"256",
"4",
"25",
"125",
"125",
"512"
);
}


[Test]
public void TestConstantPropagation()
{
// Test that local constant variables propagate
RunScript("integration/constantPropagation.ks");
RunSingleStep();
AssertOutput(
"test",
"6",
"False",
"6",
"9",
"7",
"10",
"14",
"True",
"False",
"7",
"6",
"11",
"9",
"5",
"6",
"1"
);
}
}
}
Loading