# Path: clara/common.py
# class UnknownLanguage(Exception):
#     '''
#     Signals use of unknown language either in parser or interpreter.
#     '''
# 
# Path: clara/model.py
# class Program(object):
#     '''
#     Program - consisting of functions
#     '''
# 
#     def __init__(self):
#         self.fncs = {}
#         self.meta = {}
#         self.warns = []
# 
#     def addfnc(self, fnc):
#         self.fncs[fnc.name] = fnc
# 
#     def getfnc(self, name):
#         return self.fncs[name]
# 
#     def getfncs(self):
#         return list(self.fncs.values())
# 
#     def getfncnames(self):
#         return list(self.fncs.keys())
# 
#     def rmfnc(self, name):
#         del self.fncs[name]
# 
#     def addmeta(self, name, val):
#         self.meta[name] = val
# 
#     def getmeta(self, name, default=None):
#         return self.meta.get(name, default)
# 
#     def addwarn(self, msg):
#         self.warns.append(msg)
# 
#     def slice(self):
#         for fnc in self.fncs.values():
#             fnc.slice()
# 
#     def __repr__(self):
#         return '\n\n'.join(map(str, list(self.fncs.values())))
# 
#     def tostring(self):
#         return '\n\n'.join([x.tostring() for x in list(self.fncs.values())])
# 
#     def getstruct(self):
#         
#         s = []
#         for fname in sorted(self.fncs):
#             sf = []
#             fnc = self.getfnc(fname)
#             dl = {}
#             todo = [fnc.initloc]
#             locs = list()
#             while len(todo) > 0:
#                 loc, todo = todo[0], todo[1:]
#                 if loc in dl:
#                     continue
#                 dl[loc] = len(dl) + 1
#                 locs.append(loc)
#                 if fnc.trans(loc, True) is not None:
#                     todo.append(fnc.trans(loc, True))
#                 if fnc.trans(loc, False) is not None:
#                     todo.append(fnc.trans(loc, False))
#                     
#             for loc in locs:
#                 lt = fnc.trans(loc, True)
#                 if lt is None:
#                     lt = ''
#                 else:
#                     lt = str(dl[lt])
#                 lf = fnc.trans(loc, False)
#                 if lf is None:
#                     lf = ''
#                 else:
#                     lf = str(dl[lf])
#                 sf.append('%s:%s,%s' % (dl[loc], lt, lf))
#             s.append('%s{%s}' % (fname, ' '.join(sf)))
#         return ' '.join(s)
# 
# VAR_IN = '$in'
# 
# VAR_OUT = '$out'
# 
# VAR_RET = '$ret'
# 
# VAR_COND = '$cond'
# 
# Path: clara/model.py
# def prime(var):
#     assert not isprimed(var), 'Variable already primed!'
#     
#     if isinstance(var, str):
#         return "%s'" % (var,)
# 
#     var = var.copy()
#     var.primed = True
#     return var
# 
# def unprime(var):
# 
#     assert isprimed(var), 'Variable not primed!'
# 
#     if isinstance(var, str):
#         return var[:-1]
# 
#     var = var.copy()
#     var.primed = False
#     return var
# 
# def isprimed(var):
#     if isinstance(var, str):
#         return var.endswith("'")
#     return var.primed


import time
from copy import deepcopy
from .common import UnknownLanguage
from .model import Program, VAR_IN, VAR_OUT, VAR_RET, VAR_COND
from .model import prime, unprime, isprimed
    def execute_StrFormat(self, f, mem):

        fmt = self.execute(f.args[0], mem)
        if not isinstance(fmt, str):
            raise RuntimeErr("Expected 'str' for format, got '%s'" % (fmt,))
        
        args = [self.execute(x, mem) for x in f.args[1:]]

        return fmt % tuple(args)

    def execute_ite(self, ite, mem):

        cond = not not self.execute(ite.args[0], mem)

        if cond:
            return self.execute(ite.args[1], mem)
        else:
            return self.execute(ite.args[2], mem)

    def execute_FuncCall(self, f, mem):
        name = f.args[0].name
        try:
            fnc = self.getfnc(name)
        except KeyError:
            raise RuntimeErr("Unknown function: '%s'" % (name,))

        args = [self.execute(x, mem) for x in f.args[1:]]

        newmem = {
            VAR_IN: mem.get(VAR_IN, UndefValue()),

# Path: clara/common.py
# class UnknownLanguage(Exception):
#     '''
#     Signals use of unknown language either in parser or interpreter.
#     '''
# 
# Path: clara/model.py
# class Program(object):
#     '''
#     Program - consisting of functions
#     '''
# 
#     def __init__(self):
#         self.fncs = {}
#         self.meta = {}
#         self.warns = []
# 
#     def addfnc(self, fnc):
#         self.fncs[fnc.name] = fnc
# 
#     def getfnc(self, name):
#         return self.fncs[name]
# 
#     def getfncs(self):
#         return list(self.fncs.values())
# 
#     def getfncnames(self):
#         return list(self.fncs.keys())
# 
#     def rmfnc(self, name):
#         del self.fncs[name]
# 
#     def addmeta(self, name, val):
#         self.meta[name] = val
# 
#     def getmeta(self, name, default=None):
#         return self.meta.get(name, default)
# 
#     def addwarn(self, msg):
#         self.warns.append(msg)
# 
#     def slice(self):
#         for fnc in self.fncs.values():
#             fnc.slice()
# 
#     def __repr__(self):
#         return '\n\n'.join(map(str, list(self.fncs.values())))
# 
#     def tostring(self):
#         return '\n\n'.join([x.tostring() for x in list(self.fncs.values())])
# 
#     def getstruct(self):
#         
#         s = []
#         for fname in sorted(self.fncs):
#             sf = []
#             fnc = self.getfnc(fname)
#             dl = {}
#             todo = [fnc.initloc]
#             locs = list()
#             while len(todo) > 0:
#                 loc, todo = todo[0], todo[1:]
#                 if loc in dl:
#                     continue
#                 dl[loc] = len(dl) + 1
#                 locs.append(loc)
#                 if fnc.trans(loc, True) is not None:
#                     todo.append(fnc.trans(loc, True))
#                 if fnc.trans(loc, False) is not None:
#                     todo.append(fnc.trans(loc, False))
#                     
#             for loc in locs:
#                 lt = fnc.trans(loc, True)
#                 if lt is None:
#                     lt = ''
#                 else:
#                     lt = str(dl[lt])
#                 lf = fnc.trans(loc, False)
#                 if lf is None:
#                     lf = ''
#                 else:
#                     lf = str(dl[lf])
#                 sf.append('%s:%s,%s' % (dl[loc], lt, lf))
#             s.append('%s{%s}' % (fname, ' '.join(sf)))
#         return ' '.join(s)
# 
# VAR_IN = '$in'
# 
# VAR_OUT = '$out'
# 
# VAR_RET = '$ret'
# 
# VAR_COND = '$cond'
# 
# Path: clara/model.py
# def prime(var):
#     assert not isprimed(var), 'Variable already primed!'
#     
#     if isinstance(var, str):
#         return "%s'" % (var,)
# 
#     var = var.copy()
#     var.primed = True
#     return var
# 
# def unprime(var):
# 
#     assert isprimed(var), 'Variable not primed!'
# 
#     if isinstance(var, str):
#         return var[:-1]
# 
#     var = var.copy()
#     var.primed = False
#     return var
# 
# def isprimed(var):
#     if isinstance(var, str):
#         return var.endswith("'")
#     return var.primed


# Path: clara/interpreter.py
import time
from copy import deepcopy
from .common import UnknownLanguage
from .model import Program, VAR_IN, VAR_OUT, VAR_RET, VAR_COND
from .model import prime, unprime, isprimed

    def execute_StrFormat(self, f, mem):

        fmt = self.execute(f.args[0], mem)
        if not isinstance(fmt, str):
            raise RuntimeErr("Expected 'str' for format, got '%s'" % (fmt,))
        
        args = [self.execute(x, mem) for x in f.args[1:]]

        return fmt % tuple(args)

    def execute_ite(self, ite, mem):

        cond = not not self.execute(ite.args[0], mem)

        if cond:
            return self.execute(ite.args[1], mem)
        else:
            return self.execute(ite.args[2], mem)

    def execute_FuncCall(self, f, mem):
        name = f.args[0].name
        try:
            fnc = self.getfnc(name)
        except KeyError:
            raise RuntimeErr("Unknown function: '%s'" % (name,))

        args = [self.execute(x, mem) for x in f.args[1:]]

        newmem = {
            VAR_IN: mem.get(VAR_IN, UndefValue()),

            VAR_OUT: mem.get(VAR_OUT, UndefValue()),