maroon 0.6.1 → 0.6.5

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 (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,86 @@
1
+ context :MethodInfo do
2
+ initialize do |on_self, block_source, is_private|
3
+ raise 'Must be S-Expressions' unless block_source.instance_of? Sexp
4
+
5
+ if on_self.instance_of? Hash
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
+ role :on_self do
18
+ end
19
+
20
+ role :block do
21
+ end
22
+
23
+ role :block_source do
24
+ get_arguments {
25
+ sexp = block_source[2]
26
+ return nil unless sexp
27
+ return sexp[1] if sexp[0] == :lasgn
28
+ return [] if sexp[1] == nil
29
+ sexp = sexp[1..-1]
30
+ args = []
31
+ sexp.each do |e|
32
+ args << if e.instance_of? Symbol
33
+ e
34
+ else
35
+ if e[0] == :splat
36
+ '*' + e[1][1].to_s
37
+ else
38
+ e[1]
39
+ end
40
+ end
41
+ end
42
+
43
+ if block
44
+ b = '&' + block.to_s
45
+ if args
46
+ unless args.instance_of? Array
47
+ args = [args]
48
+ end
49
+ args << b
50
+ else
51
+ args = [b]
52
+ end
53
+ end
54
+ args
55
+ }
56
+
57
+ arguments {
58
+ args = block_source.get_arguments
59
+ args && args.length ? args.join(',') : nil
60
+ }
61
+
62
+ body {
63
+ block_source[3]
64
+ }
65
+ end
66
+
67
+ is_private do
68
+ @private
69
+ end
70
+
71
+ build_as_context_method do |context_method_name, interpretation_context|
72
+ MethodDefinition.new(block_source.body, interpretation_context).transform
73
+ body = Ruby2Ruby.new.process(block_source.body)
74
+ args = block_source.arguments ? '(' + block_source.arguments + ')' : ""
75
+ on = if on_self then
76
+ 'self.'
77
+ else
78
+ ''
79
+ end
80
+ '
81
+ def ' + on.to_s + context_method_name.to_s + args +'
82
+ ' + body +'
83
+ end
84
+ '
85
+ end
86
+ end
@@ -0,0 +1,60 @@
1
+ context :Self, :execute do
2
+ initialize do |abstract_syntax_tree, interpretationcontext|
3
+ raise 'Interpretation context missing' unless interpretationcontext
4
+ raise 'Must have a defining role' unless interpretationcontext.defining_role
5
+
6
+ @abstract_syntax_tree = abstract_syntax_tree
7
+ @interpretation_context = interpretationcontext
8
+ end
9
+
10
+ role :abstract_syntax_tree do
11
+ is_indexer_call_on_self do
12
+ abstract_syntax_tree.length == 4 &&
13
+ abstract_syntax_tree[0] == :call &&
14
+ abstract_syntax_tree[1] == nil &&
15
+ abstract_syntax_tree[2] == :[] &&
16
+ abstract_syntax_tree[3][0] == :argslist
17
+ end
18
+
19
+ end
20
+ role :interpretation_context do
21
+ defining_role do
22
+ interpretation_context.defining_role
23
+ end
24
+ end
25
+
26
+ # rewrites a call to self in a role method to a call to the role player accessor
27
+ # which is subsequently rewritten to a call to the instance variable itself
28
+ # in the case where no role method is called on the role player
29
+ # It's rewritten to an instance call on the context object if a role method is called
30
+ execute do
31
+ if abstract_syntax_tree
32
+ if abstract_syntax_tree[0] == :self #if self is used in a role method, then rewrite to role getter
33
+ abstract_syntax_tree[0] = :call
34
+ abstract_syntax_tree[1] = nil
35
+ abstract_syntax_tree[2] = interpretation_context.defining_role
36
+ elsif abstract_syntax_tree[0] == :call and abstract_syntax_tree[1] == nil
37
+ method_name = abstract_syntax_tree[2]
38
+ #self is removed from S-expressions
39
+ if method_name == :[] or method_name == :[]=
40
+ get_role = Sexp.new
41
+ get_role[0] = :call
42
+ get_role[1] = nil
43
+ get_role[2] = interpretation_context.defining_role
44
+ abstract_syntax_tree[1] = get_role
45
+ end
46
+ elsif abstract_syntax_tree.instance_of? Sexp
47
+ if abstract_syntax_tree.is_indexer_call_on_self
48
+ getter = new Sexp.new
49
+ getter[0] = :call
50
+ getter[1] = nil
51
+ getter[2] = interpretation_context.defining_role
52
+ arglist = Sexp.new
53
+ getter[3] = arglist
54
+ arglist[0] = :arglist
55
+ abstract_syntax_tree[1] = getter
56
+ end
57
+ end
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,13 @@
1
+ require 'sorcerer'
2
+ require 'sourcify'
3
+
4
+ require_relative './Self'
5
+ require_relative './Bind'
6
+ require_relative './ImmutableStack'
7
+ require_relative './ImmutableQueue'
8
+ require_relative './interpretation_context'
9
+ require_relative './MethodInfo'
10
+ require_relative './MethodCall'
11
+ require_relative './MethodDefinition'
12
+ require_relative './Context'
13
+
@@ -0,0 +1,29 @@
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
+ @contracts = contracts
26
+ @role_aliases = role_aliases
27
+ @defining_role = defining_role
28
+ end
29
+ end
@@ -0,0 +1,65 @@
1
+ class Bind
2
+
3
+ def initialize(local,aliased_role,block)
4
+ @local = local
5
+ @aliased_role = aliased_role
6
+ @block = block
7
+
8
+ end
9
+
10
+ def execute()
11
+ must_b_sym = "aliased_role must be a Symbol".to_sym
12
+ local_must_b_sym = "local must be a Symbol".to_sym
13
+ raise(must_b_sym) unless aliased_role.instance_of?(Symbol)
14
+ raise(local_must_b_sym) unless local.instance_of?(Symbol)
15
+ aliased_field = ("@" + aliased_role.to_s).to_sym
16
+ temp_symbol = ("temp____" + aliased_role.to_s).to_sym
17
+ assignment = Sexp.new
18
+ assignment[0] = :iasgn
19
+ assignment[1] = aliased_field
20
+ load_arg = Sexp.new
21
+ load_arg[0] = :lvar
22
+ load_arg[1] = local
23
+ assignment[2] = load_arg
24
+ block.insert(1, assignment)
25
+ assignment = Sexp.new
26
+ assignment[0] = :lasgn
27
+ assignment[1] = temp_symbol
28
+ load_field = Sexp.new
29
+ load_field[0] = :ivar
30
+ load_field[1] = aliased_field
31
+ assignment[2] = load_field
32
+ block.insert(1, assignment)
33
+ assignment = Sexp.new
34
+ assignment[0] = :iasgn
35
+ assignment[1] = aliased_field
36
+ load_temp = Sexp.new
37
+ load_temp[0] = :lvar
38
+ load_temp[1] = temp_symbol
39
+ assignment[2] = load_temp
40
+ block[block.length] = assignment
41
+
42
+ end
43
+
44
+ def self.call(*args)
45
+ arity = Bind.method(:new).arity
46
+ newArgs = args[0..arity-1]
47
+ obj = Bind.new *newArgs
48
+ if arity < args.length
49
+ methodArgs = args[arity..-1]
50
+ obj.execute *methodArgs
51
+ else
52
+ obj.execute
53
+ end
54
+ end
55
+
56
+ def call(*args);execute *args; end
57
+
58
+ private
59
+ attr_reader :block
60
+ attr_reader :local
61
+ attr_reader :aliased_role
62
+
63
+
64
+
65
+ end
@@ -0,0 +1,187 @@
1
+ class Context
2
+
3
+ def self.define(*args,&block)
4
+ @@with_contracts ||= nil
5
+ @@generate_file_path ||= nil
6
+ (alias :method_missing :role_or_interaction_method)
7
+ base_class, ctx, default_interaction, name = self.send(:create_context_factory, args, block)
8
+ if (args.last.instance_of?(FalseClass) or args.last.instance_of?(TrueClass)) then
9
+ ctx.generate_files_in(args.last)
10
+ end
11
+ return ctx.send(:finalize, name, base_class, default_interaction)
12
+
13
+ end
14
+
15
+ def self.generate_files_in(*args,&b)
16
+ if block_given? then
17
+ return role_or_interaction_method(:generate_files_in, *args, &b)
18
+ end
19
+ @@generate_file_path = args[0]
20
+
21
+ end
22
+
23
+ private
24
+
25
+ def self.with_contracts(*args)
26
+ return @@with_contracts if (args.length == 0)
27
+ value = args[0]
28
+ if @@with_contracts and (not value) then
29
+ raise("make up your mind! disabling contracts during execution will result in undefined behavior")
30
+ end
31
+ @@with_contracts = value
32
+
33
+ end
34
+
35
+ def role(*args,&b)
36
+ role_name = args[0]
37
+ if (args.length.!=(1) or (not role_name.instance_of?(Symbol))) then
38
+ return role_or_interaction_method(:role, *args, &b)
39
+ end
40
+ @defining_role = role_name
41
+ @roles[role_name] = Hash.new
42
+ yield if block_given?
43
+ @defining_role = nil
44
+
45
+ end
46
+
47
+ def initialize(*args,&b)
48
+ if block_given? then
49
+ role_or_interaction_method(:initialize, *args, &b)
50
+ else
51
+ @roles = Hash.new
52
+ @interactions = Hash.new
53
+ @role_alias = Hash.new
54
+ @contracts = Hash.new
55
+ end
56
+ end
57
+
58
+ def private()
59
+ @private = true
60
+ end
61
+
62
+ def current_interpretation_context(*args,&b)
63
+ if block_given? then
64
+ return role_or_interaction_method(:current_interpretation_context, *args, &b)
65
+ end
66
+ InterpretationContext.new(roles, contracts, role_alias, nil)
67
+
68
+ end
69
+
70
+ def get_methods(*args,&b)
71
+ return role_or_interaction_method(:get_methods, *args, &b) if block_given?
72
+ name = args[0]
73
+ sources = (@defining_role ? (@roles[@defining_role]) : (@interactions))[name]
74
+ if @defining_role and (not sources) then
75
+ @roles[@defining_role][name] = []
76
+ else
77
+ @interactions[name] = []
78
+ end
79
+
80
+ end
81
+
82
+ def add_method(*args,&b)
83
+ return role_or_interaction_method(:add_method, *args, &b) if block_given?
84
+ name, method = *args
85
+ sources = get_methods(name)
86
+ (sources << method)
87
+
88
+ end
89
+
90
+ def finalize(*args,&b)
91
+ return role_or_interaction_method(:finalize, *args, &b) if block_given?
92
+ name, base_class, default = *args
93
+ code = generate_context_code(default, name)
94
+ if @@generate_file_path then
95
+ name = name.to_s
96
+ complete = ((((("class " + name) + (base_class ? (("<< " + base_class.name)) : (""))) + "\n ") + code.to_s) + "\n end")
97
+ File.open((((("./" + @@generate_file_path.to_s) + "/") + name) + ".rb"), "w") do |f|
98
+ f.write(complete)
99
+ end
100
+ complete
101
+ else
102
+ c = base_class ? (Class.new(base_class)) : (Class.new)
103
+ if @@with_contracts then
104
+ c.class_eval("def self.assert_that(obj)\n ContextAsserter.new(self.contracts,obj)\n end\n def self.refute_that(obj)\n ContextAsserter.new(self.contracts,obj,false)\n end\n def self.contracts\n @@contracts\n end\n def self.contracts=(value)\n raise 'Contracts must be supplied' unless value\n @@contracts = value\n end")
105
+ c.contracts = contracts
106
+ end
107
+ Kernel.const_set(name, c)
108
+ temp = c.class_eval(code)
109
+ (temp or c)
110
+ end
111
+
112
+ end
113
+
114
+ def self.create_context_factory(args,block)
115
+ name, base_class, default_interaction = *args
116
+ if default_interaction and (not base_class.instance_of?(Class)) then
117
+ base_class = eval(base_class.to_s)
118
+ end
119
+ if base_class and ((not default_interaction) and (not base_class.instance_of?(Class))) then
120
+ base_class, default_interaction = default_interaction, base_class
121
+ end
122
+ ctx = Context.new
123
+ ctx.instance_eval(&block)
124
+ return [base_class, ctx, default_interaction, name]
125
+
126
+ end
127
+
128
+ def generate_context_code(*args,&b)
129
+ if block_given? then
130
+ return role_or_interaction_method(:generate_context_code, *args, &b)
131
+ end
132
+ default, name = args
133
+ getters = ""
134
+ impl = ""
135
+ interactions = ""
136
+ @interactions.each do |method_name, methods|
137
+ methods.each do |method|
138
+ @defining_role = nil
139
+ code = (" " + method.build_as_context_method(method_name, current_interpretation_context))
140
+ method.is_private ? ((getters << code)) : ((interactions << code))
141
+ end
142
+ end
143
+ if default then
144
+ (interactions << (((((((("\n def self.call(*args)\n arity = " + name.to_s) + ".method(:new).arity\n newArgs = args[0..arity-1]\n obj = ") + name.to_s) + ".new *newArgs\n if arity < args.length\n methodArgs = args[arity..-1]\n obj.") + default.to_s) + " *methodArgs\n else\n obj.") + default.to_s) + "\n end\n end\n "))
145
+ (interactions << (("\n def call(*args);" + default.to_s) + " *args; end\n"))
146
+ end
147
+ @roles.each do |role, methods|
148
+ (getters << (("attr_reader :" + role.to_s) + "\n "))
149
+ methods.each do |method_name, method_sources|
150
+ unless (method_sources.length < 2) then
151
+ raise(("Duplicate definition of " + method_name.to_s))
152
+ end
153
+ unless (method_sources.length > 0) then
154
+ raise(("No source for " + method_name.to_s))
155
+ end
156
+ method_source = method_sources[0]
157
+ @defining_role = role
158
+ rewritten_method_name = ((("self_" + role.to_s) + "_") + method_name.to_s)
159
+ definition = method_source.build_as_context_method(rewritten_method_name, current_interpretation_context)
160
+ (impl << (" " + definition.to_s)) if definition
161
+ end
162
+ end
163
+ (((((interactions + "\n private\n") + getters) + "\n ") + impl) + "\n ")
164
+
165
+ end
166
+
167
+ def role_or_interaction_method(*arguments,&b)
168
+ method_name, on_self = *arguments
169
+ unless method_name.instance_of?(Symbol) then
170
+ on_self = method_name
171
+ method_name = :role_or_interaction_method
172
+ end
173
+ raise(("Method with out block " + method_name.to_s)) unless block_given?
174
+ add_method(method_name, MethodInfo.new(on_self, b.to_sexp, @private))
175
+
176
+ end
177
+ attr_reader :roles
178
+ attr_reader :interactions
179
+ attr_reader :defining_role
180
+ attr_reader :role_alias
181
+ attr_reader :alias_list
182
+ attr_reader :cached_roles_and_alias_list
183
+ attr_reader :contracts
184
+
185
+
186
+
187
+ end
@@ -0,0 +1,50 @@
1
+ class ImmutableQueue
2
+
3
+ def push(element)
4
+ b = (back or ImmutableStack.empty)
5
+ ImmutableQueue.new(front, b.push(element))
6
+
7
+ end
8
+
9
+ def pop()
10
+ f, b = front, back
11
+ if (f == ImmutableStack.empty) then
12
+ until (b == ImmutableStack.empty) do
13
+ (e, b = b.pop
14
+ f = f.push(e))
15
+ end
16
+ end
17
+ head, f = f.pop
18
+ if (f == b) then
19
+ [head, ImmutableQueue.empty]
20
+ else
21
+ [head, ImmutableQueue.new(f, b)]
22
+ end
23
+
24
+ end
25
+
26
+ def self.empty()
27
+ @@empty ||= ImmutableQueue.new(ImmutableStack.empty, ImmutableStack.empty)
28
+ end
29
+
30
+ def push_array(arr)
31
+ q = self
32
+ arr.each { |i| q = q.push(i) } if arr
33
+ q
34
+
35
+ end
36
+
37
+ private
38
+
39
+ def initialize(front,back)
40
+ @front = (front or ImmutableStack.empty)
41
+ @back = (back or ImmutableStack.empty)
42
+ self.freeze
43
+
44
+ end
45
+ attr_reader :front
46
+ attr_reader :back
47
+
48
+
49
+
50
+ end