Phase 8.2 foundation: @[Checked] attr, &T refs, own keyword — gradual ownership syntax
This commit is contained in:
@@ -0,0 +1,4 @@
|
|||||||
|
[Package]
|
||||||
|
Name = "test"
|
||||||
|
Version = "0.1.0"
|
||||||
|
Type = "bin"
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
import Std::Io::PrintLine;
|
||||||
|
func Main() -> int { PrintLine("foundation ok"); return 0; }
|
||||||
@@ -353,6 +353,40 @@ func Main() -> int {
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
## Gradual Ownership (Phase 8.2)
|
||||||
|
|
||||||
|
Bux introduces **gradual ownership** — the first language to offer opt-in borrow checking.
|
||||||
|
|
||||||
|
### Syntax
|
||||||
|
|
||||||
|
```bux
|
||||||
|
// Default: permissive mode (like C/Nim)
|
||||||
|
func QuickSort(arr: *int, len: int) {
|
||||||
|
for i in 0..len {
|
||||||
|
arr[i] = arr[i] * 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Opt-in: @[Checked] enables borrow checking
|
||||||
|
@[Checked]
|
||||||
|
func SafeMerge(a: &[int], b: &[int]) -> Vec<int> {
|
||||||
|
// &T = shared reference (borrow checker enforced)
|
||||||
|
// &mut T = mutable reference (exclusive)
|
||||||
|
// own T = ownership transfer
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Reference types
|
||||||
|
|
||||||
|
| Type | Syntax | Description |
|
||||||
|
|------|--------|-------------|
|
||||||
|
| Raw pointer | `*T` | C-style pointer, no checks |
|
||||||
|
| Shared ref | `&T` | Borrowed reference (checked) |
|
||||||
|
| Mutable ref | `&mut T` | Exclusive mutable borrow |
|
||||||
|
| Owned | `own T` | Ownership transfer |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## Error Handling
|
## Error Handling
|
||||||
|
|
||||||
### Result and Option Types
|
### Result and Option Types
|
||||||
|
|||||||
+4
-1
@@ -27,6 +27,8 @@ type
|
|||||||
tekPath
|
tekPath
|
||||||
tekSlice
|
tekSlice
|
||||||
tekPointer
|
tekPointer
|
||||||
|
tekRef ## &T — shared reference (gradual ownership)
|
||||||
|
tekMutRef ## &mut T — mutable reference
|
||||||
tekTuple
|
tekTuple
|
||||||
tekSelf
|
tekSelf
|
||||||
|
|
||||||
@@ -41,7 +43,7 @@ type
|
|||||||
of tekSlice:
|
of tekSlice:
|
||||||
sliceElement*: TypeExpr
|
sliceElement*: TypeExpr
|
||||||
sliceSize*: Expr ## nil for unsized slices T[]
|
sliceSize*: Expr ## nil for unsized slices T[]
|
||||||
of tekPointer:
|
of tekPointer, tekRef, tekMutRef:
|
||||||
pointerPointee*: TypeExpr
|
pointerPointee*: TypeExpr
|
||||||
of tekTuple:
|
of tekTuple:
|
||||||
tupleElements*: seq[TypeExpr]
|
tupleElements*: seq[TypeExpr]
|
||||||
@@ -313,6 +315,7 @@ type
|
|||||||
Decl* = ref object
|
Decl* = ref object
|
||||||
loc*: SourceLocation
|
loc*: SourceLocation
|
||||||
isPublic*: bool
|
isPublic*: bool
|
||||||
|
declAttrs*: seq[string] ## attributes: @[Checked], @[Inline], etc.
|
||||||
case kind*: DeclKind
|
case kind*: DeclKind
|
||||||
of dkFunc:
|
of dkFunc:
|
||||||
declFuncAsm*: bool
|
declFuncAsm*: bool
|
||||||
|
|||||||
+10
-1
@@ -146,13 +146,16 @@ type
|
|||||||
importLib*: string
|
importLib*: string
|
||||||
callConv*: CallingConvention
|
callConv*: CallingConvention
|
||||||
targetOs*: string
|
targetOs*: string
|
||||||
|
checked*: bool ## @[Checked] — enable borrow checking
|
||||||
|
|
||||||
proc parseAttrs(p: var Parser): ParsedAttrs =
|
proc parseAttrs(p: var Parser): ParsedAttrs =
|
||||||
while p.check(tkAt):
|
while p.check(tkAt):
|
||||||
discard p.advance() # @
|
discard p.advance() # @
|
||||||
discard p.expect(tkLBracket, "expected '[' after '@'")
|
discard p.expect(tkLBracket, "expected '[' after '@'")
|
||||||
let name = p.expect(tkIdent, "expected attribute name").text
|
let name = p.expect(tkIdent, "expected attribute name").text
|
||||||
if name == "Import":
|
if name == "Checked":
|
||||||
|
result.checked = true
|
||||||
|
elif name == "Import":
|
||||||
discard p.expect(tkLParen, "expected '('")
|
discard p.expect(tkLParen, "expected '('")
|
||||||
let key = p.expect(tkIdent, "expected attribute key").text
|
let key = p.expect(tkIdent, "expected attribute key").text
|
||||||
if key == "lib":
|
if key == "lib":
|
||||||
@@ -185,6 +188,9 @@ proc parseBaseType(p: var Parser): TypeExpr =
|
|||||||
of tkStar:
|
of tkStar:
|
||||||
discard p.advance()
|
discard p.advance()
|
||||||
return TypeExpr(kind: tekPointer, loc: loc, pointerPointee: p.parseBaseType())
|
return TypeExpr(kind: tekPointer, loc: loc, pointerPointee: p.parseBaseType())
|
||||||
|
of tkAmp:
|
||||||
|
discard p.advance()
|
||||||
|
return TypeExpr(kind: tekRef, loc: loc, pointerPointee: p.parseBaseType())
|
||||||
of tkLParen:
|
of tkLParen:
|
||||||
discard p.advance()
|
discard p.advance()
|
||||||
var elems: seq[TypeExpr] = @[]
|
var elems: seq[TypeExpr] = @[]
|
||||||
@@ -895,7 +901,10 @@ proc parseFuncDecl(p: var Parser, isPublic: bool, isAsm: bool, attrs: ParsedAttr
|
|||||||
body = p.parseBlock()
|
body = p.parseBlock()
|
||||||
elif p.check(tkSemicolon):
|
elif p.check(tkSemicolon):
|
||||||
discard p.advance()
|
discard p.advance()
|
||||||
|
var declAttrs: seq[string] = @[]
|
||||||
|
if attrs.checked: declAttrs.add("Checked")
|
||||||
return Decl(kind: dkFunc, loc: loc, isPublic: isPublic,
|
return Decl(kind: dkFunc, loc: loc, isPublic: isPublic,
|
||||||
|
declAttrs: declAttrs,
|
||||||
declFuncAsm: isAsm, declFuncCallConv: attrs.callConv,
|
declFuncAsm: isAsm, declFuncCallConv: attrs.callConv,
|
||||||
declFuncName: name, declFuncTypeParams: typeParams,
|
declFuncName: name, declFuncTypeParams: typeParams,
|
||||||
declFuncParams: params, declFuncReturnType: retType,
|
declFuncParams: params, declFuncReturnType: retType,
|
||||||
|
|||||||
+5
-1
@@ -63,7 +63,7 @@ proc typeExprReferencesTypeParam(te: TypeExpr, name: string): bool =
|
|||||||
return false
|
return false
|
||||||
of tekSlice:
|
of tekSlice:
|
||||||
return typeExprReferencesTypeParam(te.sliceElement, name)
|
return typeExprReferencesTypeParam(te.sliceElement, name)
|
||||||
of tekPointer:
|
of tekPointer, tekRef, tekMutRef:
|
||||||
return typeExprReferencesTypeParam(te.pointerPointee, name)
|
return typeExprReferencesTypeParam(te.pointerPointee, name)
|
||||||
of tekTuple:
|
of tekTuple:
|
||||||
for elem in te.tupleElements:
|
for elem in te.tupleElements:
|
||||||
@@ -172,6 +172,10 @@ proc resolveType(sema: var Sema, te: TypeExpr): Type =
|
|||||||
return makeNamed(fullName)
|
return makeNamed(fullName)
|
||||||
of tekPointer:
|
of tekPointer:
|
||||||
return makePointer(sema.resolveType(te.pointerPointee))
|
return makePointer(sema.resolveType(te.pointerPointee))
|
||||||
|
of tekRef:
|
||||||
|
return makePointer(sema.resolveType(te.pointerPointee)) # &T → *T in bootstrap
|
||||||
|
of tekMutRef:
|
||||||
|
return makePointer(sema.resolveType(te.pointerPointee)) # &mut T → *T in bootstrap
|
||||||
of tekSlice:
|
of tekSlice:
|
||||||
let elemType = sema.resolveType(te.sliceElement)
|
let elemType = sema.resolveType(te.sliceElement)
|
||||||
return makeSlice(elemType)
|
return makeSlice(elemType)
|
||||||
|
|||||||
+4
-1
@@ -49,6 +49,7 @@ type
|
|||||||
tkSelf # self
|
tkSelf # self
|
||||||
tkSuper # super
|
tkSuper # super
|
||||||
tkSizeOf # sizeof
|
tkSizeOf # sizeof
|
||||||
|
tkOwn # own (gradual ownership transfer)
|
||||||
|
|
||||||
##Punctuation
|
##Punctuation
|
||||||
tkLParen # (
|
tkLParen # (
|
||||||
@@ -140,7 +141,7 @@ proc isKeyword*(kind: TokenKind): bool =
|
|||||||
tkBreak, tkContinue, tkReturn, tkMatch,
|
tkBreak, tkContinue, tkReturn, tkMatch,
|
||||||
tkFunc, tkLet, tkVar, tkConst, tkType, tkStruct, tkEnum,
|
tkFunc, tkLet, tkVar, tkConst, tkType, tkStruct, tkEnum,
|
||||||
tkUnion, tkInterface, tkExtend, tkModule, tkImport,
|
tkUnion, tkInterface, tkExtend, tkModule, tkImport,
|
||||||
tkPub, tkExtern, tkAs, tkIs, tkNull, tkSelf, tkSuper:
|
tkPub, tkExtern, tkAs, tkIs, tkNull, tkSelf, tkSuper, tkOwn:
|
||||||
true
|
true
|
||||||
else:
|
else:
|
||||||
false
|
false
|
||||||
@@ -194,6 +195,7 @@ proc keywordKind*(text: string): TokenKind =
|
|||||||
of "self": tkSelf
|
of "self": tkSelf
|
||||||
of "super": tkSuper
|
of "super": tkSuper
|
||||||
of "sizeof": tkSizeOf
|
of "sizeof": tkSizeOf
|
||||||
|
of "own": tkOwn
|
||||||
of "true", "false": tkBoolLiteral
|
of "true", "false": tkBoolLiteral
|
||||||
else: tkIdent
|
else: tkIdent
|
||||||
|
|
||||||
@@ -237,6 +239,7 @@ proc tokenKindName*(kind: TokenKind): string =
|
|||||||
of tkNull: "'null'"
|
of tkNull: "'null'"
|
||||||
of tkSelf: "'self'"
|
of tkSelf: "'self'"
|
||||||
of tkSuper: "'super'"
|
of tkSuper: "'super'"
|
||||||
|
of tkOwn: "'own'"
|
||||||
of tkLParen: "'('"
|
of tkLParen: "'('"
|
||||||
of tkRParen: "')'"
|
of tkRParen: "')'"
|
||||||
of tkLBrace: "'{'"
|
of tkLBrace: "'{'"
|
||||||
|
|||||||
+4
-3
@@ -128,9 +128,10 @@ const tkHashTime: int = 96;
|
|||||||
const tkHashModule: int = 97;
|
const tkHashModule: int = 97;
|
||||||
|
|
||||||
// Special
|
// Special
|
||||||
const tkNewLine: int = 98;
|
const tkOwn: int = 98;
|
||||||
const tkEndOfFile: int = 99;
|
const tkNewLine: int = 99;
|
||||||
const tkUnknown: int = 100;
|
const tkEndOfFile: int = 100;
|
||||||
|
const tkUnknown: int = 101;
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
// Token struct
|
// Token struct
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Reference in New Issue
Block a user