diff options
author | Oleh Hromiak <o.a.gromyak@gmail.com> | 2019-10-07 22:35:03 +0300 |
---|---|---|
committer | Oleh Hromiak <o.a.gromyak@gmail.com> | 2019-10-07 22:35:03 +0300 |
commit | 3024f90a397cfef7e51577d232417b8f753b771d (patch) | |
tree | e4d95d9946e357b8d14a054fa49035712dcd82d4 /uk-ua/wasm.html.markdown | |
parent | f7a4c3ed54983fb3e632d0d5e36215606f2a9f1e (diff) |
Fix [wasm/ua] filename
Diffstat (limited to 'uk-ua/wasm.html.markdown')
-rw-r--r-- | uk-ua/wasm.html.markdown | 225 |
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)) -) - -``` |