Exemplo n.º 1
0
        private void InternalValidateCodes(List <CodeCommand> codes, List <LogInfo> logs)
        {
            foreach (CodeCommand cmd in codes)
            {
                switch (cmd.Type)
                {
                case CodeType.If:
                {
                    Debug.Assert(cmd.Info.GetType() == typeof(CodeInfo_If));
                    CodeInfo_If info = cmd.Info as CodeInfo_If;

                    if (info.Condition.Type == BranchConditionType.ExistSection)
                    {
                        // Exception Handling for 1-files.script
                        // If,ExistSection,%ScriptFile%,Cache_Delete_B,Run,%ScriptFile%,Cache_Delete_B
                        if (info.Condition.Arg1.Equals("%ScriptFile%", StringComparison.OrdinalIgnoreCase))
                        {
                            if (info.Embed.Type == CodeType.Run || info.Embed.Type == CodeType.Exec)
                            {
                                Debug.Assert(info.Embed.Info.GetType() == typeof(CodeInfo_RunExec));
                                CodeInfo_RunExec subInfo = info.Embed.Info as CodeInfo_RunExec;

                                if (subInfo.ScriptFile.Equals("%ScriptFile%", StringComparison.OrdinalIgnoreCase))
                                {
                                    if (info.Condition.Arg2.Equals(subInfo.SectionName, StringComparison.OrdinalIgnoreCase))
                                    {
                                        continue;
                                    }
                                }
                            }
                        }
                    }

                    InternalValidateCodes(info.Link, logs);
                }
                break;

                case CodeType.Else:
                {
                    Debug.Assert(cmd.Info.GetType() == typeof(CodeInfo_Else));
                    CodeInfo_Else info = cmd.Info as CodeInfo_Else;

                    InternalValidateCodes(info.Link, logs);
                }
                break;

                case CodeType.Run:
                case CodeType.Exec:
                {
                    Debug.Assert(cmd.Info.GetType() == typeof(CodeInfo_RunExec));
                    CodeInfo_RunExec info = cmd.Info as CodeInfo_RunExec;

                    // CodeValidator does not have Variable information, so just check with predefined literal
                    if (info.ScriptFile.Equals("%ScriptFile%", StringComparison.OrdinalIgnoreCase))
                    {
                        if (p.Sections.ContainsKey(info.SectionName))
                        {
                            logs.AddRange(ValidateCodeSection(p.Sections[info.SectionName]));
                        }
                        else if (CodeParser.StringContainsVariable(info.SectionName) == false)
                        {
                            logs.Add(new LogInfo(LogState.Error, $"Section [{info.SectionName}] does not exist", cmd));
                        }
                    }
                }
                break;

                case CodeType.Loop:
                {
                    Debug.Assert(cmd.Info.GetType() == typeof(CodeInfo_Loop));
                    CodeInfo_Loop info = cmd.Info as CodeInfo_Loop;

                    if (info.Break)
                    {
                        continue;
                    }

                    // CodeValidator does not have Variable information, so just check with predefined literal
                    if (info.ScriptFile.Equals("%ScriptFile%", StringComparison.OrdinalIgnoreCase))
                    {
                        if (p.Sections.ContainsKey(info.SectionName))
                        {
                            logs.AddRange(ValidateCodeSection(p.Sections[info.SectionName]));
                        }
                        else if (CodeParser.StringContainsVariable(info.SectionName) == false)
                        {
                            logs.Add(new LogInfo(LogState.Error, $"Section [{info.SectionName}] does not exist", cmd));
                        }
                    }
                }
                break;

                default:
                    break;
                }
            }
        }
Exemplo n.º 2
0
        public static void Loop(EngineState s, CodeCommand cmd)
        {
            Debug.Assert(cmd.Info.GetType() == typeof(CodeInfo_Loop));
            CodeInfo_Loop info = cmd.Info as CodeInfo_Loop;

            if (info.Break)
            {
                if (s.LoopState == LoopState.Off)
                {
                    s.Logger.Build_Write(s, new LogInfo(LogState.Error, "Loop is not running", cmd, s.CurDepth));
                }
                else
                {
                    s.LoopState = LoopState.Off;
                    s.Logger.Build_Write(s, new LogInfo(LogState.Info, "Breaking loop", cmd, s.CurDepth));

                    // Reset LoopCounter, to be sure
                    s.LoopLetter  = ' ';
                    s.LoopCounter = 0;
                }
            }
            else if (s.LoopState != LoopState.Off)
            { // If loop is already turned on, throw error
                s.Logger.Build_Write(s, new LogInfo(LogState.Error, "Nested loop is not supported", cmd, s.CurDepth));
            }
            else
            {
                string startStr = StringEscaper.Preprocess(s, info.StartIdx);
                string endStr   = StringEscaper.Preprocess(s, info.EndIdx);

                // Prepare Loop
                string        scriptFile  = StringEscaper.Preprocess(s, info.ScriptFile);
                string        sectionName = StringEscaper.Preprocess(s, info.SectionName);
                List <string> paramList   = StringEscaper.Preprocess(s, info.Parameters);

                Script p = Engine.GetScriptInstance(s, cmd, s.CurrentScript.FullPath, scriptFile, out bool inCurrentScript);

                // Does section exists?
                if (!p.Sections.ContainsKey(sectionName))
                {
                    throw new ExecuteException($"[{scriptFile}] does not have section [{sectionName}]");
                }

                // Section Parameter
                Dictionary <int, string> paramDict = new Dictionary <int, string>();
                for (int i = 0; i < paramList.Count; i++)
                {
                    paramDict[i + 1] = paramList[i];
                }

                long loopCount = 0;
                long startIdx = 0, endIdx = 0;
                char startLetter = ' ', endLetter = ' ';
                switch (cmd.Type)
                {
                case CodeType.Loop:
                {         // Integer Index
                    if (!NumberHelper.ParseInt64(startStr, out startIdx))
                    {
                        throw new ExecuteException($"Argument [{startStr}] is not a valid integer");
                    }
                    if (!NumberHelper.ParseInt64(endStr, out endIdx))
                    {
                        throw new ExecuteException($"Argument [{endStr}] is not a valid integer");
                    }
                    loopCount = endIdx - startIdx + 1;
                }
                break;

                case CodeType.LoopLetter:
                {         // Drive Letter
                    if (!(startStr.Length == 1 && StringHelper.IsAlphabet(startStr[0])))
                    {
                        throw new ExecuteException($"Argument [{startStr}] is not a valid drive letter");
                    }
                    if (!(endStr.Length == 1 && StringHelper.IsAlphabet(endStr[0])))
                    {
                        throw new ExecuteException($"Argument [{endStr}] is not a valid drive letter");
                    }

                    startLetter = char.ToUpper(startStr[0]);
                    endLetter   = char.ToUpper(endStr[0]);

                    if (endLetter < startLetter)
                    {
                        throw new ExecuteException($"StartLetter must be smaller than EndLetter in lexicographic order");
                    }

                    loopCount = endLetter - startLetter + 1;
                }
                break;

                default:
                    throw new InternalException("Internal Logic Error at CommandBranch.Loop");
                }

                // Log Messages
                string logMessage;
                if (inCurrentScript)
                {
                    logMessage = $"Loop Section [{sectionName}] [{loopCount}] times";
                }
                else
                {
                    logMessage = $"Loop [{p.Title}]'s Section [{sectionName}] [{loopCount}] times";
                }
                s.Logger.Build_Write(s, new LogInfo(LogState.Info, logMessage, cmd, s.CurDepth));

                // Loop it
                SectionAddress nextAddr = new SectionAddress(p, p.Sections[sectionName]);
                int            loopIdx  = 1;
                switch (cmd.Type)
                {
                case CodeType.Loop:
                    for (s.LoopCounter = startIdx; s.LoopCounter <= endIdx; s.LoopCounter++)
                    {     // Counter Variable is [#c]
                        s.Logger.Build_Write(s, new LogInfo(LogState.Info, $"Entering Loop with [{s.LoopCounter}] ({loopIdx}/{loopCount})", cmd, s.CurDepth));
                        s.Logger.LogSectionParameter(s, s.CurDepth, paramDict, cmd);

                        int depthBackup = s.CurDepth;
                        s.LoopState = LoopState.OnIndex;
                        Engine.RunSection(s, nextAddr, paramDict, s.CurDepth + 1, true);
                        if (s.LoopState == LoopState.Off)     // Loop,Break
                        {
                            break;
                        }
                        s.LoopState = LoopState.Off;
                        s.CurDepth  = depthBackup;

                        s.Logger.Build_Write(s, new LogInfo(LogState.Info, $"End of Loop with [{s.LoopCounter}] ({loopIdx}/{loopCount})", cmd, s.CurDepth));
                        loopIdx += 1;
                    }
                    break;

                case CodeType.LoopLetter:
                    for (s.LoopLetter = startLetter; s.LoopLetter <= endLetter; s.LoopLetter++)
                    {     // Counter Variable is [#c]
                        s.Logger.Build_Write(s, new LogInfo(LogState.Info, $"Entering Loop with [{s.LoopLetter}] ({loopIdx}/{loopCount})", cmd, s.CurDepth));
                        s.Logger.LogSectionParameter(s, s.CurDepth, paramDict, cmd);

                        int depthBackup = s.CurDepth;
                        s.LoopState = LoopState.OnDriveLetter;
                        Engine.RunSection(s, nextAddr, paramDict, s.CurDepth + 1, true);
                        if (s.LoopState == LoopState.Off)     // Loop,Break
                        {
                            break;
                        }
                        s.LoopState = LoopState.Off;
                        s.CurDepth  = depthBackup;

                        s.Logger.Build_Write(s, new LogInfo(LogState.Info, $"End of Loop with [{s.LoopLetter}] ({loopIdx}/{loopCount})", cmd, s.CurDepth));
                        loopIdx += 1;
                    }
                    break;

                default:
                    throw new InternalException("Internal Logic Error at CommandBranch.Loop");
                }

                // Reset LoopCounter, to be sure
                s.LoopLetter  = ' ';
                s.LoopCounter = 0;
            }
        }
Exemplo n.º 3
0
        public static void Loop(EngineState s, CodeCommand cmd)
        {
            Debug.Assert(cmd.Info.GetType() == typeof(CodeInfo_Loop));
            CodeInfo_Loop info = cmd.Info as CodeInfo_Loop;

            if (info.Break)
            {
                if (s.LoopRunning)
                {
                    s.LoopRunning = false;
                    s.Logger.Build_Write(s, new LogInfo(LogState.Info, "Breaking Loop", cmd, s.CurDepth));
                }
                else
                {
                    s.Logger.Build_Write(s, new LogInfo(LogState.Error, "Loop is not running", cmd, s.CurDepth));
                }
            }
            else
            {
                string startIdxStr = StringEscaper.Preprocess(s, info.StartIdx);
                if (NumberHelper.ParseInt64(startIdxStr, out long startIdx) == false)
                {
                    throw new ExecuteException($"Argument [{startIdxStr}] is not a valid integer");
                }
                string endIdxStr = StringEscaper.Preprocess(s, info.EndIdx);
                if (NumberHelper.ParseInt64(endIdxStr, out long endIdx) == false)
                {
                    throw new ExecuteException($"Argument [{endIdxStr}] is not a valid integer");
                }
                long loopCount = endIdx - startIdx + 1;

                // Prepare Loop
                string        pluginFile  = StringEscaper.Preprocess(s, info.PluginFile);
                string        sectionName = StringEscaper.Preprocess(s, info.SectionName);
                List <string> paramList   = StringEscaper.Preprocess(s, info.Parameters);

                Plugin p = Engine.GetPluginInstance(s, cmd, s.CurrentPlugin.FullPath, pluginFile, out bool inCurrentPlugin);

                // Does section exists?
                if (!p.Sections.ContainsKey(sectionName))
                {
                    throw new ExecuteException($"[{pluginFile}] does not have section [{sectionName}]");
                }

                string logMessage;
                if (inCurrentPlugin)
                {
                    logMessage = $"Loop Section [{sectionName}] [{loopCount}] times";
                }
                else
                {
                    logMessage = $"Loop [{p.Title}]'s Section [{sectionName}] [{loopCount}] times";
                }
                s.Logger.Build_Write(s, new LogInfo(LogState.Info, logMessage, cmd, s.CurDepth));

                // Section Parameter
                Dictionary <int, string> paramDict = new Dictionary <int, string>();
                for (int i = 0; i < paramList.Count; i++)
                {
                    paramDict[i + 1] = paramList[i];
                }

                // Loop it
                SectionAddress nextAddr = new SectionAddress(p, p.Sections[sectionName]);
                for (s.LoopCounter = startIdx; s.LoopCounter <= endIdx; s.LoopCounter++)
                { // Counter Variable is [#c]
                    s.Logger.Build_Write(s, new LogInfo(LogState.Info, $"Entering Loop [{s.LoopCounter}/{loopCount}]", cmd, s.CurDepth));
                    s.Logger.LogSectionParameter(s, s.CurDepth, paramDict, cmd);

                    int depthBackup = s.CurDepth;
                    s.LoopRunning = true;
                    Engine.RunSection(s, nextAddr, paramDict, s.CurDepth + 1, true);
                    if (s.LoopRunning == false) // Loop,Break
                    {
                        break;
                    }
                    s.LoopRunning = false;
                    s.CurDepth    = depthBackup;

                    s.Logger.Build_Write(s, new LogInfo(LogState.Info, $"End of Loop [{s.LoopCounter}/{loopCount}]", cmd, s.CurDepth));
                }
            }
        }
Exemplo n.º 4
0
        private void RecursiveFindCodeSection(IReadOnlyList <CodeCommand> codes, List <LogInfo> logs)
        {
            string targetCodeSection      = null;
            string targetInterfaceSection = null;

            foreach (CodeCommand cmd in codes)
            {
                switch (cmd.Type)
                {
                    #region Check CodeSections
                case CodeType.If:
                {
                    CodeInfo_If info = cmd.Info.Cast <CodeInfo_If>();

                    if (info.Condition.Type == BranchConditionType.ExistSection)
                    {
                        // For recursive section call
                        // Ex) If,ExistSection,%ScriptFile%,DoWork,Run,%ScriptFile%,DoWork
                        if (info.Condition.Arg1.Equals(Script.Const.ScriptFile, StringComparison.OrdinalIgnoreCase) &&
                            info.Embed.Type == CodeType.Run || info.Embed.Type == CodeType.RunEx || info.Embed.Type == CodeType.Exec)
                        {
                            CodeInfo_RunExec subInfo = info.Embed.Info.Cast <CodeInfo_RunExec>();
                            if (subInfo.ScriptFile.Equals(Script.Const.ScriptFile, StringComparison.OrdinalIgnoreCase))
                            {
                                if (info.Condition.Arg2.Equals(subInfo.SectionName, StringComparison.OrdinalIgnoreCase))
                                {
                                    continue;
                                }
                            }
                        }
                    }

                    RecursiveFindCodeSection(info.Link, logs);
                }
                break;

                case CodeType.Else:
                {
                    CodeInfo_Else info = cmd.Info.Cast <CodeInfo_Else>();

                    RecursiveFindCodeSection(info.Link, logs);
                }
                break;

                case CodeType.Run:
                case CodeType.Exec:
                case CodeType.RunEx:
                {
                    CodeInfo_RunExec info = cmd.Info.Cast <CodeInfo_RunExec>();

                    // CodeValidator does not have Variable information, so just check with predefined literal
                    if (info.ScriptFile.Equals(Script.Const.ScriptFile, StringComparison.OrdinalIgnoreCase) &&
                        !CodeParser.StringContainsVariable(info.SectionName))
                    {
                        targetCodeSection = info.SectionName;
                    }
                }
                break;

                case CodeType.Loop:
                case CodeType.LoopLetter:
                case CodeType.LoopEx:
                case CodeType.LoopLetterEx:
                {
                    CodeInfo_Loop info = cmd.Info.Cast <CodeInfo_Loop>();

                    if (info.Break)
                    {
                        continue;
                    }

                    // CodeValidator does not have Variable information, so just check with predefined literal
                    if (info.ScriptFile.Equals(Script.Const.ScriptFile, StringComparison.OrdinalIgnoreCase) &&
                        !CodeParser.StringContainsVariable(info.SectionName))
                    {
                        targetCodeSection = info.SectionName;
                    }
                }
                break;

                case CodeType.UserInput:
                {
                    CodeInfo_UserInput info = cmd.Info.Cast <CodeInfo_UserInput>();

                    UserInputType type = info.Type;
                    switch (type)
                    {
                    case UserInputType.DirPath:
                    case UserInputType.FilePath:
                    {
                        UserInputInfo_DirFile subInfo = info.SubInfo.Cast <UserInputInfo_DirFile>();

                        if (info.Type == UserInputType.FilePath)
                        {                 // Select File
                            if (subInfo.Filter != null)
                            {
                                string filter = StringEscaper.Unescape(subInfo.Filter);
                                if (StringEscaper.IsFileFilterValid(filter) == false)
                                {
                                    logs.Add(new LogInfo(LogState.Error, $"File filter pattern [{filter}] is invalid", cmd));
                                }
                            }
                        }
                        else
                        {                 // Select Folder
                            if (subInfo.Filter != null)
                            {
                                logs.Add(new LogInfo(LogState.Warning, $"File filters cannot be used for folder selection", cmd));
                            }
                        }
                    }
                    break;
                    }
                }
                break;

                    #endregion
                    #region Check InterfaceSections
                case CodeType.AddInterface:
                {
                    CodeInfo_AddInterface info = cmd.Info.Cast <CodeInfo_AddInterface>();

                    // CodeValidator does not have Variable information, so just check with predefined literal
                    if (info.ScriptFile.Equals(Script.Const.ScriptFile, StringComparison.OrdinalIgnoreCase) &&
                        !CodeParser.StringContainsVariable(info.Section))
                    {
                        targetInterfaceSection = info.Section;
                    }
                }
                break;

                case CodeType.ReadInterface:
                {
                    CodeInfo_ReadInterface info = cmd.Info.Cast <CodeInfo_ReadInterface>();

                    // CodeValidator does not have Variable information, so just check with predefined literal
                    if (info.ScriptFile.Equals(Script.Const.ScriptFile, StringComparison.OrdinalIgnoreCase) &&
                        !CodeParser.StringContainsVariable(info.Section))
                    {
                        targetInterfaceSection = info.Section;
                    }
                }
                break;

                case CodeType.WriteInterface:
                {
                    CodeInfo_WriteInterface info = cmd.Info.Cast <CodeInfo_WriteInterface>();

                    // CodeValidator does not have Variable information, so just check with predefined literal
                    if (info.ScriptFile.Equals(Script.Const.ScriptFile, StringComparison.OrdinalIgnoreCase) &&
                        !CodeParser.StringContainsVariable(info.Section))
                    {
                        targetInterfaceSection = info.Section;
                    }
                }
                break;

                case CodeType.IniWrite:
                {
                    // To detect multi-interface without `InterfaceList=`,
                    // Inspect pattern `IniWrite,%ScriptFile%,Main,Interface,<NewInterfaceSection>`
                    CodeInfo_IniWrite info = cmd.Info.Cast <CodeInfo_IniWrite>();

                    // CodeValidator does not have Variable information, so just check with predefined literal
                    if (info.FileName.Equals(Script.Const.ScriptFile, StringComparison.OrdinalIgnoreCase) &&
                        info.Section.Equals(ScriptSection.Names.Main, StringComparison.OrdinalIgnoreCase) &&
                        info.Key.Equals(ScriptSection.Names.Interface, StringComparison.OrdinalIgnoreCase) &&
                        !CodeParser.StringContainsVariable(info.Value))
                    {
                        targetInterfaceSection = info.Value;
                    }
                }
                break;
                    #endregion
                }

                if (targetCodeSection != null)
                {
                    if (_sc.Sections.ContainsKey(targetCodeSection))
                    {
                        logs.AddRange(CheckCodeSection(_sc.Sections[targetCodeSection], cmd.RawCode, cmd.LineIdx));
                    }
                    else
                    {
                        logs.Add(new LogInfo(LogState.Error, $"Section [{targetCodeSection}] does not exist", cmd));
                    }
                }

                if (targetInterfaceSection != null)
                {
                    if (_sc.Sections.ContainsKey(targetInterfaceSection))
                    {
                        logs.AddRange(CheckInterfaceSection(_sc.Sections[targetInterfaceSection], cmd.RawCode, cmd.LineIdx));
                    }
                    else
                    {
                        logs.Add(new LogInfo(LogState.Error, $"Section [{targetInterfaceSection}] does not exist", cmd));
                    }
                }
            }
        }
Exemplo n.º 5
0
        private void InternalValidateCodes(CodeCommand[] codes, List <LogInfo> logs)
        {
            string targetCodeSection      = null;
            string targetInterfaceSection = null;

            foreach (CodeCommand cmd in codes)
            {
                switch (cmd.Type)
                {
                    #region Check CodeSections
                case CodeType.If:
                {
                    CodeInfo_If info = cmd.Info.Cast <CodeInfo_If>();

                    if (info.Condition.Type == BranchConditionType.ExistSection)
                    {
                        // For recursive section call
                        // Ex) If,ExistSection,%ScriptFile%,DoWork,Run,%ScriptFile%,DoWork
                        if (info.Condition.Arg1.Equals("%ScriptFile%", StringComparison.OrdinalIgnoreCase) &&
                            info.Embed.Type == CodeType.Run || info.Embed.Type == CodeType.Exec)
                        {
                            CodeInfo_RunExec subInfo = info.Embed.Info.Cast <CodeInfo_RunExec>();
                            if (subInfo.ScriptFile.Equals("%ScriptFile%", StringComparison.OrdinalIgnoreCase))
                            {
                                if (info.Condition.Arg2.Equals(subInfo.SectionName, StringComparison.OrdinalIgnoreCase))
                                {
                                    continue;
                                }
                            }
                        }
                    }

                    InternalValidateCodes(info.Link.ToArray(), logs);
                }
                break;

                case CodeType.Else:
                {
                    CodeInfo_Else info = cmd.Info.Cast <CodeInfo_Else>();

                    InternalValidateCodes(info.Link.ToArray(), logs);
                }
                break;

                case CodeType.Run:
                case CodeType.Exec:
                case CodeType.RunEx:
                {
                    CodeInfo_RunExec info = cmd.Info.Cast <CodeInfo_RunExec>();

                    // CodeValidator does not have Variable information, so just check with predefined literal
                    if (info.ScriptFile.Equals("%ScriptFile%", StringComparison.OrdinalIgnoreCase) &&
                        !CodeParser.StringContainsVariable(info.SectionName))
                    {
                        targetCodeSection = info.SectionName;
                    }
                }
                break;

                case CodeType.Loop:
                case CodeType.LoopLetter:
                case CodeType.LoopEx:
                case CodeType.LoopLetterEx:
                {
                    CodeInfo_Loop info = cmd.Info.Cast <CodeInfo_Loop>();

                    if (info.Break)
                    {
                        continue;
                    }

                    // CodeValidator does not have Variable information, so just check with predefined literal
                    if (info.ScriptFile.Equals("%ScriptFile%", StringComparison.OrdinalIgnoreCase) &&
                        !CodeParser.StringContainsVariable(info.SectionName))
                    {
                        targetCodeSection = info.SectionName;
                    }
                }
                break;

                    #endregion
                    #region Check InterfaceSections
                case CodeType.AddInterface:
                {
                    CodeInfo_AddInterface info = cmd.Info.Cast <CodeInfo_AddInterface>();

                    // CodeValidator does not have Variable information, so just check with predefined literal
                    if (info.ScriptFile.Equals("%ScriptFile%", StringComparison.OrdinalIgnoreCase) &&
                        CodeParser.StringContainsVariable(info.Section))
                    {
                        targetInterfaceSection = info.Section;
                    }
                }
                break;

                case CodeType.ReadInterface:
                {
                    CodeInfo_ReadInterface info = cmd.Info.Cast <CodeInfo_ReadInterface>();

                    // CodeValidator does not have Variable information, so just check with predefined literal
                    if (info.ScriptFile.Equals("%ScriptFile%", StringComparison.OrdinalIgnoreCase) &&
                        CodeParser.StringContainsVariable(info.Section))
                    {
                        targetInterfaceSection = info.Section;
                    }
                }
                break;

                case CodeType.WriteInterface:
                {
                    CodeInfo_WriteInterface info = cmd.Info.Cast <CodeInfo_WriteInterface>();

                    // CodeValidator does not have Variable information, so just check with predefined literal
                    if (info.ScriptFile.Equals("%ScriptFile%", StringComparison.OrdinalIgnoreCase) &&
                        CodeParser.StringContainsVariable(info.Section))
                    {
                        targetInterfaceSection = info.Section;
                    }
                }
                break;
                    #endregion
                }

                if (targetCodeSection != null && !_visitedSections.Contains(targetCodeSection))
                {
                    _visitedSections.Add(targetCodeSection);

                    if (_sc.Sections.ContainsKey(targetCodeSection))
                    {
                        logs.AddRange(ValidateCodeSection(_sc.Sections[targetCodeSection], cmd.RawCode, cmd.LineIdx));
                    }
                    else
                    {
                        logs.Add(new LogInfo(LogState.Error, $"Section [{targetCodeSection}] does not exist", cmd));
                    }
                }

                if (targetInterfaceSection != null && !_visitedSections.Contains(targetInterfaceSection))
                {
                    _visitedSections.Add(targetInterfaceSection);

                    if (_sc.Sections.ContainsKey(targetInterfaceSection))
                    {
                        logs.AddRange(ValidateInterfaceSection(_sc.Sections[targetInterfaceSection], cmd.RawCode, cmd.LineIdx));
                    }
                    else
                    {
                        logs.Add(new LogInfo(LogState.Error, $"Section [{targetInterfaceSection}] does not exist", cmd));
                    }
                }
            }
        }