Value* Vector_eval(const Vector* vec, const Context* ctx) { ArgList* args = ArgList_eval(vec->vals, ctx); if(args == NULL) { return ValErr(ignoreError()); } return ValVec(Vector_new(args)); }
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)); }
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)); }
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; }
Value* Vector_parse(const char** expr) { ArgList* vals = ArgList_parse(expr, ',', '>'); if(vals == NULL) return ValErr(ignoreError()); if(vals->count < 2) { ArgList_free(vals); return ValErr(syntaxError("Vector must have at least 2 components.")); } return ValVec(Vector_new(vals)); }
Value* Vector_parse(const char** expr, parser_cb* cb) { ArgList* vals = ArgList_parse(expr, ',', '>', cb); if(vals == NULL) { /* Error occurred and has already been raised */ return ValErr(ignoreError()); } if(vals->count < 1) { ArgList_free(vals); return ValErr(syntaxError("Vector must have at least 1 component.")); } return ValVec(Vector_new(vals)); }
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)); }
Value* Vector_eval(Vector* vec, Context* ctx) { return ValVec(Vector_new(ArgList_eval(vec->vals, ctx))); }
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)); }
void RulePrinter::end() { uint32_t body = output_->addSet(); output_->popSet(); const ReifiedOutput::Set &head = output_->getSet(); assert(head.size() <= 1); out() << "rule("; if(head.empty()) { out() << "pos(false)"; } else { output_->val(head.front()).print(output()->storage(), out()); } out() << ",pos(conjunction(" << body << "))).\n"; Val val; val = Val::create(Val::NUM, int(body)); val = Val::create(Val::FUNC, output_->storage()->index(Func(output_->storage(), output_->storage()->index("conjunction"), ValVec(1, val)))); val = Val::create(Val::FUNC, output_->storage()->index(Func(output_->storage(), output_->storage()->index("pos"), ValVec(1, val)))); size_t conjunction = output_->symbol(val); output_->popSet(); output_->addDep(conjunction, 2); output_->popDep(true, 2); // lits -> body -> head output_->popDep(false); }
void JunctionAggrLitPrinter::end() { if(head_) { if(output_->getSet().size() == 1) { size_t sym = output_->getSet().back(); output_->popSet(); output_->addToSet(sym); } else if(output_->getSet().size() > 0) { uint32_t set = output_->addSet(); output_->popSet(); Val val; val = Val::create(Val::NUM, (int)set); val = Val::create(Val::FUNC, output_->storage()->index(Func(output_->storage(), output_->storage()->index("disjunction"), ValVec(1, val)))); val = Val::create(Val::FUNC, output_->storage()->index(Func(output_->storage(), output_->storage()->index("pos"), ValVec(1, val)))); output_->addToSet(output_->symbol(val)); } else { output_->popSet(); } } }
void ParityAggrLitPrinter::end() { uint32_t list = output_->addList(); output_->popList(); Val val; val = Val::create(Val::NUM, (int)list); val = Val::create(Val::FUNC, output_->storage()->index(Func(output_->storage(), output_->storage()->index(even_ ? "even" : "odd"), ValVec(1, val)))); val = Val::create(Val::FUNC, output_->storage()->index(Func(output_->storage(), output_->storage()->index(sign_ ? "neg" : "pos"), ValVec(1, val)))); size_t parity = output_->symbol(val); output_->addToSet(parity); if(!head_ && !sign_) { output_->addDep(parity, 2); output_->popDep(true); output_->popDep(false); output_->addDep(parity); } }
void MinMaxAggrLitPrinter::end() { uint32_t list = output_->addList(); output_->popList(); ValVec vals; vals.push_back(hasLower_ ? lower_ : max_ ? Val::inf() : Val::sup()); vals.push_back(Val::create(Val::NUM, (int)list)); vals.push_back(hasUpper_ ? upper_ : max_ ? Val::sup() : Val::inf()); Val val; val = Val::create(Val::FUNC, output_->storage()->index(Func(output_->storage(), output_->storage()->index(max_ ? "max" : "min"), vals))); val = Val::create(Val::FUNC, output_->storage()->index(Func(output_->storage(), output_->storage()->index(sign_ ? "neg" : "pos"), ValVec(1, val)))); size_t minmax = output_->symbol(val); output_->addToSet(minmax); if(!head_ && !sign_) { if((hasLower_ && max_) || (hasUpper_ && !max_)) { output_->addDep(minmax, 2); output_->popDep(true); output_->popDep(false); output_->addDep(minmax); } else { output_->popDep(false, 2); } } }
void AvgAggrLitPrinter::end() { uint32_t list = output_->addList(); output_->popList(); ValVec vals; vals.push_back(Val::create(Val::NUM, hasLower_ ? lower_ : min_)); vals.push_back(Val::create(Val::NUM, (int)list)); vals.push_back(Val::create(Val::NUM, hasUpper_ ? upper_ : max_)); Val val; val = Val::create(Val::FUNC, output_->storage()->index(Func(output_->storage(), output_->storage()->index("avg"), vals))); val = Val::create(Val::FUNC, output_->storage()->index(Func(output_->storage(), output_->storage()->index(sign_ ? "neg" : "pos"), ValVec(1, val)))); size_t avg = output_->symbol(val); output_->addToSet(avg); if(!head_ && !sign_) { output_->addDep(avg, 2); output_->popDep(true); output_->popDep(false); output_->addDep(avg); } }
void SumAggrLitPrinter::end() { uint32_t list = output_->addList(); output_->popList(); ValVec vals; vals.push_back(Val::create(Val::NUM, hasLower_ ? lower_ : min_)); vals.push_back(Val::create(Val::NUM, (int)list)); vals.push_back(Val::create(Val::NUM, hasUpper_ ? upper_ : max_)); Val val; val = Val::create(Val::FUNC, output_->storage()->index(Func(output_->storage(), output_->storage()->index("sum"), vals))); val = Val::create(Val::FUNC, output_->storage()->index(Func(output_->storage(), output_->storage()->index(sign_ ? "neg" : "pos"), ValVec(1, val)))); size_t sum = output_->symbol(val); output_->addToSet(sum); if(!sign_ && !head_) { if(hasNeg_ || hasLower_) { output_->addDep(sum, 2); output_->popDep(true); output_->popDep(false); output_->addDep(sum); } else { output_->popDep(false, 2); } } }