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; } }
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()); }
protected void ResolveReturnStmt(AstReturnStmt stmt) { if (stmt.m_expr != null) { ResolveExpr(stmt.m_expr); } }
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); }
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)); }
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()); }
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(); } }
public virtual ReturnType VisitReturnStmt(AstReturnStmt stmt, DataType data = default) => default;
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}"); } }