public override ParseResult VisitFunctionDefinitionStatement(MelonParser.FunctionDefinitionStatementContext context)
        {
            string name = context.Name.GetText();

            LexicalEnvironment functionEnvironment = new LexicalEnvironment(parseContext.LexicalEnvironment, true);

            var functionParameters = new List <FunctionParameter>();

            if (context.Parameters != null)
            {
                for (var i = 0; i < context.Parameters.parameter().Length; i++)
                {
                    var parameter = context.Parameters.parameter(i);

                    bool isVarargs = parameter.VARARGS() != null;

                    if (isVarargs && i < context.Parameters.parameter().Length - 1)
                    {
                        throw new MelonException("Varargs parameter can only appear once and has to be the last parameter");
                    }

                    MelonType type = _engine.anyType;

                    if (parameter.Type != null)
                    {
                        var typeName = parameter.Type.name().value;
                        var typeKv   = _engine.Types.FirstOrDefault(x => x.Value.Name == typeName);

                        if (typeKv.Value == null)
                        {
                            throw new MelonException($"Could not find type '{typeName}'");
                        }

                        type = typeKv.Value;
                    }

                    var typeRef = new TypeReference(_engine, type);

                    functionEnvironment.AddVariable(parameter.Name.value, null, typeRef);
                    functionParameters.Add(new FunctionParameter(parameter.Name.value, typeRef, isVarargs));
                }
            }

            var function = new ScriptFunctionInstance(name, _engine)
            {
                ParameterTypes = functionParameters.ToArray()
            };

            var variable = parseContext.LexicalEnvironment.AddVariable(name, function, new TypeReference(_engine, _engine.functionType));

            parseContext.AddVariableReference(variable, VariableReferenceType.Local);

            if (context.ReturnType != null)
            {
                var typeName = context.ReturnType.value;
                var typeKv   = _engine.Types.FirstOrDefault(x => x.Value.Name == typeName);

                if (typeKv.Value == null)
                {
                    throw new MelonException($"Could not find type '{typeName}'");
                }

                function.ReturnType = new TypeReference(_engine, typeKv.Value);
            }

            MelonVisitor visitor = new MelonVisitor(_engine, function);
            ParseContext functionParseContext = visitor.Parse(context.Block, functionEnvironment);

            function.SetContext(functionEnvironment, functionParseContext);

            return(DefaultResult);
        }