activefacts 0.8.16 → 0.8.18

Sign up to get free protection for your applications and to get access to all the features.
Files changed (100) hide show
  1. checksums.yaml +15 -0
  2. data/Manifest.txt +10 -4
  3. data/bin/afgen +26 -20
  4. data/bin/cql +1 -1
  5. data/css/orm2.css +89 -9
  6. data/examples/CQL/CompanyDirectorEmployee.cql +4 -4
  7. data/examples/CQL/Genealogy.cql +5 -5
  8. data/examples/CQL/Metamodel.cql +121 -91
  9. data/examples/CQL/MonthInSeason.cql +2 -6
  10. data/examples/CQL/SeparateSubtype.cql +11 -9
  11. data/examples/CQL/ServiceDirector.cql +21 -33
  12. data/examples/CQL/Supervision.cql +0 -3
  13. data/examples/CQL/WindowInRoomInBldg.cql +10 -4
  14. data/examples/CQL/unit.cql +1 -1
  15. data/lib/activefacts.rb +1 -0
  16. data/lib/activefacts/cql/CQLParser.treetop +5 -1
  17. data/lib/activefacts/cql/Context.treetop +2 -7
  18. data/lib/activefacts/cql/Expressions.treetop +2 -2
  19. data/lib/activefacts/cql/FactTypes.treetop +37 -31
  20. data/lib/activefacts/cql/Language/English.treetop +21 -4
  21. data/lib/activefacts/cql/LexicalRules.treetop +59 -1
  22. data/lib/activefacts/cql/ObjectTypes.treetop +22 -12
  23. data/lib/activefacts/cql/Terms.treetop +13 -9
  24. data/lib/activefacts/cql/ValueTypes.treetop +30 -11
  25. data/lib/activefacts/cql/compiler.rb +34 -5
  26. data/lib/activefacts/cql/compiler/clause.rb +207 -116
  27. data/lib/activefacts/cql/compiler/constraint.rb +129 -105
  28. data/lib/activefacts/cql/compiler/entity_type.rb +49 -27
  29. data/lib/activefacts/cql/compiler/expression.rb +71 -42
  30. data/lib/activefacts/cql/compiler/fact.rb +70 -64
  31. data/lib/activefacts/cql/compiler/fact_type.rb +108 -57
  32. data/lib/activefacts/cql/compiler/query.rb +178 -0
  33. data/lib/activefacts/cql/compiler/shared.rb +13 -12
  34. data/lib/activefacts/cql/compiler/value_type.rb +10 -4
  35. data/lib/activefacts/cql/nodes.rb +1 -1
  36. data/lib/activefacts/cql/parser.rb +6 -2
  37. data/lib/activefacts/generate/absorption.rb +6 -3
  38. data/lib/activefacts/generate/cql.rb +140 -84
  39. data/lib/activefacts/generate/dm.rb +12 -6
  40. data/lib/activefacts/generate/help.rb +25 -6
  41. data/lib/activefacts/generate/helpers/oo.rb +195 -0
  42. data/lib/activefacts/generate/helpers/ordered.rb +589 -0
  43. data/lib/activefacts/generate/helpers/rails.rb +57 -0
  44. data/lib/activefacts/generate/html/glossary.rb +274 -54
  45. data/lib/activefacts/generate/json.rb +25 -22
  46. data/lib/activefacts/generate/null.rb +1 -0
  47. data/lib/activefacts/generate/rails/models.rb +244 -0
  48. data/lib/activefacts/generate/rails/schema.rb +185 -0
  49. data/lib/activefacts/generate/records.rb +1 -0
  50. data/lib/activefacts/generate/ruby.rb +51 -30
  51. data/lib/activefacts/generate/sql/mysql.rb +5 -3
  52. data/lib/activefacts/generate/sql/server.rb +8 -4
  53. data/lib/activefacts/generate/text.rb +1 -0
  54. data/lib/activefacts/generate/transform/surrogate.rb +209 -0
  55. data/lib/activefacts/generate/version.rb +1 -0
  56. data/lib/activefacts/input/orm.rb +234 -181
  57. data/lib/activefacts/mapping/rails.rb +122 -0
  58. data/lib/activefacts/persistence/columns.rb +34 -18
  59. data/lib/activefacts/persistence/foreignkey.rb +129 -71
  60. data/lib/activefacts/persistence/index.rb +42 -12
  61. data/lib/activefacts/persistence/reference.rb +37 -23
  62. data/lib/activefacts/persistence/tables.rb +53 -19
  63. data/lib/activefacts/registry.rb +11 -0
  64. data/lib/activefacts/support.rb +28 -10
  65. data/lib/activefacts/version.rb +1 -1
  66. data/lib/activefacts/vocabulary/extensions.rb +246 -117
  67. data/lib/activefacts/vocabulary/metamodel.rb +105 -65
  68. data/lib/activefacts/vocabulary/verbaliser.rb +226 -194
  69. data/spec/absorption_spec.rb +1 -0
  70. data/spec/cql/comparison_spec.rb +8 -8
  71. data/spec/cql/contractions_spec.rb +16 -43
  72. data/spec/cql/entity_type_spec.rb +2 -1
  73. data/spec/cql/expressions_spec.rb +2 -2
  74. data/spec/cql/fact_type_matching_spec.rb +4 -1
  75. data/spec/cql/parser/bad_literals_spec.rb +30 -30
  76. data/spec/cql/parser/entity_types_spec.rb +6 -6
  77. data/spec/cql/parser/expressions_spec.rb +25 -19
  78. data/spec/cql/samples_spec.rb +5 -4
  79. data/spec/cql_cql_spec.rb +2 -1
  80. data/spec/cql_dm_spec.rb +4 -0
  81. data/spec/cql_mysql_spec.rb +4 -0
  82. data/spec/cql_parse_spec.rb +2 -0
  83. data/spec/cql_ruby_spec.rb +4 -0
  84. data/spec/cql_sql_spec.rb +4 -0
  85. data/spec/cqldump_spec.rb +7 -4
  86. data/spec/helpers/parse_to_ast_matcher.rb +7 -3
  87. data/spec/helpers/test_parser.rb +2 -0
  88. data/spec/norma_cql_spec.rb +5 -2
  89. data/spec/norma_ruby_spec.rb +4 -1
  90. data/spec/norma_ruby_sql_spec.rb +4 -1
  91. data/spec/norma_sql_spec.rb +4 -1
  92. data/spec/norma_tables_spec.rb +2 -2
  93. data/spec/ruby_api_spec.rb +1 -1
  94. data/spec/spec_helper.rb +2 -0
  95. data/spec/transform_surrogate_spec.rb +59 -0
  96. metadata +70 -60
  97. data/TODO +0 -308
  98. data/lib/activefacts/cql/compiler/join.rb +0 -162
  99. data/lib/activefacts/generate/oo.rb +0 -176
  100. data/lib/activefacts/generate/ordered.rb +0 -602
@@ -6,7 +6,7 @@
6
6
  #
7
7
  module ActiveFacts
8
8
  module CQL
9
- grammar Language
9
+ grammar English
10
10
 
11
11
  # >>>>>>>>>>>>>>>>>>>> Object Types <<<<<<<<<<<<<<<<<<<<
12
12
  # The pattern to introduce a Value Type
@@ -38,10 +38,9 @@ module ActiveFacts
38
38
  { def independent; !i.empty?; end }
39
39
  end
40
40
 
41
- rule in_which # Introduce an objectification join
41
+ rule in_which # Introduce an objectification step
42
42
  where / # Old syntax
43
43
  in s which # preferred syntax
44
- { def independent; !i.empty?; end }
45
44
  end
46
45
 
47
46
  # Units conversion keyword
@@ -126,6 +125,10 @@ module ActiveFacts
126
125
  s clauses s only s if s r2:clauses s c:context_note? enforcement ';'
127
126
  end
128
127
 
128
+ rule only_if
129
+ only s if s
130
+ end
131
+
129
132
  # Subset constraint using "if A then B" syntax
130
133
  rule if_b_then_a
131
134
  s if s clauses s then s r2:clauses s c:context_note? enforcement ';'
@@ -204,7 +207,18 @@ module ActiveFacts
204
207
  id (s id)*
205
208
  end
206
209
 
210
+ rule negative_prefix
211
+ s it s is s not s the s case s that s
212
+ end
213
+
214
+ rule agg_of of end
215
+ rule agg_in in end
216
+ rule restricted_to 'restricted' s 'to' s !alphanumeric end
217
+ # any is optionally used in an identifying role_list
218
+ rule any one / a end
219
+
207
220
  # >>>>>>>>>>>>>>>>>>>> Internal vocabulary <<<<<<<<<<<<<<<<<<<<
221
+ rule a ('a' !alphanumeric /'an' !alphanumeric) end
208
222
  rule all 'all' !alphanumeric end
209
223
  rule ascending 'ascending' !alphanumeric end
210
224
  rule at 'at' !alphanumeric end
@@ -240,6 +254,7 @@ module ActiveFacts
240
254
  rule because 'because' !alphanumeric end
241
255
  rule but 'but' !alphanumeric end
242
256
  rule by 'by' !alphanumeric end # fix? Used in 'returning' for ordering
257
+ rule case 'case' !alphanumeric end
243
258
  rule definitely 'definitely' !alphanumeric end
244
259
  rule ephemera 'ephemera' !alphanumeric end
245
260
  rule false 'false' !alphanumeric end
@@ -249,9 +264,11 @@ module ActiveFacts
249
264
  rule in 'in' !alphanumeric end
250
265
  rule import 'import' !alphanumeric end
251
266
  rule independent 'independent' !alphanumeric end
267
+ rule stronglyintransitive 'stronglyintransitive' !alphanumeric end
252
268
  rule intransitive 'intransitive' !alphanumeric end
253
269
  rule irreflexive 'irreflexive' !alphanumeric end
254
270
  rule is 'is' !alphanumeric end
271
+ rule it 'it' !alphanumeric end
255
272
  rule its 'its' !alphanumeric end
256
273
  rule masculine 'masculine' !alphanumeric end
257
274
  rule maybe 'maybe' !alphanumeric end
@@ -264,13 +281,13 @@ module ActiveFacts
264
281
  rule personal 'personal' !alphanumeric end
265
282
  rule radix_point '.' end
266
283
  rule reflexive 'reflexive' !alphanumeric end
267
- rule restricted 'restricted' !alphanumeric end
268
284
  rule returning 'returning' !alphanumeric end
269
285
  rule separate 'separate' !alphanumeric end
270
286
  rule so_that 'so' S that end
271
287
  rule static 'static' !alphanumeric end
272
288
  rule symmetric 'symmetric' !alphanumeric end
273
289
  rule that 'that' !alphanumeric end
290
+ rule the 'the' !alphanumeric end
274
291
  rule then 'then' !alphanumeric end
275
292
  rule to 'to' !alphanumeric end
276
293
  rule to_avoid to s 'avoid' !alphanumeric end
@@ -116,6 +116,7 @@ module ActiveFacts
116
116
  rule string_char
117
117
  ( '\\' [befntr\\']
118
118
  / '\\' [0-7] [0-7] [0-7]
119
+ / '\\' [\r]* [\n] [\r]*
119
120
  / '\\0'
120
121
  / '\\x' [0-9A-Fa-f] [0-9A-Fa-f]
121
122
  / '\\u' [0-9A-Fa-f] [0-9A-Fa-f] [0-9A-Fa-f] [0-9A-Fa-f]
@@ -157,7 +158,7 @@ module ActiveFacts
157
158
  end
158
159
 
159
160
  rule alpha
160
- [A-Za-z_]
161
+ [[:alpha:]]
161
162
  end
162
163
 
163
164
  rule alphanumeric
@@ -190,6 +191,63 @@ module ActiveFacts
190
191
  }
191
192
  end
192
193
 
194
+ rule regular_expression
195
+ '/' !'/' regular_expression_contents '/'
196
+ {
197
+ def contents
198
+ regular_expression_contents.text_value
199
+ end
200
+ }
201
+ end
202
+
203
+ rule regular_expression_contents
204
+ regular_expression_alternate ( '|' regular_expression_alternate )*
205
+ end
206
+
207
+ rule regular_expression_alternate
208
+ regular_expression_sequence
209
+ end
210
+
211
+ rule regular_expression_sequence
212
+ regular_expression_atom*
213
+ end
214
+
215
+ rule regular_expression_atom
216
+ (
217
+ '[' character_classes ']'
218
+ / regular_expression_group
219
+ / ![*+?()|/] string_char
220
+ ) regular_expression_multiplicity?
221
+ end
222
+
223
+ rule character_classes
224
+ character_class+
225
+ end
226
+
227
+ rule character_class
228
+ !']' string_char '-' !']' string_char
229
+ / '-'
230
+ / !']' string_char
231
+ end
232
+
233
+ rule regular_expression_multiplicity
234
+ '*' / '+' / '?'
235
+ end
236
+
237
+ rule regular_expression_group
238
+ '('
239
+ regular_expression_group_extension?
240
+ regular_expression_contents
241
+ ')'
242
+ end
243
+
244
+ rule regular_expression_group_extension
245
+ '?' (
246
+ '<' ( !'>' .)+ '>' # A tag for a regular expression group
247
+ # REVISIT: Add more group extensions as needed
248
+ )
249
+ end
250
+
193
251
  end
194
252
  end
195
253
  end
@@ -15,19 +15,22 @@ module ActiveFacts
15
15
  end
16
16
 
17
17
  rule entity_type
18
+ s each?
18
19
  s term_definition_name
19
20
  m1:mapping_pragmas
21
+ c:context_note?
20
22
  sup:(basetype / subtype)
21
23
  &{|s|
22
24
  # There's an implicit type when we use an identification mode, register it:
23
- mode = s[3].identification_mode
25
+ mode = s[6].identification_mode
24
26
  if mode
25
- input.context.object_type(s[1].value+mode, "identification mode type")
26
- input.context.object_type(s[1].value+' '+mode, "identification mode type")
27
+ input.context.object_type(s[3].value+mode, "identification mode type")
28
+ input.context.object_type(s[3].value+' '+mode, "identification mode type")
27
29
  end
28
30
  true
29
31
  }
30
32
  m2:mapping_pragmas
33
+ c2:context_note?
31
34
  ec:entity_clauses?
32
35
  ';'
33
36
  {
@@ -36,7 +39,8 @@ module ActiveFacts
36
39
  clauses_ast = ec.empty? ? [] : ec.ast
37
40
  pragmas = m1.value+m2.value
38
41
  pragmas << 'independent' if sup.independent
39
- Compiler::EntityType.new name, sup.supers, sup.ast, pragmas, clauses_ast
42
+ context_note = !c.empty? ? c.ast : (!c2.empty? ? c2.ast : nil)
43
+ Compiler::EntityType.new name, sup.supers, sup.ast, pragmas, clauses_ast, context_note
40
44
  end
41
45
  }
42
46
  end
@@ -62,7 +66,7 @@ module ActiveFacts
62
66
  end
63
67
 
64
68
  rule supertype_list
65
- primary:term s alternate_supertypes:( ',' s !identified_by name:term s )*
69
+ primary:term s alternate_supertypes:( (','/'and' !alpha) s !identified_by name:term s )*
66
70
  {
67
71
  def value
68
72
  [primary.value, *alternate_supertypes.elements.map { |sup| sup.name.value } ]
@@ -79,7 +83,7 @@ module ActiveFacts
79
83
  if r.empty?
80
84
  value_constraint = nil
81
85
  else
82
- value_constraint = Compiler::ValueConstraint.new(r.value_constraint.ranges, r.value_constraint.units, r.enforcement.ast)
86
+ value_constraint = Compiler::ValueConstraint.new(r.value_constraint.ast, r.enforcement.ast)
83
87
  end
84
88
  Compiler::ReferenceMode.new(i.value, value_constraint, value_type_parameters.values)
85
89
  end
@@ -115,7 +119,13 @@ module ActiveFacts
115
119
 
116
120
  # Identified by roles... also used for constraints, beware
117
121
  rule role_list
118
- head:term_or_unary s tail:( ( and S / ',' s ) term_or_unary s )*
122
+ a:any? s
123
+ head:term_or_unary s
124
+ tail:(
125
+ ( and S / ',' s )
126
+ any? s
127
+ term_or_unary s
128
+ )*
119
129
  {
120
130
  def ast
121
131
  [head.ast, *tail.elements.map{|e| e.term_or_unary.ast}]
@@ -124,7 +134,7 @@ module ActiveFacts
124
134
  end
125
135
 
126
136
  rule unary_text
127
- (s !non_phrase !term id)*
137
+ (s !any !non_phrase !term id)*
128
138
  {
129
139
  def node_type; :linking; end
130
140
  }
@@ -146,11 +156,11 @@ module ActiveFacts
146
156
  end
147
157
  }
148
158
  /
149
- s !non_phrase id s &non_phrase s ss:subscript
159
+ s !non_phrase id s &non_phrase s ss:subscript?
150
160
  { # A forward-referenced entity type
151
161
  # REVISIT: A change in this rule might allow forward-referencing a multi-word term
152
162
  def ast
153
- Compiler::VarRef.new(id.text_value, nil, nil, nil, ss.empty? ? nil : ss.value)
163
+ Compiler::Reference.new(id.text_value, nil, nil, nil, ss.empty? ? nil : ss.value)
154
164
  end
155
165
  }
156
166
  end
@@ -171,10 +181,10 @@ module ActiveFacts
171
181
  end
172
182
 
173
183
  rule entity_clauses
174
- (':' / where) s joined_clauses
184
+ (':' / where) s query_clauses
175
185
  {
176
186
  def ast
177
- joined_clauses.ast
187
+ query_clauses.ast
178
188
  end
179
189
  }
180
190
  end
@@ -25,20 +25,24 @@ module ActiveFacts
25
25
  is s (independent s )? identified_by
26
26
  /
27
27
  subtype_prefix (independent s )? term_definition_name
28
- &{|e| input.context.object_type(e[2].value, "subtype") }
28
+ &{|e| input.context.object_type(e[2].value, "subtype") }
29
29
  end
30
30
 
31
31
  rule prescan
32
- s (
32
+ s each?
33
+ s (
33
34
  term_definition_name mapping_pragmas entity_prefix
34
35
  &{|e| input.context.object_type(e[0].value, "entity type") }
35
36
  /
36
- t1:term_definition_name mapping_pragmas written_as t2:term_definition_name
37
- &{|e| input.context.object_type(e[0].value, "value type")
38
- input.context.object_type(e[3].value, "value type")
37
+ t1:term_definition_name mapping_pragmas written_as any? s t2:term_definition_name
38
+ &{|e|
39
+ new_term = e[0].value
40
+ input.context.object_type(new_term, "value type")
41
+ base_term = e[5].value
42
+ input.context.object_type(base_term, "value type")
39
43
  }
40
44
  /
41
- term_definition_name s mapping_pragmas is s (independent s )? where
45
+ term_definition_name s mapping_pragmas is_where
42
46
  &{|e| input.context.object_type(e[0].value, "objectified_fact_type") }
43
47
  )?
44
48
  prescan_rest
@@ -61,7 +65,7 @@ module ActiveFacts
61
65
  / '(' as S term_definition_name s ')' s # Prepare for a Role Name
62
66
  &{|s| input.context.role_name(s[3].value) }
63
67
  / new_derived_value # Prepare for a derived term
64
- / new_adjective_term # Prepae for an existing term with new Adjectives
68
+ / new_adjective_term # Prepare for an existing term with new Adjectives
65
69
  # The remaining rules exist to correctly eat up anything that doesn't match the above:
66
70
  / global_term # If we see A B - C D, don't recognise B as a new adjective for C D.
67
71
  / prescan_aggregate
@@ -76,7 +80,7 @@ module ActiveFacts
76
80
 
77
81
  # Not sure this is even needed, but it doesn't seem to hurt:
78
82
  rule prescan_aggregate
79
- aggregate_type:id s of s global_term in s &'('
83
+ aggregate_type:id s agg_of s global_term agg_in s &'('
80
84
  end
81
85
 
82
86
  rule new_derived_value
@@ -163,7 +167,7 @@ module ActiveFacts
163
167
  / but
164
168
  / if
165
169
  / role_list_constraint_followers
166
- / only
170
+ / only_if
167
171
  / or
168
172
  / quantifier
169
173
  / returning
@@ -8,15 +8,19 @@ module ActiveFacts
8
8
  module CQL
9
9
  grammar ValueTypes
10
10
  rule value_type
11
+ s each?
11
12
  s term_definition_name
12
13
  m1:mapping_pragmas
13
14
  # REVISIT: ORM2 would allow (subtype_prefix term)?
14
15
  written_as
16
+ any? s
15
17
  base:(term/implicit_value_type_name) s
16
18
  value_type_parameters
17
19
  u:units?
20
+ c:context_note?
18
21
  r:(value_constraint enforcement)?
19
22
  m2:mapping_pragmas
23
+ c2:context_note?
20
24
  s ';' s
21
25
  {
22
26
  def ast
@@ -24,11 +28,12 @@ module ActiveFacts
24
28
  params = value_type_parameters.values
25
29
  value_constraint = nil
26
30
  unless r.empty?
27
- value_constraint = Compiler::ValueConstraint.new(r.value_constraint.ranges, r.value_constraint.units, r.enforcement.ast)
31
+ value_constraint = Compiler::ValueConstraint.new(r.value_constraint.ast, r.enforcement.ast)
28
32
  end
29
33
  units = u.empty? ? [] : u.value
30
34
  pragmas = m1.value+m2.value
31
- Compiler::ValueType.new name, base.value, params, units, value_constraint, pragmas
35
+ context_note = !c.empty? ? c.ast : (!c2.empty? ? c2.ast : nil)
36
+ Compiler::ValueType.new name, base.value, params, units, value_constraint, pragmas, context_note
32
37
  end
33
38
  }
34
39
  end
@@ -125,7 +130,7 @@ module ActiveFacts
125
130
  end
126
131
 
127
132
  rule non_unit
128
- restricted / conversion / approximately / ephemera
133
+ restricted_to / conversion / approximately / ephemera
129
134
  end
130
135
 
131
136
  rule unit
@@ -146,20 +151,34 @@ module ActiveFacts
146
151
  end
147
152
 
148
153
  rule value_constraint
149
- restricted s to s range_list s u:units?
154
+ restricted_to restricted_values c:context_note?
150
155
  {
151
- def ranges
152
- range_list.ranges
153
- end
154
-
155
- def units
156
- u.empty? ? nil : u.value
156
+ def ast
157
+ v = restricted_values.values
158
+ c[:context_note] = c.ast unless c.empty?
159
+ v
157
160
  end
158
161
  }
159
162
  # REVISIT: "where the possible value/s of that <Term> is/are value (, ...)"
160
163
  end
161
164
 
162
- # REVISIT: Value constraint for ValueType or EntityType&Refmode: "the possible values of <TYPE> are value (, ...)"
165
+ rule restricted_values
166
+ range_list s u:units?
167
+ {
168
+ def values
169
+ { :ranges => range_list.ranges,
170
+ :units => u.empty? ? nil : u.value
171
+ }
172
+ end
173
+ }
174
+ /
175
+ regular_expression
176
+ {
177
+ def values
178
+ { :regular_expression => contents }
179
+ end
180
+ }
181
+ end
163
182
 
164
183
  rule range_list
165
184
  '{' s
@@ -12,17 +12,24 @@ require 'activefacts/cql/compiler/fact_type'
12
12
  require 'activefacts/cql/compiler/expression'
13
13
  require 'activefacts/cql/compiler/fact'
14
14
  require 'activefacts/cql/compiler/constraint'
15
- require 'activefacts/cql/compiler/join'
15
+ require 'activefacts/cql/compiler/query'
16
16
 
17
17
  module ActiveFacts
18
18
  module CQL
19
19
  class Compiler < ActiveFacts::CQL::Parser
20
+ LANGUAGES = {
21
+ 'en' => 'English',
22
+ 'fr' => 'French',
23
+ 'cn' => 'Mandarin'
24
+ }
20
25
  attr_reader :vocabulary
21
26
 
22
- def initialize(filename = "stdin")
23
- @filename = filename
27
+ def initialize *a
28
+ @filename = a.shift || "stdio"
29
+ super *a
24
30
  @constellation = ActiveFacts::API::Constellation.new(ActiveFacts::Metamodel)
25
- debug :file, "Parsing '#{filename}'"
31
+ @language = nil
32
+ debug :file, "Parsing '#{@filename}'"
26
33
  end
27
34
 
28
35
  def compile_file filename
@@ -35,8 +42,25 @@ module ActiveFacts
35
42
  @vocabulary
36
43
  end
37
44
 
45
+ # Load the appropriate natural language module
46
+ def detect_language
47
+ @filename =~ /.*\.(..)\.cql$/i
48
+ language_code = $1
49
+ @language = LANGUAGES[language_code] || 'English'
50
+ end
51
+
52
+ def include_language
53
+ detect_language unless @langage
54
+ require 'activefacts/cql/Language/'+@language
55
+ language_module = ActiveFacts::CQL.const_get(@language)
56
+ extend language_module
57
+ end
58
+
38
59
  def compile input
60
+ include_language
61
+
39
62
  @string = input
63
+
40
64
  # The syntax tree created from each parsed CQL statement gets passed to the block.
41
65
  # parse_all returns an array of the block's non-nil return values.
42
66
  ok = parse_all(@string, :definition) do |node|
@@ -69,9 +93,12 @@ module ActiveFacts
69
93
  def compile_import file, aliases
70
94
  saved_index = @index
71
95
  saved_block = @block
96
+ saved_string = @string
97
+ saved_input_length = @input_length
72
98
  old_filename = @filename
73
- @filename = file+'.cql'
99
+ @filename = file+'.cql' # REVISIT: Use File.dirname(@filename)+@filename ?
74
100
 
101
+ # REVISIT: Save and use another @vocabulary for this file?
75
102
  File.open(@filename) do |f|
76
103
  ok = parse_all(f.read, nil, &@block)
77
104
  end
@@ -83,6 +110,8 @@ module ActiveFacts
83
110
  ensure
84
111
  @block = saved_block
85
112
  @index = saved_index
113
+ @input_length = saved_input_length
114
+ @string = saved_string
86
115
  @filename = old_filename
87
116
  nil
88
117
  end