myco 0.1.0.dev

Sign up to get free protection for your applications and to get access to all the features.
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