Fix line number reporting bugs: look for lines in the right place.

This commit is contained in:
Scott Richmond 2023-12-18 00:20:34 -05:00
parent 4e646101e2
commit be2c91b7dc
7 changed files with 45 additions and 31 deletions

View File

@ -1,7 +1,7 @@
(ns ludus.error (ns ludus.error
(:require [clojure.string :as string])) (:require [clojure.string :as string]))
(defn get-line [source {:keys [line]}] (defn get-line [source line]
(let [lines (string/split-lines source) (let [lines (string/split-lines source)
the_line (nth lines (dec line))] the_line (nth lines (dec line))]
the_line)) the_line))
@ -21,22 +21,26 @@
(defn scan-error [] :TODO) (defn scan-error [] :TODO)
(defn parse-error [source {:keys [trace token]}] (defn parse-error [{:keys [trace token]}]
(let [line (get-line source token) (let [source (:source token)
input (:input token)
line-num (:line token)
line (get-line source line-num)
line-num (:line token) line-num (:line token)
prefix (str line-num ": ") prefix (str line-num ": ")
underline (get-underline source token (count prefix)) underline (get-underline source token (count prefix))
expected (first trace) expected (first trace)
got (:type token) got (:type token)
message (str "Ludus found a parsing error on line " line-num ".\nExpected: " expected "\nGot: " got "\n") message (str "Ludus found a parsing error on line " line-num " in " input ".\nExpected: " expected "\nGot: " got "\n")
] ]
(str message "\n" prefix line "\n" underline) (str message "\n" prefix line "\n" underline)
) )
) )
(defn run-error [source {:keys [line message]}] (defn run-error [{:keys [message token line]}]
(let [source (:source token) input (:input token)]
(if line (if line
(str "Ludus panicked on line " line ":\n" (get-line source {:line line}) "\n" message) (str "Ludus panicked!: " message "\nOn line " line " in " input "\n" (get-line source line))
(str "Ludus panicked!\n" message) (str "Ludus panicked!\n" message)
)) )))

View File

@ -915,11 +915,11 @@
(into {} (map-keys kw->str) ns)) (into {} (map-keys kw->str) ns))
(def ludus-prelude (def ludus-prelude
(let [scanned (scanner/scan prelude/prelude) (let [scanned (scanner/scan prelude/prelude "prelude")
parsed (p/apply-parser g/script (:tokens scanned)) parsed (p/apply-parser g/script (:tokens scanned))
; _ (println "Parse status: " (:status parsed)) ; _ (println "Parse status: " (:status parsed))
; _ (if (= :err (:status parsed)) ; _ (if (= :err (:status parsed))
; (throw (ex-info (error/parse-error prelude/prelude parsed) {}))) ; (throw (ex-info (error/parse-error parsed) {})))
base-ctx (volatile! {::parent (volatile! {"base" 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)
@ -980,6 +980,7 @@
;(pp/pprint (ex-data e)) ;(pp/pprint (ex-data e))
;(throw e) ;(throw e)
{::data/error true {::data/error true
:token (get-in (ex-data e) [:ast :token])
:line (get-in (ex-data e) [:ast :token :line]) :line (get-in (ex-data e) [:ast :token :line])
:message (ex-message e)} :message (ex-message e)}
)))) ))))
@ -991,12 +992,13 @@
(interpret-ast parsed base-ctx) (interpret-ast parsed base-ctx)
(catch Throwable e (catch Throwable e
{::data/error true {::data/error true
:token (get-in (ex-data e) [:ast :token])
:line (get-in (ex-data e) [:ast :token :line]) :line (get-in (ex-data e) [:ast :token :line])
:message (ex-message e)})))) :message (ex-message e)}))))
;; repl ;; repl
(do (comment
(println "***********") (println "***********")
@ -1004,7 +1006,7 @@
panic! (:oh, :no) panic! (:oh, :no)
") ")
(def tokens (-> source scanner/scan :tokens)) (def tokens (-> source (scanner/scan "test input") :tokens))
(def ast (p/apply-parser g/script tokens)) (def ast (p/apply-parser g/script tokens))

View File

@ -31,12 +31,12 @@
#?(:clj value :cljs (clj->js value))) #?(:clj value :cljs (clj->js value)))
(defn run [source] (defn run [source]
(let [user_scanned (s/scan source) (let [user_scanned (s/scan source "user input")
user_tokens (:tokens user_scanned) user_tokens (:tokens user_scanned)
user_parsed (p/apply-parser g/script user_tokens) user_parsed (p/apply-parser g/script user_tokens)
user_result (i/interpret-safe source user_parsed {}) user_result (i/interpret-safe source user_parsed {})
result_str (show/show user_result) result_str (show/show user_result)
post_scanned (s/scan pre/postlude) post_scanned (s/scan pre/postlude "postlude")
post_tokens (:tokens post_scanned) post_tokens (:tokens post_scanned)
post_parsed (p/apply-parser g/script post_tokens) post_parsed (p/apply-parser g/script post_tokens)
post_result (i/interpret-safe source post_parsed {}) post_result (i/interpret-safe source post_parsed {})
@ -48,22 +48,24 @@
(clean-out {:errors (:errors user_tokens)}) (clean-out {:errors (:errors user_tokens)})
(= :err (:status user_parsed)) (= :err (:status user_parsed))
(clean-out {:errors [(error/parse-error source user_parsed)]}) (clean-out {:errors [(error/parse-error user_parsed)]})
(::data/error user_result) (::data/error user_result)
(clean-out (assoc (ld->clj post_result) :errors [(error/run-error source user_result)])) (clean-out (assoc (ld->clj post_result) :errors [(error/run-error user_result)]))
:else :else
(clean-out clj_result) (clean-out clj_result)
) )
)) ))
(do (comment
(def source "
(def source "panic! :oops") a b c
(def tokens (s/scan source)) ")
(-> source run :errors println)
) )

View File

@ -897,10 +897,10 @@ fn unwrap_or {
fn assert! { fn assert! {
"Asserts a condition: returns the value if the value is truthy, panics if the value is falsy. Takes an optional message." "Asserts a condition: returns the value if the value is truthy, panics if the value is falsy. Takes an optional message."
(value) -> if value then value else panic! string ("Assert failed", value) (value) -> if value then value else panic! string ("Assert failed:", value)
(value, message) -> if value (msg, value) -> if value
then value then value
else panic! string ("Assert failed:", message, value) else panic! string ("Assert failed: ", msg, " with ", value)
} }
&&& Turtle & other graphics &&& Turtle & other graphics

View File

@ -51,8 +51,9 @@
(defn- new-scanner (defn- new-scanner
"Creates a new scanner." "Creates a new scanner."
[source] [source input]
{:source source {:source source
:input input
:length (count source) :length (count source)
:errors [] :errors []
:start 0 :start 0
@ -135,7 +136,9 @@
(current-lexeme scanner) (current-lexeme scanner)
literal literal
(:line scanner) (:line scanner)
(:start scanner))))) (:start scanner)
(:source scanner)
(:input scanner)))))
;; TODO: errors should also be in the vector of tokens ;; TODO: errors should also be in the vector of tokens
;; The goal is to be able to be able to hand this to an LSP? ;; The goal is to be able to be able to hand this to an LSP?
@ -146,7 +149,9 @@
(current-lexeme scanner) (current-lexeme scanner)
nil nil
(:line scanner) (:line scanner)
(:start scanner)) (:start scanner)
(:source scanner)
(:input scanner))
err-token (assoc token :message msg)] err-token (assoc token :message msg)]
(-> scanner (-> scanner
(update :errors conj err-token) (update :errors conj err-token)
@ -240,7 +245,7 @@
comm (str char)] comm (str char)]
(let [char (current-char scanner)] (let [char (current-char scanner)]
(if (= \newline char) (if (= \newline char)
(update scanner :line inc) scanner
(recur (advance scanner) (str comm char)))))) (recur (advance scanner) (str comm char))))))
(defn- scan-token [scanner] (defn- scan-token [scanner]
@ -322,8 +327,8 @@
(defn- next-token [scanner] (defn- next-token [scanner]
(assoc scanner :start (:current scanner))) (assoc scanner :start (:current scanner)))
(defn scan [source] (defn scan [source input]
(loop [scanner (new-scanner source)] (loop [scanner (new-scanner source input)]
(if (at-end? scanner) (if (at-end? scanner)
(let [scanner (add-token (add-token scanner :break) :eof)] (let [scanner (add-token (add-token scanner :break) :eof)]
{:tokens (:tokens scanner) {:tokens (:tokens scanner)

View File

@ -1,9 +1,11 @@
(ns ludus.token) (ns ludus.token)
(defn token (defn token
[type text literal line start] [type text literal line start source input]
{:type type {:type type
:lexeme text :lexeme text
:literal literal :literal literal
:line line :line line
:source source
:input input
:start start}) :start start})

View File

@ -1 +0,0 @@
51828