diff --git a/compiler/Generator.cs b/compiler/Generator.cs index 105e1d8..7bcb8f4 100644 --- a/compiler/Generator.cs +++ b/compiler/Generator.cs @@ -21,9 +21,9 @@ public class Generator private readonly ModuleGraph moduleGraph; private readonly string? entryPoint; private IndentedTextWriter writer = new(); - private HashSet referencedTypes = new(); - private readonly Dictionary referencedStringLiterals = new(); - private readonly HashSet emittedTypes = new(); + private readonly HashSet referencedTypes = []; + private readonly Dictionary referencedStringLiterals = []; + private readonly HashSet emittedTypes = []; private readonly Stack scopes = new(); private int tmpNameIndex = 0; @@ -34,22 +34,7 @@ public class Generator writer.WriteLine($$""" int main(int argc, char *argv[]) { - struct nub_dynamic_array_52747d8c11b7118c args = (struct nub_dynamic_array_52747d8c11b7118c){0}; - - for (int i = 0; i < argc; ++i) - { - auto nubstring = nub_core_string_from_cstr(argv[i]); - da_append(&args, nubstring); - } - - int returnValue = {{entryPoint}}(args); - - for (int i = 0; i < args.count; ++i) - { - nub_core_string_rc_dec(args.items[i]); - } - - return returnValue; + return {{entryPoint}}(); } """); @@ -108,154 +93,147 @@ public class Generator writer = new IndentedTextWriter(); - writer.WriteLine(""" - #include - #include - #include - #include - #include - #include - #include - #include + writer.WriteLine( +""" +#include +#include +#include +#include - #define FLAG_STRING_LITERAL 1 - #define STRING_DEBUG 1 +typedef struct +{ + char *data; + size_t length; + uint32_t ref; + uint32_t flags; +} string; - #if STRING_DEBUG - #define STR_DBG(fmt, ...) fprintf(stderr, "[STR] " fmt "\n", ##__VA_ARGS__) - #else - #define STR_DBG(fmt, ...) - #endif +typedef uint8_t u8; +typedef int8_t i8; - struct nub_core_string - { - char *data; - size_t length; - uint32_t ref; - uint32_t flags; - }; +typedef uint16_t u16; +typedef int16_t i16; - #if STRING_DEBUG - static size_t nub_core_string_allocs = 0; - static size_t nub_core_string_frees = 0; +typedef uint32_t u32; +typedef int32_t i32; - __attribute__((destructor)) - static void string_debug_report(void) - { - fprintf(stderr, "[STR] REPORT allocs=%zu frees=%zu leaks=%zu\n", nub_core_string_allocs, nub_core_string_frees, nub_core_string_allocs - nub_core_string_frees); - } - #endif +typedef uint64_t u64; +typedef int64_t i64; - static inline void nub_core_string_rc_inc(struct nub_core_string *string) - { - if (string == NULL) - { - STR_DBG("INC null string"); - return; - } +#define FLAG_STRING_LITERAL 1 +#define STRING_DEBUG 1 - if (string->flags & FLAG_STRING_LITERAL) - return; +#if STRING_DEBUG +#define STR_DBG(fmt, ...) fprintf(stderr, "[STR] " fmt "\n", ##__VA_ARGS__) +#else +#define STR_DBG(fmt, ...) +#endif - string->ref += 1; +#if STRING_DEBUG +static size_t string_allocs = 0; +static size_t string_frees = 0; - STR_DBG("INC: str=%p ref=%u \"%s\"", (void*)string, string->ref, string->data); - } +__attribute__((destructor)) +static void string_debug_report(void) +{ + fprintf(stderr, "[STR] REPORT allocs=%zu frees=%zu leaks=%zu\n", string_allocs, string_frees, string_allocs - string_frees); +} +#endif - static inline void nub_core_string_rc_dec(struct nub_core_string *string) - { - if (string == NULL) - { - STR_DBG("DEC null string"); - return; - } +static inline void string_rc_inc(string *str) +{ + if (str == NULL) { + STR_DBG("INC null string"); + return; + } - if (string->flags & FLAG_STRING_LITERAL) - return; + if (str->flags & FLAG_STRING_LITERAL) + return; - if (string->ref == 0) - { - STR_DBG("ERROR: DEC on zero refcount str=%p", (void*)string); - return; - } + str->ref += 1; - string->ref -= 1; + STR_DBG("INC: str=%p ref=%u \"%s\"", (void *)str, str->ref, str->data); +} - STR_DBG("DEC: str=%p ref=%u \"%s\"", (void*)string, string->ref, string->data); +static inline void string_rc_dec(string *str) +{ + if (str == NULL) + { + STR_DBG("DEC null string"); + return; + } - if (string->ref == 0) - { - STR_DBG("FREE: str=%p data=%p \"%s\"", (void*)string, (void*)string->data, string->data); + if (str->flags & FLAG_STRING_LITERAL) + return; - char *data_ptr = string->data; - struct nub_core_string *str_ptr = string; + if (str->ref == 0) + { + STR_DBG("ERROR: DEC on zero refcount str=%p", (void *)str); + return; + } - #if STRING_DEBUG - nub_core_string_frees++; + str->ref -= 1; - memset(data_ptr, 0xDD, str_ptr->length); - memset(str_ptr, 0xDD, sizeof(*str_ptr)); - #endif + STR_DBG("DEC: str=%p ref=%u \"%s\"", (void *)str, str->ref, str->data); - free(data_ptr); - free(str_ptr); - } - } + if (str->ref == 0) { + STR_DBG("FREE: str=%p data=%p \"%s\"", (void *)str, (void *)str->data, str->data); - static inline struct nub_core_string *nub_core_string_concat(struct nub_core_string *left, struct nub_core_string *right) - { - size_t new_length = left->length + right->length; +#if STRING_DEBUG + string_frees++; +#endif - struct nub_core_string *result = malloc(sizeof(struct nub_core_string)); - result->data = malloc(new_length + 1); + free(str->data); + free(str); + } +} - memcpy(result->data, left->data, left->length); - memcpy(result->data + left->length, right->data, right->length); +static inline string *string_concat(string *left, string *right) +{ + size_t new_length = left->length + right->length; - result->data[new_length] = '\0'; - result->length = new_length; - result->ref = 1; - result->flags = 0; + string *result = (string *)malloc(sizeof(string)); + result->data = (char *)malloc(new_length + 1); - #if STRING_DEBUG - nub_core_string_allocs++; - STR_DBG("NEW concat: str=%p ref=%u \"%s\"", (void*)result, result->ref, result->data); - #endif + memcpy(result->data, left->data, left->length); + memcpy(result->data + left->length, right->data, right->length); - return result; - } + result->data[new_length] = '\0'; + result->length = new_length; + result->ref = 1; + result->flags = 0; - static inline struct nub_core_string *nub_core_string_from_cstr(char* cstr) - { - size_t len = strlen(cstr); +#if STRING_DEBUG + string_allocs++; + STR_DBG("NEW concat: str=%p ref=%u \"%s\"", (void *)result, result->ref, result->data); +#endif - struct nub_core_string *result = malloc(sizeof(struct nub_core_string)); - result->data = malloc(len + 1); + return result; +} - memcpy(result->data, cstr, len + 1); +static inline string *string_from_cstr(char *cstr) +{ + size_t len = strlen(cstr); - result->length = len; - result->ref = 1; - result->flags = 0; + string *result = (string *)malloc(sizeof(string)); + result->data = (char *)malloc(len + 1); - #if STRING_DEBUG - nub_core_string_allocs++; - STR_DBG("NEW from_cstr: str=%p ref=%u \"%s\"", (void*)result, result->ref, result->data); - #endif + memcpy(result->data, cstr, len + 1); - return result; - } + result->length = len; + result->ref = 1; + result->flags = 0; - #define da_append(xs, x) \ - do { \ - if ((xs)->count >= (xs)->capacity) { \ - if ((xs)->capacity == 0) (xs)->capacity = 256; \ - else (xs)->capacity *= 2; \ - (xs)->items = realloc((xs)->items, (xs)->capacity*sizeof(*(xs)->items)); \ - } \ - (xs)->items[(xs)->count++] = (x); \ - } while (0) - """); +#if STRING_DEBUG + string_allocs++; + STR_DBG("NEW from_cstr: str=%p ref=%u \"%s\"", (void *)result, result->ref, result->data); +#endif + + return result; +} + +""" +); while (referencedTypes.Count != 0) { @@ -269,9 +247,9 @@ public class Generator writer.WriteLine ( $$""" - static struct nub_core_string {{name}} = { + static string {{name}} = (string){ .data = "{{value}}", - .length = {{value.Length}}, + .length = {{Encoding.UTF8.GetByteCount(value)}}, .ref = 0, .flags = FLAG_STRING_LITERAL }; @@ -296,19 +274,19 @@ public class Generator { case NubTypeArray arrayType: { - var name = NameMangler.Mangle("dynamic", "array", arrayType); + EmitTypeDefinitionIfNotEmitted(arrayType.ElementType); - writer.WriteLine - ( - $$""" - struct {{name}} + writer.WriteLine("typedef struct"); + writer.WriteLine("{"); + using (writer.Indent()) { - size_t count; - size_t capacity; - {{CType(arrayType.ElementType)}} *items; - }; - """ - ); + writer.WriteLine("size_t count;"); + writer.WriteLine("size_t capacity;"); + writer.WriteLine($"{CType(arrayType.ElementType)} *items;"); + } + writer.WriteLine($"}} {typeNames[arrayType]};"); + writer.WriteLine(); + break; } case NubTypeStruct structType: @@ -319,12 +297,10 @@ public class Generator foreach (var field in structInfo.Fields) EmitTypeDefinitionIfNotEmitted(field.Type); - writer.Write("struct "); - if (structInfo.Packed) writer.Write("__attribute__((__packed__)) "); - writer.WriteLine(NameMangler.Mangle(structType.Module, structType.Name, structType)); + writer.WriteLine("typedef struct"); writer.WriteLine("{"); using (writer.Indent()) { @@ -333,7 +309,7 @@ public class Generator writer.WriteLine($"{CType(field.Type, field.Name)};"); } } - writer.WriteLine("};"); + writer.WriteLine($"}} {typeNames[structType]};"); writer.WriteLine(); break; @@ -343,7 +319,7 @@ public class Generator foreach (var field in anonymousStructType.Fields) EmitTypeDefinitionIfNotEmitted(field.Type); - writer.WriteLine($"struct {NameMangler.Mangle("anonymous", "struct", anonymousStructType)}"); + writer.WriteLine("typedef struct"); writer.WriteLine("{"); using (writer.Indent()) { @@ -352,7 +328,7 @@ public class Generator writer.WriteLine($"{CType(field.Type, field.Name)};"); } } - writer.WriteLine("};"); + writer.WriteLine($"}} {typeNames[anonymousStructType]};"); writer.WriteLine(); break; @@ -370,7 +346,7 @@ public class Generator } } - writer.WriteLine($"struct {NameMangler.Mangle(enumType.Module, enumType.Name, enumType)}"); + writer.WriteLine("typedef struct"); writer.WriteLine("{"); using (writer.Indent()) { @@ -389,7 +365,7 @@ public class Generator } writer.WriteLine("};"); } - writer.WriteLine("};"); + writer.WriteLine($"}} {typeNames[enumType]};"); writer.WriteLine(); break; @@ -782,23 +758,31 @@ public class Generator { NubTypeVoid => "void" + (varName != null ? $" {varName}" : ""), NubTypeBool => "bool" + (varName != null ? $" {varName}" : ""), - NubTypeStruct type => $"struct {NameMangler.Mangle(type.Module, type.Name, type)}" + (varName != null ? $" {varName}" : ""), - NubTypeAnonymousStruct type => CTypeAnonymousStruct(type, varName), - NubTypeEnum type => $"struct {NameMangler.Mangle(type.Module, type.Name, type)}" + (varName != null ? $" {varName}" : ""), + NubTypeStruct type => CTypeNamed(type, varName), + NubTypeAnonymousStruct type => CTypeNamed(type, varName), + NubTypeEnum type => CTypeNamed(type, varName), NubTypeEnumVariant type => CType(type.EnumType, varName), - NubTypeSInt type => $"int{type.Width}_t" + (varName != null ? $" {varName}" : ""), - NubTypeUInt type => $"uint{type.Width}_t" + (varName != null ? $" {varName}" : ""), + NubTypeSInt type => $"i{type.Width}" + (varName != null ? $" {varName}" : ""), + NubTypeUInt type => $"u{type.Width}" + (varName != null ? $" {varName}" : ""), NubTypePointer type => CType(type.To) + (varName != null ? $" *{varName}" : "*"), - NubTypeString type => "struct nub_core_string" + (varName != null ? $" *{varName}" : "*"), + NubTypeString type => "string" + (varName != null ? $" *{varName}" : "*"), NubTypeFunc type => $"{CType(type.ReturnType)} (*{varName})({string.Join(", ", type.Parameters.Select(p => CType(p)))})", - NubTypeArray type => $"struct {NameMangler.Mangle("dynamic", "array", type)}" + (varName != null ? $" {varName}" : ""), + NubTypeArray type => CTypeNamed(type, varName), _ => throw new ArgumentOutOfRangeException(nameof(node), node, null) }; } - private static string CTypeAnonymousStruct(NubTypeAnonymousStruct type, string? varName) + private readonly Dictionary typeNames = []; + + private string CTypeNamed(NubType type, string? varName) { - return $"struct {NameMangler.Mangle("anonymous", "struct", type)}{(varName != null ? $" {varName}" : "")}"; + if (!typeNames.TryGetValue(type, out var name)) + { + name = Tmp(); + typeNames[type] = name; + } + + return $"{name}{(varName != null ? $" {varName}" : "")}"; } private string Tmp() @@ -833,7 +817,7 @@ public class Generator { case NubTypeString: { - writer.WriteLine($"nub_core_string_rc_inc({value});"); + writer.WriteLine($"string_rc_inc({value});"); break; } case NubTypeStruct structType: @@ -904,7 +888,7 @@ public class Generator { case NubTypeString: { - writer.WriteLine($"nub_core_string_rc_dec({value});"); + writer.WriteLine($"string_rc_dec({value});"); break; } case NubTypeStruct structType: diff --git a/compiler/Program.cs b/compiler/Program.cs index adb898a..de22558 100644 --- a/compiler/Program.cs +++ b/compiler/Program.cs @@ -144,18 +144,6 @@ if (!compileLib) return 1; } - if (entryPointType.Parameters.Count != 1) - { - DiagnosticFormatter.Print(Diagnostic.Error($"Entrypoint must take exaxtly one parameter").Build(), Console.Error); - return 1; - } - - if (entryPointType.Parameters[0] is not NubTypeArray { ElementType: NubTypeString }) - { - DiagnosticFormatter.Print(Diagnostic.Error($"First parameter of entrypoint must be a string array").Build(), Console.Error); - return 1; - } - entryPoint = info.MangledName; } diff --git a/examples/program/main.nub b/examples/program/main.nub index 63849fd..6ea92d3 100644 --- a/examples/program/main.nub +++ b/examples/program/main.nub @@ -10,15 +10,19 @@ enum Message { Say: string } -func main(args: []string): i32 { - let i = 0 - while i < args.count { - // core::print(args[i]) - i = i + 1 +func main(): i32 { + let message = getMessage() + + match message { + Quit {} + Say msg { + core::println(msg) + } } + return 0 } func getMessage(): Message { - return new Message::Say("test") + return new Message::Say("testæøå") } \ No newline at end of file