Lots of progress

This commit is contained in:
Scott Richmond 2023-12-01 19:08:51 -05:00
parent 3f865a64d7
commit bc7565926a
8 changed files with 262 additions and 123 deletions

4
.gitignore vendored
View File

@ -1,4 +1,6 @@
target/ target/stale
target/js
target/classes
classes/ classes/
checkouts/ checkouts/
profiles.clj profiles.clj

View File

@ -1,64 +0,0 @@
& this file, uniquely, gets `base` loaded. See src/ludus/base.cljc for exports
fn first {
"Returns the first element of a list or tuple."
(xs as :list) -> extern (:first, xs)
(xs as :tuple) -> extern (:second, xs)
}
fn nth {
"Returns the element at index n of a list or tuple. Zero-indexed: the first element is at index 0."
(xs as :list, n as :number) -> extern (:nth, xs, n)
(xs as :tuple, n as :number) -> extern (:nth, xs, extern (:inc, n))
}
fn count {
"Returns the number of elements in a list or tuple."
(xs as :list) -> extern (count, xs)
(xs as :tuple) -> extern (:dec, extern (:count, xs))
}
fn list {
"Takes a tuple, and returns it as a list."
(xs as :tuple) -> extern (:into, [], extern (:rest, xs))
}
fn fold {
"Folds a collection."
(f as :function, xs as :list) -> extern (:reduce, f, xs)
(f as :function, root, xs as :list) -> extern (:reduce, f, root, xs)
}
fn conj {
"Adds an element to a list. Short for conjoin."
() -> []
(xs as :list) -> xs
(xs as :list, x) -> extern (:conj, xs, x)
& (xs, x, ...ys) -> extern (:conj, xs, x, ...ys)
}
fn ludus/add {
"Adds numbers."
() -> 0
(x as :number) -> x
(x as :number, y as :number) -> add (x, y)
(x as :number, y as :number, ...zs) -> fold (ludus/add, add (x, y), zs)
}
ns math {
:add ludus/add
}
print ("From Prelude, hello.")
ns prelude {
first
nth
conj
fold
list
}
print (prelude)
prelude

View File

@ -63,7 +63,7 @@
::data/type ::data/clj ::data/type ::data/clj
:body dec}) :body dec})
(def ld-not {:name "not" (def not- {:name "not"
::data/type ::data/clj ::data/type ::data/clj
:body not}) :body not})
@ -118,10 +118,6 @@
(get map key default) (get map key default)
default)))}) default)))})
(def first- {:name "first"
::data/type ::data/clj
:body (fn [v] (second v))})
(def rest- {:name "rest" (def rest- {:name "rest"
::data/type ::data/clj ::data/type ::data/clj
:body (fn [v] :body (fn [v]
@ -129,17 +125,7 @@
(def nth- {:name "nth" (def nth- {:name "nth"
::data/type ::data/clj ::data/type ::data/clj
:body (fn :body nth})
([i, xs]
(cond
(> 0 i) nil
(contains? xs (inc i)) (nth xs (inc i))
:else nil))
([i, xs, default]
(cond
(> 0 i) default
(contains? xs (inc i)) (nth xs (inc i))
:else default)))})
(def types { (def types {
:keyword :keyword
@ -160,6 +146,12 @@
:cljs js/Number :cljs js/Number
) )
:integer
#?(
:clj java.lang.Integer
:cljs js/Number
)
:string :string
#?( #?(
:clj java.lang.String :clj java.lang.String
@ -202,6 +194,8 @@
(= (:double types) t) :number (= (:double types) t) :number
(= (:integer types) t) :number
(= (:string types) t) :string (= (:string types) t) :string
(= (:boolean types) t) :boolean (= (:boolean types) t) :boolean
@ -220,6 +214,7 @@
::data/ns :ns) ::data/ns :ns)
(::data/dict value) :dict (::data/dict value) :dict
(::data/struct value) :struct (::data/struct value) :struct
(::data/ref value) :ref
:else :none :else :none
)))) ))))
@ -255,35 +250,73 @@
(def count- {:name "count" (def count- {:name "count"
::data/type ::data/clj ::data/type ::data/clj
:body (fn [xs] (dec (count xs)))}) :body count})
(def into- {:name "into"
::data/type ::data/clj
:body into})
(def to_vec {:name "to_vec"
::data/type ::data.clj
:body (fn [xs] (into [] xs))})
(def fold {:name "fold"
::data/type ::data/clj
:body reduce})
(def map- {:name "map"
::data/type ::data/clj
:body map})
(def prn- {:name "raw"
::data/type ::data/clj
:body println})
(def concat- {:name "concat"
::data/type ::data/clj
:body (fn [xs ys]
(if (= ::data/list (first xs))
(into [::data/list] (concat (rest xs) (rest ys)))
(into #{} (concat xs ys))))})
(def str- {:name "str"
::data/type ::data/clj
:body str})
(def base { (def base {
"id" id :id id
"eq" eq :eq eq
"add" add :add add
"print" print- :print print-
"sub" sub :sub sub
"mult" mult :mult mult
"div" div :div div
"gt" gt :gt gt
"gte" gte :gte gte
"lt" lt :lt lt
"lte" lte :lte lte
"inc" inc- :inc inc-
"dec" dec- :dec dec-
"not" not :not not-
"show" show :show show
"deref" deref- :deref deref-
"set!" set!- :set! set!-
"and" and- :and and-
"or" or- :or or-
"assoc" assoc- :assoc assoc-
"conj" conj- :conj conj-
"get" get- :get get-
"type" type- :type type-
"extern" extern :extern extern
"first" first- :rest rest-
"rest" rest- :nth nth-
"nth" nth- :count count-
"count" count- :into into-
:to_vec to_vec
:fold fold
:map map
:panic! panic!
:prn prn-
:concat concat-
:str str-
}) })

View File

@ -19,8 +19,8 @@
;; that's for later, tho ;; that's for later, tho
(defn- ludus-resolve [key ctx-vol] (defn- ludus-resolve [key ctx-vol]
(let [ctx @ctx-vol] (let [ctx @ctx-vol]
(println "Resolving " key) ;(println "Resolving " key " in context " (keys ctx))
(println "Current context: " (keys ctx)) ;(println "Current context: " (keys ctx))
;(println "Parent context: " (keys (if (::parent ctx) (deref (::parent ctx)) {}))) ;(println "Parent context: " (keys (if (::parent ctx) (deref (::parent ctx)) {})))
(if (contains? ctx key) (if (contains? ctx key)
(get ctx key) (get ctx key)
@ -473,7 +473,7 @@
(interpret-ast body fn-ctx))) (interpret-ast body fn-ctx)))
(recur (first clauses) (rest clauses)))) (recur (first clauses) (rest clauses))))
(throw (ex-info "Match Error: No match found" {:ast (:ast lfn)}))))) (throw (ex-info (str "Match Error: No match found for " (show/show args) " in function " (:name lfn)) {:ast (:ast lfn)})))))
(keyword? lfn) (keyword? lfn)
(if (= 2 (count args)) (if (= 2 (count args))
@ -488,7 +488,7 @@
(kw target))) (kw target)))
(throw (ex-info "Called keywords take a single argument" {:ast lfn}))) (throw (ex-info "Called keywords take a single argument" {:ast lfn})))
:else (throw (ex-info "I don't know how to call that" {:ast lfn})))) :else (throw (ex-info (str "I don't know how to call " (show/show lfn)) {:ast lfn}))))
(defn- interpret-args [args ctx] (defn- interpret-args [args ctx]
;(println "interpreting arg" args) ;(println "interpreting arg" args)
@ -873,7 +873,7 @@
(def ludus-prelude (def ludus-prelude
(let [scanned (scanner/scan prelude/prelude) (let [scanned (scanner/scan prelude/prelude)
parsed (p/apply-parser g/script (:tokens scanned)) parsed (p/apply-parser g/script (:tokens scanned))
base-ctx (volatile! {::parent (volatile! base/base)}) base-ctx (volatile! {::parent (volatile! {"base" base/base})})
interpreted (interpret-ast parsed base-ctx) interpreted (interpret-ast parsed base-ctx)
namespace (dissoc interpreted ::data/type ::data/name ::data/struct) namespace (dissoc interpreted ::data/type ::data/name ::data/struct)
context (ns->ctx namespace)] context (ns->ctx namespace)]

View File

@ -1,3 +0,0 @@
(ns ludus.prelude)
(def prelude (slurp "prelude.ld"))

9
src/ludus/prelude.cljc Normal file
View File

@ -0,0 +1,9 @@
(ns ludus.prelude
#?(:cljs (:require [shadow.resource :as r]))
)
(def prelude
#?(
:clj (slurp "src/ludus/prelude.ld")
:cljs (r/inline "prelude.ld")
))

158
src/ludus/prelude.ld Normal file
View File

@ -0,0 +1,158 @@
& this file, uniquely, gets `base` loaded as context. See src/ludus/base.cljc for exports
fn rest {
"Returns all but the first element of a list, as a list."
(xs as :list) -> base :rest (xs)
}
fn inc {
"Increments a number."
(x as :number) -> base :inc (x)
}
fn dec {
"Decrements a number."
(x as :number) -> base :dec (x)
(x) -> report (x)
}
fn nth {
"Returns the element at index n of a list or tuple. Zero-indexed: the first element is at index 0."
(xs as :list, n as :number) -> base :nth (xs, inc(n))
(xs as :tuple, n as :number) -> base :nth (xs, inc (n))
}
fn first {
"Returns the first element of a list or tuple."
(xs) -> nth (xs, 0)
}
fn second {
"Returns the second element of a list or tuple."
(xs) -> nth (xs, 1)
}
fn count {
"Returns the number of elements in a collection (including string)."
(xs as :list) -> dec (base :count (report(xs)))
(xs as :tuple) -> dec (base :count (xs))
(xs as :dict) -> base :count (xs)
(xs as :string) -> base :count (xs)
(xs as :set) -> base :count (xs)
(xs as :struct) -> dec (base :count (xs))
}
fn list {
"Takes a tuple, and returns it as a list."
(xs as :tuple) -> base :into ([], base :rest (xs))
}
fn fold {
"Folds a list."
(f as :fn, xs as :list) -> fold (f, xs, f ())
(f as :fn, xs as :list, root) -> loop (root, first (xs), rest (xs)) with {
(prev, curr, []) -> f (prev, curr)
(prev, curr, remaining) -> recur (
f (prev, curr)
first (remaining)
rest (remaining)
)
}
}
fn map {
"Maps over a list."
(f as :fn, xs) -> {
fn mapper (prev, curr) -> conj (prev, f (curr))
fold (mapper, xs, [])
}
}
fn conj {
"Adds an element to a list or set. Short for conjoin."
() -> []
(xs as :list) -> xs
(xs as :list, x) -> base :conj (xs, x)
(xs as :set) -> xs
(xs as :set, x) -> base :conj (xs, x)
}
fn add {
"Adds numbers."
() -> 0
(x as :number) -> x
(x as :number, y as :number) -> base :add (x, y)
(x as :number, y as :number, ...zs) -> fold (base :add, add (x, y), zs)
}
fn print {
"Sends a text representation of a Ludus value to stdout."
(x) -> base :print (x)
}
fn show {
"Returns a text representation of a Ludus value as a string."
(x) -> base :show (x)
}
fn type {
"Returns a keyword representing the type of the value passed in."
(x) -> base :type (x)
}
fn prn {
"Prints the underlying Clojure data structure of a Ludus value."
(x) -> base :prn (x)
}
fn concat {
"Combines two lists, strings, or sets."
(x as :string, y as :string) -> base :str (x, y)
(xs as :list, ys as :list) -> base :concat (xs, ys)
(xs as :set, ys as :set) -> base :concat (xs, ys)
(xs, ys, ...zs) -> fold (concat, zs, concat(xs, ys))
}
fn report {
"Prints a value, then returns it."
(x) -> {
print (x)
x
}
(msg as :string, x) -> print (concat (msg, show (x)))
}
fn deref {
"Resolves a ref into a value."
(r as :ref) -> base :deref (r)
}
fn set! {
"Sets the value of a ref."
(r as :ref, value) -> base :set! (r, value)
}
ns prelude {
first
second
rest
nth
count
conj
fold
map
list
inc
dec
add
print
show
prn
type
report
concat
deref
set!
}
prelude

View File

@ -35,6 +35,10 @@
(js/fill 155)) (js/fill 155))
(js/ellipse js/mouseX js/mouseY 80 80)) (js/ellipse js/mouseX js/mouseY 80 80))
(doto js/window (defn init []
(doto js/window
(o/set "setup" setup) (o/set "setup" setup)
(o/set "draw" draw)) (o/set "draw" draw)))
(o/set js/window "ludus_init" init)