Implement the Sufficiently Simple Syntax macro, some cleanup

This commit is contained in:
Jeremy Penner 2021-08-02 14:49:29 -04:00
parent 5bf35209be
commit e37a7a2153
4 changed files with 54 additions and 23 deletions

View file

@ -1,6 +1,6 @@
-- bootstrap the compiler -- bootstrap the compiler
fennel = require("lib.fennel") fennel = require("lib.fennel")
table.insert(package.loaders, fennel.make_searcher()) table.insert(package.loaders, fennel.searcher)
debug.traceback = fennel.traceback debug.traceback = fennel.traceback
fv = fennel.view fv = fennel.view
pp = function(x) print(fv(x)) end pp = function(x) print(fv(x)) end

View file

@ -34,7 +34,6 @@
; * implement read / write (pointers) ; * implement read / write (pointers)
; * implement write (locals) ; * implement write (locals)
; * implement loops ; * implement loops
; * implement custom special forms (macros?)
; * implement "getters" (subroutine that runs when referenced by name without an explicit call) ; * implement "getters" (subroutine that runs when referenced by name without an explicit call)
(local Object (require :core.object)) (local Object (require :core.object))
@ -70,7 +69,7 @@
(fn [_ iprev] (let [i (if iprev (+ iprev 2) 1)] (fn [_ iprev] (let [i (if iprev (+ iprev 2) 1)]
(when (< i (length l)) (values i (. l i) (. l (+ i 1))))))) (when (< i (length l)) (values i (. l i) (. l (+ i 1)))))))
(fn boolop [self left right negbranch] (fn boolop [self left right branch]
(let [compiled-left (self:compile-expr left) (let [compiled-left (self:compile-expr left)
push-left (when (not= (type right) :number) (self:push)) push-left (when (not= (type right) :number) (self:push))
compiled-compare (if (not push-left) [:cmp right] compiled-compare (if (not push-left) [:cmp right]
@ -79,11 +78,11 @@
[:block [:block
compiled-left compiled-left
compiled-compare compiled-compare
[negbranch :-false-] [branch :-true-]
[:lda 0xffff]
[:bra :-finished-]
:-false-
[:lda 0] [:lda 0]
[:bra :-finished-]
:-true-
[:lda 0xffff]
:-finished- :-finished-
drop-left])) drop-left]))
@ -124,31 +123,33 @@
(where sym (= (type sym) :string) (self:local-offset sym)) [:block [:sec] [:sbc (self:local-offset sym) :s]] (where sym (= (type sym) :string) (self:local-offset sym)) [:block [:sec] [:sbc (self:local-offset sym) :s]]
_ [:block (self:push) (self:compile-expr val) [:sec] [:sbc 0 :s] (self:drop)]))))) _ [:block (self:push) (self:compile-expr val) [:sec] [:sbc 0 :s] (self:drop)])))))
block)) block))
:= (lambda [self lhs rhs] (boolop self lhs rhs :bne)) := (lambda [self lhs rhs] (boolop self lhs rhs :beq))
:not= (lambda [self lhs rhs] (boolop self lhs rhs :beq)) :not= (lambda [self lhs rhs] (boolop self lhs rhs :bne))
:< (lambda [self lhs rhs] (boolop self lhs rhs :bmi)) :< (lambda [self lhs rhs] (boolop self lhs rhs :bmi))
:> (lambda [self lhs rhs] (boolop self rhs lhs :bmi))
:>= (lambda [self lhs rhs] (boolop self lhs rhs :bpl)) :>= (lambda [self lhs rhs] (boolop self lhs rhs :bpl))
:> (lambda [self lhs rhs] (boolop self rhs lhs :bpl)) :<= (lambda [self lhs rhs] (boolop self rhs lhs :bpl))
:<= (lambda [self lhs rhs] (boolop self rhs lhs :bmi))
:not (lambda [self bool] (self:compile-expr [:if bool 0 0xffff])) :not (lambda [self bool] (self:compile-expr [:if bool 0 0xffff]))
:if (lambda [self test iftrue ?iffalse] :if (lambda [self test iftrue ?iffalse]
[:block (lume.concat
(self:compile-expr test) [:block
[:cmp 0] (self:compile-expr test)
[:beq :-elseblock-] [:cmp 0]
(self:compile-expr iftrue) [:beq :-elseblock-]
(when ?iffalse [:bra :-finished-]) (self:compile-expr iftrue)]
:-elseblock- (when ?iffalse [[:bra :-finished-]])
(when ?iffalse (self:compile-expr ?iffalse)) [:-elseblock-]
:-finished-]) (when ?iffalse [(self:compile-expr ?iffalse)])
[:-finished-]))
:fn (lambda [self name args ...] :fn (lambda [self name args ...]
(assert (= (length self.locals) 0)) (assert (= (length self.locals) 0))
(set self.locals (lume.concat args [[:tmp]])) (set self.locals (lume.concat args [[:tmp]]))
(tset self.functions name {:arity (length args) : args :org self.org}) (tset self.functions name {:arity (length args) : args :org self.org})
; todo: maybe handle mutually recursive functions? ; todo: maybe handle mutually recursive functions? (compile-expr only has access to currently-defined functions)
(self.org:append name (self:compile-expr (lume.push [:do ...] [:asm [:rts]]))) (self.org:append name (self:compile-expr (lume.concat [:do ...] [[:asm [:rts]]])))
(assert (= (length self.locals) (+ (length args) 1))) (assert (= (length self.locals) (+ (length args) 1)))
(set self.locals [])) (set self.locals []))
:form (lambda [self name func] (tset self.forms name func))
}) })
(fn Ssc.local-offset [self symbol] (fn Ssc.local-offset [self symbol]
@ -169,8 +170,12 @@
(lume.concat [:block] pre [[:jsr func]] post)) (lume.concat [:block] pre [[:jsr func]] post))
(where [form & args] (. self.forms form)) (where [form & args] (. self.forms form))
((. self.forms form) self (table.unpack args)) ((. self.forms form) self (table.unpack args))
nil [:block]
_ (error (.. "Unrecognized expression " (fv expr))))) _ (error (.. "Unrecognized expression " (fv expr)))))
(pp (: (Ssc) :compile-expr [:let [:x 2 :y 4] [:if [:< :x :y] :x :y]])) (fn Ssc.compile [self ...]
(for [i 1 (select :# ...)]
(self:compile-expr (select i ...)))
self)
Ssc Ssc

24
ssc/macros.fnl Normal file
View file

@ -0,0 +1,24 @@
; Sufficiently Simple Syntax macro
; This is basically just a quote that converts fennel syntax to Lua tables.
; Turns symbols into strings and lists into table literals. Table literals can be used to escape into regular fennel.
; Examples:
; (let (x 1 y 2) (+ "x" :y))
; => [:let [:x 1 :y 2] [:+ :x :y]]
; (form mymacro [(fn [ssc] (ssc:compile-expr [:+ 1 2]))])
; => [:form :mymacro (fn [ssc] (ssc:compile-expr [:+ 1 2]))]
(fn form-to-fnl [form]
(if (sym? form) (tostring form)
(sequence? form) (. form 1) ; escape
(list? form) (icollect [_ inner-form (ipairs form)] (form-to-fnl inner-form))
form))
(fn sss [...]
(let [result `(values)]
(for [i 1 (select :# ...)]
(table.insert result (form-to-fnl (select i ...))))
result))
(fn compile [ssc ...] `(: ,ssc :compile ,(sss ...)))
{: sss : form-to-fnl : compile}

View file

@ -10,6 +10,8 @@
(local translate (require :core.doc.translate)) (local translate (require :core.doc.translate))
(local files (require :game.files)) (local files (require :game.files))
(setmetatable _G nil)
(command.add nil { (command.add nil {
"honeylisp:open-project" (fn [] "honeylisp:open-project" (fn []
(core.command_view:enter "Open Project" (core.command_view:enter "Open Project"