Class: Lignite::BodyCompiler

Inherits:
Object
  • Object
show all
Includes:
ParameterDeclarer, VariableDeclarer
Defined in:
lib/lignite/body_compiler.rb

Overview

Extends OpCompiler by

Constant Summary

Constants included from ParameterDeclarer

ParameterDeclarer::IN, ParameterDeclarer::OUT, ParameterDeclarer::PAR16, ParameterDeclarer::PAR32, ParameterDeclarer::PAR8, ParameterDeclarer::PARF, ParameterDeclarer::PARS

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from ParameterDeclarer

#in16, #in32, #in8, #inf, #ins, #io16, #io32, #io8, #iof, #ios, #out16, #out32, #out8, #outf, #outs

Methods included from VariableDeclarer

#array8, #data16, #data32, #data8, #dataf, #datas

Constructor Details

#initialize(globals, locals, declared_objects) ⇒ BodyCompiler

Returns a new instance of BodyCompiler.



27
28
29
30
31
32
33
# File 'lib/lignite/body_compiler.rb', line 27

def initialize(globals, locals, declared_objects)
  @bytes = ""
  @globals = globals
  @locals = locals
  @declared_objects = declared_objects
  @op_compiler = OpCompiler.new(@globals, @locals)
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(name, *args) ⇒ Object

Delegate the ops to the OpCompiler, but also aggregate the result in @bytes.



113
114
115
116
117
# File 'lib/lignite/body_compiler.rb', line 113

def method_missing(name, *args)
  super unless @op_compiler.respond_to?(name)

  @bytes += @op_compiler.send(name, *args)
end

Instance Attribute Details

#bytesByteString (readonly)

Returns:



7
8
9
# File 'lib/lignite/body_compiler.rb', line 7

def bytes
  @bytes
end

#declared_objectsObject (readonly)

Returns the value of attribute declared_objects.



11
12
13
# File 'lib/lignite/body_compiler.rb', line 11

def declared_objects
  @declared_objects
end

#localsVariables (readonly)

Returns:



9
10
11
# File 'lib/lignite/body_compiler.rb', line 9

def locals
  @locals
end

Instance Method Details

#call(name, *args) ⇒ Object



101
102
103
104
105
106
107
108
109
# File 'lib/lignite/body_compiler.rb', line 101

def call(name, *args)
  obj_id = declared_objects.index_of(name)
  raise "Name #{name} not found" if obj_id.nil?

  # TODO: check that args match their declaration
  # In particular, mixing up data32 with dataf passes the VM validity check
  # but then misinterprets the bits.
  super(obj_id, *args) # Ev3Ops::call
end

#clone_contextObject



35
36
37
# File 'lib/lignite/body_compiler.rb', line 35

def clone_context
  BodyCompiler.new(@globals, @locals, @declared_objects)
end

#if(cond, &body) ⇒ Object



39
40
41
42
43
44
45
46
47
# File 'lib/lignite/body_compiler.rb', line 39

def if(cond, &body)
  cond = Flag.new(cond) unless cond.is_a? Condition

  subc = clone_context
  subc.instance_exec(&body)

  cond.not.jump_forward(self, subc.bytes.bytesize)
  @bytes << subc.bytes
end

#if_else(flag8, body_true, body_false) ⇒ Object



49
50
51
52
53
54
55
56
57
58
59
60
# File 'lib/lignite/body_compiler.rb', line 49

def if_else(flag8, body_true, body_false)
  truec = clone_context
  falsec = clone_context
  truec.instance_exec(&body_true)
  falsec.instance_exec(&body_false)

  # 4 is the unconditional jump size
  jr_false(flag8, JumpOffset.new(truec.bytes.bytesize + 4))
  @bytes << truec.bytes
  jr(JumpOffset.new(falsec.bytes.bytesize))
  @bytes << falsec.bytes
end

#loop(&body) ⇒ Object



62
63
64
65
66
67
68
# File 'lib/lignite/body_compiler.rb', line 62

def loop(&body)
  subc = clone_context
  subc.instance_exec(&body)
  @bytes << subc.bytes
  # the jump takes up 4 bytes: JR, LC2, LO, HI
  jr(JumpOffset.new(- (subc.bytes.bytesize + 4)))
end

#loop_until_pre(condition, &body) ⇒ Object



90
91
92
93
94
95
96
97
98
99
# File 'lib/lignite/body_compiler.rb', line 90

def loop_until_pre(condition, &body)
  subc = clone_context
  subc.instance_exec(&body)
  ofs1 = @bytes.bytesize
  condition.jump_forward(self, subc.bytes.bytesize + 4)
  ofs2 = @bytes.bytesize
  fw_jump_size = ofs2 - ofs1
  @bytes << subc.bytes
  jr(JumpOffset.new(-(fw_jump_size + subc.bytes.bytesize + 4)))
end

#loop_while(a, b) ⇒ Object



74
75
76
77
78
79
80
# File 'lib/lignite/body_compiler.rb', line 74

def loop_while(a, b)
  if a.respond_to? :call
    loop_while_post(b, &a)
  else
    loop_while_pre(a, &b)
  end
end

#loop_while_post(condition, &body) ⇒ Object



82
83
84
85
86
87
88
# File 'lib/lignite/body_compiler.rb', line 82

def loop_while_post(condition, &body)
  subc = clone_context
  subc.instance_exec(&body)
  @bytes << subc.bytes
  body_size = subc.bytes.bytesize
  condition.jump_back(self, body_size)
end

#loop_while_postcond(flag8, &body) ⇒ Object



70
71
72
# File 'lib/lignite/body_compiler.rb', line 70

def loop_while_postcond(flag8, &body)
  loop_while(body, Flag.new(flag8))
end

#param_decl_headerObject



23
24
25
# File 'lib/lignite/body_compiler.rb', line 23

def param_decl_header
  parameters.param_decl_header
end

#parametersObject



18
19
20
# File 'lib/lignite/body_compiler.rb', line 18

def parameters
  locals
end

#respond_to_missing?(name, _include_private) ⇒ Boolean

Returns:

  • (Boolean)


119
120
121
# File 'lib/lignite/body_compiler.rb', line 119

def respond_to_missing?(name, _include_private)
  @op_compiler.respond_to?(name) || super
end

#variablesObject



13
14
15
# File 'lib/lignite/body_compiler.rb', line 13

def variables
  locals
end