feat: Num.toStr

* add type for Num.toStr
  * create new lowlevel
  * delete types and Symbol for fromInt and fromFloat
  * leave LowLevel::{StrFromFloat,StrFromInt}
  * match on LowLevel::NumToStr and figure out the layout to decide
    which build function to delegate to
This commit is contained in:
rvcas 2021-11-30 14:52:06 -05:00
parent d67cc883ca
commit f995a07029
8 changed files with 65 additions and 75 deletions

View file

@ -385,6 +385,13 @@ pub fn types() -> MutMap<Symbol, (SolvedType, Region)> {
// maxI128 : I128
add_type!(Symbol::NUM_MAX_I128, i128_type());
// toStr : Num a -> Str
add_top_level_function_type!(
Symbol::NUM_TO_STR,
vec![num_type(flex(TVAR1))],
Box::new(str_type())
);
// Float module
// div : Float a, Float a -> Float a
@ -618,13 +625,6 @@ pub fn types() -> MutMap<Symbol, (SolvedType, Region)> {
Box::new(nat_type())
);
// fromInt : Int a -> Str
add_top_level_function_type!(
Symbol::STR_FROM_INT,
vec![int_type(flex(TVAR1))],
Box::new(str_type())
);
// repeat : Str, Nat -> Str
add_top_level_function_type!(
Symbol::STR_REPEAT,
@ -702,13 +702,6 @@ pub fn types() -> MutMap<Symbol, (SolvedType, Region)> {
Box::new(list_type(u8_type()))
);
// fromFloat : Float a -> Str
add_top_level_function_type!(
Symbol::STR_FROM_FLOAT,
vec![float_type(flex(TVAR1))],
Box::new(str_type())
);
// List module
// get : List elem, Nat -> Result elem [ OutOfBounds ]*

View file

@ -61,11 +61,9 @@ pub fn builtin_defs_map(symbol: Symbol, var_store: &mut VarStore) -> Option<Def>
STR_STARTS_WITH_CODE_PT => str_starts_with_code_point,
STR_ENDS_WITH => str_ends_with,
STR_COUNT_GRAPHEMES => str_count_graphemes,
STR_FROM_INT => str_from_int,
STR_FROM_UTF8 => str_from_utf8,
STR_FROM_UTF8_RANGE => str_from_utf8_range,
STR_TO_UTF8 => str_to_utf8,
STR_FROM_FLOAT=> str_from_float,
STR_REPEAT => str_repeat,
STR_TRIM => str_trim,
STR_TRIM_LEFT => str_trim_left,
@ -192,6 +190,7 @@ pub fn builtin_defs_map(symbol: Symbol, var_store: &mut VarStore) -> Option<Def>
NUM_SHIFT_RIGHT_ZERO_FILL => num_shift_right_zf_by,
NUM_INT_CAST=> num_int_cast,
NUM_MAX_I128=> num_max_i128,
NUM_TO_STR => num_to_str,
RESULT_MAP => result_map,
RESULT_MAP_ERR => result_map_err,
RESULT_AFTER => result_after,
@ -369,6 +368,26 @@ fn num_min_int(symbol: Symbol, var_store: &mut VarStore) -> Def {
}
}
// Num.toStr : Num a -> Str
fn num_to_str(symbol: Symbol, var_store: &mut VarStore) -> Def {
let num_var = var_store.fresh();
let str_var = var_store.fresh();
let body = RunLowLevel {
op: LowLevel::NumToStr,
args: vec![(num_var, Var(Symbol::ARG_1))],
ret_var: str_var,
};
defn(
symbol,
vec![(num_var, Symbol::ARG_1)],
var_store,
body,
str_var,
)
}
/// Bool.isEq : val, val -> Bool
fn bool_eq(symbol: Symbol, var_store: &mut VarStore) -> Def {
let arg_var = var_store.fresh();
@ -1436,26 +1455,6 @@ fn str_count_graphemes(symbol: Symbol, var_store: &mut VarStore) -> Def {
)
}
/// Str.fromInt : Int * -> Str
fn str_from_int(symbol: Symbol, var_store: &mut VarStore) -> Def {
let int_var = var_store.fresh();
let str_var = var_store.fresh();
let body = RunLowLevel {
op: LowLevel::StrFromInt,
args: vec![(int_var, Var(Symbol::ARG_1))],
ret_var: str_var,
};
defn(
symbol,
vec![(int_var, Symbol::ARG_1)],
var_store,
body,
str_var,
)
}
/// Str.fromUtf8 : List U8 -> Result Str [ BadUtf8 { byteIndex : Nat, problem : Utf8Problem } } ]*
fn str_from_utf8(symbol: Symbol, var_store: &mut VarStore) -> Def {
let bytes_var = var_store.fresh();
@ -1738,26 +1737,6 @@ fn str_to_utf8(symbol: Symbol, var_store: &mut VarStore) -> Def {
lowlevel_1(symbol, LowLevel::StrToUtf8, var_store)
}
/// Str.fromFloat : Float * -> Str
fn str_from_float(symbol: Symbol, var_store: &mut VarStore) -> Def {
let float_var = var_store.fresh();
let str_var = var_store.fresh();
let body = RunLowLevel {
op: LowLevel::StrFromFloat,
args: vec![(float_var, Var(Symbol::ARG_1))],
ret_var: str_var,
};
defn(
symbol,
vec![(float_var, Symbol::ARG_1)],
var_store,
body,
str_var,
)
}
/// List.concat : List elem, List elem -> List elem
fn list_concat(symbol: Symbol, var_store: &mut VarStore) -> Def {
let list_var = var_store.fresh();

View file

@ -5522,6 +5522,24 @@ fn run_low_level<'a, 'ctx, 'env>(
list_join(env, parent, list, outer_list_layout)
}
NumToStr => {
// Num.toStr : Num a -> Str
debug_assert_eq!(args.len(), 1);
let (num, num_layout) = load_symbol_and_layout(scope, &args[0]);
match num_layout {
Layout::Builtin(Builtin::Int(int_width)) => {
let int = num.into_int_value();
str_from_int(env, int, *int_width)
}
Layout::Builtin(Builtin::Float(_float_width)) => {
str_from_float(env, scope, args[0])
}
_ => unreachable!(),
}
}
NumAbs | NumNeg | NumRound | NumSqrtUnchecked | NumLogUnchecked | NumSin | NumCos
| NumCeiling | NumFloor | NumToFloat | NumIsFinite | NumAtan | NumAcos | NumAsin => {
debug_assert_eq!(args.len(), 1);

View file

@ -406,7 +406,7 @@ pub fn str_from_utf8<'a, 'ctx, 'env>(
decode_from_utf8_result(env, result_ptr).into()
}
/// Str.fromInt : Int -> Str
/// Str.fromFloat : Int -> Str
pub fn str_from_float<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
scope: &Scope<'a, 'ctx>,

View file

@ -87,6 +87,7 @@ pub fn decode_low_level<'a>(
F32 => code_builder.f32_add(),
F64 => code_builder.f64_add(),
},
NumToStr => return NotImplemented,
NumAddChecked => return NotImplemented,
NumSub => match ret_layout.arg_types(CallConv::Zig)[0] {
I32 => code_builder.i32_sub(),

View file

@ -108,6 +108,7 @@ pub enum LowLevel {
NumShiftRightBy,
NumShiftRightZfBy,
NumIntCast,
NumToStr,
Eq,
NotEq,
And,
@ -186,12 +187,10 @@ impl LowLevel {
Symbol::STR_ENDS_WITH => Some(StrEndsWith),
Symbol::STR_SPLIT => Some(StrSplit),
Symbol::STR_COUNT_GRAPHEMES => Some(StrCountGraphemes),
Symbol::STR_FROM_INT => Some(StrFromInt),
Symbol::STR_FROM_UTF8 => None,
Symbol::STR_FROM_UTF8_RANGE => None,
Symbol::STR_TO_UTF8 => Some(StrToUtf8),
Symbol::STR_REPEAT => Some(StrRepeat),
Symbol::STR_FROM_FLOAT => Some(StrFromFloat),
Symbol::STR_TRIM => Some(StrTrim),
Symbol::STR_TRIM_LEFT => Some(StrTrimLeft),
Symbol::STR_TRIM_RIGHT => Some(StrTrimRight),
@ -268,6 +267,7 @@ impl LowLevel {
Symbol::NUM_CEILING => Some(NumCeiling),
Symbol::NUM_POW_INT => Some(NumPowInt),
Symbol::NUM_FLOOR => Some(NumFloor),
Symbol::NUM_TO_STR => Some(NumToStr),
// => Some(NumIsFinite),
Symbol::NUM_ATAN => Some(NumAtan),
Symbol::NUM_ACOS => Some(NumAcos),

View file

@ -992,6 +992,7 @@ define_builtins! {
104 NUM_BYTES_TO_U32: "bytesToU32"
105 NUM_CAST_TO_NAT: "#castToNat"
106 NUM_DIV_CEIL: "divCeil"
107 NUM_TO_STR: "toStr"
}
2 BOOL: "Bool" => {
0 BOOL_BOOL: "Bool" imported // the Bool.Bool type alias
@ -1017,19 +1018,17 @@ define_builtins! {
7 STR_COUNT_GRAPHEMES: "countGraphemes"
8 STR_STARTS_WITH: "startsWith"
9 STR_ENDS_WITH: "endsWith"
10 STR_FROM_INT: "fromInt"
11 STR_FROM_FLOAT: "fromFloat"
12 STR_FROM_UTF8: "fromUtf8"
13 STR_UT8_PROBLEM: "Utf8Problem" // the Utf8Problem type alias
14 STR_UT8_BYTE_PROBLEM: "Utf8ByteProblem" // the Utf8ByteProblem type alias
15 STR_TO_UTF8: "toUtf8"
16 STR_STARTS_WITH_CODE_PT: "startsWithCodePt"
17 STR_ALIAS_ANALYSIS_STATIC: "#aliasAnalysisStatic" // string with the static lifetime
18 STR_FROM_UTF8_RANGE: "fromUtf8Range"
19 STR_REPEAT: "repeat"
20 STR_TRIM: "trim"
21 STR_TRIM_LEFT: "trimLeft"
22 STR_TRIM_RIGHT: "trimRight"
10 STR_FROM_UTF8: "fromUtf8"
11 STR_UT8_PROBLEM: "Utf8Problem" // the Utf8Problem type alias
12 STR_UT8_BYTE_PROBLEM: "Utf8ByteProblem" // the Utf8ByteProblem type alias
13 STR_TO_UTF8: "toUtf8"
14 STR_STARTS_WITH_CODE_PT: "startsWithCodePt"
15 STR_ALIAS_ANALYSIS_STATIC: "#aliasAnalysisStatic" // string with the static lifetime
16 STR_FROM_UTF8_RANGE: "fromUtf8Range"
17 STR_REPEAT: "repeat"
18 STR_TRIM: "trim"
19 STR_TRIM_LEFT: "trimLeft"
20 STR_TRIM_RIGHT: "trimRight"
}
4 LIST: "List" => {
0 LIST_LIST: "List" imported // the List.List type alias

View file

@ -980,9 +980,9 @@ pub fn lowlevel_borrow_signature(arena: &Bump, op: LowLevel) -> &[bool] {
| NumPowInt | NumBitwiseAnd | NumBitwiseXor | NumBitwiseOr | NumShiftLeftBy
| NumShiftRightBy | NumShiftRightZfBy => arena.alloc_slice_copy(&[irrelevant, irrelevant]),
NumAbs | NumNeg | NumSin | NumCos | NumSqrtUnchecked | NumLogUnchecked | NumRound
| NumCeiling | NumFloor | NumToFloat | Not | NumIsFinite | NumAtan | NumAcos | NumAsin
| NumIntCast => arena.alloc_slice_copy(&[irrelevant]),
NumToStr | NumAbs | NumNeg | NumSin | NumCos | NumSqrtUnchecked | NumLogUnchecked
| NumRound | NumCeiling | NumFloor | NumToFloat | Not | NumIsFinite | NumAtan | NumAcos
| NumAsin | NumIntCast => arena.alloc_slice_copy(&[irrelevant]),
NumBytesToU16 => arena.alloc_slice_copy(&[borrowed, irrelevant]),
NumBytesToU32 => arena.alloc_slice_copy(&[borrowed, irrelevant]),
StrStartsWith | StrEndsWith => arena.alloc_slice_copy(&[owned, borrowed]),