00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "Val.H"
00022 #include "Expr.H"
00023 #include "Parser.H"
00024 #include "Location.H"
00025 #include "ModelState.H"
00026 #include "PrimRunTool.H"
00027 #include "Files.H"
00028 #include "Debug.H"
00029 #include <CacheC.H>
00030 #include <VestaSource.H>
00031 #include <UniqueId.H>
00032 #include <sstream>
00033 #include <sys/types.h>
00034 #include <sys/stat.h>
00035 #include <BufStream.H>
00036
00037 using std::ios;
00038 using std::ostream;
00039 using std::istream;
00040 using std::fstream;
00041 using std::ostringstream;
00042 using std::istringstream;
00043 using std::cerr;
00044 using std::endl;
00045 using std::oct;
00046 using std::hex;
00047 using std::dec;
00048 using Basics::OBufStream;
00049
00050 static Basics::mutex valMu;
00051
00052
00053 Val valTrue = NEW_CONSTR(BooleanVC, (true));
00054 Val valFalse = NEW_CONSTR(BooleanVC, (false));
00055 Val valZero = NEW_CONSTR(IntegerVC, (0));
00056 Val valErr = NEW_CONSTR(ErrorVC, (true));
00057 Val valUnbnd = NEW(UnbndVC);
00058 Assoc nullAssoc = NEW_CONSTR(AssocVC, (nameDot, valUnbnd));
00059
00060
00061 Val valTBinding = NEW_CONSTR(TextVC, ("t_binding"));
00062 Val valTBool = NEW_CONSTR(TextVC, ("t_bool"));
00063 Val valTClosure = NEW_CONSTR(TextVC, ("t_closure"));
00064 Val valTErr = NEW_CONSTR(TextVC, ("t_err"));
00065 Val valTInt = NEW_CONSTR(TextVC, ("t_int"));
00066 Val valTList = NEW_CONSTR(TextVC, ("t_list"));
00067 Val valTText = NEW_CONSTR(TextVC, ("t_text"));
00068
00069
00070 FP::Tag booleanTag("Bool"),
00071 integerTag("Int"),
00072 listTag("List"),
00073 bindingTag("Binding"),
00074 primitiveTag("Prim"),
00075 textTag("Text"),
00076 closureTag("Closure"),
00077 modelTag("Model"),
00078 errorTag("Error"),
00079 unbndTag("Unbnd");
00080
00081 Context conEmpty, conInitial;
00082
00083 Val CollectLet(const Text& name, Val v1, Val v2);
00084 void CollectLet(const Text& name, Val v1, DPaths *ps, Val res,
00085 DPaths*& nps);
00086 Val CollectFunc(Val bodyv, Val fv, const Context& c);
00087 void CollectFunc(DPaths *ps, Val fv, const Context& c, Val res,
00088 DPaths*& nps);
00089 Val CollectModel(Val bodyv, Val fv, const Context& c);
00090 void CollectModel(DPaths *ps, const Context& c, Val res,
00091 DPaths*& nps);
00092
00093
00094 static int currentDpsVersion = 0;
00095 static int currentDpathVersion = 0;
00096
00097 static void Indent(ostream *os, int amount) {
00098 while (amount--) *os << " ";
00099 }
00100
00101 static int counter = 0;
00102
00103 static Text GetUniqueName() {
00104 int num = IncCounter(&counter);
00105 char buff[16];
00106 sprintf(buff, "%d", num);
00107 Text res(buff);
00108 return res;
00109 }
00110
00111
00112 FP::Tag FingerPrintContext(const Context& c) {
00113 Context work = c;
00114
00115 RawFP fp = POLY_ONE;
00116 while (!work.Null())
00117 FP::Tag::ExtendRaw( fp, work.Pop()->FingerPrint());
00118 FP::Tag tag;
00119 tag.Permute(fp);
00120 return tag;
00121 }
00122
00123 FP::Tag FingerPrintContext(const Context& c, const Text& id) {
00124 Context work = c;
00125
00126 RawFP fp = POLY_ONE;
00127 while (!work.Null()) {
00128 Assoc a = work.Pop();
00129 if (a->name != id)
00130 FP::Tag::ExtendRaw( fp, a->FingerPrint());
00131 }
00132 FP::Tag tag;
00133 tag.Permute(fp);
00134 return tag;
00135 }
00136
00137
00138 void PrintContext(ostream *os, const Context& c, bool verbose, int indent) {
00139 Context cc = c;
00140
00141 *os << "[ ";
00142 if (!cc.Null())
00143 cc.Pop()->PrintD(os, verbose, indent + 2);
00144 while (!cc.Null()) {
00145 *os << ",\n";
00146 Indent(os, indent + 2);
00147 cc.Pop()->PrintD(os, verbose, indent + 2);
00148 }
00149 *os << " ]";
00150 }
00151
00152 void PrintContext(ostream *os, const Context& c, const Text& id, bool verbose,
00153 int indent) {
00154 Context cc = c;
00155
00156 *os << "[ ";
00157 while (!cc.Null()) {
00158 Assoc a = cc.Pop();
00159 if (a->name != id) {
00160 a->PrintD(os, verbose, indent + 2);
00161 break;
00162 }
00163 }
00164 while (!cc.Null()) {
00165 Assoc a = cc.Pop();
00166 if (a->name != id) {
00167 *os << ",\n";
00168 Indent(os, indent + 2);
00169 a->PrintD(os, verbose, indent + 2);
00170 }
00171 }
00172 *os << " ]";
00173 }
00174
00176 Val ValC::MergeDPS(DPaths* ps) {
00177 if (ps != NULL) {
00178 if (this->dps == NULL)
00179 this->dps = NEW_CONSTR(DPaths, (ps->Size()));
00180 this->dps->Merge(ps);
00181 }
00182 return this;
00183 }
00184
00185 Val ValC::Merge(Val v) {
00186 this->MergeDPS(v->dps);
00187 if (v->path != NULL) {
00188 if (this->dps == NULL)
00189 this->dps = NEW(DPaths);
00190
00191 DepPathTbl::KVPairPtr pr;
00192 (void)this->dps->Put(*(v->path), v, pr);
00193
00194 }
00195 return this;
00196 }
00197
00198 Val ValC::MergeAndTypeDPS(Val v) {
00199 this->MergeDPS(v->dps);
00200 if (v->path != NULL)
00201 this->AddToDPS(v->path, ValType(v), TypePK);
00202 return this;
00203 }
00204
00205 Val ValC::MergeLenDPS(Val v) {
00206 if (v->vKind == BindingVK) {
00207 DPaths *ps = ((BindingVC*)v)->lenDps;
00208 if (ps != NULL) {
00209 if (this->dps == NULL)
00210 this->dps = NEW_CONSTR(DPaths, (ps->Size()));
00211 DepPathTbl::TIter iter(ps);
00212 DepPathTbl::KVPairPtr ptr;
00213 while (iter.Next(ptr)) {
00214 DepPath lenPath(ptr->key.content->path, BLenPK, ptr->key.content->pathFP);
00215 Val vNames = ((BindingVC*)ptr->val)->Names();
00216 (void)this->dps->Put(lenPath, vNames, ptr);
00217
00218 }
00219 }
00220 }
00221 else {
00222 assert(v->vKind == ListVK);
00223 DPaths *ps = ((ListVC*)v)->lenDps;
00224 if (ps != NULL) {
00225 if (this->dps == NULL)
00226 this->dps = NEW_CONSTR(DPaths, (ps->Size()));
00227 DepPathTbl::TIter iter(ps);
00228 DepPathTbl::KVPairPtr ptr;
00229 while (iter.Next(ptr)) {
00230 DepPath lenPath(ptr->key.content->path, LLenPK, ptr->key.content->pathFP);
00231 Val vLen = NEW_CONSTR(IntegerVC, (((ListVC*)ptr->val)->elems.Length()));
00232 (void)this->dps->Put(lenPath, vLen, ptr);
00233
00234 }
00235 }
00236 }
00237 return this;
00238 }
00239
00240 Val ValC::MergeAndLenDPS(Val v) {
00241 this->MergeDPS(v->dps);
00242 if (v->vKind == BindingVK) {
00243 BindingVC *bv = (BindingVC*)v;
00244 if (bv->path != NULL)
00245 this->AddToDPS(bv->path, bv->Names(), BLenPK);
00246 else
00247 this->MergeLenDPS(bv);
00248 }
00249 else {
00250 assert(v->vKind == ListVK);
00251 ListVC *lstv = (ListVC*)v;
00252 if (lstv->path != NULL) {
00253 int len = lstv->elems.Length();
00254 IntegerVC *vLen = NEW_CONSTR(IntegerVC, (len));
00255 this->AddToDPS(lstv->path, vLen, LLenPK);
00256 }
00257 else
00258 this->MergeLenDPS(lstv);
00259 }
00260 return this;
00261 }
00262
00263 Val ValC::AddToDPS(DepPath *dp, Val v, PathKind pk) {
00264 if (dp != NULL) {
00265 if (this->dps == NULL)
00266 this->dps = NEW(DPaths);
00267 DepPathTbl::KVPairPtr ptr;
00268 if (pk == DummyPK)
00269 ptr = NEW_CONSTR(DepPathTbl::KVPair, (*dp, v));
00270 else {
00271 DepPath newPath(dp->content->path, pk, dp->content->pathFP);
00272 ptr = NEW_CONSTR(DepPathTbl::KVPair, (newPath, v));
00273 }
00274 (void)this->dps->Put(ptr);
00275 }
00276 return this;
00277 }
00278
00279 Val ValC::AddExtendToDPS(DepPath *dp, Val v, PathKind pk, const Text& id) {
00280 if (dp != NULL) {
00281 if (this->dps == NULL)
00282 this->dps = NEW(DPaths);
00283 DepPath newPath(dp->content);
00284 newPath.Extend(id);
00285 newPath.content->pKind = pk;
00286 DepPathTbl::KVPairPtr pr;
00287 (void)this->dps->Put(newPath, v, pr);
00288
00289 }
00290 return this;
00291 }
00292
00293 Val ValC::Extend(Val v, const Text& id, PathKind pk, bool add) {
00294 Val result;
00295
00296 if (this->path != NULL) {
00297 result = v->Copy();
00298 result->path = this->path->DeepCopy();
00299 result->path->Extend(id, pk);
00300 if (add) result->dps = this->dps;
00301 }
00302 else if (add) {
00303 result = v->Copy();
00304 result->path = v->path;
00305 result->MergeDPS(v->dps)->MergeDPS(this->dps);
00306 }
00307 else
00308
00309 return v;
00310 return result;
00311 }
00312
00314
00315 FP::Tag BooleanVC::FingerPrint() {
00316 if (!this->tagged) {
00317 FP::Tag theTag = booleanTag;
00318 bool8 fp_b = b ? 1 : 0;
00319 theTag.Extend(&fp_b, sizeof_assert(fp_b, 1));
00320 this->tag = theTag;
00321 this->tagged = true;
00322 }
00323 return this->tag;
00324 }
00325
00326
00327 FP::Tag IntegerVC::FingerPrint() {
00328 if (!this->tagged) {
00329 FP::Tag theTag = integerTag;
00330 Basics::int32 num_net = Basics::hton32(num);
00331 theTag.Extend((char*)(&num_net), sizeof_assert(num_net, 4));
00332 this->tag = theTag;
00333 this->tagged = true;
00334 }
00335 return this->tag;
00336 }
00337
00338
00339 void ListVC::PrintD(ostream *os, bool verbose, int indent) {
00340 Vals vv = this->elems;
00341
00342 *os << "< ";
00343 if (!vv.Null())
00344 vv.Pop()->PrintD(os, verbose, indent + 2);
00345 while (!vv.Null()) {
00346 *os << ",\n";
00347 Indent(os, indent + 2);
00348 vv.Pop()->PrintD(os, verbose, indent + 2);
00349 }
00350 *os << " >";
00351 }
00352
00353 FP::Tag ListVC::FingerPrint() {
00354 Vals vv = elems;
00355
00356 if (!this->tagged) {
00357 FP::Tag theTag = listTag;
00358 RawFP fp;
00359 theTag.Unpermute( fp);
00360 while (!vv.Null())
00361 FP::Tag::ExtendRaw( fp, vv.Pop()->FingerPrint());
00362 theTag.Permute(fp);
00363 this->tag = theTag;
00364 this->tagged = true;
00365 }
00366 return this->tag;
00367 }
00368
00369 IntegerVC* ListVC::Length() {
00370 int len = this->elems.Length();
00371 IntegerVC *result = NEW_CONSTR(IntegerVC, (len));
00372
00373 result->MergeDPS(this->dps);
00374 if (this->path != NULL) {
00375 FpVC *fpv = NEW_CONSTR(FpVC, (result->FingerPrint()));
00376 result->AddToDPS(this->path, fpv, LLenPK);
00377 }
00378 else
00379 result->MergeLenDPS(this);
00380 result->cacheit = this->cacheit;
00381 return result;
00382 }
00383
00384 Val ListVC::GetElem(int index) {
00385 Vals vv = this->elems;
00386 Val result;
00387
00388 if (index < 0 || index >= vv.Length()) {
00389
00390 result = NEW(ErrorVC);
00391 return result->MergeAndLenDPS(this);
00392 }
00393 result = vv.Nth(index);
00394 if (path != NULL) {
00395 result = result->Copy();
00396 result->path = path->DeepCopy();
00397 result->path->Extend(IntArc(index));
00398 result->dps = this->dps;
00399 }
00400 else
00401 result->MergeDPS(this->dps);
00402 result->cacheit = result->cacheit && this->cacheit;
00403 return result;
00404 }
00405
00406 Val ListVC::GetElemNoDpnd(int index) {
00407 Vals vv = elems;
00408
00409 if (index < 0 || index >= vv.Length())
00410 return valErr;
00411 return vv.Nth(index);
00412 }
00413
00414 Val ListVC::AddToLenDPS(const DepPath& dp, Val val) {
00415 if (this->lenDps == NULL) {
00416 this->lenDps = NEW_CONSTR(DPaths, (1));
00417 }
00418 DepPathTbl::KVPairPtr pr;
00419 (void)this->lenDps->Put(dp, val, pr);
00420
00421 return this;
00422 }
00423
00424 Val ListVC::MergeToLenDPS(DPaths *ps) {
00425
00426 if (ps != NULL) {
00427 if (this->lenDps == NULL) {
00428 this->lenDps = NEW_CONSTR(DPaths, (ps->Size()));
00429 }
00430 this->lenDps->Merge(ps);
00431 }
00432 return this;
00433 }
00434
00435 Val ListVC::Copy(bool more) {
00436 ListVC *result = NEW_CONSTR(ListVC, (*this));
00437 if (more) {
00438 if (this->lenDps != NULL && this->lenDps->Size() != 0) {
00439 result->lenDps = NEW_CONSTR(DPaths, (this->lenDps->Size()));
00440 result->lenDps->Merge(this->lenDps);
00441 }
00442 }
00443 return result;
00444 }
00445
00446
00447 BindingVC::BindingVC(BindingVC *b1, BindingVC *b2, bool rec)
00448 : ValC(BindingVK), lenDps(NULL) {
00449
00450
00451
00452 if (rec)
00453 this->elems = b1->RecursiveOverlay(b2);
00454 else
00455 this->elems = b1->SimpleOverlay(b2);
00456
00457
00458 if (b1->path != NULL)
00459 this->AddToLenDPS(*b1->path, b1);
00460 else
00461 this->MergeToLenDPS(b1->lenDps);
00462
00463 if (b2->path != NULL)
00464 this->AddToLenDPS(*b2->path, b2);
00465 else
00466 this->MergeToLenDPS(b2->lenDps);
00467
00468
00469 this->cacheit = b1->cacheit && b2->cacheit;
00470 }
00471
00472 void BindingVC::PrintD(ostream *os, bool verbose, int indent) {
00473 Context work = this->elems;
00474 *os << "[ ";
00475 if (!work.Null())
00476 work.Pop()->PrintD(os, verbose, indent + 2);
00477 while (!work.Null()) {
00478 *os << ",\n";
00479 Indent(os, indent + 2);
00480 work.Pop()->PrintD(os, verbose, indent + 2);
00481 }
00482 *os << " ]";
00483 }
00484
00485 FP::Tag BindingVC::FingerPrint() {
00486 if (!this->tagged) {
00487 FP::Tag theTag = bindingTag;
00488 Context work = this->elems;
00489 RawFP fp;
00490 theTag.Unpermute( fp);
00491 while (!work.Null()) {
00492 FP::Tag::ExtendRaw( fp, work.Pop()->FingerPrint());
00493 }
00494 theTag.Permute(fp);
00495 this->tag = theTag;
00496 this->tagged = true;
00497 }
00498 return this->tag;
00499 }
00500
00501 Val BindingVC::Names() {
00502 Context work = this->elems;
00503
00504 Vals vs;
00505 while (!work.Null())
00506 vs.Append1D(NEW_CONSTR(TextVC, (work.Pop()->name)));
00507 return NEW_CONSTR(ListVC, (vs));
00508 }
00509
00510 IntegerVC* BindingVC::Length() {
00511 int len = this->elems.Length();
00512 IntegerVC *result = NEW_CONSTR(IntegerVC, (len));
00513
00514 result->MergeDPS(this->dps);
00515 if (this->path != NULL)
00516 result->AddToDPS(this->path, this->Names(), BLenPK);
00517 else
00518 result->MergeLenDPS(this);
00519 result->cacheit = this->cacheit;
00520 return result;
00521 }
00522
00523 Val BindingVC::Defined(const Text& id) {
00524 Assoc elem = FindInContext(id, this->elems);
00525 bool b = (elem != nullAssoc);
00526 Val result = NEW_CONSTR(BooleanVC, (b));
00527
00528
00529 result->MergeDPS(this->dps);
00530 if (this->path != NULL) {
00531 Val val = (b ? valTrue : valFalse);
00532 result->AddExtendToDPS(this->path, val, BangPK, id);
00533 }
00534 else if (this->lenDps != NULL) {
00535 DepPathTbl::TIter iter(this->lenDps);
00536 DepPathTbl::KVPairPtr ptr;
00537 while (iter.Next(ptr)) {
00538 Context work = ((BindingVC*)ptr->val)->elems;
00539 bool b1 = false;
00540 while (!work.Null()) {
00541 if (work.Pop()->name == id) {
00542 b1 = true;
00543 break;
00544 }
00545 }
00546 Val val = (b1 ? valTrue : valFalse);
00547 result->AddExtendToDPS(&(ptr->key), val, BangPK, id);
00548 }
00549 }
00550 result->cacheit = this->cacheit;
00551 return result;
00552 }
00553
00554 Val BindingVC::Lookup(const Text& id) {
00555 Val v = LookupInContext(id, this->elems);
00556 Val result = this->Extend(v, id);
00557 result->cacheit = result->cacheit && this->cacheit;
00558 return result;
00559 }
00560
00561 Context BindingVC::SimpleOverlay(BindingVC *bv) {
00562 Context c1 = this->elems, c2 = bv->elems;
00563 Context result;
00564 Assoc a, a1, a2;
00565 Val v, v1, v2;
00566 Text name;
00567
00568 while (!c1.Null()) {
00569 a1 = c1.Pop();
00570 name = a1->name;
00571 a2 = FindInContext(name, c2);
00572 if (a2 == nullAssoc) {
00573 v1 = a1->val;
00574 v = this->Extend(v1, name, NormPK, false);
00575 v->AddExtendToDPS(bv->path, valFalse, BangPK, name);
00576 }
00577 else {
00578 v2 = a2->val;
00579 v = bv->Extend(v2, name, NormPK, false);
00580 }
00581 a = NEW_CONSTR(AssocVC, (name, v));
00582 result.Append1D(a);
00583 }
00584 c1 = this->elems;
00585 while (!c2.Null()) {
00586 a2 = c2.Pop();
00587 name = a2->name;
00588 if (FindInContext(name, c1) == nullAssoc) {
00589 v2 = a2->val;
00590 v = bv->Extend(v2, name, NormPK, false);
00591 a = NEW_CONSTR(AssocVC, (name, v));
00592 result.Append1D(a);
00593 }
00594 }
00595 return result;
00596 }
00597
00598 Context BindingVC::RecursiveOverlay(BindingVC *bv) {
00599 Context c1 = this->elems;
00600 Context c2 = bv->elems;
00601 Context result;
00602 Assoc a, a1, a2;
00603 Val v, v1, v2;
00604 Text name;
00605
00606 while (!c1.Null()) {
00607 a1 = c1.Pop();
00608 name = a1->name;
00609 a2 = FindInContext(name, c2);
00610 if (a2 == nullAssoc) {
00611 v1 = a1->val;
00612 v = this->Extend(v1, name, NormPK, false);
00613 v->AddExtendToDPS(bv->path, valFalse, BangPK, name);
00614 }
00615 else {
00616 v2 = a2->val;
00617 if (v2->vKind == BindingVK) {
00618 v1 = a1->val;
00619 if (v1->vKind == BindingVK) {
00620 v1 = this->Extend(v1, name, NormPK, false);
00621 v2 = bv->Extend(v2, name, NormPK, false);
00622 v = NEW_CONSTR(BindingVC, ((BindingVC*)v1, (BindingVC*)v2, true));
00623 v->MergeDPS(v1->dps)->MergeDPS(v2->dps);
00624 }
00625 else {
00626 v = bv->Extend(v2, name, NormPK, false);
00627 v->AddExtendToDPS(this->path, ValType(v1), TypePK, name);
00628 }
00629 }
00630 else
00631 v = bv->Extend(v2, name, NormPK, false);
00632 }
00633 a = NEW_CONSTR(AssocVC, (name, v));
00634 result.Append1D(a);
00635 }
00636 c1 = this->elems;
00637 while (!c2.Null()) {
00638 a2 = c2.Pop();
00639 name = a2->name;
00640 if (FindInContext(name, c1) == nullAssoc) {
00641 v2 = a2->val;
00642 v = bv->Extend(v2, name, NormPK, false);
00643 if (v2->vKind == BindingVK)
00644 v->AddExtendToDPS(path, valFalse, BangPK, name);
00645 a = NEW_CONSTR(AssocVC, (name, v));
00646 result.Append1D(a);
00647 }
00648 }
00649 return result;
00650 }
00651
00652 Val BindingVC::GetElem(const Text& name, int& index) {
00653 Context work = this->elems;
00654 Val result;
00655
00656 index = 0;
00657 while (!work.Null()) {
00658 Assoc a = work.Pop();
00659 if (a->name == name) {
00660 result = a->val;
00661 return Extend(result, name);
00662 }
00663 index++;
00664 }
00665 result = NEW(ErrorVC);
00666 result->MergeDPS(dps);
00667 result->AddExtendToDPS(path, valFalse, BangPK, name);
00668 result->cacheit = result->cacheit && this->cacheit;
00669 return result;
00670 }
00671
00672 Val BindingVC::GetElem(int index, Text& name) {
00673 Context work = this->elems;
00674 Val result;
00675
00676 if (index < 0 || index >= work.Length()) {
00677 result = NEW(ErrorVC);
00678 return result->MergeAndLenDPS(this);
00679 }
00680 Assoc a = work.Nth(index);
00681 name = a->name;
00682 result = this->Extend(a->val, IntArc(index));
00683 result->cacheit = result->cacheit && this->cacheit;
00684 return result;
00685 }
00686
00687 bool BindingVC::DefinedNoDpnd(const Text& id) {
00688 return (FindInContext(id, this->elems) != nullAssoc);
00689 }
00690
00691 Val BindingVC::LookupNoDpnd(const Text& id) {
00692 return LookupInContext(id, this->elems);
00693 }
00694
00695 Val BindingVC::GetElemNoDpnd(const Text& name, int& index) {
00696 Context work = this->elems;
00697 index = 0;
00698
00699 while (!work.Null()) {
00700 Assoc a = work.Pop();
00701 if (a->name == name)
00702 return a->val;
00703 index++;
00704 }
00705 return valErr;
00706 }
00707
00708 Val BindingVC::GetElemNoDpnd(int index, Text& name) {
00709 Context work = this->elems;
00710
00711 if (index < 0 || index >= work.Length())
00712 return valErr;
00713 Assoc a = work.Nth(index);
00714 name = a->name;
00715 return a->val;
00716 }
00717
00718 Binding BindingVC::AddBindingAssoc(const Text& name, Val v) {
00719 return NEW_CONSTR(BindingVC,
00720 (Context(NEW_CONSTR(AssocVC, (name, v)), this->elems)));
00721 }
00722
00723 Binding BindingVC::RemoveBindingAssoc(const Text& id) {
00724 Context work = this->elems;
00725 bool found;
00726 return NEW_CONSTR(BindingVC, (Snip(work, id, found)));
00727 }
00728
00729 Val BindingVC::AddToLenDPS(const DepPath& dp, Val val) {
00730 if (this->lenDps == NULL)
00731 this->lenDps = NEW_CONSTR(DPaths, (1));
00732 DepPathTbl::KVPairPtr pr;
00733 (void)this->lenDps->Put(dp, val, pr);
00734
00735 return this;
00736 }
00737
00738 Val BindingVC::MergeToLenDPS(DPaths *ps) {
00739 if (ps != NULL) {
00740 if (this->lenDps == NULL)
00741 this->lenDps = NEW_CONSTR(DPaths, (ps->Size()));
00742 this->lenDps->Merge(ps);
00743 }
00744 return this;
00745 }
00746
00747 Val BindingVC::Copy(bool more) {
00748 BindingVC *result = NEW_CONSTR(BindingVC, (*this));
00749 if (more) {
00750 if (this->lenDps != NULL && this->lenDps->Size() != 0) {
00751 result->lenDps = NEW_CONSTR(DPaths, (this->lenDps->Size()));
00752 result->lenDps->Merge(this->lenDps);
00753 }
00754 }
00755 return result;
00756 }
00757
00758
00759 FP::Tag PrimitiveVC::FingerPrint() {
00760 if (!this->tagged) {
00761 FP::Tag theTag = primitiveTag;
00762 theTag.Extend(name);
00763 this->tag = theTag;
00764 this->tagged = true;
00765 }
00766 return this->tag;
00767 }
00768
00769
00770 TextVC::TextC::TextC(const Text& tname, const Text& ttext)
00771 : hasTxt(false), hasName(true), name(tname) {
00772 SourceOrDerived file;
00773 try {
00774 this->shortId = CreateDerived();
00775 this->name = file.shortIdToName(this->shortId);
00776 this->hasName = true;
00777 file.open(this->shortId, ios::out);
00778 if (file.fail()) {
00779 outputMu.lock();
00780 Error(Text("Failed to convert text to file: ") + this->name);
00781 outputMu.unlock();
00782 file.close();
00783 throw(Evaluator::failure(Text("exiting"), false));
00784 }
00785 FS::Write(file, ttext.chars(), ttext.Length());
00786 FS::Close(file);
00787 } catch (FS::Failure f) {
00788
00789 outputMu.lock();
00790 ostringstream l_err_msg;
00791 l_err_msg << "Failed to convert text to file:" << endl << f;
00792 Error(l_err_msg.str());
00793 outputMu.unlock();
00794 throw(Evaluator::failure(Text("exiting"), false));
00795 } catch (SRPC::failure f) {
00796
00797 outputMu.lock();
00798 Error(Text("Failed to convert text to file: SRPC::failure (")
00799 + IntToText(f.r) + "), " + f.msg + ".\n");
00800 outputMu.unlock();
00801 throw(Evaluator::failure(Text("exiting"), false));
00802 } catch (SourceOrDerived::Fatal f) {
00803
00804 outputMu.lock();
00805 Error(Text("Failed to convert text to file: ") + f.msg + ".\n");
00806 outputMu.unlock();
00807 throw(Evaluator::failure(Text("exiting"), false));
00808 }
00809 }
00810
00811 TextVC::TextC::TextC(const Text& tname, fstream *iFile, VestaSource *vSource)
00812 : name(tname), hasTxt(false), hasName(true), shortId(NullShortId) {
00813 this->shortId = vSource->shortId();
00814 }
00815
00816 TextVC::TextVC(const Text& tname, const Text& ttext, char c, const FP::Tag& fp)
00817 : ValC(TextVK) {
00818 content = NEW_CONSTR(TextC, (tname, ttext));
00819 this->tag = textTag;
00820 this->tag.Extend(c);
00821 this->tag.Extend(fp);
00822 this->tagged = true;
00823 }
00824
00825 TextVC::TextVC(const Text& tname, fstream *iFile, VestaSource *vSource)
00826 : ValC(TextVK) {
00827 this->content = NEW_CONSTR(TextC, (tname, iFile, vSource));
00828 this->tag = vSource->fptag;
00829 this->tagged = true;
00830 }
00831
00832 TextVC::TextVC(const Text& tname, const ShortId sid, int fp_content)
00833 : ValC(TextVK) {
00834 this->content = NEW_CONSTR(TextC, (tname, sid));
00835 this->tag = textTag;
00836 if (fp_content != 0) {
00837 SourceOrDerived f;
00838 f.open(sid);
00839 if (fp_content == -1) {
00840 this->tag.Extend('D');
00841 FP::FileContents(f, this->tag);
00842 FS::Close(f);
00843 }
00844 else {
00845 f.seekg(0, ios::end);
00846 int length = f.tellg();
00847 f.seekg(0, ios::beg);
00848 if (length < fp_content) {
00849 this->tag.Extend('D');
00850 FP::FileContents(f, this->tag);
00851 FS::Close(f);
00852 }
00853 else {
00854 this->tag.Extend('d');
00855 this->tag.Extend(UniqueId());
00856 }
00857 }
00858 }
00859 else {
00860 this->tag.Extend('d');
00861 this->tag.Extend(UniqueId());
00862 }
00863 this->tagged = true;
00864 }
00865
00866 void TextVC::PrintD(ostream *os, bool verbose, int indent) {
00867 if (verbose || this->HasTxt()) {
00868 bool close;
00869 istream *txt = this->Content(close);
00870 if (txt == NULL) return;
00871 *os << '"' << oct;
00872 int ch;
00873 while ((ch = txt->get()) != EOF) {
00874 unsigned char c = ch;
00875 switch (c) {
00876 case '\n': *os << "\\n"; break;
00877 case '\t': *os << "\\t"; break;
00878 case '\r': *os << "\\r"; break;
00879 case '\f': *os << "\\f"; break;
00880 case '\b': *os << "\\b"; break;
00881 case '\\': *os << "\\\\"; break;
00882 case '"': *os << "\\\""; break;
00883 default:
00884 if (c < ' ' || c > '~') {
00885 char oc = os->fill('0');
00886 int ow = os->width(3);
00887 *os << '\\' << (int)c;
00888 (void)os->fill(oc);
00889 }
00890 else *os << c;
00891 }
00892 }
00893 *os << '"' << dec;
00894 if (close) ((SourceOrDerived*)txt)->close();
00895 }
00896 else {
00897 if (this->HasSid()) {
00898 *os << "<file";
00899 if(printSidNum) {
00900 char sidbuf[9];
00901 sprintf(sidbuf, "0x%08x", this->content->shortId);
00902 *os << " " << sidbuf;
00903 }
00904 *os << ": "
00905 << SourceOrDerived::shortIdToName(this->content->shortId, false)
00906 << ">";
00907 }
00908 else {
00909
00910 *os << "<badfile " << this->content->name << ">";
00911 }
00912 }
00913 }
00914
00915 FP::Tag TextVC::FingerPrint() {
00916 if (!this->tagged) {
00917
00918 FP::Tag theTag = textTag;
00919 bool8 fp_hasTxt = content->hasTxt ? 1 : 0;
00920 theTag.Extend(&fp_hasTxt, sizeof_assert(fp_hasTxt, 1));
00921 theTag.Extend(content->txt);
00922 this->tag = theTag;
00923 this->tagged = true;
00924 }
00925 return this->tag;
00926 }
00927
00928 static SourceOrDerived *open_shortid(ShortId sid,
00929 const char *err_what,
00930 const Text &err_name)
00931 {
00932 SourceOrDerived *result = NEW(SourceOrDerived);
00933 errno = 0;
00934 result->open(sid);
00935 int l_errno_save = errno;
00936 if (result->fail())
00937 {
00938 OBufStream l_err_msg;
00939 char *l_sid_path = SourceOrDerived::shortIdToName(sid, false);
00940 l_err_msg << "Failed to open " << err_what
00941 << ": " << err_name << endl
00942 << " shortid = 0x" << hex << sid << dec << " ("
00943 << l_sid_path << ")" << endl;
00944 if(l_errno_save != 0)
00945 {
00946 l_err_msg << " " << Basics::errno_Text(l_errno_save)
00947 << " (errno = " << l_errno_save << ")" << endl;
00948 }
00949 else if(!FS::Exists(l_sid_path))
00950 {
00951 l_err_msg << " shortid doesn't exist!" << endl;
00952 }
00953 delete [] l_sid_path;
00954 outputMu.lock();
00955 Error(l_err_msg.str());
00956 outputMu.unlock();
00957 return 0;
00958 }
00959 return result;
00960 }
00961
00962 istream* TextVC::Content(bool& closeIt) {
00963 if (this->content->hasTxt) {
00964 closeIt = false;
00965 return NEW_CONSTR(istringstream, (this->content->txt.chars()));
00966 }
00967 assert(this->HasSid());
00968 SourceOrDerived *iFile =
00969 open_shortid(this->content->shortId,
00970 "file",
00971 (this->content->hasName
00972 ? this->content->name
00973 : SourceOrDerived::shortIdToName(this->content->shortId)));
00974 if (!iFile) {
00975 if (!this->content->hasName) {
00976 this->content->name = iFile->shortIdToName(this->content->shortId);
00977 this->content->hasName = true;
00978 }
00979 throw(Evaluator::failure(Text("exiting"), false));
00980 }
00981 closeIt = true;
00982 return iFile;
00983 }
00984
00985 Text TextVC::NDS() {
00986 if (this->content->hasTxt) {
00987 return this->content->txt;
00988 }
00989
00990 SourceOrDerived *file =
00991 open_shortid(this->content->shortId,
00992 "file",
00993 (this->content->hasName
00994 ? this->content->name
00995 : SourceOrDerived::shortIdToName(this->content->shortId)));
00996 if (!file) {
00997 throw(Evaluator::failure(Text("exiting"), false));
00998 }
00999 file->seekg(0, ios::end);
01000 unsigned long length = file->tellg();
01001
01002
01003 if(length > Text::MaxInt)
01004 {
01005 outputMu.lock();
01006 VError(Text("file ") + file->shortIdToName(content->shortId) +
01007 " too big to manipulate as a text value");
01008 outputMu.unlock();
01009 throw(Evaluator::failure(Text("exiting"), false));
01010 }
01011 file->seekg(0, ios::beg);
01012 char *bytes = NEW_PTRFREE_ARRAY(char, length+1);
01013 if (!file->read(bytes, length)) {
01014 outputMu.lock();
01015 VError(Text("reading file ") + file->shortIdToName(content->shortId));
01016 outputMu.unlock();
01017 throw(Evaluator::failure(Text("exiting"), false));
01018 }
01019 file->close();
01020
01021 bytes[length] = 0;
01022 return Text(bytes, (void*)1);
01023 }
01024
01025 ShortId TextVC::Sid() {
01026 valMu.lock();
01027 if (this->HasSid()) {
01028 ShortId sid = this->content->shortId;
01029 valMu.unlock();
01030 return sid;
01031 }
01032
01033 SourceOrDerived file;
01034 try {
01035 this->content->shortId = CreateDerived();
01036 if (!this->content->hasName) {
01037 this->content->name = file.shortIdToName(content->shortId);
01038 this->content->hasName = true;
01039 }
01040 file.open(this->content->shortId, ios::out);
01041 if (file.fail()) {
01042 outputMu.lock();
01043 VError(Text("Failed to convert text to file: ") + this->content->name);
01044 outputMu.unlock();
01045 file.close();
01046 throw(Evaluator::failure(Text("exiting"), false));
01047 }
01048 FS::Write(file, this->content->txt.chars(), this->content->txt.Length());
01049 FS::Close(file);
01050 } catch (FS::Failure f) {
01051
01052 outputMu.lock();
01053 ostringstream l_err_msg;
01054 l_err_msg << "Failed to convert text to file:" << endl << f;
01055 Error(l_err_msg.str());
01056 outputMu.unlock();
01057 throw(Evaluator::failure(Text("exiting"), false));
01058 } catch (SRPC::failure f) {
01059
01060 valMu.unlock();
01061 outputMu.lock();
01062 VError(Text("Failed to convert text to file: SRPC::failure (")
01063 + IntToText(f.r) + "), " + f.msg + ".\n");
01064 outputMu.unlock();
01065 throw(Evaluator::failure(Text("exiting"), false));
01066 } catch (SourceOrDerived::Fatal f) {
01067
01068 valMu.unlock();
01069 outputMu.lock();
01070 VError(Text("Failed to convert text to file: ") + f.msg + ".\n");
01071 outputMu.unlock();
01072 throw(Evaluator::failure(Text("exiting"), false));
01073 }
01074 ShortId sid = this->content->shortId;
01075 valMu.unlock();
01076 return sid;
01077 }
01078
01079 Text TextVC::TName() {
01080 valMu.lock();
01081 if (this->content->hasName) {
01082 valMu.unlock();
01083 return this->content->name;
01084 }
01085
01086 valMu.unlock();
01087 this->Sid();
01088 return this->content->name;
01089 }
01090
01091 int TextVC::Length() {
01092 if (this->content->hasTxt) {
01093 return this->content->txt.Length();
01094 }
01095 assert(this->HasSid());
01096 SourceOrDerived *file =
01097 open_shortid(this->content->shortId,
01098 "file",
01099 (this->content->hasName
01100 ? this->content->name
01101 : SourceOrDerived::shortIdToName(this->content->shortId)));
01102 if (!file) {
01103 throw(Evaluator::failure(Text("exiting"), false));
01104 }
01105 file->seekg(0, ios::end);
01106 int length = file->tellg();
01107 file->close();
01108 return length;
01109 }
01110
01111
01112 ClosureVC::ClosureVC(FuncEC *tfunc, const Context& c, bool fresh)
01113 : ValC(ClosureVK), func(tfunc), exprTagged(false) {
01114 if (fresh) {
01115 Context work = c;
01116 while (!work.Null()) {
01117 Assoc a = work.Pop();
01118 Val val = a->val->Copy(true);
01119 val->path = NEW_CONSTR(DepPath, (a->name));
01120 this->con.Append1D(NEW_CONSTR(AssocVC, (a->name, val)));
01121 }
01122 }
01123 else
01124 this->con = c;
01125 }
01126
01127 void ClosureVC::PrintD(ostream *os, bool verbose, int indent) {
01128 if (verbose) {
01129 *os << "((Closure: formals = ";
01130 this->func->args->PrintD(os);
01131 *os << "\n";
01132 Indent(os, indent);
01133 *os << "--Closure: body = ";
01134 this->func->body->PrintD(os);
01135 *os << "\n";
01136 Indent(os, indent);
01137 *os << "--Closure: context =\n";
01138 Indent(os, indent + 2);
01139 PrintContext(os, this->con, this->func->name, true, indent + 2);
01140 *os << "\n";
01141 Indent(os, indent);
01142 *os << "--End Closure))";
01143 }
01144 else {
01145 *os << "<Closure>";
01146 }
01147 }
01148
01149 FP::Tag ClosureVC::FingerPrint() {
01150 if (!this->tagged) {
01151 FP::Tag theTag = this->FingerPrintExpr();
01152 theTag.Extend(FingerPrintContext(con, this->func->name));
01153 this->tag = theTag;
01154 this->tagged = true;
01155 }
01156 return this->tag;
01157 }
01158
01159 FP::Tag ClosureVC::FingerPrintExpr() {
01160 if (!this->exprTagged) {
01161 FP::Tag theTag = closureTag;
01162 theTag.Extend(this->func->FingerPrint());
01163 this->exprTag = theTag;
01164 this->exprTagged = true;
01165 }
01166 return this->exprTag;
01167 }
01168
01169
01170 ModelVC::ModelVC(const Text& tname, ShortId tsid, VestaSource *root,
01171 Expr mod, const Context& cc, VestaSource *vSource)
01172 : ValC(ModelVK) {
01173 this->content = NEW_CONSTR(ModelC, (tname, tsid, root, mod, cc));
01174
01175 this->tag = modelTag;
01176 this->tag.Extend(vSource->fptag);
01177 this->tagged = true;
01178
01179 this->lidTag = modelTag;
01180 this->lidTag.Extend(root->fptag);
01181 Text prefix, tail;
01182 SplitPath(tname, prefix, tail);
01183 this->lidTag.Extend(tail);
01184 }
01185
01186 ModelVC::ModelVC(const Text& tlPath, VestaSource *root, SrcLoc *loc)
01187 : ValC(ModelVK) {
01188 this->content = NEW_CONSTR(ModelC, (tlPath));
01189 if (!IsAbsolutePath(tlPath)) {
01190 Text prefix, tail;
01191 SplitPath(loc->file, prefix, tail);
01192 this->content->name = prefix + tlPath;
01193 }
01194 fstream *iFile;
01195 VestaSource *vSource;
01196 this->cacheit = OpenSource(root, tlPath, loc, iFile,
01197 content->mRoot, content->sid,
01198 vSource);
01199 if (this->cacheit) {
01200
01201 this->tag = modelTag;
01202 this->tag.Extend(vSource->fptag);
01203 this->tagged = true;
01204
01205 this->lidTag = modelTag;
01206 this->lidTag.Extend(content->mRoot->fptag);
01207 Text prefix, tail;
01208 SplitPath(tlPath, prefix, tail);
01209 this->lidTag.Extend(tail);
01210 }
01211 else {
01212 throw(Evaluator::failure(Text("exiting"), false));
01213 }
01214 }
01215
01216 void ModelVC::PrintD(ostream *os, bool verbose, int indent) {
01217
01218 *os << "<Model " << this->content->name << ">";
01219 }
01220
01221 Val ModelVC::Force() {
01222 valMu.lock();
01223 if (!this->content->parsed) {
01224
01225 SourceOrDerived *iFile = open_shortid(content->sid,
01226 "the model", content->name);
01227 if (!iFile) {
01228 valMu.unlock();
01229 return NEW(ErrorVC);
01230 }
01231 try {
01232 content->model = Parse(iFile, this->content->name, this->content->sid,
01233 this->content->mRoot);
01234 } catch (const char* report) {
01235 valMu.unlock();
01236 throw report;
01237 }
01238 iFile->close();
01239 this->content->c = ProcessModelHead((ModelEC*)content->model);
01240 this->content->parsed = true;
01241 }
01242 valMu.unlock();
01243 return this;
01244 }
01245
01246
01247 ErrorVC::ErrorVC()
01248 : ValC(ErrorVK) {
01249
01250 throw(Evaluator::failure(Text("exiting"), false));
01251 }
01252
01253 FP::Tag ErrorVC::FingerPrint() { return errorTag; }
01254
01255
01256 FP::Tag UnbndVC::FingerPrint() { return unbndTag; }
01257
01258
01259 void AssocVC::PrintD(ostream *os, bool verbose, int indent) {
01260 bool quote = false;
01261
01262 for (int i = 0; i < name.Length(); i++) {
01263 char c = name[i];
01264 if (((c < 'a') || (c > 'z')) &&
01265 ((c < 'A') || (c > 'Z')) &&
01266 ((c < '0') || (c > '9')) &&
01267 (c != '_') &&
01268 (c != '.')) {
01269 quote = true;
01270 break;
01271 }
01272 }
01273 if (quote)
01274 *os << '"' << name << "\"=";
01275 else
01276 *os << name << "=";
01277 switch (this->val->vKind) {
01278 case BindingVK:
01279 case ListVK:
01280 *os << "\n";
01281 Indent(os, indent);
01282 break;
01283 case ClosureVK:
01284 if (verbose) {
01285 *os << "\n";
01286 Indent(os, indent);
01287 }
01288 break;
01289 default:
01290 break;
01291 }
01292 this->val->PrintD(os, verbose, indent);
01293 }
01294
01295 FP::Tag AssocVC::FingerPrint() {
01296 FP::Tag tag(this->name);
01297 tag.Extend(this->val->FingerPrint());
01298 return tag;
01299 }
01300
01302
01303 bool IsValTrue(Val v) {
01304 return ((v->vKind == BooleanVK) && ((BooleanVC*)v)->b);
01305 }
01306
01307 bool IsValFalse(Val v) {
01308 return ((v->vKind == BooleanVK) && !(((BooleanVC*)v)->b));
01309 }
01310
01311 bool IsEmptyBinding(Val v) {
01312 return ((v->vKind == BindingVK) && ((BindingVC*)v)->Null());
01313 }
01314
01315 bool IsEmptyList(Val v) {
01316 return ((v->vKind == ListVK) && ((ListVC*)v)->elems.Null());
01317 }
01318
01319
01320 Val ValType(Val v) {
01321 switch(v->vKind) {
01322 case BooleanVK:
01323 return valTBool;
01324 case IntegerVK:
01325 return valTInt;
01326 case TextVK:
01327 return valTText;
01328 case BindingVK:
01329 return valTBinding;
01330 case ListVK:
01331 return valTList;
01332 case ClosureVK: case ModelVK: case PrimitiveVK:
01333 return valTClosure;
01334 case ErrorVK: case UnbndVK:
01335 return valTErr;
01336 default:
01337 outputMu.lock();
01338 v->VError("Unexpected type");
01339 assert(v != 0);
01340 cerr << "v = ";
01341 v->PrintD(&cerr);
01342 cerr << endl;
01343 InternalError("ValType");
01344 outputMu.unlock();
01345 break;
01346 }
01347 return NULL;
01348 }
01349
01350
01351 void DeleteDuplicatePathsInner(Val v, DPaths *ps) {
01352
01353 if (v->SizeOfDPS() == 0)
01354 v->dps = NULL;
01355 else {
01356 DepPathTbl::TIter iter(v->dps);
01357 DepPathTbl::KVPairPtr ptr;
01358 DPaths *newDps = NEW_CONSTR(DPaths, (v->SizeOfDPS()));
01359 while (iter.Next(ptr)) {
01360 if (!ps->Member(ptr->key))
01361 (void)newDps->Put(ptr);
01362 }
01363 v->dps = (newDps->Size() == 0) ? NULL : newDps;
01364 }
01365
01366
01367 if (v->path == NULL) {
01368 switch (v->vKind) {
01369 case BindingVK:
01370 {
01371 Context work = ((BindingVC*)v)->elems;
01372 while (!work.Null())
01373 DeleteDuplicatePathsInner(work.Pop()->val, ps);
01374 break;
01375 }
01376 case ListVK:
01377 {
01378 Vals elems = ((ListVC*)v)->elems;
01379 while (!elems.Null())
01380 DeleteDuplicatePathsInner(elems.Pop(), ps);
01381 break;
01382 }
01383 default:
01384 break;
01385 }
01386 }
01387 return;
01388 }
01389
01390 void DeleteDuplicatePaths(Val v) {
01391 DPaths *ps = v->dps;
01392
01393
01394 if (v->path != NULL || ps == NULL || ps->Size() == 0)
01395 return;
01396
01397 switch (v->vKind) {
01398 case BindingVK:
01399 {
01400 Context work = ((BindingVC*)v)->elems;
01401 while (!work.Null())
01402 DeleteDuplicatePathsInner(work.Pop()->val, ps);
01403 break;
01404 }
01405 case ListVK:
01406 {
01407 Vals elems = ((ListVC*)v)->elems;
01408 while (!elems.Null())
01409 DeleteDuplicatePathsInner(elems.Pop(), ps);
01410 break;
01411 }
01412 default:
01413 break;
01414 }
01415 return;
01416 }
01417
01418 void PromoteCommonPaths(DPaths *ps, DPaths *psList[], int len) {
01419
01420
01421 DepPathTbl::TIter iter(psList[0]);
01422 DepPathTbl::KVPairPtr ptr;
01423 while (iter.Next(ptr)) {
01424 bool shared = true;
01425
01426 int i;
01427 for (i = 1; i < len; i++) {
01428 if (!psList[i]->Member(ptr->key)) {
01429 shared = false;
01430 break;
01431 }
01432 }
01433 if (shared) {
01434
01435 for (i = 0; i < len; i++) {
01436 DepPathTbl::KVPairPtr dummyPtr = NULL;
01437 psList[i]->Delete(ptr->key, dummyPtr, false);
01438 }
01439
01440 (void)ps->Put(ptr);
01441 }
01442 }
01443
01444 for (int i = 0; i < len; i++) {
01445 psList[i]->Resize();
01446 }
01447 return;
01448 }
01449
01450 Val CanonicalDpnd(Val v) {
01451
01452 DPaths *ps = v->dps;
01453
01454
01455 if (v->path != NULL || ps == NULL || ps->Size() == 0)
01456 return v;
01457
01458
01459 switch (v->vKind) {
01460 case BindingVK:
01461 {
01462 Context work = ((BindingVC*)v)->elems;
01463 int len = work.Length();
01464
01465 if (len == 0) return v;
01466 DPaths **psList = NEW_ARRAY(DPaths*, len);
01467 DPaths *psi = CanonicalDpnd(work.Pop()->val)->dps;
01468 int minSize = (psi ? psi->Size() : 0);
01469 psList[0] = psi;
01470 for (int i = 1; i < len; i++) {
01471 psi = CanonicalDpnd(work.Pop()->val)->dps;
01472 psList[i] = psi;
01473 minSize = min(minSize, (psi ? psi->Size() : 0));
01474 }
01475 if (minSize > 0)
01476 PromoteCommonPaths(ps, psList, len);
01477 break;
01478 }
01479 case ListVK:
01480 {
01481 Vals elems = ((ListVC*)v)->elems;
01482 int len = elems.Length();
01483
01484 if (len == 0) return v;
01485 DPaths **psList = NEW_ARRAY(DPaths*, len);
01486 DPaths *psi = CanonicalDpnd(elems.Pop())->dps;
01487 int minSize = (psi ? psi->Size() : 0);
01488 psList[0] = psi;
01489 for (int i = 1; i < len; i++) {
01490 psi = CanonicalDpnd(elems.Pop())->dps;
01491 psList[i] = psi;
01492 minSize = min(minSize, (psi ? psi->Size() : 0));
01493 }
01494 if (minSize > 0)
01495 PromoteCommonPaths(ps, psList, len);
01496 break;
01497 }
01498 default:
01499 break;
01500 }
01501 return v;
01502 }
01503
01504 void ModelCutOff(Val v) {
01505
01506
01507
01508
01509 if (v->SizeOfDPS() == 0)
01510 v->dps = NULL;
01511 else {
01512 DepPathTbl::TIter iter(v->dps);
01513 DepPathTbl::KVPairPtr ptr;
01514 DPaths *newDps = NEW(DPaths);
01515 while (iter.Next(ptr)) {
01516 if (ptr->key.content->path->getlo() == nameDot) {
01517 (void)newDps->Put(ptr);
01518 }
01519 }
01520 v->dps = newDps;
01521 }
01522
01523 DepPath *dp = v->path;
01524 if (dp != NULL) {
01525 if (dp->content->path->getlo() != nameDot)
01526 v->path = NULL;
01527 }
01528 else {
01529
01530 switch (v->vKind) {
01531 case BindingVK:
01532 {
01533 BindingVC *bv = (BindingVC*)v;
01534 if (bv->lenDps != NULL && bv->lenDps->Size() != 0) {
01535 DepPathTbl::TIter iter(bv->lenDps);
01536 DepPathTbl::KVPairPtr ptr;
01537 DPaths *newDps = NEW(DPaths);
01538 while (iter.Next(ptr)) {
01539 if (ptr->key.content->path->getlo() == nameDot)
01540 (void)newDps->Put(ptr);
01541 }
01542 bv->lenDps = newDps;
01543 }
01544 Context work = bv->elems;
01545 while (!work.Null()) ModelCutOff(work.Pop()->val);
01546 break;
01547 }
01548 case ListVK:
01549 {
01550 ListVC *lstv = (ListVC*)v;
01551 if (lstv->lenDps != NULL && lstv->lenDps->Size() != 0) {
01552 DepPathTbl::TIter iter(lstv->lenDps);
01553 DepPathTbl::KVPairPtr ptr;
01554 DPaths *newDps = NEW(DPaths);
01555 while (iter.Next(ptr)) {
01556 if (ptr->key.content->path->getlo() == nameDot)
01557 (void)newDps->Put(ptr);
01558 }
01559 lstv->lenDps = newDps;
01560 }
01561 Vals vv = lstv->elems;
01562 while (!vv.Null()) ModelCutOff(vv.Pop());
01563 break;
01564 }
01565 case ClosureVK:
01566 {
01567 ClosureVC *cl = (ClosureVC*)v;
01568 Context work = cl->con;
01569 while (!work.Null()) {
01570 Assoc a = work.Pop();
01571 if (cl->func->name != a->name) ModelCutOff(a->val);
01572 }
01573 break;
01574 }
01575 default:
01576 break;
01577 }
01578 }
01579 return;
01580 }
01581
01582 void CollectDefined(BindingVC *bv, const Text& id, DPaths *ps) {
01583
01584
01585 if (bv->path != NULL) {
01586 bool b = bv->DefinedNoDpnd(id);
01587 Val val = (b ? valTrue : valFalse);
01588 ps->AddExtend(bv->path, val, BangPK, id);
01589 }
01590 else if (bv->lenDps != NULL) {
01591 DepPathTbl::TIter iter(bv->lenDps);
01592 DepPathTbl::KVPairPtr ptr;
01593 while (iter.Next(ptr)) {
01594 Context work = ((BindingVC*)ptr->val)->elems;
01595 bool b1 = false;
01596 while (!work.Null()) {
01597 if (work.Pop()->name == id) {
01598 b1 = true;
01599 break;
01600 }
01601 }
01602 Val val = (b1 ? valTrue : valFalse);
01603 ps->AddExtend(&(ptr->key), val, BangPK, id);
01604 }
01605 }
01606 return;
01607 }
01608
01609 Val CollectLookup(BindingVC *bv, const Text& id, DepPath*& path,
01610 DPaths *ps) {
01611
01612
01613 if (bv->path != NULL) {
01614 path = bv->path->DeepCopy();
01615 path->Extend(id);
01616 return bv->LookupNoDpnd(id);
01617 }
01618 path = NULL;
01619 Val result = LookupInContext(id, bv->elems);
01620 if (result->dpsVersion != currentDpsVersion) {
01621 ps->Merge(result->dps);
01622 result->dpsVersion = currentDpsVersion;
01623 }
01624 return result;
01625 }
01626
01627 void ValueDpnd(Val v, DPaths *ps) {
01628
01629
01630
01631 DepPath *dp = v->path;
01632 if (dp != NULL) {
01633
01634 DepPathTbl::KVPairPtr pr;
01635 (void)ps->Put(*dp, v, pr);
01636
01637 }
01638 else {
01639
01640 switch (v->vKind) {
01641 case BindingVK:
01642 {
01643 BindingVC *bv = (BindingVC*)v;
01644 if (bv->lenDps != NULL && bv->lenDps->Size() != 0) {
01645 DepPathTbl::TIter iter(bv->lenDps);
01646 DepPathTbl::KVPairPtr ptr;
01647 while (iter.Next(ptr))
01648 (void)ps->Put(ptr);
01649 }
01650 Context work = bv->elems;
01651 while (!work.Null()) {
01652 Val v1 = work.Pop()->val;
01653 ps->Merge(v1->dps);
01654 ValueDpnd(v1, ps);
01655 }
01656
01657
01658
01659
01660
01661
01662
01663
01664
01665
01666
01667
01668
01669
01670
01671
01672 break;
01673 }
01674 case ListVK:
01675 {
01676 ListVC *lstv = (ListVC*)v;
01677 if (lstv->lenDps != NULL && lstv->lenDps->Size() != 0) {
01678 DepPathTbl::TIter iter(lstv->lenDps);
01679 DepPathTbl::KVPairPtr ptr;
01680 while (iter.Next(ptr))
01681 (void)ps->Put(ptr);
01682 }
01683 Vals vv = lstv->elems;
01684 while (!vv.Null()) {
01685 Val v1 = vv.Pop();
01686 ps->Merge(v1->dps);
01687 ValueDpnd(v1, ps);
01688 }
01689
01690
01691
01692
01693
01694
01695
01696
01697
01698
01699
01700
01701
01702
01703
01704
01705 break;
01706 }
01707 case ClosureVK:
01708 {
01709 ClosureVC *cl = (ClosureVC*)v;
01710 Context work = cl->con;
01711 while (!work.Null()) {
01712 Assoc a = work.Pop();
01713 if (cl->func->name != a->name) {
01714 ps->Merge(a->val->dps);
01715 ValueDpnd(a->val, ps);
01716 }
01717 }
01718 break;
01719 }
01720 default:
01721 break;
01722 }
01723 }
01724 return;
01725 }
01726
01727 DepPath* CollectDpnd(Val v, DepPath *dp, DPaths *ps, bool all = true) {
01728
01729
01730
01731
01732
01733 DepPath *newPath = NULL;
01734
01735 if (v->path != NULL) {
01736 dp->ExtendLow(v->path);
01737 return dp;
01738 }
01739 if (dp->Size() == 0) {
01740 if (all) {
01741 switch (dp->content->pKind) {
01742 case NormPK:
01743 {
01744 ValueDpnd(v, ps);
01745 break;
01746 }
01747 case BLenPK:
01748 {
01749 DPaths *lenDps = ((BindingVC*)v)->lenDps;
01750 if (lenDps != NULL && lenDps->Size() != 0) {
01751 DepPathTbl::TIter iter(lenDps);
01752 DepPathTbl::KVPairPtr ptr;
01753 while (iter.Next(ptr)) {
01754 DepPath lenPath(ptr->key.content->path, BLenPK, ptr->key.content->pathFP);
01755 Val vNames = ((BindingVC*)ptr->val)->Names();
01756 (void)ps->Put(lenPath, vNames, ptr);
01757
01758 }
01759 }
01760 break;
01761 }
01762 case LLenPK:
01763 {
01764 DPaths *lenDps = ((ListVC*)v)->lenDps;
01765 if (lenDps != NULL && lenDps->Size() != 0) {
01766 DepPathTbl::TIter iter(lenDps);
01767 DepPathTbl::KVPairPtr ptr;
01768 while (iter.Next(ptr))
01769 (void)ps->Put(ptr);
01770 }
01771 break;
01772 }
01773 case TypePK:
01774 {
01775 DPaths *lenDps = NULL;
01776 if (v->vKind == BindingVK) {
01777 lenDps = ((BindingVC*)v)->lenDps;
01778 if (lenDps != NULL && lenDps->Size() != 0) {
01779 DepPathTbl::TIter iter(lenDps);
01780 DepPathTbl::KVPairPtr ptr;
01781 while (iter.Next(ptr)) {
01782 DepPath typePath(ptr->key.content->path, TypePK, ptr->key.content->pathFP);
01783 (void)ps->Put(typePath, valTBinding, ptr);
01784
01785 }
01786 }
01787 }
01788 else if (v->vKind == ListVK) {
01789 lenDps = ((ListVC*)v)->lenDps;
01790 if (lenDps != NULL && lenDps->Size() != 0) {
01791 DepPathTbl::TIter iter(lenDps);
01792 DepPathTbl::KVPairPtr ptr;
01793 while (iter.Next(ptr))
01794 (void)ps->Put(ptr);
01795 }
01796 }
01797 break;
01798 }
01799 default:
01800 break;
01801 }
01802 }
01803 return NULL;
01804 }
01805 switch (v->vKind) {
01806 case BindingVK:
01807 {
01808 BindingVC *bv = (BindingVC*)v;
01809 if (dp->Size() == 1 && dp->content->pKind == BangPK)
01810 CollectDefined(bv, dp->content->path->getlo(), ps);
01811 else {
01812 int n = ArcInt(dp->content->path->getlo());
01813 if (n == -1) {
01814 Val v1 = CollectLookup(bv, dp->content->path->getlo(), newPath, ps);
01815 dp->content->path->remlo();
01816 if (newPath != NULL) {
01817 newPath->Extend(*dp->content->path, dp->content->pKind);
01818 return newPath;
01819 }
01820 newPath = CollectDpnd(v1, dp, ps);
01821 }
01822 else {
01823 Context elems = bv->elems;
01824 dp->content->path->remlo();
01825 newPath = CollectDpnd(elems.Nth(n)->val, dp, ps);
01826 }
01827 }
01828 break;
01829 }
01830 case ListVK:
01831 {
01832 int n = ArcInt(dp->content->path->getlo());
01833 dp->content->path->remlo();
01834 Val v1 = ((ListVC*)v)->elems.Nth(n);
01835 if (v1->dpsVersion != currentDpsVersion) {
01836 ps->Merge(v1->dps);
01837 v1->dpsVersion = currentDpsVersion;
01838 }
01839 newPath = CollectDpnd(v1, dp, ps);
01840 break;
01841 }
01842 case ClosureVK:
01843 {
01844 ClosureVC *cl = (ClosureVC*)v;
01845 Context work = cl->con;
01846 Text name(dp->content->path->getlo());
01847 while (!work.Null()) {
01848 Assoc a = work.Pop();
01849 if (a->name == name) {
01850 Val v1 = a->val;
01851 if (v1->dpsVersion != currentDpsVersion) {
01852 ps->Merge(v1->dps);
01853 v1->dpsVersion = currentDpsVersion;
01854 }
01855 dp->content->path->remlo();
01856 newPath = CollectDpnd(v1, dp, ps);
01857 return newPath;
01858 }
01859 }
01860 break;
01861 }
01862 default:
01863 outputMu.lock();
01864 Error("(Impl) CollectDpnd: wrong type of value.\n");
01865
01866
01867 assert(v != 0);
01868 cerr << "v = ";
01869 v->PrintD(&cerr);
01870 cerr << endl;
01871 assert(dp != 0);
01872 cerr << "dp = ";
01873 dp->Print(&cerr);
01874 cerr << endl;
01875 InternalError("CollectDpnd");
01876 outputMu.unlock();
01877 break;
01878 }
01879 return newPath;
01880 }
01881
01882 Val CollectLetS(const Text& name, Val v1, Val v2) {
01883
01884 switch (v2->vKind) {
01885 case BindingVK:
01886 {
01887
01888 BindingVC *bv = (BindingVC*)v2;
01889 Context rc, work = bv->elems;
01890 while (!work.Null()) {
01891 Assoc a = work.Pop();
01892 a = NEW_CONSTR(AssocVC, (a->name, CollectLet(name, v1, a->val)));
01893 rc.Append1D(a);
01894 }
01895 bv->elems = rc;
01896
01897 DPaths *newLenDps;
01898 CollectLet(name, v1, bv->lenDps, bv, newLenDps);
01899 bv->lenDps = newLenDps;
01900 return bv;
01901 }
01902 case ListVK:
01903 {
01904
01905 ListVC *lstv = (ListVC*)v2;
01906 Vals res, elems = lstv->elems;
01907 while (!elems.Null())
01908 res.Append1D(CollectLet(name, v1, elems.Pop()));
01909 lstv->elems = res;
01910
01911 DPaths *newLenDps;
01912 CollectLet(name, v1, lstv->lenDps, lstv, newLenDps);
01913 lstv->lenDps = newLenDps;
01914 return lstv;
01915 }
01916 case ClosureVK:
01917 {
01918 ClosureVC *cl = (ClosureVC*)v2;
01919 Context rc, work = cl->con;
01920 while (!work.Null()) {
01921 Assoc a = work.Pop();
01922 if (a->name != cl->func->name)
01923 a = NEW_CONSTR(AssocVC, (a->name, CollectLet(name, v1, a->val)));
01924 rc.Append1D(a);
01925 }
01926 cl->con = rc;
01927 return v2;
01928 }
01929 default:
01930 break;
01931 }
01932 return v2;
01933 }
01934
01935 Val CollectLet(const Text& name, Val v1, Val v2) {
01936
01937 if (name == emptyText) {
01938
01939 v2->Merge(v1);
01940 return v2;
01941 }
01942
01943
01944 bool found = false;
01945 DepPath *newPath = NULL;
01946 DPaths *rps;
01947
01948 if (v2->SizeOfDPS() != 0) {
01949 DepPathTbl::TIter iter(v2->dps);
01950 DepPathTbl::KVPairPtr ptr;
01951 while (iter.Next(ptr)) {
01952 if (ptr->key.content->path->getlo() == name) {
01953 found = true;
01954 break;
01955 }
01956 }
01957 if (found) {
01958 rps = NEW(DPaths);
01959 iter.Reset();
01960 while (iter.Next(ptr)) {
01961 if (ptr->key.content->path->getlo() == name) {
01962 if (v1->dpsVersion != currentDpsVersion) {
01963 rps->Merge(v1->dps);
01964 v1->dpsVersion = currentDpsVersion;
01965 }
01966 DepPath key1;
01967 key1.DeepCopy(ptr->key, currentDpathVersion);
01968 key1.content->path->remlo();
01969 newPath = CollectDpnd(v1, &key1, rps);
01970 if (newPath != NULL) {
01971 DepPathTbl::KVPairPtr pr;
01972 (void)rps->Put(*newPath, ptr->val, pr);
01973
01974 }
01975 }
01976 else
01977 (void)rps->Put(ptr);
01978 }
01979 }
01980 }
01981
01982 DepPath *dp = v2->path;
01983 Val v3 = v2->Copy(true);
01984 v3->dps = (found) ? rps : v2->dps;
01985 rps = NULL;
01986 if (dp != NULL) {
01987 v3->path = dp;
01988 if (dp->content->path->getlo() == name) {
01989 if (v1->dpsVersion != currentDpsVersion) {
01990 v3->MergeDPS(v1->dps);
01991 v1->dpsVersion = currentDpsVersion;
01992 }
01993 newPath = dp->DeepCopy();
01994 newPath->content->path->remlo();
01995 if (v3->dps == NULL)
01996 v3->dps = NEW(DPaths);
01997 v3->path = CollectDpnd(v1, newPath, v3->dps, false);
01998 }
01999 return v3;
02000 }
02001
02002
02003 return CollectLetS(name, v1, v3);
02004 }
02005
02006 Val LetDpnd(Val v, const Context& c) {
02007 Context work = c;
02008 Assoc a;
02009
02010
02011
02012
02013 currentDpathVersion++;
02014 while (!work.Null()) {
02015 a = work.Pop();
02016 currentDpsVersion++;
02017 v = CollectLet(a->name, a->val, v);
02018
02019
02020
02021
02022 DeleteDuplicatePaths(v);
02023 CanonicalDpnd(v);
02024 }
02025 return v;
02026 }
02027
02028 Val CollectFuncS(Val bodyv, Val fv, const Context& c) {
02029
02030 switch (bodyv->vKind) {
02031 case BindingVK:
02032 {
02033 BindingVC *bv = (BindingVC*)bodyv;
02034 Context rc, work = bv->elems;
02035 while (!work.Null()) {
02036 Assoc a = work.Pop();
02037 a = NEW_CONSTR(AssocVC, (a->name, CollectFunc(a->val, fv, c)));
02038 rc.Append1D(a);
02039 }
02040 bv->elems = rc;
02041 DPaths *newLenDps;
02042 CollectFunc(bv->lenDps, fv, c, bv, newLenDps);
02043 bv->lenDps = newLenDps;
02044 return bv;
02045 }
02046 case ListVK:
02047 {
02048 ListVC *lstv = (ListVC*)bodyv;
02049 Vals res, elems = lstv->elems;
02050 while (!elems.Null())
02051 res.Append1D(CollectFunc(elems.Pop(), fv, c));
02052 lstv->elems = res;
02053 DPaths *newLenDps;
02054 CollectFunc(lstv->lenDps, fv, c, lstv, newLenDps);
02055 lstv->lenDps = newLenDps;
02056 return lstv;
02057 }
02058 case ClosureVK:
02059 {
02060 ClosureVC *cl = (ClosureVC*)bodyv;
02061 Context rc, work = cl->con;
02062 while (!work.Null()) {
02063 Assoc a = work.Pop();
02064 if (a->name != cl->func->name)
02065 a = NEW_CONSTR(AssocVC, (a->name, CollectFunc(a->val, fv, c)));
02066 rc.Append1D(a);
02067 }
02068 cl->con = rc;
02069 return cl;
02070 }
02071 default:
02072 break;
02073 }
02074 return bodyv;
02075 }
02076
02077 Val CollectFunc(Val bodyv, Val fv, const Context& c) {
02078 Text name;
02079 DepPath *newPath = NULL;
02080 bool fromArgsCon;
02081
02082 Context argsCon1, argsCon2;
02083 Context work = c;
02084 while (!work.Null()) {
02085 Assoc a = work.Pop();
02086 if (a->val->path != NULL &&
02087 a->val->path->Size() == 1 &&
02088 a->name == a->val->path->content->path->getlo())
02089 argsCon1.Push(a);
02090 else
02091 argsCon2.Push(a);
02092 }
02093
02094 DPaths *rps = NEW(DPaths);
02095
02096 if (bodyv->dps != NULL) {
02097 DepPathTbl::TIter iter(bodyv->dps);
02098 DepPathTbl::KVPairPtr ptr;
02099 DepPath key1;
02100 while (iter.Next(ptr)) {
02101 name = ptr->key.content->path->getlo();
02102 fromArgsCon = false;
02103 work = argsCon1;
02104 while (!fromArgsCon && !work.Null()) {
02105 Assoc a = work.Pop();
02106 if (a->name == name) {
02107 if (a->val->dpsVersion != currentDpsVersion) {
02108 rps->Merge(a->val->dps);
02109 a->val->dpsVersion = currentDpsVersion;
02110 }
02111 newPath = NULL;
02112 (void)rps->Put(ptr);
02113 fromArgsCon = true;
02114 }
02115 }
02116 work = argsCon2;
02117 while (!fromArgsCon && !work.Null()) {
02118 Assoc a = work.Pop();
02119 if (a->name == name) {
02120 if (a->val->dpsVersion != currentDpsVersion) {
02121 rps->Merge(a->val->dps);
02122 a->val->dpsVersion = currentDpsVersion;
02123 }
02124 key1.DeepCopy(ptr->key);
02125 key1.content->path->remlo();
02126 newPath = CollectDpnd(a->val, &key1, rps);
02127 fromArgsCon = true;
02128 }
02129 }
02130 if (!fromArgsCon) {
02131 key1.DeepCopy(ptr->key);
02132 if (((ClosureVC*)fv)->func->name == name) {
02133
02134 key1.content->path->remlo();
02135 }
02136 newPath = CollectDpnd(fv, &key1, rps);
02137 }
02138 if (newPath != NULL) {
02139 DepPathTbl::KVPairPtr pr;
02140 (void)rps->Put(*newPath, ptr->val, pr);
02141
02142 }
02143 }
02144 }
02145
02146
02147 if (fv->dpsVersion != currentDpsVersion) {
02148 rps->Merge(fv->dps);
02149 fv->dpsVersion = currentDpsVersion;
02150 }
02151 rps->Add(fv->path, fv, ExprPK);
02152
02153
02154 DepPath *dp = bodyv->path;
02155 Val bodyv1 = bodyv->Copy(true);
02156 bodyv1->dps = rps;
02157 bodyv1->path = dp;
02158 if (dp != NULL) {
02159 name = dp->content->path->getlo();
02160 fromArgsCon = false;
02161 work = argsCon1;
02162 while (!fromArgsCon && !work.Null()) {
02163 Assoc a = work.Pop();
02164 if (a->name == name) {
02165 if (a->val->dpsVersion != currentDpsVersion) {
02166 bodyv1->MergeDPS(a->val->dps);
02167 a->val->dpsVersion = currentDpsVersion;
02168 }
02169 fromArgsCon = true;
02170 }
02171 }
02172 work = argsCon2;
02173 while (!fromArgsCon && !work.Null()) {
02174 Assoc a = work.Pop();
02175 if (a->name == name) {
02176 if (a->val->dpsVersion != currentDpsVersion) {
02177 bodyv1->MergeDPS(a->val->dps);
02178 a->val->dpsVersion = currentDpsVersion;
02179 }
02180 newPath = dp->DeepCopy();
02181 newPath->content->path->remlo();
02182 bodyv1->path = CollectDpnd(a->val, newPath, bodyv1->dps, false);
02183 fromArgsCon = true;
02184 }
02185 }
02186 if (!fromArgsCon) {
02187 newPath = dp->DeepCopy();
02188 if (((ClosureVC*)fv)->func->name == name) {
02189
02190 newPath->content->path->remlo();
02191 }
02192 bodyv1->path = CollectDpnd(fv, newPath, bodyv1->dps, false);
02193 }
02194 return bodyv1;
02195 }
02196
02197
02198
02199
02200 return CollectFuncS(bodyv1, fv, c);
02201 }
02202
02203 Val FuncDpnd(Val bodyv, Val fv, const Context& c) {
02204 currentDpsVersion++;
02205 return CollectFunc(bodyv, fv, c);
02206 }
02207
02208 Val CollectModelS(Val bodyv, Val fv, const Context& c) {
02209
02210 switch (bodyv->vKind) {
02211 case BindingVK:
02212 {
02213 BindingVC *bv = (BindingVC*)bodyv;
02214 Context rc, work = bv->elems;
02215 while (!work.Null()) {
02216 Assoc a = work.Pop();
02217 a = NEW_CONSTR(AssocVC, (a->name, CollectModel(a->val, fv, c)));
02218 rc.Append1D(a);
02219 }
02220 bv->elems = rc;
02221 DPaths *newLenDps;
02222 CollectModel(bv->lenDps, c, bv, newLenDps);
02223 bv->lenDps = newLenDps;
02224 return bv;
02225 }
02226 case ListVK:
02227 {
02228 ListVC *lstv = (ListVC*)bodyv;
02229 Vals res, elems = lstv->elems;
02230 while (!elems.Null())
02231 res.Append1D(CollectModel(elems.Pop(), fv, c));
02232 lstv->elems = res;
02233 DPaths *newLenDps;
02234 CollectModel(lstv->lenDps, c, lstv, newLenDps);
02235 lstv->lenDps = newLenDps;
02236 return lstv;
02237 }
02238 case ClosureVK:
02239 {
02240 ClosureVC *cl = (ClosureVC*)bodyv;
02241 Context rc, work = cl->con;
02242 while (!work.Null()) {
02243 Assoc a = work.Pop();
02244 if (a->name != cl->func->name)
02245 a = NEW_CONSTR(AssocVC, (a->name, CollectModel(a->val, fv, c)));
02246 rc.Append1D(a);
02247 }
02248 cl->con = rc;
02249 return cl;
02250 }
02251 default:
02252 break;
02253 }
02254 return bodyv;
02255 }
02256
02257 Val CollectModel(Val bodyv, Val fv, const Context& c) {
02258 DepPath *newPath = NULL;
02259 bool merged = false;
02260
02261 Val dotVal = c.Nth(0)->val;
02262 DPaths *rps = NEW(DPaths);
02263
02264
02265 if (bodyv->SizeOfDPS() != 0) {
02266 DepPathTbl::TIter iter(bodyv->dps);
02267 DepPathTbl::KVPairPtr ptr;
02268 DepPath key1;
02269 while (iter.Next(ptr)) {
02270 assert(ptr->key.content->path->getlo() == nameDot);
02271 if (dotVal->dpsVersion != currentDpsVersion) {
02272 rps->Merge(dotVal->dps);
02273 dotVal->dpsVersion = currentDpsVersion;
02274 }
02275 key1.DeepCopy(ptr->key);
02276 key1.content->path->remlo();
02277 newPath = CollectDpnd(dotVal, &key1, rps);
02278 if (newPath != NULL) {
02279 DepPathTbl::KVPairPtr pr;
02280 (void)rps->Put(*newPath, ptr->val, pr);
02281
02282 }
02283 }
02284 }
02285
02286 rps->Merge(fv->dps);
02287 rps->Add(fv->path, fv, ExprPK);
02288 rps->Add(fv->path, fv, NormPK);
02289
02290
02291 DepPath *dp = bodyv->path;
02292 Val bodyv1 = bodyv->Copy(true);
02293 bodyv1->dps = rps;
02294 if (dp != NULL) {
02295 newPath = NULL;
02296 assert(dp->content->path->getlo() == nameDot);
02297 if (dotVal->dpsVersion != currentDpsVersion)
02298 bodyv1->MergeDPS(dotVal->dps);
02299 newPath = dp->DeepCopy();
02300 newPath->content->path->remlo();
02301 newPath = CollectDpnd(dotVal, newPath, bodyv1->dps, false);
02302 bodyv1->path = newPath;
02303 return bodyv1;
02304 }
02305
02306
02307 return CollectModelS(bodyv1, fv, c);
02308 }
02309
02310 Val ModelDpnd(Val bodyv, Val fv, const Context& c) {
02311 currentDpsVersion++;
02312 return CollectModel(bodyv, fv, c);
02313 }
02314
02315 void CollectLet(const Text& name, Val v1, DPaths *ps, Val res,
02316 DPaths*& nps) {
02317
02318 if (name == emptyText) {
02319
02320 res->MergeDPS(v1->dps)->MergeDPS(ps);
02321 return;
02322 }
02323
02324 if (ps == NULL || ps->Size() == 0) {
02325 nps = NULL;
02326 return;
02327 }
02328
02329 bool found = false;
02330 DepPath *newPath = NULL;
02331 DepPathTbl::TIter iter(ps);
02332 DepPathTbl::KVPairPtr ptr;
02333 while (iter.Next(ptr)) {
02334 if (ptr->key.content->path->getlo() == name) {
02335 found = true;
02336 break;
02337 }
02338 }
02339 if (!found) {
02340 nps = ps;
02341 }
02342 else {
02343 nps = NEW(DPaths);
02344 if (res->dps == NULL)
02345 res->dps = NEW(DPaths);
02346 DPaths *rps = res->dps;
02347 iter.Reset();
02348 while (iter.Next(ptr)) {
02349 if (ptr->key.content->path->getlo() != name)
02350 (void)nps->Put(ptr);
02351 else {
02352 if (v1->dpsVersion != currentDpsVersion) {
02353 rps->Merge(v1->dps);
02354 v1->dpsVersion = currentDpsVersion;
02355 }
02356 DepPath key1;
02357 key1.DeepCopy(ptr->key, currentDpathVersion);
02358 key1.content->path->remlo();
02359 newPath = CollectDpnd(v1, &key1, rps);
02360 if (newPath != NULL) {
02361 DepPathTbl::KVPairPtr pr;
02362 nps->Put(*newPath, ptr->val, pr);
02363
02364 }
02365 }
02366 }
02367 }
02368 if (nps->Size() == 0) nps = NULL;
02369 return;
02370 }
02371
02372 void CollectFunc(DPaths *ps, Val fv, const Context& c, Val res,
02373 DPaths*& nps) {
02374
02375 if (ps == NULL || ps->Size() == 0) {
02376 nps = NULL;
02377 return;
02378 }
02379
02380 DepPath *newPath = NULL;
02381 Text name;
02382 bool fromArgsCon;
02383 nps = NEW(DPaths);
02384 if (res->dps == NULL)
02385 res->dps = NEW(DPaths);
02386 DPaths *rps = res->dps;
02387 DepPathTbl::TIter iter(ps);
02388 DepPathTbl::KVPairPtr ptr;
02389 DepPath key1;
02390 while (iter.Next(ptr)) {
02391 name = ptr->key.content->path->getlo();
02392 Context work = c;
02393 fromArgsCon = false;
02394 while (!fromArgsCon && !work.Null()) {
02395 Assoc a = work.Pop();
02396 if (a->name == name) {
02397 if (a->val->dpsVersion != currentDpsVersion) {
02398 rps->Merge(a->val->dps);
02399 a->val->dpsVersion = currentDpsVersion;
02400 }
02401 key1.DeepCopy(ptr->key);
02402 key1.content->path->remlo();
02403 newPath = CollectDpnd(a->val, &key1, rps);
02404 fromArgsCon = true;
02405 }
02406 }
02407 if (!fromArgsCon) {
02408 key1.DeepCopy(ptr->key);
02409 if (((ClosureVC*)fv)->func->name == name) {
02410 key1.content->path->remlo();
02411 }
02412 if (fv->dpsVersion != currentDpsVersion) {
02413 rps->Merge(fv->dps);
02414 fv->dpsVersion = currentDpsVersion;
02415 }
02416 newPath = CollectDpnd(fv, &key1, rps);
02417 }
02418 if (newPath != NULL) {
02419 DepPathTbl::KVPairPtr pr;
02420 nps->Put(*newPath, ptr->val, pr);
02421
02422 }
02423 }
02424 if (nps->Size() == 0) nps = NULL;
02425 return;
02426 }
02427
02428 void CollectModel(DPaths *ps, const Context& c, Val res,
02429 DPaths*& nps) {
02430 DepPath *newPath = NULL;
02431
02432
02433 if (ps == NULL)
02434 nps = NULL;
02435 else {
02436 Val dotVal = c.Nth(0)->val;
02437 nps = NEW(DPaths);
02438 if (res->dps == NULL)
02439 res->dps = NEW(DPaths);
02440 DPaths *rps = res->dps;
02441 DepPathTbl::TIter iter(ps);
02442 DepPathTbl::KVPairPtr ptr;
02443 DepPath key1;
02444 while (iter.Next(ptr)) {
02445 assert(ptr->key.content->path->getlo() == nameDot);
02446 if (dotVal->dpsVersion != currentDpsVersion) {
02447 rps->Merge(dotVal->dps);
02448 dotVal->dpsVersion = currentDpsVersion;
02449 }
02450 key1.DeepCopy(ptr->key);
02451 key1.content->path->remlo();
02452 newPath = CollectDpnd(dotVal, &key1, rps);
02453 if (newPath != NULL) {
02454 DepPathTbl::KVPairPtr pr;
02455 nps->Put(*newPath, ptr->val, pr);
02456
02457 }
02458 }
02459 }
02460 return;
02461 }
02462
02463
02464 Text PrintForm(Val v) {
02465 OBufStream stream;
02466 v->PrintD(&stream);
02467 return Text(stream.str());
02468 }
02469
02470
02471 Assoc FindInContext(const Text& id, const Context& c) {
02472 Context work = c;
02473
02474 while (!work.Null()) {
02475 Assoc a = work.Pop();
02476 if (a->name == id) return a;
02477 }
02478 return nullAssoc;
02479 }
02480
02481 Val LookupInContext(const Text& id, const Context& c) {
02482 return FindInContext(id, c)->val;
02483 }
02484
02485
02486
02487
02488 Val LookupArc(const Text& arc, Val v) {
02489 switch (v->vKind) {
02490 case BindingVK:
02491 {
02492 int n = ArcInt(arc);
02493 if (n == -1)
02494 v = ((BindingVC*)v)->LookupNoDpnd(arc);
02495 else {
02496 Text arc1;
02497 v = ((BindingVC*)v)->GetElemNoDpnd(n, arc1);
02498 }
02499 break;
02500 }
02501 case ListVK:
02502 {
02503 int n = ArcInt(arc);
02504 if (n == -1) return valUnbnd;
02505 v = ((ListVC*)v)->GetElemNoDpnd(n);
02506 break;
02507 }
02508 case ClosureVK:
02509 v = LookupInContext(arc, ((ClosureVC*)v)->con);
02510 break;
02511 default:
02512
02513 return valUnbnd;
02514 }
02515 return v;
02516 }
02517
02518 Val LookupPath(const FV2::T& path, const Context& c) {
02519
02520
02521
02522 int len = path.size();
02523 Val result;
02524
02525
02526 PathKind pkind = (PathKind)path.get(0).chars()[0];
02527
02528
02529 result = LookupInContext(path.get(1), c);
02530 if (result->vKind == UnbndVK) return result;
02531
02532
02533 if (pkind == BangPK) {
02534 for (int i = 2; i < (len - 1); i++) {
02535 result = LookupArc(path.get(i), result);
02536 if (result->vKind == UnbndVK) return result;
02537 }
02538 if (result->vKind != BindingVK)
02539 return valUnbnd;
02540 return ((BindingVC*)result)->DefinedNoDpnd(path.get(len-1)) ? valTrue : valFalse;
02541 }
02542 for (int i = 2; i < len; i++) {
02543 result = LookupArc(path.get(i), result);
02544 if (result->vKind == UnbndVK) return result;
02545 }
02546
02547
02548 switch (pkind) {
02549 case BLenPK:
02550 if (result->vKind != BindingVK) return valUnbnd;
02551 return ((BindingVC*)result)->Names();
02552 case LLenPK:
02553 if (result->vKind != ListVK) return valUnbnd;
02554 return ((ListVC*)result)->Length();
02555 case TypePK:
02556 return ValType(result);
02557 case ExprPK:
02558 if (result->vKind == ClosureVK)
02559 result = NEW_CONSTR(FpVC, (((ClosureVC*)result)->FingerPrintExpr()));
02560 else if (result->vKind == ModelVK)
02561 result = NEW_CONSTR(FpVC, (((ModelVC*)result)->FingerPrintFile()));
02562 else
02563 result = valUnbnd;
02564 return result;
02565 default:
02566 return result;
02567 }
02568
02569 }
02570
02571 Val LookupPath(DepPath *dp, const Context& c) {
02572
02573
02574 PathKind pkind = dp->content->pKind;
02575 ArcSeq *path = dp->content->path;
02576 int len = path->size();
02577
02578
02579 Val result = LookupInContext(path->get(0), c);
02580
02581
02582 if (pkind == BangPK) {
02583 for (int i = 1; i < len-1; i++) {
02584 assert(result->vKind != UnbndVK);
02585 result = LookupArc(path->get(i), result);
02586 }
02587 assert(result->vKind == BindingVK);
02588 return ((BindingVC*)result)->DefinedNoDpnd(path->get(len-1)) ? valTrue : valFalse;
02589 }
02590 for (int i = 1; i < len; i++) {
02591 assert(result->vKind != UnbndVK);
02592 result = LookupArc(path->get(i), result);
02593 }
02594
02595
02596 switch (pkind) {
02597 case BLenPK:
02598 assert(result->vKind == BindingVK);
02599 return ((BindingVC*)result)->Names();
02600 case LLenPK:
02601 assert(result->vKind == ListVK);
02602 return ((ListVC*)result)->Length();
02603 case TypePK:
02604 return ValType(result);
02605 case ExprPK:
02606 if (result->vKind == ClosureVK)
02607 result = NEW_CONSTR(FpVC, (((ClosureVC*)result)->FingerPrintExpr()));
02608 else {
02609 assert(result->vKind == ModelVK);
02610 result = NEW_CONSTR(FpVC, (((ModelVC*)result)->FingerPrintFile()));
02611 }
02612 return result;
02613 default:
02614 return result;
02615 }
02616
02617 }
02618
02619 Val Lookup(Basics::uint16 idx, const PrefixTbl& tbl,
02620 const Context& c, Val* vals) {
02621 Val res;
02622 if (vals[idx] == NULL) {
02623 if (tbl.PrefixIndex(idx) == PrefixTbl::endMarker) {
02624 res = LookupInContext(tbl.Arc(idx), c);
02625 vals[idx] = res;
02626 }
02627 else {
02628 res = Lookup(tbl.PrefixIndex(idx), tbl, c, vals);
02629 if (res->vKind == UnbndVK) {
02630 vals[idx] = valUnbnd;
02631 }
02632 else {
02633 res = LookupArc(tbl.Arc(idx), res);
02634 vals[idx] = res;
02635 }
02636 }
02637 }
02638 else {
02639 res = vals[idx];
02640 }
02641 return res;
02642 }
02643
02644 Val LookupPath(Basics::uint16 idx, PathKind pkind, const PrefixTbl& tbl,
02645 const Context& c, Val *vals) {
02646 Val result;
02647 if (pkind == BangPK) {
02648 short int idx1 = tbl.PrefixIndex(idx);
02649 result = Lookup(idx1, tbl, c, vals);
02650 if (result->vKind == BindingVK)
02651 result = ((BindingVC*)result)->DefinedNoDpnd(tbl.Arc(idx)) ? valTrue : valFalse;
02652 else
02653 result = valUnbnd;
02654 }
02655 else {
02656 result = Lookup(idx, tbl, c, vals);
02657 switch (pkind) {
02658 case BLenPK:
02659 if (result->vKind == BindingVK)
02660 result = ((BindingVC*)result)->Names();
02661 else
02662 result = valUnbnd;
02663 break;
02664 case LLenPK:
02665 if (result->vKind == ListVK)
02666 result = ((ListVC*)result)->Length();
02667 else
02668 result = valUnbnd;
02669 break;
02670 case TypePK:
02671 result = ValType(result);
02672 break;
02673 case ExprPK:
02674 if (result->vKind == ClosureVK)
02675 result = NEW_CONSTR(FpVC, (((ClosureVC*)result)->FingerPrintExpr()));
02676 else if (result->vKind == ModelVK)
02677 result = NEW_CONSTR(FpVC, (((ModelVC*)result)->FingerPrintFile()));
02678 else
02679 result = valUnbnd;
02680 break;
02681 default:
02682 break;
02683 }
02684 }
02685 return result;
02686 }
02687
02688 void AppendDToContext(const Text& name, Expr elem, const Context& cElem,
02689 Context& cc) {
02690
02691 Val v = elem->Eval(RestrictContext(cElem, elem->freeVars));
02692 cc.Append1D(NEW_CONSTR(AssocVC, (name, v)));
02693 }
02694
02695 void PushToContext(const Text& name, Expr elem, const Context& cElem,
02696 Context& in) {
02697
02698 Val v = elem->Eval(RestrictContext(cElem, elem->freeVars));
02699 in.Push(NEW_CONSTR(AssocVC, (name, v)));
02700 }
02701
02702 Context RestrictContext(const Context& con, Vars fv) {
02703 Context result;
02704
02705 while (!fv.Null()) {
02706 Text id(fv.Pop());
02707 Assoc a = FindInContext(id, con);
02708 if (a != nullAssoc) result.Append1D(a);
02709 }
02710 return result;
02711 }
02712
02713 Context Snip(const Context& orig, const Text& name, bool& found) {
02714 Context result;
02715 Context work = orig;
02716 Assoc a;
02717
02718 found = false;
02719 while (!work.Null()) {
02720 a = work.Pop();
02721 if (a->name == name) {
02722 found = true;
02723 break;
02724 }
02725 result.Append1D(a);
02726 }
02727 if (!found) return orig;
02728 while (!work.Null()) {
02729 a = work.Pop();
02730 if (a->name != name)
02731 result.Append1D(a);
02732 }
02733 return result;
02734 }
02735
02736 Context Prune(const Context& orig, const Context& remove) {
02737 if (remove.Null()) return orig;
02738
02739 Context work = orig;
02740 Context result;
02741 while (!work.Null()) {
02742 Assoc a = work.Pop();
02743 if (FindInContext(a->name, remove) == nullAssoc)
02744 result.Append1D(a);
02745 }
02746 return result;
02747 }
02748
02749 void AssignAssoc(AssignEC *ae, Context& con) {
02750 Text name(ae->lhs->id);
02751
02752 if (ae->isFunc) {
02753 FuncEC *e = (FuncEC*)ae->rhs;
02754 ClosureVC *cl = NEW_CONSTR(ClosureVC, (e, con, true));
02755 AssocVC* av = NEW_CONSTR(AssocVC, (name, cl));
02756 con.Push(av);
02757 cl->con = RestrictContext(Context(av, cl->con), e->freeVars);
02758 }
02759 else {
02760 Expr e = ae->rhs;
02761 ExprKind ek = e->kind;
02762 if (ek != BaseTEK && ek != ListTEK &&
02763 ek != BindingTEK && ek != FuncTEK) {
02764 Val v = e->Eval(RestrictContext(con, e->freeVars));
02765 con.Push(NEW_CONSTR(AssocVC, (name, v)));
02766 }
02767 }
02768 }
02769
02770 void IterateAssoc(IterateEC *it, Context& c) {
02771 Expr control = it->control, e = it->e;
02772 StmtListEC *body = it->body;
02773 Val v = e->Eval(c), v1;
02774 Text newName = GetUniqueName();
02775 c.Push(new AssocVC(newName, v));
02776
02777 if (control->kind == NameEK) {
02778 Text id(((Name)control)->id);
02779 if (v->vKind == ListVK) {
02780 int len = ((ListVC*)v)->elems.Length();
02781 v1 = NEW_CONSTR(IntegerVC, (len));
02782 FpVC *fpv = NEW_CONSTR(FpVC, (v1->FingerPrint()));
02783 v1->AddToDPS(NEW_CONSTR(DepPath, (newName)), fpv, LLenPK);
02784 c.Push(NEW_CONSTR(AssocVC, (emptyText, v1)));
02785 Vals vlist = ((ListVC*)v)->elems;
02786 int i = 0;
02787 while (!vlist.Null()) {
02788 v1 = vlist.Pop()->Copy();
02789 v1->path = NEW_CONSTR(DepPath, (newName));
02790 v1->path->Extend(IntArc(i++), NormPK);
02791 c.Push(NEW_CONSTR(AssocVC, (id, v1)));
02792 c = AddStmtAssocs(body, c);
02793 }
02794 }
02795 else {
02796 c.Push(NEW_CONSTR(AssocVC, (emptyText, v)));
02797 outputMu.lock();
02798 Error("Control expression doesn't evaluate to list.\n", e->loc);
02799 ErrorVal(v);
02800 outputMu.unlock();
02801 throw(Evaluator::failure(Text("exiting"), false));
02802 }
02803 }
02804 else {
02805
02806 PairEC *pair = (PairEC*)control;
02807 Text id1(((Name)(pair->first))->id);
02808 Text id2(((Name)(pair->second))->id);
02809 if (v->vKind == BindingVK) {
02810 BindingVC *bv = (BindingVC*)v;
02811 int len = bv->elems.Length();
02812 v1 = NEW_CONSTR(IntegerVC, (len));
02813 v1->AddToDPS(NEW_CONSTR(DepPath, (newName)), bv->Names(), BLenPK);
02814 c.Push(NEW_CONSTR(AssocVC, (emptyText, v1)));
02815 Context es = ((BindingVC*)v)->elems;
02816 while (!es.Null()) {
02817 Assoc a = es.Pop();
02818 c.Push(NEW_CONSTR(AssocVC, (id1, NEW_CONSTR(TextVC, (a->name)))));
02819 v1 = a->val->Copy();
02820 v1->path = NEW_CONSTR(DepPath, (newName));
02821 v1->path->Extend(a->name, NormPK);
02822 c.Push(NEW_CONSTR(AssocVC, (id2, v1)));
02823 c = AddStmtAssocs(body, c);
02824 }
02825 }
02826 else {
02827 c.Push(NEW_CONSTR(AssocVC, (emptyText, v)));
02828 outputMu.lock();
02829 Error("Control expression doesn't evaluate to binding.\n", e->loc);
02830 ErrorVal(v);
02831 outputMu.unlock();
02832 throw(Evaluator::failure(Text("exiting"), false));
02833 }
02834 }
02835 return;
02836 }
02837
02838 Context AddStmtAssocs(StmtListEC *assocs, const Context& c) {
02839 Context cc = c;
02840 Exprs els = assocs->elems;
02841
02842 for (int i = 0; i < els.size(); i++) {
02843 Expr e = els.get(i);
02844 switch (e->kind) {
02845 case TypedEK:
02846
02847 break;
02848 case AssignEK:
02849 AssignAssoc((AssignEC*)e, cc);
02850 break;
02851 case IterateEK:
02852 IterateAssoc((IterateEC*)e, cc);
02853 break;
02854 case TryEK:
02855 e->Eval(cc);
02856 break;
02857 default:
02858 outputMu.lock();
02859 Error("Invalid statement:\n`", e->loc);
02860 ErrorExpr(e);
02861 ErrorDetail("'.");
02862 outputMu.unlock();
02863 }
02864 }
02865 return cc;
02866 }
02867
02868 void ValInit() {
02869 conInitial.Push(NEW_CONSTR(AssocVC, (nameDot, NEW(BindingVC))));
02870 }