Exemplo n.º 1
0
    protected void ExecuteReturnStmt(AstReturnStmt stmt)
    {
        if (HadErrorOrReturn())
        {
            return;
        }

        if (stmt.m_expr != null)
        {
            object returnValue = EvaluateExpr(stmt.m_expr);

            if (!m_runtimeError)
            {
                m_returnValue    = returnValue;
                m_hasReturnValue = true;
            }
        }
        else
        {
            // TODO: is this really what I want to happen if you explicitly return nothing?
            //  I don't have any code to handle implicitly returning nothing so I don't think they
            //  will behave the same way. I think I would rather sidestep the issue by not allowing
            //  you to "use" a value returned by a function that doesn't return anything. This wolud
            //  require a semantic pass. Maybe I can cram it into the resolve pass?

            m_returnValue    = null;
            m_hasReturnValue = true;
        }
    }
Exemplo n.º 2
0
        public override string VisitReturnStmt(AstReturnStmt ret, int data = 0)
        {
            var sb = new StringBuilder();

            if (ret.Destructions != null)
            {
                foreach (var dest in ret.Destructions)
                {
                    sb.AppendLine($"{dest.Accept(this)};");
                }
            }

            if (ret.DeferredStatements.Count > 0)
            {
                sb.AppendLine();
                sb.AppendLine("// deferred statements");
                foreach (var s in ret.DeferredStatements)
                {
                    sb.AppendLine(s.Accept(this));
                }

                sb.AppendLine("// return");
            }

            sb.Append("return");
            if (ret.ReturnValue != null)
            {
                sb.Append(" ").Append(ret.ReturnValue.Accept(this));
            }
            return(sb.ToString());
        }
Exemplo n.º 3
0
 protected void ResolveReturnStmt(AstReturnStmt stmt)
 {
     if (stmt.m_expr != null)
     {
         ResolveExpr(stmt.m_expr);
     }
 }
Exemplo n.º 4
0
        private AstReturnStmt AnalyseReturnStatement(AstReturnStmt ret)
        {
            ret.SetFlag(StmtFlags.Returns);

            if (ret.ReturnValue != null)
            {
                ret.ReturnValue.SetFlag(ExprFlags.ValueRequired, true);
                ret.ReturnValue.AttachTo(ret);
                ret.ReturnValue = InferType(
                    ret.ReturnValue,
                    currentFunction.FunctionType.ReturnType,
                    typeOfExprContext: currentFunction.FunctionType.ReturnType);

                ConvertLiteralTypeToDefaultType(ret.ReturnValue, currentFunction.FunctionType.ReturnType);

                if (ret.ReturnValue.Type.IsErrorType)
                {
                    return(ret);
                }

                ret.ReturnValue = CheckType(ret.ReturnValue, currentFunction.FunctionType.ReturnType, $"The type of the return value '{ret.ReturnValue.Type}' does not match the return type of the function '{currentFunction.FunctionType.ReturnType}'");

                if (ret.ReturnValue.Type is VoidType)
                {
                    ReportError(ret, $"Can't return void");
                }
            }
            return(ret);
        }
Exemplo n.º 5
0
        public override NodeFinderResult VisitReturnStmt(AstReturnStmt ret, int index = 0)
        {
            if (ret.ReturnValue != null && GetRelativeLocation(ret.ReturnValue.Location, index) == RelativeLocation.Same)
            {
                return(ret.ReturnValue.Accept(this, index));
            }

            return(new NodeFinderResult(ret.Scope, stmt: ret));
        }
Exemplo n.º 6
0
        public override string VisitReturnStmt(AstReturnStmt ret, int data = 0)
        {
            var sb = new StringBuilder();

            sb.Append("return");
            if (ret.ReturnValue != null)
            {
                sb.Append(" ").Append(ret.ReturnValue.Accept(this));
            }
            return(sb.ToString());
        }
Exemplo n.º 7
0
        private void GenerateReturnStatement(AstReturnStmt ret)
        {
            if (ret.ReturnValue != null)
            {
                var return_var = valueMap[currentFunction.ReturnTypeExpr];
                var retval     = GenerateExpression(ret.ReturnValue, true);

                // dtors
                if (ret.Destructions != null)
                {
                    foreach (var dest in ret.Destructions)
                    {
                        GenerateStatement(dest);
                    }
                }

                PopStackTrace();
                builder.CreateRet(retval);
            }
            else if (currentFunction.ReturnTypeExpr != null)
            {
                var retVal = valueMap[currentFunction.ReturnTypeExpr];
                retVal = builder.CreateLoad(retVal, "");

                // dtors
                if (ret.Destructions != null)
                {
                    foreach (var dest in ret.Destructions)
                    {
                        GenerateStatement(dest);
                    }
                }

                PopStackTrace();
                builder.CreateRet(retVal);
            }
            else
            {
                // dtors
                if (ret.Destructions != null)
                {
                    foreach (var dest in ret.Destructions)
                    {
                        GenerateStatement(dest);
                    }
                }

                PopStackTrace();
                builder.CreateRetVoid();
            }
        }
Exemplo n.º 8
0
 public virtual ReturnType VisitReturnStmt(AstReturnStmt stmt, DataType data = default) => default;
Exemplo n.º 9
0
        private void AnalyseFunction(AstFuncExpr func)
        {
            if (func.IsAnalysed)
            {
                return;
            }
            func.IsAnalysed = true;

            Log($"Analysing function {func.Name}", $"impl = {func.ImplBlock?.Accept(new SignatureAstPrinter())}", $"poly = {func.IsGeneric}");
            PushLogScope();

            var prevCurrentFunction = currentFunction;

            currentFunction = func;
            try
            {
                if (func.SelfType != SelfParamType.None)
                {
                    var p = func.Parameters[0];
                    if (p.Name == null)
                    {
                        p.Name = new AstIdExpr("self", false, p.Location);
                    }

                    if (func.ImplBlock.TargetType is StructType @struct)
                    {
                        ComputeStructMembers(@struct.Declaration);
                        foreach (var m in @struct.Declaration.Members)
                        {
                            AstExpression expr = new AstDotExpr(new AstSymbolExpr(p), new AstIdExpr(m.Name, false, p.Location), p.Location);
                            expr.AttachTo(func, func.SubScope);
                            expr = InferType(expr, m.Type);

                            // define use if no parameter has the same name
                            if (!func.Parameters.Any(pa => pa.Name?.Name == m.Name))
                            {
                                var(ok, other) = func.SubScope.DefineUse(m.Name, expr, false, out var use);

                                if (!ok)
                                {
                                    ReportError(p, $"A symbol with name '{m.Name}' already exists", ("Other here:", other));
                                }
                            }
                        }
                    }
                }

                if (func.IsGeneric)
                {
                    return;
                }

                if (func.TryGetDirective("linkname", out var ln))
                {
                    if (ln.Arguments.Count != 1)
                    {
                        ReportError(ln, $"#linkname requires exactly one argument!");
                    }
                    else
                    {
                        var arg = ln.Arguments[0];
                        arg.SetFlag(ExprFlags.ValueRequired, true);
                        arg = ln.Arguments[0] = InferType(arg, null);
                        if (!(arg.Value is string))
                        {
                            ReportError(arg, $"Argument to #linkname must be a constant string!");
                        }
                    }
                }

                // define parameters
                foreach (var p in func.Parameters)
                {
                    p.ContainingFunction = func;
                    if (p.Name != null)
                    {
                        var(ok, other) = func.SubScope.DefineSymbol(p);
                        if (!ok)
                        {
                            ReportError(p, $"Duplicate parameter '{p.Name}'", ("Other parameter here:", other));
                        }
                    }

                    if (p.DefaultValue != null)
                    {
                        p.DefaultValue.Scope = func.Scope;
                        p.DefaultValue       = InferTypeHelper(p.DefaultValue, p.Type, new TypeInferenceContext {
                            TypeOfExprContext = p.Type
                        });
                        ConvertLiteralTypeToDefaultType(p.DefaultValue, p.Type);
                        p.DefaultValue = CheckType(p.DefaultValue, p.Type);
                        if (p.DefaultValue.Type != p.Type && !p.DefaultValue.Type.IsErrorType)
                        {
                            ReportError(p.DefaultValue,
                                        $"The type of the default value ({p.DefaultValue.Type}) does not match the type of the parameter ({p.Type})");
                        }
                    }
                }

                if (func.ReturnTypeExpr != null)
                {
                    func.ReturnTypeExpr.Mutable = true;
                }

                if (func.ReturnTypeExpr?.Name != null)
                {
                    func.ReturnTypeExpr.ContainingFunction = func;
                    func.ReturnTypeExpr.IsReturnParam      = true;
                    var(ok, other) = func.SubScope.DefineSymbol(func.ReturnTypeExpr);
                    if (!ok)
                    {
                        ReportError(func.ReturnTypeExpr, $"A symbol with name '{func.ReturnTypeExpr.Name.Name}' already exists in current scope", ("Other symbol here:", other));
                    }
                }
                else if (func.ReturnTypeExpr != null)
                {
                    func.SubScope.DefineSymbol(func.ReturnTypeExpr, ".ret");
                }
                if (func.ReturnTypeExpr?.TypeExpr is AstTupleExpr t)
                {
                    int index = 0;
                    foreach (var m in t.Types)
                    {
                        if (m.Name == null)
                        {
                            continue;
                        }
                        m.Mutable = true;
                        AstExpression access = new AstArrayAccessExpr(new AstSymbolExpr(func.ReturnTypeExpr), new AstNumberExpr(index, Location: func.ReturnTypeExpr.Location), func.ReturnTypeExpr.Location);
                        access         = InferType(access, null);
                        var(ok, other) = func.SubScope.DefineUse(m.Name.Name, access, false, out var use);
                        if (!ok)
                        {
                            ReportError(m, $"A symbol with name '{m.Name.Name}' already exists in current scope", ("Other symbol here:", other));
                        }
                        m.Symbol = use;
                        ++index;
                    }
                }

                if (func.FunctionType.IsErrorType || func.FunctionType.IsPolyType)
                {
                    return;
                }

                if (func.Body != null && !func.IsMacroFunction)
                {
                    var errs = PushSilentErrorHandler();
                    func.Body.AttachTo(func, func.SubScope);
                    InferType(func.Body, null);

                    if (func.ReturnTypeExpr != null && !func.Body.GetFlag(ExprFlags.Returns))
                    {
                        // TODO: check that all return values are set
                        var ret = new AstReturnStmt(null, new Location(func.Body.End));
                        ret.Scope = func.Body.SubScope;
                        ret       = AnalyseReturnStatement(ret);
                        func.Body.Statements.Add(ret);
                        func.Body.SetFlag(ExprFlags.Returns, true);
                    }

                    PopErrorHandler();

                    if (errs.HasErrors)
                    {
                        if (func.IsPolyInstance && func.InstantiatedAt != null)
                        {
                            ReportError($"Errors in polymorphic function '{func.Name}':");
                            errs.ForwardErrors(CurrentErrorHandler);

                            void ReportSources(AstFuncExpr func, string indent = "")
                            {
                                if (func.InstantiatedAt == null)
                                {
                                    return;
                                }
                                foreach (var loc in func.InstantiatedAt)
                                {
                                    ReportError(loc, indent + $"Failed to instantiate function '{func.Name}'");
                                }
                                foreach (var loc in func.InstantiatedBy)
                                {
                                    ReportError(loc, indent + $"Failed to instantiate function '{func.Name}'");
                                    ReportSources(loc, indent + "  ");
                                }
                            }

                            ReportError($"Caused from invocations here:");
                            ReportSources(func);
                        }
                        else
                        {
                            errs.ForwardErrors(CurrentErrorHandler);
                        }
                    }
                    else
                    {
                        PassVariableLifetimes(func);
                    }
                }
            }
            finally
            {
                currentFunction = prevCurrentFunction;
                PopLogScope();
                Log($"Finished function {func.Name}");
            }
        }