Bend/README.md
2024-01-17 09:09:35 -03:00

4.2 KiB
Raw Blame History

HVM-Lang

HVM-Lang is a lambda-calculus based language and serves as an Intermediate Representation for HVM-Core, offering a higher level syntax for writing programs based on the Interaction-Calculus.

Installation

With the nightly version of rust installed, clone the repository:

git clone https://github.com/HigherOrderCO/hvm-lang.git

cd hvm-lang

Install using cargo:

cargo install --path .

Usage

First things first, let's write a basic program that adds the numbers 3 and 2.

main = (+ 3 2)

HVM-Lang searches for the main | Main definitions as entrypoint of the program.

To run a program, use the run argument:

hvml run <file>

It will show the number 5. Adding the --stats option displays some runtime stats like time and rewrites.

To limit the runtime memory, use the --mem <size> option. The default is 1GB:

hvml --mem 65536 run <file>

You can specify the memory size in bytes (default), kilobytes (k), megabytes (m), or gigabytes (g), e.g., --mem 200m.

To compile a program use the compile argument:

hvml compile <file>

This will output the compiled file to stdout.

Syntax

HVM-Lang files consists of a series of definitions, which bind a name to a term. Terms can be lambdas, applications, or other terms.

Here's a lambda where the body is the variable x:

id = λx x

Lambdas can also be defined using @. To discard the variable and not bind it to any name, use *:

True  = @t @* t
False = λ* λf f

Applications are enclosed by ( ).

(λx x λx x λx x)

This term is the same as:

(((λx x) (λx x)) (λx x))

Parentheses around lambdas are optional. Lambdas have a high precedence

(λx a b) == ((λx a) b) != (λx (a b))

* can also be used to define an eraser term.
It compiles to an inet node with only one port that deletes anything thats plugged into it.

era = *

A let term binds some value to the next term, in this case (* result 2):

let result = (+ 1 2); (* result 2)

It is possible to define tuples:

tup = (2, 2)

And destructuring tuples with let:

let (x, y) = tup; (+ x y)

Strings are delimited by " " and support Unicode characters.

main = "Hello, 🌎"

A string is desugared to a String data type containing two constructors, SCons and SNil.

// These two are equivalent
StrEx1 = "Hello"

data String = (SCons head tail) | SNil
StrEx2 = (SCons 'H' (SCons 'e', (SCons 'l' (SCons 'l', (SCons 'o' SNil)))))

Characters are delimited by ' ' and support Unicode escape sequences. They have a numeric value associated with them.

main = '\u4242'

Lists are delimited by [ ] and elements can be optionally separated by ,.

ids = [3, 6, 9 12 16]

A list is desugared to a List data type containing two constructors, LCons and LNil.

// These two are equivalent
ListEx1 = [1, 2, 3]

data List = (LCons head tail) | (LNil)
ListEx2 = (LCons 1 (LCons 2 (LCons 3 LNil)))

More features

Key:

  • 📗: Basic resources
  • 📙: Intermediate resources
  • 📕: Advanced resources

Other features are described in the following documentation files:

Further reading