# HG changeset patch # User Adam Chlipala # Date 1220377494 14400 # Node ID e4baf03a3a64e93ad3ca93bbf5b50c2f1b01f8f0 # Parent 09c66a30ef326a87912dfa4ad6c8ba28720135b9 Generating SQL files diff -r 09c66a30ef32 -r e4baf03a3a64 src/cjr_print.sig --- a/src/cjr_print.sig Tue Sep 02 13:09:54 2008 -0400 +++ b/src/cjr_print.sig Tue Sep 02 13:44:54 2008 -0400 @@ -33,5 +33,7 @@ val p_decl : CjrEnv.env -> Cjr.decl Print.printer val p_file : CjrEnv.env -> Cjr.file Print.printer + val p_sql : CjrEnv.env -> Cjr.file Print.printer + val debug : bool ref end diff -r 09c66a30ef32 -r e4baf03a3a64 src/cjr_print.sml --- a/src/cjr_print.sml Tue Sep 02 13:09:54 2008 -0400 +++ b/src/cjr_print.sml Tue Sep 02 13:44:54 2008 -0400 @@ -1238,4 +1238,51 @@ newline] end +fun p_sqltype env (tAll as (t, loc)) = + let + val s = case t of + TFfi ("Basis", "int") => "int8" + | TFfi ("Basis", "float") => "float8" + | TFfi ("Basis", "string") => "text" + | TFfi ("Basis", "bool") => "bool" + | _ => (ErrorMsg.errorAt loc "Don't know SQL equivalent of type"; + Print.eprefaces' [("Type", p_typ env tAll)]; + "ERROR") + in + string s + end + +fun p_sql env (ds, _) = + let + val (pps, _) = ListUtil.foldlMap + (fn (dAll as (d, _), env) => + let + val pp = case d of + DTable (s, xts) => + box [string "CREATE TABLE ", + string s, + string "(", + p_list (fn (x, t) => + box [string "lw_", + string x, + space, + string ":", + space, + p_sqltype env t, + space, + string "NOT", + space, + string "NULL"]) xts, + string ");", + newline, + newline] + | _ => box [] + in + (pp, E.declBinds env dAll) + end) + env ds + in + box pps + end + end diff -r 09c66a30ef32 -r e4baf03a3a64 src/compiler.sig --- a/src/compiler.sig Tue Sep 02 13:09:54 2008 -0400 +++ b/src/compiler.sig Tue Sep 02 13:44:54 2008 -0400 @@ -31,7 +31,10 @@ type job = { database : string option, - sources : string list + sources : string list, + exe : string, + sql : string option, + debug : bool } val compile : string -> unit val compileC : {cname : string, oname : string, ename : string} -> unit @@ -65,6 +68,7 @@ val mono_reduce : (Mono.file, Mono.file) phase val mono_shake : (Mono.file, Mono.file) phase val cjrize : (Mono.file, Cjr.file) phase + val sqlify : (Mono.file, Cjr.file) phase val toParseJob : (string, job) transform val toParse : (string, Source.file) transform @@ -83,5 +87,6 @@ val toMono_shake : (string, Mono.file) transform val toMono_opt2 : (string, Mono.file) transform val toCjrize : (string, Cjr.file) transform + val toSqlify : (string, Cjr.file) transform end diff -r 09c66a30ef32 -r e4baf03a3a64 src/compiler.sml --- a/src/compiler.sml Tue Sep 02 13:09:54 2008 -0400 +++ b/src/compiler.sml Tue Sep 02 13:44:54 2008 -0400 @@ -37,7 +37,10 @@ type job = { database : string option, - sources : string list + sources : string list, + exe : string, + sql : string option, + debug : bool } type ('src, 'dst) phase = { @@ -190,15 +193,25 @@ handle LrParser.ParseError => [], print = SourcePrint.p_file} -fun p_job {database, sources} = +fun p_job {database, exe, sql, sources, debug} = let open Print.PD open Print in - box [case database of + box [if debug then + box [string "DEBUG", newline] + else + box [], + case database of NONE => string "No database." | SOME db => string ("Database: " ^ db), newline, + string "Exe: ", + string exe, + newline, + case sql of + NONE => string "No SQL file." + | SOME sql => string ("SQL fle: " ^ sql), string "Sources:", p_list string sources, newline] @@ -218,6 +231,10 @@ val dir = OS.Path.dir filename val inf = TextIO.openIn (OS.Path.joinBaseExt {base = filename, ext = SOME "urp"}) + fun relify fname = + OS.Path.concat (dir, fname) + handle OS.Path.Path => fname + fun readSources acc = case TextIO.inputLine inf of NONE => rev acc @@ -229,8 +246,7 @@ let val fname = String.implode (List.filter (fn x => not (Char.isSpace x)) (String.explode line)) - val fname = OS.Path.concat (dir, fname) - handle OS.Path.Path => fname + val fname = relify fname in fname :: acc end @@ -238,10 +254,18 @@ readSources acc end - fun read database = + fun finish (database, exe, sql, debug, sources) = + {database = database, + exe = Option.getOpt (exe, OS.Path.joinBaseExt {base = OS.Path.base filename, + ext = SOME "exe"}), + sql = sql, + debug = debug, + sources = sources} + + fun read (database, exe, sql, debug) = case TextIO.inputLine inf of - NONE => {database = database, sources = []} - | SOME "\n" => {database = database, sources = readSources []} + NONE => finish (database, exe, sql, debug, []) + | SOME "\n" => finish (database, exe, sql, debug, readSources []) | SOME line => let val (cmd, arg) = Substring.splitl (fn x => not (Char.isSpace x)) (Substring.full line) @@ -253,12 +277,23 @@ (case database of NONE => () | SOME _ => ErrorMsg.error "Duplicate 'database' directive"; - read (SOME arg)) + read (SOME arg, exe, sql, debug)) + | "exe" => + (case exe of + NONE => () + | SOME _ => ErrorMsg.error "Duplicate 'exe' directive"; + read (database, SOME (relify arg), sql, debug)) + | "sql" => + (case sql of + NONE => () + | SOME _ => ErrorMsg.error "Duplicate 'sql' directive"; + read (database, exe, SOME (relify arg), debug)) + | "debug" => read (database, exe, sql, true) | _ => (ErrorMsg.error ("Unrecognized command '" ^ cmd ^ "'"); - read database) + read (database, exe, sql, debug)) end in - read NONE + read (NONE, NONE, NONE, false) before TextIO.closeIn inf end, print = p_job @@ -270,7 +305,7 @@ | capitalize s = str (Char.toUpper (String.sub (s, 0))) ^ String.extract (s, 1, NONE) val parse = { - func = fn {database, sources = fnames} => + func = fn {database, sources = fnames, ...} : job => let fun nameOf fname = capitalize (OS.Path.file fname) @@ -414,6 +449,13 @@ val toCjrize = transform cjrize "cjrize" o toMono_opt2 +val sqlify = { + func = Cjrize.cjrize, + print = CjrPrint.p_sql CjrEnv.empty +} + +val toSqlify = transform sqlify "sqlify" o toMono_opt2 + fun compileC {cname, oname, ename} = let val compile = "gcc -O3 -I include -c " ^ cname ^ " -o " ^ oname @@ -432,17 +474,48 @@ NONE => print "Ur compilation failed\n" | SOME file => let - val cname = "/tmp/urweb.c" - val oname = "/tmp/urweb.o" - val ename = "/tmp/webapp" + val job = valOf (run (transform parseUrp "parseUrp") job) - val outf = TextIO.openOut cname - val s = TextIOPP.openOut {dst = outf, wid = 80} + val (cname, oname, cleanup) = + if #debug job then + ("/tmp/urweb.c", "/tmp/urweb.o", fn () => ()) + else + let + val dir = OS.FileSys.tmpName () + val cname = OS.Path.joinDirFile {dir = dir, file = "urweb.c"} + val oname = OS.Path.joinDirFile {dir = dir, file = "urweb.o"} + in + OS.FileSys.mkDir dir; + (cname, oname, + fn () => (OS.FileSys.remove cname; + OS.FileSys.remove oname; + OS.FileSys.rmDir dir)) + end + val ename = #exe job in - Print.fprint s (CjrPrint.p_file CjrEnv.empty file); - TextIO.closeOut outf; + let + val outf = TextIO.openOut cname + val s = TextIOPP.openOut {dst = outf, wid = 80} + in + Print.fprint s (CjrPrint.p_file CjrEnv.empty file); + TextIO.closeOut outf; - compileC {cname = cname, oname = oname, ename = ename} + case #sql job of + NONE => () + | SOME sql => + let + val outf = TextIO.openOut sql + val s = TextIOPP.openOut {dst = outf, wid = 80} + in + Print.fprint s (CjrPrint.p_sql CjrEnv.empty file); + TextIO.closeOut outf + end; + + compileC {cname = cname, oname = oname, ename = ename}; + + cleanup () + end + handle ex => (((cleanup ()) handle _ => ()); raise ex) end end diff -r 09c66a30ef32 -r e4baf03a3a64 src/monoize.sml --- a/src/monoize.sml Tue Sep 02 13:09:54 2008 -0400 +++ b/src/monoize.sml Tue Sep 02 13:44:54 2008 -0400 @@ -1417,6 +1417,7 @@ let val t = (L.CFfi ("Basis", "string"), loc) val t' = (L'.TFfi ("Basis", "string"), loc) + val s = "lw_" ^ s val e = (L'.EPrim (Prim.String s), loc) val xts = map (fn (x, t) => (monoName env x, monoType env t)) xts diff -r 09c66a30ef32 -r e4baf03a3a64 tests/query.urp --- a/tests/query.urp Tue Sep 02 13:09:54 2008 -0400 +++ b/tests/query.urp Tue Sep 02 13:44:54 2008 -0400 @@ -1,3 +1,6 @@ +debug database dbname=test +exe /tmp/webapp +sql /tmp/urweb.sql query