Esempio n. 1
0
 def doCall2(phrase, args):
     '''
     "Calls" a phrase. This uses the language construct we have to
     specify the key, scale, instrument, etc to be used in the 
     Phrases.
     '''
     new_env = {}
     new_env['__up__'] = phrase.outer_env
     new_env["_notes"] = [{}]
     for arg in args:
         if arg[0] == "key":
             new_env["_scale"] = key_engine(arg[1], arg[2])
         elif arg[0] == "instr":
             new_env[arg[1]] = arg[2]
         else:
             new_env["_" + arg[0]] = arg[1]
     return self.evalStmt(phrase.body, new_env)
Esempio n. 2
0
    def evalStmt(self, stmts, env):
        '''
        Evaluates a list of statements in a given environment.
        '''
        def doCall(phrase, args):
            '''
            "Calls" a phrase. Essentially evaluates the phrase
            and returns its environment, typically to retreive the notelist.
            '''
            new_env = {}
            new_env['__up__'] = phrase.outer_env
            new_env["_notes"] = [{}]
            for i in range(len(args)):
                new_env[phrase.args[i]] = args[i]
            return self.evalStmt(phrase.body, new_env)
        def doCall2(phrase, args):
            '''
            "Calls" a phrase. This uses the language construct we have to
            specify the key, scale, instrument, etc to be used in the 
            Phrases.
            '''
            new_env = {}
            new_env['__up__'] = phrase.outer_env
            new_env["_notes"] = [{}]
            for arg in args:
                if arg[0] == "key":
                    new_env["_scale"] = key_engine(arg[1], arg[2])
                elif arg[0] == "instr":
                    new_env[arg[1]] = arg[2]
                else:
                    new_env["_" + arg[0]] = arg[1]
            return self.evalStmt(phrase.body, new_env)

        def update(name,env,val):
            '''
            Updates a binding in the environment to a given value.
            '''
            if not env:
                sys.exit(1)
            elif name in env:
                env[name] = val
            else:
                update(name,env['__up__'],val)
        # Evaluate the statements
        for s in stmts:
            if s[0] == 'phrase-def':
                # Phrase definition, binds a phrase to a name in
                # the environment
                env[s[1]] = Phrase(s[1], s[3], s[2], env)
            elif s[0] == "play":
                # Play each phrase sequentially
                for p in s[1]:
                    phrase = self.lookup(p, env)
                    val = doCall(phrase, phrase.args)
                    if self.recording == True:
                        env["_notes"] = val["_notes"]
                    else:
                        if env["_notes"][0] == {}:
                            env["_notes"] = val["_notes"]
                        else:
                            env["_notes"].extend(val["_notes"])
            elif s[0] == 'play-with': # only one phrase can follow after
                phrase = self.lookup(s[1], env)
                val = doCall2(phrase, s[2])
                if self.recording == True:
                    env["_notes"] = val["_notes"]
                else:
                    if env["_notes"][0] == {}:
                        env["_notes"] = val["_notes"]
                    else:
                        env["_notes"].extend(val["_notes"])
            elif s[0] == 'loop':
                # Loops a set of phrases
                self.evalStmt(s[1], env)
            elif s[0] == "asgn":
                # Assign a binding in the environment
                env[s[1]] = s[2]
            elif s[0] == "playing":
                # Sets the current instrument to be played 
                if s[1] in env.keys():
                    env["_currInstr"] = env[s[1]]
                else:
                    env["_currInstr"] = s[1]
            elif s[0] == "playing-in":
                # Sets the current instrument to be played and the
                # octave it will be played in
                if s[1] in env.keys():
                    env["_currInstr"] = env[s[1]]
                else:
                    env["_currInstr"] = s[1]
                if "_octave"in env.keys() and env["__up__"] is not None:
                    pass
                else:
                    env["_octave"] = s[2]
            elif s[0] == "key":
                # Declare the key to be played
                if "_scale" in env.keys() and env["__up__"] is not None:
                    print "passing"
                    pass
                else:
                    # Calls the key engine to dynamically generate the
                    # notes in the scale
                    env["_scale"] = key_engine(s[1], s[2])
            elif s[0] == "meter":
                # Declare the meter
                if "_meter" in env.keys() and env["__up__"] is not None:
                    pass
                else:
                    env["_meter"] = s[1]
            elif s[0] == "tempo":
                # Declare the tempo
                if "_tempo" in env.keys() and env["__up__"] is not None:
                    env["_tempo"] = s[1]
            elif s[0] == "duration":
                # Declare the default duration to be played
                if "_duration" in env.keys() and env["__up__"] is not None:
                    pass
                else:
                    env["_duration"] = s[1]
            elif s[0] == 'import-instr':
                # Imports an instrument that can be used in writing songs
                filename = s[1]
                ot.importInstrument(filename)
            elif s[0] == 'include':
                # Include phrases from another file
                filename = s[1]
                try:
                    # Parse and interpret the phrase to get the notelist and environment
                    fil = open(filename, "r")
                    text = fil.read()
                    fil.close()
                    grammar_file = ReadFile("fortissimo/fortissimo.grm")
                    parser = parser_generator.makeParser(grammar_parser.parse(cs164_grammar_file))
                    input_ast = parser.parse(text)
                    interpr = Intepreter(False)
                    new_env = interpr.evalStmt(input_ast, interpr.global_env)
                    self.global_env.update(new_env)
                except:
                    print "Could not include file '" + filename + "'."
            elif s[0] == "notes":
                # Adds notes to the environments notelist
                self.addNotesToQueue(s[1], env)
            else:
                raise SyntaxError("Illegal or Unimplemented AST node: " + str(s))        
        return env