]> gerrit.simantics Code Review - simantics/platform.git/blob - tests/org.simantics.scl.compiler.tests/src/org/simantics/scl/compiler/tests/TestExpressionEvaluator.java
Merge commit 'bf75fd9'
[simantics/platform.git] / tests / org.simantics.scl.compiler.tests / src / org / simantics / scl / compiler / tests / TestExpressionEvaluator.java
1 package org.simantics.scl.compiler.tests;
2
3 import java.util.Arrays;
4
5 import org.junit.Before;
6 import org.junit.Test;
7 import org.simantics.scl.compiler.elaboration.expressions.EVariable;
8 import org.simantics.scl.compiler.elaboration.expressions.Expression;
9 import org.simantics.scl.compiler.elaboration.expressions.Variable;
10 import org.simantics.scl.compiler.environment.AbstractLocalEnvironment;
11 import org.simantics.scl.compiler.environment.Environment;
12 import org.simantics.scl.compiler.environment.LocalEnvironment;
13 import org.simantics.scl.compiler.environment.specification.EnvironmentSpecification;
14 import org.simantics.scl.compiler.errors.CompilationErrorFormatter;
15 import org.simantics.scl.compiler.module.repository.ImportFailure;
16 import org.simantics.scl.compiler.module.repository.ImportFailureException;
17 import org.simantics.scl.compiler.module.repository.ModuleRepository;
18 import org.simantics.scl.compiler.runtime.RuntimeEnvironment;
19 import org.simantics.scl.compiler.source.repository.CompositeModuleSourceRepository;
20 import org.simantics.scl.compiler.source.repository.SourceRepositories;
21 import org.simantics.scl.compiler.top.ExpressionEvaluator;
22 import org.simantics.scl.compiler.top.SCLExpressionCompilationException;
23 import org.simantics.scl.compiler.types.Type;
24 import org.simantics.scl.compiler.types.Types;
25 import org.simantics.scl.runtime.function.Function;
26 import org.simantics.scl.runtime.tuple.Tuple0;
27
28 import junit.framework.Assert;
29
30 public class TestExpressionEvaluator {
31
32     public static final boolean TIMING = false;
33     public static final int COUNT = 10000;
34
35     ModuleRepository moduleRepository;
36     
37     RuntimeEnvironment runtimeEnvironment;
38     
39     @Before
40     public void initialize() throws Exception {
41         moduleRepository = InitialRepository.getInitialRepository();
42         
43         // Environment for compiling expressions
44         EnvironmentSpecification environmentSpecification = new EnvironmentSpecification();
45         environmentSpecification.importModule("Builtin", "");
46         environmentSpecification.importModule("Prelude", "");
47         
48         try {
49             runtimeEnvironment = moduleRepository.createRuntimeEnvironment(environmentSpecification,
50                     getClass().getClassLoader());
51         } catch(ImportFailureException e) {
52             for(ImportFailure failure : e.failures)
53                 System.err.println("Failed to import " + failure.moduleName);
54             throw e;
55         }
56     }
57
58     private void testExpression0(String expressionText,
59             Object expectedValue,
60             Type expectedType) throws Exception {
61         // Compiling and running expression
62         try {
63             Object result = new ExpressionEvaluator(runtimeEnvironment, expressionText)
64             .expectedType(expectedType)
65             .eval();
66             if(expectedValue != null)
67                 Assert.assertEquals(expectedValue, result);
68         } catch(SCLExpressionCompilationException e) {
69             System.out.println(CompilationErrorFormatter.toString(expressionText, e.getErrors()));
70             throw e;
71         }
72     }
73     
74     private void testExpression(String expressionText,
75             Object expectedValue,
76             Type expectedType) throws Exception {
77         if(TIMING) {
78             System.out.println(expressionText);
79             long beginTime = System.nanoTime();
80             for(int i=0;i<COUNT;++i)
81                 testExpression0(expressionText, expectedValue, expectedType);
82             long endTime = System.nanoTime();
83             System.out.println( "    " + (endTime-beginTime)*1e-6/COUNT + " ms");
84         }
85         else
86             testExpression0(expressionText, expectedValue, expectedType);
87     }
88
89     @Test
90     public void testExpressionCompiler() throws Exception {
91         testExpression("1",
92                 Integer.valueOf(1),
93                 Types.INTEGER);
94         testExpression("1+2",
95                 Integer.valueOf(3),
96                 Types.INTEGER);
97         testExpression("map (\\(_,x) -> x) [(1,2),(2,3)]",
98                 Arrays.asList(2.0, 3.0),
99                 Types.list(Types.DOUBLE));
100         testExpression("map (\\x -> snd x) [(1,2),(2,3)]",
101                 Arrays.asList(2.0, 3.0),
102                 Types.list(Types.DOUBLE));
103         testExpression("let f x = x+1 in (f . f . f) 3",
104                 Double.valueOf(6.0),
105                 Types.DOUBLE);
106         if(!TIMING)
107             testExpression("print \"Hello world!\"",
108                     Tuple0.INSTANCE,
109                     Types.UNIT);
110         testExpression("[1,2+3,4+5]",
111                 Arrays.asList(1,5,9),
112                 Types.list(Types.INTEGER));
113         testExpression("let a = 5.3 in let f x = x+a in f 3",
114                 Double.valueOf(8.3),
115                 Types.DOUBLE);
116         testExpression("let mm x y = if x < y then x else y in mm 2 (mm 1 3)",
117                 Double.valueOf(1.0),
118                 Types.DOUBLE);
119     }
120
121     @Test
122     public void testLocalEnvironment() throws Exception {
123         String expressionText = "a + b";
124         LocalEnvironment localEnvironment = new AbstractLocalEnvironment() {
125             Variable[] localParameters = new Variable[] {
126                     new Variable("a", Types.DOUBLE),
127                     new Variable("b", Types.DOUBLE),
128             };
129             
130             @Override
131             public Expression resolve(Environment environment, String localName) {
132                 if(localName.equals("a"))
133                     return new EVariable(localParameters[0]);
134                 else if(localName.equals("b"))
135                     return new EVariable(localParameters[1]);
136                 else
137                     return null;
138             }
139             
140             @Override
141             protected Variable[] getContextVariables() {
142                 return localParameters;
143             }
144         };
145         try {
146             Object result = new ExpressionEvaluator(runtimeEnvironment, expressionText)
147             .localEnvironment(localEnvironment)
148             .expectedType(Types.DOUBLE)
149             .eval();
150             Assert.assertEquals(
151                     Double.valueOf(15.0),
152                     ((Function)result).apply(7.0, 8.0));
153         } catch(SCLExpressionCompilationException e) {
154             System.out.println(CompilationErrorFormatter.toString(expressionText, e.getErrors()));
155             throw e;
156         }
157     }
158     
159     @Test
160     public void testArities() throws Exception {
161         for(int arity=1;arity<50;++arity) {
162             // Build expressions
163             StringBuilder b = new StringBuilder();
164             b.append('\\');
165             for(int i=0;i<arity;++i)
166                 b.append("v" + i + " ");
167             b.append("-> ");
168             for(int i=0;i<arity;++i) {
169                 if(i > 0)
170                     b.append(" + ");
171                 b.append("v" + i);
172             }
173             //System.out.println(b.toString());
174             
175             // Compile
176             Type expectedType = Types.INTEGER;
177             for(int i=0;i<arity;++i)
178                 expectedType = Types.function(Types.INTEGER, expectedType);
179             
180             Function function = (Function)new ExpressionEvaluator(runtimeEnvironment, b.toString())
181             .expectedType(expectedType)
182             .interpretIfPossible(false)
183             .eval();
184             
185             // Evaluate
186             Object[] parameters = new Object[arity];
187             int sum = 0;
188             for(int i=0;i<arity;++i) {
189                 int value = i+1;
190                 parameters[i] = value;
191                 sum += value;
192             }
193             Object result = function.applyArray(parameters);
194             Assert.assertEquals(sum, result);
195         }
196     }
197 }