feat: Phase 8.2, 8.4, 8.5, 9.1 + C backend fixes

Phase 8.2 — Gradual Ownership:
- Add tkRef/tkMutRef types and `mut` keyword
- Add @[Checked] attribute for opt-in borrow checking
- Reject assignment through &T in checked functions
- examples/ownership.bux

Phase 8.4 — CTFE:
- Evaluate const func at compile-time via evalExpr/evalBlock
- Fold const declarations to literals; emit #define in C
- examples/ctfe.bux (Factorial(10) → 3628800)

Phase 8.5 — Trait Bounds:
- Change declFuncTypeParams from seq[string] to seq[TypeParam] (name + bound)
- Parser handles <T: Comparable>
- Sema checks typeImplements at call sites
- Fix C backend: generic receivers + pointer self field access
- examples/trait_bounds.bux

Phase 9.1 — Package Manager:
- Inline tables/arrays in TOML parser
- bux add, bux install, bux.lock generation
- Dependency resolution with git/path sources
- Build pipeline merges dependency .bux sources

C Backend Fixes:
- resolveExprType(ekIdent) now applies typeSubst for generic params
- Method desugaring works for monomorphized generic receivers
- Pointer checks use isPointer (covers tkRef/tkMutRef)
- Field access on &T emits -> instead of .

Remove accidentally committed test binaries from tracking
This commit is contained in:
2026-05-31 23:48:45 +03:00
parent b1f1fc277c
commit 8e255b2125
21 changed files with 1360 additions and 111 deletions
+24 -28
View File
@@ -166,6 +166,10 @@ proc substituteType(ctx: var LowerCtx, te: TypeExpr, subst: Table[string, Type])
return ctx.resolveTypeExpr(te)
of tekPointer:
return makePointer(substituteType(ctx, te.pointerPointee, subst))
of tekRef:
return makeRef(substituteType(ctx, te.pointerPointee, subst))
of tekMutRef:
return makeMutRef(substituteType(ctx, te.pointerPointee, subst))
of tekSlice:
return makeSlice(substituteType(ctx, te.sliceElement, subst))
of tekTuple:
@@ -194,7 +198,7 @@ proc resolveTypeExpr(ctx: var LowerCtx, te: TypeExpr): Type =
var concreteArgs: seq[Type] = @[]
for j, tp in genericDecl.declStructTypeParams:
if j < te.typeArgs.len:
subst[tp] = ctx.resolveTypeExpr(te.typeArgs[j])
subst[tp.name] = ctx.resolveTypeExpr(te.typeArgs[j])
for arg in te.typeArgs:
concreteArgs.add(ctx.resolveTypeExpr(arg))
for f in genericDecl.declStructFields:
@@ -257,7 +261,7 @@ proc resolveExprType(ctx: var LowerCtx, expr: Expr): Type =
if sym != nil and sym.typ != nil: return sym.typ
# Check local variables and parameters tracked in varTypeExprs
if ctx.varTypeExprs.hasKey(expr.exprIdent):
return ctx.resolveTypeExpr(ctx.varTypeExprs[expr.exprIdent])
return substituteType(ctx, ctx.varTypeExprs[expr.exprIdent], ctx.typeSubst)
# Check current function parameters (fallback for untracked params)
if ctx.currentFuncDecl != nil:
var params: seq[Param] = @[]
@@ -267,21 +271,7 @@ proc resolveExprType(ctx: var LowerCtx, expr: Expr): Type =
else: discard
for p in params:
if p.name == expr.exprIdent and p.ptype != nil:
case p.ptype.kind
of tekNamed:
case p.ptype.typeName
of "int", "int32": return makeInt()
of "int64": return makeInt64()
of "float64": return makeFloat64()
of "float32": return makeFloat32()
of "bool": return makeBool()
of "uint": return makeUInt()
of "void": return makeVoid()
else: return makeNamed(p.ptype.typeName)
of tekPointer:
let pointeeType = ctx.resolveTypeExpr(p.ptype.pointerPointee)
return makePointer(pointeeType)
else: discard
return substituteType(ctx, p.ptype, ctx.typeSubst)
return makeUnknown()
of ekSelf:
# Look up self parameter type from current function
@@ -329,7 +319,7 @@ proc resolveExprType(ctx: var LowerCtx, expr: Expr): Type =
of ekField:
var objType = ctx.resolveExprType(expr.exprFieldObj)
# Auto-dereference pointer types for field access
if objType.kind == tkPointer and objType.inner.len > 0:
if objType.isPointer and objType.inner.len > 0:
objType = objType.inner[0]
if objType.kind == tkNamed:
let sym = ctx.globalScope.lookup(objType.name)
@@ -460,7 +450,13 @@ proc lowerExpr(ctx: var LowerCtx, expr: Expr): HirNode =
var receiverTypeName = ""
if receiverType.kind == tkNamed:
receiverTypeName = receiverType.name
elif receiverType.kind == tkPointer and receiverType.inner.len > 0 and receiverType.inner[0].kind == tkNamed:
if ctx.typeSubst.hasKey(receiverTypeName):
let substituted = ctx.typeSubst[receiverTypeName]
if substituted.kind == tkNamed:
receiverTypeName = substituted.name
elif substituted.isPointer and substituted.inner.len > 0 and substituted.inner[0].kind == tkNamed:
receiverTypeName = substituted.inner[0].name
elif receiverType.isPointer and receiverType.inner.len > 0 and receiverType.inner[0].kind == tkNamed:
receiverTypeName = receiverType.inner[0].name
# Look up method for receiver type specifically
@@ -477,7 +473,7 @@ proc lowerExpr(ctx: var LowerCtx, expr: Expr): HirNode =
var args: seq[HirNode] = @[]
let loweredReceiver = ctx.lowerExpr(receiverExpr)
# Auto-address if method expects pointer but receiver is value
if minfo.params.len > 0 and minfo.params[0].kind == tkPointer and receiverType.kind != tkPointer:
if minfo.params.len > 0 and minfo.params[0].isPointer and not receiverType.isPointer:
args.add(hirUnary(tkAmp, loweredReceiver, makePointer(receiverType), loc))
else:
args.add(loweredReceiver)
@@ -558,7 +554,7 @@ proc lowerExpr(ctx: var LowerCtx, expr: Expr): HirNode =
let objType = ctx.resolveExprType(expr.exprFieldObj)
let base = ctx.lowerExpr(expr.exprFieldObj)
# Auto-dereference pointer types for field access
if objType.kind == tkPointer:
if objType.isPointer:
let arrowPtr = HirNode(kind: hArrowField, arrowFieldBase: base,
arrowFieldName: expr.exprFieldName,
typ: makePointer(typ), loc: loc)
@@ -1010,7 +1006,7 @@ proc generateMethodInstance(ctx: var LowerCtx, baseMethodName: string, typeArgs:
if i > 0: typeSuffix.add("_")
if i < typeArgs.len:
let argType = ctx.resolveTypeExpr(typeArgs[i])
subst[tp] = argType
subst[tp.name] = argType
typeSuffix.add(argType.toString)
else:
typeSuffix.add("unknown")
@@ -1178,12 +1174,12 @@ proc lowerModule*(module: Module, sema: Sema): HirModule =
let targ = inst.typeArgs[j]
if targ.kind == tekNamed:
case targ.typeName
of "int", "int32": subst[tp] = makeInt()
of "int64": subst[tp] = makeInt64()
of "float64": subst[tp] = makeFloat64()
of "float32": subst[tp] = makeFloat32()
of "bool": subst[tp] = makeBool()
else: subst[tp] = makeNamed(targ.typeName)
of "int", "int32": subst[tp.name] = makeInt()
of "int64": subst[tp.name] = makeInt64()
of "float64": subst[tp.name] = makeFloat64()
of "float32": subst[tp.name] = makeFloat32()
of "bool": subst[tp.name] = makeBool()
else: subst[tp.name] = makeNamed(targ.typeName)
# Create specialized declaration
var specDecl = Decl(