cfad47cfa3/t2compiler/tads2/prs.c

4b825dc642cb6eb9a060e54bf8d69288fbee4904cfad47cfa334b206c65f22086bcc5d63e6f70944
1
#ifdef RCSID
2
static char RCSid[] =
3
"$Header: d:/cvsroot/tads/TADS2/PRS.C,v 1.2 1999/05/17 02:52:13 MJRoberts Exp $";
4
#endif
5
6
/* 
7
 *   Copyright (c) 1991, 2002 Michael J. Roberts.  All Rights Reserved.
8
 *   
9
 *   Please see the accompanying license file, LICENSE.TXT, for information
10
 *   on using and copying this software.  
11
 */
12
/*
13
Name
14
  prs.c - code parser
15
Function
16
  Parse TADS code
17
Notes
18
  This module contains the TADS code parser.  TADS code is basically
19
  a series of object definitions (a function is just a special kind
20
  of object).  So, this module has a function that reads from a line
21
  source and generates a compiled object.  Compiled objects are
22
  completely self-contained, apart from references to other objects.
23
  We initially allocate a block of space for the object, then make
24
  it larger if need be.  If it's a class object, we will reduce its
25
  size down to its actual size, because class objects generally are
26
  not modified at run-time.
27
Modified
28
  04/11/99 CNebel        - Fix signing errors.
29
  09/14/92 MJRoberts     - note where an object was created
30
  08/27/91 MJRoberts     - creation
31
*/
32
33
#include <string.h>
34
#include <assert.h>
35
#include "os.h"
36
#include "std.h"
37
#include "mcm.h"
38
#include "tok.h"
39
#include "prs.h"
40
#include "lst.h"
41
#include "prp.h"
42
#include "obj.h"
43
#include "opc.h"
44
#include "emt.h"
45
#include "mch.h"
46
#include "voc.h"
47
48
49
/* allocate space from node pool */
50
static prsndef *prsalo(prscxdef *ctx, int subnodes);
51
52
/* parse an expression (can be called recursively) */
53
static prsndef *prsxexp(prscxdef *ctx, int inlist);
54
55
/* add a symbol to the symbol table if it's not already there */
56
void prsdef(prscxdef *ctx, tokdef *tok, int typ)
57
{
58
    toktdef *tab;
59
    
60
    tab = (typ == TOKSTLABEL ? ctx->prscxgtab : ctx->prscxstab);
61
    
62
    if (tok->toktyp == TOKTSYMBOL && tok->toksym.tokstyp == TOKSTUNK)
63
    {
64
        if (!tab) errsig(ctx->prscxerr, ERR_UNDFSYM);
65
                         
66
        /* see if it's been defined since we last looked */
67
        if (!(*tab->toktfsea)(tab, tok->toknam, tok->toklen,
68
                              tok->tokhash, &tok->toksym))
69
        {
70
            /* still not defined; add to the symbol table */
71
            (*tab->toktfadd)(tab, tok->toknam, tok->toklen,
72
                             TOKSTUNK, 0, tok->tokhash);
73
            (*tab->toktfsea)(tab, tok->toknam, tok->toklen,
74
                             tok->tokhash, &tok->toksym);
75
        }
76
    }
77
    if (tok->toktyp == TOKTSYMBOL && tok->toksym.tokstyp == TOKSTUNK)
78
    {
79
        if (!tab) errsig(ctx->prscxerr, ERR_UNDFSYM);
80
81
        switch(typ)
82
        {
83
        case TOKSTPROP:
84
            tok->toksym.toksval = ctx->prscxprp++;
85
            break;
86
87
        case TOKSTFWDOBJ:
88
        case TOKSTFWDFN:
89
            /* fill in the symbol with the object information */
90
            prsdefobj(ctx, tok, typ);
91
            break;
92
93
        case TOKSTEXTERN:
94
            tok->toksym.toksval = ctx->prscxextc++;
95
            break;
96
            
97
        case TOKSTLABEL:
98
            tok->toksym.toksval = emtglbl(ctx->prscxemt);
99
            break;
100
        }
101
        tok->toksym.tokstyp = typ;
102
        (*tab->toktfset)(tab, &tok->toksym);
103
    }
104
}
105
106
/* define a symbol as an object or forward object */
107
void prsdefobj(prscxdef *ctx, tokdef *tok, int typ)
108
{
109
    mcmon  newobj;
110
    uchar *p;
111
112
    /* allocate the object and clear its memory */
113
    p = mcmalo(ctx->prscxmem, (ushort)PRSOBJSIZ, &newobj);
114
    memset(p, 0, (size_t)OBJDEFSIZ);
115
116
    /* save the line position after the object header */
117
    linppos(ctx->prscxtok->tokcxlin, (char *)p + OBJDEFSIZ,
118
            (uint)(PRSOBJSIZ - OBJDEFSIZ));
119
120
#ifdef OS_ERRLINE
121
    /* save the source line for error displays later on */
122
    {
123
        int   len;
124
        int   need;
125
126
                    /* compute how much space we'll need for the line */
127
        len = ctx->prscxtok->tokcxlin->linlen + 1;
128
        need = len + OBJDEFSIZ
129
               + strlen((char *)p + OBJDEFSIZ) + 1;
130
131
                    /* reallocate the object if we need more room */
132
        if (need > PRSOBJSIZ)
133
            p = mcmrealo(ctx->prscxmem, newobj, need);
134
135
                    /* copy the line */
136
        p += OBJDEFSIZ;
137
        p += strlen((char *)p) + 1;
138
        memcpy(p, ctx->prscxtok->tokcxlin->linbuf, (size_t)len);
139
        p[len] = '\0';
140
    }
141
#endif
142
143
    /* unlock the object */
144
    mcmtch(ctx->prscxmem, newobj);
145
    mcmunlck(ctx->prscxmem, newobj);
146
147
    /* set the symbol to point to the new object */
148
    tok->toksym.toksval = newobj;
149
}
150
151
/* require a property identifier, returning the property number */
152
prpnum prsrqpr(prscxdef *ctx)
153
{
154
    tokdef *tok = &ctx->prscxtok->tokcxcur;
155
    prpnum  ret;
156
        
157
    /* make sure we get a symbol */
158
    if (tok->toktyp != TOKTSYMBOL)
159
        errsig(ctx->prscxerr, ERR_REQSYM);
160
    
161
    /* if it's an undefined symbol, make it a property id */
162
    if (tok->toksym.tokstyp == TOKSTUNK)
163
        prsdef(ctx, tok, TOKSTPROP);
164
    
165
    /* make sure we have a property */
166
    if (tok->toksym.tokstyp != TOKSTPROP)
167
        errsig(ctx->prscxerr, ERR_REQPRP);
168
    
169
    ret = tok->toksym.toksval;
170
    toknext(ctx->prscxtok);
171
    return(ret);
172
}
173
174
/* signal a "missing required token" error, finding token name */
175
void prssigreq(prscxdef *ctx, int t)
176
{
177
    int   i;
178
    char *p;
179
    static struct
180
    {
181
        int   tokid;
182
        char *toknam;
183
    } toklist[] =
184
    {
185
        { TOKTSEM, "semicolon" },
186
        { TOKTCOLON, "colon" },
187
        { TOKTFUNCTION, "\"function\"" },
188
        { TOKTCOMMA, "comma" },
189
        { TOKTLBRACE, "left brace ('{')" },
190
        { TOKTRPAR, "right paren (')')" },
191
        { TOKTRBRACK, "right square bracket (']')" },
192
        { TOKTWHILE, "\"while\"" },
193
        { TOKTLPAR, "left paren ('(')" },
194
        { TOKTEQ, "'='" },
195
        { 0, (char *)0 }
196
    };
197
                    
198
    for (i = 0 ; toklist[i].toknam ; ++i)
199
    {
200
        if (toklist[i].tokid == t)
201
        {
202
            p = toklist[i].toknam;
203
            break;
204
        }
205
    }
206
    if (!toklist[i].toknam)
207
        p = "<unknown token>";
208
    errsig1(ctx->prscxerr, ERR_REQTOK, ERRTSTR, p);
209
}
210
211
/* check for and skip a required token */
212
void prsreq(prscxdef *ctx, int t)
213
{
214
    tokdef *tok = &ctx->prscxtok->tokcxcur;
215
    
216
    if (tok->toktyp != t)
217
        prssigreq(ctx, t);
218
    toknext(ctx->prscxtok);
219
}
220
221
/* get next token, require it to be a specific token, and skip it */
222
void prsnreq(prscxdef *ctx, int t)
223
{
224
    tokdef *tok = &ctx->prscxtok->tokcxcur;
225
226
    toknext(ctx->prscxtok);
227
    if (tok->toktyp != t)
228
        prssigreq(ctx, t);
229
    toknext(ctx->prscxtok);
230
}
231
232
/* allocate bytes from node pool */
233
uchar *prsbalo(prscxdef *ctx, uint siz)
234
{
235
    uchar *ret;
236
237
    /* round size for alignment, and see if we have room for it */
238
    siz = osrndsz(siz);
239
    if (ctx->prscxnrem < siz) errsig(ctx->prscxerr, ERR_NONODE);
240
241
    /* adjust sizes and pointers, and return the new node */
242
    ret = ctx->prscxnode;
243
    ctx->prscxnrem -= siz;
244
    ctx->prscxnode += siz;
245
    return(ret);
246
}
247
248
/* allocate a node with a given number of subnodes from node pool */
249
static prsndef *prsalo(prscxdef *ctx, int subnodes)
250
{
251
    uint siz;
252
253
    /* figure size of node we actually need */
254
    siz = offsetof(prsndef, prsnv.prsnvt);
255
    if (subnodes)
256
        siz += (subnodes * sizeof(prsndef *));
257
    else
258
        siz += sizeof(tokdef);
259
    
260
    return((prsndef *)prsbalo(ctx, siz));
261
}
262
263
/* begin a string in expression evaluation mode (puts in node pool) */
264
ushort prsxsst(prscxdef *ctx)
265
{
266
    /* make sure there's space for the length prefix (a ushort) */
267
    if (ctx->prscxnrem < 2)
268
        errsig(ctx->prscxerr, ERR_NONODE);
269
    
270
    ctx->prscxsofs = ctx->prscxnode - &ctx->prscxpool[0];
271
    ctx->prscxnode += 2;
272
    ctx->prscxnrem -= 2;
273
    ctx->prscxslen = 2;
274
    return(ctx->prscxsofs);
275
}
276
277
/* add bytes to a string in expression mode */
278
void prsxsad(prscxdef *ctx, char *p, ushort len)
279
{
280
    /* make sure there's room for the extra bytes */
281
    if (ctx->prscxnrem < len)
282
        errsig(ctx->prscxerr, ERR_NONODE);
283
    
284
    memcpy(ctx->prscxnode, p, (size_t)len);
285
    ctx->prscxnode += len;
286
    ctx->prscxnrem -= len;
287
    ctx->prscxslen += len;
288
}
289
290
/* terminate a string in expression evaluation mode */
291
void prsxsend(prscxdef *ctx)
292
{
293
    ushort siz;
294
    ushort rounded;
295
    
296
    /* figure total size of string, including padding for alignment */
297
    siz = ctx->prscxslen;
298
    
299
    /* write length at beginning of string */
300
    oswp2(&ctx->prscxpool[ctx->prscxsofs], siz);
301
    
302
    /* if desired, write the string to the strings file */
303
    if (ctx->prscxstrfile != 0)
304
    {
305
        uchar *str;
306
307
        str = &ctx->prscxpool[ctx->prscxsofs] + 2;
308
        str[siz - 2] = '\0';
309
        osfputs((char *)str, ctx->prscxstrfile);
310
        osfputs("\n", ctx->prscxstrfile);
311
    }
312
313
    /* round size of string if necessary */
314
    rounded = osrndsz(siz);
315
    if (rounded - siz)
316
    {
317
        rounded -= siz;
318
        if (ctx->prscxnrem < rounded)
319
            errsig(ctx->prscxerr, ERR_NONODE);
320
        ctx->prscxnode += rounded;
321
        ctx->prscxnrem -= rounded;
322
    }
323
}
324
325
/* parse a list */
326
static prsndef *prslst(prscxdef *ctx)
327
{
328
    prsndef *node = (prsndef *)0;
329
    
330
    for (;;)
331
    {
332
        if (ctx->prscxtok->tokcxcur.toktyp == TOKTRBRACK) break;
333
        node = prsnew2(ctx, TOKTRBRACK, prsxexp(ctx, TRUE), node);
334
        
335
        /* allow optional comma (just skip it if one is present) */
336
        if (ctx->prscxtok->tokcxcur.toktyp == TOKTCOMMA)
337
            toknext(ctx->prscxtok);
338
    }
339
    toknext(ctx->prscxtok);                       /* skip the right bracket */
340
    
341
    /* if it's an empty list, make an empty list token for it */
342
    if (!node)
343
    {
344
        tokdef t;
345
        
346
        t.toktyp = TOKTLIST;
347
        t.tokofs = 0;
348
        node = prsnew0(ctx, &t);
349
    }
350
    
351
    return(node);
352
}
353
354
/* build a four-way operator node */
355
prsndef *prsnew4(prscxdef *ctx, int t, prsndef *n1, prsndef *n2,
356
                 prsndef *n3, prsndef *n4)
357
{
358
    prsndef *n = prsalo(ctx, 4);
359
    
360
    n->prsntyp = t;
361
    n->prsnnlf = 4;
362
    n->prsnv.prsnvn[0] = n1;
363
    n->prsnv.prsnvn[1] = n2;
364
    n->prsnv.prsnvn[2] = n3;
365
    n->prsnv.prsnvn[3] = n4;
366
    return(n);
367
}
368
369
/* build a tertiary operator node - three subnodes */
370
prsndef *prsnew3(prscxdef *ctx, int t, prsndef *n1, prsndef *n2, prsndef *n3)
371
{
372
    prsndef *n = prsalo(ctx, 3);
373
    
374
    n->prsntyp = t;
375
    n->prsnnlf = 3;
376
    n->prsnv.prsnvn[0] = n1;
377
    n->prsnv.prsnvn[1] = n2;
378
    n->prsnv.prsnvn[2] = n3;
379
    return(n);
380
}
381
382
/* build a binary operator node - two subnodes */
383
prsndef *prsnew2(prscxdef *ctx, int t, prsndef *n1, prsndef *n2)
384
{
385
    prsndef *n = prsalo(ctx, 2);
386
    
387
    n->prsntyp = t;
388
    n->prsnnlf = 2;
389
    n->prsnv.prsnvn[0] = n1;
390
    n->prsnv.prsnvn[1] = n2;
391
    return(n);
392
}
393
394
/* build a unary operator node - one subnode */
395
prsndef *prsnew1(prscxdef *ctx, int t, prsndef *n)
396
{
397
    prsndef *newnode = prsalo(ctx, 1);
398
399
    newnode->prsntyp = t;
400
    newnode->prsnnlf = 1;
401
    newnode->prsnv.prsnvn[0] = n;
402
    return newnode;
403
}
404
405
/* build a new value node - no subnodes */
406
prsndef *prsnew0(prscxdef *ctx, tokdef *tokp)
407
{
408
    prsndef *n = prsalo(ctx, 0);
409
    
410
    n->prsntyp = 0;                                           /* value node */
411
    n->prsnnlf = 0;
412
    OSCPYSTRUCT(n->prsnv.prsnvt, *tokp);
413
    return(n);
414
}
415
416
/* binary operator definition */
417
typedef struct prsbdef prsbdef;
418
struct prsbdef
419
{
420
    int       *prsblst;          /* list of tokens at this precedence level */
421
    prsndef *(*prsblf)(prscxdef *ctx, prsbdef *binctx);
422
    prsndef *(*prsbrf)(prscxdef *ctx, prsbdef *binctx);
423
    prsbdef   *prsbctx;               /* secondary context for left & right */
424
    int        prsbrpt;                   /* TRUE ==> iterate right operand */
425
};
426
427
428
/* generate code for a function call */
429
static void prsgfn(prscxdef *ctx, prsndef *n, int argcnt);
430
431
/* generate code for an argument list; returns argument count */
432
static int prsgargs(prscxdef *ctx, prsndef *n);
433
434
/* generate code for a property lookup */
435
static void prsgdot(prscxdef *ctx, prsndef *n, int argcnt);
436
437
/* generate code for a property lookup during speculative evaluation */
438
static void prsgdotspec(prscxdef *ctx, prsndef *n);
439
440
/* generate code to assign an l-value */
441
static void prsglval(prscxdef *ctx, int typ, prsndef *n);
442
443
/* Build a general binary node.  The context tells us how. */
444
static prsndef *prsxbin(prscxdef *ctx, prsbdef *binctx);
445
446
/* parse an argument list */
447
static prsndef *prsxarg(prscxdef *ctx);
448
449
/* parse an atom */
450
static prsndef *prsxatm(prscxdef *ctx);
451
452
/* parse a structure member expression */
453
static prsndef *prsxmem(prscxdef *ctx);
454
455
/* parse a unary operator expression */
456
static prsndef *prsxun(prscxdef *ctx, prsbdef *binctx);
457
458
/* parse a conditional expression */
459
static prsndef *prsxcnd(prscxdef *ctx, prsbdef *binctx);
460
461
/* parse an object definition (superclass list is already parsed) */
462
static void prsobj(prscxdef *ctx, tokdef *objtok,
463
                   int numsc, objnum *sclist, int classflg);
464
465
/* factor */
466
static int prsl_fact[] = { TOKTTIMES, TOKTDIV, TOKTMOD, 0 };
467
static prsbdef prsb_fact = { prsl_fact, prsxun, prsxun, 0, TRUE };
468
469
/* term */
470
static int prsl_term[] = { TOKTPLUS, TOKTMINUS, 0 };
471
static prsbdef prsb_term = { prsl_term, prsxbin, prsxbin, &prsb_fact, TRUE };
472
473
/* shift */
474
static int prsl_shift[] = { TOKTSHL, TOKTSHR, 0 };
475
static prsbdef prsb_shift = { prsl_shift, prsxbin, prsxbin, &prsb_term, TRUE };
476
477
/* relational (magnitude comparison) */
478
static int prsl_rel[] = { TOKTGT, TOKTGE, TOKTLT, TOKTLE, 0 };
479
static prsbdef prsb_rel = { prsl_rel, prsxbin, prsxbin, &prsb_shift, FALSE };
480
481
/* comparison */
482
/* WARNING - keep prsl_cmp and prsl_cmp_C in sync with one another */
483
static int prsl_cmp[] =
484
    { TOKTEQ, TOKTNE, 0 };
485
static prsbdef prsb_cmp = { prsl_cmp, prsxbin, prsxbin, &prsb_rel, FALSE };
486
static int prsl_cmp_C[] =
487
    { TOKTEQEQ, TOKTNE, 0 };
488
static prsbdef prsb_cmp_C =
489
    { prsl_cmp_C, prsxbin, prsxbin, &prsb_rel, FALSE };
490
491
/* bitwise AND */
492
static int prsl_band[] = { TOKTBOR, 0 };
493
static prsbdef prsb_band = { prsl_band, prsxbin, prsxbin, &prsb_cmp, TRUE };
494
static prsbdef prsb_band_C = {prsl_band, prsxbin, prsxbin, &prsb_cmp_C, TRUE };
495
496
/* bitwise XOR */
497
static int prsl_xor[] = { TOKTXOR, 0 };
498
static prsbdef prsb_xor = { prsl_xor, prsxbin, prsxbin, &prsb_band, TRUE };
499
static prsbdef prsb_xor_C = { prsl_xor, prsxbin, prsxbin, &prsb_band_C, TRUE };
500
501
/* bitwise OR */
502
static int prsl_bor[] = { TOKTBAND, 0 };
503
static prsbdef prsb_bor = { prsl_bor, prsxbin, prsxbin, &prsb_xor, TRUE };
504
static prsbdef prsb_bor_C = { prsl_bor, prsxbin, prsxbin, &prsb_xor_C, TRUE };
505
506
/* logical AND */
507
static int prsl_and[] = { TOKTAND, 0 };
508
static prsbdef prsb_and = { prsl_and, prsxbin, prsxbin, &prsb_bor, TRUE };
509
static prsbdef prsb_and_C = { prsl_and, prsxbin, prsxbin, &prsb_bor_C, TRUE };
510
511
/* logical OR */
512
static int prsl_or[] = { TOKTOR, 0 };
513
static prsbdef prsb_or = { prsl_or, prsxbin, prsxbin, &prsb_and, TRUE };
514
static prsbdef prsb_or_C = { prsl_or, prsxbin, prsxbin, &prsb_and_C, TRUE };
515
516
/* assignment */
517
/* WARNING - keep prsl_asi and prsl_asi_C in sync with one another */
518
static int prsl_asi[] =
519
    { TOKTASSIGN, TOKTPLEQ, TOKTMINEQ, TOKTDIVEQ, TOKTTIMEQ, TOKTMODEQ,
520
      TOKTBANDEQ, TOKTBOREQ, TOKTXOREQ, TOKTSHLEQ, TOKTSHREQ, 0 };
521
static int prsl_asi_C[] =
522
    { TOKTEQ, TOKTPLEQ, TOKTMINEQ, TOKTDIVEQ, TOKTTIMEQ, TOKTMODEQ,
523
      TOKTBANDEQ, TOKTBOREQ, TOKTXOREQ, TOKTSHLEQ, TOKTSHREQ, 0 };
524
static prsbdef prsb_asi = { prsl_asi, prsxcnd, prsxbin, &prsb_asi, FALSE };
525
static prsbdef prsb_asi_C =
526
    { prsl_asi_C, prsxcnd, prsxbin, &prsb_asi_C, FALSE };
527
528
/* comma */
529
static int prsl_cma[] = { TOKTCOMMA, 0 };
530
static prsbdef prsb_cma = { prsl_cma, prsxbin, prsxbin, &prsb_asi, TRUE };
531
static prsbdef prsb_cma_C = { prsl_cma, prsxbin, prsxbin, &prsb_asi_C, TRUE };
532
533
534
/* determine if we're in C-mode - return true if so, false otherwise */
535
static int prs_cmode(prscxdef *ctx)
536
{
537
    return (ctx->prscxtok->tokcxflg & TOKCXFCMODE) != 0;
538
}
539
540
/* build general binary node, iterating to the right if desired */
541
static prsndef *prsxbin(prscxdef *ctx, prsbdef *binctx)
542
{
543
    prsndef *n;
544
    int      t;
545
    int     *lp;
546
    
547
    n = (*binctx->prsblf)(ctx, binctx->prsbctx);
548
    do
549
    {
550
        t = ctx->prscxtok->tokcxcur.toktyp;
551
        for (lp = binctx->prsblst ; *lp && *lp != t ; ++lp) ;
552
        if (*lp == t)
553
        {
554
            /*
555
             *   if inside a list, check to see if this is a binary
556
             *   operator that can also server as a unary operator -- if
557
             *   so, interpret it as a unary operator and warn about it 
558
             */
559
            if (ctx->prscxflg & PRSCXFLST)
560
            {
561
                static int ambig_ops[] = { TOKTBAND, TOKTPLUS, TOKTMINUS, 0 };
562
                static char *ambig_names[] = { "&", "+", "-" };
563
564
                for (lp = ambig_ops ; *lp && *lp != t ; ++lp) ;
565
                if (*lp)
566
                {
567
                    errlog1(ctx->prscxerr, ERR_AMBIGBIN,
568
                            ERRTSTR, ambig_names[lp - ambig_ops]);
569
                    break;
570
                }
571
            }
572
573
            /* skip the operator */
574
            toknext(ctx->prscxtok);
575
576
            /* use C-style operators if in C mode */
577
            if (prs_cmode(ctx))
578
            {
579
                switch(t)
580
                {
581
                case TOKTEQEQ:
582
                    t = TOKTEQ;
583
                    break;
584
585
                case TOKTEQ:
586
                    t = TOKTASSIGN;
587
                    break;
588
                }
589
            }
590
591
            /* generate a node for the binary operator */
592
            n = prsnew2(ctx, t, n, (*binctx->prsbrf)(ctx, binctx->prsbctx));
593
        }
594
        else
595
            break;
596
    } while (binctx->prsbrpt);
597
    
598
    return(n);
599
}
600
601
static prsndef *prsxarg(prscxdef *ctx)
602
{
603
    prsndef *n;
604
    int      t;
605
    
606
    /* arguments are assignments:  just under comma-expressions */
607
    n = prsxbin(ctx, prs_cmode(ctx) ? &prsb_asi_C : &prsb_asi);
608
    
609
    t = ctx->prscxtok->tokcxcur.toktyp;
610
    toknext(ctx->prscxtok);
611
    switch(t)
612
    {
613
    case TOKTRPAR:
614
        return(n);
615
        
616
    case TOKTCOMMA:
617
        return(prsnew2(ctx, TOKTRPAR, n, prsxarg(ctx)));
618
        
619
    default:
620
        errsig(ctx->prscxerr, ERR_REQARG);
621
        NOTREACHEDV(prsndef *);
622
        return 0;
623
    }
624
}
625
626
static prsndef *prsxatm(prscxdef *ctx)
627
{
628
    prsndef *n;
629
    tokdef  *tok = &ctx->prscxtok->tokcxcur;
630
    tokdef   newtok;
631
    prpnum   pr;
632
    
633
    switch(tok->toktyp)
634
    {
635
    case TOKTPOUND:
636
    case TOKTBAND:
637
        toknext(ctx->prscxtok);
638
        if (ctx->prscxtok->tokcxcur.toktyp == TOKTSYMBOL &&
639
            (ctx->prscxtok->tokcxcur.toksym.tokstyp == TOKSTFWDFN ||
640
             ctx->prscxtok->tokcxcur.toksym.tokstyp == TOKSTFUNC))
641
        {
642
            n = prsnew0(ctx, tok);
643
            toknext(ctx->prscxtok);
644
            return(n);
645
        }
646
        else
647
        {
648
            pr = prsrqpr(ctx);
649
            newtok.toktyp = TOKTPOUND;
650
            newtok.tokofs = pr;
651
            return(prsnew0(ctx, &newtok));
652
        }
653
        
654
    case TOKTLPAR:
655
        toknext(ctx->prscxtok);
656
        n = prsxexp(ctx, FALSE);
657
        prsreq(ctx, TOKTRPAR);
658
        return(n);
659
        
660
    case TOKTLBRACK:
661
        toknext(ctx->prscxtok);
662
        return(prslst(ctx));
663
        
664
    case TOKTNUMBER:
665
    case TOKTNIL:
666
    case TOKTTRUE:
667
    case TOKTSSTRING:
668
    case TOKTDSTRING:
669
        /* create and return a new terminal node for this item */
670
        n = prsnew0(ctx, tok);
671
        toknext(ctx->prscxtok);
672
        return n;
673
        
674
    case TOKTSYMBOL:
675
        /* create a new terminal node for the symbol */
676
        n = prsnew0(ctx, tok);
677
        toknext(ctx->prscxtok);
678
679
        /* 
680
         *   if it was 'inherited', and there's another symbol name
681
         *   following, we have the explicit superclass notation - parse
682
         *   it 
683
         */
684
        if (n->prsnv.prsnvt.toksym.tokstyp == TOKSTINHERIT
685
            && tok->toktyp == TOKTSYMBOL)
686
        {
687
            /* build a new node for the explicit superclass */
688
            n = prsnew0(ctx, tok);
689
690
            /* build a containing node for the inheritance operator */
691
            n = prsnew1(ctx, TOKTEXPINH, n);
692
693
            /* skip the superclass name token */
694
            toknext(ctx->prscxtok);
695
        }
696
697
        /* return the new node */
698
        return n;
699
        
700
    default:
701
        errsig(ctx->prscxerr, ERR_REQOPN);
702
        return 0;
703
        NOTREACHEDV(prsndef *);
704
    }
705
}
706
707
static prsndef *prsxmem(prscxdef *ctx)
708
{
709
    prsndef *n1, *n2;
710
    tokdef  *tok;
711
    tokdef   newtok;
712
    prpnum   prop;
713
    
714
    n1 = prsxatm(ctx);
715
    for ( ;; )
716
    {
717
        tok = &ctx->prscxtok->tokcxcur;
718
        switch(tok->toktyp)
719
        {
720
        case TOKTDOT:
721
            if (toknext(ctx->prscxtok) == TOKTLPAR)
722
            {
723
                toknext(ctx->prscxtok);
724
                n2 = prsxexp(ctx, FALSE);
725
                prsreq(ctx, TOKTRPAR);
726
            }
727
            else if (ctx->prscxtok->tokcxcur.toktyp == TOKTSYMBOL &&
728
                     ctx->prscxtok->tokcxcur.toksym.tokstyp == TOKSTLOCAL)
729
            {
730
                n2 = prsnew0(ctx, &ctx->prscxtok->tokcxcur);
731
                toknext(ctx->prscxtok);
732
            }
733
            else
734
            {
735
                prop = prsrqpr(ctx);
736
                newtok.toktyp = TOKTPOUND;
737
                newtok.tokofs = prop;
738
                n2 = prsnew0(ctx, &newtok);
739
            }
740
741
            /* see if there's an argument list for the method */
742
            if (ctx->prscxtok->tokcxcur.toktyp == TOKTLPAR)
743
            {
744
                toknext(ctx->prscxtok);
745
                n1 = prsnew3(ctx, TOKTDOT, n1, n2, prsxarg(ctx));
746
            }
747
            else
748
                n1 = prsnew2(ctx, TOKTDOT, n1, n2);
749
750
            break;
751
            
752
        case TOKTLBRACK:
753
            if (ctx->prscxflg & PRSCXFLST) return(n1);
754
            toknext(ctx->prscxtok);
755
            n2 = prsxexp(ctx, FALSE);
756
            n1 = prsnew2(ctx, TOKTLBRACK, n1, n2);
757
            prsreq(ctx, TOKTRBRACK);
758
            break;
759
            
760
        case TOKTLPAR:
761
            if (toknext(ctx->prscxtok) == TOKTRPAR)
762
            {
763
                toknext(ctx->prscxtok);
764
                n1 = prsnew1(ctx, TOKTLPAR, n1);
765
            }
766
            else
767
                n1 = prsnew2(ctx, TOKTLPAR, n1, prsxarg(ctx));
768
            break;
769
            
770
        case TOKTINC:
771
        case TOKTDEC:
772
            n1 = prsnew1(ctx, tok->toktyp + 1, n1);
773
            toknext(ctx->prscxtok);
774
            return(n1);
775
            
776
        default:
777
            return(n1);
778
        }
779
    }
780
}
781
782
/* parse a unary operator expression */
783
static prsndef *prsxun(prscxdef *ctx, prsbdef *binctx)
784
{
785
    int      t;
786
    
787
    VARUSED(binctx);
788
789
    t = ctx->prscxtok->tokcxcur.toktyp;
790
    if (t == TOKTPLUS || t == TOKTMINUS || t == TOKTNOT
791
        || t == TOKTINC || t == TOKTDEC || t == TOKTTILDE
792
        || t == TOKTDELETE)
793
    {
794
        toknext(ctx->prscxtok);
795
        return(prsnew1(ctx, t, prsxun(ctx, (prsbdef *)0)));
796
    }
797
    else if (t == TOKTNEW)
798
    {
799
        if (toknext(ctx->prscxtok) == TOKTOBJECT)
800
        {
801
            tokdef tok;
802
803
            toknext(ctx->prscxtok);
804
            tok.toktyp = TOKTNEW;
805
            return prsnew0(ctx, &tok);
806
        }
807
        else
808
            return prsnew1(ctx, t, prsxun(ctx, (prsbdef *)0));
809
    }
810
    return(prsxmem(ctx));
811
}
812
813
/* parse a ternary conditional expression */
814
static prsndef *prsxcnd(prscxdef *ctx, prsbdef *binctx)
815
{
816
    prsndef *n1, *n2;
817
    
818
    VARUSED(binctx);
819
820
    n1 = prsxbin(ctx, prs_cmode(ctx) ? &prsb_or_C : &prsb_or);
821
    for (;;)
822
    {
823
        if (ctx->prscxtok->tokcxcur.toktyp != TOKTQUESTION) break;
824
        toknext(ctx->prscxtok);
825
        n2 = prsxexp(ctx, FALSE);
826
        prsreq(ctx, TOKTCOLON);
827
        n1 = prsnew3(ctx, TOKTQUESTION, n1, n2,
828
                     prsxbin(ctx, prs_cmode(ctx) ? &prsb_asi_C : &prsb_asi));
829
    }
830
    return(n1);
831
}
832
833
/* parse an expression (called recursively during expression parsing) */
834
static prsndef *prsxexp(prscxdef *ctx, int inlist)
835
{
836
    ushort   oldflg = ctx->prscxflg;
837
    prsndef *retval;
838
    
839
    if (inlist)
840
    {
841
        ctx->prscxflg |= PRSCXFLST;
842
        retval = prsxbin(ctx, (prs_cmode(ctx) ? &prsb_asi_C : &prsb_asi));
843
    }
844
    else
845
    {
846
        ctx->prscxflg &= ~PRSCXFLST;
847
        retval = prsxbin(ctx, prs_cmode(ctx) ? &prsb_cma_C : &prsb_cma);
848
    }
849
    
850
    ctx->prscxflg = oldflg;
851
    return(retval);
852
}
853
854
/* fold constants in a parse tree */
855
static prsndef *prsfold(prscxdef *ctx, prsndef *node)
856
{
857
    int       i;
858
    prsndef **n;
859
    int       can_fold;
860
    int       typ;
861
    tokdef   *tok1, *tok2;
862
    int       typ1, typ2;
863
    long      val1, val2;
864
    prsndef  *ncur;
865
    
866
    can_fold = TRUE;                       /* assume we can do some folding */
867
868
    /* if this is a list-construction node, special handling is needed */
869
    if (node->prsntyp == TOKTRBRACK)
870
    {
871
        for (i=0, ncur = node ; ncur ; ++i, ncur = ncur->prsnv.prsnvn[1])
872
        {
873
            ncur->prsnv.prsnvn[0] = prsfold(ctx, ncur->prsnv.prsnvn[0]);
874
            typ = TOKTINVALID;
875
            if (ncur->prsnv.prsnvn[0]->prsnnlf != 0 ||
876
                ((typ = ncur->prsnv.prsnvn[0]->prsnv.prsnvt.toktyp)
877
                 != TOKTNUMBER && typ != TOKTSSTRING && typ != TOKTLIST
878
                 && typ != TOKTNIL && typ != TOKTTRUE && typ != TOKTPOUND
879
                 && typ != TOKTSYMBOL))
880
                can_fold = FALSE;              /* not constant - can't fold */
881
            
882
            if (typ == TOKTSYMBOL
883
                && (ncur->prsnv.prsnvn[0]->prsnv.prsnvt.toksym.tokstyp
884
                    == TOKSTLOCAL
885
                    || ncur->prsnv.prsnvn[0]->prsnv.prsnvt.toksym.tokstyp
886
                    == TOKSTSELF))
887
                can_fold = FALSE;
888
            
889
            if (ncur->prsnv.prsnvn[0]->prsnnlf == 0 && typ == TOKTSYMBOL)
890
                prsdef(ctx, &ncur->prsnv.prsnvn[0]->prsnv.prsnvt,
891
                       TOKSTFWDOBJ);
892
        }
893
        if (can_fold)
894
        {
895
            tokdef    t;
896
            emtlidef *lst;
897
            prsndef  *retval;
898
            emtledef *ele;
899
            
900
            lst = (emtlidef *)prsbalo(ctx, (uint)(sizeof(emtldef) +
901
                                                 (i - 1) * sizeof(emtledef)));
902
            t.toktyp = TOKTLIST;
903
            t.tokofs = ((uchar *)lst) - &ctx->prscxpool[0];
904
            retval = prsnew0(ctx, &t);
905
            
906
            lst->emtlicnt = i;
907
            
908
            for (ele = &lst->emtliele[0] ; node ;
909
                   node = node->prsnv.prsnvn[1], ++ele)
910
            {
911
                ncur = node->prsnv.prsnvn[0];
912
                switch(ele->emtletyp = ncur->prsnv.prsnvt.toktyp)
913
                {
914
                case TOKTLIST:
915
                case TOKTSSTRING:
916
                case TOKTPOUND:
917
                    ele->emtleval = ncur->prsnv.prsnvt.tokofs;
918
                    break;
919
                    
920
                case TOKTSYMBOL:
921
                    switch(ncur->prsnv.prsnvt.toksym.tokstyp)
922
                    {
923
                    case TOKSTFUNC:
924
                    case TOKSTFWDFN:
925
                        ele->emtletyp = TOKTFUNCTION;
926
                        break;
927
                    case TOKSTOBJ:
928
                    case TOKSTFWDOBJ:
929
                        ele->emtletyp = TOKTOBJECT;
930
                        break;
931
                    case TOKSTPROP:
932
                        ele->emtletyp = TOKTDOT;
933
                        break;
934
                    case TOKSTPROPSPEC:
935
                        ele->emtletyp = TOKTDOT;
936
                        break;
937
                    default:
938
                        errsig(ctx->prscxerr, ERR_INVLSTE);
939
                    }
940
                    ele->emtleval = ncur->prsnv.prsnvt.toksym.toksval;
941
                    break;
942
                    
943
                default:
944
                    ele->emtleval = ncur->prsnv.prsnvt.tokval;
945
                    break;
946
                }
947
            }
948
949
            node = retval;
950
        }
951
        return(node);
952
    }
953
    
954
    /*
955
     *   If we have sub-nodes, try to fold them.  If they fold down to
956
     *   leaf nodes, we can try to apply the expression to them. 
957
     */
958
    for (i = node->prsnnlf, n = &node->prsnv.prsnvn[0] ; i ; ++n, --i)
959
    {
960
        *n = prsfold(ctx, *n);
961
        if ((*n)->prsnnlf != 0 ||
962
            ((typ = (*n)->prsnv.prsnvt.toktyp) != TOKTNUMBER &&
963
             typ != TOKTSSTRING && typ != TOKTLIST &&
964
             typ != TOKTNIL && typ != TOKTTRUE && typ != TOKTPOUND))
965
            can_fold = FALSE;                  /* not constant - can't fold */
966
    }
967
968
    /* if at a leaf, or subnodes are non-constant, can't fold anything */
969
    if (node->prsnnlf == 0 || !can_fold) return(node);
970
971
    switch(node->prsnnlf)
972
    {
973
    case 1:
974
        tok1 = &node->prsnv.prsnvn[0]->prsnv.prsnvt;
975
        typ1 = tok1->toktyp;
976
        val1 = tok1->tokval;
977
        
978
        switch(node->prsntyp)
979
        {
980
        case TOKTPLUS:
981
            break;
982
            
983
        case TOKTMINUS:
984
            if (typ1 != TOKTNUMBER)
985
                errsig(ctx->prscxerr, ERR_INVOP);
986
            tok1->tokval = -val1;
987
            break;
988
            
989
        case TOKTNOT:
990
            if (!prsvlog(typ1))
991
                errsig(ctx->prscxerr, ERR_INVOP);
992
            tok1->toktyp = (prs2log(typ1, val1) == TOKTNIL ?
993
                            TOKTTRUE : TOKTNIL);
994
            break;
995
996
        case TOKTTILDE:
997
            if (typ1 != TOKTNUMBER)
998
                errsig(ctx->prscxerr, ERR_INVOP);
999
            tok1->tokval = ~val1;
1000
            break;
1001
            
1002
        default:
1003
            return(node);
1004
        }
1005
        break;
1006
        
1007
    case 2:
1008
        tok1 = &node->prsnv.prsnvn[0]->prsnv.prsnvt;
1009
        tok2 = &node->prsnv.prsnvn[1]->prsnv.prsnvt;
1010
        val1 = tok1->tokval;
1011
        val2 = tok2->tokval;
1012
        typ1 = tok1->toktyp;
1013
        typ2 = tok2->toktyp;
1014
        
1015
        switch(node->prsntyp)
1016
        {
1017
        case TOKTOR:
1018
        case TOKTAND:
1019
            if (!prsvlog(typ1) || !prsvlog(typ2))
1020
                errsig(ctx->prscxerr, ERR_INVOP);
1021
            typ1 = (prs2log(typ1, val1) == TOKTTRUE);
1022
            typ2 = (prs2log(typ2, val2) == TOKTTRUE);
1023
1024
            if (node->prsntyp == TOKTAND) typ1 = typ1 && typ2;
1025
            else                          typ1 = typ1 || typ2;
1026
1027
            tok1->toktyp = (typ1 ? TOKTTRUE : TOKTNIL);
1028
            break;
1029
1030
        case TOKTPLUS:
1031
        case TOKTMINUS:
1032
            if (typ1 == TOKTSSTRING || typ1 == TOKTLIST || typ2 == TOKTLIST)
1033
                return(node);
1034
            /* FALLTHROUGH */
1035
            
1036
        case TOKTEQ:
1037
        case TOKTNE:
1038
        case TOKTGT:
1039
        case TOKTGE:
1040
        case TOKTLT:
1041
        case TOKTLE:
1042
            if (typ1 != TOKTNUMBER || typ2 != TOKTNUMBER)
1043
                return(node);
1044
            /* FALLTHROUGH */
1045
1046
        case TOKTXOR:
1047
            if ((typ1 == TOKTTRUE || typ1 == TOKTNIL)
1048
                && (typ2 == TOKTTRUE || typ2 == TOKTNIL))
1049
            {
1050
                int a, b;
1051
1052
                a = (typ1 == TOKTTRUE ? 1 : 0);
1053
                b = (typ2 == TOKTTRUE ? 1 : 0);
1054
                tok1->toktyp = ((a ^ b) ? TOKTTRUE : TOKTNIL);
1055
                break;
1056
            }
1057
            /* FALLTHROUGH */
1058
1059
        case TOKTDIV:
1060
        case TOKTTIMES:
1061
        case TOKTMOD:
1062
        case TOKTSHL:
1063
        case TOKTSHR:
1064
            if (typ1 != TOKTNUMBER || typ2 != TOKTNUMBER)
1065
                errsig(ctx->prscxerr, ERR_INVOP);
1066
            switch(node->prsntyp)
1067
            {
1068
            case TOKTPLUS:
1069
                val1 += val2;
1070
                break;
1071
            case TOKTMINUS:
1072
                val1 -= val2;
1073
                break;
1074
            case TOKTTIMES:
1075
                val1 *= val2;
1076
                break;
1077
            case TOKTDIV:
1078
                if (val2 == 0)
1079
                    errsig(ctx->prscxerr, ERR_DIVZERO);
1080
                val1 /= val2;
1081
                break;
1082
            case TOKTMOD:
1083
                if (val2 == 0)
1084
                    errsig(ctx->prscxerr, ERR_DIVZERO);
1085
                val1 %= val2;
1086
                break;
1087
            case TOKTXOR:
1088
                val1 ^= val2;
1089
                break;
1090
            case TOKTSHL:
1091
                val1 <<= val2;
1092
                break;
1093
            case TOKTSHR:
1094
                val1 >>= val2;
1095
                break;
1096
            case TOKTEQ:
1097
                typ1 = (val1 == val2 ? TOKTTRUE : TOKTNIL);
1098
                break;
1099
            case TOKTNE:
1100
                typ1 = (val1 != val2 ? TOKTTRUE : TOKTNIL);
1101
                break;
1102
            case TOKTGT:
1103
                typ1 = (val1 > val2 ? TOKTTRUE : TOKTNIL);
1104
                break;
1105
            case TOKTLT:
1106
                typ1 = (val1 < val2 ? TOKTTRUE : TOKTNIL);
1107
                break;
1108
            case TOKTLE:
1109
                typ1 = (val1 <= val2 ? TOKTTRUE : TOKTNIL);
1110
                break;
1111
            case TOKTGE:
1112
                typ1 = (val1 >= val2 ? TOKTTRUE : TOKTNIL);
1113
                break;
1114
                
1115
            default:
1116
                return(node);
1117
            }
1118
            tok1->toktyp = typ1;
1119
            tok1->tokval = val1;
1120
            break;
1121
            
1122
        default:
1123
            return(node);
1124
        }
1125
        break;
1126
        
1127
    case 3:
1128
        tok1 = &node->prsnv.prsnvn[0]->prsnv.prsnvt;
1129
        if (!prsvlog(tok1->toktyp)) errsig(ctx->prscxerr, ERR_INVOP);
1130
        if (prs2log(tok1->toktyp, tok1->tokval) == TOKTTRUE)
1131
            return(node->prsnv.prsnvn[1]);
1132
        else
1133
            return(node->prsnv.prsnvn[2]);
1134
        
1135
    default:
1136
        return(node);
1137
    }
1138
1139
    /* return the first sub-node, which has the folded value */
1140
    return(node->prsnv.prsnvn[0]);
1141
}
1142
1143
/* start parsing an initializer expression (resets node pool) */
1144
prsndef *prsxini(prscxdef *ctx)
1145
{
1146
    prsndef *node;
1147
    
1148
    node = prsxbin(ctx, (prs_cmode(ctx) ? &prsb_asi_C : &prsb_asi));
1149
    return(prsfold(ctx, node));                           /* fold constants */
1150
}
1151
1152
/* start parsing an expression (folds constants) */
1153
prsndef *prsexpr(prscxdef *ctx)
1154
{
1155
    return(prsfold(ctx, prsxbin(ctx,
1156
                                prs_cmode(ctx) ? &prsb_cma_C : &prsb_cma)));
1157
}
1158
1159
/* parse an expression and generate code for it immediately */
1160
void prsxgen(prscxdef *ctx)
1161
{
1162
    prsndef *exprnode;
1163
1164
    exprnode = prsexpr(ctx);
1165
    prsgexp(ctx, exprnode);
1166
    prsrstn(ctx);
1167
}
1168
1169
/*
1170
 *   Check a parse tree for speculative execution problems.  
1171
 */
1172
static void prs_check_spec(prscxdef *ctx, prsndef *expr)
1173
{
1174
    int i;
1175
    
1176
    /* 
1177
     *   check the type of this node - if it's an assignment or a function
1178
     *   call, prohibit it 
1179
     */
1180
    if (expr->prsnnlf == 0)
1181
    {
1182
        /* value node - check for a symbol */
1183
        if (expr->prsnv.prsnvt.toktyp == TOKTSYMBOL)
1184
        {
1185
            switch(expr->prsnv.prsnvt.toksym.tokstyp)
1186
            {
1187
            case TOKSTPROP:
1188
                /* 
1189
                 *   convert this to a speculative evaluation property, so
1190
                 *   that the emitter knows to emit the correct opcode for
1191
                 *   it 
1192
                 */
1193
                expr->prsnv.prsnvt.toksym.tokstyp = TOKSTPROPSPEC;
1194
                break;
1195
1196
            case TOKSTBIFN:
1197
            case TOKSTINHERIT:
1198
            case TOKSTEXTERN:
1199
                /* don't allow calls */
1200
                errsig(ctx->prscxerr, ERR_BADSPECEXPR);
1201
1202
            default:
1203
                /* others are okay */
1204
                break;
1205
            }
1206
        }
1207
        else if (expr->prsnv.prsnvt.toktyp == TOKTDSTRING)
1208
        {
1209
            /* don't allow double-quoted strings in speculative evaluation */
1210
            errsig(ctx->prscxerr, ERR_BADSPECEXPR);
1211
        }
1212
    }
1213
    else
1214
    {
1215
        switch(expr->prsntyp)
1216
        {
1217
        case TOKTINC:
1218
        case TOKTDEC:
1219
        case TOKTPOSTINC:
1220
        case TOKTPOSTDEC:
1221
        case TOKTNEW:
1222
        case TOKTDELETE:
1223
        case TOKTLPAR:
1224
        case TOKTASSIGN:
1225
        case TOKTPLEQ:
1226
        case TOKTMINEQ:
1227
        case TOKTDIVEQ:
1228
        case TOKTMODEQ:
1229
        case TOKTTIMEQ:
1230
        case TOKTBANDEQ:
1231
        case TOKTBOREQ:
1232
        case TOKTXOREQ:
1233
        case TOKTSHLEQ:
1234
        case TOKTSHREQ:
1235
        case TOKTRPAR:
1236
            /* assignments and function calls are all prohibited */
1237
            errsig(ctx->prscxerr, ERR_BADSPECEXPR);
1238
            
1239
        case TOKTDOT:
1240
            /* property lookup - only allow no argument version */
1241
            if (expr->prsnnlf == 3)
1242
                errsig(ctx->prscxerr, ERR_BADSPECEXPR);
1243
            
1244
            /* replace with data-only (no method call) version */
1245
            expr->prsntyp = TOKTDOTSPEC;
1246
            break;
1247
            
1248
        default:
1249
            /* other expressions are acceptable */
1250
            break;
1251
        }
1252
        
1253
        /* go through all subnodes of this node */
1254
        for (i = 0 ; i < expr->prsnnlf ; ++i)
1255
            prs_check_spec(ctx, expr->prsnv.prsnvn[i]);
1256
    }
1257
}
1258
1259
/*
1260
 *   Parse an expression and generate code for it using speculative
1261
 *   evaluation rules 
1262
 */
1263
void prsxgen_spec(prscxdef *ctx)
1264
{
1265
    prsndef *exprnode;
1266
1267
    /* parse the expression */
1268
    exprnode = prsexpr(ctx);
1269
1270
    /* check for speculative execution problems */
1271
    prs_check_spec(ctx, exprnode);
1272
1273
    /* generate the expression, then reset the parse node pool */
1274
    prsgexp(ctx, exprnode);
1275
    prsrstn(ctx);
1276
}
1277
1278
1279
/*
1280
 *   Parse an expression and generate code, checking the expression for a
1281
 *   possibly incorrect assigment if in C mode. 
1282
 */
1283
void prsxgen_pia(prscxdef *ctx)
1284
{
1285
    prsndef *exprnode;
1286
1287
    /* parse the expression */
1288
    exprnode = prsexpr(ctx);
1289
1290
    /* check for a possibly incorrect assignment if in C mode */
1291
    if ((ctx->prscxtok->tokcxflg & TOKCXFCMODE)
1292
        && exprnode && exprnode->prsntyp == TOKTASSIGN)
1293
        errlog(ctx->prscxerr, ERR_PIA);
1294
1295
    /* generate the expression, and reset the parse node pool */
1296
    prsgexp(ctx, exprnode);
1297
    prsrstn(ctx);
1298
}
1299
1300
1301
1302
/* opcodes for general binary operators */
1303
uchar prsbopl[] =
1304
{
1305
    OPCADD, OPCSUB, OPCDIV, OPCMUL, 0, OPCEQ, OPCNE, OPCGT, OPCGE,
1306
    OPCLT, OPCLE, OPCMOD, OPCBAND, OPCBOR, OPCXOR, OPCSHL, OPCSHR
1307
};
1308
1309
/* descend an expression tree and generate code for the expression */
1310
void prsgexp(prscxdef *ctx, prsndef *n)
1311
{
1312
    int cnt;
1313
    
1314
    switch(n->prsnnlf)
1315
    {
1316
    case 0:
1317
        prsdef(ctx, &n->prsnv.prsnvt, TOKSTFWDOBJ);
1318
        emtval(ctx->prscxemt, &n->prsnv.prsnvt, ctx->prscxpool);
1319
        break;
1320
        
1321
    case 1:
1322
        switch(n->prsntyp)
1323
        {
1324
        case TOKTINC:
1325
        case TOKTDEC:
1326
        case TOKTPOSTINC:
1327
        case TOKTPOSTDEC:
1328
            prsglval(ctx, n->prsntyp, n->prsnv.prsnvn[0]);
1329
            break;
1330
            
1331
        case TOKTPLUS:
1332
        case TOKTMINUS:
1333
        case TOKTNOT:
1334
        case TOKTTILDE:
1335
        case TOKTNEW:
1336
        case TOKTDELETE:
1337
            prsgexp(ctx, n->prsnv.prsnvn[0]);
1338
            if (n->prsntyp != TOKTPLUS)
1339
                emtop(ctx->prscxemt,
1340
                      n->prsntyp == TOKTMINUS ? OPCNEG :
1341
                      n->prsntyp == TOKTTILDE ? OPCBNOT :
1342
                      n->prsntyp == TOKTNEW ? OPCNEW :
1343
                      n->prsntyp == TOKTDELETE ? OPCDELETE :
1344
                      OPCNOT);
1345
            break;
1346
1347
        case TOKTLPAR:
1348
            prsgfn(ctx, n->prsnv.prsnvn[0], 0);
1349
            break;
1350
1351
        default:
1352
            errsig(ctx->prscxerr, ERR_REQUNO);
1353
        }
1354
        break;
1355
        
1356
    case 2:
1357
        switch(n->prsntyp)
1358
        {
1359
        case TOKTAND:
1360
        case TOKTOR:
1361
        {
1362
            uint lab;
1363
            
1364
            lab = emtglbl(ctx->prscxemt);
1365
            prsgexp(ctx, n->prsnv.prsnvn[0]);
1366
            emtjmp(ctx->prscxemt,
1367
                   (uchar)(n->prsntyp == TOKTAND ? OPCJSF : OPCJST),
1368
                   lab);
1369
            prsgexp(ctx, n->prsnv.prsnvn[1]);
1370
            emtslbl(ctx->prscxemt, &lab, TRUE);
1371
            break;
1372
        }
1373
        
1374
        case TOKTPLUS:
1375
        case TOKTMINUS:
1376
        case TOKTDIV:
1377
        case TOKTMOD:
1378
        case TOKTTIMES:
1379
        case TOKTEQ:
1380
        case TOKTNE:
1381
        case TOKTGT:
1382
        case TOKTGE:
1383
        case TOKTLT:
1384
        case TOKTLE:
1385
        case TOKTBAND:
1386
        case TOKTBOR:
1387
        case TOKTXOR:
1388
        case TOKTSHL:
1389
        case TOKTSHR:
1390
            prsgexp(ctx, n->prsnv.prsnvn[0]);
1391
            prsgexp(ctx, n->prsnv.prsnvn[1]);
1392
            emtop(ctx->prscxemt, prsbopl[n->prsntyp - TOKTPLUS]);
1393
            break;
1394
            
1395
        case TOKTCOMMA:
1396
            prsgexp(ctx, n->prsnv.prsnvn[0]);
1397
            prsgexp(ctx, n->prsnv.prsnvn[1]);
1398
            break;
1399
            
1400
        case TOKTLPAR:                      /* function call with arguments */
1401
            cnt = prsgargs(ctx, n->prsnv.prsnvn[1]);      /* push arguments */
1402
            prsgfn(ctx, n->prsnv.prsnvn[0], cnt);
1403
            break;
1404
        
1405
        case TOKTASSIGN:
1406
        case TOKTPLEQ:
1407
        case TOKTMINEQ:
1408
        case TOKTDIVEQ:
1409
        case TOKTMODEQ:
1410
        case TOKTTIMEQ:
1411
        case TOKTBANDEQ:
1412
        case TOKTBOREQ:
1413
        case TOKTXOREQ:
1414
        case TOKTSHLEQ:
1415
        case TOKTSHREQ:
1416
            prsgexp(ctx, n->prsnv.prsnvn[1]);      /* eval right side of := */
1417
            prsglval(ctx, n->prsntyp, n->prsnv.prsnvn[0]);
1418
            break;
1419
            
1420
        case TOKTDOT:
1421
            prsgdot(ctx, n, 0);
1422
            break;
1423
1424
        case TOKTDOTSPEC:
1425
            prsgdotspec(ctx, n);
1426
            break;
1427
            
1428
        case TOKTLBRACK:
1429
            prsgexp(ctx, n->prsnv.prsnvn[0]);    /* push list being indexed */
1430
            prsgexp(ctx, n->prsnv.prsnvn[1]);       /* push the index value */
1431
            emtop(ctx->prscxemt, OPCINDEX);
1432
            break;
1433
        
1434
        case TOKTRBRACK:
1435
        {
1436
            prsndef *nsub;
1437
            uint     cnt;
1438
            
1439
            for (cnt = 0, nsub = n ; nsub
1440
                 ; ++cnt, nsub = nsub->prsnv.prsnvn[1])
1441
                prsgexp(ctx, nsub->prsnv.prsnvn[0]);
1442
            emtop(ctx->prscxemt, OPCCONS);         /* construction operator */
1443
            emtint2(ctx->prscxemt, cnt);
1444
            break;
1445
        }
1446
            
1447
        default:
1448
            errsig(ctx->prscxerr, ERR_INVBIN);
1449
        }
1450
        break;
1451
1452
    case 3:
1453
        switch(n->prsntyp)
1454
        {
1455
        case TOKTQUESTION:
1456
        {
1457
            uint lfalse;                          /* label for FALSE branch */
1458
            uint ldone;                       /* label for end of condition */
1459
            
1460
            prsgexp(ctx, n->prsnv.prsnvn[0]);         /* evaluate condition */
1461
            lfalse = emtglbl(ctx->prscxemt);
1462
            emtjmp(ctx->prscxemt, OPCJF, lfalse);
1463
            prsgexp(ctx, n->prsnv.prsnvn[1]);             /* eval TRUE expr */
1464
            ldone = emtglbl(ctx->prscxemt);
1465
            emtjmp(ctx->prscxemt, OPCJMP, ldone);
1466
            emtslbl(ctx->prscxemt, &lfalse, TRUE);
1467
            prsgexp(ctx, n->prsnv.prsnvn[2]);          /* eval FALSE branch */
1468
            emtslbl(ctx->prscxemt, &ldone, TRUE);
1469
            break;
1470
        }
1471
        case TOKTDOT:
1472
            cnt = prsgargs(ctx, n->prsnv.prsnvn[2]);
1473
            prsgdot(ctx, n, cnt);
1474
            break;
1475
        }
1476
        break;
1477
    }
1478
}
1479
1480
/* generate code for initializer */
1481
void prsgini(prscxdef *ctx, prsndef *node, uint curfr)
1482
{
1483
    int lcl;
1484
    
1485
    /* descend tree - always generate in order specified by user */
1486
    if (node->prsnv.prsnvn[2])
1487
        prsgini(ctx, node->prsnv.prsnvn[2], curfr);
1488
    
1489
    /* generate OPCLINE if one was specified */
1490
    if (node->prsnnlf == 4)
1491
    {
1492
        uchar *p;
1493
        uint   oldofs;
1494
        
1495
        /* tell the line source about the OPCLINE instruction */
1496
        dbgclin(ctx->prscxtok, ctx->prscxemt->emtcxobj,
1497
                (uint)ctx->prscxemt->emtcxofs);
1498
        
1499
        /* now actually emit the OPCLINE instruction */
1500
        oldofs = ctx->prscxemt->emtcxofs;
1501
        p = ctx->prscxpool + node->prsnv.prsnvn[3]->prsnv.prsnvt.tokofs;
1502
        emtmem(ctx->prscxemt, p, (uint)(*(p + 1) + 1));
1503
        
1504
        /* fix it up with the correct frame */
1505
        emtint2at(ctx->prscxemt, curfr, oldofs + 2);
1506
    }
1507
    
1508
    prsgexp(ctx, node->prsnv.prsnvn[0]);
1509
    emtop(ctx->prscxemt, OPCSETLCL);
1510
    lcl = node->prsnv.prsnvn[1]->prsnv.prsnvt.tokval;
1511
    emtint2(ctx->prscxemt, lcl);
1512
}
1513
1514
/* generate code for a function all */
1515
static void prsgfn(prscxdef *ctx, prsndef *n, int cnt)
1516
{
1517
    if (n->prsnnlf == 0 && n->prsnv.prsnvt.toktyp == TOKTSYMBOL
1518
        && (n->prsnv.prsnvt.toksym.tokstyp == TOKSTUNK
1519
            || n->prsnv.prsnvt.toksym.tokstyp != TOKSTLOCAL))
1520
    {
1521
        tokdef *t = &n->prsnv.prsnvt;
1522
        
1523
        /* if symbol is undefined, add to symbol table as a new function */
1524
        prsdef(ctx, t, TOKSTFWDFN);
1525
        
1526
        /* non-local-var symbol: interpret as a function */
1527
        switch(t->toksym.tokstyp)
1528
        {
1529
        case TOKSTFUNC:
1530
        case TOKSTFWDFN:
1531
            emtop(ctx->prscxemt, OPCCALL);
1532
            break;
1533
        case TOKSTEXTERN:
1534
            emtop(ctx->prscxemt, OPCCALLEXT);
1535
            break;
1536
        case TOKSTBIFN:
1537
            emtop(ctx->prscxemt, OPCBUILTIN);
1538
            break;
1539
        default:
1540
            errlog(ctx->prscxerr, ERR_REQFCN);
1541
        }
1542
        emtbyte(ctx->prscxemt, cnt);            /* emit argument count byte */
1543
        emtint2(ctx->prscxemt, t->toksym.toksval);
1544
    }
1545
    else
1546
    {
1547
        /* expression - evaluate, and assume it yields a function pointer */
1548
        prsgexp(ctx, n);
1549
        emtop(ctx->prscxemt, OPCPTRCALL);
1550
        emtbyte(ctx->prscxemt, cnt);                 /* argument count byte */
1551
    }
1552
}
1553
1554
/* generate code for a property lookup */
1555
static void prsgdot(prscxdef *ctx, prsndef *n, int cnt)
1556
{
1557
    prsndef *n0 = n->prsnv.prsnvn[0];
1558
    prsndef *n1 = n->prsnv.prsnvn[1];
1559
    int      inh;                                 /* flag: "inherited.prop" */
1560
    int      slf;                                      /* flag: "self.prop" */
1561
    int      objflg;           /* flag: LHS of dot is constant object value */
1562
    int      exp_inh;                  /* flag: "inherited superclass.prop" */
1563
    uchar    reg_op;                /* operator to use for regular property */
1564
    uchar    ptr_op;                /* operator to use for property pointer */
1565
    objnum   exp_inh_obj;     /* explicit superclass object to inherit from */
1566
1567
    /* presume we'll have a regular object expression for the LHS */
1568
    inh = exp_inh = slf = objflg = FALSE;
1569
1570
    /* set up the default opcodes for ordinary object expressions */
1571
    reg_op = OPCGETP;
1572
    ptr_op = OPCPTRGETP;
1573
1574
    /* check for special left-hand-side values */
1575
    if (n0->prsnnlf == 0 && n0->prsnv.prsnvt.toktyp == TOKTSYMBOL)
1576
    {
1577
        switch(n0->prsnv.prsnvt.toksym.tokstyp)
1578
        {
1579
        case TOKSTINHERIT:
1580
            inh = TRUE;
1581
            reg_op = OPCINHERIT;
1582
            ptr_op = OPCPTRINH;
1583
            break;
1584
            
1585
        case TOKSTSELF:
1586
            if (ctx->prscxflg & PRSCXFFUNC) errlog(ctx->prscxerr, ERR_NOSELF);
1587
            slf = TRUE;
1588
            reg_op = OPCGETPSELF;
1589
            ptr_op = OPCGETPPTRSELF;
1590
            break;
1591
            
1592
        case TOKSTOBJ:
1593
        case TOKSTFWDOBJ:
1594
            objflg = TRUE;
1595
            reg_op = OPCGETPOBJ;
1596
            break;
1597
        }
1598
    }
1599
    else if (n0->prsnnlf == 1 && n0->prsntyp == TOKTEXPINH)
1600
    {
1601
        tokdef *sc_tok;
1602
        
1603
        /* 
1604
         *   explicit superclass inheritance - this is inheritance, but
1605
         *   with an explicit superclass value 
1606
         */
1607
        inh = TRUE;
1608
        exp_inh = TRUE;
1609
        reg_op = OPCEXPINH;
1610
        ptr_op = OPCEXPINHPTR;
1611
1612
        /* get the explicit superclass subnode */
1613
        sc_tok = &n0->prsnv.prsnvn[0]->prsnv.prsnvt;
1614
1615
        /* make sure the superclass is an object */
1616
        prsdef(ctx, sc_tok, TOKSTFWDOBJ);
1617
1618
        /* get the explicit superclass - it's the subnode */
1619
        exp_inh_obj = sc_tok->toksym.toksval;
1620
    }
1621
1622
    /* 
1623
     *   push object whose property we're getting unless inheriting or
1624
     *   getting a property of 'self' or of a fixed object (in which cases
1625
     *   the object is implicit in the opcode, rather than being on the
1626
     *   stack) 
1627
     */
1628
    if (!inh && !slf && !objflg)
1629
        prsgexp(ctx, n0);
1630
1631
    if (n1->prsnnlf == 0
1632
        && n1->prsnv.prsnvt.toktyp == TOKTPOUND)
1633
    {
1634
        /* RHS is a property symbol - do a simple GETP (or INHERIT) */
1635
        prpnum prop = n1->prsnv.prsnvt.tokofs;
1636
1637
        /* 
1638
         *   emit the opcode and argument count - use the regular
1639
         *   (non-pointer) opcode, since we have a regular property value 
1640
         */
1641
        emtop(ctx->prscxemt, reg_op);
1642
        emtbyte(ctx->prscxemt, cnt);
1643
1644
        /* if we are encoding the object in the instruction, emit it now */
1645
        if (objflg)
1646
            emtint2(ctx->prscxemt, n0->prsnv.prsnvt.toksym.toksval);
1647
1648
        /* add the property value */
1649
        emtint2(ctx->prscxemt, prop);
1650
1651
        /* 
1652
         *   if this is an "inherited" with an explicit superclass, add
1653
         *   the explicit superclass value 
1654
         */
1655
        if (exp_inh)
1656
            emtint2(ctx->prscxemt, exp_inh_obj);
1657
    }
1658
    else
1659
    {
1660
        /* 
1661
         *   evaluate the LHS unconditionally, even if it's just a fixed
1662
         *   object, since we have no special instruction that encodes an
1663
         *   object value in a pointer property evaluation 
1664
         */
1665
        if (objflg)
1666
            prsgexp(ctx, n0);
1667
1668
        /* RHS is an expression - evaluate it */
1669
        prsgexp(ctx, n1);
1670
1671
        /* 
1672
         *   emit the opcode and the byte count - use the pointer opcode,
1673
         *   since we have a property pointer 
1674
         */
1675
        emtop(ctx->prscxemt, ptr_op);
1676
        emtbyte(ctx->prscxemt, cnt);
1677
1678
        /* 
1679
         *   if this is an "inherited" with an explicit superclass, add
1680
         *   the explicit superclass value 
1681
         */
1682
        if (exp_inh)
1683
            emtint2(ctx->prscxemt, exp_inh_obj);
1684
    }
1685
}
1686
1687
/* generate code for a property lookup during speculative evaluation */
1688
static void prsgdotspec(prscxdef *ctx, prsndef *n)
1689
{
1690
    prsndef *n0 = n->prsnv.prsnvn[0];
1691
    prsndef *n1 = n->prsnv.prsnvn[1];
1692
1693
    /* push object whose property we're getting */
1694
    prsgexp(ctx, n0);
1695
1696
    if (n1->prsnnlf == 0
1697
        && n1->prsnv.prsnvt.toktyp == TOKTPOUND)
1698
    {
1699
        /* RHS is a property symbol - do a simple GETP (or INHERIT) */
1700
        prpnum prop = n1->prsnv.prsnvt.tokofs;
1701
1702
        /* push the data property */
1703
        emtop(ctx->prscxemt, OPCGETPDATA);
1704
        emtint2(ctx->prscxemt, prop);
1705
    }
1706
    else
1707
    {
1708
        /* RHS is an expression - evaluate it */
1709
        prsgexp(ctx, n1);
1710
1711
        /* get the data property */
1712
        emtop(ctx->prscxemt, OPCPTRGETPDATA);
1713
    }
1714
}
1715
1716
/* token -> assignment type field conversions */
1717
static uchar prsglcvt[] =
1718
{
1719
    OPCASIINC | OPCASIPRE,                                        /* pre ++ */
1720
    OPCASIINC | OPCASIPOST,                                      /* post ++ */
1721
    OPCASIDEC | OPCASIPRE,                                        /* pre -- */
1722
    OPCASIDEC | OPCASIPOST,                                      /* post ++ */
1723
    OPCASIADD,                                                        /* += */
1724
    OPCASISUB,                                                        /* -= */
1725
    OPCASIDIV,                                                        /* /= */
1726
    OPCASIMUL,                                                        /* *= */
1727
    OPCASIDIR                                                         /* := */
1728
};
1729
1730
/* extended assignment type field conversions */
1731
static uchar prsglcvt_ext[] =
1732
{
1733
    OPCASIMOD,                                                        /* %= */
1734
    OPCASIBAND,                                                       /* &= */
1735
    OPCASIBOR,                                                        /* |= */
1736
    OPCASIXOR,                                                        /* ^= */
1737
    OPCASISHL,                                                       /* <<= */
1738
    OPCASISHR                                                        /* >>= */
1739
};
1740
    
1741
/* generate code for an l-value */
1742
static void prsglval(prscxdef *ctx, int typ, prsndef *n)
1743
{
1744
    uchar op;
1745
    uchar op2;
1746
1747
    if (typ - TOKTINC < sizeof(prsglcvt)/sizeof(prsglcvt[0]))
1748
    {
1749
        op = OPCASI_MASK | prsglcvt[typ - TOKTINC];   /* form basic op code */
1750
        op2 = 0;
1751
    }
1752
    else
1753
    {
1754
        op = OPCASI_MASK | OPCASIEXT;
1755
        op2 = prsglcvt_ext[typ - TOKTMODEQ];
1756
    }
1757
    
1758
    switch(n->prsnnlf)
1759
    {
1760
    case 0:
1761
        {
1762
            int lclnum;
1763
            int styp;
1764
1765
            /* DON'T assume this is a 'self.' property if unknown */
1766
            /* DON'T prsdef(ctx, &n->prsnv.prsnvt, TOKSTPROP); */
1767
1768
            if (n->prsnv.prsnvt.toktyp == TOKTSYMBOL)
1769
            {
1770
                if (ctx->prscxflg & PRSCXFWTCH)
1771
                    errsig(ctx->prscxerr, ERR_WTCHLCL);
1772
1773
                if ((styp = n->prsnv.prsnvt.toksym.tokstyp) == TOKSTLOCAL)
1774
                {
1775
                    emtop(ctx->prscxemt, op | OPCASILCL);
1776
                    if (op2) emtop(ctx->prscxemt, op2);
1777
                    lclnum = n->prsnv.prsnvt.toksym.toksval;
1778
                    emtint2(ctx->prscxemt, lclnum);
1779
                }
1780
                else if (styp == TOKSTPROP)
1781
                {
1782
                    if (ctx->prscxflg & PRSCXFFUNC)
1783
                        errlog(ctx->prscxerr, ERR_NOSELF);
1784
                    
1785
                    emtop(ctx->prscxemt, OPCPUSHSELF);
1786
                    emtop(ctx->prscxemt, op | OPCASIPRP);
1787
                    if (op2) emtop(ctx->prscxemt, op2);
1788
                    lclnum = n->prsnv.prsnvt.toksym.toksval;
1789
                    emtint2(ctx->prscxemt, lclnum);
1790
                }
1791
                else if (styp == TOKSTPROPSPEC)
1792
                    errsig(ctx->prscxerr, ERR_BADSPECEXPR);
1793
                else
1794
                    errlog(ctx->prscxerr, ERR_INVASI);
1795
            }
1796
            else
1797
                errlog(ctx->prscxerr, ERR_INVASI);
1798
        }
1799
        break;
1800
        
1801
    case 2:
1802
        switch(n->prsntyp)
1803
        {
1804
        case TOKTDOT:
1805
            {
1806
                prsndef *n1 = n->prsnv.prsnvn[1];
1807
                int      base_opc;
1808
                int      direct_prop;
1809
                prpnum   prop;
1810
                    
1811
                /* generate the expression providing the object */
1812
                prsgexp(ctx, n->prsnv.prsnvn[0]);
1813
1814
                /* determine the correct base opcode */
1815
                if (n1->prsnnlf == 0 && n1->prsnv.prsnvt.toktyp == TOKTPOUND)
1816
                {
1817
1818
                    /* simple property assignment */
1819
                    direct_prop = TRUE;
1820
                    base_opc = OPCASIPRP;
1821
1822
                    /* remember the property id */
1823
                    prop = n1->prsnv.prsnvt.tokofs;
1824
                }
1825
                else
1826
                {
1827
                    /* assignment through property pointer */
1828
                    direct_prop = FALSE;
1829
                    base_opc = OPCASIPRPPTR;
1830
1831
                    /* generate the property pointer expression */
1832
                    prsgexp(ctx, n1);
1833
                }
1834
1835
                /* generate the appropriate property assignment opcode */
1836
                emtop(ctx->prscxemt, op | base_opc);
1837
                if (op2) emtop(ctx->prscxemt, op2);
1838
1839
                /* if it's a simple assignment, add the property code */
1840
                if (direct_prop) emtint2(ctx->prscxemt, prop);
1841
1842
                break;
1843
            }
1844
            
1845
        case TOKTLBRACK:
1846
            prsgexp(ctx, n->prsnv.prsnvn[0]);             /* evaluate list  */
1847
            prsgexp(ctx, n->prsnv.prsnvn[1]);             /* evaluate index */
1848
            emtop(ctx->prscxemt, op | OPCASIIND);
1849
            if (op2) emtop(ctx->prscxemt, op2);
1850
            prsglval(ctx, TOKTASSIGN, n->prsnv.prsnvn[0]);      /* set list */
1851
            break;
1852
            
1853
        default:
1854
            errlog(ctx->prscxerr, ERR_INVASI);
1855
        }
1856
        break;
1857
        
1858
    default:
1859
        errlog(ctx->prscxerr, ERR_INVASI);
1860
    }
1861
}
1862
1863
/* generate code for an argument list; returns argument count */
1864
static int prsgargs(prscxdef *ctx, prsndef *n)
1865
{
1866
    int cnt = 0;
1867
    
1868
    if (n->prsnnlf == 2 && n->prsntyp == TOKTRPAR)
1869
    {
1870
        cnt = prsgargs(ctx, n->prsnv.prsnvn[1]);
1871
        prsgexp(ctx, n->prsnv.prsnvn[0]);
1872
    }
1873
    else
1874
        prsgexp(ctx, n);
1875
    
1876
    return(cnt + 1);
1877
}
1878