HS parser: fix number+comparison keyword collision, eval-hs uses hs-compile
Parser: skip unit suffix when next ident is a comparison keyword (starts, ends, contains, matches, is, does, in, precedes, follows). Fixes "123 starts with '12'" returning "123starts" instead of true. eval-hs: use hs-compile directly instead of hs-to-sx-from-source with "return " prefix, which was causing the parser to consume the comparison as a string suffix. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
34
sx/sx/spec-introspect/spec-compute-stats.sx
Normal file
34
sx/sx/spec-introspect/spec-compute-stats.sx
Normal file
@@ -0,0 +1,34 @@
|
||||
(define spec-compute-stats
|
||||
(fn
|
||||
(sections source)
|
||||
(let
|
||||
((total 0)
|
||||
(pure 0)
|
||||
(mutation 0)
|
||||
(io 0)
|
||||
(render 0)
|
||||
(lines (len (split source "\n"))))
|
||||
(for-each
|
||||
(fn
|
||||
(section)
|
||||
(for-each
|
||||
(fn
|
||||
(d)
|
||||
(set! total (inc total))
|
||||
(if
|
||||
(empty? (get d "effects"))
|
||||
(set! pure (inc pure))
|
||||
(for-each
|
||||
(fn
|
||||
(eff)
|
||||
(cond
|
||||
(= eff "mutation")
|
||||
(set! mutation (inc mutation))
|
||||
(= eff "io")
|
||||
(set! io (inc io))
|
||||
(= eff "render")
|
||||
(set! render (inc render))))
|
||||
(get d "effects"))))
|
||||
(get section "defines")))
|
||||
sections)
|
||||
{:lines lines :io-count io :render-count render :pure-count pure :mutation-count mutation :test-total 0 :total-defines total})))
|
||||
21
sx/sx/spec-introspect/spec-explore-define.sx
Normal file
21
sx/sx/spec-introspect/spec-explore-define.sx
Normal file
@@ -0,0 +1,21 @@
|
||||
(define spec-explore-define
|
||||
:effects (io)
|
||||
(fn
|
||||
(filename def-name)
|
||||
(let
|
||||
((source (helper "read-spec-file" filename)))
|
||||
(if
|
||||
(starts-with? source ";; spec file not found")
|
||||
nil
|
||||
(let
|
||||
((forms (sx-parse source)) (found nil))
|
||||
(for-each
|
||||
(fn
|
||||
(form)
|
||||
(when
|
||||
(and (not found) (list? form) (> (len form) 1))
|
||||
(let
|
||||
((name (spec-form-name form)))
|
||||
(when (= name def-name) (set! found {:kind (spec-form-kind form) :effects (spec-form-effects form) :params (spec-form-params form) :source (serialize form) :name name})))))
|
||||
forms)
|
||||
found)))))
|
||||
14
sx/sx/spec-introspect/spec-explore.sx
Normal file
14
sx/sx/spec-introspect/spec-explore.sx
Normal file
@@ -0,0 +1,14 @@
|
||||
(define spec-explore
|
||||
:effects (io)
|
||||
(fn
|
||||
(filename title desc)
|
||||
(let
|
||||
((source (helper "read-spec-file" filename)))
|
||||
(if
|
||||
(starts-with? source ";; spec file not found")
|
||||
nil
|
||||
(let
|
||||
((forms (sx-parse source))
|
||||
(sections (spec-group-sections forms source))
|
||||
(stats (spec-compute-stats sections source)))
|
||||
{:stats stats :desc desc :title title :filename filename :platform-interface (list) :sections sections})))))
|
||||
32
sx/sx/spec-introspect/spec-form-effects.sx
Normal file
32
sx/sx/spec-introspect/spec-form-effects.sx
Normal file
@@ -0,0 +1,32 @@
|
||||
(define spec-form-effects
|
||||
(fn
|
||||
(form)
|
||||
(let
|
||||
((result (list)) (found false))
|
||||
(when
|
||||
(> (len form) 3)
|
||||
(for-each
|
||||
(fn
|
||||
(item)
|
||||
(if
|
||||
found
|
||||
(when
|
||||
(and (list? item) (empty? result))
|
||||
(for-each
|
||||
(fn
|
||||
(eff)
|
||||
(append!
|
||||
result
|
||||
(if
|
||||
(= (type-of eff) "symbol")
|
||||
(symbol-name eff)
|
||||
(str eff))))
|
||||
item)
|
||||
(set! found false))
|
||||
(when
|
||||
(and
|
||||
(= (type-of item) "keyword")
|
||||
(= (keyword-name item) "effects"))
|
||||
(set! found true))))
|
||||
(slice form 2)))
|
||||
result)))
|
||||
26
sx/sx/spec-introspect/spec-form-kind.sx
Normal file
26
sx/sx/spec-introspect/spec-form-kind.sx
Normal file
@@ -0,0 +1,26 @@
|
||||
(define spec-form-kind
|
||||
(fn
|
||||
(form)
|
||||
(let
|
||||
((head (symbol-name (first form))))
|
||||
(cond
|
||||
(= head "defcomp")
|
||||
"component"
|
||||
(= head "defisland")
|
||||
"island"
|
||||
(= head "defmacro")
|
||||
"macro"
|
||||
(= head "define")
|
||||
(let
|
||||
((body (last form)))
|
||||
(if
|
||||
(and
|
||||
(list? body)
|
||||
(> (len body) 0)
|
||||
(= (type-of (first body)) "symbol")
|
||||
(or
|
||||
(= (symbol-name (first body)) "fn")
|
||||
(= (symbol-name (first body)) "lambda")))
|
||||
"function"
|
||||
"constant"))
|
||||
:else "unknown"))))
|
||||
14
sx/sx/spec-introspect/spec-form-name.sx
Normal file
14
sx/sx/spec-introspect/spec-form-name.sx
Normal file
@@ -0,0 +1,14 @@
|
||||
(define spec-form-name
|
||||
(fn
|
||||
(form)
|
||||
(if
|
||||
(< (len form) 2)
|
||||
nil
|
||||
(let
|
||||
((head (symbol-name (first form))) (name-part (nth form 1)))
|
||||
(cond
|
||||
(= head "define")
|
||||
(if (= (type-of name-part) "symbol") (symbol-name name-part) nil)
|
||||
(or (= head "defcomp") (= head "defisland") (= head "defmacro"))
|
||||
(if (= (type-of name-part) "symbol") (symbol-name name-part) nil)
|
||||
:else nil)))))
|
||||
35
sx/sx/spec-introspect/spec-form-params.sx
Normal file
35
sx/sx/spec-introspect/spec-form-params.sx
Normal file
@@ -0,0 +1,35 @@
|
||||
(define spec-form-params
|
||||
(fn
|
||||
(form)
|
||||
(if
|
||||
(< (len form) 2)
|
||||
(list)
|
||||
(let
|
||||
((body (nth form (- (len form) 1))))
|
||||
(if
|
||||
(and
|
||||
(list? body)
|
||||
(> (len body) 1)
|
||||
(= (type-of (first body)) "symbol")
|
||||
(or
|
||||
(= (symbol-name (first body)) "fn")
|
||||
(= (symbol-name (first body)) "lambda")))
|
||||
(let
|
||||
((raw-params (nth body 1)))
|
||||
(if
|
||||
(list? raw-params)
|
||||
(map
|
||||
(fn
|
||||
(p)
|
||||
(cond
|
||||
(= (type-of p) "symbol")
|
||||
{:type nil :name (symbol-name p)}
|
||||
(and
|
||||
(list? p)
|
||||
(>= (len p) 3)
|
||||
(= (type-of (first p)) "symbol"))
|
||||
{:type (if (and (>= (len p) 3) (= (type-of (nth p 2)) "symbol")) (symbol-name (nth p 2)) nil) :name (symbol-name (first p))}
|
||||
:else {:type nil :name (str p)}))
|
||||
raw-params)
|
||||
(list)))
|
||||
(list))))))
|
||||
26
sx/sx/spec-introspect/spec-form-signature.sx
Normal file
26
sx/sx/spec-introspect/spec-form-signature.sx
Normal file
@@ -0,0 +1,26 @@
|
||||
(define spec-form-signature
|
||||
(fn
|
||||
(form)
|
||||
(let
|
||||
((head (symbol-name (first form))) (name (spec-form-name form)))
|
||||
(cond
|
||||
(or
|
||||
(= head "define")
|
||||
(= head "defcomp")
|
||||
(= head "defisland")
|
||||
(= head "defmacro"))
|
||||
(let
|
||||
((body (last form)))
|
||||
(if
|
||||
(and
|
||||
(list? body)
|
||||
(> (len body) 0)
|
||||
(= (type-of (first body)) "symbol")
|
||||
(or
|
||||
(= (symbol-name (first body)) "fn")
|
||||
(= (symbol-name (first body)) "lambda")))
|
||||
(let
|
||||
((params (nth body 1)))
|
||||
(str "(" head " " name " (fn " (serialize params) " …))"))
|
||||
(str "(" head " " name " …)")))
|
||||
:else (str "(" head " " name " …)")))))
|
||||
19
sx/sx/spec-introspect/spec-group-sections.sx
Normal file
19
sx/sx/spec-introspect/spec-group-sections.sx
Normal file
@@ -0,0 +1,19 @@
|
||||
(define spec-group-sections
|
||||
(fn
|
||||
(forms source)
|
||||
(let
|
||||
((sections (list))
|
||||
(current-title "Definitions")
|
||||
(current-comment nil)
|
||||
(current-defines (list)))
|
||||
(for-each
|
||||
(fn
|
||||
(form)
|
||||
(when
|
||||
(and (list? form) (> (len form) 1))
|
||||
(let
|
||||
((name (spec-form-name form)))
|
||||
(when name (append! current-defines {:kind (spec-form-kind form) :name name})))))
|
||||
forms)
|
||||
(when (not (empty? current-defines)) (append! sections {:defines current-defines :title current-title :comment current-comment}))
|
||||
sections)))
|
||||
Reference in New Issue
Block a user