src/wam/compiler/1-parsing.lisp @ a095d20eeebc
Split up the damn compiler.lisp file
| author | Steve Losh <steve@stevelosh.com> |
|---|---|
| date | Fri, 15 Jul 2016 19:37:17 +0000 |
| parents | (none) |
| children | e555488c15e6 |
(in-package #:bones.wam) ;;;; .-,--. ;;;; '|__/ ,-. ,-. ,-. . ,-. ,-. ;;;; ,| ,-| | `-. | | | | | ;;;; `' `-^ ' `-' ' ' ' `-| ;;;; ,| ;;;; `' (defclass node () ()) (defclass top-level-node (node) ((functor :accessor node-functor :type symbol :initarg :functor) (arity :accessor node-arity :type arity :initarg :arity) (arguments :accessor node-arguments :type list :initarg :arguments))) (defclass vanilla-node (node) ((register :accessor node-register :type register :documentation "The register allocated to store this node."))) (defclass structure-node (vanilla-node) ((functor :accessor node-functor :type symbol :initarg :functor) (arity :accessor node-arity :type arity :initarg :arity) (arguments :accessor node-arguments :type list :initarg :arguments))) (defclass variable-node (vanilla-node) ((variable :accessor node-variable :type symbol :initarg :variable))) (defclass argument-variable-node (variable-node) ((secondary-register :accessor node-secondary-register :type register :documentation "The register that actually holds the variable (NOT the argument register)."))) (defclass list-node (vanilla-node) ((head :accessor node-head :type node :initarg :head) (tail :accessor node-tail :type node :initarg :tail))) (defclass lisp-object-node (vanilla-node) ((object :accessor node-object :type t :initarg :object))) ; todo functor -> fname (defun* make-top-level-node ((functor symbol) (arity arity) (arguments list)) (:returns top-level-node) (values (make-instance 'top-level-node :functor functor :arity arity :arguments arguments))) (defun* make-structure-node ((functor symbol) (arity arity) (arguments list)) (:returns structure-node) (values (make-instance 'structure-node :functor functor :arity arity :arguments arguments))) (defun* make-variable-node ((variable symbol)) (:returns variable-node) (values (make-instance 'variable-node :variable variable))) (defun* make-argument-variable-node ((variable symbol)) (:returns variable-node) (values (make-instance 'argument-variable-node :variable variable))) (defun* make-list-node ((head node) (tail node)) (:returns list-node) (values (make-instance 'list-node :head head :tail tail))) (defun* make-lisp-object-node ((object t)) (:returns lisp-object-node) (values (make-instance 'lisp-object-node :object object))) (defgeneric* node-children (node) (:returns list) "Return the children of the given node. Presumably these will need to be traversed when allocating registers.") (defmethod node-children ((node vanilla-node)) (list)) (defmethod node-children ((node top-level-node)) (node-arguments node)) (defmethod node-children ((node structure-node)) (node-arguments node)) (defmethod node-children ((node list-node)) (list (node-head node) (node-tail node))) (defun* nil-node-p ((node node)) (:returns boolean) "Return whether the given node is the magic nil/0 constant." (and (typep node 'structure-node) (eql (node-functor node) nil) (zerop (node-arity node)))) (defparameter *dump-node-indent* 0) (defun print-node-register (node stream &optional space-before) (when (slot-boundp node 'register) (format stream (if space-before " ~A =" "~A = ") (node-register node)))) (defun print-node-secondary-register (node stream &optional space-before) (when (slot-boundp node 'secondary-register) (format stream (if space-before " ~A =" "~A = ") (node-secondary-register node)))) (defgeneric dump-node (node)) (defmethod dump-node ((node node)) (format t "~VAAN NODE" *dump-node-indent* "")) (defmethod dump-node ((node variable-node)) (format t "~VA#<VAR" *dump-node-indent* "") (print-node-register node t t) (format t " ~S>" (node-variable node))) (defmethod dump-node ((node argument-variable-node)) (format t "~VA#<VAR" *dump-node-indent* "") (print-node-register node t t) (print-node-secondary-register node t t) (format t " ~S>" (node-variable node))) (defmethod dump-node ((node structure-node)) (format t "~VA#<STRUCT " *dump-node-indent* "") (print-node-register node t) (format t "~A/~D" (node-functor node) (node-arity node)) (let ((*dump-node-indent* (+ *dump-node-indent* 4))) (dolist (a (node-arguments node)) (terpri) (dump-node a))) (format t ">")) (defmethod dump-node ((node list-node)) (format t "~VA#<LIST" *dump-node-indent* "") (print-node-register node t t) (let ((*dump-node-indent* (+ *dump-node-indent* 4))) (loop :for element = node :then tail :while (typep element 'list-node) :for head = (node-head element) :for tail = (node-tail element) :do (progn (terpri) (dump-node head)) :finally (when (not (nil-node-p element)) (format t "~%~VA.~%" *dump-node-indent* "") (dump-node element)))) (format t ">")) (defmethod dump-node ((node lisp-object-node)) (format t "~VA#<LISP OBJECT " *dump-node-indent* "") (print-node-register node t) (format t "~A>" (lisp-object-to-string (node-object node)))) (defmethod dump-node ((node top-level-node)) (format t "#<~A/~D" (node-functor node) (node-arity node)) (let ((*dump-node-indent* 4)) (dolist (n (node-arguments node)) (terpri) (dump-node n))) (format t ">")) (defmethod print-object ((node node) stream) (let ((*standard-output* stream)) (dump-node node))) (defun* parse-list ((contents list)) (:returns node) (if contents (make-list-node (parse (car contents)) (parse-list (cdr contents))) (make-structure-node 'nil 0 ()))) (defun* parse-list* ((contents list)) (:returns node) (destructuring-bind (next . remaining) contents (if (null remaining) (parse next) (make-list-node (parse next) (parse-list* remaining))))) (defun* parse (term &optional top-level-argument) (:returns node) (cond ((variablep term) (if top-level-argument (make-argument-variable-node term) (make-variable-node term))) ((symbolp term) (parse (list term))) ; c/0 -> (c/0) ((consp term) (destructuring-bind (functor . arguments) term (when (not (symbolp functor)) (error "Cannot parse term ~S because ~S is not a valid functor." term functor)) (case functor (list (parse-list arguments)) (list* (parse-list* arguments)) (t (make-structure-node functor (length arguments) (mapcar #'parse arguments)))))) ((numberp term) (make-lisp-object-node term)) (t (error "Cannot parse term ~S into a Prolog term." term)))) (defun* parse-top-level (term) (:returns top-level-node) (typecase term (symbol (parse-top-level (list term))) ; c/0 -> (c/0) (cons (destructuring-bind (functor . arguments) term (when (not (symbolp functor)) (error "Cannot parse top-level term ~S because ~S is not a valid functor." term functor)) (make-top-level-node functor (length arguments) (mapcar (lambda (a) (parse a t)) arguments)))) (t (error "Cannot parse top-level term ~S into a Prolog term." term))))