upl 0.2.1 → 0.2.2

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: '098024c977917fd375c9743595fbee2063227946d6c2df8110ca5a7d76dd7cca'
4
- data.tar.gz: b3a4df0143e5847a303fbef5dbbdb0f639c5270cb577c1bff932b5e15ed52c2d
3
+ metadata.gz: a3f3986baaa4caf8654ae53619fc3606dd9f608f7f7722cd3860d6ec2af8a1fe
4
+ data.tar.gz: 18e8d59804dd3802da05df95d667ffff47d71e73af82d3bbad509dc0ab4f2930
5
5
  SHA512:
6
- metadata.gz: 21f5784f9b8c8699c75728cff0f57bf66f6eec802d613fb5018d224d4376d57702b570a7eb1210218bfd828f954e283a265f3885474eb1cd4c1a8c9599270936
7
- data.tar.gz: 25ad0f5cfa693432e3ceee531eefa7d8ebde8f587ae8d7b80eacc57fb68b7baab72c21491e45a27c98c886bd458193d1c71627b4c6a7c038c548d853a47393d5
6
+ metadata.gz: f34cf6fafe347a3f7494108bf286abbff5771e51450594858d455d13630ac7645f36f1b26c3f45757a611bdca52dbe604dbd5e4c63c54ee4cb3cf176d22de7a8
7
+ data.tar.gz: c4524355fa328c53fe99c56a1a99553e0a9cecff4b31c177571f4c6b895bc229388829d406a714e34b61667f975b046dde2507236c473d565f415634a130f604
@@ -1,3 +1,6 @@
1
+ == 0.2.2
2
+ * restrict to <=swi-prolog-8.1.22
3
+
1
4
  == 0.2.1
2
5
  * Query map_blk for transforms
3
6
  * frames for Query reuse
data/lib/upl.rb CHANGED
@@ -15,12 +15,11 @@ require_relative 'upl/foreign'
15
15
  require_relative 'upl/query'
16
16
 
17
17
  module Upl
18
- # todo need .call and .consult at this level?
19
-
18
+ # You probably want to use Query.new instead of this.
20
19
  # an enumerator yielding hashes keyed by the variables, mapping to the term
21
20
  module_function def query string_or_term, vars = nil, &blk
22
21
  if string_or_term.is_a?(Term) && vars
23
- Runtime.term_vars_query string_or_term, vars
22
+ Runtime.query string_or_term, vars
24
23
  else
25
24
  case string_or_term
26
25
  when Term
@@ -29,13 +28,19 @@ module Upl
29
28
  Runtime.query string_or_term
30
29
  when String
31
30
  term, vars = Runtime.term_vars string_or_term
32
- Runtime.term_vars_query term, vars, &blk
31
+ Runtime.query term, vars, &blk
33
32
  else
34
33
  raise "dunno about #{string_or_term.inspect}"
35
34
  end
36
35
  end
37
36
  end
38
37
 
38
+ # For semidet predicates, ie that have only one result.
39
+ # You have to extract values using Upl::Variable#to_ruby.
40
+ module_function def call term
41
+ Runtime::call term
42
+ end
43
+
39
44
  module_function def consult filename
40
45
  p = Pathname filename
41
46
  Runtime::call %Q{["#{p.realpath.to_s}"]}
@@ -38,7 +38,7 @@ module Upl
38
38
  query_hash.delete :Dict
39
39
 
40
40
  # now we have a result set with K,V values
41
- en = Upl::Runtime.term_vars_query query_term, query_hash
41
+ en = Upl::Runtime.query query_term, query_hash
42
42
 
43
43
  # map to a hash-y thing
44
44
  en.each_with_object Dict.new(tag: dict_tag(dict_term_t)) do |row,values|
@@ -9,11 +9,13 @@ module Upl
9
9
 
10
10
  # fetch config values from swipl executable
11
11
  def self.swipl_config_values
12
- swipl_exe = 'swipl'
13
- values = `#{swipl_exe} --dump-runtime-variables=sh`.each_line.with_object Hash.new do |line,ha|
14
- # split by = and for rhs strip surrounding quotes and trailing ;
15
- line =~ /^([^=]+)="([^"]*)";\s*$/
16
- ha[$1] = $2.strip
12
+ @swipl_config_value ||= begin
13
+ swipl_exe = 'swipl'
14
+ values = `#{swipl_exe} --dump-runtime-variables=sh`.each_line.with_object Hash.new do |line,ha|
15
+ # split by = and for rhs strip surrounding quotes and trailing ;
16
+ line =~ /^([^=]+)="([^"]*)";\s*$/
17
+ ha[$1] = $2.strip
18
+ end
17
19
  end
18
20
  rescue Errno::ENOENT => ex
19
21
  puts "#{swipl_exe} not found on path #{ENV['PATH']}"
@@ -33,6 +35,11 @@ module Upl
33
35
  exit 1
34
36
  end
35
37
 
38
+ if (version = swipl_config_values['PLVERSION']) >= '80100'
39
+ # 801xx seems to have changed some calls. Not sure yet what they are.
40
+ raise "unsupported version #{version}"
41
+ end
42
+
36
43
  dlload so_path
37
44
 
38
45
  def self.ruby_free_fn
@@ -40,7 +40,7 @@ module Upl
40
40
  end
41
41
 
42
42
  def call
43
- @results ||= Upl::Runtime.term_vars_query @term, @vars
43
+ @results ||= Upl::Runtime.query @term, @vars
44
44
  end
45
45
 
46
46
  def each &blk
@@ -72,10 +72,7 @@ module Upl
72
72
  end
73
73
 
74
74
  # once_only. Should probably be a singleton or something.
75
- # TODO Nope, wrong. init is for the entire engine.
76
- # PL_thread_attach_engine is for one-to-one threads,
77
- # PL_create_engine is for engine pool
78
- Thread::current[:upl] ||= init
75
+ @_upl_runtime ||= init
79
76
 
80
77
  def self.predicate name, arity, module_name = 0
81
78
  Extern.PL_predicate Ptr[name.to_s], arity, Fiddle::Pointer[module_name]
@@ -122,11 +119,12 @@ module Upl
122
119
 
123
120
  # just to make sure the query handle pointer is properly closed
124
121
  # TODO should be private, because args are gnarly
125
- def self.open_query qterm, args, mod: nil, flags: nil, &blk
122
+ def self.open_query qterm, mod: nil, flags: nil, &blk
126
123
  # This will need a string for the module, eventually
127
124
  # module is NULL, flags is 0
128
125
  mod ||= Fiddle::NULL
129
126
  flags ||= flags=Extern::Flags::PL_Q_EXT_STATUS | Extern::Flags::PL_Q_CATCH_EXCEPTION
127
+ args = TermVector.new qterm.arity do |idx| qterm[idx] end
130
128
 
131
129
  query_id_p = Extern.PL_open_query mod, flags, qterm.to_predicate, args.terms
132
130
  query_id_p != 0 or raise 'no space on environment stack, see SWI-Prolog docs for PL_open_query'
@@ -150,93 +148,43 @@ module Upl
150
148
  end
151
149
  end
152
150
 
153
- # do a query for the given term and vars, as parsed by term_vars
151
+ # Do a query for the given term and vars, as parsed by term_vars.
154
152
  # qvars_hash is a hash of :VariableName => Term(PL_VARIABLE)
155
- # and each variable is already bound in term.
153
+ # and each variable is already bound in qterm.
156
154
  # TODO much duplication between this and .query below
157
- def self.term_vars_query qterm, qvars_hash
155
+ def self.query qterm, qvars_hash = nil
158
156
  raise "not a term" unless Term === qterm
159
157
  return enum_for __method__, qterm, qvars_hash unless block_given?
160
158
 
161
- with_frame do |fid_t|
162
- # populate input values from qterm
163
- args = TermVector.new qterm.arity do |idx| qterm[idx] end
164
- open_query qterm, args do |query_id_p|
165
- loop do
166
- case Extern.PL_next_solution query_id_p
167
- when Extern::ExtStatus::FALSE
168
- break
169
-
170
- when Extern::ExtStatus::EXCEPTION
171
- raise_prolog_or_ruby query_id_p
172
-
173
- # when Extern::ExtStatus::TRUE
174
- # when Extern::ExtStatus::LAST
175
- else
176
- hash = qvars_hash.each_with_object Hash.new do |(name_sym,var),ha|
177
- # var will be invalidated by the next call to PL_next_solution,
178
- # so we need to construct a ruby tree copy of the value term.
179
- ha[name_sym] = var.to_ruby
180
- end
181
-
182
- yield hash
183
- end
159
+ result_map =
160
+ if qvars_hash
161
+ lambda do
162
+ # construct map of given variable names to their values
163
+ qvars_hash.each_with_object Hash.new do |(name_sym,var),ha|
164
+ ha[name_sym] = var.to_ruby
184
165
  end
185
166
  end
167
+ else
168
+ # no variable names provided so just get the values
169
+ ->{ qterm.map{|term_t| Tree.of_term term_t} }
186
170
  end
187
- end
188
-
189
- def self.predicate name, arity
190
- pred_p = Extern.PL_predicate Ptr[name.to_s], arity, Fiddle::NULL
191
- end
192
-
193
- # Simple query with predicate / arity
194
- # Returns an array of arrays.
195
- # TODO remove, not really used
196
- def self.squery predicate_str, arity
197
- return enum_for :squery, predicate_str, arity unless block_given?
198
-
199
- # bit of a hack because open_query wants to call to_predicate
200
- # and we have to construct that manually here because Upl::Term
201
- # is slightly ill-suited.
202
- qterm = Object.new
203
- qterm.define_singleton_method :to_predicate do
204
- p_functor = Extern::PL_new_functor predicate_str.to_sym.to_atom, arity
205
- Extern::PL_pred p_functor, Fiddle::NULL
206
- end
207
-
208
- args = TermVector.new arity
209
- open_query qterm, args do |query_id_p|
210
- loop do
211
- rv = Extern.PL_next_solution query_id_p
212
- break if rv == 0
213
- yield args.each_t.map{|term_t| Tree.of_term term_t}
214
- end
215
- end
216
- end
217
-
218
- # TODO much duplication between this and .term_vars_query
219
- # Only used by the term branch of Upl.query
220
- def self.query term
221
- raise "not a Term" unless Term === term
222
- return enum_for :query, term unless block_given?
223
171
 
224
- answer_lst = TermVector.new term.arity do |idx| term[idx] end
225
-
226
- open_query term, answer_lst do |query_id_p|
172
+ open_query qterm do |query_id_p|
227
173
  loop do
228
- case Extern.PL_next_solution query_id_p
174
+ case (status = Extern.PL_next_solution query_id_p)
229
175
  when Extern::ExtStatus::FALSE
230
176
  break
231
177
 
232
178
  when Extern::ExtStatus::EXCEPTION
233
179
  raise_prolog_or_ruby query_id_p
234
180
 
235
- # when Extern::ExtStatus::TRUE
236
- # when Extern::ExtStatus::LAST
237
- else
238
- yield answer_lst.each_t.map{|term_t| Tree.of_term term_t}
181
+ when Extern::ExtStatus::TRUE, Extern::ExtStatus::LAST
182
+ # var will be invalidated by the next call to PL_next_solution,
183
+ # so we need to construct a ruby tree copy of the value term immediately.
184
+ yield result_map[]
239
185
 
186
+ else
187
+ raise "unknown PL_next_solution status #{status}"
240
188
  end
241
189
  end
242
190
  end
@@ -1,3 +1,3 @@
1
1
  module Upl
2
- VERSION = '0.2.1'
2
+ VERSION = '0.2.2'
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: upl
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.1
4
+ version: 0.2.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - John Anderson
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2020-02-16 00:00:00.000000000 Z
11
+ date: 2020-05-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler