Wire up repl & file interpreters.
This commit is contained in:
parent
c179325719
commit
7c30b6259b
3
sandbox.ld
Normal file
3
sandbox.ld
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
import "foo.ld" as foo
|
||||||
|
|
||||||
|
print ("Hello, world!", foo)
|
|
@ -1,37 +1,39 @@
|
||||||
(ns ludus.core
|
(ns ludus.core
|
||||||
"A tree-walk interpreter for the Ludus language."
|
"A tree-walk interpreter for the Ludus language."
|
||||||
(:require
|
(:require
|
||||||
[ludus.scanner :as scanner]
|
[ludus.scanner :as scanner]
|
||||||
[ludus.parser :as parser]
|
;[ludus.parser :as parser]
|
||||||
[ludus.interpreter :as interpreter]
|
[ludus.parser-new :as p]
|
||||||
[ludus.show :as show]
|
[ludus.grammar :as g]
|
||||||
[clojure.pprint :as pp]
|
[ludus.interpreter :as interpreter]
|
||||||
[ludus.loader :as loader]
|
[ludus.show :as show]
|
||||||
[ludus.repl :as repl])
|
[clojure.pprint :as pp]
|
||||||
|
[ludus.loader :as loader]
|
||||||
|
[ludus.repl :as repl])
|
||||||
(:gen-class))
|
(:gen-class))
|
||||||
|
|
||||||
(defn- run [file source]
|
(defn- run [file source]
|
||||||
(comment (let [scanned (scanner/scan source)]
|
(let [scanned (scanner/scan source)]
|
||||||
(if (not-empty (:errors scanned))
|
(if (not-empty (:errors scanned))
|
||||||
(do
|
(do
|
||||||
(println "I found some scanning errors!")
|
(println "I found some scanning errors!")
|
||||||
(pp/pprint (:errors scanned))
|
(pp/pprint (:errors scanned))
|
||||||
(System/exit 65))
|
(System/exit 65))
|
||||||
(let [parsed (parser/parse scanned)]
|
(let [parsed (p/apply-parser g/script (:tokens scanned))]
|
||||||
(if (not-empty (:errors parsed))
|
(if (p/fail? parsed)
|
||||||
(do
|
(do
|
||||||
(println "I found some parsing errors!")
|
(println "I found some parsing errors!")
|
||||||
(pp/pprint (:errors parsed))
|
(println p/err-msg parsed)
|
||||||
(System/exit 66))
|
(System/exit 66))
|
||||||
(let [interpreted (interpreter/interpret parsed file)]
|
(let [interpreted (interpreter/interpret source file parsed)]
|
||||||
(println (show/show interpreted))
|
(println (show/show interpreted))
|
||||||
(System/exit 0))))))))
|
(System/exit 0)))))))
|
||||||
|
|
||||||
(defn -main [& args]
|
(defn -main [& args]
|
||||||
(comment (cond
|
(cond
|
||||||
(= (count args) 1)
|
(= (count args) 1)
|
||||||
(let [file (first args)
|
(let [file (first args)
|
||||||
source (loader/load-import file)]
|
source (loader/load-import file)]
|
||||||
(run file source))
|
(run file source))
|
||||||
|
|
||||||
:else (repl/launch))))
|
:else (repl/launch)))
|
|
@ -11,8 +11,8 @@
|
||||||
[ludus.loader :as loader]
|
[ludus.loader :as loader]
|
||||||
[ludus.token :as token]
|
[ludus.token :as token]
|
||||||
[ludus.process :as process]
|
[ludus.process :as process]
|
||||||
[clojure.pprint :as pp]
|
[clojure.set]
|
||||||
[clojure.set]))
|
[clojure.string]))
|
||||||
|
|
||||||
(def ^:dynamic self @process/current-pid)
|
(def ^:dynamic self @process/current-pid)
|
||||||
|
|
||||||
|
@ -301,7 +301,7 @@
|
||||||
|
|
||||||
:struct-pattern (match-struct pattern value ctx-vol)
|
:struct-pattern (match-struct pattern value ctx-vol)
|
||||||
|
|
||||||
(throw (ex-info "Unknown pattern on line " {:pattern pattern :value value})))))
|
(throw (ex-info "Unknown pattern on line " {:ast pattern :value value})))))
|
||||||
|
|
||||||
(defn- update-ctx [ctx new-ctx]
|
(defn- update-ctx [ctx new-ctx]
|
||||||
(merge ctx new-ctx))
|
(merge ctx new-ctx))
|
||||||
|
@ -607,9 +607,15 @@
|
||||||
(if (::loader/error (ex-data e))
|
(if (::loader/error (ex-data e))
|
||||||
(throw (ex-info (ex-message e) {:ast ast}))
|
(throw (ex-info (ex-message e) {:ast ast}))
|
||||||
(throw e))))
|
(throw e))))
|
||||||
result (-> source (scanner/scan) (parser/parse) (interpret-file path))]
|
parsed (->> source (scanner/scan) :tokens (p/apply-parser g/script))]
|
||||||
(vswap! ctx update-ctx {name result})
|
(if (p/fail? parsed)
|
||||||
result
|
(throw (ex-info
|
||||||
|
(str "Parse error in file " path "\n"
|
||||||
|
(p/err-msg parsed))
|
||||||
|
{:ast ast}))
|
||||||
|
(let [interpret-result (interpret-file source path parsed)]
|
||||||
|
(vswap! ctx update-ctx {name interpret-result})
|
||||||
|
interpret-result))
|
||||||
))))
|
))))
|
||||||
|
|
||||||
(defn- interpret-ref [ast ctx]
|
(defn- interpret-ref [ast ctx]
|
||||||
|
@ -883,35 +889,42 @@
|
||||||
:dict (interpret-dict ast ctx)
|
:dict (interpret-dict ast ctx)
|
||||||
|
|
||||||
:struct-literal
|
:struct-literal
|
||||||
(let [members (:members ast)] (interpret-struct ast ctx))
|
(interpret-struct ast ctx)
|
||||||
|
|
||||||
(throw (ex-info "Unknown AST node type" {:ast ast}))))
|
(throw (ex-info (str "Unknown AST node type: " (:type ast)) {:ast ast}))))
|
||||||
|
|
||||||
|
(defn get-line [source line]
|
||||||
|
(if line
|
||||||
|
(let [lines (clojure.string/split source #"\n")]
|
||||||
|
(clojure.string/trim (nth lines (dec line))))))
|
||||||
|
|
||||||
;; TODO: update this to use new parser pipeline & new AST representation
|
;; TODO: update this to use new parser pipeline & new AST representation
|
||||||
(defn interpret-file [parsed file]
|
(defn interpret-file [source path parsed]
|
||||||
(try
|
(try
|
||||||
(let [base-ctx (volatile! (merge {:file file} prelude/prelude process/process))]
|
(let [base-ctx (volatile! {::parent (volatile! prelude/prelude) :file path})]
|
||||||
(interpret-ast (::parser/ast parsed) base-ctx))
|
(interpret-ast parsed base-ctx))
|
||||||
(catch clojure.lang.ExceptionInfo e
|
(catch clojure.lang.ExceptionInfo e
|
||||||
(println "Ludus panicked in" file)
|
(println "Ludus panicked in" path)
|
||||||
(println "On line" (get-in (ex-data e) [:ast :token ::token/line]))
|
(println "On line" (get-in (ex-data e) [:ast :token :line]))
|
||||||
|
(println ">>> " (get-line source (get-in (ex-data e) [:ast :token :line])))
|
||||||
(println (ex-message e))
|
(println (ex-message e))
|
||||||
(System/exit 67))))
|
(System/exit 67))))
|
||||||
|
|
||||||
;; TODO: update this to use new parser pipeline & new AST representation
|
;; TODO: update this to use new parser pipeline & new AST representation
|
||||||
(defn interpret [parsed file]
|
(defn interpret [source path parsed]
|
||||||
(try
|
(try
|
||||||
(let [base-ctx (volatile! (merge {:file file} prelude/prelude process/process))
|
(let [base-ctx (volatile! {::parent (volatile! prelude/prelude) :file path})
|
||||||
process (process/new-process)]
|
process (process/new-process)]
|
||||||
(process/start-vm)
|
(process/start-vm)
|
||||||
(with-bindings {#'self (:pid @process)}
|
(with-bindings {#'self (:pid @process)}
|
||||||
(let [result (interpret-ast (::parser/ast parsed) {::parent base-ctx})]
|
(let [result (interpret-ast parsed base-ctx)]
|
||||||
(swap! process #(assoc % :status :dead))
|
(swap! process #(assoc % :status :dead))
|
||||||
(process/stop-vm)
|
(process/stop-vm)
|
||||||
result)))
|
result)))
|
||||||
(catch clojure.lang.ExceptionInfo e
|
(catch clojure.lang.ExceptionInfo e
|
||||||
(println "Ludus panicked in" file)
|
(println "Ludus panicked in" path)
|
||||||
(println "On line" (get-in (ex-data e) [:ast :token ::token/line]))
|
(println "On line" (get-in (ex-data e) [:ast :token :line]))
|
||||||
|
(println ">>> " (get-line source (get-in (ex-data e) [:ast :token :line])))
|
||||||
(println (ex-message e))
|
(println (ex-message e))
|
||||||
(System/exit 67))))
|
(System/exit 67))))
|
||||||
|
|
||||||
|
@ -927,10 +940,11 @@
|
||||||
result)))
|
result)))
|
||||||
(catch clojure.lang.ExceptionInfo e
|
(catch clojure.lang.ExceptionInfo e
|
||||||
(process/stop-vm)
|
(process/stop-vm)
|
||||||
(println "Ludus panicked!")
|
(println "Ludus panicked on line " (get-in (ex-data e) [:ast :token :line]))
|
||||||
(println "On line" (get-in (ex-data e) [:ast :token :line]))
|
(println "> " (get-in (ex-data e) [:ast :token]))
|
||||||
(println (ex-message e))
|
(println (ex-message e))
|
||||||
(pp/pprint (ex-data e)))))
|
;(pp/pprint (ex-data e))
|
||||||
|
)))
|
||||||
|
|
||||||
;; TODO: update this to use new parser pipeline & new AST representation
|
;; TODO: update this to use new parser pipeline & new AST representation
|
||||||
(defn interpret-repl
|
(defn interpret-repl
|
||||||
|
@ -941,7 +955,7 @@
|
||||||
(try
|
(try
|
||||||
(process/start-vm)
|
(process/start-vm)
|
||||||
(with-bindings {#'self pid}
|
(with-bindings {#'self pid}
|
||||||
(let [result (interpret-ast (::parser/ast parsed) ctx)]
|
(let [result (interpret-ast parsed ctx)]
|
||||||
{:result result :ctx ctx :pid pid}))
|
{:result result :ctx ctx :pid pid}))
|
||||||
(catch clojure.lang.ExceptionInfo e
|
(catch clojure.lang.ExceptionInfo e
|
||||||
(println "Ludus panicked!")
|
(println "Ludus panicked!")
|
||||||
|
@ -952,7 +966,7 @@
|
||||||
(try
|
(try
|
||||||
(process/start-vm)
|
(process/start-vm)
|
||||||
(with-bindings {#'self pid}
|
(with-bindings {#'self pid}
|
||||||
(let [result (interpret-ast (::parser/ast parsed) ctx)]
|
(let [result (interpret-ast parsed ctx)]
|
||||||
{:result result :ctx ctx :pid pid}))
|
{:result result :ctx ctx :pid pid}))
|
||||||
(catch clojure.lang.ExceptionInfo e
|
(catch clojure.lang.ExceptionInfo e
|
||||||
(println "Ludus panicked!")
|
(println "Ludus panicked!")
|
||||||
|
@ -961,11 +975,9 @@
|
||||||
)))))
|
)))))
|
||||||
|
|
||||||
|
|
||||||
(do
|
(comment
|
||||||
(def source "
|
(def source "
|
||||||
let xs = [1, 2, 3]
|
let 2 = 1
|
||||||
let ys = #{:a 1, :b 2}
|
|
||||||
get (:c, ys)
|
|
||||||
")
|
")
|
||||||
|
|
||||||
(println "")
|
(println "")
|
||||||
|
|
|
@ -2,7 +2,8 @@
|
||||||
(: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
|
||||||
|
@ -102,10 +103,6 @@
|
||||||
(get map key default)
|
(get map key default)
|
||||||
default)))})
|
default)))})
|
||||||
|
|
||||||
(def draw {:name "draw"
|
|
||||||
::data/type ::data/clj
|
|
||||||
:body d/ludus-draw})
|
|
||||||
|
|
||||||
(def first- {:name "first"
|
(def first- {:name "first"
|
||||||
::data/type ::data/clj
|
::data/type ::data/clj
|
||||||
:body (fn [v] (second v))})
|
:body (fn [v] (second v))})
|
||||||
|
@ -191,7 +188,6 @@
|
||||||
"assoc" assoc-
|
"assoc" assoc-
|
||||||
"conj" conj-
|
"conj" conj-
|
||||||
"get" get-
|
"get" get-
|
||||||
"draw" draw
|
|
||||||
"type" type-
|
"type" type-
|
||||||
"clj" clj
|
"clj" clj
|
||||||
"first" first-
|
"first" first-
|
||||||
|
|
|
@ -1,12 +1,15 @@
|
||||||
(ns ludus.repl
|
(ns ludus.repl
|
||||||
(:require
|
(:require
|
||||||
[ludus.scanner :as scanner]
|
[ludus.scanner :as scanner]
|
||||||
[ludus.parser :as parser]
|
;[ludus.parser :as parser]
|
||||||
|
[ludus.parser-new :as p]
|
||||||
|
[ludus.grammar :as g]
|
||||||
[ludus.interpreter :as interpreter]
|
[ludus.interpreter :as interpreter]
|
||||||
[ludus.prelude :as prelude]
|
[ludus.prelude :as prelude]
|
||||||
[ludus.show :as show]
|
[ludus.show :as show]
|
||||||
[ludus.data :as data]
|
[ludus.data :as data]
|
||||||
[ludus.process :as process]))
|
;[ludus.process :as process]
|
||||||
|
))
|
||||||
|
|
||||||
(declare repl-prelude new-session)
|
(declare repl-prelude new-session)
|
||||||
|
|
||||||
|
@ -20,7 +23,7 @@
|
||||||
(println "\nGoodbye!")
|
(println "\nGoodbye!")
|
||||||
(System/exit 0))
|
(System/exit 0))
|
||||||
|
|
||||||
(def base-ctx (merge prelude/prelude process/process
|
(def base-ctx (merge prelude/prelude ;process/process
|
||||||
{::repl true
|
{::repl true
|
||||||
"repl"
|
"repl"
|
||||||
{::data/struct true
|
{::data/struct true
|
||||||
|
@ -91,20 +94,27 @@
|
||||||
(= "" input) (recur)
|
(= "" input) (recur)
|
||||||
|
|
||||||
:else
|
:else
|
||||||
(let [parsed (-> input (scanner/scan) (parser/parse))
|
(let [parsed (->> input
|
||||||
{result :result ctx :ctx pid- :pid}
|
(scanner/scan)
|
||||||
(if pid
|
:tokens
|
||||||
(interpreter/interpret-repl parsed orig-ctx pid)
|
(p/apply-parser g/script))]
|
||||||
(interpreter/interpret-repl parsed orig-ctx))]
|
(if (= :err (:status parsed))
|
||||||
(if (= result ::interpreter/error)
|
|
||||||
(recur)
|
|
||||||
(do
|
(do
|
||||||
(println (show/show result))
|
(println (p/err-msg parsed))
|
||||||
(when (not (= @ctx @orig-ctx))
|
(recur))
|
||||||
(swap! session-atom #(assoc % :ctx ctx)))
|
(let [{result :result ctx :ctx pid- :pid}
|
||||||
(when (not (= pid pid-))
|
(if pid
|
||||||
(swap! session-atom #(assoc % :pid pid-)))
|
(interpreter/interpret-repl parsed orig-ctx pid)
|
||||||
(recur))))))))
|
(interpreter/interpret-repl parsed orig-ctx))]
|
||||||
|
(if (= result :error)
|
||||||
|
(recur)
|
||||||
|
(do
|
||||||
|
(println (show/show result))
|
||||||
|
(when (not (= @ctx @orig-ctx))
|
||||||
|
(swap! session-atom #(assoc % :ctx ctx)))
|
||||||
|
(when (not (= pid pid-))
|
||||||
|
(swap! session-atom #(assoc % :pid pid-)))
|
||||||
|
(recur))))))))))
|
||||||
|
|
||||||
(defn launch []
|
(defn launch []
|
||||||
(println "Welcome to Ludus (v. 0.1.0-alpha)")
|
(println "Welcome to Ludus (v. 0.1.0-alpha)")
|
||||||
|
|
Loading…
Reference in New Issue
Block a user