public override ExpressionTarget ParseExpression(HlCompilation compilation, HlInvocationOp expr)
        {
            string target = expr.Left.ToString();

            if (m_CtFuncCollection.IsCompiletimeFunction(target))
            {
                return(m_CtFuncCollection.Compile(target, compilation, expr));
            }

            bool isInternalFunc = compilation.FunctionMap.Contains(target);

            IExternalData externalSymbol =
                compilation.ExternalSymbols.FirstOrDefault(
                    x => x.GetName() == target &&
                    x.DataType == ExternalDataType.Function
                    );

            //if (expr.Instance == null &&
            //    expr.MemberDefinition == null &&
            //    expr.InstanceType != null &&
            //    target == "new")
            //{
            //    ExpressionTarget instance = compilation.Parse(expr.ParameterList[0]);

            //    HlTypeDefinition tdef = expr.InstanceType;

            //    ExpressionTarget ret = new ExpressionTarget(
            //                                                instance.ResultAddress,
            //                                                true,
            //                                                tdef,
            //                                                true
            //                                               );

            //    if(SettingsManager.GetSettings<HlCompilerSettings>().ConstructorPrologMode == HlTypeConstructorPrologMode.Outline)
            //    WriteConstructorInvocationProlog(compilation, tdef, ret.ResultAddress);

            //    return ret;
            //}
            if (expr.Instance == null &&
                expr.InstanceType != null)
            {
                if (expr.MemberDefinition == expr.InstanceType.StaticConstructor)
                {
                    ExpressionTarget instance = compilation.Parse(expr.ParameterList[0]);

                    HlTypeDefinition tdef = expr.InstanceType;

                    ExpressionTarget ret = new ExpressionTarget(
                        instance.ResultAddress,
                        true,
                        tdef,
                        true
                        );

                    if (expr.WriteProlog &&
                        SettingsManager.GetSettings <HlCompilerSettings>().ConstructorPrologMode ==
                        HlTypeConstructorPrologMode.Outline)
                    {
                        WriteConstructorInvocationProlog(compilation, tdef, ret.ResultAddress);
                    }

                    expr.Redirect(ret.ResultAddress, tdef, tdef.StaticConstructor, expr.WriteProlog);

                    ParseExpression(
                        compilation,
                        expr
                        );

                    return(ret);
                }
                else
                {
                    int l = (expr.MemberDefinition as HlFunctionDefinition).ParameterTypes.Length;

                    if (isInternalFunc)
                    {
                        compilation.FunctionMap.Get(target).SetUsed();
                    }
                    else
                    {
                        externalSymbol?.SetUsed();
                    }

                    return(ParseFunctionInvocation(compilation, expr, l, target, "JSR"));
                }
            }

            if (compilation.TypeSystem.HasType(compilation.Root, target))
            {
                string           var  = HlCompilation.GetUniqueName("static_alloc");
                HlTypeDefinition tdef = compilation.TypeSystem.GetType(compilation.Root, target);
                uint             size = tdef.GetSize();
                compilation.CreateVariable(var, size, tdef, VariableDataEmitFlags.None);
                string finalName = compilation.GetFinalName(var);

                ExpressionTarget ret = new ExpressionTarget(
                    compilation.GetTempVarLoad(finalName),
                    true,
                    tdef,
                    true
                    );

                if (SettingsManager.GetSettings <HlCompilerSettings>().ConstructorPrologMode ==
                    HlTypeConstructorPrologMode.Outline)
                {
                    WriteConstructorInvocationProlog(compilation, tdef, ret.ResultAddress);
                }

                if (tdef.StaticConstructor != null)
                {
                    expr.Redirect(ret.ResultAddress, tdef, tdef.StaticConstructor);

                    ParseExpression(
                        compilation,
                        expr
                        );
                }

                return(ret);
            }

            if (expr.Instance != null &&
                expr.MemberDefinition is HlFunctionDefinition fdef)
            {
                if (fdef.IsVirtual || fdef.IsAbstract || fdef.IsOverride)
                {
                    uint i = expr.InstanceType.GetOffset(fdef.Name);

                    string init = i.ToString();
                    string tmp  = compilation.GetTempVarLoad(init);

                    compilation.EmitterResult.Emit("ADD", tmp, expr.Instance);
                    compilation.EmitterResult.Emit("DREF", tmp, tmp);

                    int targetLength = fdef.ParameterTypes != null
                                           ? fdef.ParameterTypes.Length
                                           : expr.ParameterList.Length;

                    externalSymbol?.SetUsed();
                    ExpressionTarget t = ParseFunctionInvocation(compilation, expr, targetLength, tmp, "JSREF");
                    compilation.ReleaseTempVar(tmp);

                    return(t);
                }
                else if (!isInternalFunc && externalSymbol == null)
                {
                    string funcEmit = target;

                    int targetLength = fdef.ParameterTypes?.Length ?? expr.ParameterList.Length;

                    if (expr.InstanceType != null &&
                        expr.InstanceType.StaticConstructor == expr.MemberDefinition &&
                        expr.WriteProlog &&
                        SettingsManager.GetSettings <HlCompilerSettings>().ConstructorPrologMode ==
                        HlTypeConstructorPrologMode.Inline)
                    {
                        funcEmit = expr.InstanceType.GetInternalConstructor(compilation);
                    }

                    return(ParseFunctionInvocation(compilation, expr, targetLength, funcEmit, "JSR"));
                }
            }

            if (isInternalFunc)
            {
                string funcEmit = target;

                FunctionData fData        = compilation.FunctionMap.Get(target);
                int          targetLength = fData.ParameterCount;

                //if (!expr.WriteProlog && SettingsManager.GetSettings < HlCompilerSettings >().ConstructorPrologMode ==
                //     HlTypeConstructorPrologMode.Inline )
                //{
                //    funcEmit = expr.MemberDefinition.
                //}

                if (expr.InstanceType != null &&
                    expr.InstanceType.StaticConstructor == expr.MemberDefinition &&
                    expr.WriteProlog &&
                    SettingsManager.GetSettings <HlCompilerSettings>().ConstructorPrologMode ==
                    HlTypeConstructorPrologMode.Inline)
                {
                    funcEmit = expr.InstanceType.GetInternalConstructor(compilation);
                }

                fData.SetUsed();

                return(ParseFunctionInvocation(compilation, expr, targetLength, funcEmit, "JSR").
                       Cast(
                           compilation.TypeSystem.GetType(
                               compilation.Root,
                               fData?.ReturnType ?? HLBaseTypeNames.s_UintTypeName
                               )
                           ));
            }

            if (externalSymbol != null)
            {
                string funcEmit = (externalSymbol as LinkedData)?.Info.Address.ToString() ?? target;

                FunctionData fData        = externalSymbol as FunctionData;
                int          targetLength = (externalSymbol as FunctionData)?.ParameterCount ?? expr.ParameterList.Length;

                if (expr.InstanceType != null &&
                    expr.InstanceType.StaticConstructor == expr.MemberDefinition &&
                    expr.WriteProlog &&
                    SettingsManager.GetSettings <HlCompilerSettings>().ConstructorPrologMode ==
                    HlTypeConstructorPrologMode.Inline)
                {
                    funcEmit = expr.InstanceType.GetInternalConstructor(compilation);
                }

                externalSymbol.SetUsed();

                return(ParseFunctionInvocation(compilation, expr, targetLength, funcEmit, "JSR").
                       Cast(compilation.TypeSystem.GetType(
                                compilation.Root,
                                fData?.ReturnType ?? HLBaseTypeNames.s_UintTypeName
                                )));
            }

            //if (isInternalFunc || externalSymbol != null)
            //{
            //    string funcEmit = externalSymbol is LinkedData l ? l.Info.Address.ToString() : target;

            //    int targetLength = isInternalFunc
            //                           ? compilation.FunctionMap.Get(target).ParameterCount
            //                           : (externalSymbol as FunctionData)?.ParameterCount ??
            //                             expr.ParameterList.Length;

            //    //if (!expr.WriteProlog && SettingsManager.GetSettings < HlCompilerSettings >().ConstructorPrologMode ==
            //    //     HlTypeConstructorPrologMode.Inline )
            //    //{
            //    //    funcEmit = expr.MemberDefinition.
            //    //}

            //    return ParseFunctionInvocation(compilation, expr, targetLength, funcEmit, "JSR");
            //}

            if (compilation.ContainsVariable(target) ||
                compilation.ConstValTypes.Contains(target))
            {
                foreach (HlExpression parameter in expr.ParameterList)
                {
                    ExpressionTarget ttVal = compilation.Parse(parameter);
                    ExpressionTarget tt    = ttVal.MakeAddress(compilation);

                    compilation.EmitterResult.Emit(
                        $"PUSH",
                        tt.ResultAddress
                        );

                    compilation.ReleaseTempVar(tt.ResultAddress);
                    compilation.ReleaseTempVar(ttVal.ResultAddress);
                }

                if (compilation.ContainsVariable(target))
                {
                    compilation.EmitterResult.Emit($"JSREF", compilation.GetFinalName(target));
                }
                else
                {
                    compilation.EmitterResult.Emit($"JSREF", target);
                }

                ExpressionTarget tempReturn = new ExpressionTarget(
                    compilation.GetTempVarPop(),
                    true,
                    compilation.TypeSystem.GetType(
                        compilation.Root,
                        HLBaseTypeNames.s_UintTypeName
                        )
                    );

                return(tempReturn);
            }

            EventManager <ErrorEvent> .SendEvent(new FunctionNotFoundEvent( target ));

            return(new ExpressionTarget());
        }