Mercurial > repos > tabletprog
annotate types.js @ 251:2557ce4e671f
Fix a couple of compiler bugs. topenv was getting initialized in multiple places. This resulted in multiple copies of modules getting created which caused problems for macro expansion. Additionally, arguments were not being marked as declared during code generation so assigning to an argument that was not closed over generated invalid C code.
author | Michael Pavone <pavone@retrodev.com> |
---|---|
date | Fri, 11 Apr 2014 22:29:32 -0700 |
parents | 09b65b364927 |
children |
rev | line source |
---|---|
99 | 1 function anytype() {}; |
2 anytype.prototype.satisfiedBy = function(type) { | |
3 return true; | |
4 }; | |
5 anytype.prototype.str = function(indent) { | |
6 if (indent === undefined) { | |
7 indent = ''; | |
8 } | |
9 return indent + 'any\n'; | |
10 }; | |
11 anytype.prototype.id = 0; | |
12 anytype.prototype.callable = true; | |
13 anytype.prototype.replaceParams = function() { return this; }; | |
14 var any = new anytype(); | |
15 | |
16 function typeparam(name, base) | |
17 { | |
18 this.name = name; | |
19 this.base = base; | |
20 this.callable = base.callable; | |
21 } | |
22 typeparam.prototype.replaceParams = function(paramtypes) { | |
23 if (!(this.name in paramtypes)) { | |
24 return this; | |
25 } | |
26 if (!this.base.satisfiedBy(paramtypes[this.name])) { | |
27 throw new Error('param ' + this.name + ' has base type ' + this.base.str() + ' which is not satisfied by ' + paramtypes[this.name].str()); | |
28 } | |
29 return paramtypes[this.name]; | |
30 }; | |
31 typeparam.prototype.satisfiedBy = function(type) { | |
32 return this.base.satisfiedBy(type); | |
33 }; | |
34 typeparam.prototype.str = function(indent) { | |
35 return indent + 'param ' + this.name + '\n'; | |
36 }; | |
37 | |
38 var nexttypeid = 1; | |
39 | |
40 function objecttype() | |
41 { | |
42 this.messages = {}; | |
43 this.id = nexttypeid++; | |
44 this.typeparams = []; | |
45 this.satisfies_cache = {}; | |
46 this.satisfies_cache[this.id] = true; | |
47 } | |
48 | |
49 objecttype.prototype.callable = false; | |
50 | |
51 objecttype.prototype.addMessage = function(name, type) | |
52 { | |
53 this.messages[name] = type; | |
54 }; | |
55 | |
56 objecttype.prototype.satisfiedBy = function(type) { | |
57 if (type.id in this.satisfies_cache) { | |
58 return this.satisfies_cache[type.id]; | |
59 } | |
60 //temporarily set cache entry to true to prevent infinite recursion | |
61 this.satisfies_cache[type.id] = true; | |
62 var ret = true; | |
63 if (type.messages === undefined) { | |
64 ret = false; | |
65 } | |
66 if (ret) { | |
67 for (var msgname in this.messages) { | |
68 if (!(msgname in type.messages) || !this.messages[msgname].satisfiedBy(type.messages[msgname])) { | |
69 ret = false; | |
70 break; | |
71 } | |
72 } | |
73 } | |
74 this.satisfies_cache[type.id] = ret; | |
75 return ret; | |
76 }; | |
77 | |
78 objecttype.prototype.str = function(indent) { | |
79 if (indent === undefined) { | |
80 indent = ''; | |
81 } | |
82 if (indent.length > 6) { | |
83 return 'max depth reached\n'; | |
84 } | |
85 var newindent = indent + '\t'; | |
86 var childindent = newindent + '\t' | |
87 var ret = indent + 'objectype {\n'; | |
88 for (var msgname in this.messages) { | |
89 ret += newindent + msgname + ':\n' + this.messages[msgname].str(childindent) | |
90 } | |
91 return ret + indent + '}\n'; | |
92 }; | |
93 | |
94 objecttype.prototype.replaceParams = function(paramtypes, visited) { | |
100
9db0e3533b23
Some work on parameterized types
Mike Pavone <pavone@retrodev.com>
parents:
99
diff
changeset
|
95 if (visited === undefined) { |
99 | 96 visited = {}; |
97 } | |
98 if (this.id in visited) { | |
99 return visited[this.id]; | |
100 } | |
101 var me = visited[this.id] = this.clone(); | |
102 for (var msgname in this.messages) { | |
103 me.messages[msgname] = me.messages[msgname].replaceParams(paramtypes, visited); | |
104 } | |
105 return me; | |
106 }; | |
107 | |
108 objecttype.prototype.clone = function() { | |
109 var clone = new objecttype(); | |
110 for (var msgname in this.messages) { | |
111 clone.messages[msgname] = this.messages[msgname]; | |
112 } | |
113 clone.typeparams = this.typeparams; | |
114 return clone; | |
115 }; | |
116 | |
117 function lambdatype() | |
118 { | |
119 this.id = nexttypeid++; | |
120 this.messages = {}; | |
121 this.params = []; | |
122 this.paramlu = {}; | |
123 this.typeparams = []; | |
124 this.returntype = any; | |
125 this.satisfies_cache = {}; | |
126 this.satisfies_cache[this.id] = true; | |
127 } | |
128 | |
129 lambdatype.prototype.callable = true; | |
130 | |
131 lambdatype.prototype.addParam = function(name) { | |
132 this.paramlu[name] = this.params.length; | |
133 this.params.push(any); | |
134 }; | |
135 | |
136 lambdatype.prototype.paramType = function(name, type) { | |
137 this.params[this.paramlu[name]] = type; | |
138 }; | |
139 | |
140 lambdatype.prototype.addMessage = function(name, type) | |
141 { | |
142 this.messages[name] = type; | |
143 }; | |
144 | |
145 lambdatype.prototype.satisfiedBy = function(type) { | |
146 if (type.id in this.satisfies_cache) { | |
147 return this.satisfies_cache[type.id]; | |
148 } | |
149 //temporarily set cache entry to true to prevent infinite recursion | |
150 this.satisfies_cache[type.id] = true; | |
151 var ret = true; | |
152 if (!(type.callable) || this.params.length != type.params.length) { | |
153 ret = false; | |
154 } | |
155 if (ret) { | |
156 for (var i in this.params) { | |
103
182c311a9fed
Fix variance of lambda parameters
Mike Pavone <pavone@retrodev.com>
parents:
102
diff
changeset
|
157 if (i >= type.params.length || !type.params[i].satisfiedBy(this.params[i])) { |
99 | 158 ret = false; |
159 break; | |
160 } | |
161 } | |
162 } | |
163 if (ret) { | |
164 for (var msgname in this.messages) { | |
165 if (!(msgname in type.messages) || !this.messages[msgname].satisfiedBy(type.messages[msgname])) { | |
166 ret = false; | |
167 break; | |
168 } | |
169 } | |
170 } | |
171 ret = ret && this.returntype.satisfiedBy(type.returntype); | |
172 this.satisfies_cache[type.id] = ret; | |
173 return ret; | |
174 } | |
175 | |
176 lambdatype.prototype.str = function(indent) { | |
177 if (indent === undefined) { | |
178 indent = ''; | |
179 } | |
180 if (indent.length > 6) { | |
181 return 'max depth reached\n'; | |
182 } | |
183 var newindent = indent + '\t'; | |
184 var childindent = newindent + '\t' | |
185 var ret = indent + 'lambdatype {\n' + newindent + 'params: {\n'; | |
186 for (var i = 0; i < this.params.length; i++) { | |
187 ret += childindent + i + ':\n' + this.params[i].str(childindent + '\t'); | |
188 } | |
189 ret += newindent + '}\n' + newindent + 'returntype:\n' + this.returntype.str(childindent); | |
190 | |
191 for (var msgname in this.messages) { | |
192 ret += newindent + msgname + ':\n' + this.messages[msgname].str(childindent) | |
193 } | |
194 return ret + indent + '}\n'; | |
195 }; | |
196 | |
197 lambdatype.prototype.replaceParams = function(paramtypes, visited) { | |
100
9db0e3533b23
Some work on parameterized types
Mike Pavone <pavone@retrodev.com>
parents:
99
diff
changeset
|
198 if (visited === undefined) { |
99 | 199 visited = {}; |
200 } | |
201 if (this.id in visited) { | |
202 return visited[this.id]; | |
203 } | |
204 var me = visited[this.id] = this.clone(); | |
101
5d15b91e738a
Fix paramerized types. Remove debug print calls.
Mike Pavone <pavone@retrodev.com>
parents:
100
diff
changeset
|
205 for (var msgname in me.messages) { |
99 | 206 me.messages[msgname] = me.messages[msgname].replaceParams(paramtypes, visited); |
207 } | |
101
5d15b91e738a
Fix paramerized types. Remove debug print calls.
Mike Pavone <pavone@retrodev.com>
parents:
100
diff
changeset
|
208 for (var i in me.params) { |
5d15b91e738a
Fix paramerized types. Remove debug print calls.
Mike Pavone <pavone@retrodev.com>
parents:
100
diff
changeset
|
209 me.params[i] = me.params[i].replaceParams(paramtypes, visited); |
5d15b91e738a
Fix paramerized types. Remove debug print calls.
Mike Pavone <pavone@retrodev.com>
parents:
100
diff
changeset
|
210 } |
5d15b91e738a
Fix paramerized types. Remove debug print calls.
Mike Pavone <pavone@retrodev.com>
parents:
100
diff
changeset
|
211 me.returntype = me.returntype.replaceParams(paramtypes, visited); |
99 | 212 return me; |
213 }; | |
214 | |
215 lambdatype.prototype.clone = function() { | |
216 var clone = new lambdatype(); | |
217 for (var msgname in this.messages) { | |
218 clone.messages[msgname] = this.messages[msgname]; | |
219 } | |
220 clone.paramlu = this.paramlu; | |
221 clone.params = this.params.slice(0, this.params.length); | |
222 clone.returntype = this.returntype; | |
223 clone.typeparams = this.typeparams; | |
224 return clone; | |
225 }; | |
226 | |
227 function uniontype(a, b) | |
228 { | |
229 this.a = a; | |
230 this.b = b; | |
231 this.id = nexttypeid++; | |
232 this.satisfies_cache = null; | |
233 } | |
234 | |
101
5d15b91e738a
Fix paramerized types. Remove debug print calls.
Mike Pavone <pavone@retrodev.com>
parents:
100
diff
changeset
|
235 uniontype.prototype = { |
5d15b91e738a
Fix paramerized types. Remove debug print calls.
Mike Pavone <pavone@retrodev.com>
parents:
100
diff
changeset
|
236 lazyinit: function() { |
5d15b91e738a
Fix paramerized types. Remove debug print calls.
Mike Pavone <pavone@retrodev.com>
parents:
100
diff
changeset
|
237 if (this.satisfies_cache == null) { |
5d15b91e738a
Fix paramerized types. Remove debug print calls.
Mike Pavone <pavone@retrodev.com>
parents:
100
diff
changeset
|
238 this.satisfies_cache = {}; |
5d15b91e738a
Fix paramerized types. Remove debug print calls.
Mike Pavone <pavone@retrodev.com>
parents:
100
diff
changeset
|
239 this.satisfies_cache[this.id] = true; |
5d15b91e738a
Fix paramerized types. Remove debug print calls.
Mike Pavone <pavone@retrodev.com>
parents:
100
diff
changeset
|
240 this._messages = {}; |
5d15b91e738a
Fix paramerized types. Remove debug print calls.
Mike Pavone <pavone@retrodev.com>
parents:
100
diff
changeset
|
241 if (this.a.messages !== undefined && this.b.messages !== undefined) { |
5d15b91e738a
Fix paramerized types. Remove debug print calls.
Mike Pavone <pavone@retrodev.com>
parents:
100
diff
changeset
|
242 for (var msgname in this.a.messages) { |
5d15b91e738a
Fix paramerized types. Remove debug print calls.
Mike Pavone <pavone@retrodev.com>
parents:
100
diff
changeset
|
243 if (msgname in this.b.messages) { |
5d15b91e738a
Fix paramerized types. Remove debug print calls.
Mike Pavone <pavone@retrodev.com>
parents:
100
diff
changeset
|
244 this._messages[msgname] = mkunion(this.a.messages[msgname], this.b.messages[msgname]); |
5d15b91e738a
Fix paramerized types. Remove debug print calls.
Mike Pavone <pavone@retrodev.com>
parents:
100
diff
changeset
|
245 } |
99 | 246 } |
247 } | |
101
5d15b91e738a
Fix paramerized types. Remove debug print calls.
Mike Pavone <pavone@retrodev.com>
parents:
100
diff
changeset
|
248 this._callable = false; |
5d15b91e738a
Fix paramerized types. Remove debug print calls.
Mike Pavone <pavone@retrodev.com>
parents:
100
diff
changeset
|
249 if (this.a.callable && this.b.callable && this.a.params.length == this.b.params.length) { |
5d15b91e738a
Fix paramerized types. Remove debug print calls.
Mike Pavone <pavone@retrodev.com>
parents:
100
diff
changeset
|
250 this._callable = true; |
5d15b91e738a
Fix paramerized types. Remove debug print calls.
Mike Pavone <pavone@retrodev.com>
parents:
100
diff
changeset
|
251 this._params = []; |
5d15b91e738a
Fix paramerized types. Remove debug print calls.
Mike Pavone <pavone@retrodev.com>
parents:
100
diff
changeset
|
252 for (var i = 0; i < this.a.params.length; i++) { |
5d15b91e738a
Fix paramerized types. Remove debug print calls.
Mike Pavone <pavone@retrodev.com>
parents:
100
diff
changeset
|
253 this._params.push(mkunion(this.a.params[i], this.b.params[i])); |
5d15b91e738a
Fix paramerized types. Remove debug print calls.
Mike Pavone <pavone@retrodev.com>
parents:
100
diff
changeset
|
254 } |
5d15b91e738a
Fix paramerized types. Remove debug print calls.
Mike Pavone <pavone@retrodev.com>
parents:
100
diff
changeset
|
255 this._returntype = mkunion(this.a.returntype, this.b.returntype); |
5d15b91e738a
Fix paramerized types. Remove debug print calls.
Mike Pavone <pavone@retrodev.com>
parents:
100
diff
changeset
|
256 } |
99 | 257 } |
101
5d15b91e738a
Fix paramerized types. Remove debug print calls.
Mike Pavone <pavone@retrodev.com>
parents:
100
diff
changeset
|
258 }, |
5d15b91e738a
Fix paramerized types. Remove debug print calls.
Mike Pavone <pavone@retrodev.com>
parents:
100
diff
changeset
|
259 satisfiedBy: function(type) |
5d15b91e738a
Fix paramerized types. Remove debug print calls.
Mike Pavone <pavone@retrodev.com>
parents:
100
diff
changeset
|
260 { |
5d15b91e738a
Fix paramerized types. Remove debug print calls.
Mike Pavone <pavone@retrodev.com>
parents:
100
diff
changeset
|
261 this.lazyinit(); |
5d15b91e738a
Fix paramerized types. Remove debug print calls.
Mike Pavone <pavone@retrodev.com>
parents:
100
diff
changeset
|
262 if (type.id in this.satisfies_cache) { |
5d15b91e738a
Fix paramerized types. Remove debug print calls.
Mike Pavone <pavone@retrodev.com>
parents:
100
diff
changeset
|
263 return this.satisfies_cache[type.id]; |
5d15b91e738a
Fix paramerized types. Remove debug print calls.
Mike Pavone <pavone@retrodev.com>
parents:
100
diff
changeset
|
264 } |
5d15b91e738a
Fix paramerized types. Remove debug print calls.
Mike Pavone <pavone@retrodev.com>
parents:
100
diff
changeset
|
265 this.satisfies_cache[type.id] = true; |
5d15b91e738a
Fix paramerized types. Remove debug print calls.
Mike Pavone <pavone@retrodev.com>
parents:
100
diff
changeset
|
266 var ret = this.a.satisfiedBy(type) || this.b.satisfiedBy(type); |
5d15b91e738a
Fix paramerized types. Remove debug print calls.
Mike Pavone <pavone@retrodev.com>
parents:
100
diff
changeset
|
267 this.satisfies_cache[type.id] = ret; |
5d15b91e738a
Fix paramerized types. Remove debug print calls.
Mike Pavone <pavone@retrodev.com>
parents:
100
diff
changeset
|
268 return ret; |
5d15b91e738a
Fix paramerized types. Remove debug print calls.
Mike Pavone <pavone@retrodev.com>
parents:
100
diff
changeset
|
269 }, |
5d15b91e738a
Fix paramerized types. Remove debug print calls.
Mike Pavone <pavone@retrodev.com>
parents:
100
diff
changeset
|
270 str: function(indent) |
5d15b91e738a
Fix paramerized types. Remove debug print calls.
Mike Pavone <pavone@retrodev.com>
parents:
100
diff
changeset
|
271 { |
5d15b91e738a
Fix paramerized types. Remove debug print calls.
Mike Pavone <pavone@retrodev.com>
parents:
100
diff
changeset
|
272 if (indent === undefined) { |
5d15b91e738a
Fix paramerized types. Remove debug print calls.
Mike Pavone <pavone@retrodev.com>
parents:
100
diff
changeset
|
273 indent = ''; |
5d15b91e738a
Fix paramerized types. Remove debug print calls.
Mike Pavone <pavone@retrodev.com>
parents:
100
diff
changeset
|
274 } |
5d15b91e738a
Fix paramerized types. Remove debug print calls.
Mike Pavone <pavone@retrodev.com>
parents:
100
diff
changeset
|
275 if (indent.length > 6) { |
5d15b91e738a
Fix paramerized types. Remove debug print calls.
Mike Pavone <pavone@retrodev.com>
parents:
100
diff
changeset
|
276 return 'max depth reached\n'; |
5d15b91e738a
Fix paramerized types. Remove debug print calls.
Mike Pavone <pavone@retrodev.com>
parents:
100
diff
changeset
|
277 } |
5d15b91e738a
Fix paramerized types. Remove debug print calls.
Mike Pavone <pavone@retrodev.com>
parents:
100
diff
changeset
|
278 return indent + 'Union {\n\t' + indent + this.a.str(indent+'\t') + '\t' + indent + this.b.str(indent+'\t') + indent + '}\n'; |
5d15b91e738a
Fix paramerized types. Remove debug print calls.
Mike Pavone <pavone@retrodev.com>
parents:
100
diff
changeset
|
279 }, |
5d15b91e738a
Fix paramerized types. Remove debug print calls.
Mike Pavone <pavone@retrodev.com>
parents:
100
diff
changeset
|
280 replaceParams: function(paramtypes, visited) { |
5d15b91e738a
Fix paramerized types. Remove debug print calls.
Mike Pavone <pavone@retrodev.com>
parents:
100
diff
changeset
|
281 if (visited === undefined) { |
5d15b91e738a
Fix paramerized types. Remove debug print calls.
Mike Pavone <pavone@retrodev.com>
parents:
100
diff
changeset
|
282 visited = {}; |
99 | 283 } |
101
5d15b91e738a
Fix paramerized types. Remove debug print calls.
Mike Pavone <pavone@retrodev.com>
parents:
100
diff
changeset
|
284 if (this.id in visited) { |
5d15b91e738a
Fix paramerized types. Remove debug print calls.
Mike Pavone <pavone@retrodev.com>
parents:
100
diff
changeset
|
285 return visited[this.id]; |
5d15b91e738a
Fix paramerized types. Remove debug print calls.
Mike Pavone <pavone@retrodev.com>
parents:
100
diff
changeset
|
286 } |
5d15b91e738a
Fix paramerized types. Remove debug print calls.
Mike Pavone <pavone@retrodev.com>
parents:
100
diff
changeset
|
287 var me = visited[this.id] = this.clone(); |
5d15b91e738a
Fix paramerized types. Remove debug print calls.
Mike Pavone <pavone@retrodev.com>
parents:
100
diff
changeset
|
288 me.a = me.a.replaceParams(paramtypes, visited); |
5d15b91e738a
Fix paramerized types. Remove debug print calls.
Mike Pavone <pavone@retrodev.com>
parents:
100
diff
changeset
|
289 me.b = me.b.replaceParams(paramtypes, visited); |
5d15b91e738a
Fix paramerized types. Remove debug print calls.
Mike Pavone <pavone@retrodev.com>
parents:
100
diff
changeset
|
290 return me; |
5d15b91e738a
Fix paramerized types. Remove debug print calls.
Mike Pavone <pavone@retrodev.com>
parents:
100
diff
changeset
|
291 }, |
5d15b91e738a
Fix paramerized types. Remove debug print calls.
Mike Pavone <pavone@retrodev.com>
parents:
100
diff
changeset
|
292 clone: function() { |
5d15b91e738a
Fix paramerized types. Remove debug print calls.
Mike Pavone <pavone@retrodev.com>
parents:
100
diff
changeset
|
293 return new uniontype(this.a, this.b); |
5d15b91e738a
Fix paramerized types. Remove debug print calls.
Mike Pavone <pavone@retrodev.com>
parents:
100
diff
changeset
|
294 }, |
5d15b91e738a
Fix paramerized types. Remove debug print calls.
Mike Pavone <pavone@retrodev.com>
parents:
100
diff
changeset
|
295 get messages() { |
5d15b91e738a
Fix paramerized types. Remove debug print calls.
Mike Pavone <pavone@retrodev.com>
parents:
100
diff
changeset
|
296 this.lazyinit(); |
5d15b91e738a
Fix paramerized types. Remove debug print calls.
Mike Pavone <pavone@retrodev.com>
parents:
100
diff
changeset
|
297 return this._messages; |
5d15b91e738a
Fix paramerized types. Remove debug print calls.
Mike Pavone <pavone@retrodev.com>
parents:
100
diff
changeset
|
298 }, |
5d15b91e738a
Fix paramerized types. Remove debug print calls.
Mike Pavone <pavone@retrodev.com>
parents:
100
diff
changeset
|
299 get params() { |
5d15b91e738a
Fix paramerized types. Remove debug print calls.
Mike Pavone <pavone@retrodev.com>
parents:
100
diff
changeset
|
300 this.lazyinit(); |
5d15b91e738a
Fix paramerized types. Remove debug print calls.
Mike Pavone <pavone@retrodev.com>
parents:
100
diff
changeset
|
301 return this._params; |
5d15b91e738a
Fix paramerized types. Remove debug print calls.
Mike Pavone <pavone@retrodev.com>
parents:
100
diff
changeset
|
302 }, |
5d15b91e738a
Fix paramerized types. Remove debug print calls.
Mike Pavone <pavone@retrodev.com>
parents:
100
diff
changeset
|
303 get returntype() { |
5d15b91e738a
Fix paramerized types. Remove debug print calls.
Mike Pavone <pavone@retrodev.com>
parents:
100
diff
changeset
|
304 this.lazyinit(); |
5d15b91e738a
Fix paramerized types. Remove debug print calls.
Mike Pavone <pavone@retrodev.com>
parents:
100
diff
changeset
|
305 return this._returntype; |
5d15b91e738a
Fix paramerized types. Remove debug print calls.
Mike Pavone <pavone@retrodev.com>
parents:
100
diff
changeset
|
306 }, |
5d15b91e738a
Fix paramerized types. Remove debug print calls.
Mike Pavone <pavone@retrodev.com>
parents:
100
diff
changeset
|
307 get callable() { |
5d15b91e738a
Fix paramerized types. Remove debug print calls.
Mike Pavone <pavone@retrodev.com>
parents:
100
diff
changeset
|
308 this.lazyinit(); |
5d15b91e738a
Fix paramerized types. Remove debug print calls.
Mike Pavone <pavone@retrodev.com>
parents:
100
diff
changeset
|
309 return this._callable; |
99 | 310 } |
311 }; | |
312 | |
313 | |
314 function mkunion(a, b) | |
315 { | |
316 //if b is a subtype of a, then a | b is equivalent to a | |
317 if (a.satisfiedBy(b)) { | |
318 return a; | |
319 } | |
320 //if a is a subtype of b, then a | b is equivalent to b | |
321 if (b.satisfiedBy(a)) { | |
322 return b; | |
323 } | |
324 return new uniontype(a, b); | |
325 } | |
326 | |
327 function withtparams(type, params) | |
328 { | |
329 this.type = type; | |
330 this.params = params; | |
100
9db0e3533b23
Some work on parameterized types
Mike Pavone <pavone@retrodev.com>
parents:
99
diff
changeset
|
331 this.replaced = false; |
99 | 332 } |
333 | |
100
9db0e3533b23
Some work on parameterized types
Mike Pavone <pavone@retrodev.com>
parents:
99
diff
changeset
|
334 withtparams.prototype = { |
9db0e3533b23
Some work on parameterized types
Mike Pavone <pavone@retrodev.com>
parents:
99
diff
changeset
|
335 satisfiedBy: function(type) { |
9db0e3533b23
Some work on parameterized types
Mike Pavone <pavone@retrodev.com>
parents:
99
diff
changeset
|
336 this.lazyinit(); |
9db0e3533b23
Some work on parameterized types
Mike Pavone <pavone@retrodev.com>
parents:
99
diff
changeset
|
337 return this.type.satisfiedBy(type); |
9db0e3533b23
Some work on parameterized types
Mike Pavone <pavone@retrodev.com>
parents:
99
diff
changeset
|
338 }, |
9db0e3533b23
Some work on parameterized types
Mike Pavone <pavone@retrodev.com>
parents:
99
diff
changeset
|
339 str: function(indent) { |
9db0e3533b23
Some work on parameterized types
Mike Pavone <pavone@retrodev.com>
parents:
99
diff
changeset
|
340 if (indent === undefined) { |
9db0e3533b23
Some work on parameterized types
Mike Pavone <pavone@retrodev.com>
parents:
99
diff
changeset
|
341 indent = ''; |
9db0e3533b23
Some work on parameterized types
Mike Pavone <pavone@retrodev.com>
parents:
99
diff
changeset
|
342 } |
9db0e3533b23
Some work on parameterized types
Mike Pavone <pavone@retrodev.com>
parents:
99
diff
changeset
|
343 if (indent.length > 6) { |
9db0e3533b23
Some work on parameterized types
Mike Pavone <pavone@retrodev.com>
parents:
99
diff
changeset
|
344 return 'max depth reached\n'; |
99 | 345 } |
100
9db0e3533b23
Some work on parameterized types
Mike Pavone <pavone@retrodev.com>
parents:
99
diff
changeset
|
346 return this.type.str(indent) + indent + '<' + this.params.map(function(p) { return p.str(indent); }).join(', ') + '>'; |
9db0e3533b23
Some work on parameterized types
Mike Pavone <pavone@retrodev.com>
parents:
99
diff
changeset
|
347 }, |
9db0e3533b23
Some work on parameterized types
Mike Pavone <pavone@retrodev.com>
parents:
99
diff
changeset
|
348 replaceParams: function(paramtypes) { |
9db0e3533b23
Some work on parameterized types
Mike Pavone <pavone@retrodev.com>
parents:
99
diff
changeset
|
349 var replaced = false; |
9db0e3533b23
Some work on parameterized types
Mike Pavone <pavone@retrodev.com>
parents:
99
diff
changeset
|
350 for (var i in this.params) { |
9db0e3533b23
Some work on parameterized types
Mike Pavone <pavone@retrodev.com>
parents:
99
diff
changeset
|
351 var newp = this.params[i].replaceParams(paramtypes); |
9db0e3533b23
Some work on parameterized types
Mike Pavone <pavone@retrodev.com>
parents:
99
diff
changeset
|
352 if (newp != this.params[i]) { |
9db0e3533b23
Some work on parameterized types
Mike Pavone <pavone@retrodev.com>
parents:
99
diff
changeset
|
353 replaced = true; |
9db0e3533b23
Some work on parameterized types
Mike Pavone <pavone@retrodev.com>
parents:
99
diff
changeset
|
354 this.params[i] = newp; |
9db0e3533b23
Some work on parameterized types
Mike Pavone <pavone@retrodev.com>
parents:
99
diff
changeset
|
355 } |
9db0e3533b23
Some work on parameterized types
Mike Pavone <pavone@retrodev.com>
parents:
99
diff
changeset
|
356 } |
9db0e3533b23
Some work on parameterized types
Mike Pavone <pavone@retrodev.com>
parents:
99
diff
changeset
|
357 return this; |
9db0e3533b23
Some work on parameterized types
Mike Pavone <pavone@retrodev.com>
parents:
99
diff
changeset
|
358 }, |
9db0e3533b23
Some work on parameterized types
Mike Pavone <pavone@retrodev.com>
parents:
99
diff
changeset
|
359 lazyinit: function() { |
9db0e3533b23
Some work on parameterized types
Mike Pavone <pavone@retrodev.com>
parents:
99
diff
changeset
|
360 if (!this.replaced) { |
9db0e3533b23
Some work on parameterized types
Mike Pavone <pavone@retrodev.com>
parents:
99
diff
changeset
|
361 var childptypes = {}; |
9db0e3533b23
Some work on parameterized types
Mike Pavone <pavone@retrodev.com>
parents:
99
diff
changeset
|
362 for (var i in this.type.typeparams) { |
9db0e3533b23
Some work on parameterized types
Mike Pavone <pavone@retrodev.com>
parents:
99
diff
changeset
|
363 childptypes[this.type.typeparams[i]] = this.params[i] |
9db0e3533b23
Some work on parameterized types
Mike Pavone <pavone@retrodev.com>
parents:
99
diff
changeset
|
364 } |
9db0e3533b23
Some work on parameterized types
Mike Pavone <pavone@retrodev.com>
parents:
99
diff
changeset
|
365 this.type = this.type.replaceParams(childptypes, {}); |
9db0e3533b23
Some work on parameterized types
Mike Pavone <pavone@retrodev.com>
parents:
99
diff
changeset
|
366 this.replaced = true; |
9db0e3533b23
Some work on parameterized types
Mike Pavone <pavone@retrodev.com>
parents:
99
diff
changeset
|
367 } |
9db0e3533b23
Some work on parameterized types
Mike Pavone <pavone@retrodev.com>
parents:
99
diff
changeset
|
368 }, |
9db0e3533b23
Some work on parameterized types
Mike Pavone <pavone@retrodev.com>
parents:
99
diff
changeset
|
369 get messages() { |
9db0e3533b23
Some work on parameterized types
Mike Pavone <pavone@retrodev.com>
parents:
99
diff
changeset
|
370 this.lazyinit(); |
9db0e3533b23
Some work on parameterized types
Mike Pavone <pavone@retrodev.com>
parents:
99
diff
changeset
|
371 return this.type.messages; |
99 | 372 } |
373 }; | |
374 | |
129
09b65b364927
Some old changes to the WIP type checker
Mike Pavone <pavone@retrodev.com>
parents:
103
diff
changeset
|
375 object.prototype.toType = function(parent) { |
09b65b364927
Some old changes to the WIP type checker
Mike Pavone <pavone@retrodev.com>
parents:
103
diff
changeset
|
376 var me = new objecttype(); |
09b65b364927
Some old changes to the WIP type checker
Mike Pavone <pavone@retrodev.com>
parents:
103
diff
changeset
|
377 for (var i in this.messages) { |
09b65b364927
Some old changes to the WIP type checker
Mike Pavone <pavone@retrodev.com>
parents:
103
diff
changeset
|
378 this.messages[i].toObjectType(me); |
09b65b364927
Some old changes to the WIP type checker
Mike Pavone <pavone@retrodev.com>
parents:
103
diff
changeset
|
379 } |
09b65b364927
Some old changes to the WIP type checker
Mike Pavone <pavone@retrodev.com>
parents:
103
diff
changeset
|
380 return me; |
09b65b364927
Some old changes to the WIP type checker
Mike Pavone <pavone@retrodev.com>
parents:
103
diff
changeset
|
381 }; |
09b65b364927
Some old changes to the WIP type checker
Mike Pavone <pavone@retrodev.com>
parents:
103
diff
changeset
|
382 |
09b65b364927
Some old changes to the WIP type checker
Mike Pavone <pavone@retrodev.com>
parents:
103
diff
changeset
|
383 lambda.prototype.toType = function(parent) { |
09b65b364927
Some old changes to the WIP type checker
Mike Pavone <pavone@retrodev.com>
parents:
103
diff
changeset
|
384 var me = new lambdatype(); |
09b65b364927
Some old changes to the WIP type checker
Mike Pavone <pavone@retrodev.com>
parents:
103
diff
changeset
|
385 for (var i in this.args) { |
09b65b364927
Some old changes to the WIP type checker
Mike Pavone <pavone@retrodev.com>
parents:
103
diff
changeset
|
386 me.addParam(this.args[i].cleanName()); |
09b65b364927
Some old changes to the WIP type checker
Mike Pavone <pavone@retrodev.com>
parents:
103
diff
changeset
|
387 } |
09b65b364927
Some old changes to the WIP type checker
Mike Pavone <pavone@retrodev.com>
parents:
103
diff
changeset
|
388 for (var i in this.expressions) { |
09b65b364927
Some old changes to the WIP type checker
Mike Pavone <pavone@retrodev.com>
parents:
103
diff
changeset
|
389 this.expressions[i].toType(me); |
09b65b364927
Some old changes to the WIP type checker
Mike Pavone <pavone@retrodev.com>
parents:
103
diff
changeset
|
390 } |
09b65b364927
Some old changes to the WIP type checker
Mike Pavone <pavone@retrodev.com>
parents:
103
diff
changeset
|
391 return me; |
09b65b364927
Some old changes to the WIP type checker
Mike Pavone <pavone@retrodev.com>
parents:
103
diff
changeset
|
392 }; |
09b65b364927
Some old changes to the WIP type checker
Mike Pavone <pavone@retrodev.com>
parents:
103
diff
changeset
|
393 |
09b65b364927
Some old changes to the WIP type checker
Mike Pavone <pavone@retrodev.com>
parents:
103
diff
changeset
|
394 funcall.prototype.toType = function(parent) { |
09b65b364927
Some old changes to the WIP type checker
Mike Pavone <pavone@retrodev.com>
parents:
103
diff
changeset
|
395 var name = this.name[this.name.length-1] == ':' ? this.name.substr(0, this.name.length-1) : this.name; |
09b65b364927
Some old changes to the WIP type checker
Mike Pavone <pavone@retrodev.com>
parents:
103
diff
changeset
|
396 switch(name) |
09b65b364927
Some old changes to the WIP type checker
Mike Pavone <pavone@retrodev.com>
parents:
103
diff
changeset
|
397 { |
09b65b364927
Some old changes to the WIP type checker
Mike Pavone <pavone@retrodev.com>
parents:
103
diff
changeset
|
398 case 'typeParam': |
09b65b364927
Some old changes to the WIP type checker
Mike Pavone <pavone@retrodev.com>
parents:
103
diff
changeset
|
399 break; |
09b65b364927
Some old changes to the WIP type checker
Mike Pavone <pavone@retrodev.com>
parents:
103
diff
changeset
|
400 case 'isa': |
09b65b364927
Some old changes to the WIP type checker
Mike Pavone <pavone@retrodev.com>
parents:
103
diff
changeset
|
401 break; |
09b65b364927
Some old changes to the WIP type checker
Mike Pavone <pavone@retrodev.com>
parents:
103
diff
changeset
|
402 }; |
09b65b364927
Some old changes to the WIP type checker
Mike Pavone <pavone@retrodev.com>
parents:
103
diff
changeset
|
403 |
09b65b364927
Some old changes to the WIP type checker
Mike Pavone <pavone@retrodev.com>
parents:
103
diff
changeset
|
404 assignment.prototype.toObjectType = function(parent) { |
09b65b364927
Some old changes to the WIP type checker
Mike Pavone <pavone@retrodev.com>
parents:
103
diff
changeset
|
405 if (this.expression.instanceof lambda) { |
09b65b364927
Some old changes to the WIP type checker
Mike Pavone <pavone@retrodev.com>
parents:
103
diff
changeset
|
406 parent.addMessage(this.symbol.name, this.expression.toType(parent)); |
09b65b364927
Some old changes to the WIP type checker
Mike Pavone <pavone@retrodev.com>
parents:
103
diff
changeset
|
407 } else { |
09b65b364927
Some old changes to the WIP type checker
Mike Pavone <pavone@retrodev.com>
parents:
103
diff
changeset
|
408 var valtype = this.expression.toType(parent); |
09b65b364927
Some old changes to the WIP type checker
Mike Pavone <pavone@retrodev.com>
parents:
103
diff
changeset
|
409 var getter = new lambdatype(); |
09b65b364927
Some old changes to the WIP type checker
Mike Pavone <pavone@retrodev.com>
parents:
103
diff
changeset
|
410 getter.returntype = valtype; |
09b65b364927
Some old changes to the WIP type checker
Mike Pavone <pavone@retrodev.com>
parents:
103
diff
changeset
|
411 var setter = new lambdatype(); |
09b65b364927
Some old changes to the WIP type checker
Mike Pavone <pavone@retrodev.com>
parents:
103
diff
changeset
|
412 setter.addParam('val'); |
09b65b364927
Some old changes to the WIP type checker
Mike Pavone <pavone@retrodev.com>
parents:
103
diff
changeset
|
413 setter.paramType('val', valtype); |
09b65b364927
Some old changes to the WIP type checker
Mike Pavone <pavone@retrodev.com>
parents:
103
diff
changeset
|
414 setter.returntype = parent; |
09b65b364927
Some old changes to the WIP type checker
Mike Pavone <pavone@retrodev.com>
parents:
103
diff
changeset
|
415 parent.addMessage(this.symbol.name, setter); |
09b65b364927
Some old changes to the WIP type checker
Mike Pavone <pavone@retrodev.com>
parents:
103
diff
changeset
|
416 } |
09b65b364927
Some old changes to the WIP type checker
Mike Pavone <pavone@retrodev.com>
parents:
103
diff
changeset
|
417 }; |
09b65b364927
Some old changes to the WIP type checker
Mike Pavone <pavone@retrodev.com>
parents:
103
diff
changeset
|
418 |
99 | 419 function typetest() |
420 { | |
421 var foo = new objecttype(); | |
422 var msgtype = new lambdatype(); | |
423 msgtype.addParam('fo'); | |
424 msgtype.returntype = foo; | |
425 foo.addMessage('bar', msgtype); | |
426 var baz = new objecttype(); | |
427 var msgtype2 = new lambdatype(); | |
428 msgtype2.addParam('fo'); | |
429 msgtype2.paramType('fo', foo); | |
430 msgtype2.returntype = baz; | |
431 baz.addMessage('bar', msgtype2); | |
432 baz.addMessage('qux', msgtype); | |
433 var shizzle = new objecttype(); | |
434 shizzle.addMessage('bar', msgtype); | |
435 shizzle.addMessage('boo', msgtype); | |
436 return {foo: foo, baz: baz, shizzle: shizzle}; | |
437 } | |
438 | |
439 function paramtypetest() | |
440 { | |
441 var empty = new objecttype(); | |
442 var tlnode = new objecttype(); | |
443 tlnode.typeparams = ['T']; | |
444 var t = new typeparam('T', any); | |
445 var q = new typeparam('Q', any); | |
446 var head = new lambdatype(); | |
100
9db0e3533b23
Some work on parameterized types
Mike Pavone <pavone@retrodev.com>
parents:
99
diff
changeset
|
447 head.returntype = t; |
99 | 448 tlnode.addMessage('head', head); |
449 var tail = new lambdatype(); | |
450 var econs = new lambdatype(); | |
451 econs.addParam('val'); | |
452 econs.typeparams = ['Q']; | |
453 econs.paramType('val', q); | |
454 econs.returntype = new withtparams(tlnode, [q]); | |
455 empty.addMessage('cons', econs); | |
456 tail.returntype = new uniontype(new withtparams(tlnode, [t]), empty); | |
457 tlnode.addMessage('tail', tail); | |
458 var cons = new lambdatype(); | |
459 cons.addParam('val'); | |
460 cons.paramType('val', t); | |
461 cons.returntype = new withtparams(tlnode, [t]); | |
462 tlnode.addMessage('cons', cons); | |
463 return {empty: empty, tlnode: tlnode}; | |
464 } | |
465 |