Skip to content

Commit 53023c1

Browse files
authored
all: add UnsafeExpr (#5793)
1 parent cad816a commit 53023c1

File tree

9 files changed

+78
-2
lines changed

9 files changed

+78
-2
lines changed

vlib/v/ast/ast.v

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ pub type Expr = AnonFn | ArrayInit | AsCast | Assoc | BoolLiteral | CallExpr | C
1313
CharLiteral | ComptimeCall | ConcatExpr | EnumVal | FloatLiteral | Ident | IfExpr | IfGuardExpr |
1414
IndexExpr | InfixExpr | IntegerLiteral | Likely | LockExpr | MapInit | MatchExpr | None |
1515
OrExpr | ParExpr | PostfixExpr | PrefixExpr | RangeExpr | SelectorExpr | SizeOf | SqlExpr |
16-
StringInterLiteral | StringLiteral | StructInit | Type | TypeOf
16+
StringInterLiteral | StringLiteral | StructInit | Type | TypeOf | UnsafeExpr
1717

1818
pub type Stmt = AssertStmt | AssignStmt | Attr | Block | BranchStmt | Comment | CompFor |
1919
CompIf | ConstDecl | DeferStmt | EnumDecl | ExprStmt | FnDecl | ForCStmt | ForInStmt |
@@ -446,6 +446,12 @@ pub mut:
446446
left_as_name string // only used in x is SumType check
447447
}
448448

449+
pub struct UnsafeExpr {
450+
pub:
451+
stmts []Stmt
452+
pos token.Position
453+
}
454+
449455
pub struct LockExpr {
450456
pub:
451457
stmts []Stmt

vlib/v/ast/str.v

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -254,6 +254,9 @@ pub fn (x Expr) str() string {
254254
Likely {
255255
return '_likely_(${it.expr.str()})'
256256
}
257+
UnsafeExpr {
258+
return 'unsafe { $it.stmts.len stmts }'
259+
}
257260
else {
258261
return '[unhandled expr type ${typeof(x)}]'
259262
}

vlib/v/checker/checker.v

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2031,6 +2031,7 @@ fn (mut c Checker) stmt(node ast.Stmt) {
20312031
c.type_decl(node)
20322032
}
20332033
ast.UnsafeStmt {
2034+
assert !c.inside_unsafe
20342035
c.inside_unsafe = true
20352036
c.stmts(node.stmts)
20362037
c.inside_unsafe = false
@@ -2291,6 +2292,9 @@ pub fn (mut c Checker) expr(node ast.Expr) table.Type {
22912292
node.expr_type = c.expr(node.expr)
22922293
return table.string_type
22932294
}
2295+
ast.UnsafeExpr {
2296+
return c.unsafe_expr(mut node)
2297+
}
22942298
ast.Likely {
22952299
ltype := c.expr(node.expr)
22962300
if !c.check_types(ltype, table.bool_type) {
@@ -2630,6 +2634,34 @@ pub fn (mut c Checker) lock_expr(mut node ast.LockExpr) table.Type {
26302634
return table.void_type
26312635
}
26322636

2637+
pub fn (mut c Checker) unsafe_expr(mut node ast.UnsafeExpr) table.Type {
2638+
slen := node.stmts.len
2639+
if slen > 1 {
2640+
c.error('FIXME: unsafe expression block should support multiple statements',
2641+
node.pos)
2642+
return table.none_type
2643+
}
2644+
if slen == 0 {
2645+
c.error('unsafe expression does not yield an expression', node.pos)
2646+
return table.none_type
2647+
}
2648+
assert !c.inside_unsafe
2649+
c.inside_unsafe = true
2650+
defer {
2651+
c.inside_unsafe = false
2652+
}
2653+
if slen > 1 {
2654+
c.stmts(node.stmts[0..slen - 1])
2655+
}
2656+
last := node.stmts[0]
2657+
if last is ast.ExprStmt {
2658+
t := c.expr(last.expr)
2659+
return t
2660+
}
2661+
c.error('unsafe expression does not yield an expression', node.pos)
2662+
return table.none_type
2663+
}
2664+
26332665
pub fn (mut c Checker) if_expr(mut node ast.IfExpr) table.Type {
26342666
mut expr_required := false
26352667
if c.expected_type != table.void_type {

vlib/v/fmt/fmt.v

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1051,6 +1051,11 @@ pub fn (mut f Fmt) expr(node ast.Expr) {
10511051
f.expr(node.expr)
10521052
f.write(')')
10531053
}
1054+
ast.UnsafeExpr {
1055+
f.writeln('unsafe {')
1056+
f.stmts(it.stmts)
1057+
f.writeln('}')
1058+
}
10541059
}
10551060
}
10561061

vlib/v/gen/cgen.v

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1837,6 +1837,10 @@ fn (mut g Gen) expr(node ast.Expr) {
18371837
g.expr(node.expr)
18381838
g.write(')')
18391839
}
1840+
ast.UnsafeExpr {
1841+
es := node.stmts[0] as ast.ExprStmt
1842+
g.expr(es.expr)
1843+
}
18401844
}
18411845
}
18421846

vlib/v/gen/js/js.v

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -633,6 +633,10 @@ fn (mut g JsGen) expr(node ast.Expr) {
633633
ast.ComptimeCall {
634634
// TODO
635635
}
636+
ast.UnsafeExpr {
637+
es := it.stmts[0] as ast.ExprStmt
638+
g.expr(es.expr)
639+
}
636640
}
637641
}
638642

vlib/v/parser/parser.v

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -572,6 +572,7 @@ pub fn (mut p Parser) stmt(is_top_level bool) ast.Stmt {
572572
}
573573
.key_unsafe {
574574
p.next()
575+
assert !p.inside_unsafe
575576
p.inside_unsafe = true
576577
stmts := p.parse_block()
577578
p.inside_unsafe = false

vlib/v/parser/pratt.v

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,18 @@ pub fn (mut p Parser) expr(precedence int) ast.Expr {
7979
.key_if {
8080
node = p.if_expr()
8181
}
82+
.key_unsafe {
83+
p.next()
84+
pos := p.tok.position()
85+
assert !p.inside_unsafe
86+
p.inside_unsafe = true
87+
stmts := p.parse_block()
88+
p.inside_unsafe = false
89+
node = ast.UnsafeExpr {
90+
stmts: stmts
91+
pos: pos
92+
}
93+
}
8294
.key_lock, .key_rlock {
8395
node = p.lock_expr()
8496
}

vlib/v/tests/ptr_arithmetic_test.v

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,20 @@ fn test_ptr_arithmetic(){
66
p += 2
77
p = p - 1
88
}
9+
assert p == unsafe {&v + 2}
10+
p = unsafe { p + 1 }
11+
assert p == unsafe {&v + 3}
12+
r := unsafe { p++ }
13+
assert r == unsafe {&v + 3}
14+
assert p == unsafe {&v + 4}
915

1016
// byteptr, voidptr, charptr are handled differently
11-
mut q := byteptr(1)
17+
mut q := byteptr(10)
1218
unsafe {
1319
q -= 2
1420
q = q + 1
1521
}
22+
assert q == byteptr(9)
23+
s := unsafe { q - 1 }
24+
assert s == byteptr(8)
1625
}

0 commit comments

Comments
 (0)