Reputation: 1572
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:
eval
)(defun f (x))
) and then parse itAm 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
Reputation: 529
Most of the cases in your code can be replaced with a single check: ((constantp body) body)
As for other cases:
boundp
to check if a symbol has a global value.symbol-value
.fboundp
can be used to check if a symbol is globally bound to a functionsymbol-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.macro-function
(returns non-nil if it does).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