Przeglądaj źródła

- Continued implementation of interfaces in the bytecode compiler.

- Added support to have a native method both as operator and named method
Stan Hebben 5 lat temu
rodzic
commit
aab7cc69f1

+ 2
- 0
JavaBytecodeCompiler/src/main/java/org/openzen/zenscript/javabytecode/compiler/JavaExpressionVisitor.java Wyświetl plik

@@ -3984,6 +3984,8 @@ public class JavaExpressionVisitor implements ExpressionVisitor<Void>, JavaNativ
3984 3984
 
3985 3985
 		if (methodInfo.kind == JavaMethod.Kind.STATIC) {
3986 3986
 			getJavaWriter().invokeStatic(methodInfo);
3987
+		} else if (methodInfo.kind == JavaMethod.Kind.INTERFACE) {
3988
+			getJavaWriter().invokeInterface(methodInfo);
3987 3989
 		} else if (methodInfo.kind == JavaMethod.Kind.COMPILED) {
3988 3990
 			Objects.requireNonNull(methodInfo.translation).translate(expression, this);
3989 3991
 		} else {

+ 19
- 7
JavaBytecodeCompiler/src/main/java/org/openzen/zenscript/javabytecode/compiler/definitions/JavaMemberVisitor.java Wyświetl plik

@@ -17,6 +17,7 @@ import org.openzen.zenscript.javabytecode.JavaBytecodeContext;
17 17
 import org.openzen.zenscript.javashared.JavaClass;
18 18
 import org.openzen.zenscript.javashared.JavaCompiledModule;
19 19
 import org.openzen.zenscript.javashared.JavaField;
20
+import org.openzen.zenscript.javashared.JavaImplementation;
20 21
 import org.openzen.zenscript.javashared.JavaMethod;
21 22
 
22 23
 public class JavaMemberVisitor implements MemberVisitor<Void> {
@@ -116,7 +117,7 @@ public class JavaMemberVisitor implements MemberVisitor<Void> {
116 117
 		final Label constructorEnd = new Label();
117 118
 		final JavaWriter destructorWriter = new JavaWriter(member.position, writer, method, definition, null, null);
118 119
 		destructorWriter.label(constructorStart);
119
-
120
+		
120 121
         final JavaStatementVisitor statementVisitor = new JavaStatementVisitor(context, javaModule, destructorWriter);
121 122
         statementVisitor.start();
122 123
 		// TODO: destruction of members (to be done when memory tags are implemented)
@@ -132,14 +133,18 @@ public class JavaMemberVisitor implements MemberVisitor<Void> {
132 133
 
133 134
         final boolean isAbstract = member.body == null || Modifiers.isAbstract(member.getEffectiveModifiers());
134 135
         final JavaMethod method = context.getJavaMethod(member);
135
-
136
-		final Label methodStart = new Label();
137
-		final Label methodEnd = new Label();
138
-	    final JavaWriter methodWriter = new JavaWriter(member.position, writer, method, definition, context.getMethodSignature(member.header), null);
139
-
140
-        final JavaStatementVisitor statementVisitor = new JavaStatementVisitor(context, javaModule, methodWriter);
136
+		
137
+		final JavaWriter methodWriter = new JavaWriter(member.position, writer, method, definition, context.getMethodSignature(member.header), null);
141 138
 
142 139
 		if (!isAbstract) {
140
+			if (method.isAbstract() || method.cls.kind == JavaClass.Kind.INTERFACE)
141
+				throw new IllegalArgumentException();
142
+			
143
+			final Label methodStart = new Label();
144
+			final Label methodEnd = new Label();
145
+		
146
+			final JavaStatementVisitor statementVisitor = new JavaStatementVisitor(context, javaModule, methodWriter);
147
+
143 148
 			statementVisitor.start();
144 149
 			member.body.accept(statementVisitor);
145 150
 			methodWriter.label(methodEnd);
@@ -180,6 +185,13 @@ public class JavaMemberVisitor implements MemberVisitor<Void> {
180 185
 
181 186
 	@Override
182 187
 	public Void visitImplementation(ImplementationMember member) {
188
+		JavaImplementation implementation = context.getJavaImplementation(member);
189
+		if (implementation.inline) {
190
+			for (IDefinitionMember imember : member.members)
191
+				imember.accept(this);
192
+		} else {
193
+			throw new UnsupportedOperationException("Non-inline interface implementations not yet available");
194
+		}
183 195
 		return null;
184 196
 	}
185 197
 

+ 24
- 4
JavaIntegration/src/main/java/org/openzen/zencode/java/JavaNativeModule.java Wyświetl plik

@@ -39,6 +39,7 @@ import org.openzen.zenscript.codemodel.member.CasterMember;
39 39
 import org.openzen.zenscript.codemodel.member.ConstructorMember;
40 40
 import org.openzen.zenscript.codemodel.member.FieldMember;
41 41
 import org.openzen.zenscript.codemodel.member.GetterMember;
42
+import org.openzen.zenscript.codemodel.member.ImplementationMember;
42 43
 import org.openzen.zenscript.codemodel.member.MethodMember;
43 44
 import org.openzen.zenscript.codemodel.member.OperatorMember;
44 45
 import org.openzen.zenscript.codemodel.member.SetterMember;
@@ -56,6 +57,7 @@ import org.openzen.zenscript.codemodel.type.storage.AutoStorageTag;
56 57
 import org.openzen.zenscript.javashared.JavaClass;
57 58
 import org.openzen.zenscript.javashared.JavaCompiledModule;
58 59
 import org.openzen.zenscript.javashared.JavaField;
60
+import org.openzen.zenscript.javashared.JavaImplementation;
59 61
 import org.openzen.zenscript.javashared.JavaMethod;
60 62
 import stdlib.Strings;
61 63
 
@@ -207,6 +209,10 @@ public class JavaNativeModule {
207 209
 		return methodMember.ref(registry.getForDefinition(definition).stored());
208 210
 	}
209 211
 	
212
+	private boolean isInBasePackage(String className) {
213
+		return className.startsWith(basePackage + ".");
214
+	}
215
+	
210 216
 	private ZSPackage getPackage(String className) {
211 217
 		if (!className.contains("."))
212 218
 			return pkg;
@@ -246,6 +252,7 @@ public class JavaNativeModule {
246 252
 				TypeID type = loadType(bound);
247 253
 				parameter.addBound(new ParameterTypeBound(CodePosition.NATIVE, type));
248 254
 			}
255
+			typeParameters[i] = parameter;
249 256
 		}
250 257
 		
251 258
 		HighLevelDefinition definition;
@@ -263,6 +270,19 @@ public class JavaNativeModule {
263 270
 		} else {
264 271
 			definition = new ClassDefinition(CodePosition.NATIVE, module, classPkg, className, Modifiers.PUBLIC);
265 272
 			javaClass = JavaClass.fromInternalName(internalName, JavaClass.Kind.CLASS);
273
+			
274
+			if (cls.getSuperclass() != null && shouldLoadClass(cls.getSuperclass())) {
275
+				definition.setSuperType(loadType(cls.getSuperclass(), false, false));
276
+			}
277
+		}
278
+		
279
+		for (Class<?> iface : cls.getInterfaces()) {
280
+			if (shouldLoadClass(iface)) {
281
+				TypeID type = loadType(iface, false, false);
282
+				ImplementationMember member = new ImplementationMember(CodePosition.NATIVE, definition, Modifiers.PUBLIC, type);
283
+				definition.members.add(member);
284
+				compiled.setImplementationInfo(member, new JavaImplementation(true, javaClass));
285
+			}
266 286
 		}
267 287
 		
268 288
 		definition.typeParameters = typeParameters;
@@ -318,7 +338,6 @@ public class JavaNativeModule {
318 338
 				GetterMember member = asGetter(definition, method, getter);
319 339
 				definition.addMember(member);
320 340
 				compiled.setMethodInfo(member, getMethod(javaClass, method, member.getType()));
321
-				continue;
322 341
 			}
323 342
 			
324 343
 			ZenCodeType.Setter setter = method.getAnnotation(ZenCodeType.Setter.class);
@@ -326,7 +345,6 @@ public class JavaNativeModule {
326 345
 				SetterMember member = asSetter(definition, method, setter);
327 346
 				definition.addMember(member);
328 347
 				compiled.setMethodInfo(member, getMethod(javaClass, method, BasicTypeID.VOID.stored));
329
-				continue;
330 348
 			}
331 349
 			
332 350
 			ZenCodeType.Operator operator = method.getAnnotation(ZenCodeType.Operator.class);
@@ -334,7 +352,6 @@ public class JavaNativeModule {
334 352
 				OperatorMember member = asOperator(definition, method, operator);
335 353
 				definition.addMember(member);
336 354
 				compiled.setMethodInfo(member, getMethod(javaClass, method, member.header.getReturnType()));
337
-				continue;
338 355
 			}
339 356
 			
340 357
 			ZenCodeType.Caster caster = method.getAnnotation(ZenCodeType.Caster.class);
@@ -342,7 +359,6 @@ public class JavaNativeModule {
342 359
 				CasterMember member = asCaster(definition, method, caster);
343 360
 				definition.addMember(member);
344 361
 				compiled.setMethodInfo(member, getMethod(javaClass, method, member.toType));
345
-				continue;
346 362
 			}
347 363
 			
348 364
 			/*if (!annotated) {
@@ -355,6 +371,10 @@ public class JavaNativeModule {
355 371
 		return definition;
356 372
 	}
357 373
 	
374
+	private boolean shouldLoadClass(Class<?> cls) {
375
+		return isInBasePackage(cls.getName());
376
+	}
377
+	
358 378
 	private boolean isGetterName(String name) {
359 379
 		return name.startsWith("get") || name.startsWith("is") || name.startsWith("has");
360 380
 	}

+ 5
- 0
JavaShared/src/main/java/org/openzen/zenscript/javashared/JavaContext.java Wyświetl plik

@@ -18,6 +18,7 @@ import org.openzen.zenscript.codemodel.definition.VariantDefinition;
18 18
 import org.openzen.zenscript.codemodel.definition.ZSPackage;
19 19
 import org.openzen.zenscript.codemodel.generic.TypeParameter;
20 20
 import org.openzen.zenscript.codemodel.member.IDefinitionMember;
21
+import org.openzen.zenscript.codemodel.member.ImplementationMember;
21 22
 import org.openzen.zenscript.codemodel.member.ref.DefinitionMemberRef;
22 23
 import org.openzen.zenscript.codemodel.member.ref.VariantOptionRef;
23 24
 import org.openzen.zenscript.codemodel.type.BasicTypeID;
@@ -184,6 +185,10 @@ public abstract class JavaContext {
184 185
 		return getJavaVariantOption(member.getOption());
185 186
 	}
186 187
 	
188
+	public JavaImplementation getJavaImplementation(ImplementationMember member) {
189
+		return getJavaModule(member.definition.module).getImplementationInfo(member);
190
+	}
191
+	
187 192
 	public void useShared() {
188 193
 		if (useShared)
189 194
 			return;

+ 9
- 0
JavaShared/src/main/java/org/openzen/zenscript/javashared/JavaMethod.java Wyświetl plik

@@ -5,6 +5,8 @@
5 5
  */
6 6
 package org.openzen.zenscript.javashared;
7 7
 
8
+import org.openzen.zenscript.codemodel.Modifiers;
9
+
8 10
 /**
9 11
  *
10 12
  * @author Hoofdgebruiker
@@ -60,6 +62,8 @@ public class JavaMethod {
60 62
 	public JavaMethod(JavaClass cls, Kind kind, String name, boolean compile, String descriptor, int modifiers, boolean genericResult, boolean[] typeParameterArguments) {
61 63
 		if (descriptor.contains("<")) // fix signature bug
62 64
 			throw new IllegalArgumentException("Invalid descriptor!");
65
+		if (cls.isInterface() && !JavaModifiers.isStatic(modifiers))
66
+			kind = Kind.INTERFACE;
63 67
 		
64 68
 		this.cls = cls;
65 69
 		this.kind = kind;
@@ -99,10 +103,15 @@ public class JavaMethod {
99 103
 		return result.toString();
100 104
 	}
101 105
 	
106
+	public boolean isAbstract() {
107
+		return (modifiers & Modifiers.ABSTRACT) > 0;
108
+	}
109
+	
102 110
 	public enum Kind {
103 111
 		STATIC,
104 112
 		STATICINIT,
105 113
 		INSTANCE,
114
+		INTERFACE,
106 115
 		EXPANSION,
107 116
 		CONSTRUCTOR,
108 117
 		COMPILED

+ 4
- 0
JavaShared/src/main/java/org/openzen/zenscript/javashared/JavaModifiers.java Wyświetl plik

@@ -53,5 +53,9 @@ public class JavaModifiers {
53 53
 		return out;
54 54
 	}
55 55
 	
56
+	public static boolean isStatic(int modifiers) {
57
+		return (modifiers & STATIC) > 0;
58
+	}
59
+	
56 60
 	private JavaModifiers() {}
57 61
 }

+ 4
- 2
JavaShared/src/main/java/org/openzen/zenscript/javashared/prepare/JavaPrepareClassMethodVisitor.java Wyświetl plik

@@ -8,6 +8,7 @@ package org.openzen.zenscript.javashared.prepare;
8 8
 import org.openzen.zenscript.javashared.JavaNativeClass;
9 9
 import org.openzen.zencode.shared.StringExpansion;
10 10
 import org.openzen.zenscript.codemodel.FunctionHeader;
11
+import org.openzen.zenscript.codemodel.Modifiers;
11 12
 import org.openzen.zenscript.codemodel.OperatorType;
12 13
 import org.openzen.zenscript.codemodel.annotations.NativeTag;
13 14
 import org.openzen.zenscript.codemodel.member.CallerMember;
@@ -296,6 +297,7 @@ public class JavaPrepareClassMethodVisitor implements MemberVisitor<Void> {
296 297
 		if (nativeTag != null && nativeClass != null)
297 298
 			method = nativeClass.getMethod(nativeTag.value);
298 299
 		
300
+		int modifiers = cls.kind == JavaClass.Kind.INTERFACE ? JavaModifiers.ABSTRACT : 0;
299 301
 		if (member.getOverrides() != null) {
300 302
 			DefinitionMemberRef base = member.getOverrides();
301 303
 			
@@ -307,7 +309,7 @@ public class JavaPrepareClassMethodVisitor implements MemberVisitor<Void> {
307 309
 					baseMethod.name,
308 310
 					true,
309 311
 					context.getMethodDescriptor(header),
310
-					JavaModifiers.getJavaModifiers(member.getEffectiveModifiers()),
312
+					modifiers | JavaModifiers.getJavaModifiers(member.getEffectiveModifiers()),
311 313
 					header.getReturnType().type instanceof GenericTypeID,
312 314
 					header.useTypeParameters());
313 315
 		} else if (method == null) {
@@ -317,7 +319,7 @@ public class JavaPrepareClassMethodVisitor implements MemberVisitor<Void> {
317 319
 					name,
318 320
 					true,
319 321
 					context.getMethodDescriptor(header),
320
-					JavaModifiers.getJavaModifiers(member.getEffectiveModifiers()),
322
+					modifiers | JavaModifiers.getJavaModifiers(member.getEffectiveModifiers()),
321 323
 					header.getReturnType().type instanceof GenericTypeID,
322 324
 					header.useTypeParameters());
323 325
 		}

+ 1
- 1
Parser/src/main/java/org/openzen/zenscript/parser/statements/ParsedEmptyFunctionBody.java Wyświetl plik

@@ -24,6 +24,6 @@ public class ParsedEmptyFunctionBody implements ParsedFunctionBody {
24 24
 	
25 25
 	@Override
26 26
 	public Statement compile(StatementScope scope, FunctionHeader header) {
27
-		return new EmptyStatement(position);
27
+		return null;
28 28
 	}
29 29
 }

+ 8
- 0
ScriptingExample/scripts/integration.zs Wyświetl plik

@@ -13,6 +13,12 @@ class TestOperators {
13 13
 	//	=> "key " + key;
14 14
 }
15 15
 
16
+class TestImplementation {
17
+	public implements TestInterface {
18
+		interfaceMethod() => "TestImplementation";
19
+	}
20
+}
21
+
16 22
 val testInstance = new TestOperators();
17 23
 //testInstance("something");
18 24
 
@@ -24,6 +30,8 @@ printMany(objects);
24 30
 
25 31
 println(<test string>);
26 32
 println(<test string>.name);
33
+println(<test string>.interfaceMethod());
34
+println(new TestImplementation().interfaceMethod());
27 35
 
28 36
 var diamond = <item:minecraft:diamond>;
29 37
 var dirt = <item:minecraft:dirt>;

+ 17
- 0
ScriptingExample/scripts/interfaces.zs Wyświetl plik

@@ -0,0 +1,17 @@
1
+public interface MyInterface {
2
+	interfaceMethod() as string;
3
+}
4
+
5
+public class MyClass {
6
+	val name as string;
7
+	
8
+	public this(name as string) {
9
+		this.name = name;
10
+	}
11
+
12
+	public implements MyInterface {
13
+		interfaceMethod() => "InterfaceMethod " + name;
14
+	}
15
+}
16
+
17
+println(new MyClass("hello").interfaceMethod());

+ 1
- 0
ScriptingExample/src/main/java/org/openzen/zenscript/scriptingexample/Main.java Wyświetl plik

@@ -25,6 +25,7 @@ public class Main {
25 25
 		JavaNativeModule example = scriptingEngine.createNativeModule("example", "org.openzen.zenscript.scriptingexample");
26 26
 		example.addGlobals(Globals.class);
27 27
 		example.addClass(TestClass.class);
28
+		example.addClass(TestInterface.class);
28 29
 		scriptingEngine.registerNativeProvided(example);
29 30
 		
30 31
 		File inputDirectory = new File("scripts");

+ 6
- 3
ScriptingExample/src/main/java/org/openzen/zenscript/scriptingexample/TestClass.java Wyświetl plik

@@ -5,13 +5,11 @@
5 5
  */
6 6
 package org.openzen.zenscript.scriptingexample;
7 7
 
8
-import org.openzen.zencode.java.ZenCodeType;
9
-
10 8
 /**
11 9
  *
12 10
  * @author Hoofdgebruiker
13 11
  */
14
-public class TestClass implements ZenCodeType {
12
+public class TestClass implements TestInterface {
15 13
 	private final String name;
16 14
 	
17 15
 	@Constructor
@@ -39,4 +37,9 @@ public class TestClass implements ZenCodeType {
39 37
 	public String toString() {
40 38
 		return name;
41 39
 	}
40
+
41
+	@Override
42
+	public String interfaceMethod() {
43
+		return "Interface method of " + name;
44
+	}
42 45
 }

Ładowanie…
Anuluj
Zapisz