Class: Lignite::Assembler
- Inherits:
-
Object
- Object
- Lignite::Assembler
- Includes:
- Bytes, Logger, VariableDeclarer
- Defined in:
- lib/lignite/assembler.rb
Overview
Assemble a complete RBF program file.
The compilation has two passes:
-
pass1, Declaration
-
pass2, Resolution
After P1, the instruction sequence is iterated. If an item responds to :pass2, it is replaced by the result of that call. After pass2 we have a sequence of ByteStrings which are just concatenated
No, pass1, gather names, pass2 do all the rest
Constant Summary collapse
- HEADER_SIZE =
16
- SIGNATURE =
"LEGO".freeze
Instance Attribute Summary collapse
- #globals ⇒ Variables readonly
- #objects ⇒ Array<RbfObject> readonly
Instance Method Summary collapse
-
#assemble(rb_filename, rbf_filename, version: 109) ⇒ Object
Assemble a complete RBF program file.
- #image_header(image_size:, version:, object_count:, global_bytes:) ⇒ Object
- #sub(_name, &body) ⇒ Object
- #variables ⇒ Object
- #vmthread(name, &body) ⇒ Object
- #write(rbf_filename, version) ⇒ Object
Methods included from VariableDeclarer
#array8, #data16, #data32, #data8, #dataf, #datas
Methods included from Logger
Methods included from Bytes
#bin_to_hex, #f32, #hex_to_bin, #u16, #u32, #u8, #unpack_f32, #unpack_u16, #unpack_u32, #unpack_u8
Instance Attribute Details
#globals ⇒ Variables (readonly)
31 32 33 |
# File 'lib/lignite/assembler.rb', line 31 def globals @globals end |
#objects ⇒ Array<RbfObject> (readonly)
29 30 31 |
# File 'lib/lignite/assembler.rb', line 29 def objects @objects end |
Instance Method Details
#assemble(rb_filename, rbf_filename, version: 109) ⇒ Object
Assemble a complete RBF program file. (it is OK to reuse an Assembler and call this several times in a sequence) TODO: redesign for Assembler.new(rb_filename).assemble(rbf_filename)?
38 39 40 41 42 43 44 45 46 47 48 |
# File 'lib/lignite/assembler.rb', line 38 def assemble(rb_filename, rbf_filename, version: 109) rb_text = File.read(rb_filename) @objects = [] @globals = Variables.new @declarer = RbfDeclarer.new @declarer.instance_eval(rb_text, rb_filename, 1) # 1 is the line number instance_eval(rb_text, rb_filename, 1) # 1 is the line number write(rbf_filename, version) end |
#image_header(image_size:, version:, object_count:, global_bytes:) ⇒ Object
23 24 25 26 |
# File 'lib/lignite/assembler.rb', line 23 def image_header(image_size:, version:, object_count:, global_bytes:) SIGNATURE + u32(image_size) + u16(version) + u16(object_count) + u32(global_bytes) end |
#sub(_name, &body) ⇒ Object
90 91 92 93 94 95 96 97 98 99 100 |
# File 'lib/lignite/assembler.rb', line 90 def sub(_name, &body) @locals = Variables.new bodyc = BodyCompiler.new(@globals, @locals, @declarer) bodyc.instance_exec(&body) bodyc.instance_exec do self.return object_end end @objects << RbfObject.subcall(body: bodyc.param_decl_header + bodyc.bytes, local_bytes: @locals.bytesize) end |
#variables ⇒ Object
74 75 76 |
# File 'lib/lignite/assembler.rb', line 74 def variables globals end |
#vmthread(name, &body) ⇒ Object
79 80 81 82 83 84 85 86 87 88 |
# File 'lib/lignite/assembler.rb', line 79 def vmthread(name, &body) @locals = Variables.new bodyc = BodyCompiler.new(@globals, @locals, @declarer) bodyc.instance_exec(&body) bodyc.instance_exec { object_end } logger.debug "VMTHREAD #{name}" logger.debug " size #{bodyc.bytes.bytesize}" logger.debug " " + bin_to_hex(bodyc.bytes) @objects << RbfObject.vmthread(body: bodyc.bytes, local_bytes: @locals.bytesize) end |
#write(rbf_filename, version) ⇒ Object
50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 |
# File 'lib/lignite/assembler.rb', line 50 def write(rbf_filename, version) image_size = HEADER_SIZE + @objects.map(&:size).reduce(0, :+) File.open(rbf_filename, "w") do |f| header = image_header(image_size: image_size, version: version, object_count: @objects.size, global_bytes: @globals.bytesize) f.write(header) object_instruction_offset = HEADER_SIZE + @objects.count * RbfObject::HEADER_SIZE @objects.each do |obj| h = obj.header(object_instruction_offset) f.write(h) object_instruction_offset += obj.body.bytesize end @objects.each do |obj| f.write(obj.body) # align?? end end end |