# Derw

Derw is a programming language aimed at making complex apps in a simple way. It's built on top of TypeScript and Node, so it's easy to have interop with TypeScript.&#x20;

With Derw, you can write both frontend and backend code. The easiest way to write frontend code is with Derw's [html](https://github.com/derw-lang/html) package, which is built upon a model-view-update structure.

{% hint style="info" %}
Want to stay up to date with Derw? Follow the [blog](https://derw.substack.com/) for regular updates, the [Twitter](https://twitter.com/derwlang) for smaller updates and [star the repo](https://github.com/eeue56/derw) to keep it in your list.
{% endhint %}

### What you'll find in this book

This book will walk you through creating projects, language syntax, working with existing TypeScript and Javascript codebases, and details on how the compiler works.

If you have suggested changes, feel free to open issues or pull requests [here](https://github.com/derw-lang/language-docs/)

## What does Derw look like?

```elm
sayHi: string -> string
sayHi name =
    `Hello, ${name}`
    
helloWorld: string
helloWorld =
    sayHi "world"
```

You can also check out the [examples](https://github.com/derw-lang/examples) repo for more fleshed out examples.

## What can you use Derw for?

Derw is perfect for interactive web apps,. You can also use it to write command line tooling, and servers.

## Derw's concept

Derw prioritizes practicality above all else. The language is designed to empower developers to get things done in a straightforward and intuitive manner. Derw integrates seamlessly with other programming languages to enhance the development experience. Its syntax is particularly well-suited for those familiar with functional programming.

Derw is a language that is open to new ideas and approaches. If there is something that has not been done in Derw before, the community should work towards implementing it, and if it proves to be a valuable addition, it should be incorporated into the language.

While Derw is beginner-friendly, it is also designed to cater to the needs of experienced developers. It strikes a balance between simplicity and functionality, ensuring that developers of all levels can write efficient, high-quality code with ease.

Writing code that is provably correct allows developers to spend less time fixing bugs in production, leading them to deliver better products. Derw is not the answer to everyone's wishes; there are other languages out there that provide features others want, and that's okay! Derw is happy to sit in this space. You, as a Derw developer, should expect a well tested language that moves at a quick speed, helping you to write better code - and enjoy yourself while doing so.

## What is Derw inspired by?

{% hint style="info" %}
Derw is a general purpose, functional, static, strongly-typed language. It may be both lazy and inferring at a later point.
{% endhint %}

Derw as a language is [inspired by a number of languages](https://derw.substack.com/p/a-love-of-languages?utm_source=w): Elm, Haskell, Python, Idris, TypeScript and Go.

Syntax-wise, Derw is most similar to Elm and Haskell, in that it is an [ML-family](https://en.wikipedia.org/wiki/ML_\(programming_language\)) language. The majority comes from Elm, so you'll see things like `:` being used for type definitions, `let..in` for definitions within a function or const, and type aliases rather than record types. Derw additionally adds `do..return` notation, inspired by both Haskell and Idris.&#x20;

Tooling-wise, Derw is influenced by Go, TypeScript and Elm. The Go idea of having excellent built-in tooling for formatting, testing and benchmarking has inspired Derw to provide as many of these features by default. Packages are based on a similar idea to using a git-based package.json dependency tree, but is stripped back so that there are only the basic fields needed and not extended fields like you might find in JavaScript.

Package-wise, Derw follows the Elm convention of packages always being by a particular name or organization. Names for packages should not be cute, but instead follow the convention of being named based on what they do. html should be called html, for example. One break with Elm is that due to the interop-story of Derw, it is possible to have a package.json listing dependencies that your Derw package may use.&#x20;

In terms of pragmatism, Derw follows Python's idea of being useful rather than pure. Derw strives to be a language that allows you to leverage existing code, e.g TypeScript and JavaScript, in a way that allows you to follow functional standards and design.

## How is Derw developed?

Derw started as a collection of libraries for writing TypeScript in a more functional fashion, called [Hiraeth](https://github.com/eeue56/hiraeth). These libraries were mostly for my own use, but as I used them I realized that I needed a language that wasn't TypeScript to write code in my ideally preferred fashion. The best experience I have had to this point for writing web apps has been with Elm, and having been a contributor to Elm, I figured that I could achieve something similar with some differences.

Derw is currently developed in my spare time, but that doesn't mean progress is slow. In fact since Derw started, there's been over 1000 commits to Derw-related projects and repos. The pace really picked up once Derw reached a point where I could start writing things in it and have them work - i.e, once the compiler was generating code and running without bugs. I'm a big believer in designing tooling and APIs through real-world usage. Derw has been used for several real-world apps now, some quite complicated, which helped nail down the remaining bugs.

Every time a new bug is found, I try to add a test to the comprehensive test suite that ensures that the bug won't be encountered again. This allows me to make big refactors quickly.

To keep track of features and bugs, I use a private Pivotal Tracker instance that allows me to write down my thoughts as they come from my head, and prioritize them on a monthly basis. Each month I write up a summary of all the changes on the [Derw blog](https://derw.substack.com/).&#x20;

## Getting Started

{% content-ref url="/pages/nfbSYHqdPaPAy65ickGk" %}
[Creating your first project](/guides/creating-your-first-project)
{% endcontent-ref %}

{% content-ref url="/pages/mvZt1m85fbJ4PhUILOM4" %}
[Installing packages](/guides/installing-packages)
{% endcontent-ref %}

{% content-ref url="/spaces/xsLYiKUIBqHoFtXVlAsD/pages/5p8WKJoEqBoJ2RCzoQcO" %}
[Compiling and running your code](/guides/compiling-and-running-your-code)
{% endcontent-ref %}

{% content-ref url="/spaces/xsLYiKUIBqHoFtXVlAsD/pages/fowQOG1pAXN1YU1hdyt0" %}
[Formatting](/guides/formatting)
{% endcontent-ref %}

{% content-ref url="/spaces/xsLYiKUIBqHoFtXVlAsD/pages/wUNSnz9W76j8L0v1qZQu" %}
[Repl and playground](/guides/repl-and-playground)
{% endcontent-ref %}

{% content-ref url="/spaces/xsLYiKUIBqHoFtXVlAsD/pages/w7ocsLYlB3JLHpHvRCn1" %}
[Testing](/guides/testing)
{% endcontent-ref %}


# Roadmap

Derw is currently in a usable place, but there's a lot more planned. This page documents the current features, along with some ideas I have yet to implement.

* [x] Arrays `[ ]`, `[ 1, 2, 3 ]`, `[ [ 1, 2, 3 ], [ 3, 2, 1 ] ]`
* [x] Booleans `true`, `false`
* [x] Boolean equality `1 < 2`, `1 <= 2`, `1 == 2`, `1 != 2`, `1 > 2`, `1 >= 2`
* [x] Boolean operations `true && false`, `not true`, `true || false`
* [x] Strings `""`, `"hello world"`
* [x] Format strings ` `` `, `` `Hello ${name}` ``
* [x] Numbers `-1`, `0`, `1`, `-1.1`, `1.1`
* [x] Addition `1 + 2`, `"Hello" + name`
* [x] Subtraction `2 - 1`
* [x] Multiplication `2 * 1`
* [x] Division `2 / 1`
* [x] Pipe `[1, 2, 3] |> List.fold add`, `List.fold add <| [1, 2, 3]`
* [ ] Compose `>>`, `<<`
* [x] Constants `hello = "hello world"`
* [x] Function definitions
* [x] Lists `[ 1, 2, 3 ]`, `[ "hello", "world" ]`
* [x] List ranges `[ 1..5 ]`, `[ start..end ]`

  ```elm
  add : number -> number -> number
  add x y = x + y
  ```
* [x] Function calls

  ```elm
  three = add 1 2
  ```
* [x] Module references

  ```elm
  three = List.map identity [ 1, 2, 3 ]
  ```
* [x] Union types

  ```elm
  type Result a b
      = Err { error: a }
      | Ok { value: b }
  ```
* [x] Type variables

  ```
  type Thing a = Thing a
  ```
* [x] Type aliases

  ```elm
  type alias User =
      { name: string }
  ```
* [x] Object literals

  ```elm
  user: User
  user = { name: "Noah" }
  ```
* [x] Object literals updates

  ```elm
  user: User
  user = { ...noah, name: "Noah" }
  ```
* [x] Imports

  ```elm
  import List
  import Result exposing ( map )
  import something as banana
  ```
* [x] Exports

  ```elm
  exposing ( map )
  ```
* [x] Let statements

  ```elm
  sayHiTo : User -> string
  sayHiTo user =
      let
          name = user.name
      in
          "Hello " + name

  sayHelloTo : User -> string
  sayHelloTo user =
      let
          getName: User -> string
          getName user = user.name
      in
          "Hello" + getName user
  ```
* [x] If statements

  ```elm
  type Animal = Animal { age: number }
  sayHiTo : Animal -> string
  sayHiTo animal =
      if animal.age == 1 of
          "Hello little one!"
      else
          "You're old"
  ```
* [x] Case..of

  ```elm
  type Animal = Dog | Cat
  sayHiTo : Animal -> string
  sayHiTo animal =
      case animal of
          Dog -> "Hi dog!"
          Cat -> "Hi cat!"
  ```
* [x] Destructing in case..of

  ```elm
  type User = User { name: string }

  sayHiTo : User -> string
  sayHiTo user =
      case user of
          User { name } -> "Hi " + name + !"
  ```
* [x] strings in case..of
* [x] defaults in case..of

  ```elm
  sayHiTo : string -> string
  sayHiTo name =
      case name of
          "Noah" -> "Hi " + name + !"
          default: "I don't know you"
  ```
* [x] List destructing

  ```elm
  sum: List number -> number
  sum xs =
      case xs of
          [] -> 0
          y :: ys :: [] -> y + ys
          z :: zs -> z + sum zs
          default -> 0
  ```
* [x] List destructing with string values

  ```elm
  sum: List string -> number
  sum xs =
      case xs of
          [] -> 0
          "1" :: ys :: [] -> 1 + 2
          "2" :: zs -> 2 + sum zs
          default -> 0
  ```
* [x] List destructing with union types values

  ```elm
  sum: List (Maybe number) -> number
  sum xs =
      case xs of
          [] -> 0
          Just { value } :: rest -> value + sum rest
          Nothing :: rest -> sum rest
          default -> 0
  ```
* [x] Constructing union types

  ```elm
  type User = User { name: string }
  noah = User { name: "Noah" }
  ```
* [x] Accessors

  ```elm
  type alias User = { name: string }
  names = List.map .name [ { name: "Noah" }, { name: "Dave" } ]
  ```
* [ ] Nested accessors

  ```elm
  type alias Group = { person: { name: string } }
  names = List.map .person.name [ { person: { name: "Noah" } }, { person: { name: "Dave" } } ]
  ```
* [x] Errors on type name collison

  ````markdown
  The name `Person` has been used for different things.
  8 - 10:

  ```
  type Person =
      Person { name: string }
  ```

  11 - 14:

  ```
  type alias Person = {
      name: string
  }
  ```
  ````
* [x] Errors on function name collison

  ````markdown
  The name `isTrue` has been used for different things.
  0 - 3:

  ```
  isTrue: boolean -> boolean
  isTrue x =
      x == true
  ```

  4 - 7:

  ```
  isTrue: boolean -> boolean
  isTrue x =
      x != true
  ```
  ````
* [x] Some form of basic type errors

  ````markdown
  Failed to parse examples/errors/mismatching_types.derw due to:
  Error on lines 0 - 3
  Expected `boolean` but got `number` in the body of the function:

  ```
  isTrue: boolean -> boolean
  isTrue x =
      1 + 2
  ```

  Error on lines 4 - 7
  Expected `List string` but got `List number`:

  ```
  names: List string
  names =
      [1..2]
  ```
  ````
* [x] lambdas `\x -> x + 1`, `\x y -> x + y`
* [x] Typescript output
* [x] Javscript output
* [x] Elm output
* [x] Module resolution
* [x] CLI
* [x] Basic type checking
* [x] Detect if types exist in current namespace
* [x] Syntax highlighting for editors
* [x] Collision detection for names in a module
* [x] Importing of Derw files

  ```elm
  import "./other"
  import "./something" as banana
  import "./another" exposing ( isTrue, isFalse )
  import "./Maybe" as Maybe exposing (Maybe)
  ```
* [x] Errors when failing to find relative import

  ```
  Warning! Failed to find `examples/derw_imports/banana` as either derw, ts or js
  ```
* [x] Single line comments

  ```elm
  -- hello
  isTrue: boolean -> boolean
  isTrue x =
      x
  ```
* [x] Single line comments in function or const bodies

  ```elm
  isTrue: boolean -> boolean
  isTrue x =
      -- hello
      x
  ```
* [x] Multiline comments

  ```elm
  {-
  hello
  world
  -}
  isTrue: boolean -> boolean
  isTrue x =
      x
  ```
* [x] Function arguments

  ```elm
  map: (a -> b) -> a -> b
  map fn value =
      fn value
  ```
* [x] Globals

  Globals can be accessed through the `globalThis` module which is imported into every namespace. E.g `globalThis.console.log`
* [x] Constant if statements

  ```elm
  name: string
  name =
      if 1 == 1 then
          "Noah"
      else
          "James"
  ```
* [x] Constant case statements

  ```elm
  name: string
  name =
      case person of
          "n" -> "Noah"
          "j" -> "James"
          default -> "Other"
  ```
* [x] List prepend

  ```elm
  numbers: List number
  numbers =
      1 :: [ 2, 3 ]
  ```

### 1.0.0

* [x] An automatic formatter with no options

  ```
  derw format
  ```
* [ ] A standard library
* [x] Support for [Coed](https://github.com/eeue56/coed)

  Use [html](https://github.com/derw-lang/html)
* [x] Testing support via [Bach](https://github.com/eeue56/bach)

  Write a file with `_test` as an extension (e.g `List_test.derw`).

  ```elm
  import Test exposing (equals)

  testMath: boolean -> void
  testMath a? =
      equals 1 1
  ```

  Compile it, then run bach via `npx @eeue56/bach`
* [ ] Type checking
* [ ] Benchmarking support via [Mainc](https://github.com/eeue56/mainc)
* [ ] Async support
* [x] Packaging
* [x] Package init

  ```
  derw init
  ```
* [x] Package testing

  ```
  # inside a package directory
  derw test
  ```
* [x] Compile a package

  ```
  derw compile
  ```
* [x] Install a package

  ```
  derw install --name derw-lang/stdlib --version main
  ```
* [x] An info command to find out stats about modules

  ```
  derw init
  ```
* [x] A repl

  ```
  derw repl
  ```
* [x] Bundling

  ```
  derw bundle --entry src/Main.derw --output dist/index.js --watch --quiet
  ```
* [x] English output

  ```
  derw compile --target english
  ```
* [x] Template generation

  ```
  derw template --path src/Main.derw --template web
  ```
* [x] Do notation

  ```elm
  sayHi: string -> void
  sayHi name =
      do
          globalThis.console.log "Hello" name
      return
          undefined
  ```

## 2.0.0

* [ ] Time travelling debugger
* [ ] Type checking with interop with TypeScript
* [ ] Derw compiler is written in Derw


# Creating your first project

## Installing Derw

First we need to install Derw. It's recommended that you use the latest stable version of Node, though most supported versions should work. You need ts-node to run the test runner, so it's recommended to install that too.

```
npm install -g ts-node derw
```

## Creating a project

Starting a project is as simple as making a directory, then initializing Derw inside it.&#x20;

```
derw init
```

```bash
Initialize a directory as a Derw project.
  --dir string:		name of a directory to use as package name e.g stdlib. 
                        Defaults to current directory's name
  -h, --help :		This help text
```

### Using templates to get started

Derw comes with some templates to get you started. Right now there is only one template: for creating a web app using Derw's html library.&#x20;

To create a web template, run

```bash
derw template --template web --path src/Main.derw
```

```bash
Generate a Derw file from a template.
Also installs required packages.
  --path string:		path of Derw file to create
  --template web:		Template to use
  -h, --help :		        This help text
```

## Installing editor and CLI utils

Right now the best supported editor is VSCode, with three extensions that can be used in combination to get some nice features

### Install vscode-language-server

The language server supports things like inline error messages.

On the vscode store: <https://marketplace.visualstudio.com/items?itemName=derw.derw-language-server>

```
git clone https://github.com/derw-lang/derw-language-server
cp -r derw-language-server ~/.vscode/extensions/derw-language-server-0.0.1
```

### Install Derw syntax

Derw syntax highlighting it provided in a separate extension

On the vscode store: <https://marketplace.visualstudio.com/items?itemName=derw.derw-syntax>

```
git clone https://github.com/derw-lang/derw-syntax
cp -r derw-syntax ~/.vscode/extensions/derw-syntax-0.0.1
```

### Install auto-formatter

The auto-formatter runs on-save for files with the .derw extension

On the vscode store: <https://marketplace.visualstudio.com/items?itemName=derw.derw-formatter-vscode>

```
git clone https://github.com/derw-lang/derw-formatter-vscode
cp -r derw-formatter-vscode ~/.vscode/extensions/derw-formatter-vscode-0.0.1
```

### Install Bash completions

If you use Bash, then you probably want some auto completion.

* Clone this [repo](https://github.com/derw-lang/derw-bash-completion)
* Source the `_derw_completions.sh` files in your `~/.bashrc` or `~/.bash_profile`, using `source`
* Restart bash or open a new terminal session

If you're using Linux, you probably want `.bashrc`. If you're using OS X, you probably want `.bash_profile`.

Example .bashrc or .bash\_profile file:

```bash
for f in ~/dev/derw-bash-completion/_*; do source $f; done
```

#### Oh my Zsh

Use `bashcompinit`.

```bash
autoload bashcompinit
bashcompinit
for f in ~/dev/derw-bash-completion/_*; do source $f; done
```


# Installing packages

Derw's packages are Git based, with the ability to use private packages and specific revisions and branches. When fetching a package, Derw checks to see if there is a Node package.json contained within that repo, and if so, it will also pull the npm packages needed.

If you've just cloned a repo for the first time and want to install packages from the derw-package.json, you can simply do:

```bash
derw install
```

If you want to install a new package, you must provide a name and a version. This will be cloned and added to your derw-package.json.

```bash
derw install --name derw-lang/stdlib --version main
```

If you've installed a package at a particular branch and it has updated, simply run `derw install` again and it will fetch the latest version.

```bash
To install a new package run `derw install --name {package name} --version {version}`
Or run me without args inside a package directory to install all packages in derw-package.json
  --name string:		name of the package e.g derw-lang/stdlib
  --version string:		name of the package e.g main or master
  --quiet :		Keep it short and sweet
  -h, --help :		This help text
```


# Compiling and running your code

Now that you have some Derw code, it's time to turn it into something useful. This can be done through either compiling the code, or through bundling it - which also compiles your code.&#x20;

{% hint style="info" %}
Both bundling and compiling have watching support, through the `--watch` flag.
{% endhint %}

{% hint style="info" %}
The best workflow for Derw currently is to have the generated TypeScript files open for your project, to ensure that the TypeScript part compiles
{% endhint %}

## Compiling

Compiling Derw can be done through the `derw compile` command. It will compile everything in your `src` folder and anything that they depend upon. You can specify if you want to generate TypeScript or JavaScript, but the recommended option is TypeScript.

{% hint style="info" %}
Typical usage of `derw compile` doesn't use any flags
{% endhint %}

```bash
Let's write some Derw code
To get started:
Initialize the current directory via `init`
Or provide entry files via `--files`
Or run me without args inside a package directory
  --files [string...]:		File names to be compiled
  --target ts | js | derw | elm | english:		Target TS, JS, Derw, Elm, or English output
  --output string:		Output directory name
  --verify :		Run typescript compiler on generated files to ensure valid output
  --debug :		Show a parsed object tree
  --only string:		Only show a particular object
  --run :		Should be run via ts-node/node
  --names :		Check for missing names out of scope
  --watch :		Watch the files for changes
  --quiet :		Keep it short and sweet
  -h, --help :		This help text
```

You can then run the compiled code via  `ts-node src/<NameOfYourFile>.ts` or `node src/<NameOfYourFile>.js` if you used js as an target. Note that if you used js as a target, your dependencies may need to be compiled if they relied on an npm package that did not provide JavaScript output.

## Bundling

When you produce JavaScript for a website, you would typically want to bundle all the files into a single file. This is done in Derw through `derw bundle`, which uses [esbuild](https://esbuild.github.io/) underneath. Bundling first compiles the Derw code, then uses esbuild to produce a JavaScript file.

```
To bundle, run `derw build --entry {filename} --output {filename}`
To watch use the --watch flag
To produce the smallest bundle use the --optimize flag
  --entry string:		Entry point file to bundle up
  --output string:		Output file to generate
  --quiet :		Don't print any output
  --watch :		Watch Derw files for changes
  --optimize :		Run generated Javascript through minification
  -h, --help :		This help text
```

You would then want to reference the generated file inside a html file, for example:

```bash
derw bundle --entry src/Main.derw --output bundle.js
```

```markup
<html>
    <body>
        <div id="root"></div>
        <script type="text/javascript" src="bundle.js"></script>
    </body>
</html>
```


# Formatting

How to format your Derw code

Derw comes with a built-in formatter. Simply run `derw format` to format all files within your src directory from the root of a Derw project.

```bash
To format, run `derw format`
To watch use the --watch flag
  --watch :		Watch Derw files for changes
  -h, --help :		This help text
```


# Repl and playground

You might want to explore Derw in an interactive fashion, and for that there's two tools that are handy: the repl, and the playground.

## Repl

To access the repl, simply run `derw repl`.

In the repl, you can enter definitions for  imports, types, functions and consts. They will not be evaluated until you use `:run` or `:show`. Between each definition, you should enter a blank newline so that it will be parsed. If parsed successfully, the repl will inform you - and if not, it will show you any errors.&#x20;

#### :run&#x20;

run will evaluate functions and constants

```elm
> x: void
> x = globalThis.console.log "hi"
> 
Parsed successfully
> :run
hi
>
```

#### :show&#x20;

show will first evaluate the current repl body, then print the value of the named value provided

```elm
> x: number
> x = 1 + 10
> 
Parsed successfully
> :show x
11
>
```

#### :eval&#x20;

eval can be used to run some Derw code without needing a definition

```elm
> :eval 10 + 10
Parsed successfully
20
```

#### :help&#x20;

And if you forget all the above, you can use help to get a reminder

```elm
> :help
Enter some code, followed by a blank newline.
Run the current namespace via :run
And check the values of code via :show <name>
Or evaluate a constant or function with :eval <function> <args>
```

## Playground

The [playground](https://www.derw-lang.com/playground/) currently lets you write Derw code, and see the outputted code in any of the target languages. Later on error messages will be added, along with the ability to import packages and run code in the browser.

&#x20;


# Testing

How to test your Derw code

Derw comes with a built-in test runner via `derw test`. The runner is based on [bach](https://github.com/eeue56/bach), a test runner written in TypeScript.

```bash
To run tests, run `derw test` from the package directory
To watch use the --watch flag
  --watch :		Watch Derw files for changes
  --function string:		A particular function name to run
  --file string:		A particular file name to run
  --only-fails :		Only log failing tests
  -h, --help :		This help text
```

## Writing a test

### Naming your file

Your file must have the extension `_test.derw` to be picked up by the test runner.

### Importing the testing functions

Testing functions are provided by the stdlib, which you can install via:

```bash
derw install --name derw-lang/stdlib --version main
```

These can then be imported like&#x20;

```elm
import "./Test" exposing ( equals, notEquals )
```

### Writing your test

A test function should be called `testNameOfTest`, and have the type `a -> void`. Test functions are automatically exported by the compiler.

```elm
testEmptySplit: a -> void
testEmptySplit =
    split "," ""
        |> equals [ "" ]

testSplit: a -> void
testSplit =
    split "," "a,b,c"
        |> equals [
        "a",
        "b",
        "c"
    ]
```

## In-browser tests

When working with html, you may find yourself needing to test a repeated set of actions in the browser - and ensuring the correct data shows up. This can be done via [html-test](https://github.com/derw-lang/html-test) package. It provides both a html element you can embed for results, and a console output. It is currently a work in progress, but if you're curious you can try it out.

![console output](/files/V6ApIYJDmM2mhleEdxut)

![web output](/files/NS04qjsVfO8xSjAGpysY)


# Literals

## Strings

Regular strings can be denoted through double quotation marks. String interpolation can be done through backticks.

```typescript
"hello world"
`hello ${name}`
```

## Numbers

```elm
10
-10
```

## Booleans

```typescript
true
false
```

## Null

```typescript
null
```

## Lists

```typescript
[ 1, 2, 3, 4 ]
```

## List ranges

```elm
[ 1..10 ] -- produces [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ]
[ n..m ]
```

## Objects

```typescript
{ name: "Noah", age: 29 }
```

## Spread operator

In order to update an existing object, you can use the `...` spread operator. This will create a new version of the object, which you can then modify fields on. For example:

```elm
type alias Person = {
    age: number,
    name: string
}

person: Person
person = { age: 27, name: "Noah" }

olderPerson: Person
olderPerson = { ...person, age: 79 } -- equal to { age: 79, name: "Noah" }
```


# Definitions

Definitions are things that you have given a name to: constants, and functions. Derw calls constants const. Each definition of is composed of two parts: a type line, specifying the type of the definition, and the body, specifying the value it should have.

## Consts

A constant is simply a value that does not change.

```elm
name: string
name =
    "Noah"
```

## Functions

A function takes arguments to produce a value.

```elm
sayHi: string -> string
sayHi name =
    if name == "noah" then
        "Hi Noah"
    else
        "I don't know you"
```

### Lambdas

Lambdas (or anonoymous functions) are functions without a name. You'd typically want to use them for making small functions that you pass to another function, like `List.map`.

```elm
incrementAges: List number -> List number
incrementAges ages =
    List.map (\age -> age + 1) ages
```

## Definitions within definitions

Sometimes, you'll want to define a function or a const inside another. This is particularly useful when you have a helper function that you wish to use with a set of arguments from the parent function. These can be done via `let..in`. `let..in` are converted to local variables within the parent code, so you don't need to worry about naming collisions. You can also use `let..in` in if and case branches.

### In a function

```elm
viewPerson: Person -> HtmlNode Msg
viewPerson person =
    let
        viewName: HtmlNode Msg
        viewName =
            text person.name
    in
        div [] [] [ viewName ] 
```

### In a const

```elm
doubledX: number
doubledX =
    let
        x: number
        x = 5
    in
        x + x
```

## Kernel code

### Consts

Consts simply become TypeScript consts

```typescript
const name: string = "Noah";
```

### Functions

Functions become TypeScript functions. All functions must have a return value

```typescript
function sayHi(name: string): string {
    if (name === "noah") {
        return "Hi Noah";
    } else {
        return "I don't know you";
    }
}
```

### Lambdas

Lambdas are turned into anonymous functions in TypeScript, with each argument being marked as `any`.

```typescript
function incrementAges(ages: number[]): number[] {
    return List.map(function(age: any) {
        return age + 1;
    }, ages);
}
```


# Types

There are two main ways to declare a new type in Derw: type aliases, such as those representing a JSON object, and union types, composed of multiple constructors.

Additionally, both type aliases and union types may take a type as an argument. You might want to use this to represent a generic wrapper, such as a `Maybe`.

Derw's types are typically written in caps case, whereas generic arguments are lowercase. Builtin types, such as those that have direct overlap with TypeScript, are often lowercase.

{% hint style="info" %}
There are some builtin types: string, number, boolean, void, null, any, and List&#x20;
{% endhint %}

## Type aliases

Type aliases are what you'd use to represent your typical data objects. A typical usage is for models.

```elm
type alias Model = {
    age: number

}

initialModel: Model
initialModel =
    { age: 29 }
    
myAge: number
myAge =
    initialModel.age
```

In order to pass a type argument, simply follow the name of the type alias with the type argument.

```elm
type alias Person pet = {
    name: string,
    age: number,
    pet: pet
}

type Dog = {
    tailWags: number
}

type Cat = {
    lives: number
}

me: Person Cat
me = 
    {
        name: "Noah",
        age: 29,
        pet: { lives: 9 }
    }
    
myCatsLives: number
myCatsLives =
    me.pet.lives

you: Person Dog
you = 
    {
        name: "Charlie",
        age: 22,
        pet: { tailWags: 9001 }
    }
    
yourDogsTailWags: number
yourDogsTailWags =
    you.pet.tailWags
```

## Union types&#x20;

Union types are useful for when you want to say *this data has multiple shapes.*

Imagine you have multiple modes for a page, and you want to do different things based on the current page. You could use a string, as in the example below.

```elm
viewCurrentPage: string -> HtmlNode msg
viewCurrentPage currentPage =
    case currentPage of
        "home" ->
            div [] [] [ text "Home" ]
    
        "login" ->
            div [] [] [ text "login" ]
        
        default ->
            div [] [] [ text "This should be impossible" ]
```

Using a string requires a default case for when no other strings match, leading you to have impossible states represented in code. Instead, you can use a union type to represent the only possible states, as shown below. Each one of the possible states is known as a tag.

```elm
type PageMode = Home | Login

viewCurrentPage: PageMode -> HtmlNode msg
viewCurrentPage currentPage =
    case currentPage of
        Home ->
            div [] [] [ text "Home" ]
    
        Login ->
            div [] [] [ text "login" ]
```

A particularly useful case for union types is when you want to have an optional data type. You'd represent the contained value as either being there or not. Lots of languages have this concept: optional, maybe, either, result. In Derw's stdlib, Maybe is provided and implemented as the following:

```elm
type Maybe value = Just { value: value } | Nothing

something: Maybe string
something =
    Just { value: "Hello" }
    
nothing: Maybe string
nothing =
    Nothing
    
greeting: Maybe string -> string
greeting maybeGreetingText =
    case maybeGreetingText of
        Just { value } -> value
        
        Nothing -> "No greeting for you"
```

## Untagged union types

Untagged union types represent some data that has a particular set of literal values. Currently only strings are supported.

```elm
type Animal = "cat" | "dog
```

## Kernel code

In the generated TypeScript, union types are represented as TypeScript union types, with a type for each tag. Type aliases are simply a new type. For both union types and type aliases, constructor functions are generated. When generating JavaScript, only the constructor functions are generated.

### Union types

```elm
type Maybe a = Just { value: a } | Nothing
```

compiles into

```typescript
type Just<a> = {
    kind: "Just";
    value: a;
};

function Just<a>(args: { value: a }): Just<a> {
    return {
        kind: "Just",
        ...args,
    };
}

type Nothing = {
    kind: "Nothing";
};

function Nothing(args: {}): Nothing {
    return {
        kind: "Nothing",
        ...args,
    };
}

type Maybe<a> = Just<a> | Nothing;
```

### Type aliases

```elm
type alias Model = { age: number }
```

compiles into

```typescript
type Model = {
    name: string
}

function Model(args: { name: string }): Model {
    return {
        ...args,
    };
}
```

### Untagged union types

```elm
type Animal = "cat" | "dog"
```

compiles into&#x20;

```typescript
type Animal = "cat" | "dog"
```


# Conditionals

In Derw, there are two main types of conditions: if statements, for simple tests of whether something is true or not, and case statements, for pattern matching a value against the possible values it might have. Typically you'd want to use if statements for small checks, and case statements when you have a wide range of possible values.

Both if statements and case statements must have a final value: all branches must have a value have a value.

## If statements

If statements typically look like the following:

```elm
if condition then 
    someValue
else
    someOtherValue
```

Which can be put to use like this:

```elm
sayHi: string -> string
sayHi name =
    if name == "noah" then
        "Hi Noah!"
    else
        `I don't know you, ${name}`
```

They can also be used inline, like

```elm
if condition then someValue else someOtherValue
```

which might look like:

```elm
viewHi: string -> string
viewHi name =
    div 
        [] 
        [] 
        [ if name == "Noah" then text "Hi Noah" else text "I don't know you" ]
```

Typical ways of getting condition are: a boolean value, returning boolean from a function call, or using comparisons (==, !=, <, <=, >, >=).

## Case statements

Case statements typically look like the following:

```
case value of
    somePotentialValue -> someValueToReturn
```

The most common use case is with union types, as shown in the [Types](/fundamentals/types#union-types) page.&#x20;

You can also match against literal values of strings and numbers. When using literal values, you must provide a default case, for example:

```elm
sayHi: string -> string
sayHi name =
    case name of
        "noah" -> "Hi, Noah!"
        "jeremey" -> "Hello, Jeremy!"
        default -> "I don't know you"
        
binaryToString: number -> string
binaryToString binary =
    case binary of
        0 -> "0"
        1 -> "1"
        default -> "0"
```

Lists can be pattern matched with destuctures, again with a default case being required. In the example below, the pattern looks for one element in the front of a list and calls it x, while calling the tail xs.

```elm
sum: List number -> number
sum numbers =
    case numbers of
        x :: xs -> x + (sum xs)
        default -> 0
```

Multiple list destructures can be chained, for example:

```elm
type Summary = 
    ValidSummary { pageCount: number, currentPage: number} 
    | InvalidSummary { reason: string }

parseSummary: List number -> Summary
parseSummary xs =
    case xs of 
        x :: y :: [] -> ValidSummary { pageCount: x, currentPage: y }
        x :: [] -> ValidSummary { pageCount: x, currentPage: y }
        default -> InvalidSummary { reason: "Too many values" }
```

It is also possible to match against parts of list. This is non-greedy by default for example:

```elm
parseParens: List string -> string
parseParens xs =
    case xs of
        "(" :: middle :: ")" :: rest -> String.join "" middle
        default -> ""
        
somethingWithAMiddle: string
somethingWithAMiddel =
    parseParens [ "(", "hello", ")" ]
    
testSomethingWithAMiddle: void
testSomethingWithAMiddle =
    Test.equals "hello" somethingWithAMiddle 
    
somethingWithoutAMiddle: string
somethingWithoutAMiddel =
    parseParens [ "(", "hello" ]
    
testSomethingWithoutAMiddle: void
testSomethingWithoutAMiddle =
    Test.equals "" somethingWithoutAMiddle 
```

## Kernel code

If statements are turned into typical Javascript if statements. If the if statement is used within a const definition, then the generated if is turned into a ternary.

```typescript
function sayHi(name: string): string {
    if (name === "noah") {
        return "Hi, Noah!";
    } else {
        return "I don't know you";
    }
}

const isMe: boolean = name === "noah" ? true: false;
```

Case statements are turned into switch statements. The case conditional is put into a const which is called `_res` + the body turned into a number. This is to prevent collisions with nested cases. Cases used within a const are turned into functions

```typescript
function sayHello(name: string): string {
    const _res3373707 = name;
    switch (_res3373707) {
        case "Noah": {
            return "Hi Noah";
        }
        case "James": {
            return "Greetings";
        }
        default: {
            return "I don't know you";
        }
    }
}

const isKnownPerson = (function(): any {
    const _res3373707 = name;
    switch (_res3373707) {
        case "Noah": {
            return true;
        }
        case "James": {
            return true;
        }
        default: {
            return false;
        }
    }
})();
```


# Imports and exports

When you're working with multiple files, whether they're your own or from a package, you will want to import and export definitions. You'll also want to work with TypeScript or Javascript code, and Derw provides a way to work with that.

## Imports

All imports can either have an alias you provide, or a list of exposed functions which are imported into the current scope. If no alias is provided, the file is imported with the name of the file as the alias. You can export types, functions and consts from other files if they have been exposed. If the an imported type has the same name as the module, then you can refer to the type by its name and also use it for module lookups.

If you want to import from another Derw file, this is the syntax:

```elm
import "./FileName" as FileName
import "./OtherFileName" exposing (sayHi)
import "./FinalFileName"

calulateSomething: string -> string
calculateSomething name =
    FileName.something name

sayHiToSomeone: string -> string
sayHiToSomeone name =
    sayHi name
    
calculateTheFinal: number -> number
calculateTheFinal num =
    FinalFileName.final num
```

If you're working with the stdlib and the html package, then you'd typically have these two imports:

```elm
import "../derw-packages/derw-lang/html/src/Html" as Html exposing ( HtmlNode, RunningProgram, div, text, program, attribute, class_ )
import "../derw-packages/derw-lang/stdlib/src/Maybe" as Maybe exposing ( Maybe, Just, Nothing )
```

When importing from TypeScript or JavaScript local files, the syntax is the same as above. There is no need to include a file extension.

But if you're importing from a global module, for example those provided by node or installed via npm, you can use the syntax:

```elm
import fs
```

## Exports

Exports are done through the exposing keyword. You can have multiple exposing statements, but they must be at the top of the file. You can also expose multiple things in one statement

```elm
exposing (sayHi, sayBye)

sayHi: string -> string
sayHi name =
    "Hi " + name + "!"

sayBye: string -> string
sayBye name =
    "Bye " + name + "!"
```

## Kernel code

### Imports

imports map directly to standard TypeScript imports:

```typescript
import * as fs from "fs";
import * as FileName from "./FileName";
import { sayHi } from "./OtherFileName";
import * as FinalFileName from "./FinalFileName";
import * as Maybe from "./Maybe";
import { Just, Nothing } from "./Maybe";
```

Note that if a type is exposed with the same name as the imported filename, then the generated code will refer to it as `FileName.FileName`.

### Exports

Exports are also standard named exports. There is no default export

```typescript
export { sayHi };
export { sayBye };
```


# Comments

Currently comments exist in two forms: single line and multiline. When using the formatter, comments at the top level are preserved but not those inside function bodies.

## Single line

```elm
-- a single line comment
```

## Multi line

```elm
{-
hello world
multiple lines
-}
```


# Web pages

After you've created your project, the simplest way to start a web-based project is to run `derw template --template web --path src/Main.derw`.

That will generate the following file at `src/Main.derw:`

```elm
import "../derw-packages/derw-lang/html/src/Html" exposing ( HtmlNode, RunningProgram, div, text, program, attribute, class_ )

type alias Model = {
}

initialModel: Model
initialModel =
    { }

type Msg =
    Noop

update: Msg -> Model -> (Msg -> void) -> Model
update msg model send =
    case msg of
        Noop ->
            model

view: Model -> HtmlNode Msg
view model =
    div [ ] [ ] [ text "Hello" ]

root: any
root =
    document.getElementById "root"

main: RunningProgram Model Msg
main =
    program {
        initialModel: initialModel,
        view: view,
        update: update,
        root: root
    }
```

### Imports

First we import the types and some functions from the html package.

```elm
import "../derw-packages/derw-lang/html/src/Html" exposing ( HtmlNode, RunningProgram, div, text, program, attribute, class_ )
```

### Model

The model is the representation of the information required. The generator provides you with an empty one, along with an object literal which you will use for the first render. See [types](/fundamentals/types) for more information.

```elm
type alias Model = {
}

initialModel: Model
initialModel =
    { }
```

### Update

Here we define two things: firstly, the union type that represents all possible actions, which in this case we called `Msg`. Secondly, the update function which takes in an action message, the current model, and a callback for sending messages from async operations. It returns a new version of the model to be used.

```elm
type Msg =
    Noop

update: Msg -> Model -> (Msg -> void) -> Model
update msg model send =
    case msg of
        Noop ->
            model
```

### View

We also define a view function, which takes a model and returns html created by the html package functions.

```elm
view: Model -> HtmlNode Msg
view model =
    div [ ] [ ] [ text "Hello" ]
```

### Root and running

Finally, to hook up the renderer, we grab an element from your index.html file, and use it to contain our Derw program.

```elm
root: any
root =
    document.getElementById "root"

main: RunningProgram Model Msg
main =
    program {
        initialModel: initialModel,
        view: view,
        update: update,
        root: root
    }
```

## Next steps

Imagine you'd like to change the program so that there is a button that when you click on it, it will increment in value and display the value.

### Model

First we would want to edit the model so that it contains a value that we can increment.

```elm
type alias Model = {
    currentNumber: number
}

initialModel: Model
initialModel =
    { currentNumber: 0 }
```

### Update

Next we'll add a message to our `Msg` type - to represent when a user has clicked on the button. We'll also add the logic for incrementing the current number to the update function.

```elm
type Msg =
    Noop
    | Increment

update: Msg -> Model -> (Msg -> void) -> Model
update msg model send =
    case msg of
        Noop ->
            model
            
        Increment ->
            { ...model, currentNumber: model.currentNumber + 1 }
```

### View

We'll also add an onClick listener to the view, and show the current number. Note to do so, we also need to update our import:

```elm
import "../derw-packages/derw-lang/html/src/Html" as Html exposing ( HtmlNode, RunningProgram, div, text, program, attribute, class_ )
```

Now we will be able to refer to the html library via `Html`

```elm
view: Model -> HtmlNode Msg
view model =
    Html.button 
        [ Html.onClick (\_ -> Increment) ] 
        [ ] 
        [ text `Current count: ${model.currentNumber}` ]
```

### Finally

That's it! You now have an incrementing button. You code should look something like this:

```elm
import "../derw-packages/derw-lang/html/src/Html" as Html exposing ( HtmlNode, RunningProgram, div, text, program, attribute, class_ )

type alias Model = {
    currentNumber: number
}

initialModel: Model
initialModel =
    { currentNumber: 0 }

type Msg =
    Noop
    | Increment

update: Msg -> Model -> (Msg -> void) -> Model
update msg model send =
    case msg of
        Noop ->
            model

        Increment ->
            { ...model, currentNumber: model.currentNumber + 1 }

view: Model -> HtmlNode Msg
view model =
    Html.button [ Html.onClick (\_ -> Increment) ] [ ] [ text `Current count: ${model.currentNumber}` ]

root: any
root =
    document.getElementById "root"

main: RunningProgram Model Msg
main =
    program {
        initialModel: initialModel,
        view: view,
        update: update,
        root: root
    }
```

And it should look visually like this:

![Click counter after 13 clicks](/files/G9R8x0lOESbJikJ1TRhn)


# REPLs

A REPL is an interactive command line program where a user responds to questions and things happen.

There's a package for Derw called [repl](https://github.com/derw-lang/repl), which provides a wrapper around Readline.

The structure is similar to the html package, in that everything revolves around a model-view-update loop.

```elm
import "../derw-packages/derw-lang/repl/src/Repl" exposing (RunningProgram, Program, View, Question, End, Statement, program)

type Page =
    Intro
    | ShowInput
    | Quit

type alias Model = {
    page: Page,
    name: string
}

initialModel: Model
initialModel =
    { page: Intro, name: "" }

type Msg =
    SetName { value: string }
    | Finish

setName: string -> Msg
setName name =
    SetName { value: name }

finish: string -> Msg
finish _ =
    Finish

view: Model -> View Msg
view model =
    case model.page of
        Intro ->
            Question { prompt: "What's your name? ", onInput: setName }
        ShowInput ->
            Question { prompt: `Your name is ${model.name}. Press enter to quit`, onInput: finish }
        Quit ->
            End

update: Msg -> Model -> (Msg -> void) -> Model
update msg model send =
    case msg of
        SetName { value } ->
            { ...model, name: value, page: ShowInput }

        Finish ->
            { ...model, page: Quit }

main: RunningProgram Model Msg
main =
    program { initialModel: initialModel, view: view, update: update }

© 2022 GitHub, Inc. 
```


# Contribution flow

Contributions in the form of bug fixes and issues are most welcome. In terms of language design - reach out to me first on [Twitter](https://twitter.com/derwlang) to check if what you've got in mind fits with my plans. Communication is a great way of helping me understand why a pull request might be made, and helps me to help you contribute.

A couple of times a month, I go through the Derw-related repos and see if there's any issues or pull requests I can respond to or merge. Some issues I leave until later - particularly if it's part of some future plan that I might have. If there's something urgent, the best way to esclate is via Twitter. I check my Twitter notifications more frequently than Github.

Releases generally happen throughout the month, but at the end of every month I try to release a new version of Derw and update all the repos that use it - e.g the language server.


# Working on the compiler

Right now the compiler is easiest for me to work on, which means that it's better to either open an issue or reach out to me on Twitter before opening a pull request. That being said: well reasoned pull requests that fit into my plans are totally welcome, across any Derw repo.

This repo contains the compiler, which is split into: parser, tokenizer, type checking, cli and generators.

The flow for compliation looks roughly like:

* Split content into blocks of functions, constants, imports, exports and types.
* Tokenize each block
* Parse each block into an AST
* Check names for collisions and imports
* Check types
* Generate target code

The CLI is mostly responsible for handling all these steps, but the library can be used programatically as it is in the [playground](https://github.com/derw-lang/playground/). Each file in the src/cli folder is responsible for the different abilities of the CLI: installing, formatting, bundling, testing, compiling, templating, etc. These functions all follow the same API to make working on them easier. My rule in designing the CLIs is that they should be obvious on how to use them. There should be a limited number of commands: but I don't want developers to need to install multiple tools to perform standard operations, like formatting or testing. It uses [Baner](https://github.com/eeue56/baner) under the hood for parsing the flags and arguments, so check out the [docs](https://github.com/eeue56/baner/blob/main/docs/src/baner.md) for that if you're unsure.

The generation files are split between Derw, TypeScript, Javascript and Elm. Generally the rule is to avoid code sharing between these as much as possible, as it's easier to read when the code is all in one file and you can clearly see what each AST token generates. That being said, there are some shared files - for example, code for handling indentation. Adding a new code generation target is simplest done by copying the TypeScript generation file - but please reach out to me if you have a new target in mind!

The parser follows a simple rule of one function per expression. There should be only one expression type returned by each parser, and figuring out which to call is done by the main `parseExpression` function. The code here is mostly token based, though in some places it is just done through string manipulation. This is intended to be re-written in Derw in the future, so big refactors aren't necessary at the moment.

Every bug encountered in the parser needs to have a test added for it. There's a combination of tests, some running on library code, some running on short snippets to ensure the parser and generators are consistent. You can find this all in the src/tests folder. To make a new test, just copy one of the existing tests and rename it. It must end with `_test.ts` in order for the test runner to pick it up. You can run the whole suite through `npm run test`, or specifics via `npm run test --file {name of file}`. You can also specify a specific function via the `--function {name of function}` flag, useful for testing just the `testParse` or `testGenerate` of each file. There is also the `--only-fails` flag, useful for just seeing failing tests. Typically snippet tests should test block analysis, parsing, generation, and running the generated TypeScript through tsc. Check out src/tests/simple\_function\_test.ts for an example on how each of those is done. You'll want to also have a [derw-lang/stdlib](https://github.com/derw-lang/stdlib/) folder in the same folder as `derw` to ensure that the stdlib tests can run.


# Hypotheticals

The documents in this collection specify how the language will work and look in the future, not as it currently works. The intention is to share plans for the language and language design before they are actually implemented.


# Async / await

Async / await is a pattern that can be used for managing asynchronus functions, i.e functions that don't complete each function call in order of calling, but rather based on when the task is finished executing. Working with this pattern in JavaScript typically looks like using Promises and callbacks, and modern JavaScript uses two new keywords to manage this: async, which specifies that a function can use await, and await, which specifies that the function should wait until the function provided is finished executing before moving on.

Derw handles this through the use of `do..return`, blocks which can exist within functions, similarly to `let..in` blocks. The main difference is that `do..return` blocks can have top level function calls (i.e without needing to assign the result to a const or a function). Each function call within a do..return block waits until has finished executing before continuing. This means that the order of definitions matter.

Under the hood, these are compiled to async/await JS blocks.


