diff --git a/jse/src/main/java/org/luaj/vm2/ast/NameResolver.class b/jse/src/main/java/org/luaj/vm2/ast/NameResolver.class new file mode 100644 index 00000000..ae329b11 Binary files /dev/null and b/jse/src/main/java/org/luaj/vm2/ast/NameResolver.class differ diff --git a/jse/src/main/java/org/luaj/vm2/ast/NameResolver.java b/jse/src/main/java/org/luaj/vm2/ast/NameResolver.java index 73ea1ede..2c3f7df9 100644 --- a/jse/src/main/java/org/luaj/vm2/ast/NameResolver.java +++ b/jse/src/main/java/org/luaj/vm2/ast/NameResolver.java @@ -21,6 +21,7 @@ import org.luaj.vm2.ast.Stat.NumericFor; public class NameResolver extends Visitor { private NameScope scope = null; + private boolean injectMethodSelf; private void pushScope() { scope = new NameScope(scope); @@ -43,6 +44,9 @@ public class NameResolver extends Visitor { pushScope(); scope.functionNestingCount++; body.scope = scope; + if (injectMethodSelf) { + scope.define("self"); + } super.visit(body); popScope(); } @@ -76,7 +80,13 @@ public class NameResolver extends Visitor { public void visit(FuncDef stat) { stat.name.name.variable = resolveNameReference(stat.name.name); stat.name.name.variable.hasassignments = true; - super.visit(stat); + boolean previousInjectMethodSelf = injectMethodSelf; + injectMethodSelf = stat.name.method != null; + try { + super.visit(stat); + } finally { + injectMethodSelf = previousInjectMethodSelf; + } } public void visit(Assign stat) { diff --git a/jse/src/test/java/org/luaj/vm2/compiler/LuaParserTests.java b/jse/src/test/java/org/luaj/vm2/compiler/LuaParserTests.java index e09483a9..ecd863e5 100644 --- a/jse/src/test/java/org/luaj/vm2/compiler/LuaParserTests.java +++ b/jse/src/test/java/org/luaj/vm2/compiler/LuaParserTests.java @@ -1,5 +1,10 @@ package org.luaj.vm2.compiler; +import org.luaj.vm2.ast.Chunk; +import org.luaj.vm2.ast.Exp; +import org.luaj.vm2.ast.NameResolver; +import org.luaj.vm2.ast.Stat; +import org.luaj.vm2.ast.Variable; import org.luaj.vm2.LuaValue; import org.luaj.vm2.compiler.CompilerUnitTests; import org.luaj.vm2.parser.LuaParser; @@ -37,4 +42,24 @@ public class LuaParserTests extends CompilerUnitTests { fail(e.getMessage()); } } + + public void testMethodDefinitionInjectsHiddenSelf() { + try { + Reader r = new StringReader("function t:f() return self end"); + LuaParser parser = new LuaParser(r); + Chunk chunk = parser.Chunk(); + new NameResolver().visit(chunk); + + Stat.FuncDef stat = (Stat.FuncDef) chunk.block.stats.get(0); + Variable self = stat.body.scope.namedVariables.get("self"); + assertNotNull(self); + assertTrue(self.isLocal()); + + Stat.Return ret = (Stat.Return) stat.body.block.stats.get(0); + Exp.NameExp selfRef = (Exp.NameExp) ret.values.get(0); + assertSame(self, selfRef.name.variable); + } catch (Exception e) { + fail(e.getMessage()); + } + } }