FreeBASIC  0.91.0
ast-node-misc.bas
Go to the documentation of this file.
1 '' AST misc nodes
2 ''
3 '' chng: sep/2004 written [v1ctor]
4 
5 
6 #include once "fb.bi"
7 #include once "fbint.bi"
8 #include once "lex.bi"
9 #include once "parser.bi"
10 #include once "ir.bi"
11 #include once "ast.bi"
12 #include once "emit.bi"
13 
14 '' Labels (l = NULL; r = NULL)
15 function astNewLABEL _
16  ( _
17  byval sym as FBSYMBOL ptr, _
18  byval doflush as integer _
19  ) as ASTNODE ptr
20 
21  dim as ASTNODE ptr n = any
22 
23  n = astNewNode( AST_NODECLASS_LABEL, FB_DATATYPE_INVALID )
24 
25  n->sym = sym
26  n->lbl.flush = doflush
27 
28  if( symbIsLabel( sym ) ) then
29  if( symbGetLabelIsDeclared( sym ) = FALSE ) then
30  symbSetLabelIsDeclared( sym )
31  symbGetLabelStmt( sym ) = parser.stmt.cnt
32  symbGetLabelParent( sym ) = parser.currblock
33  end if
34  end if
35 
36  function = n
37 end function
38 
39 function astLoadLABEL( byval n as ASTNODE ptr ) as IRVREG ptr
40  if( ast.doemit ) then
41  if( n->lbl.flush ) then
42  irEmitLABEL( n->sym )
43  else
44  irEmitLABELNF( n->sym )
45  end if
46  end if
47 
48  function = NULL
49 end function
50 
51 '' Literals (l = NULL; r = NULL)
52 function astNewLIT( byval text as zstring ptr ) as ASTNODE ptr
53  dim as ASTNODE ptr n = any
54 
55  n = astNewNode( AST_NODECLASS_LIT, FB_DATATYPE_INVALID )
56 
57  n->lit.text = ZstrAllocate( len( *text ) )
58  *n->lit.text = *text
59 
60  function = n
61 end function
62 
63 function astLoadLIT( byval n as ASTNODE ptr ) as IRVREG ptr
64  if( ast.doemit ) then
65  irEmitCOMMENT( n->lit.text )
66  end if
67 
68  ZstrFree( n->lit.text )
69 
70  function = NULL
71 end function
72 
73 function astAsmAppend _
74  ( _
75  byval tail as ASTASMTOK ptr, _
76  byval typ as integer _
77  ) as ASTASMTOK ptr
78 
79  dim as ASTASMTOK ptr asmtok = any
80 
81  asmtok = listNewNode( @ast.asmtoklist )
82 
83  if( tail ) then
84  tail->next = asmtok
85  end if
86  asmtok->type = typ
87  asmtok->next = NULL
88 
89  function = asmtok
90 end function
91 
92 function astAsmAppendText _
93  ( _
94  byval tail as ASTASMTOK ptr, _
95  byval text as zstring ptr _
96  ) as ASTASMTOK ptr
97 
98  tail = astAsmAppend( tail, AST_ASMTOK_TEXT )
99 
100  tail->text = ZstrAllocate( len( *text ) )
101  *tail->text = *text
102 
103  function = tail
104 end function
105 
106 function astAsmAppendSymb _
107  ( _
108  byval tail as ASTASMTOK ptr, _
109  byval sym as FBSYMBOL ptr _
110  ) as ASTASMTOK ptr
111 
112  tail = astAsmAppend( tail, AST_ASMTOK_SYMB )
113 
114  tail->sym = sym
115 
116  function = tail
117 end function
118 
119 '' ASM (l = NULL; r = NULL)
120 function astNewASM( byval asmtokhead as ASTASMTOK ptr ) as ASTNODE ptr
121  dim as ASTNODE ptr n = any
122 
123  n = astNewNode( AST_NODECLASS_ASM, FB_DATATYPE_INVALID )
124 
125  n->asm.tokhead = asmtokhead
126 
127  function = n
128 end function
129 
130 function astLoadASM( byval n as ASTNODE ptr ) as IRVREG ptr
131  dim as ASTASMTOK ptr node = any, nxt = any
132 
133  if( ast.doemit ) then
134  irEmitAsmBegin( )
135  end if
136 
137  node = n->asm.tokhead
138  while( node )
139  nxt = node->next
140 
141  select case( node->type )
142  case AST_ASMTOK_TEXT
143  if( ast.doemit ) then
144  irEmitAsmText( node->text )
145  end if
146  ZstrFree( node->text )
147  case AST_ASMTOK_SYMB
148  if( ast.doemit ) then
149  irEmitAsmSymb( node->sym )
150  end if
151  end select
152 
153  listDelNode( @ast.asmtoklist, node )
154  node = nxt
155  wend
156 
157  if( ast.doemit ) then
158  irEmitAsmEnd( )
159  end if
160 
161  function = NULL
162 end function
163 
164 '' Debug (l = NULL; r = NULL)
165 function astNewDBG _
166  ( _
167  byval op as integer, _
168  byval ex as integer _
169  ) as ASTNODE ptr
170 
171  dim as ASTNODE ptr n = any
172 
173  if( env.clopt.debug = FALSE ) then
174  return NULL
175  end if
176 
177  n = astNewNode( AST_NODECLASS_DBG, FB_DATATYPE_INVALID )
178 
179  n->dbg.op = op
180  n->dbg.ex = ex
181 
182  function = n
183 end function
184 
185 function astLoadDBG( byval n as ASTNODE ptr ) as IRVREG ptr
186  if( ast.doemit ) then
187  irEmitDBG( n->dbg.op, astGetProc( )->sym, n->dbg.ex )
188  end if
189 
190  function = NULL
191 end function
192 
193 '' No Operation (l = NULL; r = NULL)
194 function astNewNOP( ) as ASTNODE ptr
195  dim as ASTNODE ptr n = any
196 
197  n = astNewNode( AST_NODECLASS_NOP, FB_DATATYPE_INVALID )
198 
199  function = n
200 end function
201 
202 function astLoadNOP( byval n as ASTNODE ptr ) as IRVREG ptr
203  '' do nothing
204  function = NULL
205 end function
206 
207 '' Non-Indexed Array (l = expr; r = NULL)
208 function astNewNIDXARRAY( byval expr as ASTNODE ptr ) as ASTNODE ptr
209  dim as ASTNODE ptr n = any
210 
211  n = astNewNode( AST_NODECLASS_NIDXARRAY, FB_DATATYPE_INVALID )
212 
213  n->l = expr
214 
215  function = n
216 end function
217 
218 function astLoadNIDXARRAY( byval n as ASTNODE ptr ) as IRVREG ptr
219  astDelTree( n->l )
220  function = NULL
221 end function
222 
223 '' Links (l = statement 1; r = statement 2)
224 function astNewLINK _
225  ( _
226  byval l as ASTNODE ptr, _
227  byval r as ASTNODE ptr, _
228  byval ret_left as integer _
229  ) as ASTNODE ptr
230 
231  dim as ASTNODE ptr n = any
232 
233  if( l = NULL ) then
234  return r
235  end if
236 
237  if( r = NULL ) then
238  return l
239  end if
240 
241  if( ret_left ) then
242  n = astNewNode( AST_NODECLASS_LINK, astGetFullType( l ), l->subtype )
243  else
244  n = astNewNode( AST_NODECLASS_LINK, astGetFullType( r ), r->subtype )
245  end if
246 
247  n->link.ret_left = ret_left
248  n->l = l
249  n->r = r
250 
251  function = n
252 end function
253 
254 function astLoadLINK( byval n as ASTNODE ptr ) as IRVREG ptr
255  dim as IRVREG ptr vrl = any, vrr = any
256 
257  vrl = astLoad( n->l )
258  astDelNode( n->l )
259 
260  vrr = astLoad( n->r )
261  astDelNode( n->r )
262 
263  if( n->link.ret_left ) then
264  function = vrl
265  else
266  function = vrr
267  end if
268 end function
269 
270 '' Explicit loads (l = expression to load to a register; r = NULL)
271 function astNewLOAD _
272  ( _
273  byval l as ASTNODE ptr, _
274  byval dtype as integer, _
275  byval isresult as integer _
276  ) as ASTNODE ptr
277 
278  '' alloc new node
279  dim as ASTNODE ptr n = astNewNode( AST_NODECLASS_LOAD, dtype )
280 
281  n->l = l
282  n->lod.isres = isresult
283 
284  function = n
285 end function
286 
287 function astLoadLOAD( byval n as ASTNODE ptr ) as IRVREG ptr
288  dim as ASTNODE ptr l = any
289  dim as IRVREG ptr v1 = any, vr = any
290 
291  l = n->l
292  if( l = NULL ) then
293  return NULL
294  end if
295 
296  v1 = astLoad( l )
297 
298  if( ast.doemit ) then
299  if( n->lod.isres ) then
300  vr = irAllocVREG( irGetVRDataType( v1 ), irGetVRSubType( v1 ) )
301  irEmitLOADRES( v1, vr )
302  else
303  irEmitLOAD( v1 )
304  end if
305  end if
306 
307  astDelNode( l )
308 
309  function = v1
310 end function
311 
312 '' Field accesses - used in expression trees to be able to identify bitfield
313 '' assignments/accesses, and also by astOptimizeTree() to optimize nested field
314 '' accesses.
315 '' l = field access; r = NULL
316 function astNewFIELD _
317  ( _
318  byval l as ASTNODE ptr, _
319  byval sym as FBSYMBOL ptr _
320  ) as ASTNODE ptr
321 
322  dim as ASTNODE ptr n = any
323  dim as integer dtype = any
324  dim as FBSYMBOL ptr subtype = any
325 
326  dtype = l->dtype
327  subtype = l->subtype
328 
329  if( typeGetDtAndPtrOnly( dtype ) = FB_DATATYPE_BITFIELD ) then
330  '' final type is always an unsigned int
331  dtype = typeJoin( dtype, FB_DATATYPE_UINT )
332  subtype = NULL
333 
334  ast.bitfieldcount += 1
335 
336  '' Note: We can't generate bitfield access code here yet,
337  '' because we don't know whether this will be a load from or
338  '' store to a bitfield.
339  end if
340 
341  n = astNewNode( AST_NODECLASS_FIELD, dtype, subtype )
342  n->sym = sym
343  n->l = l
344 
345  function = n
346 end function
347 
348 '' Decrease bitfield counter for the bitfield FIELD nodes in this tree,
349 '' to be used on field/parameter initializers that are never astAdd()ed,
350 '' but only ever cloned.
351 sub astForgetBitfields( byval n as ASTNODE ptr )
352  if( (n = NULL) or (ast.bitfieldcount <= 0) ) then
353  exit sub
354  end if
355 
356  if( astIsBITFIELD( n ) ) then
357  ast.bitfieldcount -= 1
358  end if
359 
360  astForgetBitfields( n->l )
361  astForgetBitfields( n->r )
362 end sub
363 
364 function astSetBitfield _
365  ( _
366  byval l as ASTNODE ptr, _
367  byval r as ASTNODE ptr _
368  ) as ASTNODE ptr
369 
370  dim as FBSYMBOL ptr s = any
371 
372  ''
373  '' l<bitfield> = r
374  '' becomes:
375  '' l<int> = (l<int> and mask) or ((r and bits) shl bitpos)
376  ''
377 
378  s = l->subtype
379  assert( symbIsBitfield( s ) )
380 
381  '' Remap type from bitfield to short/integer/etc., whichever was given
382  '' on the bitfield, to do a "full" field access.
383  astGetFullType( l ) = symbGetFullType( s )
384  l->subtype = s->subtype
385 
386  '' l is reused on the rhs and thus must be duplicated
387  l = astCloneTree( l )
388 
389  '' Apply a mask to retrieve all bits but the bitfield's ones
390  l = astNewBOP( AST_OP_AND, l, astNewCONSTi( not (ast_bitmaskTB(s->bitfld.bits) shl s->bitfld.bitpos) ) )
391 
392  '' This ensures the bitfield is zeroed & clean before the new value
393  '' is ORed in below. Since the new value may contain zeroes while the
394  '' old values may have one-bits, the OR alone wouldn't necessarily
395  '' overwrite the old value.
396 
397  '' Truncate r if it's too big, ensuring the OR below won't touch any
398  '' other bits outside the target bitfield.
399  r = astNewBOP( AST_OP_AND, r, astNewCONSTi( ast_bitmaskTB(s->bitfld.bits) ) )
400 
401  '' Move r into position if the bitfield doesn't lie at the beginning of
402  '' the accessed field.
403  if( s->bitfld.bitpos > 0 ) then
404  r = astNewBOP( AST_OP_SHL, r, astNewCONSTi( s->bitfld.bitpos ) )
405  end if
406 
407  '' OR in the new bitfield value r
408  function = astNewBOP( AST_OP_OR, l, r )
409 end function
410 
411 function astAccessBitfield( byval l as ASTNODE ptr ) as ASTNODE ptr
412  dim as FBSYMBOL ptr s = any
413 
414  '' l<bitfield>
415  '' becomes:
416  '' (l<int> shr bitpos) and mask
417 
418  s = l->subtype
419  assert( symbIsBitfield( s ) )
420 
421  '' Remap type from bitfield to short/integer/etc, while keeping in
422  '' mind that the bitfield may have been casted, so the FIELD's type
423  '' can't just be discarded.
424  l->dtype = typeJoin( l->dtype, s->typ )
425  l->subtype = s->subtype
426 
427  '' Shift into position, other bits to the right are shifted out
428  if( s->bitfld.bitpos > 0 ) then
429  l = astNewBOP( AST_OP_SHR, l, astNewCONSTi( s->bitfld.bitpos ) )
430  end if
431 
432  '' Mask out other bits to the left
433  return astNewBOP( AST_OP_AND, l, astNewCONSTi( ast_bitmaskTB(s->bitfld.bits) ) )
434 end function
435 
436 #if __FB_DEBUG__
437 '' Count the bitfield FIELD nodes in a tree
438 function astCountBitfields( byval n as ASTNODE ptr ) as integer
439  dim as integer count = any
440 
441  count = 0
442 
443  if( n ) then
444  if( astIsBITFIELD( n ) ) then
445  count += 1
446  end if
447 
448  count += astCountBitfields( n->l )
449  count += astCountBitfields( n->r )
450  end if
451 
452  function = count
453 end function
454 #endif
455 
456 '' Remove FIELD nodes that mark bitfield accesses/assignments and add the
457 '' corresponding code instead. Non-bitfield FIELD nodes stay in,
458 '' they're used by astProcVectorize().
459 function astUpdateBitfields( byval n as ASTNODE ptr ) as ASTNODE ptr
460  dim as ASTNODE ptr l = any
461 
462  '' Shouldn't miss any bitfields
463  assert( astCountBitfields( n ) <= ast.bitfieldcount )
464 
465  if( ast.bitfieldcount <= 0 ) then
466  return n
467  end if
468 
469  if( n = NULL ) then
470  return NULL
471  end if
472 
473  select case( n->class )
474  case AST_NODECLASS_ASSIGN
475  '' Assigning to a bitfield?
476  if( n->l->class = AST_NODECLASS_FIELD ) then
477  if( astGetDataType( n->l->l ) = FB_DATATYPE_BITFIELD ) then
478  '' Delete and link out the FIELD
479  ast.bitfieldcount -= 1
480  astDelNode( n->l )
481  n->l = n->l->l
482 
483  '' The lhs' type is adjusted, and the new rhs
484  '' is returned.
485  n->r = astSetBitfield( n->l, n->r )
486  end if
487  end if
488 
489  case AST_NODECLASS_FIELD
490  l = n->l
491  if( astGetDataType( l ) = FB_DATATYPE_BITFIELD ) then
492  l = astAccessBitfield( l )
493 
494  '' Delete and link out the FIELD
495  ast.bitfieldcount -= 1
496  astDelNode( n )
497  n = l
498 
499  return astUpdateBitfields( n )
500  end if
501 
502  end select
503 
504  n->l = astUpdateBitfields( n->l )
505  n->r = astUpdateBitfields( n->r )
506 
507  function = n
508 end function
509 
510 function astLoadFIELD( byval n as ASTNODE ptr ) as IRVREG ptr
511  dim as IRVREG ptr vr = any
512 
513  vr = astLoad( n->l )
514  astDelNode( n->l )
515 
516  if( ast.doemit ) then
517  vr->vector = n->vector
518  end if
519 
520  function = vr
521 end function
522 
523 '' Stack operations (l = expression; r = NULL)
524 
525 function astNewSTACK _
526  ( _
527  byval op as integer, _
528  byval l as ASTNODE ptr _
529  ) as ASTNODE ptr
530 
531  dim as ASTNODE ptr n = any
532 
533  if( l = NULL ) then
534  return NULL
535  end if
536 
537  n = astNewNode( AST_NODECLASS_STACK, astGetFullType( l ), NULL )
538 
539  n->stack.op = op
540  n->l = l
541 
542  function = n
543 end function
544 
545 function astLoadSTACK( byval n as ASTNODE ptr ) as IRVREG ptr
546  dim as ASTNODE ptr l = any
547  dim as IRVREG ptr vr = any
548 
549  l = n->l
550  if( l = NULL ) then
551  return NULL
552  end if
553 
554  vr = astLoad( l )
555 
556  if( ast.doemit ) then
557  irEmitSTACK( n->stack.op, vr )
558  end if
559 
560  astDelNode( l )
561 
562  function = vr
563 end function
564 
565 '':::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
566 '' dumping
567 '':::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
568 
569 '' The tables below use 'NameInfo' as the struct for
570 '' information. To keep the size down, the FullName
571 '' field and value field (unused anyway) are commented
572 '' out.
573 
575  '' fullname as zstring ptr
576  name as const zstring ptr
577  '' value as integer
578 end type
579 
580 '':::::
581 sub dbg_astOutput _
582  ( _
583  byref s as string, _
584  byval col as integer, _
585  byval just as integer, _
586  byval depth as integer = -1 _
587  )
588 
589  dim pad as integer = any
590 
591  select case just
592  case -1
593  pad = col - len(s)
594  case 1
595  pad = col - 1
596  case else
597  pad = col
598  end select
599 
600  if( depth < 0 ) then
601  print space(pad-1); s
602  else
603  print str(depth); space(pad-1 - len(str(depth)) ); s
604  end if
605 
606 end sub
607 
608 ''
609 dim shared dbg_astNodeClassNames( 0 to AST_CLASSES-1 ) as NameInfo = _
610 { _
611 /' @"AST_NODECLASS_NOP" , '/ @"NOP"/' , 0 '/ ), _
612 /' @"AST_NODECLASS_LOAD" , '/ @"LOAD"/' , 0 '/ ), _
613 /' @"AST_NODECLASS_ASSIGN" , '/ @"ASSIGN"/' , 0 '/ ), _
614 /' @"AST_NODECLASS_BOP" , '/ @"BOP"/' , 0 '/ ), _
615 /' @"AST_NODECLASS_UOP" , '/ @"UOP"/' , 0 '/ ), _
616 /' @"AST_NODECLASS_CONV" , '/ @"CONV"/' , 0 '/ ), _
617 /' @"AST_NODECLASS_ADDROF" , '/ @"ADDROF"/' , 0 '/ ), _
618 /' @"AST_NODECLASS_BRANCH" , '/ @"BRANCH"/' , 0 '/ ), _
619 /' @"AST_NODECLASS_JMPTB" , '/ @"JMPTB"/' , 0 '/ ), _
620 /' @"AST_NODECLASS_CALL" , '/ @"CALL"/' , 0 '/ ), _
621 /' @"AST_NODECLASS_CALLCTOR" , '/ @"CALLCTOR"/' , 0 '/ ), _
622 /' @"AST_NODECLASS_STACK" , '/ @"STACK"/' , 0 '/ ), _
623 /' @"AST_NODECLASS_MEM" , '/ @"MEM"/' , 0 '/ ), _
624 /' @"AST_NODECLASS_LOOP" , '/ @"LOOP"/' , 0 '/ ), _
625 /' @"AST_NODECLASS_COMP" , '/ @"COMP"/' , 0 '/ ), _
626 /' @"AST_NODECLASS_LINK" , '/ @"LINK"/' , 0 '/ ), _
627 /' @"AST_NODECLASS_CONST" , '/ @"CONST"/' , 0 '/ ), _
628 /' @"AST_NODECLASS_VAR" , '/ @"VAR"/' , 0 '/ ), _
629 /' @"AST_NODECLASS_IDX" , '/ @"IDX"/' , 0 '/ ), _
630 /' @"AST_NODECLASS_FIELD" , '/ @"FIELD"/' , 0 '/ ), _
631 /' @"AST_NODECLASS_DEREF" , '/ @"DEREF"/' , 0 '/ ), _
632 /' @"AST_NODECLASS_LABEL" , '/ @"LABEL"/' , 0 '/ ), _
633 /' @"AST_NODECLASS_ARG" , '/ @"ARG"/' , 0 '/ ), _
634 /' @"AST_NODECLASS_OFFSET" , '/ @"OFFSET"/' , 0 '/ ), _
635 /' @"AST_NODECLASS_DECL" , '/ @"DECL"/' , 0 '/ ), _
636 /' @"AST_NODECLASS_NIDXARRAY" , '/ @"NIDXARRAY"/' , 0 '/ ), _
637 /' @"AST_NODECLASS_IIF" , '/ @"IIF"/' , 0 '/ ), _
638 /' @"AST_NODECLASS_LIT" , '/ @"LIT"/' , 0 '/ ), _
639 /' @"AST_NODECLASS_ASM" , '/ @"ASM"/' , 0 '/ ), _
640 /' @"AST_NODECLASS_DATASTMT" , '/ @"DATASTMT"/' , 0 '/ ), _
641 /' @"AST_NODECLASS_DBG" , '/ @"DBG"/' , 0 '/ ), _
642 /' @"AST_NODECLASS_BOUNDCHK" , '/ @"BOUNDCHK"/' , 0 '/ ), _
643 /' @"AST_NODECLASS_PTRCHK" , '/ @"PTRCHK"/' , 0 '/ ), _
644 /' @"AST_NODECLASS_SCOPEBEGIN" , '/ @"SCOPEBEGIN"/' , 0 '/ ), _
645 /' @"AST_NODECLASS_SCOPEEND" , '/ @"SCOPEEND"/' , 0 '/ ), _
646 /' @"AST_NODECLASS_SCOPE_BREAK" , '/ @"SCOPE_BREAK"/' , 0 '/ ), _
647 /' @"AST_NODECLASS_TYPEINI" , '/ @"TYPEINI"/' , 0 '/ ), _
648 /' @"AST_NODECLASS_TYPEINI_PAD" , '/ @"TYPEINI_PAD"/' , 0 '/ ), _
649 /' @"AST_NODECLASS_TYPEINI_ASSIGN" , '/ @"TYPEINI_ASSIGN"/' , 0 '/ ), _
650 /' @"AST_NODECLASS_TYPEINI_CTORCALL" , '/ @"TYPEINI_CTORCALL"/' , 0 '/ ), _
651 /' @"AST_NODECLASS_TYPEINI_CTORLIST" , '/ @"TYPEINI_CTORLIST"/' , 0 '/ ), _
652 /' @"AST_NODECLASS_TYPEINI_SCOPEINI" , '/ @"TYPEINI_SCOPEINI"/' , 0 '/ ), _
653 /' @"AST_NODECLASS_TYPEINI_SCOPEEND" , '/ @"TYPEINI_SCOPEEND"/' , 0 '/ ), _
654 /' @"AST_NODECLASS_PROC" , '/ @"PROC"/' , 0 '/ ) _
655 }
656 
657 ''
658 dim shared dbg_astNodeOpNames( 0 to AST_OPCODES - 1 ) as NameInfo = _
659 { _
660 /' @"AST_OP_ASSIGN" , '/ @"="/' , 0 '/ ), _
661 /' @"AST_OP_ADD_SELF" , '/ @"+="/' , 0 '/ ), _
662 /' @"AST_OP_SUB_SELF" , '/ @"-="/' , 0 '/ ), _
663 /' @"AST_OP_MUL_SELF" , '/ @"*="/' , 0 '/ ), _
664 /' @"AST_OP_DIV_SELF" , '/ @"/="/' , 0 '/ ), _
665 /' @"AST_OP_INTDIV_SELF" , '/ @"\="/' , 0 '/ ), _
666 /' @"AST_OP_MOD_SELF" , '/ @"MOD="/' , 0 '/ ), _
667 /' @"AST_OP_AND_SELF" , '/ @"AND="/' , 0 '/ ), _
668 /' @"AST_OP_OR_SELF" , '/ @"OR="/' , 0 '/ ), _
669 /' @"AST_OP_ANDALSO_SELF" , '/ @"ANDALSO="/' , 0 '/ ), _
670 /' @"AST_OP_ORELSE_SELF" , '/ @"ORELSE="/' , 0 '/ ), _
671 /' @"AST_OP_XOR_SELF" , '/ @"XOR="/' , 0 '/ ), _
672 /' @"AST_OP_EQV_SELF" , '/ @"EQV="/' , 0 '/ ), _
673 /' @"AST_OP_IMP_SELF" , '/ @"IMP="/' , 0 '/ ), _
674 /' @"AST_OP_SHL_SELF" , '/ @"SHL="/' , 0 '/ ), _
675 /' @"AST_OP_SHR_SELF" , '/ @"SHR="/' , 0 '/ ), _
676 /' @"AST_OP_POW_SELF" , '/ @"^="/' , 0 '/ ), _
677 /' @"AST_OP_CONCAT_SELF" , '/ @"&="/' , 0 '/ ), _
678 /' @"AST_OP_NEW_SELF" , '/ @"new="/' , 0 '/ ), _
679 /' @"AST_OP_NEW_VEC_SELF" , '/ @"new[]="/' , 0 '/ ), _
680 /' @"AST_OP_DEL_SELF" , '/ @"del="/' , 0 '/ ), _
681 /' @"AST_OP_DEL_VEC_SELF" , '/ @"del[]="/' , 0 '/ ), _
682 /' @"AST_OP_ADDROF" , '/ @"ADDROF"/' , 0 '/ ), _
683 /' @"AST_OP_PTRINDEX" , '/ @"PTRINDEX"/' , 0 '/ ), _
684 /' @"AST_OP_FOR" , '/ @"FOR"/' , 0 '/ ), _
685 /' @"AST_OP_STEP" , '/ @"STEP"/' , 0 '/ ), _
686 /' @"AST_OP_NEXT" , '/ @"NEXT"/' , 0 '/ ), _
687 /' @"AST_OP_CAST" , '/ @"CAST"/' , 0 '/ ), _
688 /' @"AST_OP_ADD" , '/ @"+"/' , 0 '/ ), _
689 /' @"AST_OP_SUB" , '/ @"-"/' , 0 '/ ), _
690 /' @"AST_OP_MUL" , '/ @"*"/' , 0 '/ ), _
691 /' @"AST_OP_DIV" , '/ @"/"/' , 0 '/ ), _
692 /' @"AST_OP_INTDIV" , '/ @"\"/' , 0 '/ ), _
693 /' @"AST_OP_MOD" , '/ @"MOD"/' , 0 '/ ), _
694 /' @"AST_OP_AND" , '/ @"AND"/' , 0 '/ ), _
695 /' @"AST_OP_OR" , '/ @"OR"/' , 0 '/ ), _
696 /' @"AST_OP_ANDALSO" , '/ @"ANDALSO"/' , 0 '/ ), _
697 /' @"AST_OP_ORELSE" , '/ @"ORELSE"/' , 0 '/ ), _
698 /' @"AST_OP_XOR" , '/ @"XOR"/' , 0 '/ ), _
699 /' @"AST_OP_EQV" , '/ @"EQV"/' , 0 '/ ), _
700 /' @"AST_OP_IMP" , '/ @"IMP"/' , 0 '/ ), _
701 /' @"AST_OP_SHL" , '/ @"SHL"/' , 0 '/ ), _
702 /' @"AST_OP_SHR" , '/ @"SHR"/' , 0 '/ ), _
703 /' @"AST_OP_POW" , '/ @"^"/' , 0 '/ ), _
704 /' @"AST_OP_CONCAT" , '/ @"&"/' , 0 '/ ), _
705 /' @"AST_OP_EQ" , '/ @"=="/' , 0 '/ ), _
706 /' @"AST_OP_GT" , '/ @">"/' , 0 '/ ), _
707 /' @"AST_OP_LT" , '/ @"<"/' , 0 '/ ), _
708 /' @"AST_OP_NE" , '/ @"<>"/' , 0 '/ ), _
709 /' @"AST_OP_GE" , '/ @">="/' , 0 '/ ), _
710 /' @"AST_OP_LE" , '/ @"<="/' , 0 '/ ), _
711 /' @"AST_OP_IS" , '/ @"IS"/' , 0 '/ ), _
712 /' @"AST_OP_NOT" , '/ @"NOT"/' , 0 '/ ), _
713 /' @"AST_OP_PLUS" , '/ @"+"/' , 0 '/ ), _
714 /' @"AST_OP_NEG" , '/ @"NEG"/' , 0 '/ ), _
715 /' @"AST_OP_HADD" , '/ @"HADD"/' , 0 '/ ), _
716 /' @"AST_OP_ABS" , '/ @"ABS"/' , 0 '/ ), _
717 /' @"AST_OP_SGN" , '/ @"SGN"/' , 0 '/ ), _
718 /' @"AST_OP_SIN" , '/ @"SIN"/' , 0 '/ ), _
719 /' @"AST_OP_ASIN" , '/ @"ASIN"/' , 0 '/ ), _
720 /' @"AST_OP_COS" , '/ @"COS"/' , 0 '/ ), _
721 /' @"AST_OP_ACOS" , '/ @"ACOS"/' , 0 '/ ), _
722 /' @"AST_OP_TAN" , '/ @"TAN"/' , 0 '/ ), _
723 /' @"AST_OP_ATAN" , '/ @"ATAN"/' , 0 '/ ), _
724 /' @"AST_OP_ATAN2" , '/ @"ATAN2"/' , 0 '/ ), _
725 /' @"AST_OP_SQRT" , '/ @"SQRT"/' , 0 '/ ), _
726 /' @"AST_OP_RSQRT" , '/ @"RSQRT"/' , 0 '/ ), _
727 /' @"AST_OP_RCP" , '/ @"RCP"/' , 0 '/ ), _
728 /' @"AST_OP_LOG" , '/ @"LOG"/' , 0 '/ ), _
729 /' @"AST_OP_EXP" , '/ @"EXP"/' , 0 '/ ), _
730 /' @"AST_OP_FLOOR" , '/ @"FLOOR"/' , 0 '/ ), _
731 /' @"AST_OP_FIX" , '/ @"FIX"/' , 0 '/ ), _
732 /' @"AST_OP_FRAC" , '/ @"FRAC"/' , 0 '/ ), _
733 /' @"AST_OP_CONVFD2FS" , '/ @"CONVFD2FS"/' , 0 '/ ), _
734 /' @"AST_OP_SWZREP" , '/ @"SWZREP"/' , 0 '/ ), _
735 /' @"AST_OP_DEREF" , '/ @"DEREF"/' , 0 '/ ), _
736 /' @"AST_OP_FLDDEREF" , '/ @"FLDDEREF"/' , 0 '/ ), _
737 /' @"AST_OP_NEW" , '/ @"NEW"/' , 0 '/ ), _
738 /' @"AST_OP_NEW_VEC" , '/ @"NEW_VEC"/' , 0 '/ ), _
739 /' @"AST_OP_DEL" , '/ @"DEL"/' , 0 '/ ), _
740 /' @"AST_OP_DEL_VEC" , '/ @"DEL_VEC"/' , 0 '/ ), _
741 /' @"AST_OP_TOINT" , '/ @"TOINT"/' , 0 '/ ), _
742 /' @"AST_OP_TOFLT" , '/ @"TOFLT"/' , 0 '/ ), _
743 /' @"AST_OP_LOAD" , '/ @"LOAD"/' , 0 '/ ), _
744 /' @"AST_OP_LOADRES" , '/ @"LOADRES"/' , 0 '/ ), _
745 /' @"AST_OP_SPILLREGS" , '/ @"SPILLREGS"/' , 0 '/ ), _
746 /' @"AST_OP_PUSH" , '/ @"PUSH"/' , 0 '/ ), _
747 /' @"AST_OP_POP" , '/ @"POP"/' , 0 '/ ), _
748 /' @"AST_OP_PUSHUDT" , '/ @"PUSHUDT"/' , 0 '/ ), _
749 /' @"AST_OP_STACKALIGN" , '/ @"STACKALIGN"/' , 0 '/ ), _
750 /' @"AST_OP_JEQ" , '/ @"JEQ"/' , 0 '/ ), _
751 /' @"AST_OP_JGT" , '/ @"JGT"/' , 0 '/ ), _
752 /' @"AST_OP_JLT" , '/ @"JLT"/' , 0 '/ ), _
753 /' @"AST_OP_JNE" , '/ @"JNE"/' , 0 '/ ), _
754 /' @"AST_OP_JGE" , '/ @"JGE"/' , 0 '/ ), _
755 /' @"AST_OP_JLE" , '/ @"JLE"/' , 0 '/ ), _
756 /' @"AST_OP_JMP" , '/ @"JMP"/' , 0 '/ ), _
757 /' @"AST_OP_CALL" , '/ @"CALL"/' , 0 '/ ), _
758 /' @"AST_OP_LABEL" , '/ @"LABEL"/' , 0 '/ ), _
759 /' @"AST_OP_RET" , '/ @"RET"/' , 0 '/ ), _
760 /' @"AST_OP_CALLFUNCT" , '/ @"CALLFUNCT"/' , 0 '/ ), _
761 /' @"AST_OP_CALLPTR" , '/ @"CALLPTR"/' , 0 '/ ), _
762 /' @"AST_OP_JUMPPTR" , '/ @"JUMPPTR"/' , 0 '/ ), _
763 /' @"AST_OP_MEMMOVE" , '/ @"MEMMOVE"/' , 0 '/ ), _
764 /' @"AST_OP_MEMSWAP" , '/ @"MEMSWAP"/' , 0 '/ ), _
765 /' @"AST_OP_MEMCLEAR" , '/ @"MEMCLEAR"/' , 0 '/ ), _
766 /' @"AST_OP_STKCLEAR" , '/ @"STKCLEAR"/' , 0 '/ ), _
767 /' @"AST_OP_DBG_LINEINI" , '/ @"DBG_LINEINI"/' , 0 '/ ), _
768 /' @"AST_OP_DBG_LINEEND" , '/ @"DBG_LINEEND"/' , 0 '/ ), _
769 /' @"AST_OP_DBG_SCOPEINI" , '/ @"DBG_SCOPEINI"/' , 0 '/ ), _
770 /' @"AST_OP_DBG_SCOPEEND" , '/ @"BDG_SCOPEEND"/' , 0 '/ ), _
771 /' @"AST_OP_LIT_COMMENT" , '/ @"LIT_COMMENT"/' , 0 '/ ), _
772 /' @"AST_OP_LIT_ASM" , '/ @"LIT_ASM"/' , 0 '/ ), _
773 /' @"AST_OP_TOSIGNED" , '/ @"TOSIGNED"/' , 0 '/ ), _
774 /' @"AST_OP_TOUNSIGNED" , '/ @"TOUNSIGNED"/' , 0 '/ ) _
775 }
776 
777 function astDumpOp( byval op as AST_OP ) as string
778  if(( op > AST_OPCODES - 1 ) or ( op < 0 )) then
779  return "OP:" + str(op)
780  end if
781  return *dbg_astNodeOpNames( op ).name
782 end function
783 
784 '':::::
785 function hAstNodeClassToStr _
786  ( _
787  byval c as AST_NODECLASS _
788  ) as string
789 
790  if(( c > AST_CLASSES - 1 ) or ( c < 0 )) then
791  return "CLASS:" + str(c)
792  end if
793 
794  return *dbg_astNodeClassNames( c ).name
795 
796 end function
797 
798 '':::::
799 function hSymbToStr _
800  ( _
801  byval s as FBSYMBOL ptr _
802  ) as string
803 
804  if( s = NULL ) then return ""
805 
806  if( s->id.name ) then
807  return *(s->id.name)
808  elseif( s->id.alias ) then
809  return *(s->id.alias)
810  end if
811 end function
812 
813 '':::::
814 function hAstNodeToStr _
815  ( _
816  byval n as ASTNODE ptr _
817  ) as string
818 
819  select case as const n->class
820  case AST_NODECLASS_BOP
821  return astDumpOp( n->op.op ) & " =-= " & hSymbToStr( n->op.ex )
822 
823  case AST_NODECLASS_UOP
824  return astDumpOp( n->op.op )
825 
826  case AST_NODECLASS_CONST
827  if( typeGetClass( n->dtype ) = FB_DATACLASS_FPOINT ) then
828  return str( astConstGetFloat( n ) )
829  end if
830  return str( astConstGetInt( n ) )
831 
832  case AST_NODECLASS_VAR
833  return "VAR( " & *symbGetName( n->sym ) & " )"
834 
835  case AST_NODECLASS_DECL
836  if( n->sym ) then
837  return "DECL( " & *symbGetName( n->sym ) & " )"
838  end if
839  return "DECL"
840 
841  case AST_NODECLASS_CALL
842  return "CALL( " & *symbGetName( n->sym ) & " )"
843 
844  case AST_NODECLASS_LABEL
845  return "LABEL: " & hSymbToStr( n->sym )
846 
847  case AST_NODECLASS_BRANCH
848  return "BRANCH: " & astDumpOp( n->op.op ) & " " & hSymbToStr( n->op.ex )
849 
850  case AST_NODECLASS_SCOPEBEGIN
851  return "SCOPEBEGIN: " & hSymbToStr( n->sym )
852 
853  case else
854  return hAstNodeClassToStr( n->class )
855  end select
856 
857 end function
858 
859 '':::::
860 sub astDumpTreeEx _
861  ( _
862  byval n as ASTNODE ptr, _
863  byval col as integer, _
864  byval just as integer, _
865  byval depth as integer _
866  )
867 
868  if( col <= 4 or col >= 76 ) then
869  col = 40
870  end if
871 
872  if( n = NULL ) then
873  print "<NULL>"
874  exit sub
875  end if
876 
877  dim as string s
878  's += "[" + hex( n, 8 ) + "] "
879  s += hAstNodeToStr( n )
880  's += " " + typeDump( n->dtype, n->subtype )
881  dbg_astOutput( s, col, just, depth )
882 
883  depth += 1
884 
885  if( n->l <> NULL ) then
886  if( n->r <> NULL ) then
887  dbg_astOutput( "/ \", col-2, 0 )
888  else
889  dbg_astOutput( "/", col-2, 0 )
890  end if
891  elseif( n->r <> NULL ) then
892  dbg_astOutput( " \", col-2, 0 )
893  else
894  dbg_astOutput( "", 0, 0 )
895  end if
896 
897  if( n->l <> NULL ) then
898  astDumpTreeEx( n->l, col-2, -1, depth )
899  end if
900  if( n->r <> NULL ) then
901  astDumpTreeEx( n->r, col+2, 1, depth )
902  end if
903 
904 end sub
905 
906 '':::::
907 sub astDumpTree _
908  ( _
909  byval n as ASTNODE ptr, _
910  byval col as integer _
911  )
912 
913  astDumpTreeEx( n, col, -1, 0 )
914 
915 end sub
916 
917 ''::::
918 sub astDumpList _
919  ( _
920  byval n as ASTNODE ptr, _
921  byval col as integer _
922  )
923 
924  do while( n <> NULL )
925  astDumpTree( n, col )
926  n = n->next
927  loop
928 
929 end sub
930 
931 #if __FB_DEBUG__
932 function astDumpInline( byval n as ASTNODE ptr ) as string
933  static reclevel as integer
934 
935  reclevel += 1
936 
937  dim s as string
938  if( n = NULL ) then
939  s = "<NULL>"
940  else
941  s += hAstNodeClassToStr( n->class )
942  's += typeDump( n->dtype, n->subtype )
943 
944  var have_data = (n->sym <> NULL) or (n->l <> NULL) or (n->r <> NULL)
945  select case as const( n->class )
946  case AST_NODECLASS_BOP, AST_NODECLASS_UOP, AST_NODECLASS_CONST
947  have_data or= TRUE
948  end select
949 
950  if( have_data ) then
951  s += "( "
952  end if
953 
954  select case as const( n->class )
955  case AST_NODECLASS_BOP, AST_NODECLASS_UOP
956  s += astDumpOp( n->op.op ) + ", "
957  case AST_NODECLASS_CONST
958  if( typeGetClass( n->dtype ) = FB_DATACLASS_FPOINT ) then
959  s += str( astConstGetFloat( n ) ) + ", "
960  else
961  s += str( astConstGetInt( n ) ) + ", "
962  end if
963  end select
964 
965  if( n->sym ) then
966  s += *symbGetName( n->sym ) + ", "
967  end if
968  if( n->l ) then
969  s += astDumpInline( n->l ) + ", "
970  end if
971  if( n->r ) then
972  s += astDumpInline( n->r ) + ", "
973  end if
974 
975  if( have_data ) then
976  if( right( s, 2 ) = ", " ) then
977  s = left( s, len( s ) - 2 )
978  end if
979  s += " )"
980  end if
981  end if
982 
983  reclevel -= 1
984 
985  function = s
986 end function
987 #endif
988