geam-stdlib 0.2.0

Official Gleam standard-library providers for Geam
Documentation
use super::{IoOutput, IoSink, IoStream};
use ecow::EcoString;

pub(super) fn print<Io>(io: &mut Io, text: EcoString)
where
    Io: IoSink,
{
    emit(io, IoStream::Stdout, text);
}

pub(super) fn print_error<Io>(io: &mut Io, text: EcoString)
where
    Io: IoSink,
{
    emit(io, IoStream::Stderr, text);
}

pub(super) fn println<Io>(io: &mut Io, mut text: EcoString)
where
    Io: IoSink,
{
    text.push('\n');
    emit(io, IoStream::Stdout, text);
}

pub(super) fn println_error<Io>(io: &mut Io, mut text: EcoString)
where
    Io: IoSink,
{
    text.push('\n');
    emit(io, IoStream::Stderr, text);
}

fn emit<Io>(io: &mut Io, stream: IoStream, text: EcoString)
where
    Io: IoSink,
{
    io.emit(IoOutput::new(stream, text));
}

#[cfg(test)]
mod tests {
    use crate::{GleamStdlibProfile, GleamStdlibRunState, IoStream};
    use crate::{
        HostModule, HostProviderSet, HostedExecution, ModuleSource, PackageSource, Value,
        compile_typed_host_program, plan_host_program,
    };
    use ecow::EcoString;

    const IO_SOURCE: &str = r#"
@external(erlang, "gleam_stdlib", "print")
pub fn print(string: String) -> Nil

@external(erlang, "gleam_stdlib", "print_error")
pub fn print_error(string: String) -> Nil

@external(erlang, "gleam_stdlib", "println")
pub fn println(string: String) -> Nil

@external(erlang, "gleam_stdlib", "println_error")
pub fn println_error(string: String) -> Nil

pub fn main() {
  print("first")
  print_error("second")
  println("third")
  println_error("fourth")
}
"#;

    #[test]
    fn executes_all_io_callbacks_through_the_typed_provider() {
        let provider = super::super::host_provider::<GleamStdlibProfile>()
            .expect("synthetic IO provider should register");
        let typed = compile_typed_host_program(
            "gleam_stdlib",
            "gleam/io",
            [PackageSource::new(
                "gleam_stdlib",
                Vec::<EcoString>::new(),
                [ModuleSource::new(
                    "gleam/io",
                    "src/gleam/io.gleam",
                    IO_SOURCE,
                )],
            )],
            HostProviderSet::with_providers(
                Vec::<HostModule<GleamStdlibProfile>>::new(),
                [provider],
            )
            .expect("synthetic IO provider module should be unique"),
        )
        .expect("synthetic IO source should compile");
        let plan = plan_host_program(typed).expect("synthetic IO source should plan");
        let execution =
            HostedExecution::try_from_module_plan(plan).expect("synthetic IO source should seal");
        let mut state = GleamStdlibRunState::from_seed([2; 32]);

        assert_eq!(
            execution
                .run_main(&mut state, &mut Vec::new())
                .expect("synthetic IO source should run"),
            Value::Nil,
        );
        assert_eq!(
            state
                .io_outputs()
                .iter()
                .map(|output| (output.stream(), output.text().as_str()))
                .collect::<Vec<_>>(),
            [
                (IoStream::Stdout, "first"),
                (IoStream::Stderr, "second"),
                (IoStream::Stdout, "third\n"),
                (IoStream::Stderr, "fourth\n"),
            ],
        );
    }
}