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* eval_dot(Context* ctx, ArgList* arglist) { if(arglist->count != 2) { /* Two vectors are required for a dot product */ return ValErr(builtinArgs("dot", 2, arglist->count)); } Value* vector1 = Value_eval(arglist->args[0], ctx); if(vector1->type == VAL_ERR) { return vector1; } Value* vector2 = Value_eval(arglist->args[1], ctx); if(vector2->type == VAL_ERR) { Value_free(vector1); return vector2; } if(vector1->type != VAL_VEC || vector2->type != VAL_VEC) { /* Both values must be vectors */ return ValErr(typeError("Builtin dot expects two vectors.")); } unsigned count = vector1->vec->vals->count; if(count != vector2->vec->vals->count) { /* Both vectors must have the same number of values */ return ValErr(mathError("Vectors must have the same dimensions for dot product.")); } Value* total = ValInt(0); // store the total value of the dot product unsigned i; for(i = 0; i < count; i++) { /* Multiply v1[i] and v2[i] */ BinOp* mul = BinOp_new(BIN_MUL, Value_copy(vector1->vec->vals->args[i]), Value_copy(vector2->vec->vals->args[i])); Value* part = BinOp_eval(mul, ctx); BinOp_free(mul); /* Accumulate the sum for all products */ BinOp* add = BinOp_new(BIN_ADD, part, total); total = BinOp_eval(add, ctx); BinOp_free(add); } return total; }
Value* Expression_eval(Expression* expr, Context* ctx) { Value* ret; Variable* var = expr->var; if(var->type == VAR_VALUE) { /* Evaluate right side */ ret = Value_eval(var->val, ctx); /* If an error occurred, bail */ if(ret->type == VAL_ERR) return ret; /* Variable assignment? */ if(ret->type == VAL_VAR) { /* This means ret must be a function */ Variable* func = Variable_get(ctx, ret->name); if(func == NULL) { Value* err = ValErr(varNotFound(ret->name)); Value_free(ret); return err; } if(func->type == VAR_BUILTIN) { Value_free(ret); return ValErr(typeError("Cannot assign a variable to a builtin value.")); } if(var->name != NULL) { Context_setGlobal(ctx, var->name, Variable_copy(func)); } } else { /* This means ret must be a Value */ Value_free(var->val); var->val = Value_copy(ret); /* Update ans */ Context_setGlobal(ctx, "ans", Variable_copy(var)); /* Save the newly evaluated variable */ if(var->name != NULL) Context_setGlobal(ctx, var->name, Variable_copy(var)); } } else if(var->type == VAR_FUNC) { ret = ValVar(var->name); Context_setGlobal(ctx, var->name, Variable_copy(var)); } else { badVarType(var->type); } return ret; }
Value* Value_coerce(const Value* val, const Context* ctx) { Value* ret = Value_eval(val, ctx); if(ret->type == VAL_VAR) { Variable* var = Variable_get(ctx, ret->name); if(var == NULL) { Value* tmp = ValErr(varNotFound(ret->name)); Value_free(ret); ret = tmp; } else { ret = Variable_coerce(var, ctx); } } return ret; }
static Value* eval_cross(Context* ctx, ArgList* arglist) { if(arglist->count != 2) { /* Two vectors are required for a cross product */ return ValErr(builtinArgs("cross", 2, arglist->count)); } Value* vector1 = Value_eval(arglist->args[0], ctx); if(vector1->type == VAL_ERR) { return vector1; } Value* vector2 = Value_eval(arglist->args[1], ctx); if(vector2->type == VAL_ERR) { Value_free(vector1); return vector2; } if(vector1->type != VAL_VEC || vector2->type != VAL_VEC) { /* Both values must be vectors */ return ValErr(typeError("Builtin dot expects two vectors.")); } if(vector1->vec->vals->count != 3) { /* Vectors must each have a size of 3 */ return ValErr(mathError("Vectors must each have a size of 3 for cross product.")); } /* First cross multiplication */ BinOp* i_pos_op = BinOp_new(BIN_MUL, Value_copy(vector1->vec->vals->args[1]), Value_copy(vector2->vec->vals->args[2])); BinOp* i_neg_op = BinOp_new(BIN_MUL, Value_copy(vector1->vec->vals->args[2]), Value_copy(vector2->vec->vals->args[1])); /* Evaluate multiplications */ Value* i_pos = BinOp_eval(i_pos_op, ctx); Value* i_neg = BinOp_eval(i_neg_op, ctx); BinOp_free(i_pos_op); BinOp_free(i_neg_op); /* Error checking */ if(i_pos->type == VAL_ERR) { Value_free(vector1); Value_free(vector2); Value_free(i_neg); return i_pos; } if(i_neg->type == VAL_ERR) { Value_free(vector1); Value_free(vector2); Value_free(i_pos); return i_neg; } /* Subtract products */ BinOp* i_op = BinOp_new(BIN_SUB, i_pos, i_neg); Value* i_val = BinOp_eval(i_op, ctx); BinOp_free(i_op); if(i_val->type == VAL_ERR) { Value_free(vector1); Value_free(vector2); return i_val; } /* Part 2 */ BinOp* j_pos_op = BinOp_new(BIN_MUL, Value_copy(vector1->vec->vals->args[0]), Value_copy(vector2->vec->vals->args[2])); BinOp* j_neg_op = BinOp_new(BIN_MUL, Value_copy(vector1->vec->vals->args[2]), Value_copy(vector2->vec->vals->args[0])); Value* j_pos = BinOp_eval(j_pos_op, ctx); Value* j_neg = BinOp_eval(j_neg_op, ctx); BinOp_free(j_pos_op); BinOp_free(j_neg_op); if(j_pos->type == VAL_ERR) { Value_free(vector1); Value_free(vector2); Value_free(j_neg); return j_pos; } if(j_neg->type == VAL_ERR) { Value_free(vector1); Value_free(vector2); Value_free(j_pos); return j_neg; } BinOp* j_op = BinOp_new(BIN_SUB, j_pos, j_neg); Value* j_val = BinOp_eval(j_op, ctx); BinOp_free(j_op); if(j_val->type == VAL_ERR) { Value_free(vector1); Value_free(vector2); return j_val; } /* Part 3 */ BinOp* k_pos_op = BinOp_new(BIN_MUL, Value_copy(vector1->vec->vals->args[0]), Value_copy(vector2->vec->vals->args[1])); BinOp* k_neg_op = BinOp_new(BIN_MUL, Value_copy(vector1->vec->vals->args[1]), Value_copy(vector2->vec->vals->args[0])); Value* k_pos = BinOp_eval(k_pos_op, ctx); Value* k_neg = BinOp_eval(k_neg_op, ctx); BinOp_free(k_pos_op); BinOp_free(k_neg_op); if(k_pos->type == VAL_ERR) { Value_free(vector1); Value_free(vector2); Value_free(k_neg); return k_pos; } if(k_neg->type == VAL_ERR) { Value_free(vector1); Value_free(vector2); Value_free(k_pos); return k_neg; } BinOp* k_op = BinOp_new(BIN_SUB, k_pos, k_neg); Value* k_val = BinOp_eval(k_op, ctx); BinOp_free(k_op); if(k_val->type == VAL_ERR) { Value_free(vector1); Value_free(vector2); return k_val; } ArgList* args = ArgList_create(3, i_val, j_val, k_val); return ValVec(Vector_new(args)); }