myco 0.1.0.dev
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.
- checksums.yaml +7 -0
- data/LICENSE +2 -0
- data/bin/myco +7 -0
- data/lib/myco/backtrace.rb +56 -0
- data/lib/myco/bootstrap/component.rb +142 -0
- data/lib/myco/bootstrap/empty_object.rb +4 -0
- data/lib/myco/bootstrap/file_toplevel.rb +5 -0
- data/lib/myco/bootstrap/find_constant.rb +86 -0
- data/lib/myco/bootstrap/instance.rb +52 -0
- data/lib/myco/bootstrap/meme.rb +160 -0
- data/lib/myco/bootstrap/void.rb +40 -0
- data/lib/myco/bootstrap.my +15 -0
- data/lib/myco/bootstrap.rb +10 -0
- data/lib/myco/command.my +33 -0
- data/lib/myco/core/BasicObject.my +46 -0
- data/lib/myco/core/Category.my +5 -0
- data/lib/myco/core/Decorator.my +18 -0
- data/lib/myco/core/FileToplevel.my +23 -0
- data/lib/myco/core/Object.my +24 -0
- data/lib/myco/core/Switch.my +31 -0
- data/lib/myco/eval.rb +63 -0
- data/lib/myco/parser/ast/constant_access.rb +29 -0
- data/lib/myco/parser/ast/constant_define.rb +40 -0
- data/lib/myco/parser/ast/constant_reopen.rb +47 -0
- data/lib/myco/parser/ast/declare_category.rb +51 -0
- data/lib/myco/parser/ast/declare_decorator.rb +35 -0
- data/lib/myco/parser/ast/declare_file.rb +54 -0
- data/lib/myco/parser/ast/declare_meme.rb +44 -0
- data/lib/myco/parser/ast/declare_object.rb +75 -0
- data/lib/myco/parser/ast/declare_string.rb +37 -0
- data/lib/myco/parser/ast/invoke.rb +66 -0
- data/lib/myco/parser/ast/local_variable_access_ambiguous.rb +38 -0
- data/lib/myco/parser/ast/misc.rb +61 -0
- data/lib/myco/parser/ast/myco_module_scope.rb +58 -0
- data/lib/myco/parser/ast/quest.rb +82 -0
- data/lib/myco/parser/ast.rb +15 -0
- data/lib/myco/parser/builder.output +3995 -0
- data/lib/myco/parser/builder.racc +585 -0
- data/lib/myco/parser/builder.rb +1592 -0
- data/lib/myco/parser/lexer.rb +2306 -0
- data/lib/myco/parser/lexer.rl +393 -0
- data/lib/myco/parser/lexer_char_classes.rl +56 -0
- data/lib/myco/parser/lexer_common.rb +95 -0
- data/lib/myco/parser/lexer_skeleton.rl +154 -0
- data/lib/myco/parser/peg_parser.kpeg +759 -0
- data/lib/myco/parser/peg_parser.rb +7094 -0
- data/lib/myco/parser.rb +40 -0
- data/lib/myco/tools/OptionParser.my +38 -0
- data/lib/myco/tools/mycompile.my +51 -0
- data/lib/myco/toolset.rb +16 -0
- data/lib/myco/version.rb +22 -0
- data/lib/myco.rb +15 -0
- metadata +247 -0
@@ -0,0 +1,18 @@
|
|
1
|
+
|
2
|
+
::Myco::Decorator < ::Myco::BasicObject {
|
3
|
+
# Implement the apply meme to mutate the incoming meme in more custom ways.
|
4
|
+
# This is run after transforms.apply has already mutated the meme.
|
5
|
+
apply: |meme, *args| { }
|
6
|
+
|
7
|
+
[transforms]
|
8
|
+
# Implement one of the recognized transform memes to
|
9
|
+
# set the corresponding property of the incoming meme.
|
10
|
+
apply: |meme, *args| {
|
11
|
+
# TODO: make order-agnostic by waiting to assign until all have run
|
12
|
+
self .? target(meme) .tap |x| { meme.target = x }
|
13
|
+
self .? name(meme) .tap |x| { meme.name = x }
|
14
|
+
self .? body(meme) .tap |x| { meme.body = x }
|
15
|
+
self .? cache(meme) .tap |x| { meme.cache = x }
|
16
|
+
self .? expose(meme) .tap |x| { meme.expose = x }
|
17
|
+
}
|
18
|
+
}
|
@@ -0,0 +1,23 @@
|
|
1
|
+
|
2
|
+
::Myco::FileToplevel < ::Myco::Object {
|
3
|
+
# TODO: don't use instance_variable_get
|
4
|
+
dirname: component.instance_variable_get("@dirname")
|
5
|
+
basename: component.instance_variable_get("@basename")
|
6
|
+
filename: component.instance_variable_get("@filename")
|
7
|
+
|
8
|
+
[decorators]
|
9
|
+
|
10
|
+
# Run the code in the given file, ignoring the return value but
|
11
|
+
# importing the constants defined therein into the current namespace.
|
12
|
+
import: Decorator {
|
13
|
+
apply: |meme, *args| {
|
14
|
+
# TODO: shouldn't have to use meme.target here;
|
15
|
+
# should be able to use 'parent' to reach the outer objects
|
16
|
+
# while still referring to distinct instances rather than the originals.
|
17
|
+
load_paths = [meme.target.instance.dirname]
|
18
|
+
scope = meme.target.constant_scope
|
19
|
+
component = Myco.eval_file(meme.name.to_s, load_paths, false, scope)
|
20
|
+
meme.target.include(component)
|
21
|
+
}
|
22
|
+
}
|
23
|
+
}
|
@@ -0,0 +1,24 @@
|
|
1
|
+
|
2
|
+
::Myco::Object < ::Myco::BasicObject {
|
3
|
+
# Send the named signal to all handlers for this object
|
4
|
+
__signal__: |name, *args, &block| {
|
5
|
+
component.ancestors.reverse.each |other| {
|
6
|
+
inst = (component == other) && self || other.instance
|
7
|
+
inst.?decorators.?on.?signal_handlers(name).each |meme| {
|
8
|
+
meme.result_for(self, *args, &block)
|
9
|
+
}
|
10
|
+
}
|
11
|
+
}
|
12
|
+
|
13
|
+
[decorators]
|
14
|
+
|
15
|
+
# Register a named signal handler
|
16
|
+
var on: Decorator {
|
17
|
+
storage signal_handlers: Array.new
|
18
|
+
|
19
|
+
apply: |meme| signal_handlers(meme.name).push(meme)
|
20
|
+
|
21
|
+
[transforms]
|
22
|
+
expose: false
|
23
|
+
}
|
24
|
+
}
|
@@ -0,0 +1,31 @@
|
|
1
|
+
|
2
|
+
::Myco::Switch < ::Myco::Object {
|
3
|
+
var input: void
|
4
|
+
var output: void
|
5
|
+
var matched: false
|
6
|
+
var comparator: :"=="
|
7
|
+
|
8
|
+
when: |expected, &blk| {
|
9
|
+
matched || (input.send(comparator, expected) &&
|
10
|
+
((matched() = true) && (output() = blk.call(input))))
|
11
|
+
self
|
12
|
+
}
|
13
|
+
|
14
|
+
when_true: |&blk| {
|
15
|
+
matched || (input &&
|
16
|
+
((matched() = true) && (output() = blk.call(input))))
|
17
|
+
self
|
18
|
+
}
|
19
|
+
|
20
|
+
when_false: |&blk| {
|
21
|
+
matched || (input ||
|
22
|
+
((matched() = true) && (output() = blk.call(input))))
|
23
|
+
self
|
24
|
+
}
|
25
|
+
|
26
|
+
else: |&blk| {
|
27
|
+
matched ||
|
28
|
+
((matched() = true) && (output() = blk.call(input)))
|
29
|
+
self
|
30
|
+
}
|
31
|
+
}
|
data/lib/myco/eval.rb
ADDED
@@ -0,0 +1,63 @@
|
|
1
|
+
|
2
|
+
module Myco
|
3
|
+
|
4
|
+
# Most of method is stolen from Rubinius implementation of Kernel#eval
|
5
|
+
def self.eval(string, scope=nil, filename=nil, lineno=nil)
|
6
|
+
string = StringValue(string)
|
7
|
+
filename = StringValue(filename) if filename
|
8
|
+
lineno = Rubinius::Type.coerce_to lineno, Fixnum, :to_i if lineno
|
9
|
+
lineno = 1 if filename && !lineno
|
10
|
+
|
11
|
+
binding = ::Binding.setup(Rubinius::VariableScope.of_sender,
|
12
|
+
Rubinius::CompiledCode.of_sender,
|
13
|
+
(scope||Rubinius::ConstantScope.of_sender),
|
14
|
+
self)
|
15
|
+
|
16
|
+
filename ||= "(eval)"
|
17
|
+
|
18
|
+
lineno ||= binding.line_number
|
19
|
+
|
20
|
+
existing_scope = binding.constant_scope
|
21
|
+
binding.constant_scope = existing_scope.dup
|
22
|
+
|
23
|
+
c = Myco::ToolSet::Compiler
|
24
|
+
be = c.construct_block string, binding, filename, lineno
|
25
|
+
|
26
|
+
result = be.call_on_instance(binding.self)
|
27
|
+
binding.constant_scope = existing_scope
|
28
|
+
result
|
29
|
+
end
|
30
|
+
|
31
|
+
# TODO: replace with proper import set of functions
|
32
|
+
def self.eval_file path, load_paths=nil, get_last=true, scope=nil
|
33
|
+
load_paths ||= [File.dirname(Rubinius::VM.backtrace(1).first.file)]
|
34
|
+
|
35
|
+
tmp_path = File.expand_path(path)
|
36
|
+
use_path = File.file?(tmp_path) && tmp_path
|
37
|
+
load_paths.each do |load_path|
|
38
|
+
break if use_path
|
39
|
+
tmp_path = File.expand_path(path, load_path)
|
40
|
+
use_path = File.file?(tmp_path) && tmp_path
|
41
|
+
end
|
42
|
+
|
43
|
+
raise ArgumentError, "Couldn't resolve file: #{path.inspect} \n" \
|
44
|
+
"in load_paths: #{load_paths.inspect}" \
|
45
|
+
unless use_path
|
46
|
+
|
47
|
+
file_toplevel = Myco.eval File.read(use_path), scope, use_path, 1
|
48
|
+
get_last ? file_toplevel.component.__last__ : file_toplevel.component
|
49
|
+
end
|
50
|
+
|
51
|
+
def self.rescue
|
52
|
+
begin
|
53
|
+
yield
|
54
|
+
rescue Exception=>e
|
55
|
+
unless e.is_a? SystemExit
|
56
|
+
puts e.awesome_backtrace.show
|
57
|
+
puts e.awesome_backtrace.first_color + e.message + "\033[0m"
|
58
|
+
puts
|
59
|
+
exit(1)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
|
2
|
+
module CodeTools::AST
|
3
|
+
|
4
|
+
# Monkey patch original to use methods of ::Myco to lookup constants
|
5
|
+
class ConstantAccess
|
6
|
+
def bytecode(g)
|
7
|
+
pos(g)
|
8
|
+
|
9
|
+
if g.state.op_asgn? # TODO: is this branch unnecessary with Myco AST?
|
10
|
+
g.push_cpath_top
|
11
|
+
g.find_const :Myco
|
12
|
+
g.push_literal @name
|
13
|
+
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
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
|
2
|
+
module CodeTools::AST
|
3
|
+
|
4
|
+
module ProcessorMethods
|
5
|
+
def process_cdefn line, name, object
|
6
|
+
ConstantDefine.new line, name, object
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
class ConstantDefine < Node
|
11
|
+
attr_accessor :name, :object
|
12
|
+
|
13
|
+
def initialize line, name, object
|
14
|
+
@line = line
|
15
|
+
@name = name
|
16
|
+
@object = object
|
17
|
+
@object.create = false
|
18
|
+
end
|
19
|
+
|
20
|
+
def to_sexp
|
21
|
+
[:cdefn, @name.name, @object.to_sexp]
|
22
|
+
end
|
23
|
+
|
24
|
+
def implementation
|
25
|
+
ConstantAssignment.new @line, @name, @object
|
26
|
+
end
|
27
|
+
|
28
|
+
def bytecode g
|
29
|
+
pos(g)
|
30
|
+
|
31
|
+
implementation.bytecode g
|
32
|
+
|
33
|
+
g.dup_top
|
34
|
+
g.push_literal @name.name
|
35
|
+
g.send :__name__=, 1
|
36
|
+
g.pop
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
|
2
|
+
module CodeTools::AST
|
3
|
+
|
4
|
+
module ProcessorMethods
|
5
|
+
def process_copen line, name, body
|
6
|
+
ConstantReopen.new line, name, body
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
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)
|
19
|
+
|
20
|
+
attach_and_call g, :__component_init__, true
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
class ConstantReopen < Node
|
25
|
+
attr_accessor :name, :body
|
26
|
+
|
27
|
+
def initialize line, name, body
|
28
|
+
@line = line
|
29
|
+
@name = name
|
30
|
+
@body = body
|
31
|
+
end
|
32
|
+
|
33
|
+
def to_sexp
|
34
|
+
[:copen, @name.name, @body.to_sexp]
|
35
|
+
end
|
36
|
+
|
37
|
+
def bytecode g
|
38
|
+
pos(g)
|
39
|
+
|
40
|
+
scope = ConstantReopenScope.new @line, @body
|
41
|
+
|
42
|
+
@name.bytecode g
|
43
|
+
scope.bytecode g
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
|
2
|
+
require_relative 'myco_module_scope'
|
3
|
+
|
4
|
+
|
5
|
+
module CodeTools::AST
|
6
|
+
|
7
|
+
module ProcessorMethods
|
8
|
+
def process_category line, name, body
|
9
|
+
DeclareCategory.new line, name, body
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
class DeclareCategoryScope < MycoModuleScope
|
14
|
+
def body_bytecode g
|
15
|
+
g.push_scope
|
16
|
+
g.send :set_myco_category, 0
|
17
|
+
g.pop
|
18
|
+
|
19
|
+
@body.bytecode g
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
class DeclareCategory < Node
|
24
|
+
attr_accessor :name, :body
|
25
|
+
|
26
|
+
def initialize line, name, body
|
27
|
+
@line = line
|
28
|
+
@name = name
|
29
|
+
@body = body
|
30
|
+
end
|
31
|
+
|
32
|
+
def to_sexp
|
33
|
+
[:category, @name.value, @body.to_sexp]
|
34
|
+
end
|
35
|
+
|
36
|
+
def bytecode g
|
37
|
+
pos(g)
|
38
|
+
|
39
|
+
scope = DeclareCategoryScope.new @line, @body
|
40
|
+
|
41
|
+
##
|
42
|
+
# category = self.__category__ @name
|
43
|
+
g.push_self
|
44
|
+
g.push_literal @name.value
|
45
|
+
g.send :__category__, 1
|
46
|
+
|
47
|
+
scope.bytecode g
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
|
2
|
+
module CodeTools::AST
|
3
|
+
|
4
|
+
module ProcessorMethods
|
5
|
+
def process_deco line, name, arguments
|
6
|
+
DeclareDecorator.new line, name, arguments
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
class DeclareDecorator < Node
|
11
|
+
attr_accessor :line, :name, :arguments
|
12
|
+
|
13
|
+
def initialize line, name, arguments
|
14
|
+
@line = line
|
15
|
+
@name = name
|
16
|
+
@arguments = arguments || ArrayLiteral.new(@line, [])
|
17
|
+
end
|
18
|
+
|
19
|
+
def to_sexp
|
20
|
+
args_sexp = @arguments.to_sexp
|
21
|
+
args_sexp[0] = :arglist
|
22
|
+
sexp = [:deco, @name.value]
|
23
|
+
sexp.push args_sexp unless @arguments.body.empty?
|
24
|
+
sexp
|
25
|
+
end
|
26
|
+
|
27
|
+
def bytecode g
|
28
|
+
pos(g)
|
29
|
+
|
30
|
+
ary = ArrayLiteral.new @line, [@name, @arguments]
|
31
|
+
ary.bytecode g
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
|
2
|
+
module CodeTools::AST
|
3
|
+
|
4
|
+
module ProcessorMethods
|
5
|
+
def process_declfile line, body
|
6
|
+
DeclareFile.new line, body
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
class DeclareFileScope < MycoModuleScope
|
11
|
+
def body_bytecode g
|
12
|
+
g.push_scope
|
13
|
+
g.send :set_myco_file, 0
|
14
|
+
g.pop
|
15
|
+
|
16
|
+
@body.bytecode g
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
class DeclareFile < Node
|
21
|
+
attr_accessor :body
|
22
|
+
|
23
|
+
# Use minimal inspect to avoid huge inspect output for inner AST nodes
|
24
|
+
# that store a reference to a DeclareFile in an instance variable.
|
25
|
+
def inspect
|
26
|
+
to_s
|
27
|
+
end
|
28
|
+
|
29
|
+
def initialize line, body
|
30
|
+
@line = line
|
31
|
+
@body = body
|
32
|
+
end
|
33
|
+
|
34
|
+
def to_sexp
|
35
|
+
[:declfile, @body.to_sexp]
|
36
|
+
end
|
37
|
+
|
38
|
+
def implementation
|
39
|
+
myco = ToplevelConstant.new @line, :Myco
|
40
|
+
type = ScopedConstant.new @line, myco, :FileToplevel
|
41
|
+
types = ArrayLiteral.new @line, [type]
|
42
|
+
decl = DeclareObject.new @line, types, @body
|
43
|
+
decl.scope_type = DeclareFileScope
|
44
|
+
decl
|
45
|
+
end
|
46
|
+
|
47
|
+
def bytecode g
|
48
|
+
pos(g)
|
49
|
+
|
50
|
+
implementation.bytecode g
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
|
2
|
+
module CodeTools::AST
|
3
|
+
|
4
|
+
module ProcessorMethods
|
5
|
+
def process_meme line, name, decorations, arguments, body
|
6
|
+
DeclareMeme.new line, name, decorations, arguments, body
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
class DeclareMeme < Define
|
11
|
+
attr_accessor :name, :decorations, :arguments, :body
|
12
|
+
|
13
|
+
def initialize line, name, decorations, arguments, body
|
14
|
+
@line = line
|
15
|
+
@name = name.value
|
16
|
+
@decorations = decorations || ArrayLiteral.new(line, [])
|
17
|
+
@arguments = arguments || Parameters.new(line, [], nil, false, nil, nil, nil, nil)
|
18
|
+
@body = body || NilLiteral.new(line)
|
19
|
+
end
|
20
|
+
|
21
|
+
def to_sexp
|
22
|
+
[:meme, @name, @decorations.to_sexp, @arguments.to_sexp, @body.to_sexp]
|
23
|
+
end
|
24
|
+
|
25
|
+
def bytecode(g)
|
26
|
+
pos(g)
|
27
|
+
|
28
|
+
##
|
29
|
+
# module = scope.for_method_definition
|
30
|
+
# module.send :declare_meme, @name, @decorations,
|
31
|
+
# CompiledCode(@body), const_scope, var_scope
|
32
|
+
#
|
33
|
+
g.push_scope
|
34
|
+
g.send :for_method_definition, 0
|
35
|
+
g.push_literal @name
|
36
|
+
@decorations.bytecode g
|
37
|
+
g.push_generator compile_body(g)
|
38
|
+
g.push_scope
|
39
|
+
g.push_variables
|
40
|
+
g.send :declare_meme, 5
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
@@ -0,0 +1,75 @@
|
|
1
|
+
|
2
|
+
require_relative 'myco_module_scope'
|
3
|
+
|
4
|
+
|
5
|
+
module CodeTools::AST
|
6
|
+
|
7
|
+
module ProcessorMethods
|
8
|
+
def process_declobj line, types, body
|
9
|
+
DeclareObject.new line, types, body
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
class DeclareObjectScope < MycoModuleScope
|
14
|
+
def body_bytecode g
|
15
|
+
g.push_scope
|
16
|
+
g.send :set_myco_component, 0
|
17
|
+
g.pop
|
18
|
+
|
19
|
+
@body.bytecode g
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
class DeclareObject < Node
|
24
|
+
attr_accessor :types, :body
|
25
|
+
attr_accessor :create
|
26
|
+
|
27
|
+
attr_accessor :scope_type
|
28
|
+
|
29
|
+
def initialize line, types, body
|
30
|
+
@line = line
|
31
|
+
@types = types
|
32
|
+
@body = body
|
33
|
+
|
34
|
+
@create = true
|
35
|
+
@scope_type = DeclareObjectScope
|
36
|
+
end
|
37
|
+
|
38
|
+
def to_sexp
|
39
|
+
[:declobj, @types.to_sexp, @body.to_sexp]
|
40
|
+
end
|
41
|
+
|
42
|
+
def bytecode g
|
43
|
+
pos(g)
|
44
|
+
|
45
|
+
scope = @scope_type.new @line, @body
|
46
|
+
|
47
|
+
# ::Myco::Component.new types, parent, filename
|
48
|
+
g.push_cpath_top
|
49
|
+
g.find_const :Myco
|
50
|
+
g.find_const :Component
|
51
|
+
@types.bytecode g
|
52
|
+
g.push_scope; g.send :for_method_definition, 0
|
53
|
+
g.push_scope; g.send :active_path, 0; g.meta_to_s
|
54
|
+
g.push_literal @line
|
55
|
+
g.send :new, 4
|
56
|
+
|
57
|
+
# The return value of Component.new at the top of the stack
|
58
|
+
# will be consumed by @scope.bytecode, so save two copies of it.
|
59
|
+
g.dup_top # One for sending :__last__= to
|
60
|
+
g.dup_top # One for sending :instance to (or returning, if !@create)
|
61
|
+
|
62
|
+
# Compile the inner scope,
|
63
|
+
# leaving the last object in the scope at the top of the stack.
|
64
|
+
scope.bytecode g
|
65
|
+
|
66
|
+
# component.__last__ = (value left on stack from @scope.bytecode)
|
67
|
+
g.send :__last__=, 1
|
68
|
+
g.pop
|
69
|
+
|
70
|
+
# return (@create ? component.instance : component)
|
71
|
+
g.send :instance, 0 if @create
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
|
2
|
+
module CodeTools::AST
|
3
|
+
|
4
|
+
module ProcessorMethods
|
5
|
+
def process_declstr line, types, string
|
6
|
+
DeclareString.new line, types, string
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
class DeclareString < Node
|
11
|
+
attr_accessor :types, :string
|
12
|
+
|
13
|
+
def initialize line, types, string
|
14
|
+
@line = line
|
15
|
+
@types = types
|
16
|
+
@string = string
|
17
|
+
end
|
18
|
+
|
19
|
+
def to_sexp
|
20
|
+
[:declstr, @types.to_sexp, @string.to_sexp]
|
21
|
+
end
|
22
|
+
|
23
|
+
def implementation
|
24
|
+
blk = NilLiteral.new @line
|
25
|
+
obj = DeclareObject.new @line, @types, blk
|
26
|
+
args = ArrayLiteral.new @string.line, [@string]
|
27
|
+
SendWithArguments.new @string.line, obj, :from_string, args
|
28
|
+
end
|
29
|
+
|
30
|
+
def bytecode g
|
31
|
+
pos(g)
|
32
|
+
|
33
|
+
implementation.bytecode g
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
|
2
|
+
module CodeTools::AST
|
3
|
+
|
4
|
+
module ProcessorMethods
|
5
|
+
def process_invoke line, receiver, name, arguments, *rest
|
6
|
+
Invoke.new line, receiver, name, arguments, *rest
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
class Invoke < Node
|
11
|
+
attr_accessor :receiver, :name, :arguments, :block_params, :block
|
12
|
+
|
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
|
20
|
+
|
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
|
28
|
+
end
|
29
|
+
|
30
|
+
def bytecode g
|
31
|
+
pos(g)
|
32
|
+
|
33
|
+
implementation.bytecode(g)
|
34
|
+
end
|
35
|
+
|
36
|
+
def to_sexp
|
37
|
+
implementation.to_sexp
|
38
|
+
end
|
39
|
+
|
40
|
+
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
|
53
|
+
else
|
54
|
+
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
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
|
2
|
+
module CodeTools::AST
|
3
|
+
|
4
|
+
module ProcessorMethods
|
5
|
+
def process_lambig line, name
|
6
|
+
LocalVariableAccessAmbiguous.new line, name
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
class LocalVariableAccessAmbiguous < Node
|
11
|
+
attr_accessor :name
|
12
|
+
|
13
|
+
def initialize line, name
|
14
|
+
@line = line
|
15
|
+
@name = name
|
16
|
+
end
|
17
|
+
|
18
|
+
def bytecode g
|
19
|
+
pos(g)
|
20
|
+
|
21
|
+
implementation(g).bytecode(g)
|
22
|
+
end
|
23
|
+
|
24
|
+
def to_sexp
|
25
|
+
[:lambig, @name]
|
26
|
+
end
|
27
|
+
|
28
|
+
def implementation g
|
29
|
+
if g.state.scope.variables.has_key? @name
|
30
|
+
LocalVariableAccess.new @line, @name
|
31
|
+
else
|
32
|
+
rcvr = Self.new @line
|
33
|
+
Send.new @line, rcvr, @name, true, true
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|