1 // Copyright (c) 1996 James Clark
2 // See the file copying.txt for copying permission.
3
4 #ifndef Insn_INCLUDED
5 #define Insn_INCLUDED 1
6
7 #include "ELObj.h"
8 #include "Resource.h"
9 #include "Ptr.h"
10 #include "Location.h"
11 #include "Message.h"
12
13 #ifdef DSSSL_NAMESPACE
14 namespace DSSSL_NAMESPACE {
15 #endif
16
17 class VM;
18 class EvalContext;
19 class Interpreter;
20
21 class Insn : public Resource {
22 public:
23 virtual ~Insn();
24 virtual const Insn *execute(VM &) const = 0;
VM(Interpreter & interpreter)25 virtual bool isReturn(int &nArgs) const;
26 virtual bool isPopBindings(int &n, ConstPtr<Insn> &) const;
27 };
28
29 typedef ConstPtr<Insn> InsnPtr;
30
VM(EvalContext & context,Interpreter & interpreter)31 class ErrorInsn : public Insn {
32 public:
33 const Insn *execute(VM &) const;
34 };
35
36 class CondFailInsn : public ErrorInsn {
init()37 public:
38 CondFailInsn(const Location &loc);
39 const Insn *execute(VM &) const;
40 private:
41 Location loc_;
42 };
43
44 class CaseFailInsn : public ErrorInsn {
45 public:
46 CaseFailInsn(const Location &loc);
47 const Insn *execute(VM &) const;
48 private:
49 Location loc_;
50 };
~VM()51
52 class ConstantInsn : public Insn {
53 public:
54 ConstantInsn(ELObj *, InsnPtr);
55 const Insn *execute(VM &) const;
56 private:
57 ELObj *value_;
58 InsnPtr next_;
59 };
60
61 class ResolveQuantitiesInsn : public Insn {
62 public:
63 ResolveQuantitiesInsn(const Location &, InsnPtr);
64 const Insn *execute(VM &) const;
growStack(int n)65 private:
66 Location loc_;
67 InsnPtr next_;
68 };
69
70 class TestInsn : public Insn {
71 public:
72 TestInsn(InsnPtr, InsnPtr);
73 const Insn *execute(VM &) const;
74 private:
75 InsnPtr consequent_;
76 InsnPtr alternative_;
77 };
78
79 class OrInsn : public Insn {
80 public:
81 OrInsn(InsnPtr nextTest, InsnPtr next);
trace(Collector & c) const82 const Insn *execute(VM &) const;
83 private:
84 InsnPtr nextTest_;
85 InsnPtr next_;
86 };
87
88 class AndInsn : public Insn {
89 public:
90 AndInsn(InsnPtr nextTest, InsnPtr next);
91 const Insn *execute(VM &) const;
92 private:
93 InsnPtr nextTest_;
94 InsnPtr next_;
pushFrame(const Insn * next,int argsPushed)95 };
96
97 class CaseInsn : public Insn {
98 public:
99 CaseInsn(ELObj *, InsnPtr match, InsnPtr fail);
100 const Insn *execute(VM &) const;
101 private:
102 ELObj *obj_;
103 InsnPtr match_;
104 InsnPtr fail_;
105 };
106
107 class PopInsn : public Insn {
108 public:
109 PopInsn(InsnPtr next);
110 const Insn *execute(VM &) const;
111 private:
112 InsnPtr next_;
113 };
114
115 class ConsInsn : public Insn {
116 public:
117 ConsInsn(InsnPtr next);
popFrame()118 const Insn *execute(VM &) const;
119 private:
120 InsnPtr next_;
121 };
122
123 class AppendInsn : public Insn {
124 public:
125 AppendInsn(const Location &, InsnPtr next);
126 const Insn *execute(VM &) const;
127 private:
128 Location loc_;
129 InsnPtr next_;
130 };
setClosureArgToCC()131
132 class ApplyBaseInsn : public Insn {
133 public:
134 ApplyBaseInsn(int nArgs, const Location &);
135 protected:
136 FunctionObj *decodeArgs(VM &) const;
137 Location loc_;
138 int nArgs_;
139 };
140
141 class ApplyInsn : public ApplyBaseInsn {
142 public:
143 ApplyInsn(int nArgs, const Location &, InsnPtr);
144 const Insn *execute(VM &) const;
145 private:
146 InsnPtr next_;
147 };
148
149 class TailApplyInsn : public ApplyBaseInsn {
150 public:
151 TailApplyInsn(int nCallerArgs, int nArgs, const Location &);
152 const Insn *execute(VM &) const;
153 private:
154 int nCallerArgs_;
155 };
156
157 class FrameRefInsn : public Insn {
158 public:
159 FrameRefInsn(int index, InsnPtr next);
160 const Insn *execute(VM &vm) const;
161 private:
162 int index_;
163 InsnPtr next_;
164 };
165
166 class StackRefInsn : public Insn {
167 public:
stackTrace()168 StackRefInsn(int index, int frameIndex, InsnPtr next);
169 const Insn *execute(VM &vm) const;
170 private:
171 int index_; // always negative
172 int frameIndex_;
173 InsnPtr next_;
174 };
175
176 class ClosureRefInsn : public Insn {
177 public:
178 ClosureRefInsn(int index, InsnPtr next);
179 const Insn *execute(VM &vm) const;
180 private:
181 int index_;
182 InsnPtr next_;
183 };
184
185 class StackSetBoxInsn : public Insn {
186 public:
187 StackSetBoxInsn(int index, int frameIndex, const Location &loc, InsnPtr next);
188 const Insn *execute(VM &vm) const;
189 private:
190 int index_; // always negative
191 int frameIndex_;
~Insn()192 Location loc_;
193 InsnPtr next_;
194 };
195
isReturn(int &) const196 class StackSetInsn : public Insn {
197 public:
198 StackSetInsn(int index, int frameIndex, InsnPtr next);
199 const Insn *execute(VM &vm) const;
200 private:
201 int index_; // always negative
202 int frameIndex_;
203 InsnPtr next_;
204 };
205
execute(VM & vm) const206 class ClosureSetBoxInsn : public Insn {
207 public:
208 ClosureSetBoxInsn(int index, const Location &loc, InsnPtr next);
209 const Insn *execute(VM &vm) const;
210 private:
211 int index_;
212 Location loc_;
213 InsnPtr next_;
214 };
215
216 class TopRefInsn : public Insn {
execute(VM & vm) const217 public:
218 TopRefInsn(const Identifier *var, InsnPtr next);
219 const Insn *execute(VM &vm) const;
220 private:
221 const Identifier *var_;
222 InsnPtr next_;
223 Location loc_;
CaseFailInsn(const Location & loc)224 };
225
226 class PopBindingsInsn : public Insn {
227 public:
228 const Insn *execute(VM &vm) const;
execute(VM & vm) const229 bool isPopBindings(int &n, InsnPtr &) const;
230 static InsnPtr make(int n, InsnPtr next);
231 private:
232 PopBindingsInsn(int n, InsnPtr next);
233 int n_;
234 InsnPtr next_;
235 };
ConstantInsn(ELObj * obj,InsnPtr next)236
237 class PrimitiveObj;
238
239 class PrimitiveCallInsn : public Insn {
240 public:
execute(VM & vm) const241 PrimitiveCallInsn(int nArgs, PrimitiveObj *, const Location &, InsnPtr);
242 const Insn *execute(VM &) const;
243 private:
244 int nArgs_;
245 PrimitiveObj *prim_;
246 Location loc_;
247 InsnPtr next_;
ResolveQuantitiesInsn(const Location & loc,InsnPtr next)248 };
249
250 struct Signature {
251 int nRequiredArgs;
252 int nOptionalArgs;
execute(VM & vm) const253 bool restArg;
254 int nKeyArgs;
255 const Identifier *const *keys;
256 };
257
258 // This Insn constructs a ClosureObj.
259
260 class ClosureInsn : public Insn {
261 public:
262 ClosureInsn(const Signature *, InsnPtr code, int displayLength, InsnPtr next);
263 const Insn *execute(VM &) const;
264 private:
265 const Signature *sig_;
266 InsnPtr code_;
TestInsn(InsnPtr consequent,InsnPtr alternative)267 int displayLength_;
268 InsnPtr next_;
269 };
270
271 class ClosureObj;
execute(VM & vm) const272
273 class FunctionCallInsn : public Insn {
274 public:
275 FunctionCallInsn(int nArgs, FunctionObj *, const Location &, InsnPtr);
276 const Insn *execute(VM &) const;
277 private:
278 int nArgs_;
279 FunctionObj *function_; // must be permanent
280 Location loc_;
281 InsnPtr next_;
282 };
283
284 class FunctionTailCallInsn : public Insn {
285 public:
286 FunctionTailCallInsn(int nArgs, FunctionObj *, const Location &,
287 int nCallerArgs);
288 const Insn *execute(VM &) const;
289 private:
AndInsn(InsnPtr nextTest,InsnPtr next)290 int nArgs_;
291 FunctionObj *function_; // must be permanent
292 Location loc_;
293 int nCallerArgs_;
294 };
execute(VM & vm) const295
296 class VarargsInsn : public Insn {
297 public:
298 VarargsInsn(const Signature &, Vector<InsnPtr> &entryPoints,
299 const Location &);
300 const Insn *execute(VM &) const;
301 private:
302 const Signature *sig_;
303 Vector<InsnPtr> entryPoints_;
304 Location loc_;
305 };
306
307 class SetKeyArgInsn : public Insn {
execute(VM & vm) const308 public:
309 SetKeyArgInsn(int offset, InsnPtr);
310 const Insn *execute(VM &) const;
311 private:
312 int offset_;
313 InsnPtr next_;
314 };
315
316 class TestNullInsn : public Insn {
PopInsn(InsnPtr next)317 public:
318 TestNullInsn(int offset, InsnPtr ifNull, InsnPtr ifNotNull);
319 const Insn *execute(VM &) const;
320 private:
321 int offset_;
execute(VM & vm) const322 InsnPtr ifNull_;
323 InsnPtr ifNotNull_;
324 InsnPtr next_;
325 };
326
327 class ReturnInsn : public Insn {
ConsInsn(InsnPtr next)328 public:
329 ReturnInsn(int totalArgs);
330 const Insn *execute(VM &) const;
331 bool isReturn(int &nArgs) const;
332 private:
execute(VM & vm) const333 int totalArgs_;
334 };
335
336 class FunctionObj : public ELObj {
337 public:
338 FunctionObj(const Signature *sig) : sig_(sig) { }
339 int totalArgs();
AppendInsn(const Location & loc,InsnPtr next)340 int nRequiredArgs();
341 int nOptionalArgs();
342 int nKeyArgs();
343 bool restArg();
344 virtual const Insn *call(VM &vm, const Location &, const Insn *next) = 0;
execute(VM & vm) const345 virtual const Insn *tailCall(VM &vm, const Location &, int nCallerArgs) = 0;
346 virtual InsnPtr makeCallInsn(int nArgs, Interpreter &, const Location &,
347 InsnPtr next);
348 virtual InsnPtr makeTailCallInsn(int nArgs, Interpreter &,
349 const Location &, int nCallerArgs);
350 const Signature &signature() const { return *sig_; }
351 FunctionObj *asFunction();
352 virtual void setArgToCC(VM &);
353 private:
354 const Signature *sig_;
355 };
356
357 class PrimitiveObj : public FunctionObj {
358 public:
359 PrimitiveObj(const Signature *sig) : FunctionObj(sig) { }
360 const Insn *call(VM &vm, const Location &, const Insn *next);
361 const Insn *tailCall(VM &vm, const Location &, int nCallerArgs);
362 InsnPtr makeCallInsn(int nArgs, Interpreter &, const Location &, InsnPtr next);
363 virtual ELObj *primitiveCall(int nArgs, ELObj **args, EvalContext &, Interpreter &,
364 const Location &) = 0;
365 void setIdentifier(const Identifier *ident);
366 protected:
367 ELObj *argError(Interpreter &, const Location &,
368 const MessageType3 &, unsigned, ELObj *) const;
369 ELObj *noCurrentNodeError(Interpreter &, const Location &) const;
370 private:
371 const Identifier *ident_;
372 };
373
374 class ApplyPrimitiveObj : public FunctionObj {
375 public:
376 ApplyPrimitiveObj();
377 const Insn *call(VM &vm, const Location &, const Insn *next);
378 const Insn *tailCall(VM &vm, const Location &, int nCallerArgs);
ApplyBaseInsn(int nArgs,const Location & loc)379 private:
380 bool shuffle(VM &vm, const Location &loc);
381 static const Signature signature_;
382 };
383
ApplyInsn(int nArgs,const Location & loc,InsnPtr next)384 class CallWithCurrentContinuationPrimitiveObj : public FunctionObj {
385 public:
386 CallWithCurrentContinuationPrimitiveObj();
387 const Insn *call(VM &vm, const Location &, const Insn *next);
388 const Insn *tailCall(VM &vm, const Location &, int nCallerArgs);
389 private:
390 static const Signature signature_;
391 };
392
393 class ClosureObj : public FunctionObj {
394 public:
395 void *operator new(size_t, Collector &c) {
decodeArgs(VM & vm) const396 return c.allocateObject(1);
397 }
398 ClosureObj(const Signature *, InsnPtr, ELObj **display);
399 ~ClosureObj() { delete [] display_; }
400 ELObj **display();
401 const Insn *call(VM &, const Location &, const Insn *);
402 const Insn *tailCall(VM &, const Location &, int nCallerArgs);
403 void traceSubObjects(Collector &) const;
404 ELObj *display(int) const;
405 void setArgToCC(VM &);
406 private:
407 InsnPtr code_;
408 // terminated by null pointer.
409 // null if empty.
410 ELObj **display_;
411 };
412
413 class ContinuationObj : public FunctionObj {
414 public:
415 ContinuationObj();
416 const Insn *call(VM &, const Location &, const Insn *);
417 const Insn *tailCall(VM &, const Location &, int nCallerArgs);
418 void set(size_t stackSize, size_t controlStackSize) {
419 stackSize_ = stackSize;
420 controlStackSize_ = controlStackSize;
421 }
422 void kill() { controlStackSize_ = 0; }
423 bool live() const { return controlStackSize_ > 0; }
424 private:
425 size_t stackSize_;
426 size_t controlStackSize_;
427 static const Signature signature_;
428 };
429
430 class BoxObj : public ELObj {
431 public:
execute(VM & vm) const432 BoxObj();
433 BoxObj(ELObj *);
434 BoxObj *asBox();
435 void traceSubObjects(Collector &) const;
436 ELObj *value;
437 };
438
439 class SetBoxInsn : public Insn {
440 public:
441 SetBoxInsn(int n, InsnPtr next);
execute(VM & vm) const442 const Insn *execute(VM &vm) const;
443 private:
444 int n_;
445 InsnPtr next_;
446 };
447
448 class SetImmediateInsn : public Insn {
449 public:
450 SetImmediateInsn(int n, InsnPtr next);
451 const Insn *execute(VM &vm) const;
ApplyPrimitiveObj()452 private:
453 int n_;
454 InsnPtr next_;
455 };
456
457 class UnboxInsn : public Insn {
458 public:
call(VM & vm,const Location & loc,const Insn * next)459 UnboxInsn(InsnPtr next);
460 const Insn *execute(VM &vm) const;
461 private:
462 InsnPtr next_;
463 };
464
465 class CheckInitInsn : public Insn {
466 public:
467 CheckInitInsn(const Identifier *ident, const Location &, InsnPtr next);
shuffle(VM & vm,const Location & loc)468 const Insn *execute(VM &vm) const;
469 private:
470 const Identifier *ident_;
471 Location loc_;
472 InsnPtr next_;
473 };
474
475 class BoxInsn : public Insn {
476 public:
477 BoxInsn(InsnPtr next);
478 const Insn *execute(VM &vm) const;
479 private:
480 InsnPtr next_;
481 };
482
483 class BoxArgInsn : public Insn {
484 public:
485 BoxArgInsn(int n, InsnPtr next);
486 const Insn *execute(VM &vm) const;
487 private:
488 int n_;
489 InsnPtr next_;
490 };
491
492 class BoxStackInsn : public Insn {
493 public:
494 BoxStackInsn(int n, InsnPtr next);
495 const Insn *execute(VM &vm) const;
496 private:
497 int n_;
tailCall(VM & vm,const Location & loc,int nCallerArgs)498 InsnPtr next_;
499 };
500
501 class VectorInsn : public Insn {
502 public:
503 VectorInsn(size_t n, InsnPtr next);
504 const Insn *execute(VM &vm) const;
505 private:
506 size_t n_;
PrimitiveCallInsn(int nArgs,PrimitiveObj * prim,const Location & loc,InsnPtr next)507 InsnPtr next_;
508 };
509
510 class ListToVectorInsn : public Insn {
511 public:
512 ListToVectorInsn(InsnPtr next);
513 const Insn *execute(VM &vm) const;
execute(VM & vm) const514 private:
515 InsnPtr next_;
516 };
517
518 inline
519 int FunctionObj::nRequiredArgs()
520 {
521 return signature().nRequiredArgs;
522 }
523
524 inline
525 int FunctionObj::nOptionalArgs()
526 {
527 return signature().nOptionalArgs;
528 }
529
makeCallInsn(int nArgs,Interpreter &,const Location & loc,InsnPtr next)530 inline
531 bool FunctionObj::restArg()
532 {
533 return signature().restArg;
534 }
535
536 inline
makeTailCallInsn(int nArgs,Interpreter &,const Location & loc,int nCallerArgs)537 int FunctionObj::nKeyArgs()
538 {
539 return signature().nKeyArgs;
540 }
541
542 inline
asFunction()543 int FunctionObj::totalArgs()
544 {
545 const Signature &sig = signature();
546 return sig.nRequiredArgs + sig.nOptionalArgs + sig.nKeyArgs + sig.restArg;
547 }
setArgToCC(VM &)548
549 inline
550 void PrimitiveObj::setIdentifier(const Identifier *ident)
551 {
552 ident_ = ident;
553 }
554
555 inline
556 ELObj *ClosureObj::display(int i) const
557 {
558 return display_[i];
559 }
560
561 #ifdef DSSSL_NAMESPACE
562 }
563 #endif
564
565 #endif /* not Insn_INCLUDED */
566