Repository: tweag/nickel
Pull request #1992 (2024-07-08 23:55:11)

clean up outdated primitive operator names
PR #1937 recently renamed many primitive operators. It missed some instances of the previous names, though. In particular:

- error messages
- comments
- documentation
- an unused function "apply_contract" in core/src/term/mod.rs

While most of these names were only made obsolete in #1937, some of them have been incorrect for longer, eg "%array_access%" in core/src/term/pattern/compile.rs and "recordMap" in core/src/term/mod.rs.

I caught as many as I could find. However it's hard to be sure I got all of them, given that some of the previous names are very general terms like "value", "fields", "length", and "map".

The full list of renames I identifiend are as follows, formatted as `<old name> <new name>`.

First, the easy cases:

    chng_pol label/flip_polarity
    record_map record/map
    str_trim string/trim
    str_chars string/chars
    str_uppercase string/uppercase
    str_lowercase string/lowercase
    str_length string/length
    str_from to_string
    num_from number/from_string
    enum_from enum/from_string
    str_is_match string/is_match
    str_find string/find
    str_find_all string/find_all
    record_empty_with_tail record/empty_with_tail
    label_push_diag label/push_diag
    enum_unwrap_variant enum/unwrap_variant
    enum_is_variant enum/is_variant
    enum_get_tag enum/get_tag
    apply_contract contract/apply
    array_lazy_app_ctr contract/array_lazy_app
    record_lazy_app_ctr contract/record_lazy_app
    elem_at array/at
    str_split string/split
    str_contains string/contains
    record_insert record/insert
    record_insert_with_opts record/insert_with_opts
    record_remove record/remove
    record_remove_with_opts record/remove_with_opts
    label_with_message label/with_message
    label_with_notes label/with_notes
    label_append_note label/append_note
    str_replace string/replace
    str_replace_regex string/replace_regex
    str_substr string/substr
    record_seal_tail record/seal_tail
    record_unseal_tail record/unseal_tail
    array_slice array/slice

Then the harder cases:

    polarity label/polarity
    go_dom label/go_dom
    go_codom label/go_codom
    go_array label/go_array
    go_dict label/go_dict
    embed enum/embed
    map array/map
    generate array/generate
    length array/length
    fields record/fields
    fields_with_opts record/fields_with_opts
    values record/values
    go_field label/go_field
    has_field record/has_field
    has_field_with_opts record/has_field_with_opts
    field_is_defined record/field_is_defined
    field_is_defined_with_opts record/field_is_defined_with_opts
    lookup_type_variable label/lookup_type_variable
    insert_type_variable label/insert_type_variable

Finally, two cases that I didn't understand and seem to be unused:

    rec_force_op op rec_force
    rec_default_op op rec_default

yannham: > rec_force_op op rec_force
> rec_default_op op rec_default

You can safely ignore those. They've been disabled several versions ago (or even before 1.0, I believe). The code is kept around in the vague hope of resuscitating them once we find a reasonable design, but for now, it's just dead code.
jeremyschlatter: @yannham Thanks for the review! I addressed all of your comments.

Patch:
diff --git a/core/src/eval/operation.rs b/core/src/eval/operation.rs
index f611b045..3f79adf9 100644
--- a/core/src/eval/operation.rs
+++ b/core/src/eval/operation.rs
@@ -312,7 +312,7 @@ impl<R: ImportResolver, C: Cache> VirtualMachine<R, C> {
                         pos: pos_op_inh,
                     }))
                 } else {
-                    Err(mk_type_error!("embed", "Enum"))
+                    Err(mk_type_error!("enum/embed", "Enum"))
                 }
             }
             UnaryOp::TagsOnlyMatch { has_default } => {
@@ -377,7 +377,7 @@ impl<R: ImportResolver, C: Cache> VirtualMachine<R, C> {
                         pos_op_inh,
                     )))
                 }
-                _ => Err(mk_type_error!("chng_pol", "Label")),
+                _ => Err(mk_type_error!("label/flip_polarity", "Label")),
             }),
             UnaryOp::LabelPol => {
                 if let Term::Lbl(l) = &*t {
@@ -386,7 +386,7 @@ impl<R: ImportResolver, C: Cache> VirtualMachine<R, C> {
                         pos_op_inh,
                     )))
                 } else {
-                    Err(mk_type_error!("polarity", "Label"))
+                    Err(mk_type_error!("label/polarity", "Label"))
                 }
             }
             UnaryOp::LabelGoDom => match_sharedterm!(match (t) {
@@ -398,7 +398,7 @@ impl<R: ImportResolver, C: Cache> VirtualMachine<R, C> {
                         pos_op_inh,
                     )))
                 }
-                _ => Err(mk_type_error!("go_dom", "Label")),
+                _ => Err(mk_type_error!("label/go_dom", "Label")),
             }),
             UnaryOp::LabelGoCodom => match_sharedterm!(match (t) {
                 Term::Lbl(l) => {
@@ -409,7 +409,7 @@ impl<R: ImportResolver, C: Cache> VirtualMachine<R, C> {
                         pos_op_inh,
                     )))
                 }
-                _ => Err(mk_type_error!("go_codom", "Label")),
+                _ => Err(mk_type_error!("label/go_codom", "Label")),
             }),
             UnaryOp::LabelGoArray => match_sharedterm!(match (t) {
                 Term::Lbl(l) => {
@@ -420,7 +420,7 @@ impl<R: ImportResolver, C: Cache> VirtualMachine<R, C> {
                         pos_op_inh,
                     )))
                 }
-                _ => Err(mk_type_error!("go_array", "Label")),
+                _ => Err(mk_type_error!("label/go_array", "Label")),
             }),
             UnaryOp::LabelGoDict => match_sharedterm!(match (t) {
                 Term::Lbl(l) => {
@@ -431,7 +431,7 @@ impl<R: ImportResolver, C: Cache> VirtualMachine<R, C> {
                         pos_op_inh,
                     )))
                 }
-                _ => Err(mk_type_error!("go_dict", "Label")),
+                _ => Err(mk_type_error!("label/go_dict", "Label")),
             }),
             UnaryOp::RecordAccess(id) => {
                 if let Term::Record(record) = &*t {
@@ -491,7 +491,7 @@ impl<R: ImportResolver, C: Cache> VirtualMachine<R, C> {
                         pos_op_inh,
                     )))
                 }
-                _ => Err(mk_type_error!("fields", "Record")),
+                _ => Err(mk_type_error!("record/fields", "Record")),
             }),
             UnaryOp::RecordValues => match_sharedterm!(match (t) {
                 Term::Record(record) => {
@@ -510,13 +510,12 @@ impl<R: ImportResolver, C: Cache> VirtualMachine<R, C> {
                         env,
                     })
                 }
-                _ => Err(mk_type_error!("values", "Record")),
+                _ => Err(mk_type_error!("record/values", "Record")),
             }),
             UnaryOp::ArrayMap => {
-                let (f, ..) = self
-                    .stack
-                    .pop_arg(&self.cache)
-                    .ok_or_else(|| EvalError::NotEnoughArgs(2, String::from("map"), pos_op))?;
+                let (f, ..) = self.stack.pop_arg(&self.cache).ok_or_else(|| {
+                    EvalError::NotEnoughArgs(2, String::from("array/map"), pos_op)
+                })?;
                 match_sharedterm!(match (t) {
                     Term::Array(ts, attrs) => {
                         let f_as_var = f.body.closurize(&mut self.cache, f.env);
@@ -546,23 +545,22 @@ impl<R: ImportResolver, C: Cache> VirtualMachine<R, C> {
                             env: Environment::new(),
                         })
                     }
-                    _ => Err(mk_type_error!("map", "Array")),
+                    _ => Err(mk_type_error!("array/map", "Array")),
                 })
             }
             UnaryOp::ArrayGen => {
-                let (f, _) = self
-                    .stack
-                    .pop_arg(&self.cache)
-                    .ok_or_else(|| EvalError::NotEnoughArgs(2, String::from("generate"), pos_op))?;
+                let (f, _) = self.stack.pop_arg(&self.cache).ok_or_else(|| {
+                    EvalError::NotEnoughArgs(2, String::from("array/generate"), pos_op)
+                })?;
 
                 let Term::Num(ref n) = *t else {
-                    return Err(mk_type_error!("generate", "Number"));
+                    return Err(mk_type_error!("array/generate", "Number"));
                 };
 
                 if n < &Number::ZERO {
                     return Err(EvalError::Other(
                         format!(
-                            "generate expects its first argument to be a positive number, got {n}"
+                            "array/generate expects its first argument to be a positive number, got {n}"
                         ),
                         pos_op,
                     ));
@@ -571,7 +569,7 @@ impl<R: ImportResolver, C: Cache> VirtualMachine<R, C> {
                 let Ok(n_int) = u32::try_from(n) else {
                     return Err(EvalError::Other(
                         format!(
-                            "generate expects its first argument to be an integer \
+                            "array/generate expects its first argument to be an integer \
                             smaller than {}, got {n}",
                             u32::MAX,
                         ),
@@ -601,7 +599,7 @@ impl<R: ImportResolver, C: Cache> VirtualMachine<R, C> {
             }
             UnaryOp::RecordMap => {
                 let (f, ..) = self.stack.pop_arg(&self.cache).ok_or_else(|| {
-                    EvalError::NotEnoughArgs(2, String::from("record_map"), pos_op)
+                    EvalError::NotEnoughArgs(2, String::from("record/map"), pos_op)
                 })?;
 
                 match_sharedterm!(match (t) {
@@ -647,7 +645,7 @@ impl<R: ImportResolver, C: Cache> VirtualMachine<R, C> {
                             env: Environment::new(),
                         })
                     }
-                    _ => Err(mk_type_error!("record_map", "Record", 1)),
+                    _ => Err(mk_type_error!("record/map", "Record", 1)),
                 })
             }
             UnaryOp::Seq => self
@@ -737,7 +735,7 @@ impl<R: ImportResolver, C: Cache> VirtualMachine<R, C> {
                         env: Environment::new(),
                     })
                 } else {
-                    Err(mk_type_error!("length", "Array"))
+                    Err(mk_type_error!("array/length", "Array"))
                 }
             }
             UnaryOp::ChunksConcat => {
@@ -806,7 +804,7 @@ impl<R: ImportResolver, C: Cache> VirtualMachine<R, C> {
                         pos_op_inh,
                     )))
                 } else {
-                    Err(mk_type_error!("str_trim", "String"))
+                    Err(mk_type_error!("string/trim", "String"))
                 }
             }
             UnaryOp::StringChars => {
@@ -817,7 +815,7 @@ impl<R: ImportResolver, C: Cache> VirtualMachine<R, C> {
                         pos_op_inh,
                     )))
                 } else {
-                    Err(mk_type_error!("str_chars", "String"))
+                    Err(mk_type_error!("string/chars", "String"))
                 }
             }
             UnaryOp::StringUppercase => {
@@ -827,7 +825,7 @@ impl<R: ImportResolver, C: Cache> VirtualMachine<R, C> {
                         pos_op_inh,
                     )))
                 } else {
-                    Err(mk_type_error!("str_uppercase", "String"))
+                    Err(mk_type_error!("string/uppercase", "String"))
                 }
             }
             UnaryOp::StringLowercase => {
@@ -837,7 +835,7 @@ impl<R: ImportResolver, C: Cache> VirtualMachine<R, C> {
                         pos_op_inh,
                     )))
                 } else {
-                    Err(mk_type_error!("string_lowercase", "String"))
+                    Err(mk_type_error!("string/lowercase", "String"))
                 }
             }
             UnaryOp::StringLength => {
@@ -848,7 +846,7 @@ impl<R: ImportResolver, C: Cache> VirtualMachine<R, C> {
                         pos_op_inh,
                     )))
                 } else {
-                    Err(mk_type_error!("str_length", "String"))
+                    Err(mk_type_error!("string/length", "String"))
                 }
             }
             UnaryOp::ToString => {
@@ -873,7 +871,10 @@ impl<R: ImportResolver, C: Cache> VirtualMachine<R, C> {
                 if let Term::Str(s) = &*t {
                     let n = parse_number_sci(s).map_err(|_| {
                         EvalError::Other(
-                            format!("num_from_string: invalid number literal `{}`", s.as_str()),
+                            format!(
+                                "number/from_string: invalid number literal `{}`",
+                                s.as_str()
+                            ),
                             pos,
                         )
                     })?;
@@ -882,7 +883,7 @@ impl<R: ImportResolver, C: Cache> VirtualMachine<R, C> {
                         pos_op_inh,
                     )))
                 } else {
-                    Err(mk_type_error!("num_from_str", "String"))
+                    Err(mk_type_error!("number/from_str", "String"))
                 }
             }
             UnaryOp::EnumFromString => {
@@ -892,7 +893,7 @@ impl<R: ImportResolver, C: Cache> VirtualMachine<R, C> {
                         pos_op_inh,
                     )))
                 } else {
-                    Err(mk_type_error!("enum_from_str", "String"))
+                    Err(mk_type_error!("enum/from_str", "String"))
                 }
             }
             UnaryOp::StringIsMatch => {
@@ -914,7 +915,7 @@ impl<R: ImportResolver, C: Cache> VirtualMachine<R, C> {
 
                     Ok(Closure::atomic_closure(RichTerm::new(matcher, pos)))
                 } else {
-                    Err(mk_type_error!("str_is_match", "String", 1))
+                    Err(mk_type_error!("string/is_match", "String", 1))
                 }
             }
             UnaryOp::StringFind => {
@@ -936,7 +937,7 @@ impl<R: ImportResolver, C: Cache> VirtualMachine<R, C> {
 
                     Ok(Closure::atomic_closure(RichTerm::new(matcher, pos)))
                 } else {
-                    Err(mk_type_error!("str_find", "String", 1))
+                    Err(mk_type_error!("string/find", "String", 1))
                 }
             }
             UnaryOp::StringFindAll => {
@@ -958,7 +959,7 @@ impl<R: ImportResolver, C: Cache> VirtualMachine<R, C> {
 
                     Ok(Closure::atomic_closure(RichTerm::new(matcher, pos_op_inh)))
                 } else {
-                    Err(mk_type_error!("str_find_all", "String", 1))
+                    Err(mk_type_error!("string/find_all", "String", 1))
                 }
             }
             UnaryOp::StringIsMatchCompiled(regex) => {
@@ -1168,7 +1169,7 @@ impl<R: ImportResolver, C: Cache> VirtualMachine<R, C> {
                         env,
                     })
                 }
-                _ => Err(mk_type_error!("record_empty_with_tail", "Record")),
+                _ => Err(mk_type_error!("record/empty_with_tail", "Record")),
             }),
             UnaryOp::Trace => {
                 if let Term::Str(s) = &*t {
@@ -1193,7 +1194,7 @@ impl<R: ImportResolver, C: Cache> VirtualMachine<R, C> {
                             env,
                         })
                     }
-                    _ => Err(mk_type_error!("label_push_diag", "Label")),
+                    _ => Err(mk_type_error!("label/push_diag", "Label")),
                 })
             }
             #[cfg(feature = "nix-experimental")]
@@ -1227,7 +1228,7 @@ impl<R: ImportResolver, C: Cache> VirtualMachine<R, C> {
                         env,
                     })
                 } else {
-                    Err(mk_type_error!("enum_unwrap_variant", "Enum variant"))
+                    Err(mk_type_error!("enum/get_arg", "Enum variant"))
                 }
             }
             UnaryOp::EnumMakeVariant => {
@@ -1254,7 +1255,7 @@ impl<R: ImportResolver, C: Cache> VirtualMachine<R, C> {
                 Term::EnumVariant { tag, .. } | Term::Enum(tag) => Ok(Closure::atomic_closure(
                     RichTerm::new(Term::Enum(*tag), pos_op_inh),
                 )),
-                _ => Err(mk_type_error!("enum_get_tag", "Enum")),
+                _ => Err(mk_type_error!("enum/get_tag", "Enum")),
             },
             UnaryOp::EnumIsVariant => {
                 let result = matches!(&*t, Term::EnumVariant { .. });
@@ -1568,7 +1569,7 @@ impl<R: ImportResolver, C: Cache> VirtualMachine<R, C> {
                     // Track the contract argument for better error reporting, and push back the
                     // label on the stack, so that it becomes the first argument of the contract.
                     let idx = self.stack.track_arg(&mut self.cache).ok_or_else(|| {
-                        EvalError::NotEnoughArgs(3, String::from("apply_contract"), pos_op)
+                        EvalError::NotEnoughArgs(3, String::from("contract/apply"), pos_op)
                     })?;
                     let mut l = l.clone();
                     l.arg_pos = self.cache.get_then(idx.clone(), |c| c.body.pos);
@@ -1628,10 +1629,10 @@ impl<R: ImportResolver, C: Cache> VirtualMachine<R, C> {
                                 env: Environment::new(),
                             })
                         }
-                        _ => Err(mk_type_error!("apply_contract", "Contract", 1, t1, pos1)),
+                        _ => Err(mk_type_error!("contract/apply", "Contract", 1, t1, pos1)),
                     }
                 } else {
-                    Err(mk_type_error!("apply_contract", "Label", 2, t2, pos2))
+                    Err(mk_type_error!("contract/apply", "Label", 2, t2, pos2))
                 }
             }
             BinaryOp::Unseal => {
@@ -1770,9 +1771,9 @@ impl<R: ImportResolver, C: Cache> VirtualMachine<R, C> {
                             pos_op_inh,
                         )))
                     }
-                    _ => Err(mk_type_error!("go_field", "Label", 2, t2, pos2)),
+                    _ => Err(mk_type_error!("label/go_field", "Label", 2, t2, pos2)),
                 }),
-                _ => Err(mk_type_error!("go_field", "String", 1, t1, pos1)),
+                _ => Err(mk_type_error!("label/go_field", "String", 1, t1, pos1)),
             }),
             BinaryOp::RecordGet => {
                 match_sharedterm!(match (t1) {
@@ -1875,7 +1876,7 @@ impl<R: ImportResolver, C: Cache> VirtualMachine<R, C> {
                                 {
                                     Err(EvalError::Other(
                                         format!(
-                                            "record_insert: \
+                                            "record/insert: \
                                             tried to extend a record with the field {id}, \
                                             but it already exists"
                                         ),
@@ -1888,10 +1889,10 @@ impl<R: ImportResolver, C: Cache> VirtualMachine<R, C> {
                                 }),
                             }
                         }
-                        _ => Err(mk_type_error!("record_insert", "Record", 2, t2, pos2)),
+                        _ => Err(mk_type_error!("record/insert", "Record", 2, t2, pos2)),
                     })
                 } else {
-                    Err(mk_type_error!("record_insert", "String", 1, t1, pos1))
+                    Err(mk_type_error!("record/insert", "String", 1, t1, pos1))
                 }
             }
             BinaryOp::RecordRemove(op_kind) => match_sharedterm!(match (t1) {
@@ -1931,7 +1932,7 @@ impl<R: ImportResolver, C: Cache> VirtualMachine<R, C> {
                                     Err(EvalError::FieldMissing {
                                         id: id.into(),
                                         field_names: record.field_names(op_kind),
-                                        operator: String::from("record_remove"),
+                                        operator: String::from("record/remove"),
                                         pos_record: pos2,
                                         pos_op,
                                     })
@@ -1947,9 +1948,9 @@ impl<R: ImportResolver, C: Cache> VirtualMachine<R, C> {
                             })
                         }
                     }
-                    _ => Err(mk_type_error!("record_remove", "Record", 2, t2, pos2)),
+                    _ => Err(mk_type_error!("record/remove", "Record", 2, t2, pos2)),
                 }),
-                _ => Err(mk_type_error!("record_remove", "String", 1, t1, pos1)),
+                _ => Err(mk_type_error!("record/remove", "String", 1, t1, pos1)),
             }),
             BinaryOp::RecordHasField(op_kind) => match_sharedterm!(match (t1) {
                 Term::Str(id) => {
@@ -1962,10 +1963,10 @@ impl<R: ImportResolver, C: Cache> VirtualMachine<R, C> {
                             pos_op_inh,
                         )))
                     } else {
-                        Err(mk_type_error!("has_field", "Record", 2, t2, pos2))
+                        Err(mk_type_error!("record/has_field", "Record", 2, t2, pos2))
                     }
                 }
-                _ => Err(mk_type_error!("has_field", "String", 1, t1, pos1)),
+                _ => Err(mk_type_error!("record/has_field", "String", 1, t1, pos1)),
             }),
             BinaryOp::RecordFieldIsDefined(op_kind) => match_sharedterm!(match (t1) {
                 Term::Str(id) => {
@@ -1978,10 +1979,22 @@ impl<R: ImportResolver, C: Cache> VirtualMachine<R, C> {
                             pos_op_inh,
                         )))
                     } else {
-                        Err(mk_type_error!("field_is_defined", "Record", 2, t2, pos2))
+                        Err(mk_type_error!(
+                            "record/field_is_defined",
+                            "Record",
+                            2,
+                            t2,
+                            pos2
+                        ))
                     }
                 }
-                _ => Err(mk_type_error!("field_is_defined", "String", 1, t1, pos1)),
+                _ => Err(mk_type_error!(
+                    "record/field_is_defined",
+                    "String",
+                    1,
+                    t1,
+                    pos1
+                )),
             }),
             BinaryOp::ArrayConcat => match_sharedterm!(match (t1) {
                 Term::Array(ts1, attrs1) => match_sharedterm!(match (t2) {
@@ -2110,7 +2123,7 @@ impl<R: ImportResolver, C: Cache> VirtualMachine<R, C> {
                     let Ok(n_as_usize) = usize::try_from(n) else {
                         return Err(EvalError::Other(
                             format!(
-                                "elem_at expects its second argument to be a \
+                                "array/at expects its second argument to be a \
                                 positive integer smaller than {}, got {n}",
                                 usize::MAX
                             ),
@@ -2121,7 +2134,7 @@ impl<R: ImportResolver, C: Cache> VirtualMachine<R, C> {
                     if n_as_usize >= ts.len() {
                         return Err(EvalError::Other(
                             format!(
-                                "elem_at: index out of bounds. \
+                                "array/at: index out of bounds. \
                                 Expected an index between 0 and {}, got {}",
                                 ts.len(),
                                 n
@@ -2141,8 +2154,8 @@ impl<R: ImportResolver, C: Cache> VirtualMachine<R, C> {
                         env: env1,
                     })
                 }
-                (Term::Array(..), _) => Err(mk_type_error!("elem_at", "Number", 2, t2, pos2)),
-                (_, _) => Err(mk_type_error!("elem_at", "Array", 1, t1, pos1)),
+                (Term::Array(..), _) => Err(mk_type_error!("array/at", "Number", 2, t2, pos2)),
+                (_, _) => Err(mk_type_error!("array/at", "Array", 1, t1, pos1)),
             },
             BinaryOp::Merge(merge_label) => merge::merge(
                 &mut self.cache,
@@ -2302,8 +2315,8 @@ impl<R: ImportResolver, C: Cache> VirtualMachine<R, C> {
                         pos_op_inh,
                     )))
                 }
-                (Term::Str(_), _) => Err(mk_type_error!("str_split", "String", 2, t2, pos2)),
-                (_, _) => Err(mk_type_error!("str_split", "String", 1, t1, pos1)),
+                (Term::Str(_), _) => Err(mk_type_error!("string/split", "String", 2, t2, pos2)),
+                (_, _) => Err(mk_type_error!("string/split", "String", 1, t1, pos1)),
             },
             BinaryOp::StringContains => match (&*t1, &*t2) {
                 (Term::Str(s1), Term::Str(s2)) => {
@@ -2313,8 +2326,8 @@ impl<R: ImportResolver, C: Cache> VirtualMachine<R, C> {
                         pos_op_inh,
                     )))
                 }
-                (Term::Str(_), _) => Err(mk_type_error!("str_contains", "String", 2, t2, pos2)),
-                (_, _) => Err(mk_type_error!("str_contains", "String", 1, t1, pos1)),
+                (Term::Str(_), _) => Err(mk_type_error!("string/contains", "String", 2, t2, pos2)),
+                (_, _) => Err(mk_type_error!("string/contains", "String", 1, t1, pos1)),
             },
             BinaryOp::StringCompare => match (&*t1, &*t2) {
                 (Term::Str(s1), Term::Str(s2)) => {
@@ -2336,7 +2349,7 @@ impl<R: ImportResolver, C: Cache> VirtualMachine<R, C> {
             },
             BinaryOp::ContractArrayLazyApp => {
                 let (ctr, _) = self.stack.pop_arg(&self.cache).ok_or_else(|| {
-                    EvalError::NotEnoughArgs(3, String::from("array_lazy_app_ctr"), pos_op)
+                    EvalError::NotEnoughArgs(3, String::from("contract/array_lazy_app"), pos_op)
                 })?;
 
                 let Closure {
@@ -2347,7 +2360,14 @@ impl<R: ImportResolver, C: Cache> VirtualMachine<R, C> {
                 // FIXME: use match?
                 let lbl = match_sharedterm!(match (t1) {
                     Term::Lbl(lbl) => lbl,
-                    _ => return Err(mk_type_error!("array_lazy_app_ctr", "Label", 1, t1, pos1)),
+                    _ =>
+                        return Err(mk_type_error!(
+                            "contract/array_lazy_app",
+                            "Label",
+                            1,
+                            t1,
+                            pos1
+                        )),
                 });
 
                 match_sharedterm!(match (t2) {
@@ -2371,7 +2391,13 @@ impl<R: ImportResolver, C: Cache> VirtualMachine<R, C> {
 
                         Ok(array_with_ctr)
                     }
-                    _ => Err(mk_type_error!("array_lazy_app_ctr", "Array", 2, t2, pos2)),
+                    _ => Err(mk_type_error!(
+                        "contract/array_lazy_app",
+                        "Array",
+                        2,
+                        t2,
+                        pos2
+                    )),
                 })
             }
             BinaryOp::ContractRecordLazyApp => {
@@ -2384,12 +2410,19 @@ impl<R: ImportResolver, C: Cache> VirtualMachine<R, C> {
                     },
                     _,
                 ) = self.stack.pop_arg(&self.cache).ok_or_else(|| {
-                    EvalError::NotEnoughArgs(3, String::from("record_lazy_app_ctr"), pos_op)
+                    EvalError::NotEnoughArgs(3, String::from("contract/record_lazy_app"), pos_op)
                 })?;
 
                 let label = match_sharedterm!(match (t1) {
                     Term::Lbl(label) => label,
-                    _ => return Err(mk_type_error!("record_lazy_app_ctr", "Label", 1, t1, pos1)),
+                    _ =>
+                        return Err(mk_type_error!(
+                            "contract/record_lazy_app",
+                            "Label",
+                            1,
+                            t1,
+                            pos1
+                        )),
                 });
 
                 match_sharedterm!(match (t2) {
@@ -2437,7 +2470,13 @@ impl<R: ImportResolver, C: Cache> VirtualMachine<R, C> {
                             env: Environment::new(),
                         })
                     }
-                    _ => Err(mk_type_error!("record_lazy_app_ctr", "Record", 2, t2, pos2)),
+                    _ => Err(mk_type_error!(
+                        "contract/record_lazy_app",
+                        "Record",
+                        2,
+                        t2,
+                        pos2
+                    )),
                 })
             }
             BinaryOp::LabelWithMessage => {
@@ -2446,7 +2485,7 @@ impl<R: ImportResolver, C: Cache> VirtualMachine<R, C> {
 
                 let Term::Str(message) = t1 else {
                     return Err(mk_type_error!(
-                        "label_with_message",
+                        "label/with_message",
                         "String",
                         1,
                         t1.into(),
@@ -2456,7 +2495,7 @@ impl<R: ImportResolver, C: Cache> VirtualMachine<R, C> {
 
                 let Term::Lbl(label) = t2 else {
                     return Err(mk_type_error!(
-                        "label_with_message",
+                        "label/with_message",
                         "String",
                         2,
                         t2.into(),
@@ -2488,7 +2527,7 @@ impl<R: ImportResolver, C: Cache> VirtualMachine<R, C> {
 
                 let Term::Array(array, _) = t1 else {
                     return Err(mk_type_error!(
-                        "label_with_notes",
+                        "label/with_notes",
                         "Array",
                         1,
                         t1.into(),
@@ -2505,7 +2544,7 @@ impl<R: ImportResolver, C: Cache> VirtualMachine<R, C> {
                             Ok(s.into_inner())
                         } else {
                             Err(mk_type_error!(
-                                "label_with_notes",
+                                "label/with_notes",
                                 "String",
                                 1,
                                 term.into(),
@@ -2517,7 +2556,7 @@ impl<R: ImportResolver, C: Cache> VirtualMachine<R, C> {
 
                 let Term::Lbl(label) = t2 else {
                     return Err(mk_type_error!(
-                        "label_with_notes",
+                        "label/with_notes",
                         "Label",
                         2,
                         t2.into(),
@@ -2536,7 +2575,7 @@ impl<R: ImportResolver, C: Cache> VirtualMachine<R, C> {
 
                 let Term::Str(note) = t1 else {
                     return Err(mk_type_error!(
-                        "label_append_note",
+                        "label/append_note",
                         "String",
                         1,
                         t1.into(),
@@ -2546,7 +2585,7 @@ impl<R: ImportResolver, C: Cache> VirtualMachine<R, C> {
 
                 let Term::Lbl(label) = t2 else {
                     return Err(mk_type_error!(
-                        "label_append_note",
+                        "label/append_note",
                         "Label",
                         2,
                         t2.into(),
@@ -2565,7 +2604,7 @@ impl<R: ImportResolver, C: Cache> VirtualMachine<R, C> {
 
                 let Term::SealingKey(key) = t1 else {
                     return Err(mk_type_error!(
-                        "lookup_type_variable",
+                        "label/lookup_type_variable",
                         "SealingKey",
                         1,
                         t1.into(),
@@ -2575,7 +2614,7 @@ impl<R: ImportResolver, C: Cache> VirtualMachine<R, C> {
 
                 let Term::Lbl(label) = t2 else {
                     return Err(mk_type_error!(
-                        "lookup_type_variable",
+                        "label/lookup_type_variable",
                         "Label",
                         2,
                         t2.into(),
@@ -2868,7 +2907,7 @@ impl<R: ImportResolver, C: Cache> VirtualMachine<R, C> {
                         })
                         .map_err(|e| EvalError::Other(format!("{}", e), pos_op)),
                     (Term::Str(_), Term::Num(_), _) => Err(EvalError::NAryPrimopTypeError {
-                        primop: String::from("str_subst"),
+                        primop: String::from("string/subst"),
                         expected: String::from("String"),
                         arg_number: 3,
                         arg_pos: thd_pos,
@@ -2878,7 +2917,7 @@ impl<R: ImportResolver, C: Cache> VirtualMachine<R, C> {
                         },
                     }),
                     (Term::Str(_), _, _) => Err(EvalError::NAryPrimopTypeError {
-                        primop: String::from("str_subst"),
+                        primop: String::from("string/subst"),
                         expected: String::from("String"),
                         arg_number: 2,
                         arg_pos: snd_pos,
@@ -2888,7 +2927,7 @@ impl<R: ImportResolver, C: Cache> VirtualMachine<R, C> {
                         },
                     }),
                     (_, _, _) => Err(EvalError::NAryPrimopTypeError {
-                        primop: String::from("str_substr"),
+                        primop: String::from("string/substr"),
                         expected: String::from("String"),
                         arg_number: 1,
                         arg_pos: fst_pos,
@@ -3034,7 +3073,7 @@ impl<R: ImportResolver, C: Cache> VirtualMachine<R, C> {
                     }
                     (Term::SealingKey(_), Term::Lbl(_), Term::Record(_), _) => {
                         Err(EvalError::NAryPrimopTypeError {
-                            primop: String::from("record_seal_tail"),
+                            primop: String::from("record/seal_tail"),
                             expected: String::from("Record"),
                             arg_number: 4,
                             arg_pos: frth_pos,
@@ -3046,7 +3085,7 @@ impl<R: ImportResolver, C: Cache> VirtualMachine<R, C> {
                     }
                     (Term::SealingKey(_), Term::Lbl(_), _, _) => {
                         Err(EvalError::NAryPrimopTypeError {
-                            primop: String::from("record_seal_tail"),
+                            primop: String::from("record/seal_tail"),
                             expected: String::from("Record"),
                             arg_number: 3,
                             arg_pos: thd_pos,
@@ -3057,7 +3096,7 @@ impl<R: ImportResolver, C: Cache> VirtualMachine<R, C> {
                         })
                     }
                     (Term::SealingKey(_), _, _, _) => Err(EvalError::NAryPrimopTypeError {
-                        primop: String::from("record_seal_tail"),
+                        primop: String::from("record/seal_tail"),
                         expected: String::from("Label"),
                         arg_number: 2,
                         arg_pos: snd_pos,
@@ -3067,7 +3106,7 @@ impl<R: ImportResolver, C: Cache> VirtualMachine<R, C> {
                         },
                     }),
                     (_, _, _, _) => Err(EvalError::NAryPrimopTypeError {
-                        primop: String::from("record_seal_tail"),
+                        primop: String::from("record/seal_tail"),
                         expected: String::from("SealingKey"),
                         arg_number: 1,
                         arg_pos: fst_pos,
@@ -3127,7 +3166,7 @@ impl<R: ImportResolver, C: Cache> VirtualMachine<R, C> {
                         })
                         .map(|t| Closure { body: t, env: env3 }),
                     (Term::SealingKey(_), Term::Lbl(_), _) => Err(EvalError::NAryPrimopTypeError {
-                        primop: String::from("record_unseal_tail"),
+                        primop: String::from("record/unseal_tail"),
                         expected: String::from("Record"),
                         arg_number: 3,
                         arg_pos: thd_pos,
@@ -3137,7 +3176,7 @@ impl<R: ImportResolver, C: Cache> VirtualMachine<R, C> {
                         },
                     }),
                     (Term::SealingKey(_), _, _) => Err(EvalError::NAryPrimopTypeError {
-                        primop: String::from("record_unseal_tail"),
+                        primop: String::from("record/unseal_tail"),
                         expected: String::from("Label"),
                         arg_number: 2,
                         arg_pos: snd_pos,
@@ -3147,7 +3186,7 @@ impl<R: ImportResolver, C: Cache> VirtualMachine<R, C> {
                         },
                     }),
                     (_, _, _) => Err(EvalError::NAryPrimopTypeError {
-                        primop: String::from("record_unseal_tail"),
+                        primop: String::from("record/unseal_tail"),
                         expected: String::from("SealingKey"),
                         arg_number: 1,
                         arg_pos: fst_pos,
@@ -3200,7 +3239,7 @@ impl<R: ImportResolver, C: Cache> VirtualMachine<R, C> {
 
                 let Term::SealingKey(key) = *key else {
                     return Err(EvalError::NAryPrimopTypeError {
-                        primop: String::from("insert_type_variable"),
+                        primop: String::from("label/insert_type_variable"),
                         expected: String::from("SealingKey"),
                         arg_number: 1,
                         arg_pos: key_pos,
@@ -3213,7 +3252,7 @@ impl<R: ImportResolver, C: Cache> VirtualMachine<R, C> {
 
                 let Ok(polarity) = Polarity::try_from(polarity.as_ref()) else {
                     return Err(EvalError::NAryPrimopTypeError {
-                        primop: String::from("insert_type_variable"),
+                        primop: String::from("label/insert_type_variable"),
                         expected: String::from("Polarity"),
                         arg_number: 2,
                         arg_pos: polarity_pos,
@@ -3226,7 +3265,7 @@ impl<R: ImportResolver, C: Cache> VirtualMachine<R, C> {
 
                 let Term::Lbl(label) = &*label else {
                     return Err(EvalError::NAryPrimopTypeError {
-                        primop: String::from("insert_type_variable"),
+                        primop: String::from("label/insert_type_variable"),
                         expected: String::from("Label"),
                         arg_number: 3,
                         arg_pos: label_pos,
@@ -3289,7 +3328,7 @@ impl<R: ImportResolver, C: Cache> VirtualMachine<R, C> {
 
                 let Term::Num(ref start) = &*t1 else {
                     return Err(EvalError::NAryPrimopTypeError {
-                        primop: String::from("array_slice"),
+                        primop: String::from("array/slice"),
                         expected: String::from("Number"),
                         arg_number: 1,
                         arg_pos: fst_pos,
@@ -3302,7 +3341,7 @@ impl<R: ImportResolver, C: Cache> VirtualMachine<R, C> {
 
                 let Term::Num(ref end) = &*t2 else {
                     return Err(EvalError::NAryPrimopTypeError {
-                        primop: String::from("array_slice"),
+                        primop: String::from("array/slice"),
                         expected: String::from("Number"),
                         arg_number: 2,
                         arg_pos: snd_pos,
@@ -3317,7 +3356,7 @@ impl<R: ImportResolver, C: Cache> VirtualMachine<R, C> {
 
                 let Term::Array(mut array, attrs) = t3_owned else {
                     return Err(EvalError::NAryPrimopTypeError {
-                        primop: String::from("array_slice"),
+                        primop: String::from("array/slice"),
                         expected: String::from("Array"),
                         arg_number: 3,
                         arg_pos: third_pos,
@@ -3328,7 +3367,7 @@ impl<R: ImportResolver, C: Cache> VirtualMachine<R, C> {
                 let Ok(start_as_usize) = usize::try_from(start) else {
                     return Err(EvalError::Other(
                         format!(
-                            "array_slice expects its first argument (start) to be a \
+                            "array/slice expects its first argument (start) to be a \
                             positive integer smaller than {}, got {start}",
                             usize::MAX
                         ),
@@ -3339,7 +3378,7 @@ impl<R: ImportResolver, C: Cache> VirtualMachine<R, C> {
                 let Ok(end_as_usize) = usize::try_from(end) else {
                     return Err(EvalError::Other(
                         format!(
-                            "array_slice expects its second argument (end) to be a \
+                            "array/slice expects its second argument (end) to be a \
                             positive integer smaller than {}, got {end}",
                             usize::MAX
                         ),
@@ -3352,7 +3391,7 @@ impl<R: ImportResolver, C: Cache> VirtualMachine<R, C> {
                 if let Err(OutOfBoundError) = result {
                     return Err(EvalError::Other(
                         format!(
-                            "array_slice: index out of bounds. Expected `start <= end <= {}`, but \
+                            "array/slice: index out of bounds. Expected `start <= end <= {}`, but \
                             got `start={start}` and `end={end}`.",
                             array.len()
                         ),
diff --git a/core/src/term/mod.rs b/core/src/term/mod.rs
index a17b1cfc..fc312208 100644
--- a/core/src/term/mod.rs
+++ b/core/src/term/mod.rs
@@ -1234,9 +1234,9 @@ pub enum UnaryOp {
 
     /// Typecast an enum to a larger enum type.
     ///
-    /// `Embed` is used to upcast enums. For example, if a value `x` has enum type `a | b`, then
-    /// `embed c x` will have enum type `a | b | c`. It only affects typechecking as at runtime
-    /// `embed someId` act like the identity.
+    /// `EnumEmbed` is used to upcast enums. For example, if a value `x` has enum type `a | b`,
+    /// then `%enum/embed% c x` will have enum type `a | b | c`. It only affects typechecking as at
+    /// runtime `%enum/embed% someId` acts like the identity function.
     EnumEmbed(LocIdent),
 
     /// A specialized primop for match when all patterns are enum tags. In that case, instead of
@@ -1257,7 +1257,7 @@ pub enum UnaryOp {
     ///
     /// The mapped function must take two arguments, the name of the field as a string, and the
     /// content of the field. `RecordMap` then replaces the content of each field by the result of
-    /// the function: i.e., `recordMap f {a=2;}` evaluates to `{a=(f "a" 2);}`.
+    /// the function: i.e., `%record/map% f {a=2;}` evaluates to `{a=(f "a" 2);}`.
     RecordMap,
 
     /// Inverse the polarity of a label.
diff --git a/core/src/term/pattern/compile.rs b/core/src/term/pattern/compile.rs
index 88201715..8bdc3ad4 100644
--- a/core/src/term/pattern/compile.rs
+++ b/core/src/term/pattern/compile.rs
@@ -102,7 +102,7 @@ fn remove_from_rest(rest_field: LocIdent, field: LocIdent, bindings_id: LocIdent
 /// More precisely, [with_default_value] generates the following code:
 ///
 /// ```nickel
-/// if !(%field_is_defined% "<field>" record_id) then
+/// if !(%record/field_is_defined% "<field>" record_id) then
 ///   if %record/has_field% "<field>" record_id then
 ///     record_id & { "<field>" = default }
 ///   else
@@ -363,14 +363,14 @@ impl CompilePart for RecordPattern {
     //      - initial accumulator is `%record/insert% "<REST_FIELD>" bindings_id value_id`
     //      >
     //
-    //     # If there is a default value, we must set it before the %field_is_defined% check below,
+    //     # If there is a default value, we must set it before the %record/field_is_defined% check below,
     //     # because the default acts like if the original matched value always have this field
     //     # defined
     //     <if field.default.is_some()>
     //       let value_id = <with_default_value value_id field default> in
     //     <end if>
     //
-    //      if %field_is_defined% field value_id then
+    //      if %record/field_is_defined% field value_id then
     //         <if !field_pat.annotation.is_empty()>
     //           let value_id = value_id & { "<field>" | <field_pat.annotation> } in
     //         <end if>
@@ -429,14 +429,14 @@ impl CompilePart for RecordPattern {
         //  - initial accumulator is `%record/insert% "<REST>" bindings_id value_id`
         // >
         //
-        // # If there is a default value, we must set it before the %field_is_defined% check below,
+        // # If there is a default value, we must set it before the %record/field_is_defined% check below,
         // # because the default acts like if the original matched value always have this field
         // # defined
         // <if field.default.is_some()>
         //   let value_id = <with_default_value value_id field default> in
         // <end if>
         //
-        // if %field_is_defined% field value_id then
+        // if %record/field_is_defined% field value_id then
         //   # If the field is present, we apply the potential contracts coming from user-provided
         //   # annotations before anything else. We just offload the actual work to `&`
         //   <if !field_pat.annotation.is_empty() >
@@ -514,7 +514,7 @@ impl CompilePart for RecordPattern {
                 binding_cont_let
             };
 
-            // %field_is_defined% field value_id
+            // %record/field_is_defined% field value_id
             let has_field = make::op2(
                 BinaryOp::RecordFieldIsDefined(RecordOpKind::ConsiderAllFields),
                 Term::Str(field.label().into()),
@@ -623,7 +623,7 @@ impl CompilePart for RecordPattern {
 impl CompilePart for ArrayPattern {
     // Compilation of an array pattern.
     //
-    // let value_len = %array_length% value_id in
+    // let value_len = %array/length% value_id in
     //
     // <if self.is_open()>
     // if %typeof% value_id == 'Array && value_len >= <self.patterns.len()>
@@ -641,7 +641,7 @@ impl CompilePart for ArrayPattern {
     //       if local_bindings_id == null then
     //         null
     //       else
-    //         let local_value_id = %array_access% <idx> value_id in
+    //         let local_value_id = %array/at% <idx> value_id in
     //         <elem_pat.compile_part(local_value_id, local_bindings_id)>
     //
     //     <end fold>
@@ -673,7 +673,7 @@ impl CompilePart for ArrayPattern {
         //       if local_bindings_id == null then
         //         null
         //       else
-        //         let local_value_id = %array_access% <idx> value_id in
+        //         let local_value_id = %array/at% <idx> value_id in
         //         <self.patterns[idx].compile_part(local_value_id, local_bindings_id)>
         //
         //     <end fold>
@@ -686,7 +686,7 @@ impl CompilePart for ArrayPattern {
                 // <self.patterns[idx].compile_part(local_value_id, local_bindings_id)>
                 let updated_bindings_let = elem_pat.compile_part(local_value_id, local_bindings_id);
 
-                // %array_access% idx value_id
+                // %array/at% idx value_id
                 let extracted_value = make::op2(
                     BinaryOp::ArrayAt,
                     Term::Var(value_id),
@@ -786,7 +786,7 @@ impl CompilePart for ArrayPattern {
 
 impl CompilePart for EnumPattern {
     fn compile_part(&self, value_id: LocIdent, bindings_id: LocIdent) -> RichTerm {
-        // %enum_get_tag% value_id == '<self.tag>
+        // %enum/get_tag% value_id == '<self.tag>
         let tag_matches = make::op2(
             BinaryOp::Eq,
             make::op1(UnaryOp::EnumGetTag, Term::Var(value_id)),
@@ -794,13 +794,13 @@ impl CompilePart for EnumPattern {
         );
 
         if let Some(pat) = &self.pattern {
-            // if %enum_is_variant% value_id && %enum_get_tag% value_id == '<self.tag> then
-            //   let value_id = %enum_unwrap_variant% value_id in
+            // if %enum/is_variant% value_id && %enum/get_tag% value_id == '<self.tag> then
+            //   let value_id = %enum/get_arg% value_id in
             //   <pattern.compile(value_id, bindings_id)>
             // else
             //   null
 
-            // %enum_is_variant% value_id && <tag_matches>
+            // %enum/is_variant% value_id && <tag_matches>
             let if_condition = mk_app!(
                 make::op1(
                     UnaryOp::BoolAnd,
@@ -819,7 +819,7 @@ impl CompilePart for EnumPattern {
                 Term::Null,
             )
         } else {
-            // if %typeof% value_id == 'Enum && !(%enum_is_variant% value_id) && <tag_matches> then
+            // if %typeof% value_id == 'Enum && !(%enum/is_variant% value_id) && <tag_matches> then
             //   bindings_id
             // else
             //   null
@@ -831,7 +831,7 @@ impl CompilePart for EnumPattern {
                 Term::Enum("Enum".into()),
             );
 
-            // !(%enum_is_variant% value_id)
+            // !(%enum/is_variant% value_id)
             let is_enum_tag = make::op1(
                 UnaryOp::BoolNot,
                 make::op1(UnaryOp::EnumIsVariant, Term::Var(value_id)),
diff --git a/core/src/typ.rs b/core/src/typ.rs
index b3ac6ecb..df31c781 100644
--- a/core/src/typ.rs
+++ b/core/src/typ.rs
@@ -980,7 +980,7 @@ impl Subcontract for EnumRows {
         //   x |> match {
         //     'foo => x,
         //     'bar => x,
-        //     'Baz variant_arg => 'Baz (%apply_contract% T label_arg variant_arg),
+        //     'Baz variant_arg => 'Baz (%contract/apply% T label_arg variant_arg),
         //     _ => $enum_fail l
         //   }
         // ```
@@ -996,7 +996,7 @@ impl Subcontract for EnumRows {
                     });
 
                     let body = if let Some(ty) = row.typ.as_ref() {
-                        // 'Tag (%apply_contract% T label_arg variant_arg)
+                        // 'Tag (%contract/apply% T label_arg variant_arg)
                         let arg = mk_app!(
                             mk_term::op2(
                                 BinaryOp::ContractApply,
diff --git a/core/stdlib/internals.ncl b/core/stdlib/internals.ncl
index ff99d391..2dd04e88 100644
--- a/core/stdlib/internals.ncl
+++ b/core/stdlib/internals.ncl
@@ -82,16 +82,17 @@
     if polarity == current_polarity then
       %unseal% sealing_key value (%blame% label)
     else
-      # [^forall_chng_pol]: Blame assignment for polymorphic contracts
-      # should take into account the polarity at the point the forall was
-      # introduced, not the current polarity of the variable occurrence. Indeed,
-      # forall can never blame in a negative position (relative to the
+      # [^forall_label_flip_polarity]: Blame assignment for polymorphic
+      # contracts should take into account the polarity at the point the forall
+      # was introduced, not the current polarity of the variable occurrence.
+      # Indeed, forall can never blame in a negative position (relative to the
       # forall): the contract is entirely on the callee.
       #
       # Thus, for correct blame assignment, we want to set the polarity to the
-      # forall polarity (here `polarity`). Because we only have the `chng_pol`
-      # primop, and we know that in this branch they are unequal, flipping the
-      # current polarity will indeed give the original forall's polarity.
+      # forall polarity (here `polarity`). Because we only have the
+      # `%label/flip_polarity%` primop, and we know that in this branch they are
+      # unequal, flipping the current polarity will indeed give the original
+      # forall's polarity.
       %seal% sealing_key (%label/flip_polarity% label) value,
 
   "$forall" = fun sealing_key polarity contract label value =>
@@ -254,7 +255,7 @@
               label
           )
       else
-        # See [^forall_chng_pol]
+        # See [^forall_label_flip_polarity]
         %record/seal_tail% sealing_key (%label/flip_polarity% label) acc value,
 
   "$dyn_tail" = fun acc label value => acc & value,
diff --git a/notes/fixing-sealing-and-recursive-records.md b/notes/fixing-sealing-and-recursive-records.md
index 2ca60700..63b08c12 100644
--- a/notes/fixing-sealing-and-recursive-records.md
+++ b/notes/fixing-sealing-and-recursive-records.md
@@ -120,14 +120,14 @@ Final result:
 Run of a `%record/map% { foo | Num =  1, bar | PosNat | Even = foo + 1} (fun _key ((+) 1)`
 
 ```
-App(Op1(record_map, record), function)
-Op1(record_map, record); {stack..}
+App(Op1(record/map, record), function)
+Op1(record/map, record); {stack..}
 record ~ RecRecord {..}
 
 RECORD{ foo |pending Num = %1, bar |pending [PosNat,Even] = %2}
-%2 := (%apply_contract% Num label %1) + 1
+%2 := (%contract/apply% Num label %1) + 1
 
-RECORD{ foo = f (%apply_contract% Num %1), bar = f (%apply_contract% PosNat,Even %2) }
+RECORD{ foo = f (%contract/apply% Num %1), bar = f (%contract/apply% PosNat,Even %2) }
 
 # With a call to pending_contract.dualize()
 


Test patch:
diff --git a/cli/tests/snapshot/snapshots/snapshot__eval_stderr_record_access.ncl.snap b/cli/tests/snapshot/snapshots/snapshot__eval_stderr_record_access.ncl.snap
index 295a4d5f..ff8a51a6 100644
--- a/cli/tests/snapshot/snapshots/snapshot__eval_stderr_record_access.ncl.snap
+++ b/cli/tests/snapshot/snapshots/snapshot__eval_stderr_record_access.ncl.snap
@@ -2,6 +2,6 @@
 source: cli/tests/snapshot/main.rs
 expression: err
 ---
-error: record_insert: tried to extend a record with the field bar, but it already exists
+error: record/insert: tried to extend a record with the field bar, but it already exists