From ac0eb041680cb8d65dba6f9b58d9fe4e717b13e0 Mon Sep 17 00:00:00 2001 From: Georg Schwarz Date: Thu, 20 Jul 2023 15:27:56 +0200 Subject: [PATCH 01/15] Introduce concept of builtin valuetypes --- libs/interpreter-lib/src/parsing-util.ts | 17 ++-------------- libs/language-server/src/grammar/main.langium | 4 ++-- .../src/grammar/valuetype.langium | 18 ++++------------- .../wrappers/value-type/atomic-valuetype.ts | 6 +++++- .../value-type/primitive/boolean-valuetype.ts | 3 +-- .../value-type/primitive/decimal-valuetype.ts | 3 +-- .../value-type/primitive/integer-valuetype.ts | 3 +-- .../primitive/primitive-valuetypes.ts | 17 ++++++++-------- .../value-type/primitive/text-valuetype.ts | 3 +-- .../ast/wrappers/value-type/valuetype-util.ts | 20 ++++++++----------- .../lib/ast/wrappers/value-type/valuetype.ts | 9 ++------- .../jayvee-workspace-manager.ts | 14 +++++++++++++ .../lib/validation/checks/transform-body.ts | 13 ++---------- .../validation/checks/valuetype-definition.ts | 1 + .../src/stdlib/builtin-valuetypes.jv | 4 ++++ .../language-server/src/test/langium-utils.ts | 3 +++ 16 files changed, 59 insertions(+), 79 deletions(-) create mode 100644 libs/language-server/src/stdlib/builtin-valuetypes.jv diff --git a/libs/interpreter-lib/src/parsing-util.ts b/libs/interpreter-lib/src/parsing-util.ts index 8f8fb62f6..a08029a09 100644 --- a/libs/interpreter-lib/src/parsing-util.ts +++ b/libs/interpreter-lib/src/parsing-util.ts @@ -6,11 +6,9 @@ import * as fs from 'fs'; import * as path from 'path'; import { Logger } from '@jvalue/jayvee-execution'; +import { initializeWorkspace } from '@jvalue/jayvee-language-server'; import { AstNode, LangiumDocument, LangiumServices } from 'langium'; -import { - DiagnosticSeverity, - WorkspaceFolder, -} from 'vscode-languageserver-protocol'; +import { DiagnosticSeverity } from 'vscode-languageserver-protocol'; import { URI } from 'vscode-uri'; export enum ExitCode { @@ -63,17 +61,6 @@ export async function extractDocumentFromString( return await validateDocument(document, services, logger); } -/** - * Initializes the workspace with all workspace folders. - * Also loads additional required files, e.g., the standard library - */ -async function initializeWorkspace(services: LangiumServices): Promise { - const workspaceFolders: WorkspaceFolder[] = []; - await services.shared.workspace.WorkspaceManager.initializeWorkspace( - workspaceFolders, - ); -} - export async function validateDocument( document: LangiumDocument, services: LangiumServices, diff --git a/libs/language-server/src/grammar/main.langium b/libs/language-server/src/grammar/main.langium index 55d307284..79dfb50c3 100644 --- a/libs/language-server/src/grammar/main.langium +++ b/libs/language-server/src/grammar/main.langium @@ -13,7 +13,7 @@ import './transform' entry JayveeModel: ( pipelines+=PipelineDefinition - | valuetypes+=ValuetypeDefinition + | valuetypes+=(CustomValuetypeDefinition | BuiltinValuetypeDefinition) | constraints+=ConstraintDefinition | transforms+=TransformDefinition )*; @@ -23,7 +23,7 @@ PipelineDefinition: ( blocks+=BlockDefinition | pipes+=PipeDefinition - | valuetypes+=ValuetypeDefinition + | valuetypes+=CustomValuetypeDefinition | constraints+=ConstraintDefinition | transforms+=TransformDefinition )* diff --git a/libs/language-server/src/grammar/valuetype.langium b/libs/language-server/src/grammar/valuetype.langium index 06e9ee68b..050017c36 100644 --- a/libs/language-server/src/grammar/valuetype.langium +++ b/libs/language-server/src/grammar/valuetype.langium @@ -5,7 +5,10 @@ import './expression' import './terminal' -ValuetypeDefinition: +BuiltinValuetypeDefinition infers ValuetypeDefinition: + isBuiltin?='builtin' 'valuetype' name=ID ';'; + +CustomValuetypeDefinition infers ValuetypeDefinition: 'valuetype' name=ID 'oftype' type=ValuetypeReference '{' 'constraints' ':' constraints=CollectionLiteral ';' '}'; @@ -17,17 +20,4 @@ ValuetypeAssignment: name=STRING 'oftype' type=ValuetypeReference; ValuetypeReference: - (PrimitiveValuetypeKeywordLiteral | ValuetypeDefinitionReference); - -// Workaround as cross-references cannot be mixed with other types -ValuetypeDefinitionReference: reference=[ValuetypeDefinition]; - -PrimitiveValuetypeKeywordLiteral: - keyword=PrimitiveValuetypeKeyword; - -PrimitiveValuetypeKeyword returns string: - 'text' - | 'decimal' - | 'integer' - | 'boolean'; \ No newline at end of file diff --git a/libs/language-server/src/lib/ast/wrappers/value-type/atomic-valuetype.ts b/libs/language-server/src/lib/ast/wrappers/value-type/atomic-valuetype.ts index c02fab34b..7de05c0f3 100644 --- a/libs/language-server/src/lib/ast/wrappers/value-type/atomic-valuetype.ts +++ b/libs/language-server/src/lib/ast/wrappers/value-type/atomic-valuetype.ts @@ -2,6 +2,8 @@ // // SPDX-License-Identifier: AGPL-3.0-only +import { strict as assert } from 'assert'; + // eslint-disable-next-line import/no-cycle import { EvaluationContext, @@ -30,7 +32,9 @@ export class AtomicValuetype } getConstraints(context: EvaluationContext): ConstraintDefinition[] { - const constraintCollection = this.astNode.constraints; + // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition + const constraintCollection = this.astNode?.constraints; + assert(constraintCollection !== undefined); const constraintCollectionType = new CollectionValuetype( PrimitiveValuetypes.Constraint, ); diff --git a/libs/language-server/src/lib/ast/wrappers/value-type/primitive/boolean-valuetype.ts b/libs/language-server/src/lib/ast/wrappers/value-type/primitive/boolean-valuetype.ts index 391f34788..003a6938d 100644 --- a/libs/language-server/src/lib/ast/wrappers/value-type/primitive/boolean-valuetype.ts +++ b/libs/language-server/src/lib/ast/wrappers/value-type/primitive/boolean-valuetype.ts @@ -3,7 +3,6 @@ // SPDX-License-Identifier: AGPL-3.0-only import { type InternalValueRepresentation } from '../../../expressions/internal-value-representation'; -import { PrimitiveValuetypeKeyword } from '../../../generated/ast'; // eslint-disable-next-line import/no-cycle import { ValuetypeVisitor } from '../valuetype'; @@ -18,7 +17,7 @@ class BooleanValuetypeImpl extends PrimitiveValuetype { return true; } - override getName(): PrimitiveValuetypeKeyword { + override getName(): 'boolean' { return 'boolean'; } diff --git a/libs/language-server/src/lib/ast/wrappers/value-type/primitive/decimal-valuetype.ts b/libs/language-server/src/lib/ast/wrappers/value-type/primitive/decimal-valuetype.ts index 97818d91d..d8a25072b 100644 --- a/libs/language-server/src/lib/ast/wrappers/value-type/primitive/decimal-valuetype.ts +++ b/libs/language-server/src/lib/ast/wrappers/value-type/primitive/decimal-valuetype.ts @@ -3,7 +3,6 @@ // SPDX-License-Identifier: AGPL-3.0-only import { type InternalValueRepresentation } from '../../../expressions/internal-value-representation'; -import { PrimitiveValuetypeKeyword } from '../../../generated/ast'; // eslint-disable-next-line import/no-cycle import { ValuetypeVisitor } from '../valuetype'; @@ -18,7 +17,7 @@ class DecimalValuetypeImpl extends PrimitiveValuetype { return true; } - override getName(): PrimitiveValuetypeKeyword { + override getName(): 'decimal' { return 'decimal'; } diff --git a/libs/language-server/src/lib/ast/wrappers/value-type/primitive/integer-valuetype.ts b/libs/language-server/src/lib/ast/wrappers/value-type/primitive/integer-valuetype.ts index 28b32db90..49be0b94f 100644 --- a/libs/language-server/src/lib/ast/wrappers/value-type/primitive/integer-valuetype.ts +++ b/libs/language-server/src/lib/ast/wrappers/value-type/primitive/integer-valuetype.ts @@ -3,7 +3,6 @@ // SPDX-License-Identifier: AGPL-3.0-only import { type InternalValueRepresentation } from '../../../expressions/internal-value-representation'; -import { PrimitiveValuetypeKeyword } from '../../../generated/ast'; // eslint-disable-next-line import/no-cycle import { Valuetype, ValuetypeVisitor } from '../valuetype'; @@ -23,7 +22,7 @@ class IntegerValuetypeImpl extends PrimitiveValuetype { return true; } - override getName(): PrimitiveValuetypeKeyword { + override getName(): 'integer' { return 'integer'; } diff --git a/libs/language-server/src/lib/ast/wrappers/value-type/primitive/primitive-valuetypes.ts b/libs/language-server/src/lib/ast/wrappers/value-type/primitive/primitive-valuetypes.ts index 68c71c328..9925d16eb 100644 --- a/libs/language-server/src/lib/ast/wrappers/value-type/primitive/primitive-valuetypes.ts +++ b/libs/language-server/src/lib/ast/wrappers/value-type/primitive/primitive-valuetypes.ts @@ -2,9 +2,7 @@ // // SPDX-License-Identifier: AGPL-3.0-only -import { assertUnreachable } from 'langium'; - -import { PrimitiveValuetypeKeywordLiteral } from '../../../generated/ast'; +import { ValuetypeReference } from '../../../generated/ast'; // eslint-disable-next-line import/no-cycle import { Boolean, BooleanValuetype } from './boolean-valuetype'; @@ -52,16 +50,15 @@ export const PrimitiveValuetypes: { }; export function createPrimitiveValuetype( - keywordLiteral: PrimitiveValuetypeKeywordLiteral, + builtinValuetypeReference: ValuetypeReference, ): PrimitiveValuetype | undefined { // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition - const keyword = keywordLiteral?.keyword; - // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition - if (keyword === undefined) { + const name = builtinValuetypeReference?.reference?.ref?.name; + if (name === undefined) { return undefined; } - switch (keyword) { + switch (name) { case 'boolean': return Boolean; case 'decimal': @@ -71,6 +68,8 @@ export function createPrimitiveValuetype( case 'text': return Text; default: - assertUnreachable(keyword); + throw new Error( + `Found no PrimitiveValuetype for builtin valuetype "${name}"`, + ); } } diff --git a/libs/language-server/src/lib/ast/wrappers/value-type/primitive/text-valuetype.ts b/libs/language-server/src/lib/ast/wrappers/value-type/primitive/text-valuetype.ts index 3b7ef01f1..a09bc2f1d 100644 --- a/libs/language-server/src/lib/ast/wrappers/value-type/primitive/text-valuetype.ts +++ b/libs/language-server/src/lib/ast/wrappers/value-type/primitive/text-valuetype.ts @@ -3,7 +3,6 @@ // SPDX-License-Identifier: AGPL-3.0-only import { type InternalValueRepresentation } from '../../../expressions/internal-value-representation'; -import { PrimitiveValuetypeKeyword } from '../../../generated/ast'; // eslint-disable-next-line import/no-cycle import { ValuetypeVisitor } from '../valuetype'; @@ -18,7 +17,7 @@ class TextValuetypeImpl extends PrimitiveValuetype { return true; } - override getName(): PrimitiveValuetypeKeyword { + override getName(): 'text' { return 'text'; } diff --git a/libs/language-server/src/lib/ast/wrappers/value-type/valuetype-util.ts b/libs/language-server/src/lib/ast/wrappers/value-type/valuetype-util.ts index 69aa3ad1f..0796f72f4 100644 --- a/libs/language-server/src/lib/ast/wrappers/value-type/valuetype-util.ts +++ b/libs/language-server/src/lib/ast/wrappers/value-type/valuetype-util.ts @@ -7,9 +7,7 @@ import { assertUnreachable } from 'langium'; import { ValuetypeDefinition, ValuetypeReference, - isPrimitiveValuetypeKeywordLiteral, isValuetypeDefinition, - isValuetypeDefinitionReference, isValuetypeReference, } from '../../generated/ast'; @@ -28,18 +26,16 @@ export function createValuetype( if (identifier === undefined) { return undefined; } else if (isValuetypeReference(identifier)) { - if (isPrimitiveValuetypeKeywordLiteral(identifier)) { - return createPrimitiveValuetype(identifier); - } else if (isValuetypeDefinitionReference(identifier)) { - // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition - const referenced = identifier?.reference?.ref; - if (referenced === undefined) { - return undefined; - } + // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition + const valuetype = identifier?.reference?.ref; + if (valuetype === undefined) { + return undefined; + } - return new AtomicValuetype(referenced); + if (valuetype.isBuiltin) { + return createPrimitiveValuetype(identifier); } - assertUnreachable(identifier); + return new AtomicValuetype(valuetype); } else if (isValuetypeDefinition(identifier)) { return new AtomicValuetype(identifier); } diff --git a/libs/language-server/src/lib/ast/wrappers/value-type/valuetype.ts b/libs/language-server/src/lib/ast/wrappers/value-type/valuetype.ts index fc0e068d4..1872bba23 100644 --- a/libs/language-server/src/lib/ast/wrappers/value-type/valuetype.ts +++ b/libs/language-server/src/lib/ast/wrappers/value-type/valuetype.ts @@ -3,10 +3,7 @@ // SPDX-License-Identifier: AGPL-3.0-only import { type InternalValueRepresentation } from '../../expressions/internal-value-representation'; -import { - PrimitiveValuetypeKeywordLiteral, - ValuetypeDefinition, -} from '../../generated/ast'; +import { ValuetypeDefinition } from '../../generated/ast'; // eslint-disable-next-line import/no-cycle import { AtomicValuetype } from './atomic-valuetype'; @@ -24,9 +21,7 @@ import { type ValuetypeAssignmentValuetype, } from './primitive'; -export type ValuetypeAstNode = - | PrimitiveValuetypeKeywordLiteral - | ValuetypeDefinition; +export type ValuetypeAstNode = ValuetypeDefinition; export interface VisitableValuetype { acceptVisitor(visitor: ValuetypeVisitor): void; diff --git a/libs/language-server/src/lib/builtin-library/jayvee-workspace-manager.ts b/libs/language-server/src/lib/builtin-library/jayvee-workspace-manager.ts index 726b74ced..f408ccb41 100644 --- a/libs/language-server/src/lib/builtin-library/jayvee-workspace-manager.ts +++ b/libs/language-server/src/lib/builtin-library/jayvee-workspace-manager.ts @@ -6,6 +6,7 @@ import { DefaultWorkspaceManager, LangiumDocument, LangiumDocumentFactory, + LangiumServices, LangiumSharedServices, } from 'langium'; import { WorkspaceFolder } from 'vscode-languageserver'; @@ -32,3 +33,16 @@ export class JayveeWorkspaceManager extends DefaultWorkspaceManager { }); } } + +/** + * Initializes the workspace with all workspace folders. + * Also loads additional required files, e.g., the standard library + */ +export async function initializeWorkspace( + services: LangiumServices, +): Promise { + const workspaceFolders: WorkspaceFolder[] = []; + await services.shared.workspace.WorkspaceManager.initializeWorkspace( + workspaceFolders, + ); +} diff --git a/libs/language-server/src/lib/validation/checks/transform-body.ts b/libs/language-server/src/lib/validation/checks/transform-body.ts index 46b6417a3..9470ff99a 100644 --- a/libs/language-server/src/lib/validation/checks/transform-body.ts +++ b/libs/language-server/src/lib/validation/checks/transform-body.ts @@ -7,15 +7,11 @@ */ /* eslint-disable @typescript-eslint/no-unnecessary-condition */ -import { assertUnreachable } from 'langium'; - import { EvaluationContext } from '../../ast/expressions/evaluation'; import { TransformBody, TransformPortDefinition, - isPrimitiveValuetypeKeywordLiteral, isTransformPortDefinition, - isValuetypeDefinitionReference, } from '../../ast/generated/ast'; import { ValidationContext } from '../validation-context'; import { checkUniqueNames } from '../validation-util'; @@ -145,15 +141,10 @@ function checkAreInputsUsed( function isOutputPortComplete( portDefinition: TransformPortDefinition, ): boolean { - const valueType = portDefinition?.valueType; + const valueType = portDefinition?.valueType?.reference?.ref; if (valueType === undefined) { return false; } - if (isPrimitiveValuetypeKeywordLiteral(valueType)) { - return valueType?.keyword !== undefined; - } else if (isValuetypeDefinitionReference(valueType)) { - return valueType?.reference?.ref?.name !== undefined; - } - return assertUnreachable(valueType); + return valueType?.name !== undefined; } diff --git a/libs/language-server/src/lib/validation/checks/valuetype-definition.ts b/libs/language-server/src/lib/validation/checks/valuetype-definition.ts index 64f46ca76..8cceb7dc6 100644 --- a/libs/language-server/src/lib/validation/checks/valuetype-definition.ts +++ b/libs/language-server/src/lib/validation/checks/valuetype-definition.ts @@ -48,6 +48,7 @@ function checkSupertypeCycle( const hasCycle = createValuetype(valuetypeDefinition)?.hasSupertypeCycle() ?? false; if (hasCycle) { + assert(!valuetypeDefinition.isBuiltin); context.accept( 'error', 'Could not construct this valuetype since there is a cycle in the (transitive) "oftype" relation.', diff --git a/libs/language-server/src/stdlib/builtin-valuetypes.jv b/libs/language-server/src/stdlib/builtin-valuetypes.jv new file mode 100644 index 000000000..b319e2d9d --- /dev/null +++ b/libs/language-server/src/stdlib/builtin-valuetypes.jv @@ -0,0 +1,4 @@ +builtin valuetype text; +builtin valuetype decimal; +builtin valuetype integer; +builtin valuetype boolean; \ No newline at end of file diff --git a/libs/language-server/src/test/langium-utils.ts b/libs/language-server/src/test/langium-utils.ts index e14231e1d..d13aecb14 100644 --- a/libs/language-server/src/test/langium-utils.ts +++ b/libs/language-server/src/test/langium-utils.ts @@ -15,6 +15,8 @@ import { import { Diagnostic } from 'vscode-languageserver'; import { URI } from 'vscode-uri'; +import { initializeWorkspace } from '../lib/builtin-library/jayvee-workspace-manager'; + export interface ParseHelperOptions extends BuildOptions { documentUri?: string; } @@ -39,6 +41,7 @@ export function parseHelper( uri, ); services.shared.workspace.LangiumDocuments.addDocument(document); + await initializeWorkspace(services); await documentBuilder.build([document], options); return document; }; From 63bbe672df0a03d5322863620cefbd7d74d1f548 Mon Sep 17 00:00:00 2001 From: Georg Schwarz Date: Fri, 21 Jul 2023 14:35:14 +0200 Subject: [PATCH 02/15] Test valuetype name uniqueness interplay with builtin valuetypes --- .../lib/validation/checks/jayvee-model.spec.ts | 15 +++++++++++++++ ...valid-duplicate-name-with-builtin-valuetype.jv | 11 +++++++++++ 2 files changed, 26 insertions(+) create mode 100644 libs/language-server/src/test/assets/jayvee-model/invalid-duplicate-name-with-builtin-valuetype.jv diff --git a/libs/language-server/src/lib/validation/checks/jayvee-model.spec.ts b/libs/language-server/src/lib/validation/checks/jayvee-model.spec.ts index 31e0ee2d9..ff2020dd1 100644 --- a/libs/language-server/src/lib/validation/checks/jayvee-model.spec.ts +++ b/libs/language-server/src/lib/validation/checks/jayvee-model.spec.ts @@ -106,6 +106,21 @@ describe('Validation of JayveeModel', () => { ); }); + it('should diagnose error on non unique valuetypes (naming collision with builtin)', async () => { + const text = readJvTestAsset( + 'jayvee-model/invalid-duplicate-name-with-builtin-valuetype.jv', + ); + + await parseAndValidateJayveeModel(text); + + expect(validationAcceptorMock).toHaveBeenCalledTimes(2); + expect(validationAcceptorMock).toHaveBeenCalledWith( + 'error', + `The valuetypedefinition name "DuplicateValuetype" needs to be unique.`, + expect.any(Object), + ); + }); + it('should diagnose error on non unique constraints', async () => { const text = readJvTestAsset( 'jayvee-model/invalid-non-unique-constraints.jv', diff --git a/libs/language-server/src/test/assets/jayvee-model/invalid-duplicate-name-with-builtin-valuetype.jv b/libs/language-server/src/test/assets/jayvee-model/invalid-duplicate-name-with-builtin-valuetype.jv new file mode 100644 index 000000000..f062b6b92 --- /dev/null +++ b/libs/language-server/src/test/assets/jayvee-model/invalid-duplicate-name-with-builtin-valuetype.jv @@ -0,0 +1,11 @@ +// SPDX-FileCopyrightText: 2023 Friedrich-Alexander-Universitat Erlangen-Nurnberg +// +// SPDX-License-Identifier: AGPL-3.0-only + +valuetype DuplicateValuetype oftype text { + constraints: [ + Constraint, + ]; +} + +builtin valuetype DuplicateValuetype; From d26f4b8e4a77c7fde512b5bc841f95f111fe1ec3 Mon Sep 17 00:00:00 2001 From: Georg Schwarz Date: Fri, 21 Jul 2023 14:50:22 +0200 Subject: [PATCH 03/15] Tests for builtin valuetype parsing --- .../src/lib/ast/value-definition.spec.ts | 50 +++++++++++++++++++ .../invalid-missing-builtin-keyword.jv | 5 ++ .../invalid-unallowed-builtin-body.jv | 7 +++ 3 files changed, 62 insertions(+) create mode 100644 libs/language-server/src/lib/ast/value-definition.spec.ts create mode 100644 libs/language-server/src/test/assets/valuetype-definition/invalid-missing-builtin-keyword.jv create mode 100644 libs/language-server/src/test/assets/valuetype-definition/invalid-unallowed-builtin-body.jv diff --git a/libs/language-server/src/lib/ast/value-definition.spec.ts b/libs/language-server/src/lib/ast/value-definition.spec.ts new file mode 100644 index 000000000..846f488f0 --- /dev/null +++ b/libs/language-server/src/lib/ast/value-definition.spec.ts @@ -0,0 +1,50 @@ +import { AstNode, LangiumDocument } from 'langium'; +import { NodeFileSystem } from 'langium/node'; + +import { useExtension } from '..'; +import { TestLangExtension } from '../../test/extension'; +import { ParseHelperOptions, parseHelper } from '../../test/langium-utils'; +import { readJvTestAssetHelper } from '../../test/utils'; +import { createJayveeServices } from '../jayvee-module'; + +describe('Parsing of ValuetypeDefinition', () => { + let parse: ( + input: string, + options?: ParseHelperOptions, + ) => Promise>; + + const readJvTestAsset = readJvTestAssetHelper( + __dirname, + '../../test/assets/', + ); + + beforeAll(() => { + useExtension(new TestLangExtension()); + const services = createJayveeServices(NodeFileSystem).Jayvee; + parse = parseHelper(services); + }); + + it('should diagnose error on missing builtin keyword', async () => { + const text = readJvTestAsset( + 'valuetype-definition/invalid-missing-builtin-keyword.jv', + ); + + const document = await parse(text); + expect(document.parseResult.parserErrors.length).toBeGreaterThanOrEqual(1); + expect(document.parseResult.parserErrors[0]?.message).toBe( + "Expecting token of type 'oftype' but found `;`.", + ); + }); + + it('should diagnose error on unallowed body for builtin valuetypes', async () => { + const text = readJvTestAsset( + 'valuetype-definition/invalid-unallowed-builtin-body.jv', + ); + + const document = await parse(text); + expect(document.parseResult.parserErrors.length).toBeGreaterThanOrEqual(1); + expect(document.parseResult.parserErrors[0]?.message).toBe( + "Expecting token of type ';' but found `{`.", + ); + }); +}); diff --git a/libs/language-server/src/test/assets/valuetype-definition/invalid-missing-builtin-keyword.jv b/libs/language-server/src/test/assets/valuetype-definition/invalid-missing-builtin-keyword.jv new file mode 100644 index 000000000..8bf4adedd --- /dev/null +++ b/libs/language-server/src/test/assets/valuetype-definition/invalid-missing-builtin-keyword.jv @@ -0,0 +1,5 @@ +// SPDX-FileCopyrightText: 2023 Friedrich-Alexander-Universitat Erlangen-Nurnberg +// +// SPDX-License-Identifier: AGPL-3.0-only + +valuetype ValueType; diff --git a/libs/language-server/src/test/assets/valuetype-definition/invalid-unallowed-builtin-body.jv b/libs/language-server/src/test/assets/valuetype-definition/invalid-unallowed-builtin-body.jv new file mode 100644 index 000000000..708235e42 --- /dev/null +++ b/libs/language-server/src/test/assets/valuetype-definition/invalid-unallowed-builtin-body.jv @@ -0,0 +1,7 @@ +// SPDX-FileCopyrightText: 2023 Friedrich-Alexander-Universitat Erlangen-Nurnberg +// +// SPDX-License-Identifier: AGPL-3.0-only + +builtin valuetype ValueType { + constraints: []; +}; From 8b28981d600756b2dad47c2e964849afbed8b3ed Mon Sep 17 00:00:00 2001 From: Georg Schwarz Date: Fri, 21 Jul 2023 14:59:28 +0200 Subject: [PATCH 04/15] Add license header --- .../src/lib/ast/value-definition.spec.ts | 4 ++++ .../value-type/primitive/primitive-valuetypes.ts | 9 ++++++--- .../src/lib/ast/wrappers/value-type/valuetype-util.ts | 10 +++------- libs/language-server/src/stdlib/builtin-valuetypes.jv | 4 ++++ 4 files changed, 17 insertions(+), 10 deletions(-) diff --git a/libs/language-server/src/lib/ast/value-definition.spec.ts b/libs/language-server/src/lib/ast/value-definition.spec.ts index 846f488f0..14e362807 100644 --- a/libs/language-server/src/lib/ast/value-definition.spec.ts +++ b/libs/language-server/src/lib/ast/value-definition.spec.ts @@ -1,3 +1,7 @@ +// SPDX-FileCopyrightText: 2023 Friedrich-Alexander-Universitat Erlangen-Nurnberg +// +// SPDX-License-Identifier: AGPL-3.0-only + import { AstNode, LangiumDocument } from 'langium'; import { NodeFileSystem } from 'langium/node'; diff --git a/libs/language-server/src/lib/ast/wrappers/value-type/primitive/primitive-valuetypes.ts b/libs/language-server/src/lib/ast/wrappers/value-type/primitive/primitive-valuetypes.ts index 9925d16eb..0acc688e8 100644 --- a/libs/language-server/src/lib/ast/wrappers/value-type/primitive/primitive-valuetypes.ts +++ b/libs/language-server/src/lib/ast/wrappers/value-type/primitive/primitive-valuetypes.ts @@ -2,7 +2,9 @@ // // SPDX-License-Identifier: AGPL-3.0-only -import { ValuetypeReference } from '../../../generated/ast'; +import { strict as assert } from 'assert'; + +import { ValuetypeDefinition } from '../../../generated/ast'; // eslint-disable-next-line import/no-cycle import { Boolean, BooleanValuetype } from './boolean-valuetype'; @@ -50,10 +52,11 @@ export const PrimitiveValuetypes: { }; export function createPrimitiveValuetype( - builtinValuetypeReference: ValuetypeReference, + builtinValuetype: ValuetypeDefinition, ): PrimitiveValuetype | undefined { + assert(builtinValuetype.isBuiltin); + const name = builtinValuetype.name; // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition - const name = builtinValuetypeReference?.reference?.ref?.name; if (name === undefined) { return undefined; } diff --git a/libs/language-server/src/lib/ast/wrappers/value-type/valuetype-util.ts b/libs/language-server/src/lib/ast/wrappers/value-type/valuetype-util.ts index 0796f72f4..7eec7d2bc 100644 --- a/libs/language-server/src/lib/ast/wrappers/value-type/valuetype-util.ts +++ b/libs/language-server/src/lib/ast/wrappers/value-type/valuetype-util.ts @@ -28,15 +28,11 @@ export function createValuetype( } else if (isValuetypeReference(identifier)) { // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition const valuetype = identifier?.reference?.ref; - if (valuetype === undefined) { - return undefined; - } - - if (valuetype.isBuiltin) { + return createValuetype(valuetype); + } else if (isValuetypeDefinition(identifier)) { + if (identifier.isBuiltin) { return createPrimitiveValuetype(identifier); } - return new AtomicValuetype(valuetype); - } else if (isValuetypeDefinition(identifier)) { return new AtomicValuetype(identifier); } assertUnreachable(identifier); diff --git a/libs/language-server/src/stdlib/builtin-valuetypes.jv b/libs/language-server/src/stdlib/builtin-valuetypes.jv index b319e2d9d..3795e355b 100644 --- a/libs/language-server/src/stdlib/builtin-valuetypes.jv +++ b/libs/language-server/src/stdlib/builtin-valuetypes.jv @@ -1,3 +1,7 @@ +// SPDX-FileCopyrightText: 2023 Friedrich-Alexander-Universitat Erlangen-Nurnberg +// +// SPDX-License-Identifier: AGPL-3.0-only + builtin valuetype text; builtin valuetype decimal; builtin valuetype integer; From ca11c2d080367ff42adf85bf22ced4e09e064edb Mon Sep 17 00:00:00 2001 From: Georg Schwarz Date: Wed, 26 Jul 2023 16:50:23 +0200 Subject: [PATCH 05/15] Load builtin valuetypes programmatically instead of via std lib --- .../standard-library-file-system-provider.ts | 27 ++++++++++++++++++- .../value-type/primitive/boolean-valuetype.ts | 4 +++ .../value-type/primitive/decimal-valuetype.ts | 4 +++ .../value-type/primitive/integer-valuetype.ts | 4 +++ .../primitive/primitive-valuetype.ts | 7 +++++ .../value-type/primitive/text-valuetype.ts | 4 +++ .../jayvee-workspace-manager.ts | 22 +++++++++++++++ .../src/stdlib/builtin-valuetypes.jv | 8 ------ 8 files changed, 71 insertions(+), 9 deletions(-) delete mode 100644 libs/language-server/src/stdlib/builtin-valuetypes.jv diff --git a/apps/vs-code-extension/src/standard-library-file-system-provider.ts b/apps/vs-code-extension/src/standard-library-file-system-provider.ts index 91ee7b933..c711d704d 100644 --- a/apps/vs-code-extension/src/standard-library-file-system-provider.ts +++ b/apps/vs-code-extension/src/standard-library-file-system-provider.ts @@ -2,7 +2,7 @@ // // SPDX-License-Identifier: AGPL-3.0-only -import { StdLib } from '@jvalue/jayvee-language-server'; +import { PrimitiveValuetypes, StdLib } from '@jvalue/jayvee-language-server'; import { EventEmitter, ExtensionContext, @@ -23,6 +23,11 @@ export class StandardLibraryFileSystemProvider implements FileSystemProvider { onDidChangeFile = this.didChangeFile.event; constructor() { + this.registerBuiltinValuetypes(); + this.registerStdLib(); + } + + private registerStdLib() { Object.entries(StdLib).forEach(([libName, lib]) => { this.libraries.set( Uri.parse(libName).toString(), // removes slashes if missing authorities, required for matching later on @@ -31,6 +36,26 @@ export class StandardLibraryFileSystemProvider implements FileSystemProvider { }); } + private registerBuiltinValuetypes() { + const builtinValuetypeDefinitions: string[] = []; + Object.values(PrimitiveValuetypes) + .filter((v) => v.isUserExtendable()) + .forEach((valueType) => { + // TODO: filter the ones we support! + builtinValuetypeDefinitions.push( + `builtin valuetype ${valueType.getName()};`, + ); + }); + + const joinedDocument = builtinValuetypeDefinitions.join('\n'); + const libName = 'builtin:///stdlib/builtin-valuetypes.jv'; + + this.libraries.set( + Uri.parse(libName).toString(), + Buffer.from(joinedDocument), + ); + } + static register(context: ExtensionContext) { context.subscriptions.push( workspace.registerFileSystemProvider( diff --git a/libs/language-server/src/lib/ast/wrappers/value-type/primitive/boolean-valuetype.ts b/libs/language-server/src/lib/ast/wrappers/value-type/primitive/boolean-valuetype.ts index 003a6938d..1534d1605 100644 --- a/libs/language-server/src/lib/ast/wrappers/value-type/primitive/boolean-valuetype.ts +++ b/libs/language-server/src/lib/ast/wrappers/value-type/primitive/boolean-valuetype.ts @@ -26,6 +26,10 @@ class BooleanValuetypeImpl extends PrimitiveValuetype { ): operandValue is boolean { return typeof operandValue === 'boolean'; } + + override isUserExtendable() { + return true; + } } // Only export instance to enforce singleton diff --git a/libs/language-server/src/lib/ast/wrappers/value-type/primitive/decimal-valuetype.ts b/libs/language-server/src/lib/ast/wrappers/value-type/primitive/decimal-valuetype.ts index d8a25072b..69242ac10 100644 --- a/libs/language-server/src/lib/ast/wrappers/value-type/primitive/decimal-valuetype.ts +++ b/libs/language-server/src/lib/ast/wrappers/value-type/primitive/decimal-valuetype.ts @@ -26,6 +26,10 @@ class DecimalValuetypeImpl extends PrimitiveValuetype { ): operandValue is number { return typeof operandValue === 'number' && Number.isFinite(operandValue); } + + override isUserExtendable() { + return true; + } } // Only export instance to enforce singleton diff --git a/libs/language-server/src/lib/ast/wrappers/value-type/primitive/integer-valuetype.ts b/libs/language-server/src/lib/ast/wrappers/value-type/primitive/integer-valuetype.ts index 49be0b94f..1a68f18f9 100644 --- a/libs/language-server/src/lib/ast/wrappers/value-type/primitive/integer-valuetype.ts +++ b/libs/language-server/src/lib/ast/wrappers/value-type/primitive/integer-valuetype.ts @@ -31,6 +31,10 @@ class IntegerValuetypeImpl extends PrimitiveValuetype { ): operandValue is number { return typeof operandValue === 'number' && Number.isInteger(operandValue); } + + override isUserExtendable() { + return true; + } } // Only export instance to enforce singleton diff --git a/libs/language-server/src/lib/ast/wrappers/value-type/primitive/primitive-valuetype.ts b/libs/language-server/src/lib/ast/wrappers/value-type/primitive/primitive-valuetype.ts index 93da54225..0228a439b 100644 --- a/libs/language-server/src/lib/ast/wrappers/value-type/primitive/primitive-valuetype.ts +++ b/libs/language-server/src/lib/ast/wrappers/value-type/primitive/primitive-valuetype.ts @@ -24,6 +24,13 @@ export abstract class PrimitiveValuetype< protected override doGetSupertype(): undefined { return undefined; } + + /** + * Flag whether an atomic value type can be based on this primitive value type. + */ + isUserExtendable(): boolean { + return false; + } } export function isPrimitiveValuetype(v: unknown): v is PrimitiveValuetype { diff --git a/libs/language-server/src/lib/ast/wrappers/value-type/primitive/text-valuetype.ts b/libs/language-server/src/lib/ast/wrappers/value-type/primitive/text-valuetype.ts index a09bc2f1d..2ca2dd776 100644 --- a/libs/language-server/src/lib/ast/wrappers/value-type/primitive/text-valuetype.ts +++ b/libs/language-server/src/lib/ast/wrappers/value-type/primitive/text-valuetype.ts @@ -26,6 +26,10 @@ class TextValuetypeImpl extends PrimitiveValuetype { ): operandValue is string { return typeof operandValue === 'string'; } + + override isUserExtendable() { + return true; + } } // Only export instance to enforce singleton diff --git a/libs/language-server/src/lib/builtin-library/jayvee-workspace-manager.ts b/libs/language-server/src/lib/builtin-library/jayvee-workspace-manager.ts index f408ccb41..f296e2b3b 100644 --- a/libs/language-server/src/lib/builtin-library/jayvee-workspace-manager.ts +++ b/libs/language-server/src/lib/builtin-library/jayvee-workspace-manager.ts @@ -12,6 +12,8 @@ import { import { WorkspaceFolder } from 'vscode-languageserver'; import { URI } from 'vscode-uri'; +import { PrimitiveValuetypes } from '../ast'; + import { StdLib } from './generated/stdlib'; export class JayveeWorkspaceManager extends DefaultWorkspaceManager { @@ -27,11 +29,31 @@ export class JayveeWorkspaceManager extends DefaultWorkspaceManager { collector: (document: LangiumDocument) => void, ): Promise { await super.loadAdditionalDocuments(folders, collector); + this.loadBuiltinValuetypes(collector); Object.entries(StdLib).forEach(([libName, libCode]) => { collector(this.documentFactory.fromString(libCode, URI.parse(libName))); }); } + + private loadBuiltinValuetypes( + collector: (document: LangiumDocument) => void, + ) { + const builtinValuetypeDefinitions: string[] = []; + Object.values(PrimitiveValuetypes) + .filter((v) => v.isUserExtendable()) + .forEach((valueType) => { + builtinValuetypeDefinitions.push( + `builtin valuetype ${valueType.getName()};`, + ); + }); + + const joinedDocument = builtinValuetypeDefinitions.join('\n'); + const libName = 'builtin:///stdlib/builtin-valuetypes.jv'; + collector( + this.documentFactory.fromString(joinedDocument, URI.parse(libName)), + ); + } } /** diff --git a/libs/language-server/src/stdlib/builtin-valuetypes.jv b/libs/language-server/src/stdlib/builtin-valuetypes.jv deleted file mode 100644 index 3795e355b..000000000 --- a/libs/language-server/src/stdlib/builtin-valuetypes.jv +++ /dev/null @@ -1,8 +0,0 @@ -// SPDX-FileCopyrightText: 2023 Friedrich-Alexander-Universitat Erlangen-Nurnberg -// -// SPDX-License-Identifier: AGPL-3.0-only - -builtin valuetype text; -builtin valuetype decimal; -builtin valuetype integer; -builtin valuetype boolean; \ No newline at end of file From 2a6f1e081784110b2b35260c79514d8515b5354d Mon Sep 17 00:00:00 2001 From: Georg Schwarz Date: Wed, 26 Jul 2023 17:04:19 +0200 Subject: [PATCH 06/15] Pull out StdLib generation --- .../standard-library-file-system-provider.ts | 23 +----------------- .../primitive/primitive-valuetypes.ts | 7 ++++++ .../src/lib/builtin-library/index.ts | 2 +- .../jayvee-workspace-manager.ts | 24 +------------------ .../src/lib/builtin-library/stdlib.ts | 5 ++++ 5 files changed, 15 insertions(+), 46 deletions(-) create mode 100644 libs/language-server/src/lib/builtin-library/stdlib.ts diff --git a/apps/vs-code-extension/src/standard-library-file-system-provider.ts b/apps/vs-code-extension/src/standard-library-file-system-provider.ts index c711d704d..1b9c29b69 100644 --- a/apps/vs-code-extension/src/standard-library-file-system-provider.ts +++ b/apps/vs-code-extension/src/standard-library-file-system-provider.ts @@ -2,7 +2,7 @@ // // SPDX-License-Identifier: AGPL-3.0-only -import { PrimitiveValuetypes, StdLib } from '@jvalue/jayvee-language-server'; +import { StdLib } from '@jvalue/jayvee-language-server'; import { EventEmitter, ExtensionContext, @@ -23,7 +23,6 @@ export class StandardLibraryFileSystemProvider implements FileSystemProvider { onDidChangeFile = this.didChangeFile.event; constructor() { - this.registerBuiltinValuetypes(); this.registerStdLib(); } @@ -36,26 +35,6 @@ export class StandardLibraryFileSystemProvider implements FileSystemProvider { }); } - private registerBuiltinValuetypes() { - const builtinValuetypeDefinitions: string[] = []; - Object.values(PrimitiveValuetypes) - .filter((v) => v.isUserExtendable()) - .forEach((valueType) => { - // TODO: filter the ones we support! - builtinValuetypeDefinitions.push( - `builtin valuetype ${valueType.getName()};`, - ); - }); - - const joinedDocument = builtinValuetypeDefinitions.join('\n'); - const libName = 'builtin:///stdlib/builtin-valuetypes.jv'; - - this.libraries.set( - Uri.parse(libName).toString(), - Buffer.from(joinedDocument), - ); - } - static register(context: ExtensionContext) { context.subscriptions.push( workspace.registerFileSystemProvider( diff --git a/libs/language-server/src/lib/ast/wrappers/value-type/primitive/primitive-valuetypes.ts b/libs/language-server/src/lib/ast/wrappers/value-type/primitive/primitive-valuetypes.ts index 0acc688e8..0a7f4ffb5 100644 --- a/libs/language-server/src/lib/ast/wrappers/value-type/primitive/primitive-valuetypes.ts +++ b/libs/language-server/src/lib/ast/wrappers/value-type/primitive/primitive-valuetypes.ts @@ -51,6 +51,13 @@ export const PrimitiveValuetypes: { Transform: Transform, }; +export const BuiltinValuetypesLib = { + 'builtin:///stdlib/builtin-valuetypes.jv': Object.values(PrimitiveValuetypes) + .filter((v) => v.isUserExtendable()) + .map((valueType) => `builtin valuetype ${valueType.getName()};`) + .join('\n'), +}; + export function createPrimitiveValuetype( builtinValuetype: ValuetypeDefinition, ): PrimitiveValuetype | undefined { diff --git a/libs/language-server/src/lib/builtin-library/index.ts b/libs/language-server/src/lib/builtin-library/index.ts index 29c31493c..d2b2d8907 100644 --- a/libs/language-server/src/lib/builtin-library/index.ts +++ b/libs/language-server/src/lib/builtin-library/index.ts @@ -2,5 +2,5 @@ // // SPDX-License-Identifier: AGPL-3.0-only +export { StdLib } from './stdlib'; export * from './jayvee-workspace-manager'; -export { StdLib } from './generated/stdlib'; diff --git a/libs/language-server/src/lib/builtin-library/jayvee-workspace-manager.ts b/libs/language-server/src/lib/builtin-library/jayvee-workspace-manager.ts index f296e2b3b..8bcadaf6f 100644 --- a/libs/language-server/src/lib/builtin-library/jayvee-workspace-manager.ts +++ b/libs/language-server/src/lib/builtin-library/jayvee-workspace-manager.ts @@ -12,9 +12,7 @@ import { import { WorkspaceFolder } from 'vscode-languageserver'; import { URI } from 'vscode-uri'; -import { PrimitiveValuetypes } from '../ast'; - -import { StdLib } from './generated/stdlib'; +import { StdLib } from './stdlib'; export class JayveeWorkspaceManager extends DefaultWorkspaceManager { private documentFactory: LangiumDocumentFactory; @@ -29,31 +27,11 @@ export class JayveeWorkspaceManager extends DefaultWorkspaceManager { collector: (document: LangiumDocument) => void, ): Promise { await super.loadAdditionalDocuments(folders, collector); - this.loadBuiltinValuetypes(collector); Object.entries(StdLib).forEach(([libName, libCode]) => { collector(this.documentFactory.fromString(libCode, URI.parse(libName))); }); } - - private loadBuiltinValuetypes( - collector: (document: LangiumDocument) => void, - ) { - const builtinValuetypeDefinitions: string[] = []; - Object.values(PrimitiveValuetypes) - .filter((v) => v.isUserExtendable()) - .forEach((valueType) => { - builtinValuetypeDefinitions.push( - `builtin valuetype ${valueType.getName()};`, - ); - }); - - const joinedDocument = builtinValuetypeDefinitions.join('\n'); - const libName = 'builtin:///stdlib/builtin-valuetypes.jv'; - collector( - this.documentFactory.fromString(joinedDocument, URI.parse(libName)), - ); - } } /** diff --git a/libs/language-server/src/lib/builtin-library/stdlib.ts b/libs/language-server/src/lib/builtin-library/stdlib.ts new file mode 100644 index 000000000..5cea679d5 --- /dev/null +++ b/libs/language-server/src/lib/builtin-library/stdlib.ts @@ -0,0 +1,5 @@ +import { BuiltinValuetypesLib } from '../ast/wrappers/value-type/primitive/primitive-valuetypes'; + +import { StdLib as PartialStdLib } from './generated/stdlib'; + +export const StdLib = { ...PartialStdLib, ...BuiltinValuetypesLib }; From 0f82280757d203611c5d895618a9d1b2992d3e7e Mon Sep 17 00:00:00 2001 From: Georg Schwarz Date: Wed, 26 Jul 2023 17:07:48 +0200 Subject: [PATCH 07/15] Avoid name collision "StdLib" --- .../value-type/primitive/primitive-valuetypes.ts | 7 ------- .../language-server/src/lib/builtin-library/stdlib.ts | 11 +++++++++-- tools/scripts/language-server/generate-stdlib.mjs | 4 ++-- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/libs/language-server/src/lib/ast/wrappers/value-type/primitive/primitive-valuetypes.ts b/libs/language-server/src/lib/ast/wrappers/value-type/primitive/primitive-valuetypes.ts index 0a7f4ffb5..0acc688e8 100644 --- a/libs/language-server/src/lib/ast/wrappers/value-type/primitive/primitive-valuetypes.ts +++ b/libs/language-server/src/lib/ast/wrappers/value-type/primitive/primitive-valuetypes.ts @@ -51,13 +51,6 @@ export const PrimitiveValuetypes: { Transform: Transform, }; -export const BuiltinValuetypesLib = { - 'builtin:///stdlib/builtin-valuetypes.jv': Object.values(PrimitiveValuetypes) - .filter((v) => v.isUserExtendable()) - .map((valueType) => `builtin valuetype ${valueType.getName()};`) - .join('\n'), -}; - export function createPrimitiveValuetype( builtinValuetype: ValuetypeDefinition, ): PrimitiveValuetype | undefined { diff --git a/libs/language-server/src/lib/builtin-library/stdlib.ts b/libs/language-server/src/lib/builtin-library/stdlib.ts index 5cea679d5..fb59ec844 100644 --- a/libs/language-server/src/lib/builtin-library/stdlib.ts +++ b/libs/language-server/src/lib/builtin-library/stdlib.ts @@ -1,5 +1,12 @@ -import { BuiltinValuetypesLib } from '../ast/wrappers/value-type/primitive/primitive-valuetypes'; +import { PrimitiveValuetypes } from '../ast/wrappers/value-type/primitive/primitive-valuetypes'; -import { StdLib as PartialStdLib } from './generated/stdlib'; +import { PartialStdLib } from './generated/partial-stdlib'; + +export const BuiltinValuetypesLib = { + 'builtin:///stdlib/builtin-valuetypes.jv': Object.values(PrimitiveValuetypes) + .filter((v) => v.isUserExtendable()) + .map((valueType) => `builtin valuetype ${valueType.getName()};`) + .join('\n'), +}; export const StdLib = { ...PartialStdLib, ...BuiltinValuetypesLib }; diff --git a/tools/scripts/language-server/generate-stdlib.mjs b/tools/scripts/language-server/generate-stdlib.mjs index 28754ccfe..5f4035809 100644 --- a/tools/scripts/language-server/generate-stdlib.mjs +++ b/tools/scripts/language-server/generate-stdlib.mjs @@ -10,7 +10,7 @@ import { join } from "path"; const projectName = 'language-server'; const stdLibInputPath = 'stdlib'; const outputDirPath = join('lib', 'builtin-library', 'generated'); -const outputFilePath = join(outputDirPath, 'stdlib.ts'); +const outputFilePath = join(outputDirPath, 'partial-stdlib.ts'); // Executing this script: node path/to/generate-stdlib.mjs console.log('Generating stdlib...'); @@ -33,7 +33,7 @@ const stdlibOutput = `/********************************************************* * DO NOT EDIT MANUALLY! ******************************************************************************/ -` + 'export const StdLib = ' + JSON.stringify(libsRecord, null, 2) + ';\n'; +` + 'export const PartialStdLib = ' + JSON.stringify(libsRecord, null, 2) + ';\n'; if (!existsSync(outputDirPath)) { mkdirSync(outputDirPath, {recursive: true}); } From 66495a02c59202efb4b18a8086fe6739ea5b3a63 Mon Sep 17 00:00:00 2001 From: Georg Schwarz Date: Wed, 26 Jul 2023 17:29:04 +0200 Subject: [PATCH 08/15] Generate comments in user extendable value types --- .../wrappers/value-type/primitive/boolean-valuetype.ts | 7 +++++++ .../wrappers/value-type/primitive/decimal-valuetype.ts | 7 +++++++ .../wrappers/value-type/primitive/integer-valuetype.ts | 7 +++++++ .../value-type/primitive/primitive-valuetype.ts | 9 +++++++++ .../wrappers/value-type/primitive/text-valuetype.ts | 7 +++++++ libs/language-server/src/lib/builtin-library/stdlib.ts | 10 ++++++++-- 6 files changed, 45 insertions(+), 2 deletions(-) diff --git a/libs/language-server/src/lib/ast/wrappers/value-type/primitive/boolean-valuetype.ts b/libs/language-server/src/lib/ast/wrappers/value-type/primitive/boolean-valuetype.ts index 1534d1605..9e8c6641c 100644 --- a/libs/language-server/src/lib/ast/wrappers/value-type/primitive/boolean-valuetype.ts +++ b/libs/language-server/src/lib/ast/wrappers/value-type/primitive/boolean-valuetype.ts @@ -30,6 +30,13 @@ class BooleanValuetypeImpl extends PrimitiveValuetype { override isUserExtendable() { return true; } + + override getUserDoc(): string { + return ` +A boolean value. +Examples: true, false +`.trimStart(); + } } // Only export instance to enforce singleton diff --git a/libs/language-server/src/lib/ast/wrappers/value-type/primitive/decimal-valuetype.ts b/libs/language-server/src/lib/ast/wrappers/value-type/primitive/decimal-valuetype.ts index 69242ac10..a3320c65d 100644 --- a/libs/language-server/src/lib/ast/wrappers/value-type/primitive/decimal-valuetype.ts +++ b/libs/language-server/src/lib/ast/wrappers/value-type/primitive/decimal-valuetype.ts @@ -30,6 +30,13 @@ class DecimalValuetypeImpl extends PrimitiveValuetype { override isUserExtendable() { return true; } + + override getUserDoc(): string { + return ` +A decimal value. +Example: 3.14 +`.trimStart(); + } } // Only export instance to enforce singleton diff --git a/libs/language-server/src/lib/ast/wrappers/value-type/primitive/integer-valuetype.ts b/libs/language-server/src/lib/ast/wrappers/value-type/primitive/integer-valuetype.ts index 1a68f18f9..dd92845c1 100644 --- a/libs/language-server/src/lib/ast/wrappers/value-type/primitive/integer-valuetype.ts +++ b/libs/language-server/src/lib/ast/wrappers/value-type/primitive/integer-valuetype.ts @@ -35,6 +35,13 @@ class IntegerValuetypeImpl extends PrimitiveValuetype { override isUserExtendable() { return true; } + + override getUserDoc(): string { + return ` +An integer value. +Example: 3 +`.trimStart(); + } } // Only export instance to enforce singleton diff --git a/libs/language-server/src/lib/ast/wrappers/value-type/primitive/primitive-valuetype.ts b/libs/language-server/src/lib/ast/wrappers/value-type/primitive/primitive-valuetype.ts index 0228a439b..d309951e3 100644 --- a/libs/language-server/src/lib/ast/wrappers/value-type/primitive/primitive-valuetype.ts +++ b/libs/language-server/src/lib/ast/wrappers/value-type/primitive/primitive-valuetype.ts @@ -31,6 +31,15 @@ export abstract class PrimitiveValuetype< isUserExtendable(): boolean { return false; } + + /** + * The user documentation for the value type. + * Text only, no comment characters. + * Should be given for all user extendable value types @see isUserExtendable + */ + getUserDoc(): string | undefined { + return undefined; + } } export function isPrimitiveValuetype(v: unknown): v is PrimitiveValuetype { diff --git a/libs/language-server/src/lib/ast/wrappers/value-type/primitive/text-valuetype.ts b/libs/language-server/src/lib/ast/wrappers/value-type/primitive/text-valuetype.ts index 2ca2dd776..7fe7e0f17 100644 --- a/libs/language-server/src/lib/ast/wrappers/value-type/primitive/text-valuetype.ts +++ b/libs/language-server/src/lib/ast/wrappers/value-type/primitive/text-valuetype.ts @@ -30,6 +30,13 @@ class TextValuetypeImpl extends PrimitiveValuetype { override isUserExtendable() { return true; } + + override getUserDoc(): string { + return ` +A text value. +Example: "Hello World" +`.trimStart(); + } } // Only export instance to enforce singleton diff --git a/libs/language-server/src/lib/builtin-library/stdlib.ts b/libs/language-server/src/lib/builtin-library/stdlib.ts index fb59ec844..982a63287 100644 --- a/libs/language-server/src/lib/builtin-library/stdlib.ts +++ b/libs/language-server/src/lib/builtin-library/stdlib.ts @@ -5,8 +5,14 @@ import { PartialStdLib } from './generated/partial-stdlib'; export const BuiltinValuetypesLib = { 'builtin:///stdlib/builtin-valuetypes.jv': Object.values(PrimitiveValuetypes) .filter((v) => v.isUserExtendable()) - .map((valueType) => `builtin valuetype ${valueType.getName()};`) - .join('\n'), + .map( + (valueType) => + `${(valueType.getUserDoc()?.trim().split('\n') ?? []) + .map((t) => '// ' + t) + .join('\n')} +builtin valuetype ${valueType.getName()};`, + ) + .join('\n\n'), }; export const StdLib = { ...PartialStdLib, ...BuiltinValuetypesLib }; From bba5cc8847a81272255443e272fbb35ce5f0519a Mon Sep 17 00:00:00 2001 From: Philip Heltweg Date: Wed, 26 Jul 2023 17:32:30 +0200 Subject: [PATCH 09/15] Fixed REUSE Compliance Check --- libs/language-server/src/lib/builtin-library/stdlib.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libs/language-server/src/lib/builtin-library/stdlib.ts b/libs/language-server/src/lib/builtin-library/stdlib.ts index 982a63287..473ec1186 100644 --- a/libs/language-server/src/lib/builtin-library/stdlib.ts +++ b/libs/language-server/src/lib/builtin-library/stdlib.ts @@ -1,3 +1,7 @@ +// SPDX-FileCopyrightText: 2023 Friedrich-Alexander-Universitat Erlangen-Nurnberg +// +// SPDX-License-Identifier: AGPL-3.0-only + import { PrimitiveValuetypes } from '../ast/wrappers/value-type/primitive/primitive-valuetypes'; import { PartialStdLib } from './generated/partial-stdlib'; From 8cf2b47ca717aff867a099854aea429553891f6e Mon Sep 17 00:00:00 2001 From: Philip Heltweg Date: Wed, 26 Jul 2023 18:37:48 +0200 Subject: [PATCH 10/15] Autogenerate documentation for built-in valuetypes --- apps/docs/docs/user/.gitignore | 1 + apps/docs/docs/user/core-concepts.md | 3 +- apps/docs/docs/user/expressions.md | 2 +- apps/docs/generator/src/main.ts | 15 +++++ apps/docs/generator/src/user-doc-generator.ts | 60 ++++++++++++++++++- .../src/lib/docs/jayvee-doc-generator.ts | 5 ++ 6 files changed, 82 insertions(+), 4 deletions(-) create mode 100644 apps/docs/docs/user/.gitignore diff --git a/apps/docs/docs/user/.gitignore b/apps/docs/docs/user/.gitignore new file mode 100644 index 000000000..0baf894f1 --- /dev/null +++ b/apps/docs/docs/user/.gitignore @@ -0,0 +1 @@ +builtin-valuetypes.md \ No newline at end of file diff --git a/apps/docs/docs/user/core-concepts.md b/apps/docs/docs/user/core-concepts.md index 69b0486a2..a104b8ac7 100644 --- a/apps/docs/docs/user/core-concepts.md +++ b/apps/docs/docs/user/core-concepts.md @@ -81,8 +81,7 @@ In the example above, the `url` property of type `text` is defined by the corres A `ValueType` is the definition of a data type of the processed data. Some `Blocks` use `ValueTypes` to define logic (like filtering or assessing the data type in a data sink). We differentiate the following types of `ValueTypes`: -- `Built-in ValueTypes` come with the basic version of Jayvee. - Currently `text`, `decimal`, `integer`, and `boolean` are supported. +- `Built-in ValueTypes` come with the basic version of Jayvee. See [Built-in Valuetypes](./builtin-valuetypes). - `Primitive ValueTypes` can be defined by the user to model domain-specific data types and represent a single value. `Constraints` can be added to a `Primitive ValueType` (see [below](#constraints)). - `Compound ValueTypes`: UPCOMING. diff --git a/apps/docs/docs/user/expressions.md b/apps/docs/docs/user/expressions.md index 57f13573b..250e3294f 100644 --- a/apps/docs/docs/user/expressions.md +++ b/apps/docs/docs/user/expressions.md @@ -9,7 +9,7 @@ Expressions in Jayvee are arbitrarily nested statements. They consist of: - variables (e.g., declared by `from` properties in [Transforms](./transforms.md)) - operators (e.g., `*` or `sqrt`) -Expressions get evaluated at runtime by the interpreter to a [Built-in ValueType](./core-concepts.md#valuetypes). +Expressions get evaluated at runtime by the interpreter to a [Built-in ValueType](./builtin-valuetypes). ### Example diff --git a/apps/docs/generator/src/main.ts b/apps/docs/generator/src/main.ts index b83837adf..fb81e33bc 100644 --- a/apps/docs/generator/src/main.ts +++ b/apps/docs/generator/src/main.ts @@ -7,6 +7,7 @@ import { join } from 'path'; import { StdLangExtension } from '@jvalue/jayvee-extensions/std/lang'; import { + PrimitiveValuetypes, getRegisteredBlockMetaInformation, getRegisteredConstraintMetaInformation, registerConstraints, @@ -21,6 +22,7 @@ function main(): void { const rootPath = join(__dirname, '..', '..', '..', '..'); generateBlockTypeDocs(rootPath); generateConstraintTypeDocs(rootPath); + generateValueTypeDocs(rootPath); } function generateBlockTypeDocs(rootPath: string): void { @@ -69,4 +71,17 @@ function generateConstraintTypeDocs(rootPath: string): void { } } +function generateValueTypeDocs(rootPath: string): void { + const docsPath = join(rootPath, 'apps', 'docs', 'docs', 'user'); + const userDocBuilder = new UserDocGenerator(); + const valueTypeDoc = + userDocBuilder.generateValueTypesDoc(PrimitiveValuetypes); + + const fileName = `builtin-valuetypes.md`; + writeFileSync(join(docsPath, fileName), valueTypeDoc, { + flag: 'w', + }); + console.info(`Generated file ${fileName}`); +} + main(); diff --git a/apps/docs/generator/src/user-doc-generator.ts b/apps/docs/generator/src/user-doc-generator.ts index 4269abe58..3a1c6cff4 100644 --- a/apps/docs/generator/src/user-doc-generator.ts +++ b/apps/docs/generator/src/user-doc-generator.ts @@ -9,13 +9,66 @@ import { IOType, JayveeBlockTypeDocGenerator, JayveeConstraintTypeDocGenerator, + JayveeValueTypesDocGenerator, MarkdownBuilder, + PrimitiveValuetype, PropertySpecification, } from '@jvalue/jayvee-language-server'; +import { strict as assert } from 'assert'; export class UserDocGenerator - implements JayveeBlockTypeDocGenerator, JayveeConstraintTypeDocGenerator + implements + JayveeBlockTypeDocGenerator, + JayveeConstraintTypeDocGenerator, + JayveeValueTypesDocGenerator { + generateValueTypesDoc(valueTypes: { + [name: string]: PrimitiveValuetype; + }): string { + const builder = new UserDocMarkdownBuilder() + .docTitle('Built-in Valuetypes') + .generationComment() + .description( + ` +For an intro to valuetypes, see the [Core Concepts](./core-concepts). +Built-in valuetypes come with the basic version of Jayvee. +They are the basis for more restricted \`Primitive Valuetypes\` +that fullfil [Constrains](./core-concepts#constraints).`.trim(), + 1, + ) + .heading('Available built-in valuetypes', 1); + + Object.entries(valueTypes) + .filter(([_, valueType]) => valueType.isUserExtendable()) + .forEach(([name, valueType]) => { + assert( + valueType.getUserDoc(), + `Documentation is missing for user extendable value type: ${valueType.getName()}`, + ); + builder + .heading(name, 2) + .description(valueType.getUserDoc() ?? '', 3) + .examples( + [ + { + code: ` +block ExampleTableInterpreter oftype TableInterpreter { + header: true; + columns: [ + "columnName" oftype ${valueType.getName()} + ]; +}`.trim(), + description: `A block of type \`TableInterpreter\` that + interprets data in the column \`columnName\` as \`${valueType.getName()}\`. + `.trim(), + }, + ], + 3, + ); + }); + + return builder.build(); + } generateBlockTypeDoc(metaInf: BlockMetaInformation): string { const builder = new UserDocMarkdownBuilder() .docTitle(metaInf.type) @@ -84,6 +137,11 @@ class UserDocMarkdownBuilder { return this; } + heading(heading: string, depth = 1): UserDocMarkdownBuilder { + this.markdownBuilder.heading(heading, depth); + return this; + } + propertyHeading(propertyName: string, depth = 1): UserDocMarkdownBuilder { this.markdownBuilder.heading(`\`${propertyName}\``, depth); return this; diff --git a/libs/language-server/src/lib/docs/jayvee-doc-generator.ts b/libs/language-server/src/lib/docs/jayvee-doc-generator.ts index 00749fd96..8feb857dd 100644 --- a/libs/language-server/src/lib/docs/jayvee-doc-generator.ts +++ b/libs/language-server/src/lib/docs/jayvee-doc-generator.ts @@ -2,6 +2,7 @@ // // SPDX-License-Identifier: AGPL-3.0-only +import { Valuetype } from '../ast/wrappers/value-type/valuetype'; import { ConstraintMetaInformation } from '../meta-information'; import { BlockMetaInformation } from '../meta-information/block-meta-inf'; @@ -13,6 +14,10 @@ export interface JayveeConstraintTypeDocGenerator { generateConstraintTypeDoc(metaInf: ConstraintMetaInformation): string; } +export interface JayveeValueTypesDocGenerator { + generateValueTypesDoc(valueTypes: { [name: string]: Valuetype }): string; +} + export interface JayveePropertyDocGenerator { generatePropertyDoc( metaInf: BlockMetaInformation, From f08f918934f40c297f20cf0db056d0c943ed8f93 Mon Sep 17 00:00:00 2001 From: Philip Heltweg Date: Wed, 26 Jul 2023 18:40:44 +0200 Subject: [PATCH 11/15] Fixed linting errors --- apps/docs/generator/src/user-doc-generator.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/apps/docs/generator/src/user-doc-generator.ts b/apps/docs/generator/src/user-doc-generator.ts index 3a1c6cff4..bfecd24a1 100644 --- a/apps/docs/generator/src/user-doc-generator.ts +++ b/apps/docs/generator/src/user-doc-generator.ts @@ -2,6 +2,8 @@ // // SPDX-License-Identifier: AGPL-3.0-only +import { strict as assert } from 'assert'; + import { BlockMetaInformation, ConstraintMetaInformation, @@ -14,7 +16,6 @@ import { PrimitiveValuetype, PropertySpecification, } from '@jvalue/jayvee-language-server'; -import { strict as assert } from 'assert'; export class UserDocGenerator implements @@ -39,6 +40,7 @@ that fullfil [Constrains](./core-concepts#constraints).`.trim(), .heading('Available built-in valuetypes', 1); Object.entries(valueTypes) + // eslint-disable-next-line @typescript-eslint/no-unused-vars .filter(([_, valueType]) => valueType.isUserExtendable()) .forEach(([name, valueType]) => { assert( From 872e98b1e287f36611eea1d85e2c8c6e0d49ce43 Mon Sep 17 00:00:00 2001 From: Philip Heltweg Date: Wed, 26 Jul 2023 18:41:54 +0200 Subject: [PATCH 12/15] Added license identifier --- apps/docs/docs/user/.gitignore | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/apps/docs/docs/user/.gitignore b/apps/docs/docs/user/.gitignore index 0baf894f1..eb7531ecd 100644 --- a/apps/docs/docs/user/.gitignore +++ b/apps/docs/docs/user/.gitignore @@ -1 +1,5 @@ +# SPDX-FileCopyrightText: 2023 Friedrich-Alexander-Universitat Erlangen-Nurnberg +# +# SPDX-License-Identifier: AGPL-3.0-only + builtin-valuetypes.md \ No newline at end of file From e0bfd24703b07ce94b301e04c72342072ac165a8 Mon Sep 17 00:00:00 2001 From: Georg Schwarz Date: Thu, 27 Jul 2023 11:20:05 +0200 Subject: [PATCH 13/15] Use trim instead of trimStart --- .../lib/ast/wrappers/value-type/primitive/boolean-valuetype.ts | 2 +- .../lib/ast/wrappers/value-type/primitive/decimal-valuetype.ts | 2 +- .../lib/ast/wrappers/value-type/primitive/integer-valuetype.ts | 2 +- .../src/lib/ast/wrappers/value-type/primitive/text-valuetype.ts | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/libs/language-server/src/lib/ast/wrappers/value-type/primitive/boolean-valuetype.ts b/libs/language-server/src/lib/ast/wrappers/value-type/primitive/boolean-valuetype.ts index 9e8c6641c..b6fe5a840 100644 --- a/libs/language-server/src/lib/ast/wrappers/value-type/primitive/boolean-valuetype.ts +++ b/libs/language-server/src/lib/ast/wrappers/value-type/primitive/boolean-valuetype.ts @@ -35,7 +35,7 @@ class BooleanValuetypeImpl extends PrimitiveValuetype { return ` A boolean value. Examples: true, false -`.trimStart(); +`.trim(); } } diff --git a/libs/language-server/src/lib/ast/wrappers/value-type/primitive/decimal-valuetype.ts b/libs/language-server/src/lib/ast/wrappers/value-type/primitive/decimal-valuetype.ts index a3320c65d..86cd05c17 100644 --- a/libs/language-server/src/lib/ast/wrappers/value-type/primitive/decimal-valuetype.ts +++ b/libs/language-server/src/lib/ast/wrappers/value-type/primitive/decimal-valuetype.ts @@ -35,7 +35,7 @@ class DecimalValuetypeImpl extends PrimitiveValuetype { return ` A decimal value. Example: 3.14 -`.trimStart(); +`.trim(); } } diff --git a/libs/language-server/src/lib/ast/wrappers/value-type/primitive/integer-valuetype.ts b/libs/language-server/src/lib/ast/wrappers/value-type/primitive/integer-valuetype.ts index dd92845c1..d4f94a0b9 100644 --- a/libs/language-server/src/lib/ast/wrappers/value-type/primitive/integer-valuetype.ts +++ b/libs/language-server/src/lib/ast/wrappers/value-type/primitive/integer-valuetype.ts @@ -40,7 +40,7 @@ class IntegerValuetypeImpl extends PrimitiveValuetype { return ` An integer value. Example: 3 -`.trimStart(); +`.trim(); } } diff --git a/libs/language-server/src/lib/ast/wrappers/value-type/primitive/text-valuetype.ts b/libs/language-server/src/lib/ast/wrappers/value-type/primitive/text-valuetype.ts index 7fe7e0f17..e0f80cc10 100644 --- a/libs/language-server/src/lib/ast/wrappers/value-type/primitive/text-valuetype.ts +++ b/libs/language-server/src/lib/ast/wrappers/value-type/primitive/text-valuetype.ts @@ -35,7 +35,7 @@ class TextValuetypeImpl extends PrimitiveValuetype { return ` A text value. Example: "Hello World" -`.trimStart(); +`.trim(); } } From 07bb669e4b34fd1d12bfb051424c0e4e5a95cd1b Mon Sep 17 00:00:00 2001 From: Georg Schwarz Date: Thu, 27 Jul 2023 11:20:18 +0200 Subject: [PATCH 14/15] Fix typo in valuetype doc generation --- apps/docs/generator/src/user-doc-generator.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/docs/generator/src/user-doc-generator.ts b/apps/docs/generator/src/user-doc-generator.ts index bfecd24a1..2e54cec18 100644 --- a/apps/docs/generator/src/user-doc-generator.ts +++ b/apps/docs/generator/src/user-doc-generator.ts @@ -31,10 +31,10 @@ export class UserDocGenerator .generationComment() .description( ` -For an intro to valuetypes, see the [Core Concepts](./core-concepts). +For an introduction to valuetypes, see the [Core Concepts](./core-concepts). Built-in valuetypes come with the basic version of Jayvee. They are the basis for more restricted \`Primitive Valuetypes\` -that fullfil [Constrains](./core-concepts#constraints).`.trim(), +that fullfil [Constraints](./core-concepts#constraints).`.trim(), 1, ) .heading('Available built-in valuetypes', 1); From eb77b8240f46ce489a7091e4d36fb2c953b1238d Mon Sep 17 00:00:00 2001 From: Georg Schwarz Date: Thu, 27 Jul 2023 11:46:18 +0200 Subject: [PATCH 15/15] Move valuetype doc into own category --- apps/docs/docs/user/.gitignore | 2 - .../user/constraint-types/_category_.json | 2 +- apps/docs/docs/user/core-concepts.md | 54 +++++-------------- apps/docs/docs/user/expressions.md | 4 +- apps/docs/docs/user/runtime-parameters.md | 2 +- apps/docs/docs/user/transforms.md | 2 +- apps/docs/docs/user/valuetypes/.gitignore | 5 ++ .../docs/docs/user/valuetypes/_category_.json | 8 +++ .../user/valuetypes/_category_.json.license | 3 ++ .../user/valuetypes/primitive-valuetypes.md | 48 +++++++++++++++++ .../primitive-valuetypes.md.license | 3 ++ apps/docs/generator/src/main.ts | 2 +- apps/docs/generator/src/user-doc-generator.ts | 7 +-- 13 files changed, 91 insertions(+), 51 deletions(-) create mode 100644 apps/docs/docs/user/valuetypes/.gitignore create mode 100644 apps/docs/docs/user/valuetypes/_category_.json create mode 100644 apps/docs/docs/user/valuetypes/_category_.json.license create mode 100644 apps/docs/docs/user/valuetypes/primitive-valuetypes.md create mode 100644 apps/docs/docs/user/valuetypes/primitive-valuetypes.md.license diff --git a/apps/docs/docs/user/.gitignore b/apps/docs/docs/user/.gitignore index eb7531ecd..d1b2321da 100644 --- a/apps/docs/docs/user/.gitignore +++ b/apps/docs/docs/user/.gitignore @@ -1,5 +1,3 @@ # SPDX-FileCopyrightText: 2023 Friedrich-Alexander-Universitat Erlangen-Nurnberg # # SPDX-License-Identifier: AGPL-3.0-only - -builtin-valuetypes.md \ No newline at end of file diff --git a/apps/docs/docs/user/constraint-types/_category_.json b/apps/docs/docs/user/constraint-types/_category_.json index 9cced194c..7eecb5c68 100644 --- a/apps/docs/docs/user/constraint-types/_category_.json +++ b/apps/docs/docs/user/constraint-types/_category_.json @@ -1,6 +1,6 @@ { "label": "Constraint Types", - "position": 4, + "position": 5, "link": { "type": "generated-index", "description": "These constraints are shipped with Jayvee and are available right out of the box." diff --git a/apps/docs/docs/user/core-concepts.md b/apps/docs/docs/user/core-concepts.md index a104b8ac7..d46c48ac3 100644 --- a/apps/docs/docs/user/core-concepts.md +++ b/apps/docs/docs/user/core-concepts.md @@ -81,55 +81,29 @@ In the example above, the `url` property of type `text` is defined by the corres A `ValueType` is the definition of a data type of the processed data. Some `Blocks` use `ValueTypes` to define logic (like filtering or assessing the data type in a data sink). We differentiate the following types of `ValueTypes`: -- `Built-in ValueTypes` come with the basic version of Jayvee. See [Built-in Valuetypes](./builtin-valuetypes). +- `Built-in ValueTypes` come with the basic version of Jayvee. See [Built-in Valuetypes](./valuetypes/builtin-valuetypes). - `Primitive ValueTypes` can be defined by the user to model domain-specific data types and represent a single value. - `Constraints` can be added to a `Primitive ValueType` (see [below](#constraints)). + `Constraints` can be added to a `Primitive ValueType`. +See [Primitive Valuetypes](./valuetypes/primitive-valuetypes). - `Compound ValueTypes`: UPCOMING. -### Constraints - -`Constraints` for `ValueTypes` declare the validity criteria that each concrete value is checked against. - -#### Syntax 1: Expression syntax - -The syntax of expression-based `Constraints` uses an expression that evaluates to `true` or `false` for the given `value`. The type of the values the expression is working in is indicated ofter the keyword `on`: - ```jayvee +valuetype GasFillLevel oftype integer { + constraints: [ GasFillLevelRange ]; +} + constraint GasFillLevelRange on decimal: value >= 0 and value <= 100; ``` -Refer to the [Expression documentation](./expressions.md) for further reading on expressions. - - -#### Syntax 2: Block-like syntax - -The syntax of `Constraints` is similar to the syntax of `Blocks`. -The availability of property keys and their respective `ValueTypes` is determined by the type of the `Constraint` - indicated by the identifier after the keyword `oftype`: +## Transforms +`Transforms` are used to transform data from one `ValueType` to a different one. For more details, see [Transforms](./transforms.md). ```jayvee -constraint GasFillLevelRange oftype RangeConstraint { - lowerBound: 0; - lowerBoundInclusive: true; - upperBound: 100; - upperBoundInclusive: true; -} -``` - -Note that the type of `Constraint` also determines its applicability to `ValueTypes`. -For instance, a `RangeConstraint` can only be applied to the numerical types `integer` and `decimal`. - -### Primitive ValueTypes - -`Primitive ValueTypes` are based on `Built-in ValueTypes` and use a collection of constraints to restrict the range of valid values. -Such constraints are implicitly connected via a logical `AND` relation. -Note that the `Constraints` need to be applicable to the base-type of the `ValueType` - indicated by the identifier after the keyword `oftype`: +transform CelsiusToKelvin { + from tempCelsius oftype decimal; + to tempKelvin oftype decimal; -```jayvee -valuetype GasFillLevel oftype integer { - constraints: [ GasFillLevelRange ]; + tempKelvin: tempCelsius + 273.15; } -``` - -### Transforms -`Transforms` are used to transform data from one `ValueType` to a different one. For more details, see [Transforms](./transforms.md) \ No newline at end of file +``` \ No newline at end of file diff --git a/apps/docs/docs/user/expressions.md b/apps/docs/docs/user/expressions.md index 250e3294f..c3728c886 100644 --- a/apps/docs/docs/user/expressions.md +++ b/apps/docs/docs/user/expressions.md @@ -1,5 +1,5 @@ --- -sidebar_position: 5 +sidebar_position: 6 --- # Expressions @@ -9,7 +9,7 @@ Expressions in Jayvee are arbitrarily nested statements. They consist of: - variables (e.g., declared by `from` properties in [Transforms](./transforms.md)) - operators (e.g., `*` or `sqrt`) -Expressions get evaluated at runtime by the interpreter to a [Built-in ValueType](./builtin-valuetypes). +Expressions get evaluated at runtime by the interpreter to a [Built-in ValueType](./valuetypes/builtin-valuetypes). ### Example diff --git a/apps/docs/docs/user/runtime-parameters.md b/apps/docs/docs/user/runtime-parameters.md index ac5d8995e..4f257fac9 100644 --- a/apps/docs/docs/user/runtime-parameters.md +++ b/apps/docs/docs/user/runtime-parameters.md @@ -1,5 +1,5 @@ --- -sidebar_position: 5 +sidebar_position: 8 --- # Runtime Parameters diff --git a/apps/docs/docs/user/transforms.md b/apps/docs/docs/user/transforms.md index f232f6dbd..731ec304a 100644 --- a/apps/docs/docs/user/transforms.md +++ b/apps/docs/docs/user/transforms.md @@ -1,5 +1,5 @@ --- -sidebar_position: 4 +sidebar_position: 7 --- # Transforms diff --git a/apps/docs/docs/user/valuetypes/.gitignore b/apps/docs/docs/user/valuetypes/.gitignore new file mode 100644 index 000000000..eb7531ecd --- /dev/null +++ b/apps/docs/docs/user/valuetypes/.gitignore @@ -0,0 +1,5 @@ +# SPDX-FileCopyrightText: 2023 Friedrich-Alexander-Universitat Erlangen-Nurnberg +# +# SPDX-License-Identifier: AGPL-3.0-only + +builtin-valuetypes.md \ No newline at end of file diff --git a/apps/docs/docs/user/valuetypes/_category_.json b/apps/docs/docs/user/valuetypes/_category_.json new file mode 100644 index 000000000..d69f22af2 --- /dev/null +++ b/apps/docs/docs/user/valuetypes/_category_.json @@ -0,0 +1,8 @@ +{ + "label": "Valuetypes", + "position": 4, + "link": { + "type": "generated-index", + "description": "Jayvee supports these different kinds of valuetypes." + } +} diff --git a/apps/docs/docs/user/valuetypes/_category_.json.license b/apps/docs/docs/user/valuetypes/_category_.json.license new file mode 100644 index 000000000..17c5d2bad --- /dev/null +++ b/apps/docs/docs/user/valuetypes/_category_.json.license @@ -0,0 +1,3 @@ +SPDX-FileCopyrightText: 2023 Friedrich-Alexander-Universitat Erlangen-Nurnberg + +SPDX-License-Identifier: AGPL-3.0-only diff --git a/apps/docs/docs/user/valuetypes/primitive-valuetypes.md b/apps/docs/docs/user/valuetypes/primitive-valuetypes.md new file mode 100644 index 000000000..92400a538 --- /dev/null +++ b/apps/docs/docs/user/valuetypes/primitive-valuetypes.md @@ -0,0 +1,48 @@ +--- +sidebar_position: 2 +--- +# Primitive ValueTypes + +`Primitive ValueTypes` are based on `Built-in ValueTypes` and use a collection of constraints to restrict the range of valid values. +Such constraints are implicitly connected via a logical `AND` relation. +Note that the `Constraints` need to be applicable to the base-type of the `ValueType` - indicated by the identifier after the keyword `oftype`: + +```jayvee +valuetype GasFillLevel oftype integer { + constraints: [ GasFillLevelRange ]; +} +``` + + +## Constraints + +`Constraints` for `ValueTypes` declare the validity criteria that each concrete value is checked against. + +### Syntax 1: Expression syntax + +The syntax of expression-based `Constraints` uses an expression that evaluates to `true` or `false` for the given `value`. The type of the values the expression is working in is indicated ofter the keyword `on`: + +```jayvee +constraint GasFillLevelRange on decimal: + value >= 0 and value <= 100; +``` + +Refer to the [Expression documentation](../expressions.md) for further reading on expressions. + + +### Syntax 2: Block-like syntax + +The syntax of `Constraints` is similar to the syntax of `Blocks`. +The availability of property keys and their respective `ValueTypes` is determined by the type of the `Constraint` - indicated by the identifier after the keyword `oftype`: + +```jayvee +constraint GasFillLevelRange oftype RangeConstraint { + lowerBound: 0; + lowerBoundInclusive: true; + upperBound: 100; + upperBoundInclusive: true; +} +``` + +Note that the type of `Constraint` also determines its applicability to `ValueTypes`. +For instance, a `RangeConstraint` can only be applied to the numerical types `integer` and `decimal`. \ No newline at end of file diff --git a/apps/docs/docs/user/valuetypes/primitive-valuetypes.md.license b/apps/docs/docs/user/valuetypes/primitive-valuetypes.md.license new file mode 100644 index 000000000..17c5d2bad --- /dev/null +++ b/apps/docs/docs/user/valuetypes/primitive-valuetypes.md.license @@ -0,0 +1,3 @@ +SPDX-FileCopyrightText: 2023 Friedrich-Alexander-Universitat Erlangen-Nurnberg + +SPDX-License-Identifier: AGPL-3.0-only diff --git a/apps/docs/generator/src/main.ts b/apps/docs/generator/src/main.ts index fb81e33bc..ceeadf3b5 100644 --- a/apps/docs/generator/src/main.ts +++ b/apps/docs/generator/src/main.ts @@ -72,7 +72,7 @@ function generateConstraintTypeDocs(rootPath: string): void { } function generateValueTypeDocs(rootPath: string): void { - const docsPath = join(rootPath, 'apps', 'docs', 'docs', 'user'); + const docsPath = join(rootPath, 'apps', 'docs', 'docs', 'user', 'valuetypes'); const userDocBuilder = new UserDocGenerator(); const valueTypeDoc = userDocBuilder.generateValueTypesDoc(PrimitiveValuetypes); diff --git a/apps/docs/generator/src/user-doc-generator.ts b/apps/docs/generator/src/user-doc-generator.ts index 2e54cec18..23781d642 100644 --- a/apps/docs/generator/src/user-doc-generator.ts +++ b/apps/docs/generator/src/user-doc-generator.ts @@ -31,10 +31,10 @@ export class UserDocGenerator .generationComment() .description( ` -For an introduction to valuetypes, see the [Core Concepts](./core-concepts). +For an introduction to valuetypes, see the [Core Concepts](../core-concepts). Built-in valuetypes come with the basic version of Jayvee. -They are the basis for more restricted \`Primitive Valuetypes\` -that fullfil [Constraints](./core-concepts#constraints).`.trim(), +They are the basis for more restricted [Primitive Valuetypes](./primitive-valuetypes) +that fullfil [Constraints](./primitive-valuetypes#constraints).`.trim(), 1, ) .heading('Available built-in valuetypes', 1); @@ -71,6 +71,7 @@ block ExampleTableInterpreter oftype TableInterpreter { return builder.build(); } + generateBlockTypeDoc(metaInf: BlockMetaInformation): string { const builder = new UserDocMarkdownBuilder() .docTitle(metaInf.type)