1 package org.simantics.scl.compiler.elaboration.expressions;
\r
3 import gnu.trove.map.hash.THashMap;
\r
5 import org.simantics.scl.compiler.elaboration.contexts.TranslationContext;
\r
6 import org.simantics.scl.compiler.elaboration.expressions.ERuleset.DatalogRule;
\r
7 import org.simantics.scl.compiler.elaboration.expressions.block.RuleStatement;
\r
8 import org.simantics.scl.compiler.elaboration.relations.LocalRelation;
\r
9 import org.simantics.scl.compiler.errors.Locations;
\r
11 public class EPreRuleset extends ASTExpression {
\r
13 RuleStatement[] statements;
\r
16 public EPreRuleset(RuleStatement[] statements, Expression in) {
\r
17 this.statements = statements;
\r
22 public Expression resolve(TranslationContext context) {
\r
23 THashMap<String, LocalRelation> relations = new THashMap<String, LocalRelation>();
\r
24 DatalogRule[] rules = new DatalogRule[statements.length];
\r
25 context.pushRelationFrame();
\r
27 for(int i=0;i<statements.length;++i) {
\r
28 RuleStatement statement = statements[i];
\r
29 Expression head = statement.head;
\r
30 if(!(head instanceof EApply)) {
\r
31 context.getErrorLog().log(head.location, "Invalid rule head.");
\r
32 return new EError();
\r
34 EApply apply = (EApply)head;
\r
35 if(!(apply.function instanceof EVar)) {
\r
36 context.getErrorLog().log(head.location, "Invalid relation in rule head.");
\r
37 return new EError();
\r
39 String relationName = ((EVar)apply.function).name;
\r
40 LocalRelation relation = relations.get(relationName);
\r
41 if(relation == null) {
\r
42 relation = new LocalRelation(relationName, apply.parameters.length);
\r
43 relations.put(relationName, relation);
\r
44 context.newRelation(relationName, relation);
\r
46 else if(apply.parameters.length != relation.getArity()) {
\r
47 context.getErrorLog().log(apply.location, "Different rules have different relation arity.");
\r
48 return new EError();
\r
50 rules[i] = new DatalogRule(relation, apply.parameters, statement.body);
\r
52 for(DatalogRule rule : rules) {
\r
53 context.pushExistentialFrame();
\r
54 for(int i=0;i<rule.headParameters.length;++i)
\r
55 rule.headParameters[i] = rule.headParameters[i].resolve(context);
\r
56 rule.body = rule.body.resolve(context);
\r
57 rule.variables = context.popExistentialFrame();
\r
59 return new ERuleset(
\r
60 relations.values().toArray(new LocalRelation[relations.size()]),
\r
62 in.resolve(context));
\r
64 context.popRelationFrame();
\r
69 public void setLocationDeep(long loc) {
\r
70 if(location == Locations.NO_LOCATION) {
\r
72 for(RuleStatement statement : statements)
\r
73 statement.setLocationDeep(loc);
\r
74 in.setLocationDeep(loc);
\r
79 public Expression accept(ExpressionTransformer transformer) {
\r
80 return transformer.transform(this);
\r