From 386ed4b75026f1262818ae5631eb593e694f2185 Mon Sep 17 00:00:00 2001 From: "Nahuel J. Sacchetti" Date: Wed, 16 Oct 2024 14:15:53 -0500 Subject: [PATCH] feat: add namespacing for foreign and unit tests for C interoperability --- compiler/codegen.go | 15 ++++++++++----- compiler/frontend.go | 14 +++++++++++++- libs/libc.sk | 8 +++++--- tests/c-printf.sk | 6 ++++++ tests/c-printf.txt | 1 + 5 files changed, 35 insertions(+), 9 deletions(-) create mode 100644 tests/c-printf.sk create mode 100644 tests/c-printf.txt diff --git a/compiler/codegen.go b/compiler/codegen.go index 9fd075d..4110ed5 100644 --- a/compiler/codegen.go +++ b/compiler/codegen.go @@ -58,7 +58,7 @@ func generateLinuxX64() { out.WriteMetadata("public main") for _, f := range TheProgram.chunks { if f.foreign { - out.WriteMetadata("extrn %s", f.word) + out.WriteMetadata("extrn %s", f.name) } } out.WriteCode("section '.text' executable") @@ -307,7 +307,7 @@ func generateLinuxX64() { out.WriteCode(" pop %s", registers[i]) } - out.WriteCode(" call %s", function.word) + out.WriteCode(" call %s", function.name) if hasResults { out.WriteCode(" push rax") @@ -367,9 +367,14 @@ func generateLinuxX64() { out.WriteCode(" mov rax, return_stack_rsp_end") out.WriteCode(" mov [return_stack_rsp], rax") out.WriteCode(" call fn%d", mainFuncIP) - out.WriteCode(" mov rax, 60") - out.WriteCode(" mov rdi, 0") - out.WriteCode(" syscall") + if TheProgram.libcEnabled { + out.WriteCode(" mov rdi, 0") + out.WriteCode(" call exit") + } else { + out.WriteCode(" mov rax, 60") + out.WriteCode(" mov rdi, 0") + out.WriteCode(" syscall") + } } func CodegenRun(out *OutputCode) { diff --git a/compiler/frontend.go b/compiler/frontend.go index c2e2bee..14f10bf 100644 --- a/compiler/frontend.go +++ b/compiler/frontend.go @@ -22,6 +22,8 @@ const ( type Function struct { ip int loc Location + name string + namespace string token Token word string @@ -373,6 +375,14 @@ func createConstant() { func createForeigns() { t := parser.previousToken + if !match(TOKEN_WORD) { + t := parser.previousToken + ReportErrorAtLocation(DeclarationWordMissing, t.loc) + ExitWithError(ParseError) + } + + namespace := parser.previousToken.value.(string) + consume(TOKEN_CURLY_BRACKET_OPEN, UnexpectedSymbol, parser.previousToken.kind, "{") @@ -392,7 +402,9 @@ func createForeigns() { advance() tokenWord := parser.previousToken - function.word = tokenWord.value.(string) + function.namespace = namespace + function.name = tokenWord.value.(string) + function.word = function.namespace + "." + function.name consume(TOKEN_PAREN_OPEN, UnexpectedSymbol, t.kind, "(") parsingArguments := true diff --git a/libs/libc.sk b/libs/libc.sk index 7207dc0..03729c7 100644 --- a/libs/libc.sk +++ b/libs/libc.sk @@ -34,7 +34,9 @@ ; all the C required procedures, making compilation slower and final file ; size bigger. 'libc' is linked statically. -foreign { - fn printf (any str) ... - fn puts (str) ... +foreign c { + fn exit (int) ... + fn fprintf (int any str) ... + fn printf (any str) ... + fn puts (str) ... } diff --git a/tests/c-printf.sk b/tests/c-printf.sk new file mode 100644 index 0000000..3e26439 --- /dev/null +++ b/tests/c-printf.sk @@ -0,0 +1,6 @@ +using libc +using unix + +fn main () + "Stańczyk" "Hello, %s\n" c.printf +ret diff --git a/tests/c-printf.txt b/tests/c-printf.txt new file mode 100644 index 0000000..18c53b6 --- /dev/null +++ b/tests/c-printf.txt @@ -0,0 +1 @@ +Hello, Stańczyk