bets 0.0.13 → 0.0.14

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/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