|
8 | 8 | import fi.benjami.code4jvm.Constant;
|
9 | 9 | import fi.benjami.code4jvm.Type;
|
10 | 10 | import fi.benjami.code4jvm.Variable;
|
| 11 | +import fi.benjami.code4jvm.lua.LuaVm; |
11 | 12 | import fi.benjami.code4jvm.lua.ir.LuaLocalVar;
|
12 | 13 | import fi.benjami.code4jvm.lua.ir.LuaType;
|
13 | 14 | import fi.benjami.code4jvm.lua.ir.LuaVariable;
|
|
16 | 17 |
|
17 | 18 | public class LuaContext {
|
18 | 19 |
|
| 20 | + public static LuaContext forFunction(LuaVm vm, LuaType.Function type, boolean truncateReturn, LuaType... argTypes) { |
| 21 | + // Init scope with upvalue types |
| 22 | + var ctx = new LuaContext(vm, truncateReturn); |
| 23 | + for (var upvalue : type.upvalues()) { |
| 24 | + ctx.recordType(upvalue.variable(), upvalue.type()); |
| 25 | + } |
| 26 | + |
| 27 | + // Add types of function arguments |
| 28 | + // Missing arguments are allowed and treated as nil |
| 29 | + var normalArgs = type.acceptedArgs().size(); |
| 30 | + if (type.isVarargs()) { |
| 31 | + normalArgs--; |
| 32 | + ctx.recordType(LuaLocalVar.VARARGS, LuaType.UNKNOWN); // No type analysis for these yet |
| 33 | + } |
| 34 | + var acceptedArgs = type.acceptedArgs(); |
| 35 | + for (var i = 0; i < normalArgs; i++) { |
| 36 | + if (argTypes.length > i) { |
| 37 | + ctx.recordType(acceptedArgs.get(i), argTypes[i]); |
| 38 | + } else { |
| 39 | + ctx.recordType(acceptedArgs.get(i), LuaType.NIL); |
| 40 | + } |
| 41 | + } |
| 42 | + |
| 43 | + // Compute types of local variables and the return type |
| 44 | + type.body().outputType(ctx); |
| 45 | + return ctx; |
| 46 | + } |
| 47 | + |
19 | 48 | /**
|
20 | 49 | * Local variable type table. When variables are written to, their types
|
21 | 50 | * are recorded here.
|
@@ -45,12 +74,21 @@ public class LuaContext {
|
45 | 74 |
|
46 | 75 | private boolean allowSpread;
|
47 | 76 |
|
48 |
| - public LuaContext(boolean truncateReturn) { |
| 77 | + /** |
| 78 | + * The Lua VM that 'owns' this context. |
| 79 | + */ |
| 80 | + private final LuaVm owner; |
| 81 | + private final Constant ownerConstant; |
| 82 | + |
| 83 | + public LuaContext(LuaVm owner, boolean truncateReturn) { |
| 84 | + assert owner != null; |
49 | 85 | this.typeTable = new IdentityHashMap<>();
|
50 | 86 | this.variables = new IdentityHashMap<>();
|
51 | 87 | this.classData = new ArrayList<>();
|
52 | 88 | this.cache = new IdentityHashMap<>();
|
53 | 89 | this.truncateReturn = truncateReturn;
|
| 90 | + this.owner = owner; |
| 91 | + this.ownerConstant = addClassData(owner); |
54 | 92 | }
|
55 | 93 |
|
56 | 94 | public void recordType(LuaVariable variable, LuaType type) {
|
@@ -187,5 +225,13 @@ public void setAllowSpread(boolean value) {
|
187 | 225 | public boolean allowSpread() {
|
188 | 226 | return allowSpread;
|
189 | 227 | }
|
| 228 | + |
| 229 | + public LuaVm owner() { |
| 230 | + return owner; |
| 231 | + } |
| 232 | + |
| 233 | + public Constant ownerConstant() { |
| 234 | + return ownerConstant; |
| 235 | + } |
190 | 236 |
|
191 | 237 | }
|
0 commit comments