2022-01-04 10:21:08 +01:00
|
|
|
// Copyright (c) 2019-2022 Alexander Medvednikov. All rights reserved.
|
2020-04-17 18:11:04 +02:00
|
|
|
// Use of this source code is governed by an MIT license
|
|
|
|
// that can be found in the LICENSE file.
|
|
|
|
module parser
|
2020-04-17 18:16:55 +02:00
|
|
|
|
|
|
|
import v.ast
|
|
|
|
|
2020-04-23 01:16:58 +02:00
|
|
|
fn (mut p Parser) array_init() ast.ArrayInit {
|
2022-01-26 11:36:28 +01:00
|
|
|
first_pos := p.tok.pos()
|
|
|
|
mut last_pos := p.tok.pos()
|
2020-04-17 18:16:55 +02:00
|
|
|
p.check(.lsbr)
|
|
|
|
// p.warn('array_init() exp=$p.expected_type')
|
2021-04-02 00:57:09 +02:00
|
|
|
mut array_type := ast.void_type
|
|
|
|
mut elem_type := ast.void_type
|
2020-05-28 13:32:12 +02:00
|
|
|
mut elem_type_pos := first_pos
|
2020-04-26 09:17:13 +02:00
|
|
|
mut exprs := []ast.Expr{}
|
2020-11-11 21:53:21 +01:00
|
|
|
mut ecmnts := [][]ast.Comment{}
|
2021-02-21 19:18:19 +01:00
|
|
|
mut pre_cmnts := []ast.Comment{}
|
2020-04-23 01:16:58 +02:00
|
|
|
mut is_fixed := false
|
2020-04-25 18:26:38 +02:00
|
|
|
mut has_val := false
|
2020-04-26 09:17:13 +02:00
|
|
|
mut has_type := false
|
2020-08-15 11:01:54 +02:00
|
|
|
mut has_default := false
|
2021-10-15 02:57:49 +02:00
|
|
|
mut has_it := false
|
2021-03-31 10:13:15 +02:00
|
|
|
mut default_expr := ast.empty_expr()
|
2020-04-17 18:16:55 +02:00
|
|
|
if p.tok.kind == .rsbr {
|
2022-01-26 11:36:28 +01:00
|
|
|
last_pos = p.tok.pos()
|
2020-04-17 18:16:55 +02:00
|
|
|
// []typ => `[]` and `typ` must be on the same line
|
|
|
|
line_nr := p.tok.line_nr
|
2020-05-07 06:51:36 +02:00
|
|
|
p.next()
|
2020-04-17 18:16:55 +02:00
|
|
|
// []string
|
2021-02-08 00:28:29 +01:00
|
|
|
if p.tok.kind in [.name, .amp, .lsbr, .key_shared] && p.tok.line_nr == line_nr {
|
2022-01-26 11:36:28 +01:00
|
|
|
elem_type_pos = p.tok.pos()
|
2020-04-17 18:16:55 +02:00
|
|
|
elem_type = p.parse_type()
|
2020-08-15 11:01:54 +02:00
|
|
|
// this is set here because it's a known type, others could be the
|
2020-04-17 18:16:55 +02:00
|
|
|
// result of expr so we do those in checker
|
2021-01-13 23:43:19 +01:00
|
|
|
idx := p.table.find_or_register_array(elem_type)
|
2021-04-15 01:44:11 +02:00
|
|
|
if elem_type.has_flag(.generic) {
|
|
|
|
array_type = ast.new_type(idx).set_flag(.generic)
|
|
|
|
} else {
|
|
|
|
array_type = ast.new_type(idx)
|
|
|
|
}
|
2020-04-26 09:17:13 +02:00
|
|
|
has_type = true
|
2020-04-17 18:16:55 +02:00
|
|
|
}
|
2022-01-26 11:36:28 +01:00
|
|
|
last_pos = p.tok.pos()
|
2020-04-17 18:16:55 +02:00
|
|
|
} else {
|
2022-04-15 17:35:56 +02:00
|
|
|
// [1,2,3] or [const]u8
|
2021-04-17 01:37:17 +02:00
|
|
|
old_inside_array_lit := p.inside_array_lit
|
|
|
|
p.inside_array_lit = true
|
2021-07-20 10:17:08 +02:00
|
|
|
pre_cmnts = p.eat_comments()
|
2020-12-12 04:06:09 +01:00
|
|
|
for i := 0; p.tok.kind !in [.rsbr, .eof]; i++ {
|
2020-07-17 19:13:22 +02:00
|
|
|
exprs << p.expr(0)
|
2021-07-20 10:17:08 +02:00
|
|
|
ecmnts << p.eat_comments()
|
2020-04-17 18:16:55 +02:00
|
|
|
if p.tok.kind == .comma {
|
2020-05-07 06:51:36 +02:00
|
|
|
p.next()
|
2020-04-17 18:16:55 +02:00
|
|
|
}
|
2021-07-20 10:17:08 +02:00
|
|
|
ecmnts.last() << p.eat_comments()
|
2020-04-17 18:16:55 +02:00
|
|
|
}
|
2021-04-17 01:37:17 +02:00
|
|
|
p.inside_array_lit = old_inside_array_lit
|
2020-04-17 18:16:55 +02:00
|
|
|
line_nr := p.tok.line_nr
|
|
|
|
$if tinyc {
|
2022-03-06 18:01:22 +01:00
|
|
|
// Note: do not remove the next line without testing
|
2020-04-17 18:16:55 +02:00
|
|
|
// v selfcompilation with tcc first
|
|
|
|
tcc_stack_bug := 12345
|
2020-04-22 01:52:56 +02:00
|
|
|
_ = tcc_stack_bug
|
2020-04-17 18:16:55 +02:00
|
|
|
}
|
2022-01-26 11:36:28 +01:00
|
|
|
last_pos = p.tok.pos()
|
2020-04-17 18:16:55 +02:00
|
|
|
p.check(.rsbr)
|
2021-01-10 06:58:31 +01:00
|
|
|
if exprs.len == 1 && p.tok.kind in [.name, .amp, .lsbr] && p.tok.line_nr == line_nr {
|
2022-04-15 17:35:56 +02:00
|
|
|
// [100]u8
|
2020-04-17 18:16:55 +02:00
|
|
|
elem_type = p.parse_type()
|
2022-04-15 19:40:23 +02:00
|
|
|
if p.table.sym(elem_type).name == 'byte' {
|
2022-04-20 12:03:22 +02:00
|
|
|
p.error('`byte` has been deprecated in favor of `u8`: use `[10]u8{}` instead of `[10]byte{}`')
|
2022-04-15 19:40:23 +02:00
|
|
|
}
|
2022-01-26 11:36:28 +01:00
|
|
|
last_pos = p.tok.pos()
|
2020-04-17 18:16:55 +02:00
|
|
|
is_fixed = true
|
2020-08-15 11:01:54 +02:00
|
|
|
if p.tok.kind == .lcbr {
|
|
|
|
p.next()
|
|
|
|
if p.tok.kind != .rcbr {
|
2022-01-26 11:36:28 +01:00
|
|
|
pos := p.tok.pos()
|
2020-08-15 11:01:54 +02:00
|
|
|
n := p.check_name()
|
|
|
|
if n != 'init' {
|
|
|
|
p.error_with_pos('expected `init:`, not `$n`', pos)
|
2020-12-04 19:34:05 +01:00
|
|
|
return ast.ArrayInit{}
|
2020-08-15 11:01:54 +02:00
|
|
|
}
|
|
|
|
p.check(.colon)
|
2021-10-15 02:57:49 +02:00
|
|
|
p.open_scope()
|
2020-08-15 11:01:54 +02:00
|
|
|
has_default = true
|
2021-10-15 02:57:49 +02:00
|
|
|
p.scope_register_it_as_index()
|
2020-08-15 11:01:54 +02:00
|
|
|
default_expr = p.expr(0)
|
2021-10-15 02:57:49 +02:00
|
|
|
has_it = if var := p.scope.find_var('it') {
|
|
|
|
mut variable := var
|
|
|
|
is_used := variable.is_used
|
|
|
|
variable.is_used = true
|
|
|
|
is_used
|
|
|
|
} else {
|
|
|
|
false
|
|
|
|
}
|
|
|
|
p.close_scope()
|
2020-08-15 11:01:54 +02:00
|
|
|
}
|
2022-01-26 11:36:28 +01:00
|
|
|
last_pos = p.tok.pos()
|
2020-08-15 11:01:54 +02:00
|
|
|
p.check(.rcbr)
|
2020-08-16 04:54:05 +02:00
|
|
|
} else {
|
2020-10-15 22:12:59 +02:00
|
|
|
p.warn_with_pos('use e.g. `x := [1]Type{}` instead of `x := [1]Type`',
|
2021-01-13 06:03:23 +01:00
|
|
|
first_pos.extend(last_pos))
|
2020-08-15 11:01:54 +02:00
|
|
|
}
|
2020-04-25 18:26:38 +02:00
|
|
|
} else {
|
2021-02-12 09:12:22 +01:00
|
|
|
if p.tok.kind == .not { // && p.tok.line_nr == p.prev_tok.line_nr {
|
2022-01-26 11:36:28 +01:00
|
|
|
last_pos = p.tok.pos()
|
2021-01-13 03:28:53 +01:00
|
|
|
is_fixed = true
|
|
|
|
has_val = true
|
2020-04-25 18:26:38 +02:00
|
|
|
p.next()
|
|
|
|
}
|
2021-01-13 03:28:53 +01:00
|
|
|
if p.tok.kind == .not && p.tok.line_nr == p.prev_tok.line_nr {
|
2022-01-26 11:36:28 +01:00
|
|
|
last_pos = p.tok.pos()
|
2021-01-14 03:51:13 +01:00
|
|
|
p.error_with_pos('use e.g. `[1, 2, 3]!` instead of `[1, 2, 3]!!`', last_pos)
|
2020-04-25 18:26:38 +02:00
|
|
|
p.next()
|
|
|
|
}
|
2020-04-17 18:16:55 +02:00
|
|
|
}
|
|
|
|
}
|
2020-04-26 09:17:13 +02:00
|
|
|
if exprs.len == 0 && p.tok.kind != .lcbr && has_type {
|
2021-02-03 10:25:08 +01:00
|
|
|
if !p.pref.is_fmt {
|
|
|
|
p.warn_with_pos('use `x := []Type{}` instead of `x := []Type`', first_pos.extend(last_pos))
|
|
|
|
}
|
2020-04-26 09:17:13 +02:00
|
|
|
}
|
2020-04-26 17:28:43 +02:00
|
|
|
mut has_len := false
|
|
|
|
mut has_cap := false
|
2021-03-31 10:13:15 +02:00
|
|
|
mut len_expr := ast.empty_expr()
|
|
|
|
mut cap_expr := ast.empty_expr()
|
2021-04-02 00:57:09 +02:00
|
|
|
if p.tok.kind == .lcbr && exprs.len == 0 && array_type != ast.void_type {
|
2020-04-17 18:16:55 +02:00
|
|
|
// `[]int{ len: 10, cap: 100}` syntax
|
|
|
|
p.next()
|
|
|
|
for p.tok.kind != .rcbr {
|
|
|
|
key := p.check_name()
|
|
|
|
p.check(.colon)
|
2020-04-26 17:28:43 +02:00
|
|
|
match key {
|
|
|
|
'len' {
|
|
|
|
has_len = true
|
|
|
|
len_expr = p.expr(0)
|
|
|
|
}
|
|
|
|
'cap' {
|
|
|
|
has_cap = true
|
|
|
|
cap_expr = p.expr(0)
|
|
|
|
}
|
2020-05-13 22:00:24 +02:00
|
|
|
'init' {
|
2021-10-15 02:57:49 +02:00
|
|
|
p.open_scope()
|
2020-05-13 16:11:52 +02:00
|
|
|
has_default = true
|
2021-10-15 02:57:49 +02:00
|
|
|
p.scope_register_it_as_index()
|
2020-05-13 16:11:52 +02:00
|
|
|
default_expr = p.expr(0)
|
2021-10-15 02:57:49 +02:00
|
|
|
has_it = if var := p.scope.find_var('it') {
|
|
|
|
mut variable := var
|
|
|
|
is_used := variable.is_used
|
|
|
|
variable.is_used = true
|
|
|
|
is_used
|
|
|
|
} else {
|
|
|
|
false
|
|
|
|
}
|
|
|
|
p.close_scope()
|
2020-04-26 17:28:43 +02:00
|
|
|
}
|
|
|
|
else {
|
2020-05-13 22:00:24 +02:00
|
|
|
p.error('wrong field `$key`, expecting `len`, `cap`, or `init`')
|
2020-12-04 19:34:05 +01:00
|
|
|
return ast.ArrayInit{}
|
2020-04-26 17:28:43 +02:00
|
|
|
}
|
2020-04-17 18:16:55 +02:00
|
|
|
}
|
|
|
|
if p.tok.kind != .rcbr {
|
|
|
|
p.check(.comma)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
p.check(.rcbr)
|
|
|
|
}
|
2021-01-19 14:49:40 +01:00
|
|
|
pos := first_pos.extend_with_last_line(last_pos, p.prev_tok.line_nr)
|
2020-04-17 18:16:55 +02:00
|
|
|
return ast.ArrayInit{
|
|
|
|
is_fixed: is_fixed
|
2020-04-25 18:26:38 +02:00
|
|
|
has_val: has_val
|
2020-04-17 18:16:55 +02:00
|
|
|
mod: p.mod
|
|
|
|
elem_type: elem_type
|
|
|
|
typ: array_type
|
|
|
|
exprs: exprs
|
2020-11-11 21:53:21 +01:00
|
|
|
ecmnts: ecmnts
|
2021-02-21 19:18:19 +01:00
|
|
|
pre_cmnts: pre_cmnts
|
2020-04-17 18:16:55 +02:00
|
|
|
pos: pos
|
2020-05-28 13:32:12 +02:00
|
|
|
elem_type_pos: elem_type_pos
|
2020-04-26 17:28:43 +02:00
|
|
|
has_len: has_len
|
|
|
|
len_expr: len_expr
|
|
|
|
has_cap: has_cap
|
2020-05-13 16:11:52 +02:00
|
|
|
has_default: has_default
|
2021-10-15 02:57:49 +02:00
|
|
|
has_it: has_it
|
2020-04-26 17:28:43 +02:00
|
|
|
cap_expr: cap_expr
|
2020-05-13 16:11:52 +02:00
|
|
|
default_expr: default_expr
|
2020-04-17 18:16:55 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-02-06 22:13:24 +01:00
|
|
|
// parse tokens between braces
|
2020-04-23 01:16:58 +02:00
|
|
|
fn (mut p Parser) map_init() ast.MapInit {
|
2022-01-26 11:36:28 +01:00
|
|
|
first_pos := p.prev_tok.pos()
|
2020-04-26 09:17:13 +02:00
|
|
|
mut keys := []ast.Expr{}
|
|
|
|
mut vals := []ast.Expr{}
|
2021-02-22 12:04:48 +01:00
|
|
|
mut comments := [][]ast.Comment{}
|
2021-07-20 10:17:08 +02:00
|
|
|
pre_cmnts := p.eat_comments()
|
2021-02-22 12:04:48 +01:00
|
|
|
for p.tok.kind !in [.rcbr, .eof] {
|
2020-04-17 18:16:55 +02:00
|
|
|
key := p.expr(0)
|
|
|
|
keys << key
|
|
|
|
p.check(.colon)
|
|
|
|
val := p.expr(0)
|
|
|
|
vals << val
|
|
|
|
if p.tok.kind == .comma {
|
|
|
|
p.next()
|
|
|
|
}
|
2021-07-20 10:17:08 +02:00
|
|
|
comments << p.eat_comments()
|
2020-04-17 18:16:55 +02:00
|
|
|
}
|
|
|
|
return ast.MapInit{
|
|
|
|
keys: keys
|
|
|
|
vals: vals
|
2022-01-26 11:36:28 +01:00
|
|
|
pos: first_pos.extend_with_last_line(p.tok.pos(), p.tok.line_nr)
|
2021-02-22 12:04:48 +01:00
|
|
|
comments: comments
|
|
|
|
pre_cmnts: pre_cmnts
|
2020-04-17 18:16:55 +02:00
|
|
|
}
|
|
|
|
}
|
2021-10-15 02:57:49 +02:00
|
|
|
|
|
|
|
fn (mut p Parser) scope_register_it_as_index() {
|
|
|
|
p.scope.objects['it'] = ast.Var{ // override it variable if it already exist, else create it variable
|
|
|
|
name: 'it'
|
2022-01-26 11:36:28 +01:00
|
|
|
pos: p.tok.pos()
|
2021-10-15 02:57:49 +02:00
|
|
|
typ: ast.int_type
|
|
|
|
is_mut: false
|
|
|
|
is_used: false
|
|
|
|
}
|
|
|
|
}
|