Simplify async_sequence function calls.

This commit is contained in:
Condorra 2024-09-21 23:25:24 +10:00
parent 855ecfc13a
commit 0214897a91
3 changed files with 106 additions and 220 deletions

View File

@ -1,8 +1,10 @@
use self::{frameroutes::*, frames::*, muds::*};
use anyhow::Error;
use piccolo::{
async_callback::Locals, meta_ops::MetaResult, Callback, Closure, Context, Executor,
ExternError, FromValue, Function, Lua, MetaMethod, Stack, StashedExecutor, StashedFunction,
async_callback::{AsyncSequence, Locals},
meta_ops::{self, MetaResult},
Callback, Closure, Context, Executor, ExternError, FromValue, Function, IntoValue, Lua,
MetaMethod, Stack, StashedError, StashedExecutor, StashedFunction, StashedTable, StashedValue,
Table, Value, Variadic,
};
use yew::UseStateSetter;
@ -140,15 +142,16 @@ pub fn install_lua_globals(
};
}
register_command!(alias);
register_command!(close_mud);
register_command!(connect_mud);
register_command!(delete_mud);
register_command!(echo);
register_command!(echo_frame);
register_command!(echo_frame_raw);
register_command!(connect_mud);
register_command!(delete_mud);
register_command!(close_mud);
register_command!(sendmud_raw);
register_command!(hsplit);
register_command!(panel_merge);
register_command!(sendmud_raw);
register_command!(vsplit);
ctx.set_global("commands", cmd_table);
let info_table = Table::new(&ctx);
@ -289,3 +292,41 @@ pub fn prep_metaop_call<'gc, const N: usize>(
}
}
}
pub async fn call_checking_metatable<'gc, 'a>(
seq: &mut AsyncSequence,
obj: StashedTable,
func_name: &'static str,
arguments: &[StashedValue],
) -> Result<(), StashedError> {
let call = seq.try_enter(|ctx, locals, _execution, mut stack| {
let obj = locals.fetch(&obj);
stack.consume(ctx)?;
Ok(prep_metaop_call(
ctx,
stack,
locals,
meta_ops::index(
ctx,
obj.into_value(ctx),
ctx.intern_static(func_name.as_bytes()).into_value(ctx),
)?,
))
})?;
if let Some(call) = call {
seq.call(&call, 0).await?;
}
let call = seq.try_enter(|ctx, locals, _, mut stack| {
let value = stack
.pop_back()
.ok_or_else(|| anyhow::Error::msg("Index didn't return value"))?;
stack.consume(ctx)?;
stack.push_back(locals.fetch(&obj).into_value(ctx));
for arg in arguments {
stack.push_back(locals.fetch(arg));
}
Ok(locals.stash(&ctx, Function::from_value(ctx, value)?))
})?;
seq.call(&call, 0).await?;
Ok(())
}

View File

@ -4,13 +4,23 @@ use crate::{
};
use gc_arena::{Gc, Rootable};
use piccolo::{
self, async_sequence, meta_ops, Callback, CallbackReturn, Context, FromValue, Function,
IntoValue, SequenceReturn, Table, UserData, Value, Variadic,
self, async_sequence, Callback, CallbackReturn, Context, FromValue, Function, IntoValue,
SequenceReturn, Table, UserData, Value, Variadic,
};
use std::{rc::Rc, str};
use yew::UseStateSetter;
use super::prep_metaop_call;
use super::call_checking_metatable;
pub fn alias<'gc, 'a>(
ctx: Context<'gc>,
_global_memo: &'a GlobalMemoCell,
_global_layout: &'a UseStateSetter<GlobalLayoutCell>,
) -> Callback<'gc> {
Callback::from_fn(&ctx, move |_ctx, _ex, _stack| {
Ok(piccolo::CallbackReturn::Return)
})
}
pub fn echo_frame_raw<'gc, 'a>(
ctx: Context<'gc>,
@ -185,38 +195,12 @@ pub fn ensure_frame_instance<'gc>(ctx: Context<'gc>, frame: &TermFrame) -> Callb
frames.set(ctx, frame.0 as i64, frame_tab)?;
// Call frame_tab:new(frame) to setup.
let frame = frame.clone();
let frame = intern_id::<TermFrame>(ctx, frame.clone());
let seq = async_sequence(&ctx, move |locals, mut seq| {
let frame_tab = locals.stash(&ctx, frame_tab);
let frame = locals.stash(&ctx, frame);
async move {
let call = seq.try_enter(|ctx, locals, _execution, mut stack| {
let frame_tab = locals.fetch(&frame_tab);
stack.consume(ctx)?;
Ok(prep_metaop_call(
ctx,
stack,
locals,
meta_ops::index(
ctx,
frame_tab.into_value(ctx),
ctx.intern_static(b"new").into_value(ctx),
)?,
))
})?;
if let Some(call) = call {
seq.call(&call, 0).await?;
}
let call = seq.try_enter(|ctx, locals, _, mut stack| {
let value = stack
.pop_back()
.ok_or_else(|| anyhow::Error::msg("Index didn't return value"))?;
stack.consume(ctx)?;
stack.push_back(locals.fetch(&frame_tab).into_value(ctx));
stack.push_back(intern_id::<TermFrame>(ctx, frame.clone()));
Ok(locals.stash(&ctx, Function::from_value(ctx, value)?))
})?;
seq.call(&call, 0).await?;
call_checking_metatable(&mut seq, frame_tab, "new", &[frame]).await?;
Ok(SequenceReturn::Return)
}
});
@ -250,35 +234,9 @@ pub(super) fn send_command_to_frame<'gc>(ctx: Context<'gc>) -> Callback<'gc> {
let (frame, line): (Table, piccolo::String) = stack.consume(ctx)?;
let seq = async_sequence(&ctx, |locals, mut seq| {
let frame = locals.stash(&ctx, frame);
let line = locals.stash(&ctx, line);
let line = locals.stash(&ctx, line.into_value(ctx));
async move {
let call = seq.try_enter(|ctx, locals, _execution, stack| {
let frame = locals.fetch(&frame);
Ok(prep_metaop_call(
ctx,
stack,
locals,
meta_ops::index(
ctx,
frame.into_value(ctx),
ctx.intern_static(b"input").into_value(ctx),
)?,
))
})?;
if let Some(call) = call {
seq.call(&call, 0).await?;
}
let call = seq.try_enter(|ctx, locals, _, mut stack| {
let value = stack
.pop_back()
.ok_or_else(|| anyhow::Error::msg("Index didn't return value"))?;
stack.consume(ctx)?;
stack.push_back(locals.fetch(&frame).into_value(ctx));
stack.push_back(locals.fetch(&line).into_value(ctx));
Ok(locals.stash(&ctx, Function::from_value(ctx, value)?))
})?;
seq.call(&call, 0).await?;
call_checking_metatable(&mut seq, frame, "input", &[line]).await?;
Ok(SequenceReturn::Return)
}
});
@ -297,6 +255,7 @@ pub(super) fn frame_input<'gc>(ctx: Context<'gc>, _global_memo: &GlobalMemoCell)
let line: Value = stack
.pop_front()
.ok_or_else(|| anyhow::Error::msg("classes.frame:new missing line!"))?;
stack.consume(ctx)?;
let linked_mud = frame_tab.get_value(ctx, ctx.intern_static(b"linked_mud"));
if linked_mud.is_nil() {
@ -309,34 +268,7 @@ pub(super) fn frame_input<'gc>(ctx: Context<'gc>, _global_memo: &GlobalMemoCell)
let linked_mud = locals.stash(&ctx, linked_mud);
let line = locals.stash(&ctx, line);
async move {
let call = seq.try_enter(|ctx, locals, _execution, mut stack| {
let linked_mud = locals.fetch(&linked_mud);
stack.consume(ctx)?;
Ok(prep_metaop_call(
ctx,
stack,
locals,
meta_ops::index(
ctx,
linked_mud.into_value(ctx),
ctx.intern_static(b"mudinput_line").into_value(ctx),
)?,
))
})?;
if let Some(call) = call {
seq.call(&call, 0).await?;
}
let call = seq.try_enter(|ctx, locals, _, mut stack| {
let value = stack
.pop_back()
.ok_or_else(|| anyhow::Error::msg("Index didn't return value"))?;
stack.consume(ctx)?;
stack.push_back(locals.fetch(&linked_mud).into_value(ctx));
stack.push_back(locals.fetch(&line));
Ok(locals.stash(&ctx, Function::from_value(ctx, value)?))
})?;
seq.call(&call, 0).await?;
call_checking_metatable(&mut seq, linked_mud, "mudinput_line", &[line]).await?;
Ok(SequenceReturn::Return)
}
});

View File

@ -1,8 +1,8 @@
use anyhow::Error;
use gc_arena::{Gc, Rootable};
use piccolo::{
self, async_sequence, meta_ops, Callback, CallbackReturn, Context, FromValue, Function,
IntoValue, SequenceReturn, StashedValue, Table, UserData, Value,
self, async_sequence, Callback, CallbackReturn, Context, FromValue, Function, IntoValue,
SequenceReturn, StashedTable, StashedValue, Table, UserData, Value,
};
use wasm_bindgen::JsValue;
use web_sys::console;
@ -15,7 +15,7 @@ use crate::{
GlobalLayoutCell, GlobalMemoCell,
};
use super::{prep_metaop_call, try_unwrap_frame, LuaState};
use super::{call_checking_metatable, try_unwrap_frame, LuaState};
fn try_unwrap_socketid<'gc>(
ctx: Context<'gc>,
@ -192,29 +192,7 @@ pub(super) fn connect_mud<'gc>(
let seq = async_sequence(&ctx, |locals, mut seq| {
let conntab = locals.stash(&ctx, conntab);
async move {
let call = seq.try_enter(|ctx, locals, _execution, mut stack| {
let conntab = locals.fetch(&conntab);
stack.consume(ctx)?;
Ok(prep_metaop_call(
ctx,
stack,
locals,
meta_ops::index(
ctx,
conntab.into_value(ctx),
ctx.intern_static(b"new").into_value(ctx),
)?,
))
})?;
if let Some(call) = call {
seq.call(&call, 0).await?;
}
let new_fn = seq.try_enter(|ctx, locals, _execution, mut stack| {
let new_fn: Function = stack.consume(ctx)?;
stack.push_back(locals.fetch(&conntab).into_value(ctx));
Ok(locals.stash(&ctx, new_fn))
})?;
seq.call(&new_fn, 0).await?;
call_checking_metatable(&mut seq, conntab, "new", &[]).await?;
Ok(SequenceReturn::Return)
}
});
@ -310,7 +288,7 @@ pub(super) fn mudoutput<'gc>(ctx: Context<'gc>, _global_memo: &GlobalMemoCell) -
.as_bytes();
let mut cur_buf: Vec<u8> = [buf, output].concat();
let mut fns: Vec<(&'static [u8], Vec<Value>)> = vec![];
let mut fns: Vec<(&'static str, Vec<Value>)> = vec![];
loop {
match parse_telnet_buf(&cur_buf) {
(new_buf, None) => {
@ -318,7 +296,7 @@ pub(super) fn mudoutput<'gc>(ctx: Context<'gc>, _global_memo: &GlobalMemoCell) -
let seq = piccolo::async_sequence(&ctx, |locals, mut seq| {
let conntab = locals.stash(&ctx, conntab);
let fns: Vec<(&'static [u8], Vec<StashedValue>)> = fns
let fns: Vec<(&'static str, Vec<StashedValue>)> = fns
.into_iter()
.map(|fnv| {
(
@ -329,37 +307,13 @@ pub(super) fn mudoutput<'gc>(ctx: Context<'gc>, _global_memo: &GlobalMemoCell) -
.collect();
async move {
for (func_name, params) in fns {
let call =
seq.try_enter(|ctx, locals, _execution, mut stack| {
let conntab = locals.fetch(&conntab);
stack.consume(ctx)?;
Ok(prep_metaop_call(
ctx,
stack,
locals,
meta_ops::index(
ctx,
conntab.into_value(ctx),
ctx.intern_static(func_name).into_value(ctx),
)?,
))
})?;
if let Some(call) = call {
seq.call(&call, 0).await?;
}
let call = seq.try_enter(|ctx, locals, _, mut stack| {
let value = stack.pop_back().ok_or_else(|| {
anyhow::Error::msg("Index didn't return value")
})?;
stack.consume(ctx)?;
stack.push_back(locals.fetch(&conntab).into_value(ctx));
for param in &params {
stack.push_back(locals.fetch(param));
}
Ok(locals.stash(&ctx, Function::from_value(ctx, value)?))
})?;
seq.call(&call, 0).await?;
call_checking_metatable(
&mut seq,
conntab.clone(),
func_name,
&params,
)
.await?;
}
Ok(piccolo::SequenceReturn::Return)
}
@ -371,30 +325,30 @@ pub(super) fn mudoutput<'gc>(ctx: Context<'gc>, _global_memo: &GlobalMemoCell) -
cur_buf = new_buf;
match cmd {
TelnetOutput::Line(l) => {
fns.push((b"mudoutput_line", vec![ctx.intern(&l).into_value(ctx)]))
fns.push(("mudoutput_line", vec![ctx.intern(&l).into_value(ctx)]))
}
TelnetOutput::Prompt(p) => {
fns.push((b"mudoutput_prompt", vec![ctx.intern(&p).into_value(ctx)]))
fns.push(("mudoutput_prompt", vec![ctx.intern(&p).into_value(ctx)]))
}
TelnetOutput::Nop => {}
TelnetOutput::Break => fns.push((b"mudoutput_break", vec![])),
TelnetOutput::Sync => fns.push((b"mudoutput_sync", vec![])),
TelnetOutput::Interrupt => fns.push((b"mudoutput_interrupt", vec![])),
TelnetOutput::Break => fns.push(("mudoutput_break", vec![])),
TelnetOutput::Sync => fns.push(("mudoutput_sync", vec![])),
TelnetOutput::Interrupt => fns.push(("mudoutput_interrupt", vec![])),
TelnetOutput::AbortOutput => fns.push((b"mudoutput_abort_output", vec![])),
TelnetOutput::AreYouThere => fns.push((b"mudoutput_areyouthere", vec![])),
TelnetOutput::AbortOutput => fns.push(("mudoutput_abort_output", vec![])),
TelnetOutput::AreYouThere => fns.push(("mudoutput_areyouthere", vec![])),
TelnetOutput::Will(v) => {
fns.push((b"mudoutput_will", vec![v.into_value(ctx)]))
fns.push(("mudoutput_will", vec![v.into_value(ctx)]))
}
TelnetOutput::Wont(v) => {
fns.push((b"mudoutput_wont", vec![v.into_value(ctx)]))
fns.push(("mudoutput_wont", vec![v.into_value(ctx)]))
}
TelnetOutput::Do(v) => fns.push((b"mudoutput_do", vec![v.into_value(ctx)])),
TelnetOutput::Do(v) => fns.push(("mudoutput_do", vec![v.into_value(ctx)])),
TelnetOutput::Dont(v) => {
fns.push((b"mudoutput_dont", vec![v.into_value(ctx)]))
fns.push(("mudoutput_dont", vec![v.into_value(ctx)]))
}
TelnetOutput::Subnegotiation(t) => {
fns.push((b"mudoutput_subnegotiation", vec![t.into_value(ctx)]))
fns.push(("mudoutput_subnegotiation", vec![t.into_value(ctx)]))
}
}
}
@ -424,37 +378,18 @@ pub(super) fn mudoutput_line<'gc>(
let frameroutes: Table = mud.get(ctx, "frameroutes")?;
let seq = async_sequence(&ctx, |locals, mut seq| {
let frameroutes: Vec<StashedValue> = frameroutes
let frameroutes: Vec<StashedTable> = frameroutes
.iter()
.map(|fr| locals.stash(&ctx, fr.1))
.filter_map(|fr| {
Table::from_value(ctx, fr.1)
.ok()
.map(|v| locals.stash(&ctx, v))
})
.collect();
let line = locals.stash(&ctx, line);
let line = locals.stash(&ctx, line.into_value(ctx));
async move {
for frameroute in frameroutes {
let call = seq.try_enter(|ctx, locals, _execution, mut stack| {
let frameroute = locals.fetch(&frameroute);
stack.consume(ctx)?;
Ok(prep_metaop_call(
ctx,
stack,
locals,
meta_ops::index(
ctx,
frameroute.into_value(ctx),
ctx.intern_static(b"route").into_value(ctx),
)?,
))
})?;
if let Some(call) = call {
seq.call(&call, 0).await?;
}
let route_fn = seq.try_enter(|ctx, locals, _execution, mut stack| {
let route_fn: Function = stack.consume(ctx)?;
stack.push_back(locals.fetch(&frameroute).into_value(ctx));
stack.push_back(locals.fetch(&line).into_value(ctx));
Ok(locals.stash(&ctx, route_fn))
})?;
seq.call(&route_fn, 0).await?;
call_checking_metatable(&mut seq, frameroute, "route", &[line.clone()]).await?;
}
Ok(SequenceReturn::Return)
}
@ -538,38 +473,16 @@ pub(super) fn new_mud<'gc>(ctx: Context<'gc>, _global_memo: &GlobalMemoCell) ->
);
mud.set(ctx, ctx.intern_static(b"frameroutes"), frameroutes)?;
let curr_frame: Value = ctx
.get_global::<Table>("info")?
.get(ctx, ctx.intern_static(b"current_frame"))?;
// And call new on the frameroute, for the current frame.
let seq = async_sequence(&ctx, |locals, mut seq| {
let frameroute = locals.stash(&ctx, frameroute);
async move {
let call = seq.try_enter(|ctx, locals, _execution, mut stack| {
let frameroute = locals.fetch(&frameroute);
stack.consume(ctx)?;
Ok(prep_metaop_call(
ctx,
stack,
locals,
meta_ops::index(
ctx,
frameroute.into_value(ctx),
ctx.intern_static(b"new").into_value(ctx),
)?,
))
})?;
if let Some(call) = call {
seq.call(&call, 0).await?;
}
let new_fn = seq.try_enter(|ctx, locals, _execution, mut stack| {
let new_fn: Function = stack.consume(ctx)?;
stack.push_back(locals.fetch(&frameroute).into_value(ctx));
stack.push_back(
ctx.get_global::<Table>("info")?
.get(ctx, ctx.intern_static(b"current_frame"))?,
);
Ok(locals.stash(&ctx, new_fn))
})?;
seq.call(&new_fn, 0).await?;
let curr_frame = locals.stash(&ctx, curr_frame);
async move {
call_checking_metatable(&mut seq, frameroute, "new", &[curr_frame]).await?;
Ok(SequenceReturn::Return)
}
});