static Value* vecCompOp(const Vector* vector1, const Vector* vector2, const Context* ctx, BINTYPE bin) { unsigned count = vector1->vals->count; if(count != vector2->vals->count && vector2->vals->count > 1) { return ValErr(mathError("Cannot %s vectors of different sizes.", binop_verb[bin])); } ArgList* newv = ArgList_new(count); unsigned i; for(i = 0; i < count; i++) { /* Perform the specified operation on each matching component */ Value* val2; if(vector2->vals->count == 1) { val2 = vector2->vals->args[0]; } else { val2 = vector2->vals->args[i]; } BinOp* op = BinOp_new(bin, Value_copy(vector1->vals->args[i]), Value_copy(val2)); Value* result = BinOp_eval(op, ctx); BinOp_free(op); /* Error checking */ if(result->type == VAL_ERR) { ArgList_free(newv); return result; } /* Store result */ newv->args[i] = result; } return ValVec(Vector_new(newv)); }
static Value* eval_map(Context* ctx, ArgList* arglist) { if(arglist->count != 2) { return ValErr(builtinArgs("map", 2, arglist->count)); } Value* func = Value_copy(arglist->args[0]); if(func->type != VAL_VAR) { Value* val = Value_eval(func, ctx); Value_free(func); if(val->type == VAL_ERR) return val; if(val->type != VAL_VAR) { Value_free(val); return ValErr(typeError("Builtin 'map' expects a callable as its first argument.")); } func = val; } Value* vec = Value_eval(arglist->args[1], ctx); if(vec->type == VAL_ERR) { Value_free(func); return vec; } if(func->type != VAL_VAR) { Value_free(func); Value_free(vec); return ValErr(typeError("Builtin 'map' expects a callable as its first argument.")); } if(vec->type != VAL_VEC) { Value_free(func); Value_free(vec); return ValErr(typeError("Builtin 'map' expects a vector as its second argument.")); } ArgList* mapping = ArgList_new(vec->vec->vals->count); /* Don't evaluate the call now. Let Builtin_eval do this for us */ unsigned i; for(i = 0; i < mapping->count; i++) { ArgList* arg = ArgList_create(1, Value_copy(vec->vec->vals->args[i])); Value* call = ValCall(FuncCall_new(func->name, arg)); mapping->args[i] = call; } Value_free(func); Value_free(vec); return ValVec(Vector_new(mapping)); }
static Value* vecScalarOp(const Vector* vec, const Value* scalar, const Context* ctx, BINTYPE bin) { ArgList* newv = ArgList_new(vec->vals->count); unsigned i; for(i = 0; i < vec->vals->count; i++) { /* Perform operation */ BinOp* op = BinOp_new(bin, Value_copy(vec->vals->args[i]), Value_copy(scalar)); Value* result = BinOp_eval(op, ctx); BinOp_free(op); /* Error checking */ if(result->type == VAL_ERR) { ArgList_free(newv); return result; } /* Store result */ newv->args[i] = result; } return ValVec(Vector_new(newv)); }