Mercurial > urweb
diff src/compiler.sml @ 764:7f653298dd66
C FFI compiler options
author | Adam Chlipala <adamc@hcoop.net> |
---|---|
date | Thu, 30 Apr 2009 17:15:14 -0400 |
parents | 43553c93dd8c |
children | a28982de5645 |
line wrap: on
line diff
--- a/src/compiler.sml Thu Apr 30 16:25:27 2009 -0400 +++ b/src/compiler.sml Thu Apr 30 17:15:14 2009 -0400 @@ -1,4 +1,4 @@ -(* Copyright (c) 2008, Adam Chlipala +(* Copyright (c) 2008-2009, Adam Chlipala * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -25,8 +25,6 @@ * POSSIBILITY OF SUCH DAMAGE. *) -(* Ur/Web language parser *) - structure Compiler :> COMPILER = struct structure UrwebLrVals = UrwebLrValsFn(structure Token = LrParser.Token) @@ -43,7 +41,10 @@ sql : string option, debug : bool, profile : bool, - timeout : int + timeout : int, + ffi : string list, + link : string list, + headers : string list } type ('src, 'dst) phase = { @@ -201,7 +202,7 @@ handle LrParser.ParseError => [], print = SourcePrint.p_file} -fun p_job {prefix, database, exe, sql, sources, debug, profile, timeout} = +fun p_job {prefix, database, exe, sql, sources, debug, profile, timeout, ffi, link, headers} = let open Print.PD open Print @@ -228,6 +229,9 @@ string "Timeout: ", string (Int.toString timeout), newline, + p_list_sep (box []) (fn s => box [string "Ffi", space, string s, newline]) ffi, + p_list_sep (box []) (fn s => box [string "Header", space, string s, newline]) headers, + p_list_sep (box []) (fn s => box [string "Link", space, string s, newline]) link, string "Sources:", p_list string sources, newline] @@ -251,6 +255,10 @@ OS.Path.concat (dir, fname) handle OS.Path.Path => fname + val absDir = OS.Path.mkAbsolute {path = dir, relativeTo = OS.FileSys.getDir ()} + + fun relifyA fname = OS.Path.mkAbsolute {path = fname, relativeTo = absDir} + fun readSources acc = case TextIO.inputLine inf of NONE => rev acc @@ -270,21 +278,35 @@ readSources acc end - fun finish (prefix, database, exe, sql, debug, profile, timeout, sources) = - {prefix = Option.getOpt (prefix, "/"), - database = database, - exe = Option.getOpt (exe, OS.Path.joinBaseExt {base = OS.Path.base filename, - ext = SOME "exe"}), - sql = sql, - debug = debug, - profile = profile, - timeout = Option.getOpt (timeout, 60), + val prefix = ref NONE + val database = ref NONE + val exe = ref NONE + val sql = ref NONE + val debug = ref false + val profile = ref false + val timeout = ref NONE + val ffi = ref [] + val link = ref [] + val headers = ref [] + + fun finish sources = + {prefix = Option.getOpt (!prefix, "/"), + database = !database, + exe = Option.getOpt (!exe, OS.Path.joinBaseExt {base = OS.Path.base filename, + ext = SOME "exe"}), + sql = !sql, + debug = !debug, + profile = !profile, + timeout = Option.getOpt (!timeout, 60), + ffi = !ffi, + link = !link, + headers = !headers, sources = sources} - fun read (prefix, database, exe, sql, debug, profile, timeout) = + fun read () = case TextIO.inputLine inf of - NONE => finish (prefix, database, exe, sql, debug, profile, timeout, []) - | SOME "\n" => finish (prefix, database, exe, sql, debug, profile, timeout, readSources []) + NONE => finish [] + | SOME "\n" => finish (readSources []) | SOME line => let val (cmd, arg) = Substring.splitl (fn x => not (Char.isSpace x)) (Substring.full line) @@ -293,41 +315,45 @@ in case cmd of "prefix" => - (case prefix of + (case !prefix of NONE => () | SOME _ => ErrorMsg.error "Duplicate 'prefix' directive"; - read (SOME arg, database, exe, sql, debug, profile, timeout)) + prefix := SOME arg) | "database" => - (case database of + (case !database of NONE => () | SOME _ => ErrorMsg.error "Duplicate 'database' directive"; - read (prefix, SOME arg, exe, sql, debug, profile, timeout)) + database := SOME arg) | "exe" => - (case exe of + (case !exe of NONE => () | SOME _ => ErrorMsg.error "Duplicate 'exe' directive"; - read (prefix, database, SOME (relify arg), sql, debug, profile, timeout)) + exe := SOME (relify arg)) | "sql" => - (case sql of + (case !sql of NONE => () | SOME _ => ErrorMsg.error "Duplicate 'sql' directive"; - read (prefix, database, exe, SOME (relify arg), debug, profile, timeout)) - | "debug" => read (prefix, database, exe, sql, true, profile, timeout) - | "profile" => read (prefix, database, exe, sql, debug, true, timeout) + sql := SOME (relify arg)) + | "debug" => debug := true + | "profile" => profile := true | "timeout" => - (case timeout of + (case !timeout of NONE => () | SOME _ => ErrorMsg.error "Duplicate 'timeout' directive"; - read (prefix, database, exe, sql, debug, profile, SOME (valOf (Int.fromString arg)))) - | _ => (ErrorMsg.error ("Unrecognized command '" ^ cmd ^ "'"); - read (prefix, database, exe, sql, debug, profile, timeout)) + timeout := SOME (valOf (Int.fromString arg))) + | "ffi" => ffi := relify arg :: !ffi + | "link" => link := relifyA arg :: !link + | "include" => headers := relifyA arg :: !headers + | _ => ErrorMsg.error ("Unrecognized command '" ^ cmd ^ "'"); + read () end - val job = read (NONE, NONE, NONE, NONE, false, false, NONE) + val job = read () in TextIO.closeIn inf; - Monoize.urlPrefix := #prefix job; - CjrPrint.timeout := #timeout job; + Settings.setUrlPrefix (#prefix job); + Settings.setTimeout (#timeout job); + Settings.setHeaders (#headers job); job end, print = p_job @@ -339,10 +365,24 @@ | capitalize s = str (Char.toUpper (String.sub (s, 0))) ^ String.extract (s, 1, NONE) val parse = { - func = fn {database, sources = fnames, ...} : job => + func = fn {database, sources = fnames, ffi, ...} : job => let fun nameOf fname = capitalize (OS.Path.file fname) + fun parseFfi fname = + let + val mname = nameOf fname + val urs = OS.Path.joinBaseExt {base = fname, ext = SOME "urs"} + + val loc = {file = urs, + first = ErrorMsg.dummyPos, + last = ErrorMsg.dummyPos} + + val sgn = (Source.SgnConst (#func parseUrs urs), loc) + in + (Source.DFfiStr (mname, sgn), loc) + end + fun parseOne fname = let val mname = nameOf fname @@ -367,12 +407,14 @@ (Source.DStr (mname, sgnO, (Source.StrConst ds, loc)), loc) end + val dsFfi = map parseFfi ffi val ds = map parseOne fnames in let val final = nameOf (List.last fnames) - val ds = ds @ [(Source.DExport (Source.StrVar final, ErrorMsg.dummySpan), ErrorMsg.dummySpan)] + val ds = dsFfi @ ds + @ [(Source.DExport (Source.StrVar final, ErrorMsg.dummySpan), ErrorMsg.dummySpan)] in case database of NONE => ds @@ -605,7 +647,7 @@ val toSqlify = transform sqlify "sqlify" o toMono_opt2 -fun compileC {cname, oname, ename, libs, profile, debug} = +fun compileC {cname, oname, ename, libs, profile, debug, link = link'} = let val urweb_o = clibFile "urweb.o" val driver_o = clibFile "driver.o" @@ -624,6 +666,8 @@ (compile ^ " -g", link ^ " -g") else (compile, link) + + val link = foldl (fn (s, link) => link ^ " " ^ s) link link' in if not (OS.Process.isSuccess (OS.Process.system compile)) then print "C compilation failed\n" @@ -689,7 +733,7 @@ end; compileC {cname = cname, oname = oname, ename = ename, libs = libs, - profile = #profile job, debug = #debug job}; + profile = #profile job, debug = #debug job, link = #link job}; cleanup () end