way better prints yay

This commit is contained in:
uan
2026-02-05 21:48:44 +01:00
parent 5af769acc2
commit 078a300c1f
4 changed files with 135 additions and 33 deletions

View File

@@ -12,6 +12,7 @@ enum Precedence {
product // *, /
prefix // -x, !x
call // function()
access // .
}
fn (p Parser) get_precedence(tok_type TokenType) Precedence {
@@ -20,6 +21,7 @@ fn (p Parser) get_precedence(tok_type TokenType) Precedence {
.eq_eq, .not_eq, .less_eq, .greater_eq { .comparison }
.plus, .minus { .sum }
.star, .slash { .product }
.dot { .access }
else { .lowest }
}
}
@@ -39,6 +41,7 @@ struct FuncSymbolInfo {
struct ClassSymbolInfo {
name string
members_info map[string]VarSymbolInfo
}
struct SymbolTable {
@@ -90,8 +93,12 @@ fn (mut s SymbolTable) lookup_func(name string) ?FuncSymbolInfo {
return none
}
fn (mut s SymbolTable) define_class(name string) {
s.structs[name] = ClassSymbolInfo{name: name}
fn (mut s SymbolTable) define_class(name string, members []ClassMember) {
mut members_info := map[string]VarSymbolInfo{}
for member in members {
members_info[member.name] = VarSymbolInfo{member.type}
}
s.structs[name] = ClassSymbolInfo{name: name, members_info: members_info}
}
fn (mut s SymbolTable) lookup_class(name string) ?ClassSymbolInfo {
@@ -108,7 +115,7 @@ fn (mut s SymbolTable) is_in_global_scope() bool {
// ------------------------------------------- Expressions
type Expr = VoidExpr | UnaryExpr | BinaryExpr | IntegerLiteral | RealLiteral | BoolLiteral | Variable | TypeExpr | Function | TypeCast | ParenExpr | PrintExpr | FnCall | ClassMember | ClassInstantiation
type Expr = VoidExpr | UnaryExpr | BinaryExpr | IntegerLiteral | RealLiteral | BoolLiteral | Variable | TypeExpr | Function | TypeCast | ParenExpr | PrintExpr | FnCall | ClassMember | ClassInstantiation | MemberAccess
struct VoidExpr {}
@@ -148,6 +155,11 @@ struct ClassMember {
type string
}
struct MemberAccess {
from Expr
member string
}
struct ClassInstantiation {
name string
member_values []Expr
@@ -295,9 +307,16 @@ fn (mut p Parser) parse_primary() Expr {
fn (mut p Parser) parse_expr(prec Precedence) Expr {
mut expr := p.parse_primary()
for int(prec) < int(p.get_precedence(p.peek().type)) {
op_tok := p.next()
expr = p.parse_binary(expr, op_tok.text, p.get_precedence(op_tok.type))
if op_tok.type == .dot {
expr = p.parse_member_access(expr)
} else {
expr = p.parse_binary(expr, op_tok.text, p.get_precedence(op_tok.type))
}
}
return expr
@@ -307,7 +326,7 @@ fn (mut p Parser) parse_ident(ident string) Expr {
if p.symbols.lookup_class(ident) != none {
return match p.peek().type {
.lbracket {p.parse_class_inst(ident)}
else {p.parse_type('struct ${ident}')}
else {p.parse_type('${ident}')}
}
}
@@ -322,6 +341,12 @@ fn (mut p Parser) parse_ident(ident string) Expr {
}
}
fn (mut p Parser) parse_member_access(from Expr) MemberAccess {
member_tok := p.next()
if member_tok.type != .identifier {parse_error("Expected identifier after member access")}
return MemberAccess {from: from, member: member_tok.text}
}
fn (mut p Parser) parse_class_member(name string) ClassMember {
p.expect(.identifier)
@@ -330,7 +355,7 @@ fn (mut p Parser) parse_class_member(name string) ClassMember {
.type {type_tok.text}
.identifier {
p.expect_ident_is_class(type_tok.text)
'struct ${type_tok.text}'
type_tok.text
}
else{parse_error("Expected type after class member ${name} in declaration, got ${p.peek().type}")}
}
@@ -448,7 +473,6 @@ fn (mut p Parser) get_expr_type(expr Expr) string {
}
}
Variable {
p.dump_stmt()
info := p.symbols.lookup_var(expr.name) or {
parse_error("Undefined variable ${expr.name}")
}
@@ -459,6 +483,15 @@ fn (mut p Parser) get_expr_type(expr Expr) string {
fninfo := p.symbols.lookup_func(expr.name) or {parse_error("Tried to call undefined function ${expr.name}")}
fninfo.type
}
MemberAccess {
mut type_from := p.get_expr_type(expr.from)
classinfo := p.symbols.lookup_class(type_from)or{parse_error("Non-existant class ${type_from}")}
if expr.member in classinfo.members_info {
classinfo.members_info[expr.member].type
} else {
parse_error("Undefined class member ${expr.member}")
}
}
ClassInstantiation {expr.name}
else {"Tried getting type of unexpected Expr"}
}
@@ -515,7 +548,7 @@ fn (mut p Parser) parse_var_decl(is_const bool) VarDecl {
.type {type_tok.text}
.identifier {
p.expect_ident_is_class(type_tok.text)
'struct ${type_tok.text}'
type_tok.text
}
else{parse_error("Expected variable type after name when declaring ${name_tok.text}")}
}
@@ -569,7 +602,7 @@ fn (mut p Parser) parse_func_decl() FuncDecl {
.type {type_tok.text}
.identifier {
p.expect_ident_is_class(type_tok.text)
'struct ${type_tok.text}'
type_tok.text
}
else{parse_error("Expected argument type after name when declaring ${p_name}")}
}
@@ -594,7 +627,7 @@ fn (mut p Parser) parse_func_decl() FuncDecl {
.type {type_tok.text}
.identifier {
p.expect_ident_is_class(type_tok.text)
'struct ${type_tok.text}'
type_tok.text
}
else{parse_error("Expected function return type after name when declaring ${name_tok.text}")}
}
@@ -632,7 +665,7 @@ fn (mut p Parser) parse_class() ClassDecl {
members << p.parse_class_member(p.peek().text)
}
p.expect(.rbracket)
p.symbols.define_class(name)
p.symbols.define_class(name, members)
return ClassDecl{name: name, members: members}
}
@@ -697,7 +730,7 @@ fn (mut p Parser) parse_block(no_scope bool) Block {
}
fn (mut p Parser) parse_program() []Stmt {
fn (mut p Parser) parse_program() ([]Stmt, SymbolTable) {
p.symbols.variable_scopes << map[string]VarSymbolInfo{}
for p.peek().type != .eof {
p.statements << p.parse_statement()
@@ -706,7 +739,7 @@ fn (mut p Parser) parse_program() []Stmt {
$if debug {
dump(p.symbols.functions)
}
return p.statements
return p.statements, p.symbols
}