mirror of
https://github.com/xibyte/jsketcher
synced 2025-12-11 10:53:45 +01:00
87 lines
2.5 KiB
JavaScript
87 lines
2.5 KiB
JavaScript
import {merge, state} from 'lstream';
|
|
import {indexArray} from 'gems/iterables';
|
|
import {NOOP} from 'gems/func';
|
|
|
|
export function defineStreams(ctx) {
|
|
const script = state('');
|
|
const list = state([]);
|
|
const table = list.map(varList => indexArray(varList, i => i.name, i => i.value)).remember();
|
|
const synced = merge(script.map(() => false), list.map(() => true));
|
|
ctx.streams.expressions = {
|
|
script, list, table, synced,
|
|
errors: state([])
|
|
};
|
|
}
|
|
|
|
export function activate(ctx) {
|
|
let _evaluateExpression = NOOP;
|
|
function reevaluateExpressions() {
|
|
let {varList, errors, evaluateExpression} = rebuildVariableTable(ctx.streams.expressions.script.value);
|
|
ctx.streams.expressions.list.next(varList);
|
|
ctx.streams.expressions.errors.next(errors);
|
|
_evaluateExpression = evaluateExpression;
|
|
}
|
|
function load(script) {
|
|
ctx.streams.expressions.script.next(script);
|
|
reevaluateExpressions();
|
|
}
|
|
function evaluateExpression(expr) {
|
|
if (typeof expr === 'number') {
|
|
return expr;
|
|
}
|
|
let value = ctx.streams.expressions.table.value[expr];
|
|
if (value === undefined) {
|
|
value = parseFloat(expr);
|
|
if (isNaN(value)) {
|
|
value = _evaluateExpression(expr);
|
|
}
|
|
}
|
|
return value;
|
|
}
|
|
ctx.services.expressions = {
|
|
reevaluateExpressions, load, evaluateExpression,
|
|
signature: ''
|
|
};
|
|
ctx.streams.expressions.table.attach(() => ctx.services.expressions.signature = Date.now() + '');
|
|
ctx.services.action.registerAction({
|
|
id: 'expressionsUpdateTable',
|
|
appearance: {
|
|
info: 'reevaluate expression script (happens automatically on script focus lost)',
|
|
label: 'update expressions',
|
|
},
|
|
invoke: ({services}) => {
|
|
services.extension.reevaluateExpressions();
|
|
}
|
|
})
|
|
}
|
|
|
|
function rebuildVariableTable(script) {
|
|
let varList = [];
|
|
let errors = [];
|
|
if (script == null) return;
|
|
let lines = script.split('\n');
|
|
let evalContext = "(function() { \n";
|
|
function evaluateExpression(expr) {
|
|
return eval(evalContext + "return " + expr + "; \n})()");
|
|
}
|
|
for (let i = 0; i < lines.length; i++) {
|
|
let line = lines[i];
|
|
let m = line.match(/^\s*([^\s]+)\s*=(.+)$/);
|
|
if (m != null && m.length === 3) {
|
|
let name = m[1];
|
|
try {
|
|
let value = evaluateExpression(m[2]);
|
|
varList.push({name, value});
|
|
evalContext += "const " + name + " = " + value + ";\n"
|
|
} catch (e) {
|
|
errors.push({
|
|
line: i,
|
|
message: e.message
|
|
});
|
|
console.log(e);
|
|
}
|
|
}
|
|
}
|
|
return {varList, errors, evaluateExpression};
|
|
}
|
|
|