From fbf80dc31513ec12da73d06796e43b364a0f843e Mon Sep 17 00:00:00 2001 From: Alexander Medvednikov Date: Sat, 7 Mar 2020 16:39:15 +0100 Subject: [PATCH] cgen: array_set() --- vlib/v/ast/ast.v | 24 ++++---- vlib/v/checker/checker.v | 1 + vlib/v/gen/cgen.v | 125 ++++++++++++++++++++++++--------------- vlib/v/gen/tests/1.c | 1 + vlib/v/gen/tests/1.vv | 3 +- 5 files changed, 95 insertions(+), 59 deletions(-) diff --git a/vlib/v/ast/ast.v b/vlib/v/ast/ast.v index 307d92a6a6..954eb23911 100644 --- a/vlib/v/ast/ast.v +++ b/vlib/v/ast/ast.v @@ -8,15 +8,15 @@ import ( v.table ) -pub type Expr = InfixExpr | IfExpr | StringLiteral | IntegerLiteral | CharLiteral | -FloatLiteral | Ident | CallExpr | BoolLiteral | StructInit | ArrayInit | SelectorExpr | PostfixExpr | -AssignExpr | PrefixExpr | MethodCallExpr | IndexExpr | RangeExpr | MatchExpr | -CastExpr | EnumVal | Assoc | SizeOf | None | MapInit | IfGuardExpr | ParExpr | OrExpr | +pub type Expr = InfixExpr | IfExpr | StringLiteral | IntegerLiteral | CharLiteral | +FloatLiteral | Ident | CallExpr | BoolLiteral | StructInit | ArrayInit | SelectorExpr | PostfixExpr | +AssignExpr | PrefixExpr | MethodCallExpr | IndexExpr | RangeExpr | MatchExpr | +CastExpr | EnumVal | Assoc | SizeOf | None | MapInit | IfGuardExpr | ParExpr | OrExpr | ConcatExpr | Type | AsCast -pub type Stmt = VarDecl | GlobalDecl | FnDecl | Return | Module | Import | ExprStmt | -ForStmt | StructDecl | ForCStmt | ForInStmt | CompIf | ConstDecl | Attr | BranchStmt | -HashStmt | AssignStmt | EnumDecl | TypeDecl | DeferStmt | GotoLabel | GotoStmt | +pub type Stmt = VarDecl | GlobalDecl | FnDecl | Return | Module | Import | ExprStmt | +ForStmt | StructDecl | ForCStmt | ForInStmt | CompIf | ConstDecl | Attr | BranchStmt | +HashStmt | AssignStmt | EnumDecl | TypeDecl | DeferStmt | GotoLabel | GotoStmt | LineComment | MultiLineComment | AssertStmt | UnsafeStmt // pub type Type = StructType | ArrayType // pub struct StructType { @@ -463,10 +463,12 @@ pub: pub struct AssignExpr { pub: - op token.Kind - pos token.Position - left Expr - val Expr + op token.Kind + pos token.Position + left Expr + val Expr +//mut: + //left_type table.Type } pub struct GotoLabel { diff --git a/vlib/v/checker/checker.v b/vlib/v/checker/checker.v index b861e5dc2f..ff4b8ab591 100644 --- a/vlib/v/checker/checker.v +++ b/vlib/v/checker/checker.v @@ -157,6 +157,7 @@ fn (c mut Checker) assign_expr(assign_expr ast.AssignExpr) { } left_type := c.expr(assign_expr.left) c.expected_type = left_type + // assign_expr.left_type = left_type // t := c.table.get_type_symbol(left_type) // println('setting exp type to $c.expected_type $t.name') right_type := c.expr(assign_expr.val) diff --git a/vlib/v/gen/cgen.v b/vlib/v/gen/cgen.v index ae3be96b23..6f92ef05f8 100644 --- a/vlib/v/gen/cgen.v +++ b/vlib/v/gen/cgen.v @@ -9,14 +9,16 @@ import ( ) struct Gen { - out strings.Builder - typedefs strings.Builder - definitions strings.Builder // typedefs, defines etc (everything that goes to the top of the file) - table &table.Table + out strings.Builder + typedefs strings.Builder + definitions strings.Builder // typedefs, defines etc (everything that goes to the top of the file) + table &table.Table mut: - fn_decl &ast.FnDecl // pointer to the FnDecl we are currently inside otherwise 0 - tmp_count int - is_c_call bool // e.g. `C.printf("v")` + fn_decl &ast.FnDecl // pointer to the FnDecl we are currently inside otherwise 0 + tmp_count int + is_c_call bool // e.g. `C.printf("v")` + is_assign_expr bool + is_array_set bool } pub fn cgen(files []ast.File, table &table.Table) string { @@ -383,9 +385,18 @@ fn (g mut Gen) expr(node ast.Expr) { g.write('/* as */') } ast.AssignExpr { + g.is_assign_expr = true g.expr(it.left) - g.write(' $it.op.str() ') + // arr[i] = val => `array_set(arr, i, val)`, not `array_get(arr, i) = val` + if !g.is_array_set { + g.write(' $it.op.str() ') + } g.expr(it.val) + if g.is_array_set { + g.write(')') + g.is_array_set = false + } + g.is_assign_expr = false } ast.Assoc { g.write('/* assoc */') @@ -498,40 +509,7 @@ fn (g mut Gen) expr(node ast.Expr) { g.index_expr(it) } ast.InfixExpr { - // if it.left_type == table.string_type_idx { - // g.write('/*$it.left_type str*/') - // } - // string + string - if it.op == .plus && it.left_type == table.string_type_idx { - g.write('string_add(') - g.expr(it.left) - g.write(', ') - g.expr(it.right) - g.write(')') - } - else if it.op == .eq && it.left_type == table.string_type_idx { - g.write('string_eq(') - g.expr(it.left) - g.write(', ') - g.expr(it.right) - g.write(')') - } - // arr << val - else if it.op == .left_shift && g.table.get_type_symbol(it.left_type).kind == .array { - g.write('array_push(') - g.expr(it.left) - g.write(', ') - g.expr(it.right) - g.write(')') - } - else { - // if it.op == .dot { - // println('!! dot') - // } - g.expr(it.left) - g.write(' $it.op.str() ') - g.expr(it.right) - } + g.infix_expr(it) } ast.IntegerLiteral { g.write(it.val.str()) @@ -687,6 +665,49 @@ fn (g mut Gen) expr(node ast.Expr) { } } +fn (g mut Gen) infix_expr(it ast.InfixExpr) { + // if it.left_type == table.string_type_idx { + // g.write('/*$it.left_type str*/') + // } + // string + string, string == string etc + if it.left_type == table.string_type_idx { + fn_name := match it.op { + .plus{ + 'string_add(' + } + .eq{ + 'string_eq(' + } + .ne{ + 'string_ne(' + } + else { + ''} + } + g.write(fn_name) + g.expr(it.left) + g.write(', ') + g.expr(it.right) + g.write(')') + } + // arr << val + else if it.op == .left_shift && g.table.get_type_symbol(it.left_type).kind == .array { + g.write('array_push(') + g.expr(it.left) + g.write(', ') + g.expr(it.right) + g.write(')') + } + else { + // if it.op == .dot { + // println('!! dot') + // } + g.expr(it.left) + g.write(' $it.op.str() ') + g.expr(it.right) + } +} + fn (g mut Gen) index_expr(node ast.IndexExpr) { // TODO else doesn't work with sum types mut is_range := false @@ -729,11 +750,21 @@ fn (g mut Gen) index_expr(node ast.IndexExpr) { if !is_range && node.container_type != 0 { sym := g.table.get_type_symbol(node.container_type) if sym.kind == .array { - g.write('array_get(') - g.expr(node.left) - g.write(', ') - g.expr(node.index) - g.write(')') + if g.is_assign_expr { + g.is_array_set = true + g.write('array_set(&') + g.expr(node.left) + g.write(', ') + g.expr(node.index) + g.write(', ') + } + else { + g.write('array_get(') + g.expr(node.left) + g.write(', ') + g.expr(node.index) + g.write(')') + } } else if sym.kind == .string { g.write('string_at(') diff --git a/vlib/v/gen/tests/1.c b/vlib/v/gen/tests/1.c index 4bff212d48..2035a7e35b 100644 --- a/vlib/v/gen/tests/1.c +++ b/vlib/v/gen/tests/1.c @@ -69,6 +69,7 @@ i < 10; i++) { array_int nums3 = array_slice(nums, 1, 2); array_int nums4 = array_slice(nums, 1, nums.len); int number = array_get(nums, 0); + array_set(&nums, 1, 10); array_bool bools = new_array_from_c_array(2, 2, sizeof(array_bool), (bool[]){ true, false, }); diff --git a/vlib/v/gen/tests/1.vv b/vlib/v/gen/tests/1.vv index f6b4d3d069..0d632c7f57 100644 --- a/vlib/v/gen/tests/1.vv +++ b/vlib/v/gen/tests/1.vv @@ -59,11 +59,12 @@ fn foo(a int) { for i := 0; i < 10; i++ { } - nums := [1,2,3] + mut nums := [1,2,3] nums2 := nums[..2] nums3 := nums[1..2] nums4 := nums[1..] number := nums[0] + nums[1] = 10 bools := [true, false] users := [User{}] //ptr := &User{}