diff --git a/Test/JavaSources/Main.java b/Test/JavaSources/Main.java index b912e91..e3b7b76 100644 --- a/Test/JavaSources/Main.java +++ b/Test/JavaSources/Main.java @@ -15,6 +15,7 @@ public class Main { TestMultipleClasses multipleClasses = new TestMultipleClasses(); TestRecursion recursion = new TestRecursion(10); TestMalicious malicious = new TestMalicious(); + TestLoop loop = new TestLoop(); // constructing a basic class works assert empty != null; @@ -32,6 +33,7 @@ public class Main { assert recursion.child.child.child.child.child.value == 5; // self-referencing methods work. assert recursion.fibonacci(15) == 610; + assert loop.factorial(5) == 120; // intentionally dodgy expressions work assert malicious.assignNegativeIncrement(42) == -42; assert malicious.tripleAddition(1, 2, 3) == 6; diff --git a/Test/JavaSources/TestLoop.java b/Test/JavaSources/TestLoop.java new file mode 100644 index 0000000..40491fb --- /dev/null +++ b/Test/JavaSources/TestLoop.java @@ -0,0 +1,12 @@ +public class TestLoop { + public int factorial(int n) + { + int tally = 1; + for(int i = 1; i <= n; i++) + { + tally *= i; + } + + return tally; + } +} diff --git a/src/ByteCode/Assembler.hs b/src/ByteCode/Assembler.hs index 101d7aa..555569b 100644 --- a/src/ByteCode/Assembler.hs +++ b/src/ByteCode/Assembler.hs @@ -221,26 +221,26 @@ assembleStatement (constants, ops, lvars) (TypedStatement _ (Block statements)) assembleStatement (constants, ops, lvars) (TypedStatement dtype (If expr if_stmt else_stmt)) = let (constants_cmp, ops_cmp, _) = assembleExpression (constants, [], lvars) expr - (constants_ifa, ops_ifa, _) = assembleStatement (constants_cmp, [], lvars) if_stmt + (constants_ifa, ops_ifa, lvars_ifa) = assembleStatement (constants_cmp, [], lvars) if_stmt (constants_elsea, ops_elsea, _) = case else_stmt of - Nothing -> (constants_ifa, [], lvars) - Just stmt -> assembleStatement (constants_ifa, [], lvars) stmt + Nothing -> (constants_ifa, [], lvars_ifa) + Just stmt -> assembleStatement (constants_ifa, [], lvars_ifa) stmt -- +6 because we insert 2 gotos, one for if, one for else if_length = sum (map opcodeEncodingLength ops_ifa) -- +3 because we need to account for the goto in the if statement. else_length = sum (map opcodeEncodingLength ops_elsea) in case dtype of - "void" -> (constants_ifa, ops ++ ops_cmp ++ [Opsipush 0, Opif_icmpeq (if_length + 6)] ++ ops_ifa ++ [Opgoto (else_length + 3)] ++ ops_elsea, lvars) - _ -> (constants_ifa, ops ++ ops_cmp ++ [Opsipush 0, Opif_icmpeq (if_length + 3)] ++ ops_ifa ++ ops_elsea, lvars) + "void" -> (constants_ifa, ops ++ ops_cmp ++ [Opsipush 0, Opif_icmpeq (if_length + 6)] ++ ops_ifa ++ [Opgoto (else_length + 3)] ++ ops_elsea, lvars_ifa) + _ -> (constants_ifa, ops ++ ops_cmp ++ [Opsipush 0, Opif_icmpeq (if_length + 3)] ++ ops_ifa ++ ops_elsea, lvars_ifa) assembleStatement (constants, ops, lvars) (TypedStatement _ (While expr stmt)) = let (constants_cmp, ops_cmp, _) = assembleExpression (constants, [], lvars) expr - (constants_stmta, ops_stmta, _) = assembleStatement (constants_cmp, [], lvars) stmt + (constants_stmta, ops_stmta, lvars_stmta) = assembleStatement (constants_cmp, [], lvars) stmt -- +3 because we insert 2 gotos, one for the comparison, one for the goto back to the comparison stmt_length = sum (map opcodeEncodingLength ops_stmta) + 6 entire_length = stmt_length + sum (map opcodeEncodingLength ops_cmp) in - (constants_stmta, ops ++ ops_cmp ++ [Opsipush 0, Opif_icmpeq stmt_length] ++ ops_stmta ++ [Opgoto (-entire_length)], lvars) + (constants_stmta, ops ++ ops_cmp ++ [Opsipush 0, Opif_icmpeq stmt_length] ++ ops_stmta ++ [Opgoto (-entire_length)], lvars_stmta) assembleStatement (constants, ops, lvars) (TypedStatement _ (LocalVariableDeclaration (VariableDeclaration dtype name expr))) = let isPrimitive = elem dtype ["char", "boolean", "int"]