Invert event loop
This commit is contained in:
@@ -97,6 +97,36 @@ impl<'a> Emitter<'a> {
|
||||
let value = operand(self, FIRST_ARG as usize, self.rep(&self.cache.protos[kind as usize]));
|
||||
(format!("({} = {value}, (undefined_t){{0}})", proto_global(kind)), Type::Undefined)
|
||||
}
|
||||
|
||||
// Keeps the fn where `jsrt_complete` finds it
|
||||
Code::HostLink => {
|
||||
let value = operand(self, FIRST_ARG as usize, self.rep(&self.cache.host_complete));
|
||||
(format!("({HOST_COMPLETE_GLOBAL} = {value}, (undefined_t){{0}})"), Type::Undefined)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// The body of `jsrt_complete(h)`: a call of the fn that the stdlib links
|
||||
/// for the host, with op `h` (see `infer::host_calls()`)
|
||||
pub(super) fn host_complete(&mut self) -> String {
|
||||
let ty = self.cache.host_complete.clone();
|
||||
let mut out = String::new();
|
||||
|
||||
if ty == Type::Unknown {
|
||||
return out;
|
||||
}
|
||||
|
||||
let rep = self.rep(&ty);
|
||||
let operands = [(HOST_COMPLETE_GLOBAL.to_string(), rep), ("(undefined_t){0}".into(), Rep::Undefined), ("h".into(), Rep::Int)];
|
||||
|
||||
self.dispatch(HOST_COMPLETE_GLOBAL, &ty, "jsrt_type_error();", &mut out, |e, member, callee, rep| {
|
||||
let Type::Obj(cell) = member else { return None };
|
||||
let mut operands = operands.clone();
|
||||
operands[0] = (callee.into(), rep);
|
||||
let arg_types = [member.clone(), Type::Undefined, Type::Int];
|
||||
Some(format!("{};", e.call_code(cell.code()?, HOST_COMPLETE, &arg_types, &operands).0))
|
||||
});
|
||||
|
||||
out
|
||||
}
|
||||
}
|
||||
|
||||
@@ -121,6 +121,7 @@ pub(super) fn cell_sig(cell: &Cell, class: &HashMap<Cell, CellNum>, sig: &mut Ve
|
||||
Code::Fn(id) => [1, id as u32],
|
||||
Code::Native(id) => [2, id as u32],
|
||||
Code::ProtoLink(kind) => [3, kind as u32],
|
||||
Code::HostLink => [5, 0],
|
||||
}),
|
||||
ObjKind::Array { elems } => {
|
||||
sig.push(4);
|
||||
|
||||
@@ -69,6 +69,7 @@ impl<'a> Emitter<'a> {
|
||||
JsValue::String(s) => self.string_lit(&js_string_text(s)),
|
||||
JsValue::NativeFn(id) => format!("&{}", builtin_name(self.num(self.cache.builtin(Code::Native(*id))))),
|
||||
JsValue::ProtoLink(kind) => format!("&{}", builtin_name(self.num(self.cache.builtin(Code::ProtoLink(*kind))))),
|
||||
JsValue::HostLink => format!("&{}", builtin_name(self.num(self.cache.builtin(Code::HostLink)))),
|
||||
_ => format!("({}){{0}}", self.c_type(rep)),
|
||||
},
|
||||
Undefined | Null => format!("({}){{0}}", self.c_type(rep)),
|
||||
|
||||
@@ -18,7 +18,7 @@ use std::{
|
||||
|
||||
use crate::{
|
||||
infer::{
|
||||
HOST, InferResult, Place, TypeCache,
|
||||
HOST, HOST_COMPLETE, InferResult, Place, TypeCache,
|
||||
cells::{Cell, Code, LENGTH_FIELD, ObjKind, read_value},
|
||||
types::Type,
|
||||
},
|
||||
@@ -94,11 +94,16 @@ pub fn emit(fns: &[RegFn], cache: &TypeCache, atoms: &[Atom]) -> String {
|
||||
}
|
||||
}
|
||||
|
||||
// The walks that the code calls, from the entry. The host calls the entry
|
||||
// with nothing: its env and `this` are undefined
|
||||
if cache.host_complete != Type::Unknown {
|
||||
let _ = writeln!(statics, "static {} {HOST_COMPLETE_GLOBAL};", e.c_type(e.rep(&cache.host_complete)));
|
||||
}
|
||||
|
||||
// The walks that the code calls, from the host's calls. The host calls the
|
||||
// entry with nothing: its env and `this` are undefined
|
||||
let entry = cache.find(fns.len() - 1, HOST, &[], fns);
|
||||
let entry_args = vec!["(undefined_t){0}"; cache.walks[entry].req.arg_types.len()].join(", ");
|
||||
e.use_walk(entry);
|
||||
let complete = e.host_complete();
|
||||
|
||||
let mut fn_protos = String::new();
|
||||
let mut bodies = String::new();
|
||||
@@ -127,7 +132,9 @@ pub fn emit(fns: &[RegFn], cache: &TypeCache, atoms: &[Atom]) -> String {
|
||||
e.helper_protos,
|
||||
e.helper_defs
|
||||
);
|
||||
let _ = writeln!(out, "int main(void) {{\n{init} {}({entry_args});\n return 0;\n}}", e.fn_name(entry));
|
||||
// What the host calls (see `lib/rt/jsrt.h`)
|
||||
let _ = writeln!(out, "void jsrt_start(void) {{\n{init} {}({entry_args});\n}}\n", e.fn_name(entry));
|
||||
let _ = writeln!(out, "void jsrt_complete(int32_t h) {{\n{complete}}}");
|
||||
out
|
||||
}
|
||||
|
||||
@@ -287,6 +294,9 @@ fn builtin_name(id: CellNum) -> String {
|
||||
format!("b{id}")
|
||||
}
|
||||
|
||||
/// The global that holds what the host calls when an IO op completes
|
||||
const HOST_COMPLETE_GLOBAL: &str = "jsrt_host_complete";
|
||||
|
||||
fn proto_global(kind: ProtoOf) -> String {
|
||||
format!("proto_{kind:?}").to_lowercase()
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user