From 56644c1bb18f3befaaf0b8608aaaeb346a012504 Mon Sep 17 00:00:00 2001 From: Chris Zheng Date: Wed, 8 Jan 2025 07:15:18 +1100 Subject: [PATCH] adding some tests --- src-build/meta/gen_big_file.clj | 50 ++++ src/std/lang/base/compile.clj | 28 +-- src/std/lang/model/spec_js.clj | 2 +- src/xt/demo/brainfuck.clj | 79 ++++++ src/xt/demo/fizzbuzz.clj | 31 +++ src/xt/runtime/type_hashmap.clj | 266 +++++++++++++++------ src/xt/runtime/type_hashmap_node.clj | 176 +++++++++++--- test/std/lang/base/compile_test.clj | 45 ++-- test/xt/demo/brainfuck_test.clj | 6 + test/xt/demo/fizzbuzz_test.clj | 17 ++ test/xt/runtime/type_hashmap_node_test.clj | 195 +++++++++++++++ test/xt/runtime/type_hashmap_test.clj | 133 +++++++++++ test/xt/runtime/type_syntax_test.clj | 5 +- 13 files changed, 900 insertions(+), 133 deletions(-) create mode 100644 src-build/meta/gen_big_file.clj create mode 100644 src/xt/demo/brainfuck.clj create mode 100644 src/xt/demo/fizzbuzz.clj create mode 100644 test/xt/demo/brainfuck_test.clj create mode 100644 test/xt/demo/fizzbuzz_test.clj create mode 100644 test/xt/runtime/type_hashmap_node_test.clj create mode 100644 test/xt/runtime/type_hashmap_test.clj diff --git a/src-build/meta/gen_big_file.clj b/src-build/meta/gen_big_file.clj new file mode 100644 index 0000000..9873352 --- /dev/null +++ b/src-build/meta/gen_big_file.clj @@ -0,0 +1,50 @@ +(ns concat-files + (:require [std.fs :as fs] + [clojure.java.io :as io])) + +(def +all-files+ + (sort (keys (fs/list "src" {:recursive true + :include [".clj$"]})))) + +(defn concat-files + [& [file-filter out-file dir root]] + (let [out-file (or out-file "output.clj") + root (or root ".") + root-path (fs/path root) + dir (or dir "src") + proj-file "project.clj"] + (with-open [writer (io/writer out-file)] + (let [all-paths (cons (str (fs/path root proj-file)) + (sort (keys (fs/list (fs/path root dir) + {:recursive true + :include [(or file-filter ".clj$")]}))))] + + (doseq [p all-paths] + (let [relative-path (fs/relativize root-path p)] + (.write writer (str "\n\n\n;;; ------- " relative-path "------- \n\n\n")) + (try (with-open [r (io/reader p)] + (doseq [line (line-seq r)] + (.write writer ^String line) + (.write writer "\n"))) + (catch Throwable t)))))))) + +(comment + (concat-files) + + (fs/list (fs/path "test") + {:recursive true + :include [".clj$"]}) + (concat-files nil + "output-xtalk.clj" + "src/xt") + (concat-files nil + "output-tests.clj" + "test") + + + (concat-files ".clj$" + "output-xtalk.clj" + "../statstrade-core/src/statsdb" + "../statstrade-core") + + ) diff --git a/src/std/lang/base/compile.clj b/src/std/lang/base/compile.clj index 76d8568..ae164b5 100755 --- a/src/std/lang/base/compile.clj +++ b/src/std/lang/base/compile.clj @@ -102,20 +102,20 @@ (defn compile-module-schema "compiles all namespaces into a single file (for sql)" {:added "4.0"} - ([{:keys [header footer lang main root target] :as opts}] - (let [mopts (last (impl/emit-options opts)) - lib (impl/runtime-library) - snapshot (lib/get-snapshot lib) - book (snap/get-book snapshot lang) - deps (h/deps:ordered book [main]) - full-arr (map (fn [module-id] - (-> (lifecycle/emit-module-setup module-id - mopts) - (compile/compile-fullbody opts))) - deps) - full (str/join "\n\n" full-arr) - output (compile/compile-out-path opts)] - (compile/compile-write output full)))) + ([{:keys [header footer lang main root target] :as opts}] + (let [mopts (last (impl/emit-options opts)) + lib (impl/runtime-library) + snapshot (lib/get-snapshot lib) + book (snap/get-book snapshot lang) + deps (h/deps:ordered book [main]) + full-arr (map (fn [module-id] + (-> (lifecycle/emit-module-setup module-id + mopts) + (compile/compile-fullbody opts))) + deps) + full (str/join "\n\n" full-arr) + output (compile/compile-out-path opts)] + (compile/compile-write output full)))) (def +install-module-schema-fn+ (compile/types-add :module.schema #'compile-module-schema)) diff --git a/src/std/lang/model/spec_js.clj b/src/std/lang/model/spec_js.clj index e54df58..8e90e21 100755 --- a/src/std/lang/model/spec_js.clj +++ b/src/std/lang/model/spec_js.clj @@ -11,7 +11,7 @@ [std.lang.base.grammar :as grammar] [std.lang.base.grammar-spec :as spec] [std.lang.base.util :as ut] - [std.lang.base.book :as book] + [std.lang.base.book :as book] [std.lang.base.script :as script] [std.lang.model.spec-xtalk] [std.lang.model.spec-xtalk.fn-js :as fn] diff --git a/src/xt/demo/brainfuck.clj b/src/xt/demo/brainfuck.clj new file mode 100644 index 0000000..a1448a9 --- /dev/null +++ b/src/xt/demo/brainfuck.clj @@ -0,0 +1,79 @@ +(ns xt.demo.brainfuck + (:require [std.lang :as l] + [std.lib :as h])) + +(l/script :xtalk + {:require [[xt.lang.base-lib :as k]] + :export [MODULE]}) + +(defn.xt brainfuck-interpreter + "Interprets and executes Brainfuck code" + {:added "1.0"} + [bfCode] + ;; Initialize memory, pointer, and output + (var memory {}) + (k/for:index [i [(x:offset 0) + (x:offset 30000)]] + (= (. memory [i]) 0)) + (var output "") + (var codeLength (k/len bfCode)) + (var i 0) ;; Instruction pointer + + ;; Execute Brainfuck commands + (while (< i codeLength) + (var command (k/get-idx bfCode i)) + (cond + ;; Increment the pointer + (== command ">") (:= pointer (+ pointer 1)) + + ;; Decrement the pointer + (== command "<") (:= pointer (- pointer 1)) + + ;; Increment the value at the current cell + (== command "+") + (k/set-idx memory pointer (mod (+ (k/get-idx memory pointer) 1) 256)) + + ;; Decrement the value at the current cell + (== command "-") + (k/set-idx memory pointer (mod (- (+ (k/get-idx memory pointer) 256) 1) 256)) + + ;; Output the character at the current cell + (== command ".") + (:= output (k/cat output (k/char (k/get-idx memory pointer)))) + + ;; Input a character into the current cell + (== command ",") + (do + (var input (k/read "Input a character:")) + (k/set-idx memory pointer (:? input (k/char-code (k/first input)) 0))) + + ;; Jump forward if the current cell is 0 + (== command "[") + (if (== (k/get-idx memory pointer) 0) + (do + (var bracketCounter 1) + (while (> bracketCounter 0) + (:= i (+ i 1)) + (if (== (k/get-idx bfCode i) "[") + (:= bracketCounter (+ bracketCounter 1))) + (if (== (k/get-idx bfCode i) "]") + (:= bracketCounter (- bracketCounter 1)))))) + + ;; Jump backward if the current cell is non-zero + (== command "]") + (if (not= (k/get-idx memory pointer) 0) + (do + (var bracketCounter 1) + (while (> bracketCounter 0) + (:= i (- i 1)) + (if (== (k/get-idx bfCode i) "]") + (:= bracketCounter (+ bracketCounter 1))) + (if (== (k/get-idx bfCode i) "[") + (:= bracketCounter (- bracketCounter 1)))))))) + ;; Move to the next instruction + (:= i (+ i 1)) + + ;; Return the output + (return output)) + +(def.xt MODULE (!:module)) diff --git a/src/xt/demo/fizzbuzz.clj b/src/xt/demo/fizzbuzz.clj new file mode 100644 index 0000000..dd15883 --- /dev/null +++ b/src/xt/demo/fizzbuzz.clj @@ -0,0 +1,31 @@ +(ns xt.demo.fizzbuzz + (:require [std.lang :as l] + [std.lib :as h])) + +(l/script :xtalk + {:require [[xt.lang.base-lib :as k]] + :export [MODULE]}) + +(defn.xt fizzbuzz + "Generates FizzBuzz for numbers from 1 to n" + {:added "1.0"} + [n] + ;; Initialize an empty array for results + (var result []) + ;; Iterate through numbers 1 to n + (k/for:index [i [1 (+ n 1) 1]] + (var value nil) + ;; Check divisibility for FizzBuzz + (if (and (== 0 (mod i 3)) (== 0 (mod i 5))) + (:= value "FizzBuzz") + (if (== 0 (mod i 3)) + (:= value "Fizz") + (if (== 0 (mod i 5)) + (:= value "Buzz") + (:= value i)))) + ;; Append the value to the result array + (x:arr-push result value)) + ;; Return the result array + (return result)) + +(def.xt MODULE (!:module)) diff --git a/src/xt/runtime/type_hashmap.clj b/src/xt/runtime/type_hashmap.clj index de394bc..ee0ebe7 100644 --- a/src/xt/runtime/type_hashmap.clj +++ b/src/xt/runtime/type_hashmap.clj @@ -1,89 +1,211 @@ -^{:no-test true} (ns xt.runtime.type-hashmap (:require [std.lang :as l] [std.lib :as h])) (l/script :xtalk {:require [[xt.lang.base-lib :as k] - [xt.lang.base-iter :as it] - [xt.runtime.interface-common :as data-common]] + [xt.runtime.interface-spec :as spec] + [xt.runtime.interface-collection :as interface-collection] + [xt.runtime.type-hashmap-node :as node] + [xt.runtime.common-hash :as hash] + [xt.lang.base-iter :as iter]] :export [MODULE]}) -(def.xt BITS 5) -(def.xt WIDTH (k/pow 2 -/BITS)) -(def.xt MASK (- -/WIDTH 1)) +;; HashMap Implementation -(defn.xt impl-mask - [hash shift] - (return (k/bit-and (k/bit-rshift hash shift) - -/MASK))) +(defn.xt hashmap-create + "Creates a new hashmap" + {:added "4.0"} + [root size] + (var hashmap {"::" "hashmap" + :_root root + :_size size}) + (return hashmap)) -(defn.xt impl-bitpos - [hash shift] - (return (k/bit-lshift 1 (-/impl-mask hash shift)))) +(defn.xt hashmap-empty + "Creates an empty hashmap" + {:added "4.0"} + [] + (return (-/hashmap-create node/EMPTY_HASHMAP_NODE 0))) -(defn.xt impl-edit-allowed - [edit-0 edit-1] - (return (and (k/not-nil? edit-0) - (== edit-0 edit-1)))) +(defn.xt hashmap-find + "Finds a value by key" + {:added "4.0"} + [hashmap key] + (var #{_root} hashmap) + (var hash (hash/hash-native key)) + (return (node/node-find-entry _root key hash 0))) -(defn.xt impl-copy-without - []) +(defn.xt hashmap-assoc + "Associates a key-value pair in the hashmap" + {:added "4.0"} + [hashmap key val] + (var #{_root _size} hashmap) + (var hash (hash/hash-native key)) + (var new-root (node/node-insert _root key val hash 0 false)) + (var new-size (:? (k/not-nil? (node/node-find-entry _root key hash 0)) + _size + (+ _size 1))) + (return (-/hashmap-create new-root new-size))) -;; -;; -;; +(defn.xt hashmap-dissoc + "Dissociates a key-value pair from the hashmap" + {:added "4.0"} + [hashmap key] + (var #{_root _size} hashmap) + (var hash (hash/hash-native key)) + (when (k/nil? (node/node-find-entry _root key hash 0)) + (return hashmap)) + (var new-root (node/node-delete _root key hash 0 false)) + (return (-/hashmap-create new-root (- _size 1)))) -(comment +(defn.xt hashmap-size + "Returns the size of the hashmap" + {:added "4.0"} + [hashmap] + (var #{_size} hashmap) + (return _size)) + +(defgen.xt hashmap-to-iter + "Converts hashmap to iterator" + {:added "4.0"} + [hashmap] + (var #{_root} hashmap) + (iter/for:iter [[key val] _root] + (yield [key val]))) + +(defn.xt hashmap-to-array + "Converts hashmap to an array of key-value pairs" + {:added "4.0"} + [hashmap] + (var #{_root} hashmap) + (var out []) + (iter/for:iter [[key val] _root] + (x:arr-push out [key val])) + (return out)) + +;; Interface Specification + +(def.xt HASHMAP_SPEC + [[spec/IColl {:to-iter -/hashmap-to-iter + :to-array -/hashmap-to-array}] + [spec/IEmpty {:empty -/hashmap-empty}] + [spec/ISize {:size -/hashmap-size}] + [spec/IFind {:find -/hashmap-find}] + [spec/IAssoc {:assoc -/hashmap-assoc}] + [spec/IDissoc {:dissoc -/hashmap-dissoc}]]) + +(def.xt HASHMAP_PROTOTYPE + (-> -/HASHMAP_SPEC + (k/proto-spec) + (k/proto-create))) + +(defn.xt hashmap-new + "Creates a new hashmap with the given key-value pairs" + {:added "4.0"} + [pairs] + (var hashmap (-/hashmap-empty)) + (k/for:array [[key val] pairs] + (:= hashmap (-/hashmap-assoc hashmap key val))) + (return hashmap)) - (defn.xt data-node-create - [edit-id shift leaf] - (return - {"::" "hashmap.node" - :bitmap (-/impl-mask (k/get-key leaf "hash") shift) - :nodemap (-/impl-mask (k/get-key leaf "hash") shift) - :nodes [leaf] - :shift shift})) - - (defn.xt data-node-create - [edit-id shift leaf] - (return - {"::" "hashmap.node" - :bitmap (-/impl-mask (k/get-key leaf "hash") shift) - :nodes [leaf] - :shift shift})) - - (defn.xt node-create - "creates a new node" - {:added "4.0"} - [edit-id children] - (var out {"::" "vector.node" - :children children}) - (when (k/not-nil? edit-id) - (k/set-key out "edit_id" edit-id)) - (return out)) - - (defn.xt node-clone - "clones the node" - {:added "4.0"} - [node] - (var #{edit-id children} node) - (return (-/node-create edit-id - (k/arr-clone children)))) - - (defn.xt node-editable-root - "creates an editable root" - {:added "4.0"} - [node] - (var #{children} node) - (return (-/node-create (k/random) (k/arr-clone children)))) - - (defn.xt node-editable - "creates an editable node" - {:added "4.0"} - [node edit-id] - (return (:? (== edit-id (k/get-key node "edit_id")) - node - (-/node-clone node))))) +;; Constants +(def.xt EMPTY_HASHMAP + (-/hashmap-empty)) +;; Module Export (def.xt MODULE (!:module)) + + + +(comment + ^{:no-test true} + (ns xt.runtime.type-hashmap + (:require [std.lang :as l] + [std.lib :as h])) + + (l/script :xtalk + {:require [[xt.lang.base-lib :as k] + [xt.lang.base-iter :as it] + [xt.runtime.interface-common :as data-common]] + :export [MODULE]}) + + (def.xt BITS 5) + (def.xt WIDTH (k/pow 2 -/BITS)) + (def.xt MASK (- -/WIDTH 1)) + + (defn.xt impl-mask + [hash shift] + (return (k/bit-and (k/bit-rshift hash shift) + -/MASK))) + + (defn.xt impl-bitpos + [hash shift] + (return (k/bit-lshift 1 (-/impl-mask hash shift)))) + + (defn.xt impl-edit-allowed + [edit-0 edit-1] + (return (and (k/not-nil? edit-0) + (== edit-0 edit-1)))) + + (defn.xt impl-copy-without + []) + + ;; + ;; + ;; + + (comment + + (defn.xt data-node-create + [edit-id shift leaf] + (return + {"::" "hashmap.node" + :bitmap (-/impl-mask (k/get-key leaf "hash") shift) + :nodemap (-/impl-mask (k/get-key leaf "hash") shift) + :nodes [leaf] + :shift shift})) + + (defn.xt data-node-create + [edit-id shift leaf] + (return + {"::" "hashmap.node" + :bitmap (-/impl-mask (k/get-key leaf "hash") shift) + :nodes [leaf] + :shift shift})) + + (defn.xt node-create + "creates a new node" + {:added "4.0"} + [edit-id children] + (var out {"::" "vector.node" + :children children}) + (when (k/not-nil? edit-id) + (k/set-key out "edit_id" edit-id)) + (return out)) + + (defn.xt node-clone + "clones the node" + {:added "4.0"} + [node] + (var #{edit-id children} node) + (return (-/node-create edit-id + (k/arr-clone children)))) + + (defn.xt node-editable-root + "creates an editable root" + {:added "4.0"} + [node] + (var #{children} node) + (return (-/node-create (k/random) (k/arr-clone children)))) + + (defn.xt node-editable + "creates an editable node" + {:added "4.0"} + [node edit-id] + (return (:? (== edit-id (k/get-key node "edit_id")) + node + (-/node-clone node))))) + + (def.xt MODULE (!:module)) + ) diff --git a/src/xt/runtime/type_hashmap_node.clj b/src/xt/runtime/type_hashmap_node.clj index fc3f701..03dc705 100644 --- a/src/xt/runtime/type_hashmap_node.clj +++ b/src/xt/runtime/type_hashmap_node.clj @@ -1,48 +1,170 @@ -^{:no-test true} + (ns xt.runtime.type-hashmap-node (:require [std.lang :as l] [std.lib :as h])) (l/script :xtalk - {:require [[xt.lang.base-lib :as k] - [xt.lang.base-iter :as it] - [xt.runtime.interface-common :as data-common]] + {:require [[xt.lang.base-lib :as k]] :export [MODULE]}) -(def.xt BITS 5) -(def.xt WIDTH (k/pow 2 -/BITS)) -(def.xt MASK (- -/WIDTH 1)) +;; Basic Definitions +(def.xt HASHMAP_BITS 5) +(def.xt HASHMAP_MASK (- (k/pow 2 -/HASHMAP_BITS) 1)) -(defn.xt impl-mask +;; Masks a hash value to fit within a node +(defmacro.xt impl-mask + "Masks a hash value to the appropriate range" + {:added "4.0"} [hash shift] - (return (k/bit-and (k/bit-rshift hash shift) - -/MASK))) + (list 'x:bit-and (list 'x:bit-rshift hash shift) `-/HASHMAP_MASK)) -(defn.xt impl-bitpos - [hash shift] - (return (k/bit-lshift 1 (-/impl-mask hash shift)))) +(defn.xt impl-assoc-entry + "associates a key-value pair in an array of key-value pairs" + {:added "4.0"} + [entry key val] + (var updated false) + (var result + (k/arr-map + entry + (fn [pair] + (if (== (k/first pair) key) + (do (:= updated true) + (return [key val])) + (return pair))))) + (if updated + (return result) + (do (x:arr-push result [key val]) + (return result)))) -(defn.xt impl-edit-allowed - [edit-0 edit-1] - (return (and (k/not-nil? edit-0) - (== edit-0 edit-1)))) +(defn.xt impl-dissoc-entry + "dissociates a key from an array of key-value pairs" + {:added "4.0"} + [entry key] + (return (k/arr-filter entry (fn:> [pair] (not= (k/first pair) key))))) +;; Node Operations (defn.xt node-create - "creates a new node" + "creates a new hashmap node" {:added "4.0"} - [edit-id bitmap children] - (var out {"::" "hashmap.node" - :bitmap bitmap - :children children}) + [edit-id entries] + (var node {"::" "hashmap.node" + "entries" entries}) (when (k/not-nil? edit-id) - (k/set-key out "edit_id" edit-id)) - (return out)) + (k/set-key node "edit_id" edit-id)) + (return node)) + +(defn.xt node-clone + "clones a hashmap node" + {:added "4.0"} + [node] + (var #{edit-id entries} node) + (return (-/node-create edit-id (k/arr-clone entries)))) + +(defn.xt ensure-editable + "ensures a node is editable" + {:added "4.0"} + [node] + (var #{edit-id} node) + (when (k/nil? edit-id) + (k/err "Node is not editable"))) + +(defn.xt ensure-persistent + "ensures a node is persistent" + {:added "4.0"} + [node] + (var #{edit-id entries} node) + (cond (k/nil? edit-id) + (return node) + + :else + (return (-/node-create nil (k/arr-clone entries))))) -(defn.xt node-set- - "creates a new node" +;; Lookup +(defn.xt node-find-entry + "finds an entry in the node" {:added "4.0"} - [node edit-id idx val]) + [node key hash shift] + (var #{entries} node) + (var idx (-/impl-mask hash shift)) ;; Calculate the index in the entries array + (var entry (k/get-idx entries (x:offset idx))) ;; Retrieve the entry at the index + (cond (k/nil? entry) ;; If no entry exists at the index, return nil + (return nil) + (and (k/is-object? entry) (k/get-key entry "::")) ;; If the entry is another hashmap node + (return (-/node-find-entry entry key hash (+ shift -/HASHMAP_BITS))) + + (== (k/first entry) key) + (return (k/second entry)))) +;; Insertion +(defn.xt node-insert + "inserts a key-value pair into the node" + {:added "4.0"} + [node key val hash shift editable] + (when editable + (-/ensure-editable node)) + + (var #{edit-id entries} node) + (var idx (k/x:offset (-/impl-mask hash shift))) + (var entry (k/get-idx entries idx)) + + (cond + (k/nil? entry) + (do (var new-entry [key val]) + (k/set-idx entries idx new-entry) + (return node)) + + (k/is-array? entry) + (do (k/set-idx entries idx (-/impl-assoc-entry entry key val)) + (return node)) + + (and (k/is-object? entry) + (k/get-key entry "::")) + (do (var new-child (-/node-insert entry key val hash (+ shift -/HASHMAP_BITS) editable)) + (k/set-idx entries idx new-child) + (return node)) + + :else + (do (var child (-/node-create edit-id [])) + (k/set-idx entries idx (-/node-insert child key val hash (+ shift -/HASHMAP_BITS) editable)) + (return node)))) + +;; Deletion +(defn.xt node-delete + "deletes a key-value pair from the node" + {:added "4.0"} + [node key hash shift editable] + (when editable + (-/ensure-editable node)) + + (var #{edit-id entries} node) + (var idx (k/x:offset (-/impl-mask hash shift))) + (var entry (k/get-idx entries idx)) + + (cond + (k/nil? entry) (return node) + + (and (k/is-object? entry) + (k/get-key entry "::")) + (do (var new-child (-/node-delete entry key hash (+ shift -/HASHMAP_BITS) editable)) + (if (k/is-empty? new-child) + (do (k/set-idx entries idx nil) + (return node)) + (do (k/set-idx entries idx new-child) + (return node)))) + + (k/is-array? entry) + (do (k/set-idx entries idx nil) + (return node)) + + :else + (return node))) + +;; Constants +(def.xt EMPTY_HASHMAP_NODE + (-/node-create nil [])) + +;; Module Export (def.xt MODULE (!:module)) + diff --git a/test/std/lang/base/compile_test.clj b/test/std/lang/base/compile_test.clj index 8630019..425710c 100755 --- a/test/std/lang/base/compile_test.clj +++ b/test/std/lang/base/compile_test.clj @@ -1,6 +1,7 @@ (ns std.lang.base.compile-test (:use code.test) - (:require [std.lang.base.compile :refer :all])) + (:require [std.lang.base.compile :refer :all] + [std.make.compile :as compile])) ^{:refer std.lang.base.compile/compile-script :added "4.0"} (fact "compiles a script") @@ -20,7 +21,7 @@ (fact "compiles a script with dependencies when given a " ^:hidden - (with:mock-compile + (compile/with:mock-compile (compile-script {:root ".build" :target "src" :file "pkg/file.lua" @@ -59,33 +60,43 @@ " end,nil,seq)" " return out" "end")]) - + ^{:refer std.make.compile/compile-module :added "4.0"} (fact "compiles a module" ^:hidden - - (with:mock-compile - (compile-module 'L.core - {:lang :lua - :root ".build" - :target "src" - :file "pkg/file.lua"})) + (compile/with:mock-compile + (compile-module-single + {:lang :lua + :root ".build" + :target "src" + :file "pkg/file.lua" + :main 'L.core})) => (contains [".build/src/pkg/file.lua" string?])) - + ^{:refer std.make.compile/compile-graph :added "4.0"} (fact "compiles a root module and all dependencies" ^:hidden (require 'js.blessed.form-test) - (with:mock-compile - (compile-graph - {:lang :js - :main 'js.blessed.form-test - :root ".build" - :target "src"})) + (compile/with:mock-compile + (compile-module-graph + {:lang :js + :main 'js.blessed.form-test + :root ".build" + :target "src"})) + => coll? + + + (require 'js.blessed.form-test) + (compile/with:mock-compile + (compile-module-single + {:lang :js + :main 'js.blessed.form-test + :root ".build" + :target "src"})) => coll?) ^{:refer std.make.compile/compile-schema :added "4.0"} diff --git a/test/xt/demo/brainfuck_test.clj b/test/xt/demo/brainfuck_test.clj new file mode 100644 index 0000000..5da733e --- /dev/null +++ b/test/xt/demo/brainfuck_test.clj @@ -0,0 +1,6 @@ +(ns xt.demo.brainfuck-test + (:use code.test) + (:require [xt.demo.brainfuck :refer :all])) + +^{:refer xt.demo.brainfuck/brainfuck-compiler :added "4.0"} +(fact "TODO") \ No newline at end of file diff --git a/test/xt/demo/fizzbuzz_test.clj b/test/xt/demo/fizzbuzz_test.clj new file mode 100644 index 0000000..b0db3bd --- /dev/null +++ b/test/xt/demo/fizzbuzz_test.clj @@ -0,0 +1,17 @@ +(ns xt.demo.fizzbuzz-test + (:use code.test) + (:require [std.lang :as l] + [std.lib :as h])) + +(l/script- :js + {:runtime :basic + :require [[xt.demo.fizzbuzz :as fb]]}) + +^{:refer xt.demo.fizzbuzz/fizzbuzz :added "4.0"} +(fact "look at fizzbuzz" + ^:hidden + + (l/with:print + (fb/fizzbuzz 20)) + => [1 2 "Fizz" 4 "Buzz" "Fizz" 7 8 "Fizz" "Buzz" 11 "Fizz" 13 14 "FizzBuzz" 16 17 "Fizz" 19 "Buzz"]) + diff --git a/test/xt/runtime/type_hashmap_node_test.clj b/test/xt/runtime/type_hashmap_node_test.clj new file mode 100644 index 0000000..55a4f3c --- /dev/null +++ b/test/xt/runtime/type_hashmap_node_test.clj @@ -0,0 +1,195 @@ +(ns xt.runtime.type-hashmap-node-test + (:use code.test) + (:require [std.lang :as l] + [std.lib :as h] + [xt.lang.base-notify :as notify])) + +(l/script- :js + {:runtime :basic + :require [[xt.runtime.type-hashmap-node :as node] + [xt.runtime.common-hash :as hash] + [xt.lang.base-lib :as k] + [xt.lang.base-iter :as it] + [xt.lang.base-repl :as repl]]}) + +(l/script- :lua + {:runtime :basic + :require [[xt.runtime.type-hashmap-node :as node] + [xt.runtime.common-hash :as hash] + [xt.lang.base-lib :as k] + [xt.lang.base-iter :as it] + [xt.lang.base-repl :as repl]]}) + +(fact:global + {:setup [(l/rt:restart)] + :teardown [(l/rt:stop)]}) + + +^{:refer xt.runtime.type-hashmap-node/impl-mask :added "4.0"} +(fact "Masks a hash value to the appropriate range" + ^:hidden + + (!.js + [(node/impl-mask 123456789 5) + (node/impl-mask 0xFFFFFFFF 10)]) + => [8 31] + + (!.lua + [(node/impl-mask 123456789 5) + (node/impl-mask 0xFFFFFFFF 10)]) + => [8 31]) + +^{:refer xt.runtime.type-hashmap-node/impl-assoc-entry :added "4.0"} +(fact "associates a key-value pair in an array of key-value pairs" + ^:hidden + + (!.js + [(node/impl-assoc-entry [["k1" "v1"] ["k2" "v2"]] "k1" "NEW") + (node/impl-assoc-entry [["k1" "v1"]] "k2" "v2")]) + => [[["k1" "NEW"] ["k2" "v2"]] + [["k1" "v1"] ["k2" "v2"]]] + + (!.lua + [(node/impl-assoc-entry [["k1" "v1"] ["k2" "v2"]] "k1" "NEW") + (node/impl-assoc-entry [["k1" "v1"]] "k2" "v2")]) + => [[["k1" "NEW"] ["k2" "v2"]] + [["k1" "v1"] ["k2" "v2"]]]) + +^{:refer xt.runtime.type-hashmap-node/impl-dissoc-entry :added "4.0"} +(fact "dissociates a key from an array of key-value pairs" + ^:hidden + + (!.js + [(node/impl-dissoc-entry [["k1" "v1"] ["k2" "v2"]] "k1") + (node/impl-dissoc-entry [["k1" "v1"] ["k2" "v2"]] "k3")]) + => [[["k2" "v2"]] + [["k1" "v1"] ["k2" "v2"]]] + + (!.lua + [(node/impl-dissoc-entry [["k1" "v1"] ["k2" "v2"]] "k1") + (node/impl-dissoc-entry [["k1" "v1"] ["k2" "v2"]] "k3")]) + => [[["k2" "v2"]] + [["k1" "v1"] ["k2" "v2"]]]) + +^{:refer xt.runtime.type-hashmap-node/node-create :added "4.0"} +(fact "creates a new hashmap node" + ^:hidden + + (!.js + (node/node-create nil [])) + => {"::" "hashmap.node", "entries" []} + + (!.lua + (node/node-create nil [])) + => {"::" "hashmap.node", "entries" {}}) + +^{:refer xt.runtime.type-hashmap-node/node-clone :added "4.0"} +(fact "clones a hashmap node" + ^:hidden + (!.js + (node/node-clone + (node/node-create nil [["k1" "v1"]]))) + => {"::" "hashmap.node", "entries" [["k1" "v1"]]} + + (!.lua + (node/node-clone + (node/node-create nil [["k1" "v1"]]))) + => {"::" "hashmap.node", "entries" [["k1" "v1"]]}) + +^{:refer xt.runtime.type-hashmap-node/ensure-editable :added "4.0"} +(fact "ensures a node is editable" + ^:hidden + + (!.js + (node/ensure-editable + (node/node-create nil []))) + => (throws) + + (!.lua + (node/ensure-editable + (node/node-create nil []))) + => (throws)) + +^{:refer xt.runtime.type-hashmap-node/ensure-persistent :added "4.0"} +(fact "ensures a node is persistent" + ^:hidden + + (!.js + (node/ensure-persistent (node/node-create nil []))) + => {"::" "hashmap.node", "entries" []} + + (!.lua + (node/ensure-persistent (node/node-create nil []))) + => {"::" "hashmap.node", "entries" {}}) + +^{:refer xt.runtime.type-hashmap-node/node-find-entry :added "4.0"} +(fact "finds an entry in the node" + ^:hidden + + (!.js + (-> (node/node-create nil []) + (node/node-insert "key1" "val1" (hash/hash-native "key1") 0 false) + (node/node-insert "key2" "val2" (hash/hash-native "key2") 0 false) + (node/node-find-entry "key1" (hash/hash-native "key1") 0))) + => "val1" + + (!.lua + (-> (node/node-create nil []) + (node/node-insert "key1" "val1" (hash/hash-native "key1") 0 false) + (node/node-insert "key2" "val2" (hash/hash-native "key2") 0 false) + (node/node-find-entry "key1" (hash/hash-native "key1") 0))) + => "val1") + + + + + +{"::" "hashmap.node", "entries" [nil nil nil nil nil nil nil ["key1" "val1"]]} +{"::" "hashmap.node", "entries" [nil nil nil nil nil nil nil ["key1" "val1"]]} + +(!.lua + (var n (node/node-create nil [])) + (node/node-insert n "key1" "val1" (hash/hash-native "key1") 0 false + ) + n) + + + +(node/impl-mask (hash/hash-native "key1") 0) + +^{:refer xt.runtime.type-hashmap-node/node-insert :added "4.0"} +(fact "inserts a key-value pair into the node" + ^:hidden + + (!.lua + (-> (node/node-create nil []) + (node/node-insert "key1" "val1" (hash/hash-native "key1") 0 false))) + => {"::" "hashmap.node", "entries" [nil nil nil nil nil nil nil ["key1" "val1"]]} + + (!.js + (-> (node/node-create nil []) + (node/node-insert "key1" "val1" (hash/hash-native "key1") 0 false) + (node/node-insert "key2" "val2" (hash/hash-native "key2") 0 false))) + => {"::" "hashmap.node", + "entries" [nil nil nil nil nil nil nil ["key1" "val1"] nil nil nil nil nil nil + nil nil nil nil nil nil nil nil nil nil nil nil ["key2" "val2"]]}) + +^{:refer xt.runtime.type-hashmap-node/node-delete :added "4.0"} +(fact "deletes a key-value pair from the node" + ^:hidden + + (!.js + (-> (node/node-create nil []) + (node/node-insert "key1" "val1" (hash/hash-native "key1") 0 false) + (node/node-insert "key2" "val2" (hash/hash-native "key2") 0 false) + (node/node-insert "key3" "val3" (hash/hash-native "key3") 0 false) + (node/node-delete "key1" (hash/hash-native "key1") 0 false))) + => {"::" "hashmap.node", "entries" [nil nil nil nil nil nil nil nil nil nil nil nil nil ["key3" "val3"] + nil nil nil nil nil nil nil nil nil nil nil nil ["key2" "val2"]]} + + (!.lua + (-> (node/node-create nil []) + (node/node-insert "key1" "val1" (hash/hash-native "key1") 0 false) + (node/node-insert "key2" "val2" (hash/hash-native "key2") 0 false) + (node/node-delete "key2" (hash/hash-native "key2") 0 false))) + => {"::" "hashmap.node", "entries" [nil nil nil nil nil nil nil ["key1" "val1"]]}) diff --git a/test/xt/runtime/type_hashmap_test.clj b/test/xt/runtime/type_hashmap_test.clj new file mode 100644 index 0000000..5370ad4 --- /dev/null +++ b/test/xt/runtime/type_hashmap_test.clj @@ -0,0 +1,133 @@ +(ns xt.runtime.type-hashmap-test + (:use code.test) + (:require [std.lang :as l] + [std.lib :as h] + [xt.lang.base-notify :as notify])) + +(l/script- :js + {:runtime :basic + :require [[xt.runtime.type-hashmap :as hashmap] + [xt.runtime.type-hashmap-node :as node] + [xt.lang.base-lib :as k] + [xt.lang.base-iter :as it] + [xt.lang.base-repl :as repl]]}) + +(l/script- :lua + {:runtime :basic + :require [[xt.runtime.type-hashmap :as hashmap] + [xt.runtime.type-hashmap-node :as node] + [xt.lang.base-lib :as k] + [xt.lang.base-iter :as it] + [xt.lang.base-repl :as repl]]}) + +(fact:global + {:setup [(l/rt:restart)] + :teardown [(l/rt:stop)]}) + +^{:refer xt.runtime.type-hashmap/hashmap-create :added "4.0"} +(fact "creates a new hashmap" + ^:hidden + (!.js + (hashmap/hashmap-create {} 0)) + => {"::" "hashmap", "_root" {}, "_size" 0} + + (!.lua + (hashmap/hashmap-create {} 0)) + => {"::" "hashmap", "_root" {}, "_size" 0}) + +^{:refer xt.runtime.type-hashmap/hashmap-empty :added "4.0"} +(fact "creates an empty hashmap" + ^:hidden + + (!.js + (hashmap/hashmap-empty)) + => {"::" "hashmap", "_size" 0, "_root" {"::" "hashmap.node", "entries" []}} + + (!.lua + (hashmap/hashmap-empty)) + => {"::" "hashmap", "_size" 0, "_root" {"::" "hashmap.node", "entries" {}}}) + +^{:refer xt.runtime.type-hashmap/hashmap-find :added "4.0"} +(fact "finds a value by key" + ^:hidden + + (!.js + (var hm (-> (hashmap/hashmap-empty) + (hashmap/hashmap-assoc "A" 1))) + (hashmap/hashmap-find hm "A")) + => 1 + + (!.lua + (var hm (-> (hashmap/hashmap-empty) + (hashmap/hashmap-assoc "A" 1))) + (hashmap/hashmap-find hm "A")) + => 1) + +^{:refer xt.runtime.type-hashmap/hashmap-assoc :added "4.0"} +(fact "associates a key-value pair in the hashmap" + ^:hidden + + (!.js + (var hm (-> (hashmap/hashmap-empty) + (hashmap/hashmap-assoc "A" 1) + (hashmap/hashmap-assoc "B" 2) + (hashmap/hashmap-assoc "C" 3) + (hashmap/hashmap-assoc "D" 4))) + hm) + => {"::" "hashmap", + "_size" 0, + "_root" {"::" "hashmap.node", + "entries" [nil nil nil nil nil ["B" 2] nil nil nil nil + nil nil ["A" 1] nil nil nil nil nil ["C" 3] ["D" 4]]}} + + (!.lua + (var hm (-> (hashmap/hashmap-empty) + (hashmap/hashmap-assoc "A" 1) + (hashmap/hashmap-assoc "B" 2) + (hashmap/hashmap-assoc "C" 3) + (hashmap/hashmap-assoc "D" 4))) + hm)) + +^{:refer xt.runtime.type-hashmap/hashmap-dissoc :added "4.0"} +(fact "dissociates a key-value pair from the hashmap" + ^:hidden + + (!.js + (-> (hashmap/hashmap-empty) + (hashmap/hashmap-assoc "A" 1) + (hashmap/hashmap-assoc "B" 2) + (hashmap/hashmap-assoc "C" 3) + (hashmap/hashmap-assoc "D" 4) + (hashmap/hashmap-dissoc "C") + (hashmap/hashmap-dissoc "D"))) + => {"::" "hashmap", "_size" -2, + "_root" {"::" "hashmap.node", "entries" [nil nil nil nil nil ["B" 2] nil nil nil nil + nil nil ["A" 1] nil nil nil nil nil nil nil]}}) + +^{:refer xt.runtime.type-hashmap/hashmap-size :added "4.0"} +(comment "returns the size of the hashmap" + ^:hidden + + (!.js + (var hm (-> (hashmap/hashmap-empty) + (hashmap/hashmap-assoc "key1" "val1") + (hashmap/hashmap-assoc "key2" "val2"))) + (hashmap/hashmap-size hm)) + => 2 + + (!.lua + (var hm (-> (hashmap/hashmap-empty) + (hashmap/hashmap-assoc "key1" "val1") + (hashmap/hashmap-assoc "key2" "val2"))) + (hashmap/hashmap-size hm)) + => 2) + +^{:refer xt.runtime.type-hashmap/hashmap-to-array :added "4.0"} +(fact "converts hashmap to an array of key-value pairs" + ^:hidden + + (!.js + (var hm (-> (hashmap/hashmap-empty) + (hashmap/hashmap-assoc "key1" "val1") + (hashmap/hashmap-assoc "key2" "val2"))) + (hashmap/hashmap-to-array hm))) diff --git a/test/xt/runtime/type_syntax_test.clj b/test/xt/runtime/type_syntax_test.clj index d378721..7b6b2ad 100644 --- a/test/xt/runtime/type_syntax_test.clj +++ b/test/xt/runtime/type_syntax_test.clj @@ -40,8 +40,9 @@ (fact "creates a syntax" (!.js - (tc/count - (syn/syntax-create [1 2 3] "hello")))) + (tc/count + (syn/syntax-create [1 2 3] "hello"))) + => 3) ^{:refer xt.runtime.type-syntax/get-metadata :added "4.0"} (fact "gets metadata"