예제 #1
0
        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;
            }
        }
예제 #2
0
        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);
        }