2 Révisions

Auteur SHA1 Message Date
  kindlich af2ca1e45a
Added a test for generic expansions and a more sophisticated one that uses that Game of life code il y a 4 ans
  kindlich eb48f35453
Fixed function definitions not generating properly il y a 4 ans

+ 36
- 34
JavaBytecodeCompiler/src/main/java/org/openzen/zenscript/javabytecode/JavaCompiler.java Voir le fichier

@@ -5,32 +5,19 @@
5 5
  */
6 6
 package org.openzen.zenscript.javabytecode;
7 7
 
8
-import java.util.*;
9
-
10
-import org.objectweb.asm.ClassWriter;
11
-import org.objectweb.asm.Opcodes;
12
-import org.openzen.zencode.shared.CodePosition;
13
-import org.openzen.zencode.shared.SourceFile;
8
+import org.objectweb.asm.*;
9
+import org.openzen.zencode.shared.*;
14 10
 import org.openzen.zencode.shared.logging.*;
15
-import org.openzen.zenscript.codemodel.FunctionHeader;
16
-import org.openzen.zenscript.codemodel.FunctionParameter;
17
-import org.openzen.zenscript.codemodel.HighLevelDefinition;
18
-import org.openzen.zenscript.codemodel.ScriptBlock;
19
-import org.openzen.zenscript.codemodel.SemanticModule;
20
-import org.openzen.zenscript.codemodel.definition.ExpansionDefinition;
21
-import org.openzen.zenscript.codemodel.statement.Statement;
22
-import org.openzen.zenscript.codemodel.type.BasicTypeID;
23
-import org.openzen.zenscript.javabytecode.compiler.JavaClassWriter;
24
-import org.openzen.zenscript.javabytecode.compiler.JavaScriptFile;
25
-import org.openzen.zenscript.javabytecode.compiler.JavaStatementVisitor;
26
-import org.openzen.zenscript.javabytecode.compiler.JavaWriter;
27
-import org.openzen.zenscript.javabytecode.compiler.definitions.JavaDefinitionVisitor;
28
-import org.openzen.zenscript.javashared.JavaClass;
29
-import org.openzen.zenscript.javashared.JavaCompileSpace;
30
-import org.openzen.zenscript.javashared.JavaMethod;
31
-import org.openzen.zenscript.javashared.JavaParameterInfo;
32
-import org.openzen.zenscript.javashared.prepare.JavaPrepareDefinitionMemberVisitor;
33
-import org.openzen.zenscript.javashared.prepare.JavaPrepareDefinitionVisitor;
11
+import org.openzen.zenscript.codemodel.*;
12
+import org.openzen.zenscript.codemodel.definition.*;
13
+import org.openzen.zenscript.codemodel.statement.*;
14
+import org.openzen.zenscript.codemodel.type.*;
15
+import org.openzen.zenscript.javabytecode.compiler.*;
16
+import org.openzen.zenscript.javabytecode.compiler.definitions.*;
17
+import org.openzen.zenscript.javashared.*;
18
+import org.openzen.zenscript.javashared.prepare.*;
19
+
20
+import java.util.*;
34 21
 
35 22
 /**
36 23
  * @author Hoofdgebruiker
@@ -55,22 +42,37 @@ public class JavaCompiler {
55 42
 		
56 43
 		for (HighLevelDefinition definition : module.definitions.getAll()) {
57 44
 			final String className = getClassName(getFilename(definition));
58
-			String filename = className + "_" + (definition.name == null ? "generated" : definition.name) + "_" + expansionCounter++;
59
-			JavaPrepareDefinitionVisitor definitionPreparer = new JavaPrepareDefinitionVisitor(context, target, filename, null, filename);
60
-			definition.accept(definitionPreparer);
45
+			final String filename;
46
+            if(definition instanceof FunctionDefinition) {
47
+                filename = className;
48
+            } else {
49
+                filename = className + "_" + (definition.name == null ? "generated" : definition.name) + "_" + expansionCounter++;
50
+            }
51
+            JavaPrepareDefinitionVisitor definitionPreparer = new JavaPrepareDefinitionVisitor(context, target, filename, null, filename);
52
+            definition.accept(definitionPreparer);
61 53
 		}
62 54
 		
63 55
 		for (HighLevelDefinition definition : module.definitions.getAll()) {
64 56
 			JavaPrepareDefinitionMemberVisitor memberPreparer = new JavaPrepareDefinitionMemberVisitor(context, target);
65 57
 			definition.accept(memberPreparer);
66 58
 		}
67
-		
68
-		for (HighLevelDefinition definition : module.definitions.getAll()) {
69
-            JavaClass cls = definition instanceof ExpansionDefinition ? context.getJavaExpansionClass(definition) : context.getJavaClass(definition);
70
-            JavaScriptFile scriptFile = getScriptFile(scriptBlocks, cls.fullName);
59
+        
60
+        for(HighLevelDefinition definition : module.definitions.getAll()) {
61
+            final String internalName;
62
+            final JavaScriptFile scriptFile;
63
+            if(definition instanceof FunctionDefinition) {
64
+                internalName = getClassName(getFilename(definition));
65
+                scriptFile = getScriptFile(scriptBlocks, module.modulePackage.fullName + "/" + internalName);
66
+                scriptFilesThatAreActuallyUsedInScripts.add(scriptFile);
67
+            } else {
68
+                JavaClass cls = definition instanceof ExpansionDefinition ? context.getJavaExpansionClass(definition) : context
69
+                        .getJavaClass(definition);
70
+                scriptFile = getScriptFile(scriptBlocks, cls.fullName);
71
+                internalName = cls.internalName;
72
+            }
71 73
             scriptFile.classWriter.visitSource(definition.position.getFilename(), null);
72
-			target.addClass(cls.internalName, definition.accept(new JavaDefinitionVisitor(context, scriptFile.classWriter)));
73
-		}
74
+            target.addClass(internalName, definition.accept(new JavaDefinitionVisitor(context, scriptFile.classWriter)));
75
+        }
74 76
 		
75 77
 		FunctionHeader scriptHeader = new FunctionHeader(BasicTypeID.VOID, module.parameters);
76 78
 		String scriptDescriptor = context.getMethodDescriptor(scriptHeader);

+ 44
- 0
ScriptingExample/src/test/java/org/openzen/zenscript/scriptingexample/tests/actual_test/expansions/GenericExpansions.java Voir le fichier

@@ -0,0 +1,44 @@
1
+package org.openzen.zenscript.scriptingexample.tests.actual_test.expansions;
2
+
3
+import org.junit.jupiter.api.*;
4
+import org.openzen.zenscript.scriptingexample.tests.helpers.*;
5
+
6
+public class GenericExpansions extends ZenCodeTest {
7
+    
8
+    @Test
9
+    public void TestThatSameTypeParameterWorks() {
10
+        ScriptBuilder.create()
11
+                .add("public class MyClass<T> {")
12
+                .add("    public this() {}")
13
+                .add("}")
14
+                .add("")
15
+                .add("public expand MyClass<string> {")
16
+                .add("    public printMe() as void {println(\"Hello World\");}")
17
+                .add("}")
18
+                .add("")
19
+                .add("new MyClass<string>().printMe();")
20
+                .execute(this);
21
+        
22
+        logger.assertPrintOutputSize(1);
23
+        logger.assertPrintOutput(0, "Hello World");
24
+    }
25
+    
26
+    @Test
27
+    public void TestThatDifferentTypeParameterWorks() {
28
+        ScriptBuilder.create()
29
+                .add("public class MyClass<T> {")
30
+                .add("    public this() {}")
31
+                .add("}")
32
+                .add("")
33
+                .add("public expand MyClass<string> {")
34
+                .add("    public printMe() as void {println(\"Hello World\");}")
35
+                .add("}")
36
+                .add("")
37
+                .add("new MyClass<bool>().printMe();")
38
+                .execute(this, ScriptBuilder.LogTolerance.ALLOW_ERRORS);
39
+        
40
+        logger.assertPrintOutputSize(0);
41
+        logger.errors().assertSize(1);
42
+        logger.errors().assertLineContains(0, "No such member: printMe");
43
+    }
44
+}

+ 35
- 0
ScriptingExample/src/test/java/org/openzen/zenscript/scriptingexample/tests/actual_test/functions/Function.java Voir le fichier

@@ -0,0 +1,35 @@
1
+package org.openzen.zenscript.scriptingexample.tests.actual_test.functions;
2
+
3
+import org.junit.jupiter.api.*;
4
+import org.openzen.zenscript.scriptingexample.tests.helpers.*;
5
+
6
+public class Function extends ZenCodeTest {
7
+    
8
+    @Test
9
+    public void testCallSameFile() {
10
+        ScriptBuilder.create()
11
+                .add("public function addSomeRecipe() as void {")
12
+                .add("    println('Hello World');")
13
+                .add("}")
14
+                .add("")
15
+                .add("addSomeRecipe();")
16
+                .execute(this);
17
+        
18
+        logger.assertPrintOutputSize(1);
19
+        logger.assertPrintOutput(0, "Hello World");
20
+    }
21
+    
22
+    @Test
23
+    public void testCallDifferentFile() {
24
+        ScriptBuilder.create()
25
+                .add("public function addSomeRecipe() as void {")
26
+                .add("    println('Hello World');")
27
+                .add("}")
28
+                .startNewScript()
29
+                .add("addSomeRecipe();")
30
+                .execute(this);
31
+        
32
+        logger.assertPrintOutputSize(1);
33
+        logger.assertPrintOutput(0, "Hello World");
34
+    }
35
+}

+ 41
- 0
ScriptingExample/src/test/java/org/openzen/zenscript/scriptingexample/tests/actual_test/joined_tests/ConwaysGame.java Voir le fichier

@@ -0,0 +1,41 @@
1
+package org.openzen.zenscript.scriptingexample.tests.actual_test.joined_tests;
2
+
3
+import org.junit.jupiter.api.*;
4
+import org.openzen.zenscript.scriptingexample.tests.helpers.*;
5
+
6
+public class ConwaysGame extends ZenCodeTest {
7
+    
8
+    private static final String expandUsizeZs;
9
+    private static final String cellZs;
10
+    private static final String conwayGridZs;
11
+    private static final String gridTestZs;
12
+    private static final int[] aliveCellsAtGeneration;
13
+    
14
+    static {
15
+        aliveCellsAtGeneration = new int[] {4, 7, 6, 6, 8, 8, 12, 12, 20, 12, 12, 12};
16
+        
17
+        expandUsizeZs = "public expand usize .. usize {\n" + "    public withBounds(bounds as usize .. usize) as usize .. usize {\n" + "        return (from < bounds.from ? bounds.from : from) .. (to > bounds.to ? bounds.to : to);\n" + "    }\n" + "}";
18
+        gridTestZs = "var height = 25;\n" + "var width = 25;\n" + "\n" + "var conwayGrid = new ConwayGrid(height, width);\n" + "\n" + "conwayGrid[4,5] = true;\n" + "conwayGrid[5,4] = true;\n" + "conwayGrid[5,5] = true;\n" + "conwayGrid[5,6] = true;\n" + "\n" + "\n" + "\n" + "for i in 0 .. " + aliveCellsAtGeneration.length + " {\n" + "    println(\"Generation \" + i);\n" + "    println(\"Number of alive cells: \" + conwayGrid.totalNumberOfAliveCells);" + "    conwayGrid.update();\n" + "}";
19
+        cellZs = "public class Cell {\n" + "\n" + "    public var alive as bool;\n" + "    private var row as usize;\n" + "    private var column as usize;\n" + "\n" + "    public this(row as usize, column as usize) {\n" + "        this(row, column, false);\n" + "    }\n" + "\n" + "    public this(row as usize, column as usize, alive as bool) {\n" + "            this.row = row;\n" + "            this.column = column;\n" + "            this.alive = alive;\n" + "    }\n" + "\n" + "    public getCellNextTick(currentGrid as ConwayGrid) as Cell {\n" + "        //+2 because upperbound exclusive\n" + "        var range = currentGrid[(row - 1) .. (row + 2), (column - 1) .. (column + 2)];\n" + "        var aliveCellsIn3x3Grid = range.filter(element => element.alive).length;\n" + "\n" + "\n" + "        if(!alive) {\n" + "            return new Cell(row, column, aliveCellsIn3x3Grid == 3);\n" + "        }\n" + "\n" + "        //2. Any live cell with two or three live neighbours lives on to the next generation.\n" + "        return new Cell(row, column, aliveCellsIn3x3Grid == 3 || aliveCellsIn3x3Grid == 4);\n" + "    }\n" + "}";
20
+        conwayGridZs = "public class ConwayGrid {\n" + "    public var cells as Cell[,];\n" + "    private var width as usize;\n" + "    private var height as usize;\n" + "\n" + "    public this(width as usize, height as usize) {\n" + "        this.cells = new Cell[,](width, height, (row, column) => new Cell(row, column));\n" + "        this.width = width;\n" + "        this.height = height;\n" + "    }\n" + "\n" + "    public []=(row as int, column as int, alive as bool) as void {\n" + "        this.cells[row,column].alive = alive;\n" + "    }\n" + "\n" + "    public update() as void {\n" + "        var gridCapture = this;\n" + "        this.cells = new Cell[,](width, height, (row, column) => gridCapture.cells[row, column].getCellNextTick(gridCapture));\n" + "    }\n" + "\n" + "    //public [](row as usize, column as usize) as Cell => cells[row,column];\n" + "\n" + "    public [](rows as usize .. usize, columns as usize .. usize) as Cell[]{\n" + "        var usedRows = rows.withBounds(0 .. height);\n" + "        var usedColumns = columns.withBounds(0 .. width);\n" + "\n" + "        var rowSpan = usedRows.to - usedRows.from;\n" + "        var columnSpan = usedColumns.to - usedColumns.from;\n" + "        var cells = this.cells;\n" + "        return new Cell[](rowSpan * columnSpan, cellNo => cells[usedRows.from + (cellNo / columnSpan), usedColumns.from + (cellNo % columnSpan)]);\n" + "    }\n" + "\n" + "    public get totalNumberOfAliveCells as usize => this[0 .. height + 1, 0 .. width + 1].filter(element => element.alive).length;\n" + "}";
21
+    }
22
+    
23
+    @Test
24
+    public void doTheTest() {
25
+        ScriptBuilder.create()
26
+                .add(expandUsizeZs)
27
+                .startNewScript()
28
+                .add(cellZs)
29
+                .startNewScript()
30
+                .add(conwayGridZs)
31
+                .startNewScript()
32
+                .add(gridTestZs)
33
+                .execute(this);
34
+        
35
+        logger.assertPrintOutputSize(aliveCellsAtGeneration.length * 2);
36
+        for(int generation = 0; generation < aliveCellsAtGeneration.length; generation++) {
37
+            logger.assertPrintOutput(generation * 2, "Generation " + generation);
38
+            logger.assertPrintOutput(generation * 2 + 1, "Number of alive cells: " + aliveCellsAtGeneration[generation]);
39
+        }
40
+    }
41
+}

+ 2
- 5
ScriptingExample/src/test/java/org/openzen/zenscript/scriptingexample/tests/helpers/ScriptBuilder.java Voir le fichier

@@ -44,15 +44,12 @@ public class ScriptBuilder {
44 44
     
45 45
     public void execute(ZenCodeTest test, LogTolerance logTolerance) {
46 46
         appendScriptsToTest(test);
47
-        test.executeEngine();
47
+        test.executeEngine(logTolerance != LogTolerance.NO_ERRORS);
48 48
         switch(logTolerance) {
49 49
             case NO_WARNINGS:
50
-                test.logger.assertNoWarnings();
50
+                test.logger.assertNoWarnings(); //Fallthrough intended
51 51
             case NO_ERRORS:
52 52
                 test.logger.assertNoErrors();
53
-                break;
54
-            case ALLOW_ERRORS:
55
-                break;
56 53
         }
57 54
     }
58 55
     

+ 13
- 3
ScriptingExample/src/test/java/org/openzen/zenscript/scriptingexample/tests/helpers/ZenCodeTest.java Voir le fichier

@@ -8,7 +8,6 @@ import org.openzen.zenscript.codemodel.type.*;
8 8
 import org.openzen.zenscript.lexer.*;
9 9
 import org.openzen.zenscript.parser.*;
10 10
 import org.openzen.zenscript.scriptingexample.tests.*;
11
-import org.openzen.zenscript.scriptingexample.tests.helpers.*;
12 11
 
13 12
 import java.util.*;
14 13
 
@@ -40,12 +39,23 @@ public abstract class ZenCodeTest {
40 39
     }
41 40
     
42 41
     public void executeEngine() {
42
+        executeEngine(false);
43
+    }
44
+    
45
+    public void executeEngine(boolean allowError) {
43 46
         try {
44 47
             final FunctionParameterList parameters = getParameters();
45 48
             final SemanticModule script_tests = engine.createScriptedModule("script_tests", sourceFiles
46 49
                     .toArray(new SourceFile[0]), getBEP(), parameters.getParameters());
47
-            
48
-            Assertions.assertTrue(script_tests.isValid(), "Scripts are not valid!");
50
+            final boolean scriptsValid = script_tests.isValid();
51
+            if(allowError) {
52
+                if(!scriptsValid) {
53
+                    logger.setEngineComplete();
54
+                    return;
55
+                }
56
+            } else {
57
+                Assertions.assertTrue(scriptsValid, "Scripts are not valid!");
58
+            }
49 59
             engine.registerCompiled(script_tests);
50 60
             engine.run(parameters.getParameterMap());
51 61
         } catch(ParseException e) {

+ 26
- 10
ScriptingExample/src/test/java/org/openzen/zenscript/scriptingexample/tests/helpers/ZenCodeTestLogger.java Voir le fichier

@@ -3,16 +3,20 @@ package org.openzen.zenscript.scriptingexample.tests.helpers;
3 3
 import org.junit.jupiter.api.*;
4 4
 import org.openzen.zencode.java.logger.*;
5 5
 
6
-import java.util.*;
7
-
8 6
 public class ZenCodeTestLogger extends ScriptingEngineStreamLogger {
9 7
     
10 8
     private static final boolean logDebug = false;
11
-    private final List<String> printlnOutputs = new ArrayList<>();
12
-    private final List<String> errors = new ArrayList<>();
13
-    private final List<String> warnings = new ArrayList<>();
9
+    private final ZenCodeTestLoggerOutput printlnOutputs;
10
+    private final ZenCodeTestLoggerOutput errors;
11
+    private final ZenCodeTestLoggerOutput warnings;
14 12
     private boolean isEngineComplete = false;
15 13
     
14
+    public ZenCodeTestLogger() {
15
+        this.printlnOutputs = new ZenCodeTestLoggerOutput();
16
+        this.errors = new ZenCodeTestLoggerOutput();
17
+        this.warnings = new ZenCodeTestLoggerOutput();
18
+    }
19
+    
16 20
     @Override
17 21
     public void debug(String message) {
18 22
         if(logDebug) {
@@ -34,7 +38,7 @@ public class ZenCodeTestLogger extends ScriptingEngineStreamLogger {
34 38
     
35 39
     public void logPrintln(String line) {
36 40
         info(line);
37
-        this.printlnOutputs.addAll(Arrays.asList(String.valueOf(line).split(System.lineSeparator())));
41
+        this.printlnOutputs.add(line);
38 42
     }
39 43
     
40 44
     @Override
@@ -57,21 +61,33 @@ public class ZenCodeTestLogger extends ScriptingEngineStreamLogger {
57 61
         if(!isEngineComplete) {
58 62
             Assertions.fail("Trying to call an assertion before the engine ran, probably a fault in the test!");
59 63
         }
60
-        Assertions.assertEquals(content, printlnOutputs.get(line));
64
+        printlnOutputs.assertLine(line, content);
61 65
     }
62 66
     
63 67
     public void assertPrintOutputSize(int size) {
64 68
         if(!isEngineComplete) {
65 69
             Assertions.fail("Trying to call an assertion before the engine ran, probably a fault in the test!");
66 70
         }
67
-        Assertions.assertEquals(size, printlnOutputs.size());
71
+        printlnOutputs.assertSize(size);
68 72
     }
69 73
     
70 74
     public void assertNoErrors() {
71
-        Assertions.assertEquals(0, errors.size());
75
+        errors.assertEmpty();
72 76
     }
73 77
     
74 78
     public void assertNoWarnings() {
75
-        Assertions.assertEquals(0, warnings.size());
79
+        warnings.assertEmpty();
80
+    }
81
+    
82
+    public ZenCodeTestLoggerOutput printlnOutputs() {
83
+        return printlnOutputs;
84
+    }
85
+    
86
+    public ZenCodeTestLoggerOutput errors() {
87
+        return errors;
88
+    }
89
+    
90
+    public ZenCodeTestLoggerOutput warnings() {
91
+        return warnings;
76 92
     }
77 93
 }

+ 31
- 0
ScriptingExample/src/test/java/org/openzen/zenscript/scriptingexample/tests/helpers/ZenCodeTestLoggerOutput.java Voir le fichier

@@ -0,0 +1,31 @@
1
+package org.openzen.zenscript.scriptingexample.tests.helpers;
2
+
3
+import org.junit.jupiter.api.*;
4
+
5
+import java.util.*;
6
+
7
+public class ZenCodeTestLoggerOutput {
8
+    
9
+    private final List<String> lines = new ArrayList<>();
10
+    
11
+    void add(String line) {
12
+        lines.addAll(Arrays.asList(String.valueOf(line).split(System.lineSeparator())));
13
+    }
14
+    
15
+    public void assertEmpty() {
16
+        assertSize(0);
17
+    }
18
+    
19
+    public void assertSize(int size) {
20
+        Assertions.assertEquals(size, lines.size());
21
+    }
22
+    
23
+    public void assertLine(int line, String content) {
24
+        Assertions.assertEquals(content, lines.get(line));
25
+    }
26
+    
27
+    public void assertLineContains(int line, String content) {
28
+        final String foundLine = lines.get(line);
29
+        Assertions.assertTrue(foundLine.contains(content), "Expected this line to contain '" + content + "' but found '" + line + "'!");
30
+    }
31
+}

Loading…
Annuler
Enregistrer