forked from AbleOS/holey-bytes
fixing sizeof not storing values
This commit is contained in:
parent
af147b3cb6
commit
c9b85f9004
|
@ -12,9 +12,9 @@ async function getHbcInstance() {
|
||||||
|
|
||||||
const stack_pointer_offset = 1 << 20;
|
const stack_pointer_offset = 1 << 20;
|
||||||
|
|
||||||
/** @param {WebAssembly.Instance} instance @param {Uint8Array} code @param {number} fuel
|
/** @param {WebAssembly.Instance} instance @param {Post[]} packages @param {number} fuel
|
||||||
* @returns {string} */
|
* @returns {string} */
|
||||||
function compileCode(instance, code, fuel) {
|
function compileCode(instance, packages, fuel) {
|
||||||
let {
|
let {
|
||||||
INPUT, INPUT_LEN,
|
INPUT, INPUT_LEN,
|
||||||
LOG_MESSAGES, LOG_MESSAGES_LEN,
|
LOG_MESSAGES, LOG_MESSAGES_LEN,
|
||||||
|
@ -30,9 +30,8 @@ function compileCode(instance, code, fuel) {
|
||||||
&& typeof compile_and_run === "function"
|
&& typeof compile_and_run === "function"
|
||||||
)) never();
|
)) never();
|
||||||
|
|
||||||
const dw = new DataView(memory.buffer);
|
const codeLength = packPosts(packages, new DataView(memory.buffer, INPUT.value));
|
||||||
dw.setUint32(INPUT_LEN.value, code.length, true);
|
new DataView(memory.buffer).setUint32(INPUT_LEN.value, codeLength, true);
|
||||||
new Uint8Array(memory.buffer, INPUT.value).set(code);
|
|
||||||
|
|
||||||
runWasmFunction(instance, compile_and_run, fuel);
|
runWasmFunction(instance, compile_and_run, fuel);
|
||||||
return bufToString(memory, LOG_MESSAGES, LOG_MESSAGES_LEN);
|
return bufToString(memory, LOG_MESSAGES, LOG_MESSAGES_LEN);
|
||||||
|
@ -111,19 +110,16 @@ function runWasmFunction(instance, func, ...args) {
|
||||||
* @property {string} path
|
* @property {string} path
|
||||||
* @property {string} code */
|
* @property {string} code */
|
||||||
|
|
||||||
/** @param {Post[]} posts @returns {Uint8Array} */
|
/** @param {Post[]} posts @param {DataView} view @returns {number} */
|
||||||
function packPosts(posts) {
|
function packPosts(posts, view) {
|
||||||
let len = 0; for (const post of posts) len += 2 + post.path.length + 2 + post.code.length;
|
const enc = new TextEncoder(), buf = new Uint8Array(view.buffer, view.byteOffset);
|
||||||
|
let len = 0; for (const post of posts) {
|
||||||
const buf = new Uint8Array(len), view = new DataView(buf.buffer), enc = new TextEncoder();
|
|
||||||
len = 0; for (const post of posts) {
|
|
||||||
view.setUint16(len, post.path.length, true); len += 2;
|
view.setUint16(len, post.path.length, true); len += 2;
|
||||||
buf.set(enc.encode(post.path), len); len += post.path.length;
|
buf.set(enc.encode(post.path), len); len += post.path.length;
|
||||||
view.setUint16(len, post.code.length, true); len += 2;
|
view.setUint16(len, post.code.length, true); len += 2;
|
||||||
buf.set(enc.encode(post.code), len); len += post.code.length;
|
buf.set(enc.encode(post.code), len); len += post.code.length;
|
||||||
}
|
}
|
||||||
|
return len;
|
||||||
return buf;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @param {WebAssembly.Memory} mem
|
/** @param {WebAssembly.Memory} mem
|
||||||
|
@ -146,35 +142,98 @@ function wireUp(target) {
|
||||||
bindCodeEdit(target);
|
bindCodeEdit(target);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @type {{ [key: string]: (content: string) => Promise<string> | string }} */
|
const importRe = /@use\s*\(\s*"(([^"]|\\")+)"\s*\)/g;
|
||||||
const applyFns = {
|
/** @param {string} code @param {string[]} matches @returns {string[]} */
|
||||||
timestamp: (content) => new Date(parseInt(content) * 1000).toLocaleString(),
|
function findImports(code, matches) {
|
||||||
fmt: (content) => getFmtInstance().then(i => modifyCode(i, content, "fmt") ?? "invalid code"),
|
matches.length = 0;
|
||||||
};
|
for (const match of code.matchAll(importRe)) {
|
||||||
|
matches.push(match[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
matches.sort();
|
||||||
|
|
||||||
|
let c = 0;
|
||||||
|
for (let i = 1; i < matches.length; i++) {
|
||||||
|
if (matches[c] != matches[i]) {
|
||||||
|
matches[++c] = matches[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
matches.length = Math.min(matches.length, c + 1);
|
||||||
|
|
||||||
|
return matches;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/** @param {HTMLElement} target */
|
/** @param {HTMLElement} target */
|
||||||
async function bindCodeEdit(target) {
|
async function bindCodeEdit(target) {
|
||||||
const edit = target.querySelector("#code-edit");
|
const edit = target.querySelector("#code-edit");
|
||||||
if (!(edit instanceof HTMLTextAreaElement)) return;
|
if (!(edit instanceof HTMLTextAreaElement)) return;
|
||||||
|
|
||||||
const codeSize = target.querySelector("#code-size");
|
const codeSize = target.querySelector("#code-size");
|
||||||
if (!(codeSize instanceof HTMLSpanElement)) never();
|
const errors = target.querySelector("#compiler-output");
|
||||||
|
if (!(true
|
||||||
|
&& codeSize instanceof HTMLSpanElement
|
||||||
|
&& errors instanceof HTMLPreElement
|
||||||
|
)) never();
|
||||||
|
|
||||||
const MAX_CODE_SIZE = parseInt(codeSize.innerHTML);
|
const MAX_CODE_SIZE = parseInt(codeSize.innerHTML);
|
||||||
if (Number.isNaN(MAX_CODE_SIZE)) never();
|
if (Number.isNaN(MAX_CODE_SIZE)) never();
|
||||||
const errors = target.querySelector("#compiler-output");
|
|
||||||
if (!(errors instanceof HTMLPreElement)) never();
|
|
||||||
|
|
||||||
const hbc = await getHbcInstance();
|
|
||||||
const fmt = await getFmtInstance();
|
|
||||||
|
|
||||||
|
const hbc = await getHbcInstance(), fmt = await getFmtInstance();
|
||||||
|
const prevImports = [];
|
||||||
|
const matches = [];
|
||||||
|
/**@type{Post[]}*/
|
||||||
|
const packages = [{ path: "local.hb", code: "" }];
|
||||||
const debounce = 100;
|
const debounce = 100;
|
||||||
|
/**@type{AbortController|undefined}*/
|
||||||
|
let cancelation = undefined;
|
||||||
let timeout = 0;
|
let timeout = 0;
|
||||||
|
|
||||||
edit.addEventListener("input", () => {
|
edit.addEventListener("input", () => {
|
||||||
if (timeout) clearTimeout(timeout);
|
if (timeout) clearTimeout(timeout);
|
||||||
timeout = setTimeout(() => {
|
timeout = setTimeout(() => {
|
||||||
const buf = packPosts([
|
prevImports.length = 0; prevImports.push(...matches);
|
||||||
{ path: "local.hb", code: edit.value },
|
const imports = findImports(edit.value, matches);
|
||||||
]);
|
let changed = imports.length !== prevImports.length;
|
||||||
errors.textContent = compileCode(hbc, buf, 1);
|
for (let i = 0; i < imports.length && !changed; i++) {
|
||||||
|
changed ||= imports[i] !== prevImports[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (changed && imports.length !== 0) {
|
||||||
|
if (cancelation) cancelation.abort();
|
||||||
|
cancelation = new AbortController();
|
||||||
|
errors.textContent = "fetching: " + imports.join(", ");
|
||||||
|
fetch(`/code`, {
|
||||||
|
method: "POST",
|
||||||
|
signal: cancelation.signal,
|
||||||
|
headers: { "Content-Type": "application/json" },
|
||||||
|
body: JSON.stringify(imports),
|
||||||
|
}).then(async e => {
|
||||||
|
try {
|
||||||
|
const json = await e.json();
|
||||||
|
if (e.status == 200) {
|
||||||
|
packages.length = 1;
|
||||||
|
packages.push(...json);
|
||||||
|
cancelation = undefined;
|
||||||
|
edit.dispatchEvent(new InputEvent("input"));
|
||||||
|
} else {
|
||||||
|
errors.textContent = "failed to fetch: " + json.join(", ");
|
||||||
|
}
|
||||||
|
} catch (er) {
|
||||||
|
errors.textContent = "completely failed to fetch ("
|
||||||
|
+ e.status + "): " + imports.join(", ");
|
||||||
|
console.error(e);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cancelation && imports.length !== 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
packages[0].code = edit.value;
|
||||||
|
|
||||||
|
errors.textContent = compileCode(hbc, packages, 1);
|
||||||
const minified_size = modifyCode(fmt, edit.value, "minify")?.length;
|
const minified_size = modifyCode(fmt, edit.value, "minify")?.length;
|
||||||
if (minified_size) {
|
if (minified_size) {
|
||||||
codeSize.textContent = (MAX_CODE_SIZE - minified_size) + "";
|
codeSize.textContent = (MAX_CODE_SIZE - minified_size) + "";
|
||||||
|
@ -187,6 +246,11 @@ async function bindCodeEdit(target) {
|
||||||
edit.dispatchEvent(new InputEvent("input"));
|
edit.dispatchEvent(new InputEvent("input"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @type {{ [key: string]: (content: string) => Promise<string> | string }} */
|
||||||
|
const applyFns = {
|
||||||
|
timestamp: (content) => new Date(parseInt(content) * 1000).toLocaleString(),
|
||||||
|
fmt: (content) => getFmtInstance().then(i => modifyCode(i, content, "fmt") ?? "invalid code"),
|
||||||
|
};
|
||||||
/** @param {HTMLElement} target */
|
/** @param {HTMLElement} target */
|
||||||
function execApply(target) {
|
function execApply(target) {
|
||||||
for (const elem of target.querySelectorAll('[apply]')) {
|
for (const elem of target.querySelectorAll('[apply]')) {
|
||||||
|
@ -268,8 +332,7 @@ if (window.location.hostname === 'localhost') {
|
||||||
path: "foo.hb",
|
path: "foo.hb",
|
||||||
code: "main:=fn():int{return 42}",
|
code: "main:=fn():int{return 42}",
|
||||||
}];
|
}];
|
||||||
const buf = packPosts(posts);
|
const res = compileCode(await getHbcInstance(), posts, 1) ?? never();
|
||||||
const res = compileCode(await getHbcInstance(), buf, 1) ?? never();
|
|
||||||
const expected = "exit code: 42\n";
|
const expected = "exit code: 42\n";
|
||||||
if (expected != res) console.error(expected, res);
|
if (expected != res) console.error(expected, res);
|
||||||
}
|
}
|
||||||
|
|
|
@ -174,7 +174,7 @@ main := fn(): int {
|
||||||
return 9001
|
return 9001
|
||||||
}
|
}
|
||||||
|
|
||||||
finst := Ty2.{ty: .{a: 4, b: 1}, c: 3}
|
finst := Ty2.{ty: .{a: @bitcast(@sizeof(u32)), b: 1}, c: 3}
|
||||||
inst := odher_pass(finst)
|
inst := odher_pass(finst)
|
||||||
if inst.c == 3 {
|
if inst.c == 3 {
|
||||||
return pass(&inst.ty)
|
return pass(&inst.ty)
|
||||||
|
|
|
@ -1004,11 +1004,11 @@ impl Codegen {
|
||||||
}
|
}
|
||||||
E::Directive { name: "sizeof", args: [ty], .. } => {
|
E::Directive { name: "sizeof", args: [ty], .. } => {
|
||||||
let ty = self.ty(ty);
|
let ty = self.ty(ty);
|
||||||
return Some(Value::imm(self.tys.size_of(ty) as _));
|
Some(Value::imm(self.tys.size_of(ty) as _))
|
||||||
}
|
}
|
||||||
E::Directive { name: "alignof", args: [ty], .. } => {
|
E::Directive { name: "alignof", args: [ty], .. } => {
|
||||||
let ty = self.ty(ty);
|
let ty = self.ty(ty);
|
||||||
return Some(Value::imm(self.tys.align_of(ty) as _));
|
Some(Value::imm(self.tys.align_of(ty) as _))
|
||||||
}
|
}
|
||||||
E::Directive { name: "intcast", args: [val], .. } => {
|
E::Directive { name: "intcast", args: [val], .. } => {
|
||||||
let Some(ty) = ctx.ty else {
|
let Some(ty) = ctx.ty else {
|
||||||
|
|
|
@ -1389,7 +1389,6 @@ fn test_parse_files(ident: &'static str, input: &'static str) -> (Vec<parser::As
|
||||||
last_module_name = module_name;
|
last_module_name = module_name;
|
||||||
last_start = i + m.len() + module_name.len() + 1;
|
last_start = i + m.len() + module_name.len() + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if last_module_name.ends_with(".hb") {
|
if last_module_name.ends_with(".hb") {
|
||||||
fmt::test::format(ident, input[last_start..].trim());
|
fmt::test::format(ident, input[last_start..].trim());
|
||||||
module_map.push((last_module_name, &input[last_start..]));
|
module_map.push((last_module_name, &input[last_start..]));
|
||||||
|
|
Loading…
Reference in a new issue