package org.rascalmpl.library.experiments.Compiler.RVM.Interpreter;
import java.util.ArrayList;
import java.util.NoSuchElementException;
import java.util.Scanner;
import java.util.regex.Pattern;
import org.rascalmpl.interpreter.TypeReifier;
import org.rascalmpl.interpreter.types.RascalTypeFactory;
import org.rascalmpl.value.IConstructor;
import org.rascalmpl.value.IValue;
import org.rascalmpl.value.IValueFactory;
import org.rascalmpl.value.type.Type;
import org.rascalmpl.value.type.TypeFactory;
import org.rascalmpl.values.uptr.RascalValueFactory;
public class Types {
private final TypeFactory tf = TypeFactory.getInstance();
private final TypeReifier tr;
public Types(IValueFactory vf) {
this.tr = new TypeReifier(vf);
}
public IValue typeToValue(Type t, RascalExecutionContext rex) {
// TODO: check rex.getSymbolDefinitions(); don't know if this is correct
System.err.println("TODO: check correctness of typeToValue here");
return tr.typeToValue(t, rex.getTypeStore(), rex.getSymbolDefinitions());
}
public Type symbolToType(IConstructor symbol) {
return tr.symbolToType(symbol);
}
public Type loadProduction(IConstructor prod) {
return tr.productionToConstructorType(prod);
}
private static Pattern identifier = Pattern.compile("\\w+");
private static Pattern openBracket = Pattern.compile("\\[");
private static Pattern closeBracket = Pattern.compile("\\]");
private static Pattern openPar = Pattern.compile("\\(");
private static Pattern closePar = Pattern.compile("\\)");
private static Pattern comma = Pattern.compile(",");
private static Pattern whiteSpace = Pattern.compile("\\s*");
static String preprocess(String input){
return input.replaceAll("(\\[|,|\\]|\\(|\\))", " $1 ");
}
Type parseType(String input){
Scanner s = new Scanner(preprocess(input));
return parseType(s);
}
public Type getFunctionType(String signature){
Scanner s = new Scanner(preprocess(signature));
try {
Type returnType = parseType(s);
s.next(identifier); // skip function name
s.next(openPar);
Object[] argumentTypes = parseFields(s);
s.next(closePar);
s.close();
return RascalTypeFactory.getInstance().functionType(returnType, tf.tupleType(argumentTypes), null);
} catch (NoSuchElementException e){
if(s.hasNext()){
String tok = s.next();
s.close();
throw new RuntimeException("Malformed function signature: " + signature + " at '" + tok + "'");
} else {
s.close();
throw new RuntimeException("Malformed function signature: " + signature + " near end, may be missing ')'");
}
}
}
public String getFunctionName(String signature){
Scanner s = new Scanner(preprocess(signature));
try {
parseType(s); // skip function type
String name = s.next(identifier);
s.close();
return name;
} catch (NoSuchElementException e){
if(s.hasNext()){
String tok = s.next();
s.close();
throw new RuntimeException("Malformed function signature: " + signature + " at '" + tok + "'");
} else {
s.close();
throw new RuntimeException("Malformed function signature: " + signature + " near end, may be missing ')'");
}
}
}
private Type parseType(Scanner s){
String kw = s.next(identifier);
Type res;
switch(kw){
case "int": return tf.integerType();
case "real": return tf.realType();
case "rat": return tf.rationalType();
case "bool": return tf.boolType();
case "datetime": return tf.dateTimeType();
case "num": return tf.numberType();
case "loc": return tf.sourceLocationType();
case "void": return tf.voidType();
case "value": return tf.valueType();
case "node": return tf.nodeType();
case "str": return tf.stringType();
case "set":
case "list":
s.next(openBracket);
Type elmType = parseType(s);
s.skip(whiteSpace);
s.next(closeBracket);
return kw.equals("list") ? tf.listType(elmType) : tf.setType(elmType);
case "tuple":
case "rel":
case "lrel":
s.next(openBracket);
Object[] flds = parseFields(s);
s.next(closeBracket);
switch(kw){
case "tuple": return tf.tupleType(flds);
case "rel": return tf.relType(flds);
case "lrel": return tf.lrelType(flds);
}
case "map":
s.next(openBracket);
flds = parseFields(s);
s.next(closeBracket);
if(flds.length == 4){
return tf.mapType((Type)flds[0], (Type)flds[2]);
} else {
throw new NoSuchElementException();
}
default:
res = tf.abstractDataType(RascalValueFactory.getStore(), kw);
return res;
//throw new CompilerError("Unimplemented: " + kw);
}
}
private Object[] parseFields(Scanner s){
ArrayList<Object> flds = new ArrayList<>();
do {
if(s.hasNext(comma)){
s.next(comma);
}
if(s.hasNext(closeBracket) || s.hasNext(closePar)){
break;
}
flds.add(parseType(s));
if(s.hasNext(identifier)){
flds.add(s.next());
} else {
flds.add("");
}
} while(s.hasNext(comma));
return flds.toArray();
}
// End deprecated
}