private void Visit(IReadOnlyList <Cursor> decls, TraversalData traversalData) { foreach (var decl in decls) { Visit(decl, traversalData); } }
/// <summary> /// Visit a function declaration /// </summary> private void VisitFunctionDecl(FunctionDecl funDecl, TraversalData traversalData) { var desc = MatchHook(traversalData.GetQualifiedType(funDecl)); if (desc != null) { m_bir.Hooks.Add(CreateHook(funDecl, desc, traversalData)); } }
/// <summary> /// Visit a namespace declaration /// </summary> private void VisitTypeDecl(TypeDecl typeDecl, TraversalData traversalData) { if (typeDecl.Kind == CXCursorKind.CXCursor_ClassDecl || typeDecl.Kind == CXCursorKind.CXCursor_StructDecl) { traversalData.AddClass(typeDecl.Name); } Visit(typeDecl.CursorChildren, traversalData); if (typeDecl.Kind == CXCursorKind.CXCursor_ClassDecl || typeDecl.Kind == CXCursorKind.CXCursor_StructDecl) { traversalData.RemoveClass(); } }
/// <summary> /// Main dispatch method /// </summary> private void Visit(Cursor cursor, TraversalData traversalData) { if (m_visitedCursors.Contains(cursor)) { // The AST can by cyclic return; } m_visitedCursors.Add(cursor); if (cursor is Decl decl) { VisitDecl(decl, traversalData); } }
public static PgnFormatterVariationTestCase GetLongVariation() { var testCase = new PgnFormatterVariationTestCase(BoardConstants.FenStartingPosition, PGN.PgnFormatterAllAccoutrements, TraversalData.longGameMainLine, "Game with comments, multiple variations on variations, annotations, tags filled"); TraversalData.SetupLongGame(testCase); testCase.Game.Tags.Event = "The Mediocre of Chess"; testCase.Game.Tags.White = "GoodPlayer, One"; testCase.Game.Tags.Black = "DecentPlayer, A."; testCase.Game.Tags.Site = "New York City, NY USA"; testCase.Game.Tags.Date = "2021.08.18"; testCase.Game.Tags.Round = "2"; testCase.Game.Tags["EventDate"] = "2021.08.16"; testCase.Game.GameResult = GameResult.WhiteWins; testCase.Game.Tags["ECO"] = "D51"; return(testCase); }
/// <summary> /// Declaration dispatch /// </summary> private void VisitDecl(Decl decl, TraversalData traversalData) { if (decl.Kind == CXCursorKind.CXCursor_FirstDecl || decl.Kind == CXCursorKind.CXCursor_UnexposedDecl) { Visit(decl.CursorChildren, traversalData); } else if (decl is NamespaceDecl namespaceDecl) { VisitNamespaceDecl(namespaceDecl, traversalData); } else if (decl is FunctionDecl funDecl) { VisitFunctionDecl(funDecl, traversalData); } else if (decl is TypeDecl typeDecl) { VisitTypeDecl(typeDecl, traversalData); } }
/// <summary> /// Register a hook /// </summary> private BIR.BIR.Hook CreateHook(FunctionDecl decl, HookDesc hookDesc, TraversalData traversalData) { BIR.BIR.Hook hook = new BIR.BIR.Hook(); var desc = hookDesc.Desc; hook.Identifier = IO.MakeValidIdentifier(string.IsNullOrEmpty(desc.Identifier) ? traversalData.GetQualifiedType(decl).Replace("::", "_") : desc.Identifier); hook.ReturnType = decl.ReturnType.ToString(); hook.Module = desc.Module; hook.Inputs = desc.Input; if (decl.Handle.Kind == CXCursorKind.CXCursor_CXXMethod) { var cxxMethodDecl = (CXXMethodDecl)decl; hook.VTableThisType = traversalData.GetClasses(); hook.HookType = cxxMethodDecl.IsVirtual ? BIR.BIR.HookTypeEnum.VTable : BIR.BIR.HookTypeEnum.CFunction; } else { hook.HookType = BIR.BIR.HookTypeEnum.CFunction; hook.CFunctionName = traversalData.GetQualifiedType(decl); if (string.IsNullOrEmpty(hook.Module)) { throw new Exception($"'hook.descriptions.[{hookDesc.Key}].module' is required to load function \"{desc.Name}\""); } } // Extract parameter foreach (var param in decl.Parameters) { hook.Parameters.Add(new BIR.BIR.Hook.Parameter() { Name = param.Name, Type = param.Type.ToString(), }); } return(hook); }
/// <summary> /// Save persiston to database /// </summary> /// <param name="pristineDaton">null or the version before the diff was applied</param> /// <param name="modifiedDaton">the validated final version</param> /// <param name="diff">the difference between pristine and modified, which is what this method inspects to make the changes</param> public virtual async Task Save(IDbConnection db, IUser user, Persiston pristineDaton, Persiston modifiedDaton, PersistonDiff diff) { //called for each row in traversal; return true to recurse over children async Task <(object, bool)> rowCallback(RowChangingData cdata) { if (cdata.DiffRow.Kind == DiffKind.DeletedRow) { await DeleteRowWithCascade(db, cdata.TableDef, cdata.PristineRow); return(null, false); //don't recur to children of deleted row } object newpk = await InsertUpdateRow(db, cdata); return(newpk, true); } var tdata = new TraversalData { ParentKey = null, TableDef = diff.DatonDef.MainTableDef, DiffRowList = diff.MainTable, PristineList = null, ModifiedList = null, ProcessRowF = rowCallback }; if (diff.DatonDef.MultipleMainRows) { var mainListField = diff.DatonDef.Type.GetField(tdata.TableDef.Name); tdata.PristineList = mainListField.GetValue(pristineDaton) as IList; tdata.ModifiedList = mainListField.GetValue(modifiedDaton) as IList; await TraverseDiffList(tdata, null, null); } else { await TraverseDiffList(tdata, pristineDaton, modifiedDaton); } }
/// <summary> /// Call ProcessRowF on all rows in the diff list, and recurse to all child tables. /// </summary> /// <param name="singleMainPristineRow">only set for top level call if there is a single main row</param> /// <param name="singleMainModifiedRow">only set for top level call if there is a single main row</param> protected async Task TraverseDiffList(TraversalData tdata, Row singleMainPristineRow, Row singleMainModifiedRow) { var pkField = tdata.TableDef.RowType.GetField(tdata.TableDef.PrimaryKeyColName); foreach (var row in tdata.DiffRowList) { if (!row.Columns.TryGetValue(tdata.TableDef.PrimaryKeyColName, out object rowKey)) { throw new Exception($"Diff row is missing primary key {tdata.TableDef.PrimaryKeyColName}"); } //find pristine row Row pristineRow = singleMainPristineRow; if (tdata.PristineList != null && row.Kind != DiffKind.NewRow) { int rowIdx = Utils.IndexOfPrimaryKeyMatch(tdata.PristineList, pkField, rowKey); if (rowIdx >= 0) { pristineRow = tdata.PristineList[rowIdx] as Row; } } //find modified row Row modifiedRow = singleMainModifiedRow; if (tdata.ModifiedList != null) { int rowIdx = Utils.IndexOfPrimaryKeyMatch(tdata.ModifiedList, pkField, rowKey); if (rowIdx >= 0) { modifiedRow = tdata.ModifiedList[rowIdx] as Row; } } //callback to process row var cdata = new RowChangingData { ParentKey = tdata.ParentKey, DiffRow = row, DiffRowList = tdata.DiffRowList, TableDef = tdata.TableDef, PristineRow = pristineRow, ModifiedRow = modifiedRow }; (object newPK, bool doTraverseChildren) = await tdata.ProcessRowF?.Invoke(cdata); if (newPK != null) { rowKey = newPK; } //skip child tables? if (!doTraverseChildren) { continue; } //loop child tables of this row if (row.ChildTables != null) { foreach (var child in row.ChildTables) { var childTableDef = child.Key; var childRows = child.Value; var listField = tdata.TableDef.RowType.GetField(childTableDef.Name); //get pristine list IList childPristineList = null; if (pristineRow != null) { childPristineList = listField.GetValue(pristineRow) as IList; } //get modified list IList childModifiedList = null; if (modifiedRow != null) { childModifiedList = listField.GetValue(modifiedRow) as IList; } var childTdata = new TraversalData { ParentKey = rowKey, TableDef = childTableDef, DiffRowList = childRows, PristineList = childPristineList, ModifiedList = childModifiedList, ProcessRowF = tdata.ProcessRowF }; await TraverseDiffList(childTdata, null, null); } } } }
/// <summary> /// Visit a namespace declaration /// </summary> private void VisitNamespaceDecl(NamespaceDecl namespaceDecl, TraversalData traversalData) { traversalData.AddNamespace(namespaceDecl.ToString()); Visit(namespaceDecl.Decls, traversalData); traversalData.RemoveNamespace(); }
/// <summary> /// basic init /// </summary> public Tile() { Traversals = new TraversalData(this); Cover = new CoverData(); TileObjects = new TileObjectData(this); }