Skip to content

Indentation based syntax

Alex Zimin edited this page Jul 11, 2011 · 3 revisions

This was one of the open projects.

Table of Contents

Enabling

There are two ways of enabling the indentation syntax. One is to use the -i compiler option. This enables it for all the files passed to the compiler.

The other is to use #pragma indent at the top of the file (comments and whitespace before are OK, anything else is NOT!).

The algorithm

We maintain a stack of indentation strings. Whenever a new, non-empty line is processed we check if:

  • its indentation is the same as the one on the top of the stack, in which case we add a semicolon to close the previous line
  • otherwise the indentation has the top-one as prefix, in which case we push it on the stack and add an open brace
  • otherwise, if the new indentation is somewhere on the stack, we pop elements looking for it and generate a close brace for each indentation popped
  • otherwise it is an error

Exceptions

When the line ends with backslash, in which case it is effectively merged with the next one.

When the line ends with ; or the next one begins with {, the ; is not added.

Inside [], () and {} the indentation processing is off.

Further reading

Most of the comments in Python: Myths about Indentation also applies to our indentation syntax.

Example

using System.Console

[Qux] \
class FooBar
  public static Main () : void
    WriteLine ("Hello")

  static Foo (x : int) : void
    if (x == 3)
      def y = x * 42
      Foo (x)
    else
      [x].Map (fun (x) {
        x * 2
      })

  static Bar () : int
    def foo = 2 \
       + 7 \
       * 13
    foo

is translated to:

using System.Console;

[Qux]
class FooBar {
  public static Main () : void {
    WriteLine ("Hello")
  }

  static Foo (x : int) : void {
    if (x == 3) {
      def y = x * 42;
      Foo (x)
    } else {
      [x].Map (fun (x) {
        x * 2
      })
    }
  }

  static Bar () : int {
    def foo = 2
       + 7
       * 13;
    foo
  }
}

Alternative clauses in a match

If you use alternative clauses in a match, to match multiple cases to one result,

match (s) {
  | "a"
  | "aa" => 1
  | "b"
  | "bb" => 2
  | _ => 0
}

in indententation based syntax :

match (s)
  | "a"
  | "aa" => 1
  | "b"
  | "bb" => 2
  | _ => 0

it won't compile, you need to use line continuation ('\')

match (s)
  | "a" \
  | "aa" => 1
  | "b" \
  | "bb" => 2
  | _ => 0

or just use standard syntax with { .. } for this specific match:

match (s) {
  | "a"
  | "aa" => 1
  | "b"
  | "bb" => 2
  | _ => 0
}
Clone this wiki locally