From c2d8205bfbce9eac2096fc260475e84f5c2566e2 Mon Sep 17 00:00:00 2001 From: Richard Feldman Date: Sun, 15 Nov 2020 21:13:22 -0500 Subject: [PATCH 01/35] Reproduce fun rustmft bug --- compiler/parse/src/module.rs | 35 +++++++++++++++++++++++++---------- 1 file changed, 25 insertions(+), 10 deletions(-) diff --git a/compiler/parse/src/module.rs b/compiler/parse/src/module.rs index da8288f4bd..0036a417e8 100644 --- a/compiler/parse/src/module.rs +++ b/compiler/parse/src/module.rs @@ -251,16 +251,31 @@ fn provides<'a>() -> impl Parser< Vec<'a, Located>>, ), > { - and!( - and!(skip_second!(space1(1), ascii_string("provides")), space1(1)), - collection!( - ascii_char(b'['), - loc!(exposes_entry()), - ascii_char(b','), - ascii_char(b']'), - 1 - ) - ) + map!( + and!( + and!(skip_second!(space1(1), ascii_string("provides")), space1(1)), + collection!( + ascii_char(b'['), + loc!(exposes_entry()), + ascii_char(b','), + ascii_char(b']'), + 1 + ) + ) + , + |((before_provides_keyword, after_provides_keyword), provides_entries| { + Provides { + provides_entries, + to, + before_provides_keyword, + after_provides_keyword, + before_to_keyword, + after_to_keyword, + } + } + ) + } + } } #[inline(always)] From ab1be6e394024db35c01df93bb1d56bb3d1c21e4 Mon Sep 17 00:00:00 2001 From: Richard Feldman Date: Sun, 15 Nov 2020 23:22:37 -0500 Subject: [PATCH 02/35] Update examples --- examples/closure/Closure.roc | 5 ++--- examples/effect/Main.roc | 2 +- examples/hello-world/Hello.roc | 2 +- examples/multi-module/Quicksort.roc | 6 +++--- examples/quicksort/Quicksort.roc | 10 ++-------- examples/shared-quicksort/Quicksort.roc | 5 ++--- 6 files changed, 11 insertions(+), 19 deletions(-) diff --git a/examples/closure/Closure.roc b/examples/closure/Closure.roc index 7dd2e10a5e..fcd157f768 100644 --- a/examples/closure/Closure.roc +++ b/examples/closure/Closure.roc @@ -1,9 +1,8 @@ -app Closure provides [ makeClosure ] imports [] +app "closure" provides [ makeClosure ] to "./platform/" makeClosure : ({} -> Int) as MyClosure -makeClosure = +makeClosure = x = 42 y = 42 \{} -> x + y - diff --git a/examples/effect/Main.roc b/examples/effect/Main.roc index 0821fd9f27..c13c2afb63 100644 --- a/examples/effect/Main.roc +++ b/examples/effect/Main.roc @@ -1,4 +1,4 @@ -app Main provides [ main ] imports [ Effect, RBTree ] +app "effect-example" provides [ main ] imports [ Effect, RBTree ] toAndFro : Int toAndFro = diff --git a/examples/hello-world/Hello.roc b/examples/hello-world/Hello.roc index fba6332807..d19e681b48 100644 --- a/examples/hello-world/Hello.roc +++ b/examples/hello-world/Hello.roc @@ -1,4 +1,4 @@ -app Hello provides [ main ] imports [] +app "hello-world" provides [ main ] to "./platform" greeting = hi = "Hello" diff --git a/examples/multi-module/Quicksort.roc b/examples/multi-module/Quicksort.roc index b5af1d1031..549d964954 100644 --- a/examples/multi-module/Quicksort.roc +++ b/examples/multi-module/Quicksort.roc @@ -1,8 +1,8 @@ -app Quicksort provides [ quicksort ] imports [ Utils.{swap} ] +app "quicksort" imports [ Utils.{ swap } ] provides [ quicksort ] to "./platform" quicksort : List Int -> List Int -quicksort = \originalList -> +quicksort = \originalList -> quicksortHelp : List (Num a), Int, Int -> List (Num a) quicksortHelp = \list, low, high -> if low < high then @@ -43,5 +43,5 @@ quicksort = \originalList -> - n = List.len originalList + n = List.len originalList quicksortHelp originalList 0 (n - 1) diff --git a/examples/quicksort/Quicksort.roc b/examples/quicksort/Quicksort.roc index cb87ad8ef5..d2e3cfd31b 100644 --- a/examples/quicksort/Quicksort.roc +++ b/examples/quicksort/Quicksort.roc @@ -1,4 +1,4 @@ -app Quicksort provides [ quicksort ] imports [] +app "quicksort" provides [ quicksort ] to "./platform" quicksort = \originalList -> @@ -52,11 +52,5 @@ quicksort = \originalList -> _ -> [] - n = List.len originalList + n = List.len originalList quicksortHelp originalList 0 (n - 1) - - - - - - diff --git a/examples/shared-quicksort/Quicksort.roc b/examples/shared-quicksort/Quicksort.roc index 28859806af..8e2b39410c 100644 --- a/examples/shared-quicksort/Quicksort.roc +++ b/examples/shared-quicksort/Quicksort.roc @@ -1,11 +1,11 @@ -app Quicksort provides [ quicksort ] imports [] +app "quicksort" provides [ quicksort ] to "./platform" quicksort : List Int -> List Int quicksort = \originalList -> helper originalList helper : List Int -> List Int helper = \originalList -> - + quicksortHelp : List (Num a), Int, Int -> List (Num a) quicksortHelp = \list, low, high -> if low < high then @@ -66,4 +66,3 @@ helper = \originalList -> # Absolutely make the `originalList` Shared by using it again here # but this branch is not evaluated, so should not affect performance List.set originalList 0 (List.len originalList) - From a78434fd482cf5e8fee91d54daca05612172bd46 Mon Sep 17 00:00:00 2001 From: Richard Feldman Date: Mon, 16 Nov 2020 23:34:45 -0500 Subject: [PATCH 03/35] Finish introducing new header keywords --- compiler/fmt/src/module.rs | 19 +-- compiler/load/src/file.rs | 15 ++- compiler/parse/src/ast.rs | 114 +---------------- compiler/parse/src/header.rs | 238 ++++++++++++++++++++++++++++++++--- compiler/parse/src/module.rs | 218 +++++++++++++++++++++++--------- compiler/parse/src/parser.rs | 10 +- 6 files changed, 404 insertions(+), 210 deletions(-) diff --git a/compiler/fmt/src/module.rs b/compiler/fmt/src/module.rs index 27b825ec55..aa856ca8ca 100644 --- a/compiler/fmt/src/module.rs +++ b/compiler/fmt/src/module.rs @@ -1,8 +1,7 @@ use crate::spaces::{fmt_spaces, INDENT}; use bumpalo::collections::{String, Vec}; -use roc_parse::ast::{ - AppHeader, ExposesEntry, ImportsEntry, InterfaceHeader, Module, PlatformHeader, -}; +use roc_parse::ast::Module; +use roc_parse::header::{AppHeader, ExposesEntry, ImportsEntry, InterfaceHeader, PlatformHeader}; use roc_region::all::Located; pub fn fmt_module<'a>(buf: &mut String<'a>, module: &'a Module<'a>) { @@ -113,7 +112,7 @@ fn fmt_imports<'a>( fn fmt_exposes<'a>( buf: &mut String<'a>, - loc_entries: &'a Vec<'a, Located>>, + loc_entries: &'a Vec<'a, Located>>, indent: u16, ) { buf.push('['); @@ -137,11 +136,11 @@ fn fmt_exposes<'a>( buf.push(']'); } -fn fmt_exposes_entry<'a>(buf: &mut String<'a>, entry: &'a ExposesEntry<'a>, indent: u16) { - use roc_parse::ast::ExposesEntry::*; +fn fmt_exposes_entry<'a>(buf: &mut String<'a>, entry: &'a ExposesEntry<'a, &'a str>, indent: u16) { + use roc_parse::header::ExposesEntry::*; match entry { - Ident(ident) => buf.push_str(ident), + Exposed(ident) => buf.push_str(ident), SpaceBefore(sub_entry, spaces) => { fmt_spaces(buf, spaces.iter(), indent); @@ -155,7 +154,7 @@ fn fmt_exposes_entry<'a>(buf: &mut String<'a>, entry: &'a ExposesEntry<'a>, inde } fn fmt_imports_entry<'a>(buf: &mut String<'a>, entry: &'a ImportsEntry<'a>, indent: u16) { - use roc_parse::ast::ImportsEntry::*; + use roc_parse::header::ImportsEntry::*; match entry { Module(module, loc_exposes_entries) => { @@ -176,6 +175,10 @@ fn fmt_imports_entry<'a>(buf: &mut String<'a>, entry: &'a ImportsEntry<'a>, inde } } + Package(_name, _entries) => { + todo!("TODO Format imported package"); + } + SpaceBefore(sub_entry, spaces) => { fmt_spaces(buf, spaces.iter(), indent); fmt_imports_entry(buf, sub_entry, indent); diff --git a/compiler/load/src/file.rs b/compiler/load/src/file.rs index a769bc2a98..1f505ad0ab 100644 --- a/compiler/load/src/file.rs +++ b/compiler/load/src/file.rs @@ -19,9 +19,8 @@ use roc_mono::ir::{ CapturedSymbols, ExternalSpecializations, PartialProc, PendingSpecialization, Proc, Procs, }; use roc_mono::layout::{Layout, LayoutCache}; -use roc_parse::ast::{ - self, Attempting, ExposesEntry, ImportsEntry, PlatformHeader, TypeAnnotation, TypedIdent, -}; +use roc_parse::ast::{self, Attempting, TypeAnnotation}; +use roc_parse::header::{ExposesEntry, ImportsEntry, PlatformHeader, TypedIdent}; use roc_parse::module::module_defs; use roc_parse::parser::{self, Fail, Parser}; use roc_region::all::{Located, Region}; @@ -2087,7 +2086,7 @@ fn load_from_str<'a>( fn send_header<'a>( name: Located>, filename: PathBuf, - exposes: &'a [Located>], + exposes: &'a [Located>], imports: &'a [Located>], parse_state: parser::State<'a>, module_ids: Arc>, @@ -2737,7 +2736,7 @@ fn parse<'a>(arena: &'a Bump, header: ModuleHeader<'a>) -> Result, Loadi } fn exposed_from_import(entry: &ImportsEntry<'_>) -> (ModuleName, Vec) { - use roc_parse::ast::ImportsEntry::*; + use roc_parse::header::ImportsEntry::*; match entry { Module(module_name, exposes) => { @@ -2757,11 +2756,11 @@ fn exposed_from_import(entry: &ImportsEntry<'_>) -> (ModuleName, Vec) { } } -fn ident_from_exposed(entry: &ExposesEntry<'_>) -> Ident { - use roc_parse::ast::ExposesEntry::*; +fn ident_from_exposed(entry: &ExposesEntry<'_, &str>) -> Ident { + use roc_parse::header::ExposesEntry::*; match entry { - Ident(ident) => (*ident).into(), + Exposed(ident) => (*ident).into(), SpaceBefore(sub_entry, _) | SpaceAfter(sub_entry, _) => ident_from_exposed(sub_entry), } } diff --git a/compiler/parse/src/ast.rs b/compiler/parse/src/ast.rs index f7bb798278..d707775ab9 100644 --- a/compiler/parse/src/ast.rs +++ b/compiler/parse/src/ast.rs @@ -1,7 +1,6 @@ -use crate::header::{ModuleName, PackageName}; +use crate::header::{AppHeader, ImportsEntry, InterfaceHeader, PlatformHeader, TypedIdent}; use crate::ident::Ident; use bumpalo::collections::String; -use bumpalo::collections::Vec; use bumpalo::Bump; use roc_module::operator::{BinOp, CalledVia, UnaryOp}; use roc_region::all::{Loc, Region}; @@ -13,20 +12,6 @@ pub enum Module<'a> { Platform { header: PlatformHeader<'a> }, } -#[derive(Clone, Debug, PartialEq)] -pub struct InterfaceHeader<'a> { - pub name: Loc>, - pub exposes: Vec<'a, Loc>>, - pub imports: Vec<'a, Loc>>, - - // Potential comments and newlines - these will typically all be empty. - pub after_interface_keyword: &'a [CommentOrNewline<'a>], - pub before_exposes: &'a [CommentOrNewline<'a>], - pub after_exposes: &'a [CommentOrNewline<'a>], - pub before_imports: &'a [CommentOrNewline<'a>], - pub after_imports: &'a [CommentOrNewline<'a>], -} - #[derive(Clone, Debug, PartialEq)] pub struct WhenBranch<'a> { pub patterns: &'a [Loc>], @@ -34,94 +19,6 @@ pub struct WhenBranch<'a> { pub guard: Option>>, } -#[derive(Clone, Debug, PartialEq)] -pub struct AppHeader<'a> { - pub name: Loc>, - pub provides: Vec<'a, Loc>>, - pub imports: Vec<'a, Loc>>, - - // Potential comments and newlines - these will typically all be empty. - pub after_app_keyword: &'a [CommentOrNewline<'a>], - pub before_provides: &'a [CommentOrNewline<'a>], - pub after_provides: &'a [CommentOrNewline<'a>], - pub before_imports: &'a [CommentOrNewline<'a>], - pub after_imports: &'a [CommentOrNewline<'a>], -} - -#[derive(Clone, Debug, PartialEq)] -pub struct PlatformHeader<'a> { - pub name: Loc>, - pub provides: Vec<'a, Loc>>, - pub requires: Vec<'a, Loc>>, - pub imports: Vec<'a, Loc>>, - pub effects: Effects<'a>, - - // Potential comments and newlines - these will typically all be empty. - pub after_platform_keyword: &'a [CommentOrNewline<'a>], - pub before_provides: &'a [CommentOrNewline<'a>], - pub after_provides: &'a [CommentOrNewline<'a>], - pub before_requires: &'a [CommentOrNewline<'a>], - pub after_requires: &'a [CommentOrNewline<'a>], - pub before_imports: &'a [CommentOrNewline<'a>], - pub after_imports: &'a [CommentOrNewline<'a>], -} - -#[derive(Clone, Debug, PartialEq)] -pub struct Effects<'a> { - pub spaces_before_effects_keyword: &'a [CommentOrNewline<'a>], - pub spaces_after_effects_keyword: &'a [CommentOrNewline<'a>], - pub spaces_after_type_name: &'a [CommentOrNewline<'a>], - pub type_name: &'a str, - pub entries: Vec<'a, Loc>>, -} - -#[derive(Clone, Debug, PartialEq)] -pub enum TypedIdent<'a> { - /// e.g. - /// - /// printLine : Str -> Effect {} - Entry { - ident: Loc<&'a str>, - spaces_before_colon: &'a [CommentOrNewline<'a>], - ann: Loc>, - }, - - // Spaces - SpaceBefore(&'a TypedIdent<'a>, &'a [CommentOrNewline<'a>]), - SpaceAfter(&'a TypedIdent<'a>, &'a [CommentOrNewline<'a>]), -} - -#[derive(Clone, Debug, PartialEq)] -pub enum ExposesEntry<'a> { - /// e.g. `Task` - Ident(&'a str), - - // Spaces - SpaceBefore(&'a ExposesEntry<'a>, &'a [CommentOrNewline<'a>]), - SpaceAfter(&'a ExposesEntry<'a>, &'a [CommentOrNewline<'a>]), -} - -#[derive(Clone, Debug, PartialEq)] -pub enum ImportsEntry<'a> { - /// e.g. `Task` or `Task.{ Task, after }` - Module(ModuleName<'a>, Vec<'a, Loc>>), - - // Spaces - SpaceBefore(&'a ImportsEntry<'a>, &'a [CommentOrNewline<'a>]), - SpaceAfter(&'a ImportsEntry<'a>, &'a [CommentOrNewline<'a>]), -} - -impl<'a> ExposesEntry<'a> { - pub fn as_str(&'a self) -> &'a str { - use ExposesEntry::*; - - match self { - Ident(string) => string, - SpaceBefore(sub_entry, _) | SpaceAfter(sub_entry, _) => sub_entry.as_str(), - } - } -} - #[derive(Clone, Debug, PartialEq)] pub struct WhenPattern<'a> { pub pattern: Loc>, @@ -633,15 +530,6 @@ impl<'a> Spaceable<'a> for TypeAnnotation<'a> { } } -impl<'a> Spaceable<'a> for ExposesEntry<'a> { - fn before(&'a self, spaces: &'a [CommentOrNewline<'a>]) -> Self { - ExposesEntry::SpaceBefore(self, spaces) - } - fn after(&'a self, spaces: &'a [CommentOrNewline<'a>]) -> Self { - ExposesEntry::SpaceAfter(self, spaces) - } -} - impl<'a> Spaceable<'a> for ImportsEntry<'a> { fn before(&'a self, spaces: &'a [CommentOrNewline<'a>]) -> Self { ImportsEntry::SpaceBefore(self, spaces) diff --git a/compiler/parse/src/header.rs b/compiler/parse/src/header.rs index 59d52d4606..75cf286084 100644 --- a/compiler/parse/src/header.rs +++ b/compiler/parse/src/header.rs @@ -1,15 +1,43 @@ -use crate::ast::CommentOrNewline; +use crate::ast::{CommentOrNewline, Spaceable, StrLiteral, TypeAnnotation}; +use crate::blankspace::space0; +use crate::ident::lowercase_ident; +use crate::module::package_name; +use crate::parser::{ascii_char, optional, Either, Parser}; +use crate::string_literal; use bumpalo::collections::Vec; use inlinable_string::InlinableString; use roc_region::all::Loc; -#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)] +#[derive(Clone, PartialEq, Eq, Debug, Hash)] pub struct PackageName<'a> { pub account: &'a str, pub pkg: &'a str, } -#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)] +#[derive(Clone, PartialEq, Eq, Debug, Hash)] +pub enum Version<'a> { + Exact(&'a str), + Range { + min: &'a str, + min_comparison: VersionComparison, + max: &'a str, + max_comparison: VersionComparison, + }, +} + +#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)] +pub enum VersionComparison { + AllowsEqual, + DisallowsEqual, +} + +#[derive(Clone, PartialEq, Debug)] +pub enum PackageOrPath<'a> { + Package(PackageName<'a>, Version<'a>), + Path(StrLiteral<'a>), +} + +#[derive(Clone, PartialEq, Eq, Debug, Hash)] pub struct ModuleName<'a>(&'a str); impl<'a> Into<&'a str> for ModuleName<'a> { @@ -34,15 +62,14 @@ impl<'a> ModuleName<'a> { } } -// TODO is this all duplicated from parse::ast? #[derive(Clone, Debug, PartialEq)] pub struct InterfaceHeader<'a> { pub name: Loc>, - pub exposes: Vec<'a, Loc>>, - pub imports: Vec<'a, (ModuleName<'a>, Vec<'a, Loc>>)>, + pub exposes: Vec<'a, Loc>>, + pub imports: Vec<'a, Loc>>, // Potential comments and newlines - these will typically all be empty. - pub after_interface: &'a [CommentOrNewline<'a>], + pub after_interface_keyword: &'a [CommentOrNewline<'a>], pub before_exposes: &'a [CommentOrNewline<'a>], pub after_exposes: &'a [CommentOrNewline<'a>], pub before_imports: &'a [CommentOrNewline<'a>], @@ -51,29 +78,202 @@ pub struct InterfaceHeader<'a> { #[derive(Clone, Debug, PartialEq)] pub struct AppHeader<'a> { - pub imports: Vec<'a, (ModuleName<'a>, Loc>)>, + pub name: Loc>, + pub packages: Vec<'a, Loc>>, + pub imports: Vec<'a, Loc>>, + pub provides: Vec<'a, Loc>>, + pub to: Loc<&'a str>, // Potential comments and newlines - these will typically all be empty. + pub after_app_keyword: &'a [CommentOrNewline<'a>], + pub before_packages: &'a [CommentOrNewline<'a>], + pub after_packages: &'a [CommentOrNewline<'a>], + pub before_imports: &'a [CommentOrNewline<'a>], + pub after_imports: &'a [CommentOrNewline<'a>], + pub before_provides: &'a [CommentOrNewline<'a>], + pub after_provides: &'a [CommentOrNewline<'a>], + pub before_to: &'a [CommentOrNewline<'a>], + pub after_to: &'a [CommentOrNewline<'a>], +} + +#[derive(Clone, Debug, PartialEq)] +pub struct PackageHeader<'a> { + pub name: Loc>, + pub exposes: Vec<'a, Loc>>, + pub packages: Vec<'a, (Loc<&'a str>, Loc>)>, + pub imports: Vec<'a, Loc>>, + + // Potential comments and newlines - these will typically all be empty. + pub after_package_keyword: &'a [CommentOrNewline<'a>], + pub before_exposes: &'a [CommentOrNewline<'a>], + pub after_exposes: &'a [CommentOrNewline<'a>], + pub before_packages: &'a [CommentOrNewline<'a>], + pub after_packages: &'a [CommentOrNewline<'a>], pub before_imports: &'a [CommentOrNewline<'a>], pub after_imports: &'a [CommentOrNewline<'a>], } #[derive(Clone, Debug, PartialEq)] -pub enum Exposes<'a> { - /// e.g. `Task` - Ident(&'a str), +pub struct PlatformHeader<'a> { + pub name: Loc>, + pub requires: Vec<'a, Loc>>, + pub exposes: Vec<'a, Loc>>>, + pub packages: Vec<'a, Loc>>, + pub imports: Vec<'a, Loc>>, + pub provides: Vec<'a, Loc>>, + pub effects: Effects<'a>, - // Spaces - SpaceBefore(&'a Exposes<'a>, &'a [CommentOrNewline<'a>]), - SpaceAfter(&'a Exposes<'a>, &'a [CommentOrNewline<'a>]), + // Potential comments and newlines - these will typically all be empty. + pub after_platform_keyword: &'a [CommentOrNewline<'a>], + pub before_requires: &'a [CommentOrNewline<'a>], + pub after_requires: &'a [CommentOrNewline<'a>], + pub before_exposes: &'a [CommentOrNewline<'a>], + pub after_exposes: &'a [CommentOrNewline<'a>], + pub before_packages: &'a [CommentOrNewline<'a>], + pub after_packages: &'a [CommentOrNewline<'a>], + pub before_imports: &'a [CommentOrNewline<'a>], + pub after_imports: &'a [CommentOrNewline<'a>], + pub before_provides: &'a [CommentOrNewline<'a>], + pub after_provides: &'a [CommentOrNewline<'a>], } #[derive(Clone, Debug, PartialEq)] -pub enum Imports<'a> { - /// e.g. `Task` or `Task.{ Task, after }` - Ident(&'a str, Vec<'a, &'a str>), +pub struct Effects<'a> { + pub spaces_before_effects_keyword: &'a [CommentOrNewline<'a>], + pub spaces_after_effects_keyword: &'a [CommentOrNewline<'a>], + pub spaces_after_type_name: &'a [CommentOrNewline<'a>], + pub type_name: &'a str, + pub entries: Vec<'a, Loc>>, +} + +#[derive(Clone, Debug, PartialEq)] +pub enum ExposesEntry<'a, T> { + /// e.g. `Task` + Exposed(T), // Spaces - SpaceBefore(&'a Imports<'a>, &'a [CommentOrNewline<'a>]), - SpaceAfter(&'a Imports<'a>, &'a [CommentOrNewline<'a>]), + SpaceBefore(&'a ExposesEntry<'a, T>, &'a [CommentOrNewline<'a>]), + SpaceAfter(&'a ExposesEntry<'a, T>, &'a [CommentOrNewline<'a>]), +} + +impl<'a, T> Spaceable<'a> for ExposesEntry<'a, T> { + fn before(&'a self, spaces: &'a [CommentOrNewline<'a>]) -> Self { + ExposesEntry::SpaceBefore(self, spaces) + } + fn after(&'a self, spaces: &'a [CommentOrNewline<'a>]) -> Self { + ExposesEntry::SpaceAfter(self, spaces) + } +} + +#[derive(Clone, Debug, PartialEq)] +pub enum ImportsEntry<'a> { + /// e.g. `Task` or `Task.{ Task, after }` + Module(ModuleName<'a>, Vec<'a, Loc>>), + + /// e.g. `base.Task` or `base.Task.{ after }` or `base.{ Task.{ Task, after } }` + Package(&'a str, Vec<'a, Loc<&'a ImportsEntry<'a>>>), + + // Spaces + SpaceBefore(&'a ImportsEntry<'a>, &'a [CommentOrNewline<'a>]), + SpaceAfter(&'a ImportsEntry<'a>, &'a [CommentOrNewline<'a>]), +} + +impl<'a> ExposesEntry<'a, &'a str> { + pub fn as_str(&'a self) -> &'a str { + use ExposesEntry::*; + + match self { + Exposed(string) => string, + SpaceBefore(sub_entry, _) | SpaceAfter(sub_entry, _) => sub_entry.as_str(), + } + } +} + +#[derive(Clone, Debug, PartialEq)] +pub enum TypedIdent<'a> { + /// e.g. + /// + /// printLine : Str -> Effect {} + Entry { + ident: Loc<&'a str>, + spaces_before_colon: &'a [CommentOrNewline<'a>], + ann: Loc>, + }, + + // Spaces + SpaceBefore(&'a TypedIdent<'a>, &'a [CommentOrNewline<'a>]), + SpaceAfter(&'a TypedIdent<'a>, &'a [CommentOrNewline<'a>]), +} + +#[derive(Clone, Debug, PartialEq)] +pub enum PackageEntry<'a> { + Entry { + shorthand: &'a str, + spaces_after_shorthand: &'a [CommentOrNewline<'a>], + package_or_path: Loc>, + }, + + // Spaces + SpaceBefore(&'a PackageEntry<'a>, &'a [CommentOrNewline<'a>]), + SpaceAfter(&'a PackageEntry<'a>, &'a [CommentOrNewline<'a>]), +} + +impl<'a> Spaceable<'a> for PackageEntry<'a> { + fn before(&'a self, spaces: &'a [CommentOrNewline<'a>]) -> Self { + PackageEntry::SpaceBefore(self, spaces) + } + fn after(&'a self, spaces: &'a [CommentOrNewline<'a>]) -> Self { + PackageEntry::SpaceAfter(self, spaces) + } +} + +pub fn package_entry<'a>() -> impl Parser<'a, PackageEntry<'a>> { + move |arena, state| { + // You may optionally have a package shorthand, + // e.g. "uc" in `uc: roc/unicode 1.0.0` + // + // (Indirect dependencies don't have a shorthand.) + let (opt_shorthand, state) = optional(and!( + skip_second!(lowercase_ident(), ascii_char(b':')), + space0(1) + )) + .parse(arena, state)?; + let (package_or_path, state) = loc!(package_or_path()).parse(arena, state)?; + let entry = match opt_shorthand { + Some((shorthand, spaces_after_shorthand)) => PackageEntry::Entry { + shorthand, + spaces_after_shorthand, + package_or_path, + }, + None => PackageEntry::Entry { + shorthand: "", + spaces_after_shorthand: &[], + package_or_path, + }, + }; + + Ok((entry, state)) + } +} + +fn package_or_path<'a>() -> impl Parser<'a, PackageOrPath<'a>> { + map!( + either!( + string_literal::parse(), + and!( + package_name(), + skip_first!(one_or_more!(ascii_char(b' ')), package_version()) + ) + ), + |answer| { + match answer { + Either::First(str_literal) => PackageOrPath::Path(str_literal), + Either::Second((name, version)) => PackageOrPath::Package(name, version), + } + } + ) +} + +fn package_version<'a>() -> impl Parser<'a, Version<'a>> { + move |_, _| todo!("TODO parse package version") } diff --git a/compiler/parse/src/module.rs b/compiler/parse/src/module.rs index 0036a417e8..dd82351e28 100644 --- a/compiler/parse/src/module.rs +++ b/compiler/parse/src/module.rs @@ -1,15 +1,16 @@ -use crate::ast::{ - AppHeader, Attempting, CommentOrNewline, Def, Effects, ExposesEntry, ImportsEntry, - InterfaceHeader, Module, PlatformHeader, TypedIdent, -}; +use crate::ast::{Attempting, CommentOrNewline, Def, Module}; use crate::blankspace::{space0, space0_around, space0_before, space1}; use crate::expr::def; -use crate::header::{ModuleName, PackageName}; +use crate::header::{ + package_entry, AppHeader, Effects, ExposesEntry, ImportsEntry, InterfaceHeader, ModuleName, + PackageEntry, PackageName, PlatformHeader, TypedIdent, +}; use crate::ident::{lowercase_ident, unqualified_ident, uppercase_ident}; use crate::parser::{ self, ascii_char, ascii_string, loc, optional, peek_utf8_char, peek_utf8_char_at, unexpected, unexpected_eof, ParseResult, Parser, State, }; +use crate::string_literal; use crate::type_annotation; use bumpalo::collections::{String, Vec}; use bumpalo::Bump; @@ -44,7 +45,7 @@ pub fn interface_header<'a>() -> impl Parser<'a, InterfaceHeader<'a>> { ascii_string("interface"), and!(space1(1), loc!(module_name())) ), - and!(exposes(), imports()) + and!(exposes_values(), imports()) ), |( (after_interface_keyword, name), @@ -176,25 +177,31 @@ pub fn module_name<'a>() -> impl Parser<'a, ModuleName<'a>> { fn app_header<'a>() -> impl Parser<'a, AppHeader<'a>> { parser::map( and!( - skip_first!(ascii_string("app"), and!(space1(1), loc!(module_name()))), - and!(provides(), imports()) + skip_first!( + ascii_string("app"), + and!(space1(1), loc!(string_literal::parse())) + ), + and!(packages(), and!(imports(), provides_to())) ), |( (after_app_keyword, name), - ( - ((before_provides, after_provides), provides), - ((before_imports, after_imports), imports), - ), + (packages, (((before_imports, after_imports), imports), provides)), )| { AppHeader { name, - provides, + packages: packages.entries, imports, + provides: provides.entries, + to: provides.to, after_app_keyword, - before_provides, - after_provides, + before_packages: packages.before_packages_keyword, + after_packages: packages.after_packages_keyword, before_imports, after_imports, + before_provides: provides.before_provides_keyword, + after_provides: provides.after_provides_keyword, + before_to: provides.before_to_keyword, + after_to: provides.after_to_keyword, } }, ) @@ -208,31 +215,49 @@ fn platform_header<'a>() -> impl Parser<'a, PlatformHeader<'a>> { ascii_string("platform"), and!(space1(1), loc!(package_name())) ), - and!(provides(), and!(requires(), and!(imports(), effects()))) + and!( + and!( + and!(requires(), and!(exposes_modules(), packages())), + and!(imports(), provides_without_to()) + ), + effects() + ) ), |( (after_platform_keyword, name), ( - ((before_provides, after_provides), provides), ( - ((before_requires, after_requires), requires), - (((before_imports, after_imports), imports), effects), + ( + ((before_requires, after_requires), requires), + (((before_exposes, after_exposes), exposes), packages), + ), + ( + ((before_imports, after_imports), imports), + ((before_provides, after_provides), provides), + ), ), + effects, ), )| { PlatformHeader { name, - provides, requires, + exposes, + packages: packages.entries, imports, + provides, effects, after_platform_keyword, - before_provides, - after_provides, before_requires, after_requires, + before_exposes, + after_exposes, + before_packages: packages.before_packages_keyword, + after_packages: packages.after_packages_keyword, before_imports, after_imports, + before_provides, + after_provides, } }, ) @@ -243,39 +268,69 @@ pub fn module_defs<'a>() -> impl Parser<'a, Vec<'a, Located>>> { zero_or_more!(space0_around(loc(def(0)), 0)) } +struct ProvidesTo<'a> { + entries: Vec<'a, Located>>, + to: Located<&'a str>, + + before_provides_keyword: &'a [CommentOrNewline<'a>], + after_provides_keyword: &'a [CommentOrNewline<'a>], + before_to_keyword: &'a [CommentOrNewline<'a>], + after_to_keyword: &'a [CommentOrNewline<'a>], +} + #[inline(always)] -fn provides<'a>() -> impl Parser< +fn provides_to<'a>() -> impl Parser<'a, ProvidesTo<'a>> { + map!( + and!( + and!(skip_second!(space1(1), ascii_string("provides")), space1(1)), + and!( + collection!( + ascii_char(b'['), + loc!(map!(unqualified_ident(), ExposesEntry::Exposed)), + ascii_char(b','), + ascii_char(b']'), + 1 + ), + and!( + space1(1), + skip_first!(ascii_string("to"), and!(space1(1), loc!(lowercase_ident()))) + ) + ) + ), + |( + (before_provides_keyword, after_provides_keyword), + (entries, (before_to_keyword, (after_to_keyword, to))), + )| { + ProvidesTo { + entries, + to, + before_provides_keyword, + after_provides_keyword, + before_to_keyword, + after_to_keyword, + } + } + ) +} + +#[inline(always)] +fn provides_without_to<'a>() -> impl Parser< 'a, ( (&'a [CommentOrNewline<'a>], &'a [CommentOrNewline<'a>]), - Vec<'a, Located>>, + Vec<'a, Located>>, ), > { - map!( - and!( - and!(skip_second!(space1(1), ascii_string("provides")), space1(1)), - collection!( - ascii_char(b'['), - loc!(exposes_entry()), - ascii_char(b','), - ascii_char(b']'), - 1 - ) - ) - , - |((before_provides_keyword, after_provides_keyword), provides_entries| { - Provides { - provides_entries, - to, - before_provides_keyword, - after_provides_keyword, - before_to_keyword, - after_to_keyword, - } - } - ) - } - } + and!( + and!(skip_second!(space1(1), ascii_string("provides")), space1(1)), + collection!( + ascii_char(b'['), + loc!(map!(unqualified_ident(), ExposesEntry::Exposed)), + ascii_char(b','), + ascii_char(b']'), + 1 + ) + ) } #[inline(always)] @@ -299,18 +354,18 @@ fn requires<'a>() -> impl Parser< } #[inline(always)] -fn exposes<'a>() -> impl Parser< +fn exposes_values<'a>() -> impl Parser< 'a, ( (&'a [CommentOrNewline<'a>], &'a [CommentOrNewline<'a>]), - Vec<'a, Located>>, + Vec<'a, Located>>, ), > { and!( and!(skip_second!(space1(1), ascii_string("exposes")), space1(1)), collection!( ascii_char(b'['), - loc!(exposes_entry()), + loc!(map!(unqualified_ident(), ExposesEntry::Exposed)), ascii_char(b','), ascii_char(b']'), 1 @@ -318,6 +373,56 @@ fn exposes<'a>() -> impl Parser< ) } +#[inline(always)] +fn exposes_modules<'a>() -> impl Parser< + 'a, + ( + (&'a [CommentOrNewline<'a>], &'a [CommentOrNewline<'a>]), + Vec<'a, Located>>>, + ), +> { + and!( + and!(skip_second!(space1(1), ascii_string("exposes")), space1(1)), + collection!( + ascii_char(b'['), + loc!(map!(module_name(), ExposesEntry::Exposed)), + ascii_char(b','), + ascii_char(b']'), + 1 + ) + ) +} + +struct Packages<'a> { + entries: Vec<'a, Located>>, + + before_packages_keyword: &'a [CommentOrNewline<'a>], + after_packages_keyword: &'a [CommentOrNewline<'a>], +} + +#[inline(always)] +fn packages<'a>() -> impl Parser<'a, Packages<'a>> { + map!( + and!( + and!(skip_second!(space1(1), ascii_string("packages")), space1(1)), + collection!( + ascii_char(b'{'), + loc!(package_entry()), + ascii_char(b','), + ascii_char(b'}'), + 1 + ) + ), + |((before_packages_keyword, after_packages_keyword), entries)| { + Packages { + entries, + before_packages_keyword, + after_packages_keyword, + } + } + ) +} + #[inline(always)] fn imports<'a>() -> impl Parser< 'a, @@ -397,11 +502,6 @@ fn typed_ident<'a>() -> impl Parser<'a, TypedIdent<'a>> { } } -#[inline(always)] -fn exposes_entry<'a>() -> impl Parser<'a, ExposesEntry<'a>> { - map!(unqualified_ident(), ExposesEntry::Ident) -} - #[inline(always)] fn imports_entry<'a>() -> impl Parser<'a, ImportsEntry<'a>> { map_with_arena!( @@ -413,7 +513,7 @@ fn imports_entry<'a>() -> impl Parser<'a, ImportsEntry<'a>> { ascii_char(b'.'), collection!( ascii_char(b'{'), - loc!(exposes_entry()), + loc!(map!(unqualified_ident(), ExposesEntry::Exposed)), ascii_char(b','), ascii_char(b'}'), 1 @@ -423,7 +523,7 @@ fn imports_entry<'a>() -> impl Parser<'a, ImportsEntry<'a>> { |arena, (module_name, opt_values): ( ModuleName<'a>, - Option>>> + Option>>> )| { let exposed_values = opt_values.unwrap_or_else(|| Vec::new_in(arena)); diff --git a/compiler/parse/src/parser.rs b/compiler/parse/src/parser.rs index 479bba7cc1..b09ce2543b 100644 --- a/compiler/parse/src/parser.rs +++ b/compiler/parse/src/parser.rs @@ -1037,7 +1037,11 @@ macro_rules! one_or_more { } } } - Err((_, new_state)) => Err(unexpected_eof(0, new_state.attempting, new_state)), + Err((_, new_state)) => Err($crate::parser::unexpected_eof( + 0, + new_state.attempting, + new_state, + )), } } }; @@ -1083,9 +1087,9 @@ macro_rules! either { let original_attempting = state.attempting; match $p1.parse(arena, state) { - Ok((output, state)) => Ok((Either::First(output), state)), + Ok((output, state)) => Ok(($crate::parser::Either::First(output), state)), Err((_, state)) => match $p2.parse(arena, state) { - Ok((output, state)) => Ok((Either::Second(output), state)), + Ok((output, state)) => Ok(($crate::parser::Either::Second(output), state)), Err((fail, state)) => Err(( Fail { attempting: original_attempting, From eb6a7b51ffc5894341b5748c8d29fc0bf98581f1 Mon Sep 17 00:00:00 2001 From: Richard Feldman Date: Wed, 18 Nov 2020 00:28:47 -0500 Subject: [PATCH 04/35] Use app path in output --- cli/src/build.rs | 6 +-- compiler/load/src/file.rs | 89 ++++++++++++++++++++++++++++-------- compiler/module/src/ident.rs | 1 + 3 files changed, 74 insertions(+), 22 deletions(-) diff --git a/cli/src/build.rs b/cli/src/build.rs index 2cbb70d078..c4e2dc02ed 100644 --- a/cli/src/build.rs +++ b/cli/src/build.rs @@ -85,6 +85,9 @@ pub fn build_file( buf ); + let cwd = app_o_file.parent().unwrap(); + let binary_path = cwd.join(&*loaded.output_path); // TODO should join ".exe" on Windows + program::gen_from_mono_module( &arena, loaded, @@ -106,11 +109,8 @@ pub fn build_file( size, ); - let cwd = app_o_file.parent().unwrap(); - // Step 2: link the precompiled host and compiled app let host_input_path = cwd.join("platform").join("host.o"); - let binary_path = cwd.join("app"); // TODO should be app.exe on Windows // TODO 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. diff --git a/compiler/load/src/file.rs b/compiler/load/src/file.rs index 1f505ad0ab..f3cba328a6 100644 --- a/compiler/load/src/file.rs +++ b/compiler/load/src/file.rs @@ -19,7 +19,7 @@ use roc_mono::ir::{ CapturedSymbols, ExternalSpecializations, PartialProc, PendingSpecialization, Proc, Procs, }; use roc_mono::layout::{Layout, LayoutCache}; -use roc_parse::ast::{self, Attempting, TypeAnnotation}; +use roc_parse::ast::{self, Attempting, StrLiteral, TypeAnnotation}; use roc_parse::header::{ExposesEntry, ImportsEntry, PlatformHeader, TypedIdent}; use roc_parse::module::module_defs; use roc_parse::parser::{self, Fail, Parser}; @@ -39,6 +39,9 @@ use std::str::from_utf8_unchecked; use std::sync::Arc; use std::time::{Duration, SystemTime}; +/// Default name for the binary generated for an app, if an invalid one was specified. +const DEFAULT_APP_OUTPUT_PATH: &str = "app"; + /// Filename extension for normal Roc modules const ROC_FILE_EXTENSION: &str = "roc"; @@ -533,7 +536,7 @@ pub enum BuildProblem<'a> { #[derive(Debug)] struct ModuleHeader<'a> { module_id: ModuleId, - module_name: ModuleName, + module_name: AppOrInterfaceName<'a>, module_path: PathBuf, exposed_ident_ids: IdentIds, deps_by_name: MutMap, @@ -580,6 +583,7 @@ pub struct MonomorphizedModule<'a> { pub module_id: ModuleId, pub interns: Interns, pub subs: Subs, + pub output_path: Box, pub can_problems: MutMap>, pub type_problems: MutMap>, pub mono_problems: MutMap>, @@ -598,7 +602,7 @@ pub struct VariablySizedLayouts<'a> { #[derive(Debug)] struct ParsedModule<'a> { module_id: ModuleId, - module_name: ModuleName, + module_name: AppOrInterfaceName<'a>, module_path: PathBuf, src: &'a str, module_timing: ModuleTiming, @@ -617,7 +621,7 @@ enum Msg<'a> { CanonicalizedAndConstrained { constrained_module: ConstrainedModule, canonicalization_problems: Vec, - module_docs: ModuleDocumentation, + module_docs: Option, }, MadeEffectModule { constrained_module: ConstrainedModule, @@ -671,6 +675,7 @@ struct State<'a> { pub goal_phase: Phase, pub stdlib: StdLib, pub exposed_types: SubsByModule, + pub output_path: Option<&'a str>, pub headers_parsed: MutSet, @@ -1242,6 +1247,7 @@ where root_id, goal_phase, stdlib, + output_path: None, module_cache: ModuleCache::default(), dependencies: Dependencies::default(), procedures: MutMap::default(), @@ -1426,6 +1432,22 @@ fn update<'a>( .sources .insert(parsed.module_id, (parsed.module_path.clone(), parsed.src)); + // If this was an app module, set the output path to be + // the module's declared "name". + // + // e.g. for `app "blah"` we should generate an output file named "blah" + match &parsed.module_name { + AppOrInterfaceName::App(output_str) => match output_str { + StrLiteral::PlainLine(path) => { + state.output_path = Some(path); + } + _ => { + todo!("TODO gracefully handle a malformed string literal after `app` keyword."); + } + }, + AppOrInterfaceName::Interface(_) => {} + } + let module_id = parsed.module_id; state.module_cache.parsed.insert(parsed.module_id, parsed); @@ -1449,10 +1471,9 @@ fn update<'a>( .can_problems .insert(module_id, canonicalization_problems); - state - .module_cache - .documentation - .insert(module_id, module_docs); + if let Some(docs) = module_docs { + state.module_cache.documentation.insert(module_id, docs); + } state .module_cache @@ -1750,6 +1771,7 @@ fn finish_specialization<'a>( let State { procedures, module_cache, + output_path, .. } = state; @@ -1770,6 +1792,7 @@ fn finish_specialization<'a>( can_problems, mono_problems, type_problems, + output_path: output_path.unwrap_or(DEFAULT_APP_OUTPUT_PATH).into(), exposed_to_host, module_id: state.root_id, subs, @@ -1966,7 +1989,10 @@ fn parse_header<'a>( match parsed { Ok((ast::Module::Interface { header }, parse_state)) => Ok(send_header( - header.name, + Located { + region: header.name.region, + value: AppOrInterfaceName::Interface(header.name.value), + }, filename, header.exposes.into_bump_slice(), header.imports.into_bump_slice(), @@ -1980,7 +2006,10 @@ fn parse_header<'a>( pkg_config_dir.pop(); let (module_id, app_module_header_msg) = send_header( - header.name, + Located { + region: header.name.region, + value: AppOrInterfaceName::App(header.name.value), + }, filename, header.provides.into_bump_slice(), header.imports.into_bump_slice(), @@ -2082,9 +2111,16 @@ fn load_from_str<'a>( ) } +#[derive(Debug)] +enum AppOrInterfaceName<'a> { + /// A filename + App(StrLiteral<'a>), + Interface(roc_parse::header::ModuleName<'a>), +} + #[allow(clippy::too_many_arguments)] fn send_header<'a>( - name: Located>, + loc_name: Located>, filename: PathBuf, exposes: &'a [Located>], imports: &'a [Located>], @@ -2093,10 +2129,17 @@ fn send_header<'a>( ident_ids_by_module: Arc>>, module_timing: ModuleTiming, ) -> (ModuleId, Msg<'a>) { - let declared_name: ModuleName = name.value.as_str().into(); + use AppOrInterfaceName::*; - // TODO check to see if declared_name is consistent with filename. - // If it isn't, report a problem! + let declared_name: ModuleName = match &loc_name.value { + App(_) => ModuleName::APP.into(), + Interface(module_name) => { + // TODO check to see if module_name is consistent with filename. + // If it isn't, report a problem! + + module_name.as_str().into() + } + }; let mut imported: Vec<(ModuleName, Vec, Region)> = Vec::with_capacity(imports.len()); let mut imported_modules: MutSet = MutSet::default(); @@ -2199,15 +2242,13 @@ fn send_header<'a>( // We always need to send these, even if deps is empty, // because the coordinator thread needs to receive this message // to decrement its "pending" count. - - // Send the header the main thread for processing, ( home, Msg::Header(ModuleHeader { module_id: home, module_path: filename, exposed_ident_ids: ident_ids, - module_name: declared_name, + module_name: loc_name.value, imported_modules, deps_by_name, exposes: exposed, @@ -2618,8 +2659,14 @@ fn canonicalize_and_constrain<'a>( // Generate documentation information // TODO: store timing information? - let module_docs = - crate::docs::generate_module_docs(module_name, &exposed_ident_ids, &parsed_defs); + let module_docs = match module_name { + AppOrInterfaceName::App(_) => None, + AppOrInterfaceName::Interface(name) => Some(crate::docs::generate_module_docs( + name.as_str().into(), + &exposed_ident_ids, + &parsed_defs, + )), + }; let mut var_store = VarStore::default(); let canonicalized = canonicalize_module_defs( @@ -2749,6 +2796,10 @@ fn exposed_from_import(entry: &ImportsEntry<'_>) -> (ModuleName, Vec) { (module_name.as_str().into(), exposed) } + Package(_package_name, _exposes) => { + todo!("TODO support exposing package-qualified module names."); + } + SpaceBefore(sub_entry, _) | SpaceAfter(sub_entry, _) => { // Ignore spaces. exposed_from_import(*sub_entry) diff --git a/compiler/module/src/ident.rs b/compiler/module/src/ident.rs index 4920a53826..f3bcb53561 100644 --- a/compiler/module/src/ident.rs +++ b/compiler/module/src/ident.rs @@ -59,6 +59,7 @@ impl TagName { impl ModuleName { // NOTE: After adding one of these, go to `impl ModuleId` and // add a corresponding ModuleId to there! + pub const APP: &'static str = ""; // app modules have no module name pub const BOOL: &'static str = "Bool"; pub const STR: &'static str = "Str"; pub const NUM: &'static str = "Num"; From f5a480f799e2367e20282181f1c668fa872b5cb3 Mon Sep 17 00:00:00 2001 From: Richard Feldman Date: Wed, 18 Nov 2020 00:33:05 -0500 Subject: [PATCH 05/35] Fix a test compilation error --- compiler/parse/tests/test_parse.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/parse/tests/test_parse.rs b/compiler/parse/tests/test_parse.rs index 3f07260220..3e90250eb4 100644 --- a/compiler/parse/tests/test_parse.rs +++ b/compiler/parse/tests/test_parse.rs @@ -24,9 +24,9 @@ mod test_parse { use roc_parse::ast::StrLiteral::*; use roc_parse::ast::StrSegment::*; use roc_parse::ast::{ - self, Attempting, Def, EscapedChar, InterfaceHeader, Spaceable, TypeAnnotation, WhenBranch, + self, Attempting, Def, EscapedChar, Spaceable, TypeAnnotation, WhenBranch, }; - use roc_parse::header::ModuleName; + use roc_parse::header::{InterfaceHeader, ModuleName}; use roc_parse::module::{interface_header, module_defs}; use roc_parse::parser::{Fail, FailReason, Parser, State}; use roc_parse::test_helpers::parse_expr_with; From 3e01df2bcf694bce9434188640f9948c89c42de2 Mon Sep 17 00:00:00 2001 From: Richard Feldman Date: Wed, 18 Nov 2020 22:33:30 -0500 Subject: [PATCH 06/35] Update parse tests to incorporate module headers --- cli/tests/fixtures/multi-dep-thunk/Main.roc | 2 +- .../fixtures/build/app_with_deps/Primary.roc | 2 +- .../build/app_with_deps/Quicksort.roc | 5 ++- .../build/app_with_deps/QuicksortOneDef.roc | 4 +- compiler/load/tests/test_load.rs | 28 ++++++------ compiler/parse/src/module.rs | 2 +- compiler/parse/src/test_helpers.rs | 2 +- compiler/parse/tests/test_parse.rs | 44 +++++++++++++++++-- 8 files changed, 63 insertions(+), 26 deletions(-) diff --git a/cli/tests/fixtures/multi-dep-thunk/Main.roc b/cli/tests/fixtures/multi-dep-thunk/Main.roc index c04b36b7d6..5559d5fc09 100644 --- a/cli/tests/fixtures/multi-dep-thunk/Main.roc +++ b/cli/tests/fixtures/multi-dep-thunk/Main.roc @@ -1,4 +1,4 @@ -app Main provides [ main ] imports [ Dep1 ] +app "test-app" provides [ main ] imports [ Dep1 ] main : Str main = Dep1.value1 {} diff --git a/compiler/load/tests/fixtures/build/app_with_deps/Primary.roc b/compiler/load/tests/fixtures/build/app_with_deps/Primary.roc index 50701ac9b4..8cf44b401d 100644 --- a/compiler/load/tests/fixtures/build/app_with_deps/Primary.roc +++ b/compiler/load/tests/fixtures/build/app_with_deps/Primary.roc @@ -1,4 +1,4 @@ -app Primary +app "primary" provides [ blah2, blah3, str, alwaysThree, identity, z, w, succeed, withDefault, yay ] imports [ Dep1, Dep2.{ two, foo }, Dep3.Blah.{ bar }, Res ] diff --git a/compiler/load/tests/fixtures/build/app_with_deps/Quicksort.roc b/compiler/load/tests/fixtures/build/app_with_deps/Quicksort.roc index 9cbf0c7e38..fc551081c9 100644 --- a/compiler/load/tests/fixtures/build/app_with_deps/Quicksort.roc +++ b/compiler/load/tests/fixtures/build/app_with_deps/Quicksort.roc @@ -1,6 +1,7 @@ -app Quicksort - provides [ swap, partition, partitionHelp, quicksort ] +app "quicksort" + packages {} imports [] + provides [ swap, partition, partitionHelp, quicksort ] to "blah" quicksort : List (Num a), Int, Int -> List (Num a) quicksort = \list, low, high -> diff --git a/compiler/load/tests/fixtures/build/app_with_deps/QuicksortOneDef.roc b/compiler/load/tests/fixtures/build/app_with_deps/QuicksortOneDef.roc index 43906df5ec..c7100377df 100644 --- a/compiler/load/tests/fixtures/build/app_with_deps/QuicksortOneDef.roc +++ b/compiler/load/tests/fixtures/build/app_with_deps/QuicksortOneDef.roc @@ -1,4 +1,4 @@ -app QuicksortOneDef provides [ quicksort ] imports [] +app "quicksort-one-def" provides [ quicksort ] imports [] quicksort = \originalList -> quicksortHelp : List (Num a), Int, Int -> List (Num a) @@ -53,5 +53,5 @@ quicksort = \originalList -> - n = List.len originalList + n = List.len originalList quicksortHelp originalList 0 (n - 1) diff --git a/compiler/load/tests/test_load.rs b/compiler/load/tests/test_load.rs index 97c6b7bbee..f62dab01a6 100644 --- a/compiler/load/tests/test_load.rs +++ b/compiler/load/tests/test_load.rs @@ -238,31 +238,31 @@ mod test_load { "RBTree", indoc!( r#" - interface RBTree exposes [ Dict, empty ] imports [] + interface RBTree exposes [ Dict, empty ] imports [] - # The color of a node. Leaves are considered Black. - NodeColor : [ Red, Black ] + # The color of a node. Leaves are considered Black. + NodeColor : [ Red, Black ] - Dict k v : [ Node NodeColor k v (Dict k v) (Dict k v), Empty ] + Dict k v : [ Node NodeColor k v (Dict k v) (Dict k v), Empty ] - # Create an empty dictionary. - empty : Dict k v - empty = - Empty - "# + # Create an empty dictionary. + empty : Dict k v + empty = + Empty + "# ), ), ( "Main", indoc!( r#" - app Test provides [ main ] imports [ RBTree ] + app "test-app" provides [ main ] imports [ RBTree ] - empty : RBTree.Dict Int Int - empty = RBTree.empty + empty : RBTree.Dict Int Int + empty = RBTree.empty - main = empty - "# + main = empty + "# ), ), ]; diff --git a/compiler/parse/src/module.rs b/compiler/parse/src/module.rs index dd82351e28..d6506967a3 100644 --- a/compiler/parse/src/module.rs +++ b/compiler/parse/src/module.rs @@ -174,7 +174,7 @@ pub fn module_name<'a>() -> impl Parser<'a, ModuleName<'a>> { } #[inline(always)] -fn app_header<'a>() -> impl Parser<'a, AppHeader<'a>> { +pub fn app_header<'a>() -> impl Parser<'a, AppHeader<'a>> { parser::map( and!( skip_first!( diff --git a/compiler/parse/src/test_helpers.rs b/compiler/parse/src/test_helpers.rs index b7a78e2354..7887ee21ac 100644 --- a/compiler/parse/src/test_helpers.rs +++ b/compiler/parse/src/test_helpers.rs @@ -12,10 +12,10 @@ pub fn parse_expr_with<'a>(arena: &'a Bump, input: &'a str) -> Result(arena: &'a Bump, input: &'a str) -> Result, Fail> { let state = State::new(input.trim().as_bytes(), Attempting::Module); let answer = header().parse(arena, state); + answer .map(|(loc_expr, _)| loc_expr) .map_err(|(fail, _)| fail) diff --git a/compiler/parse/tests/test_parse.rs b/compiler/parse/tests/test_parse.rs index 3e90250eb4..ed698bd960 100644 --- a/compiler/parse/tests/test_parse.rs +++ b/compiler/parse/tests/test_parse.rs @@ -21,13 +21,13 @@ mod test_parse { use roc_parse::ast::CommentOrNewline::*; use roc_parse::ast::Expr::{self, *}; use roc_parse::ast::Pattern::{self, *}; - use roc_parse::ast::StrLiteral::*; + use roc_parse::ast::StrLiteral::{self, *}; use roc_parse::ast::StrSegment::*; use roc_parse::ast::{ self, Attempting, Def, EscapedChar, Spaceable, TypeAnnotation, WhenBranch, }; - use roc_parse::header::{InterfaceHeader, ModuleName}; - use roc_parse::module::{interface_header, module_defs}; + use roc_parse::header::{AppHeader, InterfaceHeader, ModuleName}; + use roc_parse::module::{app_header, interface_header, module_defs}; use roc_parse::parser::{Fail, FailReason, Parser, State}; use roc_parse::test_helpers::parse_expr_with; use roc_region::all::{Located, Region}; @@ -2200,7 +2200,43 @@ mod test_parse { // MODULE #[test] - fn empty_module() { + fn empty_app_header() { + let arena = Bump::new(); + let packages = Vec::new_in(&arena); + let imports = Vec::new_in(&arena); + let provides = Vec::new_in(&arena); + let module_name = StrLiteral::PlainLine("test-app"); + let expected = AppHeader { + name: Located::new(0, 0, 4, 14, module_name), + packages, + imports, + provides, + to: Located::new(0, 0, 53, 57, "blah"), + after_app_keyword: &[], + before_packages: &[], + after_packages: &[], + before_imports: &[], + after_imports: &[], + before_provides: &[], + after_provides: &[], + before_to: &[], + after_to: &[], + }; + + let src = indoc!( + r#" + app "test-app" packages {} imports [] provides [] to blah + "# + ); + let actual = app_header() + .parse(&arena, State::new(src.as_bytes(), Attempting::Module)) + .map(|tuple| tuple.0); + + assert_eq!(Ok(expected), actual); + } + + #[test] + fn empty_interface_header() { let arena = Bump::new(); let exposes = Vec::new_in(&arena); let imports = Vec::new_in(&arena); From ce4469de806d6ad33be879ec581960e4e6baf6de Mon Sep 17 00:00:00 2001 From: Richard Feldman Date: Wed, 18 Nov 2020 23:02:19 -0500 Subject: [PATCH 07/35] Make packages and imports optional --- compiler/parse/src/module.rs | 43 +++++++++++++++++++++++------- compiler/parse/tests/test_parse.rs | 36 +++++++++++++++++++++++++ 2 files changed, 69 insertions(+), 10 deletions(-) diff --git a/compiler/parse/src/module.rs b/compiler/parse/src/module.rs index d6506967a3..3351fd59c0 100644 --- a/compiler/parse/src/module.rs +++ b/compiler/parse/src/module.rs @@ -175,27 +175,50 @@ pub fn module_name<'a>() -> impl Parser<'a, ModuleName<'a>> { #[inline(always)] pub fn app_header<'a>() -> impl Parser<'a, AppHeader<'a>> { - parser::map( + map_with_arena!( and!( skip_first!( ascii_string("app"), and!(space1(1), loc!(string_literal::parse())) ), - and!(packages(), and!(imports(), provides_to())) + and!( + optional(packages()), + and!(optional(imports()), provides_to()) + ) ), - |( - (after_app_keyword, name), - (packages, (((before_imports, after_imports), imports), provides)), - )| { + |arena, ((after_app_keyword, name), (opt_pkgs, (opt_imports, provides)))| { + let (before_packages, after_packages, package_entries) = match opt_pkgs { + Some(pkgs) => { + let pkgs: Packages<'a> = pkgs; // rustc must be told the type here + + ( + pkgs.before_packages_keyword, + pkgs.after_packages_keyword, + pkgs.entries, + ) + } + None => (&[] as _, &[] as _, Vec::new_in(arena)), + }; + + // rustc must be told the type here + let opt_imports: Option<( + (&'a [CommentOrNewline<'a>], &'a [CommentOrNewline<'a>]), + Vec<'a, Located>>, + )> = opt_imports; + + let ((before_imports, after_imports), imports) = + opt_imports.unwrap_or_else(|| ((&[] as _, &[] as _), Vec::new_in(arena))); + let provides: ProvidesTo<'a> = provides; // rustc must be told the type here + AppHeader { name, - packages: packages.entries, + packages: package_entries, imports, provides: provides.entries, to: provides.to, after_app_keyword, - before_packages: packages.before_packages_keyword, - after_packages: packages.after_packages_keyword, + before_packages, + after_packages, before_imports, after_imports, before_provides: provides.before_provides_keyword, @@ -203,7 +226,7 @@ pub fn app_header<'a>() -> impl Parser<'a, AppHeader<'a>> { before_to: provides.before_to_keyword, after_to: provides.after_to_keyword, } - }, + } ) } diff --git a/compiler/parse/tests/test_parse.rs b/compiler/parse/tests/test_parse.rs index ed698bd960..1fd8f0eaf5 100644 --- a/compiler/parse/tests/test_parse.rs +++ b/compiler/parse/tests/test_parse.rs @@ -2235,6 +2235,42 @@ mod test_parse { assert_eq!(Ok(expected), actual); } + #[test] + fn minimal_app_header() { + let arena = Bump::new(); + let packages = Vec::new_in(&arena); + let imports = Vec::new_in(&arena); + let provides = Vec::new_in(&arena); + let module_name = StrLiteral::PlainLine("test-app"); + let expected = AppHeader { + name: Located::new(0, 0, 4, 14, module_name), + packages, + imports, + provides, + to: Located::new(0, 0, 30, 34, "blah"), + after_app_keyword: &[], + before_packages: &[], + after_packages: &[], + before_imports: &[], + after_imports: &[], + before_provides: &[], + after_provides: &[], + before_to: &[], + after_to: &[], + }; + + let src = indoc!( + r#" + app "test-app" provides [] to blah + "# + ); + let actual = app_header() + .parse(&arena, State::new(src.as_bytes(), Attempting::Module)) + .map(|tuple| tuple.0); + + assert_eq!(Ok(expected), actual); + } + #[test] fn empty_interface_header() { let arena = Bump::new(); From a7eb56826752b6ba34b8cd85620ff02c3f3b5c30 Mon Sep 17 00:00:00 2001 From: Richard Feldman Date: Wed, 18 Nov 2020 23:14:07 -0500 Subject: [PATCH 08/35] Fix load tests --- .../fixtures/build/app_with_deps/Primary.roc | 5 +-- .../build/app_with_deps/Quicksort.roc | 5 ++- .../build/app_with_deps/QuicksortOneDef.roc | 2 +- compiler/load/tests/test_load.rs | 11 ++++-- compiler/parse/tests/test_parse.rs | 36 +++++++++++++++++++ examples/quicksort/Quicksort.roc | 2 +- examples/shared-quicksort/Quicksort.roc | 2 +- 7 files changed, 53 insertions(+), 10 deletions(-) diff --git a/compiler/load/tests/fixtures/build/app_with_deps/Primary.roc b/compiler/load/tests/fixtures/build/app_with_deps/Primary.roc index 8cf44b401d..abe12a64a3 100644 --- a/compiler/load/tests/fixtures/build/app_with_deps/Primary.roc +++ b/compiler/load/tests/fixtures/build/app_with_deps/Primary.roc @@ -1,6 +1,7 @@ app "primary" - provides [ blah2, blah3, str, alwaysThree, identity, z, w, succeed, withDefault, yay ] + packages { blah: "./blah" } imports [ Dep1, Dep2.{ two, foo }, Dep3.Blah.{ bar }, Res ] + provides [ blah2, blah3, str, alwaysThree, identity, z, w, succeed, withDefault, yay ] to blah blah2 = Dep2.two blah3 = bar @@ -12,7 +13,7 @@ alwaysThree = \_ -> "foo" identity = \a -> a -z = identity (Primary.alwaysThree {}) +z = identity (alwaysThree {}) w : Dep1.Identity {} w = Identity {} diff --git a/compiler/load/tests/fixtures/build/app_with_deps/Quicksort.roc b/compiler/load/tests/fixtures/build/app_with_deps/Quicksort.roc index fc551081c9..87facdda0d 100644 --- a/compiler/load/tests/fixtures/build/app_with_deps/Quicksort.roc +++ b/compiler/load/tests/fixtures/build/app_with_deps/Quicksort.roc @@ -1,7 +1,6 @@ app "quicksort" - packages {} - imports [] - provides [ swap, partition, partitionHelp, quicksort ] to "blah" + packages { base: "./platform" } + provides [ swap, partition, partitionHelp, quicksort ] to base quicksort : List (Num a), Int, Int -> List (Num a) quicksort = \list, low, high -> diff --git a/compiler/load/tests/fixtures/build/app_with_deps/QuicksortOneDef.roc b/compiler/load/tests/fixtures/build/app_with_deps/QuicksortOneDef.roc index c7100377df..e9978b2260 100644 --- a/compiler/load/tests/fixtures/build/app_with_deps/QuicksortOneDef.roc +++ b/compiler/load/tests/fixtures/build/app_with_deps/QuicksortOneDef.roc @@ -1,4 +1,4 @@ -app "quicksort-one-def" provides [ quicksort ] imports [] +app "quicksort" packages { base: "./platform" } provides [ quicksort ] to base quicksort = \originalList -> quicksortHelp : List (Num a), Int, Int -> List (Num a) diff --git a/compiler/load/tests/test_load.rs b/compiler/load/tests/test_load.rs index f62dab01a6..770c7a8be7 100644 --- a/compiler/load/tests/test_load.rs +++ b/compiler/load/tests/test_load.rs @@ -23,6 +23,7 @@ mod test_load { use roc_collections::all::MutMap; use roc_constrain::module::SubsByModule; use roc_load::file::LoadedModule; + use roc_module::ident::ModuleName; use roc_module::symbol::{Interns, ModuleId}; use roc_types::pretty_print::{content_to_string, name_all_type_vars}; use roc_types::subs::Subs; @@ -148,7 +149,10 @@ mod test_load { .get_name(loaded_module.module_id) .expect("Test ModuleID not found in module_ids"); - assert_eq!(expected_name, &InlinableString::from(module_name)); + // App module names are hardcoded and not based on anything user-specified + if expected_name != ModuleName::APP { + assert_eq!(expected_name, &InlinableString::from(module_name)); + } loaded_module } @@ -256,7 +260,10 @@ mod test_load { "Main", indoc!( r#" - app "test-app" provides [ main ] imports [ RBTree ] + app "test-app" + packages { blah: "./blah" } + imports [ RBTree ] + provides [ main ] to blah empty : RBTree.Dict Int Int empty = RBTree.empty diff --git a/compiler/parse/tests/test_parse.rs b/compiler/parse/tests/test_parse.rs index 1fd8f0eaf5..3e7a1cb10e 100644 --- a/compiler/parse/tests/test_parse.rs +++ b/compiler/parse/tests/test_parse.rs @@ -2271,6 +2271,42 @@ mod test_parse { assert_eq!(Ok(expected), actual); } + #[test] + fn full_app_header() { + let arena = Bump::new(); + let packages = Vec::new_in(&arena); + let imports = Vec::new_in(&arena); + let provides = Vec::new_in(&arena); + let module_name = StrLiteral::PlainLine("test-app"); + let expected = AppHeader { + name: Located::new(0, 0, 4, 14, module_name), + packages, + imports, + provides, + to: Located::new(0, 0, 30, 34, "blah"), + after_app_keyword: &[], + before_packages: &[], + after_packages: &[], + before_imports: &[], + after_imports: &[], + before_provides: &[], + after_provides: &[], + before_to: &[], + after_to: &[], + }; + + let src = indoc!( + r#" + app "quicksort" packages { base: "./platform" } provides [ quicksort ] to base + "# + ); + let actual = app_header() + .parse(&arena, State::new(src.as_bytes(), Attempting::Module)) + .map(|tuple| tuple.0); + + assert_eq!(Ok(expected), actual); + } + #[test] fn empty_interface_header() { let arena = Bump::new(); diff --git a/examples/quicksort/Quicksort.roc b/examples/quicksort/Quicksort.roc index d2e3cfd31b..a611a082f3 100644 --- a/examples/quicksort/Quicksort.roc +++ b/examples/quicksort/Quicksort.roc @@ -1,4 +1,4 @@ -app "quicksort" provides [ quicksort ] to "./platform" +app "quicksort" packages { base: "./platform" } provides [ quicksort ] to base quicksort = \originalList -> diff --git a/examples/shared-quicksort/Quicksort.roc b/examples/shared-quicksort/Quicksort.roc index 8e2b39410c..b75781e673 100644 --- a/examples/shared-quicksort/Quicksort.roc +++ b/examples/shared-quicksort/Quicksort.roc @@ -1,4 +1,4 @@ -app "quicksort" provides [ quicksort ] to "./platform" +app "quicksort" packages { base: "./platform" } provides [ quicksort ] to base quicksort : List Int -> List Int quicksort = \originalList -> helper originalList From 09d107e469caaff87ebdad017bcb05cdc86f5d22 Mon Sep 17 00:00:00 2001 From: Richard Feldman Date: Wed, 18 Nov 2020 23:28:30 -0500 Subject: [PATCH 09/35] Require packages and imports once again --- .../build/app_with_deps/Quicksort.roc | 1 + .../build/app_with_deps/QuicksortOneDef.roc | 2 +- compiler/parse/src/module.rs | 40 +++++-------------- compiler/parse/tests/test_parse.rs | 36 ----------------- 4 files changed, 12 insertions(+), 67 deletions(-) diff --git a/compiler/load/tests/fixtures/build/app_with_deps/Quicksort.roc b/compiler/load/tests/fixtures/build/app_with_deps/Quicksort.roc index 87facdda0d..6127fa6930 100644 --- a/compiler/load/tests/fixtures/build/app_with_deps/Quicksort.roc +++ b/compiler/load/tests/fixtures/build/app_with_deps/Quicksort.roc @@ -1,5 +1,6 @@ app "quicksort" packages { base: "./platform" } + imports [] provides [ swap, partition, partitionHelp, quicksort ] to base quicksort : List (Num a), Int, Int -> List (Num a) diff --git a/compiler/load/tests/fixtures/build/app_with_deps/QuicksortOneDef.roc b/compiler/load/tests/fixtures/build/app_with_deps/QuicksortOneDef.roc index e9978b2260..68ad8826eb 100644 --- a/compiler/load/tests/fixtures/build/app_with_deps/QuicksortOneDef.roc +++ b/compiler/load/tests/fixtures/build/app_with_deps/QuicksortOneDef.roc @@ -1,4 +1,4 @@ -app "quicksort" packages { base: "./platform" } provides [ quicksort ] to base +app "quicksort" packages { base: "./platform" } imports [] provides [ quicksort ] to base quicksort = \originalList -> quicksortHelp : List (Num a), Int, Int -> List (Num a) diff --git a/compiler/parse/src/module.rs b/compiler/parse/src/module.rs index 3351fd59c0..4e9c2764e2 100644 --- a/compiler/parse/src/module.rs +++ b/compiler/parse/src/module.rs @@ -175,50 +175,30 @@ pub fn module_name<'a>() -> impl Parser<'a, ModuleName<'a>> { #[inline(always)] pub fn app_header<'a>() -> impl Parser<'a, AppHeader<'a>> { - map_with_arena!( + map!( and!( skip_first!( ascii_string("app"), and!(space1(1), loc!(string_literal::parse())) ), - and!( - optional(packages()), - and!(optional(imports()), provides_to()) - ) + and!(packages(), and!(imports(), provides_to())) ), - |arena, ((after_app_keyword, name), (opt_pkgs, (opt_imports, provides)))| { - let (before_packages, after_packages, package_entries) = match opt_pkgs { - Some(pkgs) => { - let pkgs: Packages<'a> = pkgs; // rustc must be told the type here - - ( - pkgs.before_packages_keyword, - pkgs.after_packages_keyword, - pkgs.entries, - ) - } - None => (&[] as _, &[] as _, Vec::new_in(arena)), - }; - - // rustc must be told the type here - let opt_imports: Option<( - (&'a [CommentOrNewline<'a>], &'a [CommentOrNewline<'a>]), - Vec<'a, Located>>, - )> = opt_imports; - - let ((before_imports, after_imports), imports) = - opt_imports.unwrap_or_else(|| ((&[] as _, &[] as _), Vec::new_in(arena))); + |( + (after_app_keyword, name), + (pkgs, (((before_imports, after_imports), imports), provides)), + )| { + let pkgs: Packages<'a> = pkgs; // rustc must be told the type here let provides: ProvidesTo<'a> = provides; // rustc must be told the type here AppHeader { name, - packages: package_entries, + packages: pkgs.entries, imports, provides: provides.entries, to: provides.to, after_app_keyword, - before_packages, - after_packages, + before_packages: pkgs.before_packages_keyword, + after_packages: pkgs.after_packages_keyword, before_imports, after_imports, before_provides: provides.before_provides_keyword, diff --git a/compiler/parse/tests/test_parse.rs b/compiler/parse/tests/test_parse.rs index 3e7a1cb10e..a6943cab5e 100644 --- a/compiler/parse/tests/test_parse.rs +++ b/compiler/parse/tests/test_parse.rs @@ -2235,42 +2235,6 @@ mod test_parse { assert_eq!(Ok(expected), actual); } - #[test] - fn minimal_app_header() { - let arena = Bump::new(); - let packages = Vec::new_in(&arena); - let imports = Vec::new_in(&arena); - let provides = Vec::new_in(&arena); - let module_name = StrLiteral::PlainLine("test-app"); - let expected = AppHeader { - name: Located::new(0, 0, 4, 14, module_name), - packages, - imports, - provides, - to: Located::new(0, 0, 30, 34, "blah"), - after_app_keyword: &[], - before_packages: &[], - after_packages: &[], - before_imports: &[], - after_imports: &[], - before_provides: &[], - after_provides: &[], - before_to: &[], - after_to: &[], - }; - - let src = indoc!( - r#" - app "test-app" provides [] to blah - "# - ); - let actual = app_header() - .parse(&arena, State::new(src.as_bytes(), Attempting::Module)) - .map(|tuple| tuple.0); - - assert_eq!(Ok(expected), actual); - } - #[test] fn full_app_header() { let arena = Bump::new(); From ecfdadb5e3557f9b28784062cce513230cb9ff63 Mon Sep 17 00:00:00 2001 From: Richard Feldman Date: Wed, 18 Nov 2020 23:37:21 -0500 Subject: [PATCH 10/35] Revert "Require packages and imports once again" This reverts commit 119329dffc86edbb2bc0475dfcded905f0f19c04. --- .../build/app_with_deps/Quicksort.roc | 1 - .../build/app_with_deps/QuicksortOneDef.roc | 2 +- compiler/parse/src/module.rs | 40 ++++++++++++++----- compiler/parse/tests/test_parse.rs | 36 +++++++++++++++++ 4 files changed, 67 insertions(+), 12 deletions(-) diff --git a/compiler/load/tests/fixtures/build/app_with_deps/Quicksort.roc b/compiler/load/tests/fixtures/build/app_with_deps/Quicksort.roc index 6127fa6930..87facdda0d 100644 --- a/compiler/load/tests/fixtures/build/app_with_deps/Quicksort.roc +++ b/compiler/load/tests/fixtures/build/app_with_deps/Quicksort.roc @@ -1,6 +1,5 @@ app "quicksort" packages { base: "./platform" } - imports [] provides [ swap, partition, partitionHelp, quicksort ] to base quicksort : List (Num a), Int, Int -> List (Num a) diff --git a/compiler/load/tests/fixtures/build/app_with_deps/QuicksortOneDef.roc b/compiler/load/tests/fixtures/build/app_with_deps/QuicksortOneDef.roc index 68ad8826eb..e9978b2260 100644 --- a/compiler/load/tests/fixtures/build/app_with_deps/QuicksortOneDef.roc +++ b/compiler/load/tests/fixtures/build/app_with_deps/QuicksortOneDef.roc @@ -1,4 +1,4 @@ -app "quicksort" packages { base: "./platform" } imports [] provides [ quicksort ] to base +app "quicksort" packages { base: "./platform" } provides [ quicksort ] to base quicksort = \originalList -> quicksortHelp : List (Num a), Int, Int -> List (Num a) diff --git a/compiler/parse/src/module.rs b/compiler/parse/src/module.rs index 4e9c2764e2..3351fd59c0 100644 --- a/compiler/parse/src/module.rs +++ b/compiler/parse/src/module.rs @@ -175,30 +175,50 @@ pub fn module_name<'a>() -> impl Parser<'a, ModuleName<'a>> { #[inline(always)] pub fn app_header<'a>() -> impl Parser<'a, AppHeader<'a>> { - map!( + map_with_arena!( and!( skip_first!( ascii_string("app"), and!(space1(1), loc!(string_literal::parse())) ), - and!(packages(), and!(imports(), provides_to())) + and!( + optional(packages()), + and!(optional(imports()), provides_to()) + ) ), - |( - (after_app_keyword, name), - (pkgs, (((before_imports, after_imports), imports), provides)), - )| { - let pkgs: Packages<'a> = pkgs; // rustc must be told the type here + |arena, ((after_app_keyword, name), (opt_pkgs, (opt_imports, provides)))| { + let (before_packages, after_packages, package_entries) = match opt_pkgs { + Some(pkgs) => { + let pkgs: Packages<'a> = pkgs; // rustc must be told the type here + + ( + pkgs.before_packages_keyword, + pkgs.after_packages_keyword, + pkgs.entries, + ) + } + None => (&[] as _, &[] as _, Vec::new_in(arena)), + }; + + // rustc must be told the type here + let opt_imports: Option<( + (&'a [CommentOrNewline<'a>], &'a [CommentOrNewline<'a>]), + Vec<'a, Located>>, + )> = opt_imports; + + let ((before_imports, after_imports), imports) = + opt_imports.unwrap_or_else(|| ((&[] as _, &[] as _), Vec::new_in(arena))); let provides: ProvidesTo<'a> = provides; // rustc must be told the type here AppHeader { name, - packages: pkgs.entries, + packages: package_entries, imports, provides: provides.entries, to: provides.to, after_app_keyword, - before_packages: pkgs.before_packages_keyword, - after_packages: pkgs.after_packages_keyword, + before_packages, + after_packages, before_imports, after_imports, before_provides: provides.before_provides_keyword, diff --git a/compiler/parse/tests/test_parse.rs b/compiler/parse/tests/test_parse.rs index a6943cab5e..3e7a1cb10e 100644 --- a/compiler/parse/tests/test_parse.rs +++ b/compiler/parse/tests/test_parse.rs @@ -2235,6 +2235,42 @@ mod test_parse { assert_eq!(Ok(expected), actual); } + #[test] + fn minimal_app_header() { + let arena = Bump::new(); + let packages = Vec::new_in(&arena); + let imports = Vec::new_in(&arena); + let provides = Vec::new_in(&arena); + let module_name = StrLiteral::PlainLine("test-app"); + let expected = AppHeader { + name: Located::new(0, 0, 4, 14, module_name), + packages, + imports, + provides, + to: Located::new(0, 0, 30, 34, "blah"), + after_app_keyword: &[], + before_packages: &[], + after_packages: &[], + before_imports: &[], + after_imports: &[], + before_provides: &[], + after_provides: &[], + before_to: &[], + after_to: &[], + }; + + let src = indoc!( + r#" + app "test-app" provides [] to blah + "# + ); + let actual = app_header() + .parse(&arena, State::new(src.as_bytes(), Attempting::Module)) + .map(|tuple| tuple.0); + + assert_eq!(Ok(expected), actual); + } + #[test] fn full_app_header() { let arena = Bump::new(); From 186805110560d00f483bf26ecfe60b64846befd5 Mon Sep 17 00:00:00 2001 From: Richard Feldman Date: Wed, 18 Nov 2020 23:55:57 -0500 Subject: [PATCH 11/35] Allow for shorter app headers --- .../build/app_with_deps/Quicksort.roc | 4 +-- .../build/app_with_deps/QuicksortOneDef.roc | 2 +- compiler/parse/src/header.rs | 10 ++++-- compiler/parse/src/module.rs | 29 +++++++++++++---- compiler/parse/tests/test_parse.rs | 32 +++++++++++++------ examples/quicksort/Quicksort.roc | 2 +- 6 files changed, 57 insertions(+), 22 deletions(-) diff --git a/compiler/load/tests/fixtures/build/app_with_deps/Quicksort.roc b/compiler/load/tests/fixtures/build/app_with_deps/Quicksort.roc index 87facdda0d..af67b92f93 100644 --- a/compiler/load/tests/fixtures/build/app_with_deps/Quicksort.roc +++ b/compiler/load/tests/fixtures/build/app_with_deps/Quicksort.roc @@ -1,6 +1,4 @@ -app "quicksort" - packages { base: "./platform" } - provides [ swap, partition, partitionHelp, quicksort ] to base +app "quicksort" provides [ swap, partition, partitionHelp, quicksort ] to "./platform" quicksort : List (Num a), Int, Int -> List (Num a) quicksort = \list, low, high -> diff --git a/compiler/load/tests/fixtures/build/app_with_deps/QuicksortOneDef.roc b/compiler/load/tests/fixtures/build/app_with_deps/QuicksortOneDef.roc index e9978b2260..f199f07272 100644 --- a/compiler/load/tests/fixtures/build/app_with_deps/QuicksortOneDef.roc +++ b/compiler/load/tests/fixtures/build/app_with_deps/QuicksortOneDef.roc @@ -1,4 +1,4 @@ -app "quicksort" packages { base: "./platform" } provides [ quicksort ] to base +app "quicksort" provides [ quicksort ] to "./platform" quicksort = \originalList -> quicksortHelp : List (Num a), Int, Int -> List (Num a) diff --git a/compiler/parse/src/header.rs b/compiler/parse/src/header.rs index 75cf286084..7fda5784cb 100644 --- a/compiler/parse/src/header.rs +++ b/compiler/parse/src/header.rs @@ -76,13 +76,19 @@ pub struct InterfaceHeader<'a> { pub after_imports: &'a [CommentOrNewline<'a>], } +#[derive(Clone, Debug, PartialEq)] +pub enum To<'a> { + ExistingPackage(&'a str), + NewPackage(PackageOrPath<'a>), +} + #[derive(Clone, Debug, PartialEq)] pub struct AppHeader<'a> { pub name: Loc>, pub packages: Vec<'a, Loc>>, pub imports: Vec<'a, Loc>>, pub provides: Vec<'a, Loc>>, - pub to: Loc<&'a str>, + pub to: Loc>, // Potential comments and newlines - these will typically all be empty. pub after_app_keyword: &'a [CommentOrNewline<'a>], @@ -256,7 +262,7 @@ pub fn package_entry<'a>() -> impl Parser<'a, PackageEntry<'a>> { } } -fn package_or_path<'a>() -> impl Parser<'a, PackageOrPath<'a>> { +pub fn package_or_path<'a>() -> impl Parser<'a, PackageOrPath<'a>> { map!( either!( string_literal::parse(), diff --git a/compiler/parse/src/module.rs b/compiler/parse/src/module.rs index 3351fd59c0..d5382adff7 100644 --- a/compiler/parse/src/module.rs +++ b/compiler/parse/src/module.rs @@ -2,13 +2,14 @@ use crate::ast::{Attempting, CommentOrNewline, Def, Module}; use crate::blankspace::{space0, space0_around, space0_before, space1}; use crate::expr::def; use crate::header::{ - package_entry, AppHeader, Effects, ExposesEntry, ImportsEntry, InterfaceHeader, ModuleName, - PackageEntry, PackageName, PlatformHeader, TypedIdent, + package_entry, package_or_path, AppHeader, Effects, ExposesEntry, ImportsEntry, + InterfaceHeader, ModuleName, PackageEntry, PackageName, PackageOrPath, PlatformHeader, To, + TypedIdent, }; use crate::ident::{lowercase_ident, unqualified_ident, uppercase_ident}; use crate::parser::{ self, ascii_char, ascii_string, loc, optional, peek_utf8_char, peek_utf8_char_at, unexpected, - unexpected_eof, ParseResult, Parser, State, + unexpected_eof, Either, ParseResult, Parser, State, }; use crate::string_literal; use crate::type_annotation; @@ -293,7 +294,7 @@ pub fn module_defs<'a>() -> impl Parser<'a, Vec<'a, Located>>> { struct ProvidesTo<'a> { entries: Vec<'a, Located>>, - to: Located<&'a str>, + to: Located>, before_provides_keyword: &'a [CommentOrNewline<'a>], after_provides_keyword: &'a [CommentOrNewline<'a>], @@ -316,14 +317,30 @@ fn provides_to<'a>() -> impl Parser<'a, ProvidesTo<'a>> { ), and!( space1(1), - skip_first!(ascii_string("to"), and!(space1(1), loc!(lowercase_ident()))) + skip_first!( + ascii_string("to"), + and!( + space1(1), + loc!(either!(lowercase_ident(), package_or_path())) + ) + ) ) ) ), |( (before_provides_keyword, after_provides_keyword), - (entries, (before_to_keyword, (after_to_keyword, to))), + (entries, (before_to_keyword, (after_to_keyword, loc_to))), )| { + let loc_to: Located>> = loc_to; + let to_val = match loc_to.value { + Either::First(pkg) => To::ExistingPackage(pkg), + Either::Second(pkg) => To::NewPackage(pkg), + }; + let to = Located { + value: to_val, + region: loc_to.region, + }; + ProvidesTo { entries, to, diff --git a/compiler/parse/tests/test_parse.rs b/compiler/parse/tests/test_parse.rs index 3e7a1cb10e..067a2d708b 100644 --- a/compiler/parse/tests/test_parse.rs +++ b/compiler/parse/tests/test_parse.rs @@ -26,7 +26,9 @@ mod test_parse { use roc_parse::ast::{ self, Attempting, Def, EscapedChar, Spaceable, TypeAnnotation, WhenBranch, }; - use roc_parse::header::{AppHeader, InterfaceHeader, ModuleName}; + use roc_parse::header::{ + AppHeader, ExposesEntry, InterfaceHeader, ModuleName, PackageEntry, PackageOrPath, To, + }; use roc_parse::module::{app_header, interface_header, module_defs}; use roc_parse::parser::{Fail, FailReason, Parser, State}; use roc_parse::test_helpers::parse_expr_with; @@ -2211,7 +2213,7 @@ mod test_parse { packages, imports, provides, - to: Located::new(0, 0, 53, 57, "blah"), + to: Located::new(0, 0, 53, 57, To::ExistingPackage("blah")), after_app_keyword: &[], before_packages: &[], after_packages: &[], @@ -2237,6 +2239,8 @@ mod test_parse { #[test] fn minimal_app_header() { + use PackageOrPath::Path; + let arena = Bump::new(); let packages = Vec::new_in(&arena); let imports = Vec::new_in(&arena); @@ -2247,7 +2251,7 @@ mod test_parse { packages, imports, provides, - to: Located::new(0, 0, 30, 34, "blah"), + to: Located::new(0, 0, 30, 38, To::NewPackage(Path(PlainLine("./blah")))), after_app_keyword: &[], before_packages: &[], after_packages: &[], @@ -2261,7 +2265,7 @@ mod test_parse { let src = indoc!( r#" - app "test-app" provides [] to blah + app "test-app" provides [] to "./blah" "# ); let actual = app_header() @@ -2273,17 +2277,27 @@ mod test_parse { #[test] fn full_app_header() { + use ExposesEntry::Exposed; + use PackageOrPath::Path; + + let pkg_entry = PackageEntry::Entry { + shorthand: "base", + spaces_after_shorthand: &[], + package_or_path: Located::new(0, 0, 33, 45, Path(PlainLine("./platform"))), + }; + let loc_pkg_entry = Located::new(0, 0, 27, 45, pkg_entry); let arena = Bump::new(); - let packages = Vec::new_in(&arena); + let packages = bumpalo::vec![in &arena; loc_pkg_entry]; let imports = Vec::new_in(&arena); - let provides = Vec::new_in(&arena); - let module_name = StrLiteral::PlainLine("test-app"); + let provide_entry = Located::new(0, 0, 59, 68, Exposed("quicksort")); + let provides = bumpalo::vec![in &arena; provide_entry]; + let module_name = StrLiteral::PlainLine("quicksort"); let expected = AppHeader { - name: Located::new(0, 0, 4, 14, module_name), + name: Located::new(0, 0, 4, 15, module_name), packages, imports, provides, - to: Located::new(0, 0, 30, 34, "blah"), + to: Located::new(0, 0, 74, 78, To::ExistingPackage("base")), after_app_keyword: &[], before_packages: &[], after_packages: &[], diff --git a/examples/quicksort/Quicksort.roc b/examples/quicksort/Quicksort.roc index a611a082f3..425fe72057 100644 --- a/examples/quicksort/Quicksort.roc +++ b/examples/quicksort/Quicksort.roc @@ -1,4 +1,4 @@ -app "quicksort" packages { base: "./platform" } provides [ quicksort ] to base +app "quicksort" provides [ main ] to "./platform" quicksort = \originalList -> From a8ae25697d34dd34f4d6d2f15f38d950a8d882b5 Mon Sep 17 00:00:00 2001 From: Richard Feldman Date: Fri, 20 Nov 2020 22:09:23 -0500 Subject: [PATCH 12/35] Expose platform_header --- compiler/parse/src/module.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/parse/src/module.rs b/compiler/parse/src/module.rs index d5382adff7..09e395773a 100644 --- a/compiler/parse/src/module.rs +++ b/compiler/parse/src/module.rs @@ -232,7 +232,7 @@ pub fn app_header<'a>() -> impl Parser<'a, AppHeader<'a>> { } #[inline(always)] -fn platform_header<'a>() -> impl Parser<'a, PlatformHeader<'a>> { +pub fn platform_header<'a>() -> impl Parser<'a, PlatformHeader<'a>> { parser::map( and!( skip_first!( From c441471767e7136fe343a8f3267eeca85374089f Mon Sep 17 00:00:00 2001 From: Richard Feldman Date: Fri, 20 Nov 2020 22:09:44 -0500 Subject: [PATCH 13/35] Add parse tests for platform headers --- compiler/parse/tests/test_parse.rs | 115 ++++++++++++++++++++++++++++- 1 file changed, 113 insertions(+), 2 deletions(-) diff --git a/compiler/parse/tests/test_parse.rs b/compiler/parse/tests/test_parse.rs index 067a2d708b..889534414f 100644 --- a/compiler/parse/tests/test_parse.rs +++ b/compiler/parse/tests/test_parse.rs @@ -27,9 +27,10 @@ mod test_parse { self, Attempting, Def, EscapedChar, Spaceable, TypeAnnotation, WhenBranch, }; use roc_parse::header::{ - AppHeader, ExposesEntry, InterfaceHeader, ModuleName, PackageEntry, PackageOrPath, To, + AppHeader, Effects, ExposesEntry, InterfaceHeader, ModuleName, PackageEntry, PackageName, + PackageOrPath, PlatformHeader, To, }; - use roc_parse::module::{app_header, interface_header, module_defs}; + use roc_parse::module::{app_header, interface_header, module_defs, platform_header}; use roc_parse::parser::{Fail, FailReason, Parser, State}; use roc_parse::test_helpers::parse_expr_with; use roc_region::all::{Located, Region}; @@ -2321,6 +2322,116 @@ mod test_parse { assert_eq!(Ok(expected), actual); } + #[test] + fn empty_platform_header() { + let pkg_name = PackageName { + account: "rtfeldman", + pkg: "blah", + }; + let arena = Bump::new(); + let effects = Effects { + type_name: "Blah", + entries: Vec::new_in(&arena), + spaces_before_effects_keyword: &[], + spaces_after_effects_keyword: &[], + spaces_after_type_name: &[], + }; + let expected = PlatformHeader { + name: Located::new(0, 0, 9, 23, pkg_name), + requires: Vec::new_in(&arena), + exposes: Vec::new_in(&arena), + packages: Vec::new_in(&arena), + imports: Vec::new_in(&arena), + provides: Vec::new_in(&arena), + effects, + after_platform_keyword: &[], + before_requires: &[], + after_requires: &[], + before_exposes: &[], + after_exposes: &[], + before_packages: &[], + after_packages: &[], + before_imports: &[], + after_imports: &[], + before_provides: &[], + after_provides: &[], + }; + + let src = "platform rtfeldman/blah requires {} exposes [] packages {} imports [] provides [] effects Blah {}"; + let actual = platform_header() + .parse(&arena, State::new(src.as_bytes(), Attempting::Module)) + .map(|tuple| tuple.0); + + assert_eq!(Ok(expected), actual); + } + + #[test] + fn nonempty_platform_header() { + use ExposesEntry::Exposed; + use PackageOrPath::Path; + + let newlines = &[Newline]; + let pkg_name = PackageName { + account: "foo", + pkg: "barbaz", + }; + let pkg_entry = PackageEntry::Entry { + shorthand: "foo", + spaces_after_shorthand: &[], + package_or_path: Located::new(3, 3, 20, 27, Path(PlainLine("./foo"))), + }; + let loc_pkg_entry = Located::new(3, 3, 15, 27, pkg_entry); + let arena = Bump::new(); + let packages = bumpalo::vec![in &arena; loc_pkg_entry]; + let imports = Vec::new_in(&arena); + let provide_entry = Located::new(5, 5, 15, 26, Exposed("mainForHost")); + let provides = bumpalo::vec![in &arena; provide_entry]; + let effects = Effects { + type_name: "Effect", + entries: Vec::new_in(&arena), + spaces_before_effects_keyword: newlines, + spaces_after_effects_keyword: &[], + spaces_after_type_name: &[], + }; + let expected = PlatformHeader { + name: Located::new(0, 0, 9, 19, pkg_name), + requires: Vec::new_in(&arena), + exposes: Vec::new_in(&arena), + packages, + imports, + provides, + effects, + after_platform_keyword: &[], + before_requires: newlines, + after_requires: &[], + before_exposes: newlines, + after_exposes: &[], + before_packages: newlines, + after_packages: &[], + before_imports: newlines, + after_imports: &[], + before_provides: newlines, + after_provides: &[], + }; + + let src = indoc!( + r#" + platform foo/barbaz + requires {} + exposes [] + packages { foo: "./foo" } + imports [] + provides [ mainForHost ] + effects Effect {} + "# + ); + let actual = platform_header() + .parse(&arena, State::new(src.as_bytes(), Attempting::Module)) + .map(|tuple| tuple.0); + + assert_eq!(Ok(expected), actual); + } + #[test] fn empty_interface_header() { let arena = Bump::new(); From 759c047b4ce19d8b912415424e82a13ef75cf168 Mon Sep 17 00:00:00 2001 From: Richard Feldman Date: Fri, 20 Nov 2020 22:41:37 -0500 Subject: [PATCH 14/35] Add some .gitignores --- cli/tests/fixtures/.gitignore | 2 +- cli/tests/fixtures/multi-dep-str/.gitignore | 1 + cli/tests/fixtures/multi-dep-thunk/.gitignore | 1 + examples/.gitignore | 2 +- examples/hello-world/.gitignore | 1 + examples/multi-module/.gitignore | 1 + examples/quicksort/.gitignore | 1 + 7 files changed, 7 insertions(+), 2 deletions(-) create mode 100644 cli/tests/fixtures/multi-dep-str/.gitignore create mode 100644 cli/tests/fixtures/multi-dep-thunk/.gitignore create mode 100644 examples/hello-world/.gitignore create mode 100644 examples/multi-module/.gitignore create mode 100644 examples/quicksort/.gitignore diff --git a/cli/tests/fixtures/.gitignore b/cli/tests/fixtures/.gitignore index 997c1f6e7b..84792abbd6 100644 --- a/cli/tests/fixtures/.gitignore +++ b/cli/tests/fixtures/.gitignore @@ -1,4 +1,4 @@ app host.o c_host.o -app.dSYM +*.dSYM diff --git a/cli/tests/fixtures/multi-dep-str/.gitignore b/cli/tests/fixtures/multi-dep-str/.gitignore new file mode 100644 index 0000000000..0d35ca1e7a --- /dev/null +++ b/cli/tests/fixtures/multi-dep-str/.gitignore @@ -0,0 +1 @@ +multi-dep-str diff --git a/cli/tests/fixtures/multi-dep-thunk/.gitignore b/cli/tests/fixtures/multi-dep-thunk/.gitignore new file mode 100644 index 0000000000..2ffad1b586 --- /dev/null +++ b/cli/tests/fixtures/multi-dep-thunk/.gitignore @@ -0,0 +1 @@ +multi-dep-thunk diff --git a/examples/.gitignore b/examples/.gitignore index bc98244855..a6f6981d3d 100644 --- a/examples/.gitignore +++ b/examples/.gitignore @@ -2,4 +2,4 @@ app host.o c_host.o roc_app.o -app.dSYM +*.dSYM diff --git a/examples/hello-world/.gitignore b/examples/hello-world/.gitignore new file mode 100644 index 0000000000..6b820fd903 --- /dev/null +++ b/examples/hello-world/.gitignore @@ -0,0 +1 @@ +hello-world diff --git a/examples/multi-module/.gitignore b/examples/multi-module/.gitignore new file mode 100644 index 0000000000..19abff6005 --- /dev/null +++ b/examples/multi-module/.gitignore @@ -0,0 +1 @@ +quicksort diff --git a/examples/quicksort/.gitignore b/examples/quicksort/.gitignore new file mode 100644 index 0000000000..19abff6005 --- /dev/null +++ b/examples/quicksort/.gitignore @@ -0,0 +1 @@ +quicksort From 88d2ad1ffcf8b8e17379760c097c064dc3cbd94c Mon Sep 17 00:00:00 2001 From: Richard Feldman Date: Mon, 23 Nov 2020 00:00:13 -0500 Subject: [PATCH 15/35] Use roc__ prefix for exposed app functions --- cli/tests/fixtures/multi-dep-str/Main.roc | 2 +- .../multi-dep-str/platform/Pkg-Config.roc | 8 +++++--- .../fixtures/multi-dep-str/platform/src/lib.rs | 2 +- cli/tests/fixtures/multi-dep-thunk/Main.roc | 2 +- .../multi-dep-thunk/platform/Pkg-Config.roc | 8 +++++--- .../fixtures/multi-dep-thunk/platform/src/lib.rs | 2 +- compiler/gen/src/llvm/build.rs | 3 ++- examples/closure/platform/Pkg-Config.roc | 15 +++++++++++---- examples/effect/platform/Pkg-Config.roc | 4 +++- examples/hello-world/platform/Pkg-Config.roc | 8 +++++--- examples/hello-world/platform/src/lib.rs | 2 +- examples/multi-module/platform/Pkg-Config.roc | 8 +++++--- examples/multi-module/platform/src/lib.rs | 2 +- examples/quicksort/Quicksort.roc | 2 +- examples/quicksort/platform/Pkg-Config.roc | 8 +++++--- examples/quicksort/platform/src/lib.rs | 2 +- examples/shared-quicksort/platform/src/lib.rs | 2 +- 17 files changed, 50 insertions(+), 30 deletions(-) diff --git a/cli/tests/fixtures/multi-dep-str/Main.roc b/cli/tests/fixtures/multi-dep-str/Main.roc index 5a94037b88..69af7c5d9b 100644 --- a/cli/tests/fixtures/multi-dep-str/Main.roc +++ b/cli/tests/fixtures/multi-dep-str/Main.roc @@ -1,4 +1,4 @@ -app Main provides [ main ] imports [ Dep1 ] +app "multi-dep-str" imports [ Dep1 ] provides [ main ] to "./platform" main : Str main = Dep1.str1 diff --git a/cli/tests/fixtures/multi-dep-str/platform/Pkg-Config.roc b/cli/tests/fixtures/multi-dep-str/platform/Pkg-Config.roc index c8977f335d..6e7af88a5c 100644 --- a/cli/tests/fixtures/multi-dep-str/platform/Pkg-Config.roc +++ b/cli/tests/fixtures/multi-dep-str/platform/Pkg-Config.roc @@ -1,5 +1,7 @@ -platform roc/quicksort - provides [] - requires {} +platform examples/multi-module + requires { main : Str } + exposes [] + packages {} imports [] + provides [ main ] effects Effect {} diff --git a/cli/tests/fixtures/multi-dep-str/platform/src/lib.rs b/cli/tests/fixtures/multi-dep-str/platform/src/lib.rs index c41f2828ff..4d390b0560 100644 --- a/cli/tests/fixtures/multi-dep-str/platform/src/lib.rs +++ b/cli/tests/fixtures/multi-dep-str/platform/src/lib.rs @@ -3,7 +3,7 @@ use roc_std::RocStr; use std::str; extern "C" { - #[link_name = "Main_main_1_exposed"] + #[link_name = "roc__main_1_exposed"] fn say_hello(output: &mut RocCallResult) -> (); } diff --git a/cli/tests/fixtures/multi-dep-thunk/Main.roc b/cli/tests/fixtures/multi-dep-thunk/Main.roc index 5559d5fc09..2b2e3fc233 100644 --- a/cli/tests/fixtures/multi-dep-thunk/Main.roc +++ b/cli/tests/fixtures/multi-dep-thunk/Main.roc @@ -1,4 +1,4 @@ -app "test-app" provides [ main ] imports [ Dep1 ] +app "multi-dep-thunk" imports [ Dep1 ] provides [ main ] to "./platform" main : Str main = Dep1.value1 {} diff --git a/cli/tests/fixtures/multi-dep-thunk/platform/Pkg-Config.roc b/cli/tests/fixtures/multi-dep-thunk/platform/Pkg-Config.roc index c8977f335d..86d0701468 100644 --- a/cli/tests/fixtures/multi-dep-thunk/platform/Pkg-Config.roc +++ b/cli/tests/fixtures/multi-dep-thunk/platform/Pkg-Config.roc @@ -1,5 +1,7 @@ -platform roc/quicksort - provides [] - requires {} +platform examples/multi-dep-thunk + requires { main : Str } + exposes [] + packages {} imports [] + provides [ main ] effects Effect {} diff --git a/cli/tests/fixtures/multi-dep-thunk/platform/src/lib.rs b/cli/tests/fixtures/multi-dep-thunk/platform/src/lib.rs index c41f2828ff..4d390b0560 100644 --- a/cli/tests/fixtures/multi-dep-thunk/platform/src/lib.rs +++ b/cli/tests/fixtures/multi-dep-thunk/platform/src/lib.rs @@ -3,7 +3,7 @@ use roc_std::RocStr; use std::str; extern "C" { - #[link_name = "Main_main_1_exposed"] + #[link_name = "roc__main_1_exposed"] fn say_hello(output: &mut RocCallResult) -> (); } diff --git a/compiler/gen/src/llvm/build.rs b/compiler/gen/src/llvm/build.rs index dbd06bd64c..fc226fe1a6 100644 --- a/compiler/gen/src/llvm/build.rs +++ b/compiler/gen/src/llvm/build.rs @@ -1707,7 +1707,8 @@ fn expose_function_to_host<'a, 'ctx, 'env>( env: &Env<'a, 'ctx, 'env>, roc_function: FunctionValue<'ctx>, ) { - let c_function_name: String = format!("{}_exposed", roc_function.get_name().to_str().unwrap()); + let c_function_name: String = + format!("roc_{}_exposed", roc_function.get_name().to_str().unwrap()); let result = expose_function_to_host_help(env, roc_function, &c_function_name); diff --git a/examples/closure/platform/Pkg-Config.roc b/examples/closure/platform/Pkg-Config.roc index c8977f335d..8e351ef6ba 100644 --- a/examples/closure/platform/Pkg-Config.roc +++ b/examples/closure/platform/Pkg-Config.roc @@ -1,5 +1,12 @@ -platform roc/quicksort - provides [] - requires {} +platform examples/closure + requires { main : Effect {} } + exposes [] + packages {} imports [] - effects Effect {} + provides [ mainForHost ] + effects Effect + { + putChar : Int -> Effect {}, + putLine : Str -> Effect {}, + getLine : Effect Str + } diff --git a/examples/effect/platform/Pkg-Config.roc b/examples/effect/platform/Pkg-Config.roc index a463e3bbb9..ec2c67ca43 100644 --- a/examples/effect/platform/Pkg-Config.roc +++ b/examples/effect/platform/Pkg-Config.roc @@ -1,7 +1,9 @@ platform folkertdev/foo - provides [ mainForHost ] requires { main : Effect {} } + exposes [] + packages {} imports [] + provides [ mainForHost ] effects Effect { putChar : Int -> Effect {}, diff --git a/examples/hello-world/platform/Pkg-Config.roc b/examples/hello-world/platform/Pkg-Config.roc index c8977f335d..0f5b87c117 100644 --- a/examples/hello-world/platform/Pkg-Config.roc +++ b/examples/hello-world/platform/Pkg-Config.roc @@ -1,5 +1,7 @@ -platform roc/quicksort - provides [] - requires {} +platform examples/hello-world + requires { main : Str } + exposes [] + packages {} imports [] + provides [ main ] effects Effect {} diff --git a/examples/hello-world/platform/src/lib.rs b/examples/hello-world/platform/src/lib.rs index 8f8309e5e3..4d390b0560 100644 --- a/examples/hello-world/platform/src/lib.rs +++ b/examples/hello-world/platform/src/lib.rs @@ -3,7 +3,7 @@ use roc_std::RocStr; use std::str; extern "C" { - #[link_name = "Hello_main_1_exposed"] + #[link_name = "roc__main_1_exposed"] fn say_hello(output: &mut RocCallResult) -> (); } diff --git a/examples/multi-module/platform/Pkg-Config.roc b/examples/multi-module/platform/Pkg-Config.roc index c8977f335d..a414c550c9 100644 --- a/examples/multi-module/platform/Pkg-Config.roc +++ b/examples/multi-module/platform/Pkg-Config.roc @@ -1,5 +1,7 @@ -platform roc/quicksort - provides [] - requires {} +platform examples/multi-module + requires { quicksort : List (Num a) -> List (Num a) } + exposes [] + packages {} imports [] + provides [ main ] effects Effect {} diff --git a/examples/multi-module/platform/src/lib.rs b/examples/multi-module/platform/src/lib.rs index c175ee17d5..1166ccbb32 100644 --- a/examples/multi-module/platform/src/lib.rs +++ b/examples/multi-module/platform/src/lib.rs @@ -3,7 +3,7 @@ use roc_std::RocList; use std::time::SystemTime; extern "C" { - #[link_name = "Quicksort_quicksort_1_exposed"] + #[link_name = "roc__quicksort_1_exposed"] fn quicksort(list: RocList, output: &mut RocCallResult>) -> (); } diff --git a/examples/quicksort/Quicksort.roc b/examples/quicksort/Quicksort.roc index 425fe72057..d2e3cfd31b 100644 --- a/examples/quicksort/Quicksort.roc +++ b/examples/quicksort/Quicksort.roc @@ -1,4 +1,4 @@ -app "quicksort" provides [ main ] to "./platform" +app "quicksort" provides [ quicksort ] to "./platform" quicksort = \originalList -> diff --git a/examples/quicksort/platform/Pkg-Config.roc b/examples/quicksort/platform/Pkg-Config.roc index c8977f335d..c26ae3837c 100644 --- a/examples/quicksort/platform/Pkg-Config.roc +++ b/examples/quicksort/platform/Pkg-Config.roc @@ -1,5 +1,7 @@ -platform roc/quicksort - provides [] - requires {} +platform examples/quicksort + requires { quicksort : List (Num a) -> List (Num a) } + exposes [] + packages {} imports [] + provides [ main ] effects Effect {} diff --git a/examples/quicksort/platform/src/lib.rs b/examples/quicksort/platform/src/lib.rs index 3380455a85..53cf2f83b9 100644 --- a/examples/quicksort/platform/src/lib.rs +++ b/examples/quicksort/platform/src/lib.rs @@ -3,7 +3,7 @@ use roc_std::RocList; use std::time::SystemTime; extern "C" { - #[link_name = "Quicksort_quicksort_1_exposed"] + #[link_name = "roc__quicksort_1_exposed"] fn quicksort(list: RocList, output: &mut RocCallResult>) -> (); } diff --git a/examples/shared-quicksort/platform/src/lib.rs b/examples/shared-quicksort/platform/src/lib.rs index 5971d7a9de..85d5c80781 100644 --- a/examples/shared-quicksort/platform/src/lib.rs +++ b/examples/shared-quicksort/platform/src/lib.rs @@ -3,7 +3,7 @@ use roc_std::RocList; use std::time::SystemTime; extern "C" { - #[link_name = "Main_quicksort_1_exposed"] + #[link_name = "_quicksort_1_exposed"] fn quicksort(list: RocList, output: &mut RocCallResult>) -> (); } From da328f9e78601fad54b7616c5fac60fe23d1ee23 Mon Sep 17 00:00:00 2001 From: Richard Feldman Date: Fri, 20 Nov 2020 22:52:41 -0500 Subject: [PATCH 16/35] Fix gen tests --- compiler/gen/tests/gen_list.rs | 2 +- compiler/gen/tests/gen_primitives.rs | 56 ++++++++++++++-------------- compiler/gen/tests/gen_records.rs | 10 ++--- compiler/gen/tests/gen_tags.rs | 4 +- compiler/gen/tests/helpers/eval.rs | 2 +- 5 files changed, 37 insertions(+), 37 deletions(-) diff --git a/compiler/gen/tests/gen_list.rs b/compiler/gen/tests/gen_list.rs index 6562936abf..d69b74a0f4 100644 --- a/compiler/gen/tests/gen_list.rs +++ b/compiler/gen/tests/gen_list.rs @@ -1186,7 +1186,7 @@ mod gen_list { assert_evals_to!( indoc!( r#" - app Quicksort provides [ main ] imports [] + app "quicksort" provides [ main ] to "./platform" swap : Int, Int, List a -> List a diff --git a/compiler/gen/tests/gen_primitives.rs b/compiler/gen/tests/gen_primitives.rs index 90c695f2af..8ab6c06899 100644 --- a/compiler/gen/tests/gen_primitives.rs +++ b/compiler/gen/tests/gen_primitives.rs @@ -535,7 +535,7 @@ mod gen_primitives { assert_evals_to!( indoc!( r#" - app LinkedListLen0 provides [ main ] imports [] + app "test" provides [ main ] to "./platform" pi = 3.1415 @@ -553,7 +553,7 @@ mod gen_primitives { assert_non_opt_evals_to!( indoc!( r#" - app Test provides [ main ] imports [] + app "test" provides [ main ] to "./platform" LinkedList a : [ Nil, Cons a (LinkedList a) ] @@ -580,7 +580,7 @@ mod gen_primitives { assert_non_opt_evals_to!( indoc!( r#" - app LinkedListLenTwice0 provides [ main ] imports [] + app "test" provides [ main ] to "./platform" LinkedList a : [ Nil, Cons a (LinkedList a) ] @@ -607,7 +607,7 @@ mod gen_primitives { assert_non_opt_evals_to!( indoc!( r#" - app Test provides [ main ] imports [] + app "test" provides [ main ] to "./platform" LinkedList a : [ Nil, Cons a (LinkedList a) ] @@ -634,7 +634,7 @@ mod gen_primitives { assert_non_opt_evals_to!( indoc!( r#" - app Test provides [ main ] imports [] + app "test" provides [ main ] to "./platform" LinkedList a : [ Nil, Cons a (LinkedList a) ] @@ -661,7 +661,7 @@ mod gen_primitives { assert_non_opt_evals_to!( indoc!( r#" - app Test provides [ main ] imports [] + app "test" provides [ main ] to "./platform" LinkedList a : [ Nil, Cons a (LinkedList a) ] @@ -689,7 +689,7 @@ mod gen_primitives { assert_non_opt_evals_to!( indoc!( r#" - app Test provides [ main ] imports [] + app "test" provides [ main ] to "./platform" LinkedList a : [ Nil, Cons a (LinkedList a) ] @@ -717,7 +717,7 @@ mod gen_primitives { assert_non_opt_evals_to!( indoc!( r#" - app Test provides [ main ] imports [] + app "test" provides [ main ] to "./platform" LinkedList a : [ Nil, Cons a (LinkedList a) ] @@ -744,7 +744,7 @@ mod gen_primitives { assert_non_opt_evals_to!( indoc!( r#" - app Test provides [ main ] imports [] + app "test" provides [ main ] to "./platform" LinkedList a : [ Nil, Cons a (LinkedList a) ] @@ -907,7 +907,7 @@ mod gen_primitives { assert_evals_to!( indoc!( r#" - app Test provides [ main ] imports [] + app "test" provides [ main ] to "./platform" x = 42 @@ -928,7 +928,7 @@ mod gen_primitives { assert_evals_to!( indoc!( r#" - app Test provides [ main ] imports [] + app "test" provides [ main ] to "./platform" foo = \{} -> x = 41 @@ -951,7 +951,7 @@ mod gen_primitives { assert_evals_to!( indoc!( r#" - app Test provides [ main ] imports [] + app "test" provides [ main ] to "./platform" foo = \{} -> x = 41 @@ -978,7 +978,7 @@ mod gen_primitives { assert_evals_to!( indoc!( r#" - app Test provides [ main ] imports [] + app "test" provides [ main ] to "./platform" foo = \{} -> x = 41 @@ -1006,7 +1006,7 @@ mod gen_primitives { assert_non_opt_evals_to!( indoc!( r#" - app Test provides [ main ] imports [] + app "test" provides [ main ] to "./platform" Effect a : [ @Effect ({} -> a) ] @@ -1036,7 +1036,7 @@ mod gen_primitives { assert_evals_to!( indoc!( r#" - app Test provides [ main ] imports [] + app "test" provides [ main ] to "./platform" # succeed : a -> ({} -> a) succeed = \x -> \{} -> x @@ -1063,7 +1063,7 @@ mod gen_primitives { assert_non_opt_evals_to!( indoc!( r#" - app Test provides [ main ] imports [] + app "test" provides [ main ] to "./platform" Effect a : [ @Effect ({} -> a) ] @@ -1085,7 +1085,7 @@ mod gen_primitives { assert_non_opt_evals_to!( indoc!( r#" - app Test provides [ main ] imports [] + app "test" provides [ main ] to "./platform" Effect a : [ @Effect ({} -> a) ] @@ -1110,7 +1110,7 @@ mod gen_primitives { assert_non_opt_evals_to!( indoc!( r#" - app Test provides [ main ] imports [] + app "test" provides [ main ] to "./platform" ConsList a : [ Cons a (ConsList a), Nil ] @@ -1144,7 +1144,7 @@ mod gen_primitives { assert_non_opt_evals_to!( indoc!( r#" - app Test provides [ main ] imports [] + app "test" provides [ main ] to "./platform" ConsList a : [ Cons a (ConsList a), Nil ] @@ -1175,7 +1175,7 @@ mod gen_primitives { assert_non_opt_evals_to!( indoc!( r#" - app Test provides [ main ] imports [] + app "test" provides [ main ] to "./platform" State a : { count : Int, x : a } @@ -1202,7 +1202,7 @@ mod gen_primitives { assert_non_opt_evals_to!( indoc!( r#" - app Test provides [ main ] imports [] + app "test" provides [ main ] to "./platform" NodeColor : [ Red, Black ] @@ -1284,7 +1284,7 @@ mod gen_primitives { assert_non_opt_evals_to!( indoc!( r#" - app Test provides [ main ] imports [] + app "test" provides [ main ] to "./platform" NodeColor : [ Red, Black ] @@ -1323,7 +1323,7 @@ mod gen_primitives { assert_non_opt_evals_to!( indoc!( r#" - app Test provides [ main ] imports [] + app "test" provides [ main ] to "./platform" Dict k : [ Node k (Dict k) (Dict k), Empty ] @@ -1353,7 +1353,7 @@ mod gen_primitives { assert_non_opt_evals_to!( indoc!( r#" - app Test provides [ main ] imports [] + app "test" provides [ main ] to "./platform" NodeColor : [ Red, Black ] @@ -1393,7 +1393,7 @@ mod gen_primitives { assert_non_opt_evals_to!( indoc!( r#" - app Test provides [ main ] imports [] + app "test" provides [ main ] to "./platform" NodeColor : [ Red, Black ] @@ -1498,7 +1498,7 @@ mod gen_primitives { assert_non_opt_evals_to!( indoc!( r#" - app Test provides [ main ] imports [] + app "test" provides [ main ] to "./platform" ConsList a : [ Cons a (ConsList a), Nil ] @@ -1527,7 +1527,7 @@ mod gen_primitives { assert_non_opt_evals_to!( indoc!( r#" - app Test provides [ main ] imports [] + app "test" provides [ main ] to "./platform" ConsList a : [ Cons a (ConsList a), Nil ] @@ -1552,7 +1552,7 @@ mod gen_primitives { assert_non_opt_evals_to!( indoc!( r#" - app Test provides [ main ] imports [] + app "test" provides [ main ] to "./platform" BTree : [ Node BTree BTree, Leaf Int ] diff --git a/compiler/gen/tests/gen_records.rs b/compiler/gen/tests/gen_records.rs index 54f651636b..b25c1f7c9b 100644 --- a/compiler/gen/tests/gen_records.rs +++ b/compiler/gen/tests/gen_records.rs @@ -405,7 +405,7 @@ mod gen_records { assert_evals_to!( indoc!( r#" - app Test provides [ main ] imports [] + app "test" provides [ main ] to "./platform" f = \r -> when r is @@ -455,7 +455,7 @@ mod gen_records { assert_evals_to!( indoc!( r#" - app Test provides [ main ] imports [] + app "test" provides [ main ] to "./platform" f = \r -> { x ? 10, y } = r @@ -492,7 +492,7 @@ mod gen_records { assert_evals_to!( indoc!( r#" - app Test provides [ main ] imports [] + app "test" provides [ main ] to "./platform" f = \r -> { x ? 10, y } = r @@ -512,7 +512,7 @@ mod gen_records { assert_evals_to!( indoc!( r#" - app Test provides [ main ] imports [] + app "test" provides [ main ] to "./platform" f = \r -> { x ? 10, y } = r @@ -565,7 +565,7 @@ mod gen_records { assert_evals_to!( indoc!( r#" - app Test provides [ main ] imports [] + app "test" provides [ main ] to "./platform" f = \{ x ? 10, y } -> x + y diff --git a/compiler/gen/tests/gen_tags.rs b/compiler/gen/tests/gen_tags.rs index 7e317015b9..0de5052058 100644 --- a/compiler/gen/tests/gen_tags.rs +++ b/compiler/gen/tests/gen_tags.rs @@ -417,7 +417,7 @@ mod gen_tags { assert_evals_to!( indoc!( r#" - app Test provides [ main ] imports [] + app "test" provides [ main ] to "./platform" Maybe a : [ Just a, Nothing ] @@ -630,7 +630,7 @@ mod gen_tags { assert_evals_to!( indoc!( r#" - app Test provides [ main ] imports [] + app "test" provides [ main ] to "./platform" Maybe a : [ Nothing, Just a ] diff --git a/compiler/gen/tests/helpers/eval.rs b/compiler/gen/tests/helpers/eval.rs index bbe6888c78..40e83e4f02 100644 --- a/compiler/gen/tests/helpers/eval.rs +++ b/compiler/gen/tests/helpers/eval.rs @@ -4,7 +4,7 @@ use roc_build::program::FunctionIterator; use roc_collections::all::{MutMap, MutSet}; fn promote_expr_to_module(src: &str) -> String { - let mut buffer = String::from("app Test provides [ main ] imports []\n\nmain =\n"); + let mut buffer = String::from("app \"test\" provides [ main ] to \"./platform\"\n\nmain =\n"); for line in src.lines() { // indent the body! From b3b37db2c0ac2927cb89f2366a8ca410cd45aa95 Mon Sep 17 00:00:00 2001 From: Richard Feldman Date: Fri, 20 Nov 2020 22:52:54 -0500 Subject: [PATCH 17/35] Fix test_uniq_load --- compiler/load/tests/test_uniq_load.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/compiler/load/tests/test_uniq_load.rs b/compiler/load/tests/test_uniq_load.rs index 498870fe3d..34ca8ea318 100644 --- a/compiler/load/tests/test_uniq_load.rs +++ b/compiler/load/tests/test_uniq_load.rs @@ -22,6 +22,7 @@ mod test_uniq_load { use roc_collections::all::MutMap; use roc_constrain::module::SubsByModule; use roc_load::file::LoadedModule; + use roc_module::ident::ModuleName; use roc_module::symbol::{Interns, ModuleId}; use roc_types::pretty_print::{content_to_string, name_all_type_vars}; use roc_types::subs::Subs; @@ -66,7 +67,10 @@ mod test_uniq_load { .get_name(loaded_module.module_id) .expect("Test ModuleID not found in module_ids"); - assert_eq!(expected_name, &InlinableString::from(module_name)); + // App module names are hardcoded and not based on anything user-specified + if expected_name != ModuleName::APP { + assert_eq!(expected_name, &InlinableString::from(module_name)); + } loaded_module } From 9de8ebe8e0ce1214da2d569856d97ce58ce27e23 Mon Sep 17 00:00:00 2001 From: Richard Feldman Date: Fri, 20 Nov 2020 23:01:17 -0500 Subject: [PATCH 18/35] Fix test_mono --- compiler/mono/tests/test_mono.rs | 1843 +++++++++++++++--------------- 1 file changed, 922 insertions(+), 921 deletions(-) diff --git a/compiler/mono/tests/test_mono.rs b/compiler/mono/tests/test_mono.rs index ab1dab9af4..d3cbc2eea7 100644 --- a/compiler/mono/tests/test_mono.rs +++ b/compiler/mono/tests/test_mono.rs @@ -18,7 +18,8 @@ mod test_mono { use roc_mono::layout::Layout; fn promote_expr_to_module(src: &str) -> String { - let mut buffer = String::from("app Test provides [ main ] imports []\n\nmain =\n"); + let mut buffer = + String::from("app \"test\" provides [ main ] to \"./platform\"\n\nmain =\n"); for line in src.lines() { // indent the body! @@ -152,9 +153,9 @@ mod test_mono { "#, indoc!( r#" - procedure Test.0 (): - let Test.1 = 5i64; - ret Test.1; + procedure .0 (): + let .1 = 5i64; + ret .1; "# ), ) @@ -170,9 +171,9 @@ mod test_mono { "#, indoc!( r#" - procedure Test.0 (): - let Test.1 = 5i64; - ret Test.1; + procedure .0 (): + let .1 = 5i64; + ret .1; "# ), ) @@ -188,19 +189,19 @@ mod test_mono { "#, indoc!( r#" - procedure Test.0 (): - let Test.8 = 0i64; - let Test.9 = 3i64; - let Test.2 = Just Test.8 Test.9; - let Test.5 = 0i64; - let Test.6 = Index 0 Test.2; - let Test.7 = lowlevel Eq Test.5 Test.6; - if Test.7 then - let Test.1 = Index 1 Test.2; - ret Test.1; + procedure .0 (): + let .8 = 0i64; + let .9 = 3i64; + let .2 = Just .8 .9; + let .5 = 0i64; + let .6 = Index 0 .2; + let .7 = lowlevel Eq .5 .6; + if .7 then + let .1 = Index 1 .2; + ret .1; else - let Test.4 = 0i64; - ret Test.4; + let .4 = 0i64; + ret .4; "# ), ) @@ -217,23 +218,23 @@ mod test_mono { "#, indoc!( r#" - procedure Test.0 (): - let Test.8 = 1i64; - let Test.9 = 1i64; - let Test.10 = 2i64; - let Test.4 = These Test.8 Test.9 Test.10; - switch Test.4: + procedure .0 (): + let .8 = 1i64; + let .9 = 1i64; + let .10 = 2i64; + let .4 = These .8 .9 .10; + switch .4: case 2: - let Test.1 = Index 1 Test.4; - ret Test.1; + let .1 = Index 1 .4; + ret .1; case 0: - let Test.2 = Index 1 Test.4; - ret Test.2; + let .2 = Index 1 .4; + ret .2; default: - let Test.3 = Index 1 Test.4; - ret Test.3; + let .3 = Index 1 .4; + ret .3; "# ), @@ -249,12 +250,12 @@ mod test_mono { "#, indoc!( r#" - procedure Test.0 (): - let Test.5 = 1i64; - let Test.6 = 3.14f64; - let Test.2 = Struct {Test.5, Test.6}; - let Test.1 = Index 0 Test.2; - ret Test.1; + procedure .0 (): + let .5 = 1i64; + let .6 = 3.14f64; + let .2 = Struct {.5, .6}; + let .1 = Index 0 .2; + ret .1; "# ), ) @@ -269,14 +270,14 @@ mod test_mono { indoc!( r#" procedure Num.14 (#Attr.2, #Attr.3): - let Test.4 = lowlevel NumAdd #Attr.2 #Attr.3; - ret Test.4; + let .4 = lowlevel NumAdd #Attr.2 #Attr.3; + ret .4; - procedure Test.0 (): - let Test.2 = 1i64; - let Test.3 = 2i64; - let Test.1 = CallByName Num.14 Test.2 Test.3; - ret Test.1; + procedure .0 (): + let .2 = 1i64; + let .3 = 2i64; + let .1 = CallByName Num.14 .2 .3; + ret .1; "# ), ) @@ -291,13 +292,13 @@ mod test_mono { indoc!( r#" procedure Num.36 (#Attr.2): - let Test.3 = lowlevel NumRound #Attr.2; - ret Test.3; + let .3 = lowlevel NumRound #Attr.2; + ret .3; - procedure Test.0 (): - let Test.2 = 3.6f64; - let Test.1 = CallByName Num.36 Test.2; - ret Test.1; + procedure .0 (): + let .2 = 3.6f64; + let .1 = CallByName Num.36 .2; + ret .1; "# ), ) @@ -314,32 +315,32 @@ mod test_mono { indoc!( r#" procedure Num.32 (#Attr.2, #Attr.3): - let Test.17 = 0i64; - let Test.13 = lowlevel NotEq #Attr.3 Test.17; - if Test.13 then - let Test.15 = 1i64; - let Test.16 = lowlevel NumDivUnchecked #Attr.2 #Attr.3; - let Test.14 = Ok Test.15 Test.16; - ret Test.14; + let .17 = 0i64; + let .13 = lowlevel NotEq #Attr.3 .17; + if .13 then + let .15 = 1i64; + let .16 = lowlevel NumDivUnchecked #Attr.2 #Attr.3; + let .14 = Ok .15 .16; + ret .14; else - let Test.11 = 0i64; - let Test.12 = Struct {}; - let Test.10 = Err Test.11 Test.12; - ret Test.10; + let .11 = 0i64; + let .12 = Struct {}; + let .10 = Err .11 .12; + ret .10; - procedure Test.0 (): - let Test.8 = 1000i64; - let Test.9 = 10i64; - let Test.2 = CallByName Num.32 Test.8 Test.9; - let Test.5 = 1i64; - let Test.6 = Index 0 Test.2; - let Test.7 = lowlevel Eq Test.5 Test.6; - if Test.7 then - let Test.1 = Index 1 Test.2; - ret Test.1; + procedure .0 (): + let .8 = 1000i64; + let .9 = 10i64; + let .2 = CallByName Num.32 .8 .9; + let .5 = 1i64; + let .6 = Index 0 .2; + let .7 = lowlevel Eq .5 .6; + if .7 then + let .1 = Index 1 .2; + ret .1; else - let Test.4 = -1i64; - ret Test.4; + let .4 = -1i64; + ret .4; "# ), ) @@ -357,14 +358,14 @@ mod test_mono { indoc!( r#" procedure Num.14 (#Attr.2, #Attr.3): - let Test.4 = lowlevel NumAdd #Attr.2 #Attr.3; - ret Test.4; + let .4 = lowlevel NumAdd #Attr.2 #Attr.3; + ret .4; - procedure Test.0 (): - let Test.1 = 3i64; - let Test.2 = 4i64; - let Test.3 = CallByName Num.14 Test.1 Test.2; - ret Test.3; + procedure .0 (): + let .1 = 3i64; + let .2 = 4i64; + let .3 = CallByName Num.14 .1 .2; + ret .3; "# ), ) @@ -384,24 +385,24 @@ mod test_mono { indoc!( r#" procedure Num.14 (#Attr.2, #Attr.3): - let Test.5 = lowlevel NumAdd #Attr.2 #Attr.3; - ret Test.5; + let .5 = lowlevel NumAdd #Attr.2 #Attr.3; + ret .5; - procedure Test.0 (): - let Test.10 = 0i64; - let Test.11 = 41i64; - let Test.1 = Just Test.10 Test.11; - let Test.7 = 0i64; - let Test.8 = Index 0 Test.1; - let Test.9 = lowlevel Eq Test.7 Test.8; - if Test.9 then - let Test.2 = Index 1 Test.1; - let Test.4 = 1i64; - let Test.3 = CallByName Num.14 Test.2 Test.4; - ret Test.3; + procedure .0 (): + let .10 = 0i64; + let .11 = 41i64; + let .1 = Just .10 .11; + let .7 = 0i64; + let .8 = Index 0 .1; + let .9 = lowlevel Eq .7 .8; + if .9 then + let .2 = Index 1 .1; + let .4 = 1i64; + let .3 = CallByName Num.14 .2 .4; + ret .3; else - let Test.6 = 1i64; - ret Test.6; + let .6 = 1i64; + ret .6; "# ), ) @@ -418,10 +419,10 @@ mod test_mono { "#, indoc!( r#" - procedure Test.0 (): - let Test.3 = 2i64; - let Test.1 = Struct {Test.3}; - ret Test.1; + procedure .0 (): + let .3 = 2i64; + let .1 = Struct {.3}; + ret .1; "# ), ) @@ -440,31 +441,31 @@ mod test_mono { "#, indoc!( r#" - procedure Test.1 (Test.2): - let Test.5 = 2i64; - joinpoint Test.11: - let Test.9 = 0i64; - ret Test.9; + procedure .1 (.2): + let .5 = 2i64; + joinpoint .11: + let .9 = 0i64; + ret .9; in - let Test.10 = 2i64; - let Test.13 = lowlevel Eq Test.10 Test.5; - if Test.13 then - joinpoint Test.7 Test.12: - if Test.12 then - let Test.6 = 42i64; - ret Test.6; + let .10 = 2i64; + let .13 = lowlevel Eq .10 .5; + if .13 then + joinpoint .7 .12: + if .12 then + let .6 = 42i64; + ret .6; else - jump Test.11; + jump .11; in - let Test.8 = false; - jump Test.7 Test.8; + let .8 = false; + jump .7 .8; else - jump Test.11; + jump .11; - procedure Test.0 (): - let Test.4 = Struct {}; - let Test.3 = CallByName Test.1 Test.4; - ret Test.3; + procedure .0 (): + let .4 = Struct {}; + let .3 = CallByName .1 .4; + ret .3; "# ), ) @@ -480,16 +481,16 @@ mod test_mono { indoc!( r#" procedure Num.14 (#Attr.2, #Attr.3): - let Test.5 = lowlevel NumAdd #Attr.2 #Attr.3; - ret Test.5; + let .5 = lowlevel NumAdd #Attr.2 #Attr.3; + ret .5; - procedure Test.0 (): - let Test.6 = 2i64; - let Test.2 = Struct {Test.6}; - let Test.1 = Index 0 Test.2; - let Test.4 = 3i64; - let Test.3 = CallByName Num.14 Test.1 Test.4; - ret Test.3; + procedure .0 (): + let .6 = 2i64; + let .2 = Struct {.6}; + let .1 = Index 0 .2; + let .4 = 3i64; + let .3 = CallByName Num.14 .1 .4; + ret .3; "# ), ) @@ -511,37 +512,37 @@ mod test_mono { indoc!( r#" procedure Num.14 (#Attr.2, #Attr.3): - let Test.6 = lowlevel NumAdd #Attr.2 #Attr.3; - ret Test.6; + let .6 = lowlevel NumAdd #Attr.2 #Attr.3; + ret .6; - procedure Test.0 (): - let Test.17 = 0i64; - let Test.19 = 0i64; - let Test.20 = 41i64; - let Test.18 = Just Test.19 Test.20; - let Test.2 = Just Test.17 Test.18; - joinpoint Test.14: - let Test.8 = 1i64; - ret Test.8; + procedure .0 (): + let .17 = 0i64; + let .19 = 0i64; + let .20 = 41i64; + let .18 = Just .19 .20; + let .2 = Just .17 .18; + joinpoint .14: + let .8 = 1i64; + ret .8; in - let Test.12 = 0i64; - let Test.13 = Index 0 Test.2; - let Test.16 = lowlevel Eq Test.12 Test.13; - if Test.16 then - let Test.9 = Index 1 Test.2; - let Test.10 = 0i64; - let Test.11 = Index 0 Test.9; - let Test.15 = lowlevel Eq Test.10 Test.11; - if Test.15 then - let Test.7 = Index 1 Test.2; - let Test.3 = Index 1 Test.7; - let Test.5 = 1i64; - let Test.4 = CallByName Num.14 Test.3 Test.5; - ret Test.4; + let .12 = 0i64; + let .13 = Index 0 .2; + let .16 = lowlevel Eq .12 .13; + if .16 then + let .9 = Index 1 .2; + let .10 = 0i64; + let .11 = Index 0 .9; + let .15 = lowlevel Eq .10 .11; + if .15 then + let .7 = Index 1 .2; + let .3 = Index 1 .7; + let .5 = 1i64; + let .4 = CallByName Num.14 .3 .5; + ret .4; else - jump Test.14; + jump .14; else - jump Test.14; + jump .14; "# ), ) @@ -558,33 +559,33 @@ mod test_mono { indoc!( r#" procedure Num.14 (#Attr.2, #Attr.3): - let Test.6 = lowlevel NumAdd #Attr.2 #Attr.3; - ret Test.6; + let .6 = lowlevel NumAdd #Attr.2 #Attr.3; + ret .6; - procedure Test.0 (): - let Test.14 = 2i64; - let Test.15 = 3i64; - let Test.3 = Struct {Test.14, Test.15}; - joinpoint Test.11: - let Test.1 = Index 0 Test.3; - let Test.2 = Index 1 Test.3; - let Test.5 = CallByName Num.14 Test.1 Test.2; - ret Test.5; + procedure .0 (): + let .14 = 2i64; + let .15 = 3i64; + let .3 = Struct {.14, .15}; + joinpoint .11: + let .1 = Index 0 .3; + let .2 = Index 1 .3; + let .5 = CallByName Num.14 .1 .2; + ret .5; in - let Test.9 = Index 1 Test.3; - let Test.10 = 3i64; - let Test.13 = lowlevel Eq Test.10 Test.9; - if Test.13 then - let Test.7 = Index 0 Test.3; - let Test.8 = 4i64; - let Test.12 = lowlevel Eq Test.8 Test.7; - if Test.12 then - let Test.4 = 9i64; - ret Test.4; + let .9 = Index 1 .3; + let .10 = 3i64; + let .13 = lowlevel Eq .10 .9; + if .13 then + let .7 = Index 0 .3; + let .8 = 4i64; + let .12 = lowlevel Eq .8 .7; + if .12 then + let .4 = 9i64; + ret .4; else - jump Test.11; + jump .11; else - jump Test.11; + jump .11; "# ), ) @@ -600,21 +601,21 @@ mod test_mono { "#, indoc!( r#" + procedure .1 (.2): + let .6 = 42i64; + let .5 = CallByName List.5 .2 .6; + ret .5; + procedure List.5 (#Attr.2, #Attr.3): - let Test.7 = lowlevel ListAppend #Attr.2 #Attr.3; - ret Test.7; + let .7 = lowlevel ListAppend #Attr.2 #Attr.3; + ret .7; - procedure Test.1 (Test.2): - let Test.6 = 42i64; - let Test.5 = CallByName List.5 Test.2 Test.6; - ret Test.5; - - procedure Test.0 (): - let Test.8 = 1i64; - let Test.9 = 2i64; - let Test.4 = Array [Test.8, Test.9]; - let Test.3 = CallByName Test.1 Test.4; - ret Test.3; + procedure .0 (): + let .8 = 1i64; + let .9 = 2i64; + let .4 = Array [.8, .9]; + let .3 = CallByName .1 .4; + ret .3; "# ), ) @@ -631,15 +632,15 @@ mod test_mono { indoc!( r#" procedure List.5 (#Attr.2, #Attr.3): - let Test.4 = lowlevel ListAppend #Attr.2 #Attr.3; - ret Test.4; + let .4 = lowlevel ListAppend #Attr.2 #Attr.3; + ret .4; - procedure Test.0 (): - let Test.5 = 1i64; - let Test.2 = Array [Test.5]; - let Test.3 = 2i64; - let Test.1 = CallByName List.5 Test.2 Test.3; - ret Test.1; + procedure .0 (): + let .5 = 1i64; + let .2 = Array [.5]; + let .3 = 2i64; + let .1 = CallByName List.5 .2 .3; + ret .1; "# ), ) @@ -657,30 +658,30 @@ mod test_mono { indoc!( r#" procedure List.7 (#Attr.2): - let Test.7 = lowlevel ListLen #Attr.2; - ret Test.7; + let .7 = lowlevel ListLen #Attr.2; + ret .7; procedure List.7 (#Attr.2): - let Test.8 = lowlevel ListLen #Attr.2; - ret Test.8; + let .8 = lowlevel ListLen #Attr.2; + ret .8; procedure Num.14 (#Attr.2, #Attr.3): - let Test.6 = lowlevel NumAdd #Attr.2 #Attr.3; - ret Test.6; + let .6 = lowlevel NumAdd #Attr.2 #Attr.3; + ret .6; - procedure Test.0 (): - let Test.10 = 1i64; - let Test.11 = 2i64; - let Test.12 = 3i64; - let Test.1 = Array [Test.10, Test.11, Test.12]; - let Test.9 = 1f64; - let Test.2 = Array [Test.9]; - let Test.4 = CallByName List.7 Test.1; - dec Test.1; - let Test.5 = CallByName List.7 Test.2; - dec Test.2; - let Test.3 = CallByName Num.14 Test.4 Test.5; - ret Test.3; + procedure .0 (): + let .10 = 1i64; + let .11 = 2i64; + let .12 = 3i64; + let .1 = Array [.10, .11, .12]; + let .9 = 1f64; + let .2 = Array [.9]; + let .4 = CallByName List.7 .1; + dec .1; + let .5 = CallByName List.7 .2; + dec .2; + let .3 = CallByName Num.14 .4 .5; + ret .3; "# ), ) @@ -706,29 +707,29 @@ mod test_mono { "#, indoc!( r#" - procedure Test.1 (Test.4): - let Test.2 = 0u8; - joinpoint Test.8 Test.3: - ret Test.3; + procedure .1 (.4): + let .2 = 0u8; + joinpoint .8 .3: + ret .3; in - switch Test.2: + switch .2: case 1: - let Test.9 = 1i64; - jump Test.8 Test.9; + let .9 = 1i64; + jump .8 .9; case 2: - let Test.10 = 2i64; - jump Test.8 Test.10; + let .10 = 2i64; + jump .8 .10; default: - let Test.11 = 3i64; - jump Test.8 Test.11; + let .11 = 3i64; + jump .8 .11; - procedure Test.0 (): - let Test.6 = Struct {}; - let Test.5 = CallByName Test.1 Test.6; - ret Test.5; + procedure .0 (): + let .6 = Struct {}; + let .5 = CallByName .1 .6; + ret .5; "# ), ) @@ -745,14 +746,14 @@ mod test_mono { "#, indoc!( r#" - procedure Test.0 (): - let Test.2 = true; - if Test.2 then - let Test.3 = 1i64; - ret Test.3; + procedure .0 (): + let .2 = true; + if .2 then + let .3 = 1i64; + ret .3; else - let Test.1 = 2i64; - ret Test.1; + let .1 = 2i64; + ret .1; "# ), ) @@ -771,19 +772,19 @@ mod test_mono { "#, indoc!( r#" - procedure Test.0 (): - let Test.4 = true; - if Test.4 then - let Test.5 = 1i64; - ret Test.5; + procedure .0 (): + let .4 = true; + if .4 then + let .5 = 1i64; + ret .5; else - let Test.2 = false; - if Test.2 then - let Test.3 = 2i64; - ret Test.3; + let .2 = false; + if .2 then + let .3 = 2i64; + ret .3; else - let Test.1 = 3i64; - ret Test.1; + let .1 = 3i64; + ret .1; "# ), ) @@ -808,34 +809,34 @@ mod test_mono { "#, indoc!( r#" - procedure Test.1 (Test.4): - let Test.18 = 1i64; - let Test.19 = 2i64; - let Test.2 = Ok Test.18 Test.19; - joinpoint Test.8 Test.3: - ret Test.3; + procedure .1 (.4): + let .18 = 1i64; + let .19 = 2i64; + let .2 = Ok .18 .19; + joinpoint .8 .3: + ret .3; in - let Test.15 = 1i64; - let Test.16 = Index 0 Test.2; - let Test.17 = lowlevel Eq Test.15 Test.16; - if Test.17 then - let Test.12 = Index 1 Test.2; - let Test.13 = 3i64; - let Test.14 = lowlevel Eq Test.13 Test.12; - if Test.14 then - let Test.9 = 1i64; - jump Test.8 Test.9; + let .15 = 1i64; + let .16 = Index 0 .2; + let .17 = lowlevel Eq .15 .16; + if .17 then + let .12 = Index 1 .2; + let .13 = 3i64; + let .14 = lowlevel Eq .13 .12; + if .14 then + let .9 = 1i64; + jump .8 .9; else - let Test.10 = 2i64; - jump Test.8 Test.10; + let .10 = 2i64; + jump .8 .10; else - let Test.11 = 3i64; - jump Test.8 Test.11; + let .11 = 3i64; + jump .8 .11; - procedure Test.0 (): - let Test.6 = Struct {}; - let Test.5 = CallByName Test.1 Test.6; - ret Test.5; + procedure .0 (): + let .6 = Struct {}; + let .5 = CallByName .1 .6; + ret .5; "# ), ) @@ -851,12 +852,12 @@ mod test_mono { "#, indoc!( r#" - procedure Test.0 (): - let Test.5 = 2i64; - let Test.6 = 3.14f64; - let Test.4 = Struct {Test.5, Test.6}; - let Test.1 = Index 0 Test.4; - ret Test.1; + procedure .0 (): + let .5 = 2i64; + let .6 = 3.14f64; + let .4 = Struct {.5, .6}; + let .1 = Index 0 .4; + ret .1; "# ), ) @@ -872,17 +873,17 @@ mod test_mono { "#, indoc!( r#" - procedure Test.0 (): - let Test.7 = 1i64; - let Test.8 = 3i64; - let Test.9 = 4i64; - let Test.5 = Array [Test.7, Test.8, Test.9]; - let Test.6 = 3.14f64; - let Test.4 = Struct {Test.5, Test.6}; - let Test.1 = Index 0 Test.4; - inc Test.1; - dec Test.4; - ret Test.1; + procedure .0 (): + let .7 = 1i64; + let .8 = 3i64; + let .9 = 4i64; + let .5 = Array [.7, .8, .9]; + let .6 = 3.14f64; + let .4 = Struct {.5, .6}; + let .1 = Index 0 .4; + inc .1; + dec .4; + ret .1; "# ), ) @@ -903,28 +904,28 @@ mod test_mono { ), indoc!( r#" - procedure Bool.5 (#Attr.2, #Attr.3): - let Test.11 = lowlevel Eq #Attr.2 #Attr.3; - ret Test.11; - - procedure Test.1 (Test.3): - let Test.6 = 10i64; - joinpoint Test.8 Test.13: - if Test.13 then - let Test.7 = 0i64; - ret Test.7; + procedure .1 (.3): + let .6 = 10i64; + joinpoint .8 .13: + if .13 then + let .7 = 0i64; + ret .7; else - let Test.12 = 42i64; - ret Test.12; + let .12 = 42i64; + ret .12; in - let Test.10 = 5i64; - let Test.9 = CallByName Bool.5 Test.6 Test.10; - jump Test.8 Test.9; + let .10 = 5i64; + let .9 = CallByName Bool.5 .6 .10; + jump .8 .9; - procedure Test.0 (): - let Test.5 = Struct {}; - let Test.4 = CallByName Test.1 Test.5; - ret Test.4; + procedure Bool.5 (#Attr.2, #Attr.3): + let .11 = lowlevel Eq #Attr.2 #Attr.3; + ret .11; + + procedure .0 (): + let .5 = Struct {}; + let .4 = CallByName .1 .5; + ret .4; "# ), ) @@ -943,10 +944,10 @@ mod test_mono { ), indoc!( r#" - procedure Test.0 (): - let Test.1 = 5i64; - let Test.3 = 3i64; - ret Test.3; + procedure .0 (): + let .1 = 5i64; + let .3 = 3i64; + ret .3; "# ), ); @@ -962,9 +963,9 @@ mod test_mono { ), indoc!( r#" - procedure Test.0 (): - let Test.1 = 5i64; - ret Test.1; + procedure .0 (): + let .1 = 5i64; + ret .1; "# ), ) @@ -982,15 +983,15 @@ mod test_mono { ), indoc!( r#" - procedure Test.0 (): - let Test.2 = 0i64; - let Test.5 = 1i64; - let Test.6 = lowlevel Eq Test.5 Test.2; - if Test.6 then - let Test.3 = 12i64; - ret Test.3; + procedure .0 (): + let .2 = 0i64; + let .5 = 1i64; + let .6 = lowlevel Eq .5 .2; + if .6 then + let .3 = 12i64; + ret .3; else - ret Test.2; + ret .2; "# ), ) @@ -1012,28 +1013,28 @@ mod test_mono { ), indoc!( r#" + procedure .2 (.3): + let .6 = 0i64; + let .7 = 0i64; + let .5 = CallByName List.4 .3 .6 .7; + ret .5; + procedure List.4 (#Attr.2, #Attr.3, #Attr.4): - let Test.11 = lowlevel ListLen #Attr.2; - let Test.9 = lowlevel NumLt #Attr.3 Test.11; - if Test.9 then - let Test.10 = lowlevel ListSet #Attr.2 #Attr.3 #Attr.4; - ret Test.10; + let .11 = lowlevel ListLen #Attr.2; + let .9 = lowlevel NumLt #Attr.3 .11; + if .9 then + let .10 = lowlevel ListSet #Attr.2 #Attr.3 #Attr.4; + ret .10; else ret #Attr.2; - procedure Test.2 (Test.3): - let Test.6 = 0i64; - let Test.7 = 0i64; - let Test.5 = CallByName List.4 Test.3 Test.6 Test.7; - ret Test.5; - - procedure Test.0 (): - let Test.12 = 1i64; - let Test.13 = 2i64; - let Test.14 = 3i64; - let Test.1 = Array [Test.12, Test.13, Test.14]; - let Test.4 = CallByName Test.2 Test.1; - ret Test.4; + procedure .0 (): + let .12 = 1i64; + let .13 = 2i64; + let .14 = 3i64; + let .1 = Array [.12, .13, .14]; + let .4 = CallByName .2 .1; + ret .4; "# ), ) @@ -1054,22 +1055,22 @@ mod test_mono { ), indoc!( r#" + procedure .1 (.2): + let .3 = Index 0 .2; + let .4 = Index 1 .2; + let .7 = CallByName Num.14 .3 .4; + ret .7; + procedure Num.14 (#Attr.2, #Attr.3): - let Test.8 = lowlevel NumAdd #Attr.2 #Attr.3; - ret Test.8; + let .8 = lowlevel NumAdd #Attr.2 #Attr.3; + ret .8; - procedure Test.1 (Test.2): - let Test.3 = Index 0 Test.2; - let Test.4 = Index 1 Test.2; - let Test.7 = CallByName Num.14 Test.3 Test.4; - ret Test.7; - - procedure Test.0 (): - let Test.9 = 4i64; - let Test.10 = 9i64; - let Test.6 = Struct {Test.9, Test.10}; - let Test.5 = CallByName Test.1 Test.6; - ret Test.5; + procedure .0 (): + let .9 = 4i64; + let .10 = 9i64; + let .6 = Struct {.9, .10}; + let .5 = CallByName .1 .6; + ret .5; "# ), ) @@ -1090,21 +1091,21 @@ mod test_mono { ), indoc!( r#" + procedure .1 (.2): + let .3 = 10i64; + let .4 = Index 1 .2; + let .7 = CallByName Num.14 .3 .4; + ret .7; + procedure Num.14 (#Attr.2, #Attr.3): - let Test.8 = lowlevel NumAdd #Attr.2 #Attr.3; - ret Test.8; + let .8 = lowlevel NumAdd #Attr.2 #Attr.3; + ret .8; - procedure Test.1 (Test.2): - let Test.3 = 10i64; - let Test.4 = Index 1 Test.2; - let Test.7 = CallByName Num.14 Test.3 Test.4; - ret Test.7; - - procedure Test.0 (): - let Test.9 = 9i64; - let Test.6 = Struct {Test.9}; - let Test.5 = CallByName Test.1 Test.6; - ret Test.5; + procedure .0 (): + let .9 = 9i64; + let .6 = Struct {.9}; + let .5 = CallByName .1 .6; + ret .5; "# ), ) @@ -1123,22 +1124,22 @@ mod test_mono { ), indoc!( r#" + procedure .1 (.4): + let .2 = Index 0 .4; + let .3 = Index 1 .4; + let .7 = CallByName Num.14 .2 .3; + ret .7; + procedure Num.14 (#Attr.2, #Attr.3): - let Test.8 = lowlevel NumAdd #Attr.2 #Attr.3; - ret Test.8; + let .8 = lowlevel NumAdd #Attr.2 #Attr.3; + ret .8; - procedure Test.1 (Test.4): - let Test.2 = Index 0 Test.4; - let Test.3 = Index 1 Test.4; - let Test.7 = CallByName Num.14 Test.2 Test.3; - ret Test.7; - - procedure Test.0 (): - let Test.9 = 4i64; - let Test.10 = 9i64; - let Test.6 = Struct {Test.9, Test.10}; - let Test.5 = CallByName Test.1 Test.6; - ret Test.5; + procedure .0 (): + let .9 = 4i64; + let .10 = 9i64; + let .6 = Struct {.9, .10}; + let .5 = CallByName .1 .6; + ret .5; "# ), ) @@ -1157,21 +1158,21 @@ mod test_mono { ), indoc!( r#" + procedure .1 (.4): + let .2 = 10i64; + let .3 = Index 1 .4; + let .7 = CallByName Num.14 .2 .3; + ret .7; + procedure Num.14 (#Attr.2, #Attr.3): - let Test.8 = lowlevel NumAdd #Attr.2 #Attr.3; - ret Test.8; + let .8 = lowlevel NumAdd #Attr.2 #Attr.3; + ret .8; - procedure Test.1 (Test.4): - let Test.2 = 10i64; - let Test.3 = Index 1 Test.4; - let Test.7 = CallByName Num.14 Test.2 Test.3; - ret Test.7; - - procedure Test.0 (): - let Test.9 = 9i64; - let Test.6 = Struct {Test.9}; - let Test.5 = CallByName Test.1 Test.6; - ret Test.5; + procedure .0 (): + let .9 = 9i64; + let .6 = Struct {.9}; + let .5 = CallByName .1 .6; + ret .5; "# ), ) @@ -1201,70 +1202,70 @@ mod test_mono { indoc!( r#" procedure List.3 (#Attr.2, #Attr.3): - let Test.38 = lowlevel ListLen #Attr.2; - let Test.34 = lowlevel NumLt #Attr.3 Test.38; - if Test.34 then - let Test.36 = 1i64; - let Test.37 = lowlevel ListGetUnsafe #Attr.2 #Attr.3; - let Test.35 = Ok Test.36 Test.37; - ret Test.35; + let .38 = lowlevel ListLen #Attr.2; + let .34 = lowlevel NumLt #Attr.3 .38; + if .34 then + let .36 = 1i64; + let .37 = lowlevel ListGetUnsafe #Attr.2 #Attr.3; + let .35 = Ok .36 .37; + ret .35; else - let Test.32 = 0i64; - let Test.33 = Struct {}; - let Test.31 = Err Test.32 Test.33; - ret Test.31; + let .32 = 0i64; + let .33 = Struct {}; + let .31 = Err .32 .33; + ret .31; procedure List.4 (#Attr.2, #Attr.3, #Attr.4): - let Test.14 = lowlevel ListLen #Attr.2; - let Test.12 = lowlevel NumLt #Attr.3 Test.14; - if Test.12 then - let Test.13 = lowlevel ListSet #Attr.2 #Attr.3 #Attr.4; - ret Test.13; + let .14 = lowlevel ListLen #Attr.2; + let .12 = lowlevel NumLt #Attr.3 .14; + if .12 then + let .13 = lowlevel ListSet #Attr.2 #Attr.3 #Attr.4; + ret .13; else ret #Attr.2; - procedure Test.1 (Test.2): - let Test.39 = 0i64; - let Test.28 = CallByName List.3 Test.2 Test.39; - let Test.30 = 0i64; - let Test.29 = CallByName List.3 Test.2 Test.30; - let Test.7 = Struct {Test.28, Test.29}; - joinpoint Test.25: - let Test.18 = Array []; - ret Test.18; + procedure .1 (.2): + let .39 = 0i64; + let .28 = CallByName List.3 .2 .39; + let .30 = 0i64; + let .29 = CallByName List.3 .2 .30; + let .7 = Struct {.28, .29}; + joinpoint .25: + let .18 = Array []; + ret .18; in - let Test.19 = Index 0 Test.7; - let Test.20 = 1i64; - let Test.21 = Index 0 Test.19; - let Test.27 = lowlevel Eq Test.20 Test.21; - if Test.27 then - let Test.22 = Index 1 Test.7; - let Test.23 = 1i64; - let Test.24 = Index 0 Test.22; - let Test.26 = lowlevel Eq Test.23 Test.24; - if Test.26 then - let Test.17 = Index 0 Test.7; - let Test.3 = Index 1 Test.17; - let Test.16 = Index 1 Test.7; - let Test.4 = Index 1 Test.16; - let Test.15 = 0i64; - let Test.9 = CallByName List.4 Test.2 Test.15 Test.4; - let Test.10 = 0i64; - let Test.8 = CallByName List.4 Test.9 Test.10 Test.3; - ret Test.8; + let .19 = Index 0 .7; + let .20 = 1i64; + let .21 = Index 0 .19; + let .27 = lowlevel Eq .20 .21; + if .27 then + let .22 = Index 1 .7; + let .23 = 1i64; + let .24 = Index 0 .22; + let .26 = lowlevel Eq .23 .24; + if .26 then + let .17 = Index 0 .7; + let .3 = Index 1 .17; + let .16 = Index 1 .7; + let .4 = Index 1 .16; + let .15 = 0i64; + let .9 = CallByName List.4 .2 .15 .4; + let .10 = 0i64; + let .8 = CallByName List.4 .9 .10 .3; + ret .8; else - dec Test.2; - jump Test.25; + dec .2; + jump .25; else - dec Test.2; - jump Test.25; + dec .2; + jump .25; - procedure Test.0 (): - let Test.40 = 1i64; - let Test.41 = 2i64; - let Test.6 = Array [Test.40, Test.41]; - let Test.5 = CallByName Test.1 Test.6; - ret Test.5; + procedure .0 (): + let .40 = 1i64; + let .41 = 2i64; + let .6 = Array [.40, .41]; + let .5 = CallByName .1 .6; + ret .5; "# ), ) @@ -1277,7 +1278,7 @@ mod test_mono { compiles_to_ir( indoc!( r#" - app Test provides [ main ] imports [] + app "test" provides [ main ] to "./platform" swap = \list -> when Pair (List.get list 0) (List.get list 0) is @@ -1295,71 +1296,71 @@ mod test_mono { ), indoc!( r#" - procedure List.3 (#Attr.2, #Attr.3): - let Test.38 = lowlevel ListLen #Attr.2; - let Test.34 = lowlevel NumLt #Attr.3 Test.38; - if Test.34 then - let Test.36 = 1i64; - let Test.37 = lowlevel ListGetUnsafe #Attr.2 #Attr.3; - let Test.35 = Ok Test.36 Test.37; - ret Test.35; + procedure .1 (.2): + let .39 = 0i64; + let .28 = CallByName List.3 .2 .39; + let .30 = 0i64; + let .29 = CallByName List.3 .2 .30; + let .7 = Struct {.28, .29}; + joinpoint .25: + let .18 = Array []; + ret .18; + in + let .22 = Index 1 .7; + let .23 = 1i64; + let .24 = Index 0 .22; + let .27 = lowlevel Eq .23 .24; + if .27 then + let .19 = Index 0 .7; + let .20 = 1i64; + let .21 = Index 0 .19; + let .26 = lowlevel Eq .20 .21; + if .26 then + let .17 = Index 0 .7; + let .3 = Index 1 .17; + let .16 = Index 1 .7; + let .4 = Index 1 .16; + let .15 = 0i64; + let .9 = CallByName List.4 .2 .15 .4; + let .10 = 0i64; + let .8 = CallByName List.4 .9 .10 .3; + ret .8; + else + dec .2; + jump .25; else - let Test.32 = 0i64; - let Test.33 = Struct {}; - let Test.31 = Err Test.32 Test.33; - ret Test.31; + dec .2; + jump .25; + + procedure List.3 (#Attr.2, #Attr.3): + let .38 = lowlevel ListLen #Attr.2; + let .34 = lowlevel NumLt #Attr.3 .38; + if .34 then + let .36 = 1i64; + let .37 = lowlevel ListGetUnsafe #Attr.2 #Attr.3; + let .35 = Ok .36 .37; + ret .35; + else + let .32 = 0i64; + let .33 = Struct {}; + let .31 = Err .32 .33; + ret .31; procedure List.4 (#Attr.2, #Attr.3, #Attr.4): - let Test.14 = lowlevel ListLen #Attr.2; - let Test.12 = lowlevel NumLt #Attr.3 Test.14; - if Test.12 then - let Test.13 = lowlevel ListSet #Attr.2 #Attr.3 #Attr.4; - ret Test.13; + let .14 = lowlevel ListLen #Attr.2; + let .12 = lowlevel NumLt #Attr.3 .14; + if .12 then + let .13 = lowlevel ListSet #Attr.2 #Attr.3 #Attr.4; + ret .13; else ret #Attr.2; - procedure Test.1 (Test.2): - let Test.39 = 0i64; - let Test.28 = CallByName List.3 Test.2 Test.39; - let Test.30 = 0i64; - let Test.29 = CallByName List.3 Test.2 Test.30; - let Test.7 = Struct {Test.28, Test.29}; - joinpoint Test.25: - let Test.18 = Array []; - ret Test.18; - in - let Test.22 = Index 1 Test.7; - let Test.23 = 1i64; - let Test.24 = Index 0 Test.22; - let Test.27 = lowlevel Eq Test.23 Test.24; - if Test.27 then - let Test.19 = Index 0 Test.7; - let Test.20 = 1i64; - let Test.21 = Index 0 Test.19; - let Test.26 = lowlevel Eq Test.20 Test.21; - if Test.26 then - let Test.17 = Index 0 Test.7; - let Test.3 = Index 1 Test.17; - let Test.16 = Index 1 Test.7; - let Test.4 = Index 1 Test.16; - let Test.15 = 0i64; - let Test.9 = CallByName List.4 Test.2 Test.15 Test.4; - let Test.10 = 0i64; - let Test.8 = CallByName List.4 Test.9 Test.10 Test.3; - ret Test.8; - else - dec Test.2; - jump Test.25; - else - dec Test.2; - jump Test.25; - - procedure Test.0 (): - let Test.40 = 1i64; - let Test.41 = 2i64; - let Test.6 = Array [Test.40, Test.41]; - let Test.5 = CallByName Test.1 Test.6; - ret Test.5; + procedure .0 (): + let .40 = 1i64; + let .41 = 2i64; + let .6 = Array [.40, .41]; + let .5 = CallByName .1 .6; + ret .5; "# ), ) @@ -1373,7 +1374,7 @@ mod test_mono { compiles_to_ir( indoc!( r#" - app Test provides [ main ] imports [] + app "test" provides [ main ] to "./platform" partitionHelp : Int, Int, List (Num a), Int, (Num a) -> [ Pair Int (List (Num a)) ] partitionHelp = \i, j, list, high, pivot -> @@ -1409,7 +1410,7 @@ mod test_mono { compiles_to_ir( indoc!( r#" - app Test provides [ main ] imports [] + app "test" provides [ main ] to "./platform" quicksortHelp : List (Num a), Int, Int -> List (Num a) quicksortHelp = \list, low, high -> @@ -1495,33 +1496,33 @@ mod test_mono { "#, indoc!( r#" + procedure .1 (.2, .3): + joinpoint .7 .2 .3: + let .15 = 0i64; + let .16 = lowlevel Eq .15 .2; + if .16 then + ret .3; + else + let .13 = 1i64; + let .10 = CallByName Num.15 .2 .13; + let .11 = CallByName Num.16 .2 .3; + jump .7 .10 .11; + in + jump .7 .2 .3; + procedure Num.15 (#Attr.2, #Attr.3): - let Test.14 = lowlevel NumSub #Attr.2 #Attr.3; - ret Test.14; + let .14 = lowlevel NumSub #Attr.2 #Attr.3; + ret .14; procedure Num.16 (#Attr.2, #Attr.3): - let Test.12 = lowlevel NumMul #Attr.2 #Attr.3; - ret Test.12; + let .12 = lowlevel NumMul #Attr.2 #Attr.3; + ret .12; - procedure Test.1 (Test.2, Test.3): - joinpoint Test.7 Test.2 Test.3: - let Test.15 = 0i64; - let Test.16 = lowlevel Eq Test.15 Test.2; - if Test.16 then - ret Test.3; - else - let Test.13 = 1i64; - let Test.10 = CallByName Num.15 Test.2 Test.13; - let Test.11 = CallByName Num.16 Test.2 Test.3; - jump Test.7 Test.10 Test.11; - in - jump Test.7 Test.2 Test.3; - - procedure Test.0 (): - let Test.5 = 10i64; - let Test.6 = 1i64; - let Test.4 = CallByName Test.1 Test.5 Test.6; - ret Test.4; + procedure .0 (): + let .5 = 10i64; + let .6 = 1i64; + let .4 = CallByName .1 .5 .6; + ret .4; "# ), ) @@ -1544,26 +1545,26 @@ mod test_mono { "#, indoc!( r#" - procedure Test.1 (Test.3): - let Test.13 = true; - let Test.15 = Index 0 Test.3; - let Test.14 = 1i64; - let Test.16 = lowlevel Eq Test.14 Test.15; - let Test.12 = lowlevel And Test.16 Test.13; - if Test.12 then - let Test.10 = true; - ret Test.10; + procedure .1 (.3): + let .13 = true; + let .15 = Index 0 .3; + let .14 = 1i64; + let .16 = lowlevel Eq .14 .15; + let .12 = lowlevel And .16 .13; + if .12 then + let .10 = true; + ret .10; else - let Test.11 = false; - ret Test.11; + let .11 = false; + ret .11; - let Test.6 = 0i64; - let Test.7 = 2i64; - let Test.9 = 1i64; - let Test.8 = Nil Test.9; - let Test.5 = Cons Test.6 Test.7 Test.8; - let Test.4 = CallByName Test.1 Test.5; - ret Test.4; + let .6 = 0i64; + let .7 = 2i64; + let .9 = 1i64; + let .8 = Nil .9; + let .5 = Cons .6 .7 .8; + let .4 = CallByName .1 .5; + ret .4; "# ), ) @@ -1588,26 +1589,26 @@ mod test_mono { "#, indoc!( r#" - procedure Test.1 (Test.3): - let Test.13 = true; - let Test.15 = Index 0 Test.3; - let Test.14 = 1i64; - let Test.16 = lowlevel Eq Test.14 Test.15; - let Test.12 = lowlevel And Test.16 Test.13; - if Test.12 then - let Test.10 = true; - ret Test.10; + procedure .1 (.3): + let .13 = true; + let .15 = Index 0 .3; + let .14 = 1i64; + let .16 = lowlevel Eq .14 .15; + let .12 = lowlevel And .16 .13; + if .12 then + let .10 = true; + ret .10; else - let Test.11 = false; - ret Test.11; + let .11 = false; + ret .11; - let Test.6 = 0i64; - let Test.7 = 2i64; - let Test.9 = 1i64; - let Test.8 = Nil Test.9; - let Test.5 = Cons Test.6 Test.7 Test.8; - let Test.4 = CallByName Test.1 Test.5; - ret Test.4; + let .6 = 0i64; + let .7 = 2i64; + let .9 = 1i64; + let .8 = Nil .9; + let .5 = Cons .6 .7 .8; + let .4 = CallByName .1 .5; + ret .4; "# ), ) @@ -1618,7 +1619,7 @@ mod test_mono { compiles_to_ir( indoc!( r#" - app Test provides [ main ] imports [] + app "test" provides [ main ] to "./platform" mkPairOf = \x -> Pair x x @@ -1628,18 +1629,18 @@ mod test_mono { ), indoc!( r#" - procedure Test.1 (Test.2): - inc Test.2; - let Test.5 = Struct {Test.2, Test.2}; - ret Test.5; + procedure .1 (.2): + inc .2; + let .5 = Struct {.2, .2}; + ret .5; - procedure Test.0 (): - let Test.6 = 1i64; - let Test.7 = 2i64; - let Test.8 = 3i64; - let Test.4 = Array [Test.6, Test.7, Test.8]; - let Test.3 = CallByName Test.1 Test.4; - ret Test.3; + procedure .0 (): + let .6 = 1i64; + let .7 = 2i64; + let .8 = 3i64; + let .4 = Array [.6, .7, .8]; + let .3 = CallByName .1 .4; + ret .3; "# ), ) @@ -1650,7 +1651,7 @@ mod test_mono { compiles_to_ir( indoc!( r#" - app Test provides [ main ] imports [] + app "test" provides [ main ] to "./platform" fst = \x, _ -> x @@ -1660,23 +1661,23 @@ mod test_mono { ), indoc!( r#" - procedure Test.1 (Test.2, Test.3): - inc Test.2; - ret Test.2; + procedure .1 (.2, .3): + inc .2; + ret .2; - procedure Test.0 (): - let Test.11 = 1i64; - let Test.12 = 2i64; - let Test.13 = 3i64; - let Test.5 = Array [Test.11, Test.12, Test.13]; - let Test.8 = 3i64; - let Test.9 = 2i64; - let Test.10 = 1i64; - let Test.6 = Array [Test.8, Test.9, Test.10]; - let Test.4 = CallByName Test.1 Test.5 Test.6; - dec Test.6; - dec Test.5; - ret Test.4; + procedure .0 (): + let .11 = 1i64; + let .12 = 2i64; + let .13 = 3i64; + let .5 = Array [.11, .12, .13]; + let .8 = 3i64; + let .9 = 2i64; + let .10 = 1i64; + let .6 = Array [.8, .9, .10]; + let .4 = CallByName .1 .5 .6; + dec .6; + dec .5; + ret .4; "# ), ) @@ -1687,7 +1688,7 @@ mod test_mono { compiles_to_ir( indoc!( r#" - app Test provides [ main ] imports [] + app "test" provides [ main ] to "./platform" x : List Int x = [1,2,3] @@ -1701,46 +1702,46 @@ mod test_mono { ), indoc!( r#" + procedure .1 (): + let .11 = 1i64; + let .12 = 2i64; + let .13 = 3i64; + let .10 = Array [.11, .12, .13]; + ret .10; + + procedure .2 (.3): + let .17 = 0i64; + let .18 = 0i64; + let .16 = CallByName List.4 .3 .17 .18; + ret .16; + procedure List.4 (#Attr.2, #Attr.3, #Attr.4): - let Test.22 = lowlevel ListLen #Attr.2; - let Test.20 = lowlevel NumLt #Attr.3 Test.22; - if Test.20 then - let Test.21 = lowlevel ListSet #Attr.2 #Attr.3 #Attr.4; - ret Test.21; + let .22 = lowlevel ListLen #Attr.2; + let .20 = lowlevel NumLt #Attr.3 .22; + if .20 then + let .21 = lowlevel ListSet #Attr.2 #Attr.3 #Attr.4; + ret .21; else ret #Attr.2; procedure List.7 (#Attr.2): - let Test.9 = lowlevel ListLen #Attr.2; - ret Test.9; + let .9 = lowlevel ListLen #Attr.2; + ret .9; procedure Num.14 (#Attr.2, #Attr.3): - let Test.7 = lowlevel NumAdd #Attr.2 #Attr.3; - ret Test.7; + let .7 = lowlevel NumAdd #Attr.2 #Attr.3; + ret .7; - procedure Test.1 (): - let Test.11 = 1i64; - let Test.12 = 2i64; - let Test.13 = 3i64; - let Test.10 = Array [Test.11, Test.12, Test.13]; - ret Test.10; - - procedure Test.2 (Test.3): - let Test.17 = 0i64; - let Test.18 = 0i64; - let Test.16 = CallByName List.4 Test.3 Test.17 Test.18; - ret Test.16; - - procedure Test.0 (): - let Test.15 = FunctionPointer Test.1; - let Test.14 = CallByName Test.2 Test.15; - let Test.5 = CallByName List.7 Test.14; - dec Test.14; - let Test.8 = FunctionPointer Test.1; - let Test.6 = CallByName List.7 Test.8; - dec Test.8; - let Test.4 = CallByName Num.14 Test.5 Test.6; - ret Test.4; + procedure .0 (): + let .15 = FunctionPointer .1; + let .14 = CallByName .2 .15; + let .5 = CallByName List.7 .14; + dec .14; + let .8 = FunctionPointer .1; + let .6 = CallByName List.7 .8; + dec .8; + let .4 = CallByName Num.14 .5 .6; + ret .4; "# ), ) @@ -1759,34 +1760,34 @@ mod test_mono { ), indoc!( r#" + procedure .1 (.2): + let .16 = 1i64; + let .17 = 2i64; + let .18 = 3i64; + let .6 = Array [.16, .17, .18]; + let .7 = 0i64; + let .5 = CallByName List.3 .6 .7; + dec .6; + ret .5; + procedure List.3 (#Attr.2, #Attr.3): - let Test.15 = lowlevel ListLen #Attr.2; - let Test.11 = lowlevel NumLt #Attr.3 Test.15; - if Test.11 then - let Test.13 = 1i64; - let Test.14 = lowlevel ListGetUnsafe #Attr.2 #Attr.3; - let Test.12 = Ok Test.13 Test.14; - ret Test.12; + let .15 = lowlevel ListLen #Attr.2; + let .11 = lowlevel NumLt #Attr.3 .15; + if .11 then + let .13 = 1i64; + let .14 = lowlevel ListGetUnsafe #Attr.2 #Attr.3; + let .12 = Ok .13 .14; + ret .12; else - let Test.9 = 0i64; - let Test.10 = Struct {}; - let Test.8 = Err Test.9 Test.10; - ret Test.8; + let .9 = 0i64; + let .10 = Struct {}; + let .8 = Err .9 .10; + ret .8; - procedure Test.1 (Test.2): - let Test.16 = 1i64; - let Test.17 = 2i64; - let Test.18 = 3i64; - let Test.6 = Array [Test.16, Test.17, Test.18]; - let Test.7 = 0i64; - let Test.5 = CallByName List.3 Test.6 Test.7; - dec Test.6; - ret Test.5; - - procedure Test.0 (): - let Test.4 = Struct {}; - let Test.3 = CallByName Test.1 Test.4; - ret Test.3; + procedure .0 (): + let .4 = Struct {}; + let .3 = CallByName .1 .4; + ret .3; "# ), ) @@ -1807,16 +1808,16 @@ mod test_mono { ), indoc!( r#" - procedure Test.0 (): - let Test.4 = 0i64; - let Test.6 = 0i64; - let Test.8 = 0i64; - let Test.10 = 1i64; - let Test.9 = Z Test.10; - let Test.7 = S Test.8 Test.9; - let Test.5 = S Test.6 Test.7; - let Test.2 = S Test.4 Test.5; - ret Test.2; + procedure .0 (): + let .4 = 0i64; + let .6 = 0i64; + let .8 = 0i64; + let .10 = 1i64; + let .9 = Z .10; + let .7 = S .8 .9; + let .5 = S .6 .7; + let .2 = S .4 .5; + ret .2; "# ), ) @@ -1839,25 +1840,25 @@ mod test_mono { ), indoc!( r#" - procedure Test.0 (): - let Test.8 = 0i64; - let Test.10 = 0i64; - let Test.12 = 0i64; - let Test.14 = 1i64; - let Test.13 = Z Test.14; - let Test.11 = S Test.12 Test.13; - let Test.9 = S Test.10 Test.11; - let Test.2 = S Test.8 Test.9; - let Test.5 = 1i64; - let Test.6 = Index 0 Test.2; - dec Test.2; - let Test.7 = lowlevel Eq Test.5 Test.6; - if Test.7 then - let Test.3 = 0i64; - ret Test.3; + procedure .0 (): + let .8 = 0i64; + let .10 = 0i64; + let .12 = 0i64; + let .14 = 1i64; + let .13 = Z .14; + let .11 = S .12 .13; + let .9 = S .10 .11; + let .2 = S .8 .9; + let .5 = 1i64; + let .6 = Index 0 .2; + dec .2; + let .7 = lowlevel Eq .5 .6; + if .7 then + let .3 = 0i64; + ret .3; else - let Test.4 = 1i64; - ret Test.4; + let .4 = 1i64; + ret .4; "# ), ) @@ -1881,38 +1882,38 @@ mod test_mono { ), indoc!( r#" - procedure Test.0 (): - let Test.14 = 0i64; - let Test.16 = 0i64; - let Test.18 = 0i64; - let Test.20 = 1i64; - let Test.19 = Z Test.20; - let Test.17 = S Test.18 Test.19; - let Test.15 = S Test.16 Test.17; - let Test.2 = S Test.14 Test.15; - let Test.11 = 0i64; - let Test.12 = Index 0 Test.2; - let Test.13 = lowlevel Eq Test.11 Test.12; - if Test.13 then - let Test.7 = Index 1 Test.2; - inc Test.7; - let Test.8 = 0i64; - let Test.9 = Index 0 Test.7; - dec Test.7; - let Test.10 = lowlevel Eq Test.8 Test.9; - if Test.10 then - let Test.4 = Index 1 Test.2; - dec Test.2; - let Test.3 = 1i64; - ret Test.3; + procedure .0 (): + let .14 = 0i64; + let .16 = 0i64; + let .18 = 0i64; + let .20 = 1i64; + let .19 = Z .20; + let .17 = S .18 .19; + let .15 = S .16 .17; + let .2 = S .14 .15; + let .11 = 0i64; + let .12 = Index 0 .2; + let .13 = lowlevel Eq .11 .12; + if .13 then + let .7 = Index 1 .2; + inc .7; + let .8 = 0i64; + let .9 = Index 0 .7; + dec .7; + let .10 = lowlevel Eq .8 .9; + if .10 then + let .4 = Index 1 .2; + dec .2; + let .3 = 1i64; + ret .3; else - dec Test.2; - let Test.5 = 0i64; - ret Test.5; + dec .2; + let .5 = 0i64; + ret .5; else - dec Test.2; - let Test.6 = 0i64; - ret Test.6; + dec .2; + let .6 = 0i64; + ret .6; "# ), ) @@ -1938,51 +1939,51 @@ mod test_mono { ), indoc!( r#" + procedure .1 (.6): + let .18 = Index 0 .6; + let .19 = false; + let .20 = lowlevel Eq .19 .18; + if .20 then + let .8 = Index 1 .6; + ret .8; + else + let .10 = Index 1 .6; + ret .10; + + procedure .1 (.6): + let .29 = Index 0 .6; + let .30 = false; + let .31 = lowlevel Eq .30 .29; + if .31 then + let .8 = 3i64; + ret .8; + else + let .10 = 5i64; + ret .10; + procedure Num.16 (#Attr.2, #Attr.3): - let Test.13 = lowlevel NumMul #Attr.2 #Attr.3; - ret Test.13; + let .13 = lowlevel NumMul #Attr.2 #Attr.3; + ret .13; - procedure Test.1 (Test.6): - let Test.18 = Index 0 Test.6; - let Test.19 = false; - let Test.20 = lowlevel Eq Test.19 Test.18; - if Test.20 then - let Test.8 = Index 1 Test.6; - ret Test.8; - else - let Test.10 = Index 1 Test.6; - ret Test.10; - - procedure Test.1 (Test.6): - let Test.29 = Index 0 Test.6; - let Test.30 = false; - let Test.31 = lowlevel Eq Test.30 Test.29; - if Test.31 then - let Test.8 = 3i64; - ret Test.8; - else - let Test.10 = 5i64; - ret Test.10; - - procedure Test.0 (): - let Test.34 = true; - let Test.33 = Struct {Test.34}; - let Test.5 = CallByName Test.1 Test.33; - let Test.32 = false; - let Test.26 = Struct {Test.32}; - let Test.3 = CallByName Test.1 Test.26; - let Test.24 = true; - let Test.25 = 11i64; - let Test.23 = Struct {Test.24, Test.25}; - let Test.4 = CallByName Test.1 Test.23; - let Test.21 = false; - let Test.22 = 7i64; - let Test.15 = Struct {Test.21, Test.22}; - let Test.2 = CallByName Test.1 Test.15; - let Test.14 = CallByName Num.16 Test.2 Test.3; - let Test.12 = CallByName Num.16 Test.14 Test.4; - let Test.11 = CallByName Num.16 Test.12 Test.5; - ret Test.11; + procedure .0 (): + let .34 = true; + let .33 = Struct {.34}; + let .5 = CallByName .1 .33; + let .32 = false; + let .26 = Struct {.32}; + let .3 = CallByName .1 .26; + let .24 = true; + let .25 = 11i64; + let .23 = Struct {.24, .25}; + let .4 = CallByName .1 .23; + let .21 = false; + let .22 = 7i64; + let .15 = Struct {.21, .22}; + let .2 = CallByName .1 .15; + let .14 = CallByName Num.16 .2 .3; + let .12 = CallByName Num.16 .14 .4; + let .11 = CallByName Num.16 .12 .5; + ret .11; "# ), ) @@ -2006,37 +2007,37 @@ mod test_mono { indoc!( r#" procedure Num.14 (#Attr.2, #Attr.3): - let Test.6 = lowlevel NumAdd #Attr.2 #Attr.3; - ret Test.6; + let .6 = lowlevel NumAdd #Attr.2 #Attr.3; + ret .6; - procedure Test.0 (): - let Test.17 = 0i64; - let Test.19 = 0i64; - let Test.20 = 41i64; - let Test.18 = Just Test.19 Test.20; - let Test.2 = Just Test.17 Test.18; - joinpoint Test.14: - let Test.8 = 1i64; - ret Test.8; + procedure .0 (): + let .17 = 0i64; + let .19 = 0i64; + let .20 = 41i64; + let .18 = Just .19 .20; + let .2 = Just .17 .18; + joinpoint .14: + let .8 = 1i64; + ret .8; in - let Test.12 = 0i64; - let Test.13 = Index 0 Test.2; - let Test.16 = lowlevel Eq Test.12 Test.13; - if Test.16 then - let Test.9 = Index 1 Test.2; - let Test.10 = 0i64; - let Test.11 = Index 0 Test.9; - let Test.15 = lowlevel Eq Test.10 Test.11; - if Test.15 then - let Test.7 = Index 1 Test.2; - let Test.3 = Index 1 Test.7; - let Test.5 = 1i64; - let Test.4 = CallByName Num.14 Test.3 Test.5; - ret Test.4; + let .12 = 0i64; + let .13 = Index 0 .2; + let .16 = lowlevel Eq .12 .13; + if .16 then + let .9 = Index 1 .2; + let .10 = 0i64; + let .11 = Index 0 .9; + let .15 = lowlevel Eq .10 .11; + if .15 then + let .7 = Index 1 .2; + let .3 = Index 1 .7; + let .5 = 1i64; + let .4 = CallByName Num.14 .3 .5; + ret .4; else - jump Test.14; + jump .14; else - jump Test.14; + jump .14; "# ), ) @@ -2065,34 +2066,34 @@ mod test_mono { indoc!( r#" procedure Num.14 (#Attr.2, #Attr.3): - let Test.9 = lowlevel NumAdd #Attr.2 #Attr.3; - ret Test.9; + let .9 = lowlevel NumAdd #Attr.2 #Attr.3; + ret .9; - procedure Test.3 (Test.4): - let Test.15 = true; - let Test.16 = 1i64; - let Test.17 = Index 0 Test.4; - let Test.18 = lowlevel Eq Test.16 Test.17; - let Test.14 = lowlevel And Test.18 Test.15; - if Test.14 then - dec Test.4; - let Test.10 = 0i64; - ret Test.10; + procedure .3 (.4): + let .15 = true; + let .16 = 1i64; + let .17 = Index 0 .4; + let .18 = lowlevel Eq .16 .17; + let .14 = lowlevel And .18 .15; + if .14 then + dec .4; + let .10 = 0i64; + ret .10; else - let Test.5 = Index 2 Test.4; - dec Test.4; - let Test.12 = 1i64; - let Test.13 = CallByName Test.3 Test.5; - let Test.11 = CallByName Num.14 Test.12 Test.13; - ret Test.11; + let .5 = Index 2 .4; + dec .4; + let .12 = 1i64; + let .13 = CallByName .3 .5; + let .11 = CallByName Num.14 .12 .13; + ret .11; - procedure Test.0 (): - let Test.20 = 1i64; - let Test.2 = Nil Test.20; - let Test.7 = CallByName Test.3 Test.2; - let Test.8 = CallByName Test.3 Test.2; - let Test.6 = CallByName Num.14 Test.7 Test.8; - ret Test.6; + procedure .0 (): + let .20 = 1i64; + let .2 = Nil .20; + let .7 = CallByName .3 .2; + let .8 = CallByName .3 .2; + let .6 = CallByName Num.14 .7 .8; + ret .6; "# ), ) @@ -2103,7 +2104,7 @@ mod test_mono { compiles_to_ir( indoc!( r#" - app Test provides [ main ] imports [] + app "test" provides [ main ] to "./platform" swap : Int, Int, List a -> List a swap = \i, j, list -> @@ -2124,68 +2125,68 @@ mod test_mono { ), indoc!( r#" - procedure List.3 (#Attr.2, #Attr.3): - let Test.40 = lowlevel ListLen #Attr.2; - let Test.36 = lowlevel NumLt #Attr.3 Test.40; - if Test.36 then - let Test.38 = 1i64; - let Test.39 = lowlevel ListGetUnsafe #Attr.2 #Attr.3; - let Test.37 = Ok Test.38 Test.39; - ret Test.37; + procedure .1 (.2, .3, .4): + let .31 = CallByName List.3 .4 .2; + let .32 = CallByName List.3 .4 .3; + let .12 = Struct {.31, .32}; + joinpoint .28: + let .21 = Array []; + ret .21; + in + let .25 = Index 1 .12; + let .26 = 1i64; + let .27 = Index 0 .25; + let .30 = lowlevel Eq .26 .27; + if .30 then + let .22 = Index 0 .12; + let .23 = 1i64; + let .24 = Index 0 .22; + let .29 = lowlevel Eq .23 .24; + if .29 then + let .20 = Index 0 .12; + let .5 = Index 1 .20; + let .19 = Index 1 .12; + let .6 = Index 1 .19; + let .14 = CallByName List.4 .4 .2 .6; + let .13 = CallByName List.4 .14 .3 .5; + ret .13; + else + dec .4; + jump .28; else - let Test.34 = 0i64; - let Test.35 = Struct {}; - let Test.33 = Err Test.34 Test.35; - ret Test.33; + dec .4; + jump .28; + + procedure List.3 (#Attr.2, #Attr.3): + let .40 = lowlevel ListLen #Attr.2; + let .36 = lowlevel NumLt #Attr.3 .40; + if .36 then + let .38 = 1i64; + let .39 = lowlevel ListGetUnsafe #Attr.2 #Attr.3; + let .37 = Ok .38 .39; + ret .37; + else + let .34 = 0i64; + let .35 = Struct {}; + let .33 = Err .34 .35; + ret .33; procedure List.4 (#Attr.2, #Attr.3, #Attr.4): - let Test.18 = lowlevel ListLen #Attr.2; - let Test.16 = lowlevel NumLt #Attr.3 Test.18; - if Test.16 then - let Test.17 = lowlevel ListSet #Attr.2 #Attr.3 #Attr.4; - ret Test.17; + let .18 = lowlevel ListLen #Attr.2; + let .16 = lowlevel NumLt #Attr.3 .18; + if .16 then + let .17 = lowlevel ListSet #Attr.2 #Attr.3 #Attr.4; + ret .17; else ret #Attr.2; - procedure Test.1 (Test.2, Test.3, Test.4): - let Test.31 = CallByName List.3 Test.4 Test.2; - let Test.32 = CallByName List.3 Test.4 Test.3; - let Test.12 = Struct {Test.31, Test.32}; - joinpoint Test.28: - let Test.21 = Array []; - ret Test.21; - in - let Test.25 = Index 1 Test.12; - let Test.26 = 1i64; - let Test.27 = Index 0 Test.25; - let Test.30 = lowlevel Eq Test.26 Test.27; - if Test.30 then - let Test.22 = Index 0 Test.12; - let Test.23 = 1i64; - let Test.24 = Index 0 Test.22; - let Test.29 = lowlevel Eq Test.23 Test.24; - if Test.29 then - let Test.20 = Index 0 Test.12; - let Test.5 = Index 1 Test.20; - let Test.19 = Index 1 Test.12; - let Test.6 = Index 1 Test.19; - let Test.14 = CallByName List.4 Test.4 Test.2 Test.6; - let Test.13 = CallByName List.4 Test.14 Test.3 Test.5; - ret Test.13; - else - dec Test.4; - jump Test.28; - else - dec Test.4; - jump Test.28; - - procedure Test.0 (): - let Test.9 = 0i64; - let Test.10 = 0i64; - let Test.41 = 1i64; - let Test.11 = Array [Test.41]; - let Test.8 = CallByName Test.1 Test.9 Test.10 Test.11; - ret Test.8; + procedure .0 (): + let .9 = 0i64; + let .10 = 0i64; + let .41 = 1i64; + let .11 = Array [.41]; + let .8 = CallByName .1 .9 .10 .11; + ret .8; "# ), ) @@ -2210,11 +2211,11 @@ mod test_mono { ), indoc!( r#" - procedure Test.0 (): - let Test.1 = 5i64; - let Test.4 = 17i64; - let Test.2 = 1337i64; - ret Test.2; + procedure .0 (): + let .1 = 5i64; + let .4 = 17i64; + let .2 = 1337i64; + ret .2; "# ), ) @@ -2242,14 +2243,14 @@ mod test_mono { ), indoc!( r#" - procedure Test.0 (): - let Test.1 = 5i64; - let Test.4 = 17i64; - let Test.5 = 1i64; - let Test.2 = 1337i64; - let Test.7 = Struct {Test.2, Test.4}; - let Test.6 = Index 0 Test.7; - ret Test.6; + procedure .0 (): + let .1 = 5i64; + let .4 = 17i64; + let .5 = 1i64; + let .2 = 1337i64; + let .7 = Struct {.2, .4}; + let .6 = Index 0 .7; + ret .6; "# ), ) @@ -2260,7 +2261,7 @@ mod test_mono { compiles_to_ir( indoc!( r#" - app Test provides [ main ] imports [] + app "test" provides [ main ] to "./platform" foo = \{} -> x = 42 @@ -2274,24 +2275,24 @@ mod test_mono { ), indoc!( r#" - procedure Test.1 (Test.5): - let Test.2 = 42i64; - let Test.13 = FunctionPointer Test.3; - let Test.3 = Struct {Test.13, Test.2}; - ret Test.3; + procedure .1 (.5): + let .2 = 42i64; + let .13 = FunctionPointer .3; + let .3 = Struct {.13, .2}; + ret .3; - procedure Test.3 (Test.11, #Attr.12): - let Test.2 = Index 0 #Attr.12; - ret Test.2; + procedure .3 (.11, #Attr.12): + let .2 = Index 0 #Attr.12; + ret .2; - procedure Test.0 (): - let Test.10 = Struct {}; - let Test.4 = CallByName Test.1 Test.10; - let Test.7 = Struct {}; - let Test.8 = Index 1 Test.4; - let Test.9 = Index 0 Test.4; - let Test.6 = CallByPointer Test.9 Test.7 Test.8; - ret Test.6; + procedure .0 (): + let .10 = Struct {}; + let .4 = CallByName .1 .10; + let .7 = Struct {}; + let .8 = Index 1 .4; + let .9 = Index 0 .4; + let .6 = CallByPointer .9 .7 .8; + ret .6; "# ), ) @@ -2302,7 +2303,7 @@ mod test_mono { compiles_to_ir( indoc!( r#" - app Test provides [ main ] imports [] + app "test" provides [ main ] to "./platform" foo = \{} -> x = 41 @@ -2319,27 +2320,27 @@ mod test_mono { ), indoc!( r#" + procedure .1 (.5): + let .2 = 41i64; + let .12 = FunctionPointer .3; + let .11 = Struct {.12, .2}; + let .10 = Array [.11]; + ret .10; + + procedure .3 (.9, #Attr.12): + let .2 = Index 0 #Attr.12; + ret .2; + procedure List.7 (#Attr.2): - let Test.7 = lowlevel ListLen #Attr.2; - ret Test.7; + let .7 = lowlevel ListLen #Attr.2; + ret .7; - procedure Test.1 (Test.5): - let Test.2 = 41i64; - let Test.12 = FunctionPointer Test.3; - let Test.11 = Struct {Test.12, Test.2}; - let Test.10 = Array [Test.11]; - ret Test.10; - - procedure Test.3 (Test.9, #Attr.12): - let Test.2 = Index 0 #Attr.12; - ret Test.2; - - procedure Test.0 (): - let Test.8 = Struct {}; - let Test.4 = CallByName Test.1 Test.8; - let Test.6 = CallByName List.7 Test.4; - dec Test.4; - ret Test.6; + procedure .0 (): + let .8 = Struct {}; + let .4 = CallByName .1 .8; + let .6 = CallByName List.7 .4; + dec .4; + ret .6; "# ), ) From 7e5fde1d154fbc3c7aa79f1f9d013204be809aee Mon Sep 17 00:00:00 2001 From: Richard Feldman Date: Fri, 20 Nov 2020 23:05:37 -0500 Subject: [PATCH 19/35] Fix solve_expr --- compiler/solve/tests/solve_expr.rs | 39 +++++++++++++++--------------- 1 file changed, 20 insertions(+), 19 deletions(-) diff --git a/compiler/solve/tests/solve_expr.rs b/compiler/solve/tests/solve_expr.rs index 060fd27e0f..3ad29d4a48 100644 --- a/compiler/solve/tests/solve_expr.rs +++ b/compiler/solve/tests/solve_expr.rs @@ -128,7 +128,8 @@ mod solve_expr { } fn promote_expr_to_module(src: &str) -> String { - let mut buffer = String::from("app Test provides [ main ] imports []\n\nmain =\n"); + let mut buffer = + String::from("app \"test\" provides [ main ] to \"./platform\"\n\nmain =\n"); for line in src.lines() { // indent the body! @@ -2054,7 +2055,7 @@ mod solve_expr { infer_eq( indoc!( r#" - app Test provides [ main ] imports [] + app "test" provides [ main ] to "./platform" Peano : [ S Peano, Z ] @@ -2138,7 +2139,7 @@ mod solve_expr { infer_eq_without_problem( indoc!( r#" - app Test provides [ main ] imports [] + app "test" provides [ main ] to "./platform" ConsList a : [ Cons a (ConsList a), Nil ] @@ -2194,7 +2195,7 @@ mod solve_expr { infer_eq( indoc!( r#" - app Test provides [ main ] imports [] + app "test" provides [ main ] to "./platform" map = \peano -> @@ -2632,7 +2633,7 @@ mod solve_expr { infer_eq_without_problem( indoc!( r#" - app Test provides [ main ] imports [] + app "test" provides [ main ] to "./platform" boom = \_ -> boom {} @@ -2978,7 +2979,7 @@ mod solve_expr { infer_eq_without_problem( indoc!( r#" - app Test provides [ main ] imports [] + app "test" provides [ main ] to "./platform" main : List x @@ -2998,7 +2999,7 @@ mod solve_expr { infer_eq_without_problem( indoc!( r#" - app Test provides [ main ] imports [] + app "test" provides [ main ] to "./platform" main = @@ -3019,7 +3020,7 @@ mod solve_expr { infer_eq_without_problem( indoc!( r#" - app Test provides [ main ] imports [] + app "test" provides [ main ] to "./platform" Bar : [ Bar ] Foo : [ Foo Bar Int, Empty ] @@ -3045,7 +3046,7 @@ mod solve_expr { infer_eq_without_problem( indoc!( r#" - app Test provides [ main ] imports [] + app "test" provides [ main ] to "./platform" Foo : [ @Foo [ @Bar ] Int, @Empty ] @@ -3070,7 +3071,7 @@ mod solve_expr { infer_eq_without_problem( indoc!( r#" - app Test provides [ main ] imports [] + app "test" provides [ main ] to "./platform" State a : { count : Int, x : a } @@ -3095,7 +3096,7 @@ mod solve_expr { infer_eq_without_problem( indoc!( r#" - app Test provides [ main ] imports [] + app "test" provides [ main ] to "./platform" # The color of a node. Leaves are considered Black. NodeColor : [ Red, Black ] @@ -3128,7 +3129,7 @@ mod solve_expr { infer_eq_without_problem( indoc!( r#" - app Test provides [ main ] imports [] + app "test" provides [ main ] to "./platform" Dict k : [ Node k (Dict k), Empty ] @@ -3153,7 +3154,7 @@ mod solve_expr { infer_eq_without_problem( indoc!( r#" - app Test provides [ main ] imports [] + app "test" provides [ main ] to "./platform" NodeColor : [ Red, Black ] @@ -3383,7 +3384,7 @@ mod solve_expr { infer_eq_without_problem( indoc!( r#" - app Test provides [ main ] imports [] + app "test" provides [ main ] to "./platform" Dict k : [ Node k (Dict k) (Dict k), Empty ] @@ -3423,7 +3424,7 @@ mod solve_expr { infer_eq_without_problem( indoc!( r#" - app Test provides [ main ] imports [] + app "test" provides [ main ] to "./platform" NodeColor : [ Red, Black ] @@ -3499,7 +3500,7 @@ mod solve_expr { infer_eq_without_problem( indoc!( r#" - app Test provides [ partitionHelp ] imports [] + app "test" provides [ main ] to "./platform" swap : Int, Int, List a -> List a swap = \i, j, list -> @@ -3537,7 +3538,7 @@ mod solve_expr { infer_eq_without_problem( indoc!( r#" - app Test provides [ main ] imports [] + app "test" provides [ main ] to "./platform" Dict k : [ Node k (Dict k) (Dict k), Empty ] @@ -3559,7 +3560,7 @@ mod solve_expr { infer_eq_without_problem( indoc!( r#" - app Test provides [ main ] imports [] + app "test" provides [ main ] to "./platform" Dict k : [ Node k (Dict k) (Dict k), Empty ] @@ -3583,7 +3584,7 @@ mod solve_expr { infer_eq_without_problem( indoc!( r#" - app Test provides [ main ] imports [] + app "test" provides [ main ] to "./platform" NodeColor : [ Red, Black ] From d0f52cb27e2f0c74231282afe9898c8bef73cb1a Mon Sep 17 00:00:00 2001 From: Richard Feldman Date: Fri, 20 Nov 2020 23:22:36 -0500 Subject: [PATCH 20/35] Fix quicksort_partition_help --- compiler/solve/tests/solve_expr.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/solve/tests/solve_expr.rs b/compiler/solve/tests/solve_expr.rs index 3ad29d4a48..1d31ff4e4f 100644 --- a/compiler/solve/tests/solve_expr.rs +++ b/compiler/solve/tests/solve_expr.rs @@ -3500,7 +3500,7 @@ mod solve_expr { infer_eq_without_problem( indoc!( r#" - app "test" provides [ main ] to "./platform" + app "test" provides [ partitionHelp ] to "./platform" swap : Int, Int, List a -> List a swap = \i, j, list -> From 37daff3a571fc41705606d62c2bd739938e5e205 Mon Sep 17 00:00:00 2001 From: Richard Feldman Date: Fri, 20 Nov 2020 23:42:13 -0500 Subject: [PATCH 21/35] Update shared-quicksort Pkg-Config --- examples/shared-quicksort/platform/Pkg-Config.roc | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/examples/shared-quicksort/platform/Pkg-Config.roc b/examples/shared-quicksort/platform/Pkg-Config.roc index c8977f335d..18e1f25552 100644 --- a/examples/shared-quicksort/platform/Pkg-Config.roc +++ b/examples/shared-quicksort/platform/Pkg-Config.roc @@ -1,5 +1,12 @@ -platform roc/quicksort - provides [] - requires {} +platform examples/shared-quicksort + requires { main : Effect {} } + exposes [] + packages {} imports [] - effects Effect {} + provides [ mainForHost ] + effects Effect + { + putChar : Int -> Effect {}, + putLine : Str -> Effect {}, + getLine : Effect Str + } From ed67fc8d09d615c19cefba2c54162df30e52bb89 Mon Sep 17 00:00:00 2001 From: Richard Feldman Date: Fri, 20 Nov 2020 23:45:26 -0500 Subject: [PATCH 22/35] It's gonna be okay, clippy. --- compiler/parse/src/module.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/compiler/parse/src/module.rs b/compiler/parse/src/module.rs index 09e395773a..fff9a6a94f 100644 --- a/compiler/parse/src/module.rs +++ b/compiler/parse/src/module.rs @@ -202,6 +202,7 @@ pub fn app_header<'a>() -> impl Parser<'a, AppHeader<'a>> { }; // rustc must be told the type here + #[allow(clippy::type_complexity)] let opt_imports: Option<( (&'a [CommentOrNewline<'a>], &'a [CommentOrNewline<'a>]), Vec<'a, Located>>, From f3881cd3b839cf30cbeb018992ee309bcab1f0b0 Mon Sep 17 00:00:00 2001 From: Richard Feldman Date: Sat, 21 Nov 2020 10:06:29 -0500 Subject: [PATCH 23/35] Install valgrind 3.16.1 on CI --- ci/install-ci-libraries.sh | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/ci/install-ci-libraries.sh b/ci/install-ci-libraries.sh index ae7e92be0f..ceb4778fc9 100755 --- a/ci/install-ci-libraries.sh +++ b/ci/install-ci-libraries.sh @@ -59,7 +59,17 @@ esac wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | apt-key add - add-apt-repository "${REPO_NAME}" apt-get update -apt-get install -y clang-$LLVM_VERSION lldb-$LLVM_VERSION lld-$LLVM_VERSION clangd-$LLVM_VERSION libc++abi-dev libunwind-dev valgrind +apt-get install -y clang-$LLVM_VERSION lldb-$LLVM_VERSION lld-$LLVM_VERSION clangd-$LLVM_VERSION libc++abi-dev libunwind-dev + +wget https://sourceware.org/pub/valgrind/valgrind-3.16.1.tar.bz2 +tar -xf valgrind-3.16.1.tar.bz2 +pushd valgrind-3.16.1 +apt-get install -y autotools-dev automake +./autogen.sh +./configure +make -j`nproc` +sudo make install +popd # install zig - can't use apt-get since we require at least a specific commit later then the most recent tag (0.6.0) wget -c https://ziglang.org/builds/zig-linux-x86_64-0.6.0+0088efc4b.tar.xz --no-check-certificate From 01495940e3f3a6e841e2d750238b395625de72eb Mon Sep 17 00:00:00 2001 From: Richard Feldman Date: Sat, 21 Nov 2020 10:08:37 -0500 Subject: [PATCH 24/35] Cache compiled valgrind on CI --- .github/workflows/ci.yml | 6 ++++++ ci/install-ci-libraries.sh | 3 ++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 100a5542cf..82ab08363c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -40,6 +40,12 @@ jobs: path: ~/.cargo/git key: ${{ runner.os }}-cargo-index-${{ hashFiles('**/Cargo.lock') }} + - name: Cache compiled valgrind + uses: actions/cache@v1 + with: + path: ~/valgrind-3.6.1/ + key: ${{ runner.os }}-cargo-registry-${{ hashFiles('**/Cargo.lock') }} + - uses: actions-rs/cargo@v1 name: cargo fmt --check with: diff --git a/ci/install-ci-libraries.sh b/ci/install-ci-libraries.sh index ceb4778fc9..e66b84642a 100755 --- a/ci/install-ci-libraries.sh +++ b/ci/install-ci-libraries.sh @@ -63,7 +63,8 @@ apt-get install -y clang-$LLVM_VERSION lldb-$LLVM_VERSION lld-$LLVM_VERSION clan wget https://sourceware.org/pub/valgrind/valgrind-3.16.1.tar.bz2 tar -xf valgrind-3.16.1.tar.bz2 -pushd valgrind-3.16.1 +mv valgrind-3.16.1 ~ +pushd ~/valgrind-3.16.1 apt-get install -y autotools-dev automake ./autogen.sh ./configure From ac4dc52335f8268a1d573314820a4e46b8d08a06 Mon Sep 17 00:00:00 2001 From: Richard Feldman Date: Sat, 21 Nov 2020 11:34:54 -0500 Subject: [PATCH 25/35] Report current valgrind version --- ci/install-ci-libraries.sh | 3 +++ 1 file changed, 3 insertions(+) diff --git a/ci/install-ci-libraries.sh b/ci/install-ci-libraries.sh index e66b84642a..82d0542150 100755 --- a/ci/install-ci-libraries.sh +++ b/ci/install-ci-libraries.sh @@ -72,6 +72,9 @@ make -j`nproc` sudo make install popd +# Report current valgrind version, to confirm it installed properly +valgrind --version + # install zig - can't use apt-get since we require at least a specific commit later then the most recent tag (0.6.0) wget -c https://ziglang.org/builds/zig-linux-x86_64-0.6.0+0088efc4b.tar.xz --no-check-certificate tar -xf zig-linux-x86_64-0.6.0+0088efc4b.tar.xz From c78abeaa544951d64be1c2d15723f5dfdcc43d46 Mon Sep 17 00:00:00 2001 From: Richard Feldman Date: Sat, 21 Nov 2020 11:35:18 -0500 Subject: [PATCH 26/35] Use debug formatter on valgrind error --- cli/tests/helpers.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cli/tests/helpers.rs b/cli/tests/helpers.rs index 0ba8ba883e..8e38646d69 100644 --- a/cli/tests/helpers.rs +++ b/cli/tests/helpers.rs @@ -164,7 +164,7 @@ pub struct ValgrindErrorXWhat { pub fn extract_valgrind_errors(xml: &str) -> Vec { let parsed_xml: ValgrindOutput = from_str(xml).unwrap_or_else(|err| - panic!("failed to parse the `valgrind` xml output. Error was:\n\n{:?}\n\nRaw valgrind output was:\n\n{}", err, xml)); + panic!("failed to parse the `valgrind` xml output. Error was:\n\n{:?}\n\nRaw valgrind output was:\n\n{:?}", err, xml)); parsed_xml .fields .iter() From 6563d0b306eeb0c7267784cecbf81a1d3752e0c1 Mon Sep 17 00:00:00 2001 From: Richard Feldman Date: Sun, 22 Nov 2020 23:03:02 -0500 Subject: [PATCH 27/35] Improve valgrind diagnostics --- cli/tests/cli_run.rs | 5 ++++- cli/tests/helpers.rs | 12 ++++++------ 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/cli/tests/cli_run.rs b/cli/tests/cli_run.rs index 73e89f9b6b..0848310020 100644 --- a/cli/tests/cli_run.rs +++ b/cli/tests/cli_run.rs @@ -27,7 +27,10 @@ mod cli_run { let out = if use_valgrind { let (valgrind_out, raw_xml) = run_with_valgrind(&[file.with_file_name("app").to_str().unwrap()]); - let memory_errors = extract_valgrind_errors(&raw_xml); + let memory_errors = extract_valgrind_errors(&raw_xml).unwrap_or_else(|err| { + panic!("failed to parse the `valgrind` xml output. Error was:\n\n{:?}\n\nvalgrind xml was:\n\n{:?}\n\nother valgrind output was:\n\n{:?}", err, valgrind_out, raw_xml); + }); + if !memory_errors.is_empty() { panic!("{:?}", memory_errors); } diff --git a/cli/tests/helpers.rs b/cli/tests/helpers.rs index 8e38646d69..1da44d8542 100644 --- a/cli/tests/helpers.rs +++ b/cli/tests/helpers.rs @@ -161,18 +161,18 @@ pub struct ValgrindErrorXWhat { } #[allow(dead_code)] -pub fn extract_valgrind_errors(xml: &str) -> Vec { - let parsed_xml: ValgrindOutput = - from_str(xml).unwrap_or_else(|err| - panic!("failed to parse the `valgrind` xml output. Error was:\n\n{:?}\n\nRaw valgrind output was:\n\n{:?}", err, xml)); - parsed_xml +pub fn extract_valgrind_errors(xml: &str) -> Result, serde_xml_rs::Error> { + let parsed_xml: ValgrindOutput = from_str(xml)?; + let answer = parsed_xml .fields .iter() .filter_map(|field| match field { ValgrindField::Error(err) => Some(err.clone()), _ => None, }) - .collect() + .collect(); + + Ok(answer) } #[allow(dead_code)] From 6453292224d87bfc8e36895f8a77113a4759d4fa Mon Sep 17 00:00:00 2001 From: Richard Feldman Date: Sun, 22 Nov 2020 23:47:39 -0500 Subject: [PATCH 28/35] Tell valgrind the right executable name --- cli/tests/cli_run.rs | 29 ++++++++++++++++++++++++++--- 1 file changed, 26 insertions(+), 3 deletions(-) diff --git a/cli/tests/cli_run.rs b/cli/tests/cli_run.rs index 0848310020..514a4b455a 100644 --- a/cli/tests/cli_run.rs +++ b/cli/tests/cli_run.rs @@ -17,7 +17,13 @@ mod cli_run { use serial_test::serial; use std::path::Path; - fn check_output(file: &Path, flags: &[&str], expected_ending: &str, use_valgrind: bool) { + fn check_output( + file: &Path, + executable_filename: &str, + flags: &[&str], + expected_ending: &str, + use_valgrind: bool, + ) { let compile_out = run_roc(&[&["build", file.to_str().unwrap()], flags].concat()); if !compile_out.stderr.is_empty() { panic!(compile_out.stderr); @@ -26,7 +32,7 @@ mod cli_run { let out = if use_valgrind { let (valgrind_out, raw_xml) = - run_with_valgrind(&[file.with_file_name("app").to_str().unwrap()]); + run_with_valgrind(&[file.with_file_name(executable_filename).to_str().unwrap()]); let memory_errors = extract_valgrind_errors(&raw_xml).unwrap_or_else(|err| { panic!("failed to parse the `valgrind` xml output. Error was:\n\n{:?}\n\nvalgrind xml was:\n\n{:?}\n\nother valgrind output was:\n\n{:?}", err, valgrind_out, raw_xml); }); @@ -36,7 +42,10 @@ mod cli_run { } valgrind_out } else { - run_cmd(file.with_file_name("app").to_str().unwrap(), &[]) + run_cmd( + file.with_file_name(executable_filename).to_str().unwrap(), + &[], + ) }; if !&out.stdout.ends_with(expected_ending) { panic!( @@ -52,6 +61,7 @@ mod cli_run { fn run_hello_world() { check_output( &example_file("hello-world", "Hello.roc"), + "hello-world", &[], "Hello, World!!!!!!!!!!!!!\n", true, @@ -63,6 +73,7 @@ mod cli_run { fn run_hello_world_optimized() { check_output( &example_file("hello-world", "Hello.roc"), + "hello-world", &[], "Hello, World!!!!!!!!!!!!!\n", true, @@ -74,6 +85,7 @@ mod cli_run { fn run_quicksort_not_optimized() { check_output( &example_file("quicksort", "Quicksort.roc"), + "quicksort", &[], "[0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2]\n", false, @@ -85,6 +97,7 @@ mod cli_run { fn run_quicksort_optimized() { check_output( &example_file("quicksort", "Quicksort.roc"), + "quicksort", &["--optimize"], "[0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2]\n", false, @@ -98,6 +111,7 @@ mod cli_run { fn run_quicksort_valgrind() { check_output( &example_file("quicksort", "Quicksort.roc"), + "quicksort", &[], "[0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2]\n", true, @@ -111,6 +125,7 @@ mod cli_run { fn run_quicksort_optimized_valgrind() { check_output( &example_file("quicksort", "Quicksort.roc"), + "quicksort", &["--optimize"], "[0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2]\n", true, @@ -122,6 +137,7 @@ mod cli_run { fn run_multi_module() { check_output( &example_file("multi-module", "Quicksort.roc"), + "quicksort", &[], "[0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2]\n", false, @@ -133,6 +149,7 @@ mod cli_run { fn run_multi_module_optimized() { check_output( &example_file("multi-module", "Quicksort.roc"), + "quicksort", &["--optimize"], "[0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2]\n", false, @@ -146,6 +163,7 @@ mod cli_run { fn run_multi_module_valgrind() { check_output( &example_file("multi-module", "Quicksort.roc"), + "quicksort", &[], "[0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2]\n", true, @@ -159,6 +177,7 @@ mod cli_run { fn run_multi_module_optimized_valgrind() { check_output( &example_file("multi-module", "Quicksort.roc"), + "quicksort", &["--optimize"], "[0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2]\n", true, @@ -181,6 +200,7 @@ mod cli_run { fn run_multi_dep_str_unoptimized() { check_output( &fixture_file("multi-dep-str", "Main.roc"), + "multi-dep-str", &[], "I am Dep2.str2\n", true, @@ -192,6 +212,7 @@ mod cli_run { fn run_multi_dep_str_optimized() { check_output( &fixture_file("multi-dep-str", "Main.roc"), + "multi-dep-str", &["--optimize"], "I am Dep2.str2\n", true, @@ -203,6 +224,7 @@ mod cli_run { fn run_multi_dep_thunk_unoptimized() { check_output( &fixture_file("multi-dep-thunk", "Main.roc"), + "multi-dep-thunk", &[], "I am Dep2.value2\n", true, @@ -214,6 +236,7 @@ mod cli_run { fn run_multi_dep_thunk_optimized() { check_output( &fixture_file("multi-dep-thunk", "Main.roc"), + "multi-dep-thunk", &["--optimize"], "I am Dep2.value2\n", true, From f6e42e610f85d183c7e47a5446335b6173dd418c Mon Sep 17 00:00:00 2001 From: Richard Feldman Date: Mon, 23 Nov 2020 00:20:50 -0500 Subject: [PATCH 29/35] Fix repl --- cli/src/repl/gen.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/cli/src/repl/gen.rs b/cli/src/repl/gen.rs index 775345182f..1d9427842a 100644 --- a/cli/src/repl/gen.rs +++ b/cli/src/repl/gen.rs @@ -109,7 +109,7 @@ pub fn gen_and_eval(src: &[u8], target: Triple, opt_level: OptLevel) -> Result Result String { - let mut buffer = String::from("app Repl provides [ replOutput ] imports []\n\nreplOutput =\n"); + let mut buffer = + String::from("app \"app\" provides [ replOutput ] to \"./platform\"\n\nreplOutput =\n"); for line in src.lines() { // indent the body! From 144bdcb3bb3f1d5708f44c376bc9829188ccfd7e Mon Sep 17 00:00:00 2001 From: Richard Feldman Date: Mon, 23 Nov 2020 00:24:19 -0500 Subject: [PATCH 30/35] Fix some gen_primitives tests --- compiler/gen/tests/gen_primitives.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/gen/tests/gen_primitives.rs b/compiler/gen/tests/gen_primitives.rs index 8ab6c06899..27404e45a1 100644 --- a/compiler/gen/tests/gen_primitives.rs +++ b/compiler/gen/tests/gen_primitives.rs @@ -1444,7 +1444,7 @@ mod gen_primitives { assert_non_opt_evals_to!( indoc!( r#" - app Test provides [ main ] imports [] + app "test" provides [ main ] to "./platform" ConsList a : [ Cons a (ConsList a), Nil ] @@ -1470,7 +1470,7 @@ mod gen_primitives { assert_non_opt_evals_to!( indoc!( r#" - app Test provides [ main ] imports [] + app "test" provides [ main ] to "./platform" ConsList a : [ Cons a (ConsList a), Nil ] From 2991e695aa05f73a84cebda760704508097d9d60 Mon Sep 17 00:00:00 2001 From: Richard Feldman Date: Mon, 23 Nov 2020 00:26:29 -0500 Subject: [PATCH 31/35] Ignore *.o in examples/ and fixtures/ --- cli/tests/fixtures/.gitignore | 3 +-- examples/.gitignore | 4 +--- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/cli/tests/fixtures/.gitignore b/cli/tests/fixtures/.gitignore index 84792abbd6..f159786dd3 100644 --- a/cli/tests/fixtures/.gitignore +++ b/cli/tests/fixtures/.gitignore @@ -1,4 +1,3 @@ app -host.o -c_host.o +*.o *.dSYM diff --git a/examples/.gitignore b/examples/.gitignore index a6f6981d3d..f159786dd3 100644 --- a/examples/.gitignore +++ b/examples/.gitignore @@ -1,5 +1,3 @@ app -host.o -c_host.o -roc_app.o +*.o *.dSYM From d632e588effa59317d62e0e6793c46aefb74dae9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Besnier?= Date: Mon, 23 Nov 2020 14:24:10 +0100 Subject: [PATCH 32/35] add failing test --- compiler/parse/tests/test_parse.rs | 39 ++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/compiler/parse/tests/test_parse.rs b/compiler/parse/tests/test_parse.rs index 3f07260220..c073d671a3 100644 --- a/compiler/parse/tests/test_parse.rs +++ b/compiler/parse/tests/test_parse.rs @@ -1733,6 +1733,45 @@ mod test_parse { ); } + #[test] + fn multiline_type_signature() { + assert_parses_to( + "f :\n {}\n\n42", + Defs( + &[&Located::new( + 0, + 0, + 0, + 6, + Def::Annotation( + Located::new(0, 0, 0, 1, Pattern::Identifier("f")), + Located::new( + 1, + 1, + 4, + 6, + TypeAnnotation::SpaceBefore( + &TypeAnnotation::Record { + fields: &[], + ext: None, + final_comments: &[], + }, + &[Newline], + ), + ), + ), + )], + &Located::new( + 2, + 2, + 0, + 2, + Expr::SpaceBefore(&Expr::Num("42"), &[Newline, Newline]), + ), + ), + ); + } + // #[test] // fn type_signature_function_def() { // use TypeAnnotation; From 88373240a924af2269839f16c43c67a39dbbaa93 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Besnier?= Date: Mon, 23 Nov 2020 15:30:48 +0100 Subject: [PATCH 33/35] fix multiline type signature bug --- compiler/parse/src/expr.rs | 22 ++-------------------- compiler/parse/tests/test_parse.rs | 6 +++--- 2 files changed, 5 insertions(+), 23 deletions(-) diff --git a/compiler/parse/src/expr.rs b/compiler/parse/src/expr.rs index 480b3fb302..8818d6ac79 100644 --- a/compiler/parse/src/expr.rs +++ b/compiler/parse/src/expr.rs @@ -1730,17 +1730,8 @@ fn ident_etc<'a>(min_indent: u16) -> impl Parser<'a, Expr<'a>> { }; let region = loc_ident.region; let loc_pattern = Located { region, value }; - let (spaces_after_colon, state) = space0(min_indent).parse(arena, state)?; - let (parsed_expr, state) = - parse_def_signature(min_indent, colon_indent, arena, state, loc_pattern)?; - let answer = if spaces_after_colon.is_empty() { - parsed_expr - } else { - Expr::SpaceBefore(arena.alloc(parsed_expr), spaces_after_colon) - }; - - Ok((answer, state)) + parse_def_signature(min_indent, colon_indent, arena, state, loc_pattern) } (None, None) => { // We got nothin' @@ -1977,17 +1968,8 @@ fn record_literal<'a>(min_indent: u16) -> impl Parser<'a, Expr<'a>> { Pattern::SpaceAfter(arena.alloc(pattern), spaces_before_colon) }; let loc_pattern = Located { region, value }; - let (spaces_after_equals, state) = space0(min_indent).parse(arena, state)?; - let (parsed_expr, state) = - parse_def_signature(min_indent, colon_indent, arena, state, loc_pattern)?; - let answer = if spaces_after_equals.is_empty() { - parsed_expr - } else { - Expr::SpaceBefore(arena.alloc(parsed_expr), spaces_after_equals) - }; - - Ok((answer, state)) + parse_def_signature(min_indent, colon_indent, arena, state, loc_pattern) } } }, diff --git a/compiler/parse/tests/test_parse.rs b/compiler/parse/tests/test_parse.rs index c073d671a3..a1e68b8edf 100644 --- a/compiler/parse/tests/test_parse.rs +++ b/compiler/parse/tests/test_parse.rs @@ -1740,7 +1740,7 @@ mod test_parse { Defs( &[&Located::new( 0, - 0, + 1, 0, 6, Def::Annotation( @@ -1762,8 +1762,8 @@ mod test_parse { ), )], &Located::new( - 2, - 2, + 3, + 3, 0, 2, Expr::SpaceBefore(&Expr::Num("42"), &[Newline, Newline]), From 91bc0a36c36eff192403adcd6550d583bfe1256b Mon Sep 17 00:00:00 2001 From: Richard Feldman Date: Mon, 23 Nov 2020 21:43:28 -0500 Subject: [PATCH 34/35] Improve valgrind error output --- cli/tests/cli_run.rs | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/cli/tests/cli_run.rs b/cli/tests/cli_run.rs index 514a4b455a..5cc55f1b52 100644 --- a/cli/tests/cli_run.rs +++ b/cli/tests/cli_run.rs @@ -33,13 +33,24 @@ mod cli_run { let out = if use_valgrind { let (valgrind_out, raw_xml) = run_with_valgrind(&[file.with_file_name(executable_filename).to_str().unwrap()]); - let memory_errors = extract_valgrind_errors(&raw_xml).unwrap_or_else(|err| { - panic!("failed to parse the `valgrind` xml output. Error was:\n\n{:?}\n\nvalgrind xml was:\n\n{:?}\n\nother valgrind output was:\n\n{:?}", err, valgrind_out, raw_xml); - }); - if !memory_errors.is_empty() { - panic!("{:?}", memory_errors); + if valgrind_out.status.success() { + let memory_errors = extract_valgrind_errors(&raw_xml).unwrap_or_else(|err| { + panic!("failed to parse the `valgrind` xml output. Error was:\n\n{:?}\n\nvalgrind xml was: \"{}\"\n\nvalgrind stdout was: \"{}\"\n\nvalgrind stderr was: \"{}\"", err, raw_xml, valgrind_out.stdout, valgrind_out.stderr); + }); + + if !memory_errors.is_empty() { + panic!("{:?}", memory_errors); + } + } else { + let exit_code = match valgrind_out.status.code() { + Some(code) => format!("exit code {}", code), + None => "no exit code".to_string(), + }; + + panic!("`valgrind` exited with {}. valgrind stdout was: \"{}\"\n\nvalgrind stderr was: \"{}\"", exit_code, valgrind_out.stdout, valgrind_out.stderr); } + valgrind_out } else { run_cmd( From 77c84eaaa8e750e8aeb7818473fce2ccfc5f0900 Mon Sep 17 00:00:00 2001 From: Richard Feldman Date: Mon, 23 Nov 2020 21:47:15 -0500 Subject: [PATCH 35/35] Install a libc6-dbg (valgrind requested it) --- ci/install-ci-libraries.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ci/install-ci-libraries.sh b/ci/install-ci-libraries.sh index 82d0542150..dffa36436a 100755 --- a/ci/install-ci-libraries.sh +++ b/ci/install-ci-libraries.sh @@ -59,7 +59,7 @@ esac wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | apt-key add - add-apt-repository "${REPO_NAME}" apt-get update -apt-get install -y clang-$LLVM_VERSION lldb-$LLVM_VERSION lld-$LLVM_VERSION clangd-$LLVM_VERSION libc++abi-dev libunwind-dev +apt-get install -y clang-$LLVM_VERSION lldb-$LLVM_VERSION lld-$LLVM_VERSION clangd-$LLVM_VERSION libc++abi-dev libunwind-dev libc6-dbg wget https://sourceware.org/pub/valgrind/valgrind-3.16.1.tar.bz2 tar -xf valgrind-3.16.1.tar.bz2