cfad47cfa3/t3compiler/tads3/tct3base.h

4b825dc642cb6eb9a060e54bf8d69288fbee4904cfad47cfa334b206c65f22086bcc5d63e6f70944
1
/* $Header: d:/cvsroot/tads/tads3/TCT3BASE.H,v 1.3 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
  tct3base.h - base parse node classes for T3 code generator
12
Function
13
  
14
Notes
15
  
16
Modified
17
  05/10/99 MJRoberts  - Creation
18
*/
19
20
#ifndef TCT3BASE_H
21
#define TCT3BASE_H
22
23
#include "tcprs.h"
24
25
/* include the target-independent base classes */
26
#include "tcpnbase.h"
27
28
29
/* ------------------------------------------------------------------------ */
30
/*
31
 *   Base parse node class 
32
 */
33
class CTcPrsNode: public CTcPrsNodeBase
34
{
35
public:
36
    /*
37
     *   Generate code to assign into the expression as an lvalue.  By
38
     *   default, we'll throw an error; a default node should never be
39
     *   called upon to generate code as an assignment target, because the
40
     *   impossibility of this condition should be detected during
41
     *   parsing.  Each class that overrides check_lvalue() to return true
42
     *   must override this to generate code for an assignment.
43
     *   
44
     *   Returns true if the assignment type was handled, false if not.
45
     *   Simple assignment must always be handled, but composite
46
     *   assignments (such as "+=" or "*=") can refused.  If the
47
     *   assignment isn't handled, the caller must perform a generic
48
     *   calculation to compute the result of the assignment (for example,
49
     *   for "+=", the caller must generate code compute the sum of the
50
     *   right-hand side and the original value of the left-hand side),
51
     *   then call gen_code_asi() again to generate a simple assignment.
52
     *   
53
     *   In general, gen_code_asi() must generate code for complex
54
     *   assignments itself only when it can take advantage of special
55
     *   opcodes that would result in more efficient generated code.  When
56
     *   no special opcodes are available for the assignment, there's no
57
     *   need for special coding here.
58
     *   
59
     *   If 'ignore_error' is true, this should not generate an error if
60
     *   this node is not a suitable lvalue, but should simply return
61
     *   false.  
62
     */
63
    virtual int gen_code_asi(int discard, tc_asitype_t typ,
64
                             class CTcPrsNode *rhs,
65
                             int ignore_error);
66
67
    /*
68
     *   Generate code to take the address of the expression.  By default,
69
     *   we'll throw an internal error; a default node should never be
70
     *   called upon to generate code to take its address, because we
71
     *   shouldn't be able to parse such a thing.  Each class that
72
     *   overrides has_addr() to return true must override this to
73
     *   generate address code.  
74
     */
75
    virtual void gen_code_addr();
76
77
    /*
78
     *   Generate an if-then-else condition test.  This is called on the
79
     *   controlling expression of an if-then-else, and can also be called on
80
     *   subexpressions of short-circuit operators (|| and &&).  The purpose
81
     *   of this type of code generation is to avoid pushing the result of
82
     *   the controlling expression onto the stack when this can be avoided,
83
     *   and generate a jump to the appropriate if-else branch directly.
84
     *   
85
     *   Either then_label or else_label will be non-null; the one that's
86
     *   null directly follows the condition test, so we are simply to fall
87
     *   through to that code rather than jump to it explicitly.  
88
     */
89
    virtual void gen_code_cond(struct CTcCodeLabel *then_label,
90
                               struct CTcCodeLabel *else_label);
91
    
92
    /*
93
     *   Generate code to call the expression as a function or method.
94
     *   The caller will already have generated code to push the argument
95
     *   list; this routine only needs to generate code to make the call.
96
     *   
97
     *   By default, we'll assume that the result of evaluating the
98
     *   expression is a method or function pointer, so we'll generate a
99
     *   call-indirect instruction to call the result of evaluating the
100
     *   expression.  
101
     */
102
    virtual void gen_code_call(int discard, int argc, int varargs);
103
104
    /*
105
     *   Generate code to apply operator 'new' to the expression.  By
106
     *   default, 'new' cannot be applied to an expression; nodes that
107
     *   allow operator 'new' must override this.  
108
     */
109
    virtual void gen_code_new(int discard, int argc, int varargs,
110
                              int from_call, int is_transient);
111
112
    /*
113
     *   Generate code to evaluate a member expression on this object
114
     *   expression, calling the property expression given.  By default,
115
     *   we'll evaluate our own expression to yield the object value, then
116
     *   get the property expression (either as a constant or by
117
     *   generating code to yield a property pointer), then we'll invoke
118
     *   that code.  Nodes should override this where more specific
119
     *   instructions can be generated.
120
     *   
121
     *   If 'prop_is_expr' is true, the property expression (prop_expr) is
122
     *   a parenthesized expression; otherwise, it's a simple property
123
     *   symbol.  (We need this information because a symbol enclosed in
124
     *   parentheses would be otherwise indistinguishable from a plain
125
     *   symbol, but the two syntax cases differ in their behavior: a
126
     *   plain symbol is always a property name, whereas a symbol in
127
     *   parentheses can be a local variable.)  
128
     */
129
    virtual void gen_code_member(int discard,
130
                                 class CTcPrsNode *prop_expr,
131
                                 int prop_is_expr,
132
                                 int argc, int varargs);
133
134
    /*
135
     *   Generate code for an object on the left side of a '.' expression.
136
     *   If possible, return the constant object rather than generating
137
     *   code.  If the expression refers to "self", set (*is_self) to true
138
     *   and return VM_INVALID_OBJ; otherwise, if the expression refers to
139
     *   a constant object reference, set (*is_self) to false and return
140
     *   the constant object value; otherwise, generate code for the
141
     *   expression, set (*is_self) to false, and return VM_INVALID_OBJ to
142
     *   indicate that the value must be obtained from the generated code
143
     *   at run-time.
144
     *   
145
     *   By default, we'll use generated code to get the value.  
146
     */
147
    virtual vm_obj_id_t gen_code_obj_predot(int *is_self)
148
    {
149
        /* generate the expression */
150
        gen_code(FALSE, FALSE);
151
152
        /* tell the caller that the value is not a compile-time constant */
153
        *is_self = FALSE;
154
        return VM_INVALID_OBJ;
155
    }
156
    
157
158
    /* 
159
     *   generic generation for a member expression after the left side
160
     *   has been generated 
161
     */
162
    static void s_gen_member_rhs(int discard,
163
                                 class CTcPrsNode *prop_expr,
164
                                 int prop_is_expr, int argc, int varargs);
165
166
    /*
167
     *   Get the property ID of this expression.  If the property ID is
168
     *   available as a constant value, this doesn't generate any code and
169
     *   simply returns the constant property ID value.  If this
170
     *   expression requires run-time evaluation, we'll generate code for
171
     *   the expression and return VM_INVALID_PROP to indicate that a
172
     *   constant property ID is not available.
173
     *   
174
     *   If 'check_only' is true, this routine should only check to see
175
     *   whether a constant property value is available and return the
176
     *   appropriate indication, but should not generate any code in any
177
     *   case.  Errors should also be suppressed in this case, because the
178
     *   routine will always be called again to perform the actual
179
     *   generation, at which point any errors can be logged.
180
     *   
181
     *   If 'is_expr' is true, it means that this property was given as an
182
     *   expression by being explicitly enclosed in parentheses.  If
183
     *   'is_expr' is false, it means that the property was given as a
184
     *   simple symbol name.  For cases where the property expression is a
185
     *   symbol, this distinction is important because we must resolve an
186
     *   unparenthesized symbol as a property name, even if it's hidden by
187
     *   a local variable.  
188
     */
189
    virtual vm_prop_id_t gen_code_propid(int check_only, int is_expr);
190
191
    /* 
192
     *   generate a jump-ahead instruction, returning a new label which
193
     *   serves as the jump destination 
194
     */
195
    static struct CTcCodeLabel *gen_jump_ahead(uchar opc);
196
197
    /* define the position of a code label */
198
    static void def_label_pos(struct CTcCodeLabel *lbl);
199
200
    /* allocate a new label at the current write position */
201
    static struct CTcCodeLabel *new_label_here();
202
};
203
204
/* ------------------------------------------------------------------------ */
205
/*
206
 *   Basic T3-specific symbol class 
207
 */
208
class CTcSymbol: public CTcSymbolBase
209
{
210
public:
211
    CTcSymbol(const char *str, size_t len, int copy, tc_symtype_t typ)
212
        : CTcSymbolBase(str, len, copy, typ) { }
213
214
    /* 
215
     *   get the object value for the symbol, if the symbol has an object
216
     *   value; returns VM_INVALID_OBJ if the symbol is not an object 
217
     */
218
    virtual vm_obj_id_t get_val_obj() const { return VM_INVALID_OBJ; }
219
220
    /* generate code to evaluate the symbol */
221
    virtual void gen_code(int discard) = 0;
222
223
    /* 
224
     *   Generate code to assign to the symbol.  By default, we'll
225
     *   generate an error indicating that the symbol cannot be assigned
226
     *   into.  As with CTcPrsNode::gen_code_asi(), this returns true if
227
     *   the assignment was generated, false if the caller must generate a
228
     *   generic assignment; simple assignment must always return true.
229
     *   
230
     *   If 'rhs' is null, the caller has already generated the value to
231
     *   be assigned, so this code doesn't need to do that.  Otherwise,
232
     *   this code must generate the rvalue code.  The reason that 'rhs'
233
     *   is passed down at all is that we can sometimes optimize the type
234
     *   of opcode we generate according to the type of value being
235
     *   assigned, especially when a constant value is being assigned.
236
     *   
237
     *   If 'ignore_error' is true, this should not log an error if the
238
     *   value cannot be assigned.  
239
     */
240
    virtual int gen_code_asi(int discard, tc_asitype_t typ,
241
                             class CTcPrsNode *rhs, int ignore_error);
242
243
    /* 
244
     *   Generate code for taking the address of the symbol.  By default,
245
     *   we'll generate an error indicating that the symbol's address
246
     *   cannot be taken. 
247
     */
248
    virtual void gen_code_addr();
249
250
    /*
251
     *   Generate code to call the symbol.  By default, we can't call a
252
     *   symbol.  
253
     */
254
    virtual void gen_code_call(int discard, int argc, int varargs);
255
256
    /* 
257
     *   generate code for operator 'new' applied to the symbol, with the
258
     *   given number of arguments; by default, we can't generate any such
259
     *   code 
260
     */
261
    virtual void gen_code_new(int discard, int argc, int varargs,
262
                              int is_transient);
263
264
    /* evaluate a property ID */
265
    virtual vm_prop_id_t gen_code_propid(int check_only, int is_expr);
266
267
    /* generate code for a member expression */
268
    virtual void gen_code_member(int discard,
269
                                 class CTcPrsNode *prop_expr,
270
                                 int prop_is_expr,
271
                                 int argc, int varargs);
272
273
    /* get the object value for a '.' expression */
274
    virtual vm_obj_id_t gen_code_obj_predot(int *is_self);
275
276
    /* 
277
     *   Write the symbol to a local frame debugging record in the code
278
     *   stream.  Returns true if we wrote the symbol, false if not.  By
279
     *   default, we'll write nothing and return false, since most symbols
280
     *   aren't used in local symbol tables.  
281
     */
282
    virtual int write_to_debug_frame() { return FALSE; }
283
284
    /*
285
     *   Write the symbol to the global symbol table in the debugging
286
     *   records in an image file.  Returns true if we wrote the symbol,
287
     *   false if not.  By default, we'll write nothing and return false,
288
     *   since by default symbols don't go in the image file's global
289
     *   symbol table.
290
     */
291
    virtual int write_to_image_file_global(class CVmImageWriter *)
292
        { return FALSE; }
293
};
294
295
#endif /* TCT3BASE_H */
296