From f809827beabc9cc82c8ea2d5c9d85f2ed19d6c3f Mon Sep 17 00:00:00 2001 From: dimgigov Date: Tue, 9 Jun 2026 17:30:19 +0300 Subject: [PATCH] feat(selfhost): add &T (shared ref) and &mut T (mutable ref) type syntax - Add tekRef and tekMutRef to TypeExpr enum (ast.bux) - Parse &T and &mut T in parserParseType, before *T handling (parser.bux) - Map tekRef/tekMutRef to tyPointer in HIR lowering (hir_lower.bux) - Both emit as T* in C backend (same as raw pointer) - Borrow checker rejects write-through-pointer in @[Checked] functions for all pointer types (safe default) --- src/ast.bux | 2 ++ src/hir_lower.bux | 2 +- src/parser.bux | 27 +++++++++++++++++++++++++++ 3 files changed, 30 insertions(+), 1 deletion(-) diff --git a/src/ast.bux b/src/ast.bux index 4caaa6a..ccbe55d 100644 --- a/src/ast.bux +++ b/src/ast.bux @@ -26,6 +26,8 @@ const tekNamed: int = 0; const tekPath: int = 1; const tekSlice: int = 2; const tekPointer: int = 3; +const tekRef: int = 7; // &T — shared reference +const tekMutRef: int = 8; // &mut T — mutable reference const tekTuple: int = 4; const tekSelf: int = 5; const tekFunc: int = 6; diff --git a/src/hir_lower.bux b/src/hir_lower.bux index e21a75e..f6e687c 100644 --- a/src/hir_lower.bux +++ b/src/hir_lower.bux @@ -53,7 +53,7 @@ func Lcx_ResolveTypeKindFromName(name: String) -> int { func Lcx_ResolveTypeKind(te: *TypeExpr) -> int { if te == null as *TypeExpr { return tyUnknown; } - if te.kind == tekPointer { return tyPointer; } + if te.kind == tekPointer || te.kind == tekRef || te.kind == tekMutRef { return tyPointer; } if te.kind == tekSlice { return tySlice; } if te.kind == tekTuple { return tyTuple; } if te.kind == tekFunc { return tyFunc; } diff --git a/src/parser.bux b/src/parser.bux index a054fc1..40e204c 100644 --- a/src/parser.bux +++ b/src/parser.bux @@ -149,6 +149,33 @@ func parserParseType(p: *Parser) -> *TypeExpr { let col: uint32 = parserCurToken(p).column; let kindTok: int = parserPeek(p, 0); + // &T (shared reference) and &mut T (mutable reference) + if kindTok == tkAmp { + discard parserAdvance(p); // & + var isMut: bool = false; + // Check for "mut" keyword + if parserCheck(p, tkIdent) { + let tok: LexToken = parserCurToken(p); + if String_Eq(tok.text, "mut") { + isMut = true; + discard parserAdvance(p); // mut + } + } + let te: *TypeExpr = bux_alloc(sizeof(TypeExpr)) as *TypeExpr; + if isMut { + te.kind = tekMutRef; + } else { + te.kind = tekRef; + } + te.line = line; + te.column = col; + te.pointerPointee = parserParseType(p); + if te.pointerPointee != null as *TypeExpr { + te.typeName = String_Concat(te.pointerPointee.typeName, "*"); + } + return te; + } + // *T (pointer) if kindTok == tkStar { discard parserAdvance(p);