kevinlawler / kona

Open-source implementation of the K programming language
ISC License
1.36k stars 138 forks source link

Dictionaries and Symbolic Indexing #571

Closed tavmem closed 4 years ago

tavmem commented 4 years ago

Regular indexing of a dictionary (as described on page 96 of the k 2.0 reference manual) works:

kona      \ for help. \\ to exit.

  c: .((`a;1 2 3);(`b;"2+3";.,(`c;`button)))
  c.a
1 2 3
  c.b
"2+3"
  c.b..c
`button

However, symbolic indexing (described on page 91) fails:

kona      \ for help. \\ to exit.

  dir: .((`a;2 3 4);(`b; "abcdefg"))
  `dir .`b
rank error
`dir .`b
     ^
>

In k2.8

K 2.8 2000-10-10 Copyright (C) 1993-2000 Kx Systems
\ for help. \\ to exit.

  dir: .((`a;2 3 4);(`b; "abcdefg"))
  `dir .`b 
"abcdefg"
tavmem commented 4 years ago

First ... check whether this is a regression.

I does not appear to be. Using a commit from Jun 23, 2011

$ rlwrap -n ./k
K Console - Enter \ for help
  dir: .((`a;2 3 4);(`b; "abcdefg"))
.((`a
   2 3 4
   )
  (`b
   "abcdefg"
   ))
  `dir .`b
type error

Using a commit from Dec 12, 2012

$ rlwrap -n ./k
K Console - Enter \ for help
  dir: .((`a;2 3 4);(`b; "abcdefg"))
.((`a
   2 3 4
   )
  (`b
   "abcdefg"
   ))
  `dir .`b
type error

Using a commit from Dec 31, 2013

$ rlwrap -n ./k
K Console - Enter \ for help
  dir: .((`a;2 3 4);(`b; "abcdefg"))
.((`a
   2 3 4
   )
  (`b
   "abcdefg"
   ))
  `dir .`b
type error

Using a commit from Dec 30, 2014

$ rlwrap -n ./k
K Console - Enter \ for help

  dir: .((`a;2 3 4);(`b; "abcdefg"))
.((`a
   2 3 4
   )
  (`b
   "abcdefg"
   ))
  `dir .`b
type error
`dir .`b
     ^
> 

Using a commit from Dec 16, 2015

$ rlwrap -n ./k
K Console - Enter \ for help

  dir: .((`a;2 3 4);(`b; "abcdefg"))
.((`a
   2 3 4
   )
  (`b
   "abcdefg"
   ))
  `dir .`b
rank error
`dir .`b
     ^
> 

Using a commit from Jun 30, 2016

$ rlwrap -n ./k
K Console - Enter \ for help

  dir: .((`a;2 3 4);(`b; "abcdefg"))
.((`a
   2 3 4
   )
  (`b
   "abcdefg"
   ))
  `dir .`b
rank error
`dir .`b
     ^
>

Using a commit from Dec 12, 2017

$ rlwrap -n ./k
K Console - Enter \ for help

  dir: .((`a;2 3 4);(`b; "abcdefg"))
  `dir .`b
rank error
`dir .`b
     ^
> 

Using a commit from May 22, 2018

$ rlwrap -n ./k
kona      \ for help. \\ to exit.

  dir: .((`a;2 3 4);(`b; "abcdefg"))
  `dir .`b
rank error
`dir .`b
     ^
>

Using a commit from Nov 20, 2019

$ rlwrap -n ./k
kona      \ for help. \\ to exit.

  dir: .((`a;2 3 4);(`b; "abcdefg"))
  `dir .`b
rank error
`dir .`b
     ^
>

Using the latest commit of Jan 8, 2020

$ rlwrap -n ./k
kona      \ for help. \\ to exit.

  dir: .((`a;2 3 4);(`b; "abcdefg"))
  `dir .`b
rank error
`dir .`b
     ^
> 
tavmem commented 4 years ago

Next ... simplify as much as possible In k2.8

$ rlwrap -n ./k
K 2.8 2000-10-10 Copyright (C) 1993-2000 Kx Systems
\ for help. \\ to exit.

  d:.((`a;0);(`b;1))
  `d .`b
1

In kona

$ rlwrap -n ./k
kona      \ for help. \\ to exit.

  d:.((`a;0);(`b;1))
  `d .`b
rank error
`d .`b
   ^
>
tavmem commented 4 years ago

This is interesting: If you add the following line to the codebase ...

$ git diff
diff --git a/src/kx.c b/src/kx.c
index f39bfaf..3698f39 100644
--- a/src/kx.c
+++ b/src/kx.c
@@ -591,6 +591,7 @@ Z V ex_(V a, I r)   //Expand wd()->7-0 types, expand and evaluate brackets.   Co

 K ex(K a)   //Input is (usually, but not always) 7-0 type from wd()
 { U(a);
+  O("sd_(a,2):");sd_(a,2);O("\n");
   if(a->t==7 && kVC(a)>(K)DT_SIZE && 7==kVC(a)->t && 6==kVC(a)->n) fwh=1;
   if(a->t==7)
   { if(prnt==0)

... you get a display of the single parameter a that is passed from the parser module to the execution module. In the case of regular indexing, we get

  d.b
sd_(a,2):     0x7feecb1f2000 0x7feecb1f2018            1-7 7 0   
     a0:    0x7feecb1f2018     .k
     a1:    0x7feecb1f2020     (nil)
     a2:    0x7feecb1f2028     0x7feecb21d840 0x7feecb21d858            1-6 -4 2   ` (nil)  
     .2a[0]: 0x7feecb1f13a0     0x7feecb1f1400 0x7feecb1f1418            1-6 1 1   1
     a3:    0x7feecb1f2030     0x7feecb21d600 0x7feecb21d618            1-6 5 0   
.()
     a4:    0x7feecb1f2038     0x7feecb21d880 0x7feecb21d898            1-6 5 0   
.()
     a5:    0x7feecb1f2040     
     a6:    0x7feecb1f2048     
     a7:    0x7feecb1f2050     

1

a2: is the code to be executed. It has 2 elements (one with content and then the terminating nil). The one with content is listed at .2a[0] and is the final result: 1. In other words the parser did both the parsing and the execution.

In the case of symbolic indexing, we get

  `d .`b
sd_(a,2):     0x7f7d5ff64080 0x7f7d5ff64098            1-7 7 0   
     a0:    0x7f7d5ff64098     .k
     a1:    0x7f7d5ff640a0     (nil)
     a2:    0x7f7d5ff640a8     0x7f7d5ff8ff00 0x7f7d5ff8ff18            1-6 -4 4   `"@��_}" 0x3a ` (nil)  
     .2a[0]: 0x7f7d5ff8f820     0x7f7d5ff8f840 0x7f7d5ff8f858 0x1cf3500  1-6 4 1   `d
     .2a[1]: 0x3a
     .2a[2]: 0x7f7d5ff8f9a0     0x7f7d5ff8f900 0x7f7d5ff8f918 0x1cf3540  1-6 4 1   `b
     a3:    0x7f7d5ff640b0     0x7f7d5ff8f640 0x7f7d5ff8f658            1-6 5 2   
.((`;`d;)
  (`;`b;))
 0x7f7d5ff8f660     0x7f7d5ff8f800 0x7f7d5ff8f818            1-6 0 3   
(`;`d;)
 0x7f7d5ff8f828     0x7f7d5ff8f9c0 0x7f7d5ff8f9d8 0x1cf0290  1-6 4 1   `
 0x7f7d5ff8f820     0x7f7d5ff8f840 0x7f7d5ff8f858 0x1cf3500  1-6 4 1   `d
 0x7f7d5ff8f818     0x7f7d5ff8f040 0x7f7d5ff8f058            8-6 6 0   
 0x7f7d5ff8f658     0x7f7d5ff8f980 0x7f7d5ff8f998            1-6 0 3   
(`;`b;)
 0x7f7d5ff8f9a8     0x7f7d5ff8f940 0x7f7d5ff8f958 0x1cf0290  1-6 4 1   `
 0x7f7d5ff8f9a0     0x7f7d5ff8f900 0x7f7d5ff8f918 0x1cf3540  1-6 4 1   `b
 0x7f7d5ff8f998     0x7f7d5ff8f040 0x7f7d5ff8f058            8-6 6 0   
     a4:    0x7f7d5ff640b8     0x7f7d5ff8f600 0x7f7d5ff8f618            1-6 5 0   
.()
     a5:    0x7f7d5ff640c0     
     a6:    0x7f7d5ff640c8     
     a7:    0x7f7d5ff640d0     

rank error
`d .`b
   ^
> 

The "code" has 4 elements, 3 with content. The first is `d The second is 0x3a which references this line in the dispatch table: {0, 2, dot,".",{0}}, The third is `b

The parser did only the parsing.

tavmem commented 4 years ago

We have 2 options:

tavmem commented 4 years ago

In regular indexing d.b is parsed as a name. The parser denames it and uses the associated value. Hence, the parser is able to provide the final result.

In symbolic indexing `d and `b are parsed as symbols.

To get symbolic indexing to work, we need to get the execution module to to handle the parsed result correctly.

tavmem commented 4 years ago

Although this line raises the "rank error" in the function K of(K a, K b) in src/vd.c

$ git diff
diff --git a/src/vd.c b/src/vd.c
index b35a4db..f136067 100644
--- a/src/vd.c
+++ b/src/vd.c
@@ -76,7 +76,7 @@ K of(K a, K b)  //TODO: oom all (see of2() for M(z,kK(z)[i]=...) pattern )
     R of(*aa,b);
   }

-  P(0<at && at<5 && 6!=bt,RE)
+  P(0<at && at<5 && 6!=bt,RE)     // This line raises the rank error.
   //At is either <=0 or dict or nil. b is not ()
   if(6==at)
   { // _n . x  for various x in K3.2

it may be better to modify the function

K dot(K a, K b) //NB: b can be a cheating 0-type with NULLs .. ?
{
  //TODO: create dename without path-creation effect. will lookup correct handle or return a _n to use ... but won't create path. K at() also needs this.
  //if(4==a->t)a=retrieveByHandle(a);

  if(7==a->t) R vf_ex(&a,b); //Verb: "Apply" //TODO: my guess is this fails everywhere vf_ex does (derived verbs?) (|+) . (0;1) ???
  R of(a,b); //TODO: vf_ex might/could implement this itself ?
}

which calls K of(K a, K b).