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 +4 -4
- data/History.txt +3 -0
- data/lib/upl.rb +9 -4
- data/lib/upl/dict.rb +1 -1
- data/lib/upl/extern.rb +12 -5
- data/lib/upl/query.rb +1 -1
- data/lib/upl/runtime.rb +23 -75
- data/lib/upl/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a3f3986baaa4caf8654ae53619fc3606dd9f608f7f7722cd3860d6ec2af8a1fe
|
4
|
+
data.tar.gz: 18e8d59804dd3802da05df95d667ffff47d71e73af82d3bbad509dc0ab4f2930
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f34cf6fafe347a3f7494108bf286abbff5771e51450594858d455d13630ac7645f36f1b26c3f45757a611bdca52dbe604dbd5e4c63c54ee4cb3cf176d22de7a8
|
7
|
+
data.tar.gz: c4524355fa328c53fe99c56a1a99553e0a9cecff4b31c177571f4c6b895bc229388829d406a714e34b61667f975b046dde2507236c473d565f415634a130f604
|
data/History.txt
CHANGED
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
|
-
#
|
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.
|
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.
|
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}"]}
|
data/lib/upl/dict.rb
CHANGED
@@ -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.
|
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|
|
data/lib/upl/extern.rb
CHANGED
@@ -9,11 +9,13 @@ module Upl
|
|
9
9
|
|
10
10
|
# fetch config values from swipl executable
|
11
11
|
def self.swipl_config_values
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
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
|
data/lib/upl/query.rb
CHANGED
data/lib/upl/runtime.rb
CHANGED
@@ -72,10 +72,7 @@ module Upl
|
|
72
72
|
end
|
73
73
|
|
74
74
|
# once_only. Should probably be a singleton or something.
|
75
|
-
|
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,
|
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
|
-
#
|
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
|
153
|
+
# and each variable is already bound in qterm.
|
156
154
|
# TODO much duplication between this and .query below
|
157
|
-
def self.
|
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
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
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
|
-
|
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
|
-
|
236
|
-
|
237
|
-
|
238
|
-
yield
|
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
|
data/lib/upl/version.rb
CHANGED
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.
|
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-
|
11
|
+
date: 2020-05-24 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|