upl 0.2.1 → 0.2.2
Sign up to get free protection for your applications and to get access to all the features.
- 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
|