fabulator 0.0.8 → 0.0.9

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 (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