00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "Pickle.H"
00022 #include "Parser.H"
00023 #include "Expr.H"
00024 #include "Val.H"
00025 #include "Err.H"
00026 #include "Files.H"
00027 #include "WordKey.H"
00028 #include "ThreadData.H"
00029 #include <VDirSurrogate.H>
00030 #include <FP.H>
00031 #include <Atom.H>
00032 #include <BufStream.H>
00033
00034 using std::ios;
00035 using std::streampos;
00036 using std::ostringstream;
00037 using std::cerr;
00038 using std::endl;
00039 using Basics::BufStream;
00040
00041 class PickleC {
00042 public:
00043
00044 PickleC()
00045 : size(0), shortId(NullShortId), linePos(0), read_size(0)
00046 { bytes = NEW(BufStream); }
00047
00048
00049 PickleC(char* str, int sz, const PrefixTbl& prefix, const Context& c)
00050 : size(sz), con(c), shortId(NullShortId), linePos(0), prefix(prefix),
00051 read_size(0)
00052 {
00053 bytes = NEW_CONSTR(BufStream, (str, sz, sz));
00054 }
00055
00056 void PickleInt8(Basics::int8 n);
00057 void UnpickleInt8(Basics::int8& n);
00058
00059 void PickleInt16(Basics::uint16 n);
00060 void UnpickleInt16(Basics::uint16& n);
00061
00062 void PickleInt32(Basics::uint32 n);
00063 void UnpickleInt32(Basics::uint32& n);
00064
00065 inline void PickleInt(int n) { PickleInt32(n); }
00066 inline void UnpickleInt(int& n)
00067 {
00068 Basics::uint32 un;
00069 UnpickleInt32(un);
00070 n = (int) un;
00071 }
00072
00073 void PickleInt64(Basics::uint64 n);
00074 void UnpickleInt64(Basics::uint64& n);
00075
00076 void PickleText(const Text& t);
00077 void UnpickleText(Text& t);
00078
00079 void UnpickleAtom(Atom& t);
00080
00081
00082
00083 void PickleLText(const Text& t);
00084 void UnpickleLText(Text& t);
00085
00086
00087
00088
00089 inline void PickleBool(bool v) { PickleInt8(v ? 1 : 0); }
00090 inline void UnpickleBool(bool& v)
00091 {
00092 Basics::int8 wv;
00093 UnpickleInt8(wv);
00094 v = (wv != 0);
00095 }
00096
00097 void PickleLongId(const LongId &lid);
00098 void UnpicklLongId(LongId &lid);
00099
00100 bool PickleVal(bool cut, Val value);
00101 bool UnpickleVal(bool cut, Val& value);
00102 Derived::IndicesApp dis;
00103 PrefixTbl prefix;
00104
00105
00106 inline const char *getBytes()
00107 {
00108 return bytes->str();
00109 }
00110 inline int getSize()
00111 {
00112 unsigned int result = bytes->tellp();
00113 assert(size == result);
00114 return result;
00115 }
00116
00117
00118 bool checkNumBytesRead();
00119 private:
00120 BufStream *bytes;
00121 int size, read_size;
00122 Context con;
00123 Text fileName;
00124 ShortId shortId;
00125 int linePos;
00126 TextIntTbl nameTbl;
00127 bool PickleLocation(SrcLoc *loc);
00128 bool UnpickleLocation(SrcLoc*& loc);
00129 bool PickleContext(const Context& c);
00130 bool UnpickleContext(Context& c);
00131 void PickleDepPath(const DepPath& dp);
00132 DepPath UnpickleDepPath();
00133 bool PickleDPS(DPaths *ps);
00134 bool UnpickleDPS(DPaths*& ps);
00135 void CollectDIs(Val value);
00136 bool PickleExpr(Expr expr);
00137 bool UnpickleExpr(Expr& expr);
00138 };
00139
00140
00141
00142
00143
00144 static int currentPickleVersion = 2;
00145
00146 void PickleC::PickleInt8(Basics::int8 n)
00147 {
00148 FS::Write(*bytes, (char*)&n, sizeof_assert(n, 1));
00149 size += sizeof(n);
00150 }
00151
00152 void PickleC::PickleInt16(Basics::uint16 n)
00153 {
00154 Basics::uint16 n_net = Basics::hton16(n);
00155 FS::Write(*bytes, (char*)&n_net, sizeof_assert(n_net, 2));
00156 size += sizeof(n_net);
00157 }
00158
00159 void PickleC::PickleInt32(Basics::uint32 n)
00160 {
00161 Basics::uint32 n_net = Basics::hton32(n);
00162 FS::Write(*bytes, (char*)&n_net, sizeof_assert(n_net, 4));
00163 size += sizeof(n_net);
00164 }
00165
00166 void PickleC::PickleInt64(Basics::uint64 n)
00167 {
00168 Basics::uint64 n_net = Basics::hton64(n);
00169 FS::Write(*bytes, (char*)&n_net, sizeof_assert(n_net, 8));
00170 size += sizeof(n_net);
00171 }
00172
00173 void PickleC::UnpickleInt8(Basics::int8& n)
00174 {
00175 FS::Read(*bytes, (char*)&n, sizeof_assert(n, 1));
00176 read_size += sizeof(n);
00177 }
00178
00179 void PickleC::UnpickleInt16(Basics::uint16& n)
00180 {
00181 Basics::uint16 n_net;
00182 FS::Read(*bytes, (char*)&n_net, sizeof_assert(n_net, 2));
00183 n = Basics::ntoh16(n_net);
00184 read_size += sizeof(n_net);
00185 }
00186
00187 void PickleC::UnpickleInt32(Basics::uint32& n)
00188 {
00189 Basics::uint32 n_net;
00190 FS::Read(*bytes, (char*)&n_net, sizeof_assert(n_net, 4));
00191 n = Basics::ntoh32(n_net);
00192 read_size += sizeof(n_net);
00193 }
00194
00195 void PickleC::UnpickleInt64(Basics::uint64& n)
00196 {
00197 Basics::uint64 n_net;
00198 FS::Read(*bytes, (char*)&n_net, sizeof_assert(n_net, 8));
00199 n = Basics::ntoh64(n_net);
00200 read_size += sizeof(n_net);
00201 }
00202
00203 void PickleC::PickleText(const Text& t)
00204 {
00205 Basics::uint16 len = t.Length();
00206 assert(len == t.Length());
00207 PickleInt16(len);
00208 FS::Write(*bytes, t.chars(), len);
00209 size += len;
00210 }
00211
00212 void PickleC::UnpickleText(Text& t)
00213 {
00214 Basics::uint16 len;
00215 UnpickleInt16(len);
00216 if (len > size)
00217 throw FS::EndOfFile();
00218 char *s = NEW_PTRFREE_ARRAY(char, len+1);
00219 FS::Read(*bytes, s, len);
00220 read_size += len;
00221 s[len] = 0;
00222 t = Text(s, (void*)s);
00223 }
00224
00225 void PickleC::UnpickleAtom(Atom& a)
00226 {
00227 Basics::uint16 len;
00228 UnpickleInt16(len);
00229 if (len > size)
00230 throw FS::EndOfFile();
00231 char *s = NEW_PTRFREE_ARRAY(char, len+1);
00232 FS::Read(*bytes, s, len);
00233 read_size += len;
00234 s[len] = 0;
00235 a = Atom(s, (void*)s);
00236 }
00237
00238 void PickleC::PickleLText(const Text& t)
00239 {
00240 Basics::uint32 len = t.Length();
00241 assert(len == t.Length());
00242 PickleInt32(len);
00243 FS::Write(*bytes, t.chars(), len);
00244 size += len;
00245 }
00246
00247 void PickleC::UnpickleLText(Text& t)
00248 {
00249 Basics::uint32 len;
00250 UnpickleInt32(len);
00251 if (len > size)
00252 throw FS::EndOfFile();
00253 char *s = NEW_PTRFREE_ARRAY(char, len+1);
00254 FS::Read(*bytes, s, len);
00255 read_size += len;
00256 s[len] = 0;
00257 t = Text(s, (void*)s);
00258 }
00259
00260 void PickleC::PickleLongId(const LongId &lid)
00261 {
00262 FS::Write(*bytes, (char*)lid.value.byte, sizeof_assert(lid.value.byte, 32));
00263 size += sizeof(lid.value.byte);
00264 }
00265
00266 void PickleC::UnpicklLongId(LongId &lid)
00267 {
00268 FS::Read(*bytes, (char*)lid.value.byte, sizeof_assert(lid.value.byte, 32));
00269 read_size += sizeof(lid.value.byte);
00270 }
00271
00272 bool PickleC::PickleLocation(SrcLoc *loc) {
00273
00274
00275
00276 char lineDelta = (char)(loc->line - linePos);
00277 char charPos = (char)loc->character;
00278 PickleInt8(lineDelta);
00279 PickleInt8(charPos);
00280
00281 linePos = loc->line;
00282 return true;
00283 }
00284
00285 bool PickleC::UnpickleLocation(SrcLoc*& loc) {
00286
00287 char lineDelta;
00288 UnpickleInt8(lineDelta);
00289 linePos += (int)lineDelta;
00290
00291 char charPos;
00292 UnpickleInt8(charPos);
00293
00294 loc = NEW_CONSTR(SrcLoc, (linePos, (int)charPos, fileName, shortId));
00295 return true;
00296 }
00297
00298 bool PickleC::PickleContext(const Context& c) {
00299 bool success = true;
00300 Context cc = c;
00301 Basics::uint16 len = cc.Length();
00302
00303 assert(len == cc.Length());
00304 PickleInt16(len);
00305 unsigned int pickled_entry_count = 0;
00306 while (success && !cc.Null()) {
00307 Assoc elem = cc.Pop();
00308 PickleText(elem->name);
00309 success = PickleVal(true, elem->val);
00310 pickled_entry_count++;
00311 }
00312
00313 assert(len == pickled_entry_count);
00314 return success;
00315 }
00316
00317 bool PickleC::UnpickleContext(Context& c) {
00318 bool success = true;
00319 Basics::uint16 cLen;
00320 UnpickleInt16(cLen);
00321 Val val;
00322 while (success && cLen--) {
00323 Atom name;
00324 UnpickleAtom(name);
00325 success = UnpickleVal(true, val);
00326 c.Append1D(NEW_CONSTR(AssocVC, (name, val)));
00327 }
00328 return success;
00329 }
00330
00331 void PickleC::PickleDepPath(const DepPath& dp) {
00332
00333 Basics::uint16 index = prefix.Put(*dp.content->path, nameTbl);
00334
00335 char pk = (char)dp.content->pKind;
00336 PickleInt8(pk);
00337
00338 PickleInt16(index);
00339 }
00340
00341 DepPath PickleC::UnpickleDepPath() {
00342
00343 char pk;
00344 UnpickleInt8(pk);
00345
00346 Basics::uint16 index;
00347 UnpickleInt16(index);
00348 ArcSeq *path = prefix.Get(index);
00349
00350 return DepPath(path, (PathKind)pk);
00351 }
00352
00353 bool PickleC::PickleDPS(DPaths *ps) {
00354 Basics::uint16 len = 0;
00355 if (ps != NULL) {
00356 len = ps->Size();
00357
00358 assert(len == ps->Size());
00359 }
00360 PickleInt16(len);
00361
00362 unsigned int pickled_path_count = 0;
00363 if (ps != NULL) {
00364 DepPathTbl::TIter iter(ps);
00365 DepPathTbl::KVPairPtr ptr;
00366 while (iter.Next(ptr))
00367 {
00368 PickleDepPath(ptr->key);
00369 pickled_path_count++;
00370 }
00371 }
00372
00373 assert(pickled_path_count == len);
00374 return true;
00375 }
00376
00377 bool PickleC::UnpickleDPS(DPaths*& ps) {
00378 Basics::uint16 len;
00379 UnpickleInt16(len);
00380
00381 if (len > 0) {
00382 ps = NEW_CONSTR(DPaths, (len));
00383 while (len-- > 0) {
00384 DepPath newPath(UnpickleDepPath());
00385 DepPathTbl::KVPairPtr dummyPtr;
00386 Val val = LookupPath(&newPath, this->con);
00387 ps->Put(newPath, val, dummyPtr);
00388 }
00389 }
00390 return true;
00391 }
00392
00393 void PickleC::CollectDIs(Val value) {
00394
00395 switch (value->vKind) {
00396 case ListVK:
00397 {
00398 Vals elems = ((ListVC*)value)->elems;
00399 while (!elems.Null())
00400 CollectDIs(elems.Pop());
00401 break;
00402 }
00403 case BindingVK:
00404 {
00405 Context elems = ((BindingVC*)value)->elems;
00406 while (!elems.Null())
00407 CollectDIs(elems.Pop()->val);
00408 break;
00409 }
00410 case TextVK:
00411 {
00412 TextVC *tv = (TextVC*)value;
00413 if (!tv->HasTxt()) dis.Append(tv->Sid());
00414 break;
00415 }
00416 case ClosureVK:
00417 {
00418 ClosureVC *cl = (ClosureVC*)value;
00419 Text name(cl->func->name);
00420 Context work = cl->con;
00421 while (!work.Null()) {
00422 Assoc a = work.Pop();
00423 if (a->name != name) CollectDIs(a->val);
00424 }
00425 break;
00426 }
00427 case ModelVK:
00428 {
00429 dis.Append(((ModelVC*)value)->content->mRoot->shortId());
00430 break;
00431 }
00432 default:
00433 break;
00434 }
00435 return;
00436 }
00437
00438 bool PickleC::PickleExpr(Expr expr) {
00439 PickleLocation(expr->loc);
00440
00441 char ek = (char)expr->kind;
00442 PickleInt8(ek);
00443 switch (ek) {
00444 case ConstantEK:
00445 {
00446 PickleVal(true, ((ConstantEC*)expr)->val);
00447 break;
00448 }
00449 case IfEK:
00450 {
00451 IfEC *ife = (IfEC*)expr;
00452 PickleExpr(ife->test);
00453 PickleExpr(ife->then);
00454 PickleExpr(ife->els);
00455 break;
00456 }
00457 case ComputedEK:
00458 {
00459 PickleExpr(((ComputedEC*)expr)->name);
00460 break;
00461 }
00462 case ExprListEK:
00463 {
00464 Exprs es = ((ExprListEC*)expr)->elems;
00465 Basics::uint16 len = es.size();
00466
00467 assert(len == es.size());
00468 PickleInt16(len);
00469 for (int i = 0; i < len; i++) {
00470 PickleExpr(es.get(i));
00471 }
00472 break;
00473 }
00474 case ArgListEK:
00475 {
00476 Exprs es = ((ArgListEC*)expr)->elems;
00477 PickleInt64(((ArgListEC*)expr)->inPKs);
00478 Basics::uint16 len = es.size();
00479
00480 assert(len == es.size());
00481 PickleInt16(len);
00482 for (int i = 0; i < len; i++) {
00483 PickleExpr(es.get(i));
00484 }
00485 break;
00486 }
00487 case StmtListEK:
00488 {
00489 Exprs es = ((StmtListEC*)expr)->elems;
00490 Basics::uint16 len = es.size();
00491
00492 assert(len == es.size());
00493 PickleInt16(len);
00494 for (int i = 0; i < len; i++) {
00495 PickleExpr(es.get(i));
00496 }
00497 break;
00498 }
00499 case ListEK:
00500 {
00501 Exprs es = ((ListEC*)expr)->elems;
00502 Basics::uint16 len = es.size();
00503
00504 assert(len == es.size());
00505 PickleInt16(len);
00506 for (int i = 0; i < len; i++) {
00507 PickleExpr(es.get(i));
00508 }
00509 break;
00510 }
00511 case AssignEK:
00512 {
00513 AssignEC *ae = (AssignEC*)expr;
00514 PickleExpr(ae->lhs);
00515 PickleExpr(ae->rhs);
00516 PickleBool(ae->isFunc);
00517 break;
00518 }
00519 case BindEK:
00520 {
00521 BindEC *be = (BindEC*)expr;
00522 PickleExpr(be->lhs);
00523 PickleExpr(be->rhs);
00524 break;
00525 }
00526 case NameEK:
00527 {
00528 NameEC *ne = (NameEC*)expr;
00529 PickleText(ne->id);
00530 break;
00531 }
00532 case BindingEK:
00533 {
00534 Exprs assocs = ((BindingEC*)expr)->assocs;
00535 Basics::uint16 len = assocs.size();
00536
00537 assert(len == assocs.size());
00538 PickleInt16(len);
00539 for (int i = 0; i < len; i++) {
00540 PickleExpr(assocs.get(i));
00541 }
00542 break;
00543 }
00544 case ApplyOpEK:
00545 {
00546 ApplyOpEC *ae = (ApplyOpEC*)expr;
00547 PickleText(ae->op);
00548 PickleExpr(ae->e1);
00549 PickleExpr(ae->e2);
00550 break;
00551 }
00552 case ApplyUnOpEK:
00553 {
00554 ApplyUnOpEC *ae = (ApplyUnOpEC*)expr;
00555 PickleText(ae->op);
00556 PickleExpr(ae->e);
00557 break;
00558 }
00559 case ModelEK:
00560 {
00561 ModelEC *me = (ModelEC*)expr;
00562 PickleExpr(me->files);
00563 PickleExpr(me->imports);
00564 PickleExpr(me->block);
00565 PickleLongId(me->modelRoot->longid);
00566 break;
00567 }
00568 case FileEK:
00569 {
00570 FileEC *fe = (FileEC*)expr;
00571
00572 PickleExpr(fe->name);
00573
00574 PickleText(fe->localPath);
00575
00576 PickleLongId(fe->modelRoot->longid);
00577
00578 PickleBool(fe->import);
00579 break;
00580 }
00581 case PrimitiveEK:
00582 {
00583 PrimitiveEC *pe = (PrimitiveEC*)expr;
00584 PickleText(pe->name);
00585 break;
00586 }
00587 case PairEK:
00588 {
00589 PairEC *pe = (PairEC*)expr;
00590 PickleExpr(pe->first);
00591 PickleExpr(pe->second);
00592 break;
00593 }
00594 case SelectEK:
00595 {
00596 SelectEC *se = (SelectEC*)expr;
00597 PickleExpr(se->binding);
00598 PickleExpr(se->field);
00599 PickleBool(se->bang);
00600 break;
00601 }
00602 case FuncEK:
00603 {
00604 FuncEC *fe = (FuncEC*)expr;
00605 PickleText(fe->name);
00606 PickleBool(fe->noCache);
00607 PickleExpr(fe->args);
00608 PickleExpr(fe->body);
00609 break;
00610 }
00611 case BlockEK:
00612 {
00613 BlockEC *be = (BlockEC*)expr;
00614 PickleExpr(be->assocs);
00615 PickleExpr(be->body);
00616 PickleBool(be->isReturn);
00617 break;
00618 }
00619 case IterateEK:
00620 {
00621 IterateEC *ie = (IterateEC*)expr;
00622 PickleExpr(ie->control);
00623 PickleExpr(ie->e);
00624 PickleExpr(ie->body);
00625 break;
00626 }
00627 case ApplyEK:
00628 {
00629 ApplyEC *ae = (ApplyEC*)expr;
00630 PickleExpr(ae->func);
00631 PickleExpr(ae->args);
00632 break;
00633 }
00634 case ErrorEK:
00635 break;
00636 default:
00637 throw("Bad expression type in pickling.\n");
00638 }
00639 return true;
00640 }
00641
00642 bool PickleC::UnpickleExpr(Expr& expr) {
00643 SrcLoc *loc;
00644 UnpickleLocation(loc);
00645
00646 char ek;
00647 UnpickleInt8(ek);
00648 switch (ek) {
00649 case ConstantEK:
00650 {
00651 Val val;
00652 UnpickleVal(true, val);
00653 expr = NEW_CONSTR(ConstantEC, (val, loc));
00654 break;
00655 }
00656 case IfEK:
00657 {
00658 Expr test, then, els;
00659 UnpickleExpr(test);
00660 UnpickleExpr(then);
00661 UnpickleExpr(els);
00662 expr = NEW_CONSTR(IfEC, (test, then, els, loc));
00663 break;
00664 }
00665 case ComputedEK:
00666 {
00667 Expr name;
00668 UnpickleExpr(name);
00669 expr = NEW_CONSTR(ComputedEC, (name));
00670 break;
00671 }
00672 case ExprListEK:
00673 {
00674 Basics::uint16 len;
00675 UnpickleInt16(len);
00676 ExprListEC *elst = NEW_CONSTR(ExprListEC, (len, loc));
00677 Expr elem;
00678 while (len--) {
00679 UnpickleExpr(elem);
00680 elst->AddExpr(elem);
00681 }
00682 expr = elst;
00683 break;
00684 }
00685 case ArgListEK:
00686 {
00687 Bit64 inPKs;
00688 UnpickleInt64(inPKs);
00689 Basics::uint16 len;
00690 UnpickleInt16(len);
00691 ArgListEC *alst = NEW_CONSTR(ArgListEC, (len, loc));
00692 Expr elem;
00693 while (len--) {
00694 UnpickleExpr(elem);
00695 alst->AddExpr(elem, false);
00696 }
00697 alst->inPKs = inPKs;
00698 expr = alst;
00699 break;
00700 }
00701 case StmtListEK:
00702 {
00703 Basics::uint16 len;
00704 UnpickleInt16(len);
00705 StmtListEC *es = NEW_CONSTR(StmtListEC, (loc));
00706 Expr elem;
00707 while (len--) {
00708 UnpickleExpr(elem);
00709 es->AddExpr(elem);
00710 }
00711 expr = es;
00712 break;
00713 }
00714 case ListEK:
00715 {
00716 Basics::uint16 len;
00717 UnpickleInt16(len);
00718 ListEC *elst = NEW_CONSTR(ListEC, (len, loc));
00719 Expr elem;
00720 while (len--) {
00721 UnpickleExpr(elem);
00722 elst->AddExpr(elem);
00723 }
00724 expr = elst;
00725 break;
00726 }
00727 case AssignEK:
00728 {
00729 Expr lhs, rhs;
00730 UnpickleExpr(lhs);
00731 UnpickleExpr(rhs);
00732 bool isFunc;
00733 UnpickleBool(isFunc);
00734 expr = NEW_CONSTR(AssignEC, ((NameEC*)lhs, rhs, isFunc, loc));
00735 break;
00736 }
00737 case BindEK:
00738 {
00739 Expr lhs, rhs;
00740 UnpickleExpr(lhs);
00741 UnpickleExpr(rhs);
00742 expr = NEW_CONSTR(BindEC, (lhs, rhs, loc));
00743 break;
00744 }
00745 case NameEK:
00746 {
00747 Text id;
00748 UnpickleText(id);
00749 expr = NEW_CONSTR(NameEC, (id, loc));
00750 break;
00751 }
00752 case BindingEK:
00753 {
00754 Basics::uint16 len;
00755 UnpickleInt16(len);
00756 BindingEC *be = NEW_CONSTR(BindingEC, (len, loc));
00757 Expr elem;
00758 while (len--) {
00759 UnpickleExpr(elem);
00760 be->AddExpr(elem);
00761 }
00762 expr = be;
00763 break;
00764 }
00765 case ApplyOpEK:
00766 {
00767
00768 Text op;
00769 UnpickleText(op);
00770
00771 Expr e1, e2;
00772 UnpickleExpr(e1);
00773 UnpickleExpr(e2);
00774 expr = NEW_CONSTR(ApplyOpEC, (e1, op, e2, loc));
00775 break;
00776 }
00777 case ApplyUnOpEK:
00778 {
00779
00780 Text op;
00781 UnpickleText(op);
00782
00783 Expr e;
00784 UnpickleExpr(e);
00785 expr = NEW_CONSTR(ApplyUnOpEC, (op, e, loc));
00786 break;
00787 }
00788 case ModelEK:
00789 {
00790 Expr files, imports, block;
00791 UnpickleExpr(files);
00792 UnpickleExpr(imports);
00793 UnpickleExpr(block);
00794 LongId lid;
00795 UnpicklLongId(lid);
00796 VestaSource *modelRoot = lid.lookup();
00797 expr = NEW_CONSTR(ModelEC,
00798 ((ExprListEC*)files, (ExprListEC*)imports, block,
00799 modelRoot, loc));
00800 break;
00801 }
00802 case FileEK:
00803 {
00804 Expr name;
00805 UnpickleExpr(name);
00806 Text localPath;
00807 UnpickleText(localPath);
00808 LongId lid;
00809 UnpicklLongId(lid);
00810 VestaSource *modelRoot = lid.lookup();
00811 bool import;
00812 UnpickleBool(import);
00813 expr = NEW_CONSTR(FileEC,
00814 ((NameEC*)name, localPath, modelRoot, import, loc));
00815 break;
00816 }
00817 case PrimitiveEK:
00818 {
00819 Text name;
00820 UnpickleText(name);
00821 expr = NEW_CONSTR(PrimitiveEC, (name, LookupPrim(name), loc));
00822 break;
00823 }
00824 case PairEK:
00825 {
00826 Expr first, second;
00827 UnpickleExpr(first);
00828 UnpickleExpr(second);
00829 expr = NEW_CONSTR(PairEC, (first, second, loc));
00830 break;
00831 }
00832 case SelectEK:
00833 {
00834 Expr binding, field;
00835 UnpickleExpr(binding);
00836 UnpickleExpr(field);
00837 bool bang;
00838 UnpickleBool(bang);
00839 expr = NEW_CONSTR(SelectEC, (binding, field, bang, loc));
00840 break;
00841 }
00842 case FuncEK:
00843 {
00844 Text name;
00845 UnpickleText(name);
00846 bool noCache;
00847 UnpickleBool(noCache);
00848 Expr args, body;
00849 UnpickleExpr(args);
00850 UnpickleExpr(body);
00851 expr = NEW_CONSTR(FuncEC, (noCache, name, (ArgListEC*)args, body, loc));
00852 break;
00853 }
00854 case BlockEK:
00855 {
00856 Expr assocs, body;
00857 UnpickleExpr(assocs);
00858 UnpickleExpr(body);
00859 bool isReturn;
00860 UnpickleBool(isReturn);
00861 expr = NEW_CONSTR(BlockEC, ((StmtListEC*)assocs, body, isReturn, loc));
00862 break;
00863 }
00864 case IterateEK:
00865 {
00866 Expr control, e, body;
00867 UnpickleExpr(control);
00868 UnpickleExpr(e);
00869 UnpickleExpr(body);
00870 expr = NEW_CONSTR(IterateEC, (control, e, (StmtListEC*)body, loc));
00871 break;
00872 }
00873 case ApplyEK:
00874 {
00875 Expr func, args;
00876 UnpickleExpr(func);
00877 UnpickleExpr(args);
00878 expr = NEW_CONSTR(ApplyEC, (func, (ArgListEC*)args, loc));
00879 break;
00880 }
00881 case ErrorEK:
00882 {
00883 expr = NEW_CONSTR(ErrorEC, (loc, false));
00884 break;
00885 }
00886 default:
00887 throw("Bad expression type in unpickling.\n");
00888 }
00889 return true;
00890 }
00891
00892 bool PickleC::PickleVal(bool cut, Val value) {
00893 if (!value->cacheit) return false;
00894
00895 bool success = true;
00896
00897
00898 bool hasPath = (value->path != NULL);
00899 PickleBool(hasPath);
00900 if (hasPath)
00901 PickleDepPath(*(value->path));
00902
00903
00904 if (hasPath && cut)
00905 CollectDIs(value);
00906 else {
00907 char vk = (char)value->vKind;
00908 PickleInt8(vk);
00909 switch (vk) {
00910 case BooleanVK:
00911 {
00912 PickleBool(((BooleanVC*)value)->b);
00913 break;
00914 }
00915 case IntegerVK:
00916 {
00917 PickleInt(((IntegerVC*)value)->num);
00918 break;
00919 }
00920 case PrimitiveVK:
00921 {
00922 PickleText(((PrimitiveVC*)value)->name);
00923 break;
00924 }
00925 case ListVK:
00926 {
00927 ListVC *lstv = (ListVC*)value;
00928 Vals elems = lstv->elems;
00929 Basics::uint16 len = elems.Length();
00930
00931 assert(len == elems.Length());
00932 PickleInt16(len);
00933 unsigned int pickled_elem_count = 0;
00934 while (success && !elems.Null())
00935 {
00936 success = PickleVal(cut, elems.Pop());
00937 pickled_elem_count++;
00938 }
00939
00940 assert(pickled_elem_count == len);
00941 success = success && PickleDPS(lstv->lenDps);
00942 break;
00943 }
00944 case BindingVK:
00945 {
00946 BindingVC *bv = (BindingVC*)value;
00947 Context elems = bv->elems;
00948 Basics::uint16 len = elems.Length();
00949
00950 assert(len == elems.Length());
00951 PickleInt16(len);
00952 unsigned int pickled_elem_count = 0;
00953 while (success && !elems.Null()) {
00954 Assoc a = elems.Pop();
00955 PickleText(a->name);
00956 success = PickleVal(cut, a->val);
00957 pickled_elem_count++;
00958 }
00959
00960 assert(pickled_elem_count == len);
00961 success = success && PickleDPS(bv->lenDps);
00962 break;
00963 }
00964 case TextVK:
00965 {
00966 TextVC *tv = (TextVC*)value;
00967
00968
00969
00970
00971 bool asTxt = !tv->HasSid() ||
00972 (tv->HasTxt() && (tv->Length() < (tv->TName().Length() +
00973 sizeof(ShortId) + FP::ByteCnt)));
00974 PickleBool(asTxt);
00975 if (asTxt) {
00976 assert(tv->HasTxt());
00977 PickleLText(tv->NDS());
00978 }
00979 else {
00980 assert(tv->HasSid());
00981 PickleText(tv->TName());
00982 ShortId sid = tv->Sid();
00983 PickleInt32(sid);
00984
00985 tv->FingerPrint().Write(*bytes);
00986 size += FP::ByteCnt;
00987 dis.Append(sid);
00988 }
00989 break;
00990 }
00991 case ClosureVK:
00992 {
00993 ClosureVC *cl = (ClosureVC*)value;
00994
00995
00996 SrcLoc *loc = cl->func->loc;
00997 PickleText(loc->file);
00998 PickleInt32(loc->shortId);
00999 linePos = loc->line;
01000 PickleInt(linePos);
01001 success = PickleExpr(cl->func);
01002
01003
01004 if (!success) break;
01005 Text name(cl->func->name);
01006 bool recursive;
01007 Context cc = Snip(cl->con, name, recursive);
01008 success = PickleContext(cc);
01009
01010
01011 if (!success) break;
01012 PickleBool(recursive);
01013 PickleLText(name);
01014 break;
01015 }
01016 case ModelVK:
01017 {
01018 ModelVC *model = (ModelVC*)value;
01019
01020 PickleText(model->content->name);
01021
01022
01023 ShortId sid = model->content->sid;
01024 assert(sid != 0);
01025 PickleInt32(sid);
01026
01027
01028
01029 sid = model->content->mRoot->shortId();
01030 PickleInt32(sid);
01031 model->content->mRoot->fptag.Write(*bytes);
01032 size += FP::ByteCnt;
01033
01034
01035 dis.Append(sid);
01036
01037 model->FingerPrintFile().Write(*bytes);
01038 size += FP::ByteCnt;
01039 model->FingerPrint().Write(*bytes);
01040 size += FP::ByteCnt;
01041 break;
01042 }
01043 case ErrorVK:
01044 break;
01045 default:
01046 {
01047 outputMu.lock();
01048 Error("Bad value type in pickling.\n");
01049 outputMu.unlock();
01050 success = false;
01051 break;
01052 }
01053 }
01054 }
01055
01056 if (success)
01057 success = PickleDPS(value->dps);
01058 return success;
01059 }
01060
01061 bool PickleC::UnpickleVal(bool cut, Val& value) {
01062 bool success = true;
01063
01064
01065 bool hasPath;
01066 UnpickleBool(hasPath);
01067 DepPath *path = NULL;
01068 if (hasPath)
01069 path = NEW_CONSTR(DepPath, (UnpickleDepPath()));
01070
01071
01072 if (hasPath && cut) {
01073 Val val = LookupPath(path, con);
01074 value = val->Copy(true);
01075 }
01076 else {
01077 char vk;
01078 UnpickleInt8(vk);
01079 switch (vk) {
01080 case BooleanVK:
01081 {
01082 bool b;
01083 UnpickleBool(b);
01084 value = NEW_CONSTR(BooleanVC, (b));
01085 break;
01086 }
01087 case IntegerVK:
01088 {
01089 Basics::int32 n;
01090 UnpickleInt(n);
01091 value = NEW_CONSTR(IntegerVC, (n));
01092 break;
01093 }
01094 case PrimitiveVK:
01095 {
01096 Atom name;
01097 UnpickleAtom(name);
01098 value = NEW_CONSTR(PrimitiveVC, (name, LookupPrim(name)));
01099 break;
01100 }
01101 case ListVK:
01102 {
01103 Basics::uint16 len;
01104 UnpickleInt16(len);
01105 Vals elems;
01106 Val v;
01107 while ((len-- > 0) && UnpickleVal(cut, v))
01108 elems.Append1D(v);
01109 value = NEW_CONSTR(ListVC, (elems));
01110 success = success && UnpickleDPS(((ListVC*)value)->lenDps);
01111 break;
01112 }
01113 case BindingVK:
01114 {
01115 Basics::uint16 len;
01116 UnpickleInt16(len);
01117 Context elems;
01118 Val v;
01119 while (success && len--) {
01120 Atom name;
01121 UnpickleAtom(name);
01122 success = UnpickleVal(cut, v);
01123 elems.Append1D(NEW_CONSTR(AssocVC, (name, v)));
01124 }
01125 value = NEW_CONSTR(BindingVC, (elems));
01126 success = success && UnpickleDPS(((BindingVC*)value)->lenDps);
01127 break;
01128 }
01129 case TextVK:
01130 {
01131 bool hasTxt;
01132 UnpickleBool(hasTxt);
01133 if (hasTxt) {
01134 Text t;
01135 UnpickleLText(t);
01136 value = NEW_CONSTR(TextVC, (t));
01137 }
01138 else {
01139
01140 Text name;
01141 UnpickleText(name);
01142 ShortId sid;
01143 UnpickleInt32(sid);
01144 FP::Tag tag;
01145
01146 tag.Read(*bytes);
01147 read_size += FP::ByteCnt;
01148 value = NEW_CONSTR(TextVC, (name, sid, tag));
01149 }
01150 break;
01151 }
01152 case ClosureVK:
01153 {
01154
01155 UnpickleText(fileName);
01156 UnpickleInt32(shortId);
01157 UnpickleInt(linePos);
01158 Expr func;
01159 success = UnpickleExpr(func);
01160
01161
01162 Context c;
01163 if (success)
01164 success = UnpickleContext(c);
01165
01166
01167 Text name;
01168 bool recursive;
01169 if (success) {
01170 UnpickleBool(recursive);
01171 UnpickleLText(name);
01172 }
01173
01174
01175 if (success) {
01176 value = NEW_CONSTR(ClosureVC, ((FuncEC*)func, c, false));
01177 if (recursive)
01178 ((ClosureVC*)value)->con =
01179 Context(NEW_CONSTR(AssocVC, (name, value)), c);
01180 }
01181 break;
01182 }
01183 case ModelVK:
01184 {
01185
01186 Text name;
01187 UnpickleText(name);
01188
01189
01190 ShortId sid;
01191 UnpickleInt32(sid);
01192
01193
01194
01195
01196
01197 ShortId rootSid;
01198 UnpickleInt32(rootSid);
01199 FP::Tag rootTag;
01200 rootTag.Read(*bytes);
01201 read_size += FP::ByteCnt;
01202 VestaSource* root = NEW_CONSTR(VDirSurrogate, (0, rootSid));
01203 root->type = VestaSource::immutableDirectory;
01204 root->longid = LongId::fromShortId(rootSid);
01205 root->fptag = rootTag;
01206
01207
01208 FP::Tag tag;
01209
01210 tag.Read(*bytes);
01211 read_size += FP::ByteCnt;
01212 FP::Tag lidTag;
01213 lidTag.Read(*bytes);
01214 read_size += FP::ByteCnt;
01215
01216 value = NEW_CONSTR(ModelVC, (name, sid, root, tag, lidTag));
01217 break;
01218 }
01219 case ErrorVK:
01220 {
01221 value = NEW_CONSTR(ErrorVC, (true));
01222 break;
01223 }
01224 default:
01225 {
01226 outputMu.lock();
01227 Error("Bad value type in unpickling. Cache data may be corrupted!\n");
01228 outputMu.unlock();
01229 success = false;
01230 }
01231 }
01232 }
01233 if (success) {
01234 value->path = path;
01235 success = UnpickleDPS(value->dps);
01236 }
01237 return success;
01238 }
01239
01240 bool PickleC::checkNumBytesRead()
01241 {
01242 assert((unsigned int) bytes->tellg() == read_size);
01243
01244
01245 if(size > read_size)
01246 {
01247 outputMu.lock();
01248 cerr << ThreadLabel() << "Unpickling didn't read complete pickle (read "
01249 << read_size << " out of " << size << " bytes)" << endl
01250 << "(This is probably a bug; please report it.)" << endl;
01251 outputMu.unlock();
01252 return false;
01253 }
01254
01255
01256 else if(size < read_size)
01257 {
01258 ostringstream l_msg;
01259 l_msg << "Read past end of pickle (read "
01260 << read_size << " bytes, pickle was " << size << " bytes)";
01261 throw Evaluator::failure(l_msg.str(), false);
01262 }
01263 return true;
01264 }
01265
01266 bool Pickle(Val value, VestaVal::T& vval) {
01267 PickleC pickle;
01268 bool success;
01269
01270 try {
01271
01272 pickle.PickleInt(currentPickleVersion);
01273
01274 success = pickle.PickleVal(true, value);
01275 } catch (FS::Failure f) {
01276 outputMu.lock();
01277 cerr << ThreadLabel() << "Pickling error: " << f;
01278 outputMu.unlock();
01279 success = false;
01280 } catch (PrefixTbl::Overflow) {
01281
01282 throw;
01283 } catch (...) {
01284 outputMu.lock();
01285 cerr << ThreadLabel() << "Unknown exception in pickling.\n";
01286 outputMu.unlock();
01287 success = false;
01288 }
01289 if (success) {
01290 vval.fp = value->FingerPrint();
01291 vval.bytes = (char *) pickle.getBytes();
01292 vval.len = pickle.getSize();
01293 vval.dis = pickle.dis;
01294 vval.prefixTbl = pickle.prefix;
01295 }
01296 return success;
01297 }
01298
01299 bool Unpickle(const VestaVal::T& vval, const Context& c, Val& value) {
01300 try {
01301 PickleC pickle(vval.bytes, vval.len, vval.prefixTbl, c);
01302
01303 int pickleVersion = -1;
01304 pickle.UnpickleInt(pickleVersion);
01305
01306 if (pickleVersion != currentPickleVersion) {
01307 ostringstream l_msg;
01308 l_msg << "Pickle version mismatch. (Got " << pickleVersion
01309 << ", expected " << currentPickleVersion << ")";
01310 throw Evaluator::failure(l_msg.str(), false);
01311 }
01312 bool success = pickle.UnpickleVal(true, value);
01313
01314
01315 success = success && pickle.checkNumBytesRead();
01316 return success;
01317 } catch (FS::Failure f) {
01318 outputMu.lock();
01319 cerr << ThreadLabel() << "Unpickling error: " << f << endl
01320 << "(This is probably a bug; please report it.)" << endl;
01321 outputMu.unlock();
01322 } catch (FS::EndOfFile f) {
01323 outputMu.lock();
01324 cerr << ThreadLabel() << "EOF while unpickling." << endl
01325 << "(This is probably a bug; please report it.)" << endl;
01326 outputMu.unlock();
01327 } catch (const char* report) {
01328 outputMu.lock();
01329 cerr << ThreadLabel() << report << endl;
01330 outputMu.unlock();
01331 } catch (Evaluator::failure f) {
01332 outputMu.lock();
01333 cerr << ThreadLabel() << f.msg << endl;
01334 outputMu.unlock();
01335 throw;
01336 } catch (...) {
01337 outputMu.lock();
01338 cerr << ThreadLabel() << "Unknown exception in unpickling.\n";
01339 outputMu.unlock();
01340 }
01341 return false;
01342 }