Пример #1
0
        public override int Compile(FunctionContext context)
        {
            context.Line(FileName, Line);

            var isStatement = Parent is IBlockStatementExpression;

            if (Name == null && isStatement)
                throw new MondCompilerException(FileName, Line, "Function is never used");

            IdentifierOperand identifier = null;

            if (Name != null)
            {
                if (!context.DefineIdentifier(Name, true))
                    throw new MondCompilerException(FileName, Line, "Identifier '{0}' was previously defined in this scope", Name);

                identifier = context.Identifier(Name);
            }

            var functionContext = context.MakeFunction(Name);
            functionContext.Function(FileName, Name);

            context.PushFrame();

            for (var i = 0; i < Arguments.Count; i++)
            {
                var name = Arguments[i];

                if (!functionContext.DefineArgument(i, name))
                    throw new MondCompilerException(FileName, Line, "Identifier '{0}' was previously defined in this scope", name);
            }

            functionContext.Bind(functionContext.Label);
            functionContext.Enter();
            Block.Compile(functionContext);
            functionContext.LoadUndefined();
            functionContext.Return();

            context.PopFrame();

            context.Closure(functionContext.Label);

            if (identifier != null)
            {
                if (!isStatement) // statements should leave nothing on the stack
                    context.Dup();

                context.Store(identifier);

                if (isStatement)
                    return 0;
            }

            return 1;
        }