Exemplo n.º 1
0
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;
}
Exemplo n.º 2
0
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;
}
Exemplo n.º 3
0
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;
}
Exemplo n.º 4
0
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));
}
Exemplo n.º 5
0
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;
}
Exemplo n.º 6
0
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;
}
Exemplo n.º 7
0
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;
}
Exemplo n.º 8
0
SCExpression* Fraction_asExpression(SCFraction* self) {
    return Expression_new(kExpressionDivide, ValInt(self->numerator), ValInt(self->denominator));
}
Exemplo n.º 9
0
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);
}