diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/c/memmem.c | 15 | ||||
-rw-r--r-- | src/c/memmem.h | 23 | ||||
-rw-r--r-- | src/c/request.c | 5 | ||||
-rw-r--r-- | src/c/urweb.c | 2 | ||||
-rw-r--r-- | src/cjr_print.sml | 8 | ||||
-rw-r--r-- | src/compiler.sig | 2 | ||||
-rw-r--r-- | src/compiler.sml | 10 | ||||
-rw-r--r-- | src/core_util.sig | 6 | ||||
-rw-r--r-- | src/core_util.sml | 16 | ||||
-rw-r--r-- | src/demo.sml | 1 | ||||
-rw-r--r-- | src/monoize.sml | 31 | ||||
-rw-r--r-- | src/mysql.sml | 2 | ||||
-rw-r--r-- | src/postgres.sml | 2 | ||||
-rw-r--r-- | src/settings.sig | 5 | ||||
-rw-r--r-- | src/settings.sml | 11 | ||||
-rw-r--r-- | src/specialize.sml | 134 | ||||
-rw-r--r-- | src/sqlite.sml | 2 |
17 files changed, 203 insertions, 72 deletions
diff --git a/src/c/memmem.c b/src/c/memmem.c index f31f4e31..efddd0c1 100644 --- a/src/c/memmem.c +++ b/src/c/memmem.c @@ -1,4 +1,6 @@ -#include "config.h" +#include "memmem.h" + +#ifndef HAVE_MEMMEM /* $NetBSD$ */ @@ -38,8 +40,6 @@ * POSSIBILITY OF SUCH DAMAGE. */ -// Function renamed by Adam Chlipala in 2016. - #include <sys/cdefs.h> #if defined(LIBC_SCCS) && !defined(lint) __RCSID("$NetBSD$"); @@ -54,13 +54,8 @@ __RCSID("$NetBSD$"); #define NULL ((char *)0) #endif -/* - * urweb_memmem() returns the location of the first occurence of data - * pattern b2 of size len2 in memory block b1 of size len1 or - * NULL if none is found. - */ void * -urweb_memmem(const void *b1, size_t len1, const void *b2, size_t len2) +memmem(const void *b1, size_t len1, const void *b2, size_t len2) { /* Sanity check */ if(!(b1 != NULL && b2 != NULL && len1 != 0 && len2 != 0)) @@ -85,3 +80,5 @@ urweb_memmem(const void *b1, size_t len1, const void *b2, size_t len2) return NULL; } + +#endif // !defined(HAVE_MEMMEM) diff --git a/src/c/memmem.h b/src/c/memmem.h new file mode 100644 index 00000000..0ddbb494 --- /dev/null +++ b/src/c/memmem.h @@ -0,0 +1,23 @@ +#ifndef URWEB_MEMMEM_H +#define URWEB_MEMMEM_H + +#include "config.h" + +#ifdef HAVE_MEMMEM + +#include <string.h> + +#else // !defined(HAVE_MEMMEM) + +#include <stddef.h> + +/* + * memmem() returns the location of the first occurence of data + * pattern b2 of size len2 in memory block b1 of size len1 or + * NULL if none is found. + */ +void *memmem(const void *b1, size_t len1, const void *b2, size_t len2); + +#endif // !defined(HAVE_MEMMEM) + +#endif // URWEB_MEMMEM_H diff --git a/src/c/request.c b/src/c/request.c index 3e7ac34c..195b3cdc 100644 --- a/src/c/request.c +++ b/src/c/request.c @@ -11,13 +11,12 @@ #include <pthread.h> +#include "memmem.h" #include "urweb.h" #include "request.h" #define MAX_RETRIES 5 -void *urweb_memmem(const void *b1, size_t len1, const void *b2, size_t len2); - static int try_rollback(uw_context ctx, int will_retry, void *logger_data, uw_logger log_error) { int r = uw_rollback(ctx, will_retry); @@ -422,7 +421,7 @@ request_result uw_request(uw_request_context rc, uw_context ctx, } } - part = urweb_memmem(after_sub_headers, body + body_len - after_sub_headers, boundary, boundary_len); + part = memmem(after_sub_headers, body + body_len - after_sub_headers, boundary, boundary_len); if (!part) { log_error(logger_data, "Missing boundary after multipart payload\n"); return FAILED; diff --git a/src/c/urweb.c b/src/c/urweb.c index 78946872..6f36e3ed 100644 --- a/src/c/urweb.c +++ b/src/c/urweb.c @@ -4328,7 +4328,7 @@ uw_Basis_time uw_Basis_fromDatetime(uw_context ctx, uw_Basis_int year, uw_Basis_ struct tm tm = { .tm_year = year - 1900, .tm_mon = month, .tm_mday = day, .tm_hour = hour, .tm_min = minute, .tm_sec = second, .tm_isdst = -1 }; - uw_Basis_time r = { timelocal(&tm) }; + uw_Basis_time r = { mktime(&tm) }; return r; } diff --git a/src/cjr_print.sml b/src/cjr_print.sml index 87d2576c..e0153944 100644 --- a/src/cjr_print.sml +++ b/src/cjr_print.sml @@ -3783,7 +3783,13 @@ fun p_sql env (ds, _) = end) env ds in - box (string (#sqlPrefix (Settings.currentDbms ())) :: pps) + box ((case Settings.getFileCache () of + NONE => [] + | SOME _ => case #supportsSHA512 (Settings.currentDbms ()) of + NONE => (ErrorMsg.error "Using file cache with database that doesn't support SHA512"; + []) + | SOME line => [string line, newline, newline]) + @ string (#sqlPrefix (Settings.currentDbms ())) :: pps) end end diff --git a/src/compiler.sig b/src/compiler.sig index bcf69fd4..09c913f8 100644 --- a/src/compiler.sig +++ b/src/compiler.sig @@ -61,6 +61,7 @@ signature COMPILER = sig dbms : string option, sigFile : string option, fileCache : string option, + safeGetDefault : bool, safeGets : string list, onError : (string * string list * string) option, minHeap : int, @@ -163,6 +164,7 @@ signature COMPILER = sig val toUnpoly2 : (string, Core.file) transform val toShake4'' : (string, Core.file) transform val toEspecialize3 : (string, Core.file) transform + val toSpecialize3 : (string, Core.file) transform val toReduce2 : (string, Core.file) transform val toShake5 : (string, Core.file) transform val toMarshalcheck : (string, Core.file) transform diff --git a/src/compiler.sml b/src/compiler.sml index faf5bbe6..868dd628 100644 --- a/src/compiler.sml +++ b/src/compiler.sml @@ -65,6 +65,7 @@ type job = { dbms : string option, sigFile : string option, fileCache : string option, + safeGetDefault : bool, safeGets : string list, onError : (string * string list * string) option, minHeap : int, @@ -385,6 +386,7 @@ fun institutionalizeJob (job : job) = Settings.setMetaRules (#filterMeta job); Option.app Settings.setProtocol (#protocol job); Option.app Settings.setDbms (#dbms job); + Settings.setSafeGetDefault (#safeGetDefault job); Settings.setSafeGets (#safeGets job); Settings.setOnError (#onError job); Settings.setMinHeap (#minHeap job); @@ -470,6 +472,7 @@ fun parseUrp' accLibs fname = dbms = NONE, sigFile = NONE, fileCache = NONE, + safeGetDefault = false, safeGets = [], onError = NONE, minHeap = 0, @@ -605,6 +608,7 @@ fun parseUrp' accLibs fname = val dbms = ref NONE val sigFile = ref (Settings.getSigFile ()) val fileCache = ref (Settings.getFileCache ()) + val safeGetDefault = ref false val safeGets = ref [] val onError = ref NONE val minHeap = ref 0 @@ -645,6 +649,7 @@ fun parseUrp' accLibs fname = dbms = !dbms, sigFile = !sigFile, fileCache = !fileCache, + safeGetDefault = !safeGetDefault, safeGets = rev (!safeGets), onError = !onError, minHeap = !minHeap, @@ -708,6 +713,7 @@ fun parseUrp' accLibs fname = dbms = mergeO #2 (#dbms old, #dbms new), sigFile = mergeO #2 (#sigFile old, #sigFile new), fileCache = mergeO #2 (#fileCache old, #fileCache new), + safeGetDefault = #safeGetDefault old orelse #safeGetDefault new, safeGets = #safeGets old @ #safeGets new, onError = mergeO #2 (#onError old, #onError new), minHeap = Int.max (#minHeap old, #minHeap new), @@ -829,6 +835,7 @@ fun parseUrp' accLibs fname = | "include" => headers := relifyA arg :: !headers | "script" => scripts := arg :: !scripts | "clientToServer" => clientToServer := ffiS () :: !clientToServer + | "safeGetDefault" => safeGetDefault := true | "safeGet" => safeGets := arg :: !safeGets | "effectful" => effectful := ffiS () :: !effectful | "benignEffectful" => benignEffectful := ffiS () :: !benignEffectful @@ -1383,8 +1390,9 @@ val toUnpoly2 = transform unpoly "unpoly2" o toShake4' val toSpecialize2 = transform specialize "specialize2" o toUnpoly2 val toShake4'' = transform shake "shake4'" o toSpecialize2 val toEspecialize3 = transform especialize "especialize3" o toShake4'' +val toSpecialize3 = transform specialize "specialize3" o toEspecialize3 -val toReduce2 = transform reduce "reduce2" o toEspecialize3 +val toReduce2 = transform reduce "reduce2" o toSpecialize3 val toShake5 = transform shake "shake5" o toReduce2 diff --git a/src/core_util.sig b/src/core_util.sig index 835577a3..8d295f1e 100644 --- a/src/core_util.sig +++ b/src/core_util.sig @@ -161,6 +161,12 @@ structure Decl : sig decl : (Core.decl', 'state, 'abort) Search.mapfolder} -> (Core.decl, 'state, 'abort) Search.mapfolder + val map : {kind : Core.kind' -> Core.kind', + con : Core.con' -> Core.con', + exp : Core.exp' -> Core.exp', + decl : Core.decl' -> Core.decl'} + -> Core.decl -> Core.decl + val fold : {kind : Core.kind' * 'state -> 'state, con : Core.con' * 'state -> 'state, exp : Core.exp' * 'state -> 'state, diff --git a/src/core_util.sml b/src/core_util.sml index 57ef16f7..d1d3d9c4 100644 --- a/src/core_util.sml +++ b/src/core_util.sml @@ -1029,6 +1029,22 @@ fun mapfold {kind = fk, con = fc, exp = fe, decl = fd} = decl = fn () => fd, bind = fn ((), _) => ()} () +fun mapB {kind, con, exp, decl, bind} ctx d = + case mapfoldB {kind = fn ctx => fn k => fn () => S.Continue (kind ctx k, ()), + con = fn ctx => fn c => fn () => S.Continue (con ctx c, ()), + exp = fn ctx => fn e => fn () => S.Continue (exp ctx e, ()), + decl = fn ctx => fn d => fn () => S.Continue (decl ctx d, ()), + bind = bind} ctx d () of + S.Continue (d, ()) => d + | S.Return _ => raise Fail "CoreUtil.Decl.mapB: Impossible" + +fun map {kind, con, exp, decl} d = + mapB {kind = fn () => kind, + con = fn () => con, + exp = fn () => exp, + decl = fn () => decl, + bind = fn _ => ()} () d + fun fold {kind, con, exp, decl} s d = case mapfold {kind = fn k => fn s => S.Continue (k, kind (k, s)), con = fn c => fn s => S.Continue (c, con (c, s)), diff --git a/src/demo.sml b/src/demo.sml index 1e58e2f8..eaec38bb 100644 --- a/src/demo.sml +++ b/src/demo.sml @@ -124,6 +124,7 @@ fun make' {prefix, dirname, guided} = dbms = mergeWith #2 (#dbms combined, #dbms urp), sigFile = mergeWith #2 (#sigFile combined, #sigFile urp), fileCache = mergeWith #2 (#fileCache combined, #fileCache urp), + safeGetDefault = #safeGetDefault combined orelse #safeGetDefault urp, safeGets = #safeGets combined @ #safeGets urp, onError = NONE, minHeap = 0, diff --git a/src/monoize.sml b/src/monoize.sml index dfa88be3..48001a13 100644 --- a/src/monoize.sml +++ b/src/monoize.sml @@ -1540,17 +1540,31 @@ fun monoExp (env, st, fm) (all as (e, loc)) = | L.EFfiApp ("Basis", "dml", [(e, _)]) => let + val string = (L'.TFfi ("Basis", "string"), loc) val (e, fm) = monoExp (env, st, fm) e in - ((L'.EDml (e, L'.Error), loc), + ((L'.ECase (e, + [((L'.PPrim (Prim.String (Prim.Normal, "")), loc), + (L'.ERecord [], loc)), + ((L'.PVar ("cmd", string), loc), + (L'.EDml ((L'.ERel 0, loc), L'.Error), loc))], + {disc = string, + result = (L'.TRecord [], loc)}), loc), fm) end | L.EFfiApp ("Basis", "tryDml", [(e, _)]) => let + val string = (L'.TFfi ("Basis", "string"), loc) val (e, fm) = monoExp (env, st, fm) e in - ((L'.EDml (e, L'.None), loc), + ((L'.ECase (e, + [((L'.PPrim (Prim.String (Prim.Normal, "")), loc), + (L'.ERecord [], loc)), + ((L'.PVar ("cmd", string), loc), + (L'.EDml ((L'.ERel 0, loc), L'.None), loc))], + {disc = string, + result = (L'.TRecord [], loc)}), loc), fm) end @@ -1579,7 +1593,18 @@ fun monoExp (env, st, fm) (all as (e, loc)) = | L.ECApp ((L.ECApp ((L.ECApp ((L.EFfi ("Basis", "update"), _), _), _), _), _), changed) => (case monoType env (L.TRecord changed, loc) of - (L'.TRecord changed, _) => + (L'.TRecord [], _) => + let + val s = (L'.TFfi ("Basis", "string"), loc) + val rt = (L'.TRecord [], loc) + in + ((L'.EAbs ("fs", rt, (L'.TFun (s, (L'.TFun (s, s), loc)), loc), + (L'.EAbs ("tab", s, (L'.TFun (s, s), loc), + (L'.EAbs ("e", s, s, + str ""), loc)), loc)), loc), + fm) + end + | (L'.TRecord changed, _) => let val s = (L'.TFfi ("Basis", "string"), loc) val changed = map (fn (x, _) => (x, s)) changed diff --git a/src/mysql.sml b/src/mysql.sml index e7cad84e..768c5441 100644 --- a/src/mysql.sml +++ b/src/mysql.sml @@ -1610,6 +1610,6 @@ val () = addDbms {name = "mysql", nestedRelops = false, windowFunctions = false, supportsIsDistinctFrom = true, - supportsSHA512 = false} + supportsSHA512 = NONE} end diff --git a/src/postgres.sml b/src/postgres.sml index 2b6bee8c..a33a1de4 100644 --- a/src/postgres.sml +++ b/src/postgres.sml @@ -1154,7 +1154,7 @@ val () = addDbms {name = "postgres", nestedRelops = true, windowFunctions = true, supportsIsDistinctFrom = true, - supportsSHA512 = true} + supportsSHA512 = SOME "CREATE EXTENSION pgcrypto;"} val () = setDbms "postgres" diff --git a/src/settings.sig b/src/settings.sig index 29817467..a6a9c5fc 100644 --- a/src/settings.sig +++ b/src/settings.sig @@ -222,7 +222,9 @@ signature SETTINGS = sig nestedRelops : bool, windowFunctions : bool, supportsIsDistinctFrom : bool, - supportsSHA512 : bool + supportsSHA512 : string option (* If supported, give the SQL code to + * enable the feature in a particular + * database. *) } val addDbms : dbms -> unit @@ -260,6 +262,7 @@ signature SETTINGS = sig val getFileCache : unit -> string option (* Which GET-able functions should be allowed to have side effects? *) + val setSafeGetDefault : bool -> unit val setSafeGets : string list -> unit val isSafeGet : string -> bool diff --git a/src/settings.sml b/src/settings.sml index 2e386a4f..f42df135 100644 --- a/src/settings.sml +++ b/src/settings.sml @@ -648,7 +648,7 @@ type dbms = { nestedRelops : bool, windowFunctions: bool, supportsIsDistinctFrom : bool, - supportsSHA512 : bool + supportsSHA512 : string option } val dbmses = ref ([] : dbms list) @@ -682,7 +682,7 @@ val curDb = ref ({name = "", nestedRelops = false, windowFunctions = false, supportsIsDistinctFrom = false, - supportsSHA512 = false} : dbms) + supportsSHA512 = NONE} : dbms) fun addDbms v = dbmses := v :: !dbmses fun setDbms s = @@ -729,7 +729,8 @@ fun getSigFile () = !sigFile val fileCache = ref (NONE : string option) fun setFileCache v = - (if Option.isSome v andalso not (#supportsSHA512 (currentDbms ())) then + (if Option.isSome v andalso (case #supportsSHA512 (currentDbms ()) of NONE => true + | SOME _ => false) then ErrorMsg.error "The selected database engine is incompatible with file caching." else (); @@ -741,9 +742,11 @@ structure SS = BinarySetFn(struct val compare = String.compare end) +val safeGetDefault = ref false val safeGet = ref SS.empty +fun setSafeGetDefault b = safeGetDefault := b fun setSafeGets ls = safeGet := SS.addList (SS.empty, ls) -fun isSafeGet x = SS.member (!safeGet, x) +fun isSafeGet x = !safeGetDefault orelse SS.member (!safeGet, x) val onError = ref (NONE : (string * string list * string) option) fun setOnError x = onError := x diff --git a/src/specialize.sml b/src/specialize.sml index 33545250..70e646e3 100644 --- a/src/specialize.sml +++ b/src/specialize.sml @@ -44,6 +44,7 @@ end structure CM = BinaryMapFn(CK) structure IM = IntBinaryMap +structure IS = IntBinarySet type datatyp' = { name : int, @@ -61,7 +62,7 @@ type state = { count : int, datatypes : datatyp IM.map, constructors : int IM.map, - decls : (string * int * string list * (string * int * con option) list) list + decls : (string * int * string list * (string * int * con option) list) list } fun kind (k, st) = (k, st) @@ -72,6 +73,12 @@ val isOpen = U.Con.exists {kind = fn _ => false, CRel _ => true | _ => false} +fun findApp (c, args) = + case c of + CApp ((c', _), arg) => findApp (c', arg :: args) + | CNamed n => SOME (n, args) + | _ => NONE + fun considerSpecialization (st : state, n, args, dt : datatyp) = let val args = map ReduceLocal.reduceCon args @@ -132,31 +139,20 @@ fun considerSpecialization (st : state, n, args, dt : datatyp) = end and con (c, st : state) = - let - fun findApp (c, args) = - case c of - CApp ((c', _), arg) => findApp (c', arg :: args) - | CNamed n => SOME (n, args) - | _ => NONE - in - case findApp (c, []) of - SOME (n, args as (_ :: _)) => - if List.exists isOpen args then - (c, st) - else - (case IM.find (#datatypes st, n) of - NONE => (c, st) - | SOME dt => - if length args <> #params dt then - (c, st) - else - let - val (n, _, st) = considerSpecialization (st, n, args, dt) - in - (CNamed n, st) - end) - | _ => (c, st) - end + case findApp (c, []) of + SOME (n, args as ((_, loc) :: _)) => + (case IM.find (#datatypes st, n) of + NONE => (c, st) + | SOME dt => + if length args <> #params dt then + (c, st) + else + let + val (n, _, st) = considerSpecialization (st, n, args, dt) + in + (CNamed n, st) + end) + | _ => (c, st) and specCon st = U.Con.foldMap {kind = kind, con = con} st @@ -252,6 +248,48 @@ val specDecl = U.Decl.foldMap {kind = kind, con = con, exp = exp, decl = decl} fun specialize file = let + (*val () = CorePrint.debug := true + val () = print "SPECIALIZING\n"*) + + (* Let's run around a file, finding any polymorphic uses of a datatype. + * However, don't count polymorphism within a datatype's own definition! + * To that end, we run a silly transform on the file before traversing. *) + val file' = + map (fn d => + case #1 d of + DDatatype dts => + U.Decl.map {kind = fn x => x, + exp = fn x => x, + decl = fn x => x, + con = fn CNamed n => + if List.exists (fn (_, n', _, _) => n' = n) dts then + CUnit + else + CNamed n + | c => c} d + | _ => d) file + + val fancyDatatypes = U.File.fold {kind = fn (_, fd) => fd, + exp = fn (_, fd) => fd, + decl = fn (_, fd) => fd, + con = fn (c, fd) => + case c of + CApp (c1, c2) => + if isOpen c2 then + case findApp (c, []) of + SOME (n, _) => + ((*Print.preface ("Disqualifier", + CorePrint.p_con CoreEnv.empty (c, ErrorMsg.dummySpan));*) + IS.add (fd, n)) + | NONE => fd + else + fd + | _ => fd} + IS.empty file' + + (* Why did we find the polymorphism? + * It would be incoherent to specialize a datatype used polymorphically. *) + fun doDecl (d, st) = let (*val () = Print.preface ("decl:", CorePrint.p_decl CoreEnv.empty all)*) @@ -259,23 +297,27 @@ fun specialize file = in case #1 d of DDatatype dts => - ((case #decls st of - [] => [d] - | dts' => [(DDatatype (dts' @ dts), #2 d)]), - {count = #count st, - datatypes = foldl (fn ((x, n, xs, xnts), dts) => - IM.insert (dts, n, - {name = x, - params = length xs, - constructors = xnts, - specializations = CM.empty})) - (#datatypes st) dts, - constructors = foldl (fn ((x, n, xs, xnts), cs) => - foldl (fn ((_, n', _), constructors) => - IM.insert (constructors, n', n)) + if List.exists (fn (_, n, _, _) => IS.member (fancyDatatypes, n)) dts then + ((*Print.preface ("Skipping", CorePrint.p_decl CoreEnv.empty d);*) + ([d], st)) + else + ((case #decls st of + [] => [d] + | dts' => [(DDatatype (dts' @ dts), #2 d)]), + {count = #count st, + datatypes = foldl (fn ((x, n, xs, xnts), dts) => + IM.insert (dts, n, + {name = x, + params = length xs, + constructors = xnts, + specializations = CM.empty})) + (#datatypes st) dts, + constructors = foldl (fn ((x, n, xs, xnts), cs) => + foldl (fn ((_, n', _), constructors) => + IM.insert (constructors, n', n)) cs xnts) - (#constructors st) dts, - decls = []}) + (#constructors st) dts, + decls = []}) | _ => (case #decls st of [] => [d] @@ -287,10 +329,10 @@ fun specialize file = end val (ds, _) = ListUtil.foldlMapConcat doDecl - {count = U.File.maxName file + 1, - datatypes = IM.empty, - constructors = IM.empty, - decls = []} file + {count = U.File.maxName file + 1, + datatypes = IM.empty, + constructors = IM.empty, + decls = []} file in ds end diff --git a/src/sqlite.sml b/src/sqlite.sml index db7052d1..0a3ae4ea 100644 --- a/src/sqlite.sml +++ b/src/sqlite.sml @@ -856,6 +856,6 @@ val () = addDbms {name = "sqlite", nestedRelops = false, windowFunctions = false, supportsIsDistinctFrom = false, - supportsSHA512 = false} + supportsSHA512 = NONE} end |