changeset 1071:26197c957ad6

Better record summary error messages; more tweaking SQL usability
author Adam Chlipala <adamc@hcoop.net>
date Sun, 13 Dec 2009 11:28:47 -0500
parents e933297c4e24
children 9001966ae1c8
files lib/ur/basis.urs src/elab_err.sig src/elab_err.sml src/elaborate.sml src/elisp/urweb-mode.el src/monoize.sml src/urweb.grm src/urweb.lex
diffstat 8 files changed, 52 insertions(+), 9 deletions(-) [+]
line wrap: on
line diff
--- a/lib/ur/basis.urs	Sun Dec 13 10:13:06 2009 -0500
+++ b/lib/ur/basis.urs	Sun Dec 13 11:28:47 2009 -0500
@@ -344,6 +344,9 @@
                 -> sql_query1 tables1 selectedFields selectedExps
                 -> sql_query1 tables2 selectedFields selectedExps
                 -> sql_query1 selectedFields selectedFields selectedExps
+val sql_forget_tables : tables ::: {{Type}} -> selectedFields ::: {{Type}} -> selectedExps ::: {Type}
+                        -> sql_query1 tables selectedFields selectedExps
+                        -> sql_query1 selectedFields selectedFields selectedExps
 
 type sql_direction
 val sql_asc : sql_direction
--- a/src/elab_err.sig	Sun Dec 13 10:13:06 2009 -0500
+++ b/src/elab_err.sig	Sun Dec 13 11:28:47 2009 -0500
@@ -55,7 +55,7 @@
            | CIncompatible of Elab.con * Elab.con
            | CExplicitness of Elab.con * Elab.con
            | CKindof of Elab.kind * Elab.con * string
-           | CRecordFailure of Elab.con * Elab.con
+           | CRecordFailure of Elab.con * Elab.con * (Elab.con * Elab.con * Elab.con) option
 
     val cunifyError : ElabEnv.env -> cunify_error -> unit
 
--- a/src/elab_err.sml	Sun Dec 13 10:13:06 2009 -0500
+++ b/src/elab_err.sml	Sun Dec 13 11:28:47 2009 -0500
@@ -119,7 +119,7 @@
        | CIncompatible of con * con
        | CExplicitness of con * con
        | CKindof of kind * con * string
-       | CRecordFailure of con * con
+       | CRecordFailure of con * con * (con * con * con) option
 
 fun cunifyError env err =
     case err of
@@ -144,10 +144,16 @@
         eprefaces ("Unexpected kind for kindof calculation (expecting " ^ expected ^ ")")
                   [("Kind", p_kind env k),
                    ("Con", p_con env c)]
-      | CRecordFailure (c1, c2) =>
+      | CRecordFailure (c1, c2, fo) =>
         eprefaces "Can't unify record constructors"
-                  [("Summary 1", p_con env c1),
-                   ("Summary 2", p_con env c2)]
+                  (("Summary 1", p_con env c1)
+                   :: ("Summary 2", p_con env c2)
+                   :: (case fo of
+                           NONE => []
+                         | SOME (nm, t1, t2) =>
+                           [("Field", p_con env nm),
+                            ("Value 1", p_con env t1),
+                            ("Value 2", p_con env t2)]))
 
 datatype exp_error =
        UnboundExp of ErrorMsg.span * string
--- a/src/elaborate.sml	Sun Dec 13 10:13:06 2009 -0500
+++ b/src/elaborate.sml	Sun Dec 13 11:28:47 2009 -0500
@@ -817,7 +817,24 @@
                                           ("#2", p_summary env {fields = fs2, unifs = unifs2, others = others2})]*)
 
          val empty = (L'.CRecord (k, []), loc)
-         fun failure () = raise CUnify' (CRecordFailure (unsummarize s1, unsummarize s2))
+         fun failure () =
+             let
+                 val fs2 = #fields s2
+
+                 fun findPointwise fs1 =
+                     case fs1 of
+                         [] => NONE
+                       | (nm1, c1) :: fs1 =>
+                         case List.find (fn (nm2, _) => consEq env loc (nm1, nm2)) fs2 of
+                             NONE => findPointwise fs1
+                           | SOME (_, c2) =>
+                             if consEq env loc (c1, c2) then
+                                 findPointwise fs1
+                             else
+                                 SOME (nm1, c1, c2)
+             in
+                 raise CUnify' (CRecordFailure (unsummarize s1, unsummarize s2, findPointwise (#fields s1)))
+             end
      in
          (case (unifs1, fs1, others1, unifs2, fs2, others2) of
               (_, [], [], [], [], []) =>
--- a/src/elisp/urweb-mode.el	Sun Dec 13 10:13:06 2009 -0500
+++ b/src/elisp/urweb-mode.el	Sun Dec 13 11:28:47 2009 -0500
@@ -150,7 +150,7 @@
                  "ASC" "DESC" "INSERT" "INTO" "VALUES" "UPDATE" "SET" "DELETE"
                  "PRIMARY" "KEY" "CONSTRAINT" "UNIQUE" "CHECK"
                  "FOREIGN" "REFERENCES" "ON" "NO" "ACTION" "CASCADE" "RESTRICT" "NULL"
-                 "JOIN" "INNER" "OUTER" "LEFT" "RIGHT" "FULL" "CROSS")
+                 "JOIN" "INNER" "OUTER" "LEFT" "RIGHT" "FULL" "CROSS" "SELECT1")
   "A regexp that matches SQL keywords.")
 
 (defconst urweb-lident-regexp "\\<[a-z_][A-Za-z0-9_']*\\>"
@@ -530,7 +530,7 @@
     (current-indentation)))
 
 (defconst urweb-sql-main-starters
-  '("SQL" "SELECT" "INSERT" "UPDATE" "DELETE"))
+  '("SQL" "SELECT" "INSERT" "UPDATE" "DELETE" "FROM" "SELECT1" "WHERE"))
 
 (defconst urweb-sql-starters
   (append urweb-sql-main-starters
--- a/src/monoize.sml	Sun Dec 13 10:13:06 2009 -0500
+++ b/src/monoize.sml	Sun Dec 13 11:28:47 2009 -0500
@@ -2292,6 +2292,20 @@
                                                        sc "))"]), loc)), loc)), loc),
                  fm)
             end
+          | L.ECApp (
+            (L.ECApp (
+             (L.ECApp (
+              (L.EFfi ("Basis", "sql_forget_tables"), _),
+              _), _),
+             _), _),
+            _) =>
+            let
+                val s = (L'.TFfi ("Basis", "string"), loc)
+                fun sc s = (L'.EPrim (Prim.String s), loc)
+            in
+                ((L'.EAbs ("x", s, s, (L'.ERel 0, loc)), loc),
+                 fm)
+            end
 
           | L.EFfi ("Basis", "sql_union") => ((L'.EPrim (Prim.String "UNION"), loc), fm)
           | L.EFfi ("Basis", "sql_intersect") => ((L'.EPrim (Prim.String "INTERSECT"), loc), fm)
--- a/src/urweb.grm	Sun Dec 13 10:13:06 2009 -0500
+++ b/src/urweb.grm	Sun Dec 13 11:28:47 2009 -0500
@@ -199,7 +199,7 @@
  | ARROW | LARROW | DARROW | STAR | SEMI | KARROW | DKARROW | BANG
  | FN | PLUSPLUS | MINUSMINUS | MINUSMINUSMINUS | DOLLAR | TWIDDLE | CARET
  | LET | IN
- | STRUCTURE | SIGNATURE | STRUCT | SIG | END | FUNCTOR | WHERE | EXTERN | SQL
+ | STRUCTURE | SIGNATURE | STRUCT | SIG | END | FUNCTOR | WHERE | EXTERN | SQL | SELECT1
  | INCLUDE | OPEN | CONSTRAINT | CONSTRAINTS | EXPORT | TABLE | SEQUENCE | VIEW
  | COOKIE | STYLE
  | CASE | IF | THEN | ELSE | ANDALSO | ORELSE
@@ -1170,6 +1170,7 @@
        | LPAREN CWHERE sqlexp RPAREN    (sqlexp)
        | LPAREN SQL sqlexp RPAREN       (sqlexp)
        | LPAREN FROM tables RPAREN      (#2 tables)
+       | LPAREN SELECT1 query1 RPAREN   (query1)
 
        | LPAREN INSERT INTO texp LPAREN fields RPAREN VALUES LPAREN sqlexps RPAREN RPAREN
                                         (let
@@ -1540,6 +1541,7 @@
                                          end)
 
 fitem  : table'                         ([#1 table'], #2 table')
+       | LBRACE LBRACE eexp RBRACE RBRACE ([], eexp)
        | fitem JOIN fitem ON sqlexp     (let
                                              val loc = s (fitem1left, sqlexpright)
                                                        
--- a/src/urweb.lex	Sun Dec 13 10:13:06 2009 -0500
+++ b/src/urweb.lex	Sun Dec 13 11:28:47 2009 -0500
@@ -420,6 +420,7 @@
 <INITIAL> "LIMIT"     => (Tokens.LIMIT (pos yypos, pos yypos + size yytext));
 <INITIAL> "OFFSET"    => (Tokens.OFFSET (pos yypos, pos yypos + size yytext));
 <INITIAL> "ALL"       => (Tokens.ALL (pos yypos, pos yypos + size yytext));
+<INITIAL> "SELECT1"   => (Tokens.SELECT1 (pos yypos, pos yypos + size yytext));
 
 <INITIAL> "JOIN"      => (Tokens.JOIN (pos yypos, pos yypos + size yytext));
 <INITIAL> "INNER"     => (Tokens.INNER (pos yypos, pos yypos + size yytext));