Skip to content

Commit 6805e21

Browse files
committed
fix: broken type_of and type_tag after NickelValue migration
1 parent 918fa73 commit 6805e21

File tree

2 files changed

+66
-43
lines changed

2 files changed

+66
-43
lines changed

core/src/bytecode/value/mod.rs

Lines changed: 42 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,8 @@ use crate::{
2020
traverse::{Traverse as _, TraverseOrder},
2121
typ::Type,
2222
};
23-
use nickel_lang_vector::Slice;
2423
use malachite::base::num::conversion::traits::ToSci as _;
24+
use nickel_lang_vector::Slice;
2525
use std::{
2626
alloc::{Layout, alloc, dealloc},
2727
cmp::max,
@@ -978,29 +978,48 @@ impl NickelValue {
978978
/// class is less precise than the type and indicates the general shape of the term: `Record`
979979
/// for records, `Array` for arrays, etc. If the term is not a WHNF, `None` is returned.
980980
pub fn type_of(&self) -> Option<&'static str> {
981-
match self.tag() {
982-
ValueTag::Pointer => match self.body_tag().unwrap() {
983-
BodyTag::Number => Some("Number"),
984-
BodyTag::Array => Some("Array"),
985-
BodyTag::Record => Some("Record"),
986-
BodyTag::String => Some("String"),
987-
BodyTag::Label => Some("Label"),
988-
BodyTag::EnumVariant => {
989-
let variant = self.as_value_body::<EnumVariantBody>().unwrap();
990-
if variant.arg.is_some() {
991-
Some("EnumVariant")
992-
} else {
993-
Some("EnumTag")
994-
}
995-
}
996-
BodyTag::ForeignId => Some("ForeignId"),
997-
BodyTag::SealingKey => Some("SealingKey"),
998-
BodyTag::CustomContract => Some("CustomContract"),
999-
BodyTag::Type => Some("Type"),
1000-
BodyTag::Thunk | BodyTag::Term => None,
981+
match self.content_ref() {
982+
ValueContentRef::Inline(inline) => match inline {
983+
InlineValue::True | InlineValue::False => Some("Bool"),
984+
InlineValue::Null => Some("Other"),
985+
InlineValue::EmptyArray => Some("Array"),
986+
InlineValue::EmptyRecord => Some("Record"),
1001987
},
1002-
// Safety: `self.tag()` is `ValueTag::Inline`
1003-
ValueTag::Inline => unsafe { self.as_inline_unchecked().type_of() },
988+
ValueContentRef::Number(_) => Some("Number"),
989+
ValueContentRef::Array(_) => Some("Array"),
990+
ValueContentRef::Record(_) => Some("Record"),
991+
ValueContentRef::String(_) => Some("String"),
992+
ValueContentRef::Term(term_body) => match &term_body.0 {
993+
Term::Value(v) | Term::Closurize(v) => v.type_of(),
994+
Term::RecRecord(..) => Some("Record"),
995+
Term::Fun(..) | Term::FunPattern(..) => Some("Function"),
996+
Term::Match { .. } => Some("MatchExpression"),
997+
Term::Sealed(..) => Some("Sealed"),
998+
Term::Annotated(..) => Some("Annotated"),
999+
Term::Let(..)
1000+
| Term::LetPattern(..)
1001+
| Term::App(_, _)
1002+
| Term::Var(_)
1003+
| Term::Op1(_, _)
1004+
| Term::Op2(_, _, _)
1005+
| Term::OpN(..)
1006+
| Term::Import(_)
1007+
| Term::ResolvedImport(_)
1008+
| Term::StrChunks(_)
1009+
| Term::ParseError(_)
1010+
| Term::RuntimeError(_) => None,
1011+
},
1012+
ValueContentRef::Label(_) => Some("Label"),
1013+
ValueContentRef::EnumVariant(EnumVariantBody { arg: None, tag: _ }) => Some("EnumTag"),
1014+
ValueContentRef::EnumVariant(EnumVariantBody {
1015+
arg: Some(_),
1016+
tag: _,
1017+
}) => Some("EnumVariant"),
1018+
ValueContentRef::ForeignId(_) => Some("ForeignId"),
1019+
ValueContentRef::SealingKey(_) => Some("SealingKey"),
1020+
ValueContentRef::CustomContract(_) => Some("CustomContract"),
1021+
ValueContentRef::Type(_) => Some("Type"),
1022+
_ => None,
10041023
}
10051024
}
10061025

core/src/eval/operation.rs

Lines changed: 24 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -3682,32 +3682,36 @@ impl<'ctxt, R: ImportResolver, C: Cache> VirtualMachine<'ctxt, R, C> {
36823682
}
36833683
}
36843684

3685-
// The enum tag returned by Typeof and Cast.
3685+
/// The enum tag returned by Typeof and Cast.
3686+
///
3687+
/// This function is a less precise version of `v.type_of()`, because `type_tag` has backward
3688+
/// compatibility guarantees to uphold. Instead of relying on
3689+
/// [crate::bytecode::value::NickelValue::type_of], it's safer to duplicate the logic here.
36863690
fn type_tag(v: &NickelValue) -> &'static str {
3687-
use crate::bytecode::value::{BodyTag, InlineValue, ValueTag};
3688-
// This is almost like `v.type_of()`, but there are a few subtle differences, and `type_tag`
3689-
// has backward compatibility guarantees to uphold. Instead of relying on `type_of`, it's safer
3690-
// to duplicate the logic here.
3691-
match v.tag() {
3692-
ValueTag::Pointer => match v.body_tag().unwrap() {
3693-
BodyTag::Number => "Number",
3694-
BodyTag::Array => "Array",
3695-
BodyTag::Record => "Record",
3696-
BodyTag::String => "String",
3697-
BodyTag::Label => "Label",
3698-
BodyTag::EnumVariant => "Enum",
3699-
BodyTag::ForeignId => "ForeignId",
3700-
BodyTag::CustomContract => "CustomContract",
3701-
BodyTag::Type => "Type",
3702-
_ => "Other",
3703-
},
3704-
// unwrap(): if the body tag is inline, `v` must be an inline value
3705-
ValueTag::Inline => match v.as_inline().unwrap() {
3691+
use crate::bytecode::value::InlineValue;
3692+
3693+
match v.content_ref() {
3694+
ValueContentRef::Inline(inline) => match inline {
37063695
InlineValue::True | InlineValue::False => "Bool",
37073696
InlineValue::Null => "Other",
37083697
InlineValue::EmptyArray => "Array",
37093698
InlineValue::EmptyRecord => "Record",
37103699
},
3700+
ValueContentRef::Number(_) => "Number",
3701+
ValueContentRef::Array(_) => "Array",
3702+
ValueContentRef::Record(_) => "Record",
3703+
ValueContentRef::String(_) => "String",
3704+
ValueContentRef::Term(term_body) => match term_body.0 {
3705+
Term::RecRecord(..) => "Record",
3706+
Term::Fun(..) | Term::Match { .. } => "Function",
3707+
_ => "Other",
3708+
},
3709+
ValueContentRef::Label(_) => "Label",
3710+
ValueContentRef::EnumVariant(_) => "Enum",
3711+
ValueContentRef::ForeignId(_) => "ForeignId",
3712+
ValueContentRef::CustomContract(_) => "CustomContract",
3713+
ValueContentRef::Type(_) => "Type",
3714+
_ => "Other",
37113715
}
37123716
}
37133717

0 commit comments

Comments
 (0)