bets 0.0.13 → 0.0.14

Sign up to get free protection for your applications and to get access to all the features.
data/lib/rules.rb ADDED
@@ -0,0 +1,747 @@
1
+ # encoding: utf-8
2
+ module Rules
3
+ class Lexical
4
+ attr_reader :result
5
+ attr_reader :errors
6
+ private
7
+ def initialize
8
+ # Дерево лексического разбора
9
+ keywrd_trm = '[\s\;]'
10
+ digvar_trm = '[\s\)\+\-\*\/\=\>\<\;]'
11
+ operat_trm = '[\sA-Za-zА-Яа-я0-9\(]'
12
+
13
+ @lexems = [
14
+ [['\.','\s','',:stop],
15
+ ['','\.',keywrd_trm,'',:dup],
16
+ ['','','','','','','','','','']],
17
+ [[';','\s','',:semicolon],
18
+ ['','','','','','','','']],
19
+ [['\(','.?\s?','',:l_brace],
20
+ ['','','','','','','','']],
21
+ [['\)','.?\s?','',:r_brace],
22
+ ['','','','','','','','']],
23
+ [['\=',operat_trm,'',:equ],
24
+ ['','','','','','','','','','']],
25
+ [['\+',operat_trm,'',:plus],
26
+ ['','','','','','','','','','']],
27
+ [['\-',operat_trm,'',:minus],
28
+ ['','','','','','','','','','']],
29
+ [['\*',operat_trm,'',:mul],
30
+ ['','','','','','','','','','']],
31
+ [['\/',operat_trm,'',:div],
32
+ ['','','','','','','','','','']],
33
+ [['\>',operat_trm,'',:great],
34
+ ['' ,'=', operat_trm, '', :ge],
35
+ ['','','','','','','','','','']],
36
+ [['\<',operat_trm,'',:low],
37
+ ['','\=',operat_trm,'',:le],
38
+ ['','\-',keywrd_trm,'',:ret],
39
+ ['','\>',keywrd_trm,'',:swap],
40
+ ['','','','','','','','','','']],
41
+ [['\|', keywrd_trm,'',:lim],
42
+ ['','','','','','','','','','']],
43
+
44
+ [['\-','\-', '[\r\n]','',:comment],
45
+ ['','', '~', '.', '[\r\n]','',:comment],
46
+ ['','','','','','','','']],
47
+
48
+
49
+ [['\?','д','а',keywrd_trm,'',:if_yes],
50
+ ['','н','е','т',keywrd_trm,'',:if_no],
51
+ ['','|',keywrd_trm,'',:lcp],
52
+ ['','','','','','','','']],
53
+
54
+ [['и',keywrd_trm,'',:and],
55
+ ['','л','и',keywrd_trm,'',:or],
56
+ ['','н','а','ч','е',keywrd_trm,'',:else],
57
+ ['','с','т','и','н','а',keywrd_trm,'',:true],
58
+ ['','','','','','','','','','']],
59
+
60
+ [['л','о','ж','ь',keywrd_trm,'',:false],
61
+ ['','','','','','','','']],
62
+
63
+ [['п','о','д','к','л','ю','ч','и','т','ь',keywrd_trm,'',:include],
64
+ ['','у','с','т','о',keywrd_trm,'',:nil],
65
+ ['','','','','','','','']],
66
+
67
+ [['r','u','b','y',keywrd_trm,'',:ruby],
68
+ ['','','','','','','','']],
69
+
70
+ [['\d',digvar_trm,'', :number],
71
+ ['' ,'\.','~','\d',digvar_trm,'',:float],
72
+ ['' ,'~','\d',digvar_trm,'',:number],
73
+ ['' , '', '','\.','~','\d',digvar_trm,'',:float],
74
+ ['','','','','','','','','','','','','']],
75
+
76
+ [['\"','~','[^"]','\"',keywrd_trm,'',:string],
77
+ ['','','','','','','','','','']],
78
+
79
+ [['\'','~','[^\']','\'',keywrd_trm,'',:string],
80
+ ['','','','','','','','','','']],
81
+
82
+ [['\:','~','[а-яА-Я\w]',keywrd_trm,'',:word],
83
+ ['','','','','','','','','','']],
84
+
85
+ [['[а-яА-Яa-zA-Z]',digvar_trm,'',:var],
86
+ ['','~','[а-яА-Я\w]',digvar_trm,'',:var],
87
+ ['','','','\:','\s','',:label],
88
+ ['','','','','\:','\s','',:proc],
89
+ ['','','','','','','','','','']],
90
+
91
+ [['@','~','[а-яА-Я\w]',digvar_trm,'',:addr],
92
+ ['','','','','','','','','','']],
93
+
94
+ [['!','~','[а-яА-Я\w]',digvar_trm,'',:wvar],
95
+ ['','','','','','','','','','']],
96
+
97
+ [['\x0', '\s', '', :end],
98
+ ['','','','','','','','','','']],
99
+
100
+ [['.','\s','',:lexical_error],
101
+ ['', '~', '.','\s', '',:lexical_error],
102
+ ['','','','','','','','','','']]
103
+ ]
104
+ @error_msg = {
105
+ incorrect_lexem: "Недопустимая лексема"
106
+ }
107
+ @result = []
108
+ @errors = []
109
+
110
+ @step = @step_count = 1
111
+ end
112
+ # Проход по подлексемам
113
+ def get_sublexem(lg, tp)
114
+ bp = p = tp
115
+ y = x = 0
116
+ f = false
117
+ value = ''
118
+ loop do
119
+ while @t[p] =~ Regexp.new(lg[y][x]) do
120
+ x += 1 unless f
121
+ value += @t[p]
122
+ if lg[y][x].empty?
123
+ result = {
124
+ line: @l,
125
+ begin: bp,
126
+ length: p - bp,
127
+ lexem: lg[y][x + 1],
128
+ value: value[0..-2]
129
+ }
130
+ return result
131
+ end
132
+ p += 1
133
+ if f == true && not(@t[p] =~ Regexp.new(lg[y][x]))
134
+ x += 1
135
+ f = false
136
+ end
137
+ end
138
+
139
+ if lg[y][x] == '~'
140
+ x += 1
141
+ f = true
142
+ next
143
+ end
144
+ y += 1
145
+
146
+ y += 1 while not lg[y][x-1].empty?
147
+ return nil if lg[y][x].empty?
148
+ end
149
+ end
150
+ # Получить текущую лексему
151
+ def get_lexem
152
+ a = 0
153
+ loop do
154
+ return nil if @p >= @t.length
155
+ lg = @lexems[a]
156
+ while @t[@p] =~ /\s/ do
157
+ @l += 1 if @t[@p] =~ /\n/
158
+ @p += 1
159
+ return nil if @p >= @t.length
160
+ end
161
+ if @t[@p] =~ Regexp.new(lg[0][0])
162
+ result = get_sublexem(lg, @p)
163
+ unless result.nil?
164
+ @p += result[:length]
165
+ @cls.send(@mth, @p * 20 / @t.length ) unless @cls.nil?
166
+ return result
167
+ end
168
+ end
169
+ a += 1
170
+ end
171
+ end
172
+ public
173
+ # Разбор на лексемы
174
+ def analyze (text, filename)
175
+ @p = 0
176
+ @l = 1
177
+ @t = text + "\n\x0\n"
178
+ # Удаление блочных комментариев
179
+ # @t.gsub!(/\/\*([^*]|[\r\n]|(\*+([^*\/]|[\r\n])))*\*+\//, '')
180
+ # Удаление строчных комментариев
181
+ # @t.gsub!(/\-\-.*\n/, '')
182
+
183
+ @result = []
184
+ @errors = []
185
+ loop do
186
+ lexem = get_lexem
187
+ break if lexem.nil?
188
+ break if lexem[:lexem] == :end
189
+ lexem[:filename] = filename
190
+ if lexem[:lexem] == :lexical_error
191
+ @errors << {
192
+ :message => @error_msg[:incorrect_lexem],
193
+ :lexem => lexem } if @errors.length < 5
194
+ else
195
+ @result << lexem
196
+ end
197
+ end
198
+ end
199
+ def set_progress_callback(classp, mth)
200
+ @cls = classp
201
+ @mth = mth
202
+ end
203
+
204
+ end
205
+
206
+ class Syntax
207
+ attr_reader :errors
208
+ private
209
+ def initialize
210
+ # Дерево синтаксического разбора
211
+ operators = [:plus,:minus,:div,:mul,:great,:ge,:low,:le,:equ,:or,:and]
212
+ digits = [:number,:float,:true,:false,:nil]
213
+ strings = [:string,:word]
214
+ conditions = [:if_yes,:if_no,:else,:lcp,:semicolon]
215
+ ids = [:var,:proc,:label,:addr,:wvar]
216
+ term = ids + conditions + operators + digits + strings + [:stop,:l_brace,:end,:ret,:include,:dup,:swap,:lim,:ruby,:comment,nil]
217
+
218
+ @syntax = {
219
+ :stop => term + [nil],
220
+ :semicolon => term + [nil],
221
+ :dup => term + [nil],
222
+ :swap => term + [nil],
223
+ :l_brace => [:l_brace] + digits + [:minus,:var,nil],
224
+ :r_brace => [:r_brace] + operators + ids + term + [:semicolon,nil],
225
+ :equ => term + [nil],
226
+ :plus => term + [nil],
227
+ :minus => term + [nil],
228
+ :mul => term + [nil],
229
+ :div => term + [nil],
230
+ :great => term + [nil],
231
+ :ge => term + [nil],
232
+ :low => term + [nil],
233
+ :le => term + [nil],
234
+ :and => term + [nil],
235
+ :or => term + [nil],
236
+ :ret => term + [nil],
237
+ :if_yes => term + [nil],
238
+ :if_no => term + [nil],
239
+ :lcp => term + [nil],
240
+ :else => term + [nil],
241
+ :true => digits + [:var,:wvar] + operators + conditions + [:r_brace,:end,nil],
242
+ :false => digits + [:var,:wvar] + operators + conditions + [:r_brace,:end,nil],
243
+ :number => digits + strings + [:var,:wvar] + operators + conditions + [:r_brace,:end,nil],
244
+ :float => digits + strings + [:var,:wvar] + operators + conditions + [:r_brace,:end,nil],
245
+ :string => term + [nil],
246
+ :var => operators + term + [nil],
247
+ :addr => operators + term + [nil],
248
+ :wvar => term + [nil],
249
+ :label => term + [nil],
250
+ :proc => term + [nil],
251
+ :include => term + [nil],
252
+ :ruby => term + [nil],
253
+ :comment => term + [nil],
254
+ :nil => term + [nil],
255
+ :lim => term + [nil],
256
+ :word => term + [nil],
257
+ :end => term + [nil]
258
+ }
259
+
260
+ @error_msg = {
261
+ incorrect_syntax: "Недопустимый синтаксис"
262
+ }
263
+ @errors = []
264
+ end
265
+ public
266
+ def analyze(lexem_seq)
267
+ @errors = []
268
+ sp = nil
269
+ lp = 0
270
+ while lp < lexem_seq.length and !lexem_seq[lp + 1].nil? do
271
+ sp = @syntax[lexem_seq[lp][:lexem]]
272
+ sp.each do |s|
273
+ break if s == lexem_seq[lp + 1][:lexem]
274
+ if s.nil?
275
+ @errors << {
276
+ :message => @error_msg[:incorrect_syntax],
277
+ :lexem => lexem_seq[lp + 1]} if @errors.length < 5
278
+ break
279
+ end
280
+ end
281
+ lp += 1
282
+ @cls.send(@mth, 20 + lp * 20 / lexem_seq.length ) unless @cls.nil?
283
+ end
284
+ end
285
+
286
+ def set_progress_callback(classp, mth)
287
+ @cls = classp
288
+ @mth = mth
289
+ end
290
+ end
291
+
292
+ class Translator
293
+ attr_reader :ids
294
+ attr_reader :debug
295
+ attr_reader :data_seg
296
+ attr_reader :code_seg
297
+ attr_reader :errors
298
+ attr_reader :includes
299
+
300
+ private
301
+ def initialize
302
+ @syntax = Syntax.new
303
+ @lexical = Lexical.new
304
+ @uid = 0
305
+ @errors = 0
306
+
307
+ @error_msg = {
308
+ brace: "Кол-во открытых скобок не соответствует кол-ву закрытых",
309
+ include: "Ошибка открытия файла в инструкции `подключить`"
310
+ }
311
+ end
312
+ def unique_id
313
+ @uid += 1
314
+ return "ABC#{@uid}"
315
+ end
316
+
317
+ # Первый проход:
318
+ def first_pass(lex_seq, libdir)
319
+ @errors = []
320
+ @code_seg = []
321
+ @data_seg = []
322
+ @ids = {}
323
+ @debug = []
324
+ @includes = []
325
+
326
+ postfix_stack = []
327
+ condition_stack = []
328
+ f_unary = false
329
+
330
+ store = nil
331
+ il = 0
332
+ while il < lex_seq.length do
333
+ break if lex_seq[il].nil?
334
+ case lex_seq[il][:lexem]
335
+ # Раздел обработки выражений
336
+ when :l_brace
337
+ postfix_stack.push lex_seq[il]
338
+ when :r_brace
339
+ loop do
340
+ if postfix_stack.last.nil?
341
+ @errors << {
342
+ message: @error_msg[:brace],
343
+ lexem: lex_seq[il]
344
+ }
345
+ return
346
+ end
347
+
348
+ break if postfix_stack.last[:lexem] == :l_brace
349
+ d = postfix_stack.pop
350
+ @code_seg << d[:lexem]
351
+ @debug << d
352
+ end
353
+ postfix_stack.pop
354
+ when :plus,:minus,:div,:mul,:equ,:great,:low,:ge,:le
355
+ if postfix_stack.length == 0
356
+ @code_seg << lex_seq[il][:lexem]
357
+ @debug << lex_seq[il]
358
+ else
359
+ if store[:lexem] == :l_brace and lex_seq[il][:lexem] == :minus
360
+ lex_seq[il][:lexem] = :unary_minus
361
+ f_unary = true
362
+ else
363
+ if ([:plus,:minus,:equ,:great,:low,:ge,:le].include? lex_seq[il][:lexem] and !postfix_stack.last.nil? and [:plus,:minus,:div,:mul].include? postfix_stack.last[:lexem]) or (!postfix_stack.last.nil? and [:div,:mul,:unary_minus].include? postfix_stack.last[:lexem])
364
+ d = postfix_stack.pop
365
+ @code_seg << d[:lexem]
366
+ @debug << d
367
+ end
368
+ postfix_stack.push lex_seq[il]
369
+ end
370
+ end
371
+ # Раздел обработки идентификаторов
372
+ when :var
373
+ id = lex_seq[il][:value]
374
+ if @ids[id].nil?
375
+ @data_seg << nil
376
+ @ids[id] = {:type => :var, :addr => @data_seg.length - 1, :changes => [@code_seg.length + 1]}
377
+ else
378
+ @ids[id][:changes] << @code_seg.length + 1
379
+ end
380
+ if @ids[id][:type] == :var
381
+ @code_seg << :dpush
382
+ @debug << lex_seq[il]
383
+ else
384
+ @code_seg << 0
385
+ @debug << lex_seq[il]
386
+ end
387
+ @code_seg << @ids[id][:addr]
388
+ @debug << lex_seq[il]
389
+ when :wvar
390
+ id = lex_seq[il][:value][1..-1]
391
+ if @ids[id].nil?
392
+ @data_seg << nil
393
+ @ids[id] = {:type => :var, :addr => @data_seg.length - 1, :changes => [@code_seg.length + 1]}
394
+ else
395
+ @ids[id][:changes] << @code_seg.length + 1
396
+ end
397
+ @code_seg << :dpop
398
+ @debug << lex_seq[il]
399
+ @code_seg << @ids[id][:addr]
400
+ @debug << lex_seq[il]
401
+ when :proc
402
+ id = lex_seq[il][:value].gsub(/\:*/, '')
403
+ if @ids[id].nil?
404
+ @ids[id] = {:type => :proc, :addr => @code_seg.length, :changes => []}
405
+ else
406
+ @data_seg.delete_at @ids[id][:addr]
407
+ @ids[id][:addr] = @code_seg.length
408
+ @ids[id][:type] = :proc
409
+ end
410
+ when :label
411
+ id = lex_seq[il][:value].gsub(/\:*/, '')
412
+ if @ids[id].nil?
413
+ @ids[id] = {:type => :label, :addr => @code_seg.length, :changes => []}
414
+ else
415
+ @data_seg.delete_at @ids[id][:addr]
416
+ @ids[id][:addr] = @code_seg.length
417
+ @ids[id][:type] = :label
418
+ end
419
+ # Раздел обработки литералов
420
+ when :addr
421
+ @code_seg << :push
422
+ @debug << lex_seq[il]
423
+ addr = @ids[lex_seq[il][:value][1..-1]][:addr]
424
+ @code_seg << addr
425
+ @debug << lex_seq[il]
426
+ when :number
427
+ @code_seg << :push
428
+ @debug << lex_seq[il]
429
+ @code_seg << lex_seq[il][:value].to_i * (f_unary ? -1 : 1)
430
+ @debug << lex_seq[il]
431
+ f_unary = false
432
+ when :float
433
+ @code_seg << :push
434
+ @debug << lex_seq[il]
435
+ @code_seg << lex_seq[il][:value].to_f * (f_unary ? -1 : 1)
436
+ @debug << lex_seq[il]
437
+ f_unary = false
438
+ when :string
439
+ @code_seg << :push
440
+ @debug << lex_seq[il]
441
+ @code_seg << lex_seq[il][:value][1..-2]
442
+ @debug << lex_seq[il]
443
+ when :word
444
+ @code_seg << :push
445
+ @debug << lex_seq[il]
446
+ @code_seg << lex_seq[il][:value][1..-1]
447
+ @debug << lex_seq[il]
448
+ when :uminus
449
+ f_unary = true
450
+ # Раздел обработки условий
451
+ when :true
452
+ @code_seg << :push
453
+ @debug << lex_seq[il]
454
+ @code_seg << 1
455
+ @debug << lex_seq[il]
456
+ when :false
457
+ @code_seg << :push
458
+ @debug << lex_seq[il]
459
+ @code_seg << 0
460
+ @debug << lex_seq[il]
461
+ when :nil
462
+ @code_seg << :push
463
+ @debug << lex_seq[il]
464
+ @code_seg << nil
465
+ @debug << lex_seq[il]
466
+ when :if_yes
467
+ @code_seg << :jne
468
+ @debug << lex_seq[il]
469
+ id = unique_id
470
+ @ids[id] = {:type => :in, :addr => 0, :changes => [@code_seg.length]}
471
+ @code_seg << 0
472
+ @debug << lex_seq[il]
473
+ condition_stack.push id
474
+ when :if_no
475
+ @code_seg << :je
476
+ @debug << lex_seq[il]
477
+ id = unique_id
478
+ @ids[id] = {:type => :in, :addr => 0, :changes => [@code_seg.length]}
479
+ @code_seg << 0
480
+ @debug << lex_seq[il]
481
+ condition_stack.push id
482
+ when :else
483
+ id_yesno = condition_stack.pop
484
+ id = unique_id
485
+ @code_seg << :jmp
486
+ @debug << lex_seq[il]
487
+ @ids[id] = {:type => :in, :addr => 0, :changes => [@code_seg.length]}
488
+ @code_seg << 0
489
+ @debug << lex_seq[il]
490
+ condition_stack.push id
491
+ @ids[id_yesno][:addr] = @code_seg.length
492
+ when :semicolon
493
+ id = condition_stack.pop
494
+ @ids[id][:addr] = @code_seg.length
495
+ when :include
496
+ il += 1
497
+ # Чтение исходного кода
498
+ filename = lex_seq[il][:value][1..-2]
499
+ basename = File.basename(filename)
500
+ unless File.exist?("#{filename}.rules")
501
+ filename = File.join(libdir, 'ruleslib', "#{basename}.rules")
502
+ end
503
+ unless File.exist?(filename)
504
+ gem_file = Gem::find_files("#{basename}_rules.rb").last
505
+ if gem_file.nil?
506
+ @errors << {
507
+ message: @error_msg[:include],
508
+ lexem: lex_seq[il]
509
+ }
510
+ return
511
+ end
512
+ filename = File.join(File.dirname(gem_file), "#{basename}.rules")
513
+ end
514
+ text = ''
515
+ begin
516
+ filename = File.expand_path(filename)
517
+ text = File.open(filename, "r:UTF-8").read
518
+ @includes << basename
519
+ rescue Exception => e
520
+ @errors << {
521
+ message: @error_msg[:include],
522
+ lexem: lex_seq[il]
523
+ }
524
+ return
525
+ end
526
+ @lexical.analyze(text, filename)
527
+ @syntax.analyze(@lexical.result)
528
+ @errors += @syntax.errors + @lexical.errors
529
+ @lexical.result.each_index do |i|
530
+ lex_seq.insert(il+1+i,@lexical.result[i])
531
+ end
532
+ when :comment
533
+ else
534
+ @code_seg << lex_seq[il][:lexem]
535
+ @debug << lex_seq[il]
536
+ end
537
+ store = lex_seq[il]
538
+ il += 1
539
+ @cls.send(@mth, 40 + il * 40 / lex_seq.length ) unless @cls.nil?
540
+ end
541
+ while postfix_stack.length > 0 do
542
+ if postfix_stack.last[:lexem] == :l_brace
543
+ @errors << {
544
+ message: @error_msg[:brace],
545
+ lexem: postfix_stack.last
546
+ }
547
+ return
548
+ end
549
+ d = postfix_stack.pop
550
+ @code_seg << d[:lexem]
551
+ @debug << d
552
+ end
553
+ if @errors.length > 0
554
+ @code_seg = nil
555
+ @data_seg = nil
556
+ @debug = nil
557
+ @ids = nil
558
+ end
559
+ end
560
+ # Второй проход
561
+ def second_pass
562
+ i = 0
563
+ @ids.each do |k,id|
564
+ id[:changes].each do |c|
565
+ @code_seg[c] = id[:addr]
566
+ @code_seg[c - 1] = :call if id[:type] == :proc
567
+ @code_seg[c - 1] = :jmp if id[:type] == :label
568
+ end
569
+ i += 1
570
+ @cls.send(@mth, 80 + i * 20 / @ids.length ) unless @cls.nil?
571
+ end
572
+ end
573
+ public
574
+ def translate(lex_seq, libdir)
575
+ @ids = {}
576
+ @debug = []
577
+ @data_seg = []
578
+ @code_seg = []
579
+ first_pass(lex_seq, libdir)
580
+ # @code_seg.each_index {|i| puts "#{i} -- #{@code_seg[i]}"}
581
+ second_pass unless @errors.length > 0
582
+ # @code_seg.each_index {|i| puts "#{i} -- #{@code_seg[i]}"}
583
+ end
584
+
585
+ def set_progress_callback(classp, mth)
586
+ @cls = classp
587
+ @mth = mth
588
+ end
589
+ end
590
+
591
+ class VM
592
+ attr_reader :data
593
+ attr_reader :data_stack
594
+ attr_reader :limit_stack
595
+ attr_reader :prog
596
+ attr_reader :ip
597
+
598
+ private
599
+ def initialize(data_seg, code_seg, debug)
600
+ @cls = nil
601
+ @mth = nil
602
+ # trap("SIGINT") { exit! }
603
+ # Память данных
604
+ @data = data_seg
605
+ # Стек данных
606
+ @data_stack = []
607
+ # Стек ограничителей
608
+ @limit_stack = []
609
+ # Стек вызовов
610
+ @call_stack = []
611
+ # Память программ
612
+ @prog = code_seg
613
+ # Указатель текущей инструкции
614
+ @ip = 0
615
+ # Отладочная информация
616
+ @debug = debug
617
+
618
+ # Объекты ruby
619
+ @uid = 0
620
+ @objects = {}
621
+ end
622
+
623
+ def unique_id
624
+ @uid += 1
625
+ return "#vm_#{@uid}"
626
+ end
627
+
628
+ public
629
+ def halt
630
+ @thread.terminate unless @thread.nil?
631
+ end
632
+
633
+ def run
634
+ Thread.abort_on_exception = true
635
+ @thread = Thread.new do
636
+ @ip = 0
637
+ while @ip < @prog.length do
638
+ @cls.send(@mth, @debug[@ip]) unless @cls.nil?
639
+ case @prog[@ip]
640
+ when :push
641
+ @ip += 1; @data_stack.push @prog[@ip]
642
+ when :call
643
+ @call_stack.push @ip + 2
644
+ @ip = @prog[@ip + 1]
645
+ next
646
+ when :ret
647
+ @ip = @call_stack.pop
648
+ next
649
+ when :dup
650
+ @data_stack.push @data_stack.last
651
+ when :swap
652
+ a = @data_stack.pop
653
+ b = @data_stack.pop
654
+ @data_stack.push a
655
+ @data_stack.push b
656
+ when :plus
657
+ a = @data_stack.pop
658
+ b = @data_stack.pop
659
+ @data_stack.push b + a
660
+ when :minus
661
+ a = @data_stack.pop
662
+ b = @data_stack.pop
663
+ @data_stack.push b - a
664
+ when :div
665
+ a = @data_stack.pop
666
+ b = @data_stack.pop
667
+ @data_stack.push b / a
668
+ when :mul
669
+ a = @data_stack.pop
670
+ b = @data_stack.pop
671
+ @data_stack.push b * a
672
+ when :great
673
+ a = @data_stack.pop
674
+ b = @data_stack.pop
675
+ @data_stack.push b > a
676
+ when :low
677
+ a = @data_stack.pop
678
+ b = @data_stack.pop
679
+ @data_stack.push b < a
680
+ when :ge
681
+ a = @data_stack.pop
682
+ b = @data_stack.pop
683
+ @data_stack.push b >= a
684
+ when :gl
685
+ a = @data_stack.pop
686
+ b = @data_stack.pop
687
+ @data_stack.push b <= a
688
+ when :equ
689
+ a = @data_stack.pop
690
+ b = @data_stack.pop
691
+ @data_stack.push b == a
692
+ when :dpush
693
+ @ip += 1
694
+ @data_stack.push @data[@prog[@ip]]
695
+ when :dpop
696
+ @ip += 1
697
+ @data[@prog[@ip]] = @data_stack.pop
698
+ when :je
699
+ a = @data_stack.pop
700
+ a = (a > 0) if a.kind_of? Fixnum or a.kind_of? Float
701
+ if a
702
+ @ip = @prog[@ip + 1]
703
+ else
704
+ @ip += 2
705
+ end
706
+ next
707
+ when :jne
708
+ a = @data_stack.pop
709
+ a = (a > 0) if a.kind_of? Fixnum or a.kind_of? Float
710
+ unless a
711
+ @ip = @prog[@ip + 1]
712
+ else
713
+ @ip += 2
714
+ end
715
+ next
716
+ when :jmp
717
+ @ip = @prog[@ip + 1]
718
+ next
719
+ when :stop
720
+ break
721
+ when :ruby
722
+ a = @data_stack.pop
723
+ begin
724
+ send(a)
725
+ rescue Exception => e
726
+ puts e
727
+ end
728
+ when :lim
729
+ @limit_stack.push @data_stack.length
730
+ when :lcp
731
+ a = @data_stack.length
732
+ b = @limit_stack.pop
733
+ result = a <= b
734
+ @limit_stack.push b unless result
735
+ @data_stack.push result
736
+ end
737
+ @ip += 1
738
+ end
739
+ end
740
+ end
741
+
742
+ def set_debug_callback(classp, mth)
743
+ @cls = classp
744
+ @mth = mth
745
+ end
746
+ end
747
+ end