diff --git a/vlib/builtin/array.v b/vlib/builtin/array.v index 57e6a87425..50c913c962 100644 --- a/vlib/builtin/array.v +++ b/vlib/builtin/array.v @@ -378,7 +378,8 @@ pub fn (b []byte) hex() string { // TODO: implement for all types pub fn copy(dst, src []byte) int { if dst.len > 0 && src.len > 0 { - min := if dst.len < src.len { dst.len } else { src.len } + mut min := 0 + min = if dst.len < src.len { dst.len } else { src.len } C.memcpy(dst.data, src[..min].data, dst.element_size * min) return min } diff --git a/vlib/v/ast/ast.v b/vlib/v/ast/ast.v index 354275ba20..dbaee4f029 100644 --- a/vlib/v/ast/ast.v +++ b/vlib/v/ast/ast.v @@ -10,7 +10,7 @@ import ( pub type Expr = InfixExpr | IfExpr | StringLiteral | IntegerLiteral | FloatLiteral | Ident | CallExpr | BoolLiteral | StructInit | ArrayInit | SelectorExpr | PostfixExpr | -AssignExpr | PrefixExpr | MethodCallExpr | IndexExpr +AssignExpr | PrefixExpr | MethodCallExpr | IndexExpr | RangeExpr pub type Stmt = VarDecl | FnDecl | Return | Module | Import | ExprStmt | ForStmt | StructDecl | ForCStmt | ForInStmt @@ -296,6 +296,13 @@ pub: ti table.Type } +// s[10..20] +pub struct RangeExpr { +pub: + low Expr + high Expr +} + // string representaiton of expr pub fn (x Expr) str() string { match x { diff --git a/vlib/v/checker/checker.v b/vlib/v/checker/checker.v index 899de2b4e8..c8f0319006 100644 --- a/vlib/v/checker/checker.v +++ b/vlib/v/checker/checker.v @@ -194,112 +194,112 @@ fn (c &Checker) stmt(node ast.Stmt) { } ast.VarDecl { typ := c.expr(it.expr) - println('1111var decl $typ.name it.typ=$it.typ.name $it.pos.line_nr') + // println('var decl $typ.name it.typ=$it.typ.name $it.pos.line_nr') if it.typ.kind == .unresolved { // it.ti = typ - println('VAR DECL UN!!!') + // println('unresolved var') + } } - } - ast.ForStmt { - c.expr(it.cond) - for stmt in it.stmts { - c.stmt(stmt) + ast.ForStmt { + c.expr(it.cond) + for stmt in it.stmts { + c.stmt(stmt) + } } - } - ast.ForCStmt { - c.stmt(it.init) - c.expr(it.cond) - c.stmt(it.inc) - for stmt in it.stmts { - c.stmt(stmt) + ast.ForCStmt { + c.stmt(it.init) + c.expr(it.cond) + c.stmt(it.inc) + for stmt in it.stmts { + c.stmt(stmt) + } } - } - // ast.StructDecl {} - ast.ExprStmt { - c.expr(it.expr) - } - else {} + // ast.StructDecl {} + ast.ExprStmt { + c.expr(it.expr) + } + else {} + } } -} -pub fn (c &Checker) expr(node ast.Expr) table.Type { - match node { - ast.AssignExpr { - c.check_assign_expr(it) - } - ast.IntegerLiteral { - return table.int_type - } - // ast.FloatLiteral {} - ast.PostfixExpr { - return c.expr(it.expr) - } - /* + pub fn (c &Checker) expr(node ast.Expr) table.Type { + match node { + ast.AssignExpr { + c.check_assign_expr(it) + } + ast.IntegerLiteral { + return table.int_type + } + // ast.FloatLiteral {} + ast.PostfixExpr { + return c.expr(it.expr) + } + /* ast.UnaryExpr { c.expr(it.left) } */ - ast.StringLiteral { - return table.string_type - } - ast.PrefixExpr { - return c.expr(it.right) - } - ast.InfixExpr { - return c.infix_expr(it) - } - ast.StructInit { - return c.check_struct_init(it) - } - ast.CallExpr { - return c.call_expr(it) - } - ast.MethodCallExpr { - return c.check_method_call_expr(it) - } - ast.ArrayInit { - return c.array_init(it) - } - ast.Ident { - if it.kind == .variable { - info := it.info as ast.IdentVar - if info.typ.kind != .unresolved { - return info.typ + ast.StringLiteral { + return table.string_type + } + ast.PrefixExpr { + return c.expr(it.right) + } + ast.InfixExpr { + return c.infix_expr(it) + } + ast.StructInit { + return c.check_struct_init(it) + } + ast.CallExpr { + return c.call_expr(it) + } + ast.MethodCallExpr { + return c.check_method_call_expr(it) + } + ast.ArrayInit { + return c.array_init(it) + } + ast.Ident { + if it.kind == .variable { + info := it.info as ast.IdentVar + if info.typ.kind != .unresolved { + return info.typ + } + return c.expr(info.expr) } - return c.expr(info.expr) + return table.void_type } - return table.void_type - } - // ast.BoolLiteral {} - ast.SelectorExpr { - return c.selector_expr(it) - } - ast.IndexExpr { - c.expr(it.left) - c.expr(it.index) - } - ast.IfExpr { - c.expr(it.cond) - for i, stmt in it.stmts { - c.stmt(stmt) + // ast.BoolLiteral {} + ast.SelectorExpr { + return c.selector_expr(it) } - if it.else_stmts.len > 0 { - for stmt in it.else_stmts { + ast.IndexExpr { + c.expr(it.left) + c.expr(it.index) + } + ast.IfExpr { + c.expr(it.cond) + for i, stmt in it.stmts { c.stmt(stmt) } + if it.else_stmts.len > 0 { + for stmt in it.else_stmts { + c.stmt(stmt) + } + } } - } - else {} + else {} + } + return table.void_type } - return table.void_type -} -pub fn (c &Checker) error(s string, pos token.Position) { - print_backtrace() - final_msg_line := '$c.file_name:$pos.line_nr: error: $s' - eprintln(final_msg_line) - /* + pub fn (c &Checker) error(s string, pos token.Position) { + print_backtrace() + final_msg_line := '$c.file_name:$pos.line_nr: error: $s' + eprintln(final_msg_line) + /* if colored_output { eprintln(term.bold(term.red(final_msg_line))) }else{ @@ -307,5 +307,5 @@ pub fn (c &Checker) error(s string, pos token.Position) { } */ - exit(1) -} + exit(1) + } diff --git a/vlib/v/gen/cgen.v b/vlib/v/gen/cgen.v index ed54a76712..2267445853 100644 --- a/vlib/v/gen/cgen.v +++ b/vlib/v/gen/cgen.v @@ -5,7 +5,6 @@ import ( v.ast v.table v.checker - // v.types term ) @@ -25,7 +24,7 @@ pub fn cgen(files []ast.File, table &table.Table) string { definitions: strings.new_builder(100) table: table checker: checker.new_checker(table) // checker - + fn_decl: 0 } for file in files { @@ -267,10 +266,7 @@ fn (g mut Gen) expr(node ast.Expr) { g.write(it.field) } ast.IndexExpr { - g.expr(it.left) - g.write('[') - g.expr(it.index) - g.write(']') + g.index_expr(it) } ast.IfExpr { // If expression? Assign the value to a temp var. @@ -307,6 +303,31 @@ fn (g mut Gen) expr(node ast.Expr) { } } +fn (g mut Gen) index_expr(node ast.IndexExpr) { + // TODO else doesn't work with sum types + mut is_range := false + match node.index { + ast.RangeExpr { + is_range = true + g.write('array_slice(') + g.expr(node.left) + g.write(', ') + // g.expr(it.low) + g.write('0') + g.write(', ') + g.expr(it.high) + g.write(')') + } + else {} + } + if !is_range { + g.expr(node.left) + g.write('[') + g.expr(node.index) + g.write(']') + } +} + fn verror(s string) { println(s) exit(1) diff --git a/vlib/v/gen/tests/1.c b/vlib/v/gen/tests/1.c index 9eaf8146c7..783229570a 100644 --- a/vlib/v/gen/tests/1.c +++ b/vlib/v/gen/tests/1.c @@ -33,6 +33,7 @@ i < 10; i++; array_int nums = new_array_from_c_array(3, 3, sizeof(array_int), { 1, 2, 3, }); + array_int nums2 = array_slice(nums, 0, 2); int number = nums[0]; array_bool bools = new_array_from_c_array(2, 2, sizeof(array_bool), { true, false, diff --git a/vlib/v/gen/tests/1.vv b/vlib/v/gen/tests/1.vv index 73cdeabb47..7446a10d17 100644 --- a/vlib/v/gen/tests/1.vv +++ b/vlib/v/gen/tests/1.vv @@ -33,6 +33,7 @@ fn foo(a int) { } nums := [1,2,3] + nums2 := nums[..2] number := nums[0] bools := [true, false] b := bools[0] diff --git a/vlib/v/parser/parser.v b/vlib/v/parser/parser.v index 01fb92cefb..a9e3d84974 100644 --- a/vlib/v/parser/parser.v +++ b/vlib/v/parser/parser.v @@ -231,6 +231,20 @@ pub fn (p mut Parser) assign_expr(left ast.Expr) ast.AssignExpr { return node } +fn (p mut Parser) range_expr(low ast.Expr) ast.Expr { + // ,table.Type) { + p.next() + high,typ := p.expr(0) + if typ.kind != .int { + p.error('non-integer index `$typ.name`') + } + node := ast.RangeExpr{ + low: low + high: high + } + return node +} + /* pub fn (p mut Parser) assign_stmt() ast.AssignStmt { name := p.tok.lit @@ -340,21 +354,26 @@ pub fn (p mut Parser) name_expr() (ast.Expr,table.Type) { mut ident := ast.Ident{ name: p.tok.lit } - var := p.table.find_var(p.tok.lit) or { - p.error('name expr unknown variable `$p.tok.lit`') - exit(0) + if var := p.table.find_var(p.tok.lit) { + typ = var.typ + ident.kind = .variable + ident.info = ast.IdentVar{ + typ: typ + name: ident.name + // expr: p.expr(0)// var.expr + + } + // ident.ti = ti + node = ident + p.next() + }else{ + // Function object (not a call), e.g. `onclick(my_click)` + p.table.find_fn(p.tok.lit) or { + p.error('name expr unknown variable `$p.tok.lit`') + exit(0) + } + p.next() } - typ = var.typ - ident.kind = .variable - ident.info = ast.IdentVar{ - typ: typ - name: ident.name - // expr: p.expr(0)// var.expr - - } - // ident.ti = ti - node = ident - p.next() } return node,typ } @@ -372,7 +391,7 @@ pub fn (p mut Parser) expr(precedence int) (ast.Expr,table.Type) { node,typ = p.string_expr() } // -1, -a etc - .minus, .amp { + .minus, .amp, .mul { node,typ = p.prefix_expr() } // .amp { @@ -412,21 +431,7 @@ pub fn (p mut Parser) expr(precedence int) (ast.Expr,table.Type) { node,typ = p.dot_expr(node, typ) } else if p.tok.kind == .lsbr { - // TODO - // info := ti.info as table.Array - // ti = p.table.types[info.elem_type_idx] - if typ.name.starts_with('array_') { - elm_typ := typ.name[6..] - x := p.table.find_type(elm_typ) or { - p.error(elm_typ) - exit(0) - } - typ = x - } - else { - typ = table.int_type - } - node = p.index_expr(node) + node,typ = p.index_expr(node, typ) } else if p.tok.kind.is_infix() { node,typ = p.infix_expr(node) @@ -459,23 +464,50 @@ fn (p mut Parser) prefix_expr() (ast.Expr,table.Type) { return expr,ti } -fn (p mut Parser) index_expr(left ast.Expr) ast.Expr { - // ,table.Type) { +fn (p mut Parser) index_expr(left ast.Expr, typ_ table.Type) (ast.Expr,table.Type) { + mut typ := typ_ + // TODO + // info := ti.info as table.Array + // ti = p.table.types[info.elem_type_idx] + if typ.name.starts_with('array_') { + elm_typ := typ.name[6..] + // TODO `typ = ... or ...` + x := p.table.find_type(elm_typ) or { + p.error(elm_typ) + exit(0) + } + typ = x + } + else { + typ = table.int_type + } // println('index expr$p.tok.str() line=$p.tok.line_nr') - p.next() - println('start index expr') - index,typ := p.expr(0) - println('end expr typ=$typ.name') + p.next() // [ + // `numbers[..end]` + mut index_expr := ast.Expr{} + if p.tok.kind == .dotdot { + index_expr = p.range_expr(left) + typ = typ_ // set the type back to array + } + else { + // println('start index expr') + mut index_type := table.Type{} + index_expr,index_type = p.expr(0) + if index_type.kind != .int { + p.error('non-integer index (type `$typ.name`)') + } + } + // println('end expr typ=$typ.name') p.check(.rsbr) - println('got ]') + // println('got ]') // /ti := table.int_type mut node := ast.Expr{} node = ast.IndexExpr{ left: left - index: index + index: index_expr } - return node - // /return node,ti + // return node + return node,typ } fn (p mut Parser) dot_expr(left ast.Expr, left_ti &table.Type) (ast.Expr,table.Type) { diff --git a/vlib/v/token/token.v b/vlib/v/token/token.v index ed0e630d2b..b3da0bcaf9 100644 --- a/vlib/v/token/token.v +++ b/vlib/v/token/token.v @@ -357,6 +357,8 @@ const ( ) // precedence returns a tokens precedence if defined, otherwise lowest_prec pub fn (tok Token) precedence() int { + // TODO + // return int(precedences[int(tok)]) match tok.kind { .lsbr { return 9