diff --git a/src/index.ts b/src/index.ts index 8d6800f..dbfe63c 100644 --- a/src/index.ts +++ b/src/index.ts @@ -11,10 +11,8 @@ import { exec } from "child_process"; const input = ` function main() = ( - print("uwu -"); - print("owo -"); + print("\\3AAA\\n"); + print("meow\\n"); ); `; diff --git a/src/lexer.ts b/src/lexer.ts index d93d122..7ec4f2e 100644 --- a/src/lexer.ts +++ b/src/lexer.ts @@ -134,6 +134,7 @@ export function tokenize(input: string): Token[] { break; } case '"': { + const result = []; while (true) { const next = input[i + 1]; span.end++; @@ -141,11 +142,48 @@ export function tokenize(input: string): Token[] { if (next === '"') { break; } + + if (next === "\\") { + span.end++; + i++; + switch (input[i]) { + case "\\": + result.push("\\"); + break; + case '"': + result.push('"'); + break; + case "n": + result.push("\n"); + break; + case "r": + result.push("\r"); + break; + case "t": + result.push("\t"); + break; + case "a": + result.push("\x07"); + break; + case "3": + // device control 3 for callie's big project + result.push("\x13"); + break; + default: + throw new CompilerError( + `invalid escape character: ${input[i]}`, + { start: span.end - 1, end: span.end } + ); + } + continue; + } + + result.push(next); if (next === undefined) { throw new CompilerError(`Unterminated string literal`, span); } } - const value = input.slice(span.start + 1, span.end - 1); + const value = result.join(""); tokens.push({ kind: "lit_string", span, value }); break; } diff --git a/src/lower.ts b/src/lower.ts index 6290670..a196058 100644 --- a/src/lower.ts +++ b/src/lower.ts @@ -112,7 +112,9 @@ export function lower(ast: Ast): wasm.Module { } }); - cx.reservedHeapMemoryStart = (mod.datas[0].init.length & ~0x8) + 0x8; + const HEAP_ALIGN = 0x08; + cx.reservedHeapMemoryStart = + (mod.datas[0].init.length + (HEAP_ALIGN - 1)) & ~(HEAP_ALIGN - 1); addRt(cx, ast); diff --git a/src/wasm/wat.ts b/src/wasm/wat.ts index f1c960a..e39ebc0 100644 --- a/src/wasm/wat.ts +++ b/src/wasm/wat.ts @@ -138,8 +138,14 @@ function printString(s: string, f: Formatter) { function printBinaryString(buf: Uint8Array, f: Formatter) { const parts: string[] = []; for (let i = 0; i < buf.length; i++) { - const idx = buf[i]; - parts.push(`\\${idx.toString(16).padStart(2, "0")}`); + const byte = buf[i]; + const noEscape = + (byte > 0x30 && byte <= 0x5a) || (byte > 0x61 && byte <= 0x71); + if (noEscape) { + parts.push(`${String.fromCharCode(byte)}`); + } else { + parts.push(`\\${byte.toString(16).padStart(2, "0")}`); + } } f.word(`"${parts.join("")}"`);