chore(parser/diff): use generic
This commit is contained in:
		
							parent
							
								
									7e61f8ae7d
								
							
						
					
					
						commit
						f3a93a2097
					
				|  | @ -50,7 +50,7 @@ func isWhitespace(b byte) bool { | ||||||
| 		b == 0xA0 | 		b == 0xA0 | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func formatDiff(oldList []string, newList []string, ops []Op) string { | func formatDiff(oldList []string, newList []string, ops []Op[string]) string { | ||||||
| 	var result []string | 	var result []string | ||||||
| 	i, j := 0, 0 | 	i, j := 0, 0 | ||||||
| 	for _, op := range ops { | 	for _, op := range ops { | ||||||
|  |  | ||||||
|  | @ -11,21 +11,21 @@ const ( | ||||||
| 	OpDelete | 	OpDelete | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| type Op struct { | type Op[T any] struct { | ||||||
| 	OpType OpType // Insert or delete, as above
 | 	OpType OpType // Insert or delete, as above
 | ||||||
| 	OldPos int    // Position in the old list of item to be inserted or deleted
 | 	OldPos int    // Position in the old list of item to be inserted or deleted
 | ||||||
| 	NewPos int    // Position in the _new_ list of item to be inserted
 | 	NewPos int    // Position in the _new_ list of item to be inserted
 | ||||||
| 	Elem   any    // Actual value to be inserted or deleted
 | 	Elem   T      // Actual value to be inserted or deleted
 | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // Returns a minimal list of differences between 2 lists e and f
 | // Returns a minimal list of differences between 2 lists e and f
 | ||||||
| // requiring O(min(len(e),len(f))) space and O(min(len(e),len(f)) * D)
 | // requiring O(min(len(e),len(f))) space and O(min(len(e),len(f)) * D)
 | ||||||
| // worst-case execution time where D is the number of differences.
 | // worst-case execution time where D is the number of differences.
 | ||||||
| func myersDiff(e, f []any, equals func(any, any) bool) []Op { | func myersDiff[T any](e, f []T, equals func(T, T) bool) []Op[T] { | ||||||
| 	return diffInternal(e, f, equals, 0, 0) | 	return diffInternal(e, f, equals, 0, 0) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func diffInternal(e, f []any, equals func(any, any) bool, i, j int) []Op { | func diffInternal[T any](e, f []T, equals func(T, T) bool, i, j int) []Op[T] { | ||||||
| 	N := len(e) | 	N := len(e) | ||||||
| 	M := len(f) | 	M := len(f) | ||||||
| 	L := N + M | 	L := N + M | ||||||
|  | @ -88,26 +88,26 @@ func diffInternal(e, f []any, equals func(any, any) bool, i, j int) []Op { | ||||||
| 						case D > 1 || (x != u && y != v): | 						case D > 1 || (x != u && y != v): | ||||||
| 							return append(diffInternal(e[0:x], f[0:y], equals, i, j), diffInternal(e[u:N], f[v:M], equals, i+u, j+v)...) | 							return append(diffInternal(e[0:x], f[0:y], equals, i, j), diffInternal(e[u:N], f[v:M], equals, i+u, j+v)...) | ||||||
| 						case M > N: | 						case M > N: | ||||||
| 							return diffInternal(make([]any, 0), f[N:M], equals, i+N, j+N) | 							return diffInternal(make([]T, 0), f[N:M], equals, i+N, j+N) | ||||||
| 						case M < N: | 						case M < N: | ||||||
| 							return diffInternal(e[M:N], make([]any, 0), equals, i+M, j+M) | 							return diffInternal(e[M:N], make([]T, 0), equals, i+M, j+M) | ||||||
| 						default: | 						default: | ||||||
| 							return make([]Op, 0) | 							return make([]Op[T], 0) | ||||||
| 						} | 						} | ||||||
| 					} | 					} | ||||||
| 				} | 				} | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 	case N > 0: | 	case N > 0: | ||||||
| 		res := make([]Op, N) | 		res := make([]Op[T], N) | ||||||
| 		for n := range N { | 		for n := range N { | ||||||
| 			res[n] = Op{OpDelete, i + n, -1, e[n]} | 			res[n] = Op[T]{OpDelete, i + n, -1, e[n]} | ||||||
| 		} | 		} | ||||||
| 		return res | 		return res | ||||||
| 	default: | 	default: | ||||||
| 		res := make([]Op, M) | 		res := make([]Op[T], M) | ||||||
| 		for n := range M { | 		for n := range M { | ||||||
| 			res[n] = Op{OpInsert, i, j + n, f[n]} | 			res[n] = Op[T]{OpInsert, i, j + n, f[n]} | ||||||
| 		} | 		} | ||||||
| 		return res | 		return res | ||||||
| 	} | 	} | ||||||
|  | @ -127,15 +127,8 @@ func pyMod(x, y int) int { | ||||||
| // Let us map element in same way as in
 | // Let us map element in same way as in
 | ||||||
| 
 | 
 | ||||||
| // Convenient wrapper for string lists
 | // Convenient wrapper for string lists
 | ||||||
| func myersDiffStr(e, f []string, compareSpace bool) []Op { | func myersDiffStr(e, f []string, compareSpace bool) []Op[string] { | ||||||
| 	e1, f1 := make([]any, len(e)), make([]any, len(f)) | 	return myersDiff[string](e, f, func(s1, s2 string) bool { | ||||||
| 	for i, ee := range e { | 		return compareStrings(s1, s2, compareSpace) | ||||||
| 		e1[i] = ee |  | ||||||
| 	} |  | ||||||
| 	for i, fe := range f { |  | ||||||
| 		f1[i] = fe |  | ||||||
| 	} |  | ||||||
| 	return myersDiff(e1, f1, func(s1, s2 any) bool { |  | ||||||
| 		return compareStrings(s1.(string), s2.(string), compareSpace) |  | ||||||
| 	}) | 	}) | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -8,7 +8,7 @@ import ( | ||||||
| type TestCase struct { | type TestCase struct { | ||||||
| 	l1  []string | 	l1  []string | ||||||
| 	l2  []string | 	l2  []string | ||||||
| 	exp []Op | 	exp []Op[string] | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func TestDiff(t *t.T) { | func TestDiff(t *t.T) { | ||||||
|  | @ -16,28 +16,28 @@ func TestDiff(t *t.T) { | ||||||
| 	B := "B" | 	B := "B" | ||||||
| 	C := "C" | 	C := "C" | ||||||
| 	testCases := []TestCase{ | 	testCases := []TestCase{ | ||||||
| 		{[]string{}, []string{}, []Op{}}, | 		{[]string{}, []string{}, []Op[string]{}}, | ||||||
| 		{[]string{}, []string{"foo"}, []Op{{OpInsert, 0, 0, "foo"}}}, | 		{[]string{}, []string{"foo"}, []Op[string]{{OpInsert, 0, 0, "foo"}}}, | ||||||
| 		{[]string{"foo"}, []string{}, []Op{{OpDelete, 0, -1, "foo"}}}, | 		{[]string{"foo"}, []string{}, []Op[string]{{OpDelete, 0, -1, "foo"}}}, | ||||||
| 		{[]string{"foo", "bar", "baz"}, []string{"foo", "bar", "baz"}, []Op{}}, | 		{[]string{"foo", "bar", "baz"}, []string{"foo", "bar", "baz"}, []Op[string]{}}, | ||||||
| 		{[]string{"foo", "bar", "baz"}, []string{"foo", "baz"}, []Op{{OpDelete, 1, -1, "bar"}}}, | 		{[]string{"foo", "bar", "baz"}, []string{"foo", "baz"}, []Op[string]{{OpDelete, 1, -1, "bar"}}}, | ||||||
| 		{[]string{"baz"}, []string{"foo", "baz"}, []Op{{OpInsert, 0, 0, "foo"}}}, | 		{[]string{"baz"}, []string{"foo", "baz"}, []Op[string]{{OpInsert, 0, 0, "foo"}}}, | ||||||
| 		{[]string{"bar", "baz"}, []string{"foo", "baz"}, []Op{{OpDelete, 0, -1, "bar"}, {OpInsert, 1, 0, "foo"}}}, | 		{[]string{"bar", "baz"}, []string{"foo", "baz"}, []Op[string]{{OpDelete, 0, -1, "bar"}, {OpInsert, 1, 0, "foo"}}}, | ||||||
| 		{[]string{"foo", "bar", "baz"}, []string{"foo", "bar"}, []Op{{OpDelete, 2, -1, "baz"}}}, | 		{[]string{"foo", "bar", "baz"}, []string{"foo", "bar"}, []Op[string]{{OpDelete, 2, -1, "baz"}}}, | ||||||
| 		{ | 		{ | ||||||
| 			[]string{A, B, C, A, B, B, A}, | 			[]string{A, B, C, A, B, B, A}, | ||||||
| 			[]string{C, B, A, B, A, C}, | 			[]string{C, B, A, B, A, C}, | ||||||
| 			[]Op{{OpDelete, 0, -1, A}, {OpInsert, 1, 0, C}, {OpDelete, 2, -1, C}, {OpDelete, 5, -1, B}, {OpInsert, 7, 5, C}}, | 			[]Op[string]{{OpDelete, 0, -1, A}, {OpInsert, 1, 0, C}, {OpDelete, 2, -1, C}, {OpDelete, 5, -1, B}, {OpInsert, 7, 5, C}}, | ||||||
| 		}, | 		}, | ||||||
| 		{ | 		{ | ||||||
| 			[]string{C, A, B, A, B, A, B, A, B, A, B, A, B, C}, | 			[]string{C, A, B, A, B, A, B, A, B, A, B, A, B, C}, | ||||||
| 			[]string{B, A, B, A, B, A, B, A, B, A, B, A, B, A}, | 			[]string{B, A, B, A, B, A, B, A, B, A, B, A, B, A}, | ||||||
| 			[]Op{{OpDelete, 0, -1, C}, {OpInsert, 1, 0, B}, {OpDelete, 13, -1, C}, {OpInsert, 14, 13, A}}, | 			[]Op[string]{{OpDelete, 0, -1, C}, {OpInsert, 1, 0, B}, {OpDelete, 13, -1, C}, {OpInsert, 14, 13, A}}, | ||||||
| 		}, | 		}, | ||||||
| 		{ | 		{ | ||||||
| 			[]string{B}, | 			[]string{B}, | ||||||
| 			[]string{A, B, C, B, A}, | 			[]string{A, B, C, B, A}, | ||||||
| 			[]Op{{OpInsert, 0, 0, A}, {OpInsert, 0, 1, B}, {OpInsert, 0, 2, C}, {OpInsert, 1, 4, A}}, | 			[]Op[string]{{OpInsert, 0, 0, A}, {OpInsert, 0, 1, B}, {OpInsert, 0, 2, C}, {OpInsert, 1, 4, A}}, | ||||||
| 		}, | 		}, | ||||||
| 	} | 	} | ||||||
| 	for _, c := range testCases { | 	for _, c := range testCases { | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue
	
	Block a user