Пример #1
0
struct lispobj *apply(struct lispobj *proc, struct lispobj *args)
{    
    if(proc != NULL && OBJ_TYPE(proc) == CONS) {
        struct lispobj *ret;
        
        if(NEW_SYMBOL("SUBR") == CAR(proc)) {
            /* Apply primitive function. */
            struct lispobj *body, *(*subr)(struct lispobj *);

            body = CADR(proc);
            subr = (struct lispobj *) NUMBER_VALUE(body);
            //subr = (struct lispobj *) body;

            ret = heap_grab(subr(args));
        } else if(NEW_SYMBOL("PROC") == CAR(proc)) {
            /* Apply user defined procedure. */
            struct lispobj *body, *params, *penv;

            body = CADDR(proc);
            params = CADR(proc);
            penv = CADDDR(proc);
            
            if(length(params) == length(args)) {
                struct lispobj *env;

                if(params == NULL || params == NEW_SYMBOL("NIL")) {
                    env = penv;

                    ret = eval_progn(body, env);
                } else {
                    env = heap_grab(NEW_CONS(env_frame_make(params, args), penv));

                    ret = eval_progn(body, env);
                    heap_release(env);
                }
            } else {
                char error[64]; 
                snprintf(error,
                         64,
                         "Has recieved wrong number of parameters: %d.\n",
                         length(args));
                ret = heap_grab(NEW_ERROR(error));
            }
        } else {
            goto error;
        }

        return ret;
    }
    
    error:
    return heap_grab(NEW_ERROR("Unknown procedure.\n"));
}
Пример #2
0
static struct lispobj *eval_progn(struct lispobj *exps, struct lispobj *env)
{
    if(exps == NULL) {
        return exps;
    } else if(CDR(exps) == NULL) {
        return eval(CAR(exps), env);
    } else {
        eval(CAR(exps), env);
        return eval_progn(CDR(exps), env);
    }
}
Пример #3
0
struct lispobj *eval(struct lispobj *obj, struct lispobj *env)
{
    struct lispobj *ret;
    
    if(obj == NULL || OBJ_TYPE(obj) == NUMBER ||
       OBJ_TYPE(obj) == ERROR || OBJ_TYPE(obj) == STRING) {
        /* Return self-evaluating object. */
        ret = heap_grab(obj);
    } else if(OBJ_TYPE(obj) == SYMBOL) {
        /* Lookup value of the variable in the env. */
        struct lispobj *val;

        val = env_var_lookup(obj, env);
        if(OBJ_TYPE(val) == ERROR) {
            ret = heap_grab(val);
        } else {
            ret = heap_grab(CDR(val));
        }
    } else if(NEW_SYMBOL("QUOTE") == CAR(obj)) {
        /* (quote whatever) */
        if(length(obj) != 2) {
            ret = heap_grab(ERROR_ARGS);
        } else {
            /* Return quoted object. */
            ret = heap_grab(CADR(obj));
        }
#ifdef __DEBUG_GC__
        printf("eval quote debug:");
        heap_debug_object(ret);
        printf("\n");
#endif
    } else if(NEW_SYMBOL("SETQ") == CAR(obj)) {
        /* (setq var val) */
        if(length(obj) != 3) {
            ret = heap_grab(ERROR_ARGS);
        } else {
            /* Try to assign existing variable. */
            struct lispobj *val;
            
            val = eval(CADDR(obj), env);
            if(val != NULL && OBJ_TYPE(val) == ERROR) {
                ret = val;
            } else {
                ret = heap_grab(env_var_assign(CADR(obj), val, env));
                heap_release(val);
            }
        }
    } else if(NEW_SYMBOL("LABEL") == CAR(obj)) {
        /* (label var val) */
        if(length(obj) != 3) {
            ret = heap_grab(ERROR_ARGS);
        } else {
            /* Try to define new variable. */
            struct lispobj *val;

            val = eval(CADDR(obj), env);
            if(val != NULL && OBJ_TYPE(val) == ERROR) {
                ret = val;
            } else {
                ret = heap_grab(env_var_define(CADR(obj), val, env));
                heap_release(val);
            }
        }
    } else if(NEW_SYMBOL("IF") == CAR(obj)) {
        /* (if predicate consequence alternative) */
        if(length(obj) != 4) {
            ret = heap_grab(ERROR_ARGS);
        } else {
            /* Invoke condition function. */
            struct lispobj *pred;

            pred = eval(CADR(obj), env);
            if(pred != NULL && OBJ_TYPE(pred) == ERROR) {
                ret = pred;
            } else {
                if(pred) {
                    /* Eval consequence. */
                    ret = eval(CADDR(obj), env);
                } else {
                    /* Eval alternative. */
                    ret = eval(CADDDR(obj), env);
                }

                heap_release(pred);
            }
        }
    } else if(NEW_SYMBOL("COND") == CAR(obj)) {
        /* (cond (cond1 ret1) (cond2 ret2)) */
        if(length(obj) < 2) {
            ret = heap_grab(ERROR_ARGS);
        } else {
            ret = eval_cond(CDR(obj), env);
        }
    }
    else if(NEW_SYMBOL("LET") == CAR(obj)) {
        if(length(obj) < 3) {
            ret = heap_grab(ERROR_ARGS);
        } else {
            ret = eval_let(CDR(obj), env);
        }
    } else if(NEW_SYMBOL("PROGN") == CAR(obj)) {
        ret = eval_progn(CDR(obj), env);
    } else if(NEW_SYMBOL("LAMBDA") == CAR(obj)) {
        /* (lambda (var) (proc var var)) */
        if(length(obj) < 3) {
            ret = heap_grab(ERROR_ARGS);
        } else {
            /* Make and return new procedure. */
            ret = heap_grab(env_proc_make(CADR(obj), CDDR(obj), env));
        }
    } else {
        /* Apply case. */
        struct lispobj *proc = eval(CAR(obj), env);
        
        if(proc != NULL && OBJ_TYPE(proc) == ERROR) {
            ret = proc;
        } else {
            struct lispobj *args = heap_grab(env_val_list(CDR(obj), env));

            if(args != NULL && OBJ_TYPE(args) == ERROR) {
                ret = args;
            } else {
                ret = apply(proc, args);
                heap_release(args);
            }
            
            heap_release(proc);
        }
    }
    
    return ret;
}
Пример #4
0
Файл: eval.c Проект: ianwild/qsl
obj apply_internal (obj fn, obj args)
{
  switch (get_type (fn))
  {
  case rom_symbol_type:
  {
    const rom_object *p = get_rom_header (fn);
    built_in_fn f = (built_in_fn) pgm_read_word_near (&p -> global_fn);
    if (! f)
      throw_error (no_fdefn);
    obj argv = make_argv (args, pgm_read_byte_near (&p -> is_fexpr));
    objhdr *argv_hdr = get_header (argv);
    argv_hdr -> flags |= gc_fixed;
    obj res = f (argv);
    argv_hdr -> flags &= ~ gc_fixed;
    return (res);
  }

  case symbol_type:
  {
    objhdr *fn_hdr = get_header (fn);
    fn = fn_hdr -> u.symbol_val.global_fn;
    if (! fn)
      throw_error (no_fdefn);
    // fall through to "apply closure"
  }

  case closure_type:
  {
    objhdr *fn_hdr = get_header (fn);
    obj code = fn_hdr -> u.closure_val.code;
    obj new_env;
    {
      obj type_sym, params;
      decons (code, &type_sym, &code);
      decons (code, &params, &code);
      if (type_sym == obj_LAMBDA)
	new_env = make_lambda_binding (params, args);
      else
	new_env = make_fexpr_binding (params, args);
    }
    if (new_env)
    {
      objhdr *env_hdr = NULL;
      env_hdr = get_header (new_env);
      env_hdr -> u.array_val [1] = fn_hdr -> u.closure_val.environment;
    }
    else
      new_env = fn_hdr -> u.closure_val.environment;

    bool unprotect = save_env ();
    obj keep_env = current_environment;
    current_environment = new_env;
    obj res = eval_progn (code, obj_NIL);
    current_environment = keep_env;
    if (unprotect)
      get_header (current_environment) -> flags &= ~gc_fixed;

    return (res);
  }

  default:
    return (obj_NIL);
  }
}