From aa0485fe33204169724d020f9c5e3b91e558ab1e Mon Sep 17 00:00:00 2001 From: ubq323 Date: Tue, 23 Jul 2024 17:00:56 +0100 Subject: add pend builtin function --- doc.txt | 4 ++++ g.peg | 6 +++--- ideas | 35 +++++++++++++++++++++++++++++++++++ lib.c | 17 ++++++++++++++++- tests/pend.bth | 25 +++++++++++++++++++++++++ tests/pend.out | 19 +++++++++++++++++++ 6 files changed, 102 insertions(+), 4 deletions(-) create mode 100644 ideas create mode 100644 tests/pend.bth create mode 100644 tests/pend.out diff --git a/doc.txt b/doc.txt index fce7e9d..d65c981 100644 --- a/doc.txt +++ b/doc.txt @@ -43,6 +43,10 @@ (arr): create new empty array (append a x): appends to array a, returns a (len a): get length of array a + (, ...): pend. concatenates arrays, promotes non-arrays to arrays + (, [1 2 3] 4) -> [1 2 3 4] + (, [1 2 3] [4 5]) -> [1 2 3 4 5] + (, 10 20) -> [10 20] etc # cmdline args bth [-Dl] [-Dt] filenames... diff --git a/g.peg b/g.peg index 08ded48..84d907e 100644 --- a/g.peg +++ b/g.peg @@ -32,12 +32,12 @@ expr <- / a:array { $$ = a; } list <- { $$ = astnode_new_list(); } - '(' + '(' _ ( e:expr { astnode_append(&$$, e); } )* ')' _ array <- { $$ = astnode_new_arr(); } - '[' + '[' _ ( e:expr { astnode_append(&$$, e); } )* ']' _ @@ -46,7 +46,7 @@ number <- < [0-9]+ > (! ident_char) _ { $$ = astnode_new_num(atoi($1)); } ident <- < ident_char+ > _ { $$ = astnode_new_ident($1); } string <- '"' < [^"]* > '"' _ { $$ = astnode_new_string($1); } -ident_char <- [-_a-zA-Z'+*/\\%=0-9<>!] +ident_char <- [-_a-zA-Z'+*/\\%=0-9<>!,] _ <- [ \t\n]* diff --git a/ideas b/ideas new file mode 100644 index 0000000..9717cb6 --- /dev/null +++ b/ideas @@ -0,0 +1,35 @@ +(, a b) +pend. +concatenates arrays, but enlists anything that isnt already an array +thus + (, x xs) (, xs x) is like append or prepend + (, x y) is pair + (, x) is enlist + (, xs ys) is extend +if you really want an array to be inside another array + you can do (, xs (, ys)) or equivalently (, xs [ys]) + this is probably the rarer case so that's good +this always returns (allocates) a new object. that's probably fine +most of the time +if you want it to modify inplace have a (,! ...) form +but need to specify which one to modify ... + (,! x xs) (,! xs x) are unambiguous + but should (,! xs ys) copy ys to xs or vice versa? + maybe something like (,!< xs ys) (,!> xs ys) respectively + or maybe more generally (,! xs (! ys)) but that's uglier + (,! xs !ys) ??? +this also does string concatenation. +have a variant (,, ...) maybe that puts spaces in between +have a variant that uniions hashes + does (, {'x 10} {'y 20}) do {'x 10 'y 20} or [{'x 10} {'y 20}] ? + probably see which is commoner + + + +separate strings from symbols +symbols are atomic and interned +strings are just arrays of characters (codepoints) + + + + diff --git a/lib.c b/lib.c index e070bc0..a1ca311 100644 --- a/lib.c +++ b/lib.c @@ -40,7 +40,21 @@ static Val fn_len(State *S, int nargs, Val *args) { ObjArr *a = AS_ARR(args[0]); return VAL_NUM(a->len); } - +static Val fn_pend(State *S, int nargs, Val *args) { + CHECK(nargs > 0, "need at least 1 arg to ,"); + ObjArr *a = objarr_new(S); + for (int i = 0; i < nargs; i++) { + Val v = args[i]; + if (!IS_ARR(v)) + objarr_append(S, a, v); + else { + ObjArr *b = AS_ARR(v); + for (int j = 0; j < b->len; j++) + objarr_append(S, a, b->d[j]); + } + } + return VAL_OBJ(a); +} typedef struct { @@ -55,6 +69,7 @@ static BuiltinFunc builtin_funcs[] = { { "arr", fn_arr }, { "append", fn_append }, { "len", fn_len }, + { ",", fn_pend }, { 0 }, }; diff --git a/tests/pend.bth b/tests/pend.bth new file mode 100644 index 0000000..9a37f00 --- /dev/null +++ b/tests/pend.bth @@ -0,0 +1,25 @@ +(def xs [ + (, 10) + (, [100 200]) + + (, 22 33) + (, 11 [111 222]) + (, [333 444] 99) + (, [555 666] [777 888]) + + (, 10 11 12) + (, 10 11 [20 30]) + (, 10 [222 333] 99) + (, 10 [22 33] [44 55]) + (, [100 200] 33 44) + (, [100 200] 33 [444 555]) + (, [100 200] [33 44] 55) + (, [100 200] [333 444] [555 666]) + + (, []) + (, [1]) + (, 10 []) + (, [] 20) + (, [] []) +]) +(each (x xs) (say x)) diff --git a/tests/pend.out b/tests/pend.out new file mode 100644 index 0000000..44239f7 --- /dev/null +++ b/tests/pend.out @@ -0,0 +1,19 @@ +[ 10 ] +[ 100 200 ] +[ 22 33 ] +[ 11 111 222 ] +[ 333 444 99 ] +[ 555 666 777 888 ] +[ 10 11 12 ] +[ 10 11 20 30 ] +[ 10 222 333 99 ] +[ 10 22 33 44 55 ] +[ 100 200 33 44 ] +[ 100 200 33 444 555 ] +[ 100 200 33 44 55 ] +[ 100 200 333 444 555 666 ] +[ ] +[ 1 ] +[ 10 ] +[ 20 ] +[ ] -- cgit v1.2.3