Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,8 @@ const main = runtime.module(define, Inspector.into(document.body));

<a href="#compile_cell" name="compile_cell">#</a>compile.<b>cell</b>(<i>contents</i>)

Returns an object that has `define` and `redefine` functions that would define or redefine variables in the given cell to a specified module. `contents` is input for the [`parseCell`](https://github.com/observablehq/parser#parseCell) function. If the cell is not an ImportDeclaration, then the `redefine` functions can be used to redefine previously existing variables in a module. This is an asynchronous function because if the cell is an import, the imported notebook is fetched.
Returns an object that has `define` and `redefine` functions that would define or redefine variables in the given cell to a specified module. `contents` is input for the [`parseCell`](https://github.com/observablehq/parser#parseCell) function. If the cell is not an ImportDeclaration, then the `redefine` functions can be used to redefine previously existing variables in a module. This is an asynchronous function because if the cell is an import, the imported notebook is fetched.
Note: Calling the define method will return the variables created as an array. This can be helpful to remove unnamed variables or multiple cells imported using import statements when creating an editor interface to remove previously defined variables.

```javascript
let define, redefine;
Expand All @@ -165,7 +166,7 @@ await main.value("c"); // 22
define(main); // would throw an error, since a is already defined in main

{define} = await compile.cell(`x = 2`);
define(main);
define(main); // this will return an array, example:[variable_for_x]
{define} = await compile.cell(`y = x * 4`);
define(main);

Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
"scripts": {
"build": "rollup -c",
"format": "prettier --write src/**/*.js",
"test": "npm run build && tape 'test/**/*-test.js' && npm run test-format",
"test": "npm run build && tape test/*-test.js && npm run test-format",
"test-format": "prettier --check src/**/*.js",
"test-html": "http-server",
"prepublishOnly": "npm run build",
Expand Down
52 changes: 40 additions & 12 deletions src/compiler.js
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,8 @@ const createCellDefinition = (
dependencyMap,
define = true
) => {
let variables = [];
let tmp_variable_store = null;
if (cell.body.type === "ImportDeclaration") {
const {
specifiers,
Expand All @@ -164,23 +166,30 @@ const createCellDefinition = (
importString
} = setupImportCell(cell);
// this will display extra names for viewof / mutable imports (for now?)
main.variable(observer()).define(
tmp_variable_store = main.variable(observer()).define(
null,
["md"],
md => md`~~~javascript
${importString}
~~~`
);
variables.push(tmp_variable_store);

const other = main._runtime.module(
dependencyMap.get(cell.body.source.value)
);

if (hasInjections) {
const child = other.derive(injections, main);
for (const { name, alias } of specifiers) main.import(name, alias, child);
for (const { name, alias } of specifiers) {
tmp_variable_store = main.import(name, alias, child);
variables.push(tmp_variable_store);
}
} else {
for (const { name, alias } of specifiers) main.import(name, alias, other);
for (const { name, alias } of specifiers) {
tmp_variable_store = main.import(name, alias, other);
variables.push(tmp_variable_store);
}
}
} else {
const {
Expand All @@ -191,12 +200,15 @@ ${importString}
if (cell.id && cell.id.type === "ViewExpression") {
const reference = `viewof ${cellName}`;
if (define) {
main
tmp_variable_store = main
.variable(observer(reference))
.define(reference, cellReferences, cellFunction);
main
variables.push(tmp_variable_store);

tmp_variable_store = main
.variable(observer(cellName))
.define(cellName, ["Generators", reference], (G, _) => G.input(_));
variables.push(tmp_variable_store);
} else {
main.redefine(reference, cellReferences, cellFunction);
main.redefine(cellName, ["Generators", reference], (G, _) =>
Expand All @@ -207,13 +219,20 @@ ${importString}
const initialName = `initial ${cellName}`;
const mutableName = `mutable ${cellName}`;
if (define) {
main.variable(null).define(initialName, cellReferences, cellFunction);
main
tmp_variable_store = main
.variable(null)
.define(initialName, cellReferences, cellFunction);
variables.push(tmp_variable_store);

tmp_variable_store = main
.variable(observer(mutableName))
.define(mutableName, ["Mutable", initialName], (M, _) => new M(_));
main
variables.push(tmp_variable_store);

tmp_variable_store = main
.variable(observer(cellName))
.define(cellName, [mutableName], _ => _.generator);
variables.push(tmp_variable_store);
} else {
main.redefine(initialName, cellReferences, cellFunction);
main.redefine(
Expand All @@ -224,13 +243,15 @@ ${importString}
main.redefine(cellName, [mutableName], _ => _.generator);
}
} else {
if (define)
main
if (define) {
tmp_variable_store = main
.variable(observer(cellName))
.define(cellName, cellReferences, cellFunction);
else main.redefine(cellName, cellReferences, cellFunction);
variables.push(tmp_variable_store);
} else main.redefine(cellName, cellReferences, cellFunction);
}
}
return variables;
};
const createModuleDefintion = async (
moduleObject,
Expand Down Expand Up @@ -427,7 +448,14 @@ export class Compiler {
}
return {
define(module, observer) {
createCellDefinition(cell, module, observer, dependencyMap, true);
//return [variables] when creating a cell
return createCellDefinition(
cell,
module,
observer,
dependencyMap,
true
);
},
redefine(module, observer) {
createCellDefinition(cell, module, observer, dependencyMap, false);
Expand Down
37 changes: 35 additions & 2 deletions test/compiler-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,9 @@ viewof e = {
t.equal(await main.value("c"), 12);

const { define: xDefine } = await compile.cell(`x = y - 1`);
xDefine(main, () => true);
const xDefineVars = xDefine(main, () => true);
t.equal(xDefineVars.length, 1); //check length
t.equal(xDefineVars[0]._name, "x"); //check name
await rt._compute();

try {
Expand All @@ -65,7 +67,10 @@ viewof e = {
}

const { define: yDefine } = await compile.cell(`y = 101`);
yDefine(main, () => true);
const yDefineVars = yDefine(main, () => true);
t.equal(yDefineVars.length, 1); //check length
t.equal(yDefineVars[0]._name, "y"); //check name

await rt._compute();

t.equal(await main.value("y"), 101);
Expand All @@ -86,6 +91,34 @@ viewof e = {

t.equal(await main.value("e"), 20);

const { define: fDefine } = await compile.cell(`viewof f = {
let output = {};
let listeners = [];
output.value = 20;
output.addEventListener = (listener) => listeners.push(listener);;
output.removeEventListener = (listener) => {
listeners = listeners.filter(l => l !== listener);
};
return output;
}`);
const fDefineVars = fDefine(main, () => true);
t.equal(fDefineVars.length, 2); //check length
t.equal(fDefineVars[0]._name, "viewof f"); //check name
t.equal(fDefineVars[1]._name, "f"); //check name
await rt._compute();

t.equal(await main.value("f"), 20);

const { define: gDefine } = await compile.cell(`mutable g = 123`);
const gDefineVars = gDefine(main, () => true);
t.equal(gDefineVars.length, 3); //check length
t.equal(gDefineVars[0]._name, "initial g"); //check name
t.equal(gDefineVars[1]._name, "mutable g"); //check name
t.equal(gDefineVars[2]._name, "g"); //check name
await rt._compute();

t.equal(await main.value("g"), 123);

rt.dispose();
t.end();
});
38 changes: 35 additions & 3 deletions test/test_cell.html
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,11 @@
window.MODULE = rt.module(define, observer);

compile.cell(`d = 200`).then(({ define: defineCell }) => {
defineCell(window.MODULE, observer);
const variables = defineCell(window.MODULE, observer);
console.log(
"Define variable d= 200, created following variables: ",
variables
);
});

compile.cell(`a = -300`).then(({ redefine: redefineCell }) => {
Expand All @@ -65,11 +69,39 @@
`import {hello } with {myName as name} from "@tmcw/hello-world"`
)
.then(({ define: defineCell }) => {
defineCell(window.MODULE, observer);
const variables = defineCell(window.MODULE, observer);
console.log(
'Define import {hello } with {myName as name} from "@tmcw/hello-world", created following variables: ',
variables
);

compile.cell(`hello`).then(({ define: defineCell }) => {
defineCell(window.MODULE, observer);
const variables = defineCell(window.MODULE, observer);
console.log(
"Define hello, created following variables: ",
variables
);
});

compile
.cell(`viewof some_viewof = DOM.range()`)
.then(({ define: defineCell }) => {
const variables = defineCell(window.MODULE, observer);
console.log(
"Define viewof some_viewof = DOM.range(), created following variables: ",
variables
);
});

compile
.cell(`mutable some_mutable = 123`)
.then(({ define: defineCell }) => {
const variables = defineCell(window.MODULE, observer);
console.log(
"Define mutable some_mutable = 123, created following variables: ",
variables
);
});
});
});
</script>
Expand Down
Loading