linny-r 2.0.12 → 2.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/static/images/update.png +0 -0
- package/static/index.html +34 -3
- package/static/linny-r.css +42 -3
- package/static/scripts/linny-r-ctrl.js +6 -0
- package/static/scripts/linny-r-gui-actor-manager.js +6 -6
- package/static/scripts/linny-r-gui-chart-manager.js +54 -32
- package/static/scripts/linny-r-gui-controller.js +52 -35
- package/static/scripts/linny-r-gui-dataset-manager.js +7 -16
- package/static/scripts/linny-r-gui-monitor.js +3 -2
- package/static/scripts/linny-r-gui-paper.js +10 -1
- package/static/scripts/linny-r-gui-repository-browser.js +304 -17
- package/static/scripts/linny-r-gui-undo-redo.js +41 -52
- package/static/scripts/linny-r-model.js +429 -308
- package/static/scripts/linny-r-utils.js +21 -23
- package/static/scripts/linny-r-vm.js +103 -17
@@ -319,7 +319,7 @@ function compareTailFirst(a, b, tail) {
|
|
319
319
|
}
|
320
320
|
|
321
321
|
function endsWithDigits(str) {
|
322
|
-
//
|
322
|
+
// Return trailing digts of `str` (empty string will evaluate as FALSE).
|
323
323
|
let i = str.length - 1,
|
324
324
|
c = str[i],
|
325
325
|
d = '';
|
@@ -332,8 +332,8 @@ function endsWithDigits(str) {
|
|
332
332
|
}
|
333
333
|
|
334
334
|
function indexOfMatchingBracket(str, offset) {
|
335
|
-
//
|
336
|
-
// NOTE:
|
335
|
+
// Return index of closing bracket, ignoring matched [...] inside.
|
336
|
+
// NOTE: Start at offset + 1, assuming that character at offset = '['.
|
337
337
|
let ob = 0, c;
|
338
338
|
for(let i = offset + 1; i < str.length; i++) {
|
339
339
|
c = str.charAt(i);
|
@@ -347,12 +347,12 @@ function indexOfMatchingBracket(str, offset) {
|
|
347
347
|
}
|
348
348
|
}
|
349
349
|
}
|
350
|
-
// No matching bracket => return -1
|
350
|
+
// No matching bracket => return -1.
|
351
351
|
return -1;
|
352
352
|
}
|
353
353
|
|
354
354
|
function monoSpaced(vbl) {
|
355
|
-
//
|
355
|
+
// Remove all non-essential spaces from variable reference `vbl`.
|
356
356
|
// First reduce all whitespace to a single space.
|
357
357
|
return vbl.replace(/\s+/g, ' ')
|
358
358
|
// Then remove spaces after the opening bracket.
|
@@ -834,13 +834,11 @@ function customizeXML(str) {
|
|
834
834
|
// and then load it again for the customization to be performed.
|
835
835
|
if(str.indexOf('!!CUSTOMIZE</name><author>') >= 0) {
|
836
836
|
// Modify `str` -- by default, do nothing, but typical modifications
|
837
|
-
// will replace RexEx patterns by other strings.
|
838
|
-
|
839
|
-
/*
|
837
|
+
// will replace RexEx patterns by other strings.
|
838
|
+
|
840
839
|
const
|
841
|
-
re = /
|
842
|
-
r = '
|
843
|
-
*/
|
840
|
+
re = /pattern/g,
|
841
|
+
r = 'replacement';
|
844
842
|
|
845
843
|
// Trace the changes to the console.
|
846
844
|
console.log('Customizing:', re, r);
|
@@ -868,8 +866,8 @@ function cleanXML(node) {
|
|
868
866
|
}
|
869
867
|
|
870
868
|
function parseXML(xml) {
|
871
|
-
//
|
872
|
-
// (or null if errors)
|
869
|
+
// Parse string `xml` into an XML document, and returns its root node
|
870
|
+
// (or null if errors).
|
873
871
|
xml = XML_PARSER.parseFromString(customizeXML(xml), 'application/xml');
|
874
872
|
const
|
875
873
|
de = xml.documentElement,
|
@@ -880,8 +878,8 @@ function parseXML(xml) {
|
|
880
878
|
}
|
881
879
|
|
882
880
|
function childNodeByTag(node, tag) {
|
883
|
-
//
|
884
|
-
// no such child node exists
|
881
|
+
// Return the XML child node of `node` having node name `tag`, or NULL if
|
882
|
+
// no such child node exists.
|
885
883
|
let cn = null;
|
886
884
|
for (let i = 0; i < node.childNodes.length; i++) {
|
887
885
|
if(node.childNodes[i].tagName === tag) {
|
@@ -893,19 +891,19 @@ function childNodeByTag(node, tag) {
|
|
893
891
|
}
|
894
892
|
|
895
893
|
function nodeContentByTag(node, tag) {
|
896
|
-
//
|
897
|
-
// or the empty string if no such node exists
|
894
|
+
// Return the text content of the child node of `node` having name `tag`,
|
895
|
+
// or the empty string if no such node exists.
|
898
896
|
return nodeContent(childNodeByTag(node, tag));
|
899
897
|
}
|
900
898
|
|
901
899
|
function nodeContent(node) {
|
902
|
-
//
|
900
|
+
// Return the text content of XML element `node`.
|
903
901
|
if(node) {
|
904
|
-
// For text nodes, return their value
|
902
|
+
// For text nodes, return their value.
|
905
903
|
if(node.nodeType === 3) return node.nodeValue;
|
906
|
-
// For empty nodes, return empty string
|
904
|
+
// For empty nodes, return empty string.
|
907
905
|
if(node.childNodes.length === 0) return '';
|
908
|
-
// If first child is text, return its value
|
906
|
+
// If first child is text, return its value.
|
909
907
|
const fcn = node.childNodes.item(0);
|
910
908
|
if(fcn && fcn.nodeType === 3) return fcn.nodeValue;
|
911
909
|
console.log('UNEXPECTED XML', fcn.nodeType, node);
|
@@ -914,8 +912,8 @@ function nodeContent(node) {
|
|
914
912
|
}
|
915
913
|
|
916
914
|
function nodeParameterValue(node, param) {
|
917
|
-
//
|
918
|
-
// this parameter, otherwise the empty string
|
915
|
+
// Return the value of parameter `param` as string if `node` has
|
916
|
+
// this parameter, otherwise the empty string.
|
919
917
|
const a = node.getAttribute(param);
|
920
918
|
return a || '';
|
921
919
|
}
|
@@ -309,7 +309,7 @@ class Expression {
|
|
309
309
|
if(DEBUGGING) {
|
310
310
|
// Show the "time step stack" for --START and --STOP
|
311
311
|
if(action.startsWith('--') || action.startsWith('"')) {
|
312
|
-
action = `[${step.join(', ')}] ${action}`;
|
312
|
+
action = `[${this.step.join(', ')}] ${action}`;
|
313
313
|
}
|
314
314
|
console.log(action);
|
315
315
|
}
|
@@ -2903,7 +2903,11 @@ class VirtualMachine {
|
|
2903
2903
|
vlist = [],
|
2904
2904
|
xlist = [];
|
2905
2905
|
for(const x of this.call_stack) {
|
2906
|
-
|
2906
|
+
// For equations, only show the attribute.
|
2907
|
+
const ons = (x.object === MODEL.equations_dataset ?
|
2908
|
+
(x.attribute.startsWith(':') ? x.method_object_prefix : '') :
|
2909
|
+
x.object.displayName + '|');
|
2910
|
+
vlist.push(ons + x.attribute);
|
2907
2911
|
// Trim spaces around all object-attribute separators in the
|
2908
2912
|
// expression as entered by the modeler.
|
2909
2913
|
xlist.push(x.text.replace(/\s*\|\s*/g, '|'));
|
@@ -6933,7 +6937,8 @@ function VMI_push_method(x, args) {
|
|
6933
6937
|
// and possibly also the entity to be used as its object.
|
6934
6938
|
// NOTE: Methods can only be called "as is" (without prefix) in a
|
6935
6939
|
// method expression. The object of such "as is" method calls is
|
6936
|
-
// the object of the calling method expression `x
|
6940
|
+
// the object of the calling method expression `x`, or for chart
|
6941
|
+
// variables the method object selected for the chart.
|
6937
6942
|
const
|
6938
6943
|
method = args[0].meq,
|
6939
6944
|
mex = method.expression,
|
@@ -7675,7 +7680,13 @@ function VMI_add(x) {
|
|
7675
7680
|
const d = x.pop();
|
7676
7681
|
if(d !== false) {
|
7677
7682
|
if(DEBUGGING) console.log('ADD (' + d.join(', ') + ')');
|
7678
|
-
|
7683
|
+
if(Math.abs(d[0]) === VM.PLUS_INFINITY) {
|
7684
|
+
x.retop(d[0]);
|
7685
|
+
} else if(Math.abs(d[1]) === VM.PLUS_INFINITY) {
|
7686
|
+
x.retop(d[1]);
|
7687
|
+
} else {
|
7688
|
+
x.retop(d[0] + d[1]);
|
7689
|
+
}
|
7679
7690
|
}
|
7680
7691
|
}
|
7681
7692
|
|
@@ -7685,17 +7696,27 @@ function VMI_sub(x) {
|
|
7685
7696
|
const d = x.pop();
|
7686
7697
|
if(d !== false) {
|
7687
7698
|
if(DEBUGGING) console.log('SUB (' + d.join(', ') + ')');
|
7688
|
-
|
7699
|
+
if(d[0] === VM.PLUS_INFINITY || d[1] === VM.MINUS_INFINITY) {
|
7700
|
+
x.retop(VM.PLUS_INFINITY);
|
7701
|
+
} else if(d[0] === VM.MINUS_INFINITY || d[1] === VM.PLUS_INFINITY) {
|
7702
|
+
x.retop(VM.MINUS_INFINITY);
|
7703
|
+
} else {
|
7704
|
+
x.retop(d[0] + d[1]);
|
7705
|
+
}
|
7689
7706
|
}
|
7690
7707
|
}
|
7691
7708
|
|
7692
7709
|
function VMI_mul(x) {
|
7693
7710
|
// Pop the top number on the stack, and multiply it with the new
|
7694
|
-
// top number
|
7711
|
+
// top number.
|
7695
7712
|
const d = x.pop();
|
7696
7713
|
if(d !== false) {
|
7697
7714
|
if(DEBUGGING) console.log('MUL (' + d.join(', ') + ')');
|
7698
|
-
|
7715
|
+
if(Math.abs(d[0]) === VM.PLUS_INFINITY || Math.abs(d[1]) === VM.PLUS_INFINITY) {
|
7716
|
+
x.retop(VM.PLUS_INFINITY * Math.sign(d[0] * d[1]));
|
7717
|
+
} else {
|
7718
|
+
x.retop(d[0] * d[1]);
|
7719
|
+
}
|
7699
7720
|
}
|
7700
7721
|
}
|
7701
7722
|
|
@@ -7707,7 +7728,19 @@ function VMI_div(x) {
|
|
7707
7728
|
if(DEBUGGING) console.log('DIV (' + d.join(', ') + ')');
|
7708
7729
|
if(Math.abs(d[1]) <= VM.NEAR_ZERO) {
|
7709
7730
|
x.retop(VM.DIV_ZERO);
|
7731
|
+
} else if(Math.abs(d[0]) === VM.PLUS_INFINITY) {
|
7732
|
+
if(Math.abs(d[1]) === VM.PLUS_INFINITY) {
|
7733
|
+
// Treat INF / INF as 1.
|
7734
|
+
x.retop(Math.sign(d[0]) * Math.sign(d[1]));
|
7735
|
+
} else {
|
7736
|
+
// Push the + or - infinity value.
|
7737
|
+
x.retop(d[0]);
|
7738
|
+
}
|
7739
|
+
} else if(Math.abs(d[1]) === VM.PLUS_INFINITY) {
|
7740
|
+
// Treat N / Infinity as 0 for any non-infinite value of N.
|
7741
|
+
x.retop(0);
|
7710
7742
|
} else {
|
7743
|
+
// Standard division.
|
7711
7744
|
x.retop(d[0] / d[1]);
|
7712
7745
|
}
|
7713
7746
|
}
|
@@ -7722,7 +7755,19 @@ function VMI_div_zero(x) {
|
|
7722
7755
|
if(DEBUGGING) console.log('DIV-ZERO (' + d.join(', ') + ')');
|
7723
7756
|
if(Math.abs(d[1]) <= VM.NEAR_ZERO) {
|
7724
7757
|
x.retop(d[0]);
|
7758
|
+
} else if(Math.abs(d[0]) === VM.PLUS_INFINITY) {
|
7759
|
+
if(Math.abs(d[1]) === VM.PLUS_INFINITY) {
|
7760
|
+
// Treat INF / INF as 1.
|
7761
|
+
x.retop(Math.sign(d[0]) * Math.sign(d[1]));
|
7762
|
+
} else {
|
7763
|
+
// Push the + or - infinity value.
|
7764
|
+
x.retop(d[0]);
|
7765
|
+
}
|
7766
|
+
} else if(Math.abs(d[1]) === VM.PLUS_INFINITY) {
|
7767
|
+
// Treat N / Infinity as 0 for any non-infinite value of N.
|
7768
|
+
x.retop(0);
|
7725
7769
|
} else {
|
7770
|
+
// Standard division.
|
7726
7771
|
x.retop(d[0] / d[1]);
|
7727
7772
|
}
|
7728
7773
|
}
|
@@ -7738,6 +7783,9 @@ function VMI_mod(x) {
|
|
7738
7783
|
if(DEBUGGING) console.log('DIV (' + d.join(', ') + ')');
|
7739
7784
|
if(Math.abs(d[1]) <= VM.NEAR_ZERO) {
|
7740
7785
|
x.retop(VM.DIV_ZERO);
|
7786
|
+
} else if(Math.abs(d[0]) === VM.PLUS_INFINITY || Math.abs(d[1]) === VM.PLUS_INFINITY) {
|
7787
|
+
// If either operand is infinite, return 0 as remainder.
|
7788
|
+
x.retop(0);
|
7741
7789
|
} else {
|
7742
7790
|
x.retop(d[0] % d[1]); // % is the modulo operator in JavaScript.
|
7743
7791
|
}
|
@@ -7759,7 +7807,16 @@ function VMI_power(x) {
|
|
7759
7807
|
const d = x.pop();
|
7760
7808
|
if(d !== false) {
|
7761
7809
|
if(DEBUGGING) console.log('POWER (' + d.join(', ') + ')');
|
7762
|
-
|
7810
|
+
const r = Math.pow(d[0], d[1]);
|
7811
|
+
if(isNaN(r)) {
|
7812
|
+
x.retop(VM.BAD_CALC);
|
7813
|
+
} else if(r >= VM.PLUS_INFINITY) {
|
7814
|
+
x.retop(VM.PLUS_INFINITY);
|
7815
|
+
} else if(r <= VM.MINUS_INFINITY) {
|
7816
|
+
x.retop(VM.MINUS_INFINITY);
|
7817
|
+
} else {
|
7818
|
+
x.retop(r);
|
7819
|
+
}
|
7763
7820
|
}
|
7764
7821
|
}
|
7765
7822
|
|
@@ -7771,6 +7828,8 @@ function VMI_sqrt(x) {
|
|
7771
7828
|
if(DEBUGGING) console.log('SQRT ' + d);
|
7772
7829
|
if(d < 0) {
|
7773
7830
|
x.retop(VM.BAD_CALC);
|
7831
|
+
} else if (d === VM.PLUS_INFINITY) {
|
7832
|
+
x.retop(VM.PLUS_INFINITY);
|
7774
7833
|
} else {
|
7775
7834
|
x.retop(Math.sqrt(d));
|
7776
7835
|
}
|
@@ -7782,7 +7841,12 @@ function VMI_sin(x) {
|
|
7782
7841
|
const d = x.top();
|
7783
7842
|
if(d !== false) {
|
7784
7843
|
if(DEBUGGING) console.log('SIN ' + d);
|
7785
|
-
|
7844
|
+
const r = Math.sin(d);
|
7845
|
+
if(isNaN(r) || Math.abs(d) === VM.PLUS_INFINITY) {
|
7846
|
+
x.retop(VM.BAD_CALC);
|
7847
|
+
} else {
|
7848
|
+
x.retop(r);
|
7849
|
+
}
|
7786
7850
|
}
|
7787
7851
|
}
|
7788
7852
|
|
@@ -7791,7 +7855,12 @@ function VMI_cos(x) {
|
|
7791
7855
|
const d = x.top();
|
7792
7856
|
if(d !== false) {
|
7793
7857
|
if(DEBUGGING) console.log('COS ' + d);
|
7794
|
-
|
7858
|
+
const r = Math.cos(d);
|
7859
|
+
if(isNaN(r) || Math.abs(d) === VM.PLUS_INFINITY) {
|
7860
|
+
x.retop(VM.BAD_CALC);
|
7861
|
+
} else {
|
7862
|
+
x.retop(r);
|
7863
|
+
}
|
7795
7864
|
}
|
7796
7865
|
}
|
7797
7866
|
|
@@ -7800,7 +7869,12 @@ function VMI_atan(x) {
|
|
7800
7869
|
const d = x.top();
|
7801
7870
|
if(d !== false) {
|
7802
7871
|
if(DEBUGGING) console.log('ATAN ' + d);
|
7803
|
-
|
7872
|
+
const r = Math.atan(d);
|
7873
|
+
if(isNaN(r) || Math.abs(d) === VM.PLUS_INFINITY) {
|
7874
|
+
x.retop(VM.BAD_CALC);
|
7875
|
+
} else {
|
7876
|
+
x.retop(r);
|
7877
|
+
}
|
7804
7878
|
}
|
7805
7879
|
}
|
7806
7880
|
|
@@ -7812,6 +7886,8 @@ function VMI_ln(x) {
|
|
7812
7886
|
if(DEBUGGING) console.log('LN ' + d);
|
7813
7887
|
if(d < 0) {
|
7814
7888
|
x.retop(VM.BAD_CALC);
|
7889
|
+
} else if(d === VM.PLUS_INFINITY) {
|
7890
|
+
x.retop(VM.PLUS_INFINITY);
|
7815
7891
|
} else {
|
7816
7892
|
x.retop(Math.log(d));
|
7817
7893
|
}
|
@@ -7823,7 +7899,13 @@ function VMI_exp(x) {
|
|
7823
7899
|
const d = x.top();
|
7824
7900
|
if(d !== false) {
|
7825
7901
|
if(DEBUGGING) console.log('EXP ' + d);
|
7826
|
-
|
7902
|
+
if(d === VM.PLUS_INFINITY) {
|
7903
|
+
x.retop(VM.PLUS_INFINITY);
|
7904
|
+
} else if(d === VM.MINUS_INFINITY) {
|
7905
|
+
x.retop(0);
|
7906
|
+
} else {
|
7907
|
+
x.retop(Math.exp(d));
|
7908
|
+
}
|
7827
7909
|
}
|
7828
7910
|
}
|
7829
7911
|
|
@@ -7833,12 +7915,16 @@ function VMI_log(x) {
|
|
7833
7915
|
let d = x.pop();
|
7834
7916
|
if(d !== false) {
|
7835
7917
|
if(DEBUGGING) console.log('LOG (' + d.join(', ') + ')');
|
7836
|
-
|
7837
|
-
|
7838
|
-
}
|
7839
|
-
|
7918
|
+
if(Math.abs(d[0]) === VM.PLUS_INFINITY || Math.abs(d[1]) === VM.PLUS_INFINITY) {
|
7919
|
+
x.retop(VM.BAD_CALC);
|
7920
|
+
} else {
|
7921
|
+
try {
|
7922
|
+
d = Math.log(d[1]) / Math.log(d[0]);
|
7923
|
+
} catch(err) {
|
7924
|
+
d = VM.BAD_CALC;
|
7925
|
+
}
|
7926
|
+
x.retop(d);
|
7840
7927
|
}
|
7841
|
-
x.retop(d);
|
7842
7928
|
}
|
7843
7929
|
}
|
7844
7930
|
|