nushell icon indicating copy to clipboard operation
nushell copied to clipboard

Parsing of table literal as an argument is inconsistent

Open ErichDonGubler opened this issue 1 year ago • 3 comments

Describe the bug

It appears that parsing of the header form of table literals is incorrect for at least the table argument of the join command. Perhaps this happens for other commands, too?

How to reproduce

Run this script:

use std assert

# start figuring out the relation between islands in Riven :grin:

let list_of_records = [{"island name": boiler}]
let table = [["island name"]; [boiler]]

assert ($list_of_records == $table)
assert (($list_of_records | join $list_of_records "island name") == $table)

assert (($table | join $list_of_records "island name") == $table)
assert (($table | join ([{"island name": boiler}]) "island name") == $table)
assert (($table | join [{"island name": boiler}] "island name") == $table)

assert (($table | join $table "island name") == $table)
assert (($table | join ([["island name"]; [boiler]]) "island name") == $table)
assert (($table | join [["island name"]; [boiler]] "island name") == $table) # fails :'(

Expected behavior

The final line:

assert (($table | join [["island name"]; [boiler]] "island name") == $table) # fails :'(

…should not fail its assert call.

Screenshots

No response

Configuration

key value
version 0.96.1
major 0
minor 96
patch 1
branch
commit_hash
build_os macos-aarch64
build_target aarch64-apple-darwin
rust_version rustc 1.79.0 (129f3b996 2024-06-10) (Homebrew)
cargo_version cargo 1.79.0
build_time 2024-07-29 23:31:36 +00:00
build_rust_channel release
allocator mimalloc
features default, sqlite, system-clipboard, trash
installed_plugins

Additional context

No response

ErichDonGubler avatar Aug 04 '24 21:08 ErichDonGubler

I wonder if this could be a bug with join too because this doesn't return anything.

$table | join [["island name"]; [boiler]] "island name"

It is interesting that this works though, as if the table literal needs to be in parens for proper evaluation.

($table | join ([["island name"]; [boiler]]) "island name") == $table

fdncred avatar Aug 04 '24 22:08 fdncred

I'm on mobile, so I can't get dumo the info, but if you run nu --ide-ast on the script, the unparenthesized table literal appears to be parsed as a list? 👀 The parenthesized literal right before it works fine.

ErichDonGubler avatar Aug 04 '24 22:08 ErichDonGubler

hmmm, interesting. I forgot about --ide-ast. I wonder what the IR says.

❯ view ir { $table | join [["island name"]; [boiler]] "island name" }
# 4 registers, 13 instructions, 22 bytes of data
   0: load-variable          %0, var 4209 "$table"
   1: load-literal           %1, list(capacity = 1)
   2: load-literal           %2, list(capacity = 1)
   3: load-literal           %3, string("island name")
   4: list-push              %2, %3
   5: list-push              %1, %2
   6: load-literal           %2, string("island name")
   7: push-positional        %1
   8: push-positional        %2
   9: redirect-out           caller
  10: redirect-err           caller
  11: call                   decl 81 "join", %0
  12: return                 %0

❯ view ir { $table | join ([["island name"]; [boiler]]) "island name" }
# 6 registers, 16 instructions, 28 bytes of data
   0: load-variable          %0, var 4209 "$table"
   1: load-literal           %1, list(capacity = 1)
   2: load-literal           %2, string("island name")
   3: load-literal           %3, record(capacity = 1)
   4: clone                  %4, %2
   5: load-literal           %5, string("boiler")
   6: record-insert          %3, %4, %5
   7: list-push              %1, %3
   8: drop                   %2
   9: load-literal           %2, string("island name")
  10: push-positional        %1
  11: push-positional        %2
  12: redirect-out           caller
  13: redirect-err           caller
  14: call                   decl 81 "join", %0

fdncred avatar Aug 04 '24 23:08 fdncred

I think this reveals two underlying issues:

  • maybe the parse_value List arm should actually call parse_table_expression (see #14226)
  • the data is partially parsed due to missing checks in parse_list_expression (a quick-and-dirty fix is described at https://github.com/nushell/nushell/issues/14188#issuecomment-2445394490)

sgvictorino avatar Oct 29 '24 22:10 sgvictorino