private void CreateFunctions_Function( ref TranslationUnitData transUnit, ES_NamespaceData.Builder namespaceBuilder, SymbolStack <FrontendSymbol> symbols, SourceData unitSrc, ES_TypeInfo *parentType, ES_AstFunctionDefinition funcDef ) { Debug.Assert(Environment is not null); Debug.Assert(EnvironmentBuilder is not null); var sourceUnit = transUnit.Name; var idPool = Environment.IdPool; // Get the namespace and function names. var funcName = Environment.IdPool.GetIdentifier(funcDef.Name.Text.Span); // Get the fully-qualified name. ES_FullyQualifiedName fullyQualifiedName; if (parentType == null) { var namespaceName = namespaceBuilder.NamespaceData.NamespaceName; fullyQualifiedName = new ES_FullyQualifiedName(namespaceName, funcName); } else { using var namespaceBytes = UnmanagedArray <byte> .GetArray(parentType->Name.NamespaceName.Length + 2 + parentType->Name.TypeName.Length); var span = namespaceBytes.Span; parentType->Name.NamespaceName.Span.CopyTo(span); span = span [parentType->Name.NamespaceName.Length..];
private static void CheckFunction( ref PassData passData, ES_TypeInfo *parentType, ES_NamespaceData?namespaceData, ES_AstFunctionDefinition funcDef ) { Debug.Assert(parentType is not null || namespaceData is not null); var idPool = passData.Env.IdPool; var symbols = passData.Symbols; var irWriter = passData.IRWriter; var funcName = idPool.GetIdentifier(funcDef.Name.Text.Span); var retType = UnpackFirstConst(GetTypeRef(funcDef.ReturnType)); Debug.Assert(retType.Type is not null); ES_FunctionData *funcData; if (namespaceData is not null) { if (!namespaceData.Functions.TryGetValue(funcName, out var funcDataPtr)) { Debug.Fail("This shouldn't ever be reached."); } funcData = funcDataPtr.Address; } else { throw new NotImplementedException("[TODO] Member functions not implemented yet."); } symbols.Push(); irWriter.StartFunction(MangleFunctionName(ref passData, funcData), TypeNode(ref passData, retType)); foreach (var arg in funcDef.ArgumentsList) { var argName = idPool.GetIdentifier(arg.Name.Text.Span); var argValType = UnpackFirstConst(GetTypeRef(arg.ValueType)); var flags = (SymbolFlags)0; var argType = arg.ArgType; switch (argType) { case ES_ArgumentType.Normal: break; case ES_ArgumentType.Ref: flags |= SymbolFlags.RefVar; break; case ES_ArgumentType.In: if (argValType.Constness != Constness.Mutable) { passData.ErrorList.Add(ES_FrontendErrors.GenTypeAlreadyConst( false, argValType.Constness == Constness.Immutable, arg.Name )); break; } argType = ES_ArgumentType.Normal; argValType = argValType.WithConst(Constness.Const); break; case ES_ArgumentType.Out: throw new NotImplementedException("[TODO] Argument type not implemented yet."); default: throw new NotImplementedException("Argument type not implemented yet."); } if (argValType.IsWritable) { flags |= SymbolFlags.Writable; } var argIdx = irWriter.AddArgument(ArgumentDefinition(argType, TypeNode(ref passData, argValType))); if (!symbols.AddSymbol(argName, TCSymbol.NewVariable(argValType, ArgumentExpression(argIdx), flags))) { Debug.Fail("This shouldn't be reachable."); } if (arg.DefaultExpression is not null) { var argDefExpr = CheckExpression(ref passData, arg.DefaultExpression, argValType); EnsureCompat(ref argDefExpr, argValType, ref passData, arg.DefaultExpression.NodeBounds); } } // Emit the function body. Debug.Assert(funcDef.Statement is not null); Debug.Assert(funcDef.Statement.Endpoint is null); if (funcDef.ExpressionBody) { Debug.Assert(funcDef.Statement is ES_AstExpressionStatement); var exprExpType = retType.Type->TypeTag != ES_TypeTag.Void ? retType : passData.GetUnknownType(Constness.Mutable); var exprStmt = (funcDef.Statement as ES_AstExpressionStatement) !; var exprData = CheckExpression(ref passData, exprStmt.Expression, exprExpType); if (retType.Type->TypeTag != ES_TypeTag.Void) { if (!EnsureCompat(ref exprData, retType, ref passData, exprData.Expr.NodeBounds)) { passData.ErrorList.Add(new (funcDef.Name, ES_FrontendErrors.MissingReturnStatement)); } } using var exprList = exprData.Expressions; foreach (var expr in exprList.Expressions) { irWriter.AddStatement(ExpressionStatement(expr)); } if (retType.Type->TypeTag != ES_TypeTag.Void) { irWriter.AddStatement(ReturnStatement(exprData.Value)); } else { irWriter.AddStatement(ExpressionStatement(exprData.Value)); } irWriter.AddScopeRegisters(exprList.Registers); irWriter.AddScopeRegister(exprData.ValueRegister); } else { var stmtData = CheckStatement(ref passData, retType, funcDef.Statement); if (!stmtData.AlwaysReturns && retType.Type->TypeTag != ES_TypeTag.Void) { passData.ErrorList.Add(new (funcDef.Name, ES_FrontendErrors.MissingReturnStatement)); } } symbols.Pop(); ESIR_TraceDataAttribute traceDataAttr; ESIR_FunctionDataAttribute funcDataAttr; if (parentType is not null) { traceDataAttr = TraceDataAttribute( parentType->Name.NamespaceName, funcName, parentType->Name.TypeName, funcDef.Name.FileName.Span.GetPooledString() ); funcDataAttr = FunctionDataAttribute(funcData, parentType); } else { traceDataAttr = TraceDataAttribute( namespaceData.NamespaceName, funcName, funcDef.Name.FileName.Span.GetPooledString() ); funcDataAttr = FunctionDataAttribute(funcData); } irWriter.EndFunction(List <ESIR_Attribute> (traceDataAttr, funcDataAttr)); }