Skip to content

Commit

Permalink
fix some bugs in array/uasm
Browse files Browse the repository at this point in the history
  • Loading branch information
kaikalii committed Nov 28, 2024
1 parent f418165 commit a535e9d
Show file tree
Hide file tree
Showing 4 changed files with 117 additions and 151 deletions.
74 changes: 59 additions & 15 deletions src/array.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1411,24 +1411,68 @@ trait ArrayValueSer: ArrayValue + fmt::Debug {
}
}

macro_rules! array_value_ser {
($ty:ty) => {
impl ArrayValueSer for $ty {
type Scalar = $ty;
type Collection = CowSlice<$ty>;
fn make_collection(data: CowSlice<Self>) -> Self::Collection {
data
}
fn make_data(collection: Self::Collection) -> CowSlice<Self> {
collection
}
impl ArrayValueSer for u8 {
type Scalar = u8;
type Collection = CowSlice<u8>;
fn make_collection(data: CowSlice<Self>) -> Self::Collection {
data
}
fn make_data(collection: Self::Collection) -> CowSlice<Self> {
collection
}
}

#[derive(Debug, Clone, Serialize, Deserialize)]
enum BoxCollection {
#[serde(rename = "empty_boxes")]
Empty([Boxed; 0]),
#[serde(untagged)]
List(CowSlice<Boxed>),
}

impl ArrayValueSer for Boxed {
type Scalar = Boxed;
type Collection = BoxCollection;
fn make_collection(data: CowSlice<Self>) -> Self::Collection {
if data.is_empty() {
BoxCollection::Empty([])
} else {
BoxCollection::List(data)
}
};
}
fn make_data(collection: Self::Collection) -> CowSlice<Self> {
match collection {
BoxCollection::Empty(_) => CowSlice::new(),
BoxCollection::List(data) => data,
}
}
}

#[derive(Debug, Clone, Serialize, Deserialize)]
enum ComplexCollection {
#[serde(rename = "empty_complex")]
Empty([Complex; 0]),
#[serde(untagged)]
List(CowSlice<Complex>),
}

array_value_ser!(u8);
array_value_ser!(Boxed);
array_value_ser!(Complex);
impl ArrayValueSer for Complex {
type Scalar = Complex;
type Collection = ComplexCollection;
fn make_collection(data: CowSlice<Self>) -> Self::Collection {
if data.is_empty() {
ComplexCollection::Empty([])
} else {
ComplexCollection::List(data)
}
}
fn make_data(collection: Self::Collection) -> CowSlice<Self> {
match collection {
ComplexCollection::Empty(_) => CowSlice::new(),
ComplexCollection::List(data) => data,
}
}
}

impl ArrayValueSer for f64 {
type Scalar = F64Rep;
Expand Down
71 changes: 41 additions & 30 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -264,41 +264,52 @@ mod tests {

#[test]
#[cfg(feature = "native_sys")]
fn errors() {
fn error_dont_crash() {
use super::*;
for path in test_files(|path| {
(path.file_stem().unwrap())
.to_string_lossy()
.contains("error")
}) {
let mut code = std::fs::read_to_string(&path).unwrap();
if code.contains('\r') {
code = code.replace('\r', "");
}
for section in code.split("\n\n") {
let mut env = Uiua::with_native_sys();
let mut comp = Compiler::new();
let res = comp
.load_str_src(section, &path)
.and_then(|comp| env.run_asm(comp.finish()));
if res.is_ok()
&& comp
.take_diagnostics()
.into_iter()
.filter(|diag| diag.kind > DiagnosticKind::Advice)
.count()
== 0
{
panic!(
"Test succeeded when it should have failed in {}:\n{}",
path.display(),
section
);
}
let path = Path::new("tests_special/error.ua");
let mut code = std::fs::read_to_string(path).unwrap();
if code.contains('\r') {
code = code.replace('\r', "");
}
for section in code.split("\n\n") {
let mut env = Uiua::with_native_sys();
let mut comp = Compiler::new();
let res = comp
.load_str_src(section, path)
.and_then(|comp| env.run_asm(comp.finish()));
if res.is_ok()
&& comp
.take_diagnostics()
.into_iter()
.filter(|diag| diag.kind > DiagnosticKind::Advice)
.count()
== 0
{
panic!(
"Test succeeded when it should have failed in {}:\n{}",
path.display(),
section
);
}
}
}

#[test]
#[cfg(feature = "native_sys")]
fn assembly_round_trip() {
use super::*;
let path = Path::new("tests_special/uasm.ua");
let mut comp = Compiler::new();
comp.load_file(path).unwrap();
let asm = comp.finish();
let root = asm.root.clone();
let uasm = asm.to_uasm();
let asm = Assembly::from_uasm(&uasm).unwrap();
assert_eq!(asm.root, root);
let mut env = Uiua::with_native_sys();
env.run_asm(asm).unwrap();
}

#[test]
fn lsp_spans() {
use super::*;
Expand Down
22 changes: 17 additions & 5 deletions src/tree.rs
Original file line number Diff line number Diff line change
Expand Up @@ -452,8 +452,8 @@ impl Node {
f: impl FnOnce(&mut Node) -> T + Copy,
) -> Option<T> {
let mut this_node = match target {
Some(i) => &asm.functions[i],
None => &*node,
Some(i) => asm.functions[i].inner(),
None => node.inner(),
};
if let Some(i) = sub {
this_node = this_node.get(i)?;
Expand All @@ -470,18 +470,30 @@ impl Node {
Node::Call(func, _) => recurse(Some(func.index), None, node, asm, f),
_ => {
let mut node = match target {
Some(i) => &mut asm.functions.make_mut()[i],
None => node,
Some(i) => asm.functions.make_mut()[i].inner_mut(),
None => node.inner_mut(),
};
if let Some(i) = sub {
node = node.as_mut_slice().get_mut(i)?;
node = node.as_mut_slice().get_mut(i)?.inner_mut();
}
Some(f(node))
}
}
}
recurse(None, None, self, asm, f)
}
fn inner(&self) -> &Node {
match self {
Node::TrackCaller(inner) | Node::NoInline(inner) => inner,
node => node,
}
}
fn inner_mut(&mut self) -> &mut Node {
match self {
Node::TrackCaller(inner) | Node::NoInline(inner) => Arc::make_mut(inner),
node => node,
}
}
pub(crate) fn hash_with_span(&self, hasher: &mut impl Hasher) {
self.hash(hasher);
if let Some(span) = self.span() {
Expand Down
101 changes: 0 additions & 101 deletions tests/error.ua

This file was deleted.

0 comments on commit a535e9d

Please sign in to comment.