package org.dynjs.parser.ast;
import org.dynjs.exception.ThrowException;
import org.dynjs.parser.CodeVisitor;
import org.dynjs.parser.js.Position;
import org.dynjs.runtime.ExecutionContext;
import org.dynjs.runtime.Reference;
import org.dynjs.runtime.Types;
import org.dynjs.runtime.linker.DynJSBootstrapper;
import java.lang.invoke.CallSite;
import java.util.ArrayList;
import java.util.List;
public class VariableDeclaration {
public static final List<VariableDeclaration> EMPTY_LIST = new ArrayList<>();
private Position position;
private String identifier;
private Expression expr;
private CallSite get;
public VariableDeclaration(Position position, String identifier, Expression initializerExpr) {
this.position = position;
this.identifier = identifier;
this.expr = initializerExpr;
if (this.expr != null) {
this.get = DynJSBootstrapper.factory().createGet(initializerExpr.getPosition());
}
}
public Position getPosition() {
return this.position;
}
public Expression getExpr() {
return this.expr;
}
public String getIdentifier() {
return this.identifier;
}
public String dump(String indent) {
StringBuilder buf = new StringBuilder();
buf.append(indent + getClass().getSimpleName() + "(" + this.identifier + ")\n");
if (this.expr != null) {
buf.append(this.expr.dump(indent + " "));
}
return buf.toString();
}
public Object accept(Object context, CodeVisitor visitor, boolean strict) {
return visitor.visit(context, this, strict);
}
public String interpret(ExecutionContext context, boolean debug) {
if (this.expr != null) {
Object value = getValue(this.get, context, this.expr.interpret(context, debug));
Reference var = context.resolve(getIdentifier());
var.putValue(context, value);
}
return (getIdentifier());
}
public int getSizeMetric() {
if (this.expr != null) {
return this.expr.getSizeMetric() + 3;
}
return 3;
}
public String toString() {
StringBuilder buf = new StringBuilder();
buf.append(this.identifier);
if (this.expr != null) {
buf.append(" = ");
buf.append(this.expr);
}
return buf.toString();
}
protected Object getValue(CallSite callSite, ExecutionContext context, Object obj) {
if (obj instanceof Reference) {
Reference ref = (Reference) obj;
String name = ref.getReferencedName();
try {
Object result = callSite.getTarget().invoke(obj, context, name);
return result;
} catch (ThrowException e) {
throw e;
} catch (NoSuchMethodError e) {
if (ref.isPropertyReference() && !ref.isUnresolvableReference()) {
return Types.UNDEFINED;
}
throw new ThrowException(context, context.createReferenceError("unable to reference: " + name));
} catch (Throwable e) {
throw new ThrowException(context, e);
}
} else {
return obj;
}
}
}