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.
- checksums.yaml +7 -7
- data/LICENSE +1 -1
- data/README.md +79 -0
- data/lib/myco/backtrace.rb +1 -1
- data/lib/myco/bootstrap/component.rb +78 -39
- data/lib/myco/bootstrap/find_constant.rb +12 -1
- data/lib/myco/bootstrap/instance.rb +5 -12
- data/lib/myco/bootstrap/meme.rb +176 -28
- data/lib/myco/bootstrap.my +8 -7
- data/lib/myco/code_loader.rb +332 -0
- data/lib/myco/command/inoculate.my +83 -0
- data/lib/myco/command.my +26 -26
- data/lib/myco/core/BasicDecorators.my +62 -0
- data/lib/myco/core/BasicObject.my +12 -34
- data/lib/myco/core/Decorator.my +1 -0
- data/lib/myco/core/FileToplevel.my +0 -3
- data/lib/myco/core/Myco.my +4 -0
- data/lib/myco/core/Object.my +6 -4
- data/lib/myco/eval.rb +17 -18
- data/lib/myco/misc.rb +16 -0
- data/lib/myco/parser/ast/argument_assembly.rb +76 -0
- data/lib/myco/parser/ast/array_assembly.rb +57 -0
- data/lib/myco/parser/ast/branch_operator.rb +73 -0
- data/lib/myco/parser/ast/constant_access.rb +4 -18
- data/lib/myco/parser/ast/constant_define.rb +3 -3
- data/lib/myco/parser/ast/constant_reopen.rb +12 -13
- data/lib/myco/parser/ast/declare_category.rb +8 -6
- data/lib/myco/parser/ast/declare_decorator.rb +4 -4
- data/lib/myco/parser/ast/declare_file.rb +4 -4
- data/lib/myco/parser/ast/declare_meme.rb +53 -11
- data/lib/myco/parser/ast/declare_object.rb +9 -7
- data/lib/myco/parser/ast/declare_string.rb +5 -5
- data/lib/myco/parser/ast/invoke.rb +18 -36
- data/lib/myco/parser/ast/invoke_method.rb +28 -0
- data/lib/myco/parser/ast/local_variable_access_ambiguous.rb +9 -13
- data/lib/myco/parser/ast/misc.rb +128 -33
- data/lib/myco/parser/ast/myco_module_scope.rb +26 -0
- data/lib/myco/parser/ast/quest.rb +3 -3
- data/lib/myco/parser/ast/to_ruby/array_assembly.rb +15 -0
- data/lib/myco/parser/ast/to_ruby/block.rb +14 -0
- data/lib/myco/parser/ast/to_ruby/block_pass.rb +6 -0
- data/lib/myco/parser/ast/to_ruby/branch_operator.rb +9 -0
- data/lib/myco/parser/ast/to_ruby/constant_access.rb +10 -0
- data/lib/myco/parser/ast/to_ruby/constant_assignment.rb +6 -0
- data/lib/myco/parser/ast/to_ruby/constant_define.rb +9 -0
- data/lib/myco/parser/ast/to_ruby/constant_reopen.rb +6 -0
- data/lib/myco/parser/ast/to_ruby/declare_category.rb +7 -0
- data/lib/myco/parser/ast/to_ruby/declare_decorator.rb +6 -0
- data/lib/myco/parser/ast/to_ruby/declare_file.rb +6 -0
- data/lib/myco/parser/ast/to_ruby/declare_meme.rb +16 -0
- data/lib/myco/parser/ast/to_ruby/declare_object.rb +8 -0
- data/lib/myco/parser/ast/to_ruby/declare_string.rb +6 -0
- data/lib/myco/parser/ast/to_ruby/dynamic_string.rb +14 -0
- data/lib/myco/parser/ast/to_ruby/dynamic_symbol.rb +7 -0
- data/lib/myco/parser/ast/to_ruby/eval_expression.rb +6 -0
- data/lib/myco/parser/ast/to_ruby/false_literal.rb +6 -0
- data/lib/myco/parser/ast/to_ruby/hash_literal.rb +16 -0
- data/lib/myco/parser/ast/to_ruby/invoke.rb +6 -0
- data/lib/myco/parser/ast/to_ruby/invoke_method.rb +35 -0
- data/lib/myco/parser/ast/to_ruby/iter.rb +10 -0
- data/lib/myco/parser/ast/to_ruby/local_variable_access_ambiguous.rb +16 -0
- data/lib/myco/parser/ast/to_ruby/local_variable_assignment.rb +8 -0
- data/lib/myco/parser/ast/to_ruby/myco_module_scope.rb +8 -0
- data/lib/myco/parser/ast/to_ruby/null_literal.rb +6 -0
- data/lib/myco/parser/ast/to_ruby/parameters.rb +60 -0
- data/lib/myco/parser/ast/to_ruby/quest.rb +13 -0
- data/lib/myco/parser/ast/to_ruby/return.rb +7 -0
- data/lib/myco/parser/ast/to_ruby/scoped_constant.rb +11 -0
- data/lib/myco/parser/ast/to_ruby/self.rb +6 -0
- data/lib/myco/parser/ast/to_ruby/splat_value.rb +33 -0
- data/lib/myco/parser/ast/to_ruby/string_literal.rb +6 -0
- data/lib/myco/parser/ast/to_ruby/symbol_literal.rb +6 -0
- data/lib/myco/parser/ast/to_ruby/toplevel_constant.rb +11 -0
- data/lib/myco/parser/ast/to_ruby/true_literal.rb +6 -0
- data/lib/myco/parser/ast/to_ruby/void_literal.rb +6 -0
- data/lib/myco/parser/ast/to_ruby.rb +138 -0
- data/lib/myco/parser/ast.rb +6 -0
- data/lib/myco/parser/peg_parser.rb +361 -181
- data/lib/myco/parser.rb +27 -11
- data/lib/myco/tools/BasicCommand.my +42 -0
- data/lib/myco/tools/Generator.my +18 -0
- data/lib/myco/toolset.rb +0 -3
- data/lib/myco/version.rb +1 -4
- data/lib/myco.rb +2 -0
- metadata +230 -160
- data/lib/myco/parser/builder.output +0 -3995
- data/lib/myco/parser/builder.racc +0 -585
- data/lib/myco/parser/builder.rb +0 -1592
- data/lib/myco/parser/lexer.rb +0 -2306
- data/lib/myco/parser/lexer.rl +0 -393
- data/lib/myco/parser/lexer_char_classes.rl +0 -56
- data/lib/myco/parser/lexer_common.rb +0 -95
- data/lib/myco/parser/lexer_skeleton.rl +0 -154
- data/lib/myco/parser/peg_parser.kpeg +0 -759
- data/lib/myco/tools/OptionParser.my +0 -38
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
|
-
---
|
2
|
-
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
5
|
-
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 417744da4484853e229b10a6f5de25b140e67af1
|
4
|
+
data.tar.gz: 9e4e018656fef08864d79948f9ff58731fa33c65
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: c81eb1fd9f81a6c1c5d02d29929c9922b749e9a6833c6190b88eb996f56ad9d1ed4cb60e3edd276b8bcf6fd0f151634129f4e4754b3f591594b0e600abae0be4
|
7
|
+
data.tar.gz: b2db5fe48fd80b3c49aa472ed3dc89d32b3b15ff800f943760a7f36480aa2aef2851832a88cccc1eed40064a48c690471b44e0d9aa12edf27a5dd0df29d4be5e
|
data/LICENSE
CHANGED
@@ -1,2 +1,2 @@
|
|
1
|
-
Copyright
|
1
|
+
Copyright 2013-2015 Joe McIlvain.
|
2
2
|
All rights reserved.
|
data/README.md
ADDED
@@ -0,0 +1,79 @@
|
|
1
|
+
|
2
|
+
```myco
|
3
|
+
Myco < Ruby, QML, Ioke {
|
4
|
+
primary author: "Joe Eli McIlvain"
|
5
|
+
|
6
|
+
latest gem version: 0.1.0
|
7
|
+
development status: [:alpha, :experimental]
|
8
|
+
|
9
|
+
dependency "Rubinius VM": git(:master)
|
10
|
+
|
11
|
+
development dependency 'bundler': 1.6
|
12
|
+
development dependency 'rake': 10.3
|
13
|
+
development dependency 'rspec': 3.0
|
14
|
+
development dependency 'fivemat': 1.3
|
15
|
+
|
16
|
+
[features]
|
17
|
+
|
18
|
+
"innovative declarative syntax layer around a familiar Ruby-like layer"
|
19
|
+
"ease of expression of intent" : "consistent but powerful rules"
|
20
|
+
todo "runtime parsing rule intercession"
|
21
|
+
todo "nested blocks parsed by user parsers"
|
22
|
+
|
23
|
+
"patterns for a responsibly localized import system": ImportSystemMethods {
|
24
|
+
import 'some/library'
|
25
|
+
import as(:SomeLibrary) 'some/library'
|
26
|
+
private import 'some/library'
|
27
|
+
export as(:MyGlobalLibrary) 'my/library'
|
28
|
+
arbitrary user_defined import_mechanism 'special/library'
|
29
|
+
}
|
30
|
+
|
31
|
+
"fluid integration with the host Ruby runtime": {
|
32
|
+
ruby_require('some_ruby_gem')
|
33
|
+
obj = SomeRubyGem::Object.new(1, 2, *rest, foo:8, bar:9)
|
34
|
+
|
35
|
+
RubyEval """
|
36
|
+
Myco::SomeObject.new(foo:8, bar:9)
|
37
|
+
"""
|
38
|
+
}
|
39
|
+
|
40
|
+
rich support_for(:decorators) in: user_space
|
41
|
+
|
42
|
+
[decorators]
|
43
|
+
|
44
|
+
support_for: Decorator {
|
45
|
+
apply: |meme|
|
46
|
+
arguments.each |feature| { meme.supported_features.push(feature) }
|
47
|
+
}
|
48
|
+
|
49
|
+
rich: Decorator {
|
50
|
+
[transforms]
|
51
|
+
richness: true
|
52
|
+
memoize: true
|
53
|
+
}
|
54
|
+
|
55
|
+
[contributing]
|
56
|
+
|
57
|
+
Github < RepositoryHost {
|
58
|
+
URL: "https://github.com/jemc/myco"
|
59
|
+
IssueTracker: URL + "/issues"
|
60
|
+
}
|
61
|
+
|
62
|
+
contributing_process: |user, problem| {
|
63
|
+
issue = user.file_bug_report(problem, on: Github::IssueTracker)
|
64
|
+
|
65
|
+
if(user.can_implement?) {
|
66
|
+
pr = PullRequest {
|
67
|
+
name: "Fix for issue #"issue.number" - "issue.description"."
|
68
|
+
branch: snake_case(issue.name)
|
69
|
+
user: user
|
70
|
+
|
71
|
+
include fix: for(problem)
|
72
|
+
include tests: for(fix)
|
73
|
+
|
74
|
+
user.file_pull_request(pr, on: Github::IssueTracker)
|
75
|
+
}
|
76
|
+
}
|
77
|
+
}
|
78
|
+
}
|
79
|
+
```
|
data/lib/myco/backtrace.rb
CHANGED
@@ -27,7 +27,7 @@ class Myco::Backtrace < Rubinius::Backtrace
|
|
27
27
|
file_width = file.length + 1 + sbullet.length
|
28
28
|
|
29
29
|
place = loc.instance_variable_get(:@method_module).to_s + '#'
|
30
|
-
place += loc.
|
30
|
+
place += loc.method.name.to_s
|
31
31
|
place_width = place.length + 1 + ebullet.length
|
32
32
|
|
33
33
|
padding = @width - file_width - place_width
|
@@ -1,12 +1,13 @@
|
|
1
1
|
|
2
2
|
module Myco
|
3
|
-
|
3
|
+
module Component
|
4
|
+
include MemeBindable
|
5
|
+
|
4
6
|
attr_accessor :__last__
|
5
7
|
attr_accessor :__name__
|
6
8
|
|
7
9
|
attr_reader :parent
|
8
10
|
attr_reader :parent_meme
|
9
|
-
attr_reader :memes
|
10
11
|
attr_reader :categories
|
11
12
|
|
12
13
|
attr_reader :constant_scope
|
@@ -45,29 +46,36 @@ module Myco
|
|
45
46
|
line ||= location.line
|
46
47
|
end
|
47
48
|
|
48
|
-
this =
|
49
|
+
this = Class.new Instance
|
50
|
+
# TODO: avoid extending here to avoid touching/making the singleton_class
|
51
|
+
this.extend self
|
49
52
|
|
50
53
|
this.instance_eval {
|
51
54
|
@super_components = super_components
|
52
|
-
@memes = { }
|
53
55
|
@parent = parent
|
54
56
|
@filename = filename
|
55
57
|
@line = line
|
56
58
|
@basename = File.basename @filename
|
57
59
|
@dirname = File.dirname @filename
|
58
|
-
@categories = {
|
60
|
+
@categories = { main: this }
|
59
61
|
@parent_meme = parent_meme
|
60
62
|
}
|
61
63
|
|
62
64
|
all_categories = Hash.new { |h,k| h[k] = Array.new }
|
63
65
|
|
64
66
|
super_components.each do |other|
|
65
|
-
|
66
|
-
|
67
|
+
raise TypeError, "Got non-Component in supers for new Component: "\
|
68
|
+
"#{super_components.inspect}" \
|
69
|
+
unless other.is_a? Component
|
70
|
+
|
71
|
+
this.include other
|
72
|
+
other.categories.each do |name, cat|
|
73
|
+
all_categories[name] << cat
|
74
|
+
end
|
67
75
|
end
|
68
76
|
|
69
77
|
all_categories.each do |name, supers|
|
70
|
-
if name
|
78
|
+
if name == :main
|
71
79
|
this.categories[name] = this
|
72
80
|
else
|
73
81
|
this.categories[name] = this.__new_category__ name, supers, filename, line
|
@@ -77,6 +85,11 @@ module Myco
|
|
77
85
|
this
|
78
86
|
end
|
79
87
|
|
88
|
+
# Get a reference to the main Component from main or from any inner Category
|
89
|
+
def main
|
90
|
+
self < Category ? parent : self
|
91
|
+
end
|
92
|
+
|
80
93
|
def __category__ name
|
81
94
|
@categories[name] ||= __new_category__(name)
|
82
95
|
end
|
@@ -92,50 +105,76 @@ module Myco
|
|
92
105
|
category = Component.new super_cats, self, filename, line
|
93
106
|
category.__name__ = name
|
94
107
|
category_instance = category.instance
|
95
|
-
declare_meme(name) { category_instance }
|
96
|
-
|
108
|
+
meme = declare_meme(name) { category_instance }
|
109
|
+
meme.cache = true
|
97
110
|
|
98
111
|
category
|
99
112
|
end
|
100
113
|
|
101
|
-
def declare_meme name, decorations=[], body=nil, scope=nil, varscope=nil, &blk
|
102
|
-
body.scope = scope.dup if scope && body.respond_to?(:scope=)
|
103
|
-
meme = Meme.new self, name, body, &blk
|
104
|
-
|
105
|
-
decorations.each do |decoration, arguments|
|
106
|
-
search_component = self<Category ? parent : self
|
107
|
-
decorators = search_component.categories[:decorators].instance
|
108
|
-
|
109
|
-
raise KeyError, "Unknown decorator for #{self}##{name}: #{decoration}" \
|
110
|
-
unless decorators.respond_to?(decoration)
|
111
|
-
decorator = decorators.send(decoration)
|
112
|
-
decorator.transforms.apply meme, *arguments
|
113
|
-
decorator.apply meme, *arguments
|
114
|
-
end
|
115
|
-
meme.bind
|
116
|
-
|
117
|
-
meme
|
118
|
-
end
|
119
|
-
|
120
114
|
def instance
|
121
|
-
if
|
122
|
-
@instance = Instance.new(self)
|
123
|
-
@instance.extend self
|
115
|
+
if @instance
|
124
116
|
yield @instance if block_given?
|
125
|
-
@instance.__signal__ :creation if @instance.respond_to? :__signal__
|
126
117
|
else
|
118
|
+
@instance = allocate
|
119
|
+
@instance.instance_variable_set(:@component, self)
|
127
120
|
yield @instance if block_given?
|
121
|
+
@instance.__signal__ :creation if @instance.respond_to? :__signal__
|
128
122
|
end
|
129
123
|
|
130
124
|
@instance
|
131
125
|
end
|
132
126
|
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
127
|
+
# Override Module#include to bypass type checks of others
|
128
|
+
def include *others
|
129
|
+
others.reverse_each do |other|
|
130
|
+
Rubinius::Type.include_modules_from(other, self.origin)
|
131
|
+
Rubinius::Type.infect(self, other)
|
132
|
+
other.__send__ :included, self
|
133
|
+
end
|
134
|
+
self
|
135
|
+
end
|
136
|
+
|
137
|
+
# Extend the given object with this component's features
|
138
|
+
# Called on object.extend(component)
|
139
|
+
def extend_object object
|
140
|
+
singleton_class = Rubinius::Type.object_singleton_class(object)
|
141
|
+
Rubinius::Type.include_modules_from(self, singleton_class.origin)
|
142
|
+
Rubinius::Type.infect(singleton_class, self)
|
143
|
+
object
|
144
|
+
end
|
145
|
+
|
146
|
+
# Create a child component of self to act as the component of the object,
|
147
|
+
# which is allowed to be a Ruby object (not a Myco::Instance).
|
148
|
+
# TODO: re-evaluate usefulness and possibly remove in favor of using extend.
|
149
|
+
def inject_into object
|
150
|
+
object.extend InstanceMethods unless object.is_a? InstanceMethods
|
151
|
+
object.instance_variable_set(:@component, self)
|
152
|
+
extend_object object
|
153
|
+
object
|
154
|
+
end
|
155
|
+
|
156
|
+
# Create an untracked instance of this component and
|
157
|
+
# call setters on the instance with the values given by kwargs.
|
158
|
+
def new **kwargs
|
159
|
+
instance = allocate
|
160
|
+
instance.instance_variable_set(:@component, self)
|
161
|
+
kwargs.each { |key,val| instance.send :"#{key}=", val }
|
162
|
+
instance
|
163
|
+
end
|
164
|
+
|
165
|
+
# Like module_eval, but it also shifts the ConstantScope of the block
|
166
|
+
def component_eval &block
|
167
|
+
block_env = block.block
|
168
|
+
cscope = Rubinius::ConstantScope.new(self, block_env.constant_scope)
|
169
|
+
if defined? ::Myco::FileToplevel && self < ::Myco::FileToplevel
|
170
|
+
cscope.set_myco_file
|
171
|
+
elsif defined? ::Myco::Category && self < ::Myco::Category
|
172
|
+
cscope.set_myco_category
|
173
|
+
else
|
174
|
+
cscope.set_myco_component
|
175
|
+
end
|
176
|
+
result = block_env.call_under(self, cscope, true, self)
|
177
|
+
result
|
139
178
|
end
|
140
179
|
end
|
141
180
|
|
@@ -7,6 +7,11 @@ module Rubinius
|
|
7
7
|
attr_reader :myco_category
|
8
8
|
attr_reader :myco_meme
|
9
9
|
|
10
|
+
# TODO: Can this be more graceful and more eager?
|
11
|
+
def myco_file
|
12
|
+
@myco_file ||= parent.myco_file
|
13
|
+
end
|
14
|
+
|
10
15
|
def myco_levels
|
11
16
|
@myco_levels ||= (parent ? parent.myco_levels.dup : [])
|
12
17
|
end
|
@@ -51,8 +56,14 @@ end
|
|
51
56
|
|
52
57
|
module Myco
|
53
58
|
|
54
|
-
|
59
|
+
# Get the "current" ConstantScope (from the caller's perspective)
|
60
|
+
def self.cscope
|
61
|
+
Rubinius::ConstantScope.of_sender
|
62
|
+
end
|
63
|
+
|
64
|
+
def self.find_constant(name, scope=nil)
|
55
65
|
name = ::Rubinius::Type.coerce_to_constant_name name
|
66
|
+
scope ||= ::Rubinius::ConstantScope.of_sender
|
56
67
|
|
57
68
|
category = scope.myco_category
|
58
69
|
component = scope.myco_component
|
@@ -1,6 +1,6 @@
|
|
1
1
|
|
2
2
|
module Myco
|
3
|
-
|
3
|
+
module InstanceMethods
|
4
4
|
include ::Kernel
|
5
5
|
|
6
6
|
# TODO: clean this up
|
@@ -24,10 +24,6 @@ module Myco
|
|
24
24
|
p str
|
25
25
|
end
|
26
26
|
|
27
|
-
def initialize component
|
28
|
-
@component = component
|
29
|
-
end
|
30
|
-
|
31
27
|
attr_reader :component
|
32
28
|
|
33
29
|
def parent
|
@@ -41,12 +37,9 @@ module Myco
|
|
41
37
|
def memes
|
42
38
|
@component.memes
|
43
39
|
end
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
::Kernel.instance_method(sym).bind(self).call(*args)
|
49
|
-
end
|
50
|
-
end
|
40
|
+
end
|
41
|
+
|
42
|
+
class Instance < ::BasicObject
|
43
|
+
include InstanceMethods
|
51
44
|
end
|
52
45
|
end
|
data/lib/myco/bootstrap/meme.rb
CHANGED
@@ -1,13 +1,54 @@
|
|
1
1
|
|
2
2
|
module Myco
|
3
|
+
module MemeBindable
|
4
|
+
def memes
|
5
|
+
@memes ||= {}
|
6
|
+
end
|
7
|
+
|
8
|
+
def declare_meme name, decorations=[], body=nil, cscope=nil, &blk
|
9
|
+
meme = Meme.new self, name
|
10
|
+
if cscope && blk
|
11
|
+
body = blk.block.dup
|
12
|
+
blk = nil
|
13
|
+
body.instance_variable_set(:@constant_scope, cscope)
|
14
|
+
end
|
15
|
+
meme.body = body || blk
|
16
|
+
|
17
|
+
decorations = decorations.map do |decoration, arguments|
|
18
|
+
decorators = main.categories[:decorators]
|
19
|
+
decorators = decorators && decorators.instance
|
20
|
+
|
21
|
+
unless decorators.respond_to?(decoration)
|
22
|
+
reason = if decorators.nil?
|
23
|
+
"#{self} has no [decorators] category."
|
24
|
+
else
|
25
|
+
"Known decorators in #{decorators}: " \
|
26
|
+
"#{decorators.component.memes.keys.inspect}."
|
27
|
+
end
|
28
|
+
raise KeyError,
|
29
|
+
"Unknown decorator for #{self}##{name}: '#{decoration}'. #{reason}"
|
30
|
+
end
|
31
|
+
|
32
|
+
[decorators.send(decoration), arguments]
|
33
|
+
end
|
34
|
+
decorations.each { |deco, args| deco.transforms.apply meme, *args }
|
35
|
+
decorations.each { |deco, args| deco.apply meme, *args }
|
36
|
+
|
37
|
+
meme.bind
|
38
|
+
|
39
|
+
meme
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
3
43
|
class Meme
|
4
44
|
attr_accessor :target
|
5
45
|
attr_accessor :name
|
6
46
|
attr_accessor :body
|
7
47
|
attr_accessor :cache
|
48
|
+
attr_accessor :var
|
8
49
|
attr_accessor :expose
|
9
50
|
|
10
|
-
attr_reader :
|
51
|
+
attr_reader :metadata
|
11
52
|
|
12
53
|
def to_s
|
13
54
|
"#<#{self.class}:#{self.name.to_s}>"
|
@@ -20,10 +61,14 @@ module Myco
|
|
20
61
|
def initialize target, name, body=nil, &blk
|
21
62
|
self.target = target
|
22
63
|
self.name = name
|
23
|
-
self.body = body
|
64
|
+
self.body = body if body
|
65
|
+
self.body = blk if blk
|
24
66
|
self.cache = false
|
67
|
+
self.var = false
|
25
68
|
self.expose = true
|
26
69
|
|
70
|
+
@metadata = {}
|
71
|
+
|
27
72
|
@caches = {}
|
28
73
|
end
|
29
74
|
|
@@ -31,33 +76,96 @@ module Myco
|
|
31
76
|
case value
|
32
77
|
when Rubinius::Executable
|
33
78
|
@body = value
|
34
|
-
@body.scope.set_myco_meme self
|
79
|
+
@body.scope.set_myco_meme self
|
80
|
+
when Rubinius::BlockEnvironment
|
81
|
+
block_env = value
|
82
|
+
block_env.change_name name
|
83
|
+
block_env.constant_scope.set_myco_meme self
|
84
|
+
@body = Rubinius::BlockEnvironment::AsMethod.new block_env
|
35
85
|
when Proc
|
36
86
|
block_env = value.block.dup
|
37
87
|
block_env.change_name name
|
88
|
+
block_env.constant_scope.set_myco_meme self \
|
89
|
+
unless block_env.constant_scope.myco_meme
|
38
90
|
@body = Rubinius::BlockEnvironment::AsMethod.new block_env
|
39
|
-
value = value.dup
|
40
|
-
value.lambda_style!
|
41
91
|
else
|
42
92
|
raise ArgumentError,
|
43
|
-
"Meme body must be a Rubinius::Executable
|
93
|
+
"Meme body must be a Rubinius::Executable, " \
|
94
|
+
"Rubinius::BlockEnvironment or a Proc; got: #{value.inspect}"
|
44
95
|
end
|
45
96
|
|
97
|
+
@effective_body = @body
|
98
|
+
|
99
|
+
bind if @bound
|
46
100
|
@body
|
47
101
|
end
|
48
102
|
|
103
|
+
def target= value
|
104
|
+
@target = value
|
105
|
+
@target.extend(MemeBindable) unless @target.is_a?(MemeBindable)
|
106
|
+
bind if @bound
|
107
|
+
@target
|
108
|
+
end
|
109
|
+
|
110
|
+
def cache= value
|
111
|
+
@cache = value
|
112
|
+
bind if @bound
|
113
|
+
@cache
|
114
|
+
end
|
115
|
+
|
116
|
+
def var= value
|
117
|
+
@var = value
|
118
|
+
bind if @bound
|
119
|
+
@var
|
120
|
+
end
|
121
|
+
|
122
|
+
def to_proc
|
123
|
+
Proc.__from_block__(@body.block_env)
|
124
|
+
end
|
125
|
+
|
49
126
|
def bind
|
127
|
+
@bound = true
|
50
128
|
return if not @expose
|
51
129
|
|
52
|
-
|
53
|
-
target.memes[@name] = meme
|
130
|
+
@target.memes[@name] = self
|
54
131
|
|
132
|
+
if @var
|
133
|
+
bind_var_getter
|
134
|
+
bind_var_setter
|
135
|
+
@effective_body = @target.instance_method(@name).executable
|
136
|
+
elsif @cache
|
137
|
+
bind_cache_method
|
138
|
+
@effective_body = @target.instance_method(@name).executable
|
139
|
+
else
|
140
|
+
Rubinius.add_method @name, @body, @target, :public
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
def result *args, &blk
|
145
|
+
result_for target.instance, *args, &blk
|
146
|
+
end
|
147
|
+
|
148
|
+
def result_for obj, *args, &blk
|
149
|
+
result = @effective_body.invoke @name, @target, obj, args, blk
|
150
|
+
end
|
151
|
+
|
152
|
+
def set_result_for obj, result, *args, &blk
|
153
|
+
raise "Can't set_result_for this Meme" unless @cache
|
154
|
+
cache_key = [obj.hash, args.hash, blk.hash]
|
155
|
+
@caches[cache_key] = result
|
156
|
+
end
|
157
|
+
|
158
|
+
private
|
159
|
+
|
160
|
+
def bind_cache_method
|
55
161
|
##
|
56
162
|
# This dynamic method is nearly the same as Meme#result_for
|
57
163
|
# (but written from the perspective of the receiver)
|
58
164
|
# implemented in bytecode to avoid forwarding to another method
|
59
165
|
# on the call stack.
|
60
166
|
# TODO: move this bytecode generation to a helper method
|
167
|
+
meme = self
|
168
|
+
|
61
169
|
target.dynamic_method @name, '(myco_internal)' do |g|
|
62
170
|
g.splat_index = 0 # *args
|
63
171
|
|
@@ -89,15 +197,10 @@ module Myco
|
|
89
197
|
g.pop
|
90
198
|
|
91
199
|
##
|
92
|
-
# if
|
200
|
+
# if caches.has_key?(cache_key)
|
93
201
|
# return caches[cache_key]
|
94
202
|
# end
|
95
203
|
#
|
96
|
-
g.push_local 1 # meme
|
97
|
-
g.send :cache, 0
|
98
|
-
g.send :false?, 0
|
99
|
-
g.goto_if_true invoke
|
100
|
-
|
101
204
|
g.push_local 2 # caches
|
102
205
|
g.push_local 3 # cache_key
|
103
206
|
g.send :has_key?, 1
|
@@ -137,24 +240,69 @@ module Myco
|
|
137
240
|
end
|
138
241
|
end
|
139
242
|
|
140
|
-
def
|
141
|
-
|
243
|
+
def bind_var_getter
|
244
|
+
# TODO: move this bytecode generation to a helper method
|
245
|
+
meme = self
|
246
|
+
|
247
|
+
target.dynamic_method @name, '(myco_internal)' do |g|
|
248
|
+
get = g.new_label
|
249
|
+
ret = g.new_label
|
250
|
+
|
251
|
+
##
|
252
|
+
# meme = <this meme>
|
253
|
+
#
|
254
|
+
g.push_literal meme
|
255
|
+
g.set_local 1 # meme
|
256
|
+
g.pop
|
257
|
+
|
258
|
+
##
|
259
|
+
# if @#{:"__#{@name}_defined__"}
|
260
|
+
# @#{name} = meme.body.invoke meme.name, @target, obj, [], nil
|
261
|
+
# end
|
262
|
+
# return @#{name}
|
263
|
+
#
|
264
|
+
g.push_ivar(:"__#{@name}_defined__")
|
265
|
+
g.goto_if_true(get)
|
266
|
+
|
267
|
+
g.push_local 1 # meme
|
268
|
+
g.send :body, 0
|
269
|
+
g.push_local 1; g.send :name, 0 # meme.name
|
270
|
+
g.push_local 1; g.send :target, 0 # meme.target
|
271
|
+
g.push_self
|
272
|
+
g.make_array 0
|
273
|
+
g.push_nil
|
274
|
+
g.send :invoke, 5
|
275
|
+
g.set_ivar(@name)
|
276
|
+
|
277
|
+
g.push_true
|
278
|
+
g.set_ivar(:"__#{@name}_defined__")
|
279
|
+
g.pop
|
280
|
+
g.goto(ret)
|
281
|
+
|
282
|
+
get.set!
|
283
|
+
g.push_ivar(@name)
|
284
|
+
|
285
|
+
ret.set!
|
286
|
+
g.ret
|
287
|
+
end
|
142
288
|
end
|
143
289
|
|
144
|
-
def
|
145
|
-
|
146
|
-
|
147
|
-
|
290
|
+
def bind_var_setter
|
291
|
+
# TODO: move this bytecode generation to a helper method
|
292
|
+
target.dynamic_method :"#{@name}=", '(myco_internal)' do |g|
|
293
|
+
g.total_args = 1
|
294
|
+
g.local_count = 1
|
295
|
+
|
296
|
+
g.push_true
|
297
|
+
g.set_ivar(:"__#{@name}_defined__")
|
298
|
+
g.pop
|
299
|
+
|
300
|
+
g.push_local 0 # value
|
301
|
+
g.set_ivar @name
|
302
|
+
|
303
|
+
g.ret
|
148
304
|
end
|
149
|
-
|
150
|
-
result = @body.invoke @name, @target, obj, args, blk
|
151
|
-
|
152
|
-
@caches[cache_key] = result
|
153
305
|
end
|
154
306
|
|
155
|
-
def set_result_for obj, result, *args, &blk
|
156
|
-
cache_key = [obj.hash, args.hash, blk.hash]
|
157
|
-
@caches[cache_key] = result
|
158
|
-
end
|
159
307
|
end
|
160
308
|
end
|
data/lib/myco/bootstrap.my
CHANGED
@@ -1,15 +1,16 @@
|
|
1
1
|
|
2
|
-
RubyEval < EmptyObject {
|
2
|
+
::Myco::RubyEval < EmptyObject {
|
3
3
|
from_string: |string| ::Kernel.instance_method(:eval).bind(self).call(string)
|
4
4
|
}
|
5
5
|
|
6
6
|
RubyEval @@@
|
7
|
-
Myco.eval_file("core/Category.my",
|
8
|
-
Myco.eval_file("core/
|
9
|
-
Myco.eval_file("core/
|
10
|
-
Myco.eval_file("core/
|
11
|
-
Myco.eval_file("core/
|
7
|
+
Myco.eval_file("core/Category.my", [Myco::CoreLoadPath])
|
8
|
+
Myco.eval_file("core/BasicDecorators.my", [Myco::CoreLoadPath])
|
9
|
+
Myco.eval_file("core/BasicObject.my", [Myco::CoreLoadPath])
|
10
|
+
Myco.eval_file("core/Decorator.my", [Myco::CoreLoadPath])
|
11
|
+
Myco.eval_file("core/Object.my", [Myco::CoreLoadPath])
|
12
|
+
Myco.eval_file("core/FileToplevel.my", [Myco::CoreLoadPath])
|
12
13
|
|
13
14
|
# Below are not necessary for bootstrapping; TODO: move out of RubyEval
|
14
|
-
Myco.eval_file("core/Switch.my",
|
15
|
+
Myco.eval_file("core/Switch.my", [Myco::CoreLoadPath])
|
15
16
|
@@@
|