diff --git a/blog/2026-10-12-no-more-annotations.md b/blog/2026-10-12-no-more-annotations.md new file mode 100644 index 000000000..84510853e --- /dev/null +++ b/blog/2026-10-12-no-more-annotations.md @@ -0,0 +1,42 @@ +--- +title: Final step in replacing the annotations feature with the keyword field feature +authors: [jvinju] +--- + +Over the years we have been gradually replacing the [Annotation](/docs/Rascal/Declarations/Annotation) feature with the [Keyword field](/docs/Rascal/Declarations/AlgebraicDataType) feature. +In [release 0.43.0](/release-notes/rascal-0-43-x-release-notes) the final step has been made by replacing the semantics of annotations with a "not implemented" error message with a **quick-fix** suggestion. +This feature removal went through the following stages to make for a smooth transition: + +1. `2009-2013` only annotations implemented (syntax and semantics). +2. `2013-2019` both annotations and keyword fields implemented (syntax and semantics), but never at the same time on the same node. +3. `2019-2026` annotations simulated by keyword fields (both the syntactical features use semantics of keyword fields); `Tree@\loc` is simulated by `Tree.src`. +4. `2026-....` annotations not implemented anymore (only syntax), everything is a keyword field. `anno loc Tree@\loc` is replaced by `data Tree(loc src=|unknown:///|)` in the `ParseTree` module. + +We are now past step 4. Every use of a syntactic construct related to annotations will produce: +1. an error message by the checker. +2. a quick-fix suggestion to remove any and all uses of annotation syntax _in the current project_ and replace them by the respective keyword field feature. +3. a static error by the interpreter. + +Note that: +* If you don't fix the code, it will not run anymore and you will get static exceptions by the interpreter. +* After you have fixed the code, it may not run properly on older versions of Rascal anymore, because older versions always come with their own version of the `ParseTree` module. + +For your convenience we list the differences in syntax and semantics here: + +| Feature | Annotations | Keyword fields | Note | +| --- | --- | ---- | --- | +| declaration | `anno OfType OnType@name` | `data OnType(OfType name = Default)` | annotations do not have default expressions | +| projection | `OnExpr@name` | `OnExpr.name` | annotations throw `NoSuchAnnotation` if `name` does not exist, while keyword fields return their default. Keyword fields on `node` throw `NoSuchField` exceptions and return a value of type `value` always. | +| assignment | `OnExpr@name = Expr` | `OnExpr.name = Expr` | Assigment operators like `+=` also inherit the semantics of projection | +| update | `OnExpr[@name=Expr]` | `OnExpr[name=Expr]` | field update works the same for both features, both set the field whether or not it was there before | +| equality | `Cons[@f=1] == Cons[@f=2]` is `true` | `Cons(f=1) == Cons(f=2)` is `false` | constructor equality ignores annotations while it does not ignore keyword fields, this also holds for set elements, and map/relation keys | +| matching | `Cons[@f=1] := Cons[@f=2]` is `true` | `Cons(f=1) := Cons(f=2)` is `true` | constructor matching always ignores keyword fields and annotations | + +In stage 3, annotations took the semantics of keyword fields for _declaration_, _assignment_ and _matching_, and _equality_ while for _projection_ still the old `NoSuchAnnotation` was thrown. This is the stage you have probably been using. The hard change was between stages 2 and 3. + +The quickfix for stage 4 produces an arbitrary default for well known types, +i.e. `int age = 0`, while for more complex type an exception is thrown by the default expression. It is advised to review the defaults manually. + +Finally, the quickfix may open and rewrite a large group of files for the current project. You have to save and close each of them manually to write the result to disk. This would also be a good time to review the generated defaults. + +If you get stuck, please contact (Jurgen Vinju)[mailto:Jurgen.Vinju@cwi.nl] or (Davy Landman)[mailto:Davy.Landman@swat.engineering] for help. \ No newline at end of file diff --git a/blog/authors.yml b/blog/authors.yml index 3edf2fffa..959958f8a 100644 --- a/blog/authors.yml +++ b/blog/authors.yml @@ -1,6 +1,6 @@ jvinju: name: Jurgen Vinju - title: Senior Researcher @ CWI-SWAT, professor @ TU/E, Rascal Core Team + title: Senior Researcher @ CWI-SWAT, Rascal Core Team url: http://homepages.cwi.nl/~jurgenv image_url: /images/authors/jurgen.jpg diff --git a/courses/Rascal/Declarations/Annotation/Annotation.md b/courses/Rascal/Declarations/Annotation/Annotation.md index 557b1a1a5..f544e6bb0 100644 --- a/courses/Rascal/Declarations/Annotation/Annotation.md +++ b/courses/Rascal/Declarations/Annotation/Annotation.md @@ -4,13 +4,15 @@ keywords: - anno - attributes - decorations + - keyword field - "@" --- #### Synopsis -Declare an annotation type for nodes. This feature is deprecated; please use [keyword fields]((AlgebraicDataType)) instead. +Declare an annotation type for nodes. This feature has been removed; please use [keyword fields]((AlgebraicDataType)) instead. +See [blog](/blog/2026/10/12/no-more-annotations). #### Syntax @@ -22,35 +24,8 @@ Declare an annotation type for nodes. This feature is deprecated; please use [ke #### Description -An annotation may be associated with any node value, be it a pure node or some ((Algebraic Data Type)) derived from it. - -Annotations are intended to attach application data to values, -like adding position information or control flow information to source code or adding visualization information to a graph. - -An annotation declaration defines: - -* _AnnoType_, the type of the annotation values, -* _OnType_, the type of the values that are being annotated, -* _Name_, the name of the annotation. - - -Any value of any named type can be annotated and the type of these annotations can be declared precisely. - -The following constructs are provided for handling annotations: - -* `Val @ Anno`: is an expression that retrieves the value of annotation _Anno_ of value _Val_ (may be undefined!). - -* `Val~1~[@Anno = Val~2~]`: is an expression that sets the value of annotation _Anno_ of the value _Val~1~_ to _Val~2~_ - and returns _Val~1~_ with the new annotation value as result. - -* `Var @ Anno = Val`: is an assignment statement that sets the value of annotation _Anno_ of the value of variable _Var_ to _Val_. - #### Examples -Examples have been removed since this feature is deprecated. - #### Benefits #### Pitfalls - -* Annotations are cumbersome since they change the structure of ((Values)) without changing the semantics of the identity of a value. This is why they are deprecated. diff --git a/courses/Rascal/Errors/CompileTimeErrors/UndeclaredAnnotation/UndeclaredAnnotation.md b/courses/Rascal/Errors/CompileTimeErrors/UndeclaredAnnotation/UndeclaredAnnotation.md deleted file mode 100644 index ee864b87b..000000000 --- a/courses/Rascal/Errors/CompileTimeErrors/UndeclaredAnnotation/UndeclaredAnnotation.md +++ /dev/null @@ -1,45 +0,0 @@ ---- -title: UndeclaredAnnotation ---- - -#### Synopsis - -An annotation is used that has not been declared. - -#### Syntax - -#### Types - -#### Function - -#### Usage - -#### Description - -An [annotation]((Rascal:Declarations-Annotation)) can be used to add information to an instance of an -[algebraic data type]((Rascal:Declarations-AlgebraicDataType)). -An annotation has to declared beforehand. This error is generated when an undeclared annotation is used. - -Remedies: - -* Declare the annotation. -* Use an already declared annotation. - -#### Examples - -This is correct: -```rascal-shell -data Fruit = apple(int n) | orange(int n); -anno str Fruit @ quality; -piece = orange(13); -piece@quality = "great"; -``` -But using a wrong annotation name generates an error: -```rascal-shell,continue,error -piece@qual -``` - -#### Benefits - -#### Pitfalls - diff --git a/courses/Rascal/Errors/RunTimeErrors/RuntimeExceptions/NoSuchAnnotation/NoSuchAnnotation.md b/courses/Rascal/Errors/RunTimeErrors/RuntimeExceptions/NoSuchAnnotation/NoSuchAnnotation.md deleted file mode 100644 index a5268d892..000000000 --- a/courses/Rascal/Errors/RunTimeErrors/RuntimeExceptions/NoSuchAnnotation/NoSuchAnnotation.md +++ /dev/null @@ -1,71 +0,0 @@ ---- -title: No Such Annotation ---- - -#### Synopsis - -Annotation without a value. - -#### Types - -`data RuntimeException = NoSuchAnnotation(str label);` - -#### Usage - -`import Exception;` (only needed when `NoSuchAnnotation` is used in `catch`) - - -#### Function - -#### Usage - -#### Description - -An [annotation]((Rascal:Declarations-Annotation)) can be associated with any node value -(including any [algebraic data type]((Rascal:Declarations-AlgebraicDataType))). -This error is generated when the value of an annotation is requested but has not been defined. - -Remedies: - -* Ensure that the annotation value is properly initialized for all relevant parts of the node value. -* Use the - [isDefined]((Rascal:Boolean-IsDefined)) and - [ifDefinedElse]((Rascal:Boolean-IfDefinedElse)) operators to check whether the annotation value - is set and act accordingly. -* Catch the `NoSuchAnnotation yourself`, see [try catch]((Rascal:Statements-TryCatch)). - -#### Examples - -```rascal-shell,error -data Fruit = apple(int n) | orange(int n); -anno str Fruit @ quality; -piece = orange(13); -piece@quality; -``` -Use the unary postfix operator isDefined `?` to check whether the `quality` annotation is set: -```rascal-shell,continue -piece@quality?; -``` -Use the ternary operator ifDefinedElse `?` to compute an alternative value when the `quality` annotation is not set: -```rascal-shell,continue -piece@quality ? "no quality value"; -``` -We can also catch the `NoSuchAnnotation` error. First import the Rascal exceptions (which are also included in `Prelude`) -and `IO`: -```rascal-shell,continue -import Exception; -import IO; -try piece@quality; catch NoSuchAnnotation(l): println("No such annotation: "); -``` -Finally, we can just assign a value to the `quality` annotation: -```rascal-shell,continue -piece@quality = "excellent"; -piece@quality; -``` - -#### Benefits - -#### Pitfalls - -WARNING: Using white space around the `@` confuses the Rascal parser - diff --git a/courses/Rascal/Statements/Assignment/Annotation/Annotation.md b/courses/Rascal/Statements/Assignment/Annotation/Annotation.md index 97db6bd51..05c69a4b1 100644 --- a/courses/Rascal/Statements/Assignment/Annotation/Annotation.md +++ b/courses/Rascal/Statements/Assignment/Annotation/Annotation.md @@ -8,7 +8,8 @@ keywords: #### Synopsis -Assign to an annotation. This feature is deprecated. +Assign to an annotation. This feature has been removed. +See [this blog](/blog/2026/10/12/no-more-annotations). #### Syntax @@ -20,14 +21,9 @@ Assign to an annotation. This feature is deprecated. #### Description -The value _V_ of _Assignable_ is determined and should be of a type that has an annotation _Name_. -A new value _V_' is created that is a copy of _V_ but with the value of annotation _Name_ replaced by the value of _Exp_. -_V_' is assigned to _Assignable_. -See ((Declarations-Annotation)). #### Examples -Examples have been removed since this feature is deprecated. #### Benefits diff --git a/courses/Rascal/Statements/Assignment/Assignment.md b/courses/Rascal/Statements/Assignment/Assignment.md index 6441585cd..cfd220dba 100644 --- a/courses/Rascal/Statements/Assignment/Assignment.md +++ b/courses/Rascal/Statements/Assignment/Assignment.md @@ -12,7 +12,7 @@ keywords: - "]" - "." - "?" - - "@" + - deconstructing bind --- @@ -35,7 +35,6 @@ An _Assignable_ is one of the following: * `Assignable . Name` * `< Assignable, Assignable, ..., Assignable >` * `Assignable ? Exp` -* `Assignable @ Name` * `Name ( Assignable, Assignable, ... )` #### Types diff --git a/release-notes/rascal-0-43-x-release-notes.md b/release-notes/rascal-0-43-x-release-notes.md index 910e4dd42..24faef673 100644 --- a/release-notes/rascal-0-43-x-release-notes.md +++ b/release-notes/rascal-0-43-x-release-notes.md @@ -1,7 +1,7 @@ --- authors: [sungshik] title: "Rascal 0.43.x release notes" -sidebar_position: 87 +sidebar_position: 85 --- In this post we report on the Rascal release 0.43.x @@ -23,11 +23,16 @@ The Java-air project was extracted from the Rascal standard library in version 0 * The `std` scheme to refer to locations in the standard library has been sunsetted. See the separate [blog post](/blog/2026/10/08/removed-library-schemes) for details. ([#2828](https://github.com/usethesource/rascal/pull/2828), [#2847](https://github.com/usethesource/rascal/pull/2847)) * The scheme and authority of locations are now case-insensitive (normalized to lowercase), as required by the [URI RFC](https://datatracker.ietf.org/doc/html/rfc3986). This fixes a few subtle issues when locations were used in combination with some form of RPC (HTTP/JSON/LSP) or case-sensitive file system. ([#2845](https://github.com/usethesource/rascal/pull/2845), [#2857](https://github.com/usethesource/rascal/pull/2857), [#2851](https://github.com/usethesource/rascal/pull/2851), [#2860](https://github.com/usethesource/rascal/pull/2860), [#2862](https://github.com/usethesource/rascal/pull/2862)) * Parsers (including concrete syntax pattern matchers) can now be run directly for symbols with regular operators, including `*`, `+`, and `?`, without the need to introduce dummy symbols in the grammar. ([#2809](https://github.com/usethesource/rascal/pull/2809)) -* Annotations have been removed. A Quick Fix is available in VS Code to automatically migrate all Rascal code with annotations to equivalent code without them. ([#1974](https://github.com/usethesource/rascal/pull/1974), [#2793](https://github.com/usethesource/rascal/pull/2793)) +* Annotation syntax and semantics have been removed. See [blog post](/blog/2026/10/12/no-more-annotations). A Quick Fix is available in VS Code to automatically migrate all Rascal code with annotations to equivalent code (keyword fields). ([#1974](https://github.com/usethesource/rascal/pull/1974), [#2793](https://github.com/usethesource/rascal/pull/2793)) * The Rascal language now depends on version 1.1.x of Vallang. :::info -The removal of the `std` scheme, the removal of annotation support, and the case-insensitivity of scheme/authority are low-impact breaking changes. Migration tools and Quick Fixes in the VS Code extension are provided to streamline the few code changes that might be needed. +The removal of the `std` scheme, the removal of annotation support, and the case-insensitivity of scheme/authority are low-impact breaking changes. Migration tools and Quick Fixes in the VS Code extension are provided to streamline the few code changes that might be needed. +::: + +:::info +If you have string constants in your own Java code for location schemes, changing these to all lowercase will help prevent any issues. For example, +change `String myScheme = "arrayLength";` to `String myScheme = "arraylength";`, to make sure that `myLoc.getScheme().equals(myScheme)` still works. ::: ### Maven and evaluator improvements