uslap-query / Code_files /amr_emitter.py
uslap's picture
Upload folder using huggingface_hub
7cc8e29 verified
Raw
History Blame Contribute Delete
11.6 kB
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Ψ£ΩŽΩ…Ω’Ψ± EMITTER β€” AST β†’ Python Source Code
Transforms the Ψ£ΩŽΩ…Ω’Ψ± AST into valid Python source code.
Each Ψ£ΩŽΩ…Ω’Ψ± keyword maps to its Python equivalent via KEYWORDS dict.
"""
import sys
import os
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
try:
from amr_parser import (
parse_source, parse_file, Program, FuncDef, VarDecl, Assignment,
IfStmt, WhileLoop, ForLoop, ReturnStmt, BreakStmt, PassStmt,
DeleteStmt, ImportStmt, TryStmt, RaiseStmt, ExprStmt,
BinOp, UnaryOp, Compare, BoolOp, NotOp, FuncCall, Name, Num, Str,
ListLiteral, DictLiteral, TupleLiteral, Subscript, Attribute,
Constant, Kwarg, ParseError
)
from amr_lexer import LexerError
except ImportError:
from Code_files.amr_parser import (
parse_source, parse_file, Program, FuncDef, VarDecl, Assignment,
IfStmt, WhileLoop, ForLoop, ReturnStmt, BreakStmt, PassStmt,
DeleteStmt, ImportStmt, TryStmt, RaiseStmt, ExprStmt,
BinOp, UnaryOp, Compare, BoolOp, NotOp, FuncCall, Name, Num, Str,
ListLiteral, DictLiteral, TupleLiteral, Subscript, Attribute,
Constant, Kwarg, ParseError
)
from Code_files.amr_lexer import LexerError
# ═══════════════════════════════════════════════════════════════════════
# EMITTER
# ═══════════════════════════════════════════════════════════════════════
class EmitterError(Exception):
pass
class Emitter:
"""Transforms Ψ£ΩŽΩ…Ω’Ψ± AST into Python source code."""
def __init__(self):
self.indent_level = 0
self.lines = []
def indent(self):
return ' ' * self.indent_level
def emit_line(self, code):
self.lines.append(f'{self.indent()}{code}')
def emit(self, node):
"""Emit Python code for an AST node."""
method = f'emit_{type(node).__name__}'
handler = getattr(self, method, None)
if handler is None:
raise EmitterError(f'Ω„ΩŽΨ§ Ω…ΩΨΉΩŽΨ§Ω„ΩΨ¬ Ω„ΩΩ†ΩŽΩˆΩ’ΨΉ Ψ§Ω„ΨΉΩΩ‚Ω’Ψ―ΩŽΨ©: {type(node).__name__}')
return handler(node)
# ─── PROGRAM ──────────────────────────────────────────────────────
def emit_Program(self, node):
# Prepend runtime import
self.lines.append('# -*- coding: utf-8 -*-')
self.lines.append('# Generated from Ψ£ΩŽΩ…Ω’Ψ± source')
self.lines.append('import sys, os')
self.lines.append('sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))')
self.lines.append('from amr_runtime import *')
self.lines.append('')
for stmt in node.body:
self.emit(stmt)
return '\n'.join(self.lines)
# ─── STATEMENTS ───────────────────────────────────────────────────
def emit_FuncDef(self, node):
params = ', '.join(node.params)
self.emit_line(f'def {node.name}({params}):')
self.indent_level += 1
if not node.body:
self.emit_line('pass')
else:
for stmt in node.body:
self.emit(stmt)
self.indent_level -= 1
self.emit_line('') # blank line after function
def emit_VarDecl(self, node):
val = self.emit_expr(node.value)
self.emit_line(f'{node.name} = {val}')
def emit_Assignment(self, node):
target = self.emit_expr(node.target)
val = self.emit_expr(node.value)
self.emit_line(f'{target} = {val}')
def emit_IfStmt(self, node):
cond = self.emit_expr(node.condition)
self.emit_line(f'if {cond}:')
self.indent_level += 1
if not node.body:
self.emit_line('pass')
else:
for stmt in node.body:
self.emit(stmt)
self.indent_level -= 1
for elif_cond, elif_body in node.elif_clauses:
c = self.emit_expr(elif_cond)
self.emit_line(f'elif {c}:')
self.indent_level += 1
if not elif_body:
self.emit_line('pass')
else:
for stmt in elif_body:
self.emit(stmt)
self.indent_level -= 1
if node.else_body:
self.emit_line('else:')
self.indent_level += 1
for stmt in node.else_body:
self.emit(stmt)
self.indent_level -= 1
def emit_WhileLoop(self, node):
cond = self.emit_expr(node.condition)
self.emit_line(f'while {cond}:')
self.indent_level += 1
if not node.body:
self.emit_line('pass')
else:
for stmt in node.body:
self.emit(stmt)
self.indent_level -= 1
def emit_ForLoop(self, node):
iterable = self.emit_expr(node.iterable)
self.emit_line(f'for {node.var} in {iterable}:')
self.indent_level += 1
if not node.body:
self.emit_line('pass')
else:
for stmt in node.body:
self.emit(stmt)
self.indent_level -= 1
def emit_ReturnStmt(self, node):
if node.value is not None:
val = self.emit_expr(node.value)
self.emit_line(f'return {val}')
else:
self.emit_line('return')
def emit_BreakStmt(self, node):
self.emit_line('break')
def emit_PassStmt(self, node):
self.emit_line('pass')
def emit_DeleteStmt(self, node):
target = self.emit_expr(node.target)
self.emit_line(f'del {target}')
def emit_ImportStmt(self, node):
if node.names:
names = ', '.join(node.names)
self.emit_line(f'from {node.module} import {names}')
else:
self.emit_line(f'import {node.module}')
def emit_TryStmt(self, node):
self.emit_line('try:')
self.indent_level += 1
if not node.body:
self.emit_line('pass')
else:
for stmt in node.body:
self.emit(stmt)
self.indent_level -= 1
if node.exc_name:
self.emit_line(f'except (ΨΆΩŽΩ„ΩŽΨ§Ω„, Exception) as {node.exc_name}:')
else:
self.emit_line('except (ΨΆΩŽΩ„ΩŽΨ§Ω„, Exception):')
self.indent_level += 1
if not node.handler_body:
self.emit_line('pass')
else:
for stmt in node.handler_body:
self.emit(stmt)
self.indent_level -= 1
def emit_RaiseStmt(self, node):
if node.value is not None:
val = self.emit_expr(node.value)
self.emit_line(f'raise ΨΆΩŽΩ„ΩŽΨ§Ω„({val})')
else:
self.emit_line('raise')
def emit_ExprStmt(self, node):
expr = self.emit_expr(node.expr)
self.emit_line(expr)
# ─── EXPRESSIONS ──────────────────────────────────────────────────
def emit_expr(self, node):
"""Emit an expression and return as string."""
method = f'emit_expr_{type(node).__name__}'
handler = getattr(self, method, None)
if handler is None:
raise EmitterError(f'Ω„ΩŽΨ§ Ω…ΩΨΉΩŽΨ§Ω„ΩΨ¬ لِΨͺΩŽΨΉΩ’Ψ¨ΩΩŠΨ±: {type(node).__name__}')
return handler(node)
def emit_expr_BinOp(self, node):
left = self.emit_expr(node.left)
right = self.emit_expr(node.right)
return f'({left} {node.op} {right})'
def emit_expr_UnaryOp(self, node):
operand = self.emit_expr(node.operand)
return f'({node.op}{operand})'
def emit_expr_Compare(self, node):
parts = [self.emit_expr(node.left)]
for op, comp in zip(node.ops, node.comparators):
parts.append(op)
parts.append(self.emit_expr(comp))
return f'({" ".join(parts)})'
def emit_expr_BoolOp(self, node):
py_op = 'and' if node.op == 'وَ' else 'or'
parts = [self.emit_expr(v) for v in node.values]
return f'({f" {py_op} ".join(parts)})'
def emit_expr_NotOp(self, node):
operand = self.emit_expr(node.operand)
return f'(not {operand})'
def emit_expr_FuncCall(self, node):
func = self.emit_expr(node.func)
parts = [self.emit_expr(a) for a in node.args]
for kw in node.kwargs:
parts.append(f'{kw.name}={self.emit_expr(kw.value)}')
return f'{func}({", ".join(parts)})'
def emit_expr_Name(self, node):
return node.name
def emit_expr_Num(self, node):
return repr(node.value)
def emit_expr_Str(self, node):
return repr(node.value)
def emit_expr_Constant(self, node):
return repr(node.value)
def emit_expr_ListLiteral(self, node):
elements = ', '.join(self.emit_expr(e) for e in node.elements)
return f'[{elements}]'
def emit_expr_DictLiteral(self, node):
pairs = ', '.join(
f'{self.emit_expr(k)}: {self.emit_expr(v)}'
for k, v in node.pairs
)
return f'{{{pairs}}}'
def emit_expr_TupleLiteral(self, node):
elements = ', '.join(self.emit_expr(e) for e in node.elements)
if len(node.elements) == 1:
return f'({elements},)'
return f'({elements})'
def emit_expr_Subscript(self, node):
obj = self.emit_expr(node.obj)
index = self.emit_expr(node.index)
return f'{obj}[{index}]'
def emit_expr_Attribute(self, node):
obj = self.emit_expr(node.obj)
return f'{obj}.{node.attr}'
# ═══════════════════════════════════════════════════════════════════════
# PUBLIC API
# ═══════════════════════════════════════════════════════════════════════
def emit_source(source, filename='<input>'):
"""Parse Ψ£ΩŽΩ…Ω’Ψ± source and emit Python code."""
ast = parse_source(source, filename)
emitter = Emitter()
return emitter.emit(ast)
def emit_file(filepath):
"""Parse a .Ψ£Ω…Ψ± file and emit Python code."""
ast = parse_file(filepath)
emitter = Emitter()
return emitter.emit(ast)
if __name__ == '__main__':
test_code = '''كُنْ Ψ³ ← Ω₯
اُكْΨͺُبْ(Ψ³ + Ω‘Ω )
Ψ₯ِنْ Ψ³ ΩΩŽΩˆΩ’Ω‚ΩŽ Ω£:
اُكْΨͺُبْ("ΩƒΨ¨ΩŠΨ±")
وَΨ₯ΩΩ„ΩŽΩ‘Ψ§:
اُكْΨͺُبْ("ءغير")
Ψ§ΩΨΉΩ’Ω…ΩŽΩ„Ω’ Ω…ΩŽΨΆΩ’Ψ±ΩΩˆΨ¨(Ω†):
Ψ₯ِنْ Ω† Ψ―ΩΩˆΩ†ΩŽ Ω’:
اِرْجِعْ Ω‘
اِرْجِعْ Ω† * Ω…ΩŽΨΆΩ’Ψ±ΩΩˆΨ¨(Ω† - Ω‘)
اُكْΨͺُبْ(Ω…ΩŽΨΆΩ’Ψ±ΩΩˆΨ¨(Ω₯))
'''
try:
python_code = emit_source(test_code)
print('═══ GENERATED PYTHON ═══')
print(python_code)
print()
print('═══ EXECUTION ═══')
# We'll test execution after runtime is built
except (EmitterError, ParseError, LexerError) as e:
print(f'ERROR: {e}')