Giter Club home page Giter Club logo

codewalk's Introduction

CODEWALK: a portable codewalker for Common Lisp

This is an incomplete proof-of-concept implementation of a Common Lisp codewalker.

usage

Invoke with:

(walk-subforms FUNCTION FORM)

This is in many ways analogous to mapcar or map, except that FUNCTION should accept two arguments, a keyword SUBFORM-TYPE and a SUBFORM.

current form types

As of writing, [2021-09-03], the SUBFORM-TYPE argument to a walk-subforms visitor may take on the following values:

:block-name

The name of a block, as in block or return-from.

:expr

A Common Lisp expression, suitable for eval.

:catch-tag

A symbol used in catch or throw.

:eval-time

One of the keywords :compile-toplevel, :load-toplevel or :execute, as provided to eval-when.

:function-binding

A symbol which names a new function, to be bound by flet, labels, defun, etc.

:variable-binding

A symbol which names a new variable, to be bound by let, let*, lambda, multiple-value-bind, etc.

:function

A form suitable for the function special form or the #'~ reader macro, i.e. a symbol which names a function or a ~lambda form.

:go-tag

A symbol used in tagbody or go.

:constant

An unevaluated constant object, e.g. in quote.

:type

An unquoted type, as in the or check-type.

:docstring

A constant string, to be used as a documentation string.

:package-name

A constant string or symbol, to be used as a package name.

:place

A form suitable for setf et.al.

examples

print all the subforms of a form

(walk-subforms (lambda (type form)
                 (format t "~&~a is a(n) ~a~%" form type)
                 (values form t))
               '(let ((a (foo))) (bar a)))
;; LET is a(n) FORM-HEAD
;; A is a(n) VARIABLE-BINDING
;; (FOO) is a(n) EXPR
;; FOO is a(n) FUNCTION
;; (BAR A) is a(n) EXPR
;; BAR is a(n) FUNCTION
;; A is a(n) EXPR
;;
;; => (LET ((A (FOO)))
;;      (BAR A))

rename a variable

(walk-subforms (lambda (type form)
                 (form-typecase (type form)
                   ((:variable-binding :expr)
                    (if (eq form 'rename-me)
                        (values 'different-name nil)
                        (values form t)))))
               '(let ((rename-me (rename-me but-not-as-a-function)))
                 (different-function rename-me)))
;; => (LET ((DIFFERENT-NAME (RENAME-ME BUT-NOT-AS-A-FUNCTION)))
;;      (DIFFERENT-FUNCTION DIFFERENT-NAME))

needed work

If possible, you should view this list in Emacs with org-mode, rather than in the GitHub viewer, since it has annotations that GitHub seems to discard.

support declarations and docstrings

Possibly just ignore these? You still have to detect them, though.

Will likely require altering some existing templates to properly handle bodies.

Simple version: instead of treating &body and &rest as equivalent, have &body call alexandria:parse-body on the provided form, while &rest retains its current behavior. This would require some amount of updating existing templates, since some use &body in places that do not accept docstrings or declarations.

different sets of templates for different languages

like, have a set of templates for subforms of ~:type~s, and another for subforms of ~:declaration~s.

support form types like (or :declaration :expr)

If we even want to do this… it’d be quite hard to make matching functions work.

What we’d likely want to do is, when codewalking a form that we believe has type (or :declaration :expr), decide whether it’s a declaration or not, and invoke the visitor function on either :declaration or :expr appropriately, not just pass the form (or :declaration :expr) to the visitor function.

support &key templates

also &allow-other-keys

support defclass~/~defgeneric style options

Like &key arguments, only they’re alists instead of plists.

Likely, the template syntax for this will be &alist, like:

(register-subform-types defgeneric (&rest :variable-binding)
  &alist
  (:documentation :docstring)
  (:method-combination :method-combination)
  (:generic-function-class :class-name)
  (:method-class :class-name)
  (:argument-precedence-order &rest :constant)
  (declare &rest :declaration)
  (:method etc))

Note that I’m not actually clear on how to parse :method forms, but whatever.

inline optionals

Like method qualifiers on defmethod.

support arbitrary traversal functions in place of templates

support lambda lists

At present, lambda et.al. are treated as accepting only required positional arguments, not &optional, &key or &rest arguments.

This will likely involve getting the capability to define special form types which have different behavior than just “visit or recurse.”

support multi-element destructuring of &rest~/~&body

As in setf, whose template should be &body :place :expr.

write templates for remaining Common Lisp special forms and builtin macros

and, or

assert

call-method

case, ccase, ecase

Needs fix: support for multiple alternatives to match, like in (case foo ((a b) (print 'early-letter)))

check-type

cond

declaim

defclass

defconstant

defgeneric

define-compiler-macro

define-condition

define-method-combination

define-modify-macro

define-setf-expander

define-symbol-macro

defmacro

defmethod

defpackage

defparameter

defsetf

defstruct

deftype

defun

defvar

destructuring-bind

do, do*

do-external-symbols, do-all-symbols, do-symbols

dolist, dotimes

formatter

handler-bind

handler-case

ignore-errors

in-package

incf, decf

lambda

Needs improvement: support for complex lambda lists.

locally

loop, loop-finish

macrolet

multiple-value-bind

multiple-value-call

multiple-value-list

multiple-value-prog1

multiple-value-setq

nth-value

pprint-exit-if-list-exhausted, pprint-pop

pprint-logical-block

print-unreadable-object

prog, prog*

prog1, prog2

progv

push, pop

pushnew

quote

remf

restart-bind

restart-case

return

return-from

rotatef

shiftf

setf, psetf

setq, psetq

step, time

symbol-macrolet

tagbody

the

throw

trace, untrace

typecase, ctypecase, etypecase

unwind-protect

when, unless

with-accessors, with-slots

with-compilation-unit

with-condition-restarts

with-hash-table-iterator, with-package-iterator

with-input-from-string, with-output-to-string

with-open-file, with-open-stream

with-simple-restart

with-standard-io-syntax

write tests

new pattern-matching defmacro alternative which also generates a template

codewalk's People

Contributors

gefjon avatar

Stargazers

 avatar  avatar

Watchers

 avatar  avatar

codewalk's Issues

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.