Esempio n. 1
0
        /// <summary>
        ///     Provides macro environment to its implementing function. The resulting closure 
        ///     implements the expansion of the macro.
        /// </summary>
        /// <param name = "sctx">The stack context to use for wrapping the context.</param>
        /// <param name = "func">The implementation of the macro.</param>
        /// <param name = "context">The macro context for this expansion.</param>
        /// <returns>A closure that implements the expansion of this macro.</returns>
        public static Closure PrepareMacroImplementation(StackContext sctx, PFunction func,
            MacroContext context)
        {
            var contextVar =
                CompilerTarget.CreateReadonlyVariable(sctx.CreateNativePValue(context));

            var env = new SymbolTable<PVariable>(1) {{MacroAliases.ContextAlias, contextVar}};

            var sharedVariables =
                func.Meta[PFunction.SharedNamesKey].List.Select(entry => env[entry.Text]).
                    ToArray();
            return new Closure(func, sharedVariables);
        }
Esempio n. 2
0
        private static void _reportException(MacroContext context, IMacroExpander expander,
            Exception e)
        {
            context.ReportMessage(Message.Create(MessageSeverity.Error,
                String.Format(
                    Resources.MacroSession_ExceptionDuringExpansionOfMacro,
                    expander.HumanId, context.Function.LogicalId,
                    e.Message), context.Invocation.Position, MessageClasses.ExceptionDuringCompilation));
#if DEBUG
            Console.WriteLine(e);
#endif
        }
Esempio n. 3
0
 private static void _setupDefaultExpression(MacroContext context)
 {
     context.Block.Clear();
     context.Block.Expression = CreateNeutralExpression(context.Invocation);
     context.SuppressDefaultExpression = false;
 }
Esempio n. 4
0
            private PValue _invokeMacroFunction(CompilerTarget target, MacroContext context)
            {
                var macro = PrepareMacroImplementation(target.Loader, MacroFunction, context);

                //Execute macro (argument nodes of the invocation node are passed as arguments to the macro)
                var macroInvocation = context.Invocation;
                var arguments =
                    macroInvocation.Arguments.Select(target.Loader.CreateNativePValue).ToArray();
                var parentApplication = MacroFunction.ParentApplication;
                PValue astRaw;
                try
                {
                    parentApplication._SuppressInitialization = true;
                    astRaw = macro.IndirectCall(target.Loader, arguments);
                }
                finally
                {
                    parentApplication._SuppressInitialization = false;
                }
                return astRaw;
            }
Esempio n. 5
0
        public AstNode ExpandMacro(AstGetSet invocation, bool justEffect)
        {
            var target = Target;
            var context = new MacroContext(this, invocation, justEffect);

            //Delegate actual expansion to approriate expander
            var expander = _getExpander(invocation, target);

            if (expander != null)
            {
                expander.Initialize(target, invocation, justEffect);

                //Macro invocations need to be unique within a session
                if (_invocations.Contains(invocation))
                {
                    target.Loader.ReportMessage(
                        Message.Create(MessageSeverity.Error,
                               String.Format(
                                   Resources.MacroSession_MacroNotReentrant,
                                   expander.HumanId),
                               invocation.Position, MessageClasses.MacroNotReentrant));
                    return CreateNeutralExpression(invocation);
                }
                _invocations.Add(invocation);

                //check if this macro is a partial application (illegal)
                if (invocation.Arguments.Any(AstPartiallyApplicable.IsPlaceholder))
                {
                    //Attempt to expand partial macro
                    try
                    {
                        if (!expander.TryExpandPartially(target, context))
                        {
                            target.Loader.ReportMessage(
                                Message.Create(
                                    MessageSeverity.Error,
                                    string.Format(
                                        Resources.MacroSession_MacroCannotBeAppliedPartially,
                                        expander.HumanId), invocation.Position,
                                    MessageClasses.PartialApplicationNotSupported));
                            return CreateNeutralExpression(invocation);
                        }
                    }
                    catch (Exception e)
                    {
                        _setupDefaultExpression(context);
                        _reportException(context, expander, e);
                    }
                }
                else
                {
                    //Actual macro expansion takes place here
                    try
                    {
                        var cub = target.CurrentBlock;
                        expander.Expand(target, context);
                        if(!ReferenceEquals(cub,target.CurrentBlock))
                            throw new PrexoniteException("Macro must restore previous lexical scope.");
                    }
                    catch (Exception e)
                    {
                        _setupDefaultExpression(context);
                        _reportException(context, expander, e);
                    }
                }
            }

            //Sanitize output
            var ast = context.Block;

            //ensure that there is at least null being pushed onto the stack))
            if (!justEffect && ast.Expression == null && !context.SuppressDefaultExpression)
                ast.Expression = CreateNeutralExpression(invocation);

            var node = AstNode._GetOptimizedNode(Target, ast);

            return node;
        }
Esempio n. 6
0
 /// <summary>
 ///     Expands the macro according to the supplied macro context.
 /// </summary>
 /// <param name = "context">Supplies call site information to the macro.</param>
 public void Expand(MacroContext context)
 {
     DoExpand(context);
 }
Esempio n. 7
0
            private void _implementMergeRules(MacroContext context, AstExpr ce,
                                              IEnumerable<AstNode> fs, AstExpr fe)
            {
                var contextBlock = context.Block;
                //cs  is already stored in contextBlock, 
                //  the rules position cs always at the beginning, thus no need to handle cs.

                //At this point
                //  {   ce   }  iff (ce ∧ fs ∧ fe)
                //  {tmp = ce}  iff (ce ∧ fs ∧ ¬fe)
                //  {        }  otherwise
                if (ce != null && fs != null)
                {
                    if (fe != null)
                    {
                        contextBlock.Add(ce);
                    }
                    else
                    {
                        //Might at a later point become a warning
                        var invocationPosition = context.Invocation.Position;
                        context.ReportMessage(Message.Create(MessageSeverity.Info,
                                                             String.Format(
                                                                 Resources.MacroFunctionExpander__UsedTemporaryVariable,
                                                                 HumanId),
                                                             invocationPosition, MessageClasses.BlockMergingUsesVariable));

                        var tmpV = context.AllocateTemporaryVariable();

                        //Generate assignment to temporary variable
                        var tmpVRef = context.Factory.Reference(invocationPosition, EntityRef.Variable.Local.Create(tmpV));
                        var assignTmpV = context.Factory.IndirectCall(invocationPosition,tmpVRef,PCall.Set);
                        assignTmpV.Arguments.Add(ce);
                        contextBlock.Add(assignTmpV);

                        //Generate lookup of computed value
                        ce = context.Factory.IndirectCall(invocationPosition,tmpVRef);
                    }
                }

                //At this point
                //  {fs}    iff (fs)
                //  {  }    otherwise

                if (fs != null)
                {
                    foreach (var stmt in fs)
                        contextBlock.Add(stmt);
                }

                //Finally determine expression
                //  = fe    iff (ce ∧ fe)
                //  = ce    iff (ce ∧ ¬fe ∧ ¬fs)
                //  = tmp   iff (ce ∧ ¬fe ∧ fs)
                //  = ⊥     otherwise
                if (fe != null)
                    contextBlock.Expression = fe;
                else if (ce != null)
                    contextBlock.Expression = ce; //if tmp is involved, it has replaced ce
                else
                    contextBlock.Expression = null; //macro session will cover this case
            }
Esempio n. 8
0
 public bool TryExpandPartially(CompilerTarget target, MacroContext context)
 {
     var pac = MacroCommand as PartialMacroCommand;
     return pac != null && pac.ExpandPartialApplication(context);
 }
Esempio n. 9
0
            public void Expand(CompilerTarget target, MacroContext context)
            {
                if (MacroFunction == null)
                    return;

                var astRaw = _invokeMacroFunction(target, context);

                //Optimize
                AstNode ast;
                if (astRaw != null)
                    ast = astRaw.Value as AstNode;
                else
                    ast = null;

                var expr = ast as AstExpr;

                /*Merge with context expression block
                 *  cs = Statements from context
                 *  ce = Expression from context
                 *  fs = Statements from function return value
                 *  fe = Expression from function return value
                 * Rules
                 *  general:
                 *      {cs;ce;fs} = fe
                 *  no-fe:
                 *      {cs;tmp = ce;fs} = tmp
                 *  no-f:
                 *      {cs} = ce
                 *  no-c:
                 *      {fs} = fe
                 */
                var contextBlock = context.Block;
                var macroBlock = ast as AstBlock;

                // ReSharper disable JoinDeclarationAndInitializer
                AstExpr ce, fe;
                IEnumerable<AstNode> fs;
                // ReSharper restore JoinDeclarationAndInitializer
                //determine ce
                ce = contextBlock.Expression;

                //determine fe
                if (macroBlock != null)
                    fe = macroBlock.Expression;
                else if (expr != null)
                {
                    fe = expr;

                    //cannot be statement at the same time, set ast to null.
                    ast = null;
                }
                else
                    fe = null;

                //determine fs
                if (macroBlock != null)
                    fs = macroBlock.Count > 0 ? macroBlock.Statements : null;
                else if (ast != null)
                    fs = new[] {ast};
                else
                    fs = null;

                _implementMergeRules(context, ce, fs, fe);
            }
Esempio n. 10
0
 protected override int GetPassThroughArguments(MacroContext context)
 {
     return 3;
 }
Esempio n. 11
0
            public void Expand(CompilerTarget target, MacroContext context)
            {
                if (MacroCommand == null)
                    return;

                MacroCommand.Expand(context);
            }
Esempio n. 12
0
 protected override AstGetSet GetTrivialPartialApplication(MacroContext context)
 {
     var pa = base.GetTrivialPartialApplication(context);
     pa.Arguments.Insert(1, _getIsSetExpr(context));
     return pa;
 }
Esempio n. 13
0
 private static AstExpr _getIsSetExpr(MacroContext context)
 {
     return context.CreateConstant(context.Invocation.Call == PCall.Set);
 }
Esempio n. 14
0
 protected override IEnumerable<AstExpr> GetCallArguments(MacroContext context)
 {
     var argv = context.Invocation.Arguments;
     return
         argv.Take(1).Append(_getIsSetExpr(context)).Append(argv.Skip(1));
 }
Esempio n. 15
0
            protected override void DoExpand(MacroContext context)
            {
                _specifyDeficiency(context);

                base.DoExpand(context);
            }
Esempio n. 16
0
            public bool TryExpandPartially(CompilerTarget target, MacroContext context)
            {
                if (!MacroFunction.Meta[PartialMacroKey].Switch)
                    return false;

                var successRaw = _invokeMacroFunction(target, context);
                if (successRaw.Type != PType.Bool)
                {
                    context.ReportMessage(Message.Create(MessageSeverity.Error,
                                                         Resources.MacroFunctionExpander_PartialMacroMustIndicateSuccessWithBoolean,
                                                         context.Invocation.Position,
                                                         MessageClasses.PartialMacroMustReturnBoolean));
                    _setupDefaultExpression(context);
                    return false;
                }

                return (bool) successRaw.Value;
            }
Esempio n. 17
0
 private static void _specifyDeficiency(MacroContext context)
 {
     context.Function.Meta[PFunction.VolatileKey] = true;
     MetaEntry deficiency;
     if (!context.Function.Meta.TryGetValue(PFunction.DeficiencyKey, out deficiency) ||
         deficiency.Text == "")
         context.Function.Meta[PFunction.DeficiencyKey] = string.Format("Uses {0}.",
             Engine.Call_TailAlias);
 }
Esempio n. 18
0
 /// <summary>
 ///     Implementation of the application of this macro.
 /// </summary>
 /// <param name = "context">The macro context for this macro expansion.</param>
 protected abstract void DoExpand(MacroContext context);