SuperScriptMaterializer/SuperScriptDecorator/DecoratorBB.py
2023-02-22 21:49:31 +08:00

271 lines
12 KiB
Python

import sqlite3, collections
import DecoratorData, DecoratorConst
class IntermediateTreeNode(object):
def __init__(self):
self.m_FirstVisit: bool = True
self.m_LoactedLayer: int = DecoratorData.TreeLayout.NO_REFERENCE_LAYER
self.m_LocatedPos: int = DecoratorData.TreeLayout.NO_START_POS_OF_REF_LAYER
self.m_Collection: collections.deque[int] = collections.deque()
class IntermediateOperDownwardSearch(object):
def __init__(self):
self.m_Collection: collections.deque[int] = collections.deque()
class BlocksFactory(object):
def __init__(self, db: sqlite3.Connection, graph: DecoratorData.GraphResult):
# assign members
self.m_Graph: DecoratorData.GraphResult = graph
self.m_Db: sqlite3.Connection = db
self.__AllBB: set[int] = set()
self.__AllOper: set[int] = set()
# fill data first
self.__FillDataFromDb()
# proc each data
self.__ProcActiveBB()
self.__ProcPassiveBB()
self.__ProcPassiveOper()
def __GetOneFromSet(self, vals: set[int]) -> int:
return next(iter(vals))
def __FillDataFromDb(self):
cursor: sqlite3.Cursor = self.m_Db.cursor()
cursor.execute('SELECT * FROM [script_behavior] WHERE parent == ?', (self.m_Graph.m_GraphCKID, ))
for sqldata in cursor.fetchall():
payload: DecoratorData.BBDataPayload = DecoratorData.BBDataPayload(sqldata)
self.m_Graph.m_BlockDict[payload.m_CKID] = DecoratorData.BBTreeNode(payload)
self.__AllBB.add(payload.m_CKID)
cursor.execute('SELECT * FROM [script_pOper] WHERE parent == ?', (self.m_Graph.m_GraphCKID, ))
for sqldata in cursor.fetchall():
payload: DecoratorData.OperDataPayload = DecoratorData.OperDataPayload(sqldata)
self.m_Graph.m_BlockDict[payload.m_CKID] = DecoratorData.OperTreeNode(payload)
self.__AllOper.add(payload.m_CKID)
cursor.close()
def __FindBBBottomOperRoot(self, start_pOut: tuple[int]) -> tuple[int]:
cursor: sqlite3.Cursor = self.m_Db.cursor()
cursor_outget: sqlite3.Cursor = self.m_Db.cursor()
# prepare something
stack: collections.deque[int] = collections.deque()
procedOut: set[int] = set()
result: set[int] = set()
# prepare start symbol
stack.extend(start_pOut)
# analyze
while len(stack) != 0:
# peek again
pout: int = stack.pop()
# search this pOut in pLink
cursor.execute('SELECT [output], [output_obj], [output_type], [output_is_bb] FROM [script_pLink] WHERE ([input] == ? AND NOT (([output_type] == ? OR [output_type] == ?) AND [output_is_bb] == ?) AND [parent] == ?);',
(pout,
DecoratorConst.Export_pLink_InputOutputType.PIN, DecoratorConst.Export_pLink_InputOutputType.PTARGET, DecoratorConst.Export_Boolean.TRUE, # filter all BB's pIn
self.m_Graph.m_GraphCKID)
)
# read datas
for (output, output_obj, output_type, output_is_bb, ) in cursor.fetchall():
# check dup
if output in procedOut:
continue
procedOut.add(output)
if output_type == DecoratorConst.Export_pLink_InputOutputType.PIN and output_is_bb == DecoratorConst.Export_Boolean.FALSE:
# this is a oper. find its pOut and add into stack
cursor_outget.execute('SELECT [thisobj] FROM [script_pOut] WHERE [parent] == ?;',
(output_obj, )
)
for (thisobj, ) in cursor_outget.fetchall():
stack.append(thisobj)
else:
# this oper point to non-pIn, should be add into result
result.add(output_obj)
# free cursor and return
cursor.close()
cursor_outget.close()
return tuple(i for i in result)
def __BuildOper(self, tree: DecoratorData.TreeLayout[DecoratorData.OperTreeNode], start_oper: int):
# prepare stack and start condition
stack: collections.deque[IntermediateTreeNode] = collections.deque()
# check whether this BB has been processed
if start_oper not in self.__AllOper:
return
self.__AllOper.remove(start_oper)
# create cursor
cursor: sqlite3.Cursor = self.m_Db.cursor()
# create new layer and insert it
tree.NewLayer(DecoratorData.TreeLayout.NO_REFERENCE_LAYER, DecoratorData.TreeLayout.NO_START_POS_OF_REF_LAYER)
tree.NewItem(self.m_Graph.m_BlockDict[start_oper])
# prepare stack data
start_oper_data: IntermediateTreeNode = IntermediateTreeNode()
start_oper_data.m_LoactedLayer = tree.GetCurrentLayerIndex()
start_oper_data.m_LocatedPos = tree.GetCurrentItemIndex()
cursor.execute("SELECT [input_obj] FROM [script_pLink] WHERE ([output_obj] == ? AND [output_type] == ? AND [input_type] == ? AND [input_is_bb] == ? AND [parent] = ?);",
(start_oper, DecoratorConst.Export_pLink_InputOutputType.PIN, # order pOper's pIn
DecoratorConst.Export_pLink_InputOutputType.POUT, DecoratorConst.Export_Boolean.FALSE, # order pOper's pOut
self.m_Graph.m_GraphCKID, )
)
for (input_obj, ) in cursor.fetchall():
start_oper_data.m_Collection.append(input_obj)
stack.append(start_oper_data)
# start analyze
while len(stack) != 0:
# pick stack and decide whether pop this
stack_entry: IntermediateTreeNode = stack[-1]
if len(stack_entry.m_Collection) == 0:
stack.pop()
continue
# pick a new Oper from collection.
# check whether it need process
oper_id: int = stack_entry.m_Collection[-1]
if oper_id not in self.__AllOper:
stack_entry.m_Collection.pop()
continue
self.__AllOper.remove(oper_id)
# get corresponding tree node
tree_node: DecoratorData.BBTreeNode = self.m_Graph.m_BlockDict[oper_id]
# start proc Oper
# create new stack entry
oper_data: IntermediateTreeNode = IntermediateTreeNode()
# push tree node into tree layout and get corresponding index.
# create new layer according to whether first visit
if stack_entry.m_FirstVisit:
tree.NewItem(tree_node)
oper_data.m_LoactedLayer = stack_entry.m_LoactedLayer
oper_data.m_LocatedPos = stack_entry.m_LocatedPos + 1
# reset first visit
stack_entry.m_FirstVisit = False
else:
tree.NewLayer(stack_entry.m_LoactedLayer, stack_entry.m_LocatedPos)
tree.NewItem(tree_node)
oper_data.m_LoactedLayer = tree.GetCurrentLayerIndex()
oper_data.m_LocatedPos = tree.GetCurrentItemIndex()
# query and fill stack entry data
cursor.execute("SELECT [input_obj] FROM [script_pLink] WHERE ([output_obj] == ? AND [output_type] == ? AND [input_type] == ? AND [input_is_bb] == ? AND [parent] = ?);",
(oper_id, DecoratorConst.Export_pLink_InputOutputType.PIN, # order pOper's pIn
DecoratorConst.Export_pLink_InputOutputType.POUT, DecoratorConst.Export_Boolean.FALSE, # order pOper's pOut
self.m_Graph.m_GraphCKID, )
)
for (output_obj, ) in cursor.fetchall():
oper_data.m_Collection.append(output_obj)
stack.append(oper_data)
cursor.close()
def __BuildBB(self, tree: DecoratorData.TreeLayout[DecoratorData.BBTreeNode], start_bb: int):
# prepare stack and start condition
stack: collections.deque[IntermediateTreeNode] = collections.deque()
# check whether this BB has been processed
if start_bb not in self.__AllBB:
return
self.__AllBB.remove(start_bb)
# create cursor
cursor: sqlite3.Cursor = self.m_Db.cursor()
# create new layer and insert it
tree.NewLayer(DecoratorData.TreeLayout.NO_REFERENCE_LAYER, DecoratorData.TreeLayout.NO_START_POS_OF_REF_LAYER)
tree.NewItem(self.m_Graph.m_BlockDict[start_bb])
# prepare stack data
start_bb_data: IntermediateTreeNode = IntermediateTreeNode()
start_bb_data.m_LoactedLayer = tree.GetCurrentLayerIndex()
start_bb_data.m_LocatedPos = tree.GetCurrentItemIndex()
cursor.execute("SELECT [output_obj] FROM [script_bLink] WHERE ([input_obj] == ? AND [input_type] == ? AND [parent] = ?) ORDER BY [input_index] ASC;",
(start_bb, DecoratorConst.Export_bLink_InputOutputType.OUTPUT, self.m_Graph.m_GraphCKID, )
)
for (output_obj, ) in cursor.fetchall():
start_bb_data.m_Collection.append(output_obj)
stack.append(start_bb_data)
# start analyze
while len(stack) != 0:
# pick stack and decide whether pop this
stack_entry: IntermediateTreeNode = stack[-1]
if len(stack_entry.m_Collection) == 0:
stack.pop()
continue
# pick a new BB from collection.
# check whether it need process
bb_id: int = stack_entry.m_Collection[-1]
if bb_id not in self.__AllBB:
stack_entry.m_Collection.pop()
continue
self.__AllBB.remove(bb_id)
# get corresponding tree node
tree_node: DecoratorData.BBTreeNode = self.m_Graph.m_BlockDict[bb_id]
# start proc BB
# create new stack entry
bb_data: IntermediateTreeNode = IntermediateTreeNode()
# push tree node into tree layout and get corresponding index.
# create new layer according to whether first visit
if stack_entry.m_FirstVisit:
tree.NewItem(tree_node)
bb_data.m_LoactedLayer = stack_entry.m_LoactedLayer
bb_data.m_LocatedPos = stack_entry.m_LocatedPos + 1
# reset first visit
stack_entry.m_FirstVisit = False
else:
tree.NewLayer(stack_entry.m_LoactedLayer, stack_entry.m_LocatedPos)
tree.NewItem(tree_node)
bb_data.m_LoactedLayer = tree.GetCurrentLayerIndex()
bb_data.m_LocatedPos = tree.GetCurrentItemIndex()
# query and fill stack entry data
cursor.execute("SELECT [output_obj] FROM [script_bLink] WHERE ([input_obj] == ? AND [input_type] == ? AND [belong_to] = ?) ORDER BY [input_index] ASC;",
(bb_id, DecoratorConst.Export_bLink_InputOutputType.OUTPUT, self.m_Graph.m_GraphCKID, )
)
for (output_obj, ) in cursor.fetchall():
bb_data.m_Collection.append(output_obj)
stack.append(bb_data)
# todo: executing oper finder for current bb
cursor.close()
def __ProcActiveBB(self):
cursor: sqlite3.Cursor = self.m_Db.cursor()
cursor.execute("SELECT [output_obj] FROM [script_bLink] WHERE ([input_obj] == ? AND [input_type] == ? AND [belong_to] = ?) ORDER BY [input_index] ASC;",
(self.m_Graph.m_GraphCKID, DecoratorConst.Export_bLink_InputOutputType.INPUT, self.m_Graph.m_GraphCKID, )
)
for (output_obj, ) in cursor.fetchall():
self.__BuildBB(self.m_Graph.m_ActiveBB, output_obj)
cursor.close()
def __ProcPassiveBB(self):
cursor: sqlite3.Cursor = self.m_Db.cursor()
while len(self.__AllBB) != 0:
self.__BuildBB(self.m_PassiveBBLayer, self.__GetOneFromSet(self.__AllBB))
cursor.close()
def __ProcPassiveOper(self):
pass