summaryrefslogtreecommitdiffhomepage
path: root/uk-ua/wasm.html.markdown
diff options
context:
space:
mode:
authorOleh Hromiak <o.a.gromyak@gmail.com>2019-10-07 22:35:03 +0300
committerOleh Hromiak <o.a.gromyak@gmail.com>2019-10-07 22:35:03 +0300
commit3024f90a397cfef7e51577d232417b8f753b771d (patch)
treee4d95d9946e357b8d14a054fa49035712dcd82d4 /uk-ua/wasm.html.markdown
parentf7a4c3ed54983fb3e632d0d5e36215606f2a9f1e (diff)
Fix [wasm/ua] filename
Diffstat (limited to 'uk-ua/wasm.html.markdown')
-rw-r--r--uk-ua/wasm.html.markdown225
1 files changed, 0 insertions, 225 deletions
diff --git a/uk-ua/wasm.html.markdown b/uk-ua/wasm.html.markdown
deleted file mode 100644
index b5a1f4dd..00000000
--- a/uk-ua/wasm.html.markdown
+++ /dev/null
@@ -1,225 +0,0 @@
----
-language: WebAssembly
-filename: learnwasm-ua.wast
-contributors:
- - ["Dean Shaff", "http://dean-shaff.github.io"]
-translators:
- - ["Oleh Hromiak", "https://github.com/ogroleg"]
----
-
-```
-;; learnwasm-ua.wast
-
-(module
- ;; У WebAssembly весь код знаходиться в модулях. Будь-яка операція
- ;; може бути записана за допомогою s-виразу. Також існує синтаксис "стек машини",
- ;; втім, він не сумісний з проміжним бінарним представленням коду.
-
- ;; Формат бінарного проміжного представлення майже повністю сумісний
- ;; з текстовим форматом WebAssembly.
- ;; Деякі відмінності:
- ;; local_set -> local.set
- ;; local_get -> local.get
-
- ;; Код розміщується у функціях
-
- ;; Типи даних
- (func $data_types
- ;; WebAssembly має чотири типи даних:
- ;; i32 - ціле число, 32 біти
- ;; i64 - ціле число, 64 біти (не підтримується у JavaScript)
- ;; f32 - число з плаваючою комою, 32 біти
- ;; f64 - число з плаваючою комою, 64 біти
-
- ;; Створити локальну змінну можна за допомогою ключового слова "local".
- ;; Змінні потрібно оголошувати на початку функції.
-
- (local $int_32 i32)
- (local $int_64 i64)
- (local $float_32 f32)
- (local $float_64 f64)
-
- ;; Змінні, оголошені вище, ще не ініціалізовані, себто, не мають значення.
- ;; Давайте присвоїмо їм значення за допомогою <тип даних>.const:
-
- (local.set $int_32 (i32.const 16))
- (local.set $int_32 (i64.const 128))
- (local.set $float_32 (f32.const 3.14))
- (local.set $float_64 (f64.const 1.28))
- )
-
- ;; Базові операції
- (func $basic_operations
-
- ;; Нагадаємо, у WebAssembly будь-що є s-виразом, включно
- ;; з математичними виразами або зчитуванням значень змінних
-
- (local $add_result i32)
- (local $mult_result f64)
-
- (local.set $add_result (i32.add (i32.const 2) (i32.const 4)))
- ;; тепер add_result дорівнює 6!
-
- ;; Для кожної операції потрібно використовувати правильний тип:
- ;; (local.set $mult_result (f32.mul (f32.const 2.0) (f32.const 4.0))) ;; Ніт! mult_result має тип f64!
- (local.set $mult_result (f64.mul (f64.const 2.0) (f64.const 4.0))) ;; Ніт! mult_result має тип f64!
-
- ;; У WebAssembly є вбудовані функції накшталт математики та побітових операцій.
- ;; Варто зазначити, що тут відсутні вбудовані тригонометричні функції.
- ;; Тож нам потрібно:
- ;; - написати їх самостійно (не найкраща ідея)
- ;; - звідкись їх імпортувати (як саме - побачимо згодом)
- )
-
- ;; Функції
- ;; Параметри вказуються ключовим словом `param`, значення, що повертається - `result`
- ;; Поточне значення стеку і є значенням функції, що повертається
-
- ;; Ми можемо викликати інші функції за допомогою `call`
-
- (func $get_16 (result i32)
- (i32.const 16)
- )
-
- (func $add (param $param0 i32) (param $param1 i32) (result i32)
- (i32.add
- (local.get $param0)
- (local.get $param1)
- )
- )
-
- (func $double_16 (result i32)
- (i32.mul
- (i32.const 2)
- (call $get_16))
- )
-
- ;; Досі ми не могли що-небудь вивести на консоль і не мали доступу
- ;; до високорівневої математики (степеневі функції, обрахунок експоненти або тригонометрія).
- ;; Більше того, ми навіть не могли викликати WASM функції у Javascript!
- ;; Виклик цих функцій у WebAssembly залежить від того,
- ;; де ми знаходимось - чи це Node.js, чи середовище браузера.
-
- ;; Якщо ми у Node.js, то потрібно виконати два кроки. По-перше, ми маємо сконвертувати
- ;; текстове представлення WASM у справжній код webassembly.
- ;; Наприклад, ось так (Binaryen):
-
- ;; wasm-as learn-wasm.wast -o learn-wasm.wasm
-
- ;; Давай також застосуємо оптимізації:
-
- ;; wasm-opt learn-wasm.wasm -o learn-wasm.opt.wasm -O3 --rse
-
- ;; Тепер наш скомпільований WebAssembly можна завантажити у Node.js:
- ;; const fs = require('fs')
- ;; const instantiate = async function (inFilePath, _importObject) {
- ;; var importObject = {
- ;; console: {
- ;; log: (x) => console.log(x),
- ;; },
- ;; math: {
- ;; cos: (x) => Math.cos(x),
- ;; }
- ;; }
- ;; importObject = Object.assign(importObject, _importObject)
- ;;
- ;; var buffer = fs.readFileSync(inFilePath)
- ;; var module = await WebAssembly.compile(buffer)
- ;; var instance = await WebAssembly.instantiate(module, importObject)
- ;; return instance.exports
- ;; }
- ;;
- ;; const main = function () {
- ;; var wasmExports = await instantiate('learn-wasm.wasm')
- ;; wasmExports.print_args(1, 0)
- ;; }
-
- ;; Цей код зчитує функції з importObject
- ;; (вказано у асинхронній JavaScript функції instantiate), а потім експортує функцію
- ;; "print_args", яку ми викликаємо у Node.js
-
- (import "console" "log" (func $print_i32 (param i32)))
- (import "math" "cos" (func $cos (param f64) (result f64)))
-
- (func $print_args (param $arg0 i32) (param $arg1 i32)
- (call $print_i32 (local.get $arg0))
- (call $print_i32 (local.get $arg1))
- )
- (export "print_args" (func $print_args))
-
- ;; Завантаження даних з пам'яті WebAssembly.
- ;; Наприклад, ми хочемо порахувати cos для елементів Javascript масиву.
- ;; Нам потрібно отримати доступ до масиву і можливість ітерувати по ньому.
- ;; У прикладі нижче ми змінимо існуючий масив.
- ;; f64.load і f64.store приймають адресу числа у пам'яті *у байтах*.
- ;; Для того, щоб отримати доступ до 3-го елементу масиву, ми маємо передати щось
- ;; накшталт (i32.mul (i32.const 8) (i32.const 2)) у функцію f64.store.
-
- ;; У JavaScript ми викличемо `apply_cos64` таким чином
- ;; (використаємо функцію instantiate з попереднього прикладу):
- ;;
- ;; const main = function () {
- ;; var wasm = await instantiate('learn-wasm.wasm')
- ;; var n = 100
- ;; const memory = new Float64Array(wasm.memory.buffer, 0, n)
- ;; for (var i=0; i<n; i++) {
- ;; memory[i] = i;
- ;; }
- ;; wasm.apply_cos64(n)
- ;; }
- ;;
- ;; Ця функція не буде працювати, якщо ми виділимо пам'ять для (створимо) Float32Array у JavaScript.
-
- (memory (export "memory") 100)
-
- (func $apply_cos64 (param $array_length i32)
- ;; визначаємо змінну циклу або лічильник
- (local $idx i32)
- ;; визначаємо змінну для доступу до пам'яті
- (local $idx_bytes i32)
- ;; константа - кількість байтів у числі типу f64.
- (local $bytes_per_double i32)
-
- ;; визначаємо змінну, яка зберігатиме значення з пам'яті
- (local $temp_f64 f64)
-
- (local.set $idx (i32.const 0))
- (local.set $idx_bytes (i32.const 0)) ;; не обов'язково
- (local.set $bytes_per_double (i32.const 8))
-
- (block
- (loop
- ;; записуємо у idx_bytes необхідне зміщення в пам'яті - для поточного числа.
- (local.set $idx_bytes (i32.mul (local.get $idx) (local.get $bytes_per_double)))
-
- ;; отримуємо число з пам'яті (за зміщенням):
- (local.set $temp_f64 (f64.load (local.get $idx_bytes)))
-
- ;; рахуємо cos:
- (local.set $temp_64 (call $cos (local.get $temp_64)))
-
- ;; тепер зберігаємо результат обчислень у пам'ять:
- (f64.store
- (local.get $idx_bytes)
- (local.get $temp_64))
-
- ;; або робимо все за один крок (альтернативний код)
- (f64.store
- (local.get $idx_bytes)
- (call $cos
- (f64.load
- (local.get $idx_bytes))))
-
- ;; збільшуємо лічильник на одиницю (інкремент)
- (local.set $idx (i32.add (local.get $idx) (i32.const 1)))
-
- ;; якщо лічильник дорівнює довжині масиву, то завершуємо цикл
- (br_if 1 (i32.eq (local.get $idx) (local.get $array_length)))
- (br 0)
- )
- )
- )
- (export "apply_cos64" (func $apply_cos64))
-)
-
-```