package org.rascalmpl.library.experiments.Compiler.RVM.Interpreter.repl.debug;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.rascalmpl.library.experiments.Compiler.RVM.Interpreter.Frame;
import org.rascalmpl.library.experiments.Compiler.RVM.Interpreter.RVMCore;
import org.rascalmpl.value.IConstructor;
import org.rascalmpl.value.IInteger;
import org.rascalmpl.value.IList;
import org.rascalmpl.value.IMap;
import org.rascalmpl.value.IString;
import org.rascalmpl.value.IValue;
import org.rascalmpl.value.IValueFactory;
import org.rascalmpl.values.ValueFactoryFactory;
public class EvalExpr {
private static IValueFactory vf = ValueFactoryFactory.getValueFactory();
private static final String intLiteral = "[0-9]+";
private static final String strLiteral = "\"[^\"]*\"";
private static final String variable = "[a-zA-Z][a-zA-Z0-9_]*";
private static final String baseExpr = intLiteral + "|" + strLiteral + "|" + variable;
private static final String subscript1 = "\\[(?<subscript1>" + baseExpr + ")\\]";
private static final String subscript2 = "\\[(?<subscript2>" + baseExpr + ")\\]";
private static final String field1 = "\\.(?<field1>" + baseExpr + ")";
private static final String field2 = "\\.(?<field2>" + baseExpr + ")";
private static final String expr = "(?<base>" + baseExpr + ")(" + subscript1 + "|" + field1 + ")?(" + subscript2 + "|" + field2 + ")?" ;
private static final Pattern exprPat = Pattern.compile(expr);
private static IValue baseValue(String base, RVMCore rvm, Frame currentFrame){
if(base.matches("[0-9]+")){
return vf.integer(Integer.valueOf(base));
}
if(base.startsWith("\"")){
return vf.string(base.substring(1, base.length()-1));
}
return getVar(base, rvm, currentFrame);
}
private static IValue getVar(String base, RVMCore rvm, Frame currentFrame){
for(Frame f = currentFrame; f != null; f = f.previousCallFrame){
IValue val = f.getVars().get(base);
if(val != null){
return val;
}
}
Map<IValue, IValue> mvars = rvm.getModuleVariables();
String moduleName = ":" + base;
IValue foundKey = null;
for(IValue ikey : mvars.keySet()){
String key = ((IString) ikey).getValue();
if(key.endsWith(moduleName)){
if(foundKey != null){ // Same module var name can be used in different modules
System.err.println(base + " is ambiguous, using " + foundKey);
} else {
foundKey = ikey;
}
return mvars.get(ikey);
}
}
return foundKey == null ? null : mvars.get(foundKey);
}
private static IValue subscript(IValue base, IValue index){
if(base.getType().isList()){
IList lst = (IList) base;
if(index.getType().isInteger()){
int i = ((IInteger) index).intValue();
return lst.get(i);
}
}
if(base.getType().isMap()){
IMap map = (IMap) base;
return map.get(index);
}
throw new RuntimeException("subscript: " + base);
}
private static IValue select(IValue base, String field){
if(base.getType().isAbstractData()){
IConstructor cons = (IConstructor) base;
return cons.get(field);
}
throw new RuntimeException("select: " + base);
}
static IValue eval(String expr, RVMCore rvm, Frame currentFrame){
Matcher matcher = exprPat.matcher(expr);
try {
if(matcher.matches()){
IValue base = baseValue(matcher.group("base"), rvm, currentFrame);
if(matcher.end("subscript1") > 0){
base = subscript(base, baseValue(matcher.group("subscript1"), rvm, currentFrame));
}
else if(matcher.end("field1") > 0){
base = select(base, matcher.group("field1"));
}
if(matcher.end("subscript2") > 0){
base = subscript(base, baseValue(matcher.group("subscript2"), rvm, currentFrame));
}
else if(matcher.end("field2") > 0){
base = select(base, matcher.group("field2"));
}
return base;
}
}
catch (Exception e){
}
return null;
}
}