blob: 060eafd3a1320407a1b757d90481f6e588474342 [file] [log] [blame] [raw]
package org.luaj.vm3.ast;
import java.util.List;
import org.luaj.vm3.LuaValue;
import org.luaj.vm3.ast.Exp.Constant;
import org.luaj.vm3.ast.Exp.NameExp;
import org.luaj.vm3.ast.Exp.VarExp;
import org.luaj.vm3.ast.Stat.Assign;
import org.luaj.vm3.ast.Stat.FuncDef;
import org.luaj.vm3.ast.Stat.GenericFor;
import org.luaj.vm3.ast.Stat.LocalAssign;
import org.luaj.vm3.ast.Stat.LocalFuncDef;
import org.luaj.vm3.ast.Stat.NumericFor;
/**
* Visitor that resolves names to scopes.
* Each Name is resolved to a NamedVarible, possibly in a NameScope
* if it is a local, or in no named scope if it is a global.
*/
public class NameResolver extends Visitor {
private NameScope scope = null;
private void pushScope() {
scope = new NameScope(scope);
}
private void popScope() {
scope = scope.outerScope;
}
public void visit(NameScope scope) {}
public void visit(Block block) {
pushScope();
block.scope = scope;
super.visit(block);
popScope();
}
public void visit(FuncBody body) {
pushScope();
scope.functionNestingCount++;
body.scope = scope;
super.visit(body);
popScope();
}
public void visit(LocalFuncDef stat) {
defineLocalVar(stat.name);
super.visit(stat);
}
public void visit(NumericFor stat) {
pushScope();
stat.scope = scope;
defineLocalVar(stat.name);
super.visit(stat);
popScope();
}
public void visit(GenericFor stat) {
pushScope();
stat.scope = scope;
defineLocalVars(stat.names);
super.visit(stat);
popScope();
}
public void visit(NameExp exp) {
exp.name.variable = resolveNameReference(exp.name);
super.visit(exp);
}
public void visit(FuncDef stat) {
stat.name.name.variable = resolveNameReference(stat.name.name);
stat.name.name.variable.hasassignments = true;
super.visit(stat);
}
public void visit(Assign stat) {
super.visit(stat);
for (int i = 0, n = stat.vars.size(); i < n; i++) {
VarExp v = (VarExp) stat.vars.get(i);
v.markHasAssignment();
}
}
public void visit(LocalAssign stat) {
visitExps(stat.values);
defineLocalVars(stat.names);
int n = stat.names.size();
int m = stat.values != null ? stat.values.size() : 0;
boolean isvarlist = m > 0 && m < n && ((Exp) stat.values.get(m - 1)).isvarargexp();
for (int i = 0; i < n && i < (isvarlist ? m - 1 : m); i++)
if (stat.values.get(i) instanceof Constant)
((Name) stat.names.get(i)).variable.initialValue = ((Constant) stat.values.get(i)).value;
if (!isvarlist)
for (int i = m; i < n; i++)
((Name) stat.names.get(i)).variable.initialValue = LuaValue.NIL;
}
public void visit(ParList pars) {
if (pars.names != null)
defineLocalVars(pars.names);
if (pars.isvararg)
scope.define("arg");
super.visit(pars);
}
protected void defineLocalVars(List<Name> names) {
for (int i = 0, n = names.size(); i < n; i++)
defineLocalVar((Name) names.get(i));
}
protected void defineLocalVar(Name name) {
name.variable = scope.define(name.name);
}
protected Variable resolveNameReference(Name name) {
Variable v = scope.find(name.name);
if (v.isLocal() && scope.functionNestingCount != v.definingScope.functionNestingCount)
v.isupvalue = true;
return v;
}
}