maroon 0.6.5 → 0.7.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.
@@ -3,18 +3,20 @@ context :ImmutableStack do
3
3
  end
4
4
  role :tail do
5
5
  end
6
- pop do
6
+
7
+ def pop
7
8
  [@head, @tail]
8
9
  end
9
- push do |element|
10
+
11
+ def push(element)
10
12
  ImmutableStack.new element, self
11
13
  end
12
14
 
13
- empty self do
15
+ def self.empty
14
16
  @@empty ||= self.new(nil, nil)
15
17
  end
16
18
 
17
- each do
19
+ def each
18
20
  yield head
19
21
  t = tail
20
22
  while t != ImmutableStack::empty do
@@ -23,7 +25,7 @@ context :ImmutableStack do
23
25
  end
24
26
  end
25
27
 
26
- initialize do |h, t|
28
+ def initialize(h, t)
27
29
  @head = h
28
30
  @tail = t
29
31
  self.freeze
@@ -0,0 +1,145 @@
1
+ context :Production do
2
+ role :interpretation_context do
3
+ end
4
+ role :queue do
5
+ end
6
+
7
+ role :production do
8
+ def is_role?
9
+
10
+ case
11
+ when production.is_call? && (interpretation_context.roles.has_key?(production[2]))
12
+ @date = [production[2]]
13
+ return true
14
+ when (production == :self ||
15
+ (production.is_indexer? && (production[1] == nil || production[1] == :self)) ||
16
+ (production && ((production.instance_of?(Sexp) || production.instance_of?(Array)) && production[0] == :self))) && @interpretation_context.defining_role
17
+ @data = @interpretation_context.defining_role
18
+ return true
19
+ else
20
+ false
21
+ end
22
+ end
23
+
24
+ def is_indexer?
25
+ production.is_call? && (production[2] == :[] || production[2] == :[]=)
26
+ end
27
+
28
+ def is_call?
29
+ production && ((production.instance_of?(Sexp) || production.instance_of?(Array)) && production[0] == :call)
30
+ end
31
+
32
+ def is_block?
33
+ production && ((production.instance_of?(Sexp) || production.instance_of?(Array)) && production[0] == :iter)
34
+ end
35
+
36
+ def is_block_with_bind?
37
+ if production.is_block?
38
+ body = @production.last()
39
+ if body && (exp = body[0])
40
+ bind = Production.new exp, @interpretation_context
41
+ if bind.type == Tokens::call && bind.data == :bind
42
+ true
43
+ end
44
+ end
45
+ end
46
+ end
47
+
48
+ def is_rolemethod_call?
49
+ can_be = production.is_call?
50
+ if can_be
51
+ instance = Production.new(production[1], @interpretation_context)
52
+ can_be = instance.type == Tokens::role
53
+ if can_be
54
+ instance_data = instance.data
55
+ role = @interpretation_context.roles[instance_data]
56
+ data = production[2]
57
+ can_be = role.has_key?(data)
58
+ @data = [data, instance_data]
59
+
60
+ end
61
+ end
62
+ can_be
63
+ end
64
+ end
65
+
66
+ def initialize(ast, interpretation_context)
67
+ rebind ImmutableQueue::empty.push(ast), interpretation_context
68
+ end
69
+
70
+ def type
71
+ case
72
+ when nil == production
73
+ nil
74
+ when production.is_block_with_bind?
75
+ Tokens::block_with_bind
76
+ when production.is_block?
77
+ Tokens::block
78
+ when production.instance_of?(Fixnum) || production.instance_of?(Symbol)
79
+ Tokens::terminal
80
+ when production.is_rolemethod_call?
81
+ Tokens::rolemethod_call
82
+ when production.is_role?
83
+ Tokens::role
84
+ when production.is_indexer?
85
+ Tokens::indexer
86
+ when production.is_call?
87
+ Tokens::call
88
+ else
89
+ Tokens::other
90
+ end
91
+ end
92
+
93
+ def [](i)
94
+ @production[i]
95
+ end
96
+
97
+ def []=(i, v)
98
+ @production[i]=v
99
+ end
100
+
101
+ def length
102
+ @production.length
103
+ end
104
+
105
+ def last
106
+ @production.last
107
+ end
108
+
109
+ def first
110
+ @production.first
111
+ end
112
+
113
+ def data
114
+ return @data if @data
115
+ @data = case
116
+ when production.is_call?
117
+ @production[2]
118
+ else
119
+ @production
120
+ end
121
+ end
122
+
123
+ def each
124
+ yield self
125
+ if production.instance_of? Sexp || production.instance_of?(Array)
126
+ @queue = @queue.push_array production
127
+ end
128
+ while @queue != ImmutableQueue::empty
129
+ rebind @queue, @interpretation_context
130
+ yield self
131
+ if production.instance_of? Sexp || production.instance_of?(Array)
132
+ @queue = @queue.push_array production
133
+ end
134
+ end
135
+ end
136
+
137
+ private
138
+
139
+ def rebind(queue, ctx)
140
+ @data = nil
141
+ @production, @queue = queue.pop
142
+ @interpretation_context = ctx
143
+ end
144
+
145
+ end
@@ -3,12 +3,13 @@ context :ImmutableQueue do
3
3
  end
4
4
  role :back do
5
5
  end
6
- push do |element|
6
+
7
+ def push(element)
7
8
  b = back || ImmutableStack::empty
8
9
  ImmutableQueue.new(front, b.push(element))
9
10
  end
10
11
 
11
- pop do
12
+ def pop
12
13
  f, b = front, back
13
14
  if f == ImmutableStack::empty
14
15
  #reverse the back stack to be able to pop from the front in correct order
@@ -25,11 +26,11 @@ context :ImmutableQueue do
25
26
  end
26
27
  end
27
28
 
28
- empty true do
29
+ def self.empty
29
30
  @@empty ||= ImmutableQueue.new(ImmutableStack::empty, ImmutableStack::empty)
30
31
  end
31
32
 
32
- push_array do |arr|
33
+ def push_array(arr)
33
34
  q = self
34
35
  if arr
35
36
  arr.each do |i|
@@ -41,7 +42,7 @@ context :ImmutableQueue do
41
42
 
42
43
  private
43
44
 
44
- initialize do |front, back|
45
+ def initialize(front, back)
45
46
  @front = front || ImmutableStack::empty
46
47
  @back = back || ImmutableStack::empty
47
48
  self.freeze
@@ -19,7 +19,7 @@
19
19
  # end
20
20
  # end
21
21
  # greeting do
22
- # p "Hello #{who.say}!"
22
+ # p 'Hello #{who.say}!'
23
23
  # end
24
24
  # end
25
25
  #
@@ -29,239 +29,281 @@
29
29
  # end
30
30
  # end
31
31
  #
32
- # Greeter.new('world').greeting #Will print "Hello world!"
32
+ # Greeter.new('world').greeting #Will print 'Hello world!'
33
33
  #maroon is base on Marvin which was the first injectionless language for DCI
34
34
  #being injectionless there's no runtime extend or anything else impacting the performance. There' only regular method invocation even when using role methods
35
35
  #Author:: Rune Funch Søltoft (funchsoltoft@gmail.com)
36
36
  #License:: Same as for Ruby
37
37
  ##
38
- Context::generate_files_in 'generated'
39
- context :Context do
40
- role :roles do
41
- end
42
- role :interactions do
43
- end
44
- role :defining_role do
45
- end
46
- role :role_alias do
47
- end
48
- role :alias_list do
49
- end
50
- role :cached_roles_and_alias_list do
51
- end
38
+ c = context :Context do
52
39
 
53
- #define is the only exposed method and can be used to define a context (class)
54
- #if maroon/kernel is required calling context of Context::define are equivalent
55
- #params
56
- #name:: the name of the context. Since this is used as the name of a class, class naming convetions should be used
57
- #block:: the body of the context. Can include definitions of roles (through the role method) or definitions of interactions
58
- #by simply calling a method with the name of the interaction and passing a block as the body of the interaction
59
- define :block => :block, :self => self do |*args|
40
+ def self.define(*args, &block)
60
41
  @@with_contracts ||= nil
61
42
  @@generate_file_path ||= nil
62
- alias method_missing role_or_interaction_method
43
+ (alias :method_missing :role_or_interaction_method)
44
+
63
45
  base_class, ctx, default_interaction, name = self.send(:create_context_factory, args, block)
64
- ctx.generate_files_in(args.last()) if args.last().instance_of? FalseClass or args.last().instance_of? TrueClass
65
- return ctx.send(:finalize, name, base_class, default_interaction)
66
- end
46
+ if (args.last.instance_of?(FalseClass) or args.last.instance_of?(TrueClass)) then
47
+ ctx.generate_files_in(args.last)
48
+ end
49
+ return ctx.send(:finalize, name, base_class, default_interaction, @@generate_file_path, @@with_contracts)
67
50
 
68
- generate_files_in :block => :b,:self => self do |*args|
69
- return role_or_interaction_method(:generate_files_in, *args, &b) if block_given?
51
+ end
70
52
 
53
+ def self.generate_files_in(*args, &b)
54
+ if block_given? then
55
+ return role_or_interaction_method(:generate_files_in, *args, &b)
56
+ end
71
57
  @@generate_file_path = args[0]
58
+
72
59
  end
73
60
 
74
61
  private
75
- with_contracts self do |*args|
76
- return @@with_contracts if args.length == 0
62
+
63
+ def get_definitions(b)
64
+ sexp = b.to_sexp
65
+ unless is_definition? sexp[3]
66
+ sexp = sexp[3]
67
+ if sexp
68
+ sexp = sexp.select do |exp|
69
+ is_definition? exp
70
+ end
71
+ end
72
+ sexp ||= []
73
+ end
74
+
75
+ sexp.select do |exp|
76
+ is_definition? exp
77
+ end
78
+ end
79
+
80
+ def self.create_context_factory(args, block)
81
+ name, base_class, default_interaction = *args
82
+ if default_interaction and (not base_class.instance_of?(Class)) then
83
+ base_class = eval(base_class.to_s)
84
+ end
85
+ if base_class and ((not default_interaction) and (not base_class.instance_of?(Class))) then
86
+ base_class, default_interaction = default_interaction, base_class
87
+ end
88
+ ctx = Context.new
89
+ ctx.instance_eval {
90
+ sexp = block.to_sexp
91
+ temp_block = sexp[3]
92
+ i = 0
93
+
94
+ while i < temp_block.length
95
+ exp = temp_block[i]
96
+ unless temp_block[i-2] && temp_block[i-2][0] == :call && temp_block[i-1] && temp_block[i-1][0] == :args
97
+ if exp[0] == :defn || exp[0] == :defs
98
+ add_method(exp)
99
+ temp_block.delete_at i
100
+ i -= 1
101
+ elsif exp[0] == :call && exp[1] == nil && exp[2] == :private
102
+ @private = true
103
+ end
104
+ end
105
+ i += 1
106
+ end
107
+ ctx.instance_eval &block
108
+ }
109
+
110
+ return [base_class, ctx, default_interaction, name]
111
+
112
+ end
113
+
114
+ def self.with_contracts(*args)
115
+ return @@with_contracts if (args.length == 0)
77
116
  value = args[0]
78
- raise 'make up your mind! disabling contracts during execution will result in undefined behavior' if @@with_contracts && !value
117
+ if @@with_contracts and (not value) then
118
+ raise('make up your mind! disabling contracts during execution will result in undefined behavior')
119
+ end
79
120
  @@with_contracts = value
121
+
80
122
  end
81
123
 
82
- ##
83
- #Defines a role with the given name
84
- #role methods can be defined inside a block passed to this method
85
- # = Example
86
- # role :who do
87
- # say do
88
- # p @who
89
- # end
90
- # end
91
- #The above code defines a role called 'who' with a role method called say
92
- ##
93
- role :block => :b do |*args|
94
- role_name = args[0]
95
- return role_or_interaction_method(:role, *args, &b) if args.length != 1 or not (role_name.instance_of? Symbol)
124
+ def createInfo(definition)
125
+ MethodInfo.new(definition, @defining_role, @private)
126
+ end
96
127
 
128
+ def is_definition?(exp)
129
+ exp && (exp[0] == :defn || exp[0] == :defs)
130
+ end
131
+
132
+ def role(*args, &b)
133
+ role_name = args[0]
134
+ if (args.length.!=(1) or (not role_name.instance_of?(Symbol))) then
135
+ return role_or_interaction_method(:role, *args, &b)
136
+ end
97
137
  @defining_role = role_name
138
+ @roles = {} unless @roles
98
139
  @roles[role_name] = Hash.new
99
- yield if block_given?
100
- @defining_role = nil
101
- end
102
140
 
103
- initialize :block => :b do |*args|
104
- if block_given?
105
- role_or_interaction_method(:initialize, *args, &b)
106
- else
107
- @roles = Hash.new
108
- @interactions = Hash.new
109
- @role_alias = Hash.new
110
- @contracts = Hash.new
141
+ definitions = get_definitions(b)
142
+
143
+ definitions.each do |exp|
144
+ add_method(exp)
111
145
  end
112
- end
113
146
 
114
- role_or_interaction_method(:private) do
115
- @private = true
116
147
  end
117
148
 
118
- current_interpretation_context :block => :b do |*args|
119
- return role_or_interaction_method(:current_interpretation_context, *args, &b) if block_given?
120
- InterpretationContext.new(roles, contracts, role_alias, nil)
149
+ def current_interpretation_context(*args, &b)
150
+ if block_given? then
151
+ return role_or_interaction_method(:current_interpretation_context, *args, &b)
152
+ end
153
+ InterpretationContext.new(@roles, @contracts, @role_alias, nil)
154
+
121
155
  end
122
156
 
123
- get_methods :block => :b do |*args|
157
+ def get_methods(*args, &b)
124
158
  return role_or_interaction_method(:get_methods, *args, &b) if block_given?
125
159
  name = args[0]
126
160
  sources = (@defining_role ? (@roles[@defining_role]) : (@interactions))[name]
127
- if @defining_role && !sources
161
+ if @defining_role and (not sources) then
128
162
  @roles[@defining_role][name] = []
129
163
  else
130
- (@interactions)[name] = []
164
+ @interactions[name] = []
131
165
  end
132
- end
133
166
 
134
- role :contracts do
135
167
  end
136
168
 
137
- add_method :block => :b do |*args|
169
+ def add_method(*args, &b)
138
170
  return role_or_interaction_method(:add_method, *args, &b) if block_given?
139
- name, method = *args
140
- sources = get_methods(name)
141
- sources << method
171
+ exp = args[0]
172
+ info = createInfo exp
173
+ sources = get_methods(info.name)
174
+ (sources << info)
142
175
  end
143
176
 
144
- finalize :block => :b do |*args|
177
+ def finalize(*args, &b)
145
178
  return role_or_interaction_method(:finalize, *args, &b) if block_given?
146
- name, base_class, default = *args
147
-
179
+ name, base_class, default, file_path, with_contracts = *args
148
180
  code = generate_context_code(default, name)
149
-
150
- if @@generate_file_path
181
+ if file_path then
151
182
  name = name.to_s
152
- complete = 'class ' + name + (base_class ? '<< ' + base_class.name : '') + '
153
- ' + code.to_s + '
154
- end'
155
- File.open('./' + @@generate_file_path.to_s + '/' + name + '.rb', 'w') { |f| f.write(complete) }
183
+ complete = ((((('class ' + name) + (base_class ? (('<< ' + base_class.name)) : (''))) + '
184
+ ') + code.to_s) + '
185
+ end')
186
+ File.open((((('./' + file_path.to_s) + '/') + name) + '.rb'), 'w') do |f|
187
+ f.write(complete)
188
+ end
156
189
  complete
157
190
  else
158
-
159
- c = base_class ? (Class.new base_class) : Class.new
160
- if @@with_contracts
161
- c.class_eval('def self.assert_that(obj)
162
- ContextAsserter.new(self.contracts,obj)
163
- end
164
- def self.refute_that(obj)
165
- ContextAsserter.new(self.contracts,obj,false)
166
- end
167
- def self.contracts
168
- @@contracts
169
- end
170
- def self.contracts=(value)
171
- raise \'Contracts must be supplied\' unless value
172
- @@contracts = value
173
- end')
174
- c.contracts=contracts
191
+ c = base_class ? (Class.new(base_class)) : (Class.new)
192
+ if with_contracts then
193
+ c.class_eval(
194
+ 'def self.assert_that(obj)
195
+ ContextAsserter.new(self.contracts,obj)
196
+ end
197
+ def self.refute_that(obj)
198
+ ContextAsserter.new(self.contracts,obj,false)
199
+ end
200
+ def self.contracts
201
+ @@contracts
202
+ end
203
+ def self.contracts=(value)
204
+ @@contracts = value
205
+ end')
206
+ c.contracts = contracts
207
+ end
208
+ Kernel.const_set(name, c)
209
+ begin
210
+ temp = c.class_eval(code)
211
+ rescue SyntaxError
212
+ p 'error: ' + code
175
213
  end
176
- Kernel.const_set name, c
177
- temp = c.class_eval(code)
178
- (temp || c)
179
- end
180
- end
181
214
 
182
- create_context_factory self do |args, block|
183
- name, base_class, default_interaction = *args
184
- #if there's two arguments and the second is not a class it must be an interaction
185
- if default_interaction && (!base_class.instance_of? Class) then
186
- base_class = eval(base_class.to_s)
215
+ (temp or c)
187
216
  end
188
- base_class, default_interaction = default_interaction, base_class if base_class and !default_interaction and !base_class.instance_of? Class
189
- ctx = Context.new
190
- ctx.instance_eval &block
191
- return base_class, ctx, default_interaction, name
217
+
192
218
  end
193
219
 
194
- generate_context_code :block => :b do |*args|
195
- return role_or_interaction_method(:generate_context_code, *args, &b) if block_given?
220
+ def generate_context_code(*args, &b)
221
+ if block_given? then
222
+ return role_or_interaction_method(:generate_context_code, *args, &b)
223
+ end
196
224
  default, name = args
197
-
198
225
  getters = ''
199
226
  impl = ''
200
227
  interactions = ''
201
228
  @interactions.each do |method_name, methods|
202
229
  methods.each do |method|
203
230
  @defining_role = nil
204
- code = ' ' + (method.build_as_context_method method_name, current_interpretation_context)
205
- if method.is_private
206
- getters << code
207
- else
208
- interactions << code
209
- end
231
+ code = (' ' + method.build_as_context_method(current_interpretation_context))
232
+ method.is_private ? ((getters << code)) : ((interactions << code))
210
233
  end
211
234
  end
212
-
213
- if default
214
- interactions << '
215
- def self.call(*args)
216
- arity = ' + name.to_s + '.method(:new).arity
235
+ if default then
236
+ (interactions << (((((((('
237
+ def self.call(*args)
238
+ arity = ' + name.to_s) + '.method(:new).arity
217
239
  newArgs = args[0..arity-1]
218
- obj = ' + name.to_s + '.new *newArgs
240
+ obj = ') + name.to_s) + '.new *newArgs
219
241
  if arity < args.length
220
242
  methodArgs = args[arity..-1]
221
- obj.' + default.to_s + ' *methodArgs
243
+ obj.') + default.to_s) + ' *methodArgs
222
244
  else
223
- obj.' + default.to_s + '
224
- end
245
+ obj.') + default.to_s) + '
246
+ end
225
247
  end
226
- '
227
- interactions << '
228
- def call(*args);' + default.to_s + ' *args; end
229
- '
248
+ '))
249
+ (interactions << (('
250
+ def call(*args);' + default.to_s) + ' *args; end
251
+ '))
230
252
  end
231
-
232
253
  @roles.each do |role, methods|
233
- getters << 'attr_reader :' + role.to_s + '
234
- '
235
-
254
+ (getters << (('attr_reader :' + role.to_s) + '
255
+ '))
236
256
  methods.each do |method_name, method_sources|
237
- raise 'Duplicate definition of ' + method_name.to_s unless method_sources.length < 2
238
- raise 'No source for ' + method_name.to_s unless method_sources.length > 0
239
-
257
+ unless (method_sources.length < 2) then
258
+ raise(('Duplicate definition of ' + method_name.to_s))
259
+ end
260
+ unless (method_sources.length > 0) then
261
+ raise(('No source for ' + method_name.to_s))
262
+ end
240
263
  method_source = method_sources[0]
241
264
  @defining_role = role
242
- rewritten_method_name = 'self_' + role.to_s + '_' + method_name.to_s
243
- definition = method_source.build_as_context_method rewritten_method_name, current_interpretation_context
244
- (impl << ' ' + definition.to_s) if definition
265
+
266
+ definition = method_source.build_as_context_method(current_interpretation_context)
267
+ (impl << (' ' + definition.to_s)) if definition
245
268
  end
246
269
  end
247
-
248
-
249
- interactions + '
250
- private
251
- ' + getters + '
270
+ private_string = (getters + impl).strip! != '' ? '
271
+ private
272
+ ' : ''
273
+ impl = impl.strip! != '' ? '
252
274
  ' + impl + '
275
+ ' : '
253
276
  '
277
+ interactions + private_string + getters + impl
278
+
254
279
  end
255
280
 
256
- role_or_interaction_method({:block => :b}) do |*arguments|
281
+ def role_or_interaction_method(*arguments, &b)
257
282
  method_name, on_self = *arguments
258
- unless method_name.instance_of? Symbol
283
+ unless method_name.instance_of?(Symbol) then
259
284
  on_self = method_name
260
285
  method_name = :role_or_interaction_method
261
286
  end
287
+ raise(('Method with out block ' + method_name.to_s)) unless block_given?
288
+
289
+ end
290
+
291
+ def private
292
+ @private = true
293
+ end
294
+
295
+ def initialize
296
+ @roles = {}
297
+ @interactions = {}
298
+ @role_alias = {}
299
+ end
262
300
 
263
- raise 'Method with out block ' + method_name.to_s unless block_given?
301
+ end
264
302
 
265
- add_method(method_name, MethodInfo.new(on_self, b.to_sexp, @private))
303
+ if c.instance_of? String
304
+ file_name = './generated/Context.rb'
305
+ p "writing to: " + file_name
306
+ File.open(file_name, 'w') do |f|
307
+ f.write(c)
266
308
  end
267
- end
309
+ end