Account Options

  1. Sign in
Google Groups Home
« Groups Home
a hardware Lisp interpreter
There are currently too many topics in this group that display first. To make this topic appear first, remove this option from another topic.
There was an error processing your request. Please try again.
flag
  3 messages - Collapse all  -  Translate all to Translated (View all originals)
The group you are posting to is a Usenet group. Messages posted to this group will make your email address visible to anyone on the Internet.
Your reply message has not been sent.
Your post was successful
 
From:
To:
Cc:
Followup To:
Add Cc | Add Followup-to | Edit Subject
Subject:
Validation:
For verification purposes please type the characters you see in the picture below or the numbers you hear by clicking the accessibility icon. Listen and type the numbers you hear
 
Frank Buss  
View profile  
 More options Jun 16 2006, 9:20 pm
Newsgroups: comp.lang.lisp
From: Frank Buss <f...@frank-buss.de>
Date: Sat, 17 Jun 2006 03:20:49 +0200
Local: Fri, Jun 16 2006 9:20 pm
Subject: a hardware Lisp interpreter
My goal is to write an interpreter, which uses a state machine and not the
Common Lisp call stack, because then it is easier to translate it to VHDL.
I think I can simplify the source below a bit, but I like some ideas, which
are inspired from SECD and other implementations:

- there is a variables stack, which stores variable/value pairs, where the
car of a pair is the variable name and the cdr is the value.

- functions are stored in the form (parameterlist . body), e.g. ((list) .
(car (cdr list))) for the cadr function

- if a list instead of a symbol is the car of an expression, it is
interpreted as a function, so you could write this:
(@eval '(((a b) . (cons a b)) 1 2))
and it returns (1 . 2). This is the same like "lambda". I wonder why Common
Lisp has an extra lambda macro for this?

I think with the lambda construct in theory it should be possible to define
a "let" semantic and with this you can write everything you need. But I'll
add a "let" operator (with implicit progn) and a "set" function, to make
programming for this system a bit easier.

What do you think about it?

(defun test ()
  (assert (equalp 1 (@eval 1)))
  (assert (equalp 3 (@eval '(car (cdr (cdr '(1 2 3)))))))
  (assert (equalp '(1 . 2) (@eval '(cons 1 2))))
  (assert (equalp '(1 . 2) (@eval '(((a b) . (cons)) 1 2)))))

(defparameter *variables* nil)
(defparameter *data-stack* nil)
(defparameter *state-stack* nil)
(defparameter *eval-stack* nil)
(defparameter *state* nil)
(defparameter *eval-state* nil)
(defparameter *expression* nil)
(defparameter *stop* nil)

(defun lookup-variable (search-name)
  (loop for (name . value) in *variables* do
        (when (eql name search-name)
          (return-from lookup-variable value))))

(defstruct eval-state
  parameters
  parameter-names
  parameter
  parameter-name
  body
  variables-before-function
  variables-for-function
  function-name)

(defun init-machine ()
  (setf *variables* '())
  (setf *data-stack* '())
  (setf *state-stack* '())
  (setf *eval-stack* '())
  (setf *state* 'start)
  (setf *stop* nil)
  (setf *eval-state* nil)
  (push '(car . ((list))) *variables*)
  (push '(cdr . ((list))) *variables*)
  (push '(cadr . ((list) . (car (cdr list)))) *variables*)
  (push '(cons . ((a b))) *variables*)
  (push '(quote . ((a))) *variables*))

(defun start-state ()
  (let ((pop-state t))
    (if (atom *expression*)
        (if (numberp *expression*)
            (push *expression* *data-stack*)
          (push (lookup-variable *expression*) *data-stack*))
      (let ((function-or-function-name (car *expression*)))
        (cond ((consp function-or-function-name)
               (let ((parameter-names (car function-or-function-name))
                     (body (cdr function-or-function-name))
                     (parameters (cdr *expression*)))
                 (push *eval-state* *eval-stack*)
                 (setf *eval-state* (make-eval-state
                                     :function-name nil
                                     :parameters parameters
                                     :parameter-names parameter-names
                                     :body body
                                     :variables-before-function *variables*
                                     :variables-for-function *variables*)
                       *state* 'eval-parameters
                       pop-state nil)))
              ((eql function-or-function-name 'quote)
               (push (cadr *expression*) *data-stack*))
              (t
               (let ((parameters (cdr *expression*))
                     (function (lookup-variable
function-or-function-name)))
                 (push *eval-state* *eval-stack*)
                 (setf *eval-state* (make-eval-state
                                     :function-name function-or-function-name
                                     :parameters parameters
                                     :parameter-names (car function)
                                     :body (cdr function)
                                     :variables-before-function *variables*
                                     :variables-for-function *variables*)
                       *state* 'eval-parameters
                       pop-state nil))))))
    (when pop-state
      (let ((next-state (pop *state-stack*)))
        (unless next-state (setf *stop* t))
        (setf *state* next-state)))))

(defun eval-parameters-state ()
  (setf (eval-state-parameter *eval-state*) (pop (eval-state-parameters
*eval-state*))
        (eval-state-parameter-name *eval-state*) (pop
(eval-state-parameter-names *eval-state*)))
  (if (and (eval-state-parameter *eval-state*) (eval-state-parameter-name
*eval-state*))
      (progn
        (push 'set-parameter *state-stack*)
        (setf *state* 'start
              *expression* (eval-state-parameter *eval-state*)))
    (progn
      (setf *variables* (eval-state-variables-for-function *eval-state*))
      (let ((function-name (eval-state-function-name *eval-state*))
            (pop-state t))
        (cond ((eql function-name 'car)
               (let ((list (lookup-variable 'list)))
                 (push (car list) *data-stack*)))
              ((eql function-name 'cdr)
               (let ((list (lookup-variable 'list)))
                 (push (cdr list) *data-stack*)))
              ((eql function-name 'cons)
               (let ((a (lookup-variable 'a))
                     (b (lookup-variable 'b)))
                 (push (cons a b) *data-stack*)))
              (t
               (setf *state* 'start
                     pop-state nil
                     *expression* (eval-state-body *eval-state*))))
        (when pop-state
          (setf *variables* (eval-state-variables-before-function
*eval-state*))
          (setf *eval-state* (pop *eval-stack*))
          (if *eval-state*
              (let ((next-state (pop *state-stack*)))
                (unless next-state (setf *stop* t))
                (setf *state* next-state))
            (setf *stop* t)))))))

(defun set-parameter-state ()
  (let ((variable (cons (eval-state-parameter-name *eval-state*) (pop
*data-stack*))))
    (push variable (eval-state-variables-for-function *eval-state*)))
  (setf *state* 'eval-parameters))

(defun @eval (expression)
  (init-machine)
  (setf *expression* expression)
  (loop with count = 0 do
        (incf count)
        (when (> count 1000) (return-from @eval "endless loop"))
        (cond ((eql *state* 'start)
               (start-state))
              ((eql *state* 'eval-parameters)
               (eval-parameters-state))
              ((eql *state* 'set-parameter)
               (set-parameter-state)))
        (when *stop* (loop-finish)))
  (pop *data-stack*))

--
Frank Buss, f...@frank-buss.de
http://www.frank-buss.de, http://www.it4-systems.de


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Levi Campbell  
View profile  
 More options Jun 17 2006, 12:58 pm
Newsgroups: comp.lang.lisp
From: "Levi Campbell" <levicc00...@gmail.com>
Date: 17 Jun 2006 09:58:26 -0700
Local: Sat, Jun 17 2006 12:58 pm
Subject: Re: a hardware Lisp interpreter
First thing I would do is comment the code to help people understand
what you're trying to do and how you're doing it.


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Tolstoy  
View profile  
 More options Jun 17 2006, 1:12 pm
Newsgroups: comp.lang.lisp
From: "Tolstoy" <keith.ir...@gmail.com>
Date: 17 Jun 2006 10:12:24 -0700
Local: Sat, Jun 17 2006 1:12 pm
Subject: Re: a hardware Lisp interpreter

Frank Buss wrote:
> My goal is to write an interpreter, which uses a state machine and not the
> Common Lisp call stack, because then it is easier to translate it to VHDL.

I recall that Structure and Interpretation of Computer Programs has a
chapter/section or so on a register machine for running the interpreter
they develop.  They include memory management, garbage collection, the
definition of various registers for specific purposes and so on.

Might that be of help?

--K


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
End of messages
« Back to Discussions « Newer topic     Older topic »