Phase 8.2 foundation: @[Checked] attr, &T refs, own keyword — gradual ownership syntax

This commit is contained in:
2026-05-31 13:39:20 +03:00
parent f71c034d9e
commit 3949a2f91e
11 changed files with 67 additions and 7 deletions
+4
View File
@@ -0,0 +1,4 @@
[Package]
Name = "test"
Version = "0.1.0"
Type = "bin"
+2
View File
@@ -0,0 +1,2 @@
import Std::Io::PrintLine;
func Main() -> int { PrintLine("foundation ok"); return 0; }
+34
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.