def stub_on_error(self, context: Context, lhs: List[Stmt], rhs: List[Stmt]): assert len(lhs) == 0 assert len(rhs) >= 2 if context.last_exception_index + context.exception_ttl < context.stmt_index: raise LookupError( f"exception could not handle, it is too far, " f"current index {context.stmt_index}, last {context.last_exception_index}, " f"ttl: {context.exception_ttl}") error_handler = f'Stub{do_capitalize(context.fn.name)}ErrorHandler{context.stmt_index}' if error_handler in context.extended_methods: raise KeyError( f"method {error_handler} is already exists in current struct scope" ) capturing = rhs[2:] _, func_sign_body = rhs[1].body_content.split('{', maxsplit=1) capturing_args = ', '.join( map( lambda st: f'{st.ident.name} {self.find_local_type(context, st.ident)}', capturing)) context.extended_methods[error_handler] = OpaqueExp.create( f'func ({context.fn.recv.name} {context.fn.recv.type}) {error_handler}(err error, ' f'{capturing_args}) error {{{func_sign_body}') capturing_input = ','.join(map(lambda st: st.ident.name, capturing)) self.get_promise_handler( context, 'catch', context.last_exception_index ).append( OpaqueExp.create( f'err = {context.fn.recv.name}.{error_handler}(err, {capturing_input})' )) return None, []
def handle_function(self, func: FuncDesc): items = [] opaque_items_list = [] context = Context(fn=func, context_vars=dict(), local_vars=dict(), insert_items_list=list(), extended_methods=dict(), service_methods=dict(), insert_points=dict()) for i, item in enumerate(func.body.items): context.insert_items_list.append(context.insert_points) context.stmt_index = i new_items = [] self.handle_stmt(item, context, new_items) opaque_items_list.append( filter(lambda o_item: isinstance(o_item, OpaqueExp), new_items)) items.extend(new_items) context.insert_points = dict() for opaque_items, insert_points in zip(opaque_items_list, context.insert_items_list): for x_item in opaque_items: for k, v in insert_points.items(): x_item.opaque = x_item.opaque.replace( k, '\n'.join(map(str, v))) func.body.items = items res = [] if context.created_context: fields = [] for k in context.context_vars.values(): fields.append(f'{k.name} {k.type}') fields = '\n'.join(fields) res.append( OpaqueExp.create( f"""type {func.name}Context struct {{\n{fields}\n}}""")) interface_sub_services = [] for service_name, value in context.service_methods.items(): _, _, key = value method_name = self.resolve_service_method_handler( context, service_name + 'Service', context.fn.name, key) service_name = f"{func.name}{key or 'Self'}Service" res.append( OpaqueExp.create(f"""\ntype {service_name} interface {{ {method_name}(context *{func.name}Context) (err error)\n}}""")) interface_sub_services.append(service_name) interface_sub_services = '\n'.join(interface_sub_services) res.append( OpaqueExp.create( f"""\ntype {func.name}Service interface {{\n{interface_sub_services}\n}}""" )) res.extend(context.extended_methods.values()) res.append(func) return res
def stub_do_get_id(self, context: Context, lhs: List[Stmt], k: str): id_name = lhs[0].ident.name.title() res = self.must_create_context(context, []) res = self.must_create_ok_decl(context, res) context.context_vars[id_name] = Object.create(id_name, 'uint') res.append( OpaqueExp.create( f"context.{id_name}, ok = snippet.ParseUint(c, {k})")) res.append(OpaqueExp.create("if !ok {\nreturn\n}")) return None, res
def stub_do_get_id(self, context: Context, lhs: List[Stmt], k: str): raw = lhs[0].ident.name id_name = do_capitalize(raw) res = self.must_create_context(context, []) res = self.must_create_ok_decl(context, res) context.context_vars[id_name] = Object.create(id_name, 'uint') context.local_vars[raw] = Object.create(raw, 'uint') res.append(OpaqueExp.create(f"var {raw} uint")) res.append(OpaqueExp.create(f"{raw}, ok = snippet.ParseUint(c, {k})")) res.append(OpaqueExp.create("if !ok {\nreturn\n}")) res.append(OpaqueExp.create(f"stubContext.{id_name} = {raw}")) return None, res
def must_create_context(self, context: Context, res): _ = self if not context.created_context: context.created_context = True res.append( OpaqueExp.create(f"var stubContext {context.fn.name}Context")) return res
def global_bool_handler(self, context: Context, a: AssignExp, res): print(a) # todo context.last_excetion_ok_index = context.stmt_index if_stmt = OpaqueExp.create( f'{self.create_promise_handler(context, "catch_ok")}\n' f"if !ok {{\nreturn\n}}") return res + [a, if_stmt]
def stub_bind(self, context: Context, lhs: List[Stmt], rhs: List[Stmt]): assert len(lhs) == 0 res = [] for binding in rhs: bc = binding.body_content bc.strip('&').strip() if bc not in context.local_vars: raise KeyError(f'can not bind {repr(binding)}') res = self.must_create_context(context, res) local_var = context.local_vars[bc] cc = do_capitalize(bc) context.context_vars[cc] = Object.create(cc, local_var.type) res.append(OpaqueExp.create(f"stubContext.{cc} = {bc}")) res.append( OpaqueExp.create( f"if !snippet.BindRequest(c, {bc}) {{\nreturn\n}}")) return None, res
def stub_do_abort_if_hint(self, context: Context, lhs: List[Stmt], assertion: Stmt, rhs: List[Stmt], hint: str): assert len(lhs) == 0 _ = self rest_args = ','.join(map(str, rhs)) assertion = assertion.body_content return None, [ OpaqueExp.create(f"""if {assertion} {{ snippet.DoReportHintRaw(c, "Assertion Failed: want {escape(assertion)}", {hint}, {rest_args})\nreturn\n}}""" ) ]
def promise_insert_stmts(self, context: Context, _: List[Stmt], rhs: List[Stmt], point_name): _ = self assert len(rhs) == 1 res = [] # todo rhs type rhs = rhs[0].body_content _, rhs = rhs.split('{', maxsplit=1) rhs = rhs.strip()[:-1] self.get_promise_handler(context, point_name).append(OpaqueExp.create(rhs)) return 'Promise', res
def invoking_stub_context(self, context: Context, _: List[Stmt], rhs: List[Stmt]): _ = self res = [] for binding in rhs: bc = binding.body_content if bc not in context.local_vars: raise KeyError(f'can not serve {repr(binding)}') res = self.must_create_context(context, res) local_var = context.local_vars[bc] tbc = do_capitalize(bc) context.context_vars[tbc] = Object.create(tbc, local_var.type) res.append(OpaqueExp.create(f"stubContext.{tbc} = {bc}")) return 'InvokingStub', res
def stub_do_abort_if_hint(self, context: Context, lhs: List[Stmt], assertion: Stmt, rhs: List[Stmt], hint: str): assert len(lhs) == 0 _ = self rest_args = ','.join(map(str, rhs)) res = [] assertion = str( self.check_replace_stub_variable_exp(context, assertion, res)) if len(res) != 0: raise LookupError(f"input of the assertion is not defined: {res}") return None, [ OpaqueExp.create(f"""if {assertion} {{ snippet.DoReportHintRaw(c, "Assertion Failed: want {escape(assertion)}", {hint}, {rest_args})\nreturn\n}}""" ) ]
def must_create_decl(self, context: Context, decl: Object, res): _ = self if decl.name not in context.local_vars: context.local_vars[decl.name] = decl res.append(OpaqueExp.create(f"var {decl.name} {decl.type}")) return res
def invoking_stub_do_serve(self, context: Context, _: List[Stmt], rhs: List[Stmt], key: Optional[str]): res = [] res = self.must_create_err_decl(context, res) res = self.must_create_context(context, res) last_one = rhs[-1] service_name = context.fn.name + (key or 'Self') serve_handler = self.resolve_service_handler(context, service_name + 'Service', context.fn.name, key) if service_name not in context.service_methods: context.service_methods[service_name] = method_desc = (list(), list(), key) for binding in rhs: bc = binding.body_content tbc = do_capitalize(bc) if tbc in context.context_vars: method_desc[0].append(context.context_vars[tbc]) continue if bc in context.local_vars: local_var = context.local_vars[bc] method_desc[0].append(local_var) context.context_vars[tbc] = Object.create( tbc, local_var.type) if binding != last_one: res.append( OpaqueExp.create(f"stubContext.{tbc} = {bc}")) continue raise KeyError( f'can not bind {repr(binding)} to service method') method_desc[1].append(Object.create('err', 'error')) else: raise NotImplementedError("todo check signature") # method_desc = context.service_methods[service_name] # # if len(method_desc[0]) != len(rhs): # raise TypeError(f"signature not consistent want {method_desc[0]} got {rhs}") # # for i, binding in enumerate(rhs): # bc = binding.body_content # tbc = do_capitalize(bc) # # if tbc in context.context_vars: # method_desc[0][i].append(context.context_vars[tbc]) # # if bc in context.local_vars: # method_desc[0][i].append(context.local_vars[bc]) # raise KeyError(f'can not bind {repr(binding)} to service method') # # method_desc[1].append(Object.create('err', 'error')) if_stmt = [ f"if err = {serve_handler}(&stubContext, ); err != nil {{" f'{self.create_promise_handler(context, "catch")}\n' f'{self.create_promise_handler(context, "finally")}\nsnippet.DoReport(c, err)\nreturn\n}} else {{' ] for binding in rhs: bc = binding.body_content tbc = do_capitalize(bc) if bc in context.local_vars: if_stmt.append(f"{bc} = stubContext.{tbc}") if_stmt.append(f'{self.create_promise_handler(context, "then")}\n' f'{self.create_promise_handler(context, "finally")}}}') res.append(OpaqueExp.create('\n'.join(if_stmt))) return 'Promise', res
def must_create_err_decl(self, context: Context, res): _ = self if not context.created_err: context.created_err = True res.append(OpaqueExp.create(f"var err error")) return res
def must_create_ok_decl(self, context: Context, res): _ = self if not context.created_ok: context.created_ok = True res.append(OpaqueExp.create(f"var ok bool")) return res