commit 07bc628

shrub  ·  2026-10-15 18:02:46 +0000 UTC
parent 8cb90de
use string buffer instead of allocating per character
3 files changed,  +53, -63
+10, -2
 1@@ -1,5 +1,7 @@
 2 #include "share/atspre_staload.hats"
 3-staload IO = "libats/libc/SATS/stdio.sats"
 4+staload "libats/libc/SATS/stdio.sats"
 5+staload "libats/SATS/stringbuf.sats"
 6+staload "libats/DATS/stringbuf.dats"
 7 staload "scan.sats"
 8 staload "parse.sats"
 9 
10@@ -9,12 +11,18 @@ let
11     (* initialize the scanner *)
12     var s: scanner = @{
13         file = manifest,
14-        cur  = $IO.fgetc0(manifest),
15+        buf  = stringbuf_make_nil(i2sz(64)),
16+        cur  = fgetc0(manifest),
17         line = 1,
18         col  = 1 }
19     val result = parse(s, nil_vt(), nil_vt(), nil_vt())
20 in
21     printrule(result.rules);
22     manifest_free(result);
23+    let 
24+        val @{file = _, buf = buf, cur = _, line = _, col = _} = s 
25+    in
26+        stringbuf_free(buf)
27+    end;
28     fileref_close(manifest)
29 end
+39, -60
  1@@ -1,21 +1,30 @@
  2 #include "share/atspre_staload.hats"
  3 #define ATS_DYNLOADFLAG 0
  4-staload IO = "libats/libc/SATS/stdio.sats"
  5+staload "libats/libc/SATS/stdio.sats"
  6+staload "libats/SATS/stringbuf.sats"
  7+staload "libats/DATS/stringbuf.dats"
  8 staload "scan.sats"
  9 
 10 exception ScanErr of ()
 11 
 12 (*get one character from a file and return the corresponding int*)
 13 fun char (manifest: FILEref): int =
 14-    $IO.fgetc0(manifest)
 15+    fgetc0(manifest)
 16 
 17-(* stuff ninja allows *)
 18 fun isnamec(c: int): bool = 
 19     isalnum(c)           || 
 20     (c = char2int0('_')) || 
 21     (c = char2int0('-')) ||
 22     (c = char2int0('.'))
 23 
 24+fun isvaluec(c: int): bool = 
 25+    (c != char2int0('\n'))
 26+
 27+fun ispathc(c: int): bool = 
 28+    (c != char2int0('\n')) &&
 29+    (c != char2int0 (' ')) &&
 30+    (c != char2int0 (':'))
 31+
 32 implement next(s) (*void*) =
 33     ((if s.cur = char2int0('\n') then (
 34         s.line := s.line + 1;
 35@@ -23,34 +32,31 @@ implement next(s) (*void*) =
 36     else s.col := s.col +1);
 37     s.cur := char(s.file))
 38 
 39-fun name(s: &scanner, chars: List0_vt(charNZ)): List0_vt(charNZ) =
 40-    if (s.cur >= 0) && isnamec(s.cur) then
 41+fun read(s: &scanner, allowed: (int) -<fun1> bool): void =
 42+    if (s.cur >= 0) && allowed(s.cur) then
 43         let
 44-            val c    = g1ofg0_char(int2char0(s.cur))
 45+            val c = g1ofg0_char(int2char0(s.cur))
 46         in
 47             if c != '\000' then
 48                 let 
 49-                    val more = cons_vt(c, chars);
 50+                    val inserted = stringbuf_insert_char(s.buf, c);
 51                 in
 52-                    next(s);
 53-                    name(s, more)
 54-                end
 55-            else list_vt_reverse(chars)
 56+                    if inserted = 1 then (
 57+                        next(s);
 58+                        read(s, allowed) ) 
 59+                    else $raise ScanErr
 60+               end
 61+            else ()
 62         end
 63-    else list_vt_reverse(chars)
 64+    else ()
 65 
 66-(* list of chars to string pointer *)
 67-fun c2s(chars: List0_vt(charNZ)): Strptr1 =
 68-let 
 69-    val text = string_make_list_vt(chars)
 70-    prval () = lemma_strnptr_param(text)
 71-in
 72-    strnptr2strptr(text)
 73-end   
 74 
 75-(* do name with the initialized scanner and a fresh list *)
 76 implement scanname(s) (*Strptr1*)= 
 77-    c2s(name(s, nil_vt()))
 78+let
 79+    val () = read(s, isnamec)
 80+in
 81+    stringbuf_takeout_all(s.buf) 
 82+end
 83 
 84 implement skipspace(s) (*void*) =
 85     if (s.cur = char2int0(' ')) then (
 86@@ -106,43 +112,16 @@ implement scankeyword(s) =
 87     else (prerrln!("expected name at ",s.line, ":", s.col);
 88           $raise ScanErr())
 89 
 90-fun value(s: &scanner, chars: List0_vt(charNZ)): List0_vt(charNZ) =
 91-    if (s.cur >=0) && (s.cur != char2int0('\n')) then (
 92-        let
 93-            val c    = g1ofg0_char(int2char0(s.cur))
 94-        in
 95-            if c != '\000' then
 96-                let 
 97-                    val more = cons_vt(c, chars);
 98-                in
 99-                    next (s);
100-                    value(s, more)
101-                end
102-            else list_vt_reverse(chars)
103-        end
104-    ) else list_vt_reverse(chars)
105-
106-implement scanvalue(s) = 
107-     c2s(value(s, nil_vt())) 
108-
109-fun path(s: &scanner, chars: List0_vt(charNZ)): List0_vt(charNZ) =
110-     if (s.cur >= 0) &&
111-        (s.cur != char2int0 ('\n')) && 
112-        (s.cur != char2int0  (':')) &&
113-        (s.cur != char2int0  (' ')) then (
114-         let val c = g1ofg0_char(int2char0(s.cur))
115-         in 
116-             if c != '\000' then
117-                 let 
118-                     val more = cons_vt(c, chars)
119-                 in 
120-                     next(s);
121-                     path(s, more)
122-                end
123-             else list_vt_reverse(chars)
124-         end
125-     ) else list_vt_reverse(chars)
126+implement scanvalue(s) (*Strptr1*) = 
127+let
128+    val () = read(s, isvaluec)
129+in
130+    stringbuf_takeout_all(s.buf)
131+end
132 
133 implement scanpath(s) = 
134-    c2s(path(s, nil_vt()))
135-               
136+let
137+    val () = read(s, ispathc) 
138+in
139+    stringbuf_takeout_all(s.buf)
140+end 
+4, -1
 1@@ -1,5 +1,8 @@
 2-typedef scanner = @{
 3+staload  "libats/SATS/stringbuf.sats"
 4+
 5+vtypedef scanner = @{
 6     file = FILEref,
 7+    buf  = stringbuf,
 8     cur  = int,
 9     line = int,
10     col  = int