00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "Prim.H"
00022 #include "Val.H"
00023 #include "Expr.H"
00024 #include "ApplyCache.H"
00025 #include "Location.H"
00026 #include "Err.H"
00027 #include "Debug.H"
00028 #include "VASTi.H"
00029 #include "ThreadData.H"
00030 #include <Table.H>
00031 #include <VestaConfig.H>
00032 #include <iostream>
00033 #include <iomanip>
00034 #include <fstream>
00035 #include <BufStream.H>
00036
00037 using std::ostream;
00038 using std::cout;
00039 using std::cerr;
00040 using std::hex;
00041 using std::setw;
00042 using std::setfill;
00043 using Basics::OBufStream;
00044
00045 static const Text noName("Anonymous");
00046 static int numThreads = 1;
00047 static int threadAllowed;
00048 static bool parMapFailing = false;
00049 static Basics::mutex parMu;
00050 static Basics::cond WorkCond;
00051 static IntSeq ThreadIds;
00052 static int ThreadIdMax = 1;
00053
00054 void PrimError(const Text& msg, const Vals& args, SrcLoc *loc) {
00055 outputMu.lock();
00056 Error(msg + ":\n args = ", loc);
00057 ErrorArgs(args);
00058 ErrorDetail(".\n");
00059 outputMu.unlock();
00060 }
00061
00062 void PrimError(const Text& msg, Val arg, SrcLoc *loc) {
00063 outputMu.lock();
00064 Error(msg + ":\n arg = `", loc);
00065 ErrorVal(arg);
00066 ErrorDetail("'.\n");
00067 outputMu.unlock();
00068 }
00069
00070 void PrimError(const Text& msg, Val arg1, Val arg2, SrcLoc *loc) {
00071 outputMu.lock();
00072 Error(msg + ":\n arg1 = `", loc);
00073 ErrorVal(arg1);
00074 ErrorDetail("',\n arg2 = `");
00075 ErrorVal(arg2);
00076 ErrorDetail("'.\n");
00077 outputMu.unlock();
00078 }
00079
00080 static Table<Text,PrimExec>::Default Primitives(64);
00081
00082 void AddPrimitive(const Text& id, PrimExec exec) {
00083 if (Primitives.Put(id, exec)) {
00084 outputMu.lock();
00085 Error("(impl) Name conflict in Primitives! `" + id + "'.\n");
00086 outputMu.unlock();
00087 }
00088 }
00089
00090 PrimExec LookupPrim(const Text& id) {
00091 PrimExec result;
00092 return Primitives.Get(id, result) ? result : NULL;
00093 }
00094
00096 Val IsType(Val v, bool b) {
00097
00098
00099 Val result = NEW_CONSTR(BooleanVC, (b));
00100 result->dps = v->dps;
00101 result->AddToDPS(v->path, ValType(v), TypePK);
00102 result->cacheit = v->cacheit;
00103 return result;
00104 }
00105
00106 Val IsBinding(ArgList exprs, const Context& c) {
00107 Vals args = EvalArgs(exprs, c);
00108 if (args.Length() != 1) {
00109 PrimError("_is_binding takes one argument", args, exprs->loc);
00110 return NEW(ErrorVC);
00111 }
00112 Val v = args.First();
00113 bool b = (v->vKind == BindingVK);
00114 return IsType(v, b);
00115 }
00116
00117 Val IsBool(ArgList exprs, const Context& c) {
00118 Vals args = EvalArgs(exprs, c);
00119 if (args.Length() != 1) {
00120 PrimError("_is_bool takes one argument", args, exprs->loc);
00121 return NEW(ErrorVC);
00122 }
00123 Val v = args.First();
00124 bool b = (v->vKind == BooleanVK);
00125 return IsType(v, b);
00126 }
00127
00128 Val IsClosure(ArgList exprs, const Context& c) {
00129 Vals args = EvalArgs(exprs, c);
00130 if (args.Length() != 1) {
00131 PrimError("_is_closure takes one argument", args, exprs->loc);
00132 return NEW(ErrorVC);
00133 }
00134 Val v = args.First();
00135 bool b = (v->vKind == ClosureVK ||
00136 v->vKind == ModelVK ||
00137 v->vKind == PrimitiveVK);
00138 return IsType(v, b);
00139 }
00140
00141 Val IsErr(ArgList exprs, const Context& c) {
00142 Vals args = EvalArgs(exprs, c);
00143 if (args.Length() != 1) {
00144 PrimError("_is_err takes one argument", args, exprs->loc);
00145 return NEW(ErrorVC);
00146 }
00147 Val v = args.First();
00148 bool b = (v->vKind == ErrorVK);
00149 return IsType(v, b);
00150 }
00151
00152 Val IsInt(ArgList exprs, const Context& c) {
00153 Vals args = EvalArgs(exprs, c);
00154 if (args.Length() != 1) {
00155 PrimError("_is_int takes one argument", args, exprs->loc);
00156 return NEW(ErrorVC);
00157 }
00158 Val v = args.First();
00159 bool b = (v->vKind == IntegerVK);
00160 return IsType(v, b);
00161 }
00162
00163 Val IsList(ArgList exprs, const Context& c) {
00164 Vals args = EvalArgs(exprs, c);
00165 if (args.Length() != 1) {
00166 PrimError("_is_list takes one argument", args, exprs->loc);
00167 return NEW(ErrorVC);
00168 }
00169 Val v = args.First();
00170 bool b = (v->vKind == ListVK);
00171 return IsType(v, b);
00172 }
00173
00174 Val IsText(ArgList exprs, const Context& c) {
00175 Vals args = EvalArgs(exprs, c);
00176 if (args.Length() != 1) {
00177 PrimError("_is_text takes one argument", args, exprs->loc);
00178 return NEW(ErrorVC);
00179 }
00180 Val v = args.First();
00181 bool b = (v->vKind == TextVK);
00182 return IsType(v, b);
00183 }
00184
00185 Val TypeOfVal(Val v) {
00186
00187
00188 Val tv = ValType(v);
00189 Val result = tv->Copy();
00190 result->dps = v->dps;
00191 result->AddToDPS(v->path, tv, TypePK);
00192 return result;
00193 }
00194
00195 Val TypeOf(ArgList exprs, const Context& c) {
00196 Vals args = EvalArgs(exprs, c);
00197 if (args.Length() != 1) {
00198 PrimError("_type_of takes one argument", args, exprs->loc);
00199 return NEW(ErrorVC);
00200 }
00201 return TypeOfVal(args.First());
00202 }
00203
00204 Val SameTypeInner(Val v1, Val v2) {
00205 Val result;
00206 bool b = (v1->vKind == v2->vKind);
00207 result = NEW_CONSTR(BooleanVC, (b));
00208 result->dps = TypeOfVal(v1)->dps;
00209 return result->MergeAndTypeDPS(v2);
00210 }
00211
00212 Val SameType(ArgList exprs, const Context& c) {
00213 Vals args = EvalArgs(exprs, c);
00214 if (args.Length() != 2) {
00215 PrimError("_same_type takes two arguments", args, exprs->loc);
00216 return NEW(ErrorVC);
00217 }
00218 Val v1 = args.First(), v2 = args.Second();
00219 Val result = SameTypeInner(v1, v2);
00220 result->cacheit = v1->cacheit && v2->cacheit;
00221 return result;
00222 }
00223
00224 Val BindingAppend(BindingVC* b1, BindingVC* b2) {
00225 Context c1 = b1->elems, c2 = b2->elems;
00226 Context rc;
00227 Val v, test;
00228 Assoc a1, a2;
00229 Text name;
00230
00231 while (!c1.Null()) {
00232 a1 = c1.Pop();
00233 name = a1->name;
00234 test = b2->Defined(name);
00235 if (IsValTrue(test)) {
00236 Val result = NEW_CONSTR(ErrorVC, (false));
00237 return result->Merge(test)->Merge(b1->Defined(name));
00238 }
00239 v = b1->Extend(a1->val, name, NormPK, false);
00240 rc.Append1D(NEW_CONSTR(AssocVC, (name, v)));
00241 }
00242 while (!c2.Null()) {
00243 a2 = c2.Pop();
00244 name = a2->name;
00245 v = b2->Extend(a2->val, name, NormPK, false);
00246 rc.Append1D(NEW_CONSTR(AssocVC, (name, v)));
00247 }
00248 BindingVC *result = NEW_CONSTR(BindingVC, (rc));
00249 result->MergeAndLenDPS(b1)->MergeAndLenDPS(b2);
00250 result->cacheit = b1->cacheit && b2->cacheit;
00251 return result;
00252 }
00253
00254 Val ListAppend(ListVC* l1, ListVC* l2) {
00255 Vals elems1 = l1->elems, elems2 = l2->elems;
00256 Val v1, v2, v;
00257 Vals rc;
00258
00259 int cnt = 0;
00260 while (!elems1.Null()) {
00261 v1 = elems1.Pop();
00262 v = l1->Extend(v1, IntArc(cnt++), NormPK, false);
00263 rc.Append1D(v);
00264 }
00265 cnt = 0;
00266 while (!elems2.Null()) {
00267 v2 = elems2.Pop();
00268 v = l2->Extend(v2, IntArc(cnt++), NormPK, false);
00269 rc.Append1D(v);
00270 }
00271 ListVC* result = NEW_CONSTR(ListVC, (rc));
00272 result->MergeDPS(l1->dps)->MergeDPS(l2->dps);
00273
00274
00275
00276
00277
00278 if (l1->path != NULL) {
00279 result->AddToDPS(l1->path, NEW_CONSTR(IntegerVC, (l1->elems.Length())),
00280 LLenPK);
00281 result->AddToLenDPS(*l1->path, l1);
00282 }
00283 else {
00284 result->MergeLenDPS(l1);
00285 result->MergeToLenDPS(l1->lenDps);
00286 }
00287
00288 if (l2->path != NULL)
00289 result->AddToLenDPS(*l2->path, l2);
00290 else
00291 result->MergeToLenDPS(l2->lenDps);
00292 result->cacheit = l1->cacheit && l2->cacheit;
00293 return result;
00294 }
00295
00296 Val Append(ArgList exprs, const Context& c) {
00297 Vals args = EvalArgs(exprs, c);
00298
00299 if (args.Length() != 2) {
00300 PrimError("_append must take two arguments", args, exprs->loc);
00301 return NEW(ErrorVC);
00302 }
00303 Val v1 = args.First(), v2 = args.Second(), result;
00304 if (v1->vKind != v2->vKind) {
00305 PrimError("`_append' not implemented for these args", v1, v2, exprs->loc);
00306 result = NEW(ErrorVC);
00307 return result->MergeAndTypeDPS(v1)->MergeAndTypeDPS(v2);
00308 }
00309 switch (v1->vKind) {
00310 case ListVK:
00311
00312 if (IsEmptyList(v2)) {
00313 v1->cacheit = v1->cacheit && v2->cacheit;
00314 return v1->MergeAndLenDPS(v2);
00315 }
00316 if (IsEmptyList(v1)) {
00317 v2->cacheit = v1->cacheit && v2->cacheit;
00318 return v2->MergeAndLenDPS(v1);
00319 }
00320 return ListAppend((ListVC*)v1, (ListVC*)v2);
00321 case BindingVK:
00322 if (IsEmptyBinding(v2)) {
00323 v1->cacheit = v1->cacheit && v2->cacheit;
00324 return v1->MergeAndLenDPS(v2);
00325 }
00326 if (IsEmptyBinding(v1)) {
00327 v2->cacheit = v1->cacheit && v2->cacheit;
00328 return v2->MergeAndLenDPS(v1);
00329 }
00330 result = BindingAppend((BindingVC*)v1, (BindingVC*)v2);
00331 if (result->vKind == ErrorVK) {
00332 PrimError("Bindings passed to _append must be disjoint", v1, v2, exprs->loc);
00333 return NEW(ErrorVC);
00334 }
00335 return result;
00336 default:
00337 PrimError("Arguments of _append must be lists or bindings", v1, v2, exprs->loc);
00338 result = NEW(ErrorVC);
00339 return result->MergeAndTypeDPS(v1)->MergeAndTypeDPS(v2);
00340 }
00341 }
00342
00343 Val BindingMinus(BindingVC* b1, BindingVC* b2) {
00344 Context rc;
00345
00346 Context work = b1->elems;
00347 while (!work.Null()) {
00348 Assoc a = work.Pop();
00349 if (!b2->DefinedNoDpnd(a->name)) {
00350 Val v = b1->Extend(a->val, a->name, NormPK, false);
00351 rc.Append1D(NEW_CONSTR(AssocVC, (a->name, v)));
00352 }
00353 }
00354 BindingVC *result = NEW_CONSTR(BindingVC, (rc));
00355 result->MergeAndTypeDPS(b1)->MergeAndLenDPS(b2);
00356
00357 if (b1->path != NULL)
00358 result->AddToLenDPS(*b1->path, b1);
00359 else
00360 result->MergeToLenDPS(b1->lenDps);
00361 if (b2->path != NULL)
00362 result->AddToLenDPS(*b2->path, b1);
00363 else
00364 result->MergeToLenDPS(b2->lenDps);
00365 result->cacheit = b1->cacheit && b2->cacheit;
00366 return result;
00367 }
00368
00369 Val Minus(Expr e1, Expr e2, const Context& c) {
00370 Val v1 = e1->Eval(c), v2 = e2->Eval(c);
00371 Val result;
00372
00373 if (v1->vKind != v2->vKind) {
00374 PrimError("`-' not implemented for these args", v1, v2, e1->loc);
00375 result = NEW(ErrorVC);
00376 return result->MergeAndTypeDPS(v1)->MergeAndTypeDPS(v2);
00377 }
00378 switch (v1->vKind) {
00379 case IntegerVK:
00380 {
00381 Basics::int32 n1 = ((IntegerVC*)v1)->num;
00382 Basics::int32 n2 = ((IntegerVC*)v2)->num;
00383 Basics::int32 res = n1 - n2;
00384 if ((n1 < 0) != (n2 < 0) && (n1 < 0) != (res < 0)) {
00385 PrimError("Overflow on `-'", v1, v2, e1->loc);
00386 result = NEW(ErrorVC);
00387 return result->Merge(v1)->Merge(v2);
00388 }
00389 result = NEW_CONSTR(IntegerVC, (res));
00390 result->cacheit = v1->cacheit && v2->cacheit;
00391 return result->Merge(v1)->Merge(v2);
00392 }
00393 case BindingVK:
00394 if (IsEmptyBinding(v2)) {
00395 v1->cacheit = v1->cacheit && v2->cacheit;
00396 return v1->MergeAndLenDPS(v2);
00397 }
00398 if (IsEmptyBinding(v1)) {
00399 v1->cacheit = v1->cacheit && v2->cacheit;
00400 return v1->MergeAndTypeDPS(v2);
00401 }
00402 return BindingMinus((BindingVC*)v1, (BindingVC*)v2);
00403 default:
00404 PrimError("`-' not implemented for these args", v1, v2, e1->loc);
00405 result = NEW(ErrorVC);
00406 return result->MergeAndTypeDPS(v1)->MergeAndTypeDPS(v2);
00407 }
00408 }
00409
00410 Val Bind1(ArgList exprs, const Context& c) {
00411 Vals args = EvalArgs(exprs, c);
00412
00413 if (args.Length() != 2) {
00414 PrimError("_bind1 takes two arguments", args, exprs->loc);
00415 return NEW(ErrorVC);
00416 }
00417 Val v1 = args.First(), v2 = args.Second(), result;
00418 if (v1->vKind != TextVK) {
00419 PrimError("First argument of _bind1 must be a text", v1, exprs->loc);
00420 result = NEW(ErrorVC);
00421 return result->MergeAndTypeDPS(v1);
00422 }
00423 Text name(((TextVC*)v1)->NDS());
00424 if (name.Empty()) {
00425 PrimError("First argument of _bind1 must be nonempty", v1, exprs->loc);
00426 result = NEW(ErrorVC);
00427 return result->Merge(v1);
00428 }
00429 result = NEW_CONSTR(BindingVC,
00430 (Context(NEW_CONSTR(AssocVC, (name, v2)))));
00431 result->cacheit = v1->cacheit;
00432 return result->Merge(v1);
00433 }
00434
00435 Val List1(ArgList exprs, const Context& c) {
00436 Vals args = EvalArgs(exprs, c);
00437 if (args.Length() != 1) {
00438 PrimError("_list1 takes one argument", args, exprs->loc);
00439 return NEW(ErrorVC);
00440 }
00441 Val v1 = args.First();
00442
00443 return NEW_CONSTR(ListVC, (Vals(v1)));
00444 }
00445
00446 Val Defined(ArgList exprs, const Context& c) {
00447 Vals args = EvalArgs(exprs, c);
00448 if (args.Length() != 2) {
00449 PrimError("_defined takes two arguments", args, exprs->loc);
00450 return NEW(ErrorVC);
00451 }
00452 Val v1 = args.First(), v2 = args.Second(), result;
00453 if (v2->vKind != TextVK) {
00454 PrimError("Second argument of _defined must be a text", v2, exprs->loc);
00455 result = NEW(ErrorVC);
00456 return result->MergeAndTypeDPS(v2);
00457 }
00458 Text name(((TextVC*)v2)->NDS());
00459 if (name.Empty()) {
00460 PrimError("Second argument of _defined must be nonempty", v2, exprs->loc);
00461 result = NEW(ErrorVC);
00462 return result->Merge(v2);
00463 }
00464 if (IsEmptyBinding(v1)) {
00465 result = NEW_CONSTR(BooleanVC, (false));
00466 result->cacheit = v1->cacheit && v2->cacheit;
00467 return result->MergeAndLenDPS(v1)->Merge(v2);
00468 }
00469 if (v1->vKind != BindingVK) {
00470 PrimError("First argument of _defined must be a binding", v1, exprs->loc);
00471 result = NEW(ErrorVC);
00472 return result->MergeAndTypeDPS(v1);
00473 }
00474 result = ((BindingVC*)v1)->Defined(name);
00475 result->cacheit = result->cacheit && v2->cacheit;
00476 return result->Merge(v2);
00477 }
00478
00479 Val Div(ArgList exprs, const Context& ctxt) {
00480 Vals args = EvalArgs(exprs, ctxt);
00481 if (args.Length() != 2) {
00482 PrimError("_div takes two arguments", args, exprs->loc);
00483 return NEW(ErrorVC);
00484 }
00485 Val v1 = args.First(), v2 = args.Second(), result;
00486 if (v1->vKind != IntegerVK) {
00487 PrimError("First arguments of _div must be integer", v1, exprs->loc);
00488 result = NEW(ErrorVC);
00489 return result->MergeAndTypeDPS(v1);
00490 }
00491 if (v2->vKind != IntegerVK) {
00492 PrimError("Second argument of _div must be integer", v2, exprs->loc);
00493 result = NEW(ErrorVC);
00494 return result->MergeAndTypeDPS(v2);
00495 }
00496 Basics::int32 a = ((IntegerVC*)v1)->num;
00497 Basics::int32 b = ((IntegerVC*)v2)->num;
00498 if (b == 0) {
00499 PrimError("Attempt to divide by 0 with _div", args, exprs->loc);
00500 result = NEW(ErrorVC);
00501 return result->Merge(v2);
00502 }
00503
00504 Basics::int32 c;
00505 if ((a == 0) && (b != 0)) { c = 0;
00506 } else if (a > 0) { c = (b >= 0) ? (a) / (b) : -1 - (a-1) / (-b);
00507 } else { c = (b >= 0) ? -1 - (-1-a) / (b) : (-a) / (-b);
00508 }
00509 if (b == -1 && a == c) {
00510 PrimError("Overflow in _div", args, exprs->loc);
00511 result = NEW(ErrorVC);
00512 return result->Merge(v1)->Merge(v2);
00513 }
00514 result = NEW_CONSTR(IntegerVC, (c));
00515 result->cacheit = v1->cacheit && v2->cacheit;
00516 return result->Merge(v1)->Merge(v2);
00517 }
00518
00519 Val Elem(ArgList exprs, const Context& c) {
00520 Vals args = EvalArgs(exprs, c);
00521 if (args.Length() != 2) {
00522 PrimError("_elem takes two arguments", args, exprs->loc);
00523 return NEW(ErrorVC);
00524 }
00525 Val v1 = args.First(), v2 = args.Second(), result;
00526 if (v2->vKind != IntegerVK) {
00527 PrimError("Second argument of _elem must be an integer", v2, exprs->loc);
00528 result = NEW(ErrorVC);
00529 return result->MergeAndTypeDPS(v2);
00530 }
00531 Basics::int32 n = ((IntegerVC*)v2)->num;
00532 switch (v1->vKind) {
00533 case TextVK:
00534 if (n < 0) {
00535 result = NEW_CONSTR(TextVC, (emptyText));
00536 result->cacheit = v1->cacheit && v2->cacheit;
00537 return result->MergeAndTypeDPS(v1)->Merge(v2);
00538 }
00539 if (n > Text::MaxInt) {
00540 PrimError("(impl) _elem integer argument too big", v2, exprs->loc);
00541 result = NEW(ErrorVC);
00542 return result->MergeAndTypeDPS(v1)->Merge(v2);
00543 }
00544 result = NEW_CONSTR(TextVC, (((TextVC*)v1)->NDS().Sub(n, 1)));
00545 result->cacheit = v1->cacheit && v2->cacheit;
00546 return result->Merge(v1)->Merge(v2);
00547 case ListVK:
00548 {
00549 ListVC *lstv = (ListVC*)v1;
00550 int len = lstv->elems.Length();
00551 if (n < 0 || n >= len) {
00552 PrimError("_elem number out of range", v2, exprs->loc);
00553 result = NEW(ErrorVC);
00554 return result->MergeAndLenDPS(lstv)->Merge(v2);
00555 }
00556 result = lstv->GetElem(n);
00557 result->cacheit = result->cacheit && v2->cacheit;
00558 return result->Merge(v2);
00559 }
00560 case BindingVK:
00561 {
00562 BindingVC *bv = (BindingVC*)v1;
00563 int len = bv->elems.Length();
00564 if (n < 0 || n >= len) {
00565 PrimError("_elem number out of range", v2, exprs->loc);
00566 result = NEW(ErrorVC);
00567 return result->MergeAndLenDPS(bv)->Merge(v2);
00568 }
00569 Assoc a = bv->elems.Nth(n);
00570 Val v = v1->Extend(a->val, IntArc(n), NormPK, false);
00571 result = NEW_CONSTR(BindingVC,
00572 (Context(NEW_CONSTR(AssocVC, (a->name, v)))));
00573 result->cacheit = result->cacheit && v2->cacheit;
00574 return result->MergeDPS(v1->dps)->Merge(v2);
00575 }
00576 default:
00577 PrimError("First argument of _elem must be a text, list, or binding", v1, exprs->loc);
00578 result = NEW(ErrorVC);
00579 return result->MergeAndTypeDPS(v1);
00580 }
00581 }
00582
00583 Val Assert(ArgList exprs, const Context& c) {
00584 Vals args = EvalArgs(exprs, c);
00585 if (args.Length() != 2) {
00586 PrimError("_assert takes two arguments", args, exprs->loc);
00587 return NEW(ErrorVC);
00588 }
00589 Val v1 = args.First();
00590 if (v1->vKind != BooleanVK) {
00591 PrimError("First argument of _assert must be a boolean", v1, exprs->loc);
00592 return NEW(ErrorVC);
00593 }
00594 if (((BooleanVC*)v1)->b) { return v1; }
00595 Val v2 = args.Second();
00596 outputMu.lock();
00597 Error("");
00598 ErrorVal(v2);
00599 ErrorDetail(".\n");
00600 if (diagnose) { PrintContext(&cerr, c); }
00601 outputMu.unlock();
00602 return NEW(ErrorVC);
00603 }
00604
00605 Val Find(ArgList exprs, const Context& c) {
00606 Vals args = EvalArgs(exprs, c);
00607 Basics::int32 start = 0;
00608 Val v1, v2, v3 = valZero, result;
00609 switch (args.Length()) {
00610 case 3:
00611 v3 = args.Third();
00612 if (v3->vKind != IntegerVK) {
00613 PrimError("Third argument of _find must be an integer", v3, exprs->loc);
00614 result = NEW(ErrorVC);
00615 return result->MergeAndTypeDPS(v3);
00616 }
00617 start = ((IntegerVC*)v3)->num;
00618 break;
00619 case 2:
00620 break;
00621 default:
00622 PrimError("_find takes two or three arguments", args, exprs->loc);
00623 return NEW(ErrorVC);
00624 }
00625 v1 = args.First();
00626 if (v1->vKind != TextVK) {
00627 PrimError("First argument of _find must be a text", v1, exprs->loc);
00628 result = NEW(ErrorVC);
00629 return result->MergeAndTypeDPS(v1);
00630 }
00631 Text t(((TextVC*)v1)->NDS());
00632 v2 = args.Second();
00633 if (v2->vKind != TextVK) {
00634 PrimError("Second argument of _find must be a text", v2, exprs->loc);
00635 result = NEW(ErrorVC);
00636 return result->MergeAndTypeDPS(v2);
00637 }
00638 Text p(((TextVC*)v2)->NDS());
00639 if (start > Text::MaxInt) {
00640 PrimError("(impl) _find integer argument too big", v3, exprs->loc);
00641 result = NEW(ErrorVC);
00642 return result->Merge(v3);
00643 }
00644 int plen = p.Length();
00645 int j = t.Length() - plen;
00646 int i = max(start, 0);
00647 while (i <= j) {
00648 int k = 0;
00649 while (k < plen && t[i+k] == p[k]) k++;
00650 if (k == plen) {
00651 result = NEW_CONSTR(IntegerVC, (i));
00652 result->cacheit = v1->cacheit && v2->cacheit && v3->cacheit;
00653 return result->Merge(v1)->Merge(v2)->Merge(v3);
00654 }
00655 i++;
00656 }
00657 result = NEW_CONSTR(IntegerVC, (-1));
00658 result->cacheit = v1->cacheit && v2->cacheit && v3->cacheit;
00659 return result->Merge(v1)->Merge(v2)->Merge(v3);
00660 }
00661
00662 Val FindR(ArgList exprs, const Context& c) {
00663 Vals args = EvalArgs(exprs, c);
00664 Basics::int32 start = 0;
00665 Val v1, v2, v3 = valZero, result;
00666 switch (args.Length()) {
00667 case 3:
00668 v3 = args.Third();
00669 if (v3->vKind != IntegerVK) {
00670 PrimError("Third argument of _findr must be an integer", v3, exprs->loc);
00671 result = NEW(ErrorVC);
00672 return result->MergeAndTypeDPS(v3);
00673 }
00674 start = ((IntegerVC*)v3)->num;
00675 break;
00676 case 2:
00677 break;
00678 default:
00679 PrimError("_findr takes two or three arguments", args, exprs->loc);
00680 return NEW(ErrorVC);
00681 }
00682 v1 = args.First();
00683 if (v1->vKind != TextVK) {
00684 PrimError("First argument of _findr must be a text", v1, exprs->loc);
00685 result = NEW(ErrorVC);
00686 return result->MergeAndTypeDPS(v1);
00687 }
00688 Text t(((TextVC*)v1)->NDS());
00689 v2 = args.Second();
00690 if (v2->vKind != TextVK) {
00691 PrimError("Second argument of _findr must be a text", args, exprs->loc);
00692 result = NEW(ErrorVC);
00693 return result->MergeAndTypeDPS(v2);
00694 }
00695 Text p(((TextVC*)v2)->NDS());
00696 if (start > Text::MaxInt) {
00697 PrimError("(impl) _findr integer argument too big", args, exprs->loc);
00698 result = NEW(ErrorVC);
00699 return result->Merge(v3);
00700 }
00701 int plen = p.Length();
00702 int j = t.Length() - plen;
00703 int i = max(start, 0);
00704 while (i <= j) {
00705 int k = 0;
00706 while (k < plen && t[j+k] == p[k]) k++;
00707 if (k == plen) {
00708 result = NEW_CONSTR(IntegerVC, (j));
00709 result->cacheit = v1->cacheit && v2->cacheit && v3->cacheit;
00710 return result->Merge(v1)->Merge(v2)->Merge(v3);
00711 }
00712 j--;
00713 }
00714 result = NEW_CONSTR(IntegerVC, (-1));
00715 result->cacheit = v1->cacheit && v2->cacheit && v3->cacheit;
00716 return result->Merge(v1)->Merge(v2)->Merge(v3);
00717 }
00718
00719 Val Head(ArgList exprs, const Context& c) {
00720 Vals args = EvalArgs(exprs, c);
00721
00722 if (args.Length() != 1) {
00723 PrimError("_head takes one argument", args, exprs->loc);
00724 return NEW(ErrorVC);
00725 }
00726 Val v = args.First(), result;
00727 switch (v->vKind) {
00728 case ListVK:
00729 {
00730 Vals vals = ((ListVC*)v)->elems;
00731 if (vals.Null()) {
00732 PrimError("Argument of _head must not be nil", v, exprs->loc);
00733 result = NEW(ErrorVC);
00734 return result->Merge(v);
00735 }
00736 return ((ListVC*)v)->GetElem(0);
00737 }
00738 case BindingVK:
00739 {
00740 Context ctxt = ((BindingVC*)v)->elems;
00741 if (ctxt.Null()) {
00742 PrimError("Argument of _head must not be nil", v, exprs->loc);
00743 result = NEW(ErrorVC);
00744 return result->Merge(v);
00745 }
00746 Assoc a = ctxt.First();
00747 Val v0 = v->Extend(a->val, IntArc(0), NormPK, false);
00748 result = NEW_CONSTR(BindingVC,
00749 (Context(NEW_CONSTR(AssocVC, (a->name, v0)))));
00750 result->cacheit = v->cacheit;
00751 return result->MergeDPS(v->dps);
00752 }
00753 default:
00754 PrimError("Argument of _head must be a list or binding", v, exprs->loc);
00755 result = NEW(ErrorVC);
00756 return result->MergeAndTypeDPS(v);
00757 }
00758 }
00759
00760 Val Tail(ArgList exprs, const Context& c) {
00761 Vals args = EvalArgs(exprs, c);
00762 if (args.Length() != 1) {
00763 PrimError("_tail takes one argument", args, exprs->loc);
00764 return NEW(ErrorVC);
00765 }
00766 Val v = args.First();
00767 switch (v->vKind) {
00768 case ListVK:
00769 {
00770 ListVC *lstv = (ListVC*)v;
00771 Vals vals = lstv->elems;
00772 if (vals.Null()) {
00773 PrimError("Argument of _tail must not be nil", lstv, exprs->loc);
00774 Val result = NEW(ErrorVC);
00775 return result->Merge(lstv);
00776 }
00777 Val v1 = vals.Pop();
00778 Vals vs;
00779 ListVC *result;
00780 if (lstv->path == NULL) {
00781 result = NEW_CONSTR(ListVC, (vals));
00782 result->lenDps = lstv->lenDps;
00783 }
00784 else {
00785 int cnt = 1;
00786 while (!vals.Null()) {
00787 v1 = lstv->Extend(vals.Pop(), IntArc(cnt++), NormPK, false);
00788 vs.Append1D(v1);
00789 }
00790 result = NEW_CONSTR(ListVC, (vs));
00791
00792 result->AddToLenDPS(*lstv->path, lstv);
00793 }
00794 result->dps = lstv->dps;
00795 result->cacheit = lstv->cacheit;
00796 return result;
00797 }
00798 case BindingVK:
00799 {
00800 BindingVC *bv = (BindingVC*)v;
00801 Context ctxt = bv->elems;
00802 if (ctxt.Null()) {
00803 PrimError("Argument of _tail must not be nil", bv, exprs->loc);
00804 Val result = NEW(ErrorVC);
00805 return result->Merge(bv);
00806 }
00807 Assoc a = ctxt.Pop();
00808 Context cc;
00809 Val v1;
00810 BindingVC *result;
00811 if (bv->path == NULL) {
00812 result = NEW_CONSTR(BindingVC, (ctxt));
00813 result->lenDps = bv->lenDps;
00814 }
00815 else {
00816 while (!ctxt.Null()) {
00817 a = ctxt.Pop();
00818 v1 = bv->Extend(a->val, a->name, NormPK, false);
00819 cc.Append1D(NEW_CONSTR(AssocVC, (a->name, v1)));
00820 }
00821 result = NEW_CONSTR(BindingVC, (cc));
00822
00823 result->AddToLenDPS(*bv->path, bv);
00824 }
00825 result->dps = bv->dps;
00826 result->cacheit = bv->cacheit;
00827 return result;
00828 }
00829 default:
00830 {
00831 PrimError("Argument of _tail must be a list or binding", v, exprs->loc);
00832 Val result = NEW(ErrorVC);
00833 return result->MergeAndTypeDPS(v);
00834 }
00835 }
00836 }
00837
00838 Val Length(ArgList exprs, const Context& c) {
00839 Vals args = EvalArgs(exprs, c);
00840 if (args.Length() != 1) {
00841 PrimError("_length takes one argument", args, exprs->loc);
00842 return NEW(ErrorVC);
00843 }
00844 Val v1 = args.First(), result;
00845 switch (v1->vKind) {
00846 case TextVK:
00847 result = NEW_CONSTR(IntegerVC, (((TextVC*)v1)->NDS().Length()));
00848 result->cacheit = v1->cacheit;
00849 return result->Merge(v1);
00850 case ListVK:
00851 return ((ListVC*)v1)->Length();
00852 case BindingVK:
00853 return ((BindingVC*)v1)->Length();
00854 default:
00855 PrimError("Argument of _length must be a text, list, or binding", v1, exprs->loc);
00856 result = NEW(ErrorVC);
00857 return result->MergeAndTypeDPS(v1);
00858 }
00859 }
00860
00861 Val Lookup(ArgList exprs, const Context& c) {
00862 Vals args = EvalArgs(exprs, c);
00863 if (args.Length() != 2) {
00864 PrimError("_lookup takes two arguments", args, exprs->loc);
00865 return NEW(ErrorVC);
00866 }
00867 Val v1 = args.First(), v2 = args.Second(), result;
00868 if (v2->vKind != TextVK) {
00869 PrimError("Second argument of _lookup must be a text", v2, exprs->loc);
00870 result = NEW(ErrorVC);
00871 return result->MergeAndTypeDPS(v2);
00872 }
00873 Text name(((TextVC*)v2)->NDS());
00874 if (name.Empty()) {
00875 PrimError("Second argument of _lookup must be nonempty", v2, exprs->loc);
00876 result = NEW(ErrorVC);
00877 return result->Merge(v2);
00878 }
00879 if (IsEmptyBinding(v1)) {
00880 PrimError("_lookup of unbound name", args, exprs->loc);
00881 result = NEW(ErrorVC);
00882 return result->MergeAndLenDPS(v1)->Merge(v2);
00883 }
00884 if (v1->vKind != BindingVK) {
00885 PrimError("First argument of _lookup must be a binding", v1, exprs->loc);
00886 result = NEW(ErrorVC);
00887 return result->MergeAndTypeDPS(v1);
00888 }
00889 result = ((BindingVC*)v1)->Lookup(name);
00890 if (result->vKind == UnbndVK) {
00891 PrimError("_lookup of unbound name", args, exprs->loc);
00892 Val err = NEW(ErrorVC);
00893 err->MergeDPS(result->dps);
00894 return err->AddToDPS(result->path, valFalse, BangPK);
00895 }
00896 result->cacheit = result->cacheit && v2->cacheit;
00897 return result->Merge(v2);
00898 }
00899
00900 Val Map(ArgList exprs, const Context& c) {
00901 Vals args = EvalArgs(exprs, c);
00902 if (args.Length() != 2) {
00903 PrimError("_map takes two arguments", args, exprs->loc);
00904 return NEW(ErrorVC);
00905 }
00906 ThreadData *thData = ThreadDataGet();
00907 ostream *traceRes = thData->traceRes;
00908 Val v1 = args.First(), v2 = args.Second(), result;
00909 switch (v2->vKind) {
00910 case BindingVK:
00911 {
00912 Context work = ((BindingVC*)v2)->elems, elems;
00913 if (v1->vKind != ClosureVK) {
00914 PrimError("The first argument of _map must be a function",
00915 v1, exprs->loc);
00916 result = NEW(ErrorVC);
00917 return result->MergeAndTypeDPS(v1);
00918 }
00919 ClosureVC *fun = (ClosureVC*)v1;
00920 Exprs forms = fun->func->args->elems;
00921 if (forms.size() != 2) {
00922 PrimError("The first argument of _map must be a function of two arguments",
00923 v1, exprs->loc);
00924 result = NEW(ErrorVC);
00925 return result->MergeAndTypeDPS(v1);
00926 }
00927 Text name1, name2;
00928 Expr fe = forms.get(0);
00929 if (fe->kind == NameEK)
00930 name1 = ((Name)fe)->id;
00931 else if (fe->kind == AssignEK)
00932 name1 = ((AssignEC*)fe)->lhs->id;
00933 else {
00934 outputMu.lock();
00935 fe->EError("The function has bad parameter list.");
00936 outputMu.unlock();
00937 return NEW(ErrorVC);
00938 }
00939 fe = forms.get(1);
00940 if (fe->kind == NameEK)
00941 name2 = ((Name)fe)->id;
00942 else if (fe->kind == AssignEK)
00943 name2 = ((AssignEC*)fe)->lhs->id;
00944 else {
00945 outputMu.lock();
00946 fe->EError("The function has bad parameter list.");
00947 outputMu.unlock();
00948 return NEW(ErrorVC);
00949 }
00950 bool cacheit = true;
00951 Name eDot = NEW_CONSTR(NameEC, (nameDot, exprs->loc));
00952 Val vDot = eDot->Eval(RestrictContext(c, eDot->freeVars));
00953 DPaths *ps = NEW(DPaths);
00954 while (!work.Null()) {
00955 Assoc a = work.Pop();
00956 Context argsCon(NEW_CONSTR(AssocVC,
00957 (name1, NEW_CONSTR(TextVC, (a->name)))));
00958 Val elem = v2->Extend(a->val, a->name, NormPK, false);
00959 argsCon.Push(NEW_CONSTR(AssocVC, (name2, elem)));
00960 argsCon.Push(NEW_CONSTR(AssocVC, (nameDot, vDot)));
00961
00962 thData->funcCallDepth++;
00963 if (traceRes) {
00964 *traceRes << " " << thData->funcCallDepth << ". "
00965 << fun->func->args->loc->file << ": "
00966 << fun->func->name << "()";
00967 }
00968 elem = ApplicationFromCache(fun, argsCon, exprs->loc);
00969 thData->funcCallDepth--;
00970 if (elem->vKind != BindingVK) {
00971 outputMu.lock();
00972 Error("The function must return a binding.\n", exprs->loc);
00973 outputMu.unlock();
00974 result = NEW(ErrorVC);
00975 return result->MergeDPS(v2->dps)->Merge(elem);
00976 }
00977
00978
00979 Context work = ((BindingVC*)elem)->elems;
00980 while (!work.Null()) {
00981 Assoc as = work.Pop();
00982 if (FindInContext(as->name, elems) != nullAssoc) {
00983 outputMu.lock();
00984 Error("Field name conflicts in binding.\n", exprs->loc);
00985 outputMu.unlock();
00986 result = NEW(ErrorVC);
00987 return result->MergeDPS(ps)->Merge(elem);
00988 }
00989 ps->Merge(elem->dps);
00990 Val asVal = elem->Extend(as->val, as->name, NormPK, false);
00991 elems.Append1D(NEW_CONSTR(AssocVC, (as->name, asVal)));
00992 }
00993 cacheit = cacheit && elem->cacheit;
00994 }
00995 result = NEW_CONSTR(BindingVC, (elems));
00996 result->dps = ps;
00997 result->MergeAndLenDPS(v2);
00998 result->cacheit = cacheit;
00999 return result;
01000 }
01001 case ListVK:
01002 {
01003 Vals work = ((ListVC*)v2)->elems, vals;
01004 switch (v1->vKind) {
01005 case ClosureVK:
01006 {
01007 ClosureVC *fun = (ClosureVC*)v1;
01008 Exprs forms = fun->func->args->elems;
01009 if (forms.size() != 1) {
01010 PrimError("The first argument of _map must be a function of one argument",
01011 v1, exprs->loc);
01012 result = NEW(ErrorVC);
01013 return result->MergeAndTypeDPS(v1);
01014 }
01015 Expr fe = forms.getlo();
01016 Text name;
01017 if (fe->kind == NameEK)
01018 name = ((Name)fe)->id;
01019 else if (fe->kind == AssignEK)
01020 name = ((AssignEC*)fe)->lhs->id;
01021 else {
01022 outputMu.lock();
01023 fe->EError("The function has bad parameter list.");
01024 outputMu.unlock();
01025 return NEW(ErrorVC);
01026 }
01027 bool cacheit = true;
01028 Name eDot = NEW_CONSTR(NameEC, (nameDot, exprs->loc));
01029 Val vDot = eDot->Eval(RestrictContext(c, eDot->freeVars));
01030 int index = 0;
01031 while (!work.Null()) {
01032 Val elem = v2->Extend(work.Pop(), IntArc(index++), NormPK, false);
01033 Context argsCon(NEW_CONSTR(AssocVC, (name, elem)));
01034 argsCon.Push(NEW_CONSTR(AssocVC, (nameDot, vDot)));
01035
01036 thData->funcCallDepth++;
01037 if (traceRes) {
01038 *traceRes << " " << thData->funcCallDepth << ". "
01039 << fun->func->args->loc->file << ": "
01040 << fun->func->name << "()";
01041 }
01042 elem = ApplicationFromCache(fun, argsCon, exprs->loc);
01043 thData->funcCallDepth--;
01044 cacheit = cacheit && elem->cacheit;
01045 vals.Append1D(elem);
01046 }
01047 result = NEW_CONSTR(ListVC, (vals));
01048 result->MergeAndLenDPS(v2);
01049 result->cacheit = cacheit;
01050 break;
01051 }
01052 case ModelVK:
01053 {
01054 ModelVC *fun = (ModelVC*)v1;
01055 bool cacheit = true;
01056 int index = 0;
01057 while (!work.Null()) {
01058 Val elem = v2->Extend(work.Pop(), IntArc(index++), NormPK, false);
01059 Context argsCon(NEW_CONSTR(AssocVC, (nameDot, elem)));
01060 elem = ModelFromCache(fun, argsCon, exprs->loc);
01061 cacheit = cacheit && elem->cacheit;
01062 vals.Append1D(elem);
01063 }
01064 result = NEW_CONSTR(ListVC, (vals));
01065 result->MergeAndLenDPS(v2);
01066 result->cacheit = cacheit;
01067 break;
01068 }
01069 default:
01070 PrimError("The first argument of _map must be either a function or a model",
01071 v1, exprs->loc);
01072 result = NEW(ErrorVC);
01073 return result->MergeAndTypeDPS(v1);
01074 }
01075 return result;
01076 }
01077 default:
01078 PrimError("The second argument of _map must be either a binding or a list",
01079 v2, exprs->loc);
01080 result = NEW(ErrorVC);
01081 return result->MergeAndTypeDPS(v2);
01082 }
01083 }
01084
01085 class EvalWorker {
01086 public:
01087 EvalWorker(Val fun, const Context& args, SrcLoc *loc,
01088 int depth, int stackSize, ThreadData* parent)
01089 : id(-1), fun(fun), argsCon(args), loc(loc), result(NULL),
01090 funcCallDepth(depth), parentCallStackSize(stackSize),
01091 parent(parent), done(false), isWaiting(false) {
01092 if (numThreads < threadAllowed) {
01093 numThreads++;
01094 if (ThreadIds.size() == 0) {
01095 this->id = ThreadIdMax++;
01096 }
01097 else {
01098 this->id = ThreadIds.remhi();
01099 }
01100 }
01101 }
01102 int id;
01103 Val fun;
01104 Context argsCon;
01105 SrcLoc *loc;
01106 Val result;
01107 CacheEntry::IndicesApp orphanCIs;
01108 OBufStream traceRes;
01109 int funcCallDepth;
01110 int parentCallStackSize;
01111 ThreadData *parent;
01112 bool done;
01113 Basics::cond doneCond;
01114 bool isWaiting;
01115 };
01116
01117 typedef Sequence<EvalWorker*> Workers;
01118
01119 static void* DoWork(void *arg) throw () {
01120 EvalWorker *worker = (EvalWorker*)arg;
01121 ThreadData* thdata;
01122 if (worker->id < 0) {
01123 thdata = ThreadDataGet();
01124 }
01125 else {
01126 thdata = ThreadDataCreate(worker->id, &worker->orphanCIs);
01127 thdata->traceRes = &worker->traceRes;
01128 thdata->funcCallDepth = worker->funcCallDepth;
01129 thdata->parentCallStackSize = worker->parentCallStackSize;
01130 thdata->parent = worker->parent;
01131 }
01132 ostream *traceRes = thdata->traceRes;
01133
01134
01135 parMu.lock();
01136 bool failing = parMapFailing;
01137 parMu.unlock();
01138 if (!failing) {
01139 try {
01140 if (worker->fun->vKind == ClosureVK) {
01141 ClosureVC *fun = (ClosureVC*)worker->fun;
01142 thdata->funcCallDepth++;
01143 if (traceRes) {
01144 *traceRes << " " << thdata->funcCallDepth << ". "
01145 << fun->func->args->loc->file << ": "
01146 << fun->func->name << "()";
01147 }
01148 worker->result =
01149 ApplicationFromCache(fun, worker->argsCon, worker->loc);
01150 thdata->funcCallDepth--;
01151 }
01152 else {
01153 assert(worker->fun->vKind == ModelVK);
01154 worker->result =
01155 ModelFromCache((ModelVC*)worker->fun, worker->argsCon, worker->loc);
01156 }
01157 } catch (SRPC::failure f) {
01158 parMu.lock();
01159 if (!parMapFailing) {
01160 outputMu.lock();
01161 Error(Text("_par_map: SRPC failure (") + IntToText(f.r) + "): " + f.msg +
01162 "The evaluation will exit when _par_map finishes.\n",
01163 worker->loc);
01164 PrintErrorStack(&cerr);
01165 outputMu.unlock();
01166 }
01167 parMu.unlock();
01168 } catch (Evaluator::failure f) {
01169 parMu.lock();
01170 if (!parMapFailing) {
01171 outputMu.lock();
01172 Error(Text("_par_map: Vesta evaluation failure; ") +
01173 "The evaluation will exit when _par_map finishes.\n",
01174 worker->loc);
01175 PrintErrorStack(&cerr);
01176 outputMu.unlock();
01177 }
01178 parMu.unlock();
01179 } catch (const char* report) {
01180
01181 parMu.lock();
01182 if (!parMapFailing) {
01183 outputMu.lock();
01184 ErrorDetail(Text(report) +
01185 " The evaluation will exit when _par_map finishes.\n");
01186 PrintErrorStack(&cerr);
01187 outputMu.unlock();
01188 }
01189 parMu.unlock();
01190 }
01191 }
01192
01193
01194 parMu.lock();
01195 worker->done = true;
01196 if (worker->result == NULL) parMapFailing = true;
01197 if (worker->isWaiting) {
01198 numThreads--;
01199 ThreadIds.addhi(worker->id);
01200 worker->doneCond.signal();
01201 }
01202 else if (worker->id >= 0) {
01203 numThreads--;
01204 ThreadIds.addhi(worker->id);
01205 WorkCond.signal();
01206 }
01207 parMu.unlock();
01208 return (void *)NULL;
01209 }
01210
01211 static long WorkerStackSize = 0x20000;
01212
01213 static EvalWorker* StartWorker(Val val, const Context& argsCon, SrcLoc *loc,
01214 ThreadData *thdata, Workers *workers) {
01215 EvalWorker *worker =
01216 NEW_CONSTR(EvalWorker, (val, argsCon, loc, thdata->funcCallDepth,
01217 (recordCallStack ? thdata->callStack->size() : 0), thdata));
01218 workers->addhi(worker);
01219 if (worker->id == -1) return worker;
01220 Basics::thread *th = NEW(Basics::thread);
01221 th->fork_and_detach(DoWork, (void*)worker, WorkerStackSize);
01222 return (EvalWorker *)NULL;
01223 }
01224
01225 static Val FinishWorker(EvalWorker *worker, ThreadData *thdata) {
01226 if (worker->id != -1) {
01227 parMu.lock();
01228 while (!worker->done) {
01229 threadAllowed++;
01230 WorkCond.signal();
01231 worker->isWaiting = true;
01232 worker->doneCond.wait(parMu);
01233 threadAllowed--;
01234 }
01235 parMu.unlock();
01236 for (int i = 0; i < worker->orphanCIs.len; i++) {
01237 thdata->orphanCIs->Append(worker->orphanCIs.index[i]);
01238 }
01239 if (recordTrace) {
01240 *thdata->traceRes << worker->traceRes.str();
01241 }
01242 }
01243 Val elem = worker->result;
01244 return elem;
01245 }
01246
01247 class ParWork {
01248 public:
01249 ParWork(Val func, Val arg, const Text& name1, const Text& name2,
01250 Val vDot, Context bwork, Vals lwork, ThreadData *thdata, SrcLoc *loc)
01251 : func(func), arg(arg), formal1(name1), formal2(name2), vDot(vDot),
01252 bwork(bwork), lwork(lwork), index(0), workers(10),
01253 thdata(thdata), loc(loc), prev(NULL), next(NULL)
01254 { }
01255
01256 Val func;
01257 Val arg;
01258 const Text formal1;
01259 const Text formal2;
01260 Val vDot;
01261 Context bwork;
01262 Vals lwork;
01263 int index;
01264 Workers workers;
01265 ThreadData* thdata;
01266 SrcLoc* loc;
01267 ParWork *prev;
01268 ParWork *next;
01269 };
01270
01271 static ParWork *AvailWorks;
01272
01273 static void AddParWork(ParWork *parWork) {
01274 parWork->prev == NULL;
01275 if (AvailWorks) AvailWorks->prev = parWork;
01276 parWork->next = AvailWorks;
01277 AvailWorks = parWork;
01278 }
01279
01280 static void DeleteParWork(ParWork *parWork) {
01281 if (parWork->prev) {
01282 parWork->prev->next = parWork->next;
01283 }
01284 else {
01285 AvailWorks = parWork->next;
01286 }
01287 if (parWork->next) {
01288 parWork->next->prev = parWork->prev;
01289 }
01290 }
01291
01292 static void* DoAvailWork(void *arg) throw () {
01293 parMu.lock();
01294 while (true) {
01295 waiting:
01296 WorkCond.wait(parMu);
01297 while (numThreads >= threadAllowed) {
01298 WorkCond.wait(parMu);
01299 }
01300 ParWork *parWork = AvailWorks;
01301 while (parWork) {
01302 if (!parWork->bwork.Null()) {
01303 while (!parWork->bwork.Null()) {
01304 Assoc a = parWork->bwork.Pop();
01305 Context argsCon(NEW_CONSTR(AssocVC, (parWork->formal1,
01306 NEW_CONSTR(TextVC, (a->name)))));
01307 Val elem = parWork->arg->Extend(a->val, a->name, NormPK, false);
01308 argsCon.Push((NEW_CONSTR(AssocVC, (parWork->formal2, elem))));
01309 if (parWork->vDot != NULL) {
01310 argsCon.Push(NEW_CONSTR(AssocVC, (nameDot, parWork->vDot)));
01311 }
01312
01313
01314 StartWorker(parWork->func, argsCon, parWork->loc,
01315 parWork->thdata, &parWork->workers);
01316 if (numThreads >= threadAllowed) goto waiting;
01317 }
01318 }
01319 else {
01320 while (!parWork->lwork.Null()) {
01321 Val elem = parWork->arg->Extend(parWork->lwork.Pop(),
01322 IntArc((parWork->index)++),
01323 NormPK, false);
01324 Context argsCon(NEW_CONSTR(AssocVC, (parWork->formal1, elem)));
01325 if (parWork->vDot != NULL) {
01326 argsCon.Push(NEW_CONSTR(AssocVC, (nameDot, parWork->vDot)));
01327 }
01328
01329 StartWorker(parWork->func, argsCon, parWork->loc,
01330 parWork->thdata, &parWork->workers);
01331 if (numThreads >= threadAllowed) goto waiting;
01332 }
01333 }
01334 parWork = parWork->next;
01335 }
01336 }
01337
01338 }
01339
01340 Val ParMap(ArgList exprs, const Context& c) {
01341
01342 if (maxThreads < 2) {
01343
01344 return Map(exprs, c);
01345 }
01346 Vals args = EvalArgs(exprs, c);
01347 if (args.Length() != 2) {
01348 PrimError("_par_map takes two arguments", args, exprs->loc);
01349 return NEW(ErrorVC);
01350 }
01351 ThreadData *thdata = ThreadDataGet();
01352
01353 Val v1 = args.First(), v2 = args.Second(), result;
01354 ParWork *parWork = NULL;
01355 bool parWorkAdded = false;
01356 switch (v2->vKind) {
01357 case BindingVK:
01358 {
01359 Context elems;
01360 if (v1->vKind != ClosureVK) {
01361 PrimError("The first argument of _par_map must be a function",
01362 v1, exprs->loc);
01363 result = NEW(ErrorVC);
01364 return result->MergeAndTypeDPS(v1);
01365 }
01366 ClosureVC *fun = (ClosureVC*)v1;
01367 Exprs forms = fun->func->args->elems;
01368 if (forms.size() != 2) {
01369 PrimError("The first argument of _par_map must be a function of two arguments",
01370 v1, exprs->loc);
01371 result = NEW(ErrorVC);
01372 return result->MergeAndTypeDPS(v1);
01373 }
01374 Text name1, name2;
01375 Expr fe = forms.get(0);
01376 if (fe->kind == NameEK)
01377 name1 = ((Name)fe)->id;
01378 else if (fe->kind == AssignEK)
01379 name1 = ((AssignEC*)fe)->lhs->id;
01380 else {
01381 outputMu.lock();
01382 fe->EError("The function has bad parameter list.");
01383 outputMu.unlock();
01384 return NEW(ErrorVC);
01385 }
01386 fe = forms.get(1);
01387 if (fe->kind == NameEK)
01388 name2 = ((Name)fe)->id;
01389 else if (fe->kind == AssignEK)
01390 name2 = ((AssignEC*)fe)->lhs->id;
01391 else {
01392 outputMu.lock();
01393 fe->EError("The function has bad parameter list.");
01394 outputMu.unlock();
01395 return NEW(ErrorVC);
01396 }
01397 Name eDot = NEW_CONSTR(NameEC, (nameDot, exprs->loc));
01398 Val vDot = eDot->Eval(RestrictContext(c, eDot->freeVars));
01399 Vals none;
01400 parWork = NEW_CONSTR(ParWork, (v1, v2, name1, name2, vDot,
01401 ((BindingVC*)v2)->elems, none,
01402 thdata, exprs->loc));
01403
01404 while (true) {
01405 parMu.lock();
01406 if(parWork->bwork.Null()) {
01407 parMu.unlock();
01408 break;
01409 }
01410 Assoc a = parWork->bwork.Pop();
01411 Context argsCon(NEW_CONSTR(AssocVC,
01412 (name1, NEW_CONSTR(TextVC, (a->name)))));
01413 Val elem = v2->Extend(a->val, a->name, NormPK, false);
01414 argsCon.Push(NEW_CONSTR(AssocVC, (name2, elem)));
01415 argsCon.Push(NEW_CONSTR(AssocVC, (nameDot, vDot)));
01416
01417 EvalWorker *worker = StartWorker(v1, argsCon, exprs->loc,
01418 thdata, &parWork->workers);
01419 if (worker != NULL && !parWorkAdded) {
01420 AddParWork(parWork);
01421 parWorkAdded = true;
01422 }
01423 parMu.unlock();
01424 if (worker != NULL) DoWork((void*)worker);
01425 }
01426
01427 bool cacheit = true;
01428 DPaths *ps = NEW(DPaths);
01429 for (int i = 0; i < parWork->workers.size(); i++) {
01430 Val elem = FinishWorker(parWork->workers.get(i), thdata);
01431 if(elem == NULL) {
01432 if(!parMapFailing)
01433 parMapFailing = true;
01434 continue;
01435 }
01436 if(elem->vKind != BindingVK) {
01437 outputMu.lock();
01438 Error("The function must return a binding.\n", exprs->loc);
01439 outputMu.unlock();
01440 if(!parMapFailing)
01441 parMapFailing = true;
01442 continue;
01443 }
01444
01445
01446 Context work = ((BindingVC*)elem)->elems;
01447 while (!work.Null()) {
01448 Assoc as = work.Pop();
01449 if (FindInContext(as->name, elems) != nullAssoc) {
01450 outputMu.lock();
01451 Error("Field name conflicts in binding.\n", exprs->loc);
01452 outputMu.unlock();
01453 if(!parMapFailing)
01454 parMapFailing = true;
01455 break;
01456 }
01457 ps->Merge(elem->dps);
01458 Val asVal = elem->Extend(as->val, as->name, NormPK, false);
01459 elems.Append1D(NEW_CONSTR(AssocVC, (as->name, asVal)));
01460 }
01461 cacheit = cacheit && elem->cacheit;
01462 }
01463 result = NEW_CONSTR(BindingVC, (elems));
01464 result->dps = ps;
01465 result->MergeAndLenDPS(v2);
01466 result->cacheit = cacheit;
01467
01468 if(parWorkAdded) {
01469 parMu.lock();
01470 DeleteParWork(parWork);
01471 parMu.unlock();
01472 }
01473 break;
01474 }
01475 case ListVK:
01476 {
01477 Vals vals;
01478 switch (v1->vKind) {
01479 case ClosureVK:
01480 {
01481 ClosureVC *fun = (ClosureVC*)v1;
01482 Exprs forms = fun->func->args->elems;
01483 if (forms.size() != 1) {
01484 PrimError("The first argument of _par_map must be a function of one argument",
01485 v1, exprs->loc);
01486 result = NEW(ErrorVC);
01487 return result->MergeAndTypeDPS(v1);
01488 }
01489 Expr fe = forms.getlo();
01490 Text name;
01491 if (fe->kind == NameEK)
01492 name = ((Name)fe)->id;
01493 else if (fe->kind == AssignEK)
01494 name = ((AssignEC*)fe)->lhs->id;
01495 else {
01496 outputMu.lock();
01497 fe->EError("The function has bad parameter list.");
01498 outputMu.unlock();
01499 return NEW(ErrorVC);
01500 }
01501 Name eDot = NEW_CONSTR(NameEC, (nameDot, exprs->loc));
01502 Val vDot = eDot->Eval(RestrictContext(c, eDot->freeVars));
01503 Context none;
01504 parWork = NEW_CONSTR(ParWork, (v1, v2, name, Text(""), vDot, none,
01505 ((ListVC*)v2)->elems, thdata, exprs->loc));
01506
01507 while (true) {
01508 parMu.lock();
01509 if (parWork->lwork.Null()) {
01510 parMu.unlock();
01511 break;
01512 }
01513 Val elem = v2->Extend(parWork->lwork.Pop(), IntArc(parWork->index++),
01514 NormPK, false);
01515 Context argsCon(NEW_CONSTR(AssocVC, (name, elem)));
01516 argsCon.Push(NEW_CONSTR(AssocVC, (nameDot, vDot)));
01517
01518 EvalWorker *worker = StartWorker(v1, argsCon, exprs->loc,
01519 thdata, &parWork->workers);
01520 if (worker != NULL && !parWorkAdded) {
01521 AddParWork(parWork);
01522 parWorkAdded = true;
01523 }
01524 parMu.unlock();
01525 if (worker != NULL) DoWork((void*)worker);
01526 }
01527 bool cacheit = true;
01528 for (int i = 0; i < parWork->workers.size(); i++) {
01529 Val elem = FinishWorker(parWork->workers.get(i), thdata);
01530 if(elem == NULL) {
01531 if(!parMapFailing)
01532 parMapFailing = true;
01533 continue;
01534 }
01535 cacheit = cacheit && elem->cacheit;
01536 vals.Append1D(elem);
01537 }
01538 result = NEW_CONSTR(ListVC, (vals));
01539 result->MergeAndLenDPS(v2);
01540 result->cacheit = cacheit;
01541 break;
01542 }
01543 case ModelVK:
01544 {
01545 ModelVC *fun = (ModelVC*)v1;
01546
01547 Context none;
01548 parWork = NEW_CONSTR(ParWork, (v1, v2, nameDot, Text(""), NULL, none,
01549 ((ListVC*)v2)->elems, thdata, exprs->loc));
01550 while (true) {
01551 parMu.lock();
01552 if (parWork->lwork.Null()) {
01553 parMu.unlock();
01554 break;
01555 }
01556 Val elem = v2->Extend(parWork->lwork.Pop(), IntArc(parWork->index++),
01557 NormPK, false);
01558 Context argsCon(NEW_CONSTR(AssocVC, (nameDot, elem)));
01559 EvalWorker *worker = StartWorker(v1, argsCon, exprs->loc,
01560 thdata, &parWork->workers);
01561 if (worker != NULL && !parWorkAdded) {
01562 AddParWork(parWork);
01563 parWorkAdded = true;
01564 }
01565 parMu.unlock();
01566 if (worker != NULL) DoWork((void*)worker);
01567 }
01568 bool cacheit = true;
01569 for (int i = 0; i < parWork->workers.size(); i++) {
01570 Val elem = FinishWorker(parWork->workers.get(i), thdata);
01571 if(elem == NULL) {
01572 if(!parMapFailing)
01573 parMapFailing = true;
01574 continue;
01575 }
01576 cacheit = cacheit && elem->cacheit;
01577 vals.Append1D(elem);
01578 }
01579 result = NEW_CONSTR(ListVC, (vals));
01580 result->MergeAndLenDPS(v2);
01581 result->cacheit = cacheit;
01582 break;
01583 }
01584 default:
01585 PrimError("The first argument of _par_map must be either a function or a model",
01586 v1, exprs->loc);
01587 result = NEW(ErrorVC);
01588 return result->MergeAndTypeDPS(v1);
01589 }
01590
01591 if (parWorkAdded) {
01592 parMu.lock();
01593 DeleteParWork(parWork);
01594 parMu.unlock();
01595 }
01596 break;
01597 }
01598 default:
01599 PrimError("The second argument of _par_map must be either a binding or a list",
01600 v2, exprs->loc);
01601 result = NEW(ErrorVC);
01602 return result->MergeAndTypeDPS(v2);
01603 }
01604
01605 if(parMapFailing) {
01606
01607 return NEW(ErrorVC);
01608 }
01609 return result;
01610 }
01611
01612 Val Max(ArgList exprs, const Context& c) {
01613 Vals args = EvalArgs(exprs, c);
01614 if (args.Length() != 2) {
01615 PrimError("_max takes two arguments", args, exprs->loc);
01616 return NEW(ErrorVC);
01617 }
01618 Val v1 = args.First(), v2 = args.Second(), result;
01619 if (v1->vKind != IntegerVK) {
01620 PrimError("First argument of _max must be integer", v1, exprs->loc);
01621 result = NEW(ErrorVC);
01622 return result->MergeAndTypeDPS(v1);
01623 }
01624 if (v2->vKind != IntegerVK) {
01625 PrimError("Second argument of _max must be integer", v2, exprs->loc);
01626 result = NEW(ErrorVC);
01627 return result->MergeAndTypeDPS(v2);
01628 }
01629 if (((IntegerVC*)v1)->num > ((IntegerVC*)v2)->num)
01630 result = v1->Merge(v2);
01631 else
01632 result = v2->Merge(v1);
01633 result->cacheit = v1->cacheit && v2->cacheit;
01634 return result;
01635 }
01636
01637 Val Min(ArgList exprs, const Context& c) {
01638 Vals args = EvalArgs(exprs, c);
01639 if (args.Length() != 2) {
01640 PrimError("_min takes two arguments", args, exprs->loc);
01641 return NEW(ErrorVC);
01642 }
01643 Val v1 = args.First(), v2 = args.Second(), result;
01644 if (v1->vKind != IntegerVK) {
01645 PrimError("First argument of _min must be integer", v1, exprs->loc);
01646 result = NEW(ErrorVC);
01647 return result->MergeAndTypeDPS(v1);
01648 }
01649 if (v2->vKind != IntegerVK) {
01650 PrimError("Second argument of _min must be integer", v2, exprs->loc);
01651 result = NEW(ErrorVC);
01652 return result->MergeAndTypeDPS(v2);
01653 }
01654 if (((IntegerVC*)v1)->num > ((IntegerVC*)v2)->num)
01655 result = v2->Merge(v1);
01656 else
01657 result = v1->Merge(v2);
01658 result->cacheit = v1->cacheit && v2->cacheit;
01659 return result;
01660 }
01661
01662 Val Mod(ArgList exprs, const Context& ctxt) {
01663 Vals args = EvalArgs(exprs, ctxt);
01664 if (args.Length() != 2) {
01665 PrimError("_mod takes two arguments", args, exprs->loc);
01666 return NEW(ErrorVC);
01667 }
01668 Val v1 = args.First(), v2 = args.Second(), result;
01669 if (v1->vKind != IntegerVK) {
01670 PrimError("First argument of _mod must be integer", v1, exprs->loc);
01671 result = NEW(ErrorVC);
01672 return result->MergeAndTypeDPS(v1);
01673 }
01674 if (v2->vKind != IntegerVK) {
01675 PrimError("Second argument of _mod must be integer", v2, exprs->loc);
01676 result = NEW(ErrorVC);
01677 return result->MergeAndTypeDPS(v2);
01678 }
01679 Basics::int32 a = ((IntegerVC*)v1)->num;
01680 Basics::int32 b = ((IntegerVC*)v2)->num;
01681 if (b == 0) {
01682 PrimError("Attempt to divide by 0 with _mod", args, exprs->loc);
01683 result = NEW(ErrorVC);
01684 return result->Merge(v2);
01685 }
01686
01687 Basics::int32 c;
01688 if ((a == 0) && (b != 0)) { c = 0;
01689 } else if (a > 0) { c = (b >= 0) ? a % b : b + 1 + (a-1) % (-b);
01690 } else { c = (b >= 0) ? b - 1 - (-1-a) % (b) : - ((-a) % (-b));
01691 }
01692 result = NEW_CONSTR(IntegerVC, (c));
01693 result->cacheit = v1->cacheit && v2->cacheit;
01694 return result->Merge(v1)->Merge(v2);
01695 }
01696
01697 Val GetName(ArgList exprs, const Context& c) {
01698 Vals args = EvalArgs(exprs, c);
01699 if (args.Length() != 1) {
01700 PrimError("_n takes one argument", args, exprs->loc);
01701 return NEW(ErrorVC);
01702 }
01703 Val v = args.First(), result;
01704 if (v->vKind != BindingVK) {
01705 PrimError("_n's argument must be a binding", v, exprs->loc);
01706 result = NEW(ErrorVC);
01707 return result->MergeAndTypeDPS(v);
01708 }
01709 int len = ((BindingVC*)v)->elems.Length();
01710 if (len != 1) {
01711 PrimError("_n's argument must be a singleton binding", v, exprs->loc);
01712 result = NEW(ErrorVC);
01713 return result->MergeAndLenDPS(v);
01714 }
01715 Text name(((BindingVC*)v)->elems.First()->name);
01716 result = NEW_CONSTR(TextVC, (name));
01717 result->cacheit = v->cacheit;
01718 return result->MergeAndLenDPS(v);
01719 }
01720
01721 Val GetValue(ArgList exprs, const Context& c) {
01722 Vals args = EvalArgs(exprs, c);
01723 if (args.Length() != 1) {
01724 PrimError("_v takes one argument", args, exprs->loc);
01725 return NEW(ErrorVC);
01726 }
01727 Val v = args.First(), result;
01728 if (v->vKind != BindingVK) {
01729 PrimError("_v's argument must be a binding", v, exprs->loc);
01730 result = NEW(ErrorVC);
01731 return result->MergeAndTypeDPS(v);
01732 }
01733 if (((BindingVC*)v)->elems.Length() != 1) {
01734 PrimError("_v's argument must be a binding", v, exprs->loc);
01735 result = NEW(ErrorVC);
01736 return result->MergeAndLenDPS(v);
01737 }
01738 Text name;
01739 result = ((BindingVC*)v)->GetElem(0, name);
01740 return result;
01741 }
01742
01743 Val Sub(ArgList exprs, const Context& c) {
01744 Vals args = EvalArgs(exprs, c);
01745 Basics::int32 start = 0;
01746 Basics::int32 len = Text::MaxInt;
01747 Val v1, v2 = valZero, v3 = valZero, result;
01748 int argsLen = args.Length();
01749 switch (argsLen) {
01750 case 3:
01751 v3 = args.Third();
01752 if (v3->vKind != IntegerVK) {
01753 PrimError("Third argument of _sub must be an integer", v3, exprs->loc);
01754 result = NEW(ErrorVC);
01755 return result->MergeAndTypeDPS(v3);
01756 }
01757 len = ((IntegerVC*)v3)->num;
01758 if (len < 0) len = 0;
01759 if (len > Text::MaxInt) {
01760 PrimError("(impl) _sub integer argument too big", v3, exprs->loc);
01761 result = NEW(ErrorVC);
01762 return result->Merge(v3);
01763 }
01764
01765 case 2:
01766 v2 = args.Second();
01767 if (v2->vKind != IntegerVK) {
01768 PrimError("Second argument of _sub must be an integer", v2, exprs->loc);
01769 result = NEW(ErrorVC);
01770 return result->MergeAndTypeDPS(v2);
01771 }
01772 start = ((IntegerVC*)v2)->num;
01773 if (start < 0) start = 0;
01774 if (start > Text::MaxInt) {
01775 PrimError("(impl) _sub integer argument too big", v2, exprs->loc);
01776 result = NEW(ErrorVC);
01777 return result->Merge(v2);
01778 }
01779
01780 case 1:
01781 v1 = args.First();
01782 if (v1->vKind == TextVK) {
01783 Text txt(((TextVC*)v1)->NDS());
01784 bool toFile = (!((TextVC*)v1)->HasTxt()) && (len > 128);
01785 if (toFile) {
01786 FP::Tag fp(v1->FingerPrint());
01787 if (argsLen > 1)
01788 fp.Extend(v2->FingerPrint());
01789 if (argsLen > 2)
01790 fp.Extend(v3->FingerPrint());
01791 result = NEW_CONSTR(TextVC, (noName, txt.Sub(start, len), '-', fp));
01792 }
01793 else {
01794 result = NEW_CONSTR(TextVC, (txt.Sub(start, len)));
01795 }
01796 result->Merge(v1)->Merge(v2)->Merge(v3);
01797 }
01798 else if (v1->vKind == BindingVK) {
01799 Context work = ((BindingVC*)v1)->elems;
01800 while (!work.Null() && (start-- > 0)) work.Pop();
01801 Context rElems;
01802 while (!work.Null() && (len-- > 0)) {
01803 Assoc a = work.Pop();
01804 Val v11 = v1->Extend(a->val, a->name, NormPK, false);
01805 rElems.Append1D(NEW_CONSTR(AssocVC, (a->name, v11)));
01806 }
01807 result = NEW_CONSTR(BindingVC, (rElems));
01808
01809 if (v1->path == NULL)
01810 ((BindingVC*)result)->lenDps = ((BindingVC*)v1)->lenDps;
01811 else
01812 ((BindingVC*)result)->AddToLenDPS(*v1->path, v1);
01813 result->MergeAndLenDPS(v1);
01814 result->Merge(v2)->Merge(v3);
01815 }
01816 else if (v1->vKind == ListVK) {
01817 Vals work = ((ListVC*)v1)->elems;
01818 Basics::int32 cnt = start;
01819 while (!work.Null() && (start-- > 0)) work.Pop();
01820 Vals rElems;
01821 while (!work.Null() && (len-- > 0)) {
01822 Val v11 = v1->Extend(work.Pop(), IntArc(cnt++), NormPK, false);
01823 rElems.Append1D(v11);
01824 }
01825 result = NEW_CONSTR(ListVC, (rElems));
01826
01827 if (v1->path == NULL)
01828 ((ListVC*)result)->lenDps = ((ListVC*)v1)->lenDps;
01829 else
01830 ((ListVC*)result)->AddToLenDPS(*v1->path, v1);
01831 result->MergeAndLenDPS(v1);
01832 result->Merge(v2)->Merge(v3);
01833 }
01834 else {
01835 PrimError("First argument of _sub must be a text, binding, or list", v1, exprs->loc);
01836 result = NEW(ErrorVC);
01837 return result->MergeAndTypeDPS(v1);
01838 }
01839 break;
01840 default:
01841 PrimError("_sub takes one to three arguments", args, exprs->loc);
01842 return NEW(ErrorVC);
01843 }
01844 result->cacheit = v1->cacheit && v2->cacheit && v3->cacheit;
01845 return result;
01846 }
01847
01848
01849 Val Print(ArgList exprs, const Context& c) {
01850 Vals args = EvalArgs(exprs, c);
01851 Val v1, v2, v3;
01852 bool verbose = false;
01853
01854 switch (args.Length()) {
01855 case 3:
01856 v3 = args.Third();
01857 if (v3->vKind != BooleanVK) {
01858 PrimError("Third argument of _print must be a boolean.", v3, exprs->loc);
01859 return args.First();
01860 }
01861 verbose = ((BooleanVC*)v3)->b;
01862
01863 case 2:
01864 v1 = args.First();
01865 v2 = args.Second();
01866 if (v2->vKind != IntegerVK) {
01867 PrimError("Second argument of _print must be an integer.", v2, exprs->loc);
01868 return v1;
01869 }
01870 outputMu.lock();
01871 switch (((IntegerVC*)v2)->num) {
01872 case 0:
01873 v1->PrintD(&cout, verbose);
01874 cout << "\n";
01875 break;
01876 case 1:
01877 cout << "The value is: ";
01878 v1->PrintD(&cout, verbose);
01879 cout << "\nAnd the dependency is:\n";
01880 PrintDpnd(&cout, v1);
01881 cout << "\n";
01882 break;
01883 default:
01884 cout << "The value is: ";
01885 v1->PrintD(&cout, verbose);
01886 cout << "\nAnd the dependency is:\n";
01887 PrintAllDpnd(&cout, v1);
01888 cout << "\n";
01889 break;
01890 }
01891 outputMu.unlock();
01892 break;
01893 case 1:
01894 outputMu.lock();
01895 v1 = args.First();
01896 v1->PrintD(&cout);
01897 cout << "\n";
01898 outputMu.unlock();
01899 break;
01900 default:
01901 PrimError("_print takes one or two or three arguments.", args, exprs->loc);
01902 return NEW(ErrorVC);
01903 }
01904 cout.flush();
01905 return v1;
01906 }
01907
01908 Val ModelName(ArgList exprs, const Context& c) {
01909 Vals args = EvalArgs(exprs, c);
01910 if (args.Length() != 1) {
01911 PrimError("_model_name takes one argument", args, exprs->loc);
01912 return NEW(ErrorVC);
01913 }
01914 Val result;
01915 Val v = args.First();
01916 if (v->vKind != ModelVK) {
01917 PrimError("_model_name's argument must be a model", v, exprs->loc);
01918 return NEW(ErrorVC);
01919 }
01920 result = NEW_CONSTR(TextVC, (((ModelVC*)v)->content->name));
01921 result->cacheit = v->cacheit;
01922 return result->Merge(v);
01923 }
01924
01925 Val GetFP(ArgList exprs, const Context& c) {
01926 Vals args = EvalArgs(exprs, c);
01927 if (args.Length() != 1) {
01928 PrimError("_fingerprint takes one argument", args, exprs->loc);
01929 return NEW(ErrorVC);
01930 }
01931 Val result;
01932 Val v = args.First();
01933
01934 int i;
01935 unsigned char fpbytes[FP::ByteCnt];
01936 v->FingerPrint().ToBytes(fpbytes);
01937 char buf[FP::ByteCnt*2+1];
01938 OBufStream fp(buf, sizeof(buf));
01939 fp << hex;
01940 for (i=0; i<FP::ByteCnt; i++) {
01941 fp << setw(2) << setfill('0') << (int) fpbytes[i];
01942 }
01943 result = NEW_CONSTR(TextVC, (Text(fp.str())));
01944 result->cacheit = v->cacheit;
01945 return result->Merge(v);
01946 }
01947
01949 static Table<Text,PrimOp>::Default PrimitiveOps(64);
01950
01951 void AddPrimitiveOp(const Text& name, PrimOp op) {
01952 if (PrimitiveOps.Put(name, op)) {
01953 outputMu.lock();
01954 Error("(impl) Name conflict in PrimitiveOps! `" + name + "'.\n");
01955 outputMu.unlock();
01956 }
01957 }
01958
01959 PrimOp LookupOp(const Text& opid) {
01960 PrimOp result;
01961 return PrimitiveOps.Get(opid, result) ? result : NULL;
01962 }
01963
01964 static Table<Text,PrimUnOp>::Default PrimitiveUnOps(8);
01965
01966 void AddPrimitiveUnOp(const Text& name, PrimUnOp op) {
01967 if (PrimitiveUnOps.Put(name, op)) {
01968 outputMu.lock();
01969 Error("(impl) Name conflict in PrimitiveUnOps! `" + name + "'.\n");
01970 outputMu.unlock();
01971 }
01972 }
01973
01974 PrimUnOp LookupUnOp(const Text& opid) {
01975 PrimUnOp result;
01976 return PrimitiveUnOps.Get(opid, result) ? result : NULL;
01977 }
01978
01979 Val Plus(Expr e1, Expr e2, const Context& c) {
01980 Val v1 = e1->Eval(c), v2 = e2->Eval(c);
01981 Val result;
01982
01983 if (v1->vKind != v2->vKind) {
01984 PrimError("`+' not implemented for these args", v1, v2, e1->loc);
01985 result = NEW(ErrorVC);
01986 return result->MergeAndTypeDPS(v1)->MergeAndTypeDPS(v2);
01987 }
01988 switch (v1->vKind) {
01989 case IntegerVK:
01990 {
01991 Basics::int32 n1 = ((IntegerVC*)v1)->num;
01992 Basics::int32 n2 = ((IntegerVC*)v2)->num;
01993 Basics::int32 res = n1 + n2;
01994 if ((n1 < 0) == (n2 < 0) && (n2 < 0) != (res < 0)) {
01995 PrimError("Overflow on `+'", v1, v2, e1->loc);
01996 result = NEW(ErrorVC);
01997 return result->Merge(v1)->Merge(v2);
01998 }
01999 result = NEW_CONSTR(IntegerVC, (res));
02000 result->cacheit = v1->cacheit && v2->cacheit;
02001 return result->Merge(v1)->Merge(v2);
02002 }
02003 case ListVK:
02004 if (IsEmptyList(v2)) {
02005 v1->cacheit = v1->cacheit && v2->cacheit;
02006 return v1->MergeAndLenDPS(v2);
02007 }
02008 if (IsEmptyList(v1)) {
02009 v2->cacheit = v2->cacheit && v1->cacheit;
02010 return v2->MergeAndLenDPS(v1);
02011 }
02012 return ListAppend((ListVC*)v1, (ListVC*)v2);
02013 case BindingVK:
02014 if (IsEmptyBinding(v2)) {
02015 v1->cacheit = v1->cacheit && v2->cacheit;
02016 return v1->MergeAndLenDPS(v2);
02017 }
02018 if (IsEmptyBinding(v1)) {
02019 v2->cacheit = v1->cacheit && v2->cacheit;
02020 return v2->MergeAndLenDPS(v1);
02021 }
02022 result = NEW_CONSTR(BindingVC, ((BindingVC*)v1, (BindingVC*)v2, false));
02023 return result->MergeAndTypeDPS(v1)->MergeAndTypeDPS(v2);
02024 case TextVK:
02025 {
02026 bool toFile = ((TextVC*)v1)->HasSid() || ((TextVC*)v2)->HasSid();
02027 if (toFile) {
02028 FP::Tag fp(v1->FingerPrint());
02029 fp.Extend(v2->FingerPrint());
02030 result = NEW_CONSTR(TextVC, (noName, ((TextVC*)v1)->NDS() +
02031 ((TextVC*)v2)->NDS(), '+', fp));
02032 }
02033 else {
02034 result = NEW_CONSTR(TextVC, (((TextVC*)v1)->NDS() + ((TextVC*)v2)->NDS()));
02035 }
02036 result->cacheit = v1->cacheit && v2->cacheit;
02037 return result->Merge(v1)->Merge(v2);
02038 }
02039 default:
02040 PrimError("`+' not implemented for these args", v1, v2, e1->loc);
02041 result = NEW(ErrorVC);
02042 return result->MergeAndTypeDPS(v1)->MergeAndTypeDPS(v2);
02043 }
02044 }
02045
02046 Val PlusPlus(Expr e1, Expr e2, const Context& c) {
02047 Val v1 = e1->Eval(c), v2 = e2->Eval(c);
02048 Val result;
02049
02050 if (v1->vKind != BindingVK) {
02051 PrimError("`++' not implemented for non-binding", v1, e1->loc);
02052 result = NEW(ErrorVC);
02053 return result->MergeAndTypeDPS(v1);
02054 }
02055 if (v2->vKind != BindingVK) {
02056 PrimError("`++' not implemented for non-binding", v2, e2->loc);
02057 result = NEW(ErrorVC);
02058 return result->MergeAndTypeDPS(v2);
02059 }
02060 if (IsEmptyBinding(v2)) {
02061 v1->cacheit = v1->cacheit && v2->cacheit;
02062 return v1->MergeAndLenDPS(v2);
02063 }
02064 if (IsEmptyBinding(v1)) {
02065 v2->cacheit = v2->cacheit && v1->cacheit;
02066 return v2->MergeAndLenDPS(v1);
02067 }
02068 result = NEW_CONSTR(BindingVC, ((BindingVC*)v1, (BindingVC*)v2, true));
02069 return result->MergeAndTypeDPS(v1)->MergeAndTypeDPS(v2);
02070 }
02071
02072 Val EqualVal(Val v1, Val v2, SrcLoc *loc) {
02073 Val test, result;
02074 bool b;
02075
02076 if (v1->vKind == v2->vKind) {
02077 switch (v1->vKind) {
02078 case BooleanVK:
02079 b = (((BooleanVC*)v1)->b == ((BooleanVC*)v2)->b);
02080 result = NEW_CONSTR(BooleanVC, (b));
02081 result->cacheit = v1->cacheit && v2->cacheit;
02082 return result->Merge(v1)->Merge(v2);
02083 case IntegerVK:
02084 b = (((IntegerVC*)v1)->num == ((IntegerVC*)v2)->num);
02085 result = NEW_CONSTR(BooleanVC, (b));
02086 result->cacheit = v1->cacheit && v2->cacheit;
02087 return result->Merge(v1)->Merge(v2);
02088 case TextVK:
02089 b = (((TextVC*)v1)->NDS() == ((TextVC*)v2)->NDS());
02090 result = NEW_CONSTR(BooleanVC, (b));
02091 result->cacheit = v1->cacheit && v2->cacheit;
02092 return result->Merge(v1)->Merge(v2);
02093 case ListVK:
02094 {
02095 if (IsEmptyList(v1) && IsEmptyList(v2)) {
02096 result = NEW_CONSTR(BooleanVC, (true));
02097 result->cacheit = v1->cacheit && v2->cacheit;
02098 return result->MergeAndLenDPS(v1)->MergeAndLenDPS(v2);
02099 }
02100 Vals l1 = ((ListVC*)v1)->elems, l2 = ((ListVC*)v2)->elems;
02101 int len1 = l1.Length(), len2 = l2.Length();
02102 if (len1 != len2) {
02103 result = NEW_CONSTR(BooleanVC, (false));
02104 result->cacheit = v1->cacheit && v2->cacheit;
02105 return result->MergeAndLenDPS(v1)->MergeAndLenDPS(v2);
02106 }
02107 Val vv1, vv2;
02108 result = NEW_CONSTR(BooleanVC, (true));
02109 unsigned int l_elem = 0;
02110 while (!l1.Null()) {
02111 vv1 = v1->Extend(l1.Pop(), IntArc(l_elem), NormPK, false);
02112 vv2 = v2->Extend(l2.Pop(), IntArc(l_elem), NormPK, false);
02113 l_elem++;
02114 test = EqualVal(vv1, vv2, loc);
02115 if (IsValFalse(test)) {
02116 test->cacheit = test->cacheit && v1->cacheit && v2->cacheit;
02117 return test->MergeAndLenDPS(v1)->MergeAndLenDPS(v2);
02118 }
02119 result->Merge(test);
02120 result->cacheit = result->cacheit && test->cacheit;
02121 }
02122 result->MergeAndLenDPS(v1)->MergeAndLenDPS(v2);
02123 result->cacheit = result->cacheit && v1->cacheit && v2->cacheit;
02124 return result;
02125 }
02126 case BindingVK:
02127 {
02128 if (IsEmptyBinding(v1) & IsEmptyBinding(v2)) {
02129 result = NEW_CONSTR(BooleanVC, (true));
02130 result->cacheit = v1->cacheit && v2->cacheit;
02131 return result->MergeAndLenDPS(v1)->MergeAndLenDPS(v2);
02132 }
02133 Binding b1 = (BindingVC*)v1, b2 = (BindingVC*)v2;
02134 Context c1 = b1->elems, c2 = b2->elems;
02135 int len1 = c1.Length(), len2 = c2.Length();
02136 if (len1 != len2) {
02137 result = NEW_CONSTR(BooleanVC, (false));
02138 result->cacheit = b1->cacheit && b2->cacheit;
02139 return result->MergeAndLenDPS(b1)->MergeAndLenDPS(b2);
02140 }
02141 Val vv1, vv2;
02142 Assoc a1, a2;
02143 result = NEW_CONSTR(BooleanVC, (true));
02144 unsigned int l_elem = 0;
02145 while (!c1.Null()) {
02146 a1 = c1.Pop();
02147 a2 = c2.Pop();
02148 if (a1->name != a2->name) {
02149 result = NEW_CONSTR(BooleanVC, (false));
02150 result->cacheit = b1->cacheit && b2->cacheit;
02151 return result->MergeAndLenDPS(b1)->MergeAndLenDPS(b2);
02152 }
02153 vv1 = v1->Extend(a1->val, IntArc(l_elem), NormPK, false);
02154 vv2 = v2->Extend(a2->val, IntArc(l_elem), NormPK, false);
02155 l_elem++;
02156 test = EqualVal(vv1, vv2, loc);
02157 if (IsValFalse(test)) {
02158 test->cacheit = test->cacheit && b1->cacheit && b2->cacheit;
02159 return test->MergeAndLenDPS(b1)->MergeAndLenDPS(b2);
02160 }
02161 result->Merge(test);
02162 result->cacheit = result->cacheit && test->cacheit;
02163 }
02164 result->MergeAndLenDPS(v1)->MergeAndLenDPS(v2);
02165 result->cacheit = result->cacheit && b1->cacheit && b2->cacheit;
02166 return result;
02167 }
02168 case ErrorVK:
02169 result = NEW_CONSTR(BooleanVC, (true));
02170 result->cacheit = v1->cacheit && v2->cacheit;
02171 return result->Merge(v1)->Merge(v2);
02172 default:
02173 PrimError("(impl) `==' not implemented for these args", v1, v2, loc);
02174 result = NEW(ErrorVC);
02175 return result->Merge(v1)->Merge(v2);
02176 }
02177 }
02178 result = NEW_CONSTR(BooleanVC, (false));
02179 result->cacheit = v1->cacheit && v2->cacheit;
02180 return result->MergeAndTypeDPS(v1)->MergeAndTypeDPS(v2);
02181 }
02182
02183 Val Equal(Expr e1, Expr e2, const Context& c) {
02184
02185 return EqualVal(e1->Eval(c), e2->Eval(c), e1->loc);
02186 }
02187
02188 Val Not(Expr e, const Context& c) {
02189 Val v1 = e->Eval(c);
02190 Val result;
02191
02192 if (v1->vKind != BooleanVK) {
02193 PrimError("Argument of unary `!' must be a boolean.", v1, e->loc);
02194 result = NEW(ErrorVC);
02195 return result->MergeAndTypeDPS(v1);
02196 }
02197 result = NEW_CONSTR(BooleanVC, (!(((BooleanVC*)v1)->b)));
02198 result->cacheit = v1->cacheit;
02199 return result->Merge(v1);
02200 }
02201
02202 Val Neg(Expr e, const Context& c) {
02203 Val v1 = e->Eval(c);
02204 Val result;
02205
02206 if (v1->vKind != IntegerVK) {
02207 PrimError("Argument of unary `-' must be an integer.", v1, e->loc);
02208 result = NEW(ErrorVC);
02209 return result->MergeAndTypeDPS(v1);
02210 }
02211 Basics::int32 n = ((IntegerVC*)v1)->num;
02212 if (n != 0 && n == -n) {
02213 PrimError("Overflow on unary `-'.", v1, e->loc);
02214 result = NEW(ErrorVC);
02215 return result->Merge(v1);
02216 }
02217 result = NEW_CONSTR(IntegerVC, (-n));
02218 result->cacheit = v1->cacheit;
02219 return result->Merge(v1);
02220 }
02221
02222 Val And(Expr e1, Expr e2, const Context& c) {
02223 Val v1 = e1->Eval(c);
02224 if (v1->vKind != BooleanVK) {
02225 PrimError("First argument of `&&' must be boolean.", v1, e1->loc);
02226 Val result = NEW(ErrorVC);
02227 return result->MergeAndTypeDPS(v1);
02228 }
02229 if (IsValFalse(v1)) return v1;
02230 Val v2 = e2->Eval(c);
02231 if (v2->vKind != BooleanVK) {
02232 PrimError("Second Argument of `&&' must be boolean.", v2, e2->loc);
02233 Val result = NEW(ErrorVC);
02234 return result->Merge(v1)->MergeAndTypeDPS(v2);
02235 }
02236 v2->cacheit = v2->cacheit && v1->cacheit;
02237 return v2->Merge(v1);
02238 }
02239
02240 Val Or(Expr e1, Expr e2, const Context& c) {
02241 Val v1 = e1->Eval(c);
02242 if (v1->vKind != BooleanVK) {
02243 outputMu.lock();
02244 Error("First argument of `||' must be boolean. \n");
02245 outputMu.unlock();
02246 Val result = NEW(ErrorVC);
02247 return result->MergeAndTypeDPS(v1);
02248 }
02249 if (IsValTrue(v1)) return v1;
02250 Val v2 = e2->Eval(c);
02251 if (v2->vKind != BooleanVK) {
02252 outputMu.lock();
02253 Error("Second argument of `||' must be boolean. \n");
02254 outputMu.unlock();
02255 Val result = NEW(ErrorVC);
02256 return result->Merge(v1)->MergeAndTypeDPS(v2);
02257 }
02258 v2->cacheit = v2->cacheit && v1->cacheit;
02259 return v2->Merge(v1);
02260 }
02261
02262 Val Implies(Expr e1, Expr e2, const Context& c) {
02263 Val v1 = e1->Eval(c);
02264 if (v1->vKind != BooleanVK) {
02265 PrimError("First argument of `=>' must be boolean.", v1, e1->loc);
02266 Val result = NEW(ErrorVC);
02267 return result->MergeAndTypeDPS(v1);
02268 }
02269 if (IsValFalse(v1)) {
02270 Val result = NEW_CONSTR(BooleanVC, (true));
02271 result->cacheit = v1->cacheit;
02272 return result->Merge(v1);
02273 }
02274 Val v2 = e2->Eval(c);
02275 if (v2->vKind != BooleanVK) {
02276 PrimError("Second argument of `=>' must be boolean.", v2, e2->loc);
02277 Val result = NEW(ErrorVC);
02278 return result->Merge(v1)->MergeAndTypeDPS(v2);
02279 }
02280 v2->cacheit = v2->cacheit && v1->cacheit;
02281 return v2->Merge(v1);
02282 }
02283
02284 Val NotEq(Expr e1, Expr e2, const Context& c) {
02285
02286 Val test = EqualVal(e1->Eval(c), e2->Eval(c), e1->loc);
02287
02288 if (test->vKind == ErrorVK) return test;
02289 BooleanVC *result = (BooleanVC*)test;
02290 result->b = IsValFalse(test);
02291 return result;
02292 }
02293
02294 Val GreaterEq(Expr e1, Expr e2, const Context& c) {
02295 Val v1 = e1->Eval(c), v2 = e2->Eval(c);
02296 if (v1->vKind != IntegerVK) {
02297 PrimError("First argument of `>=' must be integer", v1, e1->loc);
02298 Val result = NEW(ErrorVC);
02299 return result->MergeAndTypeDPS(v1);
02300 }
02301 if (v2->vKind != IntegerVK) {
02302 PrimError("Second argument of `>=' must be integer", v2, e2->loc);
02303 Val result = NEW(ErrorVC);
02304 return result->MergeAndTypeDPS(v2);
02305 }
02306 bool b = (((IntegerVC*)v1)->num >= ((IntegerVC*)v2)->num);
02307 Val result = NEW_CONSTR(BooleanVC, (b));
02308 result->cacheit = v1->cacheit && v2->cacheit;
02309 return result->Merge(v1)->Merge(v2);
02310 }
02311
02312 Val LessEq(Expr e1, Expr e2, const Context& c) {
02313 Val v1 = e1->Eval(c), v2 = e2->Eval(c);
02314 if (v1->vKind != IntegerVK) {
02315 PrimError("First argument of `<=' must be integer", v1, e1->loc);
02316 Val result = NEW(ErrorVC);
02317 return result->MergeAndTypeDPS(v1);
02318 }
02319 if (v2->vKind != IntegerVK) {
02320 PrimError("Second argument of `<=' must be integer", v2, e2->loc);
02321 Val result = NEW(ErrorVC);
02322 return result->MergeAndTypeDPS(v2);
02323 }
02324 bool b = (((IntegerVC*)v1)->num <= ((IntegerVC*)v2)->num);
02325 Val result = NEW_CONSTR(BooleanVC, (b));
02326 result->cacheit = v1->cacheit && v2->cacheit;
02327 return result->Merge(v1)->Merge(v2);
02328 }
02329
02330 Val Greater(Expr e1, Expr e2, const Context& c) {
02331 Val v1 = e1->Eval(c), v2 = e2->Eval(c);
02332 if (v1->vKind != IntegerVK) {
02333 PrimError("First argument of `>' must be integer", v1, e1->loc);
02334 Val result = NEW(ErrorVC);
02335 return result->MergeAndTypeDPS(v1);
02336 }
02337 if (v2->vKind != IntegerVK) {
02338 PrimError("Second argument of `>' must be integer", v2, e2->loc);
02339 Val result = NEW(ErrorVC);
02340 return result->MergeAndTypeDPS(v2);
02341 }
02342 bool b = (((IntegerVC*)v1)->num > ((IntegerVC*)v2)->num);
02343 Val result = NEW_CONSTR(BooleanVC, (b));
02344 result->cacheit = v1->cacheit && v2->cacheit;
02345 return result->Merge(v1)->Merge(v2);
02346 }
02347
02348 Val Less(Expr e1, Expr e2, const Context& c) {
02349 Val v1 = e1->Eval(c), v2 = e2->Eval(c);
02350 Val result;
02351
02352 if (v1->vKind != IntegerVK) {
02353 PrimError("First argument of `<' must be integer", v1, e1->loc);
02354 result = NEW(ErrorVC);
02355 return result->MergeAndTypeDPS(v1);
02356 }
02357 if (v2->vKind != IntegerVK) {
02358 PrimError("Second argument of `<' must be integer", v2, e2->loc);
02359 result = NEW(ErrorVC);
02360 return result->MergeAndTypeDPS(v2);
02361 }
02362 bool b = (((IntegerVC*)v1)->num < ((IntegerVC*)v2)->num);
02363 result = NEW_CONSTR(BooleanVC, (b));
02364 result->cacheit = v1->cacheit && v2->cacheit;
02365 return result->Merge(v1)->Merge(v2);
02366 }
02367
02368 Val Star(Expr e1, Expr e2, const Context& c) {
02369 Val v1 = e1->Eval(c), v2 = e2->Eval(c);
02370 Val result;
02371
02372 if (v1->vKind != IntegerVK) {
02373 PrimError("First argument of `*' must be integer", v1, e1->loc);
02374 result = NEW(ErrorVC);
02375 return result->MergeAndTypeDPS(v1);
02376 }
02377 if (v2->vKind != IntegerVK) {
02378 PrimError("Second argument of `*' must be integer", v2, e2->loc);
02379 result = NEW(ErrorVC);
02380 return result->MergeAndTypeDPS(v2);
02381 }
02382 Basics::int32 n1 = ((IntegerVC*)v1)->num;
02383 Basics::int32 n2 = ((IntegerVC*)v2)->num;
02384 Basics::int32 res = n1 * n2;
02385
02386
02387
02388 Basics::int64 l_overflow_check = n1;
02389 l_overflow_check *= n2;
02390 if(l_overflow_check != res)
02391 {
02392 PrimError("Overflow on `*'", v1, v2, e1->loc);
02393 result = NEW(ErrorVC);
02394 return result->Merge(v1)->Merge(v2);
02395 }
02396
02397 result = NEW_CONSTR(IntegerVC, (res));
02398 result->cacheit = v1->cacheit && v2->cacheit;
02399 return result->Merge(v1)->Merge(v2);
02400 }
02401
02402 void PrimInit() {
02403 AddPrimitive("_append", Append);
02404 AddPrimitive("_assert", Assert);
02405 AddPrimitive("_bind1", Bind1);
02406 AddPrimitive("_defined", Defined);
02407 AddPrimitive("_div", Div);
02408 AddPrimitive("_elem", Elem);
02409 AddPrimitive("_find", Find);
02410 AddPrimitive("_findr", FindR);
02411 AddPrimitive("_head", Head);
02412 AddPrimitive("_is_binding", IsBinding);
02413 AddPrimitive("_is_bool", IsBool);
02414 AddPrimitive("_is_closure", IsClosure);
02415 AddPrimitive("_is_err", IsErr);
02416 AddPrimitive("_is_int", IsInt);
02417 AddPrimitive("_is_list", IsList);
02418 AddPrimitive("_is_text", IsText);
02419 AddPrimitive("_length", Length);
02420 AddPrimitive("_list1", List1);
02421 AddPrimitive("_lookup", Lookup);
02422 AddPrimitive("_map", Map);
02423 AddPrimitive("_par_map", ParMap);
02424 AddPrimitive("_max", Max);
02425 AddPrimitive("_min", Min);
02426 AddPrimitive("_mod", Mod);
02427 AddPrimitive("_n", GetName);
02428 AddPrimitive("_same_type", SameType);
02429 AddPrimitive("_sub", Sub);
02430 AddPrimitive("_tail", Tail);
02431 AddPrimitive("_type_of", TypeOf);
02432 AddPrimitive("_v", GetValue);
02433 AddPrimitive("_run_tool", ApplyRunTool);
02434 AddPrimitive("_print", Print);
02435 AddPrimitive("_model_name", ModelName);
02436 AddPrimitive("_fingerprint", GetFP);
02437
02438 AddPrimitiveUnOp("!", Not);
02439 AddPrimitiveUnOp("-", Neg);
02440
02441 AddPrimitiveOp("==", Equal);
02442 AddPrimitiveOp("&&", And);
02443 AddPrimitiveOp("||", Or);
02444 AddPrimitiveOp("=>", Implies);
02445 AddPrimitiveOp("!=", NotEq);
02446 AddPrimitiveOp(">=", GreaterEq);
02447 AddPrimitiveOp("<=", LessEq);
02448 AddPrimitiveOp("++", PlusPlus);
02449 AddPrimitiveOp(">", Greater);
02450 AddPrimitiveOp("<", Less);
02451 AddPrimitiveOp("-", Minus);
02452 AddPrimitiveOp("+", Plus);
02453 AddPrimitiveOp("*", Star);
02454
02455 if(VestaConfig::is_set("Evaluator", "WorkerStackSize"))
02456 {
02457 WorkerStackSize = VestaConfig::get_int("Evaluator", "WorkerStackSize");
02458 }
02459
02460 threadAllowed = maxThreads;
02461 AvailWorks = NULL;
02462 Basics::thread* th = NEW(Basics::thread);
02463 th->fork(DoAvailWork, (void*)NULL);
02464 }