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