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