Rune - Generation work
[rune.git] / librune / exp.c
1 /*
2  * EXP.C
3  *
4  * (c)Copyright 1993-2014, Matthew Dillon, All Rights Reserved.  See the  
5  *    COPYRIGHT file at the base of the distribution.
6  */
7
8 #include "defs.h"
9
10 Exp *
11 _AllocExpDebug(token_t *tok, const char *file, int line)
12 {
13         fprintf(stderr, "allocate from %s:%d\n", file, line);
14         return(_AllocExp(tok));
15 }
16
17 Exp *
18 _AllocExp(token_t *tok)
19 {
20         Exp *exp = zalloc(sizeof(Exp));
21         exp->ex_Run = RunUnresolvedExp;
22         exp->ex_Gen = GenUnresolvedExp;
23         exp->ex_Visibility = SCOPE_ALL_VISIBLE | 0x80000000;
24         exp->ex_TmpOffset = -1;
25         if (tok)
26                 LexInitRef(&exp->ex_LexRef, tok);
27         return(exp);
28 }
29
30 void
31 FreeExp(Exp *next)
32 {
33         Exp *exp;
34
35         while ((exp = next) != NULL) {
36                 RelStrTable(&exp->ex_Id);
37                 FreeExp(exp->ex_Lhs);
38                 FreeExp(exp->ex_Rhs);
39                 exp->ex_Lhs = NULL;     /* safety */
40                 exp->ex_Rhs = NULL;     /* safety */
41                 /* XXX free type */
42                 next = exp->ex_Next;
43                 exp->ex_Next = NULL;
44                 LexDoneRef(&exp->ex_LexRef);
45                 zfree(exp, sizeof(Exp));
46         }
47 }
48
49 /*
50  * Wrap an expression (used for things like typeof()).  The
51  * passed expression may be NULL.
52  */
53 Exp *
54 WrapExp(token_t *tok, Exp *oexp, int t)
55 {
56         Exp *exp = AllocExp(NULL);
57
58         exp->ex_Lhs = oexp;
59         exp->ex_Token = t;
60         if (oexp) {
61                 LexDupRef(&oexp->ex_LexRef, &exp->ex_LexRef);
62                 exp->ex_Flags |= EXF_UNARY;
63                 exp->ex_ArgId = oexp->ex_ArgId;
64                 oexp->ex_ArgId = NULL;
65         } else {
66                 LexInitRef(&exp->ex_LexRef, tok);
67         }
68         return(exp);
69 }
70
71 /*
72  * Invert the sense of a boolean expression
73  */
74 Exp *
75 ExpToNotExp(Exp *oexp)
76 {
77         Exp *exp = AllocExp(NULL);
78
79         LexDupRef(&oexp->ex_LexRef, &exp->ex_LexRef);
80
81         exp->ex_Lhs = oexp;
82         exp->ex_Token = TOK_NOT;
83         exp->ex_Type = &BoolType;
84         exp->ex_Flags |= EXF_UNARY | EXF_PARSE_TYPE;
85         exp->ex_Flags |= oexp->ex_Flags & EXF_DUPEXP;
86         exp->ex_ArgId = oexp->ex_ArgId;
87         oexp->ex_ArgId = NULL;
88         return(exp);
89 }
90
91 /*
92  * General Cast
93  */
94 Exp *
95 ExpToCastExp(Exp *oexp, Type *type)
96 {
97         if (oexp->ex_Type != type) {
98                 Exp *exp = AllocExp(NULL);
99
100                 LexDupRef(&oexp->ex_LexRef, &exp->ex_LexRef);
101                 exp->ex_Lhs = oexp;
102                 exp->ex_Token = TOK_CAST;
103                 exp->ex_Type = type;
104                 exp->ex_Flags |= EXF_UNARY | EXF_PARSE_TYPE;
105                 exp->ex_Flags |= oexp->ex_Flags & EXF_DUPEXP;
106                 exp->ex_ArgId = oexp->ex_ArgId;
107                 oexp->ex_ArgId = NULL;
108                 oexp = exp;
109         }
110         return(oexp);
111 }
112
113 /*
114  * Convert a list of expressions linked by ex_Next to a compound expression.
115  * Note that a degenerate TOK_VOIDEXP converts to an empty compound
116  * expression (just as () was originally parsed as TOK_VOIDEXP).
117  *
118  * Since ex_Next is used for other purposes, such as the resolver's
119  * method call conversion code, we have to return a consolidated
120  * TOK_COMPOUND expression node whos Lhs bases a linked list of 
121  * expressions representing the compound expression.
122  *
123  * Compound expressions need a type hint to be evaluated properly (handled
124  * elsewhere).
125  *
126  * Note that we do not promote ex_ArgId to the compound element here.  This
127  * function is designed to create a compound expression out of a linked list,
128  * not really to convert a non-compound expression to a compound expression
129  * (though it does that too).
130  */
131
132 Exp *
133 ExpToCompoundExp(Exp *oexp, int t)
134 {
135         Exp *exp = AllocExp(NULL);
136
137         LexDupRef(&oexp->ex_LexRef, &exp->ex_LexRef);
138         if (oexp->ex_Token == TOK_VOIDEXP && oexp->ex_Next == NULL)
139                 exp->ex_Lhs = NULL;
140         else
141                 exp->ex_Lhs = oexp;
142         exp->ex_Token = t;
143         exp->ex_Flags |= EXF_COMPOUND;
144         exp->ex_Flags |= oexp->ex_Flags & EXF_DUPEXP;
145         return(exp);
146 }
147
148 Exp *
149 SetDupExp(SemGroup *sg, Exp *exp)
150 {
151         if (exp && (exp->ex_Flags & EXF_DUPEXP) == 0) {
152                 exp->ex_Flags |= EXF_DUPEXP;
153                 if (exp->ex_Lhs)
154                         SetDupExp(sg, exp->ex_Lhs);
155                 if (exp->ex_Rhs)
156                         SetDupExp(sg, exp->ex_Rhs);
157                 if (exp->ex_Next)
158                         SetDupExp(sg, exp->ex_Next);
159         }
160         return(exp);
161 }
162
163 /*
164  * DupExp() - duplicate an expression
165  *
166  *      This occurs during the superclass/subclass merge, before we
167  *      resolve any expression trees.
168  */
169 Exp *
170 DupExp(SemGroup *sg, Exp *oexp)
171 {
172         Exp *exp;
173
174         if (oexp) {
175                 exp = AllocExp(NULL);
176                 LexDupRef(&oexp->ex_LexRef, &exp->ex_LexRef);
177                 dassert_exp(exp, exp->ex_Decl == NULL);
178
179                 switch(oexp->ex_Flags & (EXF_COMPOUND|EXF_UNARY|EXF_BINARY)) {
180                 case EXF_COMPOUND:
181                         dassert_exp(oexp, oexp->ex_Rhs == NULL);
182                         if (oexp->ex_Lhs) {
183                                 Exp **pscan;
184                                 Exp *oscan;
185
186                                 pscan = &exp->ex_Lhs;
187                                 for (oscan = oexp->ex_Lhs;
188                                      oscan;
189                                      oscan = oscan->ex_Next) {
190                                         *pscan = DupExp(sg, oscan);
191                                         pscan = &(*pscan)->ex_Next;
192                                 }
193                         }
194                         break;
195                 case EXF_UNARY:
196                         /*
197                          * Duplicate a unary expression.  We do NOT duplicate
198                          * alias substitutions, that creates havoc.
199                          */
200                         dassert_exp(oexp, oexp->ex_Lhs);
201                         dassert_exp(oexp, oexp->ex_Rhs == NULL);
202                         if (oexp->ex_Flags & EXF_ALIAS)
203                                 exp->ex_Lhs = NULL;
204                         else
205                                 exp->ex_Lhs = DupExp(sg, oexp->ex_Lhs);
206                         break;
207                 case EXF_BINARY:
208                         dassert_exp(oexp, oexp->ex_Lhs);
209                         dassert_exp(oexp, oexp->ex_Rhs);
210                         exp->ex_Lhs = DupExp(sg, oexp->ex_Lhs);
211                         exp->ex_Rhs = DupExp(sg, oexp->ex_Rhs);
212                         break;
213                 default:
214                         if (oexp->ex_Flags & (EXF_COMPOUND |
215                                               EXF_UNARY |
216                                               EXF_BINARY)) {
217                                 dassert_exp(oexp, 0);
218                         }
219                         dassert_exp(oexp, oexp->ex_Lhs == NULL);
220                         dassert_exp(oexp, oexp->ex_Rhs == NULL);
221                         break;
222                 }
223                 exp->ex_Prec = oexp->ex_Prec;
224                 exp->ex_Flags = oexp->ex_Flags & ~(EXF_DUPEXP | EXF_RESOLVED);
225
226                 /*
227                  * NOTE!  Special case!  ex_Decl is only non-NULL when we do
228                  * a TypeToQualType() and have to dup an expression
229                  * post-resolve.  sg will be NULL in this case.
230                  *
231                  * XXX DupExp optimization invalidates this test, don't assert.
232                  * XXX add EXF_PARSE_DECL
233                  */
234 #if 0
235                 dassert_exp(exp, oexp->ex_Decl == NULL || sg == NULL);
236 #endif
237                 exp->ex_Decl = oexp->ex_Decl;
238                 exp->u = oexp->u;
239                 if (oexp->ex_Id)
240                         exp->ex_Id = StrTableDup(oexp->ex_Id);
241                 if (oexp->ex_ArgId)
242                         exp->ex_ArgId = StrTableDup(oexp->ex_ArgId);
243                 exp->ex_Token = oexp->ex_Token;
244
245                 /*
246                  * The type may be left over from the original resolution of
247                  * the expression prior to duplication.  Only copy types
248                  * set at parse time.  Duplicated expressions gain their
249                  * non-parse type simply by being re-resolved.
250                  */
251                 if ((oexp->ex_Flags & EXF_PARSE_TYPE) && oexp->ex_Type)
252                         exp->ex_Type = DupType(sg, oexp->ex_Type);
253         } else {
254                 exp = NULL;
255         }
256         return(exp);
257 }
258
259 void
260 ExpPrintError(Exp *exp, int type)
261 {
262         LexPrintRef(&exp->ex_LexRef, type);
263 }