cfad47cfa3/t3compiler/tads3/tct3drv.h

4b825dc642cb6eb9a060e54bf8d69288fbee4904cfad47cfa334b206c65f22086bcc5d63e6f70944
1
/* $Header: d:/cvsroot/tads/tads3/TCT3DRV.H,v 1.4 1999/07/11 00:46:57 MJRoberts Exp $ */
2
3
/* 
4
 *   Copyright (c) 1999, 2002 Michael J. Roberts.  All Rights Reserved.
5
 *   
6
 *   Please see the accompanying license file, LICENSE.TXT, for information
7
 *   on using and copying this software.  
8
 */
9
/*
10
Name
11
  tct3drv.h - derived final T3-specific parse node classes
12
Function
13
  
14
Notes
15
  
16
Modified
17
  05/10/99 MJRoberts  - Creation
18
*/
19
20
#ifndef TCT3DRV_H
21
#define TCT3DRV_H
22
23
#include <assert.h>
24
25
/* include our T3-specific intermediate classes */
26
#include "tct3int.h"
27
28
/* include the target-independent derived classes */
29
#include "tcpndrv.h"
30
31
32
/* ------------------------------------------------------------------------ */
33
/*
34
 *   "self" 
35
 */
36
class CTPNSelf: public CTPNSelfBase
37
{
38
public:
39
    /* generate code */
40
    void gen_code(int discard, int for_condition);
41
42
    /* generate a member expression */
43
    void gen_code_member(int discard,
44
                         class CTcPrsNode *prop_expr, int prop_is_expr,
45
                         int argc, int varargs);
46
47
    /* get the object value for a '.' expression */
48
    vm_obj_id_t gen_code_obj_predot(int *is_self);
49
};
50
51
/* ------------------------------------------------------------------------ */
52
/*
53
 *   "replaced" 
54
 */
55
class CTPNReplaced: public CTPNReplacedBase
56
{
57
public:
58
    /* generate code */
59
    void gen_code(int discard, int for_condition);
60
61
    /* generate a function call expression */
62
    void gen_code_call(int discard, int argc, int varargs);
63
};
64
65
/* ------------------------------------------------------------------------ */
66
/*
67
 *   "targetprop" 
68
 */
69
class CTPNTargetprop: public CTPNTargetpropBase
70
{
71
public:
72
    /* generate code */
73
    void gen_code(int discard, int for_condition);
74
};
75
76
77
/* ------------------------------------------------------------------------ */
78
/*
79
 *   "targetobj" 
80
 */
81
class CTPNTargetobj: public CTPNTargetobjBase
82
{
83
public:
84
    /* generate code */
85
    void gen_code(int discard, int for_condition);
86
};
87
88
/* ------------------------------------------------------------------------ */
89
/*
90
 *   "definingobj" 
91
 */
92
class CTPNDefiningobj: public CTPNDefiningobjBase
93
{
94
public:
95
    /* generate code */
96
    void gen_code(int discard, int for_condition);
97
};
98
99
100
/* ------------------------------------------------------------------------ */
101
/*
102
 *   "inherited" 
103
 */
104
class CTPNInh: public CTPNInhBase
105
{
106
public:
107
    /* generate code */
108
    void gen_code(int discard, int for_condition);
109
110
    /* generate a member expression */
111
    void gen_code_member(int discard,
112
                         class CTcPrsNode *prop_expr, int prop_is_expr,
113
                         int argc, int varargs);
114
115
protected:
116
    /* generate a multi-method inherited() call */
117
    void gen_code_mminh(CTcSymFunc *func, int discard,
118
                        class CTcPrsNode *prop_expr, int prop_is_expr,
119
                        int argc, int varargs);
120
};
121
122
/*
123
 *   "inherited" with explicit superclass 
124
 */
125
class CTPNInhClass: public CTPNInhClassBase
126
{
127
public:
128
    CTPNInhClass(const char *sym, size_t len)
129
        : CTPNInhClassBase(sym, len) { }
130
131
    /* generate code */
132
    void gen_code(int discard, int for_condition);
133
134
    /* generate a member expression */
135
    void gen_code_member(int discard,
136
                         class CTcPrsNode *prop_expr, int prop_is_expr,
137
                         int argc, int varargs);
138
};
139
140
/*
141
 *   "delegated" 
142
 */
143
class CTPNDelegated: public CTPNDelegatedBase
144
{
145
public:
146
    CTPNDelegated(CTcPrsNode *delegatee)
147
        : CTPNDelegatedBase(delegatee) { }
148
149
    /* generate code */
150
    void gen_code(int discard, int for_condition);
151
152
    /* generate a member expression */
153
    void gen_code_member(int discard,
154
                         class CTcPrsNode *prop_expr, int prop_is_expr,
155
                         int argc, int varargs);
156
};
157
158
/* ------------------------------------------------------------------------ */
159
/*
160
 *   "argcount" node 
161
 */
162
class CTPNArgc: public CTPNArgcBase
163
{
164
public:
165
    void gen_code(int discard, int for_condition);
166
};
167
168
169
/* ------------------------------------------------------------------------ */
170
/* 
171
 *   constant node 
172
 */
173
class CTPNConst: public CTPNConstBase
174
{
175
public:
176
    CTPNConst(CTcConstVal *val) : CTPNConstBase(val) { }
177
178
    /* generate code for the constant */
179
    void gen_code(int discard, int for_condition);
180
181
    /* generate code for operator 'new' applied to this expression */
182
    void gen_code_new(int discard, int argc, int varargs, int from_call,
183
                      int is_transient);
184
185
    /* evaluate a property ID */
186
    vm_prop_id_t gen_code_propid(int check_only, int is_expr);
187
188
    /* generate a member expression */
189
    void gen_code_member(int discard,
190
                         class CTcPrsNode *prop_expr, int prop_is_expr,
191
                         int argc, int varargs);
192
193
    /* generate a function call expression */
194
    void gen_code_call(int discard, int argc, int varargs);
195
196
    /* get the object value for a '.' expression */
197
    vm_obj_id_t gen_code_obj_predot(int *is_self);
198
199
    /* generate code to push an integer constant */
200
    static void s_gen_code_int(long intval);
201
};
202
203
/*
204
 *   Debugger constant node 
205
 */
206
class CTPNDebugConst: public CTPNConst
207
{
208
public:
209
    CTPNDebugConst(CTcConstVal *val) : CTPNConst(val) { }
210
211
    /* generate code for the constant */
212
    void gen_code(int discard, int for_condition);
213
};
214
215
/* ------------------------------------------------------------------------ */
216
/*
217
 *   Unary Operators 
218
 */
219
220
/* bitwise NOT */
221
CTPNUnary_def(CTPNBNot);
222
223
/* arithmetic positive */
224
CTPNUnary_def(CTPNPos);
225
226
/* arithmetic negative */
227
CTPNUnary_def(CTPNNeg);
228
229
/* pre-increment */
230
CTPNUnary_side_def(CTPNPreInc);
231
232
/* pre-decrement */
233
CTPNUnary_side_def(CTPNPreDec);
234
235
/* post-increment */
236
CTPNUnary_side_def(CTPNPostInc);
237
238
/* post-decrement */
239
CTPNUnary_side_def(CTPNPostDec);
240
241
/* delete */
242
CTPNUnary_side_def(CTPNDelete);
243
244
/* boolean-ize */
245
CTPNUnary_def(CTPNBoolize);
246
247
/* ------------------------------------------------------------------------ */
248
/*
249
 *   NEW operator 
250
 */
251
class CTPNNew: public CTPNUnary
252
{ 
253
public:
254
    CTPNNew(class CTcPrsNode *sub, int is_transient)
255
        : CTPNUnary(sub)
256
    {
257
        /* remember 'transient' status */
258
        transient_ = is_transient;
259
    }
260
261
    /* generate code */
262
    void gen_code(int discard, int for_condition);
263
264
    /* note that we have side effects */
265
    virtual int has_side_effects() const { return TRUE; }
266
267
protected:
268
    /* flag: it's a 'new transient' operator */
269
    int transient_;
270
};
271
272
273
/* ------------------------------------------------------------------------ */
274
/*
275
 *   NOT operator 
276
 */
277
class CTPNNot: public CTPNNotBase
278
{
279
public:
280
    CTPNNot(CTcPrsNode *sub) : CTPNNotBase(sub) { }
281
282
    /* generate code */
283
    void gen_code(int discard, int for_condition);
284
};
285
286
287
/* ------------------------------------------------------------------------ */
288
/* 
289
 *   Binary Operators 
290
 */
291
292
class CTPNComma: public CTPNCommaBase
293
{
294
public:
295
    CTPNComma(class CTcPrsNode *lhs, CTcPrsNode *rhs)
296
        : CTPNCommaBase(lhs, rhs) { }
297
298
    /* generate code */
299
    void gen_code(int discard, int for_condition);
300
};
301
302
/* bitwise OR */
303
CTPNBin_def(CTPNBOr);
304
305
/* bitwise AND */
306
CTPNBin_def(CTPNBAnd);
307
308
/* bitwise XOR */
309
CTPNBin_def(CTPNBXor);
310
311
/* greater than */
312
CTPNBin_def(CTPNGt);
313
314
/* greater or equal */
315
CTPNBin_def(CTPNGe);
316
317
/* less than */
318
CTPNBin_def(CTPNLt);
319
320
/* less or equal */
321
CTPNBin_def(CTPNLe);
322
323
/* bit shift left */
324
CTPNBin_def(CTPNShl);
325
326
/* bit shift right */
327
CTPNBin_def(CTPNShr);
328
329
/* multiply */
330
CTPNBin_def(CTPNMul);
331
332
/* divide */
333
CTPNBin_def(CTPNDiv);
334
335
/* modulo */
336
CTPNBin_def(CTPNMod);
337
338
/* ------------------------------------------------------------------------ */
339
/*
340
 *   Addition 
341
 */
342
343
class CTPNAdd: public CTPNAddBase
344
{
345
public:
346
    CTPNAdd(class CTcPrsNode *left, class CTcPrsNode *right)
347
        : CTPNAddBase(left, right) { }
348
349
    /* generate code */
350
    void gen_code(int discard, int for_condition);
351
};
352
353
354
/* ------------------------------------------------------------------------ */
355
/*
356
 *   Subtraction
357
 */
358
359
class CTPNSub: public CTPNSubBase
360
{
361
public:
362
    CTPNSub(class CTcPrsNode *left, class CTcPrsNode *right)
363
        : CTPNSubBase(left, right) { }
364
365
    /* generate code */
366
    void gen_code(int discard, int for_condition);
367
};
368
369
/* ------------------------------------------------------------------------ */
370
/*
371
 *   Equality Comparison
372
 */
373
374
class CTPNEq: public CTPNEqBase
375
{
376
public:
377
    CTPNEq(class CTcPrsNode *left, class CTcPrsNode *right)
378
        : CTPNEqBase(left, right) { }
379
380
    /* generate code */
381
    void gen_code(int discard, int for_condition);
382
};
383
384
385
/* ------------------------------------------------------------------------ */
386
/*
387
 *   Inequality Comparison
388
 */
389
390
class CTPNNe: public CTPNNeBase
391
{
392
public:
393
    CTPNNe(class CTcPrsNode *left, class CTcPrsNode *right)
394
        : CTPNNeBase(left, right) { }
395
396
    /* generate code */
397
    void gen_code(int discard, int for_condition);
398
};
399
400
/* ------------------------------------------------------------------------ */
401
/*
402
 *   'is in' 
403
 */
404
405
class CTPNIsIn: public CTPNIsInBase
406
{
407
public:
408
    CTPNIsIn(class CTcPrsNode *left, class CTPNArglist *right)
409
        : CTPNIsInBase(left, right) { }
410
411
    /* generate code */
412
    void gen_code(int discard, int for_condition);
413
};
414
415
416
/* ------------------------------------------------------------------------ */
417
/*
418
 *   'not in' 
419
 */
420
421
class CTPNNotIn: public CTPNNotInBase
422
{
423
public:
424
    CTPNNotIn(class CTcPrsNode *left, class CTPNArglist *right)
425
        : CTPNNotInBase(left, right) { }
426
427
    /* generate code */
428
    void gen_code(int discard, int for_condition);
429
};
430
431
432
/* ------------------------------------------------------------------------ */
433
/*
434
 *   Logical AND (short-circuit logic)
435
 */
436
437
class CTPNAnd: public CTPNAndBase
438
{
439
public:
440
    CTPNAnd(class CTcPrsNode *left, class CTcPrsNode *right)
441
        : CTPNAndBase(left, right) { }
442
443
    /* generate code */
444
    void gen_code(int discard, int for_condition);
445
446
    /* generate a condition */
447
    virtual void gen_code_cond(struct CTcCodeLabel *then_label,
448
                               struct CTcCodeLabel *else_label);
449
};
450
451
452
/* ------------------------------------------------------------------------ */
453
/*
454
 *   Logical OR (short-circuit logic)
455
 */
456
457
class CTPNOr: public CTPNOrBase
458
{
459
public:
460
    CTPNOr(class CTcPrsNode *left, class CTcPrsNode *right)
461
        : CTPNOrBase(left, right) { }
462
463
    /* generate code */
464
    void gen_code(int discard, int for_condition);
465
466
    /* generate a condition */
467
    virtual void gen_code_cond(struct CTcCodeLabel *then_label,
468
                               struct CTcCodeLabel *else_label);
469
};
470
471
472
/* ------------------------------------------------------------------------ */
473
/*
474
 *   Assignment Operators 
475
 */
476
477
/* simple assignment */
478
class CTPNAsi: public CTPNAsiBase
479
{
480
public:
481
    CTPNAsi(class CTcPrsNode *left, class CTcPrsNode *right)
482
        : CTPNAsiBase(left, right) { }
483
484
    /* generate code */
485
    void gen_code(int discard, int for_condition);
486
};
487
488
/* add and assign */
489
CTPNBin_side_def(CTPNAddAsi);
490
491
/* subtract and assign */
492
CTPNBin_side_def(CTPNSubAsi);
493
494
/* multiple and assign */
495
CTPNBin_side_def(CTPNMulAsi);
496
497
/* divide and assign */
498
CTPNBin_side_def(CTPNDivAsi);
499
500
/* modulo and assign */
501
CTPNBin_side_def(CTPNModAsi);
502
503
/* bitwise AND and assign */
504
CTPNBin_side_def(CTPNBAndAsi);
505
506
/* bitwise OR and assign */
507
CTPNBin_side_def(CTPNBOrAsi);
508
509
/* bitwise XOR and assign */
510
CTPNBin_side_def(CTPNBXorAsi);
511
512
/* bit shift left and assign */
513
CTPNBin_side_def(CTPNShlAsi);
514
515
/* bit shift right and assign */
516
CTPNBin_side_def(CTPNShrAsi);
517
518
/* ------------------------------------------------------------------------ */
519
/*
520
 *   Array/list Subscript 
521
 */
522
class CTPNSubscript: public CTPNSubscriptBase
523
{
524
public:
525
    CTPNSubscript(CTcPrsNode *lhs, CTcPrsNode *rhs)
526
        : CTPNSubscriptBase(lhs, rhs) { }
527
528
    /* generate code */
529
    void gen_code(int discard, int for_condition);
530
531
    /* generate code to assign a value to the symbol */
532
    int gen_code_asi(int discard, tc_asitype_t typ, CTcPrsNode *rhs,
533
                     int ignore_errors);
534
};
535
536
537
/* ------------------------------------------------------------------------ */
538
/*
539
 *   Address-of Operator 
540
 */
541
542
class CTPNAddr: public CTPNAddrBase
543
{
544
public:
545
    CTPNAddr(CTcPrsNode *sub)
546
        : CTPNAddrBase(sub) { }
547
548
    /* generate code */
549
    void gen_code(int discard, int for_condition)
550
    {
551
        /* 
552
         *   if we're not discarding the value, tell the subnode to
553
         *   generate its address; if the value is being discarded, do
554
         *   nothing, since taking an address has no side effects 
555
         */
556
        if (!discard)
557
            sub_->gen_code_addr();
558
    }
559
560
    /* generate a member expression */
561
    void gen_code_member(int discard,
562
                         class CTcPrsNode *prop_expr, int prop_is_expr,
563
                         int argc, int varargs)
564
    {
565
        /* 
566
         *   let the subnode do the work, since "&obj" is the same as
567
         *   "obj" in any context 
568
         */
569
        sub_->gen_code_member(discard, prop_expr, prop_is_expr,
570
                              argc, varargs);
571
    }
572
573
    /* evaluate a property ID */
574
    vm_prop_id_t gen_code_propid(int check_only, int is_expr)
575
    {
576
        /* 
577
         *   let the subexpression handle it, so that we treat "x.&prop"
578
         *   the same as "x.prop" 
579
         */
580
        return sub_->gen_code_propid(check_only, is_expr);
581
    }
582
583
    /* get the object value for a '.' expression */
584
    vm_obj_id_t gen_code_obj_predot(int *is_self)
585
    {
586
        /* 
587
         *   let the subexpression handle it, since "x.&prop" is the same
588
         *   as "x.prop" 
589
         */
590
        return sub_->gen_code_obj_predot(is_self);
591
    }
592
};
593
594
/* ------------------------------------------------------------------------ */
595
/*
596
 *   Conditional Operator 
597
 */
598
class CTPNIf: public CTPNIfBase
599
{
600
public:
601
    CTPNIf(class CTcPrsNode *first, class CTcPrsNode *second,
602
           class CTcPrsNode *third)
603
        : CTPNIfBase(first, second, third) { }
604
605
    /* generate code for the conditional */
606
    void gen_code(int discard, int for_condition);
607
};
608
609
/* ------------------------------------------------------------------------ */
610
/*
611
 *   Symbol node 
612
 */
613
class CTPNSym: public CTPNSymBase
614
{
615
public:
616
    CTPNSym(const char *sym, size_t len)
617
        : CTPNSymBase(sym, len) { }
618
619
    /* generate code for the symbol evaluated as an rvalue */
620
    void gen_code(int discard, int for_condition);
621
622
    /* generate code to assign a value to the symbol */
623
    int gen_code_asi(int discard, tc_asitype_t typ, CTcPrsNode *rhs,
624
                     int ignore_errors);
625
626
    /* generate code to take the address of the symbol */
627
    void gen_code_addr();
628
629
    /* generate code to call the symbol */
630
    void gen_code_call(int discard, int argc, int varargs);
631
632
    /* generate code for operator 'new' applied to this expression */
633
    void gen_code_new(int discard, int argc, int varargs, int from_call,
634
                      int is_transient);
635
636
    /* evaluate a property ID */
637
    vm_prop_id_t gen_code_propid(int check_only, int is_expr);
638
639
    /* generate a member expression */
640
    void gen_code_member(int discard,
641
                         class CTcPrsNode *prop_expr, int prop_is_expr,
642
                         int argc, int varargs);
643
644
    /* get the object value for a '.' expression */
645
    vm_obj_id_t gen_code_obj_predot(int *is_self);
646
};
647
648
/* ------------------------------------------------------------------------ */
649
/*
650
 *   Resolved symbol 
651
 */
652
class CTPNSymResolved: public CTPNSymResolvedBase
653
{
654
public:
655
    CTPNSymResolved(CTcSymbol *sym)
656
        : CTPNSymResolvedBase(sym) { }
657
658
    /* generate code for the symbol evaluated as an rvalue */
659
    void gen_code(int discard, int for_condition);
660
661
    /* generate code to assign a value to the symbol */
662
    int gen_code_asi(int discard, tc_asitype_t typ, CTcPrsNode *rhs,
663
                     int ignore_errors);
664
665
    /* generate code to take the address of the symbol */
666
    void gen_code_addr();
667
668
    /* generate code to call the symbol */
669
    void gen_code_call(int discard, int argc, int varargs);
670
671
    /* generate code for operator 'new' applied to this expression */
672
    void gen_code_new(int discard, int argc, int varargs, int from_call,
673
                      int is_transient);
674
675
    /* evaluate a property ID */
676
    vm_prop_id_t gen_code_propid(int check_only, int is_expr);
677
678
    /* generate a member expression */
679
    void gen_code_member(int discard,
680
                         class CTcPrsNode *prop_expr, int prop_is_expr,
681
                         int argc, int varargs);
682
683
    /* get the object value for a '.' expression */
684
    vm_obj_id_t gen_code_obj_predot(int *is_self);
685
};
686
687
/* ------------------------------------------------------------------------ */
688
/*
689
 *   Resolved debugger local variable symbol 
690
 */
691
class CTPNSymDebugLocal: public CTPNSymDebugLocalBase
692
{
693
public:
694
    CTPNSymDebugLocal(const struct tcprsdbg_sym_info *info)
695
        : CTPNSymDebugLocalBase(info)
696
    {
697
    }
698
699
    /* generate code */
700
    void gen_code(int discard, int for_condition);
701
702
    /* generate code for assigning into this node */
703
    int gen_code_asi(int discard, tc_asitype_t typ,
704
                     class CTcPrsNode *rhs, int ignore_errors);
705
};
706
707
/* ------------------------------------------------------------------------ */
708
/*
709
 *   double-quoted string expression 
710
 */
711
class CTPNDstr: public CTPNDstrBase
712
{
713
public:
714
    CTPNDstr(const char *str, size_t len)
715
        : CTPNDstrBase(str, len) { }
716
717
    void gen_code(int discard, int for_condition);
718
};
719
720
/*
721
 *   debug version of string 
722
 */
723
class CTPNDebugDstr: public CTPNDstr
724
{
725
public:
726
    CTPNDebugDstr(const char *str, size_t len)
727
        : CTPNDstr(str, len) { }
728
729
    void gen_code(int discard, int for_condition);
730
};
731
732
/*
733
 *   double-quoted string embedding 
734
 */
735
class CTPNDstrEmbed: public CTPNDstrEmbedBase
736
{
737
public:
738
    CTPNDstrEmbed(CTcPrsNode *sub);
739
740
    void gen_code(int discard, int for_condition);
741
};
742
743
/* ------------------------------------------------------------------------ */
744
/*
745
 *   Argument List 
746
 */
747
class CTPNArglist: public CTPNArglistBase
748
{
749
public:
750
    CTPNArglist(int argc, class CTPNArg *list_head)
751
        : CTPNArglistBase(argc, list_head) { }
752
753
    void gen_code(int, int)
754
    {
755
        /* 
756
         *   this isn't used - we always generate explicitly via
757
         *   gen_code_arglist() 
758
         */
759
        assert(FALSE);
760
    }
761
762
    /* generate code for an argument list */
763
    void gen_code_arglist(int *varargs);
764
};
765
766
/*
767
 *   Argument List Entry 
768
 */
769
class CTPNArg: public CTPNArgBase
770
{
771
public:
772
    CTPNArg(CTcPrsNode *expr)
773
        : CTPNArgBase(expr) { }
774
775
    void gen_code(int discard, int for_condition);
776
};
777
778
/* ------------------------------------------------------------------------ */
779
/*
780
 *   Function/method call 
781
 */
782
class CTPNCall: public CTPNCallBase
783
{
784
public:
785
    CTPNCall(CTcPrsNode *func, class CTPNArglist *arglist);
786
787
    /* generate code */
788
    void gen_code(int discard, int for_condition);
789
790
    /* generate code for operator 'new' applied to this expression */
791
    void gen_code_new(int discard, int argc, int varargs, int from_call,
792
                      int is_transient);
793
};
794
795
796
/* ------------------------------------------------------------------------ */
797
/*
798
 *   Member expression with no arguments 
799
 */
800
class CTPNMember: public CTPNMemberBase
801
{
802
public:
803
    CTPNMember(CTcPrsNode *lhs, CTcPrsNode *rhs, int rhs_is_expr)
804
        : CTPNMemberBase(lhs, rhs, rhs_is_expr) { }
805
806
    /* generate code */
807
    void gen_code(int discard, int for_condition);
808
809
    /* generate code to assign a value to the symbol */
810
    int gen_code_asi(int discard, tc_asitype_t typ, CTcPrsNode *rhs,
811
                     int ignore_errors);
812
};
813
814
/*
815
 *   Member evaluation with argument list 
816
 */
817
class CTPNMemArg: public CTPNMemArgBase
818
{
819
public:
820
    CTPNMemArg(CTcPrsNode *obj_expr, CTcPrsNode *prop_expr, int prop_is_expr,
821
               class CTPNArglist *arglist)
822
        : CTPNMemArgBase(obj_expr, prop_expr, prop_is_expr, arglist) { }
823
824
    void gen_code(int discard, int for_condition);
825
};
826
827
828
/* ------------------------------------------------------------------------ */
829
/*
830
 *   List 
831
 */
832
class CTPNList: public CTPNListBase
833
{
834
public:
835
    void gen_code(int discard, int for_condition);
836
};
837
838
/*
839
 *   List Element 
840
 */
841
class CTPNListEle: public CTPNListEleBase
842
{
843
public:
844
    CTPNListEle(CTcPrsNode *expr)
845
        : CTPNListEleBase(expr) { }
846
847
    void gen_code(int discard, int for_condition);
848
};
849
850
/* ------------------------------------------------------------------------ */
851
/*
852
 *   Derived T3-specific symbol classes 
853
 */
854
855
/*
856
 *   undefined symbol 
857
 */
858
class CTcSymUndef: public CTcSymUndefBase
859
{
860
public:
861
    CTcSymUndef(const char *str, size_t len, int copy)
862
        : CTcSymUndefBase(str, len, copy) { }
863
864
    /* 
865
     *   generate code to evaluate the symbol; since it's undefined, this
866
     *   doesn't generate any code at all 
867
     */
868
    virtual void gen_code(int) { }
869
870
    /* 
871
     *   Generate code to assign to the symbol.  The symbol is undefined,
872
     *   so we can't generate any code; but we'll indicate to the caller
873
     *   that the assignment is fully processed anyway, since there's no
874
     *   need for the caller to try generating any code either. 
875
     */
876
    virtual int gen_code_asi(int, tc_asitype_t, class CTcPrsNode *, int)
877
    {
878
        return TRUE;
879
    }
880
881
    /* 
882
     *   Generate code for taking the address of the symbol.  The symbol
883
     *   has no address, so this generates no code. 
884
     */
885
    virtual void gen_code_addr() { }
886
887
    /* 
888
     *   generate code to call the symbol - we can't generate any code for
889
     *   this, but don't bother issuing an error since we will have shown
890
     *   an error for the undefined symbol in the first place 
891
     */
892
    virtual void gen_code_call(int, int, int) { }
893
894
    /* 
895
     *   generate code for operator 'new' applied to this expression - we
896
     *   can't generate any code, but suppress errors as usual 
897
     */
898
    void gen_code_new(int, int, int, int) { }
899
900
    /* generate a member expression */
901
    void gen_code_member(int, class CTcPrsNode *, int, int, int) { }
902
903
    /* get the object value for a '.' expression */
904
    vm_obj_id_t gen_code_obj_predot(int *is_self)
905
    {
906
        *is_self = FALSE;
907
        return VM_INVALID_OBJ;
908
    }
909
};
910
911
912
/*
913
 *   function 
914
 */
915
class CTcSymFunc: public CTcSymFuncBase
916
{
917
public:
918
    CTcSymFunc(const char *str, size_t len, int copy,
919
               int argc, int varargs, int has_retval,
920
               int is_multimethod, int is_mm_base, int is_extern)
921
        : CTcSymFuncBase(str, len, copy, argc, varargs, has_retval,
922
                         is_multimethod, is_mm_base, is_extern)
923
    {
924
        /* 
925
         *   we don't have a valid absolute address - by default, we use
926
         *   the anchor 
927
         */
928
        abs_addr_valid_ = FALSE;
929
        abs_addr_ = 0;
930
    }
931
932
    /* generate code to evaluate the symbol */
933
    virtual void gen_code(int discard);
934
935
    /* we can take the address of this symbol type */
936
    virtual void gen_code_addr();
937
938
    /* generate a call */
939
    virtual void gen_code_call(int discard, int argc, int varargs);
940
941
    /* 
942
     *   Get my code pool address.  This is valid only after the linking
943
     *   phase has been completed and all fixups have been applied.  (The
944
     *   normal use for this is to generate image file elements not
945
     *   subject to fixup, such as the entrypoint record.  Normally,
946
     *   references to the symbol that require the code pool address would
947
     *   simply generate a fixup rather than asking for the true address,
948
     *   since a fixup can be generated at any time during code
949
     *   generation.)
950
     */
951
    ulong get_code_pool_addr() const;
952
953
    /* write the symbol to an image file's global symbol table */
954
    int write_to_image_file_global(class CVmImageWriter *image_writer);
955
956
    /*
957
     *   Set the absolute code pool address.  This can only be used when
958
     *   the symbol is loaded from a fully-linked image file; in most
959
     *   cases, this routine is not needed, because the function's address
960
     *   will be kept with its associated anchor to allow for relocation
961
     *   of the function during the linking process.  
962
     */
963
    void set_abs_addr(ulong addr)
964
    {
965
        /* remember the address */
966
        abs_addr_ = addr;
967
968
        /* note that the absolute address is valid */
969
        abs_addr_valid_ = TRUE;
970
    }
971
972
    /* add a runtime symbol table entry */
973
    void add_runtime_symbol(class CVmRuntimeSymbols *symtab);
974
    
975
protected:
976
    /*
977
     *   Absolute code pool address, and a flag indicating whether the
978
     *   address is valid.  When we load a function symbol from a
979
     *   fully-linked image file (specifically, when we load the symbol
980
     *   from the debug records of an image file), the address of the
981
     *   function is fully resolved and doesn't require fixups via the
982
     *   anchor mechanism.  In these cases, we'll simply remember the
983
     *   resolved address here.  
984
     */
985
    ulong abs_addr_;
986
    uint abs_addr_valid_ : 1;
987
};
988
989
/*
990
 *   metaclass 
991
 */
992
class CTcSymMetaclass: public CTcSymMetaclassBase
993
{
994
public:
995
    CTcSymMetaclass(const char *str, size_t len, int copy, int meta_idx,
996
                    tctarg_obj_id_t class_obj)
997
        : CTcSymMetaclassBase(str, len, copy, meta_idx, class_obj)
998
    {
999
    }
1000
1001
    /* generate code to evaluate the symbol */
1002
    virtual void gen_code(int discard);
1003
1004
    /* generate code for operator 'new' */
1005
    void gen_code_new(int discard, int argc, int varargs, int is_transient);
1006
1007
    /* generate a member expression */
1008
    void gen_code_member(int discard,
1009
                         class CTcPrsNode *prop_expr, int prop_is_expr,
1010
                         int argc, int varargs);
1011
1012
    /* get the object value for a '.' expression */
1013
    vm_obj_id_t gen_code_obj_predot(int *is_self)
1014
    {
1015
        /* simply generate our code as normal */
1016
        gen_code(FALSE);
1017
1018
        /* indicate that the caller must use generated code */
1019
        *is_self = FALSE;
1020
        return VM_INVALID_OBJ;
1021
    }
1022
1023
    /* write the symbol to an image file's global symbol table */
1024
    int write_to_image_file_global(class CVmImageWriter *image_writer);
1025
1026
    /* 
1027
     *   fix up the inheritance chain in the modifier objects - each
1028
     *   object file has its own independent inheritance list, so we can
1029
     *   only build the complete and connected list after loading them all 
1030
     */
1031
    void fix_mod_obj_sc_list();
1032
1033
    /* add a runtime symbol table entry */
1034
    void add_runtime_symbol(class CVmRuntimeSymbols *symtab);
1035
};
1036
1037
/*
1038
 *   object 
1039
 */
1040
class CTcSymObj: public CTcSymObjBase
1041
{
1042
public:
1043
    CTcSymObj(const char *str, size_t len, int copy, vm_obj_id_t obj_id,
1044
              int is_extern, tc_metaclass_t meta, class CTcDictEntry *dict)
1045
        : CTcSymObjBase(str, len, copy, obj_id, is_extern, meta, dict)
1046
    {
1047
    }
1048
1049
    /* we have a valid object value */
1050
    virtual vm_obj_id_t get_val_obj() const { return get_obj_id(); }
1051
1052
    /* generate code to evaluate the symbol */
1053
    virtual void gen_code(int discard);
1054
1055
    /* we can take the address of this symbol type */
1056
    virtual void gen_code_addr();
1057
1058
    /* generate code for operator 'new' */
1059
    void gen_code_new(int discard, int argc, int varargs, int is_transient);
1060
1061
    /* static code to generate code for 'new' */
1062
    static void s_gen_code_new(int discard, vm_obj_id_t obj_id,
1063
                               tc_metaclass_t meta,
1064
                               int argc, int varargs, int is_transient);
1065
1066
    /* generate a member expression */
1067
    void gen_code_member(int discard,
1068
                         class CTcPrsNode *prop_expr, int prop_is_expr,
1069
                         int argc, int varargs);
1070
1071
    /* static code to generate a member expression */
1072
    static void s_gen_code_member(int discard,
1073
                                  class CTcPrsNode *prop_expr,
1074
                                  int prop_is_expr, int argc,
1075
                                  vm_obj_id_t obj_id, int varargs);
1076
1077
    /* get the object value for a '.' expression */
1078
    vm_obj_id_t gen_code_obj_predot(int *is_self);
1079
1080
    /* delete a property from our modified base classes */
1081
    virtual void delete_prop_from_mod_base(tctarg_prop_id_t prop_id);
1082
1083
    /* mark the compiled data for the object as a 'class' object */
1084
    virtual void mark_compiled_as_class();
1085
1086
    /* write the symbol to an image file's global symbol table */
1087
    int write_to_image_file_global(class CVmImageWriter *image_writer);
1088
1089
    /* build my dictionary */
1090
    virtual void build_dictionary();
1091
1092
    /* add a runtime symbol table entry */
1093
    void add_runtime_symbol(class CVmRuntimeSymbols *symtab);
1094
};
1095
1096
/*
1097
 *   property 
1098
 */
1099
class CTcSymProp: public CTcSymPropBase
1100
{
1101
public:
1102
    CTcSymProp(const char *str, size_t len, int copy, tctarg_prop_id_t prop)
1103
        : CTcSymPropBase(str, len, copy, prop) { }
1104
1105
    /* generate code to evaluate the symbol */
1106
    virtual void gen_code(int discard);
1107
1108
    /* we can take the address of this symbol type */
1109
    virtual void gen_code_addr();
1110
1111
    /* assign to the property */
1112
    virtual int gen_code_asi(int discard, tc_asitype_t typ,
1113
                             class CTcPrsNode *rhs, int ignore_errors);
1114
1115
    /* generate a call */
1116
    virtual void gen_code_call(int discard, int argc, int varargs);
1117
1118
    /* evaluate a property ID */
1119
    vm_prop_id_t gen_code_propid(int check_only, int is_expr);
1120
1121
    /* generate a member expression */
1122
    void gen_code_member(int discard,
1123
                         class CTcPrsNode *prop_expr, int prop_is_expr,
1124
                         int argc, int varargs);
1125
1126
    /* get the object value for a '.' expression */
1127
    vm_obj_id_t gen_code_obj_predot(int *is_self)
1128
    {
1129
        /* simply generate our code as normal */
1130
        gen_code(FALSE);
1131
1132
        /* indicate that the caller must use generated code */
1133
        *is_self = FALSE;
1134
        return VM_INVALID_OBJ;
1135
    }
1136
1137
    /* write the symbol to an image file's global symbol table */
1138
    int write_to_image_file_global(class CVmImageWriter *image_writer);
1139
1140
    /* add a runtime symbol table entry */
1141
    void add_runtime_symbol(class CVmRuntimeSymbols *symtab);
1142
};
1143
1144
/*
1145
 *   Enumerator 
1146
 */
1147
class CTcSymEnum: public CTcSymEnumBase
1148
{
1149
public:
1150
    CTcSymEnum(const char *str, size_t len, int copy, ulong id, int is_token)
1151
        : CTcSymEnumBase(str, len, copy, id, is_token)
1152
    {
1153
    }
1154
1155
    /* generate code */
1156
    virtual void gen_code(int discard);
1157
1158
    /* write the symbol to an image file's global symbol table */
1159
    int write_to_image_file_global(class CVmImageWriter *image_writer);
1160
1161
    /* add a runtime symbol table entry */
1162
    void add_runtime_symbol(class CVmRuntimeSymbols *symtab);
1163
};
1164
1165
/*
1166
 *   local variable/parameter 
1167
 */
1168
class CTcSymLocal: public CTcSymLocalBase
1169
{
1170
public:
1171
    CTcSymLocal(const char *str, size_t len, int copy,
1172
                int is_param, int var_num)
1173
        : CTcSymLocalBase(str, len, copy, is_param, var_num) { }
1174
1175
    /* generate code to evaluate the symbol */
1176
    virtual void gen_code(int discard);
1177
1178
    /* generate code to store the value at top of stack in the variable */
1179
    void gen_code_setlcl_stk() { s_gen_code_setlcl_stk(var_num_, is_param_); }
1180
1181
    /* generate code to get a local with a given ID */
1182
    static void s_gen_code_getlcl(int local_id, int is_param);
1183
1184
    /* generate code to store a local with a given ID */
1185
    static void s_gen_code_setlcl_stk(int local_id, int is_param);
1186
1187
    /* generate code to store the value at top of stack in the local */
1188
    void gen_code_setlcl();
1189
1190
    /* assign to the variable */
1191
    virtual int gen_code_asi(int discard, tc_asitype_t typ,
1192
                             class CTcPrsNode *rhs, int ignore_errors);
1193
1194
    /* 
1195
     *   generate a call - invoking a local as a function assumes that the
1196
     *   local contains a method or function pointer 
1197
     */
1198
    virtual void gen_code_call(int discard, int argc, int varargs);
1199
1200
    /* evaluate a property ID */
1201
    vm_prop_id_t gen_code_propid(int check_only, int is_expr);
1202
1203
    /* generate a member expression */
1204
    void gen_code_member(int discard,
1205
                         class CTcPrsNode *prop_expr, int prop_is_expr,
1206
                         int argc, int varargs);
1207
1208
    /* get the object value for a '.' expression */
1209
    vm_obj_id_t gen_code_obj_predot(int *is_self)
1210
    {
1211
        /* simply generate our code as normal */
1212
        gen_code(FALSE);
1213
1214
        /* indicate that the caller must use generated code */
1215
        *is_self = FALSE;
1216
        return VM_INVALID_OBJ;
1217
    }
1218
1219
    /* write the symbol to a debug frame */
1220
    virtual int write_to_debug_frame();
1221
};
1222
1223
/*
1224
 *   built-in function 
1225
 */
1226
class CTcSymBif: public CTcSymBifBase
1227
{
1228
public:
1229
    CTcSymBif(const char *str, size_t len, int copy,
1230
              int func_set_id, int func_idx, int has_retval,
1231
              int min_argc, int max_argc, int varargs)
1232
        : CTcSymBifBase(str, len, copy, func_set_id, func_idx,
1233
                        has_retval, min_argc, max_argc, varargs) { }
1234
1235
    /* generate code to evaluate the symbol */
1236
    virtual void gen_code(int discard);
1237
1238
    /* generate a call */
1239
    virtual void gen_code_call(int discard, int argc, int varargs);
1240
1241
    /* write the symbol to an image file's global symbol table */
1242
    int write_to_image_file_global(class CVmImageWriter *image_writer);
1243
};
1244
1245
/*
1246
 *   external function 
1247
 */
1248
class CTcSymExtfn: public CTcSymExtfnBase
1249
{
1250
public:
1251
    CTcSymExtfn(const char *str, size_t len, int copy,
1252
                int argc, int varargs, int has_retval)
1253
        : CTcSymExtfnBase(str, len, copy, argc, varargs, has_retval) { }
1254
1255
    /* generate code to evaluate the symbol */
1256
    virtual void gen_code(int discard);
1257
1258
    /* generate a call */
1259
    virtual void gen_code_call(int discard, int argc, int varargs);
1260
1261
    /* write the symbol to an image file's global symbol table */
1262
    int write_to_image_file_global(class CVmImageWriter *image_writer);
1263
};
1264
1265
/*
1266
 *   code label 
1267
 */
1268
class CTcSymLabel: public CTcSymLabelBase
1269
{
1270
public:
1271
    CTcSymLabel(const char *str, size_t len, int copy)
1272
        : CTcSymLabelBase(str, len, copy) { }
1273
1274
    /* generate code to evaluate the symbol */
1275
    virtual void gen_code(int discard);
1276
};
1277
1278
/* ------------------------------------------------------------------------ */
1279
/*
1280
 *   Anonymous function 
1281
 */
1282
class CTPNAnonFunc: public CTPNAnonFuncBase
1283
{
1284
public:
1285
    CTPNAnonFunc(class CTPNCodeBody *code_body, int has_retval)
1286
        : CTPNAnonFuncBase(code_body, has_retval)
1287
    {
1288
    }
1289
1290
    /* generate code */
1291
    virtual void gen_code(int discard, int for_condition);
1292
};
1293
1294
/* ------------------------------------------------------------------------ */
1295
/*
1296
 *   Code Body 
1297
 */
1298
class CTPNCodeBody: public CTPNCodeBodyBase
1299
{
1300
public:
1301
    CTPNCodeBody(class CTcPrsSymtab *lcltab, class CTcPrsSymtab *gototab,
1302
                 class CTPNStm *stm, int argc, int varargs,
1303
                 int varargs_list, class CTcSymLocal *varargs_list_local,
1304
                 int local_cnt, int self_valid,
1305
                 struct CTcCodeBodyRef *enclosing_code_body)
1306
        : CTPNCodeBodyBase(lcltab, gototab, stm, argc, varargs,
1307
                           varargs_list, varargs_list_local,
1308
                           local_cnt, self_valid, enclosing_code_body)
1309
    {
1310
        /* presume I'm not a constructor */
1311
        is_constructor_ = FALSE;
1312
1313
        /* presume I won't need a 'finally' return value holder local */
1314
        allocated_fin_ret_lcl_ = FALSE;
1315
        fin_ret_lcl_ = 0;
1316
1317
        /* presume it won't be static */
1318
        is_static_ = FALSE;
1319
1320
        /* no nested symbol table list yet */
1321
        first_nested_symtab_ = 0;
1322
    }
1323
1324
    /* 
1325
     *   Mark the code body as belonging to a constructor.  A constructor
1326
     *   must return its 'self' object as the return value.  
1327
     */
1328
    void set_constructor(int f) { is_constructor_ = f; }
1329
1330
    /* 
1331
     *   mark the code body as static - this indicates that it is a static
1332
     *   initializer
1333
     */
1334
    void set_static() { is_static_ = TRUE; }
1335
1336
    /* generate code */
1337
    virtual void gen_code(int discard, int for_condition);
1338
1339
    /* check locals */
1340
    virtual void check_locals();
1341
1342
    /*
1343
     *   Allocate a local variable for temporarily saving the expression
1344
     *   value of a 'return' statement while calling the enclosing
1345
     *   'finally' block(s).  Returns the variable ID.  Only one such
1346
     *   local is needed per code body, so if we've already allocated one
1347
     *   for another 'return' statement, we'll just return the same one we
1348
     *   allocated previously.  
1349
     */
1350
    uint alloc_fin_ret_lcl()
1351
    {
1352
        /* if we haven't allocated it yet, do so now */
1353
        if (!allocated_fin_ret_lcl_)
1354
        {
1355
            /* use the next available local */
1356
            fin_ret_lcl_ = local_cnt_++;
1357
1358
            /* note that we've allocated it */
1359
            allocated_fin_ret_lcl_ = TRUE;
1360
        }
1361
1362
        /* return the local ID */
1363
        return fin_ret_lcl_;
1364
    }
1365
1366
protected:
1367
    /* 
1368
     *   callback for enumerating local frame symbol table entries - write
1369
     *   each entry to the code stream as a debug record 
1370
     */
1371
    static void write_local_to_debug_frame(void *ctx, class CTcSymbol *sym);
1372
1373
    /* 
1374
     *   enumerator for checking for parameter symbols that belong in the
1375
     *   local context 
1376
     */
1377
    static void enum_for_param_ctx(void *ctx, class CTcSymbol *sym);
1378
1379
    /* write the debug information table to the code stream */
1380
    void build_debug_table(ulong start_ofs);
1381
1382
    /* show disassembly */
1383
    void show_disassembly(unsigned long start_ofs,
1384
                          unsigned long code_start_ofs,
1385
                          unsigned long code_end_ofs);
1386
1387
    /* head of list of nested symbol tables */
1388
    class CTcPrsSymtab *first_nested_symtab_;
1389
1390
    /* 
1391
     *   ID of local variable for temporarily storing the expression value
1392
     *   of a 'return' statement while calling the enclosing 'finally'
1393
     *   block(s); valid only when allocated_fin_ret_lcl_ is true 
1394
     */
1395
    uint fin_ret_lcl_;
1396
1397
    /* flag: I'm a constructor */
1398
    uint is_constructor_ : 1;
1399
1400
    /* 
1401
     *   flag: I've allocated a local for saving the expression value of a
1402
     *   'return' statement while calling the enclosing 'finally' block(s) 
1403
     */
1404
    uint allocated_fin_ret_lcl_ : 1;
1405
1406
    /* flag: I'm a static property initializer */
1407
    uint is_static_ : 1;
1408
};
1409
1410
/* ------------------------------------------------------------------------ */
1411
/*
1412
 *   Compound Statement
1413
 */
1414
class CTPNStmComp: public CTPNStmCompBase
1415
{
1416
public:
1417
    CTPNStmComp(class CTPNStm *first_stm, class CTcPrsSymtab *symtab)
1418
        : CTPNStmCompBase(first_stm, symtab) { }
1419
};
1420
1421
/* ------------------------------------------------------------------------ */
1422
/*
1423
 *   Null statement 
1424
 */
1425
class CTPNStmNull: public CTPNStmNullBase
1426
{
1427
public:
1428
    CTPNStmNull() { }
1429
};
1430
1431
/* ------------------------------------------------------------------------ */
1432
/*
1433
 *   Expression statement 
1434
 */
1435
class CTPNStmExpr: public CTPNStmExprBase
1436
{
1437
public:
1438
    CTPNStmExpr(class CTcPrsNode *expr)
1439
        : CTPNStmExprBase(expr) { }
1440
};
1441
1442
/* ------------------------------------------------------------------------ */
1443
/*
1444
 *   Static property initializer statement
1445
 */
1446
class CTPNStmStaticPropInit: public CTPNStmStaticPropInitBase
1447
{
1448
public:
1449
    CTPNStmStaticPropInit(class CTcPrsNode *expr,
1450
                          tctarg_prop_id_t prop)
1451
        : CTPNStmStaticPropInitBase(expr, prop) { }
1452
1453
    /* generate code */
1454
    virtual void gen_code(int discard, int for_condition);
1455
};
1456
1457
/* ------------------------------------------------------------------------ */
1458
/*
1459
 *   'if' statement 
1460
 */
1461
class CTPNStmIf: public CTPNStmIfBase
1462
{
1463
public:
1464
    CTPNStmIf(class CTcPrsNode *cond_expr,
1465
              class CTPNStm *then_part, class CTPNStm *else_part)
1466
        : CTPNStmIfBase(cond_expr, then_part, else_part) { }
1467
    
1468
    /* generate code */
1469
    virtual void gen_code(int discard, int for_condition);
1470
};
1471
1472
/* ------------------------------------------------------------------------ */
1473
/*
1474
 *   'for' statement 
1475
 */
1476
class CTPNStmFor: public CTPNStmForBase
1477
{
1478
public:
1479
    CTPNStmFor(class CTcPrsNode *init_expr,
1480
               class CTcPrsNode *cond_expr,
1481
               class CTcPrsNode *reinit_expr,
1482
               class CTcPrsSymtab *symtab,
1483
               class CTPNStmEnclosing *enclosing_stm)
1484
        : CTPNStmForBase(init_expr, cond_expr, reinit_expr,
1485
                         symtab, enclosing_stm)
1486
    {
1487
    }
1488
1489
    /* generate code */
1490
    virtual void gen_code(int discard, int for_condition);
1491
1492
    /* generate code for 'break' */
1493
    virtual int gen_code_break(const textchar_t *lbl, size_t lbl_len)
1494
        { return gen_code_break_loop(break_lbl_, lbl, lbl_len); }
1495
1496
    /* generate code for 'continue' */
1497
    virtual int gen_code_labeled_continue()
1498
        { return gen_code_continue_loop(cont_lbl_, 0, 0); }
1499
1500
    /* generate code for a labeled 'continue' */
1501
    virtual int gen_code_continue(const textchar_t *lbl, size_t lbl_len)
1502
        { return gen_code_continue_loop(cont_lbl_, lbl, lbl_len); }
1503
1504
protected:
1505
    /* our 'break' label */
1506
    struct CTcCodeLabel *break_lbl_;
1507
1508
    /* our 'continue' label */
1509
    struct CTcCodeLabel *cont_lbl_;
1510
};
1511
1512
/* ------------------------------------------------------------------------ */
1513
/*
1514
 *   'for' statement 
1515
 */
1516
class CTPNStmForeach: public CTPNStmForeachBase
1517
{
1518
public:
1519
    CTPNStmForeach(class CTcPrsNode *iter_expr,
1520
                   class CTcPrsNode *coll_expr,
1521
                   class CTcPrsSymtab *symtab,
1522
                   class CTPNStmEnclosing *enclosing_stm,
1523
                   int iter_local_id)
1524
        : CTPNStmForeachBase(iter_expr, coll_expr, symtab, enclosing_stm,
1525
                             iter_local_id)
1526
    {
1527
    }
1528
1529
    /* generate code */
1530
    virtual void gen_code(int discard, int for_condition);
1531
1532
    /* generate code for 'break' */
1533
    virtual int gen_code_break(const textchar_t *lbl, size_t lbl_len)
1534
        { return gen_code_break_loop(break_lbl_, lbl, lbl_len); }
1535
1536
    /* generate code for 'continue' */
1537
    virtual int gen_code_labeled_continue()
1538
        { return gen_code_continue_loop(cont_lbl_, 0, 0); }
1539
1540
    /* generate code for a labeled 'continue' */
1541
    virtual int gen_code_continue(const textchar_t *lbl, size_t lbl_len)
1542
        { return gen_code_continue_loop(cont_lbl_, lbl, lbl_len); }
1543
1544
protected:
1545
    /* our 'break' label */
1546
    struct CTcCodeLabel *break_lbl_;
1547
1548
    /* our 'continue' label */
1549
    struct CTcCodeLabel *cont_lbl_;
1550
};
1551
1552
/* ------------------------------------------------------------------------ */
1553
/*
1554
 *   'break' statement 
1555
 */
1556
class CTPNStmBreak: public CTPNStmBreakBase
1557
{
1558
public:
1559
    CTPNStmBreak() { }
1560
1561
    /* generate code */
1562
    virtual void gen_code(int discard, int for_condition);
1563
};
1564
1565
/* ------------------------------------------------------------------------ */
1566
/*
1567
 *   'continue' statement 
1568
 */
1569
class CTPNStmContinue: public CTPNStmContinueBase
1570
{
1571
public:
1572
    CTPNStmContinue() { }
1573
1574
    /* generate code */
1575
    virtual void gen_code(int discard, int for_condition);
1576
};
1577
1578
/* ------------------------------------------------------------------------ */
1579
/*
1580
 *   'while' statement 
1581
 */
1582
class CTPNStmWhile: public CTPNStmWhileBase
1583
{
1584
public:
1585
    CTPNStmWhile(class CTcPrsNode *cond_expr,
1586
                 class CTPNStmEnclosing *enclosing_stm)
1587
        : CTPNStmWhileBase(cond_expr, enclosing_stm) { }
1588
1589
    /* generate code */
1590
    virtual void gen_code(int discard, int for_condition);
1591
1592
    /* generate code for 'break' */
1593
    virtual int gen_code_break(const textchar_t *lbl, size_t lbl_len)
1594
        { return gen_code_break_loop(break_lbl_, lbl, lbl_len); }
1595
1596
    /* generate code for 'continue' */
1597
    virtual int gen_code_labeled_continue()
1598
        { return gen_code_continue_loop(cont_lbl_, 0, 0); }
1599
1600
    /* generate code for a labeled 'continue' */
1601
    virtual int gen_code_continue(const textchar_t *lbl, size_t lbl_len)
1602
        { return gen_code_continue_loop(cont_lbl_, lbl, lbl_len); }
1603
1604
protected:
1605
    /* our 'break' label */
1606
    struct CTcCodeLabel *break_lbl_;
1607
1608
    /* our 'continue' label */
1609
    struct CTcCodeLabel *cont_lbl_;
1610
};
1611
1612
/* ------------------------------------------------------------------------ */
1613
/*
1614
 *   'do-while' statement 
1615
 */
1616
class CTPNStmDoWhile: public CTPNStmDoWhileBase
1617
{
1618
public:
1619
    CTPNStmDoWhile(class CTPNStmEnclosing *enclosing_stm)
1620
        : CTPNStmDoWhileBase(enclosing_stm) { }
1621
1622
    /* generate code */
1623
    virtual void gen_code(int discard, int for_condition);
1624
1625
    /* generate code for 'break' */
1626
    virtual int gen_code_break(const textchar_t *lbl, size_t lbl_len)
1627
        { return gen_code_break_loop(break_lbl_, lbl, lbl_len); }
1628
1629
    /* generate code for 'continue' */
1630
    virtual int gen_code_labeled_continue()
1631
        { return gen_code_continue_loop(cont_lbl_, 0, 0); }
1632
1633
    /* generate code for a labeled 'continue' */
1634
    virtual int gen_code_continue(const textchar_t *lbl, size_t lbl_len)
1635
        { return gen_code_continue_loop(cont_lbl_, lbl, lbl_len); }
1636
1637
protected:
1638
    /* our 'break' label */
1639
    struct CTcCodeLabel *break_lbl_;
1640
1641
    /* our 'continue' label */
1642
    struct CTcCodeLabel *cont_lbl_;
1643
};
1644
1645
/* ------------------------------------------------------------------------ */
1646
/*
1647
 *   'return' statement 
1648
 */
1649
class CTPNStmReturn: public CTPNStmReturnBase
1650
{
1651
public:
1652
    CTPNStmReturn(class CTcPrsNode *expr)
1653
        : CTPNStmReturnBase(expr) { }
1654
1655
    /* generate code */
1656
    virtual void gen_code(int discard, int for_condition);
1657
};
1658
1659
/* ------------------------------------------------------------------------ */
1660
/*
1661
 *   'switch' statement 
1662
 */
1663
class CTPNStmSwitch: public CTPNStmSwitchBase
1664
{
1665
public:
1666
    CTPNStmSwitch(class CTPNStmEnclosing *enclosing_stm)
1667
        : CTPNStmSwitchBase(enclosing_stm)
1668
    {
1669
        /* the 'case' and 'default' slot pointers aren't valid yet */
1670
        case_slot_ofs_ = 0;
1671
        default_slot_ofs_ = 0;
1672
    }
1673
1674
    /* generate code */
1675
    virtual void gen_code(int discard, int for_condition);
1676
1677
    /* 
1678
     *   Get the next case slot offset, and consume the slot.  Each call
1679
     *   consumes one slot.  This is valid only during code generation in
1680
     *   the switch body; 'case' labels use this to figure out where to
1681
     *   write their data.  
1682
     */
1683
    ulong alloc_case_slot()
1684
    {
1685
        ulong ret;
1686
1687
        /* note the value to return */
1688
        ret = case_slot_ofs_;
1689
1690
        /* move our internal counter to the next slot */
1691
        case_slot_ofs_ += VMB_DATAHOLDER + VMB_UINT2;
1692
1693
        /* return the allocated slot */
1694
        return ret;
1695
    }
1696
1697
    /* get the code offset of the 'default' case slot */
1698
    ulong get_default_slot() const { return default_slot_ofs_; }
1699
1700
    /* generate code for 'break' */
1701
    virtual int gen_code_break(const textchar_t *lbl, size_t lbl_len)
1702
    {
1703
        /* 
1704
         *   if there's no label, and we don't have a 'break' label
1705
         *   ourselves, it must mean that we're processing an unreachable
1706
         *   'break' - we can simply do nothing in this case and pretend we
1707
         *   succeeded 
1708
         */
1709
        if (lbl == 0 && break_lbl_ == 0)
1710
            return TRUE;
1711
1712
        /* break to our break label */
1713
        return gen_code_break_loop(break_lbl_, lbl, lbl_len);
1714
    }
1715
1716
protected:
1717
    /* 
1718
     *   code offset of the next 'case' slot to be allocated from the
1719
     *   switch's case table - this is only valid during generation of the
1720
     *   body, because we set this up during generation of the switch
1721
     *   itself 
1722
     */
1723
    ulong case_slot_ofs_;
1724
1725
    /* code offset of the 'default' slot */
1726
    ulong default_slot_ofs_;
1727
1728
    /* our 'break' label */
1729
    struct CTcCodeLabel *break_lbl_;
1730
};
1731
1732
1733
/* ------------------------------------------------------------------------ */
1734
/*
1735
 *   code label statement 
1736
 */
1737
class CTPNStmLabel: public CTPNStmLabelBase
1738
{
1739
public:
1740
    CTPNStmLabel(class CTcSymLabel *lbl, class CTPNStmEnclosing *enclosing);
1741
1742
    /* generate code */
1743
    virtual void gen_code(int discard, int for_condition);
1744
1745
    /* generate code for 'break' */
1746
    virtual int gen_code_break(const textchar_t *lbl, size_t lbl_len);
1747
1748
    /* generate code for 'continue' */
1749
    virtual int gen_code_continue(const textchar_t *lbl, size_t lbl_len);
1750
1751
    /* 
1752
     *   Generate code for a labeled 'continue'.  We'll simply generate
1753
     *   code for a labeled continue in our enclosed statement.
1754
     *   
1755
     *   (This is normally a routine that *we* call on our contained
1756
     *   statement in response to a 'continue' being targeted at this
1757
     *   label.  This can be invoked on us, however, when a statement has
1758
     *   multiple labels, and the outer label is mentioned in the 'break'
1759
     *   -- the outer label will call this routine on the inner label,
1760
     *   which is us, so we simply need to pass it along to the enclosed
1761
     *   statement.)  
1762
     */
1763
    virtual int gen_code_labeled_continue()
1764
        { return (stm_ != 0 ? stm_->gen_code_labeled_continue() : FALSE); }
1765
1766
    /* get my 'goto' label */
1767
    struct CTcCodeLabel *get_goto_label();
1768
1769
protected:
1770
    /* the byte label to jump to this statement */
1771
    struct CTcCodeLabel *goto_label_;
1772
1773
    /* the byte label to break from this statement */
1774
    struct CTcCodeLabel *break_label_;
1775
};
1776
1777
/* ------------------------------------------------------------------------ */
1778
/*
1779
 *   'case' label statement 
1780
 */
1781
class CTPNStmCase: public CTPNStmCaseBase
1782
{
1783
public:
1784
    CTPNStmCase() { }
1785
1786
    /* generate code */
1787
    virtual void gen_code(int discard, int for_condition);
1788
};
1789
1790
/* ------------------------------------------------------------------------ */
1791
/*
1792
 *   'default' label statement 
1793
 */
1794
class CTPNStmDefault: public CTPNStmDefaultBase
1795
{
1796
public:
1797
    CTPNStmDefault() { }
1798
1799
    /* generate code */
1800
    virtual void gen_code(int discard, int for_condition);
1801
};
1802
1803
/* ------------------------------------------------------------------------ */
1804
/*
1805
 *   'try' block 
1806
 */
1807
class CTPNStmTry: public CTPNStmTryBase
1808
{
1809
public:
1810
    CTPNStmTry(class CTPNStmEnclosing *enclosing)
1811
        : CTPNStmTryBase(enclosing)
1812
    {
1813
    }
1814
1815
    /* generate code */
1816
    virtual void gen_code(int discard, int for_condition);
1817
1818
    /* generate code for 'break' */
1819
    virtual int gen_code_break(const textchar_t *lbl, size_t lbl_len);
1820
1821
    /* generate code for 'continue' */
1822
    virtual int gen_code_continue(const textchar_t *lbl, size_t lbl_len);
1823
1824
    /* 
1825
     *   Generate the code necessary to unwind for returning.  We must
1826
     *   generate a call to our 'finally' code, then unwind any enclosing
1827
     *   statements. 
1828
     */
1829
    virtual void gen_code_unwind_for_return()
1830
    {
1831
        /* call 'finally' on the way out */
1832
        gen_jsr_finally();
1833
1834
        /* inherit default to unwind enclosing statements */
1835
        CTPNStmTryBase::gen_code_unwind_for_return();
1836
    }
1837
1838
    /* determine if we'll generate code for unwinding from a return */
1839
    virtual int will_gen_code_unwind_for_return() const
1840
    {
1841
        /* we'll generate a call to our 'finally' block if we have one */
1842
        if (finally_stm_ != 0)
1843
            return TRUE;
1844
1845
        /* we'll also generate code if any enclosing statement does */
1846
        return CTPNStmTryBase::will_gen_code_unwind_for_return();
1847
    }
1848
1849
    /* generate the code necessary to transfer out of the block */
1850
    virtual void gen_code_for_transfer_out()
1851
    {
1852
        /* call 'finally' on the way out */
1853
        gen_jsr_finally();
1854
    }
1855
1856
    /* 
1857
     *   generate a local subroutine call to our 'finally' block, if we
1858
     *   have a 'finally' block - this should be invoked whenever code
1859
     *   within the protected block or a 'catch' block executes a break,
1860
     *   continue, return, or goto out of the protected region, or when
1861
     *   merely falling off the end of the protected block or a 'catch'
1862
     *   block.  
1863
     */
1864
    void gen_jsr_finally();
1865
1866
    /* get my 'finally' label */
1867
    struct CTcCodeLabel *get_finally_lbl() const { return finally_lbl_; }
1868
    
1869
protected:
1870
    /* our 'finally' label */
1871
    struct CTcCodeLabel *finally_lbl_;
1872
};
1873
1874
/* ------------------------------------------------------------------------ */
1875
/*
1876
 *   'catch'
1877
 */
1878
class CTPNStmCatch: public CTPNStmCatchBase
1879
{
1880
public:
1881
    CTPNStmCatch() { }
1882
1883
    /* generate code */
1884
    virtual void gen_code(int discard, int for_condition);
1885
1886
    /* generate code for the 'catch' clause */
1887
    virtual void gen_code_catch(ulong protected_start_ofs,
1888
                                ulong protected_end_ofs);
1889
};
1890
1891
/* ------------------------------------------------------------------------ */
1892
/*
1893
 *   'finally' 
1894
 */
1895
class CTPNStmFinally: public CTPNStmFinallyBase
1896
{
1897
public:
1898
    CTPNStmFinally(CTPNStmEnclosing *enclosing,
1899
                   int exc_local_id, int jsr_local_id)
1900
        : CTPNStmFinallyBase(enclosing, exc_local_id, jsr_local_id)
1901
    {
1902
    }
1903
1904
    /* generate code */
1905
    virtual void gen_code(int discard, int for_condition);
1906
1907
    /* generate code for the 'finally' clause */
1908
    virtual void gen_code_finally(ulong protected_start_ofs,
1909
                                  ulong protected_end_ofs,
1910
                                  class CTPNStmTry *try_stm);
1911
1912
    /* check for transfer in via 'goto' statements */
1913
    virtual int check_enter_by_goto(class CTPNStmGoto *goto_stm,
1914
                                    class CTPNStmLabel *target);
1915
};
1916
1917
1918
/* ------------------------------------------------------------------------ */
1919
/*
1920
 *   'throw' statement 
1921
 */
1922
class CTPNStmThrow: public CTPNStmThrowBase
1923
{
1924
public:
1925
    CTPNStmThrow(class CTcPrsNode *expr)
1926
        : CTPNStmThrowBase(expr)
1927
    {
1928
    }
1929
    
1930
    /* generate code */
1931
    virtual void gen_code(int discard, int for_condition);
1932
};
1933
1934
1935
/* ------------------------------------------------------------------------ */
1936
/*
1937
 *   'goto' statement 
1938
 */
1939
class CTPNStmGoto: public CTPNStmGotoBase
1940
{
1941
public:
1942
    CTPNStmGoto(const textchar_t *lbl, size_t lbl_len)
1943
        : CTPNStmGotoBase(lbl, lbl_len)
1944
    {
1945
    }
1946
1947
    /* generate code */
1948
    virtual void gen_code(int discard, int for_condition);
1949
};
1950
1951
/* ------------------------------------------------------------------------ */
1952
/*
1953
 *   'dictionary' statement 
1954
 */
1955
class CTPNStmDict: public CTPNStmDictBase
1956
{
1957
public:
1958
    CTPNStmDict(class CTcDictEntry *dict)
1959
        : CTPNStmDictBase(dict)
1960
    {
1961
    }
1962
1963
    /* generate code */
1964
    virtual void gen_code(int, int) { }
1965
};
1966
1967
/* ------------------------------------------------------------------------ */
1968
/*
1969
 *   Object Definition 
1970
 */
1971
class CTPNStmObject: public CTPNStmObjectBase
1972
{
1973
public:
1974
    CTPNStmObject(class CTcSymObj *obj_sym, int is_class)
1975
        : CTPNStmObjectBase(obj_sym, is_class)
1976
    {
1977
    }
1978
1979
    /* generate code */
1980
    virtual void gen_code(int discard, int for_condition);
1981
1982
    /* check locals */
1983
    virtual void check_locals();
1984
1985
    /* 
1986
     *   given the stream offset for the start of the object data in the
1987
     *   stream, get information on the object from the stream data:
1988
     *   
1989
     *.  - get the number of properties in the stream data 
1990
     *.  - set the number of properties in the stream data, updating the
1991
     *   stored data size in the metaclass header in the stream; returns
1992
     *   the new data size
1993
     *.  - get the number of superclasses in the stream data
1994
     *.  - get a superclass object ID
1995
     *.  - get the offset of the first property in the stream data
1996
     *.  - get the offset of the property at the given index
1997
     *.  - get the ID of the object's property at the given index
1998
     *.  - set the ID of the object's property at the given index
1999
     *.  - get the object flags from the tads-object header
2000
     *.  - set the object flags in the tads-object heade 
2001
     */
2002
    static uint get_stream_prop_cnt(class CTcDataStream *stream,
2003
                                    ulong obj_ofs);
2004
    static size_t set_stream_prop_cnt(class CTcDataStream *stream,
2005
                                      ulong obj_ofs, uint prop_cnt);
2006
    static uint get_stream_sc_cnt(class CTcDataStream *stream,
2007
                                  ulong obj_ofs);
2008
    static vm_obj_id_t get_stream_sc(class CTcDataStream *stream,
2009
                                     ulong obj_ofs, uint sc_idx);
2010
    static void set_stream_sc(class CTcDataStream *stream,
2011
                              ulong obj_ofs, uint sc_idx, vm_obj_id_t new_sc);
2012
    static ulong get_stream_first_prop_ofs(class CTcDataStream *stream,
2013
                                           ulong obj_ofs);
2014
    static ulong get_stream_prop_ofs(class CTcDataStream *stream,
2015
                                     ulong obj_ofs, uint prop_idx);
2016
    static vm_prop_id_t get_stream_prop_id(class CTcDataStream *stream,
2017
                                           ulong obj_ofs, uint prop_idx);
2018
    static enum vm_datatype_t
2019
        get_stream_prop_type(class CTcDataStream *stream,
2020
                             ulong obj_ofs, uint prop_idx);
2021
    static ulong get_stream_prop_val_ofs(class CTcDataStream *stream,
2022
                                         ulong obj_ofs, uint prop_idx);
2023
    static void set_stream_prop_id(class CTcDataStream *stream,
2024
                                   ulong obj_ofs, uint prop_idx,
2025
                                   vm_prop_id_t new_id);
2026
    static uint get_stream_obj_flags(class CTcDataStream *stream,
2027
                                     ulong obj_ofs);
2028
    static void set_stream_obj_flags(class CTcDataStream *stream,
2029
                                     ulong obj_ofs, uint flags);
2030
};
2031
2032
/*
2033
 *   Property Value list entry 
2034
 */
2035
class CTPNObjProp: public CTPNObjPropBase
2036
{
2037
public:
2038
    CTPNObjProp(class CTPNStmObject *obj_stm, class CTcSymProp *prop_sym,
2039
                class CTcPrsNode *expr, class CTPNCodeBody *code_body,
2040
                int is_static)
2041
        : CTPNObjPropBase(obj_stm, prop_sym, expr, code_body, is_static)
2042
    {
2043
    }
2044
    
2045
    /* generate code */
2046
    virtual void gen_code(int discard, int for_condition);
2047
2048
    /* check locals */
2049
    void check_locals();
2050
};
2051
2052
/*
2053
 *   Implicit constructor 
2054
 */
2055
class CTPNStmImplicitCtor: public CTPNStmImplicitCtorBase
2056
{
2057
public:
2058
    CTPNStmImplicitCtor(class CTPNStmObject *obj_stm)
2059
        : CTPNStmImplicitCtorBase(obj_stm)
2060
    {
2061
    }
2062
2063
    /* generate code */
2064
    virtual void gen_code(int discard, int for_condition);
2065
};
2066
2067
2068
#endif /* TCT3DRV_H */