c3lang / c3c

Compiler for the C3 language
GNU Lesser General Public License v3.0
1.34k stars 80 forks source link

Better error information for macros #1198

Closed cbuttner closed 2 weeks ago

cbuttner commented 1 month ago
module test;
import std::io;

macro macro_2(str) {
  int a = str;
}

macro macro_1(str) {
  macro_2(str);
}

fn int main(String[] args) {
  macro_1("Test");
  return 0;
}

Emits

 2: import std::io;
 3: 
 4: macro macro_2(str) {
 5:   int a = str;
              ^^^
(/tmp/test/src/main.c3:5:11) Error: You cannot cast 'String' to 'int'.

But there is no information on where this macro was invoked from.

The error should trace all the way back to the origin. Kind of like so:

 2: import std::io;
 3: 
 4: macro macro_2(str) {
 5:   int a = str;
              ^^^
(/tmp/test/src/main.c3:5:11) Error: You cannot cast 'String' to 'int'.

 6: }
 7:
 8: macro macro_1(str) {
 9:   macro_2(str);
      ^^^^^^^
(/tmp/test/src/main.c3:9:3) Note: Invoked from here.

 10: }
 11:
 12: fn int main(String[] args) {
 13:  macro_1("Test");
      ^^^^^^^
(/tmp/test/src/main.c3:13:3) Note: Invoked from here.
lerno commented 1 month ago

I've changed this in dev, please have a try.

cbuttner commented 3 weeks ago

Works great, thank you.

cbuttner commented 3 weeks ago

Any chance this could also be improved?

module test;
import std::io;

macro @macro_2(#x) {
  int a = #x;
}

macro @macro_1(#x) {
  @macro_2(#x);
}

fn int main(String[] args) {
  @macro_1(TEST);
  return 0;
}
 2: import std::io;
 3: 
 4: macro @macro_2(#x) {
 5:   int a = #x;
              ^^
(/tmp/test/src/main.c3:5:11) Error: 'TEST' could not be found, did you spell it right?
lerno commented 3 weeks ago

Tracing was missing a bit, try it now.

cbuttner commented 2 weeks ago

Better, but I found another case:

module test;
import std::io;

macro void @macro_2(x) {
  int a = x;
}

macro void @macro_1(#x) {
  @macro_2(#x);
}

fn int main(String[] args) {
  @macro_1(TEST);
  return 0;
}
 6: }
 7: 
 8: macro void @macro_1(#x) {
 9:   @macro_2(#x);
               ^^
(/tmp/test/src/main.c3:9:12) Error: 'TEST' could not be found, did you spell it right?
lerno commented 2 weeks ago

Heh, fixed one side of the if, but not the other... Try it again @cbuttner

cbuttner commented 2 weeks ago

That case is fixed, but here's one more:

module test;

struct Foo {
  bool a;
  int b;
}

fn int main(String[] args) {
  mem::new(Foo, {
    .test = 1,
  });
  return 0;
}
 555: 
 556: /**
 557:  * @require $vacount < 2 : "Too many arguments."
 558:  * @require $or($vacount == 0, $assignable($vaexpr(0), $Type)) : "The second argument must be an initializer for |
                                                 ^^^^^^^^^^
(/home/christian/Github/c3c/lib/std/core/mem.c3:558:44) Error: This is not a valid member of 'Foo'.
lerno commented 2 weeks ago

Thanks! Fixed now @cbuttner

cbuttner commented 2 weeks ago

Cool, I'll let you know if I stumble across another case.