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 {
|
||||
x y: f32,
|
||||
enum MyEnum {
|
||||
EnumItem1,
|
||||
EnumItem2 = 1,
|
||||
EnumItem3,
|
||||
EnumItem4,
|
||||
}
|
||||
|
||||
struct Rect {
|
||||
pos size: Vec2,
|
||||
enum MyTypedEnum : i8 {
|
||||
EnumItem1,
|
||||
EnumItem2,
|
||||
EnumItem3 = 105,
|
||||
EnumItem4,
|
||||
}
|
||||
|
||||
let CONSTPOS :: .Vec2 {20.0 20.0}
|
||||
let CONSTSZ :: .Vec2 {100.0 100.0}
|
||||
let CONST :: .Rect {(CONSTPOS) (CONSTSZ)}
|
||||
|
||||
\ FIXME: LLVM IR geneartion is borked
|
||||
\ let CONST :: .Rect { .Vec2 { 20.0 20.0 } .Vec2 { 100.0 100.0 } }
|
||||
|
||||
struct Color {
|
||||
r g b a: u8,
|
||||
}
|
||||
|
||||
let KEY_R :: 82
|
||||
|
||||
fn InitWindow(w h: i32, title: []u8)
|
||||
fn CloseWindow
|
||||
fn BeginDrawing
|
||||
fn SetTargetFPS(fps: i32)
|
||||
fn EndDrawing
|
||||
fn DrawFPS(x y: i32)
|
||||
fn WindowShouldClose i32
|
||||
fn TextSubtext(text: []u8, start end: i32) []u8
|
||||
fn IsKeyPressed(key: i32) u1
|
||||
|
||||
struct Rectangle {
|
||||
x y w h: f32,
|
||||
}
|
||||
|
||||
fn ColorToRaylib(c: Color) u32 {
|
||||
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 ClearBackgroundWrap(c: Color) {
|
||||
fn ClearBackground(c: u32)
|
||||
ClearBackground (ColorToRaylib c)
|
||||
}
|
||||
|
||||
fn DrawRectangleWrap(x y w h: i32, c: Color) {
|
||||
fn DrawRectangle(x y w h: i32, c: u32)
|
||||
DrawRectangle x y w h (ColorToRaylib c)
|
||||
}
|
||||
|
||||
fn DrawCircleWrap(x y: i32, r: f32, c: Color) {
|
||||
fn DrawCircle(x y: i32, r: f32, c: u32)
|
||||
DrawCircle x y r (ColorToRaylib c)
|
||||
}
|
||||
|
||||
fn DrawRectangleRecWrap(r: Rectangle, c: Color) {
|
||||
fn DrawRectangleRec(r: Rectangle, c: u32)
|
||||
DrawRectangleRec r (ColorToRaylib c)
|
||||
}
|
||||
|
||||
fn DrawTextWrap(text: []u8, x y size: i32, c: Color) {
|
||||
fn DrawText(text: []u8, x y size: i32, c: u32)
|
||||
DrawText text x y size (ColorToRaylib c)
|
||||
}
|
||||
|
||||
let WHITE :: .Color {255 255 255 255}
|
||||
let BLACK :: .Color {0 0 0 255}
|
||||
let RED :: .Color {255 0 0 255}
|
||||
let BLUE :: .Color {0 0 255 255}
|
||||
|
||||
InitWindow 800 450 Raylib
|
||||
SetTargetFPS 60
|
||||
|
||||
fn GetScreenWidth i32
|
||||
fn GetScreenHeight i32
|
||||
|
||||
fn DrawRect(rect: Rect, c: Color) {
|
||||
DrawRectangleWrap (rect.pos.x as i32) (rect.pos.y as i32) (rect.size.x as i32) (rect.size.y as i32) c
|
||||
}
|
||||
|
||||
let logox := GetScreenWidth / 2 - 128
|
||||
let logoy := GetScreenHeight / 2 - 128
|
||||
|
||||
\ FIXME: Cannot inline
|
||||
let fc := 0
|
||||
let lc := 0
|
||||
let top_side_rec_width := 16
|
||||
let left_side_rec_height := 16
|
||||
let bottom_side_rec_width := 16
|
||||
let right_side_rec_height := 16
|
||||
|
||||
let state := 0
|
||||
let alpha := 1.0
|
||||
|
||||
for WindowShouldClose == 0 {
|
||||
if state == 0 {
|
||||
if ++fc == 120 {
|
||||
state = 1
|
||||
fc = 0
|
||||
}
|
||||
} elif state == 1 {
|
||||
top_side_rec_width = top_side_rec_width + 4
|
||||
left_side_rec_height = left_side_rec_height + 4
|
||||
|
||||
if top_side_rec_width == 256 {
|
||||
state = 2
|
||||
}
|
||||
} elif state == 2 {
|
||||
bottom_side_rec_width = bottom_side_rec_width + 4
|
||||
right_side_rec_height = right_side_rec_height + 4
|
||||
|
||||
if bottom_side_rec_width == 256 {
|
||||
state = 3
|
||||
}
|
||||
} elif state == 3 {
|
||||
if ++fc / 12 != 0 {
|
||||
++lc
|
||||
fc = 0
|
||||
}
|
||||
|
||||
if lc >= 10 {
|
||||
alpha = alpha - 0.01
|
||||
if alpha <= 0.0 {
|
||||
alpha = 0.0
|
||||
state = 4
|
||||
}
|
||||
}
|
||||
} elif IsKeyPressed(KEY_R) { \
|
||||
fc = lc = 0
|
||||
|
||||
top_side_rec_width = 16
|
||||
left_side_rec_height = 16
|
||||
bottom_side_rec_width = 16
|
||||
right_side_rec_height = 16
|
||||
|
||||
state = 0
|
||||
alpha = 1.0
|
||||
}
|
||||
|
||||
BeginDrawing
|
||||
ClearBackgroundWrap WHITE
|
||||
DrawFPS 20 20
|
||||
|
||||
DrawRect CONST RED
|
||||
|
||||
if state == 0 {
|
||||
if (fc/15)%2 != 0 {
|
||||
DrawRectangleWrap logox logoy 16 16 BLACK
|
||||
}
|
||||
} elif state == 1 {
|
||||
DrawRectangleWrap logox logoy top_side_rec_width 16 BLACK
|
||||
DrawRectangleWrap logox logoy 16 left_side_rec_height BLACK
|
||||
} elif state == 2 {
|
||||
DrawRectangleWrap logox logoy top_side_rec_width 16 BLACK
|
||||
DrawRectangleWrap logox logoy 16 left_side_rec_height BLACK
|
||||
|
||||
DrawRectangleWrap logox+240 logoy 16 right_side_rec_height BLACK
|
||||
DrawRectangleWrap logox logoy+240 bottom_side_rec_width 16 BLACK
|
||||
} elif state == 3 {
|
||||
let colorw := .Color{255 255 255 (alpha*255.0) as u8}
|
||||
let colorb := .Color{0 0 0 (alpha*255.0) as u8}
|
||||
\ FIXME: ADD field access assignment
|
||||
\color.a = (alpha * 255.0) as u8
|
||||
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 16 right_side_rec_height-32 cbolor
|
||||
DrawRectangleWrap logox logoy+240 bottom_side_rec_width 16 colorb
|
||||
|
||||
DrawRectangleWrap GetScreenWidth/2-112 GetScreenHeight/2-112 224 224 colorw
|
||||
|
||||
DrawTextWrap (TextSubtext raylib 0 lc) GetScreenWidth/2-44 GetScreenHeight/2+48 50 colorb
|
||||
} else {
|
||||
DrawTextWrap "[R] REPLAY" 340 200 20 BLACK
|
||||
}
|
||||
|
||||
EndDrawing
|
||||
}
|
||||
CloseWindow
|
||||
|
||||
\struct Vec2 {
|
||||
\ x y: f32,
|
||||
\}
|
||||
\
|
||||
\struct Rect {
|
||||
\ pos size: Vec2,
|
||||
\}
|
||||
\
|
||||
\let CONSTPOS :: .Vec2 {20.0 20.0}
|
||||
\let CONSTSZ :: .Vec2 {100.0 100.0}
|
||||
\let CONST :: .Rect {(CONSTPOS) (CONSTSZ)}
|
||||
\
|
||||
\\ FIXME: LLVM IR geneartion is borked
|
||||
\\ let CONST :: .Rect { .Vec2 { 20.0 20.0 } .Vec2 { 100.0 100.0 } }
|
||||
\
|
||||
\struct Color {
|
||||
\ r g b a: u8,
|
||||
\}
|
||||
\
|
||||
\let KEY_R :: 82
|
||||
\
|
||||
\fn InitWindow(w h: i32, title: []u8)
|
||||
\fn CloseWindow
|
||||
\fn BeginDrawing
|
||||
\fn SetTargetFPS(fps: i32)
|
||||
\fn EndDrawing
|
||||
\fn DrawFPS(x y: i32)
|
||||
\fn WindowShouldClose i32
|
||||
\fn TextSubtext(text: []u8, start end: i32) []u8
|
||||
\fn IsKeyPressed(key: i32) u1
|
||||
\
|
||||
\struct Rectangle {
|
||||
\ x y w h: f32,
|
||||
\}
|
||||
\
|
||||
\fn ColorToRaylib(c: Color) u32 {
|
||||
\ 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 ClearBackgroundWrap(c: Color) {
|
||||
\ fn ClearBackground(c: u32)
|
||||
\ ClearBackground (ColorToRaylib c)
|
||||
\}
|
||||
\
|
||||
\fn DrawRectangleWrap(x y w h: i32, c: Color) {
|
||||
\ fn DrawRectangle(x y w h: i32, c: u32)
|
||||
\ DrawRectangle x y w h (ColorToRaylib c)
|
||||
\}
|
||||
\
|
||||
\fn DrawCircleWrap(x y: i32, r: f32, c: Color) {
|
||||
\ fn DrawCircle(x y: i32, r: f32, c: u32)
|
||||
\ DrawCircle x y r (ColorToRaylib c)
|
||||
\}
|
||||
\
|
||||
\fn DrawRectangleRecWrap(r: Rectangle, c: Color) {
|
||||
\ fn DrawRectangleRec(r: Rectangle, c: u32)
|
||||
\ DrawRectangleRec r (ColorToRaylib c)
|
||||
\}
|
||||
\
|
||||
\fn DrawTextWrap(text: []u8, x y size: i32, c: Color) {
|
||||
\ fn DrawText(text: []u8, x y size: i32, c: u32)
|
||||
\ DrawText text x y size (ColorToRaylib c)
|
||||
\}
|
||||
\
|
||||
\let WHITE :: .Color {255 255 255 255}
|
||||
\let BLACK :: .Color {0 0 0 255}
|
||||
\let RED :: .Color {255 0 0 255}
|
||||
\let BLUE :: .Color {0 0 255 255}
|
||||
\
|
||||
\InitWindow 800 450 Raylib
|
||||
\SetTargetFPS 60
|
||||
\
|
||||
\fn GetScreenWidth i32
|
||||
\fn GetScreenHeight i32
|
||||
\
|
||||
\fn DrawRect(rect: Rect, c: Color) {
|
||||
\ DrawRectangleWrap (rect.pos.x as i32) (rect.pos.y as i32) (rect.size.x as i32) (rect.size.y as i32) c
|
||||
\}
|
||||
\
|
||||
\let logox := GetScreenWidth / 2 - 128
|
||||
\let logoy := GetScreenHeight / 2 - 128
|
||||
\
|
||||
\\ FIXME: Cannot inline
|
||||
\let fc := 0
|
||||
\let lc := 0
|
||||
\let top_side_rec_width := 16
|
||||
\let left_side_rec_height := 16
|
||||
\let bottom_side_rec_width := 16
|
||||
\let right_side_rec_height := 16
|
||||
\
|
||||
\let state := 0
|
||||
\let alpha := 1.0
|
||||
\
|
||||
\for WindowShouldClose == 0 {
|
||||
\ if state == 0 {
|
||||
\ if ++fc == 120 {
|
||||
\ state = 1
|
||||
\ fc = 0
|
||||
\ }
|
||||
\ } elif state == 1 {
|
||||
\ top_side_rec_width = top_side_rec_width + 4
|
||||
\ left_side_rec_height = left_side_rec_height + 4
|
||||
\
|
||||
\ if top_side_rec_width == 256 {
|
||||
\ state = 2
|
||||
\ }
|
||||
\ } elif state == 2 {
|
||||
\ bottom_side_rec_width = bottom_side_rec_width + 4
|
||||
\ right_side_rec_height = right_side_rec_height + 4
|
||||
\
|
||||
\ if bottom_side_rec_width == 256 {
|
||||
\ state = 3
|
||||
\ }
|
||||
\ } elif state == 3 {
|
||||
\ if ++fc / 12 != 0 {
|
||||
\ ++lc
|
||||
\ fc = 0
|
||||
\ }
|
||||
\
|
||||
\ if lc >= 10 {
|
||||
\ alpha = alpha - 0.01
|
||||
\ if alpha <= 0.0 {
|
||||
\ alpha = 0.0
|
||||
\ state = 4
|
||||
\ }
|
||||
\ }
|
||||
\ } elif IsKeyPressed(KEY_R) { \
|
||||
\ fc = lc = 0
|
||||
\
|
||||
\ top_side_rec_width = 16
|
||||
\ left_side_rec_height = 16
|
||||
\ bottom_side_rec_width = 16
|
||||
\ right_side_rec_height = 16
|
||||
\
|
||||
\ state = 0
|
||||
\ alpha = 1.0
|
||||
\ }
|
||||
\
|
||||
\ BeginDrawing
|
||||
\ ClearBackgroundWrap WHITE
|
||||
\ DrawFPS 20 20
|
||||
\
|
||||
\ DrawRect CONST RED
|
||||
\
|
||||
\ if state == 0 {
|
||||
\ if (fc/15)%2 != 0 {
|
||||
\ DrawRectangleWrap logox logoy 16 16 BLACK
|
||||
\ }
|
||||
\ } elif state == 1 {
|
||||
\ DrawRectangleWrap logox logoy top_side_rec_width 16 BLACK
|
||||
\ DrawRectangleWrap logox logoy 16 left_side_rec_height BLACK
|
||||
\ } elif state == 2 {
|
||||
\ DrawRectangleWrap logox logoy top_side_rec_width 16 BLACK
|
||||
\ DrawRectangleWrap logox logoy 16 left_side_rec_height BLACK
|
||||
\
|
||||
\ DrawRectangleWrap logox+240 logoy 16 right_side_rec_height BLACK
|
||||
\ DrawRectangleWrap logox logoy+240 bottom_side_rec_width 16 BLACK
|
||||
\ } elif state == 3 {
|
||||
\ let colorw := .Color{255 255 255 (alpha*255.0) as u8}
|
||||
\ let colorb := .Color{0 0 0 (alpha*255.0) as u8}
|
||||
\ \ FIXME: ADD field access assignment
|
||||
\ \color.a = (alpha * 255.0) as u8
|
||||
\ 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 16 right_side_rec_height-32 cbolor
|
||||
\ DrawRectangleWrap logox logoy+240 bottom_side_rec_width 16 colorb
|
||||
\
|
||||
\ DrawRectangleWrap GetScreenWidth/2-112 GetScreenHeight/2-112 224 224 colorw
|
||||
\
|
||||
\ DrawTextWrap (TextSubtext raylib 0 lc) GetScreenWidth/2-44 GetScreenHeight/2+48 50 colorb
|
||||
\ } else {
|
||||
\ DrawTextWrap "[R] REPLAY" 340 200 20 BLACK
|
||||
\ }
|
||||
\
|
||||
\ EndDrawing
|
||||
\}
|
||||
\CloseWindow
|
||||
\
|
||||
|
46
src/ast.odin
46
src/ast.odin
@ -47,6 +47,18 @@ NodeKind :: enum {
|
||||
// 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 {
|
||||
kind: NodeKind,
|
||||
range: SourceLocation,
|
||||
@ -54,6 +66,7 @@ Node :: struct {
|
||||
value: TokenValue,
|
||||
value_token_kind: TokenKind,
|
||||
return_type: ^Type,
|
||||
enum_value: EnumValue,
|
||||
}
|
||||
|
||||
node_create_value :: proc(kind: NodeKind, range: SourceLocation, value: TokenValue) -> (ret: ^Node) {
|
||||
@ -223,8 +236,26 @@ node_print :: proc(node: ^Node, indent := 0) {
|
||||
}
|
||||
fmt.println("")
|
||||
|
||||
for child in node.children {
|
||||
node_print(child, indent + 1)
|
||||
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 {
|
||||
node_print(child, indent + 1)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -380,7 +411,7 @@ node_create_struct_initializer :: proc(
|
||||
return
|
||||
}
|
||||
|
||||
node_create_struct_enum_or_union :: proc(
|
||||
node_create_struct_or_union :: proc(
|
||||
range: SourceLocation,
|
||||
kind: NodeKind,
|
||||
name: [dynamic]u8,
|
||||
@ -401,6 +432,15 @@ node_create_struct_enum_or_union :: proc(
|
||||
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) {
|
||||
ret = new(Node)
|
||||
ret^ = node^
|
||||
|
@ -46,52 +46,54 @@ main :: proc() {
|
||||
os.exit(1)
|
||||
}
|
||||
}
|
||||
clear(&g_message_list)
|
||||
type_check(ast, nil)
|
||||
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
|
||||
}
|
||||
}
|
||||
if contains_errors {
|
||||
os.exit(1)
|
||||
}
|
||||
}
|
||||
//clear(&g_message_list)
|
||||
//type_check(ast, nil)
|
||||
//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
|
||||
// }
|
||||
// }
|
||||
// if contains_errors {
|
||||
// os.exit(1)
|
||||
// }
|
||||
//}
|
||||
|
||||
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)
|
||||
node_print(ast)
|
||||
|
||||
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)
|
||||
// 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) {
|
||||
|
@ -154,7 +154,7 @@ parser_parse_struct_definition :: proc(parser: ^Parser) -> ^Node {
|
||||
expect(parser, .OpenBrace)
|
||||
fields := parser_parse_definitions(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
|
||||
return n
|
||||
}
|
||||
@ -163,7 +163,86 @@ parser_parse_struct_definition :: proc(parser: ^Parser) -> ^Node {
|
||||
parser_parse_enum_definition :: proc(parser: ^Parser) -> ^Node {
|
||||
range := parser.tok.range
|
||||
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")
|
||||
@ -180,7 +259,7 @@ parser_parse_union_definition :: proc(parser: ^Parser) -> ^Node {
|
||||
expect(parser, .OpenBrace)
|
||||
fields := parser_parse_definitions(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")
|
||||
|
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 setting values in struct (uses second ret val)
|
||||
- [ ] Enums
|
||||
- [x] Add support for enums in the parser
|
||||
- [ ] Add support for enums in the type checker
|
||||
- [ ] Add support for enums in the LLVM emitter
|
||||
- [ ] Add support for member accesses in the type checker
|
||||
- [ ] Add support for member accesses in the LLVM emitter
|
||||
- [ ] Unions
|
||||
- [ ] Add support for unions in the parser
|
||||
- [ ] Add support for unions in the type checker
|
||||
- [ ] Add support for unions in the LLVM emitter
|
||||
- [ ] Add support for member accesses in the type checker
|
||||
|
Loading…
x
Reference in New Issue
Block a user