summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Adam Chlipala <adamc@hcoop.net>2008-11-06 12:08:41 -0500
committerGravatar Adam Chlipala <adamc@hcoop.net>2008-11-06 12:08:41 -0500
commitbffeb0e5a10ae58b8f7c3f5249b3665373236e21 (patch)
treeab9e9c68fbb15a38d5a42e489dbc1ecdfd886525
parent09d844ebdc60010b6b19d1833c213bcbba035515 (diff)
Reading cookies works
-rw-r--r--include/urweb.h2
-rw-r--r--src/c/urweb.c16
-rw-r--r--src/cjr.sml1
-rw-r--r--src/cjr_print.sml741
-rw-r--r--src/cjrize.sml7
-rw-r--r--src/mono.sml2
-rw-r--r--src/mono_print.sml3
-rw-r--r--src/mono_reduce.sml2
-rw-r--r--src/mono_util.sml6
-rw-r--r--src/monoize.sml4
-rw-r--r--src/prepare.sml7
-rw-r--r--tests/cookie.ur2
12 files changed, 440 insertions, 353 deletions
diff --git a/include/urweb.h b/include/urweb.h
index 4fb2d612..2330a0b4 100644
--- a/include/urweb.h
+++ b/include/urweb.h
@@ -100,4 +100,6 @@ uw_Basis_time uw_Basis_stringToTime_error(uw_context, uw_Basis_string);
uw_Basis_string uw_Basis_requestHeader(uw_context, uw_Basis_string);
void uw_write_header(uw_context, uw_Basis_string);
+
+uw_Basis_string uw_Basis_get_cookie(uw_context, uw_Basis_string);
uw_unit uw_Basis_set_cookie(uw_context, uw_Basis_string, uw_Basis_string);
diff --git a/src/c/urweb.c b/src/c/urweb.c
index dc58576a..be12c5ea 100644
--- a/src/c/urweb.c
+++ b/src/c/urweb.c
@@ -1143,7 +1143,23 @@ uw_Basis_string uw_Basis_requestHeader(uw_context ctx, uw_Basis_string h) {
return NULL;
}
}
+}
+
+uw_Basis_string uw_Basis_get_cookie(uw_context ctx, uw_Basis_string c) {
+ int len = strlen(c);
+ char *s = ctx->headers, *p;
+ while (p = strchr(s, ':')) {
+ if (!strncasecmp(s, "Cookie: ", 8) && !strncmp(p + 2, c, len)
+ && p + 2 + len < ctx->headers_end && p[2 + len] == '=') {
+ return p + 3 + len;
+ } else {
+ if ((s = strchr(p, 0)) && s < ctx->headers_end)
+ s += 2;
+ else
+ return NULL;
+ }
+ }
}
uw_unit uw_Basis_set_cookie(uw_context ctx, uw_Basis_string c, uw_Basis_string v) {
diff --git a/src/cjr.sml b/src/cjr.sml
index dc700a56..84aea54e 100644
--- a/src/cjr.sml
+++ b/src/cjr.sml
@@ -92,6 +92,7 @@ datatype exp' =
prepared : int option }
| ENextval of { seq : exp,
prepared : int option }
+ | EUnurlify of exp * typ
withtype exp = exp' located
diff --git a/src/cjr_print.sml b/src/cjr_print.sml
index f1f4ef70..06154b91 100644
--- a/src/cjr_print.sml
+++ b/src/cjr_print.sml
@@ -62,6 +62,12 @@ val ident = String.translate (fn #"'" => "PRIME"
val p_ident = string o ident
+fun isUnboxable (t : typ) =
+ case #1 t of
+ TDatatype (Default, _, _) => true
+ | TFfi ("Basis", "string") => true
+ | _ => false
+
fun p_typ' par env (t, loc) =
case t of
TFun (t1, t2) => parenIf par (box [p_typ' true env t2,
@@ -96,11 +102,11 @@ fun p_typ' par env (t, loc) =
handle CjrEnv.UnboundNamed _ => string ("__uwd_UNBOUND__" ^ Int.toString n))
| TFfi (m, x) => box [string "uw_", p_ident m, string "_", p_ident x]
| TOption t =>
- (case #1 t of
- TDatatype _ => p_typ' par env t
- | TFfi ("Basis", "string") => p_typ' par env t
- | _ => box [p_typ' par env t,
- string "*"])
+ if isUnboxable t then
+ p_typ' par env t
+ else
+ box [p_typ' par env t,
+ string "*"]
and p_typ env = p_typ' false env
@@ -228,13 +234,12 @@ fun p_pat (env, exit, depth) (p, _) =
string "->data.",
string x]
| Option =>
- case #1 t of
- TDatatype _ => box [string "disc",
- string (Int.toString depth)]
- | TFfi ("Basis", "string") => box [string "disc",
- string (Int.toString depth)]
- | _ => box [string "*disc",
- string (Int.toString depth)],
+ if isUnboxable t then
+ box [string "disc",
+ string (Int.toString depth)]
+ else
+ box [string "*disc",
+ string (Int.toString depth)],
string ";",
newline,
p,
@@ -335,13 +340,12 @@ fun p_pat (env, exit, depth) (p, _) =
space,
string "=",
space,
- case #1 t of
- TDatatype _ => box [string "disc",
- string (Int.toString depth)]
- | TFfi ("Basis", "string") => box [string "disc",
- string (Int.toString depth)]
- | _ => box [string "*disc",
- string (Int.toString depth)],
+ if isUnboxable t then
+ box [string "disc",
+ string (Int.toString depth)]
+ else
+ box [string "*disc",
+ string (Int.toString depth)],
string ";",
newline,
p,
@@ -468,6 +472,288 @@ fun notLeaky env allowHeapAllocated =
nl
end
+fun capitalize s =
+ if s = "" then
+ ""
+ else
+ str (Char.toUpper (String.sub (s, 0))) ^ String.extract (s, 1, NONE)
+
+fun unurlify env (t, loc) =
+ let
+ fun unurlify' rf t =
+ case t of
+ TFfi ("Basis", "unit") => string ("uw_unit_v")
+ | TFfi (m, t) => string ("uw_" ^ ident m ^ "_unurlify" ^ capitalize t ^ "(ctx, &request)")
+
+ | TRecord 0 => string "uw_unit_v"
+ | TRecord i =>
+ let
+ val xts = E.lookupStruct env i
+ in
+ box [string "({",
+ newline,
+ box (map (fn (x, t) =>
+ box [p_typ env t,
+ space,
+ string "uwr_",
+ string x,
+ space,
+ string "=",
+ space,
+ unurlify' rf (#1 t),
+ string ";",
+ newline]) xts),
+ string "struct",
+ space,
+ string "__uws_",
+ string (Int.toString i),
+ space,
+ string "tmp",
+ space,
+ string "=",
+ space,
+ string "{",
+ space,
+ p_list_sep (box [string ",", space]) (fn (x, _) => box [string "uwr_",
+ string x]) xts,
+ space,
+ string "};",
+ newline,
+ string "tmp;",
+ newline,
+ string "})"]
+ end
+
+ | TDatatype (Enum, i, _) =>
+ let
+ val (x, xncs) = E.lookupDatatype env i
+
+ fun doEm xncs =
+ case xncs of
+ [] => string ("(uw_error(ctx, FATAL, \"Error unurlifying datatype "
+ ^ x ^ "\"), (enum __uwe_"
+ ^ x ^ "_" ^ Int.toString i ^ ")0)")
+ | (x', n, to) :: rest =>
+ box [string "((!strncmp(request, \"",
+ string x',
+ string "\", ",
+ string (Int.toString (size x')),
+ string ") && (request[",
+ string (Int.toString (size x')),
+ string "] == 0 || request[",
+ string (Int.toString (size x')),
+ string ("] == '/')) ? __uwc_" ^ ident x' ^ "_" ^ Int.toString n),
+ space,
+ string ":",
+ space,
+ doEm rest,
+ string ")"]
+ in
+ doEm xncs
+ end
+
+ | TDatatype (Option, i, xncs) =>
+ if IS.member (rf, i) then
+ box [string "unurlify_",
+ string (Int.toString i),
+ string "()"]
+ else
+ let
+ val (x, _) = E.lookupDatatype env i
+
+ val (no_arg, has_arg, t) =
+ case !xncs of
+ [(no_arg, _, NONE), (has_arg, _, SOME t)] =>
+ (no_arg, has_arg, t)
+ | [(has_arg, _, SOME t), (no_arg, _, NONE)] =>
+ (no_arg, has_arg, t)
+ | _ => raise Fail "CjrPrint: unfooify misclassified Option datatype"
+
+ val rf = IS.add (rf, i)
+ in
+ box [string "({",
+ space,
+ p_typ env t,
+ space,
+ string "*unurlify_",
+ string (Int.toString i),
+ string "(void) {",
+ newline,
+ box [string "return (request[0] == '/' ? ++request : request,",
+ newline,
+ string "((!strncmp(request, \"",
+ string no_arg,
+ string "\", ",
+ string (Int.toString (size no_arg)),
+ string ") && (request[",
+ string (Int.toString (size no_arg)),
+ string "] == 0 || request[",
+ string (Int.toString (size no_arg)),
+ string "] == '/')) ? (request",
+ space,
+ string "+=",
+ space,
+ string (Int.toString (size no_arg)),
+ string ", NULL) : ((!strncmp(request, \"",
+ string has_arg,
+ string "\", ",
+ string (Int.toString (size has_arg)),
+ string ") && (request[",
+ string (Int.toString (size has_arg)),
+ string "] == 0 || request[",
+ string (Int.toString (size has_arg)),
+ string "] == '/')) ? (request",
+ space,
+ string "+=",
+ space,
+ string (Int.toString (size has_arg)),
+ string ", (request[0] == '/' ? ++request : NULL), ",
+ newline,
+
+ if isUnboxable t then
+ unurlify' rf (#1 t)
+ else
+ box [string "({",
+ newline,
+ p_typ env t,
+ space,
+ string "*tmp",
+ space,
+ string "=",
+ space,
+ string "uw_malloc(ctx, sizeof(",
+ p_typ env t,
+ string "));",
+ newline,
+ string "*tmp",
+ space,
+ string "=",
+ space,
+ unurlify' rf (#1 t),
+ string ";",
+ newline,
+ string "tmp;",
+ newline,
+ string "})"],
+ string ")",
+ newline,
+ string ":",
+ space,
+ string ("(uw_error(ctx, FATAL, \"Error unurlifying datatype " ^ x
+ ^ "\"), NULL))));"),
+ newline],
+ string "}",
+ newline,
+ newline,
+
+ string "unurlify_",
+ string (Int.toString i),
+ string "();",
+ newline,
+ string "})"]
+ end
+
+ | TDatatype (Default, i, _) =>
+ if IS.member (rf, i) then
+ box [string "unurlify_",
+ string (Int.toString i),
+ string "()"]
+ else
+ let
+ val (x, xncs) = E.lookupDatatype env i
+
+ val rf = IS.add (rf, i)
+
+ fun doEm xncs =
+ case xncs of
+ [] => string ("(uw_error(ctx, FATAL, \"Error unurlifying datatype "
+ ^ x ^ "\"), NULL)")
+ | (x', n, to) :: rest =>
+ box [string "((!strncmp(request, \"",
+ string x',
+ string "\", ",
+ string (Int.toString (size x')),
+ string ") && (request[",
+ string (Int.toString (size x')),
+ string "] == 0 || request[",
+ string (Int.toString (size x')),
+ string "] == '/')) ? ({",
+ newline,
+ string "struct",
+ space,
+ string ("__uwd_" ^ ident x ^ "_" ^ Int.toString i),
+ space,
+ string "*tmp = uw_malloc(ctx, sizeof(struct __uwd_",
+ string x,
+ string "_",
+ string (Int.toString i),
+ string "));",
+ newline,
+ string "tmp->tag",
+ space,
+ string "=",
+ space,
+ string ("__uwc_" ^ ident x' ^ "_" ^ Int.toString n),
+ string ";",
+ newline,
+ string "request",
+ space,
+ string "+=",
+ space,
+ string (Int.toString (size x')),
+ string ";",
+ newline,
+ string "if (request[0] == '/') ++request;",
+ newline,
+ case to of
+ NONE => box []
+ | SOME (t, _) => box [string "tmp->data.uw_",
+ p_ident x',
+ space,
+ string "=",
+ space,
+ unurlify' rf t,
+ string ";",
+ newline],
+ string "tmp;",
+ newline,
+ string "})",
+ space,
+ string ":",
+ space,
+ doEm rest,
+ string ")"]
+ in
+ box [string "({",
+ space,
+ p_typ env (t, ErrorMsg.dummySpan),
+ space,
+ string "unurlify_",
+ string (Int.toString i),
+ string "(void) {",
+ newline,
+ box [string "return",
+ space,
+ doEm xncs,
+ string ";",
+ newline],
+ string "}",
+ newline,
+ newline,
+
+ string "unurlify_",
+ string (Int.toString i),
+ string "();",
+ newline,
+ string "})"]
+ end
+
+ | _ => (ErrorMsg.errorAt loc "Unable to choose a URL decoding function";
+ space)
+ in
+ unurlify' IS.empty t
+ end
+
fun p_exp' par env (e, loc) =
case e of
EPrim p => Prim.p_t_GCC p
@@ -485,30 +771,30 @@ fun p_exp' par env (e, loc) =
NONE => raise Fail "CjrPrint: ECon argument status mismatch"
| SOME t => t
in
- case #1 t of
- TDatatype _ => p_exp' par env e
- | TFfi ("Basis", "string") => p_exp' par env e
- | _ => box [string "({",
- newline,
- p_typ env t,
- space,
- string "*tmp",
- space,
- string "=",
- space,
- string "uw_malloc(ctx, sizeof(",
- p_typ env t,
- string "));",
- newline,
- string "*tmp",
- space,
- string "=",
- p_exp' par env e,
- string ";",
- newline,
- string "tmp;",
- newline,
- string "})"]
+ if isUnboxable t then
+ p_exp' par env e
+ else
+ box [string "({",
+ newline,
+ p_typ env t,
+ space,
+ string "*tmp",
+ space,
+ string "=",
+ space,
+ string "uw_malloc(ctx, sizeof(",
+ p_typ env t,
+ string "));",
+ newline,
+ string "*tmp",
+ space,
+ string "=",
+ p_exp' par env e,
+ string ";",
+ newline,
+ string "tmp;",
+ newline,
+ string "})"]
end
| ECon (Default, pc, eo) =>
let
@@ -551,30 +837,30 @@ fun p_exp' par env (e, loc) =
end
| ENone _ => string "NULL"
| ESome (t, e) =>
- (case #1 t of
- TDatatype _ => p_exp' par env e
- | TFfi ("Basis", "string") => p_exp' par env e
- | _ => box [string "({",
- newline,
- p_typ env t,
- space,
- string "*tmp",
- space,
- string "=",
- space,
- string "uw_malloc(ctx, sizeof(",
- p_typ env t,
- string "));",
- newline,
- string "*tmp",
- space,
- string "=",
- p_exp' par env e,
- string ";",
- newline,
- string "tmp;",
- newline,
- string "})"])
+ if isUnboxable t then
+ p_exp' par env e
+ else
+ box [string "({",
+ newline,
+ p_typ env t,
+ space,
+ string "*tmp",
+ space,
+ string "=",
+ space,
+ string "uw_malloc(ctx, sizeof(",
+ p_typ env t,
+ string "));",
+ newline,
+ string "*tmp",
+ space,
+ string "=",
+ p_exp' par env e,
+ string ";",
+ newline,
+ string "tmp;",
+ newline,
+ string "})"]
| EFfi (m, x) => box [string "uw_", p_ident m, string "_", p_ident x]
| EError (e, t) =>
@@ -1078,6 +1364,41 @@ fun p_exp' par env (e, loc) =
string "}))"]
end
+ | EUnurlify (e, t) =>
+ let
+ fun getIt () =
+ if isUnboxable t then
+ unurlify env t
+ else
+ box [string "({",
+ newline,
+ p_typ env t,
+ string " *tmp = uw_malloc(ctx, sizeof(",
+ p_typ env t,
+ string "));",
+ newline,
+ string "*tmp = ",
+ unurlify env t,
+ string ";",
+ newline,
+ string "tmp;",
+ newline,
+ string "})"]
+ in
+ box [string "({",
+ newline,
+ string "uw_Basis_string request = ",
+ p_exp env e,
+ string ";",
+ newline,
+ newline,
+ string "(request ? ",
+ getIt (),
+ string " : NULL);",
+ newline,
+ string "})"]
+ end
+
and p_exp env = p_exp' false env
fun p_fun env (fx, n, args, ran, e) =
@@ -1527,288 +1848,6 @@ fun p_file env (ds, ps) =
string "}"]
end
- fun capitalize s =
- if s = "" then
- ""
- else
- str (Char.toUpper (String.sub (s, 0))) ^ String.extract (s, 1, NONE)
-
- fun unurlify (t, loc) =
- let
- fun unurlify' rf t =
- case t of
- TFfi ("Basis", "unit") => string ("uw_unit_v")
- | TFfi (m, t) => string ("uw_" ^ ident m ^ "_unurlify" ^ capitalize t ^ "(ctx, &request)")
-
- | TRecord 0 => string "uw_unit_v"
- | TRecord i =>
- let
- val xts = E.lookupStruct env i
- in
- box [string "({",
- newline,
- box (map (fn (x, t) =>
- box [p_typ env t,
- space,
- string "uwr_",
- string x,
- space,
- string "=",
- space,
- unurlify' rf (#1 t),
- string ";",
- newline]) xts),
- string "struct",
- space,
- string "__uws_",
- string (Int.toString i),
- space,
- string "tmp",
- space,
- string "=",
- space,
- string "{",
- space,
- p_list_sep (box [string ",", space]) (fn (x, _) => box [string "uwr_",
- string x]) xts,
- space,
- string "};",
- newline,
- string "tmp;",
- newline,
- string "})"]
- end
-
- | TDatatype (Enum, i, _) =>
- let
- val (x, xncs) = E.lookupDatatype env i
-
- fun doEm xncs =
- case xncs of
- [] => string ("(uw_error(ctx, FATAL, \"Error unurlifying datatype "
- ^ x ^ "\"), (enum __uwe_"
- ^ x ^ "_" ^ Int.toString i ^ ")0)")
- | (x', n, to) :: rest =>
- box [string "((!strncmp(request, \"",
- string x',
- string "\", ",
- string (Int.toString (size x')),
- string ") && (request[",
- string (Int.toString (size x')),
- string "] == 0 || request[",
- string (Int.toString (size x')),
- string ("] == '/')) ? __uwc_" ^ ident x' ^ "_" ^ Int.toString n),
- space,
- string ":",
- space,
- doEm rest,
- string ")"]
- in
- doEm xncs
- end
-
- | TDatatype (Option, i, xncs) =>
- if IS.member (rf, i) then
- box [string "unurlify_",
- string (Int.toString i),
- string "()"]
- else
- let
- val (x, _) = E.lookupDatatype env i
-
- val (no_arg, has_arg, t) =
- case !xncs of
- [(no_arg, _, NONE), (has_arg, _, SOME t)] =>
- (no_arg, has_arg, t)
- | [(has_arg, _, SOME t), (no_arg, _, NONE)] =>
- (no_arg, has_arg, t)
- | _ => raise Fail "CjrPrint: unfooify misclassified Option datatype"
-
- val rf = IS.add (rf, i)
- in
- box [string "({",
- space,
- p_typ env t,
- space,
- string "*unurlify_",
- string (Int.toString i),
- string "(void) {",
- newline,
- box [string "return (request[0] == '/' ? ++request : request,",
- newline,
- string "((!strncmp(request, \"",
- string no_arg,
- string "\", ",
- string (Int.toString (size no_arg)),
- string ") && (request[",
- string (Int.toString (size no_arg)),
- string "] == 0 || request[",
- string (Int.toString (size no_arg)),
- string "] == '/')) ? (request",
- space,
- string "+=",
- space,
- string (Int.toString (size no_arg)),
- string ", NULL) : ((!strncmp(request, \"",
- string has_arg,
- string "\", ",
- string (Int.toString (size has_arg)),
- string ") && (request[",
- string (Int.toString (size has_arg)),
- string "] == 0 || request[",
- string (Int.toString (size has_arg)),
- string "] == '/')) ? (request",
- space,
- string "+=",
- space,
- string (Int.toString (size has_arg)),
- string ", (request[0] == '/' ? ++request : NULL), ",
- newline,
-
- case #1 t of
- TDatatype _ => unurlify' rf (#1 t)
- | TFfi ("Basis", "string") => unurlify' rf (#1 t)
- | _ => box [string "({",
- newline,
- p_typ env t,
- space,
- string "*tmp",
- space,
- string "=",
- space,
- string "uw_malloc(ctx, sizeof(",
- p_typ env t,
- string "));",
- newline,
- string "*tmp",
- space,
- string "=",
- space,
- unurlify' rf (#1 t),
- string ";",
- newline,
- string "tmp;",
- newline,
- string "})"],
- string ")",
- newline,
- string ":",
- space,
- string ("(uw_error(ctx, FATAL, \"Error unurlifying datatype " ^ x
- ^ "\"), NULL))));"),
- newline],
- string "}",
- newline,
- newline,
-
- string "unurlify_",
- string (Int.toString i),
- string "();",
- newline,
- string "})"]
- end
-
- | TDatatype (Default, i, _) =>
- if IS.member (rf, i) then
- box [string "unurlify_",
- string (Int.toString i),
- string "()"]
- else
- let
- val (x, xncs) = E.lookupDatatype env i
-
- val rf = IS.add (rf, i)
-
- fun doEm xncs =
- case xncs of
- [] => string ("(uw_error(ctx, FATAL, \"Error unurlifying datatype "
- ^ x ^ "\"), NULL)")
- | (x', n, to) :: rest =>
- box [string "((!strncmp(request, \"",
- string x',
- string "\", ",
- string (Int.toString (size x')),
- string ") && (request[",
- string (Int.toString (size x')),
- string "] == 0 || request[",
- string (Int.toString (size x')),
- string "] == '/')) ? ({",
- newline,
- string "struct",
- space,
- string ("__uwd_" ^ ident x ^ "_" ^ Int.toString i),
- space,
- string "*tmp = uw_malloc(ctx, sizeof(struct __uwd_",
- string x,
- string "_",
- string (Int.toString i),
- string "));",
- newline,
- string "tmp->tag",
- space,
- string "=",
- space,
- string ("__uwc_" ^ ident x' ^ "_" ^ Int.toString n),
- string ";",
- newline,
- string "request",
- space,
- string "+=",
- space,
- string (Int.toString (size x')),
- string ";",
- newline,
- string "if (request[0] == '/') ++request;",
- newline,
- case to of
- NONE => box []
- | SOME (t, _) => box [string "tmp->data.uw_",
- p_ident x',
- space,
- string "=",
- space,
- unurlify' rf t,
- string ";",
- newline],
- string "tmp;",
- newline,
- string "})",
- space,
- string ":",
- space,
- doEm rest,
- string ")"]
- in
- box [string "({",
- space,
- p_typ env (t, ErrorMsg.dummySpan),
- space,
- string "unurlify_",
- string (Int.toString i),
- string "(void) {",
- newline,
- box [string "return",
- space,
- doEm xncs,
- string ";",
- newline],
- string "}",
- newline,
- newline,
-
- string "unurlify_",
- string (Int.toString i),
- string "();",
- newline,
- string "})"]
- end
-
- | _ => (ErrorMsg.errorAt loc "Unable to choose a URL decoding function";
- space)
- in
- unurlify' IS.empty t
- end
-
fun p_page (ek, s, n, ts) =
let
val (ts, defInputs, inputsVar) =
@@ -1855,7 +1894,7 @@ fun p_file env (ds, ps) =
space,
string "=",
space,
- unurlify t,
+ unurlify env t,
string ";",
newline]
end) xts),
@@ -1904,7 +1943,7 @@ fun p_file env (ds, ps) =
space,
string "=",
space,
- unurlify t,
+ unurlify env t,
string ";",
newline]) ts),
defInputs,
diff --git a/src/cjrize.sml b/src/cjrize.sml
index db2bd48f..6c34923b 100644
--- a/src/cjrize.sml
+++ b/src/cjrize.sml
@@ -412,6 +412,13 @@ fun cifyExp (eAll as (e, loc), sm) =
((L'.ENextval {seq = e, prepared = NONE}, loc), sm)
end
+ | L.EUnurlify (e, t) =>
+ let
+ val (e, sm) = cifyExp (e, sm)
+ val (t, sm) = cifyTyp (t, sm)
+ in
+ ((L'.EUnurlify (e, t), loc), sm)
+ end
fun cifyDecl ((d, loc), sm) =
case d of
diff --git a/src/mono.sml b/src/mono.sml
index b7ac6346..f465d2bd 100644
--- a/src/mono.sml
+++ b/src/mono.sml
@@ -94,6 +94,8 @@ datatype exp' =
| EDml of exp
| ENextval of exp
+ | EUnurlify of exp * typ
+
withtype exp = exp' located
diff --git a/src/mono_print.sml b/src/mono_print.sml
index 5d9f8007..8d91d048 100644
--- a/src/mono_print.sml
+++ b/src/mono_print.sml
@@ -272,6 +272,9 @@ fun p_exp' par env (e, _) =
| ENextval e => box [string "nextval(",
p_exp env e,
string ")"]
+ | EUnurlify (e, _) => box [string "unurlify(",
+ p_exp env e,
+ string ")"]
and p_exp env = p_exp' false env
diff --git a/src/mono_reduce.sml b/src/mono_reduce.sml
index 7420f14f..3c4ac0df 100644
--- a/src/mono_reduce.sml
+++ b/src/mono_reduce.sml
@@ -41,6 +41,7 @@ fun impure (e, _) =
| EQuery _ => true
| EDml _ => true
| ENextval _ => true
+ | EUnurlify _ => true
| EAbs _ => false
| EPrim _ => false
@@ -275,6 +276,7 @@ fun summarize d (e, _) =
| EDml e => summarize d e @ [WriteDb]
| ENextval e => summarize d e @ [WriteDb]
+ | EUnurlify (e, _) => summarize d e
fun exp env e =
let
diff --git a/src/mono_util.sml b/src/mono_util.sml
index 080c3dc9..14ab1674 100644
--- a/src/mono_util.sml
+++ b/src/mono_util.sml
@@ -305,6 +305,12 @@ fun mapfoldB {typ = fc, exp = fe, bind} =
S.map2 (mfe ctx e,
fn e' =>
(ENextval e', loc))
+ | EUnurlify (e, t) =>
+ S.bind2 (mfe ctx e,
+ fn e' =>
+ S.map2 (mft t,
+ fn t' =>
+ (EUnurlify (e', t'), loc)))
in
mfe
end
diff --git a/src/monoize.sml b/src/monoize.sml
index 64522a18..b8c3a6a9 100644
--- a/src/monoize.sml
+++ b/src/monoize.sml
@@ -955,7 +955,9 @@ fun monoExp (env, st, fm) (all as (e, loc)) =
in
((L'.EAbs ("c", s, (L'.TFun (un, s), loc),
(L'.EAbs ("_", un, s,
- (L'.EPrim (Prim.String "Cookie!"), loc)), loc)), loc),
+ (L'.EUnurlify ((L'.EFfiApp ("Basis", "get_cookie", [(L'.ERel 1, loc)]), loc),
+ t),
+ loc)), loc)), loc),
fm)
end
diff --git a/src/prepare.sml b/src/prepare.sml
index 166f658b..6d63ad7d 100644
--- a/src/prepare.sml
+++ b/src/prepare.sml
@@ -191,6 +191,13 @@ fun prepExp (e as (_, loc), sns) =
((String.concat (rev ss), n) :: #1 sns, #2 sns + 1))
end
+ | EUnurlify (e, t) =>
+ let
+ val (e, sns) = prepExp (e, sns)
+ in
+ ((EUnurlify (e, t), loc), sns)
+ end
+
fun prepDecl (d as (_, loc), sns) =
case #1 d of
DStruct _ => (d, sns)
diff --git a/tests/cookie.ur b/tests/cookie.ur
index 36734260..cb4f8854 100644
--- a/tests/cookie.ur
+++ b/tests/cookie.ur
@@ -2,7 +2,7 @@ cookie c : string
fun main () : transaction page =
setCookie c "Hi";
- so <- requestHeader "Cookie";
+ so <- getCookie c;
case so of
None => return <xml>No cookie</xml>
| Some s => return <xml>Cookie: {[s]}</xml>