Skip to content
Arthur Buldauskas edited this page Jan 4, 2018 · 2 revisions

THIS IS DEPRECATED

This info is here only for historical reasons.

;

No semicolons. I couldn't think of a good reason for them.

It's actually harder to write a parser without using semicolons/newline terminated expressions, at least for me.

Module

Each file is assumed to be a module and is scoped as such, unless the module keyword is used to declare 1 or more modules inside the file.

module See: function

module is an alias for function but is treated as a special Module declaration by the parser. This provides the ability to define more than one module per file. Which is also available in wast.

// module and function keyword can omit an identifier
module () {
  // memory, table, imports, exports and module body are here
}

// Multiple modules can be declared in a single file
module bar() {
  // everything scoped to bar
}

// assertions, not part of any module code

// assert_return(...);
// assert_return(...);

These two are equivalent

  • module () {} - empty module function
  • - empty file

They compile to:

  • (module) - empty module

Functions

Function declarations resemble ES5 functions. Functions with return values must be declared as such. A function not returning a result can omit a return type. func keyword is used for both function declarations and function pointer types.

// name can be omited, but the function may not be referenced
func() {
};

// named function
func foo() {
}

// return values
func bar(): i32 {
  x:f64 = 5.0
  return x
} //     ^  Type Error: return value of type i32 expected

// IIFE
(func (num): bool {
  return num % 2 !== 0
})(2)

Exports, Imports

ES6-like imports and exports are supported. default keyword is not, there are not default exports in wast modules. All imports must be statically typed. For example, imported function must have a type of func.

module foobar() {
  import log: func from 'console'

  global counter: i32 = 0

  export func count() {
    log(counter++)
  }
}

import statements are only allowed at the top of the module. import inside module body is a syntax error.

module notallowed() {
  import bar from 'console'
  // ^ Syntax Error: Expect type after identifier 'bar'

  global foo: bool = false
  import log: func from 'console'
  // ^ Syntax error: imports are only allowed at the start of the module
}

Memory, Table (WIP)

Memory and Table defined with by memory and table keyword. Values of each must be an arrays.

Memory

mem: memory = [0, 128] // number of pages [min, max]

Table

Declaration

let and const declarations are supported. Scope is inferred based on where the value is declared. There are only two possible scopes: function or global. Variables declared outside a function are global by default.

Type operator :

: "type of" keyword is a special operator and only has a single meaning in walt. Is used to describe types

The line: x : i32

can be rad as: x type of 32-bit integer

type of operator can be used with assigned to perform type conversion

The line: y = x : f32

can be read as: assign y the value of x type of 32-bit float

Types

Native wasm modules are supported: i32, i64, f32, f64. With two additional types bool and func.

  • bool is an alias for i32 but is a strictly type checked.
  • func is a function pointer. Function pointer cannot be cast to any other type.

Type casting

All type-casting must be explicit. No type casting is performed for you. Parser will throw an error on implicit conversions.

x: i32 = 0
y: f32 = 1

x = y;
// ^ Type Error: implicit conversion f32 to i32

x = y:i32
// Ok!

z: bool = 1
x = z
// ^ Type Error: implicit conversion bool to i32

// bool is alias for i32 but is type-checked for full type safety
x = z:i32
// Ok!

// function pointer cannot be converted
func (log: func) {
  x: i64 = func
  // ^ Type Error: cannot convert function to i64
  z: i64;
  z = log:i64;
  // ^ Type Error: cannot convert function to i64
}

// function can be declared as variables
import log: func from 'console';
foo: func = (num: i32) {
  log(num)
}

foo(42); // 42

function fibonacci(num){
  var a = 1, b = 0, temp;

  while (num >= 0){
    temp = a;
    a = a + b;
    b = temp;
    num--;
  }

  return b;
}
func fibonacci(num: i64): i64 {
	a: i64 = 1
  b: i64 = 0
  temp: i64

	while (num >= 0) {
		temp = a
    a = a + b
    b = temp
    num--
  }

  return b
}
function fibonacci(num) {
    if (num <= 1) return 1;

  return fibonacci(num - 1) + fibonacci(num - 2);
}
func fibonacci(num: i64): i64 {
  if (num <= 1) return 1
  return fibonacci(num - 1) + fibonacci(num - 2)
}