Skip to content

Commit

Permalink
micros/walker: add tagbody/go form
Browse files Browse the repository at this point in the history
  • Loading branch information
cxxxr committed Dec 17, 2023
1 parent b609fe4 commit 56cbc71
Show file tree
Hide file tree
Showing 3 changed files with 90 additions and 2 deletions.
7 changes: 7 additions & 0 deletions contrib/walker/example.lisp
Original file line number Diff line number Diff line change
Expand Up @@ -286,3 +286,10 @@
(defvar x
(let ((foo 0))
foo))

(tagbody
(uiop:println 1)
(go foo)
(uiop:println 2)
foo
(uiop:println 3))
30 changes: 30 additions & 0 deletions contrib/walker/tests/test-cases.lisp
Original file line number Diff line number Diff line change
Expand Up @@ -3779,3 +3779,33 @@
MICROS/WALKER::B)
(0 0 1))
((2) (0 0 1)))
((MICROS/WALKER:COLLECT-HIGHLIGHT-PATHS
(TAGBODY
(UIOP/STREAM:PRINTLN 1)
(GO MICROS/WALKER::FOO)
(GO MICROS/WALKER::FOO)
(UIOP/STREAM:PRINTLN 2)
MICROS/WALKER::FOO
(UIOP/STREAM:PRINTLN 3))
(5))
((5) (1 3) (1 2)))
((MICROS/WALKER:COLLECT-HIGHLIGHT-PATHS
(TAGBODY
(UIOP/STREAM:PRINTLN 1)
(GO MICROS/WALKER::FOO)
(GO MICROS/WALKER::FOO)
(UIOP/STREAM:PRINTLN 2)
MICROS/WALKER::FOO
(UIOP/STREAM:PRINTLN 3))
(1 3))
((5) (1 3) (1 2)))
((MICROS/WALKER:COLLECT-HIGHLIGHT-PATHS
(TAGBODY
(UIOP/STREAM:PRINTLN 1)
(GO MICROS/WALKER::FOO)
(GO MICROS/WALKER::FOO)
(UIOP/STREAM:PRINTLN 2)
MICROS/WALKER::FOO
(UIOP/STREAM:PRINTLN 3))
(1 2))
((5) (1 3) (1 2)))
55 changes: 53 additions & 2 deletions contrib/walker/walker.lisp
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
(defclass special-variable-binding (binding) ())
(defclass lexical-variable-binding (binding) ())
(defclass lexical-function-binding (binding) ())
(defclass tagbody-binding (binding) ())
(defclass block-binding (binding) ())
(defclass macrolet-binding (binding)
((lambda-list :initarg :lambda-list
Expand Down Expand Up @@ -71,6 +72,9 @@
(defun lookup-macrolet-binding (env name)
(lookup-binding env name 'macrolet-binding))

(defun lookup-tagbody-binding (env name)
(lookup-binding env name 'tagbody-binding))

(defun lookup-block-binding (env name)
(lookup-binding env name 'block-binding))

Expand Down Expand Up @@ -218,6 +222,21 @@
(value :initarg :value
:reader ast-value)))

(defclass tagbody-form (ast)
((statements :type (proper-list (or ast tag))
:initarg :statements
:reader ast-statements)))

(defclass tag (ast <with-binding-form>)
((binding :type tagbody-binding
:initarg :binding
:reader ast-binding)))

(defclass go-form (ast)
((tag :type tag
:initarg :tag
:reader ast-tag)))

(defclass the-form (ast)
((value-type :initarg :value-type
:reader ast-value-type)
Expand Down Expand Up @@ -670,10 +689,30 @@
(unimplemented name :form form :path path))

(defmethod walk-form ((walker walker) (name (eql 'tagbody)) form env path)
(unimplemented name :form form :path path))
(with-walker-bindings (&rest statements) (rest form)
(let* ((bindings (mapcar (lambda (tag)
(make-instance 'tagbody-binding :name tag))
(remove-if-not #'symbolp statements)))
(env (extend-env* env bindings))
(statements
(loop :for statement :in statements
:for n :from 1
:collect (if (symbolp statement)
(make-instance 'tag
:binding (lookup-tagbody-binding env statement)
:path (cons n path))
(walk walker statement env (cons n path))))))
(make-instance 'tagbody-form
:path (cons 0 path)
:statements statements))))

(defmethod walk-form ((walker walker) (name (eql 'go)) form env path)
(unimplemented name :form form :path path))
(with-walker-bindings (tag) (rest form)
(make-instance 'go-form
:tag (make-instance 'tag
:binding (lookup-tagbody-binding env tag)
:path (cons 1 path))
:path (cons 0 path))))

(defmethod walk-form ((walker walker) (name (eql 'the)) form env path)
(with-walker-bindings (value-type form) (rest form)
Expand Down Expand Up @@ -872,6 +911,18 @@
(visit visitor (ast-proctected-form ast))
(visit-foreach visitor (ast-cleanup-forms ast)))

(defmethod visit (visitor (ast tagbody-form))
(visit-foreach visitor (ast-statements ast)))

(defmethod visit (visitor (ast tag))
(values))

(defmethod visit (visitor (ast go-form))
(visit visitor (ast-tag ast)))

(defmethod visit (visitor (ast return-from-form))
(values))

(defmethod visit (visitor (ast block-name-form))
(values))

Expand Down

0 comments on commit 56cbc71

Please sign in to comment.