Files
hakorune/src/llvm_py/mir_reader.py
Selfhosting Dev ef44801fa6 Python LLVM backend implementation (experimental)
- Created llvmlite-based LLVM backend in src/llvm_py/
- Implemented all MIR14 instructions (const, binop, jump, branch, ret, compare, phi, call, boxcall, externcall, typeop, newbox, safepoint, barrier)
- Experimental LoopForm support
- ~2000 lines of clean Python code vs complex Rust/inkwell
- Useful for PHI/SSA validation and rapid prototyping
- Added documentation to CLAUDE.md

This was created while waiting for ChatGPT's investigation of BuilderCursor issues.
2025-09-12 20:55:13 +09:00

142 lines
4.1 KiB
Python

"""
MIR JSON Reader
Parses Nyash MIR JSON format into Python structures
"""
from dataclasses import dataclass
from typing import Dict, List, Any, Optional, Union, Tuple
from enum import Enum
class MirType(Enum):
"""MIR type enumeration"""
VOID = "void"
I64 = "i64"
F64 = "f64"
BOOL = "bool"
STRING = "string"
BOX = "box"
ARRAY = "array"
MAP = "map"
PTR = "ptr"
@dataclass
class MirFunction:
"""MIR function representation"""
name: str
params: List[Tuple[str, MirType]]
return_type: MirType
blocks: Dict[int, 'MirBlock']
entry_block: int
@dataclass
class MirBlock:
"""MIR basic block"""
id: int
instructions: List['MirInstruction']
terminator: Optional['MirInstruction']
@dataclass
class MirInstruction:
"""Base MIR instruction"""
kind: str
# Common fields
dst: Optional[int] = None
# Instruction-specific fields
value: Optional[Any] = None # For Const
op: Optional[str] = None # For BinOp/Compare
lhs: Optional[int] = None # For BinOp/Compare
rhs: Optional[int] = None # For BinOp/Compare
cond: Optional[int] = None # For Branch
then_bb: Optional[int] = None
else_bb: Optional[int] = None
target: Optional[int] = None # For Jump
box_val: Optional[int] = None # For BoxCall
method: Optional[str] = None
args: Optional[List[int]] = None
def parse_mir_json(data: Dict[str, Any]) -> Dict[str, MirFunction]:
"""Parse MIR JSON into Python structures"""
functions = {}
# Parse each function
for func_name, func_data in data.get("functions", {}).items():
# Parse parameters
params = []
for param in func_data.get("params", []):
params.append((param["name"], MirType(param["type"])))
# Parse blocks
blocks = {}
for block_id, block_data in func_data.get("blocks", {}).items():
bid = int(block_id)
# Parse instructions
instructions = []
for instr_data in block_data.get("instructions", []):
instr = parse_instruction(instr_data)
instructions.append(instr)
# Parse terminator
terminator = None
if "terminator" in block_data:
terminator = parse_instruction(block_data["terminator"])
blocks[bid] = MirBlock(bid, instructions, terminator)
# Create function
func = MirFunction(
name=func_name,
params=params,
return_type=MirType(func_data.get("return_type", "void")),
blocks=blocks,
entry_block=func_data.get("entry_block", 0)
)
functions[func_name] = func
return functions
def parse_instruction(data: Dict[str, Any]) -> MirInstruction:
"""Parse a single MIR instruction"""
kind = data["kind"]
instr = MirInstruction(kind=kind)
# Copy common fields
for field in ["dst", "value", "op", "lhs", "rhs", "cond",
"then_bb", "else_bb", "target", "box_val", "method"]:
if field in data:
setattr(instr, field, data[field])
# Handle args array
if "args" in data:
instr.args = data["args"]
return instr
class MIRReader:
"""MIR JSON reader wrapper"""
def __init__(self, mir_json: Dict[str, Any]):
self.mir_json = mir_json
self.functions = None
def get_functions(self) -> List[Dict[str, Any]]:
"""Get functions in the expected format for llvm_builder"""
if self.functions is not None:
return self.functions
# Convert from the existing JSON format to what llvm_builder expects
self.functions = []
funcs = self.mir_json.get("functions", [])
if isinstance(funcs, list):
# Already in list format
self.functions = funcs
elif isinstance(funcs, dict):
# Convert dict format to list
for name, func_data in funcs.items():
func_data["name"] = name
self.functions.append(func_data)
return self.functions