]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/visitors/CollectFreeVariablesVisitor.java
(refs #7375) Replaced collectFreeVariables method by a visitor
[simantics/platform.git] / bundles / org.simantics.scl.compiler / src / org / simantics / scl / compiler / elaboration / expressions / visitors / CollectFreeVariablesVisitor.java
diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/visitors/CollectFreeVariablesVisitor.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/visitors/CollectFreeVariablesVisitor.java
new file mode 100644 (file)
index 0000000..04f6791
--- /dev/null
@@ -0,0 +1,184 @@
+package org.simantics.scl.compiler.elaboration.expressions.visitors;
+
+import org.simantics.scl.compiler.elaboration.chr.CHRLiteral;
+import org.simantics.scl.compiler.elaboration.chr.CHRQuery;
+import org.simantics.scl.compiler.elaboration.chr.CHRRule;
+import org.simantics.scl.compiler.elaboration.chr.relations.SpecialCHRRelation;
+import org.simantics.scl.compiler.elaboration.expressions.Assignment;
+import org.simantics.scl.compiler.elaboration.expressions.Case;
+import org.simantics.scl.compiler.elaboration.expressions.EAsPattern;
+import org.simantics.scl.compiler.elaboration.expressions.EBind;
+import org.simantics.scl.compiler.elaboration.expressions.ECHRSelect;
+import org.simantics.scl.compiler.elaboration.expressions.ELet;
+import org.simantics.scl.compiler.elaboration.expressions.ERuleset.DatalogRule;
+import org.simantics.scl.compiler.elaboration.expressions.ESelect;
+import org.simantics.scl.compiler.elaboration.expressions.ESimpleLambda;
+import org.simantics.scl.compiler.elaboration.expressions.ESimpleLet;
+import org.simantics.scl.compiler.elaboration.expressions.EVariable;
+import org.simantics.scl.compiler.elaboration.expressions.EViewPattern;
+import org.simantics.scl.compiler.elaboration.expressions.EWhen;
+import org.simantics.scl.compiler.elaboration.expressions.Expression;
+import org.simantics.scl.compiler.elaboration.expressions.Variable;
+import org.simantics.scl.compiler.elaboration.expressions.list.ListAssignment;
+import org.simantics.scl.compiler.elaboration.expressions.list.ListGenerator;
+import org.simantics.scl.compiler.elaboration.query.QExists;
+
+import gnu.trove.set.hash.THashSet;
+
+public class CollectFreeVariablesVisitor extends StandardExpressionVisitor {
+    private THashSet<Variable> freeVariables = new THashSet<Variable>();
+    
+    private StandardExpressionVisitor collectBoundVariablesVisitor = new StandardExpressionVisitor() {
+        @Override
+        public void visit(EVariable expression) {
+            if(expression.variable != null)
+                freeVariables.remove(expression.variable);
+        }
+        
+        
+        @Override
+        public void visit(EAsPattern expression) {
+            freeVariables.remove(expression.var);
+            expression.pattern.accept(this);
+        }
+        
+        @Override
+        public void visit(EViewPattern expression) {
+            expression.expression.accept(CollectFreeVariablesVisitor.this);
+            expression.pattern.accept(this);
+        }
+    };
+    
+    @Override
+    public void visit(EVariable expression) {
+        if(expression.variable != null)
+            freeVariables.add(expression.variable);
+    }
+    
+    @Override
+    public void visit(EBind expression) {
+        if(expression.monadEvidence != null)
+            visit(expression.monadEvidence);
+        expression.in.accept(this);
+        expression.value.accept(this);
+        expression.pattern.accept(collectBoundVariablesVisitor);
+    }
+    
+    @Override
+    public void visit(Assignment assignment) {
+        assignment.value.accept(this);
+        assignment.pattern.accept(collectBoundVariablesVisitor);
+    }
+    
+    @Override
+    public void visit(ELet expression) {
+        expression.in.accept(this);
+        for(int i=expression.assignments.length-1;i>=0;--i)
+            visit(expression.assignments[i]);
+    }
+    
+    @Override
+    public void visit(Case case_) {
+        case_.value.accept(this);
+        for(Expression pattern : case_.patterns)
+            pattern.accept(collectBoundVariablesVisitor);
+    }
+    
+    @Override
+    public void visit(ESimpleLambda expression) {
+        expression.value.accept(this);
+        freeVariables.remove(expression.parameter);
+    }
+    
+    @Override
+    public void visit(ESimpleLet expression) {
+        expression.in.accept(this);
+        expression.value.accept(this);
+        freeVariables.remove(expression.variable);
+    }
+    
+    @Override
+    public void visit(ECHRSelect expression) {
+        expression.expression.accept(this);
+        visit(expression.query);
+        for(Variable variable : expression.existentialVariables)
+            freeVariables.remove(variable);
+    }
+    
+    @Override
+    public void visit(ESelect expression) {
+        expression.expression.accept(this);
+        expression.query.accept(this);
+        for(Variable variable : expression.variables)
+            freeVariables.remove(variable);
+    }
+    
+    @Override
+    public void visit(EWhen expression) {
+        expression.action.accept(this);
+        expression.query.accept(this);
+        for(Variable variable : expression.variables)
+            freeVariables.remove(variable);
+    }
+
+    @Override
+    public void visit(DatalogRule rule) {
+        for(Expression parameter : rule.headParameters)
+            parameter.accept(this);
+        rule.body.accept(this);
+        for(Variable variable : rule.variables)
+            freeVariables.remove(variable);
+    }
+    
+    @Override
+    public void visit(ListGenerator qualifier) {
+        qualifier.pattern.accept(collectBoundVariablesVisitor);
+        qualifier.value.accept(this);
+    }
+    
+    @Override
+    public void visit(ListAssignment qualifier) {
+        qualifier.pattern.accept(collectBoundVariablesVisitor);
+        qualifier.value.accept(this);
+    }
+    
+    @Override
+    public void visit(CHRLiteral literal) {
+        if(literal.relation == SpecialCHRRelation.ASSIGN) {
+            literal.parameters[0].accept(collectBoundVariablesVisitor);
+            literal.parameters[1].accept(this);
+        }
+        else {
+            for(Expression parameter : literal.parameters)
+                parameter.accept(this);
+            if(literal.typeConstraintEvidenceParameters != null)
+                for(Expression parameter : literal.typeConstraintEvidenceParameters)
+                    parameter.accept(this);
+        }
+    }
+    
+    @Override
+    public void visit(CHRQuery query) {
+        for(int i=query.literals.length-1;i>=0;--i) {
+            visit(query.literals[i]);
+        }
+    }
+    
+    @Override
+    public void visit(CHRRule rule) {
+        super.visit(rule);
+        for(Variable variable : rule.existentialVariables)
+            freeVariables.remove(variable);
+    }
+    
+    @Override
+    public void visit(QExists query) {
+        query.query.accept(this);
+        for(Variable variable : query.variables)
+            freeVariables.remove(variable);
+    }
+    
+    public THashSet<Variable> getFreeVariables() {
+        return freeVariables;
+    }
+}