voodoo 0.6.2 → 0.6.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/lib/voodoo/generators/mips_gas_generator.rb +17 -1
- data/lib/voodoo/generators/nasm_elf_generator.rb +30 -21
- data/lib/voodoo/generators/nasm_generator.rb +31 -1
- data/lib/voodoo/parser.rb +16 -1
- metadata +17 -6
- data/bin/ast.rb +0 -47
@@ -163,6 +163,11 @@ module Voodoo
|
|
163
163
|
[:div, :mod, :sub].member?(op)
|
164
164
|
end
|
165
165
|
|
166
|
+
# Test if a value is an at-expression
|
167
|
+
def at_expr? value
|
168
|
+
value.respond_to?(:[]) && value[0] == :'@'
|
169
|
+
end
|
170
|
+
|
166
171
|
# Emit function prologue and declare _formals_ as function arguments
|
167
172
|
def begin_function formals, nlocals
|
168
173
|
if @environment != @top_level
|
@@ -530,6 +535,13 @@ module Voodoo
|
|
530
535
|
end
|
531
536
|
end
|
532
537
|
|
538
|
+
# Load the value at the given address.
|
539
|
+
def load_at address, register = @TEMPORARY
|
540
|
+
load_value_into_register address, register
|
541
|
+
emit "lw #{register}, 0(#{register})\n"
|
542
|
+
register
|
543
|
+
end
|
544
|
+
|
533
545
|
# Load a value into a register.
|
534
546
|
# Returns the name of the register.
|
535
547
|
# If the value was already in a register, the name of that
|
@@ -573,6 +585,8 @@ module Voodoo
|
|
573
585
|
emit "addiu #{register}, %lo(#{x})\n"
|
574
586
|
return register
|
575
587
|
end
|
588
|
+
elsif at_expr? x
|
589
|
+
load_at x[1], register
|
576
590
|
else
|
577
591
|
raise "Don't know how to load #{x.inspect}"
|
578
592
|
end
|
@@ -728,7 +742,9 @@ module Voodoo
|
|
728
742
|
def string value
|
729
743
|
code = ''
|
730
744
|
value.each_byte do |b|
|
731
|
-
if b
|
745
|
+
if b == 92
|
746
|
+
code << "\\\\"
|
747
|
+
elsif b >= 32 && b < 127 && b != 34
|
732
748
|
code << b.chr
|
733
749
|
else
|
734
750
|
code << sprintf("\\%03o", b)
|
@@ -31,29 +31,38 @@ module Voodoo
|
|
31
31
|
end
|
32
32
|
|
33
33
|
Tempfile.open(base + '.asm') do |nasmfile|
|
34
|
-
|
35
|
-
elffile
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
34
|
+
begin
|
35
|
+
Tempfile.open(base + '.o') do |elffile|
|
36
|
+
begin
|
37
|
+
elffile.close
|
38
|
+
# Write NASM code to nsamfile
|
39
|
+
@nasmgenerator.write nasmfile
|
40
|
+
nasmfile.close
|
41
|
+
# Find out the name of the nasm executable
|
42
|
+
if ENV.has_key? 'NASM'
|
43
|
+
nasm = ENV['NASM']
|
44
|
+
elsif ENV.has_key? 'YASM'
|
45
|
+
nasm = ENV['YASM']
|
46
|
+
else
|
47
|
+
nasm = Voodoo::Config.nasm_command
|
48
|
+
end
|
49
|
+
# Invoke nasm on nasmfile
|
50
|
+
command = "#{nasm} #{@nasm_extra_args}" +
|
51
|
+
" -o #{shell_encode elffile.path}" +
|
52
|
+
" #{shell_encode nasmfile.path}"
|
53
|
+
if system(command)
|
54
|
+
write_file_to_io elffile.path, io
|
55
|
+
else
|
56
|
+
raise "Command (#{command}) failed " +
|
57
|
+
" with status #{$?.exitstatus}"
|
58
|
+
end
|
59
|
+
ensure
|
60
|
+
elffile.unlink
|
61
|
+
end
|
46
62
|
end
|
47
|
-
|
48
|
-
|
49
|
-
" -o #{shell_encode elffile.path}" +
|
50
|
-
" #{shell_encode nasmfile.path}"
|
51
|
-
if system(command)
|
52
|
-
write_file_to_io elffile.path, io
|
53
|
-
end
|
54
|
-
elffile.unlink
|
63
|
+
ensure
|
64
|
+
nasmfile.unlink
|
55
65
|
end
|
56
|
-
nasmfile.unlink
|
57
66
|
end
|
58
67
|
end
|
59
68
|
end
|
@@ -88,7 +88,7 @@ module Voodoo
|
|
88
88
|
code = ''
|
89
89
|
in_quote = false
|
90
90
|
value.each_byte do |b|
|
91
|
-
if b >= 32 && b <
|
91
|
+
if b >= 32 && b < 127 && b != 39
|
92
92
|
if in_quote
|
93
93
|
code << b.chr
|
94
94
|
else
|
@@ -185,6 +185,11 @@ module Voodoo
|
|
185
185
|
# == Value Classification
|
186
186
|
#
|
187
187
|
|
188
|
+
# Test if a value is an at-expression
|
189
|
+
def at_expr? value
|
190
|
+
value.respond_to?(:[]) && value[0] == :'@'
|
191
|
+
end
|
192
|
+
|
188
193
|
# Test if op is a binary operation
|
189
194
|
def binop? op
|
190
195
|
[:div, :mod, :sub].member?(op) || symmetric_operation?(op)
|
@@ -271,6 +276,17 @@ module Voodoo
|
|
271
276
|
end
|
272
277
|
end
|
273
278
|
|
279
|
+
# Load the value at the given address.
|
280
|
+
# Invoking this code may clobber @BX.
|
281
|
+
def load_at address, reg = @SCRATCH_REG
|
282
|
+
if integer?(address) || global?(address)
|
283
|
+
"[#{address}]"
|
284
|
+
else
|
285
|
+
load_value_into_register address, @BX
|
286
|
+
"[#{@BX}]"
|
287
|
+
end
|
288
|
+
end
|
289
|
+
|
274
290
|
# Load the value associated with the given symbol.
|
275
291
|
# Returns a string that can be used to refer to the loaded value.
|
276
292
|
def load_symbol symbol, reg = @SCRATCH_REG
|
@@ -298,6 +314,20 @@ module Voodoo
|
|
298
314
|
value
|
299
315
|
elsif symbol? value
|
300
316
|
load_symbol value, reg
|
317
|
+
elsif at_expr? value
|
318
|
+
load_at value[1], reg
|
319
|
+
else
|
320
|
+
raise "Don't know how to load #{value.inspect}"
|
321
|
+
end
|
322
|
+
end
|
323
|
+
|
324
|
+
# Load a value into a register.
|
325
|
+
def load_value_into_register value, register
|
326
|
+
load_code = load_value(value), register
|
327
|
+
if load_code == register.to_s
|
328
|
+
load_code
|
329
|
+
else
|
330
|
+
"mov #{register}, #{load_code}\n"
|
301
331
|
end
|
302
332
|
end
|
303
333
|
|
data/lib/voodoo/parser.rb
CHANGED
@@ -108,8 +108,23 @@ module Voodoo
|
|
108
108
|
when /\s/
|
109
109
|
# Skip whitespace
|
110
110
|
consume
|
111
|
+
when '@'
|
112
|
+
# Parse at-expression.
|
113
|
+
# '@' must be followed by a number or symbol.
|
114
|
+
consume
|
115
|
+
case lookahead
|
116
|
+
when /\d|-/
|
117
|
+
expr = parse_number
|
118
|
+
when /\w|\\/
|
119
|
+
expr = parse_symbol
|
120
|
+
else
|
121
|
+
raise "Invalid character (#{@lookahead.chr.inspect})" +
|
122
|
+
" at #{@line}:#{@char}; expecting number or symbol"
|
123
|
+
end
|
124
|
+
words << [:'@', expr]
|
111
125
|
else
|
112
|
-
raise "Invalid character (#{@lookahead})
|
126
|
+
raise "Invalid character (#{@lookahead.chr.inspect})" +
|
127
|
+
" at #{@line}:#{@char}"
|
113
128
|
end
|
114
129
|
end
|
115
130
|
|
metadata
CHANGED
@@ -1,7 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: voodoo
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
|
4
|
+
hash: 1
|
5
|
+
prerelease: false
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 6
|
9
|
+
- 3
|
10
|
+
version: 0.6.3
|
5
11
|
platform: ruby
|
6
12
|
authors:
|
7
13
|
- Robbert Haarman
|
@@ -9,7 +15,7 @@ autorequire:
|
|
9
15
|
bindir: bin
|
10
16
|
cert_chain: []
|
11
17
|
|
12
|
-
date: 2010-
|
18
|
+
date: 2010-11-21 00:00:00 +01:00
|
13
19
|
default_executable:
|
14
20
|
dependencies: []
|
15
21
|
|
@@ -29,7 +35,6 @@ extensions: []
|
|
29
35
|
extra_rdoc_files: []
|
30
36
|
|
31
37
|
files:
|
32
|
-
- bin/ast.rb
|
33
38
|
- bin/voodooc
|
34
39
|
- lib/voodoo.rb
|
35
40
|
- lib/voodoo/parser.rb
|
@@ -61,21 +66,27 @@ rdoc_options:
|
|
61
66
|
require_paths:
|
62
67
|
- lib
|
63
68
|
required_ruby_version: !ruby/object:Gem::Requirement
|
69
|
+
none: false
|
64
70
|
requirements:
|
65
71
|
- - ">="
|
66
72
|
- !ruby/object:Gem::Version
|
73
|
+
hash: 3
|
74
|
+
segments:
|
75
|
+
- 0
|
67
76
|
version: "0"
|
68
|
-
version:
|
69
77
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
78
|
+
none: false
|
70
79
|
requirements:
|
71
80
|
- - ">="
|
72
81
|
- !ruby/object:Gem::Version
|
82
|
+
hash: 3
|
83
|
+
segments:
|
84
|
+
- 0
|
73
85
|
version: "0"
|
74
|
-
version:
|
75
86
|
requirements: []
|
76
87
|
|
77
88
|
rubyforge_project: voodoo
|
78
|
-
rubygems_version: 1.3.
|
89
|
+
rubygems_version: 1.3.7
|
79
90
|
signing_key:
|
80
91
|
specification_version: 3
|
81
92
|
summary: Compiler for the Voodoo programming language
|
data/bin/ast.rb
DELETED
@@ -1,47 +0,0 @@
|
|
1
|
-
module Ast
|
2
|
-
# A program consists of zero or more elements,
|
3
|
-
# each one of which can be a label, an action,
|
4
|
-
# a function definition, or a comment
|
5
|
-
class Program
|
6
|
-
def initialize elements
|
7
|
-
@elements = elements
|
8
|
-
end
|
9
|
-
attr_accessor :elements
|
10
|
-
end
|
11
|
-
|
12
|
-
# A comment contains text
|
13
|
-
class Comment
|
14
|
-
def initialize text
|
15
|
-
@text = text
|
16
|
-
end
|
17
|
-
attr_accessor :text
|
18
|
-
end
|
19
|
-
|
20
|
-
# A label contains text
|
21
|
-
class Label
|
22
|
-
def initialize text
|
23
|
-
@text = text
|
24
|
-
end
|
25
|
-
attr_accessor :text
|
26
|
-
end
|
27
|
-
|
28
|
-
# A function definition has an argument list and contains
|
29
|
-
# a number of actions and/or comments
|
30
|
-
class Function
|
31
|
-
def initialize args, actions
|
32
|
-
@args = args
|
33
|
-
@statements = actions
|
34
|
-
end
|
35
|
-
attr_accessor :args, :actions
|
36
|
-
end
|
37
|
-
|
38
|
-
# An action contains an operation and zero or more
|
39
|
-
# arguments
|
40
|
-
class Action
|
41
|
-
def initialize op, args
|
42
|
-
@op = op
|
43
|
-
@args = args
|
44
|
-
end
|
45
|
-
attr_accessor :op, :args
|
46
|
-
end
|
47
|
-
end
|