From 68093f96e9b09dc6ce75cd02866fd8d131457d8c Mon Sep 17 00:00:00 2001 From: User <> Date: Tue, 28 Nov 2017 16:45:15 +0100 Subject: [PATCH] check 'if' condition type, mark functions constant, improved tests --- src/pp/s1184725/boppi/BoppiChecker.java | 4 ++- src/pp/s1184725/boppi/antlr/Boppi.g4 | 2 +- src/pp/s1184725/boppi/test/ArrayTest.java | 1 - .../s1184725/boppi/test/ConditionalTest.java | 15 ++++++++++ .../s1184725/boppi/test/ExpressionTest.java | 8 +++-- .../boppi/test/ILOCAllocatorTest.java | 1 - .../boppi/test/SimpleFunctionTest.java | 30 ++++++++++++++++++- .../boppi/test/SimpleVariableTest.java | 5 +++- .../boppi/test/programs/closure2.boppi | 5 ++-- .../boppi/test/programs/closure3.boppi | 5 ++-- .../test/programs/fibonacciRecursive.boppi | 18 ++++++----- .../boppi/test/programs/simpleScope.boppi | 4 ++- 12 files changed, 77 insertions(+), 21 deletions(-) diff --git a/src/pp/s1184725/boppi/BoppiChecker.java b/src/pp/s1184725/boppi/BoppiChecker.java index 7528963..7ac6ae3 100644 --- a/src/pp/s1184725/boppi/BoppiChecker.java +++ b/src/pp/s1184725/boppi/BoppiChecker.java @@ -180,6 +180,7 @@ public class BoppiChecker extends BoppiBaseVisitor { FunctionType type = new FunctionType(returnType, parameterTypes); Variable func = an.symbols.put(ctx.name.getText(), type); + func.setConstant(true); func.assign(); an.variables.put(ctx, func); @@ -207,7 +208,8 @@ public class BoppiChecker extends BoppiBaseVisitor { @Override public Type visitIf(IfContext ctx) { return an.symbols.withScope(() -> { - visit(ctx.cond); + checkConstraint(visit(ctx.cond), SimpleType.BOOL, ctx.cond); + if (ctx.onFalse != null) { Type trueType = an.symbols.withScope(() -> visit(ctx.onTrue)); Type falseType = an.symbols.withScope(() -> visit(ctx.onFalse)); diff --git a/src/pp/s1184725/boppi/antlr/Boppi.g4 b/src/pp/s1184725/boppi/antlr/Boppi.g4 index cffa21f..6d517a8 100644 --- a/src/pp/s1184725/boppi/antlr/Boppi.g4 +++ b/src/pp/s1184725/boppi/antlr/Boppi.g4 @@ -16,7 +16,6 @@ stat declareStat : DECLARE CONSTANT? type IDENTIFIER #declare | FUNCTION (result=type)? name=IDENTIFIER PAROPEN parameters? PARCLOSE body=expr #declareFunction - | LAMBDA IDENTIFIER+ ARROW expr #lambda ; assignStat @@ -36,6 +35,7 @@ expr | OUT PAROPEN expr (LISTDELIM expr)* PARCLOSE #write | IFOPEN cond=stats IFTRUE onTrue=stats (IFFALSE onFalse=stats)? IFCLOSE #if | WHILEOPEN cond=stats WHILETRUE onTrue=stats WHILECLOSE #while + | LAMBDA IDENTIFIER+ ARROW expr #lambda | variable PAROPEN (expr (LISTDELIM expr)*)? PARCLOSE #call | variable #getVariable | LITERAL10 #literalInteger diff --git a/src/pp/s1184725/boppi/test/ArrayTest.java b/src/pp/s1184725/boppi/test/ArrayTest.java index fc6d6b4..46da063 100644 --- a/src/pp/s1184725/boppi/test/ArrayTest.java +++ b/src/pp/s1184725/boppi/test/ArrayTest.java @@ -17,7 +17,6 @@ public class ArrayTest { @Test public void correctArrayParsing() { BoppiTests.parseFile("simpleArray.boppi"); - BoppiTests.log.forEach((l)->System.out.println(l.getMessage())); assertThat(BoppiTests.log, empty()); } diff --git a/src/pp/s1184725/boppi/test/ConditionalTest.java b/src/pp/s1184725/boppi/test/ConditionalTest.java index 727530d..69c2bf8 100644 --- a/src/pp/s1184725/boppi/test/ConditionalTest.java +++ b/src/pp/s1184725/boppi/test/ConditionalTest.java @@ -35,6 +35,21 @@ public class ConditionalTest { assertThat(BoppiTests.log, is(empty())); } + /** + * Wrong if-else and loop use + */ + @Test + public void wrongConditionalChecking() { + BoppiTests.checkString("if 5 then 0 fi"); + assertThat(BoppiTests.log, hasSize(1)); + + BoppiTests.checkString("5 + if true then 3 fi"); + assertThat(BoppiTests.log, hasSize(1)); + + BoppiTests.checkString("while 'a' do 1+1 od"); + assertThat(BoppiTests.log, hasSize(1)); + } + /** * Correct evaluation of basic programs */ diff --git a/src/pp/s1184725/boppi/test/ExpressionTest.java b/src/pp/s1184725/boppi/test/ExpressionTest.java index 15670fd..76abbc8 100644 --- a/src/pp/s1184725/boppi/test/ExpressionTest.java +++ b/src/pp/s1184725/boppi/test/ExpressionTest.java @@ -8,6 +8,8 @@ import java.util.logging.Level; import org.apache.commons.lang3.StringUtils; import org.junit.Test; +import pp.s1184725.boppi.util.RegisterPool; + /** * Test cases for the basic expression language. * @@ -82,14 +84,16 @@ public class ExpressionTest { public void correctExpressionGeneration() { BoppiTests.compileAndRunFile("simpleExpression.boppi"); assertThat(BoppiTests.log, is(empty())); + assertThat(BoppiTests.out, is(arrayContaining("1", "1", "3", "A", "false"))); - int n = 12; - String expression = StringUtils.repeat("1+(", n) + "1" + StringUtils.repeat(")", n); + int n = RegisterPool.RECOMMENDED_REGISTER_COUNT+3; + String expression = StringUtils.repeat("1+(", n) + "0" + StringUtils.repeat(")", n); BoppiTests.withWarnings(() -> { BoppiTests.compileAndRunString("print(" + expression + ")", "" + n); assertThat(BoppiTests.log, hasSize(1)); assertThat(BoppiTests.log.get(0).getLevel(), is(Level.WARNING)); + assertThat(BoppiTests.out, is(arrayContaining(Integer.toString(n)))); }); } diff --git a/src/pp/s1184725/boppi/test/ILOCAllocatorTest.java b/src/pp/s1184725/boppi/test/ILOCAllocatorTest.java index edb9f1d..8c46479 100644 --- a/src/pp/s1184725/boppi/test/ILOCAllocatorTest.java +++ b/src/pp/s1184725/boppi/test/ILOCAllocatorTest.java @@ -106,7 +106,6 @@ public class ILOCAllocatorTest { */ @Test public void simpleMallocFree() { -// Simulator.DEBUG = true; sim(malloc(11, obj1)); assertThat(vm.getInterrupt(), is(0)); assertThat(vm.load(FIRSTPTR), is(not(FIRSTSLOT))); diff --git a/src/pp/s1184725/boppi/test/SimpleFunctionTest.java b/src/pp/s1184725/boppi/test/SimpleFunctionTest.java index 488bce8..7683a54 100644 --- a/src/pp/s1184725/boppi/test/SimpleFunctionTest.java +++ b/src/pp/s1184725/boppi/test/SimpleFunctionTest.java @@ -16,6 +16,12 @@ public class SimpleFunctionTest { */ @Test public void correctFunctionParsing() { + BoppiTests.parseString("function constantProcedure() 0; 1"); + assertThat(BoppiTests.log, is(empty())); + + BoppiTests.parseString("function procedure(int a) a; 1"); + assertThat(BoppiTests.log, is(empty())); + BoppiTests.parseString("function int id(int a) a; 1"); assertThat(BoppiTests.log, is(empty())); @@ -40,9 +46,12 @@ public class SimpleFunctionTest { */ @Test public void wrongFunctionParsing() { - BoppiTests.parseString("function char add(int a, int b);"); + BoppiTests.parseString("function char add(int a, int b); 'c'"); assertThat(BoppiTests.log, hasSize(1)); + BoppiTests.parseString("function char add(a, b); 1"); + assertThat(BoppiTests.log, is(not(empty()))); + BoppiTests.parseString("function int add(int a, int b) a+b; add(4,)"); assertThat(BoppiTests.log, hasSize(1)); } @@ -69,6 +78,9 @@ public class SimpleFunctionTest { BoppiTests.checkString("function int factorial(int n) {if (n > 1) then n*factorial(n-1) else 1 fi}; 0"); assertThat(BoppiTests.log, is(empty())); + + BoppiTests.checkString("var int a; a := 1; function int id(int a) a; 1"); + assertThat(BoppiTests.log, is(empty())); } /** @@ -76,6 +88,9 @@ public class SimpleFunctionTest { */ @Test public void wrongFunctionChecking() { + BoppiTests.checkString("var int add; add := 1; add(4, 2)"); + assertThat(BoppiTests.log, hasSize(1)); + BoppiTests.checkString("function int add(int a, char b) a+b; print(add(4, 'T')+1)"); assertThat(BoppiTests.log, hasSize(1)); @@ -84,6 +99,15 @@ public class SimpleFunctionTest { BoppiTests.checkString("function int add(int a, int b) a+b; print(add(4, 'T')+1)"); assertThat(BoppiTests.log, hasSize(1)); + + BoppiTests.checkString("function int id(int a) a; print(id(4, 2)+1)"); + assertThat(BoppiTests.log, hasSize(1)); + + BoppiTests.checkString("function nothing(int a) a; print(nothing(2))"); + assertThat(BoppiTests.log, hasSize(1)); + + BoppiTests.checkString("function int add(int a, int b) a+b; print(add(4)+1)"); + assertThat(BoppiTests.log, hasSize(1)); } /** @@ -104,6 +128,10 @@ public class SimpleFunctionTest { assertThat(BoppiTests.log, is(empty())); assertThat(BoppiTests.out, is(arrayContaining("1"))); + BoppiTests.compileAndRunString("var int a; a := 1; function int id(int a) a; print(id(4))"); + assertThat(BoppiTests.log, is(empty())); + assertThat(BoppiTests.out, is(arrayContaining("4"))); + BoppiTests.compileAndRunString("function int add(int a, int b) a+b; print(add(4, 5)+1)"); assertThat(BoppiTests.log, is(empty())); assertThat(BoppiTests.out, is(arrayContaining("10"))); diff --git a/src/pp/s1184725/boppi/test/SimpleVariableTest.java b/src/pp/s1184725/boppi/test/SimpleVariableTest.java index a3180be..8540947 100644 --- a/src/pp/s1184725/boppi/test/SimpleVariableTest.java +++ b/src/pp/s1184725/boppi/test/SimpleVariableTest.java @@ -126,7 +126,10 @@ public class SimpleVariableTest { @Test public void correctVariableGeneration() { BoppiTests.compileAndRunFile("simpleVariable.boppi"); - BoppiTests.log.forEach((l)->System.out.println(l.getMessage())); + assertThat(BoppiTests.log, is(empty())); + + BoppiTests.compileAndRunFile("simpleScope.boppi"); + assertThat(BoppiTests.out, is(arrayContaining("9", "4", "true"))); assertThat(BoppiTests.log, is(empty())); } diff --git a/src/pp/s1184725/boppi/test/programs/closure2.boppi b/src/pp/s1184725/boppi/test/programs/closure2.boppi index 481d79e..b5118b3 100644 --- a/src/pp/s1184725/boppi/test/programs/closure2.boppi +++ b/src/pp/s1184725/boppi/test/programs/closure2.boppi @@ -28,7 +28,8 @@ function (int,int)->int logCalls((int,int)->int f) { return }; -add := logCalls(add); +var add add_; +add_ := logCalls(add); -print(add(1,6), add(10,5)); +print(add_(1,6), add_(10,5)); print(getCalls()); diff --git a/src/pp/s1184725/boppi/test/programs/closure3.boppi b/src/pp/s1184725/boppi/test/programs/closure3.boppi index d14e1d2..f6ee819 100644 --- a/src/pp/s1184725/boppi/test/programs/closure3.boppi +++ b/src/pp/s1184725/boppi/test/programs/closure3.boppi @@ -20,9 +20,10 @@ function int main1() { return }; - add := logCalls(add); + var add add_; + add_ := logCalls(add); - print(add(1,6), add(10,5)); + print(add_(1,6), add_(10,5)); print(getCalls()); }; diff --git a/src/pp/s1184725/boppi/test/programs/fibonacciRecursive.boppi b/src/pp/s1184725/boppi/test/programs/fibonacciRecursive.boppi index 20a2868..2b97bb0 100644 --- a/src/pp/s1184725/boppi/test/programs/fibonacciRecursive.boppi +++ b/src/pp/s1184725/boppi/test/programs/fibonacciRecursive.boppi @@ -2,13 +2,7 @@ var int n; -function int fib(int n) { - if n < 2 then - 1 - else - fib(n-1)+fib(n-2) - fi -}; +var (int)->int fib; function fib memoize(fib f) { var [50]int memo; @@ -33,7 +27,15 @@ function fib memoize(fib f) { memoFib }; -fib := memoize(fib); +function int fib_(int n) { + if n < 2 then + 1 + else + fib(n-1)+fib(n-2) //has to call `fib` instead of `fib_` because `fib_` is constant + fi +}; + +fib := memoize(fib_); read(n); diff --git a/src/pp/s1184725/boppi/test/programs/simpleScope.boppi b/src/pp/s1184725/boppi/test/programs/simpleScope.boppi index 2ee25e7..efc8f72 100644 --- a/src/pp/s1184725/boppi/test/programs/simpleScope.boppi +++ b/src/pp/s1184725/boppi/test/programs/simpleScope.boppi @@ -32,4 +32,6 @@ myBool := { 99 + (myInt := 100); }; otherInt > 3; -} +}; + +print(otherInt, myInt, myBool);