Skip to content

Commit

Permalink
feat: Provide std.effect.io as a mirror of std.io
Browse files Browse the repository at this point in the history
We do this by generating a module based on the types of `std.io` this
isn't perfect yet (see `catch` for instance) but it is a pretty good
approximation.
  • Loading branch information
Marwes committed Oct 6, 2019
1 parent dc7ec72 commit 66e49b3
Show file tree
Hide file tree
Showing 12 changed files with 285 additions and 80 deletions.
21 changes: 20 additions & 1 deletion base/src/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ use crate::pos::{self, BytePos, HasSpan, Span, Spanned};
use crate::resolve::remove_aliases_cow;
use crate::symbol::Symbol;
use crate::types::{
self, Alias, AliasData, ArcType, ArgType, NullInterner, Type, TypeEnv, TypeExt,
self, Alias, AliasData, ArcType, ArgType, Flags, NullInterner, Type, TypeEnv, TypeExt,
};
use ordered_float::NotNan;

Expand Down Expand Up @@ -112,6 +112,12 @@ impl<Id> From<Type<Id, AstType<Id>>> for AstType<Id> {
}
}

impl<Id> From<(Type<Id, AstType<Id>>, Flags)> for AstType<Id> {
fn from((typ, _): (Type<Id, AstType<Id>>, Flags)) -> AstType<Id> {
Self::from(typ)
}
}

impl<Id> HasSpan for AstType<Id> {
fn span(&self) -> Span<BytePos> {
self._typ.typ.span
Expand Down Expand Up @@ -423,6 +429,18 @@ impl<Id> Default for Expr<Id> {
}

impl<Id> Expr<Id> {
pub fn app(func: SpannedExpr<Id>, args: Vec<SpannedExpr<Id>>) -> Self {
if args.is_empty() {
func.value
} else {
Expr::App {
func: func.into(),
implicit_args: Vec::new(),
args,
}
}
}

// TODO Use impl Trait
pub fn field_iter<'a>(
&'a self,
Expand Down Expand Up @@ -902,6 +920,7 @@ impl Typed for Expr<Symbol> {
fn try_type_of(&self, env: &dyn TypeEnv<Type = ArcType>) -> Result<ArcType, String> {
match *self {
Expr::Ident(ref id) => Ok(id.typ.clone()),
Expr::Tuple { ref elems, .. } if elems.len() == 1 => elems[0].try_type_of(env),
Expr::Projection(_, _, ref typ)
| Expr::Record { ref typ, .. }
| Expr::Tuple { ref typ, .. } => Ok(typ.clone()),
Expand Down
8 changes: 8 additions & 0 deletions base/src/types/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1501,6 +1501,14 @@ pub trait TypeExt: Deref<Target = Type<<Self as TypeExt>::Id, Self>> + Clone + S
type_field_iter(self)
}

fn arg_iter(&self) -> ArgIterator<Self> {
arg_iter(self)
}

fn implicit_arg_iter(&self) -> ImplicitArgIterator<Self> {
implicit_arg_iter(self)
}

/// Returns an iterator over all fields in a record.
/// `{ Test, Test2, x, y } => [x, y]`
fn row_iter(&self) -> RowIterator<Self> {
Expand Down
17 changes: 10 additions & 7 deletions examples/http/server.glu
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
let prelude = import! std.prelude
let io @ { ? } = import! std.io
let io = import! std.effect.io
let { ? } = import! std.io
let string = import! std.string
let { (<>) } = import! std.prelude
let { map } = import! std.functor
Expand All @@ -10,11 +11,11 @@ let { ? } = import! std.array
let { Result } = import! std.result
let { foldl } = import! std.foldable
let { Eff, ? } = import! std.effect
let { run_lift } = import! std.effect.lift

let http @ {
Request, Response, HttpEffect, StatusCode,
handle,
io_handler,
empty_response,
get,
post,
Expand All @@ -38,7 +39,7 @@ let hello_world : Eff (HttpEffect r) Response =
*> (wrap { status = status.ok, .. http.response })

let echo_body request : Request -> Eff (HttpEffect r) () =
do chunk = io_handler (read_chunk request.body)
do chunk = read_chunk request.body
match chunk with
| Some chunk -> write_response chunk *> echo_body request
| None -> wrap ()
Expand All @@ -48,7 +49,7 @@ let echo : Eff (HttpEffect r) Response =
*> wrap { status = status.ok, .. http.response }

let array_body request : Request -> Eff (HttpEffect r) (Array Byte) =
do chunk = io_handler (read_chunk request.body)
do chunk = read_chunk request.body
match chunk with
| Some chunk ->
do rest = array_body request
Expand Down Expand Up @@ -80,8 +81,10 @@ let handler : Eff (HttpEffect r) Response =
<|> (post *> path "/sum" *> sum)
<|> (get *> path "/error" *> (wrap { status = status.internal_server_error, .. http.response }))

let print_error h = catch_error h (\msg -> io_handler (io.println msg))
let print_error h = catch_error h (\msg -> io.println msg)

\port ->
io.println ("Opened server on port " <> show port)
*> listen { port, .. http.default_listen_settings } handler
let action =
seq io.println ("Opened server on port " <> show port)
listen { port, .. http.default_listen_settings } handler
run_lift action
55 changes: 25 additions & 30 deletions repl/src/repl.glu
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
let prelude = import! std.prelude
let io @ { ? } = import! std.io
let io = import! std.effect.io
let mio @ { ? } = import! std.io
let map @ { Map, empty, singleton, find, insert, ? } = import! std.map
let { Bool } = import! std.bool
let { Option } = import! std.option
Expand Down Expand Up @@ -43,8 +44,7 @@ let run_interruptible_io action :
do cpu_pool = asks (\r -> r.cpu_pool)
do eval_thread = lift <| thread.new_thread ()
let interruptible_action = repl_prim.finish_or_interrupt cpu_pool eval_thread action
lift
<| io.catch (io.functor.map Ok interruptible_action) (wrap << Err)
io.catch (mio.functor.map Ok interruptible_action) (wrap << Err)


let load_file filename : String -> Eff (ReplEffect r) String =
Expand All @@ -54,8 +54,8 @@ let load_file filename : String -> Eff (ReplEffect r) String =
| Some i -> i + 1
let modulename = string.slice filename last_slash (string.len filename - 3)
let action =
do expr = io.read_file_to_string filename
do result = io.load_script modulename expr
do expr = mio.read_file_to_string filename
do result = mio.load_script modulename expr
wrap result

do result = run_interruptible_io action
Expand All @@ -65,22 +65,20 @@ let load_file filename : String -> Eff (ReplEffect r) String =

let run_file filename : String -> Eff (ReplEffect r) () =
let action =
do expr = io.read_file_to_string filename
do result = io.run_expr expr
do expr = mio.read_file_to_string filename
do result = mio.run_expr expr
wrap (result.value ++ " : " ++ result.typ)

do result = run_interruptible_io action
lift
<| (match result with
| Ok _ -> io.println ""
| Err x -> io.println x)
match result with
| Ok _ -> io.println ""
| Err x -> io.println x

let commands : Commands =
let print_result result =
lift
<| (match result with
| Ok x -> io.println x
| Err x -> io.println x)
match result with
| Ok x -> io.println x
| Err x -> io.println x

let commands = ref []
let cmds : Array Cmd = [{
Expand Down Expand Up @@ -124,7 +122,7 @@ let commands : Commands =
info = "Loads the file at \'folder/module.ext\' and stores it at \'module\'",
action
= \arg ->
(load_file arg >>= (lift << io.println))
(load_file arg >>= io.println)
*> wrap Continue,
},
{
Expand Down Expand Up @@ -160,7 +158,7 @@ let commands : Commands =
{ color,
.. settings
})
| Err msg -> lift <| io.println msg
| Err msg -> io.println msg
wrap Continue,
},
{
Expand All @@ -177,10 +175,9 @@ let commands : Commands =
alias = "h",
info = "Print this help",
action = \_ ->
let print_header = lift <| io.println "Available commands\n"
let print_header = io.println "Available commands\n"
let print_cmd cmd : Cmd -> Eff (ReplEffect r) () =
lift
(io.println (" :" ++ cmd.name ++ " (" ++ cmd.alias ++ ") " ++ cmd.info))
io.println (" :" ++ cmd.name ++ " (" ++ cmd.alias ++ ") " ++ cmd.info)

print_header
*> array.traversable.traverse effect.applicative print_cmd (load commands)
Expand Down Expand Up @@ -218,10 +215,9 @@ let do_command commands line : Commands -> String -> Eff (ReplEffect r) ReplActi
| Ok { cmd, arg } ->
match find cmd commands with
| Some command -> command.action arg
| None -> lift <| io.println ("Unknown command \'" ++ cmd ++ "\'") *> wrap Continue
| None -> io.println ("Unknown command \'" ++ cmd ++ "\'") *> wrap Continue
| Err err ->
lift
<| io.println "Expected a command such as `:h`" *> wrap Continue
io.println "Expected a command such as `:h`" *> wrap Continue

let loop _ : () -> Eff (ReplEffect r) () =
do repl = ask
Expand All @@ -238,8 +234,7 @@ let loop _ : () -> Eff (ReplEffect r) () =
do eval_thread = thread.new_thread ()
let eval_action = repl_prim.eval_line settings.color line
repl_prim.finish_or_interrupt cpu_pool eval_thread eval_action
lift
<| io.catch action io.println *> wrap Continue
io.catch action mio.println *> wrap Continue

do line_result = lift <| rustyline.readline repl.editor settings.prompt
match line_result with
Expand All @@ -253,11 +248,11 @@ let loop _ : () -> Eff (ReplEffect r) () =
seq lift <| rustyline.save_history repl.editor
wrap ()

let run settings : Settings -> IO () =
let run settings : Settings -> Eff [| lift : Lift IO |] () =
seq io.println "gluon (:h for help, :q to quit)"
do editor = rustyline.new_editor ()
do cpu_pool = repl_prim.new_cpu_pool 1
do editor = lift <| rustyline.new_editor ()
do cpu_pool = lift <| repl_prim.new_cpu_pool 1
let repl = { commands, editor, cpu_pool }
run_lift (run_reader repl (eval_state settings (loop ())))
run_reader repl (eval_state settings (loop ()))

run
run_lift << run
34 changes: 19 additions & 15 deletions src/import.rs
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ pub trait Importer: Any + Clone + Sync + Send {
compiler: &mut ModuleCompiler,
vm: &Thread,
modulename: &str,
) -> Result<(), (Option<ArcType>, crate::Error)>;
) -> Result<ArcType, (Option<ArcType>, crate::Error)>;
}

#[derive(Clone)]
Expand All @@ -90,12 +90,12 @@ impl Importer for DefaultImporter {
compiler: &mut ModuleCompiler,
_vm: &Thread,
modulename: &str,
) -> Result<(), (Option<ArcType>, crate::Error)> {
compiler
) -> Result<ArcType, (Option<ArcType>, crate::Error)> {
let value = compiler
.database
.global(modulename.to_string())
.map_err(|err| (None, err))?;
Ok(())
Ok(value.typ)
}
}

Expand Down Expand Up @@ -285,7 +285,7 @@ impl<I> Import<I> {
compiler: &mut ModuleCompiler,
vm: &Thread,
module_id: &Symbol,
) -> Result<(), (Option<ArcType>, MacroError)>
) -> Result<ArcType, (Option<ArcType>, MacroError)>
where
I: Importer,
{
Expand All @@ -297,22 +297,26 @@ impl<I> Import<I> {
.get_unloaded_module(vm, &modulename)
.map_err(|err| (None, MacroError::new(err)))?;

match unloaded_module {
Ok(match unloaded_module {
UnloadedModule::Extern(ExternModule {
value,
typ,
metadata,
}) => {
vm.set_global(module_id.clone(), typ, metadata.into(), value.get_value())
.map_err(|err| (None, MacroError::new(err)))?;
}
UnloadedModule::Source => {
self.importer
.import(compiler, vm, &modulename)
.map_err(|(t, err)| (t, MacroError::new(err)))?;
vm.set_global(
module_id.clone(),
typ.clone(),
metadata.into(),
value.get_value(),
)
.map_err(|err| (None, MacroError::new(err)))?;
typ
}
}
Ok(())
UnloadedModule::Source => self
.importer
.import(compiler, vm, &modulename)
.map_err(|(t, err)| (t, MacroError::new(err)))?,
})
}
}

Expand Down
24 changes: 17 additions & 7 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ macro_rules! try_future {
pub mod compiler_pipeline;
#[macro_use]
pub mod import;
pub mod lift_io;
#[doc(hidden)]
pub mod query;
pub mod std_lib;
Expand Down Expand Up @@ -594,6 +595,7 @@ pub trait ThreadExt {
&module_name,
)
.map_err(|(_, err)| err.into())
.map(|_| ())
.into_future(),
)
}
Expand Down Expand Up @@ -831,15 +833,23 @@ impl VmBuilder {
let vm =
RootedThread::with_global_state(crate::vm::vm::GlobalVmStateBuilder::new().build());

let import = Import::new(DefaultImporter);
if let Some(import_paths) = self.import_paths {
import.set_paths(import_paths);
}
{
let macros = vm.get_macros();

{
let import = Import::new(DefaultImporter);
if let Some(import_paths) = self.import_paths {
import.set_paths(import_paths);
}

if let Ok(gluon_path) = env::var("GLUON_PATH") {
import.add_path(gluon_path);
}
macros.insert(String::from("import"), import);
}

if let Ok(gluon_path) = env::var("GLUON_PATH") {
import.add_path(gluon_path);
macros.insert(String::from("lift_io"), lift_io::LiftIo);
}
vm.get_macros().insert(String::from("import"), import);

add_extern_module(&vm, "std.prim", crate::vm::primitives::load);

Expand Down
Loading

0 comments on commit 66e49b3

Please sign in to comment.