Esempio n. 1
0
 public static bool TryCreateConstant(
     CompilerTarget target,
     ISourcePosition position,
     PValue value,
     out AstExpr expr)
 {
     expr = null;
     if (value.Type is ObjectPType)
         target.Loader.Options.ParentEngine.CreateNativePValue(value.Value);
     if (value.Type is IntPType 
         || value.Type is RealPType 
         || value.Type is BoolPType 
         || value.Type is StringPType 
         || value.Type is NullPType 
         || _isModuleName(value))
         expr = new AstConstant(position.File, position.Line, position.Column, value.Value);
     else //Cannot represent value in a constant instruction
         return false;
     return true;
 }
Esempio n. 2
0
 private static AstExpr _genCompare(MacroContext context, AstExpr retVar,
     ReturnVariant expected)
 {
     var inv = context.Invocation;
     AstExpr expectedNode = new AstConstant(inv.File,
         inv.Line,
         inv.Column, (int) expected);
     return context.Factory.BinaryOperation(inv.Position, retVar, BinaryOperator.Equality, expectedNode);
 }
Esempio n. 3
0
        private static void _replaceDebug(CompilerTarget t, IList<AstNode> block, bool debugging)
        {
            for (var i = 0; i < block.Count; i++)
            {
                var stmt = block[i] as AstGetSet;
                //look for calls
                if (_isDebugCall(stmt))
                {
                    System.Diagnostics.Debug.Assert(stmt != null);
                    //Found a call to debug
                    block.RemoveAt(i);
                    if (debugging)
                    {
                        for (var j = 0; j < stmt.Arguments.Count; j++)
                        {
                            var arg = stmt.Arguments[j] as AstIndirectCall;
                            AstReference refNode;
                            if (arg != null && (refNode = arg.Subject as AstReference) != null)
                            {
                                var printlnCall = t.Factory.Call(stmt.Position,
                                                                 EntityRef.Command.Create(Engine.PrintLineAlias));
                                var concatCall = t.Factory.Call(stmt.Position,
                                                                EntityRef.Command.Create(Engine.ConcatenateAlias));
                                var consts =
                                    new AstConstant(
                                        stmt.File,
                                        stmt.Line,
                                        stmt.Column,
                                        String.Concat("DEBUG ", refNode.Entity, " = "));
                                concatCall.Arguments.Add(consts);
                                concatCall.Arguments.Add(arg);
                                printlnCall.Arguments.Add(concatCall);

                                block.Insert(i, printlnCall);
                                i += 1;
                            } //end if arg not null
                        } //end for arguments             
                    } //end if debugging

                    continue;
                } //end if debug call

                var cond = block[i] as AstCondition;

                //look for conditions
                if (cond != null)
                {
                    var expr = cond.Condition as AstIndirectCall;
                    AstReference refNode;
                    EntityRef.Command cmd;
                    if (expr != null 
                        && (refNode = expr.Subject as AstReference) != null 
                        && refNode.Entity.TryGetCommand(out cmd) 
                        && Engine.StringsAreEqual(cmd.Id,Engine.DebugAlias) )
                        cond.Condition =
                            new AstConstant(expr.File, expr.Line, expr.Column, debugging);
                }

                //Recursively replace 'debug' in nested blocks.
                var complex = block[i] as IAstHasBlocks;
                if (complex != null)
                    foreach (var subBlock in complex.Blocks)
                        _replaceDebug(t, subBlock, debugging);
            } //end for statements
        }
Esempio n. 4
0
 private bool _tryOptimizeConstCast(CompilerTarget target, AstConstant constSubject,
     AstConstantTypeExpression constType, out AstExpr expr)
 {
     expr = null;
     PType type;
     try
     {
         type = target.Loader.ConstructPType(constType.TypeExpression);
     }
     catch (PrexoniteException)
     {
         //ignore, cast failed. cannot be optimized
         return false;
     }
     PValue result;
     if (constSubject.ToPValue(target).TryConvertTo(target.Loader, type, out result))
         return AstConstant.TryCreateConstant(target, Position, result, out expr);
     else
         return false;
 }
Esempio n. 5
0
        public override bool TryOptimize(CompilerTarget target, out AstExpr expr)
        {
            expr = null;
            var placeholders = Conditions.Count(AstPartiallyApplicable.IsPlaceholder);
            for (var node = Conditions.First; node != null; node = node.Next)
            {
                var condition = node.Value;
                _OptimizeNode(target, ref condition);
                node.Value = condition; //Update list of conditions with optimized condition

                PValue resultP;
                if (condition is AstConstant &&
                    ((AstConstant) condition).ToPValue(target).TryConvertTo(target.Loader,
                        PType.Bool, false, out resultP))
                {
                    if ((bool) resultP.Value == ShortcircuitValue)
                    {
                        // Expr1 OP shortcircuit OP Expr2 = shortcircuit
                        // Expr1 OP shortcircuit OP Expr2 OP ? = const(shortcircuit)
                        var shortcircuitConst = new AstConstant(condition.File, condition.Line,
                            condition.Column, ShortcircuitValue);
                        if (placeholders > 0)
                        {
                            if (!Conditions.Last.Value.IsPlaceholder() || placeholders > 1)
                                _reportInvalidPlaceholders(target);

                            expr = shortcircuitConst.ConstFunc();
                        }
                        else
                        {
                            expr = shortcircuitConst;
                        }
                        return true;
                    }
                    else
                    {
                        // Expr1 OP ¬shortcircuit OP Expr2 = Expr1 OP Expr2
                        Conditions.Remove(node);
                    }
                }
                else if (condition is AstPlaceholder)
                {
                    placeholders++;
                }
            }

            if (Conditions.Count == 0)
            {
                expr = new AstConstant(File, Line, Column, !ShortcircuitValue);
            }
            else if (Conditions.Count == 1)
            {
                var primaryExpr = Conditions.First.Value;
                expr = _GetOptimizedNode(target,
                    new AstTypecast(primaryExpr.File, primaryExpr.Line, primaryExpr.Column,
                        primaryExpr,
                        new AstConstantTypeExpression(primaryExpr.File,
                            primaryExpr.Line,
                            primaryExpr.Column,
                            PType.Bool.ToString())));
            }

            return expr != null;
        }
Esempio n. 6
0
        private static bool _parseArguments(MacroContext context, out AstExpr call,
            out AstExpr justEffect, out AstExpr[] args,
            out AstExpr macroSpec)
        {
            /* call(macroRef,...) = call([],macroRef,[false],...);
             * call([],macroRef,[je],...) = call([],macroRef,[je,context.Call],...);
             * call([],macroRef,[je,c],...) = { macroId := macroRef.Id; 
             *                                  macroInterpretation := interpretation(macroRef); 
             *                                  call := c; 
             *                                  justEffect := je 
             *                                }
             * call([proto(...1)],...2) = call([],from_proto(proto),[false,PCall.Get],[...1],...2);
             * call([proto(...1) = x],...2) = call([],from_proto(proto),[false,PCall.Set],[...1],...2,[x]);
             * call([proto(...1),je],...2) = call([],from_proto(proto),[je,PCall.Get],[...1],...2);
             * call([proto(...1) = x,je],...2) = call([],from_proto(proto),[je,PCall.Set],[...1],...2,[x]);
             * call([proto(...1),je,c],...2) = call([],from_proto(proto),[je,c],[...1],...2);
             */

            var inv = context.Invocation;
            justEffect = new AstConstant(inv.File, inv.Line,
                inv.Column, false);
            call = PCall.Get.ToExpr(context.Invocation.Position);

            var invokeSpec = inv.Arguments[0];
            var listSpec = invokeSpec as AstListLiteral;
            if (listSpec == null)
            {
                // - Macro reference specified as expression that evaluates to an actual macro reference

                args = inv.Arguments.Skip(1).ToArray();
                macroSpec = invokeSpec;
                return _parseReference(context, inv.Arguments[0]);
            }
            else if (listSpec.Elements.Count == 0)
            {
                // - Macro reference specified as expression that evaluates to an actual macro reference
                // - followed by a list of options

                AstListLiteral optionsRaw;
                if (inv.Arguments.Count < 3 ||
                    (optionsRaw = inv.Arguments[2] as AstListLiteral) == null)
                {
                    _errorUsageFullRef(context);
                    args = null;
                    macroSpec = null;
                    return false;
                }

                macroSpec = inv.Arguments[1];

                //first option: justEffect
                if (optionsRaw.Elements.Count >= 1)
                    justEffect = optionsRaw.Elements[0];

                //second option: call type
                if (optionsRaw.Elements.Count >= 2)
                    call = optionsRaw.Elements[1];

                //args: except first 3
                args = inv.Arguments.Skip(3).ToArray();

                return _parseReference(context, inv.Arguments[1]);
            }
            else
            {
                // - Macro reference specified as a prototype
                // - includes list of options

                var specProto = listSpec.Elements[0];
                PCall protoCall;
                IList<AstExpr> protoArguments;
                if (
                    !_parsePrototype(context, specProto, out protoCall,
                        out protoArguments, out macroSpec))
                {
                    args = null;
                    return false;
                }

                //first option: justEffect
                if (listSpec.Elements.Count >= 2)
                    justEffect = listSpec.Elements[1];

                //second option: call type
                call = listSpec.Elements.Count >= 3
                    ? listSpec.Elements[2]
                    : protoCall.ToExpr(specProto.Position);

                //args: lift and pass prototype arguments, special care for set

                var setArgs = protoCall == PCall.Set
                    ? protoArguments.Last()
                    : null;
                var getArgs = protoCall == PCall.Set
                    ? protoArguments.Take(protoArguments.Count - 1)
                    : protoArguments;

                // ReSharper disable PossibleMultipleEnumeration 
                // enumerating getArgs multiple times is safe and efficient
                if (getArgs.Any(a => !_ensureExplicitPlaceholder(context, a)))

                {
                    args = new AstExpr[] {};
                    return false;
                }

                IEnumerable<AstExpr> getArgsLit;
                if (getArgs.Any())
                {
                    var getArgsLitNode = new AstListLiteral(specProto.File, specProto.Line,
                        specProto.Column);
                    getArgsLitNode.Elements.AddRange(getArgs);
                    getArgsLit = getArgsLitNode.Singleton();
                }
                // ReSharper restore PossibleMultipleEnumeration
                else
                {
                    getArgsLit = Enumerable.Empty<AstExpr>();
                }

                IEnumerable<AstExpr> setArgsLit;
                if (setArgs != null)
                {
                    if (!_ensureExplicitPlaceholder(context, setArgs))
                    {
                        args = new AstExpr[] {};
                        return false;
                    }
                    var lit = new AstListLiteral(setArgs.File, setArgs.Line, setArgs.Column);
                    lit.Elements.Add(setArgs);
                    setArgsLit = lit.Singleton();
                }
                else
                {
                    setArgsLit = Enumerable.Empty<AstExpr>();
                }

                args = getArgsLit
                    .Append(inv.Arguments.Skip(1))
                    .Append(setArgsLit).ToArray();

                return true;
            }
        }
Esempio n. 7
0
        public override bool TryOptimize(CompilerTarget target, out AstExpr expr)
        {
            _OptimizeNode(target, ref _subject);
            _type = (AstTypeExpr) _GetOptimizedNode(target, _type);

            expr = null;

            var constSubject = _subject as AstConstant;
            var constType = _type as AstConstantTypeExpression;
            if (constSubject == null || constType == null)
                return false;
            PType type;
            try
            {
                type = target.Loader.ConstructPType(constType.TypeExpression);
            }
            catch (PrexoniteException)
            {
                //ignore, cast failed. cannot be optimized
                return false;
            }
            expr =
                new AstConstant(File, Line, Column, constSubject.ToPValue(target).Type.Equals(type));
            return true;
        }