Main Page | Namespace List | Class Hierarchy | Class List | Directories | File List | Namespace Members | Class Members | File Members

Prim.C

Go to the documentation of this file.
00001 // Copyright (C) 2001, Compaq Computer Corporation
00002 // 
00003 // This file is part of Vesta.
00004 // 
00005 // Vesta is free software; you can redistribute it and/or
00006 // modify it under the terms of the GNU Lesser General Public
00007 // License as published by the Free Software Foundation; either
00008 // version 2.1 of the License, or (at your option) any later version.
00009 // 
00010 // Vesta is distributed in the hope that it will be useful,
00011 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00012 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013 // Lesser General Public License for more details.
00014 // 
00015 // You should have received a copy of the GNU Lesser General Public
00016 // License along with Vesta; if not, write to the Free Software
00017 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00018 
00019 /* File: Prim.C                                                */
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   // This function is used only in IsXxx. Since it creates new
00098   // sharing of v->dps, be careful with any other use.
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   // This function is used only in TypeOf and SameType. Since it creates
00187   // new sharing of v->dps, be careful with any other use.
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   // In addition to maintaining result->lenDps, we add length dep of l1 
00275   // into result->dps. Adding length dep of l1 into result->dps can be a 
00276   // bit too coarse.  A possible fix is to add a copy length dep of l2 
00277   // into each of elements of l2 in the second while statement.
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     // The same as +.
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   // Get the result->lenDps correct:
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   // cacheit is set to true:
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   // This code does Modula-3 style DIV
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 /* a < 0 */ {  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         // Add the length dependency:
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         // Add the length dependency:
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         // Apply the function:
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         // Add the new result elem into elems that is used to collect
00978         // the results.
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             // Apply the function:
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   // Do the real work.
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       // Handle parsing error exception.
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   // Finish up
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;  // make compiler happy
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;   // make compiler happy
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   { /*SKIP*/ }
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           // Start a worker to do the work.
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           // Start a worker to do the work.
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   // parMu.unlock();
01338 }
01339 
01340 Val ParMap(ArgList exprs, const Context& c) {
01341   // Parallel version of Map.
01342   if (maxThreads < 2) {
01343     // use Map if there is one thread allowed.
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       // Do the work.
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       // Postprocess when the work finishes.
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         // Add the new elem into elems that is used to collect
01445         // the results.
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       // Delete parWork if it is added to AvailWorks:
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           // Do the work.
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           // Do the work.
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       // Delete parWork if it is added to AvailWorks:
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   // This code does Modula-3 style MOD
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 /*a < 0*/ {  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     // fall through
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     // fall through
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       // Add the length dependency
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       // Add the length dependency
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 // Kludge for debugging help.
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     // fall through ...
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   // cacheit flag of the result is set in EqualVal.
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   // cacheit flag of the result is set in EqualVal.
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   // Overflow check.  This is cheating, but it's probably more
02387   // efficient that anything else we could write in C++.
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 }

Generated on Mon May 8 00:48:39 2006 for Vesta by  doxygen 1.4.2