shithub: mc

ref: f196ea0ea5f82cb63e4bb66f2009d8115de386a9
dir: /lib/std/iterutil.myr/

View raw version
use "types"
use "fmt"
use "extremum"

pkg std =
	type zipiter(@a, @b) = struct
		s1	: @a[:]
		s2	: @b[:]
	;;

	type reverseiter(@a) = struct
		sl	: @a[:]
		idx	: size
	;;

	type enumiter(@a) = struct
		idx	: size
		sl	: @a[:]
	;;

	type refiter(@a) = struct
		idx	: size
		sl	: @a[:]
	;;

	type chunkiter(@a) = struct
		idx	: size
		blksz	: size
		sl	: @a[:]
	;;

	impl iterable zipiter(@a, @b) -> (@a, @b)
	impl iterable enumiter(@a) -> (size, @a)
	impl iterable reverseiter(@a) -> @a
	impl iterable refiter(@a) -> @a#
	impl iterable chunkiter(@a) -> @a[:]

	generic byzip	: (a : @a[:], b : @b[:]	 -> zipiter(@a, @b))
	generic byenum	: (a : @a[:] -> enumiter(@a))
	generic byreverse 	: (sl : @a[:] -> reverseiter(@a))
	generic byref 	: (sl : @a[:] -> refiter(@a))
	generic bychunk	: (a : @a[:], chunk : size -> chunkiter(@a))
;;

generic byzip = {a, b
	-> [.s1 = a, .s2 = b]
}

impl iterable zipiter(@a, @b) -> (@a, @b) =
	__iternext__ = {itp, valp
		if itp.s1.len > 0 && itp.s2.len > 0
			valp# = (itp.s1[0], itp.s2[0])
			itp.s1 = itp.s1[1:]
			itp.s2 = itp.s2[1:]
			-> true
		else
			-> false
		;;
	}

	__iterfin__ = {itp, valp
	}
;;

generic byreverse = {sl
	-> [.sl = sl, .idx = sl.len]
}

impl iterable reverseiter(@a) -> @a =
	__iternext__ = {itp, valp
		if itp.idx > 0
			valp# = itp.sl[itp.idx - 1]
			itp.idx--
			-> true
		else
			-> false
		;;
	}

	__iterfin__ = {itp, valp
	}
;;

generic byenum = {a
	-> [.sl = a, .idx = 0]
}

impl iterable enumiter(@a) -> (size, @a) =
	__iternext__ = {itp, valp
		if itp.idx == itp.sl.len
			-> false
		;;
		valp# = (itp.idx, itp.sl[itp.idx])
		itp.idx++
		-> true
	}

	__iterfin__ = {itp, valp
	}
;;

generic byref = {a
	-> [.sl = a, .idx = 0]
}

impl iterable refiter(@a) -> @a# =
	__iternext__ = {itp, valp
		if itp.idx == itp.sl.len
			-> false
		;;
		valp# = &itp.sl[itp.idx]
		itp.idx++
		-> true
	}

	__iterfin__ = {itp, valp
	}
;;

generic bychunk = {a, sz
	-> [.sl = a, .idx = 0, .blksz = sz]
}

impl iterable chunkiter(@a) -> @a[:] =
	__iternext__ = {itp, valp
		var len

		len = min(itp.blksz, itp.sl.len - itp.idx)
		if itp.idx + len == itp.sl.len
			-> false
		;;
		valp# = itp.sl[itp.idx: itp.idx + len]
		itp.idx += itp.blksz
		-> true
	}

	__iterfin__ = {itp, valp
	}
;;