From f1362b1c94120e018b4ee31be3066868c07f0b8c Mon Sep 17 00:00:00 2001 From: Felix Roos Date: Fri, 25 Feb 2022 20:10:49 +0100 Subject: [PATCH] use state query in repl + move locations to context --- repl/src/CodeMirror.tsx | 2 +- repl/src/types.d.ts | 1 + repl/src/useCycle.ts | 9 +++++---- repl/src/useRepl.ts | 4 ++-- strudel.mjs | 32 ++++++++++++++++---------------- 5 files changed, 25 insertions(+), 23 deletions(-) diff --git a/repl/src/CodeMirror.tsx b/repl/src/CodeMirror.tsx index 0dc27b54..463c3fab 100644 --- a/repl/src/CodeMirror.tsx +++ b/repl/src/CodeMirror.tsx @@ -18,7 +18,7 @@ export default function CodeMirror({ value, onChange, options, editorDidMount }: } export const markEvent = (editor) => (event) => { - const locs = event.value.locations; + const locs = event.context.locations; if (!locs || !editor) { return; } diff --git a/repl/src/types.d.ts b/repl/src/types.d.ts index 8252d201..3829b99a 100644 --- a/repl/src/types.d.ts +++ b/repl/src/types.d.ts @@ -15,6 +15,7 @@ export declare interface Hap { whole: TimeSpan; part: TimeSpan; value: T; + context: any; show: () => string; } export declare interface Pattern { diff --git a/repl/src/useCycle.ts b/repl/src/useCycle.ts index bce7a8da..0ed7e4f5 100644 --- a/repl/src/useCycle.ts +++ b/repl/src/useCycle.ts @@ -1,12 +1,12 @@ -import { useEffect, useMemo, useRef, useState } from 'react'; +import { useEffect, useState } from 'react'; import type { ToneEventCallback } from 'tone'; import * as Tone from 'tone'; -import { TimeSpan } from '../../strudel.mjs'; +import { TimeSpan, State } from '../../strudel.mjs'; import type { Hap } from './types'; export declare interface UseCycleProps { onEvent: ToneEventCallback; - onQuery?: (query: TimeSpan) => Hap[]; + onQuery?: (state: State) => Hap[]; onSchedule?: (events: Hap[], cycle: number) => void; ready?: boolean; // if false, query will not be called on change props } @@ -21,7 +21,7 @@ function useCycle(props: UseCycleProps) { // pull events with onQuery + count up to next cycle const query = (cycle = activeCycle()) => { const timespan = new TimeSpan(cycle, cycle + 1); - const events = onQuery?.(timespan) || []; + const events = onQuery?.(new State(timespan)) || []; onSchedule?.(events, cycle); // cancel events after current query. makes sure no old events are player for rescheduled cycles // console.log('schedule', cycle); @@ -46,6 +46,7 @@ function useCycle(props: UseCycleProps) { time: event.part.begin.valueOf(), duration: event.whole.end.sub(event.whole.begin).valueOf(), value: event.value, + context: event.context, }; onEvent(time, toneEvent); }, event.part.begin.valueOf()); diff --git a/repl/src/useRepl.ts b/repl/src/useRepl.ts index e16eb331..fd742fac 100644 --- a/repl/src/useRepl.ts +++ b/repl/src/useRepl.ts @@ -81,9 +81,9 @@ function useRepl({ tune, defaultSynth, autolink = true, onEvent }: any) { [onEvent] ), onQuery: useCallback( - (span) => { + (state) => { try { - return pattern?.query(span) || []; + return pattern?.query(state) || []; } catch (err: any) { err.message = 'query error: ' + err.message; setError(err); diff --git a/strudel.mjs b/strudel.mjs index 9d90bc57..f0c1d6af 100644 --- a/strudel.mjs +++ b/strudel.mjs @@ -175,7 +175,7 @@ class Hap { The context is to store a list of source code locations causing the event */ - constructor(whole, part, value, context=[]) { + constructor(whole, part, value, context = {}) { this.whole = whole this.part = part this.value = value @@ -185,12 +185,12 @@ class Hap { withSpan(func) { // Returns a new event with the function f applies to the event timespan. const whole = this.whole ? func(this.whole) : undefined - return new Hap(whole, func(this.part), this.value) + return new Hap(whole, func(this.part), this.value, this.context) } withValue(func) { // Returns a new event with the function f applies to the event value. - return new Hap(this.whole, this.part, func(this.value)) + return new Hap(this.whole, this.part, func(this.value), this.context) } hasOnset() { @@ -317,11 +317,10 @@ class Pattern { } withLocation(location) { - return this.fmap(value => { - value = typeof value === 'object' && !Array.isArray(value) ? value : { value }; - const locations = (value.locations || []).concat([location]); - return {...value, locations } - }) + return this._withContext((context) => { + const locations = (context.locations || []).concat([location]) + return { ...context, locations } + }); } withValue(func) { @@ -367,7 +366,8 @@ class Pattern { if (s == undefined) { return undefined } - return new Hap(whole_func(event_func.whole, event_val.whole), s, event_func.value(event_val.value)) + // TODO: is it right to add event_val.context here? + return new Hap(whole_func(event_func.whole, event_val.whole), s, event_func.value(event_val.value), event_val.context) } return flatten(event_funcs.map(event_func => removeUndefineds(event_vals.map(event_val => apply(event_func, event_val))))) } @@ -396,7 +396,7 @@ class Pattern { const new_whole = hap_func.whole const new_part = hap_func.part.intersection_e(hap_val.part) const new_value = hap_func.value(hap_val.value) - const hap = new Hap(new_whole, new_part, new_value) + const hap = new Hap(new_whole, new_part, new_value, hap_val.context) haps.push(hap) } } @@ -416,7 +416,7 @@ class Pattern { const new_whole = hap_val.whole const new_part = hap_func.part.intersection_e(hap_val.part) const new_value = hap_func.value(hap_val.value) - const hap = new Hap(new_whole, new_part, new_value) + const hap = new Hap(new_whole, new_part, new_value, hap_val.context) haps.push(hap) } } @@ -461,8 +461,9 @@ class Pattern { const pat_val = this const query = function(state) { const withWhole = function(a, b) { + // TODO: what to do with a.context here? return new Hap(choose_whole(a.whole, b.whole), b.part, - b.value + b.value, b.context ) } const match = function (a) { @@ -959,9 +960,8 @@ Pattern.prototype.bootstrap = () => { // this is wrapped around mini patterns to offset krill parser location into the global js code space function withLocationOffset(pat, offset) { - return pat.fmap((value) => { - value = typeof value === 'object' && !Array.isArray(value) ? value : { value }; - let locations = (value.locations || []); + return pat._withContext((context) => { + let locations = (context.locations || []); locations = locations.map(({ start, end }) => { const colOffset = start.line === 1 ? offset.start.column : 0; return { @@ -976,7 +976,7 @@ function withLocationOffset(pat, offset) { column: end.column - 1 + colOffset, }, }}); - return {...value, locations } + return {...context, locations } }); }