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 |
|
CharLiteral | ComptimeCall | ConcatExpr | EnumVal | FloatLiteral | Ident | IfExpr | IfGuardExpr |
|
||||||
IndexExpr | InfixExpr | IntegerLiteral | Likely | LockExpr | MapInit | MatchExpr | None |
|
IndexExpr | InfixExpr | IntegerLiteral | Likely | LockExpr | MapInit | MatchExpr | None |
|
||||||
OrExpr | ParExpr | PostfixExpr | PrefixExpr | RangeExpr | SelectorExpr | SizeOf | SqlExpr |
|
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 |
|
pub type Stmt = AssertStmt | AssignStmt | Attr | Block | BranchStmt | Comment | CompFor |
|
||||||
CompIf | ConstDecl | DeferStmt | EnumDecl | ExprStmt | FnDecl | ForCStmt | ForInStmt |
|
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
|
left_as_name string // only used in x is SumType check
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct UnsafeExpr {
|
||||||
|
pub:
|
||||||
|
stmts []Stmt
|
||||||
|
pos token.Position
|
||||||
|
}
|
||||||
|
|
||||||
pub struct LockExpr {
|
pub struct LockExpr {
|
||||||
pub:
|
pub:
|
||||||
stmts []Stmt
|
stmts []Stmt
|
||||||
|
|
|
@ -254,6 +254,9 @@ pub fn (x Expr) str() string {
|
||||||
Likely {
|
Likely {
|
||||||
return '_likely_(${it.expr.str()})'
|
return '_likely_(${it.expr.str()})'
|
||||||
}
|
}
|
||||||
|
UnsafeExpr {
|
||||||
|
return 'unsafe { $it.stmts.len stmts }'
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
return '[unhandled expr type ${typeof(x)}]'
|
return '[unhandled expr type ${typeof(x)}]'
|
||||||
}
|
}
|
||||||
|
|
|
@ -2031,6 +2031,7 @@ fn (mut c Checker) stmt(node ast.Stmt) {
|
||||||
c.type_decl(node)
|
c.type_decl(node)
|
||||||
}
|
}
|
||||||
ast.UnsafeStmt {
|
ast.UnsafeStmt {
|
||||||
|
assert !c.inside_unsafe
|
||||||
c.inside_unsafe = true
|
c.inside_unsafe = true
|
||||||
c.stmts(node.stmts)
|
c.stmts(node.stmts)
|
||||||
c.inside_unsafe = false
|
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)
|
node.expr_type = c.expr(node.expr)
|
||||||
return table.string_type
|
return table.string_type
|
||||||
}
|
}
|
||||||
|
ast.UnsafeExpr {
|
||||||
|
return c.unsafe_expr(mut node)
|
||||||
|
}
|
||||||
ast.Likely {
|
ast.Likely {
|
||||||
ltype := c.expr(node.expr)
|
ltype := c.expr(node.expr)
|
||||||
if !c.check_types(ltype, table.bool_type) {
|
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
|
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 {
|
pub fn (mut c Checker) if_expr(mut node ast.IfExpr) table.Type {
|
||||||
mut expr_required := false
|
mut expr_required := false
|
||||||
if c.expected_type != table.void_type {
|
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.expr(node.expr)
|
||||||
f.write(')')
|
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.expr(node.expr)
|
||||||
g.write(')')
|
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 {
|
ast.ComptimeCall {
|
||||||
// TODO
|
// 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 {
|
.key_unsafe {
|
||||||
p.next()
|
p.next()
|
||||||
|
assert !p.inside_unsafe
|
||||||
p.inside_unsafe = true
|
p.inside_unsafe = true
|
||||||
stmts := p.parse_block()
|
stmts := p.parse_block()
|
||||||
p.inside_unsafe = false
|
p.inside_unsafe = false
|
||||||
|
|
|
@ -79,6 +79,18 @@ pub fn (mut p Parser) expr(precedence int) ast.Expr {
|
||||||
.key_if {
|
.key_if {
|
||||||
node = p.if_expr()
|
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 {
|
.key_lock, .key_rlock {
|
||||||
node = p.lock_expr()
|
node = p.lock_expr()
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,11 +6,20 @@ fn test_ptr_arithmetic(){
|
||||||
p += 2
|
p += 2
|
||||||
p = p - 1
|
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
|
// byteptr, voidptr, charptr are handled differently
|
||||||
mut q := byteptr(1)
|
mut q := byteptr(10)
|
||||||
unsafe {
|
unsafe {
|
||||||
q -= 2
|
q -= 2
|
||||||
q = q + 1
|
q = q + 1
|
||||||
}
|
}
|
||||||
|
assert q == byteptr(9)
|
||||||
|
s := unsafe { q - 1 }
|
||||||
|
assert s == byteptr(8)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue