Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

O-Prolog ver0.90

1,171 views
Skip to first unread message

ken...@gmail.com

unread,
Jun 1, 2018, 2:47:30 AM6/1/18
to
Dear everyone

Today, I updated to O-Prolog ver 0.90.
http://eisl.kan-be.com/library/oprolog1.html
I appreciate having received many advice.
I think O-Prolog still has many nonconformities.
I would be pleased if you give me some advice.

Kenichi Sasagawa

Ulrich Neumerkel

unread,
Jun 1, 2018, 4:43:20 AM6/1/18
to
ken...@gmail.com writes:
>Today, I updated to O-Prolog ver 0.90.
>http://eisl.kan-be.com/library/oprolog1.html
>I appreciate having received many advice.
>I think O-Prolog still has many nonconformities.
>I would be pleased if you give me some advice.

#5, #7, #8, #9, #10, #15, #18, #19, #222, #223,
#27, #30, #32, #203, #282, #37, #38.

of

http://www.complang.tuwien.ac.at/ulrich/iso-prolog/conformity_testing

(I stopped at #38.)

BTW, did you receive my e-mail?

ken...@gmail.com

unread,
Jun 1, 2018, 4:57:22 AM6/1/18
to
Thank you very much for reply out of your busy schedule.
I received e-mail from you.

Kenichi Sasagawa

burs...@gmail.com

unread,
Jun 1, 2018, 6:44:57 AM6/1/18
to
Yeah concerning strings, there are a lot of
sanity checks around. Question is, how do you
implement it, so that you have a usuable Top-Level?

Variant 1:
- Fatal abort if there is something wrong with
the string. You would do the checks directly
in your token scanner?

Variant 2:
- A less fatal error message, allowing a slightly
bigger token range, and then do an additional
check on top of it?

I chose Variant 2, and since my PrologReader stuff
is open source, you can have a look. Here is
what you see in the top-level:

Jekejeke Prolog 2, Runtime Library 1.2.6
(c) 1985-2018, XLOG Technologies GmbH, Switzerland

?- writeq(' ').
Error: Illegal layout character in string.
writeq(' ').
^

?- writeq('
Error: Illegal end of line in string.
writeq('
^

And here is not ScannerToken, but the post processor
of tokens, that again does a second scan of tokens,
to implement some sanity:

public static String resolveEscape(String str,
int quote, boolean cont, int offset, CodeType d)
https://github.com/jburse/jekejeke-devel/blob/master/utils/headless/matula/util/regex/CompLang.java#L155

Warning: For Variant 2, sometimes you need to check
thinhgs twice, in the ScannerToken and in the above
escape resolve, but the ScannerToken will remain

silent, it will just hand the result to the parser,
which can decide when it will hand the result to
the escape resolver. This way you can also filter

out noise, error noise that you would otherwise
get, when you for example skip superflous tokens
from a line.

burs...@gmail.com

unread,
Jun 1, 2018, 6:56:48 AM6/1/18
to
The method escapeControl() does the reverse,
it will basicall escape the ASCII control characters,
and maybe more.

This is part and parcel of the automatic atom
quoting, when you implement writeq, write_canonical,
respectively the quoted(true) option.

There is a funny ASCII control character,
the Bell character, you should hear a beep on
some terminals:
https://en.wikipedia.org/wiki/Bell_character

In the top-level, it would then beep when you
use write/1, but it shouldn't beep when you use
writeq/1, or usually answer substitutions also

don't beep, as you see here:

Welcome to SWI-Prolog (threaded, 64 bits, version 7.7.14)
SWI-Prolog comes with ABSOLUTELY NO WARRANTY. This is free software.

?- X = 'abc\adef'.
X = 'abc\adef'.

Here is a test case for the escapeControl() method
from my open source code:

/**
* <p>Some tests.</p>
*
* @param args Not used.
*/
public static void main(String[] args) throws ScannerError {
String foo = "abc\\adef";
String res = resolveEscape(foo, '\'', false, 0, CodeType.ISO_CODETYPE);
System.out.println("res=" + res);

String res2 = escapeControl(res, CodeType.ISO_CODETYPE);
System.out.println("res=" + res2);
}

And here you see the result:

res=abc def
res=abc\adef

The first line should beep on some terminals! :-) :-)

burs...@gmail.com

unread,
Jun 1, 2018, 7:07:11 AM6/1/18
to
Lets see whether Tau Prolog beeps. As a joke they
could implement something via JavaScript, for write/1,
that invokes some sound clip. So the old school hackers,

that are used to VT-100 or what ever terminal, feel
comfortable. Unfortunately their answer substitution
display is not what one would expect:

X = 'abc\adef'.

?- X = 'abc\adef'.
X = abc def.

I comes out unquoted. I made some pictures:

Interesting how many details are involved
in a Prolog Top-Level. For example answer
substitutions are usually displayed with writeq/1.
https://gist.github.com/jburse/2a7762893e2213daba1b22de01566a16#gistcomment-2607111

burs...@gmail.com

unread,
Jun 1, 2018, 7:20:51 AM6/1/18
to
Disclaimer:

The conversion is possibly not a good idea for
large blobs, etc.., also buffering a token and
converting it for large blobs might not be

a good idea. Other Prolog systems might do much
more clever things directly on the streams. There
might be also programming techniques,

that do not polute memory that much as I do....
I might also use different code in the future.
The only optimization I have implement is,

that it returns the original string and does
use any buffering if no escape was procesed, so
memory usage goes not up if code doesn't contain

escapes....

Cannot offer more.

burs...@gmail.com

unread,
Jun 1, 2018, 7:24:30 AM6/1/18
to
Corr.:
that it returns the original string and does
not use any buffering if no escape was detected, so

Should hold for both ways... You see such issues
in the start-up time of a Prolog system. A special
clause file format might help, or might also not

help. I have seen millions of attempts of binary
XML, whatever, but the positive impact can be
marginal, if you optimize the non optimized

format parser... He He. Of course a constant
pool, like Java classes have, or some DEX format
or what ever, that is directly mapped into memory,

well we all dream of electric sheep.

burs...@gmail.com

unread,
Jun 1, 2018, 7:30:17 AM6/1/18
to
The ISO core standard is a kind of text standard,
and not a binary standard. Its all based on text
streams, and not on binary streams.

Binary streams play a minor role, for only a few
test cases, like get_byte/[1,2], etc... But the
standard defines the notion of **Prolog text**:

From its glossary:

3.40 conforming Prolog data: Sequences of characters
and bytes that conform to all the compliance clauses for
ProZog data in this part of ISO/IEC 13211 (see 5, 6.2.2).

3.41 conforming Prolog text: A sequence of characters
that conforms to all the compliance clauses for Prolog text
in this part of ISO/IEC 13211 (see 5, 6.2).

burs...@gmail.com

unread,
Jun 1, 2018, 7:49:35 AM6/1/18
to
A binary standard, for clauses, something like
a Java bytecode for Prolog, would be not extremly
difficult. You could do it maybe on one page...

But the clauses would still need some compilation.
SWI-Prolog has a format, where the clauses are
already pre-compiled it seems.

Quick Load File
http://www.swi-prolog.org/pldoc/man?section=qlf

burs...@gmail.com

unread,
Jun 1, 2018, 7:53:07 AM6/1/18
to
So you plan DCG for your O-Prolog?
According to this question here:

About DCG ,CLP written in ISO-Prolog
https://groups.google.com/d/msg/comp.lang.prolog/4_2WRm2EXCQ/VgU3XHHdAgAJ

Can be also a can of worms... if you
dive into term/goal expansion.

burs...@gmail.com

unread,
Jun 1, 2018, 12:28:17 PM6/1/18
to
This tweet is an instance of the terminal suffix
skipping problem, this time in the case of an error,
and not in the case of the end of an input.

https://twitter.com/SSukimu/status/1002436466104885249

You get:
? X = ab.
<1. Error>
<2. Error>

Das it make sense to show furher errors, upon the
first syntax error? What do other systems do?

SWI-Prolog only 1 error:

Welcome to SWI-Prolog (threaded, 64 bits, version 7.7.1)
SWI-Prolog comes with ABSOLUTELY NO WARRANTY. This is free software.

?- op(1200, fx, ?-).
true.

?- [user].
? _ = ab.

ERROR: user://1:11:2: Syntax error: Operator expected
|: ?- _ = ab.
|:
true.


My system, the same, only 1 error:

Jekejeke Prolog 2, Runtime Library 1.2.6
(c) 1985-2018, XLOG Technologies GmbH, Switzerland

?- op(1200, fx, ?-).
Yes

?- [user].
? _ = ab.
Error: Superfluous token.
? _ = ab.
^

?- _ = ab.

How does this work? Well you can implement the
heristic, that a Prolog text is junked into
input lines up to the end period.

So you can just stop parsing upon an error,
and go to the end period, and thus avoid showing
multiple errors inside the same junk,

and even possibly parse parts of a junk, which
might give unexpected results. What if the junk
was the following:

:- write(halt).

And it got corrupted to:

:- write)halt .

Will your O-Prolog system execute halt?

burs...@gmail.com

unread,
Jun 1, 2018, 12:34:52 PM6/1/18
to
I don't know whether Ulrich Neumerkel has such a
test case on his conformance test list, or whether
ISO core standard would even define a behaviour,

after all its a error situation, and ISO leaves
undefined or even forbids if the Prolog system
doesn't leave table and doesn't runs away upon

the first error. Strict/Non-Strict? He could put
it as the last test, in case a Prolog system
really executes the halt.

burs...@gmail.com

unread,
Jun 1, 2018, 12:44:52 PM6/1/18
to
Strange, I cannot reproduce your two errors.

O-Prolog Ver0.90
| ? X = abc.
Syntax error expected one or two operand ['?']
| ?- X = abc.
X = abc
yes

Everything fine. Was the tweet from a pre-version
or does it have something to do with foreign glyphs?

Am Freitag, 1. Juni 2018 18:28:17 UTC+2 schrieb burs...@gmail.com:

burs...@gmail.com

unread,
Jun 1, 2018, 1:04:17 PM6/1/18
to
But I found this crash:

O-Prolog Ver0.90
| ?- time((between(1,10000,X), fail; true)).
Elapsed Time=0.015180 (second)
yes

| ?- time((between(1,100000,X), fail; true)).
Elapsed Time=0.140109 (second)
yes

| ?- time((between(1,1000000,X), fail; true)).
... does nothing for a while, and then exits interpreter ...

Compare with this expected behaviour:

Welcome to SWI-Prolog (threaded, 64 bits, version 7.7.14)
SWI-Prolog comes with ABSOLUTELY NO WARRANTY. This is free software.

?- time((between(1,10000,X), fail; true)).
% 10,003 inferences, 0.000 CPU in 0.000 seconds (?% CPU, Infinite Lips)
true.

?- time((between(1,100000,X), fail; true)).
% 100,001 inferences, 0.000 CPU in 0.000 seconds (?% CPU, Infinite Lips)
true.

?- time((between(1,1000000,X), fail; true)).
% 1,000,001 inferences, 0.047 CPU in 0.046 seconds (101% CPU, 21333355 Lips)
true.

Implementing between/3 can be tricky. Some problem
with 16-bit integers? Or then with bignums, if implemented
pure Prolog, you need to get a tailrecursive solution,

otherwise the call stack explodes, thats why my solution
uses the nasty if-then-else with cut. So that I have a
choice point first and then a tail recursion.

Not sure what my system does right now:

Jekejeke Prolog 2, Runtime Library 1.2.6
(c) 1985-2018, XLOG Technologies GmbH, Switzerland

?- use_module(library(advanced/arith)).
% 1 consults and 0 unloads in 0 ms.
Yes

?- time((between(1,10000,X), fail; true)).
% Up 29 ms, GC 0 ms, Thread Cpu 16 ms (Current 06/01/18 19:01:08)
Yes

?- time((between(1,100000,X), fail; true)).
% Up 98 ms, GC 0 ms, Thread Cpu 94 ms (Current 06/01/18 19:01:17)
Yes

?- time((between(1,1000000,X), fail; true)).
% Up 794 ms, GC 36 ms, Thread Cpu 734 ms (Current 06/01/18 19:02:14)
Yes

Well still in good shape, much slower than a
native between/3 of course.

burs...@gmail.com

unread,
Jun 1, 2018, 1:17:07 PM6/1/18
to
Since there are no conformance tests for bignum,
well here is a little test:

/* SWI-Prolog, Jekejeke Prolog */
?- X is 2^100, Y is 2^100+5, between(X,Y,Z), write(Z), nl, fail; true.
1267650600228229401496703205376
1267650600228229401496703205377
1267650600228229401496703205378
1267650600228229401496703205379
1267650600228229401496703205380
1267650600228229401496703205381
Yes

/* GNU-Prolog */
?- X is 2^100, Y is 2^100+5, between(X,Y,Z), write(Z), nl, fail; true.
0
1
2
3
4
5

Ha Ha, what says the ISO core standard about the
arithmetic operation (^)/2. Not much read yourself:

Only a float error was listed:
f) VX or VY is a float and the magnitude of VX
raised to the power of VY is too large
— evaluation_error(float_overflow).
https://www.complang.tuwien.ac.at/ulrich/iso-prolog/dtc2#pow

Here is another test case, SWI-Prolog does it nicely:

?- _ is 9^(9^9).
ERROR: Stack limit (1.0Gb) exceeded

My system still needs improvement:

?- _ is 9^(9^9).
/* hangs more or less, I dunno */

I see its busy with shuffling bignums:

"Thread-2" #21 prio=5 os_prio=0 tid=0x000000001b1b0800 nid=0x1a8 runnable [0x000000001c58d000]
java.lang.Thread.State: RUNNABLE
at java.math.BigInteger.shiftLeft(BigInteger.java:3073)
at java.math.BigInteger.multiplyToomCook3(BigInteger.java:1719)
at java.math.BigInteger.multiply(BigInteger.java:1512)
at java.math.BigInteger.multiplyToomCook3(BigInteger.java:1718)
at java.math.BigInteger.multiply(BigInteger.java:1512)
at java.math.BigInteger.multiplyToomCook3(BigInteger.java:1715)

burs...@gmail.com

unread,
Jun 1, 2018, 1:33:27 PM6/1/18
to
The ISO core standard says:

7.12 Integer
Note:
When bounded is false, expressions with an integer value
will not have a value int-Overflow, but might produce a resource
error (7. 12, 7.12.2 h) because of exhaustion of resources.

So common sense says there should be an int_overflow
for when bounded is true. So lets check GNU Prolog,
what does it give:

?- current_prolog_flag(bounded, X).
X = true

Section 9.1.3 shows that the integer operations
must provide overflow. Namely we have:

add_I(x, y) = x+y if x+y in I
= int_overflow if x+y not in I

Lets see what O-Prolog does:

O-Prolog Ver0.90
| ?- X is 2^100.
X = 1267650600228229401496703205376
yes
| ?- current_prolog_flag(bounded, X).
X = false
yes

Woa cool! But then:

| ?- X is 9^(9^9).
/* hangs, or takes very long, dunno yet */

Same problem like I have...

burs...@gmail.com

unread,
Jun 1, 2018, 2:17:48 PM6/1/18
to
Ok, you have to be patient, takes around a quater
of an hour, something like 16 minutes:

?- time((_ is 9^(9^9))).
% Up 974,318 ms, GC 9,302 ms, Thread Cpu 962,688 ms (Current 06/01/18 19:54:01)
Yes

But why does SWI-Prolog say the following:
?- _ is 9^(9^9).
ERROR: Stack limit (1.0Gb) exceeded

Isn't 9^(9^9) less than 1.0Gb,
at least I get:

log_256 9^(9^9) = (9^9) * log_256 9

= 153'511'736.76..

Thats only 154 MB(*). Does SWI-Prologs new
stack calculation not work?

(10^8) bytes = 100 megabytes

burs...@gmail.com

unread,
Jun 1, 2018, 2:19:33 PM6/1/18
to
Ok, was running with a 8 GB limit,
but it used only 3-4 GB:

?- statistics.
Max Memory 7,635,730,432 Bytes
Used Memory 765,913,440 Bytes
Free Memory 2,891,739,304 Bytes
Uptime 2,466,670 Millis
GC Time 9,315 Millis
Thread Cpu Time 963,812 Millis
Current Time 06/01/18 20:18:37
Yes

ken...@gmail.com

unread,
Jun 1, 2018, 9:56:36 PM6/1/18
to
Hi Burse.

Thanks for bug report.
I fixed.
On Windows, since the escape sequence does not sound, I used Windows API.

There seems to be a problem with my Ubuntu setting.
On my Ubuntu the Linux version does not sound.
I will ask a friend familiar with Linux.

else if(c == 'a')
#if _WIN32
MessageBeep(-1);
#elif __linux
printf("\a");
#endif

Kenichi Sasagawa

ken...@gmail.com

unread,
Jun 1, 2018, 10:24:09 PM6/1/18
to
Hi Burse.

I fixed it because the error message is difficult to understand.
This is the same as AZ-Prolog.

O-Prolog Ver1.00
| ? X = abc.
Syntax error
| ?- X = abc.
X = abc
yes
|

In the image of Tweet I just mistyped typing. There is no deep meaning.

Kenichi Sasagawa

ken...@gmail.com

unread,
Jun 1, 2018, 11:28:24 PM6/1/18
to
Hi Burse.

Thank you for bug report.

I fixed.

O-Prolog can not calculate 9^9^9 within practical time.
For this reason, when Y is greater than 10000 with X^Y, it is an error.
It also throws resource error.

resouce_error(exponentation)

O-Prolog Ver1.00
| ?- X is 9^10001.
Exponentiation of a too big integer is(X,9^10001)
| ?- X is 9^(9^9).
Exponentiation of a too big integer is(X,9^9^9)
|

Kenichi Sasagawa

ken...@gmail.com

unread,
Jun 1, 2018, 11:46:57 PM6/1/18
to
Hi Burse.

Thanks for the advice

I think it is stack overflow.
I will consider static analysis with a compiler and converting it into a loop.

Kenichi Sasagawa

ken...@gmail.com

unread,
Jun 2, 2018, 1:14:44 AM6/2/18
to
Hi Burse.

I improved between/3.

Thanks for the hint.

O-Prolog Ver1.00
| ?- time((between(1,10000,X), fail; true)).
Elapsed Time=0.001002 (second)
no
| ?- time((between(1,100000,X), fail; true)).
Elapsed Time=0.007553 (second)
no
| ?- time((between(1,1000000,X), fail; true)).
Elapsed Time=0.066175 (second)
no
| ?- time((between(1,10000000,X), fail; true)).
Elapsed Time=1.030740 (second)
no
|

Kenichi Sasagawa

ken...@gmail.com

unread,
Jun 2, 2018, 1:29:07 AM6/2/18
to
Hi Burse.

I found that there is a DCG code that Richard A. O'Keefe wrote.
If the code is ISO-Prolog compatible,
I would like to run it on O-Prolog.

Kneichi Sasagawa

Markus Triska

unread,
Jun 2, 2018, 4:21:46 AM6/2/18
to
ken...@gmail.com writes:

> O-Prolog can not calculate 9^9^9 within practical time.
> For this reason, when Y is greater than 10000 with X^Y, it is an error.

You can perform exponentiation by repeated _squaring_:

https://en.wikipedia.org/wiki/Exponentiation_by_squaring

I hope this helps to make your code faster!

All the best,
Markus

--
comp.lang.prolog FAQ: http://www.logic.at/prolog/faq/
The Power of Prolog: https://www.metalevel.at/prolog

Markus Triska

unread,
Jun 2, 2018, 4:24:30 AM6/2/18
to
Dear Kenichi,

ken...@gmail.com writes:

> If the code is ISO-Prolog compatible,
> I would like to run it on O-Prolog.

The latest draft for DCGs contains Prolog code you can use:

https://www.complang.tuwien.ac.at/ulrich/iso-prolog/#dcg

I hope this helps!

ken...@gmail.com

unread,
Jun 2, 2018, 4:45:58 AM6/2/18
to
Thank you.

Oh, I remembered. I have read that algorithm in the famous textbook SICP.

Kenichi Sasagawa

ken...@gmail.com

unread,
Jun 2, 2018, 4:48:14 AM6/2/18
to
Thank you.

That is what I was looking for.

Kenichi Sasagawa

Ulrich Neumerkel

unread,
Jun 2, 2018, 6:32:25 AM6/2/18
to
ken...@gmail.com writes:
>Hi Burse.
>
>Thank you for bug report.
>
>I fixed.
>
>O-Prolog can not calculate 9^9^9 within practical time.
>For this reason, when Y is greater than 10000 with X^Y, it is an error.
>It also throws resource error.
>
>resouce_error(exponentation)
>
>O-Prolog Ver1.00
>| ?- X is 9^10001.
>Exponentiation of a too big integer is(X,9^10001)
>| ?- X is 9^(9^9).
>Exponentiation of a too big integer is(X,9^9^9)

In general, try to avoid such limitations. It adds a lot of complexity
for maintenance. And there are, for one, several cases where
exponentiation is easy! Think of:

?- X is 1^7^7^7.

Same with -1 and 0. Also, 2^10001 is a relatively small number:
It even fits on a single screen.

There are some libraries that do all this with ease.

ken...@gmail.com

unread,
Jun 2, 2018, 6:44:37 AM6/2/18
to
Thanks for the advice.
I am improving the algorithm of powers.

Kenichi Sasagawa

ken...@gmail.com

unread,
Jun 2, 2018, 7:25:52 PM6/2/18
to
Dear Neumerkel.

I reconsidered on your advice.
I completely forgotten.
I adopted an efficient algorithm for the calculation of powers.
For this reason the following calculations were also possible at practical time even at ver0.90.
| ?- X is -1^10000000000000000.
X = 1
yes
| ?- X is -1^10000000000000001.
X = -1
yes

//x is cell address, y is integer of C
int expt(int x, int y){
int res,p;

res = makeint(1);
p = x;
while(y > 0){
if((y % 2) ==0){
p = mult(p,p);
y = y / 2;
}
else{
res = mult(res,p);
y = y -1;
}
}
return(res);
}

I decided to upgrade the limit upwards.
X^Y  X>10^19 X is integer and Y>10^19 Y is integer -> error

However, even if O-Prolog does not invoke an error,
O-Prolog may not be able to calculate in practical time.

Kenichi Sasagawa

burs...@gmail.com

unread,
Jun 2, 2018, 8:25:20 PM6/2/18
to
9^(9^9) takes around 16 minutes with java BigInteger.
How fast can GNU bignum do it?

java BigInteger uses Karatsuba and Toom–Cook, the
former has a nice story:

In 1960, Kolmogorov organized a seminar on mathematical
problems in cybernetics at the Moscow State University,
where he stated the Ω ( n 2 ) conjecture and other
problems in the complexity of computation. Within a
week, Karatsuba, then a 23-year-old student, found an
algorithm (later it was called "divide and conquer")
that multiplies two n-digit numbers in O ( n log 2 ⁡ 3 )
elementary steps, thus disproving the conjecture.

https://en.wikipedia.org/wiki/Anatoly_Karatsuba

ken...@gmail.com

unread,
Jun 2, 2018, 8:54:15 PM6/2/18
to
Hi Burse.

I was surprised that Chez-Scheme (Kent dybvig) do exponentiation at high speed before.
I also challenged a fast algorithm such as karatuba, but it did not work.
For me it was difficult to implement.
O-Prolog's bignum is a simple algorithm. I refered to Knuth's TAOCP for division.

Kenichi Sasagawa

burs...@gmail.com

unread,
Jun 2, 2018, 8:58:48 PM6/2/18
to
Its always nice to see a new Prolog with bignum.
I tried today K-Prolog, but it didn't have bignums.
At least 2<<100 didn't show something bignum.

So you say you implemented bignums, and you
implemented all on your own? Or did you use some
existing library, and let other people do the

work in implementing bignum?

j4n bur53

unread,
Jun 2, 2018, 9:00:57 PM6/2/18
to

K-Prolog ?? no bignums ??
L-Prolog
M-Prolog
N-Prolog
O-Prolog ?? bignums like ISO ??

Ha Ha

burs...@gmail.com schrieb:

ken...@gmail.com

unread,
Jun 2, 2018, 9:06:49 PM6/2/18
to
Dear Triska.

I added the '\+' operator to run that DCG code.
O-Prolog Ver1.00
| ?- \+ integer(1).
no
| ?- \+ integer(1.1).
yes
|

By the way, this operator seems to be excluded on page 5
of ISO-Prolog draft. What was the reason?

Kenichi Sasagawa

burs...@gmail.com

unread,
Jun 2, 2018, 9:09:37 PM6/2/18
to
Can you solve this classic one with O-Prolog?
How fast?

https://github.com/jburse/jekejeke-samples/blob/master/jekrun/benchmark/tests/crypt.p

Its not a bignum test. Its a small range integer
test. But if your system has bignum this can be
a problem, that the small range integers become

slow. Maybe this was a problem with between/2?
One way to represent small integers, is for example
to have tagged pointers.

+----+---------------+
|tag | pointer |
+----+---------------+

And then:

+----+---------------+
| 01 | smallint |
+----+---------------+

+----+---------------+ +------------------------------+
| 02 | bigmumadr |---->| bignumdata |
+----+---------------+ +------------------------------+

In Jekejeke Prolog, since its 100% pure Java, I
could not use tagged pointers. So I needed a few
other tricks. So the range -127 and 127 just

preallocated objects, with ordinary pointers.
For crypt the range -127 to 127 should more or less
do. So it can be done a little faster.

Ever tryed crypt?

ken...@gmail.com

unread,
Jun 2, 2018, 9:12:19 PM6/2/18
to
Hi Burse.

O-Prolog's bignum is all my own work.
I did not use the library.
I wanted to understand the calculation mechanism deeply.
For this I read Kunuth's book.

Kenichi Sasagawa

j4n bur53

unread,
Jun 2, 2018, 9:17:47 PM6/2/18
to
Its in the PDF you have:

8.15.1 (\+)/l - not provable ......................... 104
8.15.1.2 Template and modes
NOTE - \+ is a predefined infix operator (see 6.3.4.4).

Typo in standard, should read prefix operator.

900 fy \+
Table 7 - The Operator table

Here is a picture of the operator table:

https://github.com/jariazavalverde/tau-prolog/issues/10#issuecomment-392579092

ken...@gmail.com schrieb:

ken...@gmail.com

unread,
Jun 2, 2018, 9:24:05 PM6/2/18
to
Hi Burse.

Thank you.
I found it. I could solve the question.

Kenichi Sasagawa

j4n bur53

unread,
Jun 2, 2018, 9:25:18 PM6/2/18
to
DCG is based on the normal ISO core terms,
that you get via read_term. The DCG does only
a transformation. But it uses all operators that

are already defined. Even you find (-->)/2 already
in the ISO core standardd. All that DCG does
is a term expansion of clauses before they

are added. For example:

Welcome to SWI-Prolog (threaded, 64 bits, version 7.7.15)
SWI-Prolog comes with ABSOLUTELY NO WARRANTY. This is free software.

?- [user].
|: p --> [X,X]. /* this is a DCG input */

?- listing(p/2).
p([A, A|B], B). /* this is the expanded DCG that was added */

You can query this expansion anytime:

Welcome to SWI-Prolog (threaded, 64 bits, version 7.7.15)
SWI-Prolog comes with ABSOLUTELY NO WARRANTY. This is free software.

?- expand_term((p-->[X,X]), Y).
Y = (p([X, X|_2372], _2372):-true).

The expansion can also involve (\+)/1:

Welcome to SWI-Prolog (threaded, 64 bits, version 7.7.15)
SWI-Prolog comes with ABSOLUTELY NO WARRANTY. This is free software.

?- expand_term((p--> \+q), Y).
Y = (p(_2322, _2344):- \+q(_2322, _2420), _2344=_2322).

This expansion is stupid. It doesn't use QNames. So if
your Prolog system would have a module system, and if you
would somewhere defined (\+)/1 the DCG would be really able

to recognize that, and probably treat it as his own (\+)/1...

Ha Ha,

its only a stupid term transformation...

j4n bur53 schrieb:

j4n bur53

unread,
Jun 2, 2018, 9:30:13 PM6/2/18
to
Actually I havent seen so many use cases where a
Prolog system, in a module would redefine (',')/2,
(';')/2, (->)/2, etc.. how should it continue to run?

But maybe, it could (\+)/1 redefined somewhere,
even the syntax operator for it. SICStus Prolog and
SWI-Prolog have a limited solution for such

problems, their term expansion searches first in
the current module that is consulted. But is only
of limited value. It doesn't solve the QName problem,

although, as illustrated, especially for (',')/2,
the QName problem is not so severe. There might be
other cases where a real ambiguity is produced...

j4n bur53 schrieb:

j4n bur53

unread,
Jun 2, 2018, 9:32:09 PM6/2/18
to
Corr.:
would somewhere defined (\+)/1 the DCG wouldn't be really able
to recognize that, and probably treat it as his own (\+)/1...

Some prolog systems might have some meta predicate annotation,
that would possibly mingle something, but I didn't see that

used for the DCG transformer yet.. Also the DCG draft shows
a transformation that is not module aware...

j4n bur53 schrieb:

j4n bur53

unread,
Jun 2, 2018, 9:36:17 PM6/2/18
to
And not line mumber or file name aware. In case you store
some line number or file name information with your clause,
for goal break points in a debugger etc.. etc...,

how do you do that after DCG transform? What happens with
such extra information? Each Prolog system has a different
solution. In case you are at the point

of such problems, you might then have like 1 million
more questions, than you already have. Somehow developing
a Prolog system

is like: ‘The journey is the destination’

You will be almost never finished...

j4n bur53 schrieb:

ken...@gmail.com

unread,
Jun 4, 2018, 7:24:36 AM6/4/18
to
Hi Burse.

I am improving the parser. please advice me.
You taught me that it will be as follows.

O-Prolog Ver1.00
| ?- X = [(a :- b)].
X = [(a:-b)]
yes
| ?- X = [a :- b].
Syntax error expected ( ) a:-b
| ?- X = [a * b].
X = [a*b]
yes
|

I am looking for that basis in ISO/IEC 13211-1.
But I can not find it. Where is the description written?

Kenichi Sasagaawa

Ulrich Neumerkel

unread,
Jun 4, 2018, 7:57:14 AM6/4/18
to
ken...@gmail.com writes:
>O-Prolog Ver1.00
>| ?- X = [(a :- b)].
>X = [(a:-b)]
>yes
>| ?- X = [a :- b].
>Syntax error expected ( ) a:-b
>| ?- X = [a * b].
>X = [a*b]
>yes
>|
>
>I am looking for that basis in ISO/IEC 13211-1.
>But I can not find it. Where is the description written?

For the syntax of lists, see 6.3.5. There, the actual arguments
are represented by a non-terminal arg (* 6.3.3.1 *)

arg = atom ;
Abstract: a a
Condition: a is an operator

arg = term ;
Abstract: a a
Priority: 999


So either the argument is an atom which is an operator, like [:-],
or the argument is a term with fitting priority. Therefore, [a*b]
is fine, and [a :- b] is not.

And then for writing:

http://www.complang.tuwien.ac.at/ulrich/iso-prolog/draft-7.10.5.html

ken...@gmail.com

unread,
Jun 4, 2018, 8:10:21 AM6/4/18
to
Thank you very much.
I understand.

Kenichi Sasagawa

burs...@gmail.com

unread,
Jun 5, 2018, 8:06:54 AM6/5/18
to
Hi Ken,

Did you implement body conversion for O-Prolog. Body
conversion is defined in the ISO core standard. It can
be easiest illustrated by this example:

Welcome to SWI-Prolog (threaded, 64 bits, version 7.7.15)
SWI-Prolog comes with ABSOLUTELY NO WARRANTY. This is free software.

?- [user].
|: p :- q(X), X.
|:
% user://1 compiled 0.00 sec, 1 clauses
true.

?- listing(p/0).
p :-
q(A),
call(A).

But on O-Prolog I currently find:

O-Prolog Ver0.90
| p :- q(X), X.
| :- listing.
p :- q(X),X[p,',',q(X),X].

Is this only a pretty printing problem?
It should show the same as SWI-Prolog, except
you are of course allowed to show the right

variable names. Here is what my Prolog system does:

Jekejeke Prolog 2, Runtime Library 1.2.6
(c) 1985-2018, XLOG Technologies GmbH, Switzerland

?- [user].
p :- q(X), X.
Yes

?- listing.
% user
p :-
q(X),
call(X).

Among my currently 1146 test cases, there are
also test cases for such things. Mostly found in the
testing packages control (165 test cases) and
the testing packages consult (134 test cases).

See also:
http://www.jekejeke.ch/idatab/doclet/prod/en/docs/10_dev/15_stdy/07_compliance/06_summary.html

The test cases are mostly from the ISO core standard,
document itself. A typical one is:

:- dynamic legs/2.
legs(A, 7) :- A,
call(A).

runner:case(clause, 2, consult_data, 'ISO 8.8.1.4, ISO 4') :-
clause(legs(C, 7), Body),
Body == (call(C),call(C)).

burs...@gmail.com

unread,
Jun 5, 2018, 8:21:44 AM6/5/18
to
Tau Prolog is also victim of this problem:
https://github.com/jariazavalverde/tau-prolog/issues/16

j4n bur53

unread,
Jun 5, 2018, 8:25:15 AM6/5/18
to
If you follow the Tau Prolog issue #16 link, you see
a screenshot of the following desired ISO Prolog
core standard behaviour:

GNU Prolog 1.4.4 (64 bits)
Compiled Apr 23 2013, 16:05:07 with cl
By Daniel Diaz
Copyright (C) 1999-2013 Daniel Diaz
| ?- assertz((legs(C,7) :- C, call(C))).

yes
| ?- clause(legs(C,7),Body).

Body = (call(C),call(C))

yes
| ?-

I did not yet test this with O-Prolog. But
I guess raising awareness of such ISO core standard
Prolog specifics early on could be of advantage.

burs...@gmail.com schrieb:

j4n bur53

unread,
Jun 5, 2018, 8:43:41 AM6/5/18
to
Probably its only a pretty printing problem
in O-Prolog. Because this quite challenging
test case works for O-Prolog:

O-Prolog Ver0.90
| p(!).
|
q :- p(X), X.
|
r :- p(X), X, fail.
| r.
|
?- q.
yes
|
?- r.
yes

On the other hand Tau Prolog refuses to answer it:
https://github.com/jariazavalverde/tau-prolog/issues/17

j4n bur53 schrieb:

ken...@gmail.com

unread,
Jun 5, 2018, 8:48:25 AM6/5/18
to
Hi Burse.

Thank you for your bug report.
I Fixed.

O-Prolog Ver 1.00
| p :- q(X), X.
| :- listing.
p :- q(X),X.

ken...@gmail.com

unread,
Jun 5, 2018, 8:59:37 AM6/5/18
to
O-Prolog ver0.90 has more bugs than I expected. I plan to upgrade in this month.

Kenichi Sasagawa

ken...@gmail.com

unread,
Jun 6, 2018, 4:14:48 AM6/6/18
to
Hi burse.

Please help me. I am looking for the open/3 /4 encoding/1 option you were writing. Where is it written in ISO/IEC13211-1?

Kenichi Sasagawa

burs...@gmail.com

unread,
Jun 6, 2018, 4:50:11 AM6/6/18
to
I didn't say the stream option encoding/1 is in ISO
core standard. I gave links to SWI-Prolog and SICStus
Prolog, that one can provide encoding/1 (bom/1 and
buffer/1 come also to mind) stream options in a

Prolog system. You only find in the ISO core standard:

ISO/IEC 13211-1 First edition 1995-06-01
7.10.2.11 Options on stream creation - Page 57
A processor may support one or more additional
Options as an implementation specific feature.

The only minimal stream options documented
by the ISO core standard are type/1, reposition/1,
alias/1, eof_action/1. Whereby Jekejeke Prolog
even doesn't implement eof_action/1 as a creation

option. In Jekejeke Prolog the terminal can produce
multiple EOF interleaved with text (like reset?), while
ordinary streams only produce text and then EOF
forever (like eof-code?). Exceptions need to be

thrown on the application level in Java, when dealing
with streams. At least this is the case for most of
the basic streams, not sure how coders react. But my
ScannerToken and PrologReader don't do an over peeking,

so they don't read past EOF. Otherwise the terminal
would not function, and you could not do the following:

Jekejeke Prolog 2, Runtime Library 1.2.6
(c) 1985-2018, XLOG Technologies GmbH, Switzerland

?- [user]
foo
^D /* <--- this is an EOF input, CTRL-D */

?- foo
Yes

If your O-Prolog console would use some eof_action(reset)
stream, you could also provide such a user interface, instead
of the (?-)/1 directive. Although the (?-)/1 is very original
invention, its slightly confusing when somebody is used

to the other mode, implemented by most Prolog systems. The
other mode is based on the availability of eof_action(reset)
streams. That the input and output are such streams is
seen in a table of the ISO core standard.

Table 40: Properties of standard streams.
Table 40 defines the properties of the Standard streams.

But since I want to keep the number of aliases low,
I am also not compatible here. The current result is:

Jekejeke Prolog 2, Runtime Library 1.2.6
(c) 1985-2018, XLOG Technologies GmbH, Switzerland

?- stream_property(user_output, X).
Error: No such stream alias user_output.
stream_property/2

?- current_output(X), stream_property(X,Y), write(Y), nl, fail; true.
reposition(false)
file_name() /* according to table 40, ISO core, I should show that */
mode(write) /* according to table 40, ISO core, it should read append */
buffer(4096) /* implementation specific */
bom(false) /* implementation specific */
encoding(UTF-16) /* implementation specific */
output
type(text)
Yes
/* according to table 40, ISO core, alias is missing */
/* according to table 40, ISO core, eof_action is missing */

burs...@gmail.com

unread,
Jun 6, 2018, 5:09:53 AM6/6/18
to
Corr.:

file_name() /* according to table 40, ISO core, I shouldn't show that */

burs...@gmail.com

unread,
Jun 6, 2018, 5:23:17 AM6/6/18
to
Some more explorations, not directly related to
encoding/1, more the eof_action/1 thingy:

The Java API for text/EOF interleaved results is very
simple. The InputStream and Reader have both a read()
method which can return -1.

So this terminal input:

A B C EOF D E F

Would give:

97 98 99 -1 101 102

But to simplify matters, to prevent errorneous EOF
by the end-user, I only allow EOF on a new empty line.
So basically what is possible in my terminal, is the following:

A B C \n EOF D E F \n

Which would then give:

97 98 99 10 -1 101 102 10

But the use of value 10 for new line here is implementation
dependent, you find in the ISO core standard:

6.5.4 Layout characters layout char
new line char (* 6.5.4 *)
= implementation dependent ;

But you cannot really query the character by some Prolog
flag. And this here is not very convincing:

?- char_code('\n', X).
X = 10

What if you want to write the scanner/parser in Prolog
itself, and have this as a parameter somewhere?

I wonder whether a HTTP keep alive connection, can
also provide interleaved text/EOF?

ken...@gmail.com

unread,
Jun 6, 2018, 5:31:47 AM6/6/18
to
Thank you.
It is very helpful.

Kenichi Sasagawa

Ulrich Neumerkel

unread,
Jun 6, 2018, 5:39:16 AM6/6/18
to
ken...@gmail.com writes:
>O-Prolog ver0.90 has more bugs than I expected. I plan to upgrade in this month.

Please consider to kaizen. Thus, issue 0.91 rapidly. Then 0.92
...

ken...@gmail.com

unread,
Jun 6, 2018, 5:53:08 AM6/6/18
to
Thank you very much.

Kenichi Sasagawa

Ulrich Neumerkel

unread,
Jun 6, 2018, 9:12:56 AM6/6/18
to
And for errors, maybe read

http://www.complang.tuwien.ac.at/ulrich/iso-prolog/error_k

which shows you a bit how errors are viewed in ISO.

burs...@gmail.com

unread,
Jun 6, 2018, 10:17:12 AM6/6/18
to
Looks like the other side of kaizen! Ha Ha

>20 names, >30 suggestions for a simple error

not(instantiation_error)

its more an example of standards comittee
masturbation, and a total waste of money.

was this an exercise in non-productivity?

j4n bur53

unread,
Jun 6, 2018, 10:24:13 AM6/6/18
to
Hi,

Very famous, if there 1 birthday per year,
there are 364 not(birthday) per year:

Alice in Wonderland Mad Tea Party
https://www.youtube.com/watch?v=msvOUUgv6m8

I guess a not(birthday) error message
would have 364 proposals as well? You could
take the name of saints. Don't you have

a better reference for error terms, its
admittingly amusing, but also very distracting.
Not a real document.

Bye

burs...@gmail.com schrieb:

burs...@gmail.com

unread,
Jun 6, 2018, 10:46:58 AM6/6/18
to
The error, the uninstantiation_error, was consived
for a situation like:

/* without a check by open/3 you loose a file handle */
?- open('foo', read, bar).

But that is the same idea, like an error here:

?- length([a,b,c], -1).

A FFI (Foreign Function Interface) predicate with
a return value in the last argument. I don't bother
throwing this error in Jekejeke Prolog:

Jekejeke Prolog 2, Runtime Library 1.2.7
(c) 1985-2018, XLOG Technologies GmbH, Switzerland

?- open('foo', read, bar).
No

Thats just additional burden that slows down
a Prolog interpreter, and of absolutely no use.
No modern system will have a vulnerability

because of that. In Java, if you don't use
a stream handle, it partly goes away when the
GC removes it. The underlying file handle

will go away through an exit(). The suggested
error by ISO core doesn't guarantee at all
that this situation might not also happen otherwise:

/* you also loose a file handle also here */
?- open('foo', read, _).

You cant help this situation, that you loose
a file handle. It happens here:

Jekejeke Prolog 2, Runtime Library 1.2.7
(c) 1985-2018, XLOG Technologies GmbH, Switzerland

?- open('foo', read, _).
Yes

And it happens also for SWI-Prolog:

Welcome to SWI-Prolog (threaded, 64 bits, version 7.7.15)
SWI-Prolog comes with ABSOLUTELY NO WARRANTY. This is free software.

?- open('foo', read, _).
true.

So why bother with a situation, that can anyway
not completely be solved by some local predicate
call extra argument tests?

I guess its for the Tea Party:

Alice in Wonderland Mad Tea Party
https://www.youtube.com/watch?v=msvOUUgv6m8

Ulrich Neumerkel

unread,
Jun 6, 2018, 11:25:41 AM6/6/18
to
burs...@gmail.com writes:
>The error, the uninstantiation_error, was consived
>for a situation like:
>
> /* without a check by open/3 you loose a file handle */
> ?- open('foo', read, bar).
>
>But that is the same idea, like an error here:
>
> ?- length([a,b,c], -1).

Even if the term fits, this should be an error. Like:

?- open(f, read, S), open(f, read, S).

So neither a domain_error nor a type_error fits.

>No modern system will have a vulnerability because of that.

The uninstantiation_error has nothing to do with
vulnerabilities.

burs...@gmail.com

unread,
Jun 6, 2018, 11:38:20 AM6/6/18
to
Surprise, Surprise!

I don't implement such errors. They are plain nonsense.
ECLiPSe Prolog also doesn't implement it:

ECLiPSe Constraint Logic Programming System [kernel threads]
Version 7.0 #36 (x86_64_nt), Sun Jan 28 10:18 2018
[eclipse 1]: open('C:\\Users\\Jan Burse\\Desktop\\ss\\userlist.html',
read, foo).

Yes (0.00s cpu)
[eclipse 2]:

Actually I don't know what it does? A bug? Why doesn't
it fail. Did it assign an alias, some new semantics?

Not the nonsense from Tea Party? Ha Ha. Did it slip your
attention that ECLiPSe Prolog implemented something new.

I have different reasons. The reasons are very simple:

Most of my built-ins are defined via FFI. The
FFI gets simpler and more efficient, if it doesn't
check the type of method results.

These method results land in the last argument of
a predicate, and are simply passed via unification,
which can fail or succeeds. No error is possible.

But I don't know why ECLiPSe does what it does,
here is screenshot if you don't believe me:

Funny open/3 behaviour of ECLiPSe 7.0:
https://gist.github.com/jburse/2a7762893e2213daba1b22de01566a16#gistcomment-2612035

burs...@gmail.com

unread,
Jun 6, 2018, 11:47:26 AM6/6/18
to
You don't get the ECLiPSe behaviour in SWI-Prolog
or GNU Prolog, both implement the Tea Party error:

Welcome to SWI-Prolog (threaded, 64 bits, version 7.7.15)
SWI-Prolog comes with ABSOLUTELY NO WARRANTY. This is free software.

?- open('C:\\Users\\Jan Burse\\Desktop\\ss\\userlist.html', read, foo).
ERROR: Uninstantiated argument expected, found foo (stream-argument)

And GNU-Prolog:

GNU Prolog 1.4.4 (64 bits)
Copyright (C) 1999-2013 Daniel Diaz

?- open('C:\\Users\\Jan Burse\\Desktop\\ss\\userlist.html', read, foo).
uncaught exception: error(uninstantiation_error(foo),open/3)

burs...@gmail.com

unread,
Jun 6, 2018, 6:14:16 PM6/6/18
to
If you throw an error in this situation:

?- open(f, read, S), open(f, read, S).

But you don't throw an error in this situation:

?- open(f, read, S), open(f, read, T), S = T.

Then you broke steadfastness.

Richard O'Keefe, 2009:
"As the inventor of the term "steadfast" in Prolog programming,
I ought to be in favour of it. Steadfastness basically
means that you cannot force a predicate down the wrong path
by filling in output arguments wrongly."
http://blog.gmane.org/gmane.comp.ai.prolog.swi/month=20090301

Not that Richard O'Keefe explicitly talks about
output arguments. I guess he does it for the
one of the list arguments in DCG translation. Google
gives me foremost this:
https://stackoverflow.com/q/13100364/502187

So there is now a schizophrenic situation:

- There are trends against steadfastness, like
length([a,b,c],-1), and other built-ins and
library predicates
- On the other hand it is important for DCG
- I can imagine a situation where the two
come together.

Yesterday I tried to find a scenario where something
like length([a,b,c],-1) is used inside DCG,
and things break if the thingy would not be
steadfast.

But so far I didn't find an example, I didn't search
for too long. Maybe I find an example. Generally
I think everything more steadfastness, is a little
bit more Prolog-ish.

But this includes only failure and no errors. For
an output argument, which is supposed to be steadfast,
the following two should be equivalent:

P(T) <=> p(X), X = T

It is interesting that steadfastness even in
the light of CLP(X) is not anymore promoted. In
the light of CLP(X) there would be this CLP-steadfastness:

p(T) <=> X #= T, p(X)

Disclaimer: I just do some brainwriting right
now. To show that two worlds exist. One world
with steadfastness, and the other

world with errors.

Am Mittwoch, 6. Juni 2018 17:25:41 UTC+2 schrieb Ulrich Neumerkel:

j4n bur53

unread,
Jun 6, 2018, 6:19:43 PM6/6/18
to
BTW: Recently, upon programming more steadfast
predicates. Possibly not in the best way, but just
to make my routines "safe" without throwing

errors on output arguments, I adopted a new Prolog
programming style. So mostly I don't do anymore:

p(...,f(...)) :- !,
...

If f(...) is an output result. You can easily
force wrong paths. I more and more do the following
which looks like Erlang a little bit:

p(...,X) :- !,
..., X = f(...).,

Interestingly the code doesn't get slower.
Its even the other way around. Since the head
of the clause is not bothered with too much

unification, and input argument unification, or
some conditions before the cut, can still
fail, the second code variant is actually

more efficient.

burs...@gmail.com schrieb:

ken...@gmail.com

unread,
Jun 6, 2018, 10:10:04 PM6/6/18
to
Hi Burse.

Thank you for your advice.
Now,I am reading p87~ of the standards that I got from you.
When I made ver0.90, I did not have detailed material.
I referred to the 1993 draft. So ver0.90 was very rough.
I will rebuild to conform to the standards.
The open function of C language library can not detect duplicate open of file. For this reason, I need a mechanism to memorize the opened file name.
I am going to modify the data structure of the stream.

Kenichi Sasagawa

Ulrich Neumerkel

unread,
Jun 7, 2018, 2:59:39 AM6/7/18
to
ken...@gmail.com writes:
>Now,I am reading p87~ of the standards that I got from you.

Please note that on p.87, there is 8.11.5.3 Errors f, which
has been replaced in Cor.2 by an uninstanitation error!

http://www.complang.tuwien.ac.at/ulrich/iso-prolog/dtc2#uninstantiation_error

Thus:

f) Stream is not a variable
- uninstantiation_error(Stream).

>The open function of C language library can not detect duplicate open of file. For this reason, I need a mechanism to memorize the opened file name.
>I am going to modify the data structure of the stream.

There is no need to do so. It's really the programmer's responsibility, if a file
is opened for writing more than once at the same time.

ken...@gmail.com

unread,
Jun 7, 2018, 4:16:28 AM6/7/18
to
> There is no need to do so. It's really the programmer's responsibility, if a file
> is opened for writing more than once at the same time.

Thank you very much. I understand.

I'm fixing.


Kenichi Sasagawa

----
O-Prolog Ver 1.00
| ?- catch(open(F,read,S),error(E1,E2),true).
E1 = instantation_error(F)
E2 = open
yes
| ?- catch(open(f,M,S),error(E1,E2),true).
E1 = instantation_error(M)
E2 = open
yes
| ?- catch(open(f,read,S,[1|2]),error(E1,E2),true).
E1 = type_error(list,[1|2])
E2 = open
yes
| ?- catch(open(f,read,S,[type(text),G]),error(E1,E2),true).
E1 = instantation_error(G)
E2 = open
yes
| ?- catch(open(f,"123",S,[type(text)]),error(E1,E2),true).
E1 = type_error(atom,['1','2','3'])
E2 = open
yes
| ?- catch(open(f,read,S,1),error(E1,E2),true).
E1 = type_error(list,1)
E2 = open
yes
| ?- catch(open(f,read,s,[]),error(E1,E2),true).
E1 = type_error(variable,s)
E2 = open
yes
| ?- catch(open(f,read,S,[]),error(E1,E2),true).
E1 = existence_error(source_sink,f)
E2 = open
yes
| ?- catch(open('test.pl',read,S,[alias(abc)]),error(E1,E2),true).
S = <stream1357>

yes
| ?- catch(open('test.pl',read,S,[alias(abc)]),error(E1,E2),true).
E1 = permission_error(open,source_link,alias(abc))
E2 = open
yes
| ?- open('test.pl',read,S),open('test.pl',read,T),S=T.
no
|



ken...@gmail.com

unread,
Jun 7, 2018, 4:22:17 AM6/7/18
to
> Thus:
>
> f) Stream is not a variable
> - uninstantiation_error(Stream).

Is it OK?

Kenichi Sasagawa

O-Prolog Ver 1.00
| ?- catch(open(f,read,s,[]),error(E1,E2),true).
E1 = uninstantation_error(s)
E2 = open
yes
|

Ulrich Neumerkel

unread,
Jun 7, 2018, 4:26:52 AM6/7/18
to
Perfect. For E2, the value is implementation defined. So it is
up to you, but maybe open/4 is preferable in place of open.

ken...@gmail.com

unread,
Jun 7, 2018, 4:30:46 AM6/7/18
to
> Perfect. For E2, the value is implementation defined. So it is
> up to you, but maybe open/4 is preferable in place of open.

I appreciate your advice. Thank you very much.
I will fix it further.

Kenichi Sasagawa

burs...@gmail.com

unread,
Jun 7, 2018, 6:09:28 AM6/7/18
to
The file_name is really a problem since stream
property wants to show it. Which is on the other
hand good for error messages while consulting
a stream.

But the alias, which is not the file_name, but
a possibly user given name, you can code in pure
Prolog itself. Do you have these already?

dynamic/1 directive
assertz/1 predicate
asserta/1 predicate
retract/1 predicate

Like here:

sys_put_alias(Alias, _) :-
sys_alias(Alias, _), !,
throw(error(permission_error(open,source_sink,alias(Alias)),_)).
sys_put_alias(Alias, Stream) :-
assertz(sys_alias(Alias, Stream)).

https://github.com/jburse/jekejeke-devel/blob/master/jekrun/headless/jekpro/frequent/stream/stream.p#L244

But the above code doesn't work in multi-threading.
There can be a race condition, that you
have suddently two sys_alias/2 entries.

Do you have multi-threading? In unix etc..
createFile() should not have a race condintion
problem, but this is file_name.

But for alias how to do it in Prolog? One
solution would be to put the test and
assert into a mutex.

One nice addition is this here:

with_mutex(+MutexId, :Goal)
Execute Goal while holding MutexId.
http://www.swi-prolog.org/pldoc/man?predicate=with_mutex/2

burs...@gmail.com

unread,
Jun 7, 2018, 6:23:11 AM6/7/18
to
with_mutex/2 can be under the hood implemented
with a few primitives, among this one is the
hardest but the most useful:

setup_call_cleanup/3
https://www.complang.tuwien.ac.at/ulrich/iso-prolog/cleanup

Do you plan setup_call_cleanup/3? Its also
very useful for file opening and closing. Were
simple errors can happen while processing

a file, you might think about catch/throw.
But this doesn't work for backtracking file
reading and result producing type code.

Like:

get_lines(Y) :-
open('foo', read, S),
repeat,
read_line(S, X)
(X == end_of_file -> !, close(S), fail; Y = X).

What if you do:

?- get_lines(Y), !.

The file will not be closed. So you need
setup_call_cleanup/3. Since it also blocks
signals and can unrawel all the time,

You find it in production all over
the place, like in SWI-Prolog:

76 code results in SWI-Prolog/swipl-devel
https://github.com/SWI-Prolog/swipl-devel/search?q=setup_call_cleanup

burs...@gmail.com

unread,
Jun 7, 2018, 6:36:13 AM6/7/18
to
setup_call_cleanup/3 is already useful in a single
threaded Prolog system, or a Prolog system that
runs in single threaded mode.

For multi-threading with_mutex/2 comes into
play. It has also its own use cases. I also
find it in production code:

19 code results in SWI-Prolog/swipl-devel
https://github.com/SWI-Prolog/swipl-devel/search?q=with_mutex

I am happy that I did not yet provide to much
mutex code. I have a programming exercise to
code your own mutexes here:

Ha Tschi
http://jekejeke.ch/idatab/doclet/prod/en/docs/05_run/10_docu/03_interface/04_examples/06_mutex.html

But because I just now, introduced hiearchical
knowledge bases, with their own root namespaces,
I would need to rethink named mutexes.

I think what already works is the following:
Each sub knowledge base has its own alias name
space for file handles.

So two sub knowledge bases can both use the same
alias(test) for example without harm, since dynamic
predicates have now a thread group local scope,

see also my other post Pengins and Pintegration.
I will probably release hierarchical knowledge bases
tomorrow or after tomorrow, but do not yet

add more for mutex. Maybe provide a solution for
the file alias only. Not yet sure how to proceed
with a possible feature of a mutex namespace,

distributed over hierarchical knowledgebases.

ken...@gmail.com

unread,
Jun 7, 2018, 7:58:18 AM6/7/18
to
> Prolog itself. Do you have these already?
>
> dynamic/1 directive
> assertz/1 predicate
> asserta/1 predicate
> retract/1 predicate

I implemented them on ver0.90, but the conformance is incomplete.


> Do you have multi-threading? In unix etc..
>

I am interested in parallel calculation by Prolog.
I am attracted by GHC (Guarded Horn Clauses).
https://ja.wikipedia.org/wiki/Guarded_Horn_Clauses
I dreaming of implementing parallel machines and implementing GHC someday at Raspi3 cluster machine.


Kenichi Sasagawa

ken...@gmail.com

unread,
Jun 7, 2018, 8:07:01 AM6/7/18
to
I am interested in Mr. Hideyuki Nakashima's multiple world system. It is realized in Prolog/KR.This is dynamic hierarchical knowledgebases.
https://ci.nii.ac.jp/naid/500000255362


Kenichi Sasagawa

burs...@gmail.com

unread,
Jun 7, 2018, 8:08:12 AM6/7/18
to
You use some compiler and environment already,
does it already support some synchronization
primities on that level? Like threads and monitors?

If you have threads and monitors, you could
bootstrap a parallel Prolog from them. For
example SWI-Prolog uses POSIX threads/emulation:

"SWI-Prolog multithreading is based on the
POSIX thread standard Butenhof, 1997 used on
most popular systems except for MS-Windows. On
Windows it uses the pthread-win32 emulation of
POSIX threads mixed with the Windows native
API for smoother and faster operation."
http://www.swi-prolog.org/man/threads.html

But SWI-Prolog also writes: The SWI-Prolog thread
implementation has been discussed in the ISO WG17
working group and is largely addopted by YAP
and XSB Prolog.

But then there is footnote 164: The latest version
of the ISO draft can be found at http://logtalk.org/plstd/threads.pdf.
It appears to have dropped from the ISO WG17 agenda.

burs...@gmail.com

unread,
Jun 7, 2018, 8:17:00 AM6/7/18
to
Logtalk threads paper, shows how object that are
anyway present underneath, could be made accessible
via some Prolog API.

These objects are:
- mutex
- queue
- thread

My experience the queue object is a little extra,
it doesn't appear in my Prolog implementation
so far itself. But I also provide it for the

end-user, because nice things can be done with
them. So far they are queues inside a silo, inside
a thread group, they are not queues for service

commounication outside of a silo. So they are
nice for some parallel programming inside a device.
But not for distributed programming to go outside

of a device. My variant of the API, and the underlying
implementation is all open source:

Mutex object (called Lock) is here:
Queue object (called Pipe) is here:
https://github.com/jburse/jekejeke-devel/tree/master/jekrun/headless/jekpro/frequent/misc

Thread object is here:
https://github.com/jburse/jekejeke-devel/tree/master/jekrun/headless/jekpro/frequent/system

burs...@gmail.com

unread,
Jun 7, 2018, 8:27:35 AM6/7/18
to
To make a raspery pi cluster, you would possibly
need some communication primitives that are not
the thread queues or extend the thread queues in
some way.

SWI-Prolog is currently working on some UDP
communication, some paxos protocol, etc.., all
kind of fancy stuff, which I would say

fits a little bit this direction. Some stuff
is inspired by Erlang. Which doesn't mean that
Erlang invented it.

Paxos lecture (Raft user study)
https://www.youtube.com/watch?v=JEpsBg0AO6o

burs...@gmail.com

unread,
Jun 13, 2018, 1:27:08 PM6/13/18
to
Hi Ken,

Do you plan to support absolute_file_name/[2,3] in your
Prolog system? You can use it do do something along:

open(...) :-
absolute_file_name(...),
internal_open(...)

But again I find a lot of differences about the different
Prolog system. Most interesting is the name "user", what
should absolute_file_name/[2,3] do with it?

I somehow agree with this behaviour of SWI-Prolog:

?- absolute_file_name(user, X, [access(read)]).
ERROR: source_sink `user' does not exist

?- absolute_file_name(user, X, [access(write)]).
X = 'c:/users/jan burse/documents/prolog/user'.

But the above behaviour is not widespread, GNU-Prolog does:

| ?- absolute_file_name(user, X).
X = user

YAP Prolog does:

?- absolute_file_name(user, X, [access(read)]).
X = user_input

?- absolute_file_name(user, X, [access(write)]).
X = user_input

Somehow SICStus Prolog has recognized the problem, and introduced
a new absolute file option:

if_user(Val) since release 4.3
controls how to resolve the special file name user.
Val is one of the following:
file
Treat the name user like any other name, e.g. like
open/3 does. This is the default.
user
Unifies AbsFileName with the atom user and ignores
the other options. This corresponds to the behavior
prior to SICStus Prolog 4.3.
error
Treat the name user as a non-existing file, subject
to the file_errors/1 option.

https://sicstus.sics.se/sicstus/docs/4.3.1/html/sicstus/mpg_002dref_002dabsolute_005ffile_005fname.html


Am Freitag, 1. Juni 2018 08:47:30 UTC+2 schrieb ken...@gmail.com:
> Dear everyone
>
> Today, I updated to O-Prolog ver 0.90.
> http://eisl.kan-be.com/library/oprolog1.html
> I appreciate having received many advice.
> I think O-Prolog still has many nonconformities.
> I would be pleased if you give me some advice.
>
> Kenichi Sasagawa

burs...@gmail.com

unread,
Jun 13, 2018, 1:41:48 PM6/13/18
to
I am working again on absolute_file_name/[2,3], since I
want to find a way to address some well known sources in
my system. The problem is that with hierarchical knowledge

bases, I now have multitude of "user" source. For example
the parent has a "user" and the child has a "user". Same
problem with "system". But I guess I can help myself in

that I view "user" or "system" as context dependent aliases,
which internally have longer names in each hierarchy level,
working on it...

burs...@gmail.com

unread,
Jun 13, 2018, 3:27:47 PM6/13/18
to
Ok, first things first, {} syntax:

Maybe {} still needs a little improvement?
I see O-Prolog:
?- X = {}(1,2).
X = {1,2}

But then GNU-Prolog:
?- X = {}(1,2).
X = {}(1,2)

?- X = {}(1,2), Y = {1,2}, X = Y.
no

Maybe your parsing in O-Prolog has to do, that you
do not always priorize atom directly followed by
lpar as leading to compound.

But that is one of the rules of Prolog. You see it
here in this example:

GNU Prolog 1.4.4 (64 bits)
Compiled Apr 23 2013, 16:05:07 with cl

?- X = + (1,2), write_canonical(X), nl.
+(','(1,2))

yes
?- X = +(1,2), write_canonical(X), nl.
+(1,2)
Surprise, Surprise. Somehow the matter got also
broken in Tau Prolog, as I just see:
https://github.com/jariazavalverde/tau-prolog/issues/22

burs...@gmail.com

unread,
Jun 13, 2018, 3:31:38 PM6/13/18
to
The relevant ISO core standard syntax clause is the following.
This assures that write_canonical can always be read back:

```
6.3.3 Compound terms - functional notation

term = atom, open ct, arg list, close
```
It uses the "open ct" non-terminal and not the "open" non-terminal. The
"open ct" non-terminal is without layout text sequence in front. So it says
basically atom directly followed by left parenthesis should give compound.

burs...@gmail.com

unread,
Jun 13, 2018, 3:37:35 PM6/13/18
to
This can be quite challenging for a Scanner and Parser
to digest. Either you effectively introduce two different
tokens "open ct" and "open", where the Scanner gives you

already enough information, whether there was some
layout text sequence or not. You find some sample
Prolog code that does that on the internet.

Or you use a little peeking trick as is done here:

if (st.lookAhead() == OP_LPAREN.codePointAt(0)) {
nextToken();
nextToken();
skel = readCompound(help);

https://github.com/jburse/jekejeke-devel/blob/master/jekrun/headless/jekpro/model/pretty/PrologReader.java#L339

The peeking via lookAhead() looks directly after the
current token. So if after the current token, there would
by some layout text sequence, the test would be false.

The test gets true if atom directly followed by lpar.

burs...@gmail.com

unread,
Jun 14, 2018, 4:42:19 AM6/14/18
to
BTW: It can be quite rewarding to invest into
parsing of {}/1, and maybe also unparsing of it.
The following Prolog extensions make use of {}/1:

- Definite Clause Grammars (DCG), its used to
wrap aux code, i.e. plain prolog that is
neither grammar terminal nor grammar non-terminal,
in as far its very important:

7.14.7 {}//1 – grammar-body-goal
https://www.complang.tuwien.ac.at/ulrich/iso-prolog/dcgs/

- Logtalk uses {}/1 in two places, you can
use it for plain calls, and you can also wrap
the receiver with it.

receiver ::=
"{" callable "}" |
object_identifier |
variable

external_call ::=
"{" callable "}"

https://logtalk.org/manuals/refman/grammar.html#grammar_entity_identifiers

- Ha Ha, I started using it as external represetantion
of array types in Jekejeke Prolog. So the internal
Java array type 'int[]', is externally represented as {int}.
The idea is that it visually resembles the EBNF repeat.

There is some native code that handles this case,
but also plain code, even using the rather rarely
used ISO sub_atom/5 for some processing:

sys_path_to_atom(A, B):
https://github.com/jburse/jekejeke-devel/blob/master/jekrun/headless/jekpro/reference/bootload/path.p#L400

burs...@gmail.com

unread,
Jun 14, 2018, 4:47:59 AM6/14/18
to
You got atom_length/2, atom_concat/3 and
sub_atom/5 all working already in O-Prolog?
sub_atom/5 can be a little tedious to provide...

P.S.: The syntax where I use
{}/1 is formally defined here:

Predicate Definitions
http://www.jekejeke.ch/idatab/doclet/prod/en/docs/05_run/10_docu/02_reference/07_theories/06_reflect/01_predicates.html

A qualified call {int}:new(7,X) will ask Java
from within Prolog for a new primitive integer
array of length 7, which will be returned as
a reference type.

burs...@gmail.com

unread,
Jun 14, 2018, 5:33:16 AM6/14/18
to
The tedious ISO core standard sub_atom/5 seems to
be missing, or has a bug, at least in version 0.90:

O-Prolog Ver0.90
| ?- atom_length('abc', X).
X = 3
yes
| ?- atom_concat('abc', 'def', X).
X = abcdef
yes
| ?- sub_atom('abdefc', X, Y, Z, 'def').
no

Tau Prolog can already do it, cool:

?- sub_atom('abdefc', X, Y, Z, 'def').
X = 2, Y = 3, Z = 1 ;

?- atom_concat('abc', 'def', X).
X = abcdef.

?- atom_length('abc', X).
X = 3.

ken...@gmail.com

unread,
Jun 14, 2018, 6:13:44 AM6/14/18
to
Hi Burse.

Thanks for the bug report.
I improved the parser.
Especially the distinction between + (1,2) and +(1, 2) was a difficult problem for me.
I learned a lot from the advice from you.
I am currently correcting as many bugs as possible.
I will update OPL ver1.00 on 30th June.
Please wait.

Kenichi Sasagawa

O-Prolog Ver 1.00
| ?- X = {}(1,2), Y = {1,2}, X = Y.
no
| ?- X = {}(1,2).
X = {}(1,2)
yes
| ?- Y = {1,2}.
Y = {1,2}
yes
| ?- Y = {1,2,{3,4},5}.
Y = {1,2,{3,4},5}
yes
| ?- X = + (1,2), write_canonical(X), nl.
+(','(1,2))
X = +(1,2)
yes
| ?- X = +(1,2), write_canonical(X), nl.
+(1,2)
X = 1+2
yes
|

ken...@gmail.com

unread,
Jun 14, 2018, 6:30:40 AM6/14/18
to
Hi Burse

OPL ver 0.90 was very incomplete.
I am fixing many bugs.
These improvements are easier than improvement of parser.
I will improve as long as time permits.
I plan to update it to ver1.00 on 30th June.

Thank you.

Kenichi Sasagawa

janb...@easel.ch

unread,
Jun 14, 2018, 8:19:53 PM6/14/18
to
Hi Ken,

I forgot SWI-Prolog has a further use of {},
namely its used for dict, with a space rule similar
that is foud in compounds:

?- X = person{name:123}.
X = person{name:123}.

?- X = person {name:123}.
ERROR: Syntax error: Operator expected
ERROR: X = person
ERROR: ** here **
ERROR: {name:123} .

Bye

Ulrich Neumerkel

unread,
Jun 15, 2018, 2:43:07 AM6/15/18
to
ken...@gmail.com writes:
> the distinction between + (1,2) and +(1, 2) was a difficult problem for me.
...
> | ?- X = + (1,2), write_canonical(X), nl.
> +(','(1,2))
> X = +(1,2)
^^
You are missing a space here! Thus

X = + (1,2)

So writeq/1 needs improvement.

ken...@gmail.com

unread,
Jun 15, 2018, 7:20:04 AM6/15/18
to
Thank you for your advice.
Fixed.

Kenichi Sasagawa

O-Prolog Ver 1.00
| ?- X = +(1,2),write_canonical(X),nl.
+(1,2)
X = 1+2
yes
| ?- X = + (1,2),write_canonical(X),nl.
+(','(1,2))
X = + (1,2)
yes

ken...@gmail.com

unread,
Jun 15, 2018, 7:26:56 AM6/15/18
to
> You got atom_length/2, atom_concat/3 and
> sub_atom/5 all working already in O-Prolog?
> sub_atom/5 can be a little tedious to provide...

Thank you for reporting the bug.
Fixed.


Kenichi Sasagawa

O-Prolog Ver 1.00
| ?- atom_concat(T,' world','small world').
T = small
yes
| ?- atom_concat(T1, T2,hello).
T1 = ''
T2 = hello;
T1 = h
T2 = ello;
T1 = he
T2 = llo;
T1 = hel
T2 = lo;
T1 = hell
T2 = o;
T1 = hello
T2 = '';
no
| ?- sub_atom(ab,Start,Length,_,Sub_atom).
Start = 0
Length = 0
Sub_atom = '';
Start = 0
Length = 1
Sub_atom = a;
Start = 0
Length = 2
Sub_atom = ab;
Start = 1
Length = 0
Sub_atom = '';
Start = 1
Length = 1
Sub_atom = b;
Start = 2
Length = 0
Sub_atom = '';
no
|

burs...@gmail.com

unread,
Jun 16, 2018, 12:06:36 PM6/16/18
to
Hi Ken,

Ok, I found how to do absolute_file_name/2 in ECLiPSe Prolog,
its in the library(quintus). It seems that the default is

access(write), and there is only absolute_file_name/2, but
there is no absolute_file_name/3 in the said library.

But watchout what it does with the caseing:

ECLiPSe Constraint Logic Programming System [kernel threads]
Version 7.0 #36 (x86_64_nt), Sun Jan 28 10:18 2018

[eclipse 1]: use_module(library(quintus)).

[eclipse 2]: absolute_file_name('FooBar', X).
X = '//C/Users/Jan Burse/Documents/FooBar'

http://eclipseclp.org/doc/bips/lib/quintus/index.html

On the other hand here the casing gets changed:

Welcome to SWI-Prolog (threaded, 64 bits, version 7.7.15)
SWI-Prolog comes with ABSOLUTELY NO WARRANTY. This is free software.

?- absolute_file_name('FooBar', X).
X = 'c:/users/jan burse/documents/prolog/foobar'.

Bye

j4n bur53

unread,
Jun 16, 2018, 12:42:05 PM6/16/18
to
Hi Ken,

In case you deliver files with your O-Prolog in the future.
Can be quite a can of worms. The down casing can cause
a problem, see here:

Logtalk : Load a file with camelcase naming on Windows
https://stackoverflow.com/q/33387111/502187

Here are some suggestion as how the problem can be mitigated
by some semantics for absolute_file_name/3:

access(write):
Name is taken as is.
access(read):
Attempt is made to find a file, and the canonical
name of this file is resolved and returned.

Canonical name can have different semantics. It can or cannot
follow soft links etc.. Maybe the third argument of
absolute_file_name/3 might override the defaults applied

in canonization. Here is an example, assume with have
these two files in the directory:

C:/Users/Jan Burse/Documents/FooBar1.pl

C:/Users/Jan Burse/Documents/foobar2.pl

Here is what absolute_file_name/3 could deliver:

Jekejeke Prolog 3, Runtime Library 1.3.0
(c) 1985-2018, XLOG Technologies GmbH, Switzerland

?- set_prolog_flag(base_url, 'C:\\Users\\Jan Burse\\Documents').

?- absolute_file_name('foobar1', X, [access(read)]).
X = 'file:/C:/Users/Jan Burse/Documents/FooBar1.pl'

?- absolute_file_name('foobar2', X, [access(read)]).
X = 'file:/C:/Users/Jan Burse/Documents/foobar2.pl'

?- absolute_file_name('foobar3', X, [access(read)]).
Error: File foobar3 not found.

What we now have in SWI-Prolog is the following:

Welcome to SWI-Prolog (threaded, 64 bits, version 7.7.15)
SWI-Prolog comes with ABSOLUTELY NO WARRANTY.

?- working_directory(_, 'C:\\Users\\Jan Burse\\Documents\\').
true.

?- absolute_file_name('foobar1', X, [access(read),
extensions(['.pl'])]).
X = 'c:/users/jan burse/documents/foobar1.pl'.

?- absolute_file_name('foobar2', X, [acc ess(read),
extensions(['.pl'])]).
X = 'c:/users/jan burse/documents/foobar2.pl'.

?- absolute_file_name('foobar3', X, [access(read),
extensions(['.pl'])]).
ERROR: source_sink `foobar3' does not exist

I guess both solutions can be made to work somehow, with
a module system and other stuff.

burs...@gmail.com schrieb:
It is loading more messages.
0 new messages