package org.simantics.scl.compiler.elaboration.expressions; import java.util.ArrayList; import java.util.LinkedList; import java.util.List; import org.simantics.scl.compiler.common.exceptions.InternalCompilerError; import org.simantics.scl.compiler.elaboration.contexts.TranslationContext; import org.simantics.scl.compiler.elaboration.expressions.block.GuardStatement; 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.errors.Locations; public class EBlock extends ASTExpression { LinkedList statements = new LinkedList(); boolean monadic; public EBlock() { } public void addStatement(Statement statement) { statements.add(statement); } public void setMonadic(boolean monadic) { this.monadic = monadic; } public LinkedList getStatements() { return statements; } @Override public Expression resolve(TranslationContext context) { if(statements.isEmpty()) throw new InternalCompilerError(); 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); if(cur instanceof RuleStatement) { int endId = i+1; while(i>0 && statements.get(i-1) instanceof RuleStatement) --i; in = extractRules(i, endId, in); } else if(cur instanceof LetStatement && ((LetStatement)cur).pattern.isFunctionPattern()) { int endId = i+1; while(i>0 && (cur = statements.get(i-1)) instanceof LetStatement && ((LetStatement)cur).pattern.isFunctionPattern()) --i; in = extractLet(i, endId, in); } else in = cur.toExpression(context, monadic, in); } 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); } @SuppressWarnings("unchecked") private Expression extractLet(int begin, int end, Expression in) { return new EPreLet((List)(List)statements.subList(begin, end), in); } public static Expression create(ArrayList 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); } }