Ejemplo n.º 1
0
    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..];
Ejemplo n.º 2
0
    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));
    }