public override DynValue Visit(EachLoopNode eachLoopNode)
        {
            Environment.EnterScope();
            {
                var keyValue   = Visit(eachLoopNode.KeyNode);
                var valueValue = Visit(eachLoopNode.ValueNode);

                try
                {
                    var loopFrame = new LoopFrame();
                    Environment.LoopStack.Push(loopFrame);

                    var tableValue = Visit(eachLoopNode.TableNode);

                    if (tableValue.Type != DynValueType.Table)
                    {
                        throw new RuntimeException($"Expected a Table, got {tableValue.Type}.",
                                                   eachLoopNode.TableNode.Line);
                    }

                    var actualTable = tableValue.Table;

                    try
                    {
                        foreach (var element in actualTable)
                        {
                            keyValue.CopyFrom(element.Key);
                            valueValue.CopyFrom(element.Value);

                            Environment.EnterScope();
                            {
                                ExecuteStatementList(eachLoopNode.StatementList);
                            }
                            Environment.ExitScope();
                        }
                    }
                    catch (InvalidOperationException)
                    {
                        throw new RuntimeException("The table was modified, cannot continue execution.",
                                                   eachLoopNode.Line);
                    }
                }
                finally
                {
                    Environment.LoopStack.Pop();
                }
            }
            Environment.ExitScope();

            return(DynValue.Zero);
        }
Beispiel #2
0
 public abstract DynValue Visit(EachLoopNode eachLoopNode);
Beispiel #3
0
        public override DynValue Visit(EachLoopNode eachLoopNode)
        {
            var keyName   = eachLoopNode.KeyNode.Name;
            var valueName = eachLoopNode.ValueNode.Name;

            DynValue backupKeyVar   = null;
            DynValue backupValueVar = null;

            try
            {
                var lsItem = new LoopStackItem();
                LoopStack.Push(lsItem);

                DynValue tableValue = null;
                if (eachLoopNode.TableNode is VariableNode varNode)
                {
                    var tableName = varNode.Name;
                    if (CallStack.Count > 0)
                    {
                        var csItem = CallStack.Peek();

                        if (csItem.LocalVariableScope.ContainsKey(tableName))
                        {
                            tableValue = csItem.LocalVariableScope[tableName];
                        }
                        else if (csItem.ParameterScope.ContainsKey(tableName))
                        {
                            tableValue = csItem.ParameterScope[tableName];
                        }
                    }

                    if (tableValue == null)
                    {
                        if (Environment.SupplementLocalLookupTable.ContainsKey(tableName))
                        {
                            tableValue = Environment.SupplementLocalLookupTable[tableName];
                        }
                        else if (Environment.Globals.ContainsKey(tableName))
                        {
                            tableValue = Environment.Globals[tableName];
                        }

                        else
                        {
                            throw new RuntimeException($"Variable '{tableName}' could not be found in any known scope.", eachLoopNode.TableNode.Line);
                        }
                    }
                }
                else if (eachLoopNode.TableNode is FunctionCallNode fnCallNode)
                {
                    tableValue = Visit(fnCallNode);
                }
                else
                {
                    throw new RuntimeException("Expected a variable or function call.", eachLoopNode.TableNode.Line);
                }

                if (tableValue.Type != DynValueType.Table)
                {
                    throw new RuntimeException($"Expected a table, got {tableValue.Type.ToString().ToLower()}.", eachLoopNode.TableNode.Line);
                }

                var actualTable = tableValue.Table;

                if (Environment.Globals.ContainsKey(keyName))
                {
                    backupKeyVar = Environment.Globals[keyName];
                }

                if (Environment.Globals.ContainsKey(valueName))
                {
                    backupValueVar = Environment.Globals[valueName];
                }

                try
                {
                    foreach (var element in actualTable)
                    {
                        if (Environment.Globals.ContainsKey(keyName))
                        {
                            Environment.Globals.Remove(keyName);
                        }

                        if (Environment.Globals.ContainsKey(valueName))
                        {
                            Environment.Globals.Remove(valueName);
                        }

                        Environment.Globals.Add(keyName, element.Key);
                        Environment.Globals.Add(valueName, element.Value);

                        ExecuteStatementList(eachLoopNode.StatementList).GetAwaiter().GetResult();
                    }
                }
                catch (InvalidOperationException)
                {
                    throw new RuntimeException("The table was modified, cannot continue execution.", eachLoopNode.Line);
                }
                finally
                {
                    Environment.Globals.Remove(keyName);
                    Environment.Globals.Remove(valueName);
                }
            }
            catch
            {
                throw;
            }
            finally
            {
                if (backupKeyVar != null)
                {
                    Environment.Globals.Add(keyName, backupKeyVar);
                }

                if (backupValueVar != null)
                {
                    Environment.Globals.Add(valueName, backupValueVar);
                }

                LoopStack.Pop();
            }

            return(DynValue.Zero);
        }