]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/EBlock.java
New type class MonadE and corresponding monad syntax with edo keyword
[simantics/platform.git] / bundles / org.simantics.scl.compiler / src / org / simantics / scl / compiler / elaboration / expressions / EBlock.java
old mode 100755 (executable)
new mode 100644 (file)
index 295f3c1..c217325
-package org.simantics.scl.compiler.elaboration.expressions;\r
-\r
-import java.util.ArrayList;\r
-import java.util.LinkedList;\r
-import java.util.List;\r
-\r
-import org.simantics.scl.compiler.common.exceptions.InternalCompilerError;\r
-import org.simantics.scl.compiler.elaboration.contexts.TranslationContext;\r
-import org.simantics.scl.compiler.elaboration.expressions.block.GuardStatement;\r
-import org.simantics.scl.compiler.elaboration.expressions.block.LetStatement;\r
-import org.simantics.scl.compiler.elaboration.expressions.block.RuleStatement;\r
-import org.simantics.scl.compiler.elaboration.expressions.block.Statement;\r
-import org.simantics.scl.compiler.errors.Locations;\r
-\r
-public class EBlock extends ASTExpression {\r
-\r
-    LinkedList<Statement> statements = new LinkedList<Statement>();\r
-    boolean monadic;\r
-    \r
-    public EBlock() {\r
-    }\r
-\r
-    public void addStatement(Statement statement) {\r
-        statements.add(statement);\r
-    }\r
-    \r
-    public void setMonadic(boolean monadic) {\r
-        this.monadic = monadic;\r
-    }\r
-    \r
-    public LinkedList<Statement> getStatements() {\r
-        return statements;\r
-    }\r
-\r
-    @Override\r
-    public Expression resolve(TranslationContext context) {\r
-        if(statements.isEmpty())\r
-            throw new InternalCompilerError();\r
-        int i = statements.size()-1;\r
-        Statement last = statements.get(i);\r
-        if(!(last instanceof GuardStatement)) {\r
-            context.getErrorLog().log(last.location, "Block should end with an expression");\r
-            return new EError(location);\r
-        }\r
-\r
-        Expression in = ((GuardStatement)last).value;\r
-        while(--i >= 0) {\r
-            Statement cur = statements.get(i);\r
-            if(cur instanceof RuleStatement) {\r
-                int endId = i+1;\r
-                while(i>0 && statements.get(i-1) instanceof RuleStatement)\r
-                    --i;\r
-                in = extractRules(i, endId, in);\r
-            }\r
-            else if(cur instanceof LetStatement && ((LetStatement)cur).pattern.isFunctionPattern()) {\r
-                int endId = i+1;\r
-                while(i>0 && (cur = statements.get(i-1)) instanceof LetStatement &&\r
-                        ((LetStatement)cur).pattern.isFunctionPattern())\r
-                    --i;\r
-                in = extractLet(i, endId, in);\r
-            }\r
-            else\r
-                in = cur.toExpression(context, monadic, in);\r
-        }\r
-        return in.resolve(context);\r
-    }\r
-\r
-    private Expression extractRules(int begin, int end, Expression in) {\r
-        return new EPreRuleset(statements.subList(begin, end).toArray(new RuleStatement[end-begin]), in);\r
-    }\r
-\r
-    @SuppressWarnings("unchecked")\r
-    private Expression extractLet(int begin, int end, Expression in) {\r
-        return new EPreLet((List<LetStatement>)(List<?>)statements.subList(begin, end), in);\r
-    }\r
-\r
-    public static Expression create(ArrayList<Expression> statements) {\r
-        EBlock block = new EBlock();\r
-        for(Expression statement : statements)\r
-            block.addStatement(new GuardStatement(statement));\r
-        return block;\r
-    }\r
-\r
-    @Override\r
-    public void setLocationDeep(long loc) {\r
-        if(location == Locations.NO_LOCATION) {\r
-            location = loc;\r
-            for(Statement statement : statements)\r
-                statement.setLocationDeep(loc);\r
-        }\r
-    }\r
-    \r
-    @Override\r
-    public Expression accept(ExpressionTransformer transformer) {\r
-        return transformer.transform(this);\r
-    }\r
-\r
-}\r
+package org.simantics.scl.compiler.elaboration.expressions;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.simantics.scl.compiler.elaboration.chr.CHRRule;
+import org.simantics.scl.compiler.elaboration.chr.CHRRuleset;
+import org.simantics.scl.compiler.elaboration.chr.ast.CHRQueryTranslationMode;
+import org.simantics.scl.compiler.elaboration.chr.translation.CHRTranslation;
+import org.simantics.scl.compiler.elaboration.contexts.TranslationContext;
+import org.simantics.scl.compiler.elaboration.expressions.block.BlockType;
+import org.simantics.scl.compiler.elaboration.expressions.block.CHRStatement;
+import org.simantics.scl.compiler.elaboration.expressions.block.ConstraintStatement;
+import org.simantics.scl.compiler.elaboration.expressions.block.GuardStatement;
+import org.simantics.scl.compiler.elaboration.expressions.block.IncludeStatement;
+import org.simantics.scl.compiler.elaboration.expressions.block.LetStatement;
+import org.simantics.scl.compiler.elaboration.expressions.block.RuleStatement;
+import org.simantics.scl.compiler.elaboration.expressions.block.Statement;
+import org.simantics.scl.compiler.elaboration.expressions.block.StatementGroup;
+import org.simantics.scl.compiler.errors.Locations;
+
+public class EBlock extends ASTExpression {
+
+    public ArrayList<Statement> statements = new ArrayList<Statement>();
+    BlockType blockType = BlockType.Normal;
+    
+    public EBlock() {
+        this.blockType = blockType;
+    }
+    
+    public void setBlockType(BlockType blockType) {
+        this.blockType = blockType;
+    }
+
+    public void addStatement(Statement statement) {
+        statements.add(statement);
+    }
+    
+    public ArrayList<Statement> getStatements() {
+        return statements;
+    }
+    
+    public Statement getFirst() {
+        return statements.get(0);
+    }
+    
+    public Statement getLast() {
+        return statements.get(statements.size()-1);
+    }
+
+    @Override
+    public Expression resolve(TranslationContext context) {
+        if(statements.isEmpty()) {
+            context.getErrorLog().log(location, "Block should not be empty.");
+            return new EError(location);
+        }
+        int i = statements.size()-1;
+        Statement last = statements.get(i);
+        if(!(last instanceof GuardStatement)) {
+            context.getErrorLog().log(last.location, "Block should end with an expression");
+            return new EError(location);
+        }
+
+        Expression in = ((GuardStatement)last).value;
+        while(--i >= 0) {
+            Statement cur = statements.get(i);
+            StatementGroup group = cur.getStatementGroup();
+            if(group == null)
+                in = cur.toExpression(context, blockType, in);
+            else {
+                int endId = i+1;
+                while(i>0 && statements.get(i-1).getStatementGroup() == group)
+                    --i;
+                switch(group) {
+                case LetFunction:
+                    in = extractLet(i, endId, in);
+                    break;
+                case Rule:
+                    in = extractRules(i, endId, in);
+                    break;
+                case CHR: {
+                    CHRRuleset ruleset = extractCHRRules(context, i, endId);
+                    long location = Locations.combine(ruleset.location, in.location);
+                    in = new ECHRRuleset(ruleset, in);
+                    in.location = location;
+                    break;
+                }
+                }
+            }
+        }
+        return in.resolve(context);
+    }
+
+    private Expression extractRules(int begin, int end, Expression in) {
+        return new EPreRuleset(statements.subList(begin, end).toArray(new RuleStatement[end-begin]), in);
+    }
+    
+    private CHRRuleset extractCHRRules(TranslationContext context, int begin, int end) {
+        CHRRuleset ruleset = new CHRRuleset();
+        ruleset.location = Locations.combine(statements.get(begin).location, statements.get(end-1).location);
+        for(int i=begin;i<end;++i) {
+            Statement statement = statements.get(i);
+            if(statement instanceof CHRStatement) {
+                CHRStatement chrStatement = (CHRStatement)statement;
+                ruleset.addRule(new CHRRule(chrStatement.location,
+                        chrStatement.head.translate(context, CHRQueryTranslationMode.RULE_HEAD),
+                        chrStatement.body.translate(context, CHRQueryTranslationMode.RULE_BODY)));
+            }
+            else if(statement instanceof ConstraintStatement)
+                ruleset.constraints.add(CHRTranslation.convertConstraintStatement(context, (ConstraintStatement)statement));
+            else if(statement instanceof IncludeStatement)
+                ruleset.includes.add((IncludeStatement)statement);
+            else
+                context.getErrorLog().log(statement.location, "Invalid CHR statement.");
+        }
+        return ruleset;
+    }
+
+    public CHRRuleset extractCHRRules(TranslationContext context) {
+        return extractCHRRules(context, 0, statements.size());
+    }
+    
+    @SuppressWarnings("unchecked")
+    private Expression extractLet(int begin, int end, Expression in) {
+        return new EPreLet((List<LetStatement>)(List<?>)statements.subList(begin, end), in);
+    }
+
+    public static Expression create(ArrayList<Expression> statements) {
+        EBlock block = new EBlock();
+        for(Expression statement : statements)
+            block.addStatement(new GuardStatement(statement));
+        return block;
+    }
+
+    @Override
+    public void setLocationDeep(long loc) {
+        if(location == Locations.NO_LOCATION) {
+            location = loc;
+            for(Statement statement : statements)
+                statement.setLocationDeep(loc);
+        }
+    }
+    
+    @Override
+    public Expression accept(ExpressionTransformer transformer) {
+        return transformer.transform(this);
+    }
+
+    @Override
+    public int getSyntacticFunctionArity() {
+        if(blockType != BlockType.Normal)
+            return 0;
+        Statement lastStatement = statements.get(statements.size()-1);
+        if(!(lastStatement instanceof GuardStatement))
+            return 0;
+        return ((GuardStatement)lastStatement).value.getSyntacticFunctionArity();
+    }
+    
+    @Override
+    public void accept(ExpressionVisitor visitor) {
+        visitor.visit(this);
+    }
+}