diff --git a/impls/janet/Dockerfile b/impls/janet/Dockerfile index 37f242cae7..ed304066fe 100644 --- a/impls/janet/Dockerfile +++ b/impls/janet/Dockerfile @@ -1,4 +1,4 @@ -FROM ubuntu:20.04 +FROM ubuntu:24.04 MAINTAINER Joel Martin ########################################################## @@ -9,10 +9,8 @@ MAINTAINER Joel Martin RUN apt-get -y update # Required for running tests -RUN apt-get -y install make python - -# Some typical implementation and test requirements -RUN apt-get -y install wget libreadline-dev libedit-dev +RUN apt-get -y install make python3 +RUN ln -fs /usr/bin/python3 /usr/local/bin/python RUN mkdir -p /mal WORKDIR /mal @@ -21,9 +19,10 @@ WORKDIR /mal # Specific implementation requirements ########################################################## -# janet -RUN cd /usr/lib/x86_64-linux-gnu/ \ - && wget https://github.com/janet-lang/janet/releases/download/v1.12.2/janet-v1.12.2-linux.tar.gz \ - && tar xvzf janet-v1.12.2-linux.tar.gz \ - && ln -sf /usr/lib/x86_64-linux-gnu/janet-v1.12.2-linux/janet /usr/bin/janet \ - && rm janet-v1.12.2-linux.tar.gz +RUN DEBIAN_FRONTEND=noninteractive apt-get -y install \ + ca-certificates wget + +RUN wget -O- \ + https://github.com/janet-lang/janet/releases/download/v1.36.0/janet-v1.36.0-linux-x64.tar.gz \ + | tar -xzC/opt +RUN ln -sf /opt/janet-v1.36.0-linux/bin/janet /usr/local/bin/janet diff --git a/impls/janet/env.janet b/impls/janet/env.janet index d3a94100f8..4b2b817f1f 100644 --- a/impls/janet/env.janet +++ b/impls/janet/env.janet @@ -34,17 +34,8 @@ (put-in env [:data sym] value)) -(defn env-find - [env sym] - (if (get-in env [:data sym]) - env - (when-let [outer (get env :outer)] - (env-find outer sym)))) - (defn env-get [env sym] - (if-let [goal-env (env-find env sym)] - (get-in goal-env [:data sym]) - (u/throw* - (t/make-string - (string "'" (t/get-value sym) "'" " not found" ))))) + (or (get-in env [:data sym]) + (if-let [outer (get env :outer)] + (env-get outer sym)))) diff --git a/impls/janet/run b/impls/janet/run index 35b33525d7..f4782c8fae 100755 --- a/impls/janet/run +++ b/impls/janet/run @@ -1,3 +1,2 @@ -#!/bin/bash - +#!/bin/sh exec janet $(dirname $0)/${STEP:-stepA_mal}.janet "${@}" diff --git a/impls/janet/step2_eval.janet b/impls/janet/step2_eval.janet index 111bdf9b76..fa1dc786bc 100644 --- a/impls/janet/step2_eval.janet +++ b/impls/janet/step2_eval.janet @@ -20,45 +20,42 @@ (var EVAL nil) -(defn eval_ast +(defn EVAL [ast env] - (cond - (t/symbol?* ast) - (if-let [val (env ast)] - val - (error (t/make-string (string "unbound symbol: " (t/get-value ast))))) - # - (t/hash-map?* ast) + + # (print (string "EVAL: " (printer/pr_str ast true))) + + (case (t/get-type ast) + + :symbol + (or (env ast) + (error + (t/make-string + (string "'" (t/get-value ast) "'" " not found" )))) + + :hash-map (t/make-hash-map (struct ;(map |(EVAL $0 env) (kvs (t/get-value ast))))) - # - (t/list?* ast) - (t/make-list (map |(EVAL $0 env) - (t/get-value ast))) - # - (t/vector?* ast) + + :vector (t/make-vector (map |(EVAL $0 env) (t/get-value ast))) - # - ast)) -(varfn EVAL - [ast env] - (cond - (not (t/list?* ast)) - (eval_ast ast env) - # - (t/empty?* ast) - ast - # - (let [eval-list (t/get-value (eval_ast ast env)) - f (first eval-list) - args (drop 1 eval-list)] - (apply f args)))) + :list + (if (t/empty?* ast) + ast + (let [ast-head (in (t/get-value ast) 0) + f (EVAL ast-head env) + raw-args (drop 1 (t/get-value ast)) + args (map |(EVAL $0 env) raw-args)] + (apply f args))) + + # Neither a list, map, symbol or vector. + ast)) (defn PRINT - [value] - (printer/pr_str value true)) + [ast] + (printer/pr_str ast true)) (defn rep [code-str] diff --git a/impls/janet/step3_env.janet b/impls/janet/step3_env.janet index 9f99e80ee1..e07941a45c 100644 --- a/impls/janet/step3_env.janet +++ b/impls/janet/step3_env.janet @@ -1,6 +1,7 @@ (import ./reader) (import ./printer) (import ./types :as t) +(import ./utils :as u) (import ./env :as e) (defn READ @@ -23,61 +24,64 @@ (var EVAL nil) -(defn eval_ast +(var DEBUG-EVAL (t/make-symbol "DEBUG-EVAL")) + +(varfn EVAL [ast env] - (cond - (t/symbol?* ast) - (e/env-get env ast) - # - (t/hash-map?* ast) + + (if-let [dbgeval (e/env-get env DEBUG-EVAL)] + (if (not (or (t/nil?* dbgeval) + (t/false?* dbgeval))) + (print (string "EVAL: " (printer/pr_str ast true))))) + + (case (t/get-type ast) + + :symbol + (or (e/env-get env ast) + (u/throw* + (t/make-string + (string "'" (t/get-value ast) "'" " not found" )))) + + :hash-map (t/make-hash-map (struct ;(map |(EVAL $0 env) (kvs (t/get-value ast))))) - # - (t/list?* ast) - (t/make-list (map |(EVAL $0 env) - (t/get-value ast))) - # - (t/vector?* ast) + + :vector (t/make-vector (map |(EVAL $0 env) (t/get-value ast))) - # - ast)) -(varfn EVAL - [ast env] - (cond - (not (t/list?* ast)) - (eval_ast ast env) - # - (t/empty?* ast) - ast - # - (let [ast-head (first (t/get-value ast)) - head-name (t/get-value ast-head)] - (case head-name - "def!" - (let [def-name (in (t/get-value ast) 1) - def-val (EVAL (in (t/get-value ast) 2) env)] - (e/env-set env - def-name def-val) - def-val) - # - "let*" - (let [new-env (e/make-env env) - bindings (t/get-value (in (t/get-value ast) 1))] - (each [let-name let-val] (partition 2 bindings) - (e/env-set new-env - let-name (EVAL let-val new-env))) - (EVAL (in (t/get-value ast) 2) new-env)) - # - (let [eval-list (t/get-value (eval_ast ast env)) - f (first eval-list) - args (drop 1 eval-list)] - (apply f args)))))) + :list + (if (t/empty?* ast) + ast + (let [ast-head (in (t/get-value ast) 0) + head-name (t/get-value ast-head)] + (case head-name + "def!" + (let [def-name (in (t/get-value ast) 1) + def-val (EVAL (in (t/get-value ast) 2) env)] + (e/env-set env + def-name def-val) + def-val) + ## + "let*" + (let [new-env (e/make-env env) + bindings (t/get-value (in (t/get-value ast) 1))] + (each [let-name let-val] (partition 2 bindings) + (e/env-set new-env + let-name (EVAL let-val new-env))) + (EVAL (in (t/get-value ast) 2) new-env)) + ## + (let [f (EVAL ast-head env) + raw-args (drop 1 (t/get-value ast)) + args (map |(EVAL $0 env) raw-args)] + (apply f args))))) + + # Neither a list, map, symbol or vector. + ast)) (defn PRINT - [value] - (printer/pr_str value true)) + [ast] + (printer/pr_str ast true)) (defn rep [code-str] diff --git a/impls/janet/step4_if_fn_do.janet b/impls/janet/step4_if_fn_do.janet index e812eeb0ea..c028bd79f1 100644 --- a/impls/janet/step4_if_fn_do.janet +++ b/impls/janet/step4_if_fn_do.janet @@ -1,6 +1,7 @@ (import ./reader) (import ./printer) (import ./types :as t) +(import ./utils :as u) (import ./env :as e) (import ./core) @@ -16,78 +17,82 @@ (var EVAL nil) -(defn eval_ast +(var DEBUG-EVAL (t/make-symbol "DEBUG-EVAL")) + +(varfn EVAL [ast env] - (cond - (t/symbol?* ast) - (e/env-get env ast) - # - (t/hash-map?* ast) + + (if-let [dbgeval (e/env-get env DEBUG-EVAL)] + (if (not (or (t/nil?* dbgeval) + (t/false?* dbgeval))) + (print (string "EVAL: " (printer/pr_str ast true))))) + + (case (t/get-type ast) + + :symbol + (or (e/env-get env ast) + (u/throw* + (t/make-string + (string "'" (t/get-value ast) "'" " not found" )))) + + :hash-map (t/make-hash-map (struct ;(map |(EVAL $0 env) (kvs (t/get-value ast))))) - # - (t/list?* ast) - (t/make-list (map |(EVAL $0 env) - (t/get-value ast))) - # - (t/vector?* ast) + + :vector (t/make-vector (map |(EVAL $0 env) (t/get-value ast))) - # - ast)) -(varfn EVAL - [ast env] - (cond - (not (t/list?* ast)) - (eval_ast ast env) - # - (t/empty?* ast) - ast - # - (let [ast-head (first (t/get-value ast)) - head-name (t/get-value ast-head)] - (case head-name - "def!" - (let [def-name (in (t/get-value ast) 1) - def-val (EVAL (in (t/get-value ast) 2) env)] - (e/env-set env - def-name def-val) - def-val) - # - "let*" - (let [new-env (e/make-env env) - bindings (t/get-value (in (t/get-value ast) 1))] - (each [let-name let-val] (partition 2 bindings) - (e/env-set new-env - let-name (EVAL let-val new-env))) - (EVAL (in (t/get-value ast) 2) new-env)) - # - "do" - (let [do-body-forms (drop 1 (t/get-value ast)) - res-ast (eval_ast (t/make-list do-body-forms) env)] - (last (t/get-value res-ast))) - # - "if" - (let [cond-res (EVAL (in (t/get-value ast) 1) env)] - (if (or (t/nil?* cond-res) - (t/false?* cond-res)) - (if-let [else-ast (get (t/get-value ast) 3)] - (EVAL else-ast env) - t/mal-nil) - (EVAL (in (t/get-value ast) 2) env))) - # - "fn*" - (let [args (t/get-value (in (t/get-value ast) 1)) - body (in (t/get-value ast) 2)] - (t/make-function (fn [params] - (EVAL body - (e/make-env env args params))))) - # - (let [eval-list (t/get-value (eval_ast ast env)) - f (first eval-list) - args (drop 1 eval-list)] - ((t/get-value f) args)))))) + :list + (if (t/empty?* ast) + ast + (let [ast-head (in (t/get-value ast) 0) + head-name (t/get-value ast-head)] + (case head-name + "def!" + (let [def-name (in (t/get-value ast) 1) + def-val (EVAL (in (t/get-value ast) 2) env)] + (e/env-set env + def-name def-val) + def-val) + ## + "let*" + (let [new-env (e/make-env env) + bindings (t/get-value (in (t/get-value ast) 1))] + (each [let-name let-val] (partition 2 bindings) + (e/env-set new-env + let-name (EVAL let-val new-env))) + (EVAL (in (t/get-value ast) 2) new-env)) + ## + "do" + (let [most-do-body-forms (slice (t/get-value ast) 1 -2) + last-body-form (last (t/get-value ast))] + (each x most-do-body-forms (EVAL x env)) + (EVAL last-body-form env)) + ## + "if" + (let [cond-res (EVAL (in (t/get-value ast) 1) env)] + (if (or (t/nil?* cond-res) + (t/false?* cond-res)) + (if-let [else-ast (get (t/get-value ast) 3)] + (EVAL else-ast env) + t/mal-nil) + (EVAL (in (t/get-value ast) 2) env))) + ## + "fn*" + (let [params (t/get-value (in (t/get-value ast) 1)) + body (in (t/get-value ast) 2)] + (t/make-function (fn [args] + (EVAL body + (e/make-env env params args))))) + ## + (let [f (EVAL ast-head env) + raw-args (drop 1 (t/get-value ast)) + args (map |(EVAL $0 env) raw-args)] + ((t/get-value f) args))))) + + # Neither a list, map, symbol or vector. + ast)) (defn PRINT [ast] diff --git a/impls/janet/step5_tco.janet b/impls/janet/step5_tco.janet index a06cf4ebc9..e94852b8da 100644 --- a/impls/janet/step5_tco.janet +++ b/impls/janet/step5_tco.janet @@ -1,6 +1,7 @@ (import ./reader) (import ./printer) (import ./types :as t) +(import ./utils :as u) (import ./env :as e) (import ./core) @@ -16,25 +17,7 @@ (var EVAL nil) -(defn eval_ast - [ast env] - (cond - (t/symbol?* ast) - (e/env-get env ast) - # - (t/hash-map?* ast) - (t/make-hash-map (struct ;(map |(EVAL $0 env) - (kvs (t/get-value ast))))) - # - (t/list?* ast) - (t/make-list (map |(EVAL $0 env) - (t/get-value ast))) - # - (t/vector?* ast) - (t/make-vector (map |(EVAL $0 env) - (t/get-value ast))) - # - ast)) +(var DEBUG-EVAL (t/make-symbol "DEBUG-EVAL")) (varfn EVAL [ast-param env-param] @@ -42,71 +25,95 @@ (var env env-param) (label result (while true - (cond - (not (t/list?* ast)) - (return result (eval_ast ast env)) - ## - (t/empty?* ast) - (return result ast) - ## - (let [ast-head (first (t/get-value ast)) - head-name (t/get-value ast-head)] - (case head-name - "def!" - (let [def-name (in (t/get-value ast) 1) - def-val (EVAL (in (t/get-value ast) 2) env)] - (e/env-set env - def-name def-val) - (return result def-val)) - ## - "let*" - (let [new-env (e/make-env env) - bindings (t/get-value (in (t/get-value ast) 1))] - (each [let-name let-val] (partition 2 bindings) - (e/env-set new-env - let-name (EVAL let-val new-env))) - ## tco - (set ast (in (t/get-value ast) 2)) - (set env new-env)) - ## - "do" - (let [most-do-body-forms (slice (t/get-value ast) 1 -2) - last-body-form (last (t/get-value ast)) - res-ast (eval_ast (t/make-list most-do-body-forms) env)] - ## tco - (set ast last-body-form)) - ## - "if" - (let [cond-res (EVAL (in (t/get-value ast) 1) env)] - (if (or (t/nil?* cond-res) - (t/false?* cond-res)) - (if-let [else-ast (get (t/get-value ast) 3)] - ## tco - (set ast else-ast) - (return result t/mal-nil)) + + (if-let [dbgeval (e/env-get env DEBUG-EVAL)] + (if (not (or (t/nil?* dbgeval) + (t/false?* dbgeval))) + (print (string "EVAL: " (printer/pr_str ast true))))) + + (case (t/get-type ast) + + :symbol + (if-let [value (e/env-get env ast)] + (return result value) + (u/throw* + (t/make-string + (string "'" (t/get-value ast) "'" " not found" )))) + + :hash-map + (return result + (t/make-hash-map (struct ;(map |(EVAL $0 env) + (kvs (t/get-value ast)))))) + + :vector + (return result + (t/make-vector (map |(EVAL $0 env) + (t/get-value ast)))) + + :list + (if (t/empty?* ast) + (return result ast) + (let [ast-head (in (t/get-value ast) 0) + head-name (t/get-value ast-head)] + (case head-name + "def!" + (let [def-name (in (t/get-value ast) 1) + def-val (EVAL (in (t/get-value ast) 2) env)] + (e/env-set env + def-name def-val) + (return result def-val)) + ## + "let*" + (let [new-env (e/make-env env) + bindings (t/get-value (in (t/get-value ast) 1))] + (each [let-name let-val] (partition 2 bindings) + (e/env-set new-env + let-name (EVAL let-val new-env))) + ## tco + (set ast (in (t/get-value ast) 2)) + (set env new-env)) + ## + "do" + (let [most-do-body-forms (slice (t/get-value ast) 1 -2) + last-body-form (last (t/get-value ast))] + (each x most-do-body-forms (EVAL x env)) + ## tco + (set ast last-body-form)) + ## + "if" + (let [cond-res (EVAL (in (t/get-value ast) 1) env)] + (if (or (t/nil?* cond-res) + (t/false?* cond-res)) + (if-let [else-ast (get (t/get-value ast) 3)] ## tco - (set ast (in (t/get-value ast) 2)))) - ## - "fn*" - (let [params (t/get-value (in (t/get-value ast) 1)) - body (in (t/get-value ast) 2)] + (set ast else-ast) + (return result t/mal-nil)) ## tco + (set ast (in (t/get-value ast) 2)))) + ## + "fn*" + (let [params (t/get-value (in (t/get-value ast) 1)) + body (in (t/get-value ast) 2)] + ## tco + (return result + (t/make-function (fn [args] + (EVAL body + (e/make-env env params args))) + nil false + body params env))) + ## + (let [f (EVAL ast-head env) + raw-args (drop 1 (t/get-value ast)) + args (map |(EVAL $0 env) raw-args)] + (if-let [body (t/get-ast f)] ## tco + (do + (set ast body) + (set env (e/make-env (t/get-env f) (t/get-params f) args))) (return result - (t/make-function (fn [args] - (EVAL body - (e/make-env env params args))) - nil false - body params env))) - ## - (let [eval-list (t/get-value (eval_ast ast env)) - f (first eval-list) - args (drop 1 eval-list)] - (if-let [body (t/get-ast f)] ## tco - (do - (set ast body) - (set env (e/make-env (t/get-env f) (t/get-params f) args))) - (return result - ((t/get-value f) args)))))))))) + ((t/get-value f) args))))))) + + # Neither a list, map, symbol or vector. + (return result ast))))) (defn PRINT [ast] diff --git a/impls/janet/step6_file.janet b/impls/janet/step6_file.janet index b7e2dd91f2..fc078d65bf 100644 --- a/impls/janet/step6_file.janet +++ b/impls/janet/step6_file.janet @@ -1,6 +1,7 @@ (import ./reader) (import ./printer) (import ./types :as t) +(import ./utils :as u) (import ./env :as e) (import ./core) @@ -16,25 +17,7 @@ (var EVAL nil) -(defn eval_ast - [ast env] - (cond - (t/symbol?* ast) - (e/env-get env ast) - # - (t/hash-map?* ast) - (t/make-hash-map (struct ;(map |(EVAL $0 env) - (kvs (t/get-value ast))))) - # - (t/list?* ast) - (t/make-list (map |(EVAL $0 env) - (t/get-value ast))) - # - (t/vector?* ast) - (t/make-vector (map |(EVAL $0 env) - (t/get-value ast))) - # - ast)) +(var DEBUG-EVAL (t/make-symbol "DEBUG-EVAL")) (varfn EVAL [ast-param env-param] @@ -42,71 +25,95 @@ (var env env-param) (label result (while true - (cond - (not (t/list?* ast)) - (return result (eval_ast ast env)) - ## - (t/empty?* ast) - (return result ast) - ## - (let [ast-head (first (t/get-value ast)) - head-name (t/get-value ast-head)] - (case head-name - "def!" - (let [def-name (in (t/get-value ast) 1) - def-val (EVAL (in (t/get-value ast) 2) env)] - (e/env-set env - def-name def-val) - (return result def-val)) - ## - "let*" - (let [new-env (e/make-env env) - bindings (t/get-value (in (t/get-value ast) 1))] - (each [let-name let-val] (partition 2 bindings) - (e/env-set new-env - let-name (EVAL let-val new-env))) - ## tco - (set ast (in (t/get-value ast) 2)) - (set env new-env)) - ## - "do" - (let [most-do-body-forms (slice (t/get-value ast) 1 -2) - last-body-form (last (t/get-value ast)) - res-ast (eval_ast (t/make-list most-do-body-forms) env)] - ## tco - (set ast last-body-form)) - ## - "if" - (let [cond-res (EVAL (in (t/get-value ast) 1) env)] - (if (or (t/nil?* cond-res) - (t/false?* cond-res)) - (if-let [else-ast (get (t/get-value ast) 3)] - ## tco - (set ast else-ast) - (return result t/mal-nil)) + + (if-let [dbgeval (e/env-get env DEBUG-EVAL)] + (if (not (or (t/nil?* dbgeval) + (t/false?* dbgeval))) + (print (string "EVAL: " (printer/pr_str ast true))))) + + (case (t/get-type ast) + + :symbol + (if-let [value (e/env-get env ast)] + (return result value) + (u/throw* + (t/make-string + (string "'" (t/get-value ast) "'" " not found" )))) + + :hash-map + (return result + (t/make-hash-map (struct ;(map |(EVAL $0 env) + (kvs (t/get-value ast)))))) + + :vector + (return result + (t/make-vector (map |(EVAL $0 env) + (t/get-value ast)))) + + :list + (if (t/empty?* ast) + (return result ast) + (let [ast-head (in (t/get-value ast) 0) + head-name (t/get-value ast-head)] + (case head-name + "def!" + (let [def-name (in (t/get-value ast) 1) + def-val (EVAL (in (t/get-value ast) 2) env)] + (e/env-set env + def-name def-val) + (return result def-val)) + ## + "let*" + (let [new-env (e/make-env env) + bindings (t/get-value (in (t/get-value ast) 1))] + (each [let-name let-val] (partition 2 bindings) + (e/env-set new-env + let-name (EVAL let-val new-env))) + ## tco + (set ast (in (t/get-value ast) 2)) + (set env new-env)) + ## + "do" + (let [most-do-body-forms (slice (t/get-value ast) 1 -2) + last-body-form (last (t/get-value ast))] + (each x most-do-body-forms (EVAL x env)) + ## tco + (set ast last-body-form)) + ## + "if" + (let [cond-res (EVAL (in (t/get-value ast) 1) env)] + (if (or (t/nil?* cond-res) + (t/false?* cond-res)) + (if-let [else-ast (get (t/get-value ast) 3)] ## tco - (set ast (in (t/get-value ast) 2)))) - ## - "fn*" - (let [params (t/get-value (in (t/get-value ast) 1)) - body (in (t/get-value ast) 2)] + (set ast else-ast) + (return result t/mal-nil)) ## tco + (set ast (in (t/get-value ast) 2)))) + ## + "fn*" + (let [params (t/get-value (in (t/get-value ast) 1)) + body (in (t/get-value ast) 2)] + ## tco + (return result + (t/make-function (fn [args] + (EVAL body + (e/make-env env params args))) + nil false + body params env))) + ## + (let [f (EVAL ast-head env) + raw-args (drop 1 (t/get-value ast)) + args (map |(EVAL $0 env) raw-args)] + (if-let [body (t/get-ast f)] ## tco + (do + (set ast body) + (set env (e/make-env (t/get-env f) (t/get-params f) args))) (return result - (t/make-function (fn [args] - (EVAL body - (e/make-env env params args))) - nil false - body params env))) - ## - (let [eval-list (t/get-value (eval_ast ast env)) - f (first eval-list) - args (drop 1 eval-list)] - (if-let [body (t/get-ast f)] ## tco - (do - (set ast body) - (set env (e/make-env (t/get-env f) (t/get-params f) args))) - (return result - ((t/get-value f) args)))))))))) + ((t/get-value f) args))))))) + + # Neither a list, map, symbol or vector. + (return result ast))))) (defn PRINT [ast] diff --git a/impls/janet/step7_quote.janet b/impls/janet/step7_quote.janet index 7760582212..a45b9b81ba 100644 --- a/impls/janet/step7_quote.janet +++ b/impls/janet/step7_quote.janet @@ -1,6 +1,7 @@ (import ./reader) (import ./printer) (import ./types :as t) +(import ./utils :as u) (import ./env :as e) (import ./core) @@ -16,26 +17,6 @@ (var EVAL nil) -(defn eval_ast - [ast env] - (cond - (t/symbol?* ast) - (e/env-get env ast) - # - (t/hash-map?* ast) - (t/make-hash-map (struct ;(map |(EVAL $0 env) - (kvs (t/get-value ast))))) - # - (t/list?* ast) - (t/make-list (map |(EVAL $0 env) - (t/get-value ast))) - # - (t/vector?* ast) - (t/make-vector (map |(EVAL $0 env) - (t/get-value ast))) - # - ast)) - (defn starts-with [ast name] (when (and (t/list?* ast) @@ -78,88 +59,110 @@ ## ast)) +(var DEBUG-EVAL (t/make-symbol "DEBUG-EVAL")) + (varfn EVAL [ast-param env-param] (var ast ast-param) (var env env-param) (label result (while true - (cond - (not (t/list?* ast)) - (return result (eval_ast ast env)) - ## - (t/empty?* ast) - (return result ast) - ## - (let [ast-head (first (t/get-value ast)) - head-name (t/get-value ast-head)] - (case head-name - "def!" - (let [def-name (in (t/get-value ast) 1) - def-val (EVAL (in (t/get-value ast) 2) env)] - (e/env-set env - def-name def-val) - (return result def-val)) - ## - "let*" - (let [new-env (e/make-env env) - bindings (t/get-value (in (t/get-value ast) 1))] - (each [let-name let-val] (partition 2 bindings) - (e/env-set new-env - let-name (EVAL let-val new-env))) - ## tco - (set ast (in (t/get-value ast) 2)) - (set env new-env)) - ## - "quote" - (return result (in (t/get-value ast) 1)) - ## - "quasiquoteexpand" + + (if-let [dbgeval (e/env-get env DEBUG-EVAL)] + (if (not (or (t/nil?* dbgeval) + (t/false?* dbgeval))) + (print (string "EVAL: " (printer/pr_str ast true))))) + + (case (t/get-type ast) + + :symbol + (if-let [value (e/env-get env ast)] + (return result value) + (u/throw* + (t/make-string + (string "'" (t/get-value ast) "'" " not found" )))) + + :hash-map + (return result + (t/make-hash-map (struct ;(map |(EVAL $0 env) + (kvs (t/get-value ast)))))) + + :vector + (return result + (t/make-vector (map |(EVAL $0 env) + (t/get-value ast)))) + + :list + (if (t/empty?* ast) + (return result ast) + (let [ast-head (in (t/get-value ast) 0) + head-name (t/get-value ast-head)] + (case head-name + "def!" + (let [def-name (in (t/get-value ast) 1) + def-val (EVAL (in (t/get-value ast) 2) env)] + (e/env-set env + def-name def-val) + (return result def-val)) + ## + "let*" + (let [new-env (e/make-env env) + bindings (t/get-value (in (t/get-value ast) 1))] + (each [let-name let-val] (partition 2 bindings) + (e/env-set new-env + let-name (EVAL let-val new-env))) ## tco - (return result (quasiquote* (in (t/get-value ast) 1))) - ## - "quasiquote" + (set ast (in (t/get-value ast) 2)) + (set env new-env)) + ## + "quote" + (return result (in (t/get-value ast) 1)) + ## + "quasiquote" + ## tco + (set ast (quasiquote* (in (t/get-value ast) 1))) + ## + "do" + (let [most-do-body-forms (slice (t/get-value ast) 1 -2) + last-body-form (last (t/get-value ast))] + (each x most-do-body-forms (EVAL x env)) ## tco - (set ast (quasiquote* (in (t/get-value ast) 1))) - ## - "do" - (let [most-do-body-forms (slice (t/get-value ast) 1 -2) - last-body-form (last (t/get-value ast)) - res-ast (eval_ast (t/make-list most-do-body-forms) env)] - ## tco - (set ast last-body-form)) - ## - "if" - (let [cond-res (EVAL (in (t/get-value ast) 1) env)] - (if (or (t/nil?* cond-res) - (t/false?* cond-res)) - (if-let [else-ast (get (t/get-value ast) 3)] - ## tco - (set ast else-ast) - (return result t/mal-nil)) + (set ast last-body-form)) + ## + "if" + (let [cond-res (EVAL (in (t/get-value ast) 1) env)] + (if (or (t/nil?* cond-res) + (t/false?* cond-res)) + (if-let [else-ast (get (t/get-value ast) 3)] ## tco - (set ast (in (t/get-value ast) 2)))) - ## - "fn*" - (let [params (t/get-value (in (t/get-value ast) 1)) - body (in (t/get-value ast) 2)] + (set ast else-ast) + (return result t/mal-nil)) ## tco + (set ast (in (t/get-value ast) 2)))) + ## + "fn*" + (let [params (t/get-value (in (t/get-value ast) 1)) + body (in (t/get-value ast) 2)] + ## tco + (return result + (t/make-function (fn [args] + (EVAL body + (e/make-env env params args))) + nil false + body params env))) + ## + (let [f (EVAL ast-head env) + raw-args (drop 1 (t/get-value ast)) + args (map |(EVAL $0 env) raw-args)] + (if-let [body (t/get-ast f)] ## tco + (do + (set ast body) + (set env (e/make-env (t/get-env f) (t/get-params f) args))) (return result - (t/make-function (fn [args] - (EVAL body - (e/make-env env params args))) - nil false - body params env))) - ## - (let [eval-list (t/get-value (eval_ast ast env)) - f (first eval-list) - args (drop 1 eval-list)] - (if-let [body (t/get-ast f)] ## tco - (do - (set ast body) - (set env (e/make-env (t/get-env f) (t/get-params f) args))) - (return result - ((t/get-value f) args)))))))))) + ((t/get-value f) args))))))) + + # Neither a list, map, symbol or vector. + (return result ast))))) (defn PRINT [ast] diff --git a/impls/janet/step8_macros.janet b/impls/janet/step8_macros.janet index 6ebb8cc824..d894a8195b 100644 --- a/impls/janet/step8_macros.janet +++ b/impls/janet/step8_macros.janet @@ -1,6 +1,7 @@ (import ./reader) (import ./printer) (import ./types :as t) +(import ./utils :as u) (import ./env :as e) (import ./core) @@ -14,49 +15,8 @@ [code-str] (reader/read_str code-str)) -(defn is_macro_call - [ast env] - (when (and (t/list?* ast) - (not (t/empty?* ast))) - (let [head-ast (in (t/get-value ast) 0)] - (when (and (t/symbol?* head-ast) - (e/env-find env head-ast)) - (let [target-ast (e/env-get env head-ast)] - (t/macro?* target-ast)))))) - -(defn macroexpand - [ast env] - (var ast-var ast) - (while (is_macro_call ast-var env) - (let [inner-asts (t/get-value ast-var) - head-ast (in inner-asts 0) - macro-fn (t/get-value (e/env-get env head-ast)) - args (drop 1 inner-asts)] - (set ast-var (macro-fn args)))) - ast-var) - (var EVAL nil) -(defn eval_ast - [ast env] - (cond - (t/symbol?* ast) - (e/env-get env ast) - # - (t/hash-map?* ast) - (t/make-hash-map (struct ;(map |(EVAL $0 env) - (kvs (t/get-value ast))))) - # - (t/list?* ast) - (t/make-list (map |(EVAL $0 env) - (t/get-value ast))) - # - (t/vector?* ast) - (t/make-vector (map |(EVAL $0 env) - (t/get-value ast))) - # - ast)) - (defn starts-with [ast name] (when (and (t/list?* ast) @@ -99,24 +59,43 @@ ## ast)) +(var DEBUG-EVAL (t/make-symbol "DEBUG-EVAL")) + (varfn EVAL [ast-param env-param] (var ast ast-param) (var env env-param) (label result (while true - (when (not (t/list?* ast)) - (return result (eval_ast ast env))) - ## - (set ast (macroexpand ast env)) - ## - (when (not (t/list?* ast)) - (return result (eval_ast ast env))) - ## - (when (t/empty?* ast) - (return result ast)) - ## - (let [ast-head (first (t/get-value ast)) + + (if-let [dbgeval (e/env-get env DEBUG-EVAL)] + (if (not (or (t/nil?* dbgeval) + (t/false?* dbgeval))) + (print (string "EVAL: " (printer/pr_str ast true))))) + + (case (t/get-type ast) + + :symbol + (if-let [value (e/env-get env ast)] + (return result value) + (u/throw* + (t/make-string + (string "'" (t/get-value ast) "'" " not found" )))) + + :hash-map + (return result + (t/make-hash-map (struct ;(map |(EVAL $0 env) + (kvs (t/get-value ast)))))) + + :vector + (return result + (t/make-vector (map |(EVAL $0 env) + (t/get-value ast)))) + + :list + (if (t/empty?* ast) + (return result ast) + (let [ast-head (in (t/get-value ast) 0) head-name (t/get-value ast-head)] (case head-name "def!" @@ -134,9 +113,6 @@ def-name macro-ast) (return result macro-ast)) ## - "macroexpand" - (return result (macroexpand (in (t/get-value ast) 1) env)) - ## "let*" (let [new-env (e/make-env env) bindings (t/get-value (in (t/get-value ast) 1))] @@ -150,18 +126,14 @@ "quote" (return result (in (t/get-value ast) 1)) ## - "quasiquoteexpand" - ## tco - (return result (quasiquote* (in (t/get-value ast) 1))) - ## "quasiquote" ## tco (set ast (quasiquote* (in (t/get-value ast) 1))) ## "do" (let [most-do-body-forms (slice (t/get-value ast) 1 -2) - last-body-form (last (t/get-value ast)) - res-ast (eval_ast (t/make-list most-do-body-forms) env)] + last-body-form (last (t/get-value ast))] + (each x most-do-body-forms (EVAL x env)) ## tco (set ast last-body-form)) ## @@ -187,9 +159,11 @@ nil false body params env))) ## - (let [eval-list (t/get-value (eval_ast ast env)) - f (first eval-list) - args (drop 1 eval-list)] + (let [f (EVAL ast-head env) + raw-args (drop 1 (t/get-value ast))] + (if (t/macro?* f) + (set ast ((t/get-value f) raw-args)) + (let [args (map |(EVAL $0 env) raw-args)] (if-let [body (t/get-ast f)] ## tco (do (set ast body) @@ -197,6 +171,9 @@ (return result ((t/get-value f) args))))))))) + # Neither a list, map, symbol or vector. + (return result ast))))) + (defn PRINT [ast] (printer/pr_str ast true)) diff --git a/impls/janet/step9_try.janet b/impls/janet/step9_try.janet index b297965cd2..712a951441 100644 --- a/impls/janet/step9_try.janet +++ b/impls/janet/step9_try.janet @@ -15,49 +15,8 @@ [code-str] (reader/read_str code-str)) -(defn is_macro_call - [ast env] - (when (and (t/list?* ast) - (not (t/empty?* ast))) - (let [head-ast (in (t/get-value ast) 0)] - (when (and (t/symbol?* head-ast) - (e/env-find env head-ast)) - (let [target-ast (e/env-get env head-ast)] - (t/macro?* target-ast)))))) - -(defn macroexpand - [ast env] - (var ast-var ast) - (while (is_macro_call ast-var env) - (let [inner-asts (t/get-value ast-var) - head-ast (in inner-asts 0) - macro-fn (t/get-value (e/env-get env head-ast)) - args (drop 1 inner-asts)] - (set ast-var (macro-fn args)))) - ast-var) - (var EVAL nil) -(defn eval_ast - [ast env] - (cond - (t/symbol?* ast) - (e/env-get env ast) - # - (t/hash-map?* ast) - (t/make-hash-map (struct ;(map |(EVAL $0 env) - (kvs (t/get-value ast))))) - # - (t/list?* ast) - (t/make-list (map |(EVAL $0 env) - (t/get-value ast))) - # - (t/vector?* ast) - (t/make-vector (map |(EVAL $0 env) - (t/get-value ast))) - # - ast)) - (defn starts-with [ast name] (when (and (t/list?* ast) @@ -100,24 +59,43 @@ ## ast)) +(var DEBUG-EVAL (t/make-symbol "DEBUG-EVAL")) + (varfn EVAL [ast-param env-param] (var ast ast-param) (var env env-param) (label result (while true - (when (not (t/list?* ast)) - (return result (eval_ast ast env))) - ## - (set ast (macroexpand ast env)) - ## - (when (not (t/list?* ast)) - (return result (eval_ast ast env))) - ## - (when (t/empty?* ast) - (return result ast)) - ## - (let [ast-head (first (t/get-value ast)) + + (if-let [dbgeval (e/env-get env DEBUG-EVAL)] + (if (not (or (t/nil?* dbgeval) + (t/false?* dbgeval))) + (print (string "EVAL: " (printer/pr_str ast true))))) + + (case (t/get-type ast) + + :symbol + (if-let [value (e/env-get env ast)] + (return result value) + (u/throw* + (t/make-string + (string "'" (t/get-value ast) "'" " not found" )))) + + :hash-map + (return result + (t/make-hash-map (struct ;(map |(EVAL $0 env) + (kvs (t/get-value ast)))))) + + :vector + (return result + (t/make-vector (map |(EVAL $0 env) + (t/get-value ast)))) + + :list + (if (t/empty?* ast) + (return result ast) + (let [ast-head (in (t/get-value ast) 0) head-name (t/get-value ast-head)] (case head-name "def!" @@ -135,9 +113,6 @@ def-name macro-ast) (return result macro-ast)) ## - "macroexpand" - (return result (macroexpand (in (t/get-value ast) 1) env)) - ## "let*" (let [new-env (e/make-env env) bindings (t/get-value (in (t/get-value ast) 1))] @@ -151,10 +126,6 @@ "quote" (return result (in (t/get-value ast) 1)) ## - "quasiquoteexpand" - ## tco - (return result (quasiquote* (in (t/get-value ast) 1))) - ## "quasiquote" ## tco (set ast (quasiquote* (in (t/get-value ast) 1))) @@ -185,8 +156,8 @@ ## "do" (let [most-do-body-forms (slice (t/get-value ast) 1 -2) - last-body-form (last (t/get-value ast)) - res-ast (eval_ast (t/make-list most-do-body-forms) env)] + last-body-form (last (t/get-value ast))] + (each x most-do-body-forms (EVAL x env)) ## tco (set ast last-body-form)) ## @@ -212,9 +183,11 @@ nil false body params env))) ## - (let [eval-list (t/get-value (eval_ast ast env)) - f (first eval-list) - args (drop 1 eval-list)] + (let [f (EVAL ast-head env) + raw-args (drop 1 (t/get-value ast))] + (if (t/macro?* f) + (set ast ((t/get-value f) raw-args)) + (let [args (map |(EVAL $0 env) raw-args)] (if-let [body (t/get-ast f)] ## tco (do (set ast body) @@ -222,6 +195,9 @@ (return result ((t/get-value f) args))))))))) + # Neither a list, map, symbol or vector. + (return result ast))))) + (defn PRINT [ast] (printer/pr_str ast true)) diff --git a/impls/janet/stepA_mal.janet b/impls/janet/stepA_mal.janet index ca33086d8c..d5a3a87e9c 100644 --- a/impls/janet/stepA_mal.janet +++ b/impls/janet/stepA_mal.janet @@ -15,49 +15,8 @@ [code-str] (reader/read_str code-str)) -(defn is_macro_call - [ast env] - (when (and (t/list?* ast) - (not (t/empty?* ast))) - (let [head-ast (in (t/get-value ast) 0)] - (when (and (t/symbol?* head-ast) - (e/env-find env head-ast)) - (let [target-ast (e/env-get env head-ast)] - (t/macro?* target-ast)))))) - -(defn macroexpand - [ast env] - (var ast-var ast) - (while (is_macro_call ast-var env) - (let [inner-asts (t/get-value ast-var) - head-ast (in inner-asts 0) - macro-fn (t/get-value (e/env-get env head-ast)) - args (drop 1 inner-asts)] - (set ast-var (macro-fn args)))) - ast-var) - (var EVAL nil) -(defn eval_ast - [ast env] - (cond - (t/symbol?* ast) - (e/env-get env ast) - # - (t/hash-map?* ast) - (t/make-hash-map (struct ;(map |(EVAL $0 env) - (kvs (t/get-value ast))))) - # - (t/list?* ast) - (t/make-list (map |(EVAL $0 env) - (t/get-value ast))) - # - (t/vector?* ast) - (t/make-vector (map |(EVAL $0 env) - (t/get-value ast))) - # - ast)) - (defn starts-with [ast name] (when (and (t/list?* ast) @@ -100,23 +59,42 @@ ## ast)) +(var DEBUG-EVAL (t/make-symbol "DEBUG-EVAL")) + (varfn EVAL [ast-param env-param] (var ast ast-param) (var env env-param) (label result (while true - (when (not (t/list?* ast)) - (return result (eval_ast ast env))) - ## - (set ast (macroexpand ast env)) - ## - (when (not (t/list?* ast)) - (return result (eval_ast ast env))) - ## - (when (t/empty?* ast) - (return result ast)) - ## + + (if-let [dbgeval (e/env-get env DEBUG-EVAL)] + (if (not (or (t/nil?* dbgeval) + (t/false?* dbgeval))) + (print (string "EVAL: " (printer/pr_str ast true))))) + + (case (t/get-type ast) + + :symbol + (if-let [value (e/env-get env ast)] + (return result value) + (u/throw* + (t/make-string + (string "'" (t/get-value ast) "'" " not found" )))) + + :hash-map + (return result + (t/make-hash-map (struct ;(map |(EVAL $0 env) + (kvs (t/get-value ast)))))) + + :vector + (return result + (t/make-vector (map |(EVAL $0 env) + (t/get-value ast)))) + + :list + (if (t/empty?* ast) + (return result ast) (let [ast-head (in (t/get-value ast) 0) head-name (t/get-value ast-head)] (case head-name @@ -135,9 +113,6 @@ def-name macro-ast) (return result macro-ast)) ## - "macroexpand" - (return result (macroexpand (in (t/get-value ast) 1) env)) - ## "let*" (let [new-env (e/make-env env) bindings (t/get-value (in (t/get-value ast) 1))] @@ -151,10 +126,6 @@ "quote" (return result (in (t/get-value ast) 1)) ## - "quasiquoteexpand" - ## tco - (return result (quasiquote* (in (t/get-value ast) 1))) - ## "quasiquote" ## tco (set ast (quasiquote* (in (t/get-value ast) 1))) @@ -185,8 +156,8 @@ ## "do" (let [most-do-body-forms (slice (t/get-value ast) 1 -2) - last-body-form (last (t/get-value ast)) - res-ast (eval_ast (t/make-list most-do-body-forms) env)] + last-body-form (last (t/get-value ast))] + (each x most-do-body-forms (EVAL x env)) ## tco (set ast last-body-form)) ## @@ -212,9 +183,11 @@ nil false body params env))) ## - (let [eval-list (t/get-value (eval_ast ast env)) - f (first eval-list) - args (drop 1 eval-list)] + (let [f (EVAL ast-head env) + raw-args (drop 1 (t/get-value ast))] + (if (t/macro?* f) + (set ast ((t/get-value f) raw-args)) + (let [args (map |(EVAL $0 env) raw-args)] (if-let [body (t/get-ast f)] ## tco (do (set ast body) @@ -222,6 +195,9 @@ (return result ((t/get-value f) args))))))))) + # Neither a list, map, symbol or vector. + (return result ast))))) + (defn PRINT [ast] (printer/pr_str ast true))