sourcelibs/Csv/src/Csv.xtlm

1⍝# Csv: its macro library -- c_olumns<, a table's columns as named, 2⍝# typed variables. 3⍝# Imported with the functions, under one alias: "cs:" u_se< "Csv". 4⍝# A macro is a function from the source text written left and right of 5⍝# its call to the source that replaces the call, run before the program 6⍝# is compiled (X_eTaL MC10). Names with m: are macros; those under h: are 7⍝# private to this file. 8 9ᵗ⁼u̲se< "Strings" 10 11lowers ← "abcdefghijklmnopqrstuvwxyz" 12letters ← lowers c̲at ⎕A c̲at ⎕D 13 14⍝## Parsing 15 16⍝# Whether a text can be a variable's name. 17ʰn̲ame? ← { n → (0 < t̲ally n) ∧ ((f̲irst n) m̲ember? lowers) ∧ '∧ r̲/ n m̲ember? letters } 18 19⍝# A column's name and kind, from "name:kind". 20ʰc̲ut ← { c → (f̲irst w̲here c = f̲irst ":") − 1 } 21ʰc̲olName ← { c → (ʰc̲ut c) t̲ake c } 22ʰc̲olKind ← { c → (1 + ʰc̲ut c) d̲rop c } 23 24⍝# Whether a column is "name:text" or "name:number". 25ʰc̲olumn? ← { c → 26 1 ≠ t̲ally w̲here c = f̲irst ":" ? 0 = 1 27 (ʰn̲ame? ʰc̲olName c) ∧ ("text" m̲atch ʰc̲olKind c) ∨ "number" m̲atch ʰc̲olKind c 28} 29 30⍝# The code for one column of table tb: its texts, found by header, the 31⍝# header left out; numbers read from them when the kind is number. 32ʰc̲ode ← { tb c → 33 n ← ʰc̲olName c 34 texts ← "(1 d_rop ((f_irst " c̲at tb c̲at ") i_ndexOf e_nclose \"" c̲at n c̲at "\") s_elect_2 " c̲at tb c̲at ")" 35 "text" m̲atch ʰc̲olKind c ? n c̲at " := " c̲at texts 36 n c̲at " := n_umbers d_isclose '{ e_nclose (d_isclose _l) c_at \" \" c_at d_isclose _r } r_/ " c̲at texts 37} 38 39⍝## The macro 40 41⍝# "city:text population:number" cs:c_olumns< "t": the columns of table 42⍝# t (a table as cs:r_ows gives it, its first row the header) as 43⍝# variables named after them: city the texts of column "city", 44⍝# population its numbers (Floats). When the program is compiled the 45⍝# schema is checked and a definition written per column, so the rest 46⍝# of the program uses the columns by name and their kinds are 47⍝# type-checked like any variable (population c_at "x" is a type 48⍝# error). A malformed schema or table name stops the compiler: 49⍝# error[bad-columns]. Columns are found by their header when the 50⍝# program runs. 51ᵐc̲olumns< ← { schema tb → 52 cs ← ᵗw̲ords schema 53 0 = t̲ally cs ? "bad-columns left" ⎕R̲EJECT "no columns: write name:text or name:number" 54 bad ← (n̲ot '{ ʰc̲olumn? d̲isclose ⍵ } e̲ach cs) r̲eplicate cs 55 0 < t̲ally bad ? "bad-columns left" ⎕R̲EJECT (d̲isclose f̲irst bad) c̲at " is not a column: write name:text or name:number (a lowercase name)" 56 n̲ot ʰn̲ame? ᵗt̲rim tb ? "bad-columns right" ⎕R̲EJECT tb c̲at " is not a table's name" 57 "\n" ᵗj̲oin '{ c → (ᵗt̲rim tb) ʰc̲ode d̲isclose c } m̲ap cs 58}