Class: Haxor::Compiler::Core

Inherits:
Object
  • Object
show all
Defined in:
lib/haxor/compiler/core.rb

Instance Method Summary collapse

Constructor Details

#initialize ⇒ Core

Returns a new instance of Core.



4
5
6
7
8
9
10
11
# File 'lib/haxor/compiler/core.rb', line 4

def initialize
  @units = []
  @cmds = {}
  @autolabel = 0
  @prev_sections = []

  bind_cmd 'section', self, :cmd_section
end

Instance Method Details

#add(token) ⇒ Object



75
76
77
# File 'lib/haxor/compiler/core.rb', line 75

def add(token)
  @unit.add token
end

#bind_cmd(cmd, object, method) ⇒ Object



19
20
21
22
23
24
# File 'lib/haxor/compiler/core.rb', line 19

def bind_cmd(cmd, object, method)
  @cmds[cmd] = {
    object: object,
    method: method
  }
end

#cmd_section(name) ⇒ Object



26
27
28
# File 'lib/haxor/compiler/core.rb', line 26

def cmd_section(name)
  @unit.section = name[1..-1].to_sym
end

#compile(filename) ⇒ Object



55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
# File 'lib/haxor/compiler/core.rb', line 55

def compile(filename)
  input = File.read(filename, encoding: 'ASCII-8BIT')

  @unit = Unit.new

  input.lines.map(&:chomp).each_with_index do |line, index|
    next if line.empty?

    tmp = line.split ' ', 2
    cmd = tmp[0]
    args = split_arguments(tmp[1] || '')

    fail "Unknown command #{cmd} in line #{index}." unless @cmds.key? cmd

    @cmds[cmd][:object].send(@cmds[cmd][:method], *args)
  end

  @unit.save(filename + '.u')
end

#offset?(value) ⇒ Boolean

Returns:

  • (Boolean)


123
124
125
126
# File 'lib/haxor/compiler/core.rb', line 123

def offset?(value)
  return false unless value.is_a? String
  value.start_with?('[') && value.end_with?(']')
end

#offset_flags(a, b = nil) ⇒ Object



116
117
118
119
120
121
# File 'lib/haxor/compiler/core.rb', line 116

def offset_flags(a, b = nil)
  result = 0
  result |= Consts::OPCODE_FLG_DA if offset?(a)
  result |= Consts::OPCODE_FLG_DB if offset?(b)
  result
end

#parse_number(value) ⇒ Object



79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
# File 'lib/haxor/compiler/core.rb', line 79

def parse_number(value)
  md = value.match(/\A([-+]?[0-9]+[0-9A-F]*)([bhd]?)\z/)
  fail if md.nil?

  case md[2]
  when 'b'
    base = 2
  when 'h'
    base = 16
  when 'd'
  else
    base = 10
  end

  md[1].to_i(base)
end

#parse_value(value) ⇒ Object



96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
# File 'lib/haxor/compiler/core.rb', line 96

def parse_value(value)
  value = strip_offset value

  begin
    number = parse_number(value)
    @autolabel += 1
    label = "__autolabel_#{@autolabel}"

    old_section = @unit.section
    @unit.section = :data
    add Token::Label.new(label)
    add Token::Int64.new(number)
    @unit.section = old_section

    add Token::Pointer.new(label)
  rescue
    add Token::Pointer.new(value)
  end
end

#register_unit(unit) ⇒ Object



13
14
15
16
17
# File 'lib/haxor/compiler/core.rb', line 13

def register_unit(unit)
  @units << unit
  unit.compiler = self
  unit.register
end

#split_arguments(string) ⇒ Object

this is ugly and must be reworked



31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
# File 'lib/haxor/compiler/core.rb', line 31

def split_arguments(string)
  inside_quotes = false
  splits = []
  string.each_char.with_index(0) do |x, i|
    if x == '"' && string[i - 1] != '\\'
      inside_quotes ^= true
    end

    if x == ',' && !inside_quotes
      splits << i
    end
  end

  splits << string.size

  last_x = 0
  args = []
  splits.each do |x|
    args << string[last_x...x]
    last_x = x + 1
  end
  args.map!(&:strip).delete_if { |x| x.length == 0 }
end

#strip_offset(value) ⇒ Object



128
129
130
131
# File 'lib/haxor/compiler/core.rb', line 128

def strip_offset(value)
  return value[1...-1] if offset?(value)
  value
end