Ejemplo n.º 1
0
    //Optimization for a simple 'for' cycle
    private bool TryOptimizeFor(DFor node, Hints hints, CompilerContext ctx)
    {
        if (options.NoOptimizations ||
            node.Guard is not null ||
            node.Pattern.NodeType is not NodeType.NamePattern and not NodeType.WildcardPattern ||
            node.Target.NodeType is not NodeType.Range)
        {
            return(false);
        }

        var incName = node.Pattern is INamedNode nn ? nn.NodeName : null;

        if (incName is not null && incName.Length > 0 && char.IsUpper(incName[0]))
        {
            return(false);
        }

        var range = (DRange)node.Target;

        if (range.From is null)
        {
            return(false);
        }

        long step;
        var  downTo = false;

        if (range.Step is not null && range.Step.NodeType is not NodeType.Integer)
        {
            if (range.Step is not DUnaryOperation u ||
                u.Operator is not UnaryOperator.Neg ||
                u.Node.NodeType is not NodeType.Integer)
            {
                return(false);
            }

            step   = -((DIntegerLiteral)u.Node).Value;
            downTo = true;
        }
Ejemplo n.º 2
0
    private void Build(DFor node, Hints hints, CompilerContext ctx)
    {
        ctx = new(ctx)
        {
            BlockSkip      = cw.DefineLabel(),
            BlockExit      = cw.DefineLabel(),
            BlockBreakExit = cw.DefineLabel()
        };

        if (TryOptimizeFor(node, hints, ctx))
        {
            return;
        }

        StartScope(ScopeKind.Loop, node.Location);
        hints = hints.Remove(Last);

        var inc = false;

        if (node.Pattern.NodeType == NodeType.NamePattern && !char.IsUpper(((DNamePattern)node.Pattern).Name[0] !))
        {
            inc = true;
        }

        var sys      = AddVariable();
        var initSkip = cw.DefineLabel();

        Build(node.Target, hints.Append(Push), ctx);
        cw.Briter(initSkip);
        cw.GetMember(Builtins.Iterate);
        cw.CallNullaryFunction();

        cw.MarkLabel(initSkip);
        cw.GetIter();
        cw.PopVar(sys);

        var iter = cw.DefineLabel();

        cw.MarkLabel(iter);
        cw.PushVar(new ScopeVar(sys));
        cw.CallNullaryFunction();
        cw.Brterm(ctx.BlockExit);

        if (inc)
        {
            var ai = AddVariable(((DNamePattern)node.Pattern).Name !, node.Pattern.Location, VarFlags.None);
            cw.PopVar(ai);
        }
        else
        {
            BuildPattern(node.Pattern, hints, ctx);
            cw.Brfalse(ctx.BlockSkip);
        }

        if (node.Guard != null)
        {
            Build(node.Guard, hints.Append(Push), ctx);
            cw.Brfalse(ctx.BlockSkip);
        }

        var nh = hints.Remove(Push);

        Build(node.Body, nh, ctx);

        cw.MarkLabel(ctx.BlockSkip);
        cw.Br(iter);

        cw.MarkLabel(ctx.BlockExit);
        cw.Pop();
        cw.PushNil();
        AddLinePragma(node);

        cw.MarkLabel(ctx.BlockBreakExit);
        PopIf(hints);
        cw.Nop();
        EndScope();
    }
Ejemplo n.º 3
0
        private void Build(DFor node, Hints hints, CompilerContext ctx)
        {
            ctx = new CompilerContext(ctx)
            {
                BlockSkip      = cw.DefineLabel(),
                BlockExit      = cw.DefineLabel(),
                BlockBreakExit = cw.DefineLabel()
            };
            StartScope(false, node.Location);
            hints = hints.Remove(Last);

            var inc = -1;

            if (node.Pattern.NodeType == NodeType.NamePattern &&
                GetTypeHandle(null, node.Pattern.GetName(), out var _, out var _) != CompilerError.None)
            {
                inc = AddVariable(node.Pattern.GetName(), node.Pattern, VarFlags.None);
            }

            var sys      = AddVariable();
            var initSkip = cw.DefineLabel();

            Build(node.Target, hints.Append(Push), ctx);

            cw.Briter(initSkip);

            cw.GetMember(GetMemberNameId(Builtins.Iterator));

            cw.FunPrep(0);
            cw.FunCall(0);

            cw.MarkLabel(initSkip);
            cw.PopVar(sys);

            var iter = cw.DefineLabel();

            cw.MarkLabel(iter);
            cw.PushVar(new ScopeVar(sys));

            cw.FunPrep(0);
            cw.FunCall(0);

            cw.Brterm(ctx.BlockExit);

            if (inc > -1)
            {
                cw.PopVar(inc);
            }
            else
            {
                BuildPattern(node.Pattern, hints, ctx);
                cw.Brfalse(ctx.BlockSkip);
            }

            if (node.Guard != null)
            {
                Build(node.Guard, hints.Append(Push), ctx);
                cw.Brfalse(ctx.BlockSkip);
            }

            var nh = hints.Has(Push) ? hints.Remove(Push).Append(ExpectPush) : hints.Remove(ExpectPush);

            Build(node.Body, nh, ctx);

            cw.MarkLabel(ctx.BlockSkip);
            cw.Br(iter);

            cw.MarkLabel(ctx.BlockExit);
            cw.Pop();
            PushIf(hints);
            AddLinePragma(node);

            cw.MarkLabel(ctx.BlockBreakExit);
            cw.Nop();
            EndScope();
        }