1
0
mirror of https://github.com/vlang/v.git synced 2023-08-10 21:13:21 +03:00

checker: add comptime_selector() (#14286)

This commit is contained in:
yuyi 2022-05-05 00:25:58 +08:00 committed by GitHub
parent e2aa5c9b3f
commit 4242e7610f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 25 additions and 22 deletions

View File

@ -2663,28 +2663,7 @@ pub fn (mut c Checker) expr(node_ ast.Expr) ast.Type {
return c.comptime_call(mut node) return c.comptime_call(mut node)
} }
ast.ComptimeSelector { ast.ComptimeSelector {
node.left_type = c.expr(node.left) return c.comptime_selector(mut node)
expr_type := c.unwrap_generic(c.expr(node.field_expr))
expr_sym := c.table.sym(expr_type)
if expr_type != ast.string_type {
c.error('expected `string` instead of `$expr_sym.name` (e.g. `field.name`)',
node.field_expr.pos())
}
if mut node.field_expr is ast.SelectorExpr {
left_pos := node.field_expr.expr.pos()
if c.comptime_fields_type.len == 0 {
c.error('compile time field access can only be used when iterating over `T.fields`',
left_pos)
}
expr_name := node.field_expr.expr.str()
if expr_name in c.comptime_fields_type {
return c.comptime_fields_type[expr_name]
}
c.error('unknown `\$for` variable `$expr_name`', left_pos)
} else {
c.error('expected selector expression e.g. `$(field.name)`', node.field_expr.pos())
}
return ast.void_type
} }
ast.ConcatExpr { ast.ConcatExpr {
return c.concat_expr(mut node) return c.concat_expr(mut node)

View File

@ -90,6 +90,30 @@ fn (mut c Checker) comptime_call(mut node ast.ComptimeCall) ast.Type {
return f.return_type return f.return_type
} }
fn (mut c Checker) comptime_selector(mut node ast.ComptimeSelector) ast.Type {
node.left_type = c.expr(node.left)
expr_type := c.unwrap_generic(c.expr(node.field_expr))
expr_sym := c.table.sym(expr_type)
if expr_type != ast.string_type {
c.error('expected `string` instead of `$expr_sym.name` (e.g. `field.name`)', node.field_expr.pos())
}
if mut node.field_expr is ast.SelectorExpr {
left_pos := node.field_expr.expr.pos()
if c.comptime_fields_type.len == 0 {
c.error('compile time field access can only be used when iterating over `T.fields`',
left_pos)
}
expr_name := node.field_expr.expr.str()
if expr_name in c.comptime_fields_type {
return c.comptime_fields_type[expr_name]
}
c.error('unknown `\$for` variable `$expr_name`', left_pos)
} else {
c.error('expected selector expression e.g. `$(field.name)`', node.field_expr.pos())
}
return ast.void_type
}
fn (mut c Checker) comptime_for(node ast.ComptimeFor) { fn (mut c Checker) comptime_for(node ast.ComptimeFor) {
typ := c.unwrap_generic(node.typ) typ := c.unwrap_generic(node.typ)
sym := c.table.sym(typ) sym := c.table.sym(typ)