Skip to content

Commit

Permalink
Merge pull request #2401 from rtfeldman/tea-example
Browse files Browse the repository at this point in the history
Our first elm architecture example
  • Loading branch information
rtfeldman authored Jan 26, 2022
2 parents 0031e29 + 9ee7198 commit 0c5f9ff
Show file tree
Hide file tree
Showing 35 changed files with 825 additions and 153 deletions.
24 changes: 19 additions & 5 deletions cli/src/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -105,18 +105,30 @@ pub fn build_file<'a>(
// To do this we will need to preprocess files just for their exported symbols.
// Also, we should no longer need to do this once we have platforms on
// a package repository, as we can then get precompiled hosts from there.

let exposed_values = loaded
.exposed_to_host
.values
.keys()
.map(|x| x.as_str(&loaded.interns).to_string())
.collect();

let exposed_closure_types = loaded
.exposed_to_host
.closure_types
.iter()
.map(|x| x.as_str(&loaded.interns).to_string())
.collect();

let rebuild_thread = spawn_rebuild_thread(
opt_level,
surgically_link,
precompiled,
host_input_path.clone(),
binary_path.clone(),
target,
loaded
.exposed_to_host
.keys()
.map(|x| x.as_str(&loaded.interns).to_string())
.collect(),
exposed_values,
exposed_closure_types,
target_valgrind,
);

Expand Down Expand Up @@ -291,6 +303,7 @@ fn spawn_rebuild_thread(
binary_path: PathBuf,
target: &Triple,
exported_symbols: Vec<String>,
exported_closure_types: Vec<String>,
target_valgrind: bool,
) -> std::thread::JoinHandle<u128> {
let thread_local_target = target.clone();
Expand All @@ -305,6 +318,7 @@ fn spawn_rebuild_thread(
&thread_local_target,
host_input_path.as_path(),
exported_symbols,
exported_closure_types,
target_valgrind,
)
.unwrap();
Expand Down
6 changes: 4 additions & 2 deletions cli/src/format.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,11 @@ use roc_parse::ast::{
};
use roc_parse::header::{
AppHeader, Effects, ExposedName, ImportsEntry, InterfaceHeader, ModuleName, PackageEntry,
PackageName, PlatformHeader, PlatformRequires, PlatformRigid, To, TypedIdent,
PackageName, PlatformHeader, PlatformRequires, To, TypedIdent,
};
use roc_parse::{
ast::{Def, Module},
ident::UppercaseIdent,
module::{self, module_defs},
parser::{Parser, SyntaxError},
state::State,
Expand Down Expand Up @@ -176,6 +177,7 @@ impl<'a> RemoveSpaces<'a> for Module<'a> {
packages: header.packages.remove_spaces(arena),
imports: header.imports.remove_spaces(arena),
provides: header.provides.remove_spaces(arena),
provides_types: header.provides_types.map(|ts| ts.remove_spaces(arena)),
to: header.to.remove_spaces(arena),
before_header: &[],
after_app_keyword: &[],
Expand Down Expand Up @@ -285,7 +287,7 @@ impl<'a> RemoveSpaces<'a> for PlatformRequires<'a> {
}
}

impl<'a> RemoveSpaces<'a> for PlatformRigid<'a> {
impl<'a> RemoveSpaces<'a> for UppercaseIdent<'a> {
fn remove_spaces(&self, _arena: &'a Bump) -> Self {
*self
}
Expand Down
4 changes: 2 additions & 2 deletions cli/src/repl/gen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -146,8 +146,8 @@ pub fn gen_and_eval<'a>(
}
}

debug_assert_eq!(exposed_to_host.len(), 1);
let (main_fn_symbol, main_fn_var) = exposed_to_host.iter().next().unwrap();
debug_assert_eq!(exposed_to_host.values.len(), 1);
let (main_fn_symbol, main_fn_var) = exposed_to_host.values.iter().next().unwrap();
let main_fn_symbol = *main_fn_symbol;
let main_fn_var = *main_fn_var;

Expand Down
10 changes: 9 additions & 1 deletion cli/tests/cli_run.rs
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ mod cli_run {

let compile_out = run_roc(&[&["build", file.to_str().unwrap()], &all_flags[..]].concat());
if !compile_out.stderr.is_empty() {
panic!("{}", compile_out.stderr);
panic!("roc build had stderr: {}", compile_out.stderr);
}

assert!(compile_out.status.success(), "bad status {:?}", compile_out);
Expand Down Expand Up @@ -383,6 +383,14 @@ mod cli_run {
expected_ending: "Hi, Giovanni Giorgio!\n",
use_valgrind: true,
},
tui:"tui" => Example {
filename: "Main.roc",
executable_filename: "tui",
stdin: &["foo\n"], // NOTE: adding more lines leads to memory leaks
input_file: None,
expected_ending: "Hello Worldfoo!\n",
use_valgrind: true,
},
// custom_malloc:"custom-malloc" => Example {
// filename: "Main.roc",
// executable_filename: "custom-malloc-example",
Expand Down
89 changes: 46 additions & 43 deletions compiler/build/src/link.rs
Original file line number Diff line number Diff line change
Expand Up @@ -753,49 +753,52 @@ fn link_linux(

// NOTE: order of arguments to `ld` matters here!
// The `-l` flags should go after the `.o` arguments
Ok((
Command::new("ld")
// Don't allow LD_ env vars to affect this
.env_clear()
.env("PATH", &env_path)
// Keep NIX_ env vars
.envs(
env::vars()
.filter(|&(ref k, _)| k.starts_with("NIX_"))
.collect::<HashMap<String, String>>(),
)
.args(&[
"--gc-sections",
"--eh-frame-hdr",
"-A",
arch_str(target),
"-pie",
libcrt_path.join("crti.o").to_str().unwrap(),
libcrt_path.join("crtn.o").to_str().unwrap(),
])
.args(&base_args)
.args(&["-dynamic-linker", ld_linux])
.args(input_paths)
// ld.lld requires this argument, and does not accept --arch
// .args(&["-L/usr/lib/x86_64-linux-gnu"])
.args(&[
// Libraries - see https://github.com/rtfeldman/roc/pull/554#discussion_r496365925
// for discussion and further references
"-lc",
"-lm",
"-lpthread",
"-ldl",
"-lrt",
"-lutil",
"-lc_nonshared",
libgcc_path.to_str().unwrap(),
// Output
"-o",
output_path.as_path().to_str().unwrap(), // app (or app.so or app.dylib etc.)
])
.spawn()?,
output_path,
))

let mut command = Command::new("ld");

command
// Don't allow LD_ env vars to affect this
.env_clear()
.env("PATH", &env_path)
// Keep NIX_ env vars
.envs(
env::vars()
.filter(|&(ref k, _)| k.starts_with("NIX_"))
.collect::<HashMap<String, String>>(),
)
.args(&[
"--gc-sections",
"--eh-frame-hdr",
"-A",
arch_str(target),
"-pie",
libcrt_path.join("crti.o").to_str().unwrap(),
libcrt_path.join("crtn.o").to_str().unwrap(),
])
.args(&base_args)
.args(&["-dynamic-linker", ld_linux])
.args(input_paths)
// ld.lld requires this argument, and does not accept --arch
// .args(&["-L/usr/lib/x86_64-linux-gnu"])
.args(&[
// Libraries - see https://github.com/rtfeldman/roc/pull/554#discussion_r496365925
// for discussion and further references
"-lc",
"-lm",
"-lpthread",
"-ldl",
"-lrt",
"-lutil",
"-lc_nonshared",
libgcc_path.to_str().unwrap(),
// Output
"-o",
output_path.as_path().to_str().unwrap(), // app (or app.so or app.dylib etc.)
]);

let output = command.spawn()?;

Ok((output, output_path))
}

fn link_macos(
Expand Down
5 changes: 3 additions & 2 deletions compiler/build/src/program.rs
Original file line number Diff line number Diff line change
Expand Up @@ -290,7 +290,7 @@ pub fn gen_from_mono_module_llvm(
// in gen_tests, the compiler provides roc_panic
// and sets up the setjump/longjump exception handling
is_gen_test: false,
exposed_to_host: loaded.exposed_to_host.keys().copied().collect(),
exposed_to_host: loaded.exposed_to_host.values.keys().copied().collect(),
};

roc_gen_llvm::llvm::build::build_procedures(
Expand Down Expand Up @@ -495,6 +495,7 @@ fn gen_from_mono_module_dev_wasm32(

let exposed_to_host = loaded
.exposed_to_host
.values
.keys()
.copied()
.collect::<MutSet<_>>();
Expand Down Expand Up @@ -544,7 +545,7 @@ fn gen_from_mono_module_dev_assembly(
let env = roc_gen_dev::Env {
arena,
module_id,
exposed_to_host: exposed_to_host.keys().copied().collect(),
exposed_to_host: exposed_to_host.values.keys().copied().collect(),
lazy_literals,
generate_allocators,
};
Expand Down
22 changes: 20 additions & 2 deletions compiler/fmt/src/annotation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use crate::{
Buf,
};
use roc_parse::ast::{AliasHeader, AssignedField, Expr, Tag, TypeAnnotation};
use roc_parse::ident::UppercaseIdent;
use roc_region::all::Loc;

/// Does an AST node need parens around it?
Expand Down Expand Up @@ -107,6 +108,22 @@ where
}
}

impl<'a> Formattable for UppercaseIdent<'a> {
fn is_multiline(&self) -> bool {
false
}

fn format_with_options<'buf>(
&self,
buf: &mut Buf<'buf>,
_parens: Parens,
_newlines: Newlines,
_indent: u16,
) {
buf.push_str((*self).into())
}
}

impl<'a> Formattable for TypeAnnotation<'a> {
fn is_multiline(&self) -> bool {
use roc_parse::ast::TypeAnnotation::*;
Expand Down Expand Up @@ -246,8 +263,9 @@ impl<'a> Formattable for TypeAnnotation<'a> {
}

As(lhs, _spaces, AliasHeader { name, vars }) => {
// TODO use spaces?
lhs.value.format(buf, indent);
// TODO use _spaces?
lhs.value
.format_with_options(buf, Parens::InFunctionType, Newlines::No, indent);
buf.spaces(1);
buf.push_str("as");
buf.spaces(1);
Expand Down
28 changes: 11 additions & 17 deletions compiler/fmt/src/module.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,9 @@ use crate::Buf;
use roc_parse::ast::{Collection, Module, Spaced};
use roc_parse::header::{
AppHeader, Effects, ExposedName, ImportsEntry, InterfaceHeader, ModuleName, PackageEntry,
PackageName, PlatformHeader, PlatformRequires, PlatformRigid, To, TypedIdent,
PackageName, PlatformHeader, PlatformRequires, To, TypedIdent,
};
use roc_parse::ident::UppercaseIdent;
use roc_region::all::Loc;

pub fn fmt_module<'a, 'buf>(buf: &mut Buf<'buf>, module: &'a Module<'a>) {
Expand Down Expand Up @@ -76,7 +77,7 @@ pub fn fmt_app_header<'a, 'buf>(buf: &mut Buf<'buf>, header: &'a AppHeader<'a>)
buf.indent(indent);
buf.push_str("provides");
fmt_default_spaces(buf, header.after_provides, indent);
fmt_provides(buf, header.provides, indent);
fmt_provides(buf, header.provides, header.provides_types, indent);
fmt_default_spaces(buf, header.before_to, indent);
buf.indent(indent);
buf.push_str("to");
Expand Down Expand Up @@ -126,7 +127,7 @@ pub fn fmt_platform_header<'a, 'buf>(buf: &mut Buf<'buf>, header: &'a PlatformHe
buf.indent(indent);
buf.push_str("provides");
fmt_default_spaces(buf, header.after_provides, indent);
fmt_provides(buf, header.provides, indent);
fmt_provides(buf, header.provides, None, indent);

fmt_effects(buf, &header.effects, indent);
}
Expand Down Expand Up @@ -206,18 +207,6 @@ impl<'a, T: Formattable> Formattable for Spaced<'a, T> {
}
}

impl<'a> Formattable for PlatformRigid<'a> {
fn is_multiline(&self) -> bool {
false
}

fn format<'buf>(&self, buf: &mut Buf<'buf>, _indent: u16) {
buf.push_str(self.rigid);
buf.push_str("=>");
buf.push_str(self.alias);
}
}

fn fmt_imports<'a, 'buf>(
buf: &mut Buf<'buf>,
loc_entries: Collection<'a, Loc<Spaced<'a, ImportsEntry<'a>>>>,
Expand All @@ -228,10 +217,15 @@ fn fmt_imports<'a, 'buf>(

fn fmt_provides<'a, 'buf>(
buf: &mut Buf<'buf>,
loc_entries: Collection<'a, Loc<Spaced<'a, ExposedName<'a>>>>,
loc_exposed_names: Collection<'a, Loc<Spaced<'a, ExposedName<'a>>>>,
loc_provided_types: Option<Collection<'a, Loc<Spaced<'a, UppercaseIdent<'a>>>>>,
indent: u16,
) {
fmt_collection(buf, indent, '[', ']', loc_entries, Newlines::No)
fmt_collection(buf, indent, '[', ']', loc_exposed_names, Newlines::No);
if let Some(loc_provided_types) = loc_provided_types {
fmt_default_spaces(buf, &[], indent);
fmt_collection(buf, indent, '{', '}', loc_provided_types, Newlines::No);
}
}

fn fmt_to<'buf>(buf: &mut Buf<'buf>, to: To, indent: u16) {
Expand Down
2 changes: 1 addition & 1 deletion compiler/fmt/tests/test_fmt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2652,7 +2652,7 @@ mod test_fmt {
fn single_line_platform() {
module_formats_same(
"platform \"folkertdev/foo\" \
requires { model=>Model, msg=>Msg } { main : Effect {} } \
requires { Model, Msg } { main : Effect {} } \
exposes [] \
packages {} \
imports [ Task.{ Task } ] \
Expand Down
Loading

0 comments on commit 0c5f9ff

Please sign in to comment.