Browse Source

Merge branch 'development' of git.openzen.org:kindlich/ZenScript into development

Stan Hebben 6 years ago
parent
commit
74dac5c249

+ 35
- 10
JavaBytecodeCompiler/src/main/java/org/openzen/zenscript/javabytecode/JavaCompiler.java View File

6
 package org.openzen.zenscript.javabytecode;
6
 package org.openzen.zenscript.javabytecode;
7
 
7
 
8
 import java.util.ArrayList;
8
 import java.util.ArrayList;
9
+import java.util.HashMap;
9
 import java.util.List;
10
 import java.util.List;
11
+import java.util.Map;
12
+
10
 import org.objectweb.asm.ClassWriter;
13
 import org.objectweb.asm.ClassWriter;
11
 import org.objectweb.asm.Opcodes;
14
 import org.objectweb.asm.Opcodes;
12
 import org.openzen.zenscript.codemodel.HighLevelDefinition;
15
 import org.openzen.zenscript.codemodel.HighLevelDefinition;
15
 import org.openzen.zenscript.codemodel.statement.Statement;
18
 import org.openzen.zenscript.codemodel.statement.Statement;
16
 import static org.openzen.zenscript.codemodel.type.member.BuiltinTypeMembers.*;
19
 import static org.openzen.zenscript.codemodel.type.member.BuiltinTypeMembers.*;
17
 
20
 
21
+import org.openzen.zenscript.javabytecode.compiler.JavaClassWriter;
18
 import org.openzen.zenscript.javabytecode.compiler.definitions.JavaDefinitionVisitor;
22
 import org.openzen.zenscript.javabytecode.compiler.definitions.JavaDefinitionVisitor;
19
 import org.openzen.zenscript.javabytecode.compiler.JavaStatementVisitor;
23
 import org.openzen.zenscript.javabytecode.compiler.JavaStatementVisitor;
20
 import org.openzen.zenscript.javabytecode.compiler.JavaWriter;
24
 import org.openzen.zenscript.javabytecode.compiler.JavaWriter;
127
 	}
131
 	}
128
 	
132
 	
129
 	private final JavaModule target;
133
 	private final JavaModule target;
130
-	private final List<String> scriptBlockNames = new ArrayList<>();
131
-	private final ClassWriter scriptsClassWriter;
134
+	private final Map<String, JavaClassWriter> scriptBlocks = new HashMap<>();
135
+	private final JavaClassWriter scriptsClassWriter;
132
 	private int generatedScriptBlockCounter = 0;
136
 	private int generatedScriptBlockCounter = 0;
133
 	private boolean finished = false;
137
 	private boolean finished = false;
134
 	
138
 	
139
 	public JavaCompiler(boolean debug) {
143
 	public JavaCompiler(boolean debug) {
140
 		target = new JavaModule();
144
 		target = new JavaModule();
141
 		
145
 		
142
-		scriptsClassWriter = new ClassWriter(ClassWriter.COMPUTE_FRAMES);
146
+		scriptsClassWriter = new JavaClassWriter(ClassWriter.COMPUTE_FRAMES, true);
143
 		scriptsClassWriter.visit(Opcodes.V1_8, Opcodes.ACC_PUBLIC, "Scripts", null, "java/lang/Object", null);
147
 		scriptsClassWriter.visit(Opcodes.V1_8, Opcodes.ACC_PUBLIC, "Scripts", null, "java/lang/Object", null);
144
 	}
148
 	}
145
 	
149
 	
146
 	public void addDefinition(HighLevelDefinition definition) {
150
 	public void addDefinition(HighLevelDefinition definition) {
147
 		// convert definition into java class
151
 		// convert definition into java class
148
-		target.register(definition.name, definition.accept(new JavaDefinitionVisitor()));
152
+
153
+		final String methodName = definition.position.filename.substring(0, definition.position.filename.lastIndexOf('.')).replace("/", "_");
154
+
155
+
156
+		if(!scriptBlocks.containsKey(methodName)) {
157
+			JavaClassWriter scriptFileWriter = new JavaClassWriter(ClassWriter.COMPUTE_FRAMES);
158
+			scriptFileWriter.visit(Opcodes.V1_8, Opcodes.ACC_PUBLIC, methodName, null, "java/lang/Object", null);
159
+			scriptBlocks.put(methodName, scriptFileWriter);
160
+		}
161
+
162
+		target.register(definition.name, definition.accept(new JavaDefinitionVisitor(scriptBlocks.get(methodName))));
149
 
163
 
150
 	}
164
 	}
151
 	
165
 	
152
 	public void addScriptBlock(ScriptBlock script) {
166
 	public void addScriptBlock(ScriptBlock script) {
153
-		SourceFile sourceFile = script.getTag(SourceFile.class);
154
-		String methodName;
167
+		final SourceFile sourceFile = script.getTag(SourceFile.class);
168
+		final String methodName;
155
 		if (sourceFile == null) {
169
 		if (sourceFile == null) {
156
 			methodName = "generatedBlock" + (generatedScriptBlockCounter++);
170
 			methodName = "generatedBlock" + (generatedScriptBlockCounter++);
157
 		} else {
171
 		} else {
160
 			methodName = sourceFile.filename.substring(0, sourceFile.filename.lastIndexOf('.')).replace("/", "_");
174
 			methodName = sourceFile.filename.substring(0, sourceFile.filename.lastIndexOf('.')).replace("/", "_");
161
 		}
175
 		}
162
 
176
 
163
-		scriptBlockNames.add(methodName);
177
+		if(!scriptBlocks.containsKey(methodName)) {
178
+			JavaClassWriter scriptFileWriter = new JavaClassWriter(ClassWriter.COMPUTE_FRAMES, true);
179
+			scriptFileWriter.visit(Opcodes.V1_8, Opcodes.ACC_PUBLIC, methodName, null, "java/lang/Object", null);
180
+			scriptBlocks.put(methodName, scriptFileWriter);
181
+		}
164
 
182
 
165
 		// convert scripts into methods (add them to a Scripts class?)
183
 		// convert scripts into methods (add them to a Scripts class?)
166
 		// (TODO: can we break very long scripts into smaller methods? for the extreme scripts)
184
 		// (TODO: can we break very long scripts into smaller methods? for the extreme scripts)
167
-		final JavaStatementVisitor statementVisitor = new JavaStatementVisitor(new JavaWriter(scriptsClassWriter, Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC, methodName, "()V", null, null));
185
+		final JavaClassWriter visitor = scriptBlocks.get(methodName);
186
+		visitor.hasRun = true;
187
+		final JavaStatementVisitor statementVisitor = new JavaStatementVisitor(new JavaWriter(visitor, Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC, "run", "()V", null, null));
168
 		statementVisitor.start();
188
 		statementVisitor.start();
169
 		for (Statement statement : script.statements) {
189
 		for (Statement statement : script.statements) {
170
 			statement.accept(statementVisitor);
190
 			statement.accept(statementVisitor);
180
 		
200
 		
181
 		final JavaWriter runWriter = new JavaWriter(scriptsClassWriter, Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC, "run", "()V", null, null);
201
 		final JavaWriter runWriter = new JavaWriter(scriptsClassWriter, Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC, "run", "()V", null, null);
182
 		runWriter.start();
202
 		runWriter.start();
183
-		for (String scriptBlockName : scriptBlockNames) {
184
-			runWriter.invokeStatic("Scripts", scriptBlockName, "()V");
203
+		for (Map.Entry<String, JavaClassWriter> entry : scriptBlocks.entrySet()) {
204
+			final String owner = entry.getKey();
205
+			final JavaClassWriter classWriter = entry.getValue();
206
+			if(classWriter.hasRun)
207
+				runWriter.invokeStatic(owner, "run", "()V");
208
+			classWriter.visitEnd();
209
+			target.register(owner, classWriter.toByteArray());
185
 		}
210
 		}
186
 		runWriter.ret();
211
 		runWriter.ret();
187
 		runWriter.end();
212
 		runWriter.end();

+ 4
- 13
JavaBytecodeCompiler/src/main/java/org/openzen/zenscript/javabytecode/JavaModule.java View File

17
  * @author Hoofdgebruiker
17
  * @author Hoofdgebruiker
18
  */
18
  */
19
 public class JavaModule {
19
 public class JavaModule {
20
-	private Map<String, byte[]> classes = new HashMap<>();
20
+	private final Map<String, byte[]> classes = new HashMap<>();
21
 	
21
 	
22
 	public JavaModule() {
22
 	public JavaModule() {
23
 		
23
 		
24
 	}
24
 	}
25
 	
25
 	
26
 	public void register(String classname, byte[] bytecode) {
26
 	public void register(String classname, byte[] bytecode) {
27
+		if(bytecode == null) return;
27
 		classes.put(classname, bytecode);
28
 		classes.put(classname, bytecode);
28
 		try(FileOutputStream writer = new FileOutputStream(new File(classname + ".class"))) {
29
 		try(FileOutputStream writer = new FileOutputStream(new File(classname + ".class"))) {
29
 			writer.write(bytecode);
30
 			writer.write(bytecode);
37
 		
38
 		
38
 		try {
39
 		try {
39
 			classLoader.loadClass("Scripts").getMethod("run").invoke(null);
40
 			classLoader.loadClass("Scripts").getMethod("run").invoke(null);
40
-		} catch (ClassNotFoundException ex) {
41
-			Logger.getLogger(JavaModule.class.getName()).log(Level.SEVERE, null, ex);
42
-		} catch (NoSuchMethodException ex) {
43
-			Logger.getLogger(JavaModule.class.getName()).log(Level.SEVERE, null, ex);
44
-		} catch (SecurityException ex) {
45
-			Logger.getLogger(JavaModule.class.getName()).log(Level.SEVERE, null, ex);
46
-		} catch (IllegalAccessException ex) {
47
-			Logger.getLogger(JavaModule.class.getName()).log(Level.SEVERE, null, ex);
48
-		} catch (IllegalArgumentException ex) {
49
-			Logger.getLogger(JavaModule.class.getName()).log(Level.SEVERE, null, ex);
50
-		} catch (InvocationTargetException ex) {
41
+		} catch (ClassNotFoundException | InvocationTargetException | NoSuchMethodException | IllegalAccessException | SecurityException | IllegalArgumentException ex) {
51
 			Logger.getLogger(JavaModule.class.getName()).log(Level.SEVERE, null, ex);
42
 			Logger.getLogger(JavaModule.class.getName()).log(Level.SEVERE, null, ex);
52
 		}
43
 		}
53
 	}
44
 	}
54
 	
45
 	
55
 	private class ScriptClassLoader extends ClassLoader {
46
 	private class ScriptClassLoader extends ClassLoader {
56
-		final Map<String, Class> customClasses = new HashMap<>();
47
+		private final Map<String, Class> customClasses = new HashMap<>();
57
 
48
 
58
 		@Override
49
 		@Override
59
 		public Class<?> loadClass(String name) throws ClassNotFoundException {
50
 		public Class<?> loadClass(String name) throws ClassNotFoundException {

+ 9
- 0
JavaBytecodeCompiler/src/main/java/org/openzen/zenscript/javabytecode/TestIsStaticInfo.java View File

1
+package org.openzen.zenscript.javabytecode;
2
+
3
+public class TestIsStaticInfo {
4
+    public final boolean isStatic;
5
+
6
+    public TestIsStaticInfo(boolean isStatic) {
7
+        this.isStatic = isStatic;
8
+    }
9
+}

+ 48
- 1
JavaBytecodeCompiler/src/main/java/org/openzen/zenscript/javabytecode/compiler/CompilerUtils.java View File

1
 package org.openzen.zenscript.javabytecode.compiler;
1
 package org.openzen.zenscript.javabytecode.compiler;
2
 
2
 
3
+import org.objectweb.asm.Opcodes;
3
 import org.objectweb.asm.Type;
4
 import org.objectweb.asm.Type;
4
 import org.openzen.zenscript.codemodel.FunctionHeader;
5
 import org.openzen.zenscript.codemodel.FunctionHeader;
5
 import org.openzen.zenscript.codemodel.FunctionParameter;
6
 import org.openzen.zenscript.codemodel.FunctionParameter;
7
+import org.openzen.zenscript.codemodel.Modifiers;
8
+import org.openzen.zenscript.codemodel.type.BasicTypeID;
9
+import org.openzen.zenscript.codemodel.type.ITypeID;
10
+import org.openzen.zenscript.shared.CodePosition;
6
 
11
 
7
 public class CompilerUtils {
12
 public class CompilerUtils {
8
     public static String calcDesc(FunctionHeader header, boolean isEnum) {
13
     public static String calcDesc(FunctionHeader header, boolean isEnum) {
9
         StringBuilder descBuilder = new StringBuilder("(");
14
         StringBuilder descBuilder = new StringBuilder("(");
10
-        if(isEnum)
15
+        if (isEnum)
11
             descBuilder.append("Ljava/lang/String;I");
16
             descBuilder.append("Ljava/lang/String;I");
12
         for (FunctionParameter parameter : header.parameters) {
17
         for (FunctionParameter parameter : header.parameters) {
13
             descBuilder.append(Type.getDescriptor(parameter.type.accept(JavaTypeClassVisitor.INSTANCE)));
18
             descBuilder.append(Type.getDescriptor(parameter.type.accept(JavaTypeClassVisitor.INSTANCE)));
25
         signatureBuilder.append(")").append(header.returnType.accept(JavaTypeVisitor.INSTANCE).getDescriptor());
30
         signatureBuilder.append(")").append(header.returnType.accept(JavaTypeVisitor.INSTANCE).getDescriptor());
26
         return signatureBuilder.toString();
31
         return signatureBuilder.toString();
27
     }
32
     }
33
+
34
+    public static boolean isPrimitive(ITypeID id) {
35
+        if (id instanceof BasicTypeID) {
36
+            switch ((BasicTypeID) id) {
37
+                case BOOL:
38
+                case BYTE:
39
+                case SBYTE:
40
+                case SHORT:
41
+                case USHORT:
42
+                case INT:
43
+                case UINT:
44
+                case LONG:
45
+                case ULONG:
46
+                case FLOAT:
47
+                case DOUBLE:
48
+                case CHAR:
49
+                    return true;
50
+            }
51
+        }
52
+        return false;
53
+    }
54
+
55
+    public static int calcAccess(int modifiers) {
56
+        int out = 0;
57
+        if (Modifiers.isStatic(modifiers))
58
+            out |= Opcodes.ACC_STATIC;
59
+        if (Modifiers.isFinal(modifiers))
60
+            out |= Opcodes.ACC_FINAL;
61
+        if (Modifiers.isPublic(modifiers))
62
+            out |= Opcodes.ACC_PUBLIC;
63
+        if (Modifiers.isPrivate(modifiers))
64
+            out |= Opcodes.ACC_PRIVATE;
65
+        if (Modifiers.isProtected(modifiers))
66
+            out |= Opcodes.ACC_PROTECTED;
67
+        if (Modifiers.isAbstract(modifiers))
68
+            out |= Opcodes.ACC_ABSTRACT;
69
+        return out;
70
+    }
71
+
72
+    public static String calcClasName(CodePosition position) {
73
+        return position.filename.substring(0, position.filename.lastIndexOf('.')).replace("/", "_");
74
+    }
28
 }
75
 }

+ 18
- 0
JavaBytecodeCompiler/src/main/java/org/openzen/zenscript/javabytecode/compiler/JavaClassWriter.java View File

1
+package org.openzen.zenscript.javabytecode.compiler;
2
+
3
+import org.objectweb.asm.ClassWriter;
4
+
5
+public class JavaClassWriter extends ClassWriter {
6
+
7
+    public boolean hasRun;
8
+
9
+    public JavaClassWriter(int flags) {
10
+        super(flags);
11
+        this.hasRun = false;
12
+    }
13
+
14
+    public JavaClassWriter(int flags, boolean hasRun) {
15
+        super(flags);
16
+        this.hasRun = hasRun;
17
+    }
18
+}

+ 128
- 20
JavaBytecodeCompiler/src/main/java/org/openzen/zenscript/javabytecode/compiler/JavaExpressionVisitor.java View File

2
 
2
 
3
 import org.objectweb.asm.Label;
3
 import org.objectweb.asm.Label;
4
 import org.objectweb.asm.Type;
4
 import org.objectweb.asm.Type;
5
+import org.openzen.zenscript.codemodel.CompareType;
5
 import org.openzen.zenscript.codemodel.expression.*;
6
 import org.openzen.zenscript.codemodel.expression.*;
6
 import org.openzen.zenscript.codemodel.member.DefinitionMember;
7
 import org.openzen.zenscript.codemodel.member.DefinitionMember;
7
 import org.openzen.zenscript.codemodel.type.DefinitionTypeID;
8
 import org.openzen.zenscript.codemodel.type.DefinitionTypeID;
9
+import org.openzen.zenscript.codemodel.type.ITypeID;
8
 import org.openzen.zenscript.implementations.IntRange;
10
 import org.openzen.zenscript.implementations.IntRange;
9
 import org.openzen.zenscript.javabytecode.*;
11
 import org.openzen.zenscript.javabytecode.*;
10
 import org.openzen.zenscript.shared.CompileException;
12
 import org.openzen.zenscript.shared.CompileException;
11
 import org.openzen.zenscript.shared.CompileExceptionCode;
13
 import org.openzen.zenscript.shared.CompileExceptionCode;
12
 
14
 
13
-
14
 import java.util.Map;
15
 import java.util.Map;
15
 
16
 
16
 public class JavaExpressionVisitor implements ExpressionVisitor<Void> {
17
 public class JavaExpressionVisitor implements ExpressionVisitor<Void> {
27
         this.isInit = isInit;
28
         this.isInit = isInit;
28
     }
29
     }
29
 
30
 
31
+    private static Class<?> getForEquals(ITypeID id) {
32
+        if (CompilerUtils.isPrimitive(id))
33
+            return id.accept(JavaTypeClassVisitor.INSTANCE);
34
+        return Object.class;
35
+    }
36
+
30
     @Override
37
     @Override
31
     public Void visitAndAnd(AndAndExpression expression) {
38
     public Void visitAndAnd(AndAndExpression expression) {
39
+        Label end = new Label();
40
+        Label onFalse = new Label();
41
+
42
+        expression.left.accept(this);
43
+
44
+        javaWriter.ifEQ(onFalse);
45
+        expression.right.accept(this);
46
+
47
+        // //these two calls are redundant but make decompiled code look better. Keep?
48
+        // javaWriter.ifEQ(onFalse);
49
+        // javaWriter.iConst1();
50
+
51
+        javaWriter.goTo(end);
52
+
53
+        javaWriter.label(onFalse);
54
+        javaWriter.iConst0();
55
+
56
+
57
+        javaWriter.label(end);
58
+
32
         return null;
59
         return null;
33
     }
60
     }
34
 
61
 
48
 
75
 
49
     @Override
76
     @Override
50
     public Void visitCompare(BasicCompareExpression expression) {
77
     public Void visitCompare(BasicCompareExpression expression) {
78
+        expression.left.accept(this);
79
+        expression.right.accept(this);
80
+        final Type operatorType = Type.getType(CompareType.class);
81
+        javaWriter.getStaticField(operatorType.getInternalName(), expression.operator.name(), operatorType.getDescriptor());
82
+
83
+        javaWriter.invokeStatic(ZenUtils.class, "compare", boolean.class, getForEquals(expression.left.type), getForEquals(expression.right.type), CompareType.class);
84
+
51
         return null;
85
         return null;
52
     }
86
     }
53
 
87
 
65
 
99
 
66
     @Override
100
     @Override
67
     public Void visitCallStatic(CallStaticExpression expression) {
101
     public Void visitCallStatic(CallStaticExpression expression) {
102
+        for (Expression argument : expression.arguments.arguments) {
103
+            argument.accept(this);
104
+        }
105
+        //TODO: Test with actual static method
106
+        final JavaMethodInfo info = expression.member.getTag(JavaMethodInfo.class);
107
+        javaWriter.invokeStatic(info.javaClass.internalClassName, info.name, info.signature);
68
         return null;
108
         return null;
69
     }
109
     }
70
 
110
 
93
     public Void visitCapturedThis(CapturedThisExpression expression) {
133
     public Void visitCapturedThis(CapturedThisExpression expression) {
94
         return null;
134
         return null;
95
     }
135
     }
96
-	
97
-	@Override
136
+
137
+    @Override
98
     public Void visitCast(CastExpression expression) {
138
     public Void visitCast(CastExpression expression) {
99
-		expression.target.accept(this);
139
+        expression.target.accept(this);
100
         if (!checkAndExecuteByteCodeImplementation(expression.member) && !checkAndExecuteMethodInfo(expression.member))
140
         if (!checkAndExecuteByteCodeImplementation(expression.member) && !checkAndExecuteMethodInfo(expression.member))
101
             throw new IllegalStateException("Call target has no method info!");
141
             throw new IllegalStateException("Call target has no method info!");
102
-		
142
+
103
         return null;
143
         return null;
104
-	}
144
+    }
105
 
145
 
106
     @Override
146
     @Override
107
     public Void visitCheckNull(CheckNullExpression expression) {
147
     public Void visitCheckNull(CheckNullExpression expression) {
148
+        final Label end = new Label();
149
+        expression.value.accept(this);
150
+        javaWriter.dup();
151
+        javaWriter.ifNonNull(end);
152
+        javaWriter.pop();
153
+        javaWriter.newObject(NullPointerException.class);
154
+        javaWriter.dup();
155
+        javaWriter.constant("Tried to convert a null value to nonnull type " + expression.type.accept(JavaTypeClassVisitor.INSTANCE).getSimpleName());
156
+        javaWriter.invokeSpecial(NullPointerException.class, "<init>", "(Ljava/lang/String;)V");
157
+        javaWriter.aThrow();
158
+        javaWriter.label(end);
159
+
108
         return null;
160
         return null;
109
     }
161
     }
110
 
162
 
111
     @Override
163
     @Override
112
     public Void visitCoalesce(CoalesceExpression expression) {
164
     public Void visitCoalesce(CoalesceExpression expression) {
165
+        final Label end = new Label();
166
+        expression.left.accept(this);
167
+        javaWriter.dup();
168
+        javaWriter.ifNonNull(end);
169
+        javaWriter.pop();
170
+        expression.right.accept(this);
171
+        javaWriter.label(end);
113
         return null;
172
         return null;
114
     }
173
     }
115
 
174
 
116
     @Override
175
     @Override
117
     public Void visitConditional(ConditionalExpression expression) {
176
     public Void visitConditional(ConditionalExpression expression) {
177
+        final Label end = new Label();
178
+        final Label onElse = new Label();
179
+        expression.condition.accept(this);
180
+        javaWriter.ifEQ(onElse);
181
+        expression.ifThen.accept(this);
182
+        javaWriter.goTo(end);
183
+        javaWriter.label(onElse);
184
+        expression.ifElse.accept(this);
185
+        javaWriter.label(end);
118
         return null;
186
         return null;
119
     }
187
     }
120
 
188
 
121
     @Override
189
     @Override
122
     public Void visitConstantBool(ConstantBoolExpression expression) {
190
     public Void visitConstantBool(ConstantBoolExpression expression) {
123
-        getJavaWriter().constant(expression.value);
191
+        if (expression.value)
192
+            javaWriter.iConst1();
193
+        else
194
+            javaWriter.iConst0();
124
         return null;
195
         return null;
125
     }
196
     }
126
 
197
 
209
 
280
 
210
     @Override
281
     @Override
211
     public Void visitConstructorSuperCall(ConstructorSuperCallExpression expression) {
282
     public Void visitConstructorSuperCall(ConstructorSuperCallExpression expression) {
283
+        javaWriter.loadObject(0);
284
+        for (Expression argument : expression.arguments.arguments) {
285
+            argument.accept(this);
286
+        }
287
+        //No super calls in enums possible, and that's already handled in the enum constructor itself.
288
+        javaWriter.invokeSpecial(expression.objectType.accept(JavaTypeClassVisitor.INSTANCE), "<init>", CompilerUtils.calcDesc(expression.constructor.header, false));
212
         return null;
289
         return null;
213
     }
290
     }
214
 
291
 
215
     @Override
292
     @Override
216
     public Void visitEnumConstant(EnumConstantExpression expression) {
293
     public Void visitEnumConstant(EnumConstantExpression expression) {
294
+        final Type type = expression.type.accept(JavaTypeVisitor.INSTANCE);
295
+        javaWriter.getStaticField(type.getInternalName(), expression.value.name, type.getDescriptor());
217
         return null;
296
         return null;
218
     }
297
     }
219
 
298
 
224
 
303
 
225
     @Override
304
     @Override
226
     public Void visitGenericCompare(GenericCompareExpression expression) {
305
     public Void visitGenericCompare(GenericCompareExpression expression) {
306
+        //TODO: What am I supposed to do here?
227
         return null;
307
         return null;
228
     }
308
     }
229
 
309
 
237
 
317
 
238
     @Override
318
     @Override
239
     public Void visitGetFunctionParameter(GetFunctionParameterExpression expression) {
319
     public Void visitGetFunctionParameter(GetFunctionParameterExpression expression) {
240
-        javaWriter.load(Type.getType(expression.parameter.type.accept(JavaTypeClassVisitor.INSTANCE)), expression.parameter.index + 1);
320
+        //TODO is Static?
321
+        final boolean isStatic = false;
322
+        javaWriter.load(Type.getType(expression.parameter.type.accept(JavaTypeClassVisitor.INSTANCE)), isStatic ? expression.parameter.index : expression.parameter.index + 1);
241
         return null;
323
         return null;
242
     }
324
     }
243
 
325
 
262
     public Void visitGetter(GetterExpression expression) {
344
     public Void visitGetter(GetterExpression expression) {
263
         return null;
345
         return null;
264
     }
346
     }
265
-	
266
-	@Override
267
-	public Void visitGlobal(GlobalExpression expression) {
268
-		return expression.resolution.accept(this);
269
-	}
270
-	
271
-	@Override
272
-	public Void visitGlobalCall(GlobalCallExpression expression) {
273
-		return expression.resolution.accept(this);
274
-	}
347
+
348
+    @Override
349
+    public Void visitGlobal(GlobalExpression expression) {
350
+        return expression.resolution.accept(this);
351
+    }
352
+
353
+    @Override
354
+    public Void visitGlobalCall(GlobalCallExpression expression) {
355
+        return expression.resolution.accept(this);
356
+    }
275
 
357
 
276
     @Override
358
     @Override
277
     public Void visitInterfaceCast(InterfaceCastExpression expression) {
359
     public Void visitInterfaceCast(InterfaceCastExpression expression) {
289
 
371
 
290
     @Override
372
     @Override
291
     public Void visitMakeConst(MakeConstExpression expression) {
373
     public Void visitMakeConst(MakeConstExpression expression) {
292
-
374
+        //TODO: What am I supposed to do here?
293
         return null;
375
         return null;
294
     }
376
     }
295
 
377
 
311
     @Override
393
     @Override
312
     public Void visitNew(NewExpression expression) {
394
     public Void visitNew(NewExpression expression) {
313
         final String type;
395
         final String type;
314
-        if(expression.type instanceof DefinitionTypeID)
396
+        if (expression.type instanceof DefinitionTypeID)
315
             type = ((DefinitionTypeID) expression.type).definition.name;
397
             type = ((DefinitionTypeID) expression.type).definition.name;
316
         else
398
         else
317
             type = Type.getDescriptor(expression.type.accept(JavaTypeClassVisitor.INSTANCE));
399
             type = Type.getDescriptor(expression.type.accept(JavaTypeClassVisitor.INSTANCE));
337
 
419
 
338
     @Override
420
     @Override
339
     public Void visitOrOr(OrOrExpression expression) {
421
     public Void visitOrOr(OrOrExpression expression) {
422
+        Label end = new Label();
423
+        Label onTrue = new Label();
424
+
425
+        expression.left.accept(this);
426
+
427
+        javaWriter.ifNE(onTrue);
428
+        expression.right.accept(this);
429
+
430
+        // //these two calls are redundant but make decompiled code look better. Keep?
431
+        // javaWriter.ifNE(onTrue);
432
+        // javaWriter.iConst0();
433
+
434
+        javaWriter.goTo(end);
435
+
436
+        javaWriter.label(onTrue);
437
+        javaWriter.iConst1();
438
+
439
+
440
+        javaWriter.label(end);
441
+
340
         return null;
442
         return null;
341
     }
443
     }
342
 
444
 
367
 
469
 
368
     @Override
470
     @Override
369
     public Void visitSetFunctionParameter(SetFunctionParameterExpression expression) {
471
     public Void visitSetFunctionParameter(SetFunctionParameterExpression expression) {
472
+        //TODO is static?
473
+        final boolean isStatic = false;
474
+        expression.value.accept(this);
475
+        javaWriter.store(expression.type.accept(JavaTypeVisitor.INSTANCE), isStatic ? expression.parameter.index : expression.parameter.index + 1);
370
         return null;
476
         return null;
371
     }
477
     }
372
 
478
 
418
 
524
 
419
     @Override
525
     @Override
420
     public Void visitWrapOptional(WrapOptionalExpression expression) {
526
     public Void visitWrapOptional(WrapOptionalExpression expression) {
527
+        //TODO What am I supposed to do here?
528
+        expression.value.accept(this);
421
         return null;
529
         return null;
422
     }
530
     }
423
 
531
 

+ 4
- 0
JavaBytecodeCompiler/src/main/java/org/openzen/zenscript/javabytecode/compiler/JavaWriter.java View File

751
         visitor.visitMethodInsn(INVOKESPECIAL, owner, name, descriptor, false);
751
         visitor.visitMethodInsn(INVOKESPECIAL, owner, name, descriptor, false);
752
     }
752
     }
753
 
753
 
754
+    public void invokeSpecial(Class owner, String name, String descriptor) {
755
+        invokeSpecial(Type.getInternalName(owner), name, descriptor);
756
+    }
757
+
754
     public void invoke(Class owner, String name, Class result, Class... arguments) {
758
     public void invoke(Class owner, String name, Class result, Class... arguments) {
755
         if (owner.isInterface()) {
759
         if (owner.isInterface()) {
756
             invokeInterface(owner, name, result, arguments);
760
             invokeInterface(owner, name, result, arguments);

+ 77
- 0
JavaBytecodeCompiler/src/main/java/org/openzen/zenscript/javabytecode/compiler/ZenUtils.java View File

1
+package org.openzen.zenscript.javabytecode.compiler;
2
+
3
+import org.openzen.zenscript.codemodel.CompareType;
4
+
5
+import java.util.Objects;
6
+
7
+public class ZenUtils {
8
+
9
+    // ###############
10
+    // ### Compare ###
11
+    // ###############
12
+    public static boolean compare(Object a, Object b, CompareType type) {
13
+        if (type == CompareType.SAME || type == CompareType.NOTSAME) {
14
+            final boolean same = a == b;
15
+            return (type == CompareType.SAME) == same;
16
+        }
17
+
18
+        //TODO how to compare them?
19
+        if (a instanceof Comparable)
20
+            return checkCompareReturn(((Comparable) a).compareTo(b), type);
21
+        return false;
22
+    }
23
+
24
+
25
+    public static boolean compare(boolean a, boolean b, CompareType compareType) {
26
+        return checkCompareReturn(Boolean.compare(a, b), compareType);
27
+    }
28
+
29
+    public static boolean compare(int a, int b, CompareType compareType) {
30
+        return checkCompareReturn(Integer.compare(a, b), compareType);
31
+    }
32
+
33
+    public static boolean compare(char a, char b, CompareType compareType) {
34
+        return checkCompareReturn(Character.compare(a, b), compareType);
35
+    }
36
+
37
+    public static boolean compare(byte a, byte b, CompareType compareType) {
38
+        return checkCompareReturn(Byte.compare(a, b), compareType);
39
+    }
40
+
41
+    public static boolean compare(short a, short b, CompareType compareType) {
42
+        return checkCompareReturn(Short.compare(a, b), compareType);
43
+    }
44
+
45
+    public static boolean compare(long a, long b, CompareType compareType) {
46
+        return checkCompareReturn(Long.compare(a, b), compareType);
47
+    }
48
+
49
+    public static boolean compare(float a, float b, CompareType compareType) {
50
+        return checkCompareReturn(Float.compare(a, b), compareType);
51
+    }
52
+
53
+    public static boolean compare(double a, double b, CompareType compareType) {
54
+        return checkCompareReturn(Double.compare(a, b), compareType);
55
+    }
56
+
57
+    private static boolean checkCompareReturn(int compareResult, CompareType type) {
58
+        switch (type) {
59
+            case LT:
60
+                return compareResult < 0;
61
+            case GT:
62
+                return compareResult > 0;
63
+            case EQ:
64
+            case SAME:
65
+                return compareResult == 0;
66
+            case NOTSAME:
67
+            case NE:
68
+                return compareResult != 0;
69
+            case LE:
70
+                return compareResult <= 0;
71
+            case GE:
72
+                return compareResult >= 0;
73
+            default:
74
+                return false;
75
+        }
76
+    }
77
+}

+ 51
- 7
JavaBytecodeCompiler/src/main/java/org/openzen/zenscript/javabytecode/compiler/definitions/JavaDefinitionVisitor.java View File

3
 import org.objectweb.asm.ClassWriter;
3
 import org.objectweb.asm.ClassWriter;
4
 import org.objectweb.asm.Opcodes;
4
 import org.objectweb.asm.Opcodes;
5
 import org.objectweb.asm.Type;
5
 import org.objectweb.asm.Type;
6
+import org.openzen.zenscript.codemodel.FunctionParameter;
6
 import org.openzen.zenscript.codemodel.definition.*;
7
 import org.openzen.zenscript.codemodel.definition.*;
7
 import org.openzen.zenscript.codemodel.expression.Expression;
8
 import org.openzen.zenscript.codemodel.expression.Expression;
8
 import org.openzen.zenscript.codemodel.expression.ExpressionVisitor;
9
 import org.openzen.zenscript.codemodel.expression.ExpressionVisitor;
10
+import org.openzen.zenscript.codemodel.generic.TypeParameter;
9
 import org.openzen.zenscript.codemodel.member.ConstructorMember;
11
 import org.openzen.zenscript.codemodel.member.ConstructorMember;
10
 import org.openzen.zenscript.codemodel.member.EnumConstantMember;
12
 import org.openzen.zenscript.codemodel.member.EnumConstantMember;
11
 import org.openzen.zenscript.codemodel.member.FieldMember;
13
 import org.openzen.zenscript.codemodel.member.FieldMember;
12
 import org.openzen.zenscript.codemodel.member.IDefinitionMember;
14
 import org.openzen.zenscript.codemodel.member.IDefinitionMember;
13
 import org.openzen.zenscript.codemodel.statement.ExpressionStatement;
15
 import org.openzen.zenscript.codemodel.statement.ExpressionStatement;
16
+import org.openzen.zenscript.codemodel.statement.ReturnStatement;
17
+import org.openzen.zenscript.codemodel.statement.Statement;
14
 import org.openzen.zenscript.codemodel.type.BasicTypeID;
18
 import org.openzen.zenscript.codemodel.type.BasicTypeID;
19
+import org.openzen.zenscript.codemodel.type.ITypeID;
20
+import org.openzen.zenscript.javabytecode.JavaClassInfo;
15
 import org.openzen.zenscript.javabytecode.JavaEnumInfo;
21
 import org.openzen.zenscript.javabytecode.JavaEnumInfo;
16
-import org.openzen.zenscript.javabytecode.compiler.JavaExpressionVisitor;
17
-import org.openzen.zenscript.javabytecode.compiler.JavaStatementVisitor;
18
-import org.openzen.zenscript.javabytecode.compiler.JavaTypeClassVisitor;
19
-import org.openzen.zenscript.javabytecode.compiler.JavaWriter;
22
+import org.openzen.zenscript.javabytecode.JavaMethodInfo;
23
+import org.openzen.zenscript.javabytecode.TestIsStaticInfo;
24
+import org.openzen.zenscript.javabytecode.compiler.*;
25
+
26
+import java.util.Iterator;
20
 
27
 
21
 public class JavaDefinitionVisitor implements DefinitionVisitor<byte[]> {
28
 public class JavaDefinitionVisitor implements DefinitionVisitor<byte[]> {
22
 
29
 
23
 
30
 
31
+    private final JavaClassWriter outerWriter;
32
+
33
+    public JavaDefinitionVisitor(JavaClassWriter outerWriter) {
34
+
35
+        this.outerWriter = outerWriter;
36
+    }
37
+
24
     @Override
38
     @Override
25
     public byte[] visitClass(ClassDefinition definition) {
39
     public byte[] visitClass(ClassDefinition definition) {
26
-
40
+        //Classes will always be created in a new File/Class
27
 
41
 
28
         final Type superType;
42
         final Type superType;
29
         if (definition.superType == null)
43
         if (definition.superType == null)
31
         else
45
         else
32
             superType = Type.getType(definition.superType.accept(JavaTypeClassVisitor.INSTANCE));
46
             superType = Type.getType(definition.superType.accept(JavaTypeClassVisitor.INSTANCE));
33
 
47
 
34
-        ClassWriter writer = new ClassWriter(ClassWriter.COMPUTE_FRAMES);
48
+        JavaClassWriter writer = new JavaClassWriter(ClassWriter.COMPUTE_FRAMES);
35
 
49
 
36
         //TODO: Calculate signature from generic parameters
50
         //TODO: Calculate signature from generic parameters
37
         //TODO: Interfaces?
51
         //TODO: Interfaces?
144
         clinitWriter.newArray(Type.getType("L" + definition.name + ";"));
158
         clinitWriter.newArray(Type.getType("L" + definition.name + ";"));
145
 
159
 
146
         for (IDefinitionMember member : definition.members) {
160
         for (IDefinitionMember member : definition.members) {
147
-            if(!(member instanceof EnumConstantMember)) continue;
161
+            if (!(member instanceof EnumConstantMember)) continue;
148
             final EnumConstantMember constantMember = (EnumConstantMember) member;
162
             final EnumConstantMember constantMember = (EnumConstantMember) member;
149
             clinitWriter.dup();
163
             clinitWriter.dup();
150
             clinitWriter.constant(constantMember.value);
164
             clinitWriter.constant(constantMember.value);
187
 
201
 
188
     @Override
202
     @Override
189
     public byte[] visitFunction(FunctionDefinition definition) {
203
     public byte[] visitFunction(FunctionDefinition definition) {
204
+        final String signature = CompilerUtils.calcSign(definition.header, false);
205
+        final JavaWriter writer = new JavaWriter(outerWriter, true, CompilerUtils.calcAccess(definition.modifiers) | Opcodes.ACC_STATIC, definition.name, CompilerUtils.calcDesc(definition.header, false), signature, null);
206
+        final JavaStatementVisitor statementVisitor = new JavaStatementVisitor(writer);
207
+        statementVisitor.start();
208
+        final Iterator<Statement> statementIterator = definition.statements.iterator();
209
+
210
+        //TODO this is dirty, fix when there is a way of knowing if a parameter is static or not
211
+        for (FunctionParameter parameter : definition.header.parameters) {
212
+            parameter.index -= 1;
213
+        }
214
+        while (statementIterator.hasNext()) {
215
+            final Statement statement = statementIterator.next();
216
+            statement.accept(statementVisitor);
217
+            if (!statementIterator.hasNext() && !(statement instanceof ReturnStatement)) {
218
+                ITypeID type = definition.header.returnType;
219
+                if (CompilerUtils.isPrimitive(type))
220
+                    writer.iConst0();
221
+                else if (type != BasicTypeID.VOID)
222
+                    writer.aConstNull();
223
+                writer.returnType(type.accept(JavaTypeVisitor.INSTANCE));
224
+            }
225
+
226
+        }
227
+
228
+        statementVisitor.end();
229
+
230
+        final JavaMethodInfo methodInfo = new JavaMethodInfo(new JavaClassInfo(CompilerUtils.calcClasName(definition.position)), definition.name, signature, true);
231
+
232
+        definition.setTag(JavaMethodInfo.class, methodInfo);
233
+        definition.caller.setTag(JavaMethodInfo.class, methodInfo);
190
         return null;
234
         return null;
191
     }
235
     }
192
 
236
 

+ 58
- 0
ScriptingExample/scripts/conditionals.zs View File

1
+val ternaryOperation = true ? 100 : 222;
2
+
3
+println(ternaryOperation);
4
+
5
+
6
+
7
+var coalesce_one as string? = null;
8
+var coalesce_tow as string? = "test";
9
+
10
+
11
+var coalesce = coalesce_one ?? coalesce_tow;
12
+
13
+println(coalesce);
14
+
15
+
16
+//if(coalesce == "test123") {
17
+//	println("true");
18
+//}
19
+
20
+if(1 == 1) {
21
+	println("intCompareTrue");
22
+}
23
+
24
+//if(1 == "1") {
25
+//	println("well...");
26
+//}
27
+
28
+
29
+if("1" == 1) {
30
+	println("...");
31
+}
32
+
33
+
34
+//var coco as int? = 10;
35
+//var coal as int? = 1;
36
+//
37
+//println(coal ?? coco);
38
+
39
+
40
+println(".....");
41
+println(true ? "RR" : "TT");
42
+
43
+
44
+println((false && true && true) ? "true" : "false");
45
+println((true && true) ? "true" : "false");
46
+println((true && false) ? "true" : "false");
47
+println((false && false) ? "true" : "false");
48
+
49
+println("---");
50
+
51
+println((false || true) ? "true" : "false");
52
+println((true || true) ? "true" : "false");
53
+println((true || false) ? "true" : "false");
54
+println((false || false) ? "true" : "false");
55
+
56
+println(":::");
57
+
58
+println((1 <= 2) ? "true" : "false");

+ 20
- 0
ScriptingExample/scripts/functions.zs View File

1
+function test() {
2
+	println("functions.zs; test1");
3
+}
4
+
5
+
6
+
7
+function test2() as void {
8
+	println("functions.zs; test2");
9
+}
10
+
11
+
12
+test();
13
+test2();
14
+println(test3(1, 3));
15
+
16
+
17
+function test3(a as int, b as int) as int{
18
+	println(a+b);
19
+	return a + b;
20
+}

+ 2
- 2
ScriptingExample/scripts/moreHellos.zs View File

61
 
61
 
62
 println("");
62
 println("");
63
 
63
 
64
-var test2 = [1, 2, 3];
64
+var test3 = [1, 2, 3];
65
 
65
 
66
-for item in test2 {
66
+for item in test3 {
67
 	println(item);
67
 	println(item);
68
 }
68
 }
69
 
69
 

Loading…
Cancel
Save