Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update and fix Java instructions #11

Merged
merged 1 commit into from
Nov 22, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 31 additions & 11 deletions notes/java.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
# Recommendations for solving lab 2 with Java

The stub for lab 2 uses Java 21,
which admits a more readable alternative to the visitor pattern suggested in the book.
The following example code shows how you can process an object ```exp``` of the type type ```Exp```
generated by the parser defined in the stub.
The stub for lab 2 uses Java 21, which admits a more readable alternative to the visitor pattern suggested in the book. The following example code shows how you can process an object ```exp``` of the type ```Exp``` generated by the parser defined in the stub.

```java
switch(exp) {
Expand All @@ -16,37 +13,60 @@ switch(exp) {
}
```

On the right hand side of the ```->``` you can extract further information from ```e```,
for example, in the case ```EAnd e```, you can use the two operands ```e.exp_1``` and ```e.exp_2```.
On the right hand side of the ```->``` you can extract further information from ```e```, for example, in the case ```EAnd e```, you can use the two operands ```e.exp_1``` and ```e.exp_2```.

```switch```, if used like above produces a Java-expression, which means that you can use it in assignments:

```java
var typedExpression = switch(exp) { ... }
```

To define the neccessary datatypes, ```record```s are very useful.
You can define a record like this:
To define the neccessary datatypes, ```record```s are very useful. You can define a record like this:

```java
public record TypedAnd(TypedExpr e1, TypedExpr e2) {
record TypedAnd(TypedExpr e1, TypedExpr e2) {
}
```

Objects of this type can be constructed with ```new TypedAnd(e1,e2)``` where ```e1``` and ```e2``` are ```TypedExpr```s. For solving the lab, it is reasonable to define an ```interface``` ```TypedExpr``` with a method which returns the type of an expression:

```java
public interface TypedExpr {
interface TypedExpr {
Type type();
}
```

Where ```Type``` is a datatype for types that needs to be defined. With this interface, the ```TypedAnd``` from above can be turned into an implementation like this:

```java
public record TypedAnd(TypedExpr e1, TypedExpr e2) {
record TypedAnd(TypedExpr e1, TypedExpr e2) {
Type type() {
return new Type.Bool; // this is what it could look like if you implement basic types as an enum
}
}
```

To keep a good overview, you can write implentations of an interface directly into the interface as "inner classes":

```java
interface TypedExpr {
Type type();

record And(TypedExpr e1, TypedExpr e2) implements TypedExpr {
Type type() {
return new Type.Bool;
}

record Var(String name, Type type) implements TypedExpr { }
}
```

The second record `Var` shows a handy shortcut to overriding the method `type`: if the record has an attribute of the right Type and name ("`type`" in this case), it will automotically become the implementation.

You can work with a variable of type `TypedExpr` like in the example above, by using `switch` expressions. If you want to avoid the `default` case, you can use a `sealed interface` instead. To make that work, you have to declare all implementations using `permits` like this:

```java
sealed interface TypedExpr permits And, Var {
...
}
```