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