adamc@1: (* Copyright (c) 2008, Adam Chlipala adamc@1: * All rights reserved. adamc@1: * adamc@1: * Redistribution and use in source and binary forms, with or without adamc@1: * modification, are permitted provided that the following conditions are met: adamc@1: * adamc@1: * - Redistributions of source code must retain the above copyright notice, adamc@1: * this list of conditions and the following disclaimer. adamc@1: * - Redistributions in binary form must reproduce the above copyright notice, adamc@1: * this list of conditions and the following disclaimer in the documentation adamc@1: * and/or other materials provided with the distribution. adamc@1: * - The names of contributors may not be used to endorse or promote products adamc@1: * derived from this software without specific prior written permission. adamc@1: * adamc@339: * THIS SOFTARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" adamc@1: * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE adamc@1: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE adamc@1: * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE adamc@1: * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR adamc@1: * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF adamc@1: * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS adamc@1: * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN adamc@1: * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) adamc@1: * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE adamc@1: * POSSIBILITY OF SUCH DAMAGE. adamc@1: *) adamc@1: adamc@244: (* Grammar for Ur/Web programs *) adamc@1: adamc@4: open Source adamc@1: adamc@1: val s = ErrorMsg.spanOf adamc@230: val dummy = ErrorMsg.dummySpan adamc@1: adamc@204: fun capitalize "" = "" adamc@204: | capitalize s = str (Char.toUpper (String.sub (s, 0))) ^ String.extract (s, 1, NONE) adamc@104: adamc@203: fun entable t = adamc@203: case #1 t of adamc@203: TRecord c => c adamc@203: | _ => t adamc@203: adamc@207: datatype select_item = adamc@207: Field of con * con adamc@233: | Exp of con * exp adamc@341: | Fields of con * con adamc@207: adamc@207: datatype select = adamc@207: Star adamc@207: | Items of select_item list adamc@207: adamc@226: datatype group_item = adamc@226: GField of con * con adamc@226: adamc@207: fun eqTnames ((c1, _), (c2, _)) = adamc@207: case (c1, c2) of adamc@207: (CVar (ms1, x1), CVar (ms2, x2)) => ms1 = ms2 andalso x1 = x2 adamc@207: | (CName x1, CName x2) => x1 = x2 adamc@207: | _ => false adamc@207: adamc@233: fun amend_select loc (si, (tabs, exps)) = adamc@233: case si of adamc@233: Field (tx, fx) => adamc@233: let adamc@233: val c = (CRecord ([(fx, (CWild (KType, loc), loc))]), loc) adamc@207: adamc@233: val (tabs, found) = ListUtil.foldlMap (fn ((tx', c'), found) => adamc@233: if eqTnames (tx, tx') then adamc@233: ((tx', (CConcat (c, c'), loc)), true) adamc@233: else adamc@233: ((tx', c'), found)) adamc@233: false tabs adamc@233: in adamc@233: if found then adamc@233: () adamc@233: else adamc@233: ErrorMsg.errorAt loc "Select of field from unbound table"; adamc@233: adamc@233: (tabs, exps) adamc@233: end adamc@341: | Fields (tx, fs) => adamc@341: let adamc@341: val (tabs, found) = ListUtil.foldlMap (fn ((tx', c'), found) => adamc@341: if eqTnames (tx, tx') then adamc@341: ((tx', (CConcat (fs, c'), loc)), true) adamc@341: else adamc@341: ((tx', c'), found)) adamc@341: false tabs adamc@341: in adamc@341: if found then adamc@341: () adamc@341: else adamc@341: ErrorMsg.errorAt loc "Select of field from unbound table"; adamc@341: adamc@341: (tabs, exps) adamc@341: end adamc@233: | Exp (c, e) => (tabs, (c, e) :: exps) adamc@207: adamc@226: fun amend_group loc (gi, tabs) = adamc@226: let adamc@226: val (tx, c) = case gi of adamc@226: GField (tx, fx) => (tx, (CRecord ([(fx, (CWild (KType, loc), loc))]), loc)) adamc@226: adamc@226: val (tabs, found) = ListUtil.foldlMap (fn ((tx', c'), found) => adamc@226: if eqTnames (tx, tx') then adamc@226: ((tx', (CConcat (c, c'), loc)), true) adamc@226: else adamc@226: ((tx', c'), found)) adamc@226: false tabs adamc@226: in adamc@226: if found then adamc@226: () adamc@226: else adamc@226: ErrorMsg.errorAt loc "Select of field from unbound table"; adamc@226: adamc@226: tabs adamc@226: end adamc@226: adamc@403: fun sql_inject (v, loc) = adamc@403: (EApp ((EVar (["Basis"], "sql_inject", Infer), loc), (v, loc)), loc) adamc@209: adamc@219: fun sql_compare (oper, sqlexp1, sqlexp2, loc) = adamc@219: let adamc@403: val e = (EVar (["Basis"], "sql_comparison", Infer), loc) adamc@403: val e = (EApp (e, (EVar (["Basis"], "sql_" ^ oper, Infer), loc)), loc) adamc@219: val e = (EApp (e, sqlexp1), loc) adamc@219: in adamc@234: (EApp (e, sqlexp2), loc) adamc@220: end adamc@220: adamc@220: fun sql_binary (oper, sqlexp1, sqlexp2, loc) = adamc@220: let adamc@403: val e = (EVar (["Basis"], "sql_binary", Infer), loc) adamc@403: val e = (EApp (e, (EVar (["Basis"], "sql_" ^ oper, Infer), loc)), loc) adamc@220: val e = (EApp (e, sqlexp1), loc) adamc@220: in adamc@220: (EApp (e, sqlexp2), loc) adamc@220: end adamc@220: adamc@220: fun sql_unary (oper, sqlexp, loc) = adamc@220: let adamc@403: val e = (EVar (["Basis"], "sql_unary", Infer), loc) adamc@403: val e = (EApp (e, (EVar (["Basis"], "sql_" ^ oper, Infer), loc)), loc) adamc@220: in adamc@220: (EApp (e, sqlexp), loc) adamc@219: end adamc@219: adamc@229: fun sql_relop (oper, sqlexp1, sqlexp2, loc) = adamc@229: let adamc@403: val e = (EVar (["Basis"], "sql_relop", Infer), loc) adamc@403: val e = (EApp (e, (EVar (["Basis"], "sql_" ^ oper, Infer), loc)), loc) adamc@229: val e = (EApp (e, sqlexp1), loc) adamc@229: in adamc@229: (EApp (e, sqlexp2), loc) adamc@229: end adamc@229: adamc@441: fun sql_nfunc (oper, loc) = adamc@441: let adamc@441: val e = (EVar (["Basis"], "sql_nfunc", Infer), loc) adamc@441: in adamc@441: (EApp (e, (EVar (["Basis"], "sql_" ^ oper, Infer), loc)), loc) adamc@441: end adamc@441: adamc@389: fun native_unop (oper, e1, loc) = adamc@389: let adamc@403: val e = (EVar (["Basis"], oper, Infer), loc) adamc@389: in adamc@389: (EApp (e, e1), loc) adamc@389: end adamc@389: adamc@256: fun native_op (oper, e1, e2, loc) = adamc@256: let adamc@403: val e = (EVar (["Basis"], oper, Infer), loc) adamc@256: val e = (EApp (e, e1), loc) adamc@256: in adamc@256: (EApp (e, e2), loc) adamc@256: end adamc@256: adamc@310: val inDml = ref false adamc@310: adamc@325: fun tagIn bt = adamc@325: case bt of adamc@325: "table" => "tabl" adamc@325: | _ => bt adamc@325: adamc@1: %% adamc@244: %header (functor UrwebLrValsFn(structure Token : TOKEN)) adamc@1: adamc@1: %term adamc@1: EOF adamc@14: | STRING of string | INT of Int64.int | FLOAT of Real64.real adamc@1: | SYMBOL of string | CSYMBOL of string adamc@1: | LPAREN | RPAREN | LBRACK | RBRACK | LBRACE | RBRACE adamc@156: | EQ | COMMA | COLON | DCOLON | TCOLON | DOT | HASH | UNDER | UNDERUNDER | BAR adamc@403: | PLUS | MINUS | DIVIDE | DOTDOTDOT | MOD | AT adamc@242: | CON | LTYPE | VAL | REC | AND | FUN | FOLD | UNIT | KUNIT | CLASS adamc@156: | DATATYPE | OF adamc@7: | TYPE | NAME adamc@243: | ARROW | LARROW | DARROW | STAR | SEMI adamc@149: | FN | PLUSPLUS | MINUSMINUS | DOLLAR | TWIDDLE adamc@446: | LET | IN adamc@445: | STRUCTURE | SIGNATURE | STRUCT | SIG | END | FUNCTOR | WHERE | EXTERN | SQL adamc@338: | INCLUDE | OPEN | CONSTRAINT | CONSTRAINTS | EXPORT | TABLE | SEQUENCE adamc@459: | COOKIE adamc@190: | CASE | IF | THEN | ELSE adamc@1: adamc@360: | XML_BEGIN of string | XML_END | XML_BEGIN_END of string adamc@91: | NOTAGS of string adamc@91: | BEGIN_TAG of string | END_TAG of string adamc@91: adamc@230: | SELECT | FROM | AS | CWHERE | GROUP | ORDER | BY | HAVING adamc@229: | UNION | INTERSECT | EXCEPT adamc@232: | LIMIT | OFFSET | ALL adamc@220: | TRUE | FALSE | CAND | OR | NOT adamc@236: | COUNT | AVG | SUM | MIN | MAX adamc@268: | ASC | DESC adamc@470: | INSERT | INTO | VALUES | UPDATE | SET | DELETE | NULL | IS adamc@441: | CURRENT_TIMESTAMP adamc@219: | NE | LT | LE | GT | GE adamc@204: adamc@30: %nonterm adamc@1: file of decl list adamc@1: | decls of decl list adamc@325: | decl of decl list adamc@123: | vali of string * con option * exp adamc@123: | valis of (string * con option * exp) list adamc@242: | copt of con option adamc@1: adamc@191: | dargs of string list adamc@156: | barOpt of unit adamc@156: | dcons of (string * con option) list adamc@156: | dcon of string * con option adamc@156: adamc@30: | sgn of sgn adamc@42: | sgntm of sgn adamc@30: | sgi of sgn_item adamc@30: | sgis of sgn_item list adamc@30: adamc@30: | str of str adamc@30: adamc@1: | kind of kind adamc@207: | ktuple of kind list adamc@1: | kcolon of explicitness adamc@240: | kopt of kind option adamc@1: adamc@34: | path of string list * string adamc@156: | cpath of string list * string adamc@34: | spath of str adamc@59: | mpath of string list adamc@34: adamc@1: | cexp of con adamc@1: | capps of con adamc@1: | cterm of con adamc@195: | ctuple of con list adamc@207: | ctuplev of con list adamc@1: | ident of con adamc@200: | idents of con list adamc@1: | rcon of (con * con) list adamc@83: | rconn of (con * con) list adamc@1: | rcone of (con * con) list adamc@239: | cargs of con * kind -> con * kind adamc@239: | cargl of con * kind -> con * kind adamc@240: | cargl2 of con * kind -> con * kind adamc@239: | carg of con * kind -> con * kind adamc@239: | cargp of con * kind -> con * kind adamc@1: adamc@8: | eexp of exp adamc@8: | eapps of exp adamc@8: | eterm of exp adamc@195: | etuple of exp list adamc@12: | rexp of (con * exp) list adamc@91: | xml of exp adamc@91: | xmlOne of exp adamc@141: | tag of string * exp adamc@141: | tagHead of string * exp adamc@434: | bind of string * con option * exp adamc@446: | edecl of edecl adamc@446: | edecls of edecl list adamc@8: adamc@241: | earg of exp * con -> exp * con adamc@241: | eargp of exp * con -> exp * con adamc@241: | eargs of exp * con -> exp * con adamc@241: | eargl of exp * con -> exp * con adamc@242: | eargl2 of exp * con -> exp * con adamc@241: adamc@170: | branch of pat * exp adamc@170: | branchs of (pat * exp) list adamc@170: | pat of pat adamc@170: | pterm of pat adamc@174: | rpat of (string * pat) list * bool adamc@195: | ptuple of pat list adamc@170: adamc@104: | attrs of (con * exp) list adamc@104: | attr of con * exp adamc@104: | attrv of exp adamc@104: adamc@204: | query of exp adamc@226: | query1 of exp adamc@204: | tables of (con * exp) list adamc@204: | tname of con adamc@204: | table of con * exp adamc@207: | tident of con adamc@207: | fident of con adamc@207: | seli of select_item adamc@207: | selis of select_item list adamc@207: | select of select adamc@209: | sqlexp of exp adamc@209: | wopt of exp adamc@226: | groupi of group_item adamc@226: | groupis of group_item list adamc@226: | gopt of group_item list option adamc@227: | hopt of exp adamc@230: | obopt of exp adamc@268: | obitem of exp * exp adamc@230: | obexps of exp adamc@268: | diropt of exp adamc@231: | lopt of exp adamc@232: | ofopt of exp adamc@231: | sqlint of exp adamc@236: | sqlagg of string adamc@207: adamc@302: | texp of exp adamc@302: | fields of con list adamc@302: | sqlexps of exp list adamc@303: | fsets of (con * exp) list adamc@310: | enterDml of unit adamc@310: | leaveDml of unit adamc@302: adamc@204: adamc@1: %verbose (* print summary of errors *) adamc@1: %pos int (* positions *) adamc@1: %start file adamc@1: %pure adamc@1: %eop EOF adamc@1: %noshift EOF adamc@1: adamc@244: %name Urweb adamc@1: adamc@243: %right SEMI adamc@243: %nonassoc LARROW adamc@195: %nonassoc IF THEN ELSE adamc@1: %nonassoc DARROW adamc@1: %nonassoc COLON adamc@6: %nonassoc DCOLON TCOLON adamc@229: %left UNION INTERSECT EXCEPT adamc@1: %right COMMA adamc@220: %right OR adamc@220: %right CAND adamc@470: %nonassoc EQ NE LT LE GT GE IS adamc@243: %right ARROW adamc@149: %right PLUSPLUS MINUSMINUS adamc@389: %left PLUS MINUS adamc@389: %left STAR DIVIDE MOD adamc@220: %left NOT adamc@84: %nonassoc TWIDDLE adamc@1: %nonassoc DOLLAR adamc@1: %left DOT adamc@221: %nonassoc LBRACE RBRACE adamc@1: adamc@1: %% adamc@1: adamc@1: file : decls (decls) adamc@54: | SIG sgis ([(DSgn ("?", (SgnConst sgis, s (SIGleft, sgisright))), adamc@54: s (SIGleft, sgisright))]) adamc@1: adamc@1: decls : ([]) adamc@325: | decl decls (decl @ decls) adamc@1: adamc@240: decl : CON SYMBOL cargl2 kopt EQ cexp (let adamc@240: val loc = s (CONleft, cexpright) adamc@240: adamc@240: val k = Option.getOpt (kopt, (KWild, loc)) adamc@240: val (c, k) = cargl2 (cexp, k) adamc@240: in adamc@325: [(DCon (SYMBOL, SOME k, c), loc)] adamc@240: end) adamc@325: | LTYPE SYMBOL EQ cexp ([(DCon (SYMBOL, SOME (KType, s (LTYPEleft, cexpright)), cexp), adamc@325: s (LTYPEleft, cexpright))]) adamc@325: | DATATYPE SYMBOL dargs EQ barOpt dcons([(DDatatype (SYMBOL, dargs, dcons), s (DATATYPEleft, dconsright))]) adamc@191: | DATATYPE SYMBOL dargs EQ DATATYPE CSYMBOL DOT path adamc@191: (case dargs of adamc@325: [] => [(DDatatypeImp (SYMBOL, CSYMBOL :: #1 path, #2 path), s (DATATYPEleft, pathright))] adamc@191: | _ => raise Fail "Arguments specified for imported datatype") adamc@325: | VAL vali ([(DVal vali, s (VALleft, valiright))]) adamc@325: | VAL REC valis ([(DValRec valis, s (VALleft, valisright))]) adamc@325: | FUN valis ([(DValRec valis, s (FUNleft, valisright))]) adamc@1: adamc@325: | SIGNATURE CSYMBOL EQ sgn ([(DSgn (CSYMBOL, sgn), s (SIGNATUREleft, sgnright))]) adamc@325: | STRUCTURE CSYMBOL EQ str ([(DStr (CSYMBOL, NONE, str), s (STRUCTUREleft, strright))]) adamc@325: | STRUCTURE CSYMBOL COLON sgn EQ str ([(DStr (CSYMBOL, SOME sgn, str), s (STRUCTUREleft, strright))]) adamc@42: | FUNCTOR CSYMBOL LPAREN CSYMBOL COLON sgn RPAREN EQ str adamc@325: ([(DStr (CSYMBOL1, NONE, adamc@325: (StrFun (CSYMBOL2, sgn1, NONE, str), s (FUNCTORleft, strright))), adamc@325: s (FUNCTORleft, strright))]) adamc@42: | FUNCTOR CSYMBOL LPAREN CSYMBOL COLON sgn RPAREN COLON sgn EQ str adamc@325: ([(DStr (CSYMBOL1, NONE, adamc@325: (StrFun (CSYMBOL2, sgn1, SOME sgn2, str), s (FUNCTORleft, strright))), adamc@325: s (FUNCTORleft, strright))]) adamc@325: | EXTERN STRUCTURE CSYMBOL COLON sgn ([(DFfiStr (CSYMBOL, sgn), s (EXTERNleft, sgnright))]) adamc@61: | OPEN mpath (case mpath of adamc@61: [] => raise Fail "Impossible mpath parse [1]" adamc@325: | m :: ms => [(DOpen (m, ms), s (OPENleft, mpathright))]) adamc@325: | OPEN mpath LPAREN str RPAREN (let adamc@325: val loc = s (OPENleft, RPARENright) adamc@325: adamc@325: val m = case mpath of adamc@325: [] => raise Fail "Impossible mpath parse [4]" adamc@325: | m :: ms => adamc@325: foldl (fn (m, str) => (StrProj (str, m), loc)) adamc@325: (StrVar m, loc) ms adamc@325: in adamc@325: [(DStr ("anon", NONE, (StrApp (m, str), loc)), loc), adamc@325: (DOpen ("anon", []), loc)] adamc@325: end) adamc@88: | OPEN CONSTRAINTS mpath (case mpath of adamc@88: [] => raise Fail "Impossible mpath parse [3]" adamc@325: | m :: ms => [(DOpenConstraints (m, ms), s (OPENleft, mpathright))]) adamc@325: | CONSTRAINT cterm TWIDDLE cterm ([(DConstraint (cterm1, cterm2), s (CONSTRAINTleft, ctermright))]) adamc@325: | EXPORT spath ([(DExport spath, s (EXPORTleft, spathright))]) adamc@325: | TABLE SYMBOL COLON cexp ([(DTable (SYMBOL, entable cexp), s (TABLEleft, cexpright))]) adamc@338: | SEQUENCE SYMBOL ([(DSequence SYMBOL, s (SEQUENCEleft, SYMBOLright))]) adamc@325: | CLASS SYMBOL EQ cexp ([(DClass (SYMBOL, cexp), s (CLASSleft, cexpright))]) adamc@211: | CLASS SYMBOL SYMBOL EQ cexp (let adamc@211: val loc = s (CLASSleft, cexpright) adamc@211: val k = (KType, loc) adamc@211: val c = (CAbs (SYMBOL2, SOME k, cexp), loc) adamc@211: in adamc@325: [(DClass (SYMBOL1, c), s (CLASSleft, cexpright))] adamc@211: end) adamc@459: | COOKIE SYMBOL COLON cexp ([(DCookie (SYMBOL, cexp), s (COOKIEleft, cexpright))]) adamc@30: adamc@240: kopt : (NONE) adamc@240: | DCOLON kind (SOME kind) adamc@240: adamc@191: dargs : ([]) adamc@191: | SYMBOL dargs (SYMBOL :: dargs) adamc@191: adamc@156: barOpt : () adamc@156: | BAR () adamc@156: adamc@156: dcons : dcon ([dcon]) adamc@156: | dcon BAR dcons (dcon :: dcons) adamc@156: adamc@156: dcon : CSYMBOL (CSYMBOL, NONE) adamc@156: | CSYMBOL OF cexp (CSYMBOL, SOME cexp) adamc@156: adamc@242: vali : SYMBOL eargl2 copt EQ eexp (let adamc@242: val loc = s (SYMBOLleft, eexpright) adamc@242: val t = Option.getOpt (copt, (CWild (KType, loc), loc)) adamc@242: adamc@242: val (e, t) = eargl2 (eexp, t) adamc@242: in adamc@242: (SYMBOL, SOME t, e) adamc@242: end) adamc@242: adamc@242: copt : (NONE) adamc@242: | COLON cexp (SOME cexp) adamc@123: adamc@123: valis : vali ([vali]) adamc@123: | vali AND valis (vali :: valis) adamc@123: adamc@42: sgn : sgntm (sgntm) adamc@40: | FUNCTOR LPAREN CSYMBOL COLON sgn RPAREN COLON sgn adamc@40: (SgnFun (CSYMBOL, sgn1, sgn2), s (FUNCTORleft, sgn2right)) adamc@30: adamc@42: sgntm : SIG sgis END (SgnConst sgis, s (SIGleft, ENDright)) adamc@59: | mpath (case mpath of adamc@61: [] => raise Fail "Impossible mpath parse [2]" adamc@59: | [x] => SgnVar x adamc@59: | m :: ms => SgnProj (m, adamc@59: List.take (ms, length ms - 1), adamc@59: List.nth (ms, length ms - 1)), adamc@59: s (mpathleft, mpathright)) adamc@42: | sgntm WHERE CON SYMBOL EQ cexp (SgnWhere (sgntm, SYMBOL, cexp), s (sgntmleft, cexpright)) adamc@42: | sgntm WHERE LTYPE SYMBOL EQ cexp(SgnWhere (sgntm, SYMBOL, cexp), s (sgntmleft, cexpright)) adamc@42: | LPAREN sgn RPAREN (sgn) adamc@42: adamc@30: sgi : CON SYMBOL DCOLON kind (SgiConAbs (SYMBOL, kind), s (CONleft, kindright)) adamc@30: | LTYPE SYMBOL (SgiConAbs (SYMBOL, (KType, s (LTYPEleft, SYMBOLright))), adamc@30: s (LTYPEleft, SYMBOLright)) adamc@30: | CON SYMBOL EQ cexp (SgiCon (SYMBOL, NONE, cexp), s (CONleft, cexpright)) adamc@30: | CON SYMBOL DCOLON kind EQ cexp (SgiCon (SYMBOL, SOME kind, cexp), s (CONleft, cexpright)) adamc@30: | LTYPE SYMBOL EQ cexp (SgiCon (SYMBOL, SOME (KType, s (LTYPEleft, cexpright)), cexp), adamc@30: s (LTYPEleft, cexpright)) adamc@191: | DATATYPE SYMBOL dargs EQ barOpt dcons(SgiDatatype (SYMBOL, dargs, dcons), s (DATATYPEleft, dconsright)) adamc@191: | DATATYPE SYMBOL dargs EQ DATATYPE CSYMBOL DOT path adamc@191: (case dargs of adamc@191: [] => (SgiDatatypeImp (SYMBOL, CSYMBOL :: #1 path, #2 path), s (DATATYPEleft, pathright)) adamc@191: | _ => raise Fail "Arguments specified for imported datatype") adamc@30: | VAL SYMBOL COLON cexp (SgiVal (SYMBOL, cexp), s (VALleft, cexpright)) adamc@30: adamc@30: | STRUCTURE CSYMBOL COLON sgn (SgiStr (CSYMBOL, sgn), s (STRUCTUREleft, sgnright)) adamc@59: | SIGNATURE CSYMBOL EQ sgn (SgiSgn (CSYMBOL, sgn), s (SIGNATUREleft, sgnright)) adamc@42: | FUNCTOR CSYMBOL LPAREN CSYMBOL COLON sgn RPAREN COLON sgn adamc@42: (SgiStr (CSYMBOL1, adamc@42: (SgnFun (CSYMBOL2, sgn1, sgn2), s (FUNCTORleft, sgn2right))), adamc@42: s (FUNCTORleft, sgn2right)) adamc@58: | INCLUDE sgn (SgiInclude sgn, s (INCLUDEleft, sgnright)) adamc@88: | CONSTRAINT cterm TWIDDLE cterm (SgiConstraint (cterm1, cterm2), s (CONSTRAINTleft, ctermright)) adamc@460: | TABLE SYMBOL COLON cexp (let adamc@460: val loc = s (TABLEleft, cexpright) adamc@460: val t = (CApp ((CVar (["Basis"], "sql_table"), loc), adamc@460: entable cexp), loc) adamc@460: in adamc@460: (SgiVal (SYMBOL, t), loc) adamc@460: end) adamc@460: | SEQUENCE SYMBOL (let adamc@460: val loc = s (SEQUENCEleft, SYMBOLright) adamc@460: val t = (CVar (["Basis"], "sql_sequence"), loc) adamc@460: in adamc@460: (SgiVal (SYMBOL, t), loc) adamc@460: end) adamc@211: | CLASS SYMBOL (SgiClassAbs SYMBOL, s (CLASSleft, SYMBOLright)) adamc@211: | CLASS SYMBOL EQ cexp (SgiClass (SYMBOL, cexp), s (CLASSleft, cexpright)) adamc@211: | CLASS SYMBOL SYMBOL EQ cexp (let adamc@211: val loc = s (CLASSleft, cexpright) adamc@211: val k = (KType, loc) adamc@211: val c = (CAbs (SYMBOL2, SOME k, cexp), loc) adamc@211: in adamc@211: (SgiClass (SYMBOL1, c), s (CLASSleft, cexpright)) adamc@211: end) adamc@460: | COOKIE SYMBOL COLON cexp (let adamc@460: val loc = s (COOKIEleft, cexpright) adamc@460: val t = (CApp ((CVar (["Basis"], "http_cookie"), loc), adamc@460: entable cexp), loc) adamc@460: in adamc@460: (SgiVal (SYMBOL, t), loc) adamc@460: end) adamc@30: adamc@30: sgis : ([]) adamc@30: | sgi sgis (sgi :: sgis) adamc@30: adamc@30: str : STRUCT decls END (StrConst decls, s (STRUCTleft, ENDright)) adamc@34: | spath (spath) adamc@40: | FUNCTOR LPAREN CSYMBOL COLON sgn RPAREN DARROW str adamc@40: (StrFun (CSYMBOL, sgn, NONE, str), s (FUNCTORleft, strright)) adamc@40: | FUNCTOR LPAREN CSYMBOL COLON sgn RPAREN COLON sgn DARROW str adamc@40: (StrFun (CSYMBOL, sgn1, SOME sgn2, str), s (FUNCTORleft, strright)) adamc@44: | spath LPAREN str RPAREN (StrApp (spath, str), s (spathleft, RPARENright)) adamc@34: adamc@34: spath : CSYMBOL (StrVar CSYMBOL, s (CSYMBOLleft, CSYMBOLright)) adamc@34: | spath DOT CSYMBOL (StrProj (spath, CSYMBOL), s (spathleft, CSYMBOLright)) adamc@30: adamc@1: kind : TYPE (KType, s (TYPEleft, TYPEright)) adamc@1: | NAME (KName, s (NAMEleft, NAMEright)) adamc@1: | LBRACE kind RBRACE (KRecord kind, s (LBRACEleft, RBRACEright)) adamc@1: | kind ARROW kind (KArrow (kind1, kind2), s (kind1left, kind2right)) adamc@1: | LPAREN kind RPAREN (#1 kind, s (LPARENleft, RPARENright)) adamc@82: | KUNIT (KUnit, s (KUNITleft, KUNITright)) adamc@18: | UNDERUNDER (KWild, s (UNDERUNDERleft, UNDERUNDERright)) adamc@207: | LPAREN ktuple RPAREN (KTuple ktuple, s (LPARENleft, RPARENright)) adamc@207: adamc@207: ktuple : kind STAR kind ([kind1, kind2]) adamc@207: | kind STAR ktuple (kind :: ktuple) adamc@1: adamc@1: capps : cterm (cterm) adamc@1: | capps cterm (CApp (capps, cterm), s (cappsleft, ctermright)) adamc@1: adamc@1: cexp : capps (capps) adamc@1: | cexp ARROW cexp (TFun (cexp1, cexp2), s (cexp1left, cexp2right)) adamc@15: | SYMBOL kcolon kind ARROW cexp (TCFun (kcolon, SYMBOL, kind, cexp), s (SYMBOLleft, cexpright)) adamc@1: adamc@1: | cexp PLUSPLUS cexp (CConcat (cexp1, cexp2), s (cexp1left, cexp1right)) adamc@1: adamc@239: | FN cargs DARROW cexp (#1 (cargs (cexp, (KWild, s (FNleft, cexpright))))) adamc@1: adamc@8: | LPAREN cexp RPAREN DCOLON kind (CAnnot (cexp, kind), s (LPARENleft, kindright)) adamc@6: adamc@18: | UNDER DCOLON kind (CWild kind, s (UNDERleft, UNDERright)) adamc@195: | ctuple (let adamc@195: val loc = s (ctupleleft, ctupleright) adamc@195: in adamc@195: (TRecord (CRecord (ListUtil.mapi (fn (i, c) => adamc@195: ((CName (Int.toString (i + 1)), loc), adamc@195: c)) ctuple), adamc@195: loc), loc) adamc@195: end) adamc@18: adamc@1: kcolon : DCOLON (Explicit) adamc@1: | TCOLON (Implicit) adamc@1: adamc@239: cargs : carg (carg) adamc@239: | cargl (cargl) adamc@239: adamc@239: cargl : cargp cargp (cargp1 o cargp2) adamc@239: | cargp cargl (cargp o cargl) adamc@239: adamc@240: cargl2 : (fn x => x) adamc@240: | cargp cargl2 (cargp o cargl2) adamc@240: adamc@241: carg : SYMBOL DCOLON kind (fn (c, k) => adamc@239: let adamc@239: val loc = s (SYMBOLleft, kindright) adamc@239: in adamc@239: ((CAbs (SYMBOL, SOME kind, c), loc), adamc@239: (KArrow (kind, k), loc)) adamc@239: end) adamc@329: | UNDER DCOLON kind (fn (c, k) => adamc@329: let adamc@329: val loc = s (UNDERleft, kindright) adamc@329: in adamc@329: ((CAbs ("_", SOME kind, c), loc), adamc@329: (KArrow (kind, k), loc)) adamc@329: end) adamc@241: | cargp (cargp) adamc@239: adamc@239: cargp : SYMBOL (fn (c, k) => adamc@239: let adamc@239: val loc = s (SYMBOLleft, SYMBOLright) adamc@239: in adamc@239: ((CAbs (SYMBOL, NONE, c), loc), adamc@239: (KArrow ((KWild, loc), k), loc)) adamc@239: end) adamc@329: | UNDER (fn (c, k) => adamc@329: let adamc@329: val loc = s (UNDERleft, UNDERright) adamc@329: in adamc@329: ((CAbs ("_", NONE, c), loc), adamc@329: (KArrow ((KWild, loc), k), loc)) adamc@329: end) adamc@239: | LPAREN SYMBOL DCOLON kind RPAREN (fn (c, k) => adamc@239: let adamc@239: val loc = s (LPARENleft, RPARENright) adamc@239: in adamc@239: ((CAbs (SYMBOL, SOME kind, c), loc), adamc@239: (KArrow (kind, k), loc)) adamc@239: end) adamc@354: | LBRACK cterm TWIDDLE cterm RBRACK (fn (c, k) => adamc@354: let adamc@354: val loc = s (LBRACKleft, RBRACKright) adamc@354: in adamc@354: ((CDisjoint (cterm1, cterm2, c), loc), adamc@354: k) adamc@354: end) adamc@239: adamc@34: path : SYMBOL ([], SYMBOL) adamc@34: | CSYMBOL DOT path (let val (ms, x) = path in (CSYMBOL :: ms, x) end) adamc@34: adamc@156: cpath : CSYMBOL ([], CSYMBOL) adamc@156: | CSYMBOL DOT cpath (let val (ms, x) = cpath in (CSYMBOL :: ms, x) end) adamc@156: adamc@59: mpath : CSYMBOL ([CSYMBOL]) adamc@59: | CSYMBOL DOT mpath (CSYMBOL :: mpath) adamc@59: adamc@1: cterm : LPAREN cexp RPAREN (#1 cexp, s (LPARENleft, RPARENright)) adamc@1: | LBRACK rcon RBRACK (CRecord rcon, s (LBRACKleft, RBRACKright)) adamc@83: | LBRACK rconn RBRACK (CRecord rconn, s (LBRACKleft, RBRACKright)) adamc@1: | LBRACE rcone RBRACE (TRecord (CRecord rcone, s (LBRACEleft, RBRACEright)), adamc@1: s (LBRACEleft, RBRACEright)) adamc@1: | DOLLAR cterm (TRecord cterm, s (DOLLARleft, ctermright)) adamc@1: | HASH CSYMBOL (CName CSYMBOL, s (HASHleft, CSYMBOLright)) adamc@195: | HASH INT (CName (Int64.toString INT), s (HASHleft, INTright)) adamc@1: adamc@34: | path (CVar path, s (pathleft, pathright)) adamc@207: | path DOT INT (CProj ((CVar path, s (pathleft, pathright)), Int64.toInt INT), adamc@207: s (pathleft, INTright)) adamc@18: | UNDER (CWild (KWild, s (UNDERleft, UNDERright)), s (UNDERleft, UNDERright)) adamc@67: | FOLD (CFold, s (FOLDleft, FOLDright)) adamc@82: | UNIT (CUnit, s (UNITleft, UNITright)) adamc@207: | LPAREN ctuplev RPAREN (CTuple ctuplev, s (LPARENleft, RPARENright)) adamc@207: adamc@207: ctuplev: cexp COMMA cexp ([cexp1, cexp2]) adamc@207: | cexp COMMA ctuplev (cexp :: ctuplev) adamc@1: adamc@196: ctuple : capps STAR capps ([capps1, capps2]) adamc@196: | capps STAR ctuple (capps :: ctuple) adamc@195: adamc@1: rcon : ([]) adamc@1: | ident EQ cexp ([(ident, cexp)]) adamc@1: | ident EQ cexp COMMA rcon ((ident, cexp) :: rcon) adamc@1: adamc@83: rconn : ident ([(ident, (CUnit, s (identleft, identright)))]) adamc@83: | ident COMMA rconn ((ident, (CUnit, s (identleft, identright))) :: rconn) adamc@83: adamc@1: rcone : ([]) adamc@1: | ident COLON cexp ([(ident, cexp)]) adamc@1: | ident COLON cexp COMMA rcone ((ident, cexp) :: rcone) adamc@1: adamc@1: ident : CSYMBOL (CName CSYMBOL, s (CSYMBOLleft, CSYMBOLright)) adamc@195: | INT (CName (Int64.toString INT), s (INTleft, INTright)) adamc@200: | SYMBOL (CVar ([], SYMBOL), s (SYMBOLleft, SYMBOLright)) adamc@8: adamc@8: eapps : eterm (eterm) adamc@8: | eapps eterm (EApp (eapps, eterm), s (eappsleft, etermright)) adamc@8: | eapps LBRACK cexp RBRACK (ECApp (eapps, cexp), s (eappsleft, RBRACKright)) adamc@8: adamc@8: eexp : eapps (eapps) adamc@241: | FN eargs DARROW eexp (let adamc@93: val loc = s (FNleft, eexpright) adamc@93: in adamc@241: #1 (eargs (eexp, (CWild (KType, loc), loc))) adamc@93: end) adamc@196: | eexp COLON cexp (EAnnot (eexp, cexp), s (eexpleft, cexpright)) adamc@149: | eexp MINUSMINUS cexp (ECut (eexp, cexp), s (eexpleft, cexpright)) adamc@170: | CASE eexp OF barOpt branch branchs (ECase (eexp, branch :: branchs), s (CASEleft, branchsright)) adamc@190: | IF eexp THEN eexp ELSE eexp (let adamc@190: val loc = s (IFleft, eexp3right) adamc@190: in adamc@190: (ECase (eexp1, [((PCon (["Basis"], "True", NONE), loc), eexp2), adamc@190: ((PCon (["Basis"], "False", NONE), loc), eexp3)]), loc) adamc@190: end) adamc@434: | bind SEMI eexp (let adamc@434: val loc = s (bindleft, eexpright) adamc@434: val (v, to, e1) = bind adamc@403: val e = (EVar (["Basis"], "bind", Infer), loc) adamc@434: val e = (EApp (e, e1), loc) adamc@243: in adamc@434: (EApp (e, (EAbs (v, to, eexp), loc)), loc) adamc@299: end) adamc@256: | eexp EQ eexp (native_op ("eq", eexp1, eexp2, s (eexp1left, eexp2right))) adamc@257: | eexp NE eexp (native_op ("ne", eexp1, eexp2, s (eexp1left, eexp2right))) adamc@389: | MINUS eterm (native_unop ("neg", eterm, s (MINUSleft, etermright))) adamc@389: | eexp PLUS eexp (native_op ("plus", eexp1, eexp2, s (eexp1left, eexp2right))) adamc@389: | eexp MINUS eexp (native_op ("minus", eexp1, eexp2, s (eexp1left, eexp2right))) adamc@389: | eterm STAR eexp (native_op ("times", eterm, eexp, s (etermleft, eexpright))) adamc@389: | eexp DIVIDE eexp (native_op ("div", eexp1, eexp2, s (eexp1left, eexp2right))) adamc@389: | eexp MOD eexp (native_op ("mod", eexp1, eexp2, s (eexp1left, eexp2right))) adamc@391: adamc@391: | eexp LT eexp (native_op ("lt", eexp1, eexp2, s (eexp1left, eexp2right))) adamc@391: | eexp LE eexp (native_op ("le", eexp1, eexp2, s (eexp1left, eexp2right))) adamc@391: | eexp GT eexp (native_op ("gt", eexp1, eexp2, s (eexp1left, eexp2right))) adamc@391: | eexp GE eexp (native_op ("ge", eexp1, eexp2, s (eexp1left, eexp2right))) adamc@391: adamc@445: | eexp PLUSPLUS eexp (EConcat (eexp1, eexp2), s (eexp1left, eexp2right)) adamc@8: adamc@434: bind : SYMBOL LARROW eapps (SYMBOL, NONE, eapps) adamc@434: | UNIT LARROW eapps (let adamc@434: val loc = s (UNITleft, eappsright) adamc@434: in adamc@434: ("_", SOME (TRecord (CRecord [], loc), loc), eapps) adamc@434: end) adamc@434: | eapps (let adamc@434: val loc = s (eappsleft, eappsright) adamc@434: in adamc@434: ("_", SOME (TRecord (CRecord [], loc), loc), eapps) adamc@434: end) adamc@434: adamc@241: eargs : earg (earg) adamc@241: | eargl (eargl) adamc@241: adamc@241: eargl : eargp eargp (eargp1 o eargp2) adamc@241: | eargp eargl (eargp o eargl) adamc@241: adamc@242: eargl2 : (fn x => x) adamc@242: | eargp eargl2 (eargp o eargl2) adamc@242: adamc@241: earg : SYMBOL kcolon kind (fn (e, t) => adamc@241: let adamc@241: val loc = s (SYMBOLleft, kindright) adamc@241: in adamc@241: ((ECAbs (kcolon, SYMBOL, kind, e), loc), adamc@241: (TCFun (kcolon, SYMBOL, kind, t), loc)) adamc@241: end) adamc@241: | SYMBOL COLON cexp (fn (e, t) => adamc@241: let adamc@241: val loc = s (SYMBOLleft, cexpright) adamc@241: in adamc@241: ((EAbs (SYMBOL, SOME cexp, e), loc), adamc@241: (TFun (cexp, t), loc)) adamc@241: end) adamc@241: | UNDER COLON cexp (fn (e, t) => adamc@241: let adamc@241: val loc = s (UNDERleft, cexpright) adamc@241: in adamc@241: ((EAbs ("_", SOME cexp, e), loc), adamc@241: (TFun (cexp, t), loc)) adamc@241: end) adamc@241: | eargp (eargp) adamc@241: adamc@241: eargp : SYMBOL (fn (e, t) => adamc@241: let adamc@241: val loc = s (SYMBOLleft, SYMBOLright) adamc@241: in adamc@241: ((EAbs (SYMBOL, NONE, e), loc), adamc@241: (TFun ((CWild (KType, loc), loc), t), loc)) adamc@241: end) adamc@241: | UNIT (fn (e, t) => adamc@241: let adamc@241: val loc = s (UNITleft, UNITright) adamc@241: val t' = (TRecord (CRecord [], loc), loc) adamc@241: in adamc@241: ((EAbs ("_", SOME t', e), loc), adamc@241: (TFun (t', t), loc)) adamc@241: end) adamc@241: | UNDER (fn (e, t) => adamc@241: let adamc@241: val loc = s (UNDERleft, UNDERright) adamc@241: in adamc@241: ((EAbs ("_", NONE, e), loc), adamc@241: (TFun ((CWild (KType, loc), loc), t), loc)) adamc@241: end) adamc@241: | LPAREN SYMBOL kcolon kind RPAREN(fn (e, t) => adamc@241: let adamc@241: val loc = s (LPARENleft, RPARENright) adamc@241: in adamc@241: ((ECAbs (kcolon, SYMBOL, kind, e), loc), adamc@241: (TCFun (kcolon, SYMBOL, kind, t), loc)) adamc@241: end) adamc@241: | LPAREN SYMBOL COLON cexp RPAREN (fn (e, t) => adamc@241: let adamc@241: val loc = s (LPARENleft, RPARENright) adamc@241: in adamc@241: ((EAbs (SYMBOL, SOME cexp, e), loc), adamc@241: (TFun (cexp, t), loc)) adamc@241: end) adamc@241: | LPAREN UNDER COLON cexp RPAREN (fn (e, t) => adamc@241: let adamc@241: val loc = s (LPARENleft, RPARENright) adamc@241: in adamc@241: ((EAbs ("_", SOME cexp, e), loc), adamc@241: (TFun (cexp, t), loc)) adamc@241: end) adamc@354: | LPAREN cterm TWIDDLE cterm RPAREN(fn (e, t) => adamc@354: let adamc@354: val loc = s (LPARENleft, RPARENright) adamc@354: in adamc@354: ((EDisjoint (cterm1, cterm2, e), loc), adamc@354: (CDisjoint (cterm1, cterm2, t), loc)) adamc@354: end) adamc@356: | LBRACK cterm TWIDDLE cterm RBRACK(fn (e, t) => adamc@356: let adamc@356: val loc = s (LBRACKleft, RBRACKright) adamc@356: in adamc@356: ((EDisjoint (cterm1, cterm2, e), loc), adamc@356: (CDisjoint (cterm1, cterm2, t), loc)) adamc@356: end) adamc@241: adamc@8: eterm : LPAREN eexp RPAREN (#1 eexp, s (LPARENleft, RPARENright)) adamc@195: | LPAREN etuple RPAREN (let adamc@195: val loc = s (LPARENleft, RPARENright) adamc@195: in adamc@195: (ERecord (ListUtil.mapi (fn (i, e) => adamc@195: ((CName (Int.toString (i + 1)), loc), adamc@195: e)) etuple), loc) adamc@195: end) adamc@8: adamc@403: | path (EVar (#1 path, #2 path, Infer), s (pathleft, pathright)) adamc@403: | cpath (EVar (#1 cpath, #2 cpath, Infer), s (cpathleft, cpathright)) adamc@403: | AT path (EVar (#1 path, #2 path, TypesOnly), s (ATleft, pathright)) adamc@403: | AT AT path (EVar (#1 path, #2 path, DontInfer), s (AT1left, pathright)) adamc@403: | AT cpath (EVar (#1 cpath, #2 cpath, TypesOnly), s (ATleft, cpathright)) adamc@403: | AT AT cpath (EVar (#1 cpath, #2 cpath, DontInfer), s (AT1left, cpathright)) adamc@12: | LBRACE rexp RBRACE (ERecord rexp, s (LBRACEleft, RBRACEright)) adamc@110: | UNIT (ERecord [], s (UNITleft, UNITright)) adamc@12: adamc@14: | INT (EPrim (Prim.Int INT), s (INTleft, INTright)) adamc@14: | FLOAT (EPrim (Prim.Float FLOAT), s (FLOATleft, FLOATright)) adamc@14: | STRING (EPrim (Prim.String STRING), s (STRINGleft, STRINGright)) adamc@14: adamc@200: | path DOT idents (let adamc@200: val loc = s (pathleft, identsright) adamc@200: in adamc@200: foldl (fn (ident, e) => adamc@200: (EField (e, ident), loc)) adamc@403: (EVar (#1 path, #2 path, Infer), s (pathleft, pathright)) idents adamc@403: end) adamc@403: | AT path DOT idents (let adamc@403: val loc = s (ATleft, identsright) adamc@403: in adamc@403: foldl (fn (ident, e) => adamc@403: (EField (e, ident), loc)) adamc@403: (EVar (#1 path, #2 path, TypesOnly), s (pathleft, pathright)) idents adamc@403: end) adamc@403: | AT AT path DOT idents (let adamc@403: val loc = s (AT1left, identsright) adamc@403: in adamc@403: foldl (fn (ident, e) => adamc@403: (EField (e, ident), loc)) adamc@403: (EVar (#1 path, #2 path, DontInfer), s (pathleft, pathright)) idents adamc@200: end) adamc@71: | FOLD (EFold, s (FOLDleft, FOLDright)) adamc@71: adamc@360: | XML_BEGIN xml XML_END (let adamc@360: val loc = s (XML_BEGINleft, XML_ENDright) adamc@360: in adamc@360: if XML_BEGIN = "xml" then adamc@360: () adamc@360: else adamc@360: ErrorMsg.errorAt loc "Initial XML tag pair aren't both tagged \"xml\"."; adamc@360: xml adamc@360: end) adamc@360: | XML_BEGIN XML_END (let adamc@360: val loc = s (XML_BEGINleft, XML_ENDright) adamc@360: in adamc@360: if XML_BEGIN = "xml" then adamc@360: () adamc@360: else adamc@360: ErrorMsg.errorAt loc "Initial XML tag pair aren't both tagged \"xml\"."; adamc@403: (EApp ((EVar (["Basis"], "cdata", Infer), loc), adamc@360: (EPrim (Prim.String ""), loc)), adamc@360: loc) adamc@360: end) adamc@360: | XML_BEGIN_END (let adamc@360: val loc = s (XML_BEGIN_ENDleft, XML_BEGIN_ENDright) adamc@360: in adamc@360: if XML_BEGIN_END = "xml" then adamc@360: () adamc@360: else adamc@360: ErrorMsg.errorAt loc "Initial XML tag pair aren't both tagged \"xml\"."; adamc@403: (EApp ((EVar (["Basis"], "cdata", Infer), loc), adamc@360: (EPrim (Prim.String ""), loc)), adamc@360: loc) adamc@360: end) adamc@302: adamc@204: | LPAREN query RPAREN (query) adamc@300: | LPAREN CWHERE sqlexp RPAREN (sqlexp) adamc@339: | LPAREN SQL sqlexp RPAREN (sqlexp) adamc@302: adamc@302: | LPAREN INSERT INTO texp LPAREN fields RPAREN VALUES LPAREN sqlexps RPAREN RPAREN adamc@302: (let adamc@302: val loc = s (LPAREN1left, RPAREN3right) adamc@302: adamc@403: val e = (EVar (["Basis"], "insert", Infer), loc) adamc@302: val e = (EApp (e, texp), loc) adamc@302: in adamc@302: if length fields <> length sqlexps then adamc@302: ErrorMsg.errorAt loc "Length mismatch in INSERT field specification" adamc@302: else adamc@302: (); adamc@302: (EApp (e, (ERecord (ListPair.zip (fields, sqlexps)), loc)), loc) adamc@302: end) adamc@310: | LPAREN enterDml UPDATE texp SET fsets CWHERE sqlexp leaveDml RPAREN adamc@303: (let adamc@303: val loc = s (LPARENleft, RPARENright) adamc@303: adamc@403: val e = (EVar (["Basis"], "update", Infer), loc) adamc@342: val e = (ECApp (e, (CWild (KRecord (KType, loc), loc), loc)), loc) adamc@306: val e = (EApp (e, (ERecord fsets, loc)), loc) adamc@305: val e = (EApp (e, texp), loc) adamc@303: in adamc@303: (EApp (e, sqlexp), loc) adamc@303: end) adamc@310: | LPAREN enterDml DELETE FROM texp CWHERE sqlexp leaveDml RPAREN adamc@304: (let adamc@304: val loc = s (LPARENleft, RPARENright) adamc@304: adamc@403: val e = (EVar (["Basis"], "delete", Infer), loc) adamc@304: val e = (EApp (e, texp), loc) adamc@304: in adamc@304: (EApp (e, sqlexp), loc) adamc@304: end) adamc@302: adamc@211: | UNDER (EWild, s (UNDERleft, UNDERright)) adamc@91: adamc@446: | LET edecls IN eexp END (ELet (edecls, eexp), s (LETleft, ENDright)) adamc@446: adamc@446: edecls : ([]) adamc@446: | edecl edecls (edecl :: edecls) adamc@446: adamc@446: edecl : VAL vali ((EDVal vali, s (VALleft, valiright))) adamc@446: | VAL REC valis ((EDValRec valis, s (VALleft, valisright))) adamc@446: | FUN valis ((EDValRec valis, s (FUNleft, valisright))) adamc@446: adamc@310: enterDml : (inDml := true) adamc@310: leaveDml : (inDml := false) adamc@310: adamc@403: texp : SYMBOL (EVar ([], SYMBOL, Infer), s (SYMBOLleft, SYMBOLright)) adamc@302: | LBRACE LBRACE eexp RBRACE RBRACE (eexp) adamc@302: adamc@302: fields : fident ([fident]) adamc@302: | fident COMMA fields (fident :: fields) adamc@302: adamc@302: sqlexps: sqlexp ([sqlexp]) adamc@302: | sqlexp COMMA sqlexps (sqlexp :: sqlexps) adamc@302: adamc@303: fsets : fident EQ sqlexp ([(fident, sqlexp)]) adamc@303: | fident EQ sqlexp COMMA fsets ((fident, sqlexp) :: fsets) adamc@303: adamc@200: idents : ident ([ident]) adamc@200: | ident DOT idents (ident :: idents) adamc@200: adamc@195: etuple : eexp COMMA eexp ([eexp1, eexp2]) adamc@195: | eexp COMMA etuple (eexp :: etuple) adamc@195: adamc@170: branch : pat DARROW eexp (pat, eexp) adamc@170: adamc@170: branchs: ([]) adamc@170: | BAR branch branchs (branch :: branchs) adamc@170: adamc@170: pat : pterm (pterm) adamc@170: | cpath pterm (PCon (#1 cpath, #2 cpath, SOME pterm), s (cpathleft, ptermright)) adamc@170: adamc@170: pterm : SYMBOL (PVar SYMBOL, s (SYMBOLleft, SYMBOLright)) adamc@170: | cpath (PCon (#1 cpath, #2 cpath, NONE), s (cpathleft, cpathright)) adamc@170: | UNDER (PWild, s (UNDERleft, UNDERright)) adamc@173: | INT (PPrim (Prim.Int INT), s (INTleft, INTright)) adamc@173: | STRING (PPrim (Prim.String STRING), s (STRINGleft, STRINGright)) adamc@170: | LPAREN pat RPAREN (pat) adamc@174: | LBRACE RBRACE (PRecord ([], false), s (LBRACEleft, RBRACEright)) adamc@174: | UNIT (PRecord ([], false), s (UNITleft, UNITright)) adamc@174: | LBRACE rpat RBRACE (PRecord rpat, s (LBRACEleft, RBRACEright)) adamc@195: | LPAREN ptuple RPAREN (PRecord (ListUtil.mapi (fn (i, p) => (Int.toString (i + 1), p)) ptuple, adamc@195: false), adamc@195: s (LPARENleft, RPARENright)) adamc@174: adamc@175: rpat : CSYMBOL EQ pat ([(CSYMBOL, pat)], false) adamc@243: | INT EQ pat ([(Int64.toString INT, pat)], false) adamc@174: | DOTDOTDOT ([], true) adamc@175: | CSYMBOL EQ pat COMMA rpat ((CSYMBOL, pat) :: #1 rpat, #2 rpat) adamc@243: | INT EQ pat COMMA rpat ((Int64.toString INT, pat) :: #1 rpat, #2 rpat) adamc@170: adamc@195: ptuple : pat COMMA pat ([pat1, pat2]) adamc@195: | pat COMMA ptuple (pat :: ptuple) adamc@195: adamc@12: rexp : ([]) adamc@12: | ident EQ eexp ([(ident, eexp)]) adamc@12: | ident EQ eexp COMMA rexp ((ident, eexp) :: rexp) adamc@91: adamc@141: xml : xmlOne xml (let adamc@141: val pos = s (xmlOneleft, xmlright) adamc@141: in adamc@141: (EApp ((EApp ( adamc@403: (EVar (["Basis"], "join", Infer), pos), adamc@91: xmlOne), pos), adamc@141: xml), pos) adamc@141: end) adamc@141: | xmlOne (xmlOne) adamc@91: adamc@403: xmlOne : NOTAGS (EApp ((EVar (["Basis"], "cdata", Infer), s (NOTAGSleft, NOTAGSright)), adamc@141: (EPrim (Prim.String NOTAGS), s (NOTAGSleft, NOTAGSright))), adamc@141: s (NOTAGSleft, NOTAGSright)) adamc@141: | tag DIVIDE GT (let adamc@141: val pos = s (tagleft, GTright) adamc@141: in adamc@141: (EApp (#2 tag, adamc@403: (EApp ((EVar (["Basis"], "cdata", Infer), pos), adamc@141: (EPrim (Prim.String ""), pos)), adamc@141: pos)), pos) adamc@141: end) adamc@141: adamc@141: | tag GT xml END_TAG (let adamc@141: val pos = s (tagleft, GTright) adamc@325: val et = tagIn END_TAG adamc@141: in adamc@325: if #1 tag = et then adamc@361: if et = "form" then adamc@403: (EApp ((EVar (["Basis"], "form", Infer), pos), adamc@141: xml), pos) adamc@141: else adamc@141: (EApp (#2 tag, xml), pos) adamc@141: else adamc@325: (if ErrorMsg.anyErrors () then adamc@325: () adamc@325: else adamc@325: ErrorMsg.errorAt pos "Begin and end tags don't match."; adamc@141: (EFold, pos)) adamc@141: end) adamc@141: | LBRACE eexp RBRACE (eexp) adamc@391: | LBRACE LBRACK eexp RBRACK RBRACE (let adamc@391: val loc = s (LBRACEleft, RBRACEright) adamc@403: val e = (EVar (["Top"], "txt", Infer), loc) adamc@391: in adamc@391: (EApp (e, eexp), loc) adamc@391: end) adamc@92: adamc@141: tag : tagHead attrs (let adamc@141: val pos = s (tagHeadleft, attrsright) adamc@141: in adamc@141: (#1 tagHead, adamc@403: (EApp ((EApp ((EVar (["Basis"], "tag", Infer), pos), adamc@141: (ERecord attrs, pos)), pos), adamc@141: (EApp (#2 tagHead, adamc@141: (ERecord [], pos)), pos)), adamc@141: pos)) adamc@141: end) adamc@141: adamc@141: tagHead: BEGIN_TAG (let adamc@325: val bt = tagIn BEGIN_TAG adamc@141: val pos = s (BEGIN_TAGleft, BEGIN_TAGright) adamc@141: in adamc@325: (bt, adamc@473: (EVar (["Basis"], bt, Infer), pos)) adamc@141: end) adamc@141: | tagHead LBRACE cexp RBRACE (#1 tagHead, (ECApp (#2 tagHead, cexp), s (tagHeadleft, RBRACEright))) adamc@92: adamc@104: attrs : ([]) adamc@104: | attr attrs (attr :: attrs) adamc@104: adamc@204: attr : SYMBOL EQ attrv ((CName (capitalize SYMBOL), s (SYMBOLleft, SYMBOLright)), attrv) adamc@204: adamc@104: attrv : INT (EPrim (Prim.Int INT), s (INTleft, INTright)) adamc@104: | FLOAT (EPrim (Prim.Float FLOAT), s (FLOATleft, FLOATright)) adamc@104: | STRING (EPrim (Prim.String STRING), s (STRINGleft, STRINGright)) adamc@110: | LBRACE eexp RBRACE (eexp) adamc@226: adamc@232: query : query1 obopt lopt ofopt (let adamc@229: val loc = s (query1left, query1right) adamc@230: adamc@230: val re = (ERecord [((CName "Rows", loc), adamc@230: query1), adamc@230: ((CName "OrderBy", loc), adamc@231: obopt), adamc@231: ((CName "Limit", loc), adamc@232: lopt), adamc@232: ((CName "Offset", loc), adamc@232: ofopt)], loc) adamc@229: in adamc@403: (EApp ((EVar (["Basis"], "sql_query", Infer), loc), re), loc) adamc@229: end) adamc@204: adamc@227: query1 : SELECT select FROM tables wopt gopt hopt adamc@209: (let adamc@204: val loc = s (SELECTleft, tablesright) adamc@207: adamc@233: val (sel, exps) = adamc@207: case select of adamc@233: Star => (map (fn (nm, _) => adamc@233: (nm, (CTuple [(CWild (KRecord (KType, loc), loc), adamc@233: loc), adamc@233: (CRecord [], loc)], adamc@233: loc))) tables, adamc@233: []) adamc@207: | Items sis => adamc@207: let adamc@207: val tabs = map (fn (nm, _) => (nm, (CRecord [], loc))) tables adamc@233: val (tabs, exps) = foldl (amend_select loc) (tabs, []) sis adamc@207: in adamc@233: (map (fn (nm, c) => (nm, adamc@233: (CTuple [c, adamc@233: (CWild (KRecord (KType, loc), loc), adamc@233: loc)], loc))) tabs, adamc@233: exps) adamc@207: end adamc@207: adamc@207: val sel = (CRecord sel, loc) adamc@207: adamc@226: val grp = case gopt of adamc@403: NONE => (ECApp ((EVar (["Basis"], "sql_subset_all", adamc@403: Infer), loc), adamc@226: (CWild (KRecord (KRecord (KType, loc), loc), adamc@226: loc), loc)), loc) adamc@226: | SOME gis => adamc@226: let adamc@226: val tabs = map (fn (nm, _) => adamc@226: (nm, (CRecord [], loc))) tables adamc@226: val tabs = foldl (amend_group loc) tabs gis adamc@226: adamc@226: val tabs = map (fn (nm, c) => adamc@226: (nm, adamc@226: (CTuple [c, adamc@226: (CWild (KRecord (KType, loc), adamc@226: loc), adamc@226: loc)], loc))) tabs adamc@226: in adamc@403: (ECApp ((EVar (["Basis"], "sql_subset", Infer), loc), adamc@226: (CRecord tabs, loc)), loc) adamc@226: end adamc@226: adamc@403: val e = (EVar (["Basis"], "sql_query1", Infer), loc) adamc@209: val re = (ERecord [((CName "From", loc), adamc@209: (ERecord tables, loc)), adamc@209: ((CName "Where", loc), adamc@223: wopt), adamc@224: ((CName "GroupBy", loc), adamc@226: grp), adamc@224: ((CName "Having", loc), adamc@224: hopt), adamc@223: ((CName "SelectFields", loc), adamc@403: (ECApp ((EVar (["Basis"], "sql_subset", Infer), loc), adamc@233: sel), loc)), adamc@233: ((CName "SelectExps", loc), adamc@233: (ERecord exps, loc))], loc) adamc@223: adamc@209: val e = (EApp (e, re), loc) adamc@204: in adamc@207: e adamc@204: end) adamc@229: | query1 UNION query1 (sql_relop ("union", query11, query12, s (query11left, query12right))) adamc@229: | query1 INTERSECT query1 (sql_relop ("intersect", query11, query12, s (query11left, query12right))) adamc@229: | query1 EXCEPT query1 (sql_relop ("except", query11, query12, s (query11left, query12right))) adamc@204: adamc@204: tables : table ([table]) adamc@204: | table COMMA tables (table :: tables) adamc@204: adamc@204: tname : CSYMBOL (CName CSYMBOL, s (CSYMBOLleft, CSYMBOLright)) adamc@204: | LBRACE cexp RBRACE (cexp) adamc@204: adamc@243: table : SYMBOL ((CName (capitalize SYMBOL), s (SYMBOLleft, SYMBOLright)), adamc@403: (EVar ([], SYMBOL, Infer), s (SYMBOLleft, SYMBOLright))) adamc@403: | SYMBOL AS tname (tname, (EVar ([], SYMBOL, Infer), s (SYMBOLleft, SYMBOLright))) adamc@221: | LBRACE LBRACE eexp RBRACE RBRACE AS tname (tname, eexp) adamc@207: adamc@243: tident : SYMBOL (CName (capitalize SYMBOL), s (SYMBOLleft, SYMBOLright)) adamc@207: | CSYMBOL (CName CSYMBOL, s (CSYMBOLleft, CSYMBOLright)) adamc@221: | LBRACE LBRACE cexp RBRACE RBRACE (cexp) adamc@207: adamc@207: fident : CSYMBOL (CName CSYMBOL, s (CSYMBOLleft, CSYMBOLright)) adamc@207: | LBRACE cexp RBRACE (cexp) adamc@207: adamc@207: seli : tident DOT fident (Field (tident, fident)) adamc@233: | sqlexp AS fident (Exp (fident, sqlexp)) adamc@341: | tident DOT LBRACE LBRACE cexp RBRACE RBRACE (Fields (tident, cexp)) adamc@207: adamc@207: selis : seli ([seli]) adamc@207: | seli COMMA selis (seli :: selis) adamc@207: adamc@207: select : STAR (Star) adamc@207: | selis (Items selis) adamc@209: adamc@403: sqlexp : TRUE (sql_inject (EVar (["Basis"], "True", Infer), adamc@209: s (TRUEleft, TRUEright))) adamc@403: | FALSE (sql_inject (EVar (["Basis"], "False", Infer), adamc@209: s (FALSEleft, FALSEright))) adamc@209: adamc@222: | INT (sql_inject (EPrim (Prim.Int INT), adamc@222: s (INTleft, INTright))) adamc@222: | FLOAT (sql_inject (EPrim (Prim.Float FLOAT), adamc@222: s (FLOATleft, FLOATright))) adamc@229: | STRING (sql_inject (EPrim (Prim.String STRING), adamc@229: s (STRINGleft, STRINGright))) adamc@441: | CURRENT_TIMESTAMP (sql_nfunc ("current_timestamp", adamc@441: s (CURRENT_TIMESTAMPleft, CURRENT_TIMESTAMPright))) adamc@222: adamc@221: | tident DOT fident (let adamc@221: val loc = s (tidentleft, fidentright) adamc@403: val e = (EVar (["Basis"], "sql_field", Infer), loc) adamc@221: val e = (ECApp (e, tident), loc) adamc@221: in adamc@221: (ECApp (e, fident), loc) adamc@221: end) adamc@234: | CSYMBOL (let adamc@234: val loc = s (CSYMBOLleft, CSYMBOLright) adamc@310: in adamc@310: if !inDml then adamc@310: let adamc@403: val e = (EVar (["Basis"], "sql_field", Infer), loc) adamc@310: val e = (ECApp (e, (CName "T", loc)), loc) adamc@310: in adamc@310: (ECApp (e, (CName CSYMBOL, loc)), loc) adamc@310: end adamc@310: else adamc@310: let adamc@403: val e = (EVar (["Basis"], "sql_exp", Infer), loc) adamc@310: in adamc@310: (ECApp (e, (CName CSYMBOL, loc)), loc) adamc@310: end adamc@310: end) adamc@221: adamc@471: | LBRACE eexp RBRACE (eexp) adamc@470: adamc@219: | sqlexp EQ sqlexp (sql_compare ("eq", sqlexp1, sqlexp2, s (sqlexp1left, sqlexp2right))) adamc@219: | sqlexp NE sqlexp (sql_compare ("ne", sqlexp1, sqlexp2, s (sqlexp1left, sqlexp2right))) adamc@219: | sqlexp LT sqlexp (sql_compare ("lt", sqlexp1, sqlexp2, s (sqlexp1left, sqlexp2right))) adamc@219: | sqlexp LE sqlexp (sql_compare ("le", sqlexp1, sqlexp2, s (sqlexp1left, sqlexp2right))) adamc@219: | sqlexp GT sqlexp (sql_compare ("gt", sqlexp1, sqlexp2, s (sqlexp1left, sqlexp2right))) adamc@219: | sqlexp GE sqlexp (sql_compare ("ge", sqlexp1, sqlexp2, s (sqlexp1left, sqlexp2right))) adamc@219: adamc@220: | sqlexp CAND sqlexp (sql_binary ("and", sqlexp1, sqlexp2, s (sqlexp1left, sqlexp2right))) adamc@220: | sqlexp OR sqlexp (sql_binary ("or", sqlexp1, sqlexp2, s (sqlexp1left, sqlexp2right))) adamc@220: | NOT sqlexp (sql_unary ("not", sqlexp, s (NOTleft, sqlexpright))) adamc@220: adamc@470: | sqlexp IS NULL (let adamc@470: val loc = s (sqlexpleft, NULLright) adamc@470: in adamc@470: (EApp ((EVar (["Basis"], "sql_is_null", Infer), loc), adamc@470: sqlexp), loc) adamc@470: end) adamc@470: adamc@471: | LBRACE LBRACK eexp RBRACK RBRACE (sql_inject (#1 eexp, adamc@471: s (LBRACEleft, RBRACEright))) adamc@220: | LPAREN sqlexp RPAREN (sqlexp) adamc@210: adamc@467: | NULL (sql_inject ((EVar (["Basis"], "None", Infer), adamc@467: s (NULLleft, NULLright)))) adamc@467: adamc@235: | COUNT LPAREN STAR RPAREN (let adamc@235: val loc = s (COUNTleft, RPARENright) adamc@235: in adamc@403: (EApp ((EVar (["Basis"], "sql_count", Infer), loc), adamc@235: (ERecord [], loc)), loc) adamc@235: end) adamc@236: | sqlagg LPAREN sqlexp RPAREN (let adamc@236: val loc = s (sqlaggleft, RPARENright) adamc@236: adamc@403: val e = (EVar (["Basis"], "sql_" ^ sqlagg, Infer), loc) adamc@403: val e = (EApp ((EVar (["Basis"], "sql_aggregate", Infer), loc), adamc@236: e), loc) adamc@236: in adamc@236: (EApp (e, sqlexp), loc) adamc@236: end) adamc@235: adamc@403: wopt : (sql_inject (EVar (["Basis"], "True", Infer), adamc@230: dummy)) adamc@209: | CWHERE sqlexp (sqlexp) adamc@226: adamc@226: groupi : tident DOT fident (GField (tident, fident)) adamc@226: adamc@226: groupis: groupi ([groupi]) adamc@226: | groupi COMMA groupis (groupi :: groupis) adamc@226: adamc@226: gopt : (NONE) adamc@226: | GROUP BY groupis (SOME groupis) adamc@227: adamc@403: hopt : (sql_inject (EVar (["Basis"], "True", Infer), adamc@230: dummy)) adamc@227: | HAVING sqlexp (sqlexp) adamc@230: adamc@403: obopt : (ECApp ((EVar (["Basis"], "sql_order_by_Nil", Infer), dummy), adamc@234: (CWild (KRecord (KType, dummy), dummy), dummy)), adamc@230: dummy) adamc@230: | ORDER BY obexps (obexps) adamc@230: adamc@268: obitem : sqlexp diropt (sqlexp, diropt) adamc@268: adamc@268: obexps : obitem (let adamc@268: val loc = s (obitemleft, obitemright) adamc@230: adamc@403: val e' = (ECApp ((EVar (["Basis"], "sql_order_by_Nil", Infer), loc), adamc@234: (CWild (KRecord (KType, loc), loc), loc)), adamc@230: loc) adamc@403: val e = (EApp ((EVar (["Basis"], "sql_order_by_Cons", Infer), loc), adamc@268: #1 obitem), loc) adamc@268: val e = (EApp (e, #2 obitem), loc) adamc@230: in adamc@230: (EApp (e, e'), loc) adamc@230: end) adamc@268: | obitem COMMA obexps (let adamc@268: val loc = s (obitemleft, obexpsright) adamc@230: adamc@403: val e = (EApp ((EVar (["Basis"], "sql_order_by_Cons", Infer), loc), adamc@268: #1 obitem), loc) adamc@268: val e = (EApp (e, #2 obitem), loc) adamc@230: in adamc@230: (EApp (e, obexps), loc) adamc@230: end) adamc@231: adamc@403: diropt : (EVar (["Basis"], "sql_asc", Infer), dummy) adamc@403: | ASC (EVar (["Basis"], "sql_asc", Infer), s (ASCleft, ASCright)) adamc@403: | DESC (EVar (["Basis"], "sql_desc", Infer), s (DESCleft, DESCright)) adamc@268: adamc@403: lopt : (EVar (["Basis"], "sql_no_limit", Infer), dummy) adamc@403: | LIMIT ALL (EVar (["Basis"], "sql_no_limit", Infer), dummy) adamc@231: | LIMIT sqlint (let adamc@231: val loc = s (LIMITleft, sqlintright) adamc@231: in adamc@403: (EApp ((EVar (["Basis"], "sql_limit", Infer), loc), sqlint), loc) adamc@231: end) adamc@231: adamc@403: ofopt : (EVar (["Basis"], "sql_no_offset", Infer), dummy) adamc@232: | OFFSET sqlint (let adamc@232: val loc = s (OFFSETleft, sqlintright) adamc@232: in adamc@403: (EApp ((EVar (["Basis"], "sql_offset", Infer), loc), sqlint), loc) adamc@232: end) adamc@232: adamc@231: sqlint : INT (EPrim (Prim.Int INT), s (INTleft, INTright)) adamc@231: | LBRACE eexp RBRACE (eexp) adamc@236: adamc@236: sqlagg : AVG ("avg") adamc@236: | SUM ("sum") adamc@236: | MIN ("min") adamc@236: | MAX ("max")