Eric Stdlib
Eric Stdlib

Reputation: 1572

Implement Lisp eval function in Common Lisp

I am trying to implement a eval function using CLISP.

My motivation: suppose I have a Lisp program like this:

(defun call (arg)
  (cond
    (some-condition (call (other (strange (functions (on arg)))))
    (t nil)
  )
)

(defun mysterious-function (arg)
  (call (strange (functions (on arg))))
)

(mysterious-function 100)       ; only this line can be changed

I want to know what is actually called in (mysterious-function 100).

Currently my idea looks like below, but the obstacles are:

  1. How to look up a symbol (currently using eval)
  2. How to grab a definition of a function (e.g. get something like (defun f (x))) and then parse it
  3. How to detect macro and expand them

Am I in the correct direction?

(defun my-eval (body)
  (cond
    ((typep body 'integer) body)
    ((typep body 'float) body)
    ((typep body 'rational) body)
    ((typep body 'complex) body)
    ((typep body 'boolean) body)
    ((typep body 'symbol) (eval body))
    ((typep body 'list) (eval body))
    (t (error))
  )
)

(my-eval '(mysterious-function 100))

Upvotes: 0

Views: 902

Answers (1)

RowPJ
RowPJ

Reputation: 529

Most of the cases in your code can be replaced with a single check: ((constantp body) body)

As for other cases:

  • You can use boundp to check if a symbol has a global value.
  • To look up a global symbol value you can use symbol-value.
  • fboundp can be used to check if a symbol is globally bound to a function
  • To look up a global function you can use symbol-function to access its function object and can sometimes use function-lambda-expression to retrieve a parseable source code list from the function object. Sometimes this will not work as built in CLISP functions can be defined in C.
  • To check if a symbol has an associated global macro, use macro-function (returns non-nil if it does).
  • To expand a macro form, use macroexpand.

You will probably also need to detect special operators with special-operator-p, and handle them accordingly.

I think what you are trying to do would be simplified if you restrict the code you interpret to macros and user-defined functions as much as possible. I remember reading about a fast-eval function used in genetic programming to skip the macroexpansion phase of evaluating code, and its approach looked similar to what you seem to have in mind.

Upvotes: 1

Related Questions