| 201 | |
| 202 | |
| 203 | class FunctionEmitterVisitor(OpVisitor[None]): |
| 204 | def __init__( |
| 205 | self, emitter: Emitter, declarations: Emitter, source_path: str, module_name: str |
| 206 | ) -> None: |
| 207 | self.emitter = emitter |
| 208 | self.names = emitter.names |
| 209 | self.declarations = declarations |
| 210 | self.source_path = source_path |
| 211 | self.module_name = module_name |
| 212 | self.literals = emitter.context.literals |
| 213 | self.rare = False |
| 214 | # Next basic block to be processed after the current one (if any), set by caller |
| 215 | self.next_block: BasicBlock | None = None |
| 216 | # Ops in the basic block currently being processed, set by caller |
| 217 | self.ops: list[Op] = [] |
| 218 | # Current index within ops; visit methods can increment this to skip/merge ops |
| 219 | self.op_index = 0 |
| 220 | |
| 221 | def temp_name(self) -> str: |
| 222 | return self.emitter.temp_name() |
| 223 | |
| 224 | def visit_goto(self, op: Goto) -> None: |
| 225 | if op.label is not self.next_block: |
| 226 | self.emit_line("goto %s;" % self.label(op.label)) |
| 227 | |
| 228 | def error_value_check(self, value: Value, compare: str) -> str: |
| 229 | typ = value.type |
| 230 | if isinstance(typ, RTuple): |
| 231 | # TODO: What about empty tuple? |
| 232 | return self.emitter.tuple_undefined_check_cond( |
| 233 | typ, self.reg(value), self.c_error_value, compare |
| 234 | ) |
| 235 | elif isinstance(typ, RVec): |
| 236 | # Error values for vecs are represented by a negative length. |
| 237 | vec_compare = ">=" if compare == "!=" else "<" |
| 238 | return f"{self.reg(value)}.len {vec_compare} 0" |
| 239 | else: |
| 240 | return f"{self.reg(value)} {compare} {self.c_error_value(typ)}" |
| 241 | |
| 242 | def visit_branch(self, op: Branch) -> None: |
| 243 | true, false = op.true, op.false |
| 244 | negated = op.negated |
| 245 | negated_rare = False |
| 246 | if true is self.next_block and op.traceback_entry is None: |
| 247 | # Switch true/false since it avoids an else block. |
| 248 | true, false = false, true |
| 249 | negated = not negated |
| 250 | negated_rare = True |
| 251 | |
| 252 | neg = "!" if negated else "" |
| 253 | cond = "" |
| 254 | if op.op == Branch.BOOL: |
| 255 | expr_result = self.reg(op.value) |
| 256 | cond = f"{neg}{expr_result}" |
| 257 | elif op.op == Branch.IS_ERROR: |
| 258 | compare = "!=" if negated else "==" |
| 259 | cond = self.error_value_check(op.value, compare) |
| 260 | else: |
no outgoing calls
searching dependent graphs…