Skip to content

Commit

Permalink
mypyc support #1
Browse files Browse the repository at this point in the history
  • Loading branch information
x0r committed Mar 9, 2024
1 parent a3660f2 commit 96d616c
Show file tree
Hide file tree
Showing 2 changed files with 71 additions and 56 deletions.
108 changes: 61 additions & 47 deletions masm2c/cpp.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
import logging
from typing import TYPE_CHECKING, Any, Optional, Union
from typing import TYPE_CHECKING, Any, Optional, Union, List

from lark.lexer import Token
from lark.tree import Tree
Expand Down Expand Up @@ -101,7 +101,7 @@ def write_declarations(self, procs, context):
class Cpp(Gen, TopDownVisitor):
"""Visitor which can produce C++ equivalents for asm instructions."""

def __init__(self, context: Optional["Parser"]=None, outfile: str="", skip_output: None=None,
def __init__(self, context: "Parser", outfile: str="", skip_output: None=None,
merge_data_segments: bool=True) -> None:
# proc_strategy = SingleProcStrategy()):
""":param context: pointer to Parser data
Expand All @@ -118,12 +118,13 @@ def __init__(self, context: Optional["Parser"]=None, outfile: str="", skip_outpu
self._indirection: IndirectionType = IndirectionType.VALUE

#
self.__proc_done = []
self.__failed = []
self._proc_addr = []
self.__used_data_offsets = set()
self.__methods = []
self.__proc_done: list[str] = []
self.__failed: list[str] = []
self._proc_addr: list[tuple[str,int]] = []
#self.__used_data_offsets = set()
self.__methods: list[str] = []
self.__pushpop_count = 0
self._ismember = False

self.far = False
self.size_changed = False
Expand All @@ -141,7 +142,7 @@ def __init__(self, context: Optional["Parser"]=None, outfile: str="", skip_outpu

self.itisjump = False
self.itiscall = False
self.is_data = False
self.is_data = 0

self.__type_table = {op.DataType.NUMBER: self.produce_c_data_number,
op.DataType.ARRAY: self.produce_c_data_array,
Expand Down Expand Up @@ -242,7 +243,7 @@ def render_data_c(self, segments):
:param segments: a dictionary of segments, where the key is the segment name and the value is the segment object
:return: cpp_file, data_hpp_file, data_cpp_file, hpp_file
"""
self.is_data = True
self.is_data = -1

cpp_file = ""
data_hpp_file = ""
Expand Down Expand Up @@ -292,7 +293,7 @@ def render_data_c(self, segments):
data_cpp_file += _reference_in_data_cpp # reference in _data.cpp
data_hpp_file += type_and_name # headers in _data.h

self.is_data = False
self.is_data = 0
return cpp_file, data_hpp_file, data_cpp_file, hpp_file

def _generate_extern_from_declaration_c(self, _hpp):
Expand All @@ -317,6 +318,7 @@ def _generate_dataref_from_declaration_c(self, _hpp):
return _reference

def memberdir(self, tree: Tree) -> list[str]:
assert isinstance(tree.children, list) and all(isinstance(child, str)for child in tree.children)
return [self.convert_member_(tree.children)]


Expand Down Expand Up @@ -587,9 +589,9 @@ def parse2(self, dst: Expression, src: Expression) -> tuple[str, str]:
src.ptr_size = dst_size
if dst.indirection == IndirectionType.POINTER and dst.element_size == 0 and src_size and not dst.ptr_size:
dst.ptr_size = src_size
dst = self.render_instruction_argument(dst, dst_size, destination=True)
src = self.render_instruction_argument(src, src_size)
return dst, src
dst_str = self.render_instruction_argument(dst, dst_size, destination=True)
src_str = self.render_instruction_argument(src, src_size)
return dst_str, src_str

def _add(self, dst: Expression, src: Expression) -> str:
self.a, self.b = self.parse2(dst, src)
Expand Down Expand Up @@ -633,28 +635,28 @@ def _idiv(self, src: Expression) -> str:
def _jz(self, label: Expression) -> str:
if self.isrelativejump(label):
return "{;}"
label, _ = self.jump_post(label) # TODO
return f"JZ({label})"
label_str, _ = self.jump_post(label) # TODO
return f"JZ({label_str})"

def _jnz(self, label: Expression) -> str:
label, _ = self.jump_post(label)
return f"JNZ({label})"
label_str, _ = self.jump_post(label)
return f"JNZ({label_str})"

def _jbe(self, label: Expression) -> str:
label, _ = self.jump_post(label)
return f"JBE({label})"
label_str, _ = self.jump_post(label)
return f"JBE({label_str})"

def _ja(self, label: Expression) -> str:
label, far = self.jump_post(label)
return f"JA({label})"
label_str, far = self.jump_post(label)
return f"JA({label_str})"

def _jc(self, label: Expression) -> str:
label, far = self.jump_post(label)
return f"JC({label})"
label_str, far = self.jump_post(label)
return f"JC({label_str})"

def _jnc(self, label: Expression) -> str:
label, far = self.jump_post(label)
return f"JNC({label})"
label_str, far = self.jump_post(label)
return f"JNC({label_str})"

"""
def _push(self, regs):
Expand Down Expand Up @@ -722,6 +724,7 @@ def _scas(self, src: Expression) -> str:
self.a = self.render_instruction_argument(src)
size = self.calculate_size(src)
srcr = Token_.find_tokens(src, REGISTER)
assert srcr
return "SCAS(%s,%s,%d)" % (self.a, srcr[0], size)

def process(self):
Expand Down Expand Up @@ -1048,6 +1051,7 @@ def _movs(self, dst: Expression, src: Expression) -> str:
size = self.calculate_size(dst)
dstr, srcr = Token_.find_tokens(dst, REGISTER), Token_.find_tokens(src, REGISTER)
self.a, self.b = self.parse2(dst, src)
assert dstr and srcr
return "MOVS(%s, %s, %s, %s, %d)" % (self.a, self.b, dstr[0], srcr[0], size)

def _repe(self):
Expand All @@ -1062,6 +1066,7 @@ def _lods(self, src: Expression) -> str:
self.a = self.render_instruction_argument(src)
size = self.calculate_size(src)
srcr = Token_.find_tokens(src, REGISTER)
assert srcr
return "LODS(%s,%s,%d)" % (self.a, srcr[0], size)

def _leave(self) -> str:
Expand All @@ -1086,7 +1091,7 @@ def render_instruction_argument(self, expr: Expression, def_size: int = 0, desti
if def_size == 0 and expr.element_size == 0 and expr.indirection != IndirectionType.POINTER:
from .parser import ExprSizeCalculator, Vector
calc = ExprSizeCalculator(init=Vector(0, 0), context=self._context)
def_size, _ = calc.visit(expr) # , result=0)
def_size, _ = calc.visit(expr).values # , result=0)

if def_size and expr.element_size == 0:
expr.element_size = def_size
Expand Down Expand Up @@ -1115,11 +1120,12 @@ def check_parentesis(self, string: str) -> bool:
if res < 0: return False
return True

def _jump(self, cmd: str, label: Expression) -> str:
if self.isrelativejump(label):
def _jump(self, cmd: str, label_expr: Expression) -> str:
if self.isrelativejump(label_expr):
return "{;}"

label, _ = self.jump_post(label)
label, _ = self.jump_post(label_expr)
assert self._context.args
if self._context.args.mergeprocs == "separate" and cmd.upper() == "JMP":
if label == "__dispatch_call":
return "return __dispatch_call(__disp, _state);"
Expand Down Expand Up @@ -1158,7 +1164,8 @@ def _assignment(self, stmt):
self._cmdlabel += f"#undef {dst}\n#define {dst} {self.render_instruction_argument(src)}\n"
return ""

def _equ(self, dst):
def _equ(self, dst: str):
assert isinstance(dst, str)
src = self._context.get_global(dst).value
src.indirection = IndirectionType.VALUE
self._cmdlabel += f"#define {dst} {self.render_instruction_argument(src)}\n"
Expand Down Expand Up @@ -1230,9 +1237,9 @@ def produce_c_data_object(self, data: op.Data):
for i in data.getmembers():
c, _, _ = self.produce_c_data_single_(i)
rc += [c]
rc = "{" + ",".join(rc) + "}"
rc_str = "{" + ",".join(rc) + "}"
rh = f"{data_ctype} {label}"
return rc, rh
return rc_str, rh

def convert_char(self, c: Union[int, str]) -> str:
if isinstance(c, int) and c not in [10, 13]:
Expand Down Expand Up @@ -1337,13 +1344,13 @@ def cpp_mangle_label(self, name: str) -> str:
name = mangle_asm_labels(name)
return name.lower()

def produce_number_c(self, expr: str, radix: int, sign: str, value: str) -> str:
def produce_number_c(self, expr: str, radix: int, sign: int, value: int) -> str:
if radix == 10:
return f"{sign}{value}"
elif radix == 16:
return f"{sign}0x{value}"
elif radix == 2:
return f"{sign}{hex(int(value, 2))}"
return f"{sign}{hex(int(str(value), 2))}"
elif radix == 8:
return f"{sign}0{value}"
else:
Expand All @@ -1352,6 +1359,7 @@ def produce_number_c(self, expr: str, radix: int, sign: str, value: str) -> str:


def INTEGER(self, t: Token) -> list[str]:
assert t.start_pos and t.line is not None and t.column is not None
return [self.produce_number_c("", t.start_pos, t.line, t.column)]

def STRING(self, token: Token) -> list[str]:
Expand Down Expand Up @@ -1384,7 +1392,7 @@ def expr(self, tree: Expression) -> str:

self.element_size = tree.element_size
self._ismember = False
self._need_pointer_to_member = False
self._need_pointer_to_member = []
result = "".join(self.visit(tree.children))
tree.indirection = self._indirection

Expand Down Expand Up @@ -1431,12 +1439,12 @@ def data(self, data: Data) -> tuple[str, str, int]:
c, h, size = self.produce_c_data_single_(data)
c += f", // {data.getlabel()}" + "\n"
h += ";\n"
self.is_data = False
self.is_data = 0
return c, h, size

def LABEL(self, token: Token) -> list[Union[str, Token]]:
if self.is_data:
size = self.is_data if type(self.is_data) == int else 0
size = self.is_data
return [self.convert_label_data(token, size=size)]
return [self.convert_label_(token)]

Expand All @@ -1447,33 +1455,35 @@ def convert_label_data(self, v: Token, size: int=0) -> Union[Token, str]:
return v
if isinstance(g, op.var):
if g.issegment:
v = f"seg_offset({g.name})"
result = f"seg_offset({g.name})"
elif size == 2:
v = f"offset({g.segment},{g.name})"
result = f"offset({g.segment},{g.name})"
elif size == 4:
v = f"far_offset({g.segment},{g.name})"
result = f"far_offset({g.segment},{g.name})"
else:
logging.error(f"Some unknown data size {size} for {g.name}")
elif isinstance(g, (op._equ, op._assignment)):
v = g.original_name
result = g.original_name
elif isinstance(g, (op.label, proc.Proc)):
v = f"m2c::k{g.name.lower()}"
result = f"m2c::k{g.name.lower()}"
elif not isinstance(g, op.Struct):
v = g.offset
logging.debug(v)
return v
result = g.offset
logging.debug(result)
return result

def offsetdir(self, tree: Tree) -> list[Union[str, Token]]: # TODO equ, assign support
name = tree.children[0]

if isinstance(name, lark.Tree) and name.data=="memberdir":
label = name.children
assert isinstance(label, list) and all(isinstance(lab, str) for lab in label)
if (g := self._context.get_global(label[0])) is None:
return label

value = self.convert_member_offset(g, label)
return [lark.Token("memberdir", value)]
value_str = self.convert_member_offset(g, label)
return [lark.Token("memberdir", value_str)]

assert isinstance(name, str)
if (g := self._context.get_global(name)) is None:
return [name]
if isinstance(g, op.var):
Expand All @@ -1491,15 +1501,19 @@ def offsetdir(self, tree: Tree) -> list[Union[str, Token]]: # TODO equ, assign
raise ValueError("Unknown type for offsetdir %s", type(g))

def notdir(self, tree: Tree) -> list[Union[str, Token]]:
assert isinstance(tree.children, list) and all(isinstance(child, str) for child in tree.children)
return ["~", *tree.children]

def ordir(self, tree: Tree) -> list[Union[str, Token]]:
assert isinstance(tree.children, list) and all(isinstance(child, str) for child in tree.children)
return [tree.children[0], " | ", tree.children[1]]

def xordir(self, tree):
assert isinstance(tree.children, list) and all(isinstance(child, str) for child in tree.children)
return [tree.children[0], " ^ ", tree.children[1]]

def anddir(self, tree):
assert isinstance(tree.children, list) and all(isinstance(child, str) for child in tree.children)
return [tree.children[0], " & ", tree.children[1]]

def sizearg(self, tree: Tree) -> list[str]:
Expand Down
19 changes: 10 additions & 9 deletions masm2c/parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,23 +57,24 @@

class Vector:

def __init__(self, *args) -> None:
self.__value = args
def __init__(self, arg1, arg2) -> None:
self.__value: list[int] = [arg1, arg2]

def __add__(self, vec: Optional[Vector]) -> Vector:
if vec is not None:
self.__value = [a + b for a, b in zip(self.__value, vec)]
self.__value = [self.__value[0] + vec.values[0], self.__value[1] + vec.values[1]]
return self

def __mul__(self, other: int) -> Vector:
self.__value = [a * other for a in self]
self.__value = [self.__value[0] * other, self.__value[1] * other]
return self

#@property
#def value(self):
@property
def values(self):
return self.__value

def __getitem__(self, item: int) -> int:
return self.__value[item]
#def __getitem__(self, item: int) -> int:
# return self.__value[item]

def __repr__(self) -> str:
return f"{self.__value}"
Expand Down Expand Up @@ -761,7 +762,7 @@ def datadir_action(self, label: str, type: str, args: Tree, is_string: bool=Fals
#for ex in args:

calc = ExprSizeCalculator(element_size=binary_width, init=Vector(0, 0), context=self)
size, elements = calc.visit(args) #, result=0)
size, elements = calc.visit(args).values
if size == 0:
size = binary_width * elements

Expand Down

0 comments on commit 96d616c

Please sign in to comment.