def exec(self, symbols_scope: SymbolsScope, context: Context, *args, **kargs): forked = context.fork(symbols=symbols_scope.fork()) forked.symbols.assign('__callerctx__', context, local=True) for variable_name in self.using: forked.symbols.using(variable_name) for i in range(len(self.arguments)): (name, arg_mod, default_value) = self.arguments[i] argument_node, default_node = None, default_value if len(args) > i: argument_node = args[i] elif name in kargs: argument_node = kargs[name] elif default_value == None: raise Exception(f"Mandatory argument { name } was not given.") if arg_mod == 'expr': forked.symbols.assign(name, argument_node) elif (arg_mod == 'ref' or arg_mod == 'in') and argument_node is not None: is_variable = isinstance(argument_node, VariableExpressionNode) if arg_mod == 'ref' and not is_variable: raise BaseException( f"Only variable references can be passed to a function (function { self.name }, parameter { name })" ) # TODO: Should ref pointers be shallow? Since ref can mutate # the value, it could be sensible for them to be so if is_variable: pointer = context.symbols.pointer(argument_node.name) if pointer is None: context.symbols.assign(argument_node.name, None) else: forked.symbols.using(pointer, name) else: forked.symbols.assign( name, Value.assignment(argument_node.eval(context.fork()))) else: if argument_node is not None: value = Value.assignment(argument_node.eval( context.fork())) else: value = Value.assignment(default_node.eval(forked.fork())) value = forked.symbols.assign(name, value) return self.body.eval(forked)
def function_to_mkl(context: Context, music: Music, ast: bool = False, nameless_voices: bool = True, declare_voices: bool = True, base_voice: Voice = None) -> Union[str, Node]: source: Box[str] = Box("") inp, out = Transformer.pipeline2( VoiceIdentifierTransformer(), MusiklaNotationBuilderTransformer(only_final=True, ast=ast, context=context, nameless_voices=nameless_voices, declare_voices=declare_voices, base_voice=base_voice), ) out.subscribe(lambda s: source.set(s)) for ev in music.expand(context.fork(cursor=0)): inp.add_input(ev) inp.end_input() return source.value
def function_voices_create(context: Context, name: str, modifiers: Node = None, inherit: Voice = None): if inherit != None: pass voice = Voice(name, Instrument(name, 1)) forked = context.fork() forked.voice = voice if inherit != None: voice.instrument = inherit.instrument voice.time_signature = inherit.time_signature voice.velocity = inherit.velocity voice.octave = inherit.octave voice.value = inherit.value voice.tempo = inherit.tempo if modifiers != None: if isinstance(modifiers, MusicSequenceNode): for modifier in modifiers: if isinstance(modifier, ContextModifierNode): modifier.apply(voice) else: modifier.eval(forked) else: if isinstance(modifiers, ContextModifierNode): modifiers.apply(voice) else: modifiers.eval(forked) return voice
def function_save(context: Context, music: Music, outputs: Union[str, Sequencer, List[SequencerLike]]) -> Any: # The single parameter specifies if only one sequencer was given # In that case, instead of returning an array, we return just the sequencer single: bool = False if type(outputs) is str or isinstance(outputs, Sequencer): sequencers: List[Sequencer] = [ function_make_sequencer(context, outputs) ] single = True else: sequencers: List[Sequencer] = [ function_make_sequencer(context, seq) for seq in outputs ] for seq in sequencers: seq.realtime = False seq.start() for ev in music.expand(context.fork(cursor=0)): for seq in sequencers: seq.register_event(ev) for seq in sequencers: seq.close() if single: return sequencers[0] return sequencers
def function_discard(context: Context, *expr): for e in expr: value = e.eval(context.fork()) if isinstance(value, Music): for _ in value: pass return None
def function_debug(context: Context, expr): value = expr.eval(context.fork()) if value is None: print(None) elif isinstance(value, Music): print('<Music> ' + ' '.join(str(event) for event in value.expand(context))) else: print("<%s>%s" % (Value.typeof(value), value))
def __eval__(self, context: Context): forked = context.fork(symbols=context.symbols.fork( opaque=False)) if self.fork_context else context try: if self.create_stack_frame: return self.body.eval(forked) else: return self.body.child.eval(forked) finally: context.join(forked)
def values(self, context: Context): condition_value = self.condition.eval(context) while condition_value: forked = context.fork(symbols=context.symbols.fork(opaque=False)) yield self.body.eval(forked) context.join(forked) condition_value = self.condition.eval(context)
def __eval__(self, context: Context, assignment: bool = False): if self.expression is None: return None forked = context.fork() value = self.expression.eval(forked) if isinstance(value, Music): return Music(self.get_events(context, forked, value)) else: context.join(forked) return value
def function_readmidi(context: Context, file: str = None, port: Union[str, List[str], bool] = None, voices: List[Voice] = None, cutoff_sequence=None, ignore_message_types: List[str] = None): if file is not None: mid = mido.MidiFile(file) return read_midi_file(context, mid, voices, cutoff_sequence, ignore_message_types) else: if port == True: default_port = context.library( MidiLibrary).get_midi_default_input() if default_port is None: port = mido.open_input() else: port = mido.open_input(default_port) elif type(port) == str: port = mido.open_input(port) elif type(port) == list: port = MultiPort([mido.open_input(p) for p in port]) events = midi_stream_to_music(context, port, context.voice, ignore_message_types) events = ComposeNotesTransformer.iter(events) if cutoff_sequence != None: events = TerminationMelodyTransformer.iter( events, list(cutoff_sequence.expand(context.fork(cursor=0)))) events = TeeTransformer.iter( events, Transformer.pipeline( VoiceIdentifierTransformer(), MusiklaNotationBuilderTransformer(), Transformer.subscriber(lambda n: print(n + '\n\n')))) return Music(list(events))
def __eval__(self, context: Context): val = Value.assignment(self.right.eval(context.fork(cursor=0))) for i, op in enumerate(self.left): if self.operator is None or self.operator == "": op.assign(context, val[i], local=self.local) else: def _set(value): nonlocal val if self.operator == '*': value *= val[i] elif self.operator == '/': value /= val[i] elif self.operator == '+': value += val[i] elif self.operator == '-': value -= val[i] elif self.operator == '&': value &= val[i] elif self.operator == '|': value |= val[i] else: raise Exception("Invalid operator: " + self.operator) return value op.lookup_assign(context, _set, local=self.local) return None
def __eval__(self, context: Context): val = Value.assignment(self.right.eval(context.fork(cursor=0))) if self.operator is None or self.operator == "": self.left.assign(context, val, local=self.local) else: def _set(value): nonlocal val # value = context.symbols.lookup( self.name, recursive = not self.local ) if self.operator == '*': value *= val elif self.operator == '/': value /= val elif self.operator == '+': value += val elif self.operator == '-': value -= val elif self.operator == '&': value &= val elif self.operator == '|': value |= val else: raise Exception("Invalid operator: " + self.operator) return value self.left.lookup_assign(context, _set, local=self.local) return None