strings handled as built-in struct, and added immutable keyword
This commit is contained in:
65
parser.v
65
parser.v
@@ -32,6 +32,7 @@ type SymbolInfo = VarSymbolInfo | FuncSymbolInfo | ClassSymbolInfo
|
||||
|
||||
struct VarSymbolInfo {
|
||||
type string
|
||||
is_immutable bool
|
||||
}
|
||||
|
||||
struct FuncSymbolInfo {
|
||||
@@ -96,7 +97,10 @@ fn (mut s SymbolTable) lookup_func(name string) ?FuncSymbolInfo {
|
||||
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}
|
||||
members_info[member.name] = VarSymbolInfo{
|
||||
type: member.type,
|
||||
is_immutable: member.is_immutable
|
||||
}
|
||||
}
|
||||
s.structs[name] = ClassSymbolInfo{name: name, members_info: members_info}
|
||||
}
|
||||
@@ -157,11 +161,13 @@ struct TypeExpr {
|
||||
struct ClassMember {
|
||||
name string
|
||||
type string
|
||||
is_immutable bool
|
||||
}
|
||||
|
||||
struct MemberAccess {
|
||||
from Expr
|
||||
member string
|
||||
member_type string
|
||||
}
|
||||
|
||||
struct ClassInstantiation {
|
||||
@@ -349,10 +355,6 @@ fn (mut p Parser) parse_ident(ident string) Expr {
|
||||
}
|
||||
}
|
||||
|
||||
if p.inside_struct {
|
||||
return p.parse_class_member(ident)
|
||||
}
|
||||
|
||||
return match p.peek().type {
|
||||
.increment, .decrement {UnaryExpr {ident: ident, op: p.next().text}}
|
||||
.lparen {p.parse_call(ident)}
|
||||
@@ -363,25 +365,34 @@ 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}
|
||||
from_class := p.symbols.lookup_class(p.get_expr_type(from)) or {panic("Accessing member from non-class type")}
|
||||
if !(member_tok.text in from_class.members_info) {panic("Accessing undefined member ${member_tok.text}")}
|
||||
member_type := from_class.members_info[member_tok.text].type
|
||||
return MemberAccess {from: from, member: member_tok.text, member_type: member_type}
|
||||
}
|
||||
|
||||
fn (mut p Parser) parse_class_member(name string) ClassMember {
|
||||
fn (mut p Parser) parse_class_member() ClassMember {
|
||||
mut is_immut := false
|
||||
if p.peek().type == .kw_immutable {
|
||||
is_immut = true
|
||||
p.next()
|
||||
}
|
||||
member_name := p.peek().text
|
||||
p.expect(.identifier)
|
||||
|
||||
type_tok := p.peek()
|
||||
type_name := match type_tok.type {
|
||||
.type {type_tok.text}
|
||||
.identifier {
|
||||
p.expect_ident_is_class(type_tok.text)
|
||||
type_tok.text
|
||||
}
|
||||
else{parse_error("Expected type after class member ${name} in declaration, got ${p.peek().type}")}
|
||||
p.expect_ident_is_class(type_tok.text)
|
||||
type_tok.text
|
||||
}
|
||||
else{parse_error("Expected type after class member ${member_name} in declaration, got ${p.peek().type}")}
|
||||
}
|
||||
|
||||
p.next()
|
||||
p.expect(.semicolon)
|
||||
return ClassMember{name: name, type: type_name}
|
||||
return ClassMember{name: member_name, type: type_name is_immutable: is_immut}
|
||||
}
|
||||
|
||||
fn (mut p Parser) parse_class_inst(name string) ClassInstantiation {
|
||||
@@ -439,6 +450,20 @@ fn (mut p Parser) parse_print() PrintExpr {
|
||||
}
|
||||
|
||||
fn (mut p Parser) parse_binary(left Expr, op string, prec Precedence) BinaryExpr {
|
||||
|
||||
if op in ['=', '+=', '-=', '*=', '/='] {
|
||||
if left is MemberAccess {
|
||||
from_type := p.get_expr_type(left.from)
|
||||
if class_info := p.symbols.lookup_class(from_type) {
|
||||
if member_info := class_info.members_info[left.member] {
|
||||
if member_info.is_immutable {
|
||||
parse_error("Cannot assign to immutable member ${left.member} in class ${from_type}")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
right := p.parse_expr(prec)
|
||||
binary_expr := BinaryExpr{left, op, right}
|
||||
|
||||
@@ -513,13 +538,7 @@ fn (mut p Parser) get_expr_type(expr Expr) string {
|
||||
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}")
|
||||
}
|
||||
expr.member_type
|
||||
}
|
||||
ClassInstantiation {expr.name}
|
||||
else {"Tried getting type of unexpected Expr"}
|
||||
@@ -695,8 +714,8 @@ fn (mut p Parser) parse_class() ClassDecl {
|
||||
p.expect(.identifier)
|
||||
p.expect(.lbracket)
|
||||
mut members := []ClassMember{}
|
||||
for p.peek().type == .identifier {
|
||||
members << p.parse_class_member(p.peek().text)
|
||||
for p.peek().type != .rbracket {
|
||||
members << p.parse_class_member()
|
||||
}
|
||||
p.expect(.rbracket)
|
||||
p.symbols.define_class(name, members)
|
||||
@@ -793,6 +812,10 @@ fn (mut p Parser) parse_block(no_scope bool) Block {
|
||||
}
|
||||
|
||||
fn (mut p Parser) parse_program() ([]Stmt, SymbolTable) {
|
||||
p.symbols.define_class('string',[
|
||||
ClassMember{'len', 'int', true}
|
||||
])
|
||||
|
||||
p.symbols.variable_scopes << map[string]VarSymbolInfo{}
|
||||
for p.peek().type != .eof {
|
||||
p.statements << p.parse_statement()
|
||||
|
||||
Reference in New Issue
Block a user