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* 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; }
/* Arithmetic */ SCValue* Fraction_add(SCFraction* self, SCValue* other) { SCValue* ret; switch (other->type) { case kValueFraction: { SCNumber numerator = self->numerator * other->fraction->denominator + self->denominator * other->fraction->numerator; SCNumber denominator = self->denominator * other->fraction->denominator; ret = ValFrac(Fraction_new(numerator, denominator)); break; } case kValueInteger: { SCNumber numerator = self->numerator + other->integer * self->denominator; SCNumber denominator = self->denominator; ret = ValFrac(Fraction_new(numerator, denominator)); break; } case kValueReal: { ret = ValReal(Fraction_asReal(self) + other->real); break; } default: return ValErr(nonArithType(other->type)); break; } 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; }