예제 #1
0
object *setup_environment(void) {
    object *initial_env;

    initial_env = extend_environment(
                      the_empty_list,
                      the_empty_list,
                      the_empty_environment);
    return initial_env;
}
예제 #2
0
static li_object *expand_macro(li_object *mac, li_object *args) {
    li_object *env, *ret, *seq;

    ret = li_null;
    env = extend_environment(li_to_macro(mac).vars, args, li_to_macro(mac).env);
    for (seq = li_to_macro(mac).body; seq; seq = li_cdr(seq))
        ret = li_eval(li_car(seq), env);
    return ret;
}
예제 #3
0
object_t apply(object_t p, object_t argl) {
  proc_t proc = obj_get_proc(p);
  if(isprimitiveproc(proc)) /* primitive procedure */
    return (proc->fn)(argl);
  else {
    object_t extended = extend_environment(lambda_params(p), argl, lambda_env(p));
    return eval_sequence(lambda_body(p), &extended);
  }
}
예제 #4
0
item setup_environment(){
	item initial_env = extend_environment(primitive_procedure_names(), primitive_procedure_objects(), the_empty_environment());
	item t, f;
	t.type = f.type = t_number;
	t.content.number = 1;
	f.content.number = 0;
	define_variable(make_item("true"), t, initial_env);
	define_variable(make_item("false"), f, initial_env);
	return initial_env;
}
예제 #5
0
파일: eval.c 프로젝트: Liutos/liutscm
sexp eval_application(sexp operator, sexp operands) {
  if (is_primitive(operator))
    return (primitive_C_proc(operator))(operands);
  if (is_compound(operator)) {
    sexp body = compound_proc_body(operator);
    sexp vars = compound_proc_parameters(operator);
    sexp def_env = compound_proc_environment(operator);
    sexp object = make_pair(S("begin"), body);
    sexp env = extend_environment(vars, operands, def_env);
    return eval_object(object, env);
  }
  fprintf(stderr, "Unknown operator type %d\n", operator->type);
  exit(1);
}
예제 #6
0
data_t *apply(const data_t *proc, const data_t *args) {
	data_t *out;

	if(is_primitive_procedure(proc))
		return apply_primitive_procedure(proc, args);
	if(is_compound_procedure(proc)) {		
		out = eval_sequence(
			get_procedure_body(proc),
			extend_environment(get_procedure_parameters(proc),
				args,
				get_procedure_environment(proc)));		
		return out;
	}
	printf("Unknown procedure type -- APPLY\n");
	return make_symbol("error");
}
예제 #7
0
extern li_object *li_eval(li_object *exp, li_object *env) {
    li_object *seq, *proc, *args;
    int done;

    done = 0;
    while (!li_is_self_evaluating(exp) && !done) {
        li_stack_trace_push(exp);
        if (li_is_symbol(exp)) {
            exp = li_environment_lookup(env, exp);
            done = 1;
        } else if (li_is_quoted(exp)) {
            check_special_form(li_cdr(exp) && !li_cddr(exp), exp);
            exp = li_cadr(exp);
            done = 1;
        } else if (li_is_quasiquoted(exp)) {
            check_special_form(li_cdr(exp) && !li_cddr(exp), exp);
            exp = eval_quasiquote(li_cadr(exp), env);
            done = 1;
        } else if (li_is_application(exp)) {
            proc = li_eval(li_car(exp), env);
            args = li_cdr(exp);
            if (li_is_procedure(proc))
                args = list_of_values(args, env);
            if (li_is_lambda(proc)) {
                env = extend_environment(li_to_lambda(proc).vars, args,
                        li_to_lambda(proc).env);
                for (seq = li_to_lambda(proc).body; seq && li_cdr(seq);
                        seq = li_cdr(seq))
                    li_eval(li_car(seq), env);
                exp = li_car(seq);
            } else if (li_is_macro(proc)) {
                exp = expand_macro(proc, args);
            } else if (li_is_primitive_procedure(proc)) {
                exp = li_to_primitive_procedure(proc)(args);
                done = 1;
            } else if (li_is_special_form(proc)) {
                exp = li_to_special_form(proc)(args, env);
            } else {
                li_error("not applicable", proc);
            }
        } else {
            li_error("unknown expression type", exp);
        }
        li_stack_trace_pop();
    }
    return exp;
}
예제 #8
0
object *eval(object *exp, object *env) {

    object *procedure;
    object *arguments;
    object *result;
    bool tailcall = false;

    do {

        if (is_self_evaluating(exp))
            return exp;

        if (is_variable(exp))
            return lookup_variable_value(exp, env);

        if (is_quoted(exp))
            return text_of_quotation(exp);

        if (is_assignment(exp))
            return eval_assignment(exp, env);

        if (is_definition(exp))
            return eval_definition(exp, env);

        if (is_if(exp)) {
            exp = is_true(eval(if_predicate(exp), env)) ? if_consequent(exp) : if_alternative(exp);
            tailcall = true;
            continue;
        }

        if (is_lambda(exp))
            return make_compound_proc(lambda_parameters(exp), lambda_body(exp), env);

        if (is_begin(exp)) {
            exp = begin_actions(exp);
            while (!is_last_exp(exp)) {
                eval(first_exp(exp), env);
                exp = rest_exps(exp);
            }
            exp = first_exp(exp);
            tailcall = true;
            continue;
        }

        if (is_cond(exp)) {
            exp = cond_to_if(exp);
            tailcall = true;
            continue;
        }

        if (is_let(exp)) {
            exp = let_to_application(exp);
            tailcall = true;
            continue;
        }

        if (is_and(exp)) {
            exp = and_tests(exp);
            if (is_empty(exp))
                 return make_boolean(true);
            while (!is_last_exp(exp)) {
                result = eval(first_exp(exp), env);
                if (is_false(result))
                    return result;
                exp = rest_exps(exp);
            }
            exp = first_exp(exp);
            tailcall = true;
            continue;
        }

        if (is_or(exp)) {
            exp = or_tests(exp);
            if (is_empty(exp)) {
                return make_boolean(false);
            }
            while (!is_last_exp(exp)) {
                result = eval(first_exp(exp), env);
                if (is_true(result))
                    return result;
                exp = rest_exps(exp);
            }
            exp = first_exp(exp);
            tailcall = true;
            continue;
        }

        if (is_application(exp)) {

            procedure = eval(operator(exp), env);
            arguments = list_of_values(operands(exp), env);

            if (is_primitive_proc(procedure) && procedure->data.primitive_proc.fn == eval_proc) {
                exp = eval_expression(arguments);
                env = eval_environment(arguments);
                tailcall = true;
                continue;
            }

            if (is_primitive_proc(procedure) && procedure->data.primitive_proc.fn == apply_proc) {
                procedure = apply_operator(arguments);
                arguments = apply_operands(arguments);
            }

            if (is_primitive_proc(procedure))
                return (procedure->data.primitive_proc.fn)(arguments);

            if (is_compound_proc(procedure)) {
                env = extend_environment(procedure->data.compound_proc.parameters, arguments, procedure->data.compound_proc.env);
                exp = make_begin(procedure->data.compound_proc.body);
                tailcall = true;
                continue;
            }

            return make_error(342, "unknown procedure type");
        } // is_application()

    } while (tailcall);

    fprintf(stderr, "cannot eval unknown expression type\n");
    exit(EXIT_FAILURE);
}
예제 #9
0
object_t *setup_environment() {
    object_t *env = extend_environment(empty_list, empty_list,
                                           empty_list);
    return env;
}
예제 #10
0
//TODO check number of arguments given to builtins
object_t *eval(object_t *exp, object_t *env) {

    char comeback = 1;

    while(comeback) {
        comeback = 0;

        if(is_self_evaluating(exp)) {
            return exp;
        }

        if(list_begins_with(exp, quote_symbol)) {
            return cadr(exp);
        }

        // (define... )
        if(list_begins_with(exp, define_symbol)) {

            object_t *var = cadr(exp);

            // (define a b)
            if(issymbol(var)) {
                object_t *val = caddr(exp);
                return define_var(env, var, val);
            }

            // (define (a ...) ...) TODO use scheme macro
            if(ispair(var)) {
                object_t *name = car(cadr(exp)),
                    *formals = cdr(cadr(exp)),
                    *body = cddr(exp),
                    *lambda = cons(lambda_symbol,
                                      cons(formals, body));

                exp = cons(define_symbol,
                              cons(name, cons(lambda, empty_list)));
                comeback = 1;
                continue;
            }

            fprintf(stderr, "Syntax error.\n");
            exit(-1);
        }

        // (set! a b)
        if(list_begins_with(exp, set_symbol)) {
            object_t *var = cadr(exp);
            object_t *val = caddr(exp);
            return set_var(env, var, val);
        }

        // (if c a b)
        if(list_begins_with(exp, if_symbol)) {
            exp = eval_if(env, cadr(exp), caddr(exp), cadddr(exp));
            comeback = 1;
            continue;
        }

        // (cond ...)
        if(list_begins_with(exp, cond_symbol)) {
            object_t *tail = cons(void_symbol, empty_list);
            object_t *ifs = tail; //empty_list;
            object_t *rules = reverse_list(cdr(exp));

            while(!isemptylist(rules)) {
                object_t *rule = car(rules),
                    *condition = car(rule),
                    *consequence = cadr(rule);

                if(isemptylist(consequence)) {
                    consequence = cons(void_obj, empty_list);
                }

                ifs = cons(if_symbol,
                              cons(condition,
                                      cons(consequence,
                                              cons(ifs, empty_list))));

                rules = cdr(rules);
            }

            exp = ifs;

            comeback = 1;
            continue;
        }

        // (begin ...)
        if(list_begins_with(exp, begin_symbol)) {

            object_t *result = empty_list, *exps;

            for(exps = cdr(exp); ! isemptylist(exps); exps = cdr(exps)) {
                result = eval(car(exps), env);
            }

            return result;
        }

        if(list_begins_with(exp, lambda_symbol)) {
            object_t *fn = cons(begin_symbol,
                                    cdr(cdr(exp)));
            return make_compound_proc(empty_list, cadr(exp),
                                         fn,
                                         env);
        }

        // (let ...)
        if(list_begins_with(exp, let_symbol)) {
            //if(! issymbol(cadr(exp)))
            object_t *bindings = cadr(exp);
            object_t *body = cddr(exp);

            object_t *formals = empty_list;
            object_t *values = empty_list;

            while(!isemptylist(bindings)) {
                formals = cons(caar(bindings), formals);
                values = cons(cadr(car(bindings)), values);

                bindings = cdr(bindings);
            }

            exp = cons(cons(lambda_symbol, cons(formals, body)),
                          values);

            comeback = 1;
            continue;
        }

        if(issymbol(exp)) {
            return var_get_value(env, exp);
        }

        if(ispair(exp)) {
            object_t *exp_car = car(exp);
            object_t *fn = eval(exp_car, env); //var_get_value(env, car);
            if(!iscallable(fn)) {
                fprintf(stderr, "object_t is not callable\n");
                exit(-1);
            }

            object_t *args = cdr(exp);
            object_t *evaluated_args = evaluate_list(env, args, empty_list);

            if(isprimitiveproc(fn)) {
                return fn->value.prim_proc.fn(evaluated_args);
            } else if(iscompoundproc(fn)) {
                object_t *fn_formals = fn->value.compound_proc.formals;
                object_t *fn_body = fn->value.compound_proc.body;
                object_t *fn_env = fn->value.compound_proc.env;

                ARGS_EQ(evaluated_args, list_size(fn_formals));

                exp = fn_body;
                env = extend_environment(fn_formals, evaluated_args, fn_env);
                comeback = 1;
                continue;

            }
            assert(0);
        }

    }

    fprintf(stderr, "Unable to evaluate expression: \n");
    write(exp);
    exit(-1);
}
예제 #11
0
파일: eval.c 프로젝트: ingramj/bs
object *bs_eval(object *exp, object *env)
{
tailcall:
    if (is_empty_list(exp)) {
        error("unable to evaluate empty list");
    } else if (is_self_evaluating(exp)) {
        return exp;
    } else if (is_variable(exp)) {
        return lookup_variable_value(exp, env);
    } else if (is_quoted(exp)) {
        return quoted_expression(exp);
    } else if (is_assignment(exp)) {
        return eval_assignment(exp, env);
    } else if (is_definition(exp)) {
        return eval_definition(exp, env);
    } else if (is_if(exp)) {
        if (is_true(bs_eval(if_predicate(exp), env))) {
            exp = if_consequent(exp);
        } else {
            exp = if_alternate(exp);
        }
        goto tailcall;
    } else if (is_lambda(exp)) {
        return make_compound_proc(lambda_parameters(exp),
                lambda_body(exp),
                env);
    } else if (is_begin(exp)) {
        exp = begin_actions(exp);
        if (is_empty_list(exp)) {
            error("empty begin block");
        }
        while (!is_empty_list(cdr(exp))) {
            bs_eval(car(exp), env);
            exp = cdr(exp);
        }
        exp = car(exp);
        goto tailcall;
    } else if (is_cond(exp)) {
        exp = cond_to_if(exp);
        goto tailcall;
    } else if (is_let(exp)) {
        exp = let_to_application(exp);
        goto tailcall;
    } else if (is_and(exp)) {
        exp = and_tests(exp);
        if (is_empty_list(exp)) {
            return get_boolean(1);
        }
        object *result;
        while (!is_empty_list(cdr(exp))) {
            result = bs_eval(car(exp), env);
            if (is_false(result)) {
                return result;
            }
            exp = cdr(exp);
        }
        exp = car(exp);
        goto tailcall;
    } else if (is_or(exp)) {
        exp = or_tests(exp);
        if (is_empty_list(exp)) {
            return get_boolean(0);
        }
        object *result;
        while (!is_empty_list(cdr(exp))) {
            result = bs_eval(car(exp), env);
            if (is_true(result)) {
                return result;
            }
            exp = cdr(exp);
        }
        exp = car(exp);
        goto tailcall;
    } else if (is_application(exp)) {
        object *procedure = bs_eval(application_operator(exp), env);
        object *parameters = eval_parameters(application_operands(exp), env);

        // handle eval specially for tailcall requirement.
        if (is_primitive_proc(procedure) &&
                procedure->value.primitive_proc == eval_proc) {
            exp = eval_expression(parameters);
            env = eval_environment(parameters);
            goto tailcall;
        }

        // handle apply specially for tailcall requirement.
        if (is_primitive_proc(procedure) &&
                procedure->value.primitive_proc == apply_proc) {
            procedure = apply_operator(parameters);
            parameters = apply_operands(parameters);
        }

        if (is_primitive_proc(procedure)) {
            return (procedure->value.primitive_proc)(parameters);
        } else if (is_compound_proc(procedure)) {
            env = extend_environment(
                    procedure->value.compound_proc.parameters,
                    parameters,
                    procedure->value.compound_proc.env);
            exp = make_begin(procedure->value.compound_proc.body);
            goto tailcall;
        } else {
            error("unable to apply unknown procedure type");
        }
    } else {
        error("unable to evaluate expression");
    }
}
예제 #12
0
파일: eval.c 프로젝트: Liutos/liutscm
sexp eval_object(sexp object, sexp environment) {
tail_loop:
  if (is_quote_form(object)) return quotation_text(object);
  if (is_variable_form(object))
    return get_variable_value(object, environment);
  if (is_define_form(object)) {
    /* sexp value = eval_object(definition_value(object), environment); */
    /* add_binding(definition_variable(object), value, environment); */
    /* return value; */
    return eval_object(define2set(object), environment);
  }
  if (is_assignment_form(object)) {
    sexp value = eval_object(assignment_value(object), environment);
    set_binding(assignment_variable(object), value, environment);
    return value;
  }
  if (is_if_form(object)) {
    sexp test_part = if_test_part(object);
    sexp then_part = if_then_part(object);
    sexp else_part = if_else_part(object);
    if (!is_false(eval_object(test_part, environment))) {
      object = then_part;
    } else {
      object = else_part;
    }
    goto tail_loop;
  }
  if (is_lambda_form(object)) {
    sexp parameters = lambda_parameters(object);
    sexp body = lambda_body(object);
    return make_lambda_procedure(parameters, body, environment);
  }
  if (is_begin_form(object)) {
    return eval_begin(object, environment);
  }
  if (is_cond_form(object)) {
    object = cond2if(object);
    goto tail_loop;
  }
  if (is_let_form(object)) {
    object = let2lambda(object);
    goto tail_loop;
  }
  if (is_and_form(object)) {
    sexp tests = and_tests(object);
    if (is_null(tests))
      return make_true();
    while (is_pair(pair_cdr(tests))) {
      sexp result = eval_object(pair_car(tests), environment);
      if (is_false(result))
        return make_false();
      tests = pair_cdr(tests);
    }
    return eval_object(pair_car(tests), environment);
  }
  if (is_or_form(object)) {
    sexp tests = or_tests(object);
    if (is_null(tests))
      return make_false();
    while (is_pair(pair_cdr(tests))) {
      sexp result = eval_object(pair_car(tests), environment);
      if (!is_false(result))
        return result;
      tests = pair_cdr(tests);
    }
    return eval_object(pair_car(tests), environment);
  }
  if (is_macro_form(object)) {
    sexp pars = macro_parameters(object);
    sexp body = macro_body(object);
    return make_macro_procedure(pars, body, environment);
  }
  if (is_application_form(object)) {
    sexp operator = application_operator(object);
    sexp operands = application_operands(object);
    operator = eval_object(operator, environment);
    if (!is_function(operator) && !is_macro(operator)) {
      fprintf(stderr, "Illegal functional object ");
      write_object(operator, make_file_out_port(stderr));
      fprintf(stderr, " from ");
      write_object(pair_car(object), make_file_out_port(stderr));
      fputc('\n', stderr);
      exit(1);
    }
    /* Expand the macro before evaluating arguments */
    if (is_macro(operator)) {
      sexp body = macro_proc_body(operator);
      sexp vars = macro_proc_pars(operator);
      sexp def_env = macro_proc_env(operator);
      sexp object = make_pair(S("begin"), body);
      sexp env = extend_environment(vars, operands, def_env);
      sexp exp = eval_object(object, env);
      return eval_object(exp, environment);
    }
    operands = eval_arguments(operands, environment);
    /* if (is_apply(operator)) { */
    /*   operator = pair_car(operands); */
    /*   operands = apply_operands_conc(pair_cdr(operands)); */
    /* } */
    if (is_eval(operator)) {
      environment = pair_cadr(operands);
      object = pair_car(operands);
      goto tail_loop;
    }
    return eval_application(operator, operands);
  } else return object;
}