# Language Reference

This page contains a language reference with a complete overview of all language
syntax available in hop.

## Types

There are eight built-in types available in hop.

### Bool

The `Bool` type represents booleans.

Boolean literals are constructed via the keywords `true` and `false`.

| Operation         | Returns       |
| ----------------- | ------------- |
| `!Bool`           | `Bool`        |
| `Bool && Bool`    | `Bool`        |
| `Bool \|\| Bool`  | `Bool`        |
| `Bool != Bool`    | `Bool`        |
| `Bool == Bool`    | `Bool`        |

### Int

The `Int` type represents a 64-bit signed integer.

Integer literals are constructed by writing a literal number without
a decimal point.

| Operation         | Returns       |
| ----------------- | ------------- |
| `-Int`            | `Int`         |
| `Int + Int`       | `Int`         |
| `Int - Int`       | `Int`         |
| `Int < Int`       | `Bool`        |
| `Int > Int`       | `Bool`        |
| `Int <= Int`      | `Bool`        |
| `Int >= Int`      | `Bool`        |
| `Int == Int`      | `Bool`        |
| `Int != Int`      | `Bool`        |
| `Int.to_float()`  | `Float`       |
| `Int.to_string()` | `String`      |

### Float

The `Float` type represents a 64-bit floating point number.

Floating point literals are constructed by writing a literal number containing
a decimal point.

| Operation           | Returns       |
| ------------------- | ------------- |
| `-Float`            | `Float`       |
| `Float + Float`     | `Float`       |
| `Float - Float`     | `Float`       |
| `Float < Float`     | `Bool`        |
| `Float > Float`     | `Bool`        |
| `Float <= Float`    | `Bool`        |
| `Float >= Float`    | `Bool`        |
| `Float == Float`    | `Bool`        |
| `Float != Float`    | `Bool`        |
| `Float.to_int()`    | `Int`         |
| `Float.to_string()` | `String`      |

### String

The `String` type represents a string of characters.

String literals are constructed by writing a string using `""` as delimiters.

| Operation           | Returns       |
| ------------------- | ------------- |
| `String + String`   | `String`      |
| `String == String`  | `Bool`        |
| `String != String`  | `Bool`        |
| `String.is_empty()` | `Bool`        |

### Array

The `Array` type represents an array of a given type.

| Operation           | Returns       |
| ------------------- | ------------- |
| `Array.len()`       | `Int`         |
| `Array.is_empty()`  | `Bool`        |

### Option

The `Option` type represents a container that either holds a value or not.

| Operation           | Returns       |
| ------------------- | ------------- |
| `Option.is_some()`  | `Bool`        |
| `Option.is_none()`  | `Bool`        |

### Record

The `Record` types represent a collection of named fields.

```hop
record User {
  name: String,
}

view Main {
  <let {
    user: User = User {name: "Tobi"},
  }>
    The name of the user is {user.name}
  </let>
}
```

### Enum

The `Enum` types represent a value that can hold exactly one value
of a given set of types.

```hop
enum LaundryRoomState {
  Free,
  Occupied {
    available_at: String,
  },
}

view Main {
  <let {state: LaundryRoomState = LaundryRoomState::Free}>
    <match {state}>
      <case {LaundryRoomState::Free}>
        <p>
          The laundry room is available.
        </p>
        <button>
          Book now
        </button>
      </case>
      <case {LaundryRoomState::Occupied {available_at}}>
        <p>
          The laundry room is occupied.
        </p>
        <p>
          It becomes available at {available_at}.
        </p>
      </case>
    </match>
  </let>
}
```

## Expressions

Apart from the methods and operators available on values there is only one type of primitive expression
available in hop. The match expression.

### match

The match expression in hop is similar to the match expression in Rust and is used to destructure a value into
different cases.

The `match` expression works on the `Bool`, `Option` and `Enum` type. Support for
matching on other types is in progress.

```hop
record User {
  name: String,
  email: String,
}

enum Visibility {
  Visible,
  Hidden,
}

view Main {
  <!-- Matching on Enum -->
  <let {input: Visibility = Visibility::Visible}>
    {match input {
      Visibility::Visible => "It is visible",
      Visibility::Hidden => "It is invisible",
    }}
  </let>
  <!-- Matching on Option -->
  <let {
    current_user: Option[User] = Some(
      User {name: "Loki", email: "loki@example.com"}
    ),
  }>
    {match current_user {
      Some(User {
        name,
        email: _,
      }) => "The current user is " + name,
      None => "There is no current user",
    }}
  </let>
}

```

## Macros

### `join!`

The `join!` macro concatenates strings, adding a space between each string while filtering out empty strings.
The idiomatic use case for the macro is to split long class strings into separate strings.

```hop
view Main {
  <div class={
    join!(
      "px-2",
      "py-3",
      "border",
    )
  }>
  </div>
}
```

### `asset!`

The `asset!` macro registers an asset and returns the string for its production url.

```hop
view Main {
  <div>
    <img src={asset!("/tutorial/2012_2017.jpg")}>
  </div>
}
```

## Tags

### `<let>`

The `<let>` tag binds one or more variables to the value of the given expression.

```hop
view Main {
  <let {
    x: Int = 20,
    y: Int = 5,
    result: String = (x + y).to_string(),
  }>
    The result is {result}
  </let>
}
```

### `<match>`

The `<match>` tag is the cousin of the `match` expression. The `<match>` tag
works just like the `match` expression but can be used when the purpose of
matching is not to produce a value, but instead render different markup
depending on which case is matched.

```hop
component LoggedInContent {
  <div>
    Welcome to the area for authenticated users.
  </div>
}

component MustSignInMessage {
  <div>
    You need to sign in to view this content.
  </div>
}

view Main {
  <let {logged_in: Bool = true}>
    <match {logged_in}>
      <case {true}>
        <LoggedInContent/>
      </case>
      <case {false}>
        <MustSignInMessage/>
      </case>
    </match>
  </let>
}

```

### `<for>`

The `<for>` tag loops over the items of an array, rendering its contents once for
each item of the array.

```hop
view Main {
  <for {x in ["foo", "bar", "baz"]}>
    <div>
      {x}
    </div>
  </for>
}
```

### `<if>`

The `<if>` tag renders its contents when a given condition evaluates to `true`.
It is a shorthand for a match tag on a `Bool` with an empty `false` case.

```hop
view Main {
  <let {x: Int = 5, y: Int = 10}>
    <if {x + y == 15}>
      <div>
        the math is mathing
      </div>
    </if>
  </let>
}
```
