@fincity/kirun-js 3.1.4 → 3.2.0
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/__tests__/engine/dsl/GraphDebugTest.ts +316 -0
- package/__tests__/engine/runtime/expression/ExpressionParsingTest.ts +402 -14
- package/dist/index.js +15 -1
- package/dist/index.js.map +1 -1
- package/dist/module.js +15 -1
- package/dist/module.js.map +1 -1
- package/dist/types.d.ts +416 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/engine/dsl/DSLCompiler.ts +104 -0
- package/src/engine/dsl/index.ts +30 -0
- package/src/engine/dsl/lexer/DSLLexer.ts +518 -0
- package/src/engine/dsl/lexer/DSLToken.ts +74 -0
- package/src/engine/dsl/lexer/Keywords.ts +80 -0
- package/src/engine/dsl/lexer/LexerError.ts +37 -0
- package/src/engine/dsl/monaco/DSLFunctionProvider.ts +187 -0
- package/src/engine/dsl/parser/DSLParser.ts +1075 -0
- package/src/engine/dsl/parser/DSLParserError.ts +29 -0
- package/src/engine/dsl/parser/ast/ASTNode.ts +23 -0
- package/src/engine/dsl/parser/ast/ArgumentNode.ts +43 -0
- package/src/engine/dsl/parser/ast/ComplexValueNode.ts +22 -0
- package/src/engine/dsl/parser/ast/EventDeclNode.ts +27 -0
- package/src/engine/dsl/parser/ast/ExpressionNode.ts +33 -0
- package/src/engine/dsl/parser/ast/FunctionCallNode.ts +29 -0
- package/src/engine/dsl/parser/ast/FunctionDefNode.ts +37 -0
- package/src/engine/dsl/parser/ast/ParameterDeclNode.ts +25 -0
- package/src/engine/dsl/parser/ast/SchemaLiteralNode.ts +26 -0
- package/src/engine/dsl/parser/ast/SchemaNode.ts +23 -0
- package/src/engine/dsl/parser/ast/StatementNode.ts +41 -0
- package/src/engine/dsl/parser/ast/index.ts +14 -0
- package/src/engine/dsl/transformer/ASTToJSON.ts +378 -0
- package/src/engine/dsl/transformer/ExpressionHandler.ts +48 -0
- package/src/engine/dsl/transformer/JSONToText.ts +694 -0
- package/src/engine/dsl/transformer/SchemaTransformer.ts +110 -0
- package/src/engine/model/FunctionDefinition.ts +23 -0
- package/src/engine/runtime/expression/Expression.ts +5 -1
- package/src/engine/runtime/expression/ExpressionEvaluator.ts +152 -139
- package/src/engine/runtime/expression/ExpressionParser.ts +80 -27
- package/src/engine/util/duplicate.ts +3 -1
- package/src/index.ts +1 -0
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { DSLToken, SourceLocation } from '../lexer/DSLToken';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Parser error with position information and expected tokens
|
|
5
|
+
*/
|
|
6
|
+
export class DSLParserError extends Error {
|
|
7
|
+
constructor(
|
|
8
|
+
message: string,
|
|
9
|
+
public location?: SourceLocation,
|
|
10
|
+
public expectedTokens?: string[],
|
|
11
|
+
public actualToken?: DSLToken,
|
|
12
|
+
) {
|
|
13
|
+
super(message);
|
|
14
|
+
this.name = 'DSLParserError';
|
|
15
|
+
|
|
16
|
+
// Format error message with location if available
|
|
17
|
+
if (location) {
|
|
18
|
+
this.message = `${message} at ${location}`;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
if (expectedTokens && expectedTokens.length > 0) {
|
|
22
|
+
this.message += `\nExpected: ${expectedTokens.join(', ')}`;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
if (actualToken) {
|
|
26
|
+
this.message += `\nActual: ${actualToken.type} (${actualToken.value})`;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { SourceLocation } from '../../lexer/DSLToken';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Base class for all AST nodes
|
|
5
|
+
*/
|
|
6
|
+
export abstract class ASTNode {
|
|
7
|
+
constructor(
|
|
8
|
+
public readonly type: string,
|
|
9
|
+
public readonly location: SourceLocation,
|
|
10
|
+
) {}
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Convert AST node to JSON (for debugging/inspection)
|
|
14
|
+
*/
|
|
15
|
+
abstract toJSON(): any;
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Pretty-print the AST node
|
|
19
|
+
*/
|
|
20
|
+
public toString(): string {
|
|
21
|
+
return JSON.stringify(this.toJSON(), null, 2);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { SourceLocation } from '../../lexer/DSLToken';
|
|
2
|
+
import { ASTNode } from './ASTNode';
|
|
3
|
+
import { ComplexValueNode } from './ComplexValueNode';
|
|
4
|
+
import { ExpressionNode } from './ExpressionNode';
|
|
5
|
+
import { SchemaLiteralNode } from './SchemaLiteralNode';
|
|
6
|
+
|
|
7
|
+
export type ArgumentValue = ExpressionNode | ComplexValueNode | SchemaLiteralNode;
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Argument node - represents a function argument
|
|
11
|
+
* Can be a single value or multiple values (multi-value parameter)
|
|
12
|
+
* Each value can be an expression, complex value (object/array), or schema literal
|
|
13
|
+
*/
|
|
14
|
+
export class ArgumentNode extends ASTNode {
|
|
15
|
+
public values: ArgumentValue[];
|
|
16
|
+
|
|
17
|
+
constructor(
|
|
18
|
+
public key: string,
|
|
19
|
+
value: ArgumentValue | ArgumentValue[],
|
|
20
|
+
location: SourceLocation,
|
|
21
|
+
) {
|
|
22
|
+
super('Argument', location);
|
|
23
|
+
this.values = Array.isArray(value) ? value : [value];
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/** Get the first (or only) value - for backwards compatibility */
|
|
27
|
+
public get value(): ArgumentValue {
|
|
28
|
+
return this.values[0];
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/** Check if this is a multi-value parameter */
|
|
32
|
+
public isMultiValue(): boolean {
|
|
33
|
+
return this.values.length > 1;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
public toJSON(): any {
|
|
37
|
+
return {
|
|
38
|
+
type: this.type,
|
|
39
|
+
key: this.key,
|
|
40
|
+
values: this.values.map((v) => v.toJSON()),
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { SourceLocation } from '../../lexer/DSLToken';
|
|
2
|
+
import { ASTNode } from './ASTNode';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Complex value node - represents literal values
|
|
6
|
+
* Used for parameter values that are objects, arrays, or primitives (strings, numbers, booleans, null)
|
|
7
|
+
*/
|
|
8
|
+
export class ComplexValueNode extends ASTNode {
|
|
9
|
+
constructor(
|
|
10
|
+
public value: any,
|
|
11
|
+
location: SourceLocation,
|
|
12
|
+
) {
|
|
13
|
+
super('ComplexValue', location);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
public toJSON(): any {
|
|
17
|
+
return {
|
|
18
|
+
type: this.type,
|
|
19
|
+
value: this.value,
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { SourceLocation } from '../../lexer/DSLToken';
|
|
2
|
+
import { ASTNode } from './ASTNode';
|
|
3
|
+
import { ParameterDeclNode } from './ParameterDeclNode';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Event declaration node
|
|
7
|
+
* Example:
|
|
8
|
+
* output
|
|
9
|
+
* result AS ARRAY OF INTEGER
|
|
10
|
+
*/
|
|
11
|
+
export class EventDeclNode extends ASTNode {
|
|
12
|
+
constructor(
|
|
13
|
+
public name: string,
|
|
14
|
+
public parameters: ParameterDeclNode[] = [],
|
|
15
|
+
location: SourceLocation,
|
|
16
|
+
) {
|
|
17
|
+
super('EventDecl', location);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
public toJSON(): any {
|
|
21
|
+
return {
|
|
22
|
+
type: this.type,
|
|
23
|
+
name: this.name,
|
|
24
|
+
parameters: this.parameters.map((p) => p.toJSON()),
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { Expression } from '../../../runtime/expression/Expression';
|
|
2
|
+
import { SourceLocation } from '../../lexer/DSLToken';
|
|
3
|
+
import { ASTNode } from './ASTNode';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Expression node - wraps KIRun Expression
|
|
7
|
+
*/
|
|
8
|
+
export class ExpressionNode extends ASTNode {
|
|
9
|
+
public parsedExpression?: Expression;
|
|
10
|
+
|
|
11
|
+
constructor(
|
|
12
|
+
public expressionText: string,
|
|
13
|
+
location: SourceLocation,
|
|
14
|
+
) {
|
|
15
|
+
super('Expression', location);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Parse the expression using KIRun Expression parser
|
|
20
|
+
*/
|
|
21
|
+
public parse(): void {
|
|
22
|
+
if (!this.parsedExpression) {
|
|
23
|
+
this.parsedExpression = new Expression(this.expressionText);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
public toJSON(): any {
|
|
28
|
+
return {
|
|
29
|
+
type: this.type,
|
|
30
|
+
expressionText: this.expressionText,
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { SourceLocation } from '../../lexer/DSLToken';
|
|
2
|
+
import { ArgumentNode } from './ArgumentNode';
|
|
3
|
+
import { ASTNode } from './ASTNode';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Function call node
|
|
7
|
+
* Example: System.Array.InsertLast(source = Context.a, element = 10)
|
|
8
|
+
*/
|
|
9
|
+
export class FunctionCallNode extends ASTNode {
|
|
10
|
+
constructor(
|
|
11
|
+
public namespace: string,
|
|
12
|
+
public name: string,
|
|
13
|
+
public argumentsMap: Map<string, ArgumentNode>,
|
|
14
|
+
location: SourceLocation,
|
|
15
|
+
) {
|
|
16
|
+
super('FunctionCall', location);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
public toJSON(): any {
|
|
20
|
+
return {
|
|
21
|
+
type: this.type,
|
|
22
|
+
namespace: this.namespace,
|
|
23
|
+
name: this.name,
|
|
24
|
+
arguments: Object.fromEntries(
|
|
25
|
+
Array.from(this.argumentsMap.entries()).map(([key, arg]) => [key, arg.toJSON()]),
|
|
26
|
+
),
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { SourceLocation } from '../../lexer/DSLToken';
|
|
2
|
+
import { ASTNode } from './ASTNode';
|
|
3
|
+
import { EventDeclNode } from './EventDeclNode';
|
|
4
|
+
import { ParameterDeclNode } from './ParameterDeclNode';
|
|
5
|
+
import { StatementNode } from './StatementNode';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Function definition node - root AST node
|
|
9
|
+
* Represents the entire function definition
|
|
10
|
+
*/
|
|
11
|
+
export class FunctionDefNode extends ASTNode {
|
|
12
|
+
constructor(
|
|
13
|
+
public name: string,
|
|
14
|
+
public namespace?: string,
|
|
15
|
+
public parameters: ParameterDeclNode[] = [],
|
|
16
|
+
public events: EventDeclNode[] = [],
|
|
17
|
+
public logic: StatementNode[] = [],
|
|
18
|
+
location?: SourceLocation,
|
|
19
|
+
) {
|
|
20
|
+
super(
|
|
21
|
+
'FunctionDefinition',
|
|
22
|
+
location ||
|
|
23
|
+
new SourceLocation(1, 1, 0, 0), // Default location if not provided
|
|
24
|
+
);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
public toJSON(): any {
|
|
28
|
+
return {
|
|
29
|
+
type: this.type,
|
|
30
|
+
name: this.name,
|
|
31
|
+
namespace: this.namespace,
|
|
32
|
+
parameters: this.parameters.map((p) => p.toJSON()),
|
|
33
|
+
events: this.events.map((e) => e.toJSON()),
|
|
34
|
+
logic: this.logic.map((s) => s.toJSON()),
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { SourceLocation } from '../../lexer/DSLToken';
|
|
2
|
+
import { ASTNode } from './ASTNode';
|
|
3
|
+
import { SchemaNode } from './SchemaNode';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Parameter declaration node
|
|
7
|
+
* Example: n AS INTEGER
|
|
8
|
+
*/
|
|
9
|
+
export class ParameterDeclNode extends ASTNode {
|
|
10
|
+
constructor(
|
|
11
|
+
public name: string,
|
|
12
|
+
public schema: SchemaNode,
|
|
13
|
+
location: SourceLocation,
|
|
14
|
+
) {
|
|
15
|
+
super('ParameterDecl', location);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
public toJSON(): any {
|
|
19
|
+
return {
|
|
20
|
+
type: this.type,
|
|
21
|
+
name: this.name,
|
|
22
|
+
schema: this.schema.toJSON(),
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { SourceLocation } from '../../lexer/DSLToken';
|
|
2
|
+
import { ASTNode } from './ASTNode';
|
|
3
|
+
import { ExpressionNode } from './ExpressionNode';
|
|
4
|
+
import { SchemaNode } from './SchemaNode';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Schema literal node - represents inline schema definitions with default values
|
|
8
|
+
* Example: (ARRAY OF INTEGER) WITH DEFAULT VALUE []
|
|
9
|
+
*/
|
|
10
|
+
export class SchemaLiteralNode extends ASTNode {
|
|
11
|
+
constructor(
|
|
12
|
+
public schema: SchemaNode,
|
|
13
|
+
public defaultValue: ExpressionNode | undefined,
|
|
14
|
+
location: SourceLocation,
|
|
15
|
+
) {
|
|
16
|
+
super('SchemaLiteral', location);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
public toJSON(): any {
|
|
20
|
+
return {
|
|
21
|
+
type: this.type,
|
|
22
|
+
schema: this.schema.toJSON(),
|
|
23
|
+
defaultValue: this.defaultValue?.toJSON(),
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { SourceLocation } from '../../lexer/DSLToken';
|
|
2
|
+
import { ASTNode } from './ASTNode';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Schema node - represents a schema specification
|
|
6
|
+
* Can be either a simple string (e.g., "INTEGER", "ARRAY OF STRING")
|
|
7
|
+
* or a complex JSON Schema object
|
|
8
|
+
*/
|
|
9
|
+
export class SchemaNode extends ASTNode {
|
|
10
|
+
constructor(
|
|
11
|
+
public schemaSpec: string | object,
|
|
12
|
+
location: SourceLocation,
|
|
13
|
+
) {
|
|
14
|
+
super('Schema', location);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
public toJSON(): any {
|
|
18
|
+
return {
|
|
19
|
+
type: this.type,
|
|
20
|
+
schemaSpec: this.schemaSpec,
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { SourceLocation } from '../../lexer/DSLToken';
|
|
2
|
+
import { ASTNode } from './ASTNode';
|
|
3
|
+
import { FunctionCallNode } from './FunctionCallNode';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Statement node - represents a single statement in the LOGIC block
|
|
7
|
+
* Example:
|
|
8
|
+
* create: System.Context.Create(name = "a") AFTER Steps.prev
|
|
9
|
+
* iteration
|
|
10
|
+
* if: System.If(condition = true)
|
|
11
|
+
*/
|
|
12
|
+
export class StatementNode extends ASTNode {
|
|
13
|
+
constructor(
|
|
14
|
+
public statementName: string,
|
|
15
|
+
public functionCall: FunctionCallNode,
|
|
16
|
+
public afterSteps: string[] = [],
|
|
17
|
+
public executeIfSteps: string[] = [],
|
|
18
|
+
public nestedBlocks: Map<string, StatementNode[]> = new Map(),
|
|
19
|
+
location: SourceLocation,
|
|
20
|
+
public comment: string = '',
|
|
21
|
+
) {
|
|
22
|
+
super('Statement', location);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
public toJSON(): any {
|
|
26
|
+
return {
|
|
27
|
+
type: this.type,
|
|
28
|
+
statementName: this.statementName,
|
|
29
|
+
functionCall: this.functionCall.toJSON(),
|
|
30
|
+
afterSteps: this.afterSteps,
|
|
31
|
+
executeIfSteps: this.executeIfSteps,
|
|
32
|
+
nestedBlocks: Object.fromEntries(
|
|
33
|
+
Array.from(this.nestedBlocks.entries()).map(([blockName, statements]) => [
|
|
34
|
+
blockName,
|
|
35
|
+
statements.map((s) => s.toJSON()),
|
|
36
|
+
]),
|
|
37
|
+
),
|
|
38
|
+
comment: this.comment,
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AST Node exports
|
|
3
|
+
*/
|
|
4
|
+
export { ASTNode } from './ASTNode';
|
|
5
|
+
export { ArgumentNode } from './ArgumentNode';
|
|
6
|
+
export { ComplexValueNode } from './ComplexValueNode';
|
|
7
|
+
export { EventDeclNode } from './EventDeclNode';
|
|
8
|
+
export { ExpressionNode } from './ExpressionNode';
|
|
9
|
+
export { FunctionCallNode } from './FunctionCallNode';
|
|
10
|
+
export { FunctionDefNode } from './FunctionDefNode';
|
|
11
|
+
export { ParameterDeclNode } from './ParameterDeclNode';
|
|
12
|
+
export { SchemaLiteralNode } from './SchemaLiteralNode';
|
|
13
|
+
export { SchemaNode } from './SchemaNode';
|
|
14
|
+
export { StatementNode } from './StatementNode';
|