Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dialects should built their own AST #133

Open
kjx opened this issue Nov 21, 2017 · 5 comments
Open

Dialects should built their own AST #133

kjx opened this issue Nov 21, 2017 · 5 comments

Comments

@kjx
Copy link
Contributor

kjx commented Nov 21, 2017

where should the AST used by dialect checkers come from?
what if some dialect (static type checker) need more information or methods on AST objects,
others (findbugs?) will need less information, and some (static checker?) would need a crazy amount.

my suggestion is that a dialect should be (or should offer) an AST factory (aka Object Algebra) - a suite of methods to build an AST. When a module using a checker dialect is instantiated, that factory is used to build an AST with the methods on it that that particular checker needs. Something like:

type astAlgebra = interface {
     numberLiteral( n ) at ( position )
     stringLiteral( s) at ( position )
     blockLiteral ( parameters ) over ( body ) returning ( type ) at ( position ) 
     receiver (rcvr) Request ( name) args (args)  at ( position ) 
     implicitRequest (name) args (args) at ( position ) 
}

the compiler can walk its internal AST and call out to classes in the factory.

@apblack
Copy link
Contributor

apblack commented Nov 21, 2017

We do need to do something about pinning down how dialects work in an implementation-independent manner. Thanks for opening this issue.

The problem that you identify is that dialects are quite diverse. Some need a parse tree, not an AST, because they are restricting the language and need to produce precise syntax error messages. Others need, for example, the full symbol table information, including where each identifier is declared and its type.

Your proposal seems to be suggesting that we settle on a lowest-common-denominator parse tree that is just a representation of a parse of the source, with no inferred information. That is adequate, but makes building dialects much more difficult, because all of the work done by the compiler in, e.g., resolving applied occurrences of identifiers back to their defining occurrences, and in supplying omitted selfs and outers, will have to be repeated by the dialect writer. That's an unreasonable burden.

The key issue, to me, is deciding on what information the dialect writer will be able to request from the tree. For example, can the dialect ask if a method is public, or can it only ask what annotations are available on the declaration and then have to implement the visibility rules itself? Can it ask the type of a variable application, or does it have to ask for the type annotation of the declaration, or does it have to find the declaration?

I don't see how switching from a visitor of AST nodes to a constructor of AST nodes helps us to answer these questions. Unless you are going to say: all the dialect gets is raw syntax, and the dialect writer is on her own in performing all analyses. That puts too much work on the path of writing a dialect. One of the biggest wins of Grace to me as an instructor is that writing a fairly sophisticated dialect is easy.

@kjx
Copy link
Contributor Author

kjx commented Nov 21, 2017 via email

@KimBruce
Copy link
Contributor

KimBruce commented Nov 21, 2017 via email

@kjx
Copy link
Contributor Author

kjx commented Nov 21, 2017 via email

@kjx kjx closed this as completed Feb 28, 2018
@apblack
Copy link
Contributor

apblack commented Mar 7, 2018

Thinking (because of SmallGrace) about how a compiler written in a different language world interface to a dialect written in Grace, it seems that some sort of object algebra interface is the right solution. Indeed, it may be the only solution, if by “object algebra” we mean some sort of procedural interface. There would then be a Grace module that provides, in Grace, an implementation of the AST, but dialect writers would not be required to use this, if they didn’t want or need to examine the whole AST.

For example, consider my dialect that enforces certain restrictions in method comments. It doesn’t need an AST; all it needs to do is provide empty implementations for all of the AST-building methods except for methodHeader; inside that method it performs its checks.

The second question that James was raising is what the interface to these AST-building methods should be: minimal, or maximal, or somewhere in between? It seems clear to me that we are not going to resolve that question. Since we do have multiple implementations — that’s not a question, but a fact — they are going to have different amounts of information available. The way forward, it seems to me, is to allow the compiler to provide what it has, and to provide an unavailable object otherwise. As James said, we would then have a Grace library available to the dialect writer that would compute the stuff that was unavailable, on demand.

I’m not quite sure how to implement all of this — I guess that the details will not become clear until it’s done. We would also need OA interfaces to everything that hangs from the AST, such as Symbol Tables and source-code ranges. A dialect also needs a way of raising errors.

@apblack apblack reopened this Mar 7, 2018
@gracelang gracelang deleted a comment from kjx Mar 7, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants