v2: fix `mod.Enum.val` and `x = .val`

pull/3859/head
Alexander Medvednikov 2020-02-27 00:12:37 +01:00
parent 59d6a675dd
commit c51f464446
4 changed files with 59 additions and 15 deletions

View File

@ -35,6 +35,13 @@ pub fn (c mut Checker) check(ast_file ast.File) {
for stmt in ast_file.stmts {
c.stmt(stmt)
}
/*
println('all types:')
for t in c.table.types {
println(t.name + ' - ' + t.kind.str())
}
*/
if c.nr_errors > 0 {
exit(1)
}
@ -105,7 +112,7 @@ pub fn (c mut Checker) check_struct_init(struct_init ast.StructInit) table.Type
expr_type_sym := c.table.get_type_symbol(expr_type)
field_type_sym := c.table.get_type_symbol(field.typ)
if !c.table.check(expr_type, field.typ) {
c.error('cannot assign $expr_type_sym.name as $field_type_sym.name for field $field.name', struct_init.pos)
c.error('cannot assign `$expr_type_sym.name` as `$field_type_sym.name` for field `$field.name`', struct_init.pos)
}
}
}
@ -132,6 +139,7 @@ pub fn (c mut Checker) infix_expr(infix_expr ast.InfixExpr) table.Type {
}
// if !c.table.check(&infix_expr.right_type, &infix_expr.right_type) {
// c.error('infix expr: cannot use `$infix_expr.right_type.name` as `$infix_expr.left_type.name`', infix_expr.pos)
// ltyp := typeof(infix_expr.left)
c.error('infix expr: cannot use `$right.name` (right) as `$left.name`', infix_expr.pos)
}
if infix_expr.op.is_relational() {
@ -142,6 +150,9 @@ pub fn (c mut Checker) infix_expr(infix_expr ast.InfixExpr) table.Type {
fn (c mut Checker) check_assign_expr(assign_expr ast.AssignExpr) {
left_type := c.expr(assign_expr.left)
c.expected_type = left_type
// t := c.table.get_type_symbol(left_type)
// println('setting exp type to $c.expected_type $t.name')
right_type := c.expr(assign_expr.val)
if !c.table.check(right_type, left_type) {
left_type_sym := c.table.get_type_symbol(left_type)
@ -272,7 +283,11 @@ pub fn (c mut Checker) return_stmt(return_stmt ast.Return) {
}
}
pub fn (c &Checker) assign_stmt(assign_stmt ast.AssignStmt) {}
/*
pub fn (c mut Checker) assign_stmt(assign_stmt ast.AssignStmt) {
}
*/
pub fn (c mut Checker) array_init(array_init mut ast.ArrayInit) table.Type {
mut elem_type := table.void_type
@ -305,6 +320,7 @@ pub fn (c mut Checker) array_init(array_init mut ast.ArrayInit) table.Type {
}
fn (c mut Checker) stmt(node ast.Stmt) {
// c.expected_type = table.void_type
match mut node {
ast.FnDecl {
for stmt in it.stmts {
@ -314,9 +330,12 @@ fn (c mut Checker) stmt(node ast.Stmt) {
ast.Return {
c.return_stmt(it)
}
/*
ast.AssignStmt {
c.assign_stmt(it)
}
*/
ast.ConstDecl {
for i, expr in it.exprs {
mut field := it.fields[i]
@ -653,10 +672,13 @@ pub fn (c mut Checker) index_expr(node ast.IndexExpr) table.Type {
// If a short form is used, `expected_type` needs to be an enum
// with this value.
pub fn (c mut Checker) enum_val(node ast.EnumVal) table.Type {
typ_idx := if node.enum_name == '' { c.expected_type } else { c.table.find_type_idx(node.enum_name) }
// println('checker: enum: $node.enum_name')
typ_idx := if node.enum_name == '' { c.expected_type } else { //
c.table.find_type_idx(node.enum_name) }
typ := c.table.get_type_symbol(table.Type(typ_idx))
// println('checker: enum val $c.expected_type $typ.name')
info := typ.info as table.Enum
// rintln('checker: x = $info.x enum val $c.expected_type $typ.name')
// println(info.vals)
if !(node.val in info.vals) {
c.error('enum `$typ.name` does not have a value `$node.val`', node.pos)
}

View File

@ -118,6 +118,9 @@ pub fn (p mut Parser) parse_any_type(is_ptr bool) table.Type {
// prefix with full module
name = '${p.imports[name]}.$p.tok.lit'
}
else if p.expr_mod != '' {
name = p.expr_mod + '.' + name
}
// `Foo` in module `mod` means `mod.Foo`
else if !(p.mod in ['builtin', 'main']) && !(name in table.builtin_type_names) {
name = p.mod + '.' + name
@ -208,7 +211,7 @@ pub fn (p mut Parser) parse_any_type(is_ptr bool) table.Type {
// println('NOT FOUND: $name - adding placeholder - $idx')
return table.new_type(idx)
}
}
}
}
}
}

View File

@ -42,6 +42,7 @@ mut:
pref &pref.Preferences // Preferences shared from V struct
builtin_mod bool
mod string
expr_mod string
expected_type table.Type
scope &ast.Scope
imports map[string]string
@ -551,6 +552,13 @@ pub fn (p mut Parser) name_expr() ast.Expr {
mut node := ast.Expr{}
is_c := p.tok.lit == 'C'
mut mod := ''
// p.warn('resetting')
p.expr_mod = ''
// `map[string]int` initialization
if p.tok.lit == 'map' && p.peek_tok.kind == .lsbr {
map_type := p.parse_map_type()
return node
}
if p.peek_tok.kind == .dot && (is_c || p.known_import(p.tok.lit)) {
if !is_c {
// prepend the full import
@ -558,11 +566,7 @@ pub fn (p mut Parser) name_expr() ast.Expr {
}
p.next()
p.check(.dot)
}
// `map[string]int` initialization
if p.tok.lit == 'map' && p.peek_tok.kind == .lsbr {
map_type := p.parse_map_type()
return node
p.expr_mod = mod
}
// p.warn('name expr $p.tok.lit $p.peek_tok.str()')
// fn call or type cast
@ -586,6 +590,7 @@ pub fn (p mut Parser) name_expr() ast.Expr {
typ: to_typ
expr: expr
}
p.expr_mod = ''
return node
}
// fn call
@ -606,13 +611,24 @@ pub fn (p mut Parser) name_expr() ast.Expr {
return p.struct_init()
}
else if p.peek_tok.kind == .dot && p.tok.lit[0].is_capital() {
enum_name := p.check_name()
// `Color.green`
mut enum_name := p.check_name()
if mod != '' {
enum_name = mod + '.' + enum_name
}
else {
enum_name = p.prepend_mod(enum_name)
}
// p.warn('Color.green $enum_name ' + p.prepend_mod(enum_name) + 'mod=$mod')
p.check(.dot)
val := p.check_name()
// println('enum val $enum_name . $val')
p.expr_mod = ''
return ast.EnumVal{
enum_name: enum_name
enum_name: enum_name // lp.prepend_mod(enum_name)
val: val
pos: p.tok.position()
}
}
else {
@ -620,6 +636,7 @@ pub fn (p mut Parser) name_expr() ast.Expr {
ident = p.parse_ident(is_c)
node = ident
}
p.expr_mod = ''
return node
}
@ -956,6 +973,7 @@ fn (p mut Parser) enum_val() ast.EnumVal {
return ast.EnumVal{
val: val
pos: p.tok.position()
}
}
@ -1452,6 +1470,7 @@ fn (p mut Parser) struct_decl() ast.StructDecl {
if ret == -1 {
p.error('cannot register type `$name`, another type with this name exists')
}
p.expr_mod = ''
return ast.StructDecl{
name: name
is_pub: is_pub
@ -1708,7 +1727,7 @@ fn (p mut Parser) enum_decl() ast.EnumDecl {
p.check(.rcbr)
p.table.register_type_symbol(table.TypeSymbol{
kind: .enum_
name: name
name: p.prepend_mod(name)
info: table.Enum{
vals: vals
}

View File

@ -56,7 +56,7 @@ pub fn (t mut Table) register_global(name string, typ Type) {
// mod: p.mod
// is_mut: true
// idx: -1
}
}
@ -186,7 +186,7 @@ pub fn (t &Table) get_type_symbol(typ Type) &TypeSymbol {
return &t.types[idx]
}
// this should never happen
panic('get_type_symbol: invalid type $typ - ${idx}. This should neer happen')
panic('get_type_symbol: invalid type (typ=$typ idx=${idx}). This should neer happen')
}
// this will override or register builtin type