myco 0.1.3 → 0.1.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/myco/bootstrap/component.rb +6 -7
- data/lib/myco/bootstrap/instance.rb +14 -9
- data/lib/myco/bootstrap/meme.rb +34 -3
- data/lib/myco/code_loader.rb +17 -34
- data/lib/myco/code_tools/AST/ArgumentAssembly.my +60 -0
- data/lib/myco/code_tools/AST/ArgumentAssembly.my.rb +55 -0
- data/lib/myco/code_tools/AST/ArrayAssembly.my +43 -0
- data/lib/myco/code_tools/AST/ArrayAssembly.my.rb +37 -0
- data/lib/myco/code_tools/AST/BlockArgument.my +25 -0
- data/lib/myco/code_tools/AST/BlockArgument.my.rb +26 -0
- data/lib/myco/code_tools/AST/BlockLiteral.my +104 -0
- data/lib/myco/code_tools/AST/BlockLiteral.my.rb +126 -0
- data/lib/myco/code_tools/AST/BlockParameter.my +25 -0
- data/lib/myco/code_tools/AST/BlockParameter.my.rb +24 -0
- data/lib/myco/code_tools/AST/Body.my +18 -0
- data/lib/myco/code_tools/AST/Body.my.rb +20 -0
- data/lib/myco/code_tools/AST/BranchOperator.my +59 -0
- data/lib/myco/code_tools/AST/BranchOperator.my.rb +87 -0
- data/lib/myco/code_tools/AST/ConstantAccess.my +30 -0
- data/lib/myco/code_tools/AST/ConstantAccess.my.rb +32 -0
- data/lib/myco/code_tools/AST/ConstantAssignment.my +40 -0
- data/lib/myco/code_tools/AST/ConstantAssignment.my.rb +45 -0
- data/lib/myco/code_tools/AST/ConstantDefine.my +30 -0
- data/lib/myco/code_tools/AST/ConstantDefine.my.rb +36 -0
- data/lib/myco/code_tools/AST/ConstantReopen.my +29 -0
- data/lib/myco/code_tools/AST/ConstantReopen.my.rb +35 -0
- data/lib/myco/code_tools/AST/DeclareCategory.my +35 -0
- data/lib/myco/code_tools/AST/DeclareCategory.my.rb +40 -0
- data/lib/myco/code_tools/AST/DeclareDecorator.my +20 -0
- data/lib/myco/code_tools/AST/DeclareDecorator.my.rb +28 -0
- data/lib/myco/code_tools/AST/DeclareFile.my +38 -0
- data/lib/myco/code_tools/AST/DeclareFile.my.rb +53 -0
- data/lib/myco/code_tools/AST/DeclareMeme.my +79 -0
- data/lib/myco/code_tools/AST/DeclareMeme.my.rb +90 -0
- data/lib/myco/code_tools/AST/DeclareObject.my +58 -0
- data/lib/myco/code_tools/AST/DeclareObject.my.rb +67 -0
- data/lib/myco/code_tools/AST/DeclareString.my +26 -0
- data/lib/myco/code_tools/AST/DeclareString.my.rb +30 -0
- data/lib/myco/code_tools/AST/DynamicString.my +21 -0
- data/lib/myco/code_tools/AST/DynamicString.my.rb +22 -0
- data/lib/myco/code_tools/AST/DynamicSymbol.my +22 -0
- data/lib/myco/code_tools/AST/DynamicSymbol.my.rb +26 -0
- data/lib/myco/code_tools/AST/Invoke.my +37 -0
- data/lib/myco/code_tools/AST/Invoke.my.rb +58 -0
- data/lib/myco/code_tools/AST/InvokeMethod.my +19 -0
- data/lib/myco/code_tools/AST/InvokeMethod.my.rb +25 -0
- data/lib/myco/code_tools/AST/KeywordAssembly.my +30 -0
- data/lib/myco/code_tools/AST/KeywordAssembly.my.rb +36 -0
- data/lib/myco/code_tools/AST/LocalVariableAccessAmbiguous.my +22 -0
- data/lib/myco/code_tools/AST/LocalVariableAccessAmbiguous.my.rb +22 -0
- data/lib/myco/code_tools/AST/LocalVariableAssignment.my +20 -0
- data/lib/myco/code_tools/AST/LocalVariableAssignment.my.rb +20 -0
- data/lib/myco/{parser/ast/myco_module_scope.rb → code_tools/AST/MycoModuleScope.my} +32 -39
- data/lib/myco/code_tools/AST/MycoModuleScope.my.rb +82 -0
- data/lib/myco/code_tools/AST/Node.my +67 -0
- data/lib/myco/code_tools/AST/Node.my.rb +84 -0
- data/lib/myco/code_tools/AST/ParameterAssembly.my +248 -0
- data/lib/myco/code_tools/AST/ParameterAssembly.my.rb +314 -0
- data/lib/myco/code_tools/AST/Quest.my +61 -0
- data/lib/myco/code_tools/AST/Quest.my.rb +51 -0
- data/lib/myco/code_tools/AST/Script.my +27 -0
- data/lib/myco/code_tools/AST/Script.my.rb +33 -0
- data/lib/myco/code_tools/AST/SplatValue.my +23 -0
- data/lib/myco/code_tools/AST/SplatValue.my.rb +25 -0
- data/lib/myco/code_tools/AST/StringLiteral.my +17 -0
- data/lib/myco/code_tools/AST/StringLiteral.my.rb +16 -0
- data/lib/myco/code_tools/AST/SymbolLiteral.my +16 -0
- data/lib/myco/code_tools/AST/SymbolLiteral.my.rb +15 -0
- data/lib/myco/{parser/ast → code_tools/AST}/ToRuby.my +89 -90
- data/lib/myco/{parser/ast → code_tools/AST}/ToRuby.my.rb +89 -101
- data/lib/myco/code_tools/AST/misc.my +57 -0
- data/lib/myco/code_tools/AST/misc.my.rb +81 -0
- data/lib/myco/code_tools/AST.my +52 -0
- data/lib/myco/code_tools/AST.my.rb +40 -0
- data/lib/myco/{parser → code_tools/parser}/peg_parser.rb +107 -199
- data/lib/myco/{parser.rb → code_tools/parser.rb} +0 -17
- data/lib/myco/code_tools.rb +5 -0
- data/lib/myco/core/BasicDecorators.my +47 -0
- data/lib/myco/core/BasicDecorators.my.rb +66 -0
- data/lib/myco/core/FileToplevel.my +14 -3
- data/lib/myco/core/FileToplevel.my.rb +27 -12
- data/lib/myco/eval.rb +7 -37
- data/lib/myco/version.rb +1 -4
- data/lib/myco.rb +20 -22
- metadata +74 -66
- data/lib/myco/parser/ast/argument_assembly.rb +0 -76
- data/lib/myco/parser/ast/array_assembly.rb +0 -57
- data/lib/myco/parser/ast/branch_operator.rb +0 -73
- data/lib/myco/parser/ast/constant_access.rb +0 -15
- data/lib/myco/parser/ast/constant_define.rb +0 -40
- data/lib/myco/parser/ast/constant_reopen.rb +0 -46
- data/lib/myco/parser/ast/declare_category.rb +0 -53
- data/lib/myco/parser/ast/declare_decorator.rb +0 -35
- data/lib/myco/parser/ast/declare_file.rb +0 -54
- data/lib/myco/parser/ast/declare_meme.rb +0 -86
- data/lib/myco/parser/ast/declare_object.rb +0 -77
- data/lib/myco/parser/ast/declare_string.rb +0 -37
- data/lib/myco/parser/ast/invoke.rb +0 -48
- data/lib/myco/parser/ast/invoke_method.rb +0 -28
- data/lib/myco/parser/ast/local_variable_access_ambiguous.rb +0 -34
- data/lib/myco/parser/ast/misc.rb +0 -156
- data/lib/myco/parser/ast/quest.rb +0 -82
- data/lib/myco/parser/ast.rb +0 -21
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c497fbe2e87f23f8cea7374510cbac8a7aefdd6a
|
4
|
+
data.tar.gz: 519dc6fbe9d381ee9478ca46fa71fefecd5318b8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6e7dc8c64ae6d9a26b421ba7a45dc5a0ec44f969519e128ebe680701c39d68dd70b6dde54743e99c2c5fb0b2267696c4e119095cead9c41254b1de50d28556a4
|
7
|
+
data.tar.gz: 05cf18931bdf1d8632dcf9d7d88e09cc014b8af1e6a86d70f8a2b74395c8210c36d999cb25f4fc0096380618132e09887d4af23aa0130a73724055e0b7029b3d
|
@@ -18,7 +18,7 @@ module Myco
|
|
18
18
|
elsif @__name__
|
19
19
|
@__name__.to_s
|
20
20
|
else
|
21
|
-
"#{@super_components.map(&:to_s).join(',')}" \
|
21
|
+
"#{(@super_components || []).map(&:to_s).join(',')}" \
|
22
22
|
"(#{@basename}:#{@line.to_s} 0x#{object_id.to_s 16})"
|
23
23
|
end
|
24
24
|
end
|
@@ -64,13 +64,12 @@ module Myco
|
|
64
64
|
all_categories = Hash.new { |h,k| h[k] = Array.new }
|
65
65
|
|
66
66
|
super_components.each do |other|
|
67
|
-
raise TypeError, "Got non-Component in supers for new Component: "\
|
68
|
-
"#{super_components.inspect}" \
|
69
|
-
unless other.is_a? Component
|
70
|
-
|
71
67
|
this.include other
|
72
|
-
|
73
|
-
|
68
|
+
|
69
|
+
if other.is_a? Component
|
70
|
+
other.categories.each do |name, cat|
|
71
|
+
all_categories[name] << cat
|
72
|
+
end
|
74
73
|
end
|
75
74
|
end
|
76
75
|
|
@@ -3,20 +3,16 @@ module Myco
|
|
3
3
|
module InstanceMethods
|
4
4
|
include ::Kernel
|
5
5
|
|
6
|
-
# TODO: clean this up
|
7
|
-
prepend (::Module.new {
|
8
|
-
def method_missing name, *args
|
9
|
-
msg = "#{to_s} has no method called '#{name}'"
|
10
|
-
::Kernel.raise ::NoMethodError.new(msg, name, args)
|
11
|
-
end
|
12
|
-
})
|
13
|
-
|
14
6
|
def to_s
|
15
7
|
"#<#{@component.to_s}>"
|
16
8
|
end
|
17
9
|
|
18
10
|
def inspect
|
19
|
-
|
11
|
+
vars = (instance_variables - [:@component]).map { |var|
|
12
|
+
[var.to_s[1..-1], instance_variable_get(var).inspect].join(": ")
|
13
|
+
}
|
14
|
+
vars = vars.any? ? (" " + vars.join(", ")) : ""
|
15
|
+
"#<#{@component.to_s}#{vars}>"
|
20
16
|
end
|
21
17
|
|
22
18
|
# TODO: remove (for now it makes debugging easier with RSpec)
|
@@ -41,5 +37,14 @@ module Myco
|
|
41
37
|
|
42
38
|
class Instance < ::BasicObject
|
43
39
|
include InstanceMethods
|
40
|
+
|
41
|
+
# # TODO: clean this up
|
42
|
+
# prepend (::Module.new {
|
43
|
+
def method_missing name, *args
|
44
|
+
msg = "#{to_s} has no method called '#{name}'"
|
45
|
+
::Kernel.raise ::NoMethodError.new(msg, name, args)
|
46
|
+
end
|
47
|
+
# })
|
48
|
+
|
44
49
|
end
|
45
50
|
end
|
data/lib/myco/bootstrap/meme.rb
CHANGED
@@ -47,6 +47,8 @@ module Myco
|
|
47
47
|
attr_accessor :cache
|
48
48
|
attr_accessor :var
|
49
49
|
attr_accessor :expose
|
50
|
+
attr_accessor :setter
|
51
|
+
attr_accessor :getter
|
50
52
|
|
51
53
|
attr_reader :metadata
|
52
54
|
|
@@ -133,6 +135,12 @@ module Myco
|
|
133
135
|
bind_var_getter
|
134
136
|
bind_var_setter
|
135
137
|
@effective_body = @target.instance_method(@name).executable
|
138
|
+
elsif @getter
|
139
|
+
bind_var_getter
|
140
|
+
@effective_body = @target.instance_method(@name).executable
|
141
|
+
elsif @setter
|
142
|
+
bind_var_setter
|
143
|
+
@effective_body = @target.instance_method(@name).executable
|
136
144
|
elsif @cache
|
137
145
|
bind_cache_method
|
138
146
|
@effective_body = @target.instance_method(@name).executable
|
@@ -272,7 +280,7 @@ module Myco
|
|
272
280
|
g.make_array 0
|
273
281
|
g.push_nil
|
274
282
|
g.send :invoke, 5
|
275
|
-
g.set_ivar(@name)
|
283
|
+
g.set_ivar(:"@#{@name}")
|
276
284
|
|
277
285
|
g.push_true
|
278
286
|
g.set_ivar(:"__#{@name}_defined__")
|
@@ -280,14 +288,27 @@ module Myco
|
|
280
288
|
g.goto(ret)
|
281
289
|
|
282
290
|
get.set!
|
283
|
-
g.push_ivar(@name)
|
291
|
+
g.push_ivar(:"@#{@name}")
|
284
292
|
|
285
293
|
ret.set!
|
294
|
+
|
295
|
+
# If this meme has a getter defined, use it
|
296
|
+
if self.getter
|
297
|
+
g.push_self
|
298
|
+
g.push_local(1) # meme
|
299
|
+
g.send(:getter, 0)
|
300
|
+
g.rotate(3)
|
301
|
+
g.send(:call_on_object, 2)
|
302
|
+
end
|
303
|
+
|
286
304
|
g.ret
|
287
305
|
end
|
288
306
|
end
|
289
307
|
|
290
308
|
def bind_var_setter
|
309
|
+
# TODO: move this bytecode generation to a helper method
|
310
|
+
meme = self
|
311
|
+
|
291
312
|
# TODO: move this bytecode generation to a helper method
|
292
313
|
target.dynamic_method :"#{@name}=", '(myco_internal)' do |g|
|
293
314
|
g.total_args = 1
|
@@ -298,7 +319,17 @@ module Myco
|
|
298
319
|
g.pop
|
299
320
|
|
300
321
|
g.push_local 0 # value
|
301
|
-
|
322
|
+
|
323
|
+
# If this meme has a setter defined, use it
|
324
|
+
if meme.setter
|
325
|
+
g.push_self
|
326
|
+
g.push_literal(meme)
|
327
|
+
g.send(:setter, 0)
|
328
|
+
g.rotate(3)
|
329
|
+
g.send(:call_on_object, 2)
|
330
|
+
end
|
331
|
+
|
332
|
+
g.set_ivar(:"@#{@name}")
|
302
333
|
|
303
334
|
g.ret
|
304
335
|
end
|
data/lib/myco/code_loader.rb
CHANGED
@@ -16,12 +16,6 @@ module Myco
|
|
16
16
|
# Use generated ruby files only when Myco files cannot be found or loaded.
|
17
17
|
self.precedence = [:rbc, :myco, :rb]
|
18
18
|
|
19
|
-
# TODO: a more elegant solution than env vars
|
20
|
-
# Emit ruby if env var indicates
|
21
|
-
# Load from ruby exclusively if env var indicates
|
22
|
-
self.emit_rb = true if ENV['MYCO_TO_RUBY'] == 'PRE'
|
23
|
-
self.precedence = [:myco] if ENV['MYCO_TO_RUBY'] == 'PRE'
|
24
|
-
|
25
19
|
# Try to resolve the given file path
|
26
20
|
# in the current working directory or in the given load paths.
|
27
21
|
def self.resolve_file path, load_paths=[]
|
@@ -136,10 +130,10 @@ module Myco
|
|
136
130
|
def make_ast
|
137
131
|
@string || make_string
|
138
132
|
|
139
|
-
parser =
|
133
|
+
parser = new_parser
|
140
134
|
ast = parser.parse_string(@string)
|
141
135
|
|
142
|
-
ast =
|
136
|
+
ast = ast_root_for(ast)
|
143
137
|
ast.file = filename.to_sym
|
144
138
|
ast.variable_scope = @variable_scope
|
145
139
|
|
@@ -149,7 +143,7 @@ module Myco
|
|
149
143
|
def make_generator
|
150
144
|
@ast || make_ast
|
151
145
|
|
152
|
-
g =
|
146
|
+
g = new_generator
|
153
147
|
@ast.bytecode(g)
|
154
148
|
|
155
149
|
g.close
|
@@ -206,7 +200,7 @@ module Myco
|
|
206
200
|
return nil unless filename
|
207
201
|
|
208
202
|
compiled_file_type.dump(
|
209
|
-
@compiled_code, filename, Rubinius::Signature,
|
203
|
+
@compiled_code, filename, Rubinius::Signature, Rubinius::RUBY_LIB_VERSION
|
210
204
|
)
|
211
205
|
end
|
212
206
|
|
@@ -249,22 +243,16 @@ module Myco
|
|
249
243
|
end
|
250
244
|
|
251
245
|
class MycoLoader < AbstractLoader
|
252
|
-
def
|
253
|
-
|
254
|
-
raise NotImplementedError if ENV['MYCO_TO_RUBY'] == 'POST'
|
255
|
-
super
|
256
|
-
end
|
257
|
-
|
258
|
-
def ast_root_type
|
259
|
-
Myco::ToolSet::AST::EvalExpression
|
246
|
+
def ast_root_for(body)
|
247
|
+
Myco::ToolSet::AST::Script.new(body: body)
|
260
248
|
end
|
261
249
|
|
262
|
-
def
|
263
|
-
Myco::ToolSet::Parser
|
250
|
+
def new_parser
|
251
|
+
Myco::ToolSet::Parser.new
|
264
252
|
end
|
265
253
|
|
266
|
-
def
|
267
|
-
Myco::ToolSet::Generator
|
254
|
+
def new_generator
|
255
|
+
Myco::ToolSet::Generator.new
|
268
256
|
end
|
269
257
|
|
270
258
|
def compiled_file_type
|
@@ -281,16 +269,16 @@ module Myco
|
|
281
269
|
super *args
|
282
270
|
end
|
283
271
|
|
284
|
-
def
|
285
|
-
Rubinius::ToolSets::Runtime::AST::EvalExpression
|
272
|
+
def ast_root_for(body)
|
273
|
+
Rubinius::ToolSets::Runtime::AST::EvalExpression.new(body)
|
286
274
|
end
|
287
275
|
|
288
|
-
def
|
289
|
-
Rubinius::ToolSets::Runtime::Melbourne
|
276
|
+
def new_parser
|
277
|
+
Rubinius::ToolSets::Runtime::Melbourne.new(@filename, @line, [])
|
290
278
|
end
|
291
279
|
|
292
|
-
def
|
293
|
-
Rubinius::ToolSets::Runtime::Generator
|
280
|
+
def new_generator
|
281
|
+
Rubinius::ToolSets::Runtime::Generator.new
|
294
282
|
end
|
295
283
|
|
296
284
|
def compiled_file_type
|
@@ -304,17 +292,12 @@ module Myco
|
|
304
292
|
def emit_rb!; nil end
|
305
293
|
def emit_rbc!; nil end
|
306
294
|
|
307
|
-
def initialize *args
|
308
|
-
# TODO: a more elegant solution than env vars
|
309
|
-
raise NotImplementedError if ENV['MYCO_TO_RUBY'] == 'POST'
|
310
|
-
super
|
311
|
-
end
|
312
|
-
|
313
295
|
def make_compiled_code
|
314
296
|
begin
|
315
297
|
@compiled_code = primitive_load_file \
|
316
298
|
@filename, Rubinius::Signature, Rubinius::RUBY_LIB_VERSION
|
317
299
|
rescue Rubinius::InvalidRBC => e
|
300
|
+
warn e.message
|
318
301
|
File.delete @filename
|
319
302
|
raise e
|
320
303
|
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
|
2
|
+
CodeTools::AST << {
|
3
|
+
|
4
|
+
ArgumentAssembly < Node {
|
5
|
+
var body, var block
|
6
|
+
|
7
|
+
Form: [:argass, :body]
|
8
|
+
|
9
|
+
setter body: |given_body| {
|
10
|
+
given_body.last.is_a?(BlockArgument) && (self.block = given_body.pop)
|
11
|
+
given_body
|
12
|
+
}
|
13
|
+
|
14
|
+
# All items before the first SplatValue
|
15
|
+
pre_group:
|
16
|
+
self.body.take_while |item| { !item.is_a?(SplatValue) }
|
17
|
+
|
18
|
+
# All items after and including the first SplatValue
|
19
|
+
post_group:
|
20
|
+
self.body.drop_while |item| { !item.is_a?(SplatValue) }
|
21
|
+
|
22
|
+
# Symbol of bytecode operation to use for send
|
23
|
+
send_op: {
|
24
|
+
self.body.detect |item| { item.is_a?(SplatValue) } &? (
|
25
|
+
:send_with_splat
|
26
|
+
) ?? (self.block &? ( # TODO: better elsif construction
|
27
|
+
:send_with_block
|
28
|
+
) ?? (
|
29
|
+
:send
|
30
|
+
))
|
31
|
+
}
|
32
|
+
|
33
|
+
# Number of arguments to use for send operation
|
34
|
+
send_count:
|
35
|
+
pre_group.size
|
36
|
+
|
37
|
+
splat_bytecode: |g| ArrayAssembly.new(
|
38
|
+
line: self.line
|
39
|
+
body: post_group
|
40
|
+
).bytecode(g)
|
41
|
+
|
42
|
+
block_bytecode: |g|
|
43
|
+
self.block &? self.block.bytecode(g) ?? g.push_null
|
44
|
+
|
45
|
+
bytecode: |g| {
|
46
|
+
pos(g)
|
47
|
+
|
48
|
+
pre_group.each |item| { item.bytecode(g) }
|
49
|
+
|
50
|
+
send_op == :send_with_splat && (
|
51
|
+
splat_bytecode(g)
|
52
|
+
block_bytecode(g)
|
53
|
+
)
|
54
|
+
send_op == :send_with_block && (
|
55
|
+
block_bytecode(g)
|
56
|
+
)
|
57
|
+
}
|
58
|
+
}
|
59
|
+
|
60
|
+
}
|
@@ -0,0 +1,55 @@
|
|
1
|
+
|
2
|
+
::Myco::Component.new([::Myco::FileToplevel], ::Myco.cscope.for_method_definition, __FILE__, __LINE__)
|
3
|
+
.tap { |__c__| __c__.__last__ = __c__.component_eval {(::Myco.find_constant(:CodeTools)::AST.component_eval {(::Myco.cscope.for_method_definition.const_set(:ArgumentAssembly, ::Myco::Component.new([::Myco.find_constant(:Node)], ::Myco.cscope.for_method_definition, __FILE__, __LINE__)
|
4
|
+
.tap { |__c__| __c__.__last__ = __c__.component_eval {(
|
5
|
+
declare_meme(:body, [[:var, []]], nil, ::Myco.cscope.dup) { |*| nil}
|
6
|
+
declare_meme(:block, [[:var, []]], nil, ::Myco.cscope.dup) { |*| nil}
|
7
|
+
::Myco.cscope.for_method_definition.const_set(:Form, ([
|
8
|
+
:argass,
|
9
|
+
:body
|
10
|
+
]))
|
11
|
+
declare_meme(:body, [[:setter, []]], nil, ::Myco.cscope.dup) { |given_body| (
|
12
|
+
::Myco.branch_op(:"&&", given_body.last.__send__(
|
13
|
+
:is_a?,
|
14
|
+
::Myco.find_constant(:BlockArgument)
|
15
|
+
)) {self.__send__(
|
16
|
+
:block=,
|
17
|
+
given_body.pop
|
18
|
+
)}
|
19
|
+
given_body
|
20
|
+
)}
|
21
|
+
declare_meme(:pre_group, [], nil, ::Myco.cscope.dup) { |*| (self.body.take_while { |item| (item.__send__(
|
22
|
+
:is_a?,
|
23
|
+
::Myco.find_constant(:SplatValue)
|
24
|
+
).__send__(:!))})}
|
25
|
+
declare_meme(:post_group, [], nil, ::Myco.cscope.dup) { |*| (self.body.drop_while { |item| (item.__send__(
|
26
|
+
:is_a?,
|
27
|
+
::Myco.find_constant(:SplatValue)
|
28
|
+
).__send__(:!))})}
|
29
|
+
declare_meme(:send_op, [], nil, ::Myco.cscope.dup) { |*| (::Myco.branch_op(:"??", ::Myco.branch_op(:"&?", self.body.detect { |item| (item.__send__(
|
30
|
+
:is_a?,
|
31
|
+
::Myco.find_constant(:SplatValue)
|
32
|
+
))}) {:send_with_splat}) {::Myco.branch_op(:"??", ::Myco.branch_op(:"&?", self.block) {:send_with_block}) {:send}})}
|
33
|
+
declare_meme(:send_count, [], nil, ::Myco.cscope.dup) { |*| (self.pre_group.size)}
|
34
|
+
declare_meme(:splat_bytecode, [], nil, ::Myco.cscope.dup) { |g| (::Myco.find_constant(:ArrayAssembly).new({
|
35
|
+
:line => self.line,
|
36
|
+
:body => self.post_group
|
37
|
+
}).bytecode(g))}
|
38
|
+
declare_meme(:block_bytecode, [], nil, ::Myco.cscope.dup) { |g| (::Myco.branch_op(:"??", ::Myco.branch_op(:"&?", self.block) {self.block.bytecode(g)}) {g.push_null})}
|
39
|
+
declare_meme(:bytecode, [], nil, ::Myco.cscope.dup) { |g| (
|
40
|
+
self.pos(g)
|
41
|
+
self.pre_group.each { |item| (item.bytecode(g))}
|
42
|
+
::Myco.branch_op(:"&&", self.send_op.__send__(
|
43
|
+
:==,
|
44
|
+
:send_with_splat
|
45
|
+
)) {(
|
46
|
+
self.splat_bytecode(g)
|
47
|
+
self.block_bytecode(g)
|
48
|
+
)}
|
49
|
+
::Myco.branch_op(:"&&", self.send_op.__send__(
|
50
|
+
:==,
|
51
|
+
:send_with_block
|
52
|
+
)) {self.block_bytecode(g)}
|
53
|
+
)}
|
54
|
+
)}})
|
55
|
+
.tap { |__c__| __c__.__name__ = :ArgumentAssembly })})}}.instance
|
@@ -0,0 +1,43 @@
|
|
1
|
+
|
2
|
+
CodeTools::AST << {
|
3
|
+
|
4
|
+
ArrayAssembly < Node {
|
5
|
+
var body
|
6
|
+
|
7
|
+
Form: [:arrass, :body]
|
8
|
+
|
9
|
+
bytecode: |g| {
|
10
|
+
pos(g)
|
11
|
+
|
12
|
+
self.body.empty? &? (
|
13
|
+
g.make_array(0)
|
14
|
+
) ?? (
|
15
|
+
# Group the self.body into chunks of splats and non-splats
|
16
|
+
chunked = self.body.chunk |item| { item.is_a?(SplatValue) }
|
17
|
+
|
18
|
+
# Each SplatValue outputs the bytecode of a single array
|
19
|
+
# Non-SplatValues are grouped to output the bytecode of
|
20
|
+
# a single array for each contiguous group. Along the way, the
|
21
|
+
# arrays are concatenated to form one final array on the stack.
|
22
|
+
first_bytecode = true
|
23
|
+
chunked.each |is_splat_group, group| {
|
24
|
+
is_splat_group &? (
|
25
|
+
group.each |item| {
|
26
|
+
item.bytecode(g)
|
27
|
+
first_bytecode || g.send(:concat, 1)
|
28
|
+
first_bytecode = false
|
29
|
+
}
|
30
|
+
) ?? (
|
31
|
+
group.each |item| {
|
32
|
+
item.bytecode(g)
|
33
|
+
}
|
34
|
+
g.make_array(group.size)
|
35
|
+
first_bytecode || g.send(:concat, 1)
|
36
|
+
first_bytecode = false
|
37
|
+
)
|
38
|
+
}
|
39
|
+
)
|
40
|
+
}
|
41
|
+
}
|
42
|
+
|
43
|
+
}
|
@@ -0,0 +1,37 @@
|
|
1
|
+
|
2
|
+
::Myco::Component.new([::Myco::FileToplevel], ::Myco.cscope.for_method_definition, __FILE__, __LINE__)
|
3
|
+
.tap { |__c__| __c__.__last__ = __c__.component_eval {(::Myco.find_constant(:CodeTools)::AST.component_eval {(::Myco.cscope.for_method_definition.const_set(:ArrayAssembly, ::Myco::Component.new([::Myco.find_constant(:Node)], ::Myco.cscope.for_method_definition, __FILE__, __LINE__)
|
4
|
+
.tap { |__c__| __c__.__last__ = __c__.component_eval {(
|
5
|
+
declare_meme(:body, [[:var, []]], nil, ::Myco.cscope.dup) { |*| nil}
|
6
|
+
::Myco.cscope.for_method_definition.const_set(:Form, ([
|
7
|
+
:arrass,
|
8
|
+
:body
|
9
|
+
]))
|
10
|
+
declare_meme(:bytecode, [], nil, ::Myco.cscope.dup) { |g| (
|
11
|
+
self.pos(g)
|
12
|
+
::Myco.branch_op(:"??", ::Myco.branch_op(:"&?", self.body.__send__(:empty?)) {g.make_array(0)}) {(
|
13
|
+
chunked = self.body.chunk { |item| (item.__send__(
|
14
|
+
:is_a?,
|
15
|
+
::Myco.find_constant(:SplatValue)
|
16
|
+
))}
|
17
|
+
first_bytecode = true
|
18
|
+
chunked.each { |is_splat_group, group| (::Myco.branch_op(:"??", ::Myco.branch_op(:"&?", is_splat_group) {group.each { |item| (
|
19
|
+
item.bytecode(g)
|
20
|
+
::Myco.branch_op(:"||", first_bytecode) {g.send(
|
21
|
+
:concat,
|
22
|
+
1
|
23
|
+
)}
|
24
|
+
first_bytecode = false
|
25
|
+
)}}) {(
|
26
|
+
group.each { |item| (item.bytecode(g))}
|
27
|
+
g.make_array(group.size)
|
28
|
+
::Myco.branch_op(:"||", first_bytecode) {g.send(
|
29
|
+
:concat,
|
30
|
+
1
|
31
|
+
)}
|
32
|
+
first_bytecode = false
|
33
|
+
)})}
|
34
|
+
)}
|
35
|
+
)}
|
36
|
+
)}})
|
37
|
+
.tap { |__c__| __c__.__name__ = :ArrayAssembly })})}}.instance
|
@@ -0,0 +1,25 @@
|
|
1
|
+
|
2
|
+
CodeTools::AST << {
|
3
|
+
|
4
|
+
BlockArgument < Node {
|
5
|
+
var body
|
6
|
+
|
7
|
+
Form: [:blkarg, :body]
|
8
|
+
|
9
|
+
bytecode: |g| {
|
10
|
+
self.body.bytecode(g)
|
11
|
+
|
12
|
+
done_label = g.new_label
|
13
|
+
g.dup
|
14
|
+
g.is_nil
|
15
|
+
g.goto_if_true(done_label)
|
16
|
+
|
17
|
+
g.push_cpath_top; g.find_const(:"Proc")
|
18
|
+
g.swap
|
19
|
+
g.send(:"__from_block__", 1)
|
20
|
+
|
21
|
+
done_label.set!
|
22
|
+
}
|
23
|
+
}
|
24
|
+
|
25
|
+
}
|
@@ -0,0 +1,26 @@
|
|
1
|
+
|
2
|
+
::Myco::Component.new([::Myco::FileToplevel], ::Myco.cscope.for_method_definition, __FILE__, __LINE__)
|
3
|
+
.tap { |__c__| __c__.__last__ = __c__.component_eval {(::Myco.find_constant(:CodeTools)::AST.component_eval {(::Myco.cscope.for_method_definition.const_set(:BlockArgument, ::Myco::Component.new([::Myco.find_constant(:Node)], ::Myco.cscope.for_method_definition, __FILE__, __LINE__)
|
4
|
+
.tap { |__c__| __c__.__last__ = __c__.component_eval {(
|
5
|
+
declare_meme(:body, [[:var, []]], nil, ::Myco.cscope.dup) { |*| nil}
|
6
|
+
::Myco.cscope.for_method_definition.const_set(:Form, ([
|
7
|
+
:blkarg,
|
8
|
+
:body
|
9
|
+
]))
|
10
|
+
declare_meme(:bytecode, [], nil, ::Myco.cscope.dup) { |g| (
|
11
|
+
self.body.bytecode(g)
|
12
|
+
done_label = g.new_label
|
13
|
+
g.dup
|
14
|
+
g.is_nil
|
15
|
+
g.goto_if_true(done_label)
|
16
|
+
g.push_cpath_top
|
17
|
+
g.find_const(:Proc)
|
18
|
+
g.swap
|
19
|
+
g.send(
|
20
|
+
:__from_block__,
|
21
|
+
1
|
22
|
+
)
|
23
|
+
done_label.__send__(:set!)
|
24
|
+
)}
|
25
|
+
)}})
|
26
|
+
.tap { |__c__| __c__.__name__ = :BlockArgument })})}}.instance
|
@@ -0,0 +1,104 @@
|
|
1
|
+
|
2
|
+
CodeTools::AST << {
|
3
|
+
|
4
|
+
BlockLiteral < CodeTools::Compiler::LocalVariables, Node {
|
5
|
+
var parameters, var body
|
6
|
+
var parent # TODO: investigate removing
|
7
|
+
|
8
|
+
Form: [:blklit, :parameters, :body]
|
9
|
+
|
10
|
+
CompilerClass: CodeTools::Compiler # TODO: remove this
|
11
|
+
|
12
|
+
setter parameters: |given| given || ParameterAssembly.new(line:self.line)
|
13
|
+
setter body: |given| given || NullLiteral.new(line:self.line)
|
14
|
+
|
15
|
+
locals: self.body.?locals.?body.map(&:value) ?? null
|
16
|
+
|
17
|
+
block_local?: |name|
|
18
|
+
locals.?include?(name) ?? false
|
19
|
+
|
20
|
+
module?: false
|
21
|
+
|
22
|
+
nest_scope: |scope| scope.parent = self
|
23
|
+
|
24
|
+
# Look up a local variable in this block's scope.
|
25
|
+
search_local: |name| {
|
26
|
+
(variable = self.variables[name]) &? (
|
27
|
+
variable.nested_reference
|
28
|
+
) ?? (self.block_local?(name) &? (
|
29
|
+
self.new_local(name)
|
30
|
+
) ?? ((reference = self.parent.search_local(name)) &? (
|
31
|
+
reference.depth = reference.depth + 1
|
32
|
+
reference
|
33
|
+
) ?? (
|
34
|
+
null
|
35
|
+
)))
|
36
|
+
}
|
37
|
+
|
38
|
+
# Assign a slot number to a local variable access node.
|
39
|
+
# TODO: remove this method in favor of using search_local in all cases instead.
|
40
|
+
assign_local_reference: |var| {
|
41
|
+
var.variable = (variable = self.variables[var.name]) &? (
|
42
|
+
variable.reference
|
43
|
+
) ?? (self.block_local?(var.name) &? (
|
44
|
+
variable = self.new_local(var.name)
|
45
|
+
variable.reference
|
46
|
+
) ?? ((reference = self.parent.search_local(var.name)) &? (
|
47
|
+
reference.depth = reference.depth + 1
|
48
|
+
reference
|
49
|
+
) ?? (
|
50
|
+
variable = self.new_local(var.name)
|
51
|
+
variable.reference
|
52
|
+
)))
|
53
|
+
}
|
54
|
+
|
55
|
+
new_local: |name| {
|
56
|
+
self.variables[name] = \
|
57
|
+
self.variables[name] || CompilerClass::LocalVariable.new(allocate_slot)
|
58
|
+
}
|
59
|
+
|
60
|
+
new_nested_local: |name| new_local(name).nested_reference
|
61
|
+
|
62
|
+
bytecode: |g| {
|
63
|
+
pos(g)
|
64
|
+
|
65
|
+
state = g.state
|
66
|
+
state.scope.nest_scope(self)
|
67
|
+
|
68
|
+
blk = new_block_generator(g, self.parameters)
|
69
|
+
|
70
|
+
blk.push_state(self)
|
71
|
+
blk.definition_line(self.line)
|
72
|
+
blk.state.push_super(state.super)
|
73
|
+
blk.state.push_eval(state.eval)
|
74
|
+
|
75
|
+
blk.state.push_name(blk.name)
|
76
|
+
|
77
|
+
# Push line info down.
|
78
|
+
pos(blk)
|
79
|
+
|
80
|
+
self.parameters.bytecode(blk)
|
81
|
+
|
82
|
+
blk.state.push_block
|
83
|
+
blk.push_modifiers
|
84
|
+
blk.break = null
|
85
|
+
blk.next = null
|
86
|
+
blk.redo = blk.new_label
|
87
|
+
blk.redo.set!
|
88
|
+
|
89
|
+
self.body.bytecode(blk)
|
90
|
+
|
91
|
+
blk.pop_modifiers
|
92
|
+
blk.state.pop_block
|
93
|
+
blk.ret
|
94
|
+
blk.close
|
95
|
+
blk.pop_state
|
96
|
+
|
97
|
+
blk.local_count = local_count
|
98
|
+
blk.local_names = local_names
|
99
|
+
|
100
|
+
g.create_block(blk)
|
101
|
+
}
|
102
|
+
}
|
103
|
+
|
104
|
+
}
|