From 217e6f3b8ead65497bcc56a0f70349e9fed7ebea Mon Sep 17 00:00:00 2001 From: Delyan Angelov Date: Fri, 10 Apr 2020 22:00:54 +0300 Subject: [PATCH] checker/parser: allow for fixed array with sizes defined with a const --- vlib/net/socket.v | 3 -- vlib/v/ast/ast.v | 2 + vlib/v/ast/scope.v | 6 ++- vlib/v/ast/str.v | 3 ++ vlib/v/checker/checker.v | 38 ++++++++++++------ vlib/v/gen/cgen.v | 8 ++-- vlib/v/parser/parser.v | 22 ++++++++--- .../static_arrays_using_const_for_size_test.v | 39 +++++++++++++++++++ vlib/v/token/position.v | 4 ++ 9 files changed, 99 insertions(+), 26 deletions(-) create mode 100644 vlib/v/tests/static_arrays_using_const_for_size_test.v diff --git a/vlib/net/socket.v b/vlib/net/socket.v index 6d8cbc76ce..5f5009a9d3 100644 --- a/vlib/net/socket.v +++ b/vlib/net/socket.v @@ -302,7 +302,6 @@ pub fn (s Socket) close() ?int { pub const ( CRLF = '\r\n' MAX_READ = 400 - xxx = 400 MSG_PEEK = 0x02 ) // write - write a string with CRLF after it over the socket s @@ -317,7 +316,6 @@ pub fn (s Socket) write(str string) ?int { // read_line - retrieves a line from the socket s (i.e. a string ended with \n) pub fn (s Socket) read_line() string { - //mut buf2 := [xxx]byte // where C.recv will store the network data mut buf := [MAX_READ]byte // where C.recv will store the network data mut res := '' // The final result, including the ending \n. for { @@ -385,4 +383,3 @@ pub fn (s Socket) get_port() int { C.getsockname(s.sockfd, &addr, &size) return C.ntohs(addr.sin_port) } - diff --git a/vlib/v/ast/ast.v b/vlib/v/ast/ast.v index e03080ea8b..0abf933a62 100644 --- a/vlib/v/ast/ast.v +++ b/vlib/v/ast/ast.v @@ -588,6 +588,8 @@ pub struct ArrayInit { pub: pos token.Position exprs []Expr + is_fixed bool + mod string mut: elem_type table.Type typ table.Type diff --git a/vlib/v/ast/scope.v b/vlib/v/ast/scope.v index bacac487e6..1aca6c7346 100644 --- a/vlib/v/ast/scope.v +++ b/vlib/v/ast/scope.v @@ -56,7 +56,8 @@ pub fn (s &Scope) is_known(name string) bool { pub fn (s &Scope) find_var(name string) ?Var { if obj := s.find(name) { - match obj { + v := ScopeObject(obj) + match v { Var { return *it } @@ -68,7 +69,8 @@ pub fn (s &Scope) find_var(name string) ?Var { pub fn (s &Scope) find_const(name string) ?ConstField { if obj := s.find(name) { - match obj { + cf := ScopeObject(obj) + match cf { ConstField { return *it } diff --git a/vlib/v/ast/str.v b/vlib/v/ast/str.v index 766096f3c4..ff25baecac 100644 --- a/vlib/v/ast/str.v +++ b/vlib/v/ast/str.v @@ -85,6 +85,9 @@ pub fn (x Expr) str() string { PrefixExpr { return it.op.str() + it.right.str() } + CharLiteral { + return '`$it.val`' + } IntegerLiteral { return it.val } diff --git a/vlib/v/checker/checker.v b/vlib/v/checker/checker.v index a4f6ea3e18..8e60b4e7a6 100644 --- a/vlib/v/checker/checker.v +++ b/vlib/v/checker/checker.v @@ -706,7 +706,7 @@ pub fn (c mut Checker) array_init(array_init mut ast.ArrayInit) table.Type { idx := c.table.find_or_register_array(elem_type, 1) array_init.typ = table.new_type(idx) array_init.elem_type = elem_type - } else if array_init.exprs.len == 1 && array_init.elem_type != table.void_type { + } else if array_init.is_fixed && array_init.exprs.len == 1 && array_init.elem_type != table.void_type { // [50]byte mut fixed_size := 1 match array_init.exprs[0] { @@ -714,19 +714,23 @@ pub fn (c mut Checker) array_init(array_init mut ast.ArrayInit) table.Type { fixed_size = it.val.int() } ast.Ident { - /* - QTODO - scope := c.file.scope.innermost(array_init.pos.pos) - if obj := c.file.global_scope.find(it.name) { + //if obj := c.file.global_scope.find_const(it.name) { + //if obj := scope.find(it.name) { + //scope := c.file.scope.innermost(array_init.pos.pos) + //eprintln('scope: ${scope.str()}') + //scope.find(it.name) or { + // c.error('undefined: `$it.name`', array_init.pos) + //} + mut full_const_name := if it.mod == 'main' { it.name } else {it.mod + '.' + it.name } + if obj := c.file.global_scope.find_const( full_const_name ) { + cf := ast.ConstField(obj) + if cint := is_const_integer(cf) { + fixed_size = cint.val.int() + } } else { - c.error(it.name, array_init.pos) + c.error('non existant integer const $full_const_name while initializing the size of a static array', array_init.pos) } - scope.find(it.name) or { - c.error('undefined: `$it.name`', array_init.pos) - } -*/ - } - else { + } else { c.error('expecting `int` for fixed size', array_init.pos) } } @@ -737,6 +741,16 @@ pub fn (c mut Checker) array_init(array_init mut ast.ArrayInit) table.Type { return array_init.typ } +fn is_const_integer(cfield ast.ConstField) ?ast.IntegerLiteral { + match cfield.expr { + ast.IntegerLiteral { + return *it + } + else {} + } + return none +} + fn (c mut Checker) stmt(node ast.Stmt) { // c.expected_type = table.void_type match mut node { diff --git a/vlib/v/gen/cgen.v b/vlib/v/gen/cgen.v index df4c948b23..ebc7550020 100644 --- a/vlib/v/gen/cgen.v +++ b/vlib/v/gen/cgen.v @@ -723,7 +723,7 @@ fn (g mut Gen) gen_assign_stmt(assign_stmt ast.AssignStmt) { mut is_fixed_array_init := false match val { ast.ArrayInit { - is_fixed_array_init = right_sym.kind == .array_fixed + is_fixed_array_init = it.is_fixed } else {} } @@ -740,15 +740,15 @@ fn (g mut Gen) gen_assign_stmt(assign_stmt ast.AssignStmt) { return } } - if !is_fixed_array_init { + if is_fixed_array_init { + g.write('= {0}') + } else { g.write(' = ') if !is_decl { g.expr_with_cast(val, assign_stmt.left_types[i], ident_var_info.typ) } else { g.expr(val) } - } else if is_fixed_array_init { - g.write('= {0}') } if gen_or { g.or_block(ident.name, or_stmts, return_type) diff --git a/vlib/v/parser/parser.v b/vlib/v/parser/parser.v index 3921478cc6..3dd56d2b34 100644 --- a/vlib/v/parser/parser.v +++ b/vlib/v/parser/parser.v @@ -513,19 +513,28 @@ fn (p mut Parser) range_expr(low ast.Expr) ast.Expr { return node } */ + pub fn (p &Parser) error(s string) { + p.error_with_pos(s, p.tok.position()) +} + +pub fn (p &Parser) warn(s string) { + p.warn_with_pos(s, p.tok.position()) +} + +pub fn (p &Parser) error_with_pos(s string, pos token.Position) { mut kind := 'error:' if p.pref.is_verbose { print_backtrace() kind = 'parser error:' } - ferror := util.formatted_error(kind, s, p.file_name, p.tok.position()) + ferror := util.formatted_error(kind, s, p.file_name, pos) eprintln(ferror) exit(1) } -pub fn (p &Parser) warn(s string) { - ferror := util.formatted_error('warning:', s, p.file_name, p.tok.position()) +pub fn (p &Parser) warn_with_pos(s string, pos token.Position) { + ferror := util.formatted_error('warning:', s, p.file_name, pos) eprintln(ferror) } @@ -1298,6 +1307,7 @@ fn (p mut Parser) array_init() ast.ArrayInit { mut array_type := table.void_type mut elem_type := table.void_type mut exprs := []ast.Expr + is_fixed := false if p.tok.kind == .rsbr { // []typ => `[]` and `typ` must be on the same line line_nr := p.tok.line_nr @@ -1311,7 +1321,7 @@ fn (p mut Parser) array_init() ast.ArrayInit { array_type = table.new_type(idx) } } else { - // [1,2,3] + // [1,2,3] or [const]byte for i := 0; p.tok.kind != .rsbr; i++ { expr := p.expr(0) exprs << expr @@ -1325,7 +1335,7 @@ fn (p mut Parser) array_init() ast.ArrayInit { // [100]byte if exprs.len == 1 && p.tok.kind in [.name, .amp] && p.tok.line_nr == line_nr { elem_type = p.parse_type() - // p.warn('fixed size array') + is_fixed = true } } // ! @@ -1343,6 +1353,8 @@ fn (p mut Parser) array_init() ast.ArrayInit { len: len } return ast.ArrayInit{ + is_fixed: is_fixed + mod: p.mod elem_type: elem_type typ: array_type exprs: exprs diff --git a/vlib/v/tests/static_arrays_using_const_for_size_test.v b/vlib/v/tests/static_arrays_using_const_for_size_test.v new file mode 100644 index 0000000000..3a938047eb --- /dev/null +++ b/vlib/v/tests/static_arrays_using_const_for_size_test.v @@ -0,0 +1,39 @@ +const ( + sbuffer_size = 10 +) + +fn test_hardcoded_static_arr(){ + myints := [10]int + size := sizeof( myints ) + assert size == 40 +} + +fn test_const_based_static_arr(){ + myints := [sbuffer_size]int + size := sizeof( myints ) + assert size == 40 +} + +fn test_const_based_static_arr_of_f64(){ + myf64 := [sbuffer_size]f64 + size := sizeof( myf64 ) + assert size == 80 +} + +fn test_const_based_static_arr_of_f32(){ + myf32 := [sbuffer_size]f32 + size := sizeof( myf32 ) + assert size == 40 +} + +fn test_const_based_static_arr_of_i8(){ + myi8 := [sbuffer_size]i8 + size := sizeof( myi8 ) + assert size == 10 +} + +fn test_const_based_static_arr_of_i16(){ + myi16 := [sbuffer_size]i16 + size := sizeof( myi16 ) + assert size == 20 +} diff --git a/vlib/v/token/position.v b/vlib/v/token/position.v index 5747183666..ecc0272c6e 100644 --- a/vlib/v/token/position.v +++ b/vlib/v/token/position.v @@ -10,6 +10,10 @@ pub: len int // length of the literal in the source } +pub fn (pos Position) str() string { + return 'Position{ line_nr: $pos.line_nr, pos: $pos.pos, len: $pos.len }' +} + [inline] pub fn (tok &Token) position() Position { return Position{