From 5af769acc293e561929337ae3715b8f9f9b31e4e Mon Sep 17 00:00:00 2001 From: uan Date: Thu, 5 Feb 2026 19:40:59 +0100 Subject: [PATCH] struct -> class --- generator.v | 23 +++++------ lexer.v | 6 +-- main.v | 2 +- parser.v | 111 +++++++++++++++++++++++++++++++++------------------- 4 files changed, 86 insertions(+), 56 deletions(-) diff --git a/generator.v b/generator.v index 4ef2b7f..92d9872 100644 --- a/generator.v +++ b/generator.v @@ -9,20 +9,20 @@ mut: } fn mangle_var(name string) string { - return 'one_v${name}' + return 'one_var_${name}' } fn mangle_func(name string) string { if name == 'main' {return 'main'} - return 'one_f${name}' + return 'one_func_${name}' } fn mangle_struct(name string) string { - return 'one_s${name}_' + return 'one_class_${name}_' } fn mangle_if_struct_type(name string) string { - if name[0..6] != 'struct' {return name} + if name.len < 7 || name[0..6] != 'struct' {return name} return 'struct ${mangle_struct(name[7..])}' } @@ -62,7 +62,8 @@ fn (mut g Generator) gen_stmt(stmt Stmt) { g.out.writeln('}') } FuncDecl { - c_type := g.get_c_type(stmt.ret_type) + dump(stmt.ret_type) + c_type := mangle_if_struct_type(g.get_c_type(stmt.ret_type)) g.out.write_string('${c_type} ${mangle_func(stmt.name)}(') for param in stmt.params { g.gen_stmt(param) @@ -74,10 +75,10 @@ fn (mut g Generator) gen_stmt(stmt Stmt) { g.gen_stmt(stmt.block) } Param { - c_type := g.get_c_type(stmt.type) + c_type := mangle_if_struct_type(g.get_c_type(stmt.type)) g.out.write_string('${c_type} ${mangle_var(stmt.name)}') } - StructDecl { + ClassDecl { g.out.writeln('struct ${mangle_struct(stmt.name)} {') for member in stmt.members { g.gen_expr(member) @@ -124,7 +125,7 @@ fn (mut g Generator) gen_expr(expr Expr) { g.out.write_string(')') } TypeCast { - c_type := g.get_c_type(expr.type) + c_type := mangle_if_struct_type(g.get_c_type(expr.type)) g.out.write_string('((${c_type})') g.gen_expr(expr.expr) g.out.write_string(')') @@ -144,11 +145,11 @@ fn (mut g Generator) gen_expr(expr Expr) { } g.out.write_string(')') } - StructMember { - c_type := g.get_c_type(expr.type) + ClassMember { + c_type := mangle_if_struct_type(g.get_c_type(expr.type)) g.out.write_string('${c_type} ${expr.name}') } - StructInstantiation { + ClassInstantiation { g.out.write_string('(struct ${mangle_struct(expr.name)}){') for m_expr in expr.member_values { g.gen_expr(m_expr) diff --git a/lexer.v b/lexer.v index a6edacc..01a9ede 100644 --- a/lexer.v +++ b/lexer.v @@ -13,7 +13,7 @@ enum TokenType as u8 { kw_fn kw_return kw_print - kw_struct + kw_class integer real boolean @@ -104,7 +104,7 @@ fn toktype_from_kw(kw string) TokenType { 'return' {.kw_return} 'true', 'false' {.boolean} 'print' {.kw_print} - 'struct' {.kw_struct} + 'class' {.kw_class} else {.unknown} } } @@ -120,7 +120,7 @@ fn is_real(str string) bool { fn is_keyword(str string) bool { return [ - "void", "int", "real", "bool", "if", "else", "for", "break", "fn", "return", "let", "const", "true", "false", "print", "struct" + "void", "int", "real", "bool", "if", "else", "for", "break", "fn", "return", "let", "const", "true", "false", "print", "class" ].contains(str) } diff --git a/main.v b/main.v index cd1e5c4..12bd216 100644 --- a/main.v +++ b/main.v @@ -31,6 +31,6 @@ fn main() { out_c := generator.gen_c(statements) - compile(out_c, 'exec', true, 'gcc') + compile(out_c, 'exec', true, 'clang') } diff --git a/parser.v b/parser.v index 8ad03df..90bf666 100644 --- a/parser.v +++ b/parser.v @@ -26,7 +26,7 @@ fn (p Parser) get_precedence(tok_type TokenType) Precedence { // ------------------------------------------- Symbol Table -type SymbolInfo = VarSymbolInfo | FuncSymbolInfo | StructTypeSymbolInfo +type SymbolInfo = VarSymbolInfo | FuncSymbolInfo | ClassSymbolInfo struct VarSymbolInfo { type string @@ -37,7 +37,7 @@ struct FuncSymbolInfo { block Block } -struct StructTypeSymbolInfo { +struct ClassSymbolInfo { name string } @@ -45,7 +45,7 @@ struct SymbolTable { mut: variable_scopes []map[string]VarSymbolInfo functions map[string]FuncSymbolInfo - structs map[string]StructTypeSymbolInfo + structs map[string]ClassSymbolInfo } fn (mut s SymbolTable) define_var(name string, typ string) { @@ -90,11 +90,11 @@ fn (mut s SymbolTable) lookup_func(name string) ?FuncSymbolInfo { return none } -fn (mut s SymbolTable) define_struct_type(name string) { - s.structs[name] = StructTypeSymbolInfo{name: name} +fn (mut s SymbolTable) define_class(name string) { + s.structs[name] = ClassSymbolInfo{name: name} } -fn (mut s SymbolTable) lookup_struct_type(name string) ?StructTypeSymbolInfo { +fn (mut s SymbolTable) lookup_class(name string) ?ClassSymbolInfo { if name in s.structs { return s.structs[name] } @@ -108,7 +108,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 | StructMember | StructInstantiation +type Expr = VoidExpr | UnaryExpr | BinaryExpr | IntegerLiteral | RealLiteral | BoolLiteral | Variable | TypeExpr | Function | TypeCast | ParenExpr | PrintExpr | FnCall | ClassMember | ClassInstantiation struct VoidExpr {} @@ -143,12 +143,12 @@ struct TypeExpr { name string } -struct StructMember { +struct ClassMember { name string type string } -struct StructInstantiation { +struct ClassInstantiation { name string member_values []Expr } @@ -178,7 +178,7 @@ struct FnCall { // ------------------------------------------- Statements -type Stmt = VarDecl | ExprStmt | ReturnStmt | Block | FuncDecl | Param | StructDecl +type Stmt = VarDecl | ExprStmt | ReturnStmt | Block | FuncDecl | Param | ClassDecl struct VarDecl { name string @@ -194,9 +194,9 @@ struct FuncDecl { block Block } -struct StructDecl { +struct ClassDecl { name string - members []StructMember + members []ClassMember } struct ExprStmt { @@ -245,6 +245,11 @@ fn (mut p Parser) expect(type TokenType) { p.next() } + +fn (mut p Parser) expect_ident_is_class(ident string) { + if !p.is_ident_class(ident) {panic("Expected type or class type but got identifier")} +} + // ------------------------------------------- Debug fn (mut p Parser) dump_token() { @@ -299,15 +304,15 @@ fn (mut p Parser) parse_expr(prec Precedence) Expr { } fn (mut p Parser) parse_ident(ident string) Expr { - if p.symbols.lookup_struct_type(ident) != none { + if p.symbols.lookup_class(ident) != none { return match p.peek().type { - .lbracket {p.parse_struct_inst(ident)} + .lbracket {p.parse_class_inst(ident)} else {p.parse_type('struct ${ident}')} } } if p.inside_struct { - return p.parse_struct_member(ident) + return p.parse_class_member(ident) } return match p.peek().type { @@ -317,19 +322,25 @@ fn (mut p Parser) parse_ident(ident string) Expr { } } -fn (mut p Parser) parse_struct_member(name string) StructMember { +fn (mut p Parser) parse_class_member(name string) ClassMember { p.expect(.identifier) - if p.peek().type != .type { - dump(p.peek()) - parse_error("Expected type after struct member ${name} in declaration, got ${p.peek().type}") + + type_tok := p.peek() + type_name := match type_tok.type { + .type {type_tok.text} + .identifier { + p.expect_ident_is_class(type_tok.text) + 'struct ${type_tok.text}' + } + else{parse_error("Expected type after class member ${name} in declaration, got ${p.peek().type}")} } - type := p.peek().text - p.expect(.type) + + p.next() p.expect(.semicolon) - return StructMember{name: name, type: type} + return ClassMember{name: name, type: type_name} } -fn (mut p Parser) parse_struct_inst(name string) StructInstantiation { +fn (mut p Parser) parse_class_inst(name string) ClassInstantiation { p.expect(.lbracket) mut member_values := []Expr{} @@ -344,7 +355,7 @@ fn (mut p Parser) parse_struct_inst(name string) StructInstantiation { } } p.expect(.rbracket) - return StructInstantiation{name: name, member_values: member_values} + return ClassInstantiation{name: name, member_values: member_values} } fn (mut p Parser) parse_call(name string) FnCall { @@ -415,6 +426,10 @@ fn (mut p Parser) check_binary_expr_types(expr BinaryExpr) { } } +fn (mut p Parser) is_ident_class(ident string) bool { + return p.symbols.lookup_class(ident) != none +} + fn (mut p Parser) get_expr_type(expr Expr) string { return match expr { ParenExpr {p.get_expr_type(expr.expr)} @@ -422,6 +437,7 @@ fn (mut p Parser) get_expr_type(expr Expr) string { RealLiteral {'real'} BoolLiteral {'bool'} VoidExpr {'void'} + TypeExpr {expr.name} BinaryExpr { p.check_binary_expr_types(expr) left_t := p.get_expr_type(expr.left) @@ -443,7 +459,7 @@ 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 } - StructInstantiation {expr.name} + ClassInstantiation {expr.name} else {"Tried getting type of unexpected Expr"} } } @@ -477,11 +493,11 @@ fn (mut p Parser) get_return_stmts_recursive(block Block) []ReturnStmt { fn (mut p Parser) parse_statement() Stmt { match p.peek().type { .kw_let {return p.parse_var_decl(false)} - .kw_const {return p.parse_var_decl(true)} + .kw_const {return p.parse_var_decl(true)} .kw_return {return p.parse_return_stmt()} .kw_fn {return p.parse_func_decl()} .lbracket {return p.parse_block(false)} - .kw_struct {return p.parse_struct()} + .kw_class {return p.parse_class()} else {return p.parse_expr_stmt()} } } @@ -498,9 +514,7 @@ fn (mut p Parser) parse_var_decl(is_const bool) VarDecl { type_name := match type_tok.type { .type {type_tok.text} .identifier { - if p.symbols.lookup_struct_type(type_tok.text) == none { - parse_error("Expected variable type after name when declaring ${name_tok.text}") - } + p.expect_ident_is_class(type_tok.text) 'struct ${type_tok.text}' } else{parse_error("Expected variable type after name when declaring ${name_tok.text}")} @@ -548,8 +562,18 @@ fn (mut p Parser) parse_func_decl() FuncDecl { for { if p.peek().type != .identifier {parse_error("Invalid syntax to declare function arguments! use f(myint int, myreal real)")} p_name := p.next().text - if p.peek().type != .type {parse_error("Invalid syntax to declare function arguments! use f(myint int, myreal real)")} - p_type := p.next().text + //if p.peek().type != .type {parse_error("Invalid syntax to declare function arguments! use f(myint int, myreal real)")} + + type_tok := p.peek() + p_type := match type_tok.type { + .type {type_tok.text} + .identifier { + p.expect_ident_is_class(type_tok.text) + 'struct ${type_tok.text}' + } + else{parse_error("Expected argument type after name when declaring ${p_name}")} + } + p.next() params << Param{p_name, p_type} p.symbols.define_var(p_name, p_type) @@ -566,8 +590,13 @@ fn (mut p Parser) parse_func_decl() FuncDecl { p.dump_token() type_tok := p.next() - if type_tok.type != .type { - parse_error("Expected function return type after name when declaring ${name_tok.text}") + ret_type := match type_tok.type { + .type {type_tok.text} + .identifier { + p.expect_ident_is_class(type_tok.text) + 'struct ${type_tok.text}' + } + else{parse_error("Expected function return type after name when declaring ${name_tok.text}")} } block := p.parse_block(true) @@ -587,24 +616,24 @@ fn (mut p Parser) parse_func_decl() FuncDecl { return FuncDecl { name: name_tok.text - ret_type: type_tok.text + ret_type: ret_type block: block params: params } } -fn (mut p Parser) parse_struct() StructDecl { - p.expect(.kw_struct) +fn (mut p Parser) parse_class() ClassDecl { + p.expect(.kw_class) name := p.peek().text p.expect(.identifier) p.expect(.lbracket) - mut members := []StructMember{} + mut members := []ClassMember{} for p.peek().type == .identifier { - members << p.parse_struct_member(p.peek().text) + members << p.parse_class_member(p.peek().text) } p.expect(.rbracket) - p.symbols.define_struct_type(name) - return StructDecl{name: name, members: members} + p.symbols.define_class(name) + return ClassDecl{name: name, members: members} } fn (mut p Parser) parse_return_stmt() ReturnStmt {