sbyc 0.1.3 → 0.1.4
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.
- data/lib/sbyc.rb +1 -5
- data/lib/sbyc/codetree.rb +79 -77
- data/lib/sbyc/codetree/ast_node.rb +117 -115
- data/lib/sbyc/codetree/eval/ast_node_ext.rb +33 -31
- data/lib/sbyc/codetree/eval/functional_eval.rb +33 -31
- data/lib/sbyc/codetree/eval/object_eval.rb +33 -31
- data/lib/sbyc/codetree/matching/ast_node_ext.rb +13 -11
- data/lib/sbyc/codetree/matching/match_data.rb +25 -23
- data/lib/sbyc/codetree/matching/matcher.rb +73 -71
- data/lib/sbyc/codetree/name2x/delegate.rb +56 -54
- data/lib/sbyc/codetree/name2x/module_delegate.rb +23 -22
- data/lib/sbyc/codetree/proc_parser.rb +101 -99
- data/lib/sbyc/codetree/producing/producer.rb +69 -67
- data/lib/sbyc/codetree/producing/tracing_methods.rb +66 -64
- data/lib/sbyc/codetree/rewriting/class_methods.rb +15 -13
- data/lib/sbyc/codetree/rewriting/compiler.rb +27 -25
- data/lib/sbyc/codetree/rewriting/instance_methods.rb +80 -78
- data/lib/sbyc/codetree/rewriting/match.rb +51 -49
- data/lib/sbyc/shortspaces.rb +3 -0
- data/lib/sbyc/type_system.rb +4 -2
- data/lib/sbyc/type_system/contract.rb +38 -36
- data/lib/sbyc/type_system/errors.rb +8 -6
- data/lib/sbyc/type_system/ruby.rb +137 -121
- data/test/spec/spec_helper.rb +1 -1
- data/test/spec/unit/sbyc/type_system/ruby/boolean.spec +14 -0
- data/test/spec/unit/sbyc/type_system/ruby/coerce.spec +10 -1
- metadata +6 -4
@@ -1,15 +1,17 @@
|
|
1
|
-
module
|
2
|
-
module
|
3
|
-
|
4
|
-
|
1
|
+
module SByC
|
2
|
+
module CodeTree
|
3
|
+
module Rewriting
|
4
|
+
class Rewriter
|
5
|
+
module ClassMethods
|
5
6
|
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
7
|
+
# Compiles a rewriter
|
8
|
+
def compile(code = nil, &block)
|
9
|
+
Rewriter::Compiler::compile(code || block)
|
10
|
+
end
|
10
11
|
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
end # module CodeTree
|
12
|
+
end # module ClassMethods
|
13
|
+
extend ClassMethods
|
14
|
+
end # class Rewriter
|
15
|
+
end # module Rewriting
|
16
|
+
end # module CodeTree
|
17
|
+
end # module SByC
|
@@ -1,28 +1,30 @@
|
|
1
|
-
module
|
2
|
-
module
|
3
|
-
|
4
|
-
|
1
|
+
module SByC
|
2
|
+
module CodeTree
|
3
|
+
module Rewriting
|
4
|
+
class Rewriter
|
5
|
+
module Compiler
|
5
6
|
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
}
|
13
|
-
r.rule(:upon){|r, upon, upon_match, upon_rule|
|
14
|
-
matcher = CodeTree::matcher(upon_match)
|
15
|
-
upon_expr = CodeTree::expr(upon_rule)
|
16
|
-
r.scope.rule(matcher){|compiled, matched, *matched_children|
|
17
|
-
upon_expr.apply(compiled, (matcher =~ matched))
|
7
|
+
# Compiles an Ast to a Rewriter instance
|
8
|
+
def compile(ast)
|
9
|
+
compiled = Rewriter.new
|
10
|
+
Rewriter.new{|r|
|
11
|
+
r.rule(:rewrite){|r, node, *children|
|
12
|
+
r.apply(children)
|
18
13
|
}
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
14
|
+
r.rule(:upon){|r, upon, upon_match, upon_rule|
|
15
|
+
matcher = CodeTree::matcher(upon_match)
|
16
|
+
upon_expr = CodeTree::expr(upon_rule)
|
17
|
+
r.scope.rule(matcher){|compiled, matched, *matched_children|
|
18
|
+
upon_expr.apply(compiled, (matcher =~ matched))
|
19
|
+
}
|
20
|
+
}
|
21
|
+
}.rewrite(ast, compiled)
|
22
|
+
compiled
|
23
|
+
end
|
24
|
+
module_function :compile
|
24
25
|
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
end # module CodeTree
|
26
|
+
end # module Compiler
|
27
|
+
end # class Rewriter
|
28
|
+
end # module Rewriting
|
29
|
+
end # module CodeTree
|
30
|
+
end # module SByC
|
@@ -1,92 +1,94 @@
|
|
1
|
-
module
|
2
|
-
module
|
3
|
-
|
4
|
-
|
1
|
+
module SByC
|
2
|
+
module CodeTree
|
3
|
+
module Rewriting
|
4
|
+
class Rewriter
|
5
|
+
module InstanceMethods
|
5
6
|
|
6
|
-
|
7
|
-
|
7
|
+
# Installed rules
|
8
|
+
attr_reader :rules
|
8
9
|
|
9
|
-
|
10
|
-
|
10
|
+
# The scope
|
11
|
+
attr_reader :scope
|
11
12
|
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
13
|
+
# Creates a Rewriter instance
|
14
|
+
def initialize
|
15
|
+
@rules = []
|
16
|
+
yield(self) if block_given?
|
17
|
+
end
|
17
18
|
|
18
|
-
|
19
|
-
|
20
|
-
|
19
|
+
def ANY() Rewriter::Match::ANY; end
|
20
|
+
def BRANCH() Rewriter::Match::BRANCH; end
|
21
|
+
def LEAF() Rewriter::Match::LEAF; end
|
21
22
|
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
23
|
+
# Adds a rule to the engine
|
24
|
+
def rule(match, &block)
|
25
|
+
@rules << Rewriter::Match.coerce(match, block)
|
26
|
+
end
|
26
27
|
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
28
|
+
# Rewrites some code
|
29
|
+
def rewrite(code = nil, scope = nil, &block)
|
30
|
+
@stack = []
|
31
|
+
@scope = block ? code : scope
|
32
|
+
apply(CodeTree.coerce(block || code))
|
33
|
+
ensure
|
34
|
+
@stack = nil
|
35
|
+
@scope = nil
|
36
|
+
end
|
36
37
|
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
38
|
+
# Returns the current context node, being the top node on the stack
|
39
|
+
def context_node
|
40
|
+
@stack.last
|
41
|
+
end
|
41
42
|
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
43
|
+
# Applies rules on a node
|
44
|
+
def apply(*args)
|
45
|
+
case node = apply_args_conventions(*args)
|
46
|
+
when CodeTree::AstNode
|
47
|
+
apply_on_node(node)
|
48
|
+
when Array
|
49
|
+
node.collect{|c| c.kind_of?(CodeTree::AstNode) ? apply_on_node(c) : c}
|
50
|
+
else
|
51
|
+
node
|
52
|
+
end
|
51
53
|
end
|
52
|
-
end
|
53
54
|
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
55
|
+
# Applies on a single node
|
56
|
+
def apply_on_node(node)
|
57
|
+
raise ArgumentError, "Node expected, #{node.inspect} received" unless node.kind_of?(CodeTree::AstNode)
|
58
|
+
@stack.push(node)
|
59
|
+
rule = @rules.find{|r| r === node}
|
60
|
+
result = (rule ? rule.apply(self, node) : nil)
|
61
|
+
@stack.pop
|
62
|
+
result
|
63
|
+
end
|
63
64
|
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
65
|
+
# Produces a node by copying another one
|
66
|
+
def node(function, *children)
|
67
|
+
CodeTree::AstNode.coerce([function, children.flatten])
|
68
|
+
end
|
68
69
|
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
70
|
+
#
|
71
|
+
# Applies conventions announced by the _apply_ method.
|
72
|
+
#
|
73
|
+
def apply_args_conventions(*args)
|
74
|
+
if args.size == 1 and args[0].kind_of?(CodeTree::AstNode)
|
75
|
+
args[0]
|
76
|
+
elsif args.size > 1 and args[0].kind_of?(Symbol)
|
77
|
+
function = args.shift
|
78
|
+
children = args.collect{|c| apply_args_conventions(c)}.flatten
|
79
|
+
CodeTree::AstNode.coerce([function, children])
|
80
|
+
elsif args.all?{|a| a.kind_of?(CodeTree::AstNode)}
|
81
|
+
args
|
82
|
+
elsif args.size == 1
|
83
|
+
args[0]
|
84
|
+
else
|
85
|
+
raise ArgumentError, "Unable to apply on #{args.inspect} (#{args.size})", caller
|
86
|
+
end
|
85
87
|
end
|
86
|
-
end
|
87
88
|
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
end # module CodeTree
|
89
|
+
end # module InstanceMethods
|
90
|
+
include InstanceMethods
|
91
|
+
end # class Rewriter
|
92
|
+
end # module Rewriting
|
93
|
+
end # module CodeTree
|
94
|
+
end # module SByC
|
@@ -1,59 +1,61 @@
|
|
1
|
-
module
|
2
|
-
module
|
3
|
-
|
4
|
-
class
|
1
|
+
module SByC
|
2
|
+
module CodeTree
|
3
|
+
module Rewriting
|
4
|
+
class Rewriter
|
5
|
+
class Match
|
5
6
|
|
6
|
-
|
7
|
-
|
7
|
+
# Matches any node
|
8
|
+
ANY = lambda{|ast_node| true}
|
8
9
|
|
9
|
-
|
10
|
-
|
10
|
+
# Matches a branch node
|
11
|
+
BRANCH = lambda{|ast_node| ast_node.kind_of?(CodeTree::AstNode) and ast_node.branch?}
|
11
12
|
|
12
|
-
|
13
|
-
|
13
|
+
# Matches a leaf node
|
14
|
+
LEAF = lambda{|ast_node| ast_node.kind_of?(CodeTree::AstNode) and ast_node.leaf?}
|
14
15
|
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
16
|
+
# Coerce argument to a Match instance
|
17
|
+
def self.coerce(arg, block)
|
18
|
+
case arg
|
19
|
+
when Proc
|
20
|
+
Match.new(arg, block)
|
21
|
+
when Symbol
|
22
|
+
Match.new(lambda{|node| node.kind_of?(CodeTree::AstNode) and node.name == arg}, block)
|
23
|
+
when CodeTree::Matcher
|
24
|
+
Match.new(arg, block)
|
25
|
+
when "."
|
26
|
+
Match.new(Match::ANY, block)
|
27
|
+
when "*"
|
28
|
+
Match.new(Match::BRANCH, block)
|
29
|
+
when "@*", "_"
|
30
|
+
Match.new(Match::LEAF, block)
|
31
|
+
else
|
32
|
+
raise "Unexpected rule #{arg.class} #{arg.inspect}"
|
33
|
+
end
|
32
34
|
end
|
33
|
-
end
|
34
35
|
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
36
|
+
# Creates a match instance
|
37
|
+
def initialize(predicate, block)
|
38
|
+
@predicate, @block = predicate, block
|
39
|
+
end
|
39
40
|
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
41
|
+
# Does this match
|
42
|
+
def matches?(ast_node)
|
43
|
+
@predicate.call(ast_node)
|
44
|
+
end
|
45
|
+
alias :=== :matches?
|
45
46
|
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
47
|
+
# Applies this match
|
48
|
+
def apply(rewriter, ast_node)
|
49
|
+
case ast_node
|
50
|
+
when CodeTree::AstNode
|
51
|
+
@block.call(rewriter, ast_node, *ast_node.children)
|
52
|
+
else
|
53
|
+
ast_node
|
54
|
+
end
|
53
55
|
end
|
54
|
-
end
|
55
56
|
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
end # module CodeTree
|
57
|
+
end # class Match
|
58
|
+
end # class Rewriter
|
59
|
+
end # module Rewriting
|
60
|
+
end # module CodeTree
|
61
|
+
end # module SByC
|
data/lib/sbyc/type_system.rb
CHANGED
@@ -1,8 +1,10 @@
|
|
1
1
|
#
|
2
2
|
# Implements a type system abstraction.
|
3
3
|
#
|
4
|
-
module
|
5
|
-
|
4
|
+
module SByC
|
5
|
+
module TypeSystem
|
6
|
+
end # module TypeSystem
|
7
|
+
end # module SByC
|
6
8
|
require 'sbyc/type_system/contract'
|
7
9
|
require 'sbyc/type_system/errors'
|
8
10
|
require 'sbyc/type_system/ruby'
|
@@ -1,42 +1,44 @@
|
|
1
|
-
module
|
2
|
-
|
3
|
-
# Defines the abstract contract that a TypeSystem should implement.
|
4
|
-
#
|
5
|
-
module Contract
|
6
|
-
|
1
|
+
module SByC
|
2
|
+
module TypeSystem
|
7
3
|
#
|
8
|
-
#
|
4
|
+
# Defines the abstract contract that a TypeSystem should implement.
|
9
5
|
#
|
10
|
-
|
11
|
-
end
|
6
|
+
module Contract
|
12
7
|
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
#
|
19
|
-
# @raise NoSuchLiteralError if value cannot be expressed as a literal
|
20
|
-
#
|
21
|
-
def to_literal(value)
|
22
|
-
end
|
8
|
+
#
|
9
|
+
# Returns the type of a value
|
10
|
+
#
|
11
|
+
def type_of(value)
|
12
|
+
end
|
23
13
|
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
14
|
+
#
|
15
|
+
# Converts _value_ to a literal and returns it.
|
16
|
+
#
|
17
|
+
# This method should always be such that:
|
18
|
+
# v == parse_literal(to_literal(v))
|
19
|
+
#
|
20
|
+
# @raise NoSuchLiteralError if value cannot be expressed as a literal
|
21
|
+
#
|
22
|
+
def to_literal(value)
|
23
|
+
end
|
32
24
|
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
25
|
+
#
|
26
|
+
# Parse _str_ value literal and returns real value.
|
27
|
+
#
|
28
|
+
# @raise InvalidValueLiteralError if str does not look like a valid
|
29
|
+
# value literal
|
30
|
+
#
|
31
|
+
def parse_literal(str)
|
32
|
+
end
|
33
|
+
|
34
|
+
#
|
35
|
+
# Coerces a string to a given class.
|
36
|
+
#
|
37
|
+
# @raise CoercionError if something goes wrong
|
38
|
+
#
|
39
|
+
def coerce(str, clazz)
|
40
|
+
end
|
40
41
|
|
41
|
-
|
42
|
-
end # module TypeSystem
|
42
|
+
end # module Contract
|
43
|
+
end # module TypeSystem
|
44
|
+
end # module SByC
|