parent
01aa09d515
commit
982e35909d
|
@ -763,7 +763,7 @@ pub fn (mut c Checker) infix_expr(mut infix_expr ast.InfixExpr) table.Type {
|
||||||
left_pos := infix_expr.left.position()
|
left_pos := infix_expr.left.position()
|
||||||
right_pos := infix_expr.right.position()
|
right_pos := infix_expr.right.position()
|
||||||
if (left_type.is_ptr() || left.is_pointer()) && infix_expr.op in [.plus, .minus] {
|
if (left_type.is_ptr() || left.is_pointer()) && infix_expr.op in [.plus, .minus] {
|
||||||
if !c.inside_unsafe {
|
if !c.inside_unsafe && !infix_expr.left.is_mut_ident() && !infix_expr.right.is_mut_ident() {
|
||||||
c.warn('pointer arithmetic is only allowed in `unsafe` blocks', left_pos)
|
c.warn('pointer arithmetic is only allowed in `unsafe` blocks', left_pos)
|
||||||
}
|
}
|
||||||
if left_type == table.voidptr_type {
|
if left_type == table.voidptr_type {
|
||||||
|
@ -2600,7 +2600,11 @@ pub fn (mut c Checker) assign_stmt(mut assign_stmt ast.AssignStmt) {
|
||||||
right := if i < assign_stmt.right.len { assign_stmt.right[i] } else { assign_stmt.right[0] }
|
right := if i < assign_stmt.right.len { assign_stmt.right[i] } else { assign_stmt.right[0] }
|
||||||
mut right_type := assign_stmt.right_types[i]
|
mut right_type := assign_stmt.right_types[i]
|
||||||
if is_decl {
|
if is_decl {
|
||||||
left_type = c.table.mktyp(right_type)
|
if right.is_mut_ident() {
|
||||||
|
left_type = c.table.mktyp(right_type.deref())
|
||||||
|
} else {
|
||||||
|
left_type = c.table.mktyp(right_type)
|
||||||
|
}
|
||||||
if left_type == table.int_type {
|
if left_type == table.int_type {
|
||||||
if right is ast.IntegerLiteral {
|
if right is ast.IntegerLiteral {
|
||||||
mut is_large := right.val.len > 13
|
mut is_large := right.val.len > 13
|
||||||
|
@ -3007,7 +3011,11 @@ pub fn (mut c Checker) array_init(mut array_init ast.ArrayInit) table.Type {
|
||||||
}
|
}
|
||||||
// The first element's type
|
// The first element's type
|
||||||
if i == 0 {
|
if i == 0 {
|
||||||
elem_type = c.table.mktyp(typ)
|
if expr.is_mut_ident() {
|
||||||
|
elem_type = c.table.mktyp(typ.deref())
|
||||||
|
} else {
|
||||||
|
elem_type = c.table.mktyp(typ)
|
||||||
|
}
|
||||||
c.expected_type = elem_type
|
c.expected_type = elem_type
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
@ -5097,7 +5105,7 @@ pub fn (mut c Checker) postfix_expr(mut node ast.PostfixExpr) table.Type {
|
||||||
typ := c.expr(node.expr)
|
typ := c.expr(node.expr)
|
||||||
typ_sym := c.table.get_type_symbol(typ)
|
typ_sym := c.table.get_type_symbol(typ)
|
||||||
is_non_void_pointer := (typ.is_ptr() || typ.is_pointer()) && typ_sym.kind != .voidptr
|
is_non_void_pointer := (typ.is_ptr() || typ.is_pointer()) && typ_sym.kind != .voidptr
|
||||||
if !c.inside_unsafe && is_non_void_pointer {
|
if !c.inside_unsafe && is_non_void_pointer && !node.expr.is_mut_ident() {
|
||||||
c.warn('pointer arithmetic is only allowed in `unsafe` blocks', node.pos)
|
c.warn('pointer arithmetic is only allowed in `unsafe` blocks', node.pos)
|
||||||
}
|
}
|
||||||
if !(typ_sym.is_number() || (c.inside_unsafe && is_non_void_pointer)) {
|
if !(typ_sym.is_number() || (c.inside_unsafe && is_non_void_pointer)) {
|
||||||
|
@ -5224,7 +5232,7 @@ pub fn (mut c Checker) index_expr(mut node ast.IndexExpr) table.Type {
|
||||||
'(note, that variables may be mutable but string values are always immutable, like in Go and Java)',
|
'(note, that variables may be mutable but string values are always immutable, like in Go and Java)',
|
||||||
node.pos)
|
node.pos)
|
||||||
}
|
}
|
||||||
if !c.inside_unsafe && (typ.is_ptr() || typ.is_pointer()) {
|
if !c.inside_unsafe && ((typ.is_ptr() && !node.left.is_mut_ident()) || typ.is_pointer()) {
|
||||||
mut is_ok := false
|
mut is_ok := false
|
||||||
if mut node.left is ast.Ident {
|
if mut node.left is ast.Ident {
|
||||||
if node.left.obj is ast.Var {
|
if node.left.obj is ast.Var {
|
||||||
|
@ -5403,8 +5411,14 @@ pub fn (mut c Checker) map_init(mut node ast.MapInit) table.Type {
|
||||||
return node.typ
|
return node.typ
|
||||||
}
|
}
|
||||||
// `{'age': 20}`
|
// `{'age': 20}`
|
||||||
key0_type := c.table.mktyp(c.expr(node.keys[0]))
|
mut key0_type := c.table.mktyp(c.expr(node.keys[0]))
|
||||||
val0_type := c.table.mktyp(c.expr(node.vals[0]))
|
if node.keys[0].is_mut_ident() {
|
||||||
|
key0_type = key0_type.deref()
|
||||||
|
}
|
||||||
|
mut val0_type := c.table.mktyp(c.expr(node.vals[0]))
|
||||||
|
if node.vals[0].is_mut_ident() {
|
||||||
|
val0_type = val0_type.deref()
|
||||||
|
}
|
||||||
mut same_key_type := true
|
mut same_key_type := true
|
||||||
for i, key in node.keys {
|
for i, key in node.keys {
|
||||||
if i == 0 {
|
if i == 0 {
|
||||||
|
|
|
@ -26,6 +26,9 @@ fn (mut g Gen) array_init(node ast.ArrayInit) {
|
||||||
g.write('{')
|
g.write('{')
|
||||||
if node.has_val {
|
if node.has_val {
|
||||||
for i, expr in node.exprs {
|
for i, expr in node.exprs {
|
||||||
|
if expr.is_mut_ident() {
|
||||||
|
g.write('*')
|
||||||
|
}
|
||||||
g.expr(expr)
|
g.expr(expr)
|
||||||
if i != node.exprs.len - 1 {
|
if i != node.exprs.len - 1 {
|
||||||
g.write(', ')
|
g.write(', ')
|
||||||
|
|
|
@ -1525,7 +1525,7 @@ fn (mut g Gen) expr_with_cast(expr ast.Expr, got_type_raw table.Type, expected_t
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if got_is_ptr && !expected_is_ptr && neither_void
|
if got_is_ptr && !expected_is_ptr && neither_void
|
||||||
&& exp_sym.kind !in [.interface_, .placeholder] {
|
&& exp_sym.kind !in [.interface_, .placeholder] && expr !is ast.InfixExpr {
|
||||||
got_deref_type := got_type.deref()
|
got_deref_type := got_type.deref()
|
||||||
deref_sym := g.table.get_type_symbol(got_deref_type)
|
deref_sym := g.table.get_type_symbol(got_deref_type)
|
||||||
deref_will_match := expected_type in [got_type, got_deref_type, deref_sym.parent_idx]
|
deref_will_match := expected_type in [got_type, got_deref_type, deref_sym.parent_idx]
|
||||||
|
@ -2111,6 +2111,9 @@ fn (mut g Gen) gen_assign_stmt(assign_stmt ast.AssignStmt) {
|
||||||
g.write('for (int $i_var=0; $i_var<$fixed_array.size; $i_var++) {')
|
g.write('for (int $i_var=0; $i_var<$fixed_array.size; $i_var++) {')
|
||||||
g.expr(left)
|
g.expr(left)
|
||||||
g.write('[$i_var] = ')
|
g.write('[$i_var] = ')
|
||||||
|
if val.is_mut_ident() {
|
||||||
|
g.write('*')
|
||||||
|
}
|
||||||
g.expr(val)
|
g.expr(val)
|
||||||
g.write('[$i_var];')
|
g.write('[$i_var];')
|
||||||
g.writeln('}')
|
g.writeln('}')
|
||||||
|
@ -2133,6 +2136,9 @@ fn (mut g Gen) gen_assign_stmt(assign_stmt ast.AssignStmt) {
|
||||||
g.write('{0}')
|
g.write('{0}')
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
if val.is_mut_ident() {
|
||||||
|
g.write('*')
|
||||||
|
}
|
||||||
g.expr(val)
|
g.expr(val)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -2715,7 +2721,13 @@ fn (mut g Gen) expr(node ast.Expr) {
|
||||||
g.writeln('sync__RwMutex_lock(&$node.auto_locked->mtx);')
|
g.writeln('sync__RwMutex_lock(&$node.auto_locked->mtx);')
|
||||||
}
|
}
|
||||||
g.inside_map_postfix = true
|
g.inside_map_postfix = true
|
||||||
g.expr(node.expr)
|
if node.expr.is_mut_ident() {
|
||||||
|
g.write('(*')
|
||||||
|
g.expr(node.expr)
|
||||||
|
g.write(')')
|
||||||
|
} else {
|
||||||
|
g.expr(node.expr)
|
||||||
|
}
|
||||||
g.inside_map_postfix = false
|
g.inside_map_postfix = false
|
||||||
g.write(node.op.str())
|
g.write(node.op.str())
|
||||||
if node.auto_locked != '' {
|
if node.auto_locked != '' {
|
||||||
|
@ -3375,8 +3387,14 @@ fn (mut g Gen) infix_expr(node ast.InfixExpr) {
|
||||||
if need_par {
|
if need_par {
|
||||||
g.write('(')
|
g.write('(')
|
||||||
}
|
}
|
||||||
|
if node.left_type.is_ptr() && node.left.is_mut_ident() {
|
||||||
|
g.write('*')
|
||||||
|
}
|
||||||
g.expr(node.left)
|
g.expr(node.left)
|
||||||
g.write(' $node.op.str() ')
|
g.write(' $node.op.str() ')
|
||||||
|
if node.right_type.is_ptr() && node.right.is_mut_ident() {
|
||||||
|
g.write('*')
|
||||||
|
}
|
||||||
g.expr(node.right)
|
g.expr(node.right)
|
||||||
if need_par {
|
if need_par {
|
||||||
g.write(')')
|
g.write(')')
|
||||||
|
@ -3706,6 +3724,9 @@ fn (mut g Gen) map_init(node ast.MapInit) {
|
||||||
g.write('}), _MOV(($value_typ_str[$size]){')
|
g.write('}), _MOV(($value_typ_str[$size]){')
|
||||||
}
|
}
|
||||||
for expr in node.vals {
|
for expr in node.vals {
|
||||||
|
if expr.is_mut_ident() {
|
||||||
|
g.write('*')
|
||||||
|
}
|
||||||
g.expr(expr)
|
g.expr(expr)
|
||||||
g.write(', ')
|
g.write(', ')
|
||||||
}
|
}
|
||||||
|
|
|
@ -264,9 +264,15 @@ fn (mut g Gen) string_inter_literal(node ast.StringInterLiteral) {
|
||||||
if typ == table.string_type {
|
if typ == table.string_type {
|
||||||
if g.inside_vweb_tmpl {
|
if g.inside_vweb_tmpl {
|
||||||
g.write('vweb__filter(')
|
g.write('vweb__filter(')
|
||||||
|
if expr.is_mut_ident() {
|
||||||
|
g.write('*')
|
||||||
|
}
|
||||||
g.expr(expr)
|
g.expr(expr)
|
||||||
g.write(')')
|
g.write(')')
|
||||||
} else {
|
} else {
|
||||||
|
if expr.is_mut_ident() {
|
||||||
|
g.write('*')
|
||||||
|
}
|
||||||
g.expr(expr)
|
g.expr(expr)
|
||||||
}
|
}
|
||||||
} else if node.fmts[i] == `s` || typ.has_flag(.variadic) {
|
} else if node.fmts[i] == `s` || typ.has_flag(.variadic) {
|
||||||
|
@ -283,12 +289,21 @@ fn (mut g Gen) string_inter_literal(node ast.StringInterLiteral) {
|
||||||
} else {
|
} else {
|
||||||
g.write('(u64)(')
|
g.write('(u64)(')
|
||||||
}
|
}
|
||||||
|
if expr.is_mut_ident() {
|
||||||
|
g.write('*')
|
||||||
|
}
|
||||||
g.expr(expr)
|
g.expr(expr)
|
||||||
g.write(')')
|
g.write(')')
|
||||||
} else {
|
} else {
|
||||||
|
if expr.is_mut_ident() {
|
||||||
|
g.write('*')
|
||||||
|
}
|
||||||
g.expr(expr)
|
g.expr(expr)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
if expr.is_mut_ident() {
|
||||||
|
g.write('*')
|
||||||
|
}
|
||||||
g.expr(expr)
|
g.expr(expr)
|
||||||
}
|
}
|
||||||
if node.fmts[i] == `s` && node.fwidths[i] != 0 {
|
if node.fmts[i] == `s` && node.fwidths[i] != 0 {
|
||||||
|
|
|
@ -47,3 +47,210 @@ fn test_mut_2() {
|
||||||
assert b.a[0].v[3] == 8
|
assert b.a[0].v[3] == 8
|
||||||
assert b.a[0].v[4] == 5
|
assert b.a[0].v[4] == 5
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn test_mut_3() {
|
||||||
|
mut indices := []int{len: 3}
|
||||||
|
mut results := []string{}
|
||||||
|
|
||||||
|
for i, mut v in indices {
|
||||||
|
v = i
|
||||||
|
a := v
|
||||||
|
println('$i $v $a')
|
||||||
|
results << '$i $v $a'
|
||||||
|
}
|
||||||
|
assert results[0] == '0 0 0'
|
||||||
|
assert results[1] == '1 1 1'
|
||||||
|
assert results[2] == '2 2 2'
|
||||||
|
}
|
||||||
|
|
||||||
|
struct St {
|
||||||
|
mut:
|
||||||
|
n int
|
||||||
|
}
|
||||||
|
|
||||||
|
fn f(mut x St) {
|
||||||
|
mut y := St{n: 2}
|
||||||
|
a := x
|
||||||
|
b := y
|
||||||
|
x.n = 3
|
||||||
|
y.n = 4
|
||||||
|
println('$a.n $b.n')
|
||||||
|
assert '$a.n $b.n' == '1 2'
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_mut_4() {
|
||||||
|
mut x := St{ n: 1 }
|
||||||
|
f(mut x)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_mut_5() {
|
||||||
|
mut arr1 := []int{len:2}
|
||||||
|
mut arr2 := []int{len:2}
|
||||||
|
mut results := []string{}
|
||||||
|
|
||||||
|
for i, mut v in arr1 {
|
||||||
|
for ii, mut vv in arr2 {
|
||||||
|
v = i
|
||||||
|
a := v
|
||||||
|
println('$i $v $a')
|
||||||
|
results << '$i $v $a'
|
||||||
|
|
||||||
|
vv = ii
|
||||||
|
aa := vv
|
||||||
|
println('$ii $vv $aa')
|
||||||
|
results << "$ii $vv $aa"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
assert results[0] == '0 0 0'
|
||||||
|
assert results[1] == '0 0 0'
|
||||||
|
assert results[2] == '0 0 0'
|
||||||
|
assert results[3] == '1 1 1'
|
||||||
|
assert results[4] == '1 1 1'
|
||||||
|
assert results[5] == '0 0 0'
|
||||||
|
assert results[6] == '1 1 1'
|
||||||
|
assert results[7] == '1 1 1'
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_mut_6() {
|
||||||
|
mut results := []int{}
|
||||||
|
mut arr := []int{len:3}
|
||||||
|
for _, mut v in arr {
|
||||||
|
v = v + 1
|
||||||
|
println(v)
|
||||||
|
results << v
|
||||||
|
}
|
||||||
|
assert results[0] == 1
|
||||||
|
assert results[1] == 1
|
||||||
|
assert results[2] == 1
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_mut_7() {
|
||||||
|
mut arr := []int{len:3}
|
||||||
|
mut results := []int{}
|
||||||
|
for _, mut v in arr {
|
||||||
|
v = v + 1 // v: 1
|
||||||
|
mut vv := v // vv: 1, v: 1
|
||||||
|
vv = vv + v // vv: 2, v: 1
|
||||||
|
println(v)
|
||||||
|
println(vv)
|
||||||
|
results << v
|
||||||
|
results << vv
|
||||||
|
}
|
||||||
|
assert results[0] == 1
|
||||||
|
assert results[1] == 2
|
||||||
|
assert results[2] == 1
|
||||||
|
assert results[3] == 2
|
||||||
|
assert results[4] == 1
|
||||||
|
assert results[5] == 2
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_mut_8() {
|
||||||
|
mut indices := []int{len: 1}
|
||||||
|
for i, mut v in indices {
|
||||||
|
v = i
|
||||||
|
mut b := v
|
||||||
|
println(typeof(i).name)
|
||||||
|
println(typeof(v).name)
|
||||||
|
println(typeof(b).name)
|
||||||
|
u := [v, 5, 6]
|
||||||
|
println(typeof(u).name)
|
||||||
|
println(u)
|
||||||
|
assert typeof(b).name == 'int'
|
||||||
|
assert typeof(u).name == '[]int'
|
||||||
|
assert u == [0, 5, 6]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_mut_9() {
|
||||||
|
mut arr := [0,0,0]
|
||||||
|
mut results := []string{}
|
||||||
|
for _, mut v in arr {
|
||||||
|
v = v + 1 // v: 1
|
||||||
|
mut vv := v // vv: 1, v: 1
|
||||||
|
vv = vv + v // vv: 2, v: 1
|
||||||
|
foo := {'a': v, 'b': vv} // or use new syntax foo := map{'a': v, 'b': vv}, results are the same
|
||||||
|
println(v)
|
||||||
|
println(vv)
|
||||||
|
println(foo)
|
||||||
|
results << '$v'
|
||||||
|
results << '$vv'
|
||||||
|
results << '$foo'
|
||||||
|
}
|
||||||
|
assert results[0] == '1'
|
||||||
|
assert results[1] == '2'
|
||||||
|
assert results[2] == "{'a': 1, 'b': 2}"
|
||||||
|
assert results[3] == '1'
|
||||||
|
assert results[4] == '2'
|
||||||
|
assert results[5] == "{'a': 1, 'b': 2}"
|
||||||
|
assert results[6] == '1'
|
||||||
|
assert results[7] == '2'
|
||||||
|
assert results[8] == "{'a': 1, 'b': 2}"
|
||||||
|
}
|
||||||
|
|
||||||
|
fn foo1(mut arr [][]int) {
|
||||||
|
mut results := []int{}
|
||||||
|
for _, mut j in arr {
|
||||||
|
for _, mut k in j {
|
||||||
|
k = k + 1 // k: 1
|
||||||
|
mut kk := k // kk: 1, k: 1
|
||||||
|
kk = kk + k // kk: 2, k: 1
|
||||||
|
k++ // kk: 2, k: 2
|
||||||
|
kk++ // kk: 3, k: 2
|
||||||
|
println(k)
|
||||||
|
println(kk)
|
||||||
|
results << k
|
||||||
|
results << kk
|
||||||
|
}
|
||||||
|
}
|
||||||
|
assert results[0] == 2
|
||||||
|
assert results[1] == 3
|
||||||
|
assert results[2] == 2
|
||||||
|
assert results[3] == 3
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_mut_10() {
|
||||||
|
mut arr := [[0,0]]
|
||||||
|
foo1(mut arr)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn foo2(mut arr [][]int) {
|
||||||
|
mut results := []int{}
|
||||||
|
for _, mut j in arr {
|
||||||
|
for _, mut k in j {
|
||||||
|
k = k + 1 // k: 1
|
||||||
|
mut kk := k // kk: 1, k: 1
|
||||||
|
kk = kk + k // kk: 2, k: 1
|
||||||
|
k-- // kk: 2, k: 2
|
||||||
|
kk-- // kk: 3, k: 2
|
||||||
|
println(k)
|
||||||
|
println(kk)
|
||||||
|
results << k
|
||||||
|
results << kk
|
||||||
|
}
|
||||||
|
}
|
||||||
|
assert results[0] == 0
|
||||||
|
assert results[1] == 1
|
||||||
|
assert results[2] == 0
|
||||||
|
assert results[3] == 1
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_mut_11() {
|
||||||
|
mut arr := [[0,0]]
|
||||||
|
foo2(mut arr)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn foo3(mut arr [][]int) {
|
||||||
|
mut results := []string{}
|
||||||
|
for _, mut j in arr {
|
||||||
|
j[0] += 2
|
||||||
|
println(j) // [2, 0]
|
||||||
|
results << '$j'
|
||||||
|
}
|
||||||
|
assert results[0] == '[2, 0]'
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_mut_12() {
|
||||||
|
mut arr := [[0, 0]]
|
||||||
|
foo3(mut arr)
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue