Class: Nydp::VM

Inherits:
Object show all
Includes:
Helper
Defined in:
lib/nydp/vm.rb

Defined Under Namespace

Modules: Finally, HandleError

Constant Summary collapse

NIL =
Nydp::NIL

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from Helper

#cons, #list, #literal?, #pair?, #sig, #sym, #sym?

Methods included from Converter

#n2r, #r2n

Constructor Details

#initialize(ns) ⇒ VM

Returns a new instance of VM.



10
11
12
13
14
15
16
# File 'lib/nydp/vm.rb', line 10

def initialize ns
  @instructions = []
  @args         = []
  @contexts     = []
  @locals       = Nydp::Hash.new
  @ns           = ns
end

Instance Attribute Details

#argsObject

Returns the value of attribute args.



5
6
7
# File 'lib/nydp/vm.rb', line 5

def args
  @args
end

#contextsObject

Returns the value of attribute contexts.



5
6
7
# File 'lib/nydp/vm.rb', line 5

def contexts
  @contexts
end

#current_contextObject

Returns the value of attribute current_context.



5
6
7
# File 'lib/nydp/vm.rb', line 5

def current_context
  @current_context
end

#instructionsObject

Returns the value of attribute instructions.



5
6
7
# File 'lib/nydp/vm.rb', line 5

def instructions
  @instructions
end

#last_errorObject

Returns the value of attribute last_error.



5
6
7
# File 'lib/nydp/vm.rb', line 5

def last_error
  @last_error
end

#localsObject

Returns the value of attribute locals.



5
6
7
# File 'lib/nydp/vm.rb', line 5

def locals
  @locals
end

#nsObject

Returns the value of attribute ns.



5
6
7
# File 'lib/nydp/vm.rb', line 5

def ns
  @ns
end

#thisiObject

Returns the value of attribute thisi.



5
6
7
# File 'lib/nydp/vm.rb', line 5

def thisi
  @thisi
end

#unhandled_errorObject

Returns the value of attribute unhandled_error.



5
6
7
# File 'lib/nydp/vm.rb', line 5

def unhandled_error
  @unhandled_error
end

Instance Method Details

#args!Object



90
# File 'lib/nydp/vm.rb', line 90

def args!        ; args.empty? ? (raise "illegal operation: no args") : args ; end

#handle_error(ex) ⇒ Object



68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
# File 'lib/nydp/vm.rb', line 68

def handle_error ex
  @unhandled_error = ex

  protecti = []
  protectc = []

  while (@instructions.length > 0) && !(@instructions.last.car.is_a? HandleError)
    if @instructions.last.car.is_a? Finally
      protecti << @instructions.last
      protectc << @contexts.last
    end

    @instructions.pop
    @contexts.pop
  end

  while protecti.length > 0
    push_instructions protecti.pop, protectc.pop
  end
end

#peek_argObject



91
# File 'lib/nydp/vm.rb', line 91

def peek_arg     ; args!.last                                                ; end

#pop_args(count, tail = Nydp::NIL) ⇒ Object



93
94
95
96
97
98
99
100
# File 'lib/nydp/vm.rb', line 93

def pop_args count, tail=Nydp::NIL
  case count
  when 0
    tail
  else
    pop_args(count - 1, cons(args.pop, tail))
  end
end

#push_arg(a) ⇒ Object



89
# File 'lib/nydp/vm.rb', line 89

def push_arg a   ; args.push a                                               ; end

#push_ctx_instructions(ii) ⇒ Object



28
29
30
31
32
33
34
35
# File 'lib/nydp/vm.rb', line 28

def push_ctx_instructions ii
  if @current_instructions && NIL != @current_instructions
    @instructions.push @current_instructions
    @contexts.push @current_context
  end

  @current_instructions = ii
end

#push_instructions(ii, ctx) ⇒ Object



18
19
20
21
22
23
24
25
26
# File 'lib/nydp/vm.rb', line 18

def push_instructions ii, ctx
  if @current_instructions && NIL != @current_instructions
    @instructions.push @current_instructions
    @contexts.push @current_context
  end

  @current_instructions = ii
  @current_context = ctx
end

#threadObject



42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
# File 'lib/nydp/vm.rb', line 42

def thread
  while @current_instructions
    begin
      if NIL == @current_instructions
        @current_instructions = @instructions.pop
        @current_context      = @contexts.pop
      else
        now = @current_instructions.car
        @current_instructions = @current_instructions.cdr
        now.execute(self)
      end

    rescue StandardError => e
      handle_error e
    end
  end

  if @unhandled_error
    e = @unhandled_error
    @unhandled_error = nil
    raise e
  end

  args.pop
end

#thread_with_expr(expr) ⇒ Object



37
38
39
40
# File 'lib/nydp/vm.rb', line 37

def thread_with_expr expr
  @current_instructions = expr
  thread
end

#vm_infoObject



102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
# File 'lib/nydp/vm.rb', line 102

def vm_info
  msg = ""
  msg << "\n"
  msg << "\ninstruction stack"
  msg << "\n================="
  instructions.each_with_index do |ii, ix|
    msg << "\ninstructions##{ix} : #{ii} #{ii.source if ii.respond_to?(:source)}"
  end
  msg << "\n"
  msg << "\n"
  msg << "\ncontext stack"
  msg << "\n================="
  contexts.each_with_index do |ctx, ix|
    msg << "\ncontext##{ix} :\n#{ctx}"
  end
  msg << "\n"
  msg << "\n"
  msg << "\nargs stack"
  msg << "\n================="
  args.each_with_index do |args, ix|
    msg << "\args##{ix} :\n#{args}"
  end
  msg << "\n"
  msg << "\n"
  msg
end