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_MISMATCHES = "0"
ROC_PRINT_FIXPOINT_FIXING = "0"
ROC_VERIFY_RIGID_LET_GENERALIZED = "0"
ROC_VERIFY_OCCURS_ONE_RECURSION = "0"
ROC_CHECK_MONO_IR = "0"
ROC_PRINT_IR_AFTER_SPECIALIZATION = "0"

27
Cargo.lock generated
View file

@ -2393,6 +2393,7 @@ dependencies = [
"bumpalo",
"indoc",
"pretty_assertions",
"roc_can_solo",
"roc_collections",
"roc_error_macros",
"roc_exhaustive",
@ -2408,6 +2409,25 @@ dependencies = [
"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]]
name = "roc_checkmate"
version = "0.0.1"
@ -2805,6 +2825,7 @@ dependencies = [
"pretty_assertions",
"roc_builtins",
"roc_can",
"roc_can_solo",
"roc_collections",
"roc_constrain",
"roc_derive",
@ -2828,6 +2849,8 @@ dependencies = [
name = "roc_load_internal"
version = "0.0.1"
dependencies = [
"base64-url",
"blake3",
"bumpalo",
"crossbeam",
"indoc",
@ -2836,6 +2859,7 @@ dependencies = [
"pretty_assertions",
"roc_builtins",
"roc_can",
"roc_can_solo",
"roc_checkmate",
"roc_collections",
"roc_constrain",
@ -3281,6 +3305,7 @@ dependencies = [
name = "roc_types"
version = "0.0.1"
dependencies = [
"bitflags 1.3.2",
"bumpalo",
"roc_collections",
"roc_debug_flags",
@ -3871,6 +3896,7 @@ dependencies = [
"pretty_assertions",
"roc_builtins",
"roc_can",
"roc_can_solo",
"roc_collections",
"roc_constrain",
"roc_derive",
@ -4015,6 +4041,7 @@ dependencies = [
"indoc",
"pretty_assertions",
"roc_can",
"roc_can_solo",
"roc_collections",
"roc_error_macros",
"roc_fmt",

View file

@ -1,6 +1,7 @@
[workspace]
members = [
"crates/build/specialize_types",
"crates/build/*",
"crates/check/*",
"crates/compiler/*",
"crates/vendor/*",
"crates/fs",
@ -174,6 +175,7 @@ roc_bitcode_bc = { path = "crates/compiler/builtins/bitcode/bc" }
roc_build = { path = "crates/compiler/build" }
roc_builtins = { path = "crates/compiler/builtins" }
roc_can = { path = "crates/compiler/can" }
roc_can_solo = { path = "crates/check/can_solo" }
roc_checkmate = { path = "crates/compiler/checkmate" }
roc_checkmate_schema = { path = "crates/compiler/checkmate_schema" }
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 =
Set.difference(neighbors, model_popped.evaluated)
model_with_neighbors : Model position
model_with_neighbors : Model _
model_with_neighbors =
model_popped
|> &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)
model_with_costs =

View file

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

View file

@ -50,7 +50,7 @@ safe = \queen, diagonal, xs ->
when xs is
Nil -> Bool.true
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)
else
Bool.false

View file

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

View file

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

View file

@ -212,6 +212,7 @@ comptime {
exportStrFn(str.withCapacityC, "with_capacity");
exportStrFn(str.strAllocationPtr, "allocation_ptr");
exportStrFn(str.strReleaseExcessCapacity, "release_excess_capacity");
exportStrFn(str.strWithAsciiLowercased, "with_ascii_lowercased");
for (INTEGERS) |T| {
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 UpdateMode = utils.UpdateMode;
const std = @import("std");
const ascii = std.ascii;
const mem = std.mem;
const unicode = std.unicode;
const testing = std.testing;
@ -370,11 +371,17 @@ pub const RocStr = extern struct {
}
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;
}
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];
}
@ -611,16 +618,6 @@ fn initFromSmallStr(slice_bytes: [*]u8, len: usize, _: usize) RocStr {
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 {
if (delimiter.len() == 0) {
string.incref(1);
@ -2138,6 +2135,66 @@ fn countTrailingWhitespaceBytes(string: RocStr) usize {
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 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.
##
@ -44,55 +44,6 @@ true = @Bool(True)
false : Bool
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
## equivalent to the logic [NOT](https://en.wikipedia.org/wiki/Negation)
## 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)
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)
buckets1 = fill_buckets_from_data(buckets0, data, requested_shifts)
@Dict(
@ -915,7 +915,7 @@ calc_shifts_for_size_helper = |shifts, size, max_load_factor|
|> Num.to_f32
|> Num.mul(max_load_factor)
|> 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)
else
shifts
@ -1087,7 +1087,7 @@ expect
|> insert("bar", {})
|> insert("baz", {})
contains(dict, "baz") && !(contains(dict, "other"))
contains(dict, "baz") and !(contains(dict, "other"))
expect
dict =
@ -1145,17 +1145,17 @@ expect
|> insert("l", 11)
(get(dict, "a") == Ok(0))
&& (get(dict, "b") == Ok(1))
&& (get(dict, "c") == Ok(2))
&& (get(dict, "d") == Ok(3))
&& (get(dict, "e") == Ok(4))
&& (get(dict, "f") == Ok(5))
&& (get(dict, "g") == Ok(6))
&& (get(dict, "h") == Ok(7))
&& (get(dict, "i") == Ok(8))
&& (get(dict, "j") == Ok(9))
&& (get(dict, "k") == Ok(10))
&& (get(dict, "l") == Ok(11))
and (get(dict, "b") == Ok(1))
and (get(dict, "c") == Ok(2))
and (get(dict, "d") == Ok(3))
and (get(dict, "e") == Ok(4))
and (get(dict, "f") == Ok(5))
and (get(dict, "g") == Ok(6))
and (get(dict, "h") == Ok(7))
and (get(dict, "i") == Ok(8))
and (get(dict, "j") == Ok(9))
and (get(dict, "k") == Ok(10))
and (get(dict, "l") == Ok(11))
# Force rehash.
expect
@ -1197,18 +1197,18 @@ expect
|> insert("m", 12)
(get(dict, "a") == Ok(0))
&& (get(dict, "b") == Ok(1))
&& (get(dict, "c") == Ok(2))
&& (get(dict, "d") == Ok(3))
&& (get(dict, "e") == Ok(4))
&& (get(dict, "f") == Ok(5))
&& (get(dict, "g") == Ok(6))
&& (get(dict, "h") == Ok(7))
&& (get(dict, "i") == Ok(8))
&& (get(dict, "j") == Ok(9))
&& (get(dict, "k") == Ok(10))
&& (get(dict, "l") == Ok(11))
&& (get(dict, "m") == Ok(12))
and (get(dict, "b") == Ok(1))
and (get(dict, "c") == Ok(2))
and (get(dict, "d") == Ok(3))
and (get(dict, "e") == Ok(4))
and (get(dict, "f") == Ok(5))
and (get(dict, "g") == Ok(6))
and (get(dict, "h") == Ok(7))
and (get(dict, "i") == Ok(8))
and (get(dict, "j") == Ok(9))
and (get(dict, "k") == Ok(10))
and (get(dict, "l") == Ok(11))
and (get(dict, "m") == Ok(12))
expect
empty({})
@ -1266,7 +1266,7 @@ expect
bad_keys,
Bool.true,
|acc, k|
acc && Dict.contains(dict, k),
acc and Dict.contains(dict, k),
)
all_inserted_correctly

View file

@ -1361,7 +1361,7 @@ split_last = |list, delimiter|
## result is an empty list.
chunks_of : List a, U64 -> List (List a)
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
chunk_capacity = Num.div_ceil(List.len(list), chunk_size)

View file

@ -532,7 +532,7 @@ pi = 3.14159265358979323846264338327950288419716939937510
## Circle constant (τ)
tau : Frac *
tau = 2 * pi
tau = 6.2831853071795864769252867665590057683943387987502
# ------- Functions
## 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_approx_eq : Frac a, Frac a, { rtol ?? Frac a, atol ?? Frac a } -> Bool
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))))
eq || meets_tolerance
eq or meets_tolerance
## Returns `Bool.true` if the number is `0`, and `Bool.false` otherwise.
is_zero : Num a -> Bool

View file

@ -373,6 +373,7 @@ module [
contains,
drop_prefix,
drop_suffix,
with_ascii_lowercased,
]
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
## 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)
else
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_ALLOCATION_PTR: &str = "roc_builtins.str.allocation_ptr";
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_MAP2: &str = "roc_builtins.list.map2";

View file

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

View file

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

View file

@ -915,7 +915,7 @@ pub struct DefTypes {
pub loc_symbols: Slice<(Symbol, Region)>,
}
#[derive(Debug, Clone, Copy)]
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct Generalizable(pub bool);
#[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;
/// The canonicalization environment for a particular module.
#[derive(Debug)]
pub struct Env<'a> {
/// The module's path. Opaques and unqualified references to identifiers
/// are assumed to be relative to this path.
@ -51,6 +52,36 @@ pub struct 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)]
pub fn new(
arena: &'a Bump,

View file

@ -1,9 +1,6 @@
use std::path::Path;
use crate::abilities::{AbilitiesStore, ImplKey, PendingAbilitiesStore, ResolvedImpl};
use crate::annotation::{canonicalize_annotation, AnnotationFor};
use crate::def::{canonicalize_defs, report_unused_imports, Def, DefKind};
use crate::desugar::desugar_record_destructures;
use crate::env::Env;
use crate::expr::{ClosureData, Declarations, ExpectLookup, Expr, Output, PendingDerives};
use crate::pattern::{
@ -16,8 +13,8 @@ use roc_collections::{MutMap, SendMap, VecMap, VecSet};
use roc_error_macros::internal_error;
use roc_module::ident::Ident;
use roc_module::ident::Lowercase;
use roc_module::symbol::{IdentId, IdentIds, IdentIdsByModule, ModuleId, PackageModuleIds, Symbol};
use roc_parse::ast::{Defs, TypeAnnotation};
use roc_module::symbol::{IdentId, ModuleId, Symbol};
use roc_parse::ast::{Collection, Defs, Pattern as ParsePattern, TypeAnnotation};
use roc_parse::header::HeaderType;
use roc_parse::pattern::PatternType;
use roc_problem::can::{Problem, RuntimeError};
@ -209,55 +206,19 @@ fn has_no_implementation(expr: &Expr) -> bool {
#[allow(clippy::too_many_arguments)]
pub fn canonicalize_module_defs<'a>(
arena: &'a Bump,
loc_defs: &'a mut Defs<'a>,
header_type: &'a roc_parse::header::HeaderType,
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)>,
exposed_symbols: VecSet<Symbol>,
symbols_from_requires: &[(Loc<Symbol>, Loc<TypeAnnotation<'a>>)],
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 {
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
// 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
// rules multiple times unnecessarily.
crate::desugar::desugar_defs_node_values(&mut env, &mut scope, loc_defs);
let mut rigid_variables = RigidVariables::default();
// Initial scope values are treated like defs that appear before any others.
@ -319,51 +278,42 @@ pub fn canonicalize_module_defs<'a>(
let mut output = Output::default();
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);
let module_params = module_params.map(|(params_region, desugared_patterns)| {
let (destructs, _) = canonicalize_record_destructs(
&mut env,
var_store,
&mut scope,
&mut output,
PatternType::ModuleParams,
&desugared_patterns,
params_region,
PermitShadows(false),
);
let (destructs, _) = canonicalize_record_destructs(
&mut env,
var_store,
&mut scope,
&mut output,
PatternType::ModuleParams,
&desugared_patterns,
pattern.region,
PermitShadows(false),
);
let whole_symbol = scope.gen_unique_symbol();
env.top_level_symbols.insert(whole_symbol);
let whole_symbol = scope.gen_unique_symbol();
env.top_level_symbols.insert(whole_symbol);
let whole_var = var_store.fresh();
let whole_var = var_store.fresh();
env.home_params_record = Some((whole_symbol, whole_var));
env.home_params_record = Some((whole_symbol, whole_var));
ModuleParams {
region: pattern.region,
whole_var,
whole_symbol,
record_var: var_store.fresh(),
record_ext_var: var_store.fresh(),
destructs,
arity_by_name: Default::default(),
}
},
);
ModuleParams {
region: params_region,
whole_var,
whole_symbol,
record_var: var_store.fresh(),
record_ext_var: var_store.fresh(),
destructs,
arity_by_name: Default::default(),
}
});
let (defs, output, symbols_introduced, imports_introduced) = canonicalize_defs(
&mut env,
output,
var_store,
&mut scope,
loc_defs,
arena.alloc(loc_defs),
PatternType::TopLevelDef,
);

View file

@ -1,10 +1,11 @@
extern crate bumpalo;
use self::bumpalo::Bump;
use roc_can::desugar;
use roc_can::env::Env;
use roc_can::expr::{canonicalize_expr, Expr};
use roc_can::scope::Scope;
use roc_can_solo::env::SoloEnv;
use roc_can_solo::scope::SoloScope;
use roc_collections::all::MutMap;
use roc_module::symbol::{IdentIds, Interns, ModuleId, ModuleIds, PackageModuleIds, Symbol};
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
// operators, and then again on *their* nested operators, ultimately applying the
// 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(
Symbol::NUM_INT,

View file

@ -972,7 +972,59 @@ mod test_can {
}
#[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!(
r#"
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)
// 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);
assert_eq!(cond_args.len(), 1);
@ -1016,7 +1068,7 @@ mod test_can {
}
#[test]
fn try_desugar_single_question_binop() {
fn desugar_single_question_binop() {
let src = indoc!(
r#"
Str.to_u64("123") ? FailedToConvert
@ -1033,7 +1085,7 @@ mod test_can {
// 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))
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);
assert_eq!(cond_args.len(), 1);
@ -1075,11 +1127,13 @@ mod test_can {
}
#[test]
fn try_desugar_works_elsewhere() {
fn desugar_and_operator() {
let src = indoc!(
r#"
when Foo 123 is
Foo try -> try
left = Bool.true
right = Bool.false
left and right
"#
);
let arena = Bump::new();
@ -1087,43 +1141,49 @@ mod test_can {
assert_eq!(out.problems, Vec::new());
// Assert that we don't treat `try` as a keyword here
// by desugaring to:
// Assert that we desugar to:
//
// when Foo 123 is
// Foo try -> try
// if left then right else Bool.false
let (cond_expr, branches) = assert_when(&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),
}
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_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].0.value, "left", &out.interns);
assert_var_usage(&branches[0].1.value, "right", &out.interns);
assert_var_usage(&final_else.value, "false", &out.interns);
}
assert_var_usage(&branches[0].value.value, "try", &out.interns);
assert!(&branches[0].guard.is_none());
#[test]
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) {
@ -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 {
Expr::When {
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 {
match expr {
Expr::Try { result_expr, .. } => &result_expr.value,

View file

@ -95,22 +95,6 @@ flags! {
/// Prints all type variables entered for 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
/// fixed-up with one new recursion variable.
///

View file

@ -1206,7 +1206,6 @@ impl<'a> Nodify<'a> for TypeAnnotation<'a> {
before: first_node.before,
node: Node::CommaSequence {
allow_blank_lines: false,
allow_newlines: true,
indent_rest: false,
first: arena.alloc(first_node.node),
rest: rest_nodes.into_bump_slice(),
@ -1313,11 +1312,12 @@ impl<'a> Nodify<'a> for TypeAnnotation<'a> {
.to_node(arena, flags)
.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 {
comma_before: false,
before: annot.after,
before,
newline: false,
space: true,
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() {
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;
items.push(Item {
before,
@ -1346,8 +1347,7 @@ impl<'a> Nodify<'a> for TypeAnnotation<'a> {
first: arena.alloc(annot.node),
rest: arena.alloc_slice_copy(&items),
allow_blank_lines: false,
allow_newlines: false,
indent_rest: false,
indent_rest: true,
},
after: last_after,
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 {
fn to_node<'b>(&'a self, arena: &'b Bump, flags: MigrationFlags) -> NodeInfo<'b>
where
@ -1451,7 +1469,6 @@ impl<'a> Nodify<'a> for ImplementsClause<'a> {
first: arena.alloc(var.node),
rest: arena.alloc_slice_copy(&items),
allow_blank_lines: false,
allow_newlines: true,
indent_rest: false,
},
after: last_after,

View file

@ -1,20 +1,20 @@
use crate::annotation::{
ann_lift_spaces, ann_lift_spaces_after, is_collection_multiline, ty_is_outdentable,
Formattable, Newlines, Parens,
ann_lift_spaces_after, is_collection_multiline, Formattable, Newlines, Parens,
};
use crate::collection::{fmt_collection, Braces};
use crate::expr::{
expr_lift_and_lower, expr_lift_spaces, expr_lift_spaces_after, expr_lift_spaces_before,
fmt_str_literal, is_str_multiline, merge_spaces_conservative, sub_expr_requests_parens,
expr_lift_spaces, expr_lift_spaces_after, expr_lift_spaces_before, fmt_str_literal,
is_str_multiline, merge_spaces_conservative, sub_expr_requests_parens,
};
use crate::node::Nodify;
use crate::pattern::pattern_lift_spaces_before;
use crate::pattern::{pattern_lift_spaces, pattern_lift_spaces_before};
use crate::spaces::{
fmt_comments_only, fmt_default_newline, fmt_default_spaces, fmt_spaces, NewlineAt, INDENT,
};
use crate::Buf;
use bumpalo::Bump;
use roc_error_macros::internal_error;
use roc_parse::ast::Spaceable;
use roc_parse::ast::{
AbilityMember, Defs, Expr, ExtractSpaces, ImportAlias, ImportAsKeyword, ImportExposingKeyword,
ImportedModuleName, IngestedFileAnnotation, IngestedFileImport, ModuleImport,
@ -182,16 +182,29 @@ pub fn valdef_lift_spaces<'a, 'b: 'a>(
}
}
ValueDef::Body(pat, expr) => {
let pat_lifted = pattern_lift_spaces_before(arena, &pat.value);
let expr_lifted = expr_lift_spaces_after(Parens::NotNeeded, arena, &expr.value);
let pat_lifted = pattern_lift_spaces(arena, &pat.value);
Spaces {
before: pat_lifted.before,
item: ValueDef::Body(
arena.alloc(Loc::at(pat.region, pat_lifted.item)),
arena.alloc(Loc::at(expr.region, expr_lifted.item)),
),
after: expr_lifted.after,
// 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 {
before: pat_lifted.before,
item: ValueDef::Body(
arena.alloc(Loc::at(
pat.region,
pat_lifted.item.maybe_after(arena, pat_lifted.after),
)),
expr,
),
after: lifted.after,
}
}
}
ValueDef::AnnotatedBody {
@ -312,11 +325,26 @@ pub fn valdef_lift_spaces_before<'a, 'b: 'a>(
}
}
ValueDef::Body(pat, expr) => {
let pat_lifted = pattern_lift_spaces_before(arena, &pat.value);
let pat_lifted = pattern_lift_spaces(arena, &pat.value);
SpacesBefore {
before: pat_lifted.before,
item: ValueDef::Body(arena.alloc(Loc::at(pat.region, pat_lifted.item)), expr),
// 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 {
before: pat_lifted.before,
item: ValueDef::Body(
arena.alloc(Loc::at(
pat.region,
pat_lifted.item.maybe_after(arena, pat_lifted.after),
)),
expr,
),
}
}
}
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> {
fn is_multiline(&self) -> bool {
use roc_parse::ast::TypeDef::*;
@ -412,22 +454,15 @@ impl<'a> Formattable for TypeDef<'a> {
match self {
Alias { header, ann } => {
header.format(buf, indent);
buf.indent(indent);
buf.push_str(" :");
buf.spaces(1);
let ann = ann_lift_spaces(buf.text.bump(), &ann.value);
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);
fmt_general_def(
header,
Parens::NotNeeded,
buf,
indent,
":",
&ann.value,
newlines,
);
}
Opaque {
header,
@ -797,7 +832,7 @@ impl<'a> Formattable for ValueDef<'a> {
);
}
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),
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);
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),
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>(
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);
}
pub fn fmt_body<'a>(buf: &mut Buf, pattern: &'a Pattern<'a>, body: &'a Expr<'a>, indent: u16) {
pattern.format_with_options(buf, Parens::InApply, Newlines::No, indent);
if pattern.is_multiline() {
@ -996,7 +1004,12 @@ pub fn fmt_body<'a>(
let indent = buf.cur_line_indent();
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() {
match body {
@ -1009,10 +1022,7 @@ pub fn fmt_body<'a>(
_ => false,
};
if is_unit_assignment {
fmt_comments_only(buf, spaces.iter(), NewlineAt::Bottom, indent);
sub_def.format_with_options(buf, Parens::NotNeeded, Newlines::Yes, indent);
} else if should_outdent {
if should_outdent {
buf.spaces(1);
sub_def.format_with_options(buf, Parens::NotNeeded, Newlines::Yes, indent);
} else {
@ -1057,7 +1067,7 @@ pub fn fmt_body<'a>(
buf.ensure_ends_with_newline();
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:
//
// something = foo
@ -1092,6 +1102,8 @@ pub fn fmt_body<'a>(
buf.spaces(1);
body.format_with_options(buf, Parens::NotNeeded, Newlines::Yes, indent);
}
fmt_spaces(buf, after.iter(), indent);
}
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::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::TrySuffix(inner) => starts_with_block_string_literal(inner),
_ => false,

View file

@ -1,6 +1,6 @@
use crate::annotation::{except_last, is_collection_multiline, Formattable, Newlines, Parens};
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::pattern::{
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 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
&& 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>(
arena: &'a Bump,
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::LessThanOrEq => buf.push_str("<="),
called_via::BinOp::GreaterThanOrEq => buf.push_str(">="),
called_via::BinOp::And => buf.push_str("&&"),
called_via::BinOp::Or => buf.push_str("||"),
called_via::BinOp::Or => buf.push_str("or"),
called_via::BinOp::And => buf.push_str("and"),
called_via::BinOp::Pizza => buf.push_str("|>"),
called_via::BinOp::DoubleQuestion => 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>(
parens: Parens,
arena: &'a Bump,
@ -1496,7 +1480,6 @@ fn fmt_binops<'a>(
buf: &mut Buf,
lefts: &'a [(Loc<Expr<'a>>, Loc<BinOp>)],
loc_right_side: &'a Loc<Expr<'a>>,
indent: u16,
) {
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, _) => {
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::Defs(_, final_expr) => guard_needs_parens(&final_expr.value),
_ => false,

View file

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

View file

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

View file

@ -1268,20 +1268,6 @@ trait Backend<'a> {
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 => {
if let LayoutRepr::Builtin(Builtin::Int(int_width)) =
self.interner().get_repr(*ret_layout)
@ -1733,6 +1719,13 @@ trait Backend<'a> {
arg_layouts,
ret_layout,
),
LowLevel::StrWithAsciiLowercased => self.build_fn_call(
sym,
bitcode::STR_WITH_ASCII_LOWERCASED.to_string(),
args,
arg_layouts,
ret_layout,
),
LowLevel::StrToNum => {
let number_layout = match self.interner().get_repr(*ret_layout) {
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,
)
}
ListLenU64 => {
// List.len : List * -> U64
arguments!(list);
@ -614,6 +615,17 @@ pub(crate) fn run_low_level<'a, 'ctx>(
list_element_layout!(layout_interner, result_layout),
)
}
StrWithAsciiLowercased => {
arguments!(string);
call_str_bitcode_fn(
env,
&[string],
&[],
BitcodeReturns::Str,
bitcode::STR_WITH_ASCII_LOWERCASED,
)
}
ListConcat => {
debug_assert_eq!(args.len(), 2);
@ -1263,30 +1275,6 @@ pub(crate) fn run_low_level<'a, 'ctx>(
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 => {
// The (!) operator
arguments!(arg);

View file

@ -259,6 +259,9 @@ impl<'a> LowLevelCall<'a> {
self.load_args_and_call_zig(backend, bitcode::STR_SUBSTRING_UNSAFE)
}
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
ListLenU64 => {
@ -2164,14 +2167,6 @@ impl<'a> LowLevelCall<'a> {
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),
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 => {
self.load_args(backend);
backend.code_builder.i32_eqz();

View file

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

View file

@ -3,11 +3,12 @@ extern crate bumpalo;
use self::bumpalo::Bump;
use roc_can::abilities::AbilitiesStore;
use roc_can::constraint::{Constraint, Constraints};
use roc_can::desugar;
use roc_can::env::Env;
use roc_can::expected::Expected;
use roc_can::expr::{canonicalize_expr, Expr, Output, PendingDerives};
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_constrain::expr::constrain_expr;
use roc_derive::SharedDerivedModule;
@ -162,24 +163,6 @@ pub fn can_expr_with<'a>(
// ensure the Test module is accessible in our tests
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
// 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
// operators, and then again on *their* nested operators, ultimately applying the
// 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(
home,

View file

@ -1522,18 +1522,18 @@ mod test_reporting {
from_annotation_if,
indoc!(
r"
x : Num.Int *
x : Num.Int _
x = if Bool.true then 3.14 else 4
x
"
),
@r"
@r###"
TYPE MISMATCH in /code/proj/Main.roc
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
^^^^
@ -1547,14 +1547,14 @@ mod test_reporting {
Tip: You can convert between integers and fractions using functions
like `Num.to_frac` and `Num.round`.
"
"###
);
test_report!(
from_annotation_when,
indoc!(
r"
x : Num.Int *
x : Num.Int _
x =
when True is
_ -> 3.14
@ -1562,12 +1562,12 @@ mod test_reporting {
x
"
),
@r"
@r###"
TYPE MISMATCH in /code/proj/Main.roc
Something is off with the body of the `x` definition:
4 x : Num.Int *
4 x : Num.Int _
5 x =
6> when True is
7> _ -> 3.14
@ -1582,7 +1582,7 @@ mod test_reporting {
Tip: You can convert between integers and fractions using functions
like `Num.to_frac` and `Num.round`.
"
"###
);
test_report!(
@ -1910,7 +1910,7 @@ mod test_reporting {
from_annotation_complex_pattern,
indoc!(
r"
{ x } : { x : Num.Int * }
{ x } : { x : Num.Int _ }
{ x } = { x: 4.0 }
x
@ -1921,7 +1921,7 @@ mod test_reporting {
Something is off with the body of this definition:
4 { x } : { x : Num.Int * }
4 { x } : { x : Num.Int _ }
5 { x } = { x: 4.0 }
^^^^^^^^^^
@ -2047,18 +2047,18 @@ mod test_reporting {
missing_fields,
indoc!(
r"
x : { a : Num.Int *, b : Num.Frac *, c : Str }
x : { a : Num.Int _, b : Num.Frac _, c : Str }
x = { b: 4.0 }
x
"
),
@r"
@r###"
TYPE MISMATCH in /code/proj/Main.roc
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 }
^^^^^^^^^^
@ -2075,7 +2075,7 @@ mod test_reporting {
}
Tip: Looks like the c and a fields are missing.
"
"###
);
// 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 = ACons 0 (BCons 1 (ACons "foo" BNil ))
y : BList a a
y : BList _ _
y = BNil
{ x, y }
@ -4189,9 +4189,8 @@ mod test_reporting {
RBTree k v : [Node NodeColor k v (RBTree k v) (RBTree k v), Empty]
# Create an empty dictionary.
empty : RBTree k v
empty =
Empty
empty : {} -> RBTree k v
empty = \{} -> Empty
empty
"
@ -6036,7 +6035,7 @@ All branches in an `if` must have the same type!
double_binop,
indoc!(
r"
key >= 97 && <= 122
key >= 97 and <= 122
"
),
@r"
@ -6692,17 +6691,20 @@ All branches in an `if` must have the same type!
)
"
),
@r"
UNFINISHED FUNCTION in tmp/unfinished_closure_pattern_in_parens/Test.roc
@r###"
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
5 )
^
6
7
^
I just saw a pattern, so I was expecting to see a -> next.
"
I was expecting a -> next.
"###
);
test_report!(
@ -11215,10 +11217,10 @@ All branches in an `if` must have the same type!
import Decode exposing [decoder]
main =
my_decoder : Decoder (a -> a) fmt where fmt implements DecoderFormatting
my_decoder = decoder
my_decoder : Decoder (_ -> _) _
my_decoder = decoder
main =
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:
7 my_decoder = decoder
^^^^^^^
6 my_decoder = decoder
^^^^^^^
I can't generate an implementation of the `Decoding` ability for
a -> a
* -> *
Note: `Decoding` cannot be generated for functions.
"
@ -11248,10 +11250,10 @@ All branches in an `if` must have the same type!
A := {}
main =
my_decoder : Decoder {x : A} fmt where fmt implements DecoderFormatting
my_decoder = decoder
my_decoder : Decoder {x : A} _
my_decoder = decoder
main =
my_decoder
"#
),
@ -11260,8 +11262,8 @@ 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:
9 my_decoder = decoder
^^^^^^^
8 my_decoder = decoder
^^^^^^^
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]
main =
my_decoder : Decoder {x : Str, y ? Str} fmt where fmt implements DecoderFormatting
my_decoder = decoder
my_decoder : Decoder {x : Str, y ? Str} _
my_decoder = decoder
my_decoder
main = my_decoder
"#
),
@r"
@ -11523,8 +11524,8 @@ 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:
7 my_decoder = decoder
^^^^^^^
6 my_decoder = decoder
^^^^^^^
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]
main =
my_decoder : Decoder (U32, Str) fmt where fmt implements DecoderFormatting
my_decoder = decoder
my_decoder : Decoder (U32, Str) _
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]
main =
my_decoder : Decoder (U32, {} -> {}) fmt where fmt implements DecoderFormatting
my_decoder = decoder
my_decoder : Decoder (U32, {} -> {}) _
my_decoder = decoder
my_decoder
main = my_decoder
"#
),
@r"
@ -14137,8 +14136,8 @@ 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:
7 my_decoder = decoder
^^^^^^^
6 my_decoder = decoder
^^^^^^^
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 -> {}
"#
);
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]
roc_builtins.workspace = true
roc_can.workspace = true
roc_can_solo.workspace = true
roc_work.workspace = true
roc_checkmate.workspace = true
roc_collections.workspace = true
@ -39,6 +40,8 @@ bumpalo.workspace = true
crossbeam.workspace = true
parking_lot.workspace = true
tempfile.workspace = true
base64-url.workspace = true
blake3.workspace = true
[dev-dependencies]
roc_test_utils_dir.workspace = true

View file

@ -15,11 +15,14 @@ use parking_lot::Mutex;
use roc_builtins::roc::module_source;
use roc_can::abilities::{AbilitiesStore, PendingAbilitiesStore, ResolvedImpl};
use roc_can::constraint::{Constraint as ConstraintSoa, Constraints, TypeOrVar};
use roc_can::env::Env;
use roc_can::expr::{Declarations, ExpectLookup, PendingDerives};
use roc_can::module::{
canonicalize_module_defs, ExposedByModule, ExposedForModule, ExposedModuleTypes, Module,
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::{default_hasher, BumpMap, MutMap, MutSet, VecMap, VecSet};
use roc_constrain::module::constrain_module;
@ -204,9 +207,20 @@ fn start_phase<'a>(
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 => {
// canonicalize the file
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 num_deps = deps_by_name.len();
@ -318,6 +332,7 @@ fn start_phase<'a>(
exposed_module_ids: state.exposed_modules,
exec_mode: state.exec_mode,
imported_module_params,
solo_can_output,
}
}
@ -577,6 +592,7 @@ enum Msg<'a> {
Many(Vec<Msg<'a>>),
Header(ModuleHeader<'a>),
Parsed(ParsedModule<'a>),
SoloCanonicalized(ModuleId, CanSolo<'a>),
CanonicalizedAndConstrained(CanAndCon),
SolvedTypes {
module_id: ModuleId,
@ -651,6 +667,9 @@ enum Msg<'a> {
IncorrectModuleName(FileError<'a, IncorrectModuleName<'a>>),
}
#[derive(Debug)]
struct CanSolo<'a>(SoloCanOutput<'a>);
#[derive(Debug)]
struct CanAndCon {
constrained_module: ConstrainedModule,
@ -890,6 +909,9 @@ enum BuildTask<'a> {
ident_ids_by_module: SharedIdentIdsByModule,
root_type: RootType,
},
SoloCanonicalize {
parsed: ParsedModule<'a>,
},
CanonicalizeAndConstrain {
parsed: ParsedModule<'a>,
qualified_module_ids: PackageModuleIds<'a>,
@ -901,6 +923,7 @@ enum BuildTask<'a> {
skip_constraint_gen: bool,
exec_mode: ExecutionMode,
imported_module_params: VecMap<ModuleId, ModuleParams>,
solo_can_output: SoloCanOutput<'a>,
},
Solve {
module: Module,
@ -2411,6 +2434,23 @@ fn update<'a>(
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 {
constrained_module,
canonicalization_problems,
@ -2462,6 +2502,7 @@ fn update<'a>(
Ok(state)
}
SolvedTypes {
module_id,
ident_ids,
@ -5082,6 +5123,31 @@ fn build_platform_header<'a>(
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)]
fn canonicalize_and_constrain<'a>(
arena: &'a Bump,
@ -5095,21 +5161,21 @@ fn canonicalize_and_constrain<'a>(
exposed_module_ids: &[ModuleId],
exec_mode: ExecutionMode,
imported_module_params: VecMap<ModuleId, ModuleParams>,
solo_can_output: SoloCanOutput<'a>,
) -> CanAndCon {
let canonicalize_start = Instant::now();
let ParsedModule {
module_id,
module_path,
src,
header_type,
exposed_ident_ids,
parsed_defs,
initial_scope,
available_modules,
mut module_timing,
symbols_from_requires,
opt_shorthand,
exposed_ident_ids,
..
} = parsed;
@ -5117,27 +5183,55 @@ fn canonicalize_and_constrain<'a>(
let _before = roc_types::types::get_type_clone_count();
let parsed_defs_for_docs = parsed_defs.clone();
let parsed_defs = arena.alloc(parsed_defs);
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(
arena,
parsed_defs,
&header_type,
module_id,
&*arena.alloc(module_path.to_string_lossy()),
src,
qualified_module_ids,
exposed_ident_ids,
&dep_idents,
aliases,
imported_abilities_state,
initial_scope,
exposed_symbols,
&symbols_from_requires,
&mut var_store,
opt_shorthand,
scope,
env,
solo_can_output.loc_defs,
solo_can_output.module_params,
);
let mut types = Types::new();
@ -6237,6 +6331,12 @@ fn run_task<'a>(
ident_ids_by_module,
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 {
parsed,
qualified_module_ids,
@ -6248,6 +6348,7 @@ fn run_task<'a>(
exposed_module_ids,
exec_mode,
imported_module_params,
solo_can_output,
} => {
let can_and_con = canonicalize_and_constrain(
arena,
@ -6261,6 +6362,7 @@ fn run_task<'a>(
exposed_module_ids,
exec_mode,
imported_module_params,
solo_can_output,
);
Ok(Msg::CanonicalizedAndConstrained(can_and_con))

View file

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

View file

@ -5,6 +5,7 @@ use crate::module::{
};
use roc_can::abilities::PendingAbilitiesStore;
use roc_can::module::ModuleParams;
use roc_can_solo::module::SoloCanOutput;
use roc_collections::{MutMap, MutSet, VecMap};
use roc_module::ident::ModuleName;
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) aliases: MutMap<ModuleId, MutMap<Symbol, (bool, Alias)>>,
pub(crate) pending_abilities: MutMap<ModuleId, PendingAbilitiesStore>,
pub(crate) solo_canonicalized: MutMap<ModuleId, SoloCanOutput<'a>>,
pub(crate) constrained: MutMap<ModuleId, ConstrainedModule>,
pub(crate) module_params: MutMap<ModuleId, ModuleParams>,
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) sources: MutMap<ModuleId, (PathBuf, &'a str)>,
#[allow(dead_code)]
pub(crate) content_hashes: MutMap<ModuleId, String>,
}
impl<'a> ModuleCache<'a> {
@ -65,6 +69,19 @@ impl<'a> ModuleCache<'a> {
pub fn has_errors(&self) -> bool {
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<'_> {
@ -101,6 +118,7 @@ impl Default for ModuleCache<'_> {
parsed: Default::default(),
aliases: Default::default(),
pending_abilities: Default::default(),
solo_canonicalized: Default::default(),
constrained: Default::default(),
module_params: Default::default(),
typechecked: Default::default(),
@ -116,6 +134,7 @@ impl Default for ModuleCache<'_> {
can_problems: Default::default(),
type_problems: Default::default(),
sources: Default::default(),
content_hashes: Default::default(),
}
}
}

View file

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

View file

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

View file

@ -271,11 +271,13 @@ fn load_fixture(
);
}
assert!(loaded_module
.type_problems
.remove(&home)
.unwrap_or_default()
.is_empty());
assert_eq!(
loaded_module
.type_problems
.remove(&home)
.unwrap_or_default(),
Vec::new()
);
let expected_name = loaded_module
.interns
@ -433,11 +435,13 @@ fn module_with_deps() {
loaded_module.can_problems.remove(&home).unwrap_or_default(),
Vec::new()
);
assert!(loaded_module
.type_problems
.remove(&home)
.unwrap_or_default()
.is_empty(),);
assert_eq!(
loaded_module
.type_problems
.remove(&home)
.unwrap_or_default(),
Vec::new()
);
let mut def_count = 0;
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::UnsuffixedEffectfulFunction(_, _)
| TypeError::SuffixedPureFunction(_, _)
| TypeError::InvalidTryTarget(_, _, _) => {}
| TypeError::InvalidTryTarget(_, _, _)
| TypeError::TypeIsNotGeneralized(..) => {}
}
}
}
@ -213,6 +214,7 @@ fn drop_last_argument(err_type: &mut ErrorType) {
| ErrorType::Alias(_, _, _, _)
| ErrorType::Range(_)
| ErrorType::Error
| ErrorType::EffectfulFunc => {}
| ErrorType::EffectfulFunc
| ErrorType::InferenceVar => {}
}
}

View file

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

View file

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

View file

@ -986,6 +986,10 @@ macro_rules! define_builtins {
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);
)+
@ -1355,16 +1359,14 @@ define_builtins! {
0 BOOL_BOOL: "Bool" exposed_type=true // the Bool.Bool type alias
1 BOOL_FALSE: "false"
2 BOOL_TRUE: "true"
3 BOOL_AND: "and"
4 BOOL_OR: "or"
5 BOOL_NOT: "not"
6 BOOL_XOR: "xor"
7 BOOL_NEQ: "is_not_eq"
8 BOOL_EQ: "Eq" exposed_type=true
9 BOOL_IS_EQ: "is_eq"
10 BOOL_IS_EQ_IMPL: "bool_is_eq"
unexposed 11 BOOL_STRUCTURAL_EQ: "structural_eq"
unexposed 12 BOOL_STRUCTURAL_NOT_EQ: "structural_not_eq"
3 BOOL_NOT: "not"
4 BOOL_XOR: "xor"
5 BOOL_NEQ: "is_not_eq"
6 BOOL_EQ: "Eq" exposed_type=true
7 BOOL_IS_EQ: "is_eq"
8 BOOL_IS_EQ_IMPL: "bool_is_eq"
unexposed 9 BOOL_STRUCTURAL_EQ: "structural_eq"
unexposed 10 BOOL_STRUCTURAL_NOT_EQ: "structural_not_eq"
}
5 STR: "Str" => {
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"
49 STR_DROP_PREFIX: "drop_prefix"
50 STR_DROP_SUFFIX: "drop_suffix"
51 STR_FROM_UTF16: "from_utf16"
52 STR_FROM_UTF16_LOSSY: "from_utf16_lossy"
53 STR_FROM_UTF32: "from_utf32"
54 STR_FROM_UTF32_LOSSY: "from_utf32_lossy"
51 STR_WITH_ASCII_LOWERCASED: "with_ascii_lowercased"
52 STR_FROM_UTF16: "from_utf16"
53 STR_FROM_UTF16_LOSSY: "from_utf16_lossy"
54 STR_FROM_UTF32: "from_utf32"
55 STR_FROM_UTF32_LOSSY: "from_utf32_lossy"
}
6 LIST: "List" => {
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,
StrJoinWith => RC::NoRc,
ListSortWith => RC::Rc,
StrWithAsciiLowercased => RC::Rc,
ListAppendUnsafe
| ListReserve
@ -1562,7 +1563,7 @@ fn low_level_no_rc(lowlevel: &LowLevel) -> RC {
Eq | NotEq => RC::NoRc,
And | Or | NumAdd | NumAddWrap | NumAddChecked | NumAddSaturated | NumSub | NumSubWrap
NumAdd | NumAddWrap | NumAddChecked | NumAddSaturated | NumSub | NumSubWrap
| NumSubChecked | NumSubSaturated | NumMul | NumMulWrap | NumMulSaturated
| NumMulChecked | NumGt | NumGte | NumLt | NumLte | NumCompare | NumDivFrac
| NumDivTruncUnchecked | NumDivCeilUnchecked | NumRemUnchecked | NumIsMultipleOf

View file

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

View file

@ -49,7 +49,15 @@ pub fn apply_trmc<'a, 'i>(
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::*;
if let SelfRecursive(id) = proc.is_self_recursive {
let trmc_candidate_symbols = trmc_candidates(env.interner, proc);

View file

@ -738,7 +738,7 @@ fn parse_stmt_operator_chain<'a>(
| Expr::Apply(
Loc {
region: _,
value: Expr::Tag(..)
value: Expr::Tag(_)
},
&[],
_
@ -752,7 +752,7 @@ fn parse_stmt_operator_chain<'a>(
// try an operator
return parse_stmt_after_apply(
arena,
state.clone(),
state,
min_indent,
call_min_indent,
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)]
fn parse_apply_arg<'a>(
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>> {
one_of!(
closure_new_syntax_help(),
closure_new_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(
indented_seq_skip_first(
skip_first(
error_on_pizza(byte_indent(b'|', EClosure::Bar), EClosure::Start),
and(
reset_min_indent(and(
sep_by1_e(
byte_indent(b',', EClosure::Comma),
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
byte(b'|', EClosure::Bar),
// Parse the body
block(
CheckForArrow(false),
true,
EClosure::IndentBody,
EClosure::Body,
),
block(check_for_arrow, true, EClosure::IndentBody, EClosure::Body),
),
),
)),
),
|arena: &'a Bump, (params, body)| {
let params: Vec<'a, Loc<Pattern<'a>>> = params;
@ -2386,12 +2346,12 @@ fn closure_old_syntax_help<'a>(
// closure_help_help(options)
map_with_arena(
// 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)
byte_indent(b'\\', EClosure::Start),
// 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.
and(
reset_min_indent(and(
// Parse the params
// Params are comma-separated
sep_by1_e(
@ -2409,7 +2369,7 @@ fn closure_old_syntax_help<'a>(
// Parse the body
block(check_for_arrow, true, EClosure::IndentBody, EClosure::Body),
),
),
)),
),
|arena: &'a Bump, (params, body)| {
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>> {
move |_, state: State<'a>, min_indent| {
(move |_, state: State<'a>, min_indent| {
let start = state.pos();
let (_, op, state) = operator_help(EExpr::Start, EExpr::BadOperator, state, min_indent)?;
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)))
}
}
}
})
.trace("bin_op")
}
fn operator<'a>() -> impl Parser<'a, OperatorOrDef, EExpr<'a>> {
@ -4069,6 +4030,24 @@ where
G: Fn(&'a str, Position) -> E,
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());
macro_rules! good {
@ -4125,6 +4104,7 @@ where
"<=" => good!(OperatorOrDef::BinOp(BinOp::LessThanOrEq), 2),
"&&" => good!(OperatorOrDef::BinOp(BinOp::And), 2),
"||" => good!(OperatorOrDef::BinOp(BinOp::Or), 2),
"|" => Err((NoProgress, to_error("|", state.pos()))),
"//" => good!(OperatorOrDef::BinOp(BinOp::DoubleSlash), 2),
"->" => {
// 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> {
App {
provides: &'a [Loc<ExposedName<'a>>],

View file

@ -10,6 +10,8 @@ pub const IMPORT: &str = "import";
pub const EXPECT: &str = "expect";
pub const RETURN: &str = "return";
pub const CRASH: &str = "crash";
pub const AND: &str = "and";
pub const OR: &str = "or";
// These keywords are valid in imports
pub const EXPOSING: &str = "exposing";
@ -21,8 +23,8 @@ pub const WHERE: &str = "where";
// These keywords are valid in headers
pub const PLATFORM: &str = "platform";
pub const KEYWORDS: [&str; 11] = [
IF, THEN, ELSE, WHEN, AS, IS, DBG, IMPORT, EXPECT, RETURN, CRASH,
pub const KEYWORDS: [&str; 13] = [
IF, THEN, ELSE, WHEN, AS, IS, DBG, IMPORT, EXPECT, RETURN, CRASH, AND, OR,
];
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::constraint::Constraint::{self, *};
use roc_can::constraint::{
Cycle, FxCallConstraint, FxSuffixConstraint, FxSuffixKind, LetConstraint, OpportunisticResolve,
TryTargetConstraint,
Cycle, FxCallConstraint, FxSuffixConstraint, FxSuffixKind, Generalizable, LetConstraint,
OpportunisticResolve, TryTargetConstraint,
};
use roc_can::expected::{Expected, PExpected};
use roc_can::module::ModuleParams;
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_module::ident::IdentSuffix;
use roc_module::symbol::{ModuleId, Symbol};
@ -32,8 +29,8 @@ use roc_region::all::{Loc, Region};
use roc_solve_problem::TypeError;
use roc_solve_schema::UnificationMode;
use roc_types::subs::{
self, Content, FlatType, GetSubsSlice, Mark, OptVariable, Rank, Subs, TagExt, UlsOfVar,
Variable,
self, Content, ErrorTypeContext, FlatType, GetSubsSlice, Mark, OptVariable, Rank, Subs, TagExt,
UlsOfVar, Variable,
};
use roc_types::types::{Category, Polarity, Reason, RecordField, Type, TypeExtension, Types, Uls};
use roc_unify::unify::{
@ -356,29 +353,13 @@ fn solve(
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");
// check that things went well
dbg_do!(ROC_VERIFY_RIGID_LET_GENERALIZED, {
let rigid_vars = &env.constraints[let_con.rigid_vars];
// NOTE the `subs.redundant` check does not come from elm.
// It's unclear whether this is a bug with our implementation
// (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 named_variables = &env.constraints[let_con.rigid_vars];
check_named_variables_are_generalized(
env,
problems,
named_variables,
let_con.generalizable,
);
let mut new_scope = scope.clone();
for (symbol, loc_var) in local_def_vars.iter() {
@ -1636,6 +1617,30 @@ fn solve(
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(
env: &mut InferenceEnv<'_>,
problems: &mut Vec<TypeError>,

View file

@ -2510,13 +2510,15 @@ mod solve_expr {
infer_eq_without_problem(
indoc!(
r"
empty : [Cons a (ConsList a), Nil] as ConsList a
empty = Nil
ConsList a : [Cons a (ConsList a), Nil]
empty
"
empty : ConsList _
empty = Nil
empty
"
),
"ConsList a",
"ConsList *",
);
}
@ -3742,7 +3744,7 @@ mod solve_expr {
indoc!(
r"
\rec ->
{ x, y } : { x : I64, y ? Bool }*
{ x, y } : { x : I64, y ? Bool }_
{ x, y ? Bool.false } = rec
{ 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]
fn list_take_first() {
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]
fn double_tag_application() {
infer_eq_without_problem(

View file

@ -1,7 +1,7 @@
//! Provides types to describe problems that can occur during solving.
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::{
constraint::FxCallKind,
@ -50,6 +50,7 @@ pub enum TypeError {
UnsuffixedEffectfulFunction(Region, FxSuffixKind),
SuffixedPureFunction(Region, FxSuffixKind),
InvalidTryTarget(Region, ErrorType, TryKind),
TypeIsNotGeneralized(Region, ErrorType, Generalizable),
}
impl TypeError {
@ -80,6 +81,7 @@ impl TypeError {
TypeError::UnsuffixedEffectfulFunction(_, _) => Warning,
TypeError::SuffixedPureFunction(_, _) => Warning,
TypeError::InvalidTryTarget(_, _, _) => RuntimeError,
TypeError::TypeIsNotGeneralized(..) => RuntimeError,
}
}
@ -101,7 +103,8 @@ impl TypeError {
| TypeError::ExpectedEffectful(region, _)
| TypeError::UnsuffixedEffectfulFunction(region, _)
| TypeError::SuffixedPureFunction(region, _)
| TypeError::InvalidTryTarget(region, _, _) => Some(*region),
| TypeError::InvalidTryTarget(region, _, _)
| TypeError::TypeIsNotGeneralized(region, _, _) => Some(*region),
TypeError::UnfulfilledAbility(ab, ..) => ab.region(),
TypeError::Exhaustive(e) => Some(e.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}]
is_eq = \@LyingEq m, @LyingEq n -> m != n
is_eq = \@LyingEq(m), @LyingEq(n) -> m != n
main =
a = @LyingEq 10
b = @LyingEq 5
c = @LyingEq 5
if Bool.is_eq a b && !(Bool.is_eq b c) then
a = @LyingEq(10)
b = @LyingEq(5)
c = @LyingEq(5)
if Bool.is_eq(a, b) and !(Bool.is_eq(b, c)) then
"okay"
else
"fail"

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -1,6 +1,6 @@
procedure Bool.11 (#Attr.2, #Attr.3):
let Bool.23 : Int1 = lowlevel Eq #Attr.2 #Attr.3;
ret Bool.23;
procedure Bool.9 (#Attr.2, #Attr.3):
let Bool.21 : Int1 = lowlevel Eq #Attr.2 #Attr.3;
ret Bool.21;
procedure List.116 (List.563, List.564, List.565):
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;
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:
let List.697 : Int1 = CallByName Num.22 List.569 List.570;
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;
ret List.696;
in
inc #Derived_gen.0;
jump List.695 #Derived_gen.0 #Derived_gen.1 #Derived_gen.2 #Derived_gen.3 #Derived_gen.4;
inc Bool.22;
jump List.695 Bool.22 Bool.23 Bool.24 Bool.25 Bool.26;
procedure Num.22 (#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.3 : U64 = CallByName List.26 Test.2 Test.13 Test.14;
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
ret Test.2;
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;
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:
let Test.51 : U8 = 0i64;
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
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;
joinpoint #Derived_gen.3 #Derived_gen.6:
let #Derived_gen.7 : [<rnu>C [<rnu><null>, C *self *self] *self, <null>] = lowlevel PtrCast #Derived_gen.6;
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;
joinpoint Bool.24 Bool.27:
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 Bool.28 UpdateModeId { id: 1 } TagId(1) Test.33 Test.30;
let Test.45 : I64 = 1i64;
let Test.44 : I64 = CallByName Num.19 Test.31 Test.45;
jump Test.41 Test.32 Test.43 Test.44;
in
let #Derived_gen.4 : Int1 = lowlevel RefCountIsUnique Test.29;
if #Derived_gen.4 then
jump #Derived_gen.3 Test.29;
let Bool.25 : Int1 = lowlevel RefCountIsUnique Test.29;
if Bool.25 then
jump Bool.24 Test.29;
else
inc Test.32;
inc Test.33;
decref Test.29;
let #Derived_gen.8 : [<rnu><null>, C *self *self] = NullPointer;
jump #Derived_gen.3 #Derived_gen.8;
let Bool.29 : [<rnu><null>, C *self *self] = NullPointer;
jump Bool.24 Bool.29;
else
let Test.48 : U8 = 1i64;
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
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 #Derived_gen.5 : Int1 = lowlevel RefCountIsUnique Test.30;
if #Derived_gen.5 then
let Bool.26 : Int1 = lowlevel RefCountIsUnique Test.30;
if Bool.26 then
free Test.30;
jump Test.41 Test.35 Test.36 Test.31;
else
@ -51,7 +51,7 @@ procedure Test.5 (#Derived_gen.0, #Derived_gen.1, #Derived_gen.2):
else
ret Test.31;
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 ():
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:
let List.683 : Int1 = CallByName Num.22 List.178 List.179;
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;
ret List.176;
in
inc #Derived_gen.0;
jump List.681 #Derived_gen.0 #Derived_gen.1 #Derived_gen.2 #Derived_gen.3 #Derived_gen.4;
inc Bool.21;
jump List.681 Bool.21 Bool.22 Bool.23 Bool.24 Bool.25;
procedure List.18 (List.172, List.173, List.174):
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:
let List.683 : Int1 = CallByName Num.22 List.178 List.179;
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;
ret List.176;
in
inc #Derived_gen.0;
jump List.681 #Derived_gen.0 #Derived_gen.1 #Derived_gen.2 #Derived_gen.3 #Derived_gen.4;
inc Bool.21;
jump List.681 Bool.21 Bool.22 Bool.23 Bool.24 Bool.25;
procedure List.18 (List.172, List.173, List.174):
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:
let List.680 : Int1 = CallByName Num.22 List.178 List.179;
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;
ret List.176;
in
inc #Derived_gen.8;
jump List.678 #Derived_gen.8 #Derived_gen.9 #Derived_gen.10 #Derived_gen.11 #Derived_gen.12;
inc Bool.34;
jump List.678 Bool.34 Bool.35 Bool.36 Bool.37 Bool.38;
procedure List.18 (List.172, List.173, List.174):
let List.676 : U64 = 0i64;
@ -38,8 +38,8 @@ procedure Num.51 (#Attr.2, #Attr.3):
procedure Test.10 (Test.69, #Attr.12):
let Test.72 : {} = UnionAtIndex (Id 0) (Index 0) #Attr.12;
let #Derived_gen.18 : Int1 = lowlevel RefCountIsUnique #Attr.12;
if #Derived_gen.18 then
let Bool.39 : Int1 = lowlevel RefCountIsUnique #Attr.12;
if Bool.39 then
free #Attr.12;
ret Test.72;
else
@ -53,7 +53,7 @@ procedure Test.10 (Test.69, #Attr.12):
procedure Test.14 (Test.45, #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;
joinpoint #Derived_gen.19:
joinpoint Bool.40:
let Test.50 : {} = Struct {};
let Test.51 : U8 = GetTagId Test.54;
joinpoint Test.52 Test.15:
@ -80,14 +80,14 @@ procedure Test.14 (Test.45, #Attr.12):
jump Test.52 Test.53;
in
let #Derived_gen.20 : Int1 = lowlevel RefCountIsUnique #Attr.12;
if #Derived_gen.20 then
let Bool.41 : Int1 = lowlevel RefCountIsUnique #Attr.12;
if Bool.41 then
free #Attr.12;
jump #Derived_gen.19;
jump Bool.40;
else
inc Test.54;
decref #Attr.12;
jump #Derived_gen.19;
jump Bool.40;
procedure Test.20 (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 ():
let Bool.23 : Int1 = false;
ret Bool.23;
let Bool.21 : Int1 = false;
ret Bool.21;
procedure Test.2 (Test.6):
let Test.22 : U8 = 1i64;
@ -8,7 +8,7 @@ procedure Test.2 (Test.6):
let Test.24 : Int1 = lowlevel Eq Test.22 Test.23;
if Test.24 then
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.18 : Int1 = CallByName Bool.1;
if Test.18 then
@ -18,29 +18,29 @@ procedure Test.2 (Test.6):
let Test.17 : Str = "foo";
ret Test.17;
in
let #Derived_gen.2 : Int1 = lowlevel RefCountIsUnique Test.6;
if #Derived_gen.2 then
let Bool.24 : Int1 = lowlevel RefCountIsUnique Test.6;
if Bool.24 then
free Test.6;
jump #Derived_gen.1;
jump Bool.23;
else
inc Test.7;
decref Test.6;
jump #Derived_gen.1;
jump Bool.23;
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;
joinpoint #Derived_gen.3:
joinpoint Bool.25:
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!'] }";
Crash Test.21
in
let #Derived_gen.4 : Int1 = lowlevel RefCountIsUnique Test.6;
if #Derived_gen.4 then
let Bool.26 : Int1 = lowlevel RefCountIsUnique Test.6;
if Bool.26 then
free Test.6;
jump #Derived_gen.3;
jump Bool.25;
else
inc Test.9;
decref Test.6;
jump #Derived_gen.3;
jump Bool.25;
procedure Test.0 ():
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 ():
let Bool.23 : Int1 = true;
ret Bool.23;
let Bool.21 : Int1 = true;
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:
let List.680 : Int1 = CallByName Num.22 List.178 List.179;
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;
ret List.176;
in
inc #Derived_gen.5;
jump List.678 #Derived_gen.5 #Derived_gen.6 #Derived_gen.7 #Derived_gen.8 #Derived_gen.9;
inc Bool.29;
jump List.678 Bool.29 Bool.30 Bool.31 Bool.32 Bool.33;
procedure List.18 (List.172, List.173, List.174):
let List.676 : U64 = 0i64;
@ -41,17 +41,17 @@ procedure Num.51 (#Attr.2, #Attr.3):
ret Num.283;
procedure Str.3 (#Attr.2, #Attr.3):
let Str.380 : Str = lowlevel StrConcat #Attr.2 #Attr.3;
ret Str.380;
let Str.250 : Str = lowlevel StrConcat #Attr.2 #Attr.3;
ret Str.250;
procedure Test.1 (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:
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;
joinpoint #Derived_gen.14:
joinpoint Bool.36:
joinpoint Test.31 Test.29:
let Test.30 : U8 = GetTagId Test.33;
switch Test.30:
@ -78,16 +78,16 @@ procedure Test.11 (#Derived_gen.10, #Derived_gen.11):
jump Test.31 Test.32;
in
let #Derived_gen.15 : Int1 = lowlevel RefCountIsUnique #Attr.12;
if #Derived_gen.15 then
let Bool.37 : Int1 = lowlevel RefCountIsUnique #Attr.12;
if Bool.37 then
free #Attr.12;
jump #Derived_gen.14;
jump Bool.36;
else
inc Test.33;
decref #Attr.12;
jump #Derived_gen.14;
jump Bool.36;
in
jump Test.27 #Derived_gen.10 #Derived_gen.11;
jump Test.27 Bool.27 Bool.28;
procedure Test.2 (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):
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;
joinpoint #Derived_gen.12:
joinpoint Bool.34:
let Test.39 : U8 = GetTagId Test.42;
joinpoint Test.40 Test.38:
switch Test.43:
@ -146,14 +146,14 @@ procedure Test.9 (Test.10, #Attr.12):
jump Test.40 Test.41;
in
let #Derived_gen.13 : Int1 = lowlevel RefCountIsUnique #Attr.12;
if #Derived_gen.13 then
let Bool.35 : Int1 = lowlevel RefCountIsUnique #Attr.12;
if Bool.35 then
free #Attr.12;
jump #Derived_gen.12;
jump Bool.34;
else
inc Test.42;
decref #Attr.12;
jump #Derived_gen.12;
jump Bool.34;
procedure Test.0 ():
let Test.45 : Int1 = false;

View file

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

View file

@ -1,17 +1,17 @@
procedure Bool.11 (#Attr.2, #Attr.3):
let Bool.25 : Int1 = lowlevel Eq #Attr.2 #Attr.3;
ret Bool.25;
procedure Bool.11 (#Attr.2, #Attr.3):
let Bool.26 : Int1 = lowlevel Eq #Attr.2 #Attr.3;
ret Bool.26;
procedure Bool.1 ():
let Bool.22 : Int1 = false;
ret Bool.22;
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;
procedure Bool.3 (#Attr.2, #Attr.3):
let Bool.24 : Int1 = lowlevel And #Attr.2 #Attr.3;
procedure Bool.9 (#Attr.2, #Attr.3):
let Bool.24 : Int1 = lowlevel Eq #Attr.2 #Attr.3;
ret Bool.24;
procedure Inspect.245 (Inspect.246, Inspect.244):
@ -104,181 +104,184 @@ procedure Num.77 (#Attr.2, #Attr.3):
ret Num.293;
procedure Str.20 (#Attr.2):
let Str.445 : Str = lowlevel StrWithCapacity #Attr.2;
ret Str.445;
let Str.316 : Str = lowlevel StrWithCapacity #Attr.2;
ret Str.316;
procedure Str.3 (#Attr.2, #Attr.3):
let Str.378 : Str = lowlevel StrConcat #Attr.2 #Attr.3;
ret Str.378;
let Str.248 : Str = lowlevel StrConcat #Attr.2 #Attr.3;
ret Str.248;
procedure Str.35 (#Attr.2, #Attr.3):
let Str.435 : U8 = lowlevel StrGetUnsafe #Attr.2 #Attr.3;
ret Str.435;
let Str.306 : U8 = lowlevel StrGetUnsafe #Attr.2 #Attr.3;
ret Str.306;
procedure Str.36 (#Attr.2):
let Str.398 : U64 = lowlevel StrCountUtf8Bytes #Attr.2;
ret Str.398;
let Str.268 : U64 = lowlevel StrCountUtf8Bytes #Attr.2;
ret Str.268;
procedure Str.37 (#Attr.2, #Attr.3, #Attr.4):
let Str.396 : Str = lowlevel StrSubstringUnsafe #Attr.2 #Attr.3 #Attr.4;
ret Str.396;
let Str.266 : Str = lowlevel StrSubstringUnsafe #Attr.2 #Attr.3 #Attr.4;
ret Str.266;
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;
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
dec Str.210;
let Str.404 : {} = Struct {};
let Str.403 : [C {}, C {Str, Str}] = TagId(0) Str.404;
ret Str.403;
dec Str.113;
let Str.274 : {} = Struct {};
let Str.273 : [C {}, C {Str, Str}] = TagId(0) Str.274;
ret Str.273;
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;
procedure Str.45 (Str.92, Str.93, Str.94):
inc Str.92;
let Str.344 : [C {}, C {Str, Str}] = CallByName Str.38 Str.92 Str.93;
let Str.352 : U8 = 1i64;
let Str.353 : U8 = GetTagId Str.344;
let Str.354 : Int1 = lowlevel Eq Str.352 Str.353;
if Str.354 then
let Str.351 : {Str, Str} = UnionAtIndex (Id 1) (Index 0) Str.344;
let Str.96 : Str = StructAtIndex 0 Str.351;
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.473;
ret Str.189;
dec Str.344;
ret Str.92;
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;
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.196;
dec Str.383;
dec Str.197;
let Str.387 : Str = CallByName Str.3 Str.194 Str.195;
dec Str.195;
ret Str.387;
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.7;
inc #Derived_gen.8;
jump Str.382 #Derived_gen.5 #Derived_gen.6 #Derived_gen.7 #Derived_gen.8;
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.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.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.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;
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.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;
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.224;
dec Str.225;
let Str.411 : [C , C U64] = TagId(0) ;
ret Str.411;
dec Str.127;
dec Str.128;
let Str.281 : [C , C U64] = TagId(0) ;
ret Str.281;
in
inc #Derived_gen.0;
inc #Derived_gen.1;
jump Str.410 #Derived_gen.0 #Derived_gen.1 #Derived_gen.2 #Derived_gen.3;
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.66 (Str.250, Str.251):
let Str.440 : Int1 = CallByName Num.22 Str.250 Str.251;
if Str.440 then
ret Str.250;
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.251;
ret Str.154;
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.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.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;
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.433 : U8 = CallByName Str.35 Str.259 Str.260;
let Str.434 : U8 = CallByName Str.35 Str.261 Str.262;
let Str.267 : Int1 = CallByName Bool.11 Str.433 Str.434;
let Str.423 : U64 = StructAtIndex 0 Str.258;
let Str.424 : Str = StructAtIndex 1 Str.258;
let Str.426 : Str = StructAtIndex 3 Str.258;
let Str.428 : U64 = StructAtIndex 5 Str.258;
let Str.432 : U64 = 1i64;
let Str.430 : U64 = CallByName Num.51 Str.262 Str.432;
let Str.431 : U64 = 1i64;
let Str.429 : U64 = CallByName Num.51 Str.260 Str.431;
let Str.422 : {U64, Str, U64, Str, U64, U64} = Struct {Str.423, Str.424, Str.429, Str.426, Str.430, Str.428};
let Str.268 : Int1 = CallByName Str.68 Str.422;
let Str.421 : Int1 = CallByName Bool.3 Str.267 Str.268;
ret Str.421;
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 ():
let Test.4 : Str = "";

View file

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

View file

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

View file

@ -1,13 +1,13 @@
procedure Bool.11 (#Attr.2, #Attr.3):
let Bool.24 : Int1 = lowlevel Eq #Attr.2 #Attr.3;
ret Bool.24;
procedure Bool.1 ():
let Bool.21 : Int1 = false;
ret Bool.21;
procedure Bool.11 (#Attr.2, #Attr.3):
let Bool.25 : Int1 = lowlevel Eq #Attr.2 #Attr.3;
ret Bool.25;
procedure Bool.9 (#Attr.2, #Attr.3):
let Bool.22 : Int1 = lowlevel Eq #Attr.2 #Attr.3;
ret Bool.22;
procedure Bool.3 (#Attr.2, #Attr.3):
let Bool.23 : Int1 = lowlevel And #Attr.2 #Attr.3;
procedure Bool.9 (#Attr.2, #Attr.3):
let Bool.23 : Int1 = lowlevel Eq #Attr.2 #Attr.3;
ret Bool.23;
procedure Inspect.245 (Inspect.246, Inspect.244):
@ -100,181 +100,184 @@ procedure Num.77 (#Attr.2, #Attr.3):
ret Num.293;
procedure Str.20 (#Attr.2):
let Str.445 : Str = lowlevel StrWithCapacity #Attr.2;
ret Str.445;
let Str.316 : Str = lowlevel StrWithCapacity #Attr.2;
ret Str.316;
procedure Str.3 (#Attr.2, #Attr.3):
let Str.378 : Str = lowlevel StrConcat #Attr.2 #Attr.3;
ret Str.378;
let Str.248 : Str = lowlevel StrConcat #Attr.2 #Attr.3;
ret Str.248;
procedure Str.35 (#Attr.2, #Attr.3):
let Str.435 : U8 = lowlevel StrGetUnsafe #Attr.2 #Attr.3;
ret Str.435;
let Str.306 : U8 = lowlevel StrGetUnsafe #Attr.2 #Attr.3;
ret Str.306;
procedure Str.36 (#Attr.2):
let Str.398 : U64 = lowlevel StrCountUtf8Bytes #Attr.2;
ret Str.398;
let Str.268 : U64 = lowlevel StrCountUtf8Bytes #Attr.2;
ret Str.268;
procedure Str.37 (#Attr.2, #Attr.3, #Attr.4):
let Str.396 : Str = lowlevel StrSubstringUnsafe #Attr.2 #Attr.3 #Attr.4;
ret Str.396;
let Str.266 : Str = lowlevel StrSubstringUnsafe #Attr.2 #Attr.3 #Attr.4;
ret Str.266;
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;
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
dec Str.210;
let Str.404 : {} = Struct {};
let Str.403 : [C {}, C {Str, Str}] = TagId(0) Str.404;
ret Str.403;
dec Str.113;
let Str.274 : {} = Struct {};
let Str.273 : [C {}, C {Str, Str}] = TagId(0) Str.274;
ret Str.273;
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;
procedure Str.45 (Str.92, Str.93, Str.94):
inc Str.92;
let Str.344 : [C {}, C {Str, Str}] = CallByName Str.38 Str.92 Str.93;
let Str.352 : U8 = 1i64;
let Str.353 : U8 = GetTagId Str.344;
let Str.354 : Int1 = lowlevel Eq Str.352 Str.353;
if Str.354 then
let Str.351 : {Str, Str} = UnionAtIndex (Id 1) (Index 0) Str.344;
let Str.96 : Str = StructAtIndex 0 Str.351;
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.473;
ret Str.189;
dec Str.344;
ret Str.92;
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;
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.196;
dec Str.383;
dec Str.197;
let Str.387 : Str = CallByName Str.3 Str.194 Str.195;
dec Str.195;
ret Str.387;
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.382 #Derived_gen.0 #Derived_gen.1 #Derived_gen.2 #Derived_gen.3;
inc Bool.26;
inc Bool.27;
jump Str.252 Bool.24 Bool.25 Bool.26 Bool.27;
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.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.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;
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.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;
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.224;
dec Str.225;
let Str.411 : [C , C U64] = TagId(0) ;
ret Str.411;
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.410 #Derived_gen.4 #Derived_gen.5 #Derived_gen.6 #Derived_gen.7;
inc Bool.29;
inc Bool.28;
jump Str.280 Bool.28 Bool.29 Bool.30 Bool.31;
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;
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.251;
ret Str.154;
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.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.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;
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.433 : U8 = CallByName Str.35 Str.259 Str.260;
let Str.434 : U8 = CallByName Str.35 Str.261 Str.262;
let Str.267 : Int1 = CallByName Bool.11 Str.433 Str.434;
let Str.423 : U64 = StructAtIndex 0 Str.258;
let Str.424 : Str = StructAtIndex 1 Str.258;
let Str.426 : Str = StructAtIndex 3 Str.258;
let Str.428 : U64 = StructAtIndex 5 Str.258;
let Str.432 : U64 = 1i64;
let Str.430 : U64 = CallByName Num.51 Str.262 Str.432;
let Str.431 : U64 = 1i64;
let Str.429 : U64 = CallByName Num.51 Str.260 Str.431;
let Str.422 : {U64, Str, U64, Str, U64, U64} = Struct {Str.423, Str.424, Str.429, Str.426, Str.430, Str.428};
let Str.268 : Int1 = CallByName Str.68 Str.422;
let Str.421 : Int1 = CallByName Bool.3 Str.267 Str.268;
ret Str.421;
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 ():
let Test.3 : Str = "";

View file

@ -1,6 +1,6 @@
procedure Bool.11 (#Attr.2, #Attr.3):
let Bool.24 : Int1 = lowlevel Eq #Attr.2 #Attr.3;
ret Bool.24;
procedure Bool.9 (#Attr.2, #Attr.3):
let Bool.22 : Int1 = lowlevel Eq #Attr.2 #Attr.3;
ret Bool.22;
procedure Num.19 (#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;
procedure Str.3 (#Attr.2, #Attr.3):
let Str.379 : Str = lowlevel StrConcat #Attr.2 #Attr.3;
ret Str.379;
let Str.249 : Str = lowlevel StrConcat #Attr.2 #Attr.3;
ret Str.249;
procedure Test.1 (Test.2):
let Test.3 : Str = CallByName Num.96 Test.2;
@ -25,7 +25,7 @@ procedure Test.1 (Test.2):
ret Test.8;
in
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
dec Test.3;
let Test.21 : Str = "early 1";
@ -38,7 +38,7 @@ procedure Test.1 (Test.2):
jump Test.12 Test.11;
in
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
dec Test.3;
dec Test.5;

View file

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

View file

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

View file

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

View file

@ -1,6 +1,6 @@
procedure Bool.1 ():
let Bool.23 : Int1 = false;
ret Bool.23;
let Bool.21 : Int1 = false;
ret Bool.21;
procedure List.2 (List.120, List.121):
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;
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:
let List.680 : Int1 = CallByName Num.22 List.178 List.179;
if List.680 then
@ -81,10 +81,10 @@ procedure List.101 (#Derived_gen.26, #Derived_gen.27, #Derived_gen.28, #Derived_
dec List.175;
ret List.176;
in
inc #Derived_gen.26;
jump List.678 #Derived_gen.26 #Derived_gen.27 #Derived_gen.28 #Derived_gen.29 #Derived_gen.30;
inc #Derived_gen.35;
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:
let List.706 : Int1 = CallByName Num.22 List.178 List.179;
if List.706 then
@ -98,8 +98,8 @@ procedure List.101 (#Derived_gen.31, #Derived_gen.32, #Derived_gen.33, #Derived_
dec List.175;
ret List.176;
in
inc #Derived_gen.31;
jump List.704 #Derived_gen.31 #Derived_gen.32 #Derived_gen.33 #Derived_gen.34 #Derived_gen.35;
inc #Derived_gen.40;
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):
let List.676 : U64 = 0i64;
@ -164,32 +164,32 @@ procedure Num.96 (#Attr.2):
ret Num.287;
procedure Str.12 (#Attr.2):
let Str.391 : List U8 = lowlevel StrToUtf8 #Attr.2;
ret Str.391;
let Str.261 : List U8 = lowlevel StrToUtf8 #Attr.2;
ret Str.261;
procedure Str.36 (#Attr.2):
let Str.392 : U64 = lowlevel StrCountUtf8Bytes #Attr.2;
ret Str.392;
let Str.262 : U64 = lowlevel StrCountUtf8Bytes #Attr.2;
ret Str.262;
procedure Str.43 (#Attr.2):
let Str.386 : {U64, Str, Int1, U8} = lowlevel StrFromUtf8 #Attr.2;
ret Str.386;
let Str.256 : {U64, Str, Int1, U8} = lowlevel StrFromUtf8 #Attr.2;
ret Str.256;
procedure Str.9 (Str.76):
let Str.77 : {U64, Str, Int1, U8} = CallByName Str.43 Str.76;
let Str.383 : Int1 = StructAtIndex 2 Str.77;
if Str.383 then
let Str.385 : Str = StructAtIndex 1 Str.77;
let Str.384 : [C {U64, U8}, C Str] = TagId(1) Str.385;
ret Str.384;
procedure Str.9 (Str.74):
let Str.75 : {U64, Str, Int1, U8} = CallByName Str.43 Str.74;
let Str.253 : Int1 = StructAtIndex 2 Str.75;
if Str.253 then
let Str.255 : Str = StructAtIndex 1 Str.75;
let Str.254 : [C {U64, U8}, C Str] = TagId(1) Str.255;
ret Str.254;
else
let Str.381 : U64 = StructAtIndex 0 Str.77;
let Str.382 : U8 = StructAtIndex 3 Str.77;
let #Derived_gen.45 : Str = StructAtIndex 1 Str.77;
let Str.251 : U64 = StructAtIndex 0 Str.75;
let Str.252 : U8 = StructAtIndex 3 Str.75;
let #Derived_gen.45 : Str = StructAtIndex 1 Str.75;
dec #Derived_gen.45;
let Str.380 : {U64, U8} = Struct {Str.381, Str.382};
let Str.378 : [C {U64, U8}, C Str] = TagId(0) Str.380;
ret Str.378;
let Str.250 : {U64, U8} = Struct {Str.251, Str.252};
let Str.248 : [C {U64, U8}, C Str] = TagId(0) Str.250;
ret Str.248;
procedure Test.20 (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;
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:
let List.680 : Int1 = CallByName Num.22 List.178 List.179;
if List.680 then
@ -53,8 +53,8 @@ procedure List.101 (#Derived_gen.16, #Derived_gen.17, #Derived_gen.18, #Derived_
dec List.175;
ret List.176;
in
inc #Derived_gen.16;
jump List.678 #Derived_gen.16 #Derived_gen.17 #Derived_gen.18 #Derived_gen.19 #Derived_gen.20;
inc #Derived_gen.19;
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):
let List.676 : U64 = 0i64;
@ -105,32 +105,32 @@ procedure Num.96 (#Attr.2):
ret Num.283;
procedure Str.12 (#Attr.2):
let Str.388 : List U8 = lowlevel StrToUtf8 #Attr.2;
ret Str.388;
let Str.258 : List U8 = lowlevel StrToUtf8 #Attr.2;
ret Str.258;
procedure Str.36 (#Attr.2):
let Str.389 : U64 = lowlevel StrCountUtf8Bytes #Attr.2;
ret Str.389;
let Str.259 : U64 = lowlevel StrCountUtf8Bytes #Attr.2;
ret Str.259;
procedure Str.43 (#Attr.2):
let Str.386 : {U64, Str, Int1, U8} = lowlevel StrFromUtf8 #Attr.2;
ret Str.386;
let Str.256 : {U64, Str, Int1, U8} = lowlevel StrFromUtf8 #Attr.2;
ret Str.256;
procedure Str.9 (Str.76):
let Str.77 : {U64, Str, Int1, U8} = CallByName Str.43 Str.76;
let Str.383 : Int1 = StructAtIndex 2 Str.77;
if Str.383 then
let Str.385 : Str = StructAtIndex 1 Str.77;
let Str.384 : [C {U64, U8}, C Str] = TagId(1) Str.385;
ret Str.384;
procedure Str.9 (Str.74):
let Str.75 : {U64, Str, Int1, U8} = CallByName Str.43 Str.74;
let Str.253 : Int1 = StructAtIndex 2 Str.75;
if Str.253 then
let Str.255 : Str = StructAtIndex 1 Str.75;
let Str.254 : [C {U64, U8}, C Str] = TagId(1) Str.255;
ret Str.254;
else
let Str.381 : U64 = StructAtIndex 0 Str.77;
let Str.382 : U8 = StructAtIndex 3 Str.77;
let #Derived_gen.24 : Str = StructAtIndex 1 Str.77;
let Str.251 : U64 = StructAtIndex 0 Str.75;
let Str.252 : U8 = StructAtIndex 3 Str.75;
let #Derived_gen.24 : Str = StructAtIndex 1 Str.75;
dec #Derived_gen.24;
let Str.380 : {U64, U8} = Struct {Str.381, Str.382};
let Str.378 : [C {U64, U8}, C Str] = TagId(0) Str.380;
ret Str.378;
let Str.250 : {U64, U8} = Struct {Str.251, Str.252};
let Str.248 : [C {U64, U8}, C Str] = TagId(0) Str.250;
ret Str.248;
procedure Test.20 (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;
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:
let List.680 : Int1 = CallByName Num.22 List.178 List.179;
if List.680 then
@ -60,8 +60,8 @@ procedure List.101 (#Derived_gen.20, #Derived_gen.21, #Derived_gen.22, #Derived_
dec List.175;
ret List.176;
in
inc #Derived_gen.20;
jump List.678 #Derived_gen.20 #Derived_gen.21 #Derived_gen.22 #Derived_gen.23 #Derived_gen.24;
inc #Derived_gen.23;
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):
let List.676 : U64 = 0i64;
@ -112,32 +112,32 @@ procedure Num.96 (#Attr.2):
ret Num.283;
procedure Str.12 (#Attr.2):
let Str.388 : List U8 = lowlevel StrToUtf8 #Attr.2;
ret Str.388;
let Str.258 : List U8 = lowlevel StrToUtf8 #Attr.2;
ret Str.258;
procedure Str.36 (#Attr.2):
let Str.389 : U64 = lowlevel StrCountUtf8Bytes #Attr.2;
ret Str.389;
let Str.259 : U64 = lowlevel StrCountUtf8Bytes #Attr.2;
ret Str.259;
procedure Str.43 (#Attr.2):
let Str.386 : {U64, Str, Int1, U8} = lowlevel StrFromUtf8 #Attr.2;
ret Str.386;
let Str.256 : {U64, Str, Int1, U8} = lowlevel StrFromUtf8 #Attr.2;
ret Str.256;
procedure Str.9 (Str.76):
let Str.77 : {U64, Str, Int1, U8} = CallByName Str.43 Str.76;
let Str.383 : Int1 = StructAtIndex 2 Str.77;
if Str.383 then
let Str.385 : Str = StructAtIndex 1 Str.77;
let Str.384 : [C {U64, U8}, C Str] = TagId(1) Str.385;
ret Str.384;
procedure Str.9 (Str.74):
let Str.75 : {U64, Str, Int1, U8} = CallByName Str.43 Str.74;
let Str.253 : Int1 = StructAtIndex 2 Str.75;
if Str.253 then
let Str.255 : Str = StructAtIndex 1 Str.75;
let Str.254 : [C {U64, U8}, C Str] = TagId(1) Str.255;
ret Str.254;
else
let Str.381 : U64 = StructAtIndex 0 Str.77;
let Str.382 : U8 = StructAtIndex 3 Str.77;
let #Derived_gen.28 : Str = StructAtIndex 1 Str.77;
let Str.251 : U64 = StructAtIndex 0 Str.75;
let Str.252 : U8 = StructAtIndex 3 Str.75;
let #Derived_gen.28 : Str = StructAtIndex 1 Str.75;
dec #Derived_gen.28;
let Str.380 : {U64, U8} = Struct {Str.381, Str.382};
let Str.378 : [C {U64, U8}, C Str] = TagId(0) Str.380;
ret Str.378;
let Str.250 : {U64, U8} = Struct {Str.251, Str.252};
let Str.248 : [C {U64, U8}, C Str] = TagId(0) Str.250;
ret Str.248;
procedure Test.20 (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;
procedure Str.12 (#Attr.2):
let Str.388 : List U8 = lowlevel StrToUtf8 #Attr.2;
ret Str.388;
let Str.258 : List U8 = lowlevel StrToUtf8 #Attr.2;
ret Str.258;
procedure Str.36 (#Attr.2):
let Str.389 : U64 = lowlevel StrCountUtf8Bytes #Attr.2;
ret Str.389;
let Str.259 : U64 = lowlevel StrCountUtf8Bytes #Attr.2;
ret Str.259;
procedure Str.43 (#Attr.2):
let Str.386 : {U64, Str, Int1, U8} = lowlevel StrFromUtf8 #Attr.2;
ret Str.386;
let Str.256 : {U64, Str, Int1, U8} = lowlevel StrFromUtf8 #Attr.2;
ret Str.256;
procedure Str.9 (Str.76):
let Str.77 : {U64, Str, Int1, U8} = CallByName Str.43 Str.76;
let Str.383 : Int1 = StructAtIndex 2 Str.77;
if Str.383 then
let Str.385 : Str = StructAtIndex 1 Str.77;
let Str.384 : [C {U64, U8}, C Str] = TagId(1) Str.385;
ret Str.384;
procedure Str.9 (Str.74):
let Str.75 : {U64, Str, Int1, U8} = CallByName Str.43 Str.74;
let Str.253 : Int1 = StructAtIndex 2 Str.75;
if Str.253 then
let Str.255 : Str = StructAtIndex 1 Str.75;
let Str.254 : [C {U64, U8}, C Str] = TagId(1) Str.255;
ret Str.254;
else
let Str.381 : U64 = StructAtIndex 0 Str.77;
let Str.382 : U8 = StructAtIndex 3 Str.77;
let #Derived_gen.3 : Str = StructAtIndex 1 Str.77;
let Str.251 : U64 = StructAtIndex 0 Str.75;
let Str.252 : U8 = StructAtIndex 3 Str.75;
let #Derived_gen.3 : Str = StructAtIndex 1 Str.75;
dec #Derived_gen.3;
let Str.380 : {U64, U8} = Struct {Str.381, Str.382};
let Str.378 : [C {U64, U8}, C Str] = TagId(0) Str.380;
ret Str.378;
let Str.250 : {U64, U8} = Struct {Str.251, Str.252};
let Str.248 : [C {U64, U8}, C Str] = TagId(0) Str.250;
ret Str.248;
procedure Test.20 (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;
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:
let List.680 : Int1 = CallByName Num.22 List.178 List.179;
if List.680 then
@ -54,8 +54,8 @@ procedure List.101 (#Derived_gen.10, #Derived_gen.11, #Derived_gen.12, #Derived_
dec List.175;
ret List.176;
in
inc #Derived_gen.10;
jump List.678 #Derived_gen.10 #Derived_gen.11 #Derived_gen.12 #Derived_gen.13 #Derived_gen.14;
inc #Derived_gen.22;
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):
let List.701 : List Str = lowlevel ListPrepend #Attr.2 #Attr.3;
@ -110,32 +110,32 @@ procedure Num.96 (#Attr.2):
ret Num.283;
procedure Str.12 (#Attr.2):
let Str.388 : List U8 = lowlevel StrToUtf8 #Attr.2;
ret Str.388;
let Str.258 : List U8 = lowlevel StrToUtf8 #Attr.2;
ret Str.258;
procedure Str.36 (#Attr.2):
let Str.389 : U64 = lowlevel StrCountUtf8Bytes #Attr.2;
ret Str.389;
let Str.259 : U64 = lowlevel StrCountUtf8Bytes #Attr.2;
ret Str.259;
procedure Str.43 (#Attr.2):
let Str.386 : {U64, Str, Int1, U8} = lowlevel StrFromUtf8 #Attr.2;
ret Str.386;
let Str.256 : {U64, Str, Int1, U8} = lowlevel StrFromUtf8 #Attr.2;
ret Str.256;
procedure Str.9 (Str.76):
let Str.77 : {U64, Str, Int1, U8} = CallByName Str.43 Str.76;
let Str.383 : Int1 = StructAtIndex 2 Str.77;
if Str.383 then
let Str.385 : Str = StructAtIndex 1 Str.77;
let Str.384 : [C {U64, U8}, C Str] = TagId(1) Str.385;
ret Str.384;
procedure Str.9 (Str.74):
let Str.75 : {U64, Str, Int1, U8} = CallByName Str.43 Str.74;
let Str.253 : Int1 = StructAtIndex 2 Str.75;
if Str.253 then
let Str.255 : Str = StructAtIndex 1 Str.75;
let Str.254 : [C {U64, U8}, C Str] = TagId(1) Str.255;
ret Str.254;
else
let Str.381 : U64 = StructAtIndex 0 Str.77;
let Str.382 : U8 = StructAtIndex 3 Str.77;
let #Derived_gen.27 : Str = StructAtIndex 1 Str.77;
let Str.251 : U64 = StructAtIndex 0 Str.75;
let Str.252 : U8 = StructAtIndex 3 Str.75;
let #Derived_gen.27 : Str = StructAtIndex 1 Str.75;
dec #Derived_gen.27;
let Str.380 : {U64, U8} = Struct {Str.381, Str.382};
let Str.378 : [C {U64, U8}, C Str] = TagId(0) Str.380;
ret Str.378;
let Str.250 : {U64, U8} = Struct {Str.251, Str.252};
let Str.248 : [C {U64, U8}, C Str] = TagId(0) Str.250;
ret Str.248;
procedure Test.20 (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;
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:
let List.680 : Int1 = CallByName Num.22 List.178 List.179;
if List.680 then
@ -57,8 +57,8 @@ procedure List.101 (#Derived_gen.20, #Derived_gen.21, #Derived_gen.22, #Derived_
dec List.175;
ret List.176;
in
inc #Derived_gen.20;
jump List.678 #Derived_gen.20 #Derived_gen.21 #Derived_gen.22 #Derived_gen.23 #Derived_gen.24;
inc #Derived_gen.23;
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):
let List.701 : List Str = lowlevel ListPrepend #Attr.2 #Attr.3;
@ -113,32 +113,32 @@ procedure Num.96 (#Attr.2):
ret Num.283;
procedure Str.12 (#Attr.2):
let Str.388 : List U8 = lowlevel StrToUtf8 #Attr.2;
ret Str.388;
let Str.258 : List U8 = lowlevel StrToUtf8 #Attr.2;
ret Str.258;
procedure Str.36 (#Attr.2):
let Str.389 : U64 = lowlevel StrCountUtf8Bytes #Attr.2;
ret Str.389;
let Str.259 : U64 = lowlevel StrCountUtf8Bytes #Attr.2;
ret Str.259;
procedure Str.43 (#Attr.2):
let Str.386 : {U64, Str, Int1, U8} = lowlevel StrFromUtf8 #Attr.2;
ret Str.386;
let Str.256 : {U64, Str, Int1, U8} = lowlevel StrFromUtf8 #Attr.2;
ret Str.256;
procedure Str.9 (Str.76):
let Str.77 : {U64, Str, Int1, U8} = CallByName Str.43 Str.76;
let Str.383 : Int1 = StructAtIndex 2 Str.77;
if Str.383 then
let Str.385 : Str = StructAtIndex 1 Str.77;
let Str.384 : [C {U64, U8}, C Str] = TagId(1) Str.385;
ret Str.384;
procedure Str.9 (Str.74):
let Str.75 : {U64, Str, Int1, U8} = CallByName Str.43 Str.74;
let Str.253 : Int1 = StructAtIndex 2 Str.75;
if Str.253 then
let Str.255 : Str = StructAtIndex 1 Str.75;
let Str.254 : [C {U64, U8}, C Str] = TagId(1) Str.255;
ret Str.254;
else
let Str.381 : U64 = StructAtIndex 0 Str.77;
let Str.382 : U8 = StructAtIndex 3 Str.77;
let #Derived_gen.28 : Str = StructAtIndex 1 Str.77;
let Str.251 : U64 = StructAtIndex 0 Str.75;
let Str.252 : U8 = StructAtIndex 3 Str.75;
let #Derived_gen.28 : Str = StructAtIndex 1 Str.75;
dec #Derived_gen.28;
let Str.380 : {U64, U8} = Struct {Str.381, Str.382};
let Str.378 : [C {U64, U8}, C Str] = TagId(0) Str.380;
ret Str.378;
let Str.250 : {U64, U8} = Struct {Str.251, Str.252};
let Str.248 : [C {U64, U8}, C Str] = TagId(0) Str.250;
ret Str.248;
procedure Test.20 (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;
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:
let Test.13 : I64 = 0i64;
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;
jump Test.7 Test.10 Test.11;
in
jump Test.7 #Derived_gen.0 #Derived_gen.1;
jump Test.7 Bool.21 Bool.22;
procedure Test.0 ():
let Test.5 : I64 = 10i64;

View file

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

View file

@ -1,6 +1,6 @@
procedure Bool.11 (#Attr.2, #Attr.3):
let Bool.23 : Int1 = lowlevel Eq #Attr.2 #Attr.3;
ret Bool.23;
procedure Bool.9 (#Attr.2, #Attr.3):
let Bool.21 : Int1 = lowlevel Eq #Attr.2 #Attr.3;
ret Bool.21;
procedure Test.1 (Test.3):
let Test.6 : I64 = 10i64;
@ -13,7 +13,7 @@ procedure Test.1 (Test.3):
ret Test.8;
in
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;
procedure Test.0 ():

View file

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

View file

@ -1,6 +1,6 @@
procedure Bool.1 ():
let Bool.23 : Int1 = false;
ret Bool.23;
let Bool.21 : Int1 = false;
ret Bool.21;
procedure Num.19 (#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):
ret Test.4;
procedure Test.0 (#Derived_gen.0):
procedure Test.0 (Bool.22):
joinpoint Test.5 Test.1:
joinpoint Test.10 Test.2:
let Test.8 : I64 = 1i64;
@ -31,4 +31,4 @@ procedure Test.0 (#Derived_gen.0):
let Test.9 : Int1 = true;
jump Test.10 Test.9;
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;
ret Test.23;
procedure Test.0 (#Derived_gen.0):
procedure Test.0 (Bool.21):
joinpoint Test.11 Test.1:
let Test.25 : I64 = 1i64;
let Test.13 : I64 = CallByName Num.19 Test.1 Test.25;
@ -57,4 +57,4 @@ procedure Test.0 (#Derived_gen.0):
ret Test.12;
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;
ret Test.16;
procedure Test.0 (#Derived_gen.0):
procedure Test.0 (Bool.21):
joinpoint Test.7 Test.1:
let Test.21 : I64 = 1i64;
let Test.9 : I64 = CallByName Num.19 Test.1 Test.21;
@ -33,4 +33,4 @@ procedure Test.0 (#Derived_gen.0):
ret Test.8;
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