This commit is contained in:
Felix Roos
2022-02-20 20:31:55 +01:00
parent 1de371e944
commit f8df4b485d
9 changed files with 397 additions and 95 deletions
@@ -41619,7 +41619,7 @@ var _usePostMessageDefault = parcelHelpers.interopDefault(_usePostMessage);
let s4 = ()=>{
return Math.floor((1 + Math.random()) * 65536).toString(16).substring(1);
};
function useRepl({ tune , defaultSynth , autolink =true }) {
function useRepl({ tune , defaultSynth , autolink =true , onEvent }) {
const id = _react.useMemo(()=>s4()
, []);
const [code, setCode] = _react.useState(tune);
@@ -41661,6 +41661,7 @@ function useRepl({ tune , defaultSynth , autolink =true }) {
const cycle1 = _useCycleDefault.default({
onEvent: _react.useCallback((time, event)=>{
try {
onEvent?.(event);
if (!event.value?.onTrigger) {
const note = event.value?.value || event.value;
if (!_tone.isNote(note)) throw new Error('not a note: ' + note);
@@ -41676,7 +41677,9 @@ function useRepl({ tune , defaultSynth , autolink =true }) {
err.message = 'unplayable event: ' + err?.message;
pushLog(err.message); // not with setError, because then we would have to setError(undefined) on next playable event
}
}, []),
}, [
onEvent
]),
onQuery: _react.useCallback((span)=>{
try {
return pattern?.query(span) || [];
@@ -42107,6 +42110,20 @@ class Pattern {
return new Pattern((span)=>func(this.query(span))
);
}
withLocation(location) {
return this.fmap((value)=>{
value = typeof value === 'object' && !Array.isArray(value) ? value : {
value
};
const locations = (value.locations || []).concat([
location
]);
return {
...value,
locations
};
});
}
withValue(func) {
// Returns a new pattern, with the function applied to the value of
// each event. It has the alias 'fmap'.
@@ -42273,7 +42290,14 @@ class Pattern {
_patternify(func) {
const pat = this;
const patterned = function(...args) {
// the problem here: args could a pattern that has been turned into an object to add location
// to avoid object checking for every pattern method, we can remove it here...
// in the future, patternified args should be marked as well + some better object handling
args = args.map((arg)=>arg.constructor?.name === 'Pattern' ? arg.fmap((value)=>value.value || value
) : arg
);
const pat_arg = sequence(...args);
// arg.locations has to go somewhere..
return pat_arg.fmap((arg)=>func.call(pat, arg)
).outerJoin();
};
@@ -62538,17 +62562,32 @@ var _shiftTraverserDefault = parcelHelpers.interopDefault(_shiftTraverser);
var _shiftAst = require("shift-ast");
var _shiftCodegen = require("shift-codegen");
var _shiftCodegenDefault = parcelHelpers.interopDefault(_shiftCodegen);
var _strudelMjs = require("../../strudel.mjs");
const { replace } = _shiftTraverserDefault.default;
const { Pattern } = _strudelMjs;
const isNote = (name)=>/^[a-gC-G][bs]?[0-9]$/.test(name)
;
const addLocations = true;
exports.default = (code)=>{
const ast = _indexJs.parseScript(code);
const shifted = replace(ast, {
enter (node, parent) {
// replace identifiers that are a note with a note string
const ast = _indexJs.parseScriptWithLocation(code);
const nodesWithLocation = [];
const parents = [];
const shifted = replace(ast.tree, {
enter (node, parent1) {
parents.push(parent1);
const isSynthetic = parents.some((p)=>nodesWithLocation.includes(p)
);
if (isSynthetic) return node;
const grandparent = parents[parents.length - 2];
const isPatternArg = (parent)=>parent?.type === 'CallExpression' && Object.keys(Pattern.prototype.factories).includes(parent.callee.name)
;
const isTimeCat = parent1?.type === 'ArrayExpression' && isPatternArg(grandparent);
const isMarkable = isPatternArg(parent1) || isTimeCat;
// replace pseudo note variables
if (node.type === 'IdentifierExpression') {
if (isNote(node.name)) {
const value = node.name[1] === 's' ? node.name.replace('s', '#') : node.name;
if (addLocations && isMarkable) return addPureWithLocation(value, node, ast.locations, nodesWithLocation);
return new _shiftAst.LiteralStringExpression({
value
});
@@ -62557,14 +62596,152 @@ exports.default = (code)=>{
name: 'silence'
});
}
if (addLocations && node.type === 'LiteralStringExpression' && isMarkable) // console.log('add', node);
return addPureWithLocation(node.value, node, ast.locations, nodesWithLocation);
return node;
},
leave () {
parents.pop();
}
});
return _shiftCodegenDefault.default(shifted);
}; // TODO: turn x.groove['[~ x]*2'] into x.groove('[~ x]*2'.m)
};
// turns node in pure(value).withLocation(location), where location is the node's location in the source code
// with this, the pure pattern can pass its location to the event, to know where to highlight when it's active
function addPureWithLocation(value, node, locations, nodesWithLocation) {
// console.log('addPure', value, node);
const withLocation = new _shiftAst.CallExpression({
callee: new _shiftAst.StaticMemberExpression({
object: new _shiftAst.CallExpression({
callee: new _shiftAst.IdentifierExpression({
name: 'pure'
}),
arguments: [
new _shiftAst.LiteralStringExpression({
value
})
]
}),
property: 'withLocation'
}),
arguments: [
getLocationObject(node, locations)
]
});
nodesWithLocation.push(withLocation);
return withLocation;
}
// returns ast for source location object
function getLocationObject(node, locations) {
/*const locationAST = parseScript(
"x=" + JSON.stringify(ast.locations.get(node))
).statements[0].expression.expression;
console.log("locationAST", locationAST);*/ /*const callAST = parseScript(
`pure(${node.name}).withLocation(${JSON.stringify(
ast.locations.get(node)
)})`
).statements[0].expression;*/ const loc = locations.get(node);
return {
type: 'ObjectExpression',
properties: [
{
type: 'DataProperty',
name: {
type: 'StaticPropertyName',
value: 'start'
},
expression: {
type: 'ObjectExpression',
properties: [
{
type: 'DataProperty',
name: {
type: 'StaticPropertyName',
value: 'line'
},
expression: {
type: 'LiteralNumericExpression',
value: loc.start.line
}
},
{
type: 'DataProperty',
name: {
type: 'StaticPropertyName',
value: 'column'
},
expression: {
type: 'LiteralNumericExpression',
value: loc.start.column
}
},
{
type: 'DataProperty',
name: {
type: 'StaticPropertyName',
value: 'offset'
},
expression: {
type: 'LiteralNumericExpression',
value: loc.start.offset
}
},
]
}
},
{
type: 'DataProperty',
name: {
type: 'StaticPropertyName',
value: 'end'
},
expression: {
type: 'ObjectExpression',
properties: [
{
type: 'DataProperty',
name: {
type: 'StaticPropertyName',
value: 'line'
},
expression: {
type: 'LiteralNumericExpression',
value: loc.end.line
}
},
{
type: 'DataProperty',
name: {
type: 'StaticPropertyName',
value: 'column'
},
expression: {
type: 'LiteralNumericExpression',
value: loc.end.column
}
},
{
type: 'DataProperty',
name: {
type: 'StaticPropertyName',
value: 'offset'
},
expression: {
type: 'LiteralNumericExpression',
value: loc.end.offset
}
},
]
}
},
]
};
} // TODO: turn x.groove['[~ x]*2'] into x.groove('[~ x]*2'.m)
// and ['c1*2'].xx into 'c1*2'.m.xx ??
// or just all templated strings?? x.groove(`[~ x]*2`)
},{"./shift-parser/index.js":"1kFzJ","./shift-traverser":"bogJs","shift-ast":"ig2Ca","shift-codegen":"1GOrI","@parcel/transformer-js/src/esmodule-helpers.js":"gkKU3"}],"1kFzJ":[function(require,module,exports) {
},{"./shift-parser/index.js":"1kFzJ","./shift-traverser":"bogJs","shift-ast":"ig2Ca","shift-codegen":"1GOrI","../../strudel.mjs":"ggZqJ","@parcel/transformer-js/src/esmodule-helpers.js":"gkKU3"}],"1kFzJ":[function(require,module,exports) {
var parcelHelpers = require("@parcel/transformer-js/src/esmodule-helpers.js");
parcelHelpers.defineInteropFlag(exports);
parcelHelpers.export(exports, "parseModule", ()=>parseModule
@@ -97727,16 +97904,18 @@ var _javascriptJs = require("codemirror/mode/javascript/javascript.js");
var _pegjsJs = require("codemirror/mode/pegjs/pegjs.js");
var _materialCss = require("codemirror/theme/material.css");
var _codemirrorCss = require("codemirror/lib/codemirror.css");
function CodeMirror({ value , onChange , options }) {
function CodeMirror({ value , onChange , options , editorDidMount }) {
options = options || {
mode: 'javascript',
theme: 'material',
lineNumbers: true
lineNumbers: true,
styleSelectedText: true
};
return(/*#__PURE__*/ _jsxRuntime.jsx(_reactCodemirror2.Controlled, {
value: value,
options: options,
onBeforeChange: onChange
onBeforeChange: onChange,
editorDidMount: editorDidMount
}));
}
exports.default = CodeMirror;
@@ -108958,4 +109137,4 @@ exports.default = cx;
},{"@parcel/transformer-js/src/esmodule-helpers.js":"gkKU3"}]},["3uVTb"], "3uVTb", "parcelRequire94c2")
//# sourceMappingURL=index.dc15e374.js.map
//# sourceMappingURL=index.98344030.js.map
File diff suppressed because one or more lines are too long
+1 -1
View File
@@ -11,6 +11,6 @@
<body>
<div id="root"></div>
<noscript>You need to enable JavaScript to run this app.</noscript>
<script src="/tutorial/index.dc15e374.js" defer=""></script>
<script src="/tutorial/index.98344030.js" defer=""></script>
</body>
</html>