Mercurial > repos > tabletprog
annotate types.js @ 237:dae093baf36c
Optimized implementation of character classes
author | Mike Pavone <pavone@retrodev.com> |
---|---|
date | Sun, 05 Jan 2014 17:00:33 -0800 |
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 |