Make #alias work.
This commit is contained in:
		
							parent
							
								
									ff840c04c2
								
							
						
					
					
						commit
						a215133ea6
					
				@ -3,9 +3,10 @@ use anyhow::Error;
 | 
			
		||||
use piccolo::{
 | 
			
		||||
    async_callback::{AsyncSequence, Locals},
 | 
			
		||||
    meta_ops::{self, MetaResult},
 | 
			
		||||
    stash::Fetchable,
 | 
			
		||||
    Callback, Closure, Context, Executor, ExternError, FromValue, Function, IntoValue, Lua,
 | 
			
		||||
    MetaMethod, Stack, StashedError, StashedExecutor, StashedFunction, StashedTable, StashedValue,
 | 
			
		||||
    Table, Value, Variadic,
 | 
			
		||||
    MetaMethod, Stack, StashedError, StashedExecutor, StashedFunction, StashedValue, Table, Value,
 | 
			
		||||
    Variadic,
 | 
			
		||||
};
 | 
			
		||||
use yew::UseStateSetter;
 | 
			
		||||
 | 
			
		||||
@ -147,11 +148,21 @@ pub fn install_lua_globals(
 | 
			
		||||
                        .map_err(|_| Error::msg("Can't add command"))?;
 | 
			
		||||
                };
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            register_command!(alias);
 | 
			
		||||
            macro_rules! register_stateless_command {
 | 
			
		||||
                ($sym: ident) => {
 | 
			
		||||
                    cmd_table
 | 
			
		||||
                        .set(
 | 
			
		||||
                            ctx,
 | 
			
		||||
                            ctx.intern_static(stringify!($sym).as_bytes()),
 | 
			
		||||
                            $sym(ctx),
 | 
			
		||||
                        )
 | 
			
		||||
                        .map_err(|_| Error::msg("Can't add command"))?;
 | 
			
		||||
                };
 | 
			
		||||
            }
 | 
			
		||||
            register_stateless_command!(alias);
 | 
			
		||||
            register_command!(close_mud);
 | 
			
		||||
            register_command!(connect_mud);
 | 
			
		||||
            register_command!(create_match_table);
 | 
			
		||||
            register_stateless_command!(create_match_table);
 | 
			
		||||
            register_command!(delete_mud);
 | 
			
		||||
            register_command!(echo);
 | 
			
		||||
            register_command!(echo_frame);
 | 
			
		||||
@ -210,6 +221,22 @@ pub fn install_lua_globals(
 | 
			
		||||
                        .map_err(|_| Error::msg("Can't add handler"))?;
 | 
			
		||||
                };
 | 
			
		||||
            }
 | 
			
		||||
            macro_rules! register_stateless_class_function {
 | 
			
		||||
                ($class_table: ident, $sym: ident) => {
 | 
			
		||||
                    $class_table
 | 
			
		||||
                        .set(
 | 
			
		||||
                            ctx,
 | 
			
		||||
                            ctx.intern_static(stringify!($sym).as_bytes()),
 | 
			
		||||
                            $sym(ctx),
 | 
			
		||||
                        )
 | 
			
		||||
                        .map_err(|_| Error::msg("Can't add handler"))?;
 | 
			
		||||
                };
 | 
			
		||||
                ($class_table: ident, $name: literal, $sym: ident) => {
 | 
			
		||||
                    $class_table
 | 
			
		||||
                        .set(ctx, ctx.intern_static($name.as_bytes()), $sym(ctx))
 | 
			
		||||
                        .map_err(|_| Error::msg("Can't add handler"))?;
 | 
			
		||||
                };
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            register_class_function!(mud_class_table, mudoutput_line);
 | 
			
		||||
            register_class_function!(mud_class_table, mudoutput_prompt);
 | 
			
		||||
@ -254,9 +281,17 @@ pub fn install_lua_globals(
 | 
			
		||||
            let match_table_class_table = Table::new(&ctx);
 | 
			
		||||
            classes_table.set(ctx, "match_table", match_table_class_table)?;
 | 
			
		||||
            match_table_class_table.set(ctx, MetaMethod::Index, match_table_class_table)?;
 | 
			
		||||
            register_class_function!(match_table_class_table, "add", match_table_add);
 | 
			
		||||
            register_class_function!(match_table_class_table, "remove", match_table_remove);
 | 
			
		||||
            register_class_function!(match_table_class_table, "lua_table", match_table_lua_table);
 | 
			
		||||
            register_stateless_class_function!(match_table_class_table, "add", match_table_add);
 | 
			
		||||
            register_stateless_class_function!(
 | 
			
		||||
                match_table_class_table,
 | 
			
		||||
                "remove",
 | 
			
		||||
                match_table_remove
 | 
			
		||||
            );
 | 
			
		||||
            register_stateless_class_function!(
 | 
			
		||||
                match_table_class_table,
 | 
			
		||||
                "lua_table",
 | 
			
		||||
                match_table_lua_table
 | 
			
		||||
            );
 | 
			
		||||
            register_class_function!(
 | 
			
		||||
                match_table_class_table,
 | 
			
		||||
                "try_run_sub",
 | 
			
		||||
@ -312,12 +347,15 @@ pub fn prep_metaop_call<'gc, const N: usize>(
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub async fn call_checking_metatable<'gc, 'a>(
 | 
			
		||||
pub async fn call_checking_metatable<'gc, T: Fetchable>(
 | 
			
		||||
    seq: &mut AsyncSequence,
 | 
			
		||||
    obj: StashedTable,
 | 
			
		||||
    obj: T,
 | 
			
		||||
    func_name: &'static str,
 | 
			
		||||
    arguments: &[StashedValue],
 | 
			
		||||
) -> Result<(), StashedError> {
 | 
			
		||||
) -> Result<(), StashedError>
 | 
			
		||||
where
 | 
			
		||||
    for<'gcb> <T as Fetchable>::Fetched<'gcb>: IntoValue<'gcb>,
 | 
			
		||||
{
 | 
			
		||||
    let call = seq.try_enter(|ctx, locals, _execution, mut stack| {
 | 
			
		||||
        let obj = locals.fetch(&obj);
 | 
			
		||||
        stack.consume(ctx)?;
 | 
			
		||||
 | 
			
		||||
@ -1,23 +1,20 @@
 | 
			
		||||
use crate::{
 | 
			
		||||
    echo_to_term_frame, id_intern::intern_id, GlobalLayoutCell, GlobalLayoutState, GlobalMemoCell,
 | 
			
		||||
    TermFrame,
 | 
			
		||||
    echo_to_term_frame,
 | 
			
		||||
    id_intern::intern_id,
 | 
			
		||||
    match_table::{create_match_table, match_table_add},
 | 
			
		||||
    GlobalLayoutCell, GlobalLayoutState, GlobalMemoCell, TermFrame,
 | 
			
		||||
};
 | 
			
		||||
use gc_arena::{Gc, Rootable};
 | 
			
		||||
use piccolo::{
 | 
			
		||||
    self, async_sequence, Callback, CallbackReturn, Context, FromValue, Function, IntoValue,
 | 
			
		||||
    SequenceReturn, Table, UserData, Value, Variadic,
 | 
			
		||||
    SequenceReturn, StashedTable, StashedUserData, StashedValue, Table, UserData, Value, Variadic,
 | 
			
		||||
};
 | 
			
		||||
use regex::Regex;
 | 
			
		||||
use std::{rc::Rc, str};
 | 
			
		||||
use yew::UseStateSetter;
 | 
			
		||||
 | 
			
		||||
use super::call_checking_metatable;
 | 
			
		||||
 | 
			
		||||
pub fn alias<'gc, 'a>(
 | 
			
		||||
    ctx: Context<'gc>,
 | 
			
		||||
    _global_memo: &'a GlobalMemoCell,
 | 
			
		||||
    _global_layout: &'a UseStateSetter<GlobalLayoutCell>,
 | 
			
		||||
) -> Callback<'gc> {
 | 
			
		||||
pub fn alias<'gc, 'a>(ctx: Context<'gc>) -> Callback<'gc> {
 | 
			
		||||
    Callback::from_fn(&ctx, move |ctx, _ex, mut stack| {
 | 
			
		||||
        let info: Table = ctx.get_global("info")?;
 | 
			
		||||
        let cur_frame: TermFrame =
 | 
			
		||||
@ -43,11 +40,20 @@ pub fn alias<'gc, 'a>(
 | 
			
		||||
            ))?;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        let aliases: Table = cur_frame.get(ctx, "aliases")?;
 | 
			
		||||
        let aliases: UserData = cur_frame.get(ctx, "aliases")?;
 | 
			
		||||
 | 
			
		||||
        aliases.set(ctx, alias_match, sub_to)?;
 | 
			
		||||
        stack.push_back(aliases.into_value(ctx));
 | 
			
		||||
        stack.push_back(alias_match.into_value(ctx));
 | 
			
		||||
        stack.push_back(sub_to.into_value(ctx));
 | 
			
		||||
        let seq = async_sequence(&ctx, |locals, mut seq| {
 | 
			
		||||
            let add_func = locals.stash(&ctx, Function::Callback(match_table_add(ctx)));
 | 
			
		||||
            async move {
 | 
			
		||||
                seq.call(&add_func, 0).await?;
 | 
			
		||||
                Ok(SequenceReturn::Return)
 | 
			
		||||
            }
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        Ok(piccolo::CallbackReturn::Return)
 | 
			
		||||
        Ok(piccolo::CallbackReturn::Sequence(seq))
 | 
			
		||||
    })
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -229,7 +235,8 @@ pub fn ensure_frame_instance<'gc>(ctx: Context<'gc>, frame: &TermFrame) -> Callb
 | 
			
		||||
            let frame_tab = locals.stash(&ctx, frame_tab);
 | 
			
		||||
            let frame = locals.stash(&ctx, frame);
 | 
			
		||||
            async move {
 | 
			
		||||
                call_checking_metatable(&mut seq, frame_tab, "new", &[frame]).await?;
 | 
			
		||||
                call_checking_metatable::<StashedTable>(&mut seq, frame_tab, "new", &[frame])
 | 
			
		||||
                    .await?;
 | 
			
		||||
                Ok(SequenceReturn::Return)
 | 
			
		||||
            }
 | 
			
		||||
        });
 | 
			
		||||
@ -251,10 +258,21 @@ pub(super) fn new_frame<'gc>(ctx: Context<'gc>, _global_memo: &GlobalMemoCell) -
 | 
			
		||||
 | 
			
		||||
        frame_tab.set(ctx, ctx.intern_static(b"frame"), frame)?;
 | 
			
		||||
 | 
			
		||||
        let aliases_tab: Table = Table::new(&ctx);
 | 
			
		||||
        frame_tab.set(ctx, ctx.intern_static(b"aliases"), aliases_tab)?;
 | 
			
		||||
        let seq = async_sequence(&ctx, |locals, mut seq| {
 | 
			
		||||
            let frame_tab = locals.stash(&ctx, frame_tab);
 | 
			
		||||
            let create_match_tab = locals.stash(&ctx, Function::Callback(create_match_table(ctx)));
 | 
			
		||||
            async move {
 | 
			
		||||
                seq.call(&create_match_tab, 0).await?;
 | 
			
		||||
                seq.try_enter(|ctx, locals, _exec, mut stack| {
 | 
			
		||||
                    let frame_tab = locals.fetch(&frame_tab);
 | 
			
		||||
                    frame_tab.set(ctx, "aliases", stack.consume::<Value>(ctx)?)?;
 | 
			
		||||
                    Ok(())
 | 
			
		||||
                })?;
 | 
			
		||||
                Ok(piccolo::SequenceReturn::Return)
 | 
			
		||||
            }
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        Ok(piccolo::CallbackReturn::Return)
 | 
			
		||||
        Ok(piccolo::CallbackReturn::Sequence(seq))
 | 
			
		||||
    })
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -268,7 +286,7 @@ pub(super) fn send_command_to_frame<'gc>(ctx: Context<'gc>) -> Callback<'gc> {
 | 
			
		||||
            let frame = locals.stash(&ctx, frame);
 | 
			
		||||
            let line = locals.stash(&ctx, line.into_value(ctx));
 | 
			
		||||
            async move {
 | 
			
		||||
                call_checking_metatable(&mut seq, frame, "input", &[line]).await?;
 | 
			
		||||
                call_checking_metatable::<StashedTable>(&mut seq, frame, "input", &[line]).await?;
 | 
			
		||||
                Ok(SequenceReturn::Return)
 | 
			
		||||
            }
 | 
			
		||||
        });
 | 
			
		||||
@ -278,47 +296,64 @@ pub(super) fn send_command_to_frame<'gc>(ctx: Context<'gc>) -> Callback<'gc> {
 | 
			
		||||
 | 
			
		||||
pub(super) fn frame_input<'gc>(ctx: Context<'gc>, _global_memo: &GlobalMemoCell) -> Callback<'gc> {
 | 
			
		||||
    Callback::from_fn(&ctx, move |ctx, _ex, mut stack| {
 | 
			
		||||
        let frame_tab: Table = Table::from_value(
 | 
			
		||||
            ctx,
 | 
			
		||||
            stack
 | 
			
		||||
        let callback_return = {
 | 
			
		||||
            let frame_tab: Table = Table::from_value(
 | 
			
		||||
                ctx,
 | 
			
		||||
                stack
 | 
			
		||||
                    .pop_front()
 | 
			
		||||
                    .ok_or_else(|| anyhow::Error::msg("classes.frame:input missing object!"))?,
 | 
			
		||||
            )?;
 | 
			
		||||
            let line: Value = stack
 | 
			
		||||
                .pop_front()
 | 
			
		||||
                .ok_or_else(|| anyhow::Error::msg("classes.frame:new missing object!"))?,
 | 
			
		||||
        )?;
 | 
			
		||||
        let line: Value = stack
 | 
			
		||||
            .pop_front()
 | 
			
		||||
            .ok_or_else(|| anyhow::Error::msg("classes.frame:new missing line!"))?;
 | 
			
		||||
        stack.consume(ctx)?;
 | 
			
		||||
                .ok_or_else(|| anyhow::Error::msg("classes.frame:input missing line!"))?;
 | 
			
		||||
            stack.consume(ctx)?;
 | 
			
		||||
 | 
			
		||||
        // Check for an alias match...
 | 
			
		||||
        for (alias_match, alias_sub) in frame_tab.get::<&str, Table>(ctx, "aliases")?.iter() {
 | 
			
		||||
            if let Some(alias_match) = piccolo::String::from_value(ctx, alias_match)
 | 
			
		||||
                .ok()
 | 
			
		||||
                .and_then(|am| am.to_str().ok())
 | 
			
		||||
                .and_then(|v| Regex::new(v).ok())
 | 
			
		||||
            {
 | 
			
		||||
                if let Some(alias_sub) = piccolo::String::from_value(ctx, alias_sub)
 | 
			
		||||
                    .ok()
 | 
			
		||||
                    .and_then(|am| am.to_str().ok())
 | 
			
		||||
                {}
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
            let aliases: UserData = frame_tab.get(ctx, "aliases")?;
 | 
			
		||||
            let frame: Value = frame_tab.get(ctx, "frame")?;
 | 
			
		||||
 | 
			
		||||
        let linked_mud = frame_tab.get_value(ctx, ctx.intern_static(b"linked_mud"));
 | 
			
		||||
        if linked_mud.is_nil() {
 | 
			
		||||
            return Ok(piccolo::CallbackReturn::Return);
 | 
			
		||||
        }
 | 
			
		||||
        let linked_mud: Table = Table::from_value(ctx, linked_mud)?;
 | 
			
		||||
            let seq = async_sequence(&ctx, |locals, mut seq| {
 | 
			
		||||
                let aliases = locals.stash(&ctx, aliases);
 | 
			
		||||
                let line = locals.stash(&ctx, line);
 | 
			
		||||
                let frame_tab = locals.stash(&ctx, frame_tab);
 | 
			
		||||
                let frame = locals.stash(&ctx, frame);
 | 
			
		||||
                async move {
 | 
			
		||||
                    call_checking_metatable::<StashedUserData>(
 | 
			
		||||
                        &mut seq,
 | 
			
		||||
                        aliases.clone(),
 | 
			
		||||
                        "try_run_sub",
 | 
			
		||||
                        &[line.clone(), frame],
 | 
			
		||||
                    )
 | 
			
		||||
                    .await?;
 | 
			
		||||
                    let (alias_hit, linked_mud, linked_mud_nil) =
 | 
			
		||||
                        seq.try_enter(|ctx, locals, _ex, mut stack| {
 | 
			
		||||
                            let linked_mud = locals
 | 
			
		||||
                                .fetch(&frame_tab)
 | 
			
		||||
                                .get_value(ctx, ctx.intern_static(b"linked_mud"));
 | 
			
		||||
                            Ok((
 | 
			
		||||
                                stack.consume::<bool>(ctx)?,
 | 
			
		||||
                                locals.stash(&ctx, linked_mud),
 | 
			
		||||
                                linked_mud.is_nil(),
 | 
			
		||||
                            ))
 | 
			
		||||
                        })?;
 | 
			
		||||
 | 
			
		||||
        // linked_mud:mudinput_line(line)
 | 
			
		||||
        let seq = async_sequence(&ctx, |locals, mut seq| {
 | 
			
		||||
            let linked_mud = locals.stash(&ctx, linked_mud);
 | 
			
		||||
            let line = locals.stash(&ctx, line);
 | 
			
		||||
            async move {
 | 
			
		||||
                call_checking_metatable(&mut seq, linked_mud, "mudinput_line", &[line]).await?;
 | 
			
		||||
                Ok(SequenceReturn::Return)
 | 
			
		||||
            }
 | 
			
		||||
        });
 | 
			
		||||
                    if alias_hit || linked_mud_nil {
 | 
			
		||||
                        return Ok(SequenceReturn::Return);
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
        Ok(piccolo::CallbackReturn::Sequence(seq))
 | 
			
		||||
                    call_checking_metatable::<StashedValue>(
 | 
			
		||||
                        &mut seq,
 | 
			
		||||
                        linked_mud,
 | 
			
		||||
                        "mudinput_line",
 | 
			
		||||
                        &[line],
 | 
			
		||||
                    )
 | 
			
		||||
                    .await?;
 | 
			
		||||
 | 
			
		||||
                    Ok(SequenceReturn::Return)
 | 
			
		||||
                }
 | 
			
		||||
            });
 | 
			
		||||
 | 
			
		||||
            Ok(piccolo::CallbackReturn::Sequence(seq))
 | 
			
		||||
        };
 | 
			
		||||
        callback_return
 | 
			
		||||
    })
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -204,7 +204,7 @@ pub(super) fn connect_mud<'gc>(
 | 
			
		||||
        let seq = async_sequence(&ctx, |locals, mut seq| {
 | 
			
		||||
            let conntab = locals.stash(&ctx, conntab);
 | 
			
		||||
            async move {
 | 
			
		||||
                call_checking_metatable(&mut seq, conntab, "new", &[]).await?;
 | 
			
		||||
                call_checking_metatable::<StashedTable>(&mut seq, conntab, "new", &[]).await?;
 | 
			
		||||
                Ok(SequenceReturn::Return)
 | 
			
		||||
            }
 | 
			
		||||
        });
 | 
			
		||||
@ -319,7 +319,7 @@ pub(super) fn mudoutput<'gc>(ctx: Context<'gc>, _global_memo: &GlobalMemoCell) -
 | 
			
		||||
                            .collect();
 | 
			
		||||
                        async move {
 | 
			
		||||
                            for (func_name, params) in fns {
 | 
			
		||||
                                call_checking_metatable(
 | 
			
		||||
                                call_checking_metatable::<StashedTable>(
 | 
			
		||||
                                    &mut seq,
 | 
			
		||||
                                    conntab.clone(),
 | 
			
		||||
                                    func_name,
 | 
			
		||||
@ -401,7 +401,13 @@ pub(super) fn mudoutput_line<'gc>(
 | 
			
		||||
            let line = locals.stash(&ctx, line.into_value(ctx));
 | 
			
		||||
            async move {
 | 
			
		||||
                for frameroute in frameroutes {
 | 
			
		||||
                    call_checking_metatable(&mut seq, frameroute, "route", &[line.clone()]).await?;
 | 
			
		||||
                    call_checking_metatable::<StashedTable>(
 | 
			
		||||
                        &mut seq,
 | 
			
		||||
                        frameroute,
 | 
			
		||||
                        "route",
 | 
			
		||||
                        &[line.clone()],
 | 
			
		||||
                    )
 | 
			
		||||
                    .await?;
 | 
			
		||||
                }
 | 
			
		||||
                Ok(SequenceReturn::Return)
 | 
			
		||||
            }
 | 
			
		||||
@ -494,7 +500,8 @@ pub(super) fn new_mud<'gc>(ctx: Context<'gc>, _global_memo: &GlobalMemoCell) ->
 | 
			
		||||
            let curr_frame = locals.stash(&ctx, curr_frame);
 | 
			
		||||
 | 
			
		||||
            async move {
 | 
			
		||||
                call_checking_metatable(&mut seq, frameroute, "new", &[curr_frame]).await?;
 | 
			
		||||
                call_checking_metatable::<StashedTable>(&mut seq, frameroute, "new", &[curr_frame])
 | 
			
		||||
                    .await?;
 | 
			
		||||
                Ok(SequenceReturn::Return)
 | 
			
		||||
            }
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
@ -8,12 +8,11 @@ use gc_arena::{Collect, GcRefLock, Rootable};
 | 
			
		||||
use itertools::Itertools;
 | 
			
		||||
use piccolo::{Callback, Context, IntoValue, Table, UserData, Value};
 | 
			
		||||
use regex::Regex;
 | 
			
		||||
use yew::UseStateSetter;
 | 
			
		||||
 | 
			
		||||
use crate::{
 | 
			
		||||
    lua_engine::frames::try_unwrap_frame,
 | 
			
		||||
    parsing::{parse_commands, quote_string, ArgumentGuard, ParsedArgument, ParsedCommand},
 | 
			
		||||
    GlobalLayoutCell, GlobalMemoCell,
 | 
			
		||||
    GlobalMemoCell,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#[derive(Default, Debug, Collect)]
 | 
			
		||||
@ -251,6 +250,87 @@ pub enum SubTextPart {
 | 
			
		||||
    Variable(String),
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub fn create_match_table<'gc, 'a>(ctx: Context<'gc>) -> Callback<'gc> {
 | 
			
		||||
    Callback::from_fn(&ctx, move |ctx, _ex, mut stack| {
 | 
			
		||||
        let _: () = stack.consume(ctx)?;
 | 
			
		||||
        let user_data = UserData::<'gc>::new::<Rootable!['gcb => GcRefLock<'gcb, MatchSubTable>]>(
 | 
			
		||||
            &ctx,
 | 
			
		||||
            GcRefLock::new(&ctx, <MatchSubTable as Default>::default().into()),
 | 
			
		||||
        );
 | 
			
		||||
        let match_table_class: Table = ctx
 | 
			
		||||
            .get_global::<Table>("classes")?
 | 
			
		||||
            .get(ctx, "match_table")?;
 | 
			
		||||
        user_data.set_metatable(&ctx, Some(match_table_class));
 | 
			
		||||
 | 
			
		||||
        stack.push_back(user_data.into_value(ctx));
 | 
			
		||||
        Ok(piccolo::CallbackReturn::Return)
 | 
			
		||||
    })
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub fn match_table_add<'gc, 'a>(ctx: Context<'gc>) -> Callback<'gc> {
 | 
			
		||||
    Callback::from_fn(&ctx, move |ctx, _ex, mut stack| {
 | 
			
		||||
        let (match_table, match_text, sub_text): (UserData, piccolo::String, piccolo::String) =
 | 
			
		||||
            stack.consume(ctx)?;
 | 
			
		||||
        match_table
 | 
			
		||||
            .downcast::<Rootable!['gcb => GcRefLock<'gcb, MatchSubTable>]>()?
 | 
			
		||||
            .borrow_mut(&ctx)
 | 
			
		||||
            .add_record(match_text.to_str()?, sub_text.to_str()?)?;
 | 
			
		||||
        Ok(piccolo::CallbackReturn::Return)
 | 
			
		||||
    })
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub fn match_table_remove<'gc, 'a>(ctx: Context<'gc>) -> Callback<'gc> {
 | 
			
		||||
    Callback::from_fn(&ctx, move |ctx, _ex, mut stack| {
 | 
			
		||||
        let (match_table, match_text): (UserData, piccolo::String) = stack.consume(ctx)?;
 | 
			
		||||
        match_table
 | 
			
		||||
            .downcast::<Rootable!['gcb => GcRefLock<'gcb, MatchSubTable>]>()?
 | 
			
		||||
            .borrow_mut(&ctx)
 | 
			
		||||
            .remove_record(match_text.to_str()?)?;
 | 
			
		||||
        Ok(piccolo::CallbackReturn::Return)
 | 
			
		||||
    })
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub fn match_table_lua_table<'gc, 'a>(ctx: Context<'gc>) -> Callback<'gc> {
 | 
			
		||||
    Callback::from_fn(&ctx, move |ctx, _ex, mut stack| {
 | 
			
		||||
        let match_table: UserData = stack.consume(ctx)?;
 | 
			
		||||
        stack.push_back(
 | 
			
		||||
            match_table
 | 
			
		||||
                .downcast::<Rootable!['gcb => GcRefLock<'gcb, MatchSubTable>]>()?
 | 
			
		||||
                .borrow_mut(&ctx)
 | 
			
		||||
                .to_value(ctx)?,
 | 
			
		||||
        );
 | 
			
		||||
        Ok(piccolo::CallbackReturn::Return)
 | 
			
		||||
    })
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub fn match_table_try_run_sub<'gc, 'a>(
 | 
			
		||||
    ctx: Context<'gc>,
 | 
			
		||||
    global_memo: &'a GlobalMemoCell,
 | 
			
		||||
) -> Callback<'gc> {
 | 
			
		||||
    let global_memo = global_memo.clone();
 | 
			
		||||
    Callback::from_fn(&ctx, move |ctx, _ex, mut stack| {
 | 
			
		||||
        let (match_table, sub, frame): (UserData, piccolo::String, Value) = stack.consume(ctx)?;
 | 
			
		||||
        let frame = try_unwrap_frame(ctx, &frame)?;
 | 
			
		||||
 | 
			
		||||
        let cmds = match_table
 | 
			
		||||
            .downcast::<Rootable!['gcb => GcRefLock<'gcb, MatchSubTable>]>()?
 | 
			
		||||
            .borrow()
 | 
			
		||||
            .try_sub(sub.to_str()?);
 | 
			
		||||
 | 
			
		||||
        match cmds {
 | 
			
		||||
            None => stack.push_back(false.into_value(ctx)),
 | 
			
		||||
            Some(cmds) => {
 | 
			
		||||
                let mut cq = global_memo.command_queue.borrow_mut();
 | 
			
		||||
                for cmd in cmds.into_iter().rev() {
 | 
			
		||||
                    cq.push_front((frame.clone(), cmd));
 | 
			
		||||
                }
 | 
			
		||||
                stack.push_back(Value::Boolean(true))
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        Ok(piccolo::CallbackReturn::Return)
 | 
			
		||||
    })
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[cfg(test)]
 | 
			
		||||
mod tests {
 | 
			
		||||
    use super::*;
 | 
			
		||||
@ -452,97 +532,3 @@ mod tests {
 | 
			
		||||
            .is_err())
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub fn create_match_table<'gc, 'a>(
 | 
			
		||||
    ctx: Context<'gc>,
 | 
			
		||||
    _global_memo: &'a GlobalMemoCell,
 | 
			
		||||
    _global_layout: &'a UseStateSetter<GlobalLayoutCell>,
 | 
			
		||||
) -> Callback<'gc> {
 | 
			
		||||
    Callback::from_fn(&ctx, move |ctx, _ex, mut stack| {
 | 
			
		||||
        let _: () = stack.consume(ctx)?;
 | 
			
		||||
        let user_data = UserData::<'gc>::new::<Rootable!['gcb => GcRefLock<'gcb, MatchSubTable>]>(
 | 
			
		||||
            &ctx,
 | 
			
		||||
            GcRefLock::new(&ctx, <MatchSubTable as Default>::default().into()),
 | 
			
		||||
        );
 | 
			
		||||
        let match_table_class: Table = ctx
 | 
			
		||||
            .get_global::<Table>("classes")?
 | 
			
		||||
            .get(ctx, "match_table")?;
 | 
			
		||||
        user_data.set_metatable(&ctx, Some(match_table_class));
 | 
			
		||||
 | 
			
		||||
        stack.push_back(user_data.into_value(ctx));
 | 
			
		||||
        Ok(piccolo::CallbackReturn::Return)
 | 
			
		||||
    })
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub fn match_table_add<'gc, 'a>(
 | 
			
		||||
    ctx: Context<'gc>,
 | 
			
		||||
    _global_memo: &'a GlobalMemoCell,
 | 
			
		||||
) -> Callback<'gc> {
 | 
			
		||||
    Callback::from_fn(&ctx, move |ctx, _ex, mut stack| {
 | 
			
		||||
        let (match_table, match_text, sub_text): (UserData, piccolo::String, piccolo::String) =
 | 
			
		||||
            stack.consume(ctx)?;
 | 
			
		||||
        match_table
 | 
			
		||||
            .downcast::<Rootable!['gcb => GcRefLock<'gcb, MatchSubTable>]>()?
 | 
			
		||||
            .borrow_mut(&ctx)
 | 
			
		||||
            .add_record(match_text.to_str()?, sub_text.to_str()?)?;
 | 
			
		||||
        Ok(piccolo::CallbackReturn::Return)
 | 
			
		||||
    })
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub fn match_table_remove<'gc, 'a>(
 | 
			
		||||
    ctx: Context<'gc>,
 | 
			
		||||
    _global_memo: &'a GlobalMemoCell,
 | 
			
		||||
) -> Callback<'gc> {
 | 
			
		||||
    Callback::from_fn(&ctx, move |ctx, _ex, mut stack| {
 | 
			
		||||
        let (match_table, match_text): (UserData, piccolo::String) = stack.consume(ctx)?;
 | 
			
		||||
        match_table
 | 
			
		||||
            .downcast::<Rootable!['gcb => GcRefLock<'gcb, MatchSubTable>]>()?
 | 
			
		||||
            .borrow_mut(&ctx)
 | 
			
		||||
            .remove_record(match_text.to_str()?)?;
 | 
			
		||||
        Ok(piccolo::CallbackReturn::Return)
 | 
			
		||||
    })
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub fn match_table_lua_table<'gc, 'a>(
 | 
			
		||||
    ctx: Context<'gc>,
 | 
			
		||||
    _global_memo: &'a GlobalMemoCell,
 | 
			
		||||
) -> Callback<'gc> {
 | 
			
		||||
    Callback::from_fn(&ctx, move |ctx, _ex, mut stack| {
 | 
			
		||||
        let match_table: UserData = stack.consume(ctx)?;
 | 
			
		||||
        stack.push_back(
 | 
			
		||||
            match_table
 | 
			
		||||
                .downcast::<Rootable!['gcb => GcRefLock<'gcb, MatchSubTable>]>()?
 | 
			
		||||
                .borrow_mut(&ctx)
 | 
			
		||||
                .to_value(ctx)?,
 | 
			
		||||
        );
 | 
			
		||||
        Ok(piccolo::CallbackReturn::Return)
 | 
			
		||||
    })
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub fn match_table_try_run_sub<'gc, 'a>(
 | 
			
		||||
    ctx: Context<'gc>,
 | 
			
		||||
    global_memo: &'a GlobalMemoCell,
 | 
			
		||||
) -> Callback<'gc> {
 | 
			
		||||
    let global_memo = global_memo.clone();
 | 
			
		||||
    Callback::from_fn(&ctx, move |ctx, _ex, mut stack| {
 | 
			
		||||
        let (match_table, sub, frame): (UserData, piccolo::String, Value) = stack.consume(ctx)?;
 | 
			
		||||
        let frame = try_unwrap_frame(ctx, &frame)?;
 | 
			
		||||
 | 
			
		||||
        let cmds = match_table
 | 
			
		||||
            .downcast::<Rootable!['gcb => GcRefLock<'gcb, MatchSubTable>]>()?
 | 
			
		||||
            .borrow()
 | 
			
		||||
            .try_sub(sub.to_str()?);
 | 
			
		||||
 | 
			
		||||
        match cmds {
 | 
			
		||||
            None => stack.push_back(false.into_value(ctx)),
 | 
			
		||||
            Some(cmds) => {
 | 
			
		||||
                let mut cq = global_memo.command_queue.borrow_mut();
 | 
			
		||||
                for cmd in cmds.into_iter().rev() {
 | 
			
		||||
                    cq.push_front((frame.clone(), cmd));
 | 
			
		||||
                }
 | 
			
		||||
                stack.push_back(Value::Boolean(true))
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        Ok(piccolo::CallbackReturn::Return)
 | 
			
		||||
    })
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user