mirror of
https://github.com/adambard/learnxinyminutes-docs.git
synced 2024-12-24 10:01:38 +00:00
203 lines
7.0 KiB
Markdown
203 lines
7.0 KiB
Markdown
---
|
|
language: AssemblyScript
|
|
contributors:
|
|
- ["Philippe Vlérick", "https://github.com/pvlerick"]
|
|
- ["Steve Huguenin-Elie", "https://github.com/StEvUgnIn"]
|
|
- ["Sebastian Speitel", "https://github.com/SebastianSpeitel"]
|
|
- ["Max Graey", "https://github.com/MaxGraey"]
|
|
filename: learnassemblyscript.ts
|
|
---
|
|
|
|
__AssemblyScript__ compiles a variant of __TypeScript__ (basically JavaScript with types) to __WebAssembly__ using __Binaryen__. It generates lean and mean WebAssembly modules while being just an `npm install` away.
|
|
|
|
This article will focus only on AssemblyScript extra syntax, as opposed to [TypeScript](/docs/typescript) and [JavaScript](/docs/javascript).
|
|
|
|
To test AssemblyScript's compiler, head to the
|
|
[Playground](https://www.assemblyscript.org/editor.html#IyFydW50aW1lPXN0dWIKLyoqIENhbGN1bGF0ZXMgdGhlIG4tdGggRmlib25hY2NpIG51bWJlci4gKi8KZXhwb3J0IGZ1bmN0aW9uIGZpYihuOiBpMzIpOiBpMzIgewogIHZhciBhID0gMCwgYiA9IDEKICBpZiAobiA+IDApIHsKICAgIHdoaWxlICgtLW4pIHsKICAgICAgbGV0IHQgPSBhICsgYgogICAgICBhID0gYgogICAgICBiID0gdAogICAgfQogICAgcmV0dXJuIGIKICB9CiAgcmV0dXJuIGEKfQoKIyFodG1sCjx0ZXh0YXJlYSBpZD0ib3V0cHV0IiBzdHlsZT0iaGVpZ2h0OiAxMDAlOyB3aWR0aDogMTAwJSIgcmVhZG9ubHk+PC90ZXh0YXJlYT4KPHNjcmlwdD4KbG9hZGVyLmluc3RhbnRpYXRlKG1vZHVsZV93YXNtLCB7IC8qIGltcG9ydHMgKi8gfSkKICAudGhlbigoeyBleHBvcnRzIH0pID0+IHsKICAgIGNvbnN0IG91dHB1dCA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCdvdXRwdXQnKQogICAgZm9yIChsZXQgaSA9IDA7IGkgPD0gMTA7ICsraSkgewogICAgICBvdXRwdXQudmFsdWUgKz0gYGZpYigke2l9KSA9ICR7ZXhwb3J0cy5maWIoaSl9XG5gCiAgICB9CiAgfSkKPC9zY3JpcHQ+Cg==) where you will be able
|
|
to type code, have auto completion and directly see the emitted WebAssembly.
|
|
|
|
```ts
|
|
// There are many basic types in AssemblyScript,
|
|
let isDone: boolean = false;
|
|
let name: string = "Anders";
|
|
|
|
// but integer type come as signed (sized from 8 to 64 bits)
|
|
let lines8: i8 = 42;
|
|
let lines16: i16 = 42;
|
|
let lines32: i32 = 42;
|
|
let lines64: i64 = 42;
|
|
|
|
// and unsigned (sized from 8 to 64 bits),
|
|
let ulines8: u8 = 42;
|
|
let ulines16: u16 = 42;
|
|
let ulines32: u32 = 42;
|
|
let ulines64: u64 = 42;
|
|
|
|
// and float has two sizes possible (32/64).
|
|
let rate32: f32 = 1.0
|
|
let rate64: f64 = 1.0
|
|
|
|
// But you can omit the type annotation if the variables are derived
|
|
// from explicit literals
|
|
let _isDone = false;
|
|
let _lines = 42;
|
|
let _name = "Anders";
|
|
|
|
// Use const keyword for constants
|
|
const numLivesForCat = 9;
|
|
numLivesForCat = 1; // Error
|
|
|
|
// For collections, there are typed arrays and generic arrays
|
|
let list1: i8[] = [1, 2, 3];
|
|
// Alternatively, using the generic array type
|
|
let list2: Array<i8> = [1, 2, 3];
|
|
|
|
// For enumerations:
|
|
enum Color { Red, Green, Blue };
|
|
let c: Color = Color.Green;
|
|
|
|
// Functions imported from JavaScript need to be declared as external
|
|
// @ts-ignore decorator
|
|
@external("alert")
|
|
declare function alert(message: string): void;
|
|
|
|
// and you can also import JS functions in a namespace
|
|
declare namespace window {
|
|
// @ts-ignore decorator
|
|
@external("window", "alert")
|
|
function alert(message: string): void;
|
|
}
|
|
|
|
// Lastly, "void" is used in the special case of a function returning nothing
|
|
export function bigHorribleAlert(): void {
|
|
alert("I'm a little annoying box!"); // calling JS function here
|
|
}
|
|
|
|
// Functions are first class citizens, support the lambda "fat arrow" syntax
|
|
|
|
// The following are equivalent, the compiler does not offer any type
|
|
// inference for functions yet, and same WebAssembly will be emitted.
|
|
export function f1 (i: i32): i32 { return i * i; }
|
|
// "Fat arrow" syntax
|
|
let f2 = (i: i32): i32 => { return i * i; }
|
|
// "Fat arrow" syntax, braceless means no return keyword needed
|
|
let f3 = (i: i32): i32 => i * i;
|
|
|
|
// Classes - members are public by default
|
|
export class Point {
|
|
// Properties
|
|
x: f64;
|
|
|
|
// Constructor - the public/private keywords in this context will generate
|
|
// the boiler plate code for the property and the initialization in the
|
|
// constructor.
|
|
// In this example, "y" will be defined just like "x" is, but with less code
|
|
// Default values are also supported
|
|
|
|
constructor(x: f64, public y: f64 = 0) {
|
|
this.x = x;
|
|
}
|
|
|
|
// Functions
|
|
dist(): f64 { return Math.sqrt(this.x * this.x + this.y * this.y); }
|
|
|
|
// Static members
|
|
static origin: Point = new Point(0, 0);
|
|
}
|
|
|
|
// Classes can be explicitly marked as extending a parent class.
|
|
// Any missing properties will then cause an error at compile-time.
|
|
export class PointPerson extends Point {
|
|
constructor(x: f64, y: f64, public name: string) {
|
|
super(x, y);
|
|
}
|
|
move(): void {}
|
|
}
|
|
|
|
let p1 = new Point(10, 20);
|
|
let p2 = new Point(25); //y will be 0
|
|
|
|
// Inheritance
|
|
export class Point3D extends Point {
|
|
constructor(x: f64, y: f64, public z: f64 = 0) {
|
|
super(x, y); // Explicit call to the super class constructor is mandatory
|
|
}
|
|
|
|
// Overwrite
|
|
dist(): f64 {
|
|
let d = super.dist();
|
|
return Math.sqrt(d * d + this.z * this.z);
|
|
}
|
|
}
|
|
|
|
// Namespaces, "." can be used as separator for sub namespaces
|
|
export namespace Geometry {
|
|
class Square {
|
|
constructor(public sideLength: f64 = 0) {
|
|
}
|
|
area(): f64 {
|
|
return Math.pow(this.sideLength, 2);
|
|
}
|
|
}
|
|
}
|
|
|
|
let s1 = new Geometry.Square(5);
|
|
|
|
// Generics
|
|
// AssemblyScript compiles generics to one concrete method or function per set
|
|
// of unique contextual type arguments, also known as [monomorphisation].
|
|
// Implications are that a module only includes and exports concrete functions
|
|
// for sets of type arguments actually used and that concrete functions can be
|
|
// shortcutted with [static type checks] at compile time, which turned out to
|
|
// be quite useful.
|
|
// Classes
|
|
export class Tuple<T1, T2> {
|
|
constructor(public item1: T1, public item2: T2) {
|
|
}
|
|
}
|
|
|
|
export class Pair<T> {
|
|
item1: T;
|
|
item2: T;
|
|
}
|
|
|
|
// And functions
|
|
export function pairToTuple <T>(p: Pair<T>): Tuple<T, T> {
|
|
return new Tuple(p.item1, p.item2);
|
|
};
|
|
|
|
let tuple = pairToTuple<string>({ item1: "hello", item2: "world" });
|
|
|
|
// Including references to a TypeScript-only definition file:
|
|
/// <reference path="jquery.d.ts" />
|
|
|
|
// Template Strings (strings that use backticks)
|
|
// String Interpolation with Template Strings
|
|
let name = 'Tyrone';
|
|
let greeting = `Hi ${name}, how are you?`
|
|
// Multiline Strings with Template Strings
|
|
let multiline = `This is an example
|
|
of a multiline string`;
|
|
|
|
let numbers: Array<i8> = [0, 1, 2, 3, 4];
|
|
let moreNumbers: Array<i8> = numbers;
|
|
moreNumbers[5] = 5; // Error, elements are read-only
|
|
moreNumbers.push(5); // Error, no push method (because it mutates array)
|
|
moreNumbers.length = 3; // Error, length is read-only
|
|
numbers = moreNumbers; // Error, mutating methods are missing
|
|
|
|
// Type inference in Arrays
|
|
let ints = [0, 1, 2, 3, 4] // will infer as Array<i32>
|
|
let floats: f32[] = [0, 1, 2, 3, 4] // will infer as Array<f32>
|
|
let doubles = [0.0, 1.0, 2, 3, 4] // will infer as Array<f64>
|
|
let bytes1 = [0 as u8, 1, 2, 3, 4] // will infer as Array<u8>
|
|
let bytes2 = [0, 1, 2, 3, 4] as u8[] // will infer as Array<u8>
|
|
let bytes3: u8[] = [0, 1, 2, 3, 4] // will infer as Array<u8>
|
|
```
|
|
|
|
## Further Reading
|
|
|
|
* [AssemblyScript Official website](https://www.assemblyscript.org/)
|
|
* [AssemblyScript source documentation](https://github.com/AssemblyScript/website/tree/main/src)
|
|
* [Source Code on GitHub](https://github.com/AssemblyScript/assemblyscript)
|