Another set of fixes
This commit is contained in:
parent
12c9317ea0
commit
9e139c40a9
19 changed files with 600 additions and 209 deletions
111
package-lock.json
generated
111
package-lock.json
generated
|
@ -32,6 +32,16 @@
|
||||||
"@types/node": "*"
|
"@types/node": "*"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"@types/microtime": {
|
||||||
|
"version": "2.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/microtime/-/microtime-2.1.0.tgz",
|
||||||
|
"integrity": "sha1-rb2Z9QGoXIhpXrHv01FYEPJWOTI="
|
||||||
|
},
|
||||||
|
"@types/minimist": {
|
||||||
|
"version": "1.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/minimist/-/minimist-1.2.0.tgz",
|
||||||
|
"integrity": "sha1-aaI6OtKcrwCX8G7aWbNh7i8GOfY="
|
||||||
|
},
|
||||||
"@types/mocha": {
|
"@types/mocha": {
|
||||||
"version": "7.0.2",
|
"version": "7.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-7.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-7.0.2.tgz",
|
||||||
|
@ -176,24 +186,35 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"chalk": {
|
"chalk": {
|
||||||
"version": "2.4.2",
|
"version": "4.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
|
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.0.0.tgz",
|
||||||
"integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
|
"integrity": "sha512-N9oWFcegS0sFr9oh1oz2d7Npos6vNoWW9HvtCg5N1KRFpUhaAhvTv5Y58g880fZaEYSNm3qDz8SU1UrGvp+n7A==",
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
"requires": {
|
||||||
"ansi-styles": "^3.2.1",
|
"ansi-styles": "^4.1.0",
|
||||||
"escape-string-regexp": "^1.0.5",
|
"supports-color": "^7.1.0"
|
||||||
"supports-color": "^5.3.0"
|
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"supports-color": {
|
"ansi-styles": {
|
||||||
"version": "5.5.0",
|
"version": "4.2.1",
|
||||||
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
|
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz",
|
||||||
"integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
|
"integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==",
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
"requires": {
|
||||||
"has-flag": "^3.0.0"
|
"@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=="
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -600,6 +621,37 @@
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"chalk": "^2.4.2"
|
"chalk": "^2.4.2"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"chalk": {
|
||||||
|
"version": "2.4.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
|
||||||
|
"integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"ansi-styles": "^3.2.1",
|
||||||
|
"escape-string-regexp": "^1.0.5",
|
||||||
|
"supports-color": "^5.3.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"supports-color": {
|
||||||
|
"version": "5.5.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
|
||||||
|
"integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"has-flag": "^3.0.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"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"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"minimatch": {
|
"minimatch": {
|
||||||
|
@ -613,8 +665,7 @@
|
||||||
"minimist": {
|
"minimist": {
|
||||||
"version": "1.2.5",
|
"version": "1.2.5",
|
||||||
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz",
|
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz",
|
||||||
"integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==",
|
"integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw=="
|
||||||
"dev": true
|
|
||||||
},
|
},
|
||||||
"mkdirp": {
|
"mkdirp": {
|
||||||
"version": "0.5.5",
|
"version": "0.5.5",
|
||||||
|
@ -754,12 +805,22 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"moment": {
|
||||||
|
"version": "2.25.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/moment/-/moment-2.25.3.tgz",
|
||||||
|
"integrity": "sha512-PuYv0PHxZvzc15Sp8ybUCoQ+xpyPWvjOuK72a5ovzp2LI32rJXOiIfyoFoYvG3s6EwwrdkMyWuRiEHSZRLJNdg=="
|
||||||
|
},
|
||||||
"ms": {
|
"ms": {
|
||||||
"version": "2.1.1",
|
"version": "2.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz",
|
||||||
"integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==",
|
"integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"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-environment-flags": {
|
"node-environment-flags": {
|
||||||
"version": "1.0.6",
|
"version": "1.0.6",
|
||||||
"resolved": "https://registry.npmjs.org/node-environment-flags/-/node-environment-flags-1.0.6.tgz",
|
"resolved": "https://registry.npmjs.org/node-environment-flags/-/node-environment-flags-1.0.6.tgz",
|
||||||
|
@ -770,6 +831,11 @@
|
||||||
"semver": "^5.7.0"
|
"semver": "^5.7.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"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=="
|
||||||
|
},
|
||||||
"normalize-path": {
|
"normalize-path": {
|
||||||
"version": "3.0.0",
|
"version": "3.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
|
||||||
|
@ -1001,6 +1067,21 @@
|
||||||
"integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=",
|
"integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"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=="
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"to-regex-range": {
|
"to-regex-range": {
|
||||||
"version": "5.0.1",
|
"version": "5.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
|
||||||
|
|
|
@ -15,12 +15,18 @@
|
||||||
"repository": "https://github.com/samvv/Bolt",
|
"repository": "https://github.com/samvv/Bolt",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@types/fs-extra": "^8.1.0",
|
"@types/fs-extra": "^8.1.0",
|
||||||
|
"@types/microtime": "^2.1.0",
|
||||||
|
"@types/minimist": "^1.2.0",
|
||||||
"@types/node": "^13.13.5",
|
"@types/node": "^13.13.5",
|
||||||
"@types/xregexp": "^4.3.0",
|
"@types/xregexp": "^4.3.0",
|
||||||
"@types/yargs": "^15.0.4",
|
"@types/yargs": "^15.0.4",
|
||||||
"acorn": "^7.2.0",
|
"acorn": "^7.2.0",
|
||||||
|
"chalk": "^4.0.0",
|
||||||
"fs-extra": "^9.0.0",
|
"fs-extra": "^9.0.0",
|
||||||
"glob": "^7.1.6",
|
"glob": "^7.1.6",
|
||||||
|
"microtime": "^3.0.0",
|
||||||
|
"minimist": "^1.2.5",
|
||||||
|
"moment": "^2.25.3",
|
||||||
"pegjs": "^0.11.0-master.b7b87ea",
|
"pegjs": "^0.11.0-master.b7b87ea",
|
||||||
"reflect-metadata": "^0.1.13",
|
"reflect-metadata": "^0.1.13",
|
||||||
"source-map-support": "^0.5.19",
|
"source-map-support": "^0.5.19",
|
||||||
|
|
|
@ -30,6 +30,10 @@ node BoltOperator > BoltSymbol {
|
||||||
text: String,
|
text: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
node BoltAssignment > BoltToken {
|
||||||
|
operator: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
node BoltEOS > BoltToken;
|
node BoltEOS > BoltToken;
|
||||||
|
|
||||||
node BoltComma > BoltToken;
|
node BoltComma > BoltToken;
|
||||||
|
|
173
src/ast.d.ts
vendored
173
src/ast.d.ts
vendored
|
@ -5,92 +5,95 @@ export const enum SyntaxKind {
|
||||||
BoltIntegerLiteral = 6,
|
BoltIntegerLiteral = 6,
|
||||||
BoltIdentifier = 8,
|
BoltIdentifier = 8,
|
||||||
BoltOperator = 9,
|
BoltOperator = 9,
|
||||||
BoltEOS = 10,
|
BoltAssignment = 10,
|
||||||
BoltComma = 11,
|
BoltEOS = 11,
|
||||||
BoltSemi = 12,
|
BoltComma = 12,
|
||||||
BoltColon = 13,
|
BoltSemi = 13,
|
||||||
BoltDot = 14,
|
BoltColon = 14,
|
||||||
BoltDotDot = 15,
|
BoltDot = 15,
|
||||||
BoltRArrow = 16,
|
BoltDotDot = 16,
|
||||||
BoltLArrow = 17,
|
BoltRArrow = 17,
|
||||||
BoltEqSign = 18,
|
BoltLArrow = 18,
|
||||||
BoltGtSign = 19,
|
BoltEqSign = 19,
|
||||||
BoltLtSign = 20,
|
BoltGtSign = 20,
|
||||||
BoltFnKeyword = 22,
|
BoltLtSign = 21,
|
||||||
BoltForeignKeyword = 23,
|
BoltFnKeyword = 23,
|
||||||
BoltLetKeyword = 24,
|
BoltForeignKeyword = 24,
|
||||||
BoltReturnKeyword = 25,
|
BoltLetKeyword = 25,
|
||||||
BoltLoopKeyword = 26,
|
BoltReturnKeyword = 26,
|
||||||
BoltYieldKeyword = 27,
|
BoltLoopKeyword = 27,
|
||||||
BoltMatchKeyword = 28,
|
BoltYieldKeyword = 28,
|
||||||
BoltImportKeyword = 29,
|
BoltMatchKeyword = 29,
|
||||||
BoltPubKeyword = 30,
|
BoltImportKeyword = 30,
|
||||||
BoltModKeyword = 31,
|
BoltPubKeyword = 31,
|
||||||
BoltMutKeyword = 32,
|
BoltModKeyword = 32,
|
||||||
BoltEnumKeyword = 33,
|
BoltMutKeyword = 33,
|
||||||
BoltStructKeyword = 34,
|
BoltEnumKeyword = 34,
|
||||||
BoltNewTypeKeyword = 35,
|
BoltStructKeyword = 35,
|
||||||
BoltParenthesized = 37,
|
BoltNewTypeKeyword = 36,
|
||||||
BoltBraced = 38,
|
BoltParenthesized = 38,
|
||||||
BoltBracketed = 39,
|
BoltBraced = 39,
|
||||||
BoltSourceFile = 40,
|
BoltBracketed = 40,
|
||||||
BoltQualName = 41,
|
BoltSourceFile = 41,
|
||||||
BoltSentence = 42,
|
BoltQualName = 42,
|
||||||
BoltReferenceTypeNode = 44,
|
BoltSentence = 43,
|
||||||
BoltBindPattern = 46,
|
BoltReferenceTypeNode = 45,
|
||||||
BoltTypePattern = 47,
|
BoltBindPattern = 47,
|
||||||
BoltExpressionPattern = 48,
|
BoltTypePattern = 48,
|
||||||
BoltTuplePatternElement = 49,
|
BoltExpressionPattern = 49,
|
||||||
BoltTuplePattern = 50,
|
BoltTuplePatternElement = 50,
|
||||||
BoltRecordPatternField = 51,
|
BoltTuplePattern = 51,
|
||||||
BoltRecordPattern = 52,
|
BoltRecordPatternField = 52,
|
||||||
BoltReferenceExpression = 54,
|
BoltRecordPattern = 53,
|
||||||
BoltCallExpression = 55,
|
BoltReferenceExpression = 55,
|
||||||
BoltYieldExpression = 56,
|
BoltCallExpression = 56,
|
||||||
BoltMatchArm = 57,
|
BoltYieldExpression = 57,
|
||||||
BoltMatchExpression = 58,
|
BoltMatchArm = 58,
|
||||||
BoltCase = 59,
|
BoltMatchExpression = 59,
|
||||||
BoltCaseExpression = 60,
|
BoltCase = 60,
|
||||||
BoltBlockExpression = 61,
|
BoltCaseExpression = 61,
|
||||||
BoltConstantExpression = 62,
|
BoltBlockExpression = 62,
|
||||||
BoltReturnStatement = 64,
|
BoltConstantExpression = 63,
|
||||||
BoltResumeStatement = 65,
|
BoltReturnStatement = 65,
|
||||||
BoltExpressionStatement = 66,
|
BoltResumeStatement = 66,
|
||||||
BoltParameter = 67,
|
BoltExpressionStatement = 67,
|
||||||
BoltNewTypeDeclaration = 70,
|
BoltParameter = 68,
|
||||||
BoltModule = 71,
|
BoltNewTypeDeclaration = 71,
|
||||||
BoltFunctionDeclaration = 72,
|
BoltModule = 72,
|
||||||
BoltVariableDeclaration = 73,
|
BoltFunctionDeclaration = 73,
|
||||||
BoltPlainImportSymbol = 75,
|
BoltVariableDeclaration = 74,
|
||||||
BoltImportDeclaration = 76,
|
BoltPlainImportSymbol = 76,
|
||||||
BoltRecordDeclarationField = 77,
|
BoltImportDeclaration = 77,
|
||||||
BoltRecordDeclaration = 79,
|
BoltRecordDeclarationField = 78,
|
||||||
JSOperator = 82,
|
BoltRecordDeclaration = 80,
|
||||||
JSIdentifier = 83,
|
JSOperator = 83,
|
||||||
JSBindPattern = 85,
|
JSIdentifier = 84,
|
||||||
JSConstantExpression = 87,
|
JSBindPattern = 86,
|
||||||
JSMemberExpression = 89,
|
JSConstantExpression = 88,
|
||||||
JSCallExpression = 90,
|
JSMemberExpression = 90,
|
||||||
JSBinaryExpression = 91,
|
JSCallExpression = 91,
|
||||||
JSUnaryExpression = 92,
|
JSBinaryExpression = 92,
|
||||||
JSNewExpression = 93,
|
JSUnaryExpression = 93,
|
||||||
JSSequenceExpression = 94,
|
JSNewExpression = 94,
|
||||||
JSConditionalExpression = 95,
|
JSSequenceExpression = 95,
|
||||||
JSReferenceExpression = 96,
|
JSConditionalExpression = 96,
|
||||||
JSExpressionStatement = 98,
|
JSReferenceExpression = 97,
|
||||||
JSConditionalStatement = 99,
|
JSExpressionStatement = 99,
|
||||||
JSParameter = 100,
|
JSConditionalStatement = 100,
|
||||||
JSFunctionDeclaration = 103,
|
JSParameter = 101,
|
||||||
JSArrowFunctionDeclaration = 104,
|
JSFunctionDeclaration = 104,
|
||||||
JSLetDeclaration = 105,
|
JSArrowFunctionDeclaration = 105,
|
||||||
JSSourceFile = 106,
|
JSLetDeclaration = 106,
|
||||||
JSSourceElement = 107,
|
JSSourceFile = 107,
|
||||||
|
JSSourceElement = 108,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
import { TextSpan } from "./text"
|
import { TextSpan } from "./text"
|
||||||
|
|
||||||
|
export function setParents(node: Syntax): void;
|
||||||
|
|
||||||
export type SyntaxRange = [Syntax, Syntax];
|
export type SyntaxRange = [Syntax, Syntax];
|
||||||
|
|
||||||
interface SyntaxBase {
|
interface SyntaxBase {
|
||||||
|
@ -107,6 +110,7 @@ export type BoltToken
|
||||||
| BoltIntegerLiteral
|
| BoltIntegerLiteral
|
||||||
| BoltIdentifier
|
| BoltIdentifier
|
||||||
| BoltOperator
|
| BoltOperator
|
||||||
|
| BoltAssignment
|
||||||
| BoltEOS
|
| BoltEOS
|
||||||
| BoltComma
|
| BoltComma
|
||||||
| BoltSemi
|
| BoltSemi
|
||||||
|
@ -162,6 +166,11 @@ export interface BoltOperator extends SyntaxBase {
|
||||||
text: string;
|
text: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface BoltAssignment extends SyntaxBase {
|
||||||
|
kind: SyntaxKind.BoltAssignment;
|
||||||
|
operator: string | null;
|
||||||
|
}
|
||||||
|
|
||||||
export interface BoltEOS extends SyntaxBase {
|
export interface BoltEOS extends SyntaxBase {
|
||||||
kind: SyntaxKind.BoltEOS;
|
kind: SyntaxKind.BoltEOS;
|
||||||
}
|
}
|
||||||
|
@ -708,6 +717,7 @@ export type BoltSyntax
|
||||||
| BoltIntegerLiteral
|
| BoltIntegerLiteral
|
||||||
| BoltIdentifier
|
| BoltIdentifier
|
||||||
| BoltOperator
|
| BoltOperator
|
||||||
|
| BoltAssignment
|
||||||
| BoltEOS
|
| BoltEOS
|
||||||
| BoltComma
|
| BoltComma
|
||||||
| BoltSemi
|
| BoltSemi
|
||||||
|
@ -799,6 +809,7 @@ export type Syntax
|
||||||
| BoltIntegerLiteral
|
| BoltIntegerLiteral
|
||||||
| BoltIdentifier
|
| BoltIdentifier
|
||||||
| BoltOperator
|
| BoltOperator
|
||||||
|
| BoltAssignment
|
||||||
| BoltEOS
|
| BoltEOS
|
||||||
| BoltComma
|
| BoltComma
|
||||||
| BoltSemi
|
| BoltSemi
|
||||||
|
@ -888,6 +899,7 @@ export function createBoltStringLiteral(value: string, span?: TextSpan | null):
|
||||||
export function createBoltIntegerLiteral(value: bigint, span?: TextSpan | null): BoltIntegerLiteral;
|
export function createBoltIntegerLiteral(value: bigint, span?: TextSpan | null): BoltIntegerLiteral;
|
||||||
export function createBoltIdentifier(text: string, span?: TextSpan | null): BoltIdentifier;
|
export function createBoltIdentifier(text: string, span?: TextSpan | null): BoltIdentifier;
|
||||||
export function createBoltOperator(text: string, span?: TextSpan | null): BoltOperator;
|
export function createBoltOperator(text: string, span?: TextSpan | null): BoltOperator;
|
||||||
|
export function createBoltAssignment(operator: string | null, span?: TextSpan | null): BoltAssignment;
|
||||||
export function createBoltEOS(span?: TextSpan | null): BoltEOS;
|
export function createBoltEOS(span?: TextSpan | null): BoltEOS;
|
||||||
export function createBoltComma(span?: TextSpan | null): BoltComma;
|
export function createBoltComma(span?: TextSpan | null): BoltComma;
|
||||||
export function createBoltSemi(span?: TextSpan | null): BoltSemi;
|
export function createBoltSemi(span?: TextSpan | null): BoltSemi;
|
||||||
|
@ -976,6 +988,7 @@ export function isBoltIntegerLiteral(value: any): value is BoltIntegerLiteral;
|
||||||
export function isBoltSymbol(value: any): value is BoltSymbol;
|
export function isBoltSymbol(value: any): value is BoltSymbol;
|
||||||
export function isBoltIdentifier(value: any): value is BoltIdentifier;
|
export function isBoltIdentifier(value: any): value is BoltIdentifier;
|
||||||
export function isBoltOperator(value: any): value is BoltOperator;
|
export function isBoltOperator(value: any): value is BoltOperator;
|
||||||
|
export function isBoltAssignment(value: any): value is BoltAssignment;
|
||||||
export function isBoltEOS(value: any): value is BoltEOS;
|
export function isBoltEOS(value: any): value is BoltEOS;
|
||||||
export function isBoltComma(value: any): value is BoltComma;
|
export function isBoltComma(value: any): value is BoltComma;
|
||||||
export function isBoltSemi(value: any): value is BoltSemi;
|
export function isBoltSemi(value: any): value is BoltSemi;
|
||||||
|
|
|
@ -6,7 +6,7 @@ import * as fs from "fs"
|
||||||
import { parse, SyntaxError } from "../treegen/parser"
|
import { parse, SyntaxError } from "../treegen/parser"
|
||||||
import { Declaration } from "../treegen/ast"
|
import { Declaration } from "../treegen/ast"
|
||||||
import { generateAST } from "../treegen/index"
|
import { generateAST } from "../treegen/index"
|
||||||
import { getFileStem } from "../util"
|
import { getFileStem } from "../treegen/util"
|
||||||
import minimist from "minimist"
|
import minimist from "minimist"
|
||||||
|
|
||||||
const PACKAGE_ROOT = path.join(__dirname, '..', '..');
|
const PACKAGE_ROOT = path.join(__dirname, '..', '..');
|
||||||
|
|
|
@ -3,9 +3,6 @@
|
||||||
import "reflect-metadata"
|
import "reflect-metadata"
|
||||||
import "source-map-support/register"
|
import "source-map-support/register"
|
||||||
|
|
||||||
import * as path from "path"
|
|
||||||
import * as fs from "fs-extra"
|
|
||||||
|
|
||||||
import yargs from "yargs"
|
import yargs from "yargs"
|
||||||
|
|
||||||
import { Program } from "../program"
|
import { Program } from "../program"
|
||||||
|
@ -47,7 +44,7 @@ yargs
|
||||||
|
|
||||||
'link [name]',
|
'link [name]',
|
||||||
'Link projects with each other',
|
'Link projects with each other',
|
||||||
|
|
||||||
yargs => yargs,
|
yargs => yargs,
|
||||||
|
|
||||||
args => {
|
args => {
|
||||||
|
@ -66,12 +63,17 @@ yargs
|
||||||
yargs => yargs
|
yargs => yargs
|
||||||
.string('work-dir')
|
.string('work-dir')
|
||||||
.describe('work-dir', 'The working directory where files will be resolved against.')
|
.describe('work-dir', 'The working directory where files will be resolved against.')
|
||||||
.default('work-dir', '.'),
|
.default('work-dir', '.')
|
||||||
|
.string('inspect-server'),
|
||||||
|
|
||||||
args => {
|
args => {
|
||||||
|
|
||||||
const files = toArray(args.files as string[] | string).map(filepath => new TextFile(filepath, args['work-dir']));
|
const files = toArray(args.files as string[] | string);
|
||||||
const program = new Program(files)
|
const opts = {};
|
||||||
|
if (args['inspect-server'] !== undefined) {
|
||||||
|
opts.inspector = connectToInspector(args['inspect-server'] as string);
|
||||||
|
}
|
||||||
|
const program = new Program(files, opts);
|
||||||
program.compile("JS");
|
program.compile("JS");
|
||||||
|
|
||||||
})
|
})
|
||||||
|
|
|
@ -101,7 +101,7 @@ function getFullName(node: Syntax) {
|
||||||
case SyntaxKind.BoltRecordDeclaration:
|
case SyntaxKind.BoltRecordDeclaration:
|
||||||
out.unshift(getFullTextOfQualName(curr.name))
|
out.unshift(getFullTextOfQualName(curr.name))
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
curr = curr.parentNode;
|
curr = curr.parentNode;
|
||||||
if (curr === null) {
|
if (curr === null) {
|
||||||
break;
|
break;
|
||||||
|
@ -129,6 +129,8 @@ export class TypeChecker {
|
||||||
|
|
||||||
protected createType(node: Syntax): Type {
|
protected createType(node: Syntax): Type {
|
||||||
|
|
||||||
|
console.error(`creating type for ${kindToString(node.kind)}`);
|
||||||
|
|
||||||
switch (node.kind) {
|
switch (node.kind) {
|
||||||
|
|
||||||
case SyntaxKind.BoltReferenceExpression:
|
case SyntaxKind.BoltReferenceExpression:
|
||||||
|
@ -145,6 +147,10 @@ export class TypeChecker {
|
||||||
case SyntaxKind.BoltExpressionStatement:
|
case SyntaxKind.BoltExpressionStatement:
|
||||||
return voidType;
|
return voidType;
|
||||||
|
|
||||||
|
case SyntaxKind.BoltCallExpression:
|
||||||
|
// TODO
|
||||||
|
return anyType;
|
||||||
|
|
||||||
case SyntaxKind.BoltFunctionDeclaration:
|
case SyntaxKind.BoltFunctionDeclaration:
|
||||||
let returnType = anyType;
|
let returnType = anyType;
|
||||||
if (node.returnType !== null) {
|
if (node.returnType !== null) {
|
||||||
|
@ -182,8 +188,8 @@ export class TypeChecker {
|
||||||
return typ;
|
return typ;
|
||||||
|
|
||||||
case SyntaxKind.BoltParameter:
|
case SyntaxKind.BoltParameter:
|
||||||
if (node.typeNode !== null) {
|
if (node.type !== null) {
|
||||||
return this.getTypeOfNode(node.typeNode)
|
return this.getTypeOfNode(node.type)
|
||||||
}
|
}
|
||||||
return anyType;
|
return anyType;
|
||||||
|
|
||||||
|
@ -218,12 +224,21 @@ export class TypeChecker {
|
||||||
case SyntaxKind.BoltSentence:
|
case SyntaxKind.BoltSentence:
|
||||||
case SyntaxKind.BoltRecordDeclaration:
|
case SyntaxKind.BoltRecordDeclaration:
|
||||||
case SyntaxKind.BoltNewTypeDeclaration:
|
case SyntaxKind.BoltNewTypeDeclaration:
|
||||||
|
case SyntaxKind.BoltConstantExpression:
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SyntaxKind.BoltExpressionStatement:
|
case SyntaxKind.BoltExpressionStatement:
|
||||||
this.check(node.expression);
|
this.check(node.expression);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case SyntaxKind.BoltCallExpression:
|
||||||
|
this.check(node.operator);
|
||||||
|
for (const operand of node.operands) {
|
||||||
|
this.check(operand);
|
||||||
|
}
|
||||||
|
// TODO check whether the overload matches the referenced operator
|
||||||
|
break;
|
||||||
|
|
||||||
case SyntaxKind.BoltFunctionDeclaration:
|
case SyntaxKind.BoltFunctionDeclaration:
|
||||||
if (node.body !== null) {
|
if (node.body !== null) {
|
||||||
if (Array.isArray(node.body)) {
|
if (Array.isArray(node.body)) {
|
||||||
|
|
|
@ -30,6 +30,8 @@ import {
|
||||||
createJSBindPattern,
|
createJSBindPattern,
|
||||||
JSDeclarationModifiers,
|
JSDeclarationModifiers,
|
||||||
JSParameter,
|
JSParameter,
|
||||||
|
BoltSyntax,
|
||||||
|
BoltPattern,
|
||||||
} from "./ast"
|
} from "./ast"
|
||||||
|
|
||||||
import { getFullTextOfQualName, hasPublicModifier } from "./util"
|
import { getFullTextOfQualName, hasPublicModifier } from "./util"
|
||||||
|
@ -95,9 +97,11 @@ export class Compiler {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected compileDecl(node: Syntax, preamble: Syntax[]) {
|
private compilePattern(node: BoltPattern) {
|
||||||
|
|
||||||
console.log(`compiling ${kindToString(node.kind)}`)
|
}
|
||||||
|
|
||||||
|
protected compileDecl(node: BoltSyntax, preamble: Syntax[]) {
|
||||||
|
|
||||||
//if (isBoltExpression(node)) {
|
//if (isBoltExpression(node)) {
|
||||||
// const compiled = this.compileExpr(node, preamble);
|
// const compiled = this.compileExpr(node, preamble);
|
||||||
|
@ -121,6 +125,9 @@ export class Compiler {
|
||||||
// TODO
|
// TODO
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case SyntaxKind.BoltNewTypeDeclaration:
|
||||||
|
break;
|
||||||
|
|
||||||
case SyntaxKind.BoltVariableDeclaration:
|
case SyntaxKind.BoltVariableDeclaration:
|
||||||
const compiledValue = node.value !== null ? this.compileExpr(node.value, preamble) : null;
|
const compiledValue = node.value !== null ? this.compileExpr(node.value, preamble) : null;
|
||||||
preamble.push(
|
preamble.push(
|
||||||
|
@ -132,8 +139,11 @@ export class Compiler {
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SyntaxKind.BoltForeignFunctionDeclaration:
|
case SyntaxKind.BoltFunctionDeclaration:
|
||||||
if (node.target === this.target && node.body !== null) {
|
if (node.target === this.target) {
|
||||||
|
if (node.body === null) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
const params: JSParameter[] = [];
|
const params: JSParameter[] = [];
|
||||||
let body: JSStatement[] = [];
|
let body: JSStatement[] = [];
|
||||||
for (const param of node.params) {
|
for (const param of node.params) {
|
||||||
|
@ -150,6 +160,9 @@ export class Compiler {
|
||||||
result.modifiers |= JSDeclarationModifiers.IsExported;;
|
result.modifiers |= JSDeclarationModifiers.IsExported;;
|
||||||
}
|
}
|
||||||
preamble.push(result)
|
preamble.push(result)
|
||||||
|
} else {
|
||||||
|
// TODO
|
||||||
|
throw new Error(`Compiling native functions is not yet implemented.`);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
7
src/constants.ts
Normal file
7
src/constants.ts
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
|
||||||
|
export const TYPES = {
|
||||||
|
Program: Symbol('a Bolt program'),
|
||||||
|
TypeChecker: Symbol('the Bolt type checking system'),
|
||||||
|
FileManager: Symbol('the file manager'),
|
||||||
|
}
|
||||||
|
|
|
@ -5,25 +5,50 @@ export class Emitter {
|
||||||
|
|
||||||
emit(node: Syntax) {
|
emit(node: Syntax) {
|
||||||
|
|
||||||
debug(node);
|
let out = '';
|
||||||
|
|
||||||
switch (node.kind) {
|
switch (node.kind) {
|
||||||
|
|
||||||
case SyntaxKind.JSReferenceExpression:
|
case SyntaxKind.JSReferenceExpression:
|
||||||
return node.name;
|
out += node.name;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SyntaxKind.JSConstantExpression:
|
||||||
|
if (typeof node.value === 'string') {
|
||||||
|
out += '"' + node.value + '"';
|
||||||
|
} else if (typeof node.value === 'bigint') {
|
||||||
|
out += node.value.toString();
|
||||||
|
} else {
|
||||||
|
throw new Error(`Could not emit the value of a specific JSConstantExpression.`);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SyntaxKind.JSFunctionDeclaration:
|
||||||
|
out += 'function ' + node.name.text + '(';
|
||||||
|
//out += node.params.map(p => this.emit(p)).join(', ');
|
||||||
|
out += ') {\n';
|
||||||
|
out += '}\n\n'
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SyntaxKind.JSCallExpression:
|
||||||
|
out += this.emit(node.operator) + '(';
|
||||||
|
out += node.operands.map(op => this.emit(op)).join(', ');
|
||||||
|
out += ')'
|
||||||
|
break;
|
||||||
|
|
||||||
case SyntaxKind.JSSourceFile:
|
case SyntaxKind.JSSourceFile:
|
||||||
let out = ''
|
|
||||||
for (const element of node.elements) {
|
for (const element of node.elements) {
|
||||||
out += this.emit(element);
|
out += this.emit(element);
|
||||||
}
|
}
|
||||||
return out;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
throw new Error(`Could not emit source code for ${kindToString(node.kind)}`)
|
throw new Error(`Could not emit source code for ${kindToString(node.kind)}`)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return out;
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
|
|
||||||
import {
|
import {
|
||||||
SyntaxKind,
|
SyntaxKind,
|
||||||
|
setParents,
|
||||||
kindToString,
|
kindToString,
|
||||||
BoltSyntax,
|
BoltSyntax,
|
||||||
BoltSentence,
|
BoltSentence,
|
||||||
|
@ -35,20 +36,13 @@ import { TextSpan } from "./text"
|
||||||
import { TypeChecker } from "./checker"
|
import { TypeChecker } from "./checker"
|
||||||
import { Parser, ParseError } from "./parser"
|
import { Parser, ParseError } from "./parser"
|
||||||
import { Evaluator, TRUE, FALSE } from "./evaluator"
|
import { Evaluator, TRUE, FALSE } from "./evaluator"
|
||||||
import { StreamWrapper, setOrigNodeRange, BoltTokenStream } from "./util"
|
import { StreamWrapper, setOrigNodeRange, BoltTokenStream, createTokenStream } from "./util"
|
||||||
|
|
||||||
interface Transformer {
|
interface Transformer {
|
||||||
pattern: BoltPattern;
|
pattern: BoltPattern;
|
||||||
transform: (node: BoltTokenStream) => BoltSyntax;
|
transform: (node: BoltTokenStream) => BoltSyntax;
|
||||||
}
|
}
|
||||||
|
|
||||||
function createTokenStream(node: BoltSentence) {
|
|
||||||
return new StreamWrapper(
|
|
||||||
node.tokens,
|
|
||||||
() => createBoltEOS(new TextSpan(node.span!.file, node.span!.end.clone(), node.span!.end.clone()))
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function createSimpleBoltReferenceTypeNode(text: string): BoltReferenceTypeNode {
|
function createSimpleBoltReferenceTypeNode(text: string): BoltReferenceTypeNode {
|
||||||
const ids = text.split('.').map(name => createBoltIdentifier(name))
|
const ids = text.split('.').map(name => createBoltIdentifier(name))
|
||||||
return createBoltReferenceTypeNode(createBoltQualName(ids.slice(0, -1), ids[ids.length-1]), [])
|
return createBoltReferenceTypeNode(createBoltQualName(ids.slice(0, -1), ids[ids.length-1]), [])
|
||||||
|
@ -145,6 +139,7 @@ export class Expander {
|
||||||
|
|
||||||
const newSourceFile = createBoltSourceFile(expanded);
|
const newSourceFile = createBoltSourceFile(expanded);
|
||||||
setOrigNodeRange(newSourceFile, node, node);
|
setOrigNodeRange(newSourceFile, node, node);
|
||||||
|
setParents(newSourceFile);
|
||||||
return newSourceFile;
|
return newSourceFile;
|
||||||
|
|
||||||
} else if (node.kind == SyntaxKind.BoltModule) {
|
} else if (node.kind == SyntaxKind.BoltModule) {
|
||||||
|
@ -170,6 +165,7 @@ export class Expander {
|
||||||
|
|
||||||
const newModule = createBoltModule(0, node.name, expanded);
|
const newModule = createBoltModule(0, node.name, expanded);
|
||||||
setOrigNodeRange(newModule, node, node);
|
setOrigNodeRange(newModule, node, node);
|
||||||
|
setParents(newModule);
|
||||||
return newModule;
|
return newModule;
|
||||||
|
|
||||||
} else if (node.kind === SyntaxKind.BoltSentence) {
|
} else if (node.kind === SyntaxKind.BoltSentence) {
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
|
|
||||||
|
import * as acorn from "acorn"
|
||||||
|
|
||||||
import {
|
import {
|
||||||
SyntaxKind,
|
SyntaxKind,
|
||||||
kindToString,
|
kindToString,
|
||||||
|
@ -45,9 +47,12 @@ import {
|
||||||
BoltFunctionDeclaration,
|
BoltFunctionDeclaration,
|
||||||
createBoltFunctionDeclaration,
|
createBoltFunctionDeclaration,
|
||||||
createBoltCallExpression,
|
createBoltCallExpression,
|
||||||
|
BoltSymbol,
|
||||||
} from "./ast"
|
} from "./ast"
|
||||||
|
|
||||||
import { BoltTokenStream, setOrigNodeRange } from "./util"
|
import { Stream, setOrigNodeRange, createTokenStream, uniq } from "./util"
|
||||||
|
|
||||||
|
export type BoltTokenStream = Stream<BoltToken>;
|
||||||
|
|
||||||
function describeKind(kind: SyntaxKind): string {
|
function describeKind(kind: SyntaxKind): string {
|
||||||
switch (kind) {
|
switch (kind) {
|
||||||
|
@ -148,10 +153,10 @@ const KIND_EXPRESSION_T0 = [
|
||||||
SyntaxKind.BoltYieldKeyword,
|
SyntaxKind.BoltYieldKeyword,
|
||||||
]
|
]
|
||||||
|
|
||||||
const KIND_STATEMENT_T0 = [
|
const KIND_STATEMENT_T0 = uniq([
|
||||||
SyntaxKind.BoltReturnKeyword,
|
SyntaxKind.BoltReturnKeyword,
|
||||||
...KIND_EXPRESSION_T0,
|
...KIND_EXPRESSION_T0,
|
||||||
]
|
])
|
||||||
|
|
||||||
const KIND_DECLARATION_KEYWORD = [
|
const KIND_DECLARATION_KEYWORD = [
|
||||||
SyntaxKind.BoltFnKeyword,
|
SyntaxKind.BoltFnKeyword,
|
||||||
|
@ -162,18 +167,18 @@ const KIND_DECLARATION_KEYWORD = [
|
||||||
SyntaxKind.BoltStructKeyword,
|
SyntaxKind.BoltStructKeyword,
|
||||||
]
|
]
|
||||||
|
|
||||||
const KIND_DECLARATION_T0 = [
|
const KIND_DECLARATION_T0 = uniq([
|
||||||
SyntaxKind.BoltPubKeyword,
|
SyntaxKind.BoltPubKeyword,
|
||||||
SyntaxKind.BoltForeignKeyword,
|
SyntaxKind.BoltForeignKeyword,
|
||||||
...KIND_DECLARATION_KEYWORD,
|
...KIND_DECLARATION_KEYWORD,
|
||||||
]
|
])
|
||||||
|
|
||||||
const KIND_SOURCEELEMENT_T0 = [
|
const KIND_SOURCEELEMENT_T0 = uniq([
|
||||||
SyntaxKind.BoltModKeyword,
|
SyntaxKind.BoltModKeyword,
|
||||||
...KIND_EXPRESSION_T0,
|
...KIND_EXPRESSION_T0,
|
||||||
...KIND_STATEMENT_T0,
|
...KIND_STATEMENT_T0,
|
||||||
...KIND_DECLARATION_T0,
|
...KIND_DECLARATION_T0,
|
||||||
]
|
])
|
||||||
|
|
||||||
export class Parser {
|
export class Parser {
|
||||||
|
|
||||||
|
@ -213,6 +218,10 @@ export class Parser {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public parse(kind: SyntaxKind, tokens: BoltTokenStream): BoltSyntax {
|
||||||
|
return (this as any)['parse' + kindToString(kind).substring('Bolt'.length)](tokens);
|
||||||
|
}
|
||||||
|
|
||||||
public parseQualName(tokens: BoltTokenStream): BoltQualName {
|
public parseQualName(tokens: BoltTokenStream): BoltQualName {
|
||||||
|
|
||||||
const path: BoltIdentifier[] = [];
|
const path: BoltIdentifier[] = [];
|
||||||
|
@ -373,7 +382,7 @@ export class Parser {
|
||||||
//}
|
//}
|
||||||
|
|
||||||
public parseExpression(tokens: BoltTokenStream): BoltExpression {
|
public parseExpression(tokens: BoltTokenStream): BoltExpression {
|
||||||
return this.parsePrimitiveExpression(tokens)
|
return this.parseCallOrPrimitiveExpression(tokens)
|
||||||
}
|
}
|
||||||
|
|
||||||
public parseParameter(tokens: BoltTokenStream): BoltParameter {
|
public parseParameter(tokens: BoltTokenStream): BoltParameter {
|
||||||
|
@ -627,7 +636,7 @@ export class Parser {
|
||||||
let lastToken: BoltSyntax;
|
let lastToken: BoltSyntax;
|
||||||
const firstToken = k0;
|
const firstToken = k0;
|
||||||
|
|
||||||
if (k0.kind !== SyntaxKind.BoltPubKeyword) {
|
if (k0.kind === SyntaxKind.BoltPubKeyword) {
|
||||||
tokens.get();
|
tokens.get();
|
||||||
modifiers |= BoltDeclarationModifiers.Public;
|
modifiers |= BoltDeclarationModifiers.Public;
|
||||||
k0 = tokens.peek();
|
k0 = tokens.peek();
|
||||||
|
@ -650,9 +659,9 @@ export class Parser {
|
||||||
|
|
||||||
tokens.get();
|
tokens.get();
|
||||||
|
|
||||||
let name: BoltQualName;
|
let name: BoltSymbol;
|
||||||
let returnType = null;
|
let returnType = null;
|
||||||
let body = null;
|
let body: any = null; // FIXME type-checking should not be disabled
|
||||||
let params: BoltParameter[] = [];
|
let params: BoltParameter[] = [];
|
||||||
|
|
||||||
// Parse parameters
|
// Parse parameters
|
||||||
|
@ -687,16 +696,14 @@ export class Parser {
|
||||||
|
|
||||||
if (t0.kind === SyntaxKind.BoltOperator) {
|
if (t0.kind === SyntaxKind.BoltOperator) {
|
||||||
|
|
||||||
name = createBoltQualName([], t0);
|
name = t0;
|
||||||
setOrigNodeRange(name, t0, t0);
|
|
||||||
tokens.get();
|
tokens.get();
|
||||||
params.push(parseParamLike(tokens))
|
params.push(parseParamLike(tokens))
|
||||||
|
|
||||||
} else if (isParamLike(t0) && t1.kind == SyntaxKind.BoltOperator) {
|
} else if (isParamLike(t0) && t1.kind == SyntaxKind.BoltOperator) {
|
||||||
|
|
||||||
params.push(parseParamLike(tokens));
|
params.push(parseParamLike(tokens));
|
||||||
name = createBoltQualName([], t1);
|
name = t1;
|
||||||
setOrigNodeRange(name, t1, t1);
|
|
||||||
while (true) {
|
while (true) {
|
||||||
const t2 = tokens.peek();
|
const t2 = tokens.peek();
|
||||||
if (t2.kind !== SyntaxKind.BoltOperator) {
|
if (t2.kind !== SyntaxKind.BoltOperator) {
|
||||||
|
@ -711,7 +718,8 @@ export class Parser {
|
||||||
|
|
||||||
} else if (t0.kind === SyntaxKind.BoltIdentifier) {
|
} else if (t0.kind === SyntaxKind.BoltIdentifier) {
|
||||||
|
|
||||||
name = this.parseQualName(tokens)
|
name = t0;
|
||||||
|
tokens.get();
|
||||||
const t2 = tokens.get();
|
const t2 = tokens.get();
|
||||||
if (t2.kind === SyntaxKind.BoltParenthesized) {
|
if (t2.kind === SyntaxKind.BoltParenthesized) {
|
||||||
const innerTokens = createTokenStream(t2);
|
const innerTokens = createTokenStream(t2);
|
||||||
|
@ -762,8 +770,7 @@ export class Parser {
|
||||||
body = this.parseStatements(tokens);
|
body = this.parseStatements(tokens);
|
||||||
break;
|
break;
|
||||||
case "JS":
|
case "JS":
|
||||||
// TODO
|
body = acorn.parse(t3.text);
|
||||||
//body = acorn.parse(t3.text).body;
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw new Error(`Unrecognised language: ${target}`);
|
throw new Error(`Unrecognised language: ${target}`);
|
||||||
|
@ -787,7 +794,8 @@ export class Parser {
|
||||||
let t0 = tokens.peek(1);
|
let t0 = tokens.peek(1);
|
||||||
let i = 1;
|
let i = 1;
|
||||||
if (t0.kind === SyntaxKind.BoltPubKeyword) {
|
if (t0.kind === SyntaxKind.BoltPubKeyword) {
|
||||||
t0 = tokens.peek(i++);
|
i += 1;
|
||||||
|
t0 = tokens.peek(i);
|
||||||
if (t0.kind !== SyntaxKind.BoltForeignKeyword) {
|
if (t0.kind !== SyntaxKind.BoltForeignKeyword) {
|
||||||
if (KIND_DECLARATION_KEYWORD.indexOf(t0.kind) === -1) {
|
if (KIND_DECLARATION_KEYWORD.indexOf(t0.kind) === -1) {
|
||||||
throw new ParseError(t0, KIND_DECLARATION_KEYWORD);
|
throw new ParseError(t0, KIND_DECLARATION_KEYWORD);
|
||||||
|
@ -818,22 +826,22 @@ export class Parser {
|
||||||
throw new ParseError(t0, KIND_DECLARATION_T0);
|
throw new ParseError(t0, KIND_DECLARATION_T0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public parseSourceElement(tokens: BoltTokenStream): BoltSourceElement {
|
public parseSourceElement(tokens: BoltTokenStream): BoltSourceElement {
|
||||||
const t0 = tokens.peek();
|
const t0 = tokens.peek();
|
||||||
try {
|
try {
|
||||||
return this.parseDeclaration(tokens)
|
return this.parseDeclaration(tokens)
|
||||||
} catch (e) {
|
} catch (e1) {
|
||||||
if (!(e instanceof ParseError)) {
|
if (!(e1 instanceof ParseError)) {
|
||||||
throw e;
|
throw e1;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
return this.parseStatement(tokens);
|
return this.parseStatement(tokens);
|
||||||
} catch (e) {
|
} catch (e2) {
|
||||||
if (!(e instanceof ParseError)) {
|
if (!(e2 instanceof ParseError)) {
|
||||||
throw e;
|
throw e2;
|
||||||
}
|
}
|
||||||
throw new ParseError(t0, KIND_SOURCEELEMENT_T0)
|
throw e1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -879,14 +887,17 @@ export class Parser {
|
||||||
// return lhs
|
// return lhs
|
||||||
//}
|
//}
|
||||||
|
|
||||||
public parseCallExpression(tokens: BoltTokenStream): BoltCallExpression {
|
public parseCallOrPrimitiveExpression(tokens: BoltTokenStream): BoltExpression {
|
||||||
|
|
||||||
const operator = this.parsePrimitiveExpression(tokens)
|
const operator = this.parsePrimitiveExpression(tokens)
|
||||||
const args: BoltExpression[] = []
|
|
||||||
|
|
||||||
const t2 = tokens.get();
|
const t2 = tokens.get();
|
||||||
|
if (t2.kind === SyntaxKind.BoltEOS) {
|
||||||
|
return operator;
|
||||||
|
}
|
||||||
assertToken(t2, SyntaxKind.BoltParenthesized);
|
assertToken(t2, SyntaxKind.BoltParenthesized);
|
||||||
|
|
||||||
|
const args: BoltExpression[] = []
|
||||||
const innerTokens = createTokenStream(t2);
|
const innerTokens = createTokenStream(t2);
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
|
@ -903,7 +914,9 @@ export class Parser {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return createBoltCallExpression(operator, args, null)
|
const node = createBoltCallExpression(operator, args, null)
|
||||||
|
setOrigNodeRange(node, operator, t2);
|
||||||
|
return node;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
119
src/program.ts
119
src/program.ts
|
@ -1,6 +1,8 @@
|
||||||
|
|
||||||
import * as path from "path"
|
import * as path from "path"
|
||||||
import * as fs from "fs-extra"
|
import * as fs from "fs-extra"
|
||||||
|
import { now } from "microtime"
|
||||||
|
import { EventEmitter } from "events"
|
||||||
|
|
||||||
import { Parser } from "./parser"
|
import { Parser } from "./parser"
|
||||||
import { TypeChecker } from "./checker"
|
import { TypeChecker } from "./checker"
|
||||||
|
@ -10,9 +12,10 @@ import { Scanner } from "./scanner"
|
||||||
import { Compiler } from "./compiler"
|
import { Compiler } from "./compiler"
|
||||||
import { emit } from "./emitter"
|
import { emit } from "./emitter"
|
||||||
import { TextFile } from "./text"
|
import { TextFile } from "./text"
|
||||||
import { BoltSourceFile, Syntax } from "./ast"
|
import { BoltSourceFile, Syntax, JSSourceFile } from "./ast"
|
||||||
import { upsearchSync, FastStringMap, getFileStem, getLanguage } from "./util"
|
import { upsearchSync, FastStringMap, getFileStem, getLanguage } from "./util"
|
||||||
import { Package } from "./package"
|
import { Package } from "./package"
|
||||||
|
import { verbose, memoize } from "./util"
|
||||||
|
|
||||||
const targetExtensions: FastStringMap<string> = {
|
const targetExtensions: FastStringMap<string> = {
|
||||||
'JS': '.mjs',
|
'JS': '.mjs',
|
||||||
|
@ -20,55 +23,106 @@ const targetExtensions: FastStringMap<string> = {
|
||||||
'C': '.c',
|
'C': '.c',
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export interface TransformationContext {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
interface TimingInfo {
|
||||||
|
timestamp: number;
|
||||||
|
refCount: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
class Timing extends EventEmitter {
|
||||||
|
|
||||||
|
private runningTasks: FastStringMap<TimingInfo> = Object.create(null);
|
||||||
|
|
||||||
|
public start(name: string) {
|
||||||
|
if (this.runningTasks[name] !== undefined) {
|
||||||
|
this.runningTasks[name].refCount++;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.runningTasks[name] = { timestamp: now(), refCount: 1 };
|
||||||
|
this.emit(`start ${name}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
public end(name: string) {
|
||||||
|
if (this.runningTasks[name] === undefined) {
|
||||||
|
throw new Error(`Task '${name}' was never started.`);
|
||||||
|
}
|
||||||
|
const info = this.runningTasks[name];
|
||||||
|
info.refCount--;
|
||||||
|
if (info.refCount === 0) {
|
||||||
|
const usecs = now() - info.timestamp;
|
||||||
|
verbose(`Task '${name}' completed after ${usecs} microseconds.`);
|
||||||
|
this.emit(`end ${name}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
export class Program {
|
export class Program {
|
||||||
|
|
||||||
public parser: Parser
|
public parser: Parser
|
||||||
public evaluator: Evaluator;
|
public evaluator: Evaluator;
|
||||||
public checker: TypeChecker;
|
public checker: TypeChecker;
|
||||||
public expander: Expander;
|
public expander: Expander;
|
||||||
|
public timing: Timing;
|
||||||
|
|
||||||
private sourceFiles = new Map<string, BoltSourceFile>();
|
constructor(public files: string[]) {
|
||||||
private packages: FastStringMap<Package> = Object.create(null);
|
|
||||||
|
|
||||||
constructor(files: TextFile[]) {
|
|
||||||
this.checker = new TypeChecker();
|
this.checker = new TypeChecker();
|
||||||
this.parser = new Parser();
|
this.parser = new Parser();
|
||||||
this.evaluator = new Evaluator(this.checker);
|
this.evaluator = new Evaluator(this.checker);
|
||||||
this.expander = new Expander(this.parser, this.evaluator, this.checker);
|
this.expander = new Expander(this.parser, this.evaluator, this.checker);
|
||||||
for (const file of files) {
|
this.timing = new Timing();
|
||||||
console.log(`Loading ${file.origPath} ...`);
|
|
||||||
const contents = fs.readFileSync(file.fullPath, 'utf8');
|
|
||||||
const scanner = new Scanner(file, contents)
|
|
||||||
this.sourceFiles.set(file.fullPath, scanner.scan());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@memoize
|
||||||
|
public getTextFile(filename: string): TextFile {
|
||||||
|
return new TextFile(filename);
|
||||||
|
}
|
||||||
|
|
||||||
|
@memoize
|
||||||
|
public getSourceFile(file: TextFile): BoltSourceFile {
|
||||||
|
this.timing.start('read');
|
||||||
|
const contents = fs.readFileSync(file.origPath, 'utf8');
|
||||||
|
this.timing.end('read');
|
||||||
|
const scanner = new Scanner(file, contents)
|
||||||
|
this.timing.start('scan');
|
||||||
|
const sourceFile = scanner.scan();
|
||||||
|
this.timing.end('scan');
|
||||||
|
return sourceFile;
|
||||||
|
}
|
||||||
|
|
||||||
|
@memoize
|
||||||
|
public getFullyExpandedSourceFile(file: TextFile): BoltSourceFile {
|
||||||
|
const sourceFile = this.getSourceFile(file);
|
||||||
|
this.timing.start('expand');
|
||||||
|
const expanded = this.expander.getFullyExpanded(sourceFile) as BoltSourceFile;
|
||||||
|
this.timing.end('expand');
|
||||||
|
return expanded;
|
||||||
|
}
|
||||||
|
|
||||||
|
@memoize
|
||||||
public getPackage(filepath: string) {
|
public getPackage(filepath: string) {
|
||||||
filepath = path.resolve(filepath);
|
const file = this.getTextFile(filepath)
|
||||||
const projectFile = upsearchSync('Boltfile', path.dirname(filepath));
|
const projectFile = upsearchSync('Boltfile', path.dirname(file.fullPath));
|
||||||
if (projectFile === null) {
|
if (projectFile === null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
const projectDir = path.resolve(path.dirname(projectFile));
|
const projectDir = path.resolve(path.dirname(projectFile));
|
||||||
if (this.packages[projectDir] !== undefined) {
|
return new Package(projectDir);
|
||||||
return this.packages[projectDir];
|
|
||||||
}
|
|
||||||
return this.packages[projectDir] = new Package(projectDir);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public compile(target: string) {
|
public compile(target: string) {
|
||||||
const compiler = new Compiler(this, this.checker, { target })
|
const compiler = new Compiler(this, this.checker, { target })
|
||||||
const expanded: SourceFile[] = [];
|
const expanded = this.files.map(filename => this.getFullyExpandedSourceFile(this.getTextFile(filename)));
|
||||||
for (const [filepath, sourceFile] of this.sourceFiles) {
|
const compiled = compiler.compile(expanded) as JSSourceFile[];
|
||||||
expanded.push(this.expander.getFullyExpanded(sourceFile) as SourceFile);
|
|
||||||
}
|
|
||||||
const compiled = compiler.compile(expanded) as AnySourceFile[];
|
|
||||||
for (const rootNode of compiled) {
|
for (const rootNode of compiled) {
|
||||||
const filepath = rootNode.span!.file.fullPath;
|
//const filepath = rootNode.span!.file.fullPath;
|
||||||
const pkg = this.getPackage(filepath);
|
//const pkg = this.getPackage(filepath);
|
||||||
if (pkg !== null) {
|
//if (pkg !== null) {
|
||||||
|
//
|
||||||
}
|
//}
|
||||||
fs.mkdirp('.bolt-work');
|
fs.mkdirp('.bolt-work');
|
||||||
fs.writeFileSync(this.mapToTargetFile(rootNode), emit(rootNode), 'utf8');
|
fs.writeFileSync(this.mapToTargetFile(rootNode), emit(rootNode), 'utf8');
|
||||||
}
|
}
|
||||||
|
@ -78,13 +132,12 @@ export class Program {
|
||||||
return path.join('.bolt-work', getFileStem(node.span!.file.fullPath) + getDefaultExtension(getLanguage(node)));
|
return path.join('.bolt-work', getFileStem(node.span!.file.fullPath) + getDefaultExtension(getLanguage(node)));
|
||||||
}
|
}
|
||||||
|
|
||||||
eval(filename: string) {
|
public eval() {
|
||||||
const original = this.sourceFiles.get(filename);
|
for (const filename of this.files) {
|
||||||
if (original === undefined) {
|
const file = this.getTextFile(filename);
|
||||||
throw new Error(`File ${filename} does not seem to be part of this Program.`)
|
const expanded = this.getFullyExpandedSourceFile(file);
|
||||||
|
this.evaluator.eval(expanded)
|
||||||
}
|
}
|
||||||
const expanded = this.expander.getFullyExpanded(original) as BoltSourceFile;
|
|
||||||
return this.evaluator.eval(expanded)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
3
src/renamer.ts
Normal file
3
src/renamer.ts
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -8,6 +8,7 @@ import {
|
||||||
} from "./text"
|
} from "./text"
|
||||||
|
|
||||||
import {
|
import {
|
||||||
|
setParents,
|
||||||
SyntaxKind,
|
SyntaxKind,
|
||||||
BoltToken,
|
BoltToken,
|
||||||
BoltSentence,
|
BoltSentence,
|
||||||
|
@ -27,6 +28,18 @@ import {
|
||||||
createBoltEOS,
|
createBoltEOS,
|
||||||
createBoltDot,
|
createBoltDot,
|
||||||
createBoltEqSign,
|
createBoltEqSign,
|
||||||
|
createBoltPubKeyword,
|
||||||
|
createBoltMutKeyword,
|
||||||
|
createBoltStructKeyword,
|
||||||
|
createBoltEnumKeyword,
|
||||||
|
createBoltForeignKeyword,
|
||||||
|
createBoltAssignment,
|
||||||
|
createBoltYieldKeyword,
|
||||||
|
createBoltReturnKeyword,
|
||||||
|
createBoltFnKeyword,
|
||||||
|
createBoltLArrow,
|
||||||
|
createBoltDotDot,
|
||||||
|
createBoltNewTypeKeyword,
|
||||||
} from "./ast"
|
} from "./ast"
|
||||||
|
|
||||||
export enum PunctType {
|
export enum PunctType {
|
||||||
|
@ -122,14 +135,13 @@ function isIdentPart(ch: string) {
|
||||||
return ch == '_' || XRegExp('\\p{L}').test(ch)
|
return ch == '_' || XRegExp('\\p{L}').test(ch)
|
||||||
}
|
}
|
||||||
|
|
||||||
function isOperatorStart(ch: string) {
|
function isSymbol(ch: string) {
|
||||||
return /[+\-*\/%$!><]/.test(ch)
|
return /[=+\/-*%$!><&^|]/.test(ch)
|
||||||
}
|
}
|
||||||
|
|
||||||
function isOperatorPart(ch: string) {
|
//function isOperatorPart(ch: string) {
|
||||||
return /[=+\-*\/%$!><]/.test(ch)
|
//return /[=+\-*\/%$!><]/.test(ch)
|
||||||
|
//}
|
||||||
}
|
|
||||||
|
|
||||||
const EOF = ''
|
const EOF = ''
|
||||||
|
|
||||||
|
@ -210,12 +222,6 @@ export class Scanner {
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (c0) {
|
switch (c0) {
|
||||||
case '.':
|
|
||||||
this.getChar();
|
|
||||||
return createBoltDot(new TextSpan(this.file, startPos, this.currPos.clone()));
|
|
||||||
case '=':
|
|
||||||
this.getChar();
|
|
||||||
return createBoltEqSign(new TextSpan(this.file, startPos, this.currPos.clone()));
|
|
||||||
case ';':
|
case ';':
|
||||||
this.getChar();
|
this.getChar();
|
||||||
return createBoltSemi(new TextSpan(this.file, startPos, this.currPos.clone()));
|
return createBoltSemi(new TextSpan(this.file, startPos, this.currPos.clone()));
|
||||||
|
@ -304,18 +310,42 @@ export class Scanner {
|
||||||
|
|
||||||
const name = this.takeWhile(isIdentPart);
|
const name = this.takeWhile(isIdentPart);
|
||||||
const endPos = this.currPos.clone();
|
const endPos = this.currPos.clone();
|
||||||
return createBoltIdentifier(name, new TextSpan(this.file, startPos, endPos))
|
const span = new TextSpan(this.file, startPos, endPos);
|
||||||
|
switch (name) {
|
||||||
|
case 'pub': return createBoltPubKeyword(span);
|
||||||
|
case 'fn': return createBoltFnKeyword(span);
|
||||||
|
case 'return': return createBoltReturnKeyword(span);
|
||||||
|
case 'yield': return createBoltYieldKeyword(span);
|
||||||
|
case 'foreign': return createBoltForeignKeyword(span);
|
||||||
|
case 'let': return createBoltPubKeyword(span);
|
||||||
|
case 'mut': return createBoltMutKeyword(span);
|
||||||
|
case 'struct': return createBoltStructKeyword(span);
|
||||||
|
case 'enum': return createBoltEnumKeyword(span);
|
||||||
|
case 'newtype': return createBoltNewTypeKeyword(span);
|
||||||
|
default: return createBoltIdentifier(name, span);
|
||||||
|
}
|
||||||
|
|
||||||
} else if (isOperatorStart(c0)) {
|
} else if (isSymbol(c0)) {
|
||||||
|
|
||||||
const text = this.takeWhile(isOperatorPart)
|
const text = this.takeWhile(isSymbol)
|
||||||
const endPos = this.currPos.clone()
|
const endPos = this.currPos.clone()
|
||||||
const span = new TextSpan(this.file, startPos, endPos);
|
const span = new TextSpan(this.file, startPos, endPos);
|
||||||
|
|
||||||
if (text === '->') {
|
if (text.endsWith('=')) {
|
||||||
return createBoltRArrow(span);
|
const operator = text.substring(0, text.length-1);
|
||||||
} else {
|
if (text === '==') {
|
||||||
return createBoltOperator(text, span);
|
return createBoltOperator(text, span);
|
||||||
|
}
|
||||||
|
return createBoltAssignment(operator.length === 0 ? null : operator, span);
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (text) {
|
||||||
|
case '->': return createBoltRArrow(span);
|
||||||
|
case '<-': return createBoltLArrow(span);
|
||||||
|
case '.': return createBoltDot(span);
|
||||||
|
case '..': return createBoltDotDot(span);
|
||||||
|
case '=': return createBoltEqSign(span);
|
||||||
|
default: return createBoltOperator(text, span);
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
@ -385,7 +415,9 @@ export class Scanner {
|
||||||
const startPos = this.currPos.clone();
|
const startPos = this.currPos.clone();
|
||||||
const elements = this.scanTokens();
|
const elements = this.scanTokens();
|
||||||
const endPos = this.currPos.clone();
|
const endPos = this.currPos.clone();
|
||||||
return createBoltSourceFile(elements, new TextSpan(this.file, startPos, endPos));
|
const sourceFile = createBoltSourceFile(elements, new TextSpan(this.file, startPos, endPos));
|
||||||
|
setParents(sourceFile);
|
||||||
|
return sourceFile;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,6 +13,26 @@ function isSyntax(value) {
|
||||||
&& value.__NODE_TYPE !== undefined;
|
&& value.__NODE_TYPE !== undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function* getChildNodes(node) {
|
||||||
|
for (const key of Object.keys(node)) {
|
||||||
|
if (key === 'span' || key === 'parentNode') {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
const value = node[key];
|
||||||
|
if (Array.isArray(value)) {
|
||||||
|
for (const element of value) {
|
||||||
|
if (isSyntax(element)) {
|
||||||
|
yield element;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (isSyntax(value)) {
|
||||||
|
if (isSyntax(value)) {
|
||||||
|
yield value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function createNode(nodeType) {
|
function createNode(nodeType) {
|
||||||
const obj = Object.create(nodeProto);
|
const obj = Object.create(nodeProto);
|
||||||
Object.defineProperty(obj, '__NODE_TYPE', {
|
Object.defineProperty(obj, '__NODE_TYPE', {
|
||||||
|
@ -66,6 +86,13 @@ for (const nodeName of Object.keys(NODE_TYPES)) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
exported.setParents = function setParents(node, parentNode = null) {
|
||||||
|
node.parentNode = parentNode;
|
||||||
|
for (const child of getChildNodes(node)) {
|
||||||
|
setParents(child, node)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (typeof module !== 'undefined') {
|
if (typeof module !== 'undefined') {
|
||||||
module.exports = exports;
|
module.exports = exports;
|
||||||
}
|
}
|
||||||
|
|
|
@ -106,6 +106,8 @@ export function generateAST(decls: Declaration[]) {
|
||||||
|
|
||||||
import { TextSpan } from "./text"
|
import { TextSpan } from "./text"
|
||||||
|
|
||||||
|
export function setParents(node: Syntax): void;
|
||||||
|
|
||||||
export type SyntaxRange = [Syntax, Syntax];
|
export type SyntaxRange = [Syntax, Syntax];
|
||||||
|
|
||||||
interface SyntaxBase {
|
interface SyntaxBase {
|
||||||
|
|
|
@ -1,4 +1,10 @@
|
||||||
|
|
||||||
|
import * as path from "path"
|
||||||
|
|
||||||
|
export function getFileStem(filepath: string): string {
|
||||||
|
return path.basename(filepath).split('.')[0];
|
||||||
|
}
|
||||||
|
|
||||||
function isWhiteSpace(ch: string) {
|
function isWhiteSpace(ch: string) {
|
||||||
return /[\r\t ]/.test(ch);
|
return /[\r\t ]/.test(ch);
|
||||||
}
|
}
|
||||||
|
|
101
src/util.ts
101
src/util.ts
|
@ -1,20 +1,107 @@
|
||||||
|
|
||||||
import * as path from "path"
|
import * as path from "path"
|
||||||
import * as fs from "fs"
|
import * as fs from "fs"
|
||||||
|
import moment from "moment"
|
||||||
|
import chalk from "chalk"
|
||||||
|
|
||||||
import { TextSpan } from "./text"
|
import { TextSpan, TextPos } from "./text"
|
||||||
import { kindToString, Syntax, BoltToken, BoltQualName, BoltDeclaration, BoltDeclarationModifiers } from "./ast"
|
import { Scanner } from "./scanner"
|
||||||
|
import { kindToString, Syntax, BoltQualName, BoltDeclaration, BoltDeclarationModifiers, createBoltEOS, SyntaxKind, isBoltPunctuated } from "./ast"
|
||||||
|
|
||||||
export type BoltTokenStream = Stream<BoltToken>;
|
export function createTokenStream(node: Syntax) {
|
||||||
|
if (isBoltPunctuated(node)) {
|
||||||
|
const origPos = node.span!.start;
|
||||||
|
const startPos = new TextPos(origPos.offset+1, origPos.line, origPos.column+1);
|
||||||
|
return new Scanner(node.span!.file, node.text, startPos);
|
||||||
|
} else if (node.kind === SyntaxKind.BoltSentence) {
|
||||||
|
return new StreamWrapper(
|
||||||
|
node.tokens,
|
||||||
|
() => createBoltEOS(new TextSpan(node.span!.file, node.span!.end.clone(), node.span!.end.clone()))
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
throw new Error(`Could not convert ${kindToString(node.kind)} to a token stream.`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export interface JsonArray extends Array<Json> { };
|
export interface JsonArray extends Array<Json> { };
|
||||||
export interface JsonObject { [key: string]: Json }
|
export interface JsonObject { [key: string]: Json }
|
||||||
export type Json = null | string | boolean | number | JsonArray | JsonObject;
|
export type Json = null | string | boolean | number | JsonArray | JsonObject;
|
||||||
|
|
||||||
|
export function uniq<T>(elements: T[]): T[] {
|
||||||
|
const out: T[] = [];
|
||||||
|
const visited = new Set<T>();
|
||||||
|
for (const element of elements) {
|
||||||
|
if (visited.has(element)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
visited.add(element);
|
||||||
|
out.push(element);
|
||||||
|
}
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
export interface FastStringMap<T> {
|
export interface FastStringMap<T> {
|
||||||
[key: string]: T
|
[key: string]: T
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class DeepMap {
|
||||||
|
|
||||||
|
private rootMap = new Map<any, any>();
|
||||||
|
|
||||||
|
public has(key: any[]) {
|
||||||
|
let curr = this.rootMap;
|
||||||
|
for (const element of key) {
|
||||||
|
if (!curr.has(element)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
curr = curr.get(element)!;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public get(key: any[]) {
|
||||||
|
let curr = this.rootMap;
|
||||||
|
for (const element of key) {
|
||||||
|
if (!curr.has(element)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
curr = curr.get(element)!;
|
||||||
|
}
|
||||||
|
return curr;
|
||||||
|
}
|
||||||
|
|
||||||
|
public set(key: any[], value: any) {
|
||||||
|
let curr = this.rootMap;
|
||||||
|
for (const element of key.slice(0, -1)) {
|
||||||
|
if (!curr.has(element)) {
|
||||||
|
curr.set(element, new Map());
|
||||||
|
}
|
||||||
|
curr = curr.get(element)!;
|
||||||
|
}
|
||||||
|
curr.set(key[key.length-1], value);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
export function memoize(target: any, key: PropertyKey) {
|
||||||
|
const origMethod = target[key];
|
||||||
|
target[key] = function wrapper(...args: any[]) {
|
||||||
|
if (this.__MEMOIZE_CACHE === undefined) {
|
||||||
|
this.__MEMOIZE_CACHE = Object.create(null);
|
||||||
|
}
|
||||||
|
if (this.__MEMOIZE_CACHE[key] === undefined) {
|
||||||
|
this.__MEMOIZE_CACHE[key] = new DeepMap();
|
||||||
|
}
|
||||||
|
const cache = this.__MEMOIZE_CACHE[key];
|
||||||
|
if (cache.has(args)) {
|
||||||
|
return cache.get(args);
|
||||||
|
}
|
||||||
|
const result = origMethod.apply(this, args);
|
||||||
|
cache.set(args, result);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const supportedLanguages = ['Bolt', 'JS'];
|
const supportedLanguages = ['Bolt', 'JS'];
|
||||||
|
|
||||||
export function getLanguage(node: Syntax): string {
|
export function getLanguage(node: Syntax): string {
|
||||||
|
@ -39,7 +126,7 @@ export function setOrigNodeRange(node: Syntax, startNode: Syntax, endNode: Synta
|
||||||
}
|
}
|
||||||
|
|
||||||
export function hasPublicModifier(node: BoltDeclaration) {
|
export function hasPublicModifier(node: BoltDeclaration) {
|
||||||
return (node.modifiers & BoltDeclarationModifiers.IsPublic) > 0;
|
return (node.modifiers & BoltDeclarationModifiers.Public) > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getFullTextOfQualName(node: BoltQualName) {
|
export function getFullTextOfQualName(node: BoltQualName) {
|
||||||
|
@ -80,6 +167,12 @@ export class StreamWrapper<T> {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const DATETIME_FORMAT = 'YYYY-MM-DD HH:mm:ss'
|
||||||
|
|
||||||
|
export function verbose(message: string) {
|
||||||
|
console.error(chalk.gray('[') + chalk.magenta('verb') + ' ' + chalk.gray(moment().format(DATETIME_FORMAT) + ']') + ' ' + message);
|
||||||
|
}
|
||||||
|
|
||||||
export function upsearchSync(filename: string, startDir = '.') {
|
export function upsearchSync(filename: string, startDir = '.') {
|
||||||
let currDir = startDir;
|
let currDir = startDir;
|
||||||
while (true) {
|
while (true) {
|
||||||
|
|
Loading…
Reference in a new issue