def generate_arg_check(name: str, typ: RType, emitter: Emitter, error_code: str, optional: bool = False) -> None: """Insert a runtime check for argument and unbox if necessary. The object is named PyObject *obj_{}. This is expected to generate a value of name arg_{} (unboxed if necessary). For each primitive a runtime check ensures the correct type. """ if typ.is_unboxed: # Borrow when unboxing to avoid reference count manipulation. emitter.emit_unbox('obj_{}'.format(name), 'arg_{}'.format(name), typ, error_code, declare_dest=True, borrow=True, optional=optional) elif is_object_rprimitive(typ): # Object is trivial since any object is valid if optional: emitter.emit_line('PyObject *arg_{};'.format(name)) emitter.emit_line('if (obj_{} == NULL) {{'.format(name)) emitter.emit_line('arg_{} = {};'.format(name, emitter.c_error_value(typ))) emitter.emit_lines('} else {', 'arg_{} = obj_{}; '.format(name, name), '}') else: emitter.emit_line('PyObject *arg_{} = obj_{};'.format(name, name)) else: emitter.emit_cast('obj_{}'.format(name), 'arg_{}'.format(name), typ, declare_dest=True, optional=optional) if optional: emitter.emit_line('if (obj_{} != NULL && arg_{} == NULL) {}'.format( name, name, error_code)) else: emitter.emit_line('if (arg_{} == NULL) {}'.format(name, error_code))
def generate_native_function(fn: FuncIR, emitter: Emitter, source_path: str, module_name: str) -> None: declarations = Emitter(emitter.context, fn.env) body = Emitter(emitter.context, fn.env) visitor = FunctionEmitterVisitor(body, declarations, source_path, module_name) declarations.emit_line('{} {{'.format( native_function_header(fn.decl, emitter))) body.indent() for r, i in fn.env.indexes.items(): if isinstance(r.type, RTuple): emitter.declare_tuple_struct(r.type) if i < len(fn.args): continue # skip the arguments ctype = emitter.ctype_spaced(r.type) init = '' if r in fn.env.vars_needing_init: init = ' = {}'.format(declarations.c_error_value(r.type)) declarations.emit_line('{ctype}{prefix}{name}{init};'.format( ctype=ctype, prefix=REG_PREFIX, name=r.name, init=init)) # Before we emit the blocks, give them all labels for i, block in enumerate(fn.blocks): block.label = i for block in fn.blocks: body.emit_label(block) for op in block.ops: op.accept(visitor) body.emit_line('}') emitter.emit_from_emitter(declarations) emitter.emit_from_emitter(body)