speedcat/src/main.odin
Slendi a966ff45a3 Improve messages, implement* field access
Compiler messages are now printed in color with their respective code,
field access support has been added in the type checker. However, field
access nodes that contain other field access nodes are not yet
supported.

Signed-off-by: Slendi <slendi@socopon.com>
2024-04-08 11:42:39 +03:00

124 lines
2.5 KiB
Odin

package main
import "core:fmt"
import "core:os"
main :: proc() {
handle: os.Handle
file_name := "<stdin>"
if len(os.args) >= 2 {
errno: os.Errno
handle, errno = os.open(os.args[1])
if errno != 0 {
fmt.printf("Error opening file\n", errno)
return
}
file_name = os.args[1]
} else {
handle = os.stdin
}
defer os.close(handle)
data, err := os.read_entire_file_from_handle(handle)
if !err {
fmt.printf("Error reading file\n", err)
return
}
u8_arr: [dynamic]u8
for ch in data {
append(&u8_arr, u8(ch))
}
lexer := lexer_create(&u8_arr, file_name)
parser := parser_create(lexer)
ast := parser_parse(&parser)
if len(g_message_list) > 0 {
contains_errors := false
for &msg in g_message_list {
message_print(&msg, &data)
if msg.level == .Error || msg.level == .Fatal {
contains_errors = true
}
//fmt.printf("%s\n", msg)
}
if contains_errors {
return
}
}
fmt.println("After parse:")
//node_print(ast)
clear(&g_message_list)
type_check(ast, nil)
fmt.println("After type check:")
//node_print(ast)
if len(g_message_list) > 0 {
contains_errors := false
for &msg in g_message_list {
message_print(&msg, &data)
if msg.level == .Error || msg.level == .Fatal {
contains_errors = true
}
//fmt.printf("%s\n", msg)
}
if contains_errors {
return
}
}
//node_print(ast)
name: string
if handle == os.stdin {
name = "stdin"
} else {
name = os.args[1]
}
name_dyn := [dynamic]u8{}
for ch in transmute([]u8)name {
append(&name_dyn, u8(ch))
}
module_name := parse_use_path2(name_dyn)
module_name = main_module_name_from_filename(module_name)
if len(module_name) == 0 {
clear(&module_name)
append(&module_name, 'm')
append(&module_name, 'a')
append(&module_name, 'i')
append(&module_name, 'n')
}
ctx := LLVMContextCreate()
defer LLVMContextDispose(ctx)
module := LLVMModuleCreateWithNameInContext(cstring(raw_data(module_name[:])), ctx)
defer LLVMDisposeModule(module)
builder := LLVMCreateBuilderInContext(ctx)
generate_llvm(ctx, module, builder, ast)
append(&module_name, '.')
append(&module_name, 'l')
append(&module_name, 'l')
LLVMPrintModuleToFile(module, cstring(raw_data(module_name[:])), nil)
}
main_module_name_from_filename :: proc(fname: [dynamic]u8) -> (module_name: [dynamic]u8) {
temp_name := [dynamic]u8{}
for ch in fname {
if ch == '/' || ch == '\\' {
clear(&temp_name)
} else {
append(&temp_name, ch)
}
}
for ch in temp_name {
if ch == '.' {
break
}
append(&module_name, ch)
}
return
}