将无类型的JavaScript编译为WebAssembly没有意义,因为它最终会导致运行其中较慢的一个JavaScript。
相反,AssemblyScript专注于WebAssembly擅长的地方,并且不支持回退到无法提前有效编译的JavaScript的动态特性:
总体来说 AssemblyScript 比 TypeScript 又多了很多限制,编写起来会觉得局限性很大; 用 AssemblyScript 来写 WebAssembly 经常会出现 tsc 编译通过但运行 WebAssembly 时出错的情况,这很可能就是你没有遵守以上限制导致的;但 AssemblyScript 通过修改 TypeScript 编译器默认配置能在编译阶段找出大多错误。
AssemblyScript 的实现原理其实也借助了 LLVM,它通过 TypeScript 编译器把 TS 源码解析成 AST,再把 AST 翻译成 IR,再通过 LLVM 编译成 WebAssembly 字节码实现; 上面提到的各种限制都是为了方便把 AST 转换成 LLVM IR。
当调用一个从Js中导出的可变参数长度的WebAssembly函数时,例如:
1 export function add(a: i32 = 1, b: i32 = 2): i32 { 2 return a + b; 3 }
必须明确指定调用的实际参数数量,因为WebAssembly端没有与arguments.length等效的内容。 例如:
1 exports._setargc(0); 2 exports.sum(); // 3 3 4 exports._setargc(1); 5 exports.sum(2); // 4 6 7 exports._setargc(2); 8 exports.sum(2, 3); // 5
与在JS中使用各种数值的数字类型不同,AssemblyScript将它们拆分为更精确的整数和浮点类型,这些类型直接映射到WebAssembly类型。
注意:模拟类型被隐式符号扩展,分别被屏蔽以处理溢出。 在进行大量数学运算时,建议在计算中使用原生类型,然后将值存储回模拟类型,上面的"位"即byte,字节。
注意,使用目标特定类型可能需要也可能不需要显式强制类型,具体取决于目标。
注意,WASM64是未来的功能??,现在在任何地方都不受支持。
为方便起见,以下范围限制作为全局常量出现:
Constant | Value |
---|---|
i8.MIN_VALUE: i8 |
-128 |
i8.MAX_VALUE: i8 |
127 |
i16.MIN_VALUE: i16 |
-32768 |
i16.MAX_VALUE: i16 |
32767 |
i32.MIN_VALUE: i32 |
-2147483648 |
i32.MAX_VALUE: i32 |
2147483647 |
i64.MIN_VALUE: i64 |
-9223372036854775808 |
i64.MAX_VALUE: i64 |
9223372036854775807 |
isize.MIN_VALUE: isize |
target specific: either i32.MIN_VALUE or i64.MIN_VALUE |
isize.MAX_VALUE: isize |
target specific: either i32.MAX_VALUE or i64.MAX_VALUE |
u8.MIN_VALUE: u8 |
0 |
u8.MAX_VALUE: u8 |
255 |
u16.MIN_VALUE: u16 |
0 |
u16.MAX_VALUE: u16 |
65535 |
u32.MIN_VALUE: u32 |
0 |
u32.MAX_VALUE: u32 |
4294967295 |
u64.MIN_VALUE: u64 |
0 |
u64.MAX_VALUE: u64 |
18446744073709551615 |
usize.MIN_VALUE: usize |
0 |
usize.MAX_VALUE: usize |
target specific: either u32.MAX_VALUE or u64.MAX_VALUE |
bool.MIN_VALUE: bool |
0 |
bool.MAX_VALUE: bool |
1 |
f32.MIN_VALUE: f32 |
-3.40282347e+38 |
f32.MAX_VALUE: f32 |
3.40282347e+38 |
f32.MIN_SAFE_INTEGER: f32 |
-16777215 |
f32.MAX_SAFE_INTEGER: f32 |
16777215 |
f32.EPSILON: f32 |
1.19209290e-07 |
f64.MIN_VALUE: f64 |
-1.7976931348623157e+308 |
f64.MAX_VALUE: f64 |
1.7976931348623157e+308 |
f64.MIN_SAFE_INTEGER: f64 |
-9007199254740991 |
f64.MAX_SAFE_INTEGER: f64 |
9007199254740991 |
f64.EPSILON: f64 |
2.2204460492503131e-16 |
将一种类型的值分配给另一种类型的目标可以在没有显式强制转换的情况下执行,其中可以在目标类型中表示完整范围的可能值,而不管解释/签名:
? | bool | i8/u8 | i16/u16 | i32/u32 | i64/u64 | f32 | f64 |
---|---|---|---|---|---|---|---|
bool | ? | ? | ? | ? | ? | ? | ? |
i8/u8 | ? | ? | ? | ? | ? | ? | |
i16/u16 | ? | ? | ? | ? | ? | ||
i32/u32 | ? | ? | ? | ||||
i64/u64 | ? | ||||||
f32 | ? | ? | |||||
f64 | ? |
注意,如果目标是WASM32,则isize / usize的行为与i32 / u32相同,如果目标是WASM64,则分别为i64 / u64。
例如:
1 var i8val : i8 = -128; // 0x80 2 var u8val : u8 = i8val; // becomes 128 (0x80) 3 var i16val : i16 = i8val; // becomes -128 through sign-extension (0xFF80) 4 var u16val : u16 = i8val; // becomes 65408 through masking (0xFF80) 5 var f32val : f32 = i8val; // becomes -128.0
可以在可分配性中概述的相同规则下执行比较不同类型的两个值而无需显式转换
1.如果比较是绝对的 (==
, !=
)
2.如果比较是相对的 (>
, <
, >=
, <=
) 并且两种类型都具有相同的签名
因为WebAssembly对签名和未签名的比较具有不同的操作。 比较使用较大的类型并返回一个bool。
划分或取出除以不同类型的两个值的余数,可以在可转让性中概述的相同规则下进行显式转换。
因为WebAssembly对有符号和无符号除法和余数有不同的操作。 结果是更大的类型。
位运算(<<,>>)的结果是左类型,右类型隐式转换为左类型,如果左类型是有符号的,则执行算术移位;如果左类型是无符号,则执行逻辑移位。
无符号右移(>>>)的结果是左类型(保留了符号),右类型隐式转换为左类型,但始终执行逻辑移位。
如果左类型是浮点数,则会发出错误。
WebAssembly基本概念到此结束,虽然有很多不理解的东西,但还是先记录在此,慢慢学习。
参考原文:
https://github.com/AssemblyScript/assemblyscript/wiki/Types
WebAssembly学习(六):AssemblyScript - 限制与类型
原文:https://www.cnblogs.com/jixiaohua/p/10447701.html