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