import sys
import os 

output = sys.stdout 
beingVerbose = False 
variableDict={} 

def say(args) :
    outstring = "" 
    if len(args) > 3 and args[1] == "+format" : 
        formatStr = args[2].replace("_", " ")
        formatStr = args[2].replace("\\n", "\n")
        output.write(formatStr % tuple(args[3:]))
    else : 
        outstring = " ".join(args[1:])
        output.write(outstring + "\n") 
    output.flush() 

def setOutput(args) :
    global output 
    if len(args) == 1 :
        if output != sys.stdout :
            output.close() 
            output = sys.stdout
    else : 
        if len(args) > 2 : 
            if args[1] == "-append" :
                output = open(args[2], "aw") 
            else :
                output = open(args[2], "w") 
        else : 
            output = open(args[1], "w") 

def dofile(args) :
    try : 
        inputFile = open(args[1], "r")
        runInterp(inputFile)
        inputFile.close() 
    except Exception, e : 
        if e.args[0] == "quitting" :
            return
        else : 
            print "Can't execute ", args[1] 

def foo(args) :
    output.write("foo!\n") 

def quit(args) :
    output.flush() 
    raise Exception,"quitting"

# args 1 should be a number, if not punt
# args 2 will be a variable 
# then do args[3:] that many times but with the variable set
# to the argument named
# so
# times 7 i say $i
# will print the numbers 0 through 6 each on its own line 
# this can be nested, but isn't likely to do quite what you
# think.   For instance, try :
# times 7 i times $i j say i= $i j= $j

def times(args) :
    try : 
        count = int(args[1]) 
        var = args[2] 
        for i in range(count) : 
            variableDict[var] = str(i)
            lvars = doVars(args[3:]) 
            commands[lvars[0]](lvars)
    except :
        return

def doCommand(line) : 
    global beingVerbose 
    if beingVerbose :
        print line   # to usual stdout, not modified 
    if line[0] == "#" :
        return
    
    args = doVars(line.split())

    if len(args) > 0 :
        if args[0] in commands :
            commands[args[0]](args) 
        else :
            print "unknown command: ", args[0]

def maybeSub(word) :
    if word[0] == "$" and word[1:] in variableDict :
        return variableDict[word[1:]]
    else :
        return word 

def doVars(arglist) :
    return [maybeSub(i) for i in arglist] 

            
def setvar(args) :
    variableDict[args[1]] = args[2] 

def verbose(args) :
    global beingVerbose 
    if len(args) == 1 : 
        beingVerbose=False
    elif args[1] == "on" :
        beingVerbose=True 
    elif args[1] == "off" :
        beingVerbose = False 

commands = {"say":say, "quit":quit, "do":dofile, "foo":foo, "set-output":setOutput, "times":times, "verbose":verbose, "set":setvar } 

def runInterp(inFile) :
    while True : 
        try : 
            line = inFile.readline() 
            if not line : break 
            doCommand(line) 
        except Exception, e :  # keep on going till it's time to quit
            if e.args[0] == "quitting" :
                return
        else : 
            pass 

def main() :
    if len(sys.argv) == 1 : 
        runInterp(sys.stdin) 
    else :
        for i in sys.argv[1:] :
            runInterp(open(i))
            
if __name__ == "__main__" : 
    main()

