Преглед изворни кода

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

Stan Hebben пре 6 година
родитељ
комит
74dac5c249

+ 35
- 10
JavaBytecodeCompiler/src/main/java/org/openzen/zenscript/javabytecode/JavaCompiler.java Прегледај датотеку

@@ -6,7 +6,10 @@
6 6
 package org.openzen.zenscript.javabytecode;
7 7
 
8 8
 import java.util.ArrayList;
9
+import java.util.HashMap;
9 10
 import java.util.List;
11
+import java.util.Map;
12
+
10 13
 import org.objectweb.asm.ClassWriter;
11 14
 import org.objectweb.asm.Opcodes;
12 15
 import org.openzen.zenscript.codemodel.HighLevelDefinition;
@@ -15,6 +18,7 @@ import org.openzen.zenscript.codemodel.member.DefinitionMember;
15 18
 import org.openzen.zenscript.codemodel.statement.Statement;
16 19
 import static org.openzen.zenscript.codemodel.type.member.BuiltinTypeMembers.*;
17 20
 
21
+import org.openzen.zenscript.javabytecode.compiler.JavaClassWriter;
18 22
 import org.openzen.zenscript.javabytecode.compiler.definitions.JavaDefinitionVisitor;
19 23
 import org.openzen.zenscript.javabytecode.compiler.JavaStatementVisitor;
20 24
 import org.openzen.zenscript.javabytecode.compiler.JavaWriter;
@@ -127,8 +131,8 @@ public class JavaCompiler {
127 131
 	}
128 132
 	
129 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 136
 	private int generatedScriptBlockCounter = 0;
133 137
 	private boolean finished = false;
134 138
 	
@@ -139,19 +143,29 @@ public class JavaCompiler {
139 143
 	public JavaCompiler(boolean debug) {
140 144
 		target = new JavaModule();
141 145
 		
142
-		scriptsClassWriter = new ClassWriter(ClassWriter.COMPUTE_FRAMES);
146
+		scriptsClassWriter = new JavaClassWriter(ClassWriter.COMPUTE_FRAMES, true);
143 147
 		scriptsClassWriter.visit(Opcodes.V1_8, Opcodes.ACC_PUBLIC, "Scripts", null, "java/lang/Object", null);
144 148
 	}
145 149
 	
146 150
 	public void addDefinition(HighLevelDefinition definition) {
147 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 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 169
 		if (sourceFile == null) {
156 170
 			methodName = "generatedBlock" + (generatedScriptBlockCounter++);
157 171
 		} else {
@@ -160,11 +174,17 @@ public class JavaCompiler {
160 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 183
 		// convert scripts into methods (add them to a Scripts class?)
166 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 188
 		statementVisitor.start();
169 189
 		for (Statement statement : script.statements) {
170 190
 			statement.accept(statementVisitor);
@@ -180,8 +200,13 @@ public class JavaCompiler {
180 200
 		
181 201
 		final JavaWriter runWriter = new JavaWriter(scriptsClassWriter, Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC, "run", "()V", null, null);
182 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 211
 		runWriter.ret();
187 212
 		runWriter.end();

+ 4
- 13
JavaBytecodeCompiler/src/main/java/org/openzen/zenscript/javabytecode/JavaModule.java Прегледај датотеку

@@ -17,13 +17,14 @@ import java.util.logging.Logger;
17 17
  * @author Hoofdgebruiker
18 18
  */
19 19
 public class JavaModule {
20
-	private Map<String, byte[]> classes = new HashMap<>();
20
+	private final Map<String, byte[]> classes = new HashMap<>();
21 21
 	
22 22
 	public JavaModule() {
23 23
 		
24 24
 	}
25 25
 	
26 26
 	public void register(String classname, byte[] bytecode) {
27
+		if(bytecode == null) return;
27 28
 		classes.put(classname, bytecode);
28 29
 		try(FileOutputStream writer = new FileOutputStream(new File(classname + ".class"))) {
29 30
 			writer.write(bytecode);
@@ -37,23 +38,13 @@ public class JavaModule {
37 38
 		
38 39
 		try {
39 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 42
 			Logger.getLogger(JavaModule.class.getName()).log(Level.SEVERE, null, ex);
52 43
 		}
53 44
 	}
54 45
 	
55 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 49
 		@Override
59 50
 		public Class<?> loadClass(String name) throws ClassNotFoundException {

+ 9
- 0
JavaBytecodeCompiler/src/main/java/org/openzen/zenscript/javabytecode/TestIsStaticInfo.java Прегледај датотеку

@@ -0,0 +1,9 @@
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 Прегледај датотеку

@@ -1,13 +1,18 @@
1 1
 package org.openzen.zenscript.javabytecode.compiler;
2 2
 
3
+import org.objectweb.asm.Opcodes;
3 4
 import org.objectweb.asm.Type;
4 5
 import org.openzen.zenscript.codemodel.FunctionHeader;
5 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 12
 public class CompilerUtils {
8 13
     public static String calcDesc(FunctionHeader header, boolean isEnum) {
9 14
         StringBuilder descBuilder = new StringBuilder("(");
10
-        if(isEnum)
15
+        if (isEnum)
11 16
             descBuilder.append("Ljava/lang/String;I");
12 17
         for (FunctionParameter parameter : header.parameters) {
13 18
             descBuilder.append(Type.getDescriptor(parameter.type.accept(JavaTypeClassVisitor.INSTANCE)));
@@ -25,4 +30,46 @@ public class CompilerUtils {
25 30
         signatureBuilder.append(")").append(header.returnType.accept(JavaTypeVisitor.INSTANCE).getDescriptor());
26 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 Прегледај датотеку

@@ -0,0 +1,18 @@
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 Прегледај датотеку

@@ -2,15 +2,16 @@ package org.openzen.zenscript.javabytecode.compiler;
2 2
 
3 3
 import org.objectweb.asm.Label;
4 4
 import org.objectweb.asm.Type;
5
+import org.openzen.zenscript.codemodel.CompareType;
5 6
 import org.openzen.zenscript.codemodel.expression.*;
6 7
 import org.openzen.zenscript.codemodel.member.DefinitionMember;
7 8
 import org.openzen.zenscript.codemodel.type.DefinitionTypeID;
9
+import org.openzen.zenscript.codemodel.type.ITypeID;
8 10
 import org.openzen.zenscript.implementations.IntRange;
9 11
 import org.openzen.zenscript.javabytecode.*;
10 12
 import org.openzen.zenscript.shared.CompileException;
11 13
 import org.openzen.zenscript.shared.CompileExceptionCode;
12 14
 
13
-
14 15
 import java.util.Map;
15 16
 
16 17
 public class JavaExpressionVisitor implements ExpressionVisitor<Void> {
@@ -27,8 +28,34 @@ public class JavaExpressionVisitor implements ExpressionVisitor<Void> {
27 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 37
     @Override
31 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 59
         return null;
33 60
     }
34 61
 
@@ -48,6 +75,13 @@ public class JavaExpressionVisitor implements ExpressionVisitor<Void> {
48 75
 
49 76
     @Override
50 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 85
         return null;
52 86
     }
53 87
 
@@ -65,6 +99,12 @@ public class JavaExpressionVisitor implements ExpressionVisitor<Void> {
65 99
 
66 100
     @Override
67 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 108
         return null;
69 109
     }
70 110
 
@@ -93,34 +133,65 @@ public class JavaExpressionVisitor implements ExpressionVisitor<Void> {
93 133
     public Void visitCapturedThis(CapturedThisExpression expression) {
94 134
         return null;
95 135
     }
96
-	
97
-	@Override
136
+
137
+    @Override
98 138
     public Void visitCast(CastExpression expression) {
99
-		expression.target.accept(this);
139
+        expression.target.accept(this);
100 140
         if (!checkAndExecuteByteCodeImplementation(expression.member) && !checkAndExecuteMethodInfo(expression.member))
101 141
             throw new IllegalStateException("Call target has no method info!");
102
-		
142
+
103 143
         return null;
104
-	}
144
+    }
105 145
 
106 146
     @Override
107 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 160
         return null;
109 161
     }
110 162
 
111 163
     @Override
112 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 172
         return null;
114 173
     }
115 174
 
116 175
     @Override
117 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 186
         return null;
119 187
     }
120 188
 
121 189
     @Override
122 190
     public Void visitConstantBool(ConstantBoolExpression expression) {
123
-        getJavaWriter().constant(expression.value);
191
+        if (expression.value)
192
+            javaWriter.iConst1();
193
+        else
194
+            javaWriter.iConst0();
124 195
         return null;
125 196
     }
126 197
 
@@ -209,11 +280,19 @@ public class JavaExpressionVisitor implements ExpressionVisitor<Void> {
209 280
 
210 281
     @Override
211 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 289
         return null;
213 290
     }
214 291
 
215 292
     @Override
216 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 296
         return null;
218 297
     }
219 298
 
@@ -224,6 +303,7 @@ public class JavaExpressionVisitor implements ExpressionVisitor<Void> {
224 303
 
225 304
     @Override
226 305
     public Void visitGenericCompare(GenericCompareExpression expression) {
306
+        //TODO: What am I supposed to do here?
227 307
         return null;
228 308
     }
229 309
 
@@ -237,7 +317,9 @@ public class JavaExpressionVisitor implements ExpressionVisitor<Void> {
237 317
 
238 318
     @Override
239 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 323
         return null;
242 324
     }
243 325
 
@@ -262,16 +344,16 @@ public class JavaExpressionVisitor implements ExpressionVisitor<Void> {
262 344
     public Void visitGetter(GetterExpression expression) {
263 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 358
     @Override
277 359
     public Void visitInterfaceCast(InterfaceCastExpression expression) {
@@ -289,7 +371,7 @@ public class JavaExpressionVisitor implements ExpressionVisitor<Void> {
289 371
 
290 372
     @Override
291 373
     public Void visitMakeConst(MakeConstExpression expression) {
292
-
374
+        //TODO: What am I supposed to do here?
293 375
         return null;
294 376
     }
295 377
 
@@ -311,7 +393,7 @@ public class JavaExpressionVisitor implements ExpressionVisitor<Void> {
311 393
     @Override
312 394
     public Void visitNew(NewExpression expression) {
313 395
         final String type;
314
-        if(expression.type instanceof DefinitionTypeID)
396
+        if (expression.type instanceof DefinitionTypeID)
315 397
             type = ((DefinitionTypeID) expression.type).definition.name;
316 398
         else
317 399
             type = Type.getDescriptor(expression.type.accept(JavaTypeClassVisitor.INSTANCE));
@@ -337,6 +419,26 @@ public class JavaExpressionVisitor implements ExpressionVisitor<Void> {
337 419
 
338 420
     @Override
339 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 442
         return null;
341 443
     }
342 444
 
@@ -367,6 +469,10 @@ public class JavaExpressionVisitor implements ExpressionVisitor<Void> {
367 469
 
368 470
     @Override
369 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 476
         return null;
371 477
     }
372 478
 
@@ -418,6 +524,8 @@ public class JavaExpressionVisitor implements ExpressionVisitor<Void> {
418 524
 
419 525
     @Override
420 526
     public Void visitWrapOptional(WrapOptionalExpression expression) {
527
+        //TODO What am I supposed to do here?
528
+        expression.value.accept(this);
421 529
         return null;
422 530
     }
423 531
 

+ 4
- 0
JavaBytecodeCompiler/src/main/java/org/openzen/zenscript/javabytecode/compiler/JavaWriter.java Прегледај датотеку

@@ -751,6 +751,10 @@ public class JavaWriter {
751 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 758
     public void invoke(Class owner, String name, Class result, Class... arguments) {
755 759
         if (owner.isInterface()) {
756 760
             invokeInterface(owner, name, result, arguments);

+ 77
- 0
JavaBytecodeCompiler/src/main/java/org/openzen/zenscript/javabytecode/compiler/ZenUtils.java Прегледај датотеку

@@ -0,0 +1,77 @@
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 Прегледај датотеку

@@ -3,27 +3,41 @@ package org.openzen.zenscript.javabytecode.compiler.definitions;
3 3
 import org.objectweb.asm.ClassWriter;
4 4
 import org.objectweb.asm.Opcodes;
5 5
 import org.objectweb.asm.Type;
6
+import org.openzen.zenscript.codemodel.FunctionParameter;
6 7
 import org.openzen.zenscript.codemodel.definition.*;
7 8
 import org.openzen.zenscript.codemodel.expression.Expression;
8 9
 import org.openzen.zenscript.codemodel.expression.ExpressionVisitor;
10
+import org.openzen.zenscript.codemodel.generic.TypeParameter;
9 11
 import org.openzen.zenscript.codemodel.member.ConstructorMember;
10 12
 import org.openzen.zenscript.codemodel.member.EnumConstantMember;
11 13
 import org.openzen.zenscript.codemodel.member.FieldMember;
12 14
 import org.openzen.zenscript.codemodel.member.IDefinitionMember;
13 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 18
 import org.openzen.zenscript.codemodel.type.BasicTypeID;
19
+import org.openzen.zenscript.codemodel.type.ITypeID;
20
+import org.openzen.zenscript.javabytecode.JavaClassInfo;
15 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 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 38
     @Override
25 39
     public byte[] visitClass(ClassDefinition definition) {
26
-
40
+        //Classes will always be created in a new File/Class
27 41
 
28 42
         final Type superType;
29 43
         if (definition.superType == null)
@@ -31,7 +45,7 @@ public class JavaDefinitionVisitor implements DefinitionVisitor<byte[]> {
31 45
         else
32 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 50
         //TODO: Calculate signature from generic parameters
37 51
         //TODO: Interfaces?
@@ -144,7 +158,7 @@ public class JavaDefinitionVisitor implements DefinitionVisitor<byte[]> {
144 158
         clinitWriter.newArray(Type.getType("L" + definition.name + ";"));
145 159
 
146 160
         for (IDefinitionMember member : definition.members) {
147
-            if(!(member instanceof EnumConstantMember)) continue;
161
+            if (!(member instanceof EnumConstantMember)) continue;
148 162
             final EnumConstantMember constantMember = (EnumConstantMember) member;
149 163
             clinitWriter.dup();
150 164
             clinitWriter.constant(constantMember.value);
@@ -187,6 +201,36 @@ public class JavaDefinitionVisitor implements DefinitionVisitor<byte[]> {
187 201
 
188 202
     @Override
189 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 234
         return null;
191 235
     }
192 236
 

+ 58
- 0
ScriptingExample/scripts/conditionals.zs Прегледај датотеку

@@ -0,0 +1,58 @@
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 Прегледај датотеку

@@ -0,0 +1,20 @@
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 Прегледај датотеку

@@ -61,9 +61,9 @@ for item in testArray {
61 61
 
62 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 67
 	println(item);
68 68
 }
69 69
 

Loading…
Откажи
Сачувај