Esempio n. 1
0
        // helper functions
        internal void SortDeclarationsIntoImplBlock(AstImplBlock impl)
        {
            foreach (var decl in impl.Declarations)
            {
                decl.Parent = impl;
                decl.Scope  = impl.SubScope;
                decl.SetFlag(StmtFlags.ExportScope, impl.GetFlag(StmtFlags.ExportScope));
                decl.SourceFile = impl.SourceFile;

                switch (decl)
                {
                case AstConstantDeclaration con:
                {
                    con.Initializer.AttachTo(con);

                    switch (con.Initializer)
                    {
                    case AstFuncExpr func:
                        impl.Functions.Add(func);
                        break;

                    default:
                        ReportError(con.Initializer, $"This type is not allowed here.");
                        break;
                    }

                    break;
                }


                default:
                    ReportError(decl, $"This type of declaration is not allowed here.");
                    break;
                }
            }
        }
Esempio n. 2
0
        private void Pass3Impl(AstImplBlock impl)
        {
            Log($"Pass3Impl {impl.Accept(new SignatureAstPrinter())}", $"poly = {impl.IsPolymorphic}");
            PushLogScope();

            try
            {
                if (!impl.IsPolyInstance)
                {
                    impl.SubScope = new Scope($"impl {impl.TraitExpr} for {impl.TargetTypeExpr}", impl.Scope);
                    if (impl.Parameters?.Count > 0)
                    {
                        impl.IsPolymorphic = true;
                    }
                }

                // check if there are parameters
                if (impl.IsPolymorphic)
                {
                    // setup scopes
                    foreach (var param in impl.Parameters)
                    {
                        param.Scope          = impl.Scope;
                        param.TypeExpr.Scope = impl.Scope;
                        param.TypeExpr.SetFlag(ExprFlags.ValueRequired, true);
                        param.TypeExpr = ResolveTypeNow(param.TypeExpr, out var newType, forceInfer: true);

                        if (newType is AbstractType)
                        {
                            continue;
                        }

                        param.Type = newType;

                        switch (param.Type)
                        {
                        case CheezTypeType _:
                            param.Value = new PolyType(param.Name.Name, true);
                            if (param.Name != null)
                            {
                                impl.SubScope.DefineTypeSymbol(param.Name.Name, new PolyType(param.Name.Name, true));
                            }
                            break;

                        case IntType _:
                        case FloatType _:
                        case BoolType _:
                        case CharType _:
                        case EnumType _:
                            if (param.Name != null)
                            {
                                impl.SubScope.DefineConstant(param.Name.Name, param.Type, new PolyValue(param.Name.Name));
                            }
                            //impl.SubScope.DefineConstant(param.Name.Name, CheezType.PolyValue, new PolyValue(param.Name.Name));
                            break;

                        case ErrorType _:
                            break;

                        default:
                            ReportError(param.TypeExpr, $"The type '{param.Type}' is not allowed here.");
                            break;
                        }
                    }
                }

                impl.TargetTypeExpr.SetFlag(ExprFlags.ValueRequired, true);
                impl.TargetTypeExpr.Scope = impl.SubScope;
                impl.TargetTypeExpr       = ResolveTypeNow(impl.TargetTypeExpr, out var t, resolvePolyExprToConcreteType: !impl.IsPolymorphic);
                impl.TargetType           = t;

                // @TODO: does it make sense to allow conditions on impl blocks without parameters?
                // for now don't allow these

                if (impl.Conditions != null)
                {
                    if (impl.Parameters == null)
                    {
                        ReportError(new Location(impl.Conditions.First().Location.Beginning, impl.Conditions.Last().Location.End), $"An impl block can't have a condition without parameters");
                    }

                    foreach (var cond in impl.Conditions)
                    {
                        cond.Scope = impl.SubScope;
                    }
                }

                if (impl.IsPolymorphic)
                {
                    return;
                }

                impl.SubScope.DefineTypeSymbol("Self", impl.TargetType);

                SortDeclarationsIntoImplBlock(impl);

                foreach (var f in impl.Functions)
                {
                    f.Scope      = impl.SubScope;
                    f.ConstScope = new Scope($"fn$ {f.Name}", f.Scope);
                    f.SubScope   = new Scope($"fn {f.Name}", f.ConstScope);
                    f.ImplBlock  = impl;
                    f.SetFlag(ExprFlags.ExportScope, impl.GetFlag(StmtFlags.ExportScope));

                    InferTypeFuncExpr(f);
                    CheckForSelfParam(f);
                    impl.Scope.DefineImplFunction(f);
                    impl.SubScope.DefineSymbol(f);
                }
            }
            finally
            {
                PopLogScope();
                Log($"Finished Pass3Impl {impl.Accept(new SignatureAstPrinter())}", $"poly = {impl.IsPolymorphic}");
            }
        }