Beispiel #1
0
 def evaluate_interactive(self,env = None):
     ## use a persistent environment for interactive interpreter
     if ( not env ):
         env = Environment( self.call_stack, self.function_map, \
                                self.builtin_map, self.debug )
         env.call_function("__toplevel__") ##some context
     ## use this from the interactive-interpreter
     rval = self.ast.evaluate(env)
     return [ rval, env ]
Beispiel #2
0
 def evaluate(self):
     env = Environment( self.call_stack, self.function_map, \
                            self.builtin_map, self.debug, int(self.MAX_REC_DEPTH/10) )
     env.call_function("__toplevel__") ##some context
     return self.ast.evaluate(env)
Beispiel #3
0
 def evaluate(self):
     env = Environment( self.call_stack, self.function_map, \
                            self.builtin_map, self.debug, int(self.MAX_REC_DEPTH/10) )
     env.call_function("__toplevel__")  ##some context
     return self.ast.evaluate(env)
class Interpreter(DebugUtils):
    """ when you add new language feature, add a AST class 
    and its evaluate methods. Also add a parser method """
    def __init__(self,lexer, debug = False,safe_mode=False,update=True,stacksize=500,env=None):
        DebugUtils.__init__(self,debug)
        self.SAFE_MODE = safe_mode
        self.debug = debug
        self.MAX_REC_DEPTH = 10000 #for Python
        self.stacksize = stacksize #for Ezhil stacksize
        self.lexer=lexer
        self.ast=None
        self.function_map = NoClobberDict()#parsed functions
        self.builtin_map = NoClobberDict() #pointers to builtin functions
        self.call_stack = list() #call stack
        if not env:
            self.env = Environment( self.call_stack, self.function_map, \
                                        self.builtin_map, self.debug, self.stacksize )
        else:
            self.env = env
        sys.setrecursionlimit( self.MAX_REC_DEPTH ) # have a large enough Python stack
        ## use the default Exprs parser.
        lang_parser = Parser(self.lexer,self.function_map, \
                             self.builtin_map, self.debug )
        self.parser = lang_parser
        
        ## run the installation code last
        self.install_builtins()
        self.install_blind_builtins()
        
        if update :
            ## update globals
            global global_interpreter
            global_interpreter = self
        
    def get_fname(self):
        return self.lexer.fname
        
    def reset(self):
        """ reset lexer and parser """
        self.parser.reset()
        self.lexer.reset()
        return

    def change_parser(self,parser_ctor):
        """ change the parser to your-cool-language using
         a lambda function parser_ctor the constructor """
        lang_parser = parser_ctor(self.lexer,self.function_map, \
                             self.builtin_map, self.debug )
        self.parser = lang_parser
        return True
    
    def list_functions(self,*args):
        if ( not args ):
            user_prefix = None
        else:
            user_prefix = args[0]
                
        print(u"######### Builtin Function ########")
        if not user_prefix:
            pos = 0
            for xpos,fcn in enumerate(self.builtin_map.keys()):
                if ( user_prefix and not fcn.startswith(user_prefix) ):
                    continue
                pos = pos + 1
                print(u"%03d> %s"%(pos,unicode(fcn)))
            return
        
        print(u"######### Functions - Library + User defined - ########")
        pos = 0
        for xpos,fcn in enumerate(self.function_map.keys()):
            if ( user_prefix and not fcn.startswith(user_prefix) ):
                continue
            pos = pos + 1
            print(u"%03d> %s"%(pos,unicode(fcn)))
        
    def add_blind_fcns(self, bfn, b):
        """ an internal method to reduce repetition """
        if ( not inspect.ismethod(bfn) 
             and not inspect.isclass(bfn)
             and isinstance(bfn, collections.Callable) ):
            self.dbg_msg("adding: "+b);
            self.builtin_map[b] = BlindBuiltins( bfn, b);
        else:
            self.dbg_msg("skipping: "+b);
        return

    def install_blind_builtins(self):
        """ we dont know the arity of these functions,
        hence we call-em the blind builtins, but we 
        still add them to the builtin_map """
        
        for b in dir(os):
            if self.SAFE_MODE:
                break
            bfn = getattr( os ,b)
            if str(b).find('exec') >= 0 or str(b).find('spawn') >= 0:
                continue
            if PYTHON3 and b == u"replace":
                continue
            self.add_blind_fcns( bfn, b)
        
        for b in dir(sys):
            bfn = getattr( sys ,b)
            self.add_blind_fcns( bfn, b)
        
    @staticmethod
    def ezhil_assert( x  ):
        # we raise Exception(u'Assertion failed!') further up stack
        assert x
        return True
    
    # file IO functions - 6 total
    @staticmethod
    def file_open(*args):
        try:
            args = list(args)
            if ( len(args) < 2 ):
                args.append('r') #default op = read
            if ( len(args) < 3 ):
                args.append('utf-8') #default encoding = utf-8
            fp = codecs.open(*args)
            return fp
        except Exception as e:
            print(u"WARNING : cannot open file %s with exception %s",args[0],str(e))
        return -1
    
    @staticmethod
    def file_close(*args):
        try:
            assert( len(args) == 1 )
            assert( hasattr(args[0],'close') )
            args[0].close()
        except Exception as e:
            print(u"WARNING: file_close failed with exception %s"%str(e))
            return -1
        return 0
    
    @staticmethod
    def file_read(*args):
        assert( len(args) == 1 )
        assert( hasattr(args[0],'read') )
        return String( args[0].read() )
    
    @staticmethod
    def file_readlines(*args):
        assert( len(args) == 1 )
        assert( hasattr(args[0],'readlines') )
        return args[0].readlines()
    
    @staticmethod
    def file_write(*args):
        assert( len(args) == 2 )
        assert( hasattr(args[0],'write') )
        return args[0].write( args[1] )
    
    @staticmethod
    def file_writelines(*args):
        assert( len(args) == 2 )
        assert( hasattr(args[0],'writelines') )
        return args[0].writelines(args[1])
    
    # marshalling            
    @staticmethod
    def RAWINPUT(args):
        try:
            op = raw_input(args)
        except KeyboardInterrupt as e :
            print(u"\nTo exit the program type : exit or press CTRL + D on your keyboard")
            return String("")
        return String(op)
    
    @staticmethod
    def INPUT(args):
        try:
            op = (raw_input(args))
        except KeyboardInterrupt as e :
            print(u"\nTo exit the program type : exit or press CTRL + D on your keyboard")
            return Number(0)
        if ( isinstance(op,int) or isinstance(op,float) ):
            return Number(0.0+op)
        return String( op )
    
    @staticmethod   
    def SPRINTF_worker(*args):
        if ( len(args) < 1 ):
            raise Exception(u'Not enough arguments to printf() function')
        fmt = args[0]
        arg = tuple( args[1:] );
        opstr = fmt%arg;
        return opstr
    
    @staticmethod
    def SPRINTF(*args):
        opstr = Interpreter.SPRINTF_worker(*args);
        return String(opstr)
    
    @staticmethod   
    def PRINTF(*args):
        str_op = Interpreter.SPRINTF_worker(*args);
        print(str_op)
        return Number(len(str_op))
    
    @staticmethod
    def ezhil_reverse(*args):
       if ( len(args) != 1 ): raise Exception('One argument alone expected to reverse function')
       if ( isinstance( args[0], str ) or isinstance( args[0], unicode) ):
           return String(args[0][::-1]) #string-reverse
       
       return list.reverse(args[0])
    
    @staticmethod
    def ezhil_pause(*args):
        if ( len(args) >= 1 ):
             print(args[0])
        if ( len(args) < 2 ):
             ezhil_sleep( 5 )
        else:
             ezhil_sleep( args[1] )
        return
    
    def add_builtin(self,call_name,call_handle,nargin=1,ta_alias=None):        
        # make sure you don't clobber yourself
        assert not self.builtin_map.get(call_name,None)
        if ( nargin == -1 ):
            self.builtin_map[call_name] = BlindBuiltins( call_handle, call_name, self.debug)
        else:
            self.builtin_map[call_name] = BuiltinFunction( call_handle, call_name, nargin, self.debug )
        # update the alias if something was supplied
        if ( ta_alias ):
            assert not self.builtin_map.get(ta_alias,None) #noclobber
            self.builtin_map[ta_alias] = self.builtin_map[call_name]
        
        return True
    
    def install_builtins(self):
        """ populate with the builtin functions"""
        self.builtin_map[u'printf']=BlindBuiltins(Interpreter.PRINTF,u'printf',self.debug)
        self.builtin_map[u'sprintf']=BlindBuiltins(Interpreter.SPRINTF,u'sprintf',self.debug)
        
        self.builtin_map['abs']=BlindBuiltins(abs,'abs',self.debug)
        self.builtin_map['all']=BlindBuiltins(all,'all',self.debug)
        self.builtin_map['any']=BlindBuiltins(any,'any',self.debug)
        
        if not PYTHON3:
            self.builtin_map['apply']=BlindBuiltins(apply,'apply',self.debug)
            self.builtin_map['buffer']=BlindBuiltins(buffer,'buffer',self.debug)
            self.builtin_map['cmp']=BlindBuiltins(cmp,'cmp',self.debug)
        self.builtin_map['basestring']=BlindBuiltins(str,'basestring',self.debug)
        self.builtin_map['bin']=BlindBuiltins(bin,'bin',self.debug)
        self.builtin_map['bool']=BlindBuiltins(bool,'bool',self.debug)
        self.builtin_map['bytearray']=BlindBuiltins(bytearray,'bytearray',self.debug)
        self.builtin_map['bytes']=BlindBuiltins(bytes,'bytes',self.debug)
        self.builtin_map['callable']=BlindBuiltins(callable,'callable',self.debug)
        self.builtin_map['chr']=BlindBuiltins(chr,'chr',self.debug)
        #self.builtin_map['classmethod']=BlindBuiltins(classmethod,'classmethod',self.debug)
        #self.builtin_map['coerce']=BlindBuiltins(coerce,'coerce',self.debug)
        self.builtin_map['compile']=BlindBuiltins(compile,'compile',self.debug)
        self.builtin_map['complex']=BlindBuiltins(complex,'complex',self.debug)
        self.builtin_map['xor'] = BlindBuiltins(lambda *x: reduce(lambda a,b: a^b,x),'xor',self.debug)
        # special ezhil commands
        self.builtin_map['copyright']=BlindBuiltins(ezhil_copyright,'copyright',self.debug)
        self.builtin_map['version']=BlindBuiltins(ezhil_version,'version',self.debug) 
        self.builtin_map['credits']=BlindBuiltins(ezhil_credits,'credits',self.debug)
        
        # global interpreter
        self.builtin_map['dir']=BlindBuiltins(ezhil_list_functions,'dir',self.debug)

        self.builtin_map['delattr']=BlindBuiltins(delattr,'delattr',self.debug)
        self.builtin_map['dict']=BlindBuiltins(dict,'dict',self.debug)
        self.builtin_map['python_dir']=BlindBuiltins(dir,'python_dir',self.debug)
        self.builtin_map['divmod']=BlindBuiltins(divmod,'divmod',self.debug)
        self.builtin_map['enumerate']=BlindBuiltins(enumerate,'enumerate',self.debug)
        
        # skip these system functions
        self.builtin_map['eval']=BlindBuiltins(ezhil_eval,'eval',self.debug)
        self.builtin_map[u'மதிப்பீடு']=self.builtin_map['eval']
        self.builtin_map['execute']=BlindBuiltins(ezhil_execute,'execute',self.debug)
        self.builtin_map[u'இயக்கு']=self.builtin_map['execute']
        
        self.builtin_map['profile'] = BlindBuiltins(ezhil_profile,'profile',self.debug)
        #self.builtin_map['execfile']=BlindBuiltins(execfile,'execfile',self.debug)
        #self.builtin_map['exit']=BlindBuiltins(exit,'exit',self.debug)
        if not PYTHON3:
            self.builtin_map['file']=BlindBuiltins(file,'file',self.debug)
            self.builtin_map['intern']=BlindBuiltins(intern,'intern',self.debug)
        
        self.builtin_map['filter']=BlindBuiltins(filter,'filter',self.debug)
        self.builtin_map['float']=BlindBuiltins(float,'float',self.debug)
        self.builtin_map['format']=BlindBuiltins(format,'format',self.debug)
        self.builtin_map['frozenset']=BlindBuiltins(frozenset,'frozenset',self.debug)
        self.builtin_map['getattr']=BlindBuiltins(getattr,'getattr',self.debug)
        #self.builtin_map['globals']=BlindBuiltins(globals,'globals',self.debug)
        self.builtin_map['hasattr']=BlindBuiltins(hasattr,'hasattr',self.debug)
        self.builtin_map['hash']=BlindBuiltins(hash,'hash',self.debug)
        self.builtin_map['help']=BlindBuiltins(help,'help',self.debug)
        self.builtin_map['hex']=BlindBuiltins(hex,'hex',self.debug)
        self.builtin_map['id']=BlindBuiltins(id,'id',self.debug)        
        self.builtin_map['int']=BlindBuiltins(int,'int',self.debug)
        self.builtin_map['isinstance']=BlindBuiltins(isinstance,'isinstance',self.debug)
        self.builtin_map['issubclass']=BlindBuiltins(issubclass,'issubclass',self.debug)
        self.builtin_map['iter']=BlindBuiltins(iter,'iter',self.debug)
        self.builtin_map['len']=BlindBuiltins(len,'len',self.debug)
        self.builtin_map['license']=BlindBuiltins(ezhil_license,'license',self.debug)
        self.builtin_map['long']=BlindBuiltins(int,'long',self.debug)
        self.builtin_map['map']=BlindBuiltins(map,'map',self.debug)
        #self.builtin_map['max']=BlindBuiltins(max,'max',self.debug)
        
        try:
            self.builtin_map['memoryview']=BlindBuiltins(memoryview,'memoryview',self.debug)
        except NameError as ie:
            if(self.debug): 
                print(u"Name Error:",unicode(ie))
    
        #self.builtin_map['min']=BlindBuiltins(min,'min',self.debug)
        self.builtin_map['next']=BlindBuiltins(next,'next',self.debug)
        self.builtin_map['object']=BlindBuiltins(object,'object',self.debug)
        self.builtin_map['oct']=BlindBuiltins(oct,'oct',self.debug)
        #self.builtin_map['open']=BlindBuiltins(open,'open',self.debug)
        self.builtin_map['ord']=BlindBuiltins(ord,'ord',self.debug)
        #self.builtin_map['pow']=BlindBuiltins(pow,'pow',self.debug)
        self.builtin_map['property']=BlindBuiltins(property,'property',self.debug)
        self.builtin_map['quit']=BlindBuiltins(quit,'quit',self.debug)
        self.builtin_map['range']=BlindBuiltins(range,'range',self.debug)        
        if not PYTHON3:
            self.builtin_map['reduce']=BlindBuiltins(reduce,'reduce',self.debug)
            self.builtin_map['reload']=BlindBuiltins(reload,'reload',self.debug)
            self.builtin_map['unicode']=BlindBuiltins(str,'unicode',self.debug)
        
        self.builtin_map['repr']=BlindBuiltins(repr,'repr',self.debug)
        self.builtin_map['reversed']=BlindBuiltins(reversed,'reversed',self.debug)
        self.builtin_map['round']=BlindBuiltins(round,'round',self.debug)
        self.builtin_map['set']=BlindBuiltins(set,'set',self.debug)
        self.builtin_map['setattr']=BlindBuiltins(setattr,'setattr',self.debug)
        self.builtin_map['slice']=BlindBuiltins(slice,'slice',self.debug)
        self.builtin_map['sorted']=BlindBuiltins(sorted,'sorted',self.debug)
        self.builtin_map['staticmethod']=BlindBuiltins(staticmethod,'staticmethod',self.debug)
        self.builtin_map['sum']=BlindBuiltins(sum,'sum',self.debug)
        self.builtin_map['super']=BlindBuiltins(super,'super',self.debug)
        self.builtin_map['tuple']=BlindBuiltins(tuple,'tuple',self.debug)
        self.builtin_map['type']=BlindBuiltins(type,'type',self.debug)
        self.builtin_map['unichr']=BlindBuiltins(chr,'unichr',self.debug)
        self.builtin_map['vars']=BlindBuiltins(vars,'vars',self.debug)
        if not PYTHON3:
            self.builtin_map['xrange']=BlindBuiltins(xrange,'xrange',self.debug)
        self.builtin_map['zip']=BlindBuiltins(zip,'zip',self.debug)
        
        # common/generic functions
        self.builtin_map['__getitem__']=BlindBuiltins(ezhil_getitem,"__getitem__")
        self.builtin_map['__setitem__']=BuiltinFunction(ezhil_setitem,"__setitem__",3)
        
        #file-IO functions
        self.builtin_map["file_open"]=BlindBuiltins(Interpreter.file_open,"file_open")
        self.builtin_map["file_close"]=BuiltinFunction(Interpreter.file_close,"file_close")
        self.builtin_map["file_read"]=BuiltinFunction(Interpreter.file_read,"file_read")
        self.builtin_map["file_readlines"]=BuiltinFunction(Interpreter.file_readlines,"file_readlines")
        self.builtin_map["file_write"]=BuiltinFunction(Interpreter.file_write,"file_write",2)
        self.builtin_map["file_writelines"]=BuiltinFunction(Interpreter.file_writelines,"file_writelines",2)
        
        # input statements
        self.builtin_map["input"]=BuiltinFunction(Interpreter.INPUT,"input")
        self.builtin_map["raw_input"]=BuiltinFunction(Interpreter.RAWINPUT,"raw_input")

        # assert
        self.builtin_map["assert"]=BuiltinFunction(Interpreter.ezhil_assert,"assert")
        
        # str - used for simple serialization in Ezhil
        self.builtin_map["str"]=BuiltinFunction(str,"str")
        
        # sys_platform - used for Windows/Linux identification
        self.builtin_map["sys_platform"]=BuiltinFunction(lambda : sys.platform,"sys_platform",padic=0)
        
        # sleep/pause
        self.builtin_map["sleep"]=BuiltinFunction(ezhil_sleep,"sleep")
        self.builtin_map["pause"]=BlindBuiltins(Interpreter.ezhil_pause,"pause")
    
        # date/time
        self.add_builtin("date_time",ezhil_date_time,nargin=0,ta_alias=u"தேதி_நேரம்")
        self.add_builtin("time",time.time,nargin=0,ta_alias=u"நேரம்")
        self.add_builtin("ctime",time.ctime,nargin=1,ta_alias=u"cநேரம்")
        self.add_builtin("clock",time.time,nargin=0)

        # islist, isnumber predicates
        self.add_builtin("islist",ezhil_islist,nargin=1,ta_alias=u"பட்டியலா")
        self.add_builtin("isnumber",ezhil_isnumber,nargin=1,ta_alias=u"எண்ணா")    
	
        # random functions
        aslist = True;
        self.builtin_map["choice"]=BlindBuiltins(random.choice,"choice",self.debug,aslist)
        self.builtin_map["random"]=BuiltinFunction(random.random,"random",0)
        self.builtin_map["seed"]=BuiltinFunction(random.seed,"seed")
        self.builtin_map["randint"]=BuiltinFunction(random.randint,"randint",2)
    
        # math functions
        self.builtin_map["acos"]=BuiltinFunction(acos,"acos")
        self.builtin_map["asin"]=BuiltinFunction(asin,"asin")
        self.builtin_map["atan"]=BuiltinFunction(atan,"atan")
        self.builtin_map["atan2"]=BuiltinFunction(atan2,"atan2")
        self.builtin_map["ceil"]=BuiltinFunction(ceil,"ceil")
        self.builtin_map["cos"]=BuiltinFunction(cos,"cos")
        self.builtin_map["cosh"]=BuiltinFunction(cosh,"cosh")
        self.builtin_map["degrees"]=BuiltinFunction(degrees,"degrees")
        self.builtin_map["e"]=BuiltinFunction(lambda : e,"e",0)
        self.builtin_map["exp"]=BuiltinFunction(exp,"exp")
        self.builtin_map["fabs"]=BuiltinFunction(fabs,"fabs")
        self.builtin_map["floor"]=BuiltinFunction(floor,"floor")
        self.builtin_map["fmod"]=BuiltinFunction(fmod,"fmod",2)
        self.builtin_map["frexp"]=BuiltinFunction(frexp,"frexp")
        self.builtin_map["hypot"]=BuiltinFunction(hypot,"hypot",2)
        self.builtin_map["ldexp"]=BuiltinFunction(ldexp,"ldexp")
        self.builtin_map["log"]=BuiltinFunction(log,"log")
        self.builtin_map["log10"]=BuiltinFunction(log10,"log10")
        self.builtin_map["modf"]=BuiltinFunction(modf,"modf",2)
        self.builtin_map["pi"]=BuiltinFunction(lambda : pi,"pi",0)
        self.builtin_map["pow"]=BuiltinFunction(pow,"pow",2)
        self.builtin_map["radians"]=BuiltinFunction(radians,"radians")
        self.builtin_map["sin"]=BuiltinFunction(sin,"sin")
        self.builtin_map["sinh"]=BuiltinFunction(sinh,"sinh")
        self.builtin_map["sqrt"]=BuiltinFunction(sqrt,"sqrt")
        self.builtin_map["tan"]=BuiltinFunction(tan,"tan")
        self.builtin_map["tanh"]=BuiltinFunction(tanh,"tanh")

        self.builtin_map["max"]=BuiltinFunction(max,"max",2)
        self.builtin_map["min"]=BuiltinFunction(min,"min",2)
        #self.builtin_map["exit"]=BuiltinFunction(min,"exit",1)

        # turtle functions - optional - 
        try:
            # turtle graphics
            from EZTurtle import EZTurtle

            turtle_attrib = EZTurtle.functionAttributes();
            for nargs,fcnName in list(turtle_attrib.items()):
                for vv in fcnName:
                    turtlefcn = u"turtle_"+vv;
                    if ( self.debug ): print(nargs, vv)
                    if ( nargs == -1 ):
                        self.builtin_map[turtlefcn] = BlindBuiltins(getattr(EZTurtle, vv),vv,self.debug)
                    else:
                        self.builtin_map[turtlefcn] = BuiltinFunction( getattr( EZTurtle, vv ), turtlefcn, nargs )
        except ImportError as ie:
            if ( self.debug ): 
                print(u"Cannot Import EZTurtle module; ignoring for now")
        # all builtin functions should pass the following test:
        # for attr in dir(module):
        #     assert callable( getattr( module, attr ) )
        # non-callable attributes cannot be in the builtins list        
        # string module builtins
        self.builtin_map["find"] = BuiltinFunction(string.find,"find",2)
        if not PYTHON3:
            self.builtin_map["atof"] = BuiltinFunction(string.atof,"atof",1)
            self.builtin_map["atof_error"] = BuiltinFunction(string.atof_error,"atof_error",1)
            self.builtin_map["atoi"] = BuiltinFunction(string.atoi,"atoi",1)
            self.builtin_map["atoi_error"] = BuiltinFunction(string.atoi_error,"atoi_error",1)
            self.builtin_map["atol"] = BuiltinFunction(string.atol,"atol",1)
            self.builtin_map["atol_error"] = BuiltinFunction(string.atol_error,"atol_error",1)
            self.builtin_map["capitalize"] = BuiltinFunction(string.capitalize,"capitalize",1)
            self.builtin_map["capwords"] = BuiltinFunction(string.capwords,"capwords",1)
            self.builtin_map["center"] = BuiltinFunction(string.center,"center",1)
            self.builtin_map["count_string"] = BuiltinFunction(string.count,"count",1)
            self.builtin_map["expandtabs"] = BuiltinFunction(string.expandtabs,"expandtabs",1)

        self.builtin_map["index_string"] = BuiltinFunction(string.index,"index",2)
        if not PYTHON3:
            self.builtin_map["index_error"] = BuiltinFunction(string.index_error,"index_error",1)
        self.builtin_map["join"] = BuiltinFunction(str.join,"join",1)
        if not PYTHON3:
            self.builtin_map["joinfields"] = BuiltinFunction(string.joinfields,"joinfields",1)
        self.builtin_map["ljust"] = BuiltinFunction(string.ljust,"ljust",1)
        self.builtin_map["lower"] = BuiltinFunction(string.lower,"lower",1)
        self.builtin_map["lstrip"] = BuiltinFunction(string.lstrip,"lstrip",1)
        if not PYTHON3:
            self.builtin_map["maketrans"] = BuiltinFunction(string.maketrans,"maketrans",1)
        self.builtin_map["replace"] = BuiltinFunction(string.replace,"replace",3)
        self.builtin_map["rfind"] = BuiltinFunction(string.rfind,"rfind",2)
        self.builtin_map["rindex"] = BuiltinFunction(string.rindex,"rindex",1)
        self.builtin_map["rjust"] = BuiltinFunction(string.rjust,"rjust",1)
        self.builtin_map["rsplit"] = BuiltinFunction(string.rsplit,"rsplit",1)
        self.builtin_map["rstrip"] = BuiltinFunction(string.rstrip,"rstrip",1)
        self.builtin_map["split"] = BuiltinFunction(string.split,"split",2)
        if not PYTHON3:
            self.builtin_map["splitfields"] = BuiltinFunction(string.splitfields,"splitfields",1)
        self.builtin_map["strip"] = BuiltinFunction(string.strip,"strip",1)
        self.builtin_map["swapcase"] = BuiltinFunction(str.swapcase,"swapcase",1)
        self.builtin_map["translate"] = BuiltinFunction(str.translate,"translate",1)
        self.builtin_map["upper"] = BuiltinFunction(str.upper,"upper",1)
        self.builtin_map["zfill"] = BuiltinFunction(str.zfill,"zfill",2)
        # get/set methods are handled by generic __getitem__ and __setitem__
        
        # list methods - first argument, when required, is always a list obj
        self.builtin_map["append"] = BuiltinFunction(list.append,"append",2)
        self.builtin_map["insert"] = BuiltinFunction(list.insert,"insert",3)
        self.builtin_map["index"] = BuiltinFunction(list.index,"index",2)
        self.builtin_map["list"] = BuiltinFunction(list,"list",0)
        self.builtin_map["pop"] = BuiltinFunction(list.pop,"pop",1)
        
        #if PYTHON3:
        #    self.builtin_map["sort"] = BuiltinFunction(lambda x: sorted(x),"sort",1)
        #else:
        self.builtin_map["sort"] = BuiltinFunction(list.sort,"sort",1)
        self.builtin_map["count"]= BuiltinFunction(list.count,"count",2)
        self.builtin_map["extend"]= BuiltinFunction(list.extend,"extend",2)
        self.builtin_map["reverse"]= BuiltinFunction(Interpreter.ezhil_reverse,"reverse",1)
        self.builtin_map["pop_list"] = BuiltinFunction(list.pop,"pop",1)

        # dictionary methods - first argument, when required, is always a dict obj
        self.builtin_map["clear"]= BuiltinFunction(dict.clear,"clear",1)
        self.builtin_map["copy"]= BuiltinFunction(dict.copy,"copy",1)
        self.builtin_map["fromkeys"]= BuiltinFunction(dict.fromkeys,"fromkeys",1)
        self.builtin_map["items"]= BuiltinFunction(dict.items,"items",1)
        
        if not PYTHON3:
            self.builtin_map["has_key"]= BuiltinFunction(dict.has_key,"has_key",1)
            self.builtin_map["iteritems"]= BuiltinFunction(dict.iteritems,"iteritems",1)
            self.builtin_map["iterkeys"]= BuiltinFunction(dict.iterkeys,"iterkeys",1)
            self.builtin_map["itervalues"]= BuiltinFunction(dict.itervalues,"itervalues",1)
            self.builtin_map["pop_dict"]= BuiltinFunction(dict.pop,"pop",1)
            self.builtin_map["popitem"]= BuiltinFunction(dict.popitem,"popitem",1)
            self.builtin_map["setdefault"]= BuiltinFunction(dict.setdefault,"setdefault",1)
        
        if PYTHON3:
            self.builtin_map["keys"]= BuiltinFunction(lambda x: list(dict.keys(x)),"keys",1)
            self.builtin_map["values"]= BuiltinFunction(lambda x: list(dict.values(x)),"values",1)
        else:
            self.builtin_map["keys"]= BuiltinFunction(dict.keys,"keys",1)
            self.builtin_map["values"]= BuiltinFunction(dict.values,"values",1)
        
        self.builtin_map["update"]= BuiltinFunction(dict.update,"update",1)
        
        # URL API's - load except in safe mode
        if not self.SAFE_MODE:
            Load_URL_APIs( self )
        
        # open-tamil API
        # get tamil letters
        self.add_builtin("get_tamil_letters",tamil.utf8.get_letters,nargin=1,ta_alias=u"தமிழ்_எழுத்துக்கள்")
        self.add_builtin(u"த",tamil.utf8.get_letters,nargin=1)
        self.add_builtin("tamil_length",ezhil_tamil_length,nargin=1,ta_alias=u"தநீளம்")     
        
        # functions returning constant list of Tamil strings
        self.add_builtin("tamil_letters",lambda :  tamil.utf8.tamil_letters,
                         nargin=0,ta_alias=u"தமிழ்எழுத்து")
        self.add_builtin("tamil_uyir",lambda :  tamil.utf8.uyir_letters,
                         nargin=0,ta_alias=u"உயிர்எழுத்து")
        self.add_builtin("tamil_mei",lambda: tamil.utf8.mei_letters,
                         nargin=0,ta_alias=u"மெய்எழுத்து") 
        self.add_builtin("tamil_kuril",lambda: tamil.utf8.kuril_letters,
                         nargin=0,ta_alias=u"குரில்எழுத்து") 
        self.add_builtin("tamil_nedil",lambda: tamil.utf8.nedil_letters,
                         nargin=0,ta_alias=u"நேடில்எழுத்து") 
        self.add_builtin("tamil_vallinam",lambda: tamil.utf8.vallinam_letters,
                         nargin=0,ta_alias=u"வல்லினம்எழுத்து") 
        self.add_builtin("tamil_mellinam",lambda: tamil.utf8.mellinam_letters,
                         nargin=0,ta_alias=u"மெல்லினம்") 
        self.add_builtin("tamil_idayinam",lambda: tamil.utf8.idayinam_letters,
                         nargin=0,ta_alias=u"இடைனம்எழுத்து") 
        self.add_builtin("tamil_agaram",lambda: tamil.utf8.agaram_letters,
                         nargin=0,ta_alias=u"அகரம்எழுத்து") 
        self.add_builtin("tamil_uyirmei",lambda: tamil.utf8.uyirmei_letters,
                         nargin=0,ta_alias=u"உயிர்மெய்எழுத்து")
        
        self.add_builtin("tamil_istamil_prefix",tamil.utf8.istamil_prefix,
                         nargin=1)
        self.add_builtin("tamil_all_tamil", tamil.utf8.all_tamil,
                         nargin=1,ta_alias=u"தனித்தமிழா")
        self.add_builtin("tamil_hastamil",tamil.utf8.has_tamil,
                         nargin=1,ta_alias=u"தமிழ்கொண்டதா")
        self.add_builtin("tamil_reverse_word",tamil.utf8.reverse_word,
                         nargin=1,ta_alias=u"அந்தாதிமாற்று")
        return True
    def __del__(self):
        if (self.debug): print("deleting Interpreter...")
        
    def __repr__(self):
        rval =  u"[Interpreter: "
        rval = rval + u"[Functions["
        for k in list(self.function_map.keys()):
            rval = rval + u"\n "+ unicode(self.function_map[k]) 
        rval = rval +u"]] "+ unicode(self.ast) +u"]\n"
        return rval

    def parse(self):
        """ parser routine """
        self.ast = self.parser.parse()
        return self.ast
    
    def evaluate(self):
        try:
            if self.SAFE_MODE:
                TransformSafeModeFunctionCheck(interpreter=self,debug=self.debug)
            
            # always verify semantics before running code
            #if ( self.debug ): print(self.ast )
            TransformSemanticAnalyzer(interpreter=self, debug=self.debug)
            
            # constant fold
            #for i in range(0,2):
            #    TransformConstantFolder( interpreter = self, debug=self.debug)
            
            if ( len(self.call_stack) == 0 ):
                self.env.call_function("__toplevel__") ##some context
            return self.ast.evaluate(self.env)
        except Exception as e:
            self.env.unroll_stack()
            if ( self.debug ):
                traceback.print_tb(sys.exc_info()[2])
            raise e
        
    def evaluate_interactive(self,env=None):
        ## use a persistent environment for interactive interpreter
        try:
            ## use this from the interactive-interpreter
            rval = self.ast.evaluate(self.env)
            return [ rval, self.env ]
        #except RuntimeException as e:
        #    self.env.unroll_stack()
        #    #self.env.call_stack.pop()
        except Exception as e:
            self.env.unroll_stack()
            #self.env.call_stack.pop()
            print("ERROR : %s"%str(e))
            if (self.debug): print(str(self.env))
        return [str(e),self.env]