maroon 0.6.1 → 0.6.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (52) hide show
  1. checksums.yaml +7 -0
  2. data/Examples/Dijkstra/CalculateShortestDistance.rb +16 -12
  3. data/Examples/Dijkstra/calculate_shortest_path.rb +47 -27
  4. data/Examples/Dijkstra/data.rb +41 -14
  5. data/Examples/Dijkstra/dijkstra.rb +4 -3
  6. data/Examples/MoneyTransfer.rb +61 -60
  7. data/Examples/greeter.rb +8 -7
  8. data/Examples/meter.rb +35 -29
  9. data/Gemfile +9 -4
  10. data/LICENSE.txt +21 -21
  11. data/README.md +13 -0
  12. data/Rakefile +41 -1
  13. data/Test/Generate/method_info_test.rb +12 -0
  14. data/Test/{Greeter_test.rb → Greeter_test_disabled.rb} +24 -20
  15. data/Test/ImmutableQueue_test.rb +18 -0
  16. data/Test/MethodInfo_test.rb +65 -0
  17. data/Test/alltests.rb +1 -0
  18. data/Test/{source_assertions.rb → assertions.rb} +15 -7
  19. data/Test/bind_test.rb +13 -0
  20. data/Test/expression_test.rb +105 -0
  21. data/Test/method_call_test.rb +83 -0
  22. data/Test/self_test.rb +46 -0
  23. data/Test/stack_test.rb +17 -0
  24. data/Test/test_helper.rb +14 -0
  25. data/base/ImmutableStack.rb +32 -0
  26. data/base/MethodDefinition.rb +124 -0
  27. data/base/bind_rewriter.rb +58 -0
  28. data/base/immutable_queue.rb +50 -0
  29. data/base/maroon_base.rb +267 -0
  30. data/base/method_call.rb +78 -0
  31. data/base/method_info.rb +86 -0
  32. data/base/self.rb +60 -0
  33. data/generated/build.rb +13 -0
  34. data/generated/interpretation_context.rb +29 -0
  35. data/lib/Bind.rb +65 -0
  36. data/lib/Context.rb +187 -0
  37. data/lib/ImmutableQueue.rb +50 -0
  38. data/lib/ImmutableStack.rb +38 -0
  39. data/lib/MethodCall.rb +91 -0
  40. data/lib/MethodDefinition.rb +114 -0
  41. data/lib/MethodInfo.rb +78 -0
  42. data/lib/Self.rb +71 -0
  43. data/lib/build.rb +14 -0
  44. data/lib/interpretation_context.rb +30 -0
  45. data/lib/maroon/contracts.rb +43 -0
  46. data/lib/maroon/kernel.rb +2 -0
  47. data/lib/maroon/version.rb +3 -3
  48. data/maroon.gemspec +26 -26
  49. metadata +49 -31
  50. data/lib/Source_cleaner.rb +0 -34
  51. data/lib/maroon.rb +0 -165
  52. data/lib/rewriter.rb +0 -185
@@ -0,0 +1,38 @@
1
+ class ImmutableStack
2
+
3
+ def pop()
4
+ [@head, @tail]
5
+ end
6
+
7
+ def push(element)
8
+ ImmutableStack.new(element, self)
9
+ end
10
+
11
+ def self.empty()
12
+ @@empty ||= self.new(nil, nil)
13
+ end
14
+
15
+ def each()
16
+ yield(head)
17
+ t = tail
18
+ while t.!=(ImmutableStack.empty) do
19
+ h, t = t.pop
20
+ yield(h)
21
+ end
22
+
23
+ end
24
+
25
+ def initialize(h,t)
26
+ @head = h
27
+ @tail = t
28
+ self.freeze
29
+
30
+ end
31
+
32
+ private
33
+ attr_reader :head
34
+ attr_reader :tail
35
+
36
+
37
+
38
+ end
@@ -0,0 +1,91 @@
1
+ class MethodCall
2
+
3
+ def rewrite_call?()
4
+ method_name = method[2]
5
+ if (method[0] == :call) then
6
+ if (method[1] == nil) and ((method.length < 5) and (method[3] and ((method[3].length == 1) and (method[3][0] == :arglist)))) then
7
+ is_role = interpretation_context.roles.has_key?(method[3])
8
+ method[3] = (":@" + method[3].to_sym) if is_role
9
+ else
10
+ role_name, is_role_method = self_method_role_method_call?(method_name)
11
+ if is_role_method then
12
+ method[1] = nil
13
+ method[2] = ((("self_" + role_name.to_s) + "_") + method_name.to_s).to_sym
14
+ else
15
+ if interpretation_context.roles.has_key?(role_name) then
16
+ unless (method.length == 3) and ((method[1] == nil) and (method[2] == role_name)) then
17
+ contract_methods = interpretation_context.contracts[role_name] ||= {}
18
+ contract_methods[method_name] ||= 0
19
+ contract_methods[method_name] += 1
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
25
+
26
+ end
27
+
28
+ def initialize(method,interpretation_context)
29
+ raise("No method supplied") unless method
30
+ @method = method
31
+ @interpretation_context = interpretation_context
32
+
33
+ end
34
+
35
+ def self.call(*args)
36
+ arity = MethodCall.method(:new).arity
37
+ newArgs = args[0..arity-1]
38
+ obj = MethodCall.new *newArgs
39
+ if arity < args.length
40
+ methodArgs = args[arity..-1]
41
+ obj.rewrite_call? *methodArgs
42
+ else
43
+ obj.rewrite_call?
44
+ end
45
+ end
46
+
47
+ def call(*args);rewrite_call? *args; end
48
+
49
+ private
50
+ attr_reader :interpretation_context
51
+ attr_reader :method
52
+
53
+
54
+ def self_interpretation_context_role_aliases()
55
+ (@interpretation_context.role_aliases or {})
56
+ end
57
+
58
+ def self_method_call_in_block?()
59
+ @in_block unless (@in_block == nil)
60
+ @in_block = (method and (method[0] == :lvar))
61
+
62
+ end
63
+
64
+ def self_method_get_role_definition()
65
+ is_call_expression = (method and (method[0] == :call))
66
+ self_is_instance_expression = (is_call_expression and (not method[1]))
67
+ role_name = nil
68
+ role_name = method[2] if self_is_instance_expression
69
+ if (not self_is_instance_expression) and method[1] then
70
+ if (method[1][1] == nil) and (method[1][0] == :call) then
71
+ role_name = method[1][2]
72
+ end
73
+ if (method[1][0] == :lvar) then
74
+ role_name = self_interpretation_context_role_aliases[method[1][1]]
75
+ end
76
+ end
77
+ role = role_name ? (interpretation_context.roles[role_name]) : (nil)
78
+ [role, role ? (role_name) : (nil)]
79
+
80
+ end
81
+
82
+ def self_method_role_method_call?(method_name)
83
+ return [nil, nil] unless method
84
+ role, role_name = self_method_get_role_definition
85
+ is_role_method = (role and role.has_key?(method_name))
86
+ return [role_name, is_role_method]
87
+
88
+ end
89
+
90
+
91
+ end
@@ -0,0 +1,114 @@
1
+ class MethodDefinition
2
+
3
+ def rebind()
4
+ @exp, @expressions = expressions.pop
5
+ @block, @potential_bind = nil
6
+ if @exp and (@exp.instance_of?(Sexp) and (@exp[0] == :iter)) then
7
+ @exp[(1..-1)].each do |expr|
8
+ if expr and (expr.length and (expr[0] == :block)) then
9
+ @block, @potential_bind = expr, expr[1]
10
+ end
11
+ end
12
+ end
13
+ @expressions = @exp.instance_of?(Sexp) ? (@expressions.push_array(exp)) : (@expressions)
14
+
15
+ end
16
+
17
+ def transform()
18
+ until self_expressions_empty? do
19
+ (self_block_transform
20
+ if exp and exp.instance_of?(Sexp) then
21
+ is_indexer = ((exp[0] == :call) and ((exp[1] == nil) and ((exp[2] == :[]) or (exp[2] == :[]=))))
22
+ if (is_indexer or (exp[0] == :self)) and @interpretation_context.defining_role then
23
+ Self.new(exp, interpretation_context).execute
24
+ end
25
+ if (exp[0] == :call) then
26
+ MethodCall.new(exp, interpretation_context).rewrite_call?
27
+ end
28
+ end
29
+ rebind)
30
+ end
31
+ end
32
+
33
+ def initialize(exp,interpretationcontext)
34
+ no_exp = "No expression supplied".to_sym
35
+ no_ctx = "No interpretation context".to_sym
36
+ raise(no_exp) unless exp
37
+ raise(no_ctx) unless interpretationcontext
38
+ @interpretation_context = interpretationcontext
39
+ @expressions = ImmutableQueue.empty.push(exp)
40
+ rebind
41
+
42
+ end
43
+
44
+ def self.call(*args)
45
+ arity = MethodDefinition.method(:new).arity
46
+ newArgs = args[0..arity-1]
47
+ obj = MethodDefinition.new *newArgs
48
+ if arity < args.length
49
+ methodArgs = args[arity..-1]
50
+ obj.transform *methodArgs
51
+ else
52
+ obj.transform
53
+ end
54
+ end
55
+
56
+ def call(*args);transform *args; end
57
+
58
+ private
59
+ attr_reader :interpretation_context
60
+ attr_reader :exp
61
+ attr_reader :expressions
62
+ attr_reader :potential_bind
63
+ attr_reader :block
64
+
65
+
66
+ def self_interpretation_context_addalias(key,value)
67
+ @interpretation_context.role_aliases[key] = value
68
+ end
69
+
70
+ def self_expressions_empty?()
71
+ (expressions == ImmutableQueue.empty)
72
+ end
73
+
74
+ def self_potential_bind_is_bind?()
75
+ potential_bind and (potential_bind.length and ((potential_bind[0] == :call) and ((potential_bind[1] == nil) and (potential_bind[2] == :bind))))
76
+ end
77
+
78
+ def self_block_transform()
79
+ if block then
80
+ @expressions.push_array(block[(1..-1)]) if self_block_transform_bind?
81
+ end
82
+ end
83
+
84
+ def self_block_transform_bind?()
85
+ self_potential_bind_is_bind? and self_block_rewrite
86
+ end
87
+
88
+ def self_block_rewrite()
89
+ changed = false
90
+ arguments = potential_bind[3]
91
+ if arguments and (arguments[0] == :hash) then
92
+ block.delete_at(1)
93
+ count = ((arguments.length - 1) / 2)
94
+ (1..count).each do |j|
95
+ temp = (j * 2)
96
+ local = arguments[(temp - 1)][1]
97
+ local = local[1] if local.instance_of?(Sexp)
98
+ raise("invalid value for role alias") unless local.instance_of?(Symbol)
99
+ aliased_role = arguments[temp][1]
100
+ aliased_role = aliased_role[1] if aliased_role.instance_of?(Sexp)
101
+ unless aliased_role.instance_of?(Symbol) and interpretation_context.roles.has_key?(aliased_role) then
102
+ raise(((aliased_role.to_s + "used in binding is an unknown role ") + roles.to_s))
103
+ end
104
+ self_interpretation_context_addalias(local, aliased_role)
105
+ Bind.new(local, aliased_role, block).execute
106
+ changed = true
107
+ end
108
+ end
109
+ changed
110
+
111
+ end
112
+
113
+
114
+ end
@@ -0,0 +1,78 @@
1
+ class MethodInfo
2
+
3
+ def initialize(on_self,block_source,is_private)
4
+ raise("Must be S-Expressions") unless block_source.instance_of?(Sexp)
5
+ if on_self.instance_of?(Hash) then
6
+ @block = on_self[:block]
7
+ @on_self = on_self[:self]
8
+ else
9
+ @on_self = on_self
10
+ end
11
+ @block_source = block_source
12
+ @private = is_private
13
+ self.freeze
14
+
15
+ end
16
+
17
+ def is_private()
18
+ @private
19
+ end
20
+
21
+ def build_as_context_method(context_method_name,interpretation_context)
22
+ MethodDefinition.new(self_block_source_body, interpretation_context).transform
23
+ body = Ruby2Ruby.new.process(self_block_source_body)
24
+ args = if self_block_source_arguments then
25
+ (("(" + self_block_source_arguments) + ")")
26
+ else
27
+ ""
28
+ end
29
+ on = on_self ? ("self.") : ("")
30
+ (((((("\ndef " + on.to_s) + context_method_name.to_s) + args) + "\n ") + body) + "\n end\n")
31
+
32
+ end
33
+
34
+ private
35
+ attr_reader :on_self
36
+ attr_reader :block
37
+ attr_reader :block_source
38
+
39
+
40
+ def self_block_source_get_arguments()
41
+ sexp = block_source[2]
42
+ return nil unless sexp
43
+ return sexp[1] if (sexp[0] == :lasgn)
44
+ return [] if (sexp[1] == nil)
45
+ sexp = sexp[(1..-1)]
46
+ args = []
47
+ sexp.each do |e|
48
+ (args << (if e.instance_of?(Symbol) then
49
+ e
50
+ else
51
+ (e[0] == :splat) ? (("*" + e[1][1].to_s)) : (e[1])
52
+ end))
53
+ end
54
+ if block then
55
+ b = ("&" + block.to_s)
56
+ if args then
57
+ args = [args] unless args.instance_of?(Array)
58
+ (args << b)
59
+ else
60
+ args = [b]
61
+ end
62
+ end
63
+ args
64
+
65
+ end
66
+
67
+ def self_block_source_arguments()
68
+ args = self_block_source_get_arguments
69
+ args and args.length ? (args.join(",")) : (nil)
70
+
71
+ end
72
+
73
+ def self_block_source_body()
74
+ block_source[3]
75
+ end
76
+
77
+
78
+ end
@@ -0,0 +1,71 @@
1
+ class Self
2
+
3
+ def initialize(abstract_syntax_tree,interpretationcontext)
4
+ raise("Interpretation context missing") unless interpretationcontext
5
+ unless interpretationcontext.defining_role then
6
+ raise("Must have a defining role")
7
+ end
8
+ @abstract_syntax_tree = abstract_syntax_tree
9
+ @interpretation_context = interpretationcontext
10
+
11
+ end
12
+
13
+ def execute()
14
+ if abstract_syntax_tree then
15
+ if (abstract_syntax_tree[0] == :self) then
16
+ abstract_syntax_tree[0] = :call
17
+ abstract_syntax_tree[1] = nil
18
+ abstract_syntax_tree[2] = interpretation_context.defining_role
19
+ else
20
+ if (abstract_syntax_tree[0] == :call) and (abstract_syntax_tree[1] == nil) then
21
+ method_name = abstract_syntax_tree[2]
22
+ if ((method_name == :[]) or (method_name == :[]=)) then
23
+ get_role = Sexp.new
24
+ get_role[0] = :call
25
+ get_role[1] = nil
26
+ get_role[2] = interpretation_context.defining_role
27
+ abstract_syntax_tree[1] = get_role
28
+ end
29
+ else
30
+ if abstract_syntax_tree.instance_of?(Sexp) then
31
+ if self_abstract_syntax_tree_is_indexer_call_on_self then
32
+ getter = new(Sexp.new)
33
+ getter[0] = :call
34
+ getter[1] = nil
35
+ getter[2] = interpretation_context.defining_role
36
+ arglist = Sexp.new
37
+ getter[3] = arglist
38
+ arglist[0] = :arglist
39
+ abstract_syntax_tree[1] = getter
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
46
+
47
+ def self.call(*args)
48
+ arity = Self.method(:new).arity
49
+ newArgs = args[0..arity-1]
50
+ obj = Self.new *newArgs
51
+ if arity < args.length
52
+ methodArgs = args[arity..-1]
53
+ obj.execute *methodArgs
54
+ else
55
+ obj.execute
56
+ end
57
+ end
58
+
59
+ def call(*args);execute *args; end
60
+
61
+ private
62
+ attr_reader :abstract_syntax_tree
63
+ attr_reader :interpretation_context
64
+
65
+
66
+ def self_abstract_syntax_tree_is_indexer_call_on_self()
67
+ (abstract_syntax_tree.length == 4) and ((abstract_syntax_tree[0] == :call) and ((abstract_syntax_tree[1] == nil) and ((abstract_syntax_tree[2] == :[]) and (abstract_syntax_tree[3][0] == :argslist))))
68
+ end
69
+
70
+
71
+ end
@@ -0,0 +1,14 @@
1
+ require 'sorcerer'
2
+ require 'sourcify'
3
+
4
+ require_relative 'self'
5
+ require_relative 'bind'
6
+ require_relative 'ImmutableQueue'
7
+ require_relative 'ImmutableStack'
8
+ require_relative 'interpretation_context'
9
+ require_relative 'MethodDefinition'
10
+ require_relative 'MethodInfo'
11
+ require_relative 'MethodCall'
12
+
13
+ require_relative 'Context'
14
+
@@ -0,0 +1,30 @@
1
+ class InterpretationContext
2
+ def contracts
3
+ (@contracts ||= {})
4
+ end
5
+
6
+ def roles
7
+ (@roles ||= {})
8
+ end
9
+
10
+ def role_aliases
11
+ (@role_aliases ||= {})
12
+ end
13
+
14
+ def defining_role
15
+ @defining_role
16
+ end
17
+
18
+ def initialize(roles, contracts, role_aliases, defining_role)
19
+ raise "Aliases must be a hash" unless role_aliases.instance_of? Hash or role_aliases == nil
20
+ raise "Roles must be a hash" unless roles.instance_of? Hash or roles == nil
21
+ raise "Contracts must be a hash" unless contracts.instance_of? Hash or contracts == nil
22
+
23
+ @roles = roles
24
+ raise "Defining role is undefined" if defining_role && (!self.roles.has_key? defining_role)
25
+
26
+ @contracts = contracts
27
+ @role_aliases = role_aliases
28
+ @defining_role = defining_role
29
+ end
30
+ end
@@ -0,0 +1,43 @@
1
+ if Kernel::const_defined? :MiniTest
2
+ class ContextAsserterBase < MiniTest::Unit::TestCase
3
+
4
+ end
5
+ else
6
+ class ContextAsserterBase
7
+
8
+ end
9
+ end
10
+
11
+ class ContextAsserter < ContextAsserterBase
12
+ def initialize(contracts, obj, is_asserting = true)
13
+ raise 'Contracts must be supplied' unless contracts
14
+ @obj = obj
15
+ @contracts = contracts
16
+ @is_asserting = is_asserting
17
+ end
18
+
19
+ def is_test
20
+ Kernel::const_defined? :MiniTest
21
+ end
22
+
23
+ def can_play(role)
24
+ msg = "#{@is_asserting ? 'Was' : "wasn't"} expected to be able to play #{role}".intern
25
+ if is_test
26
+ assert_equal(@is_asserting, can_play?(role), msg)
27
+ else
28
+ raise msg if @is_asserting != can_play?(role)
29
+ end
30
+
31
+ end
32
+
33
+ private
34
+ def can_play?(role)
35
+ required_methods = @contracts[role]
36
+ methods = @obj.public_methods
37
+ missing = required_methods.select do |rm|
38
+ !methods.include? rm.to_sym
39
+ end
40
+ missing.length == 0
41
+ end
42
+ end
43
+ Context::with_contracts = true