Merge branch 'main' into fromutf-roc

This commit is contained in:
shua 2025-01-20 19:16:38 +01:00
commit 6c29d7aa1f
No known key found for this signature in database
237 changed files with 7237 additions and 5353 deletions

View file

@ -39,7 +39,6 @@ ROC_TRACE_COMPACTION = "0"
ROC_PRINT_UNIFICATIONS_DERIVED = "0" ROC_PRINT_UNIFICATIONS_DERIVED = "0"
ROC_PRINT_MISMATCHES = "0" ROC_PRINT_MISMATCHES = "0"
ROC_PRINT_FIXPOINT_FIXING = "0" ROC_PRINT_FIXPOINT_FIXING = "0"
ROC_VERIFY_RIGID_LET_GENERALIZED = "0"
ROC_VERIFY_OCCURS_ONE_RECURSION = "0" ROC_VERIFY_OCCURS_ONE_RECURSION = "0"
ROC_CHECK_MONO_IR = "0" ROC_CHECK_MONO_IR = "0"
ROC_PRINT_IR_AFTER_SPECIALIZATION = "0" ROC_PRINT_IR_AFTER_SPECIALIZATION = "0"

27
Cargo.lock generated
View file

@ -2393,6 +2393,7 @@ dependencies = [
"bumpalo", "bumpalo",
"indoc", "indoc",
"pretty_assertions", "pretty_assertions",
"roc_can_solo",
"roc_collections", "roc_collections",
"roc_error_macros", "roc_error_macros",
"roc_exhaustive", "roc_exhaustive",
@ -2408,6 +2409,25 @@ dependencies = [
"ven_pretty", "ven_pretty",
] ]
[[package]]
name = "roc_can_solo"
version = "0.0.1"
dependencies = [
"bitvec",
"bumpalo",
"roc_collections",
"roc_error_macros",
"roc_module",
"roc_parse",
"roc_problem",
"roc_region",
"roc_serialize",
"roc_types",
"soa",
"static_assertions",
"ven_pretty",
]
[[package]] [[package]]
name = "roc_checkmate" name = "roc_checkmate"
version = "0.0.1" version = "0.0.1"
@ -2805,6 +2825,7 @@ dependencies = [
"pretty_assertions", "pretty_assertions",
"roc_builtins", "roc_builtins",
"roc_can", "roc_can",
"roc_can_solo",
"roc_collections", "roc_collections",
"roc_constrain", "roc_constrain",
"roc_derive", "roc_derive",
@ -2828,6 +2849,8 @@ dependencies = [
name = "roc_load_internal" name = "roc_load_internal"
version = "0.0.1" version = "0.0.1"
dependencies = [ dependencies = [
"base64-url",
"blake3",
"bumpalo", "bumpalo",
"crossbeam", "crossbeam",
"indoc", "indoc",
@ -2836,6 +2859,7 @@ dependencies = [
"pretty_assertions", "pretty_assertions",
"roc_builtins", "roc_builtins",
"roc_can", "roc_can",
"roc_can_solo",
"roc_checkmate", "roc_checkmate",
"roc_collections", "roc_collections",
"roc_constrain", "roc_constrain",
@ -3281,6 +3305,7 @@ dependencies = [
name = "roc_types" name = "roc_types"
version = "0.0.1" version = "0.0.1"
dependencies = [ dependencies = [
"bitflags 1.3.2",
"bumpalo", "bumpalo",
"roc_collections", "roc_collections",
"roc_debug_flags", "roc_debug_flags",
@ -3871,6 +3896,7 @@ dependencies = [
"pretty_assertions", "pretty_assertions",
"roc_builtins", "roc_builtins",
"roc_can", "roc_can",
"roc_can_solo",
"roc_collections", "roc_collections",
"roc_constrain", "roc_constrain",
"roc_derive", "roc_derive",
@ -4015,6 +4041,7 @@ dependencies = [
"indoc", "indoc",
"pretty_assertions", "pretty_assertions",
"roc_can", "roc_can",
"roc_can_solo",
"roc_collections", "roc_collections",
"roc_error_macros", "roc_error_macros",
"roc_fmt", "roc_fmt",

View file

@ -1,6 +1,7 @@
[workspace] [workspace]
members = [ members = [
"crates/build/specialize_types", "crates/build/*",
"crates/check/*",
"crates/compiler/*", "crates/compiler/*",
"crates/vendor/*", "crates/vendor/*",
"crates/fs", "crates/fs",
@ -174,6 +175,7 @@ roc_bitcode_bc = { path = "crates/compiler/builtins/bitcode/bc" }
roc_build = { path = "crates/compiler/build" } roc_build = { path = "crates/compiler/build" }
roc_builtins = { path = "crates/compiler/builtins" } roc_builtins = { path = "crates/compiler/builtins" }
roc_can = { path = "crates/compiler/can" } roc_can = { path = "crates/compiler/can" }
roc_can_solo = { path = "crates/check/can_solo" }
roc_checkmate = { path = "crates/compiler/checkmate" } roc_checkmate = { path = "crates/compiler/checkmate" }
roc_checkmate_schema = { path = "crates/compiler/checkmate_schema" } roc_checkmate_schema = { path = "crates/compiler/checkmate_schema" }
roc_cli = { path = "crates/cli" } roc_cli = { path = "crates/cli" }

View file

@ -0,0 +1,23 @@
[package]
name = "roc_can_solo"
description = "Canonicalize a Roc module in preparation for typechecking without any knowledge of other modules."
authors.workspace = true
edition.workspace = true
license.workspace = true
version.workspace = true
[dependencies]
roc_collections.workspace = true
roc_error_macros.workspace = true
roc_module.workspace = true
roc_parse.workspace = true
roc_problem.workspace = true
roc_region.workspace = true
roc_serialize.workspace = true
roc_types.workspace = true
ven_pretty.workspace = true
bitvec.workspace = true
bumpalo.workspace = true
static_assertions.workspace = true
soa.workspace = true

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,48 @@
use std::path::Path;
use bumpalo::Bump;
use roc_module::symbol::ModuleId;
use roc_problem::can::Problem;
use roc_region::all::LineInfo;
/// The canonicalization environment for a particular module.
#[derive(Debug)]
pub struct SoloEnv<'a> {
pub arena: &'a Bump,
pub module_path: &'a Path,
pub solo_home: ModuleId,
/// Problems we've encountered along the way, which will be reported to the user at the end.
pub problems: Vec<Problem>,
pub src: &'a str,
/// Lazily calculated line info. This data is only needed if the code contains calls to `dbg`,
/// otherwise we can leave it as `None` and never pay the cost of scanning the source an extra
/// time.
pub lazy_line_info: &'a mut Option<LineInfo>,
}
impl<'a> SoloEnv<'a> {
#[allow(clippy::too_many_arguments)]
pub fn new(arena: &'a Bump, src: &'a str, module_path: &'a Path) -> SoloEnv<'a> {
SoloEnv {
arena,
module_path,
solo_home: ModuleId::first_after_builtins(),
src,
problems: Vec::new(),
lazy_line_info: arena.alloc(None),
}
}
pub fn line_info(&mut self) -> &LineInfo {
if self.lazy_line_info.is_none() {
*self.lazy_line_info = Some(LineInfo::new(self.src));
}
self.lazy_line_info.as_ref().unwrap()
}
}

View file

@ -0,0 +1,5 @@
#![warn(clippy::dbg_macro)]
pub mod desugar;
pub mod env;
pub mod module;
pub mod scope;

View file

@ -0,0 +1,81 @@
use std::path::PathBuf;
use bumpalo::Bump;
use roc_module::symbol::ModuleId;
use roc_parse::{
ast::{Collection, Defs, Pattern},
header::HeaderType,
};
use roc_problem::can::Problem;
use roc_region::all::{LineInfo, Loc, Region};
use crate::{
desugar::{desugar_defs_node_values, desugar_record_destructures},
env::SoloEnv,
scope::SoloScope,
};
#[derive(Debug)]
pub struct SoloCanOutput<'a> {
pub scope: SoloScope,
pub loc_defs: Defs<'a>,
pub solo_home: ModuleId,
/// Problems we've encountered along the way, which will be reported to the user at the end.
pub problems: Vec<Problem>,
pub src: &'a str,
/// Lazily calculated line info. This data is only needed if the code contains calls to `dbg`,
/// otherwise we can leave it as `None` and never pay the cost of scanning the source an extra
/// time.
pub lazy_line_info: &'a mut Option<LineInfo>,
pub module_params: Option<(Region, Collection<'a, Loc<Pattern<'a>>>)>,
}
// TODO trim these down
#[allow(clippy::too_many_arguments)]
pub fn solo_canonicalize_module_defs<'a>(
arena: &'a Bump,
header_type: HeaderType<'a>,
loc_defs: &'a mut Defs<'a>,
module_path: PathBuf,
src: &'a str,
) -> SoloCanOutput<'a> {
let mut scope = SoloScope::new();
let mut env = SoloEnv::new(arena, src, arena.alloc(module_path));
// Desugar operators (convert them to Apply calls, taking into account
// operator precedence and associativity rules), before doing other canonicalization.
//
// If we did this *during* canonicalization, then each time we
// visited a BinOp node we'd recursively try to apply this to each of its nested
// operators, and then again on *their* nested operators, ultimately applying the
// rules multiple times unnecessarily.
desugar_defs_node_values(&mut env, &mut scope, loc_defs);
let module_params = header_type.get_params().as_ref().map(
|roc_parse::header::ModuleParams {
pattern,
before_arrow: _,
after_arrow: _,
}| {
let desugared_patterns =
desugar_record_destructures(&mut env, &mut scope, pattern.value);
(pattern.region, desugared_patterns)
},
);
SoloCanOutput {
scope,
solo_home: env.solo_home,
loc_defs: loc_defs.clone(),
problems: env.problems,
src: env.src,
lazy_line_info: env.lazy_line_info,
module_params,
}
}

View file

@ -0,0 +1,229 @@
use roc_collections::VecMap;
use roc_module::ident::ModuleName;
use roc_module::symbol::{IdentId, IdentIds, ModuleId, ModuleIds, Symbol};
use roc_problem::can::ScopeModuleSource;
use roc_region::all::Region;
use roc_types::subs::Variable;
use roc_types::types::{Alias, EarlyReturnKind};
use bitvec::vec::BitVec;
#[derive(Clone, Debug)]
pub struct SoloScope {
/// The type aliases currently in scope
pub aliases: VecMap<Symbol, Alias>,
#[allow(dead_code)]
/// The current module being processed. This will be used to turn
/// unqualified idents into Symbols.
solo_home: ModuleId,
/// Modules that are imported
pub modules: ScopeModules,
/// Identifiers that are in scope, and defined in the current module
pub locals: ScopedIdentIds,
pub early_returns: Vec<(Variable, Region, EarlyReturnKind)>,
}
impl Default for SoloScope {
fn default() -> Self {
Self::new()
}
}
impl SoloScope {
pub fn new() -> Self {
let solo_home = ModuleId::first_after_builtins();
Self {
solo_home,
locals: ScopedIdentIds::from_ident_ids(solo_home),
aliases: VecMap::default(),
modules: ScopeModules::new(solo_home),
early_returns: Vec::default(),
}
}
/// Generates a unique new symbol and return the symbol's unqualified identifier name.
pub fn gen_unique_symbol_name(&mut self) -> &str {
let ident_id = self.locals.gen_unique();
self.locals.ident_ids.get_name(ident_id).unwrap()
}
}
#[derive(Clone, Debug)]
pub struct ScopedIdentIds {
pub ident_ids: IdentIds,
in_scope: BitVec,
regions: Vec<Region>,
#[allow(dead_code)]
solo_home: ModuleId,
}
impl ScopedIdentIds {
fn from_ident_ids(solo_home: ModuleId) -> Self {
Self {
in_scope: BitVec::repeat(false, 0),
ident_ids: IdentIds::default(),
regions: vec![Region::zero(); 0],
solo_home,
}
}
fn gen_unique(&mut self) -> IdentId {
let id = self.ident_ids.gen_unique();
debug_assert_eq!(id.index(), self.in_scope.len());
debug_assert_eq!(id.index(), self.regions.len());
self.in_scope.push(false);
self.regions.push(Region::zero());
id
}
}
#[derive(Debug, Clone)]
pub struct ScopeModules {
/// The ids of all modules in scope
ids: Vec<ModuleId>,
/// The alias or original name of each module in scope
names: Vec<ModuleName>,
/// Why is this module in scope?
sources: Vec<ScopeModuleSource>,
/// The params of a module if any
params: Vec<Option<(Variable, Symbol)>>,
}
impl ScopeModules {
pub fn new(home_id: ModuleId) -> Self {
let builtins = ModuleIds::default();
let builtins_iter = builtins.iter();
let count = builtins_iter.len();
let mut ids = Vec::with_capacity(count + 1);
let mut names = Vec::with_capacity(count + 1);
let mut sources = vec![ScopeModuleSource::Builtin; count];
let mut params = vec![None; count];
for (module_id, module_name) in builtins_iter {
ids.push(module_id);
names.push(module_name.clone());
}
if !home_id.is_builtin() {
ids.push(home_id);
names.push("".into());
sources.push(ScopeModuleSource::Current);
params.push(None);
}
Self {
ids,
names,
sources,
params,
}
}
pub fn lookup(&self, module_name: &ModuleName) -> Option<ModuleLookup> {
self.names
.iter()
.position(|name| name == module_name)
.map(|index| ModuleLookup {
id: self.ids[index],
params: self.params[index],
})
}
pub fn lookup_by_id(&self, module_id: &ModuleId) -> Option<ModuleLookup> {
self.ids
.iter()
.position(|id| id == module_id)
.map(|index| ModuleLookup {
id: self.ids[index],
params: self.params[index],
})
}
pub fn available_names(&self) -> impl Iterator<Item = &ModuleName> {
self.names.iter()
}
pub fn insert(
&mut self,
module_name: ModuleName,
module_id: ModuleId,
params: Option<(Variable, Symbol)>,
region: Region,
) -> Result<(), ScopeModuleSource> {
if let Some(index) = self.names.iter().position(|name| name == &module_name) {
if self.ids[index] == module_id {
return Ok(());
}
return Err(self.sources[index]);
}
self.ids.push(module_id);
self.names.push(module_name);
self.sources.push(ScopeModuleSource::Import(region));
self.params.push(params);
Ok(())
}
pub fn len(&self) -> usize {
debug_assert_eq!(self.ids.len(), self.names.len());
debug_assert_eq!(self.ids.len(), self.sources.len());
debug_assert_eq!(self.ids.len(), self.params.len());
self.ids.len()
}
pub fn is_empty(&self) -> bool {
self.ids.is_empty()
}
pub fn truncate(&mut self, len: usize) {
self.ids.truncate(len);
self.names.truncate(len);
self.sources.truncate(len);
self.params.truncate(len);
}
}
#[derive(Debug, Clone, Copy)]
pub struct SymbolLookup {
pub symbol: Symbol,
pub module_params: Option<(Variable, Symbol)>,
}
impl SymbolLookup {
pub fn new(symbol: Symbol, params: Option<(Variable, Symbol)>) -> Self {
Self {
symbol,
module_params: params,
}
}
pub fn no_params(symbol: Symbol) -> Self {
Self::new(symbol, None)
}
}
pub struct ModuleLookup {
pub id: ModuleId,
pub params: Option<(Variable, Symbol)>,
}
impl ModuleLookup {
pub fn into_symbol(&self, symbol: Symbol) -> SymbolLookup {
debug_assert_eq!(symbol.module_id(), self.id);
SymbolLookup {
symbol,
module_params: self.params,
}
}
}

View file

@ -90,12 +90,12 @@ astar = \cost_fn, move_fn, goal, model ->
new_neighbors = new_neighbors =
Set.difference(neighbors, model_popped.evaluated) Set.difference(neighbors, model_popped.evaluated)
model_with_neighbors : Model position model_with_neighbors : Model _
model_with_neighbors = model_with_neighbors =
model_popped model_popped
|> &open_set(Set.union(model_popped.open_set, new_neighbors)) |> &open_set(Set.union(model_popped.open_set, new_neighbors))
walker : Model position, position -> Model position walker : Model _, _ -> Model _
walker = \amodel, n -> update_cost(current, n, amodel) walker = \amodel, n -> update_cost(current, n, amodel)
model_with_costs = model_with_costs =

View file

@ -148,19 +148,19 @@ is_valid_char = \c ->
is_alpha_num : U8 -> Bool is_alpha_num : U8 -> Bool
is_alpha_num = \key -> is_alpha_num = \key ->
(key >= 48 && key <= 57) || (key >= 64 && key <= 90) || (key >= 97 && key <= 122) (key >= 48 and key <= 57) or (key >= 64 and key <= 90) or (key >= 97 and key <= 122)
# Convert a base64 character/digit to its index # Convert a base64 character/digit to its index
# See also [Wikipedia](https://en.wikipedia.org/wiki/Base64#Base64_table) # See also [Wikipedia](https://en.wikipedia.org/wiki/Base64#Base64_table)
unsafe_convert_char : U8 -> U8 unsafe_convert_char : U8 -> U8
unsafe_convert_char = \key -> unsafe_convert_char = \key ->
if key >= 65 && key <= 90 then if key >= 65 and key <= 90 then
# A-Z # A-Z
key - 65 key - 65
else if key >= 97 && key <= 122 then else if key >= 97 and key <= 122 then
# a-z # a-z
(key - 97) + 26 (key - 97) + 26
else if key >= 48 && key <= 57 then else if key >= 48 and key <= 57 then
# 0-9 # 0-9
(key - 48) + 26 + 26 (key - 48) + 26 + 26
else else

View file

@ -50,7 +50,7 @@ safe = \queen, diagonal, xs ->
when xs is when xs is
Nil -> Bool.true Nil -> Bool.true
Cons(q, t) -> Cons(q, t) ->
if queen != q && queen != q + diagonal && queen != q - diagonal then if queen != q and queen != q + diagonal and queen != q - diagonal then
safe(queen, (diagonal + 1), t) safe(queen, (diagonal + 1), t)
else else
Bool.false Bool.false

View file

@ -19,10 +19,8 @@ to_str = \@Variable(char) ->
from_utf8 : U8 -> Result Variable [InvalidVariableUtf8] from_utf8 : U8 -> Result Variable [InvalidVariableUtf8]
from_utf8 = \char -> from_utf8 = \char ->
if if
char char >= 0x61 # "a"
>= 0x61 # "a" and char <= 0x7A # "z"
&& char
<= 0x7A # "z"
then then
Ok(@Variable(char)) Ok(@Variable(char))
else else

View file

@ -457,21 +457,15 @@ pop_variable = \ctx ->
is_digit : U8 -> Bool is_digit : U8 -> Bool
is_digit = \char -> is_digit = \char ->
char char >= 0x30 # `0`
>= 0x30 # `0` and char <= 0x39 # `0`
&& char
<= 0x39 # `0`
is_whitespace : U8 -> Bool is_whitespace : U8 -> Bool
is_whitespace = \char -> is_whitespace = \char ->
char char == 0xA # new line
== 0xA # new line or char == 0xD # carriage return
|| char or char == 0x20 # space
== 0xD # carriage return or char == 0x9 # tab
|| char
== 0x20 # space
|| char
== 0x9 # tab
end_unexpected = \err -> end_unexpected = \err ->
when err is when err is

View file

@ -212,6 +212,7 @@ comptime {
exportStrFn(str.withCapacityC, "with_capacity"); exportStrFn(str.withCapacityC, "with_capacity");
exportStrFn(str.strAllocationPtr, "allocation_ptr"); exportStrFn(str.strAllocationPtr, "allocation_ptr");
exportStrFn(str.strReleaseExcessCapacity, "release_excess_capacity"); exportStrFn(str.strReleaseExcessCapacity, "release_excess_capacity");
exportStrFn(str.strWithAsciiLowercased, "with_ascii_lowercased");
for (INTEGERS) |T| { for (INTEGERS) |T| {
str.exportFromInt(T, ROC_BUILTINS ++ "." ++ STR ++ ".from_int."); str.exportFromInt(T, ROC_BUILTINS ++ "." ++ STR ++ ".from_int.");

View file

@ -2,6 +2,7 @@ const utils = @import("utils.zig");
const RocList = @import("list.zig").RocList; const RocList = @import("list.zig").RocList;
const UpdateMode = utils.UpdateMode; const UpdateMode = utils.UpdateMode;
const std = @import("std"); const std = @import("std");
const ascii = std.ascii;
const mem = std.mem; const mem = std.mem;
const unicode = std.unicode; const unicode = std.unicode;
const testing = std.testing; const testing = std.testing;
@ -370,11 +371,17 @@ pub const RocStr = extern struct {
} }
fn refcount(self: RocStr) usize { fn refcount(self: RocStr) usize {
if ((self.getCapacity() == 0 and !self.isSeamlessSlice()) or self.isSmallStr()) { const is_seamless_slice = self.isSeamlessSlice();
if ((self.getCapacity() == 0 and !is_seamless_slice) or self.isSmallStr()) {
return 1; return 1;
} }
const ptr: [*]usize = @as([*]usize, @ptrCast(@alignCast(self.bytes))); const data_ptr = if (is_seamless_slice)
self.getAllocationPtr()
else
self.bytes;
const ptr: [*]usize = @as([*]usize, @ptrCast(@alignCast(data_ptr)));
return (ptr - 1)[0]; return (ptr - 1)[0];
} }
@ -611,16 +618,6 @@ fn initFromSmallStr(slice_bytes: [*]u8, len: usize, _: usize) RocStr {
return RocStr.init(slice_bytes, len); return RocStr.init(slice_bytes, len);
} }
// The alloc_ptr must already be shifted to be ready for storing in a seamless slice.
fn initFromBigStr(slice_bytes: [*]u8, len: usize, alloc_ptr: usize) RocStr {
// Here we can make seamless slices instead of copying to a new small str.
return RocStr{
.bytes = slice_bytes,
.length = len | SEAMLESS_SLICE_BIT,
.capacity_or_alloc_ptr = alloc_ptr,
};
}
fn strSplitOnHelp(array: [*]RocStr, string: RocStr, delimiter: RocStr) void { fn strSplitOnHelp(array: [*]RocStr, string: RocStr, delimiter: RocStr) void {
if (delimiter.len() == 0) { if (delimiter.len() == 0) {
string.incref(1); string.incref(1);
@ -2138,6 +2135,66 @@ fn countTrailingWhitespaceBytes(string: RocStr) usize {
return byte_count; return byte_count;
} }
// Str.with_ascii_lowercased
pub fn strWithAsciiLowercased(string: RocStr) callconv(.C) RocStr {
var new_str = if (string.isUnique())
string
else blk: {
string.decref();
break :blk RocStr.fromSlice(string.asSlice());
};
const new_str_bytes = new_str.asU8ptrMut()[0..string.len()];
for (new_str_bytes) |*c| {
c.* = ascii.toLower(c.*);
}
return new_str;
}
test "withAsciiLowercased: small str" {
const original = RocStr.fromSlice("cOFFÉ");
try expect(original.isSmallStr());
const expected = RocStr.fromSlice("coffÉ");
defer expected.decref();
const str_result = strWithAsciiLowercased(original);
defer str_result.decref();
try expect(str_result.isSmallStr());
try expect(str_result.eq(expected));
}
test "withAsciiLowercased: non small str" {
const original = RocStr.fromSlice("cOFFÉ cOFFÉ cOFFÉ cOFFÉ cOFFÉ cOFFÉ");
defer original.decref();
try expect(!original.isSmallStr());
const expected = RocStr.fromSlice("coffÉ coffÉ coffÉ coffÉ coffÉ coffÉ");
defer expected.decref();
const str_result = strWithAsciiLowercased(original);
try expect(!str_result.isSmallStr());
try expect(str_result.eq(expected));
}
test "withAsciiLowercased: seamless slice" {
const l = RocStr.fromSlice("cOFFÉ cOFFÉ cOFFÉ cOFFÉ cOFFÉ cOFFÉ");
const original = substringUnsafeC(l, 1, l.len() - 1);
defer original.decref();
try expect(original.isSeamlessSlice());
const expected = RocStr.fromSlice("offÉ coffÉ coffÉ coffÉ coffÉ coffÉ");
defer expected.decref();
const str_result = strWithAsciiLowercased(original);
try expect(!str_result.isSmallStr());
try expect(str_result.eq(expected));
}
fn rcNone(_: ?[*]u8) callconv(.C) void {} fn rcNone(_: ?[*]u8) callconv(.C) void {}
fn decStr(ptr: ?[*]u8) callconv(.C) void { fn decStr(ptr: ?[*]u8) callconv(.C) void {

View file

@ -1,4 +1,4 @@
module [Bool, Eq, true, false, and, or, not, is_eq, is_not_eq] module [Bool, Eq, true, false, not, is_eq, is_not_eq]
## Defines a type that can be compared for total equality. ## Defines a type that can be compared for total equality.
## ##
@ -44,55 +44,6 @@ true = @Bool(True)
false : Bool false : Bool
false = @Bool(False) false = @Bool(False)
## Returns `Bool.true` when both inputs are `Bool.true`. This is equivalent to
## the logic [AND](https://en.wikipedia.org/wiki/Logical_conjunction)
## gate. The infix operator `&&` can also be used as shorthand for
## `Bool.and`.
##
## ```roc
## expect Bool.and(Bool.true, Bool.true) == Bool.true
## expect (Bool.true && Bool.true) == Bool.true
## expect (Bool.false && Bool.true) == Bool.false
## expect (Bool.true && Bool.false) == Bool.false
## expect (Bool.false && Bool.false) == Bool.false
## ```
##
## ## Performance Details
##
## In Roc the `&&` and `||` work the same way as any
## other function. However, in some languages `&&` and `||` are special-cased.
## In these languages the compiler will skip evaluating the expression after the
## first operator under certain circumstances. For example an expression like
## `enable_pets && likes_dogs(user)` would compile to.
## ```roc
## if enable_pets then
## likes_dogs(user)
## else
## Bool.false
## ```
## Roc does not do this because conditionals like `if` and `when` have a
## performance cost. Calling a function can sometimes be faster across the board
## than doing an `if` to decide whether to skip calling it.
and : Bool, Bool -> Bool
## Returns `Bool.true` when either input is a `Bool.true`. This is equivalent to
## the logic [OR](https://en.wikipedia.org/wiki/Logical_disjunction) gate.
## The infix operator `||` can also be used as shorthand for `Bool.or`.
## ```roc
## expect Bool.or(Bool.false, Bool.true) == Bool.true
## expect (Bool.true || Bool.true) == Bool.true
## expect (Bool.false || Bool.true) == Bool.true
## expect (Bool.true || Bool.false) == Bool.true
## expect (Bool.false || Bool.false) == Bool.false
## ```
##
## ## Performance Details
##
## In Roc the `&&` and `||` work the same way as any
## other functions. However, in some languages `&&` and `||` are special-cased.
## Refer to the note in `Bool.and` for more detail.
or : Bool, Bool -> Bool
## Returns `Bool.false` when given `Bool.true`, and vice versa. This is ## Returns `Bool.false` when given `Bool.true`, and vice versa. This is
## equivalent to the logic [NOT](https://en.wikipedia.org/wiki/Negation) ## equivalent to the logic [NOT](https://en.wikipedia.org/wiki/Negation)
## gate. The operator `!` can also be used as shorthand for `Bool.not`. ## gate. The operator `!` can also be used as shorthand for `Bool.not`.

View file

@ -170,7 +170,7 @@ reserve = |@Dict({ buckets, data, max_bucket_capacity: original_max_bucket_capac
size = Num.min(requested_size, max_size) size = Num.min(requested_size, max_size)
requested_shifts = calc_shifts_for_size(size, max_load_factor) requested_shifts = calc_shifts_for_size(size, max_load_factor)
if List.is_empty(buckets) || requested_shifts > shifts then if List.is_empty(buckets) or requested_shifts > shifts then
(buckets0, max_bucket_capacity) = alloc_buckets_from_shift(requested_shifts, max_load_factor) (buckets0, max_bucket_capacity) = alloc_buckets_from_shift(requested_shifts, max_load_factor)
buckets1 = fill_buckets_from_data(buckets0, data, requested_shifts) buckets1 = fill_buckets_from_data(buckets0, data, requested_shifts)
@Dict( @Dict(
@ -915,7 +915,7 @@ calc_shifts_for_size_helper = |shifts, size, max_load_factor|
|> Num.to_f32 |> Num.to_f32
|> Num.mul(max_load_factor) |> Num.mul(max_load_factor)
|> Num.floor |> Num.floor
if shifts > 0 && max_bucket_capacity < size then if shifts > 0 and max_bucket_capacity < size then
calc_shifts_for_size_helper(Num.sub_wrap(shifts, 1), size, max_load_factor) calc_shifts_for_size_helper(Num.sub_wrap(shifts, 1), size, max_load_factor)
else else
shifts shifts
@ -1087,7 +1087,7 @@ expect
|> insert("bar", {}) |> insert("bar", {})
|> insert("baz", {}) |> insert("baz", {})
contains(dict, "baz") && !(contains(dict, "other")) contains(dict, "baz") and !(contains(dict, "other"))
expect expect
dict = dict =
@ -1145,17 +1145,17 @@ expect
|> insert("l", 11) |> insert("l", 11)
(get(dict, "a") == Ok(0)) (get(dict, "a") == Ok(0))
&& (get(dict, "b") == Ok(1)) and (get(dict, "b") == Ok(1))
&& (get(dict, "c") == Ok(2)) and (get(dict, "c") == Ok(2))
&& (get(dict, "d") == Ok(3)) and (get(dict, "d") == Ok(3))
&& (get(dict, "e") == Ok(4)) and (get(dict, "e") == Ok(4))
&& (get(dict, "f") == Ok(5)) and (get(dict, "f") == Ok(5))
&& (get(dict, "g") == Ok(6)) and (get(dict, "g") == Ok(6))
&& (get(dict, "h") == Ok(7)) and (get(dict, "h") == Ok(7))
&& (get(dict, "i") == Ok(8)) and (get(dict, "i") == Ok(8))
&& (get(dict, "j") == Ok(9)) and (get(dict, "j") == Ok(9))
&& (get(dict, "k") == Ok(10)) and (get(dict, "k") == Ok(10))
&& (get(dict, "l") == Ok(11)) and (get(dict, "l") == Ok(11))
# Force rehash. # Force rehash.
expect expect
@ -1197,18 +1197,18 @@ expect
|> insert("m", 12) |> insert("m", 12)
(get(dict, "a") == Ok(0)) (get(dict, "a") == Ok(0))
&& (get(dict, "b") == Ok(1)) and (get(dict, "b") == Ok(1))
&& (get(dict, "c") == Ok(2)) and (get(dict, "c") == Ok(2))
&& (get(dict, "d") == Ok(3)) and (get(dict, "d") == Ok(3))
&& (get(dict, "e") == Ok(4)) and (get(dict, "e") == Ok(4))
&& (get(dict, "f") == Ok(5)) and (get(dict, "f") == Ok(5))
&& (get(dict, "g") == Ok(6)) and (get(dict, "g") == Ok(6))
&& (get(dict, "h") == Ok(7)) and (get(dict, "h") == Ok(7))
&& (get(dict, "i") == Ok(8)) and (get(dict, "i") == Ok(8))
&& (get(dict, "j") == Ok(9)) and (get(dict, "j") == Ok(9))
&& (get(dict, "k") == Ok(10)) and (get(dict, "k") == Ok(10))
&& (get(dict, "l") == Ok(11)) and (get(dict, "l") == Ok(11))
&& (get(dict, "m") == Ok(12)) and (get(dict, "m") == Ok(12))
expect expect
empty({}) empty({})
@ -1266,7 +1266,7 @@ expect
bad_keys, bad_keys,
Bool.true, Bool.true,
|acc, k| |acc, k|
acc && Dict.contains(dict, k), acc and Dict.contains(dict, k),
) )
all_inserted_correctly all_inserted_correctly

View file

@ -1361,7 +1361,7 @@ split_last = |list, delimiter|
## result is an empty list. ## result is an empty list.
chunks_of : List a, U64 -> List (List a) chunks_of : List a, U64 -> List (List a)
chunks_of = |list, chunk_size| chunks_of = |list, chunk_size|
if chunk_size == 0 || List.is_empty(list) then if chunk_size == 0 or List.is_empty(list) then
[] []
else else
chunk_capacity = Num.div_ceil(List.len(list), chunk_size) chunk_capacity = Num.div_ceil(List.len(list), chunk_size)

View file

@ -532,7 +532,7 @@ pi = 3.14159265358979323846264338327950288419716939937510
## Circle constant (τ) ## Circle constant (τ)
tau : Frac * tau : Frac *
tau = 2 * pi tau = 6.2831853071795864769252867665590057683943387987502
# ------- Functions # ------- Functions
## Convert a number to a [Str]. ## Convert a number to a [Str].
@ -619,9 +619,9 @@ is_gte : Num a, Num a -> Bool
## is [defined to be unordered](https://en.wikipedia.org/wiki/NaN#Comparison_with_NaN).) ## is [defined to be unordered](https://en.wikipedia.org/wiki/NaN#Comparison_with_NaN).)
is_approx_eq : Frac a, Frac a, { rtol ?? Frac a, atol ?? Frac a } -> Bool is_approx_eq : Frac a, Frac a, { rtol ?? Frac a, atol ?? Frac a } -> Bool
is_approx_eq = |x, y, { rtol ?? 0.00001, atol ?? 0.00000001 }| is_approx_eq = |x, y, { rtol ?? 0.00001, atol ?? 0.00000001 }|
eq = x <= y && x >= y eq = x <= y and x >= y
meets_tolerance = Num.abs_diff(x, y) <= Num.max(atol, (rtol * Num.max(Num.abs(x), Num.abs(y)))) meets_tolerance = Num.abs_diff(x, y) <= Num.max(atol, (rtol * Num.max(Num.abs(x), Num.abs(y))))
eq || meets_tolerance eq or meets_tolerance
## Returns `Bool.true` if the number is `0`, and `Bool.false` otherwise. ## Returns `Bool.true` if the number is `0`, and `Bool.false` otherwise.
is_zero : Num a -> Bool is_zero : Num a -> Bool

View file

@ -373,6 +373,7 @@ module [
contains, contains,
drop_prefix, drop_prefix,
drop_suffix, drop_suffix,
with_ascii_lowercased,
] ]
import Bool exposing [Bool] import Bool exposing [Bool]
@ -1205,7 +1206,7 @@ matches_at_help = |state|
}, },
) )
does_this_match && does_rest_match does_this_match and does_rest_match
## Walks over the `UTF-8` bytes of the given [Str] and calls a function to update ## Walks over the `UTF-8` bytes of the given [Str] and calls a function to update
## state for each byte. The index for that byte in the string is provided ## state for each byte. The index for that byte in the string is provided
@ -1325,3 +1326,29 @@ drop_suffix = |haystack, suffix|
substring_unsafe(haystack, start, len) substring_unsafe(haystack, start, len)
else else
haystack haystack
## Returns a version of the string with all [ASCII characters](https://en.wikipedia.org/wiki/ASCII) lowercased.
## Non-ASCII characters are left unmodified. For example:
##
## ```roc
## expect "CAFÉ".with_ascii_lowercased() == "cafÉ"
## ```
##
## This function is useful for things like [command-line options](https://en.wikipedia.org/wiki/Command-line_interface#Command-line_option)
## and [environment variables](https://en.wikipedia.org/wiki/Environment_variable)
## know in advance that you're dealing with a hardcoded string containing only ASCII characters.
## It has better performance than lowercasing operations which take Unicode into account.
##
## That said, strings received from user input can always contain
## non-ASCII Unicode characters, and lowercasing [Unicode](https://unicode.org) works
## differently in different languages. For example, the string `"I"` lowercases to `"i"`
## in English and to `"ı"` (a [dotless i](https://en.wikipedia.org/wiki/Dotless_I))
## in Turkish. These rules can also change in each [Unicode release](https://www.unicode.org/releases/),
## so we have separate [`unicode` package](https://github.com/roc-lang/unicode)
## for Unicode capitalization that can be upgraded independently from the language's builtins.
##
## To do a case-insensitive comparison of the ASCII characters in a string,
## use [`caseless_ascii_equals`](#caseless_ascii_equals).
with_ascii_lowercased : Str -> Str
expect Str.with_ascii_lowercased("cOFFÉ") == "coffÉ"

View file

@ -359,6 +359,7 @@ pub const STR_CLONE_TO: &str = "roc_builtins.str.clone_to";
pub const STR_WITH_CAPACITY: &str = "roc_builtins.str.with_capacity"; pub const STR_WITH_CAPACITY: &str = "roc_builtins.str.with_capacity";
pub const STR_ALLOCATION_PTR: &str = "roc_builtins.str.allocation_ptr"; pub const STR_ALLOCATION_PTR: &str = "roc_builtins.str.allocation_ptr";
pub const STR_RELEASE_EXCESS_CAPACITY: &str = "roc_builtins.str.release_excess_capacity"; pub const STR_RELEASE_EXCESS_CAPACITY: &str = "roc_builtins.str.release_excess_capacity";
pub const STR_WITH_ASCII_LOWERCASED: &str = "roc_builtins.str.with_ascii_lowercased";
pub const LIST_MAP: &str = "roc_builtins.list.map"; pub const LIST_MAP: &str = "roc_builtins.list.map";
pub const LIST_MAP2: &str = "roc_builtins.list.map2"; pub const LIST_MAP2: &str = "roc_builtins.list.map2";

View file

@ -8,6 +8,7 @@ license.workspace = true
version.workspace = true version.workspace = true
[dependencies] [dependencies]
roc_can_solo.workspace = true
roc_collections.workspace = true roc_collections.workspace = true
roc_error_macros.workspace = true roc_error_macros.workspace = true
roc_exhaustive.workspace = true roc_exhaustive.workspace = true

View file

@ -131,6 +131,7 @@ map_symbol_to_lowlevel_and_arity! {
StrToNum; STR_TO_NUM; 1, StrToNum; STR_TO_NUM; 1,
StrWithCapacity; STR_WITH_CAPACITY; 1, StrWithCapacity; STR_WITH_CAPACITY; 1,
StrReleaseExcessCapacity; STR_RELEASE_EXCESS_CAPACITY; 1, StrReleaseExcessCapacity; STR_RELEASE_EXCESS_CAPACITY; 1,
StrWithAsciiLowercased; STR_WITH_ASCII_LOWERCASED; 1,
ListLenUsize; LIST_LEN_USIZE; 1, ListLenUsize; LIST_LEN_USIZE; 1,
ListLenU64; LIST_LEN_U64; 1, ListLenU64; LIST_LEN_U64; 1,
@ -213,8 +214,6 @@ map_symbol_to_lowlevel_and_arity! {
Eq; BOOL_STRUCTURAL_EQ; 2, Eq; BOOL_STRUCTURAL_EQ; 2,
NotEq; BOOL_STRUCTURAL_NOT_EQ; 2, NotEq; BOOL_STRUCTURAL_NOT_EQ; 2,
And; BOOL_AND; 2,
Or; BOOL_OR; 2,
Not; BOOL_NOT; 1, Not; BOOL_NOT; 1,
BoxExpr; BOX_BOX_FUNCTION; 1, BoxExpr; BOX_BOX_FUNCTION; 1,
UnboxExpr; BOX_UNBOX; 1, UnboxExpr; BOX_UNBOX; 1,

View file

@ -915,7 +915,7 @@ pub struct DefTypes {
pub loc_symbols: Slice<(Symbol, Region)>, pub loc_symbols: Slice<(Symbol, Region)>,
} }
#[derive(Debug, Clone, Copy)] #[derive(Debug, Clone, Copy, PartialEq)]
pub struct Generalizable(pub bool); pub struct Generalizable(pub bool);
#[derive(Debug, Clone)] #[derive(Debug, Clone)]

File diff suppressed because it is too large Load diff

View file

@ -11,6 +11,7 @@ use roc_region::all::{LineInfo, Loc, Region};
use roc_types::subs::Variable; use roc_types::subs::Variable;
/// The canonicalization environment for a particular module. /// The canonicalization environment for a particular module.
#[derive(Debug)]
pub struct Env<'a> { pub struct Env<'a> {
/// The module's path. Opaques and unqualified references to identifiers /// The module's path. Opaques and unqualified references to identifiers
/// are assumed to be relative to this path. /// are assumed to be relative to this path.
@ -51,6 +52,36 @@ pub struct Env<'a> {
} }
impl<'a> Env<'a> { impl<'a> Env<'a> {
#[allow(clippy::too_many_arguments)]
pub fn from_solo_can(
arena: &'a Bump,
module_path: &'a Path,
home: ModuleId,
dep_idents: &'a IdentIdsByModule,
qualified_module_ids: &'a PackageModuleIds<'a>,
problems: Vec<Problem>,
opt_shorthand: Option<&'a str>,
src: &'a str,
line_info: &'a mut Option<LineInfo>,
) -> Self {
Env {
arena,
src,
home,
module_path,
dep_idents,
qualified_module_ids,
problems,
closures: MutMap::default(),
qualified_value_lookups: Default::default(),
tailcallable_symbol: None,
top_level_symbols: Default::default(),
home_params_record: None,
opt_shorthand,
line_info,
}
}
#[allow(clippy::too_many_arguments)] #[allow(clippy::too_many_arguments)]
pub fn new( pub fn new(
arena: &'a Bump, arena: &'a Bump,

View file

@ -1,9 +1,6 @@
use std::path::Path;
use crate::abilities::{AbilitiesStore, ImplKey, PendingAbilitiesStore, ResolvedImpl}; use crate::abilities::{AbilitiesStore, ImplKey, PendingAbilitiesStore, ResolvedImpl};
use crate::annotation::{canonicalize_annotation, AnnotationFor}; use crate::annotation::{canonicalize_annotation, AnnotationFor};
use crate::def::{canonicalize_defs, report_unused_imports, Def, DefKind}; use crate::def::{canonicalize_defs, report_unused_imports, Def, DefKind};
use crate::desugar::desugar_record_destructures;
use crate::env::Env; use crate::env::Env;
use crate::expr::{ClosureData, Declarations, ExpectLookup, Expr, Output, PendingDerives}; use crate::expr::{ClosureData, Declarations, ExpectLookup, Expr, Output, PendingDerives};
use crate::pattern::{ use crate::pattern::{
@ -16,8 +13,8 @@ use roc_collections::{MutMap, SendMap, VecMap, VecSet};
use roc_error_macros::internal_error; use roc_error_macros::internal_error;
use roc_module::ident::Ident; use roc_module::ident::Ident;
use roc_module::ident::Lowercase; use roc_module::ident::Lowercase;
use roc_module::symbol::{IdentId, IdentIds, IdentIdsByModule, ModuleId, PackageModuleIds, Symbol}; use roc_module::symbol::{IdentId, ModuleId, Symbol};
use roc_parse::ast::{Defs, TypeAnnotation}; use roc_parse::ast::{Collection, Defs, Pattern as ParsePattern, TypeAnnotation};
use roc_parse::header::HeaderType; use roc_parse::header::HeaderType;
use roc_parse::pattern::PatternType; use roc_parse::pattern::PatternType;
use roc_problem::can::{Problem, RuntimeError}; use roc_problem::can::{Problem, RuntimeError};
@ -209,55 +206,19 @@ fn has_no_implementation(expr: &Expr) -> bool {
#[allow(clippy::too_many_arguments)] #[allow(clippy::too_many_arguments)]
pub fn canonicalize_module_defs<'a>( pub fn canonicalize_module_defs<'a>(
arena: &'a Bump, arena: &'a Bump,
loc_defs: &'a mut Defs<'a>,
header_type: &'a roc_parse::header::HeaderType, header_type: &'a roc_parse::header::HeaderType,
home: ModuleId, home: ModuleId,
module_path: &'a str,
src: &'a str,
qualified_module_ids: &'a PackageModuleIds<'a>,
exposed_ident_ids: IdentIds,
dep_idents: &'a IdentIdsByModule,
aliases: MutMap<Symbol, Alias>,
imported_abilities_state: PendingAbilitiesStore,
initial_scope: MutMap<Ident, (Symbol, Region)>, initial_scope: MutMap<Ident, (Symbol, Region)>,
exposed_symbols: VecSet<Symbol>, exposed_symbols: VecSet<Symbol>,
symbols_from_requires: &[(Loc<Symbol>, Loc<TypeAnnotation<'a>>)], symbols_from_requires: &[(Loc<Symbol>, Loc<TypeAnnotation<'a>>)],
var_store: &mut VarStore, var_store: &mut VarStore,
opt_shorthand: Option<&'a str>, mut scope: Scope,
mut env: Env<'a>,
loc_defs: Defs<'a>,
module_params: Option<(Region, Collection<'a, Loc<ParsePattern<'a>>>)>,
) -> ModuleOutput { ) -> ModuleOutput {
let mut can_exposed_imports = MutMap::default(); let mut can_exposed_imports = MutMap::default();
let mut scope = Scope::new(
home,
qualified_module_ids
.get_name(home)
.expect("home module not found")
.as_inner()
.to_owned(),
exposed_ident_ids,
imported_abilities_state,
);
let mut env = Env::new(
arena,
src,
home,
arena.alloc(Path::new(module_path)),
dep_idents,
qualified_module_ids,
opt_shorthand,
);
for (name, alias) in aliases.into_iter() {
scope.add_alias(
name,
alias.region,
alias.type_variables,
alias.infer_ext_in_output_variables,
alias.typ,
alias.kind,
);
}
// Desugar operators (convert them to Apply calls, taking into account // Desugar operators (convert them to Apply calls, taking into account
// operator precedence and associativity rules), before doing other canonicalization. // operator precedence and associativity rules), before doing other canonicalization.
// //
@ -266,8 +227,6 @@ pub fn canonicalize_module_defs<'a>(
// operators, and then again on *their* nested operators, ultimately applying the // operators, and then again on *their* nested operators, ultimately applying the
// rules multiple times unnecessarily. // rules multiple times unnecessarily.
crate::desugar::desugar_defs_node_values(&mut env, &mut scope, loc_defs);
let mut rigid_variables = RigidVariables::default(); let mut rigid_variables = RigidVariables::default();
// Initial scope values are treated like defs that appear before any others. // Initial scope values are treated like defs that appear before any others.
@ -319,15 +278,7 @@ pub fn canonicalize_module_defs<'a>(
let mut output = Output::default(); let mut output = Output::default();
let module_params = header_type.get_params().as_ref().map( let module_params = module_params.map(|(params_region, desugared_patterns)| {
|roc_parse::header::ModuleParams {
pattern,
before_arrow: _,
after_arrow: _,
}| {
let desugared_patterns =
desugar_record_destructures(&mut env, &mut scope, pattern.value);
let (destructs, _) = canonicalize_record_destructs( let (destructs, _) = canonicalize_record_destructs(
&mut env, &mut env,
var_store, var_store,
@ -335,7 +286,7 @@ pub fn canonicalize_module_defs<'a>(
&mut output, &mut output,
PatternType::ModuleParams, PatternType::ModuleParams,
&desugared_patterns, &desugared_patterns,
pattern.region, params_region,
PermitShadows(false), PermitShadows(false),
); );
@ -347,7 +298,7 @@ pub fn canonicalize_module_defs<'a>(
env.home_params_record = Some((whole_symbol, whole_var)); env.home_params_record = Some((whole_symbol, whole_var));
ModuleParams { ModuleParams {
region: pattern.region, region: params_region,
whole_var, whole_var,
whole_symbol, whole_symbol,
record_var: var_store.fresh(), record_var: var_store.fresh(),
@ -355,15 +306,14 @@ pub fn canonicalize_module_defs<'a>(
destructs, destructs,
arity_by_name: Default::default(), arity_by_name: Default::default(),
} }
}, });
);
let (defs, output, symbols_introduced, imports_introduced) = canonicalize_defs( let (defs, output, symbols_introduced, imports_introduced) = canonicalize_defs(
&mut env, &mut env,
output, output,
var_store, var_store,
&mut scope, &mut scope,
loc_defs, arena.alloc(loc_defs),
PatternType::TopLevelDef, PatternType::TopLevelDef,
); );

View file

@ -1,10 +1,11 @@
extern crate bumpalo; extern crate bumpalo;
use self::bumpalo::Bump; use self::bumpalo::Bump;
use roc_can::desugar;
use roc_can::env::Env; use roc_can::env::Env;
use roc_can::expr::{canonicalize_expr, Expr}; use roc_can::expr::{canonicalize_expr, Expr};
use roc_can::scope::Scope; use roc_can::scope::Scope;
use roc_can_solo::env::SoloEnv;
use roc_can_solo::scope::SoloScope;
use roc_collections::all::MutMap; use roc_collections::all::MutMap;
use roc_module::symbol::{IdentIds, Interns, ModuleId, ModuleIds, PackageModuleIds, Symbol}; use roc_module::symbol::{IdentIds, Interns, ModuleId, ModuleIds, PackageModuleIds, Symbol};
use roc_problem::can::Problem; use roc_problem::can::Problem;
@ -65,7 +66,9 @@ pub fn can_expr_with(arena: &Bump, home: ModuleId, expr_str: &str) -> CanExprOut
// visited a BinOp node we'd recursively try to apply this to each of its nested // visited a BinOp node we'd recursively try to apply this to each of its nested
// operators, and then again on *their* nested operators, ultimately applying the // operators, and then again on *their* nested operators, ultimately applying the
// rules multiple times unnecessarily. // rules multiple times unnecessarily.
let loc_expr = desugar::desugar_expr(&mut env, &mut scope, &loc_expr); let mut solo_env = SoloEnv::new(arena, expr_str, Path::new("Test.roc"));
let mut solo_scope = SoloScope::new();
let loc_expr = roc_can_solo::desugar::desugar_expr(&mut solo_env, &mut solo_scope, &loc_expr);
scope.add_alias( scope.add_alias(
Symbol::NUM_INT, Symbol::NUM_INT,

View file

@ -972,7 +972,59 @@ mod test_can {
} }
#[test] #[test]
fn try_desugar_double_question_binop() { fn try_desugar_works_elsewhere() {
let src = indoc!(
r#"
when Foo 123 is
Foo try -> try
"#
);
let arena = Bump::new();
let out = can_expr_with(&arena, test_home(), src);
assert_eq!(out.problems, Vec::new());
// Assert that we don't treat `try` as a keyword here
// by desugaring to:
//
// when Foo 123 is
// Foo try -> try
let (cond_expr, branches) = assert_when_expr(&out.loc_expr.value);
match cond_expr {
Expr::Tag {
name, arguments, ..
} => {
assert_eq!(name.0.to_string(), "Foo");
assert_eq!(arguments.len(), 1);
assert_num_value(&arguments[0].1.value, 123);
}
_ => panic!("cond_expr was not a Tag: {:?}", cond_expr),
}
assert_eq!(branches.len(), 1);
assert_eq!(branches[0].patterns.len(), 1);
assert!(!branches[0].patterns[0].degenerate);
match &branches[0].patterns[0].pattern.value {
Pattern::AppliedTag {
tag_name,
arguments,
..
} => {
assert_eq!(tag_name.0.to_string(), "Foo");
assert_eq!(arguments.len(), 1);
assert_pattern_name(&arguments[0].1.value, "try", &out.interns);
}
other => panic!("First argument was not an applied tag: {:?}", other),
}
assert_var_usage(&branches[0].value.value, "try", &out.interns);
assert!(&branches[0].guard.is_none());
}
#[test]
fn desugar_double_question_binop() {
let src = indoc!( let src = indoc!(
r#" r#"
Str.to_u64("123") ?? Num.max_u64 Str.to_u64("123") ?? Num.max_u64
@ -989,7 +1041,7 @@ mod test_can {
// Ok(#double_question_ok_0_17) -> Ok(#double_question_ok_0_17) // Ok(#double_question_ok_0_17) -> Ok(#double_question_ok_0_17)
// Err(_) -> Num.max_u64 // Err(_) -> Num.max_u64
let (cond_expr, branches) = assert_when(&out.loc_expr.value); let (cond_expr, branches) = assert_when_expr(&out.loc_expr.value);
let cond_args = assert_func_call(cond_expr, "to_u64", CalledVia::Space, &out.interns); let cond_args = assert_func_call(cond_expr, "to_u64", CalledVia::Space, &out.interns);
assert_eq!(cond_args.len(), 1); assert_eq!(cond_args.len(), 1);
@ -1016,7 +1068,7 @@ mod test_can {
} }
#[test] #[test]
fn try_desugar_single_question_binop() { fn desugar_single_question_binop() {
let src = indoc!( let src = indoc!(
r#" r#"
Str.to_u64("123") ? FailedToConvert Str.to_u64("123") ? FailedToConvert
@ -1033,7 +1085,7 @@ mod test_can {
// Ok(#single_question_ok_0_17) -> #single_question_ok_0_17 // Ok(#single_question_ok_0_17) -> #single_question_ok_0_17
// Err(#single_question_err_0_17) -> return Err(FailedToConvert(#single_question_err_0_17)) // Err(#single_question_err_0_17) -> return Err(FailedToConvert(#single_question_err_0_17))
let (cond_expr, branches) = assert_when(&out.loc_expr.value); let (cond_expr, branches) = assert_when_expr(&out.loc_expr.value);
let cond_args = assert_func_call(cond_expr, "to_u64", CalledVia::Space, &out.interns); let cond_args = assert_func_call(cond_expr, "to_u64", CalledVia::Space, &out.interns);
assert_eq!(cond_args.len(), 1); assert_eq!(cond_args.len(), 1);
@ -1075,11 +1127,13 @@ mod test_can {
} }
#[test] #[test]
fn try_desugar_works_elsewhere() { fn desugar_and_operator() {
let src = indoc!( let src = indoc!(
r#" r#"
when Foo 123 is left = Bool.true
Foo try -> try right = Bool.false
left and right
"# "#
); );
let arena = Bump::new(); let arena = Bump::new();
@ -1087,43 +1141,49 @@ mod test_can {
assert_eq!(out.problems, Vec::new()); assert_eq!(out.problems, Vec::new());
// Assert that we don't treat `try` as a keyword here // Assert that we desugar to:
// by desugaring to:
// //
// when Foo 123 is // if left then right else Bool.false
// Foo try -> try
let (cond_expr, branches) = assert_when(&out.loc_expr.value); let continuation1 = assert_let_expr(&out.loc_expr.value);
match cond_expr { let continuation2 = assert_let_expr(&continuation1.value);
Expr::Tag { let (branches, final_else) = assert_if_expr(&continuation2.value);
name, arguments, ..
} => {
assert_eq!(name.0.to_string(), "Foo");
assert_eq!(arguments.len(), 1);
assert_num_value(&arguments[0].1.value, 123);
}
_ => panic!("cond_expr was not a Tag: {:?}", cond_expr),
}
assert_eq!(branches.len(), 1); assert_eq!(branches.len(), 1);
assert_eq!(branches[0].patterns.len(), 1);
assert!(!branches[0].patterns[0].degenerate);
match &branches[0].patterns[0].pattern.value { assert_var_usage(&branches[0].0.value, "left", &out.interns);
Pattern::AppliedTag { assert_var_usage(&branches[0].1.value, "right", &out.interns);
tag_name, assert_var_usage(&final_else.value, "false", &out.interns);
arguments,
..
} => {
assert_eq!(tag_name.0.to_string(), "Foo");
assert_eq!(arguments.len(), 1);
assert_pattern_name(&arguments[0].1.value, "try", &out.interns);
}
other => panic!("First argument was not an applied tag: {:?}", other),
} }
assert_var_usage(&branches[0].value.value, "try", &out.interns); #[test]
assert!(&branches[0].guard.is_none()); fn desugar_or_operator() {
let src = indoc!(
r#"
left = Bool.true
right = Bool.false
left or right
"#
);
let arena = Bump::new();
let out = can_expr_with(&arena, test_home(), src);
assert_eq!(out.problems, Vec::new());
// Assert that we desugar to:
//
// if left then Bool.true else right
let continuation1 = assert_let_expr(&out.loc_expr.value);
let continuation2 = assert_let_expr(&continuation1.value);
let (branches, final_else) = assert_if_expr(&continuation2.value);
assert_eq!(branches.len(), 1);
assert_var_usage(&branches[0].0.value, "left", &out.interns);
assert_var_usage(&branches[0].1.value, "true", &out.interns);
assert_var_usage(&final_else.value, "right", &out.interns);
} }
fn assert_num_value(expr: &Expr, num: usize) { fn assert_num_value(expr: &Expr, num: usize) {
@ -1238,7 +1298,14 @@ mod test_can {
} }
} }
fn assert_when(expr: &Expr) -> (&Expr, &Vec<WhenBranch>) { fn assert_let_expr(expr: &Expr) -> &Loc<Expr> {
match expr {
Expr::LetNonRec(_, continuation) | Expr::LetRec(_, continuation, _) => continuation,
_ => panic!("Expr was not a Let(Non)?Rec: {expr:?}",),
}
}
fn assert_when_expr(expr: &Expr) -> (&Expr, &Vec<WhenBranch>) {
match expr { match expr {
Expr::When { Expr::When {
loc_cond, branches, .. loc_cond, branches, ..
@ -1247,6 +1314,18 @@ mod test_can {
} }
} }
#[allow(clippy::type_complexity)]
fn assert_if_expr(expr: &Expr) -> (&[(Loc<Expr>, Loc<Expr>)], &Loc<Expr>) {
match expr {
Expr::If {
branches,
final_else,
..
} => (&branches, &**final_else),
_ => panic!("Expr was not a When: {:?}", expr),
}
}
fn assert_try_expr(expr: &Expr) -> &Expr { fn assert_try_expr(expr: &Expr) -> &Expr {
match expr { match expr {
Expr::Try { result_expr, .. } => &result_expr.value, Expr::Try { result_expr, .. } => &result_expr.value,

View file

@ -95,22 +95,6 @@ flags! {
/// Prints all type variables entered for fixpoint-fixing. /// Prints all type variables entered for fixpoint-fixing.
ROC_PRINT_FIXPOINT_FIXING ROC_PRINT_FIXPOINT_FIXING
/// Verifies that after let-generalization of a def, any rigid variables in the type annotation
/// of the def are indeed generalized.
///
/// Note that rigids need not always be generalized in a def. For example, they may be
/// constrained by a type from a lower rank, as `b` is in the following def:
///
/// F a : { foo : a }
/// foo = \arg ->
/// x : F b
/// x = arg
/// x.foo
///
/// Instead, this flag is useful for checking that in general, introduction is correct, when
/// chainging how defs are constrained.
ROC_VERIFY_RIGID_LET_GENERALIZED
/// Verifies that an `occurs` check indeed only contains non-recursive types that need to be /// Verifies that an `occurs` check indeed only contains non-recursive types that need to be
/// fixed-up with one new recursion variable. /// fixed-up with one new recursion variable.
/// ///

View file

@ -1206,7 +1206,6 @@ impl<'a> Nodify<'a> for TypeAnnotation<'a> {
before: first_node.before, before: first_node.before,
node: Node::CommaSequence { node: Node::CommaSequence {
allow_blank_lines: false, allow_blank_lines: false,
allow_newlines: true,
indent_rest: false, indent_rest: false,
first: arena.alloc(first_node.node), first: arena.alloc(first_node.node),
rest: rest_nodes.into_bump_slice(), rest: rest_nodes.into_bump_slice(),
@ -1313,11 +1312,12 @@ impl<'a> Nodify<'a> for TypeAnnotation<'a> {
.to_node(arena, flags) .to_node(arena, flags)
.add_parens(arena, Parens::NotNeeded); .add_parens(arena, Parens::NotNeeded);
let mut needs_indent = annot.needs_indent || !annot.after.is_empty(); let before = filter_newlines(arena, annot.after);
let mut needs_indent = annot.needs_indent || !before.is_empty();
items.push(Item { items.push(Item {
comma_before: false, comma_before: false,
before: annot.after, before,
newline: false, newline: false,
space: true, space: true,
node: Node::Literal(roc_parse::keyword::WHERE), node: Node::Literal(roc_parse::keyword::WHERE),
@ -1327,7 +1327,8 @@ impl<'a> Nodify<'a> for TypeAnnotation<'a> {
for (i, clause) in implements_clauses.iter().enumerate() { for (i, clause) in implements_clauses.iter().enumerate() {
let node = clause.value.to_node(arena, flags); let node = clause.value.to_node(arena, flags);
let before = merge_spaces_conservative(arena, last_after, node.before); let before =
filter_newlines(arena, merge_spaces(arena, last_after, node.before));
last_after = node.after; last_after = node.after;
items.push(Item { items.push(Item {
before, before,
@ -1346,8 +1347,7 @@ impl<'a> Nodify<'a> for TypeAnnotation<'a> {
first: arena.alloc(annot.node), first: arena.alloc(annot.node),
rest: arena.alloc_slice_copy(&items), rest: arena.alloc_slice_copy(&items),
allow_blank_lines: false, allow_blank_lines: false,
allow_newlines: false, indent_rest: true,
indent_rest: false,
}, },
after: last_after, after: last_after,
needs_indent, needs_indent,
@ -1358,6 +1358,24 @@ impl<'a> Nodify<'a> for TypeAnnotation<'a> {
} }
} }
fn filter_newlines<'a, 'b: 'a>(
arena: &'a Bump,
items: &'b [CommentOrNewline<'b>],
) -> &'a [CommentOrNewline<'a>] {
let count = items.iter().filter(|i| i.is_newline()).count();
if count > 0 {
let mut new_items = Vec::with_capacity_in(items.len() - count, arena);
for item in items {
if !item.is_newline() {
new_items.push(*item);
}
}
arena.alloc_slice_copy(&new_items)
} else {
items
}
}
impl<'a> Nodify<'a> for &'a str { impl<'a> Nodify<'a> for &'a str {
fn to_node<'b>(&'a self, arena: &'b Bump, flags: MigrationFlags) -> NodeInfo<'b> fn to_node<'b>(&'a self, arena: &'b Bump, flags: MigrationFlags) -> NodeInfo<'b>
where where
@ -1451,7 +1469,6 @@ impl<'a> Nodify<'a> for ImplementsClause<'a> {
first: arena.alloc(var.node), first: arena.alloc(var.node),
rest: arena.alloc_slice_copy(&items), rest: arena.alloc_slice_copy(&items),
allow_blank_lines: false, allow_blank_lines: false,
allow_newlines: true,
indent_rest: false, indent_rest: false,
}, },
after: last_after, after: last_after,

View file

@ -1,20 +1,20 @@
use crate::annotation::{ use crate::annotation::{
ann_lift_spaces, ann_lift_spaces_after, is_collection_multiline, ty_is_outdentable, ann_lift_spaces_after, is_collection_multiline, Formattable, Newlines, Parens,
Formattable, Newlines, Parens,
}; };
use crate::collection::{fmt_collection, Braces}; use crate::collection::{fmt_collection, Braces};
use crate::expr::{ use crate::expr::{
expr_lift_and_lower, expr_lift_spaces, expr_lift_spaces_after, expr_lift_spaces_before, expr_lift_spaces, expr_lift_spaces_after, expr_lift_spaces_before, fmt_str_literal,
fmt_str_literal, is_str_multiline, merge_spaces_conservative, sub_expr_requests_parens, is_str_multiline, merge_spaces_conservative, sub_expr_requests_parens,
}; };
use crate::node::Nodify; use crate::node::Nodify;
use crate::pattern::pattern_lift_spaces_before; use crate::pattern::{pattern_lift_spaces, pattern_lift_spaces_before};
use crate::spaces::{ use crate::spaces::{
fmt_comments_only, fmt_default_newline, fmt_default_spaces, fmt_spaces, NewlineAt, INDENT, fmt_comments_only, fmt_default_newline, fmt_default_spaces, fmt_spaces, NewlineAt, INDENT,
}; };
use crate::Buf; use crate::Buf;
use bumpalo::Bump; use bumpalo::Bump;
use roc_error_macros::internal_error; use roc_error_macros::internal_error;
use roc_parse::ast::Spaceable;
use roc_parse::ast::{ use roc_parse::ast::{
AbilityMember, Defs, Expr, ExtractSpaces, ImportAlias, ImportAsKeyword, ImportExposingKeyword, AbilityMember, Defs, Expr, ExtractSpaces, ImportAlias, ImportAsKeyword, ImportExposingKeyword,
ImportedModuleName, IngestedFileAnnotation, IngestedFileImport, ModuleImport, ImportedModuleName, IngestedFileAnnotation, IngestedFileImport, ModuleImport,
@ -182,16 +182,29 @@ pub fn valdef_lift_spaces<'a, 'b: 'a>(
} }
} }
ValueDef::Body(pat, expr) => { ValueDef::Body(pat, expr) => {
let pat_lifted = pattern_lift_spaces_before(arena, &pat.value); let pat_lifted = pattern_lift_spaces(arena, &pat.value);
let expr_lifted = expr_lift_spaces_after(Parens::NotNeeded, arena, &expr.value);
// Don't format the `{} =` for defs with this pattern
if is_body_unit_assignment(&pat_lifted, &expr.extract_spaces()) {
let lifted = expr_lift_spaces(Parens::NotNeeded, arena, &expr.value);
Spaces {
before: lifted.before,
item: ValueDef::Stmt(arena.alloc(Loc::at_zero(lifted.item))),
after: lifted.after,
}
} else {
let lifted = expr_lift_spaces(Parens::NotNeeded, arena, &expr.value);
Spaces { Spaces {
before: pat_lifted.before, before: pat_lifted.before,
item: ValueDef::Body( item: ValueDef::Body(
arena.alloc(Loc::at(pat.region, pat_lifted.item)), arena.alloc(Loc::at(
arena.alloc(Loc::at(expr.region, expr_lifted.item)), pat.region,
pat_lifted.item.maybe_after(arena, pat_lifted.after),
)),
expr,
), ),
after: expr_lifted.after, after: lifted.after,
}
} }
} }
ValueDef::AnnotatedBody { ValueDef::AnnotatedBody {
@ -312,11 +325,26 @@ pub fn valdef_lift_spaces_before<'a, 'b: 'a>(
} }
} }
ValueDef::Body(pat, expr) => { ValueDef::Body(pat, expr) => {
let pat_lifted = pattern_lift_spaces_before(arena, &pat.value); let pat_lifted = pattern_lift_spaces(arena, &pat.value);
// Don't format the `{} =` for defs with this pattern
if is_body_unit_assignment(&pat_lifted, &expr.extract_spaces()) {
let lifted = expr_lift_spaces_before(Parens::NotNeeded, arena, &expr.value);
SpacesBefore {
before: lifted.before,
item: ValueDef::Stmt(arena.alloc(Loc::at_zero(lifted.item))),
}
} else {
SpacesBefore { SpacesBefore {
before: pat_lifted.before, before: pat_lifted.before,
item: ValueDef::Body(arena.alloc(Loc::at(pat.region, pat_lifted.item)), expr), item: ValueDef::Body(
arena.alloc(Loc::at(
pat.region,
pat_lifted.item.maybe_after(arena, pat_lifted.after),
)),
expr,
),
}
} }
} }
ValueDef::AnnotatedBody { ValueDef::AnnotatedBody {
@ -396,6 +424,20 @@ pub fn valdef_lift_spaces_before<'a, 'b: 'a>(
} }
} }
fn is_body_unit_assignment(pat: &Spaces<'_, Pattern<'_>>, body: &Spaces<'_, Expr<'_>>) -> bool {
if let Pattern::RecordDestructure(collection) = pat.item {
collection.is_empty()
&& pat.before.iter().all(|s| s.is_newline())
&& pat.after.iter().all(|s| s.is_newline())
&& !matches!(body.item, Expr::Defs(..))
&& !matches!(body.item, Expr::Return(..))
&& !matches!(body.item, Expr::DbgStmt { .. })
&& !starts_with_expect_ident(&body.item)
} else {
false
}
}
impl<'a> Formattable for TypeDef<'a> { impl<'a> Formattable for TypeDef<'a> {
fn is_multiline(&self) -> bool { fn is_multiline(&self) -> bool {
use roc_parse::ast::TypeDef::*; use roc_parse::ast::TypeDef::*;
@ -412,22 +454,15 @@ impl<'a> Formattable for TypeDef<'a> {
match self { match self {
Alias { header, ann } => { Alias { header, ann } => {
header.format(buf, indent); fmt_general_def(
header,
buf.indent(indent); Parens::NotNeeded,
buf.push_str(" :"); buf,
buf.spaces(1); indent,
":",
let ann = ann_lift_spaces(buf.text.bump(), &ann.value); &ann.value,
newlines,
let inner_indent = if ty_is_outdentable(&ann.item) { );
indent
} else {
indent + INDENT
};
fmt_comments_only(buf, ann.before.iter(), NewlineAt::Bottom, inner_indent);
ann.item.format(buf, inner_indent);
fmt_spaces(buf, ann.after.iter(), indent);
} }
Opaque { Opaque {
header, header,
@ -797,7 +832,7 @@ impl<'a> Formattable for ValueDef<'a> {
); );
} }
Body(loc_pattern, loc_expr) => { Body(loc_pattern, loc_expr) => {
fmt_body(buf, true, &loc_pattern.value, &loc_expr.value, indent); fmt_body(buf, &loc_pattern.value, &loc_expr.value, indent);
} }
Dbg { condition, .. } => fmt_dbg_in_def(buf, condition, self.is_multiline(), indent), Dbg { condition, .. } => fmt_dbg_in_def(buf, condition, self.is_multiline(), indent),
Expect { condition, .. } => fmt_expect(buf, condition, self.is_multiline(), indent), Expect { condition, .. } => fmt_expect(buf, condition, self.is_multiline(), indent),
@ -826,7 +861,7 @@ impl<'a> Formattable for ValueDef<'a> {
fmt_annotated_body_comment(buf, indent, lines_between); fmt_annotated_body_comment(buf, indent, lines_between);
buf.newline(); buf.newline();
fmt_body(buf, false, &body_pattern.value, &body_expr.value, indent); fmt_body(buf, &body_pattern.value, &body_expr.value, indent);
} }
ModuleImport(module_import) => module_import.format(buf, indent), ModuleImport(module_import) => module_import.format(buf, indent),
IngestedFileImport(ingested_file_import) => ingested_file_import.format(buf, indent), IngestedFileImport(ingested_file_import) => ingested_file_import.format(buf, indent),
@ -957,34 +992,7 @@ pub fn fmt_annotated_body_comment<'a>(
} }
} }
pub fn fmt_body<'a>( pub fn fmt_body<'a>(buf: &mut Buf, pattern: &'a Pattern<'a>, body: &'a Expr<'a>, indent: u16) {
buf: &mut Buf,
allow_simplify_empty_record_destructure: bool,
pattern: &'a Pattern<'a>,
body: &'a Expr<'a>,
indent: u16,
) {
let pattern_extracted = pattern.extract_spaces();
// Check if this is an assignment into the unit value
let is_unit_assignment = if let Pattern::RecordDestructure(collection) = pattern_extracted.item
{
allow_simplify_empty_record_destructure
&& collection.is_empty()
&& pattern_extracted.before.iter().all(|s| s.is_newline())
&& pattern_extracted.after.iter().all(|s| s.is_newline())
&& !matches!(body.extract_spaces().item, Expr::Defs(..))
&& !matches!(body.extract_spaces().item, Expr::Return(..))
&& !matches!(body.extract_spaces().item, Expr::DbgStmt { .. })
&& !starts_with_expect_ident(body)
} else {
false
};
// Don't format the `{} =` for defs with this pattern
if is_unit_assignment {
return body.format_with_options(buf, Parens::NotNeeded, Newlines::No, indent);
}
pattern.format_with_options(buf, Parens::InApply, Newlines::No, indent); pattern.format_with_options(buf, Parens::InApply, Newlines::No, indent);
if pattern.is_multiline() { if pattern.is_multiline() {
@ -996,7 +1004,12 @@ pub fn fmt_body<'a>(
let indent = buf.cur_line_indent(); let indent = buf.cur_line_indent();
buf.push_str("="); buf.push_str("=");
let body = expr_lift_and_lower(Parens::NotNeeded, buf.text.bump(), body); let body_lifted = expr_lift_spaces(Parens::NotNeeded, buf.text.bump(), body);
let after = body_lifted.after;
let body = body_lifted
.item
.maybe_before(buf.text.bump(), body_lifted.before);
if body.is_multiline() { if body.is_multiline() {
match body { match body {
@ -1009,10 +1022,7 @@ pub fn fmt_body<'a>(
_ => false, _ => false,
}; };
if is_unit_assignment { if should_outdent {
fmt_comments_only(buf, spaces.iter(), NewlineAt::Bottom, indent);
sub_def.format_with_options(buf, Parens::NotNeeded, Newlines::Yes, indent);
} else if should_outdent {
buf.spaces(1); buf.spaces(1);
sub_def.format_with_options(buf, Parens::NotNeeded, Newlines::Yes, indent); sub_def.format_with_options(buf, Parens::NotNeeded, Newlines::Yes, indent);
} else { } else {
@ -1057,7 +1067,7 @@ pub fn fmt_body<'a>(
buf.ensure_ends_with_newline(); buf.ensure_ends_with_newline();
body.format_with_options(buf, Parens::NotNeeded, Newlines::Yes, indent + INDENT); body.format_with_options(buf, Parens::NotNeeded, Newlines::Yes, indent + INDENT);
} }
Expr::Defs(..) | Expr::BinOps(_, _) => { Expr::Defs(..) | Expr::BinOps(..) => {
// Binop chains always get a newline. Otherwise you can have things like: // Binop chains always get a newline. Otherwise you can have things like:
// //
// something = foo // something = foo
@ -1092,6 +1102,8 @@ pub fn fmt_body<'a>(
buf.spaces(1); buf.spaces(1);
body.format_with_options(buf, Parens::NotNeeded, Newlines::Yes, indent); body.format_with_options(buf, Parens::NotNeeded, Newlines::Yes, indent);
} }
fmt_spaces(buf, after.iter(), indent);
} }
fn starts_with_expect_ident(expr: &Expr<'_>) -> bool { fn starts_with_expect_ident(expr: &Expr<'_>) -> bool {
@ -1116,6 +1128,7 @@ pub fn starts_with_block_string_literal(expr: &Expr<'_>) -> bool {
} }
Expr::Apply(inner, _, _) => starts_with_block_string_literal(&inner.value), Expr::Apply(inner, _, _) => starts_with_block_string_literal(&inner.value),
Expr::RecordAccess(inner, _) => starts_with_block_string_literal(inner), Expr::RecordAccess(inner, _) => starts_with_block_string_literal(inner),
Expr::TupleAccess(inner, _) => starts_with_block_string_literal(inner),
Expr::PncApply(inner, _) => starts_with_block_string_literal(&inner.value), Expr::PncApply(inner, _) => starts_with_block_string_literal(&inner.value),
Expr::TrySuffix(inner) => starts_with_block_string_literal(inner), Expr::TrySuffix(inner) => starts_with_block_string_literal(inner),
_ => false, _ => false,

View file

@ -1,6 +1,6 @@
use crate::annotation::{except_last, is_collection_multiline, Formattable, Newlines, Parens}; use crate::annotation::{except_last, is_collection_multiline, Formattable, Newlines, Parens};
use crate::collection::{fmt_collection, Braces}; use crate::collection::{fmt_collection, Braces};
use crate::def::{fmt_defs, valdef_lift_spaces_before}; use crate::def::{fmt_defs, starts_with_block_string_literal, valdef_lift_spaces_before};
use crate::node::Prec; use crate::node::Prec;
use crate::pattern::{ use crate::pattern::{
fmt_pattern, pattern_lift_spaces, snakify_camel_ident, starts_with_inline_comment, fmt_pattern, pattern_lift_spaces, snakify_camel_ident, starts_with_inline_comment,
@ -264,7 +264,7 @@ fn format_expr_only(
let before_all_newlines = lifted.before.iter().all(|s| s.is_newline()); let before_all_newlines = lifted.before.iter().all(|s| s.is_newline());
let needs_newline = let needs_newline =
!before_all_newlines || term_starts_with_multiline_str(&lifted.item); !before_all_newlines || starts_with_block_string_literal(&lifted.item);
let needs_parens = (needs_newline let needs_parens = (needs_newline
&& matches!(unary_op.value, called_via::UnaryOp::Negate)) && matches!(unary_op.value, called_via::UnaryOp::Negate))
@ -367,14 +367,6 @@ fn format_expr_only(
} }
} }
fn term_starts_with_multiline_str(expr: &Expr<'_>) -> bool {
match expr {
Expr::Str(text) => is_str_multiline(text),
Expr::PncApply(inner, _) => term_starts_with_multiline_str(&inner.value),
_ => false,
}
}
fn prepare_expr_field_collection<'a>( fn prepare_expr_field_collection<'a>(
arena: &'a Bump, arena: &'a Bump,
items: Collection<'a, Loc<AssignedField<'a, Expr<'a>>>>, items: Collection<'a, Loc<AssignedField<'a, Expr<'a>>>>,
@ -959,8 +951,8 @@ fn push_op(buf: &mut Buf, op: BinOp) {
called_via::BinOp::GreaterThan => buf.push('>'), called_via::BinOp::GreaterThan => buf.push('>'),
called_via::BinOp::LessThanOrEq => buf.push_str("<="), called_via::BinOp::LessThanOrEq => buf.push_str("<="),
called_via::BinOp::GreaterThanOrEq => buf.push_str(">="), called_via::BinOp::GreaterThanOrEq => buf.push_str(">="),
called_via::BinOp::And => buf.push_str("&&"), called_via::BinOp::Or => buf.push_str("or"),
called_via::BinOp::Or => buf.push_str("||"), called_via::BinOp::And => buf.push_str("and"),
called_via::BinOp::Pizza => buf.push_str("|>"), called_via::BinOp::Pizza => buf.push_str("|>"),
called_via::BinOp::DoubleQuestion => buf.push_str("??"), called_via::BinOp::DoubleQuestion => buf.push_str("??"),
called_via::BinOp::SingleQuestion => buf.push_str("?"), called_via::BinOp::SingleQuestion => buf.push_str("?"),
@ -1026,14 +1018,6 @@ pub fn fmt_str_literal(buf: &mut Buf, literal: StrLiteral, indent: u16) {
} }
} }
pub fn expr_lift_and_lower<'a, 'b: 'a>(
_parens: Parens,
arena: &'a Bump,
expr: &Expr<'b>,
) -> Expr<'a> {
lower(arena, expr_lift_spaces(Parens::NotNeeded, arena, expr))
}
pub fn expr_lift_spaces<'a, 'b: 'a>( pub fn expr_lift_spaces<'a, 'b: 'a>(
parens: Parens, parens: Parens,
arena: &'a Bump, arena: &'a Bump,
@ -1496,7 +1480,6 @@ fn fmt_binops<'a>(
buf: &mut Buf, buf: &mut Buf,
lefts: &'a [(Loc<Expr<'a>>, Loc<BinOp>)], lefts: &'a [(Loc<Expr<'a>>, Loc<BinOp>)],
loc_right_side: &'a Loc<Expr<'a>>, loc_right_side: &'a Loc<Expr<'a>>,
indent: u16, indent: u16,
) { ) {
let is_multiline = loc_right_side.value.is_multiline() let is_multiline = loc_right_side.value.is_multiline()
@ -1825,6 +1808,8 @@ fn guard_needs_parens(value: &Expr<'_>) -> bool {
Expr::ParensAround(expr) | Expr::SpaceBefore(expr, _) | Expr::SpaceAfter(expr, _) => { Expr::ParensAround(expr) | Expr::SpaceBefore(expr, _) | Expr::SpaceAfter(expr, _) => {
guard_needs_parens(expr) guard_needs_parens(expr)
} }
Expr::BinOps(_lefts, right) => guard_needs_parens(&right.value),
Expr::UnaryOp(inner, _) => guard_needs_parens(&inner.value),
Expr::Closure(_, body) => guard_needs_parens(&body.value), Expr::Closure(_, body) => guard_needs_parens(&body.value),
Expr::Defs(_, final_expr) => guard_needs_parens(&final_expr.value), Expr::Defs(_, final_expr) => guard_needs_parens(&final_expr.value),
_ => false, _ => false,

View file

@ -5,7 +5,7 @@ use crate::{
annotation::{Formattable, Newlines, Parens}, annotation::{Formattable, Newlines, Parens},
collection::Braces, collection::Braces,
expr::merge_spaces_conservative, expr::merge_spaces_conservative,
spaces::{fmt_comments_only, fmt_spaces, fmt_spaces_no_blank_lines, NewlineAt, INDENT}, spaces::{fmt_spaces, fmt_spaces_no_blank_lines, INDENT},
Buf, MigrationFlags, Buf, MigrationFlags,
}; };
@ -87,7 +87,6 @@ pub enum Node<'a> {
}, },
CommaSequence { CommaSequence {
allow_blank_lines: bool, allow_blank_lines: bool,
allow_newlines: bool,
indent_rest: bool, indent_rest: bool,
first: &'a Node<'a>, first: &'a Node<'a>,
rest: &'a [Item<'a>], rest: &'a [Item<'a>],
@ -124,12 +123,8 @@ pub struct Item<'a> {
} }
impl<'a> Item<'a> { impl<'a> Item<'a> {
fn is_multiline(&self, allow_newlines: bool) -> bool { fn is_multiline(&self) -> bool {
let has_newlines = if allow_newlines { let has_newlines = !self.before.is_empty();
!self.before.is_empty()
} else {
self.before.iter().any(|c| c.is_comment())
};
self.newline || has_newlines || self.node.is_multiline() self.newline || has_newlines || self.node.is_multiline()
} }
} }
@ -273,7 +268,6 @@ impl<'b> NodeInfo<'b> {
}, },
node: Node::CommaSequence { node: Node::CommaSequence {
allow_blank_lines: false, allow_blank_lines: false,
allow_newlines: true,
indent_rest, indent_rest,
first: arena.alloc(first.node), first: arena.alloc(first.node),
rest: rest.into_bump_slice(), rest: rest.into_bump_slice(),
@ -361,11 +355,10 @@ impl<'a> Formattable for Node<'a> {
} => after.is_multiline() || items.iter().any(|item| item.is_multiline()), } => after.is_multiline() || items.iter().any(|item| item.is_multiline()),
Node::CommaSequence { Node::CommaSequence {
allow_blank_lines: _, allow_blank_lines: _,
allow_newlines,
indent_rest: _, indent_rest: _,
first, first,
rest, rest,
} => first.is_multiline() || rest.iter().any(|item| item.is_multiline(*allow_newlines)), } => first.is_multiline() || rest.iter().any(|item| item.is_multiline()),
Node::Literal(_) => false, Node::Literal(_) => false,
Node::TypeAnnotation(type_annotation) => type_annotation.is_multiline(), Node::TypeAnnotation(type_annotation) => type_annotation.is_multiline(),
Node::Pattern(pat) => pat.is_multiline(), Node::Pattern(pat) => pat.is_multiline(),
@ -429,7 +422,6 @@ impl<'a> Formattable for Node<'a> {
} }
Node::CommaSequence { Node::CommaSequence {
allow_blank_lines, allow_blank_lines,
allow_newlines,
indent_rest, indent_rest,
first, first,
rest, rest,
@ -448,10 +440,8 @@ impl<'a> Formattable for Node<'a> {
} }
if *allow_blank_lines { if *allow_blank_lines {
fmt_spaces(buf, item.before.iter(), indent); fmt_spaces(buf, item.before.iter(), indent);
} else if *allow_newlines {
fmt_spaces_no_blank_lines(buf, item.before.iter(), inner_indent);
} else { } else {
fmt_comments_only(buf, item.before.iter(), NewlineAt::Bottom, inner_indent); fmt_spaces_no_blank_lines(buf, item.before.iter(), inner_indent);
} }
if item.newline { if item.newline {
buf.ensure_ends_with_newline(); buf.ensure_ends_with_newline();

View file

@ -294,7 +294,8 @@ fn fmt_pattern_only(
is_negative, is_negative,
} => { } => {
buf.indent(indent); buf.indent(indent);
let needs_parens = parens == Parens::InClosurePattern; let needs_parens = parens == Parens::InClosurePattern
|| (parens == Parens::InPncApplyFunc && *is_negative);
if needs_parens { if needs_parens {
buf.push('('); buf.push('(');
} }
@ -317,7 +318,8 @@ fn fmt_pattern_only(
} }
Pattern::FloatLiteral(string) => { Pattern::FloatLiteral(string) => {
buf.indent(indent); buf.indent(indent);
let needs_parens = parens == Parens::InClosurePattern; let needs_parens = parens == Parens::InClosurePattern
|| (parens == Parens::InPncApplyFunc && string.starts_with('-'));
if needs_parens { if needs_parens {
buf.push('('); buf.push('(');
} }

View file

@ -1268,20 +1268,6 @@ trait Backend<'a> {
internal_error!("bitwise xor on a non-integer") internal_error!("bitwise xor on a non-integer")
} }
} }
LowLevel::And => {
if let LayoutRepr::Builtin(Builtin::Bool) = self.interner().get_repr(*ret_layout) {
self.build_int_bitwise_and(sym, &args[0], &args[1], IntWidth::U8)
} else {
internal_error!("bitwise and on a non-integer")
}
}
LowLevel::Or => {
if let LayoutRepr::Builtin(Builtin::Bool) = self.interner().get_repr(*ret_layout) {
self.build_int_bitwise_or(sym, &args[0], &args[1], IntWidth::U8)
} else {
internal_error!("bitwise or on a non-integer")
}
}
LowLevel::NumShiftLeftBy => { LowLevel::NumShiftLeftBy => {
if let LayoutRepr::Builtin(Builtin::Int(int_width)) = if let LayoutRepr::Builtin(Builtin::Int(int_width)) =
self.interner().get_repr(*ret_layout) self.interner().get_repr(*ret_layout)
@ -1733,6 +1719,13 @@ trait Backend<'a> {
arg_layouts, arg_layouts,
ret_layout, ret_layout,
), ),
LowLevel::StrWithAsciiLowercased => self.build_fn_call(
sym,
bitcode::STR_WITH_ASCII_LOWERCASED.to_string(),
args,
arg_layouts,
ret_layout,
),
LowLevel::StrToNum => { LowLevel::StrToNum => {
let number_layout = match self.interner().get_repr(*ret_layout) { let number_layout = match self.interner().get_repr(*ret_layout) {
LayoutRepr::Struct(field_layouts) => field_layouts[0], // TODO: why is it sometimes a struct? LayoutRepr::Struct(field_layouts) => field_layouts[0], // TODO: why is it sometimes a struct?

View file

@ -572,6 +572,7 @@ pub(crate) fn run_low_level<'a, 'ctx>(
bitcode::STR_WITH_CAPACITY, bitcode::STR_WITH_CAPACITY,
) )
} }
ListLenU64 => { ListLenU64 => {
// List.len : List * -> U64 // List.len : List * -> U64
arguments!(list); arguments!(list);
@ -614,6 +615,17 @@ pub(crate) fn run_low_level<'a, 'ctx>(
list_element_layout!(layout_interner, result_layout), list_element_layout!(layout_interner, result_layout),
) )
} }
StrWithAsciiLowercased => {
arguments!(string);
call_str_bitcode_fn(
env,
&[string],
&[],
BitcodeReturns::Str,
bitcode::STR_WITH_ASCII_LOWERCASED,
)
}
ListConcat => { ListConcat => {
debug_assert_eq!(args.len(), 2); debug_assert_eq!(args.len(), 2);
@ -1263,30 +1275,6 @@ pub(crate) fn run_low_level<'a, 'ctx>(
rhs_layout, rhs_layout,
) )
} }
And => {
// The (&&) operator
arguments!(lhs_arg, rhs_arg);
let bool_val = env.builder.new_build_and(
lhs_arg.into_int_value(),
rhs_arg.into_int_value(),
"bool_and",
);
BasicValueEnum::IntValue(bool_val)
}
Or => {
// The (||) operator
arguments!(lhs_arg, rhs_arg);
let bool_val = env.builder.new_build_or(
lhs_arg.into_int_value(),
rhs_arg.into_int_value(),
"bool_or",
);
BasicValueEnum::IntValue(bool_val)
}
Not => { Not => {
// The (!) operator // The (!) operator
arguments!(arg); arguments!(arg);

View file

@ -259,6 +259,9 @@ impl<'a> LowLevelCall<'a> {
self.load_args_and_call_zig(backend, bitcode::STR_SUBSTRING_UNSAFE) self.load_args_and_call_zig(backend, bitcode::STR_SUBSTRING_UNSAFE)
} }
StrWithCapacity => self.load_args_and_call_zig(backend, bitcode::STR_WITH_CAPACITY), StrWithCapacity => self.load_args_and_call_zig(backend, bitcode::STR_WITH_CAPACITY),
StrWithAsciiLowercased => {
self.load_args_and_call_zig(backend, bitcode::STR_WITH_ASCII_LOWERCASED)
}
// List // List
ListLenU64 => { ListLenU64 => {
@ -2164,14 +2167,6 @@ impl<'a> LowLevelCall<'a> {
NumF64ToParts => self.load_args_and_call_zig(backend, bitcode::NUM_F64_TO_PARTS), NumF64ToParts => self.load_args_and_call_zig(backend, bitcode::NUM_F64_TO_PARTS),
NumF32FromParts => self.load_args_and_call_zig(backend, bitcode::NUM_F32_FROM_PARTS), NumF32FromParts => self.load_args_and_call_zig(backend, bitcode::NUM_F32_FROM_PARTS),
NumF64FromParts => self.load_args_and_call_zig(backend, bitcode::NUM_F64_FROM_PARTS), NumF64FromParts => self.load_args_and_call_zig(backend, bitcode::NUM_F64_FROM_PARTS),
And => {
self.load_args(backend);
backend.code_builder.i32_and();
}
Or => {
self.load_args(backend);
backend.code_builder.i32_or();
}
Not => { Not => {
self.load_args(backend); self.load_args(backend);
backend.code_builder.i32_eqz(); backend.code_builder.i32_eqz();

View file

@ -9,6 +9,7 @@ version.workspace = true
[dependencies] [dependencies]
roc_can.workspace = true roc_can.workspace = true
roc_can_solo.workspace = true
roc_collections.workspace = true roc_collections.workspace = true
roc_load_internal.workspace = true roc_load_internal.workspace = true
roc_module.workspace = true roc_module.workspace = true

View file

@ -3,11 +3,12 @@ extern crate bumpalo;
use self::bumpalo::Bump; use self::bumpalo::Bump;
use roc_can::abilities::AbilitiesStore; use roc_can::abilities::AbilitiesStore;
use roc_can::constraint::{Constraint, Constraints}; use roc_can::constraint::{Constraint, Constraints};
use roc_can::desugar;
use roc_can::env::Env; use roc_can::env::Env;
use roc_can::expected::Expected; use roc_can::expected::Expected;
use roc_can::expr::{canonicalize_expr, Expr, Output, PendingDerives}; use roc_can::expr::{canonicalize_expr, Expr, Output, PendingDerives};
use roc_can::scope::Scope; use roc_can::scope::Scope;
use roc_can_solo::env::SoloEnv;
use roc_can_solo::scope::SoloScope;
use roc_collections::all::{ImMap, MutMap, SendSet}; use roc_collections::all::{ImMap, MutMap, SendSet};
use roc_constrain::expr::constrain_expr; use roc_constrain::expr::constrain_expr;
use roc_derive::SharedDerivedModule; use roc_derive::SharedDerivedModule;
@ -162,24 +163,6 @@ pub fn can_expr_with<'a>(
// ensure the Test module is accessible in our tests // ensure the Test module is accessible in our tests
module_ids.get_or_insert(&PQModuleName::Unqualified("Test".into())); module_ids.get_or_insert(&PQModuleName::Unqualified("Test".into()));
let mut scope = Scope::new(
home,
"TestPath".into(),
IdentIds::default(),
Default::default(),
);
let dep_idents = IdentIds::exposed_builtins(0);
let mut env = Env::new(
arena,
expr_str,
home,
Path::new("Test.roc"),
&dep_idents,
&module_ids,
None,
);
// Desugar operators (convert them to Apply calls, taking into account // Desugar operators (convert them to Apply calls, taking into account
// operator precedence and associativity rules), before doing other canonicalization. // operator precedence and associativity rules), before doing other canonicalization.
// //
@ -187,7 +170,9 @@ pub fn can_expr_with<'a>(
// visited a BinOp node we'd recursively try to apply this to each of its nested // visited a BinOp node we'd recursively try to apply this to each of its nested
// operators, and then again on *their* nested operators, ultimately applying the // operators, and then again on *their* nested operators, ultimately applying the
// rules multiple times unnecessarily. // rules multiple times unnecessarily.
let loc_expr = desugar::desugar_expr(&mut env, &mut scope, &loc_expr); let mut solo_env = SoloEnv::new(arena, expr_str, Path::new("Test.roc"));
let mut solo_scope = SoloScope::new();
let loc_expr = roc_can_solo::desugar::desugar_expr(&mut solo_env, &mut solo_scope, &loc_expr);
let mut scope = Scope::new( let mut scope = Scope::new(
home, home,

View file

@ -1522,18 +1522,18 @@ mod test_reporting {
from_annotation_if, from_annotation_if,
indoc!( indoc!(
r" r"
x : Num.Int * x : Num.Int _
x = if Bool.true then 3.14 else 4 x = if Bool.true then 3.14 else 4
x x
" "
), ),
@r" @r###"
TYPE MISMATCH in /code/proj/Main.roc TYPE MISMATCH in /code/proj/Main.roc
Something is off with the `then` branch of this `if` expression: Something is off with the `then` branch of this `if` expression:
4 x : Num.Int * 4 x : Num.Int _
5 x = if Bool.true then 3.14 else 4 5 x = if Bool.true then 3.14 else 4
^^^^ ^^^^
@ -1547,14 +1547,14 @@ mod test_reporting {
Tip: You can convert between integers and fractions using functions Tip: You can convert between integers and fractions using functions
like `Num.to_frac` and `Num.round`. like `Num.to_frac` and `Num.round`.
" "###
); );
test_report!( test_report!(
from_annotation_when, from_annotation_when,
indoc!( indoc!(
r" r"
x : Num.Int * x : Num.Int _
x = x =
when True is when True is
_ -> 3.14 _ -> 3.14
@ -1562,12 +1562,12 @@ mod test_reporting {
x x
" "
), ),
@r" @r###"
TYPE MISMATCH in /code/proj/Main.roc TYPE MISMATCH in /code/proj/Main.roc
Something is off with the body of the `x` definition: Something is off with the body of the `x` definition:
4 x : Num.Int * 4 x : Num.Int _
5 x = 5 x =
6> when True is 6> when True is
7> _ -> 3.14 7> _ -> 3.14
@ -1582,7 +1582,7 @@ mod test_reporting {
Tip: You can convert between integers and fractions using functions Tip: You can convert between integers and fractions using functions
like `Num.to_frac` and `Num.round`. like `Num.to_frac` and `Num.round`.
" "###
); );
test_report!( test_report!(
@ -1910,7 +1910,7 @@ mod test_reporting {
from_annotation_complex_pattern, from_annotation_complex_pattern,
indoc!( indoc!(
r" r"
{ x } : { x : Num.Int * } { x } : { x : Num.Int _ }
{ x } = { x: 4.0 } { x } = { x: 4.0 }
x x
@ -1921,7 +1921,7 @@ mod test_reporting {
Something is off with the body of this definition: Something is off with the body of this definition:
4 { x } : { x : Num.Int * } 4 { x } : { x : Num.Int _ }
5 { x } = { x: 4.0 } 5 { x } = { x: 4.0 }
^^^^^^^^^^ ^^^^^^^^^^
@ -2047,18 +2047,18 @@ mod test_reporting {
missing_fields, missing_fields,
indoc!( indoc!(
r" r"
x : { a : Num.Int *, b : Num.Frac *, c : Str } x : { a : Num.Int _, b : Num.Frac _, c : Str }
x = { b: 4.0 } x = { b: 4.0 }
x x
" "
), ),
@r" @r###"
TYPE MISMATCH in /code/proj/Main.roc TYPE MISMATCH in /code/proj/Main.roc
Something is off with the body of the `x` definition: Something is off with the body of the `x` definition:
4 x : { a : Num.Int *, b : Num.Frac *, c : Str } 4 x : { a : Num.Int _, b : Num.Frac _, c : Str }
5 x = { b: 4.0 } 5 x = { b: 4.0 }
^^^^^^^^^^ ^^^^^^^^^^
@ -2075,7 +2075,7 @@ mod test_reporting {
} }
Tip: Looks like the c and a fields are missing. Tip: Looks like the c and a fields are missing.
" "###
); );
// this previously reported the message below, not sure which is better // this previously reported the message below, not sure which is better
@ -3448,7 +3448,7 @@ mod test_reporting {
x : AList Num.I64 Num.I64 x : AList Num.I64 Num.I64
x = ACons 0 (BCons 1 (ACons "foo" BNil )) x = ACons 0 (BCons 1 (ACons "foo" BNil ))
y : BList a a y : BList _ _
y = BNil y = BNil
{ x, y } { x, y }
@ -4189,9 +4189,8 @@ mod test_reporting {
RBTree k v : [Node NodeColor k v (RBTree k v) (RBTree k v), Empty] RBTree k v : [Node NodeColor k v (RBTree k v) (RBTree k v), Empty]
# Create an empty dictionary. # Create an empty dictionary.
empty : RBTree k v empty : {} -> RBTree k v
empty = empty = \{} -> Empty
Empty
empty empty
" "
@ -6036,7 +6035,7 @@ All branches in an `if` must have the same type!
double_binop, double_binop,
indoc!( indoc!(
r" r"
key >= 97 && <= 122 key >= 97 and <= 122
" "
), ),
@r" @r"
@ -6692,17 +6691,20 @@ All branches in an `if` must have the same type!
) )
" "
), ),
@r" @r###"
UNFINISHED FUNCTION in tmp/unfinished_closure_pattern_in_parens/Test.roc MISSING ARROW in tmp/unfinished_closure_pattern_in_parens/Test.roc
I was partway through parsing a function, but I got stuck here: I am partway through parsing a function argument list, but I got stuck
here:
4 x = \( a 4 x = \( a
5 ) 5 )
6
7
^ ^
I just saw a pattern, so I was expecting to see a -> next. I was expecting a -> next.
" "###
); );
test_report!( test_report!(
@ -11215,10 +11217,10 @@ All branches in an `if` must have the same type!
import Decode exposing [decoder] import Decode exposing [decoder]
main = my_decoder : Decoder (_ -> _) _
my_decoder : Decoder (a -> a) fmt where fmt implements DecoderFormatting
my_decoder = decoder my_decoder = decoder
main =
my_decoder my_decoder
"# "#
), ),
@ -11227,12 +11229,12 @@ All branches in an `if` must have the same type!
This expression has a type that does not implement the abilities it's expected to: This expression has a type that does not implement the abilities it's expected to:
7 my_decoder = decoder 6 my_decoder = decoder
^^^^^^^ ^^^^^^^
I can't generate an implementation of the `Decoding` ability for I can't generate an implementation of the `Decoding` ability for
a -> a * -> *
Note: `Decoding` cannot be generated for functions. Note: `Decoding` cannot be generated for functions.
" "
@ -11248,10 +11250,10 @@ All branches in an `if` must have the same type!
A := {} A := {}
main = my_decoder : Decoder {x : A} _
my_decoder : Decoder {x : A} fmt where fmt implements DecoderFormatting
my_decoder = decoder my_decoder = decoder
main =
my_decoder my_decoder
"# "#
), ),
@ -11260,7 +11262,7 @@ All branches in an `if` must have the same type!
This expression has a type that does not implement the abilities it's expected to: This expression has a type that does not implement the abilities it's expected to:
9 my_decoder = decoder 8 my_decoder = decoder
^^^^^^^ ^^^^^^^
I can't generate an implementation of the `Decoding` ability for I can't generate an implementation of the `Decoding` ability for
@ -11511,11 +11513,10 @@ All branches in an `if` must have the same type!
import Decode exposing [decoder] import Decode exposing [decoder]
main = my_decoder : Decoder {x : Str, y ? Str} _
my_decoder : Decoder {x : Str, y ? Str} fmt where fmt implements DecoderFormatting
my_decoder = decoder my_decoder = decoder
my_decoder main = my_decoder
"# "#
), ),
@r" @r"
@ -11523,7 +11524,7 @@ All branches in an `if` must have the same type!
This expression has a type that does not implement the abilities it's expected to: This expression has a type that does not implement the abilities it's expected to:
7 my_decoder = decoder 6 my_decoder = decoder
^^^^^^^ ^^^^^^^
I can't generate an implementation of the `Decoding` ability for I can't generate an implementation of the `Decoding` ability for
@ -14108,11 +14109,10 @@ All branches in an `if` must have the same type!
import Decode exposing [decoder] import Decode exposing [decoder]
main = my_decoder : Decoder (U32, Str) _
my_decoder : Decoder (U32, Str) fmt where fmt implements DecoderFormatting
my_decoder = decoder my_decoder = decoder
my_decoder main = my_decoder
"# "#
) )
); );
@ -14125,11 +14125,10 @@ All branches in an `if` must have the same type!
import Decode exposing [decoder] import Decode exposing [decoder]
main = my_decoder : Decoder (U32, {} -> {}) _
my_decoder : Decoder (U32, {} -> {}) fmt where fmt implements DecoderFormatting
my_decoder = decoder my_decoder = decoder
my_decoder main = my_decoder
"# "#
), ),
@r" @r"
@ -14137,7 +14136,7 @@ All branches in an `if` must have the same type!
This expression has a type that does not implement the abilities it's expected to: This expression has a type that does not implement the abilities it's expected to:
7 my_decoder = decoder 6 my_decoder = decoder
^^^^^^^ ^^^^^^^
I can't generate an implementation of the `Decoding` ability for I can't generate an implementation of the `Decoding` ability for
@ -15994,4 +15993,66 @@ All branches in an `if` must have the same type!
Str -> {} Str -> {}
"# "#
); );
test_report!(
invalid_generic_literal,
indoc!(
r#"
module [v]
v : *
v = 1
"#
),
@r###"
TYPE MISMATCH in /code/proj/Main.roc
Something is off with the body of the `v` definition:
3 v : *
4 v = 1
^
The body is a number of type:
Num *
But the type annotation on `v` says it should be:
*
Tip: The type annotation uses the type variable `*` to say that this
definition can produce any type of value. But in the body I see that
it will only produce a `Num` value of a single specific type. Maybe
change the type annotation to be more specific? Maybe change the code
to be more general?
"###
);
test_report!(
invalid_generic_literal_list,
indoc!(
r#"
module [v]
v : List *
v = []
"#
),
@r###"
TYPE VARIABLE IS NOT GENERIC in /code/proj/Main.roc
This type variable has a single type:
3 v : List *
^
Type variables tell me that they can be used with any type, but they
can only be used with functions. All other values have exactly one
type.
Hint: If you would like the type to be inferred for you, use an
underscore _ instead.
"###
);
} }

View file

@ -10,6 +10,7 @@ version.workspace = true
[dependencies] [dependencies]
roc_builtins.workspace = true roc_builtins.workspace = true
roc_can.workspace = true roc_can.workspace = true
roc_can_solo.workspace = true
roc_work.workspace = true roc_work.workspace = true
roc_checkmate.workspace = true roc_checkmate.workspace = true
roc_collections.workspace = true roc_collections.workspace = true
@ -39,6 +40,8 @@ bumpalo.workspace = true
crossbeam.workspace = true crossbeam.workspace = true
parking_lot.workspace = true parking_lot.workspace = true
tempfile.workspace = true tempfile.workspace = true
base64-url.workspace = true
blake3.workspace = true
[dev-dependencies] [dev-dependencies]
roc_test_utils_dir.workspace = true roc_test_utils_dir.workspace = true

View file

@ -15,11 +15,14 @@ use parking_lot::Mutex;
use roc_builtins::roc::module_source; use roc_builtins::roc::module_source;
use roc_can::abilities::{AbilitiesStore, PendingAbilitiesStore, ResolvedImpl}; use roc_can::abilities::{AbilitiesStore, PendingAbilitiesStore, ResolvedImpl};
use roc_can::constraint::{Constraint as ConstraintSoa, Constraints, TypeOrVar}; use roc_can::constraint::{Constraint as ConstraintSoa, Constraints, TypeOrVar};
use roc_can::env::Env;
use roc_can::expr::{Declarations, ExpectLookup, PendingDerives}; use roc_can::expr::{Declarations, ExpectLookup, PendingDerives};
use roc_can::module::{ use roc_can::module::{
canonicalize_module_defs, ExposedByModule, ExposedForModule, ExposedModuleTypes, Module, canonicalize_module_defs, ExposedByModule, ExposedForModule, ExposedModuleTypes, Module,
ModuleParams, ResolvedImplementations, TypeState, ModuleParams, ResolvedImplementations, TypeState,
}; };
use roc_can::scope::Scope;
use roc_can_solo::module::{solo_canonicalize_module_defs, SoloCanOutput};
use roc_collections::soa::slice_extend_new; use roc_collections::soa::slice_extend_new;
use roc_collections::{default_hasher, BumpMap, MutMap, MutSet, VecMap, VecSet}; use roc_collections::{default_hasher, BumpMap, MutMap, MutSet, VecMap, VecSet};
use roc_constrain::module::constrain_module; use roc_constrain::module::constrain_module;
@ -204,9 +207,20 @@ fn start_phase<'a>(
root_type: state.root_type.clone(), root_type: state.root_type.clone(),
} }
} }
Phase::SoloCanonicalize => {
// canonicalize the file
let parsed = state.module_cache.parsed.get(&module_id).unwrap().clone();
BuildTask::SoloCanonicalize { parsed }
}
Phase::CanonicalizeAndConstrain => { Phase::CanonicalizeAndConstrain => {
// canonicalize the file // canonicalize the file
let parsed = state.module_cache.parsed.remove(&module_id).unwrap(); let parsed = state.module_cache.parsed.remove(&module_id).unwrap();
let solo_can_output = state
.module_cache
.solo_canonicalized
.remove(&module_id)
.unwrap();
let deps_by_name = &parsed.deps_by_name; let deps_by_name = &parsed.deps_by_name;
let num_deps = deps_by_name.len(); let num_deps = deps_by_name.len();
@ -318,6 +332,7 @@ fn start_phase<'a>(
exposed_module_ids: state.exposed_modules, exposed_module_ids: state.exposed_modules,
exec_mode: state.exec_mode, exec_mode: state.exec_mode,
imported_module_params, imported_module_params,
solo_can_output,
} }
} }
@ -577,6 +592,7 @@ enum Msg<'a> {
Many(Vec<Msg<'a>>), Many(Vec<Msg<'a>>),
Header(ModuleHeader<'a>), Header(ModuleHeader<'a>),
Parsed(ParsedModule<'a>), Parsed(ParsedModule<'a>),
SoloCanonicalized(ModuleId, CanSolo<'a>),
CanonicalizedAndConstrained(CanAndCon), CanonicalizedAndConstrained(CanAndCon),
SolvedTypes { SolvedTypes {
module_id: ModuleId, module_id: ModuleId,
@ -651,6 +667,9 @@ enum Msg<'a> {
IncorrectModuleName(FileError<'a, IncorrectModuleName<'a>>), IncorrectModuleName(FileError<'a, IncorrectModuleName<'a>>),
} }
#[derive(Debug)]
struct CanSolo<'a>(SoloCanOutput<'a>);
#[derive(Debug)] #[derive(Debug)]
struct CanAndCon { struct CanAndCon {
constrained_module: ConstrainedModule, constrained_module: ConstrainedModule,
@ -890,6 +909,9 @@ enum BuildTask<'a> {
ident_ids_by_module: SharedIdentIdsByModule, ident_ids_by_module: SharedIdentIdsByModule,
root_type: RootType, root_type: RootType,
}, },
SoloCanonicalize {
parsed: ParsedModule<'a>,
},
CanonicalizeAndConstrain { CanonicalizeAndConstrain {
parsed: ParsedModule<'a>, parsed: ParsedModule<'a>,
qualified_module_ids: PackageModuleIds<'a>, qualified_module_ids: PackageModuleIds<'a>,
@ -901,6 +923,7 @@ enum BuildTask<'a> {
skip_constraint_gen: bool, skip_constraint_gen: bool,
exec_mode: ExecutionMode, exec_mode: ExecutionMode,
imported_module_params: VecMap<ModuleId, ModuleParams>, imported_module_params: VecMap<ModuleId, ModuleParams>,
solo_can_output: SoloCanOutput<'a>,
}, },
Solve { Solve {
module: Module, module: Module,
@ -2411,6 +2434,23 @@ fn update<'a>(
Ok(state) Ok(state)
} }
SoloCanonicalized(module_id, CanSolo(solo_can_output)) => {
log!("solo canonicalized module {:?}", module_id);
state
.module_cache
.solo_canonicalized
.insert(module_id, solo_can_output);
let work = state
.dependencies
.notify(module_id, Phase::SoloCanonicalize);
start_tasks(arena, &mut state, work, injector, worker_wakers)?;
Ok(state)
}
CanonicalizedAndConstrained(CanAndCon { CanonicalizedAndConstrained(CanAndCon {
constrained_module, constrained_module,
canonicalization_problems, canonicalization_problems,
@ -2462,6 +2502,7 @@ fn update<'a>(
Ok(state) Ok(state)
} }
SolvedTypes { SolvedTypes {
module_id, module_id,
ident_ids, ident_ids,
@ -5082,6 +5123,31 @@ fn build_platform_header<'a>(
build_header(info, parse_state, module_ids, module_timing) build_header(info, parse_state, module_ids, module_timing)
} }
#[allow(clippy::unnecessary_wraps)]
fn canonicalize_solo<'a>(arena: &'a Bump, parsed: ParsedModule<'a>) -> CanSolo<'a> {
let canonicalize_solo_start = Instant::now();
let ParsedModule {
module_path,
header_type,
src,
parsed_defs,
mut module_timing,
..
} = parsed;
let parsed_defs = arena.alloc(parsed_defs);
let solo_can_output =
solo_canonicalize_module_defs(arena, header_type, parsed_defs, module_path, src);
let canonicalize_solo_end = Instant::now();
module_timing.canonicalize_solo = canonicalize_solo_end.duration_since(canonicalize_solo_start);
CanSolo(solo_can_output)
}
#[allow(clippy::unnecessary_wraps)] #[allow(clippy::unnecessary_wraps)]
fn canonicalize_and_constrain<'a>( fn canonicalize_and_constrain<'a>(
arena: &'a Bump, arena: &'a Bump,
@ -5095,21 +5161,21 @@ fn canonicalize_and_constrain<'a>(
exposed_module_ids: &[ModuleId], exposed_module_ids: &[ModuleId],
exec_mode: ExecutionMode, exec_mode: ExecutionMode,
imported_module_params: VecMap<ModuleId, ModuleParams>, imported_module_params: VecMap<ModuleId, ModuleParams>,
solo_can_output: SoloCanOutput<'a>,
) -> CanAndCon { ) -> CanAndCon {
let canonicalize_start = Instant::now(); let canonicalize_start = Instant::now();
let ParsedModule { let ParsedModule {
module_id, module_id,
module_path, module_path,
src,
header_type, header_type,
exposed_ident_ids,
parsed_defs, parsed_defs,
initial_scope, initial_scope,
available_modules, available_modules,
mut module_timing, mut module_timing,
symbols_from_requires, symbols_from_requires,
opt_shorthand, opt_shorthand,
exposed_ident_ids,
.. ..
} = parsed; } = parsed;
@ -5117,27 +5183,55 @@ fn canonicalize_and_constrain<'a>(
let _before = roc_types::types::get_type_clone_count(); let _before = roc_types::types::get_type_clone_count();
let parsed_defs_for_docs = parsed_defs.clone(); let parsed_defs_for_docs = parsed_defs.clone();
let parsed_defs = arena.alloc(parsed_defs);
let mut var_store = VarStore::default(); let mut var_store = VarStore::default();
let env = Env::from_solo_can(
arena,
&module_path,
module_id,
&dep_idents,
qualified_module_ids,
solo_can_output.problems,
opt_shorthand,
solo_can_output.src,
solo_can_output.lazy_line_info,
);
let mut scope = Scope::new(
module_id,
qualified_module_ids
.get_name(module_id)
.expect("home module not found")
.as_inner()
.to_owned(),
exposed_ident_ids,
imported_abilities_state,
);
for (name, alias) in aliases.into_iter() {
scope.add_alias(
name,
alias.region,
alias.type_variables,
alias.infer_ext_in_output_variables,
alias.typ,
alias.kind,
);
}
let mut module_output = canonicalize_module_defs( let mut module_output = canonicalize_module_defs(
arena, arena,
parsed_defs,
&header_type, &header_type,
module_id, module_id,
&*arena.alloc(module_path.to_string_lossy()),
src,
qualified_module_ids,
exposed_ident_ids,
&dep_idents,
aliases,
imported_abilities_state,
initial_scope, initial_scope,
exposed_symbols, exposed_symbols,
&symbols_from_requires, &symbols_from_requires,
&mut var_store, &mut var_store,
opt_shorthand, scope,
env,
solo_can_output.loc_defs,
solo_can_output.module_params,
); );
let mut types = Types::new(); let mut types = Types::new();
@ -6237,6 +6331,12 @@ fn run_task<'a>(
ident_ids_by_module, ident_ids_by_module,
root_type, root_type,
), ),
SoloCanonicalize { parsed } => {
let module_id = parsed.module_id;
let solo_can = canonicalize_solo(arena, parsed);
Ok(Msg::SoloCanonicalized(module_id, solo_can))
}
CanonicalizeAndConstrain { CanonicalizeAndConstrain {
parsed, parsed,
qualified_module_ids, qualified_module_ids,
@ -6248,6 +6348,7 @@ fn run_task<'a>(
exposed_module_ids, exposed_module_ids,
exec_mode, exec_mode,
imported_module_params, imported_module_params,
solo_can_output,
} => { } => {
let can_and_con = canonicalize_and_constrain( let can_and_con = canonicalize_and_constrain(
arena, arena,
@ -6261,6 +6362,7 @@ fn run_task<'a>(
exposed_module_ids, exposed_module_ids,
exec_mode, exec_mode,
imported_module_params, imported_module_params,
solo_can_output,
); );
Ok(Msg::CanonicalizedAndConstrained(can_and_con)) Ok(Msg::CanonicalizedAndConstrained(can_and_con))

View file

@ -189,7 +189,7 @@ pub struct MonomorphizedModule<'a> {
pub glue_layouts: GlueLayouts<'a>, pub glue_layouts: GlueLayouts<'a>,
} }
#[derive(Debug)] #[derive(Debug, Clone)]
pub struct ParsedModule<'a> { pub struct ParsedModule<'a> {
pub module_id: ModuleId, pub module_id: ModuleId,
pub module_path: PathBuf, pub module_path: PathBuf,
@ -237,11 +237,12 @@ pub struct ExposedToHost {
pub getters: Vec<Symbol>, pub getters: Vec<Symbol>,
} }
#[derive(Debug)] #[derive(Debug, Clone)]
pub struct ModuleTiming { pub struct ModuleTiming {
pub read_roc_file: Duration, pub read_roc_file: Duration,
pub parse_header: Duration, pub parse_header: Duration,
pub parse_body: Duration, pub parse_body: Duration,
pub canonicalize_solo: Duration,
pub canonicalize: Duration, pub canonicalize: Duration,
pub constrain: Duration, pub constrain: Duration,
pub solve: Duration, pub solve: Duration,
@ -261,6 +262,7 @@ impl ModuleTiming {
read_roc_file: Duration::default(), read_roc_file: Duration::default(),
parse_header: Duration::default(), parse_header: Duration::default(),
parse_body: Duration::default(), parse_body: Duration::default(),
canonicalize_solo: Duration::default(),
canonicalize: Duration::default(), canonicalize: Duration::default(),
constrain: Duration::default(), constrain: Duration::default(),
solve: Duration::default(), solve: Duration::default(),
@ -281,6 +283,7 @@ impl ModuleTiming {
read_roc_file, read_roc_file,
parse_header, parse_header,
parse_body, parse_body,
canonicalize_solo,
canonicalize, canonicalize,
constrain, constrain,
solve, solve,
@ -297,6 +300,7 @@ impl ModuleTiming {
.checked_sub(*find_specializations)? .checked_sub(*find_specializations)?
.checked_sub(*solve)? .checked_sub(*solve)?
.checked_sub(*constrain)? .checked_sub(*constrain)?
.checked_sub(*canonicalize_solo)?
.checked_sub(*canonicalize)? .checked_sub(*canonicalize)?
.checked_sub(*parse_body)? .checked_sub(*parse_body)?
.checked_sub(*parse_header)? .checked_sub(*parse_header)?

View file

@ -5,6 +5,7 @@ use crate::module::{
}; };
use roc_can::abilities::PendingAbilitiesStore; use roc_can::abilities::PendingAbilitiesStore;
use roc_can::module::ModuleParams; use roc_can::module::ModuleParams;
use roc_can_solo::module::SoloCanOutput;
use roc_collections::{MutMap, MutSet, VecMap}; use roc_collections::{MutMap, MutSet, VecMap};
use roc_module::ident::ModuleName; use roc_module::ident::ModuleName;
use roc_module::symbol::{ModuleId, PQModuleName, Symbol}; use roc_module::symbol::{ModuleId, PQModuleName, Symbol};
@ -26,6 +27,7 @@ pub(crate) struct ModuleCache<'a> {
pub(crate) parsed: MutMap<ModuleId, ParsedModule<'a>>, pub(crate) parsed: MutMap<ModuleId, ParsedModule<'a>>,
pub(crate) aliases: MutMap<ModuleId, MutMap<Symbol, (bool, Alias)>>, pub(crate) aliases: MutMap<ModuleId, MutMap<Symbol, (bool, Alias)>>,
pub(crate) pending_abilities: MutMap<ModuleId, PendingAbilitiesStore>, pub(crate) pending_abilities: MutMap<ModuleId, PendingAbilitiesStore>,
pub(crate) solo_canonicalized: MutMap<ModuleId, SoloCanOutput<'a>>,
pub(crate) constrained: MutMap<ModuleId, ConstrainedModule>, pub(crate) constrained: MutMap<ModuleId, ConstrainedModule>,
pub(crate) module_params: MutMap<ModuleId, ModuleParams>, pub(crate) module_params: MutMap<ModuleId, ModuleParams>,
pub(crate) typechecked: MutMap<ModuleId, TypeCheckedModule<'a>>, pub(crate) typechecked: MutMap<ModuleId, TypeCheckedModule<'a>>,
@ -45,6 +47,8 @@ pub(crate) struct ModuleCache<'a> {
pub(crate) type_problems: MutMap<ModuleId, Vec<TypeError>>, pub(crate) type_problems: MutMap<ModuleId, Vec<TypeError>>,
pub(crate) sources: MutMap<ModuleId, (PathBuf, &'a str)>, pub(crate) sources: MutMap<ModuleId, (PathBuf, &'a str)>,
#[allow(dead_code)]
pub(crate) content_hashes: MutMap<ModuleId, String>,
} }
impl<'a> ModuleCache<'a> { impl<'a> ModuleCache<'a> {
@ -65,6 +69,19 @@ impl<'a> ModuleCache<'a> {
pub fn has_errors(&self) -> bool { pub fn has_errors(&self) -> bool {
self.has_can_errors() || self.has_type_errors() self.has_can_errors() || self.has_type_errors()
} }
#[allow(dead_code)]
pub fn add_module_content_hash(&mut self, module_id: ModuleId, contents: &str) -> String {
let hash = Self::hash_contents(contents);
self.content_hashes.insert(module_id, hash.clone());
hash
}
#[allow(dead_code)]
pub fn hash_contents(contents: &str) -> String {
base64_url::encode(blake3::hash(contents.as_bytes()).as_bytes())
}
} }
impl Default for ModuleCache<'_> { impl Default for ModuleCache<'_> {
@ -101,6 +118,7 @@ impl Default for ModuleCache<'_> {
parsed: Default::default(), parsed: Default::default(),
aliases: Default::default(), aliases: Default::default(),
pending_abilities: Default::default(), pending_abilities: Default::default(),
solo_canonicalized: Default::default(),
constrained: Default::default(), constrained: Default::default(),
module_params: Default::default(), module_params: Default::default(),
typechecked: Default::default(), typechecked: Default::default(),
@ -116,6 +134,7 @@ impl Default for ModuleCache<'_> {
can_problems: Default::default(), can_problems: Default::default(),
type_problems: Default::default(), type_problems: Default::default(),
sources: Default::default(), sources: Default::default(),
content_hashes: Default::default(),
} }
} }
} }

View file

@ -24,7 +24,7 @@ succeed = \x -> Identity(x)
with_default = Res.with_default with_default = Res.with_default
yay : Res.Res {} err yay : Res.Res {} _
yay = yay =
ok = Ok("foo") ok = Ok("foo")

View file

@ -24,7 +24,7 @@ succeed = \x -> Identity(x)
with_default = Res.with_default with_default = Res.with_default
yay : Res.Res {} err yay : Res.Res {} _
yay = yay =
ok = Ok("foo") ok = Ok("foo")

View file

@ -271,11 +271,13 @@ fn load_fixture(
); );
} }
assert!(loaded_module assert_eq!(
loaded_module
.type_problems .type_problems
.remove(&home) .remove(&home)
.unwrap_or_default() .unwrap_or_default(),
.is_empty()); Vec::new()
);
let expected_name = loaded_module let expected_name = loaded_module
.interns .interns
@ -433,11 +435,13 @@ fn module_with_deps() {
loaded_module.can_problems.remove(&home).unwrap_or_default(), loaded_module.can_problems.remove(&home).unwrap_or_default(),
Vec::new() Vec::new()
); );
assert!(loaded_module assert_eq!(
loaded_module
.type_problems .type_problems
.remove(&home) .remove(&home)
.unwrap_or_default() .unwrap_or_default(),
.is_empty(),); Vec::new()
);
let mut def_count = 0; let mut def_count = 0;
let declarations = loaded_module.declarations_by_id.remove(&home).unwrap(); let declarations = loaded_module.declarations_by_id.remove(&home).unwrap();

View file

@ -105,7 +105,8 @@ pub fn remove_module_param_arguments(
| TypeError::ExpectedEffectful(_, _) | TypeError::ExpectedEffectful(_, _)
| TypeError::UnsuffixedEffectfulFunction(_, _) | TypeError::UnsuffixedEffectfulFunction(_, _)
| TypeError::SuffixedPureFunction(_, _) | TypeError::SuffixedPureFunction(_, _)
| TypeError::InvalidTryTarget(_, _, _) => {} | TypeError::InvalidTryTarget(_, _, _)
| TypeError::TypeIsNotGeneralized(..) => {}
} }
} }
} }
@ -213,6 +214,7 @@ fn drop_last_argument(err_type: &mut ErrorType) {
| ErrorType::Alias(_, _, _, _) | ErrorType::Alias(_, _, _, _)
| ErrorType::Range(_) | ErrorType::Range(_)
| ErrorType::Error | ErrorType::Error
| ErrorType::EffectfulFunc => {} | ErrorType::EffectfulFunc
| ErrorType::InferenceVar => {}
} }
} }

View file

@ -62,8 +62,8 @@ const DISPLAY_STRINGS: [(BinOp, &str); 18] = [
(GreaterThan, ">"), (GreaterThan, ">"),
(LessThanOrEq, "<="), (LessThanOrEq, "<="),
(GreaterThanOrEq, ">="), (GreaterThanOrEq, ">="),
(And, "&&"), (And, "and"),
(Or, "||"), (Or, "or"),
]; ];
#[derive(Clone, Copy, Debug, PartialEq, Eq)] #[derive(Clone, Copy, Debug, PartialEq, Eq)]
@ -199,7 +199,7 @@ pub enum Associativity {
/// right-associative operators: /// right-associative operators:
/// ///
/// exponentiation: ^ /// exponentiation: ^
/// boolean: && || /// boolean: and or
/// application: <| /// application: <|
RightAssociative, RightAssociative,

View file

@ -27,6 +27,7 @@ pub enum LowLevel {
StrReserve, StrReserve,
StrWithCapacity, StrWithCapacity,
StrReleaseExcessCapacity, StrReleaseExcessCapacity,
StrWithAsciiLowercased,
ListLenUsize, ListLenUsize,
ListLenU64, ListLenU64,
ListWithCapacity, ListWithCapacity,
@ -110,8 +111,6 @@ pub enum LowLevel {
NumF64FromParts, NumF64FromParts,
Eq, Eq,
NotEq, NotEq,
And,
Or,
Not, Not,
Hash, Hash,
PtrCast, PtrCast,
@ -269,6 +268,7 @@ map_symbol_to_lowlevel! {
StrToNum <= STR_TO_NUM; StrToNum <= STR_TO_NUM;
StrWithCapacity <= STR_WITH_CAPACITY; StrWithCapacity <= STR_WITH_CAPACITY;
StrReleaseExcessCapacity <= STR_RELEASE_EXCESS_CAPACITY; StrReleaseExcessCapacity <= STR_RELEASE_EXCESS_CAPACITY;
StrWithAsciiLowercased <= STR_WITH_ASCII_LOWERCASED;
ListLenU64 <= LIST_LEN_U64; ListLenU64 <= LIST_LEN_U64;
ListLenUsize <= LIST_LEN_USIZE; ListLenUsize <= LIST_LEN_USIZE;
ListGetCapacity <= LIST_CAPACITY; ListGetCapacity <= LIST_CAPACITY;
@ -345,8 +345,6 @@ map_symbol_to_lowlevel! {
NumF64FromParts <= NUM_F64_FROM_PARTS; NumF64FromParts <= NUM_F64_FROM_PARTS;
Eq <= BOOL_STRUCTURAL_EQ; Eq <= BOOL_STRUCTURAL_EQ;
NotEq <= BOOL_STRUCTURAL_NOT_EQ; NotEq <= BOOL_STRUCTURAL_NOT_EQ;
And <= BOOL_AND;
Or <= BOOL_OR;
Not <= BOOL_NOT; Not <= BOOL_NOT;
Unreachable <= LIST_UNREACHABLE; Unreachable <= LIST_UNREACHABLE;
DictPseudoSeed <= DICT_PSEUDO_SEED; DictPseudoSeed <= DICT_PSEUDO_SEED;

View file

@ -986,6 +986,10 @@ macro_rules! define_builtins {
self.to_zero_indexed() < $total self.to_zero_indexed() < $total
} }
pub const fn first_after_builtins() -> Self {
ModuleId::from_zero_indexed($total)
}
$( $(
pub const $module_const: ModuleId = ModuleId::from_zero_indexed($module_id); pub const $module_const: ModuleId = ModuleId::from_zero_indexed($module_id);
)+ )+
@ -1355,16 +1359,14 @@ define_builtins! {
0 BOOL_BOOL: "Bool" exposed_type=true // the Bool.Bool type alias 0 BOOL_BOOL: "Bool" exposed_type=true // the Bool.Bool type alias
1 BOOL_FALSE: "false" 1 BOOL_FALSE: "false"
2 BOOL_TRUE: "true" 2 BOOL_TRUE: "true"
3 BOOL_AND: "and" 3 BOOL_NOT: "not"
4 BOOL_OR: "or" 4 BOOL_XOR: "xor"
5 BOOL_NOT: "not" 5 BOOL_NEQ: "is_not_eq"
6 BOOL_XOR: "xor" 6 BOOL_EQ: "Eq" exposed_type=true
7 BOOL_NEQ: "is_not_eq" 7 BOOL_IS_EQ: "is_eq"
8 BOOL_EQ: "Eq" exposed_type=true 8 BOOL_IS_EQ_IMPL: "bool_is_eq"
9 BOOL_IS_EQ: "is_eq" unexposed 9 BOOL_STRUCTURAL_EQ: "structural_eq"
10 BOOL_IS_EQ_IMPL: "bool_is_eq" unexposed 10 BOOL_STRUCTURAL_NOT_EQ: "structural_not_eq"
unexposed 11 BOOL_STRUCTURAL_EQ: "structural_eq"
unexposed 12 BOOL_STRUCTURAL_NOT_EQ: "structural_not_eq"
} }
5 STR: "Str" => { 5 STR: "Str" => {
0 STR_STR: "Str" exposed_apply_type=true // the Str.Str type alias 0 STR_STR: "Str" exposed_apply_type=true // the Str.Str type alias
@ -1418,10 +1420,11 @@ define_builtins! {
48 STR_RELEASE_EXCESS_CAPACITY: "release_excess_capacity" 48 STR_RELEASE_EXCESS_CAPACITY: "release_excess_capacity"
49 STR_DROP_PREFIX: "drop_prefix" 49 STR_DROP_PREFIX: "drop_prefix"
50 STR_DROP_SUFFIX: "drop_suffix" 50 STR_DROP_SUFFIX: "drop_suffix"
51 STR_FROM_UTF16: "from_utf16" 51 STR_WITH_ASCII_LOWERCASED: "with_ascii_lowercased"
52 STR_FROM_UTF16_LOSSY: "from_utf16_lossy" 52 STR_FROM_UTF16: "from_utf16"
53 STR_FROM_UTF32: "from_utf32" 53 STR_FROM_UTF16_LOSSY: "from_utf16_lossy"
54 STR_FROM_UTF32_LOSSY: "from_utf32_lossy" 54 STR_FROM_UTF32: "from_utf32"
55 STR_FROM_UTF32_LOSSY: "from_utf32_lossy"
} }
6 LIST: "List" => { 6 LIST: "List" => {
0 LIST_LIST: "List" exposed_apply_type=true // the List.List type alias 0 LIST_LIST: "List" exposed_apply_type=true // the List.List type alias

View file

@ -1549,6 +1549,7 @@ fn low_level_no_rc(lowlevel: &LowLevel) -> RC {
ListPrepend => RC::Rc, ListPrepend => RC::Rc,
StrJoinWith => RC::NoRc, StrJoinWith => RC::NoRc,
ListSortWith => RC::Rc, ListSortWith => RC::Rc,
StrWithAsciiLowercased => RC::Rc,
ListAppendUnsafe ListAppendUnsafe
| ListReserve | ListReserve
@ -1562,7 +1563,7 @@ fn low_level_no_rc(lowlevel: &LowLevel) -> RC {
Eq | NotEq => RC::NoRc, Eq | NotEq => RC::NoRc,
And | Or | NumAdd | NumAddWrap | NumAddChecked | NumAddSaturated | NumSub | NumSubWrap NumAdd | NumAddWrap | NumAddChecked | NumAddSaturated | NumSub | NumSubWrap
| NumSubChecked | NumSubSaturated | NumMul | NumMulWrap | NumMulSaturated | NumSubChecked | NumSubSaturated | NumMul | NumMulWrap | NumMulSaturated
| NumMulChecked | NumGt | NumGte | NumLt | NumLte | NumCompare | NumDivFrac | NumMulChecked | NumGt | NumGte | NumLt | NumLte | NumCompare | NumDivFrac
| NumDivTruncUnchecked | NumDivCeilUnchecked | NumRemUnchecked | NumIsMultipleOf | NumDivTruncUnchecked | NumDivCeilUnchecked | NumRemUnchecked | NumIsMultipleOf

View file

@ -1258,10 +1258,11 @@ pub(crate) fn lowlevel_borrow_signature(op: LowLevel) -> &'static [Ownership] {
StrReleaseExcessCapacity => &[OWNED], StrReleaseExcessCapacity => &[OWNED],
ListIncref => &[OWNED], ListIncref => &[OWNED],
ListDecref => &[OWNED], ListDecref => &[OWNED],
StrWithAsciiLowercased => &[OWNED],
Eq | NotEq => &[BORROWED, BORROWED], Eq | NotEq => &[BORROWED, BORROWED],
And | Or | NumAdd | NumAddWrap | NumAddChecked | NumAddSaturated | NumSub | NumSubWrap NumAdd | NumAddWrap | NumAddChecked | NumAddSaturated | NumSub | NumSubWrap
| NumSubChecked | NumSubSaturated | NumMul | NumMulWrap | NumMulSaturated | NumSubChecked | NumSubSaturated | NumMul | NumMulWrap | NumMulSaturated
| NumMulChecked | NumGt | NumGte | NumLt | NumLte | NumCompare | NumDivFrac | NumMulChecked | NumGt | NumGte | NumLt | NumLte | NumCompare | NumDivFrac
| NumDivTruncUnchecked | NumDivCeilUnchecked | NumRemUnchecked | NumIsMultipleOf | NumDivTruncUnchecked | NumDivCeilUnchecked | NumRemUnchecked | NumIsMultipleOf

View file

@ -49,7 +49,15 @@ pub fn apply_trmc<'a, 'i>(
let env = &mut env; let env = &mut env;
for proc in procs.values_mut() { // TODO temporary workaround for #7531, remove this cloning and sorting once that is fixed
let clone_procs = procs.clone();
let mut procs_key_value_list = clone_procs.iter().collect::<std::vec::Vec<_>>();
procs_key_value_list.sort_by(|a, b| a.0 .0.cmp(&b.0 .0));
for (key, _) in procs_key_value_list {
let proc = procs.get_mut(key).unwrap();
use self::SelfRecursive::*; use self::SelfRecursive::*;
if let SelfRecursive(id) = proc.is_self_recursive { if let SelfRecursive(id) = proc.is_self_recursive {
let trmc_candidate_symbols = trmc_candidates(env.interner, proc); let trmc_candidate_symbols = trmc_candidates(env.interner, proc);

View file

@ -738,7 +738,7 @@ fn parse_stmt_operator_chain<'a>(
| Expr::Apply( | Expr::Apply(
Loc { Loc {
region: _, region: _,
value: Expr::Tag(..) value: Expr::Tag(_)
}, },
&[], &[],
_ _
@ -752,7 +752,7 @@ fn parse_stmt_operator_chain<'a>(
// try an operator // try an operator
return parse_stmt_after_apply( return parse_stmt_after_apply(
arena, arena,
state.clone(), state,
min_indent, min_indent,
call_min_indent, call_min_indent,
expr_state, expr_state,
@ -1934,43 +1934,6 @@ fn parse_stmt_after_apply<'a>(
} }
} }
// #[allow(clippy::too_many_arguments)]
// fn parse_expr_after_apply<'a>(
// arena: &'a Bump,
// state: State<'a>,
// min_indent: u32,
// call_min_indent: u32,
// check_for_arrow: CheckForArrow,
// check_for_defs: bool,
// mut expr_state: ExprState<'a>,
// before_op: State<'a>,
// initial_state: State<'a>,
// ) -> Result<(Progress, Expr<'a>, State<'a>), (Progress, EExpr<'a>)> {
// match loc(bin_op(check_for_defs)).parse(arena, state.clone(), call_min_indent) {
// Err((MadeProgress, f)) => Err((MadeProgress, f)),
// Ok((_, loc_op, state)) => {
// expr_state.consume_spaces(arena);
// let initial_state = before_op;
// parse_expr_operator(
// arena,
// state,
// min_indent,
// call_min_indent,
// options,
// check_for_defs,
// expr_state,
// loc_op,
// initial_state,
// )
// }
// Err((NoProgress, _)) => {
// let expr = parse_expr_final(expr_state, arena);
// // roll back space parsing
// Ok((MadeProgress, expr, initial_state))
// }
// }
// }
#[allow(clippy::too_many_arguments)] #[allow(clippy::too_many_arguments)]
fn parse_apply_arg<'a>( fn parse_apply_arg<'a>(
arena: &'a Bump, arena: &'a Bump,
@ -2340,16 +2303,18 @@ pub fn parse_top_level_defs<'a>(
fn closure_help<'a>(check_for_arrow: CheckForArrow) -> impl Parser<'a, Expr<'a>, EClosure<'a>> { fn closure_help<'a>(check_for_arrow: CheckForArrow) -> impl Parser<'a, Expr<'a>, EClosure<'a>> {
one_of!( one_of!(
closure_new_syntax_help(), closure_new_syntax_help(check_for_arrow),
closure_old_syntax_help(check_for_arrow), closure_old_syntax_help(check_for_arrow),
) )
} }
fn closure_new_syntax_help<'a>() -> impl Parser<'a, Expr<'a>, EClosure<'a>> { fn closure_new_syntax_help<'a>(
check_for_arrow: CheckForArrow,
) -> impl Parser<'a, Expr<'a>, EClosure<'a>> {
map_with_arena( map_with_arena(
indented_seq_skip_first( skip_first(
error_on_pizza(byte_indent(b'|', EClosure::Bar), EClosure::Start), error_on_pizza(byte_indent(b'|', EClosure::Bar), EClosure::Start),
and( reset_min_indent(and(
sep_by1_e( sep_by1_e(
byte_indent(b',', EClosure::Comma), byte_indent(b',', EClosure::Comma),
space0_around_ee( space0_around_ee(
@ -2363,14 +2328,9 @@ fn closure_new_syntax_help<'a>() -> impl Parser<'a, Expr<'a>, EClosure<'a>> {
// Parse the -> which separates params from body // Parse the -> which separates params from body
byte(b'|', EClosure::Bar), byte(b'|', EClosure::Bar),
// Parse the body // Parse the body
block( block(check_for_arrow, true, EClosure::IndentBody, EClosure::Body),
CheckForArrow(false),
true,
EClosure::IndentBody,
EClosure::Body,
),
),
), ),
)),
), ),
|arena: &'a Bump, (params, body)| { |arena: &'a Bump, (params, body)| {
let params: Vec<'a, Loc<Pattern<'a>>> = params; let params: Vec<'a, Loc<Pattern<'a>>> = params;
@ -2386,12 +2346,12 @@ fn closure_old_syntax_help<'a>(
// closure_help_help(options) // closure_help_help(options)
map_with_arena( map_with_arena(
// After the first token, all other tokens must be indented past the start of the line // After the first token, all other tokens must be indented past the start of the line
indented_seq_skip_first( skip_first(
// All closures start with a '\' - e.g. (\x -> x + 1) // All closures start with a '\' - e.g. (\x -> x + 1)
byte_indent(b'\\', EClosure::Start), byte_indent(b'\\', EClosure::Start),
// Once we see the '\', we're committed to parsing this as a closure. // Once we see the '\', we're committed to parsing this as a closure.
// It may turn out to be malformed, but it is definitely a closure. // It may turn out to be malformed, but it is definitely a closure.
and( reset_min_indent(and(
// Parse the params // Parse the params
// Params are comma-separated // Params are comma-separated
sep_by1_e( sep_by1_e(
@ -2409,7 +2369,7 @@ fn closure_old_syntax_help<'a>(
// Parse the body // Parse the body
block(check_for_arrow, true, EClosure::IndentBody, EClosure::Body), block(check_for_arrow, true, EClosure::IndentBody, EClosure::Body),
), ),
), )),
), ),
|arena: &'a Bump, (params, body)| { |arena: &'a Bump, (params, body)| {
let params: Vec<'a, Loc<Pattern<'a>>> = params; let params: Vec<'a, Loc<Pattern<'a>>> = params;
@ -4031,7 +3991,7 @@ enum OperatorOrDef {
} }
fn bin_op<'a>(check_for_defs: bool) -> impl Parser<'a, BinOp, EExpr<'a>> { fn bin_op<'a>(check_for_defs: bool) -> impl Parser<'a, BinOp, EExpr<'a>> {
move |_, state: State<'a>, min_indent| { (move |_, state: State<'a>, min_indent| {
let start = state.pos(); let start = state.pos();
let (_, op, state) = operator_help(EExpr::Start, EExpr::BadOperator, state, min_indent)?; let (_, op, state) = operator_help(EExpr::Start, EExpr::BadOperator, state, min_indent)?;
let err_progress = if check_for_defs { let err_progress = if check_for_defs {
@ -4049,7 +4009,8 @@ fn bin_op<'a>(check_for_defs: bool) -> impl Parser<'a, BinOp, EExpr<'a>> {
Err((err_progress, EExpr::BadOperator(":=", start))) Err((err_progress, EExpr::BadOperator(":=", start)))
} }
} }
} })
.trace("bin_op")
} }
fn operator<'a>() -> impl Parser<'a, OperatorOrDef, EExpr<'a>> { fn operator<'a>() -> impl Parser<'a, OperatorOrDef, EExpr<'a>> {
@ -4069,6 +4030,24 @@ where
G: Fn(&'a str, Position) -> E, G: Fn(&'a str, Position) -> E,
E: 'a, E: 'a,
{ {
match *state.bytes() {
[b'o', b'r', ..] => {
return Ok((
MadeProgress,
OperatorOrDef::BinOp(BinOp::Or),
state.advance(2),
))
}
[b'a', b'n', b'd', ..] => {
return Ok((
MadeProgress,
OperatorOrDef::BinOp(BinOp::And),
state.advance(3),
))
}
_ => {}
}
let chomped = chomp_ops(state.bytes()); let chomped = chomp_ops(state.bytes());
macro_rules! good { macro_rules! good {
@ -4125,6 +4104,7 @@ where
"<=" => good!(OperatorOrDef::BinOp(BinOp::LessThanOrEq), 2), "<=" => good!(OperatorOrDef::BinOp(BinOp::LessThanOrEq), 2),
"&&" => good!(OperatorOrDef::BinOp(BinOp::And), 2), "&&" => good!(OperatorOrDef::BinOp(BinOp::And), 2),
"||" => good!(OperatorOrDef::BinOp(BinOp::Or), 2), "||" => good!(OperatorOrDef::BinOp(BinOp::Or), 2),
"|" => Err((NoProgress, to_error("|", state.pos()))),
"//" => good!(OperatorOrDef::BinOp(BinOp::DoubleSlash), 2), "//" => good!(OperatorOrDef::BinOp(BinOp::DoubleSlash), 2),
"->" => { "->" => {
// makes no progress, so it does not interfere with `_ if isGood -> ...` // makes no progress, so it does not interfere with `_ if isGood -> ...`

View file

@ -927,7 +927,7 @@ impl<'a> HeaderType<'a> {
} }
} }
#[derive(Debug)] #[derive(Debug, Clone)]
pub enum HeaderType<'a> { pub enum HeaderType<'a> {
App { App {
provides: &'a [Loc<ExposedName<'a>>], provides: &'a [Loc<ExposedName<'a>>],

View file

@ -10,6 +10,8 @@ pub const IMPORT: &str = "import";
pub const EXPECT: &str = "expect"; pub const EXPECT: &str = "expect";
pub const RETURN: &str = "return"; pub const RETURN: &str = "return";
pub const CRASH: &str = "crash"; pub const CRASH: &str = "crash";
pub const AND: &str = "and";
pub const OR: &str = "or";
// These keywords are valid in imports // These keywords are valid in imports
pub const EXPOSING: &str = "exposing"; pub const EXPOSING: &str = "exposing";
@ -21,8 +23,8 @@ pub const WHERE: &str = "where";
// These keywords are valid in headers // These keywords are valid in headers
pub const PLATFORM: &str = "platform"; pub const PLATFORM: &str = "platform";
pub const KEYWORDS: [&str; 11] = [ pub const KEYWORDS: [&str; 13] = [
IF, THEN, ELSE, WHEN, AS, IS, DBG, IMPORT, EXPECT, RETURN, CRASH, IF, THEN, ELSE, WHEN, AS, IS, DBG, IMPORT, EXPECT, RETURN, CRASH, AND, OR,
]; ];
pub fn is_allowed_identifier(mut ident: &str) -> bool { pub fn is_allowed_identifier(mut ident: &str) -> bool {

View file

@ -15,15 +15,12 @@ use bumpalo::Bump;
use roc_can::abilities::{AbilitiesStore, MemberSpecializationInfo}; use roc_can::abilities::{AbilitiesStore, MemberSpecializationInfo};
use roc_can::constraint::Constraint::{self, *}; use roc_can::constraint::Constraint::{self, *};
use roc_can::constraint::{ use roc_can::constraint::{
Cycle, FxCallConstraint, FxSuffixConstraint, FxSuffixKind, LetConstraint, OpportunisticResolve, Cycle, FxCallConstraint, FxSuffixConstraint, FxSuffixKind, Generalizable, LetConstraint,
TryTargetConstraint, OpportunisticResolve, TryTargetConstraint,
}; };
use roc_can::expected::{Expected, PExpected}; use roc_can::expected::{Expected, PExpected};
use roc_can::module::ModuleParams; use roc_can::module::ModuleParams;
use roc_collections::{VecMap, VecSet}; use roc_collections::{VecMap, VecSet};
use roc_debug_flags::dbg_do;
#[cfg(debug_assertions)]
use roc_debug_flags::ROC_VERIFY_RIGID_LET_GENERALIZED;
use roc_error_macros::internal_error; use roc_error_macros::internal_error;
use roc_module::ident::IdentSuffix; use roc_module::ident::IdentSuffix;
use roc_module::symbol::{ModuleId, Symbol}; use roc_module::symbol::{ModuleId, Symbol};
@ -32,8 +29,8 @@ use roc_region::all::{Loc, Region};
use roc_solve_problem::TypeError; use roc_solve_problem::TypeError;
use roc_solve_schema::UnificationMode; use roc_solve_schema::UnificationMode;
use roc_types::subs::{ use roc_types::subs::{
self, Content, FlatType, GetSubsSlice, Mark, OptVariable, Rank, Subs, TagExt, UlsOfVar, self, Content, ErrorTypeContext, FlatType, GetSubsSlice, Mark, OptVariable, Rank, Subs, TagExt,
Variable, UlsOfVar, Variable,
}; };
use roc_types::types::{Category, Polarity, Reason, RecordField, Type, TypeExtension, Types, Uls}; use roc_types::types::{Category, Polarity, Reason, RecordField, Type, TypeExtension, Types, Uls};
use roc_unify::unify::{ use roc_unify::unify::{
@ -356,29 +353,13 @@ fn solve(
generalize(env, young_mark, visit_mark, rank.next()); generalize(env, young_mark, visit_mark, rank.next());
debug_assert!(env.pools.get(rank.next()).is_empty(), "variables left over in let-binding scope, but they should all be in a lower scope or generalized now"); debug_assert!(env.pools.get(rank.next()).is_empty(), "variables left over in let-binding scope, but they should all be in a lower scope or generalized now");
// check that things went well let named_variables = &env.constraints[let_con.rigid_vars];
dbg_do!(ROC_VERIFY_RIGID_LET_GENERALIZED, { check_named_variables_are_generalized(
let rigid_vars = &env.constraints[let_con.rigid_vars]; env,
problems,
// NOTE the `subs.redundant` check does not come from elm. named_variables,
// It's unclear whether this is a bug with our implementation let_con.generalizable,
// (something is redundant that shouldn't be) );
// or that it just never came up in elm.
let mut it = rigid_vars
.iter()
.filter(|loc_var| {
let var = loc_var.value;
!env.subs.redundant(var) && env.subs.get_rank(var) != Rank::GENERALIZED
})
.peekable();
if it.peek().is_some() {
let failing: Vec<_> = it.collect();
println!("Rigids {:?}", &rigid_vars);
println!("Failing {failing:?}");
debug_assert!(false);
}
});
let mut new_scope = scope.clone(); let mut new_scope = scope.clone();
for (symbol, loc_var) in local_def_vars.iter() { for (symbol, loc_var) in local_def_vars.iter() {
@ -1636,6 +1617,30 @@ fn solve(
state state
} }
fn check_named_variables_are_generalized(
env: &mut InferenceEnv<'_>,
problems: &mut Vec<TypeError>,
named_variables: &[Loc<Variable>],
generalizable: Generalizable,
) {
for loc_var in named_variables {
let is_generalized = env.subs.get_rank(loc_var.value) == Rank::GENERALIZED;
if !is_generalized {
// TODO: should be OF_PATTERN if on the LHS of a function, otherwise OF_VALUE.
let polarity = Polarity::OF_VALUE;
let ctx = ErrorTypeContext::NON_GENERALIZED_AS_INFERRED;
let error_type = env
.subs
.var_to_error_type_contextual(loc_var.value, ctx, polarity);
problems.push(TypeError::TypeIsNotGeneralized(
loc_var.region,
error_type,
generalizable,
));
}
}
}
fn solve_suffix_fx( fn solve_suffix_fx(
env: &mut InferenceEnv<'_>, env: &mut InferenceEnv<'_>,
problems: &mut Vec<TypeError>, problems: &mut Vec<TypeError>,

View file

@ -2510,13 +2510,15 @@ mod solve_expr {
infer_eq_without_problem( infer_eq_without_problem(
indoc!( indoc!(
r" r"
empty : [Cons a (ConsList a), Nil] as ConsList a ConsList a : [Cons a (ConsList a), Nil]
empty : ConsList _
empty = Nil empty = Nil
empty empty
" "
), ),
"ConsList a", "ConsList *",
); );
} }
@ -3742,7 +3744,7 @@ mod solve_expr {
indoc!( indoc!(
r" r"
\rec -> \rec ->
{ x, y } : { x : I64, y ? Bool }* { x, y } : { x : I64, y ? Bool }_
{ x, y ? Bool.false } = rec { x, y ? Bool.false } = rec
{ x, y } { x, y }
@ -3824,6 +3826,18 @@ mod solve_expr {
); );
} }
#[test]
fn str_with_ascii_lowercased() {
infer_eq_without_problem(
indoc!(
r"
Str.with_ascii_lowercased
"
),
"Str -> Str",
);
}
#[test] #[test]
fn list_take_first() { fn list_take_first() {
infer_eq_without_problem( infer_eq_without_problem(
@ -3909,26 +3923,6 @@ mod solve_expr {
); );
} }
#[test]
fn double_named_rigids() {
infer_eq_without_problem(
indoc!(
r#"
app "test" provides [main] to "./platform"
main : List x
main =
empty : List x
empty = []
empty
"#
),
"List x",
);
}
#[test] #[test]
fn double_tag_application() { fn double_tag_application() {
infer_eq_without_problem( infer_eq_without_problem(

View file

@ -1,7 +1,7 @@
//! Provides types to describe problems that can occur during solving. //! Provides types to describe problems that can occur during solving.
use std::{path::PathBuf, str::Utf8Error}; use std::{path::PathBuf, str::Utf8Error};
use roc_can::constraint::{ExpectEffectfulReason, FxSuffixKind}; use roc_can::constraint::{ExpectEffectfulReason, FxSuffixKind, Generalizable};
use roc_can::expr::TryKind; use roc_can::expr::TryKind;
use roc_can::{ use roc_can::{
constraint::FxCallKind, constraint::FxCallKind,
@ -50,6 +50,7 @@ pub enum TypeError {
UnsuffixedEffectfulFunction(Region, FxSuffixKind), UnsuffixedEffectfulFunction(Region, FxSuffixKind),
SuffixedPureFunction(Region, FxSuffixKind), SuffixedPureFunction(Region, FxSuffixKind),
InvalidTryTarget(Region, ErrorType, TryKind), InvalidTryTarget(Region, ErrorType, TryKind),
TypeIsNotGeneralized(Region, ErrorType, Generalizable),
} }
impl TypeError { impl TypeError {
@ -80,6 +81,7 @@ impl TypeError {
TypeError::UnsuffixedEffectfulFunction(_, _) => Warning, TypeError::UnsuffixedEffectfulFunction(_, _) => Warning,
TypeError::SuffixedPureFunction(_, _) => Warning, TypeError::SuffixedPureFunction(_, _) => Warning,
TypeError::InvalidTryTarget(_, _, _) => RuntimeError, TypeError::InvalidTryTarget(_, _, _) => RuntimeError,
TypeError::TypeIsNotGeneralized(..) => RuntimeError,
} }
} }
@ -101,7 +103,8 @@ impl TypeError {
| TypeError::ExpectedEffectful(region, _) | TypeError::ExpectedEffectful(region, _)
| TypeError::UnsuffixedEffectfulFunction(region, _) | TypeError::UnsuffixedEffectfulFunction(region, _)
| TypeError::SuffixedPureFunction(region, _) | TypeError::SuffixedPureFunction(region, _)
| TypeError::InvalidTryTarget(region, _, _) => Some(*region), | TypeError::InvalidTryTarget(region, _, _)
| TypeError::TypeIsNotGeneralized(region, _, _) => Some(*region),
TypeError::UnfulfilledAbility(ab, ..) => ab.region(), TypeError::UnfulfilledAbility(ab, ..) => ab.region(),
TypeError::Exhaustive(e) => Some(e.region()), TypeError::Exhaustive(e) => Some(e.region()),
TypeError::CircularDef(c) => c.first().map(|ce| ce.symbol_region), TypeError::CircularDef(c) => c.first().map(|ce| ce.symbol_region),

View file

@ -2095,13 +2095,13 @@ mod eq {
LyingEq := U8 implements [Eq {is_eq}] LyingEq := U8 implements [Eq {is_eq}]
is_eq = \@LyingEq m, @LyingEq n -> m != n is_eq = \@LyingEq(m), @LyingEq(n) -> m != n
main = main =
a = @LyingEq 10 a = @LyingEq(10)
b = @LyingEq 5 b = @LyingEq(5)
c = @LyingEq 5 c = @LyingEq(5)
if Bool.is_eq a b && !(Bool.is_eq b c) then if Bool.is_eq(a, b) and !(Bool.is_eq(b, c)) then
"okay" "okay"
else else
"fail" "fail"

View file

@ -121,7 +121,7 @@ fn bool_logic() {
bool2 = Bool.false bool2 = Bool.false
bool3 = !bool1 bool3 = !bool1
(bool1 && bool2) || bool2 && bool3 (bool1 and bool2) or bool2 and bool3
"# "#
), ),
false, false,
@ -132,19 +132,19 @@ fn bool_logic() {
#[test] #[test]
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))] #[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))]
fn and_bool() { fn and_bool() {
assert_evals_to!("Bool.true && Bool.true", true, bool); assert_evals_to!("Bool.true and Bool.true", true, bool);
assert_evals_to!("Bool.true && Bool.false", false, bool); assert_evals_to!("Bool.true and Bool.false", false, bool);
assert_evals_to!("Bool.false && Bool.true", false, bool); assert_evals_to!("Bool.false and Bool.true", false, bool);
assert_evals_to!("Bool.false && Bool.false", false, bool); assert_evals_to!("Bool.false and Bool.false", false, bool);
} }
#[test] #[test]
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))] #[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))]
fn or_bool() { fn or_bool() {
assert_evals_to!("Bool.true || Bool.true", true, bool); assert_evals_to!("Bool.true or Bool.true", true, bool);
assert_evals_to!("Bool.true || Bool.false", true, bool); assert_evals_to!("Bool.true or Bool.false", true, bool);
assert_evals_to!("Bool.false || Bool.true", true, bool); assert_evals_to!("Bool.false or Bool.true", true, bool);
assert_evals_to!("Bool.false || Bool.false", false, bool); assert_evals_to!("Bool.false or Bool.false", false, bool);
} }
#[test] #[test]
@ -544,7 +544,7 @@ fn eq_different_rosetrees() {
cd = c2 == d2 cd = c2 == d2
ab && cd ab and cd
"# "#
), ),
true, true,

View file

@ -662,7 +662,7 @@ fn linked_list_len_1() {
LinkedList a : [Nil, Cons a (LinkedList a)] LinkedList a : [Nil, Cons a (LinkedList a)]
one : LinkedList (Int *) one : LinkedList (Int _)
one = Cons 1 Nil one = Cons 1 Nil
length : LinkedList a -> Int * length : LinkedList a -> Int *
@ -690,7 +690,7 @@ fn linked_list_len_twice_1() {
LinkedList a : [Nil, Cons a (LinkedList a)] LinkedList a : [Nil, Cons a (LinkedList a)]
one : LinkedList (Int *) one : LinkedList (Int _)
one = Cons 1 Nil one = Cons 1 Nil
length : LinkedList a -> Int * length : LinkedList a -> Int *
@ -718,7 +718,7 @@ fn linked_list_len_3() {
LinkedList a : [Nil, Cons a (LinkedList a)] LinkedList a : [Nil, Cons a (LinkedList a)]
three : LinkedList (Int *) three : LinkedList (Int _)
three = Cons 3 (Cons 2 (Cons 1 Nil)) three = Cons 3 (Cons 2 (Cons 1 Nil))
length : LinkedList a -> Int * length : LinkedList a -> Int *
@ -747,7 +747,7 @@ fn linked_list_sum_num_a() {
LinkedList a : [Nil, Cons a (LinkedList a)] LinkedList a : [Nil, Cons a (LinkedList a)]
three : LinkedList (Int *) three : LinkedList (Int _)
three = Cons 3 (Cons 2 (Cons 1 Nil)) three = Cons 3 (Cons 2 (Cons 1 Nil))
@ -776,7 +776,7 @@ fn linked_list_sum_int() {
LinkedList a : [Nil, Cons a (LinkedList a)] LinkedList a : [Nil, Cons a (LinkedList a)]
zero : LinkedList (Int *) zero : LinkedList (Int _)
zero = Nil zero = Nil
sum : LinkedList (Int a) -> Int a sum : LinkedList (Int a) -> Int a
@ -804,7 +804,7 @@ fn linked_list_map() {
LinkedList a : [Nil, Cons a (LinkedList a)] LinkedList a : [Nil, Cons a (LinkedList a)]
three : LinkedList (Int *) three : LinkedList (Int _)
three = Cons 3 (Cons 2 (Cons 1 Nil)) three = Cons 3 (Cons 2 (Cons 1 Nil))
sum : LinkedList (Num a) -> Num a sum : LinkedList (Num a) -> Num a
@ -836,7 +836,7 @@ fn when_nested_maybe() {
r" r"
Maybe a : [Nothing, Just a] Maybe a : [Nothing, Just a]
x : Maybe (Maybe (Int a)) x : Maybe (Maybe (Int _))
x = Just (Just 41) x = Just (Just 41)
when x is when x is
@ -853,7 +853,7 @@ fn when_nested_maybe() {
r" r"
Maybe a : [Nothing, Just a] Maybe a : [Nothing, Just a]
x : Maybe (Maybe (Int *)) x : Maybe (Maybe (Int _))
x = Just Nothing x = Just Nothing
when x is when x is
@ -871,7 +871,7 @@ fn when_nested_maybe() {
r" r"
Maybe a : [Nothing, Just a] Maybe a : [Nothing, Just a]
x : Maybe (Maybe (Int *)) x : Maybe (Maybe (Int _))
x = Nothing x = Nothing
when x is when x is
@ -1402,7 +1402,7 @@ fn recursive_function_with_rigid() {
else else
1 + foo { count: state.count - 1, x: state.x } 1 + foo { count: state.count - 1, x: state.x }
main : Int * main : Int _
main = main =
foo { count: 3, x: {} } foo { count: 3, x: {} }
"# "#
@ -1517,7 +1517,7 @@ fn rbtree_balance_3() {
balance = \key, left -> balance = \key, left ->
Node key left Empty Node key left Empty
main : RedBlackTree (Int *) main : RedBlackTree (Int _)
main = main =
balance 0 Empty balance 0 Empty
"# "#
@ -1696,7 +1696,7 @@ fn nested_pattern_match_two_ways() {
_ -> 3 _ -> 3
_ -> 3 _ -> 3
main : Int * main : Int _
main = main =
when balance Nil is when balance Nil is
_ -> 3 _ -> 3
@ -1719,7 +1719,7 @@ fn nested_pattern_match_two_ways() {
Cons 1 (Cons 1 _) -> 3 Cons 1 (Cons 1 _) -> 3
_ -> 3 _ -> 3
main : Int * main : Int _
main = main =
when balance Nil is when balance Nil is
_ -> 3 _ -> 3
@ -1751,7 +1751,7 @@ fn linked_list_guarded_double_pattern_match() {
_ -> 3 _ -> 3
_ -> 3 _ -> 3
main : Int * main : Int _
main = main =
when balance Nil is when balance Nil is
_ -> 3 _ -> 3
@ -1778,7 +1778,7 @@ fn linked_list_double_pattern_match() {
Cons _ (Cons x _) -> x Cons _ (Cons x _) -> x
_ -> 0 _ -> 0
main : Int * main : Int _
main = main =
foo (Cons 1 (Cons 32 Nil)) foo (Cons 1 (Cons 32 Nil))
"# "#
@ -1886,7 +1886,7 @@ fn wildcard_rigid() {
@Effect inner @Effect inner
main : MyTask {} (Frac *) main : MyTask {} (Frac _)
main = always {} main = always {}
"# "#
), ),

View file

@ -135,7 +135,7 @@ fn err_type_var_annotation() {
assert_evals_to!( assert_evals_to!(
indoc!( indoc!(
r" r"
ok : Result I64 * ok : Result I64 _
ok = Ok 3 ok = Ok 3
Result.map_ok ok (\x -> x + 1) Result.map_ok ok (\x -> x + 1)

View file

@ -2218,3 +2218,29 @@ fn str_drop_suffix() {
RocStr RocStr
); );
} }
#[test]
#[cfg(any(feature = "gen-llvm", feature = "gen-dev", feature = "gen-wasm"))]
fn with_ascii_lowercased() {
assert_evals_to!(
r#"
Str.with_ascii_lowercased("cOFFÉ")
"#,
RocStr::from("coffÉ"),
RocStr
);
}
#[test]
#[cfg(any(feature = "gen-llvm", feature = "gen-dev", feature = "gen-wasm"))]
fn with_ascii_lowercased_non_zero_refcount() {
assert_evals_to!(
r#"
original = "cOFFÉ cOFFÉ cOFFÉ cOFFÉ cOFFÉ cOFFÉ cOFFÉ cOFFÉ cOFFÉ cOFFÉ cOFFÉ cOFFÉ"
res = Str.with_ascii_lowercased(original)
Str.drop_prefix(res, original)
"#,
RocStr::from("coffÉ coffÉ coffÉ coffÉ coffÉ coffÉ coffÉ coffÉ coffÉ coffÉ coffÉ coffÉ"),
RocStr
);
}

View file

@ -158,19 +158,19 @@ fn even_odd() {
assert_evals_to!( assert_evals_to!(
indoc!( indoc!(
r" r"
even = \n -> even = |n|
when n is when n is
0 -> Bool.true 0 -> Bool.true
1 -> Bool.false 1 -> Bool.false
_ -> odd (n - 1) _ -> odd(n - 1)
odd = \n -> odd = |n|
when n is when n is
0 -> Bool.false 0 -> Bool.false
1 -> Bool.true 1 -> Bool.true
_ -> even (n - 1) _ -> even(n - 1)
odd 5 && even 42 odd(5) and even(42)
" "
), ),
true, true,
@ -1075,7 +1075,7 @@ fn applied_tag_function_result() {
assert_evals_to!( assert_evals_to!(
indoc!( indoc!(
r#" r#"
x : List (Result Str *) x : List (Result Str _)
x = List.map ["a", "b"] Ok x = List.map ["a", "b"] Ok
List.keep_oks x (\y -> y) List.keep_oks x (\y -> y)
@ -2315,12 +2315,12 @@ fn recursive_tag_id_in_allocation_eq() {
] ]
x : Value x : Value
x = G 42 x = G(42)
y : Value y : Value
y = H 42 y = H(42)
main = (x == x) && (x != y) && (y == y) main = x == x and x != y and y == y
"# "#
), ),
true, true,

View file

@ -66,7 +66,7 @@ fn build_app_mono<'a>(
let or1_expr = Expr::Call(Call { let or1_expr = Expr::Call(Call {
call_type: CallType::LowLevel { call_type: CallType::LowLevel {
op: LowLevel::Or, op: LowLevel::NumBitwiseOr,
update_mode: UpdateModeId::BACKEND_DUMMY, update_mode: UpdateModeId::BACKEND_DUMMY,
}, },
arguments: arena.alloc([js_call_result, host_call_result]), arguments: arena.alloc([js_call_result, host_call_result]),
@ -74,7 +74,7 @@ fn build_app_mono<'a>(
let or2_expr = Expr::Call(Call { let or2_expr = Expr::Call(Call {
call_type: CallType::LowLevel { call_type: CallType::LowLevel {
op: LowLevel::Or, op: LowLevel::NumBitwiseOr,
update_mode: UpdateModeId::BACKEND_DUMMY, update_mode: UpdateModeId::BACKEND_DUMMY,
}, },
arguments: arena.alloc([or1, bitflag]), arguments: arena.alloc([or1, bitflag]),

View file

@ -1,6 +1,6 @@
procedure Bool.11 (#Attr.2, #Attr.3): procedure Bool.9 (#Attr.2, #Attr.3):
let Bool.23 : Int1 = lowlevel Eq #Attr.2 #Attr.3; let Bool.21 : Int1 = lowlevel Eq #Attr.2 #Attr.3;
ret Bool.23; ret Bool.21;
procedure List.116 (List.563, List.564, List.565): procedure List.116 (List.563, List.564, List.565):
let List.693 : U64 = 0i64; let List.693 : U64 = 0i64;
@ -51,7 +51,7 @@ procedure List.72 (#Attr.2, #Attr.3, #Attr.4):
let List.681 : List U8 = lowlevel ListSublist #Attr.2 #Attr.3 #Attr.4; let List.681 : List U8 = lowlevel ListSublist #Attr.2 #Attr.3 #Attr.4;
ret List.681; ret List.681;
procedure List.80 (#Derived_gen.0, #Derived_gen.1, #Derived_gen.2, #Derived_gen.3, #Derived_gen.4): procedure List.80 (Bool.22, Bool.23, Bool.24, Bool.25, Bool.26):
joinpoint List.695 List.566 List.567 List.568 List.569 List.570: joinpoint List.695 List.566 List.567 List.568 List.569 List.570:
let List.697 : Int1 = CallByName Num.22 List.569 List.570; let List.697 : Int1 = CallByName Num.22 List.569 List.570;
if List.697 then if List.697 then
@ -75,8 +75,8 @@ procedure List.80 (#Derived_gen.0, #Derived_gen.1, #Derived_gen.2, #Derived_gen.
let List.696 : [C U64, C U64] = TagId(1) List.567; let List.696 : [C U64, C U64] = TagId(1) List.567;
ret List.696; ret List.696;
in in
inc #Derived_gen.0; inc Bool.22;
jump List.695 #Derived_gen.0 #Derived_gen.1 #Derived_gen.2 #Derived_gen.3 #Derived_gen.4; jump List.695 Bool.22 Bool.23 Bool.24 Bool.25 Bool.26;
procedure Num.22 (#Attr.2, #Attr.3): procedure Num.22 (#Attr.2, #Attr.3):
let Num.286 : Int1 = lowlevel NumLt #Attr.2 #Attr.3; let Num.286 : Int1 = lowlevel NumLt #Attr.2 #Attr.3;
@ -95,7 +95,7 @@ procedure Test.1 (Test.2):
let Test.14 : {} = Struct {}; let Test.14 : {} = Struct {};
let Test.3 : U64 = CallByName List.26 Test.2 Test.13 Test.14; let Test.3 : U64 = CallByName List.26 Test.2 Test.13 Test.14;
let Test.12 : U64 = 0i64; let Test.12 : U64 = 0i64;
let Test.10 : Int1 = CallByName Bool.11 Test.3 Test.12; let Test.10 : Int1 = CallByName Bool.9 Test.3 Test.12;
if Test.10 then if Test.10 then
ret Test.2; ret Test.2;
else else

View file

@ -8,7 +8,7 @@ procedure Test.4 (Test.27):
let Test.38 : I64 = CallByName Test.5 Test.27 Test.39 Test.40; let Test.38 : I64 = CallByName Test.5 Test.27 Test.39 Test.40;
ret Test.38; ret Test.38;
procedure Test.5 (#Derived_gen.0, #Derived_gen.1, #Derived_gen.2): procedure Test.5 (Bool.21, Bool.22, Bool.23):
joinpoint Test.41 Test.29 Test.30 Test.31: joinpoint Test.41 Test.29 Test.30 Test.31:
let Test.51 : U8 = 0i64; let Test.51 : U8 = 0i64;
let Test.52 : U8 = GetTagId Test.29; let Test.52 : U8 = GetTagId Test.29;
@ -16,22 +16,22 @@ procedure Test.5 (#Derived_gen.0, #Derived_gen.1, #Derived_gen.2):
if Test.53 then if Test.53 then
let Test.32 : [<rnu><null>, C *self *self] = UnionAtIndex (Id 0) (Index 0) Test.29; let Test.32 : [<rnu><null>, C *self *self] = UnionAtIndex (Id 0) (Index 0) Test.29;
let Test.33 : [<rnu><null>, C *self *self] = UnionAtIndex (Id 0) (Index 1) Test.29; let Test.33 : [<rnu><null>, C *self *self] = UnionAtIndex (Id 0) (Index 1) Test.29;
joinpoint #Derived_gen.3 #Derived_gen.6: joinpoint Bool.24 Bool.27:
let #Derived_gen.7 : [<rnu>C [<rnu><null>, C *self *self] *self, <null>] = lowlevel PtrCast #Derived_gen.6; let Bool.28 : [<rnu>C [<rnu><null>, C *self *self] *self, <null>] = lowlevel PtrCast Bool.27;
let Test.43 : [<rnu>C [<rnu><null>, C *self *self] *self, <null>] = Reuse #Derived_gen.7 UpdateModeId { id: 1 } TagId(1) Test.33 Test.30; let Test.43 : [<rnu>C [<rnu><null>, C *self *self] *self, <null>] = Reuse Bool.28 UpdateModeId { id: 1 } TagId(1) Test.33 Test.30;
let Test.45 : I64 = 1i64; let Test.45 : I64 = 1i64;
let Test.44 : I64 = CallByName Num.19 Test.31 Test.45; let Test.44 : I64 = CallByName Num.19 Test.31 Test.45;
jump Test.41 Test.32 Test.43 Test.44; jump Test.41 Test.32 Test.43 Test.44;
in in
let #Derived_gen.4 : Int1 = lowlevel RefCountIsUnique Test.29; let Bool.25 : Int1 = lowlevel RefCountIsUnique Test.29;
if #Derived_gen.4 then if Bool.25 then
jump #Derived_gen.3 Test.29; jump Bool.24 Test.29;
else else
inc Test.32; inc Test.32;
inc Test.33; inc Test.33;
decref Test.29; decref Test.29;
let #Derived_gen.8 : [<rnu><null>, C *self *self] = NullPointer; let Bool.29 : [<rnu><null>, C *self *self] = NullPointer;
jump #Derived_gen.3 #Derived_gen.8; jump Bool.24 Bool.29;
else else
let Test.48 : U8 = 1i64; let Test.48 : U8 = 1i64;
let Test.49 : U8 = GetTagId Test.30; let Test.49 : U8 = GetTagId Test.30;
@ -39,8 +39,8 @@ procedure Test.5 (#Derived_gen.0, #Derived_gen.1, #Derived_gen.2):
if Test.50 then if Test.50 then
let Test.35 : [<rnu><null>, C *self *self] = UnionAtIndex (Id 1) (Index 0) Test.30; let Test.35 : [<rnu><null>, C *self *self] = UnionAtIndex (Id 1) (Index 0) Test.30;
let Test.36 : [<rnu>C [<rnu><null>, C *self *self] *self, <null>] = UnionAtIndex (Id 1) (Index 1) Test.30; let Test.36 : [<rnu>C [<rnu><null>, C *self *self] *self, <null>] = UnionAtIndex (Id 1) (Index 1) Test.30;
let #Derived_gen.5 : Int1 = lowlevel RefCountIsUnique Test.30; let Bool.26 : Int1 = lowlevel RefCountIsUnique Test.30;
if #Derived_gen.5 then if Bool.26 then
free Test.30; free Test.30;
jump Test.41 Test.35 Test.36 Test.31; jump Test.41 Test.35 Test.36 Test.31;
else else
@ -51,7 +51,7 @@ procedure Test.5 (#Derived_gen.0, #Derived_gen.1, #Derived_gen.2):
else else
ret Test.31; ret Test.31;
in in
jump Test.41 #Derived_gen.0 #Derived_gen.1 #Derived_gen.2; jump Test.41 Bool.21 Bool.22 Bool.23;
procedure Test.0 (): procedure Test.0 ():
let Test.64 : [<rnu><null>, C *self *self] = TagId(1) ; let Test.64 : [<rnu><null>, C *self *self] = TagId(1) ;

View file

@ -1,4 +1,4 @@
procedure List.101 (#Derived_gen.0, #Derived_gen.1, #Derived_gen.2, #Derived_gen.3, #Derived_gen.4): procedure List.101 (Bool.21, Bool.22, Bool.23, Bool.24, Bool.25):
joinpoint List.681 List.175 List.176 List.177 List.178 List.179: joinpoint List.681 List.175 List.176 List.177 List.178 List.179:
let List.683 : Int1 = CallByName Num.22 List.178 List.179; let List.683 : Int1 = CallByName Num.22 List.178 List.179;
if List.683 then if List.683 then
@ -11,8 +11,8 @@ procedure List.101 (#Derived_gen.0, #Derived_gen.1, #Derived_gen.2, #Derived_gen
dec List.175; dec List.175;
ret List.176; ret List.176;
in in
inc #Derived_gen.0; inc Bool.21;
jump List.681 #Derived_gen.0 #Derived_gen.1 #Derived_gen.2 #Derived_gen.3 #Derived_gen.4; jump List.681 Bool.21 Bool.22 Bool.23 Bool.24 Bool.25;
procedure List.18 (List.172, List.173, List.174): procedure List.18 (List.172, List.173, List.174):
let List.679 : U64 = 0i64; let List.679 : U64 = 0i64;

View file

@ -1,4 +1,4 @@
procedure List.101 (#Derived_gen.0, #Derived_gen.1, #Derived_gen.2, #Derived_gen.3, #Derived_gen.4): procedure List.101 (Bool.21, Bool.22, Bool.23, Bool.24, Bool.25):
joinpoint List.681 List.175 List.176 List.177 List.178 List.179: joinpoint List.681 List.175 List.176 List.177 List.178 List.179:
let List.683 : Int1 = CallByName Num.22 List.178 List.179; let List.683 : Int1 = CallByName Num.22 List.178 List.179;
if List.683 then if List.683 then
@ -11,8 +11,8 @@ procedure List.101 (#Derived_gen.0, #Derived_gen.1, #Derived_gen.2, #Derived_gen
dec List.175; dec List.175;
ret List.176; ret List.176;
in in
inc #Derived_gen.0; inc Bool.21;
jump List.681 #Derived_gen.0 #Derived_gen.1 #Derived_gen.2 #Derived_gen.3 #Derived_gen.4; jump List.681 Bool.21 Bool.22 Bool.23 Bool.24 Bool.25;
procedure List.18 (List.172, List.173, List.174): procedure List.18 (List.172, List.173, List.174):
let List.679 : U64 = 0i64; let List.679 : U64 = 0i64;

View file

@ -1,4 +1,4 @@
procedure List.101 (#Derived_gen.8, #Derived_gen.9, #Derived_gen.10, #Derived_gen.11, #Derived_gen.12): procedure List.101 (Bool.34, Bool.35, Bool.36, Bool.37, Bool.38):
joinpoint List.678 List.175 List.176 List.177 List.178 List.179: joinpoint List.678 List.175 List.176 List.177 List.178 List.179:
let List.680 : Int1 = CallByName Num.22 List.178 List.179; let List.680 : Int1 = CallByName Num.22 List.178 List.179;
if List.680 then if List.680 then
@ -11,8 +11,8 @@ procedure List.101 (#Derived_gen.8, #Derived_gen.9, #Derived_gen.10, #Derived_ge
dec List.175; dec List.175;
ret List.176; ret List.176;
in in
inc #Derived_gen.8; inc Bool.34;
jump List.678 #Derived_gen.8 #Derived_gen.9 #Derived_gen.10 #Derived_gen.11 #Derived_gen.12; jump List.678 Bool.34 Bool.35 Bool.36 Bool.37 Bool.38;
procedure List.18 (List.172, List.173, List.174): procedure List.18 (List.172, List.173, List.174):
let List.676 : U64 = 0i64; let List.676 : U64 = 0i64;
@ -38,8 +38,8 @@ procedure Num.51 (#Attr.2, #Attr.3):
procedure Test.10 (Test.69, #Attr.12): procedure Test.10 (Test.69, #Attr.12):
let Test.72 : {} = UnionAtIndex (Id 0) (Index 0) #Attr.12; let Test.72 : {} = UnionAtIndex (Id 0) (Index 0) #Attr.12;
let #Derived_gen.18 : Int1 = lowlevel RefCountIsUnique #Attr.12; let Bool.39 : Int1 = lowlevel RefCountIsUnique #Attr.12;
if #Derived_gen.18 then if Bool.39 then
free #Attr.12; free #Attr.12;
ret Test.72; ret Test.72;
else else
@ -53,7 +53,7 @@ procedure Test.10 (Test.69, #Attr.12):
procedure Test.14 (Test.45, #Attr.12): procedure Test.14 (Test.45, #Attr.12):
let Test.55 : {{}, []} = UnionAtIndex (Id 1) (Index 1) #Attr.12; let Test.55 : {{}, []} = UnionAtIndex (Id 1) (Index 1) #Attr.12;
let Test.54 : [<r>C {}, C *self {{}, []}] = UnionAtIndex (Id 1) (Index 0) #Attr.12; let Test.54 : [<r>C {}, C *self {{}, []}] = UnionAtIndex (Id 1) (Index 0) #Attr.12;
joinpoint #Derived_gen.19: joinpoint Bool.40:
let Test.50 : {} = Struct {}; let Test.50 : {} = Struct {};
let Test.51 : U8 = GetTagId Test.54; let Test.51 : U8 = GetTagId Test.54;
joinpoint Test.52 Test.15: joinpoint Test.52 Test.15:
@ -80,14 +80,14 @@ procedure Test.14 (Test.45, #Attr.12):
jump Test.52 Test.53; jump Test.52 Test.53;
in in
let #Derived_gen.20 : Int1 = lowlevel RefCountIsUnique #Attr.12; let Bool.41 : Int1 = lowlevel RefCountIsUnique #Attr.12;
if #Derived_gen.20 then if Bool.41 then
free #Attr.12; free #Attr.12;
jump #Derived_gen.19; jump Bool.40;
else else
inc Test.54; inc Test.54;
decref #Attr.12; decref #Attr.12;
jump #Derived_gen.19; jump Bool.40;
procedure Test.20 (Test.21, Test.18): procedure Test.20 (Test.21, Test.18):
let Test.23 : [C {}, C []] = CallByName Test.32 Test.21 Test.18; let Test.23 : [C {}, C []] = CallByName Test.32 Test.21 Test.18;

View file

@ -1,6 +1,6 @@
procedure Bool.1 (): procedure Bool.1 ():
let Bool.23 : Int1 = false; let Bool.21 : Int1 = false;
ret Bool.23; ret Bool.21;
procedure Test.2 (Test.6): procedure Test.2 (Test.6):
let Test.22 : U8 = 1i64; let Test.22 : U8 = 1i64;
@ -8,7 +8,7 @@ procedure Test.2 (Test.6):
let Test.24 : Int1 = lowlevel Eq Test.22 Test.23; let Test.24 : Int1 = lowlevel Eq Test.22 Test.23;
if Test.24 then if Test.24 then
let Test.7 : [<r>C List *self, C *self] = UnionAtIndex (Id 1) (Index 0) Test.6; let Test.7 : [<r>C List *self, C *self] = UnionAtIndex (Id 1) (Index 0) Test.6;
joinpoint #Derived_gen.1: joinpoint Bool.23:
let Test.8 : Str = CallByName Test.2 Test.7; let Test.8 : Str = CallByName Test.2 Test.7;
let Test.18 : Int1 = CallByName Bool.1; let Test.18 : Int1 = CallByName Bool.1;
if Test.18 then if Test.18 then
@ -18,29 +18,29 @@ procedure Test.2 (Test.6):
let Test.17 : Str = "foo"; let Test.17 : Str = "foo";
ret Test.17; ret Test.17;
in in
let #Derived_gen.2 : Int1 = lowlevel RefCountIsUnique Test.6; let Bool.24 : Int1 = lowlevel RefCountIsUnique Test.6;
if #Derived_gen.2 then if Bool.24 then
free Test.6; free Test.6;
jump #Derived_gen.1; jump Bool.23;
else else
inc Test.7; inc Test.7;
decref Test.6; decref Test.6;
jump #Derived_gen.1; jump Bool.23;
else else
let Test.9 : List [<r>C List [<r>C List *self, C *self], C [<r>C List *self, C *self]] = UnionAtIndex (Id 0) (Index 0) Test.6; let Test.9 : List [<r>C List [<r>C List *self, C *self], C [<r>C List *self, C *self]] = UnionAtIndex (Id 0) (Index 0) Test.6;
joinpoint #Derived_gen.3: joinpoint Bool.25:
dec Test.9; dec Test.9;
let Test.21 : Str = "ValueNotExposed { module_name: ModuleName(IdentStr { string: \"Result\" }), ident: Ident(IdentStr { string: \"withDefault\" }), region: @662-680, exposed_values: ['is_err', 'on_err', 'map_ok', 'map_err', 'with_default', 'try', 'is_ok', 'map_both', 'map2', 'on_err!'] }"; let Test.21 : Str = "ValueNotExposed { module_name: ModuleName(IdentStr { string: \"Result\" }), ident: Ident(IdentStr { string: \"withDefault\" }), region: @662-680, exposed_values: ['is_err', 'on_err', 'map_ok', 'map_err', 'with_default', 'try', 'is_ok', 'map_both', 'map2', 'on_err!'] }";
Crash Test.21 Crash Test.21
in in
let #Derived_gen.4 : Int1 = lowlevel RefCountIsUnique Test.6; let Bool.26 : Int1 = lowlevel RefCountIsUnique Test.6;
if #Derived_gen.4 then if Bool.26 then
free Test.6; free Test.6;
jump #Derived_gen.3; jump Bool.25;
else else
inc Test.9; inc Test.9;
decref Test.6; decref Test.6;
jump #Derived_gen.3; jump Bool.25;
procedure Test.0 (): procedure Test.0 ():
let Test.25 : List [<r>C List [<r>C List *self, C *self], C [<r>C List *self, C *self]] = Array []; let Test.25 : List [<r>C List [<r>C List *self, C *self], C [<r>C List *self, C *self]] = Array [];

View file

@ -1,8 +1,8 @@
procedure Bool.2 (): procedure Bool.2 ():
let Bool.23 : Int1 = true; let Bool.21 : Int1 = true;
ret Bool.23; ret Bool.21;
procedure List.101 (#Derived_gen.5, #Derived_gen.6, #Derived_gen.7, #Derived_gen.8, #Derived_gen.9): procedure List.101 (Bool.29, Bool.30, Bool.31, Bool.32, Bool.33):
joinpoint List.678 List.175 List.176 List.177 List.178 List.179: joinpoint List.678 List.175 List.176 List.177 List.178 List.179:
let List.680 : Int1 = CallByName Num.22 List.178 List.179; let List.680 : Int1 = CallByName Num.22 List.178 List.179;
if List.680 then if List.680 then
@ -15,8 +15,8 @@ procedure List.101 (#Derived_gen.5, #Derived_gen.6, #Derived_gen.7, #Derived_gen
dec List.175; dec List.175;
ret List.176; ret List.176;
in in
inc #Derived_gen.5; inc Bool.29;
jump List.678 #Derived_gen.5 #Derived_gen.6 #Derived_gen.7 #Derived_gen.8 #Derived_gen.9; jump List.678 Bool.29 Bool.30 Bool.31 Bool.32 Bool.33;
procedure List.18 (List.172, List.173, List.174): procedure List.18 (List.172, List.173, List.174):
let List.676 : U64 = 0i64; let List.676 : U64 = 0i64;
@ -41,17 +41,17 @@ procedure Num.51 (#Attr.2, #Attr.3):
ret Num.283; ret Num.283;
procedure Str.3 (#Attr.2, #Attr.3): procedure Str.3 (#Attr.2, #Attr.3):
let Str.380 : Str = lowlevel StrConcat #Attr.2 #Attr.3; let Str.250 : Str = lowlevel StrConcat #Attr.2 #Attr.3;
ret Str.380; ret Str.250;
procedure Test.1 (Test.5): procedure Test.1 (Test.5):
ret Test.5; ret Test.5;
procedure Test.11 (#Derived_gen.10, #Derived_gen.11): procedure Test.11 (Bool.27, Bool.28):
joinpoint Test.27 Test.12 #Attr.12: joinpoint Test.27 Test.12 #Attr.12:
let Test.34 : Int1 = UnionAtIndex (Id 2) (Index 1) #Attr.12; let Test.34 : Int1 = UnionAtIndex (Id 2) (Index 1) #Attr.12;
let Test.33 : [<rnw><null>, C *self Int1, C *self Int1] = UnionAtIndex (Id 2) (Index 0) #Attr.12; let Test.33 : [<rnw><null>, C *self Int1, C *self Int1] = UnionAtIndex (Id 2) (Index 0) #Attr.12;
joinpoint #Derived_gen.14: joinpoint Bool.36:
joinpoint Test.31 Test.29: joinpoint Test.31 Test.29:
let Test.30 : U8 = GetTagId Test.33; let Test.30 : U8 = GetTagId Test.33;
switch Test.30: switch Test.30:
@ -78,16 +78,16 @@ procedure Test.11 (#Derived_gen.10, #Derived_gen.11):
jump Test.31 Test.32; jump Test.31 Test.32;
in in
let #Derived_gen.15 : Int1 = lowlevel RefCountIsUnique #Attr.12; let Bool.37 : Int1 = lowlevel RefCountIsUnique #Attr.12;
if #Derived_gen.15 then if Bool.37 then
free #Attr.12; free #Attr.12;
jump #Derived_gen.14; jump Bool.36;
else else
inc Test.33; inc Test.33;
decref #Attr.12; decref #Attr.12;
jump #Derived_gen.14; jump Bool.36;
in in
jump Test.27 #Derived_gen.10 #Derived_gen.11; jump Test.27 Bool.27 Bool.28;
procedure Test.2 (Test.13): procedure Test.2 (Test.13):
ret Test.13; ret Test.13;
@ -118,7 +118,7 @@ procedure Test.6 (Test.7, Test.8, Test.5):
procedure Test.9 (Test.10, #Attr.12): procedure Test.9 (Test.10, #Attr.12):
let Test.43 : Int1 = UnionAtIndex (Id 1) (Index 1) #Attr.12; let Test.43 : Int1 = UnionAtIndex (Id 1) (Index 1) #Attr.12;
let Test.42 : [<rnw><null>, C *self Int1, C *self Int1] = UnionAtIndex (Id 1) (Index 0) #Attr.12; let Test.42 : [<rnw><null>, C *self Int1, C *self Int1] = UnionAtIndex (Id 1) (Index 0) #Attr.12;
joinpoint #Derived_gen.12: joinpoint Bool.34:
let Test.39 : U8 = GetTagId Test.42; let Test.39 : U8 = GetTagId Test.42;
joinpoint Test.40 Test.38: joinpoint Test.40 Test.38:
switch Test.43: switch Test.43:
@ -146,14 +146,14 @@ procedure Test.9 (Test.10, #Attr.12):
jump Test.40 Test.41; jump Test.40 Test.41;
in in
let #Derived_gen.13 : Int1 = lowlevel RefCountIsUnique #Attr.12; let Bool.35 : Int1 = lowlevel RefCountIsUnique #Attr.12;
if #Derived_gen.13 then if Bool.35 then
free #Attr.12; free #Attr.12;
jump #Derived_gen.12; jump Bool.34;
else else
inc Test.42; inc Test.42;
decref #Attr.12; decref #Attr.12;
jump #Derived_gen.12; jump Bool.34;
procedure Test.0 (): procedure Test.0 ():
let Test.45 : Int1 = false; let Test.45 : Int1 = false;

View file

@ -43,14 +43,14 @@ procedure Num.96 (#Attr.2):
ret Num.284; ret Num.284;
procedure Str.3 (#Attr.2, #Attr.3): procedure Str.3 (#Attr.2, #Attr.3):
let Str.378 : Str = lowlevel StrConcat #Attr.2 #Attr.3; let Str.248 : Str = lowlevel StrConcat #Attr.2 #Attr.3;
ret Str.378; ret Str.248;
procedure Test.0 (): procedure Test.0 ():
let Test.5 : I64 = 1i64; let Test.4 : I64 = 1i64;
let Test.2 : I64 = 2i64; let Test.1 : I64 = 2i64;
let Test.3 : Str = CallByName Inspect.33 Test.2; let Test.2 : Str = CallByName Inspect.33 Test.1;
dbg Test.3; dbg Test.2;
dec Test.3; dec Test.2;
let Test.4 : I64 = CallByName Num.19 Test.5 Test.2; let Test.3 : I64 = CallByName Num.19 Test.4 Test.1;
ret Test.4; ret Test.3;

View file

@ -1,17 +1,17 @@
procedure Bool.11 (#Attr.2, #Attr.3): procedure Bool.1 ():
let Bool.25 : Int1 = lowlevel Eq #Attr.2 #Attr.3; let Bool.22 : Int1 = false;
ret Bool.25; ret Bool.22;
procedure Bool.11 (#Attr.2, #Attr.3):
let Bool.26 : Int1 = lowlevel Eq #Attr.2 #Attr.3;
ret Bool.26;
procedure Bool.2 (): procedure Bool.2 ():
let Bool.23 : Int1 = true; let Bool.21 : Int1 = true;
ret Bool.21;
procedure Bool.9 (#Attr.2, #Attr.3):
let Bool.23 : Int1 = lowlevel Eq #Attr.2 #Attr.3;
ret Bool.23; ret Bool.23;
procedure Bool.3 (#Attr.2, #Attr.3): procedure Bool.9 (#Attr.2, #Attr.3):
let Bool.24 : Int1 = lowlevel And #Attr.2 #Attr.3; let Bool.24 : Int1 = lowlevel Eq #Attr.2 #Attr.3;
ret Bool.24; ret Bool.24;
procedure Inspect.245 (Inspect.246, Inspect.244): procedure Inspect.245 (Inspect.246, Inspect.244):
@ -104,181 +104,184 @@ procedure Num.77 (#Attr.2, #Attr.3):
ret Num.293; ret Num.293;
procedure Str.20 (#Attr.2): procedure Str.20 (#Attr.2):
let Str.445 : Str = lowlevel StrWithCapacity #Attr.2; let Str.316 : Str = lowlevel StrWithCapacity #Attr.2;
ret Str.445; ret Str.316;
procedure Str.3 (#Attr.2, #Attr.3): procedure Str.3 (#Attr.2, #Attr.3):
let Str.378 : Str = lowlevel StrConcat #Attr.2 #Attr.3; let Str.248 : Str = lowlevel StrConcat #Attr.2 #Attr.3;
ret Str.378; ret Str.248;
procedure Str.35 (#Attr.2, #Attr.3): procedure Str.35 (#Attr.2, #Attr.3):
let Str.435 : U8 = lowlevel StrGetUnsafe #Attr.2 #Attr.3; let Str.306 : U8 = lowlevel StrGetUnsafe #Attr.2 #Attr.3;
ret Str.435; ret Str.306;
procedure Str.36 (#Attr.2): procedure Str.36 (#Attr.2):
let Str.398 : U64 = lowlevel StrCountUtf8Bytes #Attr.2; let Str.268 : U64 = lowlevel StrCountUtf8Bytes #Attr.2;
ret Str.398; ret Str.268;
procedure Str.37 (#Attr.2, #Attr.3, #Attr.4): procedure Str.37 (#Attr.2, #Attr.3, #Attr.4):
let Str.396 : Str = lowlevel StrSubstringUnsafe #Attr.2 #Attr.3 #Attr.4; let Str.266 : Str = lowlevel StrSubstringUnsafe #Attr.2 #Attr.3 #Attr.4;
ret Str.396;
procedure Str.38 (Str.210, Str.211):
let Str.392 : [C , C U64] = CallByName Str.62 Str.210 Str.211;
let Str.405 : U8 = 1i64;
let Str.406 : U8 = GetTagId Str.392;
let Str.407 : Int1 = lowlevel Eq Str.405 Str.406;
if Str.407 then
let Str.212 : U64 = UnionAtIndex (Id 1) (Index 0) Str.392;
let Str.401 : U64 = CallByName Str.36 Str.210;
let Str.402 : U64 = CallByName Str.36 Str.211;
let Str.400 : U64 = CallByName Num.20 Str.401 Str.402;
let Str.213 : U64 = CallByName Num.20 Str.400 Str.212;
let Str.399 : U64 = 0i64;
inc Str.210;
let Str.214 : Str = CallByName Str.37 Str.210 Str.399 Str.212;
let Str.397 : U64 = CallByName Str.36 Str.211;
let Str.395 : U64 = CallByName Num.51 Str.212 Str.397;
let Str.215 : Str = CallByName Str.37 Str.210 Str.395 Str.213;
let Str.394 : {Str, Str} = Struct {Str.215, Str.214};
let Str.393 : [C {}, C {Str, Str}] = TagId(1) Str.394;
ret Str.393;
else
dec Str.210;
let Str.404 : {} = Struct {};
let Str.403 : [C {}, C {Str, Str}] = TagId(0) Str.404;
ret Str.403;
procedure Str.45 (Str.189, Str.190, Str.191):
inc Str.189;
let Str.473 : [C {}, C {Str, Str}] = CallByName Str.38 Str.189 Str.190;
let Str.481 : U8 = 1i64;
let Str.482 : U8 = GetTagId Str.473;
let Str.483 : Int1 = lowlevel Eq Str.481 Str.482;
if Str.483 then
let Str.480 : {Str, Str} = UnionAtIndex (Id 1) (Index 0) Str.473;
let Str.193 : Str = StructAtIndex 0 Str.480;
let Str.192 : Str = StructAtIndex 1 Str.480;
let Str.478 : U64 = CallByName Str.36 Str.189;
dec Str.189;
let Str.477 : Str = CallByName Str.20 Str.478;
let Str.476 : Str = CallByName Str.3 Str.477 Str.192;
dec Str.192;
let Str.475 : Str = CallByName Str.3 Str.476 Str.191;
let Str.474 : Str = CallByName Str.61 Str.475 Str.193 Str.190 Str.191;
ret Str.474;
else
dec Str.473;
ret Str.189;
procedure Str.61 (#Derived_gen.5, #Derived_gen.6, #Derived_gen.7, #Derived_gen.8):
joinpoint Str.382 Str.194 Str.195 Str.196 Str.197:
inc Str.195;
let Str.383 : [C {}, C {Str, Str}] = CallByName Str.38 Str.195 Str.196;
let Str.389 : U8 = 1i64;
let Str.390 : U8 = GetTagId Str.383;
let Str.391 : Int1 = lowlevel Eq Str.389 Str.390;
if Str.391 then
dec Str.195;
let Str.388 : {Str, Str} = UnionAtIndex (Id 1) (Index 0) Str.383;
let Str.199 : Str = StructAtIndex 0 Str.388;
let Str.198 : Str = StructAtIndex 1 Str.388;
let Str.386 : Str = CallByName Str.3 Str.194 Str.198;
dec Str.198;
let Str.385 : Str = CallByName Str.3 Str.386 Str.197;
jump Str.382 Str.385 Str.199 Str.196 Str.197;
else
dec Str.196;
dec Str.383;
dec Str.197;
let Str.387 : Str = CallByName Str.3 Str.194 Str.195;
dec Str.195;
ret Str.387;
in
inc #Derived_gen.7;
inc #Derived_gen.8;
jump Str.382 #Derived_gen.5 #Derived_gen.6 #Derived_gen.7 #Derived_gen.8;
procedure Str.62 (Str.219, Str.220):
let Str.221 : U64 = CallByName Str.36 Str.219;
let Str.222 : U64 = CallByName Str.36 Str.220;
let Str.223 : U64 = CallByName Num.77 Str.221 Str.222;
let Str.409 : U64 = 0i64;
let Str.408 : [C , C U64] = CallByName Str.63 Str.219 Str.220 Str.409 Str.223;
ret Str.408;
procedure Str.63 (#Derived_gen.0, #Derived_gen.1, #Derived_gen.2, #Derived_gen.3):
joinpoint Str.410 Str.224 Str.225 Str.226 Str.227:
let Str.412 : Int1 = CallByName Num.23 Str.226 Str.227;
if Str.412 then
let Str.416 : Int1 = CallByName Str.67 Str.224 Str.226 Str.225;
if Str.416 then
dec Str.224;
dec Str.225;
let Str.417 : [C , C U64] = TagId(1) Str.226;
ret Str.417;
else
let Str.415 : U64 = 1i64;
let Str.414 : U64 = CallByName Num.51 Str.226 Str.415;
jump Str.410 Str.224 Str.225 Str.414 Str.227;
else
dec Str.224;
dec Str.225;
let Str.411 : [C , C U64] = TagId(0) ;
ret Str.411;
in
inc #Derived_gen.0;
inc #Derived_gen.1;
jump Str.410 #Derived_gen.0 #Derived_gen.1 #Derived_gen.2 #Derived_gen.3;
procedure Str.66 (Str.250, Str.251):
let Str.440 : Int1 = CallByName Num.22 Str.250 Str.251;
if Str.440 then
ret Str.250;
else
ret Str.251;
procedure Str.67 (Str.252, Str.253, Str.254):
let Str.255 : U64 = CallByName Str.36 Str.252;
let Str.256 : U64 = CallByName Str.36 Str.254;
let Str.438 : U64 = CallByName Num.53 Str.253 Str.256;
let Str.257 : U64 = CallByName Str.66 Str.438 Str.255;
let Str.437 : U64 = 0i64;
inc Str.252;
inc Str.254;
let Str.419 : {U64, Str, U64, Str, U64, U64} = Struct {Str.257, Str.252, Str.253, Str.254, Str.437, Str.256};
let Str.418 : Int1 = CallByName Str.68 Str.419;
ret Str.418;
procedure Str.68 (Str.258):
let Str.264 : U64 = StructAtIndex 0 Str.258;
let Str.259 : Str = StructAtIndex 1 Str.258;
let Str.260 : U64 = StructAtIndex 2 Str.258;
let Str.261 : Str = StructAtIndex 3 Str.258;
let Str.262 : U64 = StructAtIndex 4 Str.258;
let Str.263 : U64 = StructAtIndex 5 Str.258;
let Str.265 : Int1 = CallByName Num.25 Str.260 Str.264;
if Str.265 then
dec Str.259;
dec Str.261;
let Str.266 : Int1 = CallByName Bool.11 Str.262 Str.263;
ret Str.266; ret Str.266;
procedure Str.38 (Str.113, Str.114):
let Str.262 : [C , C U64] = CallByName Str.58 Str.113 Str.114;
let Str.275 : U8 = 1i64;
let Str.276 : U8 = GetTagId Str.262;
let Str.277 : Int1 = lowlevel Eq Str.275 Str.276;
if Str.277 then
let Str.115 : U64 = UnionAtIndex (Id 1) (Index 0) Str.262;
let Str.271 : U64 = CallByName Str.36 Str.113;
let Str.272 : U64 = CallByName Str.36 Str.114;
let Str.270 : U64 = CallByName Num.20 Str.271 Str.272;
let Str.116 : U64 = CallByName Num.20 Str.270 Str.115;
let Str.269 : U64 = 0i64;
inc Str.113;
let Str.117 : Str = CallByName Str.37 Str.113 Str.269 Str.115;
let Str.267 : U64 = CallByName Str.36 Str.114;
let Str.265 : U64 = CallByName Num.51 Str.115 Str.267;
let Str.118 : Str = CallByName Str.37 Str.113 Str.265 Str.116;
let Str.264 : {Str, Str} = Struct {Str.118, Str.117};
let Str.263 : [C {}, C {Str, Str}] = TagId(1) Str.264;
ret Str.263;
else else
let Str.433 : U8 = CallByName Str.35 Str.259 Str.260; dec Str.113;
let Str.434 : U8 = CallByName Str.35 Str.261 Str.262; let Str.274 : {} = Struct {};
let Str.267 : Int1 = CallByName Bool.11 Str.433 Str.434; let Str.273 : [C {}, C {Str, Str}] = TagId(0) Str.274;
let Str.423 : U64 = StructAtIndex 0 Str.258; ret Str.273;
let Str.424 : Str = StructAtIndex 1 Str.258;
let Str.426 : Str = StructAtIndex 3 Str.258; procedure Str.45 (Str.92, Str.93, Str.94):
let Str.428 : U64 = StructAtIndex 5 Str.258; inc Str.92;
let Str.432 : U64 = 1i64; let Str.344 : [C {}, C {Str, Str}] = CallByName Str.38 Str.92 Str.93;
let Str.430 : U64 = CallByName Num.51 Str.262 Str.432; let Str.352 : U8 = 1i64;
let Str.431 : U64 = 1i64; let Str.353 : U8 = GetTagId Str.344;
let Str.429 : U64 = CallByName Num.51 Str.260 Str.431; let Str.354 : Int1 = lowlevel Eq Str.352 Str.353;
let Str.422 : {U64, Str, U64, Str, U64, U64} = Struct {Str.423, Str.424, Str.429, Str.426, Str.430, Str.428}; if Str.354 then
let Str.268 : Int1 = CallByName Str.68 Str.422; let Str.351 : {Str, Str} = UnionAtIndex (Id 1) (Index 0) Str.344;
let Str.421 : Int1 = CallByName Bool.3 Str.267 Str.268; let Str.96 : Str = StructAtIndex 0 Str.351;
ret Str.421; let Str.95 : Str = StructAtIndex 1 Str.351;
let Str.349 : U64 = CallByName Str.36 Str.92;
dec Str.92;
let Str.348 : Str = CallByName Str.20 Str.349;
let Str.347 : Str = CallByName Str.3 Str.348 Str.95;
dec Str.95;
let Str.346 : Str = CallByName Str.3 Str.347 Str.94;
let Str.345 : Str = CallByName Str.57 Str.346 Str.96 Str.93 Str.94;
ret Str.345;
else
dec Str.344;
ret Str.92;
procedure Str.57 (#Derived_gen.0, #Derived_gen.1, #Derived_gen.2, #Derived_gen.3):
joinpoint Str.252 Str.97 Str.98 Str.99 Str.100:
inc Str.98;
let Str.253 : [C {}, C {Str, Str}] = CallByName Str.38 Str.98 Str.99;
let Str.259 : U8 = 1i64;
let Str.260 : U8 = GetTagId Str.253;
let Str.261 : Int1 = lowlevel Eq Str.259 Str.260;
if Str.261 then
dec Str.98;
let Str.258 : {Str, Str} = UnionAtIndex (Id 1) (Index 0) Str.253;
let Str.102 : Str = StructAtIndex 0 Str.258;
let Str.101 : Str = StructAtIndex 1 Str.258;
let Str.256 : Str = CallByName Str.3 Str.97 Str.101;
dec Str.101;
let Str.255 : Str = CallByName Str.3 Str.256 Str.100;
jump Str.252 Str.255 Str.102 Str.99 Str.100;
else
dec Str.100;
dec Str.99;
dec Str.253;
let Str.257 : Str = CallByName Str.3 Str.97 Str.98;
dec Str.98;
ret Str.257;
in
inc #Derived_gen.3;
inc #Derived_gen.2;
jump Str.252 #Derived_gen.0 #Derived_gen.1 #Derived_gen.2 #Derived_gen.3;
procedure Str.58 (Str.122, Str.123):
let Str.124 : U64 = CallByName Str.36 Str.122;
let Str.125 : U64 = CallByName Str.36 Str.123;
let Str.126 : U64 = CallByName Num.77 Str.124 Str.125;
let Str.279 : U64 = 0i64;
let Str.278 : [C , C U64] = CallByName Str.59 Str.122 Str.123 Str.279 Str.126;
ret Str.278;
procedure Str.59 (#Derived_gen.4, #Derived_gen.5, #Derived_gen.6, #Derived_gen.7):
joinpoint Str.280 Str.127 Str.128 Str.129 Str.130:
let Str.282 : Int1 = CallByName Num.23 Str.129 Str.130;
if Str.282 then
let Str.286 : Int1 = CallByName Str.63 Str.127 Str.129 Str.128;
if Str.286 then
dec Str.127;
dec Str.128;
let Str.287 : [C , C U64] = TagId(1) Str.129;
ret Str.287;
else
let Str.285 : U64 = 1i64;
let Str.284 : U64 = CallByName Num.51 Str.129 Str.285;
jump Str.280 Str.127 Str.128 Str.284 Str.130;
else
dec Str.127;
dec Str.128;
let Str.281 : [C , C U64] = TagId(0) ;
ret Str.281;
in
inc #Derived_gen.5;
inc #Derived_gen.4;
jump Str.280 #Derived_gen.4 #Derived_gen.5 #Derived_gen.6 #Derived_gen.7;
procedure Str.62 (Str.153, Str.154):
let Str.311 : Int1 = CallByName Num.22 Str.153 Str.154;
if Str.311 then
ret Str.153;
else
ret Str.154;
procedure Str.63 (Str.155, Str.156, Str.157):
let Str.158 : U64 = CallByName Str.36 Str.155;
let Str.159 : U64 = CallByName Str.36 Str.157;
let Str.309 : U64 = CallByName Num.53 Str.156 Str.159;
let Str.160 : U64 = CallByName Str.62 Str.309 Str.158;
let Str.308 : U64 = 0i64;
inc Str.157;
inc Str.155;
let Str.289 : {U64, Str, U64, Str, U64, U64} = Struct {Str.160, Str.155, Str.156, Str.157, Str.308, Str.159};
let Str.288 : Int1 = CallByName Str.64 Str.289;
ret Str.288;
procedure Str.64 (Str.161):
let Str.167 : U64 = StructAtIndex 0 Str.161;
let Str.162 : Str = StructAtIndex 1 Str.161;
let Str.163 : U64 = StructAtIndex 2 Str.161;
let Str.164 : Str = StructAtIndex 3 Str.161;
let Str.165 : U64 = StructAtIndex 4 Str.161;
let Str.166 : U64 = StructAtIndex 5 Str.161;
let Str.168 : Int1 = CallByName Num.25 Str.163 Str.167;
if Str.168 then
dec Str.162;
dec Str.164;
let Str.169 : Int1 = CallByName Bool.9 Str.165 Str.166;
ret Str.169;
else
let Str.304 : U8 = CallByName Str.35 Str.162 Str.163;
let Str.305 : U8 = CallByName Str.35 Str.164 Str.165;
let Str.170 : Int1 = CallByName Bool.9 Str.304 Str.305;
let Str.294 : U64 = StructAtIndex 0 Str.161;
let Str.295 : Str = StructAtIndex 1 Str.161;
let Str.297 : Str = StructAtIndex 3 Str.161;
let Str.299 : U64 = StructAtIndex 5 Str.161;
let Str.303 : U64 = 1i64;
let Str.301 : U64 = CallByName Num.51 Str.165 Str.303;
let Str.302 : U64 = 1i64;
let Str.300 : U64 = CallByName Num.51 Str.163 Str.302;
let Str.293 : {U64, Str, U64, Str, U64, U64} = Struct {Str.294, Str.295, Str.300, Str.297, Str.301, Str.299};
let Str.171 : Int1 = CallByName Str.64 Str.293;
if Str.170 then
ret Str.171;
else
let Str.291 : Int1 = CallByName Bool.1;
ret Str.291;
procedure Test.1 (): procedure Test.1 ():
let Test.4 : Str = ""; let Test.4 : Str = "";

View file

@ -1,13 +1,13 @@
procedure Bool.11 (#Attr.2, #Attr.3): procedure Bool.1 ():
let Bool.24 : Int1 = lowlevel Eq #Attr.2 #Attr.3; let Bool.21 : Int1 = false;
ret Bool.24; ret Bool.21;
procedure Bool.11 (#Attr.2, #Attr.3): procedure Bool.9 (#Attr.2, #Attr.3):
let Bool.25 : Int1 = lowlevel Eq #Attr.2 #Attr.3; let Bool.22 : Int1 = lowlevel Eq #Attr.2 #Attr.3;
ret Bool.25; ret Bool.22;
procedure Bool.3 (#Attr.2, #Attr.3): procedure Bool.9 (#Attr.2, #Attr.3):
let Bool.23 : Int1 = lowlevel And #Attr.2 #Attr.3; let Bool.23 : Int1 = lowlevel Eq #Attr.2 #Attr.3;
ret Bool.23; ret Bool.23;
procedure Inspect.245 (Inspect.246, Inspect.244): procedure Inspect.245 (Inspect.246, Inspect.244):
@ -100,192 +100,195 @@ procedure Num.77 (#Attr.2, #Attr.3):
ret Num.293; ret Num.293;
procedure Str.20 (#Attr.2): procedure Str.20 (#Attr.2):
let Str.447 : Str = lowlevel StrWithCapacity #Attr.2; let Str.318 : Str = lowlevel StrWithCapacity #Attr.2;
ret Str.447; ret Str.318;
procedure Str.3 (#Attr.2, #Attr.3): procedure Str.3 (#Attr.2, #Attr.3):
let Str.380 : Str = lowlevel StrConcat #Attr.2 #Attr.3; let Str.250 : Str = lowlevel StrConcat #Attr.2 #Attr.3;
ret Str.380; ret Str.250;
procedure Str.35 (#Attr.2, #Attr.3): procedure Str.35 (#Attr.2, #Attr.3):
let Str.437 : U8 = lowlevel StrGetUnsafe #Attr.2 #Attr.3; let Str.308 : U8 = lowlevel StrGetUnsafe #Attr.2 #Attr.3;
ret Str.437; ret Str.308;
procedure Str.36 (#Attr.2): procedure Str.36 (#Attr.2):
let Str.400 : U64 = lowlevel StrCountUtf8Bytes #Attr.2; let Str.270 : U64 = lowlevel StrCountUtf8Bytes #Attr.2;
ret Str.400; ret Str.270;
procedure Str.37 (#Attr.2, #Attr.3, #Attr.4): procedure Str.37 (#Attr.2, #Attr.3, #Attr.4):
let Str.398 : Str = lowlevel StrSubstringUnsafe #Attr.2 #Attr.3 #Attr.4; let Str.268 : Str = lowlevel StrSubstringUnsafe #Attr.2 #Attr.3 #Attr.4;
ret Str.398; ret Str.268;
procedure Str.38 (Str.210, Str.211): procedure Str.38 (Str.113, Str.114):
let Str.394 : [C , C U64] = CallByName Str.62 Str.210 Str.211; let Str.264 : [C , C U64] = CallByName Str.58 Str.113 Str.114;
let Str.407 : U8 = 1i64; let Str.277 : U8 = 1i64;
let Str.408 : U8 = GetTagId Str.394; let Str.278 : U8 = GetTagId Str.264;
let Str.409 : Int1 = lowlevel Eq Str.407 Str.408; let Str.279 : Int1 = lowlevel Eq Str.277 Str.278;
if Str.409 then if Str.279 then
let Str.212 : U64 = UnionAtIndex (Id 1) (Index 0) Str.394; let Str.115 : U64 = UnionAtIndex (Id 1) (Index 0) Str.264;
let Str.403 : U64 = CallByName Str.36 Str.210; let Str.273 : U64 = CallByName Str.36 Str.113;
let Str.404 : U64 = CallByName Str.36 Str.211; let Str.274 : U64 = CallByName Str.36 Str.114;
let Str.402 : U64 = CallByName Num.20 Str.403 Str.404; let Str.272 : U64 = CallByName Num.20 Str.273 Str.274;
let Str.213 : U64 = CallByName Num.20 Str.402 Str.212; let Str.116 : U64 = CallByName Num.20 Str.272 Str.115;
let Str.401 : U64 = 0i64; let Str.271 : U64 = 0i64;
inc Str.210; inc Str.113;
let Str.214 : Str = CallByName Str.37 Str.210 Str.401 Str.212; let Str.117 : Str = CallByName Str.37 Str.113 Str.271 Str.115;
let Str.399 : U64 = CallByName Str.36 Str.211; let Str.269 : U64 = CallByName Str.36 Str.114;
let Str.397 : U64 = CallByName Num.51 Str.212 Str.399; let Str.267 : U64 = CallByName Num.51 Str.115 Str.269;
let Str.215 : Str = CallByName Str.37 Str.210 Str.397 Str.213; let Str.118 : Str = CallByName Str.37 Str.113 Str.267 Str.116;
let Str.396 : {Str, Str} = Struct {Str.215, Str.214}; let Str.266 : {Str, Str} = Struct {Str.118, Str.117};
let Str.395 : [C {}, C {Str, Str}] = TagId(1) Str.396; let Str.265 : [C {}, C {Str, Str}] = TagId(1) Str.266;
ret Str.395; ret Str.265;
else else
dec Str.210; dec Str.113;
let Str.406 : {} = Struct {}; let Str.276 : {} = Struct {};
let Str.405 : [C {}, C {Str, Str}] = TagId(0) Str.406; let Str.275 : [C {}, C {Str, Str}] = TagId(0) Str.276;
ret Str.405; ret Str.275;
procedure Str.45 (Str.189, Str.190, Str.191): procedure Str.45 (Str.92, Str.93, Str.94):
inc Str.189; inc Str.92;
let Str.475 : [C {}, C {Str, Str}] = CallByName Str.38 Str.189 Str.190; let Str.346 : [C {}, C {Str, Str}] = CallByName Str.38 Str.92 Str.93;
let Str.483 : U8 = 1i64; let Str.354 : U8 = 1i64;
let Str.484 : U8 = GetTagId Str.475; let Str.355 : U8 = GetTagId Str.346;
let Str.485 : Int1 = lowlevel Eq Str.483 Str.484; let Str.356 : Int1 = lowlevel Eq Str.354 Str.355;
if Str.485 then if Str.356 then
let Str.482 : {Str, Str} = UnionAtIndex (Id 1) (Index 0) Str.475; let Str.353 : {Str, Str} = UnionAtIndex (Id 1) (Index 0) Str.346;
let Str.193 : Str = StructAtIndex 0 Str.482; let Str.96 : Str = StructAtIndex 0 Str.353;
let Str.192 : Str = StructAtIndex 1 Str.482; let Str.95 : Str = StructAtIndex 1 Str.353;
let Str.480 : U64 = CallByName Str.36 Str.189; let Str.351 : U64 = CallByName Str.36 Str.92;
dec Str.189; dec Str.92;
let Str.479 : Str = CallByName Str.20 Str.480; let Str.350 : Str = CallByName Str.20 Str.351;
let Str.478 : Str = CallByName Str.3 Str.479 Str.192; let Str.349 : Str = CallByName Str.3 Str.350 Str.95;
dec Str.192; dec Str.95;
let Str.477 : Str = CallByName Str.3 Str.478 Str.191; let Str.348 : Str = CallByName Str.3 Str.349 Str.94;
let Str.476 : Str = CallByName Str.61 Str.477 Str.193 Str.190 Str.191; let Str.347 : Str = CallByName Str.57 Str.348 Str.96 Str.93 Str.94;
ret Str.476; ret Str.347;
else else
dec Str.475; dec Str.346;
ret Str.189; ret Str.92;
procedure Str.61 (#Derived_gen.0, #Derived_gen.1, #Derived_gen.2, #Derived_gen.3): procedure Str.57 (Bool.24, Bool.25, Bool.26, Bool.27):
joinpoint Str.384 Str.194 Str.195 Str.196 Str.197: joinpoint Str.254 Str.97 Str.98 Str.99 Str.100:
inc Str.195; inc Str.98;
let Str.385 : [C {}, C {Str, Str}] = CallByName Str.38 Str.195 Str.196; let Str.255 : [C {}, C {Str, Str}] = CallByName Str.38 Str.98 Str.99;
let Str.391 : U8 = 1i64; let Str.261 : U8 = 1i64;
let Str.392 : U8 = GetTagId Str.385; let Str.262 : U8 = GetTagId Str.255;
let Str.393 : Int1 = lowlevel Eq Str.391 Str.392; let Str.263 : Int1 = lowlevel Eq Str.261 Str.262;
if Str.393 then if Str.263 then
dec Str.195; dec Str.98;
let Str.390 : {Str, Str} = UnionAtIndex (Id 1) (Index 0) Str.385; let Str.260 : {Str, Str} = UnionAtIndex (Id 1) (Index 0) Str.255;
let Str.199 : Str = StructAtIndex 0 Str.390; let Str.102 : Str = StructAtIndex 0 Str.260;
let Str.198 : Str = StructAtIndex 1 Str.390; let Str.101 : Str = StructAtIndex 1 Str.260;
let Str.388 : Str = CallByName Str.3 Str.194 Str.198; let Str.258 : Str = CallByName Str.3 Str.97 Str.101;
dec Str.198; dec Str.101;
let Str.387 : Str = CallByName Str.3 Str.388 Str.197; let Str.257 : Str = CallByName Str.3 Str.258 Str.100;
jump Str.384 Str.387 Str.199 Str.196 Str.197; jump Str.254 Str.257 Str.102 Str.99 Str.100;
else else
dec Str.385; dec Str.100;
dec Str.196; dec Str.99;
dec Str.197; dec Str.255;
let Str.389 : Str = CallByName Str.3 Str.194 Str.195; let Str.259 : Str = CallByName Str.3 Str.97 Str.98;
dec Str.195; dec Str.98;
ret Str.389; ret Str.259;
in in
inc #Derived_gen.3; inc Bool.26;
inc #Derived_gen.2; inc Bool.27;
jump Str.384 #Derived_gen.0 #Derived_gen.1 #Derived_gen.2 #Derived_gen.3; jump Str.254 Bool.24 Bool.25 Bool.26 Bool.27;
procedure Str.62 (Str.219, Str.220): procedure Str.58 (Str.122, Str.123):
let Str.221 : U64 = CallByName Str.36 Str.219; let Str.124 : U64 = CallByName Str.36 Str.122;
let Str.222 : U64 = CallByName Str.36 Str.220; let Str.125 : U64 = CallByName Str.36 Str.123;
let Str.223 : U64 = CallByName Num.77 Str.221 Str.222; let Str.126 : U64 = CallByName Num.77 Str.124 Str.125;
let Str.411 : U64 = 0i64; let Str.281 : U64 = 0i64;
let Str.410 : [C , C U64] = CallByName Str.63 Str.219 Str.220 Str.411 Str.223; let Str.280 : [C , C U64] = CallByName Str.59 Str.122 Str.123 Str.281 Str.126;
ret Str.410; ret Str.280;
procedure Str.63 (#Derived_gen.4, #Derived_gen.5, #Derived_gen.6, #Derived_gen.7): procedure Str.59 (Bool.28, Bool.29, Bool.30, Bool.31):
joinpoint Str.412 Str.224 Str.225 Str.226 Str.227: joinpoint Str.282 Str.127 Str.128 Str.129 Str.130:
let Str.414 : Int1 = CallByName Num.23 Str.226 Str.227; let Str.284 : Int1 = CallByName Num.23 Str.129 Str.130;
if Str.414 then if Str.284 then
let Str.418 : Int1 = CallByName Str.67 Str.224 Str.226 Str.225; let Str.288 : Int1 = CallByName Str.63 Str.127 Str.129 Str.128;
if Str.418 then if Str.288 then
dec Str.224; dec Str.127;
dec Str.225; dec Str.128;
let Str.419 : [C , C U64] = TagId(1) Str.226; let Str.289 : [C , C U64] = TagId(1) Str.129;
ret Str.419; ret Str.289;
else else
let Str.417 : U64 = 1i64; let Str.287 : U64 = 1i64;
let Str.416 : U64 = CallByName Num.51 Str.226 Str.417; let Str.286 : U64 = CallByName Num.51 Str.129 Str.287;
jump Str.412 Str.224 Str.225 Str.416 Str.227; jump Str.282 Str.127 Str.128 Str.286 Str.130;
else else
dec Str.224; dec Str.127;
dec Str.225; dec Str.128;
let Str.413 : [C , C U64] = TagId(0) ; let Str.283 : [C , C U64] = TagId(0) ;
ret Str.413; ret Str.283;
in in
inc #Derived_gen.5; inc Bool.29;
inc #Derived_gen.4; inc Bool.28;
jump Str.412 #Derived_gen.4 #Derived_gen.5 #Derived_gen.6 #Derived_gen.7; jump Str.282 Bool.28 Bool.29 Bool.30 Bool.31;
procedure Str.66 (Str.250, Str.251): procedure Str.62 (Str.153, Str.154):
let Str.442 : Int1 = CallByName Num.22 Str.250 Str.251; let Str.313 : Int1 = CallByName Num.22 Str.153 Str.154;
if Str.442 then if Str.313 then
ret Str.250; ret Str.153;
else else
ret Str.251; ret Str.154;
procedure Str.67 (Str.252, Str.253, Str.254): procedure Str.63 (Str.155, Str.156, Str.157):
let Str.255 : U64 = CallByName Str.36 Str.252; let Str.158 : U64 = CallByName Str.36 Str.155;
let Str.256 : U64 = CallByName Str.36 Str.254; let Str.159 : U64 = CallByName Str.36 Str.157;
let Str.440 : U64 = CallByName Num.53 Str.253 Str.256; let Str.311 : U64 = CallByName Num.53 Str.156 Str.159;
let Str.257 : U64 = CallByName Str.66 Str.440 Str.255; let Str.160 : U64 = CallByName Str.62 Str.311 Str.158;
let Str.439 : U64 = 0i64; let Str.310 : U64 = 0i64;
inc Str.252; inc Str.157;
inc Str.254; inc Str.155;
let Str.421 : {U64, Str, U64, Str, U64, U64} = Struct {Str.257, Str.252, Str.253, Str.254, Str.439, Str.256}; let Str.291 : {U64, Str, U64, Str, U64, U64} = Struct {Str.160, Str.155, Str.156, Str.157, Str.310, Str.159};
let Str.420 : Int1 = CallByName Str.68 Str.421; let Str.290 : Int1 = CallByName Str.64 Str.291;
ret Str.420; ret Str.290;
procedure Str.68 (Str.258): procedure Str.64 (Str.161):
let Str.264 : U64 = StructAtIndex 0 Str.258; let Str.167 : U64 = StructAtIndex 0 Str.161;
let Str.259 : Str = StructAtIndex 1 Str.258; let Str.162 : Str = StructAtIndex 1 Str.161;
let Str.260 : U64 = StructAtIndex 2 Str.258; let Str.163 : U64 = StructAtIndex 2 Str.161;
let Str.261 : Str = StructAtIndex 3 Str.258; let Str.164 : Str = StructAtIndex 3 Str.161;
let Str.262 : U64 = StructAtIndex 4 Str.258; let Str.165 : U64 = StructAtIndex 4 Str.161;
let Str.263 : U64 = StructAtIndex 5 Str.258; let Str.166 : U64 = StructAtIndex 5 Str.161;
let Str.265 : Int1 = CallByName Num.25 Str.260 Str.264; let Str.168 : Int1 = CallByName Num.25 Str.163 Str.167;
if Str.265 then if Str.168 then
dec Str.259; dec Str.162;
dec Str.261; dec Str.164;
let Str.266 : Int1 = CallByName Bool.11 Str.262 Str.263; let Str.169 : Int1 = CallByName Bool.9 Str.165 Str.166;
ret Str.266; ret Str.169;
else else
let Str.435 : U8 = CallByName Str.35 Str.259 Str.260; let Str.306 : U8 = CallByName Str.35 Str.162 Str.163;
let Str.436 : U8 = CallByName Str.35 Str.261 Str.262; let Str.307 : U8 = CallByName Str.35 Str.164 Str.165;
let Str.267 : Int1 = CallByName Bool.11 Str.435 Str.436; let Str.170 : Int1 = CallByName Bool.9 Str.306 Str.307;
let Str.425 : U64 = StructAtIndex 0 Str.258; let Str.296 : U64 = StructAtIndex 0 Str.161;
let Str.426 : Str = StructAtIndex 1 Str.258; let Str.297 : Str = StructAtIndex 1 Str.161;
let Str.428 : Str = StructAtIndex 3 Str.258; let Str.299 : Str = StructAtIndex 3 Str.161;
let Str.430 : U64 = StructAtIndex 5 Str.258; let Str.301 : U64 = StructAtIndex 5 Str.161;
let Str.434 : U64 = 1i64; let Str.305 : U64 = 1i64;
let Str.432 : U64 = CallByName Num.51 Str.262 Str.434; let Str.303 : U64 = CallByName Num.51 Str.165 Str.305;
let Str.433 : U64 = 1i64; let Str.304 : U64 = 1i64;
let Str.431 : U64 = CallByName Num.51 Str.260 Str.433; let Str.302 : U64 = CallByName Num.51 Str.163 Str.304;
let Str.424 : {U64, Str, U64, Str, U64, U64} = Struct {Str.425, Str.426, Str.431, Str.428, Str.432, Str.430}; let Str.295 : {U64, Str, U64, Str, U64, U64} = Struct {Str.296, Str.297, Str.302, Str.299, Str.303, Str.301};
let Str.268 : Int1 = CallByName Str.68 Str.424; let Str.171 : Int1 = CallByName Str.64 Str.295;
let Str.423 : Int1 = CallByName Bool.3 Str.267 Str.268; if Str.170 then
ret Str.423; ret Str.171;
else
let Str.293 : Int1 = CallByName Bool.1;
ret Str.293;
procedure Test.0 (): procedure Test.0 ():
let Test.5 : Str = "Hello "; let Test.4 : Str = "Hello ";
let Test.2 : Str = "world"; let Test.1 : Str = "world";
inc Test.2; inc Test.1;
let Test.3 : Str = CallByName Inspect.33 Test.2; let Test.2 : Str = CallByName Inspect.33 Test.1;
dbg Test.3; dbg Test.2;
dec Test.3; dec Test.2;
let Test.8 : Str = "!"; let Test.7 : Str = "!";
let Test.6 : Str = CallByName Str.3 Test.2 Test.8; let Test.5 : Str = CallByName Str.3 Test.1 Test.7;
dec Test.8; dec Test.7;
let Test.4 : Str = CallByName Str.3 Test.5 Test.6; let Test.3 : Str = CallByName Str.3 Test.4 Test.5;
dec Test.6; dec Test.5;
ret Test.4; ret Test.3;

View file

@ -39,18 +39,18 @@ procedure Num.96 (#Attr.2):
ret Num.283; ret Num.283;
procedure Str.3 (#Attr.2, #Attr.3): procedure Str.3 (#Attr.2, #Attr.3):
let Str.378 : Str = lowlevel StrConcat #Attr.2 #Attr.3; let Str.248 : Str = lowlevel StrConcat #Attr.2 #Attr.3;
ret Str.378; ret Str.248;
procedure Test.0 (): procedure Test.0 ():
let Test.6 : I64 = 1i64; let Test.3 : I64 = 1i64;
let Test.7 : Str = CallByName Inspect.33 Test.6; let Test.4 : Str = CallByName Inspect.33 Test.3;
dbg Test.7; dbg Test.4;
dec Test.7; dec Test.4;
let Test.8 : Str = CallByName Inspect.33 Test.6; let Test.5 : Str = CallByName Inspect.33 Test.3;
dbg Test.8; dbg Test.5;
dec Test.8; dec Test.5;
let Test.9 : Str = CallByName Inspect.33 Test.6; let Test.6 : Str = CallByName Inspect.33 Test.3;
dbg Test.9; dbg Test.6;
dec Test.9; dec Test.6;
ret Test.6; ret Test.3;

View file

@ -1,13 +1,13 @@
procedure Bool.11 (#Attr.2, #Attr.3): procedure Bool.1 ():
let Bool.24 : Int1 = lowlevel Eq #Attr.2 #Attr.3; let Bool.21 : Int1 = false;
ret Bool.24; ret Bool.21;
procedure Bool.11 (#Attr.2, #Attr.3): procedure Bool.9 (#Attr.2, #Attr.3):
let Bool.25 : Int1 = lowlevel Eq #Attr.2 #Attr.3; let Bool.22 : Int1 = lowlevel Eq #Attr.2 #Attr.3;
ret Bool.25; ret Bool.22;
procedure Bool.3 (#Attr.2, #Attr.3): procedure Bool.9 (#Attr.2, #Attr.3):
let Bool.23 : Int1 = lowlevel And #Attr.2 #Attr.3; let Bool.23 : Int1 = lowlevel Eq #Attr.2 #Attr.3;
ret Bool.23; ret Bool.23;
procedure Inspect.245 (Inspect.246, Inspect.244): procedure Inspect.245 (Inspect.246, Inspect.244):
@ -100,181 +100,184 @@ procedure Num.77 (#Attr.2, #Attr.3):
ret Num.293; ret Num.293;
procedure Str.20 (#Attr.2): procedure Str.20 (#Attr.2):
let Str.445 : Str = lowlevel StrWithCapacity #Attr.2; let Str.316 : Str = lowlevel StrWithCapacity #Attr.2;
ret Str.445; ret Str.316;
procedure Str.3 (#Attr.2, #Attr.3): procedure Str.3 (#Attr.2, #Attr.3):
let Str.378 : Str = lowlevel StrConcat #Attr.2 #Attr.3; let Str.248 : Str = lowlevel StrConcat #Attr.2 #Attr.3;
ret Str.378; ret Str.248;
procedure Str.35 (#Attr.2, #Attr.3): procedure Str.35 (#Attr.2, #Attr.3):
let Str.435 : U8 = lowlevel StrGetUnsafe #Attr.2 #Attr.3; let Str.306 : U8 = lowlevel StrGetUnsafe #Attr.2 #Attr.3;
ret Str.435; ret Str.306;
procedure Str.36 (#Attr.2): procedure Str.36 (#Attr.2):
let Str.398 : U64 = lowlevel StrCountUtf8Bytes #Attr.2; let Str.268 : U64 = lowlevel StrCountUtf8Bytes #Attr.2;
ret Str.398; ret Str.268;
procedure Str.37 (#Attr.2, #Attr.3, #Attr.4): procedure Str.37 (#Attr.2, #Attr.3, #Attr.4):
let Str.396 : Str = lowlevel StrSubstringUnsafe #Attr.2 #Attr.3 #Attr.4; let Str.266 : Str = lowlevel StrSubstringUnsafe #Attr.2 #Attr.3 #Attr.4;
ret Str.396;
procedure Str.38 (Str.210, Str.211):
let Str.392 : [C , C U64] = CallByName Str.62 Str.210 Str.211;
let Str.405 : U8 = 1i64;
let Str.406 : U8 = GetTagId Str.392;
let Str.407 : Int1 = lowlevel Eq Str.405 Str.406;
if Str.407 then
let Str.212 : U64 = UnionAtIndex (Id 1) (Index 0) Str.392;
let Str.401 : U64 = CallByName Str.36 Str.210;
let Str.402 : U64 = CallByName Str.36 Str.211;
let Str.400 : U64 = CallByName Num.20 Str.401 Str.402;
let Str.213 : U64 = CallByName Num.20 Str.400 Str.212;
let Str.399 : U64 = 0i64;
inc Str.210;
let Str.214 : Str = CallByName Str.37 Str.210 Str.399 Str.212;
let Str.397 : U64 = CallByName Str.36 Str.211;
let Str.395 : U64 = CallByName Num.51 Str.212 Str.397;
let Str.215 : Str = CallByName Str.37 Str.210 Str.395 Str.213;
let Str.394 : {Str, Str} = Struct {Str.215, Str.214};
let Str.393 : [C {}, C {Str, Str}] = TagId(1) Str.394;
ret Str.393;
else
dec Str.210;
let Str.404 : {} = Struct {};
let Str.403 : [C {}, C {Str, Str}] = TagId(0) Str.404;
ret Str.403;
procedure Str.45 (Str.189, Str.190, Str.191):
inc Str.189;
let Str.473 : [C {}, C {Str, Str}] = CallByName Str.38 Str.189 Str.190;
let Str.481 : U8 = 1i64;
let Str.482 : U8 = GetTagId Str.473;
let Str.483 : Int1 = lowlevel Eq Str.481 Str.482;
if Str.483 then
let Str.480 : {Str, Str} = UnionAtIndex (Id 1) (Index 0) Str.473;
let Str.193 : Str = StructAtIndex 0 Str.480;
let Str.192 : Str = StructAtIndex 1 Str.480;
let Str.478 : U64 = CallByName Str.36 Str.189;
dec Str.189;
let Str.477 : Str = CallByName Str.20 Str.478;
let Str.476 : Str = CallByName Str.3 Str.477 Str.192;
dec Str.192;
let Str.475 : Str = CallByName Str.3 Str.476 Str.191;
let Str.474 : Str = CallByName Str.61 Str.475 Str.193 Str.190 Str.191;
ret Str.474;
else
dec Str.473;
ret Str.189;
procedure Str.61 (#Derived_gen.0, #Derived_gen.1, #Derived_gen.2, #Derived_gen.3):
joinpoint Str.382 Str.194 Str.195 Str.196 Str.197:
inc Str.195;
let Str.383 : [C {}, C {Str, Str}] = CallByName Str.38 Str.195 Str.196;
let Str.389 : U8 = 1i64;
let Str.390 : U8 = GetTagId Str.383;
let Str.391 : Int1 = lowlevel Eq Str.389 Str.390;
if Str.391 then
dec Str.195;
let Str.388 : {Str, Str} = UnionAtIndex (Id 1) (Index 0) Str.383;
let Str.199 : Str = StructAtIndex 0 Str.388;
let Str.198 : Str = StructAtIndex 1 Str.388;
let Str.386 : Str = CallByName Str.3 Str.194 Str.198;
dec Str.198;
let Str.385 : Str = CallByName Str.3 Str.386 Str.197;
jump Str.382 Str.385 Str.199 Str.196 Str.197;
else
dec Str.196;
dec Str.383;
dec Str.197;
let Str.387 : Str = CallByName Str.3 Str.194 Str.195;
dec Str.195;
ret Str.387;
in
inc #Derived_gen.3;
inc #Derived_gen.2;
jump Str.382 #Derived_gen.0 #Derived_gen.1 #Derived_gen.2 #Derived_gen.3;
procedure Str.62 (Str.219, Str.220):
let Str.221 : U64 = CallByName Str.36 Str.219;
let Str.222 : U64 = CallByName Str.36 Str.220;
let Str.223 : U64 = CallByName Num.77 Str.221 Str.222;
let Str.409 : U64 = 0i64;
let Str.408 : [C , C U64] = CallByName Str.63 Str.219 Str.220 Str.409 Str.223;
ret Str.408;
procedure Str.63 (#Derived_gen.4, #Derived_gen.5, #Derived_gen.6, #Derived_gen.7):
joinpoint Str.410 Str.224 Str.225 Str.226 Str.227:
let Str.412 : Int1 = CallByName Num.23 Str.226 Str.227;
if Str.412 then
let Str.416 : Int1 = CallByName Str.67 Str.224 Str.226 Str.225;
if Str.416 then
dec Str.224;
dec Str.225;
let Str.417 : [C , C U64] = TagId(1) Str.226;
ret Str.417;
else
let Str.415 : U64 = 1i64;
let Str.414 : U64 = CallByName Num.51 Str.226 Str.415;
jump Str.410 Str.224 Str.225 Str.414 Str.227;
else
dec Str.224;
dec Str.225;
let Str.411 : [C , C U64] = TagId(0) ;
ret Str.411;
in
inc #Derived_gen.5;
inc #Derived_gen.4;
jump Str.410 #Derived_gen.4 #Derived_gen.5 #Derived_gen.6 #Derived_gen.7;
procedure Str.66 (Str.250, Str.251):
let Str.440 : Int1 = CallByName Num.22 Str.250 Str.251;
if Str.440 then
ret Str.250;
else
ret Str.251;
procedure Str.67 (Str.252, Str.253, Str.254):
let Str.255 : U64 = CallByName Str.36 Str.252;
let Str.256 : U64 = CallByName Str.36 Str.254;
let Str.438 : U64 = CallByName Num.53 Str.253 Str.256;
let Str.257 : U64 = CallByName Str.66 Str.438 Str.255;
let Str.437 : U64 = 0i64;
inc Str.252;
inc Str.254;
let Str.419 : {U64, Str, U64, Str, U64, U64} = Struct {Str.257, Str.252, Str.253, Str.254, Str.437, Str.256};
let Str.418 : Int1 = CallByName Str.68 Str.419;
ret Str.418;
procedure Str.68 (Str.258):
let Str.264 : U64 = StructAtIndex 0 Str.258;
let Str.259 : Str = StructAtIndex 1 Str.258;
let Str.260 : U64 = StructAtIndex 2 Str.258;
let Str.261 : Str = StructAtIndex 3 Str.258;
let Str.262 : U64 = StructAtIndex 4 Str.258;
let Str.263 : U64 = StructAtIndex 5 Str.258;
let Str.265 : Int1 = CallByName Num.25 Str.260 Str.264;
if Str.265 then
dec Str.259;
dec Str.261;
let Str.266 : Int1 = CallByName Bool.11 Str.262 Str.263;
ret Str.266; ret Str.266;
procedure Str.38 (Str.113, Str.114):
let Str.262 : [C , C U64] = CallByName Str.58 Str.113 Str.114;
let Str.275 : U8 = 1i64;
let Str.276 : U8 = GetTagId Str.262;
let Str.277 : Int1 = lowlevel Eq Str.275 Str.276;
if Str.277 then
let Str.115 : U64 = UnionAtIndex (Id 1) (Index 0) Str.262;
let Str.271 : U64 = CallByName Str.36 Str.113;
let Str.272 : U64 = CallByName Str.36 Str.114;
let Str.270 : U64 = CallByName Num.20 Str.271 Str.272;
let Str.116 : U64 = CallByName Num.20 Str.270 Str.115;
let Str.269 : U64 = 0i64;
inc Str.113;
let Str.117 : Str = CallByName Str.37 Str.113 Str.269 Str.115;
let Str.267 : U64 = CallByName Str.36 Str.114;
let Str.265 : U64 = CallByName Num.51 Str.115 Str.267;
let Str.118 : Str = CallByName Str.37 Str.113 Str.265 Str.116;
let Str.264 : {Str, Str} = Struct {Str.118, Str.117};
let Str.263 : [C {}, C {Str, Str}] = TagId(1) Str.264;
ret Str.263;
else else
let Str.433 : U8 = CallByName Str.35 Str.259 Str.260; dec Str.113;
let Str.434 : U8 = CallByName Str.35 Str.261 Str.262; let Str.274 : {} = Struct {};
let Str.267 : Int1 = CallByName Bool.11 Str.433 Str.434; let Str.273 : [C {}, C {Str, Str}] = TagId(0) Str.274;
let Str.423 : U64 = StructAtIndex 0 Str.258; ret Str.273;
let Str.424 : Str = StructAtIndex 1 Str.258;
let Str.426 : Str = StructAtIndex 3 Str.258; procedure Str.45 (Str.92, Str.93, Str.94):
let Str.428 : U64 = StructAtIndex 5 Str.258; inc Str.92;
let Str.432 : U64 = 1i64; let Str.344 : [C {}, C {Str, Str}] = CallByName Str.38 Str.92 Str.93;
let Str.430 : U64 = CallByName Num.51 Str.262 Str.432; let Str.352 : U8 = 1i64;
let Str.431 : U64 = 1i64; let Str.353 : U8 = GetTagId Str.344;
let Str.429 : U64 = CallByName Num.51 Str.260 Str.431; let Str.354 : Int1 = lowlevel Eq Str.352 Str.353;
let Str.422 : {U64, Str, U64, Str, U64, U64} = Struct {Str.423, Str.424, Str.429, Str.426, Str.430, Str.428}; if Str.354 then
let Str.268 : Int1 = CallByName Str.68 Str.422; let Str.351 : {Str, Str} = UnionAtIndex (Id 1) (Index 0) Str.344;
let Str.421 : Int1 = CallByName Bool.3 Str.267 Str.268; let Str.96 : Str = StructAtIndex 0 Str.351;
ret Str.421; let Str.95 : Str = StructAtIndex 1 Str.351;
let Str.349 : U64 = CallByName Str.36 Str.92;
dec Str.92;
let Str.348 : Str = CallByName Str.20 Str.349;
let Str.347 : Str = CallByName Str.3 Str.348 Str.95;
dec Str.95;
let Str.346 : Str = CallByName Str.3 Str.347 Str.94;
let Str.345 : Str = CallByName Str.57 Str.346 Str.96 Str.93 Str.94;
ret Str.345;
else
dec Str.344;
ret Str.92;
procedure Str.57 (Bool.24, Bool.25, Bool.26, Bool.27):
joinpoint Str.252 Str.97 Str.98 Str.99 Str.100:
inc Str.98;
let Str.253 : [C {}, C {Str, Str}] = CallByName Str.38 Str.98 Str.99;
let Str.259 : U8 = 1i64;
let Str.260 : U8 = GetTagId Str.253;
let Str.261 : Int1 = lowlevel Eq Str.259 Str.260;
if Str.261 then
dec Str.98;
let Str.258 : {Str, Str} = UnionAtIndex (Id 1) (Index 0) Str.253;
let Str.102 : Str = StructAtIndex 0 Str.258;
let Str.101 : Str = StructAtIndex 1 Str.258;
let Str.256 : Str = CallByName Str.3 Str.97 Str.101;
dec Str.101;
let Str.255 : Str = CallByName Str.3 Str.256 Str.100;
jump Str.252 Str.255 Str.102 Str.99 Str.100;
else
dec Str.100;
dec Str.99;
dec Str.253;
let Str.257 : Str = CallByName Str.3 Str.97 Str.98;
dec Str.98;
ret Str.257;
in
inc Bool.26;
inc Bool.27;
jump Str.252 Bool.24 Bool.25 Bool.26 Bool.27;
procedure Str.58 (Str.122, Str.123):
let Str.124 : U64 = CallByName Str.36 Str.122;
let Str.125 : U64 = CallByName Str.36 Str.123;
let Str.126 : U64 = CallByName Num.77 Str.124 Str.125;
let Str.279 : U64 = 0i64;
let Str.278 : [C , C U64] = CallByName Str.59 Str.122 Str.123 Str.279 Str.126;
ret Str.278;
procedure Str.59 (Bool.28, Bool.29, Bool.30, Bool.31):
joinpoint Str.280 Str.127 Str.128 Str.129 Str.130:
let Str.282 : Int1 = CallByName Num.23 Str.129 Str.130;
if Str.282 then
let Str.286 : Int1 = CallByName Str.63 Str.127 Str.129 Str.128;
if Str.286 then
dec Str.127;
dec Str.128;
let Str.287 : [C , C U64] = TagId(1) Str.129;
ret Str.287;
else
let Str.285 : U64 = 1i64;
let Str.284 : U64 = CallByName Num.51 Str.129 Str.285;
jump Str.280 Str.127 Str.128 Str.284 Str.130;
else
dec Str.127;
dec Str.128;
let Str.281 : [C , C U64] = TagId(0) ;
ret Str.281;
in
inc Bool.29;
inc Bool.28;
jump Str.280 Bool.28 Bool.29 Bool.30 Bool.31;
procedure Str.62 (Str.153, Str.154):
let Str.311 : Int1 = CallByName Num.22 Str.153 Str.154;
if Str.311 then
ret Str.153;
else
ret Str.154;
procedure Str.63 (Str.155, Str.156, Str.157):
let Str.158 : U64 = CallByName Str.36 Str.155;
let Str.159 : U64 = CallByName Str.36 Str.157;
let Str.309 : U64 = CallByName Num.53 Str.156 Str.159;
let Str.160 : U64 = CallByName Str.62 Str.309 Str.158;
let Str.308 : U64 = 0i64;
inc Str.157;
inc Str.155;
let Str.289 : {U64, Str, U64, Str, U64, U64} = Struct {Str.160, Str.155, Str.156, Str.157, Str.308, Str.159};
let Str.288 : Int1 = CallByName Str.64 Str.289;
ret Str.288;
procedure Str.64 (Str.161):
let Str.167 : U64 = StructAtIndex 0 Str.161;
let Str.162 : Str = StructAtIndex 1 Str.161;
let Str.163 : U64 = StructAtIndex 2 Str.161;
let Str.164 : Str = StructAtIndex 3 Str.161;
let Str.165 : U64 = StructAtIndex 4 Str.161;
let Str.166 : U64 = StructAtIndex 5 Str.161;
let Str.168 : Int1 = CallByName Num.25 Str.163 Str.167;
if Str.168 then
dec Str.162;
dec Str.164;
let Str.169 : Int1 = CallByName Bool.9 Str.165 Str.166;
ret Str.169;
else
let Str.304 : U8 = CallByName Str.35 Str.162 Str.163;
let Str.305 : U8 = CallByName Str.35 Str.164 Str.165;
let Str.170 : Int1 = CallByName Bool.9 Str.304 Str.305;
let Str.294 : U64 = StructAtIndex 0 Str.161;
let Str.295 : Str = StructAtIndex 1 Str.161;
let Str.297 : Str = StructAtIndex 3 Str.161;
let Str.299 : U64 = StructAtIndex 5 Str.161;
let Str.303 : U64 = 1i64;
let Str.301 : U64 = CallByName Num.51 Str.165 Str.303;
let Str.302 : U64 = 1i64;
let Str.300 : U64 = CallByName Num.51 Str.163 Str.302;
let Str.293 : {U64, Str, U64, Str, U64, U64} = Struct {Str.294, Str.295, Str.300, Str.297, Str.301, Str.299};
let Str.171 : Int1 = CallByName Str.64 Str.293;
if Str.170 then
ret Str.171;
else
let Str.291 : Int1 = CallByName Bool.1;
ret Str.291;
procedure Test.0 (): procedure Test.0 ():
let Test.3 : Str = ""; let Test.3 : Str = "";

View file

@ -1,6 +1,6 @@
procedure Bool.11 (#Attr.2, #Attr.3): procedure Bool.9 (#Attr.2, #Attr.3):
let Bool.24 : Int1 = lowlevel Eq #Attr.2 #Attr.3; let Bool.22 : Int1 = lowlevel Eq #Attr.2 #Attr.3;
ret Bool.24; ret Bool.22;
procedure Num.19 (#Attr.2, #Attr.3): procedure Num.19 (#Attr.2, #Attr.3):
let Num.285 : I64 = lowlevel NumAdd #Attr.2 #Attr.3; let Num.285 : I64 = lowlevel NumAdd #Attr.2 #Attr.3;
@ -11,8 +11,8 @@ procedure Num.96 (#Attr.2):
ret Num.284; ret Num.284;
procedure Str.3 (#Attr.2, #Attr.3): procedure Str.3 (#Attr.2, #Attr.3):
let Str.379 : Str = lowlevel StrConcat #Attr.2 #Attr.3; let Str.249 : Str = lowlevel StrConcat #Attr.2 #Attr.3;
ret Str.379; ret Str.249;
procedure Test.1 (Test.2): procedure Test.1 (Test.2):
let Test.3 : Str = CallByName Num.96 Test.2; let Test.3 : Str = CallByName Num.96 Test.2;
@ -25,7 +25,7 @@ procedure Test.1 (Test.2):
ret Test.8; ret Test.8;
in in
let Test.22 : I64 = 1i64; let Test.22 : I64 = 1i64;
let Test.20 : Int1 = CallByName Bool.11 Test.2 Test.22; let Test.20 : Int1 = CallByName Bool.9 Test.2 Test.22;
if Test.20 then if Test.20 then
dec Test.3; dec Test.3;
let Test.21 : Str = "early 1"; let Test.21 : Str = "early 1";
@ -38,7 +38,7 @@ procedure Test.1 (Test.2):
jump Test.12 Test.11; jump Test.12 Test.11;
in in
let Test.17 : I64 = 2i64; let Test.17 : I64 = 2i64;
let Test.15 : Int1 = CallByName Bool.11 Test.2 Test.17; let Test.15 : Int1 = CallByName Bool.9 Test.2 Test.17;
if Test.15 then if Test.15 then
dec Test.3; dec Test.3;
dec Test.5; dec Test.5;

View file

@ -9,8 +9,8 @@ procedure Dict.1 (Dict.732):
procedure Dict.4 (Dict.738): procedure Dict.4 (Dict.738):
let Dict.163 : List {[], []} = StructAtIndex 1 Dict.738; let Dict.163 : List {[], []} = StructAtIndex 1 Dict.738;
let #Derived_gen.0 : List {U32, U32} = StructAtIndex 0 Dict.738; let Bool.21 : List {U32, U32} = StructAtIndex 0 Dict.738;
dec #Derived_gen.0; dec Bool.21;
let Dict.739 : U64 = CallByName List.6 Dict.163; let Dict.739 : U64 = CallByName List.6 Dict.163;
dec Dict.163; dec Dict.163;
ret Dict.739; ret Dict.739;

View file

@ -1,6 +1,6 @@
procedure Bool.2 (): procedure Bool.2 ():
let Bool.23 : Int1 = true; let Bool.21 : Int1 = true;
ret Bool.23; ret Bool.21;
procedure Test.2 (Test.5): procedure Test.2 (Test.5):
let Test.6 : Int1 = CallByName Bool.2; let Test.6 : Int1 = CallByName Bool.2;

View file

@ -1,6 +1,6 @@
procedure Bool.2 (): procedure Bool.2 ():
let Bool.23 : Int1 = true; let Bool.21 : Int1 = true;
ret Bool.23; ret Bool.21;
procedure Test.2 (Test.5): procedure Test.2 (Test.5):
let Test.6 : Int1 = CallByName Bool.2; let Test.6 : Int1 = CallByName Bool.2;

View file

@ -1,6 +1,6 @@
procedure Bool.1 (): procedure Bool.1 ():
let Bool.23 : Int1 = false; let Bool.21 : Int1 = false;
ret Bool.23; ret Bool.21;
procedure List.2 (List.120, List.121): procedure List.2 (List.120, List.121):
let List.681 : U64 = CallByName List.6 List.120; let List.681 : U64 = CallByName List.6 List.120;

View file

@ -67,7 +67,7 @@ procedure Encode.26 (Encode.107, Encode.108):
let Encode.110 : List U8 = CallByName Encode.24 Encode.111 Encode.112 Encode.108; let Encode.110 : List U8 = CallByName Encode.24 Encode.111 Encode.112 Encode.108;
ret Encode.110; ret Encode.110;
procedure List.101 (#Derived_gen.26, #Derived_gen.27, #Derived_gen.28, #Derived_gen.29, #Derived_gen.30): procedure List.101 (#Derived_gen.35, #Derived_gen.36, #Derived_gen.37, #Derived_gen.38, #Derived_gen.39):
joinpoint List.678 List.175 List.176 List.177 List.178 List.179: joinpoint List.678 List.175 List.176 List.177 List.178 List.179:
let List.680 : Int1 = CallByName Num.22 List.178 List.179; let List.680 : Int1 = CallByName Num.22 List.178 List.179;
if List.680 then if List.680 then
@ -81,10 +81,10 @@ procedure List.101 (#Derived_gen.26, #Derived_gen.27, #Derived_gen.28, #Derived_
dec List.175; dec List.175;
ret List.176; ret List.176;
in in
inc #Derived_gen.26; inc #Derived_gen.35;
jump List.678 #Derived_gen.26 #Derived_gen.27 #Derived_gen.28 #Derived_gen.29 #Derived_gen.30; jump List.678 #Derived_gen.35 #Derived_gen.36 #Derived_gen.37 #Derived_gen.38 #Derived_gen.39;
procedure List.101 (#Derived_gen.31, #Derived_gen.32, #Derived_gen.33, #Derived_gen.34, #Derived_gen.35): procedure List.101 (#Derived_gen.40, #Derived_gen.41, #Derived_gen.42, #Derived_gen.43, #Derived_gen.44):
joinpoint List.704 List.175 List.176 List.177 List.178 List.179: joinpoint List.704 List.175 List.176 List.177 List.178 List.179:
let List.706 : Int1 = CallByName Num.22 List.178 List.179; let List.706 : Int1 = CallByName Num.22 List.178 List.179;
if List.706 then if List.706 then
@ -98,8 +98,8 @@ procedure List.101 (#Derived_gen.31, #Derived_gen.32, #Derived_gen.33, #Derived_
dec List.175; dec List.175;
ret List.176; ret List.176;
in in
inc #Derived_gen.31; inc #Derived_gen.40;
jump List.704 #Derived_gen.31 #Derived_gen.32 #Derived_gen.33 #Derived_gen.34 #Derived_gen.35; jump List.704 #Derived_gen.40 #Derived_gen.41 #Derived_gen.42 #Derived_gen.43 #Derived_gen.44;
procedure List.18 (List.172, List.173, List.174): procedure List.18 (List.172, List.173, List.174):
let List.676 : U64 = 0i64; let List.676 : U64 = 0i64;
@ -164,32 +164,32 @@ procedure Num.96 (#Attr.2):
ret Num.287; ret Num.287;
procedure Str.12 (#Attr.2): procedure Str.12 (#Attr.2):
let Str.391 : List U8 = lowlevel StrToUtf8 #Attr.2; let Str.261 : List U8 = lowlevel StrToUtf8 #Attr.2;
ret Str.391; ret Str.261;
procedure Str.36 (#Attr.2): procedure Str.36 (#Attr.2):
let Str.392 : U64 = lowlevel StrCountUtf8Bytes #Attr.2; let Str.262 : U64 = lowlevel StrCountUtf8Bytes #Attr.2;
ret Str.392; ret Str.262;
procedure Str.43 (#Attr.2): procedure Str.43 (#Attr.2):
let Str.386 : {U64, Str, Int1, U8} = lowlevel StrFromUtf8 #Attr.2; let Str.256 : {U64, Str, Int1, U8} = lowlevel StrFromUtf8 #Attr.2;
ret Str.386; ret Str.256;
procedure Str.9 (Str.76): procedure Str.9 (Str.74):
let Str.77 : {U64, Str, Int1, U8} = CallByName Str.43 Str.76; let Str.75 : {U64, Str, Int1, U8} = CallByName Str.43 Str.74;
let Str.383 : Int1 = StructAtIndex 2 Str.77; let Str.253 : Int1 = StructAtIndex 2 Str.75;
if Str.383 then if Str.253 then
let Str.385 : Str = StructAtIndex 1 Str.77; let Str.255 : Str = StructAtIndex 1 Str.75;
let Str.384 : [C {U64, U8}, C Str] = TagId(1) Str.385; let Str.254 : [C {U64, U8}, C Str] = TagId(1) Str.255;
ret Str.384; ret Str.254;
else else
let Str.381 : U64 = StructAtIndex 0 Str.77; let Str.251 : U64 = StructAtIndex 0 Str.75;
let Str.382 : U8 = StructAtIndex 3 Str.77; let Str.252 : U8 = StructAtIndex 3 Str.75;
let #Derived_gen.45 : Str = StructAtIndex 1 Str.77; let #Derived_gen.45 : Str = StructAtIndex 1 Str.75;
dec #Derived_gen.45; dec #Derived_gen.45;
let Str.380 : {U64, U8} = Struct {Str.381, Str.382}; let Str.250 : {U64, U8} = Struct {Str.251, Str.252};
let Str.378 : [C {U64, U8}, C Str] = TagId(0) Str.380; let Str.248 : [C {U64, U8}, C Str] = TagId(0) Str.250;
ret Str.378; ret Str.248;
procedure Test.20 (Test.56): procedure Test.20 (Test.56):
let Test.325 : Str = CallByName Encode.23 Test.56; let Test.325 : Str = CallByName Encode.23 Test.56;

View file

@ -39,7 +39,7 @@ procedure Encode.26 (Encode.107, Encode.108):
let Encode.110 : List U8 = CallByName Encode.24 Encode.111 Encode.112 Encode.108; let Encode.110 : List U8 = CallByName Encode.24 Encode.111 Encode.112 Encode.108;
ret Encode.110; ret Encode.110;
procedure List.101 (#Derived_gen.16, #Derived_gen.17, #Derived_gen.18, #Derived_gen.19, #Derived_gen.20): procedure List.101 (#Derived_gen.19, #Derived_gen.20, #Derived_gen.21, #Derived_gen.22, #Derived_gen.23):
joinpoint List.678 List.175 List.176 List.177 List.178 List.179: joinpoint List.678 List.175 List.176 List.177 List.178 List.179:
let List.680 : Int1 = CallByName Num.22 List.178 List.179; let List.680 : Int1 = CallByName Num.22 List.178 List.179;
if List.680 then if List.680 then
@ -53,8 +53,8 @@ procedure List.101 (#Derived_gen.16, #Derived_gen.17, #Derived_gen.18, #Derived_
dec List.175; dec List.175;
ret List.176; ret List.176;
in in
inc #Derived_gen.16; inc #Derived_gen.19;
jump List.678 #Derived_gen.16 #Derived_gen.17 #Derived_gen.18 #Derived_gen.19 #Derived_gen.20; jump List.678 #Derived_gen.19 #Derived_gen.20 #Derived_gen.21 #Derived_gen.22 #Derived_gen.23;
procedure List.18 (List.172, List.173, List.174): procedure List.18 (List.172, List.173, List.174):
let List.676 : U64 = 0i64; let List.676 : U64 = 0i64;
@ -105,32 +105,32 @@ procedure Num.96 (#Attr.2):
ret Num.283; ret Num.283;
procedure Str.12 (#Attr.2): procedure Str.12 (#Attr.2):
let Str.388 : List U8 = lowlevel StrToUtf8 #Attr.2; let Str.258 : List U8 = lowlevel StrToUtf8 #Attr.2;
ret Str.388; ret Str.258;
procedure Str.36 (#Attr.2): procedure Str.36 (#Attr.2):
let Str.389 : U64 = lowlevel StrCountUtf8Bytes #Attr.2; let Str.259 : U64 = lowlevel StrCountUtf8Bytes #Attr.2;
ret Str.389; ret Str.259;
procedure Str.43 (#Attr.2): procedure Str.43 (#Attr.2):
let Str.386 : {U64, Str, Int1, U8} = lowlevel StrFromUtf8 #Attr.2; let Str.256 : {U64, Str, Int1, U8} = lowlevel StrFromUtf8 #Attr.2;
ret Str.386; ret Str.256;
procedure Str.9 (Str.76): procedure Str.9 (Str.74):
let Str.77 : {U64, Str, Int1, U8} = CallByName Str.43 Str.76; let Str.75 : {U64, Str, Int1, U8} = CallByName Str.43 Str.74;
let Str.383 : Int1 = StructAtIndex 2 Str.77; let Str.253 : Int1 = StructAtIndex 2 Str.75;
if Str.383 then if Str.253 then
let Str.385 : Str = StructAtIndex 1 Str.77; let Str.255 : Str = StructAtIndex 1 Str.75;
let Str.384 : [C {U64, U8}, C Str] = TagId(1) Str.385; let Str.254 : [C {U64, U8}, C Str] = TagId(1) Str.255;
ret Str.384; ret Str.254;
else else
let Str.381 : U64 = StructAtIndex 0 Str.77; let Str.251 : U64 = StructAtIndex 0 Str.75;
let Str.382 : U8 = StructAtIndex 3 Str.77; let Str.252 : U8 = StructAtIndex 3 Str.75;
let #Derived_gen.24 : Str = StructAtIndex 1 Str.77; let #Derived_gen.24 : Str = StructAtIndex 1 Str.75;
dec #Derived_gen.24; dec #Derived_gen.24;
let Str.380 : {U64, U8} = Struct {Str.381, Str.382}; let Str.250 : {U64, U8} = Struct {Str.251, Str.252};
let Str.378 : [C {U64, U8}, C Str] = TagId(0) Str.380; let Str.248 : [C {U64, U8}, C Str] = TagId(0) Str.250;
ret Str.378; ret Str.248;
procedure Test.20 (Test.56): procedure Test.20 (Test.56):
let Test.292 : Str = CallByName Encode.23 Test.56; let Test.292 : Str = CallByName Encode.23 Test.56;

View file

@ -46,7 +46,7 @@ procedure Encode.26 (Encode.107, Encode.108):
let Encode.110 : List U8 = CallByName Encode.24 Encode.111 Encode.112 Encode.108; let Encode.110 : List U8 = CallByName Encode.24 Encode.111 Encode.112 Encode.108;
ret Encode.110; ret Encode.110;
procedure List.101 (#Derived_gen.20, #Derived_gen.21, #Derived_gen.22, #Derived_gen.23, #Derived_gen.24): procedure List.101 (#Derived_gen.23, #Derived_gen.24, #Derived_gen.25, #Derived_gen.26, #Derived_gen.27):
joinpoint List.678 List.175 List.176 List.177 List.178 List.179: joinpoint List.678 List.175 List.176 List.177 List.178 List.179:
let List.680 : Int1 = CallByName Num.22 List.178 List.179; let List.680 : Int1 = CallByName Num.22 List.178 List.179;
if List.680 then if List.680 then
@ -60,8 +60,8 @@ procedure List.101 (#Derived_gen.20, #Derived_gen.21, #Derived_gen.22, #Derived_
dec List.175; dec List.175;
ret List.176; ret List.176;
in in
inc #Derived_gen.20; inc #Derived_gen.23;
jump List.678 #Derived_gen.20 #Derived_gen.21 #Derived_gen.22 #Derived_gen.23 #Derived_gen.24; jump List.678 #Derived_gen.23 #Derived_gen.24 #Derived_gen.25 #Derived_gen.26 #Derived_gen.27;
procedure List.18 (List.172, List.173, List.174): procedure List.18 (List.172, List.173, List.174):
let List.676 : U64 = 0i64; let List.676 : U64 = 0i64;
@ -112,32 +112,32 @@ procedure Num.96 (#Attr.2):
ret Num.283; ret Num.283;
procedure Str.12 (#Attr.2): procedure Str.12 (#Attr.2):
let Str.388 : List U8 = lowlevel StrToUtf8 #Attr.2; let Str.258 : List U8 = lowlevel StrToUtf8 #Attr.2;
ret Str.388; ret Str.258;
procedure Str.36 (#Attr.2): procedure Str.36 (#Attr.2):
let Str.389 : U64 = lowlevel StrCountUtf8Bytes #Attr.2; let Str.259 : U64 = lowlevel StrCountUtf8Bytes #Attr.2;
ret Str.389; ret Str.259;
procedure Str.43 (#Attr.2): procedure Str.43 (#Attr.2):
let Str.386 : {U64, Str, Int1, U8} = lowlevel StrFromUtf8 #Attr.2; let Str.256 : {U64, Str, Int1, U8} = lowlevel StrFromUtf8 #Attr.2;
ret Str.386; ret Str.256;
procedure Str.9 (Str.76): procedure Str.9 (Str.74):
let Str.77 : {U64, Str, Int1, U8} = CallByName Str.43 Str.76; let Str.75 : {U64, Str, Int1, U8} = CallByName Str.43 Str.74;
let Str.383 : Int1 = StructAtIndex 2 Str.77; let Str.253 : Int1 = StructAtIndex 2 Str.75;
if Str.383 then if Str.253 then
let Str.385 : Str = StructAtIndex 1 Str.77; let Str.255 : Str = StructAtIndex 1 Str.75;
let Str.384 : [C {U64, U8}, C Str] = TagId(1) Str.385; let Str.254 : [C {U64, U8}, C Str] = TagId(1) Str.255;
ret Str.384; ret Str.254;
else else
let Str.381 : U64 = StructAtIndex 0 Str.77; let Str.251 : U64 = StructAtIndex 0 Str.75;
let Str.382 : U8 = StructAtIndex 3 Str.77; let Str.252 : U8 = StructAtIndex 3 Str.75;
let #Derived_gen.28 : Str = StructAtIndex 1 Str.77; let #Derived_gen.28 : Str = StructAtIndex 1 Str.75;
dec #Derived_gen.28; dec #Derived_gen.28;
let Str.380 : {U64, U8} = Struct {Str.381, Str.382}; let Str.250 : {U64, U8} = Struct {Str.251, Str.252};
let Str.378 : [C {U64, U8}, C Str] = TagId(0) Str.380; let Str.248 : [C {U64, U8}, C Str] = TagId(0) Str.250;
ret Str.378; ret Str.248;
procedure Test.20 (Test.56): procedure Test.20 (Test.56):
let Test.296 : Str = CallByName Encode.23 Test.56; let Test.296 : Str = CallByName Encode.23 Test.56;

View file

@ -38,32 +38,32 @@ procedure Num.96 (#Attr.2):
ret Num.283; ret Num.283;
procedure Str.12 (#Attr.2): procedure Str.12 (#Attr.2):
let Str.388 : List U8 = lowlevel StrToUtf8 #Attr.2; let Str.258 : List U8 = lowlevel StrToUtf8 #Attr.2;
ret Str.388; ret Str.258;
procedure Str.36 (#Attr.2): procedure Str.36 (#Attr.2):
let Str.389 : U64 = lowlevel StrCountUtf8Bytes #Attr.2; let Str.259 : U64 = lowlevel StrCountUtf8Bytes #Attr.2;
ret Str.389; ret Str.259;
procedure Str.43 (#Attr.2): procedure Str.43 (#Attr.2):
let Str.386 : {U64, Str, Int1, U8} = lowlevel StrFromUtf8 #Attr.2; let Str.256 : {U64, Str, Int1, U8} = lowlevel StrFromUtf8 #Attr.2;
ret Str.386; ret Str.256;
procedure Str.9 (Str.76): procedure Str.9 (Str.74):
let Str.77 : {U64, Str, Int1, U8} = CallByName Str.43 Str.76; let Str.75 : {U64, Str, Int1, U8} = CallByName Str.43 Str.74;
let Str.383 : Int1 = StructAtIndex 2 Str.77; let Str.253 : Int1 = StructAtIndex 2 Str.75;
if Str.383 then if Str.253 then
let Str.385 : Str = StructAtIndex 1 Str.77; let Str.255 : Str = StructAtIndex 1 Str.75;
let Str.384 : [C {U64, U8}, C Str] = TagId(1) Str.385; let Str.254 : [C {U64, U8}, C Str] = TagId(1) Str.255;
ret Str.384; ret Str.254;
else else
let Str.381 : U64 = StructAtIndex 0 Str.77; let Str.251 : U64 = StructAtIndex 0 Str.75;
let Str.382 : U8 = StructAtIndex 3 Str.77; let Str.252 : U8 = StructAtIndex 3 Str.75;
let #Derived_gen.3 : Str = StructAtIndex 1 Str.77; let #Derived_gen.3 : Str = StructAtIndex 1 Str.75;
dec #Derived_gen.3; dec #Derived_gen.3;
let Str.380 : {U64, U8} = Struct {Str.381, Str.382}; let Str.250 : {U64, U8} = Struct {Str.251, Str.252};
let Str.378 : [C {U64, U8}, C Str] = TagId(0) Str.380; let Str.248 : [C {U64, U8}, C Str] = TagId(0) Str.250;
ret Str.378; ret Str.248;
procedure Test.20 (Test.56): procedure Test.20 (Test.56):
let Test.259 : Str = CallByName Encode.23 Test.56; let Test.259 : Str = CallByName Encode.23 Test.56;

View file

@ -40,7 +40,7 @@ procedure Encode.26 (Encode.107, Encode.108):
let Encode.110 : List U8 = CallByName Encode.24 Encode.111 Encode.112 Encode.108; let Encode.110 : List U8 = CallByName Encode.24 Encode.111 Encode.112 Encode.108;
ret Encode.110; ret Encode.110;
procedure List.101 (#Derived_gen.10, #Derived_gen.11, #Derived_gen.12, #Derived_gen.13, #Derived_gen.14): procedure List.101 (#Derived_gen.22, #Derived_gen.23, #Derived_gen.24, #Derived_gen.25, #Derived_gen.26):
joinpoint List.678 List.175 List.176 List.177 List.178 List.179: joinpoint List.678 List.175 List.176 List.177 List.178 List.179:
let List.680 : Int1 = CallByName Num.22 List.178 List.179; let List.680 : Int1 = CallByName Num.22 List.178 List.179;
if List.680 then if List.680 then
@ -54,8 +54,8 @@ procedure List.101 (#Derived_gen.10, #Derived_gen.11, #Derived_gen.12, #Derived_
dec List.175; dec List.175;
ret List.176; ret List.176;
in in
inc #Derived_gen.10; inc #Derived_gen.22;
jump List.678 #Derived_gen.10 #Derived_gen.11 #Derived_gen.12 #Derived_gen.13 #Derived_gen.14; jump List.678 #Derived_gen.22 #Derived_gen.23 #Derived_gen.24 #Derived_gen.25 #Derived_gen.26;
procedure List.13 (#Attr.2, #Attr.3): procedure List.13 (#Attr.2, #Attr.3):
let List.701 : List Str = lowlevel ListPrepend #Attr.2 #Attr.3; let List.701 : List Str = lowlevel ListPrepend #Attr.2 #Attr.3;
@ -110,32 +110,32 @@ procedure Num.96 (#Attr.2):
ret Num.283; ret Num.283;
procedure Str.12 (#Attr.2): procedure Str.12 (#Attr.2):
let Str.388 : List U8 = lowlevel StrToUtf8 #Attr.2; let Str.258 : List U8 = lowlevel StrToUtf8 #Attr.2;
ret Str.388; ret Str.258;
procedure Str.36 (#Attr.2): procedure Str.36 (#Attr.2):
let Str.389 : U64 = lowlevel StrCountUtf8Bytes #Attr.2; let Str.259 : U64 = lowlevel StrCountUtf8Bytes #Attr.2;
ret Str.389; ret Str.259;
procedure Str.43 (#Attr.2): procedure Str.43 (#Attr.2):
let Str.386 : {U64, Str, Int1, U8} = lowlevel StrFromUtf8 #Attr.2; let Str.256 : {U64, Str, Int1, U8} = lowlevel StrFromUtf8 #Attr.2;
ret Str.386; ret Str.256;
procedure Str.9 (Str.76): procedure Str.9 (Str.74):
let Str.77 : {U64, Str, Int1, U8} = CallByName Str.43 Str.76; let Str.75 : {U64, Str, Int1, U8} = CallByName Str.43 Str.74;
let Str.383 : Int1 = StructAtIndex 2 Str.77; let Str.253 : Int1 = StructAtIndex 2 Str.75;
if Str.383 then if Str.253 then
let Str.385 : Str = StructAtIndex 1 Str.77; let Str.255 : Str = StructAtIndex 1 Str.75;
let Str.384 : [C {U64, U8}, C Str] = TagId(1) Str.385; let Str.254 : [C {U64, U8}, C Str] = TagId(1) Str.255;
ret Str.384; ret Str.254;
else else
let Str.381 : U64 = StructAtIndex 0 Str.77; let Str.251 : U64 = StructAtIndex 0 Str.75;
let Str.382 : U8 = StructAtIndex 3 Str.77; let Str.252 : U8 = StructAtIndex 3 Str.75;
let #Derived_gen.27 : Str = StructAtIndex 1 Str.77; let #Derived_gen.27 : Str = StructAtIndex 1 Str.75;
dec #Derived_gen.27; dec #Derived_gen.27;
let Str.380 : {U64, U8} = Struct {Str.381, Str.382}; let Str.250 : {U64, U8} = Struct {Str.251, Str.252};
let Str.378 : [C {U64, U8}, C Str] = TagId(0) Str.380; let Str.248 : [C {U64, U8}, C Str] = TagId(0) Str.250;
ret Str.378; ret Str.248;
procedure Test.20 (Test.56): procedure Test.20 (Test.56):
let Test.297 : Str = CallByName Encode.23 Test.56; let Test.297 : Str = CallByName Encode.23 Test.56;

View file

@ -43,7 +43,7 @@ procedure Encode.26 (Encode.107, Encode.108):
let Encode.110 : List U8 = CallByName Encode.24 Encode.111 Encode.112 Encode.108; let Encode.110 : List U8 = CallByName Encode.24 Encode.111 Encode.112 Encode.108;
ret Encode.110; ret Encode.110;
procedure List.101 (#Derived_gen.20, #Derived_gen.21, #Derived_gen.22, #Derived_gen.23, #Derived_gen.24): procedure List.101 (#Derived_gen.23, #Derived_gen.24, #Derived_gen.25, #Derived_gen.26, #Derived_gen.27):
joinpoint List.678 List.175 List.176 List.177 List.178 List.179: joinpoint List.678 List.175 List.176 List.177 List.178 List.179:
let List.680 : Int1 = CallByName Num.22 List.178 List.179; let List.680 : Int1 = CallByName Num.22 List.178 List.179;
if List.680 then if List.680 then
@ -57,8 +57,8 @@ procedure List.101 (#Derived_gen.20, #Derived_gen.21, #Derived_gen.22, #Derived_
dec List.175; dec List.175;
ret List.176; ret List.176;
in in
inc #Derived_gen.20; inc #Derived_gen.23;
jump List.678 #Derived_gen.20 #Derived_gen.21 #Derived_gen.22 #Derived_gen.23 #Derived_gen.24; jump List.678 #Derived_gen.23 #Derived_gen.24 #Derived_gen.25 #Derived_gen.26 #Derived_gen.27;
procedure List.13 (#Attr.2, #Attr.3): procedure List.13 (#Attr.2, #Attr.3):
let List.701 : List Str = lowlevel ListPrepend #Attr.2 #Attr.3; let List.701 : List Str = lowlevel ListPrepend #Attr.2 #Attr.3;
@ -113,32 +113,32 @@ procedure Num.96 (#Attr.2):
ret Num.283; ret Num.283;
procedure Str.12 (#Attr.2): procedure Str.12 (#Attr.2):
let Str.388 : List U8 = lowlevel StrToUtf8 #Attr.2; let Str.258 : List U8 = lowlevel StrToUtf8 #Attr.2;
ret Str.388; ret Str.258;
procedure Str.36 (#Attr.2): procedure Str.36 (#Attr.2):
let Str.389 : U64 = lowlevel StrCountUtf8Bytes #Attr.2; let Str.259 : U64 = lowlevel StrCountUtf8Bytes #Attr.2;
ret Str.389; ret Str.259;
procedure Str.43 (#Attr.2): procedure Str.43 (#Attr.2):
let Str.386 : {U64, Str, Int1, U8} = lowlevel StrFromUtf8 #Attr.2; let Str.256 : {U64, Str, Int1, U8} = lowlevel StrFromUtf8 #Attr.2;
ret Str.386; ret Str.256;
procedure Str.9 (Str.76): procedure Str.9 (Str.74):
let Str.77 : {U64, Str, Int1, U8} = CallByName Str.43 Str.76; let Str.75 : {U64, Str, Int1, U8} = CallByName Str.43 Str.74;
let Str.383 : Int1 = StructAtIndex 2 Str.77; let Str.253 : Int1 = StructAtIndex 2 Str.75;
if Str.383 then if Str.253 then
let Str.385 : Str = StructAtIndex 1 Str.77; let Str.255 : Str = StructAtIndex 1 Str.75;
let Str.384 : [C {U64, U8}, C Str] = TagId(1) Str.385; let Str.254 : [C {U64, U8}, C Str] = TagId(1) Str.255;
ret Str.384; ret Str.254;
else else
let Str.381 : U64 = StructAtIndex 0 Str.77; let Str.251 : U64 = StructAtIndex 0 Str.75;
let Str.382 : U8 = StructAtIndex 3 Str.77; let Str.252 : U8 = StructAtIndex 3 Str.75;
let #Derived_gen.28 : Str = StructAtIndex 1 Str.77; let #Derived_gen.28 : Str = StructAtIndex 1 Str.75;
dec #Derived_gen.28; dec #Derived_gen.28;
let Str.380 : {U64, U8} = Struct {Str.381, Str.382}; let Str.250 : {U64, U8} = Struct {Str.251, Str.252};
let Str.378 : [C {U64, U8}, C Str] = TagId(0) Str.380; let Str.248 : [C {U64, U8}, C Str] = TagId(0) Str.250;
ret Str.378; ret Str.248;
procedure Test.20 (Test.56): procedure Test.20 (Test.56):
let Test.301 : Str = CallByName Encode.23 Test.56; let Test.301 : Str = CallByName Encode.23 Test.56;

View file

@ -6,7 +6,7 @@ procedure Num.21 (#Attr.2, #Attr.3):
let Num.283 : I64 = lowlevel NumMul #Attr.2 #Attr.3; let Num.283 : I64 = lowlevel NumMul #Attr.2 #Attr.3;
ret Num.283; ret Num.283;
procedure Test.1 (#Derived_gen.0, #Derived_gen.1): procedure Test.1 (Bool.21, Bool.22):
joinpoint Test.7 Test.2 Test.3: joinpoint Test.7 Test.2 Test.3:
let Test.13 : I64 = 0i64; let Test.13 : I64 = 0i64;
let Test.14 : Int1 = lowlevel Eq Test.13 Test.2; let Test.14 : Int1 = lowlevel Eq Test.13 Test.2;
@ -18,7 +18,7 @@ procedure Test.1 (#Derived_gen.0, #Derived_gen.1):
let Test.11 : I64 = CallByName Num.21 Test.2 Test.3; let Test.11 : I64 = CallByName Num.21 Test.2 Test.3;
jump Test.7 Test.10 Test.11; jump Test.7 Test.10 Test.11;
in in
jump Test.7 #Derived_gen.0 #Derived_gen.1; jump Test.7 Bool.21 Bool.22;
procedure Test.0 (): procedure Test.0 ():
let Test.5 : I64 = 10i64; let Test.5 : I64 = 10i64;

View file

@ -1,6 +1,6 @@
procedure Bool.1 (): procedure Bool.1 ():
let Bool.23 : Int1 = false; let Bool.21 : Int1 = false;
ret Bool.23; ret Bool.21;
procedure Test.1 (Test.2): procedure Test.1 (Test.2):
let Test.5 : I64 = 2i64; let Test.5 : I64 = 2i64;

View file

@ -1,6 +1,6 @@
procedure Bool.11 (#Attr.2, #Attr.3): procedure Bool.9 (#Attr.2, #Attr.3):
let Bool.23 : Int1 = lowlevel Eq #Attr.2 #Attr.3; let Bool.21 : Int1 = lowlevel Eq #Attr.2 #Attr.3;
ret Bool.23; ret Bool.21;
procedure Test.1 (Test.3): procedure Test.1 (Test.3):
let Test.6 : I64 = 10i64; let Test.6 : I64 = 10i64;
@ -13,7 +13,7 @@ procedure Test.1 (Test.3):
ret Test.8; ret Test.8;
in in
let Test.12 : I64 = 5i64; let Test.12 : I64 = 5i64;
let Test.11 : Int1 = CallByName Bool.11 Test.6 Test.12; let Test.11 : Int1 = CallByName Bool.9 Test.6 Test.12;
jump Test.10 Test.11; jump Test.10 Test.11;
procedure Test.0 (): procedure Test.0 ():

View file

@ -1,10 +1,10 @@
procedure Bool.1 (): procedure Bool.1 ():
let Bool.23 : Int1 = false; let Bool.21 : Int1 = false;
ret Bool.23; ret Bool.21;
procedure Bool.2 (): procedure Bool.2 ():
let Bool.24 : Int1 = true; let Bool.22 : Int1 = true;
ret Bool.24; ret Bool.22;
procedure Test.0 (): procedure Test.0 ():
let Test.4 : Int1 = CallByName Bool.2; let Test.4 : Int1 = CallByName Bool.2;

View file

@ -1,6 +1,6 @@
procedure Bool.1 (): procedure Bool.1 ():
let Bool.23 : Int1 = false; let Bool.21 : Int1 = false;
ret Bool.23; ret Bool.21;
procedure Num.19 (#Attr.2, #Attr.3): procedure Num.19 (#Attr.2, #Attr.3):
let Num.283 : I64 = lowlevel NumAdd #Attr.2 #Attr.3; let Num.283 : I64 = lowlevel NumAdd #Attr.2 #Attr.3;
@ -9,7 +9,7 @@ procedure Num.19 (#Attr.2, #Attr.3):
procedure Test.3 (Test.4): procedure Test.3 (Test.4):
ret Test.4; ret Test.4;
procedure Test.0 (#Derived_gen.0): procedure Test.0 (Bool.22):
joinpoint Test.5 Test.1: joinpoint Test.5 Test.1:
joinpoint Test.10 Test.2: joinpoint Test.10 Test.2:
let Test.8 : I64 = 1i64; let Test.8 : I64 = 1i64;
@ -31,4 +31,4 @@ procedure Test.0 (#Derived_gen.0):
let Test.9 : Int1 = true; let Test.9 : Int1 = true;
jump Test.10 Test.9; jump Test.10 Test.9;
in in
jump Test.5 #Derived_gen.0; jump Test.5 Bool.22;

View file

@ -34,7 +34,7 @@ procedure Test.8 (Test.9):
let Test.23 : I64 = CallByName Num.19 Test.9 Test.24; let Test.23 : I64 = CallByName Num.19 Test.9 Test.24;
ret Test.23; ret Test.23;
procedure Test.0 (#Derived_gen.0): procedure Test.0 (Bool.21):
joinpoint Test.11 Test.1: joinpoint Test.11 Test.1:
let Test.25 : I64 = 1i64; let Test.25 : I64 = 1i64;
let Test.13 : I64 = CallByName Num.19 Test.1 Test.25; let Test.13 : I64 = CallByName Num.19 Test.1 Test.25;
@ -57,4 +57,4 @@ procedure Test.0 (#Derived_gen.0):
ret Test.12; ret Test.12;
in in
jump Test.11 #Derived_gen.0; jump Test.11 Bool.21;

View file

@ -17,7 +17,7 @@ procedure Test.4 (Test.5, #Attr.12):
let Test.16 : I64 = CallByName Num.19 Test.5 Test.17; let Test.16 : I64 = CallByName Num.19 Test.5 Test.17;
ret Test.16; ret Test.16;
procedure Test.0 (#Derived_gen.0): procedure Test.0 (Bool.21):
joinpoint Test.7 Test.1: joinpoint Test.7 Test.1:
let Test.21 : I64 = 1i64; let Test.21 : I64 = 1i64;
let Test.9 : I64 = CallByName Num.19 Test.1 Test.21; let Test.9 : I64 = CallByName Num.19 Test.1 Test.21;
@ -33,4 +33,4 @@ procedure Test.0 (#Derived_gen.0):
ret Test.8; ret Test.8;
in in
jump Test.7 #Derived_gen.0; jump Test.7 Bool.21;

File diff suppressed because it is too large Load diff

Some files were not shown because too many files have changed in this diff Show more