mix-language 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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, []);