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/
checkouts/
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,9 +63,9 @@
::data/type ::data/clj
:body dec})
(def ld-not {:name "not"
::data/type ::data/clj
:body not})
(def not- {:name "not"
::data/type ::data/clj
:body not})
(def panic! {:name "panic!"
::data/type ::data/clj
@ -118,10 +118,6 @@
(get map key default)
default)))})
(def first- {:name "first"
::data/type ::data/clj
:body (fn [v] (second v))})
(def rest- {:name "rest"
::data/type ::data/clj
:body (fn [v]
@ -129,17 +125,7 @@
(def nth- {:name "nth"
::data/type ::data/clj
:body (fn
([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)))})
:body nth})
(def types {
:keyword
@ -160,6 +146,12 @@
:cljs js/Number
)
:integer
#?(
:clj java.lang.Integer
:cljs js/Number
)
:string
#?(
:clj java.lang.String
@ -202,6 +194,8 @@
(= (:double types) t) :number
(= (:integer types) t) :number
(= (:string types) t) :string
(= (:boolean types) t) :boolean
@ -220,6 +214,7 @@
::data/ns :ns)
(::data/dict value) :dict
(::data/struct value) :struct
(::data/ref value) :ref
:else :none
))))
@ -255,35 +250,73 @@
(def count- {:name "count"
::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 {
"id" id
"eq" eq
"add" add
"print" print-
"sub" sub
"mult" mult
"div" div
"gt" gt
"gte" gte
"lt" lt
"lte" lte
"inc" inc-
"dec" dec-
"not" not
"show" show
"deref" deref-
"set!" set!-
"and" and-
"or" or-
"assoc" assoc-
"conj" conj-
"get" get-
"type" type-
"extern" extern
"first" first-
"rest" rest-
"nth" nth-
"count" count-
:id id
:eq eq
:add add
:print print-
:sub sub
:mult mult
:div div
:gt gt
:gte gte
:lt lt
:lte lte
:inc inc-
:dec dec-
:not not-
:show show
:deref deref-
:set! set!-
:and and-
:or or-
:assoc assoc-
:conj conj-
:get get-
:type type-
:extern extern
:rest rest-
:nth nth-
: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
(defn- ludus-resolve [key ctx-vol]
(let [ctx @ctx-vol]
(println "Resolving " key)
(println "Current context: " (keys ctx))
;(println "Resolving " key " in context " (keys ctx))
;(println "Current context: " (keys ctx))
;(println "Parent context: " (keys (if (::parent ctx) (deref (::parent ctx)) {})))
(if (contains? ctx key)
(get ctx key)
@ -473,7 +473,7 @@
(interpret-ast body fn-ctx)))
(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)
(if (= 2 (count args))
@ -488,7 +488,7 @@
(kw target)))
(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]
;(println "interpreting arg" args)
@ -873,7 +873,7 @@
(def ludus-prelude
(let [scanned (scanner/scan prelude/prelude)
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)
namespace (dissoc interpreted ::data/type ::data/name ::data/struct)
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/ellipse js/mouseX js/mouseY 80 80))
(doto js/window
(o/set "setup" setup)
(o/set "draw" draw))
(defn init []
(doto js/window
(o/set "setup" setup)
(o/set "draw" draw)))
(o/set js/window "ludus_init" init)