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/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": {
|
||||
"version": "7.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-7.0.2.tgz",
|
||||
|
@ -176,24 +186,35 @@
|
|||
}
|
||||
},
|
||||
"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,
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.0.0.tgz",
|
||||
"integrity": "sha512-N9oWFcegS0sFr9oh1oz2d7Npos6vNoWW9HvtCg5N1KRFpUhaAhvTv5Y58g880fZaEYSNm3qDz8SU1UrGvp+n7A==",
|
||||
"requires": {
|
||||
"ansi-styles": "^3.2.1",
|
||||
"escape-string-regexp": "^1.0.5",
|
||||
"supports-color": "^5.3.0"
|
||||
"ansi-styles": "^4.1.0",
|
||||
"supports-color": "^7.1.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"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,
|
||||
"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": {
|
||||
"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,
|
||||
"requires": {
|
||||
"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": {
|
||||
|
@ -613,8 +665,7 @@
|
|||
"minimist": {
|
||||
"version": "1.2.5",
|
||||
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz",
|
||||
"integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==",
|
||||
"dev": true
|
||||
"integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw=="
|
||||
},
|
||||
"mkdirp": {
|
||||
"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": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz",
|
||||
"integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==",
|
||||
"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": {
|
||||
"version": "1.0.6",
|
||||
"resolved": "https://registry.npmjs.org/node-environment-flags/-/node-environment-flags-1.0.6.tgz",
|
||||
|
@ -770,6 +831,11 @@
|
|||
"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": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
|
||||
|
@ -1001,6 +1067,21 @@
|
|||
"integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=",
|
||||
"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": {
|
||||
"version": "5.0.1",
|
||||
"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",
|
||||
"dependencies": {
|
||||
"@types/fs-extra": "^8.1.0",
|
||||
"@types/microtime": "^2.1.0",
|
||||
"@types/minimist": "^1.2.0",
|
||||
"@types/node": "^13.13.5",
|
||||
"@types/xregexp": "^4.3.0",
|
||||
"@types/yargs": "^15.0.4",
|
||||
"acorn": "^7.2.0",
|
||||
"chalk": "^4.0.0",
|
||||
"fs-extra": "^9.0.0",
|
||||
"glob": "^7.1.6",
|
||||
"microtime": "^3.0.0",
|
||||
"minimist": "^1.2.5",
|
||||
"moment": "^2.25.3",
|
||||
"pegjs": "^0.11.0-master.b7b87ea",
|
||||
"reflect-metadata": "^0.1.13",
|
||||
"source-map-support": "^0.5.19",
|
||||
|
|
|
@ -30,6 +30,10 @@ node BoltOperator > BoltSymbol {
|
|||
text: String,
|
||||
}
|
||||
|
||||
node BoltAssignment > BoltToken {
|
||||
operator: Option<String>,
|
||||
}
|
||||
|
||||
node BoltEOS > 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,
|
||||
BoltIdentifier = 8,
|
||||
BoltOperator = 9,
|
||||
BoltEOS = 10,
|
||||
BoltComma = 11,
|
||||
BoltSemi = 12,
|
||||
BoltColon = 13,
|
||||
BoltDot = 14,
|
||||
BoltDotDot = 15,
|
||||
BoltRArrow = 16,
|
||||
BoltLArrow = 17,
|
||||
BoltEqSign = 18,
|
||||
BoltGtSign = 19,
|
||||
BoltLtSign = 20,
|
||||
BoltFnKeyword = 22,
|
||||
BoltForeignKeyword = 23,
|
||||
BoltLetKeyword = 24,
|
||||
BoltReturnKeyword = 25,
|
||||
BoltLoopKeyword = 26,
|
||||
BoltYieldKeyword = 27,
|
||||
BoltMatchKeyword = 28,
|
||||
BoltImportKeyword = 29,
|
||||
BoltPubKeyword = 30,
|
||||
BoltModKeyword = 31,
|
||||
BoltMutKeyword = 32,
|
||||
BoltEnumKeyword = 33,
|
||||
BoltStructKeyword = 34,
|
||||
BoltNewTypeKeyword = 35,
|
||||
BoltParenthesized = 37,
|
||||
BoltBraced = 38,
|
||||
BoltBracketed = 39,
|
||||
BoltSourceFile = 40,
|
||||
BoltQualName = 41,
|
||||
BoltSentence = 42,
|
||||
BoltReferenceTypeNode = 44,
|
||||
BoltBindPattern = 46,
|
||||
BoltTypePattern = 47,
|
||||
BoltExpressionPattern = 48,
|
||||
BoltTuplePatternElement = 49,
|
||||
BoltTuplePattern = 50,
|
||||
BoltRecordPatternField = 51,
|
||||
BoltRecordPattern = 52,
|
||||
BoltReferenceExpression = 54,
|
||||
BoltCallExpression = 55,
|
||||
BoltYieldExpression = 56,
|
||||
BoltMatchArm = 57,
|
||||
BoltMatchExpression = 58,
|
||||
BoltCase = 59,
|
||||
BoltCaseExpression = 60,
|
||||
BoltBlockExpression = 61,
|
||||
BoltConstantExpression = 62,
|
||||
BoltReturnStatement = 64,
|
||||
BoltResumeStatement = 65,
|
||||
BoltExpressionStatement = 66,
|
||||
BoltParameter = 67,
|
||||
BoltNewTypeDeclaration = 70,
|
||||
BoltModule = 71,
|
||||
BoltFunctionDeclaration = 72,
|
||||
BoltVariableDeclaration = 73,
|
||||
BoltPlainImportSymbol = 75,
|
||||
BoltImportDeclaration = 76,
|
||||
BoltRecordDeclarationField = 77,
|
||||
BoltRecordDeclaration = 79,
|
||||
JSOperator = 82,
|
||||
JSIdentifier = 83,
|
||||
JSBindPattern = 85,
|
||||
JSConstantExpression = 87,
|
||||
JSMemberExpression = 89,
|
||||
JSCallExpression = 90,
|
||||
JSBinaryExpression = 91,
|
||||
JSUnaryExpression = 92,
|
||||
JSNewExpression = 93,
|
||||
JSSequenceExpression = 94,
|
||||
JSConditionalExpression = 95,
|
||||
JSReferenceExpression = 96,
|
||||
JSExpressionStatement = 98,
|
||||
JSConditionalStatement = 99,
|
||||
JSParameter = 100,
|
||||
JSFunctionDeclaration = 103,
|
||||
JSArrowFunctionDeclaration = 104,
|
||||
JSLetDeclaration = 105,
|
||||
JSSourceFile = 106,
|
||||
JSSourceElement = 107,
|
||||
BoltAssignment = 10,
|
||||
BoltEOS = 11,
|
||||
BoltComma = 12,
|
||||
BoltSemi = 13,
|
||||
BoltColon = 14,
|
||||
BoltDot = 15,
|
||||
BoltDotDot = 16,
|
||||
BoltRArrow = 17,
|
||||
BoltLArrow = 18,
|
||||
BoltEqSign = 19,
|
||||
BoltGtSign = 20,
|
||||
BoltLtSign = 21,
|
||||
BoltFnKeyword = 23,
|
||||
BoltForeignKeyword = 24,
|
||||
BoltLetKeyword = 25,
|
||||
BoltReturnKeyword = 26,
|
||||
BoltLoopKeyword = 27,
|
||||
BoltYieldKeyword = 28,
|
||||
BoltMatchKeyword = 29,
|
||||
BoltImportKeyword = 30,
|
||||
BoltPubKeyword = 31,
|
||||
BoltModKeyword = 32,
|
||||
BoltMutKeyword = 33,
|
||||
BoltEnumKeyword = 34,
|
||||
BoltStructKeyword = 35,
|
||||
BoltNewTypeKeyword = 36,
|
||||
BoltParenthesized = 38,
|
||||
BoltBraced = 39,
|
||||
BoltBracketed = 40,
|
||||
BoltSourceFile = 41,
|
||||
BoltQualName = 42,
|
||||
BoltSentence = 43,
|
||||
BoltReferenceTypeNode = 45,
|
||||
BoltBindPattern = 47,
|
||||
BoltTypePattern = 48,
|
||||
BoltExpressionPattern = 49,
|
||||
BoltTuplePatternElement = 50,
|
||||
BoltTuplePattern = 51,
|
||||
BoltRecordPatternField = 52,
|
||||
BoltRecordPattern = 53,
|
||||
BoltReferenceExpression = 55,
|
||||
BoltCallExpression = 56,
|
||||
BoltYieldExpression = 57,
|
||||
BoltMatchArm = 58,
|
||||
BoltMatchExpression = 59,
|
||||
BoltCase = 60,
|
||||
BoltCaseExpression = 61,
|
||||
BoltBlockExpression = 62,
|
||||
BoltConstantExpression = 63,
|
||||
BoltReturnStatement = 65,
|
||||
BoltResumeStatement = 66,
|
||||
BoltExpressionStatement = 67,
|
||||
BoltParameter = 68,
|
||||
BoltNewTypeDeclaration = 71,
|
||||
BoltModule = 72,
|
||||
BoltFunctionDeclaration = 73,
|
||||
BoltVariableDeclaration = 74,
|
||||
BoltPlainImportSymbol = 76,
|
||||
BoltImportDeclaration = 77,
|
||||
BoltRecordDeclarationField = 78,
|
||||
BoltRecordDeclaration = 80,
|
||||
JSOperator = 83,
|
||||
JSIdentifier = 84,
|
||||
JSBindPattern = 86,
|
||||
JSConstantExpression = 88,
|
||||
JSMemberExpression = 90,
|
||||
JSCallExpression = 91,
|
||||
JSBinaryExpression = 92,
|
||||
JSUnaryExpression = 93,
|
||||
JSNewExpression = 94,
|
||||
JSSequenceExpression = 95,
|
||||
JSConditionalExpression = 96,
|
||||
JSReferenceExpression = 97,
|
||||
JSExpressionStatement = 99,
|
||||
JSConditionalStatement = 100,
|
||||
JSParameter = 101,
|
||||
JSFunctionDeclaration = 104,
|
||||
JSArrowFunctionDeclaration = 105,
|
||||
JSLetDeclaration = 106,
|
||||
JSSourceFile = 107,
|
||||
JSSourceElement = 108,
|
||||
}
|
||||
|
||||
|
||||
|
||||
import { TextSpan } from "./text"
|
||||
|
||||
export function setParents(node: Syntax): void;
|
||||
|
||||
export type SyntaxRange = [Syntax, Syntax];
|
||||
|
||||
interface SyntaxBase {
|
||||
|
@ -107,6 +110,7 @@ export type BoltToken
|
|||
| BoltIntegerLiteral
|
||||
| BoltIdentifier
|
||||
| BoltOperator
|
||||
| BoltAssignment
|
||||
| BoltEOS
|
||||
| BoltComma
|
||||
| BoltSemi
|
||||
|
@ -162,6 +166,11 @@ export interface BoltOperator extends SyntaxBase {
|
|||
text: string;
|
||||
}
|
||||
|
||||
export interface BoltAssignment extends SyntaxBase {
|
||||
kind: SyntaxKind.BoltAssignment;
|
||||
operator: string | null;
|
||||
}
|
||||
|
||||
export interface BoltEOS extends SyntaxBase {
|
||||
kind: SyntaxKind.BoltEOS;
|
||||
}
|
||||
|
@ -708,6 +717,7 @@ export type BoltSyntax
|
|||
| BoltIntegerLiteral
|
||||
| BoltIdentifier
|
||||
| BoltOperator
|
||||
| BoltAssignment
|
||||
| BoltEOS
|
||||
| BoltComma
|
||||
| BoltSemi
|
||||
|
@ -799,6 +809,7 @@ export type Syntax
|
|||
| BoltIntegerLiteral
|
||||
| BoltIdentifier
|
||||
| BoltOperator
|
||||
| BoltAssignment
|
||||
| BoltEOS
|
||||
| BoltComma
|
||||
| BoltSemi
|
||||
|
@ -888,6 +899,7 @@ export function createBoltStringLiteral(value: string, span?: TextSpan | null):
|
|||
export function createBoltIntegerLiteral(value: bigint, span?: TextSpan | null): BoltIntegerLiteral;
|
||||
export function createBoltIdentifier(text: string, span?: TextSpan | null): BoltIdentifier;
|
||||
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 createBoltComma(span?: TextSpan | null): BoltComma;
|
||||
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 isBoltIdentifier(value: any): value is BoltIdentifier;
|
||||
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 isBoltComma(value: any): value is BoltComma;
|
||||
export function isBoltSemi(value: any): value is BoltSemi;
|
||||
|
|
|
@ -6,7 +6,7 @@ import * as fs from "fs"
|
|||
import { parse, SyntaxError } from "../treegen/parser"
|
||||
import { Declaration } from "../treegen/ast"
|
||||
import { generateAST } from "../treegen/index"
|
||||
import { getFileStem } from "../util"
|
||||
import { getFileStem } from "../treegen/util"
|
||||
import minimist from "minimist"
|
||||
|
||||
const PACKAGE_ROOT = path.join(__dirname, '..', '..');
|
||||
|
|
|
@ -3,9 +3,6 @@
|
|||
import "reflect-metadata"
|
||||
import "source-map-support/register"
|
||||
|
||||
import * as path from "path"
|
||||
import * as fs from "fs-extra"
|
||||
|
||||
import yargs from "yargs"
|
||||
|
||||
import { Program } from "../program"
|
||||
|
@ -47,7 +44,7 @@ yargs
|
|||
|
||||
'link [name]',
|
||||
'Link projects with each other',
|
||||
|
||||
|
||||
yargs => yargs,
|
||||
|
||||
args => {
|
||||
|
@ -66,12 +63,17 @@ yargs
|
|||
yargs => yargs
|
||||
.string('work-dir')
|
||||
.describe('work-dir', 'The working directory where files will be resolved against.')
|
||||
.default('work-dir', '.'),
|
||||
.default('work-dir', '.')
|
||||
.string('inspect-server'),
|
||||
|
||||
args => {
|
||||
|
||||
const files = toArray(args.files as string[] | string).map(filepath => new TextFile(filepath, args['work-dir']));
|
||||
const program = new Program(files)
|
||||
const files = toArray(args.files as string[] | string);
|
||||
const opts = {};
|
||||
if (args['inspect-server'] !== undefined) {
|
||||
opts.inspector = connectToInspector(args['inspect-server'] as string);
|
||||
}
|
||||
const program = new Program(files, opts);
|
||||
program.compile("JS");
|
||||
|
||||
})
|
||||
|
|
|
@ -101,7 +101,7 @@ function getFullName(node: Syntax) {
|
|||
case SyntaxKind.BoltRecordDeclaration:
|
||||
out.unshift(getFullTextOfQualName(curr.name))
|
||||
break;
|
||||
}
|
||||
}
|
||||
curr = curr.parentNode;
|
||||
if (curr === null) {
|
||||
break;
|
||||
|
@ -129,6 +129,8 @@ export class TypeChecker {
|
|||
|
||||
protected createType(node: Syntax): Type {
|
||||
|
||||
console.error(`creating type for ${kindToString(node.kind)}`);
|
||||
|
||||
switch (node.kind) {
|
||||
|
||||
case SyntaxKind.BoltReferenceExpression:
|
||||
|
@ -145,6 +147,10 @@ export class TypeChecker {
|
|||
case SyntaxKind.BoltExpressionStatement:
|
||||
return voidType;
|
||||
|
||||
case SyntaxKind.BoltCallExpression:
|
||||
// TODO
|
||||
return anyType;
|
||||
|
||||
case SyntaxKind.BoltFunctionDeclaration:
|
||||
let returnType = anyType;
|
||||
if (node.returnType !== null) {
|
||||
|
@ -182,8 +188,8 @@ export class TypeChecker {
|
|||
return typ;
|
||||
|
||||
case SyntaxKind.BoltParameter:
|
||||
if (node.typeNode !== null) {
|
||||
return this.getTypeOfNode(node.typeNode)
|
||||
if (node.type !== null) {
|
||||
return this.getTypeOfNode(node.type)
|
||||
}
|
||||
return anyType;
|
||||
|
||||
|
@ -218,12 +224,21 @@ export class TypeChecker {
|
|||
case SyntaxKind.BoltSentence:
|
||||
case SyntaxKind.BoltRecordDeclaration:
|
||||
case SyntaxKind.BoltNewTypeDeclaration:
|
||||
case SyntaxKind.BoltConstantExpression:
|
||||
break;
|
||||
|
||||
case SyntaxKind.BoltExpressionStatement:
|
||||
this.check(node.expression);
|
||||
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:
|
||||
if (node.body !== null) {
|
||||
if (Array.isArray(node.body)) {
|
||||
|
|
|
@ -30,6 +30,8 @@ import {
|
|||
createJSBindPattern,
|
||||
JSDeclarationModifiers,
|
||||
JSParameter,
|
||||
BoltSyntax,
|
||||
BoltPattern,
|
||||
} from "./ast"
|
||||
|
||||
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)) {
|
||||
// const compiled = this.compileExpr(node, preamble);
|
||||
|
@ -121,6 +125,9 @@ export class Compiler {
|
|||
// TODO
|
||||
break;
|
||||
|
||||
case SyntaxKind.BoltNewTypeDeclaration:
|
||||
break;
|
||||
|
||||
case SyntaxKind.BoltVariableDeclaration:
|
||||
const compiledValue = node.value !== null ? this.compileExpr(node.value, preamble) : null;
|
||||
preamble.push(
|
||||
|
@ -132,8 +139,11 @@ export class Compiler {
|
|||
);
|
||||
break;
|
||||
|
||||
case SyntaxKind.BoltForeignFunctionDeclaration:
|
||||
if (node.target === this.target && node.body !== null) {
|
||||
case SyntaxKind.BoltFunctionDeclaration:
|
||||
if (node.target === this.target) {
|
||||
if (node.body === null) {
|
||||
break;
|
||||
}
|
||||
const params: JSParameter[] = [];
|
||||
let body: JSStatement[] = [];
|
||||
for (const param of node.params) {
|
||||
|
@ -150,6 +160,9 @@ export class Compiler {
|
|||
result.modifiers |= JSDeclarationModifiers.IsExported;;
|
||||
}
|
||||
preamble.push(result)
|
||||
} else {
|
||||
// TODO
|
||||
throw new Error(`Compiling native functions is not yet implemented.`);
|
||||
}
|
||||
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) {
|
||||
|
||||
debug(node);
|
||||
let out = '';
|
||||
|
||||
switch (node.kind) {
|
||||
|
||||
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:
|
||||
let out = ''
|
||||
for (const element of node.elements) {
|
||||
out += this.emit(element);
|
||||
}
|
||||
return out;
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new Error(`Could not emit source code for ${kindToString(node.kind)}`)
|
||||
|
||||
}
|
||||
|
||||
return out;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
|
||||
import {
|
||||
SyntaxKind,
|
||||
setParents,
|
||||
kindToString,
|
||||
BoltSyntax,
|
||||
BoltSentence,
|
||||
|
@ -35,20 +36,13 @@ import { TextSpan } from "./text"
|
|||
import { TypeChecker } from "./checker"
|
||||
import { Parser, ParseError } from "./parser"
|
||||
import { Evaluator, TRUE, FALSE } from "./evaluator"
|
||||
import { StreamWrapper, setOrigNodeRange, BoltTokenStream } from "./util"
|
||||
import { StreamWrapper, setOrigNodeRange, BoltTokenStream, createTokenStream } from "./util"
|
||||
|
||||
interface Transformer {
|
||||
pattern: BoltPattern;
|
||||
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 {
|
||||
const ids = text.split('.').map(name => createBoltIdentifier(name))
|
||||
return createBoltReferenceTypeNode(createBoltQualName(ids.slice(0, -1), ids[ids.length-1]), [])
|
||||
|
@ -145,6 +139,7 @@ export class Expander {
|
|||
|
||||
const newSourceFile = createBoltSourceFile(expanded);
|
||||
setOrigNodeRange(newSourceFile, node, node);
|
||||
setParents(newSourceFile);
|
||||
return newSourceFile;
|
||||
|
||||
} else if (node.kind == SyntaxKind.BoltModule) {
|
||||
|
@ -170,6 +165,7 @@ export class Expander {
|
|||
|
||||
const newModule = createBoltModule(0, node.name, expanded);
|
||||
setOrigNodeRange(newModule, node, node);
|
||||
setParents(newModule);
|
||||
return newModule;
|
||||
|
||||
} else if (node.kind === SyntaxKind.BoltSentence) {
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
|
||||
import * as acorn from "acorn"
|
||||
|
||||
import {
|
||||
SyntaxKind,
|
||||
kindToString,
|
||||
|
@ -45,9 +47,12 @@ import {
|
|||
BoltFunctionDeclaration,
|
||||
createBoltFunctionDeclaration,
|
||||
createBoltCallExpression,
|
||||
BoltSymbol,
|
||||
} from "./ast"
|
||||
|
||||
import { BoltTokenStream, setOrigNodeRange } from "./util"
|
||||
import { Stream, setOrigNodeRange, createTokenStream, uniq } from "./util"
|
||||
|
||||
export type BoltTokenStream = Stream<BoltToken>;
|
||||
|
||||
function describeKind(kind: SyntaxKind): string {
|
||||
switch (kind) {
|
||||
|
@ -148,10 +153,10 @@ const KIND_EXPRESSION_T0 = [
|
|||
SyntaxKind.BoltYieldKeyword,
|
||||
]
|
||||
|
||||
const KIND_STATEMENT_T0 = [
|
||||
const KIND_STATEMENT_T0 = uniq([
|
||||
SyntaxKind.BoltReturnKeyword,
|
||||
...KIND_EXPRESSION_T0,
|
||||
]
|
||||
])
|
||||
|
||||
const KIND_DECLARATION_KEYWORD = [
|
||||
SyntaxKind.BoltFnKeyword,
|
||||
|
@ -162,18 +167,18 @@ const KIND_DECLARATION_KEYWORD = [
|
|||
SyntaxKind.BoltStructKeyword,
|
||||
]
|
||||
|
||||
const KIND_DECLARATION_T0 = [
|
||||
const KIND_DECLARATION_T0 = uniq([
|
||||
SyntaxKind.BoltPubKeyword,
|
||||
SyntaxKind.BoltForeignKeyword,
|
||||
...KIND_DECLARATION_KEYWORD,
|
||||
]
|
||||
])
|
||||
|
||||
const KIND_SOURCEELEMENT_T0 = [
|
||||
const KIND_SOURCEELEMENT_T0 = uniq([
|
||||
SyntaxKind.BoltModKeyword,
|
||||
...KIND_EXPRESSION_T0,
|
||||
...KIND_STATEMENT_T0,
|
||||
...KIND_DECLARATION_T0,
|
||||
]
|
||||
])
|
||||
|
||||
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 {
|
||||
|
||||
const path: BoltIdentifier[] = [];
|
||||
|
@ -373,7 +382,7 @@ export class Parser {
|
|||
//}
|
||||
|
||||
public parseExpression(tokens: BoltTokenStream): BoltExpression {
|
||||
return this.parsePrimitiveExpression(tokens)
|
||||
return this.parseCallOrPrimitiveExpression(tokens)
|
||||
}
|
||||
|
||||
public parseParameter(tokens: BoltTokenStream): BoltParameter {
|
||||
|
@ -627,7 +636,7 @@ export class Parser {
|
|||
let lastToken: BoltSyntax;
|
||||
const firstToken = k0;
|
||||
|
||||
if (k0.kind !== SyntaxKind.BoltPubKeyword) {
|
||||
if (k0.kind === SyntaxKind.BoltPubKeyword) {
|
||||
tokens.get();
|
||||
modifiers |= BoltDeclarationModifiers.Public;
|
||||
k0 = tokens.peek();
|
||||
|
@ -650,9 +659,9 @@ export class Parser {
|
|||
|
||||
tokens.get();
|
||||
|
||||
let name: BoltQualName;
|
||||
let name: BoltSymbol;
|
||||
let returnType = null;
|
||||
let body = null;
|
||||
let body: any = null; // FIXME type-checking should not be disabled
|
||||
let params: BoltParameter[] = [];
|
||||
|
||||
// Parse parameters
|
||||
|
@ -687,16 +696,14 @@ export class Parser {
|
|||
|
||||
if (t0.kind === SyntaxKind.BoltOperator) {
|
||||
|
||||
name = createBoltQualName([], t0);
|
||||
setOrigNodeRange(name, t0, t0);
|
||||
name = t0;
|
||||
tokens.get();
|
||||
params.push(parseParamLike(tokens))
|
||||
|
||||
} else if (isParamLike(t0) && t1.kind == SyntaxKind.BoltOperator) {
|
||||
|
||||
params.push(parseParamLike(tokens));
|
||||
name = createBoltQualName([], t1);
|
||||
setOrigNodeRange(name, t1, t1);
|
||||
name = t1;
|
||||
while (true) {
|
||||
const t2 = tokens.peek();
|
||||
if (t2.kind !== SyntaxKind.BoltOperator) {
|
||||
|
@ -711,7 +718,8 @@ export class Parser {
|
|||
|
||||
} else if (t0.kind === SyntaxKind.BoltIdentifier) {
|
||||
|
||||
name = this.parseQualName(tokens)
|
||||
name = t0;
|
||||
tokens.get();
|
||||
const t2 = tokens.get();
|
||||
if (t2.kind === SyntaxKind.BoltParenthesized) {
|
||||
const innerTokens = createTokenStream(t2);
|
||||
|
@ -762,8 +770,7 @@ export class Parser {
|
|||
body = this.parseStatements(tokens);
|
||||
break;
|
||||
case "JS":
|
||||
// TODO
|
||||
//body = acorn.parse(t3.text).body;
|
||||
body = acorn.parse(t3.text);
|
||||
break;
|
||||
default:
|
||||
throw new Error(`Unrecognised language: ${target}`);
|
||||
|
@ -787,7 +794,8 @@ export class Parser {
|
|||
let t0 = tokens.peek(1);
|
||||
let i = 1;
|
||||
if (t0.kind === SyntaxKind.BoltPubKeyword) {
|
||||
t0 = tokens.peek(i++);
|
||||
i += 1;
|
||||
t0 = tokens.peek(i);
|
||||
if (t0.kind !== SyntaxKind.BoltForeignKeyword) {
|
||||
if (KIND_DECLARATION_KEYWORD.indexOf(t0.kind) === -1) {
|
||||
throw new ParseError(t0, KIND_DECLARATION_KEYWORD);
|
||||
|
@ -818,22 +826,22 @@ export class Parser {
|
|||
throw new ParseError(t0, KIND_DECLARATION_T0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public parseSourceElement(tokens: BoltTokenStream): BoltSourceElement {
|
||||
const t0 = tokens.peek();
|
||||
try {
|
||||
return this.parseDeclaration(tokens)
|
||||
} catch (e) {
|
||||
if (!(e instanceof ParseError)) {
|
||||
throw e;
|
||||
} catch (e1) {
|
||||
if (!(e1 instanceof ParseError)) {
|
||||
throw e1;
|
||||
}
|
||||
try {
|
||||
return this.parseStatement(tokens);
|
||||
} catch (e) {
|
||||
if (!(e instanceof ParseError)) {
|
||||
throw e;
|
||||
} catch (e2) {
|
||||
if (!(e2 instanceof ParseError)) {
|
||||
throw e2;
|
||||
}
|
||||
throw new ParseError(t0, KIND_SOURCEELEMENT_T0)
|
||||
throw e1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -879,14 +887,17 @@ export class Parser {
|
|||
// return lhs
|
||||
//}
|
||||
|
||||
public parseCallExpression(tokens: BoltTokenStream): BoltCallExpression {
|
||||
public parseCallOrPrimitiveExpression(tokens: BoltTokenStream): BoltExpression {
|
||||
|
||||
const operator = this.parsePrimitiveExpression(tokens)
|
||||
const args: BoltExpression[] = []
|
||||
|
||||
const t2 = tokens.get();
|
||||
if (t2.kind === SyntaxKind.BoltEOS) {
|
||||
return operator;
|
||||
}
|
||||
assertToken(t2, SyntaxKind.BoltParenthesized);
|
||||
|
||||
const args: BoltExpression[] = []
|
||||
const innerTokens = createTokenStream(t2);
|
||||
|
||||
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 fs from "fs-extra"
|
||||
import { now } from "microtime"
|
||||
import { EventEmitter } from "events"
|
||||
|
||||
import { Parser } from "./parser"
|
||||
import { TypeChecker } from "./checker"
|
||||
|
@ -10,9 +12,10 @@ import { Scanner } from "./scanner"
|
|||
import { Compiler } from "./compiler"
|
||||
import { emit } from "./emitter"
|
||||
import { TextFile } from "./text"
|
||||
import { BoltSourceFile, Syntax } from "./ast"
|
||||
import { BoltSourceFile, Syntax, JSSourceFile } from "./ast"
|
||||
import { upsearchSync, FastStringMap, getFileStem, getLanguage } from "./util"
|
||||
import { Package } from "./package"
|
||||
import { verbose, memoize } from "./util"
|
||||
|
||||
const targetExtensions: FastStringMap<string> = {
|
||||
'JS': '.mjs',
|
||||
|
@ -20,55 +23,106 @@ const targetExtensions: FastStringMap<string> = {
|
|||
'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 {
|
||||
|
||||
public parser: Parser
|
||||
public evaluator: Evaluator;
|
||||
public checker: TypeChecker;
|
||||
public expander: Expander;
|
||||
public timing: Timing;
|
||||
|
||||
private sourceFiles = new Map<string, BoltSourceFile>();
|
||||
private packages: FastStringMap<Package> = Object.create(null);
|
||||
|
||||
constructor(files: TextFile[]) {
|
||||
constructor(public files: string[]) {
|
||||
this.checker = new TypeChecker();
|
||||
this.parser = new Parser();
|
||||
this.evaluator = new Evaluator(this.checker);
|
||||
this.expander = new Expander(this.parser, this.evaluator, this.checker);
|
||||
for (const file of files) {
|
||||
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());
|
||||
}
|
||||
this.timing = new Timing();
|
||||
}
|
||||
|
||||
@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) {
|
||||
filepath = path.resolve(filepath);
|
||||
const projectFile = upsearchSync('Boltfile', path.dirname(filepath));
|
||||
const file = this.getTextFile(filepath)
|
||||
const projectFile = upsearchSync('Boltfile', path.dirname(file.fullPath));
|
||||
if (projectFile === null) {
|
||||
return null;
|
||||
}
|
||||
const projectDir = path.resolve(path.dirname(projectFile));
|
||||
if (this.packages[projectDir] !== undefined) {
|
||||
return this.packages[projectDir];
|
||||
}
|
||||
return this.packages[projectDir] = new Package(projectDir);
|
||||
return new Package(projectDir);
|
||||
}
|
||||
|
||||
public compile(target: string) {
|
||||
const compiler = new Compiler(this, this.checker, { target })
|
||||
const expanded: SourceFile[] = [];
|
||||
for (const [filepath, sourceFile] of this.sourceFiles) {
|
||||
expanded.push(this.expander.getFullyExpanded(sourceFile) as SourceFile);
|
||||
}
|
||||
const compiled = compiler.compile(expanded) as AnySourceFile[];
|
||||
const expanded = this.files.map(filename => this.getFullyExpandedSourceFile(this.getTextFile(filename)));
|
||||
const compiled = compiler.compile(expanded) as JSSourceFile[];
|
||||
for (const rootNode of compiled) {
|
||||
const filepath = rootNode.span!.file.fullPath;
|
||||
const pkg = this.getPackage(filepath);
|
||||
if (pkg !== null) {
|
||||
|
||||
}
|
||||
//const filepath = rootNode.span!.file.fullPath;
|
||||
//const pkg = this.getPackage(filepath);
|
||||
//if (pkg !== null) {
|
||||
//
|
||||
//}
|
||||
fs.mkdirp('.bolt-work');
|
||||
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)));
|
||||
}
|
||||
|
||||
eval(filename: string) {
|
||||
const original = this.sourceFiles.get(filename);
|
||||
if (original === undefined) {
|
||||
throw new Error(`File ${filename} does not seem to be part of this Program.`)
|
||||
public eval() {
|
||||
for (const filename of this.files) {
|
||||
const file = this.getTextFile(filename);
|
||||
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"
|
||||
|
||||
import {
|
||||
setParents,
|
||||
SyntaxKind,
|
||||
BoltToken,
|
||||
BoltSentence,
|
||||
|
@ -27,6 +28,18 @@ import {
|
|||
createBoltEOS,
|
||||
createBoltDot,
|
||||
createBoltEqSign,
|
||||
createBoltPubKeyword,
|
||||
createBoltMutKeyword,
|
||||
createBoltStructKeyword,
|
||||
createBoltEnumKeyword,
|
||||
createBoltForeignKeyword,
|
||||
createBoltAssignment,
|
||||
createBoltYieldKeyword,
|
||||
createBoltReturnKeyword,
|
||||
createBoltFnKeyword,
|
||||
createBoltLArrow,
|
||||
createBoltDotDot,
|
||||
createBoltNewTypeKeyword,
|
||||
} from "./ast"
|
||||
|
||||
export enum PunctType {
|
||||
|
@ -122,14 +135,13 @@ function isIdentPart(ch: string) {
|
|||
return ch == '_' || XRegExp('\\p{L}').test(ch)
|
||||
}
|
||||
|
||||
function isOperatorStart(ch: string) {
|
||||
return /[+\-*\/%$!><]/.test(ch)
|
||||
function isSymbol(ch: string) {
|
||||
return /[=+\/-*%$!><&^|]/.test(ch)
|
||||
}
|
||||
|
||||
function isOperatorPart(ch: string) {
|
||||
return /[=+\-*\/%$!><]/.test(ch)
|
||||
|
||||
}
|
||||
//function isOperatorPart(ch: string) {
|
||||
//return /[=+\-*\/%$!><]/.test(ch)
|
||||
//}
|
||||
|
||||
const EOF = ''
|
||||
|
||||
|
@ -210,12 +222,6 @@ export class Scanner {
|
|||
}
|
||||
|
||||
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 ';':
|
||||
this.getChar();
|
||||
return createBoltSemi(new TextSpan(this.file, startPos, this.currPos.clone()));
|
||||
|
@ -304,18 +310,42 @@ export class Scanner {
|
|||
|
||||
const name = this.takeWhile(isIdentPart);
|
||||
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 span = new TextSpan(this.file, startPos, endPos);
|
||||
|
||||
if (text === '->') {
|
||||
return createBoltRArrow(span);
|
||||
} else {
|
||||
return createBoltOperator(text, span);
|
||||
if (text.endsWith('=')) {
|
||||
const operator = text.substring(0, text.length-1);
|
||||
if (text === '==') {
|
||||
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 {
|
||||
|
@ -385,7 +415,9 @@ export class Scanner {
|
|||
const startPos = this.currPos.clone();
|
||||
const elements = this.scanTokens();
|
||||
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;
|
||||
}
|
||||
|
||||
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) {
|
||||
const obj = Object.create(nodeProto);
|
||||
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') {
|
||||
module.exports = exports;
|
||||
}
|
||||
|
|
|
@ -106,6 +106,8 @@ export function generateAST(decls: Declaration[]) {
|
|||
|
||||
import { TextSpan } from "./text"
|
||||
|
||||
export function setParents(node: Syntax): void;
|
||||
|
||||
export type SyntaxRange = [Syntax, Syntax];
|
||||
|
||||
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) {
|
||||
return /[\r\t ]/.test(ch);
|
||||
}
|
||||
|
|
101
src/util.ts
101
src/util.ts
|
@ -1,20 +1,107 @@
|
|||
|
||||
import * as path from "path"
|
||||
import * as fs from "fs"
|
||||
import moment from "moment"
|
||||
import chalk from "chalk"
|
||||
|
||||
import { TextSpan } from "./text"
|
||||
import { kindToString, Syntax, BoltToken, BoltQualName, BoltDeclaration, BoltDeclarationModifiers } from "./ast"
|
||||
import { TextSpan, TextPos } from "./text"
|
||||
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 JsonObject { [key: string]: Json }
|
||||
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> {
|
||||
[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'];
|
||||
|
||||
export function getLanguage(node: Syntax): string {
|
||||
|
@ -39,7 +126,7 @@ export function setOrigNodeRange(node: Syntax, startNode: Syntax, endNode: Synta
|
|||
}
|
||||
|
||||
export function hasPublicModifier(node: BoltDeclaration) {
|
||||
return (node.modifiers & BoltDeclarationModifiers.IsPublic) > 0;
|
||||
return (node.modifiers & BoltDeclarationModifiers.Public) > 0;
|
||||
}
|
||||
|
||||
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 = '.') {
|
||||
let currDir = startDir;
|
||||
while (true) {
|
||||
|
|
Loading…
Reference in a new issue