tonysparks / litac-lang

LitaC compiler in LitaC
7 stars 5 forks source link

Implement export name control #33

Open Wiguwbe opened 1 year ago

Wiguwbe commented 1 year ago

this allows to manually define the name of the exported symbol, using the @export("<name>") note.

As per #32

There are a few warning/errors that should be thrown, or checked in another place, let me know how you would like to proceed

Wiguwbe commented 1 year ago

As an example:

/* file: test_extern.lita */
func normal_naming() : void {
  not_this_name()
}

@extern("manual_name")
func not_this_name() : void {}

would result in

/* file: a.c */
// ...
litaC_void litaC___normal_naming() {
    manual_name();

}

litaC_void manual_name() {

}
Wiguwbe commented 1 year ago

Added an extra commit to the FileParent function

tonysparks commented 1 year ago

This is pretty cool!

I have some slight concerns, but overall I think this should be a supported feature.

1) We lose some naming conflict resolution. I think it already isn't the strongest because of foreign renaming, so this doesn't really introduce a new conflict. 2) I could see a need for more higher level control of output naming scheme, entire program level (we already have prefix) but perhaps on a per module level? Also, should consider more flexible configuration ( prefix is extremely limited).

The name of the note is interesting, I do agree export probably isn't the most appropriate (and would limit possible annotations around library exports). The extern name might be confusing as some may think this is defined else where.

How about c_name, c_gen or gen_name?

We could also (eventually) throw in additional fields on the note which could allow it to scale to module level:

public @note c_gen {
   prefix: *const char; // uses a custom prefix if 'name' is empty
   name: *const char; // if populated, just use 'name', will ignore the prefix field
}
tonysparks commented 1 year ago

We'll need some test cases as well. I can add them if you'd like, otherwise something like:

test/tests/export_note.json

{
    "description": "Custom C output naming",
    "disabled": false,
    "program": `
        @include("assert.h");
        @foreign func assert(e:bool):void;

        %definitions%

        func main(len:i32, args:**char):i32 {
            %code%
        }
    `,
    "tests": [

        {
            "name": "Custom C Output Name for Struct",
            "definitions": `
                @export("Bar")
                struct Foo {
                    v: i32
                }
                // this type should exist because of the Foo lita type
                // being renamed to Bar
                @foreign("Bar")
                struct Test {
                   v: i32
                }

            `,
            "code": `
                var foo = Foo{
                    .v = 4
                }
                var bar = Test{
                    .v = 8
                }
                assert(foo.v == 4)
                assert(bar.v == 8)
            `,
        },
    ]
}
Wiguwbe commented 1 year ago
2. I could see a need for more higher level control of output naming scheme, entire program level (we already have `prefix`) but perhaps on a per module level?  Also, should consider more flexible configuration ( `prefix` is extremely limited).

One possibility there would be to give a printf-like string, giving the user the constants e.g. MODULE and NAME (type name), having the string something like "ext_{MODULE}_{NAME}", although, that could give too much control :)

How about c_name, c_gen or gen_name?

I think c_name would be more verbose and objective (comparing to extern)

Wiguwbe commented 1 year ago

To add, thinking already about the future and the mentioned integration with C (projects), I was also thinking of the possibility of generating a C header file along with the C source file, mainly with either the @extern-ed names or with an extra @to_header or something note.

Should this work be considered in the future, I would suggest that the name replacement for extern could mean both the C name and to tell the compiler to include it in the hypothetical header file, to avoid writing 2 notes per type/function

Edit: I noticed that the c output "includes" a C header that can be extracted later