Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

newclay/lib-clay new module io.splitting: Splitting adapter to extrac…

…t sequential subranges from a source or iterator
  • Loading branch information...
commit 68248f95bbbd24c2d0ad3f4bf75dae3c7348e988 1 parent 22e1b35
Joe Groff jckarter authored
130 newclay/lib-clay/io/splitting/splitting.clay
... ... @@ -0,0 +1,130 @@
  1 +import containers.(Container?, push, resize);
  2 +import io.transformers.(SlicedUpto);
  3 +import unsafe.coordinates.(Coordinate?, RandomAccessCoordinate?, CoordinateRange);
  4 +import vectors.(Vector);
  5 +
  6 +
  7 +//
  8 +// splitting interface
  9 +//
  10 +
  11 +define getSplit;
  12 +define resetSplit;
  13 +
  14 +detachSplit(ref i) {
  15 + var split = getSplit(i);
  16 + resetSplit(i);
  17 + return split;
  18 +}
  19 +
  20 +
  21 +//
  22 +// SplittingCoordinateRange
  23 +//
  24 +
  25 +define SplittingCoordinateRange['C] as RecordType(
  26 + fromBegin:'C,
  27 + begin:'C,
  28 + end:'C,
  29 +);
  30 +
  31 +overload #Savable?(SplittingCoordinateRange['C]) = true;
  32 +overload #Reliable?(SplittingCoordinateRange['C]) = Reliable?('C);
  33 +
  34 +overload hasFront?(r:SplittingCoordinateRange['C]) | Coordinate?('C) = r.begin < r.end;
  35 +overload front(r:SplittingCoordinateRange['C]) | Coordinate?('C) {
  36 + assert(-> r.begin < r.end, "invalid ", SplittingCoordinateRange['C]);
  37 + return forward ..(r.begin^);
  38 +}
  39 +overload incFront(ref r:SplittingCoordinateRange['C])
  40 + | Coordinate?('C)
  41 + { inc(r.begin); }
  42 +
  43 +overload seekFront(ref r:SplittingCoordinateRange['C], distance:UInt)
  44 + | RandomAccessCoordinate?('C)
  45 + { r.begin += distance; }
  46 +
  47 +overload getSplit(r:SplittingCoordinateRange['C]) {
  48 + assert(-> r.fromBegin <= r.begin, "invalid ", SplittingCoordinateRange['C]);
  49 + return CoordinateRange(r.fromBegin, r.begin);
  50 +}
  51 +
  52 +overload resetSplit(ref r:SplittingCoordinateRange['C]) {
  53 + r.fromBegin = r.begin;
  54 +}
  55 +
  56 +
  57 +//
  58 +// SplittingIterator (for savable iterators)
  59 +//
  60 +
  61 +define SplittingIterator['I] as RecordType(
  62 + originalIterator:'I,
  63 + iterator:'I,
  64 + distance:UInt,
  65 +);
  66 +
  67 +overload #Savable?(SplittingIterator['I]) = true;
  68 +overload #Reliable?(SplittingIterator['I]) = Reliable?('I);
  69 +
  70 +overload hasFront?(i:SplittingIterator['I]) | Iterator?('I)
  71 + = hasFront?(i.iterator);
  72 +overload front(i:SplittingIterator['I]) | Iterator?('I)
  73 + = forward ..front(i.iterator);
  74 +overload incFront(ref i:SplittingIterator['I]) | Iterator?('I) {
  75 + incFront(i.iterator);
  76 + inc(i.distance);
  77 +}
  78 +
  79 +overload seekFront(ref i:SplittingIterator['I], distance:UInt) | SeekableIterator?('I) {
  80 + seekFront(i.iterator, distance);
  81 + i.distance += distance;
  82 +}
  83 +
  84 +overload getSplit(i:SplittingIterator['I]) = SlicedUpto(i.originalIterator, i.distance);
  85 +overload resetSplit(ref i:SplittingIterator['I]) {
  86 + i.originalIterator = save(i.iterator);
  87 + i.distance = 0u;
  88 +}
  89 +
  90 +
  91 +//
  92 +// SplittingSource (for non-savable iterators)
  93 +//
  94 +
  95 +define SplittingSource['S, 'Container] as RecordType(
  96 + front:'Container,
  97 + source:'S,
  98 +);
  99 +
  100 +overload read1(ref s:SplittingSource['S, 'C]) {
  101 + return maybe(read1(s.source),
  102 + (..elt) -> {
  103 + push(s.front, ..elt);
  104 + return just(..elt);
  105 + }
  106 + );
  107 +}
  108 +
  109 +overload getSplit(s:SplittingSource['S, 'C]) = s.front;
  110 +
  111 +overload resetSplit(ref s:SplittingSource['S, 'C]) {
  112 + resize(s.front, 0u);
  113 +}
  114 +
  115 +
  116 +//
  117 +// Splitting adapter
  118 +//
  119 +
  120 +Splitting(forward s:'S) inline | Source?('S)
  121 + = SplittingSource['S, Vector[sourceValueType('S)]](Vector[sourceValueType('S)](), s);
  122 +overload Splitting(forward i:'I) inline | Iterator?('I) and Savable?('I) {
  123 + var savedi = save(i);
  124 + return SplittingIterator['I](savedi, savedi);
  125 +}
  126 +overload Splitting(forward r:CoordinateRange['C]) inline | Coordinate?('C) {
  127 + var begin, end = ..*r;
  128 + return SplittingCoordinateRange['C](begin, begin, end);
  129 +}
  130 +
5 newclay/lib-clay/io/transformers/transformers.clay
@@ -52,15 +52,14 @@ overload size(x:Reversed['I]) inline
52 52 | SizedIterator?('I)
53 53 = size(*x);
54 54
55   -overload #Savable?(Reversed['I]) = 'I;
56   -overload #Reliable?(Reversed['I]) = 'I;
  55 +overload #Savable?(Reversed['I]) = Savable?('I);
  56 +overload #Reliable?(Reversed['I]) = Reliable?('I);
57 57
58 58
59 59 //
60 60 // zipped
61 61 //
62 62
63   -// XXX capture sequences
64 63 define Zipped[..'I] as NewType(Tuple[..'I]);
65 64
66 65 private initializeZipped(forward ..seqs:'SS) inline = Zipped[..'SS]([..seqs]);
4 newclay/test/io/splitting/File/foo.txt
... ... @@ -0,0 +1,4 @@
  1 +fee
  2 +fie
  3 +foe
  4 +fum
26 newclay/test/io/splitting/File/main.clay
... ... @@ -0,0 +1,26 @@
  1 +import io.stdio.(InputFile);
  2 +import io.splitting.(Splitting, detachSplit);
  3 +import printing.(printlnRepr, println);
  4 +import strings.(String);
  5 +import strings.encodings.utf8.(UTF8);
  6 +
  7 +getline(ref splitter) {
  8 + while (maybe(read1(splitter),
  9 + (c) -> c != '\n',
  10 + -> false,
  11 + ));
  12 +
  13 + return detachSplit(splitter);
  14 +}
  15 +
  16 +main() {
  17 + var file = UTF8(InputFile("foo.txt")), src = Splitting(source(file));
  18 +
  19 + while (true) {
  20 + var line = getline(src);
  21 + if (empty?(line))
  22 + break;
  23 + printlnRepr(String(line));
  24 + }
  25 + println("fin");
  26 +}
5 newclay/test/io/splitting/File/out.txt
... ... @@ -0,0 +1,5 @@
  1 +String("fee\n")
  2 +String("fie\n")
  3 +String("foe\n")
  4 +String("fum\n")
  5 +fin
26 newclay/test/io/splitting/Range/main.clay
... ... @@ -0,0 +1,26 @@
  1 +import io.splitting.(Splitting, detachSplit);
  2 +import printing.(printlnRepr, println);
  3 +import vectors.(Vector);
  4 +
  5 +powerof2?(x:Int) = bitand(x, x - 1) == 0;
  6 +
  7 +getpowerof2(ref splitter) {
  8 + while (maybe(read1(splitter),
  9 + (x) -> not powerof2?(x),
  10 + -> false,
  11 + ));
  12 +
  13 + return detachSplit(splitter);
  14 +}
  15 +
  16 +main() {
  17 + var range = Range(1, 17), iter = Splitting(range);
  18 +
  19 + while (true) {
  20 + var line = getpowerof2(iter);
  21 + if (empty?(line))
  22 + break;
  23 + printlnRepr(Vector(line));
  24 + }
  25 + println("fin");
  26 +}
6 newclay/test/io/splitting/Range/out.txt
... ... @@ -0,0 +1,6 @@
  1 +Vector[Int](1i)
  2 +Vector[Int](2i)
  3 +Vector[Int](3i, 4i)
  4 +Vector[Int](5i, 6i, 7i, 8i)
  5 +Vector[Int](9i, 10i, 11i, 12i, 13i, 14i, 15i, 16i)
  6 +fin
29 newclay/test/io/splitting/Vector/main.clay
... ... @@ -0,0 +1,29 @@
  1 +import io.splitting.(Splitting, detachSplit);
  2 +import printing.(printlnRepr, println);
  3 +import strings.(String);
  4 +import strings.encodings.utf8.(UTF8);
  5 +import vectors.(Vector);
  6 +
  7 +getline(ref splitter) {
  8 + while (maybe(read1(splitter),
  9 + (c) -> c != '\n',
  10 + -> false,
  11 + ));
  12 +
  13 + return detachSplit(splitter);
  14 +}
  15 +
  16 +main() {
  17 + var input = Vector[Char]("fee\nfie\nfoe\nfum\n"),
  18 + iter = Splitting(iterator(input));
  19 +
  20 + printlnRepr(#type(-> iter));
  21 +
  22 + while (true) {
  23 + var line = getline(iter);
  24 + if (empty?(line))
  25 + break;
  26 + printlnRepr(String(line));
  27 + }
  28 + println("fin");
  29 +}
6 newclay/test/io/splitting/Vector/out.txt
... ... @@ -0,0 +1,6 @@
  1 +#SplittingCoordinateRange[ContiguousCoordinate[Char]]
  2 +String("fee\n")
  3 +String("fie\n")
  4 +String("foe\n")
  5 +String("fum\n")
  6 +fin

0 comments on commit 68248f9

Please sign in to comment.
Something went wrong with that request. Please try again.