Browse Source

- Function and method bodies are now single statements (which can, of course, be a BlockStatement), this simplifies code

- Function parameters are taggable, and Java parameter indices are now tagged on these parameters
- Improved constructor forwarding code
- Added handling for potential situations where multiple code blocks exist for the same script file (this can happen in generated code)
- Continue WIP on code formatting for definitions
Stan Hebben 6 years ago
parent
commit
6d97220a92
33 changed files with 716 additions and 332 deletions
  1. 22
    3
      CodeFormatter/src/main/java/org/openzen/zenscript/formatter/DefinitionFormatter.java
  2. 24
    0
      CodeFormatter/src/main/java/org/openzen/zenscript/formatter/FormattingSettings.java
  3. 178
    0
      CodeFormatter/src/main/java/org/openzen/zenscript/formatter/FormattingUtils.java
  4. 197
    0
      CodeFormatter/src/main/java/org/openzen/zenscript/formatter/MemberFormatter.java
  5. 1
    48
      CodeFormatter/src/main/java/org/openzen/zenscript/formatter/TypeFormatter.java
  6. 0
    6
      CodeModel/src/main/java/org/openzen/zenscript/codemodel/FunctionHeader.java
  7. 2
    2
      CodeModel/src/main/java/org/openzen/zenscript/codemodel/FunctionParameter.java
  8. 11
    0
      CodeModel/src/main/java/org/openzen/zenscript/codemodel/HighLevelDefinition.java
  9. 4
    4
      CodeModel/src/main/java/org/openzen/zenscript/codemodel/definition/FunctionDefinition.java
  10. 3
    4
      CodeModel/src/main/java/org/openzen/zenscript/codemodel/expression/FunctionExpression.java
  11. 19
    0
      CodeModel/src/main/java/org/openzen/zenscript/codemodel/member/ConstructorMember.java
  12. 2
    2
      CodeModel/src/main/java/org/openzen/zenscript/codemodel/member/CustomIteratorMember.java
  13. 2
    2
      CodeModel/src/main/java/org/openzen/zenscript/codemodel/member/FunctionalMember.java
  14. 0
    12
      CodeModel/src/main/java/org/openzen/zenscript/codemodel/statement/Statement.java
  15. 7
    1
      JavaBytecodeCompiler/src/main/java/org/openzen/zenscript/javabytecode/JavaClassInfo.java
  16. 5
    3
      JavaBytecodeCompiler/src/main/java/org/openzen/zenscript/javabytecode/JavaCompiler.java
  17. 0
    11
      JavaBytecodeCompiler/src/main/java/org/openzen/zenscript/javabytecode/JavaEnumInfo.java
  18. 18
    0
      JavaBytecodeCompiler/src/main/java/org/openzen/zenscript/javabytecode/JavaParameterInfo.java
  19. 28
    0
      JavaBytecodeCompiler/src/main/java/org/openzen/zenscript/javabytecode/compiler/CompilerUtils.java
  20. 16
    6
      JavaBytecodeCompiler/src/main/java/org/openzen/zenscript/javabytecode/compiler/JavaExpressionVisitor.java
  21. 31
    30
      JavaBytecodeCompiler/src/main/java/org/openzen/zenscript/javabytecode/compiler/JavaStatementVisitor.java
  22. 14
    3
      JavaBytecodeCompiler/src/main/java/org/openzen/zenscript/javabytecode/compiler/JavaWriter.java
  23. 58
    103
      JavaBytecodeCompiler/src/main/java/org/openzen/zenscript/javabytecode/compiler/definitions/JavaDefinitionVisitor.java
  24. 44
    36
      JavaBytecodeCompiler/src/main/java/org/openzen/zenscript/javabytecode/compiler/definitions/JavaMemberVisitor.java
  25. 2
    3
      Parser/src/main/java/org/openzen/zenscript/parser/expression/ParsedExpressionFunction.java
  26. 3
    4
      Parser/src/main/java/org/openzen/zenscript/parser/statements/ParsedEmptyFunctionBody.java
  27. 1
    2
      Parser/src/main/java/org/openzen/zenscript/parser/statements/ParsedFunctionBody.java
  28. 3
    8
      Parser/src/main/java/org/openzen/zenscript/parser/statements/ParsedLambdaFunctionBody.java
  29. 4
    2
      Parser/src/main/java/org/openzen/zenscript/parser/statements/ParsedStatement.java
  30. 5
    9
      Parser/src/main/java/org/openzen/zenscript/parser/statements/ParsedStatementsFunctionBody.java
  31. 1
    0
      Validator/src/main/java/org/openzen/zenscript/validator/ValidationLogEntry.java
  32. 10
    24
      Validator/src/main/java/org/openzen/zenscript/validator/visitors/DefinitionMemberValidator.java
  33. 1
    4
      Validator/src/main/java/org/openzen/zenscript/validator/visitors/DefinitionValidator.java

+ 22
- 3
CodeFormatter/src/main/java/org/openzen/zenscript/formatter/DefinitionFormatter.java View File

13
 import org.openzen.zenscript.codemodel.definition.FunctionDefinition;
13
 import org.openzen.zenscript.codemodel.definition.FunctionDefinition;
14
 import org.openzen.zenscript.codemodel.definition.InterfaceDefinition;
14
 import org.openzen.zenscript.codemodel.definition.InterfaceDefinition;
15
 import org.openzen.zenscript.codemodel.definition.StructDefinition;
15
 import org.openzen.zenscript.codemodel.definition.StructDefinition;
16
+import org.openzen.zenscript.codemodel.member.IDefinitionMember;
16
 
17
 
17
 /**
18
 /**
18
  *
19
  *
35
 		FormattingUtils.formatModifiers(output, definition.modifiers);
36
 		FormattingUtils.formatModifiers(output, definition.modifiers);
36
 		output.append("class ");
37
 		output.append("class ");
37
 		output.append(definition.name);
38
 		output.append(definition.name);
38
-		if (definition.genericParameters.length > 0) {
39
-			
40
-		}
39
+		FormattingUtils.formatTypeParameters(output, definition.genericParameters, typeFormatter);
41
 		output.append(" ");
40
 		output.append(" ");
42
 		if (definition.superType != null) {
41
 		if (definition.superType != null) {
43
 			output.append("extends ");
42
 			output.append("extends ");
44
 			output.append(definition.superType.accept(typeFormatter));
43
 			output.append(definition.superType.accept(typeFormatter));
45
 			output.append(" ");
44
 			output.append(" ");
46
 		}
45
 		}
46
+		if (settings.classBracketOnSameLine) {
47
+			output.append("{\n");
48
+		} else {
49
+			output.append("\n")
50
+					.append(indent)
51
+					.append("{\n")
52
+					.append(indent + settings.indent);
53
+		}
54
+		
55
+		for (IDefinitionMember member : definition.members) {
56
+			member.accept(new MemberFormatter(settings, output, indent + settings.indent, typeFormatter));
57
+		}
58
+		
59
+		output.append("}\n");
47
 		return null;
60
 		return null;
48
 	}
61
 	}
49
 
62
 
50
 	@Override
63
 	@Override
51
 	public Void visitInterface(InterfaceDefinition definition) {
64
 	public Void visitInterface(InterfaceDefinition definition) {
65
+		
52
 		return null;
66
 		return null;
53
 	}
67
 	}
54
 
68
 
64
 
78
 
65
 	@Override
79
 	@Override
66
 	public Void visitFunction(FunctionDefinition definition) {
80
 	public Void visitFunction(FunctionDefinition definition) {
81
+		FormattingUtils.formatModifiers(output, definition.modifiers);
82
+		output.append("function ");
83
+		output.append(definition.name);
84
+		FormattingUtils.formatHeader(output, settings, definition.header, typeFormatter);
85
+		FormattingUtils.formatBody(output, settings, indent, typeFormatter, definition.statement);
67
 		return null;
86
 		return null;
68
 	}
87
 	}
69
 
88
 

+ 24
- 0
CodeFormatter/src/main/java/org/openzen/zenscript/formatter/FormattingSettings.java View File

33
 	public final boolean loopBracketOnSameLine;
33
 	public final boolean loopBracketOnSameLine;
34
 	public final boolean tryCatchNewLine; // new line between } and catch or } and finally
34
 	public final boolean tryCatchNewLine; // new line between } and catch or } and finally
35
 	public final boolean tryCatchBracketOnSameLine;
35
 	public final boolean tryCatchBracketOnSameLine;
36
+	public final boolean classBracketOnSameLine;
37
+	public final boolean functionBracketOnSameLine;
38
+	public final boolean lambdaMethodOnSameLine;
36
 	
39
 	
37
 	public final String indent;
40
 	public final String indent;
38
 	
41
 	
58
 		loopBracketOnSameLine = builder.loopBracketOnSameLine;
61
 		loopBracketOnSameLine = builder.loopBracketOnSameLine;
59
 		tryCatchNewLine = builder.tryCatchNewLine;
62
 		tryCatchNewLine = builder.tryCatchNewLine;
60
 		tryCatchBracketOnSameLine = builder.tryCatchBracketOnSameLine;
63
 		tryCatchBracketOnSameLine = builder.tryCatchBracketOnSameLine;
64
+		classBracketOnSameLine = builder.classBracketOnSameLine;
65
+		functionBracketOnSameLine = builder.functionBracketOnSameLine;
66
+		lambdaMethodOnSameLine = builder.lambdaMethodOnSameLine;
61
 		
67
 		
62
 		if (useTabs) {
68
 		if (useTabs) {
63
 			indent = "\t";
69
 			indent = "\t";
159
 		private boolean loopBracketOnSameLine = true;
165
 		private boolean loopBracketOnSameLine = true;
160
 		private boolean tryCatchNewLine = true;
166
 		private boolean tryCatchNewLine = true;
161
 		private boolean tryCatchBracketOnSameLine = true;
167
 		private boolean tryCatchBracketOnSameLine = true;
168
+		private boolean classBracketOnSameLine = false;
169
+		private boolean functionBracketOnSameLine = false;
170
+		private boolean lambdaMethodOnSameLine = false;
162
 		
171
 		
163
 		public Builder showAnyInFunctionHeaders(boolean show) {
172
 		public Builder showAnyInFunctionHeaders(boolean show) {
164
 			showAnyInFunctionHeaders = show;
173
 			showAnyInFunctionHeaders = show;
265
 			return this;
274
 			return this;
266
 		}
275
 		}
267
 		
276
 		
277
+		public Builder classBracketOnSameLine(boolean sameLine) {
278
+			classBracketOnSameLine = sameLine;
279
+			return this;
280
+		}
281
+		
282
+		public Builder functionBracketOnSameLine(boolean sameLine) {
283
+			functionBracketOnSameLine = sameLine;
284
+			return this;
285
+		}
286
+		
287
+		public Builder lambdaMethodOnSameLine(boolean sameLine) {
288
+			lambdaMethodOnSameLine = sameLine;
289
+			return this;
290
+		}
291
+		
268
 		public FormattingSettings build() {
292
 		public FormattingSettings build() {
269
 			return new FormattingSettings(this);
293
 			return new FormattingSettings(this);
270
 		}
294
 		}

+ 178
- 0
CodeFormatter/src/main/java/org/openzen/zenscript/formatter/FormattingUtils.java View File

5
  */
5
  */
6
 package org.openzen.zenscript.formatter;
6
 package org.openzen.zenscript.formatter;
7
 
7
 
8
+import org.openzen.zenscript.codemodel.FunctionHeader;
9
+import org.openzen.zenscript.codemodel.FunctionParameter;
8
 import org.openzen.zenscript.codemodel.Modifiers;
10
 import org.openzen.zenscript.codemodel.Modifiers;
11
+import org.openzen.zenscript.codemodel.generic.GenericParameterBound;
12
+import org.openzen.zenscript.codemodel.generic.TypeParameter;
13
+import org.openzen.zenscript.codemodel.statement.BlockStatement;
14
+import org.openzen.zenscript.codemodel.statement.BreakStatement;
15
+import org.openzen.zenscript.codemodel.statement.ContinueStatement;
16
+import org.openzen.zenscript.codemodel.statement.DoWhileStatement;
17
+import org.openzen.zenscript.codemodel.statement.EmptyStatement;
18
+import org.openzen.zenscript.codemodel.statement.ExpressionStatement;
19
+import org.openzen.zenscript.codemodel.statement.ForeachStatement;
20
+import org.openzen.zenscript.codemodel.statement.IfStatement;
21
+import org.openzen.zenscript.codemodel.statement.LockStatement;
22
+import org.openzen.zenscript.codemodel.statement.ReturnStatement;
23
+import org.openzen.zenscript.codemodel.statement.Statement;
24
+import org.openzen.zenscript.codemodel.statement.StatementVisitor;
25
+import org.openzen.zenscript.codemodel.statement.ThrowStatement;
26
+import org.openzen.zenscript.codemodel.statement.TryCatchStatement;
27
+import org.openzen.zenscript.codemodel.statement.VarStatement;
28
+import org.openzen.zenscript.codemodel.statement.WhileStatement;
29
+import org.openzen.zenscript.codemodel.type.BasicTypeID;
9
 
30
 
10
 /**
31
 /**
11
  *
32
  *
40
 		if (Modifiers.isConstOptional(modifiers))
61
 		if (Modifiers.isConstOptional(modifiers))
41
 			output.append("const? ");
62
 			output.append("const? ");
42
 	}
63
 	}
64
+	
65
+	public static void formatHeader(StringBuilder result, FormattingSettings settings, FunctionHeader header, TypeFormatter typeFormatter) {
66
+		FormattingUtils.formatTypeParameters(result, header.typeParameters, typeFormatter);
67
+		result.append("(");
68
+		int parameterIndex = 0;
69
+		for (FunctionParameter parameter : header.parameters) {
70
+			if (parameterIndex > 0)
71
+				result.append(", ");
72
+			
73
+			result.append(parameter.name);
74
+			if (parameter.variadic)
75
+				result.append("...");
76
+			
77
+			if (!settings.showAnyInFunctionHeaders || parameter.type != BasicTypeID.ANY) {
78
+				result.append(" as ");
79
+				result.append(header.returnType.accept(typeFormatter));
80
+			}
81
+			
82
+			parameterIndex++;
83
+		}
84
+		result.append(")");
85
+		if (!settings.showAnyInFunctionHeaders || header.returnType != BasicTypeID.ANY) {
86
+			result.append(" as ");
87
+			result.append(header.returnType.accept(typeFormatter));
88
+		}
89
+	}
90
+	
91
+	public static void formatTypeParameters(StringBuilder result, TypeParameter[] parameters, TypeFormatter typeFormatter) {
92
+		if (parameters.length > 0) {
93
+			result.append("<");
94
+			int index = 0;
95
+			for (TypeParameter parameter : parameters) {
96
+				if (index > 0)
97
+					result.append(", ");
98
+				
99
+				result.append(parameter.name);
100
+				
101
+				if (parameter.bounds.size() > 0) {
102
+					for (GenericParameterBound bound : parameter.bounds) {
103
+						result.append(": ");
104
+						result.append(bound.accept(typeFormatter));
105
+					}
106
+				}
107
+				
108
+				index++;
109
+			}
110
+			result.append(">");
111
+		}
112
+	}
113
+	
114
+	public static void formatBody(StringBuilder output, FormattingSettings settings, String indent, TypeFormatter typeFormatter, Statement body) {
115
+		body.accept(new BodyFormatter(output, settings, indent, typeFormatter));
116
+	}
117
+	
118
+	private static class BodyFormatter implements StatementVisitor<Void> {
119
+		private final StringBuilder output;
120
+		private final FormattingSettings settings;
121
+		private final StatementFormatter statementFormatter;
122
+		private final String indent;
123
+		private final TypeFormatter typeFormatter;
124
+		
125
+		public BodyFormatter(StringBuilder output, FormattingSettings settings, String indent, TypeFormatter typeFormatter) {
126
+			this.output = output;
127
+			this.settings = settings;
128
+			this.indent = indent;
129
+			this.typeFormatter = typeFormatter;
130
+			
131
+			statementFormatter = new StatementFormatter(indent + settings.indent, settings, new ExpressionFormatter(settings, typeFormatter)); 
132
+		}
133
+
134
+		@Override
135
+		public Void visitBlock(BlockStatement statement) {
136
+			return statementFormatter.visitBlock(statement);
137
+		}
138
+
139
+		@Override
140
+		public Void visitBreak(BreakStatement statement) {
141
+			return statementFormatter.visitBreak(statement);
142
+		}
143
+
144
+		@Override
145
+		public Void visitContinue(ContinueStatement statement) {
146
+			return statementFormatter.visitContinue(statement);
147
+		}
148
+
149
+		@Override
150
+		public Void visitDoWhile(DoWhileStatement statement) {
151
+			return statementFormatter.visitDoWhile(statement);
152
+		}
153
+
154
+		@Override
155
+		public Void visitEmpty(EmptyStatement statement) {
156
+			output.append(";\n");
157
+			return null;
158
+		}
159
+
160
+		@Override
161
+		public Void visitExpression(ExpressionStatement statement) {
162
+			if (settings.lambdaMethodOnSameLine) {
163
+				output.append(" => ");
164
+			} else {
165
+				output.append("\n").append(indent).append(settings.indent).append("=> ");
166
+			}
167
+			
168
+			output.append(statement.expression.accept(new ExpressionFormatter(settings, typeFormatter)));
169
+			output.append(";");
170
+			return null;
171
+		}
172
+
173
+		@Override
174
+		public Void visitForeach(ForeachStatement statement) {
175
+			return statementFormatter.visitForeach(statement);
176
+		}
177
+
178
+		@Override
179
+		public Void visitIf(IfStatement statement) {
180
+			return statementFormatter.visitIf(statement);
181
+		}
182
+
183
+		@Override
184
+		public Void visitLock(LockStatement statement) {
185
+			return statementFormatter.visitLock(statement);
186
+		}
187
+
188
+		@Override
189
+		public Void visitReturn(ReturnStatement statement) {
190
+			if (settings.lambdaMethodOnSameLine) {
191
+				output.append(" => ");
192
+			} else {
193
+				output.append("\n").append(indent).append(settings.indent).append("=> ");
194
+			}
195
+			
196
+			output.append(statement.value.accept(new ExpressionFormatter(settings, typeFormatter)));
197
+			output.append(";");
198
+			return null;
199
+		}
200
+
201
+		@Override
202
+		public Void visitThrow(ThrowStatement statement) {
203
+			return statementFormatter.visitThrow(statement);
204
+		}
205
+
206
+		@Override
207
+		public Void visitTryCatch(TryCatchStatement statement) {
208
+			return statementFormatter.visitTryCatch(statement);
209
+		}
210
+
211
+		@Override
212
+		public Void visitVar(VarStatement statement) {
213
+			return statementFormatter.visitVar(statement);
214
+		}
215
+
216
+		@Override
217
+		public Void visitWhile(WhileStatement statement) {
218
+			return statementFormatter.visitWhile(statement);
219
+		}
220
+	}
43
 }
221
 }

+ 197
- 0
CodeFormatter/src/main/java/org/openzen/zenscript/formatter/MemberFormatter.java View File

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.formatter;
7
+
8
+import java.util.List;
9
+import org.openzen.zenscript.codemodel.Modifiers;
10
+import org.openzen.zenscript.codemodel.member.CallerMember;
11
+import org.openzen.zenscript.codemodel.member.CasterMember;
12
+import org.openzen.zenscript.codemodel.member.ConstructorMember;
13
+import org.openzen.zenscript.codemodel.member.CustomIteratorMember;
14
+import org.openzen.zenscript.codemodel.member.EnumConstantMember;
15
+import org.openzen.zenscript.codemodel.member.FieldMember;
16
+import org.openzen.zenscript.codemodel.member.GetterMember;
17
+import org.openzen.zenscript.codemodel.member.IDefinitionMember;
18
+import org.openzen.zenscript.codemodel.member.ImplementationMember;
19
+import org.openzen.zenscript.codemodel.member.InnerDefinitionMember;
20
+import org.openzen.zenscript.codemodel.member.MemberVisitor;
21
+import org.openzen.zenscript.codemodel.member.MethodMember;
22
+import org.openzen.zenscript.codemodel.member.OperatorMember;
23
+import org.openzen.zenscript.codemodel.member.SetterMember;
24
+import org.openzen.zenscript.codemodel.statement.ReturnStatement;
25
+import org.openzen.zenscript.codemodel.statement.Statement;
26
+
27
+/**
28
+ *
29
+ * @author Hoofdgebruiker
30
+ */
31
+public class MemberFormatter implements MemberVisitor<Void> {
32
+	private final FormattingSettings settings;
33
+	private final StringBuilder output;
34
+	private final String indent;
35
+	private final TypeFormatter typeFormatter;
36
+	
37
+	public MemberFormatter(FormattingSettings settings, StringBuilder output, String indent, TypeFormatter typeFormatter) {
38
+		this.settings = settings;
39
+		this.output = output;
40
+		this.indent = indent;
41
+		this.typeFormatter = typeFormatter;
42
+	}
43
+
44
+	@Override
45
+	public Void visitField(FieldMember member) {
46
+		FormattingUtils.formatModifiers(output, member.modifiers & ~Modifiers.FINAL);
47
+		output.append(member.isFinal() ? "val " : "var ")
48
+				.append(member.name)
49
+				.append(" as ")
50
+				.append(member.type.accept(typeFormatter));
51
+		
52
+		if (member.initializer != null) {
53
+			output.append(" = ")
54
+					.append(member.initializer.accept(new ExpressionFormatter(settings, typeFormatter)));
55
+		}
56
+		output.append(";").append("\n").append(indent);
57
+		return null;
58
+	}
59
+
60
+	@Override
61
+	public Void visitConstructor(ConstructorMember member) {
62
+		FormattingUtils.formatModifiers(output, member.modifiers & ~Modifiers.FINAL);
63
+		output.append("this");
64
+		FormattingUtils.formatHeader(output, settings, member.header, typeFormatter);
65
+		formatBody(member.body);
66
+		return null;
67
+	}
68
+
69
+	@Override
70
+	public Void visitMethod(MethodMember member) {
71
+		FormattingUtils.formatModifiers(output, member.modifiers & ~Modifiers.FINAL);
72
+		output.append(member.name);
73
+		FormattingUtils.formatHeader(output, settings, member.header, typeFormatter);
74
+		formatBody(member.body);
75
+		return null;
76
+	}
77
+
78
+	@Override
79
+	public Void visitGetter(GetterMember member) {
80
+		FormattingUtils.formatModifiers(output, member.modifiers & ~Modifiers.FINAL);
81
+		output.append("get ");
82
+		output.append(member.name);
83
+		output.append(" as ");
84
+		output.append(member.type.accept(typeFormatter));
85
+		formatBody(member.body);
86
+		return null;
87
+	}
88
+
89
+	@Override
90
+	public Void visitSetter(SetterMember member) {
91
+		FormattingUtils.formatModifiers(output, member.modifiers & ~Modifiers.FINAL);
92
+		output.append("set ");
93
+		output.append(member.name);
94
+		output.append(" as ");
95
+		output.append(member.type.accept(typeFormatter));
96
+		formatBody(member.body);
97
+		return null;
98
+	}
99
+
100
+	@Override
101
+	public Void visitEnumConstant(EnumConstantMember member) {
102
+		return null; // TODO: handle separately
103
+	}
104
+
105
+	@Override
106
+	public Void visitOperator(OperatorMember member) {
107
+		FormattingUtils.formatModifiers(output, member.modifiers & ~Modifiers.FINAL);
108
+		switch (member.operator) {
109
+			case ADD: output.append("+"); break;
110
+			case SUB: output.append("-"); break;
111
+			case MUL: output.append("*"); break;
112
+			case DIV: output.append("/"); break;
113
+			case MOD: output.append("%"); break;
114
+			case CAT: output.append("~"); break;
115
+			case OR: output.append("|"); break;
116
+			case AND: output.append("&"); break;
117
+			case XOR: output.append("^"); break;
118
+			case NEG: output.append("-"); break;
119
+			case NOT: output.append("!"); break;
120
+			case INDEXSET: output.append("[]="); break;
121
+			case INDEXGET: output.append("[]"); break;
122
+			case CONTAINS: output.append("in"); break;
123
+			case MEMBERGETTER: output.append("."); break;
124
+			case MEMBERSETTER: output.append(".="); break;
125
+			case EQUALS: output.append("=="); break;
126
+			case ADDASSIGN: output.append("+="); break;
127
+			case SUBASSIGN: output.append("-="); break;
128
+			case MULASSIGN: output.append("*="); break;
129
+			case DIVASSIGN: output.append("/="); break;
130
+			case MODASSIGN: output.append("%="); break;
131
+			case CATASSIGN: output.append("~="); break;
132
+			case ORASSIGN: output.append("|="); break;
133
+			case ANDASSIGN: output.append("&="); break;
134
+			case XORASSIGN: output.append("^="); break;
135
+	
136
+			case POST_INCREMENT: output.append("++"); break;
137
+			case POST_DECREMENT: output.append("--"); break;
138
+			default:
139
+				throw new UnsupportedOperationException("Unknown operator: " + member.operator);
140
+		}
141
+		FormattingUtils.formatHeader(output, settings, member.header, typeFormatter);
142
+		formatBody(member.body);
143
+		return null;
144
+	}
145
+
146
+	@Override
147
+	public Void visitCaster(CasterMember member) {
148
+		FormattingUtils.formatModifiers(output, member.modifiers & ~Modifiers.FINAL);
149
+		output.append(" as ");
150
+		output.append(member.toType.accept(typeFormatter));
151
+		formatBody(member.body);
152
+		return null;
153
+	}
154
+
155
+	@Override
156
+	public Void visitCustomIterator(CustomIteratorMember member) {
157
+		throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
158
+	}
159
+
160
+	@Override
161
+	public Void visitCaller(CallerMember member) {
162
+		FormattingUtils.formatModifiers(output, member.modifiers & ~Modifiers.FINAL);
163
+		FormattingUtils.formatHeader(output, settings, member.header, typeFormatter);
164
+		formatBody(member.body);
165
+		return null;
166
+	}
167
+
168
+	@Override
169
+	public Void visitImplementation(ImplementationMember implementation) {
170
+		FormattingUtils.formatModifiers(output, implementation.modifiers & ~Modifiers.FINAL);
171
+		output.append("implements ");
172
+		output.append(implementation.type.accept(typeFormatter));
173
+		if (settings.classBracketOnSameLine) {
174
+			output.append("{\n");
175
+		} else {
176
+			output.append("\n").append(indent).append("{\n");
177
+		}
178
+		
179
+		for (IDefinitionMember member : implementation.members) {
180
+			member.accept(new MemberFormatter(settings, output, indent + settings.indent, typeFormatter));
181
+		}
182
+		
183
+		output.append("}\n");
184
+		return null;
185
+	}
186
+
187
+	@Override
188
+	public Void visitInnerDefinition(InnerDefinitionMember member) {
189
+		String formatted = member.innerDefinition.accept(new DefinitionFormatter(settings, typeFormatter, indent + settings.indent)).toString();
190
+		output.append(formatted);
191
+		return null;
192
+	}
193
+	
194
+	private void formatBody(Statement body) {
195
+		FormattingUtils.formatBody(output, settings, indent, typeFormatter, body);
196
+	}
197
+}

+ 1
- 48
CodeFormatter/src/main/java/org/openzen/zenscript/formatter/TypeFormatter.java View File

68
 	public String visitFunction(FunctionTypeID function) {
68
 	public String visitFunction(FunctionTypeID function) {
69
 		StringBuilder result = new StringBuilder();
69
 		StringBuilder result = new StringBuilder();
70
 		result.append("function");
70
 		result.append("function");
71
-		
72
-		FunctionHeader header = function.header;
73
-		formatTypeParameters(result, header.typeParameters);
74
-		result.append("(");
75
-		int parameterIndex = 0;
76
-		for (FunctionParameter parameter : header.parameters) {
77
-			if (parameterIndex > 0)
78
-				result.append(", ");
79
-			
80
-			result.append(parameter.name);
81
-			if (parameter.variadic)
82
-				result.append("...");
83
-			
84
-			if (!settings.showAnyInFunctionHeaders || parameter.type != BasicTypeID.ANY) {
85
-				result.append(" as ");
86
-				result.append(header.returnType.accept(this));
87
-			}
88
-			
89
-			parameterIndex++;
90
-		}
91
-		result.append(")");
92
-		if (!settings.showAnyInFunctionHeaders || header.returnType != BasicTypeID.ANY) {
93
-			result.append(" as ");
94
-			result.append(header.returnType.accept(this));
95
-		}
71
+		FormattingUtils.formatHeader(result, settings, function.header, this);
96
 		return result.toString();
72
 		return result.toString();
97
 	}
73
 	}
98
 
74
 
135
 	public String visitOptional(OptionalTypeID optional) {
111
 	public String visitOptional(OptionalTypeID optional) {
136
 		return optional.baseType.accept(this) + "?";
112
 		return optional.baseType.accept(this) + "?";
137
 	}
113
 	}
138
-	
139
-	private void formatTypeParameters(StringBuilder result, TypeParameter[] parameters) {
140
-		if (parameters.length > 0) {
141
-			result.append("<");
142
-			int index = 0;
143
-			for (TypeParameter parameter : parameters) {
144
-				if (index > 0)
145
-					result.append(", ");
146
-				
147
-				result.append(parameter.name);
148
-				
149
-				if (parameter.bounds.size() > 0) {
150
-					for (GenericParameterBound bound : parameter.bounds) {
151
-						result.append(": ");
152
-						result.append(bound.accept(this));
153
-					}
154
-				}
155
-				
156
-				index++;
157
-			}
158
-			result.append(">");
159
-		}
160
-	}
161
 
114
 
162
 	@Override
115
 	@Override
163
 	public String visitSuper(ParameterSuperBound bound) {
116
 	public String visitSuper(ParameterSuperBound bound) {

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

38
 		this.typeParameters = NO_GENERIC_PARAMETERS;
38
 		this.typeParameters = NO_GENERIC_PARAMETERS;
39
 		this.returnType = returnType;
39
 		this.returnType = returnType;
40
 		this.parameters = parameters;
40
 		this.parameters = parameters;
41
-		
42
-		for (int i = 0; i < parameters.length; i++)
43
-			parameters[i].index = i;
44
 	}
41
 	}
45
 	
42
 	
46
 	public FunctionHeader(TypeParameter[] genericParameters, ITypeID returnType, FunctionParameter[] parameters) {
43
 	public FunctionHeader(TypeParameter[] genericParameters, ITypeID returnType, FunctionParameter[] parameters) {
47
 		this.typeParameters = genericParameters;
44
 		this.typeParameters = genericParameters;
48
 		this.returnType = returnType;
45
 		this.returnType = returnType;
49
 		this.parameters = parameters;
46
 		this.parameters = parameters;
50
-		
51
-		for (int i = 0; i < parameters.length; i++)
52
-			parameters[i].index = i;
53
 	}
47
 	}
54
 	
48
 	
55
 	public FunctionHeader instance(GlobalTypeRegistry registry, Map<TypeParameter, ITypeID> mapping) {
49
 	public FunctionHeader instance(GlobalTypeRegistry registry, Map<TypeParameter, ITypeID> mapping) {

+ 2
- 2
CodeModel/src/main/java/org/openzen/zenscript/codemodel/FunctionParameter.java View File

11
 import org.openzen.zenscript.codemodel.generic.TypeParameter;
11
 import org.openzen.zenscript.codemodel.generic.TypeParameter;
12
 import org.openzen.zenscript.codemodel.type.GlobalTypeRegistry;
12
 import org.openzen.zenscript.codemodel.type.GlobalTypeRegistry;
13
 import org.openzen.zenscript.codemodel.type.ITypeID;
13
 import org.openzen.zenscript.codemodel.type.ITypeID;
14
+import org.openzen.zenscript.shared.Taggable;
14
 
15
 
15
 /**
16
 /**
16
  *
17
  *
17
  * @author Hoofdgebruiker
18
  * @author Hoofdgebruiker
18
  */
19
  */
19
-public class FunctionParameter {
20
-	public int index = -1;
20
+public class FunctionParameter extends Taggable {
21
 	public final ITypeID type;
21
 	public final ITypeID type;
22
 	public final String name;
22
 	public final String name;
23
 	public final Expression defaultValue;
23
 	public final Expression defaultValue;

+ 11
- 0
CodeModel/src/main/java/org/openzen/zenscript/codemodel/HighLevelDefinition.java View File

10
 import org.openzen.zenscript.codemodel.definition.DefinitionVisitor;
10
 import org.openzen.zenscript.codemodel.definition.DefinitionVisitor;
11
 import org.openzen.zenscript.codemodel.definition.ZSPackage;
11
 import org.openzen.zenscript.codemodel.definition.ZSPackage;
12
 import org.openzen.zenscript.codemodel.generic.TypeParameter;
12
 import org.openzen.zenscript.codemodel.generic.TypeParameter;
13
+import org.openzen.zenscript.codemodel.member.EnumConstantMember;
13
 import org.openzen.zenscript.codemodel.member.FieldMember;
14
 import org.openzen.zenscript.codemodel.member.FieldMember;
14
 import org.openzen.zenscript.codemodel.member.IDefinitionMember;
15
 import org.openzen.zenscript.codemodel.member.IDefinitionMember;
15
 import org.openzen.zenscript.codemodel.type.ITypeID;
16
 import org.openzen.zenscript.codemodel.type.ITypeID;
63
 		for (IDefinitionMember member : members)
64
 		for (IDefinitionMember member : members)
64
 			if (member instanceof FieldMember)
65
 			if (member instanceof FieldMember)
65
 				fields.add((FieldMember)member);
66
 				fields.add((FieldMember)member);
67
+		
66
 		return fields;
68
 		return fields;
67
 	}
69
 	}
68
 	
70
 	
71
+	public List<EnumConstantMember> getEnumConstants() {
72
+		List<EnumConstantMember> enumMembers = new ArrayList<>();
73
+		for (IDefinitionMember member : members)
74
+            if (member instanceof EnumConstantMember)
75
+				enumMembers.add((EnumConstantMember) member);
76
+		
77
+		return enumMembers;
78
+	}
79
+	
69
 	public boolean isStatic() {
80
 	public boolean isStatic() {
70
 		return (modifiers & Modifiers.STATIC) > 0;
81
 		return (modifiers & Modifiers.STATIC) > 0;
71
 	}
82
 	}

+ 4
- 4
CodeModel/src/main/java/org/openzen/zenscript/codemodel/definition/FunctionDefinition.java View File

22
  */
22
  */
23
 public class FunctionDefinition extends HighLevelDefinition {
23
 public class FunctionDefinition extends HighLevelDefinition {
24
 	public FunctionHeader header;
24
 	public FunctionHeader header;
25
-	public List<Statement> statements;
25
+	public Statement statement;
26
 	public OperatorMember caller;
26
 	public OperatorMember caller;
27
 	public DefinitionMemberGroup callerGroup = new DefinitionMemberGroup();
27
 	public DefinitionMemberGroup callerGroup = new DefinitionMemberGroup();
28
 	
28
 	
41
 		callerGroup.addMethod(caller, TypeMemberPriority.SPECIFIED);
41
 		callerGroup.addMethod(caller, TypeMemberPriority.SPECIFIED);
42
 	}
42
 	}
43
 	
43
 	
44
-	public void setCode(List<Statement> statements) {
45
-		this.statements = statements;
46
-		caller.setBody(statements);
44
+	public void setCode(Statement statement) {
45
+		this.statement = statement;
46
+		caller.setBody(statement);
47
 	}
47
 	}
48
 
48
 
49
 	@Override
49
 	@Override

+ 3
- 4
CodeModel/src/main/java/org/openzen/zenscript/codemodel/expression/FunctionExpression.java View File

5
  */
5
  */
6
 package org.openzen.zenscript.codemodel.expression;
6
 package org.openzen.zenscript.codemodel.expression;
7
 
7
 
8
-import java.util.List;
9
 import org.openzen.zenscript.codemodel.FunctionHeader;
8
 import org.openzen.zenscript.codemodel.FunctionHeader;
10
 import org.openzen.zenscript.codemodel.statement.Statement;
9
 import org.openzen.zenscript.codemodel.statement.Statement;
11
 import org.openzen.zenscript.codemodel.type.FunctionTypeID;
10
 import org.openzen.zenscript.codemodel.type.FunctionTypeID;
18
 public class FunctionExpression extends Expression {
17
 public class FunctionExpression extends Expression {
19
 	public final FunctionHeader header;
18
 	public final FunctionHeader header;
20
 	public final LambdaClosure closure;
19
 	public final LambdaClosure closure;
21
-	public final List<Statement> statements;
20
+	public final Statement body;
22
 	
21
 	
23
 	public FunctionExpression(
22
 	public FunctionExpression(
24
 			CodePosition position,
23
 			CodePosition position,
25
 			FunctionTypeID type,
24
 			FunctionTypeID type,
26
 			LambdaClosure closure,
25
 			LambdaClosure closure,
27
-			List<Statement> statements) {
26
+			Statement body) {
28
 		super(position, type);
27
 		super(position, type);
29
 		
28
 		
30
 		this.header = type.header;
29
 		this.header = type.header;
31
 		this.closure = closure;
30
 		this.closure = closure;
32
-		this.statements = statements;
31
+		this.body = body;
33
 	}
32
 	}
34
 
33
 
35
 	@Override
34
 	@Override

+ 19
- 0
CodeModel/src/main/java/org/openzen/zenscript/codemodel/member/ConstructorMember.java View File

8
 import java.util.Map;
8
 import java.util.Map;
9
 import org.openzen.zenscript.codemodel.FunctionHeader;
9
 import org.openzen.zenscript.codemodel.FunctionHeader;
10
 import org.openzen.zenscript.codemodel.HighLevelDefinition;
10
 import org.openzen.zenscript.codemodel.HighLevelDefinition;
11
+import org.openzen.zenscript.codemodel.expression.ConstructorSuperCallExpression;
12
+import org.openzen.zenscript.codemodel.expression.ConstructorThisCallExpression;
11
 import org.openzen.zenscript.codemodel.generic.TypeParameter;
13
 import org.openzen.zenscript.codemodel.generic.TypeParameter;
14
+import org.openzen.zenscript.codemodel.statement.BlockStatement;
15
+import org.openzen.zenscript.codemodel.statement.ExpressionStatement;
12
 import org.openzen.zenscript.codemodel.type.BasicTypeID;
16
 import org.openzen.zenscript.codemodel.type.BasicTypeID;
13
 import org.openzen.zenscript.codemodel.type.GlobalTypeRegistry;
17
 import org.openzen.zenscript.codemodel.type.GlobalTypeRegistry;
14
 import org.openzen.zenscript.codemodel.type.ITypeID;
18
 import org.openzen.zenscript.codemodel.type.ITypeID;
24
 	public ConstructorMember(CodePosition position, HighLevelDefinition definition, int modifiers, FunctionHeader header) {
28
 	public ConstructorMember(CodePosition position, HighLevelDefinition definition, int modifiers, FunctionHeader header) {
25
 		super(position, definition, modifiers, "this", new FunctionHeader(header.typeParameters, BasicTypeID.VOID, header.parameters));
29
 		super(position, definition, modifiers, "this", new FunctionHeader(header.typeParameters, BasicTypeID.VOID, header.parameters));
26
 	}
30
 	}
31
+	
32
+	public boolean isConstructorForwarded() {
33
+		ExpressionStatement firstExpression = null;
34
+		if (body instanceof ExpressionStatement) {
35
+			firstExpression = (ExpressionStatement) body;
36
+		} else if (body instanceof BlockStatement) {
37
+			BlockStatement blockBody = (BlockStatement) body;
38
+			if (blockBody.statements.size() > 0 && blockBody.statements.get(0) instanceof ExpressionStatement)
39
+				firstExpression = (ExpressionStatement) blockBody.statements.get(0);
40
+		}
41
+		
42
+		return firstExpression != null && (
43
+				firstExpression.expression instanceof ConstructorSuperCallExpression
44
+				|| firstExpression.expression instanceof ConstructorThisCallExpression);
45
+	}
27
 
46
 
28
 	@Override
47
 	@Override
29
 	public void registerTo(TypeMembers type, TypeMemberPriority priority) {
48
 	public void registerTo(TypeMembers type, TypeMemberPriority priority) {

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

23
  */
23
  */
24
 public class CustomIteratorMember extends DefinitionMember implements IIteratorMember {
24
 public class CustomIteratorMember extends DefinitionMember implements IIteratorMember {
25
 	private final ITypeID[] iteratorTypes;
25
 	private final ITypeID[] iteratorTypes;
26
-	private List<Statement> content;
26
+	private Statement content;
27
 	
27
 	
28
 	public CustomIteratorMember(CodePosition position, HighLevelDefinition definition, int modifiers, ITypeID[] iteratorTypes) {
28
 	public CustomIteratorMember(CodePosition position, HighLevelDefinition definition, int modifiers, ITypeID[] iteratorTypes) {
29
 		super(position, definition, modifiers);
29
 		super(position, definition, modifiers);
31
 		this.iteratorTypes = iteratorTypes;
31
 		this.iteratorTypes = iteratorTypes;
32
 	}
32
 	}
33
 	
33
 	
34
-	public void setContent(List<Statement> content) {
34
+	public void setContent(Statement content) {
35
 		this.content = content;
35
 		this.content = content;
36
 	}
36
 	}
37
 
37
 

+ 2
- 2
CodeModel/src/main/java/org/openzen/zenscript/codemodel/member/FunctionalMember.java View File

24
 public abstract class FunctionalMember extends DefinitionMember implements ICallableMember {
24
 public abstract class FunctionalMember extends DefinitionMember implements ICallableMember {
25
 	public final FunctionHeader header;
25
 	public final FunctionHeader header;
26
 	public final String name;
26
 	public final String name;
27
-	public List<Statement> body;
27
+	public Statement body;
28
 	
28
 	
29
 	public FunctionalMember(CodePosition position, HighLevelDefinition definition, int modifiers, String name, FunctionHeader header) {
29
 	public FunctionalMember(CodePosition position, HighLevelDefinition definition, int modifiers, String name, FunctionHeader header) {
30
 		super(position, definition, modifiers);
30
 		super(position, definition, modifiers);
33
 		this.header = header;
33
 		this.header = header;
34
 	}
34
 	}
35
 	
35
 	
36
-	public void setBody(List<Statement> body) {
36
+	public void setBody(Statement body) {
37
 		this.body = body;
37
 		this.body = body;
38
 	}
38
 	}
39
 	
39
 	

+ 0
- 12
CodeModel/src/main/java/org/openzen/zenscript/codemodel/statement/Statement.java View File

33
 	
33
 	
34
 	public abstract <T> T accept(StatementVisitor<T> visitor);
34
 	public abstract <T> T accept(StatementVisitor<T> visitor);
35
 	
35
 	
36
-	public static ITypeID getReturnType(TypeScope scope, List<Statement> statements) {
37
-		ITypeID result = null;
38
-		for (Statement statement : statements) {
39
-			ITypeID statementType = statement.getReturnType();
40
-			if (result == null)
41
-				result = statementType;
42
-			else
43
-				result = scope.getTypeMembers(result).union(statementType);
44
-		}
45
-		return result;
46
-	}
47
-	
48
 	public static List<Statement> withReturnType(TypeScope scope, List<Statement> statements, ITypeID returnType) {
36
 	public static List<Statement> withReturnType(TypeScope scope, List<Statement> statements, ITypeID returnType) {
49
 		return statements.stream()
37
 		return statements.stream()
50
 				.map(statement -> statement.withReturnType(scope, returnType))
38
 				.map(statement -> statement.withReturnType(scope, returnType))

+ 7
- 1
JavaBytecodeCompiler/src/main/java/org/openzen/zenscript/javabytecode/JavaClassInfo.java View File

13
  */
13
  */
14
 public class JavaClassInfo {
14
 public class JavaClassInfo {
15
 	public static JavaClassInfo get(Class<?> cls) {
15
 	public static JavaClassInfo get(Class<?> cls) {
16
-		return new JavaClassInfo(Type.getInternalName(cls));
16
+		return new JavaClassInfo(Type.getInternalName(cls), cls.isEnum());
17
 	}
17
 	}
18
 	
18
 	
19
 	public final String internalClassName;
19
 	public final String internalClassName;
20
+	public final boolean isEnum;
20
 	
21
 	
21
 	public JavaClassInfo(String internalClassName) {
22
 	public JavaClassInfo(String internalClassName) {
23
+		this(internalClassName, false);
24
+	}
25
+	
26
+	public JavaClassInfo(String internalClassName, boolean isEnum) {
22
 		this.internalClassName = internalClassName;
27
 		this.internalClassName = internalClassName;
28
+		this.isEnum = isEnum;
23
 	}
29
 	}
24
 }
30
 }

+ 5
- 3
JavaBytecodeCompiler/src/main/java/org/openzen/zenscript/javabytecode/JavaCompiler.java View File

156
 		final SourceFile sourceFile = script.getTag(SourceFile.class);
156
 		final SourceFile sourceFile = script.getTag(SourceFile.class);
157
 		final String className = getClassName(sourceFile == null ? null : sourceFile.filename);
157
 		final String className = getClassName(sourceFile == null ? null : sourceFile.filename);
158
 		JavaScriptFile scriptFile = getScriptFile(className);
158
 		JavaScriptFile scriptFile = getScriptFile(className);
159
+		
160
+		String methodName = scriptFile.scriptMethods.isEmpty() ? "run" : "run" + scriptFile.scriptMethods.size();
159
 
161
 
160
 		// convert scripts into methods (add them to a Scripts class?)
162
 		// convert scripts into methods (add them to a Scripts class?)
161
 		// (TODO: can we break very long scripts into smaller methods? for the extreme scripts)
163
 		// (TODO: can we break very long scripts into smaller methods? for the extreme scripts)
162
 		final JavaClassWriter visitor = scriptFile.classWriter;
164
 		final JavaClassWriter visitor = scriptFile.classWriter;
163
-		JavaMethodInfo method = new JavaMethodInfo(new JavaClassInfo(className), "run", "()V", Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC);
165
+		JavaMethodInfo method = new JavaMethodInfo(new JavaClassInfo(className), methodName, "()V", Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC);
164
 		scriptFile.scriptMethods.add(method);
166
 		scriptFile.scriptMethods.add(method);
165
 		
167
 		
166
-		final JavaStatementVisitor statementVisitor = new JavaStatementVisitor(new JavaWriter(visitor, method, null, null));
168
+		final JavaStatementVisitor statementVisitor = new JavaStatementVisitor(new JavaWriter(visitor, method, null, null, null));
167
 		statementVisitor.start();
169
 		statementVisitor.start();
168
 		for (Statement statement : script.statements) {
170
 		for (Statement statement : script.statements) {
169
 			statement.accept(statementVisitor);
171
 			statement.accept(statementVisitor);
198
 		finished = true;
200
 		finished = true;
199
 		
201
 		
200
 		JavaMethodInfo runMethod = new JavaMethodInfo(new JavaClassInfo("Scripts"), "run", "()V", Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC);
202
 		JavaMethodInfo runMethod = new JavaMethodInfo(new JavaClassInfo("Scripts"), "run", "()V", Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC);
201
-		final JavaWriter runWriter = new JavaWriter(scriptsClassWriter, runMethod, null, null);
203
+		final JavaWriter runWriter = new JavaWriter(scriptsClassWriter, runMethod, null, null, null);
202
 		runWriter.start();
204
 		runWriter.start();
203
 		for (Map.Entry<String, JavaScriptFile> entry : scriptBlocks.entrySet()) {
205
 		for (Map.Entry<String, JavaScriptFile> entry : scriptBlocks.entrySet()) {
204
 			for (JavaMethodInfo method : entry.getValue().scriptMethods)
206
 			for (JavaMethodInfo method : entry.getValue().scriptMethods)

+ 0
- 11
JavaBytecodeCompiler/src/main/java/org/openzen/zenscript/javabytecode/JavaEnumInfo.java View File

1
-package org.openzen.zenscript.javabytecode;
2
-
3
-import org.openzen.zenscript.javabytecode.compiler.JavaStatementVisitor;
4
-
5
-public class JavaEnumInfo {
6
-    public final JavaStatementVisitor clinitVisitor;
7
-
8
-    public JavaEnumInfo(JavaStatementVisitor clinitVisitor) {
9
-        this.clinitVisitor = clinitVisitor;
10
-    }
11
-}

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

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.javabytecode;
7
+
8
+/**
9
+ *
10
+ * @author Hoofdgebruiker
11
+ */
12
+public class JavaParameterInfo {
13
+	public final int index;
14
+	
15
+	public JavaParameterInfo(int index) {
16
+		this.index = index;
17
+	}
18
+}

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

4
 import org.objectweb.asm.Type;
4
 import org.objectweb.asm.Type;
5
 import org.openzen.zenscript.codemodel.FunctionHeader;
5
 import org.openzen.zenscript.codemodel.FunctionHeader;
6
 import org.openzen.zenscript.codemodel.FunctionParameter;
6
 import org.openzen.zenscript.codemodel.FunctionParameter;
7
+import org.openzen.zenscript.codemodel.HighLevelDefinition;
7
 import org.openzen.zenscript.codemodel.Modifiers;
8
 import org.openzen.zenscript.codemodel.Modifiers;
9
+import org.openzen.zenscript.codemodel.member.FieldMember;
10
+import org.openzen.zenscript.codemodel.member.IDefinitionMember;
8
 import org.openzen.zenscript.codemodel.type.BasicTypeID;
11
 import org.openzen.zenscript.codemodel.type.BasicTypeID;
9
 import org.openzen.zenscript.codemodel.type.ITypeID;
12
 import org.openzen.zenscript.codemodel.type.ITypeID;
13
+import org.openzen.zenscript.javabytecode.JavaParameterInfo;
10
 import org.openzen.zenscript.shared.CodePosition;
14
 import org.openzen.zenscript.shared.CodePosition;
11
 
15
 
12
 public class CompilerUtils {
16
 public class CompilerUtils {
72
     public static String calcClasName(CodePosition position) {
76
     public static String calcClasName(CodePosition position) {
73
         return position.filename.substring(0, position.filename.lastIndexOf('.')).replace("/", "_");
77
         return position.filename.substring(0, position.filename.lastIndexOf('.')).replace("/", "_");
74
     }
78
     }
79
+	
80
+	public static void tagMethodParameters(FunctionHeader header, boolean isStatic) {
81
+		for (int i = 0; i < header.parameters.length; i++) {
82
+			header.parameters[i].setTag(JavaParameterInfo.class, new JavaParameterInfo(isStatic ? i : i + 1));
83
+		}
84
+	}
85
+	
86
+	public static void tagConstructorParameters(FunctionHeader header, boolean isEnum) {
87
+		for (int i = 0; i < header.parameters.length; i++) {
88
+			header.parameters[i].setTag(JavaParameterInfo.class, new JavaParameterInfo(isEnum ? i + 3 : i + 1));
89
+		}
90
+	}
91
+	
92
+	public static void writeDefaultFieldInitializers(JavaWriter constructorWriter, HighLevelDefinition definition) {
93
+		JavaExpressionVisitor expressionVisitor = new JavaExpressionVisitor(constructorWriter);
94
+		for (final IDefinitionMember definitionMember : definition.members) {
95
+			if (definitionMember instanceof FieldMember && ((FieldMember) definitionMember).initializer != null) {
96
+				final FieldMember field = (FieldMember) definitionMember;
97
+				constructorWriter.loadObject(0);
98
+				field.initializer.accept(expressionVisitor);
99
+				constructorWriter.putField(definition.name, field.name, Type.getDescriptor(field.type.accept(JavaTypeClassVisitor.INSTANCE)));
100
+			}
101
+		}
102
+	}
75
 }
103
 }

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

275
     @Override
275
     @Override
276
     public Void visitConstructorThisCall(ConstructorThisCallExpression expression) {
276
     public Void visitConstructorThisCall(ConstructorThisCallExpression expression) {
277
         Type type = expression.objectType.accept(JavaTypeVisitor.INSTANCE);
277
         Type type = expression.objectType.accept(JavaTypeVisitor.INSTANCE);
278
-        //javaWriter.loadObject(0);
278
+		
279
+		if (javaWriter.method.javaClass.isEnum) {
280
+			javaWriter.loadObject(0);
281
+			javaWriter.loadObject(1);
282
+			javaWriter.loadInt(2);
283
+		} else {
284
+			javaWriter.loadObject(0);
285
+		}
286
+		
279
         for (Expression argument : expression.arguments.arguments) {
287
         for (Expression argument : expression.arguments.arguments) {
280
             argument.accept(this);
288
             argument.accept(this);
281
         }
289
         }
282
-        javaWriter.invokeSpecial(type.getInternalName(), "<init>", CompilerUtils.calcDesc(expression.constructor.header, expression.constructor.hasTag(JavaEnumInfo.class)));
290
+        javaWriter.invokeSpecial(type.getInternalName(), "<init>", CompilerUtils.calcDesc(expression.constructor.header, javaWriter.method.javaClass.isEnum));
283
         return null;
291
         return null;
284
     }
292
     }
285
 
293
 
291
         }
299
         }
292
         //No super calls in enums possible, and that's already handled in the enum constructor itself.
300
         //No super calls in enums possible, and that's already handled in the enum constructor itself.
293
         javaWriter.invokeSpecial(expression.objectType.accept(JavaTypeClassVisitor.INSTANCE), "<init>", CompilerUtils.calcDesc(expression.constructor.header, false));
301
         javaWriter.invokeSpecial(expression.objectType.accept(JavaTypeClassVisitor.INSTANCE), "<init>", CompilerUtils.calcDesc(expression.constructor.header, false));
302
+		
303
+		CompilerUtils.writeDefaultFieldInitializers(javaWriter, javaWriter.forDefinition);
294
         return null;
304
         return null;
295
     }
305
     }
296
 
306
 
322
 
332
 
323
     @Override
333
     @Override
324
     public Void visitGetFunctionParameter(GetFunctionParameterExpression expression) {
334
     public Void visitGetFunctionParameter(GetFunctionParameterExpression expression) {
325
-        //TODO is Static?
326
-        final boolean isStatic = false;
327
-        javaWriter.load(Type.getType(expression.parameter.type.accept(JavaTypeClassVisitor.INSTANCE)), isStatic ? expression.parameter.index : expression.parameter.index + 1);
335
+		JavaParameterInfo parameter = expression.parameter.getTag(JavaParameterInfo.class);
336
+        javaWriter.load(Type.getType(expression.parameter.type.accept(JavaTypeClassVisitor.INSTANCE)), parameter.index);
328
         return null;
337
         return null;
329
     }
338
     }
330
 
339
 
473
     @Override
482
     @Override
474
     public Void visitSetFunctionParameter(SetFunctionParameterExpression expression) {
483
     public Void visitSetFunctionParameter(SetFunctionParameterExpression expression) {
475
         expression.value.accept(this);
484
         expression.value.accept(this);
476
-        javaWriter.store(expression.type.accept(JavaTypeVisitor.INSTANCE), javaWriter.method.isStatic() ? expression.parameter.index : expression.parameter.index + 1);
485
+		JavaParameterInfo parameter = expression.parameter.getTag(JavaParameterInfo.class);
486
+        javaWriter.store(expression.type.accept(JavaTypeVisitor.INSTANCE), parameter.index);
477
         return null;
487
         return null;
478
     }
488
     }
479
 
489
 

+ 31
- 30
JavaBytecodeCompiler/src/main/java/org/openzen/zenscript/javabytecode/compiler/JavaStatementVisitor.java View File

5
 import org.openzen.zenscript.codemodel.statement.*;
5
 import org.openzen.zenscript.codemodel.statement.*;
6
 import org.openzen.zenscript.javabytecode.JavaLocalVariableInfo;
6
 import org.openzen.zenscript.javabytecode.JavaLocalVariableInfo;
7
 
7
 
8
-public class JavaStatementVisitor implements StatementVisitor<Void> {
8
+public class JavaStatementVisitor implements StatementVisitor<Boolean> {
9
     private final JavaWriter javaWriter;
9
     private final JavaWriter javaWriter;
10
     public final JavaExpressionVisitor expressionVisitor;
10
     public final JavaExpressionVisitor expressionVisitor;
11
 	
11
 	
18
     }
18
     }
19
 
19
 
20
     @Override
20
     @Override
21
-    public Void visitBlock(BlockStatement statement) {
21
+    public Boolean visitBlock(BlockStatement statement) {
22
+		Boolean returns = false;
22
         for (Statement statement1 : statement.statements) {
23
         for (Statement statement1 : statement.statements) {
23
-            statement1.accept(this);
24
+            returns = statement1.accept(this);
24
         }
25
         }
25
-        return null;
26
+        return returns;
26
     }
27
     }
27
 
28
 
28
     @Override
29
     @Override
29
-    public Void visitBreak(BreakStatement statement) {
30
+    public Boolean visitBreak(BreakStatement statement) {
30
         javaWriter.goTo(javaWriter.getNamedLabel(statement.target.label + "_end"));
31
         javaWriter.goTo(javaWriter.getNamedLabel(statement.target.label + "_end"));
31
-        return null;
32
+        return false;
32
     }
33
     }
33
 
34
 
34
     @Override
35
     @Override
35
-    public Void visitContinue(ContinueStatement statement) {
36
+    public Boolean visitContinue(ContinueStatement statement) {
36
         javaWriter.goTo(javaWriter.getNamedLabel(statement.target.label + "_start"));
37
         javaWriter.goTo(javaWriter.getNamedLabel(statement.target.label + "_start"));
37
-        return null;
38
+        return false;
38
     }
39
     }
39
 
40
 
40
     @Override
41
     @Override
41
-    public Void visitDoWhile(DoWhileStatement statement) {
42
+    public Boolean visitDoWhile(DoWhileStatement statement) {
42
         Label start = new Label();
43
         Label start = new Label();
43
         Label end = new Label();
44
         Label end = new Label();
44
         if (statement.label == null)
45
         if (statement.label == null)
53
 
54
 
54
         //Only needed for break statements, should be nop if not used
55
         //Only needed for break statements, should be nop if not used
55
         javaWriter.label(end);
56
         javaWriter.label(end);
56
-        return null;
57
+        return false;
57
     }
58
     }
58
 
59
 
59
     @Override
60
     @Override
60
-    public Void visitEmpty(EmptyStatement statement) {
61
+    public Boolean visitEmpty(EmptyStatement statement) {
61
         //No-Op
62
         //No-Op
62
-        return null;
63
+        return false;
63
     }
64
     }
64
 
65
 
65
     @Override
66
     @Override
66
-    public Void visitExpression(ExpressionStatement statement) {
67
+    public Boolean visitExpression(ExpressionStatement statement) {
67
         statement.expression.accept(expressionVisitor);
68
         statement.expression.accept(expressionVisitor);
68
-        return null;
69
+        return false;
69
     }
70
     }
70
 
71
 
71
     @Override
72
     @Override
72
-    public Void visitForeach(ForeachStatement statement) {
73
+    public Boolean visitForeach(ForeachStatement statement) {
73
         //Create Labels
74
         //Create Labels
74
         Label start = new Label();
75
         Label start = new Label();
75
         Label end = new Label();
76
         Label end = new Label();
97
         statement.iterator.acceptForIterator(new JavaForeachVisitor(this, statement.loopVariables, statement.content, start, end));
98
         statement.iterator.acceptForIterator(new JavaForeachVisitor(this, statement.loopVariables, statement.content, start, end));
98
         javaWriter.goTo(start);
99
         javaWriter.goTo(start);
99
         javaWriter.label(end);
100
         javaWriter.label(end);
100
-        return null;
101
+        return false;
101
     }
102
     }
102
 
103
 
103
     @Override
104
     @Override
104
-    public Void visitIf(IfStatement statement) {
105
+    public Boolean visitIf(IfStatement statement) {
105
         statement.condition.accept(expressionVisitor);
106
         statement.condition.accept(expressionVisitor);
106
         Label onElse = null;
107
         Label onElse = null;
107
         Label end = new Label();
108
         Label end = new Label();
119
             statement.onElse.accept(this);
120
             statement.onElse.accept(this);
120
         }
121
         }
121
         javaWriter.label(end);
122
         javaWriter.label(end);
122
-        return null;
123
+        return false;
123
     }
124
     }
124
 
125
 
125
     @Override
126
     @Override
126
-    public Void visitLock(LockStatement statement) {
127
-        return null;
127
+    public Boolean visitLock(LockStatement statement) {
128
+        return false;
128
     }
129
     }
129
 
130
 
130
     @Override
131
     @Override
131
-    public Void visitReturn(ReturnStatement statement) {
132
+    public Boolean visitReturn(ReturnStatement statement) {
132
         statement.value.accept(expressionVisitor);
133
         statement.value.accept(expressionVisitor);
133
         javaWriter.returnType(Type.getType(statement.value.type.accept(JavaTypeClassVisitor.INSTANCE)));
134
         javaWriter.returnType(Type.getType(statement.value.type.accept(JavaTypeClassVisitor.INSTANCE)));
134
-        return null;
135
+        return true;
135
     }
136
     }
136
 
137
 
137
     @Override
138
     @Override
138
-    public Void visitThrow(ThrowStatement statement) {
139
+    public Boolean visitThrow(ThrowStatement statement) {
139
         statement.value.accept(expressionVisitor);
140
         statement.value.accept(expressionVisitor);
140
         javaWriter.aThrow();
141
         javaWriter.aThrow();
141
-        return null;
142
+        return false;
142
     }
143
     }
143
 
144
 
144
     @Override
145
     @Override
145
-    public Void visitTryCatch(TryCatchStatement statement) {
146
+    public Boolean visitTryCatch(TryCatchStatement statement) {
146
         final Label tryCatchStart = new Label();
147
         final Label tryCatchStart = new Label();
147
         final Label tryFinish = new Label();
148
         final Label tryFinish = new Label();
148
         final Label tryCatchFinish = new Label();
149
         final Label tryCatchFinish = new Label();
189
         }
190
         }
190
         javaWriter.label(tryCatchFinish);
191
         javaWriter.label(tryCatchFinish);
191
 
192
 
192
-        return null;
193
+        return false;
193
     }
194
     }
194
 
195
 
195
     @Override
196
     @Override
196
-    public Void visitVar(VarStatement statement) {
197
+    public Boolean visitVar(VarStatement statement) {
197
         Type type = statement.type.accept(JavaTypeVisitor.INSTANCE);
198
         Type type = statement.type.accept(JavaTypeVisitor.INSTANCE);
198
         int local = javaWriter.local(type);
199
         int local = javaWriter.local(type);
199
         if (statement.initializer != null) {
200
         if (statement.initializer != null) {
205
         final JavaLocalVariableInfo info = new JavaLocalVariableInfo(type, local, variableStart, statement.name);
206
         final JavaLocalVariableInfo info = new JavaLocalVariableInfo(type, local, variableStart, statement.name);
206
         statement.setTag(JavaLocalVariableInfo.class, info);
207
         statement.setTag(JavaLocalVariableInfo.class, info);
207
         javaWriter.addVariableInfo(info);
208
         javaWriter.addVariableInfo(info);
208
-        return null;
209
+        return false;
209
     }
210
     }
210
 
211
 
211
     @Override
212
     @Override
212
-    public Void visitWhile(WhileStatement statement) {
213
+    public Boolean visitWhile(WhileStatement statement) {
213
         Label start = new Label();
214
         Label start = new Label();
214
         Label end = new Label();
215
         Label end = new Label();
215
 
216
 
225
         statement.content.accept(this);
226
         statement.content.accept(this);
226
         javaWriter.goTo(start);
227
         javaWriter.goTo(start);
227
         javaWriter.label(end);
228
         javaWriter.label(end);
228
-        return null;
229
+        return false;
229
     }
230
     }
230
 
231
 
231
     public void start() {
232
     public void start() {

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

12
 import java.util.Map;
12
 import java.util.Map;
13
 
13
 
14
 import static org.objectweb.asm.Opcodes.*;
14
 import static org.objectweb.asm.Opcodes.*;
15
+import org.openzen.zenscript.codemodel.HighLevelDefinition;
15
 import org.openzen.zenscript.javabytecode.JavaClassInfo;
16
 import org.openzen.zenscript.javabytecode.JavaClassInfo;
16
 import org.openzen.zenscript.javabytecode.JavaMethodInfo;
17
 import org.openzen.zenscript.javabytecode.JavaMethodInfo;
17
 
18
 
24
 			Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC);
25
 			Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC);
25
 	
26
 	
26
 	public final JavaMethodInfo method;
27
 	public final JavaMethodInfo method;
28
+	public final HighLevelDefinition forDefinition;
27
 	
29
 	
28
     private final LocalVariablesSorter visitor;
30
     private final LocalVariablesSorter visitor;
29
     private final List<JavaLocalVariableInfo> localVariableInfos = new ArrayList<>();
31
     private final List<JavaLocalVariableInfo> localVariableInfos = new ArrayList<>();
32
     private int labelIndex = 1;
34
     private int labelIndex = 1;
33
     private Map<Label, String> labelNames = new HashMap<>();
35
     private Map<Label, String> labelNames = new HashMap<>();
34
 
36
 
35
-    public JavaWriter(ClassVisitor visitor, boolean nameVariables, JavaMethodInfo method, String signature, String[] exceptions, String... annotations) {
37
+    public JavaWriter(
38
+			ClassVisitor visitor,
39
+			boolean nameVariables,
40
+			JavaMethodInfo method,
41
+			HighLevelDefinition forDefinition,
42
+			String signature,
43
+			String[] exceptions,
44
+			String... annotations)
45
+	{
36
 		this.method = method;
46
 		this.method = method;
47
+		this.forDefinition = forDefinition;
37
 		
48
 		
38
         final MethodVisitor methodVisitor = visitor.visitMethod(method.modifiers, method.name, method.descriptor, signature, exceptions);
49
         final MethodVisitor methodVisitor = visitor.visitMethod(method.modifiers, method.name, method.descriptor, signature, exceptions);
39
 
50
 
45
         this.nameVariables = nameVariables;
56
         this.nameVariables = nameVariables;
46
     }
57
     }
47
 
58
 
48
-    public JavaWriter(ClassVisitor visitor, JavaMethodInfo method, String signature, String[] exceptions, String... annotations) {
49
-        this(visitor, true, method, signature, exceptions, annotations);
59
+    public JavaWriter(ClassVisitor visitor, JavaMethodInfo method, HighLevelDefinition forDefinition, String signature, String[] exceptions, String... annotations) {
60
+        this(visitor, true, method, forDefinition, signature, exceptions, annotations);
50
     }
61
     }
51
 
62
 
52
     private static String signature(Class aClass) {
63
     private static String signature(Class aClass) {

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

1
 package org.openzen.zenscript.javabytecode.compiler.definitions;
1
 package org.openzen.zenscript.javabytecode.compiler.definitions;
2
 
2
 
3
+import java.util.List;
3
 import org.objectweb.asm.ClassWriter;
4
 import org.objectweb.asm.ClassWriter;
4
 import org.objectweb.asm.Opcodes;
5
 import org.objectweb.asm.Opcodes;
5
 import org.objectweb.asm.Type;
6
 import org.objectweb.asm.Type;
6
-import org.openzen.zenscript.codemodel.FunctionParameter;
7
 import org.openzen.zenscript.codemodel.definition.*;
7
 import org.openzen.zenscript.codemodel.definition.*;
8
 import org.openzen.zenscript.codemodel.expression.Expression;
8
 import org.openzen.zenscript.codemodel.expression.Expression;
9
-import org.openzen.zenscript.codemodel.expression.ExpressionVisitor;
10
-import org.openzen.zenscript.codemodel.member.ConstructorMember;
11
 import org.openzen.zenscript.codemodel.member.EnumConstantMember;
9
 import org.openzen.zenscript.codemodel.member.EnumConstantMember;
12
-import org.openzen.zenscript.codemodel.member.FieldMember;
13
 import org.openzen.zenscript.codemodel.member.IDefinitionMember;
10
 import org.openzen.zenscript.codemodel.member.IDefinitionMember;
14
-import org.openzen.zenscript.codemodel.statement.ExpressionStatement;
15
-import org.openzen.zenscript.codemodel.statement.ReturnStatement;
16
-import org.openzen.zenscript.codemodel.statement.Statement;
17
 import org.openzen.zenscript.codemodel.type.BasicTypeID;
11
 import org.openzen.zenscript.codemodel.type.BasicTypeID;
18
 import org.openzen.zenscript.codemodel.type.ITypeID;
12
 import org.openzen.zenscript.codemodel.type.ITypeID;
19
 import org.openzen.zenscript.javabytecode.JavaClassInfo;
13
 import org.openzen.zenscript.javabytecode.JavaClassInfo;
20
-import org.openzen.zenscript.javabytecode.JavaEnumInfo;
21
 import org.openzen.zenscript.javabytecode.JavaMethodInfo;
14
 import org.openzen.zenscript.javabytecode.JavaMethodInfo;
22
 import org.openzen.zenscript.javabytecode.compiler.*;
15
 import org.openzen.zenscript.javabytecode.compiler.*;
23
 
16
 
24
-import java.util.Iterator;
25
 
17
 
26
 public class JavaDefinitionVisitor implements DefinitionVisitor<byte[]> {
18
 public class JavaDefinitionVisitor implements DefinitionVisitor<byte[]> {
27
 	private static final JavaClassInfo T_CLASS = new JavaClassInfo("java/lang/Class");
19
 	private static final JavaClassInfo T_CLASS = new JavaClassInfo("java/lang/Class");
65
 
57
 
66
         writer.visit(Opcodes.V1_8, definition.modifiers, definition.name, signature, superType.getInternalName(), null);
58
         writer.visit(Opcodes.V1_8, definition.modifiers, definition.name, signature, superType.getInternalName(), null);
67
         for (IDefinitionMember member : definition.members) {
59
         for (IDefinitionMember member : definition.members) {
68
-            if (member instanceof ConstructorMember) {
69
-                final ConstructorMember constructorMember = (ConstructorMember) member;
70
-                constructorMember.body.add(0, new ExpressionStatement(constructorMember.position, new Expression(constructorMember.position, BasicTypeID.VOID) {
71
-                    @Override
72
-                    public <T> T accept(ExpressionVisitor<T> visitor) {
73
-                        if (visitor instanceof JavaExpressionVisitor) {
74
-                            JavaWriter javaWriter = ((JavaExpressionVisitor) visitor).getJavaWriter();
75
-                            javaWriter.loadObject(0);
76
-                            //TODO Super constructor?
77
-                            javaWriter.invokeSpecial(Type.getInternalName(Object.class), "<init>", "()V");
78
-                            for (final IDefinitionMember definitionMember : definition.members) {
79
-                                if (definitionMember instanceof FieldMember && ((FieldMember) definitionMember).initializer != null) {
80
-                                    final FieldMember field = (FieldMember) definitionMember;
81
-                                    javaWriter.loadObject(0);
82
-                                    field.initializer.accept(visitor);
83
-                                    javaWriter.putField(definition.name, field.name, Type.getDescriptor(field.type.accept(JavaTypeClassVisitor.INSTANCE)));
84
-                                }
85
-                            }
86
-                        }
87
-                        return null;
88
-                    }
89
-                }));
90
-            }
91
-			
92
-            member.accept(new JavaMemberVisitor(writer, toClass));
60
+            member.accept(new JavaMemberVisitor(writer, toClass, definition));
93
         }
61
         }
94
         writer.visitEnd();
62
         writer.visitEnd();
95
         return writer.toByteArray();
63
         return writer.toByteArray();
105
         String signature = null;
73
         String signature = null;
106
         writer.visit(Opcodes.V1_8, definition.modifiers | Opcodes.ACC_INTERFACE | Opcodes.ACC_ABSTRACT, definition.name, signature, Type.getInternalName(Object.class), null);
74
         writer.visit(Opcodes.V1_8, definition.modifiers | Opcodes.ACC_INTERFACE | Opcodes.ACC_ABSTRACT, definition.name, signature, Type.getInternalName(Object.class), null);
107
         for (IDefinitionMember member : definition.members) {
75
         for (IDefinitionMember member : definition.members) {
108
-            member.accept(new JavaMemberVisitor(writer, toClass));
76
+            member.accept(new JavaMemberVisitor(writer, toClass, definition));
109
         }
77
         }
110
         writer.visitEnd();
78
         writer.visitEnd();
111
         return writer.toByteArray();
79
         return writer.toByteArray();
113
 
81
 
114
     @Override
82
     @Override
115
     public byte[] visitEnum(EnumDefinition definition) {
83
     public byte[] visitEnum(EnumDefinition definition) {
84
+		System.out.println("Compiling enum " + definition.name + " in " + definition.position.filename);
85
+		
116
         final Type superType;
86
         final Type superType;
117
         if (definition.superType == null)
87
         if (definition.superType == null)
118
             superType = Type.getType(Object.class);
88
             superType = Type.getType(Object.class);
127
             if (member instanceof EnumConstantMember) {
97
             if (member instanceof EnumConstantMember) {
128
                 EnumConstantMember constantMember = (EnumConstantMember) member;
98
                 EnumConstantMember constantMember = (EnumConstantMember) member;
129
                 writer.visitField(Opcodes.ACC_STATIC | Opcodes.ACC_PUBLIC | Opcodes.ACC_FINAL | Opcodes.ACC_ENUM, constantMember.name, "L" + definition.name + ";", null, null).visitEnd();
99
                 writer.visitField(Opcodes.ACC_STATIC | Opcodes.ACC_PUBLIC | Opcodes.ACC_FINAL | Opcodes.ACC_ENUM, constantMember.name, "L" + definition.name + ";", null, null).visitEnd();
130
-            } else if (member instanceof ConstructorMember) {
131
-                member.setTag(JavaEnumInfo.class, null);
132
             }
100
             }
133
         }
101
         }
134
 
102
 
135
-		JavaClassInfo toClass = new JavaClassInfo(definition.name);
136
-		JavaMethodInfo clinitInfo = new JavaMethodInfo(toClass, "<clinit>", "()V", Opcodes.ACC_STATIC);
137
-        final JavaWriter clinitWriter = new JavaWriter(writer, clinitInfo, null, null);
138
-        final JavaStatementVisitor clinitVisitor = new JavaStatementVisitor(clinitWriter);
139
-        clinitVisitor.start();
140
-        int constantCount = 0;
141
-        for (IDefinitionMember member : definition.members) {
142
-            if (member instanceof ConstructorMember) {
143
-                final ConstructorMember constructorMember = (ConstructorMember) member;
144
-
145
-
146
-                constructorMember.body.add(0, new ExpressionStatement(constructorMember.position, new Expression(constructorMember.position, BasicTypeID.VOID) {
147
-                    @Override
148
-                    public <T> T accept(ExpressionVisitor<T> visitor) {
149
-                        if (visitor instanceof JavaExpressionVisitor) {
150
-                            JavaWriter javaWriter = ((JavaExpressionVisitor) visitor).getJavaWriter();
151
-                            javaWriter.getVisitor().newLocal(Type.getType(String.class));
152
-                            javaWriter.getVisitor().newLocal(Type.getType(int.class));
153
-                            javaWriter.loadObject(0);
154
-                            javaWriter.loadObject(1);
155
-                            javaWriter.loadInt(2);
156
-                            //javaWriter.invokeSpecial(Type.getInternalName(Enum.class), "<init>", "(Ljava/lang/String;I)V");
157
-                        }
158
-                        return null;
159
-                    }
160
-                }));
161
-            } else if (member instanceof EnumConstantMember) {
162
-                ++constantCount;
163
-                member.setTag(JavaEnumInfo.class, new JavaEnumInfo(clinitVisitor));
164
-            }
165
-            member.accept(new JavaMemberVisitor(writer, toClass));
166
-        }
167
-
168
-        clinitWriter.constant(constantCount);
169
-        clinitWriter.newArray(Type.getType("L" + definition.name + ";"));
170
-
171
-        for (IDefinitionMember member : definition.members) {
172
-            if (!(member instanceof EnumConstantMember)) continue;
173
-            final EnumConstantMember constantMember = (EnumConstantMember) member;
174
-            clinitWriter.dup();
175
-            clinitWriter.constant(constantMember.value);
176
-            clinitWriter.getStaticField(definition.name, constantMember.name, "L" + definition.name + ";");
177
-            clinitWriter.arrayStore(Type.getType("L" + definition.name + ";"));
178
-        }
179
-        clinitWriter.putStaticField(definition.name, "$VALUES", "[L" + definition.name + ";");
180
-        clinitVisitor.end();
103
+		JavaClassInfo toClass = new JavaClassInfo(definition.name, true);
104
+		writeEnumStaticInitializer(definition, toClass, writer);
181
 
105
 
182
         //Enum Stuff(required!)
106
         //Enum Stuff(required!)
183
         writer.visitField(Opcodes.ACC_STATIC | Opcodes.ACC_PRIVATE | Opcodes.ACC_FINAL | Opcodes.ACC_SYNTHETIC, "$VALUES", "[L" + definition.name + ";", null, null).visitEnd();
107
         writer.visitField(Opcodes.ACC_STATIC | Opcodes.ACC_PRIVATE | Opcodes.ACC_FINAL | Opcodes.ACC_SYNTHETIC, "$VALUES", "[L" + definition.name + ";", null, null).visitEnd();
184
 		
108
 		
109
+        for (IDefinitionMember member : definition.members) {
110
+            member.accept(new JavaMemberVisitor(writer, toClass, definition));
111
+        }
112
+		
185
 		JavaClassInfo arrayClass = new JavaClassInfo("[L" + definition.name + ";");
113
 		JavaClassInfo arrayClass = new JavaClassInfo("[L" + definition.name + ";");
186
 		JavaMethodInfo arrayClone = new JavaMethodInfo(arrayClass, "clone", "()Ljava/lang/Object;", Opcodes.ACC_PUBLIC);
114
 		JavaMethodInfo arrayClone = new JavaMethodInfo(arrayClass, "clone", "()Ljava/lang/Object;", Opcodes.ACC_PUBLIC);
187
 
115
 
188
 		JavaMethodInfo valuesMethodInfo = new JavaMethodInfo(toClass, "values", "()[L" + definition.name + ";", Opcodes.ACC_STATIC | Opcodes.ACC_PUBLIC);
116
 		JavaMethodInfo valuesMethodInfo = new JavaMethodInfo(toClass, "values", "()[L" + definition.name + ";", Opcodes.ACC_STATIC | Opcodes.ACC_PUBLIC);
189
-        JavaWriter valuesWriter = new JavaWriter(writer, true, valuesMethodInfo, null, null);
117
+        JavaWriter valuesWriter = new JavaWriter(writer, true, valuesMethodInfo, definition, null, null);
190
         valuesWriter.start();
118
         valuesWriter.start();
191
         valuesWriter.getStaticField(definition.name, "$VALUES", "[L" + definition.name + ";");
119
         valuesWriter.getStaticField(definition.name, "$VALUES", "[L" + definition.name + ";");
192
         valuesWriter.invokeVirtual(arrayClone);
120
         valuesWriter.invokeVirtual(arrayClone);
195
         valuesWriter.end();
123
         valuesWriter.end();
196
 
124
 
197
 		JavaMethodInfo valueOfMethodInfo = new JavaMethodInfo(toClass, "valueOf", "(Ljava/lang/String;)L" + definition.name + ";", Opcodes.ACC_STATIC | Opcodes.ACC_PUBLIC);
125
 		JavaMethodInfo valueOfMethodInfo = new JavaMethodInfo(toClass, "valueOf", "(Ljava/lang/String;)L" + definition.name + ";", Opcodes.ACC_STATIC | Opcodes.ACC_PUBLIC);
198
-        JavaWriter valueOfWriter = new JavaWriter(writer, true, valueOfMethodInfo, null, null);
126
+        JavaWriter valueOfWriter = new JavaWriter(writer, true, valueOfMethodInfo, definition, null, null);
199
         valueOfWriter.start();
127
         valueOfWriter.start();
200
         valueOfWriter.invokeStatic(CLASS_FORNAME);
128
         valueOfWriter.invokeStatic(CLASS_FORNAME);
201
         valueOfWriter.loadObject(0);
129
         valueOfWriter.loadObject(0);
208
         writer.visitEnd();
136
         writer.visitEnd();
209
         return writer.toByteArray();
137
         return writer.toByteArray();
210
     }
138
     }
139
+	
140
+	private void writeEnumStaticInitializer(EnumDefinition definition, JavaClassInfo toClass, ClassWriter writer) {
141
+		JavaMethodInfo clinitInfo = new JavaMethodInfo(toClass, "<clinit>", "()V", Opcodes.ACC_STATIC);
142
+        final JavaWriter clinitWriter = new JavaWriter(writer, clinitInfo, definition, null, null);
143
+        final JavaStatementVisitor clinitVisitor = new JavaStatementVisitor(clinitWriter);
144
+        clinitVisitor.start();
145
+		
146
+		List<EnumConstantMember> enumConstants = definition.getEnumConstants();
147
+		for (EnumConstantMember enumConstant : enumConstants) {
148
+			final String internalName = enumConstant.constructor.type.accept(JavaTypeVisitor.INSTANCE).getInternalName();
149
+
150
+			clinitWriter.newObject(internalName);
151
+			clinitWriter.dup();
152
+			clinitWriter.constant(enumConstant.name);
153
+			clinitWriter.constant(enumConstant.value);
154
+			for (Expression argument : enumConstant.constructor.arguments.arguments) {
155
+				argument.accept(clinitVisitor.expressionVisitor);
156
+			}
157
+			clinitWriter.invokeSpecial(internalName, "<init>", CompilerUtils.calcDesc(enumConstant.constructor.constructor.header, true));
158
+			clinitWriter.putStaticField(internalName, enumConstant.name, "L" + internalName + ";");
159
+		}
160
+
161
+        clinitWriter.constant(enumConstants.size());
162
+        clinitWriter.newArray(Type.getType("L" + definition.name + ";"));
163
+
164
+        for (EnumConstantMember enumConstant : enumConstants) {
165
+            clinitWriter.dup();
166
+            clinitWriter.constant(enumConstant.value);
167
+            clinitWriter.getStaticField(definition.name, enumConstant.name, "L" + definition.name + ";");
168
+            clinitWriter.arrayStore(Type.getType("L" + definition.name + ";"));
169
+        }
170
+        clinitWriter.putStaticField(definition.name, "$VALUES", "[L" + definition.name + ";");
171
+        clinitVisitor.end();
172
+	}
211
 
173
 
212
     @Override
174
     @Override
213
     public byte[] visitStruct(StructDefinition definition) {
175
     public byte[] visitStruct(StructDefinition definition) {
216
 
178
 
217
     @Override
179
     @Override
218
     public byte[] visitFunction(FunctionDefinition definition) {
180
     public byte[] visitFunction(FunctionDefinition definition) {
181
+		CompilerUtils.tagMethodParameters(definition.header, true);
182
+		
219
         final String signature = CompilerUtils.calcSign(definition.header, false);
183
         final String signature = CompilerUtils.calcSign(definition.header, false);
220
 		
184
 		
221
 		final JavaClassInfo toClass = new JavaClassInfo(CompilerUtils.calcClasName(definition.position));
185
 		final JavaClassInfo toClass = new JavaClassInfo(CompilerUtils.calcClasName(definition.position));
222
 		final JavaMethodInfo methodInfo = new JavaMethodInfo(toClass, definition.name, CompilerUtils.calcDesc(definition.header, false), CompilerUtils.calcAccess(definition.modifiers) | Opcodes.ACC_STATIC);
186
 		final JavaMethodInfo methodInfo = new JavaMethodInfo(toClass, definition.name, CompilerUtils.calcDesc(definition.header, false), CompilerUtils.calcAccess(definition.modifiers) | Opcodes.ACC_STATIC);
223
 
187
 
224
-		final JavaWriter writer = new JavaWriter(outerWriter, true, methodInfo, signature, null);
188
+		final JavaWriter writer = new JavaWriter(outerWriter, true, methodInfo, definition, signature, null);
225
         final JavaStatementVisitor statementVisitor = new JavaStatementVisitor(writer);
189
         final JavaStatementVisitor statementVisitor = new JavaStatementVisitor(writer);
226
         statementVisitor.start();
190
         statementVisitor.start();
227
-        final Iterator<Statement> statementIterator = definition.statements.iterator();
228
-
229
-        //TODO this is dirty, fix when there is a way of knowing if a parameter is static or not
230
-        for (FunctionParameter parameter : definition.header.parameters) {
231
-            parameter.index -= 1;
232
-        }
233
-        while (statementIterator.hasNext()) {
234
-            final Statement statement = statementIterator.next();
235
-            statement.accept(statementVisitor);
236
-            if (!statementIterator.hasNext() && !(statement instanceof ReturnStatement)) {
237
-                ITypeID type = definition.header.returnType;
238
-                if (CompilerUtils.isPrimitive(type))
239
-                    writer.iConst0();
240
-                else if (type != BasicTypeID.VOID)
241
-                    writer.aConstNull();
242
-                writer.returnType(type.accept(JavaTypeVisitor.INSTANCE));
243
-            }
191
+		boolean returns = definition.statement.accept(statementVisitor);
192
+		if (!returns) {
193
+			ITypeID type = definition.header.returnType;
194
+			if (CompilerUtils.isPrimitive(type))
195
+				writer.iConst0();
196
+			else if (type != BasicTypeID.VOID)
197
+				writer.aConstNull();
198
+			writer.returnType(type.accept(JavaTypeVisitor.INSTANCE));
244
         }
199
         }
245
 
200
 
246
         statementVisitor.end();
201
         statementVisitor.end();

+ 44
- 36
JavaBytecodeCompiler/src/main/java/org/openzen/zenscript/javabytecode/compiler/definitions/JavaMemberVisitor.java View File

5
 import org.objectweb.asm.Opcodes;
5
 import org.objectweb.asm.Opcodes;
6
 import org.objectweb.asm.Type;
6
 import org.objectweb.asm.Type;
7
 import org.openzen.zenscript.codemodel.FunctionParameter;
7
 import org.openzen.zenscript.codemodel.FunctionParameter;
8
+import org.openzen.zenscript.codemodel.HighLevelDefinition;
8
 import org.openzen.zenscript.codemodel.Modifiers;
9
 import org.openzen.zenscript.codemodel.Modifiers;
9
-import org.openzen.zenscript.codemodel.expression.Expression;
10
+import org.openzen.zenscript.codemodel.definition.EnumDefinition;
10
 import org.openzen.zenscript.codemodel.member.*;
11
 import org.openzen.zenscript.codemodel.member.*;
11
-import org.openzen.zenscript.codemodel.statement.Statement;
12
 import org.openzen.zenscript.javabytecode.JavaClassInfo;
12
 import org.openzen.zenscript.javabytecode.JavaClassInfo;
13
-import org.openzen.zenscript.javabytecode.JavaEnumInfo;
14
 import org.openzen.zenscript.javabytecode.JavaFieldInfo;
13
 import org.openzen.zenscript.javabytecode.JavaFieldInfo;
15
 import org.openzen.zenscript.javabytecode.JavaMethodInfo;
14
 import org.openzen.zenscript.javabytecode.JavaMethodInfo;
15
+import org.openzen.zenscript.javabytecode.JavaParameterInfo;
16
 import org.openzen.zenscript.javabytecode.compiler.*;
16
 import org.openzen.zenscript.javabytecode.compiler.*;
17
 
17
 
18
 public class JavaMemberVisitor implements MemberVisitor<Void> {
18
 public class JavaMemberVisitor implements MemberVisitor<Void> {
19
 
19
 
20
     private final ClassWriter writer;
20
     private final ClassWriter writer;
21
 	private final JavaClassInfo toClass;
21
 	private final JavaClassInfo toClass;
22
+	private final HighLevelDefinition definition;
22
 
23
 
23
-    public JavaMemberVisitor(ClassWriter writer, JavaClassInfo toClass) {
24
+    public JavaMemberVisitor(ClassWriter writer, JavaClassInfo toClass, HighLevelDefinition definition) {
24
         this.writer = writer;
25
         this.writer = writer;
25
 		this.toClass = toClass;
26
 		this.toClass = toClass;
27
+		this.definition = definition;
26
     }
28
     }
27
 
29
 
28
     @Override
30
     @Override
38
 
40
 
39
     @Override
41
     @Override
40
     public Void visitConstructor(ConstructorMember member) {
42
     public Void visitConstructor(ConstructorMember member) {
41
-        final boolean isEnum = member.hasTag(JavaEnumInfo.class);
43
+		System.out.println("Compiling constructor " + member.header.toString());
44
+		
45
+        final boolean isEnum = definition instanceof EnumDefinition;
42
 		String descriptor = CompilerUtils.calcDesc(member.header, isEnum);
46
 		String descriptor = CompilerUtils.calcDesc(member.header, isEnum);
43
 		final JavaMethodInfo method = new JavaMethodInfo(toClass, "<init>", descriptor, isEnum ? Opcodes.ACC_PRIVATE : CompilerUtils.calcAccess(member.modifiers));
47
 		final JavaMethodInfo method = new JavaMethodInfo(toClass, "<init>", descriptor, isEnum ? Opcodes.ACC_PRIVATE : CompilerUtils.calcAccess(member.modifiers));
44
 		
48
 		
45
         final Label constructorStart = new Label();
49
         final Label constructorStart = new Label();
46
         final Label constructorEnd = new Label();
50
         final Label constructorEnd = new Label();
47
-        final JavaWriter constructorWriter = new JavaWriter(writer, method, CompilerUtils.calcSign(member.header, isEnum), null);
51
+        final JavaWriter constructorWriter = new JavaWriter(writer, method, definition, CompilerUtils.calcSign(member.header, isEnum), null);
48
         constructorWriter.label(constructorStart);
52
         constructorWriter.label(constructorStart);
53
+		CompilerUtils.tagConstructorParameters(member.header, isEnum);
49
         for (FunctionParameter parameter : member.header.parameters) {
54
         for (FunctionParameter parameter : member.header.parameters) {
50
-            if(isEnum)
51
-                parameter.index += 2;
52
-            constructorWriter.nameVariable(parameter.index + 1, parameter.name, constructorStart, constructorEnd, Type.getType(parameter.type.accept(JavaTypeClassVisitor.INSTANCE)));
55
+            constructorWriter.nameVariable(
56
+					parameter.getTag(JavaParameterInfo.class).index,
57
+					parameter.name,
58
+					constructorStart,
59
+					constructorEnd,
60
+					Type.getType(parameter.type.accept(JavaTypeClassVisitor.INSTANCE)));
53
         }
61
         }
62
+		
54
         final JavaStatementVisitor statementVisitor = new JavaStatementVisitor(constructorWriter);
63
         final JavaStatementVisitor statementVisitor = new JavaStatementVisitor(constructorWriter);
55
         statementVisitor.start();
64
         statementVisitor.start();
56
-
57
-        for (Statement statement : member.body) {
58
-            statement.accept(statementVisitor);
59
-        }
65
+		
66
+		if (!member.isConstructorForwarded()) {
67
+			if (isEnum) {
68
+				System.out.println("Writing enum constructor");
69
+				constructorWriter.getVisitor().newLocal(Type.getType(String.class));
70
+				constructorWriter.getVisitor().newLocal(Type.getType(int.class));
71
+				constructorWriter.loadObject(0);
72
+				constructorWriter.loadObject(1);
73
+				constructorWriter.loadInt(2);
74
+				constructorWriter.invokeSpecial(Type.getInternalName(Enum.class), "<init>", "(Ljava/lang/String;I)V");
75
+			} else if (definition.superType == null) {
76
+				System.out.println("Writing regular constructor");
77
+				constructorWriter.load(Type.getType(Object.class), 0);
78
+				constructorWriter.invokeSpecial(Type.getInternalName(Object.class), "<init>", "()V");
79
+			}
80
+			
81
+			CompilerUtils.writeDefaultFieldInitializers(constructorWriter, definition);
82
+		}
83
+		
84
+        member.body.accept(statementVisitor);
60
         constructorWriter.label(constructorEnd);
85
         constructorWriter.label(constructorEnd);
61
         statementVisitor.end();
86
         statementVisitor.end();
62
         return null;
87
         return null;
64
 
89
 
65
     @Override
90
     @Override
66
     public Void visitMethod(MethodMember member) {
91
     public Void visitMethod(MethodMember member) {
67
-        final boolean isAbstract = member.body == null || member.body.isEmpty() || Modifiers.isAbstract(member.modifiers);
92
+		CompilerUtils.tagMethodParameters(member.header, member.isStatic());
93
+		
94
+        final boolean isAbstract = member.body == null || Modifiers.isAbstract(member.modifiers);
68
 		int modifiers = (isAbstract ? Opcodes.ACC_ABSTRACT : 0)
95
 		int modifiers = (isAbstract ? Opcodes.ACC_ABSTRACT : 0)
69
 				| (member.isStatic() ? Opcodes.ACC_STATIC : 0)
96
 				| (member.isStatic() ? Opcodes.ACC_STATIC : 0)
70
 				| CompilerUtils.calcAccess(member.modifiers);
97
 				| CompilerUtils.calcAccess(member.modifiers);
76
 		
103
 		
77
         final Label methodStart = new Label();
104
         final Label methodStart = new Label();
78
         final Label methodEnd = new Label();
105
         final Label methodEnd = new Label();
79
-        final JavaWriter methodWriter = new JavaWriter(writer, method, CompilerUtils.calcSign(member.header, false), null);
106
+        final JavaWriter methodWriter = new JavaWriter(writer, method, definition, CompilerUtils.calcSign(member.header, false), null);
80
         methodWriter.label(methodStart);
107
         methodWriter.label(methodStart);
81
         for (final FunctionParameter parameter : member.header.parameters) {
108
         for (final FunctionParameter parameter : member.header.parameters) {
82
             methodWriter.nameParameter(0, parameter.name);
109
             methodWriter.nameParameter(0, parameter.name);
83
             if (!isAbstract)
110
             if (!isAbstract)
84
-                methodWriter.nameVariable(parameter.index + (member.isStatic() ? 0 : 1), parameter.name, methodStart, methodEnd, Type.getType(parameter.type.accept(JavaTypeClassVisitor.INSTANCE)));
111
+                methodWriter.nameVariable(parameter.getTag(JavaParameterInfo.class).index, parameter.name, methodStart, methodEnd, Type.getType(parameter.type.accept(JavaTypeClassVisitor.INSTANCE)));
85
         }
112
         }
86
 
113
 
87
         final JavaStatementVisitor statementVisitor = new JavaStatementVisitor(methodWriter);
114
         final JavaStatementVisitor statementVisitor = new JavaStatementVisitor(methodWriter);
88
 
115
 
89
         if (!isAbstract) {
116
         if (!isAbstract) {
90
             statementVisitor.start();
117
             statementVisitor.start();
91
-            for (Statement statement : member.body) {
92
-                statement.accept(statementVisitor);
93
-            }
94
-
118
+			member.body.accept(statementVisitor);
95
             methodWriter.label(methodEnd);
119
             methodWriter.label(methodEnd);
96
             statementVisitor.end();
120
             statementVisitor.end();
97
         }
121
         }
112
 
136
 
113
     @Override
137
     @Override
114
     public Void visitEnumConstant(EnumConstantMember member) {
138
     public Void visitEnumConstant(EnumConstantMember member) {
115
-        final JavaStatementVisitor clinitVisitor = member.getTag(JavaEnumInfo.class).clinitVisitor;
116
-        final JavaWriter clinitWriter = clinitVisitor.getJavaWriter();
117
-        final String internalName = member.constructor.type.accept(JavaTypeVisitor.INSTANCE).getInternalName();
118
-
119
-        clinitWriter.newObject(internalName);
120
-        clinitWriter.dup();
121
-        clinitWriter.constant(member.name);
122
-        clinitWriter.constant(member.value);
123
-        for (Expression argument : member.constructor.arguments.arguments) {
124
-            argument.accept(clinitVisitor.expressionVisitor);
125
-        }
126
-        clinitWriter.invokeSpecial(internalName, "<init>", CompilerUtils.calcDesc(member.constructor.constructor.header, true));
127
-        clinitWriter.putStaticField(internalName, member.name, "L" + internalName + ";");
128
-
129
-
130
         return null;
139
         return null;
131
     }
140
     }
132
 
141
 
159
     public Void visitInnerDefinition(InnerDefinitionMember member) {
168
     public Void visitInnerDefinition(InnerDefinitionMember member) {
160
         return null;
169
         return null;
161
     }
170
     }
162
-
163
 }
171
 }

+ 2
- 3
Parser/src/main/java/org/openzen/zenscript/parser/expression/ParsedExpressionFunction.java View File

7
 package org.openzen.zenscript.parser.expression;
7
 package org.openzen.zenscript.parser.expression;
8
 
8
 
9
 import java.util.HashMap;
9
 import java.util.HashMap;
10
-import java.util.List;
11
 import java.util.Map;
10
 import java.util.Map;
12
 import org.openzen.zenscript.codemodel.FunctionHeader;
11
 import org.openzen.zenscript.codemodel.FunctionHeader;
13
 import org.openzen.zenscript.codemodel.expression.FunctionExpression;
12
 import org.openzen.zenscript.codemodel.expression.FunctionExpression;
66
 		
65
 		
67
 		LambdaClosure closure = new LambdaClosure();
66
 		LambdaClosure closure = new LambdaClosure();
68
 		StatementScope innerScope = new LambdaScope(scope, closure, header);
67
 		StatementScope innerScope = new LambdaScope(scope, closure, header);
69
-		List<Statement> statements = body.compile(innerScope, header);
68
+		Statement statements = body.compile(innerScope, header);
70
 		if (!scope.genericInferenceMap.isEmpty()) {
69
 		if (!scope.genericInferenceMap.isEmpty()) {
71
 			// perform type parameter inference
70
 			// perform type parameter inference
72
-			ITypeID returnType = Statement.getReturnType(scope, statements);
71
+			ITypeID returnType = statements.getReturnType();
73
 			Map<TypeParameter, ITypeID> inferredTypes = new HashMap<>();
72
 			Map<TypeParameter, ITypeID> inferredTypes = new HashMap<>();
74
 			if (!genericHeader.returnType.inferTypeParameters(returnType, inferredTypes))
73
 			if (!genericHeader.returnType.inferTypeParameters(returnType, inferredTypes))
75
 				throw new CompileException(position, CompileExceptionCode.TYPE_ARGUMENTS_NOT_INFERRABLE, "Could not infer generic type parameters");
74
 				throw new CompileException(position, CompileExceptionCode.TYPE_ARGUMENTS_NOT_INFERRABLE, "Could not infer generic type parameters");

+ 3
- 4
Parser/src/main/java/org/openzen/zenscript/parser/statements/ParsedEmptyFunctionBody.java View File

5
  */
5
  */
6
 package org.openzen.zenscript.parser.statements;
6
 package org.openzen.zenscript.parser.statements;
7
 
7
 
8
-import java.util.Collections;
9
-import java.util.List;
10
 import org.openzen.zenscript.codemodel.FunctionHeader;
8
 import org.openzen.zenscript.codemodel.FunctionHeader;
9
+import org.openzen.zenscript.codemodel.statement.EmptyStatement;
11
 import org.openzen.zenscript.codemodel.statement.Statement;
10
 import org.openzen.zenscript.codemodel.statement.Statement;
12
 import org.openzen.zenscript.linker.StatementScope;
11
 import org.openzen.zenscript.linker.StatementScope;
13
 import org.openzen.zenscript.shared.CodePosition;
12
 import org.openzen.zenscript.shared.CodePosition;
24
 	}
23
 	}
25
 	
24
 	
26
 	@Override
25
 	@Override
27
-	public List<Statement> compile(StatementScope scope, FunctionHeader header) {
28
-		return Collections.emptyList();
26
+	public Statement compile(StatementScope scope, FunctionHeader header) {
27
+		return new EmptyStatement(position);
29
 	}
28
 	}
30
 }
29
 }

+ 1
- 2
Parser/src/main/java/org/openzen/zenscript/parser/statements/ParsedFunctionBody.java View File

5
  */
5
  */
6
 package org.openzen.zenscript.parser.statements;
6
 package org.openzen.zenscript.parser.statements;
7
 
7
 
8
-import java.util.List;
9
 import org.openzen.zenscript.codemodel.FunctionHeader;
8
 import org.openzen.zenscript.codemodel.FunctionHeader;
10
 import org.openzen.zenscript.codemodel.statement.Statement;
9
 import org.openzen.zenscript.codemodel.statement.Statement;
11
 import org.openzen.zenscript.linker.StatementScope;
10
 import org.openzen.zenscript.linker.StatementScope;
15
  * @author Hoofdgebruiker
14
  * @author Hoofdgebruiker
16
  */
15
  */
17
 public abstract class ParsedFunctionBody {
16
 public abstract class ParsedFunctionBody {
18
-	public abstract List<Statement> compile(StatementScope scope, FunctionHeader header);
17
+	public abstract Statement compile(StatementScope scope, FunctionHeader header);
19
 }
18
 }

+ 3
- 8
Parser/src/main/java/org/openzen/zenscript/parser/statements/ParsedLambdaFunctionBody.java View File

5
  */
5
  */
6
 package org.openzen.zenscript.parser.statements;
6
 package org.openzen.zenscript.parser.statements;
7
 
7
 
8
-import java.util.ArrayList;
9
-import java.util.List;
10
 import org.openzen.zenscript.codemodel.FunctionHeader;
8
 import org.openzen.zenscript.codemodel.FunctionHeader;
11
 import org.openzen.zenscript.codemodel.expression.Expression;
9
 import org.openzen.zenscript.codemodel.expression.Expression;
12
 import org.openzen.zenscript.codemodel.statement.ExpressionStatement;
10
 import org.openzen.zenscript.codemodel.statement.ExpressionStatement;
29
 	}
27
 	}
30
 	
28
 	
31
 	@Override
29
 	@Override
32
-	public List<Statement> compile(StatementScope scope, FunctionHeader header) {
33
-		List<Statement> statements = new ArrayList<>();
30
+	public Statement compile(StatementScope scope, FunctionHeader header) {
34
 		if (header.returnType == BasicTypeID.VOID) {
31
 		if (header.returnType == BasicTypeID.VOID) {
35
 			Expression value = this.value.compile(new ExpressionScope(scope)).eval();
32
 			Expression value = this.value.compile(new ExpressionScope(scope)).eval();
36
-			statements.add(new ExpressionStatement(value.position, value));
37
-			statements.add(new ReturnStatement(value.position, null));
33
+			return new ExpressionStatement(value.position, value);
38
 		} else {
34
 		} else {
39
 			Expression returnValue = value
35
 			Expression returnValue = value
40
 					.compile(new ExpressionScope(scope, header.returnType))
36
 					.compile(new ExpressionScope(scope, header.returnType))
41
 					.eval()
37
 					.eval()
42
 					.castImplicit(value.position, scope, header.returnType);
38
 					.castImplicit(value.position, scope, header.returnType);
43
-			statements.add(new ReturnStatement(value.position, returnValue));
39
+			return new ReturnStatement(value.position, returnValue);
44
 		}
40
 		}
45
-		return statements;
46
 	}
41
 	}
47
 }
42
 }

+ 4
- 2
Parser/src/main/java/org/openzen/zenscript/parser/statements/ParsedStatement.java View File

17
 
17
 
18
 public abstract class ParsedStatement {
18
 public abstract class ParsedStatement {
19
 	public static ParsedFunctionBody parseLambdaBody(ZSTokenStream tokens, boolean inExpression) {
19
 	public static ParsedFunctionBody parseLambdaBody(ZSTokenStream tokens, boolean inExpression) {
20
+		ZSToken start = tokens.peek();
20
 		if (tokens.optional(T_AOPEN) != null) {
21
 		if (tokens.optional(T_AOPEN) != null) {
21
 			List<ParsedStatement> statements = new ArrayList<>();
22
 			List<ParsedStatement> statements = new ArrayList<>();
22
 			while (tokens.optional(T_ACLOSE) == null)
23
 			while (tokens.optional(T_ACLOSE) == null)
23
 				statements.add(ParsedStatement.parse(tokens));
24
 				statements.add(ParsedStatement.parse(tokens));
24
 			
25
 			
25
-			return new ParsedStatementsFunctionBody(statements);
26
+			return new ParsedStatementsFunctionBody(new ParsedStatementBlock(start.position, null, null, statements));
26
 		} else {
27
 		} else {
27
 			ParsedFunctionBody result = new ParsedLambdaFunctionBody(ParsedExpression.parse(tokens));
28
 			ParsedFunctionBody result = new ParsedLambdaFunctionBody(ParsedExpression.parse(tokens));
28
 			if (!inExpression)
29
 			if (!inExpression)
32
 	}
33
 	}
33
 	
34
 	
34
 	public static ParsedFunctionBody parseFunctionBody(ZSTokenStream tokens) {
35
 	public static ParsedFunctionBody parseFunctionBody(ZSTokenStream tokens) {
36
+		ZSToken start = tokens.peek();
35
 		if (tokens.optional(T_LAMBDA) != null) {
37
 		if (tokens.optional(T_LAMBDA) != null) {
36
 			return parseLambdaBody(tokens, false);
38
 			return parseLambdaBody(tokens, false);
37
 		} else if (tokens.optional(T_SEMICOLON) != null) {
39
 		} else if (tokens.optional(T_SEMICOLON) != null) {
42
 			while (tokens.optional(T_ACLOSE) == null) {
44
 			while (tokens.optional(T_ACLOSE) == null) {
43
 				statements.add(ParsedStatement.parse(tokens));
45
 				statements.add(ParsedStatement.parse(tokens));
44
 			}
46
 			}
45
-			return new ParsedStatementsFunctionBody(statements);
47
+			return new ParsedStatementsFunctionBody(new ParsedStatementBlock(start.position, null, null, statements));
46
 		}
48
 		}
47
 	}
49
 	}
48
 	
50
 	

+ 5
- 9
Parser/src/main/java/org/openzen/zenscript/parser/statements/ParsedStatementsFunctionBody.java View File

5
  */
5
  */
6
 package org.openzen.zenscript.parser.statements;
6
 package org.openzen.zenscript.parser.statements;
7
 
7
 
8
-import java.util.List;
9
-import java.util.stream.Collectors;
10
 import org.openzen.zenscript.codemodel.FunctionHeader;
8
 import org.openzen.zenscript.codemodel.FunctionHeader;
11
 import org.openzen.zenscript.codemodel.statement.Statement;
9
 import org.openzen.zenscript.codemodel.statement.Statement;
12
 import org.openzen.zenscript.linker.StatementScope;
10
 import org.openzen.zenscript.linker.StatementScope;
16
  * @author Hoofdgebruiker
14
  * @author Hoofdgebruiker
17
  */
15
  */
18
 public class ParsedStatementsFunctionBody extends ParsedFunctionBody {
16
 public class ParsedStatementsFunctionBody extends ParsedFunctionBody {
19
-	private final List<ParsedStatement> statements;
17
+	private final ParsedStatement body;
20
 	
18
 	
21
-	public ParsedStatementsFunctionBody(List<ParsedStatement> statements) {
22
-		this.statements = statements;
19
+	public ParsedStatementsFunctionBody(ParsedStatement body) {
20
+		this.body = body;
23
 	}
21
 	}
24
 	
22
 	
25
 	@Override
23
 	@Override
26
-	public List<Statement> compile(StatementScope scope, FunctionHeader header) {
27
-		return statements.stream()
28
-				.map(s -> s.compile(scope))
29
-				.collect(Collectors.toList());
24
+	public Statement compile(StatementScope scope, FunctionHeader header) {
25
+		return body.compile(scope);
30
 	}
26
 	}
31
 }
27
 }

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

44
 		VARIADIC_PARAMETER_MUST_BE_LAST,
44
 		VARIADIC_PARAMETER_MUST_BE_LAST,
45
 		CONSTRUCTOR_FORWARD_OUTSIDE_CONSTRUCTOR,
45
 		CONSTRUCTOR_FORWARD_OUTSIDE_CONSTRUCTOR,
46
 		CONSTRUCTOR_FORWARD_NOT_FIRST_STATEMENT,
46
 		CONSTRUCTOR_FORWARD_NOT_FIRST_STATEMENT,
47
+		CONSTRUCTOR_FORWARD_MISSING,
47
 		DUPLICATE_CONSTRUCTOR,
48
 		DUPLICATE_CONSTRUCTOR,
48
 		DUPLICATE_METHOD,
49
 		DUPLICATE_METHOD,
49
 		BODY_REQUIRED,
50
 		BODY_REQUIRED,

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

25
 import org.openzen.zenscript.codemodel.member.MethodMember;
25
 import org.openzen.zenscript.codemodel.member.MethodMember;
26
 import org.openzen.zenscript.codemodel.member.OperatorMember;
26
 import org.openzen.zenscript.codemodel.member.OperatorMember;
27
 import org.openzen.zenscript.codemodel.member.SetterMember;
27
 import org.openzen.zenscript.codemodel.member.SetterMember;
28
-import org.openzen.zenscript.codemodel.statement.Statement;
29
 import org.openzen.zenscript.codemodel.statement.VarStatement;
28
 import org.openzen.zenscript.codemodel.statement.VarStatement;
30
 import org.openzen.zenscript.codemodel.type.ITypeID;
29
 import org.openzen.zenscript.codemodel.type.ITypeID;
31
 import org.openzen.zenscript.validator.ValidationLogEntry;
30
 import org.openzen.zenscript.validator.ValidationLogEntry;
89
 			validator.logError(ValidationLogEntry.Code.BODY_REQUIRED, member.position, "Constructors must have a body");
88
 			validator.logError(ValidationLogEntry.Code.BODY_REQUIRED, member.position, "Constructors must have a body");
90
 		} else {
89
 		} else {
91
 			StatementValidator statementValidator = new StatementValidator(validator, new ConstructorStatementScope(member.header));
90
 			StatementValidator statementValidator = new StatementValidator(validator, new ConstructorStatementScope(member.header));
92
-			for (Statement statement : member.body) {
93
-				isValid &= statement.accept(statementValidator);
94
-			}
91
+			isValid &= member.body.accept(statementValidator);
95
 			
92
 			
96
-			if (!statementValidator.constructorForwarded) {
97
-				// TODO: does this type have a supertype with no-argument constructor?
93
+			if (member.definition.superType != null && !statementValidator.constructorForwarded) {
94
+				validator.logError(ValidationLogEntry.Code.CONSTRUCTOR_FORWARD_MISSING, member.position, "Constructor not forwarded to base type");
95
+				isValid &= false;
98
 			}
96
 			}
99
 		}
97
 		}
100
 		
98
 		
109
 		
107
 		
110
 		if (member.body != null) {
108
 		if (member.body != null) {
111
 			StatementValidator statementValidator = new StatementValidator(validator, new ConstructorStatementScope(member.header));
109
 			StatementValidator statementValidator = new StatementValidator(validator, new ConstructorStatementScope(member.header));
112
-			for (Statement statement : member.body) {
113
-				isValid &= statement.accept(statementValidator);
114
-			}
110
+			isValid &= member.body.accept(statementValidator);
115
 		}
111
 		}
116
 		
112
 		
117
 		return isValid;
113
 		return isValid;
125
 		
121
 		
126
 		if (member.body != null) {
122
 		if (member.body != null) {
127
 			StatementValidator statementValidator = new StatementValidator(validator, new ConstructorStatementScope(member.header));
123
 			StatementValidator statementValidator = new StatementValidator(validator, new ConstructorStatementScope(member.header));
128
-			for (Statement statement : member.body) {
129
-				isValid &= statement.accept(statementValidator);
130
-			}
124
+			isValid &= member.body.accept(statementValidator);
131
 		}
125
 		}
132
 		
126
 		
133
 		return isValid;
127
 		return isValid;
141
 		
135
 		
142
 		if (member.body != null) {
136
 		if (member.body != null) {
143
 			StatementValidator statementValidator = new StatementValidator(validator, new ConstructorStatementScope(member.header));
137
 			StatementValidator statementValidator = new StatementValidator(validator, new ConstructorStatementScope(member.header));
144
-			for (Statement statement : member.body) {
145
-				isValid &= statement.accept(statementValidator);
146
-			}
138
+			isValid &= member.body.accept(statementValidator);
147
 		}
139
 		}
148
 		
140
 		
149
 		return isValid;
141
 		return isValid;
172
 		
164
 		
173
 		if (member.body != null) {
165
 		if (member.body != null) {
174
 			StatementValidator statementValidator = new StatementValidator(validator, new ConstructorStatementScope(member.header));
166
 			StatementValidator statementValidator = new StatementValidator(validator, new ConstructorStatementScope(member.header));
175
-			for (Statement statement : member.body) {
176
-				isValid &= statement.accept(statementValidator);
177
-			}
167
+			isValid &= member.body.accept(statementValidator);
178
 		}
168
 		}
179
 		
169
 		
180
 		return isValid;
170
 		return isValid;
187
 		
177
 		
188
 		if (member.body != null) {
178
 		if (member.body != null) {
189
 			StatementValidator statementValidator = new StatementValidator(validator, new ConstructorStatementScope(member.header));
179
 			StatementValidator statementValidator = new StatementValidator(validator, new ConstructorStatementScope(member.header));
190
-			for (Statement statement : member.body) {
191
-				isValid &= statement.accept(statementValidator);
192
-			}
180
+			isValid &= member.body.accept(statementValidator);
193
 		}
181
 		}
194
 		
182
 		
195
 		return isValid;
183
 		return isValid;
207
 		
195
 		
208
 		if (member.body != null) {
196
 		if (member.body != null) {
209
 			StatementValidator statementValidator = new StatementValidator(validator, new ConstructorStatementScope(member.header));
197
 			StatementValidator statementValidator = new StatementValidator(validator, new ConstructorStatementScope(member.header));
210
-			for (Statement statement : member.body) {
211
-				isValid &= statement.accept(statementValidator);
212
-			}
198
+			isValid &= member.body.accept(statementValidator);
213
 		}
199
 		}
214
 		
200
 		
215
 		return isValid;
201
 		return isValid;

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

17
 import org.openzen.zenscript.codemodel.definition.InterfaceDefinition;
17
 import org.openzen.zenscript.codemodel.definition.InterfaceDefinition;
18
 import org.openzen.zenscript.codemodel.definition.StructDefinition;
18
 import org.openzen.zenscript.codemodel.definition.StructDefinition;
19
 import org.openzen.zenscript.codemodel.member.IDefinitionMember;
19
 import org.openzen.zenscript.codemodel.member.IDefinitionMember;
20
-import org.openzen.zenscript.codemodel.statement.Statement;
21
 import org.openzen.zenscript.validator.Validator;
20
 import org.openzen.zenscript.validator.Validator;
22
 import org.openzen.zenscript.validator.analysis.StatementScope;
21
 import org.openzen.zenscript.validator.analysis.StatementScope;
23
 
22
 
122
 				definition.name);
121
 				definition.name);
123
 				
122
 				
124
 		StatementValidator statementValidator = new StatementValidator(validator, new FunctionStatementScope(definition.header));
123
 		StatementValidator statementValidator = new StatementValidator(validator, new FunctionStatementScope(definition.header));
125
-		for (Statement statement : definition.statements) {
126
-			isValid &= statement.accept(statementValidator);
127
-		}
124
+		isValid &= definition.statement.accept(statementValidator);
128
 		return isValid;
125
 		return isValid;
129
 	}
126
 	}
130
 
127
 

Loading…
Cancel
Save