duby 0.0.2-java
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/History.txt +8 -0
- data/README.txt +39 -0
- data/Rakefile +13 -0
- data/bin/duby +9 -0
- data/bin/dubyc +9 -0
- data/bin/dubyp +9 -0
- data/examples/README +16 -0
- data/examples/appengine/Rakefile +72 -0
- data/examples/appengine/Readme +27 -0
- data/examples/appengine/config.ru +7 -0
- data/examples/appengine/lib/duby/plugin/datastore.rb +171 -0
- data/examples/appengine/src/com/google/appengine/ext/duby/db/Model.duby +132 -0
- data/examples/appengine/src/com/ribrdb/DubyApp.duby +28 -0
- data/examples/appengine/src/com/ribrdb/list.dhtml +15 -0
- data/examples/construction.duby +8 -0
- data/examples/edb.duby +3 -0
- data/examples/fib.duby +24 -0
- data/examples/fields.duby +22 -0
- data/examples/fractal.duby +57 -0
- data/examples/java_thing.duby +13 -0
- data/examples/simple_class.duby +12 -0
- data/examples/swing.duby +20 -0
- data/examples/tak.duby +15 -0
- data/examples/test.edb +9 -0
- data/javalib/JRubyParser.jar +0 -0
- data/lib/duby.rb +168 -0
- data/lib/duby/ast.rb +386 -0
- data/lib/duby/ast/call.rb +145 -0
- data/lib/duby/ast/class.rb +154 -0
- data/lib/duby/ast/flow.rb +332 -0
- data/lib/duby/ast/intrinsics.rb +56 -0
- data/lib/duby/ast/literal.rb +97 -0
- data/lib/duby/ast/local.rb +92 -0
- data/lib/duby/ast/method.rb +244 -0
- data/lib/duby/ast/structure.rb +62 -0
- data/lib/duby/ast/type.rb +93 -0
- data/lib/duby/c/compiler.rb +134 -0
- data/lib/duby/compiler.rb +282 -0
- data/lib/duby/jvm/compiler.rb +766 -0
- data/lib/duby/jvm/method_lookup.rb +193 -0
- data/lib/duby/jvm/source_compiler.rb +605 -0
- data/lib/duby/jvm/source_generator/builder.rb +387 -0
- data/lib/duby/jvm/source_generator/loops.rb +110 -0
- data/lib/duby/jvm/source_generator/precompile.rb +170 -0
- data/lib/duby/jvm/source_generator/typer.rb +11 -0
- data/lib/duby/jvm/typer.rb +131 -0
- data/lib/duby/jvm/types.rb +331 -0
- data/lib/duby/jvm/types/basic_types.rb +19 -0
- data/lib/duby/jvm/types/boolean.rb +11 -0
- data/lib/duby/jvm/types/enumerable.rb +63 -0
- data/lib/duby/jvm/types/factory.rb +155 -0
- data/lib/duby/jvm/types/floats.rb +70 -0
- data/lib/duby/jvm/types/integers.rb +110 -0
- data/lib/duby/jvm/types/intrinsics.rb +230 -0
- data/lib/duby/jvm/types/literals.rb +82 -0
- data/lib/duby/jvm/types/methods.rb +381 -0
- data/lib/duby/jvm/types/number.rb +92 -0
- data/lib/duby/nbcompiler.rb +29 -0
- data/lib/duby/old/compiler_old.rb +845 -0
- data/lib/duby/old/declaration.rb +72 -0
- data/lib/duby/old/mapper.rb +72 -0
- data/lib/duby/old/signature.rb +52 -0
- data/lib/duby/old/typer_old.rb +163 -0
- data/lib/duby/plugin/edb.rb +25 -0
- data/lib/duby/plugin/java.rb +42 -0
- data/lib/duby/plugin/math.rb +84 -0
- data/lib/duby/transform.rb +1028 -0
- data/lib/duby/typer.rb +369 -0
- data/test/TestUser.class +0 -0
- data/test/test_ast.rb +391 -0
- data/test/test_compilation.rb +98 -0
- data/test/test_java_typer.rb +199 -0
- data/test/test_javac_compiler.rb +58 -0
- data/test/test_jvm_compiler.rb +1770 -0
- data/test/test_math_plugin.rb +87 -0
- data/test/test_typer.rb +246 -0
- metadata +156 -0
@@ -0,0 +1,62 @@
|
|
1
|
+
module Duby::AST
|
2
|
+
class Body < Node
|
3
|
+
def initialize(parent, line_number, &block)
|
4
|
+
super(parent, line_number, &block)
|
5
|
+
end
|
6
|
+
|
7
|
+
# Type of a block is the type of its final element
|
8
|
+
def infer(typer)
|
9
|
+
unless @inferred_type
|
10
|
+
if children.size == 0
|
11
|
+
@inferred_type = typer.default_type
|
12
|
+
else
|
13
|
+
children.each {|child| @inferred_type = typer.infer(child)}
|
14
|
+
end
|
15
|
+
|
16
|
+
unless @inferred_type
|
17
|
+
typer.defer(self)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
@inferred_type
|
22
|
+
end
|
23
|
+
|
24
|
+
def <<(node)
|
25
|
+
@children << node
|
26
|
+
node.parent = self
|
27
|
+
end
|
28
|
+
|
29
|
+
def empty?
|
30
|
+
@children.empty?
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
class Block < Node
|
35
|
+
attr_accessor :args, :body
|
36
|
+
|
37
|
+
def initialize(parent, position, &block)
|
38
|
+
super(parent, position, &block)
|
39
|
+
@args, @body = children
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
class Noop < Node
|
44
|
+
def infer(typer)
|
45
|
+
@inferred_type ||= typer.no_type
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
class Script < Node
|
50
|
+
include Scope
|
51
|
+
attr_accessor :body
|
52
|
+
|
53
|
+
def initialize(parent, line_number, &block)
|
54
|
+
super(parent, line_number, children, &block)
|
55
|
+
@body = children[0]
|
56
|
+
end
|
57
|
+
|
58
|
+
def infer(typer)
|
59
|
+
@inferred_type ||= typer.infer(body) || (typer.defer(self); nil)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,93 @@
|
|
1
|
+
module Duby::AST
|
2
|
+
class Import < Node
|
3
|
+
attr_accessor :short
|
4
|
+
attr_accessor :long
|
5
|
+
def initialize(parent, line_number, short, long)
|
6
|
+
@short = short
|
7
|
+
@long = long
|
8
|
+
super(parent, line_number, [])
|
9
|
+
Duby::AST.type_factory.alias(short, long) if Duby::AST.type_factory
|
10
|
+
end
|
11
|
+
|
12
|
+
def to_s
|
13
|
+
"Import(#{short} = #{long})"
|
14
|
+
end
|
15
|
+
|
16
|
+
def infer(typer)
|
17
|
+
# add both the meta and non-meta imports
|
18
|
+
typer.alias_types(short, long)
|
19
|
+
typer.no_type
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
defmacro('import') do |transformer, fcall, parent|
|
24
|
+
args_node = fcall.args_node
|
25
|
+
case args_node
|
26
|
+
when JRubyAst::ArrayNode
|
27
|
+
case args_node.size
|
28
|
+
when 1
|
29
|
+
node = args_node.get(0)
|
30
|
+
case node
|
31
|
+
when JRubyAst::StrNode
|
32
|
+
long = node.value
|
33
|
+
short = long[(long.rindex('.') + 1)..-1]
|
34
|
+
when JRubyAst::CallNode
|
35
|
+
case node.args_node.size
|
36
|
+
when 0
|
37
|
+
pieces = [node.name]
|
38
|
+
while node.kind_of? JRubyAst::CallNode
|
39
|
+
node = node.receiver_node
|
40
|
+
pieces << node.name
|
41
|
+
end
|
42
|
+
long = pieces.reverse.join '.'
|
43
|
+
short = pieces[0]
|
44
|
+
when 1
|
45
|
+
arg = node.args_node.get(0)
|
46
|
+
unless (JRubyAst::FCallNode === arg &&
|
47
|
+
arg.name == 'as' && arg.args_node.size == 1)
|
48
|
+
raise Duby::TransformError.new("unknown import syntax", args_node)
|
49
|
+
end
|
50
|
+
short = arg.args_node.get(0).name
|
51
|
+
pieces = [node.name]
|
52
|
+
while node.kind_of? JRubyAst::CallNode
|
53
|
+
node = node.receiver_node
|
54
|
+
pieces << node.name
|
55
|
+
end
|
56
|
+
long = pieces.reverse.join '.'
|
57
|
+
else
|
58
|
+
raise Duby::TransformError.new("unknown import syntax", args_node)
|
59
|
+
end
|
60
|
+
else
|
61
|
+
raise Duby::TransformError.new("unknown import syntax", args_node)
|
62
|
+
end
|
63
|
+
when 2
|
64
|
+
short = args_node.child_nodes[0].value
|
65
|
+
long = args_node.child_nodes[1].value
|
66
|
+
else
|
67
|
+
raise Duby::TransformError.new("unknown import syntax", args_node)
|
68
|
+
end
|
69
|
+
else
|
70
|
+
raise Duby::TransformError.new("unknown import syntax", args_node)
|
71
|
+
end
|
72
|
+
Import.new(parent, fcall.position, short, long)
|
73
|
+
end
|
74
|
+
|
75
|
+
class EmptyArray < Node
|
76
|
+
attr_accessor :size
|
77
|
+
attr_accessor :component_type
|
78
|
+
def initialize(parent, line_number, type, &block)
|
79
|
+
super(parent, line_number, [])
|
80
|
+
@component_type = type
|
81
|
+
@size = size
|
82
|
+
@inferred_type = Duby::AST::type(type.name, true)
|
83
|
+
|
84
|
+
@size = yield(self)
|
85
|
+
end
|
86
|
+
|
87
|
+
def infer(typer)
|
88
|
+
typer.infer(size)
|
89
|
+
resolved!
|
90
|
+
return @inferred_type
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
@@ -0,0 +1,134 @@
|
|
1
|
+
require 'duby'
|
2
|
+
require 'duby/compiler'
|
3
|
+
|
4
|
+
module Duby
|
5
|
+
module Compiler
|
6
|
+
class C
|
7
|
+
class MathCompiler
|
8
|
+
def call(compiler, call)
|
9
|
+
call.target.compile(compiler)
|
10
|
+
|
11
|
+
compiler.src << " #{call.name} "
|
12
|
+
|
13
|
+
call.parameters.each {|param| param.compile(compiler)}
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
attr_accessor :filename, :src
|
18
|
+
|
19
|
+
def initialize(filename)
|
20
|
+
@filename = filename
|
21
|
+
@src = ""
|
22
|
+
|
23
|
+
self.type_mapper[AST::TypeReference.new(:fixnum)] = "int"
|
24
|
+
|
25
|
+
self.call_compilers[AST::TypeReference.new(:fixnum)] = MathCompiler.new
|
26
|
+
end
|
27
|
+
|
28
|
+
def compile(ast)
|
29
|
+
ast.compile(self)
|
30
|
+
end
|
31
|
+
|
32
|
+
def define_main(body)
|
33
|
+
old_src, @src = @src, "int main(int argc, char **argv)\n{\n"
|
34
|
+
|
35
|
+
body.compile(self)
|
36
|
+
|
37
|
+
@src << "}\n\n"
|
38
|
+
|
39
|
+
@src = old_src + @src
|
40
|
+
end
|
41
|
+
|
42
|
+
def define_method(name, signature, args, body)
|
43
|
+
old_src, @src = @src, "#{type_mapper[signature[:return]]} #{name}("
|
44
|
+
|
45
|
+
args.compile(self)
|
46
|
+
|
47
|
+
@src << ")\n{\n"
|
48
|
+
|
49
|
+
body.compile(self)
|
50
|
+
|
51
|
+
@src << "\n}\n\n"
|
52
|
+
|
53
|
+
@src = old_src + @src
|
54
|
+
end
|
55
|
+
|
56
|
+
def declare_argument(name, type)
|
57
|
+
@src << "#{type_mapper[type]} #{name}"
|
58
|
+
end
|
59
|
+
|
60
|
+
def branch(iff)
|
61
|
+
@src << "if ("
|
62
|
+
|
63
|
+
iff.condition.compile(self)
|
64
|
+
|
65
|
+
@src << ") {"
|
66
|
+
|
67
|
+
iff.body.compile(self)
|
68
|
+
|
69
|
+
if iff.else
|
70
|
+
@src << "} else {"
|
71
|
+
|
72
|
+
iff.else.compile(self)
|
73
|
+
end
|
74
|
+
|
75
|
+
@src << "}"
|
76
|
+
end
|
77
|
+
|
78
|
+
def call(call)
|
79
|
+
call_compilers[call.target.inferred_type].call(self, call)
|
80
|
+
end
|
81
|
+
|
82
|
+
def call_compilers
|
83
|
+
@call_compilers ||= {}
|
84
|
+
end
|
85
|
+
|
86
|
+
def self_call(fcall)
|
87
|
+
@src << "#{fcall.name}("
|
88
|
+
|
89
|
+
fcall.parameters.each {|param| param.compile(self)}
|
90
|
+
|
91
|
+
@src << ")"
|
92
|
+
end
|
93
|
+
|
94
|
+
def local(name, type)
|
95
|
+
@src << name
|
96
|
+
end
|
97
|
+
|
98
|
+
def fixnum(value)
|
99
|
+
@src << value.to_s
|
100
|
+
end
|
101
|
+
|
102
|
+
def newline
|
103
|
+
@src << ";\n"
|
104
|
+
end
|
105
|
+
|
106
|
+
def ret
|
107
|
+
@src << "return "
|
108
|
+
|
109
|
+
yield
|
110
|
+
end
|
111
|
+
|
112
|
+
def generate
|
113
|
+
@src
|
114
|
+
end
|
115
|
+
|
116
|
+
def type_mapper
|
117
|
+
@type_mapper ||= {}
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
if __FILE__ == $0
|
124
|
+
ast = Duby::AST.parse(File.read(ARGV[0]))
|
125
|
+
|
126
|
+
typer = Duby::Typer::Simple.new(:script)
|
127
|
+
ast.infer(typer)
|
128
|
+
typer.resolve(true)
|
129
|
+
|
130
|
+
compiler = Duby::Compiler::C.new("#{ARGV[0]}.c")
|
131
|
+
ast.compile(compiler)
|
132
|
+
|
133
|
+
File.open(compiler.filename, "w") {|file| file.write(compiler.generate)}
|
134
|
+
end
|
@@ -0,0 +1,282 @@
|
|
1
|
+
require 'duby'
|
2
|
+
|
3
|
+
module Duby
|
4
|
+
module AST
|
5
|
+
class Fixnum
|
6
|
+
def compile(compiler, expression)
|
7
|
+
if expression
|
8
|
+
compiler.line(line_number)
|
9
|
+
compiler.fixnum(literal)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
class String
|
15
|
+
def compile(compiler, expression)
|
16
|
+
if expression
|
17
|
+
compiler.line(line_number)
|
18
|
+
compiler.string(literal)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
class Float
|
24
|
+
def compile(compiler, expression)
|
25
|
+
if expression
|
26
|
+
compiler.line(line_number)
|
27
|
+
compiler.float(literal)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
class Boolean
|
33
|
+
def compile(compiler, expression)
|
34
|
+
if expression
|
35
|
+
compiler.line(line_number)
|
36
|
+
compiler.boolean(literal)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
class Array
|
42
|
+
def compile(compiler, expression)
|
43
|
+
compiler.array(self, expression)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
class Body
|
48
|
+
def compile(compiler, expression)
|
49
|
+
compiler.line(line_number)
|
50
|
+
compiler.body(self, expression)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
class Import
|
55
|
+
def compile(compiler, expression)
|
56
|
+
# TODO: what does it mean for import to be an expression?
|
57
|
+
compiler.import(short, long)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
class Constant
|
62
|
+
def compile(compiler, expression)
|
63
|
+
if expression
|
64
|
+
compiler.line(line_number)
|
65
|
+
compiler.constant(self)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
class Print
|
71
|
+
def compile(compiler, expression)
|
72
|
+
# TODO: what does it mean for printline to be an expression?
|
73
|
+
compiler.line(line_number)
|
74
|
+
compiler.print(self)
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
class Local
|
79
|
+
def compile(compiler, expression)
|
80
|
+
if expression
|
81
|
+
compiler.line(line_number)
|
82
|
+
compiler.local(name, inferred_type)
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
class LocalDeclaration
|
88
|
+
def compile(compiler, expression)
|
89
|
+
compiler.line(line_number)
|
90
|
+
compiler.local_declare(name, type)
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
class LocalAssignment
|
95
|
+
def compile(compiler, expression)
|
96
|
+
compiler.line(line_number)
|
97
|
+
compiler.local_assign(name, inferred_type, expression, value)
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
class Script
|
102
|
+
def compile(compiler, expression)
|
103
|
+
# TODO: what does it mean for a script to be an expression? possible?
|
104
|
+
compiler.define_main(body)
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
class MethodDefinition
|
109
|
+
def compile(compiler, expression)
|
110
|
+
# TODO: what does it mean for a method to be an expression?
|
111
|
+
compiler.define_method(self)
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
class ConstructorDefinition
|
116
|
+
def compile(compiler, expression)
|
117
|
+
compiler.constructor(self)
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
class Arguments
|
122
|
+
def compile(compiler, expression)
|
123
|
+
# TODO: what does it mean for a method to be an expression?
|
124
|
+
args.each {|arg| compiler.declare_argument(arg.name, arg.inferred_type)} if args
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
class Noop
|
129
|
+
def compile(compiler, expression)
|
130
|
+
# TODO: what does it mean for a noop to be an expression
|
131
|
+
# nothing
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
class If
|
136
|
+
def compile(compiler, expression)
|
137
|
+
compiler.line(line_number)
|
138
|
+
compiler.branch(self, expression)
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
class Condition
|
143
|
+
def compile(compiler, expression)
|
144
|
+
# TODO: can a condition ever be an expression? I don't think it can...
|
145
|
+
compiler.line(line_number)
|
146
|
+
predicate.compile(compiler, expression)
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
class FunctionalCall
|
151
|
+
def compile(compiler, expression)
|
152
|
+
compiler.line(line_number)
|
153
|
+
compiler.self_call(self, expression)
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
class Call
|
158
|
+
def compile(compiler, expression)
|
159
|
+
compiler.line(line_number)
|
160
|
+
compiler.call(self, expression)
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
164
|
+
class Super
|
165
|
+
def compile(compiler, expression)
|
166
|
+
compiler.line(line_number)
|
167
|
+
compiler.super_call(self, expression)
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
171
|
+
class Loop
|
172
|
+
def compile(compiler, expression)
|
173
|
+
compiler.line(line_number)
|
174
|
+
compiler.loop(self, expression)
|
175
|
+
end
|
176
|
+
end
|
177
|
+
|
178
|
+
class ClassDefinition
|
179
|
+
def compile(compiler, expression)
|
180
|
+
compiler.define_class(self, expression)
|
181
|
+
end
|
182
|
+
end
|
183
|
+
|
184
|
+
class FieldDeclaration
|
185
|
+
def compile(compiler, expression)
|
186
|
+
compiler.field_declare(name, inferred_type, annotations)
|
187
|
+
end
|
188
|
+
end
|
189
|
+
|
190
|
+
class FieldAssignment
|
191
|
+
def compile(compiler, expression)
|
192
|
+
compiler.line(line_number)
|
193
|
+
compiler.field_assign(name, inferred_type, expression, value, annotations)
|
194
|
+
end
|
195
|
+
end
|
196
|
+
|
197
|
+
class Field
|
198
|
+
def compile(compiler, expression)
|
199
|
+
compiler.line(line_number)
|
200
|
+
if expression
|
201
|
+
compiler.field(name, inferred_type, annotations)
|
202
|
+
end
|
203
|
+
end
|
204
|
+
end
|
205
|
+
|
206
|
+
class Return
|
207
|
+
def compile(compiler, expression)
|
208
|
+
compiler.line(line_number)
|
209
|
+
compiler.return(self)
|
210
|
+
end
|
211
|
+
end
|
212
|
+
|
213
|
+
class EmptyArray
|
214
|
+
def compile(compiler, expression)
|
215
|
+
if expression
|
216
|
+
compiler.line(line_number)
|
217
|
+
compiler.empty_array(component_type, size)
|
218
|
+
end
|
219
|
+
end
|
220
|
+
end
|
221
|
+
|
222
|
+
class Null
|
223
|
+
def compile(compiler, expression)
|
224
|
+
if expression
|
225
|
+
compiler.line(line_number)
|
226
|
+
compiler.null
|
227
|
+
end
|
228
|
+
end
|
229
|
+
end
|
230
|
+
|
231
|
+
class Break
|
232
|
+
def compile(compiler, expression)
|
233
|
+
compiler.line(line_number)
|
234
|
+
compiler.break(self)
|
235
|
+
end
|
236
|
+
end
|
237
|
+
|
238
|
+
class Next
|
239
|
+
def compile(compiler, expression)
|
240
|
+
compiler.line(line_number)
|
241
|
+
compiler.next(self)
|
242
|
+
end
|
243
|
+
end
|
244
|
+
|
245
|
+
class Redo
|
246
|
+
def compile(compiler, expression)
|
247
|
+
compiler.line(line_number)
|
248
|
+
compiler.redo(self)
|
249
|
+
end
|
250
|
+
end
|
251
|
+
|
252
|
+
class Raise
|
253
|
+
def compile(compiler, expression)
|
254
|
+
compiler.line(line_number)
|
255
|
+
compiler._raise(@exception)
|
256
|
+
end
|
257
|
+
end
|
258
|
+
|
259
|
+
class Rescue
|
260
|
+
def compile(compiler, expression)
|
261
|
+
compiler.line(line_number)
|
262
|
+
compiler.rescue(self, expression)
|
263
|
+
end
|
264
|
+
end
|
265
|
+
|
266
|
+
class Ensure
|
267
|
+
def compile(compiler, expression)
|
268
|
+
compiler.line(line_number)
|
269
|
+
compiler.ensure(self, expression)
|
270
|
+
end
|
271
|
+
end
|
272
|
+
|
273
|
+
class Self
|
274
|
+
def compile(compiler, expression)
|
275
|
+
if expression
|
276
|
+
compiler.line(line_number)
|
277
|
+
compiler.compile_self
|
278
|
+
end
|
279
|
+
end
|
280
|
+
end
|
281
|
+
end
|
282
|
+
end
|