Skip to content

Commit f06dc82

Browse files
committed
fixed markdown notation in RAP6
1 parent 2addfdd commit f06dc82

File tree

1 file changed

+15
-9
lines changed
  • courses/RascalAmendmentProposals/RAP6

1 file changed

+15
-9
lines changed

courses/RascalAmendmentProposals/RAP6/RAP6.md

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -12,16 +12,16 @@ sidebar_position: 6
1212

1313
### Issue
1414

15-
We have received reports, and encountered ourselves, some baffling emergent behavior of the current semantics of \`import\` and \`extend\` module semantics in Rascal. We see unexpected and complex behaviors, often after long debugging sessions, where the implementation is not wrong per se, but just very hard to get. Ergo, we have to do something about the design of these two language features. It’s not comprehensible now.
15+
We have received reports, and encountered ourselves, some baffling emergent behavior of the current semantics of `import` and `extend` module semantics in Rascal. We see unexpected and complex behaviors, often after long debugging sessions, where the implementation is not wrong per se, but just very hard to get. Ergo, we have to do something about the design of these two language features. It’s not comprehensible now.
1616

1717
### Analysis
1818

1919
First the current relevant features of import and extend are listed:
2020

21-
* import X; makes the declared items (variables, functions, data-types and syntax-definitions) of the imported module “X” visible in the importing module.
21+
* `import X;` makes the declared items (variables, functions, data-types and syntax-definitions) of the imported module “X” visible in the importing module.
2222
* An “imported” module is a singleton instance, with its own module state with respect to its global variables
2323
* If more than one importer modules A and B import the same imported module X, they share the same view on the state of the imported module X.
24-
* import X; does not make the declared items of modules it imports itself visible to the importing module. Import is not transitive.
24+
* `import X;` does not make the declared items of modules it imports itself visible to the importing module. Import is not transitive.
2525
* This is like Java import also works and what our (beginner) audience expects
2626
* It helps to keep namespaces clean
2727
* It is therefore necessary for information hiding and reuse
@@ -32,7 +32,7 @@ First the current relevant features of import and extend are listed:
3232
* This behavior stems from a time when “extend” did not exist yet in Rascal. It’s a backward compatibility issue. When “extend” did not exist yet, this was the only reason why data-types, syntax definitions could be (marginally) modularly extensible. The “extend” feature was added later because this is not enough, in combination with extensible overloaded functions.
3333
* When we added extensible overloaded recursive functions over the extensible data-types it became also urgent to add “extend”.
3434

35-
* extend X; like import also makes the declared items (variables, functions, data-types and syntax-definitions) of the imported module “X” visible in the importing module.
35+
* `extend X`; like `import` also makes the declared items (variables, functions, data-types and syntax-definitions) of the imported module “X” visible in the importing module.
3636
* An “extended” module is not an instance and it does not have state.
3737
* Instead of making reference to an external module instance, all its declarations are cloned into the local scope of the extending module
3838
* This also goes for global variables. Each extended global has its own instance in the extending module.
@@ -46,15 +46,17 @@ First the current relevant features of import and extend are listed:
4646
* By effectively merging the declarations of data-types and syntax-definitions and functions into the same extending module, both recursive functions and recursive data and syntax types are now openly extensible
4747
* Recursive calls in extended modules now resolve to the bigger overloaded function rather than to the overloaded function as it was in the original scope.
4848

49-
**Observation 1:** by not shadowing names declared by imported modules, “import” merges definitions almost like “extend” does, but not completely transitively and recursively. The **semi-merge** surely generates hard-to-predict run-time behavior (why did this function not match?)
49+
50+
> **Observation 1:** by not shadowing names declared by imported modules, “import” merges definitions almost like “extend” does, but not completely transitively and recursively. The **semi-merge** surely generates hard-to-predict run-time behavior (why did this function not match?)
51+
5052

5153
* Never static errors are produced that this semi-merging is going on
5254

53-
**Observation 2:** open extensibility is for data-types (languages) and recursive functions that operate on these data-types is a distinguishing Rascal feature with a strong language-oriented flavor. It is an important (yet advanced) language feature. “Extend” does not have any information hiding feature, which is necessary for the “openness” it requires.
55+
> **Observation 2:** open extensibility is for data-types (languages) and recursive functions that operate on these data-types is a distinguishing Rascal feature with a strong language-oriented flavor. It is an important (yet advanced) language feature. “Extend” does not have any information hiding feature, which is necessary for the “openness” it requires.
5456
55-
**Observation 3:** “import” is useful for libraries of non-extensible functions and specifically for information hiding. We can not do without “import” either: larger Rascal programs would become nearly impossible to write and maintain (remember ASF+SDF which only had “extend” semantics for its “import” declarations).
57+
> **Observation 3:** “import” is useful for libraries of non-extensible functions and specifically for information hiding. We can not do without “import” either: larger Rascal programs would become nearly impossible to write and maintain (remember ASF+SDF which only had “extend” semantics for its “import” declarations).
5658
57-
**Observation 4:** the feature interactions between import and extend are gruesome.
59+
> **Observation 4:** the feature interactions between import and extend are currently "gruesome"; unpredictable, with complex consequences, and no method of debugging.
5860
5961
* With globals involved, it becomes unclear what instance we are talking about
6062
* With function merging involved it becomes unclear which overloaded alternatives are active at which level in the import/extend hierarchy
@@ -86,16 +88,19 @@ Positive consequences:
8688

8789
By affecting this change, the type checker will start producing more warnings and errors automatically. For example:
8890

91+
```rascal
8992
module A;
9093
import basic/Identifiers;
9194
9295
module B;
9396
import A;
9497
9598
syntax Exp \= Id; // error undeclared non-terminal Id (before it would get the Id from basic/Identifiers via the transitive import of A).
99+
```
96100

97101
and:
98102

103+
```rascal
99104
module A
100105
101106
data X \= x();
@@ -108,7 +113,8 @@ import A;
108113
// X shadows the X from module A:
109114
data X \= y(X x); // possible warning: X is not productive, there is no base case
110115
111-
int f(y(x())) \= 1 // undeclared constructor x on local type \`X\`
116+
int f(y(x())) \= 1 // undeclared constructor x on local type `X`
117+
```
112118

113119
Negative consequences:
114120

0 commit comments

Comments
 (0)