1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
|
module static-semantics/webdsl-hql
imports
static-semantics/types/built-ins
static-semantics/webdsl
static-semantics/webdsl-actions
static-semantics/webdsl-types
rules // unimplemented
stmtOk(_, _, HqlStatement(_), _) :- try { false } | warning $[This statement is not yet implemented].
rules
typeOfExp(s, HqlExp(hqlExp)) = typeOfHqlExp(s, hqlExp).
: scope * HqlExp -> TYPE
typeOfHqlExp(s, HqlQuery(queryRule)) = typeOfHqlQueryRule(s, queryRule).
typeOfHqlExp(s, HqlQueryLimit(queryRule, limitExp)) = typeOfHqlQueryRule(s, queryRule) :-
limitValueExpOk(s, limitExp).
typeOfHqlExp(, HqlQueryLimitOffset(queryRule, limitExp, offsetExp)) = typeOfHqlQueryRule(s, queryRule) :-
limitValueExpOk(s, limitExp),
limitValueExpOk(s, offsetExp).
: scope * HQLQueryRule -> TYPE
typeOfHqlQueryRule(, QueryRule(SelectFrom(select, from), where, groupBy, orderBy)) = t :- { }
new s_query,
t == typeOfHqlSelectFrom(s, s_query, select, from),
hqlWhereClauseOk(s, s_query, where),
hqlGroupByClauseOk(s, s_query, groupBy),
hqlOrderByClauseOk(s, s_query, orderBy).
: scope * scope * HQLSelectClauseOpt * HQLFromClause -> TYPE
typeOfHqlSelectFrom(s, _ , SelectNone() , from) = typeOfHqlFrom(s, from).
typeOfHqlSelectFrom(, , Select(_, selection), from) = t :-
hqlFromClauseOk(s, s_query, from),
t == typeOfHqlSelect(s, s_query, selection).
: scope * scope * HQLSelection -> TYPE
typeOfHqlSelect(s, s_query, SelectedProperties([aliasedExp])) = typeOfHqlAliasedExpression(s, s_query, aliasedExp).
typeOfHqlSelect(_, _, ps@SelectedProperties([_ | [_]])) = t :- false | error $[Selecting multiple properties is not allowed] @ps.
: scope * HQLFromClause -> TYPE
typeOfHqlFrom(s, FromClause([FromRangeJoin(fromRange, _) | _])) = typeOfHqlFromRange(s, fromRange).
: scope * HQLFromRange -> TYPE
typeOfHqlFromRange(s, FromClassOrOuterQueryPath(Path([]), _, _)) = LIST() :-
t == definedType(s, ent),
t == ENTITY(_, _) | error $[[ent] is not an entity] @ent.
: scope * scope * HQLAliasedExpression -> TYPE
typeOfHqlAliasedExpression(s, s_query, AliasedExpression(hqlExp, AsAliasNone())) = typeOfHqlExpression(s, s_query, hqlExp).
typeOfHqlAliasedExpression(_, _, AliasedExpression(_, a@AsAlias(_))) = t :- try { false } | warning $[Aliased expressions not yet implemented] @a.
: scope * scope * HQLExpression -> TYPE
typeOfHqlExpression(_, _, ) = UNTYPED() :- try { false } | warning $[HQL Expression [e] not yet implemented] @e.
typeOfHqlExpression(s, s_query, HQLAvg(e)) = float(s) :- { t } t == typeOfHqlExpression(s, s_query, e).
typeOfHqlExpression(s, s_query, HQLSum(e)) = int(s) :- { t } t == typeOfHqlExpression(s, s_query, e). // TO-DO: possibly return float instead of int, based on selection
typeOfHqlExpression(s, s_query, HQLMin(e)) = int(s) :- { t } t == typeOfHqlExpression(s, s_query, e). // TO-DO: possibly return float instead of int, based on selection
typeOfHqlExpression(s, s_query, HQLMax(e)) = int(s) :- { t } t == typeOfHqlExpression(s, s_query, e). // TO-DO: possibly return float instead of int, based on selection
typeOfHqlExpression(s, s_query, HQLCountStar()) = int(s).
typeOfHqlExpression(s, s_query, HQLCount(e)) = int(s) :- { t } t == typeOfHqlExpression(s, s_query, e).
typeOfHqlExpression(_, s_query, HQLPath(Path([]))) = LIST() :- { }
resolveVar(s_query, p) == [(_, (p', t))] | error $[Cannot resolve [p]],
@p.type := t,
@p.ref := p'.
typeOfHqlExpression(s, s_query, HQLPath(Path([, prop]))) = LIST(t) :- { }
resolveVar(s_query, ent) == [(_, (ent', entityType))] | error $[Cannot resolve [ent]] @ent,
t == typeOfProperty(s, entityType, prop),
@ent.type := entityType,
@ent.ref := ent'.
rules // fill scope graph using HQL From clause
: scope * scope * HQLFromClause
hqlFromClauseOk(s, s_query, FromClause(fromRangeJoins)) :- hqlFromRangeJoinsOk(s, s_query, fromRangeJoins).
hqlFromRangeJoinsOk maps hqlFromRangeJoinOk(*, *, list(*))
: scope * scope * HQLFromRangeJoin
hqlFromRangeJoinOk(, , FromRangeJoin(fromRange, joins)) :-
hqlFromRangeOk(s, s_query, fromRange),
hqlFromJoinsOk(s, s_query, joins).
: scope * scope * HQLFromRange
hqlFromRangeOk(s, , FromClassOrOuterQueryPath(path, alias, _)) :- { }
t == typeOfHqlFromPath(s, s_query, path),
declAlias(s_query, t, alias).
hqlFromJoinsOk maps hqlFromJoinOk(*, *, list(*))
: scope * scope * HQLFromJoin
hqlFromJoinOk(s, , FromJoin(_, _, path, alias, _, _)) :- { }
t == typeOfHqlFromPath(s, s_query, path),
declAlias(s_query, t, alias).
rules // where, group by and order by analysis
: scope * scope * HQLWhereClauseOpt
hqlWhereClauseOk(_, _, WhereClauseNone()).
hqlWhereClauseOk(_, _, w@WhereClause(_)) :- try { false } | warning $[HQL Where clause is not yet implemented] @w.
: scope * scope * HQLGroupByClauseOpt
hqlGroupByClauseOk(_, _, HQLGroupByNone()).
hqlGroupByClauseOk(_, _, gb@HQLGroupBy(_, _)) :- try { false } | warning $[HQL Group By clause is not yet implemented] @gb.
: scope * scope * HQLOrderByClauseOpt
hqlOrderByClauseOk(_, _, OrderByClauseNone()).
hqlOrderByClauseOk(_, _, ob@OrderByClause(_)) :- try { false } | warning $[HQL Order By clause is not yet implemented] @ob.
rules // misc
: scope * LimitValueExp
limitValueExpOk(, LimitValueExp()) :-
typeCompatible(typeOfExp(s, exp), int(s)) | error $[Expression [exp] should be compatible with type Int].
limitValueExpOk(, LimitValueDslExp(DslExp())) :-
typeCompatible(typeOfExp(s, exp), int(s)) | error $[Expression [exp] should be compatible with type Int].
rules // utils
: scope * TYPE * HQLAsAliasOpt
declAlias(_, _, AsAliasNone()).
declAlias(s_query, t, AsAlias(Alias(a))) :- declareVar(s_query, a, t).
: scope * scope * HQLPath -> TYPE
typeOfHqlFromPath(s, _, Path([])) = :-
t == definedType(s, x)| error $[Cannot resolve [x]] @x,
t == ENTITY(_, _) | error $[[x] is not an entity] @x.
typeOfHqlFromPath(s, s_query, Path([ | tail])) = t :- { }
resolveVar(s_query, x) == [(_, (x', xType))] | error $[Cannot resolve [x]] @x,
t == typeOfHqlFromPathTail(s, xType, tail),
@x.type := xType,
@x.ref := x'.
: scope * TYPE * list(string) -> TYPE
typeOfHqlFromPathTail(s, entityType, []) = :-
t == stripOptionalSetOrListType(typeOfProperty(s, entityType, x)),
t == ENTITY(_, _) | error $[Property [x] is not an entity] @x.
typeOfHqlFromPathTail(, entityType, [ | tail]) = t :- { }
xType == stripOptionalSetOrListType(typeOfProperty(s, entityType, x)),
xType == ENTITY(_, _) | error $[Property [x] is not an entity] @x,
t == typeOfHqlFromPathTail(s, xType, tail).
|