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