@aeriajs/compiler 0.0.41 → 0.0.42
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/ast.d.ts +2 -0
- package/dist/codegen/generateContracts.d.ts +1 -1
- package/dist/codegen/generateContracts.js +10 -11
- package/dist/codegen/generateContracts.mjs +10 -11
- package/dist/codegen/generateJSCollections.d.ts +1 -1
- package/dist/codegen/generateJSCollections.js +5 -5
- package/dist/codegen/generateJSCollections.mjs +4 -4
- package/dist/codegen/generateTSCollections.d.ts +1 -1
- package/dist/codegen/generateTSCollections.js +2 -2
- package/dist/codegen/generateTSCollections.mjs +2 -2
- package/dist/codegen.js +3 -3
- package/dist/codegen.mjs +3 -3
- package/dist/compile.d.ts +5 -1
- package/dist/compile.js +24 -4
- package/dist/compile.mjs +23 -4
- package/dist/diagnostic.d.ts +1 -3
- package/dist/diagnostic.js +2 -4
- package/dist/diagnostic.mjs +2 -3
- package/dist/lexer.d.ts +1 -1
- package/dist/lexer.js +3 -1
- package/dist/lexer.mjs +3 -1
- package/dist/parser.js +22 -13
- package/dist/parser.mjs +22 -13
- package/dist/token.d.ts +1 -0
- package/package.json +1 -1
package/dist/ast.d.ts
CHANGED
|
@@ -66,6 +66,7 @@ export type CollectionNode = NodeBase<'collection'> & {
|
|
|
66
66
|
functions?: Record<string, {
|
|
67
67
|
accessCondition: AccessCondition;
|
|
68
68
|
}>;
|
|
69
|
+
functionSets?: [string, symbol][];
|
|
69
70
|
required?: RequiredProperties;
|
|
70
71
|
indexes?: readonly string[];
|
|
71
72
|
presets?: DescriptionPreset[];
|
|
@@ -97,6 +98,7 @@ export type FunctionSetNode = NodeBase<'functionset'> & {
|
|
|
97
98
|
accessCondition: AccessCondition;
|
|
98
99
|
fromFunctionSet?: true;
|
|
99
100
|
}>;
|
|
101
|
+
functionSets: [string, symbol][];
|
|
100
102
|
};
|
|
101
103
|
export type ProgramNode = NodeBase<'program'> & {
|
|
102
104
|
collections: CollectionNode[];
|
|
@@ -4,17 +4,16 @@ exports.generateContracts = void 0;
|
|
|
4
4
|
const types_1 = require("@aeriajs/types");
|
|
5
5
|
const utils_js_1 = require("./utils.js");
|
|
6
6
|
const generateContracts = (ast) => {
|
|
7
|
-
|
|
8
|
-
if (contractNodes.length === 0) {
|
|
7
|
+
if (ast.contracts.length === 0) {
|
|
9
8
|
return false;
|
|
10
9
|
}
|
|
11
10
|
return {
|
|
12
|
-
js: makeJSContractsCode(
|
|
13
|
-
dts: makeTSContractsCode(
|
|
11
|
+
js: makeJSContractsCode(ast),
|
|
12
|
+
dts: makeTSContractsCode(ast),
|
|
14
13
|
};
|
|
15
14
|
};
|
|
16
15
|
exports.generateContracts = generateContracts;
|
|
17
|
-
const makeJSContractsCode = (
|
|
16
|
+
const makeJSContractsCode = (ast) => {
|
|
18
17
|
const imports = new Set(['defineContract']);
|
|
19
18
|
const getCodeForResponse = (responseProperty) => {
|
|
20
19
|
const { kind, modifier, ...propertyNode } = responseProperty;
|
|
@@ -29,8 +28,8 @@ const makeJSContractsCode = (contractAst) => {
|
|
|
29
28
|
}
|
|
30
29
|
return `${modifierSymbol}(${(0, utils_js_1.stringify)((0, utils_js_1.unwrapPropertyNode)(propertyNode))})`;
|
|
31
30
|
};
|
|
32
|
-
const declarations =
|
|
33
|
-
const { name, kind, roles, response, ...contractProperty } =
|
|
31
|
+
const declarations = ast.contracts.map((node) => {
|
|
32
|
+
const { name, kind, roles, response, ...contractProperty } = node;
|
|
34
33
|
let responseString;
|
|
35
34
|
if (response) {
|
|
36
35
|
responseString = '';
|
|
@@ -69,9 +68,9 @@ const getResponseSchema = (response) => {
|
|
|
69
68
|
(0, types_1.resultSchema)(responseSchema) :
|
|
70
69
|
(0, types_1.errorSchema)(responseSchema);
|
|
71
70
|
};
|
|
72
|
-
const makeTSContractsCode = (
|
|
73
|
-
return
|
|
74
|
-
const { name, kind, roles, ...contractSchema } =
|
|
71
|
+
const makeTSContractsCode = (ast) => {
|
|
72
|
+
return ast.contracts.map((node) => {
|
|
73
|
+
const { name, kind, roles, ...contractSchema } = node;
|
|
75
74
|
let responseSchema = null;
|
|
76
75
|
if (contractSchema.response) {
|
|
77
76
|
if (Array.isArray(contractSchema.response)) {
|
|
@@ -88,6 +87,6 @@ const makeTSContractsCode = (contractAst) => {
|
|
|
88
87
|
if (roles) {
|
|
89
88
|
contractProperties.roles = roles;
|
|
90
89
|
}
|
|
91
|
-
return `export declare const ${
|
|
90
|
+
return `export declare const ${node.name}: ${(0, utils_js_1.stringify)(contractProperties)}`;
|
|
92
91
|
}).join('\n\n');
|
|
93
92
|
};
|
|
@@ -2,16 +2,15 @@
|
|
|
2
2
|
import { errorSchema, resultSchema } from "@aeriajs/types";
|
|
3
3
|
import { recursivelyUnwrapPropertyNodes, unwrapPropertyNode, stringify, UnquotedSymbol } from "./utils.mjs";
|
|
4
4
|
export const generateContracts = (ast) => {
|
|
5
|
-
|
|
6
|
-
if (contractNodes.length === 0) {
|
|
5
|
+
if (ast.contracts.length === 0) {
|
|
7
6
|
return false;
|
|
8
7
|
}
|
|
9
8
|
return {
|
|
10
|
-
js: makeJSContractsCode(
|
|
11
|
-
dts: makeTSContractsCode(
|
|
9
|
+
js: makeJSContractsCode(ast),
|
|
10
|
+
dts: makeTSContractsCode(ast)
|
|
12
11
|
};
|
|
13
12
|
};
|
|
14
|
-
const makeJSContractsCode = (
|
|
13
|
+
const makeJSContractsCode = (ast) => {
|
|
15
14
|
const imports = /* @__PURE__ */ new Set(["defineContract"]);
|
|
16
15
|
const getCodeForResponse = (responseProperty) => {
|
|
17
16
|
const { kind, modifier, ...propertyNode } = responseProperty;
|
|
@@ -24,8 +23,8 @@ const makeJSContractsCode = (contractAst) => {
|
|
|
24
23
|
}
|
|
25
24
|
return `${modifierSymbol}(${stringify(unwrapPropertyNode(propertyNode))})`;
|
|
26
25
|
};
|
|
27
|
-
const declarations =
|
|
28
|
-
const { name, kind, roles, response, ...contractProperty } =
|
|
26
|
+
const declarations = ast.contracts.map((node) => {
|
|
27
|
+
const { name, kind, roles, response, ...contractProperty } = node;
|
|
29
28
|
let responseString;
|
|
30
29
|
if (response) {
|
|
31
30
|
responseString = "";
|
|
@@ -63,9 +62,9 @@ const getResponseSchema = (response) => {
|
|
|
63
62
|
}
|
|
64
63
|
return response.modifier === "Result" ? resultSchema(responseSchema) : errorSchema(responseSchema);
|
|
65
64
|
};
|
|
66
|
-
const makeTSContractsCode = (
|
|
67
|
-
return
|
|
68
|
-
const { name, kind, roles, ...contractSchema } =
|
|
65
|
+
const makeTSContractsCode = (ast) => {
|
|
66
|
+
return ast.contracts.map((node) => {
|
|
67
|
+
const { name, kind, roles, ...contractSchema } = node;
|
|
69
68
|
let responseSchema = null;
|
|
70
69
|
if (contractSchema.response) {
|
|
71
70
|
if (Array.isArray(contractSchema.response)) {
|
|
@@ -81,6 +80,6 @@ const makeTSContractsCode = (contractAst) => {
|
|
|
81
80
|
if (roles) {
|
|
82
81
|
contractProperties.roles = roles;
|
|
83
82
|
}
|
|
84
|
-
return `export declare const ${
|
|
83
|
+
return `export declare const ${node.name}: ${stringify(contractProperties)}`;
|
|
85
84
|
}).join("\n\n");
|
|
86
85
|
};
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import type * as AST from '../ast.js';
|
|
2
|
-
export declare const generateJSCollections: (ast: AST.
|
|
2
|
+
export declare const generateJSCollections: (ast: AST.ProgramNode) => string;
|
|
@@ -8,7 +8,7 @@ const initialImportedFunctions = [
|
|
|
8
8
|
];
|
|
9
9
|
const generateJSCollections = (ast) => {
|
|
10
10
|
let javascriptCode = '';
|
|
11
|
-
const importsResult = (0, utils_js_1.makeASTImports)(ast, {
|
|
11
|
+
const importsResult = (0, utils_js_1.makeASTImports)(ast.collections, {
|
|
12
12
|
[utils_js_1.PACKAGE_NAME]: new Set(initialImportedFunctions),
|
|
13
13
|
}, {
|
|
14
14
|
includeRuntimeOnlyImports: true,
|
|
@@ -20,14 +20,14 @@ const generateJSCollections = (ast) => {
|
|
|
20
20
|
exports.generateJSCollections = generateJSCollections;
|
|
21
21
|
const makeJSCollections = (ast, modifiedSymbols) => {
|
|
22
22
|
const collectionCodes = {};
|
|
23
|
-
for (const collectionNode of ast) {
|
|
23
|
+
for (const collectionNode of ast.collections) {
|
|
24
24
|
const id = (0, utils_js_1.getCollectionId)(collectionNode.name); // CollectionName -> collectionName
|
|
25
25
|
const extendCollectionName = (0, utils_js_1.getExtendName)(collectionNode.name);
|
|
26
26
|
const collectionDefinition = `export const ${id} = ${collectionNode.extends
|
|
27
27
|
? `extendCollection(${id in modifiedSymbols
|
|
28
28
|
? modifiedSymbols[id]
|
|
29
|
-
: id}, ${makeJSCollectionSchema(collectionNode, id)})`
|
|
30
|
-
: `defineCollection(${makeJSCollectionSchema(collectionNode, id)})`}`;
|
|
29
|
+
: id}, ${makeJSCollectionSchema(ast, collectionNode, id)})`
|
|
30
|
+
: `defineCollection(${makeJSCollectionSchema(ast, collectionNode, id)})`}`;
|
|
31
31
|
const collectionDeclaration = `export const ${extendCollectionName} = (collection) => extendCollection(${id}, collection)`;
|
|
32
32
|
collectionCodes[collectionNode.name] = [
|
|
33
33
|
'//' + collectionNode.name,
|
|
@@ -37,7 +37,7 @@ const makeJSCollections = (ast, modifiedSymbols) => {
|
|
|
37
37
|
}
|
|
38
38
|
return Object.values(collectionCodes).join('\n\n');
|
|
39
39
|
};
|
|
40
|
-
const makeJSCollectionSchema = (collectionNode, collectionId) => {
|
|
40
|
+
const makeJSCollectionSchema = (ast, collectionNode, collectionId) => {
|
|
41
41
|
const collectionSchema = {
|
|
42
42
|
item: {},
|
|
43
43
|
description: {
|
|
@@ -6,7 +6,7 @@ const initialImportedFunctions = [
|
|
|
6
6
|
];
|
|
7
7
|
export const generateJSCollections = (ast) => {
|
|
8
8
|
let javascriptCode = "";
|
|
9
|
-
const importsResult = makeASTImports(ast, {
|
|
9
|
+
const importsResult = makeASTImports(ast.collections, {
|
|
10
10
|
[PACKAGE_NAME]: new Set(initialImportedFunctions)
|
|
11
11
|
}, {
|
|
12
12
|
includeRuntimeOnlyImports: true
|
|
@@ -17,10 +17,10 @@ export const generateJSCollections = (ast) => {
|
|
|
17
17
|
};
|
|
18
18
|
const makeJSCollections = (ast, modifiedSymbols) => {
|
|
19
19
|
const collectionCodes = {};
|
|
20
|
-
for (const collectionNode of ast) {
|
|
20
|
+
for (const collectionNode of ast.collections) {
|
|
21
21
|
const id = getCollectionId(collectionNode.name);
|
|
22
22
|
const extendCollectionName = getExtendName(collectionNode.name);
|
|
23
|
-
const collectionDefinition = `export const ${id} = ${collectionNode.extends ? `extendCollection(${id in modifiedSymbols ? modifiedSymbols[id] : id}, ${makeJSCollectionSchema(collectionNode, id)})` : `defineCollection(${makeJSCollectionSchema(collectionNode, id)})`}`;
|
|
23
|
+
const collectionDefinition = `export const ${id} = ${collectionNode.extends ? `extendCollection(${id in modifiedSymbols ? modifiedSymbols[id] : id}, ${makeJSCollectionSchema(ast, collectionNode, id)})` : `defineCollection(${makeJSCollectionSchema(ast, collectionNode, id)})`}`;
|
|
24
24
|
const collectionDeclaration = `export const ${extendCollectionName} = (collection) => extendCollection(${id}, collection)`;
|
|
25
25
|
collectionCodes[collectionNode.name] = [
|
|
26
26
|
"//" + collectionNode.name,
|
|
@@ -30,7 +30,7 @@ const makeJSCollections = (ast, modifiedSymbols) => {
|
|
|
30
30
|
}
|
|
31
31
|
return Object.values(collectionCodes).join("\n\n");
|
|
32
32
|
};
|
|
33
|
-
const makeJSCollectionSchema = (collectionNode, collectionId) => {
|
|
33
|
+
const makeJSCollectionSchema = (ast, collectionNode, collectionId) => {
|
|
34
34
|
const collectionSchema = {
|
|
35
35
|
item: {},
|
|
36
36
|
description: {
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import type * as AST from '../ast.js';
|
|
2
|
-
export declare const generateTSCollections: (ast: AST.
|
|
2
|
+
export declare const generateTSCollections: (ast: AST.ProgramNode) => string;
|
|
@@ -11,7 +11,7 @@ const initialImportedTypes = [
|
|
|
11
11
|
const generateTSCollections = (ast) => {
|
|
12
12
|
let code = '';
|
|
13
13
|
code += `import type { ${initialImportedTypes.join(', ')} } from '${utils_js_1.PACKAGE_NAME}'\n`; //Used types
|
|
14
|
-
const importsResult = (0, utils_js_1.makeASTImports)(ast);
|
|
14
|
+
const importsResult = (0, utils_js_1.makeASTImports)(ast.collections);
|
|
15
15
|
code += importsResult.code.join('\n') + '\n\n';
|
|
16
16
|
code += makeTSCollections(ast, importsResult.modifiedSymbols) + '\n';
|
|
17
17
|
return code;
|
|
@@ -19,7 +19,7 @@ const generateTSCollections = (ast) => {
|
|
|
19
19
|
exports.generateTSCollections = generateTSCollections;
|
|
20
20
|
const makeTSCollections = (ast, modifiedSymbols) => {
|
|
21
21
|
const collectionCodes = {};
|
|
22
|
-
for (const collectionNode of ast) {
|
|
22
|
+
for (const collectionNode of ast.collections) {
|
|
23
23
|
const id = (0, utils_js_1.getCollectionId)(collectionNode.name); // CollectionName -> collectionName
|
|
24
24
|
const schemaName = (0, utils_js_1.resizeFirstChar)(collectionNode.name, true); // collectionName -> CollectionName
|
|
25
25
|
const typeName = id + 'Collection'; // Pet -> petCollection
|
|
@@ -10,14 +10,14 @@ export const generateTSCollections = (ast) => {
|
|
|
10
10
|
let code = "";
|
|
11
11
|
code += `import type { ${initialImportedTypes.join(", ")} } from '${PACKAGE_NAME}'
|
|
12
12
|
`;
|
|
13
|
-
const importsResult = makeASTImports(ast);
|
|
13
|
+
const importsResult = makeASTImports(ast.collections);
|
|
14
14
|
code += importsResult.code.join("\n") + "\n\n";
|
|
15
15
|
code += makeTSCollections(ast, importsResult.modifiedSymbols) + "\n";
|
|
16
16
|
return code;
|
|
17
17
|
};
|
|
18
18
|
const makeTSCollections = (ast, modifiedSymbols) => {
|
|
19
19
|
const collectionCodes = {};
|
|
20
|
-
for (const collectionNode of ast) {
|
|
20
|
+
for (const collectionNode of ast.collections) {
|
|
21
21
|
const id = getCollectionId(collectionNode.name);
|
|
22
22
|
const schemaName = resizeFirstChar(collectionNode.name, true);
|
|
23
23
|
const typeName = id + "Collection";
|
package/dist/codegen.js
CHANGED
|
@@ -57,14 +57,14 @@ const generateFileMap = async (fileTree, outDir = '.') => {
|
|
|
57
57
|
return mappedPaths;
|
|
58
58
|
};
|
|
59
59
|
const generateCode = async (ast, options) => {
|
|
60
|
-
const contracts = (0, index_js_1.generateContracts)(ast
|
|
60
|
+
const contracts = (0, index_js_1.generateContracts)(ast);
|
|
61
61
|
const exports = (0, index_js_1.generateExports)(ast, {
|
|
62
62
|
hasContracts: !!contracts,
|
|
63
63
|
});
|
|
64
64
|
const fileTree = {
|
|
65
65
|
['collections']: {
|
|
66
|
-
['collections.d.ts']: (0, index_js_1.generateTSCollections)(ast
|
|
67
|
-
['collections.js']: (0, index_js_1.generateJSCollections)(ast
|
|
66
|
+
['collections.d.ts']: (0, index_js_1.generateTSCollections)(ast),
|
|
67
|
+
['collections.js']: (0, index_js_1.generateJSCollections)(ast),
|
|
68
68
|
['index.d.ts']: exports.collections.dts,
|
|
69
69
|
['index.js']: exports.collections.js,
|
|
70
70
|
},
|
package/dist/codegen.mjs
CHANGED
|
@@ -22,14 +22,14 @@ const generateFileMap = async (fileTree, outDir = ".") => {
|
|
|
22
22
|
return mappedPaths;
|
|
23
23
|
};
|
|
24
24
|
export const generateCode = async (ast, options) => {
|
|
25
|
-
const contracts = generateContracts(ast
|
|
25
|
+
const contracts = generateContracts(ast);
|
|
26
26
|
const exports = generateExports(ast, {
|
|
27
27
|
hasContracts: !!contracts
|
|
28
28
|
});
|
|
29
29
|
const fileTree = {
|
|
30
30
|
["collections"]: {
|
|
31
|
-
["collections.d.ts"]: generateTSCollections(ast
|
|
32
|
-
["collections.mjs"]: generateJSCollections(ast
|
|
31
|
+
["collections.d.ts"]: generateTSCollections(ast),
|
|
32
|
+
["collections.mjs"]: generateJSCollections(ast),
|
|
33
33
|
["index.d.ts"]: exports.collections.dts,
|
|
34
34
|
["index.mjs"]: exports.collections.js
|
|
35
35
|
},
|
package/dist/compile.d.ts
CHANGED
|
@@ -1,11 +1,15 @@
|
|
|
1
|
+
import type * as AST from './ast.js';
|
|
1
2
|
import type { CompilationOptions, CompilationResult } from './types.js';
|
|
2
3
|
import { Diagnostic } from './diagnostic.js';
|
|
3
4
|
export declare const GLOB_PATTERN = "**/*.aeria";
|
|
5
|
+
export declare const postflight: (ast: AST.ProgramNode) => {
|
|
6
|
+
errors: Diagnostic[];
|
|
7
|
+
};
|
|
4
8
|
export declare const parseAndCheck: (sources: Record<string, string>, options?: Pick<CompilationOptions, "languageServer">) => Promise<CompilationResult>;
|
|
5
9
|
export declare const compileFromFiles: (options: CompilationOptions) => Promise<CompilationResult | {
|
|
6
10
|
emittedFiles: Record<string, string>;
|
|
7
11
|
success: boolean;
|
|
8
|
-
ast?:
|
|
12
|
+
ast?: AST.ProgramNode;
|
|
9
13
|
errors: Diagnostic[];
|
|
10
14
|
errorCount: number;
|
|
11
15
|
}>;
|
package/dist/compile.js
CHANGED
|
@@ -33,7 +33,7 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
33
33
|
};
|
|
34
34
|
})();
|
|
35
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
-
exports.compileFromFiles = exports.parseAndCheck = exports.GLOB_PATTERN = void 0;
|
|
36
|
+
exports.compileFromFiles = exports.parseAndCheck = exports.postflight = exports.GLOB_PATTERN = void 0;
|
|
37
37
|
const diagnostic_js_1 = require("./diagnostic.js");
|
|
38
38
|
const lexer_js_1 = require("./lexer.js");
|
|
39
39
|
const parser_js_1 = require("./parser.js");
|
|
@@ -41,12 +41,31 @@ const semantic_js_1 = require("./semantic.js");
|
|
|
41
41
|
const codegen_js_1 = require("./codegen.js");
|
|
42
42
|
const fs = __importStar(require("node:fs"));
|
|
43
43
|
exports.GLOB_PATTERN = '**/*.aeria';
|
|
44
|
+
const postflight = (ast) => {
|
|
45
|
+
const errors = [];
|
|
46
|
+
for (const node of ast.collections) {
|
|
47
|
+
if (node.functionSets?.length) {
|
|
48
|
+
for (const [functionSetName, locationSymbol] of node.functionSets) {
|
|
49
|
+
const functionSet = ast.functionsets.find(({ name }) => name === functionSetName);
|
|
50
|
+
if (!functionSet) {
|
|
51
|
+
const location = parser_js_1.locationMap.get(locationSymbol);
|
|
52
|
+
errors.push(new diagnostic_js_1.Diagnostic(`invalid function set "${functionSetName}"`, location));
|
|
53
|
+
continue;
|
|
54
|
+
}
|
|
55
|
+
Object.assign(node.functions, functionSet.functions);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
return {
|
|
60
|
+
errors,
|
|
61
|
+
};
|
|
62
|
+
};
|
|
63
|
+
exports.postflight = postflight;
|
|
44
64
|
const parseAndCheck = async (sources, options = {}) => {
|
|
45
65
|
const errors = [];
|
|
46
66
|
const allTokens = [];
|
|
47
67
|
for (const fileName in sources) {
|
|
48
|
-
|
|
49
|
-
const { errors: lexerErrors, tokens } = (0, lexer_js_1.tokenize)(sources[fileName]);
|
|
68
|
+
const { errors: lexerErrors, tokens } = (0, lexer_js_1.tokenize)(sources[fileName], fileName);
|
|
50
69
|
if (lexerErrors.length > 0) {
|
|
51
70
|
errors.push(...lexerErrors);
|
|
52
71
|
}
|
|
@@ -54,7 +73,8 @@ const parseAndCheck = async (sources, options = {}) => {
|
|
|
54
73
|
}
|
|
55
74
|
const { errors: parserErrors, ast } = (0, parser_js_1.parse)(allTokens);
|
|
56
75
|
const { errors: semanticErrors } = await (0, semantic_js_1.analyze)(ast, options);
|
|
57
|
-
errors
|
|
76
|
+
const { errors: postflightErrors } = (0, exports.postflight)(ast);
|
|
77
|
+
errors.push(...parserErrors.concat(semanticErrors, postflightErrors));
|
|
58
78
|
return {
|
|
59
79
|
success: errors.length === 0,
|
|
60
80
|
errors,
|
package/dist/compile.mjs
CHANGED
|
@@ -1,17 +1,35 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
import { Diagnostic } from "./diagnostic.mjs";
|
|
3
3
|
import { tokenize } from "./lexer.mjs";
|
|
4
|
-
import { parse } from "./parser.mjs";
|
|
4
|
+
import { parse, locationMap } from "./parser.mjs";
|
|
5
5
|
import { analyze } from "./semantic.mjs";
|
|
6
6
|
import { generateCode } from "./codegen.mjs";
|
|
7
7
|
import * as fs from "node:fs";
|
|
8
8
|
export const GLOB_PATTERN = "**/*.aeria";
|
|
9
|
+
export const postflight = (ast) => {
|
|
10
|
+
const errors = [];
|
|
11
|
+
for (const node of ast.collections) {
|
|
12
|
+
if (node.functionSets?.length) {
|
|
13
|
+
for (const [functionSetName, locationSymbol] of node.functionSets) {
|
|
14
|
+
const functionSet = ast.functionsets.find(({ name }) => name === functionSetName);
|
|
15
|
+
if (!functionSet) {
|
|
16
|
+
const location = locationMap.get(locationSymbol);
|
|
17
|
+
errors.push(new Diagnostic(`invalid function set "${functionSetName}"`, location));
|
|
18
|
+
continue;
|
|
19
|
+
}
|
|
20
|
+
Object.assign(node.functions, functionSet.functions);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
return {
|
|
25
|
+
errors
|
|
26
|
+
};
|
|
27
|
+
};
|
|
9
28
|
export const parseAndCheck = async (sources, options = {}) => {
|
|
10
29
|
const errors = [];
|
|
11
30
|
const allTokens = [];
|
|
12
31
|
for (const fileName in sources) {
|
|
13
|
-
|
|
14
|
-
const { errors: lexerErrors, tokens } = tokenize(sources[fileName]);
|
|
32
|
+
const { errors: lexerErrors, tokens } = tokenize(sources[fileName], fileName);
|
|
15
33
|
if (lexerErrors.length > 0) {
|
|
16
34
|
errors.push(...lexerErrors);
|
|
17
35
|
}
|
|
@@ -19,7 +37,8 @@ export const parseAndCheck = async (sources, options = {}) => {
|
|
|
19
37
|
}
|
|
20
38
|
const { errors: parserErrors, ast } = parse(allTokens);
|
|
21
39
|
const { errors: semanticErrors } = await analyze(ast, options);
|
|
22
|
-
errors
|
|
40
|
+
const { errors: postflightErrors } = postflight(ast);
|
|
41
|
+
errors.push(...parserErrors.concat(semanticErrors, postflightErrors));
|
|
23
42
|
return {
|
|
24
43
|
success: errors.length === 0,
|
|
25
44
|
errors,
|
package/dist/diagnostic.d.ts
CHANGED
|
@@ -2,7 +2,5 @@ import type { Location } from './token.js';
|
|
|
2
2
|
export declare class Diagnostic extends Error {
|
|
3
3
|
message: string;
|
|
4
4
|
location: Location;
|
|
5
|
-
|
|
6
|
-
static currentFile: string | undefined;
|
|
7
|
-
constructor(message: string, location?: Location, fileLocation?: string | undefined);
|
|
5
|
+
constructor(message: string, location?: Location);
|
|
8
6
|
}
|
package/dist/diagnostic.js
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.Diagnostic = void 0;
|
|
4
4
|
const emptyLocation = {
|
|
5
|
+
file: '',
|
|
5
6
|
index: 0,
|
|
6
7
|
line: 0,
|
|
7
8
|
start: 0,
|
|
@@ -10,13 +11,10 @@ const emptyLocation = {
|
|
|
10
11
|
class Diagnostic extends Error {
|
|
11
12
|
message;
|
|
12
13
|
location;
|
|
13
|
-
|
|
14
|
-
static currentFile;
|
|
15
|
-
constructor(message, location = emptyLocation, fileLocation = Diagnostic.currentFile) {
|
|
14
|
+
constructor(message, location = emptyLocation) {
|
|
16
15
|
super();
|
|
17
16
|
this.message = message;
|
|
18
17
|
this.location = location;
|
|
19
|
-
this.fileLocation = fileLocation;
|
|
20
18
|
if (process.env.NODE_ENV === 'debug') {
|
|
21
19
|
console.error(message, location);
|
|
22
20
|
}
|
package/dist/diagnostic.mjs
CHANGED
|
@@ -1,19 +1,18 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
const emptyLocation = {
|
|
3
|
+
file: "",
|
|
3
4
|
index: 0,
|
|
4
5
|
line: 0,
|
|
5
6
|
start: 0,
|
|
6
7
|
end: 0
|
|
7
8
|
};
|
|
8
9
|
export class Diagnostic extends Error {
|
|
9
|
-
constructor(message, location = emptyLocation
|
|
10
|
+
constructor(message, location = emptyLocation) {
|
|
10
11
|
super();
|
|
11
12
|
this.message = message;
|
|
12
13
|
this.location = location;
|
|
13
|
-
this.fileLocation = fileLocation;
|
|
14
14
|
if (false) {
|
|
15
15
|
console.error(message, location);
|
|
16
16
|
}
|
|
17
17
|
}
|
|
18
|
-
static currentFile;
|
|
19
18
|
}
|
package/dist/lexer.d.ts
CHANGED
|
@@ -13,7 +13,7 @@ export type Keyword = typeof COLLECTION_KEYWORDS[number] | typeof COLLECTION_ACT
|
|
|
13
13
|
export declare const KEYWORDS: Keyword[];
|
|
14
14
|
export declare const FINAL_OPERATORS: readonly ["==", "in", ">=", "<=", ">", "<", "!"];
|
|
15
15
|
export declare const LOGICAL_OPERATORS: readonly ["&&", "||"];
|
|
16
|
-
export declare const tokenize: (rawInput: string) => {
|
|
16
|
+
export declare const tokenize: (rawInput: string, fileLocation: string) => {
|
|
17
17
|
tokens: Token[];
|
|
18
18
|
errors: Diagnostic[];
|
|
19
19
|
};
|
package/dist/lexer.js
CHANGED
|
@@ -212,7 +212,7 @@ const TOKENS = [
|
|
|
212
212
|
valueExtractor: (value) => value.slice(1),
|
|
213
213
|
},
|
|
214
214
|
];
|
|
215
|
-
const tokenize = function (rawInput) {
|
|
215
|
+
const tokenize = function (rawInput, fileLocation) {
|
|
216
216
|
const input = rawInput.replace(/\r\n/g, '\n');
|
|
217
217
|
let index = 0, line = 1, start = 0, end = 0;
|
|
218
218
|
const tokens = [];
|
|
@@ -254,6 +254,7 @@ const tokenize = function (rawInput) {
|
|
|
254
254
|
if (value) {
|
|
255
255
|
let tokenValue;
|
|
256
256
|
const location = {
|
|
257
|
+
file: fileLocation,
|
|
257
258
|
index: index += value.length,
|
|
258
259
|
line,
|
|
259
260
|
end: end += value.length,
|
|
@@ -354,6 +355,7 @@ const tokenize = function (rawInput) {
|
|
|
354
355
|
if (!hasMatch) {
|
|
355
356
|
index += input.slice(index).search(/[ \t\n\{\}\(\)\[\]]/);
|
|
356
357
|
errors.push(new diagnostic_js_1.Diagnostic('unexpected token', {
|
|
358
|
+
file: fileLocation,
|
|
357
359
|
index,
|
|
358
360
|
line,
|
|
359
361
|
start,
|
package/dist/lexer.mjs
CHANGED
|
@@ -220,7 +220,7 @@ const TOKENS = [
|
|
|
220
220
|
valueExtractor: (value) => value.slice(1)
|
|
221
221
|
}
|
|
222
222
|
];
|
|
223
|
-
export const tokenize = function(rawInput) {
|
|
223
|
+
export const tokenize = function(rawInput, fileLocation) {
|
|
224
224
|
const input = rawInput.replace(/\r\n/g, "\n");
|
|
225
225
|
let index = 0, line = 1, start = 0, end = 0;
|
|
226
226
|
const tokens = [];
|
|
@@ -260,6 +260,7 @@ export const tokenize = function(rawInput) {
|
|
|
260
260
|
if (value) {
|
|
261
261
|
let tokenValue;
|
|
262
262
|
const location = {
|
|
263
|
+
file: fileLocation,
|
|
263
264
|
index: index += value.length,
|
|
264
265
|
line,
|
|
265
266
|
end: end += value.length,
|
|
@@ -357,6 +358,7 @@ export const tokenize = function(rawInput) {
|
|
|
357
358
|
if (!hasMatch) {
|
|
358
359
|
index += input.slice(index).search(/[ \t\n\{\}\(\)\[\]]/);
|
|
359
360
|
errors.push(new Diagnostic("unexpected token", {
|
|
361
|
+
file: fileLocation,
|
|
360
362
|
index,
|
|
361
363
|
line,
|
|
362
364
|
start,
|
package/dist/parser.js
CHANGED
|
@@ -667,7 +667,7 @@ const parse = (tokens) => {
|
|
|
667
667
|
return checkForValidRoles(value, symbols);
|
|
668
668
|
}
|
|
669
669
|
};
|
|
670
|
-
const parseCollection = (
|
|
670
|
+
const parseCollection = () => {
|
|
671
671
|
consume(token_js_1.TokenType.Keyword, 'collection');
|
|
672
672
|
const { value: name } = consume(token_js_1.TokenType.Identifier);
|
|
673
673
|
const node = {
|
|
@@ -719,7 +719,9 @@ const parse = (tokens) => {
|
|
|
719
719
|
break;
|
|
720
720
|
}
|
|
721
721
|
case 'functions': {
|
|
722
|
-
|
|
722
|
+
const { functions, functionSets } = parseFunctionsBlock();
|
|
723
|
+
node.functions = functions;
|
|
724
|
+
node.functionSets = functionSets;
|
|
723
725
|
break;
|
|
724
726
|
}
|
|
725
727
|
case 'individualActions':
|
|
@@ -824,9 +826,10 @@ const parse = (tokens) => {
|
|
|
824
826
|
consume(token_js_1.TokenType.RightBracket);
|
|
825
827
|
return node;
|
|
826
828
|
};
|
|
827
|
-
const parseFunctionsBlock = (
|
|
829
|
+
const parseFunctionsBlock = () => {
|
|
828
830
|
consume(token_js_1.TokenType.LeftBracket);
|
|
829
831
|
const functions = {};
|
|
832
|
+
const functionSets = [];
|
|
830
833
|
while (!match(token_js_1.TokenType.RightBracket)) {
|
|
831
834
|
try {
|
|
832
835
|
if (match(token_js_1.TokenType.MacroName)) {
|
|
@@ -834,11 +837,12 @@ const parse = (tokens) => {
|
|
|
834
837
|
switch (macroName) {
|
|
835
838
|
case 'include': {
|
|
836
839
|
const { value: functionSetName, location } = consume(token_js_1.TokenType.Identifier);
|
|
837
|
-
const
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
840
|
+
const functionSetSymbol = Symbol();
|
|
841
|
+
exports.locationMap.set(functionSetSymbol, location);
|
|
842
|
+
functionSets.push([
|
|
843
|
+
functionSetName,
|
|
844
|
+
functionSetSymbol,
|
|
845
|
+
]);
|
|
842
846
|
consume(token_js_1.TokenType.RightParens);
|
|
843
847
|
break;
|
|
844
848
|
}
|
|
@@ -880,15 +884,20 @@ const parse = (tokens) => {
|
|
|
880
884
|
}
|
|
881
885
|
}
|
|
882
886
|
consume(token_js_1.TokenType.RightBracket);
|
|
883
|
-
return
|
|
887
|
+
return {
|
|
888
|
+
functions,
|
|
889
|
+
functionSets,
|
|
890
|
+
};
|
|
884
891
|
};
|
|
885
|
-
const parseFunctionSet = (
|
|
892
|
+
const parseFunctionSet = () => {
|
|
886
893
|
consume(token_js_1.TokenType.Keyword, 'functionset');
|
|
887
894
|
const { value: name } = consume(token_js_1.TokenType.Identifier);
|
|
895
|
+
const { functions, functionSets } = parseFunctionsBlock();
|
|
888
896
|
const node = {
|
|
889
897
|
kind: 'functionset',
|
|
890
898
|
name,
|
|
891
|
-
functions
|
|
899
|
+
functions,
|
|
900
|
+
functionSets,
|
|
892
901
|
};
|
|
893
902
|
return node;
|
|
894
903
|
};
|
|
@@ -1272,7 +1281,7 @@ const parse = (tokens) => {
|
|
|
1272
1281
|
try {
|
|
1273
1282
|
switch (declType) {
|
|
1274
1283
|
case 'collection': {
|
|
1275
|
-
const collection = parseCollection(
|
|
1284
|
+
const collection = parseCollection();
|
|
1276
1285
|
if (collection.name === 'User') {
|
|
1277
1286
|
const { properties } = collection;
|
|
1278
1287
|
if ('roles' in properties && 'items' in properties.roles.property && 'enum' in properties.roles.property.items) {
|
|
@@ -1287,7 +1296,7 @@ const parse = (tokens) => {
|
|
|
1287
1296
|
break;
|
|
1288
1297
|
}
|
|
1289
1298
|
case 'functionset': {
|
|
1290
|
-
ast.functionsets.push(parseFunctionSet(
|
|
1299
|
+
ast.functionsets.push(parseFunctionSet());
|
|
1291
1300
|
break;
|
|
1292
1301
|
}
|
|
1293
1302
|
default:
|
package/dist/parser.mjs
CHANGED
|
@@ -614,7 +614,7 @@ export const parse = (tokens) => {
|
|
|
614
614
|
return checkForValidRoles(value, symbols);
|
|
615
615
|
}
|
|
616
616
|
};
|
|
617
|
-
const parseCollection = (
|
|
617
|
+
const parseCollection = () => {
|
|
618
618
|
consume(TokenType.Keyword, "collection");
|
|
619
619
|
const { value: name } = consume(TokenType.Identifier);
|
|
620
620
|
const node = {
|
|
@@ -665,7 +665,9 @@ export const parse = (tokens) => {
|
|
|
665
665
|
break;
|
|
666
666
|
}
|
|
667
667
|
case "functions": {
|
|
668
|
-
|
|
668
|
+
const { functions, functionSets } = parseFunctionsBlock();
|
|
669
|
+
node.functions = functions;
|
|
670
|
+
node.functionSets = functionSets;
|
|
669
671
|
break;
|
|
670
672
|
}
|
|
671
673
|
case "individualActions":
|
|
@@ -769,9 +771,10 @@ export const parse = (tokens) => {
|
|
|
769
771
|
consume(TokenType.RightBracket);
|
|
770
772
|
return node;
|
|
771
773
|
};
|
|
772
|
-
const parseFunctionsBlock = (
|
|
774
|
+
const parseFunctionsBlock = () => {
|
|
773
775
|
consume(TokenType.LeftBracket);
|
|
774
776
|
const functions = {};
|
|
777
|
+
const functionSets = [];
|
|
775
778
|
while (!match(TokenType.RightBracket)) {
|
|
776
779
|
try {
|
|
777
780
|
if (match(TokenType.MacroName)) {
|
|
@@ -779,11 +782,12 @@ export const parse = (tokens) => {
|
|
|
779
782
|
switch (macroName) {
|
|
780
783
|
case "include": {
|
|
781
784
|
const { value: functionSetName, location } = consume(TokenType.Identifier);
|
|
782
|
-
const
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
785
|
+
const functionSetSymbol = Symbol();
|
|
786
|
+
locationMap.set(functionSetSymbol, location);
|
|
787
|
+
functionSets.push([
|
|
788
|
+
functionSetName,
|
|
789
|
+
functionSetSymbol
|
|
790
|
+
]);
|
|
787
791
|
consume(TokenType.RightParens);
|
|
788
792
|
break;
|
|
789
793
|
}
|
|
@@ -823,15 +827,20 @@ export const parse = (tokens) => {
|
|
|
823
827
|
}
|
|
824
828
|
}
|
|
825
829
|
consume(TokenType.RightBracket);
|
|
826
|
-
return
|
|
830
|
+
return {
|
|
831
|
+
functions,
|
|
832
|
+
functionSets
|
|
833
|
+
};
|
|
827
834
|
};
|
|
828
|
-
const parseFunctionSet = (
|
|
835
|
+
const parseFunctionSet = () => {
|
|
829
836
|
consume(TokenType.Keyword, "functionset");
|
|
830
837
|
const { value: name } = consume(TokenType.Identifier);
|
|
838
|
+
const { functions, functionSets } = parseFunctionsBlock();
|
|
831
839
|
const node = {
|
|
832
840
|
kind: "functionset",
|
|
833
841
|
name,
|
|
834
|
-
functions
|
|
842
|
+
functions,
|
|
843
|
+
functionSets
|
|
835
844
|
};
|
|
836
845
|
return node;
|
|
837
846
|
};
|
|
@@ -1209,7 +1218,7 @@ export const parse = (tokens) => {
|
|
|
1209
1218
|
try {
|
|
1210
1219
|
switch (declType) {
|
|
1211
1220
|
case "collection": {
|
|
1212
|
-
const collection = parseCollection(
|
|
1221
|
+
const collection = parseCollection();
|
|
1213
1222
|
if (collection.name === "User") {
|
|
1214
1223
|
const { properties } = collection;
|
|
1215
1224
|
if ("roles" in properties && "items" in properties.roles.property && "enum" in properties.roles.property.items) {
|
|
@@ -1224,7 +1233,7 @@ export const parse = (tokens) => {
|
|
|
1224
1233
|
break;
|
|
1225
1234
|
}
|
|
1226
1235
|
case "functionset": {
|
|
1227
|
-
ast.functionsets.push(parseFunctionSet(
|
|
1236
|
+
ast.functionsets.push(parseFunctionSet());
|
|
1228
1237
|
break;
|
|
1229
1238
|
}
|
|
1230
1239
|
default:
|
package/dist/token.d.ts
CHANGED