maroon 0.7.1 → 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
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