author | Alan Dipert
<alan@dipert.org> 2019-11-03 13:44:44 UTC |
committer | Alan Dipert
<alan@dipert.org> 2019-11-03 13:44:44 UTC |
parent | cb4a4d7fac1a48bb9eb0ad9f5dbe65a022316478 |
jacl.js | +27 | -12 |
diff --git a/jacl.js b/jacl.js index e36c048..af46f4f 100644 --- a/jacl.js +++ b/jacl.js @@ -1418,22 +1418,37 @@ const emitNode = (print, node) => { print('}'); if (context === 'sval') print(')()'); break; - case 'lambda': - print('(function(){\n'); - // TODO enhance arg length check - print(`if(arguments.length!==${node.lambdaList.required.length})throw new Error("Invalid number of arguments: "+arguments.length);\n`); - let argidx = 0; - if (node.lambdaList.required.length) print('var '); - for (let i = 0; i < node.lambdaList.required.length; i++) { - print(mungeSym(node.lambdaList.required[i], 'local')); - print(`=arguments[${argidx++}]`); - if (i < node.lambdaList.required.length-1) print(','); + case 'lambda': { + // Emit argument names + print('(function('); + print([ + ...node.lambdaList.required, + ...node.lambdaList.optional.map(o => o.name) + ].map(s => mungeSym(s, 'local')).join(',')); + print('){\n'); + + // Emit argument length checks + const min = node.lambdaList.required.length, + max = node.lambdaList.rest ? false : min + node.lambdaList.optional.length; + + if (min > 0 && min === max) { + print(`if (arguments.length !== ${min}) throw new Error('Called with invalid number of arguments: ' + arguments.length);\n`); + } else { + if (min > 0) { + print(`if (arguments.length < ${min}) throw new Error('Called with too few arguments: ' + arguments.length);\n`); + } + if (max) { + print(`if (arguments.length > ${max}) throw new Error('Called with too many arguments: ' + arguments.length);\n`); + } } - if (node.lambdaList.required.length) print(';'); + + // TODO bind optional svars all to true + // TODO populate optionals, svars depending on arg length + emitBlock(print, node.statements, node.ret); print('})'); break; - case 'call': + } case 'call': if (context === 'return') print('return '); emitNode(print, node.f); print('(');