Skip to content

webdsl-hql.stx

pdmosses/webdsl-statix/webdslstatix/trans/static-semantics/webdsl-hql.stx

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).