1 // Copyright (c) 1996 James Clark
2 // See the file copying.txt for copying permission.
7 #include "Interpreter.h"
8 #include "InterpreterMessages.h"
9 #include "ELObjMessageArg.h"
10 #include "Expression.h"
13 #include "SosofoObj.h"
15 #include "ELObjPropVal.h"
20 #ifdef DSSSL_NAMESPACE
21 namespace DSSSL_NAMESPACE {
25 VM::VM(Interpreter &interpreter)
26 : Collector::DynamicRoot(interpreter), interp(&interpreter)
31 VM::VM(EvalContext &context, Interpreter &interpreter)
32 : EvalContext(context), Collector::DynamicRoot(interpreter), interp(&interpreter)
65 void VM::growStack(int n)
67 size_t newSize = sp - sbase;
69 newSize += (n + 15) & ~15;
72 ELObj **newStack = new ELObj *[newSize];
73 slim = newStack + newSize;
74 memcpy(newStack, sbase, (sp - sbase)*sizeof(ELObj *));
75 sp = newStack + (sp - sbase);
76 frame = newStack + (frame - sbase);
82 void VM::trace(Collector &c) const
85 for (ELObj **p = sbase; p != sp; p++)
88 for (ControlStackEntry *p = csbase; p != csp; p++) {
89 c.trace(p->protectClosure);
90 c.trace(p->continuation);
92 c.trace(protectClosure);
95 void VM::pushFrame(const Insn *next, int argsPushed)
98 size_t newSize = csbase ? (cslim - csbase)*2 : 8;
99 ControlStackEntry *newBase = new ControlStackEntry[newSize];
100 cslim = newBase + newSize;
101 ControlStackEntry *newP = newBase;
102 for (const ControlStackEntry *oldP = csbase; oldP < csp; oldP++)
109 csp->closure = closure;
110 csp->protectClosure = protectClosure;
112 csp->frameSize = sp - frame - argsPushed;
113 csp->closureLoc = closureLoc;
114 csp->continuation = 0;
118 const Insn *VM::popFrame()
120 ASSERT(csp > csbase);
122 if (csp->continuation)
123 csp->continuation->kill();
124 closure = csp->closure;
125 protectClosure = csp->protectClosure;
126 frame = sp - csp->frameSize;
127 closureLoc = csp->closureLoc;
131 void VM::setClosureArgToCC()
133 ASSERT(nActualArgs == 1);
134 ContinuationObj *cc = (ContinuationObj *)sp[-1];
135 csp[-1].continuation = cc;
136 cc->set(sp - sbase, csp - csbase);
139 ELObj *VM::eval(const Insn *insn, ELObj **display, ELObj *arg)
151 insn = insn->execute(*this);
156 ASSERT(csp == csbase);
161 if (interp->debugMode())
163 result = interp->makeError();
168 void VM::stackTrace()
170 unsigned long count = 0;
171 if (protectClosure) {
172 interp->setNextLocation(closureLoc);
173 interp->message(InterpreterMessages::stackTrace);
176 ControlStackEntry *lim = csbase;
177 if (csp != csbase && !csbase->protectClosure)
179 for (ControlStackEntry *p = csp; p != lim; p--) {
180 interp->setNextLocation(p[-1].closureLoc);
182 if (count == 5 && p - lim > 7) {
183 interp->message(InterpreterMessages::stackTraceEllipsis,
184 NumberMessageArg(p - (lim + 6)));
188 interp->message(InterpreterMessages::stackTrace);
196 bool Insn::isReturn(int &) const
201 bool Insn::isPopBindings(int &, InsnPtr &) const
206 const Insn *ErrorInsn::execute(VM &vm) const
212 CondFailInsn::CondFailInsn(const Location &loc)
217 const Insn *CondFailInsn::execute(VM &vm) const
219 vm.interp->setNextLocation(loc_);
220 vm.interp->message(InterpreterMessages::condFail);
221 return ErrorInsn::execute(vm);
224 CaseFailInsn::CaseFailInsn(const Location &loc)
229 const Insn *CaseFailInsn::execute(VM &vm) const
231 vm.interp->setNextLocation(loc_);
232 vm.interp->message(InterpreterMessages::caseFail, ELObjMessageArg(vm.sp[-1], *vm.interp));
233 return ErrorInsn::execute(vm);
236 ConstantInsn::ConstantInsn(ELObj *obj, InsnPtr next)
237 : value_(obj), next_(next)
241 const Insn *ConstantInsn::execute(VM &vm) const
245 return next_.pointer();
248 ResolveQuantitiesInsn::ResolveQuantitiesInsn(const Location &loc, InsnPtr next)
249 : loc_(loc), next_(next)
253 const Insn *ResolveQuantitiesInsn::execute(VM &vm) const
255 ELObj *tem = vm.sp[-1]->resolveQuantities(1,
259 if (vm.interp->isError(tem)) {
264 return next_.pointer();
267 TestInsn::TestInsn(InsnPtr consequent, InsnPtr alternative)
268 : consequent_(consequent), alternative_(alternative)
272 const Insn *TestInsn::execute(VM &vm) const
274 return (*--vm.sp)->isTrue() ? consequent_.pointer() : alternative_.pointer();
277 OrInsn::OrInsn(InsnPtr nextTest, InsnPtr next)
278 : nextTest_(nextTest), next_(next)
282 const Insn *OrInsn::execute(VM &vm) const
284 if (vm.sp[-1]->isTrue())
285 return next_.pointer();
287 return nextTest_.pointer();
290 AndInsn::AndInsn(InsnPtr nextTest, InsnPtr next)
291 : nextTest_(nextTest), next_(next)
295 const Insn *AndInsn::execute(VM &vm) const
297 if (!vm.sp[-1]->isTrue())
298 return next_.pointer();
300 return nextTest_.pointer();
303 CaseInsn::CaseInsn(ELObj *obj, InsnPtr match, InsnPtr fail)
304 : obj_(obj), match_(match), fail_(fail)
308 const Insn *CaseInsn::execute(VM &vm) const
310 if (ELObj::eqv(*vm.sp[-1], *obj_)) {
312 return match_.pointer();
314 return fail_.pointer();
317 PopInsn::PopInsn(InsnPtr next)
322 const Insn *PopInsn::execute(VM &vm) const
325 return next_.pointer();
328 ConsInsn::ConsInsn(InsnPtr next)
333 const Insn *ConsInsn::execute(VM &vm) const
335 vm.sp[-2] = vm.interp->makePair(vm.sp[-1], vm.sp[-2]);
337 return next_.pointer();
340 AppendInsn:: AppendInsn(const Location &loc, InsnPtr next)
341 : loc_(loc), next_(next)
345 const Insn *AppendInsn::execute(VM &vm) const
347 ELObj *&source = vm.sp[-1];
348 if (!source->isNil()) {
349 PairObj *pair = source->asPair();
351 vm.interp->setNextLocation(loc_);
352 vm.interp->message(InterpreterMessages::spliceNotList);
356 source = pair->cdr();
357 PairObj *tail = vm.interp->makePair(pair->car(), 0);
358 ELObjDynamicRoot head(*vm.interp, tail);
359 while (!source->isNil()) {
360 pair = source->asPair();
362 vm.interp->setNextLocation(loc_);
363 vm.interp->message(InterpreterMessages::spliceNotList);
367 PairObj *newTail = vm.interp->makePair(pair->car(), 0);
368 tail->setCdr(newTail);
370 source = pair->cdr();
372 tail->setCdr(vm.sp[-2]);
376 return next_.pointer();
379 ApplyBaseInsn::ApplyBaseInsn(int nArgs, const Location &loc)
380 : nArgs_(nArgs), loc_(loc)
384 ApplyInsn::ApplyInsn(int nArgs, const Location &loc, InsnPtr next)
385 : ApplyBaseInsn(nArgs, loc), next_(next)
389 TailApplyInsn::TailApplyInsn(int nCallerArgs, int nArgs, const Location &loc)
390 : ApplyBaseInsn(nArgs, loc), nCallerArgs_(nCallerArgs)
394 // top of stack is operand; next down is last operand and so on
396 FunctionObj *ApplyBaseInsn::decodeArgs(VM &vm) const
398 FunctionObj *func = (*--vm.sp)->asFunction();
400 vm.interp->setNextLocation(loc_);
401 vm.interp->message(InterpreterMessages::callNonFunction,
402 ELObjMessageArg(*vm.sp, *vm.interp));
406 int nReq = func->nRequiredArgs();
408 vm.interp->setNextLocation(loc_);
409 vm.interp->message(InterpreterMessages::missingArg);
413 if (nArgs_ - nReq > func->nOptionalArgs()) {
414 if (func->nKeyArgs()) {
415 // Keyword args can be specified more than once
416 // so we can only check there are an even number.
417 if ((nArgs_ - nReq - func->nOptionalArgs()) & 1) {
418 vm.interp->setNextLocation(loc_);
419 vm.interp->message(InterpreterMessages::oddKeyArgs);
420 vm.sp -= (nArgs_ - nReq) - func->nOptionalArgs();
423 else if (!func->restArg()) {
424 vm.interp->setNextLocation(loc_);
425 vm.interp->message(InterpreterMessages::tooManyArgs);
426 vm.sp -= (nArgs_ - nReq) - func->nOptionalArgs();
432 const Insn *ApplyInsn::execute(VM &vm) const
434 FunctionObj *func = decodeArgs(vm);
435 vm.nActualArgs = nArgs_;
437 return func->call(vm, loc_, next_.pointer());
442 const Insn *TailApplyInsn::execute(VM &vm) const
444 FunctionObj *func = decodeArgs(vm);
445 vm.nActualArgs = nArgs_;
447 return func->tailCall(vm, loc_, nCallerArgs_);
452 ApplyPrimitiveObj::ApplyPrimitiveObj()
453 : FunctionObj(&signature_)
457 const Signature ApplyPrimitiveObj::signature_ = { 2, 0, 1 };
459 const Insn *ApplyPrimitiveObj::call(VM &vm, const Location &loc,
462 if (!shuffle(vm, loc))
464 ApplyInsn insn(vm.nActualArgs, loc, (Insn *)next);
465 return insn.execute(vm);
468 bool ApplyPrimitiveObj::shuffle(VM &vm, const Location &loc)
470 int nArgs = vm.nActualArgs;
471 ELObj *func = vm.sp[-nArgs];
472 for (int i = nArgs - 2; i > 0; i--)
473 vm.sp[-i - 2] = vm.sp[-i - 1];
474 vm.nActualArgs = nArgs - 2;
475 ELObj *list = *--vm.sp;
477 while (!list->isNil()) {
478 PairObj *tem = list->asPair();
480 vm.interp->setNextLocation(loc);
481 vm.interp->message(InterpreterMessages::notAList,
482 StringMessageArg(vm.interp->makeStringC("apply")),
483 OrdinalMessageArg(nArgs),
484 ELObjMessageArg(list, *vm.interp));
490 *vm.sp++ = tem->car();
498 const Insn *ApplyPrimitiveObj::tailCall(VM &vm, const Location &loc,
501 if (!shuffle(vm, loc))
503 TailApplyInsn insn(nCallerArgs, vm.nActualArgs, loc);
504 return insn.execute(vm);
507 PrimitiveCallInsn::PrimitiveCallInsn(int nArgs, PrimitiveObj *prim,
510 : nArgs_(nArgs), prim_(prim), loc_(loc), next_(next)
514 const Insn *PrimitiveCallInsn::execute(VM &vm) const
518 ELObj **argp = vm.sp - nArgs_;
519 *argp = prim_->primitiveCall(nArgs_, argp, vm, *vm.interp, loc_);
520 ASSERT(vm.interp->objectMaybeLive(*argp));
522 if (vm.interp->isError(*argp)) {
527 return next_.pointer();
530 InsnPtr FunctionObj::makeCallInsn(int nArgs, Interpreter &,
534 return new FunctionCallInsn(nArgs, this, loc, next);
537 InsnPtr FunctionObj::makeTailCallInsn(int nArgs, Interpreter &,
538 const Location &loc, int nCallerArgs)
540 return new FunctionTailCallInsn(nArgs, this, loc, nCallerArgs);
543 FunctionObj *FunctionObj::asFunction()
548 void FunctionObj::setArgToCC(VM &)
552 const Insn *PrimitiveObj::call(VM &vm, const Location &loc,
555 if (vm.nActualArgs == 0)
557 ELObj **argp = vm.sp - vm.nActualArgs;
558 *argp = primitiveCall(vm.nActualArgs, argp, vm, *vm.interp, loc);
560 if (vm.interp->isError(*argp)) {
568 const Insn *PrimitiveObj::tailCall(VM &vm, const Location &loc,
571 ELObj **argp = vm.sp - vm.nActualArgs;
572 ELObj *result = primitiveCall(vm.nActualArgs, argp, vm, *vm.interp, loc);
573 if (vm.interp->isError(result)) {
578 vm.sp = argp - nCallerArgs;
579 const Insn *next = vm.popFrame();
586 InsnPtr PrimitiveObj::makeCallInsn(int nArgs, Interpreter &interp, const Location &loc,
589 return new PrimitiveCallInsn(nArgs, this, loc, next);
592 ELObj *PrimitiveObj::argError(Interpreter &interp,
594 const MessageType3 &msg,
598 NodeListObj *nl = obj->asNodeList();
599 if (!nl || !nl->suppressError()) {
600 interp.setNextLocation(loc);
602 StringMessageArg(ident_->name()),
603 OrdinalMessageArg(index + 1),
604 ELObjMessageArg(obj, interp));
606 return interp.makeError();
609 ELObj *PrimitiveObj::noCurrentNodeError(Interpreter &interp,
610 const Location &loc) const
612 interp.setNextLocation(loc);
613 interp.message(InterpreterMessages::noCurrentNode);
614 return interp.makeError();
617 ClosureInsn::ClosureInsn(const Signature *sig, InsnPtr code, int displayLength,
619 : sig_(sig), code_(code), displayLength_(displayLength), next_(next)
623 const Insn *ClosureInsn::execute(VM &vm) const
626 = displayLength_ ? new ELObj *[displayLength_ + 1] : 0;
627 ELObj **tem = vm.sp - displayLength_;
628 for (int i = 0; i < displayLength_; i++)
630 if (displayLength_ == 0) {
635 display[displayLength_] = 0;
636 // Make sure objects in display are still visible on the stack
637 // to the garbage collector.
638 *tem++ = new (*vm.interp) ClosureObj(sig_, code_, display);
640 return next_.pointer();
643 FunctionCallInsn:: FunctionCallInsn(int nArgs, FunctionObj *function,
644 const Location &loc, InsnPtr next)
645 : nArgs_(nArgs), function_(function), loc_(loc), next_(next)
649 const Insn *FunctionCallInsn::execute(VM &vm) const
651 vm.nActualArgs = nArgs_;
652 return function_->call(vm, loc_, next_.pointer());
655 FunctionTailCallInsn:: FunctionTailCallInsn(int nArgs, FunctionObj *function,
658 : nArgs_(nArgs), function_(function), loc_(loc), nCallerArgs_(nCallerArgs)
662 const Insn *FunctionTailCallInsn::execute(VM &vm) const
664 vm.nActualArgs = nArgs_;
665 return function_->tailCall(vm, loc_, nCallerArgs_);
668 TestNullInsn::TestNullInsn(int offset, InsnPtr ifNull, InsnPtr ifNotNull)
669 : offset_(offset), ifNull_(ifNull), ifNotNull_(ifNotNull)
673 const Insn *TestNullInsn::execute(VM &vm) const
675 if (vm.sp[offset_] == 0)
676 return ifNull_.pointer();
678 return ifNotNull_.pointer();
681 VarargsInsn::VarargsInsn(const Signature &sig,
682 Vector<InsnPtr> &entryPoints,
684 : sig_(&sig), loc_(loc)
686 entryPoints.swap(entryPoints_);
689 const Insn *VarargsInsn::execute(VM &vm) const
691 int n = vm.nActualArgs - sig_->nRequiredArgs;
692 if ((sig_->restArg || sig_->nKeyArgs)
693 && n > entryPoints_.size() - 2) {
694 // cons up the rest args
695 ELObjDynamicRoot protect(*vm.interp, vm.interp->makeNil());
696 for (int i = n - (entryPoints_.size() - 2); i > 0; i--) {
697 protect = new (*vm.interp) PairObj(vm.sp[-1], protect);
700 vm.needStack(sig_->nKeyArgs + sig_->restArg);
703 if (sig_->nKeyArgs) {
704 for (int i = 0; i < sig_->nKeyArgs; i++)
706 ELObj *tem = protect;
707 for (int i = n - (entryPoints_.size() - 2); i > 0; i -= 2) {
708 KeywordObj *k = ((PairObj *)tem)->car()->asKeyword();
709 tem = ((PairObj *)tem)->cdr();
711 for (int j = 0; j < sig_->nKeyArgs; j++)
712 if (sig_->keys[j] == k->identifier()) {
714 vm.sp[j] = ((PairObj *)tem)->car();
718 if (k && !sig_->restArg) {
719 vm.interp->setNextLocation(loc_);
720 vm.interp->message(InterpreterMessages::invalidKeyArg,
721 StringMessageArg(k->identifier()->name()));
725 vm.interp->setNextLocation(loc_);
726 vm.interp->message(InterpreterMessages::keyArgsNotKey);
728 tem = ((PairObj *)tem)->cdr();
730 vm.sp += sig_->nKeyArgs;
732 return entryPoints_.back().pointer();
734 return entryPoints_[n].pointer();
737 SetKeyArgInsn::SetKeyArgInsn(int offset, InsnPtr next)
738 : offset_(offset), next_(next)
742 const Insn *SetKeyArgInsn::execute(VM &vm) const
744 ELObj *val = *--vm.sp;
745 vm.sp[offset_] = val;
746 return next_.pointer();
749 ClosureObj::ClosureObj(const Signature *sig, InsnPtr code, ELObj **display)
750 : FunctionObj(sig), code_(code), display_(display)
755 const Insn *ClosureObj::call(VM &vm, const Location &loc, const Insn *next)
758 vm.pushFrame(next, vm.nActualArgs);
759 vm.frame = vm.sp - vm.nActualArgs;
760 vm.closure = display_;
761 vm.protectClosure = this;
763 return code_.pointer();
766 const Insn *ClosureObj::tailCall(VM &vm, const Location &loc, int nCallerArgs)
769 int nArgs = vm.nActualArgs;
771 ELObj **oldFrame = vm.sp - nArgs;
772 ELObj **newFrame = oldFrame - nCallerArgs;
773 for (int i = 0; i < nArgs; i++)
774 newFrame[i] = oldFrame[i];
776 vm.sp = newFrame + nArgs;
779 vm.frame = vm.sp - nArgs;
780 vm.closure = display_;
781 vm.protectClosure = this;
783 return code_.pointer();
786 void ClosureObj::setArgToCC(VM &vm)
788 vm.setClosureArgToCC();
791 void ClosureObj::traceSubObjects(Collector &c) const
794 for (ELObj **p = display_; *p; p++)
799 const Signature ContinuationObj::signature_ = { 1, 0, 0 };
801 ContinuationObj::ContinuationObj()
802 : FunctionObj(&signature_), controlStackSize_(0)
806 const Insn *ContinuationObj::call(VM &vm, const Location &loc, const Insn *)
808 if (!live() || readOnly()) {
809 vm.interp->setNextLocation(loc);
810 vm.interp->message(InterpreterMessages::continuationDead);
814 ELObj *result = vm.sp[-1];
815 ASSERT(vm.sp - vm.sbase >= stackSize_);
816 ASSERT(vm.csp - vm.csbase >= controlStackSize_);
817 ASSERT(vm.csbase[controlStackSize_ - 1].continuation == this);
818 while (vm.csp - vm.csbase > controlStackSize_) {
820 if (vm.csp->continuation)
821 vm.csp->continuation->kill();
823 vm.sp = vm.sbase + stackSize_;
825 const Insn *next = vm.popFrame();
830 const Insn *ContinuationObj::tailCall(VM &vm, const Location &loc, int nCallerArgs)
832 return call(vm, loc, 0);
835 ReturnInsn::ReturnInsn(int totalArgs)
836 : totalArgs_(totalArgs)
840 bool ReturnInsn::isReturn(int &nArgs) const
846 const Insn *ReturnInsn::execute(VM &vm) const
848 ELObj *result = *--vm.sp;
850 const Insn *next = vm.popFrame();
855 FrameRefInsn::FrameRefInsn(int index, InsnPtr next)
856 : index_(index), next_(next)
860 const Insn *FrameRefInsn::execute(VM &vm) const
863 *vm.sp++ = vm.frame[index_];
864 return next_.pointer();
867 StackRefInsn::StackRefInsn(int index, int frameIndex, InsnPtr next)
868 : index_(index), frameIndex_(frameIndex), next_(next)
872 const Insn *StackRefInsn::execute(VM &vm) const
875 ASSERT(vm.sp - vm.frame == frameIndex_ - index_);
876 *vm.sp = vm.sp[index_];
878 return next_.pointer();
881 ClosureRefInsn::ClosureRefInsn(int index, InsnPtr next)
882 : index_(index), next_(next)
886 const Insn *ClosureRefInsn::execute(VM &vm) const
889 *vm.sp++ = vm.closure[index_];
890 return next_.pointer();
893 TopRefInsn::TopRefInsn(const Identifier *var, InsnPtr next)
894 : var_(var), next_(next)
898 const Insn *TopRefInsn::execute(VM &vm) const
900 ELObj *tem = var_->computeValue(1, *vm.interp);
901 if (vm.interp->isError(tem)) {
908 return next_.pointer();
912 ClosureSetBoxInsn::ClosureSetBoxInsn(int index, const Location &loc, InsnPtr next)
913 : index_(index), loc_(loc), next_(next)
917 const Insn *ClosureSetBoxInsn::execute(VM &vm) const
919 BoxObj *box = vm.closure[index_]->asBox();
921 if (box->readOnly()) {
922 vm.interp->setNextLocation(loc_);
923 vm.interp->message(InterpreterMessages::readOnly);
927 ELObj *tem = box->value;
928 box->value = vm.sp[-1];
930 return next_.pointer();
933 StackSetBoxInsn::StackSetBoxInsn(int index, int frameIndex, const Location &loc,
935 : index_(index), frameIndex_(frameIndex), loc_(loc), next_(next)
939 const Insn *StackSetBoxInsn::execute(VM &vm) const
941 ASSERT(vm.sp - vm.frame == frameIndex_ - index_);
942 BoxObj *box = vm.sp[index_]->asBox();
944 if (box->readOnly()) {
945 vm.interp->setNextLocation(loc_);
946 vm.interp->message(InterpreterMessages::readOnly);
950 ELObj *tem = box->value;
951 box->value = vm.sp[-1];
953 return next_.pointer();
956 StackSetInsn::StackSetInsn(int index, int frameIndex, InsnPtr next)
957 : index_(index), frameIndex_(frameIndex), next_(next)
961 const Insn *StackSetInsn::execute(VM &vm) const
963 ASSERT(vm.sp - vm.frame == frameIndex_ - index_);
964 ELObj *tem = vm.sp[index_];
965 vm.sp[index_] = vm.sp[-1];
967 return next_.pointer();
970 InsnPtr PopBindingsInsn::make(int n, InsnPtr next)
972 if (!next.isNull()) {
974 if (next->isReturn(i))
975 return new ReturnInsn(n + i);
976 if (next->isPopBindings(i, next))
977 return new PopBindingsInsn(n + i, next);
979 return new PopBindingsInsn(n, next);
982 PopBindingsInsn::PopBindingsInsn(int n, InsnPtr next)
987 const Insn *PopBindingsInsn::execute(VM &vm) const
990 vm.sp[-1] = vm.sp[n_ - 1];
991 return next_.pointer();
994 bool PopBindingsInsn::isPopBindings(int &n, InsnPtr &next) const
1001 SetBoxInsn::SetBoxInsn(int n, InsnPtr next)
1002 : n_(n), next_(next)
1006 const Insn *SetBoxInsn::execute(VM &vm) const
1009 BoxObj *box = vm.sp[-n_]->asBox();
1011 box->value = *vm.sp;
1012 return next_.pointer();
1015 SetImmediateInsn::SetImmediateInsn(int n, InsnPtr next)
1016 : n_(n), next_(next)
1020 const Insn *SetImmediateInsn::execute(VM &vm) const
1023 vm.sp[-n_] = *vm.sp;
1024 return next_.pointer();
1027 CheckInitInsn::CheckInitInsn(const Identifier *ident, const Location &loc, InsnPtr next)
1028 : ident_(ident), loc_(loc), next_(next)
1032 const Insn *CheckInitInsn::execute(VM &vm) const
1034 if (vm.sp[-1] == 0) {
1035 vm.interp->setNextLocation(loc_);
1036 vm.interp->message(InterpreterMessages::uninitializedVariableReference,
1037 StringMessageArg(ident_->name()));
1041 return next_.pointer();
1044 UnboxInsn::UnboxInsn(InsnPtr next)
1049 const Insn *UnboxInsn::execute(VM &vm) const
1051 BoxObj *box = vm.sp[-1]->asBox();
1053 vm.sp[-1] = box->value;
1054 return next_.pointer();
1057 BoxInsn::BoxInsn(InsnPtr next)
1062 const Insn *BoxInsn::execute(VM &vm) const
1064 vm.sp[-1] = new (*vm.interp) BoxObj(vm.sp[-1]);
1065 return next_.pointer();
1068 BoxArgInsn::BoxArgInsn(int n, InsnPtr next)
1069 : n_(n), next_(next)
1073 const Insn *BoxArgInsn::execute(VM &vm) const
1075 ELObj *&arg = vm.sp[n_ - vm.nActualArgs];
1076 arg = new (*vm.interp) BoxObj(arg);
1077 return next_.pointer();
1080 BoxStackInsn::BoxStackInsn(int n, InsnPtr next)
1081 : n_(n), next_(next)
1085 const Insn *BoxStackInsn::execute(VM &vm) const
1087 vm.sp[n_] = new (*vm.interp) BoxObj(vm.sp[n_]);
1088 return next_.pointer();
1091 VectorInsn::VectorInsn(size_t n, InsnPtr next)
1092 : n_(n), next_(next)
1096 const Insn *VectorInsn::execute(VM &vm) const
1100 *vm.sp++ = new (*vm.interp) VectorObj;
1103 Vector<ELObj *> v(n_);
1105 for (size_t n = n_; n > 0; n--)
1107 *p = new (*vm.interp) VectorObj(v);
1110 return next_.pointer();
1113 ListToVectorInsn::ListToVectorInsn(InsnPtr next)
1118 const Insn *ListToVectorInsn::execute(VM &vm) const
1121 ELObj *obj = vm.sp[-1];
1122 while (!obj->isNil()) {
1123 PairObj *pair = obj->asPair();
1125 v.push_back(pair->car());
1128 vm.sp[-1] = new (*vm.interp) VectorObj(v);
1129 return next_.pointer();
1132 const Insn *CheckSosofoInsn::execute(VM &vm) const
1134 if (!vm.sp[-1]->asSosofo()) {
1136 vm.interp->setNextLocation(loc_);
1137 vm.interp->message(InterpreterMessages::sosofoContext);
1140 return next_.pointer();
1143 const Insn *CheckStyleInsn::execute(VM &vm) const
1145 if (!vm.sp[-1]->asStyle()) {
1147 vm.interp->setNextLocation(loc_);
1148 vm.interp->message(InterpreterMessages::styleContext);
1151 return next_.pointer();
1154 const Insn *PushModeInsn::execute(VM &vm) const
1156 vm.modeStack.push_back(vm.processingMode);
1157 vm.processingMode = mode_;
1158 return next_.pointer();
1161 const Insn *PopModeInsn::execute(VM &vm) const
1163 vm.processingMode = vm.modeStack.back();
1164 vm.modeStack.resize(vm.modeStack.size() - 1);
1165 return next_.pointer();
1168 MaybeOverrideStyleInsn::MaybeOverrideStyleInsn(InsnPtr next)
1173 const Insn *MaybeOverrideStyleInsn::execute(VM &vm) const
1175 if (vm.overridingStyle)
1176 vm.sp[-1] = new (*vm.interp) OverriddenStyleObj((BasicStyleObj *)vm.sp[-1],
1177 vm.overridingStyle);
1178 return next_.pointer();
1181 VarStyleInsn::VarStyleInsn(const ConstPtr<StyleSpec> &styleSpec, unsigned displayLength,
1182 bool hasUse, InsnPtr next)
1183 : styleSpec_(styleSpec), displayLength_(displayLength), hasUse_(hasUse), next_(next)
1187 const Insn *VarStyleInsn::execute(VM &vm) const
1190 = displayLength_ ? new ELObj *[displayLength_ + 1] : 0;
1191 ELObj **tem = vm.sp - displayLength_;
1192 for (int i = 0; i < displayLength_; i++)
1193 display[i] = tem[i];
1194 if (displayLength_ == 0) {
1199 display[displayLength_] = 0;
1200 // Make sure objects in display are still visible on the stack
1201 // to the garbage collector.
1204 use = (StyleObj *)*--tem;
1207 *tem++ = new (*vm.interp) VarStyleObj(styleSpec_, use, display, vm.currentNode);
1209 vm.interp->makeReadOnly(tem[-1]);
1210 return next_.pointer();
1213 SetStyleInsn::SetStyleInsn(InsnPtr next)
1218 const Insn *SetStyleInsn::execute(VM &vm) const
1220 ((FlowObj *)vm.sp[-2])->setStyle((StyleObj *)vm.sp[-1]);
1222 return next_.pointer();
1225 SosofoAppendInsn::SosofoAppendInsn(size_t n, InsnPtr next)
1226 : n_(n), next_(next)
1230 const Insn *SosofoAppendInsn::execute(VM &vm) const
1232 AppendSosofoObj *obj = new (*vm.interp) AppendSosofoObj;
1233 ELObj **tem = vm.sp - n_;
1234 for (size_t i = 0; i < n_; i++) {
1235 ASSERT(tem[i]->asSosofo() != 0);
1236 obj->append((SosofoObj *)tem[i]);
1240 return next_.pointer();
1243 CopyFlowObjInsn::CopyFlowObjInsn(FlowObj *flowObj, InsnPtr next)
1244 : flowObj_(flowObj), next_(next)
1248 const Insn *CopyFlowObjInsn::execute(VM &vm) const
1251 *vm.sp++ = flowObj_->copy(*vm.interp);
1252 return next_.pointer();
1255 SetNonInheritedCsSosofoInsn
1256 ::SetNonInheritedCsSosofoInsn(InsnPtr code, int displayLength, InsnPtr next)
1257 : code_(code), displayLength_(displayLength), next_(next)
1261 const Insn *SetNonInheritedCsSosofoInsn::execute(VM &vm) const
1264 = displayLength_ ? new ELObj *[displayLength_ + 1] : 0;
1265 ELObj **tem = vm.sp - displayLength_;
1266 for (int i = 0; i < displayLength_; i++) {
1267 display[i] = tem[i];
1268 ASSERT(display[i] != 0);
1271 display[displayLength_] = 0;
1272 // Make sure objects in display are still visible on the stack
1273 // to the garbage collector.
1274 FlowObj *flowObj = (FlowObj *)*--tem;
1275 ASSERT((*tem)->asSosofo() != 0);
1276 *tem++ = new (*vm.interp) SetNonInheritedCsSosofoObj(flowObj, code_, display, vm.currentNode);
1278 return next_.pointer();
1282 SetPseudoNonInheritedCInsn::SetPseudoNonInheritedCInsn(const Identifier *nic, const Location &loc,
1284 : nic_(nic), loc_(loc), next_(next)
1288 const Insn *SetPseudoNonInheritedCInsn::execute(VM &vm) const
1290 ASSERT(vm.sp[-2]->asSosofo() != 0);
1291 ((FlowObj *)vm.sp[-2])->setNonInheritedC(nic_, vm.sp[-1], loc_, *vm.interp);
1293 return next_.pointer();
1296 SetNonInheritedCInsn::SetNonInheritedCInsn(const Identifier *nic, const Location &loc,
1298 : SetPseudoNonInheritedCInsn(nic, loc, next)
1302 const Insn *SetNonInheritedCInsn::execute(VM &vm) const
1304 vm.actualDependencies->resize(0);
1305 return SetPseudoNonInheritedCInsn::execute(vm);
1308 SetContentInsn::SetContentInsn(const CompoundFlowObj *flowObj, InsnPtr next)
1309 : flowObj_(flowObj), next_(next)
1313 SetImplicitCharInsn::SetImplicitCharInsn(const Location &loc, InsnPtr next)
1314 : loc_(loc), next_(next)
1318 const Insn *SetImplicitCharInsn::execute(VM &vm) const
1320 ASSERT(vm.sp[-1]->asSosofo() != 0);
1322 if (vm.currentNode) {
1323 ELObjPropertyValue value(*vm.interp, 0);
1324 AccessResult ret = vm.currentNode->property(ComponentName::idChar, *vm.interp, value);
1325 if (ret == accessOK)
1326 ((FlowObj *)vm.sp[-1])->setImplicitChar(value.obj, loc_, *vm.interp);
1328 return next_.pointer();
1331 const Insn *SetContentInsn::execute(VM &vm) const
1333 CompoundFlowObj *copy = (CompoundFlowObj *)flowObj_->copy(*vm.interp);
1334 copy->setContent((SosofoObj *)vm.sp[-1]);
1336 return next_.pointer();
1339 SetDefaultContentInsn::SetDefaultContentInsn(const CompoundFlowObj *flowObj, const Location &loc, InsnPtr next)
1340 : flowObj_(flowObj), next_(next), loc_(loc)
1344 const Insn *SetDefaultContentInsn::execute(VM &vm) const
1346 if (!vm.processingMode) {
1347 vm.interp->setNextLocation(loc_);
1348 vm.interp->message(InterpreterMessages::noCurrentProcessingMode);
1353 *vm.sp++ = flowObj_->copy(*vm.interp);
1354 ((CompoundFlowObj *)vm.sp[-1])
1355 ->setContent(new (*vm.interp) ProcessChildrenSosofoObj(vm.processingMode));
1356 return next_.pointer();
1359 MakeDefaultContentInsn::MakeDefaultContentInsn(const Location &loc, InsnPtr next)
1360 : next_(next), loc_(loc)
1364 const Insn *MakeDefaultContentInsn::execute(VM &vm) const
1366 if (!vm.processingMode) {
1367 vm.interp->setNextLocation(loc_);
1368 vm.interp->message(InterpreterMessages::noCurrentProcessingMode);
1373 *vm.sp++ = new (*vm.interp) ProcessChildrenSosofoObj(vm.processingMode);
1374 return next_.pointer();
1377 LabelSosofoInsn::LabelSosofoInsn(const Location &loc, InsnPtr next)
1378 : loc_(loc), next_(next)
1382 const Insn *LabelSosofoInsn::execute(VM &vm) const
1384 SymbolObj *sym = vm.sp[-1]->asSymbol();
1386 vm.interp->setNextLocation(loc_);
1387 vm.interp->message(InterpreterMessages::labelNotASymbol);
1391 ASSERT(vm.sp[-2]->asSosofo() != 0);
1392 vm.sp[-2] = new (*vm.interp) LabelSosofoObj(sym, loc_, (SosofoObj *)vm.sp[-2]);
1394 return next_.pointer();
1397 ContentMapSosofoInsn::ContentMapSosofoInsn(const Location &loc, InsnPtr next)
1398 : loc_(loc), next_(next)
1402 const Insn *ContentMapSosofoInsn::execute(VM &vm) const
1404 ASSERT(vm.sp[-2]->asSosofo() != 0);
1405 vm.sp[-2] = new (*vm.interp) ContentMapSosofoObj(vm.sp[-1], &loc_, (SosofoObj *)vm.sp[-2]);
1407 return next_.pointer();
1416 BoxObj::BoxObj(ELObj *obj)
1422 BoxObj *BoxObj::asBox()
1427 void BoxObj::traceSubObjects(Collector &c) const
1432 CallWithCurrentContinuationPrimitiveObj::CallWithCurrentContinuationPrimitiveObj()
1433 : FunctionObj(&signature_)
1437 const Insn *CallWithCurrentContinuationPrimitiveObj::call(VM &vm, const Location &loc,
1440 FunctionObj *f = vm.sp[-1]->asFunction();
1442 vm.interp->setNextLocation(loc);
1443 vm.interp->message(InterpreterMessages::notAProcedure,
1444 StringMessageArg(Interpreter::makeStringC("call-with-current-continuation")),
1445 OrdinalMessageArg(1),
1446 ELObjMessageArg(vm.sp[-1], *vm.interp));
1450 ELObjDynamicRoot protect(*vm.interp, f);
1451 vm.sp[-1] = new (*vm.interp) ContinuationObj;
1452 const Insn *insn = f->call(vm, loc, next);
1458 const Insn *CallWithCurrentContinuationPrimitiveObj::tailCall(VM &vm, const Location &loc,
1461 FunctionObj *f = vm.sp[-1]->asFunction();
1463 vm.interp->setNextLocation(loc);
1464 vm.interp->message(InterpreterMessages::notAProcedure,
1465 StringMessageArg(Interpreter::makeStringC("call-with-current-continuation")),
1466 OrdinalMessageArg(1),
1467 ELObjMessageArg(vm.sp[-1], *vm.interp));
1471 ELObjDynamicRoot protect(*vm.interp, f);
1472 vm.sp[-1] = new (*vm.interp) ContinuationObj;
1473 const Insn *insn = f->tailCall(vm, loc, nCallerArgs);
1478 const Signature CallWithCurrentContinuationPrimitiveObj::signature_ = { 1, 0, 0 };
1480 #ifdef DSSSL_NAMESPACE