Add support or extern function
Signed-off-by: Slendi <slendi@socopon.com>
This commit is contained in:
parent
10ae992a7b
commit
484d1a6e2c
22
src/ast.odin
22
src/ast.odin
@ -25,6 +25,7 @@ NodeKind :: enum {
|
|||||||
Ret,
|
Ret,
|
||||||
|
|
||||||
//
|
//
|
||||||
|
ExternFunction,
|
||||||
Function,
|
Function,
|
||||||
Struct,
|
Struct,
|
||||||
Enum,
|
Enum,
|
||||||
@ -154,6 +155,27 @@ node_create_function_call :: proc(
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
node_create_extern_function :: proc(
|
||||||
|
range: TextRange,
|
||||||
|
name: [dynamic]u8,
|
||||||
|
return_type: ^Node,
|
||||||
|
args: [dynamic]^Node,
|
||||||
|
) -> (
|
||||||
|
ret: ^Node,
|
||||||
|
) {
|
||||||
|
ret = new(Node)
|
||||||
|
ret^ = {
|
||||||
|
kind = .ExternFunction,
|
||||||
|
range = range,
|
||||||
|
children = {return_type},
|
||||||
|
value = name,
|
||||||
|
}
|
||||||
|
for arg in args {
|
||||||
|
append(&ret.children, arg)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
node_create_function :: proc(
|
node_create_function :: proc(
|
||||||
range: TextRange,
|
range: TextRange,
|
||||||
name: [dynamic]u8,
|
name: [dynamic]u8,
|
||||||
|
@ -55,9 +55,6 @@ lexer_should_not_emit_semicolon :: proc(lexer: ^Lexer) -> bool {
|
|||||||
lexer.last_token_kind == .OpenParen ||
|
lexer.last_token_kind == .OpenParen ||
|
||||||
lexer.last_token_kind == .OpenBrace ||
|
lexer.last_token_kind == .OpenBrace ||
|
||||||
lexer.last_token_kind == .OpenBracket ||
|
lexer.last_token_kind == .OpenBracket ||
|
||||||
lexer.last_token_kind == .CloseParen ||
|
|
||||||
lexer.last_token_kind == .CloseBrace ||
|
|
||||||
lexer.last_token_kind == .CloseBracket ||
|
|
||||||
lexer.last_token_kind == .Add ||
|
lexer.last_token_kind == .Add ||
|
||||||
lexer.last_token_kind == .Subtract ||
|
lexer.last_token_kind == .Subtract ||
|
||||||
lexer.last_token_kind == .Multiply ||
|
lexer.last_token_kind == .Multiply ||
|
||||||
|
139
src/main.odin
139
src/main.odin
@ -4,79 +4,86 @@ import "core:fmt"
|
|||||||
import "core:os"
|
import "core:os"
|
||||||
|
|
||||||
main :: proc() {
|
main :: proc() {
|
||||||
ctx := LLVMContextCreate()
|
// ctx := LLVMContextCreate()
|
||||||
defer LLVMContextDispose(ctx)
|
// defer LLVMContextDispose(ctx)
|
||||||
module := LLVMModuleCreateWithNameInContext("hello", ctx)
|
// module := LLVMModuleCreateWithNameInContext("hello", ctx)
|
||||||
defer LLVMDisposeModule(module)
|
// defer LLVMDisposeModule(module)
|
||||||
builder := LLVMCreateBuilderInContext(ctx)
|
// builder := LLVMCreateBuilderInContext(ctx)
|
||||||
|
|
||||||
int_8_type := LLVMInt8TypeInContext(ctx)
|
// int_8_type := LLVMInt8TypeInContext(ctx)
|
||||||
int_8_type_ptr := LLVMPointerType(int_8_type, 0)
|
// int_8_type_ptr := LLVMPointerType(int_8_type, 0)
|
||||||
int_32_type := LLVMInt32TypeInContext(ctx)
|
// int_32_type := LLVMInt32TypeInContext(ctx)
|
||||||
|
|
||||||
puts_function_args_type := []LLVMTypeRef{
|
// puts_function_args_type := []LLVMTypeRef{
|
||||||
int_8_type_ptr,
|
// int_8_type_ptr,
|
||||||
|
// }
|
||||||
|
|
||||||
|
// puts_function_type := LLVMFunctionType(int_32_type, raw_data(puts_function_args_type), 1, LLVMBool(0))
|
||||||
|
// puts_function := LLVMAddFunction(module, "puts", puts_function_type)
|
||||||
|
|
||||||
|
// main_function_type := LLVMFunctionType(int_32_type, nil, 0, LLVMBool(0))
|
||||||
|
// main_function := LLVMAddFunction(module, "main", main_function_type)
|
||||||
|
|
||||||
|
// entry := LLVMAppendBasicBlockInContext(ctx, main_function, "entry")
|
||||||
|
// LLVMPositionBuilderAtEnd(builder, entry)
|
||||||
|
|
||||||
|
// puts_function_args := []LLVMValueRef {
|
||||||
|
// LLVMBuildPointerCast(
|
||||||
|
// builder,
|
||||||
|
// LLVMBuildGlobalString(builder, "Hello world!\n", "hello"),
|
||||||
|
// int_8_type_ptr,
|
||||||
|
// "0",
|
||||||
|
// ),
|
||||||
|
// }
|
||||||
|
|
||||||
|
// LLVMBuildCall2(builder, puts_function_type, puts_function, raw_data(puts_function_args), len(puts_function_args), "i")
|
||||||
|
// LLVMBuildRet(builder, LLVMConstInt(int_32_type, 0, LLVMBool(0)))
|
||||||
|
|
||||||
|
// LLVMPrintModuleToFile(module, "hello.ll", nil)
|
||||||
|
|
||||||
|
handle: os.Handle
|
||||||
|
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
|
||||||
|
}
|
||||||
|
} 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
|
||||||
}
|
}
|
||||||
|
|
||||||
puts_function_type := LLVMFunctionType(int_32_type, raw_data(puts_function_args_type), 1, LLVMBool(0))
|
u8_arr : [dynamic]u8
|
||||||
puts_function := LLVMAddFunction(module, "puts", puts_function_type)
|
for ch in data {
|
||||||
|
append(&u8_arr, u8(ch))
|
||||||
main_function_type := LLVMFunctionType(int_32_type, nil, 0, LLVMBool(0))
|
|
||||||
main_function := LLVMAddFunction(module, "main", main_function_type)
|
|
||||||
|
|
||||||
entry := LLVMAppendBasicBlockInContext(ctx, main_function, "entry")
|
|
||||||
LLVMPositionBuilderAtEnd(builder, entry)
|
|
||||||
|
|
||||||
puts_function_args := []LLVMValueRef {
|
|
||||||
LLVMBuildPointerCast(
|
|
||||||
builder,
|
|
||||||
LLVMBuildGlobalString(builder, "Hello world!\n", "hello"),
|
|
||||||
int_8_type_ptr,
|
|
||||||
"0",
|
|
||||||
),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
LLVMBuildCall2(builder, puts_function_type, puts_function, raw_data(puts_function_args), len(puts_function_args), "i")
|
lexer := lexer_create(&u8_arr)
|
||||||
LLVMBuildRet(builder, LLVMConstInt(int_32_type, 0, LLVMBool(0)))
|
parser := parser_create(lexer)
|
||||||
|
|
||||||
LLVMPrintModuleToFile(module, "hello.ll", nil)
|
ast := parser_parse(&parser)
|
||||||
|
if len(g_message_list) > 0 {
|
||||||
|
for msg in g_message_list {
|
||||||
|
fmt.printf("%s\n", msg)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
clear(&g_message_list)
|
||||||
|
type_check(ast, nil)
|
||||||
|
if len(g_message_list) > 0 {
|
||||||
|
for msg in g_message_list {
|
||||||
|
fmt.printf("%s\n", msg)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
//handle: os.Handle
|
node_print(ast)
|
||||||
//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
|
|
||||||
// }
|
|
||||||
//} 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)
|
|
||||||
//parser := parser_create(lexer)
|
|
||||||
|
|
||||||
//ast := parser_parse(&parser)
|
|
||||||
//type_check(ast, nil)
|
|
||||||
//if len(g_message_list) > 0 {
|
|
||||||
// for msg in g_message_list {
|
|
||||||
// fmt.printf("%s\n", msg)
|
|
||||||
// }
|
|
||||||
// return
|
|
||||||
//}
|
|
||||||
|
|
||||||
//node_print(ast)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -185,9 +185,12 @@ parser_parse_function_definition :: proc(parser: ^Parser) -> ^Node {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type: ^Node = nil
|
type: ^Node = nil
|
||||||
if parser.tok.kind != .OpenBrace {
|
if parser.tok.kind != .OpenBrace && parser.tok.kind != .Semicolon {
|
||||||
type = parser_parse_type(parser)
|
type = parser_parse_type(parser)
|
||||||
}
|
}
|
||||||
|
if parser.tok.kind == .Semicolon {
|
||||||
|
return node_create_extern_function(parser.tok.range, name, type, params)
|
||||||
|
}
|
||||||
expect(parser, .OpenBrace)
|
expect(parser, .OpenBrace)
|
||||||
body := parser_parse_block(parser, .CloseBrace)
|
body := parser_parse_block(parser, .CloseBrace)
|
||||||
return node_create_function(parser.tok.range, name, type, body, params)
|
return node_create_function(parser.tok.range, name, type, body, params)
|
||||||
|
@ -310,6 +310,9 @@ type_check :: proc(ast: ^Node, parent_ast: ^Node) {
|
|||||||
}
|
}
|
||||||
type_check(ast.children[1], ast)
|
type_check(ast.children[1], ast)
|
||||||
scope_leave()
|
scope_leave()
|
||||||
|
case .ExternFunction:
|
||||||
|
ast.return_type = ast_to_type(ast.children[0])
|
||||||
|
scope_stack[len(scope_stack) - 1].function_return_type = ast.return_type
|
||||||
case:
|
case:
|
||||||
fmt.panicf("Unhandled node kind in type_check: {}", ast.kind)
|
fmt.panicf("Unhandled node kind in type_check: {}", ast.kind)
|
||||||
}
|
}
|
||||||
@ -323,7 +326,11 @@ find_function_definitions :: proc(ast_: ^Node) -> (ret: [dynamic]^FunctionType)
|
|||||||
if ast == nil {
|
if ast == nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
is_extern := false
|
||||||
#partial switch (ast.kind) {
|
#partial switch (ast.kind) {
|
||||||
|
case .ExternFunction:
|
||||||
|
is_extern := true
|
||||||
|
fallthrough
|
||||||
case .Function:
|
case .Function:
|
||||||
for fn in ret {
|
for fn in ret {
|
||||||
if compare_dyn_arrs(&fn.name, &ast.value.([dynamic]u8)) {
|
if compare_dyn_arrs(&fn.name, &ast.value.([dynamic]u8)) {
|
||||||
@ -346,8 +353,15 @@ find_function_definitions :: proc(ast_: ^Node) -> (ret: [dynamic]^FunctionType)
|
|||||||
return_type = ast_to_type(ast.children[0])
|
return_type = ast_to_type(ast.children[0])
|
||||||
}
|
}
|
||||||
for decl, i in ast.children {
|
for decl, i in ast.children {
|
||||||
if i < 2 {
|
if is_extern == false {
|
||||||
continue
|
if i < 2 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if i < 1 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
type := ast_to_type(decl.children[1])
|
type := ast_to_type(decl.children[1])
|
||||||
append(&fn.parameter_types, type)
|
append(&fn.parameter_types, type)
|
||||||
|
@ -5,6 +5,10 @@ fn name(a b: f32) i32 {
|
|||||||
ret (a + b) as i32
|
ret (a + b) as i32
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn put_32(str: []u32)
|
||||||
|
|
||||||
name 123.0 456.0
|
name 123.0 456.0
|
||||||
|
|
||||||
let arr: []i32, arr2: [69]u8, ptr: ^i32
|
let arr: []i32, arr2: [69]u8, ptr: ^i32
|
||||||
|
|
||||||
|
put_32("Hello")
|
||||||
|
Loading…
x
Reference in New Issue
Block a user