refactoring

This commit is contained in:
XeroOl 2022-08-07 22:10:55 -05:00
parent 80d4455ed3
commit bb13e9b809
No known key found for this signature in database
GPG Key ID: 9DD4B4B4DAED0322
7 changed files with 89 additions and 118 deletions

View File

@ -1,2 +0,0 @@
(match [0 10]
[1 a] a)

View File

@ -2,7 +2,7 @@
(local util (require :fennel-ls.util))
(λ get-ast-info [?ast info]
"find a given key of info from an AST object"
;; find a given key of info from an AST object
(or (?. (getmetatable ?ast) info)
(. ?ast info)))

View File

@ -8,70 +8,62 @@
(local -λ- (fennel.sym :λ))
(local -lambda- (fennel.sym :lambda))
;; types of things in the file.references list
{:from "a literal range" :to "a literal range"}
{:from "a literal range" :to-other-module ["modname" "key1" "key2" "key3" "key4" "etc"]}
(λ table? [t]
(= :table (type t)))
(λ string? [t]
(= :string (type t)))
(λ multisym? [t]
;; check if t is a symbol with multiple parts, eg. foo.bar.baz
(and (fennel.sym? t)
(let [t (tostring t)]
(or (t:find "%.")
(t:find ":")))))
(λ iter [t]
;; iterate through a list, sequence, or table
(if (or (fennel.list? t)
(fennel.sequence? t))
(ipairs t)
(pairs t)))
(local has-tables-mt
{:__index
(λ [self key]
(let [val {}]
(tset self key val)
val))})
(λ analyze [file]
(assert file.text (fennel.view file))
(assert file.uri)
(set file.references [])
"Compile the file, and record all the useful information from the compiler into the file object"
(local definitions
(doto {}
(setmetatable
{:__index
(λ [self key]
(let [val {}]
(tset self key val)
val))})))
(local references [])
(local definitions (doto {} (setmetatable has-tables-mt)))
(λ find-variable [name ?scope]
(λ find-definition [name ?scope]
(when ?scope
(or (. definitions ?scope name)
(find-variable name ?scope.parent))))
(find-definition name ?scope.parent))))
(λ reference [ast scope]
"called whenever a variable is referenced"
;; Add a reference to the references
(assert (fennel.sym? ast))
;; find reference
(let [name (string.match (tostring ast) "[^%.:]+")
target (find-variable (tostring name) scope)]
(tset file.references ast target)))
target (find-definition (tostring name) scope)]
(tset references ast target)))
(λ define [?definition binding scope]
"called whenever a local variable or destructure statement is introduced"
;; Add a definition to the definitions
;; recursively explore the binding (which, in the general case, is a destructuring assignment)
;; right now I'm not keeping track of *how* the symbol was destructured: just finding all the symbols for now.
(λ recurse [binding]
(if (fennel.sym? binding)
(tset (. definitions scope)
(tostring binding)
{: binding :definition ?definition})
(table? binding)
(each [k v (iter binding)]
(recurse v))))
(tset (. definitions scope)
(tostring binding)
{: binding :definition ?definition})
(= :table (type binding))
(each [k v (iter binding)]
(recurse v))))
(recurse binding))
(λ define-function-name [ast scope]
;; add a function definition to the definitions
(match ast
(where [_fn name args]
(and (fennel.sym? name)
@ -83,23 +75,26 @@
:definition ast})))
(λ define-function-args [ast scope]
;; add the definitions of function arguments to the definitions
(local args
(match ast
(where [_fn args] (fennel.sequence? args)) args
(where [_fn _name args] (fennel.sequence? args)) args))
(each [_ argument (ipairs args)]
(define nil argument scope))) ;; we say function arguments are "nil" for now
(define nil argument scope))) ;; we say function arguments are set to nil
(λ define-function [ast scope]
"Introduces the various symbols exported by a function.
This cannot be done through the :fn feature of the compiler plugin system, because it needs to be
called *before* the body of the function is processed."
;; handle the definitions of a function
(define-function-name ast scope)
(define-function-args ast scope))
(λ call [ast scope]
"called for every function call. Most calls aren't interesting, but fn is"
;; handles every function call
;; Most calls aren't interesting, but here's the list of the ones that are:
(match ast
;; This cannot be done through the :fn feature of the compiler plugin system
;; because it needs to be called *before* the body of the function is processed.
;; TODO check if hashfn needs to be here
[-fn-]
(define-function ast scope)
[-λ-]
@ -111,16 +106,25 @@ called *before* the body of the function is processed."
{:name "fennel-ls"
:versions ["1.2.0"]
:symbol-to-expression reference
: call
:call call
:destructure define})
(set file.ast (icollect [ok ast (fennel.parser file.text)]
ast))
(local ast
(icollect [ok ast (fennel.parser file.text)]
ast))
(local scope (fennel.scope))
(each [_i form (ipairs file.ast)]
(each [_i form (ipairs ast)]
(fennel.compile form
{:filename file.uri
: scope
:plugins [plugin]})))
:plugins [plugin]}))
;; write things back to the file object
(set file.references references)
;; (set file.definitions definitions) ;; not needed yet
(set file.ast ast))
;; (set file.analyzed? true))
{: analyze}

View File

@ -45,7 +45,6 @@
file)))
{: get-by-uri
: get-by-module
: set-uri-contents

View File

@ -64,94 +64,76 @@ Every time the client sends a message, it gets handled by a function in the corr
{:capabilities capabilities
:serverInfo {:name "fennel-ls" :version "0.0.0"}})
(λ string? [j]
(= (type j) :string))
(λ get-assignment-of-symbol [file symbol]
;; TODO inline
(. file.references symbol))
;; These three functions are mutually recursive
(var (search-item
search-assignment
search-symbol)
(var
(search-assignment
search-symbol
search)
nil)
(set search-item
(λ search-item [self file item stack]
(if ;; table
(fennelutils.table? item)
(if (. item (. stack (length stack)))
(search-item self file (. item (table.remove stack)) stack)
nil)
;; symbol
(sym? item)
(search-symbol self file item stack)
;; TODO
;; functioncall (into body)
;; require functioncall (into module)
;; else
true (error (.. "I don't know what to do with " (fennel.view item))))))
(set search-assignment
(λ search-assignment [self file binding ?definition stack]
(if (= 0 (length stack))
binding
;; TODO sift down the binding
(search-item self file ?definition stack))))
(search self file ?definition stack))))
(set search-symbol
(λ search-symbol [self file symbol stack]
(let [split (util.multi-sym-split symbol)]
(for [i (length split) 2 -1]
(table.insert stack (. split i))))
(match (get-assignment-of-symbol file symbol)
(match (. file.references symbol)
to (search-assignment self file to.binding to.definition stack)
nil nil)))
(λ iter [t]
(if (or (fennel.list? t)
(fennel.sequence? t))
(ipairs t)
(pairs t)))
(set search
(λ search [self file item stack]
(if (fennelutils.table? item)
(if (. item (. stack (length stack)))
(search self file (. item (table.remove stack)) stack)
nil)
(sym? item)
(search-symbol self file item stack)
;; TODO
;; functioncall (continue searching in body)
;; require call (search in the new module)
:else (error (.. "I don't know what to do with " (fennel.view item))))))
(λ find-symbol* [ast byte]
(λ find-symbol [ast byte ?recursively-called]
(if (not= :table (type ast))
nil
(parser.does-not-contain? ast byte)
nil
(sym? ast)
ast
(or (fennel.list? ast)
(or (not ?recursively-called)
(fennel.list? ast)
(fennel.sequence? ast))
;; TODO binary search
(accumulate [result nil
_ v (ipairs ast) &until (or result (parser.past? v byte))]
(find-symbol* v byte))
:else (accumulate [result nil
k v (pairs ast) &until result]
(or
(find-symbol* k byte)
(find-symbol* v byte)))))
(λ find-symbol [ast byte]
;; TODO binary search
(accumulate [result nil
_ v (ipairs ast) &until (or result (parser.past? v byte))]
(find-symbol* v byte)))
(accumulate
[result nil
_ v (ipairs ast)
&until (or result (parser.past? v byte))]
(find-symbol v byte true))
:else
(accumulate
[result nil
k v (pairs ast)
&until result]
(or
(find-symbol k byte true)
(find-symbol v byte true)))))
(λ requests.textDocument/definition [self send {: position :textDocument {: uri}}]
(local file (state.get-by-uri self uri))
(local byte (util.pos->byte file.text position.line position.character))
(local stack [])
(match (find-symbol file.ast byte)
symbol
(match (search-symbol self file symbol stack)
(match (search-symbol self file symbol [])
definition
{:range (parser.range file.text definition)
:uri uri})
nil nil))
:uri uri})))
(λ notifications.textDocument/didChange [self send {: contentChanges :textDocument {: uri}}]
(local file (state.get-by-uri self uri))
@ -163,6 +145,7 @@ Every time the client sends a message, it gets handled by a function in the corr
(set file.open? true))
(λ notifications.textDocument/didClose [self send {:textDocument {: uri}}]
;; TODO fix
(local file (state.get-by-uri self uri))
(set file.open? false))
@ -175,4 +158,3 @@ Every time the client sends a message, it gets handled by a function in the corr
{: requests
: notifications}

View File

@ -53,9 +53,10 @@ These functions are all pure functions, which makes me happy."
(text:sub end))))
(λ apply-changes [initial-text contentChanges]
"Take's a list of Language-Server-Protocol contentChanges and applies them to a piece of text. Doesn't yet handle UTF8 UTF16 magic from the protocol"
(accumulate [contents initial-text
_ change (ipairs contentChanges)]
"Takes a list of Language-Server-Protocol `contentChanges` and applies them to a piece of text. Doesn't yet handle UTF8 UTF16 magic from the protocol"
(accumulate
[contents initial-text
_ change (ipairs contentChanges)]
(match change
;; Handle a change
{:range {: start : end} : text}
@ -78,9 +79,6 @@ These functions are all pure functions, which makes me happy."
(icollect [word (: (.. sym ".") :gmatch "(.-)[%.:]")]
word))
(fn reversed [tab])
{: uri->path
: path->uri
: pos->byte

View File

@ -1,10 +0,0 @@
(var (a b c) nil)
(set a (fn a []
(b)))
(set b (fn b []
(print "yay")))
(a)