myco 0.1.0.dev → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (95) hide show
  1. checksums.yaml +7 -7
  2. data/LICENSE +1 -1
  3. data/README.md +79 -0
  4. data/lib/myco/backtrace.rb +1 -1
  5. data/lib/myco/bootstrap/component.rb +78 -39
  6. data/lib/myco/bootstrap/find_constant.rb +12 -1
  7. data/lib/myco/bootstrap/instance.rb +5 -12
  8. data/lib/myco/bootstrap/meme.rb +176 -28
  9. data/lib/myco/bootstrap.my +8 -7
  10. data/lib/myco/code_loader.rb +332 -0
  11. data/lib/myco/command/inoculate.my +83 -0
  12. data/lib/myco/command.my +26 -26
  13. data/lib/myco/core/BasicDecorators.my +62 -0
  14. data/lib/myco/core/BasicObject.my +12 -34
  15. data/lib/myco/core/Decorator.my +1 -0
  16. data/lib/myco/core/FileToplevel.my +0 -3
  17. data/lib/myco/core/Myco.my +4 -0
  18. data/lib/myco/core/Object.my +6 -4
  19. data/lib/myco/eval.rb +17 -18
  20. data/lib/myco/misc.rb +16 -0
  21. data/lib/myco/parser/ast/argument_assembly.rb +76 -0
  22. data/lib/myco/parser/ast/array_assembly.rb +57 -0
  23. data/lib/myco/parser/ast/branch_operator.rb +73 -0
  24. data/lib/myco/parser/ast/constant_access.rb +4 -18
  25. data/lib/myco/parser/ast/constant_define.rb +3 -3
  26. data/lib/myco/parser/ast/constant_reopen.rb +12 -13
  27. data/lib/myco/parser/ast/declare_category.rb +8 -6
  28. data/lib/myco/parser/ast/declare_decorator.rb +4 -4
  29. data/lib/myco/parser/ast/declare_file.rb +4 -4
  30. data/lib/myco/parser/ast/declare_meme.rb +53 -11
  31. data/lib/myco/parser/ast/declare_object.rb +9 -7
  32. data/lib/myco/parser/ast/declare_string.rb +5 -5
  33. data/lib/myco/parser/ast/invoke.rb +18 -36
  34. data/lib/myco/parser/ast/invoke_method.rb +28 -0
  35. data/lib/myco/parser/ast/local_variable_access_ambiguous.rb +9 -13
  36. data/lib/myco/parser/ast/misc.rb +128 -33
  37. data/lib/myco/parser/ast/myco_module_scope.rb +26 -0
  38. data/lib/myco/parser/ast/quest.rb +3 -3
  39. data/lib/myco/parser/ast/to_ruby/array_assembly.rb +15 -0
  40. data/lib/myco/parser/ast/to_ruby/block.rb +14 -0
  41. data/lib/myco/parser/ast/to_ruby/block_pass.rb +6 -0
  42. data/lib/myco/parser/ast/to_ruby/branch_operator.rb +9 -0
  43. data/lib/myco/parser/ast/to_ruby/constant_access.rb +10 -0
  44. data/lib/myco/parser/ast/to_ruby/constant_assignment.rb +6 -0
  45. data/lib/myco/parser/ast/to_ruby/constant_define.rb +9 -0
  46. data/lib/myco/parser/ast/to_ruby/constant_reopen.rb +6 -0
  47. data/lib/myco/parser/ast/to_ruby/declare_category.rb +7 -0
  48. data/lib/myco/parser/ast/to_ruby/declare_decorator.rb +6 -0
  49. data/lib/myco/parser/ast/to_ruby/declare_file.rb +6 -0
  50. data/lib/myco/parser/ast/to_ruby/declare_meme.rb +16 -0
  51. data/lib/myco/parser/ast/to_ruby/declare_object.rb +8 -0
  52. data/lib/myco/parser/ast/to_ruby/declare_string.rb +6 -0
  53. data/lib/myco/parser/ast/to_ruby/dynamic_string.rb +14 -0
  54. data/lib/myco/parser/ast/to_ruby/dynamic_symbol.rb +7 -0
  55. data/lib/myco/parser/ast/to_ruby/eval_expression.rb +6 -0
  56. data/lib/myco/parser/ast/to_ruby/false_literal.rb +6 -0
  57. data/lib/myco/parser/ast/to_ruby/hash_literal.rb +16 -0
  58. data/lib/myco/parser/ast/to_ruby/invoke.rb +6 -0
  59. data/lib/myco/parser/ast/to_ruby/invoke_method.rb +35 -0
  60. data/lib/myco/parser/ast/to_ruby/iter.rb +10 -0
  61. data/lib/myco/parser/ast/to_ruby/local_variable_access_ambiguous.rb +16 -0
  62. data/lib/myco/parser/ast/to_ruby/local_variable_assignment.rb +8 -0
  63. data/lib/myco/parser/ast/to_ruby/myco_module_scope.rb +8 -0
  64. data/lib/myco/parser/ast/to_ruby/null_literal.rb +6 -0
  65. data/lib/myco/parser/ast/to_ruby/parameters.rb +60 -0
  66. data/lib/myco/parser/ast/to_ruby/quest.rb +13 -0
  67. data/lib/myco/parser/ast/to_ruby/return.rb +7 -0
  68. data/lib/myco/parser/ast/to_ruby/scoped_constant.rb +11 -0
  69. data/lib/myco/parser/ast/to_ruby/self.rb +6 -0
  70. data/lib/myco/parser/ast/to_ruby/splat_value.rb +33 -0
  71. data/lib/myco/parser/ast/to_ruby/string_literal.rb +6 -0
  72. data/lib/myco/parser/ast/to_ruby/symbol_literal.rb +6 -0
  73. data/lib/myco/parser/ast/to_ruby/toplevel_constant.rb +11 -0
  74. data/lib/myco/parser/ast/to_ruby/true_literal.rb +6 -0
  75. data/lib/myco/parser/ast/to_ruby/void_literal.rb +6 -0
  76. data/lib/myco/parser/ast/to_ruby.rb +138 -0
  77. data/lib/myco/parser/ast.rb +6 -0
  78. data/lib/myco/parser/peg_parser.rb +361 -181
  79. data/lib/myco/parser.rb +27 -11
  80. data/lib/myco/tools/BasicCommand.my +42 -0
  81. data/lib/myco/tools/Generator.my +18 -0
  82. data/lib/myco/toolset.rb +0 -3
  83. data/lib/myco/version.rb +1 -4
  84. data/lib/myco.rb +2 -0
  85. metadata +230 -160
  86. data/lib/myco/parser/builder.output +0 -3995
  87. data/lib/myco/parser/builder.racc +0 -585
  88. data/lib/myco/parser/builder.rb +0 -1592
  89. data/lib/myco/parser/lexer.rb +0 -2306
  90. data/lib/myco/parser/lexer.rl +0 -393
  91. data/lib/myco/parser/lexer_char_classes.rl +0 -56
  92. data/lib/myco/parser/lexer_common.rb +0 -95
  93. data/lib/myco/parser/lexer_skeleton.rl +0 -154
  94. data/lib/myco/parser/peg_parser.kpeg +0 -759
  95. data/lib/myco/tools/OptionParser.my +0 -38
data/lib/myco/misc.rb ADDED
@@ -0,0 +1,16 @@
1
+
2
+ module Myco
3
+
4
+ # Logical branching operator with lazy evaluation of right hand
5
+ def self.branch_op type, left
6
+ case type
7
+ when :"&&"; return left if left.false?
8
+ when :"||"; return left unless left.false?
9
+ when :"??"; return left unless left.void?
10
+ when :"&?"; return ::Myco::Void if left.false?
11
+ when :"|?"; return ::Myco::Void unless left.false?
12
+ end
13
+ return yield # evaluate and return right hand
14
+ end
15
+
16
+ end
@@ -0,0 +1,76 @@
1
+
2
+ module CodeTools::AST
3
+
4
+ module BuilderMethods
5
+ def argass loc, body
6
+ ArgumentAssembly.new loc.line, body
7
+ end
8
+ end
9
+
10
+ class ArgumentAssembly < Node
11
+ attr_accessor :body, :block
12
+
13
+ def initialize(line, body, block=nil)
14
+ @line = line
15
+ @body = body
16
+
17
+ # TODO: error for multiple block arguments
18
+ @block = body.pop if body.last.is_a?(BlockPass)
19
+ end
20
+
21
+ # All items before the first SplatValue
22
+ def pre_group
23
+ @body.take_while { |item| !item.is_a?(SplatValue) }
24
+ end
25
+
26
+ # All items after and including the first SplatValue
27
+ def post_group
28
+ @body.drop_while { |item| !item.is_a?(SplatValue) }
29
+ end
30
+
31
+ # Symbol of bytecode operation to use for send
32
+ def send_op
33
+ if @body.detect { |item| item.is_a?(SplatValue) }
34
+ :send_with_splat
35
+ elsif @block
36
+ :send_with_block
37
+ else
38
+ :send
39
+ end
40
+ end
41
+
42
+ # Number of arguments to use for send operation
43
+ def send_count
44
+ pre_group.size
45
+ end
46
+
47
+ def splat_bytecode(g)
48
+ ArrayAssembly.new(@line, post_group).bytecode(g)
49
+ end
50
+
51
+ def block_bytecode(g)
52
+ @block ? @block.bytecode(g) : g.push_nil
53
+ end
54
+
55
+ def bytecode(g)
56
+ pos(g)
57
+
58
+ pre_group.each { |item| item.bytecode(g) }
59
+
60
+ case send_op
61
+ when :send_with_splat
62
+ splat_bytecode(g)
63
+ block_bytecode(g)
64
+ when :send_with_block
65
+ block_bytecode(g)
66
+ end
67
+ end
68
+
69
+ def to_sexp
70
+ sexp = [:arglist] + @body.map(&:to_sexp)
71
+ sexp.push(@block.to_sexp) if @block
72
+ sexp
73
+ end
74
+ end
75
+
76
+ end
@@ -0,0 +1,57 @@
1
+
2
+ module CodeTools::AST
3
+
4
+ module BuilderMethods
5
+ def arrass loc, body
6
+ ArrayAssembly.new loc.line, body
7
+ end
8
+ end
9
+
10
+ class ArrayAssembly < Node
11
+ attr_accessor :body
12
+
13
+ def initialize(line, body)
14
+ @line = line
15
+ @body = body
16
+ end
17
+
18
+ def bytecode(g)
19
+ pos(g)
20
+
21
+ if @body.empty?
22
+ g.make_array(0)
23
+ return
24
+ end
25
+
26
+ # Group the @body into chunks of splats and non-splats
27
+ chunked = @body.chunk { |item| item.is_a?(SplatValue) }
28
+
29
+ # Each SplatValue outputs the bytecode of a single array
30
+ # Non-SplatValues are grouped to output the bytecode of
31
+ # a single array for each contiguous group. Along the way, the
32
+ # arrays are concatenated to form one final array on the stack.
33
+ first_bytecode = true
34
+ chunked.each do |is_splat_group, group|
35
+ if is_splat_group
36
+ group.each { |item|
37
+ item.bytecode(g)
38
+ g.send(:concat, 1) unless first_bytecode
39
+ first_bytecode = false
40
+ }
41
+ else
42
+ group.each { |item|
43
+ item.bytecode(g)
44
+ }
45
+ g.make_array(group.size)
46
+ g.send(:concat, 1) unless first_bytecode
47
+ first_bytecode = false
48
+ end
49
+ end
50
+ end
51
+
52
+ def to_sexp
53
+ [:array] + @body.map(&:to_sexp)
54
+ end
55
+ end
56
+
57
+ end
@@ -0,0 +1,73 @@
1
+
2
+ module CodeTools::AST
3
+
4
+ module BuilderMethods
5
+ def branch_op loc, type, left, right
6
+ BranchOperator.new loc.line, type, left, right
7
+ end
8
+ end
9
+
10
+ class BranchOperator < Node
11
+ attr_accessor :type
12
+ attr_accessor :left
13
+ attr_accessor :right
14
+
15
+ def initialize line, type, left, right
16
+ @line = line
17
+ @type = type
18
+ @left = left
19
+ @right = right
20
+ end
21
+
22
+ def bytecode g
23
+ pos(g)
24
+
25
+ done_label = g.new_label
26
+ right_label = g.new_label
27
+ can_push_void = false
28
+
29
+ @left.bytecode(g)
30
+
31
+ case type
32
+ when :"&&"
33
+ g.dup_top
34
+ g.send :false?, 0
35
+ g.goto_if_true done_label
36
+ g.pop
37
+ when :"||"
38
+ g.dup_top
39
+ g.send :false?, 0
40
+ g.goto_if_false done_label
41
+ g.pop
42
+ when :"??"
43
+ g.dup_top
44
+ g.send :void?, 0
45
+ g.goto_if_false done_label
46
+ g.pop
47
+ when :"&?"
48
+ g.send :false?, 0
49
+ g.goto_if_false right_label
50
+ otherwise_push_void = true
51
+ when :"|?"
52
+ g.send :false?, 0
53
+ g.goto_if_true right_label
54
+ otherwise_push_void = true
55
+ end
56
+
57
+ if otherwise_push_void
58
+ g.push_void
59
+ g.goto done_label
60
+
61
+ right_label.set!
62
+ end
63
+
64
+ @right.bytecode(g)
65
+ done_label.set!
66
+ end
67
+
68
+ def to_sexp
69
+ [:branch_op, @type, @left.to_sexp, @right.to_sexp]
70
+ end
71
+ end
72
+
73
+ end
@@ -1,29 +1,15 @@
1
1
 
2
2
  module CodeTools::AST
3
-
4
- # Monkey patch original to use methods of ::Myco to lookup constants
3
+ # Monkey patch original to use ::Myco to look up constants
5
4
  class ConstantAccess
6
5
  def bytecode(g)
7
6
  pos(g)
8
7
 
9
- if g.state.op_asgn? # TODO: is this branch unnecessary with Myco AST?
10
- g.push_cpath_top
11
- g.find_const :Myco
8
+ g.push_cpath_top
9
+ g.find_const :Myco
12
10
  g.push_literal @name
13
11
  g.push_scope
14
- g.send :find_constant_for_op_asign_or, 2
15
- else
16
- if @top_level
17
- g.push_cpath_top
18
- g.find_const @name
19
- else
20
- g.push_cpath_top
21
- g.find_const :Myco
22
- g.push_literal @name
23
- g.push_scope
24
- g.send :find_constant, 2
25
- end
26
- end
12
+ g.send :find_constant, 2
27
13
  end
28
14
  end
29
15
  end
@@ -1,9 +1,9 @@
1
1
 
2
2
  module CodeTools::AST
3
3
 
4
- module ProcessorMethods
5
- def process_cdefn line, name, object
6
- ConstantDefine.new line, name, object
4
+ module BuilderMethods
5
+ def cdefn loc, name, object
6
+ ConstantDefine.new loc.line, name, object
7
7
  end
8
8
  end
9
9
 
@@ -1,23 +1,22 @@
1
1
 
2
+ require_relative 'myco_module_scope'
3
+
4
+
2
5
  module CodeTools::AST
3
6
 
4
- module ProcessorMethods
5
- def process_copen line, name, body
6
- ConstantReopen.new line, name, body
7
+ module BuilderMethods
8
+ def copen loc, name, body
9
+ ConstantReopen.new loc.line, name, body
7
10
  end
8
11
  end
9
12
 
10
- class ConstantReopenScope < ModuleScope
11
- def initialize(line, body)
12
- @line = line
13
- @name = :ConstantReopenScope # TODO: remove/fix
14
- @body = body
15
- end
16
-
17
- def bytecode(g)
18
- pos(g)
13
+ class ConstantReopenScope < MycoModuleScope
14
+ def body_bytecode g
15
+ g.push_scope
16
+ g.send :set_myco_component, 0
17
+ g.pop
19
18
 
20
- attach_and_call g, :__component_init__, true
19
+ @body.bytecode g
21
20
  end
22
21
  end
23
22
 
@@ -4,9 +4,9 @@ require_relative 'myco_module_scope'
4
4
 
5
5
  module CodeTools::AST
6
6
 
7
- module ProcessorMethods
8
- def process_category line, name, body
9
- DeclareCategory.new line, name, body
7
+ module BuilderMethods
8
+ def category loc, name, body
9
+ DeclareCategory.new loc.line, name, body
10
10
  end
11
11
  end
12
12
 
@@ -33,18 +33,20 @@ module CodeTools::AST
33
33
  [:category, @name.value, @body.to_sexp]
34
34
  end
35
35
 
36
+ def scope_implementation
37
+ DeclareCategoryScope.new @line, @body
38
+ end
39
+
36
40
  def bytecode g
37
41
  pos(g)
38
42
 
39
- scope = DeclareCategoryScope.new @line, @body
40
-
41
43
  ##
42
44
  # category = self.__category__ @name
43
45
  g.push_self
44
46
  g.push_literal @name.value
45
47
  g.send :__category__, 1
46
48
 
47
- scope.bytecode g
49
+ scope_implementation.bytecode g
48
50
  end
49
51
  end
50
52
 
@@ -1,9 +1,9 @@
1
1
 
2
2
  module CodeTools::AST
3
3
 
4
- module ProcessorMethods
5
- def process_deco line, name, arguments
6
- DeclareDecorator.new line, name, arguments
4
+ module BuilderMethods
5
+ def deco loc, name, arguments
6
+ DeclareDecorator.new loc.line, name, arguments
7
7
  end
8
8
  end
9
9
 
@@ -13,7 +13,7 @@ module CodeTools::AST
13
13
  def initialize line, name, arguments
14
14
  @line = line
15
15
  @name = name
16
- @arguments = arguments || ArrayLiteral.new(@line, [])
16
+ @arguments = arguments || ArrayAssembly.new(@line, [])
17
17
  end
18
18
 
19
19
  def to_sexp
@@ -1,9 +1,9 @@
1
1
 
2
2
  module CodeTools::AST
3
3
 
4
- module ProcessorMethods
5
- def process_declfile line, body
6
- DeclareFile.new line, body
4
+ module BuilderMethods
5
+ def declfile loc, body
6
+ DeclareFile.new loc.line, body
7
7
  end
8
8
  end
9
9
 
@@ -38,7 +38,7 @@ module CodeTools::AST
38
38
  def implementation
39
39
  myco = ToplevelConstant.new @line, :Myco
40
40
  type = ScopedConstant.new @line, myco, :FileToplevel
41
- types = ArrayLiteral.new @line, [type]
41
+ types = ArrayAssembly.new @line, [type]
42
42
  decl = DeclareObject.new @line, types, @body
43
43
  decl.scope_type = DeclareFileScope
44
44
  decl
@@ -1,20 +1,58 @@
1
1
 
2
2
  module CodeTools::AST
3
3
 
4
- module ProcessorMethods
5
- def process_meme line, name, decorations, arguments, body
6
- DeclareMeme.new line, name, decorations, arguments, body
4
+ module BuilderMethods
5
+ def meme loc, name, decorations, arguments, body
6
+ DeclareMeme.new loc.line, name, decorations, arguments, body
7
7
  end
8
8
  end
9
9
 
10
- class DeclareMeme < Define
10
+ class DeclareMemeBody < Iter
11
+ attr_accessor :name
12
+
13
+ def bytecode(g)
14
+ pos(g)
15
+
16
+ g.state.scope.nest_scope self
17
+
18
+ meth = new_generator g, @name, @arguments
19
+
20
+ meth.push_state self
21
+ meth.state.push_super self
22
+ meth.definition_line @line
23
+
24
+ meth.state.push_name @name
25
+
26
+ @arguments.bytecode meth
27
+ @body.bytecode meth
28
+
29
+ meth.state.pop_name
30
+
31
+ meth.local_count = local_count
32
+ meth.local_names = local_names
33
+ meth.splat_index = @arguments.splat_index
34
+
35
+ meth.ret
36
+ meth.close
37
+ meth.pop_state
38
+
39
+ g.push_scope
40
+ g.send :for_method_definition, 0
41
+ g.add_scope
42
+
43
+ # Create the BlockEnvironment from the meth Generator
44
+ g.create_block meth
45
+ end
46
+ end
47
+
48
+ class DeclareMeme < Node
11
49
  attr_accessor :name, :decorations, :arguments, :body
12
50
 
13
51
  def initialize line, name, decorations, arguments, body
14
52
  @line = line
15
53
  @name = name.value
16
- @decorations = decorations || ArrayLiteral.new(line, [])
17
- @arguments = arguments || Parameters.new(line, [], nil, false, nil, nil, nil, nil)
54
+ @decorations = decorations || ArrayAssembly.new(line, [])
55
+ @arguments = arguments || Parameters.new(line, [], nil, true, nil, nil, nil, nil)
18
56
  @body = body || NilLiteral.new(line)
19
57
  end
20
58
 
@@ -22,22 +60,26 @@ module CodeTools::AST
22
60
  [:meme, @name, @decorations.to_sexp, @arguments.to_sexp, @body.to_sexp]
23
61
  end
24
62
 
63
+ def body_implementation
64
+ meme_body = DeclareMemeBody.new(@line, @arguments, @body)
65
+ meme_body.name = @name
66
+ meme_body
67
+ end
68
+
25
69
  def bytecode(g)
26
70
  pos(g)
27
71
 
28
72
  ##
29
73
  # module = scope.for_method_definition
30
74
  # module.send :declare_meme, @name, @decorations,
31
- # CompiledCode(@body), const_scope, var_scope
75
+ # BlockEnvironment(body_implementation)
32
76
  #
33
77
  g.push_scope
34
78
  g.send :for_method_definition, 0
35
79
  g.push_literal @name
36
80
  @decorations.bytecode g
37
- g.push_generator compile_body(g)
38
- g.push_scope
39
- g.push_variables
40
- g.send :declare_meme, 5
81
+ body_implementation.bytecode(g)
82
+ g.send :declare_meme, 3
41
83
  end
42
84
  end
43
85
 
@@ -4,9 +4,9 @@ require_relative 'myco_module_scope'
4
4
 
5
5
  module CodeTools::AST
6
6
 
7
- module ProcessorMethods
8
- def process_declobj line, types, body
9
- DeclareObject.new line, types, body
7
+ module BuilderMethods
8
+ def declobj loc, types, body
9
+ DeclareObject.new loc.line, types, body
10
10
  end
11
11
  end
12
12
 
@@ -39,11 +39,13 @@ module CodeTools::AST
39
39
  [:declobj, @types.to_sexp, @body.to_sexp]
40
40
  end
41
41
 
42
+ def scope_implementation
43
+ @scope_type.new @line, @body
44
+ end
45
+
42
46
  def bytecode g
43
47
  pos(g)
44
48
 
45
- scope = @scope_type.new @line, @body
46
-
47
49
  # ::Myco::Component.new types, parent, filename
48
50
  g.push_cpath_top
49
51
  g.find_const :Myco
@@ -51,7 +53,7 @@ module CodeTools::AST
51
53
  @types.bytecode g
52
54
  g.push_scope; g.send :for_method_definition, 0
53
55
  g.push_scope; g.send :active_path, 0; g.meta_to_s
54
- g.push_literal @line
56
+ g.push_int @line
55
57
  g.send :new, 4
56
58
 
57
59
  # The return value of Component.new at the top of the stack
@@ -61,7 +63,7 @@ module CodeTools::AST
61
63
 
62
64
  # Compile the inner scope,
63
65
  # leaving the last object in the scope at the top of the stack.
64
- scope.bytecode g
66
+ scope_implementation.bytecode g
65
67
 
66
68
  # component.__last__ = (value left on stack from @scope.bytecode)
67
69
  g.send :__last__=, 1
@@ -1,9 +1,9 @@
1
1
 
2
2
  module CodeTools::AST
3
3
 
4
- module ProcessorMethods
5
- def process_declstr line, types, string
6
- DeclareString.new line, types, string
4
+ module BuilderMethods
5
+ def declstr loc, types, string
6
+ DeclareString.new loc.line, types, string
7
7
  end
8
8
  end
9
9
 
@@ -23,8 +23,8 @@ module CodeTools::AST
23
23
  def implementation
24
24
  blk = NilLiteral.new @line
25
25
  obj = DeclareObject.new @line, @types, blk
26
- args = ArrayLiteral.new @string.line, [@string]
27
- SendWithArguments.new @string.line, obj, :from_string, args
26
+ args = ArgumentAssembly.new @string.line, [@string]
27
+ InvokeMethod.new @string.line, obj, :from_string, args
28
28
  end
29
29
 
30
30
  def bytecode g
@@ -1,30 +1,27 @@
1
1
 
2
2
  module CodeTools::AST
3
3
 
4
- module ProcessorMethods
5
- def process_invoke line, receiver, name, arguments, *rest
6
- Invoke.new line, receiver, name, arguments, *rest
4
+ module BuilderMethods
5
+ def invoke loc, receiver, name, arguments, *rest
6
+ Invoke.new loc.line, receiver, name, arguments, *rest
7
7
  end
8
8
  end
9
9
 
10
10
  class Invoke < Node
11
- attr_accessor :receiver, :name, :arguments, :block_params, :block
11
+ attr_accessor :receiver, :name, :arguments
12
12
 
13
13
  def initialize line, receiver, name, arguments, block_params=nil, block=nil
14
- block_arg = nil
15
- if arguments.is_a? BlockPass
16
- block_arg = arguments
17
- arguments = block_arg.arguments
18
- block_arg.arguments = nil
19
- end
14
+ @line = line
15
+ @receiver = receiver
16
+ @name = name
17
+ @arguments = arguments
20
18
 
21
- @line = line
22
- @receiver = receiver
23
- @name = name
24
- @arguments = arguments
25
- @block_params = block_params
26
- @block = block
27
- @block_arg = block_arg
19
+ if block
20
+ # TODO: error if passing both block argument and block literal
21
+ # Currently, this fails silently and ignores the block argument
22
+ @arguments ||= ArgumentAssembly.new(line, [])
23
+ @arguments.block = Iter.new(line, block_params, block)
24
+ end
28
25
  end
29
26
 
30
27
  def bytecode g
@@ -38,27 +35,12 @@ module CodeTools::AST
38
35
  end
39
36
 
40
37
  def implementation
41
- if @block.nil? && @block_arg.nil?
42
- if @arguments.nil?
43
- if @receiver.nil?
44
- LocalVariableAccessAmbiguous.new @line, @name
45
- else
46
- Send.new @line, @receiver, @name
47
- end
48
- else
49
- rcvr = @receiver || Self.new(@line)
50
- send = SendWithArguments.new @line, rcvr, @name, @arguments
51
- send
52
- end
38
+ if @receiver.nil? && @arguments.nil?
39
+ LocalVariableAccessAmbiguous.new(@line, @name)
53
40
  else
54
41
  rcvr = @receiver || Self.new(@line)
55
- send = SendWithArguments.new @line, rcvr, @name, @arguments
56
- if @block
57
- send.block = Iter.new @line, @block_params, @block
58
- elsif @block_arg
59
- send.block = @block_arg
60
- end
61
- send
42
+ args = @arguments || ArgumentAssembly.new(line, [])
43
+ InvokeMethod.new @line, rcvr, @name, args
62
44
  end
63
45
  end
64
46
  end
@@ -0,0 +1,28 @@
1
+
2
+ module CodeTools::AST
3
+
4
+ class InvokeMethod < Node
5
+ attr_accessor :line, :receiver, :name, :arguments
6
+
7
+ def initialize line, receiver, name, arguments
8
+ @line = line
9
+ @receiver = receiver
10
+ @name = name
11
+ @arguments = arguments
12
+ end
13
+
14
+ def bytecode(g)
15
+ @receiver.bytecode(g)
16
+ @arguments.bytecode(g)
17
+
18
+ pos(g)
19
+
20
+ g.__send__(@arguments.send_op, @name, @arguments.send_count)
21
+ end
22
+
23
+ def to_sexp
24
+ [:call, @receiver.to_sexp, @name, @arguments.to_sexp]
25
+ end
26
+ end
27
+
28
+ end