Beispiel #1
0
        private void _expandPartialApplication(MacroContext context, int passThrough,
            List<AstExpr> arguments)
        {
            var flatArgs = new List<AstExpr>(arguments.Count);
            var directives = new List<int>(arguments.Count);

            //The call target is a "non-argument" in partial application terms. Do not include it in the
            //  stream of directives.
            flatArgs.Add(arguments[0]);

            var opaqueSpan = 0;
            for (var i = 1; i < arguments.Count; i++)
            {
                var arg = arguments[i];
                AstListLiteral lit;
                if (i < passThrough || !_isPartialList(arg, out lit))
                {
                    flatArgs.Add(arg);
                    opaqueSpan++;
                }
                else
                {
                    flatArgs.AddRange(lit.Elements);
                    if (opaqueSpan > 0)
                    {
                        directives.Add(opaqueSpan);
                        opaqueSpan = 0;
                    }
                    directives.Add(-lit.Elements.Count);
                }
            }

            var ppArgv = AstPartiallyApplicable.PreprocessPartialApplicationArguments(flatArgs);

            var argc = ppArgv.Count;
            var mappings8 = new int[argc + directives.Count + 1];
            var closedArguments = new List<AstExpr>(argc);

            AstPartiallyApplicable.GetMapping(ppArgv, mappings8, closedArguments);
            _mergeDirectivesIntoMappings(directives, mappings8, argc);
            var mappings32 = PartialApplicationCommandBase.PackMappings32(mappings8);

            var implCall = context.Factory.Call(context.Invocation.Position,
                                                EntityRef.Command.Create(PartialCallStarImplCommand.Alias), context.Call);
            implCall.Arguments.AddRange(closedArguments);

            implCall.Arguments.AddRange(mappings32.Select(m => context.CreateConstant(m)));

            context.Block.Expression = implCall;
        }
Beispiel #2
0
 private static AstGetSet _assembleImplCall(MacroContext context, SymbolEntry implementationSymbolEntry,
                                            ISourcePosition position)
 {
     var internalId = context.CreateConstant(implementationSymbolEntry.InternalId);
     var interpretation = implementationSymbolEntry.Interpretation.ToExpr(position);
     var moduleNameOpt = context.CreateConstantOrNull(implementationSymbolEntry.Module);
     var implCall = context.Factory.IndirectCall(context.Invocation.Position,
                                                 context.Factory.Reference(context.Invocation.Position,
                                                                           EntityRef.Command.Create(
                                                                               Impl.Alias)));
     implCall.Arguments.Add(internalId);
     implCall.Arguments.Add(interpretation);
     implCall.Arguments.Add(moduleNameOpt);
     return implCall;
 }
Beispiel #3
0
        protected override void DoExpand(MacroContext context)
        {
            if (context.Invocation.Arguments.Count == 0)
            {
                // Call with no arguments returns null.
                // The macro system will supply that null.
                return;
            }

            var p = context.Invocation.Arguments[0] as AstPlaceholder;
            if (context.Invocation.Arguments.Count == 1
                && p != null
                    && (p.Index.GetValueOrDefault(0) == 0))
            {
                // call(?0) ⇒ call\perform(?0)

                context.Block.Expression = GetTrivialPartialApplication(context);
                return;
            }

            if (!context.Invocation.Arguments.Any(_hasPlaceholder))
            {
                // no placeholders, invoke call\perform directly

                var call = context.Factory.IndirectCall(context.Invocation.Position,
                                                        context.Factory.Reference(context.Invocation.Position,
                                                                                  _callImplementation),
                                                        context.Call);
                call.Arguments.AddRange(GetCallArguments(context));
                context.Block.Expression = call;
                return;
            }

            // Assemble the invocation of call\*(passThrough,call\perform(?),callArguments...)
            //  Note: this is a get-call in all cases, because we are computing a partial application
            //  whether the programmer wrote a get or a set call needs to be captured by concrete
            //  implementations of partial call wrapers (see Call_Member)
            var inv = context.Factory.Expand(context.Invocation.Position, EntityRef.MacroCommand.Create(CallStar.Instance.Id));
            
            // Protect the first two arguments
            inv.Arguments.Add(context.CreateConstant(GetPassThroughArguments(context)));

            // Indicate the kind of call by passing `call\perform(?)`, a partial application of call
            var paCall = context.Factory.Call(context.Invocation.Position, _callImplementation, context.Call,
                                              new AstPlaceholder(context.Invocation.File, context.Invocation.Line,
                                                                 context.Invocation.Column, 0));
                
            inv.Arguments.Add(paCall);

            // Pass all the other arguments through
            inv.Arguments.AddRange(GetCallArguments(context));

            context.Block.Expression = inv;
        }