File tree Expand file tree Collapse file tree 9 files changed +78
-2
lines changed Expand file tree Collapse file tree 9 files changed +78
-2
lines changed Original file line number Diff line number Diff line change @@ -13,7 +13,7 @@ pub type Expr = AnonFn | ArrayInit | AsCast | Assoc | BoolLiteral | CallExpr | C
13
13
CharLiteral | ComptimeCall | ConcatExpr | EnumVal | FloatLiteral | Ident | IfExpr | IfGuardExpr |
14
14
IndexExpr | InfixExpr | IntegerLiteral | Likely | LockExpr | MapInit | MatchExpr | None |
15
15
OrExpr | ParExpr | PostfixExpr | PrefixExpr | RangeExpr | SelectorExpr | SizeOf | SqlExpr |
16
- StringInterLiteral | StringLiteral | StructInit | Type | TypeOf
16
+ StringInterLiteral | StringLiteral | StructInit | Type | TypeOf | UnsafeExpr
17
17
18
18
pub type Stmt = AssertStmt | AssignStmt | Attr | Block | BranchStmt | Comment | CompFor |
19
19
CompIf | ConstDecl | DeferStmt | EnumDecl | ExprStmt | FnDecl | ForCStmt | ForInStmt |
@@ -446,6 +446,12 @@ pub mut:
446
446
left_as_name string // only used in x is SumType check
447
447
}
448
448
449
+ pub struct UnsafeExpr {
450
+ pub :
451
+ stmts []Stmt
452
+ pos token.Position
453
+ }
454
+
449
455
pub struct LockExpr {
450
456
pub :
451
457
stmts []Stmt
Original file line number Diff line number Diff line change @@ -254,6 +254,9 @@ pub fn (x Expr) str() string {
254
254
Likely {
255
255
return '_likely_(${it.expr.str()} )'
256
256
}
257
+ UnsafeExpr {
258
+ return 'unsafe { $it.stmts.len stmts }'
259
+ }
257
260
else {
258
261
return '[unhandled expr type ${typeof(x)} ]'
259
262
}
Original file line number Diff line number Diff line change @@ -2031,6 +2031,7 @@ fn (mut c Checker) stmt(node ast.Stmt) {
2031
2031
c.type_decl (node)
2032
2032
}
2033
2033
ast.UnsafeStmt {
2034
+ assert ! c.inside_unsafe
2034
2035
c.inside_unsafe = true
2035
2036
c.stmts (node.stmts)
2036
2037
c.inside_unsafe = false
@@ -2291,6 +2292,9 @@ pub fn (mut c Checker) expr(node ast.Expr) table.Type {
2291
2292
node.expr_type = c.expr (node.expr)
2292
2293
return table.string_type
2293
2294
}
2295
+ ast.UnsafeExpr {
2296
+ return c.unsafe_expr (mut node)
2297
+ }
2294
2298
ast.Likely {
2295
2299
ltype := c.expr (node.expr)
2296
2300
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 {
2630
2634
return table.void_type
2631
2635
}
2632
2636
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
+
2633
2665
pub fn (mut c Checker) if_expr (mut node ast.IfExpr) table.Type {
2634
2666
mut expr_required := false
2635
2667
if c.expected_type != table.void_type {
Original file line number Diff line number Diff line change @@ -1051,6 +1051,11 @@ pub fn (mut f Fmt) expr(node ast.Expr) {
1051
1051
f.expr (node.expr)
1052
1052
f.write (')' )
1053
1053
}
1054
+ ast.UnsafeExpr {
1055
+ f.writeln ('unsafe {' )
1056
+ f.stmts (it .stmts)
1057
+ f.writeln ('}' )
1058
+ }
1054
1059
}
1055
1060
}
1056
1061
Original file line number Diff line number Diff line change @@ -1837,6 +1837,10 @@ fn (mut g Gen) expr(node ast.Expr) {
1837
1837
g.expr (node.expr)
1838
1838
g.write (')' )
1839
1839
}
1840
+ ast.UnsafeExpr {
1841
+ es := node.stmts[0 ] as ast.ExprStmt
1842
+ g.expr (es.expr)
1843
+ }
1840
1844
}
1841
1845
}
1842
1846
Original file line number Diff line number Diff line change @@ -633,6 +633,10 @@ fn (mut g JsGen) expr(node ast.Expr) {
633
633
ast.ComptimeCall {
634
634
// TODO
635
635
}
636
+ ast.UnsafeExpr {
637
+ es := it .stmts[0 ] as ast.ExprStmt
638
+ g.expr (es.expr)
639
+ }
636
640
}
637
641
}
638
642
Original file line number Diff line number Diff line change @@ -572,6 +572,7 @@ pub fn (mut p Parser) stmt(is_top_level bool) ast.Stmt {
572
572
}
573
573
.key_unsafe {
574
574
p.next ()
575
+ assert ! p.inside_unsafe
575
576
p.inside_unsafe = true
576
577
stmts := p.parse_block ()
577
578
p.inside_unsafe = false
Original file line number Diff line number Diff line change @@ -79,6 +79,18 @@ pub fn (mut p Parser) expr(precedence int) ast.Expr {
79
79
.key_if {
80
80
node = p.if_expr ()
81
81
}
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
+ }
82
94
.key_lock, .key_rlock {
83
95
node = p.lock_expr ()
84
96
}
Original file line number Diff line number Diff line change @@ -6,11 +6,20 @@ fn test_ptr_arithmetic(){
6
6
p + = 2
7
7
p = p - 1
8
8
}
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 }
9
15
10
16
// byteptr, voidptr, charptr are handled differently
11
- mut q := byteptr (1 )
17
+ mut q := byteptr (10 )
12
18
unsafe {
13
19
q - = 2
14
20
q = q + 1
15
21
}
22
+ assert q == byteptr (9 )
23
+ s := unsafe { q - 1 }
24
+ assert s == byteptr (8 )
16
25
}
You can’t perform that action at this time.
0 commit comments