struct -> class

This commit is contained in:
uan
2026-02-05 19:40:59 +01:00
parent 0d5cc35b5a
commit 5af769acc2
4 changed files with 86 additions and 56 deletions

View File

@@ -9,20 +9,20 @@ mut:
} }
fn mangle_var(name string) string { fn mangle_var(name string) string {
return 'one_v${name}' return 'one_var_${name}'
} }
fn mangle_func(name string) string { fn mangle_func(name string) string {
if name == 'main' {return 'main'} if name == 'main' {return 'main'}
return 'one_f${name}' return 'one_func_${name}'
} }
fn mangle_struct(name string) string { fn mangle_struct(name string) string {
return 'one_s${name}_' return 'one_class_${name}_'
} }
fn mangle_if_struct_type(name string) string { 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..])}' return 'struct ${mangle_struct(name[7..])}'
} }
@@ -62,7 +62,8 @@ fn (mut g Generator) gen_stmt(stmt Stmt) {
g.out.writeln('}') g.out.writeln('}')
} }
FuncDecl { 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)}(') g.out.write_string('${c_type} ${mangle_func(stmt.name)}(')
for param in stmt.params { for param in stmt.params {
g.gen_stmt(param) g.gen_stmt(param)
@@ -74,10 +75,10 @@ fn (mut g Generator) gen_stmt(stmt Stmt) {
g.gen_stmt(stmt.block) g.gen_stmt(stmt.block)
} }
Param { 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)}') g.out.write_string('${c_type} ${mangle_var(stmt.name)}')
} }
StructDecl { ClassDecl {
g.out.writeln('struct ${mangle_struct(stmt.name)} {') g.out.writeln('struct ${mangle_struct(stmt.name)} {')
for member in stmt.members { for member in stmt.members {
g.gen_expr(member) g.gen_expr(member)
@@ -124,7 +125,7 @@ fn (mut g Generator) gen_expr(expr Expr) {
g.out.write_string(')') g.out.write_string(')')
} }
TypeCast { 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.out.write_string('((${c_type})')
g.gen_expr(expr.expr) g.gen_expr(expr.expr)
g.out.write_string(')') g.out.write_string(')')
@@ -144,11 +145,11 @@ fn (mut g Generator) gen_expr(expr Expr) {
} }
g.out.write_string(')') g.out.write_string(')')
} }
StructMember { ClassMember {
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} ${expr.name}') g.out.write_string('${c_type} ${expr.name}')
} }
StructInstantiation { ClassInstantiation {
g.out.write_string('(struct ${mangle_struct(expr.name)}){') g.out.write_string('(struct ${mangle_struct(expr.name)}){')
for m_expr in expr.member_values { for m_expr in expr.member_values {
g.gen_expr(m_expr) g.gen_expr(m_expr)

View File

@@ -13,7 +13,7 @@ enum TokenType as u8 {
kw_fn kw_fn
kw_return kw_return
kw_print kw_print
kw_struct kw_class
integer integer
real real
boolean boolean
@@ -104,7 +104,7 @@ fn toktype_from_kw(kw string) TokenType {
'return' {.kw_return} 'return' {.kw_return}
'true', 'false' {.boolean} 'true', 'false' {.boolean}
'print' {.kw_print} 'print' {.kw_print}
'struct' {.kw_struct} 'class' {.kw_class}
else {.unknown} else {.unknown}
} }
} }
@@ -120,7 +120,7 @@ fn is_real(str string) bool {
fn is_keyword(str string) bool { fn is_keyword(str string) bool {
return [ 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) ].contains(str)
} }

2
main.v
View File

@@ -31,6 +31,6 @@ fn main() {
out_c := generator.gen_c(statements) out_c := generator.gen_c(statements)
compile(out_c, 'exec', true, 'gcc') compile(out_c, 'exec', true, 'clang')
} }

111
parser.v
View File

@@ -26,7 +26,7 @@ fn (p Parser) get_precedence(tok_type TokenType) Precedence {
// ------------------------------------------- Symbol Table // ------------------------------------------- Symbol Table
type SymbolInfo = VarSymbolInfo | FuncSymbolInfo | StructTypeSymbolInfo type SymbolInfo = VarSymbolInfo | FuncSymbolInfo | ClassSymbolInfo
struct VarSymbolInfo { struct VarSymbolInfo {
type string type string
@@ -37,7 +37,7 @@ struct FuncSymbolInfo {
block Block block Block
} }
struct StructTypeSymbolInfo { struct ClassSymbolInfo {
name string name string
} }
@@ -45,7 +45,7 @@ struct SymbolTable {
mut: mut:
variable_scopes []map[string]VarSymbolInfo variable_scopes []map[string]VarSymbolInfo
functions map[string]FuncSymbolInfo functions map[string]FuncSymbolInfo
structs map[string]StructTypeSymbolInfo structs map[string]ClassSymbolInfo
} }
fn (mut s SymbolTable) define_var(name string, typ string) { 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 return none
} }
fn (mut s SymbolTable) define_struct_type(name string) { fn (mut s SymbolTable) define_class(name string) {
s.structs[name] = StructTypeSymbolInfo{name: name} 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 { if name in s.structs {
return s.structs[name] return s.structs[name]
} }
@@ -108,7 +108,7 @@ fn (mut s SymbolTable) is_in_global_scope() bool {
// ------------------------------------------- Expressions // ------------------------------------------- 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 {} struct VoidExpr {}
@@ -143,12 +143,12 @@ struct TypeExpr {
name string name string
} }
struct StructMember { struct ClassMember {
name string name string
type string type string
} }
struct StructInstantiation { struct ClassInstantiation {
name string name string
member_values []Expr member_values []Expr
} }
@@ -178,7 +178,7 @@ struct FnCall {
// ------------------------------------------- Statements // ------------------------------------------- Statements
type Stmt = VarDecl | ExprStmt | ReturnStmt | Block | FuncDecl | Param | StructDecl type Stmt = VarDecl | ExprStmt | ReturnStmt | Block | FuncDecl | Param | ClassDecl
struct VarDecl { struct VarDecl {
name string name string
@@ -194,9 +194,9 @@ struct FuncDecl {
block Block block Block
} }
struct StructDecl { struct ClassDecl {
name string name string
members []StructMember members []ClassMember
} }
struct ExprStmt { struct ExprStmt {
@@ -245,6 +245,11 @@ fn (mut p Parser) expect(type TokenType) {
p.next() 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 // ------------------------------------------- Debug
fn (mut p Parser) dump_token() { 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 { 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 { return match p.peek().type {
.lbracket {p.parse_struct_inst(ident)} .lbracket {p.parse_class_inst(ident)}
else {p.parse_type('struct ${ident}')} else {p.parse_type('struct ${ident}')}
} }
} }
if p.inside_struct { if p.inside_struct {
return p.parse_struct_member(ident) return p.parse_class_member(ident)
} }
return match p.peek().type { 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) p.expect(.identifier)
if p.peek().type != .type {
dump(p.peek()) type_tok := p.peek()
parse_error("Expected type after struct member ${name} in declaration, got ${p.peek().type}") 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) 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) p.expect(.lbracket)
mut member_values := []Expr{} mut member_values := []Expr{}
@@ -344,7 +355,7 @@ fn (mut p Parser) parse_struct_inst(name string) StructInstantiation {
} }
} }
p.expect(.rbracket) 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 { 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 { fn (mut p Parser) get_expr_type(expr Expr) string {
return match expr { return match expr {
ParenExpr {p.get_expr_type(expr.expr)} ParenExpr {p.get_expr_type(expr.expr)}
@@ -422,6 +437,7 @@ fn (mut p Parser) get_expr_type(expr Expr) string {
RealLiteral {'real'} RealLiteral {'real'}
BoolLiteral {'bool'} BoolLiteral {'bool'}
VoidExpr {'void'} VoidExpr {'void'}
TypeExpr {expr.name}
BinaryExpr { BinaryExpr {
p.check_binary_expr_types(expr) p.check_binary_expr_types(expr)
left_t := p.get_expr_type(expr.left) 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 := p.symbols.lookup_func(expr.name) or {parse_error("Tried to call undefined function ${expr.name}")}
fninfo.type fninfo.type
} }
StructInstantiation {expr.name} ClassInstantiation {expr.name}
else {"Tried getting type of unexpected Expr"} 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 { fn (mut p Parser) parse_statement() Stmt {
match p.peek().type { match p.peek().type {
.kw_let {return p.parse_var_decl(false)} .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_return {return p.parse_return_stmt()}
.kw_fn {return p.parse_func_decl()} .kw_fn {return p.parse_func_decl()}
.lbracket {return p.parse_block(false)} .lbracket {return p.parse_block(false)}
.kw_struct {return p.parse_struct()} .kw_class {return p.parse_class()}
else {return p.parse_expr_stmt()} 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_name := match type_tok.type {
.type {type_tok.text} .type {type_tok.text}
.identifier { .identifier {
if p.symbols.lookup_struct_type(type_tok.text) == none { p.expect_ident_is_class(type_tok.text)
parse_error("Expected variable type after name when declaring ${name_tok.text}")
}
'struct ${type_tok.text}' 'struct ${type_tok.text}'
} }
else{parse_error("Expected variable type after name when declaring ${name_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 { for {
if p.peek().type != .identifier {parse_error("Invalid syntax to declare function arguments! use f(myint int, myreal real)")} if p.peek().type != .identifier {parse_error("Invalid syntax to declare function arguments! use f(myint int, myreal real)")}
p_name := p.next().text p_name := p.next().text
if p.peek().type != .type {parse_error("Invalid syntax to declare function arguments! use f(myint int, myreal real)")} //if p.peek().type != .type {parse_error("Invalid syntax to declare function arguments! use f(myint int, myreal real)")}
p_type := p.next().text
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} params << Param{p_name, p_type}
p.symbols.define_var(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() p.dump_token()
type_tok := p.next() type_tok := p.next()
if type_tok.type != .type { ret_type := match type_tok.type {
parse_error("Expected function return type after name when declaring ${name_tok.text}") .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) block := p.parse_block(true)
@@ -587,24 +616,24 @@ fn (mut p Parser) parse_func_decl() FuncDecl {
return FuncDecl { return FuncDecl {
name: name_tok.text name: name_tok.text
ret_type: type_tok.text ret_type: ret_type
block: block block: block
params: params params: params
} }
} }
fn (mut p Parser) parse_struct() StructDecl { fn (mut p Parser) parse_class() ClassDecl {
p.expect(.kw_struct) p.expect(.kw_class)
name := p.peek().text name := p.peek().text
p.expect(.identifier) p.expect(.identifier)
p.expect(.lbracket) p.expect(.lbracket)
mut members := []StructMember{} mut members := []ClassMember{}
for p.peek().type == .identifier { 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.expect(.rbracket)
p.symbols.define_struct_type(name) p.symbols.define_class(name)
return StructDecl{name: name, members: members} return ClassDecl{name: name, members: members}
} }
fn (mut p Parser) parse_return_stmt() ReturnStmt { fn (mut p Parser) parse_return_stmt() ReturnStmt {