]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/elaboration/constraints/ConstraintEnvironment.java
Migrated source code from Simantics SVN
[simantics/platform.git] / bundles / org.simantics.scl.compiler / src / org / simantics / scl / compiler / internal / elaboration / constraints / ConstraintEnvironment.java
diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/elaboration/constraints/ConstraintEnvironment.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/elaboration/constraints/ConstraintEnvironment.java
new file mode 100644 (file)
index 0000000..d19dfee
--- /dev/null
@@ -0,0 +1,297 @@
+package org.simantics.scl.compiler.internal.elaboration.constraints;
+
+import gnu.trove.map.hash.THashMap;
+
+import org.cojen.classfile.TypeDesc;
+import org.simantics.scl.compiler.common.exceptions.InternalCompilerError;
+import org.simantics.scl.compiler.constants.ClassConstant;
+import org.simantics.scl.compiler.constants.JavaConstructor;
+import org.simantics.scl.compiler.constants.JavaStaticField;
+import org.simantics.scl.compiler.constants.JavaStaticMethod;
+import org.simantics.scl.compiler.constants.StringConstant;
+import org.simantics.scl.compiler.elaboration.expressions.EApply;
+import org.simantics.scl.compiler.elaboration.expressions.EConstant;
+import org.simantics.scl.compiler.elaboration.expressions.ELiteral;
+import org.simantics.scl.compiler.elaboration.java.Builtins;
+import org.simantics.scl.compiler.elaboration.modules.TypeClass;
+import org.simantics.scl.compiler.elaboration.modules.TypeClassInstance;
+import org.simantics.scl.compiler.environment.Environment;
+import org.simantics.scl.compiler.errors.Locations;
+import org.simantics.scl.compiler.types.TApply;
+import org.simantics.scl.compiler.types.TCon;
+import org.simantics.scl.compiler.types.TFun;
+import org.simantics.scl.compiler.types.TPred;
+import org.simantics.scl.compiler.types.TUnion;
+import org.simantics.scl.compiler.types.TVar;
+import org.simantics.scl.compiler.types.Type;
+import org.simantics.scl.compiler.types.Types;
+
+public class ConstraintEnvironment {
+    Environment environment;
+    
+    public ConstraintEnvironment(Environment environment) {
+        this.environment = environment;
+    }
+
+    public Superconstraint[] getSuperconstraints(TPred constraint) {
+        TypeClass tc = environment.getTypeClass(constraint.typeClass);
+        if(tc == null) {
+            throw new InternalCompilerError("Didn't find constraint " + constraint + ". Maybe Prelude is not loaded?");
+        }
+        if(tc.context.length == 0)
+            return Superconstraint.EMPTY_ARRAY;
+        Superconstraint[] result = new Superconstraint[tc.context.length];
+        for(int i=0;i<result.length;++i) {
+            result[i] = new Superconstraint(
+                    (TPred)tc.context[i].replace(tc.parameters, constraint.parameters),
+                    tc.superGenerators[i]
+                    );
+        }
+        return result;
+    }
+    
+    private static final Type SERIALIZABLE_BOOLEAN = Types.pred(Types.SERIALIZABLE, Types.BOOLEAN);
+    private static final Type SERIALIZABLE_BYTE = Types.pred(Types.SERIALIZABLE, Types.BYTE);
+    private static final Type SERIALIZABLE_SHORT = Types.pred(Types.SERIALIZABLE, Types.SHORT);
+    private static final Type SERIALIZABLE_INTEGER = Types.pred(Types.SERIALIZABLE, Types.INTEGER);
+    private static final Type SERIALIZABLE_LONG = Types.pred(Types.SERIALIZABLE, Types.LONG);
+    private static final Type SERIALIZABLE_FLOAT = Types.pred(Types.SERIALIZABLE, Types.FLOAT);
+    private static final Type SERIALIZABLE_DOUBLE = Types.pred(Types.SERIALIZABLE, Types.DOUBLE);
+    private static final Type SERIALIZABLE_STRING = Types.pred(Types.SERIALIZABLE, Types.STRING);
+    
+    private static final Type SERIALIZABLE_BOOLEAN_ARRAY = Types.pred(Types.SERIALIZABLE, Types.BOOLEAN_ARRAY);
+    private static final Type SERIALIZABLE_BYTE_ARRAY = Types.pred(Types.SERIALIZABLE, Types.BYTE_ARRAY);
+    private static final Type SERIALIZABLE_SHORT_ARRAY = Types.pred(Types.SERIALIZABLE, Types.SHORT_ARRAY);
+    private static final Type SERIALIZABLE_INTEGER_ARRAY = Types.pred(Types.SERIALIZABLE, Types.INTEGER_ARRAY);
+    private static final Type SERIALIZABLE_LONG_ARRAY = Types.pred(Types.SERIALIZABLE, Types.LONG_ARRAY);
+    private static final Type SERIALIZABLE_FLOAT_ARRAY = Types.pred(Types.SERIALIZABLE, Types.FLOAT_ARRAY);
+    private static final Type SERIALIZABLE_DOUBLE_ARRAY = Types.pred(Types.SERIALIZABLE, Types.DOUBLE_ARRAY);
+    
+    private static final Type SERIALIZABLE_BOOLEAN_VECTOR = Types.pred(Types.SERIALIZABLE, Types.pred(Types.VECTOR, Types.BOOLEAN));
+    private static final Type SERIALIZABLE_BYTE_VECTOR = Types.pred(Types.SERIALIZABLE, Types.pred(Types.VECTOR, Types.BYTE));
+    private static final Type SERIALIZABLE_SHORT_VECTOR = Types.pred(Types.SERIALIZABLE, Types.pred(Types.VECTOR, Types.SHORT));
+    private static final Type SERIALIZABLE_INTEGER_VECTOR = Types.pred(Types.SERIALIZABLE, Types.pred(Types.VECTOR, Types.INTEGER));
+    private static final Type SERIALIZABLE_LONG_VECTOR = Types.pred(Types.SERIALIZABLE, Types.pred(Types.VECTOR, Types.LONG));
+    private static final Type SERIALIZABLE_FLOAT_VECTOR = Types.pred(Types.SERIALIZABLE, Types.pred(Types.VECTOR, Types.FLOAT));
+    private static final Type SERIALIZABLE_DOUBLE_VECTOR = Types.pred(Types.SERIALIZABLE, Types.pred(Types.VECTOR, Types.DOUBLE));
+    
+    private static final Type SERIALIZABLE_TUPLE0 = Types.pred(Types.SERIALIZABLE, Types.tuple());
+       private static final Type SERIALIZABLE_VARIANT = Types.pred(Types.SERIALIZABLE, Types.VARIANT);
+    
+    public Reduction reduce(TPred constraint) {
+        // VecComp
+        if(constraint.typeClass == Types.VEC_COMP) {
+            Type parameter = Types.canonical(constraint.parameters[0]);
+            if(parameter.isGround())
+                return new Reduction(new ELiteral(new ClassConstant(Types.pred(Types.VEC_COMP, parameter), parameter)),
+                        Type.EMPTY_ARRAY, TPred.EMPTY_ARRAY);
+        }
+        // Serializable
+        if(constraint.typeClass == Types.SERIALIZABLE) {
+            Type parameter = Types.canonical(constraint.parameters[0]);            
+            if(parameter instanceof TCon) {
+                TCon con = (TCon)parameter;
+                if(con == Types.DOUBLE)
+                    return new Reduction(
+                            new ELiteral(new JavaStaticField("org/simantics/databoard/Bindings", "DOUBLE", Types.NO_EFFECTS, TypeDesc.forClass("org/simantics/databoard/binding/DoubleBinding"), SERIALIZABLE_DOUBLE, -1)),
+                                    Type.EMPTY_ARRAY, TPred.EMPTY_ARRAY);
+                else if(con == Types.STRING)
+                    return new Reduction(
+                            new ELiteral(new JavaStaticField("org/simantics/databoard/Bindings", "STRING", Types.NO_EFFECTS, TypeDesc.forClass("org/simantics/databoard/binding/StringBinding"), SERIALIZABLE_STRING, -1)),
+                                    Type.EMPTY_ARRAY, TPred.EMPTY_ARRAY);
+                else if(con == Types.INTEGER)
+                    return new Reduction(
+                            new ELiteral(new JavaStaticField("org/simantics/databoard/Bindings", "INTEGER", Types.NO_EFFECTS, TypeDesc.forClass("org/simantics/databoard/binding/IntegerBinding"), SERIALIZABLE_INTEGER, -1)),
+                                    Type.EMPTY_ARRAY, TPred.EMPTY_ARRAY);
+                else if(con == Types.BOOLEAN)
+                    return new Reduction(
+                            new ELiteral(new JavaStaticField("org/simantics/databoard/Bindings", "BOOLEAN", Types.NO_EFFECTS, TypeDesc.forClass("org/simantics/databoard/binding/BooleanBinding"), SERIALIZABLE_BOOLEAN, -1)),
+                                    Type.EMPTY_ARRAY, TPred.EMPTY_ARRAY);
+                else if(con == Types.BYTE)
+                    return new Reduction(
+                            new ELiteral(new JavaStaticField("org/simantics/databoard/Bindings", "BYTE", Types.NO_EFFECTS, TypeDesc.forClass("org/simantics/databoard/binding/ByteBinding"), SERIALIZABLE_BYTE, -1)),
+                                    Type.EMPTY_ARRAY, TPred.EMPTY_ARRAY);
+                else if(con == Types.FLOAT)
+                    return new Reduction(
+                            new ELiteral(new JavaStaticField("org/simantics/databoard/Bindings", "FLOAT", Types.NO_EFFECTS, TypeDesc.forClass("org/simantics/databoard/binding/FloatBinding"), SERIALIZABLE_FLOAT, -1)),
+                                    Type.EMPTY_ARRAY, TPred.EMPTY_ARRAY);
+                else if(con == Types.LONG)
+                    return new Reduction(
+                            new ELiteral(new JavaStaticField("org/simantics/databoard/Bindings", "LONG", Types.NO_EFFECTS, TypeDesc.forClass("org/simantics/databoard/binding/LongBinding"), SERIALIZABLE_LONG, -1)),
+                                    Type.EMPTY_ARRAY, TPred.EMPTY_ARRAY);
+                else if(con == Types.tupleConstructor(0))
+                    return new Reduction(
+                            new ELiteral(new JavaStaticField("org/simantics/databoard/Bindings", "VOID", Types.NO_EFFECTS, TypeDesc.forClass("org/simantics/databoard/binding/Binding"), SERIALIZABLE_TUPLE0, -1)),
+                                    Type.EMPTY_ARRAY, TPred.EMPTY_ARRAY);
+                else if(con == Types.VARIANT)
+                    return new Reduction(
+                            new ELiteral(new JavaStaticField("org/simantics/databoard/Bindings", "VARIANT", Types.NO_EFFECTS, TypeDesc.forClass("org/simantics/databoard/binding/VariantBinding"), SERIALIZABLE_VARIANT, -1)),
+                                    Type.EMPTY_ARRAY, TPred.EMPTY_ARRAY);
+                else if(con == Types.DOUBLE_ARRAY)
+                    return new Reduction(
+                            new ELiteral(new JavaStaticField("org/simantics/databoard/Bindings", "DOUBLE_ARRAY", Types.NO_EFFECTS, TypeDesc.forClass("org/simantics/databoard/binding/ArrayBinding"), SERIALIZABLE_DOUBLE_ARRAY, -1)),
+                                    Type.EMPTY_ARRAY, TPred.EMPTY_ARRAY);
+                else if(con == Types.INTEGER_ARRAY)
+                    return new Reduction(
+                            new ELiteral(new JavaStaticField("org/simantics/databoard/Bindings", "INTEGER_ARRAY", Types.NO_EFFECTS, TypeDesc.forClass("org/simantics/databoard/binding/ArrayBinding"), SERIALIZABLE_INTEGER_ARRAY, -1)),
+                                    Type.EMPTY_ARRAY, TPred.EMPTY_ARRAY);
+                else if(con == Types.BOOLEAN_ARRAY)
+                    return new Reduction(
+                            new ELiteral(new JavaStaticField("org/simantics/databoard/Bindings", "BOOLEAN_ARRAY", Types.NO_EFFECTS, TypeDesc.forClass("org/simantics/databoard/binding/ArrayBinding"), SERIALIZABLE_BOOLEAN_ARRAY, -1)),
+                                    Type.EMPTY_ARRAY, TPred.EMPTY_ARRAY);
+                else if(con == Types.BYTE_ARRAY)
+                    return new Reduction(
+                            new ELiteral(new JavaStaticField("org/simantics/databoard/Bindings", "BYTE_ARRAY", Types.NO_EFFECTS, TypeDesc.forClass("org/simantics/databoard/binding/ArrayBinding"), SERIALIZABLE_BYTE_ARRAY, -1)),
+                                    Type.EMPTY_ARRAY, TPred.EMPTY_ARRAY);
+                else if(con == Types.FLOAT_ARRAY)
+                    return new Reduction(
+                            new ELiteral(new JavaStaticField("org/simantics/databoard/Bindings", "FLOAT_ARRAY", Types.NO_EFFECTS, TypeDesc.forClass("org/simantics/databoard/binding/ArrayBinding"), SERIALIZABLE_FLOAT_ARRAY, -1)),
+                                    Type.EMPTY_ARRAY, TPred.EMPTY_ARRAY);
+                else if(con == Types.LONG_ARRAY)
+                    return new Reduction(
+                            new ELiteral(new JavaStaticField("org/simantics/databoard/Bindings", "LONG_ARRAY", Types.NO_EFFECTS, TypeDesc.forClass("org/simantics/databoard/binding/ArrayBinding"), SERIALIZABLE_LONG_ARRAY, -1)),
+                                    Type.EMPTY_ARRAY, TPred.EMPTY_ARRAY);
+            }
+            else if(parameter instanceof TApply) {
+                TApply apply1 = (TApply)parameter;
+                Type f1 = Types.canonical(apply1.function);
+                Type p1 = Types.canonical(apply1.parameter);
+                if(f1 instanceof TCon) {
+                    TCon con = (TCon)f1;
+                    if(con == Types.LIST)
+                        return new Reduction(
+                            new ELiteral(new JavaConstructor("org/simantics/databoard/binding/impl/ArrayListBinding", Types.NO_EFFECTS, 
+                                    Types.pred(Types.SERIALIZABLE, Types.list(p1)), Types.pred(Types.SERIALIZABLE, p1))),
+                            Type.EMPTY_ARRAY, new TPred[] { Types.pred(Types.SERIALIZABLE, p1) });
+                    else if(con == Types.MAYBE)
+                        return new Reduction(
+                            new ELiteral(new JavaConstructor("org/simantics/databoard/binding/impl/OptionalBindingDefault", Types.NO_EFFECTS, 
+                                    Types.pred(Types.SERIALIZABLE, Types.apply(Types.MAYBE, p1)), Types.pred(Types.SERIALIZABLE, p1))),
+                            Type.EMPTY_ARRAY, new TPred[] { Types.pred(Types.SERIALIZABLE, p1) });
+                    else if(con == Types.VECTOR) {
+                       if (p1 == Types.DOUBLE)
+                                   return new Reduction(
+                                           new ELiteral(new JavaStaticField("org/simantics/databoard/Bindings", "DOUBLE_ARRAY", Types.NO_EFFECTS, TypeDesc.forClass("org/simantics/databoard/binding/ArrayBinding"), SERIALIZABLE_DOUBLE_VECTOR, -1)),
+                                                   Type.EMPTY_ARRAY, TPred.EMPTY_ARRAY);                               
+                        else if(p1 == Types.INTEGER)
+                            return new Reduction(
+                                    new ELiteral(new JavaStaticField("org/simantics/databoard/Bindings", "INTEGER_ARRAY", Types.NO_EFFECTS, TypeDesc.forClass("org/simantics/databoard/binding/ArrayBinding"), SERIALIZABLE_INTEGER_VECTOR, -1)),
+                                            Type.EMPTY_ARRAY, TPred.EMPTY_ARRAY);
+                        else if(p1 == Types.BOOLEAN)
+                            return new Reduction(
+                                    new ELiteral(new JavaStaticField("org/simantics/databoard/Bindings", "BOOLEAN_ARRAY", Types.NO_EFFECTS, TypeDesc.forClass("org/simantics/databoard/binding/ArrayBinding"), SERIALIZABLE_BOOLEAN_VECTOR, -1)),
+                                            Type.EMPTY_ARRAY, TPred.EMPTY_ARRAY);
+                        else if(p1 == Types.BYTE)
+                            return new Reduction(
+                                    new ELiteral(new JavaStaticField("org/simantics/databoard/Bindings", "BYTE_ARRAY", Types.NO_EFFECTS, TypeDesc.forClass("org/simantics/databoard/binding/ArrayBinding"), SERIALIZABLE_BYTE_VECTOR, -1)),
+                                            Type.EMPTY_ARRAY, TPred.EMPTY_ARRAY);
+                        else if(p1 == Types.FLOAT)
+                            return new Reduction(
+                                    new ELiteral(new JavaStaticField("org/simantics/databoard/Bindings", "FLOAT_ARRAY", Types.NO_EFFECTS, TypeDesc.forClass("org/simantics/databoard/binding/ArrayBinding"), SERIALIZABLE_FLOAT_VECTOR, -1)),
+                                            Type.EMPTY_ARRAY, TPred.EMPTY_ARRAY);
+                        else if(p1 == Types.LONG)
+                            return new Reduction(
+                                    new ELiteral(new JavaStaticField("org/simantics/databoard/Bindings", "LONG_ARRAY", Types.NO_EFFECTS, TypeDesc.forClass("org/simantics/databoard/binding/ArrayBinding"), SERIALIZABLE_LONG_VECTOR, -1)),
+                                            Type.EMPTY_ARRAY, TPred.EMPTY_ARRAY);
+                        else
+                               return new Reduction(
+                                               new ELiteral(new JavaStaticMethod("org/simantics/databoard/Bindings", "getArrayBinding", Types.NO_EFFECTS, 
+                                    Types.pred(Types.SERIALIZABLE, Types.pred(Types.VECTOR, p1)), Types.pred(Types.SERIALIZABLE, p1))),
+                            Type.EMPTY_ARRAY, new TPred[] { Types.pred(Types.SERIALIZABLE, p1) });
+                    }
+                }
+                else if(f1 instanceof TApply) {
+                    TApply apply2 = (TApply)parameter;
+                    Type f2 = Types.canonical(apply2.function);
+                    Type p2 = Types.canonical(apply2.parameter);
+                    if(f2 instanceof TCon) {
+                        TCon con = (TCon)f2;
+                        /*if(con == Types.tupleConstructor(2)) {
+                            return new Reduction(
+                                    new EConstant(Builtins.TUPLE_CONSTRUCTORS[2]new JavaConstructor("org/simantics/databoard/binding/impl/ArrayListBinding", Types.NO_EFFECTS, 
+                                            Types.pred(Types.SERIALIZABLE, p1), Types.pred(Types.SERIALIZABLE, Types.list(p1)))),
+                                    Type.EMPTY_ARRAY, 
+                                    new TPred[] { Types.pred(Types.SERIALIZABLE, p2), Types.pred(Types.SERIALIZABLE, p1) });
+                        }*/
+                    }
+                }
+            }
+            
+               // Default to a binding as an ObjectVariantBinding
+            // This can be applied only if the type is ground type (i.e. does not contain type variables),
+            // because otherwise the Serializable instance could be provided as a parameter to the function
+            if(parameter.isGround())
+                return new Reduction(
+                        new ELiteral(new JavaStaticField("org/simantics/databoard/Bindings", "OBJECT", Types.NO_EFFECTS,
+                                TypeDesc.forClass("org/simantics/databoard/binding/VariantBinding"), Types.pred(Types.SERIALIZABLE, parameter), -1)),
+                                Type.EMPTY_ARRAY, TPred.EMPTY_ARRAY);
+        }
+        
+        // Typeable
+        else if(constraint.typeClass == Types.TYPEABLE) {
+            Type parameter = Types.canonical(constraint.parameters[0]);
+            if(parameter instanceof TCon) {
+                TCon con = (TCon)parameter;                        
+                return new Reduction(
+                        new EApply(Locations.NO_LOCATION,
+                                new EConstant(Builtins.INSTANCE.getValue("TCon")),
+                                new ELiteral(new StringConstant(con.module)),
+                                new ELiteral(new StringConstant(con.name))),
+                                Type.EMPTY_ARRAY, TPred.EMPTY_ARRAY);
+            }
+            else if(parameter instanceof TApply) {
+                TApply apply = (TApply)parameter;
+                return new Reduction(
+                        new EConstant(Builtins.INSTANCE.getValue("TApply")),
+                        Type.EMPTY_ARRAY, new TPred[] {
+                            Types.pred(Types.TYPEABLE, apply.function),
+                            Types.pred(Types.TYPEABLE, apply.parameter),
+                        });
+            }
+            else if(parameter instanceof TFun) {
+                TFun fun = (TFun)parameter;
+                return new Reduction(
+                        new EConstant(Builtins.INSTANCE.getValue("TFun")),
+                        Type.EMPTY_ARRAY, new TPred[] {
+                            Types.pred(Types.TYPEABLE, fun.domain),
+                            Types.pred(Types.TYPEABLE, fun.effect),
+                            Types.pred(Types.TYPEABLE, fun.range)
+                        });
+            }
+            else if(parameter instanceof TUnion) {
+                TUnion union = (TUnion)parameter;
+                
+                /*TPred[] demands = new TPred[union.effects.length];
+                for(int i=0;i<union.effects.length;++i)
+                    demands[i] = Types.pred(Types.TYPEABLE, union.effects[i]);*/
+                if(union.effects.length == 0)
+                return new Reduction(
+                            new EConstant(Builtins.INSTANCE.getValue("TPure")),
+                            Type.EMPTY_ARRAY,
+                            TPred.EMPTY_ARRAY);
+            }
+        }
+        
+        // Standard case
+        THashMap<TVar, Type> substitution = new THashMap<TVar, Type>(); 
+        for(TypeClassInstance inst : environment.getInstances(constraint.typeClass)) {
+            if(Types.match(inst.instance, constraint, substitution)) {
+                TPred[] demands = new TPred[inst.context.length];
+                for(int i=0;i<demands.length;++i) {
+                    demands[i] = (TPred)inst.context[i].replace(substitution);
+                }
+                Type[] parameters = new Type[inst.generatorParameters.length];
+                for(int i=0;i<parameters.length;++i) {
+                    Type parameter = substitution.get(inst.generatorParameters[i]);
+                    if(parameter == null)
+                        parameter = inst.generatorParameters[i]; // TODO Is this correct?
+                    parameters[i] = parameter;
+                }
+                return new Reduction(new ELiteral(inst.generator), parameters, demands);
+            }
+            else
+                substitution.clear();
+        }
+        return null;
+    }
+}