Major restructuring and update to code base

- Created a new VSCode Extension subproject
 - Created a new Bolt CLI subproject
 - Created a new Bolt Language Server subproject
 - Created a new Bolt Compiler subproject
 - Moved most existing code to the new Compiler subproject
 - Added a small language server
 - Laid the foundations for a Hindley-Milner type checker
 - Fixed some bugs and type errors in the compiler
 - Removed the unused testing infrastructure
 - Added an example parser test that should be run with Ava
This commit is contained in:
Sam Vervaeck 2020-11-15 09:57:25 +01:00
parent a30450c100
commit 2b2d40c4f5
99 changed files with 26718 additions and 4354 deletions

View file

@ -1,3 +0,0 @@
{
"plugins": ["@babel/plugin-proposal-class-properties"]
}

10
.gitignore vendored
View file

@ -1,7 +1,4 @@
# embedded repositories
/meta/
# IDEs
.vscode/
@ -11,11 +8,6 @@ node_modules/
# bolt
.bolt-work/
# these are ignored to avoid a lot of bloat in IDEs
/.test-infrastructure/snapshots/
# build directories
# compiled code for testin
/lib/
/build/
/dist/

5
@boltlang/cli/.babelrc Normal file
View file

@ -0,0 +1,5 @@
{
"presets": [
"@babel/preset-env"
]
}

View file

@ -0,0 +1 @@
maintained node versions, last 4 electron versions

7
@boltlang/cli/.gitignore vendored Normal file
View file

@ -0,0 +1,7 @@
# npm
node_modules/
# resulting code
/bin/

572
@boltlang/cli/package-lock.json generated Normal file
View file

@ -0,0 +1,572 @@
{
"name": "@boltlang/cli",
"version": "1.0.0",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"version": "1.0.0",
"license": "GPL-3.0",
"dependencies": {
"ora": "^5.1.0",
"yargs": "^16.1.0"
},
"bin": {
"bolt": "bin/bolt.js"
}
},
"node_modules/ansi-regex": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz",
"integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==",
"engines": {
"node": ">=8"
}
},
"node_modules/ansi-styles": {
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
"integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
"dependencies": {
"color-convert": "^2.0.1"
},
"engines": {
"node": ">=8"
},
"funding": {
"url": "https://github.com/chalk/ansi-styles?sponsor=1"
}
},
"node_modules/chalk": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz",
"integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==",
"dependencies": {
"ansi-styles": "^4.1.0",
"supports-color": "^7.1.0"
},
"engines": {
"node": ">=10"
},
"funding": {
"url": "https://github.com/chalk/chalk?sponsor=1"
}
},
"node_modules/cli-cursor": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz",
"integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==",
"dependencies": {
"restore-cursor": "^3.1.0"
},
"engines": {
"node": ">=8"
}
},
"node_modules/cli-spinners": {
"version": "2.5.0",
"resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.5.0.tgz",
"integrity": "sha512-PC+AmIuK04E6aeSs/pUccSujsTzBhu4HzC2dL+CfJB/Jcc2qTRbEwZQDfIUpt2Xl8BodYBEq8w4fc0kU2I9DjQ==",
"engines": {
"node": ">=6"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/cliui": {
"version": "7.0.4",
"resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz",
"integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==",
"dependencies": {
"string-width": "^4.2.0",
"strip-ansi": "^6.0.0",
"wrap-ansi": "^7.0.0"
}
},
"node_modules/clone": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz",
"integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4=",
"engines": {
"node": ">=0.8"
}
},
"node_modules/color-convert": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
"dependencies": {
"color-name": "~1.1.4"
},
"engines": {
"node": ">=7.0.0"
}
},
"node_modules/color-name": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
},
"node_modules/defaults": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.3.tgz",
"integrity": "sha1-xlYFHpgX2f8I7YgUd/P+QBnz730=",
"dependencies": {
"clone": "^1.0.2"
}
},
"node_modules/emoji-regex": {
"version": "8.0.0",
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
"integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="
},
"node_modules/escalade": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz",
"integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==",
"engines": {
"node": ">=6"
}
},
"node_modules/get-caller-file": {
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
"integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==",
"engines": {
"node": "6.* || 8.* || >= 10.*"
}
},
"node_modules/has-flag": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
"integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
"engines": {
"node": ">=8"
}
},
"node_modules/is-fullwidth-code-point": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
"integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
"engines": {
"node": ">=8"
}
},
"node_modules/is-interactive": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz",
"integrity": "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==",
"engines": {
"node": ">=8"
}
},
"node_modules/log-symbols": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.0.0.tgz",
"integrity": "sha512-FN8JBzLx6CzeMrB0tg6pqlGU1wCrXW+ZXGH481kfsBqer0hToTIiHdjH4Mq8xJUbvATujKCvaREGWpGUionraA==",
"dependencies": {
"chalk": "^4.0.0"
},
"engines": {
"node": ">=10"
}
},
"node_modules/mimic-fn": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz",
"integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==",
"engines": {
"node": ">=6"
}
},
"node_modules/mute-stream": {
"version": "0.0.8",
"resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz",
"integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA=="
},
"node_modules/onetime": {
"version": "5.1.2",
"resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz",
"integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==",
"dependencies": {
"mimic-fn": "^2.1.0"
},
"engines": {
"node": ">=6"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/ora": {
"version": "5.1.0",
"resolved": "https://registry.npmjs.org/ora/-/ora-5.1.0.tgz",
"integrity": "sha512-9tXIMPvjZ7hPTbk8DFq1f7Kow/HU/pQYB60JbNq+QnGwcyhWVZaQ4hM9zQDEsPxw/muLpgiHSaumUZxCAmod/w==",
"dependencies": {
"chalk": "^4.1.0",
"cli-cursor": "^3.1.0",
"cli-spinners": "^2.4.0",
"is-interactive": "^1.0.0",
"log-symbols": "^4.0.0",
"mute-stream": "0.0.8",
"strip-ansi": "^6.0.0",
"wcwidth": "^1.0.1"
},
"engines": {
"node": ">=10"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/require-directory": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
"integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/restore-cursor": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz",
"integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==",
"dependencies": {
"onetime": "^5.1.0",
"signal-exit": "^3.0.2"
},
"engines": {
"node": ">=8"
}
},
"node_modules/signal-exit": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz",
"integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA=="
},
"node_modules/string-width": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz",
"integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==",
"dependencies": {
"emoji-regex": "^8.0.0",
"is-fullwidth-code-point": "^3.0.0",
"strip-ansi": "^6.0.0"
},
"engines": {
"node": ">=8"
}
},
"node_modules/strip-ansi": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz",
"integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==",
"dependencies": {
"ansi-regex": "^5.0.0"
},
"engines": {
"node": ">=8"
}
},
"node_modules/supports-color": {
"version": "7.2.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
"integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
"dependencies": {
"has-flag": "^4.0.0"
},
"engines": {
"node": ">=8"
}
},
"node_modules/wcwidth": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz",
"integrity": "sha1-8LDc+RW8X/FSivrbLA4XtTLaL+g=",
"dependencies": {
"defaults": "^1.0.3"
}
},
"node_modules/wrap-ansi": {
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
"integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
"dependencies": {
"ansi-styles": "^4.0.0",
"string-width": "^4.1.0",
"strip-ansi": "^6.0.0"
},
"engines": {
"node": ">=10"
},
"funding": {
"url": "https://github.com/chalk/wrap-ansi?sponsor=1"
}
},
"node_modules/y18n": {
"version": "5.0.5",
"resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.5.tgz",
"integrity": "sha512-hsRUr4FFrvhhRH12wOdfs38Gy7k2FFzB9qgN9v3aLykRq0dRcdcpz5C9FxdS2NuhOrI/628b/KSTJ3rwHysYSg==",
"engines": {
"node": ">=10"
}
},
"node_modules/yargs": {
"version": "16.1.0",
"resolved": "https://registry.npmjs.org/yargs/-/yargs-16.1.0.tgz",
"integrity": "sha512-upWFJOmDdHN0syLuESuvXDmrRcWd1QafJolHskzaw79uZa7/x53gxQKiR07W59GWY1tFhhU/Th9DrtSfpS782g==",
"dependencies": {
"cliui": "^7.0.2",
"escalade": "^3.1.1",
"get-caller-file": "^2.0.5",
"require-directory": "^2.1.1",
"string-width": "^4.2.0",
"y18n": "^5.0.2",
"yargs-parser": "^20.2.2"
},
"engines": {
"node": ">=10"
}
},
"node_modules/yargs-parser": {
"version": "20.2.4",
"resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz",
"integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==",
"engines": {
"node": ">=10"
}
}
},
"dependencies": {
"ansi-regex": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz",
"integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg=="
},
"ansi-styles": {
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
"integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
"requires": {
"color-convert": "^2.0.1"
}
},
"chalk": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz",
"integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==",
"requires": {
"ansi-styles": "^4.1.0",
"supports-color": "^7.1.0"
}
},
"cli-cursor": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz",
"integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==",
"requires": {
"restore-cursor": "^3.1.0"
}
},
"cli-spinners": {
"version": "2.5.0",
"resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.5.0.tgz",
"integrity": "sha512-PC+AmIuK04E6aeSs/pUccSujsTzBhu4HzC2dL+CfJB/Jcc2qTRbEwZQDfIUpt2Xl8BodYBEq8w4fc0kU2I9DjQ=="
},
"cliui": {
"version": "7.0.4",
"resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz",
"integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==",
"requires": {
"string-width": "^4.2.0",
"strip-ansi": "^6.0.0",
"wrap-ansi": "^7.0.0"
}
},
"clone": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz",
"integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4="
},
"color-convert": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
"requires": {
"color-name": "~1.1.4"
}
},
"color-name": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
},
"defaults": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.3.tgz",
"integrity": "sha1-xlYFHpgX2f8I7YgUd/P+QBnz730=",
"requires": {
"clone": "^1.0.2"
}
},
"emoji-regex": {
"version": "8.0.0",
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
"integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="
},
"escalade": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz",
"integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw=="
},
"get-caller-file": {
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
"integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg=="
},
"has-flag": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
"integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ=="
},
"is-fullwidth-code-point": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
"integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg=="
},
"is-interactive": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz",
"integrity": "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w=="
},
"log-symbols": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.0.0.tgz",
"integrity": "sha512-FN8JBzLx6CzeMrB0tg6pqlGU1wCrXW+ZXGH481kfsBqer0hToTIiHdjH4Mq8xJUbvATujKCvaREGWpGUionraA==",
"requires": {
"chalk": "^4.0.0"
}
},
"mimic-fn": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz",
"integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg=="
},
"mute-stream": {
"version": "0.0.8",
"resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz",
"integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA=="
},
"onetime": {
"version": "5.1.2",
"resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz",
"integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==",
"requires": {
"mimic-fn": "^2.1.0"
}
},
"ora": {
"version": "5.1.0",
"resolved": "https://registry.npmjs.org/ora/-/ora-5.1.0.tgz",
"integrity": "sha512-9tXIMPvjZ7hPTbk8DFq1f7Kow/HU/pQYB60JbNq+QnGwcyhWVZaQ4hM9zQDEsPxw/muLpgiHSaumUZxCAmod/w==",
"requires": {
"chalk": "^4.1.0",
"cli-cursor": "^3.1.0",
"cli-spinners": "^2.4.0",
"is-interactive": "^1.0.0",
"log-symbols": "^4.0.0",
"mute-stream": "0.0.8",
"strip-ansi": "^6.0.0",
"wcwidth": "^1.0.1"
}
},
"require-directory": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
"integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I="
},
"restore-cursor": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz",
"integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==",
"requires": {
"onetime": "^5.1.0",
"signal-exit": "^3.0.2"
}
},
"signal-exit": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz",
"integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA=="
},
"string-width": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz",
"integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==",
"requires": {
"emoji-regex": "^8.0.0",
"is-fullwidth-code-point": "^3.0.0",
"strip-ansi": "^6.0.0"
}
},
"strip-ansi": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz",
"integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==",
"requires": {
"ansi-regex": "^5.0.0"
}
},
"supports-color": {
"version": "7.2.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
"integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
"requires": {
"has-flag": "^4.0.0"
}
},
"wcwidth": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz",
"integrity": "sha1-8LDc+RW8X/FSivrbLA4XtTLaL+g=",
"requires": {
"defaults": "^1.0.3"
}
},
"wrap-ansi": {
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
"integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
"requires": {
"ansi-styles": "^4.0.0",
"string-width": "^4.1.0",
"strip-ansi": "^6.0.0"
}
},
"y18n": {
"version": "5.0.5",
"resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.5.tgz",
"integrity": "sha512-hsRUr4FFrvhhRH12wOdfs38Gy7k2FFzB9qgN9v3aLykRq0dRcdcpz5C9FxdS2NuhOrI/628b/KSTJ3rwHysYSg=="
},
"yargs": {
"version": "16.1.0",
"resolved": "https://registry.npmjs.org/yargs/-/yargs-16.1.0.tgz",
"integrity": "sha512-upWFJOmDdHN0syLuESuvXDmrRcWd1QafJolHskzaw79uZa7/x53gxQKiR07W59GWY1tFhhU/Th9DrtSfpS782g==",
"requires": {
"cliui": "^7.0.2",
"escalade": "^3.1.1",
"get-caller-file": "^2.0.5",
"require-directory": "^2.1.1",
"string-width": "^4.2.0",
"y18n": "^5.0.2",
"yargs-parser": "^20.2.2"
}
},
"yargs-parser": {
"version": "20.2.4",
"resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz",
"integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA=="
}
}
}

View file

@ -0,0 +1,28 @@
{
"name": "@boltlang/cli",
"version": "1.0.0",
"description": "The official command-line interface of the Bolt programming language",
"main": "index.js",
"bin": {
"bolt": "bin/bolt.js"
},
"scripts": {
"prepare": "webpack --mode production",
"watch": "webpack --mode development --watch",
"test": "echo \"Error: no test specified\" && exit 1"
},
"repository": {
"type": "git",
"url": "git+https://github.com/BoltLang/BoltJS.git"
},
"author": "Sam Vervaeck",
"license": "GPL-3.0",
"bugs": {
"url": "https://github.com/BoltLang/BoltJS/issues"
},
"homepage": "https://github.com/BoltLang/BoltJS#readme",
"dependencies": {
"ora": "^5.1.0",
"yargs": "^16.1.0"
}
}

View file

@ -4,8 +4,8 @@ import "source-map-support/register"
import yargs from "yargs"
import { Frontend } from "../frontend"
import { expandPath } from "../util"
import { Frontend } from "@boltlang/compiler/frontend"
import { expandPath } from "@boltlang/compiler/util"
const BOLT_HOME = expandPath(process.env['BOLT_HOME'] ?? '~/.bolt-compiler')
@ -61,10 +61,10 @@ yargs
const frontend = new Frontend();
parsePackageResolverFlags(frontend, toArray(args.pkg as string | string[]));
const program = frontend.loadProgramFromFileList(files, cwd, useStd);
if (program !== null) {
if (!frontend.diagnostics.hasFatal && program !== null) {
frontend.check(program);
}
if (frontend.diagnostics.hasErrors) {
if (frontend.diagnostics.hasErrors || frontend.diagnostics.hasFatal) {
process.exit(1);
}
}
@ -124,7 +124,7 @@ yargs
.default('work-dir', '.')
.boolean('skip-type-checks')
.describe('skip-type-checks', 'Do not check the program for common mistakes before evaluating.')
.default('skip-type-checks', false)
.default('skip-type-checks', true)
.boolean('force')
.describe('force', 'Ignore as much errors as possible.')
.default('force', false)
@ -138,7 +138,7 @@ yargs
const files = toArray(args.files as string[] | string);
const frontend = new Frontend();
parsePackageResolverFlags(frontend, toArray(args.pkg as string | string[]));
const program = frontend.loadProgramFromFileList(files, cwd, useStd);
@ -162,6 +162,7 @@ yargs
)
.demandCommand()
.help()
.version()
.argv

View file

@ -0,0 +1,13 @@
{
"compilerOptions": {
"target": "ES2019",
"module": "commonjs",
"sourceMap": true,
"noEmit": true,
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true,
"baseUrl": "../../"
}
}

View file

@ -1,17 +1,16 @@
const webpack = require("webpack");
const path = require("path");
const path = require('path');
const webpack = require('webpack');
module.exports = {
target: 'node',
mode: 'development',
entry: {
'bolt': './src/bin/bolt.ts',
'bolt-test': './src/bin/bolt-test.ts',
'bolt': './src/main.ts'
},
output: {
filename: 'bin/[name].js',
path: path.resolve(__dirname, 'build'),
path: path.resolve(__dirname),
devtoolModuleFilenameTemplate: '[absolute-resource-path]'
},
resolve: {
extensions: [".ts", ".js"],
@ -36,4 +35,3 @@ module.exports = {
]
}
};

16
@boltlang/compiler/.gitignore vendored Normal file
View file

@ -0,0 +1,16 @@
# all compiled files except a few
*.js
*.js.map
*.d.ts
*.d.ts.map
!/webpack.config.js
# npm
node_modules/
# compiled code for testing
/lib/
# often created when publishing to npm
*.tgz

View file

@ -0,0 +1,7 @@
/src/
/test/
/scripts/
Makefile
webpack.config.js
*.tgz
tsconfig.json

View file

@ -1,6 +1,6 @@
all: src/ast.ts
bolt check test.bolt --no-std
npm test
src/ast.ts: src/ast-spec.ts
@echo "Generating AST definitions ..."

622
@boltlang/compiler/package-lock.json generated Normal file
View file

@ -0,0 +1,622 @@
{
"name": "@samvv/bolt",
"version": "0.0.1",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
"@types/color-name": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/@types/color-name/-/color-name-1.1.1.tgz",
"integrity": "sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ=="
},
"@types/commonmark": {
"version": "0.27.4",
"resolved": "https://registry.npmjs.org/@types/commonmark/-/commonmark-0.27.4.tgz",
"integrity": "sha512-7koSjp08QxKoS1/+3T15+kD7+vqOUvZRHvM8PutF3Xsk5aAEkdlIGRsHJ3/XsC3izoqTwBdRW/vH7rzCKkIicA=="
},
"@types/diff": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/@types/diff/-/diff-4.0.2.tgz",
"integrity": "sha512-mIenTfsIe586/yzsyfql69KRnA75S8SVXQbTLpDejRrjH0QSJcpu3AUOi/Vjnt9IOsXKxPhJfGpQUNMueIU1fQ=="
},
"@types/fs-extra": {
"version": "9.0.4",
"resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-9.0.4.tgz",
"integrity": "sha512-50GO5ez44lxK5MDH90DYHFFfqxH7+fTqEEnvguQRzJ/tY9qFrMSHLiYHite+F3SNmf7+LHC1eMXojuD+E3Qcyg==",
"requires": {
"@types/node": "*"
}
},
"@types/glob": {
"version": "7.1.3",
"resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.1.3.tgz",
"integrity": "sha512-SEYeGAIQIQX8NN6LDKprLjbrd5dARM5EXsd8GI/A5l0apYI1fGMWgPHSe4ZKL4eozlAyI+doUE9XbYS4xCkQ1w==",
"requires": {
"@types/minimatch": "*",
"@types/node": "*"
}
},
"@types/js-yaml": {
"version": "3.12.5",
"resolved": "https://registry.npmjs.org/@types/js-yaml/-/js-yaml-3.12.5.tgz",
"integrity": "sha512-JCcp6J0GV66Y4ZMDAQCXot4xprYB+Zfd3meK9+INSJeVZwJmHAW30BBEEkPzXswMXuiyReUGOP3GxrADc9wPww=="
},
"@types/microtime": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/@types/microtime/-/microtime-2.1.0.tgz",
"integrity": "sha1-rb2Z9QGoXIhpXrHv01FYEPJWOTI="
},
"@types/minimatch": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.3.tgz",
"integrity": "sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA=="
},
"@types/minimist": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/@types/minimist/-/minimist-1.2.1.tgz",
"integrity": "sha512-fZQQafSREFyuZcdWFAExYjBiCL7AUCdgsk80iO0q4yihYYdcIiH28CcuPTGFgLOCC8RlW49GSQxdHwZP+I7CNg=="
},
"@types/node": {
"version": "14.14.7",
"resolved": "https://registry.npmjs.org/@types/node/-/node-14.14.7.tgz",
"integrity": "sha512-Zw1vhUSQZYw+7u5dAwNbIA9TuTotpzY/OF7sJM9FqPOF3SPjKnxrjoTktXDZgUjybf4cWVBP7O8wvKdSaGHweg=="
},
"@types/ora": {
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/@types/ora/-/ora-3.2.0.tgz",
"integrity": "sha512-jll99xUKpiFbIFZSQcxm4numfsLaOWBzWNaRk3PvTSE7BPqTzzOCFmS0mQ7m8qkTfmYhuYbehTGsxkvRLPC++w==",
"requires": {
"ora": "*"
}
},
"@types/semver": {
"version": "7.3.4",
"resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.3.4.tgz",
"integrity": "sha512-+nVsLKlcUCeMzD2ufHEYuJ9a2ovstb6Dp52A5VsoKxDXgvE051XgHI/33I1EymwkRGQkwnA0LkhnUzituGs4EQ=="
},
"@types/uuid": {
"version": "8.3.0",
"resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-8.3.0.tgz",
"integrity": "sha512-eQ9qFW/fhfGJF8WKHGEHZEyVWfZxrT+6CLIJGBcZPfxUh/+BnEj+UCGYMlr9qZuX/2AltsvwrGqp0LhEW8D0zQ=="
},
"@types/yargs": {
"version": "15.0.9",
"resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-15.0.9.tgz",
"integrity": "sha512-HmU8SeIRhZCWcnRskCs36Q1Q00KBV6Cqh/ora8WN1+22dY07AZdn6Gel8QZ3t26XYPImtcL8WV/eqjhVmMEw4g==",
"requires": {
"@types/yargs-parser": "*"
}
},
"@types/yargs-parser": {
"version": "15.0.0",
"resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-15.0.0.tgz",
"integrity": "sha512-FA/BWv8t8ZWJ+gEOnLLd8ygxH/2UFbAvgEonyfN6yWGLKc7zVjbpl2Y4CTjid9h2RfgPP6SEt6uHwEOply00yw=="
},
"ansi-regex": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz",
"integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg=="
},
"argparse": {
"version": "1.0.10",
"resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",
"integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==",
"requires": {
"sprintf-js": "~1.0.2"
}
},
"at-least-node": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz",
"integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg=="
},
"balanced-match": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
"integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c="
},
"brace-expansion": {
"version": "1.1.11",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
"requires": {
"balanced-match": "^1.0.0",
"concat-map": "0.0.1"
}
},
"buffer-from": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz",
"integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A=="
},
"chalk": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz",
"integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==",
"requires": {
"ansi-styles": "^4.1.0",
"supports-color": "^7.1.0"
},
"dependencies": {
"ansi-styles": {
"version": "4.2.1",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz",
"integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==",
"requires": {
"@types/color-name": "^1.1.1",
"color-convert": "^2.0.1"
}
},
"color-convert": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
"requires": {
"color-name": "~1.1.4"
}
},
"color-name": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
}
}
},
"cli-cursor": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz",
"integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==",
"requires": {
"restore-cursor": "^3.1.0"
}
},
"cli-spinners": {
"version": "2.5.0",
"resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.5.0.tgz",
"integrity": "sha512-PC+AmIuK04E6aeSs/pUccSujsTzBhu4HzC2dL+CfJB/Jcc2qTRbEwZQDfIUpt2Xl8BodYBEq8w4fc0kU2I9DjQ=="
},
"cliui": {
"version": "7.0.3",
"resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.3.tgz",
"integrity": "sha512-Gj3QHTkVMPKqwP3f7B4KPkBZRMR9r4rfi5bXFpg1a+Svvj8l7q5CnkBkVQzfxT5DFSsGk2+PascOgL0JYkL2kw==",
"requires": {
"string-width": "^4.2.0",
"strip-ansi": "^6.0.0",
"wrap-ansi": "^7.0.0"
}
},
"clone": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz",
"integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4="
},
"commonmark": {
"version": "0.29.2",
"resolved": "https://registry.npmjs.org/commonmark/-/commonmark-0.29.2.tgz",
"integrity": "sha512-spe43MvEIaPpHss1T7z4yQaFQfLGmMu+yvCwv6xqhELIwkG/ZGgDpxOPzKxnuYzYT2c+aziCCc8m2rBVLA7jUA==",
"requires": {
"entities": "~2.0",
"mdurl": "~1.0.1",
"minimist": ">=1.2.2",
"string.prototype.repeat": "^0.2.0"
}
},
"concat-map": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
"integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s="
},
"defaults": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.3.tgz",
"integrity": "sha1-xlYFHpgX2f8I7YgUd/P+QBnz730=",
"requires": {
"clone": "^1.0.2"
}
},
"diff": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz",
"integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w=="
},
"emoji-regex": {
"version": "8.0.0",
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
"integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="
},
"entities": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/entities/-/entities-2.0.3.tgz",
"integrity": "sha512-MyoZ0jgnLvB2X3Lg5HqpFmn1kybDiIfEQmKzTb5apr51Rb+T3KdmMiqa70T+bhGnyv7bQ6WMj2QMHpGMmlrUYQ=="
},
"escalade": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz",
"integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw=="
},
"esprima": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz",
"integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A=="
},
"fs-extra": {
"version": "9.0.1",
"resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.0.1.tgz",
"integrity": "sha512-h2iAoN838FqAFJY2/qVpzFXy+EBxfVE220PalAqQLDVsFOHLJrZvut5puAbCdNv6WJk+B8ihI+k0c7JK5erwqQ==",
"requires": {
"at-least-node": "^1.0.0",
"graceful-fs": "^4.2.0",
"jsonfile": "^6.0.1",
"universalify": "^1.0.0"
}
},
"fs.realpath": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
"integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8="
},
"get-caller-file": {
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
"integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg=="
},
"glob": {
"version": "7.1.6",
"resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz",
"integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==",
"requires": {
"fs.realpath": "^1.0.0",
"inflight": "^1.0.4",
"inherits": "2",
"minimatch": "^3.0.4",
"once": "^1.3.0",
"path-is-absolute": "^1.0.0"
}
},
"graceful-fs": {
"version": "4.2.4",
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz",
"integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw=="
},
"inflight": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
"integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
"requires": {
"once": "^1.3.0",
"wrappy": "1"
}
},
"inherits": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
},
"is-interactive": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz",
"integrity": "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w=="
},
"js-yaml": {
"version": "3.14.0",
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.0.tgz",
"integrity": "sha512-/4IbIeHcD9VMHFqDR/gQ7EdZdLimOvW2DdcxFjdyyZ9NsbS+ccrXqVWDtab/lRl5AlUqmpBx8EhPaWR+OtY17A==",
"requires": {
"argparse": "^1.0.7",
"esprima": "^4.0.0"
}
},
"jsonfile": {
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.0.1.tgz",
"integrity": "sha512-jR2b5v7d2vIOust+w3wtFKZIfpC2pnRmFAhAC/BuweZFQR8qZzxH1OyrQ10HmdVYiXWkYUqPVsz91cG7EL2FBg==",
"requires": {
"graceful-fs": "^4.1.6",
"universalify": "^1.0.0"
}
},
"log-symbols": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.0.0.tgz",
"integrity": "sha512-FN8JBzLx6CzeMrB0tg6pqlGU1wCrXW+ZXGH481kfsBqer0hToTIiHdjH4Mq8xJUbvATujKCvaREGWpGUionraA==",
"requires": {
"chalk": "^4.0.0"
}
},
"mdurl": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz",
"integrity": "sha1-/oWy7HWlkDfyrf7BAP1sYBdhFS4="
},
"microtime": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/microtime/-/microtime-3.0.0.tgz",
"integrity": "sha512-SirJr7ZL4ow2iWcb54bekS4aWyBQNVcEDBiwAz9D/sTgY59A+uE8UJU15cp5wyZmPBwg/3zf8lyCJ5NUe1nVlQ==",
"requires": {
"node-addon-api": "^1.2.0",
"node-gyp-build": "^3.8.0"
}
},
"mimic-fn": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz",
"integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg=="
},
"minimatch": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
"integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
"requires": {
"brace-expansion": "^1.1.7"
}
},
"minimist": {
"version": "1.2.5",
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz",
"integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw=="
},
"moment": {
"version": "2.29.1",
"resolved": "https://registry.npmjs.org/moment/-/moment-2.29.1.tgz",
"integrity": "sha512-kHmoybcPV8Sqy59DwNDY3Jefr64lK/by/da0ViFcuA4DH0vQg5Q6Ze5VimxkfQNSC+Mls/Kx53s7TjP1RhFEDQ=="
},
"mute-stream": {
"version": "0.0.8",
"resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz",
"integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA=="
},
"node-addon-api": {
"version": "1.7.1",
"resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-1.7.1.tgz",
"integrity": "sha512-2+DuKodWvwRTrCfKOeR24KIc5unKjOh8mz17NCzVnHWfjAdDqbfbjqh7gUT+BkXBRQM52+xCHciKWonJ3CbJMQ=="
},
"node-gyp-build": {
"version": "3.9.0",
"resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-3.9.0.tgz",
"integrity": "sha512-zLcTg6P4AbcHPq465ZMFNXx7XpKKJh+7kkN699NiQWisR2uWYOWNWqRHAmbnmKiL4e9aLSlmy5U7rEMUXV59+A=="
},
"once": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
"integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
"requires": {
"wrappy": "1"
}
},
"onetime": {
"version": "5.1.2",
"resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz",
"integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==",
"requires": {
"mimic-fn": "^2.1.0"
}
},
"ora": {
"version": "5.1.0",
"resolved": "https://registry.npmjs.org/ora/-/ora-5.1.0.tgz",
"integrity": "sha512-9tXIMPvjZ7hPTbk8DFq1f7Kow/HU/pQYB60JbNq+QnGwcyhWVZaQ4hM9zQDEsPxw/muLpgiHSaumUZxCAmod/w==",
"requires": {
"chalk": "^4.1.0",
"cli-cursor": "^3.1.0",
"cli-spinners": "^2.4.0",
"is-interactive": "^1.0.0",
"log-symbols": "^4.0.0",
"mute-stream": "0.0.8",
"strip-ansi": "^6.0.0",
"wcwidth": "^1.0.1"
}
},
"path-is-absolute": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
"integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18="
},
"reflect-metadata": {
"version": "0.1.13",
"resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.1.13.tgz",
"integrity": "sha512-Ts1Y/anZELhSsjMcU605fU9RE4Oi3p5ORujwbIKXfWa+0Zxs510Qrmrce5/Jowq3cHSZSJqBjypxmHarc+vEWg=="
},
"require-directory": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
"integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I="
},
"restore-cursor": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz",
"integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==",
"requires": {
"onetime": "^5.1.0",
"signal-exit": "^3.0.2"
}
},
"semver": {
"version": "7.3.2",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.3.2.tgz",
"integrity": "sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ=="
},
"signal-exit": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz",
"integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA=="
},
"source-map": {
"version": "0.6.1",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="
},
"source-map-support": {
"version": "0.5.19",
"resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.19.tgz",
"integrity": "sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==",
"requires": {
"buffer-from": "^1.0.0",
"source-map": "^0.6.0"
}
},
"sprintf-js": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
"integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw="
},
"string-width": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz",
"integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==",
"requires": {
"emoji-regex": "^8.0.0",
"is-fullwidth-code-point": "^3.0.0",
"strip-ansi": "^6.0.0"
},
"dependencies": {
"is-fullwidth-code-point": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
"integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg=="
}
}
},
"string.prototype.repeat": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/string.prototype.repeat/-/string.prototype.repeat-0.2.0.tgz",
"integrity": "sha1-q6Nt4I3O5qWjN9SbLqHaGyj8Ds8="
},
"strip-ansi": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz",
"integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==",
"requires": {
"ansi-regex": "^5.0.0"
}
},
"supports-color": {
"version": "7.1.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz",
"integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==",
"requires": {
"has-flag": "^4.0.0"
},
"dependencies": {
"has-flag": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
"integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ=="
}
}
},
"universalify": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/universalify/-/universalify-1.0.0.tgz",
"integrity": "sha512-rb6X1W158d7pRQBg5gkR8uPaSfiids68LTJQYOtEUhoJUWBdaQHsuT/EUduxXYxcrt4r5PJ4fuHW1MHT6p0qug=="
},
"uuid": {
"version": "8.3.1",
"resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.1.tgz",
"integrity": "sha512-FOmRr+FmWEIG8uhZv6C2bTgEVXsHk08kE7mPlrBbEe+c3r9pjceVPgupIfNIhc4yx55H69OXANrUaSuu9eInKg=="
},
"vscode-jsonrpc": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-5.0.1.tgz",
"integrity": "sha512-JvONPptw3GAQGXlVV2utDcHx0BiY34FupW/kI6mZ5x06ER5DdPG/tXWMVHjTNULF5uKPOUUD0SaXg5QaubJL0A=="
},
"vscode-languageserver": {
"version": "6.1.1",
"resolved": "https://registry.npmjs.org/vscode-languageserver/-/vscode-languageserver-6.1.1.tgz",
"integrity": "sha512-DueEpkUAkD5XTR4MLYNr6bQIp/UFR0/IPApgXU3YfCBCB08u2sm9hRCs6DxYZELkk++STPjpcjksR2H8qI3cDQ==",
"requires": {
"vscode-languageserver-protocol": "^3.15.3"
}
},
"vscode-languageserver-protocol": {
"version": "3.15.3",
"resolved": "https://registry.npmjs.org/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.15.3.tgz",
"integrity": "sha512-zrMuwHOAQRhjDSnflWdJG+O2ztMWss8GqUUB8dXLR/FPenwkiBNkMIJJYfSN6sgskvsF0rHAoBowNQfbyZnnvw==",
"requires": {
"vscode-jsonrpc": "^5.0.1",
"vscode-languageserver-types": "3.15.1"
}
},
"vscode-languageserver-textdocument": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/vscode-languageserver-textdocument/-/vscode-languageserver-textdocument-1.0.1.tgz",
"integrity": "sha512-UIcJDjX7IFkck7cSkNNyzIz5FyvpQfY7sdzVy+wkKN/BLaD4DQ0ppXQrKePomCxTS7RrolK1I0pey0bG9eh8dA=="
},
"vscode-languageserver-types": {
"version": "3.15.1",
"resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.15.1.tgz",
"integrity": "sha512-+a9MPUQrNGRrGU630OGbYVQ+11iOIovjCkqxajPa9w57Sd5ruK8WQNsslzpa0x/QJqC8kRc2DUxWjIFwoNm4ZQ=="
},
"wcwidth": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz",
"integrity": "sha1-8LDc+RW8X/FSivrbLA4XtTLaL+g=",
"requires": {
"defaults": "^1.0.3"
}
},
"wrap-ansi": {
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
"integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
"requires": {
"ansi-styles": "^4.0.0",
"string-width": "^4.1.0",
"strip-ansi": "^6.0.0"
},
"dependencies": {
"ansi-styles": {
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
"integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
"requires": {
"color-convert": "^2.0.1"
}
},
"color-convert": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
"requires": {
"color-name": "~1.1.4"
}
},
"color-name": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
}
}
},
"wrappy": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
"integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8="
},
"y18n": {
"version": "5.0.5",
"resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.5.tgz",
"integrity": "sha512-hsRUr4FFrvhhRH12wOdfs38Gy7k2FFzB9qgN9v3aLykRq0dRcdcpz5C9FxdS2NuhOrI/628b/KSTJ3rwHysYSg=="
},
"yargs": {
"version": "16.1.0",
"resolved": "https://registry.npmjs.org/yargs/-/yargs-16.1.0.tgz",
"integrity": "sha512-upWFJOmDdHN0syLuESuvXDmrRcWd1QafJolHskzaw79uZa7/x53gxQKiR07W59GWY1tFhhU/Th9DrtSfpS782g==",
"requires": {
"cliui": "^7.0.2",
"escalade": "^3.1.1",
"get-caller-file": "^2.0.5",
"require-directory": "^2.1.1",
"string-width": "^4.2.0",
"y18n": "^5.0.2",
"yargs-parser": "^20.2.2"
},
"dependencies": {
"yargs-parser": {
"version": "20.2.3",
"resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.3.tgz",
"integrity": "sha512-emOFRT9WVHw03QSvN5qor9QQT9+sw5vwxfYweivSMHTcAXPefwVae2FjO7JJjj8hCE4CzPOPeFM83VwT29HCww=="
}
}
}
}
}

View file

@ -0,0 +1,33 @@
{
"name": "@boltlang/compiler",
"version": "0.0.1",
"description": "A programming language for rapid prototyping",
"main": "index.js",
"scripts": {
"prepare": "tsc || exit 0",
"test": "ava",
"watch": "tsc -w --preserveWatchOutput",
"generate-ast": "tsastgen src/ast-spec.ts:src/ast.ts"
},
"author": "Sam Vervaeck <vervaeck.sam@skynet.be>",
"license": "GPL-3.0",
"repository": "https://github.com/samvv/Bolt",
"devDependencies": {
"@types/fs-extra": "^9.0.4",
"@types/glob": "^7.1.3",
"@types/js-yaml": "^3.12.5",
"@types/microtime": "^2.1.0",
"@types/node": "^14.14.7",
"@types/semver": "^7.3.4",
"@types/uuid": "^8.3.0",
"chalk": "^4.1.0",
"fs-extra": "^9.0.1",
"glob": "^7.1.6",
"js-yaml": "^3.14.0",
"microtime": "^3.0.0",
"moment": "^2.29.1",
"reflect-metadata": "^0.1.13",
"semver": "^7.3.2",
"uuid": "^8.3.1"
}
}

View file

@ -5,7 +5,7 @@ import { Package } from "./package"
import { Diagnostic } from "./diagnostics";
import { serializeTag, inspectTag, indent } from "./util";
import { InspectOptionsStylized, inspect } from "util";
import { Type } from "./checker";
import { Type } from "./checker"
let nextNodeId = 1;
@ -18,6 +18,8 @@ enum NodeFlags {
HasTypeError = 1,
}
declare function isSourceFile(node: Syntax): boolean;
export abstract class Syntax {
public id: number;
@ -26,6 +28,8 @@ export abstract class Syntax {
public errors: Diagnostic[] = [];
public type: Type;
public hasTypeError() {
return (this.flags & NodeFlags.HasTypeError) > 0;
}
@ -34,25 +38,6 @@ export abstract class Syntax {
this.flags |= NodeFlags.HasTypeError;
}
// --------------------------------------------------------------------------------
// NOTE The following properties and methods are only valid when inside a BoltTraitDeclaration
// TODO Move this to BoltTraitDeclaration as soon as tsastgen supports this
private impls?: BoltImplDeclaration[];
public addImplDeclaration(node: BoltImplDeclaration) {
if (this.impls === undefined) {
this.impls = [];
}
this.impls.push(node);
}
public getImplDeclarations(): BoltImplDeclaration[] {
return this.impls ?? [];
}
// --------------------------------------------------------------------------------
public abstract kind: SyntaxKind;
public abstract parentNode: Syntax | null = null;
@ -122,6 +107,17 @@ export abstract class Syntax {
return null;
}
public getSourceFile(): SourceFile {
let currNode: Syntax | null = this;
do {
if (isSourceFile(currNode)) {
return currNode;
}
currNode = currNode.parentNode;
} while (currNode !== null);
throw new Error(`Could not get a source file for node ${this.kind}`);
}
public *findAllChildrenOfKind<K extends SyntaxKind>(kind: K): IterableIterator<ResolveSyntaxKind<K>> {
for (const node of this.preorder()) {
if (!node.mayContainKind(kind)) {
@ -172,7 +168,7 @@ export interface BoltIdentifier extends BoltSymbol {
export interface BoltOperatorLike extends BoltSymbol {}
export interface BoltOperator extends BoltSymbol {
export interface BoltOperator extends BoltOperatorLike, BoltSymbol {
text: string,
}
@ -253,7 +249,7 @@ export interface BoltReferenceTypeExpression extends BoltTypeExpression {
export interface BoltFunctionTypeExpression extends BoltTypeExpression {
params: BoltParameter[],
returnType: BoltTypeExpression | null,
returnTypeExpr: BoltTypeExpression | null,
}
export interface BoltLiftedTypeExpression extends BoltTypeExpression {
@ -335,7 +331,7 @@ export interface BoltMemberExpression extends BoltExpression {
export interface BoltFunctionExpression extends BoltExpression {
params: BoltParameter[],
returnType: BoltTypeExpression | null,
returnTypeExpr: BoltTypeExpression | null,
body: BoltFunctionBodyElement[],
}
@ -359,13 +355,12 @@ export interface BoltMatchExpression extends BoltExpression {
}
export interface BoltCaseStatementCase extends BoltSyntax {
test: BoltExpression,
test: BoltExpression | null,
body: BoltFunctionBodyElement[],
}
export interface BoltCaseStatement extends BoltStatement {
cases: BoltCaseStatementCase[],
alternative: BoltFunctionBodyElement[] | null;
}
export interface BoltBlockExpression extends BoltExpression {
@ -439,7 +434,7 @@ export interface BoltFunctionDeclaration extends BoltFunctionBodyElement, BoltDe
target: string,
name: BoltSymbol,
params: BoltParameter[],
returnType: BoltTypeExpression | null,
returnTypeExpr: BoltTypeExpression | null,
typeParams: BoltTypeParameter[] | null,
body: BoltFunctionBodyElement[] | null,
}

View file

@ -23,30 +23,19 @@ enum NodeFlags {
HasTypeError = 1
}
declare function isSourceFile(node: Syntax): boolean;
export abstract class SyntaxBase {
public id: number;
private flags = NodeFlags.None;
public errors: Diagnostic[] = [];
public type: Type;
public hasTypeError() {
return (this.flags & NodeFlags.HasTypeError) > 0;
}
public markAsHavingTypeError() {
this.flags |= NodeFlags.HasTypeError;
}
// --------------------------------------------------------------------------------
// NOTE The following properties and methods are only valid when inside a BoltTraitDeclaration
// TODO Move this to BoltTraitDeclaration as soon as tsastgen supports this
private impls?: BoltImplDeclaration[];
public addImplDeclaration(node: BoltImplDeclaration) {
if (this.impls === undefined) {
this.impls = [];
}
this.impls.push(node);
}
public getImplDeclarations(): BoltImplDeclaration[] {
return this.impls ?? [];
}
// --------------------------------------------------------------------------------
public abstract kind: SyntaxKind;
public abstract parentNode: Syntax | null = null;
public abstract getChildNodes(): IterableIterator<Syntax>;
@ -107,6 +96,16 @@ export abstract class SyntaxBase {
}
return null;
}
public getSourceFile(): SourceFile {
let currNode: Syntax | null = this;
do {
if (isSourceFile(currNode)) {
return currNode;
}
currNode = currNode.parentNode;
} while (currNode !== null);
throw new Error(`Could not get a source file for node ${this.kind}`);
}
public *findAllChildrenOfKind<K extends SyntaxKind>(kind: K): IterableIterator<ResolveSyntaxKind<K>> {
for (const node of this.preorder()) {
if (!node.mayContainKind(kind)) {
@ -196,7 +195,7 @@ type BoltIdentifierParent = BoltQualName | BoltTypeParameter | BoltBindPattern |
type BoltIdentifierChild = never;
export type BoltOperatorLike = BoltVBar | BoltLtSign | BoltExMark | BoltGtSign;
export type BoltOperatorLike = BoltVBar | BoltLtSign | BoltExMark | BoltGtSign | BoltOperator;
export class BoltOperator extends SyntaxBase {
parentNode: null | BoltOperatorParent = null;
@ -706,10 +705,10 @@ type BoltReferenceTypeExpressionChild = BoltLiftedTypeExpression | BoltFunctionT
export class BoltFunctionTypeExpression extends SyntaxBase {
parentNode: null | BoltFunctionTypeExpressionParent = null;
kind: SyntaxKind.BoltFunctionTypeExpression = SyntaxKind.BoltFunctionTypeExpression;
constructor(public params: BoltParameter[], public returnType: BoltTypeExpression | null, span: TextSpan | null = null) { super(span); }
constructor(public params: BoltParameter[], public returnTypeExpr: BoltTypeExpression | null, span: TextSpan | null = null) { super(span); }
*getChildNodes(): IterableIterator<BoltFunctionTypeExpressionChild> { for (let element of this.params)
yield element; if (this.returnType !== null)
yield this.returnType; }
yield element; if (this.returnTypeExpr !== null)
yield this.returnTypeExpr; }
}
type BoltFunctionTypeExpressionParent = BoltReferenceTypeExpression | BoltFunctionTypeExpression | BoltTypeParameter | BoltTypePattern | BoltRecordPattern | BoltFunctionExpression | BoltParameter | BoltTraitDeclaration | BoltRecordDeclarationField | BoltFunctionDeclaration | BoltVariableDeclaration | BoltTypeAliasDeclaration | never;
@ -900,10 +899,10 @@ type BoltMemberExpressionChild = BoltIdentifier | BoltConstantExpression | BoltB
export class BoltFunctionExpression extends SyntaxBase {
parentNode: null | BoltFunctionExpressionParent = null;
kind: SyntaxKind.BoltFunctionExpression = SyntaxKind.BoltFunctionExpression;
constructor(public params: BoltParameter[], public returnType: BoltTypeExpression | null, public body: BoltFunctionBodyElement[], span: TextSpan | null = null) { super(span); }
constructor(public params: BoltParameter[], public returnTypeExpr: BoltTypeExpression | null, public body: BoltFunctionBodyElement[], span: TextSpan | null = null) { super(span); }
*getChildNodes(): IterableIterator<BoltFunctionExpressionChild> { for (let element of this.params)
yield element; if (this.returnType !== null)
yield this.returnType; for (let element of this.body)
yield element; if (this.returnTypeExpr !== null)
yield this.returnTypeExpr; for (let element of this.body)
yield element; }
}
@ -960,8 +959,9 @@ type BoltMatchExpressionChild = BoltMatchArm | BoltConstantExpression | BoltBloc
export class BoltCaseStatementCase extends SyntaxBase {
parentNode: null | BoltCaseStatementCaseParent = null;
kind: SyntaxKind.BoltCaseStatementCase = SyntaxKind.BoltCaseStatementCase;
constructor(public test: BoltExpression, public body: BoltFunctionBodyElement[], span: TextSpan | null = null) { super(span); }
*getChildNodes(): IterableIterator<BoltCaseStatementCaseChild> { yield this.test; for (let element of this.body)
constructor(public test: BoltExpression | null, public body: BoltFunctionBodyElement[], span: TextSpan | null = null) { super(span); }
*getChildNodes(): IterableIterator<BoltCaseStatementCaseChild> { if (this.test !== null)
yield this.test; for (let element of this.body)
yield element; }
}
@ -972,16 +972,14 @@ type BoltCaseStatementCaseChild = BoltMacroCall | BoltVariableDeclaration | Bolt
export class BoltCaseStatement extends SyntaxBase {
parentNode: null | BoltCaseStatementParent = null;
kind: SyntaxKind.BoltCaseStatement = SyntaxKind.BoltCaseStatement;
constructor(public cases: BoltCaseStatementCase[], public alternative: BoltFunctionBodyElement[] | null, span: TextSpan | null = null) { super(span); }
constructor(public cases: BoltCaseStatementCase[], span: TextSpan | null = null) { super(span); }
*getChildNodes(): IterableIterator<BoltCaseStatementChild> { for (let element of this.cases)
yield element; if (this.alternative !== null)
for (let element of this.alternative)
yield element; }
yield element; }
}
type BoltCaseStatementParent = BoltSourceFile | BoltFunctionExpression | BoltCaseStatementCase | BoltBlockExpression | BoltConditionalCase | BoltCaseStatement | BoltLoopStatement | BoltFunctionDeclaration | BoltModule | never;
type BoltCaseStatementParent = BoltSourceFile | BoltFunctionExpression | BoltCaseStatementCase | BoltBlockExpression | BoltConditionalCase | BoltLoopStatement | BoltFunctionDeclaration | BoltModule | never;
type BoltCaseStatementChild = BoltMacroCall | BoltVariableDeclaration | BoltFunctionDeclaration | BoltLoopStatement | BoltAssignStatement | BoltExpressionStatement | BoltResumeStatement | BoltConditionalStatement | BoltReturnStatement | BoltCaseStatement | BoltCaseStatementCase | never;
type BoltCaseStatementChild = BoltCaseStatementCase | never;
export class BoltBlockExpression extends SyntaxBase {
parentNode: null | BoltBlockExpressionParent = null;
@ -1016,7 +1014,7 @@ export class BoltReturnStatement extends SyntaxBase {
yield this.value; }
}
type BoltReturnStatementParent = BoltSourceFile | BoltFunctionExpression | BoltCaseStatementCase | BoltBlockExpression | BoltConditionalCase | BoltCaseStatement | BoltLoopStatement | BoltFunctionDeclaration | BoltModule | never;
type BoltReturnStatementParent = BoltSourceFile | BoltFunctionExpression | BoltCaseStatementCase | BoltBlockExpression | BoltConditionalCase | BoltLoopStatement | BoltFunctionDeclaration | BoltModule | never;
type BoltReturnStatementChild = BoltConstantExpression | BoltBlockExpression | BoltMatchExpression | BoltYieldExpression | BoltCallExpression | BoltFunctionExpression | BoltMemberExpression | BoltReferenceExpression | BoltTupleExpression | BoltQuoteExpression | BoltRecordExpression | never;
@ -1041,7 +1039,7 @@ export class BoltConditionalStatement extends SyntaxBase {
yield element; }
}
type BoltConditionalStatementParent = BoltSourceFile | BoltFunctionExpression | BoltCaseStatementCase | BoltBlockExpression | BoltConditionalCase | BoltCaseStatement | BoltLoopStatement | BoltFunctionDeclaration | BoltModule | never;
type BoltConditionalStatementParent = BoltSourceFile | BoltFunctionExpression | BoltCaseStatementCase | BoltBlockExpression | BoltConditionalCase | BoltLoopStatement | BoltFunctionDeclaration | BoltModule | never;
type BoltConditionalStatementChild = BoltConditionalCase | never;
@ -1052,7 +1050,7 @@ export class BoltResumeStatement extends SyntaxBase {
*getChildNodes(): IterableIterator<BoltResumeStatementChild> { yield this.value; }
}
type BoltResumeStatementParent = BoltSourceFile | BoltFunctionExpression | BoltCaseStatementCase | BoltBlockExpression | BoltConditionalCase | BoltCaseStatement | BoltLoopStatement | BoltFunctionDeclaration | BoltModule | never;
type BoltResumeStatementParent = BoltSourceFile | BoltFunctionExpression | BoltCaseStatementCase | BoltBlockExpression | BoltConditionalCase | BoltLoopStatement | BoltFunctionDeclaration | BoltModule | never;
type BoltResumeStatementChild = BoltConstantExpression | BoltBlockExpression | BoltMatchExpression | BoltYieldExpression | BoltCallExpression | BoltFunctionExpression | BoltMemberExpression | BoltReferenceExpression | BoltTupleExpression | BoltQuoteExpression | BoltRecordExpression | never;
@ -1063,7 +1061,7 @@ export class BoltExpressionStatement extends SyntaxBase {
*getChildNodes(): IterableIterator<BoltExpressionStatementChild> { yield this.expression; }
}
type BoltExpressionStatementParent = BoltSourceFile | BoltFunctionExpression | BoltCaseStatementCase | BoltBlockExpression | BoltConditionalCase | BoltCaseStatement | BoltLoopStatement | BoltFunctionDeclaration | BoltModule | never;
type BoltExpressionStatementParent = BoltSourceFile | BoltFunctionExpression | BoltCaseStatementCase | BoltBlockExpression | BoltConditionalCase | BoltLoopStatement | BoltFunctionDeclaration | BoltModule | never;
type BoltExpressionStatementChild = BoltConstantExpression | BoltBlockExpression | BoltMatchExpression | BoltYieldExpression | BoltCallExpression | BoltFunctionExpression | BoltMemberExpression | BoltReferenceExpression | BoltTupleExpression | BoltQuoteExpression | BoltRecordExpression | never;
@ -1074,7 +1072,7 @@ export class BoltAssignStatement extends SyntaxBase {
*getChildNodes(): IterableIterator<BoltAssignStatementChild> { yield this.lhs; yield this.rhs; }
}
type BoltAssignStatementParent = BoltSourceFile | BoltFunctionExpression | BoltCaseStatementCase | BoltBlockExpression | BoltConditionalCase | BoltCaseStatement | BoltLoopStatement | BoltFunctionDeclaration | BoltModule | never;
type BoltAssignStatementParent = BoltSourceFile | BoltFunctionExpression | BoltCaseStatementCase | BoltBlockExpression | BoltConditionalCase | BoltLoopStatement | BoltFunctionDeclaration | BoltModule | never;
type BoltAssignStatementChild = BoltConstantExpression | BoltBlockExpression | BoltMatchExpression | BoltYieldExpression | BoltCallExpression | BoltFunctionExpression | BoltMemberExpression | BoltReferenceExpression | BoltTupleExpression | BoltQuoteExpression | BoltRecordExpression | BoltRecordPattern | BoltTuplePattern | BoltExpressionPattern | BoltTypePattern | BoltBindPattern | never;
@ -1086,7 +1084,7 @@ export class BoltLoopStatement extends SyntaxBase {
yield element; }
}
type BoltLoopStatementParent = BoltSourceFile | BoltFunctionExpression | BoltCaseStatementCase | BoltBlockExpression | BoltConditionalCase | BoltCaseStatement | BoltLoopStatement | BoltFunctionDeclaration | BoltModule | never;
type BoltLoopStatementParent = BoltSourceFile | BoltFunctionExpression | BoltCaseStatementCase | BoltBlockExpression | BoltConditionalCase | BoltLoopStatement | BoltFunctionDeclaration | BoltModule | never;
type BoltLoopStatementChild = BoltMacroCall | BoltVariableDeclaration | BoltFunctionDeclaration | BoltLoopStatement | BoltAssignStatement | BoltExpressionStatement | BoltResumeStatement | BoltConditionalStatement | BoltReturnStatement | BoltCaseStatement | never;
@ -1127,17 +1125,17 @@ export type BoltFunctionBodyElement = BoltMacroCall | BoltVariableDeclaration |
export class BoltFunctionDeclaration extends SyntaxBase {
parentNode: null | BoltFunctionDeclarationParent = null;
kind: SyntaxKind.BoltFunctionDeclaration = SyntaxKind.BoltFunctionDeclaration;
constructor(public modifiers: BoltModifiers, public target: string, public name: BoltSymbol, public params: BoltParameter[], public returnType: BoltTypeExpression | null, public typeParams: BoltTypeParameter[] | null, public body: BoltFunctionBodyElement[] | null, span: TextSpan | null = null) { super(span); }
constructor(public modifiers: BoltModifiers, public target: string, public name: BoltSymbol, public params: BoltParameter[], public returnTypeExpr: BoltTypeExpression | null, public typeParams: BoltTypeParameter[] | null, public body: BoltFunctionBodyElement[] | null, span: TextSpan | null = null) { super(span); }
*getChildNodes(): IterableIterator<BoltFunctionDeclarationChild> { yield this.name; for (let element of this.params)
yield element; if (this.returnType !== null)
yield this.returnType; if (this.typeParams !== null)
yield element; if (this.returnTypeExpr !== null)
yield this.returnTypeExpr; if (this.typeParams !== null)
for (let element of this.typeParams)
yield element; if (this.body !== null)
for (let element of this.body)
yield element; }
}
type BoltFunctionDeclarationParent = BoltSourceFile | BoltFunctionExpression | BoltCaseStatementCase | BoltBlockExpression | BoltConditionalCase | BoltTraitDeclaration | BoltImplDeclaration | BoltCaseStatement | BoltLoopStatement | BoltFunctionDeclaration | BoltModule | never;
type BoltFunctionDeclarationParent = BoltSourceFile | BoltFunctionExpression | BoltCaseStatementCase | BoltBlockExpression | BoltConditionalCase | BoltTraitDeclaration | BoltImplDeclaration | BoltLoopStatement | BoltFunctionDeclaration | BoltModule | never;
type BoltFunctionDeclarationChild = BoltMacroCall | BoltVariableDeclaration | BoltFunctionDeclaration | BoltLoopStatement | BoltAssignStatement | BoltExpressionStatement | BoltResumeStatement | BoltConditionalStatement | BoltReturnStatement | BoltCaseStatement | BoltTypeParameter | BoltLiftedTypeExpression | BoltFunctionTypeExpression | BoltReferenceTypeExpression | BoltTypeOfExpression | BoltParameter | BoltOperator | BoltVBar | BoltLtSign | BoltExMark | BoltGtSign | BoltIdentifier | never;
@ -1150,7 +1148,7 @@ export class BoltVariableDeclaration extends SyntaxBase {
yield this.value; }
}
type BoltVariableDeclarationParent = BoltSourceFile | BoltFunctionExpression | BoltCaseStatementCase | BoltBlockExpression | BoltConditionalCase | BoltCaseStatement | BoltLoopStatement | BoltFunctionDeclaration | BoltModule | never;
type BoltVariableDeclarationParent = BoltSourceFile | BoltFunctionExpression | BoltCaseStatementCase | BoltBlockExpression | BoltConditionalCase | BoltLoopStatement | BoltFunctionDeclaration | BoltModule | never;
type BoltVariableDeclarationChild = BoltConstantExpression | BoltBlockExpression | BoltMatchExpression | BoltYieldExpression | BoltCallExpression | BoltFunctionExpression | BoltMemberExpression | BoltReferenceExpression | BoltTupleExpression | BoltQuoteExpression | BoltRecordExpression | BoltLiftedTypeExpression | BoltFunctionTypeExpression | BoltReferenceTypeExpression | BoltTypeOfExpression | BoltRecordPattern | BoltTuplePattern | BoltExpressionPattern | BoltTypePattern | BoltBindPattern | never;
@ -1288,7 +1286,7 @@ export class BoltMacroCall extends SyntaxBase {
*getChildNodes(): IterableIterator<BoltMacroCallChild> { yield this.name; }
}
type BoltMacroCallParent = BoltSourceFile | BoltFunctionExpression | BoltCaseStatementCase | BoltBlockExpression | BoltConditionalCase | BoltTraitDeclaration | BoltImplDeclaration | BoltCaseStatement | BoltLoopStatement | BoltFunctionDeclaration | BoltRecordDeclaration | BoltModule | never;
type BoltMacroCallParent = BoltSourceFile | BoltFunctionExpression | BoltCaseStatementCase | BoltBlockExpression | BoltConditionalCase | BoltTraitDeclaration | BoltImplDeclaration | BoltLoopStatement | BoltFunctionDeclaration | BoltRecordDeclaration | BoltModule | never;
type BoltMacroCallChild = BoltIdentifier | never;
@ -2124,7 +2122,7 @@ export function createBoltTypeOfExpression(expression: BoltExpression, span: Tex
export function createBoltReferenceTypeExpression(name: BoltQualName, typeArgs: BoltTypeExpression[] | null, span: TextSpan | null = null): BoltReferenceTypeExpression { return new BoltReferenceTypeExpression(name, typeArgs, span); }
export function createBoltFunctionTypeExpression(params: BoltParameter[], returnType: BoltTypeExpression | null, span: TextSpan | null = null): BoltFunctionTypeExpression { return new BoltFunctionTypeExpression(params, returnType, span); }
export function createBoltFunctionTypeExpression(params: BoltParameter[], returnTypeExpr: BoltTypeExpression | null, span: TextSpan | null = null): BoltFunctionTypeExpression { return new BoltFunctionTypeExpression(params, returnTypeExpr, span); }
export function createBoltLiftedTypeExpression(expression: BoltExpression, span: TextSpan | null = null): BoltLiftedTypeExpression { return new BoltLiftedTypeExpression(expression, span); }
@ -2156,7 +2154,7 @@ export function createBoltReferenceExpression(name: BoltQualName, span: TextSpan
export function createBoltMemberExpression(expression: BoltExpression, path: BoltIdentifier[], span: TextSpan | null = null): BoltMemberExpression { return new BoltMemberExpression(expression, path, span); }
export function createBoltFunctionExpression(params: BoltParameter[], returnType: BoltTypeExpression | null, body: BoltFunctionBodyElement[], span: TextSpan | null = null): BoltFunctionExpression { return new BoltFunctionExpression(params, returnType, body, span); }
export function createBoltFunctionExpression(params: BoltParameter[], returnTypeExpr: BoltTypeExpression | null, body: BoltFunctionBodyElement[], span: TextSpan | null = null): BoltFunctionExpression { return new BoltFunctionExpression(params, returnTypeExpr, body, span); }
export function createBoltCallExpression(operator: BoltExpression, operands: BoltExpression[], span: TextSpan | null = null): BoltCallExpression { return new BoltCallExpression(operator, operands, span); }
@ -2166,9 +2164,9 @@ export function createBoltMatchArm(pattern: BoltPattern, body: BoltExpression, s
export function createBoltMatchExpression(value: BoltExpression, arms: BoltMatchArm[], span: TextSpan | null = null): BoltMatchExpression { return new BoltMatchExpression(value, arms, span); }
export function createBoltCaseStatementCase(test: BoltExpression, body: BoltFunctionBodyElement[], span: TextSpan | null = null): BoltCaseStatementCase { return new BoltCaseStatementCase(test, body, span); }
export function createBoltCaseStatementCase(test: BoltExpression | null, body: BoltFunctionBodyElement[], span: TextSpan | null = null): BoltCaseStatementCase { return new BoltCaseStatementCase(test, body, span); }
export function createBoltCaseStatement(cases: BoltCaseStatementCase[], alternative: BoltFunctionBodyElement[] | null, span: TextSpan | null = null): BoltCaseStatement { return new BoltCaseStatement(cases, alternative, span); }
export function createBoltCaseStatement(cases: BoltCaseStatementCase[], span: TextSpan | null = null): BoltCaseStatement { return new BoltCaseStatement(cases, span); }
export function createBoltBlockExpression(elements: BoltFunctionBodyElement[], span: TextSpan | null = null): BoltBlockExpression { return new BoltBlockExpression(elements, span); }
@ -2192,7 +2190,7 @@ export function createBoltParameter(index: number, bindings: BoltPattern, typeEx
export function createBoltModule(modifiers: BoltModifiers, name: BoltIdentifier[], elements: BoltSourceElement[], span: TextSpan | null = null): BoltModule { return new BoltModule(modifiers, name, elements, span); }
export function createBoltFunctionDeclaration(modifiers: BoltModifiers, target: string, name: BoltSymbol, params: BoltParameter[], returnType: BoltTypeExpression | null, typeParams: BoltTypeParameter[] | null, body: BoltFunctionBodyElement[] | null, span: TextSpan | null = null): BoltFunctionDeclaration { return new BoltFunctionDeclaration(modifiers, target, name, params, returnType, typeParams, body, span); }
export function createBoltFunctionDeclaration(modifiers: BoltModifiers, target: string, name: BoltSymbol, params: BoltParameter[], returnTypeExpr: BoltTypeExpression | null, typeParams: BoltTypeParameter[] | null, body: BoltFunctionBodyElement[] | null, span: TextSpan | null = null): BoltFunctionDeclaration { return new BoltFunctionDeclaration(modifiers, target, name, params, returnTypeExpr, typeParams, body, span); }
export function createBoltVariableDeclaration(modifiers: BoltModifiers, bindings: BoltPattern, typeExpr: BoltTypeExpression | null, value: BoltExpression | null, span: TextSpan | null = null): BoltVariableDeclaration { return new BoltVariableDeclaration(modifiers, bindings, typeExpr, value, span); }
@ -2364,7 +2362,7 @@ export function isBoltSymbol(value: any): value is BoltSymbol { return value.kin
export function isBoltIdentifier(value: any): value is BoltIdentifier { return value.kind === SyntaxKind.BoltIdentifier; }
export function isBoltOperatorLike(value: any): value is BoltOperatorLike { return value.kind === SyntaxKind.BoltVBar || value.kind === SyntaxKind.BoltLtSign || value.kind === SyntaxKind.BoltExMark || value.kind === SyntaxKind.BoltGtSign; }
export function isBoltOperatorLike(value: any): value is BoltOperatorLike { return value.kind === SyntaxKind.BoltVBar || value.kind === SyntaxKind.BoltLtSign || value.kind === SyntaxKind.BoltExMark || value.kind === SyntaxKind.BoltGtSign || value.kind === SyntaxKind.BoltOperator; }
export function isBoltOperator(value: any): value is BoltOperator { return value.kind === SyntaxKind.BoltOperator; }
@ -3218,7 +3216,7 @@ export class Visitor {
protected visitBoltSymbol(node: BoltSymbol): void { this.visitBoltToken(node); }
protected visitBoltIdentifier(node: BoltIdentifier): void { this.visitBoltSymbol(node); }
protected visitBoltOperatorLike(node: BoltOperatorLike): void { this.visitBoltSymbol(node); }
protected visitBoltOperator(node: BoltOperator): void { this.visitBoltSymbol(node); }
protected visitBoltOperator(node: BoltOperator): void { this.visitBoltOperatorLike(node); this.visitBoltSymbol(node); }
protected visitBoltAssignment(node: BoltAssignment): void { this.visitBoltToken(node); }
protected visitBoltComma(node: BoltComma): void { this.visitBoltToken(node); }
protected visitBoltSemi(node: BoltSemi): void { this.visitBoltToken(node); }

View file

@ -0,0 +1,306 @@
import { BoltLiftedTypeExpression, SourceFile, Syntax, SyntaxKind } from "./ast";
import { FastStringMap } from "./util";
enum TypeKind {
TypeVar,
PrimType,
ForallType,
ArrowType,
}
type Type
= TypeVar
| PrimType
| ForallType
| ArrowType
interface TypeBase {
kind: TypeKind;
}
interface TypeVar extends TypeBase {
kind: TypeKind.TypeVar;
varId: string;
}
interface PrimType extends TypeBase {
kind: TypeKind.PrimType;
primId: number;
name: string;
}
class TypeVarSubstitution {
private mapping = new FastStringMap<string, Type>()
public add(source: TypeVar, target: Type) {
this.mapping.set(source.varId, target);
}
public assign(other: TypeVarSubstitution): void {
for (const [name, type] of other.mapping) {
this.mapping.overwrite(name, type);
}
}
}
interface ForallType extends TypeBase {
kind: TypeKind.ForallType;
typeVars: TypeVarSubstitution;
type: Type;
}
interface ArrowType extends TypeBase {
kind: TypeKind.ArrowType;
paramTypes: Type[];
returnType: Type;
}
type Constraint = [Type, Type]
class TypeEnv {
private mapping = new FastStringMap<string, Type>();
public set(name: string, scheme: Type) {
this.mapping.set(name, scheme)
}
public remove(name: string): void {
this.mapping.delete(name)
}
public lookup(name: string): Type | null {
if (!this.mapping.has(name)) {
return null;
}
return this.mapping.get(name)
}
public has(typeVar: TypeVar): boolean {
return this.mapping.has(typeVar.varId)
}
}
export class TypeChecker {
private nextVarId = 1;
private nextPrimTypeId = 1;
private intType = this.createPrimType('int');
private stringType = this.createPrimType('String');
public isIntType(type: Type) {
return type === this.intType;
}
public isStringType(type: Type) {
return type === this.stringType;
}
private builtinTypes = new FastStringMap([
['int', this.intType],
['String', this.stringType]
]);
private createTypeVar(): TypeVar {
return { kind: TypeKind.TypeVar, varId: (this.nextVarId++).toString() }
}
private createPrimType(name: string): PrimType {
return { kind: TypeKind.PrimType, name, primId: this.nextPrimTypeId++ }
}
private createArrowType(paramTypes: Type[], returnType: Type): ArrowType {
return { kind: TypeKind.ArrowType, paramTypes, returnType }
}
private createForallType(typeVars: FastStringMap<string, TypeVar>, type: Type): ForallType {
return { kind: TypeKind.ForallType, typeVars, type }
}
public registerSourceFile(sourceFile: SourceFile): void {
}
private addFreeVariables(type: Type, freeVariables: Set<string>, excludedVariables: Set<string>) {
switch (type.kind) {
case TypeKind.PrimType:
break;
case TypeKind.TypeVar:
if (!excludedVariables.has(type.varId)) {
freeVariables.add(type.varId);
}
break;
case TypeKind.ArrowType:
for (const paramType of type.paramTypes) {
this.addFreeVariables(paramType, freeVariables, excludedVariables);
}
this.addFreeVariables(type.returnType, freeVariables, excludedVariables);
break;
case TypeKind.ForallType:
const newExcludedVariables = new Set(excludedVariables);
for (const typeVar of type.typeVars.values()) {
newExcludedVariables.add(typeVar.varId);
}
this.addFreeVariables(type.type, freeVariables, newExcludedVariables)
break;
default:
throw new Error(`Could not determine the free variables in an unknown type`)
}
}
private applySubstitution(type: Type, substitution: TypeVarSubstitution): Type {
switch (type.kind) {
case TypeKind.PrimType:
return type;
case TypeKind.TypeVar:
if (substitution.has(type.varId)) {
return substitution.get(type.varId)
} else {
return type;
}
case TypeKind.ArrowType:
return this.createArrowType(
type.paramTypes.map(t => this.applySubstitution(t, substitution)),
this.applySubstitution(type.returnType, substitution)
)
case TypeKind.ForallType:
const newSubstitution = new TypeVarSubstitution();
for (const [name, mappedType] of substitution) {
if (!type.typeVars.has(name)) {
newSubstitution.set(name, mappedType);
}
}
return this.createForallType(type.typeVars, this.applySubstitution(type.type, newSubstitution));
default:
throw new Error(`Could not substitute unrecognosed type`);
}
}
private applySubstitutionToConstraints(constraints: Constraint[], substitution: TypeVarSubstitution): void {
for (let i = 0; i < constraints.length; i++) {
constraints[i][0] = this.applySubstitution(constraints[i][0], substitution)
constraints[i][1] = this.applySubstitution(constraints[i][1], substitution)
}
}
private inferNode(node: Syntax, env: TypeEnv) {
switch (node.kind) {
case SyntaxKind.BoltConstantExpression:
{
if (typeof(node.value) === 'bigint') {
return this.intType;
} else if (typeof(node.value === 'string')) {
return this.stringType;
}
}
case SyntaxKind.BoltReferenceExpression:
{
return this.createTypeVar()
}
case SyntaxKind.BoltCallExpression:
{
const operatorType = this.createTypeVar()
const operandTypes = node.operands.map(this.createTypeVar.bind(this))
return this.createArrowType(operandTypes, operatorType);
}
}
}
public checkNode(node: Syntax): void {
}
private solveConstraints(constraints: Constraint[]) {
let substitution = new TypeVarSubstitution();
while (true) {
if (constraints.length === 0) {
return substitution
}
const [a, b] = constraints.pop()!;
const newSubstitution = this.unify(a, b);
substitution.assign(newSubstitution);
this.applySubstitutionToConstraints(constraints, newSubstitution);
}
}
private areTypesEqual(a: Type, b: Type): boolean {
if (a === b) {
return true;
}
if (a.kind !== b.kind) {
return false;
}
if (a.kind === TypeKind.PrimType && b.kind === TypeKind.PrimType) {
return a.primId === b.primId;
}
if (a.kind === TypeKind.ArrowType && b.kind === TypeKind.ArrowType) {
if (a.paramTypes.length !== b.paramTypes.length
|| !this.areTypesEqual(a.returnType, b.returnType)) {
return false;
}
for (let i = 0; i < a.paramTypes.length; i++) {
if (!this.areTypesEqual(a.paramTypes[i], b.paramTypes[i])) {
return false;
}
}
return true;
}
if (a.kind === TypeKind.TypeVar && b.kind === TypeKind.TypeVar) {
return a.varId === b.varId;
}
throw new Error(`Unexpected combination of types while checking equality`)
}
private unify(a: Type, b: Type): TypeVarSubstitution {
if (this.areTypesEqual(a, b)) {
return new TypeVarSubstitution();
}
if (a.kind === TypeKind.TypeVar) {
const substitution = new TypeVarSubstitution();
substitution.add(a, b);
return substitution
}
if (b.kind === TypeKind.TypeVar) {
const substitution = new TypeVarSubstitution();
substitution.add(b, a);
return substitution
}
throw new Error(`Types ${a} and ${b} could not be unified`)
}
public getTypeOfNode(node: Syntax, env: TypeEnv): unknown {
return this.inferNode(node, env);
}
public isBuiltinType(name: string) {
return this.builtinTypes.has(name);
}
}

View file

@ -6,6 +6,8 @@ import { inject } from "./ioc";
import { SymbolResolver, ScopeType } from "./resolver";
import { assert, every } from "./util";
import { emitNode } from "./emitter";
import { TypeChecker } from "./checker";
import { getSymbolText } from "./common";
export class CheckInvalidFilePaths extends Visitor {
@ -34,7 +36,8 @@ export class CheckReferences extends Visitor {
constructor(
@inject private diagnostics: DiagnosticPrinter,
@inject private resolver: SymbolResolver
@inject private resolver: SymbolResolver,
@inject private checker: TypeChecker
) {
super();
}
@ -112,6 +115,10 @@ export class CheckReferences extends Visitor {
}
protected visitBoltReferenceTypeExpression(node: BoltReferenceTypeExpression) {
const name = getSymbolText(node.name.name);
if (node.name.modulePath.length === 0 && this.checker.isBuiltinType(name)) {
return;
}
const scope = this.resolver.getScopeSurroundingNode(node, ScopeType.Type);
assert(scope !== null);
const symbolPath = convertNodeToSymbolPath(node.name);

View file

@ -3,22 +3,20 @@ import {
BoltReturnStatement,
SyntaxKind,
BoltExpression,
BoltQualName,
kindToString,
Syntax,
Token,
isBoltPunctuated,
SourceFile,
BoltSourceFile,
isSourceFile,
BoltSyntax,
BoltModifiers,
ReturnStatement,
FunctionBodyElement,
BoltToken
BoltToken,
BoltSymbol
} from "./ast";
import { BOLT_SUPPORTED_LANGUAGES } from "./constants"
import { FastStringMap, enumOr, escapeChar, assert, registerClass, Newable, GeneratorStream, FastMultiMap } from "./util";
import { enumOr, escapeChar, assert, registerClass, GeneratorStream, FastMultiMap } from "./util";
import { TextSpan, TextPos, TextFile } from "./text";
import { Scanner } from "./scanner";
import { convertNodeToSymbolPath, SymbolPath } from "./resolver";
@ -55,23 +53,33 @@ export function getNodeLanguage(node: Syntax): string {
throw new Error(`Could not determine the language of ${kindStr}`);
}
export function createTokenStream(node: Syntax) {
if (isBoltPunctuated(node)) {
const origPos = node.span!.start;
export function createTokenStream(value: any) {
if (value instanceof Scanner) {
return new GeneratorStream<BoltToken>(() => value.scan());
} else if (typeof(value) === 'string') {
const scanner = new Scanner(new TextFile('#<anonymous>'), value);
return new GeneratorStream<BoltToken>(() => scanner.scan());
} else if (isBoltPunctuated(value)) {
const origPos = value.span!.start;
const startPos = new TextPos(origPos.offset+1, origPos.line, origPos.column+1);
const scanner = new Scanner(node.span!.file, node.text, startPos);
const scanner = new Scanner(value.span!.file, value.text, startPos);
return new GeneratorStream<BoltToken>(() => scanner.scan());
} else {
throw new Error(`Could not convert ${kindToString(node.kind)} to a token stream.`);
throw new Error(`Could not convert ${kindToString(value.kind)} to a token stream.`);
}
}
export const EOF = ''
export class ScanError extends Error {
public errorText: string;
constructor(public file: TextFile, public position: TextPos, public char: string) {
super(`${file.origPath}:${position.line}:${position.column}: unexpected char '${escapeChar(char)}'`)
super(`${file.origPath}:${position.line}:${position.column}: unexpected character '${escapeChar(char)}'`)
this.errorText = `Unexpected character '${escapeChar(char)}'`
}
}
export function cloneSpan(span: TextSpan | null) {
@ -143,15 +151,39 @@ export function isRightAssoc(kind: OperatorKind) {
}
export class ParseError extends Error {
public errorText: string;
constructor(public actual: Syntax, public expected: SyntaxKind[]) {
super(`${actual.span!.file.origPath}:${actual.span!.start.line}:${actual.span!.start.column}: expected ${enumOr(expected.map(e => describeKind(e)))} but got ${describeKind(actual.kind)}`);
this.errorText = `Expected ${enumOr(expected.map(e => describeKind(e)))} but got ${describeKind(actual.kind)}`
}
}
export class HardParseError extends ParseError {
}
export function getSymbolText(node: BoltSymbol): string {
switch (node.kind) {
case SyntaxKind.BoltIdentifier:
return node.text;
case SyntaxKind.BoltOperator:
return node.text;
case SyntaxKind.BoltGtSign:
return '>';
case SyntaxKind.BoltExMark:
return '!';
case SyntaxKind.BoltLtSign:
return '<';
case SyntaxKind.BoltVBar:
return '|';
default:
throw new Error(`Could not convert the node ${kindToString(node.kind)} to the name of an operator`);
}
}
export interface OperatorInfo {
kind: OperatorKind;
arity: number;
@ -195,6 +227,7 @@ export class OperatorTable {
return operatorInfo;
}
}
return null;
}
}
@ -400,16 +433,19 @@ export function describeKind(kind: SyntaxKind): string {
return "'if'";
case SyntaxKind.BoltElseKeyword:
return "'else'";
case SyntaxKind.BoltTypeAliasDeclaration:
return "a type alias";
case SyntaxKind.BoltMacroCall:
return "a macro call";
default:
throw new Error(`failed to describe ${kindToString(kind)}`)
}
}
export function *getAllReturnStatementsInFunctionBody(body: FunctionBodyElement[]): IterableIterator<ReturnStatement> {
export function *getAllReturnStatementsInFunctionBody(body: FunctionBodyElement[]): IterableIterator<BoltReturnStatement> {
for (const element of body) {
switch (element.kind) {
case SyntaxKind.BoltReturnStatement:
case SyntaxKind.JSReturnStatement:
{
yield element;
break;
@ -419,9 +455,7 @@ export function *getAllReturnStatementsInFunctionBody(body: FunctionBodyElement[
for (const caseNode of element.cases) {
yield* getAllReturnStatementsInFunctionBody(caseNode.body);
}
if (element.alternative !== null) {
yield* getAllReturnStatementsInFunctionBody(element.alternative);
}
break;
}
case SyntaxKind.BoltConditionalStatement:
{

View file

@ -0,0 +1,746 @@
import { BoltCallExpression, BoltExpression, BoltFunctionDeclaration, BoltFunctionExpression, BoltIdentifier, BoltPattern, BoltTypeExpression, isBoltFunctionDeclaration, isBoltRecordDeclaration, isBoltTypeAliasDeclaration, isBoltVariableDeclaration, kindToString, SourceFile, Syntax, SyntaxKind } from "./ast";
import { getAllReturnStatementsInFunctionBody, getSymbolText } from "./common";
import { DiagnosticPrinter, E_TOO_FEW_ARGUMENTS_FOR_FUNCTION_CALL, E_TOO_MANY_ARGUMENTS_FOR_FUNCTION_CALL, E_TYPE_MISMATCH } from "./diagnostics";
import { Value } from "./evaluator";
import { convertNodeToSymbolPath, ScopeType, SymbolResolver } from "./resolver";
import { assert, FastStringMap, MapLike, prettyPrintTag } from "./util";
class NodeWithContext<N = Syntax> {
constructor(
public node: N,
public context: CFGNode,
) {
}
}
class Environment {
private boundVariables = new FastStringMap<string, NodeWithContext>();
constructor(public parentEnv: Environment | null = null) {
}
public set(name: string, node: NodeWithContext): void {
this.boundVariables.set(name, node);
}
public lookup(name: string) {
let currEnv: Environment | null = this;
do {
if (currEnv.boundVariables.has(name)){
return currEnv.boundVariables.get(name);
}
currEnv = currEnv.parentEnv;
} while (currEnv !== null);
throw new Error(`Could not find '${name}' in this environment or any of its parents`);
}
}
enum TypeKind {
Prim,
}
type Type
= PrimType
class PrimType {
public kind: TypeKind.Prim = TypeKind.Prim;
constructor(public name: string) {
}
[prettyPrintTag]() {
return this.name;
}
}
type Condition
= ExprCondition
| NotCondition
| InContextCondition
| AlwaysTrueCondition
class ExprCondition {
constructor(public expression: BoltExpression) {
}
}
class NotCondition {
constructor(public conditionToNegate: Condition) {
}
}
class AlwaysTrueCondition {
}
class ConditionGroup {
private conditions: Condition[] = [];
public addCondition(condition: Condition): void {
this.conditions.push(condition);
}
public getAllConditions(): Iterable<Condition> {
return this.conditions;
}
public removeCondition(condition: Condition): void {
for (let i = 0; i < this.conditions.length; i++) {
if (condition === this.conditions[i]) {
this.conditions.splice(i, 1);
break;
}
}
}
public isEmpty(): boolean {
return this.conditions.length === 0;
}
}
class InContextCondition {
constructor(public node: CFGNode) {
}
}
class HasValueAssertion {
constructor(public value: Value) {
}
}
type Assertion
= HasValueAssertion
| ConditionalAssertion
| NegatedAssertion
class NegatedAssertion {
constructor(public propertyToNegate: Assertion) {
}
}
class ConditionalAssertion {
constructor(
public condition: ConditionGroup,
public assertion: Assertion,
) {
}
}
class PropertyGroup {
private properties: Assertion[] = []
// public addCondition(condition: Condition): void {
// this.assumptions.push(condition);
// }
public addProperty(property: Assertion) {
this.properties.push(property);
}
public getAllProperties(): Iterable<Assertion> {
return this.properties[Symbol.iterator]();
}
[Symbol.iterator]() {
return this.properties[Symbol.iterator]();
}
}
export type NodeProperties = FastStringMap<number, PropertyGroup>;
class CFGNode {
constructor(
public id: number,
public sourceNode: Syntax,
public prevNode: CFGNode | null = null,
) {
}
// public addPropertyToNode(node: Syntax, property: Property) {
// if (!this.properties.has(node.id)) {
// this.properties.set(node.id, new PropertyGroup);
// }
// this.properties.get(node.id).addProperty(property);
// }
// public getPropertiesOfNode(node: Syntax): PropertyGroup {
// if (!this.properties.has(node.id)) {
// this.properties.set(node.id, new PropertyGroup);
// }
// return this.properties.get(node.id);
// }
public isStaticContext() {
let currContext: CFGNode | null = this;
do {
if (currContext.assumptions.length > 0) {
return false;
}
currContext = currContext.prevNode;
} while (currContext !== null);
return true;
}
}
const BUILTIN_TYPES = [
'String',
'int',
'f32',
'f64',
'bool'
]
const BUILTIN_OPERATORS: MapLike<Function> = {
'=='(lhs: number, rhs: number) {
return lhs === rhs;
}
}
function hasBuiltinOperator(name: string) {
return BUILTIN_OPERATORS[name] !== undefined;
}
function getBuiltinOperator(name: string) {
assert(BUILTIN_OPERATORS[name] !== undefined);
return BUILTIN_OPERATORS[name];
}
export class TypeChecker {
private nextSimulationContextId = 1;
private contextById = new FastStringMap<number, CFGNode>();
constructor(private resolver: SymbolResolver, private diagnostics: DiagnosticPrinter) {
}
private getContextById(id: number): CFGNode {
return this.contextById.get(id);
}
public registerSourceFile(sourceFile: SourceFile) {
}
public checkNode(node: Syntax) {
switch (node.kind) {
case SyntaxKind.BoltSourceFile:
const env = new Environment();
let context = this.createCFGNode(node);
for (const element of node.elements) {
context = this.simulateEvaluation(element, context, env);
}
this.checkTypeAssertions(node);
break;
default:
throw new Error(`Could not check node of kind ${kindToString(node.kind)}`)
}
}
private *getStaticPropertiesOfNode(node: Syntax): Iterable<Assertion> {
for (const [context, property] of this.getAllPropertiesOfNode(node)) {
yield property;
}
}
private inferTypeFromStaticProperties(node: Syntax): Type {
for (const property of this.getStaticPropertiesOfNode(node)) {
if (property instanceof HasValueAssertion) {
if (typeof(property.value) === 'bigint') {
return new PrimType('int');
} else if (typeof(property.value) === 'string') {
return new PrimType('String');
} else {
throw new Error(`Could not infer the type of an unknown value.`);
}
}
}
throw new Error(`Could not deduce the type of ${kindToString(node.kind)} because not enough properties were available.`);
}
private isTypeAssignableTo(sourceType: Type, targetType: Type) {
if (sourceType.kind === TypeKind.Prim && targetType.kind === TypeKind.Prim) {
return sourceType.name === targetType.name;
}
throw new Error(`Could not deduce whether unknown types ${sourceType} and ${targetType} are assignable.`);
}
private checkTypeAssignment(value: BoltExpression, typeExpr: BoltTypeExpression) {
switch (typeExpr.kind) {
case SyntaxKind.BoltReferenceTypeExpression:
{
if (typeExpr.name.isAbsolute === false
&& typeExpr.name.modulePath.length === 0
&& BUILTIN_TYPES.indexOf((typeExpr.name.name as BoltIdentifier).text) !== -1) {
const valueType = this.inferTypeFromStaticProperties(value);
const typeExprType = new PrimType((typeExpr.name.name as BoltIdentifier).text);
if (!this.isTypeAssignableTo(valueType, typeExprType)) {
this.diagnostics.add({
node: value,
message: E_TYPE_MISMATCH,
severity: 'error',
args: {
left: typeExprType,
right: valueType,
}
});
}
break;
}
const scope = this.resolver.getScopeForNode(typeExpr, ScopeType.Type);
assert(scope !== null);
const resolvedSymbol = this.resolver.resolveSymbolPath(convertNodeToSymbolPath(typeExpr), scope!);
if (resolvedSymbol === null) {
// TODO add diagnostic
break;
}
for (const declNode of resolvedSymbol.declarations) {
if (isBoltTypeAliasDeclaration(declNode)) {
// TODO
} else if (isBoltRecordDeclaration(declNode)) {
// TODO
}
}
break;
}
default:
throw new Error(`Could not check type assignment because ${kindToString(typeExpr.kind)} was not handled.`)
}
}
public getTypeFromTypeExpr(typeExpr: BoltTypeExpression) {
}
private checkTypeAssertions(node: Syntax): void {
switch (node.kind) {
case SyntaxKind.BoltModule:
case SyntaxKind.BoltSourceFile:
for (const element of node.elements) {
this.checkTypeAssertions(element);
}
break;
case SyntaxKind.BoltVariableDeclaration:
if (node.typeExpr !== null && node.value !== null) {
this.checkTypeAssignment(node.value, node.typeExpr);
}
break;
case SyntaxKind.BoltFunctionDeclaration:
if (node.returnTypeExpr !== null && node.body !== null) {
for (const returnStmt of getAllReturnStatementsInFunctionBody(node.body)) {
if (returnStmt.value !== null) {
this.checkTypeAssignment(returnStmt.value, node.returnTypeExpr);
} else {
// TODO
}
}
}
break;
}
}
/**
* Resolves the given expression to a function declaration or function
* expression that matches the given signature.
*/
private resolveToCallable(expr: BoltExpression, args: BoltExpression[]): BoltFunctionDeclaration | BoltFunctionExpression | null {
// TODO actually match the signature for overloads
switch (expr.kind) {
case SyntaxKind.BoltFunctionExpression:
return expr;
case SyntaxKind.BoltReferenceExpression:
{
const scope = this.resolver.getScopeForNode(expr, ScopeType.Variable);
assert(scope !== null);
const resolvedSymbol = this.resolver.resolveSymbolPath(convertNodeToSymbolPath(expr), scope!);
if (resolvedSymbol === null) {
return null;
}
for (const declNode of resolvedSymbol.declarations) {
if (isBoltVariableDeclaration(declNode)) {
if (declNode.value !== null) {
const resolved = this.resolveToCallable(declNode.value, args);
if (resolved !== null) {
return resolved;
}
} else {
// TODO add diagnostic
}
} else if (isBoltFunctionDeclaration(declNode)) {
return declNode;
} else {
throw new Error(`While resolving to a function: a reference expression resolved to an unhandled declaration ${kindToString(declNode.kind)}`);
}
}
}
default:
throw new Error(`While resolving to a function: the expression ${kindToString(expr.kind)} was not recognised.`)
}
}
private createCFGNode(sourceNode: Syntax, prevContext: CFGNode | null = null) {
const context = new CFGNode(this.nextSimulationContextId++, sourceNode, prevContext);
this.contextById.set(context.id, context);
return context;
}
private bindExpressionToPattern(
pattern: BoltPattern,
expr: BoltExpression,
exprContext: CFGNode,
env: Environment
) {
switch (pattern.kind) {
case SyntaxKind.BoltBindPattern:
env.set(pattern.name.text, new NodeWithContext(expr, exprContext));
break;
default:
throw new Error(`While binding an expression to a pattern: unhandled pattern of kind ${kindToString(pattern.kind)}`);
}
}
private *getAllPropertiesOfNode(node: Syntax): IterableIterator<[CFGNode, Assertion]> {
if (node.properties === undefined) {
return;
}
for (const [contextId, propertyGroup] of node.properties) {
const context = this.getContextById(contextId);
for (const property of propertyGroup.getAllProperties()) {
yield [context, property];
}
}
}
private getAllPropertiesOfNodeInContext(node: Syntax, expectedContext: CFGNode): PropertyGroup {
if (node.properties === undefined) {
node.properties = new FastStringMap<number, PropertyGroup>();
}
if (!node.properties.has(expectedContext.id)) {
node.properties.set(expectedContext.id, new PropertyGroup());
}
return node.properties.get(expectedContext.id);
}
private addPropertyToNodeInContext(node: Syntax, property: Assertion, context: CFGNode) {
if (node.properties === undefined) {
node.properties = new FastStringMap<number, PropertyGroup>();
}
if (!node.properties.has(context.id)) {
node.properties.set(context.id, new PropertyGroup());
}
node.properties.get(context.id).addProperty(property);
}
private evaluateExpression(expr: BoltExpression, env: Environment): Value | null {
switch (expr.kind) {
case SyntaxKind.BoltConstantExpression:
return expr.value;
case SyntaxKind.BoltCallExpression:
const fn = this.evaluateExpression(expr.operator, env);
const args = expr.operands.map(op => this.evaluateExpression(op, env));
return fn(...args);
case SyntaxKind.BoltReferenceExpression:
const text = getSymbolText(expr.name.name);
if (!expr.name.isAbsolute
&& expr.name.modulePath.length === 0
&& hasBuiltinOperator(text)) {
return getBuiltinOperator(text);
} else {
const resolved = env.lookup(text);
return this.evaluateExpression(resolved.node, env);
}
default:
throw new Error(`Could not evaluate expression of unhandled kind ${kindToString(expr.kind)}`);
}
}
private doesAssumptionHold(assumption: Condition, env: Environment): boolean {
if (assumption instanceof ExprCondition) {
return this.evaluateExpression(assumption.expression, env) === true;
} else if (assumption instanceof NotCondition) {
return !this.doesAssumptionHold(assumption.conditionToNegate, env);
} else if (assumption instanceof ConditionGroup) {
for (const childCond of assumption.getAllConditions()) {
if (!this.doesAssumptionHold(childCond, env)) {
return false;
}
}
return true;
} else {
throw new Error(`Unrecognised assumption ${assumption}`);
}
}
private reduceAssumptions(assumptions: ConditionGroup, env: Environment) {
for (const assumption of [...assumptions.getAllConditions()]) {
if (this.doesAssumptionHold(assumption, env)) {
assumptions.removeCondition(assumption);
}
}
}
private addPropertiesOfNodeToNode(srcNode: Syntax, srcContext: CFGNode, dstNode: Syntax, dstContext: CFGNode) {
for (const property of this.getAllPropertiesOfNodeInContext(srcNode, srcContext)) {
this.addPropertyToNodeInContext(dstNode, property, dstContext);
}
}
private simulateCallExpression(expr: BoltCallExpression, context: CFGNode, env: Environment): CFGNode {
const fnDecl = this.resolveToCallable(expr.operator, expr.operands);
if (fnDecl === null) {
// TODO add diagnostic
return context;
}
switch (fnDecl.kind) {
case SyntaxKind.BoltFunctionDeclaration:
{
if (expr.operands.length < fnDecl.params.length) {
this.diagnostics.add({
message: E_TOO_FEW_ARGUMENTS_FOR_FUNCTION_CALL,
severity: 'error',
node: expr,
})
} else if (expr.operands.length > fnDecl.params.length) {
this.diagnostics.add({
message: E_TOO_MANY_ARGUMENTS_FOR_FUNCTION_CALL,
severity: 'error',
node: expr,
})
} else {
const fnEnv = new Environment(env);
let fnContext = context;
if (fnDecl.body !== null) {
for (let i = 0; i < fnDecl.params.length; i++) {
const param = fnDecl.params[i];
const arg = expr.operands[i];
this.bindExpressionToPattern(param.bindings, arg, context, fnEnv);
}
for (const element of fnDecl.body) {
fnContext = this.simulateEvaluation(element, fnContext, fnEnv);
}
for (const returnStmt of getAllReturnStatementsInFunctionBody(fnDecl.body)) {
if (returnStmt.value !== null) {
this.addPropertiesOfNodeToNode(returnStmt.value, fnContext, expr, context);
} else {
// TODO handle case where return expression is not set
}
}
}
return context;
}
}
default:
throw new Error(`Could not simulate application because the node ${kindToString(fnDecl.kind)} was not recognised.`)
}
}
private mergeProperties(a: BoltExpression, b: BoltExpression, context: CFGNode) {
}
private setExpressionToTrue(expr: BoltExpression, context: CFGNode, negated: boolean) {
switch (expr.kind) {
case SyntaxKind.BoltCallExpression:
{
if (expr.operator.kind === SyntaxKind.BoltReferenceExpression) {
const text = getSymbolText(expr.operator.name.name);
switch (text) {
case '==':
this.mergeProperties(expr.operands[0], expr.operands[1], context);
break;
default:
throw new Error(`Could not assume the given expression to be true: unsupported operator`)
}
}
}
}
}
private setConditionToTrue(condition: Condition, context: CFGNode, negated: boolean = true): void {
if (condition instanceof ExprCondition) {
this.setExpressionToTrue(condition.expression, context, negated);
} else if (condition instanceof NotCondition) {
this.setConditionToTrue(condition.conditionToNegate, context, !negated);
} else {
throw new Error(`Could not convert unhandled conditon to a property.`);
}
}
private simulateEvaluation(node: Syntax, context: CFGNode, env: Environment): CFGNode {
switch (node.kind) {
case SyntaxKind.BoltReferenceExpression:
assert(!node.name.isAbsolute);
assert(node.name.modulePath.length === 0);
const nodeWithContext = env.lookup(getSymbolText(node.name.name));
this.addPropertiesOfNodeToNode(nodeWithContext.node, nodeWithContext.context, node, context);
return context;
case SyntaxKind.BoltConstantExpression:
this.addPropertyToNodeInContext(node, new HasValueAssertion(node.value), context);
return context;
case SyntaxKind.BoltRecordDeclaration:
case SyntaxKind.BoltFunctionDeclaration:
return context;
case SyntaxKind.BoltCallExpression:
return this.simulateCallExpression(node, context, env);
case SyntaxKind.BoltCaseStatement:
{
let failedConditions = [];
for (const caseNode of node.cases) {
// Create a new context that will be used to evaluate the
// if-statement's body. The context will hold additional properties
// about this if-statement, as well as the properties of the parent context.
const caseContext = this.createCFGNode(caseNode, context);
// If a previous condition failed, we know that whatever expression
// that was used to test that condition must evaluate to false. We
// add this information to the newly created context.
for (const failedCondition of failedConditions) {
this.setConditionToTrue(failedCondition, caseContext);
}
// We are going to evaluate the body of this test case, which assumes
// that the test expression associated with this if-statement
// evaluated to true. We add these assumptions to the context that
// will be used to evaluate the statements.
if (caseNode.test !== null) {
const condition = new ExprCondition(caseNode.test);
this.setConditionToTrue(condition, caseContext);
failedConditions.push(new NotCondition(condition))
}
// Now iterate over the if-statement's body with the new context.
for (const element of caseNode.body) {
this.simulateEvaluation(element, context, env);
}
}
return context;
}
case SyntaxKind.BoltReturnStatement:
if (node.value !== null) {
this.simulateEvaluation(node.value, context, env);
} else {
// TODO handle the case where return is empty
}
break;
case SyntaxKind.BoltExpressionStatement:
return this.simulateEvaluation(node.expression, context, env);
case SyntaxKind.BoltVariableDeclaration:
if (node.value !== null) {
this.bindExpressionToPattern(node.bindings, node.value, context, env);
return this.simulateEvaluation(node.value, context, env);
} else {
this.addPropertyToNodeInContext(node, new IsUnsafeProperty(), context);
return context;
}
default:
throw new Error(`Could not simulate evaluation of node of kind ${kindToString(node.kind)}`);
}
}
}

View file

@ -7,7 +7,7 @@ import { BOLT_DIAG_NUM_EXTRA_LINES } from "./constants";
import { TextPos, TextFile, TextSpan } from "./text";
export const E_ASSIGN_TUPLE_LENGTH_MISMATCH = "Trying to assign a tuple of length {rhsLength} to a tuple of length {lhsLength}"
export const E_ASSIGN_TYPES_MISMATCH = "Trying to assign to a pattern of type {lhsType}, which is incompatible with expression of type {rhsType}"
export const E_TYPES_NOT_ASSIGNABLE = "Trying to assign to an expression of type {lhs}, which is incompatible with expression of type {rhs}"
export const E_MAY_NOT_RETURN_BECAUSE_TYPE_RESOLVES_TO_VOID = "May not return a value because the function's return type resolves to '()'"
export const E_MUST_RETURN_BECAUSE_TYPE_DOES_NOT_RESOLVE_TO_VOID = "Must return a value because the function's return type does not resolve to '()'"
@ -15,7 +15,7 @@ export const E_MUST_RETURN_BECAUSE_TYPE_DOES_NOT_RESOLVE_TO_VOID = "Must return
export const E_INVALID_TEST_COMPARE = "The given test results cannot be compared because they use different specifications."
export const E_TESTS_DO_NOT_COMPARE = "This test does not compare with its expected output."
export const E_NO_BOLTFILE_FOUND_IN_PATH_OR_PARENT_DIRS = 'No Boltfile found in {path} or any of its parent directories.'
export const E_SSCAN_ERROR = "Got an unexpected {char}"
export const E_SCAN_ERROR = "Got an unexpected {char}"
export const E_STDLIB_NOT_FOUND = "Package 'stdlib' is required to build the current source set but it was not found. Use --no-std if you know what you are doing."
export const E_PARSE_ERROR = "Expected {expected:enum} but got {actual}"
export const E_MAY_NOT_RETURN_A_VALUE = "Returning a value inside a function that does not return values."
@ -26,7 +26,7 @@ export const E_FIELD_NOT_PRESENT = "Field '{name}' is not present."
export const E_FIELD_MUST_BE_BOOLEAN = "Field '{name}' must be a either 'true' or 'false'."
export const E_TYPE_DECLARATION_NOT_FOUND = "A type declaration named '{name}' was not found."
export const E_DECLARATION_NOT_FOUND = "Reference to an undefined declaration '{name}'.";
export const E_TYPE_MISMATCH = "Types {left} and {right} are not compatible with one another.";
export const E_TYPE_MISMATCH = "Types '{left}' and '{right}' are not compatible with one another.";
export const E_THIS_NODE_CAUSED_INVALID_TYPE = "This expression resolved to the type {type}, which is incompatible with {origType}."
export const E_TOO_FEW_ARGUMENTS_FOR_FUNCTION_CALL = "Too few arguments for function call. Expected {expected} but got {actual}.";
export const E_TOO_MANY_ARGUMENTS_FOR_FUNCTION_CALL = "Too many arguments for function call. Expected {expected} but got {actual}.";
@ -72,6 +72,10 @@ function firstIndexOfNonEmpty(str: string) {
return j
}
export interface Diagnostics {
add(diagnostic: Diagnostic): void;
}
export class DiagnosticIndex {
private diagnostics = new Array<Diagnostic>();
@ -79,7 +83,7 @@ export class DiagnosticIndex {
public add(diagnostic: Diagnostic) {
this.diagnostics.push(diagnostic);
}
public getAllDiagnostics(): IterableIterator<Diagnostic> {
return this.diagnostics[Symbol.iterator]();
}
@ -119,7 +123,6 @@ export class DiagnosticPrinter {
out += chalk.bold.red('fatal: ')
break;
case 'warning':
this.hasErrors = true;
out += chalk.bold.red('warning: ');
break;
case 'info':
@ -129,16 +132,6 @@ export class DiagnosticPrinter {
throw new Error(`Unkown severity for diagnostic message.`);
}
if (diagnostic.node !== undefined) {
const span = diagnostic.node.span!;
out += chalk.bold.yellow(`${span.file.origPath}:${span.start.line}:${span.start.column}: `);
}
if (diagnostic.args !== undefined) {
out += format(diagnostic.message, diagnostic.args) + '\n';
} else {
out += diagnostic.message + '\n';
}
let span = null;
if (diagnostic.node !== undefined) {
span = diagnostic.node.span!;
@ -147,6 +140,15 @@ export class DiagnosticPrinter {
span = new TextSpan(diagnostic.file!, diagnostic.position, diagnostic.position)
}
if (span !== null) {
out += chalk.bold.yellow(`${span.file.origPath}:${span.start.line}:${span.start.column}: `);
}
if (diagnostic.args !== undefined) {
out += format(diagnostic.message, diagnostic.args) + '\n';
} else {
out += diagnostic.message + '\n';
}
if (span !== null) {
out += '\n'
const content = span.file.getText();

View file

@ -2,7 +2,6 @@
import { Syntax, SyntaxKind, BoltQualName, BoltExpression, kindToString, BoltSyntax, isBoltStatement } from "./ast"
import { FastStringMap, assert } from "./util"
import { emitNode } from "./emitter";
import { TypeChecker } from "./checker";
export class Record {

View file

@ -1,30 +1,29 @@
import * as path from "path"
import * as fs from "fs-extra"
import { EventEmitter } from "events"
import * as fs from "fs-extra"
import { sync as globSync } from "glob"
import { Program } from "./program"
import { now } from "moment"
import * as path from "path"
import { BoltSourceFile, BoltToken, setParents, SourceFile, Visitor } from "./ast"
import { TypeChecker } from "./checker"
import { CheckInvalidFilePaths, CheckReferences, CheckTypeAssignments } from "./checks"
import { describeKind, getNodeLanguage, ParseError, ScanError } from "./common"
import { DiagnosticPrinter, E_NO_BOLTFILE_FOUND_IN_PATH_OR_PARENT_DIRS, E_PARSE_ERROR, E_SCAN_ERROR, E_STDLIB_NOT_FOUND } from "./diagnostics"
import { emitNode } from "./emitter"
import { Syntax, BoltSourceFile, SourceFile, setParents, kindToString, Visitor, BoltToken } from "./ast"
import { getFileStem, MapLike, assert, FastStringMap, upsearchSync, GeneratorStream } from "./util"
import { verbose, memoize } from "./util"
import { Evaluator } from "./evaluator"
import { Container, Newable } from "./ioc"
import ExpandBoltTransform from "./transforms/expand"
import { loadPackageMetadata, Package } from "./package"
import { Parser } from "./parser"
import { Program } from "./program"
import { BoltSymbolResolutionStrategy, SymbolResolver } from "./resolver"
import { Scanner } from "./scanner"
import { TextFile, TextSpan } from "./text"
import CompileBoltToJSTransform from "./transforms/boltToJS"
import ConstFoldTransform from "./transforms/constFold"
import ExpandBoltTransform from "./transforms/expand"
import { TransformManager } from "./transforms/index"
import {DiagnosticPrinter, E_PARSE_ERROR, E_STDLIB_NOT_FOUND, E_SSCAN_ERROR as E_SCAN_ERROR, E_NO_BOLTFILE_FOUND_IN_PATH_OR_PARENT_DIRS} from "./diagnostics"
import { TypeChecker } from "./checker"
import { CheckInvalidFilePaths, CheckTypeAssignments, CheckReferences } from "./checks"
import { SymbolResolver, BoltSymbolResolutionStrategy } from "./resolver"
import { Evaluator } from "./evaluator"
import { getNodeLanguage, ParseError, ScanError, describeKind } from "./common"
import { Package, loadPackageMetadata } from "./package"
import { TextFile } from "./text"
import { Scanner } from "./scanner"
import { Parser } from "./parser"
import { now } from "moment"
import { escapeChar, FastStringMap, GeneratorStream, getFileStem, MapLike, upsearchSync, verbose } from "./util"
const targetExtensions: MapLike<string> = {
'JS': '.mjs',
@ -94,13 +93,13 @@ export class Frontend {
container.bindSelf(checker);
container.bindSelf(this.diagnostics);
const checks: Newable<Visitor>[] = [
const checkClasses: Newable<Visitor>[] = [
CheckInvalidFilePaths,
CheckReferences,
CheckTypeAssignments,
];
const checkers = checks.map(check => container.createInstance(check));
const checks = checkClasses.map(check => container.createInstance(check));
for (const sourceFile of program.getAllSourceFiles()) {
resolver.registerSourceFile(sourceFile);
@ -108,20 +107,22 @@ export class Frontend {
for (const sourceFile of program.getAllSourceFiles()) {
checker.registerSourceFile(sourceFile);
}
checker.solve(program.getAllSourceFiles());
for (const sourceFile of program.getAllSourceFiles()) {
checker.checkNode(sourceFile);
}
for (const pkg of program.getAllPackages()) {
if (!pkg.isDependency) {
for (const sourceFile of pkg.getAllSourceFiles()) {
for (const node of sourceFile.preorder()) {
for (const checker of checkers) {
checker.visit(node);
for (const check of checks) {
check.visit(node);
}
}
}
}
}
}
public compile(program: Program, target: string) {
@ -186,7 +187,7 @@ export class Frontend {
this.diagnostics.add({
severity: 'fatal',
message: E_SCAN_ERROR,
args: { char: e.char },
args: { char: e.char === '' ? 'end-of-file' : `'${escapeChar(e.char)}'` },
position: e.position,
file: e.file,
});
@ -214,10 +215,10 @@ export class Frontend {
let rootDir;
if (path.basename(filepath) === 'Boltfile') {
metadataPath = filepath
rootDir = path.dirname(filepath);
rootDir = path.resolve(path.dirname(filepath));
} else {
metadataPath = path.join(filepath, 'Boltfile');
rootDir = filepath;
rootDir = path.resolve(filepath);
}
const data = loadPackageMetadata(this.diagnostics, metadataPath);
const pkg = new Package(rootDir, data.name, data.version, [], data.autoImport, isDependency);
@ -254,9 +255,9 @@ export class Frontend {
}
const anonPkg = new Package(cwd, null, null, [], false, false);
const pkgs = [ anonPkg ];
for (const filename of filenames) {
if (fs.statSync(filename).isDirectory() || path.basename(filename) === 'Boltfile') {
@ -269,21 +270,21 @@ export class Frontend {
}
}
if (useStd) {
if (pkgs.find(pkg => pkg.name === 'stdlib') === undefined) {
const resolvedPath = this.findPackagePath('stdlib');
if (resolvedPath === null) {
this.diagnostics.add({
message: E_STDLIB_NOT_FOUND,
severity: 'error',
});
return null;
}
const stdlibPkg = this.loadPackageFromPath(resolvedPath, true);
pkgs.push(stdlibPkg);
}
// if (useStd) {
// if (pkgs.find(pkg => pkg.name === 'stdlib') === undefined) {
// const resolvedPath = this.findPackagePath('stdlib');
// if (resolvedPath === null) {
// this.diagnostics.add({
// message: E_STDLIB_NOT_FOUND,
// severity: 'error',
// });
// return null;
// }
// const stdlibPkg = this.loadPackageFromPath(resolvedPath, true);
// pkgs.push(stdlibPkg);
// }
// }
}
return new Program(pkgs);
}

View file

@ -49,7 +49,7 @@ export class Package {
}
export function loadPackageMetadata(diagnostics: DiagnosticPrinter, rootDir: string) {
export function loadPackageMetadata(diagnostics: DiagnosticPrinter, filepath: string) {
let name = null
let version = null;
@ -58,7 +58,6 @@ export function loadPackageMetadata(diagnostics: DiagnosticPrinter, rootDir: str
let hasVersionErrors = false;
let hasNameErrors = false;
const filepath = path.join(rootDir, 'Boltfile');
if (fs.existsSync(filepath)) {
const data = yaml.safeLoad(fs.readFileSync(filepath, 'utf8'));
if (data !== undefined) {

View file

@ -83,15 +83,12 @@ import {
BoltRecordExpressionElement,
createBoltRecordFieldValue,
BoltRecordExpression,
BoltForKeyword,
BoltBraced,
BoltAssignStatement,
createBoltAssignStatement,
BoltExportDirective,
BoltParenthesized,
createBoltCaseStatementCase,
createBoltCaseStatement,
createBoltElseKeyword,
BoltCaseStatement,
} from "./ast"
import { parseForeignLanguage } from "./foreign"
@ -104,14 +101,12 @@ import {
setOrigNodeRange,
createTokenStream,
} from "./common"
import { Stream, uniq, assert, isInsideDirectory, first } from "./util"
import { Stream, uniq } from "./util"
import { Scanner } from "./scanner"
import { TextSpan, TextPos } from "./text"
import {JSScanner} from "./foreign/js/scanner";
import { Package } from "./package"
import { BoltCaseStatement, Syntax } from "./ast-spec"
import { resourceUsage } from "process"
export type BoltTokenStream = Stream<BoltToken>;
@ -1094,18 +1089,20 @@ export class Parser {
lastToken = t4;
}
let alternative = null;
const t4 = tokens.peek();
if (t4.kind === SyntaxKind.BoltElseKeyword) {
tokens.get();
const t5 = tokens.get();
assertToken(t5, SyntaxKind.BoltBraced);
const alternativeTokens = createTokenStream(t5);
alternative = this.parseFunctionBodyElements(alternativeTokens)
const body = this.parseFunctionBodyElements(alternativeTokens)
const alternative = createBoltCaseStatementCase(null, body);
setOrigNodeRange(alternative, t4, t5);
cases.push(alternative);
lastToken = t5;
}
const result = createBoltCaseStatement(cases, alternative);
const result = createBoltCaseStatement(cases);
setOrigNodeRange(result, t0, lastToken);
return result;
}
@ -1311,7 +1308,7 @@ export class Parser {
return node;
}
private parseFunctionDeclaration(tokens: BoltTokenStream): BoltFunctionDeclaration {
public parseFunctionDeclaration(tokens: BoltTokenStream): BoltFunctionDeclaration {
let target = "Bolt";
let modifiers = 0;
@ -1522,7 +1519,7 @@ export class Parser {
// The trait may optionally have 'fn ...' and 'type ..' elements wrapped in braces.
const t3 = tokens.peek();
if (t2.kind === SyntaxKind.BoltBraced) {
if (t3.kind === SyntaxKind.BoltBraced) {
const t3 = tokens.get();
lastToken = t3;
const innerTokens = createTokenStream(t3);
@ -1578,18 +1575,18 @@ export class Parser {
if (foundForKeyword) {
// Parse the type expression that references the trait the user wants to implement
traitTypeExpr = this.parseTypeExpression(tokens);
traitTypeExpr = this.parseReferenceTypeExpression(tokens);
// Skip the 'for' keyword itself
assertToken(tokens.get(), SyntaxKind.BoltForKeyword);
// Parse the type that this implementation is for
typeExpr = this.parseTypeExpression(tokens);
typeExpr = this.parseReferenceTypeExpression(tokens);
} else {
// Just parse the trait the user wants to implement and leave the rest as is
const resultTypeExpr = this.parseTypeExpression(tokens);
const resultTypeExpr = this.parseReferenceTypeExpression(tokens);
// We cheat a bit by assigning the referenced trait to both fields
// NOTE Assigning the same node by reference to different fields should be done with great care.
@ -1604,7 +1601,7 @@ export class Parser {
const elements = this.parseTraitOrImplElements(createTokenStream(t5));
// Create and return the result
const result = createBoltImplDeclaration(modifiers, typeParams, typeExpr, traitTypeExpr, elements);
const result = createBoltImplDeclaration(modifiers, typeParams, traitTypeExpr, typeExpr, elements);
setOrigNodeRange(result, firstToken, t5);
return result;
}
@ -1769,7 +1766,7 @@ export class Parser {
);
}
public parseTraitOrImplElements(tokens: BoltTokenStream): BoltTraitOrImplElement[] {
public parseTraitOrImplElements(tokens: BoltTokenStream, allowPub = false): BoltTraitOrImplElement[] {
const elements: BoltTraitOrImplElement[] = [];
while (true) {
const t0 = tokens.peek();
@ -1789,7 +1786,16 @@ export class Parser {
if (this.lookaheadIsMacroCall(tokens)) {
return this.parseMacroCall(tokens);
}
const t0 = tokens.peek();
let i = 1;
let t0 = tokens.peek(i);
if (t0.kind === SyntaxKind.BoltPubKeyword) {
i += 1;
t0 = tokens.peek(i);
}
if (t0.kind === SyntaxKind.BoltForeignKeyword) {
i += 2;
t0 = tokens.peek(i);
}
switch (t0.kind) {
case SyntaxKind.BoltFnKeyword:
return this.parseFunctionDeclaration(tokens);

View file

@ -0,0 +1,8 @@
export class REPL {
public start(): Promise<void> {
}
}

View file

@ -0,0 +1,52 @@
import test from "ava";
import {BoltBindPattern, BoltOperator, SyntaxKind} from "../ast";
import { createTokenStream } from "../common";
import {Parser} from "../parser";
test('the Bolt parser correctly parses an operator definition', t => {
const parser = new Parser();
const tokens1 = createTokenStream(`fn +x;`)
const funcDecl1 = parser.parseFunctionDeclaration(tokens1);
t.assert(funcDecl1.kind === SyntaxKind.BoltFunctionDeclaration);
t.assert(funcDecl1.name.kind === SyntaxKind.BoltOperator);
const funcDecl1Name = funcDecl1.name as BoltOperator;
t.assert(funcDecl1Name.text === '+');
t.assert(funcDecl1.params.length === 1);
t.assert(funcDecl1.params[0].kind === SyntaxKind.BoltParameter);
t.assert(funcDecl1.params[0].bindings.kind === SyntaxKind.BoltBindPattern);
const funcDecl1BindPatt = funcDecl1.params[0].bindings as BoltBindPattern;
t.assert(funcDecl1BindPatt.name.text === 'x');
t.assert(tokens1.get().kind === SyntaxKind.BoltSemi);
const tokens2 = createTokenStream(`fn a + b;`);
const funcDecl2 = parser.parseFunctionDeclaration(tokens2);
t.assert(funcDecl2.kind === SyntaxKind.BoltFunctionDeclaration);
t.assert(funcDecl2.name.kind === SyntaxKind.BoltOperator);
const funcDecl2Name = funcDecl2.name as BoltOperator;
t.assert(funcDecl2Name.text === '+');
t.assert(funcDecl2.params.length === 2);
t.assert(funcDecl2.params[0].kind === SyntaxKind.BoltParameter);
t.assert(funcDecl2.params[0].bindings.kind === SyntaxKind.BoltBindPattern);
const funcDecl2BindPatt0 = funcDecl2.params[0].bindings as BoltBindPattern;
t.assert(funcDecl2BindPatt0.name.text === 'a');
t.assert(funcDecl2.params[1].kind === SyntaxKind.BoltParameter);
t.assert(funcDecl2.params[1].bindings.kind === SyntaxKind.BoltBindPattern);
const funcDecl2BindPatt1 = funcDecl2.params[1].bindings as BoltBindPattern;
t.assert(funcDecl2BindPatt1.name.text === 'b');
t.assert(tokens2.get().kind === SyntaxKind.BoltSemi);
const tokens3 = createTokenStream(`fn (a: Int) + (b: Int);`);
const funcDecl3 = parser.parseFunctionDeclaration(tokens3);
t.assert(funcDecl3.kind === SyntaxKind.BoltFunctionDeclaration);
// TODO complete these assertions
const tokens4 = createTokenStream(`fn a + b -> Int;`);
const funcDecl4 = parser.parseFunctionDeclaration(tokens4);
t.assert(funcDecl4.kind === SyntaxKind.BoltFunctionDeclaration);
// TODO complete these assertions
})

View file

@ -0,0 +1,18 @@
import test from "ava";
import { createBoltConstantExpression, createBoltIdentifier, createBoltQualName, createBoltReferenceExpression } from "../ast";
import { TypeChecker } from "../checker"
function createSimpleBoltReferenceExpression(name: string) {
return createBoltReferenceExpression(
createBoltQualName(false, [], createBoltIdentifier(name)),
)
}
test('an intersection with an any-type should remove that any-type', t => {
const expr = createBoltConstantExpression(BigInt(1));
const checker = new TypeChecker();
const exprType = checker.getTypeOfNode(expr);
t.assert(checker.isIntType(exprType))
});

View file

@ -390,7 +390,7 @@ export class FastMultiMap<K, V> {
this.mapping = Object.create(null);
}
public get(key: string): IterableIterator<V> {
public get(key: K): IterableIterator<V> {
if (this.mapping[key] === undefined) {
return new EmptyIterator;
}
@ -425,10 +425,20 @@ export class FastStringMap<K extends PropertyKey, V> {
private mapping = Object.create(null);
constructor(elements: Iterable<[K, V]> = []) {
for (const [k, v] of elements) {
this.set(k, v);
}
}
public clear(): void {
this.mapping.clear();
}
public overwrite(key: K, value: V): void {
this.mapping[key] = value;
}
public *[Symbol.iterator](): IterableIterator<[K, V]> {
for (const key of Object.keys(this.mapping)) {
yield [key as K, this.mapping[key]];

View file

@ -1,9 +1,10 @@
{
"compilerOptions": {
"target": "es2017",
"target": "ES2019",
"module": "commonjs",
"outDir": "./lib",
"noEmit": true,
"declaration": true,
"declarationMap": true,
"outDir": "./",
"strict": true,
"esModuleInterop": true,
"sourceMap": true,

View file

@ -15,8 +15,7 @@ module.exports = {
target: 'node',
mode: 'development',
entry: {
'bolt': './src/bin/bolt.ts',
'bolt-test': './src/bin/bolt-test.ts',
'bolt-langserver': './src/main.ts'
},
output: {
filename: 'bin/[name].js',

View file

@ -0,0 +1,5 @@
{
"presets": [
"@babel/preset-env"
]
}

View file

@ -0,0 +1 @@
maintained node versions, last 4 electron versions

7
@boltlang/langserver/.gitignore vendored Normal file
View file

@ -0,0 +1,7 @@
# npm
node_modules/
# resulting code
/bin/

102
@boltlang/langserver/package-lock.json generated Normal file
View file

@ -0,0 +1,102 @@
{
"name": "@boltlang/langserver",
"version": "1.0.0",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"version": "1.0.0",
"license": "GPL-3.0",
"dependencies": {
"minimist": "^1.2.5",
"vscode-languageserver": "^6.1.1",
"vscode-languageserver-textdocument": "^1.0.1"
},
"bin": {
"bolt-langserver": "bin/bolt-langserver.js"
}
},
"node_modules/minimist": {
"version": "1.2.5",
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz",
"integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw=="
},
"node_modules/vscode-jsonrpc": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-5.0.1.tgz",
"integrity": "sha512-JvONPptw3GAQGXlVV2utDcHx0BiY34FupW/kI6mZ5x06ER5DdPG/tXWMVHjTNULF5uKPOUUD0SaXg5QaubJL0A==",
"engines": {
"node": ">=8.0.0 || >=10.0.0"
}
},
"node_modules/vscode-languageserver": {
"version": "6.1.1",
"resolved": "https://registry.npmjs.org/vscode-languageserver/-/vscode-languageserver-6.1.1.tgz",
"integrity": "sha512-DueEpkUAkD5XTR4MLYNr6bQIp/UFR0/IPApgXU3YfCBCB08u2sm9hRCs6DxYZELkk++STPjpcjksR2H8qI3cDQ==",
"dependencies": {
"vscode-languageserver-protocol": "^3.15.3"
},
"bin": {
"installServerIntoExtension": "bin/installServerIntoExtension"
}
},
"node_modules/vscode-languageserver-protocol": {
"version": "3.15.3",
"resolved": "https://registry.npmjs.org/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.15.3.tgz",
"integrity": "sha512-zrMuwHOAQRhjDSnflWdJG+O2ztMWss8GqUUB8dXLR/FPenwkiBNkMIJJYfSN6sgskvsF0rHAoBowNQfbyZnnvw==",
"dependencies": {
"vscode-jsonrpc": "^5.0.1",
"vscode-languageserver-types": "3.15.1"
}
},
"node_modules/vscode-languageserver-textdocument": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/vscode-languageserver-textdocument/-/vscode-languageserver-textdocument-1.0.1.tgz",
"integrity": "sha512-UIcJDjX7IFkck7cSkNNyzIz5FyvpQfY7sdzVy+wkKN/BLaD4DQ0ppXQrKePomCxTS7RrolK1I0pey0bG9eh8dA=="
},
"node_modules/vscode-languageserver-types": {
"version": "3.15.1",
"resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.15.1.tgz",
"integrity": "sha512-+a9MPUQrNGRrGU630OGbYVQ+11iOIovjCkqxajPa9w57Sd5ruK8WQNsslzpa0x/QJqC8kRc2DUxWjIFwoNm4ZQ=="
}
},
"dependencies": {
"minimist": {
"version": "1.2.5",
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz",
"integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw=="
},
"vscode-jsonrpc": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-5.0.1.tgz",
"integrity": "sha512-JvONPptw3GAQGXlVV2utDcHx0BiY34FupW/kI6mZ5x06ER5DdPG/tXWMVHjTNULF5uKPOUUD0SaXg5QaubJL0A=="
},
"vscode-languageserver": {
"version": "6.1.1",
"resolved": "https://registry.npmjs.org/vscode-languageserver/-/vscode-languageserver-6.1.1.tgz",
"integrity": "sha512-DueEpkUAkD5XTR4MLYNr6bQIp/UFR0/IPApgXU3YfCBCB08u2sm9hRCs6DxYZELkk++STPjpcjksR2H8qI3cDQ==",
"requires": {
"vscode-languageserver-protocol": "^3.15.3"
}
},
"vscode-languageserver-protocol": {
"version": "3.15.3",
"resolved": "https://registry.npmjs.org/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.15.3.tgz",
"integrity": "sha512-zrMuwHOAQRhjDSnflWdJG+O2ztMWss8GqUUB8dXLR/FPenwkiBNkMIJJYfSN6sgskvsF0rHAoBowNQfbyZnnvw==",
"requires": {
"vscode-jsonrpc": "^5.0.1",
"vscode-languageserver-types": "3.15.1"
}
},
"vscode-languageserver-textdocument": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/vscode-languageserver-textdocument/-/vscode-languageserver-textdocument-1.0.1.tgz",
"integrity": "sha512-UIcJDjX7IFkck7cSkNNyzIz5FyvpQfY7sdzVy+wkKN/BLaD4DQ0ppXQrKePomCxTS7RrolK1I0pey0bG9eh8dA=="
},
"vscode-languageserver-types": {
"version": "3.15.1",
"resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.15.1.tgz",
"integrity": "sha512-+a9MPUQrNGRrGU630OGbYVQ+11iOIovjCkqxajPa9w57Sd5ruK8WQNsslzpa0x/QJqC8kRc2DUxWjIFwoNm4ZQ=="
}
}
}

View file

@ -0,0 +1,34 @@
{
"name": "@boltlang/langserver",
"version": "1.0.0",
"description": "An implementation of the Language Server Protocol for the Bolt programming language",
"bin": {
"bolt-langserver": "bin/bolt-langserver.js"
},
"scripts": {
"watch": "webpack --mode development --watch",
"test": "echo \"Error: no test specified\" && exit 1"
},
"repository": {
"type": "git",
"url": "git+https://github.com/BoltLang/BoltJS.git"
},
"keywords": [
"language-server",
"protocol",
"server",
"programming-language",
"bolt"
],
"author": "Sam Vervaeck",
"license": "GPL-3.0",
"bugs": {
"url": "https://github.com/BoltLang/BoltJS/issues"
},
"homepage": "https://github.com/BoltLang/BoltJS#readme",
"dependencies": {
"minimist": "^1.2.5",
"vscode-languageserver": "^6.1.1",
"vscode-languageserver-textdocument": "^1.0.1"
}
}

View file

@ -0,0 +1,147 @@
import net from "net"
import minimist from "minimist"
import {
createConnection,
Diagnostic,
DiagnosticSeverity,
DidChangeConfigurationNotification,
IConnection,
InitializeParams,
InitializeResult,
ProposedFeatures,
TextDocuments,
TextDocumentSyncKind
} from "vscode-languageserver";
import { TextDocument } from "vscode-languageserver-textdocument";
import { createTokenStream, ParseError, ScanError } from "@boltlang/compiler/common";
import { Parser } from "@boltlang/compiler/parser";
import { Scanner } from "@boltlang/compiler/scanner";
import { TextFile } from "@boltlang/compiler/text";
import { FastStringMap } from "@boltlang/compiler/util";
const args = minimist(process.argv.slice(2))
let connection: IConnection;
if (args.socket) {
if (typeof(args.socket) !== 'number') {
console.error(`The flag --socket=PORT must contain a valid port number when provided.`)
process.exit(1);
}
const server = net.createServer(socket => {
const connection = createConnection(ProposedFeatures.all, socket, socket);
configureConnection(connection)
});
server.listen(args.socket);
} else {
const connection = createConnection(ProposedFeatures.all);
configureConnection(connection);
}
interface BoltWorkspaceFolder {
name: string;
uri: string;
}
function configureConnection(connection: IConnection) {
const workspaceFolders = new FastStringMap<string, BoltWorkspaceFolder>()
const documents = new TextDocuments(TextDocument);
let hasConfigurationCapability = false;
let hasWorkspaceFolderCapability = false;
let hasDiagnosticRelatedInformationCapability = false;
connection.onInitialize((params: InitializeParams) => {
const capabilities = params.capabilities
hasConfigurationCapability = !!(capabilities.workspace && capabilities.workspace.configuration);
hasWorkspaceFolderCapability = !!(capabilities.workspace && capabilities.workspace.workspaceFolders);
hasDiagnosticRelatedInformationCapability = !!(capabilities.textDocument
&& capabilities.textDocument.publishDiagnostics
&& capabilities.textDocument.publishDiagnostics.relatedInformation);
const result: InitializeResult = {
capabilities: {
textDocumentSync: TextDocumentSyncKind.Incremental,
}
}
if (hasWorkspaceFolderCapability) {
result.capabilities.workspace = {
workspaceFolders: { supported: true }
}
}
return result
});
connection.onInitialized(() => {
if (hasConfigurationCapability) {
connection.client.register(DidChangeConfigurationNotification.type, undefined);
}
if (hasWorkspaceFolderCapability) {
connection.workspace.onDidChangeWorkspaceFolders(event => {
for (const removed of event.removed) {
workspaceFolders.delete(removed.uri)
}
for (const added of event.added) {
workspaceFolders.set(added.uri, { name: added.name, uri: added.uri })
}
})
}
});
documents.onDidChangeContent(event => {
validateSourceFile(event.document)
})
function validateSourceFile(document: TextDocument) {
const file = new TextFile(document.uri)
const scanner = new Scanner(file, document.getText());
const tokens = createTokenStream(scanner);
const parser = new Parser()
const diagnostics: Diagnostic[] = [];
let sourceFile;
try {
sourceFile = parser.parseSourceFile(tokens)
} catch (e) {
if (e instanceof ParseError) {
const span = e.actual.span!;
diagnostics.push({
severity: DiagnosticSeverity.Error,
range: {
start: { line: span.start.line-1, character: span.start.column-1 },
end: { line: span.end.line-1, character: span.end.column-1 }
},
message: e.errorText
});
connection.sendDiagnostics({ uri: document.uri, diagnostics })
return;
} else if (e instanceof ScanError) {
diagnostics.push({
severity: DiagnosticSeverity.Error,
range: {
start: { line: e.position.line-1, character: e.position.column-1 },
end: { line: e.position.line-1, character: e.position.column-1 },
},
message: e.errorText
});
connection.sendDiagnostics({ uri: document.uri, diagnostics })
return;
} else {
throw e;
}
}
connection.sendDiagnostics({ uri: document.uri, diagnostics })
}
documents.listen(connection)
connection.listen()
}

View file

@ -0,0 +1,12 @@
{
"compilerOptions": {
"target": "ES2019",
"module": "commonjs",
"sourceMap": true,
"noEmit": true,
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true
}
}

View file

@ -0,0 +1,37 @@
const path =require('path');
const webpack = require('webpack');
module.exports = {
target: 'node',
entry: {
'bolt-langserver': './src/main.ts'
},
output: {
filename: 'bin/[name].js',
path: path.resolve(__dirname),
devtoolModuleFilenameTemplate: '[absolute-resource-path]'
},
resolve: {
extensions: [".ts", ".js"],
},
plugins: [
new webpack.BannerPlugin({ banner: '#!/usr/bin/env node', raw: true }),
],
devtool: 'source-map',
module: {
rules: [
{
test: /\.ts$/,
exclude: /node_modules/,
loader: "ts-loader",
options: { transpileOnly: true }
},
{
test: /\.m?js$/,
exclude: /node_modules/,
loader: 'babel-loader'
},
]
}
};

9467
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -1,64 +1,39 @@
{
"name": "@samvv/bolt",
"version": "0.0.1",
"description": "A programming language for rapid prototyping",
"main": "lib/index.js",
"bin": {
"bolt": "build/bin/bolt.js",
"bolt-test": "build/bin/bolt-test.js"
},
"name": "bolt-workspace",
"version": "1.0.0",
"private": true,
"description": "The root workspace for building various Bolt language tools",
"workspaces": [
"@boltlang/compiler",
"@boltlang/langserver",
"@boltlang/cli",
"vscode-extension"
],
"scripts": {
"watch": "webpack --watch --config webpack.dev.js",
"prepare": "webpack --config webpack.prod.js",
"test": "node lib/bin/bolt-test.js",
"generate-ast": "tsastgen src/ast-spec.ts:src/ast.ts",
"update-lkg": "node lib/bin/bolt-test.js create-snapshot lkg"
"test": "concurrently --names compiler 'cd @boltlang/compiler && npm test'",
"watch": "concurrently --names compiler,langserver,cli,vscode 'cd @boltlang/compiler && npm run watch' 'cd @boltlang/langserver && npm run watch' 'cd @boltlang/cli && npm run watch' 'cd vscode-extension && npm run watch'"
},
"author": "Sam Vervaeck <vervaeck.sam@skynet.be>",
"repository": {
"type": "git",
"url": "git+https://github.com/samvv/BoltJS.git"
},
"author": "Sam Vervaeck",
"license": "GPL-3.0",
"repository": "https://github.com/samvv/Bolt",
"dependencies": {
"@types/commonmark": "^0.27.4",
"@types/diff": "^4.0.2",
"@types/fs-extra": "^9.0.2",
"@types/glob": "^7.1.3",
"@types/js-yaml": "^3.12.5",
"@types/microtime": "^2.1.0",
"@types/minimist": "^1.2.0",
"@types/node": "^14.14.6",
"@types/ora": "^3.2.0",
"@types/semver": "^7.3.4",
"@types/uuid": "^8.3.0",
"@types/yargs": "^15.0.9",
"chalk": "^4.1.0",
"commonmark": "^0.29.2",
"diff": "^4.0.2",
"fs-extra": "^9.0.1",
"glob": "^7.1.6",
"js-yaml": "^3.14.0",
"microtime": "^3.0.0",
"minimist": "^1.2.5",
"moment": "^2.29.1",
"ora": "^5.1.0",
"reflect-metadata": "^0.1.13",
"semver": "^7.3.2",
"source-map-support": "^0.5.19",
"uuid": "^8.3.1",
"yargs": "^16.1.0"
"bugs": {
"url": "https://github.com/samvv/BoltJS/issues"
},
"homepage": "https://github.com/samvv/BoltJS#readme",
"devDependencies": {
"@babel/core": "^7.12.3",
"@babel/plugin-proposal-class-properties": "^7.12.1",
"@types/chai": "^4.2.14",
"@types/tape": "^4.13.0",
"@babel/preset-env": "^7.12.1",
"@types/node": "^14.14.7",
"ava": "^3.13.0",
"babel-loader": "^8.1.0",
"babel-loader": "^8.2.1",
"concurrently": "^5.3.0",
"tap-min": "^2.0.0",
"tape": "^5.0.1",
"ts-loader": "^8.0.7",
"ts-loader": "^8.0.11",
"typescript": "^4.0.5",
"webpack": "^5.3.1",
"webpack-cli": "^4.1.0"
"webpack": "^5.4.0",
"webpack-cli": "^4.2.0"
}
}

View file

@ -1,570 +0,0 @@
// NOTE The code in this file is not as clean as we want it to be, but we'll be upgrading our
// test infrastructure anyways with version 1.0.0 so it does not matter much.
import chalk from "chalk"
import { Parser as CommonmarkParser } from "commonmark"
import * as crypto from "crypto"
import { diffLines } from "diff"
import * as fs from "fs-extra"
import { sync as globSync } from "glob"
import yaml from "js-yaml"
import ora, { Ora } from "ora"
import * as path from "path"
import "reflect-metadata"
import "source-map-support/register"
import { inspect } from "util"
import yargs, { Argv } from "yargs"
import { Syntax, SyntaxKind } from "../ast"
import { Diagnostic, DiagnosticIndex, DiagnosticPrinter, E_TESTS_DO_NOT_COMPARE } from "../diagnostics"
import { Parser } from "../parser"
import { Scanner } from "../scanner"
import { TextFile, TextPos, TextSpan } from "../text"
import { deserializable, deserialize, Json, JsonObject, MapLike, serialize, serializeTag, upsearchSync, assert } from "../util"
const PACKAGE_ROOT = path.resolve(path.dirname(upsearchSync('package.json')!));
const DEFAULT_STORAGE_DIR = 'test-storage';
const STORAGE_DIR = path.join(PACKAGE_ROOT, 'test-storage');
const diagnostics = new DiagnosticPrinter();
let spinner: Ora;
// TODO move some logic from TestSession to TestSuite
// TODO hash the entire code base and have it serve as a unique key for TestSession
class FancyError extends Error {
constructor(public message: string) {
super(message);
}
}
@deserializable()
class Test {
public key: string;
constructor(
public readonly span: TextSpan,
public readonly type: string,
public readonly text: string,
public readonly data: JsonObject,
public result?: any,
public error: Error | null = null
) {
this.key = hash([text, data]);
}
/**
* Note that tests loose their associated test results when they are serialized.
*/
[serializeTag]() {
return [
this.span,
this.type,
this.text,
this.data,
this.result,
this.error,
]
}
}
interface ScanForTestsOptions {
include: string[];
exclude: string[];
}
function getKeyForCurrentSources() {
const hasher = crypto.createHash('sha512');
for (const filepath of globSync('src/**/*.ts')) {
const contents = fs.readFileSync(filepath, 'binary');
hasher.update(contents)
hasher.update('\0');
}
return hasher.digest('hex')
}
function scanForTestsInCurrentSources(options: ScanForTestsOptions) {
const tests: Test[] = [];
const includes = options?.include ?? ['test/**/*.md'];
const excludes = options?.exclude ?? [];
spinner.text = 'Scanning for tests [0 found]';
for (const include of includes) {
for (const filepath of globSync(include, { ignore: excludes })) {
spinner.info(`Found file ${filepath}`)
for (const test of loadTests(filepath)) {
tests.push(test);
spinner.text = `Scanning for tests [${tests.length} found]`;
}
}
}
return tests;
}
function getSnapshotForCurrentSources(options: ScanForTestsOptions): TestSnapshot | null {
const key = getKeyForCurrentSources();
const tests = scanForTestsInCurrentSources(options);
runTests(tests);
if (tests.some(t => t.error !== null)) {
return null;
}
return new TestSnapshot(key, tests);
}
function runTests(tests: Test[]): void {
let failCount = 0;
let i = 1;
for (const test of tests) {
spinner.text = `Running tests [${i}/${tests.length}]`
const runner = TEST_RUNNERS[test.type]
if (runner === undefined) {
spinner.warn(`Test runner '${test.type}' not found.`)
continue;
}
let result;
try {
test.result = runner(test);
} catch (e) {
test.error = e;
failCount++;
spinner.warn(`The following test from ${path.relative(process.cwd(), test.span.file.fullPath)} failed with "${e.message}":\n\n${test.text}\n`)
}
i++;
}
if (failCount > 0) {
spinner.fail(`${failCount} tests failed.`)
}
}
//function saveTest(test: Test) {
// fs.mkdirpSync(path.join(STORAGE_DIR, 'tests'));
// fs.writeFileSync(path.join(STORAGE_DIR, 'tests', test.key), JSON.stringify(serialize(test)), 'utf8');
//}
@deserializable()
class TestSnapshot {
constructor(
public key: string,
public tests: Test[],
) {
fs.mkdirpSync(path.join(STORAGE_DIR, 'snapshots'));
fs.writeFileSync(path.join(STORAGE_DIR, 'snapshots', key), JSON.stringify(serialize(this)), 'utf8');
}
public hasFailedTests() {
return this.tests.some(t => t.error !== null);
}
public saveTo(dir: string) {
fs.mkdirpSync(dir);
const fd = fs.openSync(path.join(dir, this.key), fs.constants.O_WRONLY);
try {
for (const test of this.tests) {
assert(test.error === null);
fs.writeSync(fd, JSON.stringify([serialize(test), serialize(test.result)]) + '\n', undefined, 'utf8');
}
} finally {
fs.closeSync(fd);
}
}
private [serializeTag]() {
return [
this.key,
this.tests,
]
}
}
function loadSnapshot(key: string): TestSnapshot {
const resolvedKey = resolveSnapshotReference(key);
const data = readJson(path.join(STORAGE_DIR, 'snapshots', resolvedKey));
if (data === null) {
throw new FancyError(`A snapshot named '${resolvedKey}' could not be loaded.`)
}
return deserialize(data);
}
function valueToString(value: any): string {
return inspect(value, {
colors: false,
depth: Infinity,
})
}
function compareTestSnapshots(actualSnapshot: TestSnapshot, expectedSnapshot: TestSnapshot) {
for (const actualTest of actualSnapshot.tests) {
const expectedTest = expectedSnapshot.tests.find(t => t.key === actualTest.key);
if (expectedTest === undefined) {
spinner.warn(`Test result '${actualTest.key}' has no correspoding result to compare against.`)
continue;
}
const diffs = diffLines(valueToString(actualTest.result), valueToString(expectedTest.result));
if (diffs.some(diff => diff.added || diff.removed)) {
diagnostics.add({
message: E_TESTS_DO_NOT_COMPARE,
severity: 'error',
node: actualTest,
});
for (const diff of diffs) {
let out = diff.value;
if (diff.removed) {
out = chalk.red(out);
} else if (diff.added) {
out = chalk.green(out);
}
process.stderr.write(out);
}
}
}
}
function isWhiteSpace(ch: string): boolean {
return /[\n\r\t ]/.test(ch);
}
interface TestFileMetadata {
type: string;
expect: string;
}
interface SimpleToken {
text: string;
startPos: TextPos;
endPos: TextPos;
}
const PREAMBLE_START = '---\n';
const PREAMBLE_END = '---\n';
function getPreamble(text: string): string {
if (!text.startsWith(PREAMBLE_START)) {
return '';
}
let out = '';
for (let i = PREAMBLE_START.length; i < text.length; i++) {
if (text.startsWith(PREAMBLE_END, i)) {
break;
}
out += text[i];
}
return out;
}
function* loadTests(filepath: string): IterableIterator<Test> {
const file = new TextFile(filepath);
const contents = file.getText('utf8');
const preamble = getPreamble(contents);
const metadata = yaml.safeLoad(preamble);
const parser = new CommonmarkParser();
const rootNode = parser.parse(contents);
if (rootNode.firstChild === null) {
return;
}
for (let node = rootNode.firstChild; node.next !== null; node = node.next) {
if (node.type === 'code_block') {
if (metadata['split-lines']) {
let startPos = new TextPos(0, node.sourcepos[0][0], node.sourcepos[0][1]);
startPos.advance('```')
startPos.advance(node.info! + '\n')
let endPos = startPos.clone();
for (const line of node.literal!.split('\n')) {
if (line.length > 0) {
yield new Test(new TextSpan(file, startPos.clone(), endPos.clone()), metadata.type, line, metadata);
startPos = endPos;
}
endPos.advance(line + '\n');
}
} else {
const startPos = new TextPos(0, node.sourcepos[0][0], node.sourcepos[0][1]);
const endPos = new TextPos(0, node.sourcepos[1][0], node.sourcepos[1][1]);
yield new Test(new TextSpan(file, startPos, endPos), metadata.type, node.literal!, metadata);
}
}
}
}
function resolveSnapshotReference(reference: string): string {
// If `name` directly refers to a snapshot, we don't have any more work to do.
if (fs.existsSync(path.join(STORAGE_DIR, 'snapshots', reference))) {
return reference;
}
// Try to read an alias, returning early if it was indeed found.
const snapshotKey = tryReadFileSync(path.join(STORAGE_DIR, 'aliases', reference));
if (snapshotKey !== null) {
return snapshotKey;
}
// We don't support any more refs at the moment, so we indicate failure
throw new FancyError(`A test snapshot named '${reference}' was not found.`)
}
function readJson(filename: string): Json | null {
const contents = tryReadFileSync(filename);
if (contents === null) {
return null;
}
return JSON.parse(contents);
}
function tryReadFileSync(filename: string, encoding: BufferEncoding = 'utf8'): string | null {
try {
return fs.readFileSync(filename, encoding);
} catch (e) {
if (e.code === 'ENOENT') {
return null
}
throw e;
}
}
function tryUnlinkSync(filepath: string): void {
try {
fs.unlinkSync(filepath);
} catch (e) {
if (e.code !== 'ENOENT') {
throw e;
}
}
}
function hash(value: Json) {
const hasher = crypto.createHash('sha256');
hasher.update(JSON.stringify(value));
return hasher.digest('hex');
}
type TestRunner = (test: Test) => Json;
const TEST_RUNNERS: MapLike<TestRunner> = {
scan(test: Test): any {
const diagnostics = new DiagnosticIndex;
const scanner = new Scanner(test.span.file, test.text, test.span.start.clone());
const tokens = []
while (true) {
const token = scanner.scan();
if (token.kind === SyntaxKind.EndOfFile) {
break;
}
tokens.push(token);
}
return {
diagnostics: [...diagnostics.getAllDiagnostics()],
tokens,
};
},
parse(test: Test): any {
const kind = test.data.expect ?? 'SourceFile';
const diagnostics = new DiagnosticIndex;
const parser = new Parser();
const tokens = new Scanner(test.span.file, test.text);
let results: Syntax[];
switch (kind) {
case 'SourceFile':
results = [ parser.parseSourceFile(tokens) ];
break;
case 'SourceElements':
results = parser.parseSourceElements(tokens);
break;
default:
throw new Error(`I did not know how to parse ${kind}`)
}
return {
diagnostics: [...diagnostics.getAllDiagnostics()],
results,
};
},
}
const TEST_REPORTERS = {
scan(test: Test) {
const printer = new DiagnosticPrinter();
for (const diagnostic of test.result!.diagnostics) {
printer.add(diagnostic as Diagnostic);
}
}
}
interface CommonArgv {
}
function createTestEngineFromArgs(args: CommonArgv) {
}
function wrapper<T extends object>(fn: (args: T) => number | undefined) {
return function (args: T) {
spinner = ora(`Initializing test session ...`).start();
let exitCode;
try {
exitCode = fn(args);
} catch (e) {
if (e instanceof FancyError) {
spinner.fail(e.message);
process.exit(1);
} else {
throw e;
}
}
process.exit(exitCode ?? 0);
}
}
yargs
.command(['$0 [pattern..]', 'run [pattern..]'], 'Run all tests on the current version of the compiler',
yargs => yargs
.array('pattern')
.describe('pattern', 'Only run the tests matching the given pattern')
.array('include')
.describe('include', 'Files to scan for tests')
.default('include', ['test/**/*.md'])
.array('exclude')
.describe('exclude', 'Files to never scan for tests')
.default('exclude', [])
.array('alias')
.describe('alias', 'Save the test results under the given alias')
.default('alias', [])
.string('storage-dir')
.alias('S', 'storage-dir')
.describe('storage-dir', 'The directory where test results will be stored')
.default('storage-dir', DEFAULT_STORAGE_DIR)
, wrapper(args => {
const testEngine = createTestEngineFromArgs(args);
// Load and run all tests, saving the results to disk
const snapshot = getSnapshotForCurrentSources(args)
if (snapshot === null || snapshot.hasFailedTests()) {
return 1;
}
for (const alias of args.alias) {
fs.mkdirpSync(path.join(STORAGE_DIR, 'aliases'))
fs.writeFileSync(path.join(STORAGE_DIR, 'aliases', alias), snapshot.key, 'utf8')
}
const expectedSnapshot = loadSnapshot('lkg');
compareTestSnapshots(snapshot, expectedSnapshot)
}
))
.command(['create-snapshot [alias..]'], 'Create a new snapshot from the output of the current compiler',
yargs => yargs
.array('alias')
.describe('alias', 'A user-friendly name to refer to the snapshot.')
.default('alias', [])
.array('include')
.describe('include', 'Files to scan for tests')
.default('include', ['test/**/*.md'])
.array('exclude')
.describe('exclude', 'Files to never scan for tests')
.default('exclude', [])
, wrapper(args => {
// Load and run all tests, saving the results to disk
const snapshot = getSnapshotForCurrentSources(args);
if (snapshot === null || snapshot.hasFailedTests()) {
return 1;
}
// Add any aliases that might have been requested for this snapshot
fs.mkdirpSync(path.join(STORAGE_DIR, 'aliases'));
for (const alias of args.alias) {
fs.writeFileSync(path.join(STORAGE_DIR, 'aliases', alias), snapshot.key, 'utf8')
}
// Output the unqiue identifier for this snapshot
spinner.succeed(`${snapshot.key} created.`)
}
))
.command('compare [expected] [actual]', 'Compare the output of two given tests',
yargs => yargs
.string('actual')
.describe('actual', 'A reference to a snapshot that will be checked')
.string('expected')
.describe('expected', 'A reference to a test snapshot that will serve as the ground truth')
, wrapper(args => {
let expectedKey = args.expected ?? 'lkg';
let expectedSnapshot = null;
let actualKey = args.actual ?? null;
let actualSnapshot = null;
if (args.actual === undefined) {
// Load and run all tests, saving the results to disk
const snapshot = getSnapshotForCurrentSources(args);
if (snapshot === null) {
return 1;
}
actualSnapshot = snapshot;
actualKey = snapshot.key;
}
if (expectedSnapshot === null) {
expectedSnapshot = loadSnapshot(expectedKey);
}
if (actualSnapshot === null) {
actualSnapshot = loadSnapshot(actualKey!);
}
spinner.info(`Comparing test snapshot ${actualKey} to ${expectedKey}`)
compareTestSnapshots(actualSnapshot, expectedSnapshot);
}
))
.command( 'clean', 'Clean up test snapshots that are unused',
yargs => yargs
.string('keep')
.array('keep')
.default('keep', ['lkg'])
.describe('keep', 'Keep the given aliases and anything they refer to')
, wrapper(args => {
const snapshotsToKeep = new Set();
for (const alias of fs.readdirSync(path.join(STORAGE_DIR, 'aliases'))) {
if (args.keep.indexOf(alias) !== -1) {
const snapshotKey = tryReadFileSync(path.join(STORAGE_DIR, 'aliases', alias));
if (snapshotKey !== null && !fs.existsSync(path.join(STORAGE_DIR, 'snapshots', snapshotKey))) {
spinner.info(`Removing dangling alias ${alias} because the test snapshot it refers to is missing.`)
tryUnlinkSync(path.join(STORAGE_DIR, 'aliases', alias));
} else {
snapshotsToKeep.add(snapshotKey);
}
}
}
for (const snapshotKey of fs.readdirSync(path.join(STORAGE_DIR, 'snapshots'))) {
if (!snapshotsToKeep.has(snapshotKey)) {
fs.removeSync(path.join(STORAGE_DIR, 'snapshots', snapshotKey));
}
}
spinner.succeed('Cleanup complete.')
return 0;
}
))
.version()
.help()
.argv;

File diff suppressed because it is too large Load diff

View file

@ -1,29 +0,0 @@
export interface ParseOptions {
[key: string]: any;
}
export function parse(input: string, opts?: ParseOptions): any;
export interface Location {
line: number;
column: number;
offset: number;
}
interface LocationRange {
start: Location,
end: Location
}
export class SyntaxError {
line: number;
column: number;
offset: number;
location: LocationRange;
expected:any[];
found:any;
name:string;
message:string;
}

View file

@ -1,513 +0,0 @@
// PEG.js Grammar
// ==============
//
// PEG.js grammar syntax is designed to be simple, expressive, and similar to
// JavaScript where possible. This means that many rules, especially in the
// lexical part, are based on the grammar from ECMA-262, 5.1 Edition [1]. Some
// are directly taken or adapted from the JavaScript example grammar (see
// examples/javascript.pegjs).
//
// Limitations:
//
// * Non-BMP characters are completely ignored to avoid surrogate pair
// handling.
//
// * One can create identifiers containing illegal characters using Unicode
// escape sequences. For example, "abcd\u0020efgh" is not a valid
// identifier, but it is accepted by the parser.
//
// Both limitations could be resolved, but the costs would likely outweigh
// the benefits.
//
// [1] http://www.ecma-international.org/publications/standards/Ecma-262.htm
{
// Used as a shorthand property name for `LabeledExpression`
const pick = true;
// Used by `LabelIdentifier` to disallow the use of certain words as labels
const RESERVED_WORDS = {};
// Populate `RESERVED_WORDS` using the optional option `reservedWords`
const reservedWords = options.reservedWords || util.reservedWords;
if ( Array.isArray( reservedWords ) ) reservedWords.forEach( word => {
RESERVED_WORDS[ word ] = true;
} );
// Helper to construct a new AST Node
function createNode( type, details ) {
const node = new ast.Node( type, location() );
if ( details === null ) return node;
util.extend( node, details );
return util.enforceFastProperties( node );
}
// Used by `addComment` to store comments for the Grammar AST
const comments = options.extractComments ? {} : null;
// Helper that collects all the comments to pass to the Grammar AST
function addComment( text, multiline ) {
if ( options.extractComments ) {
const loc = location();
comments[ loc.start.offset ] = {
text: text,
multiline: multiline,
location: loc,
};
}
return text;
}
}
// ---- Syntactic Grammar -----
Grammar
= __ initializer:(@Initializer __)? rules:(@Rule __)+ {
return new ast.Grammar( initializer, rules, comments, location() );
}
Initializer
= code:CodeBlock EOS {
return createNode( "initializer", { code } );
}
Rule
= name:Identifier __ displayName:(@StringLiteral __)? "=" __ expression:Expression EOS {
if ( displayName )
expression = createNode( "named", {
name: displayName,
expression: expression,
} );
return createNode( "rule", { name, expression } );
}
Expression
= ChoiceExpression
ChoiceExpression
= head:ActionExpression tail:(__ "/" __ @ActionExpression)* {
if ( tail.length === 0 ) return head;
return createNode( "choice", {
alternatives: [ head ].concat( tail ),
} );
}
ActionExpression
= expression:SequenceExpression code:(__ @CodeBlock)? {
if ( code === null ) return expression;
return createNode( "action", { expression, code } );
}
SequenceExpression
= head:LabeledExpression tail:(__ @LabeledExpression)* {
let elements = [ head ];
if ( tail.length === 0 ) {
if ( head.type !== "labeled" || ! head.pick ) return head;
} else {
elements = elements.concat( tail );
}
return createNode( "sequence", { elements } );
}
LabeledExpression
= "@" label:LabelIdentifier? __ expression:PrefixedExpression {
return createNode( "labeled", { pick, label, expression } );
}
/ label:LabelIdentifier __ expression:PrefixedExpression {
return createNode( "labeled", { label, expression } );
}
/ PrefixedExpression
LabelIdentifier
= name:Identifier __ ":" {
if ( RESERVED_WORDS[ name ] !== true ) return name;
error( `Label can't be a reserved word "${ name }".`, location() );
}
PrefixedExpression
= operator:PrefixedOperator __ expression:SuffixedExpression {
return createNode( operator, { expression } );
}
/ SuffixedExpression
PrefixedOperator
= "$" { return "text"; }
/ "&" { return "simple_and"; }
/ "!" { return "simple_not"; }
SuffixedExpression
= expression:PrimaryExpression __ operator:SuffixedOperator {
return createNode( operator, { expression } );
}
/ PrimaryExpression
SuffixedOperator
= "?" { return "optional"; }
/ "*" { return "zero_or_more"; }
/ "+" { return "one_or_more"; }
PrimaryExpression
= LiteralMatcher
/ CharacterClassMatcher
/ AnyMatcher
/ RuleReferenceExpression
/ SemanticPredicateExpression
/ "(" __ e:Expression __ ")" {
// The purpose of the "group" AST node is just to isolate label scope. We
// don't need to put it around nodes that can't contain any labels or
// nodes that already isolate label scope themselves.
if ( e.type !== "labeled" && e.type !== "sequence" ) return e;
// This leaves us with "labeled" and "sequence".
return createNode( "group", { expression: e } );
}
RuleReferenceExpression
= name:Identifier !(__ (StringLiteral __)? "=") {
return createNode( "rule_ref", { name } );
}
SemanticPredicateExpression
= operator:SemanticPredicateOperator __ code:CodeBlock {
return createNode( operator, { code } );
}
SemanticPredicateOperator
= "&" { return "semantic_and"; }
/ "!" { return "semantic_not"; }
// ---- Lexical Grammar -----
SourceCharacter
= .
WhiteSpace "whitespace"
= "\t"
/ "\v"
/ "\f"
/ " "
/ "\u00A0"
/ "\uFEFF"
/ Zs
LineTerminator
= [\n\r\u2028\u2029]
LineTerminatorSequence "end of line"
= "\n"
/ "\r\n"
/ "\r"
/ "\u2028"
/ "\u2029"
Comment "comment"
= MultiLineComment
/ SingleLineComment
MultiLineComment
= "/*" comment:$(!"*/" SourceCharacter)* "*/" {
return addComment( comment, true );
}
MultiLineCommentNoLineTerminator
= "/*" comment:$(!("*/" / LineTerminator) SourceCharacter)* "*/" {
return addComment( comment, true );
}
SingleLineComment
= "//" comment:$(!LineTerminator SourceCharacter)* {
return addComment( comment, false );
}
Identifier "identifier"
= head:IdentifierStart tail:IdentifierPart* {
return head + tail.join("");
}
IdentifierStart
= UnicodeLetter
/ "$"
/ "_"
/ "\\" @UnicodeEscapeSequence
IdentifierPart
= IdentifierStart
/ UnicodeCombiningMark
/ UnicodeDigit
/ UnicodeConnectorPunctuation
/ "\u200C"
/ "\u200D"
UnicodeLetter
= Lu
/ Ll
/ Lt
/ Lm
/ Lo
/ Nl
UnicodeCombiningMark
= Mn
/ Mc
UnicodeDigit
= Nd
UnicodeConnectorPunctuation
= Pc
LiteralMatcher "literal"
= value:StringLiteral ignoreCase:"i"? {
return createNode( "literal", {
value: value,
ignoreCase: ignoreCase !== null,
} );
}
StringLiteral "string"
= '"' chars:DoubleStringCharacter* '"' { return chars.join(""); }
/ "'" chars:SingleStringCharacter* "'" { return chars.join(""); }
DoubleStringCharacter
= !('"' / "\\" / LineTerminator) @SourceCharacter
/ "\\" @EscapeSequence
/ LineContinuation
SingleStringCharacter
= !("'" / "\\" / LineTerminator) @SourceCharacter
/ "\\" @EscapeSequence
/ LineContinuation
CharacterClassMatcher "character class"
= "[" inverted:"^"? parts:CharacterPart* "]" ignoreCase:"i"? {
return createNode( "class", {
parts: parts.filter( part => part !== "" ),
inverted: inverted !== null,
ignoreCase: ignoreCase !== null,
} );
}
CharacterPart
= ClassCharacterRange
/ ClassCharacter
ClassCharacterRange
= begin:ClassCharacter "-" end:ClassCharacter {
if ( begin.charCodeAt( 0 ) > end.charCodeAt( 0 ) )
error( "Invalid character range: " + text() + "." );
return [ begin, end ];
}
ClassCharacter
= !("]" / "\\" / LineTerminator) @SourceCharacter
/ "\\" @EscapeSequence
/ LineContinuation
LineContinuation
= "\\" LineTerminatorSequence { return ""; }
EscapeSequence
= CharacterEscapeSequence
/ "0" !DecimalDigit { return "\0"; }
/ HexEscapeSequence
/ UnicodeEscapeSequence
CharacterEscapeSequence
= SingleEscapeCharacter
/ NonEscapeCharacter
SingleEscapeCharacter
= "'"
/ '"'
/ "\\"
/ "b" { return "\b"; }
/ "f" { return "\f"; }
/ "n" { return "\n"; }
/ "r" { return "\r"; }
/ "t" { return "\t"; }
/ "v" { return "\v"; }
NonEscapeCharacter
= !(EscapeCharacter / LineTerminator) @SourceCharacter
EscapeCharacter
= SingleEscapeCharacter
/ DecimalDigit
/ "x"
/ "u"
HexEscapeSequence
= "x" digits:$(HexDigit HexDigit) {
return String.fromCharCode( parseInt( digits, 16 ) );
}
UnicodeEscapeSequence
= "u" digits:$(HexDigit HexDigit HexDigit HexDigit) {
return String.fromCharCode( parseInt( digits, 16 ) );
}
DecimalDigit
= [0-9]
HexDigit
= [0-9a-f]i
AnyMatcher
= "." {
return createNode( "any" );
}
CodeBlock "code block"
= "{" @Code "}"
/ "{" { error("Unbalanced brace."); }
Code
= $((![{}] SourceCharacter)+ / "{" Code "}")*
// Unicode Character Categories
//
// Extracted from the following Unicode Character Database file:
//
// http://www.unicode.org/Public/11.0.0/ucd/extracted/DerivedGeneralCategory.txt
//
// Unix magic used:
//
// grep "; $CATEGORY" DerivedGeneralCategory.txt | # Filter characters
// cut -f1 -d " " | # Extract code points
// grep -v '[0-9a-fA-F]\{5\}' | # Exclude non-BMP characters
// sed -e 's/\.\./-/' | # Adjust formatting
// sed -e 's/\([0-9a-fA-F]\{4\}\)/\\u\1/g' | # Adjust formatting
// tr -d '\n' # Join lines
//
// ECMA-262 allows using Unicode 3.0 or later, version 8.0.0 was the latest one
// at the time of writing.
//
// Non-BMP characters are completely ignored to avoid surrogate pair handling
// (detecting surrogate pairs isn't possible with a simple character class and
// other methods would degrade performance). I don't consider it a big deal as
// even parsers in JavaScript engines of common browsers seem to ignore them.
// Letter, Lowercase
Ll = [\u0061-\u007A\u00B5\u00DF-\u00F6\u00F8-\u00FF\u0101\u0103\u0105\u0107\u0109\u010B\u010D\u010F\u0111\u0113\u0115\u0117\u0119\u011B\u011D\u011F\u0121\u0123\u0125\u0127\u0129\u012B\u012D\u012F\u0131\u0133\u0135\u0137-\u0138\u013A\u013C\u013E\u0140\u0142\u0144\u0146\u0148-\u0149\u014B\u014D\u014F\u0151\u0153\u0155\u0157\u0159\u015B\u015D\u015F\u0161\u0163\u0165\u0167\u0169\u016B\u016D\u016F\u0171\u0173\u0175\u0177\u017A\u017C\u017E-\u0180\u0183\u0185\u0188\u018C-\u018D\u0192\u0195\u0199-\u019B\u019E\u01A1\u01A3\u01A5\u01A8\u01AA-\u01AB\u01AD\u01B0\u01B4\u01B6\u01B9-\u01BA\u01BD-\u01BF\u01C6\u01C9\u01CC\u01CE\u01D0\u01D2\u01D4\u01D6\u01D8\u01DA\u01DC-\u01DD\u01DF\u01E1\u01E3\u01E5\u01E7\u01E9\u01EB\u01ED\u01EF-\u01F0\u01F3\u01F5\u01F9\u01FB\u01FD\u01FF\u0201\u0203\u0205\u0207\u0209\u020B\u020D\u020F\u0211\u0213\u0215\u0217\u0219\u021B\u021D\u021F\u0221\u0223\u0225\u0227\u0229\u022B\u022D\u022F\u0231\u0233-\u0239\u023C\u023F-\u0240\u0242\u0247\u0249\u024B\u024D\u024F-\u0293\u0295-\u02AF\u0371\u0373\u0377\u037B-\u037D\u0390\u03AC-\u03CE\u03D0-\u03D1\u03D5-\u03D7\u03D9\u03DB\u03DD\u03DF\u03E1\u03E3\u03E5\u03E7\u03E9\u03EB\u03ED\u03EF-\u03F3\u03F5\u03F8\u03FB-\u03FC\u0430-\u045F\u0461\u0463\u0465\u0467\u0469\u046B\u046D\u046F\u0471\u0473\u0475\u0477\u0479\u047B\u047D\u047F\u0481\u048B\u048D\u048F\u0491\u0493\u0495\u0497\u0499\u049B\u049D\u049F\u04A1\u04A3\u04A5\u04A7\u04A9\u04AB\u04AD\u04AF\u04B1\u04B3\u04B5\u04B7\u04B9\u04BB\u04BD\u04BF\u04C2\u04C4\u04C6\u04C8\u04CA\u04CC\u04CE-\u04CF\u04D1\u04D3\u04D5\u04D7\u04D9\u04DB\u04DD\u04DF\u04E1\u04E3\u04E5\u04E7\u04E9\u04EB\u04ED\u04EF\u04F1\u04F3\u04F5\u04F7\u04F9\u04FB\u04FD\u04FF\u0501\u0503\u0505\u0507\u0509\u050B\u050D\u050F\u0511\u0513\u0515\u0517\u0519\u051B\u051D\u051F\u0521\u0523\u0525\u0527\u0529\u052B\u052D\u052F\u0560-\u0588\u10D0-\u10FA\u10FD-\u10FF\u13F8-\u13FD\u1C80-\u1C88\u1D00-\u1D2B\u1D6B-\u1D77\u1D79-\u1D9A\u1E01\u1E03\u1E05\u1E07\u1E09\u1E0B\u1E0D\u1E0F\u1E11\u1E13\u1E15\u1E17\u1E19\u1E1B\u1E1D\u1E1F\u1E21\u1E23\u1E25\u1E27\u1E29\u1E2B\u1E2D\u1E2F\u1E31\u1E33\u1E35\u1E37\u1E39\u1E3B\u1E3D\u1E3F\u1E41\u1E43\u1E45\u1E47\u1E49\u1E4B\u1E4D\u1E4F\u1E51\u1E53\u1E55\u1E57\u1E59\u1E5B\u1E5D\u1E5F\u1E61\u1E63\u1E65\u1E67\u1E69\u1E6B\u1E6D\u1E6F\u1E71\u1E73\u1E75\u1E77\u1E79\u1E7B\u1E7D\u1E7F\u1E81\u1E83\u1E85\u1E87\u1E89\u1E8B\u1E8D\u1E8F\u1E91\u1E93\u1E95-\u1E9D\u1E9F\u1EA1\u1EA3\u1EA5\u1EA7\u1EA9\u1EAB\u1EAD\u1EAF\u1EB1\u1EB3\u1EB5\u1EB7\u1EB9\u1EBB\u1EBD\u1EBF\u1EC1\u1EC3\u1EC5\u1EC7\u1EC9\u1ECB\u1ECD\u1ECF\u1ED1\u1ED3\u1ED5\u1ED7\u1ED9\u1EDB\u1EDD\u1EDF\u1EE1\u1EE3\u1EE5\u1EE7\u1EE9\u1EEB\u1EED\u1EEF\u1EF1\u1EF3\u1EF5\u1EF7\u1EF9\u1EFB\u1EFD\u1EFF-\u1F07\u1F10-\u1F15\u1F20-\u1F27\u1F30-\u1F37\u1F40-\u1F45\u1F50-\u1F57\u1F60-\u1F67\u1F70-\u1F7D\u1F80-\u1F87\u1F90-\u1F97\u1FA0-\u1FA7\u1FB0-\u1FB4\u1FB6-\u1FB7\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FC7\u1FD0-\u1FD3\u1FD6-\u1FD7\u1FE0-\u1FE7\u1FF2-\u1FF4\u1FF6-\u1FF7\u210A\u210E-\u210F\u2113\u212F\u2134\u2139\u213C-\u213D\u2146-\u2149\u214E\u2184\u2C30-\u2C5E\u2C61\u2C65-\u2C66\u2C68\u2C6A\u2C6C\u2C71\u2C73-\u2C74\u2C76-\u2C7B\u2C81\u2C83\u2C85\u2C87\u2C89\u2C8B\u2C8D\u2C8F\u2C91\u2C93\u2C95\u2C97\u2C99\u2C9B\u2C9D\u2C9F\u2CA1\u2CA3\u2CA5\u2CA7\u2CA9\u2CAB\u2CAD\u2CAF\u2CB1\u2CB3\u2CB5\u2CB7\u2CB9\u2CBB\u2CBD\u2CBF\u2CC1\u2CC3\u2CC5\u2CC7\u2CC9\u2CCB\u2CCD\u2CCF\u2CD1\u2CD3\u2CD5\u2CD7\u2CD9\u2CDB\u2CDD\u2CDF\u2CE1\u2CE3-\u2CE4\u2CEC\u2CEE\u2CF3\u2D00-\u2D25\u2D27\u2D2D\uA641\uA643\uA645\uA647\uA649\uA64B\uA64D\uA64F\uA651\uA653\uA655\uA657\uA659\uA65B\uA65D\uA65F\uA661\uA663\uA665\uA667\uA669\uA66B\uA66D\uA681\uA683\uA685\uA687\uA689\uA68B\uA68D\uA68F\uA691\uA693\uA695\uA697\uA699\uA69B\uA723\uA725\uA727\uA729\uA72B\uA72D\uA72F-\uA731\uA733\uA735\uA737\uA739\uA73B\uA73D\uA73F\uA741\uA743\uA745\uA747\uA749\uA74B\uA74D\uA74F\uA751\uA753\uA755\uA757\uA759\uA75B\uA75D\uA75F\uA761\uA763\uA765\uA767\uA769\uA76B\uA76D\uA76F\uA771-\uA778\uA77A\uA77C\uA77F\uA781\uA783\uA785\uA787\uA78C\uA78E\uA791\uA793-\uA795\uA797\uA799\uA79B\uA79D\uA79F\uA7A1\uA7A3\uA7A5\uA7A7\uA7A9\uA7AF\uA7B5\uA7B7\uA7B9\uA7FA\uAB30-\uAB5A\uAB60-\uAB65\uAB70-\uABBF\uFB00-\uFB06\uFB13-\uFB17\uFF41-\uFF5A]
// Letter, Modifier
Lm = [\u02B0-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0374\u037A\u0559\u0640\u06E5-\u06E6\u07F4-\u07F5\u07FA\u081A\u0824\u0828\u0971\u0E46\u0EC6\u10FC\u17D7\u1843\u1AA7\u1C78-\u1C7D\u1D2C-\u1D6A\u1D78\u1D9B-\u1DBF\u2071\u207F\u2090-\u209C\u2C7C-\u2C7D\u2D6F\u2E2F\u3005\u3031-\u3035\u303B\u309D-\u309E\u30FC-\u30FE\uA015\uA4F8-\uA4FD\uA60C\uA67F\uA69C-\uA69D\uA717-\uA71F\uA770\uA788\uA7F8-\uA7F9\uA9CF\uA9E6\uAA70\uAADD\uAAF3-\uAAF4\uAB5C-\uAB5F\uFF70\uFF9E-\uFF9F]
// Letter, Other
Lo = [\u00AA\u00BA\u01BB\u01C0-\u01C3\u0294\u05D0-\u05EA\u05EF-\u05F2\u0620-\u063F\u0641-\u064A\u066E-\u066F\u0671-\u06D3\u06D5\u06EE-\u06EF\u06FA-\u06FC\u06FF\u0710\u0712-\u072F\u074D-\u07A5\u07B1\u07CA-\u07EA\u0800-\u0815\u0840-\u0858\u0860-\u086A\u08A0-\u08B4\u08B6-\u08BD\u0904-\u0939\u093D\u0950\u0958-\u0961\u0972-\u0980\u0985-\u098C\u098F-\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2\u09B6-\u09B9\u09BD\u09CE\u09DC-\u09DD\u09DF-\u09E1\u09F0-\u09F1\u09FC\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\u0AF9\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-\u0C39\u0C3D\u0C58-\u0C5A\u0C60-\u0C61\u0C80\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-\u0CB9\u0CBD\u0CDE\u0CE0-\u0CE1\u0CF1-\u0CF2\u0D05-\u0D0C\u0D0E-\u0D10\u0D12-\u0D3A\u0D3D\u0D4E\u0D54-\u0D56\u0D5F-\u0D61\u0D7A-\u0D7F\u0D85-\u0D96\u0D9A-\u0DB1\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0E01-\u0E30\u0E32-\u0E33\u0E40-\u0E45\u0E81-\u0E82\u0E84\u0E87-\u0E88\u0E8A\u0E8D\u0E94-\u0E97\u0E99-\u0E9F\u0EA1-\u0EA3\u0EA5\u0EA7\u0EAA-\u0EAB\u0EAD-\u0EB0\u0EB2-\u0EB3\u0EBD\u0EC0-\u0EC4\u0EDC-\u0EDF\u0F00\u0F40-\u0F47\u0F49-\u0F6C\u0F88-\u0F8C\u1000-\u102A\u103F\u1050-\u1055\u105A-\u105D\u1061\u1065-\u1066\u106E-\u1070\u1075-\u1081\u108E\u1100-\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\u1401-\u166C\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u16F1-\u16F8\u1700-\u170C\u170E-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176C\u176E-\u1770\u1780-\u17B3\u17DC\u1820-\u1842\u1844-\u1878\u1880-\u1884\u1887-\u18A8\u18AA\u18B0-\u18F5\u1900-\u191E\u1950-\u196D\u1970-\u1974\u1980-\u19AB\u19B0-\u19C9\u1A00-\u1A16\u1A20-\u1A54\u1B05-\u1B33\u1B45-\u1B4B\u1B83-\u1BA0\u1BAE-\u1BAF\u1BBA-\u1BE5\u1C00-\u1C23\u1C4D-\u1C4F\u1C5A-\u1C77\u1CE9-\u1CEC\u1CEE-\u1CF1\u1CF5-\u1CF6\u2135-\u2138\u2D30-\u2D67\u2D80-\u2D96\u2DA0-\u2DA6\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6\u2DC8-\u2DCE\u2DD0-\u2DD6\u2DD8-\u2DDE\u3006\u303C\u3041-\u3096\u309F\u30A1-\u30FA\u30FF\u3105-\u312F\u3131-\u318E\u31A0-\u31BA\u31F0-\u31FF\u3400-\u4DB5\u4E00-\u9FEF\uA000-\uA014\uA016-\uA48C\uA4D0-\uA4F7\uA500-\uA60B\uA610-\uA61F\uA62A-\uA62B\uA66E\uA6A0-\uA6E5\uA78F\uA7F7\uA7FB-\uA801\uA803-\uA805\uA807-\uA80A\uA80C-\uA822\uA840-\uA873\uA882-\uA8B3\uA8F2-\uA8F7\uA8FB\uA8FD-\uA8FE\uA90A-\uA925\uA930-\uA946\uA960-\uA97C\uA984-\uA9B2\uA9E0-\uA9E4\uA9E7-\uA9EF\uA9FA-\uA9FE\uAA00-\uAA28\uAA40-\uAA42\uAA44-\uAA4B\uAA60-\uAA6F\uAA71-\uAA76\uAA7A\uAA7E-\uAAAF\uAAB1\uAAB5-\uAAB6\uAAB9-\uAABD\uAAC0\uAAC2\uAADB-\uAADC\uAAE0-\uAAEA\uAAF2\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E\uABC0-\uABE2\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFA6D\uFA70-\uFAD9\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\uFF66-\uFF6F\uFF71-\uFF9D\uFFA0-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF\uFFD2-\uFFD7\uFFDA-\uFFDC]
// Letter, Titlecase
Lt = [\u01C5\u01C8\u01CB\u01F2\u1F88-\u1F8F\u1F98-\u1F9F\u1FA8-\u1FAF\u1FBC\u1FCC\u1FFC]
// Letter, Uppercase
Lu = [\u0041-\u005A\u00C0-\u00D6\u00D8-\u00DE\u0100\u0102\u0104\u0106\u0108\u010A\u010C\u010E\u0110\u0112\u0114\u0116\u0118\u011A\u011C\u011E\u0120\u0122\u0124\u0126\u0128\u012A\u012C\u012E\u0130\u0132\u0134\u0136\u0139\u013B\u013D\u013F\u0141\u0143\u0145\u0147\u014A\u014C\u014E\u0150\u0152\u0154\u0156\u0158\u015A\u015C\u015E\u0160\u0162\u0164\u0166\u0168\u016A\u016C\u016E\u0170\u0172\u0174\u0176\u0178-\u0179\u017B\u017D\u0181-\u0182\u0184\u0186-\u0187\u0189-\u018B\u018E-\u0191\u0193-\u0194\u0196-\u0198\u019C-\u019D\u019F-\u01A0\u01A2\u01A4\u01A6-\u01A7\u01A9\u01AC\u01AE-\u01AF\u01B1-\u01B3\u01B5\u01B7-\u01B8\u01BC\u01C4\u01C7\u01CA\u01CD\u01CF\u01D1\u01D3\u01D5\u01D7\u01D9\u01DB\u01DE\u01E0\u01E2\u01E4\u01E6\u01E8\u01EA\u01EC\u01EE\u01F1\u01F4\u01F6-\u01F8\u01FA\u01FC\u01FE\u0200\u0202\u0204\u0206\u0208\u020A\u020C\u020E\u0210\u0212\u0214\u0216\u0218\u021A\u021C\u021E\u0220\u0222\u0224\u0226\u0228\u022A\u022C\u022E\u0230\u0232\u023A-\u023B\u023D-\u023E\u0241\u0243-\u0246\u0248\u024A\u024C\u024E\u0370\u0372\u0376\u037F\u0386\u0388-\u038A\u038C\u038E-\u038F\u0391-\u03A1\u03A3-\u03AB\u03CF\u03D2-\u03D4\u03D8\u03DA\u03DC\u03DE\u03E0\u03E2\u03E4\u03E6\u03E8\u03EA\u03EC\u03EE\u03F4\u03F7\u03F9-\u03FA\u03FD-\u042F\u0460\u0462\u0464\u0466\u0468\u046A\u046C\u046E\u0470\u0472\u0474\u0476\u0478\u047A\u047C\u047E\u0480\u048A\u048C\u048E\u0490\u0492\u0494\u0496\u0498\u049A\u049C\u049E\u04A0\u04A2\u04A4\u04A6\u04A8\u04AA\u04AC\u04AE\u04B0\u04B2\u04B4\u04B6\u04B8\u04BA\u04BC\u04BE\u04C0-\u04C1\u04C3\u04C5\u04C7\u04C9\u04CB\u04CD\u04D0\u04D2\u04D4\u04D6\u04D8\u04DA\u04DC\u04DE\u04E0\u04E2\u04E4\u04E6\u04E8\u04EA\u04EC\u04EE\u04F0\u04F2\u04F4\u04F6\u04F8\u04FA\u04FC\u04FE\u0500\u0502\u0504\u0506\u0508\u050A\u050C\u050E\u0510\u0512\u0514\u0516\u0518\u051A\u051C\u051E\u0520\u0522\u0524\u0526\u0528\u052A\u052C\u052E\u0531-\u0556\u10A0-\u10C5\u10C7\u10CD\u13A0-\u13F5\u1C90-\u1CBA\u1CBD-\u1CBF\u1E00\u1E02\u1E04\u1E06\u1E08\u1E0A\u1E0C\u1E0E\u1E10\u1E12\u1E14\u1E16\u1E18\u1E1A\u1E1C\u1E1E\u1E20\u1E22\u1E24\u1E26\u1E28\u1E2A\u1E2C\u1E2E\u1E30\u1E32\u1E34\u1E36\u1E38\u1E3A\u1E3C\u1E3E\u1E40\u1E42\u1E44\u1E46\u1E48\u1E4A\u1E4C\u1E4E\u1E50\u1E52\u1E54\u1E56\u1E58\u1E5A\u1E5C\u1E5E\u1E60\u1E62\u1E64\u1E66\u1E68\u1E6A\u1E6C\u1E6E\u1E70\u1E72\u1E74\u1E76\u1E78\u1E7A\u1E7C\u1E7E\u1E80\u1E82\u1E84\u1E86\u1E88\u1E8A\u1E8C\u1E8E\u1E90\u1E92\u1E94\u1E9E\u1EA0\u1EA2\u1EA4\u1EA6\u1EA8\u1EAA\u1EAC\u1EAE\u1EB0\u1EB2\u1EB4\u1EB6\u1EB8\u1EBA\u1EBC\u1EBE\u1EC0\u1EC2\u1EC4\u1EC6\u1EC8\u1ECA\u1ECC\u1ECE\u1ED0\u1ED2\u1ED4\u1ED6\u1ED8\u1EDA\u1EDC\u1EDE\u1EE0\u1EE2\u1EE4\u1EE6\u1EE8\u1EEA\u1EEC\u1EEE\u1EF0\u1EF2\u1EF4\u1EF6\u1EF8\u1EFA\u1EFC\u1EFE\u1F08-\u1F0F\u1F18-\u1F1D\u1F28-\u1F2F\u1F38-\u1F3F\u1F48-\u1F4D\u1F59\u1F5B\u1F5D\u1F5F\u1F68-\u1F6F\u1FB8-\u1FBB\u1FC8-\u1FCB\u1FD8-\u1FDB\u1FE8-\u1FEC\u1FF8-\u1FFB\u2102\u2107\u210B-\u210D\u2110-\u2112\u2115\u2119-\u211D\u2124\u2126\u2128\u212A-\u212D\u2130-\u2133\u213E-\u213F\u2145\u2183\u2C00-\u2C2E\u2C60\u2C62-\u2C64\u2C67\u2C69\u2C6B\u2C6D-\u2C70\u2C72\u2C75\u2C7E-\u2C80\u2C82\u2C84\u2C86\u2C88\u2C8A\u2C8C\u2C8E\u2C90\u2C92\u2C94\u2C96\u2C98\u2C9A\u2C9C\u2C9E\u2CA0\u2CA2\u2CA4\u2CA6\u2CA8\u2CAA\u2CAC\u2CAE\u2CB0\u2CB2\u2CB4\u2CB6\u2CB8\u2CBA\u2CBC\u2CBE\u2CC0\u2CC2\u2CC4\u2CC6\u2CC8\u2CCA\u2CCC\u2CCE\u2CD0\u2CD2\u2CD4\u2CD6\u2CD8\u2CDA\u2CDC\u2CDE\u2CE0\u2CE2\u2CEB\u2CED\u2CF2\uA640\uA642\uA644\uA646\uA648\uA64A\uA64C\uA64E\uA650\uA652\uA654\uA656\uA658\uA65A\uA65C\uA65E\uA660\uA662\uA664\uA666\uA668\uA66A\uA66C\uA680\uA682\uA684\uA686\uA688\uA68A\uA68C\uA68E\uA690\uA692\uA694\uA696\uA698\uA69A\uA722\uA724\uA726\uA728\uA72A\uA72C\uA72E\uA732\uA734\uA736\uA738\uA73A\uA73C\uA73E\uA740\uA742\uA744\uA746\uA748\uA74A\uA74C\uA74E\uA750\uA752\uA754\uA756\uA758\uA75A\uA75C\uA75E\uA760\uA762\uA764\uA766\uA768\uA76A\uA76C\uA76E\uA779\uA77B\uA77D-\uA77E\uA780\uA782\uA784\uA786\uA78B\uA78D\uA790\uA792\uA796\uA798\uA79A\uA79C\uA79E\uA7A0\uA7A2\uA7A4\uA7A6\uA7A8\uA7AA-\uA7AE\uA7B0-\uA7B4\uA7B6\uA7B8\uFF21-\uFF3A]
// Mark, Spacing Combining
Mc = [\u0903\u093B\u093E-\u0940\u0949-\u094C\u094E-\u094F\u0982-\u0983\u09BE-\u09C0\u09C7-\u09C8\u09CB-\u09CC\u09D7\u0A03\u0A3E-\u0A40\u0A83\u0ABE-\u0AC0\u0AC9\u0ACB-\u0ACC\u0B02-\u0B03\u0B3E\u0B40\u0B47-\u0B48\u0B4B-\u0B4C\u0B57\u0BBE-\u0BBF\u0BC1-\u0BC2\u0BC6-\u0BC8\u0BCA-\u0BCC\u0BD7\u0C01-\u0C03\u0C41-\u0C44\u0C82-\u0C83\u0CBE\u0CC0-\u0CC4\u0CC7-\u0CC8\u0CCA-\u0CCB\u0CD5-\u0CD6\u0D02-\u0D03\u0D3E-\u0D40\u0D46-\u0D48\u0D4A-\u0D4C\u0D57\u0D82-\u0D83\u0DCF-\u0DD1\u0DD8-\u0DDF\u0DF2-\u0DF3\u0F3E-\u0F3F\u0F7F\u102B-\u102C\u1031\u1038\u103B-\u103C\u1056-\u1057\u1062-\u1064\u1067-\u106D\u1083-\u1084\u1087-\u108C\u108F\u109A-\u109C\u17B6\u17BE-\u17C5\u17C7-\u17C8\u1923-\u1926\u1929-\u192B\u1930-\u1931\u1933-\u1938\u1A19-\u1A1A\u1A55\u1A57\u1A61\u1A63-\u1A64\u1A6D-\u1A72\u1B04\u1B35\u1B3B\u1B3D-\u1B41\u1B43-\u1B44\u1B82\u1BA1\u1BA6-\u1BA7\u1BAA\u1BE7\u1BEA-\u1BEC\u1BEE\u1BF2-\u1BF3\u1C24-\u1C2B\u1C34-\u1C35\u1CE1\u1CF2-\u1CF3\u1CF7\u302E-\u302F\uA823-\uA824\uA827\uA880-\uA881\uA8B4-\uA8C3\uA952-\uA953\uA983\uA9B4-\uA9B5\uA9BA-\uA9BB\uA9BD-\uA9C0\uAA2F-\uAA30\uAA33-\uAA34\uAA4D\uAA7B\uAA7D\uAAEB\uAAEE-\uAAEF\uAAF5\uABE3-\uABE4\uABE6-\uABE7\uABE9-\uABEA\uABEC]
// Mark, Nonspacing
Mn = [\u0300-\u036F\u0483-\u0487\u0591-\u05BD\u05BF\u05C1-\u05C2\u05C4-\u05C5\u05C7\u0610-\u061A\u064B-\u065F\u0670\u06D6-\u06DC\u06DF-\u06E4\u06E7-\u06E8\u06EA-\u06ED\u0711\u0730-\u074A\u07A6-\u07B0\u07EB-\u07F3\u07FD\u0816-\u0819\u081B-\u0823\u0825-\u0827\u0829-\u082D\u0859-\u085B\u08D3-\u08E1\u08E3-\u0902\u093A\u093C\u0941-\u0948\u094D\u0951-\u0957\u0962-\u0963\u0981\u09BC\u09C1-\u09C4\u09CD\u09E2-\u09E3\u09FE\u0A01-\u0A02\u0A3C\u0A41-\u0A42\u0A47-\u0A48\u0A4B-\u0A4D\u0A51\u0A70-\u0A71\u0A75\u0A81-\u0A82\u0ABC\u0AC1-\u0AC5\u0AC7-\u0AC8\u0ACD\u0AE2-\u0AE3\u0AFA-\u0AFF\u0B01\u0B3C\u0B3F\u0B41-\u0B44\u0B4D\u0B56\u0B62-\u0B63\u0B82\u0BC0\u0BCD\u0C00\u0C04\u0C3E-\u0C40\u0C46-\u0C48\u0C4A-\u0C4D\u0C55-\u0C56\u0C62-\u0C63\u0C81\u0CBC\u0CBF\u0CC6\u0CCC-\u0CCD\u0CE2-\u0CE3\u0D00-\u0D01\u0D3B-\u0D3C\u0D41-\u0D44\u0D4D\u0D62-\u0D63\u0DCA\u0DD2-\u0DD4\u0DD6\u0E31\u0E34-\u0E3A\u0E47-\u0E4E\u0EB1\u0EB4-\u0EB9\u0EBB-\u0EBC\u0EC8-\u0ECD\u0F18-\u0F19\u0F35\u0F37\u0F39\u0F71-\u0F7E\u0F80-\u0F84\u0F86-\u0F87\u0F8D-\u0F97\u0F99-\u0FBC\u0FC6\u102D-\u1030\u1032-\u1037\u1039-\u103A\u103D-\u103E\u1058-\u1059\u105E-\u1060\u1071-\u1074\u1082\u1085-\u1086\u108D\u109D\u135D-\u135F\u1712-\u1714\u1732-\u1734\u1752-\u1753\u1772-\u1773\u17B4-\u17B5\u17B7-\u17BD\u17C6\u17C9-\u17D3\u17DD\u180B-\u180D\u1885-\u1886\u18A9\u1920-\u1922\u1927-\u1928\u1932\u1939-\u193B\u1A17-\u1A18\u1A1B\u1A56\u1A58-\u1A5E\u1A60\u1A62\u1A65-\u1A6C\u1A73-\u1A7C\u1A7F\u1AB0-\u1ABD\u1B00-\u1B03\u1B34\u1B36-\u1B3A\u1B3C\u1B42\u1B6B-\u1B73\u1B80-\u1B81\u1BA2-\u1BA5\u1BA8-\u1BA9\u1BAB-\u1BAD\u1BE6\u1BE8-\u1BE9\u1BED\u1BEF-\u1BF1\u1C2C-\u1C33\u1C36-\u1C37\u1CD0-\u1CD2\u1CD4-\u1CE0\u1CE2-\u1CE8\u1CED\u1CF4\u1CF8-\u1CF9\u1DC0-\u1DF9\u1DFB-\u1DFF\u20D0-\u20DC\u20E1\u20E5-\u20F0\u2CEF-\u2CF1\u2D7F\u2DE0-\u2DFF\u302A-\u302D\u3099-\u309A\uA66F\uA674-\uA67D\uA69E-\uA69F\uA6F0-\uA6F1\uA802\uA806\uA80B\uA825-\uA826\uA8C4-\uA8C5\uA8E0-\uA8F1\uA8FF\uA926-\uA92D\uA947-\uA951\uA980-\uA982\uA9B3\uA9B6-\uA9B9\uA9BC\uA9E5\uAA29-\uAA2E\uAA31-\uAA32\uAA35-\uAA36\uAA43\uAA4C\uAA7C\uAAB0\uAAB2-\uAAB4\uAAB7-\uAAB8\uAABE-\uAABF\uAAC1\uAAEC-\uAAED\uAAF6\uABE5\uABE8\uABED\uFB1E\uFE00-\uFE0F\uFE20-\uFE2F]
// Number, Decimal Digit
Nd = [\u0030-\u0039\u0660-\u0669\u06F0-\u06F9\u07C0-\u07C9\u0966-\u096F\u09E6-\u09EF\u0A66-\u0A6F\u0AE6-\u0AEF\u0B66-\u0B6F\u0BE6-\u0BEF\u0C66-\u0C6F\u0CE6-\u0CEF\u0D66-\u0D6F\u0DE6-\u0DEF\u0E50-\u0E59\u0ED0-\u0ED9\u0F20-\u0F29\u1040-\u1049\u1090-\u1099\u17E0-\u17E9\u1810-\u1819\u1946-\u194F\u19D0-\u19D9\u1A80-\u1A89\u1A90-\u1A99\u1B50-\u1B59\u1BB0-\u1BB9\u1C40-\u1C49\u1C50-\u1C59\uA620-\uA629\uA8D0-\uA8D9\uA900-\uA909\uA9D0-\uA9D9\uA9F0-\uA9F9\uAA50-\uAA59\uABF0-\uABF9\uFF10-\uFF19]
// Number, Letter
Nl = [\u16EE-\u16F0\u2160-\u2182\u2185-\u2188\u3007\u3021-\u3029\u3038-\u303A\uA6E6-\uA6EF]
// Punctuation, Connector
Pc = [\u005F\u203F-\u2040\u2054\uFE33-\uFE34\uFE4D-\uFE4F\uFF3F]
// Separator, Space
Zs = [\u0020\u00A0\u1680\u2000-\u200A\u202F\u205F\u3000]
// Skipped
__
= (WhiteSpace / LineTerminatorSequence / Comment)*
_
= (WhiteSpace / MultiLineCommentNoLineTerminator)*
// Automatic Semicolon Insertion
EOS
= __ ";"
/ _ SingleLineComment? LineTerminatorSequence
/ __ EOF
EOF
= !.

View file

@ -1,13 +0,0 @@
import test from "ava";
import { AnyType, IntersectType, PrimType } from "../checker"
import { createRef } from "../util";
test('an intersection with an any-type should remove that any-type', t => {
const t1 = new IntersectType([
createRef(new AnyType()),
createRef(new PrimType('@int')),
])
});

View file

@ -1,3 +0,0 @@
name: stdlib
version: 0.0.1
auto-import: true

View file

@ -1,3 +0,0 @@
pub struct Either<L, R>;

View file

@ -1,40 +0,0 @@
pub mod IO {
import "./numbers"
import "./either"
import "./vec"
import "./string"
pub type Result<T> = Either<Error, T>;
pub foreign "JS" fn print(message: String) {
process.stdout.write(message);
}
pub struct File;
pub trait Read {
fn read(self, count: usize, target: Vec<u8>) -> Result<usize>;
}
impl Read for File {
foreign "JS" fn read(self, count, target) -> Result<usize> {
import * as fs from "fs"
try {
return Ok(fs.readSync(self.fd, target, 0, count, null));
} catch (e) {
return Err(e.code);
}
}
}
}
// IO::print("Hello, world!");

View file

@ -1,84 +0,0 @@
import "../option";
import "../numbers";
import "../vec";
import "../string";
import "../io";
mod Bolt::Lang {
pub struct Pos {
offset: usize,
line: usize,
column: usize,
}
pub struct Span {
file: IO::File,
start: Pos,
end: Pos,
}
define_nodes! {
Identifier : Symbol {
text: String,
},
Statement,
ReturnStatement : Statement {
expression: Option<Expression>,
},
ConditionalCase {
test: Option<Expression>,
result: Vec<FunctionBodyElement>,
},
ConditionalStatement : Statement {
cases: Vec<ConditionalCase>,
},
Expression,
ReferenceExpression : Expression {
modulePath: Option<ModulePath>,
name: Symbol,
}
}
pub type Transformer = fn (node: Node) -> Node;
fn build_predicate_from_pattern(pattern: Pattern) -> Expression {
match pattern {
BindPattern { name } => quote(true).taint(pattern),
VariantPatten { elements } => quote(or($(elements),*)),
RecordPattern { members } => quote(and($elements),*)),
}
}
fn eliminate_match_rule(node: Node) {
match node {
quote {
match $value: Expression {
$patterns @ ( $pattern: Pattern => $expression: Expression ),* (,)?
}
} => {
let cases = patterns.map(|pattern| {
ConditionalCase::from_node(
pattern,
build_predicate_from_pattern(pattern),
value
)
});
return ConditionalStatement::from_node(node, cases);
}
}
}
register_transformer!(elminate_match_rule);
}

View file

@ -1,9 +0,0 @@
pub import "./option"
pub import "./either"
pub import "./string"
pub import "./numbers"
pub import "./math"
pub import "./vec"
pub import "./lang/bolt"

View file

@ -1,12 +0,0 @@
import "./numbers.bolt";
// precedence a + b < a * b;
pub fn fac(n: I) -> I where I: int {
match n {
0 => 1,
i => i * fac(i-1),
}
}

View file

@ -1,33 +0,0 @@
pub struct i8;
pub struct i16;
pub struct i32;
pub struct i64;
pub struct isize;
pub struct u8;
pub struct u16;
pub struct u32;
pub struct u64;
pub struct usize;
pub struct int;
pub struct uint;
trait Num;
fn (a: N) + (b: N) -> N where N: Num {
N::add(a, b)
}
fn (a: N) - (b: N) -> N where N: Num {
N::sub(a, b)
}
fn (a: N) / (b: N) -> N where N: Num {
N::div(a, b)
}
fn (a: N) * (b: N) -> N where N: Num {
N::mul(a, b)
}

View file

@ -1,3 +0,0 @@
pub struct Option<T>;

View file

@ -1,3 +0,0 @@
pub struct String;

View file

@ -1,3 +0,0 @@
pub struct Vec<T>;

View file

@ -1 +0,0 @@
9e87b23b96c54b7245893be35befc6fe7fd2c14ef41cc4b4815e50aee6b07d0c2c6be999719ecd236a55bbc227598117cfd2f747955c3f10b503edb069cf1828

View file

@ -1,16 +1,25 @@
struct int;
struct String;
fn (a: int) == (b: int) -> int;
fn (a: int) - (b: int) -> int;
fn (a: int) * (b: int) -> int;
fn fac(n: int) -> int {
return match n {
0 => 1,
1 => 1,
k => k * (k-1),
fn write(data: String);
struct Point<NumT> {
x: NumT,
y: NumT,
}
trait Print {
fn print(self);
}
impl Print for Point {
fn print(self) {
write("A point!");
}
}
fac(1);
let p1 = Point { x: 1, y: 2 }
p1.printer();

View file

@ -1,3 +0,0 @@
{ foo baz bar };
( foo baz bar );
[ foo baz bar ];

View file

@ -1,9 +0,0 @@
fn + x;
fn a + b;
fn (a: Int) + (b: Int);
fn a + b -> Int;

View file

@ -1,69 +0,0 @@
---
type: scan
expect: BoltIdentifier
split-lines: true
---
The most simple identifiers are those made out of ASCII letters:
```
Foo
Bar
Baz
```
However, they may also contain digits as long as they do not begin with a
digit:
```
Var1
Var2
Var10029384
```
Identifiers may be as long as you want:
```
ThisIsALongAndValidIdentifier
ThisIsAnEvenLongerButStilCompletelyValidIdentifier
```
Moreover, they may have arbitrary underscores (`_`) in their names.
```
a_valid_identifier
another__0000__valid_identfier
_1
__2
___3
```
They may even be nothing more than underscores:
```
_
__
___
```
All identifiers starting with a `ID_Start` character are valid identifiers,
including `Other_ID_Start`:
```
℘rototype
llipsis
```
Likewise, the following code points using `Other_ID_Continue` are also valid:
```
α·β
ano·teleia
```
And, of course, the combination of `ID_Start` and `ID_Continue`:
```
alfa·beta
```

View file

@ -1,26 +0,0 @@
---
type: scan
expect: BoltStringLiteral
split-lines: true
---
A string may hold arbirary ASCII characters, including spaces:
```
"Foo!"
"Once upon a time ..."
```
Special ASCII characters have no effect, other than that they are appended to
the contents of the string:
```
"S+me w3!rd @SCII ch@r$"
```
Some special escape sequences:
```
"\n\r"
"\n"
```

View file

@ -1,69 +0,0 @@
---
type: scan
expect: BoltIntegerLiteral
split-lines: true
---
All decimal digits are valid integers.
```
1
2
3
4
5
6
7
8
9
0
```
Any combination of decimal digits are valid integers, including integers
prefixed with an abirary amount of zeroes.
```
12345
99
10
01
000
0010
```
In binary mode, integers are read in base-2.
```
0b0
0b1
0b10010
0b00100
0b00000
```
This means the following expressions are invalid in binary mode:
```
0b20001
0b12345
0b00003
```
In octal mode, integers are read in base-8.
```
0o0
0o00000
0o007
0o706
0o12345
```
This means the following expressions are invalid in octal mode:
```
0o8
0o9
0o123456789
```

3
vscode-extension/.gitattributes vendored Normal file
View file

@ -0,0 +1,3 @@
# Set default behavior to automatically normalize line endings.
* text=auto

3
vscode-extension/.gitignore vendored Normal file
View file

@ -0,0 +1,3 @@
/dist/
node_modules/
*.vsix

View file

@ -0,0 +1,4 @@
.vscode/**
.vscode-test/**
.gitignore
vsc-extension-quickstart.md

View file

@ -0,0 +1,15 @@
# Change Log
All notable changes to the "bolt" VSCode extension will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [Unreleased]
### Added
- Basic TextMate syntax highlighting for keywords, some constants, some
built-in types, and string/char literals
- Initial release

View file

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2020 Sam Vervaeck
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View file

@ -0,0 +1,27 @@
Bolt
====
This is an plugin providing experimental support for the Bolt programming
language in Visual Studio Code.
## Planned Features
- Syntax highlighting with contextual information from the compiler
- Rich type hints that appear whenever you hover an expression
- Integration with the build tools
- A debugger that works independently from the target platform
## Extension Settings
This extension contributes the following settings:
- `bolt.pathToLanguageServer`: you can set this to point to a custom binary
that will be spawned instead of the built-in language server
- `bolt.watchLanguageServer`: set to `true` to automatically restart the
lanuage server whenever the binary was changed on the file system
## License
This software is generously licensed under the MIT license. See `LICENSE.txt`
for more information.

13452
vscode-extension/dist/extension.js vendored Normal file

File diff suppressed because it is too large Load diff

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,30 @@
{
"comments": {
// symbol used for single line comment. Remove this entry if your language does not support line comments
"lineComment": "//",
// symbols used for start and end a block comment. Remove this entry if your language does not support block comments
"blockComment": [ "/*", "*/" ]
},
// symbols used as brackets
"brackets": [
["{", "}"],
["[", "]"],
["(", ")"]
],
// symbols that are auto closed when typing
"autoClosingPairs": [
["{", "}"],
["[", "]"],
["(", ")"],
["\"", "\""],
["'", "'"]
],
// symbols that can be used to surround a selection
"surroundingPairs": [
["{", "}"],
["[", "]"],
["(", ")"],
["\"", "\""],
["'", "'"]
]
}

1389
vscode-extension/package-lock.json generated Normal file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,75 @@
{
"name": "bolt",
"displayName": "The Bolt Programming Language",
"description": "Adds support for the Bolt programming language",
"version": "0.0.1",
"engines": {
"vscode": "^1.51.0"
},
"categories": [
"Programming Languages"
],
"publisher": "samvv",
"main": "./dist/extension",
"activationEvents": [
"onLanguage:bolt"
],
"contributes": {
"languages": [
{
"id": "bolt",
"aliases": [
"Bolt",
"bolt"
],
"extensions": [
".bolt"
],
"configuration": "./language-configuration.json"
}
],
"grammars": [
{
"language": "bolt",
"scopeName": "source.bolt",
"path": "./syntaxes/bolt.tmLanguage.json"
}
],
"configuration": [
{
"title": "Language Server",
"properties": {
"bolt.pathToLanguageServer": {
"type": [
"string",
"null"
],
"default": null,
"description": "You can set this to point to a custom binary that will be spawned instead of the built-in language server."
},
"bolt.watchLanguageServer": {
"type": "boolean",
"default": false,
"description": "Set to `true` to automatically restart the lanuage server whenever the binary was changed on the file system."
}
}
}
]
},
"scripts": {
"vscode:prepublish": "npm run compile",
"compile": "webpack --mode production",
"watch": "webpack --mode development --watch"
},
"dependencies": {
"vscode-languageclient": "^6.1.3"
},
"devDependencies": {
"@types/node": "^14.14.7",
"@types/vscode": "^1.51.0",
"ts-loader": "^8.0.11",
"typescript": "^4.0.5",
"webpack": "^5.4.0",
"webpack-cli": "^4.2.0"
}
}

View file

@ -0,0 +1,79 @@
import * as net from "net"
import * as path from 'path';
import { workspace, ExtensionContext } from 'vscode';
import {
LanguageClient,
LanguageClientOptions,
ServerOptions,
StreamInfo,
TransportKind
} from 'vscode-languageclient';
let client: LanguageClient;
function spawnLanguageClient(context: ExtensionContext) {
if (client) {
return;
}
const config = workspace.getConfiguration('bolt');
const watchLanguageServer = config.get('watchLanguageServer') as boolean;
let pathToLanguageServer = config.get('pathToLanguageServer') as string | null;
if (pathToLanguageServer === null) {
pathToLanguageServer = context.asAbsolutePath(path.join('bin', 'langserver.js'));
}
let serverOptions: ServerOptions;
const languageServerPort = process.env['VSCODE_BOLT_LANGUAGE_SERVER_PORT']
if (languageServerPort !== undefined) {
const port = Number(languageServerPort)
if (isNaN(port)) {
return;
}
serverOptions = () => {
const socket = net.connect(port)
return Promise.resolve({ reader: socket, writer: socket });
}
} else {
serverOptions = { module: pathToLanguageServer, transport: TransportKind.ipc }
};
// Options to control the language client
let clientOptions: LanguageClientOptions = {
// Register the server for plain text documents
documentSelector: [{ scheme: 'file', language: 'bolt' }],
synchronize: {
// Notify the server about file changes to '.clientrc files contained in the workspace
fileEvents: workspace.createFileSystemWatcher('**/*.bolt')
}
};
// Create the language client and start the client.
client = new LanguageClient(
'bolt-client',
'Bolt Language Server',
serverOptions,
clientOptions
);
// Start the client. This will also launch the server
client.start();
}
export function activate(context: ExtensionContext) {
spawnLanguageClient(context);
}
export function deactivate(): Thenable<void> | undefined {
if (!client) {
return undefined;
}
return client.stop();
}

View file

@ -0,0 +1,60 @@
{
"$schema": "https://raw.githubusercontent.com/martinring/tmlanguage/master/tmlanguage.json",
"name": "Bolt",
"patterns": [
{
"include": "#keywords"
},
{
"include": "#strings"
},
{
"include": "#constants"
},
{
"name": "storage.type.bolt",
"match": "\\b(int|bool|String)\\b"
}
],
"repository": {
"keywords": {
"patterns": [{
"name": "keyword.control.bolt",
"match": "\\b(let|fn|pub|struct|if|impl|trait|while|for|return|loop)\\b"
}, {
"name": "keyword.operator.bolt",
"match": "(==+|[-+*/%^&!<>]+)"
}, {
"name": "keyword.operator.assignment.bolt",
"match": "[-+*/%^&!<>]*="
}]
},
"constants": {
"patterns": [{
"name": "constant.numeric.bolt",
"match": "\\b[0-9][0-9]*\\b"
}, {
"name": "constant.character.bolt",
"match": "'.'"
}, {
"name": "constant.character.escape.bolt",
"match": "'\\\\.'"
}, {
"name": "constant.language.boolean.bolt",
"match": "\\b(true|false)\\b"
}]
},
"strings": {
"name": "string.quoted.double.bolt",
"begin": "\"",
"end": "\"",
"patterns": [
{
"name": "constant.character.escape.bolt",
"match": "\\\\."
}
]
}
},
"scopeName": "source.bolt"
}

View file

@ -0,0 +1,16 @@
{
"compilerOptions": {
"module": "commonjs",
"target": "es2019",
"lib": ["ES2019"],
"noEmit": true,
"sourceMap": true
},
"include": [
"src"
],
"exclude": [
"node_modules",
".vscode-test"
]
}

View file

@ -0,0 +1,42 @@
//@ts-check
'use strict';
const path = require('path');
/**@type {import('webpack').Configuration}*/
const config = {
target: 'node',
entry: './src/extension.ts',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'extension.js',
libraryTarget: 'commonjs2',
devtoolModuleFilenameTemplate: '../[resource-path]'
},
devtool: 'source-map',
externals: {
vscode: 'commonjs vscode'
},
resolve: {
extensions: ['.ts', '.js']
},
module: {
rules: [
{
test: /\.ts$/,
exclude: /node_modules/,
use: [
{
loader: 'ts-loader',
options: {
transpileOnly: true
}
}
]
}
]
}
};
module.exports = config;

21
webpack.config.js Normal file
View file

@ -0,0 +1,21 @@
#!/usr/bin/env node
const path = require('path');
const glob = require('glob');
function getAllPackages() {
return glob.sync('**/package.json', {
ignore: ['node_modules', '.*'],
cwd: __dirname,
});
}
const webpackConfig = [];
for (const packageJsonPath of getAllPackages()) {
const webpackConfigPath = path.resolve(path.dirname(packageJsonPath), 'webpack.config.js');
webpackConfig.push(require(webpackConfigPath));
}
module.exports = webpackConfig;