From 96bcf594e4ac1d6126fd79cf3b19ad3f417edd9d Mon Sep 17 00:00:00 2001 From: myfreess Date: Wed, 22 Apr 2026 12:59:20 +0800 Subject: [PATCH 01/10] promote --- .github/workflows/check.yaml | 2 +- .gitignore | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/check.yaml b/.github/workflows/check.yaml index 4905e73..3ca4b33 100644 --- a/.github/workflows/check.yaml +++ b/.github/workflows/check.yaml @@ -36,7 +36,7 @@ jobs: - name: install module dependencies run: | moon update - moon install + moon check --deny-warn - name: moon check run: moon check --deny-warn diff --git a/.gitignore b/.gitignore index 70934a7..92fd93c 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,6 @@ target/ .mooncakes/ +_build/ .DS_Store .vscode/ -.moonagent/ \ No newline at end of file +.moonagent/ From 1b21d5ac60192bf2fc4dded67b3fe3c89bb6f656 Mon Sep 17 00:00:00 2001 From: myfreess Date: Wed, 22 Apr 2026 13:00:05 +0800 Subject: [PATCH 02/10] fix unnecessary annotations --- src/algorithms/capture.mbt | 16 +++++------ src/algorithms/compact.mbt | 58 +++++++++++++++++++------------------- src/algorithms/hook.mbt | 2 +- src/algorithms/type.mbt | 8 +++--- src/core.mbt | 8 +++--- 5 files changed, 46 insertions(+), 46 deletions(-) diff --git a/src/algorithms/capture.mbt b/src/algorithms/capture.mbt index 5ff0389..6f8f632 100644 --- a/src/algorithms/capture.mbt +++ b/src/algorithms/capture.mbt @@ -79,7 +79,7 @@ pub impl DiffHook for Capture with equal( new_index : Int, len : Int, ) -> Result[Unit, Error] { - self.0.push(DiffOp::Equal(old_index~, new_index~, len~)) + self.0.push(Equal(old_index~, new_index~, len~)) Ok(()) } @@ -95,7 +95,7 @@ pub impl DiffHook for Capture with delete( old_len : Int, new_index : Int, ) -> Result[Unit, Error] { - self.0.push(DiffOp::Delete(old_index~, old_len~, new_index~)) + self.0.push(Delete(old_index~, old_len~, new_index~)) Ok(()) } @@ -111,7 +111,7 @@ pub impl DiffHook for Capture with insert( new_index : Int, new_len : Int, ) -> Result[Unit, Error] { - self.0.push(DiffOp::Insert(old_index~, new_index~, new_len~)) + self.0.push(Insert(old_index~, new_index~, new_len~)) Ok(()) } @@ -129,7 +129,7 @@ pub impl DiffHook for Capture with replace( new_index : Int, new_len : Int, ) -> Result[Unit, Error] { - self.0.push(DiffOp::Replace(old_index~, old_len~, new_index~, new_len~)) + self.0.push(Replace(old_index~, old_len~, new_index~, new_len~)) Ok(()) } @@ -160,13 +160,13 @@ pub fn Capture::sort(self : Capture) -> Unit { /// Helper function to extract sorting keys from operations fn get_old_new_index(op : DiffOp) -> (Int, Int)? { match op { - DiffOp::Equal(old_index~, new_index~, len=_) => + Equal(old_index~, new_index~, len=_) => Some((old_index, new_index)) - DiffOp::Delete(old_index~, old_len=_, new_index~) => + Delete(old_index~, old_len=_, new_index~) => Some((old_index, new_index)) - DiffOp::Insert(old_index~, new_index~, new_len=_) => + Insert(old_index~, new_index~, new_len=_) => Some((old_index, new_index)) - DiffOp::Replace(old_index~, old_len=_, new_index~, new_len=_) => + Replace(old_index~, old_len=_, new_index~, new_len=_) => Some((old_index, new_index)) } } diff --git a/src/algorithms/compact.mbt b/src/algorithms/compact.mbt index c440b75..ca39509 100644 --- a/src/algorithms/compact.mbt +++ b/src/algorithms/compact.mbt @@ -75,7 +75,7 @@ pub impl[D : DiffHook, T : Eq] DiffHook for Compact[D, T] with equal( new_index, len, ) -> Result[Unit, Error] { - self.ops.push(DiffOp::Equal(old_index~, new_index~, len~)) + self.ops.push(Equal(old_index~, new_index~, len~)) Ok(()) } @@ -87,7 +87,7 @@ pub impl[D : DiffHook, T : Eq] DiffHook for Compact[D, T] with delete( old_len, new_index, ) -> Result[Unit, Error] { - self.ops.push(DiffOp::Delete(old_index~, old_len~, new_index~)) + self.ops.push(Delete(old_index~, old_len~, new_index~)) Ok(()) } @@ -99,7 +99,7 @@ pub impl[D : DiffHook, T : Eq] DiffHook for Compact[D, T] with insert( new_index, new_len, ) -> Result[Unit, Error] { - self.ops.push(DiffOp::Insert(old_index~, new_index~, new_len~)) + self.ops.push(Insert(old_index~, new_index~, new_len~)) Ok(()) } @@ -149,7 +149,7 @@ pub fn[T : Eq] cleanup_diff_ops( while pointer < ops.length() { let op = ops.get(pointer).unwrap() match op { - DiffOp::Delete(..) => { + Delete(..) => { // Shift delete operations up and down to enable merging pointer = shift_diff_ops_up(ops, old, new, pointer) pointer = shift_diff_ops_down(ops, old, new, pointer) @@ -164,7 +164,7 @@ pub fn[T : Eq] cleanup_diff_ops( while pointer < ops.length() { let op = ops.get(pointer).unwrap() match op { - DiffOp::Insert(..) => { + Insert(..) => { // Shift insert operations up and down to enable merging pointer = shift_diff_ops_up(ops, old, new, pointer) pointer = shift_diff_ops_down(ops, old, new, pointer) @@ -201,28 +201,28 @@ pub fn[T : Eq] shift_diff_ops_up( let this_op = ops[pointer] match (this_op, prev_op) { // Rule 1: Swap insert/delete to group similar operations - (DiffOp::Insert(..), DiffOp::Delete(..)) - | (DiffOp::Delete(..), DiffOp::Insert(..)) => { + (Insert(..), Delete(..)) + | (Delete(..), Insert(..)) => { ops.swap(pointer - 1, pointer) pointer -= 1 } // Rule 2: Merge adjacent insert operations - (DiffOp::Insert(..), DiffOp::Insert(..)) => { + (Insert(..), Insert(..)) => { ops[pointer - 1].grow_right(this_op.new_range().len()) let _ = ops.remove(pointer) pointer -= 1 } // Rule 3: Merge adjacent delete operations - (DiffOp::Delete(..), DiffOp::Delete(..)) => { + (Delete(..), Delete(..)) => { ops[pointer - 1].grow_right(this_op.old_range().len()) let _ = ops.remove(pointer) pointer -= 1 } // Rule 4: Align insert with common suffix - (DiffOp::Insert(..), DiffOp::Equal(..)) => { + (Insert(..), Equal(..)) => { let suffix_len = common_suffix_len( new, prev_op.new_range(), @@ -232,7 +232,7 @@ pub fn[T : Eq] shift_diff_ops_up( if suffix_len > 0 { // Found common suffix - can shift operation match ops.get(pointer + 1) { - Some(DiffOp::Equal(..) as next_op) => next_op.grow_left(suffix_len) + Some(Equal(..) as next_op) => next_op.grow_left(suffix_len) _ => { // Create new Equal operation for common suffix let old_index = this_op.old_range().end - suffix_len @@ -240,7 +240,7 @@ pub fn[T : Eq] shift_diff_ops_up( let len = suffix_len ops.insert( pointer + 1, - DiffOp::Equal(old_index~, new_index~, len~), + Equal(old_index~, new_index~, len~), ) } } @@ -263,7 +263,7 @@ pub fn[T : Eq] shift_diff_ops_up( } // Rule 5: Align delete with common suffix - (DiffOp::Delete(..), DiffOp::Equal(..)) => { + (Delete(..), Equal(..)) => { let suffix_len = common_suffix_len( old, prev_op.old_range(), @@ -273,7 +273,7 @@ pub fn[T : Eq] shift_diff_ops_up( if suffix_len > 0 { // Found common suffix - can shift operation match ops.get(pointer + 1) { - Some(DiffOp::Equal(..) as next_op) => next_op.grow_left(suffix_len) + Some(Equal(..) as next_op) => next_op.grow_left(suffix_len) _ => { // Create new Equal operation for common suffix let old_index = this_op.old_range().end - suffix_len @@ -281,7 +281,7 @@ pub fn[T : Eq] shift_diff_ops_up( let len = suffix_len ops.insert( pointer + 1, - DiffOp::Equal(old_index~, new_index~, len~), + Equal(old_index~, new_index~, len~), ) } } @@ -325,28 +325,28 @@ pub fn[T : Eq] shift_diff_ops_down( let this_op = ops[pointer] match (this_op, next_op) { // Rule 1: Swap insert/delete operations - (DiffOp::Insert(..), DiffOp::Delete(..)) - | (DiffOp::Delete(..), DiffOp::Insert(..)) => { + (Insert(..), Delete(..)) + | (Delete(..), Insert(..)) => { ops.swap(pointer, pointer + 1) pointer += 1 } // Rule 2: Merge adjacent insert operations - (DiffOp::Insert(..), DiffOp::Insert(..)) => { + (Insert(..), Insert(..)) => { this_op.grow_right(next_op.new_range().len()) let _ = ops.remove(pointer + 1) } // Rule 3: Merge adjacent delete operations - (DiffOp::Delete(..), DiffOp::Delete(..)) => { + (Delete(..), Delete(..)) => { this_op.grow_right(next_op.old_range().len()) let _ = ops.remove(pointer + 1) } // Rule 4: Align insert with common prefix - (DiffOp::Insert(..), DiffOp::Equal(..)) => { + (Insert(..), Equal(..)) => { let prefix_len = common_prefix_len( new, next_op.new_range(), @@ -356,13 +356,13 @@ pub fn[T : Eq] shift_diff_ops_down( if prefix_len > 0 { // Found common prefix - can shift operation match ops.get(pointer - 1) { - Some(DiffOp::Equal(..) as prev_op) => prev_op.grow_right(prefix_len) + Some(Equal(..) as prev_op) => prev_op.grow_right(prefix_len) _ => { // Create new Equal operation for common prefix let old_index = this_op.old_range().start let new_index = next_op.new_range().start let len = prefix_len - ops.insert(pointer, DiffOp::Equal(old_index~, new_index~, len~)) + ops.insert(pointer, Equal(old_index~, new_index~, len~)) pointer += 1 } } @@ -385,7 +385,7 @@ pub fn[T : Eq] shift_diff_ops_down( } // Rule 5: Align delete with common prefix - (DiffOp::Delete(..), DiffOp::Equal(..)) => { + (Delete(..), Equal(..)) => { let prefix_len = common_prefix_len( old, next_op.old_range(), @@ -395,13 +395,13 @@ pub fn[T : Eq] shift_diff_ops_down( if prefix_len > 0 { // Found common prefix - can shift operation match ops.get(pointer - 1) { - Some(DiffOp::Equal(..) as prev_op) => prev_op.grow_right(prefix_len) + Some(Equal(..) as prev_op) => prev_op.grow_right(prefix_len) _ => { // Create new Equal operation for common prefix let old_index = this_op.old_range().start let new_index = this_op.new_range().start let len = prefix_len - ops.insert(pointer, DiffOp::Equal(old_index~, new_index~, len~)) + ops.insert(pointer, Equal(old_index~, new_index~, len~)) pointer += 1 } } @@ -438,13 +438,13 @@ pub fn[T : Eq] shift_diff_ops_down( pub fn[D, T] Compact::sort(self : Compact[D, T]) -> Unit { fn get_old_new_index(op : DiffOp) -> (Int, Int)? { match op { - DiffOp::Equal(old_index~, new_index~, len=_) => + Equal(old_index~, new_index~, len=_) => Some((old_index, new_index)) - DiffOp::Delete(old_index~, old_len=_, new_index~) => + Delete(old_index~, old_len=_, new_index~) => Some((old_index, new_index)) - DiffOp::Insert(old_index~, new_index~, new_len=_) => + Insert(old_index~, new_index~, new_len=_) => Some((old_index, new_index)) - DiffOp::Replace(old_index~, old_len=_, new_index~, new_len=_) => + Replace(old_index~, old_len=_, new_index~, new_len=_) => Some((old_index, new_index)) } } diff --git a/src/algorithms/hook.mbt b/src/algorithms/hook.mbt index 291999d..35cdd91 100644 --- a/src/algorithms/hook.mbt +++ b/src/algorithms/hook.mbt @@ -89,7 +89,7 @@ pub(all) struct NoFinishHook[D] { ///| /// Creates a new `NoFinishHook`. pub fn[D] NoFinishHook::new(d : D) -> NoFinishHook[D] { - NoFinishHook::{ d, } + { d, } } ///| diff --git a/src/algorithms/type.mbt b/src/algorithms/type.mbt index 4858366..1cb8371 100644 --- a/src/algorithms/type.mbt +++ b/src/algorithms/type.mbt @@ -135,22 +135,22 @@ fn DiffOp::adjust( } match self { - DiffOp::Equal(old_index~, new_index~, len~) as op => { + Equal(old_index~, new_index~, len~) as op => { op.old_index = modify(old_index, adjust_offset) op.new_index = modify(new_index, adjust_offset) op.len = modify(len, adjust_len) } - DiffOp::Delete(old_index~, old_len~, new_index~) as op => { + Delete(old_index~, old_len~, new_index~) as op => { op.old_index = modify(old_index, adjust_offset) op.old_len = modify(old_len, adjust_len) op.new_index = modify(new_index, adjust_offset) } - DiffOp::Insert(old_index~, new_index~, new_len~) as op => { + Insert(old_index~, new_index~, new_len~) as op => { op.old_index = modify(old_index, adjust_offset) op.new_index = modify(new_index, adjust_offset) op.new_len = modify(new_len, adjust_len) } - DiffOp::Replace(old_index~, old_len~, new_index~, new_len~) as op => { + Replace(old_index~, old_len~, new_index~, new_len~) as op => { op.old_index = modify(old_index, adjust_offset) op.old_len = modify(old_len, adjust_len) op.new_index = modify(new_index, adjust_offset) diff --git a/src/core.mbt b/src/core.mbt index ffd2569..ccf701b 100644 --- a/src/core.mbt +++ b/src/core.mbt @@ -52,28 +52,28 @@ pub fn[T : Show] print_diff_ops( ) -> Unit { for op in ops { match op { - DiffOp::Equal(old_index~, new_index=_, len~) => { + Equal(old_index~, new_index=_, len~) => { let mut i = 0 while i < len { println(" \{old[old_index + i]}") i += 1 } } - DiffOp::Delete(old_index~, old_len~, new_index=_) => { + Delete(old_index~, old_len~, new_index=_) => { let mut i = 0 while i < old_len { println(" - \{old[old_index + i]}") i += 1 } } - DiffOp::Insert(old_index=_, new_index~, new_len~) => { + Insert(old_index=_, new_index~, new_len~) => { let mut i = 0 while i < new_len { println(" + \{new[new_index + i]}") i += 1 } } - DiffOp::Replace(old_index~, old_len~, new_index~, new_len~) => { + Replace(old_index~, old_len~, new_index~, new_len~) => { let mut i = 0 while i < old_len { println(" - \{old[old_index + i]}") From c7a5d27a07321baa860d1b742a4bcc4b622fce19 Mon Sep 17 00:00:00 2001 From: myfreess Date: Wed, 22 Apr 2026 13:00:14 +0800 Subject: [PATCH 03/10] replace deprecated boolean negation --- src/algorithms/myers.mbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/algorithms/myers.mbt b/src/algorithms/myers.mbt index ad18f4a..1ef6a1a 100644 --- a/src/algorithms/myers.mbt +++ b/src/algorithms/myers.mbt @@ -208,7 +208,7 @@ fn[T : Eq] find_middle_snake( vb[k] = x // Check if paths have met - if not(odd) && (k - delta).abs() <= d { + if !odd && (k - delta).abs() <= d { if vb[k] + vf[-(k - delta)] >= n { return Some((n - x + old_range.start, m - y + new_range.start)) } From 9331ee4a4fa43473856c36efa4d495422cd877a5 Mon Sep 17 00:00:00 2001 From: myfreess Date: Wed, 22 Apr 2026 13:02:36 +0800 Subject: [PATCH 04/10] replace deprecated show derives --- src/algorithms/range.mbt | 7 ++++++- src/algorithms/type.mbt | 24 +++++++++++++++++++++++- 2 files changed, 29 insertions(+), 2 deletions(-) diff --git a/src/algorithms/range.mbt b/src/algorithms/range.mbt index f8c7549..59293cb 100644 --- a/src/algorithms/range.mbt +++ b/src/algorithms/range.mbt @@ -27,7 +27,12 @@ pub(all) struct Range { mut start : Int /// Exclusive end index of the range mut end : Int -} derive(Show) +} + +///| +pub impl Show for Range with output(self, logger) { + logger.write_string("{start: \{self.start}, end: \{self.end}}") +} ///| /// Creates a new Range with specified start and end indices diff --git a/src/algorithms/type.mbt b/src/algorithms/type.mbt index 1cb8371..82bd2b6 100644 --- a/src/algorithms/type.mbt +++ b/src/algorithms/type.mbt @@ -14,7 +14,29 @@ pub(all) enum DiffOp { mut new_index~ : Int, mut new_len~ : Int ) -} derive(Eq, Show, Hash, Compare) +} derive(Eq, Hash, Compare) + +///| +pub impl Show for DiffOp with output(self, logger) { + match self { + Equal(old_index~, new_index~, len~) => + logger.write_string( + "Equal(old_index=\{old_index}, new_index=\{new_index}, len=\{len})", + ) + Delete(old_index~, old_len~, new_index~) => + logger.write_string( + "Delete(old_index=\{old_index}, old_len=\{old_len}, new_index=\{new_index})", + ) + Insert(old_index~, new_index~, new_len~) => + logger.write_string( + "Insert(old_index=\{old_index}, new_index=\{new_index}, new_len=\{new_len})", + ) + Replace(old_index~, old_len~, new_index~, new_len~) => + logger.write_string( + "Replace(old_index=\{old_index}, old_len=\{old_len}, new_index=\{new_index}, new_len=\{new_len})", + ) + } +} ///| /// Applies the given `DiffOp` to a `DiffHook`. From 15bbe469723448a8688c56bf1ac15151230d59f6 Mon Sep 17 00:00:00 2001 From: myfreess Date: Wed, 22 Apr 2026 13:02:49 +0800 Subject: [PATCH 05/10] declare core package imports --- src/algorithms/moon.pkg.json | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/algorithms/moon.pkg.json b/src/algorithms/moon.pkg.json index 84d8856..4a83d8d 100644 --- a/src/algorithms/moon.pkg.json +++ b/src/algorithms/moon.pkg.json @@ -1,3 +1,13 @@ { + "import": [ + { + "path": "moonbitlang/core/cmp", + "alias": "cmp" + }, + { + "path": "moonbitlang/core/hashmap", + "alias": "hashmap" + } + ], "warn-list": "+a" } From a8bd4eb9ee18ac49eb018a939268bf710eb258b5 Mon Sep 17 00:00:00 2001 From: myfreess Date: Wed, 22 Apr 2026 13:03:22 +0800 Subject: [PATCH 06/10] qualify algorithms API usage --- src/core.mbt | 38 +++++++++++++++++--------------------- 1 file changed, 17 insertions(+), 21 deletions(-) diff --git a/src/core.mbt b/src/core.mbt index ccf701b..b1763d6 100644 --- a/src/core.mbt +++ b/src/core.mbt @@ -1,38 +1,30 @@ -///| -/// Type aliases for core diff components -using @algorithms { - type Range, - type DiffOp, - type Replace, - type Capture, - type Compact, -} - ///| Computes the difference between two arrays of `T`. ///| /// Main entry point for standard diffing logic using Myers algorithm with `Replace` hook. -pub fn[T : Eq] diff(old : Array[T], new : Array[T]) -> Array[DiffOp] { - let d = Replace::new(Capture::new()) +pub fn[T : Eq] diff(old : Array[T], new : Array[T]) -> Array[@algorithms.DiffOp] { + let d = @algorithms.Replace::new(@algorithms.Capture::new()) let _ = @algorithms.Myers::diff( d, old, - Range::new(0, old.length()), + @algorithms.Range::new(0, old.length()), new, - Range::new(0, new.length()), + @algorithms.Range::new(0, new.length()), ) d.into_inner().into_ops() } ///| /// Computes the difference between two strings, character by character. -pub fn diff_str(old : String, new : String) -> Array[DiffOp] { +pub fn diff_str(old : String, new : String) -> Array[@algorithms.DiffOp] { diff(old.to_array(), new.to_array()) } ///| /// Computes the difference between two arrays of strings, line by line. -pub fn diff_line(old : Array[String], new : Array[String]) -> Array[DiffOp] { +pub fn diff_line(old : Array[String], new : Array[String]) -> Array[ + @algorithms.DiffOp, +] { diff(old, new) } @@ -48,7 +40,7 @@ pub fn[T : Eq + Show] print_diff_line(old : Array[T], new : Array[T]) -> Unit { pub fn[T : Show] print_diff_ops( old : Array[T], new : Array[T], - ops : Array[DiffOp], + ops : Array[@algorithms.DiffOp], ) -> Unit { for op in ops { match op { @@ -96,14 +88,18 @@ pub fn[T : Show] print_diff_ops( pub fn[T : Eq] diff_with_compact( old : Array[T], new : Array[T], -) -> Array[DiffOp] { - let d = Compact::new(Replace::new(Capture::new()), old, new) +) -> Array[@algorithms.DiffOp] { + let d = @algorithms.Compact::new( + @algorithms.Replace::new(@algorithms.Capture::new()), + old, + new, + ) let _ = @algorithms.Myers::diff( d, old, - Range::new(0, old.length()), + @algorithms.Range::new(0, old.length()), new, - Range::new(0, new.length()), + @algorithms.Range::new(0, new.length()), ) d.into_ops() } From 3633caa348a0d62bf6143e37545eefc09b9a6280 Mon Sep 17 00:00:00 2001 From: myfreess Date: Wed, 22 Apr 2026 13:03:43 +0800 Subject: [PATCH 07/10] moon fmt --- src/algorithms/capture.mbt | 9 +++------ src/algorithms/compact.mbt | 32 +++++++------------------------- src/algorithms/moon.pkg | 6 ++++++ src/algorithms/moon.pkg.json | 13 ------------- src/algorithms/myers.mbt | 6 ------ src/algorithms/patience.mbt | 1 - src/core.mbt | 12 ++++++++---- src/moon.pkg | 5 +++++ src/moon.pkg.json | 9 --------- 9 files changed, 29 insertions(+), 64 deletions(-) create mode 100644 src/algorithms/moon.pkg delete mode 100644 src/algorithms/moon.pkg.json create mode 100644 src/moon.pkg delete mode 100644 src/moon.pkg.json diff --git a/src/algorithms/capture.mbt b/src/algorithms/capture.mbt index 6f8f632..0196c18 100644 --- a/src/algorithms/capture.mbt +++ b/src/algorithms/capture.mbt @@ -160,12 +160,9 @@ pub fn Capture::sort(self : Capture) -> Unit { /// Helper function to extract sorting keys from operations fn get_old_new_index(op : DiffOp) -> (Int, Int)? { match op { - Equal(old_index~, new_index~, len=_) => - Some((old_index, new_index)) - Delete(old_index~, old_len=_, new_index~) => - Some((old_index, new_index)) - Insert(old_index~, new_index~, new_len=_) => - Some((old_index, new_index)) + Equal(old_index~, new_index~, len=_) => Some((old_index, new_index)) + Delete(old_index~, old_len=_, new_index~) => Some((old_index, new_index)) + Insert(old_index~, new_index~, new_len=_) => Some((old_index, new_index)) Replace(old_index~, old_len=_, new_index~, new_len=_) => Some((old_index, new_index)) } diff --git a/src/algorithms/compact.mbt b/src/algorithms/compact.mbt index ca39509..9a3dd14 100644 --- a/src/algorithms/compact.mbt +++ b/src/algorithms/compact.mbt @@ -123,7 +123,6 @@ pub impl[D : DiffHook, T : Eq] DiffHook for Compact[D, T] with finish(self) -> R // Step 3: Apply compacted operations to inner hook for op in self.ops { let _ = op.apply_to_hook(self.d) - } self.d.finish() } @@ -201,8 +200,7 @@ pub fn[T : Eq] shift_diff_ops_up( let this_op = ops[pointer] match (this_op, prev_op) { // Rule 1: Swap insert/delete to group similar operations - (Insert(..), Delete(..)) - | (Delete(..), Insert(..)) => { + (Insert(..), Delete(..)) | (Delete(..), Insert(..)) => { ops.swap(pointer - 1, pointer) pointer -= 1 } @@ -238,10 +236,7 @@ pub fn[T : Eq] shift_diff_ops_up( let old_index = this_op.old_range().end - suffix_len let new_index = this_op.new_range().end - suffix_len let len = suffix_len - ops.insert( - pointer + 1, - Equal(old_index~, new_index~, len~), - ) + ops.insert(pointer + 1, Equal(old_index~, new_index~, len~)) } } @@ -279,10 +274,7 @@ pub fn[T : Eq] shift_diff_ops_up( let old_index = this_op.old_range().end - suffix_len let new_index = this_op.new_range().end - suffix_len let len = suffix_len - ops.insert( - pointer + 1, - Equal(old_index~, new_index~, len~), - ) + ops.insert(pointer + 1, Equal(old_index~, new_index~, len~)) } } @@ -325,8 +317,7 @@ pub fn[T : Eq] shift_diff_ops_down( let this_op = ops[pointer] match (this_op, next_op) { // Rule 1: Swap insert/delete operations - (Insert(..), Delete(..)) - | (Delete(..), Insert(..)) => { + (Insert(..), Delete(..)) | (Delete(..), Insert(..)) => { ops.swap(pointer, pointer + 1) pointer += 1 } @@ -335,14 +326,12 @@ pub fn[T : Eq] shift_diff_ops_down( (Insert(..), Insert(..)) => { this_op.grow_right(next_op.new_range().len()) let _ = ops.remove(pointer + 1) - } // Rule 3: Merge adjacent delete operations (Delete(..), Delete(..)) => { this_op.grow_right(next_op.old_range().len()) let _ = ops.remove(pointer + 1) - } // Rule 4: Align insert with common prefix @@ -374,11 +363,9 @@ pub fn[T : Eq] shift_diff_ops_down( // Remove empty operations if next_op.is_empty() { let _ = ops.remove(pointer + 1) - } } else if ops[pointer + 1].is_empty() { let _ = ops.remove(pointer + 1) - } else { break } @@ -413,11 +400,9 @@ pub fn[T : Eq] shift_diff_ops_down( // Remove empty operations if next_op.is_empty() { let _ = ops.remove(pointer + 1) - } } else if ops[pointer + 1].is_empty() { let _ = ops.remove(pointer + 1) - } else { break } @@ -438,12 +423,9 @@ pub fn[T : Eq] shift_diff_ops_down( pub fn[D, T] Compact::sort(self : Compact[D, T]) -> Unit { fn get_old_new_index(op : DiffOp) -> (Int, Int)? { match op { - Equal(old_index~, new_index~, len=_) => - Some((old_index, new_index)) - Delete(old_index~, old_len=_, new_index~) => - Some((old_index, new_index)) - Insert(old_index~, new_index~, new_len=_) => - Some((old_index, new_index)) + Equal(old_index~, new_index~, len=_) => Some((old_index, new_index)) + Delete(old_index~, old_len=_, new_index~) => Some((old_index, new_index)) + Insert(old_index~, new_index~, new_len=_) => Some((old_index, new_index)) Replace(old_index~, old_len=_, new_index~, new_len=_) => Some((old_index, new_index)) } diff --git a/src/algorithms/moon.pkg b/src/algorithms/moon.pkg new file mode 100644 index 0000000..c328bf3 --- /dev/null +++ b/src/algorithms/moon.pkg @@ -0,0 +1,6 @@ +import { + "moonbitlang/core/cmp" @cmp, + "moonbitlang/core/hashmap" @hashmap, +} + +warnings = "+a" \ No newline at end of file diff --git a/src/algorithms/moon.pkg.json b/src/algorithms/moon.pkg.json deleted file mode 100644 index 4a83d8d..0000000 --- a/src/algorithms/moon.pkg.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "import": [ - { - "path": "moonbitlang/core/cmp", - "alias": "cmp" - }, - { - "path": "moonbitlang/core/hashmap", - "alias": "hashmap" - } - ], - "warn-list": "+a" -} diff --git a/src/algorithms/myers.mbt b/src/algorithms/myers.mbt index 1ef6a1a..325e31d 100644 --- a/src/algorithms/myers.mbt +++ b/src/algorithms/myers.mbt @@ -246,7 +246,6 @@ fn[T : Eq, D : DiffHook] divide_and_conquer( let common_prefix_len = common_prefix_len(old, old_range, new, new_range) if common_prefix_len > 0 { let _ = d.equal(old_range.start, new_range.start, common_prefix_len) - } old_range.start += common_prefix_len new_range.start += common_prefix_len @@ -266,11 +265,9 @@ fn[T : Eq, D : DiffHook] divide_and_conquer( } else if new_range.is_empty() { // New sequence empty - pure deletion let _ = d.delete(old_range.start, old_range.len(), new_range.start) - } else if old_range.is_empty() { // Old sequence empty - pure insertion let _ = d.insert(old_range.start, new_range.start, new_range.len()) - } else { // Step 4: Recursive case - find middle snake and divide match find_middle_snake(old, old_range, new, new_range, vf, vb) { @@ -282,13 +279,11 @@ fn[T : Eq, D : DiffHook] divide_and_conquer( // Recursively solve subproblems let _ = divide_and_conquer(d, old, old_a, new, new_a, vf, vb) let _ = divide_and_conquer(d, old, old_b, new, new_b, vf, vb) - } None => { // Fallback: treat as replace operation let _ = d.delete(old_range.start, old_range.len(), new_range.start) let _ = d.insert(old_range.start, new_range.start, new_range.len()) - } } } @@ -296,7 +291,6 @@ fn[T : Eq, D : DiffHook] divide_and_conquer( // Step 5: Report common suffix that was stripped earlier if common_suffix_len > 0 { let _ = d.equal(common_suffix.0, common_suffix.1, common_suffix_len) - } Ok(()) } diff --git a/src/algorithms/patience.mbt b/src/algorithms/patience.mbt index 4d11a06..2887098 100644 --- a/src/algorithms/patience.mbt +++ b/src/algorithms/patience.mbt @@ -143,7 +143,6 @@ impl[T : Eq, D : DiffHook] DiffHook for Patience[T, D] with equal( // Step 2: Report any common prefix found if self.old_current > a0 { let _ = self.d.equal(a0, b0, self.old_current - a0) - } // Step 3: Recursively diff the region between anchors diff --git a/src/core.mbt b/src/core.mbt index b1763d6..d5cd2e2 100644 --- a/src/core.mbt +++ b/src/core.mbt @@ -2,7 +2,10 @@ ///| /// Main entry point for standard diffing logic using Myers algorithm with `Replace` hook. -pub fn[T : Eq] diff(old : Array[T], new : Array[T]) -> Array[@algorithms.DiffOp] { +pub fn[T : Eq] diff( + old : Array[T], + new : Array[T], +) -> Array[@algorithms.DiffOp] { let d = @algorithms.Replace::new(@algorithms.Capture::new()) let _ = @algorithms.Myers::diff( d, @@ -22,9 +25,10 @@ pub fn diff_str(old : String, new : String) -> Array[@algorithms.DiffOp] { ///| /// Computes the difference between two arrays of strings, line by line. -pub fn diff_line(old : Array[String], new : Array[String]) -> Array[ - @algorithms.DiffOp, -] { +pub fn diff_line( + old : Array[String], + new : Array[String], +) -> Array[@algorithms.DiffOp] { diff(old, new) } diff --git a/src/moon.pkg b/src/moon.pkg new file mode 100644 index 0000000..079a7bf --- /dev/null +++ b/src/moon.pkg @@ -0,0 +1,5 @@ +import { + "ruifeng/diff/algorithms" @algorithms, +} + +warnings = "+a" \ No newline at end of file diff --git a/src/moon.pkg.json b/src/moon.pkg.json deleted file mode 100644 index 3b99388..0000000 --- a/src/moon.pkg.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "import": [ - { - "path": "ruifeng/diff/algorithms", - "alias": "algorithms" - } - ], - "warn-list": "+a" -} From a206ea6a96d29ec048afd64ca4d96fc516e6ad5d Mon Sep 17 00:00:00 2001 From: myfreess Date: Wed, 22 Apr 2026 13:03:53 +0800 Subject: [PATCH 08/10] moon info --- src/algorithms/pkg.generated.mbti | 8 ++------ src/pkg.generated.mbti | 6 +++--- 2 files changed, 5 insertions(+), 9 deletions(-) diff --git a/src/algorithms/pkg.generated.mbti b/src/algorithms/pkg.generated.mbti index 8acf909..1b271f7 100644 --- a/src/algorithms/pkg.generated.mbti +++ b/src/algorithms/pkg.generated.mbti @@ -17,13 +17,12 @@ pub fn[T : Eq + Hash] unique(Array[T], Range) -> Array[UniqueItem[T]] // Errors // Types and methods -type Capture +type Capture derive(Default) pub fn Capture::into_ops(Self) -> Array[DiffOp] pub fn Capture::new() -> Self pub fn Capture::ops(Self) -> Array[DiffOp] pub fn Capture::sort(Self) -> Unit pub fn Capture::to_iter(Self) -> Iter[DiffOp] -pub impl Default for Capture pub impl DiffHook for Capture pub(all) struct Compact[D, T] { @@ -43,7 +42,7 @@ pub(all) enum DiffOp { Delete(mut old_index~ : Int, mut old_len~ : Int, mut new_index~ : Int) Insert(mut old_index~ : Int, mut new_index~ : Int, mut new_len~ : Int) Replace(mut old_index~ : Int, mut old_len~ : Int, mut new_index~ : Int, mut new_len~ : Int) -} +} derive(Compare, Eq, Hash) pub fn[D : DiffHook] DiffOp::apply_to_hook(Self, D) -> Result[Unit, Error] pub fn DiffOp::grow_left(Self, Int) -> Unit pub fn DiffOp::grow_right(Self, Int) -> Unit @@ -54,9 +53,6 @@ pub fn DiffOp::shift_left(Self, Int) -> Unit pub fn DiffOp::shift_right(Self, Int) -> Unit pub fn DiffOp::shrink_left(Self, Int) -> Unit pub fn DiffOp::shrink_right(Self, Int) -> Unit -pub impl Compare for DiffOp -pub impl Eq for DiffOp -pub impl Hash for DiffOp pub impl Show for DiffOp pub type Myers diff --git a/src/pkg.generated.mbti b/src/pkg.generated.mbti index 0bf211a..7416c05 100644 --- a/src/pkg.generated.mbti +++ b/src/pkg.generated.mbti @@ -1,9 +1,9 @@ // Generated using `moon info`, DON'T EDIT IT package "ruifeng/diff" -import( - "ruifeng/diff/algorithms" -) +import { + "ruifeng/diff/algorithms", +} // Values pub fn[T : Eq] diff(Array[T], Array[T]) -> Array[@algorithms.DiffOp] From e8a2b62dcb2a18759e3d1237fa214714478dca38 Mon Sep 17 00:00:00 2001 From: myfreess Date: Fri, 24 Apr 2026 18:05:29 +0800 Subject: [PATCH 09/10] update ci --- .github/workflows/check.yaml | 88 ++++++------------------------------ 1 file changed, 14 insertions(+), 74 deletions(-) diff --git a/.github/workflows/check.yaml b/.github/workflows/check.yaml index 3ca4b33..3f028f9 100644 --- a/.github/workflows/check.yaml +++ b/.github/workflows/check.yaml @@ -1,107 +1,47 @@ name: check on: - workflow_dispatch: push: branches: - master - - main - + - main pull_request: jobs: check: - strategy: - matrix: - version: [stable] - os: - - ubuntu-latest - - macos-latest - - windows-latest - runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + runs-on: ubuntu-latest + continue-on-error: false steps: - uses: actions/checkout@v4 with: - fetch-depth: 1 - - - name: Setup Moon - uses: illusory0x0/setup-moonbit@v0.1.0 - with: - version: ${{ matrix.version }} + submodules: 'recursive' + + - name: install + run: | + curl -fsSL https://cli.moonbitlang.com/install/unix.sh | bash + echo "$HOME/.moon/bin" >> $GITHUB_PATH - name: moon version run: | moon version --all - - name: install module dependencies + - name: moon check run: | moon update moon check --deny-warn - - name: moon check - run: moon check --deny-warn - - name: moon info run: | moon info --target all git diff --exit-code - - name: moon fmt + - name: format diff run: | moon fmt git diff --exit-code - - name: Setup MSVC - if: ${{ runner.os == 'Windows' }} - uses: ilammy/msvc-dev-cmd@v1 - - - name: Set ulimit on unix - if: ${{ runner.os != 'Windows' }} - run: | - ulimit -s 8176 - - name: moon test run: | - moon test --target all - moon test --target all --release - - moon-json-format-check: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - - name: check `moon.*.json` format - shell: bash - run: | - _passed=0; - for f in $(find . -type f -name "moon.*.json"); do - if ! jq '.' $f > /dev/null; then - echo $f; - _passed=1; - fi - done - (exit $_passed) - - prettier: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - uses: actions/setup-node@v4 - - run: | - npm install --global prettier; - find . -name *.mod.json -exec npx prettier --write {} \; - find . -name *.pkg.json -exec npx prettier --write {} \; - git diff --exit-code; - - check-typos: - runs-on: ubuntu-latest - - steps: - - name: Checkout repository - uses: actions/checkout@v4 - - - name: AutoCorrect - uses: huacnlee/autocorrect-action@v2 - - - name: typos-action - uses: crate-ci/typos@v1.31.1 + moon test --target all \ No newline at end of file From 35ecf14e81eabdb4102faafd48fc8ebd69da9f1c Mon Sep 17 00:00:00 2001 From: myfreess Date: Fri, 24 Apr 2026 18:07:09 +0800 Subject: [PATCH 10/10] fmt --- src/algorithms/moon.pkg | 2 +- src/moon.pkg | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/algorithms/moon.pkg b/src/algorithms/moon.pkg index c328bf3..c1f67d7 100644 --- a/src/algorithms/moon.pkg +++ b/src/algorithms/moon.pkg @@ -3,4 +3,4 @@ import { "moonbitlang/core/hashmap" @hashmap, } -warnings = "+a" \ No newline at end of file +warnings = "+a" diff --git a/src/moon.pkg b/src/moon.pkg index 079a7bf..2288941 100644 --- a/src/moon.pkg +++ b/src/moon.pkg @@ -2,4 +2,4 @@ import { "ruifeng/diff/algorithms" @algorithms, } -warnings = "+a" \ No newline at end of file +warnings = "+a"