Add docs detailing language + grammar spec#11
Conversation
There was a problem hiding this comment.
Pull request overview
Adds documentation intended to be the single source of truth for the invariants DSL’s top-level structure, expressions, and type system.
Changes:
- Documented statement forms (
spec,field,check,invariant) and their intended semantics. - Documented expression concepts including implicit identifiers and operator precedence.
- Added type-system notes plus a sample
.invfile and a (currently empty) EBNF grammar file.
Reviewed changes
Copilot reviewed 5 out of 6 changed files in this pull request and generated 6 comments.
Show a summary per file
| File | Description |
|---|---|
| docs/lang/statements.md | Defines the statement-level constructs and evaluation semantics. |
| docs/lang/expressions.md | Defines expression semantics, implicit identifiers, and operator precedence. |
| docs/lang/data_types.md | Describes supported primitive/compound types and how to constrain them. |
| docs/lang/introduction.md | Provides a high-level overview and links to the other docs. |
| docs/lang/sample.inv | Adds an example invariants program demonstrating the language. |
| docs/lang/grammar.ebnf | Intended location for formal grammar (currently empty). |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
|
||
| ## Mixed Types | ||
|
|
||
| Mixed types (ie; to define a list with many possible types) is not supported. |
There was a problem hiding this comment.
Grammar: “Mixed types ... is not supported” should be “are not supported” (plural subject).
| Mixed types (ie; to define a list with many possible types) is not supported. | |
| Mixed types (ie; to define a list with many possible types) are not supported. |
|
|
||
| ``` | ||
| invariant bulk_discount { | ||
| this.quantity > 500 -> this.total_price < (this.unit_price \* this.quantity); |
There was a problem hiding this comment.
The multiplication operator in this sample is written as \* inside a fenced code block. In a code fence this backslash is preserved, so a copy/paste would produce an invalid operator. Use * here instead.
| this.quantity > 500 -> this.total_price < (this.unit_price \* this.quantity); | |
| this.quantity > 500 -> this.total_price < (this.unit_price * this.quantity); |
| check: value <= 1000; | ||
| } | ||
|
|
||
| field currency: number { |
There was a problem hiding this comment.
currency is declared as number, but the check uses string literals ("USD", "EUR", "GBP"). This example should declare currency as string (or change the check literals to numbers) to keep the sample consistent with the type system described in data_types.md.
| field currency: number { | |
| field currency: string { |
| field quantity: integer { } | ||
|
|
There was a problem hiding this comment.
field quantity is declared twice in the same spec (once with checks, once empty). If duplicate field keys are not allowed (as implied by “maps directly to a key”), this makes the sample invalid/ambiguous. Remove the duplicate or rename it to demonstrate a different field.
| field quantity: integer { } |
|
|
||
| ## 3. Data Types | ||
|
|
||
| `invariant` aims to maintain parity with the OpenAPI 3.0 spec. As the lexer reads atomic literals (like `500` or `"USD"`), the syntax oracle maps these directly to foundational C++ types to ensure high performance during the decoding loop. This also covers how complex, recursive structures like arrays and objects are handled. |
There was a problem hiding this comment.
This section refers to the project/DSL as invariant (singular), but elsewhere in this doc and the repo name it’s invariants. For consistency and to avoid confusion in the docs, pick one and use it consistently (likely invariants).
| `invariant` aims to maintain parity with the OpenAPI 3.0 spec. As the lexer reads atomic literals (like `500` or `"USD"`), the syntax oracle maps these directly to foundational C++ types to ensure high performance during the decoding loop. This also covers how complex, recursive structures like arrays and objects are handled. | |
| `invariants` aims to maintain parity with the OpenAPI 3.0 spec. As the lexer reads atomic literals (like `500` or `"USD"`), the syntax oracle maps these directly to foundational C++ types to ensure high performance during the decoding loop. This also covers how complex, recursive structures like arrays and objects are handled. |
| `invariant` aims to maintain parity with the OpenAPI 3.0 spec. As such, the | ||
| supported types are also largely the same. The typical complexity of managing | ||
| the custom "object" type defined by the OAS 3 is largely mitigated by the entire DSL | ||
| being focused around `spec`s, which are basically just objects. This therefore | ||
| enables first-class support thereof. |
There was a problem hiding this comment.
The doc alternates between invariant and invariants when referring to the DSL (e.g., here and later in the Strings/Booleans sections). Standardize the name to avoid ambiguity in the “single source of truth” docs.
|
@copilot apply changes based on the comments in this thread |
…sistency in docs Agent-Logs-Url: https://github.com/ujaandas/invariants/sessions/2d9cbd8d-d83f-4167-9ce2-bb7ce6d2533b Co-authored-by: ujaandas <79176268+ujaandas@users.noreply.github.com>
Applied all changes from the review thread in commit
|
Fairly straightforward, just some documentation detailing the "top-level" of how the invariants language works. To be used as a single source-of-truth for implementation, which was completed on the
feat/lang/lexerbranch, which was merged recently.Some features remain TBC, such as proper typing for Array-types (ie;
Array<Boolean>), thethisandvaluekeyword, etc...