maroon 0.7.1 → 0.8.0

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 (39) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +26 -6
  3. data/Rakefile +3 -3
  4. data/Test/Context_test.rb +16 -16
  5. data/{Examples/Dijkstra → Test/Examples}/CalculateShortestDistance.rb +11 -13
  6. data/Test/Examples/MoneyTransfer_test.rb +76 -0
  7. data/{Examples/Dijkstra → Test/Examples}/calculate_shortest_path.rb +77 -89
  8. data/{Examples/Dijkstra → Test/Examples}/data.rb +0 -0
  9. data/{Examples/Dijkstra/dijkstra.rb → Test/Examples/dijkstra_test.rb} +34 -24
  10. data/Test/Examples/greeter_test.rb +48 -0
  11. data/{Examples/meter.rb → Test/Examples/meter_test.rb} +44 -30
  12. data/Test/abstract_syntax_tree_test.rb +17 -26
  13. data/Test/alltests.rb +1 -1
  14. data/Test/test_helper.rb +2 -0
  15. data/base/AbstractSyntaxTree.rb +24 -3
  16. data/base/ImmutableStack.rb +1 -1
  17. data/base/dependency_graph.rb +94 -0
  18. data/base/immutable_queue.rb +1 -1
  19. data/base/maroon_base.rb +50 -11
  20. data/base/transfomer.rb +196 -197
  21. data/generated/Tokens.rb +64 -2
  22. data/generated/build.rb +1 -3
  23. data/generated/maroon/kernel.rb +7 -0
  24. data/lib/AbstractSyntaxTree.rb +120 -0
  25. data/lib/AstRewritter.rb +53 -58
  26. data/lib/Context.rb +104 -126
  27. data/lib/DependencyGraph.rb +76 -0
  28. data/lib/ImmutableQueue.rb +28 -39
  29. data/lib/ImmutableStack.rb +20 -34
  30. data/lib/Tokens.rb +64 -2
  31. data/lib/Transformer.rb +125 -165
  32. data/lib/build.rb +2 -4
  33. data/lib/maroon/kernel.rb +1 -1
  34. data/lib/maroon/version.rb +1 -1
  35. metadata +13 -11
  36. data/Examples/MoneyTransfer.rb +0 -62
  37. data/Examples/greeter.rb +0 -46
  38. data/Test/Greeter_test_disabled.rb +0 -203
  39. data/lib/Production.rb +0 -149
@@ -27,7 +27,7 @@ context :ImmutableQueue do
27
27
  end
28
28
 
29
29
  def self.empty
30
- @@empty ||= ImmutableQueue.new(ImmutableStack::empty, ImmutableStack::empty)
30
+ @empty ||= ImmutableQueue.new(ImmutableStack::empty, ImmutableStack::empty)
31
31
  end
32
32
 
33
33
  def push_array(arr)
@@ -10,7 +10,7 @@
10
10
  # With in the block supplied to the role method you can define role methods the same way as you define interactions. See the method who
11
11
  # in the below example
12
12
  # = Example
13
- # Context::define :Greeter do
13
+ # Context.define :Greeter do
14
14
  # role :who do
15
15
  # say do
16
16
  # @who #could be self as well to refer to the current role player of the 'who' role
@@ -39,23 +39,62 @@ c = context :Context do
39
39
 
40
40
  def self.define(*args, &block)
41
41
  name, base_class, default_interaction = *args
42
+
42
43
  if default_interaction and (not base_class.instance_of?(Class)) then
43
44
  base_class = eval(base_class.to_s)
44
45
  end
45
46
  if base_class and ((not default_interaction) and (not base_class.instance_of?(Class))) then
46
47
  base_class, default_interaction = default_interaction, base_class
47
48
  end
48
- @@with_contracts ||= nil
49
- @@generate_file_path ||= nil
50
- ctx = self.send(:create_context_factory, name, base_class, default_interaction, block)
51
- transformer = Transformer.new name, ctx.roles,ctx.interactions,ctx.private_interactions,base_class, default_interaction
52
- return transformer.transform @@generate_file_path, @@with_contracts
49
+ @with_contracts ||= nil
50
+
51
+ ctx = self.send(:create_context_factory, name, base_class, default_interaction, block)
52
+
53
+ if self.generate_dependency_graph
54
+ dependencies = {}
55
+ ctx.dependencies = DependencyGraphModel.new(DependencyGraph.new(name,ctx.roles,ctx.interactions,dependencies).create!)
56
+ end
57
+ transformer = Transformer.new(name, ctx.roles, ctx.interactions, ctx.private_interactions, base_class, default_interaction)
58
+ ctx.generated_class = transformer.transform(generate_files_in, @with_contracts)
59
+ ctx
53
60
  end
54
61
 
55
- def self.generate_files_in(*args, &b)
62
+ def self.generate_files_in
63
+ @generate_files_in
64
+ end
56
65
 
57
- @@generate_file_path = args[0]
66
+ def self.generate_files_in=(folder)
67
+ @generate_files_in = folder
68
+ end
58
69
 
70
+ def self.generate_code=(value)
71
+ @generate_code = value
72
+ end
73
+
74
+ def self.generate_dependency_graph=(value)
75
+ @generate_dependency_graph = value
76
+ end
77
+
78
+ def self.generate_code
79
+ @generate_code || !generate_dependency_graph || generate_files_in
80
+ end
81
+
82
+ def self.generate_dependency_graph
83
+ @generate_dependency_graph
84
+ end
85
+
86
+ def dependencies
87
+ @dependencies
88
+ end
89
+ def generated_class
90
+ @generated_class
91
+ end
92
+
93
+ def dependencies=(value)
94
+ @dependencies=value
95
+ end
96
+ def generated_class=(value)
97
+ @generated_class=value
59
98
  end
60
99
 
61
100
  def roles
@@ -116,12 +155,12 @@ c = context :Context do
116
155
  end
117
156
 
118
157
  def self.with_contracts(*args)
119
- return @@with_contracts if (args.length == 0)
158
+ return @with_contracts if (args.length == 0)
120
159
  value = args[0]
121
- if @@with_contracts and (not value) then
160
+ if @with_contracts and (not value) then
122
161
  raise('make up your mind! disabling contracts during execution will result in undefined behavior')
123
162
  end
124
- @@with_contracts = value
163
+ @with_contracts = value
125
164
 
126
165
  end
127
166
 
@@ -1,197 +1,196 @@
1
- context :Transformer do
2
-
3
- def initialize(context_name, roles, interactions,private_interactions, base_class,default_interaction)
4
- @context_name = context_name
5
-
6
- @roles = roles
7
- @interactions = interactions
8
- @base_class = base_class
9
- @default_interaction = default_interaction
10
- @private_interactions = private_interactions
11
- @definitions = {}
12
- end
13
-
14
- role :private_interactions do end
15
- role :context_name do end
16
- role :roles do
17
- def generated_source
18
- impl = ''
19
- getters = ''
20
- roles.each do |role, methods|
21
- getters << 'attr_reader :' + role.to_s + '
22
- '
23
- methods.each do |name, method_sources|
24
- bind :method_sources => :method , :name=> :method_name , :role => :defining_role
25
- definition = method.generated_source
26
- (impl << (' ' + definition )) if definition
27
- end
28
- end
29
- (impl.strip! || '')+ '
30
- ' + (getters.strip! || '') + '
31
- '
32
- end
33
- end
34
- role :interactions do
35
- def generated_source
36
- internal_methods = ''
37
- external_methods = interactions.default
38
- interactions.each do |name, interact|
39
- interact.each do |m|
40
- bind :m => :method, :name => :method_name
41
- @defining_role = nil
42
- code = method.generated_source
43
-
44
- (method.is_private? ? internal_methods : external_methods) << ' ' << code
45
- end
46
- end
47
- (external_methods.strip! || '') + '
48
- private
49
- ' + (internal_methods.strip! || '') + '
50
- '
51
- end
52
- def default
53
- if @default
54
- '
55
- def self.call(*args)
56
- arity = ' + name.to_s + '.method(:new).arity
57
- newArgs = args[0..arity-1]
58
- obj = ' + name.to_s + '.new *newArgs
59
- if arity < args.length
60
- methodArgs = args[arity..-1]
61
- obj.' + default.to_s + ' *methodArgs
62
- else
63
- obj.' + default.to_s + '
64
- end
65
- end
66
- def call(*args);' + default.to_s + ' *args; end
67
- '
68
- else
69
- ''
70
- end
71
- end
72
- end
73
- role :method_name do end
74
- role :defining_role do end
75
- role :method do
76
- def is_private?
77
- defining_role != nil || (private_interactions.has_key? method.name)
78
- end
79
- def definition
80
- key = (@defining_role ? @defining_role.to_s : '') + method_name.to_s
81
- return @definitions[key] if @definitions.has_key? key
82
- unless method.instance_of? Sexp
83
- unless (method.instance_of? Array) && method.length < 2 then
84
- raise(('Duplicate definition of ' + method_name.to_s + '(' + method.to_s + ')'))
85
- end
86
- unless (method.instance_of? Array) && method.length > 0 then
87
- raise(('No source for ' + method_name.to_s))
88
- end
89
- end
90
-
91
- d = (method.instance_of? Array) ? method[0] : method
92
- raise 'Sexp require' unless d.instance_of? Sexp
93
- @definitions[key] = d
94
- end
95
- def body
96
- args = method.definition.detect { |d| d[0] == :args }
97
- index = method.definition.index(args) + 1
98
- if method.definition.length > index+1
99
- body = method.definition[index..-1]
100
- body.insert(0, :block)
101
- body
102
- else
103
- method.definition[index]
104
- end
105
- end
106
-
107
- def arguments
108
- args = method.definition.detect { |d| d[0] == :args }
109
- args && args.length > 1 ? args[1..-1] : []
110
- end
111
-
112
- def name
113
- name = if method.definition[1].instance_of? Symbol
114
- method.definition[1].to_s
115
- else
116
- (method.definition[1].select { |e| e.instance_of? Symbol }.map { |e| e.to_s }.join('.') + '.' + method.definition[2].to_s)
117
- end
118
- (
119
- unless defining_role
120
- name
121
- else
122
- 'self_' + @defining_role.to_s + '_' + name.to_s
123
- end).to_sym
124
- end
125
- def generated_source
126
- AstRewritter.new(method.body, interpretation_context).rewrite!
127
- body = Ruby2Ruby.new.process(method.body)
128
- raise 'Body is undefined' unless body
129
- args = method.arguments
130
- if args && args.length
131
- args = '('+ args.join(',') + ')'
132
- else
133
- args= ''
134
- end
135
-
136
- header = 'def ' + method.name.to_s + args
137
- header + ' ' + body + ' end
138
- '
139
- end
140
- end
141
-
142
-
143
- def transform(file_path, with_contracts)
144
-
145
- code = interactions.generated_source + roles.generated_source
146
-
147
- if file_path then
148
- name = context_name.to_s
149
- complete = ((((('class ' + name) + (@base_class ? (('<< ' + @base_class.name)) : (''))) + '
150
- ') + code.to_s) + '
151
- end')
152
- File.open((((('./' + file_path.to_s) + '/') + name) + '.rb'), 'w') do |f|
153
- f.write(complete)
154
- end
155
- complete
156
- else
157
- c = @base_class ? (Class.new(base_class)) : (Class.new)
158
- if with_contracts then
159
- c.class_eval(
160
- 'def self.assert_that(obj)
161
- ContextAsserter.new(self.contracts,obj)
162
- end
163
- def self.refute_that(obj)
164
- ContextAsserter.new(self.contracts,obj,false)
165
- end
166
- def self.contracts
167
- @@contracts
168
- end
169
- def self.contracts=(value)
170
- @@contracts = value
171
- end')
172
- c.contracts = contracts
173
- end
174
- Kernel.const_set(context_name, c)
175
- begin
176
- temp = c.class_eval(code)
177
- rescue SyntaxError
178
- p 'error: ' + code
179
- end
180
-
181
- (temp or c)
182
- end
183
-
184
- end
185
-
186
- private
187
-
188
- def contracts
189
- (@contracts ||= {})
190
- end
191
- def role_aliases
192
- (@role_aliases ||={})
193
- end
194
- def interpretation_context
195
- InterpretationContext.new(roles, contracts, role_aliases, defining_role, @private_interactions)
196
- end
197
- end
1
+ context :Transformer do
2
+
3
+ def initialize(context_name, roles, interactions,private_interactions, base_class,default_interaction)
4
+ @context_name = context_name
5
+
6
+ @roles = roles
7
+ @interactions = interactions
8
+ @base_class = base_class
9
+ @default_interaction = default_interaction
10
+ @private_interactions = private_interactions
11
+ @definitions = {}
12
+ end
13
+
14
+ role :private_interactions do end
15
+ role :context_name do end
16
+ role :roles do
17
+ def generated_source
18
+ impl = ''
19
+ getters = []
20
+ roles.each do |role, methods|
21
+ getters << role.to_s
22
+ methods.each do |name, method_sources|
23
+ bind :method_sources => :method , :name=> :method_name , :role => :defining_role
24
+ definition = method.generated_source
25
+ (impl << (' ' + definition )) if definition
26
+ end
27
+ end
28
+ (impl.strip! || '')+ '
29
+ ' + (getters.length > 0 ? 'attr_reader :' +getters.join(', :') : '') + '
30
+ '
31
+ end
32
+ end
33
+ role :interactions do
34
+ def generated_source
35
+ internal_methods = ''
36
+ external_methods = interactions.default
37
+ interactions.each do |name, interact|
38
+ interact.each do |m|
39
+ bind :m => :method, :name => :method_name
40
+ @defining_role = nil
41
+ code = method.generated_source
42
+
43
+ (method.is_private? ? internal_methods : external_methods) << ' ' << code
44
+ end
45
+ end
46
+ (external_methods.strip! || '') + '
47
+ private
48
+ ' + (internal_methods.strip! || '') + '
49
+ '
50
+ end
51
+ def default
52
+ if @default
53
+ '
54
+ def self.call(*args)
55
+ arity = ' + name.to_s + '.method(:new).arity
56
+ newArgs = args[0..arity-1]
57
+ obj = ' + name.to_s + '.new *newArgs
58
+ if arity < args.length
59
+ methodArgs = args[arity..-1]
60
+ obj.' + default.to_s + ' *methodArgs
61
+ else
62
+ obj.' + default.to_s + '
63
+ end
64
+ end
65
+ def call(*args);' + default.to_s + ' *args; end
66
+ '
67
+ else
68
+ ''
69
+ end
70
+ end
71
+ end
72
+ role :method_name do end
73
+ role :defining_role do end
74
+ role :method do
75
+ def is_private?
76
+ defining_role != nil || (private_interactions.has_key? method.name)
77
+ end
78
+ def definition
79
+ key = (@defining_role ? @defining_role.to_s : '') + method_name.to_s
80
+ return @definitions[key] if @definitions.has_key? key
81
+ unless method.instance_of? Sexp
82
+ unless (method.instance_of? Array) && method.length < 2 then
83
+ raise(('Duplicate definition of ' + method_name.to_s + '(' + method.to_s + ')'))
84
+ end
85
+ unless (method.instance_of? Array) && method.length > 0 then
86
+ raise(('No source for ' + method_name.to_s))
87
+ end
88
+ end
89
+
90
+ d = (method.instance_of? Array) ? method[0] : method
91
+ raise 'Sexp require' unless d.instance_of? Sexp
92
+ @definitions[key] = d
93
+ end
94
+ def body
95
+ args = method.definition.detect { |d| d[0] == :args }
96
+ index = method.definition.index(args) + 1
97
+ if method.definition.length > index+1
98
+ body = method.definition[index..-1]
99
+ body.insert(0, :block)
100
+ body
101
+ else
102
+ method.definition[index]
103
+ end
104
+ end
105
+
106
+ def arguments
107
+ args = method.definition.detect { |d| d[0] == :args }
108
+ args && args.length > 1 ? args[1..-1] : []
109
+ end
110
+
111
+ def name
112
+ name = if method.definition[1].instance_of? Symbol
113
+ method.definition[1].to_s
114
+ else
115
+ (method.definition[1].select { |e| e.instance_of? Symbol }.map { |e| e.to_s }.join('.') + '.' + method.definition[2].to_s)
116
+ end
117
+ (
118
+ unless defining_role
119
+ name
120
+ else
121
+ 'self_' + @defining_role.to_s + '_' + name.to_s
122
+ end).to_sym
123
+ end
124
+ def generated_source
125
+ AstRewritter.new(method.body, interpretation_context).rewrite!
126
+ body = Ruby2Ruby.new.process(method.body)
127
+ raise 'Body is undefined' unless body
128
+ args = method.arguments
129
+ if args && args.length
130
+ args = '('+ args.join(',') + ')'
131
+ else
132
+ args= ''
133
+ end
134
+
135
+ header = 'def ' + method.name.to_s + args
136
+ header + ' ' + body + ' end
137
+ '
138
+ end
139
+ end
140
+
141
+
142
+ def transform(file_path, with_contracts)
143
+
144
+ code = interactions.generated_source + roles.generated_source
145
+
146
+ if file_path then
147
+ name = context_name.to_s
148
+ complete = ((((('class ' + name) + (@base_class ? (('<< ' + @base_class.name)) : (''))) + '
149
+ ') + code.to_s) + '
150
+ end')
151
+ File.open((((('./' + file_path.to_s) + '/') + name) + '.rb'), 'w') do |f|
152
+ f.write(complete)
153
+ end
154
+ complete
155
+ else
156
+ c = @base_class ? (Class.new(base_class)) : (Class.new)
157
+ if with_contracts then
158
+ c.class_eval(
159
+ 'def self.assert_that(obj)
160
+ ContextAsserter.new(self.contracts,obj)
161
+ end
162
+ def self.refute_that(obj)
163
+ ContextAsserter.new(self.contracts,obj,false)
164
+ end
165
+ def self.contracts
166
+ @contracts
167
+ end
168
+ def self.contracts=(value)
169
+ @contracts = value
170
+ end')
171
+ c.contracts = contracts
172
+ end
173
+ Kernel.const_set(context_name, c)
174
+ begin
175
+ temp = c.class_eval(code)
176
+ rescue SyntaxError
177
+ p 'error: ' + code
178
+ end
179
+
180
+ (temp or c)
181
+ end
182
+
183
+ end
184
+
185
+ private
186
+
187
+ def contracts
188
+ (@contracts ||= {})
189
+ end
190
+ def role_aliases
191
+ (@role_aliases ||={})
192
+ end
193
+ def interpretation_context
194
+ InterpretationContext.new(roles, contracts, role_aliases, defining_role, @private_interactions)
195
+ end
196
+ end