mirror of
https://github.com/vlang/v.git
synced 2023-08-10 21:13:21 +03:00
checker/parser: check & gen stmts for ForIn & fix key, val vars
This commit is contained in:
parent
e37fed437d
commit
4262ff76c3
@ -319,6 +319,11 @@ pub fn (c mut Checker) method_call_expr(method_call_expr mut ast.MethodCallExpr)
|
||||
method_call_expr.return_type = method.return_type
|
||||
return method.return_type
|
||||
}
|
||||
// TODO: str methods
|
||||
if typ_sym.kind in [.map] && name == 'str' {
|
||||
method_call_expr.return_type = table.string_type
|
||||
return table.string_type
|
||||
}
|
||||
c.error('type `$typ_sym.name` has no method `$name`', method_call_expr.pos)
|
||||
return table.void_type
|
||||
}
|
||||
@ -530,9 +535,7 @@ fn (c mut Checker) stmt(node ast.Stmt) {
|
||||
ast.FnDecl {
|
||||
c.expected_type = table.void_type
|
||||
c.fn_return_type = it.return_type
|
||||
for stmt in it.stmts {
|
||||
c.stmt(stmt)
|
||||
}
|
||||
c.stmts(it.stmts)
|
||||
}
|
||||
ast.ForStmt {
|
||||
typ := c.expr(it.cond)
|
||||
@ -541,22 +544,47 @@ fn (c mut Checker) stmt(node ast.Stmt) {
|
||||
}
|
||||
// TODO: update loop var type
|
||||
// how does this work currenly?
|
||||
for stmt in it.stmts {
|
||||
c.stmt(stmt)
|
||||
}
|
||||
c.stmts(it.stmts)
|
||||
}
|
||||
ast.ForCStmt {
|
||||
c.stmt(it.init)
|
||||
c.expr(it.cond)
|
||||
// c.stmt(it.inc)
|
||||
c.expr(it.inc)
|
||||
for stmt in it.stmts {
|
||||
c.stmt(stmt)
|
||||
}
|
||||
c.stmts(it.stmts)
|
||||
}
|
||||
ast.ForInStmt {
|
||||
c.expr(it.cond)
|
||||
c.expr(it.high)
|
||||
typ := c.expr(it.cond)
|
||||
if it.is_range {
|
||||
c.expr(it.high)
|
||||
}
|
||||
else {
|
||||
mut scope := c.file.scope.innermost(it.pos.pos)
|
||||
if it.key_var.len > 0 {
|
||||
sym := c.table.get_type_symbol(typ)
|
||||
key_type := match sym.kind {
|
||||
.map{
|
||||
sym.map_info().key_type
|
||||
}
|
||||
else {
|
||||
table.int_type}
|
||||
}
|
||||
scope.override_var(ast.Var{
|
||||
name: it.key_var
|
||||
typ: key_type
|
||||
})
|
||||
}
|
||||
value_type := c.table.value_type(typ)
|
||||
if value_type == table.void_type {
|
||||
typ_sym := c.table.get_type_symbol(typ)
|
||||
c.error('for in: cannot index $typ_sym.name', it.pos)
|
||||
}
|
||||
scope.override_var(ast.Var{
|
||||
name: it.val_var
|
||||
typ: c.table.value_type(typ)
|
||||
})
|
||||
}
|
||||
c.stmts(it.stmts)
|
||||
}
|
||||
// ast.GlobalDecl {}
|
||||
// ast.HashStmt {}
|
||||
@ -566,9 +594,7 @@ fn (c mut Checker) stmt(node ast.Stmt) {
|
||||
}
|
||||
// ast.StructDecl {}
|
||||
ast.UnsafeStmt {
|
||||
for stmt in it.stmts {
|
||||
c.stmt(stmt)
|
||||
}
|
||||
c.stmts(it.stmts)
|
||||
}
|
||||
else {}
|
||||
// println('checker.stmt(): unhandled node')
|
||||
@ -761,6 +787,15 @@ pub fn (c mut Checker) ident(ident mut ast.Ident) table.Type {
|
||||
if !name.contains('.') && !(c.file.mod.name in ['builtin', 'main']) {
|
||||
name = '${c.file.mod.name}.$ident.name'
|
||||
}
|
||||
// hack - const until consts are fixed properly
|
||||
if ident.name == 'v_modules_path' {
|
||||
ident.name = name
|
||||
ident.kind = .constant
|
||||
ident.info = ast.IdentVar{
|
||||
typ: table.string_type
|
||||
}
|
||||
return table.string_type
|
||||
}
|
||||
// constant
|
||||
if constant := c.table.find_const(name) {
|
||||
ident.name = name
|
||||
@ -913,30 +948,10 @@ pub fn (c mut Checker) index_expr(node mut ast.IndexExpr) table.Type {
|
||||
else if typ_sym.kind == .map && table.type_idx(index_type) != table.string_type_idx {
|
||||
c.error('non-string map index (type `$typ_sym.name`)', node.pos)
|
||||
}
|
||||
if typ_sym.kind == .array {
|
||||
// Check index type
|
||||
info := typ_sym.info as table.Array
|
||||
return info.elem_type
|
||||
value_type := c.table.value_type(typ)
|
||||
if value_type != table.void_type {
|
||||
return value_type
|
||||
}
|
||||
else if typ_sym.kind == .array_fixed {
|
||||
info := typ_sym.info as table.ArrayFixed
|
||||
return info.elem_type
|
||||
}
|
||||
else if typ_sym.kind == .map {
|
||||
info := typ_sym.info as table.Map
|
||||
return info.value_type
|
||||
}
|
||||
else if typ_sym.kind in [.byteptr, .string] {
|
||||
return table.byte_type
|
||||
}
|
||||
else if table.type_is_ptr(typ) {
|
||||
// byte* => byte
|
||||
// bytes[0] is a byte, not byte*
|
||||
return table.type_deref(typ)
|
||||
}
|
||||
// else {
|
||||
// return table.int_type
|
||||
// }
|
||||
}
|
||||
return typ
|
||||
}
|
||||
|
@ -271,9 +271,7 @@ fn (g mut Gen) stmt(node ast.Stmt) {
|
||||
// g.stmt(it.inc)
|
||||
g.expr(it.inc)
|
||||
g.writeln(') {')
|
||||
for stmt in it.stmts {
|
||||
g.stmt(stmt)
|
||||
}
|
||||
g.stmts(it.stmts)
|
||||
g.writeln('}')
|
||||
}
|
||||
ast.ForInStmt {
|
||||
@ -284,7 +282,7 @@ fn (g mut Gen) stmt(node ast.Stmt) {
|
||||
g.write('; $i < ')
|
||||
g.expr(it.high)
|
||||
g.writeln('; $i++) { ')
|
||||
// g.stmts(it.stmts) TODO
|
||||
g.stmts(it.stmts)
|
||||
g.writeln('}')
|
||||
}
|
||||
}
|
||||
@ -297,9 +295,7 @@ fn (g mut Gen) stmt(node ast.Stmt) {
|
||||
g.expr(it.cond)
|
||||
}
|
||||
g.writeln(') {')
|
||||
for stmt in it.stmts {
|
||||
g.stmt(stmt)
|
||||
}
|
||||
g.stmts(it.stmts)
|
||||
g.writeln('}')
|
||||
}
|
||||
ast.GlobalDecl {
|
||||
|
@ -1096,13 +1096,14 @@ fn (p mut Parser) for_statement() ast.Stmt {
|
||||
}
|
||||
// `for i in vals`, `for i in start .. end`
|
||||
else if p.peek_tok.kind in [.key_in, .comma] {
|
||||
var_name := p.check_name()
|
||||
mut val_name := ''
|
||||
mut key_var_name := ''
|
||||
mut val_var_name := p.check_name()
|
||||
if p.tok.kind == .comma {
|
||||
p.check(.comma)
|
||||
val_name = p.check_name()
|
||||
key_var_name = val_var_name
|
||||
val_var_name = p.check_name()
|
||||
p.scope.register_var(ast.Var{
|
||||
name: val_name
|
||||
name: key_var_name
|
||||
typ: table.int_type
|
||||
})
|
||||
}
|
||||
@ -1118,13 +1119,17 @@ fn (p mut Parser) for_statement() ast.Stmt {
|
||||
is_range = true
|
||||
p.check(.dotdot)
|
||||
high_expr = p.expr(0)
|
||||
p.scope.register_var(ast.Var{
|
||||
name: val_var_name
|
||||
typ: table.int_type
|
||||
})
|
||||
}
|
||||
else {
|
||||
// this type will be set in checker
|
||||
p.scope.register_var(ast.Var{
|
||||
name: val_var_name
|
||||
})
|
||||
}
|
||||
// TODO: update var type in checker
|
||||
p.scope.register_var(ast.Var{
|
||||
name: var_name
|
||||
// expr: cond
|
||||
|
||||
})
|
||||
stmts := p.parse_block()
|
||||
// println('nr stmts=$stmts.len')
|
||||
p.close_scope()
|
||||
@ -1132,8 +1137,8 @@ fn (p mut Parser) for_statement() ast.Stmt {
|
||||
stmts: stmts
|
||||
pos: p.tok.position()
|
||||
cond: cond
|
||||
key_var: var_name
|
||||
val_var: val_name
|
||||
key_var: key_var_name
|
||||
val_var: val_var_name
|
||||
high: high_expr
|
||||
is_range: is_range
|
||||
}
|
||||
|
@ -29,19 +29,19 @@ pub:
|
||||
|
||||
pub struct Arg {
|
||||
pub:
|
||||
name string
|
||||
is_mut bool
|
||||
typ Type
|
||||
name string
|
||||
is_mut bool
|
||||
typ Type
|
||||
}
|
||||
|
||||
pub struct Var {
|
||||
pub:
|
||||
name string
|
||||
is_mut bool
|
||||
is_const bool
|
||||
is_global bool
|
||||
name string
|
||||
is_mut bool
|
||||
is_const bool
|
||||
is_global bool
|
||||
mut:
|
||||
typ Type
|
||||
typ Type
|
||||
}
|
||||
|
||||
pub fn new_table() &Table {
|
||||
@ -411,6 +411,43 @@ pub fn (t mut Table) add_placeholder_type(name string) int {
|
||||
return t.register_type_symbol(ph_type)
|
||||
}
|
||||
|
||||
[inline]
|
||||
pub fn (t &Table) value_type(typ Type) Type {
|
||||
typ_sym := t.get_type_symbol(typ)
|
||||
if typ_sym.kind == .array {
|
||||
// Check index type
|
||||
info := typ_sym.info as Array
|
||||
return info.elem_type
|
||||
}
|
||||
else if typ_sym.kind == .array_fixed {
|
||||
info := typ_sym.info as ArrayFixed
|
||||
return info.elem_type
|
||||
}
|
||||
else if typ_sym.kind == .map {
|
||||
info := typ_sym.info as Map
|
||||
return info.value_type
|
||||
}
|
||||
else if typ_sym.kind in [.byteptr, .string] {
|
||||
return byte_type
|
||||
}
|
||||
else if type_is_ptr(typ) {
|
||||
// byte* => byte
|
||||
// bytes[0] is a byte, not byte*
|
||||
return type_deref(typ)
|
||||
}
|
||||
else if type_is_variadic(typ) {
|
||||
// ...string => string
|
||||
return type_clear_extra(typ)
|
||||
}
|
||||
else {
|
||||
// TODO: remove when map_string is removed
|
||||
if typ_sym.name == 'map_string' {
|
||||
return string_type
|
||||
}
|
||||
return void_type
|
||||
}
|
||||
}
|
||||
|
||||
pub fn (t &Table) check(got, expected Type) bool {
|
||||
got_type_sym := t.get_type_symbol(got)
|
||||
exp_type_sym := t.get_type_symbol(expected)
|
||||
|
Loading…
Reference in New Issue
Block a user