fabulator 0.0.8 → 0.0.9

Sign up to get free protection for your applications and to get access to all the features.
Files changed (41) hide show
  1. data/History.txt +30 -1
  2. data/VERSION +1 -1
  3. data/features/functions.feature +7 -0
  4. data/features/primitives.feature +1 -1
  5. data/features/step_definitions/template_steps.rb +40 -3
  6. data/features/step_definitions/xml_steps.rb +3 -2
  7. data/features/templates.feature +49 -22
  8. data/features/types.feature +4 -4
  9. data/lib/fabulator.rb +4 -0
  10. data/lib/fabulator/compiler.rb +27 -0
  11. data/lib/fabulator/core.rb +3 -8
  12. data/lib/fabulator/core/actions/choose.rb +0 -18
  13. data/lib/fabulator/core/actions/for_each.rb +0 -48
  14. data/lib/fabulator/core/{actions.rb → lib.rb} +189 -117
  15. data/lib/fabulator/core/structurals.rb +7 -0
  16. data/lib/fabulator/core/{constraint.rb → structurals/constraint.rb} +2 -0
  17. data/lib/fabulator/core/{filter.rb → structurals/filter.rb} +2 -0
  18. data/lib/fabulator/core/{group.rb → structurals/group.rb} +2 -0
  19. data/lib/fabulator/core/{parameter.rb → structurals/parameter.rb} +2 -0
  20. data/lib/fabulator/core/{state.rb → structurals/state.rb} +2 -0
  21. data/lib/fabulator/core/{state_machine.rb → structurals/state_machine.rb} +2 -0
  22. data/lib/fabulator/core/{transition.rb → structurals/transition.rb} +2 -0
  23. data/lib/fabulator/expr.rb +6 -0
  24. data/lib/fabulator/expr/context.rb +65 -10
  25. data/lib/fabulator/expr/node_logic.rb +3 -2
  26. data/lib/fabulator/expr/parser.rb +787 -638
  27. data/lib/fabulator/expr/statement_list.rb +27 -0
  28. data/lib/fabulator/lib.rb +3 -0
  29. data/lib/fabulator/lib/action.rb +12 -9
  30. data/lib/fabulator/lib/lib.rb +85 -9
  31. data/lib/fabulator/structural.rb +24 -5
  32. data/lib/fabulator/tag_lib.rb +78 -124
  33. data/lib/fabulator/tag_lib/presentations.rb +39 -0
  34. data/lib/fabulator/tag_lib/transformations.rb +66 -0
  35. data/lib/fabulator/tag_lib/type.rb +176 -0
  36. data/lib/fabulator/template/parse_result.rb +125 -62
  37. data/lib/fabulator/template/parser.rb +17 -1
  38. data/xslt/form.xsl +163 -2083
  39. data/xsm_expression_parser.racc +35 -20
  40. metadata +17 -13
  41. data/lib/fabulator/context.rb +0 -39
@@ -5,6 +5,11 @@ module Fabulator
5
5
  @statements = [ ]
6
6
  @ensures = [ ]
7
7
  @catches = [ ]
8
+ @context = nil
9
+ end
10
+
11
+ def use_context(c)
12
+ @context = c
8
13
  end
9
14
 
10
15
  def add_statement(s)
@@ -28,6 +33,9 @@ module Fabulator
28
33
  end
29
34
 
30
35
  def run(context, autovivify = false)
36
+ if !@context.nil?
37
+ context = @context
38
+ end
31
39
  result = [ ]
32
40
  begin
33
41
  if !@statements.nil?
@@ -84,6 +92,25 @@ module Fabulator
84
92
  end
85
93
  end
86
94
 
95
+ class ErrExpr
96
+ def initialize(e,c)
97
+ @expr = e
98
+ @err_expr = c
99
+ end
100
+
101
+ def run(context, autovivify = false)
102
+ result = []
103
+ begin
104
+ result = @expr.run(context, autovivify)
105
+ rescue => e
106
+ ctx = context.merge
107
+ ctx.set_var('e', e)
108
+ result = @err_expr.run(ctx)
109
+ end
110
+ result
111
+ end
112
+ end
113
+
87
114
  class DataSet
88
115
  def initialize(p,v)
89
116
  @path = p
@@ -65,6 +65,9 @@ module Fabulator
65
65
  #structural :type, Type
66
66
  #structural :filter, Filter
67
67
  #structural :constraint, Constraint
68
+
69
+ presentations do
70
+ end
68
71
  end
69
72
  end
70
73
  end
@@ -5,6 +5,7 @@ module Fabulator
5
5
  module Lib
6
6
  class Action < Fabulator::Structural
7
7
  attr_accessor :attributes
8
+ attr_accessor :namespace
8
9
 
9
10
  namespace FAB_LIB_NS
10
11
 
@@ -18,7 +19,7 @@ module Fabulator
18
19
  def compile_action(e, context)
19
20
  ret = nil
20
21
  context.with(e) do |ctx|
21
- ret = ActionRef.new(self, ctx, ctx.compile_actions(e))
22
+ ret = ActionRef.new([ e.namespaces.namespace.href, e.name ], ctx, ctx.compile_actions(e))
22
23
  end
23
24
  ret
24
25
  end
@@ -30,8 +31,8 @@ module Fabulator
30
31
  @action = defining_action
31
32
  @actions = actions
32
33
  @static_attributes = { }
33
- @action.attributes.collect{ |a| a.is_static? }.each do |a|
34
- @static_attributes[a.path] = a.value(@context)
34
+ @context.get_action(@action.first, @action.last).attributes.collect{ |a| a.is_static? }.each do |a|
35
+ @static_attributes[a.name] = a.value(@context)
35
36
  end
36
37
  end
37
38
 
@@ -39,17 +40,19 @@ module Fabulator
39
40
  ret = [ ]
40
41
  @context.with(context) do |ctx|
41
42
  @static_attributes.each_pair do |p,v|
42
- ctx.set_value(p, v)
43
+ ctx.set_var(p, v)
43
44
  end
44
45
  # These can be passed to f:eval to get their value
45
- @action.attributes.collect{ |a| !a.is_static? }.each do |attr|
46
- ctx.set_value(attr.path, attr.value(ctx))
46
+ action = ctx.get_action(@action.first, @action.last)
47
+ action.attributes.collect{ |a| !a.is_static? }.each do |attr|
48
+ ctx.set_var(attr.name, attr.value(ctx))
47
49
  end
48
50
  # we can f:eval($actions) in whatever current context we have
49
- if @action.has_actions?
50
- ctx.set_var('actions', ctx.root.anon_node(@actions, [ FAB_NS, 'expression' ]))
51
+ if action.has_actions?
52
+ @actions.use_context(context)
53
+ ctx.set_var('actions', ctx.root.anon_node( @actions, [ FAB_NS, 'expression' ]))
51
54
  end
52
- ret = @action.run(ctx)
55
+ ret = action.run(ctx)
53
56
  end
54
57
  ret
55
58
  end
@@ -8,15 +8,21 @@ module Fabulator
8
8
 
9
9
  attribute :ns, :static => true
10
10
 
11
- contains :action, :storage => :hash, :key => :name
12
- contains :structural, :storage => :hash, :key => :name
13
- contains :function, :storage => :hash, :key => :name
14
- contains :mapping, :storage => :hash, :key => :name
15
- contains :reduction, :storage => :hash, :key => :name
16
- contains :consolidation, :storage => :hash, :key => :name
17
- contains :type, :storage => :hash, :key => :name
18
- contains :filter, :storage => :hash, :key => :name
19
- contains :constraint, :storage => :hash, :key => :name
11
+ contains :action, :storage => :hash, :key => :name, :delayable => true
12
+ contains :structural, :storage => :hash, :key => :name, :delayable => true
13
+ contains :function, :storage => :hash, :key => :name, :delayable => true
14
+ contains :mapping, :storage => :hash, :key => :name, :delayable => true
15
+ contains :reduction, :storage => :hash, :key => :name, :delayable => true
16
+ contains :consolidation, :storage => :hash, :key => :name, :delayable => true
17
+ contains :type, :storage => :hash, :key => :name, :delayable => true
18
+ contains :filter, :storage => :hash, :key => :name, :delayable => true
19
+ contains :constraint, :storage => :hash, :key => :name, :delayable => true
20
+ contains :format, :storage => :hash, :key => :name
21
+ contains :transform
22
+
23
+ def presentation
24
+ @presentations ||= Fabulator::TagLib::Presentations.new
25
+ end
20
26
 
21
27
  def register_library
22
28
  Fabulator::TagLib.namespaces[self.ns] = self
@@ -28,6 +34,15 @@ module Fabulator
28
34
  @actions[name].compile_action(e, context)
29
35
  end
30
36
 
37
+ def get_action(nom, context)
38
+ return nil unless self.action_exists?(nom)
39
+ @actions[nom]
40
+ end
41
+
42
+ def action_exists?(nom)
43
+ @actions.has_key?(nom.to_s)
44
+ end
45
+
31
46
  def run_function(context, nom, args)
32
47
  # look for a function/mapping/consolidation
33
48
  # then pass along to any objects in @contained
@@ -115,6 +130,67 @@ module Fabulator
115
130
  end
116
131
  false
117
132
  end
133
+
134
+ protected
135
+
136
+ def setup(xml)
137
+ ns = xml.attributes.get_attribute_ns(FAB_LIB_NS, 'ns').value
138
+ Fabulator::TagLib.namespaces[ns] = self
139
+
140
+ self.init_attribute_storage
141
+
142
+ possibilities = self.class.structurals
143
+
144
+ if !possibilities.nil?
145
+
146
+ our_ns = xml.namespaces.namespace.href
147
+ our_nom = xml.name
148
+ delayed = [ ]
149
+ xml.each_element{ |e| delayed << e }
150
+ while !delayed.empty?
151
+ structs = { }
152
+ new_delayed = [ ]
153
+ delayed.each do |e|
154
+ ns = e.namespaces.namespace.href
155
+ nom = e.name.to_sym
156
+ allowed = (Fabulator::TagLib.namespaces[our_ns].structural_class(our_nom).accepts_structural?(ns, nom) rescue false)
157
+ next unless allowed
158
+ structs[ns] ||= { }
159
+ structs[ns][nom] ||= [ ]
160
+ begin
161
+ structs[ns][nom] << @context.compile_structural(e)
162
+ rescue => ee
163
+ new_delayed << e
164
+ end
165
+ structs[ns][nom] -= [ nil ]
166
+ end
167
+
168
+ structs.each_pair do |ns, parts|
169
+ next unless possibilities[ns]
170
+ parts.each_pair do |nom, objs|
171
+ next unless possibilities[ns][nom]
172
+ opts = possibilities[ns][nom]
173
+ as = "@" + (opts[:as] || nom.to_s.pluralize).to_s
174
+ if opts[:storage].nil? || opts[:storage] == :array
175
+ self.instance_variable_set(as.to_sym, self.instance_variable_get(as.to_sym) + objs)
176
+ else
177
+ tgt = self.instance_variable_get(as.to_sym)
178
+ objs.each do |obj|
179
+ tgt[obj.send(opts[:key] || :name)] = obj
180
+ end
181
+ end
182
+ end
183
+ end
184
+
185
+ if (new_delayed - delayed).empty? && (delayed - new_delayed).empty?
186
+ delayed = []
187
+ else
188
+ delayed = new_delayed
189
+ end
190
+ end
191
+ end
192
+
193
+ end
118
194
  end
119
195
  end
120
196
  end
@@ -3,6 +3,8 @@ module Fabulator
3
3
 
4
4
  def initialize
5
5
  @context = Fabulator::Expr::Context.new
6
+ self.init_attribute_storage
7
+
6
8
  end
7
9
 
8
10
  def compile_xml(xml, context = nil)
@@ -35,6 +37,9 @@ module Fabulator
35
37
  @@structurals[self.name] ||= { }
36
38
  @@structurals[self.name][ns] ||= { }
37
39
  @@structurals[self.name][ns][nom.to_sym] = opts
40
+ self.module_eval {
41
+ attr_accessor (opts[:as] || nom.to_s.pluralize).to_sym
42
+ }
38
43
  end
39
44
 
40
45
  def self.contained_in(ns, nom, h = {})
@@ -43,7 +48,7 @@ module Fabulator
43
48
  @@contained_in[ns] ||= { }
44
49
  @@contained_in[ns][nom.to_sym] ||= { }
45
50
  @@contained_in[ns][nom.to_sym][self.namespace] ||= { }
46
- @@contained_in[ns][nom.to_sym][self.namespace][self.element.to_sym] = h.update({ :as => :contained})
51
+ @@contained_in[ns][nom.to_sym][self.namespace][self.element.to_sym] = { :as => :contained }.update(h)
47
52
  end
48
53
 
49
54
  def self.structurals
@@ -79,16 +84,20 @@ module Fabulator
79
84
 
80
85
 
81
86
  protected
82
- def setup(xml)
83
- super
84
87
 
85
- #klass = self.class.name
88
+ def init_attribute_storage
86
89
  possibilities = self.class.structurals
87
90
 
88
91
  if !possibilities.nil?
89
92
  possibilities.each_pair do |ns, parts|
90
93
  parts.each_pair do |nom, opts|
91
- as = "@" + (opts[:as] || nom.to_s.pluralize).to_s
94
+ snom = (opts[:as] || nom.to_s.pluralize).to_s
95
+ as = "@" + snom
96
+ if !self.class.respond_to?(snom.to_sym)
97
+ self.class.module_eval {
98
+ attr_accessor snom.to_sym
99
+ }
100
+ end
92
101
  if opts[:storage].nil? || opts[:storage] == :array
93
102
  self.instance_variable_set(as.to_sym, [])
94
103
  elsif opts[:storage] == :hash
@@ -96,7 +105,17 @@ module Fabulator
96
105
  end
97
106
  end
98
107
  end
108
+ end
109
+ end
99
110
 
111
+ def setup(xml)
112
+ super
113
+
114
+ self.init_attribute_storage
115
+
116
+ possibilities = self.class.structurals
117
+
118
+ if !possibilities.nil?
100
119
  structs = @context.compile_structurals(xml)
101
120
  structs.each_pair do |ns, parts|
102
121
  next unless possibilities[ns]
@@ -8,6 +8,7 @@ module Fabulator
8
8
  @@namespaces = {}
9
9
  @@attributes = [ ]
10
10
  @@last_description = nil
11
+ @@presentations = { }
11
12
  @@types = { }
12
13
  @@axes = { }
13
14
 
@@ -41,6 +42,9 @@ module Fabulator
41
42
  def self.axes
42
43
  @@axes
43
44
  end
45
+ def self.presentations
46
+ @@presentations
47
+ end
44
48
 
45
49
  def self.last_description=(x)
46
50
  @@last_description = x
@@ -72,30 +76,24 @@ module Fabulator
72
76
  def self.axes=(x)
73
77
  @@axes = x
74
78
  end
79
+ def self.presentations=(x)
80
+ @@presentations = x
81
+ end
75
82
 
76
- def structural_class(nom)
77
- Fabulator::TagLib.structural_classes[self.class.name][nom.to_sym]
78
- end
83
+ def structural_class(nom)
84
+ Fabulator::TagLib.structural_classes[self.class.name][nom.to_sym]
85
+ end
79
86
 
80
87
  def self.inherited(base)
81
88
  base.extend(ClassMethods)
82
89
  end
83
90
 
84
- # def self.included(base)
85
- # base.extend(ClassMethods)
86
- # base.module_eval do
87
- # def self.included(new_base)
88
- # super
89
- # new_base.action_descriptions.merge! self.action_descriptions
90
- # new_base.function_descriptions.merge! self.function_descriptions
91
- # new_base.function_args.merge! self.function_args
92
- # new_base.types.merge! self.types
93
- # end
94
- # end
95
- # end
91
+ def self.type_handler(t)
92
+ (@@types[t[0]][t[1].to_sym] rescue nil)
93
+ end
96
94
 
97
95
  def self.find_op(t,o)
98
- (@@types[t[0]][t[1]][:ops][o] rescue nil)
96
+ (self.type_handler(t).get_method(t + o.upcase) rescue nil)
99
97
  end
100
98
 
101
99
  # returns nil if no common type can be found
@@ -110,6 +108,7 @@ module Fabulator
110
108
  # now group by types since we only need one of each type for unification
111
109
  grouped = { }
112
110
  ts.each do |t|
111
+ t = t.vtype.collect{ |i| i.to_s} unless t.is_a?(Array)
113
112
  grouped[t.join('')] = t
114
113
  end
115
114
 
@@ -121,96 +120,17 @@ module Fabulator
121
120
  # until we unify all of them
122
121
  t1 = grouped.pop
123
122
  t2 = grouped.pop
124
- ut = self._unify_types(t1, t2)
123
+ t1_obj = self.type_handler(t1)
124
+ ut = t1_obj.unify_with_type(t2)
125
125
  return nil if ut.nil?
126
126
  self.unify_types([ ut[:t] ] + grouped)
127
127
  end
128
128
 
129
129
  def self.type_path(from, to)
130
130
  return [] if from.nil? || to.nil? || from.join('') == to.join('')
131
- ut = self._unify_types(from, to, true)
132
- return [] if ut.nil? || ut[:t].join('') != to.join('')
133
- return ut[:convert]
134
- end
135
-
136
- ## TODO: allow unification with values as well so we can have
137
- # conversions dependent on the value
138
- # for example: strings that look like integers can convert to integers
139
- def self._unify_types(t1, t2, ordered = false)
140
- return nil if t1.nil? || t2.nil?
141
- d1 = { t1.join('') => { :t => t1, :w => 1.0, :path => [ t1 ], :convert => [ ] } }
142
- d2 = { t2.join('') => { :t => t2, :w => 1.0, :path => [ t2 ], :convert => [ ] } }
143
-
144
- added = true
145
- while added
146
- added = false
147
- [d1, d2].each do |d|
148
- d.keys.each do |t|
149
- if (@@types[d[t][:t][0]][d[t][:t][1]].has_key?(:to) rescue false)
150
- @@types[d[t][:t][0]][d[t][:t][1]][:to].each do |conv|
151
- w = d[t][:w] * conv[:weight]
152
- conv_key = conv[:type].join('')
153
- if d.has_key?(conv_key)
154
- if d[conv_key][:w] < w
155
- d[conv_key][:w] = w
156
- d[conv_key][:path] = d[t][:path] + [ conv[:type] ]
157
- d[conv_key][:convert] = d[t][:convert] + [ conv[:convert] ] - [nil]
158
- end
159
- else
160
- d[conv_key] = {
161
- :t => conv[:type],
162
- :w => w,
163
- :path => d[t][:path] + [ conv[:type] ],
164
- :convert => d[t][:convert] + [ conv[:convert] ] - [ nil ]
165
- }
166
- added = true
167
- end
168
- end
169
- end
170
- end
171
- # go through each type looking for :from
172
- @@types.keys.each do |ns|
173
- @@types[ns].each_pair do |ct, cd|
174
- next if cd[:from].nil?
175
- to_key = ns + ct
176
- cd[:from].each do |conv|
177
- next if conv[:type].nil?
178
- from_key = conv[:type].join('')
179
- next if !d.has_key?(from_key)
180
- w = d[from_key][:w] * conv[:weight]
181
- if d.has_key?(to_key)
182
- if d[to_key][:w] < w
183
- d[to_key][:w] = w
184
- d[to_key][:path] = d[from_key][:path] + [ conv[:type] ]
185
- d[to_key][:convert] = d[from_key][:convert] + [ conv[:convert] ] - [nil]
186
- end
187
- else
188
- d[to_key] = {
189
- :t => [ns, ct],
190
- :w => w * 95 / 100, # favor to over from
191
- :path => d[from_key][:path] + [ conv[:type] ],
192
- :convert => d[from_key][:convert] + [ conv[:convert] ] - [ nil ]
193
- }
194
- added = true
195
- end
196
- end
197
- end
198
- end
199
- end
200
- r = self._select_type_path(d1, d2, t2, ordered)
201
- return r unless r.nil?
202
- end
203
- return self._select_type_path(d1, d2, t2, ordered)
204
- end
205
-
206
- def self._select_type_path(d1, d2, t2, ordered)
207
- common = d1.keys & d2.keys
208
- if ordered && common.include?(t2.join(''))
209
- return d1[t2.join('')]
210
- elsif !common.empty?
211
- return d1[common.sort_by{ |c| d1[c][:w] * d2[c][:w] / d1[c][:path].size / d2[c][:path].size }.reverse.first]
212
- end
213
- return nil
131
+ from_obj = self.type_handler(from)
132
+ return [] if from_obj.nil?
133
+ return from_obj.build_conversion_to(to)
214
134
  end
215
135
 
216
136
  def self.with_super(s, &block)
@@ -237,6 +157,10 @@ module Fabulator
237
157
  end
238
158
  end
239
159
 
160
+ def action_exists?(nom)
161
+ self.respond_to?("action:#{nom.to_s}")
162
+ end
163
+
240
164
  def run_function(context, nom, args, depth=0)
241
165
  ret = []
242
166
 
@@ -273,23 +197,28 @@ module Fabulator
273
197
  end
274
198
  rr
275
199
  else
276
- context.root.anon_node(r) #, self.function_return_type(nom))
200
+ rt = self.function_return_type(nom)
201
+ if rt.nil?
202
+ context.root.anon_node(r) #, self.function_return_type(nom))
203
+ else
204
+ context.root.anon_node(r,rt)
205
+ end
277
206
  end
278
207
  }
279
208
  ret.flatten
280
209
  end
281
210
 
282
211
  def function_return_type(name)
283
- (self.function_descriptions[name][:returns] rescue nil)
212
+ (self.function_descriptions[name.to_sym][:returns] rescue nil)
284
213
  end
285
214
 
286
215
  def function_run_scaling(name)
287
- (self.function_descriptions[name][:scaling] rescue nil)
216
+ (self.function_descriptions[name.to_sym][:scaling] rescue nil)
288
217
  end
289
218
 
290
219
  def function_run_type(name)
291
- r = (self.function_descriptions[name][:type] rescue nil)
292
- if r.nil? && !self.function_descriptions.has_key?(name)
220
+ r = (self.function_descriptions[name.to_sym][:type] rescue nil)
221
+ if r.nil? && !self.function_descriptions.has_key?(name.to_sym)
293
222
  if name =~ /^consolidation:(.*)/
294
223
  if function_run_scaling($1) != :flat
295
224
  return :consolidation
@@ -330,6 +259,10 @@ module Fabulator
330
259
  self.class.function_args hash
331
260
  end
332
261
 
262
+ def presentation
263
+ self.class.presentation
264
+ end
265
+
333
266
  module ClassMethods
334
267
  def inherited(subclass)
335
268
  subclass.action_descriptions.reverse_merge! self.action_descriptions
@@ -353,6 +286,10 @@ module Fabulator
353
286
  Fabulator::TagLib.namespaces[ns] = self.new
354
287
  end
355
288
 
289
+ def presentation
290
+ Fabulator::TagLib.presentations[self.name] ||= Fabulator::TagLib::Presentations.new
291
+ end
292
+
356
293
  def register_attribute(a, options = {})
357
294
  ns = nil
358
295
  Fabulator::TagLib.namespaces.each_pair do |k,v|
@@ -363,7 +300,17 @@ module Fabulator
363
300
  Fabulator::TagLib.attributes << [ ns, a, options ]
364
301
  end
365
302
 
366
- def register_type(nom, options={})
303
+ def get_type(nom)
304
+ ns = nil
305
+ Fabulator::TagLib.namespaces.each_pair do |k,v|
306
+ if v.is_a?(self)
307
+ ns = k
308
+ end
309
+ end
310
+ Fabulator::TagLib.types[ns][nom.to_sym]
311
+ end
312
+
313
+ def has_type(nom, &block)
367
314
  ns = nil
368
315
  Fabulator::TagLib.namespaces.each_pair do |k,v|
369
316
  if v.is_a?(self)
@@ -371,12 +318,14 @@ module Fabulator
371
318
  end
372
319
  end
373
320
  Fabulator::TagLib.types[ns] ||= {}
374
- Fabulator::TagLib.types[ns][nom] = options
321
+ Fabulator::TagLib.types[ns][nom.to_sym] ||= Fabulator::TagLib::Type.new([ns, nom.to_sym])
375
322
 
376
- function nom do |ctx, args|
377
- args[0].collect { |i|
378
- i.to([ ns, nom ])
379
- }
323
+ if block
324
+ Fabulator::TagLib.types[ns][nom.to_sym].instance_eval &block
325
+ end
326
+
327
+ mapping nom do |ctx, i|
328
+ ctx.with_root(i).to([ ns, nom.to_s ]).root
380
329
  end
381
330
  end
382
331
 
@@ -393,10 +342,10 @@ module Fabulator
393
342
  end
394
343
 
395
344
  def action(name, klass = nil, &block)
396
- self.action_descriptions[name] = Fabulator::TagLib.last_description if Fabulator::TagLib.last_description
345
+ self.action_descriptions[name.to_sym] = Fabulator::TagLib.last_description if Fabulator::TagLib.last_description
397
346
  Fabulator::TagLib.last_description = nil
398
347
  if block
399
- define_method("action:#{name}", &block)
348
+ define_method("action:#{name.to_s}", block)
400
349
  elsif !klass.nil?
401
350
  action(name) { |e,c|
402
351
  r = klass.new
@@ -407,10 +356,10 @@ module Fabulator
407
356
  end
408
357
 
409
358
  def structural(name, klass = nil, &block)
410
- self.structural_descriptions[name] = Fabulator::TagLib.last_description if Fabulator::TagLib.last_description
359
+ self.structural_descriptions[name.to_sym] = Fabulator::TagLib.last_description if Fabulator::TagLib.last_description
411
360
  Fabulator::TagLib.last_description = nil
412
361
  if block
413
- define_method("structural:#{name}", &block)
362
+ define_method("structural:#{name.to_s}", block)
414
363
  elsif !klass.nil?
415
364
  structural(name) { |e,c|
416
365
  r = klass.new
@@ -423,21 +372,21 @@ module Fabulator
423
372
  end
424
373
 
425
374
  def function(name, returns = nil, takes = nil, &block)
426
- self.function_descriptions[name] = { :returns => returns, :takes => takes }
427
- self.function_descriptions[name][:description] = Fabulator::TagLib.last_description if Fabulator::TagLib.last_description
375
+ self.function_descriptions[name.to_sym] = { :returns => returns, :takes => takes }
376
+ self.function_descriptions[name.to_sym][:description] = Fabulator::TagLib.last_description if Fabulator::TagLib.last_description
428
377
  #self.function_args[name] = { :return => returns, :takes => takes }
429
378
  Fabulator::TagLib.last_description = nil
430
379
  define_method("fctn:#{name}", &block)
431
380
  end
432
381
 
433
382
  def reduction(name, opts = {}, &block)
434
- self.function_descriptions[name] = { :type => :reduction }.merge(opts)
435
- self.function_descriptions[name][:description] = Fabulator::TagLib.last_description if Fabulator::TagLib.last_description
383
+ self.function_descriptions[name.to_sym] = { :type => :reduction }.merge(opts)
384
+ self.function_descriptions[name.to_sym][:description] = Fabulator::TagLib.last_description if Fabulator::TagLib.last_description
436
385
  Fabulator::TagLib.last_description = nil
437
386
  define_method("fctn:#{name}", &block)
438
- cons = self.function_descriptions[name][:consolidation]
387
+ cons = self.function_descriptions[name.to_sym][:consolidation]
439
388
  if !cons.nil?
440
- Fabulator::TagLib.last_description = self.function_descriptions[name][:description]
389
+ Fabulator::TagLib.last_description = self.function_descriptions[name.to_sym][:description]
441
390
  consolidation name do |ctx, args|
442
391
  send "fctn:#{cons}", ctx, args
443
392
  end
@@ -445,17 +394,18 @@ module Fabulator
445
394
  end
446
395
 
447
396
  def consolidation(name, opts = {}, &block)
448
- self.function_descriptions[name] = { :type => :consolidation }.merge(opts)
449
- self.function_descriptions[name][:description] = Fabulator::TagLib.last_description if Fabulator::TagLib.last_description
397
+ self.function_descriptions[name.to_sym] = { :type => :consolidation }.merge(opts)
398
+ self.function_descriptions[name.to_sym][:description] = Fabulator::TagLib.last_description if Fabulator::TagLib.last_description
450
399
  Fabulator::TagLib.last_description = nil
451
400
  define_method("fctn:consolidation:#{name}", &block)
452
401
  end
453
402
 
454
403
  def mapping(name, opts = {}, &block)
404
+ name = name.to_sym
455
405
  self.function_descriptions[name] = { :type => :mapping }.merge(opts)
456
406
  self.function_descriptions[name][:description] = Fabulator::TagLib.last_description if Fabulator::TagLib.last_description
457
407
  Fabulator::TagLib.last_description = nil
458
- define_method("fctn:#{name}", &block)
408
+ define_method("fctn:#{name.to_s}", &block)
459
409
  end
460
410
 
461
411
  def function_decl(name, expr, ns)
@@ -481,6 +431,10 @@ module Fabulator
481
431
  def constraint(name, &block)
482
432
  define_method("constraint:#{name}", &block)
483
433
  end
434
+
435
+ def presentations(&block)
436
+ self.presentation.instance_eval &block
437
+ end
484
438
  end
485
439
 
486
440
  module Util