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()); }
const SpObject *SpNativeWith::native_eval(SpEnv *env, SpVM *vm) const { // first, bind the variables in a new scope std::unique_ptr<SpEnv> call_env(new SpEnv()); // TODO(evilncrazy): allow multiple variable declarations const SpExpr *name_expr = static_cast<const SpExprObject *>(env->resolve_name("x"))->expr(); call_env->bind_name(name_expr->head()->value(), env->resolve_name("val")->shallow_copy()); // then, evaluate the quoted body return vm->eval( static_cast<const SpExprObject *>(env->resolve_name("body"))->expr(), call_env.get()); }
int child(char **command, char **env, char *line) { int status; pid_t pid; pid = fork(); if ( pid == -1) { perror("fork"); return (1); } else if (pid == 0) { execvp(command[0], command); if ( str_cmp(command[0],"env") == 0) { call_env(command,env); free(line); free_command(command); exit(0); } else if( str_cmp (command[0], "$?") == 0) { printf("%d\n",status); exit(0); } else { printf("%s: command not found\n",command[0]); free(line); free_command(command); exit(0); } return (1); free(line); free_command(command); } else { wait(&status); } return status; }
void own_command(t_env *env, char **sa, char *s) { if (ft_memcmp(sa[0], "echo", 4) == 0) ft_echo(sa); else if (ft_memcmp(sa[0], "cd", 2) == 0) ft_cd(env, sa); else if (ft_memcmp(sa[0], "setenv", 6) == 0) ft_setenv(env, sa); else if (ft_memcmp(sa[0], "unsetenv", 8) == 0) ft_unsetenv(env, sa); else if (ft_memcmp(sa[0], "env", 3) == 0) call_env(*env, s); else if (ft_memcmp(sa[0], "help", 4) == 0) ft_help(env, sa); else if (ft_memcmp(sa[0], "easter", 6) == 0) easteregg(env, sa); else if (ft_memcmp(sa[0], "history", 7) == 0) list_history(env, sa); else ft_putstr(E_MESS05); FREE_(s); }