]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/EBlock.java
(refs #7250) CHR bugfixes, cleaning up unit tests
[simantics/platform.git] / bundles / org.simantics.scl.compiler / src / org / simantics / scl / compiler / elaboration / expressions / EBlock.java
1 package org.simantics.scl.compiler.elaboration.expressions;
2
3 import java.util.ArrayList;
4 import java.util.List;
5
6 import org.simantics.scl.compiler.common.exceptions.InternalCompilerError;
7 import org.simantics.scl.compiler.elaboration.chr.CHRRuleset;
8 import org.simantics.scl.compiler.elaboration.chr.translation.CHRTranslation;
9 import org.simantics.scl.compiler.elaboration.contexts.TranslationContext;
10 import org.simantics.scl.compiler.elaboration.expressions.block.CHRStatement;
11 import org.simantics.scl.compiler.elaboration.expressions.block.ConstraintStatement;
12 import org.simantics.scl.compiler.elaboration.expressions.block.GuardStatement;
13 import org.simantics.scl.compiler.elaboration.expressions.block.IncludeStatement;
14 import org.simantics.scl.compiler.elaboration.expressions.block.LetStatement;
15 import org.simantics.scl.compiler.elaboration.expressions.block.RuleStatement;
16 import org.simantics.scl.compiler.elaboration.expressions.block.Statement;
17 import org.simantics.scl.compiler.elaboration.expressions.block.StatementGroup;
18 import org.simantics.scl.compiler.errors.Locations;
19
20 public class EBlock extends ASTExpression {
21
22     ArrayList<Statement> statements = new ArrayList<Statement>();
23     boolean monadic;
24     
25     public EBlock() {
26     }
27
28     public void addStatement(Statement statement) {
29         statements.add(statement);
30     }
31     
32     public void setMonadic(boolean monadic) {
33         this.monadic = monadic;
34     }
35     
36     public ArrayList<Statement> getStatements() {
37         return statements;
38     }
39     
40     public Statement getFirst() {
41         return statements.get(0);
42     }
43     
44     public Statement getLast() {
45         return statements.get(statements.size()-1);
46     }
47
48     @Override
49     public Expression resolve(TranslationContext context) {
50         if(statements.isEmpty())
51             throw new InternalCompilerError();
52         int i = statements.size()-1;
53         Statement last = statements.get(i);
54         if(!(last instanceof GuardStatement)) {
55             context.getErrorLog().log(last.location, "Block should end with an expression");
56             return new EError(location);
57         }
58
59         Expression in = ((GuardStatement)last).value;
60         while(--i >= 0) {
61             Statement cur = statements.get(i);
62             StatementGroup group = cur.getStatementGroup();
63             if(group == null)
64                 in = cur.toExpression(context, monadic, in);
65             else {
66                 int endId = i+1;
67                 while(i>0 && statements.get(i-1).getStatementGroup() == group)
68                     --i;
69                 switch(group) {
70                 case LetFunction:
71                     in = extractLet(i, endId, in);
72                     break;
73                 case Rule:
74                     in = extractRules(i, endId, in);
75                     break;
76                 case CHR:
77                     in = new ECHRRuleset(extractCHRRules(context, i, endId), in);
78                     break;
79                 }
80             }
81         }
82         return in.resolve(context);
83     }
84
85     private Expression extractRules(int begin, int end, Expression in) {
86         return new EPreRuleset(statements.subList(begin, end).toArray(new RuleStatement[end-begin]), in);
87     }
88     
89     private CHRRuleset extractCHRRules(TranslationContext context, int begin, int end) {
90         CHRRuleset ruleset = new CHRRuleset();
91         ruleset.location = Locations.combine(statements.get(begin).location, statements.get(end-1).location);
92         for(int i=begin;i<end;++i) {
93             Statement statement = statements.get(i);
94             if(statement instanceof CHRStatement)
95                 ruleset.addRule(CHRTranslation.convertCHRStatement(context, (CHRStatement)statement));
96             else if(statement instanceof ConstraintStatement)
97                 ruleset.constraints.add(CHRTranslation.convertConstraintStatement(context, (ConstraintStatement)statement));
98             else if(statement instanceof IncludeStatement)
99                 ruleset.includes.add((IncludeStatement)statement);
100             else
101                 context.getErrorLog().log(statement.location, "Invalid CHR statement.");
102         }
103         return ruleset;
104     }
105
106     public CHRRuleset extractCHRRules(TranslationContext context) {
107         return extractCHRRules(context, 0, statements.size());
108     }
109     
110     @SuppressWarnings("unchecked")
111     private Expression extractLet(int begin, int end, Expression in) {
112         return new EPreLet((List<LetStatement>)(List<?>)statements.subList(begin, end), in);
113     }
114
115     public static Expression create(ArrayList<Expression> statements) {
116         EBlock block = new EBlock();
117         for(Expression statement : statements)
118             block.addStatement(new GuardStatement(statement));
119         return block;
120     }
121
122     @Override
123     public void setLocationDeep(long loc) {
124         if(location == Locations.NO_LOCATION) {
125             location = loc;
126             for(Statement statement : statements)
127                 statement.setLocationDeep(loc);
128         }
129     }
130     
131     @Override
132     public Expression accept(ExpressionTransformer transformer) {
133         return transformer.transform(this);
134     }
135
136     @Override
137     public int getSyntacticFunctionArity() {
138         if(monadic)
139             return 0;
140         Statement lastStatement = statements.get(statements.size()-1);
141         if(!(lastStatement instanceof GuardStatement))
142             return 0;
143         return ((GuardStatement)lastStatement).value.getSyntacticFunctionArity();
144     }
145     
146     @Override
147     public void accept(ExpressionVisitor visitor) {
148         visitor.visit(this);
149     }
150 }