(node: p.TSESTree.Expression, ctx: Context)
| 290 | } |
| 291 | |
| 292 | function convertExpr(node: p.TSESTree.Expression, ctx: Context): Term { |
| 293 | switch (node.type) { |
| 294 | case "BinaryExpression": { |
| 295 | if (node.operator !== "+") error(`unsupported operator: ${node.operator}`, node); |
| 296 | if (node.left.type === "PrivateIdentifier") error("private identifer is not allowed", node.left); |
| 297 | const left = convertExpr(node.left, ctx); |
| 298 | const right = convertExpr(node.right, ctx); |
| 299 | return { tag: "add", left, right, loc: node.loc }; |
| 300 | } |
| 301 | case "Identifier": |
| 302 | return { tag: "var", name: node.name, loc: node.loc }; |
| 303 | // deno-lint-ignore no-fallthrough |
| 304 | case "Literal": |
| 305 | switch (typeof node.value) { |
| 306 | case "number": |
| 307 | return { tag: "number", n: node.value, loc: node.loc }; |
| 308 | case "boolean": |
| 309 | return { tag: node.value ? "true" : "false", loc: node.loc }; |
| 310 | default: |
| 311 | error(`unsupported literal: ${node.value}`, node); |
| 312 | } |
| 313 | case "ArrowFunctionExpression": { |
| 314 | const typeParams = node.typeParameters?.params.map((typeParameter) => typeParameter.name.name); |
| 315 | const newCtx = typeParams ? addDefinedTypeVars(typeParams, ctx) : ctx; |
| 316 | const params = node.params.map((param) => { |
| 317 | const { name, type } = getParam(param); |
| 318 | return { name, type: simplifyType(type, newCtx) }; |
| 319 | }); |
| 320 | if (node.returnType) error("return type is not required for arrow function", node.returnType); |
| 321 | const body = node.body.type === "BlockStatement" |
| 322 | ? convertStmts(node.body.body, true, newCtx) |
| 323 | : convertExpr(node.body, newCtx); |
| 324 | const func: Term = { tag: "func", params, body, loc: node.loc }; |
| 325 | return typeParams ? { tag: "typeAbs", typeParams, body: func, loc: node.typeParameters!.loc } : func; |
| 326 | } |
| 327 | case "CallExpression": { |
| 328 | const args = node.arguments.map((argument) => { |
| 329 | if (argument.type === "SpreadElement") error("argument must be an expression", argument); |
| 330 | return convertExpr(argument, ctx); |
| 331 | }); |
| 332 | let func = convertExpr(node.callee, ctx); |
| 333 | if (node.typeArguments) { |
| 334 | const typeArgs = node.typeArguments.params.map((param) => simplifyType(convertType(param), ctx)); |
| 335 | func = { tag: "typeApp", typeAbs: func, typeArgs, loc: node.loc }; |
| 336 | } |
| 337 | return { tag: "call", func, args, loc: node.loc }; |
| 338 | } |
| 339 | case "TSAsExpression": |
| 340 | case "TSTypeAssertion": { |
| 341 | if (node.expression.type !== "ObjectExpression") { |
| 342 | error(`type assertion must be <TYPE>{ tag: "TAG", val: EXPR }`, node); |
| 343 | } |
| 344 | const ty = simplifyType(convertType(node.typeAnnotation), ctx); |
| 345 | const { tag, val } = getTagAndVal(node.expression); |
| 346 | const term = convertExpr(val, ctx); |
| 347 | return { tag: "taggedUnionNew", label: tag, term, as: ty, loc: node.loc }; |
| 348 | } |
| 349 | case "MemberExpression": { |
no test coverage detected