示例#1
0
        public void DoEmitPartialApplicationCode(CompilerTarget target)
        {
            AstPlaceholder.DeterminePlaceholderIndices(Expressions.OfType<AstPlaceholder>());

            var count = Expressions.Count;
            if (count == 0)
            {
                this.ConstFunc(null).EmitValueCode(target);
                return;
            }

            //only the very last condition may be a placeholder
            for (var i = 0; i < count; i++)
            {
                var value = Expressions[i];
                var isPlaceholder = value.IsPlaceholder();
                if (i == count - 1)
                {
                    if (!isPlaceholder)
                    {
                        //there is no placeholder at all, wrap expression in const
                        Debug.Assert(Expressions.All(e => !e.IsPlaceholder()));
                        DoEmitCode(target,StackSemantics.Value);
                        target.EmitCommandCall(Position, 1, Const.Alias);
                        return;
                    }
                }
                else
                {
                    if (isPlaceholder)
                    {
                        _reportInvalidPlaceholders(target);
                        return;
                    }
                }
            }

            if (count == 0)
            {
                this.ConstFunc().EmitValueCode(target);
            }
            else if (count == 1)
            {
                Debug.Assert(Expressions[0].IsPlaceholder(),
                    "Singleton ??-chain expected to consist of placeholder.");
                var placeholder = (AstPlaceholder) Expressions[0];
                placeholder.IdFunc().EmitValueCode(target);
            }
            else
            {
                Debug.Assert(Expressions[count - 1].IsPlaceholder(),
                    "Last expression in ??-chain expected to be placeholder.");
                var placeholder = (AstPlaceholder) Expressions[count - 1];
                var prefix = new AstCoalescence(File, Line, Column);
                prefix.Expressions.AddRange(Expressions.Take(count - 1));

                //check for null (keep a copy of prefix on stack)
                var constLabel = _generateEndLabel();
                var endLabel = _generateEndLabel();
                prefix._emitCode(target, constLabel, StackSemantics.Value);
                target.EmitDuplicate(Position);
                target.Emit(Position,OpCode.check_null);
                target.EmitJumpIfFalse(Position, constLabel);
                //prefix is null, identity function
                target.EmitPop(Position);
                placeholder.IdFunc().EmitValueCode(target);
                target.EmitJump(Position, endLabel);
                //prefix is not null, const function
                target.EmitLabel(Position, constLabel);
                target.EmitCommandCall(Position, 1, Const.Alias);
                target.EmitLabel(Position, endLabel);
            }
        }
示例#2
0
        private void _emitCode(CompilerTarget target, string endLabel, StackSemantics stackSemantics)
        {
            for (var i = 0; i < _expressions.Count; i++)
            {
                var expr = _expressions[i];

                // Value semantics: duplicate of previous, rejected value needs to be popped
                // Effect semantics: no duplicates were created in the first place
                if (i > 0 && stackSemantics == StackSemantics.Value)
                    target.EmitPop(Position);

                //For value semantics, we always generate a value
                //For effect semantics, we only need the intermediate expressions to create a value
                StackSemantics needValue;
                if (stackSemantics == StackSemantics.Value || i < _expressions.Count - 1)
                    needValue = StackSemantics.Value;
                else 
                    needValue = StackSemantics.Effect;

                expr.EmitCode(target, needValue);

                //The last element doesn't need special handling, control just 
                //  falls into the surrounding code with the correct value on top of the stack
                if (i + 1 >= _expressions.Count)
                    continue;

                if(stackSemantics == StackSemantics.Value)
                    target.EmitDuplicate(Position);
                target.Emit(Position,OpCode.check_null);
                target.EmitJumpIfFalse(Position, endLabel);
            }
        }