From 497846eb4efd637bc535aef03e823ff348153c5c Mon Sep 17 00:00:00 2001 From: victorlei Date: Tue, 1 Jul 2014 20:35:12 +0300 Subject: [PATCH] version 0.25 --- smop/backend.py | 30 +++++++++----------- smop/lexer.py | 16 +++++++---- smop/node.py | 4 +-- smop/parse.py | 10 ++++++- smop/resolve.py | 75 ++++++++++++++++++++++++------------------------- 5 files changed, 72 insertions(+), 63 deletions(-) diff --git a/smop/backend.py b/smop/backend.py index 8a2220dd..751df31a 100644 --- a/smop/backend.py +++ b/smop/backend.py @@ -38,11 +38,11 @@ def _backend(self,level=0): # size([]) # 0 0 if not self.args: - return "np.array([])" + return "matlabarray()" elif any(a.__class__ is node.string for a in self.args): return " + ".join(a._backend() for a in self.args) else: - return "np.array([%s])" % self.args._backend() + return "matlabarray([%s])" % self.args._backend() @extend(node.cellarrayref) @exceptions @@ -163,11 +163,7 @@ def _backend(self,level=0): self.args[2]._backend(), self.args[1]._backend()) if self.op == ":": - #return "arange(%s)" % self.args._backend() - if not self.args: - return ":" - else: - return "%s:%s" % (self.args[0],self.args[1]) + return "range_(%s)" % self.args._backend() if self.op == "end": if self.args: @@ -193,6 +189,7 @@ def _backend(self,level=0): return "%s %s %s" % (self.args[0]._backend(), optable.get(self.op,self.op), self.args[1]._backend()) + import pdb;pdb.set_trace() ret = "%s=" % self.ret._backend() if self.ret else "" return ret+"%s(%s)" % (self.op, ",".join([t._backend() for t in self.args])) @@ -227,17 +224,19 @@ def _backend(self,level=0): @extend(node.let) @exceptions def _backend(self,level=0): - if options.line_numbering: - s = "# %d\n" % self.lineno + level*indent - else: - s = '' +# if options.line_numbering: +# s = "# %d\n" % self.lineno + level*indent +# else: +# s = '' if self.args.__class__ is node.funcall: self.args.nargout = self.nargout - s += "%s=%s" % (self.ret._backend(), - self.args._backend()) if (self.ret.__class__ is node.ident and self.args.__class__ is node.ident): - s += ".copy()" + s = "%s=%s.copy()" % (self.ret._backend(), + self.args._backend()) + else: + s = "%s=%s" % (self.ret._backend(), + self.args._backend()) return s @extend(node.expr_list) @@ -304,8 +303,7 @@ def _backend(self,level=0): @extend(node.ident) @exceptions def _backend(self,level=0): - #return self.name if self.name not in reserved else self.name+"_" - return self.name + return self.name if self.name not in reserved else "_"+self.name @extend(node.stmt_list) @exceptions diff --git a/smop/lexer.py b/smop/lexer.py index 56d2f349..b9df222f 100644 --- a/smop/lexer.py +++ b/smop/lexer.py @@ -56,8 +56,8 @@ def new(): t_LT = r"\<" t_MINUS = r"\-" t_MUL = r"\*" - t_NE = r"~=" - t_NEG = r"\~" + t_NE = r"(~=)|(!=)" + t_NEG = r"\~|!" t_OR = r"\|" t_OROR = r"\|\|" t_PLUS = r"\+" @@ -93,8 +93,11 @@ def t_TRANSPOSE(t): return t def t_STRING(t): - r"'([^']|(''))*'" - t.value = t.value[1:-1].replace("''","'") + """('([^']|(''))*')|("([^"]|(""))*")""" + if t.value[0] == "'": + t.value = t.value[1:-1].replace("''","'") + else: + t.value = t.value[1:-1].replace('""','"') return t def t_IDENT(t): @@ -105,6 +108,9 @@ def t_IDENT(t): # So return=1 is illegal, but foo.return=1 is fine. t.type = "FIELD" return t + if t.value in ("endfunction","endif","endfor"): # octave + t.type = "END_STMT" + return t if t.value == "end": if t.lexer.parens > 0 or t.lexer.brackets > 0 or t.lexer.braces > 0: t.type = "END_EXPR" @@ -198,7 +204,7 @@ def t_NEWLINE(t): return t def t_comment(t): - r"%.*" + r"(%|\#).*" pass diff --git a/smop/node.py b/smop/node.py index 0c01be8c..bcfed61d 100644 --- a/smop/node.py +++ b/smop/node.py @@ -340,10 +340,10 @@ def __str__(self): #"sort", #"strcmp", #"strcmpi", - "sub", # synthetic opcode + "sub", # synthetic opcode for subtract #"sum", "transpose", - "true", + #"true", #"zeros", ] diff --git a/smop/parse.py b/smop/parse.py index d8f30064..f45c255e 100644 --- a/smop/parse.py +++ b/smop/parse.py @@ -392,6 +392,14 @@ def p_let(p): """ assert (isinstance(p[1],(node.ident,node.funcall,node.cellarrayref)) or (isinstance(p[1],node.expr) and p[1].op in (("{}","DOT",".")))) + try: + # a(:) = ... + # ravel(a) = ... + # a[:] = + if p[1].func_expr.name == "ravel": + p[1] = node.arrayref(p[1].args[0],node.expr(":",node.expr_list())) + except: + pass if isinstance(p[1],node.getfield): p[0] = node.setfield(p[1].args[0], p[1].args[1], @@ -569,7 +577,7 @@ def p_funcall_expr(p): len(p[3])==1 and p[3][0].__class__ is node.expr and p[3][0].op == ":" and not p[3][0].args): - # foo(:) + # foo(:) => ravel(foo) p[0] = node.funcall(func_expr=node.ident("ravel"), args=node.expr_list([p[1]])) else: diff --git a/smop/resolve.py b/smop/resolve.py index fcd3f563..d20052e1 100644 --- a/smop/resolve.py +++ b/smop/resolve.py @@ -76,6 +76,8 @@ def do_resolve(t,symtab): # 2. Iterate over ident nodes. Referenced, but undefined nodes # become funcall nodes. # 3. Function declaration require special handling + + # 1. pass I for u in node.postorder(t): if (u.__class__ is node.funcall and u.func_expr.__class__ is node.expr and u.func_expr.op == "."): @@ -88,55 +90,50 @@ def do_resolve(t,symtab): else: u.func_expr.name += "_" + # 2. pass II for u in node.postorder(t.body): if (u.__class__ is node.ident and u.name[0] != "." and u.defs == set() and u.name[-1] != "_"): u.become(node.funcall(func_expr=node.ident(u.name+"_"), args=node.expr_list())) + # 3. special handling for func decl try: t.head.ident.name += "_" except: pass - - for u in node.postorder(t): - if u.__class__ in (node.arrayref,node.cellarrayref): - for i in range(len(u.args)): - cls = u.args[i].__class__ - if cls is node.number: - u.args[i].value -= 1 - elif cls is node.expr and u.args[i].op in ("==","!=","~=","<","=<",">",">="): - pass - elif cls is node.expr and u.args[i].op == ":": - # Colon expression as a subscript becomes a - # slice. Everywhere else it becomes a call to - # the "range" function (done in a separate pass, - # see below). - u.args[i].op = "::" # slice marked with op=:: - if u.args[i].args: - u.args[i].args[0] = node.sub(u.args[i].args[0], - node.number(1)) - # for s in node.postorder(u.args[i]): - # if s.__class__==node.expr and s.op=="end" and not s.args: - # s.args = node.expr_list([u.func_expr,node.number(i)]) + # Done. Referenced, but undefined name references + # converted to funcall objects. For example, + # rand+1 converted to rand()+1 + + if 1: + for u in node.postorder(t): + if u.__class__ in (node.arrayref,node.cellarrayref): + for i in range(len(u.args)): + cls = u.args[i].__class__ + if cls is node.expr and u.args[i].op == ":": + # Colon expression as a subscript becomes a + # slice. Everywhere else it becomes a call to + # the "range" function (done in a separate pass, + # see below). + u.args[i].op = "::" # slice marked with op=:: + for s in node.postorder(u.args[i]): + if s.__class__==node.expr and s.op=="end" and not s.args: + s.args = node.expr_list([u.func_expr,node.number(i)]) + + if 1: + # These range nodes are appended after appending _ to funcall + # objects. HACK use range_ + for u in node.postorder(t): + if u.__class__ == node.expr and u.op == ":" and u.args: + if len(u.args) == 2: + w = node.funcall(node.ident("range_"), + node.expr_list([u.args[0], + u.args[1]])) else: - u.args[i] = node.sub(u.args[i],node.number(1)) - - for u in node.postorder(t): -### if u.__class__ == node.ident and u.defs == set(): -### cls = getattr(node,u.name,None) -### if cls and issubclass(cls,node.builtins): -### u.become(cls()) - if u.__class__ == node.expr and u.op == ":" and u.args: - if len(u.args) == 2: - w = node.funcall(node.ident("range"), - node.expr_list([u.args[0], - node.add(u.args[1],node.number(1))])) - u.become(w) -### else: -### u.become(node.range_(u.args[0], -### node.add(u.args[1],node.number(1)), -### u.args[2])) - + w = node.funcall(node.ident("range_"), + node.expr_list([u.args[0], + u.args[1], + u.args[2]])) #def _fix(tree): # for s in node.postorder(tree): # try: