Ejemplo n.º 1
0
static void
eval_function_call_expression(SIMCAR_Interpreter *inter,
                              SIMCAR_LocalEnvironment *env,
                              Expression *expr)
{
    FunctionDefinition  *func;
    SIMCAR_LocalEnvironment    *local_env;

    char *identifier = expr->u.function_call_expression.identifier;

    func = crb_search_function(identifier);
    if (func == NULL) {
        crb_runtime_error(expr->line_number, FUNCTION_NOT_FOUND_ERR,
                          STRING_MESSAGE_ARGUMENT, "name", identifier,
                          MESSAGE_ARGUMENT_END);
    }

    local_env = alloc_local_environment(inter);

    switch (func->type) {
    case CROWBAR_FUNCTION_DEFINITION:
        call_crowbar_function(inter, local_env, env, expr, func);
        break;
    case NATIVE_FUNCTION_DEFINITION:
        call_native_function(inter, local_env, env, expr,
                             func->u.native_f.proc);
        break;
    case FUNCTION_DEFINITION_TYPE_COUNT_PLUS_1:
    default:
        DBG_panic(("bad case..%d\n", func->type));
    }
    dispose_local_environment(inter);
}
Ejemplo n.º 2
0
static CRB_Value
eval_function_call_expression(CRB_Interpreter *inter, LcoalEnvriroment *env,
        Expression *expr)
{
    CRB_Value value;
    FunctionDefinition *func;

    char *identifier = expr->u.function_call_expression.identifier;

    func = crb_search_function(identifier);
    if(func == NULL){
        crb_runtime_error(expr->line_number, FUNCTION_NOT_FOUND_ERR,
                STRING_MESSAGE_ARGUMENT, "name", identifier,
                MESSAGE_ARGUMENT_END);
    }
    switch(func->type){
        case CROWBAR_FUNCTION_DEFINITION:
            value = call_crowbar_function(inter, env, expr, func);
            break;
        case NATIVE_FUNCTION_DEFINITION:
            value = call_native_function(inter, env, expr, func->u.native_f.proc);
            break;
        default:
            DBG_panic(("bad case..%d\n", func->type));
    }

    return value;
}
Ejemplo n.º 3
0
const SpObject *SpVM::call_function(const std::string &name, const SpFunction *func, const SpExpr *call_expr, SpEnv *env) {
   // now, evaluate the arguments in a new scope
   // this is because Spooner is lexically scoped, so any this function call
   // can only access its arguments
   std::unique_ptr<SpEnv> call_env(new SpEnv());

   // check if the correct number of arguments are provided
   if (call_expr->length() - 1 != func->num_arguments())
      RUNTIME_ERROR_F("Function call to '%s' requires %lu arguments, "
         "but %d given", name.c_str(), func->num_arguments(),
         call_expr->length() - 1);

   size_t arg_index = 0;
   for (auto it = call_expr->cbegin(); it != call_expr->cend(); ++it, arg_index++) {
      // if there is a pattern for this argument
      if (arg_index < func->pattern()->length()) {
         // need to handle the quote pattern specially
         if (func->pattern(arg_index)->type() == T_NAME) {
            const char *name = ((SpName *)func->pattern(arg_index))->value();
            if (!strcmp(name, "quote")) {
               // we need to quote this argument and not evaluate it
               call_env->bind_name(func->arguments(arg_index), new SpExprObject(*it));
            } else if (!strcmp(name, "_")) {
               // wildcards match anything
               call_env->bind_name(func->arguments(arg_index), eval(*it, env));
            } else { 
               // TODO: allow names in patterns
               RUNTIME_ERROR("Names cannot be used in patterns yet...");
            }
         } else {
            // check if this pattern matches
            const SpObject *arg_result = eval(*it, env);
            if (is_match_pattern(func->pattern(arg_index), arg_result)) {
               // good, we'll bind this argument
               call_env->bind_name(func->arguments(arg_index), arg_result);
            } else {
               RUNTIME_ERROR_F("Arguments in function call to '%s' do not match any patterns", name.c_str());
            }
         }
      } else {
         // no pattern means anything matches
         call_env->bind_name(func->arguments(arg_index), eval(*it, env));
      }
   }

   // call the function (either natively or in the VM) using the new environment 
   return func->is_native() ?
      call_native_function((SpNativeFunction *)func, call_env.get()) :
      call_function_with_env(func, call_env.get());
}