Jordan Eldredge

Compiling to AST

|

While working on Relay Resolvers, and later Grats (both of which extract GraphQL schema definitions from JavaScript source code) I stumbled upon a nice technique for compiling from one high level language to another high level language. Rather than generating a text representation of target language, generate an AST of the target language and populate the AST‘s location information/spans from the source text.

With this approach you get a number of benefits. For one, generating AST node gives you assurance that you are generating syntactically correct target language code. But if you can then pass that AST directly to modules that deal in the target language, you basically get free source mapping.

For example, if the generated code results in a type error in the target language, that type error will be reported with diagnostics pointing to the relevant parts of the user’s own code in the source language! If your compiler has an editor integration, you can even get features like “click to definition” for free.

For example, Grats parses TypeScript code to generate GraphQL schema. By generating GraphQL schema AST with location information that points back to the TypeScript code, type errors appear in the correct place. Here’s an example from Grats of a GraphQL validation error (created by graphql-js) reporting errors blamed to the source TypeScript code:

Screenshot_2025-01-05_at_2.47.01_PM.png

Even things like click-to-definition “just work”. Here’s a demo video of Relay Resolvers:

https://twitter.com/captbaritone/status/1633293186876715008

Compiling to AST