Class: Lignite::Assembler

Inherits:
Object
  • Object
show all
Includes:
Bytes, Logger, VariableDeclarer
Defined in:
lib/lignite/assembler.rb

Overview

Assemble a complete RBF program file.

The compilation has two passes:

  1. pass1, Declaration

  2. 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

Instance Method Summary collapse

Methods included from VariableDeclarer

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

Methods included from Logger

default_logger, #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

#globalsVariables (readonly)

Returns:



31
32
33
# File 'lib/lignite/assembler.rb', line 31

def globals
  @globals
end

#objectsArray<RbfObject> (readonly)

Returns:



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)?

Parameters:

  • rb_filename (String)

    input

  • rbf_filename (String)

    output



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

#variablesObject



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