Skip to content

Commit

Permalink
add unit tests for jme.makeFast
Browse files Browse the repository at this point in the history
  • Loading branch information
christianp committed Feb 13, 2024
1 parent 855c4f6 commit 982b1f8
Show file tree
Hide file tree
Showing 6 changed files with 29 additions and 15 deletions.
1 change: 1 addition & 0 deletions locales/en-GB.json
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,7 @@
"jme.display.simplifyTree.stuck in a loop": "Simplifier is stuck in a loop: <code>{{expr}}</code>",
"jme.calculus.unknown derivative": "Don't know how to differentiate <code>{{tree}}</code>",
"jme.interpreted as": "interpreted as",
"jme.makeFast.no fast definition of function": "The function <code>{{name}}</code> here isn't defined in a way that can be made fast.",
"math.precround.complex": "Can't round to a complex number of decimal places",
"math.siground.complex": "Can't round to a complex number of sig figs",
"math.combinations.complex": "Can't compute combinations of complex numbers",
Expand Down
10 changes: 5 additions & 5 deletions runtime/scripts/jme.js
Original file line number Diff line number Diff line change
Expand Up @@ -4763,7 +4763,6 @@ jme.inferExpressionType = function(tree,scope) {
* @returns {Function}
*/
jme.makeFast = function(tree,scope,names) {
const typed_tree = jme.inferTreeType(tree, scope);
const given_names = names !== undefined;

function fast_eval(t) {
Expand All @@ -4788,9 +4787,9 @@ jme.makeFast = function(tree,scope,names) {
case 'function':
case 'op':
const args = t.args.map(t2 => fast_eval(t2));
const fn = t.matched_function?.fn?.fn;
const fn = t.matched_function && t.matched_function.fn && t.matched_function.fn.fn;
if(!fn) {
throw(new Error(`The function ${t.tok.name} here isn't defined in a way that can be made fast.`));
throw(new Numbas.Error("jme.makeFast.no fast definition of function", {name: t.tok.name}));
}
if(given_names) {
if(names.length > 5 || args.length > 5) {
Expand Down Expand Up @@ -4859,9 +4858,10 @@ jme.makeFast = function(tree,scope,names) {
}
}

let subbed_tree = jme.substituteTree(typed_tree, scope, true, true);
let subbed_tree = jme.substituteTree(tree, scope, true, true);
const typed_tree = jme.inferTreeType(subbed_tree, scope);

let f = fast_eval(subbed_tree);
let f = fast_eval(typed_tree);

if(tree.tok.name) {
Object.defineProperty(f,'name',{value:tree.tok.name});
Expand Down
10 changes: 5 additions & 5 deletions tests/jme-runtime.js
Original file line number Diff line number Diff line change
Expand Up @@ -13162,7 +13162,6 @@ jme.inferExpressionType = function(tree,scope) {
* @returns {Function}
*/
jme.makeFast = function(tree,scope,names) {
const typed_tree = jme.inferTreeType(tree, scope);
const given_names = names !== undefined;

function fast_eval(t) {
Expand All @@ -13187,9 +13186,9 @@ jme.makeFast = function(tree,scope,names) {
case 'function':
case 'op':
const args = t.args.map(t2 => fast_eval(t2));
const fn = t.matched_function?.fn?.fn;
const fn = t.matched_function && t.matched_function.fn && t.matched_function.fn.fn;
if(!fn) {
throw(new Error(`The function ${t.tok.name} here isn't defined in a way that can be made fast.`));
throw(new Numbas.Error("jme.makeFast.no fast definition of function", {name: t.tok.name}));
}
if(given_names) {
if(names.length > 5 || args.length > 5) {
Expand Down Expand Up @@ -13258,9 +13257,10 @@ jme.makeFast = function(tree,scope,names) {
}
}

let subbed_tree = jme.substituteTree(typed_tree, scope, true, true);
let subbed_tree = jme.substituteTree(tree, scope, true, true);
const typed_tree = jme.inferTreeType(subbed_tree, scope);

let f = fast_eval(subbed_tree);
let f = fast_eval(typed_tree);

if(tree.tok.name) {
Object.defineProperty(f,'name',{value:tree.tok.name});
Expand Down
12 changes: 12 additions & 0 deletions tests/jme/jme-tests.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -1445,6 +1445,18 @@ Numbas.queueScript('jme_tests',['qunit','jme','jme-rules','jme-display','jme-cal
treesEqual(assert, scope.evaluate('expression("t*({f})")').tree, target, 'sub in expression JME function with brackets');
treesEqual(assert, Numbas.jme.display.subvars("t*({f})", scope), target, 'Numbas.jme.display.subvars');
});

QUnit.test('Make fast', function(assert) {
var scope = new Numbas.jme.Scope([Numbas.jme.builtinScope]);
scope.setVariable('a', scope.evaluate('5'));

var f1 = jme.makeFast(jme.compile('x^2'), scope, ['x']);
assert.equal(f1(2),4,'x^2 with x=2');
assert.equal(f1(1.5), 9/4, 'x^2 with x=1.5');

var f2 = jme.makeFast(jme.compile('x+a'), scope, ['x']);
assert.equal(f2(2),7,'x+a with x=2');
});

QUnit.module('Scopes');

Expand Down
1 change: 1 addition & 0 deletions tests/locales.js
Original file line number Diff line number Diff line change
Expand Up @@ -1670,6 +1670,7 @@ Numbas.locale = {
"jme.display.simplifyTree.stuck in a loop": "Simplifier is stuck in a loop: <code>{{expr}}</code>",
"jme.calculus.unknown derivative": "Don't know how to differentiate <code>{{tree}}</code>",
"jme.interpreted as": "interpreted as",
"jme.makeFast.no fast definition of function": "The function <code>{{name}}</code> here isn't defined in a way that can be made fast.",
"math.precround.complex": "Can't round to a complex number of decimal places",
"math.siground.complex": "Can't round to a complex number of sig figs",
"math.combinations.complex": "Can't compute combinations of complex numbers",
Expand Down
10 changes: 5 additions & 5 deletions tests/numbas-runtime.js
Original file line number Diff line number Diff line change
Expand Up @@ -12753,7 +12753,6 @@ jme.inferExpressionType = function(tree,scope) {
* @returns {Function}
*/
jme.makeFast = function(tree,scope,names) {
const typed_tree = jme.inferTreeType(tree, scope);
const given_names = names !== undefined;

function fast_eval(t) {
Expand All @@ -12778,9 +12777,9 @@ jme.makeFast = function(tree,scope,names) {
case 'function':
case 'op':
const args = t.args.map(t2 => fast_eval(t2));
const fn = t.matched_function?.fn?.fn;
const fn = t.matched_function && t.matched_function.fn && t.matched_function.fn.fn;
if(!fn) {
throw(new Error(`The function ${t.tok.name} here isn't defined in a way that can be made fast.`));
throw(new Numbas.Error("jme.makeFast.no fast definition of function", {name: t.tok.name}));
}
if(given_names) {
if(names.length > 5 || args.length > 5) {
Expand Down Expand Up @@ -12849,9 +12848,10 @@ jme.makeFast = function(tree,scope,names) {
}
}

let subbed_tree = jme.substituteTree(typed_tree, scope, true, true);
let subbed_tree = jme.substituteTree(tree, scope, true, true);
const typed_tree = jme.inferTreeType(subbed_tree, scope);

let f = fast_eval(subbed_tree);
let f = fast_eval(typed_tree);

if(tree.tok.name) {
Object.defineProperty(f,'name',{value:tree.tok.name});
Expand Down

0 comments on commit 982b1f8

Please sign in to comment.