From fe8b60d2e800c5afbd68c4415de5aef74235fa02 Mon Sep 17 00:00:00 2001 From: John Jacobsen Date: Thu, 22 Aug 2024 09:43:23 -0500 Subject: [PATCH] WIP adding argv. #96 --- examples/galax.l1 | 5 +++-- lisp/builtin.go | 20 ++++++++++++++++++++ lisp/builtin_test.go | 16 ++++++++++++++++ lisp/examples.txt | 1 + main.go | 10 ++++------ 5 files changed, 44 insertions(+), 8 deletions(-) diff --git a/examples/galax.l1 b/examples/galax.l1 index 606516e..e5cb5e0 100644 --- a/examples/galax.l1 +++ b/examples/galax.l1 @@ -174,5 +174,6 @@ darlena arlinda arlen junita margeret anette selina wilma reena tessa delma)) -(dotimes 10 - (printl (itsalive (randchoice all-names)))) +(let ((n (number (or (caddr ARGV) 10)))) + (dotimes n + (printl (itsalive (randchoice all-names))))) diff --git a/lisp/builtin.go b/lisp/builtin.go index 2fab1e3..ee9d296 100644 --- a/lisp/builtin.go +++ b/lisp/builtin.go @@ -31,6 +31,12 @@ func InitGlobals() Env { globals.Set("BQUOTE", Atom{"`"}) globals.Set("DQUOTE", Atom{"\""}) globals.Set("UPLINE", Atom{"\033[F"}) + // Form up ARGV: + var args []Sexpr + for _, arg := range os.Args { + args = append(args, Atom{arg}) + } + globals.Set("ARGV", mkListAsConsWithCdr(args, Nil)) return globals } @@ -882,6 +888,20 @@ func init() { return Nil, nil }, }, + "number": { + Name: "number", + Doc: DOC("Cast an atom, probably from an external source, to a number. Mostly used for parsing ARGV."), + FixedArity: 1, + NAry: false, + Args: LC(A("x")), + Fn: func(args []Sexpr, _ *Env) (Sexpr, error) { + if len(args) != 1 { + return nil, baseError("number expects a single argument") + } + n := Num(args[0].String()) + return n, nil + }, + }, "print": { Name: "print", Doc: DOC("Print the arguments"), diff --git a/lisp/builtin_test.go b/lisp/builtin_test.go index 2b89ff9..466f8c0 100644 --- a/lisp/builtin_test.go +++ b/lisp/builtin_test.go @@ -68,3 +68,19 @@ func TestListFromSemver(t *testing.T) { } } } + +// Test that the number function returns the number it is given. +// Primarily useful for handling argv values. +func TestNumberTest(t *testing.T) { + // Emulate setting of an argv value: + env := mkEnv(nil) + env.Set("h", Atom{"100"}) + // Check the function proper: + result, err := eval(Cons(Atom{"number"}, Cons(Atom{"h"}, Nil)), &env) + if err != nil { + t.Errorf("eval(num 100) = %q", err) + } + if !result.Equal(Num(100)) { + t.Errorf("eval(num 100) = %q", result) + } +} diff --git a/lisp/examples.txt b/lisp/examples.txt index c2d8b22..ef68c43 100644 --- a/lisp/examples.txt +++ b/lisp/examples.txt @@ -103,6 +103,7 @@ l1 - a Lisp interpreter. not N 1 Return t if the argument is nil, () otherwise not= F 0+ Complement of = function nth F 2 Find the nth value of a list, starting from zero + number N 1 Cast an atom, probably from an external source, to a number. Mostly used for parsing ARGV. number? N 1 Return true if the argument is a number, else () odd? F 1 Return true if the supplied integer argument is odd or S 0+ Boolean or diff --git a/main.go b/main.go index 79c2fb3..e7462c7 100644 --- a/main.go +++ b/main.go @@ -104,12 +104,10 @@ func main() { files := flag.Args() if len(files) > 0 { - for _, file := range files { - err := lisp.LoadFile(&globals, file) - if err != nil { - fmt.Printf("ERROR:\n%v\n", err) - os.Exit(1) - } + err := lisp.LoadFile(&globals, files[0]) + if err != nil { + fmt.Printf("ERROR:\n%v\n", err) + os.Exit(1) } return }