A compiler for a purely functional programming language with emphasis on structural typing https://giml-lang.org
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

4.4KB

Giml

This document describes the basic syntax and features of Giml.

Note, it is very terse at the moment, sorry about that.

Definitions

A Giml source file is composed of definitions. We can define a value, a function or a type using the following forms:

<name> = <expression> // A value

<name> [<argument>, ...] = <expression> // A function

newtype <Typename> <type-arguments> = // A type
    [ <type-variant> ]
end

Note that:

  • <name>, <arguments> and <type arguments> must start with a lowercase letter, <Typename> must start with an uppercase letter

  • <arguments> are separated by commas

  • <type-arguments> are separated by spaces

  • <type-variants> start with |, followed by a data tag (must start with an uppercase letter), and then optionally followed by a single type.

Examples:

hello = "hello world"

increment n = add n 1

newtype Option a =
    | None {}
    | Some a
end

Expressions

An expression can be one of the following things:

  • A literal, either an integer, a floating point number, or a string

For example:

one = 1
seven = 0x111
twentyone = 0xf5
one_and_half = 1.5
name = "Gil"
  • A variable, which must start with a lowercase letter

For example:

name
  • An anonymous function of the form \<arguments> -> <expression>

For example:

increment = \n -> add n 1
  • A function application of the form <expression> [<expression>, ...])

For example:

two = increment one
  • A variant expression of the form <data tag> <expression>

For example:

none = None
some1 = Some 1
  • A record expression of the form { [<name> = <expression>, ...] }

For example:

desc = { name = "Giml", year = 2021 }
  • A record access of the form <expression>.<label>

For example:

gimlYear = desc.year
  • A record extension of the form { [<name> = <expression>, ...] | <expression> }

For example:

descWithCreator = { author = "Gil" | desc }
  • A foreign function interface call of the form ffi(<js-function-name> [: <type>], [arguments, ...]). The type part is optional.

For example:

print x = ffi("console.log", x)

strToInt str = ffi("parseInt" : String -> Int, str)
  • A case expression of the form case <expression> of [ | <pattern> -> <expression> ] end

For example:

greet person =
    case person.name of
	    | "Gil" -> "Hi Gil!"
		| name -> concat "Hello, " name
	end
  • Do Blocks

IO actions can be chained by one or more statements separated by newlines which start with the keyword do and end with the keyword end.

Each statement is either an expression, a definition (barring type definitions), or a binding. A binding is a statement of the form <variable> <- <expression>, where the expression should have the type IO t and the variable will have the type t.

The last statement will be the return value of the do block.

For example:

print1234 = do
    let
        print2 m = do
	        ffi("console.log", m)
	        ffi("console.log", add m 1)
		end
	print2 1
	print2 3
end

-- should print:
-- 1
-- 2
-- 3
-- 4

Patterns

Case expressions match the expression between the case and of keywords with each of the patterns in order, when a match succeeds, the expression to the right of that pattern is returned.

Patterns can be one of the following:

  • A wildcard which matches any expression, denoted _

  • A variable name which matches any expression and is bound in the scope of the expression to the right of the arrow with the matched expression

  • A literal value

  • A variant of patterns

  • A record of patterns

Types

A type can be one of:

  • Type name, beginning with an uppercase letter, for example Int

  • A type variable, beginning with a lowercase letter, for example a

  • A function takes exactly one argument and returns one result. The type of a function has the form <type> -> <type> such as a -> b -> a. Note that the arrow operator is right associative so no parenthesis are needed around b -> a.

  • An application of types, separated by space, for example Option Int

  • A record of types of the form { [ <label> : <type>, ... ] }, for example { name : String, year : Int }