mix-language 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,419 @@
1
+ /**
2
+ * Copyright © 2011 Jesse Sielaff
3
+ */
4
+
5
+ function evaluate (node)
6
+ {
7
+ if (BREAK_VALUE || RETURN_VALUE)
8
+ {
9
+ return BREAK_VALUE || RETURN_VALUE;
10
+ }
11
+
12
+ switch (node[0])
13
+ {
14
+ case access_brackets:
15
+ var obj = evaluate(node[1]);
16
+ var key = evaluate(node[2]);
17
+
18
+ return call_function(obj, 'brackets', [key]);
19
+
20
+ case access_colon:
21
+ var obj = evaluate(node[1]);
22
+ var name = SYMBOLS[node[2]];
23
+
24
+ return obj.data[name] || obj.unknown(obj, [new_string(name)]);
25
+
26
+ case access_hash:
27
+ var bound = evaluate(node[1]);
28
+ var name = SYMBOLS[node[2]];
29
+
30
+ if (!bound)
31
+ {
32
+ bug("Tried to call " + name + " on a non-Mix value");
33
+ }
34
+
35
+ var body = bound.functions[name];
36
+
37
+ if (!body)
38
+ {
39
+ warn("Ignoring unknown function " + name);
40
+ body = function (self, args) { return NULL; };
41
+ body.parameters = [];
42
+ }
43
+
44
+ return new_function(body, bound);
45
+
46
+ case and:
47
+ var left = evaluate(node[1]);
48
+ return (left === NULL || left === FALSE) ? left : evaluate(node[2]);
49
+
50
+ case app:
51
+ return APP;
52
+
53
+ case array:
54
+ var items = [];
55
+ var item_nodes = node[1];
56
+
57
+ for (var i = 0, l = item_nodes.length; i < l; ++i)
58
+ {
59
+ items[i] = evaluate(item_nodes[i]);
60
+ }
61
+
62
+ return new_array(items);
63
+
64
+ case break:
65
+ if (!ITERATING)
66
+ {
67
+ warn("Ignoring break outside of iteration context");
68
+ return NULL;
69
+ }
70
+
71
+ BREAK_VALUE = evaluate(node[1]);
72
+ return NULL;
73
+
74
+ case call:
75
+ var func = evaluate(node[1]);
76
+
77
+ if (func.object_type !== FUNCTION_TYPE)
78
+ {
79
+ warn("Ignoring function call to a non-function object");
80
+ return func;
81
+ }
82
+
83
+ var argument_nodes = node[2];
84
+ var arguments = [];
85
+
86
+ for (var i = 0, l = argument_nodes.length; i < l; ++i)
87
+ {
88
+ arguments[i] = evaluate(argument_nodes[i]);
89
+ }
90
+
91
+ var result = func.value(func.bound, arguments);
92
+
93
+ if (RETURN_VALUE)
94
+ {
95
+ result = RETURN_VALUE;
96
+ RETURN_VALUE = null;
97
+ }
98
+
99
+ return result;
100
+
101
+ case false:
102
+ return FALSE;
103
+
104
+ case function:
105
+ var variables = node[1];
106
+ var body_statement = node[2];
107
+ var parameters = variables[0];
108
+ var embedded = variables[1];
109
+ var embedded_values = [];
110
+
111
+ for (var name, i = 0, l = embedded.length; i < l; ++i)
112
+ {
113
+ name = SYMBOLS[embedded[i]];
114
+ embedded_values[name] = VARIABLES[name];
115
+ }
116
+
117
+ var body = function (self, args)
118
+ {
119
+ var old_self = SELF;
120
+ var old_variables = VARIABLES;
121
+
122
+ SELF = self;
123
+ VARIABLES = {};
124
+
125
+ for (var name, i = 0, l = embedded.length; i < l; ++i)
126
+ {
127
+ name = SYMBOLS[embedded[i]];
128
+ VARIABLES[name] = embedded_values[name];
129
+ }
130
+
131
+ for (var name, i = 0, l = parameters.length; i < l; ++i)
132
+ {
133
+ name = SYMBOLS[parameters[i]];
134
+ VARIABLES[name] = args[i];
135
+ }
136
+
137
+ var result = evaluate(body_statement);
138
+
139
+ SELF = old_self;
140
+ VARIABLES = old_variables;
141
+
142
+ return result;
143
+ };
144
+
145
+ for (var p = [], i = 0, l = parameters.length; i < l; ++i)
146
+ {
147
+ p[i] = SYMBOLS[parameters[i]];
148
+ }
149
+
150
+ body.parameters = p;
151
+
152
+ return new_function(body, SELF);
153
+
154
+ case if:
155
+ var condition = evaluate(node[1]);
156
+
157
+ if (condition !== NULL && condition !== FALSE)
158
+ {
159
+ return evaluate(node[2]);
160
+ }
161
+ else
162
+ {
163
+ return evaluate(node[3]);
164
+ }
165
+
166
+ case mix:
167
+ var obj = evaluate(node[1]);
168
+ var name = SYMBOLS[node[2]];
169
+ var mixin = (MIXINS[name] = MIXINS[name] || {functions: {}});
170
+
171
+ copy_functions(obj, mixin);
172
+
173
+ if (init_function = mixin.init)
174
+ {
175
+ init_function(obj);
176
+ }
177
+
178
+ return obj;
179
+
180
+ case mixin:
181
+ var name = SYMBOLS[node[1]];
182
+ var mixin = (MIXINS[name] = MIXINS[name] || {functions: {}});
183
+ var init_statement = node[2];
184
+ var function_defs = node[3];
185
+
186
+ var old_self = SELF;
187
+ SELF = mixin;
188
+
189
+ for (var i = 0, l = function_defs.length; i < l; ++i)
190
+ {
191
+ evaluate(function_defs[i]);
192
+ }
193
+
194
+ SELF = old_self;
195
+
196
+ mixin.init = function (obj)
197
+ {
198
+ var old_self = SELF;
199
+ SELF = obj;
200
+
201
+ evaluate(init_statement);
202
+
203
+ SELF = old_self;
204
+ }
205
+
206
+ return NULL;
207
+
208
+ case newline:
209
+ FILE = SYMBOLS[node[1]];
210
+ LINE = node[2]
211
+
212
+ return evaluate(node[3]);
213
+
214
+ case not:
215
+ var value = evaluate(node[1]);
216
+ return (value === NULL || value === FALSE) ? TRUE : FALSE;
217
+
218
+ case null:
219
+ return NULL;
220
+
221
+ case number:
222
+ return new_number(node[1]);
223
+
224
+ case object:
225
+ var kv_pairs = node[1];
226
+ var mixins = node[2];
227
+ var mixin_names = [];
228
+ var fields = {};
229
+ var keys = [];
230
+
231
+ for (var kv, key, i = 0, l = kv_pairs.length; i < l; ++i)
232
+ {
233
+ kv = kv_pairs[i];
234
+ key = SYMBOLS[kv[0]];
235
+ keys.push(key);
236
+ fields[key] = evaluate(kv[1]);
237
+ }
238
+
239
+ for (var i = 0, l = mixins.length; i < l; ++i)
240
+ {
241
+ mixin_names[i] = SYMBOLS[mixins[i]];
242
+ }
243
+
244
+ var element_type = HTML_TYPES[mixin_names[0]];
245
+
246
+ if (element_type)
247
+ {
248
+ mixin_names.shift();
249
+ var obj = new_element(element_type, fields, keys);
250
+ }
251
+ else if (mixin_names[0] === 'Text')
252
+ {
253
+ mixin_names.shift();
254
+ var obj = new_text(fields, keys);
255
+ }
256
+ else
257
+ {
258
+ var obj = new_object(fields, keys);
259
+ }
260
+
261
+ for (var m, i = 0, l = mixin_names.length; i < l; ++i)
262
+ {
263
+ if (m = MIXINS[mixin_names[i]])
264
+ {
265
+ copy_functions(obj, m);
266
+
267
+ if (init_function = m.init)
268
+ {
269
+ init_function(obj);
270
+ }
271
+ }
272
+ else
273
+ {
274
+ warn("Ignoring unknown mixin `" + mixin_names[i] + "'");
275
+ }
276
+ }
277
+
278
+ return obj;
279
+
280
+ case op:
281
+ var name = SYMBOLS[node[1]];
282
+ var left = evaluate(node[2]);
283
+ var right = evaluate(node[3]);
284
+
285
+ return call_function(left, name, [right]);
286
+
287
+ case or:
288
+ var left = evaluate(node[1]);
289
+ return (left !== NULL && left !== FALSE) ? left : evaluate(node[2]);
290
+
291
+ case return:
292
+ RETURN_VALUE = evaluate(node[1]);
293
+ return NULL;
294
+
295
+ case self:
296
+ return SELF;
297
+
298
+ case set:
299
+ var lhs_node = node[1];
300
+ var value = evaluate(node[2]);
301
+
302
+ switch (lhs_node[0])
303
+ {
304
+ case access_brackets:
305
+ var obj = evaluate(lhs_node[1]);
306
+ var key = evaluate(lhs_node[2]);
307
+
308
+ return call_function(obj, 'brackets_eq', [key, value]);
309
+
310
+ case access_colon:
311
+ var obj = evaluate(lhs_node[1]);
312
+ var name = SYMBOLS[lhs_node[2]];
313
+
314
+ if (!obj.data[name])
315
+ {
316
+ obj.keys.push(name);
317
+ }
318
+
319
+ return obj.data[name] = value;
320
+
321
+ case access_hash:
322
+ var obj = evaluate(lhs_node[1]);
323
+ var name = SYMBOLS[lhs_node[2]];
324
+
325
+ if (value.object_type === FUNCTION_TYPE)
326
+ {
327
+ var func = value;
328
+ func.bound = obj;
329
+ }
330
+ else
331
+ {
332
+ warn("Assigning a non-function object as a function");
333
+ var func = new_function(function (self, args) { return value; }, obj);
334
+ func.value.parameters = [];
335
+ }
336
+
337
+ obj.functions[name] = func.value;
338
+
339
+ return func;
340
+
341
+ case variable:
342
+ return VARIABLES[SYMBOLS[lhs_node[1]]] = value;
343
+ }
344
+
345
+ case statement:
346
+ var statement = node[1];
347
+ var next_statement = node[2];
348
+
349
+ var result = evaluate(statement);
350
+
351
+ return (next_statement) ? evaluate(next_statement) : result;
352
+
353
+ case string:
354
+ return new_string(SYMBOLS[node[1]]);
355
+
356
+ case switch:
357
+ var condition = evaluate(node[1]);
358
+ var cases = node[2];
359
+ var else_case = node[3];
360
+
361
+ for (var c, test, i = 0, l = cases.length; i < l; ++i)
362
+ {
363
+ c = cases[i];
364
+ test = call_function(condition, 'eq', [evaluate(c[0])]);
365
+
366
+ if (test !== FALSE && test !== NULL)
367
+ {
368
+ return evaluate(c[1]);
369
+ }
370
+ }
371
+
372
+ return (else_case) ? evaluate(else_case) : NULL;
373
+
374
+ case true:
375
+ return TRUE;
376
+
377
+ case variable:
378
+ var name = SYMBOLS[node[1]];
379
+ var value = VARIABLES[name];
380
+
381
+ if (!value)
382
+ {
383
+ warn("Ignoring unknown variable `" + name + "'");
384
+ return NULL;
385
+ }
386
+
387
+ return value;
388
+
389
+ case while:
390
+ var test = function (value)
391
+ {
392
+ return (value !== FALSE) && (value !== NULL);
393
+ };
394
+
395
+ while (test(evaluate(node[1])))
396
+ {
397
+ ITERATING += 1;
398
+ evaluate(node[2]);
399
+ ITERATING -= 1;
400
+
401
+ if (BREAK_VALUE)
402
+ {
403
+ var result = BREAK_VALUE;
404
+
405
+ BREAK_VALUE = null;
406
+ return result;
407
+ }
408
+ else if (RETURN_VALUE)
409
+ {
410
+ return RETURN_VALUE;
411
+ }
412
+ }
413
+
414
+ return NULL;
415
+
416
+ default:
417
+ bug("Unable to evaluate a node:\t" + node[0] || node);
418
+ }
419
+ }
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Copyright © 2011 Jesse Sielaff
3
+ */
4
+
5
+ var FALSE =
6
+ {
7
+ object_type: FALSE_TYPE,
8
+ functions: {},
9
+ data: {},
10
+ keys: [],
11
+ unknown: Object_bad_key,
12
+ value: false
13
+ }
14
+
15
+ copy_functions(FALSE, OBJECT);
16
+
17
+ function False_stringify (self, args)
18
+ {
19
+ return new_string('false');
20
+ }
21
+
22
+ add_function(FALSE, 'inspect', False_stringify, []);
23
+ add_function(FALSE, 'stringify', False_stringify, []);
@@ -0,0 +1,95 @@
1
+ /**
2
+ * Copyright © 2011 Jesse Sielaff
3
+ */
4
+
5
+ var FUNCTION =
6
+ {
7
+ functions: {}
8
+ };
9
+
10
+ copy_functions(FUNCTION, OBJECT);
11
+
12
+ function new_function (body, bound)
13
+ {
14
+ var func =
15
+ {
16
+ object_type: FUNCTION_TYPE,
17
+ functions: {},
18
+ data: {},
19
+ keys: [],
20
+ unknown: Object_bad_key,
21
+ value: body,
22
+ bound: bound
23
+ };
24
+
25
+ copy_functions(func, FUNCTION);
26
+
27
+ return func;
28
+ }
29
+
30
+ function Function_bind (self, args)
31
+ {
32
+ if (xself(self, FUNCTION_TYPE, "#bind"))
33
+ {
34
+ return NULL;
35
+ }
36
+
37
+ var obj = args[0];
38
+
39
+ if (xarg(obj, null, "Function#bind", "an"))
40
+ {
41
+ return self;
42
+ }
43
+
44
+ self.bound = obj;
45
+
46
+ return self;
47
+ }
48
+
49
+ function Function_bound (self, args)
50
+ {
51
+ if (xself(self, FUNCTION_TYPE, "#bound"))
52
+ {
53
+ return NULL;
54
+ }
55
+
56
+ return self.bound;
57
+ }
58
+
59
+ function Function_parameters (self, args)
60
+ {
61
+ if (xself(self, FUNCTION_TYPE, "#parameters"))
62
+ {
63
+ return NULL;
64
+ }
65
+
66
+ var parameters = self.body.parameters;
67
+ var names = [];
68
+
69
+ for (var i = 0, l = parameters.length; i < l; ++i)
70
+ {
71
+ names[i] = new_string(parameters[i]);
72
+ }
73
+
74
+ return new_array(names);
75
+ }
76
+
77
+ function Function_stringify (self, args)
78
+ {
79
+ if (xself(self, FUNCTION_TYPE, "#stringify"))
80
+ {
81
+ return NULL;
82
+ }
83
+
84
+ var body = self.value;
85
+ var parameters = body.parameters;
86
+ var string = (parameters.length == 0) ? '# {...}' : '|' + parameters + '| {...}';
87
+
88
+ return new_string(string);
89
+ }
90
+
91
+ add_function(FUNCTION, 'bind', Function_bind, ['object']);
92
+ add_function(FUNCTION, 'bound', Function_bound, []);
93
+ add_function(FUNCTION, 'inspect', Function_stringify, []);
94
+ add_function(FUNCTION, 'parameters', Function_parameters, []);
95
+ add_function(FUNCTION, 'stringify', Function_stringify, []);
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Copyright © 2011 Jesse Sielaff
3
+ */
4
+
5
+ var NULL =
6
+ {
7
+ object_type: NULL_TYPE,
8
+ functions: {},
9
+ data: {},
10
+ keys: [],
11
+ unknown: Object_bad_key,
12
+ value: null
13
+ }
14
+
15
+ copy_functions(NULL, OBJECT);
16
+
17
+ function Null_stringify (self, args)
18
+ {
19
+ return new_string('null');
20
+ }
21
+
22
+ add_function(NULL, 'inspect', Null_stringify, []);
23
+ add_function(NULL, 'stringify', Null_stringify, []);