opal 0.0.1
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.
- data/.gitignore +2 -0
- data/Rakefile +52 -0
- data/VERSION +1 -0
- data/docs/jarv.rdoc +27 -0
- data/lib/opal.rb +29 -0
- data/runtime/array.js +153 -0
- data/runtime/class.js +469 -0
- data/runtime/compar.js +73 -0
- data/runtime/dir.js +115 -0
- data/runtime/enum.js +74 -0
- data/runtime/file.js +165 -0
- data/runtime/gem.js +241 -0
- data/runtime/hash.js +181 -0
- data/runtime/init.js +59 -0
- data/runtime/load.js +251 -0
- data/runtime/module.js +98 -0
- data/runtime/number.js +148 -0
- data/runtime/object.js +522 -0
- data/runtime/opal.js +200 -0
- data/runtime/parse.js +2218 -0
- data/runtime/range.js +56 -0
- data/runtime/re.js +91 -0
- data/runtime/string.js +199 -0
- data/runtime/variable.js +184 -0
- data/runtime/vm.js +1150 -0
- data/runtime/yaml.js +33 -0
- data/tasks/build.rb +16 -0
- metadata +90 -0
data/runtime/vm.js
ADDED
@@ -0,0 +1,1150 @@
|
|
1
|
+
/*
|
2
|
+
* vm.js
|
3
|
+
* opal
|
4
|
+
*
|
5
|
+
* Created by Adam Beynon.
|
6
|
+
* Copyright 2010 Adam Beynon.
|
7
|
+
*
|
8
|
+
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
9
|
+
* of this software and associated documentation files (the "Software"), to deal
|
10
|
+
* in the Software without restriction, including without limitation the rights
|
11
|
+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
12
|
+
* copies of the Software, and to permit persons to whom the Software is
|
13
|
+
* furnished to do so, subject to the following conditions:
|
14
|
+
*
|
15
|
+
* The above copyright notice and this permission notice shall be included in
|
16
|
+
* all copies or substantial portions of the Software.
|
17
|
+
*
|
18
|
+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
19
|
+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
20
|
+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
21
|
+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
22
|
+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
23
|
+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
24
|
+
* THE SOFTWARE.
|
25
|
+
*/
|
26
|
+
|
27
|
+
|
28
|
+
/**
|
29
|
+
Jarv - (Javascript/Just) another ruby vm
|
30
|
+
Influenced by yarv, but opcodes are (slightly) different.
|
31
|
+
Main difference are the stack frames and stacks themselves.
|
32
|
+
*/
|
33
|
+
|
34
|
+
// temp so we dont have to change code later;
|
35
|
+
var nil = null;
|
36
|
+
|
37
|
+
/**
|
38
|
+
Instruction table (opcodes)
|
39
|
+
*/
|
40
|
+
var iNOP = 0, iGETLOCAL = 1,
|
41
|
+
iSETLOCAL = 2, iGETSPECIAL = 3,
|
42
|
+
iSETSPECIAL = 4, iGETDYNAMIC = 5,
|
43
|
+
iSETDYNAMIC = 6, iGETINSTANCEVARIABLE = 7,
|
44
|
+
iSETINSTANCEVARIABLE = 8, iGETCLASSVARIABLE = 9,
|
45
|
+
iSETCLASSVARIABLE = 10, iGETCONSTANT = 11,
|
46
|
+
iSETCONSTANT = 12, iGETGLOBAL = 13,
|
47
|
+
iSETGLOBAL = 14, iPUTNIL = 15,
|
48
|
+
iPUTSELF = 16, iPUTOBJECT = 17,
|
49
|
+
iPUTSTRING = 18, iCONCATSTRINGS = 19,
|
50
|
+
iTOSTRING = 20, iTOREGEXP = 21,
|
51
|
+
iNEWARRAY = 22, iDUPARRAY = 23,
|
52
|
+
iEXPANDARRAY = 24, iCONCATARRAY = 25,
|
53
|
+
iSPLATARRAY = 26, iCHECKINCLUDEARRAY = 27,
|
54
|
+
iNEWHASH = 28, iNEWRANGE = 29,
|
55
|
+
iPOP = 30, iDUP = 31,
|
56
|
+
iDUPN = 32, iSWAP = 33,
|
57
|
+
iREPUT = 34, iTOPN = 35,
|
58
|
+
iSETN = 36, iADJUSTSTACK = 37,
|
59
|
+
iDEFINEMETHOD = 38, iALIAS = 39,
|
60
|
+
iUNDEF = 40, iDEFINED = 41,
|
61
|
+
iPOSTEXE = 42, iTRACE = 43,
|
62
|
+
iDEFINECLASS = 44, iSEND = 45,
|
63
|
+
iINVOKESUPER = 46, iINVOKEBLOCK = 47,
|
64
|
+
iLEAVE = 48, iFINISH = 49,
|
65
|
+
iTHROW = 50, iJUMP = 51,
|
66
|
+
iBRANCHIF = 52, iBRANCHUNLESS = 53,
|
67
|
+
iGETINLINECACHE = 54, iONCEINLINECACHE = 55,
|
68
|
+
iSETINLINECACHE = 56, iOPT_CASE_DISPATCH = 57,
|
69
|
+
iOPT_CHECKENV = 58, iOPT_PLUS = 59,
|
70
|
+
iOPT_MINUS = 60, iOPT_MULT = 61,
|
71
|
+
iOPT_DIV = 62, iOPT_MOD = 63,
|
72
|
+
iOPT_EQ = 64, iOPT_NEQ = 65,
|
73
|
+
iOPT_LT = 66, iOPT_LE = 67,
|
74
|
+
iOPT_GT = 68, iOPT_GE = 69,
|
75
|
+
iOPT_LTLT = 70, iOPT_AREF = 71,
|
76
|
+
iOPT_ASET = 72, iOPT_LENGTH = 73,
|
77
|
+
iOPT_SUCC = 74, iOPT_NOT = 75,
|
78
|
+
iOPT_REGEXPMATCH1 = 76, iOPT_REGEXPMATCH2 = 77,
|
79
|
+
iOPT_CALL_C_FUNCTION = 78, iBITBLT = 79,
|
80
|
+
iANSWER = 80,
|
81
|
+
// JARV additions to YARV
|
82
|
+
iPUTSYMBOL = 81;
|
83
|
+
|
84
|
+
/**
|
85
|
+
iseq types
|
86
|
+
*/
|
87
|
+
var ISEQ_TYPE_TOP = 1,
|
88
|
+
ISEQ_TYPE_METHOD = 2,
|
89
|
+
ISEQ_TYPE_BLOCK = 3,
|
90
|
+
ISEQ_TYPE_CLASS = 4,
|
91
|
+
ISEQ_TYPE_RESCUE = 5,
|
92
|
+
ISEQ_TYPE_ENSURE = 6,
|
93
|
+
ISEQ_TYPE_EVAL = 7,
|
94
|
+
ISEQ_TYPE_MAIN = 8;
|
95
|
+
|
96
|
+
/**
|
97
|
+
DEFINECLASS types
|
98
|
+
*/
|
99
|
+
var DEFINECLASS_CLASS = 0,
|
100
|
+
DEFINECLASS_SINGLETON = 1,
|
101
|
+
DEFINECLASS_MODULE = 2;
|
102
|
+
|
103
|
+
/**
|
104
|
+
== Depreceated?
|
105
|
+
|
106
|
+
|
107
|
+
call args
|
108
|
+
*/
|
109
|
+
var VM_CALL_ARGS_SPLAT_BIT = 2,
|
110
|
+
VM_CALL_ARGS_BLOCKARG_BIT = 4,
|
111
|
+
VM_CALL_FCALL_BIT = 8,
|
112
|
+
VM_CALL_VCALL_BIT = 16,
|
113
|
+
VM_CALL_TAILCALL_BIT = 32,
|
114
|
+
VM_CALL_TAILRECURSION_BIT = 64,
|
115
|
+
VM_CALL_SUPER_BIT = 128,
|
116
|
+
VM_CALL_SEND_BIT = 256;
|
117
|
+
|
118
|
+
|
119
|
+
/**
|
120
|
+
Handles some functionality found in thread until thread is added to main repo.
|
121
|
+
At the moment, using threads makes to much of a performance impact, so they
|
122
|
+
will be added if/when performance can be improved. (Need to determine how much
|
123
|
+
performance impact is justified.). See 'threads' branch on vienna.adambeynon.com
|
124
|
+
for threads code. Not currently in github branch (or branch for gem building.)
|
125
|
+
*/
|
126
|
+
function rb_vm() {
|
127
|
+
this.self = null;
|
128
|
+
|
129
|
+
this.running = 0;
|
130
|
+
|
131
|
+
// current frame pointer - rb_control_frame
|
132
|
+
this.cfp = null;
|
133
|
+
// control frame stack
|
134
|
+
this.cfs = []
|
135
|
+
|
136
|
+
// for iterations
|
137
|
+
this.passed_block = null;
|
138
|
+
|
139
|
+
this.top_self = null;
|
140
|
+
this.top_wrapper = null;
|
141
|
+
|
142
|
+
// eval env
|
143
|
+
this.base_block = null;
|
144
|
+
|
145
|
+
// search style.. search for local .rb or .vm files
|
146
|
+
this.search_style = ".rb";
|
147
|
+
}
|
148
|
+
|
149
|
+
function rb_control_frame() {
|
150
|
+
// stack. every control frame manages its own stack
|
151
|
+
this.stack = []
|
152
|
+
// stack pointer
|
153
|
+
this.sp = 0;
|
154
|
+
// program counter
|
155
|
+
this.pc = 0;
|
156
|
+
// prev env
|
157
|
+
this.prev = null;
|
158
|
+
// instruction sequence (array we got from json, for now)
|
159
|
+
this.iseq = null;
|
160
|
+
// local self
|
161
|
+
this.self = null;
|
162
|
+
// local frame pointer
|
163
|
+
this.lfp = null;
|
164
|
+
// dynamic frame pointer
|
165
|
+
this.dfp = null;
|
166
|
+
// block_t ptr
|
167
|
+
this.block_t = null;
|
168
|
+
// proc - always 0/false for methods..
|
169
|
+
this.proc = 0;
|
170
|
+
|
171
|
+
// locals
|
172
|
+
this.locals = null;
|
173
|
+
|
174
|
+
// this.insn_info_table = {
|
175
|
+
// position: 0, line_no: 0, sp: 0
|
176
|
+
// };
|
177
|
+
this.line_no = 0;
|
178
|
+
|
179
|
+
//
|
180
|
+
this.method_id = null;
|
181
|
+
this.method_class = null;
|
182
|
+
};
|
183
|
+
|
184
|
+
function rb_block_t() {
|
185
|
+
this.self = nil;
|
186
|
+
this.lfp = nil;
|
187
|
+
this.dfp = nil;
|
188
|
+
this.iseq = nil;
|
189
|
+
this.proc = nil;
|
190
|
+
};
|
191
|
+
|
192
|
+
// currently the only vm. thread support is currently disabled
|
193
|
+
var rb_top_vm = null;
|
194
|
+
|
195
|
+
|
196
|
+
|
197
|
+
// Seq is an array, [:misc, :name etc....]
|
198
|
+
function rb_iseq_eval(iseq) {
|
199
|
+
var val, vm = rb_top_vm;
|
200
|
+
vm_set_top_stack(vm, iseq);
|
201
|
+
val = vm_run_mode_running(rb_top_vm);
|
202
|
+
// must pop frame when we are done with it.
|
203
|
+
vm_pop_frame(vm);
|
204
|
+
return val;
|
205
|
+
}
|
206
|
+
|
207
|
+
function vm_set_top_stack(vm, iseq) {
|
208
|
+
// console.log(iseq);
|
209
|
+
if (iseq[4] != ISEQ_TYPE_TOP) {
|
210
|
+
// rb_raise(rb_eTypeError, "Not a toplevel InstructionSequence");
|
211
|
+
throw 'rb_eTypeError: ' + 'Not a top level InstructionSequence'
|
212
|
+
}
|
213
|
+
|
214
|
+
|
215
|
+
// vm_push_frame(vm, iseq, ISEQ_TYPE_TOP, vm.top_self, 0, 0, -1, 0, iseq[0][1])
|
216
|
+
vm_push_frame(vm, iseq, vm.top_self);
|
217
|
+
}
|
218
|
+
|
219
|
+
function vm_run_mode_sleep(vm) {
|
220
|
+
vm.running = 0;
|
221
|
+
}
|
222
|
+
|
223
|
+
function vm_run_mode_running(vm) {
|
224
|
+
vm.running = 1;
|
225
|
+
return vm_exec(vm);
|
226
|
+
}
|
227
|
+
|
228
|
+
/**
|
229
|
+
Execute iseq, for current frame pointer, which will be a function.
|
230
|
+
*/
|
231
|
+
function vm_exec(vm) {
|
232
|
+
var jumps = vm.cfp.iseq[8], iseq = vm.cfp.iseq[9], op, sf = vm.cfp;
|
233
|
+
// console.log("executing iseq: " + iseq);
|
234
|
+
for (; sf.pc < iseq.length; sf.pc++) {
|
235
|
+
op = iseq[sf.pc];
|
236
|
+
// console.log(sf.pc);
|
237
|
+
|
238
|
+
if (typeof op === 'number') {
|
239
|
+
// console.log("at line number " + op);
|
240
|
+
continue;
|
241
|
+
}
|
242
|
+
|
243
|
+
switch (op[0]) {
|
244
|
+
/**
|
245
|
+
putobject
|
246
|
+
|
247
|
+
put an object onto the stack
|
248
|
+
|
249
|
+
== operands
|
250
|
+
|
251
|
+
VALUE val
|
252
|
+
|
253
|
+
== stack
|
254
|
+
|
255
|
+
before: after:
|
256
|
+
|
257
|
+
----------
|
258
|
+
========== => val
|
259
|
+
----------
|
260
|
+
*/
|
261
|
+
case iPUTOBJECT:
|
262
|
+
// console.log("putobject" + sf.sp);
|
263
|
+
sf.stack[sf.sp++] = op[1];
|
264
|
+
break;
|
265
|
+
|
266
|
+
/**
|
267
|
+
putstring
|
268
|
+
*/
|
269
|
+
case iPUTSTRING:
|
270
|
+
sf.stack[sf.sp++] = op[1];
|
271
|
+
break;
|
272
|
+
|
273
|
+
/**
|
274
|
+
putsymbol
|
275
|
+
|
276
|
+
== operands
|
277
|
+
|
278
|
+
ptr - string value for symbol
|
279
|
+
|
280
|
+
== stack
|
281
|
+
|
282
|
+
before: after:
|
283
|
+
|
284
|
+
----------
|
285
|
+
========== => val
|
286
|
+
----------
|
287
|
+
*/
|
288
|
+
case iPUTSYMBOL:
|
289
|
+
sf.stack[sf.sp++] = ID2SYM(op[1]);
|
290
|
+
break;
|
291
|
+
|
292
|
+
/**
|
293
|
+
getlocal
|
294
|
+
|
295
|
+
get local from locals array, and put onto stack
|
296
|
+
|
297
|
+
== operands
|
298
|
+
|
299
|
+
idx
|
300
|
+
|
301
|
+
== stack
|
302
|
+
|
303
|
+
before: after:
|
304
|
+
|
305
|
+
----------
|
306
|
+
========== => val
|
307
|
+
----------
|
308
|
+
*/
|
309
|
+
case iGETLOCAL:
|
310
|
+
// console.log("getlocal" + sf.sp);
|
311
|
+
sf.stack[sf.sp++] = sf.locals[op[1]];
|
312
|
+
break;
|
313
|
+
|
314
|
+
/**
|
315
|
+
setlocal
|
316
|
+
|
317
|
+
== operands
|
318
|
+
|
319
|
+
idx - index of local. Args, then locals.
|
320
|
+
|
321
|
+
== stack
|
322
|
+
|
323
|
+
before: after:
|
324
|
+
|
325
|
+
----------
|
326
|
+
val => ==========
|
327
|
+
----------
|
328
|
+
|
329
|
+
== Discussion
|
330
|
+
|
331
|
+
Sets local var value. Note, not local ivar.
|
332
|
+
*/
|
333
|
+
case iSETLOCAL:
|
334
|
+
// console.log("setlocal" + sf.sp);
|
335
|
+
sf.locals[op[1]] = sf.stack[--sf.sp];
|
336
|
+
// console.log("after: " + sf.sp);
|
337
|
+
break;
|
338
|
+
|
339
|
+
/**
|
340
|
+
getdynamic
|
341
|
+
|
342
|
+
== operands
|
343
|
+
|
344
|
+
idx - idx in locals
|
345
|
+
level - level to search, 0 = current frame
|
346
|
+
|
347
|
+
*/
|
348
|
+
case iGETDYNAMIC:
|
349
|
+
// cheat, only works for level [0] at the moment, i.e. local frame and use
|
350
|
+
// the first index..basically, just so we can get things working.
|
351
|
+
sf.stack[sf.sp++] = sf.locals[0];
|
352
|
+
// throw ""
|
353
|
+
break;
|
354
|
+
|
355
|
+
/**
|
356
|
+
setinstancevariable
|
357
|
+
|
358
|
+
== operands
|
359
|
+
|
360
|
+
id
|
361
|
+
*/
|
362
|
+
case iSETINSTANCEVARIABLE:
|
363
|
+
rb_ivar_set(sf.self, op[1], sf.stack[--sf.sp]);
|
364
|
+
break;
|
365
|
+
|
366
|
+
/**
|
367
|
+
getinstancevariable
|
368
|
+
|
369
|
+
== operands
|
370
|
+
|
371
|
+
id
|
372
|
+
|
373
|
+
== stack
|
374
|
+
|
375
|
+
val put onto stack
|
376
|
+
*/
|
377
|
+
case iGETINSTANCEVARIABLE:
|
378
|
+
sf.stack[sf.sp++] = rb_ivar_get(sf.self, op[1]);
|
379
|
+
break;
|
380
|
+
|
381
|
+
/**
|
382
|
+
getconstant
|
383
|
+
|
384
|
+
== operands
|
385
|
+
|
386
|
+
id - constant id
|
387
|
+
|
388
|
+
== stack
|
389
|
+
|
390
|
+
before: after:
|
391
|
+
|
392
|
+
---------- ----------
|
393
|
+
klass => val
|
394
|
+
---------- ----------
|
395
|
+
|
396
|
+
== discussion
|
397
|
+
|
398
|
+
klass is the base klass to look on.
|
399
|
+
val is the constant itself
|
400
|
+
*/
|
401
|
+
case iGETCONSTANT:
|
402
|
+
var const_klass = sf.stack[--sf.sp], const_id = op[1];
|
403
|
+
|
404
|
+
if (const_klass == nil) {
|
405
|
+
if (sf.self.flags & T_OBJECT) {
|
406
|
+
const_klass = rb_class_real(sf.self.klass);
|
407
|
+
}
|
408
|
+
else {
|
409
|
+
const_klass = sf.self;
|
410
|
+
}
|
411
|
+
}
|
412
|
+
|
413
|
+
sf.stack[sf.sp++] = rb_const_get(const_klass, const_id);
|
414
|
+
break;
|
415
|
+
|
416
|
+
/**
|
417
|
+
setconstant
|
418
|
+
|
419
|
+
== operands
|
420
|
+
|
421
|
+
id - constant id
|
422
|
+
|
423
|
+
== stack
|
424
|
+
|
425
|
+
before: after:
|
426
|
+
|
427
|
+
----------
|
428
|
+
klass
|
429
|
+
---------- => ==========
|
430
|
+
val
|
431
|
+
----------
|
432
|
+
*/
|
433
|
+
case iSETCONSTANT:
|
434
|
+
var cons_klass = sf.stack[--sf.sp];
|
435
|
+
var cons_val = sf.stack[--sf.sp];
|
436
|
+
var cons_id = op[1];
|
437
|
+
|
438
|
+
|
439
|
+
if (cons_klass === nil) {
|
440
|
+
if (sf.self.flags & T_OBJECT) {
|
441
|
+
cons_klass = rb_class_real(sf.self.klass);
|
442
|
+
}
|
443
|
+
else {
|
444
|
+
cons_klass = sf.self;
|
445
|
+
}
|
446
|
+
}
|
447
|
+
|
448
|
+
rb_const_set(cons_klass, cons_id, cons_val);
|
449
|
+
break;
|
450
|
+
|
451
|
+
/**
|
452
|
+
putnil
|
453
|
+
|
454
|
+
== operands
|
455
|
+
|
456
|
+
none
|
457
|
+
|
458
|
+
== stack
|
459
|
+
|
460
|
+
before: after:
|
461
|
+
|
462
|
+
----------
|
463
|
+
========== => nil
|
464
|
+
----------
|
465
|
+
*/
|
466
|
+
case iPUTNIL:
|
467
|
+
// console.log("nil" + sf.sp);
|
468
|
+
sf.stack[sf.sp++] = nil;
|
469
|
+
break;
|
470
|
+
|
471
|
+
/**
|
472
|
+
putnil
|
473
|
+
|
474
|
+
== operands
|
475
|
+
|
476
|
+
none
|
477
|
+
|
478
|
+
== stack
|
479
|
+
|
480
|
+
before: after:
|
481
|
+
|
482
|
+
----------
|
483
|
+
========== => self
|
484
|
+
----------
|
485
|
+
*/
|
486
|
+
case iPUTSELF:
|
487
|
+
sf.stack[sf.sp++] = sf.self;
|
488
|
+
break;
|
489
|
+
|
490
|
+
/**
|
491
|
+
pop
|
492
|
+
|
493
|
+
== operands
|
494
|
+
|
495
|
+
none
|
496
|
+
|
497
|
+
== stack
|
498
|
+
|
499
|
+
before: after:
|
500
|
+
|
501
|
+
----------
|
502
|
+
val => ==========
|
503
|
+
----------
|
504
|
+
*/
|
505
|
+
case iPOP:
|
506
|
+
// console.log("pop" + sf.sp);
|
507
|
+
sf.sp--;
|
508
|
+
break;
|
509
|
+
|
510
|
+
/**
|
511
|
+
branchunless
|
512
|
+
|
513
|
+
== operands
|
514
|
+
|
515
|
+
lbl - jump label to jump to if val is false or nil (RTEST)
|
516
|
+
|
517
|
+
== stack
|
518
|
+
|
519
|
+
before: after:
|
520
|
+
|
521
|
+
----------
|
522
|
+
val => ==========
|
523
|
+
----------
|
524
|
+
*/
|
525
|
+
case iBRANCHUNLESS:
|
526
|
+
var jmp_label = op[1], jmp_test = sf.stack[--sf.sp];
|
527
|
+
if (jmp_test === nil || jmp_test === false) {
|
528
|
+
// actually do jump
|
529
|
+
// console.log(jumps[op[1]] + " ..branch unless jump: " + jmp_test);
|
530
|
+
// the loop does pc++, so we go to one less than what we actually need
|
531
|
+
sf.pc = jumps[op[1]] - 1;
|
532
|
+
}
|
533
|
+
else {
|
534
|
+
// console.log("branch unless do not jump: " + jmp_test);
|
535
|
+
}
|
536
|
+
|
537
|
+
// if RTEST was okay, do nothing..
|
538
|
+
break;
|
539
|
+
|
540
|
+
/**
|
541
|
+
jump
|
542
|
+
|
543
|
+
== operands
|
544
|
+
|
545
|
+
==stack
|
546
|
+
|
547
|
+
*/
|
548
|
+
case iJUMP:
|
549
|
+
// pc ++ in loop makes us go to actual - 1
|
550
|
+
sf.pc = jumps[op[1]] - 1;
|
551
|
+
break;
|
552
|
+
|
553
|
+
/**
|
554
|
+
leave
|
555
|
+
|
556
|
+
== discussion
|
557
|
+
|
558
|
+
on iLEAVE, return the value on top of the stack
|
559
|
+
*/
|
560
|
+
case iLEAVE:
|
561
|
+
// console.log("leaving with");
|
562
|
+
// console.log(sf.stack[sf.sp - 1]);
|
563
|
+
return sf.stack[--sf.sp];
|
564
|
+
break;
|
565
|
+
|
566
|
+
/**
|
567
|
+
newhash
|
568
|
+
|
569
|
+
== operands
|
570
|
+
|
571
|
+
num - number of hash arguments to take from stack
|
572
|
+
|
573
|
+
== stack
|
574
|
+
|
575
|
+
before: after:
|
576
|
+
|
577
|
+
---------- ----------
|
578
|
+
n args.. => hash
|
579
|
+
---------- ----------
|
580
|
+
*/
|
581
|
+
case iNEWHASH:
|
582
|
+
var i, k, v, res = rb_hash_new(), num = op[1];
|
583
|
+
var ary = sf.stack.slice(sf.sp - num, sf.sp);
|
584
|
+
sf.sp -= num;
|
585
|
+
|
586
|
+
for (i = 0; i < num; i += 2) {
|
587
|
+
rb_hash_aset(res, ary[i], ary[i + 1])
|
588
|
+
}
|
589
|
+
sf.stack[sf.sp++] = res;
|
590
|
+
break;
|
591
|
+
|
592
|
+
/**
|
593
|
+
definemethod
|
594
|
+
|
595
|
+
== operands
|
596
|
+
|
597
|
+
method_id - method id
|
598
|
+
method_iseq - body of method
|
599
|
+
is_singleton - whether the method is a singleton or not
|
600
|
+
|
601
|
+
== stack
|
602
|
+
|
603
|
+
before: after:
|
604
|
+
|
605
|
+
----------
|
606
|
+
val => ==========
|
607
|
+
----------
|
608
|
+
*/
|
609
|
+
case iDEFINEMETHOD:
|
610
|
+
var def_obj = sf.stack[--sf.sp];
|
611
|
+
var method_id = op[1], method_iseq = op[2], is_singleton = op[3];
|
612
|
+
|
613
|
+
if (def_obj === nil) {
|
614
|
+
if (sf.self.flags & T_OBJECT)
|
615
|
+
def_obj = rb_class_real(sf.self.klass);
|
616
|
+
else
|
617
|
+
def_obj = sf.self;
|
618
|
+
}
|
619
|
+
|
620
|
+
if (is_singleton) {
|
621
|
+
rb_define_method(rb_singleton_class(def_obj), method_id, method_iseq, 0);
|
622
|
+
}
|
623
|
+
else {
|
624
|
+
rb_define_method(def_obj, method_id, method_iseq, 0);
|
625
|
+
}
|
626
|
+
|
627
|
+
// console.log(def_obj);
|
628
|
+
// throw "dmethod"
|
629
|
+
break;
|
630
|
+
|
631
|
+
/**
|
632
|
+
defineclass
|
633
|
+
|
634
|
+
== operands
|
635
|
+
|
636
|
+
class_id - class name
|
637
|
+
class_iseq - class body/sequences
|
638
|
+
define_type - 0, 1 or 2.
|
639
|
+
|
640
|
+
== stack
|
641
|
+
|
642
|
+
before: after:
|
643
|
+
|
644
|
+
----------
|
645
|
+
super ----------
|
646
|
+
---------- => val
|
647
|
+
base ----------
|
648
|
+
----------
|
649
|
+
|
650
|
+
== discussion
|
651
|
+
|
652
|
+
val, the return value, is the class object itself.
|
653
|
+
*/
|
654
|
+
case iDEFINECLASS:
|
655
|
+
var klass, class_id = op[1], class_iseq = op[2], define_type = op[3];
|
656
|
+
|
657
|
+
var class_super = sf.stack[--sf.sp];
|
658
|
+
var class_base = sf.stack[--sf.sp];
|
659
|
+
|
660
|
+
switch (define_type) {
|
661
|
+
case DEFINECLASS_CLASS:
|
662
|
+
|
663
|
+
if (class_super == nil) {
|
664
|
+
class_super = rb_cObject;
|
665
|
+
}
|
666
|
+
|
667
|
+
if (class_base == nil) {
|
668
|
+
// this isn't right.
|
669
|
+
class_base = sf.self;
|
670
|
+
// if class_base is an object, then we need to get its klass.
|
671
|
+
if (class_base.flags & T_OBJECT) {
|
672
|
+
class_base = rb_class_real(class_base.klass);
|
673
|
+
}
|
674
|
+
}
|
675
|
+
|
676
|
+
// find klass, if it already exists
|
677
|
+
if (rb_const_defined_at(class_base, class_id)) {
|
678
|
+
klass = rb_const_get_at(class_base, class_id);
|
679
|
+
}
|
680
|
+
else {
|
681
|
+
// define new class
|
682
|
+
klass = rb_define_class_id(class_id, class_super);
|
683
|
+
rb_name_class(klass, class_id);
|
684
|
+
// rb_class_set_path(klass, class_base, id)
|
685
|
+
rb_const_set(class_base, class_id, klass);
|
686
|
+
klass.parent = class_base;
|
687
|
+
// rb_class_inherited(class_super, klass);
|
688
|
+
}
|
689
|
+
break;
|
690
|
+
|
691
|
+
case DEFINECLASS_SINGLETON:
|
692
|
+
// singleton reference class << self; end
|
693
|
+
klass = rb_singleton_class(class_base);
|
694
|
+
break;
|
695
|
+
|
696
|
+
case DEFINECLASS_MODULE:
|
697
|
+
|
698
|
+
if (class_base == nil) {
|
699
|
+
class_base = sf.self;
|
700
|
+
if (class_base.flags & T_OBJECT) {
|
701
|
+
class_base = rb_class_real(class_base.klass);
|
702
|
+
}
|
703
|
+
}
|
704
|
+
|
705
|
+
if (rb_const_defined_at(class_base, class_id)) {
|
706
|
+
klass = rb_const_get_at(class_base, class_id);
|
707
|
+
if (!(klass.flags & T_MODULE)) {
|
708
|
+
throw class_id + " is not a module"
|
709
|
+
// rb_raise
|
710
|
+
}
|
711
|
+
}
|
712
|
+
else {
|
713
|
+
// new module
|
714
|
+
klass = rb_define_module_id(class_id);
|
715
|
+
rb_name_class(klass, class_id);
|
716
|
+
// rb_set_class_path(klass, class_base, class_id);
|
717
|
+
rb_const_set(class_base, class_id, klass);
|
718
|
+
klass.parent = class_base;
|
719
|
+
}
|
720
|
+
break;
|
721
|
+
|
722
|
+
default:
|
723
|
+
throw "error, unknown iDEFINECLASS definetype"
|
724
|
+
}
|
725
|
+
|
726
|
+
// do body..
|
727
|
+
var pcf = vm.cfp;
|
728
|
+
var cfp = vm_push_frame(vm, class_iseq, klass);
|
729
|
+
cfp.block_iseq = nil;
|
730
|
+
|
731
|
+
var val = vm_exec(vm);
|
732
|
+
vm_pop_frame(vm);
|
733
|
+
// return val;
|
734
|
+
// puts val on stack
|
735
|
+
sf.stack[sf.sp++] = val;
|
736
|
+
break;
|
737
|
+
|
738
|
+
/**
|
739
|
+
send
|
740
|
+
|
741
|
+
== operands
|
742
|
+
|
743
|
+
== stack
|
744
|
+
|
745
|
+
*/
|
746
|
+
case iSEND:
|
747
|
+
// get off arguments first, then get off recv.
|
748
|
+
var argc = op[2], mid = op[1];
|
749
|
+
var argv = sf.stack.slice(sf.sp - argc, sf.sp);
|
750
|
+
sf.sp -= argc;
|
751
|
+
var recv = sf.stack[--sf.sp];
|
752
|
+
|
753
|
+
// if this is set, then we did not give an explicit receiver, so assume
|
754
|
+
// self (we can use this info for PRIVATE/PUBLIC calls)
|
755
|
+
if (op[4] & VM_CALL_FCALL_BIT) {
|
756
|
+
// console.log("changing receiver: " + argv.join(", "));
|
757
|
+
recv = sf.self;
|
758
|
+
}
|
759
|
+
// console.log("recv is - " + mid);
|
760
|
+
// console.log(sf.self);
|
761
|
+
// console.log("a");
|
762
|
+
// console.log(mid);
|
763
|
+
// pop result of call onto stack
|
764
|
+
sf.stack[sf.sp++] = rb_call(recv.klass, recv, mid, argc, argv, op[3]);
|
765
|
+
|
766
|
+
break;
|
767
|
+
|
768
|
+
/**
|
769
|
+
invokesuper
|
770
|
+
|
771
|
+
== operands
|
772
|
+
|
773
|
+
argc
|
774
|
+
blockiseq
|
775
|
+
op_flag
|
776
|
+
|
777
|
+
== stack
|
778
|
+
|
779
|
+
before: after:
|
780
|
+
|
781
|
+
|
782
|
+
---------- ----------
|
783
|
+
args.... => val
|
784
|
+
---------- ----------
|
785
|
+
*/
|
786
|
+
case iINVOKESUPER:
|
787
|
+
var op_argc = op[1], op_blockiseq = op[2], op_flag = op[3];
|
788
|
+
var recv = sf.self;
|
789
|
+
var argv = sf.stack.slice(sf.sp - op_argc, sf.sp);
|
790
|
+
sf.stack[sf.sp++] = rb_super_call(recv.klass, recv, sf.method_id, op_argc, argv, op_blockiseq);
|
791
|
+
break;
|
792
|
+
|
793
|
+
/**
|
794
|
+
invokeblock
|
795
|
+
|
796
|
+
== operands
|
797
|
+
|
798
|
+
argc
|
799
|
+
flag
|
800
|
+
|
801
|
+
== stack
|
802
|
+
|
803
|
+
before: after:
|
804
|
+
|
805
|
+
|
806
|
+
---------- ----------
|
807
|
+
args.... => val
|
808
|
+
---------- ----------
|
809
|
+
*/
|
810
|
+
case iINVOKEBLOCK:
|
811
|
+
console.log(vm);
|
812
|
+
throw "a"
|
813
|
+
break;
|
814
|
+
|
815
|
+
/**
|
816
|
+
opt_plus
|
817
|
+
|
818
|
+
== operands
|
819
|
+
|
820
|
+
none
|
821
|
+
|
822
|
+
== stack
|
823
|
+
|
824
|
+
before: after:
|
825
|
+
|
826
|
+
----------
|
827
|
+
obj ----------
|
828
|
+
---------- => val
|
829
|
+
recv ----------
|
830
|
+
----------
|
831
|
+
|
832
|
+
== discussion
|
833
|
+
|
834
|
+
Optomised way to send '+' between numbers. If both are numbers, then
|
835
|
+
we can just do a plus and pop value onto stack. If not, then we need to
|
836
|
+
set up a normal iSEND.
|
837
|
+
*/
|
838
|
+
case iOPT_PLUS:
|
839
|
+
var opt_obj = sf.stack[--sf.sp];
|
840
|
+
var opt_recv = sf.stack[--sf.sp];
|
841
|
+
// if both numbers, do fast track, otherwise we need to send it, as per
|
842
|
+
// normal
|
843
|
+
if ((opt_obj.flags & T_NUMBER) && (opt_recv.flags & T_NUMBER)) {
|
844
|
+
sf.stack[sf.sp++] = opt_obj + opt_recv;
|
845
|
+
}
|
846
|
+
else {
|
847
|
+
throw "opt_plus: need to send as normal iSEND"
|
848
|
+
}
|
849
|
+
break;
|
850
|
+
|
851
|
+
/**
|
852
|
+
newarray
|
853
|
+
|
854
|
+
*/
|
855
|
+
case iNEWARRAY:
|
856
|
+
var argc = op[1];
|
857
|
+
var ary = sf.stack.slice(sf.ap - argc, sf.sp);
|
858
|
+
sf.sp -= argc;
|
859
|
+
sf.stack[sf.sp++] = ary;
|
860
|
+
break;
|
861
|
+
|
862
|
+
default:
|
863
|
+
throw "unknown opcode " + op.toString()
|
864
|
+
}
|
865
|
+
}
|
866
|
+
return nil;
|
867
|
+
// return iseq();
|
868
|
+
}
|
869
|
+
|
870
|
+
|
871
|
+
function vm_push_frame(vm, iseq, self) {
|
872
|
+
var cfp = new rb_control_frame();
|
873
|
+
cfp.iseq = iseq;
|
874
|
+
cfp.self = self;
|
875
|
+
cfp.pc = 0;
|
876
|
+
cfp.stack = [];
|
877
|
+
cfp.sp = 0;
|
878
|
+
|
879
|
+
cfp.locals = new Array(iseq[0] + iseq[1]);
|
880
|
+
cfp.method_id = iseq[2];
|
881
|
+
|
882
|
+
vm.cfp = cfp;
|
883
|
+
vm.cfs.push(cfp);
|
884
|
+
return cfp;
|
885
|
+
}
|
886
|
+
|
887
|
+
function vm_pop_frame(vm) {
|
888
|
+
// console.log(vm);
|
889
|
+
// throw "."
|
890
|
+
vm.cfs.pop();
|
891
|
+
vm.cfp = vm.cfs[vm.cfs.length - 1];
|
892
|
+
}
|
893
|
+
|
894
|
+
function rb_funcall(recv, mid, argc) {
|
895
|
+
var argv = Array.prototype.slice.call(arguments, 3, argc + 3);
|
896
|
+
|
897
|
+
return rb_call(recv.klass, recv, mid, argc, argv, nil);
|
898
|
+
}
|
899
|
+
|
900
|
+
function rb_call(klass, recv, mid, argc, argv, blockptr) {
|
901
|
+
var body = rb_search_method(klass, mid);
|
902
|
+
if (!body) {
|
903
|
+
console.log("calling method missing with: " + mid);
|
904
|
+
console.log(recv);
|
905
|
+
return rb_call(klass, recv, "method_missing", 2, [mid, argv], blockptr);
|
906
|
+
}
|
907
|
+
|
908
|
+
return rb_vm_call(rb_top_vm, klass, recv, mid, mid, argc, argv, body, 0, blockptr);
|
909
|
+
};
|
910
|
+
|
911
|
+
function rb_search_method(klass, id) {
|
912
|
+
|
913
|
+
var f, k = klass;
|
914
|
+
while (!(f = k.m_tbl[id])) {
|
915
|
+
k = k.sup;
|
916
|
+
if (!k) return undefined;
|
917
|
+
}
|
918
|
+
return f;
|
919
|
+
};
|
920
|
+
|
921
|
+
function rb_vm_call(vm, klass, recv, id, oid, argc, argv, body, nosuper, blockiseq) {
|
922
|
+
// console.log(id);
|
923
|
+
// console.log(blockptr);
|
924
|
+
if (typeof body === 'function') {
|
925
|
+
|
926
|
+
var pcf = vm.cfp;
|
927
|
+
|
928
|
+
var cfp = vm_push_frame(vm, [0,0], recv);
|
929
|
+
|
930
|
+
var block_t = new rb_block_t();
|
931
|
+
cfp.block_t = block_t;
|
932
|
+
block_t.iseq = blockiseq;
|
933
|
+
block_t.dfp = cfp;
|
934
|
+
// block_t.self =
|
935
|
+
|
936
|
+
var val = call_cfunc(body, recv, body.rb_argc, argc, argv);
|
937
|
+
|
938
|
+
vm_pop_frame(vm);
|
939
|
+
// console.log("popping from " + id);
|
940
|
+
return val;
|
941
|
+
}
|
942
|
+
else {
|
943
|
+
|
944
|
+
var pcf = vm.cfp;
|
945
|
+
var cfp = vm_push_frame(vm, body, recv);
|
946
|
+
|
947
|
+
var block_t = new rb_block_t();
|
948
|
+
cfp.block_t = block_t;
|
949
|
+
block_t.iseq = blockiseq;
|
950
|
+
block_t.dfp = cfp;
|
951
|
+
|
952
|
+
for (var i = 0; i < argc; i++) {
|
953
|
+
cfp.locals[i] = argv[i];
|
954
|
+
}
|
955
|
+
|
956
|
+
var val = vm_exec(vm);
|
957
|
+
vm_pop_frame(vm);
|
958
|
+
// console.log("popping from " + id);
|
959
|
+
return val;
|
960
|
+
}
|
961
|
+
}
|
962
|
+
|
963
|
+
function call_cfunc(func, recv, len, argc, argv) {
|
964
|
+
|
965
|
+
if (len >= 0 && argc != len) {
|
966
|
+
// rb_raise(rb_eArgError, "wrong number of arguments(" + argc + " for " + len + ")");
|
967
|
+
throw "rb_eArgError: wrong number of arguments(" + argc + " for " + len + ")"
|
968
|
+
}
|
969
|
+
|
970
|
+
// even though 15 is acceptable, we should determine a cut off point. 5 seems reasonable, then after
|
971
|
+
// 5, we just push recv to start of argv, and apply().
|
972
|
+
switch (len) {
|
973
|
+
case -2:
|
974
|
+
throw "call_cfunc: unimplemeneted: -2 arg length"
|
975
|
+
case -1:
|
976
|
+
return func(argc, argv, recv);
|
977
|
+
case 0:
|
978
|
+
return func(recv);
|
979
|
+
case 1:
|
980
|
+
return func(recv, argv[0]);
|
981
|
+
case 2:
|
982
|
+
return func(recv, argv[0], argv[1]);
|
983
|
+
case 3:
|
984
|
+
return func(recv, argv[0], argv[1], argv[2]);
|
985
|
+
case 4:
|
986
|
+
return func(recv, argv[0], argv[1], argv[2], argv[3]);
|
987
|
+
case 5:
|
988
|
+
return func(recv, argv[0], argv[1], argv[2], argv[3], argv[4]);
|
989
|
+
case 6:
|
990
|
+
return func(recv, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5]);
|
991
|
+
case 7:
|
992
|
+
return func(recv, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6]);
|
993
|
+
case 8:
|
994
|
+
return func(recv, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7]);
|
995
|
+
case 9:
|
996
|
+
return func(recv, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7], argv[8]);
|
997
|
+
case 10:
|
998
|
+
return func(recv, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7], argv[8], argv[9]);
|
999
|
+
case 11:
|
1000
|
+
return func(recv, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7], argv[8], argv[9], argv[10]);
|
1001
|
+
case 12:
|
1002
|
+
return func(recv, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7], argv[8], argv[9], argv[10], argv[11]);
|
1003
|
+
case 13:
|
1004
|
+
return func(recv, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7], argv[8], argv[9], argv[10], argv[11], argv[12]);
|
1005
|
+
case 14:
|
1006
|
+
return func(recv, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7], argv[8], argv[9], argv[10], argv[11], argv[12], argv[13]);
|
1007
|
+
case 15:
|
1008
|
+
return func(recv, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7], argv[8], argv[9], argv[10], argv[11], argv[12], argv[13], argv[14]);
|
1009
|
+
default:
|
1010
|
+
// rb_raise(rb_eArgError, "too many arguments(" + len + ")");
|
1011
|
+
throw "rb_eArgError: too many arguments(" + len + ")"
|
1012
|
+
}
|
1013
|
+
throw "should never be reached"
|
1014
|
+
};
|
1015
|
+
|
1016
|
+
/**
|
1017
|
+
Call super
|
1018
|
+
*/
|
1019
|
+
function rb_super_call(klass, recv, mid, argc, argv, blockptr) {
|
1020
|
+
var vm = rb_top_vm;
|
1021
|
+
// console.log("current iseq/body");
|
1022
|
+
// find current iseq
|
1023
|
+
var k = klass, f, cur = vm.cfp.iseq;
|
1024
|
+
while (!(f = k.m_tbl[mid]) || !(f == vm.cfp.iseq)) {
|
1025
|
+
k = k.sup;
|
1026
|
+
// if (!k) return undefined;
|
1027
|
+
if (!k) throw "cannot find method in super_call"
|
1028
|
+
}
|
1029
|
+
// console.log(f);
|
1030
|
+
// f is now our current, so look for our super()
|
1031
|
+
k = k.sup;
|
1032
|
+
while (!(f = k.m_tbl[mid])) {
|
1033
|
+
k = k.sup;
|
1034
|
+
// if (!k) return undefined;
|
1035
|
+
if (!k) throw "cannot find method in super_call"
|
1036
|
+
}
|
1037
|
+
// console.log(f);
|
1038
|
+
|
1039
|
+
if (!f) {
|
1040
|
+
throw "cannot find super.."
|
1041
|
+
}
|
1042
|
+
console.log(recv);
|
1043
|
+
return rb_vm_call(rb_top_vm, klass, recv, mid, mid, argc, argv, f, 0, blockptr);
|
1044
|
+
};
|
1045
|
+
|
1046
|
+
/**
|
1047
|
+
Is block given. This is used from c functions that check the current frame
|
1048
|
+
pointer to see if it has a block.
|
1049
|
+
*/
|
1050
|
+
function rb_block_given_p() {
|
1051
|
+
|
1052
|
+
}
|
1053
|
+
|
1054
|
+
/**
|
1055
|
+
Is block given. This method, accessible from ruby, checks the previous stack
|
1056
|
+
frame for a block. Calling this method pushes a new stack frame onto the stack,
|
1057
|
+
so the previous one must be checked.
|
1058
|
+
*/
|
1059
|
+
function rb_f_block_given_p(recv) {
|
1060
|
+
|
1061
|
+
}
|
1062
|
+
|
1063
|
+
function rb_yield(val) {
|
1064
|
+
if (val === nil) return rb_yield_0(0, []);
|
1065
|
+
return rb_yield_0(1, [val]);
|
1066
|
+
}
|
1067
|
+
|
1068
|
+
function rb_yield_0(argc, argv) {
|
1069
|
+
var vm = rb_top_vm;
|
1070
|
+
// console.log(vm.cfp);
|
1071
|
+
if (vm.cfp.block_t !== nil) {
|
1072
|
+
var recv = 0; // FIXME: get the correct receiver..from dfp in block_t
|
1073
|
+
|
1074
|
+
var pcf = vm.cfp;
|
1075
|
+
var cfp = vm_push_frame(vm, vm.cfp.block_t.iseq, recv);
|
1076
|
+
// cfp.dfp = vm.cfp.block_t.iseq;
|
1077
|
+
// cfp.self = vm.cfp.block_t.self;
|
1078
|
+
|
1079
|
+
for (var i = 0; i < argc; i++) {
|
1080
|
+
cfp.locals[i] = argv[i];
|
1081
|
+
}
|
1082
|
+
|
1083
|
+
var val = vm_exec(vm);
|
1084
|
+
vm_pop_frame(vm);
|
1085
|
+
return val;
|
1086
|
+
}
|
1087
|
+
throw "rb_yield_0: no block given";
|
1088
|
+
return nil;
|
1089
|
+
}
|
1090
|
+
|
1091
|
+
|
1092
|
+
// Initializie VM - this will run the main VM
|
1093
|
+
function Init_VM() {
|
1094
|
+
rb_top_vm = new rb_vm();
|
1095
|
+
rb_top_vm.top_self = rb_top_self;
|
1096
|
+
}
|
1097
|
+
|
1098
|
+
function main_to_s() {
|
1099
|
+
return "main";
|
1100
|
+
}
|
1101
|
+
|
1102
|
+
rb_top_self = null;
|
1103
|
+
|
1104
|
+
function rb_vm_top_self() {
|
1105
|
+
return rb_top_vm.top_self;
|
1106
|
+
}
|
1107
|
+
|
1108
|
+
|
1109
|
+
// Initialize top self
|
1110
|
+
function Init_top_self() {
|
1111
|
+
/**
|
1112
|
+
Hack. When we run this, our VM isnt actually running.... so we cant use methods.. hmmm
|
1113
|
+
*/
|
1114
|
+
rb_top_self = new RObject();
|
1115
|
+
rb_top_self.klass = rb_cObject;
|
1116
|
+
FL_SET(rb_top_self, T_OBJECT);
|
1117
|
+
rb_define_singleton_method(rb_top_self, 'to_s', main_to_s, 0);
|
1118
|
+
}
|
1119
|
+
|
1120
|
+
function rb_method_missing(argc, argv, recv) {
|
1121
|
+
throw "method missing: " + argv.join(",")
|
1122
|
+
}
|
1123
|
+
|
1124
|
+
function Init_vm_eval() {
|
1125
|
+
|
1126
|
+
// rb_define_method(rb_mKernel, "eval", rb_f_eval, -1);
|
1127
|
+
// rb_define_method(rb_mKernel, "local_variables", rb_f_local_variables, 0);
|
1128
|
+
// rb_define_method(rb_mKernel, "iterator?", rb_f_block_given_p, 0);
|
1129
|
+
// rb_define_method(rb_mKernel, "block_given?", rb_f_block_given_p, 0);
|
1130
|
+
//
|
1131
|
+
// rb_define_method(rb_mKernel, "catch", rb_f_catch, -1);
|
1132
|
+
// rb_define_method(rb_mKernel, "throw", rb_f_throw, -1);
|
1133
|
+
//
|
1134
|
+
// rb_define_method(rb_mKernel, "loop", rb_f_loop, 0);
|
1135
|
+
//
|
1136
|
+
// rb_define_method(rb_cBasicObject, "instance_eval", rb_obj_instance_eval, -1);
|
1137
|
+
// rb_define_method(rb_cBasicObject, "instance_exec", rb_obj_instance_exec, -1);
|
1138
|
+
rb_define_private_method(rb_cBasicObject, "method_missing", rb_method_missing, -1);
|
1139
|
+
|
1140
|
+
// rb_define_method(rb_cBasicObject, "__send__", rb_f_send, -1);
|
1141
|
+
// rb_define_method(rb_mKernel, "send", rb_f_send, -1);
|
1142
|
+
// rb_define_method(rb_mKernel, "public_send", rb_f_public_send, -1);
|
1143
|
+
//
|
1144
|
+
// rb_define_method(rb_cModule, "module_exec", rb_mod_module_exec, -1);
|
1145
|
+
// rb_define_method(rb_cModule, "class_exec", rb_mod_module_exec, -1);
|
1146
|
+
// rb_define_method(rb_cModule, "module_eval", rb_mod_module_eval, -1);
|
1147
|
+
// rb_define_method(rb_cModule, "class_eval", rb_mod_module_eval, -1);
|
1148
|
+
//
|
1149
|
+
// rb_define_method(rb_mKernel, "caller", rb_f_caller, -1);
|
1150
|
+
}
|