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)
Beispiel #2
0
    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):
        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)
Beispiel #4
0
    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
Beispiel #5
0
    def modify(self, context: Context):
        if self.upper != None or self.lower != None:
            context.voice = context.voice.clone(time_signature=(self.upper,
                                                                self.lower))
        elif self.upper != None:
            context.voice = context.voice.clone(
                time_signature=(self.upper, context.time_signature[1]))
        elif self.lower != None:
            context.voice = context.voice.clone(
                time_signature=(context.time_signature[0], self.lower))

        yield ContextChangeEvent(context.cursor, "timeSignature",
                                 context.voice.time_signature, context.voice,
                                 0)
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
Beispiel #7
0
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 modify(self, context: Context):
        context.voice = context.voice.clone(
            instrument=Instrument.from_program(self.instrument))

        yield ContextChangeEvent(context.cursor, "instrument",
                                 context.voice.instrument.program,
                                 context.voice, 0)
Beispiel #9
0
def function_make_sequencer(context: Context,
                            sequencer: SequencerLike) -> Sequencer:
    std = cast(StandardLibrary, context.library(StandardLibrary))

    format = None
    uri = None
    args = None

    if type(sequencer) is str:
        uri = sequencer
    elif type(sequencer) is list:
        args_start = 0

        if len(sequencer) >= args_start + 2 and sequencer[args_start] == '-o':
            uri = sequencer[args_start + 1]
            args_start += 2

        if len(sequencer) >= args_start + 2 and sequencer[args_start] == '-f':
            format = sequencer[args_start + 1]
            args_start += 2

        args = sequencer[args_start:]
    elif isinstance(sequencer, Sequencer):
        return sequencer

    if format is not None:
        return std.player.make_sequencer_from_format(format, uri or "", args
                                                     or [])

    return std.player.make_sequencer_from_uri(uri or "", args or [])
    def __init__(self,
                 only_final: bool = False,
                 ast: bool = False,
                 context: Context = None,
                 nameless_voices: bool = True,
                 declare_voices: bool = True,
                 base_voice: Voice = None):
        """
        only_final          When true, the result is only emitted after the entire 
                            input (musical sequence) has been processed. When false,
                            intermediate notations are continuously emitted.
        
        ast                 When true, emits the Abstract Syntax Tree objects. When
                            false, transforms those objects into a string that can
                            be parsed, and emits the string instead

        nameless_voices     When true, it tries to produce notation that carries with
                            it any state that is needed, instead of prepending 
                            the names of the voices the events belonged to
        
        declare_voices      When `nameless_voices = False`, also include the 
                            definitions of the named voices used.
        
        base_voice          ...
        """
        super().__init__(only_final)

        self.ast: bool = ast
        self.context: Context = context or Context.create()
        self.nameless_voices: bool = nameless_voices
        self.declare_voices: bool = declare_voices
        self.base_voice: Voice = base_voice or Voice()
Beispiel #11
0
def keyboard_close ( context : Context, keyboard : Keyboard ):
    if keyboard != None:
        keyboard.close()
    else:
        lib : KeyboardLibrary = cast( KeyboardLibrary, context.library( KeyboardLibrary ) )

        lib.close()
Beispiel #12
0
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 create_context ( self, player : Player ):
        ctx = Context.create()

        ctx.link( StandardLibrary() )
        ctx.link( MusicLibrary() )
        ctx.link( KeyboardLibrary( player ) )

        return ctx
Beispiel #14
0
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
Beispiel #15
0
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))
Beispiel #16
0
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 __init__(self, event: Union[Music, NoteEvent, Note, None]):
        super().__init__()

        if isinstance(event, Music):
            event = event.first_note(Context())

        if isinstance(event, NoteEvent):
            event = event.note

        if event is None:
            raise Exception("Cannot create PianoKey of None")

        self.note: Note = event.timeless()
Beispiel #18
0
def keyboard_filedialog ( context : Context, title : str = "File", text : str = "File Path:", default_value : str = None, cb = None ):
    from prompt_toolkit.patch_stdout import patch_stdout
    from prompt_toolkit.shortcuts import input_dialog
    from prompt_toolkit.completion import PathCompleter

    lib : KeyboardLibrary = cast( KeyboardLibrary, context.library( KeyboardLibrary ) )

    def _run ():
        with patch_stdout():
            application = input_dialog( title = title, text = text, completer = PathCompleter() )

            with application.input.raw_mode():
                application.input.read_keys()

            application.layout.current_control.buffer.insert_text(default_value or "")
            
            return application.run_async()

    lib.prompt( _run, cb )
Beispiel #19
0
    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
    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
Beispiel #21
0
def function_set_midi_input_name(context: Context, name: str):
    context.library(MidiLibrary).set_midi_default_input(name)
Beispiel #22
0
def keyboard_readperf ( context : Context, file : str, keyboards : List[Keyboard] = None ) -> Music:
    lib : KeyboardLibrary = cast( KeyboardLibrary, context.library( KeyboardLibrary ) )

    return lib.readperf( context, file, keyboards )
Beispiel #23
0
def function_get_midi_input_name(context: Context) -> str:
    return context.library(MidiLibrary).get_midi_default_input()
 def setUp(self):
     self.parser = parser
     self.context = Context.create()
     self.context.link(StandardLibrary(None))
Beispiel #25
0
    def modify(self, context: Context):
        context.voice = context.voice.clone(value=self.length)

        yield ContextChangeEvent(context.cursor, "length", context.voice.value,
                                 context.voice, 0)
Beispiel #26
0
    def modify ( self, context : Context ):
        context.voice = context.voice.clone( tempo = self.tempo )

        yield ContextChangeEvent( context.cursor, "tempo", context.voice.tempo, context.voice, 0 )
Beispiel #27
0
def keyboard_open_repl ( context : Context ):
    lib : KeyboardLibrary = cast( KeyboardLibrary, context.library( KeyboardLibrary ) )

    lib.eval( context )

    return None
Beispiel #28
0
def function_setvoice(context: Context, voice: Voice):
    context.voice = voice
Beispiel #29
0
def function_settime(context: Context, time: int):
    context.cursor = time
Beispiel #30
0
def keyboard_replay ( context : Context, file : str ):
    lib : KeyboardLibrary = cast( KeyboardLibrary, context.library( KeyboardLibrary ) )

    lib.replay( file )