gotosocial/vendor/modernc.org/ccgo/v3/lib/design-notes.adoc
tobi ebdee5aed8
[chore] Downgrade sqlite v1.29.2 -> v1.28.0 (#2736)
* [chore] Downgrade sqlite v1.29.2 -> v1.29.0

* go down to v1.28.0
2024-03-08 11:45:15 +01:00

2.8 KiB
Raw Blame History

Design Notes

Problems:

Translating C to Go is harder than it looks.

Jan says: Its impossible in the general case to turn C char* into Go []byte. Its possible to do it probably often for concrete C code cases - based also on authors C coding style. The first problem this runs into is that Go does not guarantee that the backing array will keep its address stable due to Go movable stacks. C expects the opposite, a pointer never magically modifies itself, so some code will fail.

INSERT CODE EXAMPLES ILLUSTRATING THE PROBLEM HERE

How the parser works

There are no comment nodes in the C AST. Instead every cc.Token has a Sep field: https://godoc.org/modernc.org/cc/v3#Token

It captures, when configured to do so, all white space preceding the token, combined, including comments, if any. So we have all white space/comments information for every token in the AST. A final white space/comment, preceding EOF, is available as field TrailingSeperator in the AST: https://godoc.org/modernc.org/cc/v3#AST.

To get the lexically first white space/comment for any node, use tokenSeparator(): https://gitlab.com/cznic/ccgo/-/blob/6551e2544a758fdc265c8fac71fb2587fb3e1042/v3/go.go#L1476

Looking forward

Eric says: In my visualization of how the translator would work, the output of a ccgo translation of a module at any given time is a file of pseudo-Go code in which some sections may be enclosed by a Unicode bracketing character (presently using the guillemot quotes U+ab and U+bb) meaning "this is not Go yet" that intentionally makes the Go compiler barf. This expresses a color on the AST nodes.

So, for example, if Im translating hello.c with a ruleset that does not include print → fmt.Printf, this:

#include <stdio>

/* an example comment */

int main(int argc, char *argv[])
{
    printf("Hello, World")
}

becomes this without any explicit rules at all:

«#include <stdio>»

/* an example comment */

func main
{
	«printf(»"Hello, World"!\n"«)»
}

Then, when the rule print → fmt.Printf is added, it becomes

import (
        "fmt"
)

/* an example comment */

func main
{
	fmt.Printf("Hello, World"!\n")
}

because with that rule the AST node corresponding to the printf call can be translated and colored "Go". This implies an import of fmt. We observe that there are no longer C-colored spans and drop the #includes.