diff --git a/package-lock.json b/package-lock.json index 6d15a9d..50cbe74 100644 --- a/package-lock.json +++ b/package-lock.json @@ -971,18 +971,18 @@ } }, "@fink/larix": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@fink/larix/-/larix-1.0.1.tgz", - "integrity": "sha512-JFh8ibfk9DQilDDepnYeEcF9JMbQ3fXciGWIJn0adXQUhWwBwfgR2AtCk1H+JXEloLqRF/e8zxLZmFVY5lT4yg==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@fink/larix/-/larix-1.1.0.tgz", + "integrity": "sha512-Vi4uAxgMTnmjRYguYP0/tGFD20Y9RFq2ExGqO0LdoPY9jHJgtzyafPrdau4iE4Fdj+Vpd6VUmpcUCN18vIU3rQ==", "dev": true, "requires": { "@fink/prattler": "^1.0.0" } }, "@fink/prattler": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@fink/prattler/-/prattler-1.0.0.tgz", - "integrity": "sha512-SUymJhHOolabThVRe0SwkYkQFpXJDQgGijb+0525WN94dzQ0F3RX87ojIeXdw69exx1KoS2joLboY8B0YFgzKQ==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@fink/prattler/-/prattler-1.0.1.tgz", + "integrity": "sha512-+7rTrsmFNHi0WpzL3f8hIjbiH6muH+kTxc0CqtpRRd5jQ7qbosN4TTWzzGj5cogu2W3guZQzPz8ISw5HOxYVjA==", "dev": true, "requires": { "@fink/snippet": "^1.0.1" @@ -1654,15 +1654,29 @@ "@octokit/types": "^2.0.0" } }, + "@octokit/core": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/@octokit/core/-/core-2.4.2.tgz", + "integrity": "sha512-fUx/Qt774cgiPhb3HRKfdl6iufVL/ltECkwkCg373I4lIPYvAPY4cbidVZqyVqHI+ThAIlFlTW8FT4QHChv3Sg==", + "dev": true, + "requires": { + "@octokit/auth-token": "^2.4.0", + "@octokit/graphql": "^4.3.1", + "@octokit/request": "^5.3.1", + "@octokit/types": "^2.0.0", + "before-after-hook": "^2.1.0", + "universal-user-agent": "^5.0.0" + } + }, "@octokit/endpoint": { - "version": "5.5.2", - "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-5.5.2.tgz", - "integrity": "sha512-ICDcRA0C2vtTZZGud1nXRrBLXZqFayodXAKZfo3dkdcLNqcHsgaz3YSTupbURusYeucSVRjjG+RTcQhx6HPPcg==", + "version": "5.5.3", + "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-5.5.3.tgz", + "integrity": "sha512-EzKwkwcxeegYYah5ukEeAI/gYRLv2Y9U5PpIsseGSFDk+G3RbipQGBs8GuYS1TLCtQaqoO66+aQGtITPalxsNQ==", "dev": true, "requires": { "@octokit/types": "^2.0.0", "is-plain-object": "^3.0.0", - "universal-user-agent": "^4.0.0" + "universal-user-agent": "^5.0.0" }, "dependencies": { "is-plain-object": { @@ -1682,10 +1696,32 @@ } } }, + "@octokit/graphql": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-4.3.1.tgz", + "integrity": "sha512-hCdTjfvrK+ilU2keAdqNBWOk+gm1kai1ZcdjRfB30oA3/T6n53UVJb7w0L5cR3/rhU91xT3HSqCd+qbvH06yxA==", + "dev": true, + "requires": { + "@octokit/request": "^5.3.0", + "@octokit/types": "^2.0.0", + "universal-user-agent": "^4.0.0" + }, + "dependencies": { + "universal-user-agent": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-4.0.1.tgz", + "integrity": "sha512-LnST3ebHwVL2aNe4mejI9IQh2HfZ1RLo8Io2HugSif8ekzD1TlWpHpColOB/eh8JHMLkGH3Akqf040I+4ylNxg==", + "dev": true, + "requires": { + "os-name": "^3.1.0" + } + } + } + }, "@octokit/plugin-paginate-rest": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-1.1.2.tgz", - "integrity": "sha512-jbsSoi5Q1pj63sC16XIUboklNw+8tL9VOnJsWycWYR78TKss5PVpIPb1TUUcMQ+bBh7cY579cVAWmf5qG+dw+Q==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-2.0.1.tgz", + "integrity": "sha512-xtW3AQoGDD0un/AkPjIndTdFO+O/My0I15TArvrbJirBCV91R1ElrE3gRcsUJENP3t/vveiQ9C6XQjo9sS2xQg==", "dev": true, "requires": { "@octokit/types": "^2.0.1" @@ -1698,9 +1734,9 @@ "dev": true }, "@octokit/plugin-rest-endpoint-methods": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-2.4.0.tgz", - "integrity": "sha512-EZi/AWhtkdfAYi01obpX0DF7U6b1VRr30QNQ5xSFPITMdLSfhcBqjamE3F+sKcxPbD7eZuMHu3Qkk2V+JGxBDQ==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-3.2.0.tgz", + "integrity": "sha512-k+RLsegQn4s0wvAFYuk3R18FVKRg3ktvzIGW6MkmrSiSXBwYfaEsv4CuPysyef0DL+74DRj/X9MLJYlbleUO+Q==", "dev": true, "requires": { "@octokit/types": "^2.0.1", @@ -1708,9 +1744,9 @@ } }, "@octokit/request": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/@octokit/request/-/request-5.3.1.tgz", - "integrity": "sha512-5/X0AL1ZgoU32fAepTfEoggFinO3rxsMLtzhlUX+RctLrusn/CApJuGFCd0v7GMFhF+8UiCsTTfsu7Fh1HnEJg==", + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/@octokit/request/-/request-5.3.2.tgz", + "integrity": "sha512-7NPJpg19wVQy1cs2xqXjjRq/RmtSomja/VSWnptfYwuBxLdbYh2UjhGi0Wx7B1v5Iw5GKhfFDQL7jM7SSp7K2g==", "dev": true, "requires": { "@octokit/endpoint": "^5.5.0", @@ -1720,7 +1756,7 @@ "is-plain-object": "^3.0.0", "node-fetch": "^2.3.0", "once": "^1.4.0", - "universal-user-agent": "^4.0.0" + "universal-user-agent": "^5.0.0" }, "dependencies": { "is-plain-object": { @@ -1752,33 +1788,21 @@ } }, "@octokit/rest": { - "version": "16.43.1", - "resolved": "https://registry.npmjs.org/@octokit/rest/-/rest-16.43.1.tgz", - "integrity": "sha512-gfFKwRT/wFxq5qlNjnW2dh+qh74XgTQ2B179UX5K1HYCluioWj8Ndbgqw2PVqa1NnVJkGHp2ovMpVn/DImlmkw==", + "version": "17.0.0", + "resolved": "https://registry.npmjs.org/@octokit/rest/-/rest-17.0.0.tgz", + "integrity": "sha512-nSlmyy1DBEOsC4voRbk/SN56V/iuZfxZzjFFz+ocb2MAYwHC+z1TyVOMV9W630dVn9ukioJO34VD5NSYwcgFWg==", "dev": true, "requires": { - "@octokit/auth-token": "^2.4.0", - "@octokit/plugin-paginate-rest": "^1.1.1", + "@octokit/core": "^2.4.0", + "@octokit/plugin-paginate-rest": "^2.0.0", "@octokit/plugin-request-log": "^1.0.0", - "@octokit/plugin-rest-endpoint-methods": "2.4.0", - "@octokit/request": "^5.2.0", - "@octokit/request-error": "^1.0.2", - "atob-lite": "^2.0.0", - "before-after-hook": "^2.0.0", - "btoa-lite": "^1.0.0", - "deprecation": "^2.0.0", - "lodash.get": "^4.4.2", - "lodash.set": "^4.3.2", - "lodash.uniq": "^4.5.0", - "octokit-pagination-methods": "^1.1.0", - "once": "^1.4.0", - "universal-user-agent": "^4.0.0" + "@octokit/plugin-rest-endpoint-methods": "^3.0.0" } }, "@octokit/types": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-2.1.1.tgz", - "integrity": "sha512-89LOYH+d/vsbDX785NOfLxTW88GjNd0lWRz1DVPVsZgg9Yett5O+3MOvwo7iHgvUwbFz0mf/yPIjBkUbs4kxoQ==", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-2.2.0.tgz", + "integrity": "sha512-iEeW3XlkxeM/CObeoYvbUv24Oe+DldGofY+3QyeJ5XKKA6B+V94ePk14EDCarseWdMs6afKZPv3dFq8C+SY5lw==", "dev": true, "requires": { "@types/node": ">= 8" @@ -1851,12 +1875,12 @@ "dev": true }, "@semantic-release/github": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/@semantic-release/github/-/github-7.0.3.tgz", - "integrity": "sha512-4Y2nqruKHsdoayq/H/lMWudONXHLbYtSBDZPktoTrvdJZNQkLhjnxCwDUTKo8G29aI81RuoYKUHv6GSgyJDtGQ==", + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/@semantic-release/github/-/github-7.0.4.tgz", + "integrity": "sha512-qQi41eGIa/tne7T8rvQK+xJNoyadOmd5mVsNZUUqZCVueiUkCItspJ7Mgy5ZWuhwlo28+hKeT/4zJ6MIG6er2Q==", "dev": true, "requires": { - "@octokit/rest": "^16.43.0", + "@octokit/rest": "^17.0.0", "@semantic-release/error": "^2.2.0", "aggregate-error": "^3.0.0", "bottleneck": "^2.18.1", @@ -1875,9 +1899,9 @@ } }, "@semantic-release/npm": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/@semantic-release/npm/-/npm-7.0.2.tgz", - "integrity": "sha512-lugR8jvP81tDb5lmmRL7khntSIew9jsGrNac4ec381mU+CsuBbaKgpvOMEYys0QC0CXrN4yU8Ltpq+RQD5Mc+g==", + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/@semantic-release/npm/-/npm-7.0.3.tgz", + "integrity": "sha512-3wOXMtAdJkaAnW5183iSmWSimtUmOx7m6g/DWPYRs2Gq6iyB+ztMmhgwbn6luNcM9t6pGbgHvRPEXpWkygMxCA==", "dev": true, "requires": { "@semantic-release/error": "^2.2.0", @@ -1892,7 +1916,7 @@ "read-pkg": "^5.0.0", "registry-auth-token": "^4.0.0", "semver": "^7.1.2", - "tempy": "^0.3.0" + "tempy": "^0.4.0" }, "dependencies": { "cross-spawn": { @@ -2002,9 +2026,9 @@ } }, "semver": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.1.2.tgz", - "integrity": "sha512-BJs9T/H8sEVHbeigqzIEo57Iu/3DG6c4QoqTfbQB3BPA4zgzAomh/Fk9E7QtjWQ8mx2dgA9YCfSF4y9k9bHNpQ==", + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.1.3.tgz", + "integrity": "sha512-ekM0zfiA9SCBlsKa2X1hxyxiI4L3B6EbVJkkdgQXnSEEaHlGdvyodMruTiulSRWMMB4NeIuYNMC9rTKTz97GxA==", "dev": true }, "shebang-command": { @@ -2156,9 +2180,9 @@ } }, "@types/node": { - "version": "13.7.0", - "resolved": "https://registry.npmjs.org/@types/node/-/node-13.7.0.tgz", - "integrity": "sha512-GnZbirvmqZUzMgkFn70c74OQpTTUcCzlhQliTzYjQMqg+hVKcDnxdL19Ne3UdYzdMA/+W3eb646FWn/ZaT1NfQ==", + "version": "13.7.4", + "resolved": "https://registry.npmjs.org/@types/node/-/node-13.7.4.tgz", + "integrity": "sha512-oVeL12C6gQS/GAExndigSaLxTrKpQPxewx9bOcwfvJiJge4rr7wNaph4J+ns5hrmIV2as5qxqN8YKthn9qh0jw==", "dev": true }, "@types/normalize-package-data": { @@ -2462,12 +2486,6 @@ "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==", "dev": true }, - "atob-lite": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/atob-lite/-/atob-lite-2.0.0.tgz", - "integrity": "sha1-D+9a1G8b16hQLGVyfwNn1e5D1pY=", - "dev": true - }, "aws-sign2": { "version": "0.7.0", "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", @@ -2824,12 +2842,6 @@ "node-int64": "^0.4.0" } }, - "btoa-lite": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/btoa-lite/-/btoa-lite-1.0.0.tgz", - "integrity": "sha1-M3dm2hWAEhD92VbCLpxokaudAzc=", - "dev": true - }, "buffer-from": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", @@ -4510,16 +4522,17 @@ "dev": true }, "fast-glob": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.1.1.tgz", - "integrity": "sha512-nTCREpBY8w8r+boyFYAx21iL6faSsQynliPHM4Uf56SbkyohCNxpVPEH9xrF5TXKy+IsjkPUHDKiUkzBVRXn9g==", + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.2.tgz", + "integrity": "sha512-UDV82o4uQyljznxwMxyVRJgZZt3O5wENYojjzbaGEGZgeOxkLFf+V4cnUD+krzb2F72E18RhamkMZ7AdeggF7A==", "dev": true, "requires": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", "glob-parent": "^5.1.0", "merge2": "^1.3.0", - "micromatch": "^4.0.2" + "micromatch": "^4.0.2", + "picomatch": "^2.2.1" }, "dependencies": { "braces": { @@ -8157,12 +8170,6 @@ "integrity": "sha1-ZHYsSGGAglGKw99Mz11YhtriA0c=", "dev": true }, - "lodash.get": { - "version": "4.4.2", - "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", - "integrity": "sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk=", - "dev": true - }, "lodash.ismatch": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/lodash.ismatch/-/lodash.ismatch-4.4.0.tgz", @@ -8187,12 +8194,6 @@ "integrity": "sha1-dx7Hg540c9nEzeKLGTlMNWL09tM=", "dev": true }, - "lodash.set": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/lodash.set/-/lodash.set-4.3.2.tgz", - "integrity": "sha1-2HV7HagH3eJIFrDWqEvqGnYjCyM=", - "dev": true - }, "lodash.sortby": { "version": "4.7.0", "resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz", @@ -8205,12 +8206,6 @@ "integrity": "sha1-JMS/zWsvuji/0FlNsRedjptlZWE=", "dev": true }, - "lodash.uniq": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz", - "integrity": "sha1-0CJTc662Uq3BvILklFM5qEJ1R3M=", - "dev": true - }, "lodash.uniqby": { "version": "4.7.0", "resolved": "https://registry.npmjs.org/lodash.uniqby/-/lodash.uniqby-4.7.0.tgz", @@ -12466,12 +12461,6 @@ "isobject": "^3.0.1" } }, - "octokit-pagination-methods": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/octokit-pagination-methods/-/octokit-pagination-methods-1.1.0.tgz", - "integrity": "sha512-fZ4qZdQ2nxJvtcasX7Ghl+WlWS/d9IgnBIwFZXVNNZUmzpno91SX5bc5vuxiuKoCtK78XxGGNuSCrDC7xYB3OQ==", - "dev": true - }, "once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", @@ -13515,9 +13504,9 @@ } }, "semantic-release": { - "version": "17.0.2", - "resolved": "https://registry.npmjs.org/semantic-release/-/semantic-release-17.0.2.tgz", - "integrity": "sha512-f2466mNS/TpY32Jvoqgu3ricIDX/TRZXuthcyJo3ZIfdI14uMfiOu5R2dFKnPwgJh4wa9/2ckL44AFmIXAhiyg==", + "version": "17.0.4", + "resolved": "https://registry.npmjs.org/semantic-release/-/semantic-release-17.0.4.tgz", + "integrity": "sha512-5y9QRSrZtdvACmlpX5DvEVsvFuKRDUVn7JVJFxPVLGrGofDf1d0M/+hA1wFmCjiJZ+VCY8bYaSqVqF14KCF9rw==", "dev": true, "requires": { "@semantic-release/commit-analyzer": "^8.0.0", @@ -13601,9 +13590,9 @@ } }, "figures": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/figures/-/figures-3.1.0.tgz", - "integrity": "sha512-ravh8VRXqHuMvZt/d8GblBeqDMkdJMBdv/2KntFH+ra5MXkO7nxNKpzQ3n6QD/2da1kH0aWmNISdvhM7gl2gVg==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", + "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==", "dev": true, "requires": { "escape-string-regexp": "^1.0.5" @@ -13716,9 +13705,9 @@ "dev": true }, "semver": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.1.2.tgz", - "integrity": "sha512-BJs9T/H8sEVHbeigqzIEo57Iu/3DG6c4QoqTfbQB3BPA4zgzAomh/Fk9E7QtjWQ8mx2dgA9YCfSF4y9k9bHNpQ==", + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.1.3.tgz", + "integrity": "sha512-ekM0zfiA9SCBlsKa2X1hxyxiI4L3B6EbVJkkdgQXnSEEaHlGdvyodMruTiulSRWMMB4NeIuYNMC9rTKTz97GxA==", "dev": true }, "semver-diff": { @@ -14395,27 +14384,42 @@ } }, "temp-dir": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/temp-dir/-/temp-dir-1.0.0.tgz", - "integrity": "sha1-CnwOom06Oa+n4OvqnB/AvE2qAR0=", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/temp-dir/-/temp-dir-2.0.0.tgz", + "integrity": "sha512-aoBAniQmmwtcKp/7BzsH8Cxzv8OL736p7v1ihGb5e9DJ9kTwGWHrQrVB5+lfVDzfGrdRzXch+ig7LHaY1JTOrg==", "dev": true }, "tempy": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/tempy/-/tempy-0.3.0.tgz", - "integrity": "sha512-WrH/pui8YCwmeiAoxV+lpRH9HpRtgBhSR2ViBPgpGb/wnYDzp21R4MN45fsCGvLROvY67o3byhJRYRONJyImVQ==", + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/tempy/-/tempy-0.4.0.tgz", + "integrity": "sha512-mKnScm8aXv+cG6l1Nzp6mERGgC4UblbPnSDeQp83JgZ7xqDcnl+7u3+6zXnf1UE7YluDUTEIna1iKYwCSaOk9g==", "dev": true, "requires": { - "temp-dir": "^1.0.0", - "type-fest": "^0.3.1", - "unique-string": "^1.0.0" + "temp-dir": "^2.0.0", + "type-fest": "^0.10.0", + "unique-string": "^2.0.0" }, "dependencies": { + "crypto-random-string": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-2.0.0.tgz", + "integrity": "sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==", + "dev": true + }, "type-fest": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.3.1.tgz", - "integrity": "sha512-cUGJnCdr4STbePCgqNFbpVNCepa+kAVohJs1sLhxzdH+gnEoOd8VhbYa7pD3zZYGiURWM2xzEII3fQcRizDkYQ==", + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.10.0.tgz", + "integrity": "sha512-EUV9jo4sffrwlg8s0zDhP0T2WD3pru5Xi0+HTE3zTUmBaZNhfkite9PdSJwdXLwPVW0jnAHT56pZHIOYckPEiw==", "dev": true + }, + "unique-string": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-2.0.0.tgz", + "integrity": "sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg==", + "dev": true, + "requires": { + "crypto-random-string": "^2.0.0" + } } } }, @@ -14685,9 +14689,9 @@ } }, "uglify-js": { - "version": "3.7.7", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.7.7.tgz", - "integrity": "sha512-FeSU+hi7ULYy6mn8PKio/tXsdSXN35lm4KgV2asx00kzrLU9Pi3oAslcJT70Jdj7PHX29gGUPOT6+lXGBbemhA==", + "version": "3.8.0", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.8.0.tgz", + "integrity": "sha512-ugNSTT8ierCsDHso2jkBHXYrU8Y5/fY2ZUprfrJUiD7YpuFvV4jODLFmb3h4btQjqr5Nh4TX4XtgDfCU1WdioQ==", "dev": true, "optional": true, "requires": { @@ -14761,9 +14765,9 @@ } }, "universal-user-agent": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-4.0.0.tgz", - "integrity": "sha512-eM8knLpev67iBDizr/YtqkJsF3GK8gzDc6st/WKzrTuPtcsOKW/0IdL4cnMBsU69pOx0otavLWBDGTwg+dB0aA==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-5.0.0.tgz", + "integrity": "sha512-B5TPtzZleXyPrUMKCpEHFmVhMN6EhmJYjG5PQna9s7mXeSqGTLap4OpqLl5FCEFUI3UBmllkETwKf/db66Y54Q==", "dev": true, "requires": { "os-name": "^3.1.0" diff --git a/package.json b/package.json index bfee7ad..46cc5a4 100644 --- a/package.json +++ b/package.json @@ -38,6 +38,7 @@ "@babel/cli": "^7.2.3", "@babel/plugin-proposal-pipeline-operator": "^7.3.2", "@babel/preset-env": "^7.3.4", + "@fink/larix": "^1.1.0", "@nearmap/eslint-config-base": "^1.1.0", "babel-eslint": "^10.0.1", "commitizen": "^4.0.3", @@ -47,15 +48,11 @@ "eslint-plugin-babel": "^5.3.0", "jest-cli": "^25.1.0", "npx-run": "^2.1.2", - "semantic-release": "^17.0.0", - "@fink/larix": "^1.0.1" + "semantic-release": "^17.0.4" }, "dependencies": { "@babel/generator": "^7.8.4", "@babel/traverse": "^7.8.4", "@babel/types": "^7.8.3" - }, - "peerDependencies": { - "@fink/larix": "^1.0.1" } } diff --git a/src/index.js b/src/index.js index be1a425..5bde41c 100644 --- a/src/index.js +++ b/src/index.js @@ -1,10 +1,11 @@ import babel_gen from '@babel/generator'; import traverse from '@babel/traverse'; -import {identifier, numericLiteral} from '@babel/types'; + +import convert_source_map from 'convert-source-map'; import {other_token} from '@fink/prattler/symbols'; -import {ident, expr_block} from './types'; +import {ident, expr_block, wrap} from './types'; import {code_frame_err} from './errors'; import {transform_assign} from './transform/assign'; @@ -14,6 +15,8 @@ import {transform_attempt} from './transform/attempt'; import {transform_match} from './transform/match'; import {transform_map} from './transform/map'; import {transform_flat_map} from './transform/map'; +import {transform_filter} from './transform/filter'; +import {transform_while} from './transform/while'; import {transform_fold} from './transform/fold'; import {transform_unfold} from './transform/unfold'; import {transform_call} from './transform/call'; @@ -31,6 +34,9 @@ import {transform_group} from './transform/group'; import {transform_module} from './transform/module'; import {transform_unary} from './transform/unary'; import {transform_member} from './transform/member'; +import {transform_inifx} from './transform/infix'; +import {transform_other, escape_ident, var_prefix} from './transform/other'; + import { transform_jsx_elem, transform_jsx_attr, transform_jsx_str, transform_jsx_expr_container, transform_jsx_text @@ -40,14 +46,6 @@ import transform_do_expr from './transform/js/do-expression'; import {transform_async} from './transform/js/async'; -const transform_other = (node)=> { - if (node.value.match(/^[0-9].*/)) { - return numericLiteral(parseInt(node.value)); - } - return identifier(node.value); -}; - - const jsx = { 'jsx-elem': transform_jsx_elem, 'jsx-attr': transform_jsx_attr, @@ -73,7 +71,8 @@ const literals = { const unary_ops = { arithm_prefix: transform_unary, await: transform_await, - '...': transform_spread + '...': transform_spread, + '!': transform_unary }; const binary_ops = { @@ -89,27 +88,29 @@ const binary_ops = { '.': transform_member, - call: transform_call, - '|': transform_pipe + call: transform_call }; const block_like = { block: transform_block, - func: transform_func, + fn: transform_func, module: transform_module }; const control_flow = { if: transform_cond, match: transform_match, - attempt: transform_attempt + attempt: transform_attempt, + pipe: transform_pipe }; const iterables = { fold: transform_fold, unfold: transform_unfold, map: transform_map, - flat_map: transform_flat_map + flat_map: transform_flat_map, + filter: transform_filter, + while: transform_while }; @@ -120,7 +121,8 @@ const transformers = { ...block_like, ...control_flow, ...iterables, - ...jsx + ...jsx, + infix: transform_inifx }; @@ -134,17 +136,34 @@ const get_ctx = (transform, ctx)=> { }; +// eslint-disable-next-line prefer-reflect +const obj_has = (obj, key)=> Object.prototype.hasOwnProperty.call(obj, key); + + +const get_transformer = (op, type)=> { + if (obj_has(transformers, op)) { + return transformers[op]; + } + + if (obj_has(transformers, type)) { + return transformers[type]; + } +}; + + const transform_expr = (node, ctx)=> { - const transform = transformers[node.op] || transformers[node.type]; + const transform = get_transformer(node.op, node.type); if (transform === undefined) { throw code_frame_err(new Error('Unknown expression'), node, ctx.code); - } else { - try { - return transform(node, get_ctx(transform_expr, ctx)); - } catch (err) { - throw code_frame_err(err, node, ctx.code); - } + } + + try { + const foo = transform(node, get_ctx(transform_expr, ctx)); + // TODO: some nodes have location data + return wrap(node, foo); + } catch (err) { + throw code_frame_err(err, node, ctx.code); } }; @@ -155,7 +174,7 @@ const transform = (node, code)=> { code, unique_ident: (name)=> { id_ctr += 1; - return ident(`$${name}${id_ctr}`); + return ident(`${var_prefix}${name}_${id_ctr}`); } }); @@ -174,12 +193,21 @@ export const generate = (ast, filename, code)=> { const options = { // retainLines: true, filename, - sourceMaps: true, + sourceMaps: 'both', sourceFileName: filename // shouldPrintComment: ()=> true, }; - const output = babel_gen(new_ast, options, code); - return {...output, ast: new_ast}; + const generated = babel_gen(new_ast, options, code); + + const source_map = convert_source_map + .fromObject(generated.map) + .toComment(); + + // TODO: embedd source-map? + // const final_code = `${generated.code}\n\n${source_map}\n`; + const final_code = generated.code; + + return {...generated, code: final_code, ast: new_ast}; }; diff --git a/src/transform/__snapshots__/array.test.js.snap b/src/transform/__snapshots__/array.test.js.snap index 8c86af6..dc1f4d4 100644 --- a/src/transform/__snapshots__/array.test.js.snap +++ b/src/transform/__snapshots__/array.test.js.snap @@ -4,5 +4,11 @@ exports[`compiles array 1`] = ` "const array1 = []; const array2 = [1]; const array3 = [1, 2, 4, a(), ...b]; -const array4 = [a + 1 + 45 + b + c, [1, 2], (3 + 3) * 2];" +const array4 = [a + 1 + 45 + b + c, [1, 2], (3 + 3) * 2]; +Object.assign(module.exports, { + array1, + array2, + array3, + array4 +});" `; diff --git a/src/transform/__snapshots__/assign.test.js.snap b/src/transform/__snapshots__/assign.test.js.snap index 34d4a8c..c264063 100644 --- a/src/transform/__snapshots__/assign.test.js.snap +++ b/src/transform/__snapshots__/assign.test.js.snap @@ -6,5 +6,13 @@ const assign2 = assign; const no_clash_with_await = 13; const assign_lang_const1 = true; const assign_lang_const2 = false; -const multi_line_assign = 123 + 234 + (-567 - 1111);" +const multi_line_assign = 123 + 234 + (-567 - 1111); +Object.assign(module.exports, { + assign, + assign2, + no_clash_with_await, + assign_lang_const1, + assign_lang_const2, + multi_line_assign +});" `; diff --git a/src/transform/__snapshots__/attempt.test.js.snap b/src/transform/__snapshots__/attempt.test.js.snap index 46a07ce..9ed0acd 100644 --- a/src/transform/__snapshots__/attempt.test.js.snap +++ b/src/transform/__snapshots__/attempt.test.js.snap @@ -7,8 +7,8 @@ exports[`compiles attempt 1`] = ` try { const bar = shrub(); _do_result = [null, bar + ni()]; - } catch ($error1) { - _do_result = [$error1, null]; + } catch (ˆerror_1) { + _do_result = [ˆerror_1, null]; } const [item, err] = _do_result; @@ -18,7 +18,12 @@ exports[`compiles attempt 1`] = ` const foo2 = () => try { return [null, 1 / 0]; -} catch ($error2) { - return [$error2, null]; -};" +} catch (ˆerror_2) { + return [ˆerror_2, null]; +}; + +Object.assign(module.exports, { + foo1, + foo2 +});" `; diff --git a/src/transform/__snapshots__/await.test.js.snap b/src/transform/__snapshots__/await.test.js.snap index e761772..b577a47 100644 --- a/src/transform/__snapshots__/await.test.js.snap +++ b/src/transform/__snapshots__/await.test.js.snap @@ -20,12 +20,18 @@ const a_gen = async function* unfold(curr = 0) { _do_result = curr + 1; } - const $result1 = _do_result; + const ˆresult_1 = _do_result; _do_result = undefined; - yield $result1; - curr = $result1; + yield ˆresult_1; + curr = ˆresult_1; } -}(); +}; -await ni;" +await ni; +Object.assign(module.exports, { + task1, + task2, + task3, + a_gen +});" `; diff --git a/src/transform/__snapshots__/binary.test.js.snap b/src/transform/__snapshots__/binary.test.js.snap index bab2104..1fd0333 100644 --- a/src/transform/__snapshots__/binary.test.js.snap +++ b/src/transform/__snapshots__/binary.test.js.snap @@ -5,5 +5,12 @@ exports[`binary 1`] = ` const math_precedence2 = -1 + 0 + (1 + 2) * (3 / 2); const multi_line_assign = 123 + 234 + (-567 - 1111); const group1 = (1 + 2) * 3; -const group2 = 34234 ** -34234 + 1;" +const group2 = 34234 ** -34234 + 1; +Object.assign(module.exports, { + math_precedence1, + math_precedence2, + multi_line_assign, + group1, + group2 +});" `; diff --git a/src/transform/__snapshots__/call.test.js.snap b/src/transform/__snapshots__/call.test.js.snap index fbd5945..1c2ed0b 100644 --- a/src/transform/__snapshots__/call.test.js.snap +++ b/src/transform/__snapshots__/call.test.js.snap @@ -4,5 +4,11 @@ exports[`compiles call 1`] = ` "const call1 = a(ni, x = 123, ...x); const call2 = a(ni); const call3 = a(); -const call4 = a(x => x * 2);" +const call4 = a(x => x * 2); +Object.assign(module.exports, { + call1, + call2, + call3, + call4 +});" `; diff --git a/src/transform/__snapshots__/cond.test.js.snap b/src/transform/__snapshots__/cond.test.js.snap index bbc82c0..c12ead7 100644 --- a/src/transform/__snapshots__/cond.test.js.snap +++ b/src/transform/__snapshots__/cond.test.js.snap @@ -32,5 +32,9 @@ _do_result2 = undefined; } else { null; } -}" +} +Object.assign(module.exports, { + with_else, + no_else +});" `; diff --git a/src/transform/__snapshots__/filter.test.js.snap b/src/transform/__snapshots__/filter.test.js.snap new file mode 100644 index 0000000..cc6b545 --- /dev/null +++ b/src/transform/__snapshots__/filter.test.js.snap @@ -0,0 +1,13 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`filter 1`] = ` +"(function* filter(ˆitems_2) { + for (const ˆitem_1 of ˆitems_2) { + const item = ˆitem_1; + const ˆresult_3 = item % 2 === 0; + if (ˆresult_3) yield ˆitem_1; + } +}); + +Object.assign(module.exports, {});" +`; diff --git a/src/transform/__snapshots__/fold.test.js.snap b/src/transform/__snapshots__/fold.test.js.snap index b037412..c507a33 100644 --- a/src/transform/__snapshots__/fold.test.js.snap +++ b/src/transform/__snapshots__/fold.test.js.snap @@ -1,15 +1,17 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`compiles fold 1`] = ` -"$items1 => { - let $acc2 = 0; +"ˆitems_1 => { + let ˆacc_2 = 0; - for (const item of $items1) { - const acc = $acc2; + for (const item of ˆitems_1) { + const acc = ˆacc_2; const ni = item + acc; - $acc2 = item * acc; + ˆacc_2 = item * acc; } - return $acc2; -};" + return ˆacc_2; +}; + +Object.assign(module.exports, {});" `; diff --git a/src/transform/__snapshots__/func.test.js.snap b/src/transform/__snapshots__/func.test.js.snap index 15e7fd5..850e69c 100644 --- a/src/transform/__snapshots__/func.test.js.snap +++ b/src/transform/__snapshots__/func.test.js.snap @@ -9,11 +9,52 @@ const fun3 = () => \`shrub\`; const fun4 = () => \`shrub\`; -const fun5 = c => (d, e) => a + b + c; +const fun5 = c => (d, e) => { + const ˆvalue_1 = [d, e]; -const fun6 = (a, b = 12, c) => { + if (ˆvalue_1 !== undefined && ˆvalue_1 !== null && typeof ˆvalue_1[Symbol.iterator] === \\"function\\") { + const [ˆa_3, ˆa_4] = ˆvalue_1; + + if (ˆa_3 === 1 && ˆa_4 === 2) { + return c; + } + } + + if (ˆvalue_1 !== undefined && ˆvalue_1 !== null && typeof ˆvalue_1[Symbol.iterator] === \\"function\\") { + const [ˆa_5, ˆa_6] = ˆvalue_1; + + if (ˆa_5 === 2 && ˆa_6 === 1) { + return 1 / c; + } + } +}; + +const fun6 = (c, d) => { + const x = 123; + { + if (c + x) { + return d; + } else if (c + 1) { + return d + 1; + } else { + return null; + } + } +}; + +const fun7 = (a, b = 12, c) => { shrub(...a); foo(); return bar(); -};" +}; + +Object.assign(module.exports, { + fun1, + fun2, + fun3, + fun4, + fun5, + fun6, + fun7 +});" `; diff --git a/src/transform/__snapshots__/infix.test.js.snap b/src/transform/__snapshots__/infix.test.js.snap new file mode 100644 index 0000000..2466a55 --- /dev/null +++ b/src/transform/__snapshots__/infix.test.js.snap @@ -0,0 +1,11 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`identifiers as infix operators 1`] = ` +"const add = (a, b) => a + b; + +const foo = add(123, 456); +Object.assign(module.exports, { + add, + foo +});" +`; diff --git a/src/transform/__snapshots__/jsx.test.js.snap b/src/transform/__snapshots__/jsx.test.js.snap index 653e217..c42370e 100644 --- a/src/transform/__snapshots__/jsx.test.js.snap +++ b/src/transform/__snapshots__/jsx.test.js.snap @@ -12,5 +12,13 @@ const jsx6 = spam ni - ;" + ; +Object.assign(module.exports, { + jsx1, + jsx2, + jsx3, + jsx4, + jsx5, + jsx6 +});" `; diff --git a/src/transform/__snapshots__/left.test.js.snap b/src/transform/__snapshots__/left.test.js.snap index ac54246..7458020 100644 --- a/src/transform/__snapshots__/left.test.js.snap +++ b/src/transform/__snapshots__/left.test.js.snap @@ -5,9 +5,10 @@ exports[`compiles left hand sides 1`] = ` const [a2, b2, ...c3] = \`abcccl\`; const [a, ...b, c] = \`abbbc\`; const { - a3, - b: { - c: c4 + \\"a3\\": a3, + \\"b\\": { + \\"c\\": c4 } -} = {};" +} = {}; +Object.assign(module.exports, {});" `; diff --git a/src/transform/__snapshots__/logical.test.js.snap b/src/transform/__snapshots__/logical.test.js.snap index 07e45a0..44a410d 100644 --- a/src/transform/__snapshots__/logical.test.js.snap +++ b/src/transform/__snapshots__/logical.test.js.snap @@ -1,3 +1,8 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`compiles logical 1`] = `"const logical = a || b || c && d < 1 <= s;"`; +exports[`compiles logical 1`] = ` +"const logical = a || b || c && d < 1 <= s; +Object.assign(module.exports, { + logical +});" +`; diff --git a/src/transform/__snapshots__/map.test.js.snap b/src/transform/__snapshots__/map.test.js.snap index 0e9ee2d..94f1a0a 100644 --- a/src/transform/__snapshots__/map.test.js.snap +++ b/src/transform/__snapshots__/map.test.js.snap @@ -1,47 +1,49 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`compiles map 1`] = ` -"(function* map($items1) { - for (const item of $items1) { - const $result2 = item * 2; - yield $result2; +"(function* map(ˆitems_1) { + for (const item of ˆitems_1) { + const ˆresult_2 = item * 2; + yield ˆresult_2; } }); -(function* map($items3) { - for (const item = 123 of $items3) { - const $result4 = item * 2; - yield $result4; +(function* map(ˆitems_3) { + for (const item = 123 of ˆitems_3) { + const ˆresult_4 = item * 2; + yield ˆresult_4; } }); -(function* map($items5) { +(function* map(ˆitems_5) { for (const { - item - } of $items5) { - const $result6 = item * 2; - yield $result6; + \\"item\\": item + } of ˆitems_5) { + const ˆresult_6 = item * 2; + yield ˆresult_6; } }); -(function* map($items7) { - for (const [x, y] of $items7) { - const $result8 = x + y; - yield $result8; +(function* map(ˆitems_7) { + for (const [x, y] of ˆitems_7) { + const ˆresult_8 = x + y; + yield ˆresult_8; } }); -(function* map($items9) { - for (const item of $items9) { - const $result10 = [spam + item]; - yield* $result10; +(function* map(ˆitems_9) { + for (const item of ˆitems_9) { + const ˆresult_10 = [spam + item]; + yield* ˆresult_10; } }); -(function* map($items11) { - for (const item of $items11) { - const $result12 = [spam]; - yield* $result12; +(function* map(ˆitems_11) { + for (const item of ˆitems_11) { + const ˆresult_12 = [spam]; + yield* ˆresult_12; } -});" +}); + +Object.assign(module.exports, {});" `; diff --git a/src/transform/__snapshots__/match.test.js.snap b/src/transform/__snapshots__/match.test.js.snap index 08cd898..ab5e86a 100644 --- a/src/transform/__snapshots__/match.test.js.snap +++ b/src/transform/__snapshots__/match.test.js.snap @@ -1,119 +1,109 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`compiles logical 1`] = ` -"let _do_result; - -$match2: { - const $value1 = shrub; - - if ($value1 !== undefined && $value1 !== null) { - const { - foo: $p3, - ni: $p4 - } = $value1; - - if ($p3 === 4 && $p4 === ni) { - _do_result = spam + ni; - break $match2; +"{ + ˆmatch_2: { + const ˆvalue_1 = shrub; + + if (ˆvalue_1 !== undefined && ˆvalue_1 !== null) { + const { + \\"foo\\": ˆp_3, + \\"ni\\": ˆp_4 + } = ˆvalue_1; + + if (ˆp_3 === 4 && ˆp_4 === ni) { + spam + ni; + break ˆmatch_2; + } } - } - if ($value1 === 123) { - _do_result = spam; - break $match2; - } + if (ˆvalue_1 === 123) { + spam; + break ˆmatch_2; + } - if ($value1 !== undefined && $value1 !== null && typeof $value1[Symbol.iterator] === \\"function\\") { - const [$a5, $a6, $a7] = $value1; + if (ˆvalue_1 !== undefined && ˆvalue_1 !== null && typeof ˆvalue_1[Symbol.iterator] === \\"function\\") { + const [ˆa_5, ˆa_6, ˆa_7] = ˆvalue_1; - if ($a5 === 1 && $a6 === 2 && $a7 === ni) { - _do_result = ni; - break $match2; + if (ˆa_5 === 1 && ˆa_6 === 2 && ˆa_7 === ni) { + ni; + break ˆmatch_2; + } } - } - { - _do_result = shrub; - break $match2; + { + shrub; + break ˆmatch_2; + } } } - -const with_else = _do_result; -_do_result = undefined; - -let _do_result2; - -$match9: { - const $value8 = shrub; - - if ($value8 !== undefined && $value8 !== null) { - const { - foo: $p10, - ni: $p11 - } = $value8; - - if ($p10 === 4 && $p11 === ni) { - _do_result2 = spam + ni; - break $match9; +{ + ˆmatch_9: { + const ˆvalue_8 = shrub; + + if (ˆvalue_8 !== undefined && ˆvalue_8 !== null) { + const { + \\"foo\\": ˆp_10, + \\"ni\\": ˆp_11 + } = ˆvalue_8; + + if (ˆp_10 === 4 && ˆp_11 === ni) { + spam + ni; + break ˆmatch_9; + } } - } - if ($value8 === 123) { - _do_result2 = spam; - break $match9; + if (ˆvalue_8 === 123) { + spam; + break ˆmatch_9; + } } } - -const no_else = _do_result2; -_do_result2 = undefined; - -let _do_result3; - -$match13: { - const $value12 = shrub; - - if ($value12 !== undefined && $value12 !== null) { - const { - foo: $p14, - ni: $p15 - } = $value12; - - if ($p14 === 4) { - if ($p15 !== undefined && $p15 !== null) { - const { - na: $p16, - nu: $p17 - } = $p15; - - if ($p16 === na && $p17 === nu) { - _do_result3 = spam + ni; - break $match13; +{ + ˆmatch_13: { + const ˆvalue_12 = shrub; + + if (ˆvalue_12 !== undefined && ˆvalue_12 !== null) { + const { + \\"foo\\": ˆp_14, + \\"ni\\": ˆp_15 + } = ˆvalue_12; + + if (ˆp_14 === 4) { + if (ˆp_15 !== undefined && ˆp_15 !== null) { + const { + \\"na\\": ˆp_16, + \\"nu\\": ˆp_17 + } = ˆp_15; + + if (ˆp_16 === na && ˆp_17 === nu) { + spam + ni; + break ˆmatch_13; + } } } } - } - if ($value12 !== undefined && $value12 !== null && typeof $value12[Symbol.iterator] === \\"function\\") { - const [$a18, $a19, $a20] = $value12; + if (ˆvalue_12 !== undefined && ˆvalue_12 !== null && typeof ˆvalue_12[Symbol.iterator] === \\"function\\") { + const [ˆa_18, ˆa_19, ˆa_20] = ˆvalue_12; - if ($a18 === 1 && $a19 === 2) { - if ($a20 !== undefined && $a20 !== null && typeof $a20[Symbol.iterator] === \\"function\\") { - const [$a21] = $a20; + if (ˆa_18 === 1 && ˆa_19 === 2) { + if (ˆa_20 !== undefined && ˆa_20 !== null && typeof ˆa_20[Symbol.iterator] === \\"function\\") { + const [ˆa_21] = ˆa_20; - if ($a21 === ni) { - _do_result3 = ni; - break $match13; + if (ˆa_21 === ni) { + ni; + break ˆmatch_13; + } } } } - } - if ($value12 === 123) { - _do_result3 = spam; - break $match13; + if (ˆvalue_12 === 123) { + spam; + break ˆmatch_13; + } } } - -const nested = _do_result3; -_do_result3 = undefined;" +Object.assign(module.exports, {});" `; diff --git a/src/transform/__snapshots__/member.test.js.snap b/src/transform/__snapshots__/member.test.js.snap index d0c2844..b3c380c 100644 --- a/src/transform/__snapshots__/member.test.js.snap +++ b/src/transform/__snapshots__/member.test.js.snap @@ -2,5 +2,9 @@ exports[`compiles member 1`] = ` "const foo = spam.shrub; -const computed_member = item[bar + 123];" +const computed_member = item[\`bar spam\`]; +Object.assign(module.exports, { + foo, + computed_member +});" `; diff --git a/src/transform/__snapshots__/object.test.js.snap b/src/transform/__snapshots__/object.test.js.snap index ebc2551..366c079 100644 --- a/src/transform/__snapshots__/object.test.js.snap +++ b/src/transform/__snapshots__/object.test.js.snap @@ -3,29 +3,44 @@ exports[`compiles object 1`] = ` "const obj1 = {}; const obj2 = { - a + \\"a\\": a }; const obj3 = { - a, - b + \\"a\\": a, + \\"delete\\": ˆdelete, + \\"true\\": true, + \\"false\\": false }; const obj4 = { - a, - b, + \\"a\\": a, + \\"b\\": b, ...c }; const obj5 = { - a: 1, - b: 123 + \\"a\\": 1, + \\"b\\": 123 }; const obj6 = { - a: 123, - b: 123 && 123 && 1345, - c: (a, b) => 134 + \\"a\\": 123, + \\"b\\": 123 && 123 && 1345, + \\"c\\": (a, b) => 134 }; const obj7 = { - a: 123, - b: 123 && 123 && 1345, - c: (a, b) => 134 -};" + \\"a\\": 123, + \\"b\\": 123 && 123 && 1345, + \\"c\\": (a, b) => 134, + \\"d\\": (() => { + const n = a + 3; + return foo(n); + })() +}; +Object.assign(module.exports, { + obj1, + obj2, + obj3, + obj4, + obj5, + obj6, + obj7 +});" `; diff --git a/src/transform/__snapshots__/other.test.js.snap b/src/transform/__snapshots__/other.test.js.snap new file mode 100644 index 0000000..d387bf7 --- /dev/null +++ b/src/transform/__snapshots__/other.test.js.snap @@ -0,0 +1,80 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`identifiers does not escape true, false, null 1`] = ` +"const foo = [true, false, null]; +Object.assign(module.exports, { + foo +});" +`; + +exports[`identifiers escapes identifiers incompatible with JS 1`] = ` +"const ˆ1s = spam; +const ˆ6pu = shrub; +Object.assign(module.exports, { + ˆ1s, + ˆ6pu +});" +`; + +exports[`identifiers escapes reserved JS identifiers 1`] = ` +"const { + \\"do\\": ˆdo, + \\"if\\": ˆif, + \\"in\\": ˆin, + \\"for\\": ˆfor, + \\"let\\": ˆlet, + \\"new\\": ˆnew, + \\"try\\": ˆtry, + \\"var\\": ˆvar, + \\"case\\": ˆcase, + \\"enum\\": ˆenum, + \\"void\\": ˆvoid +} = foobar; +const { + \\"with\\": ˆwith, + \\"break\\": ˆbreak, + \\"catch\\": ˆcatch, + \\"class\\": ˆclass, + \\"const\\": ˆconst, + \\"super\\": ˆsuper, + \\"while\\": ˆwhile, + \\"yield\\": ˆyield, + \\"delete\\": ˆdelete +} = spam; +const { + \\"export\\": ˆexport, + \\"import\\": ˆimport, + \\"public\\": ˆpublic, + \\"return\\": ˆreturn, + \\"static\\": ˆstatic, + \\"switch\\": ˆswitch, + \\"typeof\\": ˆtypeof, + \\"default\\": ˆdefault +} = ham; +const { + \\"extends\\": ˆextends, + \\"finally\\": ˆfinally, + \\"package\\": ˆpackage, + \\"private\\": ˆprivate, + \\"continue\\": ˆcontinue, + \\"debugger\\": ˆdebugger, + \\"function\\": ˆfunction +} = ni; +const { + \\"arguments\\": ˆarguments, + \\"interface\\": ˆinterface, + \\"protected\\": ˆprotected, + \\"implements\\": ˆimplements, + \\"instanceof\\": ˆinstanceof +} = nu; +Object.assign(module.exports, {});" +`; + +exports[`numbers transforms integers 1`] = ` +"const x = 1234578; +const y = 123; +Object.assign(module.exports, { + x, + y +});" +`; diff --git a/src/transform/__snapshots__/pipe.test.js.snap b/src/transform/__snapshots__/pipe.test.js.snap index 45ad68e..2b4c332 100644 --- a/src/transform/__snapshots__/pipe.test.js.snap +++ b/src/transform/__snapshots__/pipe.test.js.snap @@ -1,3 +1,21 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`compiles pipe 1`] = `"ni(spam()(bar(foo)));"`; +exports[`compiles pipe 1`] = ` +"{ + let ˆpipe_result_1 = null; + ˆpipe_result_1 = foo(ˆpipe_result_1); + ˆpipe_result_1 = bar(ˆpipe_result_1); + ˆpipe_result_1 = spam(ˆpipe_result_1); +} +{ + let ˆpipe_result_2 = [1, 2, 3]; + + ˆpipe_result_2 = function* map(ˆitems_3) { + for (const item of ˆitems_3) { + const ˆresult_4 = item * 2; + yield ˆresult_4; + } + }(ˆpipe_result_2); +} +Object.assign(module.exports, {});" +`; diff --git a/src/transform/__snapshots__/regex.test.js.snap b/src/transform/__snapshots__/regex.test.js.snap index 4b8c488..565bba2 100644 --- a/src/transform/__snapshots__/regex.test.js.snap +++ b/src/transform/__snapshots__/regex.test.js.snap @@ -1,3 +1,8 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`compiles regex 1`] = `"const regex2 = /(?\\\\d{4})-(?\\\\d{2})-(?\\\\d{2})mgex3=rx/(?\\\\d{4})-(?\\\\d{2})-(?\\\\d{2})/;"`; +exports[`compiles regex 1`] = ` +"const regex2 = /(?\\\\d{4})-(?\\\\d{2})-(?\\\\d{2})mgex3=rx/(?\\\\d{4})-(?\\\\d{2})-(?\\\\d{2})/; +Object.assign(module.exports, { + regex2 +});" +`; diff --git a/src/transform/__snapshots__/string.test.js.snap b/src/transform/__snapshots__/string.test.js.snap index 826f7fa..0566309 100644 --- a/src/transform/__snapshots__/string.test.js.snap +++ b/src/transform/__snapshots__/string.test.js.snap @@ -4,5 +4,9 @@ exports[`compiles regex 1`] = ` "const str1 = \`line 1 line 2 with leading space line 3\`; -const str2 = \`ab\`;" +const str2 = \`ab\`; +Object.assign(module.exports, { + str1, + str2 +});" `; diff --git a/src/transform/__snapshots__/unfold.test.js.snap b/src/transform/__snapshots__/unfold.test.js.snap index 5bfb1ed..7780f49 100644 --- a/src/transform/__snapshots__/unfold.test.js.snap +++ b/src/transform/__snapshots__/unfold.test.js.snap @@ -3,17 +3,36 @@ exports[`compiles unfold 1`] = ` "(function* unfold(curr = start) { while (true) { - const $result1 = curr + inc; - yield $result1; + const ˆresult_1 = curr + inc; + yield ˆresult_1; curr = curr * 2; } -})(); +}); + +(function* unfold(curr) { + while (true) { + const ˆresult_2 = curr + inc; + yield ˆresult_2; + curr = curr * 2; + } +}); + +(function* unfold() { + while (true) { + const ˆresult_3 = 1234; + yield ˆresult_3; + } +}); const count = (start = 0, inc = 1) => function* unfold(curr = start) { while (true) { - const $result2 = curr + inc; - yield $result2; - curr = $result2; + const ˆresult_4 = curr + inc; + yield ˆresult_4; + curr = ˆresult_4; } -}();" +}; + +Object.assign(module.exports, { + count +});" `; diff --git a/src/transform/__snapshots__/while.test.js.snap b/src/transform/__snapshots__/while.test.js.snap new file mode 100644 index 0000000..c3fbe83 --- /dev/null +++ b/src/transform/__snapshots__/while.test.js.snap @@ -0,0 +1,14 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`while 1`] = ` +"(function* filter_while(ˆitems_2) { + for (const ˆitem_1 of ˆitems_2) { + const item = ˆitem_1; + const ˆresult_3 = item < 10; + if (ˆresult_3 !== true) return; + yield ˆitem_1; + } +}); + +Object.assign(module.exports, {});" +`; diff --git a/src/transform/assign.js b/src/transform/assign.js index 60682b2..19695bb 100644 --- a/src/transform/assign.js +++ b/src/transform/assign.js @@ -7,4 +7,5 @@ export const transform_assign = (node, ctx)=> { const right = ctx.transform(node.right); return assignmentExpression('=', left, right); + // return wrap(node, assignmentExpression('=', left, right)); }; diff --git a/src/transform/assign.test.js b/src/transform/assign.test.js index f78fc0f..cdc94fc 100644 --- a/src/transform/assign.test.js +++ b/src/transform/assign.test.js @@ -6,9 +6,12 @@ test('compiles assignment', ()=> { fink2js(` assign = 1 assign2 = assign + no_clash_with_await = 13 + assign_lang_const1 = true assign_lang_const2 = false + multi_line_assign = 123 + 234 + -567 diff --git a/src/transform/attempt.test.js b/src/transform/attempt.test.js index 0320899..154b0e8 100644 --- a/src/transform/attempt.test.js +++ b/src/transform/attempt.test.js @@ -4,13 +4,13 @@ import {fink2js} from '../testing'; test('compiles attempt', ()=> { expect( fink2js(` - foo1 = (): + foo1 = fn: [item, err] = attempt: bar = shrub() bar + ni() [item, err] - foo2 = (): attempt: 1/0 + foo2 = fn: attempt: 1/0 `) ).toMatchSnapshot(); }); diff --git a/src/transform/await.test.js b/src/transform/await.test.js index 9f2b204..da346e3 100644 --- a/src/transform/await.test.js +++ b/src/transform/await.test.js @@ -4,11 +4,11 @@ import {fink2js} from '../testing'; test('compiles await', ()=> { expect( fink2js(` - task1 = (foo): - await foo + task1 = fn foo: - await foo - task2 = (foo): await (foo + 4) + task2 = fn foo: await (foo + 4) - task3 = (foo): + task3 = fn foo: bar = await foo() bar + 123 diff --git a/src/transform/call.test.js b/src/transform/call.test.js index 2bd3225..9f70bd1 100644 --- a/src/transform/call.test.js +++ b/src/transform/call.test.js @@ -7,7 +7,7 @@ test('compiles call', ()=> { call1 = a(ni, x=123, ...x) call2 = a(ni) call3 = a () - call4 = a((x): x*2) + call4 = a(fn x: x*2) `) ).toMatchSnapshot(); }); diff --git a/src/transform/filter.js b/src/transform/filter.js new file mode 100644 index 0000000..596b1eb --- /dev/null +++ b/src/transform/filter.js @@ -0,0 +1,27 @@ +import { + params, generator, for_of, yield_or_stop, split_last, iff, yields, consts +} from '../types'; +import {is_call, is_calling} from './call'; +import {block_statement} from './block'; + + +export const transform_filter = (node, {transform, unique_ident})=> { + const [item_param] = params(node.args.map(transform)); + + const [expressions, last_expr] = split_last(node.exprs); + + const item = unique_ident('item'); + const items = unique_ident('items'); + const result = unique_ident('result'); + + return generator('filter')(items)( + for_of(item, items)( + consts(item_param, item), + ...expressions.map(block_statement({transform})), + consts(result, transform(last_expr)), + iff(result)( + yields(item) + ) + ) + ); +}; diff --git a/src/transform/filter.test.js b/src/transform/filter.test.js new file mode 100644 index 0000000..e50b0e1 --- /dev/null +++ b/src/transform/filter.test.js @@ -0,0 +1,11 @@ +import {fink2js} from '../testing'; + + +test('filter', ()=> { + expect( + fink2js(` + filter item: + item % 2 == 0 + `) + ).toMatchSnapshot(); +}); diff --git a/src/transform/func.test.js b/src/transform/func.test.js index ba90356..e0451d5 100644 --- a/src/transform/func.test.js +++ b/src/transform/func.test.js @@ -4,19 +4,27 @@ import {fink2js} from '../testing'; test('compiles func', ()=> { expect( fink2js(` - fun1 = (a, b=12, ...d): a + b + c + fun1 = fn a, b=12, ...d: a + b + c - fun2 = (b): + fun2 = fn b: b * 2 - fun3 = (): \`shrub\` - fun4 = (): + fun3 = fn: \`shrub\` + fun4 = fn: \`shrub\` - fun5 = (c): (d, e): - a + b + c + fun5 = fn c: fn d, e: + match [d, e]: + [1, 2]: c + [2, 1]: 1/c - fun6 = (a, b=12, c): + fun6 = fn c, d: + x = 123 + if: + c + x: d + c + 1: d + 1 + + fun7 = fn a, b=12, c: shrub(...a) foo() bar() diff --git a/src/transform/infix.js b/src/transform/infix.js new file mode 100644 index 0000000..9da7d9d --- /dev/null +++ b/src/transform/infix.js @@ -0,0 +1,8 @@ +import {call, ident} from '../types'; + + +export const transform_inifx = (node, ctx)=> { + const left = ctx.transform(node.left); + const right = ctx.transform(node.right); + return call(ident(node.op))(left, right); +}; diff --git a/src/transform/infix.test.js b/src/transform/infix.test.js new file mode 100644 index 0000000..a46bb0a --- /dev/null +++ b/src/transform/infix.test.js @@ -0,0 +1,11 @@ +import {fink2js} from '../testing'; + + +test('identifiers as infix operators', ()=> { + expect( + fink2js(` + add = fn a, b: a + b + foo = 123 add 456 + `) + ).toMatchSnapshot(); +}); diff --git a/src/transform/js/do-expression.js b/src/transform/js/do-expression.js index f9edee0..ba06fb4 100644 --- a/src/transform/js/do-expression.js +++ b/src/transform/js/do-expression.js @@ -1,4 +1,7 @@ -import {assignmentExpression, returnStatement} from '@babel/types'; +import { + assignmentExpression, returnStatement, callExpression, + arrowFunctionExpression +} from '@babel/types'; import {lets, assign, undef} from '../../types'; @@ -45,27 +48,28 @@ const replace_with_return = (path)=> { returnStatement(expr.node.expression) ); - // TODO: no need for anything after return - // const sibl = expr.getSibling(expr.key+1); - // if (sibl) { - // sibl.remove(); - // } + // TODO: no need for e.g. breaks after a return + const sibl = expr.getSibling(expr.key+1); + /* istanbul ignore else */ + if (sibl) { + sibl.remove(); + } } }; -const simple = (body /* , sl=false */)=> { +const simple = (body, sl=false)=> { if (body.isBlockStatement()) { const [stmnt, ...rest] = body.get('body'); if (rest.length === 0) { - // TODO: these were here in early prototypes, check what they did - // if (sl && stmnt.isLabeledStatement()) { - // return stmnt.node.body; - // } - // // TODO: last if statement or single in arrow - // if (sl && stmnt.isIfStatement()) { - // return body.node; - // } + // e.g. fn arg: match ...: ... + if (sl && stmnt.isLabeledStatement()) { + return stmnt.node.body; + } + + if (sl && stmnt.isIfStatement()) { + return body.node; + } return simple(stmnt); } @@ -96,7 +100,7 @@ const transform_do_expr = (path)=> { if (parent.isVariableDeclarator()) { replace_with_assign(parent, path); - } else /* istanbul ignore else */ if (parent.isArrowFunctionExpression()) { + } else if (parent.isArrowFunctionExpression()) { // console.log(dbg(parent.node)); parent.node.body = simple(path.get('body'), true); replace_with_return(path); @@ -105,24 +109,26 @@ const transform_do_expr = (path)=> { // this is used e.g. for conditional at the module level parent.replaceWith(path.get('body').node); + } else if (parent.isReturnStatement()) { + parent.replaceWith(simple(path.get('body'), true)); + replace_with_return(path); + + // eslint-disable-next-line no-negated-condition + } else /* istanbul ignore else */ if (!parent.isProgram()) { + // e.g. + // { + // foo: + // x = spam + // x + 3 + // } + path.replaceWith( + callExpression(arrowFunctionExpression([], path.node), []) + ); + // parent.insertBefore(expressionStatement(identifier('ret_st'))); + // throw parent.buildCodeFrameError(`Can't convert do-expression`); } else { throw parent.buildCodeFrameError(`Can't convert do-expression`); } - - // else if (parent.isReturnStatement()) { - // parent.replaceWith(simple(path.get('body'), true)); - // replace_with_return(path); - - // } else if (parent.type === null) { - // // console.log('=============================='); - - // } else if (!parent.isProgram()) { - // path.replaceWith( - // callExpression(arrowFunctionExpression([], path.node), []) - // ); - // // parent.insertBefore(expressionStatement(identifier('ret_st'))); - // // throw parent.buildCodeFrameError(`Can't convert do-expression`); - // } }; export default transform_do_expr; diff --git a/src/transform/match.js b/src/transform/match.js index 3e5c8f0..5eae1b7 100644 --- a/src/transform/match.js +++ b/src/transform/match.js @@ -1,18 +1,19 @@ import { arrayPattern, blockStatement, breakStatement, labeledStatement, objectPattern, - objectProperty, isObjectExpression, isArrayExpression, expressionStatement + objectProperty, isObjectExpression, isArrayExpression, expressionStatement, + identifier } from '@babel/types'; import { member, str, for_of, split_last, and, eq, not_nullish, typof, - ident, expr_block, consts, iff + expr_block, consts, iff } from '../types'; import {is_call, is_calling} from './call'; import {is_array} from './array'; const iter = (value)=> ( - member(value)(member(ident('Symbol'))(ident('iterator')), true) + member(value)(member(identifier('Symbol'))(identifier('iterator')), true) ); diff --git a/src/transform/match.test.js b/src/transform/match.test.js index e3bfe5d..63b0526 100644 --- a/src/transform/match.test.js +++ b/src/transform/match.test.js @@ -3,19 +3,21 @@ import {fink2js} from '../testing'; test('compiles logical', ()=> { expect( - // TODO: remove foo = fink2js(` - with_else = match shrub: + # with else + match shrub: {foo: 4, ni}: spam + ni 123: spam [1, 2, ni]: ni else: shrub - no_else = match shrub: + # no else + match shrub: {foo: 4, ni}: spam + ni 123: spam - nested = match shrub: + # nesting + match shrub: {foo: 4, ni: {na, nu}}: spam + ni [1, 2, [ni]]: ni 123: spam diff --git a/src/transform/member.js b/src/transform/member.js index c241929..8f6f2f3 100644 --- a/src/transform/member.js +++ b/src/transform/member.js @@ -5,5 +5,5 @@ export const transform_member = (node, ctx)=> { const left = ctx.transform(node.left); const right = ctx.transform(node.right); - return memberExpression(left, right, node.right.type === 'group'); + return memberExpression(left, right, node.right.type === 'string'); }; diff --git a/src/transform/member.test.js b/src/transform/member.test.js index c15dafd..044359f 100644 --- a/src/transform/member.test.js +++ b/src/transform/member.test.js @@ -5,7 +5,7 @@ test('compiles member', ()=> { expect( fink2js(` foo = spam.shrub - computed_member = item.(bar + 123) + computed_member = item.\`bar spam\` `) ).toMatchSnapshot(); }); diff --git a/src/transform/module.js b/src/transform/module.js index 18d726d..2a3f503 100644 --- a/src/transform/module.js +++ b/src/transform/module.js @@ -1,14 +1,38 @@ -import {file, program} from '@babel/types'; +import { + file, program, objectExpression, objectProperty, identifier, + expressionStatement +} from '@babel/types'; +import {other_token} from '@fink/prattler/symbols'; + import {block_statement} from './block'; +import {call, member, ident} from '../types'; + + +export const transform_module = (node, ctx)=> { + const exported = []; + + const body = node.exprs + .filter((expr)=> expr.type !== 'comment') + .map((expr)=> { + const result = block_statement(ctx)(expr); + + if (expr?.left?.type === other_token) { + // TODO: wrap with loc? + const id = ident(expr.left.value); + exported.push(objectProperty( + id, id, false, true + )); + } + return result; + }); -export const transform_module = (node, ctx)=> ( - file( - program( - node.exprs - .filter((expr)=> expr.type !== 'comment') - .map(block_statement(ctx)), - [], 'module' + // TODO: auto export? + const exports = expressionStatement( + call(member(identifier('Object'))(identifier('assign')))( + member(identifier('module'))(identifier('exports')), + objectExpression(exported) ) - ) -); + ); + return file(program([...body, exports], [], 'module')); +}; diff --git a/src/transform/object.js b/src/transform/object.js index 5411791..be82339 100644 --- a/src/transform/object.js +++ b/src/transform/object.js @@ -1,4 +1,6 @@ -import {isSpreadElement, objectExpression, objectProperty} from '@babel/types'; +import { + isSpreadElement, objectExpression, objectProperty, stringLiteral +} from '@babel/types'; export const transform_object = (node, ctx)=> { @@ -8,10 +10,15 @@ export const transform_object = (node, ctx)=> { export const transform_prop = (node, ctx)=> { - const computed = false; + const is_str_key = node.key.type === 'string'; + const computed = is_str_key; const shorthand = node.key === node.value; - const key = ctx.transform(node.key); + + const key = (is_str_key || node.key.type === 'spread') + ? ctx.transform(node.key) + : {...stringLiteral(node.key.value), loc: node.key.loc}; + if (isSpreadElement(key)) { return key; } diff --git a/src/transform/object.test.js b/src/transform/object.test.js index bbe5ac7..35919de 100644 --- a/src/transform/object.test.js +++ b/src/transform/object.test.js @@ -6,16 +6,19 @@ test('compiles object', ()=> { fink2js(` obj1 = {} obj2 = {a} - obj3 = {a, b} + obj3 = {a, delete, true, false} obj4 = {a, b, ...c} obj5 = {a: 1, b: 123} - obj6 = {a: 123, b: 123 && 123 && 1345, c: (a, b): 134} + obj6 = {a: 123, b: 123 && 123 && 1345, c: fn a, b: 134} obj7 = { a: 123, b: 123 && 123 && 1345, - c: (a, b): 134 + c: fn a, b: 134, + d: + n = a+3 + foo(n) } `) ).toMatchSnapshot(); diff --git a/src/transform/other.js b/src/transform/other.js new file mode 100644 index 0000000..317f72b --- /dev/null +++ b/src/transform/other.js @@ -0,0 +1,35 @@ +import {numericLiteral, identifier} from '@babel/types'; + +// eslint-disable-next-line +const check_ident = /^(?!(?:do|if|in|for|let|new|try|var|case|enum|void|with|break|catch|class|const|super|while|yield|delete|export|import|public|return|static|switch|typeof|default|extends|finally|package|private|continue|debugger|function|arguments|interface|protected|implements|instanceof)$)[$A-Z\_a-z\xaa\xb5\xba\xc0-\xd6\xd8-\xf6\xf8-\u02c1\u02c6-\u02d1\u02e0-\u02e4\u02ec\u02ee\u0370-\u0374\u0376\u0377\u037a-\u037d\u0386\u0388-\u038a\u038c\u038e-\u03a1\u03a3-\u03f5\u03f7-\u0481\u048a-\u0527\u0531-\u0556\u0559\u0561-\u0587\u05d0-\u05ea\u05f0-\u05f2\u0620-\u064a\u066e\u066f\u0671-\u06d3\u06d5\u06e5\u06e6\u06ee\u06ef\u06fa-\u06fc\u06ff\u0710\u0712-\u072f\u074d-\u07a5\u07b1\u07ca-\u07ea\u07f4\u07f5\u07fa\u0800-\u0815\u081a\u0824\u0828\u0840-\u0858\u08a0\u08a2-\u08ac\u0904-\u0939\u093d\u0950\u0958-\u0961\u0971-\u0977\u0979-\u097f\u0985-\u098c\u098f\u0990\u0993-\u09a8\u09aa-\u09b0\u09b2\u09b6-\u09b9\u09bd\u09ce\u09dc\u09dd\u09df-\u09e1\u09f0\u09f1\u0a05-\u0a0a\u0a0f\u0a10\u0a13-\u0a28\u0a2a-\u0a30\u0a32\u0a33\u0a35\u0a36\u0a38\u0a39\u0a59-\u0a5c\u0a5e\u0a72-\u0a74\u0a85-\u0a8d\u0a8f-\u0a91\u0a93-\u0aa8\u0aaa-\u0ab0\u0ab2\u0ab3\u0ab5-\u0ab9\u0abd\u0ad0\u0ae0\u0ae1\u0b05-\u0b0c\u0b0f\u0b10\u0b13-\u0b28\u0b2a-\u0b30\u0b32\u0b33\u0b35-\u0b39\u0b3d\u0b5c\u0b5d\u0b5f-\u0b61\u0b71\u0b83\u0b85-\u0b8a\u0b8e-\u0b90\u0b92-\u0b95\u0b99\u0b9a\u0b9c\u0b9e\u0b9f\u0ba3\u0ba4\u0ba8-\u0baa\u0bae-\u0bb9\u0bd0\u0c05-\u0c0c\u0c0e-\u0c10\u0c12-\u0c28\u0c2a-\u0c33\u0c35-\u0c39\u0c3d\u0c58\u0c59\u0c60\u0c61\u0c85-\u0c8c\u0c8e-\u0c90\u0c92-\u0ca8\u0caa-\u0cb3\u0cb5-\u0cb9\u0cbd\u0cde\u0ce0\u0ce1\u0cf1\u0cf2\u0d05-\u0d0c\u0d0e-\u0d10\u0d12-\u0d3a\u0d3d\u0d4e\u0d60\u0d61\u0d7a-\u0d7f\u0d85-\u0d96\u0d9a-\u0db1\u0db3-\u0dbb\u0dbd\u0dc0-\u0dc6\u0e01-\u0e30\u0e32\u0e33\u0e40-\u0e46\u0e81\u0e82\u0e84\u0e87\u0e88\u0e8a\u0e8d\u0e94-\u0e97\u0e99-\u0e9f\u0ea1-\u0ea3\u0ea5\u0ea7\u0eaa\u0eab\u0ead-\u0eb0\u0eb2\u0eb3\u0ebd\u0ec0-\u0ec4\u0ec6\u0edc-\u0edf\u0f00\u0f40-\u0f47\u0f49-\u0f6c\u0f88-\u0f8c\u1000-\u102a\u103f\u1050-\u1055\u105a-\u105d\u1061\u1065\u1066\u106e-\u1070\u1075-\u1081\u108e\u10a0-\u10c5\u10c7\u10cd\u10d0-\u10fa\u10fc-\u1248\u124a-\u124d\u1250-\u1256\u1258\u125a-\u125d\u1260-\u1288\u128a-\u128d\u1290-\u12b0\u12b2-\u12b5\u12b8-\u12be\u12c0\u12c2-\u12c5\u12c8-\u12d6\u12d8-\u1310\u1312-\u1315\u1318-\u135a\u1380-\u138f\u13a0-\u13f4\u1401-\u166c\u166f-\u167f\u1681-\u169a\u16a0-\u16ea\u16ee-\u16f0\u1700-\u170c\u170e-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176c\u176e-\u1770\u1780-\u17b3\u17d7\u17dc\u1820-\u1877\u1880-\u18a8\u18aa\u18b0-\u18f5\u1900-\u191c\u1950-\u196d\u1970-\u1974\u1980-\u19ab\u19c1-\u19c7\u1a00-\u1a16\u1a20-\u1a54\u1aa7\u1b05-\u1b33\u1b45-\u1b4b\u1b83-\u1ba0\u1bae\u1baf\u1bba-\u1be5\u1c00-\u1c23\u1c4d-\u1c4f\u1c5a-\u1c7d\u1ce9-\u1cec\u1cee-\u1cf1\u1cf5\u1cf6\u1d00-\u1dbf\u1e00-\u1f15\u1f18-\u1f1d\u1f20-\u1f45\u1f48-\u1f4d\u1f50-\u1f57\u1f59\u1f5b\u1f5d\u1f5f-\u1f7d\u1f80-\u1fb4\u1fb6-\u1fbc\u1fbe\u1fc2-\u1fc4\u1fc6-\u1fcc\u1fd0-\u1fd3\u1fd6-\u1fdb\u1fe0-\u1fec\u1ff2-\u1ff4\u1ff6-\u1ffc\u2071\u207f\u2090-\u209c\u2102\u2107\u210a-\u2113\u2115\u2119-\u211d\u2124\u2126\u2128\u212a-\u212d\u212f-\u2139\u213c-\u213f\u2145-\u2149\u214e\u2160-\u2188\u2c00-\u2c2e\u2c30-\u2c5e\u2c60-\u2ce4\u2ceb-\u2cee\u2cf2\u2cf3\u2d00-\u2d25\u2d27\u2d2d\u2d30-\u2d67\u2d6f\u2d80-\u2d96\u2da0-\u2da6\u2da8-\u2dae\u2db0-\u2db6\u2db8-\u2dbe\u2dc0-\u2dc6\u2dc8-\u2dce\u2dd0-\u2dd6\u2dd8-\u2dde\u2e2f\u3005-\u3007\u3021-\u3029\u3031-\u3035\u3038-\u303c\u3041-\u3096\u309d-\u309f\u30a1-\u30fa\u30fc-\u30ff\u3105-\u312d\u3131-\u318e\u31a0-\u31ba\u31f0-\u31ff\u3400-\u4db5\u4e00-\u9fcc\ua000-\ua48c\ua4d0-\ua4fd\ua500-\ua60c\ua610-\ua61f\ua62a\ua62b\ua640-\ua66e\ua67f-\ua697\ua6a0-\ua6ef\ua717-\ua71f\ua722-\ua788\ua78b-\ua78e\ua790-\ua793\ua7a0-\ua7aa\ua7f8-\ua801\ua803-\ua805\ua807-\ua80a\ua80c-\ua822\ua840-\ua873\ua882-\ua8b3\ua8f2-\ua8f7\ua8fb\ua90a-\ua925\ua930-\ua946\ua960-\ua97c\ua984-\ua9b2\ua9cf\uaa00-\uaa28\uaa40-\uaa42\uaa44-\uaa4b\uaa60-\uaa76\uaa7a\uaa80-\uaaaf\uaab1\uaab5\uaab6\uaab9-\uaabd\uaac0\uaac2\uaadb-\uaadd\uaae0-\uaaea\uaaf2-\uaaf4\uab01-\uab06\uab09-\uab0e\uab11-\uab16\uab20-\uab26\uab28-\uab2e\uabc0-\uabe2\uac00-\ud7a3\ud7b0-\ud7c6\ud7cb-\ud7fb\uf900-\ufa6d\ufa70-\ufad9\ufb00-\ufb06\ufb13-\ufb17\ufb1d\ufb1f-\ufb28\ufb2a-\ufb36\ufb38-\ufb3c\ufb3e\ufb40\ufb41\ufb43\ufb44\ufb46-\ufbb1\ufbd3-\ufd3d\ufd50-\ufd8f\ufd92-\ufdc7\ufdf0-\ufdfb\ufe70-\ufe74\ufe76-\ufefc\uff21-\uff3a\uff41-\uff5a\uff66-\uffbe\uffc2-\uffc7\uffca-\uffcf\uffd2-\uffd7\uffda-\uffdc][$A-Z\_a-z\xaa\xb5\xba\xc0-\xd6\xd8-\xf6\xf8-\u02c1\u02c6-\u02d1\u02e0-\u02e4\u02ec\u02ee\u0370-\u0374\u0376\u0377\u037a-\u037d\u0386\u0388-\u038a\u038c\u038e-\u03a1\u03a3-\u03f5\u03f7-\u0481\u048a-\u0527\u0531-\u0556\u0559\u0561-\u0587\u05d0-\u05ea\u05f0-\u05f2\u0620-\u064a\u066e\u066f\u0671-\u06d3\u06d5\u06e5\u06e6\u06ee\u06ef\u06fa-\u06fc\u06ff\u0710\u0712-\u072f\u074d-\u07a5\u07b1\u07ca-\u07ea\u07f4\u07f5\u07fa\u0800-\u0815\u081a\u0824\u0828\u0840-\u0858\u08a0\u08a2-\u08ac\u0904-\u0939\u093d\u0950\u0958-\u0961\u0971-\u0977\u0979-\u097f\u0985-\u098c\u098f\u0990\u0993-\u09a8\u09aa-\u09b0\u09b2\u09b6-\u09b9\u09bd\u09ce\u09dc\u09dd\u09df-\u09e1\u09f0\u09f1\u0a05-\u0a0a\u0a0f\u0a10\u0a13-\u0a28\u0a2a-\u0a30\u0a32\u0a33\u0a35\u0a36\u0a38\u0a39\u0a59-\u0a5c\u0a5e\u0a72-\u0a74\u0a85-\u0a8d\u0a8f-\u0a91\u0a93-\u0aa8\u0aaa-\u0ab0\u0ab2\u0ab3\u0ab5-\u0ab9\u0abd\u0ad0\u0ae0\u0ae1\u0b05-\u0b0c\u0b0f\u0b10\u0b13-\u0b28\u0b2a-\u0b30\u0b32\u0b33\u0b35-\u0b39\u0b3d\u0b5c\u0b5d\u0b5f-\u0b61\u0b71\u0b83\u0b85-\u0b8a\u0b8e-\u0b90\u0b92-\u0b95\u0b99\u0b9a\u0b9c\u0b9e\u0b9f\u0ba3\u0ba4\u0ba8-\u0baa\u0bae-\u0bb9\u0bd0\u0c05-\u0c0c\u0c0e-\u0c10\u0c12-\u0c28\u0c2a-\u0c33\u0c35-\u0c39\u0c3d\u0c58\u0c59\u0c60\u0c61\u0c85-\u0c8c\u0c8e-\u0c90\u0c92-\u0ca8\u0caa-\u0cb3\u0cb5-\u0cb9\u0cbd\u0cde\u0ce0\u0ce1\u0cf1\u0cf2\u0d05-\u0d0c\u0d0e-\u0d10\u0d12-\u0d3a\u0d3d\u0d4e\u0d60\u0d61\u0d7a-\u0d7f\u0d85-\u0d96\u0d9a-\u0db1\u0db3-\u0dbb\u0dbd\u0dc0-\u0dc6\u0e01-\u0e30\u0e32\u0e33\u0e40-\u0e46\u0e81\u0e82\u0e84\u0e87\u0e88\u0e8a\u0e8d\u0e94-\u0e97\u0e99-\u0e9f\u0ea1-\u0ea3\u0ea5\u0ea7\u0eaa\u0eab\u0ead-\u0eb0\u0eb2\u0eb3\u0ebd\u0ec0-\u0ec4\u0ec6\u0edc-\u0edf\u0f00\u0f40-\u0f47\u0f49-\u0f6c\u0f88-\u0f8c\u1000-\u102a\u103f\u1050-\u1055\u105a-\u105d\u1061\u1065\u1066\u106e-\u1070\u1075-\u1081\u108e\u10a0-\u10c5\u10c7\u10cd\u10d0-\u10fa\u10fc-\u1248\u124a-\u124d\u1250-\u1256\u1258\u125a-\u125d\u1260-\u1288\u128a-\u128d\u1290-\u12b0\u12b2-\u12b5\u12b8-\u12be\u12c0\u12c2-\u12c5\u12c8-\u12d6\u12d8-\u1310\u1312-\u1315\u1318-\u135a\u1380-\u138f\u13a0-\u13f4\u1401-\u166c\u166f-\u167f\u1681-\u169a\u16a0-\u16ea\u16ee-\u16f0\u1700-\u170c\u170e-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176c\u176e-\u1770\u1780-\u17b3\u17d7\u17dc\u1820-\u1877\u1880-\u18a8\u18aa\u18b0-\u18f5\u1900-\u191c\u1950-\u196d\u1970-\u1974\u1980-\u19ab\u19c1-\u19c7\u1a00-\u1a16\u1a20-\u1a54\u1aa7\u1b05-\u1b33\u1b45-\u1b4b\u1b83-\u1ba0\u1bae\u1baf\u1bba-\u1be5\u1c00-\u1c23\u1c4d-\u1c4f\u1c5a-\u1c7d\u1ce9-\u1cec\u1cee-\u1cf1\u1cf5\u1cf6\u1d00-\u1dbf\u1e00-\u1f15\u1f18-\u1f1d\u1f20-\u1f45\u1f48-\u1f4d\u1f50-\u1f57\u1f59\u1f5b\u1f5d\u1f5f-\u1f7d\u1f80-\u1fb4\u1fb6-\u1fbc\u1fbe\u1fc2-\u1fc4\u1fc6-\u1fcc\u1fd0-\u1fd3\u1fd6-\u1fdb\u1fe0-\u1fec\u1ff2-\u1ff4\u1ff6-\u1ffc\u2071\u207f\u2090-\u209c\u2102\u2107\u210a-\u2113\u2115\u2119-\u211d\u2124\u2126\u2128\u212a-\u212d\u212f-\u2139\u213c-\u213f\u2145-\u2149\u214e\u2160-\u2188\u2c00-\u2c2e\u2c30-\u2c5e\u2c60-\u2ce4\u2ceb-\u2cee\u2cf2\u2cf3\u2d00-\u2d25\u2d27\u2d2d\u2d30-\u2d67\u2d6f\u2d80-\u2d96\u2da0-\u2da6\u2da8-\u2dae\u2db0-\u2db6\u2db8-\u2dbe\u2dc0-\u2dc6\u2dc8-\u2dce\u2dd0-\u2dd6\u2dd8-\u2dde\u2e2f\u3005-\u3007\u3021-\u3029\u3031-\u3035\u3038-\u303c\u3041-\u3096\u309d-\u309f\u30a1-\u30fa\u30fc-\u30ff\u3105-\u312d\u3131-\u318e\u31a0-\u31ba\u31f0-\u31ff\u3400-\u4db5\u4e00-\u9fcc\ua000-\ua48c\ua4d0-\ua4fd\ua500-\ua60c\ua610-\ua61f\ua62a\ua62b\ua640-\ua66e\ua67f-\ua697\ua6a0-\ua6ef\ua717-\ua71f\ua722-\ua788\ua78b-\ua78e\ua790-\ua793\ua7a0-\ua7aa\ua7f8-\ua801\ua803-\ua805\ua807-\ua80a\ua80c-\ua822\ua840-\ua873\ua882-\ua8b3\ua8f2-\ua8f7\ua8fb\ua90a-\ua925\ua930-\ua946\ua960-\ua97c\ua984-\ua9b2\ua9cf\uaa00-\uaa28\uaa40-\uaa42\uaa44-\uaa4b\uaa60-\uaa76\uaa7a\uaa80-\uaaaf\uaab1\uaab5\uaab6\uaab9-\uaabd\uaac0\uaac2\uaadb-\uaadd\uaae0-\uaaea\uaaf2-\uaaf4\uab01-\uab06\uab09-\uab0e\uab11-\uab16\uab20-\uab26\uab28-\uab2e\uabc0-\uabe2\uac00-\ud7a3\ud7b0-\ud7c6\ud7cb-\ud7fb\uf900-\ufa6d\ufa70-\ufad9\ufb00-\ufb06\ufb13-\ufb17\ufb1d\ufb1f-\ufb28\ufb2a-\ufb36\ufb38-\ufb3c\ufb3e\ufb40\ufb41\ufb43\ufb44\ufb46-\ufbb1\ufbd3-\ufd3d\ufd50-\ufd8f\ufd92-\ufdc7\ufdf0-\ufdfb\ufe70-\ufe74\ufe76-\ufefc\uff21-\uff3a\uff41-\uff5a\uff66-\uffbe\uffc2-\uffc7\uffca-\uffcf\uffd2-\uffd7\uffda-\uffdc0-9\u0300-\u036f\u0483-\u0487\u0591-\u05bd\u05bf\u05c1\u05c2\u05c4\u05c5\u05c7\u0610-\u061a\u064b-\u0669\u0670\u06d6-\u06dc\u06df-\u06e4\u06e7\u06e8\u06ea-\u06ed\u06f0-\u06f9\u0711\u0730-\u074a\u07a6-\u07b0\u07c0-\u07c9\u07eb-\u07f3\u0816-\u0819\u081b-\u0823\u0825-\u0827\u0829-\u082d\u0859-\u085b\u08e4-\u08fe\u0900-\u0903\u093a-\u093c\u093e-\u094f\u0951-\u0957\u0962\u0963\u0966-\u096f\u0981-\u0983\u09bc\u09be-\u09c4\u09c7\u09c8\u09cb-\u09cd\u09d7\u09e2\u09e3\u09e6-\u09ef\u0a01-\u0a03\u0a3c\u0a3e-\u0a42\u0a47\u0a48\u0a4b-\u0a4d\u0a51\u0a66-\u0a71\u0a75\u0a81-\u0a83\u0abc\u0abe-\u0ac5\u0ac7-\u0ac9\u0acb-\u0acd\u0ae2\u0ae3\u0ae6-\u0aef\u0b01-\u0b03\u0b3c\u0b3e-\u0b44\u0b47\u0b48\u0b4b-\u0b4d\u0b56\u0b57\u0b62\u0b63\u0b66-\u0b6f\u0b82\u0bbe-\u0bc2\u0bc6-\u0bc8\u0bca-\u0bcd\u0bd7\u0be6-\u0bef\u0c01-\u0c03\u0c3e-\u0c44\u0c46-\u0c48\u0c4a-\u0c4d\u0c55\u0c56\u0c62\u0c63\u0c66-\u0c6f\u0c82\u0c83\u0cbc\u0cbe-\u0cc4\u0cc6-\u0cc8\u0cca-\u0ccd\u0cd5\u0cd6\u0ce2\u0ce3\u0ce6-\u0cef\u0d02\u0d03\u0d3e-\u0d44\u0d46-\u0d48\u0d4a-\u0d4d\u0d57\u0d62\u0d63\u0d66-\u0d6f\u0d82\u0d83\u0dca\u0dcf-\u0dd4\u0dd6\u0dd8-\u0ddf\u0df2\u0df3\u0e31\u0e34-\u0e3a\u0e47-\u0e4e\u0e50-\u0e59\u0eb1\u0eb4-\u0eb9\u0ebb\u0ebc\u0ec8-\u0ecd\u0ed0-\u0ed9\u0f18\u0f19\u0f20-\u0f29\u0f35\u0f37\u0f39\u0f3e\u0f3f\u0f71-\u0f84\u0f86\u0f87\u0f8d-\u0f97\u0f99-\u0fbc\u0fc6\u102b-\u103e\u1040-\u1049\u1056-\u1059\u105e-\u1060\u1062-\u1064\u1067-\u106d\u1071-\u1074\u1082-\u108d\u108f-\u109d\u135d-\u135f\u1712-\u1714\u1732-\u1734\u1752\u1753\u1772\u1773\u17b4-\u17d3\u17dd\u17e0-\u17e9\u180b-\u180d\u1810-\u1819\u18a9\u1920-\u192b\u1930-\u193b\u1946-\u194f\u19b0-\u19c0\u19c8\u19c9\u19d0-\u19d9\u1a17-\u1a1b\u1a55-\u1a5e\u1a60-\u1a7c\u1a7f-\u1a89\u1a90-\u1a99\u1b00-\u1b04\u1b34-\u1b44\u1b50-\u1b59\u1b6b-\u1b73\u1b80-\u1b82\u1ba1-\u1bad\u1bb0-\u1bb9\u1be6-\u1bf3\u1c24-\u1c37\u1c40-\u1c49\u1c50-\u1c59\u1cd0-\u1cd2\u1cd4-\u1ce8\u1ced\u1cf2-\u1cf4\u1dc0-\u1de6\u1dfc-\u1dff\u200c\u200d\u203f\u2040\u2054\u20d0-\u20dc\u20e1\u20e5-\u20f0\u2cef-\u2cf1\u2d7f\u2de0-\u2dff\u302a-\u302f\u3099\u309a\ua620-\ua629\ua66f\ua674-\ua67d\ua69f\ua6f0\ua6f1\ua802\ua806\ua80b\ua823-\ua827\ua880\ua881\ua8b4-\ua8c4\ua8d0-\ua8d9\ua8e0-\ua8f1\ua900-\ua909\ua926-\ua92d\ua947-\ua953\ua980-\ua983\ua9b3-\ua9c0\ua9d0-\ua9d9\uaa29-\uaa36\uaa43\uaa4c\uaa4d\uaa50-\uaa59\uaa7b\uaab0\uaab2-\uaab4\uaab7\uaab8\uaabe\uaabf\uaac1\uaaeb-\uaaef\uaaf5\uaaf6\uabe3-\uabea\uabec\uabed\uabf0-\uabf9\ufb1e\ufe00-\ufe0f\ufe20-\ufe26\ufe33\ufe34\ufe4d-\ufe4f\uff10-\uff19\uff3f]*$/; + +export const var_prefix = 'ˆ'; + +export const escape_ident = (name)=> { + if (check_ident.exec(name) !== null) { + return name; + } + + const [...chars] = name; + for (let idx = 0; idx < chars.length; idx+=1) { + const nme = `${var_prefix}${chars.join('')}`; + + if (check_ident.exec(nme) !== null) { + return nme; + } + // eslint-disable-next-line no-magic-numbers + chars[idx] = chars[idx].charCodeAt(0).toString(36); + } + + return `${var_prefix}${chars.join('')}`; +}; + + +export const transform_other = (node)=> { + if (node.value.match(/^[0-9].*/)) { + return numericLiteral(parseInt(node.value)); + } + + const name = escape_ident(node.value); + return identifier(name); +}; diff --git a/src/transform/other.test.js b/src/transform/other.test.js new file mode 100644 index 0000000..1e11d68 --- /dev/null +++ b/src/transform/other.test.js @@ -0,0 +1,68 @@ +import {fink2js} from '../testing'; + + +describe('identifiers', ()=> { + it('escapes reserved JS identifiers', ()=> { + expect( + fink2js(` + {do, if, in, for, let, new, try, var, case, enum, void} = foobar + {with, break, catch, class, const, super, while, yield, delete} = spam + {export, import, public, return, static, switch, typeof, default} = ham + {extends, finally, package, private, continue, debugger, function} = ni + {arguments, interface, protected, implements, instanceof} = nu + `) + ).toMatchSnapshot(); + }); + + + it('does not escape true, false, null', ()=> { + expect( + fink2js(` + foo = [true, false, null] + `) + ).toMatchSnapshot(); + }); + + + it('escapes identifiers incompatible with JS', ()=> { + expect( + fink2js(` + @ = spam + ∂ = shrub + `) + ).toMatchSnapshot(); + }); +}); + + +describe('numbers', ()=> { + it('transforms integers', ()=> { + expect( + fink2js(` + x = 1234578 + y = 0123 + `) + ).toMatchSnapshot(); + }); + + // TODO: not yet supported by larix + // it('transforms floats', ()=> { + // expect( + // fink2js(` + // x = 1.234578 + // y = 1.23e10 + // z = 1.23e-10 + // `) + // ).toMatchSnapshot(); + // }); + + // it('transforms hex, octet, binary', ()=> { + // expect( + // fink2js(` + // h = 0xABCDEF + // o = 0o1234567 + // b = 0b01010 + // `) + // ).toMatchSnapshot(); + // }); +}); diff --git a/src/transform/pipe.js b/src/transform/pipe.js index 36d9d61..b11c482 100644 --- a/src/transform/pipe.js +++ b/src/transform/pipe.js @@ -1,6 +1,18 @@ -import {call} from '../types'; +import {call, assign, lets, expr_block, nul} from '../types'; -export const transform_pipe = (node, {transform})=> ( - call(transform(node.right))(transform(node.left)) -); +export const transform_pipe = (node, {transform, unique_ident})=> { + const {exprs} = node; + const [start_value] = node.args; + + const result = unique_ident('pipe_result'); + + return expr_block( + // TODO: first should not be called with anything if + // there is no start_value + lets(result, start_value ? transform(start_value): nul()), + ...exprs.map((expr)=> ( + assign(result, call(transform(expr))(result)) + )) + ); +}; diff --git a/src/transform/pipe.test.js b/src/transform/pipe.test.js index bf99ac8..fca6217 100644 --- a/src/transform/pipe.test.js +++ b/src/transform/pipe.test.js @@ -4,10 +4,13 @@ import {fink2js} from '../testing'; test('compiles pipe', ()=> { expect( fink2js(` - foo - | bar - | spam() - | ni + pipe: + foo + bar + spam + + pipe [1, 2, 3]: + map item: item * 2 `) ).toMatchSnapshot(); }); diff --git a/src/transform/unfold.js b/src/transform/unfold.js index 26a7b55..95a40d4 100644 --- a/src/transform/unfold.js +++ b/src/transform/unfold.js @@ -1,6 +1,6 @@ import { - assign, generator, for_of, split_last, ident, call, yield_or_stop, - params, consts, yields + assign, generator, for_of, split_last, yield_or_stop, + params, consts, yields, true_ } from '../types'; import {whileStatement, blockStatement} from '@babel/types'; import {block_statement} from './block'; @@ -8,14 +8,17 @@ import {transform_left} from './left'; const loop = (...body)=> ( - whileStatement(ident('true'), blockStatement(body)) + whileStatement(true_(), blockStatement(body)) ); const get_acc = (inputs)=> { const [acc_init] = params(inputs); - const acc_id = acc_init.left; - return [acc_id, [acc_init]]; + if (acc_init) { + const acc_id = acc_init.left || acc_init; + return [acc_id, [acc_init]]; + } + return [null, []]; }; @@ -26,22 +29,28 @@ export const transform_unfold = (node, {transform, unique_ident})=> { const [expressions, last_expr] = split_last(node.exprs); - const [result, next_value] = last_expr.type === 'group' - ? last_expr.exprs - : [last_expr, false]; + const [result, next_value] = ( + last_expr.type === 'group' + ? last_expr.exprs + : [last_expr, false] + ); const result_id = unique_ident('result'); + const acc_assign = acc_id && ( + next_value + ? assign(acc_id, transform(next_value)) + : assign(acc_id, result_id) + ); + const gen = generator('unfold')(...acc_init)( loop( ...expressions.map(block_statement({transform})), consts(result_id, transform(result)), yields(result_id), - next_value - ? assign(acc_id, transform(next_value)) - : assign(acc_id, result_id) + ...(acc_assign ? [acc_assign] : []) ) ); - return call(gen)(); + return gen; }; diff --git a/src/transform/unfold.test.js b/src/transform/unfold.test.js index 5b6ddb0..e33c742 100644 --- a/src/transform/unfold.test.js +++ b/src/transform/unfold.test.js @@ -7,7 +7,13 @@ test('compiles unfold', ()=> { unfold curr=start: (curr + inc, curr * 2) - count = (start=0, inc=1): + unfold curr: + (curr + inc, curr * 2) + + unfold: + 1234 + + count = fn start=0, inc=1: unfold curr=start: curr + inc `) diff --git a/src/transform/while.js b/src/transform/while.js new file mode 100644 index 0000000..121ebe3 --- /dev/null +++ b/src/transform/while.js @@ -0,0 +1,29 @@ +import { + params, generator, for_of, yield_or_stop, split_last, iff, yields, consts, + returns, neq, true_ +} from '../types'; +import {is_call, is_calling} from './call'; +import {block_statement} from './block'; + + +export const transform_while = (node, {transform, unique_ident})=> { + const [item_param] = params(node.args.map(transform)); + + const [expressions, last_expr] = split_last(node.exprs); + + const item = unique_ident('item'); + const items = unique_ident('items'); + const result = unique_ident('result'); + + return generator('filter_while')(items)( + for_of(item, items)( + consts(item_param, item), + ...expressions.map(block_statement({transform})), + consts(result, transform(last_expr)), + iff(neq(result, true_()))( + returns() + ), + yields(item) + ) + ); +}; diff --git a/src/transform/while.test.js b/src/transform/while.test.js new file mode 100644 index 0000000..2e7c979 --- /dev/null +++ b/src/transform/while.test.js @@ -0,0 +1,11 @@ +import {fink2js} from '../testing'; + + +test('while', ()=> { + expect( + fink2js(` + while item: + item < 10 + `) + ).toMatchSnapshot(); +}); diff --git a/src/types.js b/src/types.js index 9299be1..b340af5 100644 --- a/src/types.js +++ b/src/types.js @@ -5,14 +5,21 @@ import { blockStatement, identifier, arrowFunctionExpression, logicalExpression, binaryExpression, unaryExpression, stringLiteral, memberExpression, ifStatement, doExpression, - assignmentExpression, isAssignmentExpression, isObjectExpression, + assignmentExpression, returnStatement, + isAssignmentExpression, isObjectExpression, isArrayExpression, isIdentifier } from '@babel/types'; +import {escape_ident} from './transform/other'; + export const map = (mapper)=> ([...items])=> items.map(mapper); +export const wrap = (larix_node, js_node)=> ( + {...js_node, loc: larix_node.loc} +); + export const expr_block = (...expr)=> ( doExpression( blockStatement( @@ -62,6 +69,10 @@ export const undef = ()=> identifier('undefined'); export const nul = ()=> identifier('null'); +// eslint-disable-next-line no-underscore-dangle +export const true_ = ()=> identifier('true'); + +// export const false_ = ()=> identifier('false'); export const not_nullish = (value)=> and( neq(value, undef()), @@ -71,7 +82,7 @@ export const not_nullish = (value)=> and( export const ident = (name)=> ( typeof name === 'string' - ? identifier(name) + ? identifier(escape_ident(name)) : name ); @@ -104,7 +115,7 @@ export const yields = (expr, delegate)=> ( export const iff = (test)=> (consequent)=> ifStatement(test, consequent); -// export const returns = (expr)=> returnStatement(expr); +export const returns = (expr)=> returnStatement(expr); export const yield_or_stop = (expr, unique_ident, delegate)=> { @@ -127,10 +138,6 @@ export const func = (...args)=> (expr, ...expressions)=> ( arrowFunctionExpression( args, expr_block(expr, ...expressions) - // TODO: check needed? - // expressions.length > 0 - // ? expr_block(expr, ...expressions) - // : expr ) );