refactor compiler.fnl

This commit is contained in:
XeroOl 2023-07-18 23:53:19 -05:00
parent 4b8172ac05
commit 3c2bc8c35c
4 changed files with 72 additions and 46 deletions

16
TODO.md
View File

@ -2,8 +2,20 @@
([X] = complete, [ ] = planned) ([X] = complete, [ ] = planned)
My current goal is to work on completions a little bit more. My current goal is to work on completions a little bit more.
- [ ] create a release
- [ ] Fix crash-files.test2 refactor brainstorm:
- [ ] get rid of `bytes` stuff and use "stack" everywhere
- [ ] search caching
- [ ] search depth limit / stop recursion
- [ ] search into calls
- [ ] entry point measurement for reference search
- [ ] arg return count
- [ ] i guess searching into calls could do this?
- [ ] diagnostic code actions
Here is my feature wishlist. I don't expect to ever get all of this done, but these are the sort of enhancements I am thinking about. Here is my feature wishlist. I don't expect to ever get all of this done, but these are the sort of enhancements I am thinking about.
- [X] Able to connect to a client - [X] Able to connect to a client
@ -36,7 +48,7 @@ Here is my feature wishlist. I don't expect to ever get all of this done, but th
- [X] from macros (only on first form in a list) - [X] from macros (only on first form in a list)
- [X] from specials (only on first form in a list) - [X] from specials (only on first form in a list)
- [X] "dot completion" for table fields - [X] "dot completion" for table fields
- [ ] dot completion is aware of a stdlib - [1/2] dot completion is aware of a stdlib
- [ ] actually compliant rules about lexical scope (only see things declared before, not after) - [ ] actually compliant rules about lexical scope (only see things declared before, not after)
- [x] show docs/icons on each suggestion - [x] show docs/icons on each suggestion
- [ ] "dot completion" for metatable `__index` fields - [ ] "dot completion" for metatable `__index` fields

View File

@ -261,7 +261,11 @@ later by fennel-ls.language to answer requests from the client."
(local allowed-globals (local allowed-globals
(icollect [k _ (pairs _G)] (icollect [k _ (pairs _G)]
k)) k))
;; just a couple of globals that are probably not errors
;; TODO make this configurable in a better way
(table.insert allowed-globals :vim) (table.insert allowed-globals :vim)
(table.insert allowed-globals :love)
;; TODO clean up this code. It's awful now that there is error handling ;; TODO clean up this code. It's awful now that there is error handling
(let [macro-file? (= (: file.text :sub 1 24) ";; fennel-ls: macro-file") (let [macro-file? (= (: file.text :sub 1 24) ";; fennel-ls: macro-file")
@ -286,47 +290,35 @@ later by fennel-ls.language to answer requests from the client."
:allowedGlobals allowed-globals :allowedGlobals allowed-globals
:requireAsInclude false :requireAsInclude false
: scope} : scope}
filter-errors (fn _filter-errors [component ...]
(case ...
(true ?item1 ?item2) (values ?item1 ?item2)
(where (or (nil err) (false err)) (not (err:find "^[^\n]-__NOT_AN_ERROR\n")))
(if (os.getenv :TESTING)
(error (.. "\nYou have crashed fennel-ls (or the fennel " component ") with the following message\n:" err
"\n\n^^^ the error message above here is the root problem\n\n"))
(table.insert diagnostics
{:range (line+byte->range self file 1 1)
:message (.. "unrecoverable " component " error: " err)}))))
parser (let [p (fennel.parser file.text file.uri opts)] parser (let [p (fennel.parser file.text file.uri opts)]
;; TODO factor this garbage out into a function (fn _p1 [p2 p3]
(fn p1 [p2 p3] (filter-errors :parser (xpcall #(p p2 p3) fennel.traceback))))
(case (xpcall #(p p2 p3) fennel.traceback)
(true r1 r2) (values r1 r2)
(where (or (nil err) (false err)) (not (err:find "^[^\n]-__NOT_AN_ERROR\n")))
(if (os.getenv :TESTING)
(error (.. "\nYou have crashed the fennel parser or fennel-ls with the following message\n:" err
"\n\n^^^ the error message above here is the root problem\n\n"))
(table.insert diagnostics
{:range (line+byte->range self file 1 1)
:message (.. "unrecoverable compiler error: " err)})))))
ast (icollect [ok ast parser &until (not ok)] ast)] ast (icollect [ok ast parser &until (not ok)] ast)]
;; This is bad; we mutate fennel.macro-path ;; This is bad; we mutate fennel.macro-path
(let [old-macro-path fennel.macro-path] (let [old-macro-path fennel.macro-path]
(set fennel.macro-path (searcher.add-workspaces-to-path macro-path [root-uri])) (set fennel.macro-path
(searcher.add-workspaces-to-path macro-path [root-uri]))
;; compile ;; compile
(each [_i form (ipairs (if macro-file? (ast->macro-ast ast) ast))] (each [_i form (ipairs (if macro-file? (ast->macro-ast ast) ast))]
(case (xpcall #(fennel.compile form opts) fennel.traceback) (filter-errors :compiler (xpcall #(fennel.compile form opts) fennel.traceback)))
(where (or (nil err) (false err)) (not (err:find "^[^\n]-__NOT_AN_ERROR\n")))
(if (os.getenv :TESTING)
(error (.. "\nYou have crashed the fennel compiler or fennel-ls with the following message\n:" err
"\n\n^^^ the error message above here is the root problem\n\n"))
(table.insert diagnostics
{:range (line+byte->range self file 1 1)
:message (.. "unrecoverable compiler error: " err)}))))
(set fennel.macro-path old-macro-path)) (set fennel.macro-path old-macro-path))
; (each [sym target (pairs references)]
; (if
; (sym? target)
; (list? target)
; (= :table (type target))))
; ;; base case???
(set file.ast ast) (set file.ast ast)
(set file.calls calls) (set file.calls calls)
(set file.scope scope) (set file.scope scope)

View File

@ -115,7 +115,6 @@ However, fennel-ls can fall back to positionEncoding=utf-16 (with a performance
:utf-8 :utf-8
:utf-16))) :utf-16)))
(λ init-state [self params] (λ init-state [self params]
(set self.files {}) (set self.files {})
(set self.modules {}) (set self.modules {})

View File

@ -156,26 +156,49 @@
{:label :-?> {:label :-?>
:kind (= kinds.Keyword) :kind (= kinds.Keyword)
:documentation documentation} :documentation documentation}
(not= documentation :nil))))))) (not= documentation :nil)))))
; (it "offers rich information about everything" (it "offers rich information about all builtin/globals"
(let [client (doto (create-client)
(: :open-file! filename "("))
[{:result completions}] (client:completion filename 0 1)
_ (table.sort completions #(< $1.label $2.label))
missing-docs (icollect [_ completion (ipairs completions)]
(if (not (and (= (type completion.label) :string)
(= (type completion.kind) :number)
(= (type completion.documentation) :table)))
completion.label))
allowed-missing-docs {:lua true
:set-forcibly! true
;; TODO remove these from fennel-ls when they become configurable
:love true
:vim true}]
(each [_ completion (ipairs completions)]
(when (not (. allowed-missing-docs completion.label))
(is.same (type completion.label) :string "unlabeled completion")
(is.same (type completion.kind) :number (.. completion.label " needs a kind"))
(is.same (type completion.documentation) :table (.. completion.label " needs documentation"))
(is.not.same completion.documentation :nil (.. completion.label " needs documentation"))))))))
; (it "offers rich information about fields"
; (let [client (doto (create-client) ; (let [client (doto (create-client)
; (: :open-file! filename "(")) ; (: :open-file! filename "(let [x (fn x [a b c] \"\"\"docstring\"\"\" nil)\n t {: x}]\n (t."))
; [{:result completions}] (client:completion filename 0 1) ; [{:result completions}] (client:completion filename 2 5)
; _ (table.sort completions #(< $1.label $2.label)) ; _ (table.sort completions #(< $1.label $2.label))
; count (accumulate [sum 0 _ completion (ipairs completions)] ; missing-docs (icollect [_ completion (ipairs completions)]
; (if (and (= (type completion.label) :string) ; (if (not (and (= (type completion.label) :string)
; (= (type completion.kind) :number) ; (= (type completion.kind) :number)
; (= (type completion.documentation) :table)) ; (= (type completion.documentation) :table)))
; (+ sum 1) ; completion.label))
; sum))] ; allowed-missing-docs {}]
; (if (< count (length completions))
; (print "!!!" (- (length completions) count) "items are missing a label or kind or doc"))
; (each [_ completion (ipairs completions)] ; (each [_ completion (ipairs completions)]
; (is.same (type completion.label) :string "unlabeled completion") ; (when (not (. allowed-missing-docs completion.label))
; (is.same (type completion.kind) :number (.. completion.label " needs a kind")) ; (is.same (type completion.label) :string "unlabeled completion")
; (is.same (type completion.documentation) :table (.. completion.label " needs documentation")) ; (is.same (type completion.kind) :number (.. completion.label " needs a kind"))
; (is.not.same completion.documentation :nil (.. completion.label " needs documentation"))))))) ; (is.same (type completion.documentation) :table (.. completion.label " needs documentation"))
; (is.not.same completion.documentation :nil (.. completion.label " needs documentation"))))))))
;; (it "offers rich information about variable completions") ;; (it "offers rich information about variable completions")