]> gerrit.simantics Code Review - simantics/platform.git/blob
41880a0224bd2fb960f9acd7cc3f05bf03c0c093
[simantics/platform.git] /
1 package org.simantics.scl.compiler.elaboration.expressions;
2
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;
8
9 import gnu.trove.map.hash.THashMap;
10
11 public class EPreRuleset extends ASTExpression {
12
13     RuleStatement[] statements;
14     Expression in;
15     
16     public EPreRuleset(RuleStatement[] statements, Expression in) {
17         this.statements = statements;
18         this.in = in;
19     }
20
21     @Override
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();
26         try {
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.");
32                     return new EError();
33                 }
34                 EApply apply = (EApply)head;
35                 if(!(apply.function instanceof EVar)) {
36                     context.getErrorLog().log(head.location, "Invalid relation in rule head.");
37                     return new EError();
38                 }
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);
45                 }
46                 else if(apply.parameters.length != relation.getArity()) {
47                     context.getErrorLog().log(apply.location, "Different rules have different relation arity.");
48                     return new EError();
49                 }
50                 rules[i] = new DatalogRule(relation, apply.parameters, statement.body);
51             }
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();
58             }
59             return new ERuleset(
60                     relations.values().toArray(new LocalRelation[relations.size()]),
61                     rules,
62                     in.resolve(context));
63         } finally {
64             context.popRelationFrame();
65         }
66     }
67
68     @Override
69     public void setLocationDeep(long loc) {
70         if(location == Locations.NO_LOCATION) {
71             location = loc;
72             for(RuleStatement statement : statements)
73                 statement.setLocationDeep(loc);
74             in.setLocationDeep(loc);
75         }
76     }
77     
78     @Override
79     public Expression accept(ExpressionTransformer transformer) {
80         return transformer.transform(this);
81     }
82     
83     @Override
84     public int getSyntacticFunctionArity() {
85         return in.getSyntacticFunctionArity();
86     }
87
88 }