private void CollectTypeDependencies(AstDecl decl, AstExpression typeExpr) { switch (typeExpr) { case AstFuncExpr fun: { foreach (var p in fun.Parameters) { CollectTypeDependencies(decl, p.TypeExpr); } if (fun.ReturnTypeExpr != null) { CollectTypeDependencies(decl, fun.ReturnTypeExpr.TypeExpr); } break; } case AstTraitTypeExpr str: { if (str.Parameters != null) { foreach (var p in str.Parameters) { CollectTypeDependencies(decl, p.TypeExpr); } } foreach (var m in str.Declarations) { switch (m) { //case AstVariableDecl v: // if (v.TypeExpr != null) // CollectTypeDependencies(decl, v.TypeExpr, DependencyKind.Value); // or type? // if (v.Initializer != null) // CollectTypeDependencies(decl, v.Initializer, DependencyKind.Type); // or type? // break; case AstConstantDeclaration v: if (v.TypeExpr != null) { CollectTypeDependencies(decl, v.TypeExpr); } CollectTypeDependencies(decl, v.Initializer); break; } } decl.Dependencies.Remove(decl); break; } case AstStructTypeExpr str: { if (str.TryGetDirective("extend", out var dir)) { foreach (var arg in dir.Arguments) { CollectTypeDependencies(decl, arg); } } if (str.TraitExpr != null) { CollectTypeDependencies(decl, str.TraitExpr); } foreach (var p in str.Parameters) { CollectTypeDependencies(decl, p.TypeExpr); } foreach (var m in str.Declarations) { switch (m) { //case AstVariableDecl v: // if (v.TypeExpr != null) // CollectTypeDependencies(decl, v.TypeExpr, DependencyKind.Value); // or type? // if (v.Initializer != null) // CollectTypeDependencies(decl, v.Initializer, DependencyKind.Type); // or type? // break; case AstConstantDeclaration v: if (v.TypeExpr != null) { CollectTypeDependencies(decl, v.TypeExpr); } CollectTypeDependencies(decl, v.Initializer); break; } } break; } case AstIdExpr id: switch (decl.Scope.GetSymbol(id.Name)) { case AstDecl d: decl.Dependencies.Add(d); break; } //if (sym is AstDecl d) //{ // if (d is AstVariableDecl sv) // d = sv; // decl.Dependencies.Add(d); //} break; case AstDotExpr dot: { switch (GetSymbolOfExpr(dot, decl.Scope)) { case AstDecl d: decl.Dependencies.Add(d); break; } break; } case AstVariableRef vr: decl.Dependencies.Add(vr.Declaration); break; case AstConstantRef vr: decl.Dependencies.Add(vr.Declaration); break; case AstAddressOfExpr add: CollectTypeDependencies(decl, add.SubExpression); break; case AstSliceTypeExpr expr: CollectTypeDependencies(decl, expr.Target); break; case AstArrayTypeExpr expr: CollectTypeDependencies(decl, expr.SizeExpr); CollectTypeDependencies(decl, expr.Target); break; case AstReferenceTypeExpr expr: CollectTypeDependencies(decl, expr.Target); break; case AstFunctionTypeExpr expr: if (expr.ReturnType != null) { CollectTypeDependencies(decl, expr.ReturnType); } foreach (var p in expr.ParameterTypes) { CollectTypeDependencies(decl, p); } break; case AstTupleExpr expr: foreach (var p in expr.Types) { if (p.TypeExpr != null) { CollectTypeDependencies(decl, p.TypeExpr); } if (p.Name != null) { CollectTypeDependencies(decl, p.Name); } if (p.DefaultValue != null) { CollectTypeDependencies(decl, p.DefaultValue); } } break; case AstCallExpr expr: CollectTypeDependencies(decl, expr.FunctionExpr); foreach (var p in expr.Arguments) { CollectTypeDependencies(decl, p.Expr); } break; case AstArrayAccessExpr expr: { CollectTypeDependencies(decl, expr.SubExpression); foreach (var p in expr.Arguments) { CollectTypeDependencies(decl, p); } break; } case AstArrayExpr arr: { foreach (var val in arr.Values) { CollectTypeDependencies(decl, val); } break; } case AstBinaryExpr b: CollectTypeDependencies(decl, b.Left); CollectTypeDependencies(decl, b.Right); break; case AstUnaryExpr u: CollectTypeDependencies(decl, u.SubExpr); break; } }
private void ResolveMissingTypesOfDeclarationsHelper( AstDecl decl, HashSet <AstDecl> whiteSet, HashSet <AstDecl> greySet, Dictionary <AstDecl, AstDecl> chain) { whiteSet.Remove(decl); greySet.Add(decl); foreach (var dep in decl.Dependencies) { if (greySet.Contains(dep)) { // cyclic dependency, report error var c = new List <AstDecl> { decl, dep }; var current = dep; while (chain.TryGetValue(current, out var d)) { c.Add(d); current = d; } var detail1 = string.Join(" -> ", c.Select(x => x.Name.Name)); var details = new List <(string, ILocation?)> { (detail1, null) }; details.AddRange(c.Skip(1).Take(c.Count - 2).Select(x => ("Here is the next declaration in the cycle", x.Name.Location)) !); ReportError(decl.Name, $"Cyclic dependency not allowed", details); return; } else if (whiteSet.Contains(dep)) { chain[decl] = dep; ResolveMissingTypesOfDeclarationsHelper(dep, whiteSet, greySet, chain); } } var newPolyDecls = new List <AstDecl>(); switch (decl) { case AstConstantDeclaration c: { if (!(c.Pattern is AstIdExpr)) { ReportError(c.Pattern, $"Only identifier pattern allowed here"); } if (c.TypeExpr != null) { c.TypeExpr.AttachTo(c); c.TypeExpr.SetFlag(ExprFlags.ValueRequired, true); c.TypeExpr = ResolveType(c.TypeExpr, newPolyDecls, out var t); c.Type = t; } c.Initializer.AttachTo(c); c.Initializer.SetFlag(ExprFlags.ValueRequired, true); c.Initializer = InferType(c.Initializer, c.Type); if (c.Type == null) { c.Type = c.Initializer.Type; } else { c.Initializer = CheckType(c.Initializer, c.Type); } if (!c.Initializer.IsCompTimeValue) { ReportError(c.Initializer, $"Value of constant declaration must be constant"); break; } c.Value = c.Initializer.Value; CheckValueRangeForType(c.Type, c.Value, c.Initializer); break; } case AstVariableDecl v: { v.SetFlag(StmtFlags.GlobalScope, true); ResolveVariableDecl(v); break; } } greySet.Remove(decl); }