From 26d5299bbdbb38855c5ae8d9f342cb43015765b3 Mon Sep 17 00:00:00 2001 From: Kai Schmidt Date: Wed, 12 Jun 2024 11:52:49 -0700 Subject: [PATCH] add by inverses --- src/algorithm/invert.rs | 42 +++++++++++++++++++++++++++++++++++++---- src/check.rs | 10 ++++++++++ tests/units.ua | 7 ++++++- todo.md | 1 - 4 files changed, 54 insertions(+), 6 deletions(-) diff --git a/src/algorithm/invert.rs b/src/algorithm/invert.rs index fd7fe5f20..0eede8774 100644 --- a/src/algorithm/invert.rs +++ b/src/algorithm/invert.rs @@ -11,7 +11,7 @@ use ecow::{eco_vec, EcoString, EcoVec}; use regex::Regex; use crate::{ - check::{instrs_signature, instrs_signature_no_temp}, + check::{instrs_clean_signature, instrs_signature, instrs_signature_no_temp}, primitive::{ImplPrimitive, Primitive}, Assembly, BindingKind, Compiler, FmtInstrs, Function, FunctionId, Instr, Signature, Span, SysOp, TempStack, Uiua, UiuaResult, Value, @@ -1349,7 +1349,41 @@ fn invert_temp_pattern<'a>( comp: &mut Compiler, ) -> Option<(&'a [Instr], EcoVec)> { // Push temp - if let Some((input, instr, inner, end_instr, _)) = try_push_temp_wrap(input) { + if let Some((input, instr, inner, end_instr, depth)) = try_push_temp_wrap(input) { + // By-inverse + if let [Instr::Prim(Primitive::Dup, dup_span)] = inner { + for len in 1..=input.len() { + for mid in 0..len { + let before = &input[..mid]; + if instrs_clean_signature(before).map_or(true, |sig| sig != (0, 0)) { + continue; + }; + let instrs = &input[mid..len]; + let Some(sig) = instrs_clean_signature(instrs) else { + continue; + }; + if sig.args != depth + 1 { + continue; + } + for pat in ON_INVERT_PATTERNS { + if let Some((after, on_inv)) = pat.invert_extract(instrs, comp) { + if after.is_empty() { + let mut instrs = eco_vec![ + instr.clone(), + Instr::Prim(Primitive::Dup, *dup_span), + end_instr.clone(), + Instr::Prim(Primitive::Flip, *dup_span), + ]; + instrs.extend(on_inv); + instrs.extend_from_slice(before); + return Some((&input[len..], instrs)); + } + } + } + } + } + } + // Normal inverse let mut instrs = invert_instrs(inner, comp)?; instrs.insert(0, instr.clone()); instrs.push(end_instr.clone()); @@ -1369,7 +1403,7 @@ fn invert_temp_pattern<'a>( continue; } for pat in ON_INVERT_PATTERNS { - if let Some((after, pseudo_inv)) = pat.invert_extract(after, comp) { + if let Some((after, on_inv)) = pat.invert_extract(after, comp) { if let Some(after_inv) = invert_instrs(after, comp) { let mut instrs = eco_vec![start_instr.clone()]; @@ -1385,7 +1419,7 @@ fn invert_temp_pattern<'a>( instrs.extend_from_slice(before); - instrs.extend(pseudo_inv); + instrs.extend(on_inv); instrs.push(end_instr.clone()); return Some((input, instrs)); diff --git a/src/check.rs b/src/check.rs index 835bbf199..acb7ba14b 100644 --- a/src/check.rs +++ b/src/check.rs @@ -34,6 +34,16 @@ pub(crate) fn instrs_signature(instrs: &[Instr]) -> Result Option { + let (sig, temps) = instrs_all_signatures(instrs).ok()?; + if temps.iter().any(|&sig| sig != (0, 0)) { + return None; + } + Some(sig) +} + pub(crate) fn instrs_temp_signatures( instrs: &[Instr], ) -> Result<[Signature; TempStack::CARDINALITY], SigCheckError> { diff --git a/tests/units.ua b/tests/units.ua index 177df4d75..89220d454 100644 --- a/tests/units.ua +++ b/tests/units.ua @@ -410,7 +410,7 @@ F ← +@A ⊟. ⍤⟜≍: 3 °°+ 1 2 ⍤⟜≍: 3 °°°°°°+ 1 2 -# Pseudo inverses +# On-inverses ⍤⟜≍: [3 2] [°⟜+ 3 5] ⍤⟜≍: [3 2] [°⟜× 3 6] ⍤⟜≍: [3 8] [°⟜- 3 5] @@ -420,6 +420,11 @@ F ← +@A ⊟. ⍤⟜≍: [3 5] [°⟜↥ 3 5] ⍤⟜≍: [1_2 3_4] [°⟜⊂ 1_2 1_2_3_4] +# By-inverses +⍤⟜≍: [3 5] [°⊸+ 8 5] +⍤⟜≍: [3 5] [°⊸× 15 5] +⍤⟜≍: [3 5] [°⊸(+?) 8 5] + F ← ×2+1 ⍤⟜≍: [1 4] [°⟜(F+) ⟜(F+) 1 4] diff --git a/todo.md b/todo.md index 63cf8b6da..68a561382 100644 --- a/todo.md +++ b/todo.md @@ -1,7 +1,6 @@ # Uiua Todo - 0.12 - - by inverses - `setinv` on and by inverses - Document on and by inverses - Pervasive switch functions and `repeat`