myco 0.1.0.dev → 0.1.0

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.
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