]> gerrit.simantics Code Review - simantics/platform.git/blob
ff27eb03a4ef066b0fa3f13d81080eede5a31e73
[simantics/platform.git] /
1 package org.simantics.scl.compiler.elaboration.expressions;\r
2 \r
3 import gnu.trove.map.hash.THashMap;\r
4 \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
10 \r
11 public class EPreRuleset extends ASTExpression {\r
12 \r
13     RuleStatement[] statements;\r
14     Expression in;\r
15     \r
16     public EPreRuleset(RuleStatement[] statements, Expression in) {\r
17         this.statements = statements;\r
18         this.in = in;\r
19     }\r
20 \r
21     @Override\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
26         try {\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
33                 }\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
38                 }\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
45                 }\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
49                 }\r
50                 rules[i] = new DatalogRule(relation, apply.parameters, statement.body);\r
51             }\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
58             }\r
59             return new ERuleset(\r
60                     relations.values().toArray(new LocalRelation[relations.size()]),\r
61                     rules,\r
62                     in.resolve(context));\r
63         } finally {\r
64             context.popRelationFrame();\r
65         }\r
66     }\r
67 \r
68     @Override\r
69     public void setLocationDeep(long loc) {\r
70         if(location == Locations.NO_LOCATION) {\r
71             location = loc;\r
72             for(RuleStatement statement : statements)\r
73                 statement.setLocationDeep(loc);\r
74             in.setLocationDeep(loc);\r
75         }\r
76     }\r
77     \r
78     @Override\r
79     public Expression accept(ExpressionTransformer transformer) {\r
80         return transformer.transform(this);\r
81     }\r
82 \r
83 }\r