]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/Expression.java
Migrated source code from Simantics SVN
[simantics/platform.git] / bundles / org.simantics.scl.compiler / src / org / simantics / scl / compiler / elaboration / expressions / Expression.java
diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/Expression.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/Expression.java
new file mode 100755 (executable)
index 0000000..83d7ec4
--- /dev/null
@@ -0,0 +1,359 @@
+package org.simantics.scl.compiler.elaboration.expressions;\r
+\r
+import gnu.trove.map.hash.TObjectIntHashMap;\r
+import gnu.trove.set.hash.THashSet;\r
+import gnu.trove.set.hash.TIntHashSet;\r
+\r
+import java.util.ArrayList;\r
+\r
+import org.simantics.scl.compiler.common.exceptions.InternalCompilerError;\r
+import org.simantics.scl.compiler.common.precedence.Precedence;\r
+import org.simantics.scl.compiler.elaboration.contexts.ReplaceContext;\r
+import org.simantics.scl.compiler.elaboration.contexts.SimplificationContext;\r
+import org.simantics.scl.compiler.elaboration.contexts.TranslationContext;\r
+import org.simantics.scl.compiler.elaboration.contexts.TypingContext;\r
+import org.simantics.scl.compiler.elaboration.errors.NotPatternException;\r
+import org.simantics.scl.compiler.elaboration.expressions.lhstype.LhsType;\r
+import org.simantics.scl.compiler.elaboration.expressions.lhstype.PatternMatchingLhs;\r
+import org.simantics.scl.compiler.elaboration.expressions.printing.ExpressionToStringVisitor;\r
+import org.simantics.scl.compiler.elaboration.query.QAtom;\r
+import org.simantics.scl.compiler.elaboration.relations.SCLRelation;\r
+import org.simantics.scl.compiler.environment.Environment;\r
+import org.simantics.scl.compiler.internal.codegen.references.IVal;\r
+import org.simantics.scl.compiler.internal.codegen.writer.CodeWriter;\r
+import org.simantics.scl.compiler.internal.elaboration.decomposed.DecomposedExpression;\r
+import org.simantics.scl.compiler.internal.elaboration.utils.ExpressionDecorator;\r
+import org.simantics.scl.compiler.internal.interpreted.IExpression;\r
+import org.simantics.scl.compiler.internal.parsing.Symbol;\r
+import org.simantics.scl.compiler.top.ExpressionInterpretationContext;\r
+import org.simantics.scl.compiler.types.TForAll;\r
+import org.simantics.scl.compiler.types.TFun;\r
+import org.simantics.scl.compiler.types.TPred;\r
+import org.simantics.scl.compiler.types.TVar;\r
+import org.simantics.scl.compiler.types.Type;\r
+import org.simantics.scl.compiler.types.Types;\r
+import org.simantics.scl.compiler.types.exceptions.MatchException;\r
+import org.simantics.scl.compiler.types.kinds.Kinds;\r
+import org.simantics.scl.compiler.types.util.Typed;\r
+\r
+public abstract class Expression extends Symbol implements Typed {\r
+    public static final Expression[] EMPTY_ARRAY = new Expression[0];\r
+    \r
+    transient\r
+    private Type type;\r
+    \r
+    public Expression() {\r
+    }\r
+    \r
+    public Expression(long loc) {\r
+        this.location = loc;\r
+    }\r
+        \r
+    @Override\r
+    public Type getType() {\r
+        if(type == null) {\r
+            try {\r
+                updateType();\r
+            } catch (MatchException e) {\r
+                throw new InternalCompilerError(e);\r
+            }\r
+            if(type == null)\r
+                throw new InternalCompilerError(getClass().getSimpleName() + \r
+                        ".updateType couldn't compute its type.");\r
+        }\r
+        return type;\r
+    }\r
+\r
+    public void setType(Type type) {\r
+        if(type == null)\r
+            throw new NullPointerException();\r
+        this.type = type;\r
+    }\r
+       \r
+       /**\r
+        * Infers the type of the expression without any context. Adds type\r
+     * applications and lambdas if needed.      \r
+        */\r
+    public Expression inferType(TypingContext context) {\r
+        return checkBasicType(context, Types.metaVar(Kinds.STAR));\r
+    }\r
+       \r
+       public Expression checkBasicType(TypingContext context, Type requiredType) {\r
+           return context.subsume(inferType(context), requiredType);\r
+       }\r
+       \r
+       /**\r
+        * Checks the type of the expression against the given type. Adds type\r
+        * applications and lambdas if needed.\r
+        */\r
+       public final Expression checkType(TypingContext context, Type requiredType) {\r
+           //System.out.println("checkType: " + this + " :: " + requiredType);\r
+           if(!context.isInPattern()) {\r
+               requiredType = Types.weakCanonical(requiredType);\r
+           if(requiredType instanceof TForAll) {\r
+                TForAll forAll = (TForAll)requiredType;\r
+                TVar var = forAll.var;\r
+                TVar newVar = Types.var(var.getKind());\r
+                requiredType = Types.canonical(forAll.type).replace(var, newVar);\r
+                return new ELambdaType(new TVar[] {newVar}, checkType(context, requiredType));\r
+            }\r
+           while(requiredType instanceof TFun) {\r
+                TFun fun = (TFun)requiredType;\r
+                if(fun.domain instanceof TPred) { // No need to canonicalize\r
+                    ArrayList<Variable> constraints = new ArrayList<Variable>(2);\r
+                    while(true) {\r
+                        constraints.add(new Variable("constraint", fun.domain));\r
+                        requiredType = Types.canonical(fun.range);\r
+                        if(!(requiredType instanceof TFun))\r
+                            break;\r
+                        fun = (TFun)requiredType;\r
+                        if(!(fun.domain instanceof TPred))\r
+                            break;\r
+                    }\r
+                    context.pushConstraintFrame(constraints.toArray(new Variable[constraints.size()]));\r
+                    Expression expression = checkType(context, requiredType);\r
+                    context.popConstraintFrame();\r
+                    for(int i=constraints.size()-1;i>=0;--i)\r
+                        expression = new ESimpleLambda(constraints.get(i), expression);\r
+                    return expression;\r
+                }\r
+                else if(fun.domain == Types.PUNIT) {\r
+                    context.pushEffectUpperBound(location, fun.effect);\r
+                    Expression expr = checkType(context, fun.range);\r
+                    context.popEffectUpperBound();       \r
+                    \r
+                    // Wrap\r
+                    Variable var = new Variable("punit", Types.PUNIT);\r
+                    return new ESimpleLambda(location, var, fun.effect, expr);\r
+                }\r
+                else\r
+                    break;\r
+            }\r
+           }\r
+           return checkBasicType(context, requiredType); \r
+       }\r
+\r
+       public abstract void collectRefs(TObjectIntHashMap<Object> allRefs, TIntHashSet refs);\r
+       public abstract void collectVars(TObjectIntHashMap<Variable> allVars, TIntHashSet vars);\r
+       public abstract void forVariables(VariableProcedure procedure);\r
+       \r
+       public Expression decomposeMatching() {\r
+        return this;\r
+    }\r
+\r
+       public String toString() {\r
+           StringBuilder b = new StringBuilder();\r
+           ExpressionToStringVisitor visitor = new ExpressionToStringVisitor(b);\r
+           accept(visitor);\r
+           return b.toString();\r
+    }\r
+\r
+       protected abstract void updateType() throws MatchException;\r
+       \r
+       public static class TypeValidationException extends Exception {\r
+        private static final long serialVersionUID = 3181298127162041248L;  \r
+        \r
+        long loc;\r
+\r
+        public TypeValidationException(long loc) {\r
+            this.loc = loc;\r
+        }\r
+        \r
+        public long getLoc() {\r
+            return loc;\r
+        }\r
+\r
+        public TypeValidationException(long loc, Throwable cause) {\r
+            super(cause);\r
+            this.loc = loc;\r
+        }\r
+    }\r
+    \r
+    public static void assertEquals(long loc, Type a, Type b) throws TypeValidationException {\r
+        if(!Types.equals(a, b))\r
+            throw new TypeValidationException(loc);\r
+    }\r
+\r
+       public abstract IVal toVal(Environment env, CodeWriter w);\r
+               \r
+       public Expression closure(TVar ... vars) {\r
+           if(vars.length == 0)\r
+            return this;\r
+        return new ELambdaType(vars, this);\r
+       }\r
+    \r
+    public abstract void collectFreeVariables(THashSet<Variable> vars);\r
+    \r
+    public Expression simplify(SimplificationContext context) {\r
+        System.out.println("#############################");\r
+        System.out.println(this);\r
+        throw new InternalCompilerError(location, getClass().getSimpleName() + " does not support simplify method.");\r
+    }\r
+\r
+    public abstract Expression resolve(TranslationContext context);\r
+    \r
+    /**\r
+     * Returns head of the pattern.\r
+     */\r
+    public EVar getPatternHead() throws NotPatternException {\r
+        throw new NotPatternException(this);\r
+    }\r
+    \r
+    public LhsType getLhsType() throws NotPatternException {\r
+        throw new NotPatternException(this);\r
+    }\r
+\r
+    protected void collectVariableNames(PatternMatchingLhs lhsType) throws NotPatternException {\r
+        throw new NotPatternException(this);\r
+    }\r
+\r
+    public void getParameters(TranslationContext translationContext,\r
+            ArrayList<Expression> parameters) {\r
+        throw new InternalCompilerError("Class " + getClass().getSimpleName() + " does not support getParameters.");        \r
+    }\r
+\r
+    public Expression resolveAsPattern(TranslationContext context) {\r
+        context.getErrorLog().log(location, "Pattern was expected here.");\r
+        return new EError();\r
+    }\r
+\r
+    public void removeFreeVariables(THashSet<Variable> vars) {\r
+        throw new InternalCompilerError(getClass().getSimpleName() + " is not a pattern.");\r
+    }\r
+    \r
+    public Expression checkTypeAsPattern(TypingContext context, Type requiredType) {\r
+        if(context.isInPattern())\r
+            throw new InternalCompilerError("Already in a pattern.");\r
+        context.setInPattern(true);\r
+        Expression expression = checkType(context, requiredType);\r
+        context.setInPattern(false);\r
+        return expression;\r
+    }\r
+\r
+    public THashSet<Variable> getFreeVariables() {\r
+        THashSet<Variable> result = new THashSet<Variable>();\r
+        collectFreeVariables(result);\r
+        return result;\r
+    }    \r
+\r
+    public static Expression[] concat(Expression[] a, Expression[] b) {\r
+        if(a.length == 0)\r
+            return b;\r
+        if(b.length == 0)\r
+            return a;\r
+        Expression[] result = new Expression[a.length + b.length];\r
+        for(int i=0;i<a.length;++i)\r
+            result[i] = a[i];\r
+        for(int i=0;i<b.length;++i)\r
+            result[i+a.length] = b[i];\r
+        return result;\r
+    }\r
+\r
+    public Expression replace(ReplaceContext context) {\r
+        throw new InternalCompilerError(getClass().getSimpleName() + " does not support replace.");\r
+    }\r
+    \r
+    public static Expression[] replace(ReplaceContext context, Expression[] expressions) {\r
+        Expression[] result = new Expression[expressions.length];\r
+        for(int i=0;i<expressions.length;++i)\r
+            result[i] = expressions[i].replace(context);\r
+        return result;\r
+    }\r
+    \r
+    public Expression copy() {\r
+        return replace(new ReplaceContext(null));\r
+    }\r
+    \r
+    public Expression copy(TypingContext typingContext) {\r
+        return replace(new ReplaceContext(typingContext));\r
+    }\r
+\r
+    public abstract void setLocationDeep(long loc);\r
+\r
+    public Expression replaceInPattern(ReplaceContext context) {\r
+        context.inPattern = true;\r
+        Expression result = replace(context);\r
+        context.inPattern = false;\r
+        return result;\r
+    }\r
+\r
+    public int getFunctionDefinitionArity() throws NotPatternException {\r
+        throw new NotPatternException(this);\r
+    }\r
+    \r
+    public IVal lambdaToVal(Environment env, CodeWriter w) {\r
+        DecomposedExpression decomposed = DecomposedExpression.decompose(this);\r
+        CodeWriter newW = w.createFunction(decomposed.typeParameters, decomposed.effect, decomposed.returnType, decomposed.parameterTypes);\r
+        IVal[] parameters = newW.getParameters();\r
+        IVal functionVal = newW.getFunction().getTarget();\r
+        for(int i=0;i<parameters.length;++i)\r
+            decomposed.parameters[i].setVal(parameters[i]);\r
+        newW.return_(decomposed.body.toVal(env, newW));\r
+        return functionVal;\r
+    }\r
+    \r
+    public IExpression toIExpression(ExpressionInterpretationContext context) {\r
+        throw new UnsupportedOperationException();\r
+    }\r
+    \r
+    public static IExpression[] toIExpressions(ExpressionInterpretationContext target, Expression[] expressions) {\r
+        IExpression[] result = new IExpression[expressions.length];\r
+        for(int i=0;i<expressions.length;++i)\r
+            result[i] = expressions[i].toIExpression(target);\r
+        return result;\r
+    }\r
+    \r
+    public Expression applyType(Type type) {\r
+        return new EApplyType(location, this, type);\r
+    }\r
+    \r
+    public abstract Expression decorate(ExpressionDecorator decorator);\r
+\r
+       public boolean isEffectful() {\r
+               return true;\r
+       }\r
+\r
+    public boolean isFunctionPattern() {\r
+        return false;\r
+    }\r
+\r
+    public boolean isConstructorApplication() {\r
+        return false;\r
+    }\r
+    \r
+    public abstract void collectEffects(THashSet<Type> effects);\r
+    \r
+    public Type getEffect() {\r
+        THashSet<Type> effects = new THashSet<Type>();\r
+        collectEffects(effects);\r
+        return Types.union(effects.toArray(new Type[effects.size()]));\r
+    }\r
+    \r
+    public abstract void accept(ExpressionVisitor visitor);\r
+    \r
+    public void collectRelationRefs(\r
+            final TObjectIntHashMap<SCLRelation> allRefs, final TIntHashSet refs) {\r
+        accept(new StandardExpressionVisitor() {\r
+            @Override\r
+            public void visit(QAtom query) {\r
+                int id = allRefs.get(query.relation);\r
+                if(id >= 0)\r
+                    refs.add(id);\r
+            }\r
+        });\r
+    }\r
+\r
+    public boolean isFunctionDefinitionLhs() {\r
+        return false;\r
+    }\r
+\r
+    public Precedence getPrecedence() {\r
+        return Precedence.DEFAULT;\r
+    }\r
+\r
+    public boolean isPattern(int arity) {\r
+        return false;\r
+    }\r
+    \r
+    public abstract Expression accept(ExpressionTransformer transformer);\r
+}\r