What's the best way to not require forward declaration when traversing an AST [Answered]
I'm making a programming language, and I don't want to force forward declaration. I also would like to traverse the AST for analysis in a single pass (unless it is better have two passes in my case). Some ways to resolve this issue are 1. adding all undefined function calls to a list and when a function is declared check the undefined calls list. 2. When the Parser sees a function expr, hold a reference to it that will be used by the analyzer. Should I do a different implementation than these two? should I do two passes of the AST instead (if so, how will this affect speed)? How is this usually done by other languages?
6 Replies
@LPeter1997 This is what I was asking from before, (but made a lot more clear)
I'm basically asking what's the best implementation of having a language where forward declaration is not required, and the analysis phase is one pass (unless it's better to have two passes)
Analysis tends to be many many passes in pipeline based compilers (what you are building)
Some up to 20+ passes for semantic steps
It's way more valuable to separate your passes into logical steps than to save miniscule amounts by complicating logic
If you look at something like nanopass, they encourage you to define many-many tiny passes. The compiler they tested the framework with was 50+ passes
I really like this talk: https://youtu.be/Os7FE3J-U5Q
Very interesting and on-topic. đź‘Ť
@Ezlanding If you don't already, use a visitor abstraction to define your passes. I forgot to mention it but for languages like C#, your (likely) best tool for defining passes over your AST is a visitor base class that recursively traverses your entire tree. Then each pass can just override the few methods it's interested about
The visitor base is something super boring to write by hand, but it's something I actually handwrote for a toy project: https://github.com/LanguageDev/SquintLang/blob/master/Bootstrap/sqc/Ast.cs#L444
In our current compiler we generate it, because our tree is fairly complex.
Great minds think alike :)
I started implementing something just like that yesterday. I have an abstract Analysis.Pass class (inheriting from the IVisitor) that had all the visit methods, some helper methods, etc. The analysis’ analyze function now creates passes and calls run on each on them.
I’m always open to receive more info about compilers but this specific question has been answered so
âś… This post has been marked as answered!