fix(bootstrap): implement collection for-in lowering
- Export typeToTypeExpr from sema and preserve generic type args - Derive loop variable type from collection element type in sema - Substitute generic struct type params on field access - Add getCollectionElementTypeExpr helper in hir_lower - Replace placeholder collection for-in lowering - Add Array/Iter lowering: Array_Iter_T / Iter_HasNext_T / Iter_Next_T - Add Channel lowering: Channel_Recv_Ok_T loop - Register loop variable in varTypeExprs before body lowering Fixes _test_forin_stdlib, _test_forin_channel, _test_generic_trait, _test_import, _test_mono
This commit is contained in:
+18
-4
@@ -137,7 +137,7 @@ proc typeExprReferencesTypeParam(te: TypeExpr, name: string): bool =
|
||||
of tekSelf:
|
||||
return false
|
||||
|
||||
proc typeToTypeExpr(t: Type): TypeExpr =
|
||||
proc typeToTypeExpr*(t: Type): TypeExpr =
|
||||
## Convert a resolved Type back to a TypeExpr for storage in inferred type args.
|
||||
case t.kind
|
||||
of tkInt: TypeExpr(kind: tekNamed, typeName: "int")
|
||||
@@ -154,7 +154,11 @@ proc typeToTypeExpr(t: Type): TypeExpr =
|
||||
of tkFloat64: TypeExpr(kind: tekNamed, typeName: "float64")
|
||||
of tkBool: TypeExpr(kind: tekNamed, typeName: "bool")
|
||||
of tkStr: TypeExpr(kind: tekNamed, typeName: "String")
|
||||
of tkNamed: TypeExpr(kind: tekNamed, typeName: t.name)
|
||||
of tkNamed:
|
||||
var args: seq[TypeExpr] = @[]
|
||||
for a in t.inner:
|
||||
args.add(typeToTypeExpr(a))
|
||||
return TypeExpr(kind: tekNamed, typeName: t.name, typeArgs: args)
|
||||
of tkPointer:
|
||||
if t.inner.len > 0:
|
||||
TypeExpr(kind: tekPointer, refLifetime: "", pointerPointee: typeToTypeExpr(t.inner[0]))
|
||||
@@ -201,6 +205,8 @@ proc substituteTypeInType(sema: var Sema, t: Type, subst: Table[string, Type]):
|
||||
inner.add(sema.substituteTypeInType(it, subst))
|
||||
return Type(kind: tkFunc, inner: inner)
|
||||
of tkNamed:
|
||||
if subst.hasKey(t.name):
|
||||
return subst[t.name]
|
||||
if t.inner.len > 0:
|
||||
var args: seq[Type] = @[]
|
||||
for a in t.inner:
|
||||
@@ -1263,9 +1269,13 @@ proc checkExpr(sema: var Sema, expr: Expr, scope: Scope): Type =
|
||||
let sym = sema.globalScope.lookup(objType.name)
|
||||
if sym != nil and sym.decl != nil:
|
||||
if sym.decl.kind == dkStruct:
|
||||
var subst = initTable[string, Type]()
|
||||
for i, tp in sym.decl.declStructTypeParams:
|
||||
if i < objType.inner.len:
|
||||
subst[tp.name] = objType.inner[i]
|
||||
for f in sym.decl.declStructFields:
|
||||
if f.name == expr.exprFieldName:
|
||||
return sema.resolveType(f.ftype)
|
||||
return sema.substituteTypeInType(sema.resolveType(f.ftype), subst)
|
||||
sema.emitError(expr.loc, &"struct '{objType.name}' has no field '{expr.exprFieldName}'")
|
||||
elif sym.decl.kind == dkEnum:
|
||||
# Algebraic enum fields
|
||||
@@ -1498,11 +1508,15 @@ proc checkStmt(sema: var Sema, stmt: Stmt, scope: Scope): Type =
|
||||
return makeVoid()
|
||||
of skFor:
|
||||
let iterExpr = stmt.stmtForIter
|
||||
discard sema.checkExpr(iterExpr, scope)
|
||||
let collType = sema.checkExpr(iterExpr, scope)
|
||||
var forScope = newScope(scope)
|
||||
var iterTyp = makeUnknown()
|
||||
if iterExpr.kind == ekRange:
|
||||
iterTyp = sema.checkExpr(iterExpr.exprRangeLo, scope)
|
||||
elif collType.kind == tkNamed and collType.inner.len > 0:
|
||||
iterTyp = collType.inner[0]
|
||||
elif collType.isPointer and collType.inner.len > 0 and collType.inner[0].kind == tkNamed and collType.inner[0].inner.len > 0:
|
||||
iterTyp = collType.inner[0].inner[0]
|
||||
let iterSym = Symbol(kind: skVar, name: stmt.stmtForVar, typ: iterTyp, isMutable: true)
|
||||
discard forScope.define(iterSym)
|
||||
discard sema.checkStmt(Stmt(kind: skExpr, loc: stmt.stmtForBody.loc, stmtExpr: Expr(kind: ekBlock, loc: stmt.stmtForBody.loc, exprBlock: stmt.stmtForBody)), forScope)
|
||||
|
||||
Reference in New Issue
Block a user