1
1
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:
Eelco Dolstra 2021-03-31 16:52:31 +02:00 committed by GitHub
commit 3c52c3ac3f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 107 additions and 1 deletions

View File

@ -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),

View File

@ -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 {

View File

@ -191,6 +191,8 @@ pub enum NormalToken<'input> {
Length,
#[token("%fieldsOf%")]
FieldsOf,
#[token("%pow%")]
Pow,
#[token("%hasField%")]
HasField,

View File

@ -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.

View File

@ -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.

View File

@ -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
View 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;
}
}