Skip to content

Commit

Permalink
feat: stricly assert argument length
Browse files Browse the repository at this point in the history
Closes #12


BREAKING CHANGE:

* functions with variable length arguments must use `...` to capture
  variable parts
  • Loading branch information
nikku committed Nov 1, 2023
1 parent 242d99a commit 152e60f
Show file tree
Hide file tree
Showing 3 changed files with 84 additions and 16 deletions.
28 changes: 14 additions & 14 deletions src/builtins.ts
Original file line number Diff line number Diff line change
Expand Up @@ -375,25 +375,25 @@ const builtins = {
return list.length;
}, [ 'list' ]),

'min': listFn(function(list) {
'min': listFn(function(...list) {
return list.reduce((min, el) => min === null ? el : Math.min(min, el), null);
}, 'number'),

'max': listFn(function(list) {
'max': listFn(function(...list) {
return list.reduce((max, el) => max === null ? el : Math.max(max, el), null);
}, 'number'),

'sum': listFn(function(list) {
'sum': listFn(function(...list) {
return sum(list);
}, 'number'),

'mean': listFn(function(list) {
'mean': listFn(function(...list) {
const s = sum(list);

return s === null ? s : s / list.length;
}, 'number'),

'all': listFn(function(list) {
'all': listFn(function(...list) {

let nonBool = false;

Expand All @@ -412,7 +412,7 @@ const builtins = {

}, 'any?'),

'any': listFn(function(list) {
'any': listFn(function(...list) {

let nonBool = false;

Expand Down Expand Up @@ -478,7 +478,7 @@ const builtins = {
}, []);
}, [ 'list', 'any' ]),

'union': listFn(function(lists) {
'union': listFn(function(...lists) {

return lists.reduce((result, list) => {

Expand Down Expand Up @@ -507,7 +507,7 @@ const builtins = {
return flatten(list);
}, [ 'list' ]),

'product': listFn(function(list) {
'product': listFn(function(...list) {

if (list.length === 0) {
return null;
Expand All @@ -518,7 +518,7 @@ const builtins = {
}, 1);
}, 'number'),

'median': listFn(function(list) {
'median': listFn(function(...list) {

if (list.length === 0) {
return null;
Expand All @@ -527,7 +527,7 @@ const builtins = {
return median(list);
}, 'number'),

'stddev': listFn(function(list) {
'stddev': listFn(function(...list) {

if (list.length < 2) {
return null;
Expand All @@ -536,7 +536,7 @@ const builtins = {
return stddev(list);
}, 'number'),

'mode': listFn(function(list) {
'mode': listFn(function(...list) {
return mode(list);
}, 'number'),

Expand Down Expand Up @@ -730,11 +730,11 @@ const builtins = {
return Object.entries(m).map(([ key, value ]) => ({ key, value }));
}, [ 'context' ]),

'context': listFn(function(_contexts) {
'context': listFn(function(..._contexts) {
throw notImplemented('context');
}, 'context'),

'context merge': listFn(function(_contexts) {
'context merge': listFn(function(..._contexts) {
throw notImplemented('context merge');
}, 'context'),

Expand Down Expand Up @@ -856,7 +856,7 @@ function listFn(fnDefinition, type, parameterNames = null) {
return null;
}

return fnDefinition(args);
return fnDefinition(...args);
};

wrappedFn.$args = parameterNames || parseParameterNames(fnDefinition);
Expand Down
33 changes: 31 additions & 2 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -261,15 +261,44 @@ export class FunctionWrapper {

if (isArray(contextOrArgs)) {
params = contextOrArgs;

// reject
if (params.length > this.parameterNames.length) {

const lastParam = this.parameterNames[this.parameterNames.length - 1];

// strictly check for parameter count provided
// for non var-args functions
if (!lastParam || !lastParam.startsWith('...')) {
return null;
}
}
} else {

// strictly check for required parameter names,
// and fail on wrong parameter name
if (Object.keys(contextOrArgs).some(key => !this.parameterNames.includes(key))) {
if (Object.keys(contextOrArgs).some(
key => !this.parameterNames.includes(key) && !this.parameterNames.includes(`...${key}`)
)) {
return null;
}

params = this.parameterNames.map(n => contextOrArgs[n]);
params = this.parameterNames.reduce((params, name) => {

if (name.startsWith('...')) {
name = name.slice(3);

const value = contextOrArgs[name];

if (!value) {
return params;
} else {
return [ ...params, ...value ];
}
}

return [ ...params, contextOrArgs[name] ];
}, []);
}

return this.fn.call(null, ...params);
Expand Down
39 changes: 39 additions & 0 deletions test/interpreter-spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,45 @@ describe('interpreter', function() {
b: 7
});

// call with wrong args
expr('foo(5)', null, {
foo: function() {
return 5;
}
});

// var args function
expr('foo(1, 2, 3)', [ [ 1, 2, 3 ] ], {
foo: function(...varArgs) {
return [ varArgs ];
}
});

expr('foo(1)', [ 1, [] ], {
foo: function(firstArg, ...varArgs) {
return [ firstArg, varArgs ];
}
});

expr('foo(firstArg: 1)', [ 1, [] ], {
foo: function(firstArg, ...varArgs) {
return [ firstArg, varArgs ];
}
});

expr('foo(firstArg: 1, varArgs: null)', [ 1, [] ], {
foo: function(firstArg, ...varArgs) {
return [ firstArg, varArgs ];
}
});


expr('foo(varArgs: [ 1, 2, 3 ])', [ [ 1, 2, 3 ] ], {
foo: function(...varArgs) {
return [ varArgs ];
}
});

});


Expand Down

0 comments on commit 152e60f

Please sign in to comment.