mirror of
https://github.com/roc-lang/roc.git
synced 2025-08-03 03:42:17 +00:00
Deriving string encoders works
This commit is contained in:
parent
a17748ea01
commit
9826253785
11 changed files with 372 additions and 33 deletions
|
@ -205,7 +205,7 @@ impl DerivedModule {
|
|||
&self.subs,
|
||||
target,
|
||||
// bookkeep unspecialized lambda sets of var - I think we want this here
|
||||
true,
|
||||
false,
|
||||
var,
|
||||
// TODO: I think this is okay because the only use of `copy_lambda_set_var_to_subs`
|
||||
// (at least right now) is for lambda set compaction, which will automatically unify
|
||||
|
@ -213,8 +213,8 @@ impl DerivedModule {
|
|||
//
|
||||
// However this is a bad coupling and maybe not a good assumption, we should revisit
|
||||
// this when possible.
|
||||
// Rank::toplevel(),
|
||||
target_rank,
|
||||
Rank::import(),
|
||||
// target_rank,
|
||||
);
|
||||
|
||||
copied_import.variable
|
||||
|
|
|
@ -10,7 +10,7 @@ use roc_collections::MutMap;
|
|||
use roc_derive::SharedDerivedModule;
|
||||
use roc_error_macros::internal_error;
|
||||
use roc_module::symbol::ModuleId;
|
||||
use roc_solve::solve::{compact_lambda_sets_of_vars, Phase, Pools};
|
||||
use roc_solve::solve::{compact_lambda_sets_of_vars, Phase, Pools, SubsProxy};
|
||||
use roc_types::subs::{Content, FlatType, LambdaSet};
|
||||
use roc_types::subs::{ExposedTypesStorageSubs, Subs, Variable};
|
||||
use roc_unify::unify::{unify as unify_unify, Mode, Unified};
|
||||
|
@ -174,7 +174,22 @@ pub fn unify(
|
|||
left: Variable,
|
||||
right: Variable,
|
||||
) -> Result<(), UnificationFailed> {
|
||||
let unified = unify_unify(subs, left, right, Mode::EQ);
|
||||
let unified = if home == ModuleId::DERIVED {
|
||||
// TODO: can we be smarter so more stuff can happen in parallel without us having to lock
|
||||
// and steal from the derived module here?
|
||||
let mut derived_module = derived_module.lock().unwrap();
|
||||
|
||||
let mut stolen = derived_module.steal();
|
||||
|
||||
let unified = unify_unify(&mut stolen.subs, left, right, Mode::EQ);
|
||||
|
||||
derived_module.return_stolen(stolen);
|
||||
|
||||
unified
|
||||
} else {
|
||||
unify_unify(subs, left, right, Mode::EQ)
|
||||
};
|
||||
|
||||
match unified {
|
||||
Unified::Success {
|
||||
vars: _,
|
||||
|
@ -186,14 +201,14 @@ pub fn unify(
|
|||
|
||||
let late_phase = LatePhase { home, abilities };
|
||||
|
||||
let mut subs_proxy = SubsProxy::new(home, subs, derived_module);
|
||||
let must_implement_constraints = compact_lambda_sets_of_vars(
|
||||
subs,
|
||||
&mut subs_proxy,
|
||||
arena,
|
||||
&mut pools,
|
||||
lambda_sets_to_specialize,
|
||||
&late_phase,
|
||||
exposed_by_module,
|
||||
derived_module,
|
||||
);
|
||||
// At this point we can't do anything with must-implement constraints, since we're no
|
||||
// longer solving. We must assume that they were totally caught during solving.
|
||||
|
@ -210,3 +225,26 @@ pub fn unify(
|
|||
Unified::Failure(..) | Unified::BadType(..) => Err(UnificationFailed),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn hack(
|
||||
lset: Variable,
|
||||
home: ModuleId,
|
||||
arena: &Bump,
|
||||
subs: &mut Subs,
|
||||
abilities: &AbilitiesView,
|
||||
derived_module: &SharedDerivedModule,
|
||||
exposed_by_module: &ExposedByModule,
|
||||
) {
|
||||
let mut subs_proxy = SubsProxy::new(home, subs, derived_module);
|
||||
let late_phase = LatePhase { home, abilities };
|
||||
let mut uls_of_var = roc_types::subs::UlsOfVar::default();
|
||||
uls_of_var.add(lset, lset);
|
||||
compact_lambda_sets_of_vars(
|
||||
&mut subs_proxy,
|
||||
arena,
|
||||
&mut Pools::default(),
|
||||
uls_of_var,
|
||||
&late_phase,
|
||||
exposed_by_module,
|
||||
);
|
||||
}
|
||||
|
|
|
@ -2706,7 +2706,15 @@ fn finish_specialization(
|
|||
.into_inner()
|
||||
.into_module_ids();
|
||||
|
||||
let all_ident_ids = state.constrained_ident_ids;
|
||||
let mut all_ident_ids = state.constrained_ident_ids;
|
||||
// Steal the derived symbols and put them in the global ident ids. Since we're done, we won't
|
||||
// need them again.
|
||||
let StolenFromDerived {
|
||||
ident_ids: derived_ident_ids,
|
||||
subs: _,
|
||||
} = state.derived_module.lock().unwrap().steal();
|
||||
ModuleId::DERIVED.register_debug_idents(&derived_ident_ids);
|
||||
all_ident_ids.insert(ModuleId::DERIVED, derived_ident_ids);
|
||||
|
||||
let interns = Interns {
|
||||
module_ids,
|
||||
|
@ -4113,7 +4121,10 @@ fn run_solve_solve(
|
|||
}
|
||||
|
||||
let (solved_subs, solved_specializations, exposed_vars_by_symbol, problems, abilities_store) = {
|
||||
let module_id = module.module_id;
|
||||
|
||||
let (solved_subs, solved_env, problems, abilities_store) = roc_solve::module::run_solve(
|
||||
module_id,
|
||||
&constraints,
|
||||
actual_constraint,
|
||||
rigid_variables,
|
||||
|
@ -4125,7 +4136,6 @@ fn run_solve_solve(
|
|||
derived_module,
|
||||
);
|
||||
|
||||
let module_id = module.module_id;
|
||||
// Figure out what specializations belong to this module
|
||||
let solved_specializations: ResolvedSpecializations = abilities_store
|
||||
.iter_specializations()
|
||||
|
|
|
@ -2923,6 +2923,7 @@ fn specialize_external<'a>(
|
|||
host_exposed_variables: &[(Symbol, Variable)],
|
||||
partial_proc_id: PartialProcId,
|
||||
) -> Result<Proc<'a>, LayoutProblem> {
|
||||
dbg!(("spec ", proc_name));
|
||||
let partial_proc = procs.partial_procs.get_id(partial_proc_id);
|
||||
let captured_symbols = partial_proc.captured_symbols;
|
||||
|
||||
|
@ -2930,7 +2931,16 @@ fn specialize_external<'a>(
|
|||
let snapshot = env.subs.snapshot();
|
||||
let cache_snapshot = layout_cache.snapshot();
|
||||
|
||||
let ann = roc_types::subs::SubsFmtContent(
|
||||
env.subs
|
||||
.get_content_without_compacting(partial_proc.annotation),
|
||||
env.subs,
|
||||
);
|
||||
let spec =
|
||||
roc_types::subs::SubsFmtContent(env.subs.get_content_without_compacting(fn_var), env.subs);
|
||||
dbg!(ann, spec);
|
||||
let _unified = env.unify(partial_proc.annotation, fn_var);
|
||||
dbg!("done");
|
||||
|
||||
// This will not hold for programs with type errors
|
||||
// let is_valid = matches!(unified, roc_unify::unify::Unified::Success(_));
|
||||
|
@ -4747,6 +4757,12 @@ pub fn with_hole<'a>(
|
|||
|
||||
match loc_expr.value {
|
||||
roc_can::expr::Expr::Var(proc_name) if is_known(proc_name) => {
|
||||
dbg!(proc_name);
|
||||
dbg!(roc_types::subs::SubsFmtContent(
|
||||
env.subs.get_content_without_compacting(fn_var),
|
||||
&env.subs
|
||||
));
|
||||
|
||||
// a call by a known name
|
||||
call_by_name(
|
||||
env,
|
||||
|
|
|
@ -1235,7 +1235,23 @@ impl<'a> Layout<'a> {
|
|||
use roc_types::subs::Content::*;
|
||||
match content {
|
||||
FlexVar(_) | RigidVar(_) => Err(LayoutProblem::UnresolvedTypeVar(var)),
|
||||
FlexAbleVar(_, _) | RigidAbleVar(_, _) => todo_abilities!("Not reachable yet"),
|
||||
FlexAbleVar(_, _) | RigidAbleVar(_, _) => {
|
||||
unsafe {
|
||||
dbg!(
|
||||
roc_types::subs::SubsFmtContent(
|
||||
env.subs
|
||||
.get_content_without_compacting(Variable::from_index(1217)),
|
||||
&env.subs
|
||||
),
|
||||
roc_types::subs::SubsFmtContent(
|
||||
env.subs
|
||||
.get_content_without_compacting(Variable::from_index(1224)),
|
||||
&env.subs
|
||||
),
|
||||
);
|
||||
}
|
||||
todo_abilities!("Not reachable yet")
|
||||
}
|
||||
RecursionVar { structure, .. } => {
|
||||
let structure_content = env.subs.get_content_without_compacting(structure);
|
||||
Self::new_help(env, structure, *structure_content)
|
||||
|
@ -2099,6 +2115,13 @@ fn layout_from_flat_type<'a>(
|
|||
}
|
||||
}
|
||||
Func(_, closure_var, _) => {
|
||||
dbg!(
|
||||
closure_var,
|
||||
roc_types::subs::SubsFmtContent(
|
||||
env.subs.get_content_without_compacting(closure_var),
|
||||
&subs
|
||||
)
|
||||
);
|
||||
let lambda_set =
|
||||
LambdaSet::from_var(env.arena, env.subs, closure_var, env.target_info)?;
|
||||
|
||||
|
@ -2116,6 +2139,13 @@ fn layout_from_flat_type<'a>(
|
|||
for (label, field) in it {
|
||||
match field {
|
||||
RecordField::Required(field_var) | RecordField::Demanded(field_var) => {
|
||||
dbg!(
|
||||
label,
|
||||
roc_types::subs::SubsFmtContent(
|
||||
subs.get_content_without_compacting(field_var),
|
||||
subs
|
||||
)
|
||||
);
|
||||
sortables.push((label, Layout::from_var(env, field_var)?));
|
||||
}
|
||||
RecordField::Optional(_) => {
|
||||
|
|
|
@ -5,9 +5,9 @@ use roc_can::expr::PendingDerives;
|
|||
use roc_can::module::{ExposedByModule, RigidVariables};
|
||||
use roc_collections::all::MutMap;
|
||||
use roc_collections::VecMap;
|
||||
use roc_derive_key::GlobalDerivedSymbols;
|
||||
use roc_derive::SharedDerivedModule;
|
||||
use roc_error_macros::internal_error;
|
||||
use roc_module::symbol::Symbol;
|
||||
use roc_module::symbol::{ModuleId, Symbol};
|
||||
use roc_types::subs::{Content, ExposedTypesStorageSubs, FlatType, StorageSubs, Subs, Variable};
|
||||
use roc_types::types::Alias;
|
||||
|
||||
|
@ -54,6 +54,7 @@ pub struct SolvedModule {
|
|||
|
||||
#[allow(clippy::too_many_arguments)] // TODO: put params in a context/env var
|
||||
pub fn run_solve(
|
||||
home: ModuleId,
|
||||
constraints: &Constraints,
|
||||
constraint: ConstraintSoa,
|
||||
rigid_variables: RigidVariables,
|
||||
|
@ -87,6 +88,7 @@ pub fn run_solve(
|
|||
|
||||
// Run the solver to populate Subs.
|
||||
let (solved_subs, solved_env) = solve::run(
|
||||
home,
|
||||
constraints,
|
||||
&mut problems,
|
||||
subs,
|
||||
|
|
|
@ -14,8 +14,8 @@ use roc_collections::all::MutMap;
|
|||
use roc_debug_flags::dbg_do;
|
||||
#[cfg(debug_assertions)]
|
||||
use roc_debug_flags::{ROC_TRACE_COMPACTION, ROC_VERIFY_RIGID_LET_GENERALIZED};
|
||||
use roc_derive::SharedDerivedModule;
|
||||
use roc_derive_key::{DeriveError, Derived};
|
||||
use roc_derive::{DerivedModule, SharedDerivedModule};
|
||||
use roc_derive_key::{DeriveError, DeriveKey};
|
||||
use roc_error_macros::internal_error;
|
||||
use roc_module::ident::TagName;
|
||||
use roc_module::symbol::{ModuleId, Symbol};
|
||||
|
@ -545,6 +545,7 @@ struct State {
|
|||
|
||||
#[allow(clippy::too_many_arguments)] // TODO: put params in a context/env var
|
||||
pub fn run(
|
||||
home: ModuleId,
|
||||
constraints: &Constraints,
|
||||
problems: &mut Vec<TypeError>,
|
||||
mut subs: Subs,
|
||||
|
@ -556,6 +557,7 @@ pub fn run(
|
|||
derived_module: SharedDerivedModule,
|
||||
) -> (Solved<Subs>, Env) {
|
||||
let env = run_in_place(
|
||||
home,
|
||||
constraints,
|
||||
problems,
|
||||
&mut subs,
|
||||
|
@ -573,6 +575,7 @@ pub fn run(
|
|||
/// Modify an existing subs in-place instead
|
||||
#[allow(clippy::too_many_arguments)] // TODO: put params in a context/env var
|
||||
fn run_in_place(
|
||||
home: ModuleId,
|
||||
constraints: &Constraints,
|
||||
problems: &mut Vec<TypeError>,
|
||||
subs: &mut Subs,
|
||||
|
@ -617,14 +620,15 @@ fn run_in_place(
|
|||
// Now that the module has been solved, we can run through and check all
|
||||
// types claimed to implement abilities. This will also tell us what derives
|
||||
// are legal, which we need to register.
|
||||
let mut subs_proxy = SubsProxy::new(home, subs, &derived_module);
|
||||
|
||||
let new_must_implement = compact_lambda_sets_of_vars(
|
||||
subs,
|
||||
&mut subs_proxy,
|
||||
&arena,
|
||||
&mut pools,
|
||||
deferred_uls_to_resolve,
|
||||
&SolvePhase { abilities_store },
|
||||
exposed_by_module,
|
||||
&derived_module,
|
||||
);
|
||||
|
||||
deferred_obligations.add(new_must_implement, AbilityImplError::IncompleteAbility);
|
||||
|
@ -1759,6 +1763,72 @@ fn check_ability_specialization(
|
|||
}
|
||||
}
|
||||
|
||||
/// A proxy for managing [`Subs`] and the derived module, in the presence of possibly having to
|
||||
/// solve within the derived module's subs.
|
||||
pub struct SubsProxy<'a> {
|
||||
home: ModuleId,
|
||||
subs: &'a mut Subs,
|
||||
derived_module: &'a SharedDerivedModule,
|
||||
}
|
||||
|
||||
impl<'a> SubsProxy<'a> {
|
||||
/// Creates a new subs proxy with the derived module.
|
||||
/// The contract is:
|
||||
/// - `subs` is for the `home` module
|
||||
/// - if `home` is the derived module, then the derived module is not in a stolen state
|
||||
pub fn new(
|
||||
home: ModuleId,
|
||||
subs: &'a mut Subs,
|
||||
derived_module: &'a SharedDerivedModule,
|
||||
) -> Self {
|
||||
Self {
|
||||
home,
|
||||
subs,
|
||||
derived_module,
|
||||
}
|
||||
}
|
||||
|
||||
fn with_subs<T, F>(&mut self, f: F) -> T
|
||||
where
|
||||
F: FnOnce(&mut Subs) -> T,
|
||||
{
|
||||
if self.home != ModuleId::DERIVED {
|
||||
f(self.subs)
|
||||
} else {
|
||||
let mut derived_module = self.derived_module.lock().unwrap();
|
||||
let mut stolen = derived_module.steal();
|
||||
let result = f(&mut stolen.subs);
|
||||
derived_module.return_stolen(stolen);
|
||||
result
|
||||
}
|
||||
}
|
||||
|
||||
fn with_derived<T, F>(&mut self, f: F) -> T
|
||||
where
|
||||
F: FnOnce(&mut DerivedModule) -> T,
|
||||
{
|
||||
let mut derived_module = self.derived_module.lock().unwrap();
|
||||
f(&mut derived_module)
|
||||
}
|
||||
|
||||
fn copy_lambda_set_var_from_derived_to_subs(
|
||||
&mut self,
|
||||
lambda_set_var_in_derived: Variable,
|
||||
target_rank: Rank,
|
||||
) -> Variable {
|
||||
if self.home == ModuleId::DERIVED {
|
||||
lambda_set_var_in_derived
|
||||
} else {
|
||||
let derived_module = self.derived_module.lock().unwrap();
|
||||
derived_module.copy_lambda_set_var_to_subs(
|
||||
lambda_set_var_in_derived,
|
||||
self.subs,
|
||||
target_rank,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(debug_assertions)]
|
||||
fn trace_compaction_step_1(subs: &Subs, c_a: Variable, uls_a: &[Variable]) {
|
||||
let c_a = roc_types::subs::SubsFmtContent(subs.get_content_without_compacting(c_a), subs);
|
||||
|
@ -1881,7 +1951,7 @@ fn unique_unspecialized_lambda(subs: &Subs, c_a: Variable, uls: &[Uls]) -> Optio
|
|||
|
||||
#[must_use]
|
||||
pub fn compact_lambda_sets_of_vars<P: Phase>(
|
||||
subs: &mut Subs,
|
||||
subs: &mut SubsProxy,
|
||||
arena: &Bump,
|
||||
pools: &mut Pools,
|
||||
uls_of_var: UlsOfVar,
|
||||
|
@ -2307,13 +2377,14 @@ fn make_specialization_decision(subs: &Subs, var: Variable) -> SpecializeDecisio
|
|||
}
|
||||
|
||||
fn get_specialization_lambda_set<P: Phase>(
|
||||
subs: &mut Subs,
|
||||
subs: &mut SubsProxy,
|
||||
phase: &P,
|
||||
ability_member: Symbol,
|
||||
lset_region: u8,
|
||||
specialization_key: SpecializationTypeKey,
|
||||
exposed_by_module: &ExposedByModule,
|
||||
derived_module: &SharedDerivedModule,
|
||||
target_rank: Rank,
|
||||
) -> Result<Variable, ()> {
|
||||
match specialization_key {
|
||||
SpecializationTypeKey::Opaque(opaque) => {
|
||||
|
@ -2344,27 +2415,25 @@ fn get_specialization_lambda_set<P: Phase>(
|
|||
}
|
||||
})?;
|
||||
|
||||
let local_lset = phase.copy_lambda_set_var_to_home_subs(
|
||||
external_specialized_lset,
|
||||
opaque_home,
|
||||
subs,
|
||||
);
|
||||
let local_lset = subs.with_subs(|subs| {
|
||||
phase.copy_lambda_set_var_to_home_subs(external_specialized_lset, opaque_home, subs)
|
||||
});
|
||||
|
||||
Ok(local_lset)
|
||||
}
|
||||
|
||||
SpecializationTypeKey::Derived(derive_key) => {
|
||||
let mut derived_module = derived_module.lock().unwrap();
|
||||
|
||||
let specialized_lambda_set = subs.with_derived(|derived_module| {
|
||||
let (_, _, specialization_lambda_sets) =
|
||||
derived_module.get_or_insert(exposed_by_module, derive_key);
|
||||
|
||||
let &specialized_lambda_set = specialization_lambda_sets
|
||||
*specialization_lambda_sets
|
||||
.get(&lset_region)
|
||||
.expect("lambda set region not resolved");
|
||||
.expect("lambda set region not resolved")
|
||||
});
|
||||
|
||||
let local_lset =
|
||||
derived_module.copy_lambda_set_var_to_subs(specialized_lambda_set, subs);
|
||||
subs.copy_lambda_set_var_from_derived_to_subs(specialized_lambda_set, target_rank);
|
||||
|
||||
Ok(local_lset)
|
||||
}
|
||||
|
|
|
@ -403,3 +403,47 @@ fn to_encoder_encode_custom_has_capture() {
|
|||
RocStr
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn encode_derived_string() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
app "test"
|
||||
imports [Encode.{ toEncoder }, Json]
|
||||
provides [main] to "./platform"
|
||||
|
||||
main =
|
||||
result = Str.fromUtf8 (Encode.toBytes "foo" Json.format)
|
||||
when result is
|
||||
Ok s -> s
|
||||
_ -> "<bad>"
|
||||
"#
|
||||
),
|
||||
RocStr::from("\"foo\""),
|
||||
RocStr
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn encode_derived_record() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
app "test"
|
||||
imports [Encode.{ toEncoder }, Json]
|
||||
provides [main] to "./platform"
|
||||
|
||||
main =
|
||||
result = Str.fromUtf8 (Encode.toBytes {a: "foo"} Json.format)
|
||||
when result is
|
||||
Ok s -> s
|
||||
_ -> "<bad>"
|
||||
"#
|
||||
),
|
||||
RocStr::from("foo"),
|
||||
RocStr
|
||||
)
|
||||
}
|
||||
|
|
106
crates/compiler/test_mono/generated/encode_derived_string.txt
Normal file
106
crates/compiler/test_mono/generated/encode_derived_string.txt
Normal file
|
@ -0,0 +1,106 @@
|
|||
procedure #Derived.0 (#Derived.1):
|
||||
let #Derived.6 : {Str} = Struct {#Derived.1};
|
||||
let #Derived.5 : {Str} = CallByName Encode.22 #Derived.6;
|
||||
ret #Derived.5;
|
||||
|
||||
procedure #Derived.2 (#Derived.3, #Derived.4, #Attr.12):
|
||||
let #Derived.1 : Str = StructAtIndex 0 #Attr.12;
|
||||
inc #Derived.1;
|
||||
dec #Attr.12;
|
||||
let #Derived.9 : {Str} = CallByName Json.17 #Derived.1;
|
||||
let #Derived.8 : List U8 = CallByName Encode.23 #Derived.3 #Derived.9 #Derived.4;
|
||||
ret #Derived.8;
|
||||
|
||||
procedure Encode.22 (Encode.93):
|
||||
ret Encode.93;
|
||||
|
||||
procedure Encode.22 (Encode.93):
|
||||
ret Encode.93;
|
||||
|
||||
procedure Encode.23 (Encode.94, Encode.102, Encode.96):
|
||||
let Encode.107 : List U8 = CallByName #Derived.2 Encode.94 Encode.96 Encode.102;
|
||||
ret Encode.107;
|
||||
|
||||
procedure Encode.23 (Encode.94, Encode.102, Encode.96):
|
||||
let Encode.114 : List U8 = CallByName Json.65 Encode.94 Encode.96 Encode.102;
|
||||
ret Encode.114;
|
||||
|
||||
procedure Encode.25 (Encode.100, Encode.101):
|
||||
let Encode.104 : List U8 = Array [];
|
||||
let Encode.105 : {Str} = CallByName #Derived.0 Encode.100;
|
||||
let Encode.103 : List U8 = CallByName Encode.23 Encode.104 Encode.105 Encode.101;
|
||||
ret Encode.103;
|
||||
|
||||
procedure Json.1 ():
|
||||
let Json.102 : {} = Struct {};
|
||||
ret Json.102;
|
||||
|
||||
procedure Json.17 (Json.64):
|
||||
let Json.104 : {Str} = Struct {Json.64};
|
||||
let Json.103 : {Str} = CallByName Encode.22 Json.104;
|
||||
ret Json.103;
|
||||
|
||||
procedure Json.65 (Json.66, Json.105, #Attr.12):
|
||||
let Json.64 : Str = StructAtIndex 0 #Attr.12;
|
||||
inc Json.64;
|
||||
dec #Attr.12;
|
||||
let Json.114 : I32 = 34i64;
|
||||
let Json.113 : U8 = CallByName Num.122 Json.114;
|
||||
let Json.111 : List U8 = CallByName List.4 Json.66 Json.113;
|
||||
let Json.112 : List U8 = CallByName Str.12 Json.64;
|
||||
let Json.108 : List U8 = CallByName List.8 Json.111 Json.112;
|
||||
let Json.110 : I32 = 34i64;
|
||||
let Json.109 : U8 = CallByName Num.122 Json.110;
|
||||
let Json.107 : List U8 = CallByName List.4 Json.108 Json.109;
|
||||
ret Json.107;
|
||||
|
||||
procedure List.4 (#Attr.2, #Attr.3):
|
||||
let List.141 : List U8 = lowlevel ListAppend #Attr.2 #Attr.3;
|
||||
ret List.141;
|
||||
|
||||
procedure List.8 (#Attr.2, #Attr.3):
|
||||
let List.142 : List U8 = lowlevel ListConcat #Attr.2 #Attr.3;
|
||||
ret List.142;
|
||||
|
||||
procedure Num.122 (#Attr.2):
|
||||
let Num.272 : U8 = lowlevel NumIntCast #Attr.2;
|
||||
ret Num.272;
|
||||
|
||||
procedure Str.12 (#Attr.2):
|
||||
let Str.73 : List U8 = lowlevel StrToUtf8 #Attr.2;
|
||||
ret Str.73;
|
||||
|
||||
procedure Str.9 (#Attr.2):
|
||||
let #Attr.3 : {U64, Str, Int1, U8} = lowlevel StrFromUtf8 #Attr.2;
|
||||
let Str.69 : Int1 = StructAtIndex 2 #Attr.3;
|
||||
if Str.69 then
|
||||
let Str.71 : Str = StructAtIndex 1 #Attr.3;
|
||||
inc Str.71;
|
||||
dec #Attr.3;
|
||||
let Str.70 : [C {U64, U8}, C Str] = Ok Str.71;
|
||||
ret Str.70;
|
||||
else
|
||||
let Str.67 : U8 = StructAtIndex 3 #Attr.3;
|
||||
let Str.68 : U64 = StructAtIndex 0 #Attr.3;
|
||||
dec #Attr.3;
|
||||
let Str.66 : {U64, U8} = Struct {Str.68, Str.67};
|
||||
let Str.65 : [C {U64, U8}, C Str] = Err Str.66;
|
||||
ret Str.65;
|
||||
|
||||
procedure Test.0 ():
|
||||
let Test.9 : Str = "abc";
|
||||
let Test.10 : {} = CallByName Json.1;
|
||||
let Test.8 : List U8 = CallByName Encode.25 Test.9 Test.10;
|
||||
let Test.1 : [C {U64, U8}, C Str] = CallByName Str.9 Test.8;
|
||||
let Test.5 : U8 = 1i64;
|
||||
let Test.6 : U8 = GetTagId Test.1;
|
||||
let Test.7 : Int1 = lowlevel Eq Test.5 Test.6;
|
||||
if Test.7 then
|
||||
let Test.2 : Str = UnionAtIndex (Id 1) (Index 0) Test.1;
|
||||
inc Test.2;
|
||||
dec Test.1;
|
||||
ret Test.2;
|
||||
else
|
||||
dec Test.1;
|
||||
let Test.4 : Str = "<bad>";
|
||||
ret Test.4;
|
|
@ -1467,6 +1467,24 @@ fn encode_custom_type() {
|
|||
}
|
||||
|
||||
#[mono_test]
|
||||
fn encode_derived_string() {
|
||||
indoc!(
|
||||
r#"
|
||||
app "test"
|
||||
imports [Encode.{ toEncoder }, Json]
|
||||
provides [main] to "./platform"
|
||||
|
||||
main =
|
||||
result = Str.fromUtf8 (Encode.toBytes "abc" Json.format)
|
||||
when result is
|
||||
Ok s -> s
|
||||
_ -> "<bad>"
|
||||
"#
|
||||
)
|
||||
}
|
||||
|
||||
#[mono_test]
|
||||
#[ignore = "TODO"]
|
||||
fn encode_derived_record() {
|
||||
indoc!(
|
||||
r#"
|
||||
|
@ -1475,7 +1493,7 @@ fn encode_derived_record() {
|
|||
provides [main] to "./platform"
|
||||
|
||||
main =
|
||||
result = Str.fromUtf8 (Encode.toBytes {a: "fieldA", b: "fieldB"} Json.format)
|
||||
result = Str.fromUtf8 (Encode.toBytes {a: "a"} Json.format)
|
||||
when result is
|
||||
Ok s -> s
|
||||
_ -> "<bad>"
|
||||
|
|
|
@ -873,7 +873,13 @@ fn subs_fmt_flat_type(this: &FlatType, subs: &Subs, f: &mut fmt::Formatter) -> f
|
|||
FlatType::Apply(name, arguments) => {
|
||||
let slice = subs.get_subs_slice(*arguments);
|
||||
|
||||
write!(f, "Apply({:?}, {:?})", name, slice)
|
||||
write!(f, "Apply({:?} ", name)?;
|
||||
for var in slice {
|
||||
let content = subs.get_content_without_compacting(*var);
|
||||
write!(f, ", <{:?}>{:?}", *var, SubsFmtContent(content, subs))?;
|
||||
}
|
||||
write!(f, ")")
|
||||
// write!(f, "Apply({:?}, {:?})", name, slice)
|
||||
}
|
||||
FlatType::Func(arguments, lambda_set, result) => {
|
||||
let slice = subs.get_subs_slice(*arguments);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue