|
1 | 1 | package org.openzen.zenscript.javabytecode.compiler.lambda.capturing; |
2 | 2 |
|
3 | | -import org.objectweb.asm.Type; |
4 | | -import org.openzen.zenscript.codemodel.FunctionParameter; |
5 | 3 | import org.openzen.zenscript.codemodel.expression.FunctionExpression; |
6 | | -import org.openzen.zenscript.codemodel.expression.GetLocalVariableExpression; |
7 | 4 | import org.openzen.zenscript.codemodel.expression.captured.*; |
8 | | -import org.openzen.zenscript.codemodel.type.BasicTypeID; |
9 | | -import org.openzen.zenscript.codemodel.type.TypeID; |
| 5 | +import org.openzen.zenscript.javabytecode.JavaBytecodeContext; |
10 | 6 | import org.openzen.zenscript.javabytecode.compiler.JavaWriter; |
11 | 7 | import org.openzen.zenscript.javabytecode.compiler.lambda.LambdaClosureInfo; |
12 | 8 |
|
13 | | -import java.util.function.Predicate; |
14 | | - |
15 | 9 | public final class JavaRedirectCapturesCapturedExpressionVisitor implements CapturedExpressionVisitor<Void> { |
16 | | - private static final class MemberData { |
17 | | - private final int position; |
18 | | - private final Type type; |
19 | | - |
20 | | - MemberData(final int position, final Type type) { |
21 | | - this.position = position; |
22 | | - this.type = type; |
23 | | - } |
24 | | - |
25 | | - void load(final JavaWriter writer) { |
26 | | - writer.load(this.type, this.position); |
27 | | - } |
28 | | - } |
29 | | - |
30 | | - private final FunctionExpression functionExpression; |
31 | 10 | private final JavaWriter javaWriter; |
32 | | - private final LambdaClosureInfo closureInfo; |
33 | | - |
34 | | - public JavaRedirectCapturesCapturedExpressionVisitor(final JavaWriter javaWriter, final FunctionExpression functionExpression, final LambdaClosureInfo closureInfo) { |
| 11 | + private final JavaCaptureDataFinderCapturedExpressionVisitor captureDataFinder; |
| 12 | + |
| 13 | + public JavaRedirectCapturesCapturedExpressionVisitor( |
| 14 | + final JavaWriter javaWriter, |
| 15 | + final FunctionExpression functionExpression, |
| 16 | + final LambdaClosureInfo closureInfo, |
| 17 | + final JavaBytecodeContext context |
| 18 | + ) { |
35 | 19 | this.javaWriter = javaWriter; |
36 | | - this.functionExpression = functionExpression; |
37 | | - this.closureInfo = closureInfo; |
| 20 | + this.captureDataFinder = new JavaCaptureDataFinderCapturedExpressionVisitor(functionExpression, closureInfo, context); |
38 | 21 | } |
39 | 22 |
|
40 | 23 | @Override |
41 | 24 | public Void visitCapturedThis(final CapturedThisExpression expression) { |
42 | | - // TODO("Remove null-check as this method should never return null") |
43 | | - final Type type = this.closureInfo.thisType() == null? Type.getType(Void.class) : this.getTypeFrom(this.closureInfo.thisType()); |
44 | | - return this.loadByMemberData(new MemberData(0, type)); |
| 25 | + return this.loadByCaptureData(expression); |
45 | 26 | } |
46 | 27 |
|
47 | 28 | @Override |
48 | 29 | public Void visitCapturedParameter(CapturedParameterExpression expression) { |
49 | | - return this.loadByMemberData(this.calculateMemberData(expression, this.functionExpression)); |
| 30 | + return this.loadByCaptureData(expression); |
50 | 31 | } |
51 | 32 |
|
52 | 33 | @Override |
53 | 34 | public Void visitCapturedLocal(CapturedLocalVariableExpression expression) { |
54 | | - return this.loadByMemberData(this.calculateMemberData(new GetLocalVariableExpression(expression.position, expression.variable), this.functionExpression)); |
| 35 | + return this.loadByCaptureData(expression); |
55 | 36 | } |
56 | 37 |
|
57 | 38 | @Override |
58 | 39 | public Void visitRecaptured(CapturedClosureExpression expression) { |
59 | | - return this.loadByMemberData(this.findIndex(expression, this.functionExpression)); |
| 40 | + return this.loadByCaptureData(expression); |
60 | 41 | } |
61 | 42 |
|
62 | | - private Void loadByMemberData(final MemberData memberData) { |
63 | | - memberData.load(this.javaWriter); |
64 | | - return null; |
| 43 | + private Void loadByCaptureData(final CapturedExpression expression) { |
| 44 | + return this.loadByCaptureData(expression.accept(this.captureDataFinder)); |
65 | 45 | } |
66 | 46 |
|
67 | | - private MemberData findIndex(final CapturedExpression capturedExpression, final FunctionExpression expression) { |
68 | | - return this.calculateMemberData( |
69 | | - expression, |
70 | | - capturedExpression.type, |
71 | | - capturedExpression::equals |
72 | | - ); |
73 | | - } |
74 | | - |
75 | | - private MemberData calculateMemberData(final GetLocalVariableExpression localVariableExpression, final FunctionExpression expression) { |
76 | | - return this.calculateMemberData( |
77 | | - expression, |
78 | | - localVariableExpression.type, |
79 | | - capture -> { |
80 | | - if (capture instanceof CapturedLocalVariableExpression) { |
81 | | - return ((CapturedLocalVariableExpression) capture).variable == localVariableExpression.variable; |
82 | | - } else if (capture instanceof CapturedClosureExpression) { |
83 | | - final CapturedExpression value = ((CapturedClosureExpression) capture).value; |
84 | | - return value instanceof CapturedLocalVariableExpression && ((CapturedLocalVariableExpression) value).variable == localVariableExpression.variable; |
85 | | - } |
86 | | - return false; |
87 | | - }); |
88 | | - } |
89 | | - |
90 | | - private MemberData calculateMemberData(final CapturedParameterExpression functionParameterExpression, final FunctionExpression expression) { |
91 | | - return this.calculateMemberData( |
92 | | - expression, |
93 | | - functionParameterExpression.parameter.type, |
94 | | - capture -> capture instanceof CapturedParameterExpression && ((CapturedParameterExpression) capture).parameter == functionParameterExpression.parameter |
95 | | - ); |
96 | | - } |
97 | | - |
98 | | - private MemberData calculateMemberData(final FunctionExpression expression, final TypeID varType, final Predicate<CapturedExpression> predicate) { |
99 | | - final Type type = this.getTypeFrom(varType); |
100 | | - int h = this.findFirstValidCaptureIndex(expression); |
101 | | - for (final CapturedExpression capture : expression.closure.captures) { |
102 | | - if (predicate.test(capture)) { |
103 | | - return new MemberData(h, type); |
104 | | - } |
105 | | - h += type.getSize(); |
106 | | - } |
107 | | - throw new IllegalStateException(expression.position.toString() + ": Captured Statement error"); |
108 | | - } |
109 | | - |
110 | | - private int findFirstValidCaptureIndex(final FunctionExpression expression) { |
111 | | - int h = 1; |
112 | | - for (final FunctionParameter parameter : expression.header.parameters) { |
113 | | - h += this.getTypeFrom(parameter.type).getSize(); |
114 | | - } |
115 | | - return h; |
116 | | - } |
117 | | - |
118 | | - private Type getTypeFrom(final TypeID type) { |
119 | | - if (type instanceof BasicTypeID) { |
120 | | - switch ((BasicTypeID) type) { |
121 | | - case VOID: return Type.VOID_TYPE; |
122 | | - case BOOL: return Type.BOOLEAN_TYPE; |
123 | | - case BYTE: return Type.BYTE_TYPE; |
124 | | - case SBYTE: return Type.BYTE_TYPE; // TODO() |
125 | | - case SHORT: return Type.SHORT_TYPE; |
126 | | - case USHORT: return Type.SHORT_TYPE; // TODO() |
127 | | - case INT: return Type.INT_TYPE; |
128 | | - case UINT: return Type.INT_TYPE; // TODO() |
129 | | - case LONG: return Type.LONG_TYPE; |
130 | | - case ULONG: return Type.LONG_TYPE; // TODO() |
131 | | - case USIZE: return Type.INT_TYPE; |
132 | | - case FLOAT: return Type.FLOAT_TYPE; |
133 | | - case DOUBLE: return Type.DOUBLE_TYPE; |
134 | | - case CHAR: return Type.CHAR_TYPE; |
135 | | - } |
136 | | - } |
137 | | - |
138 | | - // We don't care about the actual class contained in the type here, we only care that Java treats it as an |
139 | | - // object, so we simply grab a random Java class |
140 | | - return Type.getType(Void.class); |
| 47 | + private Void loadByCaptureData(final LambdaCaptureData data) { |
| 48 | + this.javaWriter.load(data.type(), data.position()); |
| 49 | + return null; |
141 | 50 | } |
142 | 51 | } |
0 commit comments