mirror of
https://github.com/tweag/nickel.git
synced 2024-09-20 08:05:15 +03:00
Merge pull request #323 from tweag/feature/stdlib-num-recs-extension
Add the nums stdlib
This commit is contained in:
commit
3c52c3ac3f
@ -455,6 +455,7 @@ BOpPre: BinaryOp = {
|
||||
"hash" => BinaryOp::Hash(),
|
||||
"serialize" => BinaryOp::Serialize(),
|
||||
"deserialize" => BinaryOp::Deserialize(),
|
||||
"pow" => BinaryOp::Pow(),
|
||||
}
|
||||
|
||||
Types: Types = {
|
||||
@ -626,6 +627,7 @@ extern {
|
||||
"tail" => Token::Normal(NormalToken::Tail),
|
||||
"length" => Token::Normal(NormalToken::Length),
|
||||
"fieldsOf" => Token::Normal(NormalToken::FieldsOf),
|
||||
"pow" => Token::Normal(NormalToken::Pow),
|
||||
|
||||
"hasField" => Token::Normal(NormalToken::HasField),
|
||||
"map" => Token::Normal(NormalToken::Map),
|
||||
|
@ -876,6 +876,36 @@ fn process_binary_operation(
|
||||
))
|
||||
}
|
||||
}
|
||||
BinaryOp::Pow() => {
|
||||
if let Term::Num(n1) = *t1 {
|
||||
if let Term::Num(n2) = *t2 {
|
||||
Ok(Closure::atomic_closure(RichTerm::new(
|
||||
Term::Num(n1.powf(n2)),
|
||||
pos_op_inh,
|
||||
)))
|
||||
} else {
|
||||
Err(EvalError::TypeError(
|
||||
String::from("Num"),
|
||||
String::from("pow, 2nd argument"),
|
||||
snd_pos,
|
||||
RichTerm {
|
||||
term: t2,
|
||||
pos: pos2,
|
||||
},
|
||||
))
|
||||
}
|
||||
} else {
|
||||
Err(EvalError::TypeError(
|
||||
String::from("Num"),
|
||||
String::from("pow, 1st argument"),
|
||||
fst_pos,
|
||||
RichTerm {
|
||||
term: t1,
|
||||
pos: pos1,
|
||||
},
|
||||
))
|
||||
}
|
||||
}
|
||||
BinaryOp::PlusStr() => {
|
||||
if let Term::Str(s1) = *t1 {
|
||||
if let Term::Str(s2) = *t2 {
|
||||
|
@ -191,6 +191,8 @@ pub enum NormalToken<'input> {
|
||||
Length,
|
||||
#[token("%fieldsOf%")]
|
||||
FieldsOf,
|
||||
#[token("%pow%")]
|
||||
Pow,
|
||||
|
||||
#[token("%hasField%")]
|
||||
HasField,
|
||||
|
@ -13,10 +13,11 @@ pub const CONTRACTS: (&str, &str) = (
|
||||
);
|
||||
pub const LISTS: (&str, &str) = ("<stdlib/lists>", include_str!("../stdlib/lists.ncl"));
|
||||
pub const RECORDS: (&str, &str) = ("<stdlib/records>", include_str!("../stdlib/records.ncl"));
|
||||
pub const NUMS: (&str, &str) = ("<stdlib/nums>", include_str!("../stdlib/nums.ncl"));
|
||||
|
||||
/// Return the list `(name, source_code)` of all the stdlib modules.
|
||||
pub fn modules() -> Vec<(&'static str, &'static str)> {
|
||||
vec![BUILTINS, CONTRACTS, LISTS, RECORDS]
|
||||
vec![BUILTINS, CONTRACTS, LISTS, RECORDS, NUMS]
|
||||
}
|
||||
|
||||
/// Accessors to the builtin contracts.
|
||||
|
@ -583,6 +583,8 @@ pub enum BinaryOp {
|
||||
Div(),
|
||||
/// Modulo of numerals.
|
||||
Modulo(),
|
||||
/// Raise a number to a power.
|
||||
Pow(),
|
||||
/// Concatenation of strings.
|
||||
PlusStr(),
|
||||
/// Polymorphic equality.
|
||||
|
@ -1707,6 +1707,11 @@ pub fn get_bop_type(state: &mut State, op: &BinaryOp) -> Result<TypeWrapper, Typ
|
||||
mk_typewrapper::str(),
|
||||
mk_typewrapper::dynamic()
|
||||
),
|
||||
BinaryOp::Pow() => mk_tyw_arrow!(
|
||||
mk_typewrapper::num(),
|
||||
mk_typewrapper::num(),
|
||||
mk_typewrapper::num()
|
||||
),
|
||||
})
|
||||
}
|
||||
|
||||
|
64
stdlib/nums.ncl
Normal file
64
stdlib/nums.ncl
Normal file
@ -0,0 +1,64 @@
|
||||
{
|
||||
nums = {
|
||||
Int = fun label value =>
|
||||
if %isNum% value then
|
||||
if value % 1 == 0 then
|
||||
value
|
||||
else
|
||||
%blame% (%tag% "not an integer" label)
|
||||
else
|
||||
%blame% (%tag% "not a number" label);
|
||||
|
||||
Nat = fun label value =>
|
||||
if %isNum% value then
|
||||
if value % 1 == 0 && value >= 0 then
|
||||
value
|
||||
else
|
||||
%blame% (%tag% "not a natural" label)
|
||||
else
|
||||
%blame% (%tag% "not a number" label);
|
||||
|
||||
PosNat = fun label value =>
|
||||
if %isNum% value then
|
||||
if value % 1 == 0 && value > 0 then
|
||||
value
|
||||
else
|
||||
%blame% (%tag% "not positive integer" label)
|
||||
else
|
||||
%blame% (%tag% "not a number" label);
|
||||
|
||||
NonZero = fun label value =>
|
||||
if %isNum% value then
|
||||
if value != 0 then
|
||||
value
|
||||
else
|
||||
%blame% (%tag% "non-zero" label)
|
||||
else
|
||||
%blame% (%tag% "not a number" label);
|
||||
|
||||
isInt : Num -> Bool = fun x =>
|
||||
%isNum% x && (x % 1 == 0);
|
||||
|
||||
min : Num -> Num -> Num = fun x y =>
|
||||
if x <= y then x else y;
|
||||
|
||||
max : Num -> Num -> Num = fun x y =>
|
||||
if x >= y then x else y;
|
||||
|
||||
floor : Num -> Num = fun x =>
|
||||
if x >= 0 then x - (x % 1)
|
||||
else x - 1 - (x % 1);
|
||||
|
||||
abs : Num -> Num = fun x =>
|
||||
if x < 0 then -x else x;
|
||||
|
||||
fract : Num -> Num = fun x =>
|
||||
x % 1;
|
||||
|
||||
trunc : Num -> Num = fun x =>
|
||||
x - (x % 1);
|
||||
|
||||
pow : Num -> Num -> Num = fun x n =>
|
||||
%pow% x n;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user