citrus-compiler 0.8.1 → 0.8.2
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/README.rdoc +2 -2
- data/lib/citrus/compiler/generator.rb +13 -6
- data/lib/citrus/exceptions.rb +14 -8
- data/lib/citrus/nodes.rb +22 -3
- metadata +4 -4
data/README.rdoc
CHANGED
@@ -32,14 +32,14 @@ As you can see, very ruby-like.
|
|
32
32
|
|
33
33
|
Citrus requires the following libraries:
|
34
34
|
|
35
|
-
* LLVM 2.
|
35
|
+
* LLVM 2.9 compiled with shared libraries
|
36
36
|
* On Mac OS X, the quickest way is to use `brew install llvm --shared`
|
37
37
|
* On Linux, there are usually pre-compiled packages
|
38
38
|
* Ruby
|
39
39
|
* Treetop
|
40
40
|
* Ruby LLVM (currently building the source from Jeremy's next branch is required)
|
41
41
|
|
42
|
-
Everything except LLVM is installed when running `gem install citrus-compiler`
|
42
|
+
Everything except LLVM (and presently, ruby-llvm) is installed when running `gem install citrus-compiler`
|
43
43
|
|
44
44
|
== Running
|
45
45
|
|
@@ -22,13 +22,15 @@ module Citrus
|
|
22
22
|
end
|
23
23
|
|
24
24
|
def range(first, last, full)
|
25
|
-
ival =
|
25
|
+
ival = nil
|
26
26
|
ary = @builder.alloca(LLVM::Array(INT, 0))
|
27
|
-
iteration = builder.alloca(INT)
|
28
|
-
builder.store(first, iteration)
|
29
|
-
index = builder.alloca(INT)
|
30
|
-
builder.store(INT.from_i(0), index)
|
27
|
+
iteration = @builder.alloca(INT)
|
28
|
+
@builder.store(first, iteration)
|
29
|
+
index = @builder.alloca(INT)
|
30
|
+
@builder.store(INT.from_i(0), index)
|
31
|
+
ib = @builder.insert_block
|
31
32
|
self.preploop(:while)
|
33
|
+
lb = @builder.insert_block
|
32
34
|
self.while(self.compare(full ? :<= : :<, @builder.load(iteration), last)) do |gw|
|
33
35
|
ival = gw.builder.load(index)
|
34
36
|
val = gw.builder.load(iteration)
|
@@ -37,7 +39,8 @@ module Citrus
|
|
37
39
|
gw.builder.store(gw.equate(:+, val, gw.number(1)), iteration)
|
38
40
|
gw.builder.store(gw.equate(:+, ival, gw.number(1)), index)
|
39
41
|
end
|
40
|
-
|
42
|
+
ival = @builder.load(index)
|
43
|
+
return Array.new(ary, :length => ival)
|
41
44
|
end
|
42
45
|
|
43
46
|
def string(value)
|
@@ -56,6 +59,10 @@ module Citrus
|
|
56
59
|
BOOL.from_i(value ? 1 : 0)
|
57
60
|
end
|
58
61
|
|
62
|
+
def negate(value)
|
63
|
+
@builder.neg(value)
|
64
|
+
end
|
65
|
+
|
59
66
|
def not(value)
|
60
67
|
@builder.not(value)
|
61
68
|
end
|
data/lib/citrus/exceptions.rb
CHANGED
@@ -1,31 +1,37 @@
|
|
1
1
|
module Citrus
|
2
|
-
class SyntaxError <
|
2
|
+
class SyntaxError < ScriptError
|
3
3
|
def initialize
|
4
4
|
line = $parser.failure_line
|
5
5
|
col = $parser.failure_column
|
6
6
|
str = $parser.input.lines.to_a[line-1]
|
7
7
|
str = str.slice(col-1, str.length).delete($/)
|
8
8
|
str = "file end" if str.empty?
|
9
|
-
puts $parser.failure_reason
|
10
9
|
super("Unexpected #{str} at #{line}:#{col}.")
|
11
10
|
end
|
12
11
|
end
|
13
12
|
|
14
|
-
class
|
13
|
+
class StandardError < RuntimeError
|
14
|
+
def initialize(message)
|
15
|
+
line = $parser.input.line_of($pindex)
|
16
|
+
col = $parser.input.column_of($pindex)
|
17
|
+
super("#{message} at #{line}:#{col}.")
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
class NameError < StandardError
|
15
22
|
def initialize(name, index=nil, ff=false)
|
16
|
-
|
17
|
-
line = $parser.input.line_of(index)
|
18
|
-
col = $parser.input.column_of(index)
|
19
|
-
super("Undefined #{ff ? "" : "local variable or "}function '#{name}' at #{line}:#{col}.")
|
23
|
+
super("Undefined #{ff ? "" : "local variable or "}function '#{name}")
|
20
24
|
end
|
21
25
|
end
|
22
26
|
|
23
27
|
class NotFoundError < StandardError
|
24
28
|
def initialize(file)
|
25
|
-
super("No such file or directory - #{file}
|
29
|
+
super("No such file or directory - #{file}")
|
26
30
|
end
|
27
31
|
end
|
28
32
|
|
33
|
+
class ArgumentError < StandardError; end
|
34
|
+
|
29
35
|
def self.error(error)
|
30
36
|
puts("#{error.message} (#{error.class.to_s.split('::').last})")
|
31
37
|
exit(1)
|
data/lib/citrus/nodes.rb
CHANGED
@@ -5,6 +5,7 @@ module Citrus
|
|
5
5
|
end
|
6
6
|
|
7
7
|
def codegen(context)
|
8
|
+
$pindex = self.interval.first
|
8
9
|
end
|
9
10
|
end
|
10
11
|
Node = Treetop::Runtime::SyntaxNode
|
@@ -53,6 +54,18 @@ module Citrus
|
|
53
54
|
end
|
54
55
|
end
|
55
56
|
|
57
|
+
class Neg < Node
|
58
|
+
def codegen(g)
|
59
|
+
g.negate(object.codegen(g))
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
class Not < Node
|
64
|
+
def codegen(g)
|
65
|
+
g.not(object.codegen(g))
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
56
69
|
class Require < Node
|
57
70
|
def codegen(g)
|
58
71
|
file = string.value
|
@@ -72,7 +85,7 @@ module Citrus
|
|
72
85
|
begin
|
73
86
|
g.call(func.value, *arg_values)
|
74
87
|
rescue
|
75
|
-
Citrus.error(NameError.new(func.value,
|
88
|
+
Citrus.error(NameError.new(func.value, true))
|
76
89
|
end
|
77
90
|
end
|
78
91
|
end
|
@@ -124,7 +137,8 @@ module Citrus
|
|
124
137
|
fb = g.block do |gb|
|
125
138
|
else_expressions.each { |e| e.codegen(gb) }
|
126
139
|
end
|
127
|
-
|
140
|
+
cond = condition.is_a?(Expression) ? condition.codegen(g).last : condition.codegen(g)
|
141
|
+
g.condition(cond, tb, fb, elfs)
|
128
142
|
end
|
129
143
|
end
|
130
144
|
|
@@ -194,7 +208,7 @@ module Citrus
|
|
194
208
|
begin
|
195
209
|
g.call(value)
|
196
210
|
rescue NoMethodError
|
197
|
-
Citrus.error(NameError.new(value
|
211
|
+
Citrus.error(NameError.new(value))
|
198
212
|
end
|
199
213
|
end
|
200
214
|
end
|
@@ -208,6 +222,11 @@ module Citrus
|
|
208
222
|
|
209
223
|
class RangeNode < Node
|
210
224
|
def codegen(g)
|
225
|
+
fval = first.codegen(g)
|
226
|
+
lval = last.codegen(g).last
|
227
|
+
unless LLVM::Type(fval) == INT.type && LLVM::Type(lval) == INT.type
|
228
|
+
Citrus.error(ArgumentError.new("Bad value for range"))
|
229
|
+
end
|
211
230
|
g.range(first.codegen(g), last.codegen(g).last, self.full?)
|
212
231
|
end
|
213
232
|
end
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: citrus-compiler
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 59
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 8
|
9
|
-
-
|
10
|
-
version: 0.8.
|
9
|
+
- 2
|
10
|
+
version: 0.8.2
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Mac Malone
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2011-05-
|
18
|
+
date: 2011-05-04 00:00:00 Z
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|
21
21
|
name: treetop
|