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))))