]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/contexts/TranslationContext.java
Merge "Resolve some dependency problems with SDK features"
[simantics/platform.git] / bundles / org.simantics.scl.compiler / src / org / simantics / scl / compiler / elaboration / contexts / TranslationContext.java
index 203bd81d2d2bd925b9fd9ee969aa475db7b31331..0331f9a50b86a7715405afc9bb37da2441d8b5b2 100644 (file)
@@ -8,6 +8,7 @@ import org.simantics.scl.compiler.common.names.Names;
 import org.simantics.scl.compiler.common.precedence.Associativity;
 import org.simantics.scl.compiler.common.precedence.Precedence;
 import org.simantics.scl.compiler.compilation.CompilationContext;
+import org.simantics.scl.compiler.elaboration.chr.CHRRuleset;
 import org.simantics.scl.compiler.elaboration.chr.relations.CHRConstraint;
 import org.simantics.scl.compiler.elaboration.expressions.Case;
 import org.simantics.scl.compiler.elaboration.expressions.EAmbiguous;
@@ -42,13 +43,26 @@ import gnu.trove.set.hash.THashSet;
 
 public class TranslationContext extends TypeTranslationContext implements EnvironmentalContext {
 
+    public static class ExistentialFrame {
+        THashSet<String> variables = new THashSet<String>(4);
+        ArrayList<Variable> blanks = new ArrayList<Variable>(2); 
+        public boolean disallowNewExistentials;
+        
+        public EVariable createBlank(long location) {
+            Variable variable = new Variable("_");
+            blanks.add(variable);
+            EVariable result = new EVariable(variable);
+            result.location = location;
+            return result;
+        }
+    }
+    
     THashMap<String, Variable> variables = new THashMap<String, Variable>();
     ArrayList<Entry> variableEntries = new ArrayList<Entry>();
     LocalEnvironment localEnvironment;
     TIntArrayList frames = new TIntArrayList();
     ArrayList<THashSet<String>> frameNameSets = new ArrayList<THashSet<String>>(); 
-    ArrayList<THashSet<String>> existentialFrames = new ArrayList<THashSet<String>>();
-    ArrayList<ArrayList<Variable>> blanksInExistentialFrame = new ArrayList<ArrayList<Variable>>();
+    ArrayList<ExistentialFrame> existentialFrames = new ArrayList<ExistentialFrame>(2);
     SCLValue bindFunction;
     
     public PreQuery currentPreQuery;
@@ -109,30 +123,40 @@ public class TranslationContext extends TypeTranslationContext implements Enviro
         
         char c = name.charAt(0);
         switch(c) {
-        case '?':
-            if(existentialFrames.isEmpty()) {
-                errorLog.log(location, "Existential variables can be used only in queries.");
+        case '?': {
+            ExistentialFrame existentialFrame = getCurrentExistentialFrame();
+            if(existentialFrame == null || existentialFrame.disallowNewExistentials) {
+                errorLog.log(location, "New existential variables can be defined only in queries.");
                 return new EError(location);
             }
             variable = new Variable(name);
             variables.put(name, variable);
-            existentialFrames.get(existentialFrames.size()-1).add(name);
+            existentialFrame.variables.add(name);
             return new EVariable(variable);
-        case '_':
+        }
+        case '_': {
             if(name.length()==1) {
-                variable = new Variable("_");
-                if(blanksInExistentialFrame.isEmpty()) {
-                    errorLog.log(location, "Cannot use blank variables in this context.");
+                ExistentialFrame existentialFrame = getCurrentExistentialFrame();
+                if(existentialFrame == null || existentialFrame.disallowNewExistentials) {
+                    errorLog.log(location, "Blank variables can be used only in queries.");
                     return new EError(location);
                 }
-                blanksInExistentialFrame.get(blanksInExistentialFrame.size()-1).add(variable);
-                return new EVariable(variable);
+                return existentialFrame.createBlank(location);
             }
             break;
         }
+        }
         return null;
     }
     
+    public ExistentialFrame getCurrentExistentialFrame() {
+        int size = existentialFrames.size(); 
+        if(size == 0)
+            return null;
+        else
+            return existentialFrames.get(size-1);
+    }
+    
     private Expression resolveFieldAccess(Expression base, int pos, String name) {
         while(pos != -1) {
             int p = findSeparator(name, pos+1);
@@ -379,19 +403,17 @@ public class TranslationContext extends TypeTranslationContext implements Enviro
     
     public void pushExistentialFrame() {
         pushFrame();
-        existentialFrames.add(new THashSet<String>());
-        blanksInExistentialFrame.add(new ArrayList<Variable>(2));
+        existentialFrames.add(new ExistentialFrame());
     }
     
     public Variable[] popExistentialFrame() {
         popFrame();
-        THashSet<String> set = existentialFrames.remove(existentialFrames.size()-1);
-        ArrayList<Variable> blanks = blanksInExistentialFrame.remove(blanksInExistentialFrame.size()-1);
-        Variable[] result = new Variable[set.size() + blanks.size()];
+        ExistentialFrame frame = existentialFrames.remove(existentialFrames.size()-1);
+        Variable[] result = new Variable[frame.variables.size() + frame.blanks.size()];
         int i=0;
-        for(String name : set)
+        for(String name : frame.variables)
             result[i++] = variables.remove(name);
-        for(Variable blank : blanks)
+        for(Variable blank : frame.blanks)
             result[i++] = blank;
         return result;
     }
@@ -521,4 +543,12 @@ public class TranslationContext extends TypeTranslationContext implements Enviro
     public SCLValue getValue(Name name) {
         return environment.getValue(name);
     }
+
+    public CHRRuleset resolveRuleset(String name) throws AmbiguousNameException {
+        return Environments.getRuleset(environment, name);
+    }
+
+    public void disallowNewExistentials() {
+        getCurrentExistentialFrame().disallowNewExistentials = true;
+    }
 }