1 // Copyright (c) 1996 James Clark
2 // See the file copying.txt for copying permission.
3 
4 #include "stylelib.h"
5 #include "VM.h"
6 #include "Insn.h"
7 #include "Interpreter.h"
8 #include "InterpreterMessages.h"
9 #include "ELObjMessageArg.h"
10 #include "Expression.h"
11 #include "macros.h"
12 #include "Insn2.h"
13 #include "SosofoObj.h"
14 #include <string.h>
15 #include <stddef.h>
16 #include <stdio.h>
17 
18 #ifdef DSSSL_NAMESPACE
19 namespace DSSSL_NAMESPACE {
20 #endif
21 
22 
VM(Interpreter & interpreter)23 VM::VM(Interpreter &interpreter)
24 : Collector::DynamicRoot(interpreter), interp(&interpreter)
25 {
26   init();
27 }
28 
VM(EvalContext & context,Interpreter & interpreter)29 VM::VM(EvalContext &context, Interpreter &interpreter)
30 : EvalContext(context), Collector::DynamicRoot(interpreter), interp(&interpreter)
31 {
32   init();
33 }
34 
init()35 void VM::init()
36 {
37   slim = 0;
38   sbase = 0;
39   sp = 0;
40   closure = 0;
41   frame = 0;
42   protectClosure = 0;
43   csp = 0;
44   cslim = 0;
45   csbase = 0;
46   closureLoc.clear();
47 }
48 
~VM()49 VM::~VM()
50 {
51   delete [] sbase;
52   delete [] csbase;
53 }
54 
initStack()55 void VM::initStack()
56 {
57   sp = sbase;
58   frame = sbase;
59   csp = csbase;
60   modeStack.resize(0);
61 }
62 
growStack(int n)63 void VM::growStack(int n)
64 {
65   size_t newSize = sp - sbase;
66   if (n > newSize)
67     newSize += (n + 15) & ~15;
68   else
69     newSize += newSize;
70   ELObj **newStack = new ELObj *[newSize];
71   slim = newStack + newSize;
72   memcpy(newStack, sbase, (sp - sbase)*sizeof(ELObj *));
73   sp = newStack + (sp - sbase);
74   frame = newStack + (frame - sbase);
75   if (sbase)
76     delete [] sbase;
77   sbase = newStack;
78 }
79 
trace(Collector & c) const80 void VM::trace(Collector &c) const
81 {
82   if (sp) {
83     for (ELObj **p = sbase; p != sp; p++)
84       c.trace(*p);
85   }
86   for (ControlStackEntry *p = csbase; p != csp; p++) {
87     c.trace(p->protectClosure);
88     c.trace(p->continuation);
89   }
90   c.trace(protectClosure);
91 }
92 
pushFrame(const Insn * next,int argsPushed)93 void VM::pushFrame(const Insn *next, int argsPushed)
94 {
95   if (csp >= cslim) {
96     size_t newSize = csbase ? (cslim - csbase)*2 : 8;
97     ControlStackEntry *newBase = new ControlStackEntry[newSize];
98     cslim = newBase + newSize;
99     ControlStackEntry *newP = newBase;
100     for (const ControlStackEntry *oldP = csbase; oldP < csp; oldP++)
101       *newP++ = *oldP;
102     csp = newP;
103     if (csbase)
104       delete [] csbase;
105     csbase = newBase;
106   }
107   csp->closure = closure;
108   csp->protectClosure = protectClosure;
109   csp->next = next;
110   csp->frameSize = sp - frame - argsPushed;
111   csp->closureLoc = closureLoc;
112   csp->continuation = 0;
113   csp++;
114 }
115 
popFrame()116 const Insn *VM::popFrame()
117 {
118   ASSERT(csp > csbase);
119   --csp;
120   if (csp->continuation)
121     csp->continuation->kill();
122   closure = csp->closure;
123   protectClosure = csp->protectClosure;
124   frame = sp - csp->frameSize;
125   closureLoc = csp->closureLoc;
126   return csp->next;
127 }
128 
setClosureArgToCC()129 void VM::setClosureArgToCC()
130 {
131   ASSERT(nActualArgs == 1);
132   ContinuationObj *cc = (ContinuationObj *)sp[-1];
133   csp[-1].continuation = cc;
134   cc->set(sp - sbase, csp - csbase);
135 }
136 
eval(const Insn * insn,ELObj ** display,ELObj * arg)137 ELObj *VM::eval(const Insn *insn, ELObj **display, ELObj *arg)
138 {
139   initStack();
140   if (arg) {
141     needStack(1);
142     *sp++ = arg;
143   }
144   closure = display;
145   protectClosure = 0;
146   closureLoc.clear();
147   // The inner loop.
148   while (insn)
149     insn = insn->execute(*this);
150   ELObj *result;
151   if (sp) {
152     sp--;
153     ASSERT(sp == sbase);
154     ASSERT(csp == csbase);
155     result = *sp;
156     ASSERT(result != 0);
157   }
158   else {
159     if (interp->debugMode())
160       stackTrace();
161     result = interp->makeError();
162   }
163   return result;
164 }
165 
stackTrace()166 void VM::stackTrace()
167 {
168   unsigned long count = 0;
169   if (protectClosure) {
170     interp->setNextLocation(closureLoc);
171     interp->message(InterpreterMessages::stackTrace);
172     count++;
173   }
174   ControlStackEntry *lim = csbase;
175   if (csp != csbase && !csbase->protectClosure)
176     lim++;
177   for (ControlStackEntry *p = csp; p != lim; p--) {
178     interp->setNextLocation(p[-1].closureLoc);
179     count++;
180     if (count == 5 && p - lim > 7) {
181       interp->message(InterpreterMessages::stackTraceEllipsis,
182 		      NumberMessageArg(p - (lim + 6)));
183       p = lim + 6;
184     }
185     else
186       interp->message(InterpreterMessages::stackTrace);
187   }
188 }
189 
~Insn()190 Insn::~Insn()
191 {
192 }
193 
isReturn(int &) const194 bool Insn::isReturn(int &) const
195 {
196   return false;
197 }
198 
isPopBindings(int &,InsnPtr &) const199 bool Insn::isPopBindings(int &, InsnPtr &) const
200 {
201   return false;
202 }
203 
execute(VM & vm) const204 const Insn *ErrorInsn::execute(VM &vm) const
205 {
206   vm.sp = 0;
207   return 0;
208 }
209 
CondFailInsn(const Location & loc)210 CondFailInsn::CondFailInsn(const Location &loc)
211 : loc_(loc)
212 {
213 }
214 
execute(VM & vm) const215 const Insn *CondFailInsn::execute(VM &vm) const
216 {
217   vm.interp->setNextLocation(loc_);
218   vm.interp->message(InterpreterMessages::condFail);
219   return ErrorInsn::execute(vm);
220 }
221 
CaseFailInsn(const Location & loc)222 CaseFailInsn::CaseFailInsn(const Location &loc)
223 : loc_(loc)
224 {
225 }
226 
execute(VM & vm) const227 const Insn *CaseFailInsn::execute(VM &vm) const
228 {
229   vm.interp->setNextLocation(loc_);
230   vm.interp->message(InterpreterMessages::caseFail, ELObjMessageArg(vm.sp[-1], *vm.interp));
231   return ErrorInsn::execute(vm);
232 }
233 
ConstantInsn(ELObj * obj,InsnPtr next)234 ConstantInsn::ConstantInsn(ELObj *obj, InsnPtr next)
235 : value_(obj), next_(next)
236 {
237 }
238 
execute(VM & vm) const239 const Insn *ConstantInsn::execute(VM &vm) const
240 {
241   vm.needStack(1);
242   *vm.sp++ = value_;
243   return next_.pointer();
244 }
245 
ResolveQuantitiesInsn(const Location & loc,InsnPtr next)246 ResolveQuantitiesInsn::ResolveQuantitiesInsn(const Location &loc, InsnPtr next)
247 : loc_(loc), next_(next)
248 {
249 }
250 
execute(VM & vm) const251 const Insn *ResolveQuantitiesInsn::execute(VM &vm) const
252 {
253   ELObj *tem = vm.sp[-1]->resolveQuantities(1,
254 					    *vm.interp,
255 					    loc_);
256   ASSERT(tem != 0);
257   if (vm.interp->isError(tem)) {
258     vm.sp = 0;
259     return 0;
260   }
261   vm.sp[-1] = tem;
262   return next_.pointer();
263 }
264 
TestInsn(InsnPtr consequent,InsnPtr alternative)265 TestInsn::TestInsn(InsnPtr consequent, InsnPtr alternative)
266 : consequent_(consequent), alternative_(alternative)
267 {
268 }
269 
execute(VM & vm) const270 const Insn *TestInsn::execute(VM &vm) const
271 {
272   return (*--vm.sp)->isTrue() ? consequent_.pointer() : alternative_.pointer();
273 }
274 
OrInsn(InsnPtr nextTest,InsnPtr next)275 OrInsn::OrInsn(InsnPtr nextTest, InsnPtr next)
276 : nextTest_(nextTest), next_(next)
277 {
278 }
279 
execute(VM & vm) const280 const Insn *OrInsn::execute(VM &vm) const
281 {
282   if (vm.sp[-1]->isTrue())
283     return next_.pointer();
284   --vm.sp;
285   return nextTest_.pointer();
286 }
287 
AndInsn(InsnPtr nextTest,InsnPtr next)288 AndInsn::AndInsn(InsnPtr nextTest, InsnPtr next)
289 : nextTest_(nextTest), next_(next)
290 {
291 }
292 
execute(VM & vm) const293 const Insn *AndInsn::execute(VM &vm) const
294 {
295   if (!vm.sp[-1]->isTrue())
296     return next_.pointer();
297   --vm.sp;
298   return nextTest_.pointer();
299 }
300 
CaseInsn(ELObj * obj,InsnPtr match,InsnPtr fail)301 CaseInsn::CaseInsn(ELObj *obj, InsnPtr match, InsnPtr fail)
302 : obj_(obj), match_(match), fail_(fail)
303 {
304 }
305 
execute(VM & vm) const306 const Insn *CaseInsn::execute(VM &vm) const
307 {
308   if (ELObj::eqv(*vm.sp[-1], *obj_)) {
309     --vm.sp;
310     return match_.pointer();
311   }
312   return fail_.pointer();
313 }
314 
PopInsn(InsnPtr next)315 PopInsn::PopInsn(InsnPtr next)
316 : next_(next)
317 {
318 }
319 
execute(VM & vm) const320 const Insn *PopInsn::execute(VM &vm) const
321 {
322   --vm.sp;
323   return next_.pointer();
324 }
325 
ConsInsn(InsnPtr next)326 ConsInsn::ConsInsn(InsnPtr next)
327 : next_(next)
328 {
329 }
330 
execute(VM & vm) const331 const Insn *ConsInsn::execute(VM &vm) const
332 {
333   vm.sp[-2] = vm.interp->makePair(vm.sp[-1], vm.sp[-2]);
334   --vm.sp;
335   return next_.pointer();
336 }
337 
AppendInsn(const Location & loc,InsnPtr next)338 AppendInsn:: AppendInsn(const Location &loc, InsnPtr next)
339 : loc_(loc), next_(next)
340 {
341 }
342 
execute(VM & vm) const343 const Insn *AppendInsn::execute(VM &vm) const
344 {
345   ELObj *&source = vm.sp[-1];
346   if (!source->isNil()) {
347     PairObj *pair = source->asPair();
348     if (!pair) {
349       vm.interp->setNextLocation(loc_);
350       vm.interp->message(InterpreterMessages::spliceNotList);
351       vm.sp = 0;
352       return 0;
353     }
354     source = pair->cdr();
355     PairObj *tail = vm.interp->makePair(pair->car(), 0);
356     ELObjDynamicRoot head(*vm.interp, tail);
357     while (!source->isNil()) {
358       pair = source->asPair();
359       if (!pair) {
360 	vm.interp->setNextLocation(loc_);
361         vm.interp->message(InterpreterMessages::spliceNotList);
362 	vm.sp = 0;
363 	return 0;
364       }
365       PairObj *newTail = vm.interp->makePair(pair->car(), 0);
366       tail->setCdr(newTail);
367       tail = newTail;
368       source = pair->cdr();
369     }
370     tail->setCdr(vm.sp[-2]);
371     vm.sp[-2] = head;
372   }
373   --vm.sp;
374   return next_.pointer();
375 }
376 
ApplyBaseInsn(int nArgs,const Location & loc)377 ApplyBaseInsn::ApplyBaseInsn(int nArgs, const Location &loc)
378 : nArgs_(nArgs), loc_(loc)
379 {
380 }
381 
ApplyInsn(int nArgs,const Location & loc,InsnPtr next)382 ApplyInsn::ApplyInsn(int nArgs, const Location &loc, InsnPtr next)
383 : ApplyBaseInsn(nArgs, loc), next_(next)
384 {
385 }
386 
TailApplyInsn(int nCallerArgs,int nArgs,const Location & loc)387 TailApplyInsn::TailApplyInsn(int nCallerArgs, int nArgs, const Location &loc)
388 : ApplyBaseInsn(nArgs, loc), nCallerArgs_(nCallerArgs)
389 {
390 }
391 
392 // top of stack is operand; next down is last operand and so on
393 
decodeArgs(VM & vm) const394 FunctionObj *ApplyBaseInsn::decodeArgs(VM &vm) const
395 {
396   FunctionObj *func = (*--vm.sp)->asFunction();
397   if (!func) {
398     vm.interp->setNextLocation(loc_);
399     vm.interp->message(InterpreterMessages::callNonFunction,
400 		       ELObjMessageArg(*vm.sp, *vm.interp));
401     vm.sp = 0;
402     return 0;
403   }
404   int nReq = func->nRequiredArgs();
405   if (nArgs_ < nReq) {
406     vm.interp->setNextLocation(loc_);
407     vm.interp->message(InterpreterMessages::missingArg);
408     vm.sp = 0;
409     return 0;
410   }
411   if (nArgs_ - nReq > func->nOptionalArgs()) {
412     if (func->nKeyArgs()) {
413       // Keyword args can be specified more than once
414       // so we can only check there are an even number.
415       if ((nArgs_ - nReq - func->nOptionalArgs()) & 1) {
416 	vm.interp->setNextLocation(loc_);
417 	vm.interp->message(InterpreterMessages::oddKeyArgs);
418 	vm.sp -= (nArgs_ - nReq) - func->nOptionalArgs();
419       }
420     }
421     else if (!func->restArg()) {
422       vm.interp->setNextLocation(loc_);
423       vm.interp->message(InterpreterMessages::tooManyArgs);
424       vm.sp -= (nArgs_ - nReq) - func->nOptionalArgs();
425     }
426   }
427   return func;
428 }
429 
execute(VM & vm) const430 const Insn *ApplyInsn::execute(VM &vm) const
431 {
432   FunctionObj *func = decodeArgs(vm);
433   vm.nActualArgs = nArgs_;
434   if (func)
435     return func->call(vm, loc_, next_.pointer());
436   else
437     return 0;
438 }
439 
execute(VM & vm) const440 const Insn *TailApplyInsn::execute(VM &vm) const
441 {
442   FunctionObj *func = decodeArgs(vm);
443   vm.nActualArgs = nArgs_;
444   if (func)
445     return func->tailCall(vm, loc_, nCallerArgs_);
446   else
447     return 0;
448 }
449 
ApplyPrimitiveObj()450 ApplyPrimitiveObj::ApplyPrimitiveObj()
451 : FunctionObj(&signature_)
452 {
453 }
454 
455 const Signature ApplyPrimitiveObj::signature_ = { 2, 0, 1 };
456 
call(VM & vm,const Location & loc,const Insn * next)457 const Insn *ApplyPrimitiveObj::call(VM &vm, const Location &loc,
458 				    const Insn *next)
459 {
460   if (!shuffle(vm, loc))
461     return 0;
462   ApplyInsn insn(vm.nActualArgs, loc, (Insn *)next);
463   return insn.execute(vm);
464 }
465 
shuffle(VM & vm,const Location & loc)466 bool ApplyPrimitiveObj::shuffle(VM &vm, const Location &loc)
467 {
468   int nArgs = vm.nActualArgs;
469   ELObj *func = vm.sp[-nArgs];
470   for (int i = nArgs - 2; i > 0; i--)
471     vm.sp[-i - 2] = vm.sp[-i - 1];
472   vm.nActualArgs = nArgs - 2;
473   ELObj *list = *--vm.sp;
474   --vm.sp;
475   while (!list->isNil()) {
476     PairObj *tem = list->asPair();
477     if (!tem) {
478       vm.interp->setNextLocation(loc);
479       vm.interp->message(InterpreterMessages::notAList,
480 			 StringMessageArg(vm.interp->makeStringC("apply")),
481 			 OrdinalMessageArg(nArgs),
482 			 ELObjMessageArg(list, *vm.interp));
483       vm.sp = 0;
484       return 0;
485     }
486     vm.needStack(1);
487     vm.nActualArgs++;
488     *vm.sp++ = tem->car();
489     list = tem->cdr();
490   }
491   vm.needStack(1);
492   *vm.sp++ = func;
493   return 1;
494 }
495 
tailCall(VM & vm,const Location & loc,int nCallerArgs)496 const Insn *ApplyPrimitiveObj::tailCall(VM &vm, const Location &loc,
497 					int nCallerArgs)
498 {
499   if (!shuffle(vm, loc))
500     return 0;
501   TailApplyInsn insn(nCallerArgs, vm.nActualArgs, loc);
502   return insn.execute(vm);
503 }
504 
PrimitiveCallInsn(int nArgs,PrimitiveObj * prim,const Location & loc,InsnPtr next)505 PrimitiveCallInsn::PrimitiveCallInsn(int nArgs, PrimitiveObj *prim,
506 				     const Location &loc,
507 				     InsnPtr next)
508 : nArgs_(nArgs), prim_(prim), loc_(loc), next_(next)
509 {
510 }
511 
execute(VM & vm) const512 const Insn *PrimitiveCallInsn::execute(VM &vm) const
513 {
514   if (nArgs_ == 0)
515     vm.needStack(1);
516   ELObj **argp = vm.sp - nArgs_;
517   *argp = prim_->primitiveCall(nArgs_, argp, vm, *vm.interp, loc_);
518   ASSERT(vm.interp->objectMaybeLive(*argp));
519   vm.sp = argp + 1;
520   if (vm.interp->isError(*argp)) {
521     vm.sp = 0;
522     return 0;
523   }
524   else
525     return next_.pointer();
526 }
527 
makeCallInsn(int nArgs,Interpreter &,const Location & loc,InsnPtr next)528 InsnPtr FunctionObj::makeCallInsn(int nArgs, Interpreter &,
529 				  const Location &loc,
530 				  InsnPtr next)
531 {
532   return new FunctionCallInsn(nArgs, this, loc, next);
533 }
534 
makeTailCallInsn(int nArgs,Interpreter &,const Location & loc,int nCallerArgs)535 InsnPtr FunctionObj::makeTailCallInsn(int nArgs, Interpreter &,
536 				      const Location &loc, int nCallerArgs)
537 {
538   return new FunctionTailCallInsn(nArgs, this, loc, nCallerArgs);
539 }
540 
asFunction()541 FunctionObj *FunctionObj::asFunction()
542 {
543   return this;
544 }
545 
setArgToCC(VM &)546 void FunctionObj::setArgToCC(VM &)
547 {
548 }
549 
call(VM & vm,const Location & loc,const Insn * next)550 const Insn *PrimitiveObj::call(VM &vm, const Location &loc,
551 			       const Insn *next)
552 {
553   if (vm.nActualArgs == 0)
554     vm.needStack(1);
555   ELObj **argp = vm.sp - vm.nActualArgs;
556   *argp = primitiveCall(vm.nActualArgs, argp, vm, *vm.interp, loc);
557   vm.sp = argp + 1;
558   if (vm.interp->isError(*argp)) {
559     vm.sp = 0;
560     return 0;
561   }
562   else
563     return next;
564 }
565 
tailCall(VM & vm,const Location & loc,int nCallerArgs)566 const Insn *PrimitiveObj::tailCall(VM &vm, const Location &loc,
567 				   int nCallerArgs)
568 {
569   ELObj **argp = vm.sp - vm.nActualArgs;
570   ELObj *result = primitiveCall(vm.nActualArgs, argp, vm, *vm.interp, loc);
571   if (vm.interp->isError(result)) {
572     vm.sp = 0;
573     return 0;
574   }
575   else {
576     vm.sp = argp - nCallerArgs;
577     const Insn *next = vm.popFrame();
578     vm.needStack(1);
579     *vm.sp++ = result;
580     return next;
581   }
582 }
583 
makeCallInsn(int nArgs,Interpreter & interp,const Location & loc,InsnPtr next)584 InsnPtr PrimitiveObj::makeCallInsn(int nArgs, Interpreter &interp, const Location &loc,
585 				   InsnPtr next)
586 {
587   return new PrimitiveCallInsn(nArgs, this, loc, next);
588 }
589 
argError(Interpreter & interp,const Location & loc,const MessageType3 & msg,unsigned index,ELObj * obj) const590 ELObj *PrimitiveObj::argError(Interpreter &interp,
591 			      const Location &loc,
592 			      const MessageType3 &msg,
593 			      unsigned index,
594 			      ELObj *obj) const
595 {
596   NodeListObj *nl = obj->asNodeList();
597   if (!nl || !nl->suppressError()) {
598     interp.setNextLocation(loc);
599     interp.message(msg,
600 		   StringMessageArg(ident_->name()),
601 		   OrdinalMessageArg(index + 1),
602 		   ELObjMessageArg(obj, interp));
603   }
604   return interp.makeError();
605 }
606 
noCurrentNodeError(Interpreter & interp,const Location & loc) const607 ELObj *PrimitiveObj::noCurrentNodeError(Interpreter &interp,
608 					const Location &loc) const
609 {
610   interp.setNextLocation(loc);
611   interp.message(InterpreterMessages::noCurrentNode);
612   return interp.makeError();
613 }
614 
ClosureInsn(const Signature * sig,InsnPtr code,int displayLength,InsnPtr next)615 ClosureInsn::ClosureInsn(const Signature *sig, InsnPtr code, int displayLength,
616 			 InsnPtr next)
617 : sig_(sig), code_(code), displayLength_(displayLength), next_(next)
618 {
619 }
620 
execute(VM & vm) const621 const Insn *ClosureInsn::execute(VM &vm) const
622 {
623   ELObj **display
624     = displayLength_ ? new ELObj *[displayLength_ + 1] : 0;
625   ELObj **tem = vm.sp - displayLength_;
626   for (int i = 0; i < displayLength_; i++)
627     display[i] = tem[i];
628   if (displayLength_ == 0) {
629     vm.needStack(1);
630     tem = vm.sp;
631   }
632   else
633     display[displayLength_] = 0;
634   // Make sure objects in display are still visible on the stack
635   // to the garbage collector.
636   *tem++ = new (*vm.interp) ClosureObj(sig_, code_, display);
637   vm.sp = tem;
638   return next_.pointer();
639 }
640 
FunctionCallInsn(int nArgs,FunctionObj * function,const Location & loc,InsnPtr next)641 FunctionCallInsn:: FunctionCallInsn(int nArgs, FunctionObj *function,
642 				    const Location &loc, InsnPtr next)
643 : nArgs_(nArgs), function_(function), loc_(loc), next_(next)
644 {
645 }
646 
execute(VM & vm) const647 const Insn *FunctionCallInsn::execute(VM &vm) const
648 {
649   vm.nActualArgs = nArgs_;
650   return function_->call(vm, loc_, next_.pointer());
651 }
652 
FunctionTailCallInsn(int nArgs,FunctionObj * function,const Location & loc,int nCallerArgs)653 FunctionTailCallInsn:: FunctionTailCallInsn(int nArgs, FunctionObj *function,
654 					    const Location &loc,
655 					    int nCallerArgs)
656 : nArgs_(nArgs), function_(function), loc_(loc), nCallerArgs_(nCallerArgs)
657 {
658 }
659 
execute(VM & vm) const660 const Insn *FunctionTailCallInsn::execute(VM &vm) const
661 {
662   vm.nActualArgs = nArgs_;
663   return function_->tailCall(vm, loc_, nCallerArgs_);
664 }
665 
TestNullInsn(int offset,InsnPtr ifNull,InsnPtr ifNotNull)666 TestNullInsn::TestNullInsn(int offset, InsnPtr ifNull, InsnPtr ifNotNull)
667 : offset_(offset), ifNull_(ifNull), ifNotNull_(ifNotNull)
668 {
669 }
670 
execute(VM & vm) const671 const Insn *TestNullInsn::execute(VM &vm) const
672 {
673   if (vm.sp[offset_] == 0)
674     return ifNull_.pointer();
675   else
676     return ifNotNull_.pointer();
677 }
678 
VarargsInsn(const Signature & sig,Vector<InsnPtr> & entryPoints,const Location & loc)679 VarargsInsn::VarargsInsn(const Signature &sig,
680 			 Vector<InsnPtr> &entryPoints,
681 			 const Location &loc)
682 : sig_(&sig), loc_(loc)
683 {
684   entryPoints.swap(entryPoints_);
685 }
686 
execute(VM & vm) const687 const Insn *VarargsInsn::execute(VM &vm) const
688 {
689   int n = vm.nActualArgs - sig_->nRequiredArgs;
690   if ((sig_->restArg || sig_->nKeyArgs)
691       && n > entryPoints_.size() - 2) {
692     // cons up the rest args
693     ELObjDynamicRoot protect(*vm.interp, vm.interp->makeNil());
694     for (int i = n - (entryPoints_.size() - 2); i > 0; i--) {
695       protect = new (*vm.interp) PairObj(vm.sp[-1], protect);
696       --vm.sp;
697     }
698     vm.needStack(sig_->nKeyArgs + sig_->restArg);
699     if (sig_->restArg)
700       *vm.sp++ = protect;
701     if (sig_->nKeyArgs) {
702       for (int i = 0; i < sig_->nKeyArgs; i++)
703 	vm.sp[i] = 0;
704       ELObj *tem = protect;
705       for (int i = n - (entryPoints_.size() - 2); i > 0; i -= 2) {
706 	KeywordObj *k = ((PairObj *)tem)->car()->asKeyword();
707 	tem = ((PairObj *)tem)->cdr();
708 	if (k) {
709 	  for (int j = 0; j < sig_->nKeyArgs; j++)
710 	    if (sig_->keys[j] == k->identifier()) {
711 	      if (vm.sp[j] == 0)
712 		vm.sp[j] = ((PairObj *)tem)->car();
713 	      k = 0;
714 	      break;
715 	    }
716 	  if (k && !sig_->restArg) {
717 	    vm.interp->setNextLocation(loc_);
718 	    vm.interp->message(InterpreterMessages::invalidKeyArg,
719 			       StringMessageArg(k->identifier()->name()));
720 	  }
721 	}
722 	else {
723 	  vm.interp->setNextLocation(loc_);
724 	  vm.interp->message(InterpreterMessages::keyArgsNotKey);
725 	}
726 	tem = ((PairObj *)tem)->cdr();
727       }
728       vm.sp += sig_->nKeyArgs;
729     }
730     return entryPoints_.back().pointer();
731   }
732   return entryPoints_[n].pointer();
733 }
734 
SetKeyArgInsn(int offset,InsnPtr next)735 SetKeyArgInsn::SetKeyArgInsn(int offset, InsnPtr next)
736 : offset_(offset), next_(next)
737 {
738 }
739 
execute(VM & vm) const740 const Insn *SetKeyArgInsn::execute(VM &vm) const
741 {
742   ELObj *val = *--vm.sp;
743   vm.sp[offset_] = val;
744   return next_.pointer();
745 }
746 
ClosureObj(const Signature * sig,InsnPtr code,ELObj ** display)747 ClosureObj::ClosureObj(const Signature *sig, InsnPtr code, ELObj **display)
748 : FunctionObj(sig), code_(code), display_(display)
749 {
750   hasSubObjects_ = 1;
751 }
752 
call(VM & vm,const Location & loc,const Insn * next)753 const Insn *ClosureObj::call(VM &vm, const Location &loc, const Insn *next)
754 {
755   vm.needStack(1);
756   vm.pushFrame(next, vm.nActualArgs);
757   vm.frame = vm.sp - vm.nActualArgs;
758   vm.closure = display_;
759   vm.protectClosure = this;
760   vm.closureLoc = loc;
761   return code_.pointer();
762 }
763 
tailCall(VM & vm,const Location & loc,int nCallerArgs)764 const Insn *ClosureObj::tailCall(VM &vm, const Location &loc, int nCallerArgs)
765 {
766   vm.needStack(1);
767   int nArgs = vm.nActualArgs;
768   if (nCallerArgs) {
769     ELObj **oldFrame = vm.sp - nArgs;
770     ELObj **newFrame = oldFrame - nCallerArgs;
771     for (int i = 0; i < nArgs; i++)
772       newFrame[i] = oldFrame[i];
773     vm.frame = newFrame;
774     vm.sp = newFrame + nArgs;
775   }
776   else
777     vm.frame = vm.sp - nArgs;
778   vm.closure = display_;
779   vm.protectClosure = this;
780   vm.closureLoc = loc;
781   return code_.pointer();
782 }
783 
setArgToCC(VM & vm)784 void ClosureObj::setArgToCC(VM &vm)
785 {
786   vm.setClosureArgToCC();
787 }
788 
traceSubObjects(Collector & c) const789 void ClosureObj::traceSubObjects(Collector &c) const
790 {
791   if (display_) {
792     for (ELObj **p = display_; *p; p++)
793       c.trace(*p);
794   }
795 }
796 
797 const Signature ContinuationObj::signature_ = { 1, 0, 0 };
798 
ContinuationObj()799 ContinuationObj::ContinuationObj()
800 : FunctionObj(&signature_), controlStackSize_(0)
801 {
802 }
803 
call(VM & vm,const Location & loc,const Insn *)804 const Insn *ContinuationObj::call(VM &vm, const Location &loc, const Insn *)
805 {
806   if (!live() || readOnly()) {
807     vm.interp->setNextLocation(loc);
808     vm.interp->message(InterpreterMessages::continuationDead);
809     vm.sp = 0;
810     return 0;
811   }
812   ELObj *result = vm.sp[-1];
813   ASSERT(vm.sp - vm.sbase >= stackSize_);
814   ASSERT(vm.csp - vm.csbase >= controlStackSize_);
815   ASSERT(vm.csbase[controlStackSize_ - 1].continuation == this);
816   while (vm.csp - vm.csbase > controlStackSize_) {
817     vm.csp--;
818     if (vm.csp->continuation)
819       vm.csp->continuation->kill();
820   }
821   vm.sp = vm.sbase + stackSize_;
822   --vm.sp;
823   const Insn *next = vm.popFrame();
824   *vm.sp++ = result;
825   return next;
826 }
827 
tailCall(VM & vm,const Location & loc,int nCallerArgs)828 const Insn *ContinuationObj::tailCall(VM &vm, const Location &loc, int nCallerArgs)
829 {
830   return call(vm, loc, 0);
831 }
832 
ReturnInsn(int totalArgs)833 ReturnInsn::ReturnInsn(int totalArgs)
834 : totalArgs_(totalArgs)
835 {
836 }
837 
isReturn(int & nArgs) const838 bool ReturnInsn::isReturn(int &nArgs) const
839 {
840   nArgs = totalArgs_;
841   return true;
842 }
843 
execute(VM & vm) const844 const Insn *ReturnInsn::execute(VM &vm) const
845 {
846   ELObj *result = *--vm.sp;
847   vm.sp -= totalArgs_;
848   const Insn *next = vm.popFrame();
849   *vm.sp++ = result;
850   return next;
851 }
852 
FrameRefInsn(int index,InsnPtr next)853 FrameRefInsn::FrameRefInsn(int index, InsnPtr next)
854 : index_(index), next_(next)
855 {
856 }
857 
execute(VM & vm) const858 const Insn *FrameRefInsn::execute(VM &vm) const
859 {
860   vm.needStack(1);
861   *vm.sp++ = vm.frame[index_];
862   return next_.pointer();
863 }
864 
StackRefInsn(int index,int frameIndex,InsnPtr next)865 StackRefInsn::StackRefInsn(int index, int frameIndex, InsnPtr next)
866 : index_(index), frameIndex_(frameIndex), next_(next)
867 {
868 }
869 
execute(VM & vm) const870 const Insn *StackRefInsn::execute(VM &vm) const
871 {
872   vm.needStack(1);
873   ASSERT(vm.sp - vm.frame == frameIndex_ - index_);
874   *vm.sp = vm.sp[index_];
875   vm.sp += 1;
876   return next_.pointer();
877 }
878 
ClosureRefInsn(int index,InsnPtr next)879 ClosureRefInsn::ClosureRefInsn(int index, InsnPtr next)
880 : index_(index), next_(next)
881 {
882 }
883 
execute(VM & vm) const884 const Insn *ClosureRefInsn::execute(VM &vm) const
885 {
886   vm.needStack(1);
887   *vm.sp++ = vm.closure[index_];
888   return next_.pointer();
889 }
890 
TopRefInsn(const Identifier * var,InsnPtr next)891 TopRefInsn::TopRefInsn(const Identifier *var, InsnPtr next)
892 : var_(var), next_(next)
893 {
894 }
895 
execute(VM & vm) const896 const Insn *TopRefInsn::execute(VM &vm) const
897 {
898   ELObj *tem = var_->computeValue(1, *vm.interp);
899   if (vm.interp->isError(tem)) {
900     vm.sp = 0;
901     return 0;
902   }
903   else {
904     vm.needStack(1);
905     *vm.sp++ = tem;
906     return next_.pointer();
907   }
908 }
909 
ClosureSetBoxInsn(int index,const Location & loc,InsnPtr next)910 ClosureSetBoxInsn::ClosureSetBoxInsn(int index, const Location &loc, InsnPtr next)
911 : index_(index), loc_(loc), next_(next)
912 {
913 }
914 
execute(VM & vm) const915 const Insn *ClosureSetBoxInsn::execute(VM &vm) const
916 {
917   BoxObj *box = vm.closure[index_]->asBox();
918   ASSERT(box != 0);
919   if (box->readOnly()) {
920     vm.interp->setNextLocation(loc_);
921     vm.interp->message(InterpreterMessages::readOnly);
922     vm.sp = 0;
923     return 0;
924   }
925   ELObj *tem = box->value;
926   box->value = vm.sp[-1];
927   vm.sp[-1] = tem;
928   return next_.pointer();
929 }
930 
StackSetBoxInsn(int index,int frameIndex,const Location & loc,InsnPtr next)931 StackSetBoxInsn::StackSetBoxInsn(int index, int frameIndex, const Location &loc,
932 				 InsnPtr next)
933 : index_(index), frameIndex_(frameIndex), loc_(loc), next_(next)
934 {
935 }
936 
execute(VM & vm) const937 const Insn *StackSetBoxInsn::execute(VM &vm) const
938 {
939   ASSERT(vm.sp - vm.frame == frameIndex_ - index_);
940   BoxObj *box = vm.sp[index_]->asBox();
941   ASSERT(box != 0);
942   if (box->readOnly()) {
943     vm.interp->setNextLocation(loc_);
944     vm.interp->message(InterpreterMessages::readOnly);
945     vm.sp = 0;
946     return 0;
947   }
948   ELObj *tem = box->value;
949   box->value = vm.sp[-1];
950   vm.sp[-1] = tem;
951   return next_.pointer();
952 }
953 
StackSetInsn(int index,int frameIndex,InsnPtr next)954 StackSetInsn::StackSetInsn(int index, int frameIndex, InsnPtr next)
955 : index_(index), frameIndex_(frameIndex), next_(next)
956 {
957 }
958 
execute(VM & vm) const959 const Insn *StackSetInsn::execute(VM &vm) const
960 {
961   ASSERT(vm.sp - vm.frame == frameIndex_ - index_);
962   ELObj *tem = vm.sp[index_];
963   vm.sp[index_] = vm.sp[-1];
964   vm.sp[-1] = tem;
965   return next_.pointer();
966 }
967 
make(int n,InsnPtr next)968 InsnPtr PopBindingsInsn::make(int n, InsnPtr next)
969 {
970   if (!next.isNull()) {
971     int i;
972     if (next->isReturn(i))
973       return new ReturnInsn(n + i);
974     if (next->isPopBindings(i, next))
975       return new PopBindingsInsn(n + i, next);
976   }
977   return new PopBindingsInsn(n, next);
978 }
979 
PopBindingsInsn(int n,InsnPtr next)980 PopBindingsInsn::PopBindingsInsn(int n, InsnPtr next)
981 : n_(n), next_(next)
982 {
983 }
984 
execute(VM & vm) const985 const Insn *PopBindingsInsn::execute(VM &vm) const
986 {
987   vm.sp -= n_;
988   vm.sp[-1] = vm.sp[n_ - 1];
989   return next_.pointer();
990 }
991 
isPopBindings(int & n,InsnPtr & next) const992 bool PopBindingsInsn::isPopBindings(int &n, InsnPtr &next) const
993 {
994   n = n_;
995   next = next_;
996   return true;
997 }
998 
SetBoxInsn(int n,InsnPtr next)999 SetBoxInsn::SetBoxInsn(int n, InsnPtr next)
1000 : n_(n), next_(next)
1001 {
1002 }
1003 
execute(VM & vm) const1004 const Insn *SetBoxInsn::execute(VM &vm) const
1005 {
1006   --vm.sp;
1007   BoxObj *box = vm.sp[-n_]->asBox();
1008   ASSERT(box != 0);
1009   box->value = *vm.sp;
1010   return next_.pointer();
1011 }
1012 
SetImmediateInsn(int n,InsnPtr next)1013 SetImmediateInsn::SetImmediateInsn(int n, InsnPtr next)
1014 : n_(n), next_(next)
1015 {
1016 }
1017 
execute(VM & vm) const1018 const Insn *SetImmediateInsn::execute(VM &vm) const
1019 {
1020   --vm.sp;
1021   vm.sp[-n_] = *vm.sp;
1022   return next_.pointer();
1023 }
1024 
CheckInitInsn(const Identifier * ident,const Location & loc,InsnPtr next)1025 CheckInitInsn::CheckInitInsn(const Identifier *ident, const Location &loc, InsnPtr next)
1026 : ident_(ident), loc_(loc), next_(next)
1027 {
1028 }
1029 
execute(VM & vm) const1030 const Insn *CheckInitInsn::execute(VM &vm) const
1031 {
1032   if (vm.sp[-1] == 0) {
1033     vm.interp->setNextLocation(loc_);
1034     vm.interp->message(InterpreterMessages::uninitializedVariableReference,
1035                        StringMessageArg(ident_->name()));
1036     vm.sp = 0;
1037     return 0;
1038   }
1039   return next_.pointer();
1040 }
1041 
UnboxInsn(InsnPtr next)1042 UnboxInsn::UnboxInsn(InsnPtr next)
1043 : next_(next)
1044 {
1045 }
1046 
execute(VM & vm) const1047 const Insn *UnboxInsn::execute(VM &vm) const
1048 {
1049   BoxObj *box = vm.sp[-1]->asBox();
1050   ASSERT(box != 0);
1051   vm.sp[-1] = box->value;
1052   return next_.pointer();
1053 }
1054 
BoxInsn(InsnPtr next)1055 BoxInsn::BoxInsn(InsnPtr next)
1056 : next_(next)
1057 {
1058 }
1059 
execute(VM & vm) const1060 const Insn *BoxInsn::execute(VM &vm) const
1061 {
1062   vm.sp[-1] = new (*vm.interp) BoxObj(vm.sp[-1]);
1063   return next_.pointer();
1064 }
1065 
BoxArgInsn(int n,InsnPtr next)1066 BoxArgInsn::BoxArgInsn(int n, InsnPtr next)
1067 : n_(n), next_(next)
1068 {
1069 }
1070 
execute(VM & vm) const1071 const Insn *BoxArgInsn::execute(VM &vm) const
1072 {
1073   ELObj *&arg = vm.sp[n_ - vm.nActualArgs];
1074   arg = new (*vm.interp) BoxObj(arg);
1075   return next_.pointer();
1076 }
1077 
BoxStackInsn(int n,InsnPtr next)1078 BoxStackInsn::BoxStackInsn(int n, InsnPtr next)
1079 : n_(n), next_(next)
1080 {
1081 }
1082 
execute(VM & vm) const1083 const Insn *BoxStackInsn::execute(VM &vm) const
1084 {
1085   vm.sp[n_] = new (*vm.interp) BoxObj(vm.sp[n_]);
1086   return next_.pointer();
1087 }
1088 
VectorInsn(size_t n,InsnPtr next)1089 VectorInsn::VectorInsn(size_t n, InsnPtr next)
1090 : n_(n), next_(next)
1091 {
1092 }
1093 
execute(VM & vm) const1094 const Insn *VectorInsn::execute(VM &vm) const
1095 {
1096   if (n_ == 0) {
1097     vm.needStack(1);
1098     *vm.sp++ = new (*vm.interp) VectorObj;
1099   }
1100   else {
1101     Vector<ELObj *> v(n_);
1102     ELObj **p = vm.sp;
1103     for (size_t n = n_; n > 0; n--)
1104       v[n - 1] = *--p;
1105     *p = new (*vm.interp) VectorObj(v);
1106     vm.sp = p + 1;
1107   }
1108   return next_.pointer();
1109 }
1110 
ListToVectorInsn(InsnPtr next)1111 ListToVectorInsn::ListToVectorInsn(InsnPtr next)
1112 : next_(next)
1113 {
1114 }
1115 
execute(VM & vm) const1116 const Insn *ListToVectorInsn::execute(VM &vm) const
1117 {
1118   Vector<ELObj *> v;
1119   ELObj *obj = vm.sp[-1];
1120   while (!obj->isNil()) {
1121     PairObj *pair = obj->asPair();
1122     ASSERT(pair != 0);
1123     v.push_back(pair->car());
1124     obj = pair->cdr();
1125   }
1126   vm.sp[-1] = new (*vm.interp) VectorObj(v);
1127   return next_.pointer();
1128 }
1129 
execute(VM & vm) const1130 const Insn *CheckSosofoInsn::execute(VM &vm) const
1131 {
1132   if (!vm.sp[-1]->asSosofo()) {
1133     vm.sp = 0;
1134     vm.interp->setNextLocation(loc_);
1135     vm.interp->message(InterpreterMessages::sosofoContext);
1136     return 0;
1137   }
1138   return next_.pointer();
1139 }
1140 
execute(VM & vm) const1141 const Insn *CheckStyleInsn::execute(VM &vm) const
1142 {
1143   if (!vm.sp[-1]->asStyle()) {
1144     vm.sp = 0;
1145     vm.interp->setNextLocation(loc_);
1146     vm.interp->message(InterpreterMessages::styleContext);
1147     return 0;
1148   }
1149   return next_.pointer();
1150 }
1151 
execute(VM & vm) const1152 const Insn *PushModeInsn::execute(VM &vm) const
1153 {
1154   vm.modeStack.push_back(vm.processingMode);
1155   vm.processingMode = mode_;
1156   return next_.pointer();
1157 }
1158 
execute(VM & vm) const1159 const Insn *PopModeInsn::execute(VM &vm) const
1160 {
1161   vm.processingMode = vm.modeStack.back();
1162   vm.modeStack.resize(vm.modeStack.size() - 1);
1163   return next_.pointer();
1164 }
1165 
MaybeOverrideStyleInsn(InsnPtr next)1166 MaybeOverrideStyleInsn::MaybeOverrideStyleInsn(InsnPtr next)
1167 : next_(next)
1168 {
1169 }
1170 
execute(VM & vm) const1171 const Insn *MaybeOverrideStyleInsn::execute(VM &vm) const
1172 {
1173   if (vm.overridingStyle)
1174     vm.sp[-1] = new (*vm.interp) OverriddenStyleObj((BasicStyleObj *)vm.sp[-1],
1175 						    vm.overridingStyle);
1176   return next_.pointer();
1177 }
1178 
VarStyleInsn(const ConstPtr<StyleSpec> & styleSpec,unsigned displayLength,bool hasUse,InsnPtr next)1179 VarStyleInsn::VarStyleInsn(const ConstPtr<StyleSpec> &styleSpec, unsigned displayLength,
1180 			   bool hasUse, InsnPtr next)
1181 : styleSpec_(styleSpec), displayLength_(displayLength), hasUse_(hasUse), next_(next)
1182 {
1183 }
1184 
execute(VM & vm) const1185 const Insn *VarStyleInsn::execute(VM &vm) const
1186 {
1187   ELObj **display
1188     = displayLength_ ? new ELObj *[displayLength_ + 1] : 0;
1189   ELObj **tem = vm.sp - displayLength_;
1190   for (int i = 0; i < displayLength_; i++)
1191     display[i] = tem[i];
1192   if (displayLength_ == 0) {
1193     vm.needStack(1);
1194     tem = vm.sp;
1195   }
1196   else
1197     display[displayLength_] = 0;
1198   // Make sure objects in display are still visible on the stack
1199   // to the garbage collector.
1200   StyleObj *use;
1201   if (hasUse_)
1202     use = (StyleObj *)*--tem;
1203   else
1204     use = 0;
1205   *tem++ = new (*vm.interp) VarStyleObj(styleSpec_, use, display, vm.currentNode);
1206   vm.sp = tem;
1207   vm.interp->makeReadOnly(tem[-1]);
1208   return next_.pointer();
1209 }
1210 
SetStyleInsn(InsnPtr next)1211 SetStyleInsn::SetStyleInsn(InsnPtr next)
1212 : next_(next)
1213 {
1214 }
1215 
execute(VM & vm) const1216 const Insn *SetStyleInsn::execute(VM &vm) const
1217 {
1218   ((FlowObj *)vm.sp[-2])->setStyle((StyleObj *)vm.sp[-1]);
1219   vm.sp--;
1220   return next_.pointer();
1221 }
1222 
SosofoAppendInsn(size_t n,InsnPtr next)1223 SosofoAppendInsn::SosofoAppendInsn(size_t n, InsnPtr next)
1224 : n_(n), next_(next)
1225 {
1226 }
1227 
execute(VM & vm) const1228 const Insn *SosofoAppendInsn::execute(VM &vm) const
1229 {
1230   AppendSosofoObj *obj = new (*vm.interp) AppendSosofoObj;
1231   ELObj **tem = vm.sp - n_;
1232   for (size_t i = 0; i < n_; i++) {
1233     ASSERT(tem[i]->asSosofo() != 0);
1234     obj->append((SosofoObj *)tem[i]);
1235   }
1236   vm.sp -= n_ - 1;
1237   vm.sp[-1] = obj;
1238   return next_.pointer();
1239 }
1240 
CopyFlowObjInsn(FlowObj * flowObj,InsnPtr next)1241 CopyFlowObjInsn::CopyFlowObjInsn(FlowObj *flowObj, InsnPtr next)
1242 : flowObj_(flowObj), next_(next)
1243 {
1244 }
1245 
execute(VM & vm) const1246 const Insn *CopyFlowObjInsn::execute(VM &vm) const
1247 {
1248   vm.needStack(1);
1249   *vm.sp++ = flowObj_->copy(*vm.interp);
1250   return next_.pointer();
1251 }
1252 
1253 SetNonInheritedCsSosofoInsn
SetNonInheritedCsSosofoInsn(InsnPtr code,int displayLength,InsnPtr next)1254 ::SetNonInheritedCsSosofoInsn(InsnPtr code, int displayLength, InsnPtr next)
1255 : code_(code), displayLength_(displayLength), next_(next)
1256 {
1257 }
1258 
execute(VM & vm) const1259 const Insn *SetNonInheritedCsSosofoInsn::execute(VM &vm) const
1260 {
1261   ELObj **display
1262     = displayLength_ ? new ELObj *[displayLength_ + 1] : 0;
1263   ELObj **tem = vm.sp - displayLength_;
1264   for (int i = 0; i < displayLength_; i++) {
1265     display[i] = tem[i];
1266     ASSERT(display[i] != 0);
1267   }
1268   if (displayLength_)
1269     display[displayLength_] = 0;
1270   // Make sure objects in display are still visible on the stack
1271   // to the garbage collector.
1272   FlowObj *flowObj = (FlowObj *)*--tem;
1273   ASSERT((*tem)->asSosofo() != 0);
1274   *tem++ = new (*vm.interp) SetNonInheritedCsSosofoObj(flowObj, code_, display);
1275   vm.sp = tem;
1276   return next_.pointer();
1277 }
1278 
1279 
SetPseudoNonInheritedCInsn(const Identifier * nic,const Location & loc,InsnPtr next)1280 SetPseudoNonInheritedCInsn::SetPseudoNonInheritedCInsn(const Identifier *nic, const Location &loc,
1281 					   InsnPtr next)
1282 : nic_(nic), loc_(loc), next_(next)
1283 {
1284 }
1285 
execute(VM & vm) const1286 const Insn *SetPseudoNonInheritedCInsn::execute(VM &vm) const
1287 {
1288   ASSERT(vm.sp[-2]->asSosofo() != 0);
1289   ((FlowObj *)vm.sp[-2])->setNonInheritedC(nic_, vm.sp[-1], loc_, *vm.interp);
1290   vm.sp--;
1291   return next_.pointer();
1292 }
1293 
SetNonInheritedCInsn(const Identifier * nic,const Location & loc,InsnPtr next)1294 SetNonInheritedCInsn::SetNonInheritedCInsn(const Identifier *nic, const Location &loc,
1295 					   InsnPtr next)
1296 : SetPseudoNonInheritedCInsn(nic, loc, next)
1297 {
1298 }
1299 
execute(VM & vm) const1300 const Insn *SetNonInheritedCInsn::execute(VM &vm) const
1301 {
1302   vm.actualDependencies->resize(0);
1303   return SetPseudoNonInheritedCInsn::execute(vm);
1304 }
1305 
SetContentInsn(const CompoundFlowObj * flowObj,InsnPtr next)1306 SetContentInsn::SetContentInsn(const CompoundFlowObj *flowObj, InsnPtr next)
1307 : flowObj_(flowObj), next_(next)
1308 {
1309 }
1310 
execute(VM & vm) const1311 const Insn *SetContentInsn::execute(VM &vm) const
1312 {
1313   CompoundFlowObj *copy = (CompoundFlowObj *)flowObj_->copy(*vm.interp);
1314   copy->setContent((SosofoObj *)vm.sp[-1]);
1315   vm.sp[-1] = copy;
1316   return next_.pointer();
1317 }
1318 
SetDefaultContentInsn(const CompoundFlowObj * flowObj,const Location & loc,InsnPtr next)1319 SetDefaultContentInsn::SetDefaultContentInsn(const CompoundFlowObj *flowObj, const Location &loc, InsnPtr next)
1320 : flowObj_(flowObj), next_(next), loc_(loc)
1321 {
1322 }
1323 
execute(VM & vm) const1324 const Insn *SetDefaultContentInsn::execute(VM &vm) const
1325 {
1326   if (!vm.processingMode) {
1327     vm.interp->setNextLocation(loc_);
1328     vm.interp->message(InterpreterMessages::noCurrentProcessingMode);
1329     vm.sp = 0;
1330     return 0;
1331   }
1332   vm.needStack(1);
1333   *vm.sp++ = flowObj_->copy(*vm.interp);
1334   ((CompoundFlowObj *)vm.sp[-1])
1335     ->setContent(new (*vm.interp) ProcessChildrenSosofoObj(vm.processingMode));
1336   return next_.pointer();
1337 }
1338 
MakeDefaultContentInsn(const Location & loc,InsnPtr next)1339 MakeDefaultContentInsn::MakeDefaultContentInsn(const Location &loc, InsnPtr next)
1340 : next_(next), loc_(loc)
1341 {
1342 }
1343 
execute(VM & vm) const1344 const Insn *MakeDefaultContentInsn::execute(VM &vm) const
1345 {
1346   if (!vm.processingMode) {
1347     vm.interp->setNextLocation(loc_);
1348     vm.interp->message(InterpreterMessages::noCurrentProcessingMode);
1349     vm.sp = 0;
1350     return 0;
1351   }
1352   vm.needStack(1);
1353   *vm.sp++ = new (*vm.interp) ProcessChildrenSosofoObj(vm.processingMode);
1354   return next_.pointer();
1355 }
1356 
LabelSosofoInsn(const Location & loc,InsnPtr next)1357 LabelSosofoInsn::LabelSosofoInsn(const Location &loc, InsnPtr next)
1358 : loc_(loc), next_(next)
1359 {
1360 }
1361 
execute(VM & vm) const1362 const Insn *LabelSosofoInsn::execute(VM &vm) const
1363 {
1364   SymbolObj *sym = vm.sp[-1]->asSymbol();
1365   if (!sym) {
1366     vm.interp->setNextLocation(loc_);
1367     vm.interp->message(InterpreterMessages::labelNotASymbol);
1368     vm.sp = 0;
1369     return 0;
1370   }
1371   ASSERT(vm.sp[-2]->asSosofo() != 0);
1372   vm.sp[-2] = new (*vm.interp) LabelSosofoObj(sym, loc_, (SosofoObj *)vm.sp[-2]);
1373   vm.sp--;
1374   return next_.pointer();
1375 }
1376 
ContentMapSosofoInsn(const Location & loc,InsnPtr next)1377 ContentMapSosofoInsn::ContentMapSosofoInsn(const Location &loc, InsnPtr next)
1378 : loc_(loc), next_(next)
1379 {
1380 }
1381 
execute(VM & vm) const1382 const Insn *ContentMapSosofoInsn::execute(VM &vm) const
1383 {
1384   ASSERT(vm.sp[-2]->asSosofo() != 0);
1385   vm.sp[-2] = new (*vm.interp) ContentMapSosofoObj(vm.sp[-1], &loc_, (SosofoObj *)vm.sp[-2]);
1386   vm.sp--;
1387   return next_.pointer();
1388 }
1389 
BoxObj()1390 BoxObj::BoxObj()
1391 : value(0)
1392 {
1393   hasSubObjects_ = 1;
1394 }
1395 
BoxObj(ELObj * obj)1396 BoxObj::BoxObj(ELObj *obj)
1397 : value(obj)
1398 {
1399   hasSubObjects_ = 1;
1400 }
1401 
asBox()1402 BoxObj *BoxObj::asBox()
1403 {
1404   return this;
1405 }
1406 
traceSubObjects(Collector & c) const1407 void BoxObj::traceSubObjects(Collector &c) const
1408 {
1409   c.trace(value);
1410 }
1411 
CallWithCurrentContinuationPrimitiveObj()1412 CallWithCurrentContinuationPrimitiveObj::CallWithCurrentContinuationPrimitiveObj()
1413 : FunctionObj(&signature_)
1414 {
1415 }
1416 
call(VM & vm,const Location & loc,const Insn * next)1417 const Insn *CallWithCurrentContinuationPrimitiveObj::call(VM &vm, const Location &loc,
1418 							  const Insn *next)
1419 {
1420   FunctionObj *f = vm.sp[-1]->asFunction();
1421   if (!f) {
1422     vm.interp->setNextLocation(loc);
1423     vm.interp->message(InterpreterMessages::notAProcedure,
1424 		       StringMessageArg(Interpreter::makeStringC("call-with-current-continuation")),
1425 		       OrdinalMessageArg(1),
1426 		       ELObjMessageArg(vm.sp[-1], *vm.interp));
1427     vm.sp = 0;
1428     return 0;
1429   }
1430   ELObjDynamicRoot protect(*vm.interp, f);
1431   vm.sp[-1] = new (*vm.interp) ContinuationObj;
1432   const Insn *insn = f->call(vm, loc, next);
1433   f->setArgToCC(vm);
1434   return insn;
1435 }
1436 
1437 
tailCall(VM & vm,const Location & loc,int nCallerArgs)1438 const Insn *CallWithCurrentContinuationPrimitiveObj::tailCall(VM &vm, const Location &loc,
1439 							      int nCallerArgs)
1440 {
1441   FunctionObj *f = vm.sp[-1]->asFunction();
1442   if (!f) {
1443     vm.interp->setNextLocation(loc);
1444     vm.interp->message(InterpreterMessages::notAProcedure,
1445 		       StringMessageArg(Interpreter::makeStringC("call-with-current-continuation")),
1446 		       OrdinalMessageArg(1),
1447 		       ELObjMessageArg(vm.sp[-1], *vm.interp));
1448     vm.sp = 0;
1449     return 0;
1450   }
1451   ELObjDynamicRoot protect(*vm.interp, f);
1452   vm.sp[-1] = new (*vm.interp) ContinuationObj;
1453   const Insn *insn = f->tailCall(vm, loc, nCallerArgs);
1454   f->setArgToCC(vm);
1455   return insn;
1456 }
1457 
1458 const Signature CallWithCurrentContinuationPrimitiveObj::signature_ = { 1, 0, 0 };
1459 
1460 #ifdef DSSSL_NAMESPACE
1461 }
1462 #endif
1463