def enterRead_config_call(self, ctx: ConfigParser.Read_config_callContext): #print('enterRead_config_call: ') readType = ctx.getChild(2).getText() readPath = ctx.path().getText() readVar = ctx.id_str().getText() #print(' ' + readType + ' ' + readPath + ' ' + readVar) rNode = Cm.CfgReadNode(readPath, readType, None) #print('enterRead_config_call: findVar name=' + readVar + ", ret=" + str(Cm.BaseCfgNode.peekNode().findVar(readVar, True))) rVar = Cm.CfgVariable.resolveLhsExpression( readVar, Cm.CfgNumDataType) # read return variable Cm.CfgAssign(rVar, Cm.ConfigAssignType.EQ, rNode)
def enterWhile_loop(self, ctx: ConfigParser.While_loopContext): #print('enterWhile_loop: ') leftOp = ctx.value(0).getText() rightOp = ctx.value(1).getText() compareOp = ctx.compare_op().getText() #print(' ' + compareOp + ' ' + rightOp) leftVal = Cm.CfgVariable.resolveRhsExpression( leftOp, Cm.CfgNumDataType) # numeric var or instance rightVal = Cm.CfgVariable.resolveRhsExpression( rightOp, Cm.CfgNumDataType) # numeric var or instance whileCompare = Cm.CfgCompare(leftVal, compareOp, rightVal) Cm.CfgWhileNode(whileCompare)
def enterFor_loop(self, ctx: ConfigParser.For_loopContext): iterName = ctx.id_str().getText() isNumeric = ctx.num_range() is not None if isNumeric: rangeStart = ctx.num_range().value(0).getText() rangeEnd = ctx.num_range().value(1).getText() #print('enterFor_loop: numeric var name=' + iterName + ", range_start=" + str(rangeStart)+ ", range_end=" + str(rangeEnd)) Cm.CfgNumericForNode(iterName, rangeStart, rangeEnd) else: # else a path for loop path = ctx.path().getText() #print('enterFor_loop: path var name=' + iterName + ", path=" + str(path)) Cm.CfgPathForNode(iterName, path)
def enterPoll_config_call(self, ctx: ConfigParser.Poll_config_callContext): #print('enterPoll_config_call: ') readType = ctx.getChild(0).getText() readPath = ctx.path().getText() pollOp = ctx.compare_op().getText() pollVal = ctx.value(0).getText() #print(' ' + readType + ' ' + readPath + ' ' + pollOp + ' ' + pollVal) rtype = Cm.CfgPathHierType.resolve( readType) # poll is compare of read value, so explicitly set type rNode = Cm.CfgReadNode(readPath, rtype, None) pVal = Cm.CfgVariable.resolveRhsExpression( pollVal, Cm.CfgNumDataType) # read compares to a numeric var or instance whileCompare = Cm.CfgCompare(rNode, pollOp, pVal) Cm.CfgWhileNode(whileCompare)
def enterDefault_case_block(self, ctx: ConfigParser.Default_case_blockContext): Cm.CfgCaseBlockNode.addChoice('default') #print('enterDefault_case_block: choice=default, choices=' + str(Cm.CfgCaseBlockNode._currentChoices)) if ctx.block_statement( ): # if block has statements, these apply to all preceeding choices Cm.CfgCaseBlockNode()
def enterLabeled_case_block(self, ctx: ConfigParser.Labeled_case_blockContext): choiceValName = ctx.id_str().getText() Cm.CfgCaseBlockNode.addChoice(choiceValName) #print('enterLabeled_case_block: choice=' + choiceValName + ', choices=' + str(Cm.CfgCaseBlockNode._currentChoices)) if ctx.block_statement( ): # if block has statements, these apply to all preceeding choices Cm.CfgCaseBlockNode()
def pyF1ToWhile(whileNd): ''' extract a reg/field poll from an ast While node - returns new model While node else returns None on no match ''' compNd = whileNd.test if type(compNd) is not ast.Compare: return None compare = __class__.pyF1ToCfgCompare(compNd) if not compare.isValid(): return None return Cm.CfgWhileNode(compare, whileNd)
def enterSimple_assign(self, ctx: ConfigParser.Simple_assignContext): varName = ctx.id_str().getText() rhsValName = ctx.value().getText() assignVar = Cm.CfgVariable.resolveLhsExpression( varName, Cm.CfgNumDataType) # TODO assign numeric only for now rhsVal = Cm.CfgVariable.resolveRhsExpression( rhsValName, Cm.CfgNumDataType) # TODO assign numeric only for now #print('enterSimple_assign: var=' + varName + ', rhsValName=' + rhsValName) Cm.CfgAssign(assignVar, Cm.ConfigAssignType.EQ, rhsVal)
def enterWrite_config_call(self, ctx: ConfigParser.Write_config_callContext): #print('enterWrite_config_call: ') writeType = ctx.getChild(0).getText() writePath = ctx.path().getText() writeVal = ctx.value().getText() #print(' ' + writeType + ' ' + writePath + ' ' + writeVal) isRmw = True if writeType == 'rmwField' else False Cm.CfgWriteNode(writePath, writeVal, writeType, isRmw, None)
def pyF1ToCfgCompare(compNd): ''' extract a compare node - returns new model node else returns None on no match ''' left = __class__.pyF1ToCfgData(compNd.left) right = __class__.pyF1ToCfgData(compNd.comparators[0]) op = __class__.pyToCfgCompareOp(compNd) #print(type(compNd).__name__, 'left:', left, 'op:', op, 'right:', right) if op.isSupported(): compNd.__cfg_valid__ = True # tag this ast node as translated return Cm.CfgCompare(left, op, right) # TODO check ops here before creating
def pyF1AddFunctionArgs(node): ''' extract argument list from FunctionDef node and add to current model scope''' #outArgs = [] argsNds = node.args.args for argsNd in argsNds: if argsNd.arg is not 'self': #outArgs.append(argsNd.arg) #print('PyF1NodeVisitor pyF1AddFunctionArgs ' + argsNd.arg) Cm.CfgInputVariable(argsNd.arg, type(None)) # add an untyped input
def pyF1GetWait(exprNd): ''' extract a wait from Expr node - adds node to model, tags ast node as valid, and returns True on match ''' if type(exprNd) is not ast.Expr: return False callNd = exprNd.value if type(callNd) is not ast.Call: return False callStr = __class__.getSourceString(callNd) pat = re.compile('time.sleep\\((\\w+)') mat = pat.match(callStr) if mat: varstr = mat.group(1) #print("....found wait, var=" + varstr) intvar = Cm.CfgNumDataType(varstr) if intvar.isValid(): # TODO allow a var here also intvar.val *= 1000 # convert time.sleep value to ms Cm.CfgWaitNode(intvar, exprNd) exprNd.__cfg_valid__ = True # tag this ast node as translated return True return False
def pyF1GetPrint(exprNd): ''' extract a print from Expr node - adds node to model, tags ast node as valid, and returns True on match ''' if type(exprNd) is not ast.Expr: return False callNd = exprNd.value if type(callNd) is not ast.Call: return False nameNd = callNd.func if type(nameNd) is not ast.Name: return False if nameNd.id is not 'print': return False argsNds = callNd.args argsNd = callNd.args[ 0] # TODO - also need to handle case of multiple print args -> form_vars getName() for each # CASE 1 - single format string with args tuple if type(argsNd) is ast.BinOp: if len(argsNds) != 1: return False opNd = argsNd.op if type(opNd) is not ast.Mod: return False form = [argsNd.left.s] form_vars = [ __class__.getSourceString(i) for i in argsNd.right.elts ] # convert each arg to a string #print("....print form rhs list") #print(form_vars) Cm.CfgPrintNode(form, form_vars, exprNd) # CASE 2 - multi-arg print else: form = [] for argNd in argsNds: if type(argNd) is ast.Str: form.append(argNd.s) else: form.append(__class__.getSourceString(argsNd)) form_vars = [] Cm.CfgPrintNode(form, form_vars, exprNd) exprNd.__cfg_valid__ = True # tag this ast node as translated return True
def visit_FunctionDef(self, node): #print(type(node).__name__, 'found:', node.name) methodNd = Cm.CfgMethodNode(node.name, node) # add method node to model methodNd.comment = self.pyF1GetComment(node) # extract comment self.pyF1AddFunctionArgs(node) # extract arguments ast.NodeVisitor.generic_visit(self, node) omit = __class__.hasInvalidChildren(node) if omit: print('python ' + type(node).__name__ + ' name=' + node.name + ' could not be converted to config model\n') Cm.BaseCfgNode.finishNode( omit) # pop node from active stack and omit if invalid
def pyF1ToCfgData(pyNd): ''' convert a py node to appropriate config model data type - returns None on no match form match is checked in following order: int, path w/ read, path only ''' s = __class__.getSourceString(pyNd) # convert py node to a string data = Cm.CfgNumDataType(s) # try converting to int if data.isValid(): return data hstr = __class__.getHierString(s) if hstr: path = Cm.CfgPathDataType(hstr) # try converting to path if path.isValid(): if path.hasCall(): if path.call == '__get__': path.setField() return Cm.CfgReadNode(path, pyNd) if path.call == '__read__': path.setReg() return Cm.CfgReadNode(path, pyNd) print('invalid call in strToCfgDataType path.val=' + path.val + ', path.call=' + path.call) return None # invalid call found else: return path return None
def enterClass_assign(self, ctx: ConfigParser.Class_assignContext): varName = ctx.path_elem().getText() className = ctx.id_str().getText() classParms = ctx.call_parms().getText() assignVar = Cm.CfgVariable.resolveLhsExpression( varName, Cm.CfgClassNode ) # read return variable - special case using CfgClass rather than data type foundClass = Cm.CfgClassNode.findClass( className) # find the class that is being called #print('enterClass_assign: var=' + varName + ', cfgClass=' + className + ', parms=' + classParms + ', foundClass=' + foundClass.name) # extract parms and check vs class signature resolvedInputList = foundClass.verifyInputParms( classParms, Cm.BaseCfgNode.peekNode()) assignVar.val = (foundClass, resolvedInputList) Cm.CfgAssign(assignVar, Cm.ConfigAssignType.EQ, foundClass)
def pyF1GetWrite(assignNd): ''' extract a reg write from Assign node - adds node to model, tags ast node as valid, and returns True on match ''' if type(assignNd) is not ast.Assign: return False # extract assign targets and paths #paths = [__class__.getSourceString(i) for i in assignNd.targets] # convert each target to a string if len(assignNd.targets) != 1: # only 1 lhs allowed per assign return False path = __class__.pyF1ToCfgData(assignNd.targets[0]) #print('found write path=' + targ_path) value = __class__.getSourceString(assignNd.value) if type(path) is Cm.CfgPathDataType: Cm.CfgWriteNode(path, value, assignNd) assignNd.__cfg_valid__ = True # tag this ast node as translated return True return False
def enterCase_statement(self, ctx: ConfigParser.Case_statementContext): selectVarName = ctx.id_str().getText() Cm.CfgCaseNode(selectVarName)
def enterValue_def(self, ctx: ConfigParser.Value_defContext): Cm.CfgInputVariable(ctx.id_str().getText(), Cm.CfgNumDataType)
def enterBool_def(self, ctx: ConfigParser.Bool_defContext): Cm.CfgInputVariable(ctx.id_str().getText(), Cm.CfgBoolDataType)
def enterPath_def(self, ctx: ConfigParser.Path_defContext): Cm.CfgInputVariable(ctx.id_str().getText(), Cm.CfgPathDataType)
def __init__(self): self.rootCfgNode = Cm.HierCfgNode() # add root node to model
def enterClass_def(self, ctx: ConfigParser.Class_defContext): name = ctx.id_str().getText() #print("enter class_def: " + name) classNd = Cm.CfgClassNode(name) # add class node to model self.addComment(classNd) # extract comment
def enterMethod_def(self, ctx: ConfigParser.Method_defContext): name = ctx.id_str().getText() #print("enter method_def: " + name) methodNd = Cm.CfgMethodNode(name) # add method node to model self.addComment(methodNd) # extract comment
def enterMethod_call(self, ctx: ConfigParser.Method_callContext): callName = ctx.path_elem().getText() classInstName = ctx.path(0).getText() if ctx.path() else None #if not callName.isidentifier(): # TODO parmList = ctx.call_parms().getText() Cm.CfgMethodCall(classInstName, callName, parmList)
def enterRoot(self, ctx: ConfigParser.RootContext): self.rootCfgNode = Cm.HierCfgNode() # add root node to model
def visit_ClassDef(self, node): #print(type(node).__name__, 'found:', node.name) classNd = Cm.CfgClassNode(node.name, node) # add class node to model classNd.comment = __class__.pyF1GetComment(node) # extract comment ast.NodeVisitor.generic_visit(self, node) Cm.BaseCfgNode.finishNode(False) # pop node from active stack