diff --git a/kiss/src/kiss/Macros.hx b/kiss/src/kiss/Macros.hx index a5cd8524..c9223a20 100644 --- a/kiss/src/kiss/Macros.hx +++ b/kiss/src/kiss/Macros.hx @@ -699,48 +699,60 @@ class Macros { macros["assertLet"] = ifLet.bind(true); k.doc("awaitLet", 2, null, "(awaitLet [] )"); - function awaitLet(wholeExp:ReaderExp, exps:Array, k:KissState) { + function awaitLet(rejectionHandler:ReaderExp->ReaderExp, wholeExp:ReaderExp, exps:Array, k:KissState) { var bindingList = exps[0].bindingList("awaitLet"); var firstName = bindingList.shift(); var firstValue = bindingList.shift(); var b = wholeExp.expBuilder(); - var firstNameStr = firstName.symbolNameValue(); - var error = b.callSymbol("+", [b.str('awaitLet $firstNameStr rejected promise: '), b.symbol("reason")]); - var rejectionHandler = switch (exps[1].def) { - case CallExp({pos: _, def: Symbol("catch")}, args): - exps.splice(1,1); - b.callSymbol("lambda", args); + if (rejectionHandler == null) { + function error(firstName:ReaderExp) { + return b.callSymbol("+", [b.str('awaitLet ${firstName.symbolNameValue()} rejected promise: '), b.symbol("reason")]); + } + rejectionHandler = switch (exps[1].def) { + case CallExp({pos: _, def: Symbol("catch")}, args): + exps.splice(1,1); + (exp) -> b.callSymbol("lambda", args); + default: + (firstName) -> b.callSymbol("lambda", [ + b.list([b.symbol("reason")]), + b.callSymbol("#when", [ + b.symbol("vscode"), + b.callSymbol("Vscode.window.showErrorMessage", [error(firstName)]), + ]), + // If running VSCode js, this throw will be a no-op but it makes the expression type-unify: + b.callSymbol("throw", [ + error(firstName) + ]) + ]); + } + } + + var innerExp = if (bindingList.length == 0) { + b.begin(exps.slice(1)); + } else { + awaitLet(rejectionHandler, wholeExp, [b.list(bindingList)].concat(exps.slice(1)), k); + }; + switch(firstName.def) { + case MetaExp("sync", firstName): + return b.let([firstName, firstValue], [innerExp]); + case MetaExp(other, _): + throw KissError.fromExp(firstName, 'bad meta annotation &$other'); default: - b.callSymbol("lambda", [ - b.list([b.symbol("reason")]), - b.callSymbol("#when", [ - b.symbol("vscode"), - b.callSymbol("Vscode.window.showErrorMessage", [error]), - ]), - // If running VSCode js, this throw will be a no-op but it makes the expression type-unify: - b.callSymbol("throw", [ - error - ]) - ]); } return b.call(b.field("then", firstValue), [ b.callSymbol("lambda", [ b.list([firstName]), - if (bindingList.length == 0) { - b.begin(exps.slice(1)); - } else { - awaitLet(wholeExp, [b.list(bindingList)].concat(exps.slice(1)), k); - } + innerExp ]), // Handle rejections: - rejectionHandler + rejectionHandler(firstName) ]); } - macros["awaitLet"] = awaitLet; + macros["awaitLet"] = awaitLet.bind(null); k.doc("whileLet", 2, null, "(whileLet [] )"); macros["whileLet"] = (wholeExp:ReaderExp, exps:Array, k:KissState) -> { diff --git a/projects/kiss-vscode/src/commands/KissTools.kiss b/projects/kiss-vscode/src/commands/KissTools.kiss index 1314e262..b83ba237 100644 --- a/projects/kiss-vscode/src/commands/KissTools.kiss +++ b/projects/kiss-vscode/src/commands/KissTools.kiss @@ -52,22 +52,22 @@ class ${className} {} (showTextDocument (Uri.file (correspondingFile .fileName .document activeTextEditor)))) (function insertUTestCase [&opt _] - (awaitLet [testName (inputBox)] - (let [testName - "$(.toUpperCase (testName.substr 0 1))$(testName.substr 1)"] - (awaitLet [_ (insert + (awaitLet [testName (inputBox) + &sync testName + "$(.toUpperCase (testName.substr 0 1))$(testName.substr 1)" + _ (insert "function test${testName}() { _test${testName}(); } ") - _ (showTextDocument (Uri.file (correspondingFile .fileName .document activeTextEditor)))] - (let [pos (activeTextEditor.document.positionAt .length (activeTextEditor.document.getText))] - (awaitLet [_ (insertAt pos + _ (showTextDocument (Uri.file (correspondingFile .fileName .document activeTextEditor))) + &sync pos (activeTextEditor.document.positionAt .length (activeTextEditor.document.getText)) + _ (insertAt pos " (function _test${testName} [] (Assert.pass)) -")] - (let [endPos (activeTextEditor.document.positionAt .length (activeTextEditor.document.getText))] - (activeTextEditor.revealRange (new Range pos endPos)) - (set activeTextEditor.selection (new Selection pos endPos))))))))) \ No newline at end of file +") + &sync endPos (activeTextEditor.document.positionAt .length (activeTextEditor.document.getText))] + (activeTextEditor.revealRange (new Range pos endPos)) + (set activeTextEditor.selection (new Selection pos endPos)))) \ No newline at end of file