check 'if' condition type, mark functions constant, improved tests
This commit is contained in:
		
							parent
							
								
									eae3c68b51
								
							
						
					
					
						commit
						68093f96e9
					
				| 
						 | 
				
			
			@ -180,6 +180,7 @@ public class BoppiChecker extends BoppiBaseVisitor<Type> {
 | 
			
		|||
			FunctionType type = new FunctionType(returnType, parameterTypes);
 | 
			
		||||
 | 
			
		||||
			Variable<Type> 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<Type> {
 | 
			
		|||
	@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));
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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());
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
	 */
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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))));
 | 
			
		||||
		});
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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)));
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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")));
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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()));
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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());
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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());
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -32,4 +32,6 @@ myBool := {
 | 
			
		|||
        99 + (myInt := 100);
 | 
			
		||||
    };
 | 
			
		||||
    otherInt > 3;
 | 
			
		||||
}
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
print(otherInt, myInt, myBool);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue