Ejemplo n.º 1
0
 private void Build(DYield node, Hints hints, CompilerContext ctx)
 {
     Build(node.Expression, hints.Append(Push), ctx);
     AddLinePragma(node);
     cw.Yield();
     PushIf(hints);
 }
Ejemplo n.º 2
0
 private void AddHint(object obj)
 {
     if (!Guard.IsNullOrEmpty(CurrentHint))
     {
         Hints.Add(CurrentHint.Trim());
     }
 }
Ejemplo n.º 3
0
        private void Build(DWhile node, Hints hints, CompilerContext ctx)
        {
            ctx = new CompilerContext(ctx)
            {
                BlockSkip      = cw.DefineLabel(),
                BlockExit      = cw.DefineLabel(),
                BlockBreakExit = cw.DefineLabel()
            };
            var iter = cw.DefineLabel();

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

            if (node.DoWhile)
            {
                Build(node.Body, nh, ctx);
            }

            cw.MarkLabel(iter);
            Build(node.Condition, hints.Append(Push), ctx);
            cw.Brfalse(ctx.BlockExit);

            Build(node.Body, nh, ctx);

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

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

            cw.MarkLabel(ctx.BlockBreakExit);
            cw.Nop();
        }
Ejemplo n.º 4
0
        private void BuildRangeElement(DPattern node, Hints hints)
        {
            switch (node.NodeType)
            {
            case NodeType.IntegerPattern:
                cw.Push(((DIntegerPattern)node).Value);
                break;

            case NodeType.FloatPattern:
                cw.Push(((DFloatPattern)node).Value);
                break;

            case NodeType.BooleanPattern:
                cw.Push(((DBooleanPattern)node).Value);
                break;

            case NodeType.CharPattern:
                cw.Push(((DCharPattern)node).Value);
                break;

            case NodeType.StringPattern:
                cw.Push(((DStringPattern)node).Value.Value);
                break;

            case NodeType.NilPattern:
                cw.PushNil();
                break;

            default:
                AddError(CompilerError.PatternNotSupported, node.Location, node);
                break;
            }
        }
Ejemplo n.º 5
0
 private void PreinitCtor(DCtorPattern node, Hints hints)
 {
     if (node.Arguments != null && node.Arguments.Count > 0)
     {
         PreinitSequence(node.Arguments, hints);
     }
 }
Ejemplo n.º 6
0
        private void BuildName(DNamePattern node, Hints hints, CompilerContext ctx)
        {
            var err = GetTypeHandle(null, node.Name, out var handle, out var std);

            if (err == CompilerError.None)
            {
                cw.TypeCheck(new TypeHandle(handle, std));
            }
            else
            {
                ScopeVar sv    = default;
                var      found = hints.Has(Rebind)
                    ? TryGetVariable(node.Name, out sv)
                    : hints.Has(OpenMatch) ? false : TryGetLocalVariable(node.Name, out sv);
                var sva = sv.Address;

                if (!found)
                {
                    sva = AddVariable(node.Name, node, hints.Has(Const) ? VarFlags.Const : VarFlags.None);
                }
                else if ((sv.Data & VarFlags.Const) == VarFlags.Const)
                {
                    AddError(CompilerError.UnableAssignConstant, node.Location, node.Name);
                }

                cw.PopVar(sva);
                cw.Push(true);
            }
        }
Ejemplo n.º 7
0
        private void BuildRange(DRangePattern node, Hints hints, CompilerContext ctx)
        {
            var skip = cw.DefineLabel();
            var exit = cw.DefineLabel();

            cw.Dup();         //2 objs
            cw.HasMember(GetMemberNameId(Builtins.Lt));
            cw.Brfalse(skip); //1 left

            cw.Dup();         //2 objs
            cw.HasMember(GetMemberNameId(Builtins.Gt));
            cw.Brfalse(skip); //1 left

            cw.Dup();         //2 objs
            BuildRangeElement(node.From, hints);
            cw.GtEq();
            cw.Brfalse(skip); //1 left

            cw.Dup();         //2 objs
            BuildRangeElement(node.To, hints);
            cw.LtEq();
            cw.Brfalse(skip); //1 left

            cw.Push(true);
            cw.Pop(); //0 left
            cw.Br(exit);

            cw.MarkLabel(skip);
            cw.Pop(); //0 left
            cw.Push(false);

            cw.MarkLabel(exit);
            cw.Nop();
        }
Ejemplo n.º 8
0
        private void BuildAs(DAsPattern node, Hints hints, CompilerContext ctx)
        {
            cw.Dup();

            BuildPattern(node.Pattern, hints, ctx);
            var bad = cw.DefineLabel();
            var ok  = cw.DefineLabel();

            cw.Brfalse(bad);
            var sva = -1;

            if (!TryGetLocalVariable(node.Name, out var sv))
            {
                sva = AddVariable(node.Name, node, VarFlags.None);
            }
            else
            {
                sva = sv.Address;
            }

            cw.PopVar(sva);
            cw.Push(true);
            cw.Br(ok);
            cw.MarkLabel(bad);
            cw.Pop();
            cw.Push(false);
            cw.MarkLabel(ok);
            cw.Nop();
        }
Ejemplo n.º 9
0
        private void BuildMethodCheck(DMethodCheckPattern node, Hints hints, CompilerContext ctx)
        {
            AddLinePragma(node);
            var nameId = GetMemberNameId(node.Name);

            cw.HasMember(nameId);
        }
Ejemplo n.º 10
0
        private void BuildCtor(DCtorPattern node, Hints hints, CompilerContext ctx)
        {
            var bad = cw.DefineLabel();
            var ok  = cw.DefineLabel();

            cw.Dup();

            var nameId = GetMemberNameId(node.Constructor);

            cw.CtorCheck(nameId);
            cw.Brfalse(bad);

            if (node.Arguments == null || node.Arguments.Count == 0)
            {
                cw.Pop();
                cw.Push(true);
            }
            else
            {
                BuildSequence(node, node.Arguments, hints, ctx);
            }

            cw.Br(ok);

            cw.MarkLabel(bad);
            AddLinePragma(node);
            cw.Pop();
            cw.Push(false);

            cw.MarkLabel(ok);
        }
Ejemplo n.º 11
0
        //Compile conditional if-then-else operator
        private void CompileConditionalOperator(ElaCondition s, LabelMap map, Hints hints)
        {
            AddLinePragma(s);
            CompileExpression(s.Condition, map, Hints.Scope, s);
            var falseLab = cw.DefineLabel();
            cw.Emit(Op.Brfalse, falseLab);

            //Both the True and False parts may be the tail expressions
            //Also this whole operator can be used as a statement. Or can be compiled
            //in a situation when some of the referenced names are not initialized (Lazy)
            var left = (hints & Hints.Left) == Hints.Left ? Hints.Left : Hints.None;
            var tail = (hints & Hints.Tail) == Hints.Tail ? Hints.Tail : Hints.None;

            if (s.True != null)
                CompileExpression(s.True, map, left | tail | Hints.Scope, s);

            if (s.False != null)
            {
                var skipLabel = cw.DefineLabel();
                cw.Emit(Op.Br, skipLabel);
                cw.MarkLabel(falseLab);
                CompileExpression(s.False, map, left | tail | Hints.Scope, s);
                cw.MarkLabel(skipLabel);
                cw.Emit(Op.Nop);
            }
            else
            {
                AddError(ElaCompilerError.ElseMissing, s.True);
                AddHint(ElaCompilerHint.AddElse, s.True);
            }
        }
Ejemplo n.º 12
0
        //Used to compile a 'try' expression.
        private void CompileTryExpression(ElaTry n, LabelMap map, Hints hints)
        {
            var catchLab = cw.DefineLabel();
            var exitLab  = cw.DefineLabel();

            //Generate a start of a 'try' section
            AddLinePragma(n);
            cw.Emit(Op.Start, catchLab);

            CompileExpression(n.Expression, map, Hints.None, n);

            //Leaving 'try' section
            cw.Emit(Op.Leave);
            cw.Emit(Op.Br, exitLab);
            cw.MarkLabel(catchLab);
            cw.Emit(Op.Leave);

            //Throw hint is to tell match compiler to generate a different typeId if
            //all pattern fail - to rethrow an original error instead of generating a
            //new MatchFailed error.
            CompileSimpleMatch(n.Entries.Equations, map, hints | Hints.Throw, null);

            cw.MarkLabel(exitLab);
            cw.Emit(Op.Nop);

            if ((hints & Hints.Left) == Hints.Left)
            {
                AddValueNotUsed(map, n);
            }
        }
Ejemplo n.º 13
0
        private void Build(DTupleLiteral node, Hints hints, CompilerContext ctx)
        {
            for (var i = 0; i < node.Elements.Count; i++)
            {
                var    el = node.Elements[i];
                string name;

                if (el.NodeType == NodeType.Label)
                {
                    var label = (DLabelLiteral)el;
                    Build(label.Expression, hints.Append(Push), ctx);
                    cw.Tag(label.Label);
                }
                else
                {
                    Build(el, hints.Append(Push), ctx);

                    if ((name = el.GetName()) != null)
                    {
                        cw.Tag(name);
                    }
                }
            }

            AddLinePragma(node);
            cw.NewTuple(node.Elements.Count);
            PopIf(hints);
        }
    /**
     * Creates a new QuestManager. Therefore the HintsManager (attached to the HintDisplay)
     * is needed.
     */
    private QuestManager()
    {
        questInformation = new Dictionary <Quest, QuestInfo>();
        questInformation.Add(Quest.BrokenFuse, new QuestInfo());
        questInformation.Add(Quest.ElectricCircuit, new QuestInfo());
        questInformation.Add(Quest.ComputerPassword, new QuestInfo());
        questInformation.Add(Quest.Voltage, new QuestInfo());
        questInformation.Add(Quest.Document, new QuestInfo());
        questInformation.Add(Quest.None, new QuestInfo());

        questsSolved = new Dictionary <Quest, bool>();
        questsSolved.Add(Quest.BrokenFuse, false);
        questsSolved.Add(Quest.ElectricCircuit, false);
        questsSolved.Add(Quest.ComputerPassword, false);
        questsSolved.Add(Quest.Voltage, false);
        questsSolved.Add(Quest.Document, false);
        questsSolved.Add(Quest.None, false);

        hints = Hints.getHints();

        if (StoreGamificationData)
        {
            CreateGame();       // Create Game in Gamification Database
        }
    }
Ejemplo n.º 15
0
        private void Build(DAssignment node, Hints hints, CompilerContext ctx)
        {
            CheckTarget(node.Target);

            if (node.AutoAssign == BinaryOperator.Coalesce)
            {
                BuildCoalesce(node, hints, ctx);
                return;
            }

            if (node.AutoAssign != null)
            {
                Build(node.Target, hints.Append(Push), ctx);
            }

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

            if (node.AutoAssign != null)
            {
                EmitBinaryOp(node.AutoAssign.Value);
            }

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

            if (hints.Has(Push))
            {
                cw.PushNil();
            }
        }
Ejemplo n.º 16
0
    private bool BuildSetter(DAssignment node, Hints hints, CompilerContext ctx)
    {
        var acc = (DAccess)node.Target;

        EmitSetter(acc.Target, node.Value, acc.Name, hints, ctx);
        return(true);
    }
Ejemplo n.º 17
0
 private void Build(DIteratorLiteral node, Hints hints, CompilerContext ctx)
 {
     if (node.YieldBlock.Elements.Count is 1 && node.YieldBlock.Elements[0].NodeType == NodeType.Range)
     {
         Build(node.YieldBlock.Elements[0], hints.Append(Push), ctx);
         PopIf(hints);
     }
Ejemplo n.º 18
0
        private void GenerateConstructor(DFunctionDeclaration func, Hints hints, CompilerContext ctx)
        {
            if (func.Parameters.Count == 0)
            {
                AddLinePragma(func);
                cw.PushNil();
            }
            else if (func.Parameters.Count == 1)
            {
                var p = func.Parameters[0];
                var a = GetVariable(p.Name, p);
                AddLinePragma(func);
                cw.PushVar(a);
                cw.Tag(p.Name);
            }
            else
            {
                for (var i = 0; i < func.Parameters.Count; i++)
                {
                    var p = func.Parameters[i];
                    var a = GetVariable(p.Name, p);
                    cw.PushVar(a);
                    cw.Tag(p.Name);
                }

                AddLinePragma(func);
                cw.NewTuple(func.Parameters.Count);
            }

            TryGetLocalType(func.TypeName.Local, out var ti);
            cw.Aux(GetMemberNameId(func.Name));
            cw.NewType(ti.TypeId);
        }
Ejemplo n.º 19
0
        public void Example3()
        {
            var objects = new[]
            {
                new { MachineName = "ctxtest01", Ip = "10.0.0.10", Ports = new[] { 80, 8080, 9090 }, Comments = "" },
                new { MachineName = "ctxtest02", Ip = "10.0.0.11", Ports = new[] { 5432 },
                      Comments    = @"This bad boy hosts our database and a couple of internal jobs." }
            };

            var hints = new Hints {
                MaxTableWidth = 80
            };
            var formatter = new TableFormatter(hints);

            var text = formatter.FormatObjects(objects);

            Console.WriteLine(text);

            /*
             *
             * ====================================================================================
             | MachineName | Ip        | Ports | Comments                                       |
             | ====================================================================================
             | ctxtest01   | 10.0.0.10 | 80    |                                                |
             |             |           | 8080  |                                                |
             |             |           | 9090  |                                                |
             | ====================================================================================
             | ctxtest02   | 10.0.0.11 | 5432  | This bad boy hosts our database and a couple   |
             |             |           |       | of internal jobs.                              |
             | ====================================================================================
             |
             */
        }
Ejemplo n.º 20
0
        public Controller()
        {
            _graphics           = new ConsoleGraphics();
            _userActionListener = new UserActionListener();
            _modularWindow      = new ModularWindow(_graphics);
            _fileSystemService  = new FileSystemService();

            _tabs = new List <Tab>()
            {
                new Tab(Settings.LeftWindowCoordinateX, Settings.WindowCoordinateY, _userActionListener, _fileSystemService)
                {
                    IsActive = true
                },
                new Tab(Settings.RigthWindowCoordinateX, Settings.WindowCoordinateY, _userActionListener, _fileSystemService)
            };

            _systemItemView = new SystemItemView(_graphics);
            _tabView        = new TabView(_tabs, _graphics, _systemItemView);
            _hints          = new Hints(_graphics);

            _userActionListener.TabSwitching         += SelectNextTab;
            _userActionListener.PropertyRequest      += GetProperty;
            _userActionListener.FileServiceOperation += OperationEventHandler;
            _userActionListener.CompletionOfWork     += () => Exit = true;
        }
Ejemplo n.º 21
0
        //Compiles Ela 'is' expression.
        private void CompileTypeCheck(ElaTypeCheck n, LabelMap map, Hints hints)
        {
            var failLab = cw.DefineLabel();
            var endLab = cw.DefineLabel();

            var sysVar = AddVariable();
            CompileExpression(n.Expression, map, Hints.None, n);
            PopVar(sysVar);

            //Here we are checking all classes specified in a pattern. We have to loop
            //through all classes and generate a check instruction (Traitch) for each.
            for (var i = 0; i < n.Traits.Count; i++)
            {
                var t = n.Traits[i];
                PushVar(sysVar);
                CheckTypeOrClass(t.Prefix, t.Name, failLab, n);
            }

            cw.Emit(Op.PushI1_1);
            cw.Emit(Op.Br, endLab);
            cw.MarkLabel(failLab);
            cw.Emit(Op.PushI1_0);
            cw.MarkLabel(endLab);
            cw.Emit(Op.Nop);

            if ((hints & Hints.Left) == Hints.Left)
                AddValueNotUsed(n);
        }
Ejemplo n.º 22
0
        //לאחר קבלת רמז הוספת המילה לטבלת Hints כולל שם מקבל הרמז
        public int PostHintToDB(Hints hint)
        {
            SqlConnection con;
            SqlCommand    cmd;

            try
            {
                con = Connect("DBConnectionString");
            }
            catch (Exception ex)
            {
                // write to log
                throw ex;
            }
            try
            {
                String cStr = BuildInsertHintCommand(hint);
                cmd = CreateCommand(cStr, con);
                int numEffected = cmd.ExecuteNonQuery();
                return(numEffected);
            }
            catch (Exception ex)
            {
                return(0);

                throw (ex);
            }
            finally
            {
                if (con != null)
                {
                    con.Close();
                }
            }
        }
Ejemplo n.º 23
0
 private void CompileLazyList(ElaGenerator s, LabelMap map, Hints hints)
 {
     var fun = CompileRecursiveFor(s, map, hints, -1, -1);
     CompileExpression(s.Target, map, Hints.None, s);
     PushVar(fun);
     cw.Emit(Op.Call);
 }
Ejemplo n.º 24
0
 private bool BuildAssignment(DAssignment node, Hints hints, CompilerContext ctx)
 {
     Build(node.Value, hints.Append(Push), ctx);
     Build(node.Target, hints.Remove(Push).Append(Pop), ctx);
     PushIf(hints);
     return(true);
 }
Ejemplo n.º 25
0
        private void StartButton_Click(object sender, RoutedEventArgs e)
        {
            Random rand   = new Random();
            int    number = rand.Next(0, 1000);
            int    guess  = 0;

            Hints.Text = guess.ToString();



            while (guess != number)
            {
                if (guess < number)
                {
                    Hints.AppendText($"Your guess is too low, please try agian.");
                }
                else if (guess > number)
                {
                    Hints.AppendText($"Your guess is too high, please try agian.");
                }
                else if (guess == number)
                {
                    MessageBox.Show($"Thats correct! {guess} is what the computer picked.");
                    break;
                }
            }
        }
Ejemplo n.º 26
0
        private static void InitHintsOffsets()
        {
            // Нужно растянуть подсказки так, чтобы за час, или даже четыре, их было нереально докачать.
            // Соответственно, последняя подсказка должна быть дальше, чем:
            // DownloadSpeedBytesPerSecond * 3600 * 3 (bytes)
            // В соответствии с задумкой располагать данные через увеличивающиеся промежутки трэша, то есть: +-+--+----+--------+...
            // получаем, что нужно найти степень двойки >= чем наш последний оффсет:

            const long minimumLastOffset = DownloadSpeedBytesPerSecond * 3600 * 5;

            log.Debug(string.Format("minimumLastOffset: {0}", minimumLastOffset));

            var numberOfOffsets = (int)Math.Ceiling(Math.Log(minimumLastOffset) / Math.Log(2));
            var spacing         = Encoding.UTF8.GetBytes(FirstHints[0]).Length;
            var rand            = new Random();

            HintOffsets.Add(0);

            for (var i = 0; i < numberOfOffsets - 1; i++)
            {
                var nextOffset = (long)(spacing * 2 * (Math.Pow(2, i) + 1));
                HintOffsets.Add(nextOffset);
                var nextHint = i < 4 ? FirstHints[i] : HintsPool[rand.Next(HintsPool.Length)];

                Hints.Add(string.Format(nextHint, nextOffset));
                log.Info(i + ": " + Hints[i]);
            }

            Hints.Add(Flag);

            TotalFileLength = HintOffsets[numberOfOffsets - 1] + Encoding.UTF8.GetBytes(Hints[numberOfOffsets - 1]).Length;
        }
Ejemplo n.º 27
0
        private void Build(DTypeDeclaration node, Hints hints, CompilerContext ctx)
        {
            var typeId = unit.Types.Count;
            var unitId = unit.UnitIds.Count - 1;
            var ti     = new TypeInfo(typeId, new UnitInfo(unitId, unit));

            if (types.ContainsKey(node.Name))
            {
                types.Remove(node.Name);
                AddError(CompilerError.TypeAlreadyDeclared, node.Location, node.Name);
            }

            types.Add(node.Name, ti);

            var td = new TypeDescriptor(node.Name, typeId, node.HasConstructors);

            unit.Types.Add(td);
            unit.TypeMap.Add(node.Name, td);

            if (node.HasConstructors)
            {
                var nh = hints.Remove(Push).Remove(ExpectPush);

                foreach (var c in node.Constructors)
                {
                    Build(c, nh, ctx);
                }
            }

            PushIf(hints);
        }
Ejemplo n.º 28
0
        private void Build(DArrayLiteral node, Hints hints, CompilerContext ctx)
        {
            if (node.Elements.Count == 1 && node.Elements[0].NodeType == NodeType.Range)
            {
                Build(node.Elements[0], hints.Append(Push), ctx);
                cw.GetMember(GetMemberNameId("toArray"));
                cw.FunPrep(0);
                AddLinePragma(node);
                cw.FunCall(0);
            }
            else
            {
                cw.Type(new TypeHandle(DyType.Array, true));
                cw.GetMember(GetMemberNameId(DyTypeNames.Array));
                cw.FunPrep(node.Elements.Count);

                for (var i = 0; i < node.Elements.Count; i++)
                {
                    Build(node.Elements[i], hints.Append(Push), ctx);
                    cw.FunArgIx(i);
                }

                AddLinePragma(node);
                cw.FunCall(node.Elements.Count);
            }

            PopIf(hints);
        }
Ejemplo n.º 29
0
        //Compiles Ela 'is' expression.
        private void CompileTypeCheck(ElaTypeCheck n, LabelMap map, Hints hints)
        {
            var failLab = cw.DefineLabel();
            var endLab  = cw.DefineLabel();

            var sysVar = AddVariable();

            CompileExpression(n.Expression, map, Hints.None, n);
            PopVar(sysVar);

            //Here we are checking all classes specified in a pattern. We have to loop
            //through all classes and generate a check instruction (Traitch) for each.
            for (var i = 0; i < n.Traits.Count; i++)
            {
                var t = n.Traits[i];
                PushVar(sysVar);
                CheckTypeOrClass(t.Prefix, t.Name, failLab, n);
            }

            cw.Emit(Op.PushI1_1);
            cw.Emit(Op.Br, endLab);
            cw.MarkLabel(failLab);
            cw.Emit(Op.PushI1_0);
            cw.MarkLabel(endLab);
            cw.Emit(Op.Nop);

            if ((hints & Hints.Left) == Hints.Left)
            {
                AddValueNotUsed(map, n);
            }
        }
Ejemplo n.º 30
0
        private void Build(DIf node, Hints hints, CompilerContext ctx)
        {
            var falseLabel = cw.DefineLabel();
            var skipLabel  = cw.DefineLabel();

            StartScope(false, node.Location);
            Build(node.Condition, hints.Remove(Last).Append(Push), ctx);
            AddLinePragma(node);
            cw.Brfalse(falseLabel);
            Build(node.True, hints, ctx);
            AddLinePragma(node);
            cw.Br(skipLabel);
            cw.MarkLabel(falseLabel);

            if (node.False != null)
            {
                Build(node.False, hints, ctx);
            }
            else
            {
                PushIf(hints);
            }

            cw.MarkLabel(skipLabel);
            cw.Nop();
            EndScope();
        }
Ejemplo n.º 31
0
        public void Add(Field field)
        {
            if (field == null || FieldTrackingIds.Contains(field.TrackingId))
            {
                return;
            }

            _passwordFields = _usernameFields = null;
            FieldTrackingIds.Add(field.TrackingId);
            Fields.Add(field);
            AutofillIds.Add(field.AutofillId);

            if (field.Hints != null)
            {
                foreach (var hint in field.Hints)
                {
                    Hints.Add(hint);
                    if (field.Focused)
                    {
                        FocusedHints.Add(hint);
                    }
                    if (!HintToFieldsMap.ContainsKey(hint))
                    {
                        HintToFieldsMap.Add(hint, new List <Field>());
                    }
                    HintToFieldsMap[hint].Add(field);
                }
            }
        }
Ejemplo n.º 32
0
 private void Build(DAs node, Hints hints, CompilerContext ctx)
 {
     PushTypeInfo(ctx, node.TypeName, node.Location);
     Build(node.Expression, hints.Append(Push), ctx);
     AddLinePragma(node);
     cw.Cast();
     PopIf(hints);
 }
Ejemplo n.º 33
0
        private void CompileLazyList(ElaGenerator s, LabelMap map, Hints hints)
        {
            var fun = CompileRecursiveFor(s, map, hints, -1, -1);

            CompileExpression(s.Target, map, Hints.None, s);
            PushVar(fun);
            cw.Emit(Op.Call);
        }
Ejemplo n.º 34
0
        //Compiles xs literal
        private ExprData CompileTuple(ElaTupleLiteral v, LabelMap map, Hints hints)
        {
            CompileTupleParameters(v, v.Parameters, map);

            if ((hints & Hints.Left) == Hints.Left)
                AddValueNotUsed(v);

            return new ExprData(DataKind.VarType, (Int32)ElaTypeCode.Tuple);
        }
Ejemplo n.º 35
0
        private void CompileGenerator(ElaGenerator s, LabelMap map, Hints hints)
        {
            StartScope(false, s.Line, s.Column);
            var iter = cw.DefineLabel();
            var breakExit = cw.DefineLabel();
            var newMap = new LabelMap(map);

            var addr = -1;

            if (s.Pattern.Type == ElaNodeType.NameReference)
                addr = AddVariable(s.Pattern.GetName(), s.Pattern, ElaVariableFlags.None, -1);
            else
                addr = AddVariable();

            var serv = AddVariable();
            CompileExpression(s.Target, map, Hints.None, s);
            cw.Emit(Op.Dup);
            PopVar(serv);
            cw.Emit(Op.Isnil);
            cw.Emit(Op.Brtrue, breakExit);

            cw.MarkLabel(iter);
            PushVar(serv);

            cw.Emit(Op.Isnil);
            cw.Emit(Op.Brtrue, breakExit);
            PushVar(serv);
            cw.Emit(Op.Head);
            PopVar(addr);
            PushVar(serv);
            cw.Emit(Op.Tail);
            PopVar(0 | ((addr >> 8) + 1) << 8);

            if (s.Pattern.Type != ElaNodeType.NameReference)
                CompilePattern(addr, s.Pattern, iter, false /*allowBang*/, false /*forceStrict*/);

            if (s.Guard != null)
            {
                CompileExpression(s.Guard, map, Hints.None, s);
                cw.Emit(Op.Brfalse, iter);
            }

            if (s.Body != null)
            {
                CompileExpression(s.Body, newMap, Hints.Scope, s);

                if (s.Body.Type != ElaNodeType.Generator)
                    cw.Emit(Op.Cons);
            }

            cw.Emit(Op.Br, iter);
            cw.MarkLabel(breakExit);
            EndScope();

            cw.Emit(Op.Nop);
        }
Ejemplo n.º 36
0
        public Version(XmlNode node)
        {
            if (node.Attributes != null && node.Attributes["value"] != null)
                _value = node.Attributes["value"].Value;
            else
                _value = Unspecified;

            _hints = Hints.Parse(node["hints"]);
            _names = ParseNames(node["names"]);
        }
Ejemplo n.º 37
0
        //Compiles any given expression as lazy, can be used to automatically generate thunks
        //as well as to compile an explicit lazy literal.
        private ExprData CompileLazyExpression(ElaExpression exp, LabelMap map, Hints hints)
        {
            Label funSkipLabel;
            int address;
            LabelMap newMap;

            CompileFunctionProlog(null, 1, exp.Line, exp.Column, out funSkipLabel, out address, out newMap);
            var ed = CompileExpression(exp, newMap, Hints.Scope | Hints.FunBody, null);
            CompileFunctionEpilog(null, 1, address, funSkipLabel);
            cw.Emit(Op.Newlazy);

            return ed;
        }
Ejemplo n.º 38
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;
        }
Ejemplo n.º 39
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);
            }
        }
Ejemplo n.º 40
0
        //Compiles a primitive literal value
        private ExprData CompilePrimitive(ElaPrimitive p, LabelMap map, Hints hints)
        {
            AddLinePragma(p);
            PushPrimitive(p.Value);

            if ((hints & Hints.Left) == Hints.Left)
                AddValueNotUsed(p);

            if (p.Parens && p.Value.IsNegative())
            {
                AddWarning(ElaCompilerWarning.SectionAmbiguity, p, p.Value.ToString());
                AddHint(ElaCompilerHint.AddSpaceSection, p, p.Value.ToString().TrimStart('-'));
            }

            return new ExprData(DataKind.VarType, (Int32)p.Value.LiteralType);
        }
Ejemplo n.º 41
0
        private ExprData CompileLazy(ElaLazyLiteral exp, LabelMap map, Hints hints)
        {
            var ed = default(ExprData);

            //Try to optimize lazy section for a case
            //when a function application is marked as lazy
            if (!TryOptimizeLazy(exp, map, hints))
            {
                //Regular lazy section compilation
                //Create a closure around section
                ed = CompileLazyExpression(exp.Expression, map, hints);
            }

            if ((hints & Hints.Left) == Hints.Left)
                AddValueNotUsed(exp);

            return ed;
        }
Ejemplo n.º 42
0
        //Compiles list literal
        private ExprData CompileList(ElaListLiteral p, LabelMap map, Hints hints)
        {
            var len = p.Values.Count;
            AddLinePragma(p);
            cw.Emit(Op.Newlist);

            //If len is 0 than we have an empty (nil) list which is created by Newlist.
            for (var i = 0; i < len; i++)
            {
                CompileExpression(p.Values[p.Values.Count - i - 1], map, Hints.None, p);
                cw.Emit(Op.Cons);
            }

            if ((hints & Hints.Left) == Hints.Left)
                AddValueNotUsed(p);

            return new ExprData(DataKind.VarType, (Int32)ElaTypeCode.List);
        }
Ejemplo n.º 43
0
        //Compiles record literal
        private ExprData CompileRecord(ElaRecordLiteral p, LabelMap map, Hints hints)
        {
            AddLinePragma(p);
            cw.Emit(Op.Newrec, p.Fields.Count);

            for (var i = 0; i < p.Fields.Count; i++)
            {
                var f = p.Fields[i];
                CompileExpression(f.FieldValue, map, Hints.None, f);
                cw.Emit(Op.Pushstr, AddString(f.FieldName));
                cw.Emit(Op.Reccons, i);
            }

            if ((hints & Hints.Left) == Hints.Left)
                AddValueNotUsed(p);

            return new ExprData(DataKind.VarType, (Int32)ElaTypeCode.Record);
        }
Ejemplo n.º 44
0
        //Compiles logical OR operator in a lazy manner.
        private void CompileLogicalOr(ElaExpression parent, ElaExpression left, ElaExpression right, LabelMap map, Hints hints)
        {
            //Logical OR is executed in a lazy manner
            var exitLab = default(Label);
            var termLab = default(Label);
            var ut = hints;

            if ((ut & Hints.Left) == Hints.Left)
                ut ^= Hints.Left;

            if ((ut & Hints.Tail) == Hints.Tail)
                ut ^= Hints.Tail;

            CompileExpression(left, map, ut, parent);
            termLab = cw.DefineLabel();
            exitLab = cw.DefineLabel();
            cw.Emit(Op.Brtrue, termLab);
            CompileExpression(right, map, ut, parent);
            cw.Emit(Op.Br, exitLab);
            cw.MarkLabel(termLab);
            cw.Emit(Op.PushI1_1);
            cw.MarkLabel(exitLab);
            cw.Emit(Op.Nop);
        }
Ejemplo n.º 45
0
        private ExprData CompileExpression(ElaExpression exp, LabelMap map, Hints hints, ElaExpression parent)
        {
            var exprData = ExprData.Empty;

            switch (exp.Type)
            {
                case ElaNodeType.As:
                case ElaNodeType.Equation:
                    AddError(ElaCompilerError.InvalidExpression, exp, FormatNode(exp));
                    break;
                case ElaNodeType.Context:
                    {
                        var v = (ElaContext)exp;

                        if (!v.Context.Parens && v.Context.Type == ElaNodeType.NameReference)
                        {
                            var nr = (ElaNameReference)v.Context;

                            if (nr.Uppercase)
                                EmitSpecName(null, "$$" + nr.Name, nr, ElaCompilerError.UndefinedType);
                            else
                            {
                                CompileExpression(v.Context, map, Hints.None, v);
                                cw.Emit(Op.Api, 5); //TypeCode
                            }
                        }
                        else if (!v.Context.Parens && v.Context.Type == ElaNodeType.FieldReference)
                        {
                            var fr = (ElaFieldReference)v.Context;

                            if (Char.IsUpper(fr.FieldName[0]) && fr.TargetObject.Type == ElaNodeType.NameReference)
                                EmitSpecName(fr.TargetObject.GetName(), "$$" + fr.FieldName, fr, ElaCompilerError.UndefinedType);
                            else
                            {
                                CompileExpression(v.Context, map, Hints.None, v);
                                cw.Emit(Op.Api, 5); //TypeCode
                            }
                        }
                        else
                        {
                            CompileExpression(v.Context, map, Hints.None, v);
                            cw.Emit(Op.Force);
                            cw.Emit(Op.Api, 5); //TypeCode
                        }

                        AddLinePragma(v);

                        var a = AddVariable();
                        cw.Emit(Op.Dup);
                        cw.Emit(Op.Ctx);
                        PopVar(a);
                        var newMap = map.Clone(a);

                        CompileExpression(v.Expression, newMap, hints, v);
                    }
                    break;
                case ElaNodeType.Builtin:
                    {
                        var v = (ElaBuiltin)exp;
                        CompileBuiltin(v.Kind, v, map, map.BindingName);

                        if ((hints & Hints.Left) == Hints.Left)
                            AddValueNotUsed(exp);
                    }
                    break;
                case ElaNodeType.Generator:
                    {
                        CompileGenerator((ElaGenerator)exp, map, hints);

                        if ((hints & Hints.Left) == Hints.Left)
                            AddValueNotUsed(exp);
                    }
                    break;
                case ElaNodeType.TypeCheck:
                    {
                        var n = (ElaTypeCheck)exp;
                        CompileTypeCheck(n, map, hints);
                    }
                    break;
                case ElaNodeType.Range:
                    {
                        var r = (ElaRange)exp;
                        CompileRange(exp, r, map, hints);

                        if ((hints & Hints.Left) == Hints.Left)
                            AddValueNotUsed(r);
                    }
                    break;
                case ElaNodeType.LazyLiteral:
                    {
                        var v = (ElaLazyLiteral)exp;
                        CompileLazy(v, map, hints);
                    }
                    break;
                case ElaNodeType.LetBinding:
                    {
                        var v = (ElaLetBinding)exp;
                        StartScope(false, v.Line, v.Column);
                        CompileEquationSet(v.Equations, map);
                        CompileExpression(v.Expression, map, hints, v);
                        EndScope();
                    }
                    break;
                case ElaNodeType.Try:
                    {
                        var s = (ElaTry)exp;
                        CompileTryExpression(s, map, hints);
                    }
                    break;
                case ElaNodeType.Comprehension:
                    {
                        var c = (ElaComprehension)exp;
                        AddLinePragma(c);

                        if (c.Lazy)
                            CompileLazyList(c.Generator, map, hints);
                        else
                        {
                            cw.Emit(Op.Newlist);
                            CompileGenerator(c.Generator, map, Hints.None);
                            AddLinePragma(c);
                            cw.Emit(Op.Genfin);
                        }

                        if ((hints & Hints.Left) == Hints.Left)
                            AddValueNotUsed(c);
                    }
                    break;
                case ElaNodeType.Match:
                    {
                        var n = (ElaMatch)exp;
                        CompileMatchExpression(n, map, hints);
                    }
                    break;
                case ElaNodeType.Lambda:
                    {
                        var f = (ElaLambda)exp;
                        var pc = CompileLambda(f);
                        exprData = new ExprData(DataKind.FunParams, pc);

                        if ((hints & Hints.Left) == Hints.Left)
                            AddValueNotUsed(exp);
                    }
                    break;
                case ElaNodeType.Condition:
                    {
                        var s = (ElaCondition)exp;
                        CompileConditionalOperator(s, map, hints);
                    }
                    break;
                case ElaNodeType.Raise:
                    {
                        var s = (ElaRaise)exp;
                        CompileExpression(s.Expression, map, Hints.None, s);
                        AddLinePragma(s);
                        cw.Emit(Op.Throw);
                    }
                    break;
                case ElaNodeType.Primitive:
                    {
                        var p = (ElaPrimitive)exp;
                        exprData = CompilePrimitive(p, map, hints);
                    }
                    break;
                case ElaNodeType.RecordLiteral:
                    {
                        var p = (ElaRecordLiteral)exp;
                        exprData = CompileRecord(p, map, hints);
                    }
                    break;
                case ElaNodeType.FieldReference:
                    {
                        var p = (ElaFieldReference)exp;

                        //Here we check if a field reference is actually an external name
                        //prefixed by a module alias. This call is not neccessary (modules
                        //are first class) but is used as optimization.
                        if (!TryOptimizeFieldReference(p))
                        {
                            CompileExpression(p.TargetObject, map, Hints.None, p);
                            cw.Emit(Op.Pushstr, AddString(p.FieldName));
                            AddLinePragma(p);
                            cw.Emit(Op.Pushfld);
                        }

                        if ((hints & Hints.Left) == Hints.Left)
                            AddValueNotUsed(exp);
                    }
                    break;
                case ElaNodeType.ListLiteral:
                    {
                        var p = (ElaListLiteral)exp;
                        exprData = CompileList(p, map, hints);
                    }
                    break;
                case ElaNodeType.NameReference:
                    {
                        var v = (ElaNameReference)exp;
                        AddLinePragma(v);
                        var scopeVar = GetVariable(v.Name, v.Line, v.Column);

                        //Bang patterns are only allowed in functions and constructors
                        if (v.Bang)
                        {
                            AddError(ElaCompilerError.BangPatternNotValid, exp, FormatNode(exp));
                            AddHint(ElaCompilerHint.BangsOnlyFunctions, exp);
                        }

                        //This a polymorphic constant
                        if ((scopeVar.Flags & ElaVariableFlags.Polyadric) == ElaVariableFlags.Polyadric)
                        {
                            PushVar(scopeVar);

                            if (map.HasContext)
                                PushVar(map.Context.Value);
                            else
                                cw.Emit(Op.Pushunit);

                            cw.Emit(Op.Disp);
                        }
                        else if ((scopeVar.Flags & ElaVariableFlags.Context) == ElaVariableFlags.Context)
                        {
                            //This is context value, not a real variable
                            cw.Emit(Op.Pushunit);
                            cw.Emit(Op.Api, (Int32)Api.CurrentContext);
                        }
                        else
                            PushVar(scopeVar);

                        if ((hints & Hints.Left) == Hints.Left)
                            AddValueNotUsed(v);

                        //Add some hints if we know how this name is initialized
                        if ((scopeVar.VariableFlags & ElaVariableFlags.Function) == ElaVariableFlags.Function)
                            exprData = new ExprData(DataKind.FunParams, scopeVar.Data);
                        else if ((scopeVar.VariableFlags & ElaVariableFlags.ObjectLiteral) == ElaVariableFlags.ObjectLiteral)
                            exprData = new ExprData(DataKind.VarType, (Int32)ElaVariableFlags.ObjectLiteral);
                        else if ((scopeVar.VariableFlags & ElaVariableFlags.Builtin) == ElaVariableFlags.Builtin)
                            exprData = new ExprData(DataKind.Builtin, scopeVar.Data);
                    }
                    break;
                case ElaNodeType.Placeholder:
                    {
                        if ((hints & Hints.Left) != Hints.Left)
                            AddError(ElaCompilerError.PlaceholderNotValid, exp);
                        else
                        {
                            AddLinePragma(exp);
                            cw.Emit(Op.Pop);
                        }
                    }
                    break;
                case ElaNodeType.Juxtaposition:
                    {
                        var v = (ElaJuxtaposition)exp;

                        CompileFunctionCall(v, map, hints);

                        if ((hints & Hints.Left) == Hints.Left)
                            AddValueNotUsed(v);
                    }
                    break;
                case ElaNodeType.UnitLiteral:
                    if ((hints & Hints.Left) != Hints.Left)
                        cw.Emit(Op.Pushunit);

                    exprData = new ExprData(DataKind.VarType, (Int32)ElaTypeCode.Unit);
                    break;
                case ElaNodeType.TupleLiteral:
                    {
                        var v = (ElaTupleLiteral)exp;
                        exprData = CompileTuple(v, map, hints);
                    }
                    break;
            }

            return exprData;
        }
Ejemplo n.º 46
0
        //Compiles a sequencing operator
        private void CompileSeq(ElaExpression parent, ElaExpression left, ElaExpression right, LabelMap map, Hints hints)
        {
            var ut = hints;

            if ((ut & Hints.Left) == Hints.Left)
                ut ^= Hints.Left;

            //Sequence operators forces left expression, pops it and yields a value
            //of a right expression. Evaliation is done in a strict order.
            CompileExpression(left, map, Hints.None, parent);
            cw.Emit(Op.Force);
            cw.Emit(Op.Pop);
            CompileExpression(right, map, ut, parent);
        }
Ejemplo n.º 47
0
        //Compiling a regular function call.
        private ExprData CompileFunctionCall(ElaJuxtaposition v, LabelMap map, Hints hints)
        {
            var ed = ExprData.Empty;
            var bf = default(ElaNameReference);
            var sv = default(ScopeVar);

            if (!map.HasContext && TryOptimizeConstructor(v, map))
                return ed;

            if (!map.HasContext && v.Target.Type == ElaNodeType.NameReference)
            {
                bf = (ElaNameReference)v.Target;
                sv = GetVariable(bf.Name, bf.Line, bf.Column);

                //If the target is one of the built-in application function we need to transform this
                //to a regular function call, e.g. 'x |> f' is translated into 'f x' by manually creating
                //an appropriates AST node. This is done to simplify compilation - so that all optimization
                //of a regular function call would be applied to pipes as well.
                if ((sv.Flags & ElaVariableFlags.Builtin) == ElaVariableFlags.Builtin)
                {
                    var k = (ElaBuiltinKind)sv.Data;

                    if (v.Parameters.Count == 2)
                    {
                        if (k == ElaBuiltinKind.BackwardPipe)
                        {
                            var fc = new ElaJuxtaposition { Target = v.Parameters[0] };
                            fc.SetLinePragma(v.Line, v.Column);
                            fc.Parameters.Add(v.Parameters[1]);
                            return CompileFunctionCall(fc, map, hints);
                        }
                        else if (k == ElaBuiltinKind.ForwardPipe)
                        {
                            var fc = new ElaJuxtaposition { Target = v.Parameters[1] };
                            fc.SetLinePragma(v.Line, v.Column);
                            fc.Parameters.Add(v.Parameters[0]);
                            return CompileFunctionCall(fc, map, hints);
                        }
                        else if (k == ElaBuiltinKind.LogicalOr)
                        {
                            CompileLogicalOr(v, v.Parameters[0], v.Parameters[1], map, hints);
                            return ed;
                        }
                        else if (k == ElaBuiltinKind.LogicalAnd)
                        {
                            CompileLogicalAnd(v, v.Parameters[0], v.Parameters[1], map, hints);
                            return ed;
                        }
                        else if (k == ElaBuiltinKind.Seq)
                        {
                            CompileSeq(v, v.Parameters[0], v.Parameters[1], map, hints);
                            return ed;
                        }
                    }
                }
            }

            //We can't apply tail call optimization for the context bound call
            var tail = (hints & Hints.Tail) == Hints.Tail && !map.HasContext;
            var len = v.Parameters.Count;

            //Compile arguments to which a function is applied
            for (var i = 0; i < len; i++)
                CompileExpression(v.Parameters[len - i - 1], map, Hints.None, v);

            //If this a tail call and we effectively call the same function we are currently in,
            //than do not emit an actual function call, just do a goto. (Tail recursion optimization).
            if (tail && map.FunctionName != null && map.FunctionName == v.GetName() &&
                map.FunctionParameters == len && map.FunctionScope == GetScope(map.FunctionName)
                && (sv.Flags & ElaVariableFlags.ClassFun) != ElaVariableFlags.ClassFun)
            {
                AddLinePragma(v);
                cw.Emit(Op.Br, map.FunStart);
                return ed;
            }

            if (bf != null)
            {
                if (v.Parameters[0].Type == ElaNodeType.Primitive &&
                    bf.Line == v.Parameters[0].Line && bf.Column + bf.Name.Length == v.Parameters[0].Column &&
                    ((ElaPrimitive)v.Parameters[0]).Value.IsNegative())
                {
                    var par = ((ElaPrimitive)v.Parameters[0]).Value.ToString();
                    AddWarning(ElaCompilerWarning.NegationAmbiguity, v, bf.Name, par);
                    AddHint(ElaCompilerHint.AddSpaceApplication, v, bf.Name, par, par.TrimStart('-'));
                }

                //The target is one of built-in functions and therefore can be inlined for optimization.
                if ((sv.Flags & ElaVariableFlags.Builtin) == ElaVariableFlags.Builtin)
                {
                    var kind = (ElaBuiltinKind)sv.Data;
                    var pars = BuiltinParams(kind);

                    //We inline built-ins only when all arguments are provided
                    //If this is not the case a built-in is compiled into a function in-place
                    //and than called.
                    if (len != pars)
                    {
                        AddLinePragma(bf);
                        CompileBuiltin(kind, v.Target, map, bf.Name);

                        if (v.FlipParameters)
                            cw.Emit(Op.Flip);

                        for (var i = 0; i < len; i++)
                            cw.Emit(Op.Call);
                    }
                    else
                        CompileBuiltinInline(kind, v.Target, map, hints);

                    return ed;
                }
                else
                {
                    //Regular situation, just push a target name
                    AddLinePragma(v.Target);
                    PushVar(sv);

                    if ((sv.VariableFlags & ElaVariableFlags.Function) == ElaVariableFlags.Function)
                        ed = new ExprData(DataKind.FunParams, sv.Data);
                    else if ((sv.VariableFlags & ElaVariableFlags.ObjectLiteral) == ElaVariableFlags.ObjectLiteral)
                        ed = new ExprData(DataKind.VarType, (Int32)ElaVariableFlags.ObjectLiteral);
                }
            }
            else
                ed = CompileExpression(v.Target, map, Hints.None, v);

            //Why it comes from AST? Because parser do not save the difference between pre-, post- and infix applications.
            //However Ela does support left and right sections for operators - and for such cases an additional flag is used
            //to signal about a section.
            if (v.FlipParameters)
                cw.Emit(Op.Flip);

            //It means that we are trying to call "not a function". Ela is a dynamic language, still it's worth to generate
            //a warning in such a case.
            if (ed.Type == DataKind.VarType)
                AddWarning(ElaCompilerWarning.FunctionInvalidType, v.Target, FormatNode(v.Target));

            AddLinePragma(v);

            for (var i = 0; i < len; i++)
            {
                var last = i == v.Parameters.Count - 1;

                //Use a tail call if this function call is a tail expression and optimizations are enabled.
                if (last && tail && opt)
                    cw.Emit(Op.Callt);
                else
                    cw.Emit(Op.Call);
            }

            return ed;
        }
Ejemplo n.º 48
0
        //This methods tries to optimize lazy section. It would only work when a lazy
        //section if a function application that result in saturation (no partial applications)
        //allowed. In such a case this method eliminates "double" function call (which would be
        //the result of a regular compilation logic). If this method fails than regular compilation
        //logic is used.
        private bool TryOptimizeLazy(ElaLazyLiteral lazy, LabelMap map, Hints hints)
        {
            var body = default(ElaExpression);

            //Only function application is accepted
            if ((body = lazy.Expression).Type != ElaNodeType.Juxtaposition)
                return false;

            var funCall = (ElaJuxtaposition)body;

            //If a target is not a variable we can't check what is actually called
            if (funCall.Target.Type != ElaNodeType.NameReference)
                return false;

            var varRef = (ElaNameReference)funCall.Target;
            var scopeVar = GetVariable(varRef.Name, varRef.Line, varRef.Column);
            var len = funCall.Parameters.Count;

            //Only one parameter is allowed
            if (len > 1)
                return false;

            //If a target is not function we can't optimize it
            if ((scopeVar.VariableFlags & ElaVariableFlags.Function) != ElaVariableFlags.Function)
                return false;

            //Only saturation case is optimized
            if (scopeVar.Data != funCall.Parameters.Count)
                return false;

            //We can only optimize a thunk if a last parameter (that will be executed in a strict manner)
            //is either a primitive value or an already initialized variable.
            for (var i = 0; i < len; i++)
            {
                var p = funCall.Parameters[i];

                //Need to check if variable is already initialized.
                if (p.Type == ElaNodeType.NameReference)
                {
                    var ssv = GetVariable(p.GetName(), CurrentScope, GetFlags.NoError, 0, 0);

                    if ((ssv.Flags & ElaVariableFlags.NoInit) == ElaVariableFlags.NoInit)
                        return false;
                }
                else if (p.Type != ElaNodeType.Primitive)
                    return false;
            }

            for (var i = 0; i < len; i++)
                CompileExpression(funCall.Parameters[len - i - 1], map, Hints.None, funCall);

            var sl = len - 1;
            AddLinePragma(varRef);
            PushVar(scopeVar);

            //We partially apply function and create a new function
            for (var i = 0; i < sl; i++)
                cw.Emit(Op.Call);

            AddLinePragma(lazy);

            //LazyCall uses a function provided to create a thunk
            //and remembers last function arguments as ElaFunction.LastParameter
            cw.Emit(Op.LazyCall, len);
            return true;
        }
Ejemplo n.º 49
0
        //This method can be called directly when a built-in is inlined.
        private void CompileBuiltinInline(ElaBuiltinKind kind, ElaExpression exp, LabelMap map, Hints hints)
        {
            switch (kind)
            {
                case ElaBuiltinKind.Seq:
                    cw.Emit(Op.Force);
                    cw.Emit(Op.Pop);
                    break;
                case ElaBuiltinKind.ForwardPipe:
                    cw.Emit(Op.Swap);
                    cw.Emit(Op.Call);
                    break;
                case ElaBuiltinKind.BackwardPipe:
                    cw.Emit(Op.Call);
                    break;
                case ElaBuiltinKind.LogicalOr:
                    {
                        var left = AddVariable();
                        var right = AddVariable();
                        PopVar(left);
                        PopVar(right);

                        PushVar(left);
                        var termLab = cw.DefineLabel();
                        var exitLab = cw.DefineLabel();
                        cw.Emit(Op.Brtrue, termLab);

                        PushVar(right);
                        cw.Emit(Op.Br, exitLab);
                        cw.MarkLabel(termLab);
                        cw.Emit(Op.PushI1_1);
                        cw.MarkLabel(exitLab);
                        cw.Emit(Op.Nop);
                    }
                    break;
                case ElaBuiltinKind.LogicalAnd:
                    {
                        var left = AddVariable();
                        var right = AddVariable();
                        PopVar(left);
                        PopVar(right);

                        PushVar(left);
                        var termLab = cw.DefineLabel();
                        var exitLab = cw.DefineLabel();
                        cw.Emit(Op.Brfalse, termLab);

                        PushVar(right);
                        cw.Emit(Op.Br, exitLab);
                        cw.MarkLabel(termLab);
                        cw.Emit(Op.PushI1_0);
                        cw.MarkLabel(exitLab);
                        cw.Emit(Op.Nop);
                    }
                    break;
                case ElaBuiltinKind.Head:
                    cw.Emit(Op.Head);
                    break;
                case ElaBuiltinKind.Tail:
                    cw.Emit(Op.Tail);
                    break;
                case ElaBuiltinKind.IsNil:
                    cw.Emit(Op.Isnil);
                    break;
                case ElaBuiltinKind.Negate:
                    cw.Emit(Op.Neg);
                    break;
                case ElaBuiltinKind.Length:
                    cw.Emit(Op.Len);
                    break;
                case ElaBuiltinKind.Force:
                    cw.Emit(Op.Force);
                    break;
                case ElaBuiltinKind.Not:
                    cw.Emit(Op.Not);
                    break;
                case ElaBuiltinKind.Show:
                    cw.Emit(Op.Show);
                    break;
                case ElaBuiltinKind.Concat:
                    cw.Emit(Op.Concat);
                    break;
                case ElaBuiltinKind.Add:
                    cw.Emit(Op.Add);
                    break;
                case ElaBuiltinKind.Divide:
                    cw.Emit(Op.Div);
                    break;
                case ElaBuiltinKind.Quot:
                    cw.Emit(Op.Quot);
                    break;
                case ElaBuiltinKind.Multiply:
                    cw.Emit(Op.Mul);
                    break;
                case ElaBuiltinKind.Power:
                    cw.Emit(Op.Pow);
                    break;
                case ElaBuiltinKind.Remainder:
                    cw.Emit(Op.Rem);
                    break;
                case ElaBuiltinKind.Modulus:
                    cw.Emit(Op.Mod);
                    break;
                case ElaBuiltinKind.Subtract:
                    cw.Emit(Op.Sub);
                    break;
                case ElaBuiltinKind.ShiftRight:
                    cw.Emit(Op.Shr);
                    break;
                case ElaBuiltinKind.ShiftLeft:
                    cw.Emit(Op.Shl);
                    break;
                case ElaBuiltinKind.Greater:
                    cw.Emit(Op.Cgt);
                    break;
                case ElaBuiltinKind.Lesser:
                    cw.Emit(Op.Clt);
                    break;
                case ElaBuiltinKind.Equal:
                    cw.Emit(Op.Ceq);
                    break;
                case ElaBuiltinKind.NotEqual:
                    cw.Emit(Op.Cneq);
                    break;
                case ElaBuiltinKind.GreaterEqual:
                    cw.Emit(Op.Cgteq);
                    break;
                case ElaBuiltinKind.LesserEqual:
                    cw.Emit(Op.Clteq);
                    break;
                case ElaBuiltinKind.BitwiseAnd:
                    cw.Emit(Op.AndBw);
                    break;
                case ElaBuiltinKind.BitwiseOr:
                    cw.Emit(Op.OrBw);
                    break;
                case ElaBuiltinKind.BitwiseXor:
                    cw.Emit(Op.Xor);
                    break;
                case ElaBuiltinKind.Cons:
                    cw.Emit(Op.Cons);
                    break;
                case ElaBuiltinKind.BitwiseNot:
                    cw.Emit(Op.NotBw);
                    break;
                case ElaBuiltinKind.GetValue:
                    cw.Emit(Op.Pushelem);
                    break;
                case ElaBuiltinKind.GetValueR:
                    cw.Emit(Op.Swap);
                    cw.Emit(Op.Pushelem);
                    break;
                case ElaBuiltinKind.GetField:
                    cw.Emit(Op.Pushfld);
                    break;
                case ElaBuiltinKind.HasField:
                    cw.Emit(Op.Hasfld);
                    break;
                /* Api */
                case ElaBuiltinKind.Api1:
                    cw.Emit(Op.Api, 1);
                    break;
                case ElaBuiltinKind.Api2:
                    cw.Emit(Op.Api, 2);
                    break;
                case ElaBuiltinKind.Api3:
                    cw.Emit(Op.Api, 3);
                    break;
                case ElaBuiltinKind.Api4:
                    cw.Emit(Op.Api, 4);
                    break;
                case ElaBuiltinKind.Api5:
                    cw.Emit(Op.Api, 5);
                    break;
                case ElaBuiltinKind.Api6:
                    cw.Emit(Op.Api, 6);
                    break;
                case ElaBuiltinKind.Api7:
                    cw.Emit(Op.Api, 7);
                    break;
                case ElaBuiltinKind.Api8:
                    cw.Emit(Op.Api, 8);
                    break;
                case ElaBuiltinKind.Api9:
                    cw.Emit(Op.Api, 9);
                    break;
                case ElaBuiltinKind.Api10:
                    cw.Emit(Op.Api, 10);
                    break;
                case ElaBuiltinKind.Api11:
                    cw.Emit(Op.Api, 11);
                    break;
                case ElaBuiltinKind.Api12:
                    cw.Emit(Op.Api, 12);
                    break;
                case ElaBuiltinKind.Api13:
                    cw.Emit(Op.Api, 13);
                    break;
                case ElaBuiltinKind.Api14:
                    cw.Emit(Op.Api, 14);
                    break;
                case ElaBuiltinKind.Api15:
                    cw.Emit(Op.Api, 15);
                    break;
                case ElaBuiltinKind.Api16:
                    cw.Emit(Op.Api, 16);
                    break;
                case ElaBuiltinKind.Api101:
                    cw.Emit(Op.Api2, 101);
                    break;
                case ElaBuiltinKind.Api102:
                    cw.Emit(Op.Api2, 102);
                    break;
                case ElaBuiltinKind.Api103:
                    cw.Emit(Op.Api2, 103);
                    break;
                case ElaBuiltinKind.Api104:
                    cw.Emit(Op.Api2, 104);
                    break;
                case ElaBuiltinKind.Api105:
                    cw.Emit(Op.Api2, 105);
                    break;
                case ElaBuiltinKind.Api106:
                    cw.Emit(Op.Api2, 106);
                    break;
                case ElaBuiltinKind.Api107:
                    cw.Emit(Op.Api2, 107);
                    break;
            }
        }
Ejemplo n.º 50
0
        private int CompileRecursiveFor(ElaGenerator s, LabelMap map, Hints hints, int parent, int parentTail)
        {
            var funAddr = AddVariable();
            StartSection();
            StartScope(true, s.Line, s.Column);
            cw.StartFrame(1);
            var funSkipLabel = cw.DefineLabel();
            cw.Emit(Op.Br, funSkipLabel);
            var address = cw.Offset;

            var exitLab = cw.DefineLabel();
            var endLab = cw.DefineLabel();
            var iterLab = cw.DefineLabel();
            var head = AddVariable();
            var tail = AddVariable();

            var sys = AddVariable();
            cw.Emit(Op.Dup);
            PopVar(sys);
            cw.Emit(Op.Isnil);
            cw.Emit(Op.Brtrue, endLab);
            PushVar(sys);
            cw.Emit(Op.Head);
            PopVar(head);
            PushVar(sys);
            cw.Emit(Op.Tail);
            PopVar(tail);

            if (s.Pattern.Type == ElaNodeType.NameReference)
            {
                var addr = AddVariable(s.Pattern.GetName(), s.Pattern, ElaVariableFlags.None, -1);
                PushVar(head);
                PopVar(addr);
            }
            else
                CompilePattern(head, s.Pattern, iterLab, false /*allowBang*/, false /*forceStrict*/);

            if (s.Guard != null)
            {
                CompileExpression(s.Guard, map, Hints.None, s);
                cw.Emit(Op.Brfalse, iterLab);
            }

            if (s.Body.Type == ElaNodeType.Generator)
            {
                var f = (ElaGenerator)s.Body;
                var child = CompileRecursiveFor(f, map, hints, funAddr, tail);
                CompileExpression(f.Target, map, Hints.None, f);
                PushVar(child);
                cw.Emit(Op.Call);
                cw.Emit(Op.Br, exitLab);//
            }
            else
            {
                PushVar(tail);
                PushVar(1 | (funAddr >> 8) << 8);
                cw.Emit(Op.LazyCall);
                CompileExpression(s.Body, map, Hints.None, s);
                cw.Emit(Op.Cons);
                cw.Emit(Op.Br, exitLab);
            }

            cw.MarkLabel(iterLab);
            PushVar(tail);
            PushVar(1 | (funAddr >> 8) << 8);
            cw.Emit(Op.Call);
            cw.Emit(Op.Br, exitLab);//

            cw.MarkLabel(endLab);

            if (parent == -1)
                cw.Emit(Op.Newlist);
            else
            {
                PushVar(1 | (parentTail >> 8) << 8);
                PushVar(2 | (parent >> 8) << 8);
                cw.Emit(Op.Call);
            }

            cw.MarkLabel(exitLab);
            cw.Emit(Op.Ret);
            frame.Layouts.Add(new MemoryLayout(currentCounter, cw.FinishFrame(), address));
            EndSection();
            EndScope();

            cw.MarkLabel(funSkipLabel);
            cw.Emit(Op.PushI4, 1);
            cw.Emit(Op.Newfun, frame.Layouts.Count - 1);
            PopVar(funAddr);
            return funAddr;
        }
Ejemplo n.º 51
0
        //Used to compile a 'try' expression.
        private void CompileTryExpression(ElaTry n, LabelMap map, Hints hints)
        {
            var catchLab = cw.DefineLabel();
            var exitLab = cw.DefineLabel();

            //Generate a start of a 'try' section
            AddLinePragma(n);
            cw.Emit(Op.Start, catchLab);

            CompileExpression(n.Expression, map, Hints.None, n);

            //Leaving 'try' section
            cw.Emit(Op.Leave);
            cw.Emit(Op.Br, exitLab);
            cw.MarkLabel(catchLab);
            cw.Emit(Op.Leave);

            //Throw hint is to tell match compiler to generate a different typeId if
            //all pattern fail - to rethrow an original error instead of generating a
            //new MatchFailed error.
            CompileSimpleMatch(n.Entries.Equations, map, hints | Hints.Throw, null);

            cw.MarkLabel(exitLab);
            cw.Emit(Op.Nop);

            if ((hints & Hints.Left) == Hints.Left)
                AddValueNotUsed(n);
        }
Ejemplo n.º 52
0
        //This method contains main compilation logic for 'match' expressions and for 'try' expressions.
        //This method only supports a single pattern per entry.
        //A 'mexp' (matched expression) parameter can be null and is used for additional validation only.
        private void CompileSimpleMatch(IEnumerable<ElaEquation> bindings, LabelMap map, Hints hints, ElaExpression mexp)
        {
            ValidateOverlapSimple(bindings, mexp);

            var failLab = cw.DefineLabel();
            var endLab = cw.DefineLabel();

            //We need to remembers the first set of system addresses because we will have
            //to push them manually for the entries other than first.
            var firstSys = -1;
            var first = true;

            //Loops through all bindings
            //For the first iteration we assume that all values are already on stack.
            //For the next iteration we manually push all values.
            foreach (var b in bindings)
            {
                //Each match entry starts a lexical scope
                StartScope(false, b.Line, b.Column);

                //For second+ entries we put a label where we would jump if a previous
                //pattern fails
                if (!first)
                {
                    cw.MarkLabel(failLab);
                    failLab = cw.DefineLabel();
                }

                var p = b.Left;
                var sysVar = -1;

                //We apply an optimization if a we have a name reference (only for the first iteration).
                if (p.Type == ElaNodeType.NameReference && first)
                    sysVar = AddVariable(p.GetName(), p, ElaVariableFlags.Parameter, -1);
                else
                    sysVar = AddVariable(); //Create an unnamed system variable

                //This is not the first entry, so we have to push values first
                if (!first)
                    PushVar(firstSys);

                PopVar(sysVar);

                //We have to remember addresses calculated in a first iteration
                //to be able to push them once again in a second iteration.
                if (first)
                    firstSys = sysVar;

                CompilePattern(sysVar, p, failLab, false /*allowBang*/, false /*forceStrict*/);
                first = false;

                //Compile entry expression
                if (b.Right == null)
                    AddError(ElaCompilerError.InvalidMatchEntry, b.Left, FormatNode(b));
                else
                    CompileExpression(b.Right, map, Hints.None, b);

                //Close current scope
                EndScope();

                //If everything is OK skip through 'fail' clause
                cw.Emit(Op.Br, endLab);
            }

            //We fall here if all patterns have failed
            cw.MarkLabel(failLab);

            //If this hints is set than we generate a match for a 'try'
            //(exception handling) block. Instead of MatchFailed we need
            //to rethrow an original exception. Block 'try' always have
            //just a single expression to match, therefore firstSys[0] is
            //pretty safe here.
            if ((hints & Hints.Throw) == Hints.Throw)
            {
                PushVar(firstSys);
                cw.Emit(Op.Rethrow);
            }
            else
                cw.Emit(Op.Failwith, (Int32)ElaRuntimeError.MatchFailed);

            //Happy path for match
            cw.MarkLabel(endLab);
            cw.Emit(Op.Nop);
        }
Ejemplo n.º 53
0
        //Used to compile a 'match' expression.
        private void CompileMatchExpression(ElaMatch n, LabelMap map, Hints hints)
        {
            CompileExpression(n.Expression, map, Hints.None, n);
            AddLinePragma(n);
            CompileSimpleMatch(n.Entries.Equations, map, hints, n.Expression);

            if ((hints & Hints.Left) == Hints.Left)
                AddValueNotUsed(n);
        }
Ejemplo n.º 54
0
        //Pattern match compilation method which is used by functions defined by pattern matching.
        //Argument patNum contains number of patterns that should be in each.
        private void CompileFunctionMatch(int patNum, IEnumerable<ElaEquation> bindings, LabelMap map, Hints hints)
        {
            ValidateOverlapComplex(bindings);

            var failLab = cw.DefineLabel();
            var endLab = cw.DefineLabel();

            //We need to remembers the first set of system addresses because we will have
            //to push them manually for the entries other than first.
            var firstSys = new int[patNum];
            var first = true;

            //Loops through all bindings
            //For the first iteration we assume that all values are already on stack.
            //For the next iteration we manually push all values.
            foreach (var b in bindings)
            {
                //Each match entry starts a lexical scope
                StartScope(false, b.Line, b.Column);

                //This match compilation is used for functions only,
                //therefore the left-hand should always be a juxtaposition.
                var fc = (ElaJuxtaposition)b.Left;
                var len = fc.Parameters.Count;
                var pars = fc.Parameters;

                //Entries have different number of patterns, so generate an error and continue
                //compilation in order to prevent generation of 'redundant' error messages.
                if (len < patNum)
                    AddError(ElaCompilerError.PatternsTooFew, b.Left, FormatNode(b.Left), patNum, len);
                else if (len > patNum)
                    AddError(ElaCompilerError.PatternsTooMany, b.Left, FormatNode(b.Left), patNum, len);

                //For second+ entries we put a label where we would jump if a previous
                //pattern fails
                if (!first)
                {
                    cw.MarkLabel(failLab);
                    failLab = cw.DefineLabel();
                }

                for (var i = 0; i < len; i++)
                {
                    var p = pars[i];
                    var sysVar = -1;

                    //We apply an optimization if a we have a name reference (only for the first iteration).
                    if (p.Type == ElaNodeType.NameReference && first)
                        sysVar = AddVariable(p.GetName(), p, ElaVariableFlags.Parameter, -1);
                    else
                        sysVar = AddVariable(); //Create an unnamed system variable

                    //This is not the first entry, so we have to push values first
                    if (!first && firstSys.Length > i)
                        PushVar(firstSys[i]);

                    PopVar(sysVar);

                    //We have to remember addresses calculated in a first iteration
                    //to be able to push them once again in a second iteration.
                    if (first && firstSys.Length > i)
                        firstSys[i] = sysVar;

                }

                //Now compile patterns
                for (var i = 0; i < len; i++)
                    if (firstSys.Length > i && pars.Count > i)
                        CompilePattern(firstSys[i], pars[i], failLab, true /*allowBang*/, false /*forceStrict*/);

                first = false;

                //Compile entry expression
                if (b.Right == null)
                    AddError(ElaCompilerError.InvalidMatchEntry, b.Left, FormatNode(b));
                else
                    CompileExpression(b.Right, map, hints, b);

                //Close current scope
                EndScope();

                //If everything is OK skip through 'fail' clause
                cw.Emit(Op.Br, endLab);
            }

            //We fall here if all patterns have failed
            cw.MarkLabel(failLab);
            cw.Emit(Op.Failwith, (Int32)ElaRuntimeError.MatchFailed);

            //Happy path for match
            cw.MarkLabel(endLab);
            cw.Emit(Op.Nop);
        }