all: add UnsafeExpr (#5793)
parent
cad816a19d
commit
53023c1ca9
|
@ -13,7 +13,7 @@ pub type Expr = AnonFn | ArrayInit | AsCast | Assoc | BoolLiteral | CallExpr | C
|
|||
CharLiteral | ComptimeCall | ConcatExpr | EnumVal | FloatLiteral | Ident | IfExpr | IfGuardExpr |
|
||||
IndexExpr | InfixExpr | IntegerLiteral | Likely | LockExpr | MapInit | MatchExpr | None |
|
||||
OrExpr | ParExpr | PostfixExpr | PrefixExpr | RangeExpr | SelectorExpr | SizeOf | SqlExpr |
|
||||
StringInterLiteral | StringLiteral | StructInit | Type | TypeOf
|
||||
StringInterLiteral | StringLiteral | StructInit | Type | TypeOf | UnsafeExpr
|
||||
|
||||
pub type Stmt = AssertStmt | AssignStmt | Attr | Block | BranchStmt | Comment | CompFor |
|
||||
CompIf | ConstDecl | DeferStmt | EnumDecl | ExprStmt | FnDecl | ForCStmt | ForInStmt |
|
||||
|
@ -446,6 +446,12 @@ pub mut:
|
|||
left_as_name string // only used in x is SumType check
|
||||
}
|
||||
|
||||
pub struct UnsafeExpr {
|
||||
pub:
|
||||
stmts []Stmt
|
||||
pos token.Position
|
||||
}
|
||||
|
||||
pub struct LockExpr {
|
||||
pub:
|
||||
stmts []Stmt
|
||||
|
|
|
@ -254,6 +254,9 @@ pub fn (x Expr) str() string {
|
|||
Likely {
|
||||
return '_likely_(${it.expr.str()})'
|
||||
}
|
||||
UnsafeExpr {
|
||||
return 'unsafe { $it.stmts.len stmts }'
|
||||
}
|
||||
else {
|
||||
return '[unhandled expr type ${typeof(x)}]'
|
||||
}
|
||||
|
|
|
@ -2031,6 +2031,7 @@ fn (mut c Checker) stmt(node ast.Stmt) {
|
|||
c.type_decl(node)
|
||||
}
|
||||
ast.UnsafeStmt {
|
||||
assert !c.inside_unsafe
|
||||
c.inside_unsafe = true
|
||||
c.stmts(node.stmts)
|
||||
c.inside_unsafe = false
|
||||
|
@ -2291,6 +2292,9 @@ pub fn (mut c Checker) expr(node ast.Expr) table.Type {
|
|||
node.expr_type = c.expr(node.expr)
|
||||
return table.string_type
|
||||
}
|
||||
ast.UnsafeExpr {
|
||||
return c.unsafe_expr(mut node)
|
||||
}
|
||||
ast.Likely {
|
||||
ltype := c.expr(node.expr)
|
||||
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 {
|
|||
return table.void_type
|
||||
}
|
||||
|
||||
pub fn (mut c Checker) unsafe_expr(mut node ast.UnsafeExpr) table.Type {
|
||||
slen := node.stmts.len
|
||||
if slen > 1 {
|
||||
c.error('FIXME: unsafe expression block should support multiple statements',
|
||||
node.pos)
|
||||
return table.none_type
|
||||
}
|
||||
if slen == 0 {
|
||||
c.error('unsafe expression does not yield an expression', node.pos)
|
||||
return table.none_type
|
||||
}
|
||||
assert !c.inside_unsafe
|
||||
c.inside_unsafe = true
|
||||
defer {
|
||||
c.inside_unsafe = false
|
||||
}
|
||||
if slen > 1 {
|
||||
c.stmts(node.stmts[0..slen - 1])
|
||||
}
|
||||
last := node.stmts[0]
|
||||
if last is ast.ExprStmt {
|
||||
t := c.expr(last.expr)
|
||||
return t
|
||||
}
|
||||
c.error('unsafe expression does not yield an expression', node.pos)
|
||||
return table.none_type
|
||||
}
|
||||
|
||||
pub fn (mut c Checker) if_expr(mut node ast.IfExpr) table.Type {
|
||||
mut expr_required := false
|
||||
if c.expected_type != table.void_type {
|
||||
|
|
|
@ -1051,6 +1051,11 @@ pub fn (mut f Fmt) expr(node ast.Expr) {
|
|||
f.expr(node.expr)
|
||||
f.write(')')
|
||||
}
|
||||
ast.UnsafeExpr {
|
||||
f.writeln('unsafe {')
|
||||
f.stmts(it.stmts)
|
||||
f.writeln('}')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1837,6 +1837,10 @@ fn (mut g Gen) expr(node ast.Expr) {
|
|||
g.expr(node.expr)
|
||||
g.write(')')
|
||||
}
|
||||
ast.UnsafeExpr {
|
||||
es := node.stmts[0] as ast.ExprStmt
|
||||
g.expr(es.expr)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -633,6 +633,10 @@ fn (mut g JsGen) expr(node ast.Expr) {
|
|||
ast.ComptimeCall {
|
||||
// TODO
|
||||
}
|
||||
ast.UnsafeExpr {
|
||||
es := it.stmts[0] as ast.ExprStmt
|
||||
g.expr(es.expr)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -572,6 +572,7 @@ pub fn (mut p Parser) stmt(is_top_level bool) ast.Stmt {
|
|||
}
|
||||
.key_unsafe {
|
||||
p.next()
|
||||
assert !p.inside_unsafe
|
||||
p.inside_unsafe = true
|
||||
stmts := p.parse_block()
|
||||
p.inside_unsafe = false
|
||||
|
|
|
@ -79,6 +79,18 @@ pub fn (mut p Parser) expr(precedence int) ast.Expr {
|
|||
.key_if {
|
||||
node = p.if_expr()
|
||||
}
|
||||
.key_unsafe {
|
||||
p.next()
|
||||
pos := p.tok.position()
|
||||
assert !p.inside_unsafe
|
||||
p.inside_unsafe = true
|
||||
stmts := p.parse_block()
|
||||
p.inside_unsafe = false
|
||||
node = ast.UnsafeExpr {
|
||||
stmts: stmts
|
||||
pos: pos
|
||||
}
|
||||
}
|
||||
.key_lock, .key_rlock {
|
||||
node = p.lock_expr()
|
||||
}
|
||||
|
|
|
@ -6,11 +6,20 @@ fn test_ptr_arithmetic(){
|
|||
p += 2
|
||||
p = p - 1
|
||||
}
|
||||
assert p == unsafe {&v + 2}
|
||||
p = unsafe { p + 1 }
|
||||
assert p == unsafe {&v + 3}
|
||||
r := unsafe { p++ }
|
||||
assert r == unsafe {&v + 3}
|
||||
assert p == unsafe {&v + 4}
|
||||
|
||||
// byteptr, voidptr, charptr are handled differently
|
||||
mut q := byteptr(1)
|
||||
mut q := byteptr(10)
|
||||
unsafe {
|
||||
q -= 2
|
||||
q = q + 1
|
||||
}
|
||||
assert q == byteptr(9)
|
||||
s := unsafe { q - 1 }
|
||||
assert s == byteptr(8)
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue