def visitSql_script(self, ctx: PlSqlParser.Sql_scriptContext): body = self.visitChildren(ctx) add_no_repeat(self.pkgs_calls_found, [PKG_PLGLOBALS, PKG_PLHELPER, PKG_PLCURSOR]) imports = self.create_imports() body = imports + body return ast.Module(body=body)
def visitCursor_declaration(self, ctx: PlSqlParser.Cursor_declarationContext): cursor_params = [ self.visitChildren(param)[0].id for param in ctx.parameter_spec() ] visitor = ScriptVisitor() visitor.vars_declared = self.vars_declared + cursor_params ret = visitor.visitChildren(ctx) ret = deque(ret) name: ast.Name = ret.popleft() sql: SQL = None sql_vars = [] for param in list(ret): if isinstance(param, SQL): sql = param elif isinstance(param, SQL_VAR): sql_var = ast.Str(s=param.varname) sql_vars.append(sql_var) else: continue ret.remove(param) cursor_params = [ast.Str(i) for i in cursor_params] add_no_repeat(self.vars_declared, name.id) return ast.Assign(targets=[name], value=ast.Call(func=ast.Attribute( value=ast.Name(id=PKG_PLCURSOR), attr="CURSOR"), args=[ ast.Str(sql.sql), ast.List(elts=sql_vars), ast.List(elts=cursor_params) ], keywords=[]))
def manual_visitProcedure_body(self, ctx: PlSqlParser.Procedure_bodyContext): args_names: List[str] = [ param.parameter_name().getText().upper() for param in ctx.parameter() ] add_no_repeat(self.vars_declared, args_names) ret = self.visitChildren(ctx) ret = deque(ret) name: ast.Name = ret.popleft() args = [] while True: arg = ret[0] if not isinstance(arg, ast.arg): break args.append(arg) ret.popleft() body = ret for item in list(body): if isinstance(item, TYPE): # is a function definition. this is the return type body.remove(item) break for i, item in enumerate(body): # everything has to be an expression? if isinstance(item, ast.Expr): continue body[i] = ast.Expr(value=item) args = ast.arguments(args=args, defaults=[], vararg=None, kwarg=None) return ast.FunctionDef(name=name.id, args=args, body=body, decorator_list=[], returns=None)
def visitCreate_function_body( self, ctx: PlSqlParser.Create_function_bodyContext): visitor = ScriptVisitor() # FIXME: the function being processed should be added to vars_declared too, in case of recursivity visitor.vars_declared = self.vars_declared.copy() ret = visitor.visitChildren(ctx) ret = deque(ret) name = ret.popleft() add_no_repeat(self.vars_declared, name.id) args = [] for expr in list(ret): if isinstance(expr, ast.arg): args.append(expr) elif isinstance(expr, TYPE): pass else: continue ret.remove(expr) args = ast.arguments(args=args, defaults=[], vararg=None, kwarg=None) body = ret return ast.FunctionDef(name=name.id, args=args, body=body, decorator_list=[], returns=None)
def visitProcedure_body(self, ctx: PlSqlParser.Procedure_bodyContext): visitor = ScriptVisitor() visitor.pkg_name = self.pkg_name visitor.vars_in_package = self.vars_in_package ret = visitor.manual_visitProcedure_body(ctx) add_no_repeat(self.vars_declared, ret.name) add_no_repeat(self.pkgs_calls_found, visitor.pkgs_calls_found) return ret
def visitType_spec(self, ctx: PlSqlParser.Type_specContext): if ctx.PERCENT_TYPE(): return None elif ctx.PERCENT_ROWTYPE(): add_no_repeat(self.pkgs_calls_found, TYPE_PLRECORD) return TYPE(ast.Name(id=TYPE_PLRECORD)) elif ctx.type_name(): type_name = self.visitChildren(ctx)[0] return TYPE(type_name) return None
def visitSeq_of_declare_specs( self, ctx: PlSqlParser.Seq_of_declare_specsContext): ret = self.visitChildren(ctx) declared_vars = [] for expr in ret: if isinstance(expr, ast.Assign): declared_vars.append(expr.targets[0].id) elif isinstance(expr, ast.FunctionDef): declared_vars.append(expr.name) add_no_repeat(self.vars_declared, declared_vars) return ret
def visitVariable_declaration( self, ctx: PlSqlParser.Variable_declarationContext): ret = self.visitChildren(ctx) ret = deque(ret) name: ast.Name = ret.popleft() value = ast.Call(func=ast.Name(id="m"), args=[], keywords=[]) add_no_repeat(self.vars_declared, name.id) if ret and isinstance(ret[0], TYPE): the_type = ret.popleft().the_type value = ast.Call(func=the_type, args=[], keywords=[]) if ret: value = ret.popleft() return ast.Assign(targets=[name], value=value)
def visitCursor_loop_param(self, ctx: PlSqlParser.Cursor_loop_paramContext): target = ctx.index_name().getText().upper() # declare the variable for being recognized by the children add_no_repeat(self.vars_declared, target) ret = self.visitChildren(ctx) target, lower, upper = ret return ast.For(target=ast.Name(id=target), iter=ast.Call(func=ast.Name(id="mrange"), args=[lower, upper], keywords=[]), body=[], orelse=[])
def add_object_to_imports(self, the_object): name = the_object while True: if isinstance(name, str): if name != self.pkg_name and name not in self.vars_declared: add_no_repeat(self.pkgs_calls_found, name) break elif isinstance(name, ast.Call): name = name.func elif isinstance(name, ast.Attribute): name = name.value elif isinstance(name, ast.Name): name = name.id else: raise NotImplementedError( f"unsupported object to import {name}")
def visitCreate_package(self, ctx: PlSqlParser.Create_packageContext): self.vars_declared = self.vars_in_package ret = self.visitChildren(ctx) ret = deque(ret) name: str = ret.popleft().id if ret: label = ret[-1] if isinstance(label, ast.Name) and label.id == name: ret.pop() name = get_spec_classname_by_classname(name) body = ret for item in body: if isinstance(item, ast.Assign): add_no_repeat(self.vars_declared, item.targets[0].id) if not body: body.append(ast.Pass()) return ast.ClassDef(name=name, body=body, decorator_list=[], bases=[])
def visitCreate_package_body(self, ctx: PlSqlParser.Create_package_bodyContext): self.pkg_name = name = ctx.package_name()[0].getText().upper() add_no_repeat(self.vars_declared, name) self.vars_in_package = self.vars_declared ret = self.visitChildren(ctx) spec_classname = get_spec_classname_by_classname(name) if ret: label = ret[-1] if isinstance(label, ast.Name) and label.id == name: ret.pop() body = ret[1:] # we already had the name for item in body: if isinstance(item, ast.FunctionDef): item.decorator_list.append(ast.Name(id="staticmethod")) return ast.ClassDef(name=name, body=body, decorator_list=[], bases=[ast.Name(id=spec_classname)])
def visitType_declaration(self, ctx: PlSqlParser.Type_declarationContext): ret = self.visitChildren(ctx) ret = deque(ret) type_name = ret.popleft() targets = [type_name] add_no_repeat(self.vars_declared, type_name.id) if ctx.table_type_def(): value = ast.Name(id=TYPE_PLTABLE) if ret and isinstance(ret[0], TYPE): the_type = ret.popleft() the_type = the_type.the_type value = ast.Call(func=ast.Name(id=TYPE_PLTABLE_OF), args=[the_type], keywords=[]) add_no_repeat(self.pkgs_calls_found, TYPE_PLRECORD) add_no_repeat(self.pkgs_calls_found, TYPE_PLTABLE) return ast.Assign(targets=targets, value=value) if ctx.record_type_def(): add_no_repeat(self.pkgs_calls_found, TYPE_PLRECORD) return ast.Assign(targets=targets, value=ast.Name(id=TYPE_PLRECORD)) raise NotImplementedError(f"unsupported Type_declaration: {ret}")