static Value* parseNum(const char** expr) { Value* ret; char* end1; char* end2; errno = 0; double dbl = strtod(*expr, &end1); if(errno != 0 || *expr == end1) { /* An error occurred (EINVAL, ERANGE) */ end1 = NULL; } long long ll = strtoll(*expr, &end2, 10); if(errno != 0 || *expr == end2) { /* An error occurred (EINVAL, ERANGE) */ end2 = NULL; } if(end1 > end2) { /* Must be a double because more of the string was parsed as double than long long */ ret = ValReal(dbl); *expr = end1; } else if(end2 != NULL) { /* Must be an integer */ ret = ValInt(ll); *expr = end2; } else { /* Both failed to convert the data */ ret = ValErr(badChar(**expr)); } return ret; }
Value* Vector_dot(const Vector* vector1, const Vector* vector2, const Context* ctx) { unsigned count = vector1->vals->count; if(count != vector2->vals->count && vector2->vals->count != 1) { /* Both vectors must have the same number of values */ return ValErr(mathError("Vectors must have the same dimensions for dot product.")); } /* Store the total value of the dot product */ Value* accum = ValInt(0); unsigned i; for(i = 0; i < count; i++) { Value* val2; if(vector2->vals->count == 1) { val2 = vector2->vals->args[0]; } else { val2 = vector2->vals->args[i]; } /* accum += v1[i] * val2 */ TP(tp); accum = TP_EVAL(tp, ctx, "@@+@@*@@", accum, Value_copy(vector1->vals->args[i]), Value_copy(val2)); } return accum; }
static Value* eval_abs(const Context* ctx, const ArgList* arglist, bool internal) { if(arglist->count != 1) { return ValErr(builtinArgs("abs", 1, arglist->count)); } Value* val = Value_coerce(arglist->args[0], ctx); if(val->type == VAL_ERR) { return val; } Value* ret; switch(val->type) { case VAL_INT: ret = ValInt(ABS(val->ival)); break; case VAL_REAL: ret = ValReal(ABS(val->rval)); break; case VAL_FRAC: ret = ValFrac(Fraction_new(ABS(val->frac->n), val->frac->d)); break; case VAL_VEC: ret = Vector_magnitude(val->vec, ctx); break; default: badValType(val->type); } Value_free(val); return ret; }
static Value* unop_fact(const Context* ctx, const Value* a) { if(a->type != VAL_INT) { return ValErr(typeError("Factorial operand must be an integer.")); } if(a->ival > 20) { return ValErr(mathError("Factorial operand too large (%lld > 20).", a->ival)); } return ValInt(fact(a->ival)); }
SCValue* Fraction_eval(SCFraction* self) { SCFraction* frac = Fraction_copy(self); Fraction_simplify(frac); SCValue* ret; if (frac->denominator == 1) { ret = ValInt(frac->numerator); Fraction_free(frac); } else { ret = ValFrac(frac); } return ret; }
Value* Value_copy(const Value* val) { Value* ret; switch(val->type) { case VAL_INT: ret = ValInt(val->ival); break; case VAL_REAL: ret = ValReal(val->rval); break; case VAL_FRAC: ret = ValFrac(Fraction_copy(val->frac)); break; case VAL_EXPR: ret = ValExpr(BinOp_copy(val->expr)); break; case VAL_CALL: ret = ValCall(FuncCall_copy(val->call)); break; case VAL_UNARY: ret = ValUnary(UnOp_copy(val->term)); break; case VAL_VAR: ret = ValVar(val->name); break; case VAL_VEC: ret = ValVec(Vector_copy(val->vec)); break; case VAL_NEG: /* Shouldn't be reached, but so easy to code */ ret = ValNeg(); break; case VAL_ERR: ret = ValErr(Error_copy(val->err)); break; default: typeError("Unknown value type: %d.", val->type); ret = NULL; break; } return ret; }
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; }
SCExpression* Fraction_asExpression(SCFraction* self) { return Expression_new(kExpressionDivide, ValInt(self->numerator), ValInt(self->denominator)); }
Value* Value_parse(const char** expr, char sep, char end, parser_cb* cb) { Value* val; BINTYPE op = BIN_UNK; BinOp* tree = NULL; BinOp* prev; while(1) { /* Get next value */ val = Value_next(expr, end, cb); /* Error parsing next value? */ if(val->type == VAL_ERR) { if(tree) { BinOp_free(tree); } return val; } /* End of input? */ if(val->type == VAL_END) { if(tree) { BinOp_free(tree); } return val; } /* Special case: negative value */ if(val->type == VAL_NEG) { Value_free(val); BinOp* cur = BinOp_new(BIN_MUL, ValInt(-1), NULL); if(tree) { prev->b = ValExpr(cur); } else { tree = cur; } prev = cur; continue; } /* Get next operator if it exists */ op = BinOp_nextType(expr, sep, end); /* Invalid operator? Return syntax error */ if(op == BIN_UNK) { /* Exit gracefully and return error */ if(tree) { BinOp_free(tree); } Value_free(val); return ValErr(badChar(**expr)); } /* End of the statement? */ else if(op == BIN_END) { /* Only skip end character if there's only one value to parse */ if(!sep && **expr && **expr == end) { (*expr)++; } /* If there was only one value, return it */ if(!tree) { return val; } /* Otherwise, place the final value into the tree and break out of the parse loop */ prev->b = val; break; } /* Tree not yet begun? Initialize it! */ if(tree == NULL) { tree = BinOp_new(op, val, NULL); prev = tree; } else { /* Tree already started, so add to it */ treeAddValue(&tree, &prev, op, val); } } return ValExpr(tree); }