diff --git a/README.md b/README.md index e9b2aee..9a42b47 100644 --- a/README.md +++ b/README.md @@ -534,17 +534,18 @@ while | yes | Control flow ### Core functions -Name | Safe-mode | Example | Example result | Description ------ | --------- | ------- | -------------- | ----------- -debug | no | `(debug)` | `true` | Toggle debug output. -doc | yes | `(doc +)` | `"Return the sum of all arguments."` | Show the documentation string for a function. - | yes | `(doc myfn "Documentation string.")` | `"Documentation string."` | Set the documentation string for a function. -exit | no | `(exit 1)` | | Terminate the script with given exit code using [exit](https://www.php.net/manual/en/function.exit.php). -print | no | `(print "hello world")` | `hello world` | Print expression on the screen. Give optional second argument as `true` to show strings in readable format. Print returns null (shown in REPL). -pstr | yes | `(pstr {"a":"b"})` | `"{\"a\":\"b\"}"` | Print expression to string. -read | yes | `(read "(+ 1 2 3)")` | `(+ 1 2 3)` | Read a string as code and return the expression. -sleep | no | `(sleep 2000)` | `null` | Sleep for the given period given in milliseconds using [usleep](https://www.php.net/manual/en/function.usleep). -throw | yes | `(throw "invalid value")` | `error: "invalid value"` | Throw an exception. The given value is passed to catch. See the section Exceptions. +Name | Safe-mode | Example | Example result | Description +------ | --------- | ------- | -------------- | ----------- +debug | no | `(debug)` | `true` | Toggle debug output. +doc | yes | `(doc +)` | `"Return the sum of all arguments."` | Show the documentation string for a function. + | yes | `(doc myfn "Documentation string.")` | `"Documentation string."` | Set the documentation string for a function. +exit | no | `(exit 1)` | | Terminate the script with given exit code using [exit](https://www.php.net/manual/en/function.exit.php). +print | no | `(print "hello world")` | `hello world` | Print expression on the screen. +printr | no | `(printr "hello world")` | `"hello world"` | Print expression on the screen in readable format. +prints | yes | `(prints "hello world")` | `"\"hello world\""` | Print expression to string in readable format. +read | yes | `(read "(+ 1 2 3)")` | `(+ 1 2 3)` | Read a string as code and return the expression. +sleep | no | `(sleep 2000)` | `null` | Sleep for the given period given in milliseconds using [usleep](https://www.php.net/manual/en/function.usleep). +throw | yes | `(throw "invalid value")` | `error: "invalid value"` | Throw an exception. The given value is passed to catch. See the section Exceptions. ### Collection functions diff --git a/mad/calc.mad b/mad/calc.mad index b160704..7a0107b 100644 --- a/mad/calc.mad +++ b/mad/calc.mad @@ -15,7 +15,8 @@ (defn cmdMod (args) (apply % args)) (defn cmdMul (args) (apply * args)) (defn cmdSub (args) (apply - args)) -(defn cmdHelp (args) (str "Available commands: " (apply join ", " (keys cmdMap)))) +(defn cmdHelp () (str "Available commands: " (apply join ", " (keys cmdMap)))) +(defn cmdQuit () (exit)) ;; And we define a hash-map for command lookups with minimum number of arguments (def cmdMap { @@ -25,6 +26,7 @@ "mul": [cmdMul 2] "sub": [cmdSub 2] "help": [cmdHelp 0] + "quit": [cmdQuit 0] }) ;; Find the first command which starts with the given name, or null @@ -38,8 +40,8 @@ ;; and call it, giving the rest of the words as arguments. (defn parseInput (inp) (let (words (split " " inp) cname (first words) args (tail words) cmd (findCmd cname)) - (if (null? cmd) (print "Unknown command, try 'help'.") - (if (< (len args) (second cmd)) (print (str "Give at least 2 arguments to " cname ".")) + (if (null? cmd) "Unknown command, try 'help'." + (if (< (len args) (second cmd)) (str "Give at least 2 arguments to " cname ".") ((first cmd) args))))) ;; Define a file for readline and load it @@ -51,4 +53,4 @@ (let (inp (readline "[calc] ")) (readline-add inp) (readline-save readlineFile) - (print (str "⇒ " (parseInput inp) EOL)))) + (print "⇒ " (parseInput inp) EOL))) diff --git a/mad/dump.mad b/mad/dump.mad index 09116d9..185d8df 100644 --- a/mad/dump.mad +++ b/mad/dump.mad @@ -11,8 +11,8 @@ ;; Return the string for defining the given function (defn funcToStr (f name) (str (if (macro? f) "(defmacro " "(defn ") - name " " (pstr (meta f "args")) " " - (pstr (meta f "body")) ")")) + name " " (prints (meta f "args")) " " + (prints (meta f "body")) ")")) ;; Write a hash-map of functions into a file (defn dumpFuncs (funcs filename) diff --git a/mad/misc.mad b/mad/misc.mad index a28211c..6f90b82 100644 --- a/mad/misc.mad +++ b/mad/misc.mad @@ -1,2 +1,2 @@ ;; Measure how long it takes to execute f -(defn timer (f) (let (st (mtime)) (f) (- (mtime) st))) +(defn timeFn (f) (let (st (mtime)) (f) (- (mtime) st))) diff --git a/src/Evaller.php b/src/Evaller.php index a1cbe67..c2b6126 100644 --- a/src/Evaller.php +++ b/src/Evaller.php @@ -212,8 +212,8 @@ class Evaller return $env; } elseif ($symbolName == 'eval') { - if ($astLength == 1) { - return null; + if ($astLength != 2) { + throw new MadLispException("eval requires exactly 1 argument"); } $ast = $this->eval($astData[1], $env, $depth + 1); diff --git a/src/Lib/Core.php b/src/Lib/Core.php index c96964e..1d64c5c 100644 --- a/src/Lib/Core.php +++ b/src/Lib/Core.php @@ -69,15 +69,26 @@ class Core implements ILib } if (!$this->safemode) { - $env->set('print', new CoreFunc('print', 'Print argument. Give second argument as true to show strings in readable format.', 1, 2, - function ($a, bool $readable = false) { - $this->printer->print($a, $readable); + $env->set('print', new CoreFunc('print', 'Print arguments.', 0, -1, + function (...$args) { + foreach ($args as $a) { + $this->printer->print($a, false); + } return null; } )); } - $env->set('pstr', new CoreFunc('pstr', 'Print argument to string.', 1, 1, + if (!$this->safemode) { + $env->set('printr', new CoreFunc('printr', 'Print argument in readable format.', 1, 1, + function ($a) { + $this->printer->print($a, true); + return null; + } + )); + } + + $env->set('prints', new CoreFunc('prints', 'Print argument in readable format to string.', 1, 1, function ($a) { return $this->printer->pstr($a, true); }