package main import "core:fmt" import "core:c/libc" NodeKind :: enum { Integer, Float, Character, String, Identifier, Block, BinaryExpression, UnaryExpression, FieldAccess, IndexAccess, FunctionCall, Function, Struct, Enum, Union, Use, If, VariableDeclaration, } Node :: struct { kind: NodeKind, range: TextRange, children: [dynamic]^Node, value: TokenValue, value_token_kind: TokenKind, } node_create_value :: proc(kind: NodeKind, range: TextRange, value: TokenValue) -> (ret: ^Node) { ret = new(Node) ret^ = { kind = kind, range = range, value = value, } return } node_create_block :: proc(range: TextRange, children: [dynamic]^Node) -> (ret: ^Node) { ret = new(Node) ret^ = { kind = .Block, range = range, children = children, } return } node_create_binary :: proc(kind: TokenKind, range: TextRange, left: ^Node, right: ^Node) -> (ret: ^Node) { ret = new(Node) ret^ = { kind = .BinaryExpression, range = range, children = { left, right }, value_token_kind = kind, } return } node_create_unary :: proc(kind: TokenKind, range: TextRange, operand: ^Node) -> (ret: ^Node) { ret = new(Node) ret^ = { kind = .UnaryExpression, range = range, children = { operand }, value_token_kind = kind, } return } node_create_field_access :: proc(range: TextRange, left: ^Node, right: ^Node) -> (ret: ^Node) { ret = new(Node) ret^ = { kind = .FieldAccess, range = range, children = { left, right }, } return } node_create_index_access :: proc(range: TextRange, left: ^Node, right: ^Node) -> (ret: ^Node) { ret = new(Node) ret^ = { kind = .IndexAccess, range = range, children = { left, right }, } return } node_create_function_call :: proc(range: TextRange, name: ^Node, args: [dynamic]^Node) -> (ret: ^Node) { ret = new(Node) ret^ = { kind = .FunctionCall, range = range, children = { name }, } for arg in args { append(&ret.children, arg) } return } node_print :: proc(node: ^Node, indent := 0) { for i in 0.. (ret: ^Node) { path_ := path // Check if the path ends with ".cat", if not, append it. len_path := len(path_) if len(path_) < 4 || path_[len_path - 4] != '.' || path_[len_path - 3] != 'c' || path_[len_path - 2] != 'a' || path_[len_path - 1] != 't' { append(&path_, '.') append(&path_, 'c') append(&path_, 'a') append(&path_, 't') } ret = new(Node) ret^ = { kind = .Use, range = range, value = path_, } if len(alias) != 0 { append(&ret.children, node_create_value(.Identifier, range, alias)) } else { // Get the filename, and trucate the extension, then replace any special characters with _ new_alias := [dynamic]u8{} for i in 0.. (ret: ^Node) { ret = new(Node) ret^ = { kind = .If, range = range, children = { condition, then }, } if else_ != nil { append(&ret.children, else_) } return } node_create_variable :: proc(range: TextRange, name, type_, value: ^Node, is_const: bool) -> (ret: ^Node) { ret = new(Node) ret^ = { kind = .VariableDeclaration, range = range, children = { name, type_, value }, value = is_const, } return }