1 package org.simantics.scl.compiler.elaboration.expressions;
3 import java.util.ArrayList;
6 import org.simantics.scl.compiler.elaboration.chr.CHRRule;
7 import org.simantics.scl.compiler.elaboration.chr.CHRRuleset;
8 import org.simantics.scl.compiler.elaboration.chr.ast.CHRQueryTranslationMode;
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.BlockType;
12 import org.simantics.scl.compiler.elaboration.expressions.block.CHRStatement;
13 import org.simantics.scl.compiler.elaboration.expressions.block.ConstraintStatement;
14 import org.simantics.scl.compiler.elaboration.expressions.block.GuardStatement;
15 import org.simantics.scl.compiler.elaboration.expressions.block.IncludeStatement;
16 import org.simantics.scl.compiler.elaboration.expressions.block.LetStatement;
17 import org.simantics.scl.compiler.elaboration.expressions.block.RuleStatement;
18 import org.simantics.scl.compiler.elaboration.expressions.block.Statement;
19 import org.simantics.scl.compiler.elaboration.expressions.block.StatementGroup;
20 import org.simantics.scl.compiler.errors.Locations;
22 public class EBlock extends ASTExpression {
24 public ArrayList<Statement> statements = new ArrayList<Statement>();
25 BlockType blockType = BlockType.Normal;
28 this.blockType = blockType;
31 public void setBlockType(BlockType blockType) {
32 this.blockType = blockType;
35 public void addStatement(Statement statement) {
36 statements.add(statement);
39 public ArrayList<Statement> getStatements() {
43 public Statement getFirst() {
44 return statements.get(0);
47 public Statement getLast() {
48 return statements.get(statements.size()-1);
52 public Expression resolve(TranslationContext context) {
53 if(statements.isEmpty()) {
54 context.getErrorLog().log(location, "Block should not be empty.");
55 return new EError(location);
57 int i = statements.size()-1;
58 Statement last = statements.get(i);
59 if(!(last instanceof GuardStatement)) {
60 context.getErrorLog().log(last.location, "Block should end with an expression");
61 return new EError(location);
64 Expression in = ((GuardStatement)last).value;
66 Statement cur = statements.get(i);
67 StatementGroup group = cur.getStatementGroup();
69 in = cur.toExpression(context, blockType, in);
72 while(i>0 && statements.get(i-1).getStatementGroup() == group)
76 in = extractLet(i, endId, in);
79 in = extractRules(i, endId, in);
82 CHRRuleset ruleset = extractCHRRules(context, i, endId);
83 long location = Locations.combine(ruleset.location, in.location);
84 in = new ECHRRuleset(ruleset, in);
85 in.location = location;
91 return in.resolve(context);
94 private Expression extractRules(int begin, int end, Expression in) {
95 return new EPreRuleset(statements.subList(begin, end).toArray(new RuleStatement[end-begin]), in);
98 private CHRRuleset extractCHRRules(TranslationContext context, int begin, int end) {
99 CHRRuleset ruleset = new CHRRuleset();
100 ruleset.location = Locations.combine(statements.get(begin).location, statements.get(end-1).location);
101 for(int i=begin;i<end;++i) {
102 Statement statement = statements.get(i);
103 if(statement instanceof CHRStatement) {
104 CHRStatement chrStatement = (CHRStatement)statement;
105 ruleset.addRule(new CHRRule(chrStatement.location,
106 chrStatement.head.translate(context, CHRQueryTranslationMode.RULE_HEAD),
107 chrStatement.body.translate(context, CHRQueryTranslationMode.RULE_BODY)));
109 else if(statement instanceof ConstraintStatement)
110 ruleset.constraints.add(CHRTranslation.convertConstraintStatement(context, (ConstraintStatement)statement));
111 else if(statement instanceof IncludeStatement)
112 ruleset.includes.add((IncludeStatement)statement);
114 context.getErrorLog().log(statement.location, "Invalid CHR statement.");
119 public CHRRuleset extractCHRRules(TranslationContext context) {
120 return extractCHRRules(context, 0, statements.size());
123 @SuppressWarnings("unchecked")
124 private Expression extractLet(int begin, int end, Expression in) {
125 return new EPreLet((List<LetStatement>)(List<?>)statements.subList(begin, end), in);
128 public static Expression create(ArrayList<Expression> statements) {
129 EBlock block = new EBlock();
130 for(Expression statement : statements)
131 block.addStatement(new GuardStatement(statement));
136 public void setLocationDeep(long loc) {
137 if(location == Locations.NO_LOCATION) {
139 for(Statement statement : statements)
140 statement.setLocationDeep(loc);
145 public Expression accept(ExpressionTransformer transformer) {
146 return transformer.transform(this);
150 public int getSyntacticFunctionArity() {
151 if(blockType != BlockType.Normal)
153 Statement lastStatement = statements.get(statements.size()-1);
154 if(!(lastStatement instanceof GuardStatement))
156 return ((GuardStatement)lastStatement).value.getSyntacticFunctionArity();
160 public void accept(ExpressionVisitor visitor) {