Browse Source

Fixed a large number of java source compilation bugs. (ZenCode.shared module now compiles, and so does StdLib.stdlib)

Stan Hebben 6 years ago
parent
commit
8594fc56e0
51 changed files with 1264 additions and 822 deletions
  1. 20
    1
      CodeFormatterShared/src/main/java/org/openzen/zenscript/formattershared/StatementFormatter.java
  2. 2
    0
      CodeFormatterShared/src/main/java/org/openzen/zenscript/formattershared/StatementFormattingTarget.java
  3. 56
    0
      CodeModel/src/main/java/org/openzen/zenscript/codemodel/FunctionHeader.java
  4. 5
    3
      CodeModel/src/main/java/org/openzen/zenscript/codemodel/annotations/PreconditionForMethod.java
  5. 4
    0
      CodeModel/src/main/java/org/openzen/zenscript/codemodel/iterator/ForeachIteratorVisitor.java
  6. 3
    3
      CodeModel/src/main/java/org/openzen/zenscript/codemodel/member/CustomIteratorMember.java
  7. 1
    1
      CodeModel/src/main/java/org/openzen/zenscript/codemodel/member/StaticInitializerMember.java
  8. 1
    1
      CodeModel/src/main/java/org/openzen/zenscript/codemodel/member/builtin/AssocIterator.java
  9. 1
    0
      CodeModel/src/main/java/org/openzen/zenscript/codemodel/member/ref/FunctionalMemberRef.java
  10. 6
    0
      CodeModel/src/main/java/org/openzen/zenscript/codemodel/type/ArrayTypeID.java
  11. 7
    0
      CodeModel/src/main/java/org/openzen/zenscript/codemodel/type/AssocTypeID.java
  12. 5
    0
      CodeModel/src/main/java/org/openzen/zenscript/codemodel/type/BasicTypeID.java
  13. 11
    5
      CodeModel/src/main/java/org/openzen/zenscript/codemodel/type/ConstTypeID.java
  14. 7
    0
      CodeModel/src/main/java/org/openzen/zenscript/codemodel/type/DefinitionTypeID.java
  15. 8
    0
      CodeModel/src/main/java/org/openzen/zenscript/codemodel/type/FunctionTypeID.java
  16. 7
    0
      CodeModel/src/main/java/org/openzen/zenscript/codemodel/type/GenericMapTypeID.java
  17. 7
    0
      CodeModel/src/main/java/org/openzen/zenscript/codemodel/type/GenericTypeID.java
  18. 3
    0
      CodeModel/src/main/java/org/openzen/zenscript/codemodel/type/ITypeID.java
  19. 7
    0
      CodeModel/src/main/java/org/openzen/zenscript/codemodel/type/IteratorTypeID.java
  20. 6
    0
      CodeModel/src/main/java/org/openzen/zenscript/codemodel/type/OptionalTypeID.java
  21. 7
    0
      CodeModel/src/main/java/org/openzen/zenscript/codemodel/type/RangeTypeID.java
  22. 3
    0
      CodeModel/src/main/java/org/openzen/zenscript/codemodel/type/member/BuiltinID.java
  23. 5
    29
      CodeModel/src/main/java/org/openzen/zenscript/codemodel/type/member/DefinitionMemberGroup.java
  24. 3
    0
      CodeModel/src/main/java/org/openzen/zenscript/codemodel/type/member/TypeMemberBuilder.java
  25. 10
    0
      JavaBytecodeCompiler/src/main/java/org/openzen/zenscript/javabytecode/compiler/JavaForeachVisitor.java
  26. 166
    0
      JavaSourceCompiler/src/main/java/org/openzen/zenscript/javasource/BaseMemberCompiler.java
  27. 92
    22
      JavaSourceCompiler/src/main/java/org/openzen/zenscript/javasource/JavaDefinitionVisitor.java
  28. 50
    247
      JavaSourceCompiler/src/main/java/org/openzen/zenscript/javasource/JavaExpansionMemberCompiler.java
  29. 59
    171
      JavaSourceCompiler/src/main/java/org/openzen/zenscript/javasource/JavaMemberCompiler.java
  30. 24
    12
      JavaSourceCompiler/src/main/java/org/openzen/zenscript/javasource/JavaSourceCompiler.java
  31. 108
    50
      JavaSourceCompiler/src/main/java/org/openzen/zenscript/javasource/JavaSourceExpressionFormatter.java
  32. 38
    30
      JavaSourceCompiler/src/main/java/org/openzen/zenscript/javasource/JavaSourceFile.java
  33. 21
    39
      JavaSourceCompiler/src/main/java/org/openzen/zenscript/javasource/JavaSourceImporter.java
  34. 44
    36
      JavaSourceCompiler/src/main/java/org/openzen/zenscript/javasource/JavaSourceStatementFormatter.java
  35. 3
    3
      JavaSourceCompiler/src/main/java/org/openzen/zenscript/javasource/JavaSourceSyntheticHelperGenerator.java
  36. 20
    9
      JavaSourceCompiler/src/main/java/org/openzen/zenscript/javasource/JavaSourceSyntheticTypeGenerator.java
  37. 33
    7
      JavaSourceCompiler/src/main/java/org/openzen/zenscript/javasource/JavaSourceTypeVisitor.java
  38. 50
    8
      JavaSourceCompiler/src/main/java/org/openzen/zenscript/javasource/JavaSourceUtils.java
  39. 23
    0
      JavaSourceCompiler/src/main/java/org/openzen/zenscript/javasource/JavaSynthesizedClass.java
  40. 40
    0
      JavaSourceCompiler/src/main/java/org/openzen/zenscript/javasource/prepare/JavaNativeClass.java
  41. 28
    73
      JavaSourceCompiler/src/main/java/org/openzen/zenscript/javasource/prepare/JavaSourcePrepareClassMethodVisitor.java
  42. 191
    50
      JavaSourceCompiler/src/main/java/org/openzen/zenscript/javasource/prepare/JavaSourcePrepareDefinitionVisitor.java
  43. 24
    6
      JavaSourceCompiler/src/main/java/org/openzen/zenscript/javasource/prepare/JavaSourcePrepareExpansionMethodVisitor.java
  44. 8
    3
      JavaSourceCompiler/src/main/java/org/openzen/zenscript/javasource/scope/JavaSourceFileScope.java
  45. 4
    4
      JavaSourceCompiler/src/main/java/org/openzen/zenscript/javasource/scope/JavaSourceStatementScope.java
  46. 11
    3
      JavaSourceCompiler/src/main/java/org/openzen/zenscript/javasource/tags/JavaSourceClass.java
  47. 5
    1
      JavaSourceCompiler/src/main/java/org/openzen/zenscript/javasource/tags/JavaSourceMethod.java
  48. 2
    2
      Shared/src/main/java/org/openzen/zenscript/shared/ConcatMap.java
  49. 4
    1
      Validator/src/main/java/org/openzen/zenscript/validator/ValidationLogEntry.java
  50. 20
    1
      Validator/src/main/java/org/openzen/zenscript/validator/visitors/DefinitionMemberValidator.java
  51. 1
    1
      Validator/src/main/java/org/openzen/zenscript/validator/visitors/ExpressionValidator.java

+ 20
- 1
CodeFormatterShared/src/main/java/org/openzen/zenscript/formattershared/StatementFormatter.java View File

@@ -205,13 +205,30 @@ public class StatementFormatter implements StatementVisitor<Void>, StatementForm
205 205
 		if (!lineAfter.isEmpty())
206 206
 			output.append('\n').append(indent).append(lineAfter);
207 207
 	}
208
+	
209
+	@Override
210
+	public void writeInner(String lineBefore, String[] inlineContents, Statement contents, LoopStatement loop, String lineAfter) {
211
+		output.append('\n').append(indent).append(lineBefore);
212
+		StatementFormatter innerFormatter = new StatementFormatter(output, settings, formatter.forLoop(loop), indent + settings.indent, loop == null ? innerLoop : loop);
213
+		for (String inline : inlineContents)
214
+			output.append('\n').append(indent).append(settings.indent).append(inline);
215
+		if (contents instanceof BlockStatement) {
216
+			for (Statement statement : ((BlockStatement) contents).statements)
217
+				statement.accept(innerFormatter);
218
+		} else {
219
+			contents.accept(innerFormatter);
220
+		}
221
+		
222
+		if (!lineAfter.isEmpty())
223
+			output.append('\n').append(indent).append(lineAfter);
224
+	}
208 225
 
209 226
 	@Override
210 227
 	public void writeInnerMulti(String lineBefore, List<StatementFormattingSubBlock> contents, LoopStatement loop, String lineAfter) {
211 228
 		output.append('\n').append(indent).append(lineBefore);
212 229
 		
213 230
 		String newIndent = indent + settings.indent + settings.indent;
214
-		StatementFormatter inner = new StatementFormatter(output, settings, formatter, newIndent, innerLoop);
231
+		StatementFormatter inner = new StatementFormatter(output, settings, formatter.forLoop(loop), newIndent, innerLoop);
215 232
 		
216 233
 		for (StatementFormattingSubBlock subBlock : contents) {
217 234
 			output.append('\n').append(indent).append(settings.indent).append(subBlock.header);
@@ -278,6 +295,8 @@ public class StatementFormatter implements StatementVisitor<Void>, StatementForm
278 295
 	}
279 296
 	
280 297
 	public interface Formatter {
298
+		public Formatter forLoop(LoopStatement statement);
299
+		
281 300
 		public void formatBlock(StatementFormattingTarget target, BlockStatement statement);
282 301
 	
283 302
 		public void formatBreak(StatementFormattingTarget target, BreakStatement statement);

+ 2
- 0
CodeFormatterShared/src/main/java/org/openzen/zenscript/formattershared/StatementFormattingTarget.java View File

@@ -23,6 +23,8 @@ public interface StatementFormattingTarget {
23 23
 	
24 24
 	void writeInner(String lineBefore, Statement contents, LoopStatement loop, String lineAfter);
25 25
 	
26
+	void writeInner(String lineBefore, String[] inlineContents, Statement contents, LoopStatement loop, String lineAfter);
27
+	
26 28
 	void writeInnerMulti(String lineBefore, List<StatementFormattingSubBlock> contents, LoopStatement loop, String lineAfter);
27 29
 	
28 30
 	void writeBlock(String lineBefore, BlockStatement contents, String lineAfter);

+ 56
- 0
CodeModel/src/main/java/org/openzen/zenscript/codemodel/FunctionHeader.java View File

@@ -29,6 +29,9 @@ public class FunctionHeader {
29 29
 	public final FunctionParameter[] parameters;
30 30
 	public final ITypeID thrownType;
31 31
 	
32
+	public final int minParameters;
33
+	public final int maxParameters;
34
+	
32 35
 	public FunctionHeader(ITypeID returnType) {
33 36
 		if (returnType == null)
34 37
 			throw new NullPointerException();
@@ -37,6 +40,9 @@ public class FunctionHeader {
37 40
 		this.returnType = returnType;
38 41
 		this.parameters = NO_PARAMETERS;
39 42
 		this.thrownType = null;
43
+		
44
+		minParameters = 0;
45
+		maxParameters = 0;
40 46
 	}
41 47
 	
42 48
 	public FunctionHeader(ITypeID returnType, ITypeID... parameterTypes) {
@@ -50,6 +56,9 @@ public class FunctionHeader {
50 56
 		
51 57
 		for (int i = 0; i < parameterTypes.length; i++)
52 58
 			parameters[i] = new FunctionParameter(parameterTypes[i], null);
59
+		
60
+		minParameters = parameterTypes.length;
61
+		maxParameters = parameterTypes.length;
53 62
 	}
54 63
 	
55 64
 	public FunctionHeader(ITypeID returnType, FunctionParameter... parameters) {
@@ -60,6 +69,9 @@ public class FunctionHeader {
60 69
 		this.returnType = returnType;
61 70
 		this.parameters = parameters;
62 71
 		this.thrownType = null;
72
+		
73
+		minParameters = getMinParameters(parameters);
74
+		maxParameters = getMaxParameters(parameters);
63 75
 	}
64 76
 	
65 77
 	public FunctionHeader(TypeParameter[] genericParameters, ITypeID returnType, ITypeID thrownType, FunctionParameter... parameters) {
@@ -70,12 +82,41 @@ public class FunctionHeader {
70 82
 		this.returnType = returnType;
71 83
 		this.parameters = parameters;
72 84
 		this.thrownType = thrownType;
85
+		
86
+		minParameters = getMinParameters(parameters);
87
+		maxParameters = getMaxParameters(parameters);
73 88
 	}
74 89
 	
75 90
 	public int getNumberOfTypeParameters() {
76 91
 		return typeParameters == null ? 0 : typeParameters.length;
77 92
 	}
78 93
 	
94
+	public boolean matchesExactly(CallArguments arguments, TypeScope scope) {
95
+		if (arguments.arguments.length < minParameters || arguments.arguments.length > maxParameters)
96
+			return false;
97
+		
98
+		FunctionHeader header = fillGenericArguments(scope.getTypeRegistry(), arguments.typeArguments);
99
+		for (int i = 0; i < header.parameters.length; i++) {
100
+			if (arguments.arguments[i].type != header.parameters[i].type)
101
+				return false;
102
+		}
103
+		
104
+		return true;
105
+	}
106
+	
107
+	public boolean matchesImplicitly(CallArguments arguments, TypeScope scope) {
108
+		if (arguments.arguments.length < minParameters || arguments.arguments.length > maxParameters)
109
+			return false;
110
+		
111
+		FunctionHeader header = fillGenericArguments(scope.getTypeRegistry(), arguments.typeArguments);
112
+		for (int i = 0; i < header.parameters.length; i++) {
113
+			if (!scope.getTypeMembers(arguments.arguments[i].type).canCastImplicit(header.parameters[i].type))
114
+				return false;
115
+		}
116
+		
117
+		return true;
118
+	}
119
+	
79 120
 	public String getCanonical() {
80 121
 		StringBuilder result = new StringBuilder();
81 122
 		if (getNumberOfTypeParameters() > 0) {
@@ -304,4 +345,19 @@ public class FunctionHeader {
304 345
 		result.append(")");
305 346
 		return result.toString();
306 347
 	}
348
+
349
+	private static int getMinParameters(FunctionParameter[] parameters) {
350
+		for (int i = 0; i < parameters.length; i++)
351
+			if (parameters[i].defaultValue != null || parameters[i].variadic)
352
+				return i;
353
+		
354
+		return parameters.length;
355
+	}
356
+	
357
+	private static int getMaxParameters(FunctionParameter[] parameters) {
358
+		if (parameters.length == 0)
359
+			return 0;
360
+		
361
+		return parameters[parameters.length - 1].variadic ? Integer.MAX_VALUE : parameters.length;
362
+	}
307 363
 }

+ 5
- 3
CodeModel/src/main/java/org/openzen/zenscript/codemodel/annotations/PreconditionForMethod.java View File

@@ -7,16 +7,18 @@ package org.openzen.zenscript.codemodel.annotations;
7 7
 
8 8
 import java.util.ArrayList;
9 9
 import java.util.List;
10
+import org.openzen.zenscript.codemodel.expression.ConstantStringExpression;
10 11
 import org.openzen.zenscript.codemodel.expression.Expression;
11 12
 import org.openzen.zenscript.codemodel.expression.ExpressionBuilder;
13
+import org.openzen.zenscript.codemodel.expression.PanicExpression;
12 14
 import org.openzen.zenscript.codemodel.member.FunctionalMember;
13 15
 import org.openzen.zenscript.codemodel.member.IDefinitionMember;
14 16
 import org.openzen.zenscript.codemodel.scope.BaseScope;
15 17
 import org.openzen.zenscript.codemodel.scope.ExpressionScope;
16 18
 import org.openzen.zenscript.codemodel.statement.BlockStatement;
19
+import org.openzen.zenscript.codemodel.statement.ExpressionStatement;
17 20
 import org.openzen.zenscript.codemodel.statement.IfStatement;
18 21
 import org.openzen.zenscript.codemodel.statement.Statement;
19
-import org.openzen.zenscript.codemodel.statement.ThrowStatement;
20 22
 import org.openzen.zenscript.codemodel.type.BasicTypeID;
21 23
 import org.openzen.zenscript.shared.CodePosition;
22 24
 
@@ -55,8 +57,8 @@ public class PreconditionForMethod implements MemberAnnotation {
55 57
 		List<Statement> statements = new ArrayList<>();
56 58
 		ExpressionBuilder expressionBuilder = new ExpressionBuilder(position, expressionScope);
57 59
 		Expression inverseCondition = expressionBuilder.not(condition);
58
-		Statement throwStatement = new ThrowStatement(CodePosition.BUILTIN, expressionBuilder.constructNew("stdlib.IllegalArgumentException", message));
59
-		statements.add(new IfStatement(CodePosition.BUILTIN, inverseCondition, throwStatement, null));
60
+		Statement throwStatement = new ExpressionStatement(position, new PanicExpression(position, BasicTypeID.VOID, message));
61
+		statements.add(new IfStatement(position, inverseCondition, throwStatement, null));
60 62
 		if (member.body instanceof BlockStatement) {
61 63
 			statements.addAll(((BlockStatement)member.body).statements);
62 64
 		} else {

+ 4
- 0
CodeModel/src/main/java/org/openzen/zenscript/codemodel/iterator/ForeachIteratorVisitor.java View File

@@ -16,6 +16,10 @@ public interface ForeachIteratorVisitor<T> {
16 16
 	
17 17
 	T visitArrayKeyValueIterator();
18 18
 	
19
+	T visitAssocKeyIterator();
20
+	
21
+	T visitAssocKeyValueIterator();
22
+	
19 23
 	T visitStringCharacterIterator();
20 24
 	
21 25
 	T visitCustomIterator();

+ 3
- 3
CodeModel/src/main/java/org/openzen/zenscript/codemodel/member/CustomIteratorMember.java View File

@@ -22,7 +22,7 @@ import org.openzen.zenscript.shared.CodePosition;
22 22
  */
23 23
 public class CustomIteratorMember extends DefinitionMember implements IIteratorMember {
24 24
 	private final ITypeID[] iteratorTypes;
25
-	private Statement content;
25
+	public Statement body;
26 26
 	
27 27
 	public CustomIteratorMember(CodePosition position, HighLevelDefinition definition, int modifiers, ITypeID[] iteratorTypes) {
28 28
 		super(position, definition, modifiers);
@@ -30,8 +30,8 @@ public class CustomIteratorMember extends DefinitionMember implements IIteratorM
30 30
 		this.iteratorTypes = iteratorTypes;
31 31
 	}
32 32
 	
33
-	public void setContent(Statement content) {
34
-		this.content = content;
33
+	public void setContent(Statement body) {
34
+		this.body = body;
35 35
 	}
36 36
 
37 37
 	@Override

+ 1
- 1
CodeModel/src/main/java/org/openzen/zenscript/codemodel/member/StaticInitializerMember.java View File

@@ -19,7 +19,7 @@ import org.openzen.zenscript.shared.Taggable;
19 19
  * @author Hoofdgebruiker
20 20
  */
21 21
 public class StaticInitializerMember extends Taggable implements IDefinitionMember {
22
-	private final CodePosition position;
22
+	public final CodePosition position;
23 23
 	public Statement body;
24 24
 	public MemberAnnotation[] annotations = MemberAnnotation.NONE;
25 25
 	

+ 1
- 1
CodeModel/src/main/java/org/openzen/zenscript/codemodel/member/builtin/AssocIterator.java View File

@@ -71,6 +71,6 @@ public class AssocIterator extends Taggable implements IIteratorMember {
71 71
 
72 72
 	@Override
73 73
 	public <T> T acceptForIterator(ForeachIteratorVisitor<T> visitor) {
74
-		return visitor.visitArrayKeyValueIterator();
74
+		return visitor.visitAssocKeyValueIterator();
75 75
 	}
76 76
 }

+ 1
- 0
CodeModel/src/main/java/org/openzen/zenscript/codemodel/member/ref/FunctionalMemberRef.java View File

@@ -69,6 +69,7 @@ public class FunctionalMemberRef implements DefinitionMemberRef {
69 69
 		return target.getKind() == FunctionalKind.OPERATOR;
70 70
 	}
71 71
 	
72
+	// TODO: shouldn't this be a call operator?
72 73
 	public boolean isCaller() {
73 74
 		return target.getKind() == FunctionalKind.CALLER;
74 75
 	}

+ 6
- 0
CodeModel/src/main/java/org/openzen/zenscript/codemodel/type/ArrayTypeID.java View File

@@ -5,6 +5,7 @@
5 5
  */
6 6
 package org.openzen.zenscript.codemodel.type;
7 7
 
8
+import java.util.List;
8 9
 import org.openzen.zenscript.codemodel.GenericMapper;
9 10
 import org.openzen.zenscript.codemodel.generic.TypeParameter;
10 11
 
@@ -64,6 +65,11 @@ public class ArrayTypeID implements ITypeID {
64 65
 		return false;
65 66
 	}
66 67
 
68
+	@Override
69
+	public void extractTypeParameters(List<TypeParameter> typeParameters) {
70
+		elementType.extractTypeParameters(typeParameters);
71
+	}
72
+
67 73
 	@Override
68 74
 	public int hashCode() {
69 75
 		int hash = 7;

+ 7
- 0
CodeModel/src/main/java/org/openzen/zenscript/codemodel/type/AssocTypeID.java View File

@@ -5,6 +5,7 @@
5 5
  */
6 6
 package org.openzen.zenscript.codemodel.type;
7 7
 
8
+import java.util.List;
8 9
 import org.openzen.zenscript.codemodel.GenericMapper;
9 10
 import org.openzen.zenscript.codemodel.generic.TypeParameter;
10 11
 
@@ -63,6 +64,12 @@ public class AssocTypeID implements ITypeID {
63 64
 		return true;
64 65
 	}
65 66
 
67
+	@Override
68
+	public void extractTypeParameters(List<TypeParameter> typeParameters) {
69
+		keyType.extractTypeParameters(typeParameters);
70
+		valueType.extractTypeParameters(typeParameters);
71
+	}
72
+
66 73
 	@Override
67 74
 	public int hashCode() {
68 75
 		int hash = 7;

+ 5
- 0
CodeModel/src/main/java/org/openzen/zenscript/codemodel/type/BasicTypeID.java View File

@@ -86,4 +86,9 @@ public enum BasicTypeID implements ITypeID {
86 86
 	public boolean hasDefaultValue() {
87 87
 		return true;
88 88
 	}
89
+
90
+	@Override
91
+	public void extractTypeParameters(List<TypeParameter> typeParameters) {
92
+		
93
+	}
89 94
 }

+ 11
- 5
CodeModel/src/main/java/org/openzen/zenscript/codemodel/type/ConstTypeID.java View File

@@ -5,6 +5,7 @@
5 5
  */
6 6
 package org.openzen.zenscript.codemodel.type;
7 7
 
8
+import java.util.List;
8 9
 import java.util.Objects;
9 10
 import org.openzen.zenscript.codemodel.GenericMapper;
10 11
 import org.openzen.zenscript.codemodel.HighLevelDefinition;
@@ -67,6 +68,16 @@ public class ConstTypeID implements ITypeID {
67 68
 		return baseType.isObjectType();
68 69
 	}
69 70
 
71
+	@Override
72
+	public boolean hasDefaultValue() {
73
+		return baseType.hasDefaultValue();
74
+	}
75
+
76
+	@Override
77
+	public void extractTypeParameters(List<TypeParameter> typeParameters) {
78
+		baseType.extractTypeParameters(typeParameters);
79
+	}
80
+
70 81
 	@Override
71 82
 	public int hashCode() {
72 83
 		int hash = 3;
@@ -93,9 +104,4 @@ public class ConstTypeID implements ITypeID {
93 104
 	public String toString() {
94 105
 		return "const " + baseType.toString();
95 106
 	}
96
-
97
-	@Override
98
-	public boolean hasDefaultValue() {
99
-		return baseType.hasDefaultValue();
100
-	}
101 107
 }

+ 7
- 0
CodeModel/src/main/java/org/openzen/zenscript/codemodel/type/DefinitionTypeID.java View File

@@ -8,6 +8,7 @@ package org.openzen.zenscript.codemodel.type;
8 8
 import java.util.Arrays;
9 9
 import java.util.Collections;
10 10
 import java.util.HashMap;
11
+import java.util.List;
11 12
 import java.util.Map;
12 13
 import java.util.Objects;
13 14
 import org.openzen.zenscript.codemodel.GenericMapper;
@@ -216,6 +217,12 @@ public class DefinitionTypeID implements ITypeID {
216 217
 	public boolean hasDefaultValue() {
217 218
 		return definition.hasEmptyConstructor();
218 219
 	}
220
+
221
+	@Override
222
+	public void extractTypeParameters(List<TypeParameter> typeParameters) {
223
+		for (ITypeID type : this.typeParameters)
224
+			type.extractTypeParameters(typeParameters);
225
+	}
219 226
 	
220 227
 	private class OuterTypeEntry {
221 228
 		private final TypeParameter parameter;

+ 8
- 0
CodeModel/src/main/java/org/openzen/zenscript/codemodel/type/FunctionTypeID.java View File

@@ -6,6 +6,7 @@
6 6
 package org.openzen.zenscript.codemodel.type;
7 7
 
8 8
 import java.util.Arrays;
9
+import java.util.List;
9 10
 import org.openzen.zenscript.codemodel.FunctionHeader;
10 11
 import org.openzen.zenscript.codemodel.FunctionParameter;
11 12
 import org.openzen.zenscript.codemodel.GenericMapper;
@@ -62,6 +63,13 @@ public class FunctionTypeID implements ITypeID {
62 63
 		return false;
63 64
 	}
64 65
 
66
+	@Override
67
+	public void extractTypeParameters(List<TypeParameter> typeParameters) {
68
+		header.returnType.extractTypeParameters(typeParameters);
69
+		for (FunctionParameter parameter : header.parameters)
70
+			parameter.type.extractTypeParameters(typeParameters);
71
+	}
72
+
65 73
 	@Override
66 74
 	public int hashCode() {
67 75
 		int hash = 5;

+ 7
- 0
CodeModel/src/main/java/org/openzen/zenscript/codemodel/type/GenericMapTypeID.java View File

@@ -5,6 +5,7 @@
5 5
  */
6 6
 package org.openzen.zenscript.codemodel.type;
7 7
 
8
+import java.util.List;
8 9
 import java.util.Objects;
9 10
 import org.openzen.zenscript.codemodel.GenericMapper;
10 11
 import org.openzen.zenscript.codemodel.generic.TypeParameter;
@@ -61,6 +62,12 @@ public class GenericMapTypeID implements ITypeID {
61 62
 	public boolean isObjectType() {
62 63
 		return true;
63 64
 	}
65
+
66
+	@Override
67
+	public void extractTypeParameters(List<TypeParameter> typeParameters) {
68
+		value.extractTypeParameters(typeParameters);
69
+		typeParameters.remove(key);
70
+	}
64 71
 	
65 72
 	@Override
66 73
 	public String toString() {

+ 7
- 0
CodeModel/src/main/java/org/openzen/zenscript/codemodel/type/GenericTypeID.java View File

@@ -5,6 +5,7 @@
5 5
  */
6 6
 package org.openzen.zenscript.codemodel.type;
7 7
 
8
+import java.util.List;
8 9
 import org.openzen.zenscript.codemodel.GenericMapper;
9 10
 import org.openzen.zenscript.codemodel.generic.TypeParameter;
10 11
 import org.openzen.zenscript.codemodel.type.member.LocalMemberCache;
@@ -68,6 +69,12 @@ public class GenericTypeID implements ITypeID {
68 69
 		return false;
69 70
 	}
70 71
 
72
+	@Override
73
+	public void extractTypeParameters(List<TypeParameter> typeParameters) {
74
+		if (!typeParameters.contains(parameter))
75
+			typeParameters.add(parameter);
76
+	}
77
+
71 78
 	@Override
72 79
 	public int hashCode() {
73 80
 		int hash = 7;

+ 3
- 0
CodeModel/src/main/java/org/openzen/zenscript/codemodel/type/ITypeID.java View File

@@ -5,6 +5,7 @@
5 5
  */
6 6
 package org.openzen.zenscript.codemodel.type;
7 7
 
8
+import java.util.List;
8 9
 import java.util.Map;
9 10
 import org.openzen.zenscript.codemodel.GenericMapper;
10 11
 import org.openzen.zenscript.codemodel.HighLevelDefinition;
@@ -64,6 +65,8 @@ public interface ITypeID {
64 65
 		return accept(new MatchingTypeVisitor(cache, targetType, mapping));
65 66
 	}
66 67
 	
68
+	public void extractTypeParameters(List<TypeParameter> typeParameters);
69
+	
67 70
 	public static class MatchingTypeVisitor implements ITypeVisitor<Boolean> {
68 71
 		private final ITypeID type;
69 72
 		private final Map<TypeParameter, ITypeID> mapping;

+ 7
- 0
CodeModel/src/main/java/org/openzen/zenscript/codemodel/type/IteratorTypeID.java View File

@@ -6,6 +6,7 @@
6 6
 package org.openzen.zenscript.codemodel.type;
7 7
 
8 8
 import java.util.Arrays;
9
+import java.util.List;
9 10
 import java.util.Map;
10 11
 import org.openzen.zenscript.codemodel.GenericMapper;
11 12
 import org.openzen.zenscript.codemodel.generic.TypeParameter;
@@ -68,6 +69,12 @@ public class IteratorTypeID implements ITypeID {
68 69
 		return false;
69 70
 	}
70 71
 
72
+	@Override
73
+	public void extractTypeParameters(List<TypeParameter> typeParameters) {
74
+		for (ITypeID type : iteratorTypes)
75
+			type.extractTypeParameters(typeParameters);
76
+	}
77
+
71 78
 	@Override
72 79
 	public int hashCode() {
73 80
 		int hash = 5;

+ 6
- 0
CodeModel/src/main/java/org/openzen/zenscript/codemodel/type/OptionalTypeID.java View File

@@ -5,6 +5,7 @@
5 5
  */
6 6
 package org.openzen.zenscript.codemodel.type;
7 7
 
8
+import java.util.List;
8 9
 import java.util.Objects;
9 10
 import org.openzen.zenscript.codemodel.GenericMapper;
10 11
 import org.openzen.zenscript.codemodel.HighLevelDefinition;
@@ -77,6 +78,11 @@ public class OptionalTypeID implements ITypeID {
77 78
 		return true;
78 79
 	}
79 80
 
81
+	@Override
82
+	public void extractTypeParameters(List<TypeParameter> typeParameters) {
83
+		baseType.extractTypeParameters(typeParameters);
84
+	}
85
+
80 86
 	@Override
81 87
 	public int hashCode() {
82 88
 		int hash = 7;

+ 7
- 0
CodeModel/src/main/java/org/openzen/zenscript/codemodel/type/RangeTypeID.java View File

@@ -5,6 +5,7 @@
5 5
  */
6 6
 package org.openzen.zenscript.codemodel.type;
7 7
 
8
+import java.util.List;
8 9
 import org.openzen.zenscript.codemodel.GenericMapper;
9 10
 import org.openzen.zenscript.codemodel.generic.TypeParameter;
10 11
 
@@ -65,6 +66,12 @@ public class RangeTypeID implements ITypeID {
65 66
 		return false;
66 67
 	}
67 68
 
69
+	@Override
70
+	public void extractTypeParameters(List<TypeParameter> typeParameters) {
71
+		from.extractTypeParameters(typeParameters);
72
+		to.extractTypeParameters(typeParameters);
73
+	}
74
+
68 75
 	@Override
69 76
 	public int hashCode() {
70 77
 		int hash = 5;

+ 3
- 0
CodeModel/src/main/java/org/openzen/zenscript/codemodel/type/member/BuiltinID.java View File

@@ -396,6 +396,7 @@ public enum BuiltinID {
396 396
 	GENERICMAP_GETOPTIONAL,
397 397
 	GENERICMAP_PUT,
398 398
 	GENERICMAP_CONTAINS,
399
+	GENERICMAP_ADDALL,
399 400
 	GENERICMAP_SIZE,
400 401
 	GENERICMAP_ISEMPTY,
401 402
 	GENERICMAP_HASHCODE,
@@ -441,5 +442,7 @@ public enum BuiltinID {
441 442
 	RANGE_FROM,
442 443
 	RANGE_TO,
443 444
 	
445
+	OPTIONAL_IS_NULL,
446
+	OPTIONAL_IS_NOT_NULL,
444 447
 	AUTOOP_NOTEQUALS
445 448
 }

+ 5
- 29
CodeModel/src/main/java/org/openzen/zenscript/codemodel/type/member/DefinitionMemberGroup.java View File

@@ -300,48 +300,24 @@ public class DefinitionMemberGroup {
300 300
 	
301 301
 	public FunctionalMemberRef selectMethod(CodePosition position, TypeScope scope, CallArguments arguments, boolean allowNonStatic, boolean allowStatic) {
302 302
 		// try to match with exact types
303
-		outer: for (TypeMember<FunctionalMemberRef> method : methods) {
303
+		for (TypeMember<FunctionalMemberRef> method : methods) {
304 304
 			if (!(method.member.isStatic() ? allowStatic : allowNonStatic))
305 305
 				continue;
306 306
 			
307 307
 			FunctionHeader header = method.member.header;
308
-			if (header.parameters.length != arguments.arguments.length)
309
-				continue;
310
-			if (header.getNumberOfTypeParameters() != arguments.getNumberOfTypeArguments())
311
-				continue;
312
-			
313
-			if (arguments.typeArguments.length > 0) {
314
-				header = header.fillGenericArguments(scope.getTypeRegistry(), arguments.typeArguments);
315
-			}
316
-			
317
-			for (int i = 0; i < header.parameters.length; i++) {
318
-				if (arguments.arguments[i].type != header.parameters[i].type)
319
-					continue outer;
320
-			}
321
-			
322
-			return method.member;
308
+			if (header.matchesExactly(arguments, scope))
309
+				return method.member;
323 310
 		}
324 311
 		
325 312
 		// try to match with approximate types
326 313
 		FunctionalMemberRef selected = null;
327
-		outer: for (TypeMember<FunctionalMemberRef> method : methods) {
314
+		for (TypeMember<FunctionalMemberRef> method : methods) {
328 315
 			if (!(method.member.isStatic() ? allowStatic : allowNonStatic))
329 316
 				continue;
330 317
 			
331 318
 			FunctionHeader header = method.member.header;
332
-			if (header.parameters.length != arguments.arguments.length)
319
+			if (!header.matchesImplicitly(arguments, scope))
333 320
 				continue;
334
-			if (header.getNumberOfTypeParameters() != arguments.getNumberOfTypeArguments())
335
-				continue;
336
-			
337
-			if (arguments.typeArguments.length > 0) {
338
-				header = header.fillGenericArguments(scope.getTypeRegistry(), arguments.typeArguments);
339
-			}
340
-			
341
-			for (int i = 0; i < header.parameters.length; i++) {
342
-				if (!scope.getTypeMembers(arguments.arguments[i].type).canCastImplicit(header.parameters[i].type))
343
-					continue outer;
344
-			}
345 321
 			
346 322
 			if (selected != null) {
347 323
 				StringBuilder explanation = new StringBuilder();

+ 3
- 0
CodeModel/src/main/java/org/openzen/zenscript/codemodel/type/member/TypeMemberBuilder.java View File

@@ -355,6 +355,7 @@ public class TypeMemberBuilder implements ITypeVisitor<Void> {
355 355
 		method(builtin, "getOptional", getOptionalHeader, GENERICMAP_GETOPTIONAL);
356 356
 		method(builtin, "put", putHeader, GENERICMAP_PUT);
357 357
 		method(builtin, "contains", containsHeader, GENERICMAP_CONTAINS);
358
+		method(builtin, "addAll", new FunctionHeader(VOID, map), GENERICMAP_ADDALL);
358 359
 		
359 360
 		getter(builtin, GENERICMAP_SIZE, "size", INT);
360 361
 		getter(builtin, GENERICMAP_ISEMPTY, "isEmpty", BOOL);
@@ -535,6 +536,8 @@ public class TypeMemberBuilder implements ITypeVisitor<Void> {
535 536
 	public Void visitOptional(OptionalTypeID optional) {
536 537
 		ClassDefinition builtin = new ClassDefinition(BUILTIN, null, "optional", Modifiers.EXPORT, null);
537 538
 		optional.baseType.accept(this);
539
+		operator(builtin, OperatorType.EQUALS, new FunctionHeader(BOOL, NULL), BuiltinID.OPTIONAL_IS_NULL);
540
+		operator(builtin, OperatorType.NOTEQUALS, new FunctionHeader(BOOL, NULL), BuiltinID.OPTIONAL_IS_NOT_NULL);
538 541
 		processType(builtin, optional);
539 542
 		return null;
540 543
 	}

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

@@ -87,4 +87,14 @@ public class JavaForeachVisitor implements ForeachIteratorVisitor<Void> {
87 87
     public Void visitCustomIterator() {
88 88
         return null;
89 89
     }
90
+
91
+	@Override
92
+	public Void visitAssocKeyIterator() {
93
+		throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
94
+	}
95
+
96
+	@Override
97
+	public Void visitAssocKeyValueIterator() {
98
+		throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
99
+	}
90 100
 }

+ 166
- 0
JavaSourceCompiler/src/main/java/org/openzen/zenscript/javasource/BaseMemberCompiler.java View File

@@ -0,0 +1,166 @@
1
+/*
2
+ * To change this license header, choose License Headers in Project Properties.
3
+ * To change this template file, choose Tools | Templates
4
+ * and open the template in the editor.
5
+ */
6
+package org.openzen.zenscript.javasource;
7
+
8
+import java.util.Collections;
9
+import org.openzen.zenscript.codemodel.FunctionHeader;
10
+import org.openzen.zenscript.codemodel.FunctionParameter;
11
+import org.openzen.zenscript.codemodel.HighLevelDefinition;
12
+import org.openzen.zenscript.codemodel.Modifiers;
13
+import org.openzen.zenscript.codemodel.generic.TypeParameter;
14
+import org.openzen.zenscript.codemodel.member.MemberVisitor;
15
+import org.openzen.zenscript.codemodel.statement.BlockStatement;
16
+import org.openzen.zenscript.codemodel.statement.EmptyStatement;
17
+import org.openzen.zenscript.codemodel.statement.Statement;
18
+import org.openzen.zenscript.codemodel.type.ITypeID;
19
+import org.openzen.zenscript.javasource.scope.JavaSourceFileScope;
20
+import org.openzen.zenscript.javasource.scope.JavaSourceStatementScope;
21
+
22
+/**
23
+ *
24
+ * @author Hoofdgebruiker
25
+ */
26
+public abstract class BaseMemberCompiler implements MemberVisitor<Void> {
27
+	protected final String indent;
28
+	protected final StringBuilder output;
29
+	protected final JavaSourceFileScope scope;
30
+	protected final JavaSourceStatementScope fieldInitializerScope;
31
+	protected final JavaSourceFormattingSettings settings;
32
+	protected final ITypeID expansionTarget;
33
+	protected final HighLevelDefinition definition;
34
+	
35
+	private ElementType currentElementType = null;
36
+	
37
+	public BaseMemberCompiler(
38
+			JavaSourceFormattingSettings settings,
39
+			String indent,
40
+			StringBuilder output,
41
+			JavaSourceFileScope scope,
42
+			ITypeID expansionTarget,
43
+			HighLevelDefinition definition)
44
+	{
45
+		this.indent = indent;
46
+		this.output = output;
47
+		this.scope = scope;
48
+		this.settings = settings;
49
+		this.expansionTarget = expansionTarget;
50
+		this.definition = definition;
51
+		
52
+		fieldInitializerScope = new JavaSourceStatementScope(
53
+				scope,
54
+				settings,
55
+				null,
56
+				indent + settings.indent,
57
+				null,
58
+				null,
59
+				true);
60
+	}
61
+	
62
+	protected void begin(ElementType type) {
63
+		if (currentElementType != null) {
64
+			if (currentElementType != ElementType.FIELD || type != ElementType.FIELD)
65
+				output.append(indent).append('\n');
66
+		}
67
+		
68
+		this.currentElementType = type;
69
+	}
70
+	
71
+	protected void modifiers(int modifiers) {
72
+		if (Modifiers.isPublic(modifiers))
73
+			output.append("public ");
74
+		if (Modifiers.isProtected(modifiers))
75
+			output.append("protected ");
76
+		if (Modifiers.isPrivate(modifiers))
77
+			output.append("private ");
78
+		if (Modifiers.isStatic(modifiers))
79
+			output.append("static ");
80
+		if (Modifiers.isFinal(modifiers))
81
+			output.append("final ");
82
+	}
83
+	
84
+	protected void compileBody(Statement body, FunctionHeader header) {
85
+		if (body == null || body instanceof EmptyStatement) {
86
+			output.append(";\n");
87
+		} else {
88
+			if (!(body instanceof BlockStatement))
89
+				body = new BlockStatement(body.position, Collections.singletonList(body));
90
+			
91
+			JavaSourceStatementScope scope = new JavaSourceStatementScope(this.scope, settings, header, indent + settings.indent, null, null, expansionTarget != null);
92
+			body.accept(new JavaSourceStatementCompiler(scope, output, true, false));
93
+			output.append('\n');
94
+		}
95
+	}
96
+	
97
+	protected void formatParameters(boolean isStatic, FunctionHeader header) {
98
+		formatParameters(isStatic, null, header);
99
+	}
100
+	
101
+	protected void formatParameters(boolean isStatic, TypeParameter[] targetTypeParameters, FunctionHeader header) {
102
+		output.append("(");
103
+		boolean first = true;
104
+		if (expansionTarget != null && !isStatic) {
105
+			if (targetTypeParameters != null) {
106
+				for (TypeParameter parameter : targetTypeParameters) {
107
+					if (first)
108
+						first = false;
109
+					else
110
+						output.append(", ");
111
+
112
+					output.append("Class<").append(parameter.name).append("> typeOf").append(parameter.name);
113
+				}
114
+			}
115
+			if (first)
116
+				first = false;
117
+			else
118
+				output.append(", ");
119
+			
120
+			output.append(scope.type(expansionTarget));
121
+			output.append(" self");
122
+		}
123
+		if (header.typeParameters != null) {
124
+			for (TypeParameter typeParameter : header.typeParameters) {
125
+				if (first)
126
+					first = false;
127
+				else
128
+					output.append(", ");
129
+
130
+				output.append("Class<")
131
+						.append(typeParameter.name)
132
+						.append(">")
133
+						.append(" ")
134
+						.append("typeOf")
135
+						.append(typeParameter.name);
136
+			}
137
+		}
138
+		
139
+		for (int i = 0; i < header.parameters.length; i++) {
140
+			if (first)
141
+				first = false;
142
+			else
143
+				output.append(", ");
144
+			
145
+			FunctionParameter parameter = header.parameters[i];
146
+			output.append(scope.type(parameter.type));
147
+			output.append(" ").append(parameter.name);
148
+			if (parameter.variadic)
149
+				output.append("...");
150
+		}
151
+		output.append(")");
152
+		
153
+		if (header.thrownType != null) {
154
+			output.append(" throws ");
155
+			output.append(scope.type(header.thrownType));
156
+		}
157
+	}
158
+	
159
+	public enum ElementType {
160
+		STATICINIT,
161
+		FIELD,
162
+		CONSTRUCTOR,
163
+		METHOD,
164
+		INNERCLASS
165
+	}
166
+}

+ 92
- 22
JavaSourceCompiler/src/main/java/org/openzen/zenscript/javasource/JavaDefinitionVisitor.java View File

@@ -7,6 +7,7 @@ package org.openzen.zenscript.javasource;
7 7
 
8 8
 import java.util.ArrayList;
9 9
 import java.util.List;
10
+import java.util.Map;
10 11
 import org.openzen.zenscript.codemodel.HighLevelDefinition;
11 12
 import org.openzen.zenscript.codemodel.Modifiers;
12 13
 import org.openzen.zenscript.codemodel.definition.AliasDefinition;
@@ -21,28 +22,57 @@ import org.openzen.zenscript.codemodel.definition.VariantDefinition;
21 22
 import org.openzen.zenscript.codemodel.member.EnumConstantMember;
22 23
 import org.openzen.zenscript.codemodel.member.IDefinitionMember;
23 24
 import org.openzen.zenscript.codemodel.member.ImplementationMember;
25
+import org.openzen.zenscript.codemodel.type.DefinitionTypeID;
26
+import org.openzen.zenscript.codemodel.type.ITypeID;
27
+import org.openzen.zenscript.compiler.CompileScope;
28
+import org.openzen.zenscript.compiler.SemanticModule;
29
+import org.openzen.zenscript.javasource.prepare.JavaNativeClass;
24 30
 import org.openzen.zenscript.javasource.scope.JavaSourceFileScope;
31
+import org.openzen.zenscript.javasource.tags.JavaSourceClass;
25 32
 
26 33
 /**
27 34
  *
28 35
  * @author Hoofdgebruiker
29 36
  */
30 37
 public class JavaDefinitionVisitor implements DefinitionVisitor<Void> {
31
-	private final JavaSourceFileScope scope;
38
+	private final JavaSourceCompiler compiler;
39
+	private final JavaSourceClass cls;
40
+	private final JavaSourceFile file;
32 41
 	private final JavaSourceFormattingSettings settings;
42
+	private final List<ExpansionDefinition> expansions;
33 43
 	private final StringBuilder output;
44
+	private final Map<HighLevelDefinition, SemanticModule> modules;
34 45
 	
35
-	public JavaDefinitionVisitor(JavaSourceFormattingSettings settings, JavaSourceFileScope scope, StringBuilder output) {
36
-		this.settings = settings;
37
-		this.scope = scope;
46
+	public JavaDefinitionVisitor(
47
+			JavaSourceCompiler compiler,
48
+			JavaSourceClass cls,
49
+			JavaSourceFile file,
50
+			StringBuilder output,
51
+			List<ExpansionDefinition> expansions,
52
+			Map<HighLevelDefinition, SemanticModule> modules)
53
+	{
54
+		this.compiler = compiler;
55
+		this.cls = cls;
56
+		this.file = file;
57
+		this.settings = compiler.settings;
38 58
 		this.output = output;
59
+		this.expansions = expansions;
60
+		this.modules = modules;
61
+	}
62
+	
63
+	private JavaSourceFileScope createScope(HighLevelDefinition definition) {
64
+		SemanticModule module = modules.get(definition);
65
+		CompileScope scope = new CompileScope(definition.access, module.compilationUnit.globalTypeRegistry, module.expansions, module.annotations);
66
+		return new JavaSourceFileScope(file.importer, compiler.typeGenerator, compiler.helperGenerator, cls, scope, definition instanceof InterfaceDefinition);
39 67
 	}
40 68
 
41 69
 	@Override
42 70
 	public Void visitClass(ClassDefinition definition) {
71
+		JavaSourceFileScope scope = createScope(definition);
72
+		
43 73
 		convertModifiers(definition.modifiers);
44 74
 		output.append("class ").append(definition.name);
45
-		JavaSourceUtils.formatTypeParameters(scope, output, definition.genericParameters);
75
+		JavaSourceUtils.formatTypeParameters(scope.typeVisitor, output, definition.genericParameters);
46 76
 		if (definition.superType != null) {
47 77
 			output.append(" extends ");
48 78
 			output.append(scope.type(definition.superType));
@@ -67,24 +97,30 @@ public class JavaDefinitionVisitor implements DefinitionVisitor<Void> {
67 97
 		}
68 98
 		
69 99
 		output.append(" {\n");
70
-		compileMembers(definition);
100
+		compileMembers(scope, definition);
101
+		compileExpansions();
71 102
 		output.append("}\n");
72 103
 		return null;
73 104
 	}
74 105
 
75 106
 	@Override
76 107
 	public Void visitInterface(InterfaceDefinition definition) {
108
+		JavaSourceFileScope scope = createScope(definition);
109
+		
77 110
 		convertModifiers(definition.modifiers | Modifiers.VIRTUAL); // to prevent 'final'
78 111
 		output.append("interface ").append(definition.name);
79
-		JavaSourceUtils.formatTypeParameters(scope, output, definition.genericParameters);
112
+		JavaSourceUtils.formatTypeParameters(scope.typeVisitor, output, definition.genericParameters);
80 113
 		output.append(" {\n");
81
-		compileMembers(definition);
114
+		compileMembers(scope, definition);
115
+		compileExpansions();
82 116
 		output.append("}\n");
83 117
 		return null;
84 118
 	}
85 119
 
86 120
 	@Override
87 121
 	public Void visitEnum(EnumDefinition definition) {
122
+		JavaSourceFileScope scope = createScope(definition);
123
+		
88 124
 		convertModifiers(definition.modifiers | Modifiers.VIRTUAL); // to prevent 'final'
89 125
 		output.append("enum ").append(definition.name);
90 126
 		
@@ -104,28 +140,34 @@ public class JavaDefinitionVisitor implements DefinitionVisitor<Void> {
104 140
 		
105 141
 		if (definition.members.size() > 0) {
106 142
 			output.append(";\n");
107
-			compileMembers(definition);
143
+			compileMembers(scope, definition);
108 144
 		} else {
109 145
 			output.append("\n");
110 146
 		}
111 147
 		
148
+		compileExpansions();
112 149
 		output.append("}\n");
113 150
 		return null;
114 151
 	}
115 152
 
116 153
 	@Override
117 154
 	public Void visitStruct(StructDefinition definition) {
155
+		JavaSourceFileScope scope = createScope(definition);
156
+		
118 157
 		convertModifiers(definition.modifiers | Modifiers.FINAL);
119 158
 		output.append("class ").append(definition.name);
120
-		JavaSourceUtils.formatTypeParameters(scope, output, definition.genericParameters);
159
+		JavaSourceUtils.formatTypeParameters(scope.typeVisitor, output, definition.genericParameters);
121 160
 		output.append(" {\n");
122
-		compileMembers(definition);
161
+		compileMembers(scope, definition);
162
+		compileExpansions();
123 163
 		output.append("}\n");
124 164
 		return null;
125 165
 	}
126 166
 
127 167
 	@Override
128 168
 	public Void visitFunction(FunctionDefinition definition) {
169
+		JavaSourceFileScope scope = createScope(definition);
170
+		
129 171
 		convertModifiers(definition.modifiers | Modifiers.STATIC);
130 172
 		
131 173
 		return null;
@@ -133,17 +175,20 @@ public class JavaDefinitionVisitor implements DefinitionVisitor<Void> {
133 175
 
134 176
 	@Override
135 177
 	public Void visitExpansion(ExpansionDefinition definition) {
178
+		JavaSourceFileScope scope = createScope(definition);
179
+		
136 180
 		convertModifiers(definition.modifiers);
137 181
 		output.append("class ");
138
-		output.append(scope.className);
182
+		output.append(cls.name);
139 183
 		output.append(" {\n");
140
-		output.append(settings.indent).append("private ").append(scope.className).append("() {}\n");
184
+		output.append(settings.indent).append("private ").append(cls.name).append("() {}\n");
141 185
 		
142
-		JavaExpansionMemberCompiler memberCompiler = new JavaExpansionMemberCompiler(settings, definition.target, "\t", output, scope);
186
+		JavaExpansionMemberCompiler memberCompiler = new JavaExpansionMemberCompiler(settings, definition.target, definition.genericParameters, "\t", output, scope, definition);
143 187
 		for (IDefinitionMember member : definition.members)
144 188
 			member.accept(memberCompiler);
145 189
 		memberCompiler.finish();
146 190
 		
191
+		compileExpansions();
147 192
 		output.append("}");
148 193
 		return null;
149 194
 	}
@@ -155,11 +200,13 @@ public class JavaDefinitionVisitor implements DefinitionVisitor<Void> {
155 200
 
156 201
 	@Override
157 202
 	public Void visitVariant(VariantDefinition variant) {
203
+		JavaSourceFileScope scope = createScope(variant);
204
+		
158 205
 		convertModifiers(variant.modifiers | Modifiers.VIRTUAL | Modifiers.ABSTRACT);
159 206
 		output.append("class ").append(variant.name);
160
-		JavaSourceUtils.formatTypeParameters(scope, output, variant.genericParameters);
207
+		JavaSourceUtils.formatTypeParameters(scope.typeVisitor, output, variant.genericParameters);
161 208
 		output.append("{\n");
162
-		compileMembers(variant);
209
+		compileMembers(scope, variant);
163 210
 		output.append(settings.indent).append("public abstract Discriminant getDiscriminant();\n");
164 211
 		
165 212
 		output.append(settings.indent).append("\n");
@@ -172,7 +219,7 @@ public class JavaDefinitionVisitor implements DefinitionVisitor<Void> {
172 219
 		for (VariantDefinition.Option option : variant.options) {
173 220
 			output.append(settings.indent).append("\n");
174 221
 			output.append(settings.indent).append("public static class ").append(option.name);
175
-			JavaSourceUtils.formatTypeParameters(scope, output, variant.genericParameters);
222
+			JavaSourceUtils.formatTypeParameters(scope.typeVisitor, output, variant.genericParameters);
176 223
 			output.append(" extends ");
177 224
 			output.append(variant.name);
178 225
 			if (variant.genericParameters != null && variant.genericParameters.length > 0) {
@@ -216,10 +263,21 @@ public class JavaDefinitionVisitor implements DefinitionVisitor<Void> {
216 263
 			output.append(settings.indent).append("}\n");
217 264
 		}
218 265
 		
266
+		compileExpansions();
219 267
 		output.append("}\n");
220 268
 		return null;
221 269
 	}
222 270
 	
271
+	private void compileExpansions() {
272
+		for (ExpansionDefinition definition : expansions) {
273
+			JavaSourceFileScope scope = createScope(definition);
274
+			JavaExpansionMemberCompiler memberCompiler = new JavaExpansionMemberCompiler(settings, definition.target, definition.genericParameters, "\t", output, scope, definition);
275
+			for (IDefinitionMember member : definition.members)
276
+				member.accept(memberCompiler);
277
+			memberCompiler.finish();
278
+		}
279
+	}
280
+	
223 281
 	private void convertModifiers(int modifiers) {
224 282
 		if (Modifiers.isExport(modifiers) || Modifiers.isPublic(modifiers))
225 283
 			output.append("public ");
@@ -239,10 +297,22 @@ public class JavaDefinitionVisitor implements DefinitionVisitor<Void> {
239 297
 		return true; // TODO: check merging conflicts
240 298
 	}
241 299
 	
242
-	private void compileMembers(HighLevelDefinition definition) {
243
-		JavaMemberCompiler memberCompiler = new JavaMemberCompiler(settings, "\t", output, scope, false, scope.isInterface);
244
-		for (IDefinitionMember member : definition.members)
245
-			member.accept(memberCompiler);
246
-		memberCompiler.finish();
300
+	private void compileMembers(JavaSourceFileScope scope, HighLevelDefinition definition) {
301
+		if (definition.hasTag(JavaNativeClass.class)) {
302
+			ITypeID[] typeParameters = new ITypeID[definition.getNumberOfGenericParameters()];
303
+			for (int i = 0; i < typeParameters.length; i++)
304
+				typeParameters[i] = scope.semanticScope.getTypeRegistry().getGeneric(definition.genericParameters[i]);
305
+			ITypeID targetType = new DefinitionTypeID(definition, typeParameters);
306
+			
307
+			JavaExpansionMemberCompiler memberCompiler = new JavaExpansionMemberCompiler(settings, targetType, definition.genericParameters, "\t", output, scope, definition);
308
+			for (IDefinitionMember member : definition.members)
309
+				member.accept(memberCompiler);
310
+			memberCompiler.finish();
311
+		} else {
312
+			JavaMemberCompiler memberCompiler = new JavaMemberCompiler(settings, "\t", output, scope, scope.isInterface, definition);
313
+			for (IDefinitionMember member : definition.members)
314
+				member.accept(memberCompiler);
315
+			memberCompiler.finish();
316
+		}
247 317
 	}
248 318
 }

+ 50
- 247
JavaSourceCompiler/src/main/java/org/openzen/zenscript/javasource/JavaExpansionMemberCompiler.java View File

@@ -6,77 +6,81 @@
6 6
 package org.openzen.zenscript.javasource;
7 7
 
8 8
 import java.util.ArrayList;
9
-import java.util.Collections;
10 9
 import java.util.List;
11 10
 import org.openzen.zenscript.codemodel.FunctionHeader;
12 11
 import org.openzen.zenscript.codemodel.FunctionParameter;
12
+import org.openzen.zenscript.codemodel.HighLevelDefinition;
13 13
 import org.openzen.zenscript.codemodel.Modifiers;
14
-import org.openzen.zenscript.codemodel.OperatorType;
15 14
 import org.openzen.zenscript.codemodel.generic.TypeParameter;
16 15
 import org.openzen.zenscript.codemodel.member.CallerMember;
17 16
 import org.openzen.zenscript.codemodel.member.CasterMember;
18 17
 import org.openzen.zenscript.codemodel.member.ConstMember;
19 18
 import org.openzen.zenscript.codemodel.member.ConstructorMember;
20 19
 import org.openzen.zenscript.codemodel.member.CustomIteratorMember;
20
+import org.openzen.zenscript.codemodel.member.DefinitionMember;
21 21
 import org.openzen.zenscript.codemodel.member.DestructorMember;
22 22
 import org.openzen.zenscript.codemodel.member.FieldMember;
23 23
 import org.openzen.zenscript.codemodel.member.GetterMember;
24 24
 import org.openzen.zenscript.codemodel.member.ImplementationMember;
25 25
 import org.openzen.zenscript.codemodel.member.InnerDefinitionMember;
26
-import org.openzen.zenscript.codemodel.member.MemberVisitor;
27 26
 import org.openzen.zenscript.codemodel.member.MethodMember;
28 27
 import org.openzen.zenscript.codemodel.member.OperatorMember;
29 28
 import org.openzen.zenscript.codemodel.member.SetterMember;
30 29
 import org.openzen.zenscript.codemodel.member.StaticInitializerMember;
31
-import org.openzen.zenscript.codemodel.statement.BlockStatement;
32
-import org.openzen.zenscript.codemodel.statement.EmptyStatement;
33 30
 import org.openzen.zenscript.codemodel.statement.Statement;
34 31
 import org.openzen.zenscript.codemodel.type.BasicTypeID;
35 32
 import org.openzen.zenscript.codemodel.type.ITypeID;
36 33
 import org.openzen.zenscript.javasource.scope.JavaSourceFileScope;
37
-import org.openzen.zenscript.javasource.scope.JavaSourceStatementScope;
38
-import org.openzen.zenscript.shared.StringUtils;
34
+import org.openzen.zenscript.javasource.tags.JavaSourceMethod;
39 35
 
40 36
 /**
41 37
  *
42 38
  * @author Hoofdgebruiker
43 39
  */
44
-public class JavaExpansionMemberCompiler implements MemberVisitor<Void> {
45
-	private final String indent;
46
-	private final StringBuilder output;
47
-	private final JavaSourceFileScope scope;
48
-	private final JavaSourceStatementScope fieldInitializerScope;
49
-	private final JavaSourceFormattingSettings settings;
40
+public class JavaExpansionMemberCompiler extends BaseMemberCompiler {
50 41
 	private final List<FieldMember> fields = new ArrayList<>();
51
-	private final ITypeID targetType;
52
-	private boolean first = true;
42
+	private final TypeParameter[] expansionTypeParameters;
53 43
 	
54
-	public JavaExpansionMemberCompiler(JavaSourceFormattingSettings settings, ITypeID targetType, String indent, StringBuilder output, JavaSourceFileScope scope) {
55
-		this.indent = indent;
56
-		this.output = output;
57
-		this.scope = scope;
58
-		this.settings = settings;
59
-		this.targetType = targetType;
44
+	public JavaExpansionMemberCompiler(
45
+			JavaSourceFormattingSettings settings,
46
+			ITypeID targetType,
47
+			TypeParameter[] expansionTypeParameters,
48
+			String indent,
49
+			StringBuilder output,
50
+			JavaSourceFileScope scope,
51
+			HighLevelDefinition definition)
52
+	{
53
+		super(settings, indent, output, scope, targetType, definition);
60 54
 		
61
-		fieldInitializerScope = new JavaSourceStatementScope(
62
-				scope,
63
-				settings,
64
-				null,
65
-				indent + settings.indent,
66
-				null,
67
-				null,
68
-				true);
55
+		this.expansionTypeParameters = expansionTypeParameters;
69 56
 	}
70 57
 	
71
-	private void addSpacing() {
72
-		if (first)
73
-			first = false;
58
+	private void compileMethod(DefinitionMember member, FunctionHeader header, Statement body) {
59
+		JavaSourceMethod method = member.getTag(JavaSourceMethod.class);
60
+		if (method == null)
61
+			throw new AssertionError();
62
+		if (!method.compile)
63
+			return;
64
+		
65
+		begin(ElementType.METHOD);
66
+		output.append(indent);
67
+		
68
+		modifiers(member.modifiers | Modifiers.STATIC);
69
+		if (member.isStatic())
70
+			JavaSourceUtils.formatTypeParameters(scope.typeVisitor, output, header.typeParameters);
74 71
 		else
75
-			output.append(indent).append("\n");
72
+			JavaSourceUtils.formatTypeParameters(scope.typeVisitor, output, expansionTypeParameters, header.typeParameters);
73
+		
74
+		output.append(header.returnType.accept(scope.typeVisitor));
75
+		output.append(" ");
76
+		output.append(method.name);
77
+		formatParameters(member.isStatic(), expansionTypeParameters, header);
78
+		compileBody(body, header);
76 79
 	}
77 80
 	
78 81
 	@Override
79 82
 	public Void visitConst(ConstMember member) {
83
+		begin(ElementType.FIELD);
80 84
 		modifiers(member.modifiers | Modifiers.STATIC | Modifiers.FINAL);
81 85
 		output.append(scope.type(member.type));
82 86
 		output.append(" ");
@@ -89,8 +93,7 @@ public class JavaExpansionMemberCompiler implements MemberVisitor<Void> {
89 93
 
90 94
 	@Override
91 95
 	public Void visitField(FieldMember member) {
92
-		// TODO: nonstatic fields!
93
-		first = false;
96
+		begin(ElementType.FIELD);
94 97
 		
95 98
 		output.append(indent);
96 99
 		int modifiers = 0;
@@ -120,16 +123,8 @@ public class JavaExpansionMemberCompiler implements MemberVisitor<Void> {
120 123
 
121 124
 	@Override
122 125
 	public Void visitConstructor(ConstructorMember member) {
123
-		// TODO: constructors
124
-		/*addSpacing();
125
-		
126
-		output.append(indent);
127
-		modifiers(member.modifiers);
128
-		JavaSourceUtils.formatTypeParameters(importer, output, member.header.typeParameters);
129
-		output.append(importer.getName());
130
-		formatParameters(true, member.header);
131
-		compileBody(member.body, member.header);*/
132
-		throw new UnsupportedOperationException("Expansions cannot declare constructors yet");
126
+		compileMethod(member, member.header, member.body);
127
+		return null;
133 128
 	}
134 129
 
135 130
 	@Override
@@ -139,105 +134,61 @@ public class JavaExpansionMemberCompiler implements MemberVisitor<Void> {
139 134
 
140 135
 	@Override
141 136
 	public Void visitMethod(MethodMember member) {
142
-		addSpacing();
143
-		
144
-		output.append(indent);
145
-		
146
-		modifiers(member.modifiers | Modifiers.STATIC);
147
-		JavaSourceUtils.formatTypeParameters(scope, output, member.header.typeParameters);
148
-		output.append(scope.type(member.header.returnType));
149
-		output.append(" ");
150
-		output.append(member.name);
151
-		formatParameters(member.isStatic(), member.header);
152
-		compileBody(member.body, member.header);
137
+		compileMethod(member, member.header, member.body);
153 138
 		return null;
154 139
 	}
155 140
 
156 141
 	@Override
157 142
 	public Void visitGetter(GetterMember member) {
158
-		addSpacing();
159
-		
160
-		output.append(indent);
161
-		modifiers(member.modifiers | Modifiers.STATIC);
162
-		output.append(scope.type(member.type));
163
-		output.append(" ");
164
-		output.append("get").append(StringUtils.capitalize(member.name));
165
-		output.append("()");
166
-		compileBody(member.body, member.header);
143
+		compileMethod(member, member.header, member.body);
167 144
 		return null;
168 145
 	}
169 146
 
170 147
 	@Override
171 148
 	public Void visitSetter(SetterMember member) {
172
-		addSpacing();
173
-		
174
-		output.append(indent);
175
-		modifiers(member.modifiers | Modifiers.STATIC);
176
-		output.append("void set").append(StringUtils.capitalize(member.name));
177
-		output.append("(");
178
-		output.append(scope.type(member.type));
179
-		output.append(" ");
180
-		output.append("value");
181
-		output.append(")");
182
-		compileBody(member.body, member.header);
149
+		compileMethod(member, new FunctionHeader(BasicTypeID.VOID, new FunctionParameter(member.type, "value")), member.body);
183 150
 		return null;
184 151
 	}
185 152
 
186 153
 	@Override
187 154
 	public Void visitOperator(OperatorMember member) {
188
-		addSpacing();
189
-		
190
-		output.append(indent);
191
-		modifiers(member.modifiers | Modifiers.STATIC);
192
-		output.append(scope.type(member.header.returnType));
193
-		output.append(' ');
194
-		output.append(getOperatorName(member.operator));
195
-		formatParameters(member.isStatic(), member.header);
196
-		compileBody(member.body, member.header);
155
+		compileMethod(member, member.header, member.body);
197 156
 		return null;
198 157
 	}
199 158
 
200 159
 	@Override
201 160
 	public Void visitCaster(CasterMember member) {
202
-		addSpacing();
203
-		
204
-		output.append(indent);
205
-		modifiers(member.modifiers | Modifiers.STATIC);
206
-		output.append(scope.type(member.toType));
207
-		output.append(" ");
208
-		output.append("to").append(member.toType.accept(new JavaSourceTypeNameVisitor()));
209
-		output.append("(").append(scope.type(targetType)).append(" self)");
210
-		compileBody(member.body, member.header);
161
+		compileMethod(member, member.header, member.body);
211 162
 		return null;
212 163
 	}
213 164
 
214 165
 	@Override
215 166
 	public Void visitCustomIterator(CustomIteratorMember member) {
216
-		addSpacing();
217
-		
167
+		compileMethod(member, new FunctionHeader(scope.semanticScope.getTypeRegistry().getIterator(member.getLoopVariableTypes())), member.body);
218 168
 		return null;
219 169
 	}
220 170
 
221 171
 	@Override
222 172
 	public Void visitCaller(CallerMember member) {
223
-		addSpacing();
224
-		
173
+		compileMethod(member, member.header, member.body);
225 174
 		return null;
226 175
 	}
227 176
 
228 177
 	@Override
229 178
 	public Void visitImplementation(ImplementationMember member) {
179
+		// TODO
230 180
 		return null;
231 181
 	}
232 182
 
233 183
 	@Override
234 184
 	public Void visitInnerDefinition(InnerDefinitionMember member) {
185
+		// TODO
235 186
 		return null;
236 187
 	}
237 188
 
238 189
 	@Override
239 190
 	public Void visitStaticInitializer(StaticInitializerMember member) {
240
-		addSpacing();
191
+		begin(ElementType.STATICINIT);
241 192
 		output.append(indent).append("static ");
242 193
 		compileBody(member.body, new FunctionHeader(BasicTypeID.VOID));
243 194
 		return null;
@@ -252,152 +203,4 @@ public class JavaExpansionMemberCompiler implements MemberVisitor<Void> {
252 203
 				visitSetter(field.autoSetter);
253 204
 		}
254 205
 	}
255
-	
256
-	private void modifiers(int modifiers) {
257
-		if (Modifiers.isPublic(modifiers))
258
-			output.append("public ");
259
-		if (Modifiers.isProtected(modifiers))
260
-			output.append("protected ");
261
-		if (Modifiers.isPrivate(modifiers))
262
-			output.append("private ");
263
-		if (Modifiers.isStatic(modifiers))
264
-			output.append("static ");
265
-		if (Modifiers.isFinal(modifiers))
266
-			output.append("final ");
267
-	}
268
-	
269
-	private void compileBody(Statement body, FunctionHeader header) {
270
-		if (body == null) {
271
-			output.append(";\n");
272
-		} else {
273
-			if (!(body instanceof BlockStatement))
274
-				body = new BlockStatement(body.position, Collections.singletonList(body));
275
-			
276
-			JavaSourceStatementScope scope = new JavaSourceStatementScope(this.scope, settings, header, indent + settings.indent, null, null, true);
277
-			body.accept(new JavaSourceStatementCompiler(scope, output, true, false));
278
-			output.append('\n');
279
-		}
280
-	}
281
-	
282
-	private void formatParameters(boolean isStatic, FunctionHeader header) {
283
-		output.append("(");
284
-		boolean first = true;
285
-		if (!isStatic) {
286
-			first = false;
287
-			output.append(scope.type(targetType));
288
-			output.append(" self");
289
-		}
290
-		if (header.typeParameters != null) {
291
-			for (TypeParameter typeParameter : header.typeParameters) {
292
-				if (first)
293
-					first = false;
294
-				else
295
-					output.append(", ");
296
-
297
-				output.append("Class<")
298
-						.append(typeParameter.name)
299
-						.append(">")
300
-						.append(" ")
301
-						.append("typeOf")
302
-						.append(typeParameter.name);
303
-			}
304
-		}
305
-		
306
-		for (int i = 0; i < header.parameters.length; i++) {
307
-			if (first)
308
-				first = false;
309
-			else
310
-				output.append(", ");
311
-			
312
-			FunctionParameter parameter = header.parameters[i];
313
-			output.append(scope.type(parameter.type));
314
-			output.append(" ").append(parameter.name);
315
-			if (parameter.variadic)
316
-				output.append("...");
317
-		}
318
-		output.append(")");
319
-	}
320
-	
321
-	private String getOperatorName(OperatorType operator) {
322
-		switch (operator) {
323
-			case NEG:
324
-				return "negate";
325
-			case NOT:
326
-				return "invert";
327
-			case ADD:
328
-				return "add";
329
-			case ADDASSIGN:
330
-				return "addAssign";
331
-			case SUB:
332
-				return "subtract";
333
-			case SUBASSIGN:
334
-				return "subAssign";
335
-			case CAT:
336
-				return "concat";
337
-			case CATASSIGN:
338
-				return "append";
339
-			case MUL:
340
-				return "mul";
341
-			case MULASSIGN:
342
-				return "mulAssign";
343
-			case DIV:
344
-				return "div";
345
-			case DIVASSIGN:
346
-				return "divAssign";
347
-			case MOD:
348
-				return "mod";
349
-			case MODASSIGN:
350
-				return "modAssign";
351
-			case AND:
352
-				return "and";
353
-			case ANDASSIGN:
354
-				return "andAssign";
355
-			case OR:
356
-				return "or";
357
-			case ORASSIGN:
358
-				return "orAssign";
359
-			case XOR:
360
-				return "xor";
361
-			case XORASSIGN:
362
-				return "xorAssign";
363
-			case SHL:
364
-				return "shl";
365
-			case SHLASSIGN:
366
-				return "shlAssign";
367
-			case SHR:
368
-				return "shr";
369
-			case SHRASSIGN:
370
-				return "shrAssign";
371
-			case USHR:
372
-				return "ushr";
373
-			case USHRASSIGN:
374
-				return "ushrAssign";
375
-			case INDEXGET:
376
-				return "getAt";
377
-			case INDEXSET:
378
-				return "setAt";
379
-			case INCREMENT:
380
-				return "increment";
381
-			case DECREMENT:
382
-				return "decrement";
383
-			case CONTAINS:
384
-				return "contains";
385
-			case EQUALS:
386
-				return "equals";
387
-			case COMPARE:
388
-				return "compareTo";
389
-			case RANGE:
390
-				return "until";
391
-			case CAST:
392
-				return "cast";
393
-			case CALL:
394
-				return "call";
395
-			case MEMBERGETTER:
396
-				return "getMember";
397
-			case MEMBERSETTER:
398
-				return "setMember";
399
-			default:
400
-				throw new IllegalArgumentException("Invalid operator: " + operator);
401
-		}
402
-	}
403 206
 }

+ 59
- 171
JavaSourceCompiler/src/main/java/org/openzen/zenscript/javasource/JavaMemberCompiler.java View File

@@ -6,78 +6,88 @@
6 6
 package org.openzen.zenscript.javasource;
7 7
 
8 8
 import java.util.ArrayList;
9
-import java.util.Collections;
10 9
 import java.util.List;
11 10
 import org.openzen.zenscript.codemodel.FunctionHeader;
12 11
 import org.openzen.zenscript.codemodel.FunctionParameter;
12
+import org.openzen.zenscript.codemodel.HighLevelDefinition;
13 13
 import org.openzen.zenscript.codemodel.Modifiers;
14
-import org.openzen.zenscript.codemodel.generic.TypeParameter;
15 14
 import org.openzen.zenscript.codemodel.member.CallerMember;
16 15
 import org.openzen.zenscript.codemodel.member.CasterMember;
17 16
 import org.openzen.zenscript.codemodel.member.ConstMember;
18 17
 import org.openzen.zenscript.codemodel.member.ConstructorMember;
19 18
 import org.openzen.zenscript.codemodel.member.CustomIteratorMember;
19
+import org.openzen.zenscript.codemodel.member.DefinitionMember;
20 20
 import org.openzen.zenscript.codemodel.member.DestructorMember;
21 21
 import org.openzen.zenscript.codemodel.member.FieldMember;
22 22
 import org.openzen.zenscript.codemodel.member.GetterMember;
23 23
 import org.openzen.zenscript.codemodel.member.ImplementationMember;
24 24
 import org.openzen.zenscript.codemodel.member.InnerDefinitionMember;
25
-import org.openzen.zenscript.codemodel.member.MemberVisitor;
26 25
 import org.openzen.zenscript.codemodel.member.MethodMember;
27 26
 import org.openzen.zenscript.codemodel.member.OperatorMember;
28 27
 import org.openzen.zenscript.codemodel.member.SetterMember;
29 28
 import org.openzen.zenscript.codemodel.member.StaticInitializerMember;
30
-import org.openzen.zenscript.codemodel.statement.BlockStatement;
31 29
 import org.openzen.zenscript.codemodel.statement.EmptyStatement;
32 30
 import org.openzen.zenscript.codemodel.statement.Statement;
33 31
 import org.openzen.zenscript.codemodel.type.BasicTypeID;
34 32
 import org.openzen.zenscript.javasource.scope.JavaSourceFileScope;
35
-import org.openzen.zenscript.javasource.scope.JavaSourceStatementScope;
36 33
 import org.openzen.zenscript.javasource.tags.JavaSourceMethod;
37
-import org.openzen.zenscript.shared.StringUtils;
38 34
 
39 35
 /**
40 36
  *
41 37
  * @author Hoofdgebruiker
42 38
  */
43
-public class JavaMemberCompiler implements MemberVisitor<Void> {
44
-	private final String indent;
45
-	private final StringBuilder output;
46
-	private final JavaSourceFileScope scope;
47
-	private final JavaSourceStatementScope fieldInitializerScope;
48
-	private final JavaSourceFormattingSettings settings;
39
+public class JavaMemberCompiler extends BaseMemberCompiler {
49 40
 	private final List<FieldMember> fields = new ArrayList<>();
50
-	private final boolean isExpansion;
51 41
 	private final boolean isInterface;
52
-	private boolean first = true;
53 42
 	
54
-	public JavaMemberCompiler(JavaSourceFormattingSettings settings, String indent, StringBuilder output, JavaSourceFileScope scope, boolean isExpansion, boolean isInterface) {
55
-		this.indent = indent;
56
-		this.output = output;
57
-		this.scope = scope;
58
-		this.settings = settings;
59
-		this.isExpansion = isExpansion;
60
-		this.isInterface = isInterface;
43
+	public JavaMemberCompiler(
44
+			JavaSourceFormattingSettings settings,
45
+			String indent,
46
+			StringBuilder output,
47
+			JavaSourceFileScope scope,
48
+			boolean isInterface,
49
+			HighLevelDefinition definition)
50
+	{
51
+		super(settings, indent, output, scope, null, definition);
61 52
 		
62
-		fieldInitializerScope = new JavaSourceStatementScope(
63
-				scope,
64
-				settings,
65
-				null,
66
-				indent + settings.indent,
67
-				null,
68
-				null,
69
-				isExpansion);
53
+		this.isInterface = isInterface;
70 54
 	}
71 55
 	
72
-	private void addSpacing() {
73
-		if (first)
74
-			first = false;
56
+	private void compileMethod(DefinitionMember member, FunctionHeader header, Statement body) {
57
+		JavaSourceMethod method = member.getTag(JavaSourceMethod.class);
58
+		if (method == null)
59
+			throw new AssertionError();
60
+		if (!method.compile)
61
+			return;
62
+		
63
+		boolean hasBody = body != null && !(body instanceof EmptyStatement);
64
+		if (isInterface && method.name.equals("toString") && header.parameters.length == 0) {
65
+			hasBody = false;
66
+		}
67
+			
68
+		
69
+		begin(ElementType.METHOD);
70
+		output.append(indent);
71
+		if (isInterface && hasBody)
72
+			output.append("default ");
73
+		
74
+		modifiers(member.modifiers);
75
+		JavaSourceUtils.formatTypeParameters(scope.typeVisitor, output, header.typeParameters);
76
+		output.append(header.returnType.accept(scope.typeVisitor));
77
+		output.append(" ");
78
+		output.append(method.name);
79
+		formatParameters(member.isStatic(), header);
80
+		
81
+		if (hasBody)
82
+			compileBody(body, header);
75 83
 		else
76
-			output.append(indent).append("\n");
84
+			output.append(";\n");
77 85
 	}
78 86
 	
79 87
 	@Override
80 88
 	public Void visitConst(ConstMember member) {
89
+		begin(ElementType.FIELD);
90
+		
81 91
 		output.append(indent);
82 92
 		modifiers(member.modifiers | Modifiers.STATIC | Modifiers.FINAL);
83 93
 		output.append(scope.type(member.type));
@@ -91,7 +101,7 @@ public class JavaMemberCompiler implements MemberVisitor<Void> {
91 101
 
92 102
 	@Override
93 103
 	public Void visitField(FieldMember member) {
94
-		first = false;
104
+		begin(ElementType.FIELD);
95 105
 		
96 106
 		output.append(indent);
97 107
 		int modifiers = 0;
@@ -121,20 +131,20 @@ public class JavaMemberCompiler implements MemberVisitor<Void> {
121 131
 
122 132
 	@Override
123 133
 	public Void visitConstructor(ConstructorMember member) {
124
-		addSpacing();
134
+		begin(ElementType.CONSTRUCTOR);
125 135
 		
126 136
 		output.append(indent);
127 137
 		modifiers(member.modifiers);
128
-		JavaSourceUtils.formatTypeParameters(scope, output, member.header.typeParameters);
129
-		output.append(scope.className);
130
-		formatParameters(member.header);
138
+		JavaSourceUtils.formatTypeParameters(scope.typeVisitor, output, member.header.typeParameters);
139
+		output.append(scope.cls.name);
140
+		formatParameters(member.isStatic(), member.header);
131 141
 		compileBody(member.body, member.header);
132 142
 		return null;
133 143
 	}
134 144
 
135 145
 	@Override
136 146
 	public Void visitDestructor(DestructorMember member) {
137
-		addSpacing();
147
+		begin(ElementType.METHOD);
138 148
 		
139 149
 		output.append(indent).append("@Override\n");
140 150
 		output.append(indent).append("public void close()");
@@ -144,123 +154,61 @@ public class JavaMemberCompiler implements MemberVisitor<Void> {
144 154
 
145 155
 	@Override
146 156
 	public Void visitMethod(MethodMember member) {
147
-		addSpacing();
148
-		
149
-		
150
-		output.append(indent);
151
-		if (isInterface && member.body != null && !(member.body instanceof EmptyStatement))
152
-			output.append("default ");
153
-		
154
-		modifiers(member.modifiers);
155
-		JavaSourceUtils.formatTypeParameters(scope, output, member.header.typeParameters);
156
-		output.append(member.header.returnType.accept(scope.typeVisitor));
157
-		output.append(" ");
158
-		output.append(member.name);
159
-		formatParameters(member.header);
160
-		compileBody(member.body, member.header);
157
+		compileMethod(member, member.header, member.body);
161 158
 		return null;
162 159
 	}
163 160
 
164 161
 	@Override
165 162
 	public Void visitGetter(GetterMember member) {
166
-		addSpacing();
167
-		
168
-		output.append(indent);
169
-		if (isInterface && member.body != null && !(member.body instanceof EmptyStatement))
170
-			output.append("default ");
171
-		
172
-		modifiers(member.modifiers);
173
-		output.append(scope.type(member.type));
174
-		output.append(" ");
175
-		output.append("get").append(StringUtils.capitalize(member.name));
176
-		output.append("()");
177
-		compileBody(member.body, member.header);
163
+		compileMethod(member, member.header, member.body);
178 164
 		return null;
179 165
 	}
180 166
 
181 167
 	@Override
182 168
 	public Void visitSetter(SetterMember member) {
183
-		addSpacing();
184
-		
185
-		output.append(indent);
186
-		if (isInterface && member.body != null && !(member.body instanceof EmptyStatement))
187
-			output.append("default ");
188
-		
189
-		modifiers(member.modifiers);
190
-		output.append("void set").append(StringUtils.capitalize(member.name));
191
-		output.append("(");
192
-		output.append(scope.type(member.type));
193
-		output.append(" ");
194
-		output.append("value");
195
-		output.append(")");
196
-		compileBody(member.body, member.header);
169
+		compileMethod(member, new FunctionHeader(BasicTypeID.VOID, new FunctionParameter(member.type, "value")), member.body);
197 170
 		return null;
198 171
 	}
199 172
 
200 173
 	@Override
201 174
 	public Void visitOperator(OperatorMember member) {
202
-		addSpacing();
203
-		JavaSourceMethod method = member.getTag(JavaSourceMethod.class);
204
-		if (method == null)
205
-			throw new IllegalStateException("Missing method tag!");
206
-		
207
-		output.append(indent);
208
-		if (isInterface && member.body != null && !(member.body instanceof EmptyStatement))
209
-			output.append("default ");
210
-		
211
-		modifiers(member.modifiers);
212
-		output.append(scope.type(member.header.returnType));
213
-		output.append(' ');
214
-		output.append(method.name);
215
-		formatParameters(member.header);
216
-		compileBody(member.body, member.header);
175
+		compileMethod(member, member.header, member.body);
217 176
 		return null;
218 177
 	}
219 178
 
220 179
 	@Override
221 180
 	public Void visitCaster(CasterMember member) {
222
-		addSpacing();
223
-		
224
-		output.append(indent);
225
-		if (isInterface && member.body != null && !(member.body instanceof EmptyStatement))
226
-			output.append("default ");
227
-		
228
-		modifiers(member.modifiers);
229
-		output.append(scope.type(member.toType));
230
-		output.append(" ");
231
-		output.append("to").append(member.toType.accept(new JavaSourceTypeNameVisitor()));
232
-		output.append("()");
233
-		compileBody(member.body, member.header);
181
+		compileMethod(member, new FunctionHeader(member.toType), member.body);
234 182
 		return null;
235 183
 	}
236 184
 
237 185
 	@Override
238 186
 	public Void visitCustomIterator(CustomIteratorMember member) {
239
-		addSpacing();
240
-		
187
+		compileMethod(member, new FunctionHeader(scope.semanticScope.getTypeRegistry().getIterator(member.getLoopVariableTypes())), member.body);
241 188
 		return null;
242 189
 	}
243 190
 
244 191
 	@Override
245 192
 	public Void visitCaller(CallerMember member) {
246
-		addSpacing();
247
-		
193
+		compileMethod(member, member.header, member.body);
248 194
 		return null;
249 195
 	}
250 196
 
251 197
 	@Override
252 198
 	public Void visitImplementation(ImplementationMember member) {
199
+		// TODO
253 200
 		return null;
254 201
 	}
255 202
 
256 203
 	@Override
257 204
 	public Void visitInnerDefinition(InnerDefinitionMember member) {
205
+		// TODO
258 206
 		return null;
259 207
 	}
260 208
 
261 209
 	@Override
262 210
 	public Void visitStaticInitializer(StaticInitializerMember member) {
263
-		addSpacing();
211
+		begin(ElementType.STATICINIT);
264 212
 		output.append(indent).append("static");
265 213
 		compileBody(member.body, new FunctionHeader(BasicTypeID.VOID));
266 214
 		return null;
@@ -275,64 +223,4 @@ public class JavaMemberCompiler implements MemberVisitor<Void> {
275 223
 				visitSetter(field.autoSetter);
276 224
 		}
277 225
 	}
278
-	
279
-	private void modifiers(int modifiers) {
280
-		if (Modifiers.isPublic(modifiers))
281
-			output.append("public ");
282
-		if (Modifiers.isProtected(modifiers))
283
-			output.append("protected ");
284
-		if (Modifiers.isPrivate(modifiers))
285
-			output.append("private ");
286
-		if (Modifiers.isStatic(modifiers))
287
-			output.append("static ");
288
-		if (Modifiers.isFinal(modifiers))
289
-			output.append("final ");
290
-	}
291
-	
292
-	private void compileBody(Statement body, FunctionHeader header) {
293
-		if (body == null || body instanceof EmptyStatement) {
294
-			output.append(";\n");
295
-		} else {
296
-			if (!(body instanceof BlockStatement))
297
-				body = new BlockStatement(body.position, Collections.singletonList(body));
298
-			
299
-			JavaSourceStatementScope scope = new JavaSourceStatementScope(this.scope, settings, header, indent + settings.indent, null, null, isExpansion);
300
-			body.accept(new JavaSourceStatementCompiler(scope, output, true, false));
301
-			output.append('\n');
302
-		}
303
-	}
304
-	
305
-	private void formatParameters(FunctionHeader header) {
306
-		output.append("(");
307
-		boolean first = true;
308
-		if (header.typeParameters != null) {
309
-			for (TypeParameter typeParameter : header.typeParameters) {
310
-				if (first)
311
-					first = false;
312
-				else
313
-					output.append(", ");
314
-
315
-				output.append("Class<")
316
-						.append(typeParameter.name)
317
-						.append(">")
318
-						.append(" ")
319
-						.append("typeOf")
320
-						.append(typeParameter.name);
321
-			}
322
-		}
323
-		
324
-		for (int i = 0; i < header.parameters.length; i++) {
325
-			if (first)
326
-				first = false;
327
-			else
328
-				output.append(", ");
329
-			
330
-			FunctionParameter parameter = header.parameters[i];
331
-			output.append(scope.type(parameter.type));
332
-			output.append(" ").append(parameter.name);
333
-			if (parameter.variadic)
334
-				output.append("...");
335
-		}
336
-		output.append(")");
337
-	}
338 226
 }

+ 24
- 12
JavaSourceCompiler/src/main/java/org/openzen/zenscript/javasource/JavaSourceCompiler.java View File

@@ -10,11 +10,12 @@ import java.util.HashMap;
10 10
 import java.util.Map;
11 11
 import org.openzen.zenscript.codemodel.HighLevelDefinition;
12 12
 import org.openzen.zenscript.codemodel.ScriptBlock;
13
-import org.openzen.zenscript.codemodel.definition.FunctionDefinition;
14 13
 import org.openzen.zenscript.codemodel.definition.ZSPackage;
15 14
 import org.openzen.zenscript.compiler.CompilationUnit;
16 15
 import org.openzen.zenscript.compiler.SemanticModule;
17 16
 import org.openzen.zenscript.compiler.ZenCodeCompiler;
17
+import org.openzen.zenscript.javasource.prepare.JavaSourcePrepareDefinitionVisitor;
18
+import org.openzen.zenscript.javasource.tags.JavaSourceClass;
18 19
 import org.openzen.zenscript.shared.SourceFile;
19 20
 
20 21
 /**
@@ -29,6 +30,8 @@ public class JavaSourceCompiler implements ZenCodeCompiler {
29 30
 	private final File directory;
30 31
 	private final Map<File, JavaSourceFile> sourceFiles = new HashMap<>();
31 32
 	
33
+	private final Map<String, Integer> classNameCounters = new HashMap<>();
34
+	
32 35
 	public JavaSourceCompiler(File directory, CompilationUnit compilationUnit) {
33 36
 		if (!directory.exists())
34 37
 			directory.mkdirs();
@@ -42,20 +45,17 @@ public class JavaSourceCompiler implements ZenCodeCompiler {
42 45
 	
43 46
 	@Override
44 47
 	public void addDefinition(HighLevelDefinition definition, SemanticModule module) {
45
-		File file = new File(getDirectory(definition.pkg), definition.name + ".java");
46
-		if (definition.name == null || definition instanceof FunctionDefinition) {
47
-			SourceFile source = definition.getTag(SourceFile.class);
48
-			if (source != null) {
49
-				int slash = Math.max(source.filename.lastIndexOf('/'), source.filename.lastIndexOf('\\'));
50
-				String filename = source.filename.substring(slash < 0 ? 0 : slash);
51
-				filename = filename.substring(0, filename.lastIndexOf('.'));
52
-				file = new File(getDirectory(definition.pkg), filename + ".java");
53
-			}
54
-		}
48
+		String filename = getFilename(definition);
49
+		JavaSourcePrepareDefinitionVisitor prepare = new JavaSourcePrepareDefinitionVisitor(filename);
50
+		JavaSourceClass cls = definition.accept(prepare);
51
+		if (cls.empty)
52
+			return;
55 53
 		
54
+		File file = new File(getDirectory(definition.pkg), cls.name + ".java");
55
+		System.out.println("Compiling " + definition.name + " as " + cls.fullName);
56 56
 		JavaSourceFile sourceFile = sourceFiles.get(file);
57 57
 		if (sourceFile == null)
58
-			sourceFiles.put(file, sourceFile = new JavaSourceFile(this, file, definition.pkg));
58
+			sourceFiles.put(file, sourceFile = new JavaSourceFile(this, file, cls, definition.pkg));
59 59
 		
60 60
 		sourceFile.add(definition, module);
61 61
 	}
@@ -89,4 +89,16 @@ public class JavaSourceCompiler implements ZenCodeCompiler {
89 89
 		File base = getDirectory(pkg.parent);
90 90
 		return new File(base, pkg.name.replace('.', '/'));
91 91
 	}
92
+	
93
+	private String getFilename(HighLevelDefinition definition) {
94
+		SourceFile source = definition.getTag(SourceFile.class);
95
+		if (source != null) {
96
+			int slash = Math.max(source.filename.lastIndexOf('/'), source.filename.lastIndexOf('\\'));
97
+			String filename = source.filename.substring(slash < 0 ? 0 : slash + 1);
98
+			filename = filename.substring(0, filename.lastIndexOf('.'));
99
+			return filename;
100
+		} else {
101
+			return definition.name == null ? "Expansion" : definition.name;
102
+		}
103
+	}
92 104
 }

+ 108
- 50
JavaSourceCompiler/src/main/java/org/openzen/zenscript/javasource/JavaSourceExpressionFormatter.java View File

@@ -80,6 +80,7 @@ import org.openzen.zenscript.codemodel.statement.VarStatement;
80 80
 import org.openzen.zenscript.codemodel.type.ArrayTypeID;
81 81
 import org.openzen.zenscript.codemodel.type.AssocTypeID;
82 82
 import org.openzen.zenscript.codemodel.type.BasicTypeID;
83
+import org.openzen.zenscript.codemodel.type.DefinitionTypeID;
83 84
 import org.openzen.zenscript.codemodel.type.GenericTypeID;
84 85
 import org.openzen.zenscript.codemodel.type.ITypeID;
85 86
 import org.openzen.zenscript.codemodel.type.member.BuiltinID;
@@ -100,8 +101,12 @@ import org.openzen.zenscript.shared.StringUtils;
100 101
  * @author Hoofdgebruiker
101 102
  */
102 103
 public class JavaSourceExpressionFormatter implements ExpressionVisitor<ExpressionString> {
103
-	private final JavaSourceStatementScope scope;
104
-	private final StatementFormattingTarget target;
104
+	private static final JavaSourceClass RESULT = new JavaSourceClass("stdlib", "Result");
105
+	private static final JavaSourceClass RESULT_OK = new JavaSourceClass("stdlib", "Result.Ok");
106
+	private static final JavaSourceClass RESULT_ERROR = new JavaSourceClass("stdlib", "Result.Error");
107
+	
108
+	public final JavaSourceStatementScope scope;
109
+	public final StatementFormattingTarget target;
105 110
 	
106 111
 	public JavaSourceExpressionFormatter(StatementFormattingTarget target, JavaSourceStatementScope scope) {
107 112
 		this.target = target;
@@ -168,7 +173,7 @@ public class JavaSourceExpressionFormatter implements ExpressionVisitor<Expressi
168 173
 		switch (method.kind) {
169 174
 			case EXPANSION: {
170 175
 				StringBuilder output = new StringBuilder();
171
-				output.append(scope.sourceClass(method.cls));
176
+				output.append(scope.type(method.cls));
172 177
 				output.append('.');
173 178
 				output.append(method.name);
174 179
 				FormattingUtils.formatExpansionCall(output, this.target, scope, target.accept(this), arguments);
@@ -197,7 +202,7 @@ public class JavaSourceExpressionFormatter implements ExpressionVisitor<Expressi
197 202
 			throw new IllegalStateException("No source method tag for " + expression.member.getCanonicalName() + "!");
198 203
 		
199 204
 		StringBuilder result = new StringBuilder();
200
-		result.append(scope.sourceClass(method.cls));
205
+		result.append(scope.type(method.cls));
201 206
 		result.append('.');
202 207
 		result.append(method.name);
203 208
 		FormattingUtils.formatCall(result, target, scope, expression.arguments);
@@ -488,11 +493,26 @@ public class JavaSourceExpressionFormatter implements ExpressionVisitor<Expressi
488 493
 		if (expression.constructor.getBuiltin() != null)
489 494
 			return visitBuiltinConstructor(expression);
490 495
 		
491
-		StringBuilder result = new StringBuilder();
492
-		result.append("new ");
493
-		result.append(scope.type(expression.type));
494
-		FormattingUtils.formatCall(result, target, scope, expression.arguments);
495
-		return new ExpressionString(result.toString(), JavaOperator.PRIMARY);
496
+		JavaSourceMethod method = expression.constructor.getTag(JavaSourceMethod.class);
497
+		switch (method.kind) {
498
+			case EXPANSION: {
499
+				StringBuilder output = new StringBuilder();
500
+				output.append(scope.type(method.cls));
501
+				output.append('.');
502
+				output.append(method.name);
503
+				FormattingUtils.formatCall(output, this.target, scope, expression.arguments);
504
+				return new ExpressionString(output.toString(), JavaOperator.CALL);
505
+			}
506
+			case CONSTRUCTOR: {
507
+				StringBuilder output = new StringBuilder();
508
+				output.append("new ");
509
+				output.append(scope.type(expression.type, method.cls));
510
+				FormattingUtils.formatCall(output, this.target, scope, expression.arguments);
511
+				return new ExpressionString(output.toString(), JavaOperator.PRIMARY);
512
+			}
513
+			default:
514
+				throw new IllegalStateException("Invalid method call kind: " + method.kind);
515
+		}
496 516
 	}
497 517
 
498 518
 	@Override
@@ -559,10 +579,15 @@ public class JavaSourceExpressionFormatter implements ExpressionVisitor<Expressi
559 579
 		JavaSourceField field = expression.field.getTag(JavaSourceField.class);
560 580
 		if (field == null)
561 581
 			throw new CompileException(expression.position, CompileExceptionCode.INTERNAL_ERROR, "Missing field tag");
562
-		
563
-		return new ExpressionString(
564
-				scope.type(field.cls) + "." + field.name + " = " + expression.value.accept(this).value,
565
-				JavaOperator.ASSIGN);
582
+		if (field.cls.fullName.equals(scope.fileScope.cls.fullName) && !scope.hasLocalVariable(field.name)) {
583
+			return new ExpressionString(
584
+					field.name + " = " + expression.value.accept(this).value,
585
+					JavaOperator.ASSIGN);
586
+		} else {
587
+			return new ExpressionString(
588
+					scope.type(field.cls) + "." + field.name + " = " + expression.value.accept(this).value,
589
+					JavaOperator.ASSIGN);
590
+		}
566 591
 	}
567 592
 
568 593
 	@Override
@@ -613,23 +638,33 @@ public class JavaSourceExpressionFormatter implements ExpressionVisitor<Expressi
613 638
 
614 639
 	@Override
615 640
 	public ExpressionString visitTryRethrowAsException(TryRethrowAsExceptionExpression expression) {
641
+		DefinitionTypeID type = (DefinitionTypeID) expression.value.type;
642
+		
643
+		String errorType = scope.fileScope.importer.importType(RESULT_ERROR);
644
+		String okType = scope.fileScope.importer.importType(RESULT_OK);
645
+		
616 646
 		ExpressionString value = hoist(expression.value).accept(this);
617
-		target.writeLine("if (" + value.value + " instanceof " + scope.fileScope.importer.importType("stdlib.Result.Error") + ")");
618
-		target.writeLine(scope.settings.indent + "throw (" + scope.fileScope.importer.importType("stdlib.Result.Error") + ")" + value.value + ".value;");
647
+		target.writeLine("if (" + value.value + " instanceof " + errorType + ")");
648
+		target.writeLine(scope.settings.indent + "throw ((" + errorType + formatTypeArguments(type.typeParameters) + ")" + value.value + ").value;");
619 649
 		
620 650
 		return value
621
-				.unaryPrefix(JavaOperator.CAST, "(" + scope.fileScope.importer.importType("stdlib.Result.Ok") + ")")
651
+				.unaryPrefix(JavaOperator.CAST, "(" + okType + formatTypeArguments(type.typeParameters) + ")")
622 652
 				.unaryPostfix(JavaOperator.MEMBER, ".value");
623 653
 	}
624 654
 
625 655
 	@Override
626 656
 	public ExpressionString visitTryRethrowAsResult(TryRethrowAsResultExpression expression) {
657
+		DefinitionTypeID type = (DefinitionTypeID) expression.value.type;
658
+		
659
+		String errorType = scope.fileScope.importer.importType(RESULT_ERROR);
660
+		String okType = scope.fileScope.importer.importType(RESULT_OK);
661
+		
627 662
 		ExpressionString value = hoist(expression.value).accept(this);
628
-		target.writeLine("if (" + value.value + " instanceof " + scope.fileScope.importer.importType("stdlib.Result.Error") + ")");
629
-		target.writeLine(scope.settings.indent + "return new " + scope.fileScope.importer.importType("stdlib.Result.Error") + "<>((" + scope.fileScope.importer.importType("stdlib.Result.Error") + ")" + value.value + ".value);");
663
+		target.writeLine("if (" + value.value + " instanceof " + errorType + ")");
664
+		target.writeLine(scope.settings.indent + "return new " + errorType + "<>(((" + errorType + formatTypeArguments(type.typeParameters) + ")" + value.value + ").value);");
630 665
 		
631 666
 		return value
632
-				.unaryPrefix(JavaOperator.CAST, "(" + scope.fileScope.importer.importType("stdlib.Result.Ok") + ")")
667
+				.unaryPrefix(JavaOperator.CAST, "(" + okType + formatTypeArguments(type.typeParameters) + ")")
633 668
 				.unaryPostfix(JavaOperator.MEMBER, ".value");
634 669
 	}
635 670
 	
@@ -648,12 +683,40 @@ public class JavaSourceExpressionFormatter implements ExpressionVisitor<Expressi
648 683
 		return expression.value.accept(this);
649 684
 	}
650 685
 	
686
+	private String formatTypeArguments(ITypeID[] types) {
687
+		if (types == null || types.length == 0)
688
+			return "";
689
+		
690
+		StringBuilder output = new StringBuilder();
691
+		output.append("<");
692
+		
693
+		for (int i = 0; i < types.length; i++) {
694
+			if (i > 0)
695
+				output.append(", ");
696
+			
697
+			output.append(types[i].accept(scope.fileScope.objectTypeVisitor));
698
+		}
699
+		output.append(">");
700
+		return output.toString();
701
+	}
702
+	
703
+	public ExpressionString newArray(ITypeID elementType, ExpressionString length) {
704
+		if (elementType instanceof GenericTypeID) {
705
+			// generic array creation
706
+			GenericTypeID generic = (GenericTypeID)elementType;
707
+			String array = scope.type(new JavaSourceClass("java.lang.reflect", "Array"));
708
+			return new ExpressionString("(" + generic.parameter.name + "[])(" + array + ".newInstance(typeOf" + generic.parameter.name + ", " + length.value + "))", JavaOperator.CAST);
709
+		} else {
710
+			return new ExpressionString("new " + scope.type(elementType) + "[" + length.value + "]", JavaOperator.NEW);
711
+		}
712
+	}
713
+	
651 714
 	public ExpressionString listToArray(CastExpression expression) {
652 715
 		Expression target = duplicable(expression.target);
653 716
 		ExpressionString targetString = target.accept(this);
654 717
 		ArrayTypeID resultType = (ArrayTypeID)expression.type;
655 718
 		return new ExpressionString(
656
-				targetString.value + ".toArray(new " + scope.type(resultType.elementType) + "[" + targetString.value + ".size()])",
719
+				targetString.value + ".toArray(" + newArray(resultType.elementType, targetString.unaryPostfix(JavaOperator.CALL, ".size()")).value + ")",
657 720
 				JavaOperator.CALL);
658 721
 	}
659 722
 	
@@ -829,7 +892,7 @@ public class JavaSourceExpressionFormatter implements ExpressionVisitor<Expressi
829 892
 		return cast.isImplicit ? cast.target.accept(this) : cast(cast, type);
830 893
 	}
831 894
 	
832
-	private Expression duplicable(Expression expression) {
895
+	public Expression duplicable(Expression expression) {
833 896
 		boolean shouldHoist = expression.accept(ExpressionHoistingChecker.INSTANCE);
834 897
 		if (!shouldHoist)
835 898
 			return expression;
@@ -843,7 +906,7 @@ public class JavaSourceExpressionFormatter implements ExpressionVisitor<Expressi
843 906
 		return new GetLocalVariableExpression(value.position, temp);
844 907
 	}
845 908
 	
846
-	private ExpressionString hoist(ExpressionString value, String type) {
909
+	public ExpressionString hoist(ExpressionString value, String type) {
847 910
 		String temp = scope.createTempVariable();
848 911
 		target.writeLine(type + " " + temp + " = " + value.value + ";");
849 912
 		return new ExpressionString(temp, JavaOperator.PRIMARY);
@@ -1014,6 +1077,7 @@ public class JavaSourceExpressionFormatter implements ExpressionVisitor<Expressi
1014 1077
 			case GENERICMAP_GETOPTIONAL: return call("get", call).unaryPrefix(JavaOperator.CAST, "(" + scope.type(call.type) + ")");
1015 1078
 			case GENERICMAP_PUT: return call("put", call);
1016 1079
 			case GENERICMAP_CONTAINS: return call("containsKey", call);
1080
+			case GENERICMAP_ADDALL: return call("putAll", call);
1017 1081
 			case GENERICMAP_EQUALS: throw new UnsupportedOperationException("Not yet supported!");
1018 1082
 			case GENERICMAP_NOTEQUALS: throw new UnsupportedOperationException("Not yet supported!");
1019 1083
 			case GENERICMAP_SAME: return binary(call, JavaOperator.EQUALS);
@@ -1038,7 +1102,7 @@ public class JavaSourceExpressionFormatter implements ExpressionVisitor<Expressi
1038 1102
 			}
1039 1103
 			case ARRAY_CONTAINS: {
1040 1104
 				JavaSourceMethod method = scope.fileScope.helperGenerator.createArrayContains((ArrayTypeID)call.target.type);
1041
-				return callAsStatic(scope.fileScope.importer.importType(method.cls.fullName) + '.' + method.name, call);
1105
+				return callAsStatic(scope.fileScope.importer.importType(method.cls) + '.' + method.name, call);
1042 1106
 			}
1043 1107
 			case ARRAY_EQUALS: return callAsStatic("Arrays.equals", call);
1044 1108
 			case ARRAY_NOTEQUALS: return callAsStatic("!Arrays.equals", call);
@@ -1062,6 +1126,8 @@ public class JavaSourceExpressionFormatter implements ExpressionVisitor<Expressi
1062 1126
 			case FUNCTION_NOTSAME: return binary(call, JavaOperator.NOTEQUALS);
1063 1127
 			case OBJECT_SAME: return binary(call, JavaOperator.EQUALS);
1064 1128
 			case OBJECT_NOTSAME: return binary(call, JavaOperator.NOTEQUALS);
1129
+			case OPTIONAL_IS_NULL: return call.target.accept(this).unaryPostfix(JavaOperator.EQUALS, " == null");
1130
+			case OPTIONAL_IS_NOT_NULL: return call.target.accept(this).unaryPostfix(JavaOperator.NOTEQUALS, " != null");
1065 1131
 			case AUTOOP_NOTEQUALS:
1066 1132
 				throw new UnsupportedOperationException("Not yet supported!");
1067 1133
 		}
@@ -1377,19 +1443,19 @@ public class JavaSourceExpressionFormatter implements ExpressionVisitor<Expressi
1377 1443
 			case STRING_CONSTRUCTOR_CHARACTERS:
1378 1444
 				return callStatic("new String", expression.arguments.arguments[0]);
1379 1445
 			case ASSOC_CONSTRUCTOR: {
1380
-				String typeName = scope.type(new JavaSourceClass("HashMap", "java.util.HashMap"));
1446
+				String typeName = scope.type(new JavaSourceClass("java.util", "HashMap"));
1381 1447
 				AssocTypeID type = (AssocTypeID) expression.type;
1382 1448
 				
1383 1449
 				StringBuilder result = new StringBuilder();
1384 1450
 				result.append("new ").append(typeName).append("<");
1385
-				result.append(scope.type(type.keyType));
1386
-				result.append(", ");
1387
-				result.append(scope.type(type.valueType));
1451
+				//result.append(scope.type(type.keyType));
1452
+				//result.append(", ");
1453
+				//result.append(scope.type(type.valueType));
1388 1454
 				result.append(">()");
1389 1455
 				return new ExpressionString(result.toString(), JavaOperator.NEW);
1390 1456
 			}
1391 1457
 			case GENERICMAP_CONSTRUCTOR: {
1392
-				String typeName = scope.type(new JavaSourceClass("HashMap", "java.util.HashMap"));
1458
+				String typeName = scope.type(new JavaSourceClass("java.util", "HashMap"));
1393 1459
 				StringBuilder result = new StringBuilder();
1394 1460
 				result.append("new ").append(typeName).append("<Class<?>, Object>()");
1395 1461
 				return new ExpressionString(result.toString(), JavaOperator.NEW);
@@ -1398,8 +1464,7 @@ public class JavaSourceExpressionFormatter implements ExpressionVisitor<Expressi
1398 1464
 				ArrayTypeID type = (ArrayTypeID) expression.type;
1399 1465
 				if (type.dimension == 1) {
1400 1466
 					ExpressionString size = expression.arguments.arguments[0].accept(this);
1401
-					String typeName = scope.type(type.elementType);
1402
-					return new ExpressionString("new " + typeName + "[" + size.value + "]", JavaOperator.NEW);
1467
+					return newArray(type.elementType, size);
1403 1468
 				} else {
1404 1469
 					// TODO: implement
1405 1470
 					throw new UnsupportedOperationException("Not yet supported!");
@@ -1418,11 +1483,8 @@ public class JavaSourceExpressionFormatter implements ExpressionVisitor<Expressi
1418 1483
 							.append(' ')
1419 1484
 							.append(temp)
1420 1485
 							.append(" = ")
1421
-							.append(" new ")
1422
-							.append(scope.type(type.elementType))
1423
-							.append("[")
1424
-							.append(size.value)
1425
-							.append("];")
1486
+							.append(newArray(type.elementType, size).value)
1487
+							.append(";")
1426 1488
 							.toString());
1427 1489
 					target.writeLine(new StringBuilder()
1428 1490
 							.append("for (int ")
@@ -1465,11 +1527,9 @@ public class JavaSourceExpressionFormatter implements ExpressionVisitor<Expressi
1465 1527
 								.append(scope.type(type))
1466 1528
 								.append(' ')
1467 1529
 								.append(temp)
1468
-								.append(" = new ")
1469
-								.append(scope.type(type.elementType))
1470
-								.append("[")
1471
-								.append(size.value)
1472
-								.append("];")
1530
+								.append(" = ")
1531
+								.append(newArray(type.elementType, size))
1532
+								.append(";")
1473 1533
 								.toString());
1474 1534
 					VarStatement tempI = new VarStatement(expression.position, scope.createTempVariable(), BasicTypeID.INT, null, true);
1475 1535
 					target.writeLine(new StringBuilder()
@@ -1537,11 +1597,9 @@ public class JavaSourceExpressionFormatter implements ExpressionVisitor<Expressi
1537 1597
 							.append(scope.type(type))
1538 1598
 							.append(' ')
1539 1599
 							.append(temp)
1540
-							.append(" = new ")
1541
-							.append(scope.type(type.elementType))
1542
-							.append("[")
1543
-							.append(originalString.value)
1544
-							.append(".length];")
1600
+							.append(" = ")
1601
+							.append(newArray(type.elementType, originalString.unaryPostfix(JavaOperator.MEMBER, ".length")))
1602
+							.append(";")
1545 1603
 							.toString());
1546 1604
 					VarStatement tempI = new VarStatement(expression.position, scope.createTempVariable(), BasicTypeID.INT, null, true);
1547 1605
 					target.writeLine(new StringBuilder()
@@ -1615,11 +1673,9 @@ public class JavaSourceExpressionFormatter implements ExpressionVisitor<Expressi
1615 1673
 							.append(scope.type(type))
1616 1674
 							.append(' ')
1617 1675
 							.append(temp)
1618
-							.append(" = new ")
1619
-							.append(scope.type(type.elementType))
1620
-							.append("[")
1621
-							.append(originalString.value)
1622
-							.append(".length];")
1676
+							.append(" = ")
1677
+							.append(newArray(type.elementType, originalString.unaryPostfix(JavaOperator.MEMBER, ".length")))
1678
+							.append(";")
1623 1679
 							.toString());
1624 1680
 					VarStatement tempI = new VarStatement(expression.position, scope.createTempVariable(), BasicTypeID.INT, null, true);
1625 1681
 					target.writeLine(new StringBuilder()
@@ -1666,6 +1722,8 @@ public class JavaSourceExpressionFormatter implements ExpressionVisitor<Expressi
1666 1722
 								.append("] = ")
1667 1723
 								.append(lambdaString.value)
1668 1724
 								.append(".invoke(")
1725
+								.append(tempI.name)
1726
+								.append(", ")
1669 1727
 								.append(originalString.value)
1670 1728
 								.append("[")
1671 1729
 								.append(tempI.name)

+ 38
- 30
JavaSourceCompiler/src/main/java/org/openzen/zenscript/javasource/JavaSourceFile.java View File

@@ -12,68 +12,76 @@ import java.io.IOException;
12 12
 import java.io.OutputStreamWriter;
13 13
 import java.io.Writer;
14 14
 import java.nio.charset.StandardCharsets;
15
+import java.util.ArrayList;
15 16
 import java.util.HashMap;
16 17
 import java.util.HashSet;
18
+import java.util.List;
17 19
 import java.util.Map;
18 20
 import java.util.Set;
19 21
 import org.openzen.zenscript.codemodel.HighLevelDefinition;
20
-import org.openzen.zenscript.codemodel.definition.InterfaceDefinition;
22
+import org.openzen.zenscript.codemodel.definition.ExpansionDefinition;
21 23
 import org.openzen.zenscript.codemodel.definition.ZSPackage;
22
-import org.openzen.zenscript.compiler.CompileScope;
23 24
 import org.openzen.zenscript.compiler.SemanticModule;
24
-import org.openzen.zenscript.javasource.prepare.JavaSourcePrepareDefinitionVisitor;
25
-import org.openzen.zenscript.javasource.scope.JavaSourceFileScope;
25
+import org.openzen.zenscript.javasource.tags.JavaSourceClass;
26 26
 
27 27
 /**
28 28
  *
29 29
  * @author Hoofdgebruiker
30 30
  */
31 31
 public class JavaSourceFile {
32
-	private final JavaSourceImporter importer;
32
+	public final JavaSourceImporter importer;
33 33
 	private final JavaSourceCompiler compiler;
34 34
 	private final File file;
35
+	private final JavaSourceClass cls;
35 36
 	private final StringBuilder contents = new StringBuilder();
36 37
 	private final ZSPackage pkg;
37 38
 	
38
-	private final Map<HighLevelDefinition, SemanticModule> definitions = new HashMap<>();
39
+	private HighLevelDefinition mainDefinition;
40
+	private final List<ExpansionDefinition> expansions = new ArrayList<>();
41
+	
42
+	private final Map<HighLevelDefinition, SemanticModule> modules = new HashMap<>();
39 43
 	private final Set<String> existing = new HashSet<>();
40 44
 	
41
-	public JavaSourceFile(JavaSourceCompiler compiler, File file, ZSPackage pkg) {
45
+	public JavaSourceFile(JavaSourceCompiler compiler, File file, JavaSourceClass cls, ZSPackage pkg) {
42 46
 		this.compiler = compiler;
43 47
 		this.pkg = pkg;
48
+		this.cls = cls;
44 49
 		this.file = file;
45 50
 		
46
-		importer = new JavaSourceImporter(pkg);
51
+		importer = new JavaSourceImporter(cls);
47 52
 	}
48 53
 	
49 54
 	public String getName() {
50
-		return file.getName().substring(0, file.getName().lastIndexOf('.'));
55
+		return cls.name;
51 56
 	}
52 57
 	
53 58
 	public void add(HighLevelDefinition definition, SemanticModule module) {
54
-		if (existing.contains(definition.name))
55
-			throw new IllegalStateException("Duplicate " + definition.name);
56
-		
57
-		System.out.println("adding " + definition.name + " to " + file.getName());
59
+		if (definition instanceof ExpansionDefinition) {
60
+			expansions.add((ExpansionDefinition)definition);
61
+		} else if (mainDefinition != null) {
62
+			throw new IllegalStateException("Multiple main definitions!");
63
+		} else {
64
+			mainDefinition = definition;
65
+		}
58 66
 		
59
-		JavaSourcePrepareDefinitionVisitor prepare = new JavaSourcePrepareDefinitionVisitor(this);
60
-		definition.accept(prepare);
61
-		definitions.put(definition, module);
67
+		modules.put(definition, module);
62 68
 	}
63 69
 	
64 70
 	public void write() {
65 71
 		System.out.println("Calling write on " + file.getName());
66 72
 		
67
-		for (Map.Entry<HighLevelDefinition, SemanticModule> entry : definitions.entrySet()) {
68
-			HighLevelDefinition definition = entry.getKey();
69
-			SemanticModule module = entry.getValue();
70
-			CompileScope scope = new CompileScope(definition.access, module.compilationUnit.globalTypeRegistry, module.expansions, module.annotations);
71
-			JavaDefinitionVisitor visitor = new JavaDefinitionVisitor(
72
-					compiler.settings,
73
-					new JavaSourceFileScope(importer, compiler.typeGenerator, compiler.helperGenerator, getName(), scope, definition instanceof InterfaceDefinition),
74
-					contents);
75
-			definition.accept(visitor);
76
-		}
73
+		if (mainDefinition == null)
74
+			mainDefinition = expansions.remove(0);
75
+		
76
+		HighLevelDefinition definition = mainDefinition;
77
+		JavaDefinitionVisitor visitor = new JavaDefinitionVisitor(
78
+				compiler,
79
+				cls,
80
+				this,
81
+				contents,
82
+				expansions,
83
+				modules);
84
+		definition.accept(visitor);
77 85
 		
78 86
 		if (!file.getParentFile().exists())
79 87
 			file.getParentFile().mkdirs();
@@ -83,14 +91,14 @@ public class JavaSourceFile {
83 91
 			writer.write(pkg.fullName);
84 92
 			writer.write(";\n\n");
85 93
 			
86
-			JavaSourceImporter.Import[] imports = importer.getUsedImports();
94
+			JavaSourceClass[] imports = importer.getUsedImports();
87 95
 			if (imports.length > 0) {
88
-				for (JavaSourceImporter.Import import_ : imports) {
89
-					if (import_.actualName.startsWith("java.lang."))
96
+				for (JavaSourceClass import_ : imports) {
97
+					if (import_.pkg.equals("java.lang"))
90 98
 						continue;
91 99
 					
92 100
 					writer.write("import ");
93
-					writer.write(import_.actualName);
101
+					writer.write(import_.fullName);
94 102
 					writer.write(";\n");
95 103
 				}
96 104
 

+ 21
- 39
JavaSourceCompiler/src/main/java/org/openzen/zenscript/javasource/JavaSourceImporter.java View File

@@ -11,64 +11,46 @@ import java.util.HashSet;
11 11
 import java.util.Map;
12 12
 import java.util.Set;
13 13
 import org.openzen.zenscript.codemodel.HighLevelDefinition;
14
-import org.openzen.zenscript.codemodel.definition.ZSPackage;
14
+import org.openzen.zenscript.javasource.tags.JavaSourceClass;
15 15
 
16 16
 /**
17 17
  *
18 18
  * @author Hoofdgebruiker
19 19
  */
20 20
 public class JavaSourceImporter {
21
-	private final ZSPackage pkg;
22
-	private final Map<String, Import> imports = new HashMap<>();
23
-	private final Set<Import> usedImports = new HashSet<>();
21
+	private final JavaSourceClass cls;
22
+	private final Map<String, JavaSourceClass> imports = new HashMap<>();
23
+	private final Set<JavaSourceClass> usedImports = new HashSet<>();
24 24
 	
25
-	public JavaSourceImporter(ZSPackage pkg) {
26
-		this.pkg = pkg;
27
-		
28
-		imports.put("IllegalArgumentException", new Import("IllegalArgumentException", "stdlib.IllegalArgumentException", "java.lang.IllegalArgumentException"));
29
-		imports.put("StringBuilder", new Import("StringBuilder", "stdlib.StringBuilder", "java.lang.StringBuilder"));
25
+	public JavaSourceImporter(JavaSourceClass cls) {
26
+		this.cls = cls;
30 27
 	}
31 28
 	
32 29
 	public String importType(HighLevelDefinition definition) {
33
-		if (definition.pkg == pkg)
34
-			return definition.name;
30
+		JavaSourceClass cls = definition.getTag(JavaSourceClass.class);
31
+		if (cls == null)
32
+			throw new IllegalStateException("Missing source class tag on " + definition.name);
33
+		if (cls.pkg.equals(this.cls.pkg))
34
+			return cls.name;
35 35
 		
36
-		return importType(definition.pkg.fullName + "." + definition.name);
36
+		return importType(cls);
37 37
 	}
38 38
 	
39
-	public String importType(String fullName) {
40
-		String name = fullName.substring(fullName.lastIndexOf('.') + 1);
41
-		if (imports.containsKey(name)) {
42
-			Import imported = imports.get(name);
39
+	public String importType(JavaSourceClass cls) {
40
+		if (imports.containsKey(cls.name)) {
41
+			JavaSourceClass imported = imports.get(cls.name);
43 42
 			usedImports.add(imported);
44
-			return imported.originalName.equals(fullName) ? name : fullName;
43
+			return imported.fullName.equals(cls.fullName) ? cls.name : cls.fullName;
45 44
 		}
46 45
 		
47
-		Import imported = new Import(name, fullName, fullName);
48
-		imports.put(name, imported);
49
-		return name;
46
+		imports.put(cls.name, cls);
47
+		usedImports.add(cls);
48
+		return cls.name;
50 49
 	}
51 50
 	
52
-	public Import[] getUsedImports() {
53
-		Import[] imports = usedImports.toArray(new Import[usedImports.size()]);
51
+	public JavaSourceClass[] getUsedImports() {
52
+		JavaSourceClass[] imports = usedImports.toArray(new JavaSourceClass[usedImports.size()]);
54 53
 		Arrays.sort(imports);
55 54
 		return imports;
56 55
 	}
57
-	
58
-	public static class Import implements Comparable<Import> {
59
-		public final String name;
60
-		public final String originalName;
61
-		public final String actualName;
62
-		
63
-		public Import(String name, String originalName, String actualName) {
64
-			this.name = name;
65
-			this.originalName = originalName;
66
-			this.actualName = actualName;
67
-		}
68
-
69
-		@Override
70
-		public int compareTo(Import o) {
71
-			return actualName.compareTo(o.actualName);
72
-		}
73
-	}
74 56
 }

+ 44
- 36
JavaSourceCompiler/src/main/java/org/openzen/zenscript/javasource/JavaSourceStatementFormatter.java View File

@@ -9,12 +9,8 @@ import java.util.ArrayList;
9 9
 import java.util.Collections;
10 10
 import java.util.List;
11 11
 import org.openzen.zenscript.codemodel.HighLevelDefinition;
12
-import org.openzen.zenscript.codemodel.OperatorType;
13
-import org.openzen.zenscript.codemodel.expression.CallArguments;
14 12
 import org.openzen.zenscript.codemodel.expression.Expression;
15
-import org.openzen.zenscript.codemodel.expression.GetLocalVariableExpression;
16 13
 import org.openzen.zenscript.codemodel.expression.RangeExpression;
17
-import org.openzen.zenscript.codemodel.expression.SetLocalVariableExpression;
18 14
 import org.openzen.zenscript.codemodel.expression.switchvalue.CharSwitchValue;
19 15
 import org.openzen.zenscript.codemodel.expression.switchvalue.EnumConstantSwitchValue;
20 16
 import org.openzen.zenscript.codemodel.expression.switchvalue.IntSwitchValue;
@@ -32,8 +28,8 @@ import org.openzen.zenscript.codemodel.statement.ExpressionStatement;
32 28
 import org.openzen.zenscript.codemodel.statement.ForeachStatement;
33 29
 import org.openzen.zenscript.codemodel.statement.IfStatement;
34 30
 import org.openzen.zenscript.codemodel.statement.LockStatement;
31
+import org.openzen.zenscript.codemodel.statement.LoopStatement;
35 32
 import org.openzen.zenscript.codemodel.statement.ReturnStatement;
36
-import org.openzen.zenscript.codemodel.statement.Statement;
37 33
 import org.openzen.zenscript.codemodel.statement.SwitchCase;
38 34
 import org.openzen.zenscript.codemodel.statement.SwitchStatement;
39 35
 import org.openzen.zenscript.codemodel.statement.ThrowStatement;
@@ -41,7 +37,6 @@ import org.openzen.zenscript.codemodel.statement.TryCatchStatement;
41 37
 import org.openzen.zenscript.codemodel.statement.VarStatement;
42 38
 import org.openzen.zenscript.codemodel.statement.WhileStatement;
43 39
 import org.openzen.zenscript.codemodel.type.DefinitionTypeID;
44
-import org.openzen.zenscript.codemodel.type.member.TypeMembers;
45 40
 import org.openzen.zenscript.formattershared.ExpressionString;
46 41
 import org.openzen.zenscript.formattershared.StatementFormatter;
47 42
 import org.openzen.zenscript.formattershared.StatementFormattingSubBlock;
@@ -60,6 +55,11 @@ public class JavaSourceStatementFormatter implements StatementFormatter.Formatte
60 55
 	public JavaSourceStatementFormatter(JavaSourceStatementScope scope) {
61 56
 		this.scope = scope;
62 57
 	}
58
+	
59
+	@Override
60
+	public JavaSourceStatementFormatter forLoop(LoopStatement statement) {
61
+		return new JavaSourceStatementFormatter(scope.createBlockScope(statement));
62
+	}
63 63
 
64 64
 	@Override
65 65
 	public void formatBlock(StatementFormattingTarget target, BlockStatement statement) {
@@ -68,7 +68,7 @@ public class JavaSourceStatementFormatter implements StatementFormatter.Formatte
68 68
 
69 69
 	@Override
70 70
 	public void formatBreak(StatementFormattingTarget target, BreakStatement statement) {
71
-		if (target.getInnerLoop() == statement.target)
71
+		if (scope.innerLoop == statement.target)
72 72
 			target.writeLine("break;");
73 73
 		else
74 74
 			target.writeLine("break " + statement.target.label + ";");
@@ -76,7 +76,7 @@ public class JavaSourceStatementFormatter implements StatementFormatter.Formatte
76 76
 
77 77
 	@Override
78 78
 	public void formatContinue(StatementFormattingTarget target, ContinueStatement statement) {
79
-		if (target.getInnerLoop() == statement.target)
79
+		if (scope.innerLoop == statement.target)
80 80
 			target.writeLine("continue;");
81 81
 		else
82 82
 			target.writeLine("continue " + statement.target.label + ";");
@@ -133,7 +133,6 @@ public class JavaSourceStatementFormatter implements StatementFormatter.Formatte
133 133
 			DefinitionTypeID variantType = (DefinitionTypeID)statement.value.type;
134 134
 			HighLevelDefinition variant = variantType.definition;
135 135
 			String variantTypeName = scope.type(variant.getTag(JavaSourceClass.class));
136
-			JavaSourceStatementScope innerScope = scope.createBlockScope(statement);
137 136
 			for (SwitchCase switchCase : statement.cases) {
138 137
 				VariantOptionSwitchValue switchValue = (VariantOptionSwitchValue)switchCase.value;
139 138
 				String header = switchValue == null ? "default:" : "case " + switchValue.option.getName() + ":";
@@ -276,35 +275,16 @@ public class JavaSourceStatementFormatter implements StatementFormatter.Formatte
276 275
 
277 276
 		@Override
278 277
 		public Void visitArrayKeyValueIterator() {
279
-			Statement content = statement.content;
280
-			
281
-			Expression list = scope.duplicable(target, statement.list);
282
-			
283
-			List<Statement> modifiedContent = new ArrayList<>();
284
-			TypeMembers arrayMembers = scope.fileScope.semanticScope.getTypeMembers(statement.list.type);
285
-			
286
-			Expression getElement = arrayMembers
287
-							.getOrCreateGroup(OperatorType.INDEXGET)
288
-							.call(statement.position,
289
-									scope.fileScope.semanticScope,
290
-									list,
291
-									new CallArguments(new GetLocalVariableExpression(statement.position, statement.loopVariables[0])), true);
292
-			Expression setLocal = new SetLocalVariableExpression(statement.position, statement.loopVariables[1], getElement);
293
-			
294
-			modifiedContent.add(new ExpressionStatement(
295
-					statement.position,
296
-					setLocal));
297
-			if (content instanceof BlockStatement) {
298
-				modifiedContent.addAll(((BlockStatement) content).statements);
299
-			} else {
300
-				modifiedContent.add(content);
301
-			}
278
+			ExpressionString list = scope.expression(target, scope.duplicable(target, statement.list));
302 279
 			
303 280
 			target.writeInner(
304
-					"for (" + scope.type(statement.loopVariables[0].type) + " " + statement.loopVariables[0].name + " : " + scope.expression(target, list) + ")",
305
-					new BlockStatement(statement.position, modifiedContent),
281
+					"for (int " + statement.loopVariables[0].name + " = 0; i < " + list.value + ".length; i++) {",
282
+					new String[] {
283
+						scope.type(statement.loopVariables[1].type) + " " + statement.loopVariables[1].name + " = " + list.value + "[" + statement.loopVariables[0].name + "];"
284
+					},
285
+					statement.content,
306 286
 					statement,
307
-					"");
287
+					"}");
308 288
 			
309 289
 			return null;
310 290
 		}
@@ -317,11 +297,39 @@ public class JavaSourceStatementFormatter implements StatementFormatter.Formatte
317 297
 		@Override
318 298
 		public Void visitStringCharacterIterator() {
319 299
 			target.writeInner(
320
-					"for (char " + statement.loopVariables[0].name + " : " + scope.expression(target, statement.list) + ".toCharArray())",
300
+					"for (char " + statement.loopVariables[0].name + " : " + scope.expression(target, statement.list).value + ".toCharArray())",
301
+					statement.content,
302
+					statement,
303
+					"");
304
+			return null;
305
+		}
306
+
307
+		@Override
308
+		public Void visitAssocKeyIterator() {
309
+			VarStatement key = statement.loopVariables[0];
310
+			target.writeInner(
311
+					"for (" + scope.type(key.type) + " " + key + " : " + scope.expression(target, statement.list).value + ".keySet())",
321 312
 					statement.content,
322 313
 					statement,
323 314
 					"");
324 315
 			return null;
325 316
 		}
317
+
318
+		@Override
319
+		public Void visitAssocKeyValueIterator() {
320
+			String temp = scope.createTempVariable();
321
+			VarStatement key = statement.loopVariables[0];
322
+			VarStatement value = statement.loopVariables[1];
323
+			target.writeInner(
324
+					"for (Map.Entry<" + scope.type(key.type) + ", " + scope.type(value.type) + "> " + temp + " : " + scope.expression(target, statement.list).value + ".entrySet()) {",
325
+					new String[] {
326
+						scope.type(key.type) + " " + key.name + " = " + temp + ".getKey();",
327
+						scope.type(value.type) + " " + value.name + " = " + temp + ".getValue();"
328
+					},
329
+					statement.content,
330
+					statement,
331
+					"}");
332
+			return null;
333
+		}
326 334
 	}
327 335
 }

+ 3
- 3
JavaSourceCompiler/src/main/java/org/openzen/zenscript/javasource/JavaSourceSyntheticHelperGenerator.java View File

@@ -39,7 +39,7 @@ public class JavaSourceSyntheticHelperGenerator {
39 39
 	private final File directory;
40 40
 	private final JavaSourceFormattingSettings settings;
41 41
 	private final Map<String, List<String>> members = new HashMap<>();
42
-	private final JavaSourceClass arrayHelpers = new JavaSourceClass("ArrayHelpers", "zsynthetic.ArrayHelpers");
42
+	private final JavaSourceClass arrayHelpers = new JavaSourceClass("zsynthetic", "ArrayHelpers");
43 43
 	private final Map<ArrayKind, JavaSourceMethod> existingContains = new HashMap<>();
44 44
 	private final Map<ArrayKind, JavaSourceMethod> existingIndexOf = new HashMap<>();
45 45
 	
@@ -56,7 +56,7 @@ public class JavaSourceSyntheticHelperGenerator {
56 56
 		String method = generateContains(kind);
57 57
 		addMember(arrayHelpers, method);
58 58
 		
59
-		JavaSourceMethod sourceMethod = new JavaSourceMethod(arrayHelpers, JavaSourceMethod.Kind.EXPANSION, kind.containsName);
59
+		JavaSourceMethod sourceMethod = new JavaSourceMethod(arrayHelpers, JavaSourceMethod.Kind.EXPANSION, kind.containsName, false);
60 60
 		existingContains.put(kind, sourceMethod);
61 61
 		return sourceMethod;
62 62
 	}
@@ -69,7 +69,7 @@ public class JavaSourceSyntheticHelperGenerator {
69 69
 		String method = generateContains(kind);
70 70
 		addMember(arrayHelpers, method);
71 71
 		
72
-		JavaSourceMethod sourceMethod = new JavaSourceMethod(arrayHelpers, JavaSourceMethod.Kind.EXPANSION, kind.containsName);
72
+		JavaSourceMethod sourceMethod = new JavaSourceMethod(arrayHelpers, JavaSourceMethod.Kind.EXPANSION, kind.containsName, false);
73 73
 		existingContains.put(kind, sourceMethod);
74 74
 		return sourceMethod;
75 75
 	}

+ 20
- 9
JavaSourceCompiler/src/main/java/org/openzen/zenscript/javasource/JavaSourceSyntheticTypeGenerator.java View File

@@ -12,11 +12,14 @@ import java.io.IOException;
12 12
 import java.io.OutputStreamWriter;
13 13
 import java.io.Writer;
14 14
 import java.nio.charset.StandardCharsets;
15
+import java.util.ArrayList;
15 16
 import java.util.HashMap;
17
+import java.util.List;
16 18
 import java.util.Map;
17 19
 import org.openzen.zenscript.codemodel.FunctionParameter;
18
-import org.openzen.zenscript.codemodel.definition.ZSPackage;
20
+import org.openzen.zenscript.codemodel.generic.TypeParameter;
19 21
 import org.openzen.zenscript.codemodel.type.FunctionTypeID;
22
+import org.openzen.zenscript.codemodel.type.ITypeID;
20 23
 import org.openzen.zenscript.javasource.tags.JavaSourceClass;
21 24
 
22 25
 /**
@@ -24,7 +27,7 @@ import org.openzen.zenscript.javasource.tags.JavaSourceClass;
24 27
  * @author Hoofdgebruiker
25 28
  */
26 29
 public class JavaSourceSyntheticTypeGenerator {
27
-	private final Map<FunctionTypeID, JavaSourceClass> functions = new HashMap<>();
30
+	private final Map<FunctionTypeID, JavaSynthesizedClass> functions = new HashMap<>();
28 31
 	private final File directory;
29 32
 	private final JavaSourceFormattingSettings settings;
30 33
 	
@@ -33,21 +36,23 @@ public class JavaSourceSyntheticTypeGenerator {
33 36
 		this.settings = settings;
34 37
 	}
35 38
 	
36
-	public JavaSourceClass createFunction(FunctionTypeID function) {
39
+	public JavaSynthesizedClass createFunction(JavaSourceTypeVisitor typeFormatter, FunctionTypeID function) {
37 40
 		if (functions.containsKey(function))
38 41
 			return functions.get(function);
39 42
 		
40 43
 		String className = createFunctionClassName(function);
41
-		JavaSourceClass result = new JavaSourceClass(className, "zsynthetic." + className);
44
+		JavaSourceClass cls = new JavaSourceClass("zsynthetic", className);
45
+		JavaSynthesizedClass result = new JavaSynthesizedClass(cls, extractTypeParameters(function));
42 46
 		functions.put(function, result);
43 47
 		
44
-		JavaSourceImporter importer = new JavaSourceImporter(new ZSPackage(null, "zsynthetic"));
48
+		JavaSourceImporter importer = new JavaSourceImporter(cls);
45 49
 		JavaSourceTypeVisitor typeVisitor = new JavaSourceTypeVisitor(importer, this);
46 50
 		
47 51
 		StringBuilder contents = new StringBuilder();
48 52
 		contents.append("@FunctionalInterface\n");
49 53
 		contents.append("public interface ");
50 54
 		contents.append(className);
55
+		JavaSourceUtils.formatTypeParameters(typeFormatter, contents, result.typeParameters);
51 56
 		contents.append(" {\n");
52 57
 		contents.append(settings.indent);
53 58
 		if (function.header.getNumberOfTypeParameters() > 0) {
@@ -83,14 +88,14 @@ public class JavaSourceSyntheticTypeGenerator {
83 88
 		try (Writer writer = new OutputStreamWriter(new BufferedOutputStream(new FileOutputStream(file)), StandardCharsets.UTF_8)) {
84 89
 			writer.write("package zsynthetic;\n");
85 90
 			
86
-			JavaSourceImporter.Import[] imports = importer.getUsedImports();
91
+			JavaSourceClass[] imports = importer.getUsedImports();
87 92
 			if (imports.length > 0) {
88
-				for (JavaSourceImporter.Import import_ : imports) {
89
-					if (import_.actualName.startsWith("java.lang."))
93
+				for (JavaSourceClass import_ : imports) {
94
+					if (import_.pkg.equals("java.lang"))
90 95
 						continue;
91 96
 					
92 97
 					writer.write("import ");
93
-					writer.write(import_.actualName);
98
+					writer.write(import_.fullName);
94 99
 					writer.write(";\n");
95 100
 				}
96 101
 
@@ -111,4 +116,10 @@ public class JavaSourceSyntheticTypeGenerator {
111 116
 		className.append(functions.size() + 1); // TODO: create more meaningful names
112 117
 		return className.toString();
113 118
 	}
119
+	
120
+	private TypeParameter[] extractTypeParameters(ITypeID type) {
121
+		List<TypeParameter> result = new ArrayList<>();
122
+		type.extractTypeParameters(result);
123
+		return result.toArray(new TypeParameter[result.size()]);
124
+	}
114 125
 }

+ 33
- 7
JavaSourceCompiler/src/main/java/org/openzen/zenscript/javasource/JavaSourceTypeVisitor.java View File

@@ -21,19 +21,30 @@ import org.openzen.zenscript.codemodel.type.IteratorTypeID;
21 21
 import org.openzen.zenscript.codemodel.type.OptionalTypeID;
22 22
 import org.openzen.zenscript.codemodel.type.RangeTypeID;
23 23
 import org.openzen.zenscript.javasource.tags.JavaSourceClass;
24
+import org.openzen.zenscript.javasource.tags.JavaSourceMethod;
24 25
 
25 26
 /**
26 27
  *
27 28
  * @author Hoofdgebruiker
28 29
  */
29 30
 public class JavaSourceTypeVisitor implements ITypeVisitor<String>, GenericParameterBoundVisitor<String> {
31
+	private static final JavaSourceClass MAP = new JavaSourceClass("java.util", "Map");
32
+	private static final JavaSourceClass HASHMAP = new JavaSourceClass("java.util", "HashMap");
33
+	private static final JavaSourceClass ITERATOR = new JavaSourceClass("java.util", "Iterator");
34
+	
30 35
 	public final JavaSourceImporter importer;
31 36
 	public final JavaSourceSyntheticTypeGenerator typeGenerator;
32 37
 	public final JavaSourceObjectTypeVisitor objectTypeVisitor;
38
+	public final JavaSourceClass cls;
33 39
 	
34 40
 	public JavaSourceTypeVisitor(JavaSourceImporter importer, JavaSourceSyntheticTypeGenerator typeGenerator) {
41
+		this(importer, typeGenerator, null);
42
+	}
43
+	
44
+	public JavaSourceTypeVisitor(JavaSourceImporter importer, JavaSourceSyntheticTypeGenerator typeGenerator, JavaSourceClass cls) {
35 45
 		this.importer = importer;
36 46
 		this.typeGenerator = typeGenerator;
47
+		this.cls = cls;
37 48
 		
38 49
 		if (this instanceof JavaSourceObjectTypeVisitor) {
39 50
 			objectTypeVisitor = (JavaSourceObjectTypeVisitor)this;
@@ -77,30 +88,45 @@ public class JavaSourceTypeVisitor implements ITypeVisitor<String>, GenericParam
77 88
 
78 89
 	@Override
79 90
 	public String visitAssoc(AssocTypeID assoc) {
80
-		String map = importer.importType("java.util.Map");
91
+		String map = importer.importType(MAP);
81 92
 		return map + "<" + assoc.keyType.accept(new JavaSourceObjectTypeVisitor(importer, typeGenerator)) + ", " + assoc.valueType.accept(new JavaSourceObjectTypeVisitor(importer, typeGenerator)) + ">";
82 93
 	}
83 94
 
84 95
 	@Override
85 96
 	public String visitGenericMap(GenericMapTypeID map) {
86
-		String javaMap = importer.importType("java.util.Map");
87
-		return javaMap + "<Class<?>, Object>";
97
+		return importer.importType(MAP) + "<Class<?>, Object>";
88 98
 	}
89 99
 
90 100
 	@Override
91 101
 	public String visitIterator(IteratorTypeID iterator) {
92
-		throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
102
+		if (iterator.iteratorTypes.length == 1) {
103
+			return importer.importType(ITERATOR) + "<" + iterator.iteratorTypes[0].accept(objectTypeVisitor) + '>';
104
+		} else {
105
+			throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
106
+		}
93 107
 	}
94 108
 
95 109
 	@Override
96 110
 	public String visitFunction(FunctionTypeID function) {
97
-		JavaSourceClass synthetic = typeGenerator.createFunction(function);
98
-		return importer.importType(synthetic.fullName);
111
+		JavaSynthesizedClass synthetic = typeGenerator.createFunction(this, function);
112
+		StringBuilder result = new StringBuilder();
113
+		result.append(importer.importType(synthetic.cls));
114
+		if (synthetic.typeParameters.length > 0) {
115
+			result.append('<');
116
+			for (int i = 0; i < synthetic.typeParameters.length; i++) {
117
+				if (i > 0)
118
+					result.append(", ");
119
+				
120
+				result.append(synthetic.typeParameters[i].name);
121
+			}
122
+			result.append('>');
123
+		}
124
+		return result.toString();
99 125
 	}
100 126
 
101 127
 	@Override
102 128
 	public String visitDefinition(DefinitionTypeID definition) {
103
-		String javaType = importer.importType(definition.definition);
129
+		String javaType = cls == null ? importer.importType(definition.definition) : importer.importType(cls);
104 130
 		StringBuilder result = new StringBuilder(javaType);
105 131
 		if (definition.typeParameters != null && definition.typeParameters.length > 0) {
106 132
 			result.append("<");

+ 50
- 8
JavaSourceCompiler/src/main/java/org/openzen/zenscript/javasource/JavaSourceUtils.java View File

@@ -10,7 +10,7 @@ import org.openzen.zenscript.codemodel.generic.GenericParameterBoundVisitor;
10 10
 import org.openzen.zenscript.codemodel.generic.ParameterSuperBound;
11 11
 import org.openzen.zenscript.codemodel.generic.ParameterTypeBound;
12 12
 import org.openzen.zenscript.codemodel.generic.TypeParameter;
13
-import org.openzen.zenscript.javasource.scope.JavaSourceFileScope;
13
+import org.openzen.zenscript.codemodel.type.ITypeID;
14 14
 
15 15
 /**
16 16
  *
@@ -19,11 +19,11 @@ import org.openzen.zenscript.javasource.scope.JavaSourceFileScope;
19 19
 public class JavaSourceUtils {
20 20
 	private JavaSourceUtils() {}
21 21
 	
22
-	public static void formatTypeParameters(JavaSourceFileScope scope, StringBuilder output, TypeParameter[] parameters) {
22
+	public static void formatTypeParameters(JavaSourceTypeVisitor typeFormatter, StringBuilder output, TypeParameter[] parameters) {
23 23
 		if (parameters == null || parameters.length == 0)
24 24
 			return;
25 25
 		
26
-		TypeParameterBoundVisitor boundVisitor = new TypeParameterBoundVisitor(scope, output);
26
+		TypeParameterBoundVisitor boundVisitor = new TypeParameterBoundVisitor(typeFormatter, output);
27 27
 		output.append("<");
28 28
 		for (int i = 0; i < parameters.length; i++) {
29 29
 			if (i > 0)
@@ -40,24 +40,66 @@ public class JavaSourceUtils {
40 40
 		output.append("> ");
41 41
 	}
42 42
 	
43
+	public static void formatTypeParameters(JavaSourceTypeVisitor typeFormatter, StringBuilder output, TypeParameter[] expansion, TypeParameter[] parameters) {
44
+		if (((parameters == null ? 0 : parameters.length) + (expansion == null ? 0 : expansion.length)) == 0)
45
+			return;
46
+		
47
+		TypeParameterBoundVisitor boundVisitor = new TypeParameterBoundVisitor(typeFormatter, output);
48
+		output.append("<");
49
+		boolean first = true;
50
+		if (parameters != null) {
51
+			for (int i = 0; i < parameters.length; i++) {
52
+				if (first)
53
+					first = false;
54
+				else
55
+					output.append(", ");
56
+
57
+				TypeParameter typeParameter = parameters[i];
58
+				output.append(typeParameter.name);
59
+
60
+				if (typeParameter.bounds.size() > 0) {
61
+					for (GenericParameterBound bound : typeParameter.bounds)
62
+						bound.accept(boundVisitor);
63
+				}
64
+			}
65
+		}
66
+		if (expansion != null) {
67
+			for (int i = 0; i < expansion.length; i++) {
68
+				if (first)
69
+					first = false;
70
+				else
71
+					output.append(", ");
72
+
73
+				TypeParameter typeParameter = expansion[i];
74
+				output.append(typeParameter.name);
75
+
76
+				if (typeParameter.bounds.size() > 0) {
77
+					for (GenericParameterBound bound : typeParameter.bounds)
78
+						bound.accept(boundVisitor);
79
+				}
80
+			}
81
+		}
82
+		output.append("> ");
83
+	}
84
+	
43 85
 	private static class TypeParameterBoundVisitor implements GenericParameterBoundVisitor<Void> {
44
-		private final JavaSourceFileScope scope;
86
+		private final JavaSourceTypeVisitor typeFormatter;
45 87
 		private final StringBuilder output;
46 88
 		
47
-		public TypeParameterBoundVisitor(JavaSourceFileScope scope, StringBuilder output) {
48
-			this.scope = scope;
89
+		public TypeParameterBoundVisitor(JavaSourceTypeVisitor typeFormatter, StringBuilder output) {
90
+			this.typeFormatter = typeFormatter;
49 91
 			this.output = output;
50 92
 		}
51 93
 
52 94
 		@Override
53 95
 		public Void visitSuper(ParameterSuperBound bound) {
54
-			output.append(" super ").append(scope.type(bound.type));
96
+			output.append(" super ").append(bound.type.accept(typeFormatter));
55 97
 			return null;
56 98
 		}
57 99
 
58 100
 		@Override
59 101
 		public Void visitType(ParameterTypeBound bound) {
60
-			output.append(" extends ").append(scope.type(bound.type));
102
+			output.append(" extends ").append(bound.type.accept(typeFormatter));
61 103
 			return null;
62 104
 		}
63 105
 	}

+ 23
- 0
JavaSourceCompiler/src/main/java/org/openzen/zenscript/javasource/JavaSynthesizedClass.java View File

@@ -0,0 +1,23 @@
1
+/*
2
+ * To change this license header, choose License Headers in Project Properties.
3
+ * To change this template file, choose Tools | Templates
4
+ * and open the template in the editor.
5
+ */
6
+package org.openzen.zenscript.javasource;
7
+
8
+import org.openzen.zenscript.codemodel.generic.TypeParameter;
9
+import org.openzen.zenscript.javasource.tags.JavaSourceClass;
10
+
11
+/**
12
+ *
13
+ * @author Hoofdgebruiker
14
+ */
15
+public class JavaSynthesizedClass {
16
+	public final JavaSourceClass cls;
17
+	public final TypeParameter[] typeParameters;
18
+	
19
+	public JavaSynthesizedClass(JavaSourceClass cls, TypeParameter[] typeParameters) {
20
+		this.cls = cls;
21
+		this.typeParameters = typeParameters;
22
+	}
23
+}

+ 40
- 0
JavaSourceCompiler/src/main/java/org/openzen/zenscript/javasource/prepare/JavaNativeClass.java View File

@@ -0,0 +1,40 @@
1
+/*
2
+ * To change this license header, choose License Headers in Project Properties.
3
+ * To change this template file, choose Tools | Templates
4
+ * and open the template in the editor.
5
+ */
6
+package org.openzen.zenscript.javasource.prepare;
7
+
8
+import java.util.HashMap;
9
+import java.util.Map;
10
+import org.openzen.zenscript.javasource.tags.JavaSourceClass;
11
+import org.openzen.zenscript.javasource.tags.JavaSourceMethod;
12
+
13
+/**
14
+ *
15
+ * @author Hoofdgebruiker
16
+ */
17
+public class JavaNativeClass {
18
+	public final JavaSourceClass cls;
19
+	private final Map<String, JavaSourceMethod> methods = new HashMap<>();
20
+	
21
+	public JavaNativeClass(JavaSourceClass cls) {
22
+		this.cls = cls;
23
+	}
24
+	
25
+	public void addMethod(String key, JavaSourceMethod method) {
26
+		methods.put(key, method);
27
+	}
28
+	
29
+	public void addConstructor(String key, String name) {
30
+		methods.put(key, new JavaSourceMethod(cls, JavaSourceMethod.Kind.CONSTRUCTOR, name, false));
31
+	}
32
+	
33
+	public void addInstanceMethod(String key, String name) {
34
+		methods.put(key, new JavaSourceMethod(cls, JavaSourceMethod.Kind.INSTANCE, name, false));
35
+	}
36
+	
37
+	public JavaSourceMethod getMethod(String name) {
38
+		return methods.get(name);
39
+	}
40
+}

+ 28
- 73
JavaSourceCompiler/src/main/java/org/openzen/zenscript/javasource/prepare/JavaSourcePrepareClassMethodVisitor.java View File

@@ -7,7 +7,6 @@ package org.openzen.zenscript.javasource.prepare;
7 7
 
8 8
 import org.openzen.zenscript.codemodel.OperatorType;
9 9
 import org.openzen.zenscript.codemodel.annotations.NativeTag;
10
-import org.openzen.zenscript.codemodel.expression.CastExpression;
11 10
 import org.openzen.zenscript.codemodel.member.CallerMember;
12 11
 import org.openzen.zenscript.codemodel.member.CasterMember;
13 12
 import org.openzen.zenscript.codemodel.member.ConstMember;
@@ -24,8 +23,6 @@ import org.openzen.zenscript.codemodel.member.MethodMember;
24 23
 import org.openzen.zenscript.codemodel.member.OperatorMember;
25 24
 import org.openzen.zenscript.codemodel.member.SetterMember;
26 25
 import org.openzen.zenscript.codemodel.member.StaticInitializerMember;
27
-import org.openzen.zenscript.formattershared.ExpressionString;
28
-import org.openzen.zenscript.javasource.JavaOperator;
29 26
 import org.openzen.zenscript.javasource.JavaSourceTypeNameVisitor;
30 27
 import org.openzen.zenscript.javasource.tags.JavaSourceClass;
31 28
 import org.openzen.zenscript.javasource.tags.JavaSourceField;
@@ -38,20 +35,30 @@ import org.openzen.zenscript.shared.StringUtils;
38 35
  */
39 36
 public class JavaSourcePrepareClassMethodVisitor implements MemberVisitor<Void> {
40 37
 	private final JavaSourceClass cls;
38
+	private final JavaNativeClass nativeClass;
41 39
 	
42
-	public JavaSourcePrepareClassMethodVisitor(JavaSourceClass cls) {
40
+	public JavaSourcePrepareClassMethodVisitor(JavaSourceClass cls, JavaNativeClass nativeClass, boolean startsEmpty) {
43 41
 		this.cls = cls;
42
+		this.nativeClass = nativeClass;
43
+		cls.empty = startsEmpty;
44 44
 	}
45 45
 	
46 46
 	@Override
47 47
 	public Void visitConst(ConstMember member) {
48
+		cls.empty = false;
48 49
 		member.setTag(JavaSourceField.class, new JavaSourceField(cls, member.name));
49 50
 		return null;
50 51
 	}
51 52
 	
52 53
 	@Override
53 54
 	public Void visitField(FieldMember member) {
55
+		cls.empty = false;
54 56
 		member.setTag(JavaSourceField.class, new JavaSourceField(cls, member.name));
57
+		if (member.hasAutoGetter())
58
+			visitGetter(member.autoGetter);
59
+		if (member.hasAutoSetter())
60
+			visitSetter(member.autoSetter);
61
+		
55 62
 		return null;
56 63
 	}
57 64
 
@@ -63,6 +70,7 @@ public class JavaSourcePrepareClassMethodVisitor implements MemberVisitor<Void>
63 70
 
64 71
 	@Override
65 72
 	public Void visitDestructor(DestructorMember member) {
73
+		cls.empty = false;
66 74
 		return null;
67 75
 	}
68 76
 
@@ -111,21 +119,27 @@ public class JavaSourcePrepareClassMethodVisitor implements MemberVisitor<Void>
111 119
 	@Override
112 120
 	public Void visitImplementation(ImplementationMember member) {
113 121
 		// TODO: implementation merge check
122
+		cls.empty = false;
114 123
 		return null;
115 124
 	}
116 125
 
117 126
 	@Override
118 127
 	public Void visitInnerDefinition(InnerDefinitionMember member) {
119 128
 		// TODO
129
+		cls.empty = false;
120 130
 		return null;
121 131
 	}
122 132
 
123 133
 	@Override
124 134
 	public Void visitStaticInitializer(StaticInitializerMember member) {
135
+		cls.empty = false;
125 136
 		return null;
126 137
 	}
127 138
 	
128 139
 	private JavaSourceMethod.Kind getKind(DefinitionMember member) {
140
+		if (member instanceof ConstructorMember)
141
+			return JavaSourceMethod.Kind.CONSTRUCTOR;
142
+		
129 143
 		return member.isStatic() ? JavaSourceMethod.Kind.STATIC : JavaSourceMethod.Kind.INSTANCE;
130 144
 	}
131 145
 	
@@ -194,7 +208,7 @@ public class JavaSourcePrepareClassMethodVisitor implements MemberVisitor<Void>
194 208
 			case CONTAINS:
195 209
 				return "contains";
196 210
 			case EQUALS:
197
-				return "equals";
211
+				return "equals_";
198 212
 			case COMPARE:
199 213
 				return "compareTo";
200 214
 			case RANGE:
@@ -214,74 +228,15 @@ public class JavaSourcePrepareClassMethodVisitor implements MemberVisitor<Void>
214 228
 	
215 229
 	private void visitFunctional(DefinitionMember member, String name) {
216 230
 		NativeTag nativeTag = member.getTag(NativeTag.class);
217
-		if (nativeTag == null) {
218
-			member.setTag(
219
-					JavaSourceMethod.class,
220
-					new JavaSourceMethod(cls, getKind(member), name));
221
-		} else {
222
-			member.setTag(JavaSourceMethod.class, getNative(nativeTag.value));
223
-		}
224
-	}
225
-	
226
-	private JavaSourceMethod getNative(String name) {
227
-		if (cls.fullName.equals("java.lang.StringBuilder"))
228
-			return getStringBuilderNative(name);
229
-		else if (cls.fullName.equals("java.util.List"))
230
-			return getListNative(name);
231
+		JavaSourceMethod method = null;
232
+		if (nativeTag != null && nativeClass != null)
233
+			method = nativeClass.getMethod(nativeTag.value);
234
+		if (method == null)
235
+			method = new JavaSourceMethod(cls, getKind(member), name, true);
231 236
 		
232
-		throw new UnsupportedOperationException("Unknown native class: " + cls.fullName);
233
-	}
234
-	
235
-	private JavaSourceMethod getListNative(String name) {
236
-		switch (name) {
237
-			case "constructor":
238
-				return new JavaSourceMethod((formatter, call) -> new ExpressionString("new ArrayList<>()", JavaOperator.NEW));
239
-			case "add":
240
-				return new JavaSourceMethod(cls, JavaSourceMethod.Kind.INSTANCE, "add");
241
-			case "getIndex":
242
-				return new JavaSourceMethod(cls, JavaSourceMethod.Kind.INSTANCE, "get");
243
-			case "setIndex":
244
-				return new JavaSourceMethod(cls, JavaSourceMethod.Kind.INSTANCE, "set");
245
-			case "toArray":
246
-				return new JavaSourceMethod((formatter, calle)
247
-						-> formatter.listToArray((CastExpression)calle));
248
-			case "length":
249
-				return new JavaSourceMethod(cls, JavaSourceMethod.Kind.INSTANCE, "size");
250
-			case "isEmpty":
251
-				return new JavaSourceMethod(cls, JavaSourceMethod.Kind.INSTANCE, "isEmpty");
252
-			default:
253
-				throw new UnsupportedOperationException("Unknown native method: " + name);
254
-		}
255
-	}
256
-	
257
-	private JavaSourceMethod getStringBuilderNative(String name) {
258
-		switch (name) {
259
-			case "constructor":
260
-			case "constructorWithCapacity":
261
-			case "constructorWithValue":
262
-				return new JavaSourceMethod(cls, JavaSourceMethod.Kind.INSTANCE, "");
263
-			case "isEmpty":
264
-				return new JavaSourceMethod(cls, JavaSourceMethod.Kind.INSTANCE, "isEmpty");
265
-			case "length":
266
-				return new JavaSourceMethod(cls, JavaSourceMethod.Kind.INSTANCE, "length");
267
-			case "appendBool":
268
-			case "appendByte":
269
-			case "appendSByte":
270
-			case "appendShort":
271
-			case "appendUShort":
272
-			case "appendInt":
273
-			case "appendUInt":
274
-			case "appendLong":
275
-			case "appendULong":
276
-			case "appendFloat":
277
-			case "appendDouble":
278
-			case "appendChar":
279
-			case "appendString":
280
-				return new JavaSourceMethod(cls, JavaSourceMethod.Kind.INSTANCE, "append");
281
-			case "asString":
282
-				return new JavaSourceMethod(cls, JavaSourceMethod.Kind.INSTANCE, "toString");
283
-			default:
284
-				throw new UnsupportedOperationException("Unknown native method: " + name);
285
-		}
237
+		if (method.compile)
238
+			cls.empty = false;
239
+		
240
+		member.setTag(JavaSourceMethod.class, method);
286 241
 	}
287 242
 }

+ 191
- 50
JavaSourceCompiler/src/main/java/org/openzen/zenscript/javasource/prepare/JavaSourcePrepareDefinitionVisitor.java View File

@@ -5,6 +5,8 @@
5 5
  */
6 6
 package org.openzen.zenscript.javasource.prepare;
7 7
 
8
+import java.util.HashMap;
9
+import java.util.Map;
8 10
 import org.openzen.zenscript.codemodel.HighLevelDefinition;
9 11
 import org.openzen.zenscript.codemodel.annotations.NativeTag;
10 12
 import org.openzen.zenscript.codemodel.definition.AliasDefinition;
@@ -16,9 +18,14 @@ import org.openzen.zenscript.codemodel.definition.FunctionDefinition;
16 18
 import org.openzen.zenscript.codemodel.definition.InterfaceDefinition;
17 19
 import org.openzen.zenscript.codemodel.definition.StructDefinition;
18 20
 import org.openzen.zenscript.codemodel.definition.VariantDefinition;
21
+import org.openzen.zenscript.codemodel.expression.CallExpression;
22
+import org.openzen.zenscript.codemodel.expression.CastExpression;
23
+import org.openzen.zenscript.codemodel.expression.Expression;
19 24
 import org.openzen.zenscript.codemodel.member.IDefinitionMember;
25
+import org.openzen.zenscript.codemodel.type.ArrayTypeID;
26
+import org.openzen.zenscript.formattershared.ExpressionString;
27
+import org.openzen.zenscript.javasource.JavaOperator;
20 28
 import org.openzen.zenscript.javasource.tags.JavaSourceClass;
21
-import org.openzen.zenscript.javasource.JavaSourceFile;
22 29
 import org.openzen.zenscript.javasource.tags.JavaSourceMethod;
23 30
 import org.openzen.zenscript.javasource.tags.JavaSourceVariantOption;
24 31
 
@@ -26,100 +33,234 @@ import org.openzen.zenscript.javasource.tags.JavaSourceVariantOption;
26 33
  *
27 34
  * @author Hoofdgebruiker
28 35
  */
29
-public class JavaSourcePrepareDefinitionVisitor implements DefinitionVisitor<Void> {
30
-	private final JavaSourceFile file;
36
+public class JavaSourcePrepareDefinitionVisitor implements DefinitionVisitor<JavaSourceClass> {
37
+	private static final Map<String, JavaNativeClass> nativeClasses = new HashMap<>();
31 38
 	
32
-	public JavaSourcePrepareDefinitionVisitor(JavaSourceFile file) {
33
-		this.file = file;
39
+	static {
40
+		{
41
+			JavaNativeClass cls = new JavaNativeClass(new JavaSourceClass("java.lang", "StringBuilder"));
42
+			cls.addConstructor("constructor", "");
43
+			cls.addConstructor("constructorWithCapacity", "");
44
+			cls.addConstructor("constructorWithValue", "");
45
+			cls.addMethod("isEmpty", new JavaSourceMethod((formatter, call) -> ((CallExpression)call).accept(formatter).unaryPostfix(JavaOperator.EQUALS, "length() == 0")));
46
+			cls.addInstanceMethod("length", "length");
47
+			cls.addInstanceMethod("appendBool", "append");
48
+			cls.addInstanceMethod("appendByte", "append");
49
+			cls.addInstanceMethod("appendSByte", "append");
50
+			cls.addInstanceMethod("appendShort", "append");
51
+			cls.addInstanceMethod("appendUShort", "append");
52
+			cls.addInstanceMethod("appendInt", "append");
53
+			cls.addInstanceMethod("appendUInt", "append");
54
+			cls.addInstanceMethod("appendLong", "append");
55
+			cls.addInstanceMethod("appendULong", "append");
56
+			cls.addInstanceMethod("appendFloat", "append");
57
+			cls.addInstanceMethod("appendDouble", "append");
58
+			cls.addInstanceMethod("appendChar", "append");
59
+			cls.addInstanceMethod("appendString", "append");
60
+			cls.addInstanceMethod("asString", "toString");
61
+			nativeClasses.put("stdlib::StringBuilder", cls);
62
+		}
63
+		
64
+		{
65
+			JavaNativeClass list = new JavaNativeClass(new JavaSourceClass("java.util", "List"));
66
+			JavaSourceClass arrayList = new JavaSourceClass("java.util", "ArrayList");
67
+			list.addMethod("constructor", new JavaSourceMethod(arrayList, JavaSourceMethod.Kind.CONSTRUCTOR, "", false));
68
+			list.addInstanceMethod("add", "add");
69
+			list.addInstanceMethod("insert", "add");
70
+			list.addInstanceMethod("getAtIndex", "get");
71
+			list.addInstanceMethod("setAtIndex", "set");
72
+			list.addMethod("toArray", new JavaSourceMethod((formatter, call) -> formatter.listToArray((CastExpression)call)));
73
+			list.addInstanceMethod("length", "length");
74
+			list.addInstanceMethod("isEmpty", "isEmpty");
75
+			nativeClasses.put("stdlib::List", list);
76
+		}
77
+		
78
+		{
79
+			JavaNativeClass comparable = new JavaNativeClass(new JavaSourceClass("java.lang", "Comparable"));
80
+			comparable.addInstanceMethod("compareTo", "compareTo");
81
+			nativeClasses.put("stdlib::Comparable", comparable);
82
+		}
83
+		
84
+		{
85
+			JavaSourceClass integer = new JavaSourceClass("java.lang", "Integer");
86
+			JavaSourceClass math = new JavaSourceClass("java.lang", "Math");
87
+			
88
+			JavaNativeClass cls = new JavaNativeClass(integer);
89
+			cls.addMethod("min", new JavaSourceMethod(math, JavaSourceMethod.Kind.STATIC, "min", false));
90
+			cls.addMethod("max", new JavaSourceMethod(math, JavaSourceMethod.Kind.STATIC, "max", false));
91
+			cls.addMethod("toHexString", new JavaSourceMethod(integer, JavaSourceMethod.Kind.EXPANSION, "toHexString", false));
92
+			nativeClasses.put("stdlib::Integer", cls);
93
+		}
94
+		
95
+		{
96
+			JavaNativeClass cls = new JavaNativeClass(new JavaSourceClass("java.lang", "String"));
97
+			cls.addMethod("contains", new JavaSourceMethod((formatter, calle) -> {
98
+				CallExpression call = (CallExpression)calle;
99
+				ExpressionString str = call.arguments.arguments[0].accept(formatter);
100
+				ExpressionString character = call.arguments.arguments[1].accept(formatter);
101
+				return str.unaryPostfix(JavaOperator.GREATER_EQUALS, ".indexOf(" + character.value + ")");
102
+			}));
103
+			cls.addInstanceMethod("indexOf", "indexOf");
104
+			cls.addInstanceMethod("indexOfFrom", "indexOf");
105
+			cls.addInstanceMethod("lastIndexOf", "lastIndexOf");
106
+			cls.addInstanceMethod("lastIndexOfFrom", "lastIndexOf");
107
+			cls.addInstanceMethod("trim", "trim");
108
+			nativeClasses.put("stdlib::String", cls);
109
+		}
110
+		
111
+		{
112
+			JavaSourceClass arrays = new JavaSourceClass("java.lang", "Arrays");
113
+			JavaNativeClass cls = new JavaNativeClass(arrays);
114
+			cls.addMethod("sort", new JavaSourceMethod(arrays, JavaSourceMethod.Kind.EXPANSION, "sort", false));
115
+			cls.addMethod("sorted", new JavaSourceMethod((formatter, calle) -> {
116
+				Expression target = formatter.duplicable(((CallExpression)calle).target);
117
+				ExpressionString targetString = target.accept(formatter);
118
+				ExpressionString copy = new ExpressionString("Arrays.copyOf(" + targetString.value + ", " + targetString.value + ".length).sort()", JavaOperator.CALL);
119
+				ExpressionString source = formatter.hoist(copy, formatter.scope.type(target.type));
120
+				formatter.target.writeLine("Arrays.sort(" + source.value + ");");
121
+				return source;
122
+			}));
123
+			cls.addMethod("sortWithComparator", new JavaSourceMethod(arrays, JavaSourceMethod.Kind.EXPANSION, "sort", false));
124
+			cls.addMethod("sortedWithComparator", new JavaSourceMethod((formatter, calle) -> {
125
+				Expression target = formatter.duplicable(((CallExpression)calle).target);
126
+				ExpressionString comparator = ((CallExpression)calle).arguments.arguments[0].accept(formatter);
127
+				ExpressionString targetString = target.accept(formatter);
128
+				ExpressionString copy = new ExpressionString("Arrays.copyOf(" + targetString.value + ", " + targetString.value + ".length).sort()", JavaOperator.CALL);
129
+				ExpressionString source = formatter.hoist(copy, formatter.scope.type(target.type));
130
+				formatter.target.writeLine("Arrays.sort(" + source.value + ", " + comparator.value + ");");
131
+				return source;
132
+			}));
133
+			cls.addMethod("copy", new JavaSourceMethod((formatter, calle) -> {
134
+				Expression target = formatter.duplicable(((CallExpression)calle).target);
135
+				ExpressionString source = target.accept(formatter);
136
+				return new ExpressionString("Arrays.copyOf(" + source.value + ", " + source.value + ".length)", JavaOperator.CALL);
137
+			}));
138
+			cls.addMethod("copyResize", new JavaSourceMethod(arrays, JavaSourceMethod.Kind.EXPANSION, "copyOf", false));
139
+			cls.addMethod("copyTo", new JavaSourceMethod((formatter, calle) -> {
140
+				CallExpression call = (CallExpression)calle;
141
+				Expression source = call.target;
142
+				Expression target = call.arguments.arguments[0];
143
+				Expression sourceOffset = call.arguments.arguments[1];
144
+				Expression targetOffset = call.arguments.arguments[2];
145
+				Expression length = call.arguments.arguments[3];
146
+				return new ExpressionString("System.arraycopy("
147
+					+ source.accept(formatter) + ", "
148
+					+ sourceOffset.accept(formatter) + ", "
149
+					+ target.accept(formatter) + ", "
150
+					+ targetOffset.accept(formatter) + ", "
151
+					+ length.accept(formatter) + ")", JavaOperator.CALL);
152
+			}));
153
+			nativeClasses.put("stdlib::Arrays", cls);
154
+		}
155
+		
156
+		{
157
+			JavaNativeClass cls = new JavaNativeClass(new JavaSourceClass("java.lang", "IllegalArgumentException"));
158
+			cls.addConstructor("constructor", "");
159
+			nativeClasses.put("stdlib::IllegalArgumentException", cls);
160
+		}
161
+		
162
+		{
163
+			JavaNativeClass cls = new JavaNativeClass(new JavaSourceClass("java.lang", "Exception"));
164
+			cls.addConstructor("constructor", "");
165
+			cls.addConstructor("constructorWithCause", "");
166
+			nativeClasses.put("stdlib::Exception", cls);
167
+		}
168
+	}
169
+	
170
+	private final String filename;
171
+	
172
+	public JavaSourcePrepareDefinitionVisitor(String filename) {
173
+		this.filename = filename;
34 174
 	}
35 175
 	
36 176
 	@Override
37
-	public Void visitClass(ClassDefinition definition) {
38
-		visitClassCompiled(definition);
39
-		return null;
177
+	public JavaSourceClass visitClass(ClassDefinition definition) {
178
+		return visitClassCompiled(definition, true);
40 179
 	}
41 180
 
42 181
 	@Override
43
-	public Void visitInterface(InterfaceDefinition definition) {
44
-		visitClassCompiled(definition);
45
-		return null;
182
+	public JavaSourceClass visitInterface(InterfaceDefinition definition) {
183
+		return visitClassCompiled(definition, true);
46 184
 	}
47 185
 
48 186
 	@Override
49
-	public Void visitEnum(EnumDefinition definition) {
50
-		visitClassCompiled(definition);
51
-		return null;
187
+	public JavaSourceClass visitEnum(EnumDefinition definition) {
188
+		return visitClassCompiled(definition, false);
52 189
 	}
53 190
 
54 191
 	@Override
55
-	public Void visitStruct(StructDefinition definition) {
56
-		visitClassCompiled(definition);
57
-		return null;
192
+	public JavaSourceClass visitStruct(StructDefinition definition) {
193
+		return visitClassCompiled(definition, true);
58 194
 	}
59 195
 
60 196
 	@Override
61
-	public Void visitFunction(FunctionDefinition definition) {
62
-		JavaSourceClass cls = new JavaSourceClass(file.getName(), definition.pkg.fullName + "." + file.getName());
197
+	public JavaSourceClass visitFunction(FunctionDefinition definition) {
198
+		JavaSourceClass cls = new JavaSourceClass(definition.pkg.fullName, filename);
63 199
 		definition.setTag(JavaSourceClass.class, cls);
64
-		JavaSourceMethod method = new JavaSourceMethod(cls, JavaSourceMethod.Kind.STATIC, definition.name);
200
+		JavaSourceMethod method = new JavaSourceMethod(cls, JavaSourceMethod.Kind.STATIC, definition.name, true);
65 201
 		definition.caller.setTag(JavaSourceMethod.class, method);
66
-		return null;
202
+		return cls;
67 203
 	}
68 204
 
69 205
 	@Override
70
-	public Void visitExpansion(ExpansionDefinition definition) {
71
-		JavaSourceClass cls = new JavaSourceClass(file.getName(), definition.pkg.fullName + "." + file.getName());
72
-		definition.setTag(JavaSourceClass.class, cls);
73
-		JavaSourcePrepareExpansionMethodVisitor methodVisitor = new JavaSourcePrepareExpansionMethodVisitor(cls);
74
-		for (IDefinitionMember member : definition.members) {
75
-			member.accept(methodVisitor);
206
+	public JavaSourceClass visitExpansion(ExpansionDefinition definition) {
207
+		NativeTag nativeTag = definition.getTag(NativeTag.class);
208
+		JavaNativeClass nativeClass = null;
209
+		if (nativeTag != null) {
210
+			nativeClass = nativeClasses.get(nativeTag.value);
76 211
 		}
77
-		return null;
212
+		
213
+		JavaSourceClass cls = new JavaSourceClass(definition.pkg.fullName, filename);
214
+		definition.setTag(JavaSourceClass.class, cls);
215
+		visitExpansionMembers(definition, cls, nativeClass);
216
+		return cls;
78 217
 	}
79 218
 
80 219
 	@Override
81
-	public Void visitAlias(AliasDefinition definition) {
220
+	public JavaSourceClass visitAlias(AliasDefinition definition) {
82 221
 		throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
83 222
 	}
84 223
 
85 224
 	@Override
86
-	public Void visitVariant(VariantDefinition variant) {
87
-		JavaSourceClass cls = new JavaSourceClass(variant.name, variant.pkg.fullName + "." + variant.name);
225
+	public JavaSourceClass visitVariant(VariantDefinition variant) {
226
+		JavaSourceClass cls = new JavaSourceClass(variant.pkg.fullName, variant.name);
88 227
 		variant.setTag(JavaSourceClass.class, cls);
89 228
 		
90 229
 		for (VariantDefinition.Option option : variant.options) {
91
-			JavaSourceClass variantCls = new JavaSourceClass(option.name, cls.fullName + "." + option.name);
230
+			JavaSourceClass variantCls = new JavaSourceClass(cls.fullName, option.name);
92 231
 			option.setTag(JavaSourceVariantOption.class, new JavaSourceVariantOption(cls, variantCls));
93 232
 		}
94 233
 		
95
-		visitClassMembers(variant, cls);
96
-		return null;
234
+		visitClassMembers(variant, cls, null, false);
235
+		return cls;
97 236
 	}
98 237
 	
99
-	private void visitClassCompiled(HighLevelDefinition definition) {
238
+	private JavaSourceClass visitClassCompiled(HighLevelDefinition definition, boolean startsEmpty) {
100 239
 		NativeTag nativeTag = definition.getTag(NativeTag.class);
101
-		if (nativeTag == null) {
102
-			JavaSourceClass cls = new JavaSourceClass(definition.name, definition.pkg.fullName + "." + definition.name);
240
+		JavaNativeClass nativeClass = nativeTag == null ? null : nativeClasses.get(nativeTag.value);
241
+		if (nativeClass == null) {
242
+			JavaSourceClass cls = new JavaSourceClass(definition.pkg.fullName, definition.name);
103 243
 			definition.setTag(JavaSourceClass.class, cls);
104
-			visitClassMembers(definition, cls);
244
+			visitClassMembers(definition, cls, null, startsEmpty);
245
+			return cls;
105 246
 		} else {
106
-			JavaSourceClass cls = getNativeClass(nativeTag.value);
107
-			definition.setTag(JavaSourceClass.class, cls);
108
-			visitClassMembers(definition, cls);
247
+			JavaSourceClass cls = new JavaSourceClass(definition.pkg.fullName, filename);
248
+			definition.setTag(JavaSourceClass.class, nativeClass.cls);
249
+			definition.setTag(JavaNativeClass.class, nativeClass);
250
+			visitExpansionMembers(definition, cls, nativeClass);
251
+			return cls;
109 252
 		}
110 253
 	}
111 254
 	
112
-	private JavaSourceClass getNativeClass(String name) {
113
-		if (name.equals("stdlib::StringBuilder"))
114
-			return new JavaSourceClass("StringBuilder", "java.lang.StringBuilder");
115
-		else if (name.equals("stdlib::List"))
116
-			return new JavaSourceClass("List", "java.util.List");
117
-		
118
-		throw new UnsupportedOperationException("Unknown native class: " + name);
255
+	private void visitClassMembers(HighLevelDefinition definition, JavaSourceClass cls, JavaNativeClass nativeClass, boolean startsEmpty) {
256
+		JavaSourcePrepareClassMethodVisitor methodVisitor = new JavaSourcePrepareClassMethodVisitor(cls, nativeClass, startsEmpty);
257
+		for (IDefinitionMember member : definition.members) {
258
+			member.accept(methodVisitor);
259
+		}
119 260
 	}
120 261
 	
121
-	private void visitClassMembers(HighLevelDefinition definition, JavaSourceClass cls) {
122
-		JavaSourcePrepareClassMethodVisitor methodVisitor = new JavaSourcePrepareClassMethodVisitor(cls);
262
+	private void visitExpansionMembers(HighLevelDefinition definition, JavaSourceClass cls, JavaNativeClass nativeClass) {
263
+		JavaSourcePrepareExpansionMethodVisitor methodVisitor = new JavaSourcePrepareExpansionMethodVisitor(cls, nativeClass);
123 264
 		for (IDefinitionMember member : definition.members) {
124 265
 			member.accept(methodVisitor);
125 266
 		}

+ 24
- 6
JavaSourceCompiler/src/main/java/org/openzen/zenscript/javasource/prepare/JavaSourcePrepareExpansionMethodVisitor.java View File

@@ -6,6 +6,7 @@
6 6
 package org.openzen.zenscript.javasource.prepare;
7 7
 
8 8
 import org.openzen.zenscript.codemodel.OperatorType;
9
+import org.openzen.zenscript.codemodel.annotations.NativeTag;
9 10
 import org.openzen.zenscript.codemodel.member.CallerMember;
10 11
 import org.openzen.zenscript.codemodel.member.CasterMember;
11 12
 import org.openzen.zenscript.codemodel.member.ConstMember;
@@ -34,14 +35,18 @@ import org.openzen.zenscript.shared.StringUtils;
34 35
  */
35 36
 public class JavaSourcePrepareExpansionMethodVisitor implements MemberVisitor<Void> {
36 37
 	private final JavaSourceClass cls;
38
+	private final JavaNativeClass nativeClass;
37 39
 	
38
-	public JavaSourcePrepareExpansionMethodVisitor(JavaSourceClass cls) {
40
+	public JavaSourcePrepareExpansionMethodVisitor(JavaSourceClass cls, JavaNativeClass nativeClass) {
39 41
 		this.cls = cls;
42
+		this.nativeClass = nativeClass;
43
+		cls.empty = true;
40 44
 	}
41 45
 	
42 46
 	@Override
43 47
 	public Void visitConst(ConstMember member) {
44 48
 		member.setTag(JavaSourceField.class, new JavaSourceField(cls, member.name));
49
+		cls.empty = false;
45 50
 		return null;
46 51
 	}
47 52
 	
@@ -49,17 +54,19 @@ public class JavaSourcePrepareExpansionMethodVisitor implements MemberVisitor<Vo
49 54
 	public Void visitField(FieldMember member) {
50 55
 		// TODO: expansion fields
51 56
 		member.setTag(JavaSourceField.class, new JavaSourceField(cls, member.name));
57
+		cls.empty = false;
52 58
 		return null;
53 59
 	}
54 60
 
55 61
 	@Override
56 62
 	public Void visitConstructor(ConstructorMember member) {
63
+		visitFunctional(member, "");
57 64
 		return null;
58 65
 	}
59 66
 
60 67
 	@Override
61 68
 	public Void visitDestructor(DestructorMember member) {
62
-		return null;
69
+		throw new UnsupportedOperationException("Destructors not allowed on expansions");
63 70
 	}
64 71
 
65 72
 	@Override
@@ -107,24 +114,35 @@ public class JavaSourcePrepareExpansionMethodVisitor implements MemberVisitor<Vo
107 114
 	@Override
108 115
 	public Void visitImplementation(ImplementationMember member) {
109 116
 		// TODO: implementation merge check
117
+		cls.empty = false;
110 118
 		return null;
111 119
 	}
112 120
 
113 121
 	@Override
114 122
 	public Void visitInnerDefinition(InnerDefinitionMember member) {
115 123
 		// TODO
124
+		cls.empty = false;
116 125
 		return null;
117 126
 	}
118 127
 
119 128
 	@Override
120 129
 	public Void visitStaticInitializer(StaticInitializerMember member) {
130
+		cls.empty = false;
121 131
 		return null;
122 132
 	}
123 133
 	
124 134
 	private void visitFunctional(DefinitionMember member, String name) {
125
-		member.setTag(
126
-				JavaSourceMethod.class,
127
-				new JavaSourceMethod(cls, getKind(member), name));
135
+		NativeTag nativeTag = member.getTag(NativeTag.class);
136
+		JavaSourceMethod method = null;
137
+		if (nativeTag != null && nativeClass != null)
138
+			method = nativeClass.getMethod(nativeTag.value);
139
+		if (method == null)
140
+			method = new JavaSourceMethod(cls, getKind(member), name, true); 
141
+		
142
+		if (method.compile)
143
+			cls.empty = false;
144
+		
145
+		member.setTag(JavaSourceMethod.class, method);
128 146
 	}
129 147
 	
130 148
 	private JavaSourceMethod.Kind getKind(DefinitionMember member) {
@@ -196,7 +214,7 @@ public class JavaSourcePrepareExpansionMethodVisitor implements MemberVisitor<Vo
196 214
 			case CONTAINS:
197 215
 				return "contains";
198 216
 			case EQUALS:
199
-				return "equals";
217
+				return "equals_";
200 218
 			case COMPARE:
201 219
 				return "compareTo";
202 220
 			case RANGE:

+ 8
- 3
JavaSourceCompiler/src/main/java/org/openzen/zenscript/javasource/scope/JavaSourceFileScope.java View File

@@ -12,6 +12,7 @@ import org.openzen.zenscript.javasource.JavaSourceObjectTypeVisitor;
12 12
 import org.openzen.zenscript.javasource.JavaSourceSyntheticHelperGenerator;
13 13
 import org.openzen.zenscript.javasource.JavaSourceSyntheticTypeGenerator;
14 14
 import org.openzen.zenscript.javasource.JavaSourceTypeVisitor;
15
+import org.openzen.zenscript.javasource.tags.JavaSourceClass;
15 16
 
16 17
 /**
17 18
  *
@@ -21,7 +22,7 @@ public class JavaSourceFileScope {
21 22
 	public final JavaSourceImporter importer;
22 23
 	public final JavaSourceSyntheticTypeGenerator typeGenerator;
23 24
 	public final JavaSourceSyntheticHelperGenerator helperGenerator;
24
-	public final String className;
25
+	public final JavaSourceClass cls;
25 26
 	public final JavaSourceTypeVisitor typeVisitor;
26 27
 	public final JavaSourceObjectTypeVisitor objectTypeVisitor;
27 28
 	public final TypeScope semanticScope;
@@ -31,14 +32,14 @@ public class JavaSourceFileScope {
31 32
 			JavaSourceImporter importer, 
32 33
 			JavaSourceSyntheticTypeGenerator typeGenerator,
33 34
 			JavaSourceSyntheticHelperGenerator helperGenerator,
34
-			String className,
35
+			JavaSourceClass cls,
35 36
 			TypeScope semanticScope,
36 37
 			boolean isInterface)
37 38
 	{
38 39
 		this.importer = importer;
39 40
 		this.typeGenerator = typeGenerator;
40 41
 		this.helperGenerator = helperGenerator;
41
-		this.className = className;
42
+		this.cls = cls;
42 43
 		this.semanticScope = semanticScope;
43 44
 		this.isInterface = isInterface;
44 45
 		
@@ -49,4 +50,8 @@ public class JavaSourceFileScope {
49 50
 	public String type(ITypeID type) {
50 51
 		return type.accept(typeVisitor);
51 52
 	}
53
+	
54
+	public String type(ITypeID type, JavaSourceClass rename) {
55
+		return type.accept(new JavaSourceTypeVisitor(importer, typeGenerator, rename));
56
+	}
52 57
 }

+ 4
- 4
JavaSourceCompiler/src/main/java/org/openzen/zenscript/javasource/scope/JavaSourceStatementScope.java View File

@@ -74,12 +74,12 @@ public class JavaSourceStatementScope {
74 74
 		return fileScope.type(type);
75 75
 	}
76 76
 	
77
-	public String type(JavaSourceClass cls) {
78
-		return fileScope.importer.importType(cls.fullName);
77
+	public String type(ITypeID type, JavaSourceClass renamed) {
78
+		return fileScope.type(type, renamed);
79 79
 	}
80 80
 	
81
-	public String sourceClass(JavaSourceClass cls) {
82
-		return fileScope.importer.importType(cls.fullName);
81
+	public String type(JavaSourceClass cls) {
82
+		return fileScope.importer.importType(cls);
83 83
 	}
84 84
 	
85 85
 	public void addLocalVariable(String localVariable) {

+ 11
- 3
JavaSourceCompiler/src/main/java/org/openzen/zenscript/javasource/tags/JavaSourceClass.java View File

@@ -9,12 +9,20 @@ package org.openzen.zenscript.javasource.tags;
9 9
  *
10 10
  * @author Hoofdgebruiker
11 11
  */
12
-public class JavaSourceClass {
12
+public class JavaSourceClass implements Comparable<JavaSourceClass> {
13
+	public final String pkg;
13 14
 	public final String name;
14 15
 	public final String fullName;
16
+	public boolean empty = false;
15 17
 	
16
-	public JavaSourceClass(String name, String fullName) {
18
+	public JavaSourceClass(String pkg, String name) {
19
+		this.pkg = pkg;
17 20
 		this.name = name;
18
-		this.fullName = fullName;
21
+		this.fullName = pkg + '.' + name;
22
+	}
23
+
24
+	@Override
25
+	public int compareTo(JavaSourceClass o) {
26
+		return fullName.compareTo(o.fullName);
19 27
 	}
20 28
 }

+ 5
- 1
JavaSourceCompiler/src/main/java/org/openzen/zenscript/javasource/tags/JavaSourceMethod.java View File

@@ -15,12 +15,14 @@ public class JavaSourceMethod {
15 15
 	public final JavaSourceClass cls;
16 16
 	public final Kind kind;
17 17
 	public final String name;
18
+	public final boolean compile;
18 19
 	public final JavaCallCompiler compiler;
19 20
 	
20
-	public JavaSourceMethod(JavaSourceClass cls, Kind kind, String name) {
21
+	public JavaSourceMethod(JavaSourceClass cls, Kind kind, String name, boolean compile) {
21 22
 		this.cls = cls;
22 23
 		this.kind = kind;
23 24
 		this.name = name;
25
+		this.compile = compile;
24 26
 		compiler = null;
25 27
 	}
26 28
 	
@@ -28,6 +30,7 @@ public class JavaSourceMethod {
28 30
 		this.cls = null;
29 31
 		this.kind = Kind.COMPILED;
30 32
 		this.name = null;
33
+		this.compile = false;
31 34
 		this.compiler = compiler;
32 35
 	}
33 36
 	
@@ -35,6 +38,7 @@ public class JavaSourceMethod {
35 38
 		STATIC,
36 39
 		INSTANCE,
37 40
 		EXPANSION,
41
+		CONSTRUCTOR,
38 42
 		COMPILED
39 43
 	}
40 44
 }

+ 2
- 2
Shared/src/main/java/org/openzen/zenscript/shared/ConcatMap.java View File

@@ -47,7 +47,7 @@ public class ConcatMap<K, V> {
47 47
 	}
48 48
 	
49 49
 	public V get(K key) {
50
-		if (key == null)
50
+		if (this.key == null)
51 51
 			return null;
52 52
 		if (key.equals(this.key))
53 53
 			return value;
@@ -56,7 +56,7 @@ public class ConcatMap<K, V> {
56 56
 	}
57 57
 	
58 58
 	public V get(K key, V defaultValue) {
59
-		if (key == null)
59
+		if (this.key == null)
60 60
 			return defaultValue;
61 61
 		if (key.equals(this.key))
62 62
 			return value;

+ 4
- 1
Validator/src/main/java/org/openzen/zenscript/validator/ValidationLogEntry.java View File

@@ -63,6 +63,9 @@ public class ValidationLogEntry {
63 63
 		SETTING_FINAL_VARIABLE,
64 64
 		INVALID_SUPERTYPE,
65 65
 		MULTIPLE_DESTRUCTORS,
66
-		PANIC_ARGUMENT_NO_STRING
66
+		PANIC_ARGUMENT_NO_STRING,
67
+		THROW_WITHOUT_THROWS,
68
+		DESTRUCTOR_CANNOT_THROW,
69
+		STATIC_INITIALIZER_CANNOT_THROW
67 70
 	}
68 71
 }

+ 20
- 1
Validator/src/main/java/org/openzen/zenscript/validator/visitors/DefinitionMemberValidator.java View File

@@ -20,6 +20,7 @@ import org.openzen.zenscript.codemodel.member.CustomIteratorMember;
20 20
 import org.openzen.zenscript.codemodel.member.DestructorMember;
21 21
 import org.openzen.zenscript.codemodel.member.EnumConstantMember;
22 22
 import org.openzen.zenscript.codemodel.member.FieldMember;
23
+import org.openzen.zenscript.codemodel.member.FunctionalMember;
23 24
 import org.openzen.zenscript.codemodel.member.GetterMember;
24 25
 import org.openzen.zenscript.codemodel.member.IDefinitionMember;
25 26
 import org.openzen.zenscript.codemodel.member.ImplementationMember;
@@ -107,7 +108,8 @@ public class DefinitionMemberValidator implements MemberVisitor<Void> {
107 108
 		} else {
108 109
 			StatementValidator statementValidator = new StatementValidator(validator, new ConstructorStatementScope(member.header));
109 110
 			member.body.accept(statementValidator);
110
-			
111
+			validateThrow(member);
112
+				
111 113
 			if (member.definition.superType != null && !statementValidator.constructorForwarded) {
112 114
 				validator.logError(ValidationLogEntry.Code.CONSTRUCTOR_FORWARD_MISSING, member.position, "Constructor not forwarded to base type");
113 115
 			}
@@ -125,6 +127,10 @@ public class DefinitionMemberValidator implements MemberVisitor<Void> {
125 127
 		if (member.body != null) {
126 128
 			StatementValidator statementValidator = new StatementValidator(validator, new ConstructorStatementScope(member.header));
127 129
 			member.body.accept(statementValidator);
130
+			validateThrow(member);
131
+			
132
+			if (member.header.thrownType != null)
133
+				validator.logError(ValidationLogEntry.Code.DESTRUCTOR_CANNOT_THROW, member.position, "Destructor cannot throw");
128 134
 		}
129 135
 		return null;
130 136
 	}
@@ -137,6 +143,7 @@ public class DefinitionMemberValidator implements MemberVisitor<Void> {
137 143
 		if (member.body != null) {
138 144
 			StatementValidator statementValidator = new StatementValidator(validator, new ConstructorStatementScope(member.header));
139 145
 			member.body.accept(statementValidator);
146
+			validateThrow(member);
140 147
 		}
141 148
 		return null;
142 149
 	}
@@ -149,6 +156,7 @@ public class DefinitionMemberValidator implements MemberVisitor<Void> {
149 156
 		if (member.body != null) {
150 157
 			StatementValidator statementValidator = new StatementValidator(validator, new ConstructorStatementScope(member.header));
151 158
 			member.body.accept(statementValidator);
159
+			validateThrow(member);
152 160
 		}
153 161
 		
154 162
 		return null;
@@ -162,6 +170,7 @@ public class DefinitionMemberValidator implements MemberVisitor<Void> {
162 170
 		if (member.body != null) {
163 171
 			StatementValidator statementValidator = new StatementValidator(validator, new ConstructorStatementScope(member.header));
164 172
 			member.body.accept(statementValidator);
173
+			validateThrow(member);
165 174
 		}
166 175
 		
167 176
 		return null;
@@ -186,6 +195,7 @@ public class DefinitionMemberValidator implements MemberVisitor<Void> {
186 195
 		if (member.body != null) {
187 196
 			StatementValidator statementValidator = new StatementValidator(validator, new ConstructorStatementScope(member.header));
188 197
 			member.body.accept(statementValidator);
198
+			validateThrow(member);
189 199
 		}
190 200
 		
191 201
 		return null;
@@ -198,6 +208,7 @@ public class DefinitionMemberValidator implements MemberVisitor<Void> {
198 208
 		if (member.body != null) {
199 209
 			StatementValidator statementValidator = new StatementValidator(validator, new ConstructorStatementScope(member.header));
200 210
 			member.body.accept(statementValidator);
211
+			validateThrow(member);
201 212
 		}
202 213
 		
203 214
 		return null;
@@ -216,6 +227,7 @@ public class DefinitionMemberValidator implements MemberVisitor<Void> {
216 227
 		if (member.body != null) {
217 228
 			StatementValidator statementValidator = new StatementValidator(validator, new ConstructorStatementScope(member.header));
218 229
 			member.body.accept(statementValidator);
230
+			validateThrow(member);
219 231
 		}
220 232
 		
221 233
 		return null;
@@ -255,9 +267,16 @@ public class DefinitionMemberValidator implements MemberVisitor<Void> {
255 267
 	@Override
256 268
 	public Void visitStaticInitializer(StaticInitializerMember member) {
257 269
 		member.body.accept(new StatementValidator(validator, new StaticInitializerScope()));
270
+		if (member.body.thrownType != null)
271
+			validator.logError(ValidationLogEntry.Code.STATIC_INITIALIZER_CANNOT_THROW, member.position, "Static initializer cannot throw");
258 272
 		return null;
259 273
 	}
260 274
 	
275
+	private void validateThrow(FunctionalMember member) {
276
+		if (member.body.thrownType != null && member.header.thrownType == null) // TODO: validate thrown type
277
+			validator.logError(ValidationLogEntry.Code.THROW_WITHOUT_THROWS, member.position, "Method is throwing but doesn't declare throws type");
278
+	}
279
+	
261 280
 	private class FieldInitializerScope implements ExpressionScope {
262 281
 		private final FieldMember field;
263 282
 		

+ 1
- 1
Validator/src/main/java/org/openzen/zenscript/validator/visitors/ExpressionValidator.java View File

@@ -449,7 +449,7 @@ public class ExpressionValidator implements ExpressionVisitor<Void> {
449 449
 	@Override
450 450
 	public Void visitPanic(PanicExpression expression) {
451 451
 		expression.value.accept(this);
452
-		if (expression.type != BasicTypeID.STRING)
452
+		if (expression.value.type != BasicTypeID.STRING)
453 453
 			validator.logError(ValidationLogEntry.Code.PANIC_ARGUMENT_NO_STRING, expression.position, "Argument to a panic must be a string");
454 454
 		return null;
455 455
 	}

Loading…
Cancel
Save