Exemple #1
0
        //This is an old typeId that was used to optimize small ranges (to generate them in-place).
        //It is currently not used, but in future it may be rejuvenated.
        private bool TryOptimizeRange(ElaRange range, LabelMap map, Hints hints)
        {
            if (range.First.Type != ElaNodeType.Primitive ||
                (range.Second != null && range.Second.Type != ElaNodeType.Primitive) ||
                range.Last.Type != ElaNodeType.Primitive)
                return false;

            var fst = (ElaPrimitive)range.First;
            var snd = range.Second != null ? (ElaPrimitive)range.Second : null;
            var lst = (ElaPrimitive)range.Last;

            if (fst.Value.LiteralType != ElaTypeCode.Integer ||
                (snd != null && snd.Value.LiteralType != ElaTypeCode.Integer) ||
                lst.Value.LiteralType != ElaTypeCode.Integer)
                return false;

            var fstVal = fst.Value.AsInteger();
            var sndVal = snd != null ? snd.Value.AsInteger() : fstVal + 1;
            var lstVal = lst.Value.AsInteger();
            var step = sndVal - fstVal;

            if (Math.Abs((fstVal - lstVal) / step) > 20)
                return false;

            cw.Emit(Op.Newlist);

            if (snd != null)
            {
                cw.Emit(Op.PushI4, fstVal);
                fstVal = sndVal;
                cw.Emit(Op.Cons);
            }

            for (;;)
            {
                cw.Emit(Op.PushI4, fstVal);
                cw.Emit(Op.Cons);
                fstVal += step;

                if (step > 0)
                {
                    if (fstVal > lstVal)
                        break;
                }
                else if (fstVal < lstVal)
                    break;
            }

            cw.Emit(Op.Genfin);
            return true;
        }
Exemple #2
0
        //An entry method for range generation. Implementation of ranges are not provided by a compiler,
        //instead a particular data type implement ranges by providing an instance of Enum class. Functions
        //succ, enumFrom and enumFromTo are explicitly invoked by this method.
        private void CompileRange(ElaExpression parent, ElaRange range, LabelMap map, Hints hints)
        {
            AddLinePragma(range);

            var snd = AddVariable();
            var fst = AddVariable();

            //Compile the first element which should always be present.
            CompileExpression(range.First, map, Hints.None, range);
            PopVar(fst);

            //If the second element is missing we will calculate it using 'succ'.
            if (range.Second == null)
            {
                var sv = GetFunction("succ", range);
                PushVar(fst);
                PushVar(sv);
                cw.Emit(Op.Call);
                PopVar(snd);
            }
            else
            {
                CompileExpression(range.Second, map, Hints.None, range);
                PopVar(snd);
            }

            //If a last element is missing we need to generate an infinite range
            //using 'enumFrom' function.
            if (range.Last == null)
            {
                var sv = GetFunction("enumFrom", range);
                PushVar(snd);
                PushVar(fst);
                PushVar(sv);
                cw.Emit(Op.Call);
                cw.Emit(Op.Call);
            }
            else
            {
                //An ordinary strict range.
                var sv = GetFunction("enumFromTo", range);
                PushVar(snd);
                PushVar(fst);
                CompileExpression(range.Last, map, Hints.None, range);
                PushVar(sv);
                cw.Emit(Op.Call);
                cw.Emit(Op.Call);
                cw.Emit(Op.Call);
            }
        }
Exemple #3
0
        //Finds a function from a Enum class - either enumFrom, enumFromTo or succ.
        private ScopeVar GetFunction(string name, ElaRange range)
        {
            var sv = GetGlobalVariable(name, GetFlags.NoError, range.Line, range.Column);
            var args = name == "enumFrom" ? 2 : name == "enumFromTo" ? 3 : 1;

            //Do some validation to ensure that a found function at least "looks like"
            //a correct one - e.g. is a class member and have a correct number of arguments.
            if (!options.IgnoreUndefined && (sv.IsEmpty() || (sv.Flags & ElaVariableFlags.ClassFun) != ElaVariableFlags.ClassFun || args != sv.Data))
                AddError(
                    name == "enumFrom" ? ElaCompilerError.FromEnumNotFound :
                    name == "enumFromTo" ? ElaCompilerError.FromEnumToNotFound :
                    ElaCompilerError.SuccNotFound,
                    range);

            return sv;
        }
Exemple #4
0
        void RangeExpr(ElaExpression first, ElaExpression sec, out ElaRange rng)
        {
            rng = new ElaRange(t) { First = first, Second = sec };
            var cexp = default(ElaExpression);

            Expect(58);
            if (StartOf(3)) {
            Expr(out cexp);
            rng.Last = cexp;
            }
        }
Exemple #5
0
        void ParamList(out List<ElaExpression> list, out ElaComprehension comp, out ElaRange rng )
        {
            var exp = default(ElaExpression);
            list = null;
            comp = null;
            rng = null;

            Expr(out exp);
            if (la.kind == 26 || la.kind == 56 || la.kind == 58) {
            if (la.kind == 26) {
                ComprehensionExpr(exp, out comp);
            } else if (la.kind == 58) {
                RangeExpr(exp, null, out rng);
            } else {
                var oexp = exp;
                Get();
                Expr(out exp);
                if (la.kind == 58) {
                    RangeExpr(oexp, exp, out rng);
                } else if (la.kind == 22 || la.kind == 56) {
                    list = new List<ElaExpression>();
                    list.Add(oexp);
                    list.Add(exp);

                    while (la.kind == 56) {
                        Get();
                        Expr(out exp);
                        list.Add(exp);
                    }
                } else SynErr(76);
            }
            }
            if (list == null && comp == null && rng == null && exp != null)
            {
            list = new List<ElaExpression>();
            list.Add(exp);
            }
        }