maroon 0.6.5 → 0.7.0

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