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)
|
|
@ -2,7 +2,9 @@
|
|||
"A tree-walk interpreter for the Ludus language."
|
||||
(:require
|
||||
[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.show :as show]
|
||||
[clojure.pprint :as pp]
|
||||
|
@ -11,27 +13,27 @@
|
|||
(:gen-class))
|
||||
|
||||
(defn- run [file source]
|
||||
(comment (let [scanned (scanner/scan source)]
|
||||
(let [scanned (scanner/scan source)]
|
||||
(if (not-empty (:errors scanned))
|
||||
(do
|
||||
(println "I found some scanning errors!")
|
||||
(pp/pprint (:errors scanned))
|
||||
(System/exit 65))
|
||||
(let [parsed (parser/parse scanned)]
|
||||
(if (not-empty (:errors parsed))
|
||||
(let [parsed (p/apply-parser g/script (:tokens scanned))]
|
||||
(if (p/fail? parsed)
|
||||
(do
|
||||
(println "I found some parsing errors!")
|
||||
(pp/pprint (:errors parsed))
|
||||
(println p/err-msg parsed)
|
||||
(System/exit 66))
|
||||
(let [interpreted (interpreter/interpret parsed file)]
|
||||
(let [interpreted (interpreter/interpret source file parsed)]
|
||||
(println (show/show interpreted))
|
||||
(System/exit 0))))))))
|
||||
(System/exit 0)))))))
|
||||
|
||||
(defn -main [& args]
|
||||
(comment (cond
|
||||
(cond
|
||||
(= (count args) 1)
|
||||
(let [file (first args)
|
||||
source (loader/load-import file)]
|
||||
(run file source))
|
||||
|
||||
:else (repl/launch))))
|
||||
:else (repl/launch)))
|
|
@ -11,8 +11,8 @@
|
|||
[ludus.loader :as loader]
|
||||
[ludus.token :as token]
|
||||
[ludus.process :as process]
|
||||
[clojure.pprint :as pp]
|
||||
[clojure.set]))
|
||||
[clojure.set]
|
||||
[clojure.string]))
|
||||
|
||||
(def ^:dynamic self @process/current-pid)
|
||||
|
||||
|
@ -301,7 +301,7 @@
|
|||
|
||||
: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]
|
||||
(merge ctx new-ctx))
|
||||
|
@ -607,9 +607,15 @@
|
|||
(if (::loader/error (ex-data e))
|
||||
(throw (ex-info (ex-message e) {:ast ast}))
|
||||
(throw e))))
|
||||
result (-> source (scanner/scan) (parser/parse) (interpret-file path))]
|
||||
(vswap! ctx update-ctx {name result})
|
||||
result
|
||||
parsed (->> source (scanner/scan) :tokens (p/apply-parser g/script))]
|
||||
(if (p/fail? parsed)
|
||||
(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]
|
||||
|
@ -883,35 +889,42 @@
|
|||
:dict (interpret-dict ast ctx)
|
||||
|
||||
: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
|
||||
(defn interpret-file [parsed file]
|
||||
(defn interpret-file [source path parsed]
|
||||
(try
|
||||
(let [base-ctx (volatile! (merge {:file file} prelude/prelude process/process))]
|
||||
(interpret-ast (::parser/ast parsed) base-ctx))
|
||||
(let [base-ctx (volatile! {::parent (volatile! prelude/prelude) :file path})]
|
||||
(interpret-ast parsed base-ctx))
|
||||
(catch clojure.lang.ExceptionInfo e
|
||||
(println "Ludus panicked in" file)
|
||||
(println "On line" (get-in (ex-data e) [:ast :token ::token/line]))
|
||||
(println "Ludus panicked in" path)
|
||||
(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))
|
||||
(System/exit 67))))
|
||||
|
||||
;; TODO: update this to use new parser pipeline & new AST representation
|
||||
(defn interpret [parsed file]
|
||||
(defn interpret [source path parsed]
|
||||
(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/start-vm)
|
||||
(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))
|
||||
(process/stop-vm)
|
||||
result)))
|
||||
(catch clojure.lang.ExceptionInfo e
|
||||
(println "Ludus panicked in" file)
|
||||
(println "On line" (get-in (ex-data e) [:ast :token ::token/line]))
|
||||
(println "Ludus panicked in" path)
|
||||
(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))
|
||||
(System/exit 67))))
|
||||
|
||||
|
@ -927,10 +940,11 @@
|
|||
result)))
|
||||
(catch clojure.lang.ExceptionInfo e
|
||||
(process/stop-vm)
|
||||
(println "Ludus panicked!")
|
||||
(println "On line" (get-in (ex-data e) [:ast :token :line]))
|
||||
(println "Ludus panicked on line " (get-in (ex-data e) [:ast :token :line]))
|
||||
(println "> " (get-in (ex-data e) [:ast :token]))
|
||||
(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
|
||||
(defn interpret-repl
|
||||
|
@ -941,7 +955,7 @@
|
|||
(try
|
||||
(process/start-vm)
|
||||
(with-bindings {#'self pid}
|
||||
(let [result (interpret-ast (::parser/ast parsed) ctx)]
|
||||
(let [result (interpret-ast parsed ctx)]
|
||||
{:result result :ctx ctx :pid pid}))
|
||||
(catch clojure.lang.ExceptionInfo e
|
||||
(println "Ludus panicked!")
|
||||
|
@ -952,7 +966,7 @@
|
|||
(try
|
||||
(process/start-vm)
|
||||
(with-bindings {#'self pid}
|
||||
(let [result (interpret-ast (::parser/ast parsed) ctx)]
|
||||
(let [result (interpret-ast parsed ctx)]
|
||||
{:result result :ctx ctx :pid pid}))
|
||||
(catch clojure.lang.ExceptionInfo e
|
||||
(println "Ludus panicked!")
|
||||
|
@ -961,11 +975,9 @@
|
|||
)))))
|
||||
|
||||
|
||||
(do
|
||||
(comment
|
||||
(def source "
|
||||
let xs = [1, 2, 3]
|
||||
let ys = #{:a 1, :b 2}
|
||||
get (:c, ys)
|
||||
let 2 = 1
|
||||
")
|
||||
|
||||
(println "")
|
||||
|
|
|
@ -2,7 +2,8 @@
|
|||
(:require
|
||||
[ludus.data :as data]
|
||||
[ludus.show :as show]
|
||||
[ludus.draw :as d]))
|
||||
;[ludus.draw :as d]
|
||||
))
|
||||
|
||||
;; TODO: make eq, and, or special forms that short-circuit
|
||||
;; Right now, they evaluate all their args
|
||||
|
@ -102,10 +103,6 @@
|
|||
(get map key default)
|
||||
default)))})
|
||||
|
||||
(def draw {:name "draw"
|
||||
::data/type ::data/clj
|
||||
:body d/ludus-draw})
|
||||
|
||||
(def first- {:name "first"
|
||||
::data/type ::data/clj
|
||||
:body (fn [v] (second v))})
|
||||
|
@ -191,7 +188,6 @@
|
|||
"assoc" assoc-
|
||||
"conj" conj-
|
||||
"get" get-
|
||||
"draw" draw
|
||||
"type" type-
|
||||
"clj" clj
|
||||
"first" first-
|
||||
|
|
|
@ -1,12 +1,15 @@
|
|||
(ns ludus.repl
|
||||
(:require
|
||||
[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.prelude :as prelude]
|
||||
[ludus.show :as show]
|
||||
[ludus.data :as data]
|
||||
[ludus.process :as process]))
|
||||
;[ludus.process :as process]
|
||||
))
|
||||
|
||||
(declare repl-prelude new-session)
|
||||
|
||||
|
@ -20,7 +23,7 @@
|
|||
(println "\nGoodbye!")
|
||||
(System/exit 0))
|
||||
|
||||
(def base-ctx (merge prelude/prelude process/process
|
||||
(def base-ctx (merge prelude/prelude ;process/process
|
||||
{::repl true
|
||||
"repl"
|
||||
{::data/struct true
|
||||
|
@ -91,12 +94,19 @@
|
|||
(= "" input) (recur)
|
||||
|
||||
:else
|
||||
(let [parsed (-> input (scanner/scan) (parser/parse))
|
||||
{result :result ctx :ctx pid- :pid}
|
||||
(let [parsed (->> input
|
||||
(scanner/scan)
|
||||
:tokens
|
||||
(p/apply-parser g/script))]
|
||||
(if (= :err (:status parsed))
|
||||
(do
|
||||
(println (p/err-msg parsed))
|
||||
(recur))
|
||||
(let [{result :result ctx :ctx pid- :pid}
|
||||
(if pid
|
||||
(interpreter/interpret-repl parsed orig-ctx pid)
|
||||
(interpreter/interpret-repl parsed orig-ctx))]
|
||||
(if (= result ::interpreter/error)
|
||||
(if (= result :error)
|
||||
(recur)
|
||||
(do
|
||||
(println (show/show result))
|
||||
|
@ -104,7 +114,7 @@
|
|||
(swap! session-atom #(assoc % :ctx ctx)))
|
||||
(when (not (= pid pid-))
|
||||
(swap! session-atom #(assoc % :pid pid-)))
|
||||
(recur))))))))
|
||||
(recur))))))))))
|
||||
|
||||
(defn launch []
|
||||
(println "Welcome to Ludus (v. 0.1.0-alpha)")
|
||||
|
|
Loading…
Reference in New Issue
Block a user