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