@guardian-network/policy-dsl 0.3.2

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.
Files changed (121) hide show
  1. package/README.md +82 -0
  2. package/dist/antlr/generated/grammar/LacLangLexer.d.ts +53 -0
  3. package/dist/antlr/generated/grammar/LacLangLexer.d.ts.map +1 -0
  4. package/dist/antlr/generated/grammar/LacLangLexer.js +322 -0
  5. package/dist/antlr/generated/grammar/LacLangLexer.js.map +1 -0
  6. package/dist/antlr/generated/grammar/LacLangListener.d.ts +39 -0
  7. package/dist/antlr/generated/grammar/LacLangListener.d.ts.map +1 -0
  8. package/dist/antlr/generated/grammar/LacLangListener.js +3 -0
  9. package/dist/antlr/generated/grammar/LacLangListener.js.map +1 -0
  10. package/dist/antlr/generated/grammar/LacLangParser.d.ts +231 -0
  11. package/dist/antlr/generated/grammar/LacLangParser.d.ts.map +1 -0
  12. package/dist/antlr/generated/grammar/LacLangParser.js +1399 -0
  13. package/dist/antlr/generated/grammar/LacLangParser.js.map +1 -0
  14. package/dist/antlr/index.d.ts +4 -0
  15. package/dist/antlr/index.d.ts.map +1 -0
  16. package/dist/antlr/index.js +20 -0
  17. package/dist/antlr/index.js.map +1 -0
  18. package/dist/index.d.ts +4 -0
  19. package/dist/index.d.ts.map +1 -0
  20. package/dist/index.js +23 -0
  21. package/dist/index.js.map +1 -0
  22. package/dist/ir-generation/hashing.helper.d.ts +3 -0
  23. package/dist/ir-generation/hashing.helper.d.ts.map +1 -0
  24. package/dist/ir-generation/hashing.helper.js +12 -0
  25. package/dist/ir-generation/hashing.helper.js.map +1 -0
  26. package/dist/ir-generation/index.d.ts +3 -0
  27. package/dist/ir-generation/index.d.ts.map +1 -0
  28. package/dist/ir-generation/index.js +19 -0
  29. package/dist/ir-generation/index.js.map +1 -0
  30. package/dist/ir-generation/parsed-state-to-ir.transformer.d.ts +11 -0
  31. package/dist/ir-generation/parsed-state-to-ir.transformer.d.ts.map +1 -0
  32. package/dist/ir-generation/parsed-state-to-ir.transformer.js +30 -0
  33. package/dist/ir-generation/parsed-state-to-ir.transformer.js.map +1 -0
  34. package/dist/transpiler/Transpiler.d.ts +17 -0
  35. package/dist/transpiler/Transpiler.d.ts.map +1 -0
  36. package/dist/transpiler/Transpiler.js +43 -0
  37. package/dist/transpiler/Transpiler.js.map +1 -0
  38. package/dist/transpiler/errors/ErrorFactory.d.ts +22 -0
  39. package/dist/transpiler/errors/ErrorFactory.d.ts.map +1 -0
  40. package/dist/transpiler/errors/ErrorFactory.js +62 -0
  41. package/dist/transpiler/errors/ErrorFactory.js.map +1 -0
  42. package/dist/transpiler/errors/helpers.d.ts +3 -0
  43. package/dist/transpiler/errors/helpers.d.ts.map +1 -0
  44. package/dist/transpiler/errors/helpers.js +6 -0
  45. package/dist/transpiler/errors/helpers.js.map +1 -0
  46. package/dist/transpiler/errors/index.d.ts +2 -0
  47. package/dist/transpiler/errors/index.d.ts.map +1 -0
  48. package/dist/transpiler/errors/index.js +18 -0
  49. package/dist/transpiler/errors/index.js.map +1 -0
  50. package/dist/transpiler/errors/validation-errors.d.ts +57 -0
  51. package/dist/transpiler/errors/validation-errors.d.ts.map +1 -0
  52. package/dist/transpiler/errors/validation-errors.js +132 -0
  53. package/dist/transpiler/errors/validation-errors.js.map +1 -0
  54. package/dist/transpiler/helpers/formatter.d.ts +10 -0
  55. package/dist/transpiler/helpers/formatter.d.ts.map +1 -0
  56. package/dist/transpiler/helpers/formatter.js +140 -0
  57. package/dist/transpiler/helpers/formatter.js.map +1 -0
  58. package/dist/transpiler/helpers/index.d.ts +5 -0
  59. package/dist/transpiler/helpers/index.d.ts.map +1 -0
  60. package/dist/transpiler/helpers/index.js +21 -0
  61. package/dist/transpiler/helpers/index.js.map +1 -0
  62. package/dist/transpiler/helpers/resources.helper.d.ts +4 -0
  63. package/dist/transpiler/helpers/resources.helper.d.ts.map +1 -0
  64. package/dist/transpiler/helpers/resources.helper.js +50 -0
  65. package/dist/transpiler/helpers/resources.helper.js.map +1 -0
  66. package/dist/transpiler/helpers/types.d.ts +12 -0
  67. package/dist/transpiler/helpers/types.d.ts.map +1 -0
  68. package/dist/transpiler/helpers/types.js +3 -0
  69. package/dist/transpiler/helpers/types.js.map +1 -0
  70. package/dist/transpiler/helpers/validations.helper.d.ts +8 -0
  71. package/dist/transpiler/helpers/validations.helper.d.ts.map +1 -0
  72. package/dist/transpiler/helpers/validations.helper.js +41 -0
  73. package/dist/transpiler/helpers/validations.helper.js.map +1 -0
  74. package/dist/transpiler/index.d.ts +3 -0
  75. package/dist/transpiler/index.d.ts.map +1 -0
  76. package/dist/transpiler/index.js +21 -0
  77. package/dist/transpiler/index.js.map +1 -0
  78. package/dist/transpiler/listener.d.ts +17 -0
  79. package/dist/transpiler/listener.d.ts.map +1 -0
  80. package/dist/transpiler/listener.js +94 -0
  81. package/dist/transpiler/listener.js.map +1 -0
  82. package/dist/transpiler/state/LatentState.d.ts +30 -0
  83. package/dist/transpiler/state/LatentState.d.ts.map +1 -0
  84. package/dist/transpiler/state/LatentState.js +130 -0
  85. package/dist/transpiler/state/LatentState.js.map +1 -0
  86. package/dist/transpiler/state/index.d.ts +3 -0
  87. package/dist/transpiler/state/index.d.ts.map +1 -0
  88. package/dist/transpiler/state/index.js +19 -0
  89. package/dist/transpiler/state/index.js.map +1 -0
  90. package/dist/transpiler/state/types.d.ts +42 -0
  91. package/dist/transpiler/state/types.d.ts.map +1 -0
  92. package/dist/transpiler/state/types.js +3 -0
  93. package/dist/transpiler/state/types.js.map +1 -0
  94. package/package.json +79 -0
  95. package/src/antlr/generated/grammar/LacLang.interp +88 -0
  96. package/src/antlr/generated/grammar/LacLang.tokens +52 -0
  97. package/src/antlr/generated/grammar/LacLangLexer.interp +108 -0
  98. package/src/antlr/generated/grammar/LacLangLexer.tokens +52 -0
  99. package/src/antlr/generated/grammar/LacLangLexer.ts +331 -0
  100. package/src/antlr/generated/grammar/LacLangListener.ts +216 -0
  101. package/src/antlr/generated/grammar/LacLangParser.ts +1484 -0
  102. package/src/antlr/index.ts +3 -0
  103. package/src/index.ts +3 -0
  104. package/src/ir-generation/hashing.helper.ts +13 -0
  105. package/src/ir-generation/index.ts +2 -0
  106. package/src/ir-generation/parsed-state-to-ir.transformer.ts +50 -0
  107. package/src/transpiler/Transpiler.ts +58 -0
  108. package/src/transpiler/errors/ErrorFactory.ts +130 -0
  109. package/src/transpiler/errors/helpers.ts +4 -0
  110. package/src/transpiler/errors/index.ts +1 -0
  111. package/src/transpiler/errors/validation-errors.ts +157 -0
  112. package/src/transpiler/helpers/formatter.ts +173 -0
  113. package/src/transpiler/helpers/index.ts +4 -0
  114. package/src/transpiler/helpers/resources.helper.ts +83 -0
  115. package/src/transpiler/helpers/types.ts +23 -0
  116. package/src/transpiler/helpers/validations.helper.ts +69 -0
  117. package/src/transpiler/index.ts +2 -0
  118. package/src/transpiler/listener.ts +180 -0
  119. package/src/transpiler/state/LatentState.ts +202 -0
  120. package/src/transpiler/state/index.ts +2 -0
  121. package/src/transpiler/state/types.ts +50 -0
@@ -0,0 +1,3 @@
1
+ export * from './generated/grammar/LacLangLexer';
2
+ export * from './generated/grammar/LacLangListener';
3
+ export * from './generated/grammar/LacLangParser';
package/src/index.ts ADDED
@@ -0,0 +1,3 @@
1
+ export * from './antlr';
2
+ export { nodeIdFromDeclaration } from './ir-generation';
3
+ export { Transpiler } from './transpiler';
@@ -0,0 +1,13 @@
1
+ import { InstanceConfig, NodeId } from '@guardian-network/shared';
2
+ import { IRTransformer } from '.';
3
+
4
+ export const nodeIdFromDeclaration = (
5
+ def: InstanceConfig,
6
+ salt: number,
7
+ ): string => {
8
+ const artifactIntermediateForm =
9
+ IRTransformer.buildIRFromInstanceDeclaration(def);
10
+
11
+ const nodeId = NodeId.fromNotation(artifactIntermediateForm, salt);
12
+ return nodeId;
13
+ };
@@ -0,0 +1,2 @@
1
+ export * from './hashing.helper';
2
+ export * from './parsed-state-to-ir.transformer';
@@ -0,0 +1,50 @@
1
+ import {
2
+ InstanceConfig,
3
+ mapToArray,
4
+ TypedValue,
5
+ } from '@guardian-network/shared';
6
+ import { LatentState } from '../transpiler/state/LatentState';
7
+
8
+ export class IRTransformer {
9
+ public static buildIRFromInstanceDeclaration(config: InstanceConfig): string {
10
+ return formatDeclaration(config);
11
+ }
12
+
13
+ public static buildFullIR(state: LatentState): {
14
+ rootNode: string;
15
+ definitions: string[];
16
+ typings: InstanceConfig[];
17
+ } {
18
+ const sortedInstances = mapToArray(state.instancesByName).sort(
19
+ (a, b) => a.index - b.index,
20
+ );
21
+
22
+ return {
23
+ definitions: sortedInstances.map((el) =>
24
+ this.buildIRFromInstanceDeclaration(el.config),
25
+ ),
26
+ rootNode: state.evaluateRelativeTo!.nodeId,
27
+ typings: sortedInstances.map((el) => el.config),
28
+ };
29
+ }
30
+ }
31
+
32
+ const formatArtifactClause = (artifactAddress: string) =>
33
+ `{${artifactAddress}}`;
34
+
35
+ const formatExecArgumentsClause = (args: TypedValue[]) =>
36
+ `(${args.map((el) => el.value).join(',')})`;
37
+
38
+ const formatInitArgumentsClause = (args: TypedValue[]) =>
39
+ `<${args.map((el) => el.value).join(',')}>`;
40
+
41
+ const formatDeclaration = (config: InstanceConfig) => {
42
+ const { artifactAddress, initArguments, execArguments, needsInitialization } =
43
+ config;
44
+ const initializationClause = needsInitialization
45
+ ? formatInitArgumentsClause(initArguments)
46
+ : '';
47
+
48
+ const formatted = `${formatArtifactClause(artifactAddress)} ${formatExecArgumentsClause(execArguments)} ${initializationClause}`;
49
+ return formatted;
50
+ };
@@ -0,0 +1,58 @@
1
+ import { TranspilerOutput } from '@guardian-network/shared';
2
+ import { CharStreams, CodePointCharStream, CommonTokenStream } from 'antlr4ts';
3
+ import { ParseTreeListener } from 'antlr4ts/tree/ParseTreeListener';
4
+ import { ParseTreeWalker } from 'antlr4ts/tree/ParseTreeWalker';
5
+ import { LacLangLexer, LacLangParser, ProgramContext } from '../antlr';
6
+ import { IRTransformer } from '../ir-generation';
7
+ import { TranspilerConfig } from './helpers';
8
+ import { LacLangTranspiler } from './listener';
9
+ import { LatentState } from './state';
10
+
11
+ export class Transpiler {
12
+ protected tree: ProgramContext;
13
+ protected listener: LacLangTranspiler;
14
+ protected walker: ParseTreeWalker;
15
+
16
+ // are those needed within state???
17
+ /* protected inputStream: CodePointCharStream;
18
+ protected lexer: LacLangLexer;
19
+ protected tokenStream: CommonTokenStream;
20
+ protected parser: LacLangParser; */
21
+
22
+ static create = (sources: string, options: TranspilerConfig) => {
23
+ return new Transpiler(sources, options);
24
+ };
25
+
26
+ constructor(sources: string, options: TranspilerConfig) {
27
+ const inputStream: CodePointCharStream = CharStreams.fromString(sources);
28
+ const lexer = new LacLangLexer(inputStream);
29
+ const tokenStream = new CommonTokenStream(lexer);
30
+ const parser = new LacLangParser(tokenStream);
31
+
32
+ this.tree = parser.program();
33
+ this.listener = new LacLangTranspiler(options);
34
+ this.walker = new ParseTreeWalker();
35
+ }
36
+
37
+ transpile() {
38
+ this.walker.walk(<ParseTreeListener>this.listener, this.tree);
39
+ return this;
40
+ }
41
+
42
+ toIntermediateRepresentation(): TranspilerOutput {
43
+ const { definitions, rootNode, typings } = IRTransformer.buildFullIR(
44
+ this.listener.latentState,
45
+ );
46
+ const ir = definitions.join('\r\n');
47
+
48
+ return {
49
+ ir,
50
+ rootNode,
51
+ typings,
52
+ };
53
+ }
54
+
55
+ getLatentState(): LatentState {
56
+ return this.listener.latentState;
57
+ }
58
+ }
@@ -0,0 +1,130 @@
1
+ import {
2
+ ArtifactAlreadyDefinedError,
3
+ ArtifactNotDefinedError,
4
+ CannotInferValueTypeError,
5
+ ConstantIsAlreadyDefinedError,
6
+ ConstantNotDefinedError,
7
+ CyclicReferenceDSLError,
8
+ EvaluateAlreadyDeclaredError,
9
+ EvaluateTypeNotBoolError,
10
+ ImportAmbiguityError,
11
+ ImpropperInitArgsMutabilityError,
12
+ InstanceAlreadyDefinedError,
13
+ InstanceNotDefinedError,
14
+ NoEvaluateStatementError,
15
+ NonInjectedVariablesNotAllowedError,
16
+ SelfReferenceDSLError,
17
+ UnkownDirectiveError,
18
+ VariableAlreadyDefinedError,
19
+ VariableNotDefinedError,
20
+ } from './validation-errors';
21
+
22
+ export class ErrorFactory {
23
+ static importAmbiguity = (
24
+ ...params: Parameters<typeof ImportAmbiguityError.create>
25
+ ) => {
26
+ return ImportAmbiguityError.create(...params);
27
+ };
28
+
29
+ static nonInjectedVariable = (
30
+ ...params: Parameters<typeof NonInjectedVariablesNotAllowedError.create>
31
+ ) => {
32
+ return NonInjectedVariablesNotAllowedError.create(...params);
33
+ };
34
+
35
+ static unknownDirective = (
36
+ ...params: Parameters<typeof UnkownDirectiveError.create>
37
+ ) => {
38
+ return UnkownDirectiveError.create(...params);
39
+ };
40
+
41
+ static constantIsAlreadyDefined = (
42
+ ...params: Parameters<typeof ConstantIsAlreadyDefinedError.create>
43
+ ) => {
44
+ return ConstantIsAlreadyDefinedError.create(...params);
45
+ };
46
+
47
+ static variableAlreadyDefined = (
48
+ ...params: Parameters<typeof VariableAlreadyDefinedError.create>
49
+ ) => {
50
+ return VariableAlreadyDefinedError.create(...params);
51
+ };
52
+
53
+ static artifactAlreadyDefined = (
54
+ ...params: Parameters<typeof ArtifactAlreadyDefinedError.create>
55
+ ) => {
56
+ return ArtifactAlreadyDefinedError.create(...params);
57
+ };
58
+
59
+ static instanceAlreadyDefined = (
60
+ ...params: Parameters<typeof InstanceAlreadyDefinedError.create>
61
+ ) => {
62
+ return InstanceAlreadyDefinedError.create(...params);
63
+ };
64
+
65
+ static evaluateAlreadyDeclared = (
66
+ ...params: Parameters<typeof EvaluateAlreadyDeclaredError.create>
67
+ ) => {
68
+ return EvaluateAlreadyDeclaredError.create(...params);
69
+ };
70
+
71
+ static artifactNotDefined = (
72
+ ...params: Parameters<typeof ArtifactNotDefinedError.create>
73
+ ) => {
74
+ return ArtifactNotDefinedError.create(...params);
75
+ };
76
+
77
+ static variableNotDefined = (
78
+ ...params: Parameters<typeof VariableNotDefinedError.create>
79
+ ) => {
80
+ return VariableNotDefinedError.create(...params);
81
+ };
82
+
83
+ static constantNotDefined = (
84
+ ...params: Parameters<typeof ConstantNotDefinedError.create>
85
+ ) => {
86
+ return ConstantNotDefinedError.create(...params);
87
+ };
88
+
89
+ static instanceNotDefined = (
90
+ ...params: Parameters<typeof InstanceNotDefinedError.create>
91
+ ) => {
92
+ return InstanceNotDefinedError.create(...params);
93
+ };
94
+
95
+ static impropperInitArgsMutabilityMode = (
96
+ ...params: Parameters<typeof ImpropperInitArgsMutabilityError.create>
97
+ ) => {
98
+ return ImpropperInitArgsMutabilityError.create(...params);
99
+ };
100
+
101
+ static evaluateTypeNotBool = (
102
+ ...params: Parameters<typeof EvaluateTypeNotBoolError.create>
103
+ ) => {
104
+ return EvaluateTypeNotBoolError.create(...params);
105
+ };
106
+
107
+ static noEvaluateStatement = (
108
+ ...params: Parameters<typeof NoEvaluateStatementError.create>
109
+ ) => {
110
+ return NoEvaluateStatementError.create(...params);
111
+ };
112
+
113
+ static cyclicReferenceDSL = (
114
+ ...params: Parameters<typeof CyclicReferenceDSLError.create>
115
+ ) => {
116
+ return CyclicReferenceDSLError.create(...params);
117
+ };
118
+
119
+ static selfReferenceDSL = (
120
+ ...params: Parameters<typeof SelfReferenceDSLError.create>
121
+ ) => {
122
+ return SelfReferenceDSLError.create(...params);
123
+ };
124
+
125
+ static cannotInferValueType = (
126
+ ...params: Parameters<typeof CannotInferValueTypeError.create>
127
+ ) => {
128
+ return CannotInferValueTypeError.create(...params);
129
+ };
130
+ }
@@ -0,0 +1,4 @@
1
+ import { ParserRuleContext } from 'antlr4ts';
2
+
3
+ export const formatTranspileErrorLocation = (ctx: ParserRuleContext) =>
4
+ `${ctx.start.line}:${ctx.start.charPositionInLine}-${ctx.stop?.line}:${ctx.stop?.charPositionInLine}`;
@@ -0,0 +1 @@
1
+ export * from './ErrorFactory';
@@ -0,0 +1,157 @@
1
+ import { BaseError } from '@guardian-network/shared';
2
+ import { ParserRuleContext } from 'antlr4ts';
3
+ import { formatTranspileErrorLocation as formatLocation } from './helpers';
4
+
5
+ export class ConstantIsAlreadyDefinedError extends BaseError {
6
+ static create = (
7
+ name: string,
8
+ selfContext: ParserRuleContext,
9
+ collisionContext: ParserRuleContext,
10
+ ) => {
11
+ const errorMessage = `Constant ${name} declared on ${formatLocation(selfContext)} was already defined on ${formatLocation(collisionContext)}`;
12
+ return this.build(errorMessage);
13
+ };
14
+ }
15
+
16
+ export class VariableAlreadyDefinedError extends BaseError {
17
+ static create = (
18
+ name: string,
19
+ selfContext: ParserRuleContext,
20
+ collisionContext: ParserRuleContext,
21
+ ) => {
22
+ const errorMessage = `Variable ${name} declared on ${formatLocation(selfContext)} was already defined on ${formatLocation(collisionContext)}`;
23
+ return this.build(errorMessage);
24
+ };
25
+ }
26
+
27
+ export class ArtifactAlreadyDefinedError extends BaseError {
28
+ static create = (
29
+ name: string,
30
+ selfContext: ParserRuleContext,
31
+ collisionContext: ParserRuleContext,
32
+ ) => {
33
+ const errorMessage = `Artifact ${name} declared on ${formatLocation(selfContext)} was already defined on ${formatLocation(collisionContext)}`;
34
+ return this.build(errorMessage);
35
+ };
36
+ }
37
+
38
+ export class InstanceAlreadyDefinedError extends BaseError {
39
+ static create = (
40
+ name: string,
41
+ selfContext: ParserRuleContext,
42
+ collisionContext: ParserRuleContext,
43
+ ) => {
44
+ const errorMessage = `Instance ${name} declared on ${formatLocation(selfContext)} was already defined on ${formatLocation(collisionContext)}`;
45
+ return this.build(errorMessage);
46
+ };
47
+ }
48
+
49
+ export class EvaluateAlreadyDeclaredError extends BaseError {
50
+ static create = (
51
+ selfContext: ParserRuleContext,
52
+ collisionContext: ParserRuleContext,
53
+ ) => {
54
+ const errorMessage = `Evaluate statement can only be declared once, but was declared on ${formatLocation(selfContext)} being already defined on ${formatLocation(collisionContext)}`;
55
+ return this.build(errorMessage);
56
+ };
57
+ }
58
+
59
+ export class ArtifactNotDefinedError extends BaseError {
60
+ static create = (name: string, selfContext: ParserRuleContext) => {
61
+ const errorMessage = `Artifact ${name} (referenced ${formatLocation(selfContext)}) was not found in the scope`;
62
+ return this.build(errorMessage);
63
+ };
64
+ }
65
+
66
+ export class VariableNotDefinedError extends BaseError {
67
+ static create = (name: string, selfContext: ParserRuleContext) => {
68
+ const errorMessage = `Variable ${name} (referenced ${formatLocation(selfContext)}) was not found in the scope`;
69
+ return this.build(errorMessage);
70
+ };
71
+ }
72
+
73
+ export class ConstantNotDefinedError extends BaseError {
74
+ static create = (name: string, selfContext: ParserRuleContext) => {
75
+ const errorMessage = `Constant ${name} (referenced ${formatLocation(selfContext)}) was not found in the scope`;
76
+ return this.build(errorMessage);
77
+ };
78
+ }
79
+
80
+ export class InstanceNotDefinedError extends BaseError {
81
+ static create = (name: string, selfContext: ParserRuleContext) => {
82
+ const errorMessage = `Instance ${name} (referenced ${formatLocation(selfContext)}) was not found in the scope`;
83
+ return this.build(errorMessage);
84
+ };
85
+ }
86
+
87
+ export class ImpropperInitArgsMutabilityError extends BaseError {
88
+ static create = (name: string, selfContext: ParserRuleContext) => {
89
+ const errorMessage = `Variable ${name} (referenced ${formatLocation(selfContext)}) must be constant to be an initialization argument`;
90
+ return this.build(errorMessage);
91
+ };
92
+ }
93
+
94
+ export class EvaluateTypeNotBoolError extends BaseError {
95
+ static create = (
96
+ name: string,
97
+ selfContext: ParserRuleContext,
98
+ referenceContext: ParserRuleContext,
99
+ ) => {
100
+ const errorMessage = `Type of ${name} instance return value (defined ${formatLocation(referenceContext)}) (referenced ${formatLocation(selfContext)}) must be boolean to be used as a root`;
101
+ return this.build(errorMessage);
102
+ };
103
+ }
104
+
105
+ export class UnkownDirectiveError extends BaseError {
106
+ static create = (name: string, selfContext: ParserRuleContext) => {
107
+ const errorMessage = `Unknown directive ${name} (dispatched ${formatLocation(selfContext)})`;
108
+ return this.build(errorMessage);
109
+ };
110
+ }
111
+
112
+ export class ImportAmbiguityError extends BaseError {
113
+ static create = (troublePropertyName: string, message: string) => {
114
+ const errorMessage = `Importing ${troublePropertyName} error: ${message}`;
115
+ return this.build(errorMessage);
116
+ };
117
+ }
118
+
119
+ export class NonInjectedVariablesNotAllowedError extends BaseError {
120
+ static create = (name: string, selfContext: ParserRuleContext) => {
121
+ const errorMessage = `Variable ${name} (declared ${formatLocation(selfContext)}) must be "injected" because of corresponding directive`;
122
+ return this.build(errorMessage);
123
+ };
124
+ }
125
+
126
+ export class NoEvaluateStatementError extends BaseError {
127
+ static create = () => {
128
+ const errorMessage = `The program must include evaluate statement to define graph root node`;
129
+ return this.build(errorMessage);
130
+ };
131
+ }
132
+
133
+ export class CyclicReferenceDSLError extends BaseError {
134
+ static create = (
135
+ selfName: string,
136
+ referenceName: string,
137
+ selfContext: ParserRuleContext,
138
+ referenceContext: ParserRuleContext,
139
+ ) => {
140
+ const errorMessage = `Instance ${selfName} (defined ${formatLocation(selfContext)}) is referenced in instance ${referenceName} (defined ${formatLocation(referenceContext)}) in a cyclic manner`;
141
+ return this.build(errorMessage);
142
+ };
143
+ }
144
+
145
+ export class SelfReferenceDSLError extends BaseError {
146
+ static create = (name: string, selfContext: ParserRuleContext) => {
147
+ const errorMessage = `Instance ${name} (defined ${formatLocation(selfContext)}) is referenced in its own arguments`;
148
+ return this.build(errorMessage);
149
+ };
150
+ }
151
+
152
+ export class CannotInferValueTypeError extends BaseError {
153
+ static create = (value: string, selfContext: ParserRuleContext) => {
154
+ const errorMessage = `Can not infer type of a literal value ${value} (encountered ${formatLocation(selfContext)})`;
155
+ return this.build(errorMessage);
156
+ };
157
+ }
@@ -0,0 +1,173 @@
1
+ import { InstanceConfig, TypedValue } from '@guardian-network/shared';
2
+ import { InstanceDeclarationContext, LiteralContext } from '../../antlr';
3
+ import { ErrorFactory } from '../errors/ErrorFactory';
4
+ import { LatentState } from '../state/LatentState';
5
+ import { Artifacts } from '../state/types';
6
+ import { lookupOrThrow } from './validations.helper';
7
+
8
+ export const extractAndLookupExecArguments = (
9
+ ctx: InstanceDeclarationContext,
10
+ latentState: LatentState,
11
+ ): TypedValue[] => {
12
+ if (!ctx.argumentsList()) return [];
13
+
14
+ return ctx
15
+ .argumentsList()!
16
+ .identifier_or_literal()
17
+ .map((el) => {
18
+ if (el.literal()) {
19
+ return inferTypedValue(el.literal()!);
20
+ }
21
+
22
+ const name = el.text;
23
+ const refConst = latentState.constants.get(name);
24
+
25
+ if (!refConst) {
26
+ const refVar = latentState.variables.get(name);
27
+ if (!refVar) {
28
+ const refInst = lookupOrThrow(
29
+ name,
30
+ latentState.instancesByName,
31
+ ErrorFactory.variableNotDefined(name, el.ruleContext),
32
+ );
33
+
34
+ return {
35
+ value: formatInstanceReference(refInst.id),
36
+ type: refInst.type,
37
+ substitution: true,
38
+ };
39
+ } else
40
+ return {
41
+ value: 'var' + name + `$${refVar.injection}`,
42
+ type: refVar.type,
43
+ };
44
+ } else {
45
+ if (refConst.type == 'bytes') {
46
+ return {
47
+ value: formatBytesLiteral(refConst.value),
48
+ type: refConst.type,
49
+ constant: true,
50
+ };
51
+ } else
52
+ return {
53
+ value: refConst.value,
54
+ type: refConst.type,
55
+ constant: true,
56
+ };
57
+ }
58
+ });
59
+ };
60
+
61
+ export const extractAndLookupInitArguments = (
62
+ ctx: InstanceDeclarationContext,
63
+ latentState: LatentState,
64
+ ): TypedValue[] | null => {
65
+ if (!ctx.WITH_KEYWORD()) return null;
66
+ if (!ctx.constantsList()) return [];
67
+
68
+ return ctx
69
+ .constantsList()!
70
+ .argumentsList()
71
+ .identifier_or_literal()
72
+ .map((el) => {
73
+ if (!!el.literal()) {
74
+ return inferTypedValue(el.literal()!);
75
+ }
76
+
77
+ const name = el.text;
78
+ const refConst = latentState.constants.get(name);
79
+
80
+ if (refConst) {
81
+ if (refConst.type == 'bytes') {
82
+ return {
83
+ value: formatBytesLiteral(refConst.value),
84
+ type: refConst.type,
85
+ };
86
+ } else
87
+ return {
88
+ value: refConst.value,
89
+ type: refConst.type,
90
+ };
91
+ } else {
92
+ lookupOrThrow(
93
+ name,
94
+ latentState.variables,
95
+ ErrorFactory.constantNotDefined(name, el.ruleContext),
96
+ );
97
+
98
+ throw ErrorFactory.impropperInitArgsMutabilityMode(
99
+ name,
100
+ el.ruleContext,
101
+ );
102
+ }
103
+ });
104
+ };
105
+
106
+ export const extractReferenceNodeIds = (config: InstanceConfig) => {
107
+ const substitutions = config.execArguments.filter((arg) => arg.substitution);
108
+
109
+ const referencesNodeIdList = substitutions.map(({ value }) =>
110
+ value.replaceAll('|', ''),
111
+ );
112
+ return referencesNodeIdList;
113
+ };
114
+
115
+ export const dereferenceArtifact = (
116
+ ctx: InstanceDeclarationContext,
117
+ artifactsMap: Artifacts,
118
+ ) => {
119
+ if (ctx.identifier_or_literal().literal()) {
120
+ const artifactDereferenced = ctx.identifier_or_literal().literal()!.text;
121
+ return artifactDereferenced;
122
+ }
123
+
124
+ const artifactName = ctx.identifier_or_literal().IDENTIFIER()!.text;
125
+ const { address } = lookupOrThrow(
126
+ artifactName,
127
+ artifactsMap,
128
+ ErrorFactory.artifactNotDefined(artifactName, ctx),
129
+ );
130
+
131
+ const artifactDereferenced = address;
132
+ return artifactDereferenced;
133
+ };
134
+
135
+ const inferTypedValue = (ctx: LiteralContext): TypedValue => {
136
+ let type: string;
137
+ let value = ctx.text;
138
+
139
+ switch (true) {
140
+ case !!ctx.ADDRESS_LITERAL():
141
+ type = 'address';
142
+ break;
143
+ case !!ctx.BOOL_LITERAL():
144
+ type = 'bool';
145
+ break;
146
+ case !!ctx.STRING_LITERAL():
147
+ type = 'string';
148
+ break;
149
+ case !!ctx.BYTES_LITERAL():
150
+ type = 'bytes';
151
+ value = formatBytesLiteral(value);
152
+ break;
153
+ case !!ctx.NUMBER_LITERAL():
154
+ type = 'number';
155
+ break;
156
+ default:
157
+ throw ErrorFactory.cannotInferValueType(ctx.text, ctx);
158
+ }
159
+
160
+ return {
161
+ type,
162
+ value,
163
+ constant: true,
164
+ };
165
+ };
166
+
167
+ const formatBytesLiteral = (value: string) => {
168
+ return value.replace(/^'|'$/g, '');
169
+ };
170
+
171
+ export const formatInstanceReference = (nodeId: string) => {
172
+ return `|${nodeId}|`;
173
+ };
@@ -0,0 +1,4 @@
1
+ export * from './formatter';
2
+ export * from './resources.helper';
3
+ export * from './types';
4
+ export * from './validations.helper';
@@ -0,0 +1,83 @@
1
+ import { readFileSync } from 'node:fs';
2
+ import fetchSycn from 'sync-fetch';
3
+
4
+ const DEFAULT_ENCODING = 'utf-8';
5
+
6
+ export const isLocalUrl = (url: string) =>
7
+ /^([a-zA-Z]:)?(\\|\/)([^\\\/]+(\\|\/)?)+$/.test(url);
8
+ export const isLocalRelativeUrl = (url: string) =>
9
+ /^(\.\.\/|\.\/)?([^\\\/]+(\\|\/)?)+$/.test(url);
10
+
11
+ const isHttpsUrl = (url: string) => /^https?:\/\//.test(url);
12
+ const isSshUrl = (url: string) => /^git@[^:]+:[^/]+\/.+\.git$/.test(url);
13
+
14
+ /*
15
+ The note about sync
16
+
17
+ The listener approach of the chosen Antlr transpiler is working sequentially:
18
+ 1. The parse tree is traversed (```.walk```)
19
+ 2. The listener hooks invoked on each node of the parse tree
20
+
21
+ The hooks (e.g. 'enterImportStatement') are void-returning by the nature. So, the hooks are synchronous.
22
+ That is the problem, the next traversing step won't wait 'till previous is resolved 'cause it's void anyways.
23
+ And an asynchronous logic in hooks can not be applied before the next step possibly needing it.
24
+
25
+ There is 3 solutions:
26
+ 1. Using Visitor approach and evaluate every parsing tree node by hand
27
+ 2. Rewrite the antlr core so the "walk" awaits
28
+ 3. Use only sync functions in hooks
29
+
30
+ The third is most appropriate by now, hence not the most elegant.
31
+ To synchronize the http request, one may want:
32
+ 1. Create a worker with all the asynchronous logic
33
+ 2. Execute this worker in a synchronus manner inside the main thread
34
+
35
+ All the above is encapsulated in "sync-fetch" using 'execSync' of 'node:process'.
36
+ Not the best solution, but for sync fetching of remote imports - it's OK.
37
+ */
38
+
39
+ export const fetchContent = (url: string): string => {
40
+ let content: string;
41
+
42
+ switch (true) {
43
+ case isSshUrl(url):
44
+ throw new Error('Not implemented import resource type: SSH');
45
+
46
+ case isHttpsUrl(url):
47
+ content = readFromHttp(url);
48
+ break;
49
+
50
+ case isLocalUrl(url):
51
+ case isLocalRelativeUrl(url):
52
+ content = readFromFile(url);
53
+ break;
54
+
55
+ default:
56
+ throw new Error(`Not supported import resource type: ${url}`);
57
+ }
58
+
59
+ return content;
60
+ };
61
+
62
+ const readFromFile = (filePath: string): string => {
63
+ try {
64
+ const content = readFileSync(filePath, DEFAULT_ENCODING);
65
+ return content;
66
+ } catch (error: any) {
67
+ throw new Error(
68
+ `Error reading file at ${filePath} with description ${error.message}`,
69
+ );
70
+ }
71
+ };
72
+
73
+ const readFromHttp = (url: string): string => {
74
+ const response = fetchSycn(url);
75
+
76
+ if (!response.ok) {
77
+ throw new Error(
78
+ `Failed to fetch file from remote URL: ${url}, status: ${response.status} ${response.statusText}`,
79
+ );
80
+ }
81
+
82
+ return response.text();
83
+ };