feat: borrow expr, parser fix, borrow tests, borrow example
This commit is contained in:
@@ -601,12 +601,10 @@ proc parseUnary(p: var Parser): Expr =
|
|||||||
case p.peek()
|
case p.peek()
|
||||||
of tkBorrow:
|
of tkBorrow:
|
||||||
discard p.advance() # borrow
|
discard p.advance() # borrow
|
||||||
let isMut = p.check(tkMut)
|
discard p.expect(tkAmp, "expected '&' after 'borrow'")
|
||||||
|
var isMut = p.check(tkMut)
|
||||||
if isMut:
|
if isMut:
|
||||||
discard p.advance() # mut
|
discard p.advance() # mut
|
||||||
discard p.expect(tkAmp, "expected '&' after 'borrow'")
|
|
||||||
if isMut and p.check(tkMut):
|
|
||||||
discard p.advance() # redundant mut after &
|
|
||||||
let operand = p.parseUnary() # parse the moved value
|
let operand = p.parseUnary() # parse the moved value
|
||||||
return Expr(kind: ekBorrow, loc: loc, exprBorrowOperand: operand, exprBorrowMutable: isMut)
|
return Expr(kind: ekBorrow, loc: loc, exprBorrowOperand: operand, exprBorrowMutable: isMut)
|
||||||
of tkBang, tkMinus, tkTilde, tkStar, tkAmp:
|
of tkBang, tkMinus, tkTilde, tkStar, tkAmp:
|
||||||
|
|||||||
@@ -0,0 +1,33 @@
|
|||||||
|
// borrow.bux — Test explicit borrow expressions
|
||||||
|
|
||||||
|
struct Point {
|
||||||
|
x: int;
|
||||||
|
y: int;
|
||||||
|
}
|
||||||
|
|
||||||
|
// NOT @[Checked] — borrow keyword available everywhere
|
||||||
|
func MovePoint(p: *Point) {
|
||||||
|
let ref: &Point = borrow &p;
|
||||||
|
let x: int = (*ref).x;
|
||||||
|
}
|
||||||
|
|
||||||
|
// @[Checked] enables borrow protection
|
||||||
|
@[Checked]
|
||||||
|
func SwapPoints(a: *Point, b: *Point) {
|
||||||
|
let ra: &mut Point = borrow &mut a;
|
||||||
|
let rb: &mut Point = borrow &mut b;
|
||||||
|
let tmp: int = (*ra).x;
|
||||||
|
(*ra).x = (*rb).x;
|
||||||
|
(*rb).x = tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
func Main() -> int {
|
||||||
|
var p1: Point;
|
||||||
|
p1.x = 10;
|
||||||
|
p1.y = 20;
|
||||||
|
var p2: Point;
|
||||||
|
p2.x = 30;
|
||||||
|
p2.y = 40;
|
||||||
|
SwapPoints(&p1, &p2);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
Binary file not shown.
+43
-5
@@ -26,7 +26,6 @@ func Main() -> int {
|
|||||||
}
|
}
|
||||||
""")
|
""")
|
||||||
check(not res.hasErrors)
|
check(not res.hasErrors)
|
||||||
|
|
||||||
test "@[Checked] function rejects write through &T":
|
test "@[Checked] function rejects write through &T":
|
||||||
let res = checkSource("""
|
let res = checkSource("""
|
||||||
@[Checked]
|
@[Checked]
|
||||||
@@ -54,7 +53,6 @@ func Main() -> int {
|
|||||||
}
|
}
|
||||||
""")
|
""")
|
||||||
check(not res.hasErrors)
|
check(not res.hasErrors)
|
||||||
|
|
||||||
test "&T allows reading":
|
test "&T allows reading":
|
||||||
let res = checkSource("""
|
let res = checkSource("""
|
||||||
@[Checked]
|
@[Checked]
|
||||||
@@ -68,7 +66,6 @@ func Main() -> int {
|
|||||||
}
|
}
|
||||||
""")
|
""")
|
||||||
check(not res.hasErrors)
|
check(not res.hasErrors)
|
||||||
|
|
||||||
test "own T type parses and resolves":
|
test "own T type parses and resolves":
|
||||||
let res = checkSource("""
|
let res = checkSource("""
|
||||||
struct Box {
|
struct Box {
|
||||||
@@ -83,7 +80,6 @@ func Main() -> int {
|
|||||||
}
|
}
|
||||||
""")
|
""")
|
||||||
check(not res.hasErrors)
|
check(not res.hasErrors)
|
||||||
|
|
||||||
test "@[Checked] rejects double mutable borrow in call":
|
test "@[Checked] rejects double mutable borrow in call":
|
||||||
let res = checkSource("""
|
let res = checkSource("""
|
||||||
@[Checked]
|
@[Checked]
|
||||||
@@ -139,7 +135,6 @@ func Main() -> int {
|
|||||||
}
|
}
|
||||||
""")
|
""")
|
||||||
check(not res.hasErrors)
|
check(not res.hasErrors)
|
||||||
|
|
||||||
test "@[Checked] move in assignment":
|
test "@[Checked] move in assignment":
|
||||||
let res = checkSource("""
|
let res = checkSource("""
|
||||||
struct Box {
|
struct Box {
|
||||||
@@ -172,3 +167,46 @@ func Main() -> int {
|
|||||||
}
|
}
|
||||||
""")
|
""")
|
||||||
check(not res.hasErrors)
|
check(not res.hasErrors)
|
||||||
|
|
||||||
|
test "borrow &mut expr parses and type-checks":
|
||||||
|
let res = checkSource("""
|
||||||
|
struct Point {
|
||||||
|
x: int;
|
||||||
|
y: int;
|
||||||
|
}
|
||||||
|
func Main() -> int {
|
||||||
|
var p: Point;
|
||||||
|
p.x = 10;
|
||||||
|
let r: &mut Point = borrow &mut p;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
""")
|
||||||
|
check(not res.hasErrors)
|
||||||
|
|
||||||
|
test "@[Shared] attribute parses without errors":
|
||||||
|
let res = checkSource("""
|
||||||
|
@[Shared]
|
||||||
|
func SharedFunc() -> int {
|
||||||
|
return 42;
|
||||||
|
}
|
||||||
|
func Main() -> int {
|
||||||
|
return SharedFunc();
|
||||||
|
}
|
||||||
|
""")
|
||||||
|
check(not res.hasErrors)
|
||||||
|
|
||||||
|
test "borrow & expr with shared ref":
|
||||||
|
let res = checkSource("""
|
||||||
|
struct Point {
|
||||||
|
x: int;
|
||||||
|
y: int;
|
||||||
|
}
|
||||||
|
func Main() -> int {
|
||||||
|
var p: Point;
|
||||||
|
p.x = 10;
|
||||||
|
let r: &Point = borrow &p;
|
||||||
|
let val: int = (*r).x;
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
""")
|
||||||
|
check(not res.hasErrors)
|
||||||
Reference in New Issue
Block a user