(i: number, ctx: Context)
| 853 | // Convert estree statement nodes to our simplified node definition |
| 854 | function convertStmts(nodes: p.TSESTree.Statement[], requireReturn: boolean, ctx: Context): Term { |
| 855 | function convertStmt(i: number, ctx: Context): Term { |
| 856 | const last = nodes.length - 1 === i; |
| 857 | const node = nodes[i]; |
| 858 | switch (node.type) { |
| 859 | case "VariableDeclaration": { |
| 860 | if (last && requireReturn) error("return is required", node); |
| 861 | if (node.declarations.length !== 1) error("multiple variable declaration is not allowed", node); |
| 862 | const decl = node.declarations[0]; |
| 863 | if (!decl.init) error("variable initializer is required", decl); |
| 864 | const name = getIdentifier(decl.id); |
| 865 | const init = convertExpr(decl.init, ctx); |
| 866 | const rest: Term = last ? { tag: "var", name, loc: node.loc } : convertStmt(i + 1, ctx); |
| 867 | return { tag: "const", name, init, rest, loc: node.loc }; |
| 868 | } |
| 869 | case "ExportNamedDeclaration": { |
| 870 | if (last && requireReturn) error("return is required", node); |
| 871 | if (!node.declaration || node.declaration.type !== "FunctionDeclaration") { |
| 872 | error("export must have a function declaration", node); |
| 873 | } |
| 874 | return getRecFunc(node.declaration, ctx, last ? null : () => convertStmt(i + 1, ctx)); |
| 875 | } |
| 876 | case "FunctionDeclaration": { |
| 877 | if (last && requireReturn) error("return is required", node); |
| 878 | return getRecFunc(node, ctx, last ? null : () => convertStmt(i + 1, ctx)); |
| 879 | } |
| 880 | case "ExpressionStatement": { |
| 881 | if ( |
| 882 | node.expression.type === "CallExpression" && node.expression.callee.type === "Identifier" && |
| 883 | node.expression.callee.name === "error" |
| 884 | ) { |
| 885 | return { tag: "undefined", loc: node.loc }; |
| 886 | } |
| 887 | const body = convertExpr(node.expression, ctx); |
| 888 | if (last && !requireReturn) return body; |
| 889 | const rest: Term = last ? { tag: "undefined", loc: node.loc } : convertStmt(i + 1, ctx); |
| 890 | return { tag: "seq", body, rest, loc: node.loc }; |
| 891 | } |
| 892 | case "ReturnStatement": { |
| 893 | if (!node.argument) error("return must have an argument", node); |
| 894 | return convertExpr(node.argument, ctx); |
| 895 | } |
| 896 | case "IfStatement": { |
| 897 | const cond = convertExpr(node.test, ctx); |
| 898 | const thn = node.consequent.type == "BlockStatement" |
| 899 | ? convertStmts(node.consequent.body, requireReturn, ctx) |
| 900 | : convertStmts([node.consequent], requireReturn, ctx); |
| 901 | let els: Term; |
| 902 | if (!node.alternate) { |
| 903 | if (!requireReturn) error("else clause is requried", node); |
| 904 | els = nodes[i + 1] ? convertStmt(i + 1, ctx) : { tag: "undefined", loc: node.loc }; |
| 905 | } else { |
| 906 | els = convertStmts( |
| 907 | node.alternate.type == "BlockStatement" ? node.alternate.body : [node.alternate], |
| 908 | requireReturn, |
| 909 | ctx, |
| 910 | ); |
| 911 | } |
| 912 | return newIfNode(cond, thn, els, node.loc); |
no test coverage detected