Ejemplo n.º 1
0
 public void DoEmitPartialApplicationCode(CompilerTarget target)
 {
     var argv =
         AstPartiallyApplicable.PreprocessPartialApplicationArguments(
             Subject.Singleton().Append(Arguments));
     var ctorArgc = this.EmitConstructorArguments(target, argv);
     target.EmitConstant(Position, (int) Call);
     target.EmitConstant(Position, Id);
     target.EmitCommandCall(Position, ctorArgc + 2, Engine.PartialMemberCallAlias);
 }
Ejemplo n.º 2
0
        protected override void DoEmitCode(CompilerTarget target, StackSemantics stackSemantics)
        {
            if(stackSemantics == StackSemantics.Value)
                throw new NotSupportedException("Foreach loops don't produce values and can thus not be emitted with value semantics.");

            if (!IsInitialized)
                throw new PrexoniteException("AstForeachLoop requires List and Element to be set.");

            //Optimize expression
            _OptimizeNode(target, ref List);

            //Create the enumerator variable
            var enumVar = Block.CreateLabel("enumerator");
            target.Function.Variables.Add(enumVar);

            //Create the element assignment statement
            var element = Element.GetCopy();
            AstExpr optElem;
            if (element.TryOptimize(target, out optElem))
            {
                element = optElem as AstGetSet;
                if (element == null)
                {
                    target.Loader.ReportMessage(Message.Error(Resources.AstForeachLoop_DoEmitCode_ElementTooComplicated,Position,MessageClasses.ForeachElementTooComplicated));
                    return;
                }
            }
            var ldEnumVar = target.Factory.Call(Position, EntityRef.Variable.Local.Create(enumVar));
            var getCurrent =
                new AstGetSetMemberAccess(File, Line, Column, ldEnumVar, "Current");
            element.Arguments.Add(getCurrent);
            element.Call = PCall.Set;

            //Actual Code Generation
            var moveNextAddr = -1;
            var getCurrentAddr = -1;
            var disposeAddr = -1;

            //Get the enumerator
            target.BeginBlock(Block);

            List.EmitValueCode(target);
            target.EmitGetCall(List.Position, 0, "GetEnumerator");
            var castAddr = target.Code.Count;
            target.Emit(List.Position, OpCode.cast_const, "Object(\"System.Collections.IEnumerator\")");
            target.EmitStoreLocal(List.Position, enumVar);

            //check whether an enhanced CIL implementation is possible
            bool emitHint;
            if (element.DefaultAdditionalArguments + element.Arguments.Count > 1)
                //has additional arguments
                emitHint = false;
            else
                emitHint = true;

            var @try = new AstTryCatchFinally(Position, Block);

            @try.TryBlock = new AstActionBlock
                (
                Position, @try,
                delegate
                    {
                        target.EmitJump(Position, Block.ContinueLabel);

                        //Assignment (begin)
                        target.EmitLabel(Position, Block.BeginLabel);
                        getCurrentAddr = target.Code.Count;
                        element.EmitEffectCode(target);

                        //Code block
                        Block.EmitEffectCode(target);

                        //Condition (continue)
                        target.EmitLabel(Position, Block.ContinueLabel);
                        moveNextAddr = target.Code.Count;
                        target.EmitLoadLocal(List.Position, enumVar);
                        target.EmitGetCall(List.Position, 0, "MoveNext");
                        target.EmitJumpIfTrue(Position, Block.BeginLabel);

                        //Break
                        target.EmitLabel(Position, Block.BreakLabel);
                    });
            @try.FinallyBlock = new AstActionBlock
                (
                Position, @try,
                delegate
                    {
                        disposeAddr = target.Code.Count;
                        target.EmitLoadLocal(List.Position, enumVar);
                        target.EmitCommandCall(List.Position, 1, Engine.DisposeAlias, true);
                    });
                

            @try.EmitEffectCode(target);

            target.EndBlock();

            if (getCurrentAddr < 0 || moveNextAddr < 0 || disposeAddr < 0)
                throw new PrexoniteException(
                    "Could not capture addresses within foreach construct for CIL compiler hint.");
            else if (emitHint)
            {
                var hint = new ForeachHint(enumVar, castAddr, getCurrentAddr, moveNextAddr,
                    disposeAddr);
                Cil.Compiler.AddCilHint(target, hint);

                Action<int, int> mkHook =
                    (index, original) =>
                        {
                            AddressChangeHook hook = null;
                            hook = new AddressChangeHook(
                                original,
                                newAddr =>
                                    {
                                        foreach (
                                            var hintEntry in target.Meta[Loader.CilHintsKey].List)
                                        {
                                            var entry = hintEntry.List;
                                            if (entry[0] == ForeachHint.Key &&
                                                entry[index].Text == original.ToString(CultureInfo.InvariantCulture))
                                            {
                                                entry[index] = newAddr.ToString(CultureInfo.InvariantCulture);
                                                // AddressChangeHook.ctor can be trusted not to call the closure.
                                                // ReSharper disable PossibleNullReferenceException
                                                // ReSharper disable AccessToModifiedClosure
                                                hook.InstructionIndex = newAddr;
                                                // ReSharper restore AccessToModifiedClosure
                                                // ReSharper restore PossibleNullReferenceException
                                                original = newAddr;
                                            }
                                        }
                                    });
                            target.AddressChangeHooks.Add(hook);
                        };

                mkHook(ForeachHint.CastAddressIndex + 1, castAddr);
                mkHook(ForeachHint.GetCurrentAddressIndex + 1, getCurrentAddr);
                mkHook(ForeachHint.MoveNextAddressIndex + 1, moveNextAddr);
                mkHook(ForeachHint.DisposeAddressIndex + 1, disposeAddr);
            } // else nothing
        }
Ejemplo n.º 3
0
 public void DoEmitPartialApplicationCode(CompilerTarget target)
 {
     var argv =
         AstPartiallyApplicable.PreprocessPartialApplicationArguments(Arguments.ToList());
     var ctorArgc = this.EmitConstructorArguments(target, argv);
     var constType = _typeExpr as AstConstantTypeExpression;
     if (constType != null)
         target.EmitConstant(Position, constType.TypeExpression);
     else
         _typeExpr.EmitValueCode(target);
     target.EmitCommandCall(Position, ctorArgc + 1, Engine.PartialConstructionAlias);
 }
Ejemplo n.º 4
0
        public void DoEmitPartialApplicationCode(CompilerTarget target)
        {
            var argv =
                AstPartiallyApplicable.PreprocessPartialApplicationArguments(Subject.Singleton());
            var ctorArgc = this.EmitConstructorArguments(target, argv);
            var constType = Type as AstConstantTypeExpression;
            if (constType != null)
                target.EmitConstant(Position, constType.TypeExpression);
            else
                Type.EmitValueCode(target);

            target.EmitCommandCall(Position, ctorArgc + 1, Engine.PartialTypeCastAlias);
        }
Ejemplo n.º 5
0
 public void DoEmitPartialApplicationCode(CompilerTarget target)
 {
     var argv = AstPartiallyApplicable.PreprocessPartialApplicationArguments(Arguments);
     var ctorArgc = this.EmitConstructorArguments(target, argv);
     var constTypeExpr = TypeExpr as AstConstantTypeExpression;
     if (constTypeExpr != null)
         target.EmitConstant(constTypeExpr.Position, constTypeExpr.TypeExpression);
     else
         TypeExpr.EmitValueCode(target);
     target.EmitConstant(Position, (int) Call);
     target.EmitConstant(Position, _memberId);
     target.EmitCommandCall(Position, ctorArgc + 3, Engine.PartialStaticCallAlias);
 }
Ejemplo n.º 6
0
        public void DoEmitPartialApplicationCode(CompilerTarget target)
        {
            if (Conditions.Count == 0)
            {
                this.ConstFunc(!ShortcircuitValue).EmitValueCode(target);
                return;
            }

            //only the very last condition may be a placeholder
            for (var node = Conditions.First; node != null; node = node.Next)
            {
                var isPlaceholder = node.Value.IsPlaceholder();
                if (node.Next == null)
                {
                    if (!isPlaceholder)
                    {
                        //there is no placeholder at all, wrap expression in const
                        Debug.Assert(Conditions.All(e => !e.IsPlaceholder()));
                        DoEmitCode(target,StackSemantics.Value);
                        target.EmitCommandCall(Position, 1, Const.Alias);
                        return;
                    }
                }
                else
                {
                    if (isPlaceholder)
                    {
                        _reportInvalidPlaceholders(target);
                        return;
                    }
                }
            }

            //We have expression of the form `e1 and e2 and e3 and ... and ?i`
            var placeholder = (AstPlaceholder) Conditions.Last.Value;
            AstPlaceholder.DeterminePlaceholderIndices(placeholder.Singleton());


            // compile the following code: `if(e1 and e2 and e3) id(?) else const(false)`
            var constExpr = CreatePrefix(Position, Conditions.Take(Conditions.Count - 1));
            //var identityFunc = new AstGetSetSymbol(File, Line, Column, PCall.Get, Commands.Core.Id.Alias, SymbolInterpretations.Command);
            //identityFunc.Arguments.Add(new AstPlaceholder(File, Line, Column, placeholder.Index));
            var identityFunc = new AstTypecast(File, Line, Column,
                placeholder.GetCopy(),
                new AstConstantTypeExpression(File, Line, Column, PType.Bool.ToString()));
            var conditional = new AstConditionalExpression(File, Line, Column, constExpr,
                ShortcircuitValue)
                {
                    IfExpression = identityFunc,
                    ElseExpression = this.ConstFunc(ShortcircuitValue)
                };
            conditional.EmitValueCode(target);
        }
Ejemplo n.º 7
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);
            }
        }