From 371b9a79473ea26dd5d05fc4411b905eb9899690 Mon Sep 17 00:00:00 2001 From: gue-ni Date: Mon, 6 Oct 2025 21:11:12 +0200 Subject: [PATCH 1/9] add tests for split and strip --- tests/test_lisp.cpp | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/tests/test_lisp.cpp b/tests/test_lisp.cpp index c79d36b..6aac9c7 100644 --- a/tests/test_lisp.cpp +++ b/tests/test_lisp.cpp @@ -1011,3 +1011,21 @@ TEST_F( LispTest, test_apply_1 ) EXPECT_EQ( err.str(), "" ); EXPECT_EQ( out.str(), "6" ); } + +TEST_F( LispTest, test_split_01 ) +{ + std::string src = "(length (split \" \" \"this text if full of spaces\"))"; + int r = eval( src, ctx, io ); + EXPECT_EQ( r, 0 ); + EXPECT_EQ( err.str(), "" ); + EXPECT_EQ( out.str(), "6" ); +} + +TEST_F( LispTest, test_strip_01 ) +{ + std::string src = "(print (strip \" remove leading and trailing whitespace\n \"))"; + int r = eval( src, ctx, io ); + EXPECT_EQ( r, 0 ); + EXPECT_EQ( err.str(), "" ); + EXPECT_EQ( out.str(), "remove leading and trailing whitespace" ); +} \ No newline at end of file From 2999a9f99ba6806c01d045adffa096ef674e206c Mon Sep 17 00:00:00 2001 From: gue-ni Date: Mon, 6 Oct 2025 21:27:04 +0200 Subject: [PATCH 2/9] update docs --- doc/getting-started.md | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/getting-started.md b/doc/getting-started.md index 682570b..bb8983e 100644 --- a/doc/getting-started.md +++ b/doc/getting-started.md @@ -206,4 +206,5 @@ passing them to the macro. Arguments can be unquoted with `,` and `,@`. | `strcmp` | Compare string | | | `strlen` | Get length of string | | | `strip` | Remove leading or trailing whitespace | | +| `split` | Split string on delimiteer | `(split " " "hello world")` | | `getenv` | Get environment variable | `(getenv "HOME")` | From 8ad4ca3c1b043459e58563ed2d153c733d07437b Mon Sep 17 00:00:00 2001 From: gue-ni Date: Mon, 6 Oct 2025 21:11:12 +0200 Subject: [PATCH 3/9] add tests for split and strip --- tests/test_lisp.cpp | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/tests/test_lisp.cpp b/tests/test_lisp.cpp index c79d36b..6aac9c7 100644 --- a/tests/test_lisp.cpp +++ b/tests/test_lisp.cpp @@ -1011,3 +1011,21 @@ TEST_F( LispTest, test_apply_1 ) EXPECT_EQ( err.str(), "" ); EXPECT_EQ( out.str(), "6" ); } + +TEST_F( LispTest, test_split_01 ) +{ + std::string src = "(length (split \" \" \"this text if full of spaces\"))"; + int r = eval( src, ctx, io ); + EXPECT_EQ( r, 0 ); + EXPECT_EQ( err.str(), "" ); + EXPECT_EQ( out.str(), "6" ); +} + +TEST_F( LispTest, test_strip_01 ) +{ + std::string src = "(print (strip \" remove leading and trailing whitespace\n \"))"; + int r = eval( src, ctx, io ); + EXPECT_EQ( r, 0 ); + EXPECT_EQ( err.str(), "" ); + EXPECT_EQ( out.str(), "remove leading and trailing whitespace" ); +} \ No newline at end of file From 1a555e933a0ebde44532a858ed97f918f6fa0e38 Mon Sep 17 00:00:00 2001 From: gue-ni Date: Mon, 6 Oct 2025 21:27:04 +0200 Subject: [PATCH 4/9] update docs --- doc/getting-started.md | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/getting-started.md b/doc/getting-started.md index 682570b..bb8983e 100644 --- a/doc/getting-started.md +++ b/doc/getting-started.md @@ -206,4 +206,5 @@ passing them to the macro. Arguments can be unquoted with `,` and `,@`. | `strcmp` | Compare string | | | `strlen` | Get length of string | | | `strip` | Remove leading or trailing whitespace | | +| `split` | Split string on delimiteer | `(split " " "hello world")` | | `getenv` | Get environment variable | `(getenv "HOME")` | From 05f34fd1d60af2b9e1802275781bc1238d1d2ce6 Mon Sep 17 00:00:00 2001 From: gue-ni Date: Mon, 6 Oct 2025 21:51:27 +0200 Subject: [PATCH 5/9] moved files --- .github/workflows/build.yml | 2 +- doc/getting-started.md | 4 ++-- src/builtin.cpp | 33 ++++++++++++++++++++++++++++++ {stdlib => src/stdlib}/profile.lsp | 0 {stdlib => src/stdlib}/shell.lsp | 0 {stdlib => src/stdlib}/util.lsp | 0 tools/create-release.lsp | 2 +- 7 files changed, 37 insertions(+), 4 deletions(-) rename {stdlib => src/stdlib}/profile.lsp (100%) rename {stdlib => src/stdlib}/shell.lsp (100%) rename {stdlib => src/stdlib}/util.lsp (100%) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 6d7ce0a..69df6fc 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -43,7 +43,7 @@ jobs: run: | mkdir -p ${{ github.workspace }}/release cp -v ${{ github.workspace }}/build/src/lisp ${{ github.workspace }}/release/ - cp -v -r ${{ github.workspace }}/stdlib ${{ github.workspace }}/release/ + cp -v -r ${{ github.workspace }}/src/stdlib ${{ github.workspace }}/release/ tar -czvf lisp-linux-amd64.tar.gz -C ${{ github.workspace }}/release lisp stdlib pwd ls -la diff --git a/doc/getting-started.md b/doc/getting-started.md index bb8983e..d4f3fca 100644 --- a/doc/getting-started.md +++ b/doc/getting-started.md @@ -190,8 +190,8 @@ passing them to the macro. Arguments can be unquoted with `,` and `,@`. | `and` , `or`, `not` | Boolean operators | | | `print` , `println` | Print to command line | | | `cons` | Create cons cell | `(cons 1 (cons 2 (cons 3 nil)))` | -| `car` | Access _car_ of _cons_ cell | `(car (cons 1 2))` | -| `cdr` | Access _cdr_ of _cons_ cell | `(cdr (cons 1 2))` | +| `car` | Access _car_ of _cons_ cell | `(car (cons 1 2))` returns `1` | +| `cdr` | Access _cdr_ of _cons_ cell | `(cdr (cons 1 2))` returns `2` | | `append` | Concatinate lists | `(append (list 1 2 3) (list 4 5 6))` | | `map` | Return list of elements with function applied | `(map (lambda (x) (* x x)) (list 1 2 3))` | | `filter` `(filter pred lst)` | Return list of elements for wich pred is true | `(filter (lambda (x) (> x 1)) (list 1 2 3))` | diff --git a/src/builtin.cpp b/src/builtin.cpp index 0ba2c29..574f9fb 100644 --- a/src/builtin.cpp +++ b/src/builtin.cpp @@ -823,6 +823,38 @@ Expr * f_symbol_name( Expr * arg, Context & context, const IO & io ) /////////////////////////////////////////////////////////////////////////////// +Expr * f_dump( Expr * arg, Context & context, const IO & io ) +{ + Context * root = &context; + while( root->parent() ) + root = root->parent(); + + for( const std::pair & p : root->env() ) + { + + if( p.second->is_native() ) + { + continue; + } + + if( p.second->is_lambda() ) + { + std::cout << "(defun " << p.first << " " << to_string_repr( p.second ) << ")" << std::endl; + } + else if( p.second->is_macro() ) + { + // TODO + } + else + { + std::cout << "(defvar " << p.first << " " << to_string_repr( p.second ) << ") " << std::endl; + } + } + return make_nil(); +} + +/////////////////////////////////////////////////////////////////////////////// + void load( Context & ctx ) { ctx.defvar( "+", make_native( builtin::f_add ) ); @@ -877,6 +909,7 @@ void load( Context & ctx ) ctx.defvar( "filter", make_native( builtin::f_filter ) ); ctx.defvar( "apply", make_native( builtin::f_apply ) ); ctx.defvar( "load", make_native( builtin::f_load ) ); + ctx.defvar( "dump", make_native( builtin::f_dump ) ); } /////////////////////////////////////////////////////////////////////////////// diff --git a/stdlib/profile.lsp b/src/stdlib/profile.lsp similarity index 100% rename from stdlib/profile.lsp rename to src/stdlib/profile.lsp diff --git a/stdlib/shell.lsp b/src/stdlib/shell.lsp similarity index 100% rename from stdlib/shell.lsp rename to src/stdlib/shell.lsp diff --git a/stdlib/util.lsp b/src/stdlib/util.lsp similarity index 100% rename from stdlib/util.lsp rename to src/stdlib/util.lsp diff --git a/tools/create-release.lsp b/tools/create-release.lsp index a79407e..edb2e25 100755 --- a/tools/create-release.lsp +++ b/tools/create-release.lsp @@ -24,7 +24,7 @@ (let ((tmp-dir (strip ($ (sh mktemp -d))))) (and (sh cp -v (strcat build-dir "/" "src/lisp") tmp-dir) - (sh cp -vr "stdlib" tmp-dir) + (sh cp -vr "src/stdlib" tmp-dir) (sh tar -czvf archive-name -C tmp-dir "lisp" "stdlib") (sh rm -rfv tmp-dir)))) From 22ae5c5fdb14a38c8adad4d779c632268c73d884 Mon Sep 17 00:00:00 2001 From: gue-ni Date: Mon, 6 Oct 2025 22:04:17 +0200 Subject: [PATCH 6/9] Update profile --- src/eval.cpp | 2 -- src/stdlib/profile.lsp | 2 -- 2 files changed, 4 deletions(-) diff --git a/src/eval.cpp b/src/eval.cpp index 1d70835..82b4b0a 100644 --- a/src/eval.cpp +++ b/src/eval.cpp @@ -730,8 +730,6 @@ int repl() eval_profile( ctx, io ); - std::cout << std::endl; - do { std::string line; diff --git a/src/stdlib/profile.lsp b/src/stdlib/profile.lsp index 29caf1a..adef408 100644 --- a/src/stdlib/profile.lsp +++ b/src/stdlib/profile.lsp @@ -4,5 +4,3 @@ (progn (load (strcat lib "util.lsp")) (load (strcat lib "shell.lsp")))) - -(println "Loaded profile.") \ No newline at end of file From b827e4e870dcd475799b63f244002a3e23915b80 Mon Sep 17 00:00:00 2001 From: gue-ni Date: Wed, 8 Oct 2025 21:09:13 +0200 Subject: [PATCH 7/9] upate --- src/eval.cpp | 10 +++++++++- src/eval.h | 3 +++ tests/test_shell.cpp | 25 ++++++++++++++++--------- tests/util.h | 6 ------ 4 files changed, 28 insertions(+), 16 deletions(-) diff --git a/src/eval.cpp b/src/eval.cpp index 82b4b0a..0c015dc 100644 --- a/src/eval.cpp +++ b/src/eval.cpp @@ -145,7 +145,7 @@ std::string init_script() /////////////////////////////////////////////////////////////////////////////// -void eval_profile( Context & context, const IO & io ) +void load_shell_macros(Context & context, const IO & io ) { const std::string shell_macros = R"( ; test if a symbol is defined @@ -166,6 +166,14 @@ void eval_profile( Context & context, const IO & io ) ( void ) eval( shell_macros, context, io ); +} + +/////////////////////////////////////////////////////////////////////////////// + +void eval_profile( Context & context, const IO & io ) +{ + load_shell_macros(context,io); + const char * home = getenv( "HOME" ); assert( home != nullptr ); diff --git a/src/eval.h b/src/eval.h index ad4eb2f..fe5a665 100644 --- a/src/eval.h +++ b/src/eval.h @@ -68,6 +68,9 @@ int eval( const std::string & source, Flags flags = FLAG_NEWLINE | FLAG_INTERACT Expr * eval_program( Expr * program, Context & context, const IO & io ); + +void load_shell_macros(Context & context, const IO & io ); + int repl(); /////////////////////////////////////////////////////////////////////////////// diff --git a/tests/test_shell.cpp b/tests/test_shell.cpp index cc91226..536c13a 100644 --- a/tests/test_shell.cpp +++ b/tests/test_shell.cpp @@ -4,12 +4,23 @@ using namespace lisp; +class ShellTest : public LispTest { + public: +void SetUp() override + { + load_shell_macros(ctx,io); + + } + + void TearDown() override + { + } +}; + #ifdef __linux__ -TEST_F( LispTest, test_shell_01 ) +TEST_F( ShellTest, test_shell_01 ) { std::string src = R"( -(load "stdlib/shell.lsp") - (defvar result ($ (pipe @@ -23,11 +34,9 @@ TEST_F( LispTest, test_shell_01 ) EXPECT_EQ( out.str(), "src/lisp.h" ); } -TEST_F( LispTest, test_shell_02 ) +TEST_F( ShellTest, test_shell_02 ) { std::string src = R"( -(load "stdlib/shell.lsp") - (defvar reversed ($ (pipe @@ -41,11 +50,9 @@ TEST_F( LispTest, test_shell_02 ) EXPECT_EQ( out.str(), "dlrow olleh" ); } -TEST_F( LispTest, test_shell_03 ) +TEST_F( ShellTest, test_shell_03 ) { std::string src = R"( -(load "stdlib/shell.lsp") - (print ($ (sh uname -o))) )"; int r = eval( src, ctx, io ); diff --git a/tests/util.h b/tests/util.h index 66c7f5b..2021823 100644 --- a/tests/util.h +++ b/tests/util.h @@ -16,13 +16,7 @@ class LispTest : public ::testing::Test { } - void SetUp() override - { - } - void TearDown() override - { - } protected: Context ctx; From 23f591e231dd456dee0cd099afc2b37cff80d2e6 Mon Sep 17 00:00:00 2001 From: gue-ni Date: Wed, 8 Oct 2025 21:14:56 +0200 Subject: [PATCH 8/9] update --- src/builtin.cpp | 25 ------------------------- src/eval.cpp | 5 ++--- src/eval.h | 3 +-- tests/test_shell.cpp | 20 ++++++++------------ tests/util.h | 2 -- 5 files changed, 11 insertions(+), 44 deletions(-) diff --git a/src/builtin.cpp b/src/builtin.cpp index 574f9fb..bf8aad3 100644 --- a/src/builtin.cpp +++ b/src/builtin.cpp @@ -825,31 +825,6 @@ Expr * f_symbol_name( Expr * arg, Context & context, const IO & io ) Expr * f_dump( Expr * arg, Context & context, const IO & io ) { - Context * root = &context; - while( root->parent() ) - root = root->parent(); - - for( const std::pair & p : root->env() ) - { - - if( p.second->is_native() ) - { - continue; - } - - if( p.second->is_lambda() ) - { - std::cout << "(defun " << p.first << " " << to_string_repr( p.second ) << ")" << std::endl; - } - else if( p.second->is_macro() ) - { - // TODO - } - else - { - std::cout << "(defvar " << p.first << " " << to_string_repr( p.second ) << ") " << std::endl; - } - } return make_nil(); } diff --git a/src/eval.cpp b/src/eval.cpp index 0c015dc..8afe424 100644 --- a/src/eval.cpp +++ b/src/eval.cpp @@ -145,7 +145,7 @@ std::string init_script() /////////////////////////////////////////////////////////////////////////////// -void load_shell_macros(Context & context, const IO & io ) +void load_shell_macros( Context & context, const IO & io ) { const std::string shell_macros = R"( ; test if a symbol is defined @@ -165,14 +165,13 @@ void load_shell_macros(Context & context, const IO & io ) )"; ( void ) eval( shell_macros, context, io ); - } /////////////////////////////////////////////////////////////////////////////// void eval_profile( Context & context, const IO & io ) { - load_shell_macros(context,io); + load_shell_macros( context, io ); const char * home = getenv( "HOME" ); assert( home != nullptr ); diff --git a/src/eval.h b/src/eval.h index fe5a665..1a539f3 100644 --- a/src/eval.h +++ b/src/eval.h @@ -68,8 +68,7 @@ int eval( const std::string & source, Flags flags = FLAG_NEWLINE | FLAG_INTERACT Expr * eval_program( Expr * program, Context & context, const IO & io ); - -void load_shell_macros(Context & context, const IO & io ); +void load_shell_macros( Context & context, const IO & io ); int repl(); diff --git a/tests/test_shell.cpp b/tests/test_shell.cpp index 536c13a..147b77f 100644 --- a/tests/test_shell.cpp +++ b/tests/test_shell.cpp @@ -4,16 +4,12 @@ using namespace lisp; -class ShellTest : public LispTest { - public: -void SetUp() override - { - load_shell_macros(ctx,io); - - } - - void TearDown() override +class ShellTest : public LispTest +{ +public: + void SetUp() override { + load_shell_macros( ctx, io ); } }; @@ -24,14 +20,14 @@ TEST_F( ShellTest, test_shell_01 ) (defvar result ($ (pipe - (sh find "src") - (sh grep "lisp.h")))) + (sh ls "/") + (sh grep "var")))) (print result) )"; int r = eval( src, ctx, io ); EXPECT_EQ( err.str(), "" ); - EXPECT_EQ( out.str(), "src/lisp.h" ); + EXPECT_EQ( out.str(), "var" ); } TEST_F( ShellTest, test_shell_02 ) diff --git a/tests/util.h b/tests/util.h index 2021823..731bed4 100644 --- a/tests/util.h +++ b/tests/util.h @@ -16,8 +16,6 @@ class LispTest : public ::testing::Test { } - - protected: Context ctx; std::ostringstream out, err; From ed349a20375e6e1cdf42f27f4bed359a37271a3d Mon Sep 17 00:00:00 2001 From: gue-ni Date: Wed, 8 Oct 2025 21:16:40 +0200 Subject: [PATCH 9/9] remove useless function --- src/eval.cpp | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/src/eval.cpp b/src/eval.cpp index 8afe424..a41cd86 100644 --- a/src/eval.cpp +++ b/src/eval.cpp @@ -133,18 +133,6 @@ bool Context::is_root() const /////////////////////////////////////////////////////////////////////////////// -std::string init_script() -{ - const char * home = getenv( "HOME" ); - assert( home != nullptr ); - - std::string profile = ".profile.lsp"; - - return "(load \"" + std::string( home ) + "/" + profile + "\")"; -} - -/////////////////////////////////////////////////////////////////////////////// - void load_shell_macros( Context & context, const IO & io ) { const std::string shell_macros = R"(