1 // Abstract syntax trees
21 mkAst(AstOp op
, CfgSym
*sym
)
29 astfreed
= (Ast
*)a
->right
;
37 ma
= emallocnz(nma
*sizeof *a
);
55 a
->parent
= NoParentYet
;
56 a
->attrmap
.root
= nil
;
67 if(a
== nil
|| a
->ref
== Leaked
|| --a
->ref
> 0)
71 for(i
=0; i
<a
->nright
; i
++)
75 a
->right
= (void*)astfreed
;
82 // Swap the AST's data but not their ref counts or tree position.
84 astswap(Ast
*a
, Ast
*b
)
95 b
->parent
= a
->parent
;
102 if(a
&& a
->ref
!= Leaked
)
112 if(ast
== nil
|| ast
->ref
== Leaked
)
116 for(i
=0; i
<ast
->nright
; i
++)
117 astleak(ast
->right
[i
]);
123 astrefcheck(Ast
*ast
, int pass
)
132 if(ast
->refcheck
++ == 0)
133 for(i
=0; i
<ast
->nright
; i
++)
134 astrefcheck(ast
->right
[i
], pass
);
137 if(ast
->refcheck
!= -1){
138 if(ast
->ref
< ast
->refcheck
){
139 fprint(2, "%d < %d | %s | %#A\n", ast
->ref
, ast
->refcheck
, ast
->sym
->name
, ast
);
142 for(i
=0; i
<ast
->nright
; i
++)
143 astrefcheck(ast
->right
[i
], pass
);
152 mkaststring(CfgSym
*sym
, Name name
)
156 a
= mkAst(AstString
, sym
);
158 a
->tag
= typegramsym(typegram1(sym
->ggram
->name
, nil
), sym
->name
, nil
);
159 assert(a
->tag
->sym
== sym
);
164 mkastmerge(Ast
*a
, Ast
*b
)
170 if(a
->op
== AstMerge
)
174 if(b
->op
== AstMerge
)
179 m
= mkAst(AstMerge
, a
->sym
);
180 m
->right
= emalloc(n
*sizeof m
->right
[0]);
183 if(a
->op
== AstMerge
)
184 for(i
=0; i
<a
->nright
; i
++)
185 m
->right
[n
++] = astdup(a
->right
[i
]);
187 m
->right
[n
++] = astdup(a
);
188 if(b
->op
== AstMerge
)
189 for(i
=0; i
<b
->nright
; i
++)
190 m
->right
[n
++] = astdup(b
->right
[i
]);
192 m
->right
[n
++] = astdup(b
);
193 assert(n
== m
->nright
);
194 if(typemax(a
->tag
, b
->tag
, &m
->tag
) < 0)
195 panic("typemax %T %T in mkastmerge", a
->tag
, b
->tag
);
196 assert(m
->tag
->sym
== m
->sym
);
197 m
->line
= m
->right
[0]->line
;
202 mkastmerge1(Ast
**right
, int nright
)
209 panic("mkastmerge %d", nright
);
214 m
= mkAst(AstMerge
, right
[0]->sym
);
218 for(i
=1; i
<nright
; i
++){
219 if(typemax(t
, right
[i
]->tag
, &t
) < 0)
220 panic("typemax %T %T in mkastmerge1", t
, right
[i
]->tag
);
223 assert(m
->tag
->sym
= m
->sym
);
224 m
->line
= m
->right
[0]->line
;
229 mkastrule(CfgRule
*r
, Ast
**right
)
235 a
= mkAst(AstRule
, r
->left
);
238 a
->nright
= r
->nsavedright
;
239 for(i
=j
=0; i
<a
->nright
; i
++, j
++){
240 while(nametostr(r
->right
[j
]->name
)[0] == '"')
242 // assert(right[i]->sym == r->right[j]);
246 panic("nil r->tgram in mkastrule %s", r
->name
);
247 for(i
=0; i
<a
->nright
; i
++){
248 if(typemax(t
, right
[i
]->tag
, &tt
) < 0)
249 panic("typemax %T %T in mkastrule", t
, right
[i
]->tag
);
253 for(i
=0; i
<a
->nright
; i
++){
254 if(right
[i
]->line
.file
){
255 a
->line
= right
[i
]->line
;
259 a
->tag
= typegramsym(t
, r
->left
->name
, nil
);
260 assert(a
->tag
->sym
== a
->sym
);
265 mkastslot(Type
*t
, CfgSym
*sym
, int slotnum
)
269 a
= mkAst(AstSlot
, sym
);
270 a
->slotnum
= slotnum
;
271 a
->tag
= typegramsym(t
, sym
->name
, sym
);
272 assert(a
->tag
->sym
== a
->sym
);
277 //============================================================
280 static void astfmtsexpr(Fmt
*, Ast
*, int, int);
281 static void astfmttext(Fmt
*, Ast
*);
283 // %A - format Ast as infix string (leaves separated by spaces)
284 // %#A - format Ast as one-line S-expression.
285 // %#lA - format Ast as multi-line S-expression.
291 ast
= va_arg(fmt
->args
, Ast
*);
293 fmtprint(fmt
, "<nil ast>");
294 else if(fmt
->flags
&FmtSharp
)
295 astfmtsexpr(fmt
, ast
, fmt
->flags
&FmtLong
, 0);
297 astfmttext(fmt
, ast
);
313 for(i
= 0; i
< m
; i
++)
321 astfmtsexpr(Fmt
*fmt
, Ast
*ast
, int newlines
, int indent
)
327 fmtprint(fmt
, " ?slot.%s", ast
->sym
->name
);
330 fmtprint(fmt
, " '%s", ast
->text
);
333 fmtprint(fmt
, " (%s.merge", ast
->sym
->name
);
336 fmtprint(fmt
, " (%R", ast
->rule
);
338 for(i
=0; i
<ast
->nright
; i
++){
340 fmtprint(fmt
, "\n%.*s", indent
*2, dots(indent
*2));
341 astfmtsexpr(fmt
, ast
->right
[i
], newlines
, indent
+1);
349 astfmttext(Fmt
*fmt
, Ast
*ast
)
357 fmtprint(fmt
, "\\%d ", ast
->slotnum
);
360 fmtprint(fmt
, "%s ", ast
->text
);
364 for(i
=0; i
<ast
->rule
->nright
; i
++){
365 sym
= ast
->rule
->right
[i
];
366 s
= nametostr(sym
->name
);
368 fmtprint(fmt
, "%.*s ", utfnlen(s
+1, strlen(s
+1)-1), s
+1);
370 astfmttext(fmt
, ast
->right
[j
++]);
372 assert(j
== ast
->nright
);
375 fmtprint(fmt
, "{M: %A}", ast
->right
[0]);
380 //============================================================
382 // Must use astright, not ast->right, to preserve parent pointers.
385 astparent(Ast
*ast
, Type
*t
)
387 if(ast
->parent
== NoParentYet
)
389 for(ast
=ast
->parent
; ast
; ast
=ast
->parent
){
390 if(t
== nil
|| issubtype(ast
->tag
, t
))
392 if(ast
->parent
== NoParentYet
)
399 astprev_attr(Ast
*ast
)
404 p
= astparent(ast
, nil
);
407 for(i
=0; i
<p
->nright
; i
++){
408 if(p
->right
[i
] == ast
){
410 if(!p
->right
[i
]->sym
->nocopy
)
411 return astright(p
, i
);
415 fprint(2, "cannot find self in parent!");
421 astnext_attr(Ast
*ast
)
426 p
= astparent(ast
, nil
);
429 for(i
=0; i
<p
->nright
; i
++){
430 if(p
->right
[i
] == ast
){
431 for(i
++; i
<p
->nright
; i
++)
432 if(!p
->right
[i
]->sym
->nocopy
)
433 return astright(p
, i
);
437 fprint(2, "cannot find self in parent!");
443 astcopiedfrom_attr(Ast
*ast
)
445 if(ast
== nil
|| ast
->copiedfrom
== nil
)
447 return ast
->copiedfrom
;
451 astcvtslot(Ast
*ast
, Type
*t
)
455 if(ast
->op
!= AstSlot
)
457 a
= mkastslot(t
, t
->sym
, ast
->slotnum
);
462 astright(Ast
*ast
, int i
)
466 assert(i
>= 0 && i
< ast
->nright
);
472 if(a
->parent
== NoParentYet
){
476 ast
->right
[i
] = a
= astcopy(a
);
482 asttoquestion(Ast
*ast
, CfgSym
*sym
)
489 assert(sym
->nrule
== 2);
490 assert(sym
->rule
[0]->nright
== 0);
491 assert(sym
->rule
[1]->nright
== 1);
492 assert(sym
->rule
[1]->nsavedright
== 1);
495 return mkastrule(sym
->rule
[0], nil
);
497 assert(ast
->sym
== sym
->rule
[1]->right
[0]);
498 right
= emalloc(1*sizeof right
[0]);
500 return mkastrule(sym
->rule
[1], right
);
504 astfromquestion(Ast
*ast
, CfgSym
*sym
)
509 assert(sym
->nrule
== 2);
510 assert(sym
->rule
[0]->nright
== 0);
511 assert(sym
->rule
[1]->nright
== 1);
512 assert(sym
->rule
[1]->nsavedright
== 1);
514 assert(ast
->sym
== sym
);
518 return astright(ast
, 0);
522 astlisttostar(Zlist
*zl
, CfgSym
*sym
)
529 assert(sym
->nrule
== 2);
530 assert(sym
->rule
[0]->nright
== 0);
531 assert(sym
->rule
[1]->nright
== 1);
532 assert(sym
->rule
[1]->nsavedright
== 1);
535 return mkastrule(sym
->rule
[0], nil
);
537 right
= emalloc(1*sizeof right
[0]);
538 right
[0] = astlisttoplus(zl
, sym
->rule
[1]->right
[0]);
541 return mkastrule(sym
->rule
[1], right
);
545 aststartolist(Ast
*ast
, CfgSym
*sym
, Zlist
**l
)
550 assert(sym
->nrule
== 2);
551 assert(sym
->rule
[0]->nright
== 0);
552 assert(sym
->rule
[1]->nright
== 1);
553 assert(sym
->rule
[1]->nsavedright
== 1);
555 assert(ast
->sym
== sym
);
557 if(ast
->op
== AstSlot
)
560 if(ast
->nright
== 0){
564 return astplustolist(astright(ast
, 0), sym
->rule
[1]->right
[0], l
);
568 _astlisttoplus(Zlist
*zl
, CfgSym
*sym
)
573 // name+: name+ sep name
575 assert(sym
->nrule
== 2);
576 assert(sym
->rule
[0]->nright
== 1);
577 assert(sym
->rule
[1]->nright
== 2 || sym
->rule
[1]->nright
== 3);
578 assert(sym
->rule
[1]->nsavedright
== 2);
580 assert(sym
->rule
[1]->right
[0] == sym
);
582 assert(sym
->rule
[1]->right
[sym
->rule
[1]->nright
-1] == sym
);
585 fprint(2, "convert nil list to %s", sym
->name
);
590 assert(((Ast
*)zl
->hd
)->sym
== sym
->rule
[0]->right
[0]);
593 right
= emalloc(1*sizeof right
[0]);
595 return mkastrule(sym
->rule
[0], right
);
598 right
= emalloc(2*sizeof right
[0]);
600 right
[0] = _astlisttoplus(zl
->tl
, sym
);
604 right
[1] = _astlisttoplus(zl
->tl
, sym
);
606 return mkastrule(sym
->rule
[1], right
);
610 astlisttoplus(Zlist
*zl
, CfgSym
*sym
)
614 return _astlisttoplus(zl
, sym
);
618 astplustolist(Ast
*ast
, CfgSym
*sym
, Zlist
**l
)
623 // name+: name+ sep name
625 assert(sym
->nrule
== 2);
626 assert(sym
->rule
[0]->nright
== 1);
627 assert(sym
->rule
[1]->nright
== 2 || sym
->rule
[1]->nright
== 3);
628 assert(sym
->rule
[1]->nsavedright
== 2);
630 assert(sym
->rule
[1]->right
[0] == sym
);
632 assert(sym
->rule
[1]->right
[sym
->rule
[1]->nright
-1] == sym
);
633 assert(ast
->sym
== sym
);
637 assert(ast
->sym
== sym
);
638 if(ast
->op
== AstSlot
)
642 panic("astplustolist");
644 ast
= astright(ast
, 0);
645 zl
= mkZlist(ast
, zl
);
650 last
= astright(ast
, ast
->nright
-1);
651 prefix
= astright(ast
, 0);
652 zl
= mkZlist(last
, zl
);
656 first
= astright(ast
, 0);
657 suffix
= astright(ast
, ast
->nright
-1);
658 zl
= mkZlist(first
, zl
);
679 s
= nametostr(ast
->sym
->name
);
680 switch(s
[strlen(s
)-1]){
682 if(aststartolist(ast
, ast
->sym
, &l
) < 0)
686 if(astplustolist(ast
, ast
->sym
, &l
) < 0)
701 for(i
=0; i
<ast
->nright
; i
++)
702 if(!ast
->right
[i
]->sym
->nocopy
)
706 for(i
=0; i
<ast
->nright
; i
++)
707 if(!ast
->right
[i
]->sym
->nocopy
)
708 za
->a
[n
++] = astright(ast
, i
);
714 astjoin(Ast
*ast
, Zarray
*za
)
720 right
= emalloc(ast
->nright
*sizeof right
[0]);
722 for(i
=0; i
<ast
->nright
; i
++){
723 if(ast
->right
[i
]->sym
->nocopy
)
724 right
[i
] = ast
->right
[i
];
726 right
[i
] = za
->a
[n
++];
730 if(ast
->op
== AstMerge
)
731 a
= mkastmerge1(right
, za
->n
);
732 else if(ast
->op
== AstRule
){
734 for(i
=0; i
<ast
->rule
->nright
; i
++){
735 if(nametostr(ast
->rule
->right
[i
]->name
)[0] == '"')
737 if(right
[n
]->sym
!= ast
->rule
->right
[i
]){
738 fprint(2, "bad right %d / %R: %s %s\n", i
, ast
->rule
, right
[i
]->sym
->name
, ast
->rule
->right
[i
]->name
);
739 assert(right
[n
]->sym
== ast
->rule
->right
[i
]);
743 assert(n
== ast
->nright
);
744 a
= mkastrule(ast
->rule
, right
);
747 panic("astjoin: %#A\n", ast
);
752 a
->copiedfrom
= ast
; // XXX is this correct?
765 if(sys_astchatty
> 0)
766 fprint(2, "astcopy: %s\n", ast
->sym
->name
);
767 a
= mkAst(ast
->op
, ast
->sym
);
768 a
->slotnum
= ast
->slotnum
;
773 a
->right
= emalloc(ast
->nright
*sizeof a
->right
[0]);
774 for(i
=0; i
<ast
->nright
; i
++)
775 a
->right
[i
] = astdup(ast
->right
[i
]);
776 a
->nright
= ast
->nright
;
780 //fprint(2, "astcopy: %p/%p -> %p\n", ast, ast->parent, a);
791 for(i
=ast
->nright
-1; i
>=0; i
--)
792 if(!ast
->right
[i
]->sym
->nocopy
)
793 return astright(ast
, i
);
800 return ast
&& ast
->op
== AstMerge
;
806 return ast
&& ast
->op
== AstSlot
;
810 asttostring(Ast
*ast
)
817 s
= smprint("%A", ast
);
822 while(e
> t
&& e
[-1] == ' ')
837 return nameof("(nil)");
838 s
= smprint("%#A", ast
);
843 while(e
> t
&& e
[-1] == ' ')
858 return nameof("(nil)");
859 s
= smprint("%#lA", ast
);
864 while(e
> t
&& e
[-1] == ' ')
877 attrinfocmp(const void *va
, const void *vb
)
883 return b
->ncompute
- a
->ncompute
;
887 regattr(AttrInfo
*info
)
891 attrinfo
= erealloc(attrinfo
, (nattrinfo
+1)*sizeof attrinfo
[0]);
892 attrinfo
[nattrinfo
++] = info
;
893 info
->registered
= 1;
902 qsort(attrinfo
, nattrinfo
, sizeof attrinfo
[0], attrinfocmp
);
903 for(i
=0; i
<nattrinfo
; i
++){
905 print("%10d %s %T\n", info
->ncompute
, info
->name
, info
->type
);
910 get_attribute(Ast
*ast
, AttrInfo
*info
)
917 fprint(2, "%s called on nil\n", info
->name
);
919 // XXX maybe return 0?
921 if(!info
->registered
)
923 if((a
= mapget(&ast
->attrmap
, info
)) == nil
){
926 ma
= emallocnz(nma
*sizeof ma
[0]);
932 mapputelem(&ast
->attrmap
, info
, a
, &a
->me
);
938 set_attribute(Ast
*ast
, AttrInfo
*info
, Zpoly data
)
942 a
= get_attribute(ast
, info
);
943 if(a
->state
== AttrComputing
)
944 fprint(2, "warning: changing attribute %s during its computation\n",
946 else if(a
->state
== AttrInit
){
947 fprint(2, "warning: changing attribute %s after its computation\n",
956 attrloop(AttrInfo
*info
)
960 fprint(2, "attribute loop:\n");
961 fprint(2, "\t%s: %s\n", info
->pos
, info
->name
);
962 for(l
=attrlinks
; l
; l
=l
->next
)
963 fprint(2, "\t%s: %s : %T\n", l
->info
->pos
, l
->info
->name
, l
->ast
->tag
);
972 p
= emalloc(2*sizeof p
[0]);
973 p
[0] = ast
->line
.file
;
974 p
[1] = (Zpoly
)ast
->line
.line
;
979 astcanonicalize(Ast
*ast
)
982 Ast
**right
, **oldright
;
987 return ast
->canonical
;
989 if(ast
->op
== AstSlot
)
992 right
= emalloc(ast
->nright
*sizeof ast
->right
[0]);
994 for(i
=0; i
<ast
->nright
; i
++){
995 right
[i
] = astcanonicalize(ast
->right
[i
]);
996 if(right
[i
] != ast
->right
[i
])
1001 // Have to make a new AST to pass to the canonicalize function.
1002 // Easier to reuse astcopy, temporarily editing ast.
1003 oldright
= ast
->right
;
1006 ast
->right
= oldright
;
1010 if(ast
->sym
!= ast
->tag
->sym
)
1011 fprint(2, "oops: %s vs %s\n", ast
->sym
->name
, ast
->tag
->sym
->name
);
1013 assert(ast
->sym
== ast
->tag
->sym
);
1014 if(ast
->op
== AstRule
){
1015 f
= ast
->sym
->canonical
;
1016 ast
->sym
->used_canonical
= 1;
1017 //extern Zfn nop_canonical;
1018 // if(f == &nop_canonical)
1019 // fprint(2, "no canonical for %T\n", ast->tag);
1021 // fprint(2, "canonical for %T\n", ast->tag);
1023 c
= ((Ast
*(*)(void*, Ast
*))f
->fn
)(f
->escf
, astleak(a
));
1026 fprint(2, "astcanonicalize(%T) returned nil for %A\n",
1040 astsame(Ast
*a
, Ast
*b
)
1044 if(a
== nil
&& b
== nil
)
1046 if(a
== nil
|| b
== nil
)
1050 || a
->rule
!= b
->rule
1051 || a
->text
!= b
->text
)
1053 for(i
=0; i
<a
->nright
; i
++)
1054 if(!astsame(a
->right
[i
], b
->right
[i
]))
1060 astremovecopiedfrom(Ast
*ast
)
1064 ast
->copiedfrom
= nil
;
1065 ast
->parent
= NoParentYet
;
1066 for(i
=0; i
<ast
->nright
; i
++)
1067 astremovecopiedfrom(ast
->right
[i
]);