c3lang / c3c

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

Hello world unable to find io.c3 #93

Closed apg360 closed 3 years ago

apg360 commented 3 years ago

Hi,

Need assistance for a test hello world file.

MacOS 10.15.7 Step1 : download pre-built binaries clang+llvm-9.0.1-x86_64-apple-darwin.tar.xz and extract Step2 : export LLVM_DIR= Step3 : mkdir build; cd build; cmake ../; make

Step 4 : create new hello_world.c3 and add this :

module hello_world;
import std::io;
func void main()
{
   io::printf("Hello, world!\n");
}

Step 5 : ./c3c compile hello_world.c3 Error :

a0@GRgr build % ./c3c compile hello_world.c3
-- DEBUG: Version: 102
-- DEBUG: Target set to x86_64-apple-darwin19.6.0.
-- DEBUG: CONTEXT: Setting module to 'hello_world'.
-- DEBUG: Creating module hello_world.
-- DEBUG: SEMA: Add import of 'std::io'.
-- DEBUG: Added import std::io
-- DEBUG: Finished parsing function main
-- DEBUG: Pass: Importing dependencies for hello_world.c3
-- DEBUG: - Import of std::io.
1: module hello_world;
2: import std::io;
          ^^^^^^^
(hello_world.c3:2) Error: No module named 'std::io' could be found.

-- DEBUG: Pass finished with 1 error(s).
a0@GRgr build %

Why is c3c unable to find lib folder which is at build folder

a0@GRgr build % ls lib/std 
builtin.c3  cinterop.c3 io.c3
a0@GRgr build % 
a0@GRgr build % cat lib/std/io.c3 
module std::io;
.......

Please help

lerno commented 3 years ago

The reason for this is that the libs are still not completely integrated. It would break the environment at https://judge0.com at the moment. So instead of doing that, when you want printf, simply use the C version by declaring it inline and then link with libc.

extern func int printf(char *format, ...);

func int main()
{
    printf("Hello, world\n");
    return 1;
}

Compile, then link and run:

> ld -lSystem hello_world.o
> ./a.out

Apologies for the sorry state of this at the moment.

apg360 commented 3 years ago

No issue, much appreciate the fast reply. All worked fine 100%

Two question please : 1) does this means that I cannot use modules like c2c ?

2) if I am not mistaken clang and gcc does that ld automatically and give executable directly. Any reason why c3c I need to link (ld) manually as extra step ?

Kinds regards,

lerno commented 3 years ago
  1. Modules should still work fine, but the "build" command is not complete, so basically today you need to include all the files you're using for the program directly on the command line. Then between these files, the module declaration will regulate visibility and so on. So let's say you have a file foo.c3 of module foo and a bar_1.c3 and bar_2.c3 of module bar. You compile all of them using: c3c compile foo.c3 bar_1.c3 bar_2.c3.

In this case trying to access a function in bar_1.c3 or bar_2.c3 from foo.c3 would require an import in foo and that the function (or struct etc) is public. Between bar_1.c3 and bar_2.c3 the only thing that is hidden are functions and types marked local as they are local to that particular file if that makes sense?

With the build system later you specify include paths for source files, and there will also be a special format for libraries where you can put library packages (big TODO on that latter feature), but the standard library should be available before that. However I had to postpone work on that + I wanted more language features to work better.

  1. Clang and GCC both allows you to invoke the linker directly. Since ld is part of Clang/GCC rather than c3c there are two options: (1) search for a linker (2) run the linker inside of llvm. (2) is what I prefer, but there is currently C API for it. So I have delayed doing this a little bit.
apg360 commented 3 years ago

Perfectly valid reason, it does makes sens.

So it is operational and working 100%, just would need to do manually what IDE usually does auto like listing every source file for compile. You are right we need priority on the language features.

Very well done Sir. I will try to find my way on setting up a usable project template and document that so it can help others too. It can be used as it is right now, just need to know what to do manually and how.

I feel so excited to start a journey with a language that support C files out of the box no wrapper, add any existing library and then programming with c3c modern feature. AWESOME

Again thank you for availability and valuable assistance.

lerno commented 3 years ago

Later the build system should be enough, but I don't remember the state of that code as it doesn't have any test cases yet. One more thing to add.

Note that the project is still very much in progress. It's absolutely not ready for any real world work yet. On the other hand, people trying it out will help me know how I should prioritize things, so I'm grateful for feedback from people who try to set it up to play with it and so on.

apg360 commented 3 years ago
1. Modules should still work fine, but the "build" command is not complete, so basically today you need to include all the files you're using for the program directly on the command line. Then between these files, the module declaration will regulate visibility and so on. So let's say you have a file `foo.c3` of module `foo` and a `bar_1.c3` and `bar_2.c3` of module bar. You compile all of them using: `c3c compile foo.c3 bar_1.c3 bar_2.c3`.

I am experimenting a bit ..... Trying to achieve c3c compile foo.c3 bar_1.c3 bar_2.c3

hello_world.c3

module hello_world;
import mylib;
func int main()
{
   mylib::printf("Hello, world!\n");
   return 1;
}

mylib.c3

module mylib;

extern func int printf(char *format, ...);

./c3c compile mylib.c3 hello_world.c3

-- DEBUG: Now resolving printf
 2: import mylib;
 3: func int main()
 4: {
 5:    mylib::printf("Hello, world!\n");
              ^^^^^^
(hello_world.c3:5) Error: Identifier 'printf' could not be found.

-- DEBUG: Pass finished with 1 error(s).
[manj20@manjaro build]$

I thought that giving multiple file manually at command line was enough. What am I doing wrong please ?

lerno commented 3 years ago

The "extern" can be thought of as a special kind of import. It's not part of the module exported functions, so you have to write your own printf that calls the "extern" printf. Unfortunately the va_* calls are not available yet, so it's hard to do so well right now. What you could do is perhaps this:

module mylib;

extern func void printf(char *text, ...);
public func void my_printf(char *text)
{
  printf(text);
}

An alternative would be making a macro, but I haven't done the vararg macros yet. Because in that case it would be possible to do this:

extern func void printf(char *text, ...);
macro printf(text, ...)
{
   printf(text, ...);
}

And used like:

@mylib::printf("foo: %d\n", foo);
lerno commented 3 years ago

There is another consideration: because the C varargs are a bit difficult to use, it might be that that the libc printf needs to be replaced by a C3 printf, and that one could actually use type safe-varargs instead.

So what you could do is to start with libc's putchar and write your own print function to begin with. If having the type safe vararg is important I could prioritize adding that. It would be something like:

func void foo(int a, double b, int... varargs) { ... }

Where the type of varargs will be a subarray (e.g. int[]). When / if the "any type" is available this could create a completely safe printf. (printf(string format, AnyType... args)), similar to how it works in Odin.

apg360 commented 3 years ago

Thank you, all clear.