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.
Files changed (53) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +2 -0
  3. data/bin/myco +7 -0
  4. data/lib/myco/backtrace.rb +56 -0
  5. data/lib/myco/bootstrap/component.rb +142 -0
  6. data/lib/myco/bootstrap/empty_object.rb +4 -0
  7. data/lib/myco/bootstrap/file_toplevel.rb +5 -0
  8. data/lib/myco/bootstrap/find_constant.rb +86 -0
  9. data/lib/myco/bootstrap/instance.rb +52 -0
  10. data/lib/myco/bootstrap/meme.rb +160 -0
  11. data/lib/myco/bootstrap/void.rb +40 -0
  12. data/lib/myco/bootstrap.my +15 -0
  13. data/lib/myco/bootstrap.rb +10 -0
  14. data/lib/myco/command.my +33 -0
  15. data/lib/myco/core/BasicObject.my +46 -0
  16. data/lib/myco/core/Category.my +5 -0
  17. data/lib/myco/core/Decorator.my +18 -0
  18. data/lib/myco/core/FileToplevel.my +23 -0
  19. data/lib/myco/core/Object.my +24 -0
  20. data/lib/myco/core/Switch.my +31 -0
  21. data/lib/myco/eval.rb +63 -0
  22. data/lib/myco/parser/ast/constant_access.rb +29 -0
  23. data/lib/myco/parser/ast/constant_define.rb +40 -0
  24. data/lib/myco/parser/ast/constant_reopen.rb +47 -0
  25. data/lib/myco/parser/ast/declare_category.rb +51 -0
  26. data/lib/myco/parser/ast/declare_decorator.rb +35 -0
  27. data/lib/myco/parser/ast/declare_file.rb +54 -0
  28. data/lib/myco/parser/ast/declare_meme.rb +44 -0
  29. data/lib/myco/parser/ast/declare_object.rb +75 -0
  30. data/lib/myco/parser/ast/declare_string.rb +37 -0
  31. data/lib/myco/parser/ast/invoke.rb +66 -0
  32. data/lib/myco/parser/ast/local_variable_access_ambiguous.rb +38 -0
  33. data/lib/myco/parser/ast/misc.rb +61 -0
  34. data/lib/myco/parser/ast/myco_module_scope.rb +58 -0
  35. data/lib/myco/parser/ast/quest.rb +82 -0
  36. data/lib/myco/parser/ast.rb +15 -0
  37. data/lib/myco/parser/builder.output +3995 -0
  38. data/lib/myco/parser/builder.racc +585 -0
  39. data/lib/myco/parser/builder.rb +1592 -0
  40. data/lib/myco/parser/lexer.rb +2306 -0
  41. data/lib/myco/parser/lexer.rl +393 -0
  42. data/lib/myco/parser/lexer_char_classes.rl +56 -0
  43. data/lib/myco/parser/lexer_common.rb +95 -0
  44. data/lib/myco/parser/lexer_skeleton.rl +154 -0
  45. data/lib/myco/parser/peg_parser.kpeg +759 -0
  46. data/lib/myco/parser/peg_parser.rb +7094 -0
  47. data/lib/myco/parser.rb +40 -0
  48. data/lib/myco/tools/OptionParser.my +38 -0
  49. data/lib/myco/tools/mycompile.my +51 -0
  50. data/lib/myco/toolset.rb +16 -0
  51. data/lib/myco/version.rb +22 -0
  52. data/lib/myco.rb +15 -0
  53. 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