# SMOP compiler -- Simple Matlab/Octave to Python compiler
# Copyright 2011-2013 Victor Leikehman

import sys,cPickle,glob,os
import getopt
import lexer,parse,resolve,backend,options,rewrite,node,typerank

def usage():
    print "SMOP compiler version 0.22"
    print """Usage: smop [options] file-list
    Options:
    -V --version
    -X --exclude=FILES      Ignore files listed in comma-separated list FILES
    -h --help
    -o --output=FILENAME    By default create file named a.py
    -o- --output=-          Use standard output
    -s --strict             Stop on the first error
    -v --verbose
"""

def main():
    try:
        opts, args = getopt.gnu_getopt(sys.argv[1:],
                                       "ho:vVsX:", 
                                       [
                                        "exclude",
                                        "help",
                                        "output=",
                                        "strict",
                                        "verbose",
                                        "version",
                                       ])
    except getopt.GetoptError, err:
        # print help information and exit:
        print str(err) # will print something like "option -a not recognized"
        usage()
        sys.exit(2)

    exclude_list = []
    output = None
    verbose = 0
    strict = 0

    for o, a in opts:
        if o in ("-s", "--strict"):
            strict = 1
        elif o in ("-X", "--exclude"):
            exclude_list += a.split(",")
        elif o in ("-v", "--verbose"):
            verbose += 1
        elif o in ("-V", "--version"):
            print "SMOP compiler version 0.22"
            sys.exit()
        elif o in ("-h", "--help"):
            usage()
            sys.exit()
        elif o in ("-o", "--output"):
            output = a
        else:
            assert False, "unhandled option"

    if not output:
        output = "a.py"
    fp = open(output,"w") if output != "-" else sys.stdout
    print >> fp, "# Autogenerated with SMOP version 0.22"
    print >> fp, "# " + " ".join(sys.argv)
    print >> fp, "from __future__ import division"
    print >> fp, "import numpy as np"
    print >> fp, "from scipy.io import loadmat,savemat"
    print >> fp, "import os\n"

    #print >> fp, "from copy import copy as _copy"
    #print >> fp, "numpy.random.seed(0)"

    for pattern in args:
        for filename in glob.glob(os.path.expanduser(pattern)):
            if not filename.endswith(".m"):
                print "\tIngored file: '%s'" % filename
                continue
            if os.path.basename(filename) in exclude_list:
                print "\tExcluded file: '%s'" % filename
                continue
            print filename
            buf = open(filename).read()
            func_list = parse.parse(buf if buf[-1]=='\n' else buf+'\n')

            try:
                for func_obj in func_list: 
                    try:
                        func_name = func_obj.head.ident.name
                        print "\t",func_name
                    except AttributeError:
                        if verbose:
                            print "\tJunk ignored"
                        if strict:
                            return
                        continue
                    if options.do_resolve:
                        resolve.resolve(func_obj)
                        cls = getattr(node,func_obj.head.ident.name,None)
                        if not cls:
                            cls = type(func_obj.head.ident.name,
                                       (node.funcall,),
                                       { 'code' : func_obj })
                            setattr(node,func_obj.head.ident.name,cls)
                        assert issubclass(cls,node.funcall)
                        #typerank.typerank(func_obj)

                # end for
                    if options.do_rewrite:
                        rewrite.rewrite(func_obj)
                    s = backend.backend(func_obj)
                    print >> fp, s
            except Exception as ex:
                print repr(ex)
                if strict:
                    return


if __name__ == "__main__":
    main()
