Clean up some stuff, add ebnf grammar, fail to get quil working

This commit is contained in:
Scott Richmond 2023-05-02 18:58:36 -04:00
commit 3a7f86e401
5 changed files with 186 additions and 9 deletions

2
.gitignore vendored
View File

@ -19,4 +19,4 @@ pom.xml.asc
**/.DS_Store **/.DS_Store
/sandbox /sandbox
ludus.sublime-workspace ludus.sublime-workspace
ludus /ludus

View File

@ -4,8 +4,15 @@
:license {:name "EPL-2.0 OR GPL-2.0-or-later WITH Classpath-exception-2.0" :license {:name "EPL-2.0 OR GPL-2.0-or-later WITH Classpath-exception-2.0"
:url "https://www.eclipse.org/legal/epl-2.0/"} :url "https://www.eclipse.org/legal/epl-2.0/"}
:dependencies [[org.clojure/clojure "1.11.1"] :dependencies [[org.clojure/clojure "1.11.1"]
<<<<<<< HEAD
[babashka/fs "0.1.6"] [babashka/fs "0.1.6"]
[quil "4.0.0-SNAPSHOT"]] [quil "4.0.0-SNAPSHOT"]]
||||||| 1c2ab51
[babashka/fs "0.1.6"]]
=======
[babashka/fs "0.1.6"]
[quil "4.0.0-SNAPSHOT-1"]]
>>>>>>> 55d76f6854bf67119873d98e2c9c18d8390ab90a
:plugins [[lein-cljfmt "0.8.0"]] :plugins [[lein-cljfmt "0.8.0"]]
:repl-options {:init-ns ludus.core} :repl-options {:init-ns ludus.core}
:main ludus.core :main ludus.core

32
src/ludus/draw.clj Normal file
View File

@ -0,0 +1,32 @@
(ns ludus.draw
(:require [quil.core :as q]
[quil.middleware :as m]))
(defn setup []
(q/frame-rate 60)
(q/color-mode :hsb)
{:color 0 :angle 0})
(defn update-state [state]
{:color (mod (+ (:color state) 0.7) 255)
:angle (+ (:angle state) 0.1)})
(defn draw-state [state]
(q/background 240)
(q/fill (:color state) 255 255)
(let [angle (:angle state)
x (* 150 (q/cos angle))
y (* 150 (q/sin angle))]
(q/with-translation [(/ (q/width) 2)
(/ (q/height) 2)]
(q/ellipse x y 100 100))))
(defn ludus-draw []
(q/defsketch sketch
:title "Hello Ludus"
:size [500 500]
:setup setup
:update update-state
:draw draw-state
:features []
:middleware [m/fun-mode]))

135
src/ludus/ludus.ebnf Normal file
View File

@ -0,0 +1,135 @@
(*
ludus.ebnf
An Instaparse-style EBNF grammer for Ludus.
*)
script = <wsnl?> toplevel <ws?> {<terminator> <ws?> toplevel <ws?>} <wsnl?>
terminator = (";" | <{comment}> "\n")+
ws = (" " | "\t" | "\r")+
wsnl = (ws | <{comment}> "\n")+
reserved = "cond" | "let" | "if" | "then" | "else" | "nil" | "true" | "false" | "as" | "match" | "with" | "NaN" | "recur"
comment = "&" not_nl*
not_nl = #"[^\n]"
toplevel = expression | import | test | ns
test = <"test" ws> string <ws> expression
import = <"import" ws> string <ws "as" ws> name
ns = <"ns" ws> name <ws? "{" wsnl?> entries <wsnl? "}">
entries = [(name | entry) {<separator> [(name | entry)]}]
expression = if | cond | let | tuple | atom | synthetic | block | match | fn | do | loop | dict | struct | list | ref | spawn | send | receive | repeat
(* TODO: is this right? *)
repeat = <"repeat" ws> (number | name) <ws> fn_clause
spawn = <"spawn" ws> expression
receive = <"receive" ws? "{" wsnl?> match_clause {terminator <ws?> [match_clause]} <wsnl? "}">
ref = <"ref" ws> name <ws? "=" ws?> expression
loop = <"loop" ws> tuple <ws "with" ws> (fn_clause
| (<"{" wsnl?> fn_clause {terminator <ws?> [fn_clause]} <wsnl? "}">))
do = <"do" ws> expression {<pipe> expression}
pipe = wsnl? "|>" wsnl?
fn = lambda | named | complex
lambda = <"fn" ws?> fn_clause
named = <"fn" ws?> name <ws> fn_clause
complex = <"fn" ws?> name <ws?> "{" <wsnl?> string? <wsnl> fn_clause {terminator <ws?> [fn_clause]} <wsnl? "}">
fn_clause = tuple_pattern <arrow> expression
match = <"match" ws> expression <ws "with" ws? "{" wsnl?> match_clause {terminator <ws?> [match_clause]} <wsnl? "}">
match_clause = pattern constraint? <arrow> expression
constraint = <"when" ws> expression
let = <"let" ws> pattern <ws "=" wsnl> expression
pattern = tuple_pattern | atom | placeholder | "else" | splattern
tuple_pattern = <"(" wsnl?> [pattern {<separator> [pattern]}] <{separator} ws? ")">
struct_pattern = <"@{" wsnl?> [(name | pattern_entry | splattern) {<separator> [(name | pattern_entry | splattern)]}] <{separator} ws? "}">
dict_pattern = <"#{" wsnl?> [(name | pattern_entry | splattern) {<separator> [(name | pattern_entry | splattern)]}] <{separator} ws? "}">
pattern_entry = keyword <ws> pattern
splattern = <"..."> name | ignored | placeholder
block = <"{" wsnl?> expression {<terminator ws?> expression <ws?>} <wsnl? "}">
cond = "cond" <ws> expression <ws? "{" wsnl?> cond_clause {terminator <ws?> [cond_clause]} <wsnl? "}">
cond_clause = expression <arrow> expression
arrow = <ws? "->" wsnl?>
if = <"if" ws> expression <wsnl "then" ws> expression <wsnl> <"else" ws> expression
synthetic = (name | keyword | recur) ((<ws?> (args | keyword))+)
recur = <"recur">
separator = <ws?> ("," | "\n") <ws?>
args = <"(" ws? {separator}> [arg_expr {<separator> [arg_expr]}] <{separator} ws? ")">
arg_expr = expression | placeholder
placeholder = <"_">
tuple = <"(" wsnl?> [expression {<separator> [expression]}] <{separator} ws? ")">
list = <"[" wsnl?> [(expression | splat) {<separator> [(expression | splat)]}] <{separator} ws? "]">
struct = <"@{" wsnl?> [(name | entry) {<separator> [(name | entry)]}] <{separator} ws? "}">
dict = <"#{" wsnl?> [(name | entry | splat) {<separator> [(name | entry | splat)]}] <{separator} ws? "}">
entry = keyword <ws> expression
splat = <"..."> name
atom = name | ignored | keyword | number | string | boolean | nil
boolean = true | false
true = <"true">
false = <"false">
nil = <"nil">
string = <'"'> {escaped_quote | nonquote} <'"'>
escaped_quote = "\\" '\"'
nonquote = #'[^"]'
keyword = #":[a-zA-Z][a-zA-Z0-9\/\-_!\*\?]*"
ignored = #"_[a-z][a-zA-Z0-9\/\-_!\*\?]*"
name = !reserved #"[a-z][a-zA-Z0-9\/\-_!\*\?]*"
(* TODO: Debug this to reject things starting with 0, eg 012. *)
number = #"\-?[1-9][0-9]*" | #"\-?(0|[1-9][0-9]*).[0-9]+" | ["-"] "0" | "NaN"

View File

@ -2,8 +2,7 @@
(:require (:require
[ludus.data :as data] [ludus.data :as data]
[ludus.show :as show] [ludus.show :as show]
[ludus.draw :as d] [ludus.draw :as d]))
))
;; TODO: make eq, and, or special forms that short-circuit ;; TODO: make eq, and, or special forms that short-circuit
;; Right now, they evaluate all their args ;; Right now, they evaluate all their args
@ -84,16 +83,20 @@
::data/type ::data/clj ::data/type ::data/clj
:body (fn [ms] (Thread/sleep ms))}) :body (fn [ms] (Thread/sleep ms))})
(def conj- {:name "conj" (def conj- {:name "conj"
::data/type ::data/clj ::data/type ::data/clj
:body conj}) :body conj})
(def assoc- {:name "assoc" (def assoc- {:name "assoc"
::data/type ::data/clj ::data/type ::data/clj
:body assoc}) :body assoc})
(def get- {:name "get" (def get- {:name "get"
::data/type ::data/clj ::data/type ::data/clj
:body get}) :body get})
(def draw {:name "draw"
::data/type ::data/clj
:body draw/ludus-draw})
(def draw {:name "draw" (def draw {:name "draw"
::data/type ::data/clj ::data/type ::data/clj