1
1
mirror of https://github.com/tweag/nickel.git synced 2024-09-11 11:47:03 +03:00
This commit is contained in:
Yann Hamdaoui 2024-08-05 15:30:25 +02:00
parent b3c8e30b68
commit d9dcdb9b65
No known key found for this signature in database
GPG Key ID: 96305DE11214ABE6
6 changed files with 76 additions and 17 deletions

View File

@ -2981,6 +2981,39 @@ impl<R: ImportResolver, C: Cache> VirtualMachine<R, C> {
pos_op_inh,
)))
}
BinaryOp::ContractBuiltin(builtin) => {
let t1 = t1.into_owned();
let Term::Lbl(label) = t1 else {
return mk_type_error!("Label", 1, t1.into(), pos1);
};
match (&*t2, builtin) {
(Term::Num(_), BuiltinContract::Number)
| (Term::Str(_), BuiltinContract::String)
| (Term::Bool(_), BuiltinContract::Bool)
| (_, BuiltinContract::Dyn) => {
let wrapped = Term::EnumVariant {
tag: "Ok".into(),
arg: RichTerm {
term: t2,
pos: pos2,
},
attrs: EnumVariantAttrs::new().closurized(),
};
Ok(Closure {
body: RichTerm::new(wrapped, pos2),
env: env2,
})
}
_ => Err(EvalError::BlameError {
evaluated_arg: label.get_evaluated_arg(&self.cache),
label,
call_stack: std::mem::take(&mut self.call_stack),
}),
}
}
}
}

View File

@ -1307,6 +1307,12 @@ BOpPre: BinaryOp = {
"contract/check" => BinaryOp::ContractCheck,
"contract/array_lazy_app" => BinaryOp::ContractArrayLazyApp,
"contract/record_lazy_app" => BinaryOp::ContractRecordLazyApp,
"contract/builtin/dyn" => BinaryOp::ContractBuiltin(BuiltinContract::Dyn),
"contract/builtin/string" =>
BinaryOp::ContractBuiltin(BuiltinContract::String),
"contract/builtin/number" =>
BinaryOp::ContractBuiltin(BuiltinContract::Number),
"contract/builtin/bool" => BinaryOp::ContractBuiltin(BuiltinContract::Bool),
"unseal" => BinaryOp::Unseal,
"seal" => BinaryOp::Seal,
"label/go_field" => BinaryOp::LabelGoField,
@ -1529,6 +1535,10 @@ extern {
"contract/array_lazy_app" => Token::Normal(NormalToken::ContractArrayLazyApp),
"contract/record_lazy_app" => Token::Normal(NormalToken::ContractRecordLazyApp),
"contract/custom" => Token::Normal(NormalToken::ContractCustom),
"contract/builtin/dyn" => Token::Normal(NormalToken::ContractBuiltinDyn),
"contract/builtin/string" => Token::Normal(NormalToken::ContractBuiltinString),
"contract/builtin/bool" => Token::Normal(NormalToken::ContractBuiltinBool),
"contract/builtin/number" => Token::Normal(NormalToken::ContractBuiltinNumber),
"op force" => Token::Normal(NormalToken::OpForce),
"blame" => Token::Normal(NormalToken::Blame),
"label/flip_polarity" => Token::Normal(NormalToken::LabelFlipPol),

View File

@ -225,6 +225,15 @@ pub enum NormalToken<'input> {
#[token("%label/lookup_type_variable%")]
LabelLookupTypeVar,
#[token("%contract/builtin/dyn%")]
ContractBuiltinDyn,
#[token("%contract/builtin/number%")]
ContractBuiltinNumber,
#[token("%contract/builtin/string%")]
ContractBuiltinString,
#[token("%contract/builtin/bool%")]
ContractBuiltinBool,
#[token("%seal%")]
Seal,
#[token("%unseal%")]

View File

@ -1682,6 +1682,14 @@ pub enum RecordOpKind {
ConsiderAllFields,
}
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum BuiltinContract {
Bool,
Number,
Dyn,
String,
}
/// Primitive binary operators
#[derive(Clone, Debug, PartialEq)]
pub enum BinaryOp {
@ -1755,6 +1763,8 @@ pub enum BinaryOp {
/// [Self::ContractCheck] preserves the immediate/delayed part of the called contract.
ContractCheck,
ContractBuiltin(BuiltinContract),
/// Take a record of type `{message | String | optional, notes | String | optional}`.
LabelWithErrorData,
@ -1909,6 +1919,10 @@ impl fmt::Display for BinaryOp {
GreaterOrEq => write!(f, "(>=)"),
ContractApply => write!(f, "contract/apply"),
ContractCheck => write!(f, "contract/check"),
ContractBuiltin(BuiltinContract::Dyn) => write!(f, "contract/builtin/dyn"),
ContractBuiltin(BuiltinContract::Number) => write!(f, "contract/builtin/number"),
ContractBuiltin(BuiltinContract::Bool) => write!(f, "contract/builtin/bool"),
ContractBuiltin(BuiltinContract::String) => write!(f, "contract/builtin/string"),
LabelWithErrorData => write!(f, "label/with_error_data"),
Unseal => write!(f, "unseal"),
LabelGoField => write!(f, "label/go_field"),

View File

@ -544,6 +544,12 @@ pub fn get_bop_type(
(dict.clone(), dict.clone(), dict)
}
// Dyn -> Dyn -> Dyn
BinaryOp::ContractBuiltin(_) => (
mk_uniftype::dynamic(),
mk_uniftype::dynamic(),
mk_uniftype::dynamic(),
),
})
}

View File

@ -9,28 +9,16 @@
# |]` as well.
# Contract for the `Dyn` type. It's just an always accepting contract.
"$dyn" = fun _label value => 'Ok value,
"$dyn" = fun label value => %contract/builtin/dyn% label value,
# Contract for the `Number` type.
"$num" = fun _label value =>
if %typeof% value == 'Number then
'Ok value
else
'Error {},
"$num" = fun label value => %contract/builtin/number% label value,
# Contract for the `Bool` type.
"$bool" = fun _label value =>
if %typeof% value == 'Bool then
'Ok value
else
'Error {},
"$bool" = fun label value => %contract/builtin/bool% label value,
# Contract for the `String` type.
"$string" = fun _label value =>
if %typeof% value == 'String then
'Ok value
else
'Error {},
"$string" = fun label value => %contract/builtin/string% label value,
# Contract for `ForeignId` values.
"$foreign_id" = fun _label value =>
@ -379,7 +367,6 @@
# just add the extra fields back to the returned value. See
# `$record_type/delayed`.
"$dyn_tail" = fun extra_fields label value => 'Ok (%record/disjoint_merge% value extra_fields),
# Tail wrapper of a helper for an empty tail. At this point, we've already
# checked (in the main contract implementation for record types) that there
# are no extra fields, so we can just ignore them and return the value as is.