Skip to content

Commit

Permalink
cell & struct expression support;
Browse files Browse the repository at this point in the history
  • Loading branch information
chaoqing committed Feb 7, 2022
1 parent 714a56d commit d9f2f32
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 17 deletions.
60 changes: 43 additions & 17 deletions miss_hit/mh_python.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@
class Python_Visitor(AST_Visitor):
"""Matlab To Python/Numpy output: Python"""

def __init__(self, fd, mh=None, matlab_alias="mp"):
def __init__(self, fd, mh=None, **kwargs):
super().__init__()
self.fd = fd
self.mh = mh
Expand All @@ -58,9 +58,18 @@ def __init__(self, fd, mh=None, matlab_alias="mp"):
self.node_visitor = {
Function_Signature: pass_visitor,
Action: pass_visitor,
Cell_Expression: getattr(self, "matrix_expression_visitor"),
}

self.func_alias = lambda n: f"{matlab_alias}.{n}"
self.options = {
"matlab_alias": "mp",
"generate_main": False,
"inline_mode": False,
"implicit_copy": True,
}
self.options.update(**kwargs)

self.func_alias = lambda n: f"{self.options['matlab_alias']}.{n}"

def __setitem__(self, node, src):
self.node_src[node.uid] = src
Expand Down Expand Up @@ -104,6 +113,13 @@ def visit_end(self, node, n_parent, relation):
def _pass_visitor(self, node: Node, n_parent, relation):
pass

def dynamic_selection_visitor(self, node: Dynamic_Selection, n_parent, relation):
self[node] = f'getfield({self.pop(node.n_prefix)}, {self.pop(node.n_field)})'
# ToDo: miss_hit_core lack support for setfield, e.g. s.(f) = v

def selection_visitor(self, node: Selection, n_parent, relation):
self[node] = f'{self.pop(node.n_prefix)}.{self.pop(node.n_field)}'

def general_for_statement_visitor(
self, node: General_For_Statement, n_parent, relation
):
Expand Down Expand Up @@ -212,35 +228,43 @@ def function_file_visitor(self, node: Function_File, n_parent, relation):
header = "import mat2py as mp\n" "from mat2py.core import *\n"

n_sig = node.l_functions[0].n_sig
is_main = len(n_sig.l_inputs) + len(n_sig.l_outputs) == 0
generate_main = self.options['generate_main'] and (len(n_sig.l_inputs) + len(n_sig.l_outputs) == 0)

l_functions = [self.pop(l) for l in node.l_functions]
if is_main:
if generate_main:
l_functions = [*l_functions[1:], l_functions[0]]

footer = (
(
f'if __name__ == "__main__":\n'
f'{self.indent(f"{n_sig.n_name.t_ident.value}()")}'
)
if is_main
if generate_main
else ""
)

func = "\n".join(l_functions)
self[node] = "\n".join([header, func, footer])
self[node] = "\n".join(
[header, func, footer][(1 if self.options['inline_mode'] else 0):]
).lstrip('\n')

def script_file_visitor(self, node: Script_File, n_parent, relation):
header = "import mat2py as mp\n" "from mat2py.core import *\n"
body = (
f"def main():\n"
f"{self.indent(self.pop(node.n_statements))}\n\n\n"
f'if __name__ == "__main__":\n'
f'{self.indent("main()")}'
)

if self.options['generate_main']:
body = (
f"def main():\n"
f"{self.indent(self.pop(node.n_statements))}\n\n\n"
f'if __name__ == "__main__":\n'
f'{self.indent("main()")}'
)
else:
body = self.pop(node.n_statements)

func = "\n".join([self.pop(l) for l in node.l_functions])
self[node] = "\n".join([header, func, body])
self[node] = "\n".join(
[header, func, body][(1 if self.options['inline_mode'] else 0):]
).lstrip('\n')

def sequence_of_statements_visitor(
self, node: Sequence_Of_Statements, n_parent, relation
Expand All @@ -267,7 +291,8 @@ def compound_assignment_statement_visitor(
def simple_assignment_statement_visitor(
self, node: Simple_Assignment_Statement, n_parent, relation
):
self[node] = f"{self.pop(node.n_lhs)} = {self.pop(node.n_rhs)}"
bra, ket = ("copy(", ")") if self.options['implicit_copy'] and isinstance(node.n_rhs, Identifier) else ("", "")
self[node] = f"{self.pop(node.n_lhs)} = {bra}{self.pop(node.n_rhs)}{ket}"

def function_call_visitor(self, node: Function_Call, n_parent, relation):
args = ", ".join(self.pop(i) for i in node.l_args)
Expand Down Expand Up @@ -368,8 +393,9 @@ def row_list_visitor(self, node: Row_List, n_parent, relation):
node
] = f'{", ".join(self.pop(i) for i in node.l_items)}{"" if no_indent else ", "}'

def matrix_expression_visitor(self, node: Matrix_Expression, n_parent, relation):
self[node] = f"M[{self.pop(node.n_content)}]"
def matrix_expression_visitor(self, node: (Matrix_Expression, Cell_Expression), n_parent, relation):
keyword = {Matrix_Expression: "M", Cell_Expression: "C"}[type(node)]
self[node] = f"{keyword}[{self.pop(node.n_content)}]"
# TODO: be careful with empty func_alias

def unary_operation_visitor(self, node: Unary_Operation, n_parent, relation):
Expand Down Expand Up @@ -484,7 +510,7 @@ def process_wp(cls, wp):
try:
n_cu.visit(
None,
Python_Visitor(fd, wp.mh, matlab_alias=wp.options.matlab_alias),
Python_Visitor(fd, wp.mh, matlab_alias=wp.options.matlab_alias, **wp.extra_options),
"Root",
)
return MH_Python_Result(wp, fd.getvalue())
Expand Down
5 changes: 5 additions & 0 deletions tests/mat2np/basic.m
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
s = struct('f',{'a','b'});
% s.('f') = 5;
disp({s.f, s.('f')});
A = 5i;
A = s;
A=A+3+4i;
disp(' a b " ');
disp('x');
Expand Down

0 comments on commit d9f2f32

Please sign in to comment.