]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/EBlock.java
Improvements to SCL compiler error messages
[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.LinkedList;
5 import java.util.List;
6
7 import org.simantics.scl.compiler.common.exceptions.InternalCompilerError;
8 import org.simantics.scl.compiler.elaboration.chr.CHRRuleset;
9 import org.simantics.scl.compiler.elaboration.chr.translation.CHRTranslation;
10 import org.simantics.scl.compiler.elaboration.contexts.TranslationContext;
11 import org.simantics.scl.compiler.elaboration.expressions.block.CHRStatement;
12 import org.simantics.scl.compiler.elaboration.expressions.block.ConstraintStatement;
13 import org.simantics.scl.compiler.elaboration.expressions.block.GuardStatement;
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     LinkedList<Statement> statements = new LinkedList<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 LinkedList<Statement> getStatements() {
37         return statements;
38     }
39
40     @Override
41     public Expression resolve(TranslationContext context) {
42         if(statements.isEmpty())
43             throw new InternalCompilerError();
44         int i = statements.size()-1;
45         Statement last = statements.get(i);
46         if(!(last instanceof GuardStatement)) {
47             context.getErrorLog().log(last.location, "Block should end with an expression");
48             return new EError(location);
49         }
50
51         Expression in = ((GuardStatement)last).value;
52         while(--i >= 0) {
53             Statement cur = statements.get(i);
54             StatementGroup group = cur.getStatementGroup();
55             if(group == null)
56                 in = cur.toExpression(context, monadic, in);
57             else {
58                 int endId = i+1;
59                 while(i>0 && statements.get(i-1).getStatementGroup() == group)
60                     --i;
61                 switch(group) {
62                 case LetFunction:
63                     in = extractLet(i, endId, in);
64                     break;
65                 case Rule:
66                     in = extractRules(i, endId, in);
67                     break;
68                 case CHR:
69                     in = extractCHRRules(context, i, endId, in);
70                     break;
71                 }
72             }
73         }
74         return in.resolve(context);
75     }
76
77     private Expression extractRules(int begin, int end, Expression in) {
78         return new EPreRuleset(statements.subList(begin, end).toArray(new RuleStatement[end-begin]), in);
79     }
80     
81     private Expression extractCHRRules(TranslationContext context, int begin, int end, Expression in) {
82         CHRRuleset ruleset = new CHRRuleset();
83         ruleset.location = Locations.combine(statements.get(begin).location, statements.get(end-1).location);
84         for(int i=begin;i<end;++i) {
85             Statement statement = statements.get(i);
86             if(statement instanceof CHRStatement)
87                 ruleset.rules.add(CHRTranslation.convertCHRStatement(context, (CHRStatement)statement));
88             else if(statement instanceof ConstraintStatement)
89                 ruleset.constraints.add(CHRTranslation.convertConstraintStatement(context, (ConstraintStatement)statement));
90             else
91                 throw new InternalCompilerError("Invalid CHR statement.");
92         }
93         return new ECHRRuleset(ruleset, in);
94     }
95
96     @SuppressWarnings("unchecked")
97     private Expression extractLet(int begin, int end, Expression in) {
98         return new EPreLet((List<LetStatement>)(List<?>)statements.subList(begin, end), in);
99     }
100
101     public static Expression create(ArrayList<Expression> statements) {
102         EBlock block = new EBlock();
103         for(Expression statement : statements)
104             block.addStatement(new GuardStatement(statement));
105         return block;
106     }
107
108     @Override
109     public void setLocationDeep(long loc) {
110         if(location == Locations.NO_LOCATION) {
111             location = loc;
112             for(Statement statement : statements)
113                 statement.setLocationDeep(loc);
114         }
115     }
116     
117     @Override
118     public Expression accept(ExpressionTransformer transformer) {
119         return transformer.transform(this);
120     }
121
122     @Override
123     public int getSyntacticFunctionArity() {
124         if(monadic)
125             return 0;
126         Statement lastStatement = statements.getLast();
127         if(!(lastStatement instanceof GuardStatement))
128             return 0;
129         return ((GuardStatement)lastStatement).value.getSyntacticFunctionArity();
130     }
131 }