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,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