Skip to content

Commit

Permalink
Implement basic printing strategy
Browse files Browse the repository at this point in the history
  • Loading branch information
dy committed Aug 20, 2023
1 parent 077cd66 commit a1d8140
Show file tree
Hide file tree
Showing 6 changed files with 116 additions and 17 deletions.
2 changes: 1 addition & 1 deletion readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ const tree = [
const str = print(tree, {
indent: ' ', // indentation characters
newline: '\n', // new line charactes
pad: 1, // pad start of each line
pad: '', // pad start of each line with a string
comments: true // keep comments
})
// (func (export "double")
Expand Down
48 changes: 48 additions & 0 deletions src/print.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import parse from './parse.js';

let indent = '', newline = '\n', pad = '', comments = false, _i = 0

export default function print(tree, options = {}) {
if (typeof tree === 'string') tree = parse(tree);

({ indent, newline, pad, comments } = options);
newline ||= ''
pad ||= ''
indent ||= ''

let out = typeof tree[0] === 'string' ? printNode(tree) : tree.map(node => printNode(node)).join(newline)

return out
}

const flats = ['param', 'local', 'global', 'result', 'export']

function printNode(node, level = 0) {
if (!Array.isArray(node)) return node + ''

let content = node[0]

for (let i = 1; i < node.length; i++) {
// new node doesn't need space separator, eg. [x,[y]] -> `x(y)`
if (Array.isArray(node[i])) {
// inline nodes like (param x)(param y)
// (func (export "xxx")..., but not (func (export "a")(param "b")...
if (
flats.includes(node[i][0]) &&
(!Array.isArray(node[i - 1]) || node[i][0] === node[i - 1][0])
) {
if (!Array.isArray(node[i - 1])) content += ` `
} else {
content += newline
if (node[i]) content += indent.repeat(level + 1)
}

content += printNode(node[i], level + 1)
}
else {
content += ` `
content += node[i]
}
}
return `(${content})`
}
15 changes: 2 additions & 13 deletions test/compile.js
Original file line number Diff line number Diff line change
Expand Up @@ -1170,7 +1170,7 @@ t.skip('bench: brownian', async () => {
console.timeEnd('wabt')
})

async function file(path) {
export async function file(path) {
let res = await fetch(path)
let src = await res.text()
return src
Expand All @@ -1183,17 +1183,6 @@ async function runExample(path) {
// const mod = new WebAssembly.Module(buffer)
}

// stub fetch for local purpose
const isNode = typeof global !== 'undefined' && globalThis === global
if (isNode) {
let { readFileSync } = await import('fs')
globalThis.fetch = async path => {
path = `.${path}`
const data = readFileSync(path, 'utf8')
return { text() { return data } }
}
}

console.hex = (d) => console.log((Object(d).buffer instanceof ArrayBuffer ? new Uint8Array(d.buffer) :
typeof d === 'string' ? (new TextEncoder('utf-8')).encode(d) :
new Uint8ClampedArray(d)).reduce((p, c, i, a) => p + (i % 16 === 0 ? i.toString(16).padStart(6, 0) + ' ' : ' ') +
Expand All @@ -1215,7 +1204,7 @@ const hex = (str, ...fields) =>
)

// convert wast code to binary via Wabt
function wat2wasm(code, config) {
export function wat2wasm(code, config) {
let metrics = config ? config.metrics : true
const parsed = wabt.parseWat('inline', code, {})
metrics && console.time('wabt build')
Expand Down
7 changes: 4 additions & 3 deletions test/index.html
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<doctype html>

<script type="importmap">
<script type="importmap">
{
"imports": {
"tst": "../node_modules/tst/tst.js",
Expand All @@ -10,5 +10,6 @@
}
</script>

<script src="./parse.js" type="module"></script>
<script src="./compile.js" type="module"></script>
<script src="./parse.js" type="module"></script>
<script src="./compile.js" type="module"></script>
<script src="./print.js" type="module"></script>
12 changes: 12 additions & 0 deletions test/index.js
Original file line number Diff line number Diff line change
@@ -1,2 +1,14 @@
import './parse.js'
import './compile.js'
import './print.js'

// stub fetch for local purpose
const isNode = typeof global !== 'undefined' && globalThis === global
if (isNode) {
let { readFileSync } = await import('fs')
globalThis.fetch = async path => {
path = `.${path}`
const data = readFileSync(path, 'utf8')
return { text() { return data } }
}
}
49 changes: 49 additions & 0 deletions test/print.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import t, { is, ok, same } from 'tst'
import print from '../src/print.js'
import { wat2wasm, file } from './compile.js'

t.only('print: basics', () => {
const tree = [
'func', ['export', '"double"'], ['param', 'f64', 'f32'], ['param', '$x', 'i32'], ['result', 'f64'],
['f64.mul', ['local.get', 0], ['f64.const', 2]]
]

// minify
const min = print(tree, {
indent: false,
newline: false,
pad: false,
comments: false
})
wat2wasm(min)
is(min, `(func (export "double")(param f64 f32)(param $x i32)(result f64)(f64.mul(local.get 0)(f64.const 2)))`)

// pretty-print
const pretty = print(tree, {
indent: ' ', // indentation characters
newline: '\n', // new line charactes
pad: '', // pad start of each line with a string
comments: true // keep comments
})
wat2wasm(pretty)
is(pretty,
`(func (export "double")
(param f64 f32)(param $x i32)
(result f64)
(f64.mul
(local.get 0)
(f64.const 2)))`)

is(
print(`(import "Math" "random" (func $random (result f32)))`),
`(import \"Math\" \"random\"(func $random (result f32)))`
)
})

t.only('print: dino', async t => {
let src = await file('./example/dino.wat')
const dino = print(src)
console.log(dino)

wat2wasm(dino)
})

0 comments on commit a1d8140

Please sign in to comment.