import sys
import optparse
import lexer
import parse
import value
import semantic
import execute
import wrap
import error

# ___________________________________________________________________________
# Interpreter State

class Interp(object):

    FILE_EXT = ".axel"
    
    def __init__(self):
        self.src_dirs = []
        self.modules = {}

    def run(self, argv):
        """
        Parse the options in argv (should not include sys.argv[0]) and
        execute the program specified with the given arguments.
        Returns the result code (0 for normal termination, 1 for user
        error).
        """
        parser = optparse.OptionParser()
        parser.set_usage("Usage: %s <program%s> [args]" % (self.FILE_EXT[1:], self.FILE_EXT))
        parser.add_option("-p", "--dump-parse-trees", action="store_true",
                          dest="dump_parse_trees",
                          help="Dump parse trees of each module")
        parser.add_option("-c", "--check-only", action="store_true",
                          dest="check_only",
                          help="Do not execute the program.")
        parser.add_option("-v", "--verbose", action="store_true",
                          dest="verbose",
                          help="Verbosely trace execution")
        parser.add_option("-d", "--debug-interp", action="store_true",
                          dest="debug_interp",
                          help="Enables output for debugging the interp")
        parser.add_option("-D", "--debug-parser", action="store_true",
                          dest="debug_parser",
                          help="Dump debugging output during parsing")
        parser.add_option("-a", "--dump-ast", action="store_true",
                          dest="dump_ast",
                          help="Dump AST trees")
        parser.set_defaults(dump_parse_trees=False,
                            check_only=False,
                            re_raise=False,
                            verbose=False,
                            debug_interp=False,
                            dump_ast=False)
        self.options, args = parser.parse_args(args=argv)

        filenm = args[0]
        prog_args = args[1:]

        if self.options.debug_parser:
            import spark
            spark.DEBUG = True

        if self.options.debug_interp:
            indent = [0]
            def dump_func(frame, event, arg):
                sys.stderr.write("%s: %s %s (%s)\n" % (
                    " " * indent[0], event, frame, arg))
                if event == "call":
                    indent[0] += 2
                elif event == "return":
                    indent[0] -= 2
            sys.settrace(dump_func)

        try:
            ast = parse.parse(filenm)
            main_func = semantic.semantic(self, ast)
            if not self.options.check_only:
                value_args = wrap.wrap_val(prog_args)
                main_func.apply_to(lexer.DUMMY_LOC, [value_args])
            return 0
        except error.AxelUserError, e:
            msg = e.message
            if not msg: msg = e.__class__
            sys.stderr.write("%s: %s\n" % (e.loc, msg))
            if self.options.verbose:
                sys.excepthook(*sys.exc_info())
            return 1
        
if __name__ == "__main__":
    args = sys.argv[1:]
    if not args: args = ["-h"]
    sys.exit(Interp().run(args))
