1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
|
package com.seaofnodes.simple;
import com.seaofnodes.simple.codegen.CodeGen;
import com.seaofnodes.simple.node.StoreNode;
import org.junit.Test;
import static org.junit.Assert.*;
public class FinalConstructionTest {
private static final String LOOP = """
val step={int x -> x*2+1;};
struct C {
val x=1;
new C={int n ->
x=0; x=1;
for(int i=0; i<n; i++) x=step(x);
};
val get={->x;};
};
return new C(arg).get();
""";
@Test public void testFinalConstructorLocals() throws java.io.IOException {
var code=new CodeGen(LOOP).driver(CodeGen.Phase.LocalSched);
assertEquals("1",Eval2.eval(code,0));
assertEquals("15",Eval2.eval(code,3));
assertEquals("63",Eval2.eval(code,5));
code._stop.walk(n -> {
if( n instanceof StoreNode st && st._name.equals("x") )
assertEquals("Final field writes belong after the loop",0,st.cfg0().loopDepth());
return null;
});
String[] sources={
"struct C { val x=1; new C={->x=1; x=2;}; }; return new C().x;",
"struct C { int ~x; new C={int n -> self.x=1; for(int i=0;i<n;i++) self.x*=2;}; }; return new C(arg).x;",
"struct C { val x=1; new C={int n -> for(int i=0;i<n;i++) ++x;}; }; return new C(arg).x;",
"struct C { val x=1.5; new C={->x=2.5;}; }; return new C().x;",
"struct C { val x=\"a\"; new C={int n -> for(int i=0;i<n;i++) x=\"b\";}; }; return new C(arg).x[0];",
"struct C { val x=new int[1]; new C={->x=new int[2]; x=new int[3];}; }; return new C().x#;"
};
String[] results={"2","8","4","2.5","98","3"};
for( int i=0; i<sources.length; i++ )
assertEquals(results[i],Eval2.eval(new CodeGen(sources[i]).driver(CodeGen.Phase.TypeCheck),3));
String[] rejected={
"struct C { val x=1; }; val c=new C(); c.x=2; return c.x;",
"struct C { new C={->val x=1; x=2;}; }; return new C();",
"struct C { val f={->1;}; new C={->f={->2;};}; }; return new C().f();"
};
for( String src : rejected ) {
try { new CodeGen(src).driver(CodeGen.Phase.TypeCheck); fail(src); }
catch( Parser.ParseException e ) { assertTrue(e.getMessage(),e.getMessage().startsWith("Cannot")); }
}
var dir=java.nio.file.Path.of("build/objs");
java.nio.file.Files.createDirectories(dir);
java.nio.file.Files.writeString(dir.resolve("finalConstruction.smp"),"val buildFinal={int arg ->"+LOOP+"};");
java.nio.file.Files.writeString(dir.resolve("finalConstruction.c"),"""
extern long long buildFinal(long long);
int main(void) { return buildFinal(0)!=1 || buildFinal(3)!=15 || buildFinal(5)!=63; }
""");
TestC.run("build/objs","finalConstruction","",-1);
}
}
|