function eval(expr); function eval(expr) { local i; if(error_message) return "nil"; if(typeof(expr) == QH_Int) return expr; if(typeof(expr) == QH_String) return symbol_value(expr); if(typeof(expr) != QH_List) { error_message = "Error Found in Lisp, This message in eval()"; return NIL; } if(typeof(car(expr)) == QH_List) { // ((lambda (arg ...) body1 body2 ...) x ...) local la; local lambda_arglist; la = car(expr); // (lambda (arg ...) body1 body2 ...) lambda_arglist = cdr(expr); // (x ...) if(!equal(car(la), "lambda")) { write("Invalid function: "); lisp::print(la); error_message = True; return "nil"; } local arg_list = lisp::cadr(la); local lambda_body_list = lisp::cddr(la); local narg = lisp::length(lambda_arglist); local arglist = NIL; local t; if(narg != lisp::length(arg_list)) { write("Invalid number of lambda arguments: "); lisp::print(car(expr)); error_message = True; return "nil"; } // evaluate each arguments if(narg > 0) { arglist = new[narg]; t = lambda_arglist; for(i = 0; i < narg; i++) { arglist[i] = eval(car(t)); if(error_message) return "nil"; t = cdr(t); } } bind_local_symbol(arg_list, arglist, narg); t = "nil"; while(typeof(lambda_body_list) == QH_List) { t = eval(car(lambda_body_list)); if(error_message) break; lambda_body_list = cdr(lambda_body_list); } unbind_local_symbol(); return t; } local func; local argorig = cdr(expr); local narg; func = symbol_function(car(expr)); if(func == NIL) { write("Undefined function: "); lisp::print(car(expr)); error_message = True; return "nil"; } // calculate number of argument narg = lisp::length(argorig); if(typeof(func) == QH_Struct) // lisp subr { if(func.narg >= 0 || func.narg == MANY) // ordinary subr { local arglist = NIL; local t; local i; // evaluate each arguments if(narg > 0) { arglist = new[narg]; t = argorig; for(i = 0; i < narg; i++) { arglist[i] = eval(car(t)); if(error_message) return "nil"; t = cdr(t); } } if(func.narg == MANY) return funcall(func.func, arglist, narg); if(narg != func.narg) { writeln("Invalid number of arguments: ", car(expr)); error_message = True; return; } switch(narg) { case 0: return funcall(func.func); break; case 1: return funcall(func.func, arglist[0]); break; case 2: return funcall(func.func, arglist[0], arglist[1]); break; case 3: return funcall(func.func, arglist[0], arglist[1], arglist[2]); break; case 4: return funcall(func.func, arglist[0], arglist[1], arglist[2], arglist[3]); break; default: writeln("Lisp Internal Error: Too Many argument of SUBR"); exit(1); } } else if(func.narg == UNEVALLED) { return funcall(func.func, argorig); } else { writeln("Lisp Internal Error: Unknown function type: ", func.narg); exit(1); } } else // user defined funtion { local t; local arglist = NIL; if(typeof(func) != QH_List) { writeln("Invalid function: "); lisp::print(car(expr)); error_message = True; return NIL; } // evaluate each arguments if(narg > 0) { arglist = new[narg]; t = argorig; for(i = 0; i < narg; i++) { arglist[i] = eval(car(t)); if(error_message) return "nil"; t = cdr(t); } } local defun_arglist = car(func); local defun_body_list = cdr(func); if(lisp::length(defun_arglist) != narg) { writeln("Invalid number of arguments: ", car(expr)); error_message = True; return "nil"; } t = "nil"; bind_local_symbol(defun_arglist, arglist, narg); while(typeof(defun_body_list) == QH_List) { t = eval(car(defun_body_list)); if(error_message) break; defun_body_list = cdr(defun_body_list); } unbind_local_symbol(); return t; } }