Add support for enums in the parser
Signed-off-by: Slendi <slendi@socopon.com>
This commit is contained in:
parent
ea9c622865
commit
95057fd359
364
pong.cat
364
pong.cat
@ -1,179 +1,193 @@
|
|||||||
struct Vec2 {
|
enum MyEnum {
|
||||||
x y: f32,
|
EnumItem1,
|
||||||
|
EnumItem2 = 1,
|
||||||
|
EnumItem3,
|
||||||
|
EnumItem4,
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Rect {
|
enum MyTypedEnum : i8 {
|
||||||
pos size: Vec2,
|
EnumItem1,
|
||||||
|
EnumItem2,
|
||||||
|
EnumItem3 = 105,
|
||||||
|
EnumItem4,
|
||||||
}
|
}
|
||||||
|
|
||||||
let CONSTPOS :: .Vec2 {20.0 20.0}
|
\struct Vec2 {
|
||||||
let CONSTSZ :: .Vec2 {100.0 100.0}
|
\ x y: f32,
|
||||||
let CONST :: .Rect {(CONSTPOS) (CONSTSZ)}
|
\}
|
||||||
|
\
|
||||||
\ FIXME: LLVM IR geneartion is borked
|
\struct Rect {
|
||||||
\ let CONST :: .Rect { .Vec2 { 20.0 20.0 } .Vec2 { 100.0 100.0 } }
|
\ pos size: Vec2,
|
||||||
|
\}
|
||||||
struct Color {
|
\
|
||||||
r g b a: u8,
|
\let CONSTPOS :: .Vec2 {20.0 20.0}
|
||||||
}
|
\let CONSTSZ :: .Vec2 {100.0 100.0}
|
||||||
|
\let CONST :: .Rect {(CONSTPOS) (CONSTSZ)}
|
||||||
let KEY_R :: 82
|
\
|
||||||
|
\\ FIXME: LLVM IR geneartion is borked
|
||||||
fn InitWindow(w h: i32, title: []u8)
|
\\ let CONST :: .Rect { .Vec2 { 20.0 20.0 } .Vec2 { 100.0 100.0 } }
|
||||||
fn CloseWindow
|
\
|
||||||
fn BeginDrawing
|
\struct Color {
|
||||||
fn SetTargetFPS(fps: i32)
|
\ r g b a: u8,
|
||||||
fn EndDrawing
|
\}
|
||||||
fn DrawFPS(x y: i32)
|
\
|
||||||
fn WindowShouldClose i32
|
\let KEY_R :: 82
|
||||||
fn TextSubtext(text: []u8, start end: i32) []u8
|
\
|
||||||
fn IsKeyPressed(key: i32) u1
|
\fn InitWindow(w h: i32, title: []u8)
|
||||||
|
\fn CloseWindow
|
||||||
struct Rectangle {
|
\fn BeginDrawing
|
||||||
x y w h: f32,
|
\fn SetTargetFPS(fps: i32)
|
||||||
}
|
\fn EndDrawing
|
||||||
|
\fn DrawFPS(x y: i32)
|
||||||
fn ColorToRaylib(c: Color) u32 {
|
\fn WindowShouldClose i32
|
||||||
ret c.a as u32 << 24 as u32 | c.b as u32 << 16 as u32 | c.g as u32 << 8 as u32 | c.r
|
\fn TextSubtext(text: []u8, start end: i32) []u8
|
||||||
}
|
\fn IsKeyPressed(key: i32) u1
|
||||||
|
\
|
||||||
fn ClearBackgroundWrap(c: Color) {
|
\struct Rectangle {
|
||||||
fn ClearBackground(c: u32)
|
\ x y w h: f32,
|
||||||
ClearBackground (ColorToRaylib c)
|
\}
|
||||||
}
|
\
|
||||||
|
\fn ColorToRaylib(c: Color) u32 {
|
||||||
fn DrawRectangleWrap(x y w h: i32, c: Color) {
|
\ ret c.a as u32 << 24 as u32 | c.b as u32 << 16 as u32 | c.g as u32 << 8 as u32 | c.r
|
||||||
fn DrawRectangle(x y w h: i32, c: u32)
|
\}
|
||||||
DrawRectangle x y w h (ColorToRaylib c)
|
\
|
||||||
}
|
\fn ClearBackgroundWrap(c: Color) {
|
||||||
|
\ fn ClearBackground(c: u32)
|
||||||
fn DrawCircleWrap(x y: i32, r: f32, c: Color) {
|
\ ClearBackground (ColorToRaylib c)
|
||||||
fn DrawCircle(x y: i32, r: f32, c: u32)
|
\}
|
||||||
DrawCircle x y r (ColorToRaylib c)
|
\
|
||||||
}
|
\fn DrawRectangleWrap(x y w h: i32, c: Color) {
|
||||||
|
\ fn DrawRectangle(x y w h: i32, c: u32)
|
||||||
fn DrawRectangleRecWrap(r: Rectangle, c: Color) {
|
\ DrawRectangle x y w h (ColorToRaylib c)
|
||||||
fn DrawRectangleRec(r: Rectangle, c: u32)
|
\}
|
||||||
DrawRectangleRec r (ColorToRaylib c)
|
\
|
||||||
}
|
\fn DrawCircleWrap(x y: i32, r: f32, c: Color) {
|
||||||
|
\ fn DrawCircle(x y: i32, r: f32, c: u32)
|
||||||
fn DrawTextWrap(text: []u8, x y size: i32, c: Color) {
|
\ DrawCircle x y r (ColorToRaylib c)
|
||||||
fn DrawText(text: []u8, x y size: i32, c: u32)
|
\}
|
||||||
DrawText text x y size (ColorToRaylib c)
|
\
|
||||||
}
|
\fn DrawRectangleRecWrap(r: Rectangle, c: Color) {
|
||||||
|
\ fn DrawRectangleRec(r: Rectangle, c: u32)
|
||||||
let WHITE :: .Color {255 255 255 255}
|
\ DrawRectangleRec r (ColorToRaylib c)
|
||||||
let BLACK :: .Color {0 0 0 255}
|
\}
|
||||||
let RED :: .Color {255 0 0 255}
|
\
|
||||||
let BLUE :: .Color {0 0 255 255}
|
\fn DrawTextWrap(text: []u8, x y size: i32, c: Color) {
|
||||||
|
\ fn DrawText(text: []u8, x y size: i32, c: u32)
|
||||||
InitWindow 800 450 Raylib
|
\ DrawText text x y size (ColorToRaylib c)
|
||||||
SetTargetFPS 60
|
\}
|
||||||
|
\
|
||||||
fn GetScreenWidth i32
|
\let WHITE :: .Color {255 255 255 255}
|
||||||
fn GetScreenHeight i32
|
\let BLACK :: .Color {0 0 0 255}
|
||||||
|
\let RED :: .Color {255 0 0 255}
|
||||||
fn DrawRect(rect: Rect, c: Color) {
|
\let BLUE :: .Color {0 0 255 255}
|
||||||
DrawRectangleWrap (rect.pos.x as i32) (rect.pos.y as i32) (rect.size.x as i32) (rect.size.y as i32) c
|
\
|
||||||
}
|
\InitWindow 800 450 Raylib
|
||||||
|
\SetTargetFPS 60
|
||||||
let logox := GetScreenWidth / 2 - 128
|
\
|
||||||
let logoy := GetScreenHeight / 2 - 128
|
\fn GetScreenWidth i32
|
||||||
|
\fn GetScreenHeight i32
|
||||||
\ FIXME: Cannot inline
|
\
|
||||||
let fc := 0
|
\fn DrawRect(rect: Rect, c: Color) {
|
||||||
let lc := 0
|
\ DrawRectangleWrap (rect.pos.x as i32) (rect.pos.y as i32) (rect.size.x as i32) (rect.size.y as i32) c
|
||||||
let top_side_rec_width := 16
|
\}
|
||||||
let left_side_rec_height := 16
|
\
|
||||||
let bottom_side_rec_width := 16
|
\let logox := GetScreenWidth / 2 - 128
|
||||||
let right_side_rec_height := 16
|
\let logoy := GetScreenHeight / 2 - 128
|
||||||
|
\
|
||||||
let state := 0
|
\\ FIXME: Cannot inline
|
||||||
let alpha := 1.0
|
\let fc := 0
|
||||||
|
\let lc := 0
|
||||||
for WindowShouldClose == 0 {
|
\let top_side_rec_width := 16
|
||||||
if state == 0 {
|
\let left_side_rec_height := 16
|
||||||
if ++fc == 120 {
|
\let bottom_side_rec_width := 16
|
||||||
state = 1
|
\let right_side_rec_height := 16
|
||||||
fc = 0
|
\
|
||||||
}
|
\let state := 0
|
||||||
} elif state == 1 {
|
\let alpha := 1.0
|
||||||
top_side_rec_width = top_side_rec_width + 4
|
\
|
||||||
left_side_rec_height = left_side_rec_height + 4
|
\for WindowShouldClose == 0 {
|
||||||
|
\ if state == 0 {
|
||||||
if top_side_rec_width == 256 {
|
\ if ++fc == 120 {
|
||||||
state = 2
|
\ state = 1
|
||||||
}
|
\ fc = 0
|
||||||
} elif state == 2 {
|
\ }
|
||||||
bottom_side_rec_width = bottom_side_rec_width + 4
|
\ } elif state == 1 {
|
||||||
right_side_rec_height = right_side_rec_height + 4
|
\ top_side_rec_width = top_side_rec_width + 4
|
||||||
|
\ left_side_rec_height = left_side_rec_height + 4
|
||||||
if bottom_side_rec_width == 256 {
|
\
|
||||||
state = 3
|
\ if top_side_rec_width == 256 {
|
||||||
}
|
\ state = 2
|
||||||
} elif state == 3 {
|
\ }
|
||||||
if ++fc / 12 != 0 {
|
\ } elif state == 2 {
|
||||||
++lc
|
\ bottom_side_rec_width = bottom_side_rec_width + 4
|
||||||
fc = 0
|
\ right_side_rec_height = right_side_rec_height + 4
|
||||||
}
|
\
|
||||||
|
\ if bottom_side_rec_width == 256 {
|
||||||
if lc >= 10 {
|
\ state = 3
|
||||||
alpha = alpha - 0.01
|
\ }
|
||||||
if alpha <= 0.0 {
|
\ } elif state == 3 {
|
||||||
alpha = 0.0
|
\ if ++fc / 12 != 0 {
|
||||||
state = 4
|
\ ++lc
|
||||||
}
|
\ fc = 0
|
||||||
}
|
\ }
|
||||||
} elif IsKeyPressed(KEY_R) { \
|
\
|
||||||
fc = lc = 0
|
\ if lc >= 10 {
|
||||||
|
\ alpha = alpha - 0.01
|
||||||
top_side_rec_width = 16
|
\ if alpha <= 0.0 {
|
||||||
left_side_rec_height = 16
|
\ alpha = 0.0
|
||||||
bottom_side_rec_width = 16
|
\ state = 4
|
||||||
right_side_rec_height = 16
|
\ }
|
||||||
|
\ }
|
||||||
state = 0
|
\ } elif IsKeyPressed(KEY_R) { \
|
||||||
alpha = 1.0
|
\ fc = lc = 0
|
||||||
}
|
\
|
||||||
|
\ top_side_rec_width = 16
|
||||||
BeginDrawing
|
\ left_side_rec_height = 16
|
||||||
ClearBackgroundWrap WHITE
|
\ bottom_side_rec_width = 16
|
||||||
DrawFPS 20 20
|
\ right_side_rec_height = 16
|
||||||
|
\
|
||||||
DrawRect CONST RED
|
\ state = 0
|
||||||
|
\ alpha = 1.0
|
||||||
if state == 0 {
|
\ }
|
||||||
if (fc/15)%2 != 0 {
|
\
|
||||||
DrawRectangleWrap logox logoy 16 16 BLACK
|
\ BeginDrawing
|
||||||
}
|
\ ClearBackgroundWrap WHITE
|
||||||
} elif state == 1 {
|
\ DrawFPS 20 20
|
||||||
DrawRectangleWrap logox logoy top_side_rec_width 16 BLACK
|
\
|
||||||
DrawRectangleWrap logox logoy 16 left_side_rec_height BLACK
|
\ DrawRect CONST RED
|
||||||
} elif state == 2 {
|
\
|
||||||
DrawRectangleWrap logox logoy top_side_rec_width 16 BLACK
|
\ if state == 0 {
|
||||||
DrawRectangleWrap logox logoy 16 left_side_rec_height BLACK
|
\ if (fc/15)%2 != 0 {
|
||||||
|
\ DrawRectangleWrap logox logoy 16 16 BLACK
|
||||||
DrawRectangleWrap logox+240 logoy 16 right_side_rec_height BLACK
|
\ }
|
||||||
DrawRectangleWrap logox logoy+240 bottom_side_rec_width 16 BLACK
|
\ } elif state == 1 {
|
||||||
} elif state == 3 {
|
\ DrawRectangleWrap logox logoy top_side_rec_width 16 BLACK
|
||||||
let colorw := .Color{255 255 255 (alpha*255.0) as u8}
|
\ DrawRectangleWrap logox logoy 16 left_side_rec_height BLACK
|
||||||
let colorb := .Color{0 0 0 (alpha*255.0) as u8}
|
\ } elif state == 2 {
|
||||||
\ FIXME: ADD field access assignment
|
\ DrawRectangleWrap logox logoy top_side_rec_width 16 BLACK
|
||||||
\color.a = (alpha * 255.0) as u8
|
\ DrawRectangleWrap logox logoy 16 left_side_rec_height BLACK
|
||||||
DrawRectangleWrap logox logoy top_side_rec_width 16 colorb
|
\
|
||||||
DrawRectangleWrap logox logoy+16 16 left_side_rec_height-32 colorb
|
\ DrawRectangleWrap logox+240 logoy 16 right_side_rec_height BLACK
|
||||||
|
\ DrawRectangleWrap logox logoy+240 bottom_side_rec_width 16 BLACK
|
||||||
DrawRectangleWrap logox+240 logoy+16 16 right_side_rec_height-32 cbolor
|
\ } elif state == 3 {
|
||||||
DrawRectangleWrap logox logoy+240 bottom_side_rec_width 16 colorb
|
\ let colorw := .Color{255 255 255 (alpha*255.0) as u8}
|
||||||
|
\ let colorb := .Color{0 0 0 (alpha*255.0) as u8}
|
||||||
DrawRectangleWrap GetScreenWidth/2-112 GetScreenHeight/2-112 224 224 colorw
|
\ \ FIXME: ADD field access assignment
|
||||||
|
\ \color.a = (alpha * 255.0) as u8
|
||||||
DrawTextWrap (TextSubtext raylib 0 lc) GetScreenWidth/2-44 GetScreenHeight/2+48 50 colorb
|
\ DrawRectangleWrap logox logoy top_side_rec_width 16 colorb
|
||||||
} else {
|
\ DrawRectangleWrap logox logoy+16 16 left_side_rec_height-32 colorb
|
||||||
DrawTextWrap "[R] REPLAY" 340 200 20 BLACK
|
\
|
||||||
}
|
\ DrawRectangleWrap logox+240 logoy+16 16 right_side_rec_height-32 cbolor
|
||||||
|
\ DrawRectangleWrap logox logoy+240 bottom_side_rec_width 16 colorb
|
||||||
EndDrawing
|
\
|
||||||
}
|
\ DrawRectangleWrap GetScreenWidth/2-112 GetScreenHeight/2-112 224 224 colorw
|
||||||
CloseWindow
|
\
|
||||||
|
\ DrawTextWrap (TextSubtext raylib 0 lc) GetScreenWidth/2-44 GetScreenHeight/2+48 50 colorb
|
||||||
|
\ } else {
|
||||||
|
\ DrawTextWrap "[R] REPLAY" 340 200 20 BLACK
|
||||||
|
\ }
|
||||||
|
\
|
||||||
|
\ EndDrawing
|
||||||
|
\}
|
||||||
|
\CloseWindow
|
||||||
|
\
|
||||||
|
42
src/ast.odin
42
src/ast.odin
@ -47,6 +47,18 @@ NodeKind :: enum {
|
|||||||
// Example for std.println: std$println
|
// Example for std.println: std$println
|
||||||
}
|
}
|
||||||
|
|
||||||
|
EnumValueItem :: struct {
|
||||||
|
range: SourceLocation,
|
||||||
|
name: [dynamic]u8,
|
||||||
|
value: u64,
|
||||||
|
resolved: bool, // Used during parsing to know if a enum item has a resolved value or not
|
||||||
|
}
|
||||||
|
|
||||||
|
EnumValue :: struct {
|
||||||
|
values: [dynamic]EnumValueItem,
|
||||||
|
type: ^Node,
|
||||||
|
}
|
||||||
|
|
||||||
Node :: struct {
|
Node :: struct {
|
||||||
kind: NodeKind,
|
kind: NodeKind,
|
||||||
range: SourceLocation,
|
range: SourceLocation,
|
||||||
@ -54,6 +66,7 @@ Node :: struct {
|
|||||||
value: TokenValue,
|
value: TokenValue,
|
||||||
value_token_kind: TokenKind,
|
value_token_kind: TokenKind,
|
||||||
return_type: ^Type,
|
return_type: ^Type,
|
||||||
|
enum_value: EnumValue,
|
||||||
}
|
}
|
||||||
|
|
||||||
node_create_value :: proc(kind: NodeKind, range: SourceLocation, value: TokenValue) -> (ret: ^Node) {
|
node_create_value :: proc(kind: NodeKind, range: SourceLocation, value: TokenValue) -> (ret: ^Node) {
|
||||||
@ -223,9 +236,27 @@ node_print :: proc(node: ^Node, indent := 0) {
|
|||||||
}
|
}
|
||||||
fmt.println("")
|
fmt.println("")
|
||||||
|
|
||||||
|
if node.kind == .Enum {
|
||||||
|
for &item in node.enum_value.values {
|
||||||
|
for i in 0 ..= indent {
|
||||||
|
fmt.printf(" ")
|
||||||
|
}
|
||||||
|
fmt.printf("%s = 0x%016x Resolved?={} at ", item.name, item.value, item.resolved)
|
||||||
|
fmt.printf(
|
||||||
|
"\x1B[32m%s\x1b[90m:\x1B[36m{}:{}\x1B[0m->\x1B[36m{}:{}\x1B[0m\n",
|
||||||
|
item.range.file,
|
||||||
|
item.range.range.start.line,
|
||||||
|
item.range.range.start.column,
|
||||||
|
item.range.range.end.line,
|
||||||
|
item.range.range.end.column,
|
||||||
|
)
|
||||||
|
|
||||||
|
}
|
||||||
|
} else {
|
||||||
for child in node.children {
|
for child in node.children {
|
||||||
node_print(child, indent + 1)
|
node_print(child, indent + 1)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
parse_use_path :: proc(path: [dynamic]u8) -> (ret: [dynamic]u8) {
|
parse_use_path :: proc(path: [dynamic]u8) -> (ret: [dynamic]u8) {
|
||||||
@ -380,7 +411,7 @@ node_create_struct_initializer :: proc(
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
node_create_struct_enum_or_union :: proc(
|
node_create_struct_or_union :: proc(
|
||||||
range: SourceLocation,
|
range: SourceLocation,
|
||||||
kind: NodeKind,
|
kind: NodeKind,
|
||||||
name: [dynamic]u8,
|
name: [dynamic]u8,
|
||||||
@ -401,6 +432,15 @@ node_create_struct_enum_or_union :: proc(
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
node_create_enum :: proc(range: SourceLocation, data: EnumValue) -> (ret: ^Node) {
|
||||||
|
ret = new(Node)
|
||||||
|
ret^ = {
|
||||||
|
kind = .Enum,
|
||||||
|
enum_value = data,
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
node_clone :: proc(node: ^Node) -> (ret: ^Node) {
|
node_clone :: proc(node: ^Node) -> (ret: ^Node) {
|
||||||
ret = new(Node)
|
ret = new(Node)
|
||||||
ret^ = node^
|
ret^ = node^
|
||||||
|
@ -46,52 +46,54 @@ main :: proc() {
|
|||||||
os.exit(1)
|
os.exit(1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
clear(&g_message_list)
|
//clear(&g_message_list)
|
||||||
type_check(ast, nil)
|
//type_check(ast, nil)
|
||||||
if len(g_message_list) > 0 {
|
//if len(g_message_list) > 0 {
|
||||||
contains_errors := false
|
// contains_errors := false
|
||||||
for &msg in g_message_list {
|
// for &msg in g_message_list {
|
||||||
message_print(&msg, &data)
|
// message_print(&msg, &data)
|
||||||
if msg.level == .Error || msg.level == .Fatal {
|
// if msg.level == .Error || msg.level == .Fatal {
|
||||||
contains_errors = true
|
// contains_errors = true
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
if contains_errors {
|
// if contains_errors {
|
||||||
os.exit(1)
|
// os.exit(1)
|
||||||
}
|
// }
|
||||||
}
|
//}
|
||||||
|
|
||||||
name: string
|
node_print(ast)
|
||||||
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)
|
// name: string
|
||||||
|
// if handle == os.stdin {
|
||||||
append(&module_name, '.')
|
// name = "stdin"
|
||||||
append(&module_name, 'l')
|
// } else {
|
||||||
append(&module_name, 'l')
|
// name = os.args[1]
|
||||||
LLVMPrintModuleToFile(module, cstring(raw_data(module_name[:])), nil)
|
// }
|
||||||
|
// 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) {
|
main_module_name_from_filename :: proc(fname: [dynamic]u8) -> (module_name: [dynamic]u8) {
|
||||||
|
@ -154,7 +154,7 @@ parser_parse_struct_definition :: proc(parser: ^Parser) -> ^Node {
|
|||||||
expect(parser, .OpenBrace)
|
expect(parser, .OpenBrace)
|
||||||
fields := parser_parse_definitions(parser, .CloseBrace)
|
fields := parser_parse_definitions(parser, .CloseBrace)
|
||||||
expect(parser, .CloseBrace)
|
expect(parser, .CloseBrace)
|
||||||
n := node_create_struct_enum_or_union(range, .Struct, name, fields)
|
n := node_create_struct_or_union(range, .Struct, name, fields)
|
||||||
n.value = is_packed
|
n.value = is_packed
|
||||||
return n
|
return n
|
||||||
}
|
}
|
||||||
@ -163,7 +163,86 @@ parser_parse_struct_definition :: proc(parser: ^Parser) -> ^Node {
|
|||||||
parser_parse_enum_definition :: proc(parser: ^Parser) -> ^Node {
|
parser_parse_enum_definition :: proc(parser: ^Parser) -> ^Node {
|
||||||
range := parser.tok.range
|
range := parser.tok.range
|
||||||
expect(parser, .Enum)
|
expect(parser, .Enum)
|
||||||
panic("TODO, enum not implemented yet")
|
|
||||||
|
enum_value := EnumValue {
|
||||||
|
values = [dynamic]EnumValueItem{},
|
||||||
|
type = nil,
|
||||||
|
}
|
||||||
|
|
||||||
|
name: [dynamic]u8
|
||||||
|
if parser.tok.kind == .Identifier {
|
||||||
|
name = parser.tok.value.([dynamic]u8)
|
||||||
|
}
|
||||||
|
if !expect(parser, .Identifier) {
|
||||||
|
if accept(parser, .Colon) {
|
||||||
|
for parser.tok.kind != .OpenBrace && parser.tok.kind != .EOF && parser.tok.kind != .Semicolon {
|
||||||
|
parser_next(parser)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if accept(parser, .OpenBrace) {
|
||||||
|
for parser.tok.kind != .CloseBrace && parser.tok.kind != .EOF {
|
||||||
|
parser_next(parser)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type_node: ^Node = nil
|
||||||
|
if accept(parser, .Colon) {
|
||||||
|
type_node = parser_parse_type(parser)
|
||||||
|
} else {
|
||||||
|
type_node = node_create_value(.Identifier, range, [dynamic]u8{'i', '3', '2'})
|
||||||
|
}
|
||||||
|
|
||||||
|
expect(parser, .OpenBrace)
|
||||||
|
|
||||||
|
for parser.tok.kind != .CloseBrace && parser.tok.kind != .EOF {
|
||||||
|
item_range := parser.tok.range
|
||||||
|
item := EnumValueItem{}
|
||||||
|
item.range = item_range
|
||||||
|
item.resolved = false
|
||||||
|
if parser.tok.kind != .Identifier {
|
||||||
|
append(&g_message_list, message_create(.Error, "Expected identifier in enum value list", parser.tok.range))
|
||||||
|
for parser.tok.kind != .CloseBrace && parser.tok.kind != .EOF {
|
||||||
|
parser_next(parser)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
name := parser.tok.value.([dynamic]u8)
|
||||||
|
item.name = name
|
||||||
|
parser_next(parser)
|
||||||
|
|
||||||
|
value := transmute(u64)(i64(-1))
|
||||||
|
if accept(parser, .Assign) {
|
||||||
|
if parser.tok.kind != .Integer {
|
||||||
|
append(
|
||||||
|
&g_message_list,
|
||||||
|
message_create(.Error, "Only integers can be values for enums", parser.tok.range),
|
||||||
|
)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
item.resolved = true
|
||||||
|
value = parser.tok.value.(u64)
|
||||||
|
item_range.range.end = parser.tok.range.range.end
|
||||||
|
parser_next(parser)
|
||||||
|
}
|
||||||
|
item.value = value
|
||||||
|
|
||||||
|
append(&enum_value.values, item)
|
||||||
|
|
||||||
|
if parser.tok.kind == .CloseBrace {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
expect(parser, .Comma)
|
||||||
|
}
|
||||||
|
range.range.end = parser.tok.range.range.end
|
||||||
|
parser_next(parser)
|
||||||
|
|
||||||
|
// FIXME: Resolve items
|
||||||
|
|
||||||
|
enum_value.type = type_node
|
||||||
|
|
||||||
|
return node_create_enum(range, enum_value)
|
||||||
}
|
}
|
||||||
|
|
||||||
@(private = "file")
|
@(private = "file")
|
||||||
@ -180,7 +259,7 @@ parser_parse_union_definition :: proc(parser: ^Parser) -> ^Node {
|
|||||||
expect(parser, .OpenBrace)
|
expect(parser, .OpenBrace)
|
||||||
fields := parser_parse_definitions(parser, .CloseBrace)
|
fields := parser_parse_definitions(parser, .CloseBrace)
|
||||||
expect(parser, .CloseBrace)
|
expect(parser, .CloseBrace)
|
||||||
return node_create_struct_enum_or_union(range, .Union, name, fields)
|
return node_create_struct_or_union(range, .Union, name, fields)
|
||||||
}
|
}
|
||||||
|
|
||||||
@(private = "file")
|
@(private = "file")
|
||||||
|
63
test.cat
63
test.cat
@ -1,63 +0,0 @@
|
|||||||
use "fmt.cat"
|
|
||||||
use lib "directory/long_library_name"
|
|
||||||
use "directory/library'with'special'chars"
|
|
||||||
|
|
||||||
\ This is a comment, it should be ignored by the compiler
|
|
||||||
|
|
||||||
fmt.printf "%i + %i = %i File length: %i\n" a b a + b (io.file_size "file.txt")
|
|
||||||
fmt.println "Hello world!"
|
|
||||||
|
|
||||||
let a := 123 \ This is another comment, that should be ignored by the compiler
|
|
||||||
let uninitialized : u32
|
|
||||||
let multiple variables here : u32 = 1 2 3
|
|
||||||
let string : str, number : i32
|
|
||||||
|
|
||||||
if a == 1 {
|
|
||||||
lol
|
|
||||||
} elif b == 2 {
|
|
||||||
kek
|
|
||||||
} else {
|
|
||||||
aaaaaaa
|
|
||||||
}
|
|
||||||
|
|
||||||
for {
|
|
||||||
\ Infinite loop
|
|
||||||
}
|
|
||||||
|
|
||||||
for a > 0 {
|
|
||||||
\ Countdown loop
|
|
||||||
fmt.printf "%i\n" a--
|
|
||||||
}
|
|
||||||
|
|
||||||
\for let i : i32 = 0; i < 20; i++ {
|
|
||||||
\ \ Loop that goes up to 19
|
|
||||||
\}
|
|
||||||
\
|
|
||||||
\for let i : i32 in 0..<20 {
|
|
||||||
\ \ Shorthand for above
|
|
||||||
\}
|
|
||||||
|
|
||||||
fn name {}
|
|
||||||
fn name returntype {}
|
|
||||||
fn name() {}
|
|
||||||
fn name(param1 param2 param3: i32, param4: u32) u32 { }
|
|
||||||
|
|
||||||
struct StructName {
|
|
||||||
field1 field2 field3: i32,
|
|
||||||
field4: u32,
|
|
||||||
}
|
|
||||||
|
|
||||||
union MyUnion {
|
|
||||||
data: StructName,
|
|
||||||
some_other_data: EnumName,
|
|
||||||
}
|
|
||||||
|
|
||||||
\enum EnumName {
|
|
||||||
\ Value1,
|
|
||||||
\ Value2,
|
|
||||||
\ Value3,
|
|
||||||
\ Value4,
|
|
||||||
\}
|
|
||||||
|
|
||||||
\EnumName.Value1
|
|
||||||
|
|
@ -1,2 +1,9 @@
|
|||||||
a++
|
enum TokenKind {
|
||||||
|
Identifier,
|
||||||
|
Number,
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Token {
|
||||||
|
kind: TokenKind,
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -15,11 +15,13 @@
|
|||||||
- [ ] Add support for nested structure initializers (LLVM)
|
- [ ] Add support for nested structure initializers (LLVM)
|
||||||
- [ ] Add support for setting values in struct (uses second ret val)
|
- [ ] Add support for setting values in struct (uses second ret val)
|
||||||
- [ ] Enums
|
- [ ] Enums
|
||||||
|
- [x] Add support for enums in the parser
|
||||||
- [ ] Add support for enums in the type checker
|
- [ ] Add support for enums in the type checker
|
||||||
- [ ] Add support for enums in the LLVM emitter
|
- [ ] Add support for enums in the LLVM emitter
|
||||||
- [ ] Add support for member accesses in the type checker
|
- [ ] Add support for member accesses in the type checker
|
||||||
- [ ] Add support for member accesses in the LLVM emitter
|
- [ ] Add support for member accesses in the LLVM emitter
|
||||||
- [ ] Unions
|
- [ ] Unions
|
||||||
|
- [ ] Add support for unions in the parser
|
||||||
- [ ] Add support for unions in the type checker
|
- [ ] Add support for unions in the type checker
|
||||||
- [ ] Add support for unions in the LLVM emitter
|
- [ ] Add support for unions in the LLVM emitter
|
||||||
- [ ] Add support for member accesses in the type checker
|
- [ ] Add support for member accesses in the type checker
|
||||||
|
Loading…
x
Reference in New Issue
Block a user