diff --git a/crates/nargo_cli/tests/test_data/option/Nargo.toml b/crates/nargo_cli/tests/test_data/option/Nargo.toml index 5a02ffe4729..2248e9c06dd 100644 --- a/crates/nargo_cli/tests/test_data/option/Nargo.toml +++ b/crates/nargo_cli/tests/test_data/option/Nargo.toml @@ -1,5 +1,6 @@ [package] +name = "option" authors = [""] compiler_version = "0.7.0" -[dependencies] \ No newline at end of file +[dependencies] diff --git a/crates/noirc_evaluator/src/ssa_refactor/acir_gen/mod.rs b/crates/noirc_evaluator/src/ssa_refactor/acir_gen/mod.rs index da8409431ce..77467c116d9 100644 --- a/crates/noirc_evaluator/src/ssa_refactor/acir_gen/mod.rs +++ b/crates/noirc_evaluator/src/ssa_refactor/acir_gen/mod.rs @@ -998,7 +998,7 @@ impl Context { } Intrinsic::ArrayLen => { let len = match self.convert_value(arguments[0], dfg) { - AcirValue::Var(_, _) => unreachable!("Non-array passed to array.len() method"), + AcirValue::Var(_, _) => unreachable!("Non-array passed to array.len() method"), AcirValue::Array(values) => (values.len() as u128).into(), AcirValue::DynamicArray(array) => (array.len as u128).into(), }; diff --git a/noir_stdlib/src/option.nr b/noir_stdlib/src/option.nr index 95cf8564a21..cdd115663ea 100644 --- a/noir_stdlib/src/option.nr +++ b/noir_stdlib/src/option.nr @@ -4,27 +4,33 @@ struct Option { } impl Option { + /// Constructs a None value fn none() -> Self { Self { _is_some: false, value: crate::unsafe::zeroed() } } + /// Constructs a Some wrapper around the given value fn some(value: T) -> Self { Self { _is_some: true, value } } + /// True if this Option is None fn is_none(self) -> bool { !self._is_some } + /// True if this Option is Some fn is_some(self) -> bool { self._is_some } + /// Asserts `self.is_some()` and returns the wrapped value. fn unwrap(self) -> T { assert(self._is_some); self.value } + /// Returns the wrapped value if `self.is_some()`. Otherwise, returns the given default value. fn unwrap_or(self, default: T) -> T { if self._is_some { self.value @@ -33,6 +39,8 @@ impl Option { } } + /// Returns the wrapped value if `self.is_some()`. Otherwise, calls the given function to return + /// a default value. fn unwrap_or_else(self, default: fn() -> T) -> T { if self._is_some { self.value @@ -41,6 +49,7 @@ impl Option { } } + /// If self is `Some(x)`, this returns `Some(f(x))`. Otherwise, this returns `None`. fn map(self, f: fn(T) -> U) -> Option { if self._is_some { Option::some(f(self.value)) @@ -49,6 +58,7 @@ impl Option { } } + /// If self is `Some(x)`, this returns `f(x)`. Otherwise, this returns the given default value. fn map_or(self, default: U, f: fn(T) -> U) -> U { if self._is_some { f(self.value) @@ -57,6 +67,7 @@ impl Option { } } + /// If self is `Some(x)`, this returns `f(x)`. Otherwise, this returns `default()`. fn map_or_else(self, default: fn() -> U, f: fn(T) -> U) -> U { if self._is_some { f(self.value) @@ -65,6 +76,7 @@ impl Option { } } + /// Returns None if self is None. Otherwise, this returns `other`. fn and(self, other: Self) -> Self { if self.is_none() { Option::none() @@ -73,6 +85,10 @@ impl Option { } } + /// If self is None, this returns None. Otherwise, this calls the given function + /// with the Some value contained within self, and returns the result of that call. + /// + /// In some languages this function is called `flat_map` or `bind`. fn and_then(self, f: fn(T) -> Option) -> Option { if self._is_some { f(self.value) @@ -81,6 +97,7 @@ impl Option { } } + /// If self is Some, return self. Otherwise, return `other`. fn or(self, other: Self) -> Self { if self._is_some { self @@ -89,7 +106,8 @@ impl Option { } } - fn or_else(self, default: fn() -> Option) -> Option { + /// If self is Some, return self. Otherwise, return `default()`. + fn or_else(self, default: fn() -> Self) -> Self { if self._is_some { self } else { @@ -97,6 +115,8 @@ impl Option { } } + // If only one of the two Options is Some, return that option. + // Otherwise, if both options are Some or both are None, None is returned. fn xor(self, other: Self) -> Self { if self._is_some { if other._is_some { @@ -110,4 +130,28 @@ impl Option { Option::none() } } + + /// Returns `Some(x)` if self is `Some(x)` and `predicate(x)` is true. + /// Otherwise, this returns `None` + fn filter(self, predicate: fn(T) -> bool) -> Self { + if self._is_some { + if predicate(self.value) { + self + } else { + None + } + } else { + None + } + } + + /// Flattens an Option> into a Option. + /// This returns None if the outer Option is None. Otherwise, this returns the inner Option. + fn flatten(option: Option>) -> Option { + if option._is_some { + option.value + } else { + None + } + } }