add atoms
authorAnotherTest <ali.mpfard@gmail.com>
Mon, 6 Jan 2020 20:55:22 +0000 (00:25 +0330)
committerAnotherTest <ali.mpfard@gmail.com>
Tue, 7 Jan 2020 20:35:33 +0000 (00:05 +0330)
+ fix lists (lists do not behave like let*)
+ add file io

jq/core.jq
jq/env.jq
jq/interp.jq
jq/printer.jq
jq/run
jq/step3_env.jq
jq/step4_if_fn_do.jq
jq/step5_tco.jq
jq/step6_file.jq
jq/utils.jq

index 986d110..17d4391 100644 (file)
@@ -83,6 +83,31 @@ def core_identify:
             kind: "fn",
             function: "slurp",
             inputs: 1
+        },
+        "atom": {
+            kind: "fn",
+            function: "atom",
+            inputs: 1
+        },
+        "atom?": {
+            kind: "fn",
+            function: "atom?",
+            inputs: 1
+        },
+        "deref": {
+            kind: "fn",
+            function: "deref",
+            inputs: 1
+        },
+        "reset!": { # defined in interp
+            kind: "fn",
+            function: "reset!",
+            inputs: 2
+        },
+        "swap!": { # defined in interp
+            kind: "fn",
+            function: "swap!",
+            inputs: -1
         }
     };
 
@@ -147,4 +172,10 @@ def core_interp(arguments; env):
         select(.function == "slurp") | arguments | map(.value) | issue_extern("read") | wrap("string")
     ) // (
         select(.function == "read-string") | arguments | first.value | read_str | read_form.value
+    ) // (
+        select(.function == "atom") | arguments | first | wrap2("atom"; {names: []})
+    ) // (
+        select(.function == "atom?") | null | wrap(arguments | first.kind == "atom" | tostring)
+    ) // (
+        select(.function == "deref") | arguments | first.value
     ) // jqmal_error("Unknown native function \(.function)");
\ No newline at end of file
index 69fe6f9..bf3a6e3 100644 (file)
--- a/jq/env.jq
+++ b/jq/env.jq
@@ -81,7 +81,7 @@ def env_multiset(env; keys; value):
     env | env_multiset(keys; value);
 
 def env_set($key; $value):
-    (if $value.kind == "function" then
+    (if $value.kind == "function" or $value.kind == "atom" then
         # inform the function of its names
         $value | inform_function($key)
     else 
@@ -93,23 +93,23 @@ def env_set($key; $value):
 
 def env_dump_keys:
     def _dump:
-        .environment | keys;
+        .environment // {} | keys;
 
     if .parent == null then
         _dump
     else
-        .parent | env_dump_keys + _dump
+        (.parent | env_dump_keys + _dump) | unique
     end;
 
 def env_set(env; $key; $value):
-    (if $value.kind == "function" then
-        # inform the function of its names
+    (if $value.kind == "function" or $value.kind == "atom" then
+        # inform the function/atom of its names
         $value | (.names += [$key]) | (.names |= unique)
     else 
         $value
     end) as $value | {
         parent: env.parent,
-        environment: (env.environment + (env.environment | .[$key] |= $value)) # merge together, as env.environment[key] |= value does not work
+        environment: ((env.environment // jqmal_error("Environment empty in \(env | keys)")) + (env.environment | .[$key] |= $value)) # merge together, as env.environment[key] |= value does not work
     };
 
 def env_find(env):
@@ -173,13 +173,20 @@ def env_set6(env; key; value):
         env_set(env.currentEnv; key; value) | wrapEnv(env.replEnv)
     end;
 
+def env_set_(env; key; value):
+    if env.currentEnv != null then
+        env_set6(env; key; value)
+    else
+        env_set(env; key; value)
+    end;
+
 def addToEnv6(envexp; name):
     envexp.expr as $value
     | envexp.env as $rawEnv
     | (if $rawEnv.isReplEnv then
-        env_set($rawEnv.currentEnv; name; $value) | wrapEnv
+        env_set_($rawEnv.currentEnv; name; $value) | wrapEnv
     else
-        env_set($rawEnv.currentEnv; name; $value) | wrapEnv($rawEnv.replEnv)
+        env_set_($rawEnv.currentEnv; name; $value) | wrapEnv($rawEnv.replEnv)
     end) as $newEnv
     | {
         expr: $value,
@@ -191,7 +198,7 @@ def addToEnv(envexp; name):
         addToEnv6(envexp; name)
     else {
         expr: envexp.expr,
-        env: env_set(envexp.env; name; envexp.expr)
+        env: env_set_(envexp.env; name; envexp.expr)
     } end;
 
 # for step2
index eca916b..1260ac8 100644 (file)
@@ -74,6 +74,14 @@ def cWithReplEnv(renv; cond):
         .
     end;
 
+def updateAtoms(newEnv):
+    . as $env
+    | reduce (newEnv | env_dump_keys | map(env_get(newEnv) as $value | select($value.kind == "atom") | $value))[] as $atom (
+        $env;
+        . as $e | reduce $atom.names[] as $name (
+            $e;
+            env_set_(.; $name; $atom)));
+
 def interpret(arguments; env; _eval):
     extractReplEnv(env) as $replEnv |
     hasReplEnv(env) as $hasReplEnv |
@@ -88,6 +96,31 @@ def interpret(arguments; env; _eval):
                 | setpath(
                     ["env", "currentEnv"];
                     extractEnv(env) | cUpdateReplEnv($xreplenv; $hasReplEnv))
+            ) //
+            (select(.function == "reset!") | 
+                # env modifying function
+                arguments[0].names as $names |
+                arguments[1]|wrap2("atom"; {names: $names}) as $value |
+                (reduce $names[] as $name (
+                    env;
+                    . as $env | env_set_($env; $name; $value)
+                )) as $env |
+                $value.value | addEnv($env)
+            ) //
+            (select(.function == "swap!") | 
+                # env modifying function
+                arguments[0].names as $names |
+                arguments[0].value as $initValue |
+                arguments[1] as $function |
+                ([$initValue] + arguments[2:]) as $args |
+                ($function | interpret($args; env; _eval)) as $newEnvValue |
+                $newEnvValue.expr|wrap2("atom"; {names: $names}) as $newValue |
+                $newEnvValue.env as $newEnv |
+                (reduce $names[] as $name (
+                    $newEnv;
+                    . as $env | env_set_($env; $name; $newValue)
+                )) as $newEnv |
+                $newValue.value | addEnv($newEnv)
             ) //
                 (core_interp(arguments; env) | addEnv(env))
     ) //
@@ -97,7 +130,7 @@ def interpret(arguments; env; _eval):
             # tell it about its surroundings
             (reduce $fn.free_referencess[] as $name (
                 $fnEnv;
-                . as $env | try env_set(
+                . as $env | try env_set_(
                     .;
                     $name;
                     $name | env_get(env) | . as $xvalue
@@ -114,15 +147,16 @@ def interpret(arguments; env; _eval):
                      | cWrapEnv($replEnv; $hasReplEnv),
                 expr: $fn.body
             }
-            | _eval
+            | _eval 
             | . as $envexp
-            | extractReplEnv($envexp.env) as $xreplenv
+            | (extractReplEnv($envexp.env)) as $xreplenv
             |
             {
                 expr: .expr,
                 env: extractEnv(env)
                     | cUpdateReplEnv($xreplenv; $hasReplEnv)
                     | cWrapEnv($xreplenv; $hasReplEnv)
+                    | updateAtoms(extractEnv($envexp.env))
             }
     ) //
         jqmal_error("Unsupported function kind \(.kind)");
index a6f2af6..ffadf5a 100644 (file)
@@ -19,6 +19,7 @@ def pr_str(opt):
     (select(.kind == "false")   | "false") //
     (select(.kind == "fn")      | "#<fn>") //
     (select(.kind == "function")| "#<function \([":anon"] + .names | join(", "))>") //
+    (select(.kind == "atom")| "(atom \(.value | pr_str(opt)))") //
     "#<Unknown \(.kind) in \(.)>";
 
 def pr_str:
diff --git a/jq/run b/jq/run
index ca78941..4d4a3cc 100755 (executable)
--- a/jq/run
+++ b/jq/run
@@ -30,10 +30,17 @@ runjq() {
                     rm $tmp
                 ;;
                 fwrite)
-                    filename=$(echo "$command" | jq -Mrc ".args[0]|fromjson")
-                    content=$(echo "$command" | jq -Mrc ".args[1]|fromjson")
-                    echo "Writing stuff to $filename"
-                    echo "$content" > "$filename"
+                    tmp=$(mktemp)
+                    echo "$command" > $tmp
+                    filename=$(cat $tmp | jq -Mrc ".args[0]|fromjson")
+                    content=$(cat $tmp | jq -Mrc ".args[1]|fromjson")
+                    app=$(cat $tmp | jq -Mrc ".args[2]|fromjson")
+                    echo "'$app': Writing stuff to $filename"
+                    if [[ $res == false ]]; then
+                        echo "$content" > "$filename"
+                    else
+                        echo "$content" >> "$filename"
+                    fi
                 ;;
                 *)
                     echo $cmd
index e939635..f15f9ea 100644 (file)
@@ -58,13 +58,10 @@ def EVAL(env):
                 ) //
                 (
                     reduce .value[] as $elem (
-                        {value: [], env: env};
-                        . as $dot | $elem | EVAL($dot.env) as $eval_env |
-                            {
-                                value: ($dot.value + [$eval_env.expr]),
-                                env: $eval_env.env
-                            }
-                    ) | { expr: .value, env: .env } as $ev
+                        [];
+                        . as $dot | $elem | EVAL(env) as $eval_env |
+                            ($dot + [$eval_env.expr])
+                    ) | { expr: ., env: env } as $ev
                         | $ev.expr | first |
                             interpret($ev.expr[1:]; $ev.env; _eval_here)
                 ) //
index a45e84c..c91fe9c 100644 (file)
@@ -124,13 +124,10 @@ def EVAL(env):
                 ) //
                 (
                     reduce .value[] as $elem (
-                        {value: [], env: env};
-                        . as $dot | $elem | EVAL($dot.env) as $eval_env |
-                            {
-                                value: ($dot.value + [$eval_env.expr]),
-                                env: $eval_env.env
-                            }
-                    ) | { expr: .value, env: .env } as $ev
+                        [];
+                        . as $dot | $elem | EVAL(env) as $eval_env |
+                            ($dot + [$eval_env.expr])
+                    ) | { expr: ., env: env } as $ev
                         | $ev.expr | first |
                             interpret($ev.expr[1:]; $ev.env; _eval_here)
                 ) //
index a45e84c..c91fe9c 100644 (file)
@@ -124,13 +124,10 @@ def EVAL(env):
                 ) //
                 (
                     reduce .value[] as $elem (
-                        {value: [], env: env};
-                        . as $dot | $elem | EVAL($dot.env) as $eval_env |
-                            {
-                                value: ($dot.value + [$eval_env.expr]),
-                                env: $eval_env.env
-                            }
-                    ) | { expr: .value, env: .env } as $ev
+                        [];
+                        . as $dot | $elem | EVAL(env) as $eval_env |
+                            ($dot + [$eval_env.expr])
+                    ) | { expr: ., env: env } as $ev
                         | $ev.expr | first |
                             interpret($ev.expr[1:]; $ev.env; _eval_here)
                 ) //
index c0ccd1a..b97181b 100644 (file)
@@ -58,8 +58,14 @@ def EVAL(env):
             else
                 $list[0] as $elem |
                 $list[1:] as $rest |
-                    $elem[1] | EVAL($env) as $resv |
-                        { value: [$elem[0], $resv.expr], env: env },
+                    $elem.value.value | EVAL($env) as $resv |
+                        {
+                            value: {
+                                key: $elem.key,
+                                value: { kkind: $elem.value.kkind, value: $resv.expr }
+                            },
+                            env: env
+                        },
                         ({env: $resv.env, list: $rest} | hmap_with_env)
             end;
     def map_with_env:
@@ -93,7 +99,7 @@ def EVAL(env):
                             (reduce ($value[1].value | nwise(2)) as $xvalue (
                                 $subenv;
                                 . as $env | $xvalue[1] | EVAL($env) as $expenv |
-                                    env_set6($expenv.env; $xvalue[0].value; $expenv.expr))) as $env
+                                    env_set_($expenv.env; $xvalue[0].value; $expenv.expr))) as $env
                                         | $value[2] | { expr: EVAL($env).expr, env: env }
                 ) //
                 (
@@ -128,13 +134,10 @@ def EVAL(env):
                 ) //
                 (
                     reduce .value[] as $elem (
-                        {value: [], env: env};
-                        . as $dot | $elem | EVAL($dot.env) as $eval_env |
-                            {
-                                value: ($dot.value + [$eval_env.expr]),
-                                env: $eval_env.env
-                            }
-                    ) | { expr: .value, env: .env } as $ev
+                        [];
+                        . as $dot | $elem | EVAL(env) as $eval_env |
+                            ($dot + [$eval_env.expr])
+                    ) | { expr: ., env: env } as $ev
                         | $ev.expr | first |
                             interpret($ev.expr[1:]; $ev.env; _eval_here)
                 ) //
@@ -157,7 +160,7 @@ def EVAL(env):
         end
     ) //
     (select(.kind == "hashmap") |
-        [ { env: env, list: .value | to_entries } | hmap_with_env ] as $res |
+        [ { env: env, list: (.value | to_entries) } | hmap_with_env ] as $res |
         {
             kind: "hashmap",
             value: $res | map(.value) | from_entries
@@ -236,4 +239,6 @@ repl(
     | wrapEnv
     | eval_ign("(def! not (fn* (a) (if a false true)))")
     | eval_ign("(def! load-file (fn* (f) (eval (read-string (str \"(do \" (slurp f) \"\\nnil)\")))))))")
+    | . as $env 
+    | env_set_($env; "*ARGV*"; $ARGS.positional | wrap("list"))
 )
\ No newline at end of file
index 5bc6621..e417f1d 100644 (file)
@@ -19,6 +19,12 @@ def wrap(kind):
         value: .
     };
 
+def wrap2(kind; opts):
+    opts + {
+        kind: kind,
+        value: .
+    };
+
 def _extern(options):
     {command: .} 
     | debug
@@ -41,6 +47,15 @@ def _print:
 
 def _write_to_file(name):
     . as $value
-    | [name, .|tojson]
+    | [(name|tojson), (.|tojson), (false|tojson)]
     | issue_extern("fwrite"; {nowait: true})
-    | $value;
\ No newline at end of file
+    | $value;
+
+def _append_to_file(name):
+    . as $value
+    | [(name|tojson), (.|tojson), (true|tojson)]
+    | issue_extern("fwrite"; {nowait: true})
+    | $value;
+
+def trap:
+    _write_to_file("trap_reason.json") | jqmal_error("trap");
\ No newline at end of file