Closed tavmem closed 4 years ago
$ cat dop.k
dop_:{
l:5=4:x;r:5=4:y
if[~l|r;:+[x]y];if[l&~r;:@[x;_n;_f[;y]]];if[r&~l;:@[y;_n;_f[x]]]
a:!x;b:!y;i:a@&a _lin b; j: a _dvl i;k:b _dvl i;
@[@[@[x;i;:;_f'[x i;y i]];j;_f[;0]];k;:;_f[0]'y k]}
a:.+(`a`b;1 2)
b:.+(`b`c;3 4)
dop_[a;b]
$
$
$
$ rlwrap -n ./k dop
K 2.8 2000-10-10 Copyright (C) 1993-2000 Kx Systems
\ for help. \\ to exit.
.((`a;1;)
(`b;5;)
(`c;4;))
This is a regression. It works in the commit 762f5267d4b17dbeda63036620cdaad513e84556 of March 24, 2018, titled "better fix for #491: pointer dereference" and is broken beginning with the commit efb970744d59af34228cf5125b9ce8fe8fd5b689 of March 25, 2018 titled "fix #506: execute"
Well, not exactly. It does not crash is the commit 762f5267d4b17dbeda63036620cdaad513e84556 of March 24, 2018, but it does not yield the correct result either:
$ rlwrap -n ./k dop
.((`a;;)
(`b;;)
(`c;;))
It does crash in (and after) the commit efb970744d59af34228cf5125b9ce8fe8fd5b689 of March 25, 2018.
Upon closer inspection, this may not have ever worked properly.
The crash occurs on line 250 of src/v.c in function K at_ref(K *p, K b, K c, K y)
else if(4==ABS(bt))
{
P(5!=pt && 6!=pt,TE)
DO(atomI(b)?1:n,
K args=newK(0,argc);U(args)//Cheating 0-type w/ NULLs
S u = kS(b)[i%bn];
if(!strlen(u))R DOE;
kK(args)[0]= ci(*lookupEVOrCreate(p,u)); // ... mm/o? tricky
if(argc > 1) kK(args)[1] = atomI(b)?ci(y):itemAtIndex(y,i%yn); //line 250
K r = specialAmendDot(c,args);
M(r,args)
K *v = EVP(DE(*p,u));
cd(*v);
*v=r;
cd(args);
)
}
The relevant data items involved are:
argc: 2
sd(b): 0x7f7d35056440 0x7f7d35056458 7-6 -4 1 ,`b
atomI(b): 0
sd(y): 0x7f7d35052480 0x7f7d35052498 4-7 7 0
i: 0 yn: 0
Floating point exception (core dumped)
The exception occurs because 0 is divided by 0.
The problem may be with function I atomI(K a){R a->t>0?1:0;}
While it is true that its type is -4, it only has 1 element, and is argueably an atom.
Here is a difference It may (or may not) be relevant.
K 2.8 2000-10-10 Copyright (C) 1993-2000 Kx Systems
\ for help. \\ to exit.
a: .+(`a`b;1 2)
b: .+(`b`c;3 4)
i: ,`b
a i
,2
b i
,3
$ rlwrap -n ./k
kona \ for help. \\ to exit.
a: .+(`a`b;1 2)
b: .+(`b`c;3 4)
i: ,`b
a i
2
b i
3
I plan to open this as a separate issue and fix it. Then see if the current issue still crashes.
After fixing issue #560, this issue no longer crashes ... but it does not give the correct result, either:
$ rlwrap -n ./k dop_
kona \ for help. \\ to exit.
.((`a;;)
(`b;;)
(`c;;))
The problem is identified ... but not fixed. If a local variable "t" is inserted in the 1st if-statement of the 2nd line of dop we get the correct result. The revised dop is:
dop_:{
l:5=4:x;r:5=4:y
if[~l|r;:t:+[x]y];if[l&~r;:@[x;_n;_f[;y]]];if[r&~l;:@[y;_n;_f[x]]]
a:!x;b:!y;i:a@&a _lin b; j: a _dvl i;k:b _dvl i;
@[@[@[x;i;:;_f'[x i;y i]];j;_f[;0]];k;:;_f[0]'y k]}
a:.+(`a`b;1 2)
b:.+(`b`c;3 4)
dop_[a;b]
Running this yields:
kona \ for help. \\ to exit.
.((`a;1;)
(`b;5;)
(`c;4;))
The local variable "t" should not be necessary. There is some kind of "shadowing" going on in the statement
@[x;i;:;_f'[x i;y i]]
where one copy of the dictionary x is being updated, but not subsequently used.
This exercise has also identified another new issue. After running the above:
\v
`dop_ `x `y `a `b
x
y
x and y are local variables and should not be added to the symbol table as global variables. Their contents is null (which is good).
The correct result can be gotten w/o using an extra local variable "t". It also works 2 other ways:
:x+y
instead of :+[x]y
:(+[x]y)
instead of :+[x]y
For some reason, the phrase :+[x]y
is not handled properly (yet).
Some simple test cases:
kona \ for help. \\ to exit.
fa:{:x+y}
fa[2;3]
5
fb:{:(+[x]y)}
fb[2;3]
5
fc:{:+[x]y}
fc[2;3]
_n~fc[2;3]
0
fa
and fb
work fine.
fc
does not work.
fc
yields no apparent response.
It is not null.
d:fa[2;3]
#d
1
d:fc[2;3]
#d
#_n
1
So, if it is not "null", what is the output? If you make the following 2 changes to the codebase:
$ git diff
diff --git a/src/kc.c b/src/kc.c
index a659909..0d1f9f8 100644
--- a/src/kc.c
+++ b/src/kc.c
@@ -256,7 +256,7 @@ I line(FILE*f, S*a, I*n, PDA*p) { //just starting or just executed: *a=*n=*p=0,
if(o&&k)O("Elapsed: %.7f\n",d);
#endif
- if(o && fam && !feci)show(k);
+ if(o && fam && !feci)sd_(k,2);
cd(k);
cleanup:
diff --git a/src/kc.h b/src/kc.h
index d7902c3..0710b1a 100644
--- a/src/kc.h
+++ b/src/kc.h
@@ -1,5 +1,6 @@
void init_genrand64(unsigned long long seed);
extern I SEED;
+extern K sd_(K x,I f);
V alloc(size_t sz);
K _dot_t();
K newE(S s,K k);
$
Then, you get:
$ rlwrap -n ./k
kona \ for help. \\ to exit.
f:{:+[y]x}
f [2;3]
0x7f18260b8380 0x7f18260b8398 2-7 7 0
a0: 0x7f18260b8398 .k
a1: 0x7f18260b83a0 (nil)
a2: 0x7f18260b83a8 0x7f18260b7340 0x7f18260b7358 1-6 -4 2 0x16
(nil)
a3: 0x7f18260b83b0 0x7f18260b72c0 0x7f18260b72d8 1-6 5 0
.()
a4: 0x7f18260b83b8 0x7f18260b7300 0x7f18260b7318 1-6 5 0
.()
a5: 0x7f18260b83c0 0x7f18260b8400 0x7f18260b8418 1-7 7 0
b0: 0x7f18260b8418 .k
b1: 0x7f18260b8420 (nil)
b2: 0x7f18260b8428 0x7f18260b7480 0x7f18260b7498 1-6 -4 2 ` (nil)
.2b[0]: 0x7f18260e6ee0
b3: 0x7f18260b8430 0x7f18260b73c0 0x7f18260b73d8 1-6 5 0
.()
b4: 0x7f18260b8438 0x7f18260b7400 0x7f18260b7418 1-6 5 0
.()
b5: 0x7f18260b8440
b6: 0x7f18260b8448
b7: 0x7f18260b8450
a6: 0x7f18260b83c8
a7: 0x7f18260b83d0
The output is a k-structure of type 7-0 (an unexecuted structure). The wiki (Data and Execution) tells us that the 2nd member is the code section. The code section (a2) has 2 elements of type 4 From src/k.c you can find that 0x16 is "dyadic plus" The second element is just a terminator for the code string (nil).
{0, 0, 0,0,{0}}, // 0x10
{0, 0, 0,0,{0}},
{0, 0, 0,0,{0}},
{0, 0, 0,0,{0}},
{0, 0, 0,0,{0}},
{0, 1, flip,"+",{0}},
{0, 2, plus,"+",{plus_over,plus_scan}}, //0x16
{0, 1, negate,"-",{0}},
{0, 2, minus,"-",{0,0,minus_eachpair}},
{0, 1, first,"*",{0}},
{0, 2, times,"*",{times_over}},
{0, 1, reciprocal,"%%",{0}},
{0, 2, divide,"%%",{0}},
{0, 1, reverse,"|",{0}},
{0, 2, max_or,"|",{max_or_over}},
{0, 1, where,"&",{0}},
{0, 2, min_and,"&",{min_and_over}}, // 0x20
I'm a bit surprised that "cache_wd" (a5) also contains a type 7-0 k-structure. It also has a 2 element code member (b2).
Even simpler test cases:
$ rlwrap -n ./k
kona \ for help. \\ to exit.
:+[2]3
+[2]3
5
:2+3
5
:(+[2]3)
5
Here is another problem (which hopefully gets fixed as a side effect of fixing the current issue):
$ rlwrap -n ./k
kona \ for help. \\ to exit.
:2
2
:+2
:
Actually, this last example may provide the "key" to the problem. The "result" that is produced is:
result: 0x7ffdbdeeeaa8 0x7fc127201080 0x7fc127201098 1-7 7 1 :
a0: 0x7fc127201098 .k
a1: 0x7fc1272010a0 (nil)
a2: 0x7fc1272010a8 0x7fc12722b800 0x7fc12722b818 1-6 -4 2 0x3c
(nil)
.2a[0]: 0x3c
a3: 0x7fc1272010b0 0x7fc12722b600 0x7fc12722b618 1-6 5 0
.()
a4: 0x7fc1272010b8 0x7fc12722b6c0 0x7fc12722b6d8 1-6 5 0
.()
a5: 0x7fc1272010c0
a6: 0x7fc1272010c8
a7: 0x7fc1272010d0
From src/k.c
{0, 2, what,"?",{0}}, // 0x30
{0, 1, floor_verb,"_",{0}},
{0, 2, drop_cut,"_",{0}},
{0, 1, enlist,",",{0}},
{0, 2, join,",",{join_over}},
{0, 1, count,"#",{0}},
{0, 2, take_reshape,"#",{0}},
{0, 1, format,"$",{0}},
{0, 2, dollar,"$",{0}},
{0, 1, dot_monadic,".",{0}},
{0, 2, dot,".",{0}},
{0, 1, colon_monadic,":",{0}},
{0, 2, colon_dyadic,":",{0}}, // 0x3c
{0, 1, _0m,"0:",{0}},
{0, 2, _0d,"0:",{0}},
{0, 1, _1m,"1:",{0}},
{0, 2, _1d,"1:",{0}}, // 0x40
The colon is being translated by the parser to 0x3c which is colon dyadic, instead of 0x7d (which is "return")
{0, 2, _dvl,"_dvl",{0}}, // 0x70
{0, 2, _hat,"_hat",{0}},
{0, 2, _in,"_in",{0}},
{0, 2, _lin,"_lin",{0}},
{0, 2, _lsq,"_lsq",{0}},
{0, 2, _mul,"_mul",{0}},
{0, 2, _setenv,"_setenv",{0}},
{0, 2, _sm,"_sm",{0}},
{0, 2, _ss,"_ss",{0}},
{0, 2, _sv,"_sv",{0}},
{0, 2, _vs,"_vs",{0}},
{0, 3, _ssr,"_ssr",{0}},
{0, 1, tr_st," \\",{0}}, //trace_stop
{0, 1, rtrn,":",{0}}, //return 0x7d
The strange thing is that the colon is being translated to 0x3c in the cases that work, as well as in the cases that fail. It is sort of interesting that any of the cases yield the correct result !
After the commit 9419b171e1c9e349a131d426979296af70f844ec made on Nov 9, 2019:
kona \ for help. \\ to exit.
:+[2]3
5
:+2
2
However, we still have:
$ rlwrap -n ./k dop_
kona \ for help. \\ to exit.
.((`a;;)
(`b;;)
(`c;;))
There must still be something else wrong.
Some simple examples of what's working ... and what's not:
kona \ for help. \\ to exit.
:+[2]3
5
:+5
5
f:{ if[x;:+[x]y]; y }; f[0;3]
3
f:{ if[x;:+[x]y]; y }; f[2;3]
f:{ if[x;:x+y]; y }; f[2;3]
5
f:{ if[x;:(+[x]y)]; y }; f[2;3]
5
This issue was identified by adam.antonik@gmail.com