Exemple #1
0
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));
}
Exemple #2
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;
}
Exemple #3
0
static Value* vecMagOp(const Vector* vec, const Value* scalar, const Context* ctx, BINTYPE bin) {
    /* Calculate old magnitude */
    Value* mag = Vector_magnitude(vec, ctx);

    /* Calculate new magnitude */
    BinOp* magOp = BinOp_new(bin, Value_copy(mag), Value_copy(scalar));
    Value* newMag = BinOp_eval(magOp, ctx);
    BinOp_free(magOp);

    /* Calculate scalar factor */
    BinOp* newDivOld = BinOp_new(BIN_DIV, newMag, mag);
    Value* scalFact = BinOp_eval(newDivOld, ctx);
    BinOp_free(newDivOld);
    /* Both newMag and mag are freed with newDivOld */

    /* Calculate new vector */
    return vecScalarOp(vec, scalFact, ctx, BIN_MUL);
}
Exemple #4
0
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));
}
Exemple #5
0
void Value_free(Value* val) {
	if(!val) return;
	
	switch(val->type) {
		case VAL_EXPR:
			BinOp_free(val->expr);
			break;
		
		case VAL_UNARY:
			UnOp_free(val->term);
			break;
		
		case VAL_CALL:
			FuncCall_free(val->call);
			break;
		
		case VAL_FRAC:
			Fraction_free(val->frac);
			break;
		
		case VAL_VAR:
			free(val->name);
			break;
		
		case VAL_VEC:
			Vector_free(val->vec);
			break;
		
		case VAL_ERR:
			Error_free(val->err);
			break;
		
		default:
			/* The rest don't need to be freed */
			break;
	}
	
	free(val);
}
Exemple #6
0
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));
}
Exemple #7
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);
}