yberreby / rgo

[STALLED] A Go compiler, written in Rust.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Keep `Span` data for AST nodes

MovingtoMars opened this issue · comments

commented

Keeping Span data for AST nodes allows nice errors in the semantic analysis phase. It also is a step towards something like gofmt.

Perhaps something like

pub struct Spanned<T> {
    value: T,
    span: Span,
}

and then update parser like so:

fn parse_import_decl(&mut self) -> PResult<Spanned<ast::ImportDecl>> {

Or even:

pub type PResult<T> = ::std::result::Result<Spanned<T>, Error>;

Sounds like a good idea, we'll need position info, indeed. I fear the size overhead is going to be massive if we use Spanned<T> everywhere, though. The Go AST implementation uses an interface, and sometimes computes the end position on the fly based on the position of inner nodes, which could save space.

What approach did you use for ark?

commented

In Ark we use

type nodePos struct {
    pos lexer.Position
}

which gets embedded in every AST node, using Go's stuct embedding.

In rgo, Span is only 64 bits, which isn't too bad. I've got an idea for a try_parse!(val) macro that:

  1. records the start of the current token
  2. runs try!(val)
  3. records the end of the previous token
  4. returns val wrapped in Spanned<T>, using the two recorded offsets

This seems like the option that'll take the least code to support.

Another option would be, like you said, to store spans for the primitive nodes, and then to compute them for more complex nodes based on their children. This would save some memory, but require much more implementation.

64 bits are not too much, indeed. Your try_parse! macro idea looks good. 👍