From 57131ad0203977941eb50d60550fa82e88614496 Mon Sep 17 00:00:00 2001 From: sewardj <unknown> Date: Wed, 3 Feb 1999 17:08:44 +0000 Subject: [PATCH] [project @ 1999-02-03 17:08:25 by sewardj] Preliminary results of the merge of STG hugs and 990121. These files will compile and link, but don't work yet. --- ghc/interpreter/Makefile | 23 +- ghc/interpreter/codegen.c | 32 +- ghc/interpreter/command.h | 14 +- ghc/interpreter/compiler.c | 1517 +++++++++++++++++++- ghc/interpreter/connect.h | 525 ++++++- ghc/interpreter/derive.c | 399 +++--- ghc/interpreter/dynamic.c | 8 +- ghc/interpreter/errors.h | 26 +- ghc/interpreter/free.c | 10 +- ghc/interpreter/hugs.c | 405 ++++-- ghc/interpreter/input.c | 360 +++-- ghc/interpreter/lift.c | 13 +- ghc/interpreter/link.c | 252 +++- ghc/interpreter/link.h | 73 +- ghc/interpreter/machdep.c | 329 ++++- ghc/interpreter/optimise.c | 9 +- ghc/interpreter/output.c | 235 ++-- ghc/interpreter/parser.y | 1177 ++++++---------- ghc/interpreter/preds.c | 159 ++- ghc/interpreter/prelude.h | 28 +- ghc/interpreter/scc.c | 19 +- ghc/interpreter/static.c | 2649 ++++++++++++++++++++++++++--------- ghc/interpreter/stg.c | 502 ++++++- ghc/interpreter/stgSubst.c | 10 +- ghc/interpreter/storage.c | 1148 +++++++++++---- ghc/interpreter/storage.h | 458 ++++-- ghc/interpreter/subst.c | 198 ++- ghc/interpreter/subst.h | 22 +- ghc/interpreter/timer.c | 16 +- ghc/interpreter/translate.c | 24 +- ghc/interpreter/type.c | 536 +++++-- 31 files changed, 8204 insertions(+), 2972 deletions(-) diff --git a/ghc/interpreter/Makefile b/ghc/interpreter/Makefile index 07af3abdd091..b5c074a09c3e 100644 --- a/ghc/interpreter/Makefile +++ b/ghc/interpreter/Makefile @@ -1,6 +1,6 @@ # ----------------------------------------------------------------------------- # -# $Id: Makefile,v 1.3 1999/01/14 18:08:26 sewardj Exp $ # +# $Id: Makefile,v 1.4 1999/02/03 17:08:25 sewardj Exp $ # # ----------------------------------------------------------------------------- # TOP = ../.. @@ -13,21 +13,26 @@ RTS_DIR = $(TOP)/ghc/rts # interpreter and relevant .a/.so files # # --------------------------------------------------------------------- # +YACC = bison -y +%.c: %.y + -$(YACC) $< + mv y.tab.c $@ + + HS_SRCS = -C_SRCS = \ - charset.c codegen.c compiler.c connect.c derive.c desugar.c \ - dynamic.c free.c hugs.c input.c interface.c lift.c link.c \ - machdep.c modules.c optimise.c output.c pat.c pmc.c pp.c static.c \ - stg.c stgSubst.c storage.c subst.c translate.c type.c +Y_SRCS = parser.y +C_SRCS = link.c type.c static.c storage.c derive.c input.c compiler.c subst.c \ + translate.c codegen.c lift.c free.c stgSubst.c optimise.c output.c \ + hugs.c dynamic.c stg.c -SRC_CC_OPTS = -g -I$(GHC_DIR)/includes -D__HUGS__ -Wall -Wno-unused +SRC_CC_OPTS = -g -I$(GHC_DIR)/includes -I$(GHC_DIR)/rts -D__HUGS__ -Wall -Wno-unused GHC_LIBS_NEEDED = $(TOP)/ghc/rts/libHSrts.a $(TOP)/ghc/rts/gmp/libgmp.a GHC_DYN_CBITS_DIR = $(TOP)/ghc/lib/std/cbits GHC_DYN_CBITS = $(GHC_DYN_CBITS_DIR)/libHS_cbits.so -all :: $(GHC_LIBS_NEEDED) $(GHC_DYN_CBITS) hugs Prelude.hs +all :: parser.c $(GHC_LIBS_NEEDED) $(GHC_DYN_CBITS) hugs Prelude.hs hugs: $(C_OBJS) $(CC) -rdynamic -o $@ $(CC_OPTS) $^ $(GHC_LIBS_NEEDED) -lbfd -liberty -ldl -lm @@ -41,7 +46,6 @@ $(TOP)/ghc/rts/libHSrts.a: $(TOP)/ghc/rts/gmp/libgmp.a: (cd $(TOP)/ghc/rts/gmp ; make clean ; make) - # --------------------------------------------------------------------- # # Prelude # # --------------------------------------------------------------------- # @@ -153,6 +157,7 @@ checkrun: all CLEAN_FILES += hugs libHS_cbits.so $(GHC_DYN_CBITS) $(GHC_DYN_CBITS_DIR)/*.o CLEAN_FILES += $(TOP)/ghc/rts/libHSrts.a $(TOP)/ghc/rts/*.o CLEAN_FILES += $(TOP)/ghc/rts/gmp/libgmp.a $(TOP)/ghc/rts/gmp/*.o $(TOP)/ghc/rts/gmp/*/*.o +CLEAN_FILES += parser.c INSTALL_LIBEXECS = hugs diff --git a/ghc/interpreter/codegen.c b/ghc/interpreter/codegen.c index 9bc719e72e7b..f396cdd9c750 100644 --- a/ghc/interpreter/codegen.c +++ b/ghc/interpreter/codegen.c @@ -1,4 +1,4 @@ -/* -*- mode: hugs-c; -*- */ + /* -------------------------------------------------------------------------- * Code generator * @@ -7,20 +7,18 @@ * Hugs version 1.4, December 1997 * * $RCSfile: codegen.c,v $ - * $Revision: 1.2 $ - * $Date: 1998/12/02 13:21:59 $ + * $Revision: 1.3 $ + * $Date: 1999/02/03 17:08:25 $ * ------------------------------------------------------------------------*/ #include "prelude.h" #include "storage.h" +#include "backend.h" #include "connect.h" #include "errors.h" -#include "stg.h" #include "Assembler.h" -#include "lift.h" #include "link.h" -#include "pp.h" -#include "codegen.h" + /* -------------------------------------------------------------------------- * Local function prototypes: @@ -193,7 +191,7 @@ static AsmBCO cgAlts( AsmSp root, AsmSp sp, List alts ) setPos(hd(vs),asmUnbox(bco,boxingConRep(con))); } else { asmBeginUnpack(bco); - map1Proc(cgBind,bco,reverse(vs)); + map1Proc(cgBind,bco,rev(vs)); asmEndUnpack(bco); } cgExpr(bco,root,body); @@ -237,7 +235,7 @@ static AsmBCO cgLambda( StgExpr e ) AsmBCO bco = asmBeginBCO(); AsmSp root = asmBeginArgCheck(bco); - map1Proc(cgBind,bco,reverse(stgLambdaArgs(e))); + map1Proc(cgBind,bco,rev(stgLambdaArgs(e))); asmEndArgCheck(bco,root); /* ppStgExpr(e); */ @@ -296,7 +294,7 @@ static Void cgExpr( AsmBCO bco, AsmSp root, StgExpr e ) /* No need to use return address or to Slide */ AsmSp beginPrim = asmBeginPrim(bco); - map1Proc(pushAtom,bco,reverse(stgPrimArgs(scrut))); + map1Proc(pushAtom,bco,rev(stgPrimArgs(scrut))); asmEndPrim(bco,(AsmPrim*)name(stgPrimOp(scrut)).primop,beginPrim); for(; nonNull(alts); alts=tl(alts)) { @@ -304,7 +302,7 @@ static Void cgExpr( AsmBCO bco, AsmSp root, StgExpr e ) List pats = stgPrimAltPats(alt); StgExpr body = stgPrimAltBody(alt); AsmSp altBegin = asmBeginAlt(bco); - map1Proc(cgBind,bco,reverse(pats)); + map1Proc(cgBind,bco,rev(pats)); testPrimPats(bco,root,pats,body); asmEndAlt(bco,altBegin); } @@ -343,7 +341,7 @@ static Void cgExpr( AsmBCO bco, AsmSp root, StgExpr e ) case STGAPP: /* Tail call */ { AsmSp env = asmBeginEnter(bco); - map1Proc(pushAtom,bco,reverse(stgAppArgs(e))); + map1Proc(pushAtom,bco,rev(stgAppArgs(e))); pushAtom(bco,stgAppFun(e)); asmEndEnter(bco,env,root); break; @@ -378,7 +376,7 @@ static Void cgExpr( AsmBCO bco, AsmSp root, StgExpr e ) case STGPRIM: /* Tail call again */ { AsmSp beginPrim = asmBeginPrim(bco); - map1Proc(pushAtom,bco,reverse(stgPrimArgs(e))); + map1Proc(pushAtom,bco,rev(stgPrimArgs(e))); asmEndPrim(bco,(AsmPrim*)name(e).primop,beginPrim); /* map1Proc(cgBind,bco,rs_vars); */ assert(0); /* asmReturn_retty(); */ @@ -435,7 +433,7 @@ static Void build( AsmBCO bco, StgVar v ) doNothing(); /* already done in alloc */ } else { AsmSp start = asmBeginPack(bco); - map1Proc(pushAtom,bco,reverse(args)); + map1Proc(pushAtom,bco,rev(args)); asmEndPack(bco,getPos(v),start,stgConInfo(con)); } return; @@ -451,12 +449,12 @@ static Void build( AsmBCO bco, StgVar v ) && whatIs(stgVarBody(fun)) == LAMBDA && length(stgLambdaArgs(stgVarBody(fun))) > length(args)) { AsmSp start = asmBeginMkPAP(bco); - map1Proc(pushAtom,bco,reverse(args)); + map1Proc(pushAtom,bco,rev(args)); pushAtom(bco,fun); asmEndMkPAP(bco,getPos(v),start); /* optimisation */ } else { AsmSp start = asmBeginMkAP(bco); - map1Proc(pushAtom,bco,reverse(args)); + map1Proc(pushAtom,bco,rev(args)); pushAtom(bco,fun); asmEndMkAP(bco,getPos(v),start); } @@ -575,7 +573,7 @@ static void endTop( StgVar v ) /* ToDo: merge this code with cgLambda */ AsmBCO bco = (AsmBCO)getObj(v); AsmSp root = asmBeginArgCheck(bco); - map1Proc(cgBind,bco,reverse(stgLambdaArgs(rhs))); + map1Proc(cgBind,bco,rev(stgLambdaArgs(rhs))); asmEndArgCheck(bco,root); cgExpr(bco,root,stgLambdaBody(rhs)); diff --git a/ghc/interpreter/command.h b/ghc/interpreter/command.h index 80753bafa92a..d709554110b1 100644 --- a/ghc/interpreter/command.h +++ b/ghc/interpreter/command.h @@ -1,13 +1,14 @@ /* -------------------------------------------------------------------------- * Interpreter command structure * - * Copyright (c) The University of Nottingham and Yale University, 1994-1997. - * All rights reserved. See NOTICE for details and conditions of use etc... - * Hugs version 1.4, December 1997 + * Hugs 98 is Copyright (c) Mark P Jones, Alastair Reid and the Yale + * Haskell Group 1994-99, and is distributed as Open Source software + * under the Artistic License; see the file "Artistic" that is included + * in the distribution for details. * * $RCSfile: command.h,v $ - * $Revision: 1.2 $ - * $Date: 1998/12/02 13:22:01 $ + * $Revision: 1.3 $ + * $Date: 1999/02/03 17:08:26 $ * ------------------------------------------------------------------------*/ typedef Int Command; @@ -37,7 +38,6 @@ extern Command readCommand Args((struct cmd *, Char, Char)); #define INFO 15 #define COLLECT 16 #define SETMODULE 17 -#define SHOWVERSION 18 -#define NOCMD 19 +#define NOCMD 18 /*-------------------------------------------------------------------------*/ diff --git a/ghc/interpreter/compiler.c b/ghc/interpreter/compiler.c index 3ca136f9d3f2..cc9b536091cd 100644 --- a/ghc/interpreter/compiler.c +++ b/ghc/interpreter/compiler.c @@ -1,55 +1,1462 @@ -/* -*- mode: hugs-c; -*- */ + /* -------------------------------------------------------------------------- * This is the Hugs compiler, handling translation of typechecked code to * `kernel' language, elimination of pattern matching and translation to * super combinators (lambda lifting). * - * Copyright (c) The University of Nottingham and Yale University, 1994-1997. - * All rights reserved. See NOTICE for details and conditions of use etc... - * Hugs version 1.4, December 1997 + * Hugs 98 is Copyright (c) Mark P Jones, Alastair Reid and the Yale + * Haskell Group 1994-99, and is distributed as Open Source software + * under the Artistic License; see the file "Artistic" that is included + * in the distribution for details. * * $RCSfile: compiler.c,v $ - * $Revision: 1.2 $ - * $Date: 1998/12/02 13:22:01 $ + * $Revision: 1.3 $ + * $Date: 1999/02/03 17:08:26 $ * ------------------------------------------------------------------------*/ #include "prelude.h" #include "storage.h" +#include "backend.h" #include "connect.h" -#include "input.h" -#include "compiler.h" -#include "hugs.h" /* for target */ #include "errors.h" +#include "Rts.h" /* for rts_eval and related stuff */ +#include "RtsAPI.h" /* for rts_eval and related stuff */ +#include "Schedule.h" +#include "link.h" -#include "desugar.h" -#include "pmc.h" - -#include "optimise.h" - -#include "Rts.h" /* for rts_eval and related stuff */ -#include "RtsAPI.h" /* for rts_eval and related stuff */ +/*#define DEBUG_SHOWSC*/ /* Must also be set in output.c */ -Name currentName; /* Top level name being processed */ +Addr inputCode; /* Addr of compiled code for expr */ +static Name currentName; /* Top level name being processed */ #if DEBUG_CODE -Bool debugCode = FALSE; /* TRUE => print G-code to screen */ +Bool debugCode = FALSE; /* TRUE => print G-code to screen */ #endif + + /* -------------------------------------------------------------------------- * Local function prototypes: * ------------------------------------------------------------------------*/ -static List local addGlobals( List binds ); +static Cell local translate Args((Cell)); +static Void local transPair Args((Pair)); +static Void local transTriple Args((Triple)); +static Void local transAlt Args((Cell)); +static Void local transCase Args((Cell)); +static List local transBinds Args((List)); +static Cell local transRhs Args((Cell)); +static Cell local mkConsList Args((List)); +static Cell local expandLetrec Args((Cell)); +static Cell local transComp Args((Cell,List,Cell)); +static Cell local transDo Args((Cell,Cell,List)); +static Cell local transConFlds Args((Cell,List)); +static Cell local transUpdFlds Args((Cell,List,List)); + +static Cell local refutePat Args((Cell)); +static Cell local refutePatAp Args((Cell)); +static Cell local matchPat Args((Cell)); +static List local remPat Args((Cell,Cell,List)); +static List local remPat1 Args((Cell,Cell,List)); + +static Cell local pmcTerm Args((Int,List,Cell)); +static Cell local pmcPair Args((Int,List,Pair)); +static Cell local pmcTriple Args((Int,List,Triple)); +static Cell local pmcVar Args((List,Text)); +static Void local pmcLetrec Args((Int,List,Pair)); +static Cell local pmcVarDef Args((Int,List,List)); +static Void local pmcFunDef Args((Int,List,Triple)); +static List local altsMatch Args((Int,Int,List,List)); +static Cell local match Args((Int,List)); +static Cell local joinMas Args((Int,List)); +static Bool local canFail Args((Cell)); +static List local addConTable Args((Cell,Cell,List)); +static Void local advance Args((Int,Int,Cell)); +static Bool local emptyMatch Args((Cell)); +static Cell local maDiscr Args((Cell)); +static Bool local isNumDiscr Args((Cell)); +static Bool local eqNumDiscr Args((Cell,Cell)); +#if TREX +static Bool local isExtDiscr Args((Cell)); +static Bool local eqExtDiscr Args((Cell,Cell)); +#endif + +static Cell local lift Args((Int,List,Cell)); +static Void local liftPair Args((Int,List,Pair)); +static Void local liftTriple Args((Int,List,Triple)); +static Void local liftAlt Args((Int,List,Cell)); +static Void local liftNumcase Args((Int,List,Triple)); +static Cell local liftVar Args((List,Cell)); +static Cell local liftLetrec Args((Int,List,Cell)); +static Void local liftFundef Args((Int,List,Triple)); +static Void local solve Args((List)); + +static Cell local preComp Args((Cell)); +static Cell local preCompPair Args((Pair)); +static Cell local preCompTriple Args((Triple)); +static Void local preCompCase Args((Pair)); +static Cell local preCompOffset Args((Int)); + static Void local compileGlobalFunction Args((Pair)); static Void local compileGenFunction Args((Name)); static Name local compileSelFunction Args((Pair)); +static Void local newGlobalFunction Args((Name,Int,List,Int,Cell)); /* -------------------------------------------------------------------------- - * STG stuff + * Translation: Convert input expressions into a less complex language + * of terms using only LETREC, AP, constants and vars. + * Also remove pattern definitions on lhs of eqns. + * ------------------------------------------------------------------------*/ + +static Cell local translate(e) /* Translate expression: */ +Cell e; { + switch (whatIs(e)) { + case LETREC : snd(snd(e)) = translate(snd(snd(e))); + return expandLetrec(e); + + case COND : transTriple(snd(e)); + return e; + + case AP : fst(e) = translate(fst(e)); + + if (fst(e)==nameId || fst(e)==nameInd) + return translate(snd(e)); +#if EVAL_INSTANCES + if (fst(e)==nameStrict) + return nameIStrict; + if (fst(e)==nameSeq) + return nameISeq; +#endif + if (isName(fst(e)) && + isMfun(fst(e)) && + mfunOf(fst(e))==0) + return translate(snd(e)); + + snd(e) = translate(snd(e)); + return e; + +#if BIGNUMS + case POSNUM : + case ZERONUM : + case NEGNUM : return e; +#endif + case NAME : if (e==nameOtherwise) + return nameTrue; + if (isCfun(e)) { + if (isName(name(e).defn)) + return name(e).defn; + if (isPair(name(e).defn)) + return snd(name(e).defn); + } + return e; + +#if TREX + case RECSEL : return nameRecSel; + + case EXT : +#endif + case TUPLE : + case VAROPCELL : + case VARIDCELL : + case DICTVAR : + case INTCELL : + case FLOATCELL : + case STRCELL : + case CHARCELL : return e; + + case FINLIST : mapOver(translate,snd(e)); + return mkConsList(snd(e)); + + case DOCOMP : { Cell m = translate(fst(snd(e))); + Cell r = translate(fst(snd(snd(e)))); + return transDo(m,r,snd(snd(snd(e)))); + } + + case MONADCOMP : { Cell m = translate(fst(snd(e))); + Cell r = translate(fst(snd(snd(e)))); + Cell qs = snd(snd(snd(e))); + if (m == nameListMonad) + return transComp(r,qs,nameNil); + else { +#if MONAD_COMPS + r = ap(ap(nameReturn,m),r); + return transDo(m,r,qs); +#else + internal("translate: monad comps"); +#endif + } + } + + case CONFLDS : return transConFlds(fst(snd(e)),snd(snd(e))); + + case UPDFLDS : return transUpdFlds(fst3(snd(e)), + snd3(snd(e)), + thd3(snd(e))); + + case CASE : { Cell nv = inventVar(); + mapProc(transCase,snd(snd(e))); + return ap(LETREC, + pair(singleton(pair(nv,snd(snd(e)))), + ap(nv,translate(fst(snd(e)))))); + } + + case LAMBDA : { Cell nv = inventVar(); + transAlt(snd(e)); + return ap(LETREC, + pair(singleton(pair( + nv, + singleton(snd(e)))), + nv)); + } + + default : internal("translate"); + } + return e; +} + +static Void local transPair(pr) /* Translate each component in a */ +Pair pr; { /* pair of expressions. */ + fst(pr) = translate(fst(pr)); + snd(pr) = translate(snd(pr)); +} + +static Void local transTriple(tr) /* Translate each component in a */ +Triple tr; { /* triple of expressions. */ + fst3(tr) = translate(fst3(tr)); + snd3(tr) = translate(snd3(tr)); + thd3(tr) = translate(thd3(tr)); +} + +static Void local transAlt(e) /* Translate alt: */ +Cell e; { /* ([Pat], Rhs) ==> ([Pat], Rhs') */ + snd(e) = transRhs(snd(e)); +} + +static Void local transCase(c) /* Translate case: */ +Cell c; { /* (Pat, Rhs) ==> ([Pat], Rhs') */ + fst(c) = singleton(fst(c)); + snd(c) = transRhs(snd(c)); +} + +static List local transBinds(bs) /* Translate list of bindings: */ +List bs; { /* eliminating pattern matching on */ + List newBinds = NIL; /* lhs of bindings. */ + for (; nonNull(bs); bs=tl(bs)) { + if (isVar(fst(hd(bs)))) { + mapProc(transAlt,snd(hd(bs))); + newBinds = cons(hd(bs),newBinds); + } + else + newBinds = remPat(fst(snd(hd(bs))), + snd(snd(hd(bs)))=transRhs(snd(snd(hd(bs)))), + newBinds); + } + return newBinds; +} + +static Cell local transRhs(rhs) /* Translate rhs: removing line nos */ +Cell rhs; { + switch (whatIs(rhs)) { + case LETREC : snd(snd(rhs)) = transRhs(snd(snd(rhs))); + return expandLetrec(rhs); + + case GUARDED : mapOver(snd,snd(rhs)); /* discard line number */ + mapProc(transPair,snd(rhs)); + return rhs; + + default : return translate(snd(rhs)); /* discard line number */ + } +} + +static Cell local mkConsList(es) /* Construct expression for list es */ +List es; { /* using nameNil and nameCons */ + if (isNull(es)) + return nameNil; + else + return ap(ap(nameCons,hd(es)),mkConsList(tl(es))); +} + +static Cell local expandLetrec(root) /* translate LETREC with list of */ +Cell root; { /* groups of bindings (from depend. */ + Cell e = snd(snd(root)); /* analysis) to use nested LETRECs */ + List bss = fst(snd(root)); + Cell temp; + + if (isNull(bss)) /* should never happen, but just in */ + return e; /* case: LETREC [] IN e ==> e */ + + mapOver(transBinds,bss); /* translate each group of bindings */ + + for (temp=root; nonNull(tl(bss)); bss=tl(bss)) { + fst(snd(temp)) = hd(bss); + snd(snd(temp)) = ap(LETREC,pair(NIL,e)); + temp = snd(snd(temp)); + } + fst(snd(temp)) = hd(bss); + + return root; +} + +/* -------------------------------------------------------------------------- + * Translation of list comprehensions is based on the description in + * `The Implementation of Functional Programming Languages': + * + * [ e | qs ] ++ l => transComp e qs l + * transComp e [] l => e : l + * transComp e ((p<-xs):qs) l => LETREC _h [] = l + * _h (p:_xs) = transComp e qs (_h _xs) + * _h (_:_xs) = _h _xs --if p !failFree + * IN _h xs + * transComp e (b:qs) l => if b then transComp e qs l else l + * transComp e (decls:qs) l => LETREC decls IN transComp e qs l + * ------------------------------------------------------------------------*/ + +static Cell local transComp(e,qs,l) /* Translate [e | qs] ++ l */ +Cell e; +List qs; +Cell l; { + if (nonNull(qs)) { + Cell q = hd(qs); + Cell qs1 = tl(qs); + + switch (fst(q)) { + case FROMQUAL : { Cell ld = NIL; + Cell hVar = inventVar(); + Cell xsVar = inventVar(); + + if (!failFree(fst(snd(q)))) + ld = cons(pair(singleton( + ap(ap(nameCons, + WILDCARD), + xsVar)), + ap(hVar,xsVar)), + ld); + + ld = cons(pair(singleton( + ap(ap(nameCons, + fst(snd(q))), + xsVar)), + transComp(e, + qs1, + ap(hVar,xsVar))), + ld); + ld = cons(pair(singleton(nameNil), + l), + ld); + + return ap(LETREC, + pair(singleton(pair(hVar, + ld)), + ap(hVar, + translate(snd(snd(q)))))); + } + + case QWHERE : return + expandLetrec(ap(LETREC, + pair(snd(q), + transComp(e,qs1,l)))); + + case BOOLQUAL : return ap(COND, + triple(translate(snd(q)), + transComp(e,qs1,l), + l)); + } + } + + return ap(ap(nameCons,e),l); +} + +/* -------------------------------------------------------------------------- + * Translation of monad comprehensions written using do-notation: + * + * do { e } => e + * do { p <- exp; qs } => LETREC _h p = do { qs } + * _h _ = fail m "match fails" + * IN bind m exp _h + * do { LET decls; qs } => LETREC decls IN do { qs } + * do { IF guard; qs } => if guard then do { qs } else fail m "guard fails" + * do { e; qs } => LETREC _h _ = [ e | qs ] in bind m exp _h + * + * where m :: Monad f + * ------------------------------------------------------------------------*/ + +static Cell local transDo(m,e,qs) /* Translate do { qs ; e } */ +Cell m; +Cell e; +List qs; { + if (nonNull(qs)) { + Cell q = hd(qs); + Cell qs1 = tl(qs); + + switch (fst(q)) { + case FROMQUAL : { Cell ld = NIL; + Cell hVar = inventVar(); + + if (!failFree(fst(snd(q)))) { + Cell str = mkStr(findText("match fails")); + ld = cons(pair(singleton(WILDCARD), + ap2(nameMFail,m,str)), + ld); + } + + ld = cons(pair(singleton(fst(snd(q))), + transDo(m,e,qs1)), + ld); + + return ap(LETREC, + pair(singleton(pair(hVar,ld)), + ap(ap(ap(nameBind, + m), + translate(snd(snd(q)))), + hVar))); + } + + case DOQUAL : { Cell hVar = inventVar(); + Cell ld = cons(pair(singleton(WILDCARD), + transDo(m,e,qs1)), + NIL); + return ap(LETREC, + pair(singleton(pair(hVar,ld)), + ap(ap(ap(nameBind, + m), + translate(snd(q))), + hVar))); + } + + case QWHERE : return + expandLetrec(ap(LETREC, + pair(snd(q), + transDo(m,e,qs1)))); + + case BOOLQUAL : return + ap(COND, + triple(translate(snd(q)), + transDo(m,e,qs1), + ap2(nameMFail,m, + mkStr(findText("guard fails"))))); + } + } + return e; +} + +/* -------------------------------------------------------------------------- + * Translation of named field construction and update: + * + * Construction is implemented using the following transformation: + * + * C{x1=e1, ..., xn=en} = C v1 ... vm + * where: + * vi = e1, if the ith component of C is labelled with x1 + * ... + * = en, if the ith component of C is labelled with xn + * = undefined, otherwise + * + * Update is implemented using the following transformation: + * + * e{x1=e1, ..., xn=en} + * = let nv (C a1 ... am) v1 ... vn = C a1' .. am' + * nv (D b1 ... bk) v1 ... vn = D b1' .. bk + * ... + * nv _ v1 ... vn = error "failed update" + * in nv e e1 ... en + * where: + * nv, v1, ..., vn, a1, ..., am, b1, ..., bk, ... are new variables, + * C,D,... = { K | K is a constr fun s.t. {x1,...,xn} subset of sels(K)} + * and: + * ai' = v1, if the ith component of C is labelled with x1 + * ... + * = vn, if the ith component of C is labelled with xn + * = ai, otherwise + * etc... + * + * The error case may be omitted if C,D,... is an enumeration of all of the + * constructors for the datatype concerned. Strictly speaking, error case + * isn't needed at all -- the only benefit of including it is that the user + * will get a "failed update" message rather than a cryptic {v354 ...}. + * So, for now, we'll go with the second option! + * + * For the time being, code for each update operation is generated + * independently of any other updates. However, if updates are used + * frequently, then we might want to consider changing the implementation + * at a later stage to cache definitions of functions like nv above. This + * would create a shared library of update functions, indexed by a set of + * constructors {C,D,...}. + * ------------------------------------------------------------------------*/ + +static Cell local transConFlds(c,flds) /* Translate C{flds} */ +Name c; +List flds; { + Cell e = c; + Int m = name(c).arity; + Int i; + for (i=m; i>0; i--) + e = ap(e,nameUndefined); + for (; nonNull(flds); flds=tl(flds)) { + Cell a = e; + for (i=m-sfunPos(fst(hd(flds)),c); i>0; i--) + a = fun(a); + arg(a) = translate(snd(hd(flds))); + } + return e; +} + +static Cell local transUpdFlds(e,cs,flds)/* Translate e{flds} */ +Cell e; /* (cs is corresp list of constrs) */ +List cs; +List flds; { + Cell nv = inventVar(); + Cell body = ap(nv,translate(e)); + List fs = flds; + List args = NIL; + List alts = NIL; + + for (; nonNull(fs); fs=tl(fs)) { /* body = nv e1 ... en */ + Cell b = hd(fs); /* args = [v1, ..., vn] */ + body = ap(body,translate(snd(b))); + args = cons(inventVar(),args); + } + + for (; nonNull(cs); cs=tl(cs)) { /* Loop through constructors to */ + Cell c = hd(cs); /* build up list of alts. */ + Cell pat = c; + Cell rhs = c; + List as = args; + Int m = name(c).arity; + Int i; + + for (i=m; i>0; i--) { /* pat = C a1 ... am */ + Cell a = inventVar(); /* rhs = C a1 ... am */ + pat = ap(pat,a); + rhs = ap(rhs,a); + } + + for (fs=flds; nonNull(fs); fs=tl(fs), as=tl(as)) { + Name s = fst(hd(fs)); /* Replace approp ai in rhs with */ + Cell r = rhs; /* vars from [v1,...,vn] */ + for (i=m-sfunPos(s,c); i>0; i--) + r = fun(r); + arg(r) = hd(as); + } + + alts = cons(pair(cons(pat,args),rhs),alts); + } + return ap(LETREC,pair(singleton(pair(nv,alts)),body)); +} + +/* -------------------------------------------------------------------------- + * Elimination of pattern bindings: + * + * The following code adopts the definition of failure free patterns as given + * in the Haskell 1.3 report; the term "irrefutable" is also used there for + * a subset of the failure free patterns described here, but has no useful + * role in this implementation. Basically speaking, the failure free patterns + * are: variable, wildcard, ~apat + * var@apat, if apat is failure free + * C apat1 ... apatn if C is a product constructor + * (i.e. an only constructor) and + * apat1,...,apatn are failure free + * Note that the last case automatically covers the case where C comes from + * a newtype construction. + * ------------------------------------------------------------------------*/ + +Bool failFree(pat) /* is pattern failure free? (do we need */ +Cell pat; { /* a conformality check?) */ + Cell c = getHead(pat); + + switch (whatIs(c)) { + case ASPAT : return failFree(snd(snd(pat))); + + case NAME : if (!isCfun(c) || cfunOf(c)!=0) + return FALSE; + /*intentional fall-thru*/ + case TUPLE : for (; isAp(pat); pat=fun(pat)) + if (!failFree(arg(pat))) + return FALSE; + /*intentional fall-thru*/ + case LAZYPAT : + case VAROPCELL : + case VARIDCELL : + case DICTVAR : + case WILDCARD : return TRUE; + +#if TREX + case EXT : return failFree(extField(pat)) && + failFree(extRow(pat)); +#endif + + case CONFLDS : if (cfunOf(fst(snd(c)))==0) { + List fs = snd(snd(c)); + for (; nonNull(fs); fs=tl(fs)) + if (!failFree(snd(hd(fs)))) + return FALSE; + return TRUE; + } + /*intentional fall-thru*/ + default : return FALSE; + } +} + +static Cell local refutePat(pat) /* find pattern to refute in conformality*/ +Cell pat; { /* test with pat. */ + /* e.g. refPat (x:y) == (_:_) */ + /* refPat ~(x:y) == _ etc.. */ + + switch (whatIs(pat)) { + case ASPAT : return refutePat(snd(snd(pat))); + + case FINLIST : { Cell ys = snd(pat); + Cell xs = NIL; + for (; nonNull(ys); ys=tl(ys)) + xs = ap(ap(nameCons,refutePat(hd(ys))),xs); + return revOnto(xs,nameNil); + } + + case CONFLDS : { Cell ps = NIL; + Cell fs = snd(snd(pat)); + for (; nonNull(fs); fs=tl(fs)) { + Cell p = refutePat(snd(hd(fs))); + ps = cons(pair(fst(hd(fs)),p),ps); + } + return pair(CONFLDS,pair(fst(snd(pat)),rev(ps))); + } + + case VAROPCELL : + case VARIDCELL : + case DICTVAR : + case WILDCARD : + case LAZYPAT : return WILDCARD; + + case STRCELL : + case CHARCELL : +#if NPLUSK + case ADDPAT : +#endif + case TUPLE : + case NAME : return pat; + + case AP : return refutePatAp(pat); + + default : internal("refutePat"); + return NIL; /*NOTREACHED*/ + } +} + +static Cell local refutePatAp(p) /* find pattern to refute in conformality*/ +Cell p; { + Cell h = getHead(p); + if (h==nameFromInt || h==nameFromInteger || h==nameFromDouble) + return p; +#if NPLUSK + else if (whatIs(h)==ADDPAT) + return ap(fun(p),refutePat(arg(p))); +#endif +#if TREX + else if (isExt(h)) { + Cell pf = refutePat(extField(p)); + Cell pr = refutePat(extRow(p)); + return ap(ap(fun(fun(p)),pf),pr); + } +#endif + else { + List as = getArgs(p); + mapOver(refutePat,as); + return applyToArgs(h,as); + } +} + +static Cell local matchPat(pat) /* find pattern to match against */ +Cell pat; { /* replaces parts of pattern that do not */ + /* include variables with wildcards */ + switch (whatIs(pat)) { + case ASPAT : { Cell p = matchPat(snd(snd(pat))); + return (p==WILDCARD) ? fst(snd(pat)) + : ap(ASPAT, + pair(fst(snd(pat)),p)); + } + + case FINLIST : { Cell ys = snd(pat); + Cell xs = NIL; + for (; nonNull(ys); ys=tl(ys)) + xs = cons(matchPat(hd(ys)),xs); + while (nonNull(xs) && hd(xs)==WILDCARD) + xs = tl(xs); + for (ys=nameNil; nonNull(xs); xs=tl(xs)) + ys = ap(ap(nameCons,hd(xs)),ys); + return ys; + } + + case CONFLDS : { Cell ps = NIL; + Name c = fst(snd(pat)); + Cell fs = snd(snd(pat)); + Bool avar = FALSE; + for (; nonNull(fs); fs=tl(fs)) { + Cell p = matchPat(snd(hd(fs))); + ps = cons(pair(fst(hd(fs)),p),ps); + if (p!=WILDCARD) + avar = TRUE; + } + return avar ? pair(CONFLDS,pair(c,rev(ps))) + : WILDCARD; + } + + case VAROPCELL : + case VARIDCELL : + case DICTVAR : return pat; + + case LAZYPAT : { Cell p = matchPat(snd(pat)); + return (p==WILDCARD) ? WILDCARD : ap(LAZYPAT,p); + } + + case WILDCARD : + case STRCELL : + case CHARCELL : return WILDCARD; + + case TUPLE : + case NAME : + case AP : { Cell h = getHead(pat); + if (h==nameFromInt || + h==nameFromInteger || h==nameFromDouble) + return WILDCARD; +#if NPLUSK + else if (whatIs(h)==ADDPAT) + return pat; +#endif +#if TREX + else if (isExt(h)) { + Cell pf = matchPat(extField(pat)); + Cell pr = matchPat(extRow(pat)); + return (pf==WILDCARD && pr==WILDCARD) + ? WILDCARD + : ap(ap(fun(fun(pat)),pf),pr); + } +#endif + else { + List args = NIL; + Bool avar = FALSE; + for (; isAp(pat); pat=fun(pat)) { + Cell p = matchPat(arg(pat)); + if (p!=WILDCARD) + avar = TRUE; + args = cons(p,args); + } + return avar ? applyToArgs(pat,args) + : WILDCARD; + } + } + + default : internal("matchPat"); + return NIL; /*NOTREACHED*/ + } +} + +#define addEqn(v,val,lds) cons(pair(v,singleton(pair(NIL,val))),lds) + +static List local remPat(pat,expr,lds) +Cell pat; /* Produce list of definitions for eqn */ +Cell expr; /* pat = expr, including a conformality */ +List lds; { /* check if required. */ + + /* Conformality test (if required): + * pat = expr ==> nv = LETREC confCheck nv@pat = nv + * IN confCheck expr + * remPat1(pat,nv,.....); + */ + + if (!failFree(pat)) { + Cell confVar = inventVar(); + Cell nv = inventVar(); + Cell locfun = pair(confVar, /* confVar [([nv@refPat],nv)] */ + singleton(pair(singleton(ap(ASPAT, + pair(nv, + refutePat(pat)))), + nv))); + + if (whatIs(expr)==GUARDED) { /* A spanner ... special case */ + lds = addEqn(nv,expr,lds); /* for guarded pattern binding*/ + expr = nv; + nv = inventVar(); + } + + if (whatIs(pat)==ASPAT) { /* avoid using new variable if*/ + nv = fst(snd(pat)); /* a variable is already given*/ + pat = snd(snd(pat)); /* by an as-pattern */ + } + + lds = addEqn(nv, /* nv = */ + ap(LETREC,pair(singleton(locfun), /* LETREC [locfun] */ + ap(confVar,expr))), /* IN confVar expr */ + lds); + + return remPat1(matchPat(pat),nv,lds); + } + + return remPat1(matchPat(pat),expr,lds); +} + +static List local remPat1(pat,expr,lds) +Cell pat; /* Add definitions for: pat = expr to */ +Cell expr; /* list of local definitions in lds. */ +List lds; { + Cell c = getHead(pat); + + switch (whatIs(c)) { + case WILDCARD : + case STRCELL : + case CHARCELL : break; + + case ASPAT : return remPat1(snd(snd(pat)), /* v@pat = expr */ + fst(snd(pat)), + addEqn(fst(snd(pat)),expr,lds)); + + case LAZYPAT : { Cell nv; + + if (isVar(expr) || isName(expr)) + nv = expr; + else { + nv = inventVar(); + lds = addEqn(nv,expr,lds); + } + + return remPat(snd(pat),nv,lds); + } + +#if NPLUSK + case ADDPAT : return remPat1(arg(pat), /* n + k = expr */ + ap(ap(ap(namePmSub, + arg(fun(pat))), + mkInt(snd(fun(fun(pat))))), + expr), + lds); +#endif + + case FINLIST : return remPat1(mkConsList(snd(pat)),expr,lds); + + case CONFLDS : { Name h = fst(snd(pat)); + Int m = name(h).arity; + Cell p = h; + List fs = snd(snd(pat)); + Int i = m; + while (0<i--) + p = ap(p,WILDCARD); + for (; nonNull(fs); fs=tl(fs)) { + Cell r = p; + for (i=m-sfunPos(fst(hd(fs)),h); i>0; i--) + r = fun(r); + arg(r) = snd(hd(fs)); + } + return remPat1(p,expr,lds); + } + + case DICTVAR : /* shouldn't really occur */ + assert(0); /* so let's test for it then! ADR */ + case VARIDCELL : + case VAROPCELL : return addEqn(pat,expr,lds); + + case NAME : if (c==nameFromInt || c==nameFromInteger + || c==nameFromDouble) { + if (argCount==2) + arg(fun(pat)) = translate(arg(fun(pat))); + break; + } + + if (argCount==1 && isCfun(c) /* for newtype */ + && cfunOf(c)==0 && name(c).defn==nameId) + return remPat1(arg(pat),expr,lds); + + /* intentional fall-thru */ + case TUPLE : { List ps = getArgs(pat); + + if (nonNull(ps)) { + Cell nv, sel; + Int i; + + if (isVar(expr) || isName(expr)) + nv = expr; + else { + nv = inventVar(); + lds = addEqn(nv,expr,lds); + } + + sel = ap(ap(nameSel,c),nv); + for (i=1; nonNull(ps); ++i, ps=tl(ps)) + lds = remPat1(hd(ps), + ap(sel,mkInt(i)), + lds); + } + } + break; + +#if TREX + case EXT : { Cell nv = inventVar(); + arg(fun(fun(pat))) + = translate(arg(fun(fun(pat)))); + lds = addEqn(nv, + ap(ap(nameRecBrk, + arg(fun(fun(pat)))), + expr), + lds); + lds = remPat1(extField(pat),ap(nameFst,nv),lds); + lds = remPat1(extRow(pat),ap(nameSnd,nv),lds); + } + break; +#endif + + default : internal("remPat1"); + break; + } + return lds; +} + +/* -------------------------------------------------------------------------- + * Eliminate pattern matching in function definitions -- pattern matching + * compiler: + * + * The original Gofer/Hugs pattern matching compiler was based on Wadler's + * algorithms described in `Implementation of functional programming + * languages'. That should still provide a good starting point for anyone + * wanting to understand this part of the system. However, the original + * algorithm has been generalized and restructured in order to implement + * new features added in Haskell 1.3. + * + * During the translation, in preparation for later stages of compilation, + * all local and bound variables are replaced by suitable offsets, and + * locally defined function symbols are given new names (which will + * eventually be their names when lifted to make top level definitions). + * ------------------------------------------------------------------------*/ + +static Offset freeBegin; /* only variables with offset <= freeBegin are of */ +static List freeVars; /* interest as `free' variables */ +static List freeFuns; /* List of `free' local functions */ + +static Cell local pmcTerm(co,sc,e) /* apply pattern matching compiler */ +Int co; /* co = current offset */ +List sc; /* sc = scope */ +Cell e; { /* e = expr to transform */ + switch (whatIs(e)) { + case GUARDED : map2Over(pmcPair,co,sc,snd(e)); + break; + + case LETREC : pmcLetrec(co,sc,snd(e)); + break; + + case VARIDCELL: + case VAROPCELL: + case DICTVAR : return pmcVar(sc,textOf(e)); + + case COND : return ap(COND,pmcTriple(co,sc,snd(e))); + + case AP : return pmcPair(co,sc,e); + +#if BIGNUMS + case POSNUM : + case ZERONUM : + case NEGNUM : +#endif +#if NPLUSK + case ADDPAT : +#endif +#if TREX + case EXT : +#endif + case TUPLE : + case NAME : + case CHARCELL : + case INTCELL : + case FLOATCELL: + case STRCELL : break; + + default : internal("pmcTerm"); + break; + } + return e; +} + +static Cell local pmcPair(co,sc,pr) /* apply pattern matching compiler */ +Int co; /* to a pair of exprs */ +List sc; +Pair pr; { + return pair(pmcTerm(co,sc,fst(pr)), + pmcTerm(co,sc,snd(pr))); +} + +static Cell local pmcTriple(co,sc,tr) /* apply pattern matching compiler */ +Int co; /* to a triple of exprs */ +List sc; +Triple tr; { + return triple(pmcTerm(co,sc,fst3(tr)), + pmcTerm(co,sc,snd3(tr)), + pmcTerm(co,sc,thd3(tr))); +} + +static Cell local pmcVar(sc,t) /* find translation of variable */ +List sc; /* in current scope */ +Text t; { + List xs; + Name n; + + for (xs=sc; nonNull(xs); xs=tl(xs)) { + Cell x = hd(xs); + if (t==textOf(fst(x))) { + if (isOffset(snd(x))) { /* local variable ... */ + if (snd(x)<=freeBegin && !cellIsMember(snd(x),freeVars)) + freeVars = cons(snd(x),freeVars); + return snd(x); + } + else { /* local function ... */ + if (!cellIsMember(snd(x),freeFuns)) + freeFuns = cons(snd(x),freeFuns); + return fst3(snd(x)); + } + } + } + + if (isNull(n=findName(t))) /* Lookup global name - the only way*/ + n = newName(t,currentName); /* this (should be able to happen) */ + /* is with new global var introduced*/ + /* after type check; e.g. remPat1 */ + return n; +} + +static Void local pmcLetrec(co,sc,e) /* apply pattern matching compiler */ +Int co; /* to LETREC, splitting decls into */ +List sc; /* two sections */ +Pair e; { + List fs = NIL; /* local function definitions */ + List vs = NIL; /* local variable definitions */ + List ds; + + for (ds=fst(e); nonNull(ds); ds=tl(ds)) { /* Split decls into two */ + Cell v = fst(hd(ds)); + Int arity = length(fst(hd(snd(hd(ds))))); + + if (arity==0) { /* Variable declaration */ + vs = cons(snd(hd(ds)),vs); + sc = cons(pair(v,mkOffset(++co)),sc); + } + else { /* Function declaration */ + fs = cons(triple(inventVar(),mkInt(arity),snd(hd(ds))),fs); + sc = cons(pair(v,hd(fs)),sc); + } + } + vs = rev(vs); /* Put declaration lists back in */ + fs = rev(fs); /* original order */ + fst(e) = pair(vs,fs); /* Store declaration lists */ + map2Over(pmcVarDef,co,sc,vs); /* Translate variable definitions */ + map2Proc(pmcFunDef,co,sc,fs); /* Translate function definitions */ + snd(e) = pmcTerm(co,sc,snd(e)); /* Translate LETREC body */ + freeFuns = diffList(freeFuns,fs); /* Delete any `freeFuns' bound in fs*/ +} + +static Cell local pmcVarDef(co,sc,vd) /* apply pattern matching compiler */ +Int co; /* to variable definition */ +List sc; +List vd; { /* vd :: [ ([], rhs) ] */ + Cell d = snd(hd(vd)); + if (nonNull(tl(vd)) && canFail(d)) + return ap(FATBAR,pair(pmcTerm(co,sc,d), + pmcVarDef(co,sc,tl(vd)))); + return pmcTerm(co,sc,d); +} + +static Void local pmcFunDef(co,sc,fd) /* apply pattern matching compiler */ +Int co; /* to function definition */ +List sc; +Triple fd; { /* fd :: (Var, Arity, [Alt]) */ + Offset saveFreeBegin = freeBegin; + List saveFreeVars = freeVars; + List saveFreeFuns = freeFuns; + Int arity = intOf(snd3(fd)); + Cell temp = altsMatch(co+1,arity,sc,thd3(fd)); + Cell xs; + + freeBegin = mkOffset(co); + freeVars = NIL; + freeFuns = NIL; + temp = match(co+arity,temp); + thd3(fd) = triple(freeVars,freeFuns,temp); + + for (xs=freeVars; nonNull(xs); xs=tl(xs)) + if (hd(xs)<=saveFreeBegin && !cellIsMember(hd(xs),saveFreeVars)) + saveFreeVars = cons(hd(xs),saveFreeVars); + + for (xs=freeFuns; nonNull(xs); xs=tl(xs)) + if (!cellIsMember(hd(xs),saveFreeFuns)) + saveFreeFuns = cons(hd(xs),saveFreeFuns); + + freeBegin = saveFreeBegin; + freeVars = saveFreeVars; + freeFuns = saveFreeFuns; +} + +/* --------------------------------------------------------------------------- + * Main part of pattern matching compiler: convert [Alt] to case constructs + * + * This section of Hugs has been almost completely rewritten to be more + * general, in particular, to allow pattern matching in orders other than the + * strictly left-to-right approach of the previous version. This is needed + * for the implementation of the so-called Haskell 1.3 `record' syntax. + * + * At each stage, the different branches for the cases to be considered + * are represented by a list of values of type: + * Match ::= { maPats :: [Pat], patterns to match + * maOffs :: [Offs], offsets of corresponding values + * maSc :: Scope, mapping from vars to offsets + * maRhs :: Rhs } right hand side + * [Implementation uses nested pairs, ((pats,offs),(sc,rhs)).] + * + * The Scope component has type: + * Scope ::= [(Var,Expr)] + * and provides a mapping from variable names to offsets used in the matching + * process. + * + * Matches can be normalized by reducing them to a form in which the list + * of patterns is empty (in which case the match itself is described as an + * empty match), or in which the list is non-empty and the first pattern is + * one that requires either a CASE or NUMCASE (or EXTCASE) to decompose. * ------------------------------------------------------------------------*/ -#include "stg.h" -#include "translate.h" -#include "codegen.h" +#define mkMatch(ps,os,sc,r) pair(pair(ps,os),pair(sc,r)) +#define maPats(ma) fst(fst(ma)) +#define maOffs(ma) snd(fst(ma)) +#define maSc(ma) fst(snd(ma)) +#define maRhs(ma) snd(snd(ma)) +#define extSc(v,o,ma) maSc(ma) = cons(pair(v,o),maSc(ma)) + +static List local altsMatch(co,n,sc,as) /* Make a list of matches from list*/ +Int co; /* of Alts, with initial offsets */ +Int n; /* reverse (take n [co..]) */ +List sc; +List as; { + List mas = NIL; + List us = NIL; + for (; n>0; n--) + us = cons(mkOffset(co++),us); + for (; nonNull(as); as=tl(as)) /* Each Alt is ([Pat], Rhs) */ + mas = cons(mkMatch(fst(hd(as)),us,sc,snd(hd(as))),mas); + return rev(mas); +} + +static Cell local match(co,mas) /* Generate case statement for Matches mas */ +Int co; /* at current offset co */ +List mas; { /* N.B. Assumes nonNull(mas). */ + Cell srhs = NIL; /* Rhs for selected matches */ + List smas = mas; /* List of selected matches */ + mas = tl(mas); + tl(smas) = NIL; + + if (emptyMatch(hd(smas))) { /* The case for empty matches: */ + while (nonNull(mas) && emptyMatch(hd(mas))) { + List temp = tl(mas); + tl(mas) = smas; + smas = mas; + mas = temp; + } + srhs = joinMas(co,rev(smas)); + } + else { /* Non-empty match */ + Int o = offsetOf(hd(maOffs(hd(smas)))); + Cell d = maDiscr(hd(smas)); + if (isNumDiscr(d)) { /* Numeric match */ + Int da = discrArity(d); + Cell d1 = pmcTerm(co,maSc(hd(smas)),d); + while (nonNull(mas) && !emptyMatch(hd(mas)) + && o==offsetOf(hd(maOffs(hd(mas)))) + && isNumDiscr(d=maDiscr(hd(mas))) + && eqNumDiscr(d,d1)) { + List temp = tl(mas); + tl(mas) = smas; + smas = mas; + mas = temp; + } + smas = rev(smas); + map2Proc(advance,co,da,smas); + srhs = ap(NUMCASE,triple(mkOffset(o),d1,match(co+da,smas))); + } +#if TREX + else if (isExtDiscr(d)) { /* Record match */ + Int da = discrArity(d); + Cell d1 = pmcTerm(co,maSc(hd(smas)),d); + while (nonNull(mas) && !emptyMatch(hd(mas)) + && o==offsetOf(hd(maOffs(hd(mas)))) + && isExtDiscr(d=maDiscr(hd(mas))) + && eqExtDiscr(d,d1)) { + List temp = tl(mas); + tl(mas) = smas; + smas = mas; + mas = temp; + } + smas = rev(smas); + map2Proc(advance,co,da,smas); + srhs = ap(EXTCASE,triple(mkOffset(o),d1,match(co+da,smas))); + } +#endif + else { /* Constructor match */ + List tab = addConTable(d,hd(smas),NIL); + Int da; + while (nonNull(mas) && !emptyMatch(hd(mas)) + && o==offsetOf(hd(maOffs(hd(mas)))) + && !isNumDiscr(d=maDiscr(hd(mas)))) { + tab = addConTable(d,hd(mas),tab); + mas = tl(mas); + } + for (tab=rev(tab); nonNull(tab); tab=tl(tab)) { + d = fst(hd(tab)); + smas = snd(hd(tab)); + da = discrArity(d); + map2Proc(advance,co,da,smas); + srhs = cons(pair(d,match(co+da,smas)),srhs); + } + srhs = ap(CASE,pair(mkOffset(o),srhs)); + } + } + return nonNull(mas) ? ap(FATBAR,pair(srhs,match(co,mas))) : srhs; +} + +static Cell local joinMas(co,mas) /* Combine list of matches into rhs*/ +Int co; /* using FATBARs as necessary */ +List mas; { /* Non-empty list of empty matches */ + Cell ma = hd(mas); + Cell rhs = pmcTerm(co,maSc(ma),maRhs(ma)); + if (nonNull(tl(mas)) && canFail(rhs)) + return ap(FATBAR,pair(rhs,joinMas(co,tl(mas)))); + else + return rhs; +} + +static Bool local canFail(rhs) /* Determine if expression (as rhs) */ +Cell rhs; { /* might ever be able to fail */ + switch (whatIs(rhs)) { + case LETREC : return canFail(snd(snd(rhs))); + case GUARDED : return TRUE; /* could get more sophisticated ..? */ + default : return FALSE; + } +} + +/* type Table a b = [(a, [b])] + * + * addTable :: a -> b -> Table a b -> Table a b + * addTable x y [] = [(x,[y])] + * addTable x y (z@(n,sws):zs) + * | n == x = (n,sws++[y]):zs + * | otherwise = (n,sws):addTable x y zs + */ + +static List local addConTable(x,y,tab) /* add element (x,y) to table */ +Cell x, y; +List tab; { + if (isNull(tab)) + return singleton(pair(x,singleton(y))); + else if (fst(hd(tab))==x) + snd(hd(tab)) = appendOnto(snd(hd(tab)),singleton(y)); + else + tl(tab) = addConTable(x,y,tl(tab)); + + return tab; +} + +static Void local advance(co,a,ma) /* Advance non-empty match by */ +Int co; /* processing head pattern */ +Int a; /* discriminator arity */ +Cell ma; { + Cell p = hd(maPats(ma)); + List ps = tl(maPats(ma)); + List us = tl(maOffs(ma)); + if (whatIs(p)==CONFLDS) { /* Special case for record syntax */ + Name c = fst(snd(p)); + List fs = snd(snd(p)); + List qs = NIL; + List vs = NIL; + for (; nonNull(fs); fs=tl(fs)) { + vs = cons(mkOffset(co+a+1-sfunPos(fst(hd(fs)),c)),vs); + qs = cons(snd(hd(fs)),qs); + } + ps = revOnto(qs,ps); + us = revOnto(vs,us); + } + else /* Normally just spool off patterns*/ + for (; a>0; --a) { /* and corresponding offsets ... */ + us = cons(mkOffset(++co),us); + ps = cons(arg(p),ps); + p = fun(p); + } + + maPats(ma) = ps; + maOffs(ma) = us; +} + +/* -------------------------------------------------------------------------- + * Normalize and test for empty match: + * ------------------------------------------------------------------------*/ + +static Bool local emptyMatch(ma)/* Normalize and test to see if a given */ +Cell ma; { /* match, ma, is empty. */ + + while (nonNull(maPats(ma))) { + Cell p; +tidyHd: switch (whatIs(p=hd(maPats(ma)))) { + case LAZYPAT : { Cell nv = inventVar(); + maRhs(ma) = ap(LETREC, + pair(remPat(snd(p),nv,NIL), + maRhs(ma))); + p = nv; + } + /* intentional fall-thru */ + case VARIDCELL : + case VAROPCELL : + case DICTVAR : extSc(p,hd(maOffs(ma)),ma); + case WILDCARD : maPats(ma) = tl(maPats(ma)); + maOffs(ma) = tl(maOffs(ma)); + continue; + + /* So-called "as-patterns"are really just pattern intersections: + * (p1@p2:ps, o:os, sc, e) ==> (p1:p2:ps, o:o:os, sc, e) + * (But the input grammar probably doesn't let us take + * advantage of this, so we stick with the special case + * when p1 is a variable.) + */ + case ASPAT : extSc(fst(snd(p)),hd(maOffs(ma)),ma); + hd(maPats(ma)) = snd(snd(p)); + goto tidyHd; + + case FINLIST : hd(maPats(ma)) = mkConsList(snd(p)); + return FALSE; + + case STRCELL : { String s = textToStr(textOf(p)); + for (p=NIL; *s!='\0'; ++s) + if (*s!='\\' || *++s=='\\') + p = ap(consChar(*s),p); + else + p = ap(consChar('\0'),p); + hd(maPats(ma)) = revOnto(p,nameNil); + } + return FALSE; + + case AP : if (isName(fun(p)) && isCfun(fun(p)) + && cfunOf(fun(p))==0 + && name(fun(p)).defn==nameId) { + hd(maPats(ma)) = arg(p); + goto tidyHd; + } + /* intentional fall-thru */ + case CHARCELL : + case NAME : + case CONFLDS : + return FALSE; + + default : internal("emptyMatch"); + } + } + return TRUE; +} + +/* -------------------------------------------------------------------------- + * Discriminators: + * ------------------------------------------------------------------------*/ + +static Cell local maDiscr(ma) /* Get the discriminator for a non-empty */ +Cell ma; { /* match, ma. */ + Cell p = hd(maPats(ma)); + Cell h = getHead(p); + switch (whatIs(h)) { + case CONFLDS : return fst(snd(p)); +#if NPLUSK + case ADDPAT : arg(fun(p)) = translate(arg(fun(p))); + return fun(p); +#endif +#if TREX + case EXT : h = fun(fun(p)); + arg(h) = translate(arg(h)); + return h; +#endif + case NAME : if (h==nameFromInt || h==nameFromInteger + || h==nameFromDouble) { + if (argCount==2) + arg(fun(p)) = translate(arg(fun(p))); + return p; + } + } + return h; +} + +static Bool local isNumDiscr(d) /* TRUE => numeric discriminator */ +Cell d; { + switch (whatIs(d)) { + case NAME : + case TUPLE : + case CHARCELL : return FALSE; + +#if TREX + case AP : return !isExt(fun(d)); +#else + case AP : return TRUE; /* must be a literal or (n+k) */ +#endif + } + internal("isNumDiscr"); + return 0;/*NOTREACHED*/ +} + +Int discrArity(d) /* Find arity of discriminator */ +Cell d; { + switch (whatIs(d)) { + case NAME : return name(d).arity; + case TUPLE : return tupleOf(d); + case CHARCELL : return 0; +#if TREX + case AP : switch (whatIs(fun(d))) { +#if NPLUSK + case ADDPAT : return 1; +#endif + case EXT : return 2; + default : return 0; + } +#else +#if NPLUSK + case AP : return (whatIs(fun(d))==ADDPAT) ? 1 : 0; +#else + case AP : return 0; /* must be an Int or Float lit */ +#endif +#endif + } + internal("discrArity"); + return 0;/*NOTREACHED*/ +} + +static Bool local eqNumDiscr(d1,d2) /* Determine whether two numeric */ +Cell d1, d2; { /* descriptors have same value */ +#if NPLUSK + if (whatIs(fun(d1))==ADDPAT) + return whatIs(fun(d2))==ADDPAT && snd(fun(d1))==snd(fun(d2)); +#endif + if (isInt(arg(d1))) + return isInt(arg(d2)) && intOf(arg(d1))==intOf(arg(d2)); + if (isFloat(arg(d1))) + return isFloat(arg(d2)) && floatOf(arg(d1))==floatOf(arg(d2)); +#if BIGNUMS + if (isBignum(arg(d1))) + return isBignum(arg(d2)) && bigCmp(arg(d1),arg(d2))==0; +#endif + internal("eqNumDiscr"); + return FALSE;/*NOTREACHED*/ +} + +#if TREX +static Bool local isExtDiscr(d) /* Test of extension discriminator */ +Cell d; { + return isAp(d) && isExt(fun(d)); +} + +static Bool local eqExtDiscr(d1,d2) /* Determine whether two extension */ +Cell d1, d2; { /* discriminators have same label */ + return fun(d1)==fun(d2); +} +#endif + +/*-------------------------------------------------------------------------*/ + + + +/* -------------------------------------------------------------------------- + * STG stuff + * ------------------------------------------------------------------------*/ static Void local stgCGBinds( List ); @@ -74,28 +1481,12 @@ static List addGlobals( List binds ) return binds; } -#if 0 -/* This is a hack to see if "show [1..1000]" will go any faster if I - * code primShowInt in C - */ -char* prim_showInt(int x) -{ - char buffer[50]; - sprintf(buffer,"%d",x); - return buffer; -} - -void prim_flush_stdout(void) -{ - fflush(stdout); -} -#endif Void evalExp() { /* compile and run input expression */ /* ToDo: this name (and other names generated during pattern match?) * get inserted in the symbol table but never get removed. */ - Name n = newName(inventText()); + Name n = newName(inventText(),NIL); StgVar v = mkStgVar(NIL,NIL); name(n).stgVar = v; compiler(RESET); @@ -108,6 +1499,7 @@ Void evalExp() { /* compile and run input expression */ /* Re-initialise the scheduler - ToDo: do I need this? */ initScheduler(); + /* ToDo: don't really initScheduler every time. fix */ { HaskellObj result; /* ignored */ SchedulerStatus status = rts_eval_(closureOfVar(v),10000,&result); @@ -145,7 +1537,7 @@ static List local addStgVar( List binds, Pair bind ) Name n = findName(t); if (isNull(n)) { /* Lookup global name - the only way*/ - n = newName(t); /* this (should be able to happen) */ + n = newName(t,NIL); /* this (should be able to happen) */ } /* is with new global var introduced*/ /* after type check; e.g. remPat1 */ name(n).stgVar = nv; @@ -223,6 +1615,7 @@ Name n; { /* generated function */ Int arity = length(fst(hd(defs))); compiler(RESET); + currentName = n; mapProc(transAlt,defs); stgDefn(n,arity,match(arity,altsMatch(1,arity,NIL,defs))); name(n).defn = NIL; @@ -240,6 +1633,33 @@ Pair p; { /* Should be merged with genDefns, */ return s; } + +#if 0 +I think this is 98-specific. +static Void local newGlobalFunction(n,arity,fvs,co,e) +Name n; +Int arity; +List fvs; +Int co; +Cell e; { +#ifdef DEBUG_SHOWSC + extern Void printSc Args((FILE*, Text, Int, Cell)); +#endif + extraVars = fvs; + numExtraVars = length(extraVars); + localOffset = co; + localArity = arity; + name(n).arity = arity+numExtraVars; + e = preComp(e); +#ifdef DEBUG_SHOWSC + if (debugCode) { + printSc(stdout,name(n).text,name(n).arity,e); + } +#endif + name(n).code = codeGen(n,name(n).arity,e); +} +#endif + /* -------------------------------------------------------------------------- * Compiler control: * ------------------------------------------------------------------------*/ @@ -248,8 +1668,19 @@ Void compiler(what) Int what; { switch (what) { case INSTALL : - case RESET : break; - case MARK : break; + case RESET : freeVars = NIL; + freeFuns = NIL; + freeBegin = mkOffset(0); + //extraVars = NIL; + //numExtraVars = 0; + //localOffset = 0; + //localArity = 0; + break; + + case MARK : mark(freeVars); + mark(freeFuns); + //mark(extraVars); + break; } } diff --git a/ghc/interpreter/connect.h b/ghc/interpreter/connect.h index b80ebfd6d442..2f3ccc6de5f5 100644 --- a/ghc/interpreter/connect.h +++ b/ghc/interpreter/connect.h @@ -1,45 +1,534 @@ -/* -*- mode: hugs-c; -*- */ /* -------------------------------------------------------------------------- * Connections between components of the Hugs system * - * Copyright (c) The University of Nottingham and Yale University, 1994-1997. - * All rights reserved. See NOTICE for details and conditions of use etc... - * Hugs version 1.4, December 1997 + * Hugs 98 is Copyright (c) Mark P Jones, Alastair Reid and the Yale + * Haskell Group 1994-99, and is distributed as Open Source software + * under the Artistic License; see the file "Artistic" that is included + * in the distribution for details. * * $RCSfile: connect.h,v $ - * $Revision: 1.2 $ - * $Date: 1998/12/02 13:22:03 $ + * $Revision: 1.3 $ + * $Date: 1999/02/03 17:08:27 $ * ------------------------------------------------------------------------*/ /* -------------------------------------------------------------------------- * Standard data: * ------------------------------------------------------------------------*/ +extern Bool haskell98; /* TRUE => Haskell 98 compatibility*/ +extern Module modulePrelude; +extern Module modulePreludeHugs; + +/* -------------------------------------------------------------------------- + * Primitive constructor functions + * ------------------------------------------------------------------------*/ + +extern Name nameFalse, nameTrue; +extern Name nameNil, nameCons; +extern Name nameJust, nameNothing; +extern Name nameLeft, nameRight; +extern Name nameUnit; + +extern Name nameLT, nameEQ; +extern Name nameGT; +extern Name nameFst, nameSnd; /* standard combinators */ +extern Name nameId, nameOtherwise; +extern Name nameNegate, nameFlip; /* primitives reqd for parsing */ +extern Name nameFrom, nameFromThen; +extern Name nameFromTo, nameFromThenTo; +extern Name nameFatbar, nameFail; /* primitives reqd for translation */ +extern Name nameIf, nameSel; +extern Name nameCompAux; +extern Name namePmInt, namePmFlt; /* primitives for pattern matching */ +extern Name namePmInteger; +#if NPLUSK +extern Name namePmNpk, namePmSub; /* primitives for (n+k) patterns */ +#endif +extern Name nameError; /* For runtime error messages */ +extern Name nameUndefined; /* A generic undefined value */ +extern Name nameBlackHole; /* For GC-detected black hole */ +extern Name nameInd; /* For dict indirection */ +extern Name nameAnd, nameOr; /* For optimisation of && and || */ +extern Name nameFromInt, nameFromDouble;/*coercion of numerics */ +extern Name nameFromInteger; +extern Name nameEq, nameCompare; /* names used for deriving */ +extern Name nameMinBnd, nameMaxBnd; +extern Name nameIndex, nameInRange; +extern Name nameRange; +extern Name nameLe, nameGt; +extern Name nameShowsPrec, nameReadsPrec; +extern Name nameMult, namePlus; +extern Name nameConCmp, nameEnRange; +extern Name nameEnIndex, nameEnInRng; +extern Name nameEnToEn, nameEnFrEn; +extern Name nameEnFrom, nameEnFrTh; +extern Name nameEnFrTo; +extern Name nameComp, nameApp; /* composition and append */ +extern Name nameShowField; /* display single field */ +extern Name nameShowParen; /* wrap with parens */ +extern Name nameReadField; /* read single field */ +extern Name nameReadParen; /* unwrap from parens */ +extern Name nameLex; /* lexer */ +extern Name nameRangeSize; /* calculate size of index range */ +extern Class classMonad; /* Monads */ +extern Name nameReturn, nameBind; /* for translating monad comps */ +extern Name nameMFail; +extern Name nameListMonad; /* builder function for List Monad */ + +#if EVAL_INSTANCES +extern Name nameStrict, nameSeq; /* Members of class Eval */ +extern Name nameIStrict, nameISeq; /* ... and their implementations */ +#endif + +extern Name namePrint; /* printing primitive */ + +#if IO_MONAD +extern Type typeProgIO; /* For the IO monad, IO () */ +extern Name nameIORun; /* IO monad executor */ +extern Name namePutStr; /* Prelude.putStr */ +extern Name nameUserErr; /* primitives required for IOError */ +extern Name nameNameErr, nameSearchErr; +#endif + +#if IO_HANDLES +extern Name nameWriteErr, nameIllegal;/* primitives required for IOError */ +extern Name nameEOFErr; +#endif + +extern Text textPrelude; +extern Text textNum; /* used to process default decls */ +#if NPLUSK +extern Text textPlus; /* Used to recognise n+k patterns */ +#endif +#if TREX +extern Name nameNoRec; /* The empty record */ +extern Type typeNoRow; /* The empty row */ +extern Type typeRec; /* Record formation */ +extern Kind extKind; /* Kind of extension, *->row->row */ +extern Name nameRecExt; /* Extend a record */ +extern Name nameRecBrk; /* Break a record */ +extern Name nameAddEv; /* Addition of evidence values */ +extern Name nameRecSel; /* Select a record */ +extern Name nameRecShw; /* Show a record */ +extern Name nameShowRecRow; /* Used to output rows */ +extern Name nameRecEq; /* Compare records */ +extern Name nameEqRecRow; /* Used to compare rows */ +extern Name nameInsFld; /* Field insertion routine */ +#endif + +extern String repeatStr; /* Repeat last command string */ +extern String hugsEdit; /* String for editor command */ +extern String hugsPath; /* String for file search path */ +extern String projectPath; /* String for project search path */ + +extern Type typeArrow; /* Builtin type constructors */ +extern Type typeList; +extern Type typeUnit; + +#define fn(from,to) ap(ap(typeArrow,from),to) /* make type: from -> to */ + +extern List stdDefaults; /* List of standard default types */ + +extern Class classEq; /* `standard' classes */ +extern Class classOrd; +extern Class classShow; +extern Class classRead; +extern Class classIx; +extern Class classEnum; +#if EVAL_INSTANCES +extern Class classEval; +#endif +extern Class classBounded; + +extern Class classReal; /* `numeric' classes */ +extern Class classIntegral; +extern Class classRealFrac; +extern Class classRealFloat; +extern Class classFractional; +extern Class classFloating; +extern Class classNum; + +extern Cell *CStackBase; /* pointer to base of C stack */ + +extern List tyconDefns; /* list of type constructor defns */ +extern List typeInDefns; /* list of synonym restrictions */ +extern List valDefns; /* list of value definitions */ +extern List classDefns; /* list of class definitions */ +extern List instDefns; /* list of instance definitions */ +extern List selDefns; /* list of selector lists */ +extern List genDefns; /* list of generated defns */ +extern List primDefns; /* list of primitive definitions */ +extern List unqualImports; /* unqualified import list */ +extern List defaultDefns; /* default definitions (if any) */ +extern Int defaultLine; /* line in which default defs occur*/ +extern List evalDefaults; /* defaults for evaluator */ +extern Cell inputExpr; /* evaluator input expression */ +extern Addr inputCode; /* Code for compiled input expr */ + +extern Int whnfArgs; /* number of args of term in whnf */ +extern Cell whnfHead; /* head of term in whnf */ +extern Int whnfInt; /* integer value of term in whnf */ +extern Float whnfFloat; /* float value of term in whnf */ +/*ToDo?? extern Long numReductions;*/ /* number of reductions used */ +extern Long numCells; /* number of cells allocated */ +extern Int numGcs; /* number of garbage collections */ +extern Bool broken; /* indicates interrupt received */ +/*ToDo?? extern Bool preludeLoaded;*/ /* TRUE => prelude has been loaded */ + +extern Bool gcMessages; /* TRUE => print GC messages */ +extern Bool literateScripts; /* TRUE => default lit scripts */ +extern Bool literateErrors; /* TRUE => report errs in lit scrs */ +/*ToDo?? extern Bool failOnError;*/ /* TRUE => error produces immediate*/ + /* termination */ + +extern Int cutoff; /* Constraint Cutoff depth */ + +#if USE_PREPROCESSOR +extern String preprocessor; /* preprocessor command */ +#endif + +#if DEBUG_CODE +extern Bool debugCode; /* TRUE => print G-code to screen */ +#endif +extern Bool kindExpert; /* TRUE => display kind errors in */ + /* full detail */ +extern Bool allowOverlap; /* TRUE => allow overlapping insts */ + /* -------------------------------------------------------------------------- * Function prototypes etc... * ------------------------------------------------------------------------*/ +extern Void everybody Args((Int)); + #define RESET 1 /* reset subsystem */ #define MARK 2 /* mark parts of graph in use by subsystem */ #define INSTALL 3 /* install subsystem (executed once only) */ #define EXIT 4 /* Take action immediately before exit() */ #define BREAK 5 /* Take action after program break */ -extern Void everybody Args((Int)); -extern Void machdep Args((Int)); +typedef long Target; +extern Void setGoal Args((String, Target)); +extern Void soFar Args((Target)); +extern Void done Args((Void)); +extern String fromEnv Args((String,String)); +extern Bool chase Args((List)); + extern Void storage Args((Int)); -extern Void linkControl Args((Int)); -extern Void translateControl Args((Int)); -extern Void staticAnalysis Args((Int)); -extern Void interface Args((Int)); -extern Void deriveControl Args((Int)); + extern Void input Args((Int)); +extern Void consoleInput Args((String)); +extern Void projInput Args((String)); +extern Void stringInput Args((String)); +extern Void parseScript Args((String,Long)); +extern Void parseExp Args((Void)); +extern String readFilename Args((Void)); +extern String readLine Args((Void)); +extern Syntax defaultSyntax Args((Text)); +extern Syntax syntaxOf Args((Name)); +extern String unlexChar Args((Char,Char)); +extern Void printString Args((String)); + +extern Void substitution Args((Int)); + +extern Void staticAnalysis Args((Int)); +#if IGNORE_MODULES +#define startModule(m) doNothing() +#define setExportList(l) doNothing() +#define setExports(l) doNothing() +#define addQualImport(m,as) doNothing() +#define addUnqualImport(m,l) doNothing() +#else +extern Void startModule Args((Cell)); +extern Void setExportList Args((List)); +extern Void setExports Args((List)); +extern Void addQualImport Args((Text,Text)); +extern Void addUnqualImport Args((Text,List)); +#endif +extern Void tyconDefn Args((Int,Cell,Cell,Cell)); +extern Void setTypeIns Args((List)); +extern Void clearTypeIns Args((Void)); +extern Type fullExpand Args((Type)); +extern Bool isAmbiguous Args((Type)); +extern Void ambigError Args((Int,String,Cell,Type)); +extern Void classDefn Args((Int,Cell,Cell)); +extern Void instDefn Args((Int,Cell,Cell)); +extern Void addTupInst Args((Class,Int)); +#if EVAL_INSTANCES +extern Void addEvalInst Args((Int,Cell,Int,List)); +#endif +#if TREX +extern Inst addRecShowInst Args((Class,Ext)); +extern Inst addRecEqInst Args((Class,Ext)); +#endif +extern Void primDefn Args((Cell,List,Cell)); +extern Void defaultDefn Args((Int,List)); +extern Void checkExp Args((Void)); +extern Void checkDefns Args((Void)); +extern Bool h98Pred Args((Bool,Cell)); +extern Cell h98Context Args((Bool,List)); +extern Void h98CheckCtxt Args((Int,String,Bool,List,Inst)); +extern Void h98CheckType Args((Int,String,Cell,Type)); +extern Void h98DoesntSupport Args((Int,String)); + extern Void typeChecker Args((Int)); -extern Void desugarControl Args((Int)); -extern Void codegen Args((Int)); +extern Type typeCheckExp Args((Bool)); +extern Void typeCheckDefns Args((Void)); +extern Cell provePred Args((Kinds,List,Cell)); +extern List simpleContext Args((List,Int)); +extern Cell rhsExpr Args((Cell)); +extern Int rhsLine Args((Cell)); +extern Bool isProgType Args((List,Type)); +extern Cell superEvid Args((Cell,Class,Class)); +extern Void linkPreludeTC Args((Void)); +extern Void linkPreludeCM Args((Void)); + extern Void compiler Args((Int)); -extern Void substitution Args((Int)); -extern Void stgTranslate Args((Int)); -extern Void codegen Args((Int)); +extern Void compileDefns Args((Void)); +extern Void compileExp Args((Void)); +extern Bool failFree Args((Cell)); +extern Int discrArity Args((Cell)); + +extern Addr codeGen Args((Name,Int,Cell)); +extern Void implementCfun Args((Name,List)); +#if TREX +extern Name implementRecShw Args((Text,Cell)); +extern Name implementRecEq Args((Text,Cell)); +#endif +extern Void addCfunTable Args((Tycon)); +extern Name succCfun Args((Name)); +extern Name nextCfun Args((Name,Name)); +extern Name cfunByNum Args((Name,Int)); +extern Void unwind Args((Cell)); +extern Void run Args((Addr,StackPtr)); + +extern Void eval Args((Cell)); +extern Cell evalWithNoError Args((Cell)); +extern Void evalFails Args((StackPtr)); + +#if BYTECODE_PRIMS +extern Int IntAt Args((Addr)); +#if !BREAK_FLOATS +extern Float FloatAt Args((Addr)); +#endif +extern Cell CellAt Args((Addr)); +extern Text TextAt Args((Addr)); +extern Addr AddrAt Args((Addr)); +extern Int InstrAt Args((Addr)); +#endif /* BYTECODE_PRIMS */ + +extern Void abandon Args((String,Cell)); +extern Void outputString Args((FILE *)); +extern Void dialogue Args((Cell)); +#define consChar(c) ap(conCons,mkChar(c)) + +#if BIGNUMS +extern Bignum bigInt Args((Int)); +extern Bignum bigDouble Args((double)); +extern Bignum bigNeg Args((Bignum)); +extern Cell bigToInt Args((Bignum)); +extern Cell bigToFloat Args((Bignum)); +extern Bignum bigStr Args((String)); +extern Cell bigOut Args((Bignum,Cell,Bool)); +extern Bignum bigShift Args((Bignum,Int,Int)); +extern Int bigCmp Args((Bignum,Bignum)); +#endif +#if IO_MONAD +extern Void setHugsArgs Args((Int,String[])); +#endif + +#if PROFILING +extern String timeString Args((Void)); +#endif + +extern Int shellEsc Args((String)); +extern Int getTerminalWidth Args((Void)); +extern Void normalTerminal Args((Void)); +extern Void noechoTerminal Args((Void)); +extern Int readTerminalChar Args((Void)); +extern Void gcStarted Args((Void)); +extern Void gcScanning Args((Void)); +extern Void gcRecovered Args((Int)); +extern Void gcCStack Args((Void)); +extern Void needPrims Args((Int)); + +extern Type primType( Int /*AsmMonad*/ monad, String a_kinds, String r_kinds ); +#define aVar mkOffset(0) /* Simple skeleton for type var */ + +/*-------------------------------------------------------------------------*/ + +/*--------------------------------------------------------------------------- + * Interrupting execution (signals, allowBreak): + *-------------------------------------------------------------------------*/ + +extern Bool breakOn Args((Bool)); + +extern Bool broken; /* indicates interrupt received */ + +#ifndef SIGBREAK /* Sigh, not defined in cygwin32 beta release 16 */ +# define SIGBREAK 21 +#endif + +/* allowBreak: call to allow user to interrupt computation + * ctrlbrk: set control break handler + */ + +#if HUGS_FOR_WINDOWS +# define ctrlbrk(bh) +# define allowBreak() kbhit() +#else /* !HUGS_FOR_WINDOWS */ +# define ctrlbrk(bh) signal(SIGINT,bh); signal(SIGBREAK,bh) +# define allowBreak() if (broken) { broken=FALSE; sigRaise(breakHandler); } +#endif /* !HUGS_FOR_WINDOWS */ + +/*--------------------------------------------------------------------------- + * Environment variables and the registry + *-------------------------------------------------------------------------*/ + +/* On Win32 we can use the registry to supplement info in environment + * variables. + */ +#define USE_REGISTRY (HAVE_WINDOWS_H && !__MSDOS__) + +#ifdef USE_REGISTRY +Bool writeRegString Args((String var, String val)); +String readRegString Args((String var, String def)); +Int readRegInt Args((String var, Int def)); +Bool writeRegInt Args((String var, Int val)); +#endif + +/*--------------------------------------------------------------------------- + * File operations: + *-------------------------------------------------------------------------*/ + +#if HAVE_UNISTD_H +# include <sys/types.h> +# include <unistd.h> +#elif !HUGS_FOR_WINDOWS +extern int chdir Args((const char*)); +#endif + +#if HAVE_STDLIB_H +# include <stdlib.h> +#else +extern int system Args((const char *)); +extern double atof Args((const char *)); +extern void exit Args((int)); +#endif + +#ifndef FILENAME_MAX /* should already be defined in an ANSI compiler*/ +#define FILENAME_MAX 256 +#else +#if FILENAME_MAX < 256 +#undef FILENAME_MAX +#define FILENAME_MAX 256 +#endif +#endif + +/* Hack, hack: if you have dos.h, you probably have a DOS filesystem */ +#define DOS_FILENAMES HAVE_DOS_H +/* ToDo: can we replace this with a feature test? */ +#define MAC_FILENAMES SYMANTEC_C + +#define CASE_INSENSITIVE_FILENAMES (DOS_FILENAMES | RISCOS) + +#if CASE_INSENSITIVE_FILENAMES +# if HAVE_STRCASECMP +# define filenamecmp(s1,s2) strcasecmp(s1,s2) +# elif HAVE__STRICMP +# define filenamecmp(s1,s2) _stricmp(s1,s2) +# elif HAVE_STRICMP +# define filenamecmp(s1,s2) stricmp(s1,s2) +# elif HAVE_STRCMPI +# define filenamecmp(s1,s2) strcmpi(s1,s2) +# endif +#else +# define filenamecmp(s1,s2) strcmp(s1,s2) +#endif + +/*--------------------------------------------------------------------------- + * Pipe-related operations: + * + * On Windows, many standard Unix names acquire a leading underscore. + * Irritating, but easy to work around. + *-------------------------------------------------------------------------*/ + +#if !defined(HAVE_POPEN) && defined(HAVE__POPEN) +#define popen(x,y) _popen(x,y) +#endif +#if !defined(HAVE_PCLOSE) && defined(HAVE__PCLOSE) +#define pclose(x) _pclose(x) +#endif + +/*--------------------------------------------------------------------------- + * Bit manipulation: + *-------------------------------------------------------------------------*/ + +#define bitArraySize(n) ((n)/bitsPerWord + 1) +#define placeInSet(n) ((-(n)-1)>>wordShift) +#define maskInSet(n) (1<<((-(n)-1)&wordMask)) + +/*--------------------------------------------------------------------------- + * Function prototypes for code in machdep.c + *-------------------------------------------------------------------------*/ + +extern String findMPathname Args((String,String,String)); +extern String findPathname Args((String,String)); + +extern Int shellEsc Args((String)); +extern Int getTerminalWidth Args((Void)); +extern Void normalTerminal Args((Void)); +extern Void noechoTerminal Args((Void)); +extern Int readTerminalChar Args((Void)); +extern Void gcStarted Args((Void)); +extern Void gcScanning Args((Void)); +extern Void gcRecovered Args((Int)); +extern Void gcCStack Args((Void)); /*-------------------------------------------------------------------------*/ + +extern Type typeInt64; +extern Type typeWord; +extern Type typeFloat; +extern Type typePrimArray; +extern Type typePrimByteArray; +extern Type typeRef; +extern Type typePrimMutableArray; +extern Type typePrimMutableByteArray; +extern Type typeStable; +extern Type typeWeak; +extern Type typeIO; +extern Type typeForeign; +extern Type typeMVar; +extern Type typeThreadId; +extern Type typeException; +extern Type typeIO; +extern Type typeST; + +extern Void foreignImport Args((Cell,Pair,Cell,Cell)); +extern List foreignImports; /* foreign import declarations */ +extern Void implementForeignImport Args((Name)); +extern Void foreignExport Args((Cell,Cell,Cell,Cell)); +extern List foreignExports; /* foreign export declarations */ +extern Void implementForeignExport Args((Name)); + +extern List diVars; +extern Int diNum; + +Int userArity Args((Name)); + + +extern List deriveEq Args((Tycon)); +extern List deriveOrd Args((Tycon)); +extern List deriveEnum Args((Tycon)); +extern List deriveIx Args((Tycon)); +extern List deriveShow Args((Tycon)); +extern List deriveRead Args((Cell)); +extern List deriveBounded Args((Tycon)); +extern List checkPrimDefn Args((Triple)); + +extern Bool typeMatches Args((Type,Type)); +extern Void evalExp Args((Void)); +extern Void linkControl Args((Int)); +extern Void deriveControl Args((Int)); +extern Void translateControl Args((Int)); +extern Void codegen Args((Int)); diff --git a/ghc/interpreter/derive.c b/ghc/interpreter/derive.c index 3f2f23450012..e6698c29483a 100644 --- a/ghc/interpreter/derive.c +++ b/ghc/interpreter/derive.c @@ -1,4 +1,4 @@ -/* -*- mode: hugs-c; -*- */ + /* -------------------------------------------------------------------------- * Deriving * @@ -7,16 +7,15 @@ * Hugs version 1.4, December 1997 * * $RCSfile: derive.c,v $ - * $Revision: 1.2 $ - * $Date: 1998/12/02 13:22:03 $ + * $Revision: 1.3 $ + * $Date: 1999/02/03 17:08:27 $ * ------------------------------------------------------------------------*/ #include "prelude.h" #include "storage.h" +#include "backend.h" #include "connect.h" #include "errors.h" -#include "translate.h" /* for implementConTag */ -#include "derive.h" static Cell varTrue; static Cell varFalse; @@ -47,7 +46,7 @@ static Cell varMinBound; static Cell varMaxBound; #endif #if DERIVE_SHOW -static Cell conCons; + Cell conCons; static Cell varShowField; /* display single field */ static Cell varShowParen; /* wrap with parens */ static Cell varCompose; /* function composition */ @@ -88,12 +87,29 @@ static List local makeDPats2 Args((Cell,Int)); static Bool local isEnumType Args((Tycon)); #endif +static Pair local mkAltEq Args((Int,List)); +static Pair local mkAltOrd Args((Int,List)); +static Cell local prodRange Args((Int,List,Cell,Cell,Cell)); +static Cell local prodIndex Args((Int,List,Cell,Cell,Cell)); +static Cell local prodInRange Args((Int,List,Cell,Cell,Cell)); +static List local mkIxBinds Args((Int,Cell,Int)); +static Cell local mkAltShow Args((Int,Cell,Int)); +static Cell local showsPrecRhs Args((Cell,Cell,Int)); +static Cell local mkReadCon Args((Name,Cell,Cell)); +static Cell local mkReadPrefix Args((Cell)); +static Cell local mkReadInfix Args((Cell)); +static Cell local mkReadTuple Args((Cell)); +static Cell local mkReadRecord Args((Cell,List)); +static List local mkBndBinds Args((Int,Cell,Int)); + + + /* -------------------------------------------------------------------------- * Deriving Utilities * ------------------------------------------------------------------------*/ -static List diVars = NIL; /* Acts as a cache of invented vars*/ -static Int diNum = 0; +List diVars = NIL; /* Acts as a cache of invented vars*/ +Int diNum = 0; static List local getDiVars(n) /* get list of at least n vars for */ Int n; { /* derived instance generation */ @@ -115,45 +131,6 @@ Cell r; { return singleton(pair(NIL,pair(mkInt(line),r))); } -#if DERIVE_EQ || DERIVE_ORD -static List local makeDPats2(h,n) /* generate pattern list */ -Cell h; /* by putting two new patterns with*/ -Int n; { /* head h and new var components */ - List us = getDiVars(2*n); - List vs = NIL; - Cell p; - Int i; - - for (i=0, p=h; i<n; ++i) { /* make first version of pattern */ - p = ap(p,hd(us)); - us = tl(us); - } - vs = cons(p,vs); - - for (i=0, p=h; i<n; ++i) { /* make second version of pattern */ - p = ap(p,hd(us)); - us = tl(us); - } - return cons(p,vs); -} -#endif - -#if DERIVE_ORD || DERIVE_ENUM || DERIVE_IX || DERIVE_BOUNDED -static Bool local isEnumType(t) /* Determine whether t is an enumeration */ -Tycon t; { /* type (i.e. all constructors arity == 0) */ - if (isTycon(t) && (tycon(t).what==DATATYPE || tycon(t).what==NEWTYPE)) { - List cs = tycon(t).defn; - for (; hasCfun(cs); cs=tl(cs)) { - if (name(hd(cs)).arity!=0) { - return FALSE; - } - } - return TRUE; - } - return FALSE; -} -#endif - /* -------------------------------------------------------------------------- * Given a datatype: data T a b = A a b | B Int | C deriving (Eq, Ord) * The derived definitions of equality and ordering are given by: @@ -172,26 +149,25 @@ Tycon t; { /* type (i.e. all constructors arity == 0) */ * constructors in the datatype definition. * ------------------------------------------------------------------------*/ -#if DERIVE_EQ - -static Pair local mkAltEq Args((Int,List)); +#define ap2(f,x,y) ap(ap(f,x),y) -List deriveEq(t) /* generate binding for derived == */ +List local deriveEq(t) /* generate binding for derived == */ Type t; { /* for some TUPLE or DATATYPE t */ List alts = NIL; if (isTycon(t)) { /* deal with type constrs */ List cs = tycon(t).defn; for (; hasCfun(cs); cs=tl(cs)) { alts = cons(mkAltEq(tycon(t).line, - makeDPats2(hd(cs),name(hd(cs)).arity)), + makeDPats2(hd(cs),userArity(hd(cs)))), alts); } if (cfunOf(hd(tycon(t).defn))!=0) { alts = cons(pair(cons(WILDCARD,cons(WILDCARD,NIL)), - pair(mkInt(tycon(t).line),varFalse)),alts); + pair(mkInt(tycon(t).line),nameFalse)),alts); } alts = rev(alts); - } else { /* special case for tuples */ + } + else { /* special case for tuples */ alts = singleton(mkAltEq(0,makeDPats2(t,tupleOf(t)))); } return singleton(mkBind("==",alts)); @@ -202,55 +178,35 @@ Int line; /* using patterns in pats for lhs */ List pats; { /* arguments */ Cell p = hd(pats); Cell q = hd(tl(pats)); - Cell e = varTrue; + Cell e = nameTrue; if (isAp(p)) { - e = ap2(varEq,arg(p),arg(q)); + e = ap2(nameEq,arg(p),arg(q)); for (p=fun(p), q=fun(q); isAp(p); p=fun(p), q=fun(q)) { - e = ap2(varAnd,ap2(varEq,arg(p),arg(q)),e); + e = ap2(nameAnd,ap2(nameEq,arg(p),arg(q)),e); } } return pair(pats,pair(mkInt(line),e)); } -#endif /* DERIVE_EQ */ - -#if DERIVE_ORD - -static Pair local mkAltOrd Args((Int,List)); List deriveOrd(t) /* make binding for derived compare*/ Type t; { /* for some TUPLE or DATATYPE t */ List alts = NIL; if (isEnumType(t)) { /* special case for enumerations */ - Cell u = inventVar(); - Cell w = inventVar(); - Cell rhs = NIL; - if (cfunOf(hd(tycon(t).defn))!=0) { - implementConToTag(t); - rhs = ap2(varCompare, - ap(tycon(t).conToTag,u), - ap(tycon(t).conToTag,w)); - } else { - rhs = varEQ; - } - alts = singleton(pair(doubleton(u,w),pair(mkInt(tycon(t).line),rhs))); + alts = mkVarAlts(tycon(t).line,nameConCmp); } else if (isTycon(t)) { /* deal with type constrs */ List cs = tycon(t).defn; for (; hasCfun(cs); cs=tl(cs)) { alts = cons(mkAltOrd(tycon(t).line, - makeDPats2(hd(cs),name(hd(cs)).arity)), + makeDPats2(hd(cs),userArity(hd(cs)))), alts); } if (cfunOf(hd(tycon(t).defn))!=0) { Cell u = inventVar(); Cell w = inventVar(); - implementConToTag(t); - alts = cons(pair(doubleton(u,w), + alts = cons(pair(cons(u,singleton(w)), pair(mkInt(tycon(t).line), - ap2(varCompare, - ap(tycon(t).conToTag,u), - ap(tycon(t).conToTag,w)))), - alts); + ap2(nameConCmp,u,w))),alts); } alts = rev(alts); } else { /* special case for tuples */ @@ -264,72 +220,72 @@ Int line; /* using patterns in pats for lhs */ List pats; { /* arguments */ Cell p = hd(pats); Cell q = hd(tl(pats)); - Cell e = varEQ; + Cell e = nameEQ; if (isAp(p)) { - e = ap2(varCompare,arg(p),arg(q)); + e = ap2(nameCompare,arg(p),arg(q)); for (p=fun(p), q=fun(q); isAp(p); p=fun(p), q=fun(q)) { - e = ap3(varCompAux,arg(p),arg(q),e); + e = ap(ap2(nameCompAux,arg(p),arg(q)),e); } } return pair(pats,pair(mkInt(line),e)); } -#endif /* DERIVE_ORD */ + +static List local makeDPats2(h,n) /* generate pattern list */ +Cell h; /* by putting two new patterns with*/ +Int n; { /* head h and new var components */ + List us = getDiVars(2*n); + List vs = NIL; + Cell p; + Int i; + + for (i=0, p=h; i<n; ++i) { /* make first version of pattern */ + p = ap(p,hd(us)); + us = tl(us); + } + vs = cons(p,vs); + + for (i=0, p=h; i<n; ++i) { /* make second version of pattern */ + p = ap(p,hd(us)); + us = tl(us); + } + return cons(p,vs); +} /* -------------------------------------------------------------------------- * Deriving Ix and Enum: * ------------------------------------------------------------------------*/ -#if DERIVE_ENUM List deriveEnum(t) /* Construct definition of enumeration */ Tycon t; { - Int l = tycon(t).line; - Cell x = inventVar(); - Cell y = inventVar(); - Cell first = hd(tycon(t).defn); - Cell last = tycon(t).defn; + Int l = tycon(t).line; if (!isEnumType(t)) { ERRMSG(l) "Can only derive instances of Enum for enumeration types" EEND; } - while (hasCfun(tl(last))) { - last = tl(last); - } - last = hd(last); - implementConToTag(t); - implementTagToCon(t); - return cons(mkBind("toEnum", mkVarAlts(l,tycon(t).tagToCon)), - cons(mkBind("fromEnum", mkVarAlts(l,tycon(t).conToTag)), - cons(mkBind("enumFrom", singleton(pair(singleton(x), pair(mkInt(l),ap2(varEnumFromTo,x,last))))), - /* default instance of enumFromTo is good */ - cons(mkBind("enumFromThen",singleton(pair(doubleton(x,y),pair(mkInt(l),ap3(varEnumFromThenTo,x,y,ap(COND,triple(ap2(varLe,x,y),last,first))))))), - /* default instance of enumFromThenTo is good */ - NIL)))); -} -#endif /* DERIVE_ENUM */ -#if DERIVE_IX -static List local mkIxBindsEnum Args((Tycon)); -static List local mkIxBinds Args((Int,Cell,Int)); -static Cell local prodRange Args((Int,List,Cell,Cell,Cell)); -static Cell local prodIndex Args((Int,List,Cell,Cell,Cell)); -static Cell local prodInRange Args((Int,List,Cell,Cell,Cell)); + return cons(mkBind("toEnum",mkVarAlts(l,ap(nameEnToEn,hd(tycon(t).defn)))), + cons(mkBind("fromEnum",mkVarAlts(l,nameEnFrEn)), + cons(mkBind("enumFrom",mkVarAlts(l,nameEnFrom)), + cons(mkBind("enumFromTo",mkVarAlts(l,nameEnFrTo)), + cons(mkBind("enumFromThen",mkVarAlts(l,nameEnFrTh)),NIL))))); +} List deriveIx(t) /* Construct definition of indexing */ Tycon t; { - Int l = tycon(t).line; if (isEnumType(t)) { /* Definitions for enumerations */ - implementConToTag(t); - implementTagToCon(t); - return mkIxBindsEnum(t); + return cons(mkBind("range",mkVarAlts(tycon(t).line,nameEnRange)), + cons(mkBind("index",mkVarAlts(tycon(t).line,nameEnIndex)), + cons(mkBind("inRange",mkVarAlts(tycon(t).line,nameEnInRng)), + NIL))); } else if (isTuple(t)) { /* Definitions for product types */ return mkIxBinds(0,t,tupleOf(t)); } else if (isTycon(t) && cfunOf(hd(tycon(t).defn))==0) { return mkIxBinds(tycon(t).line, hd(tycon(t).defn), - name(hd(tycon(t).defn)).arity); + userArity(hd(tycon(t).defn))); } ERRMSG(tycon(t).line) "Can only derive instances of Ix for enumeration or product types" @@ -337,30 +293,19 @@ Tycon t; { return NIL;/* NOTREACHED*/ } -/* instance Ix T where - * range (c1,c2) = map tagToCon [conToTag c1 .. conToTag c2] - * index b@(c1,c2) ci - * | inRange b ci = conToTag ci - conToTag c1 - * | otherwise = error "Ix.index.T: Index out of range." - * inRange (c1,c2) ci = conToTag c1 <= i && i <= conToTag c2 - * where i = conToTag ci - */ -static List local mkIxBindsEnum(t) -Tycon t; { - Int l = tycon(t).line; - Name tagToCon = tycon(t).tagToCon; - Name conToTag = tycon(t).conToTag; - Cell b = inventVar(); - Cell c1 = inventVar(); - Cell c2 = inventVar(); - Cell ci = inventVar(); - return cons(mkBind("range", singleton(pair(singleton(ap2(mkTuple(2),c1,c2)), pair(mkInt(l),ap2(varMap,tagToCon,ap2(varEnumFromTo,ap(conToTag,c1),ap(conToTag,c2))))))), - cons(mkBind("index", singleton(pair(doubleton(ap(ASPAT,pair(b,ap2(mkTuple(2),c1,c2))),ci), - pair(mkInt(l),ap(COND,triple(ap2(varInRange,b,ci), - ap2(varMinus,ap(conToTag,ci),ap(conToTag,c1)), - ap(varError,mkStr(findText("Ix.index: Index out of range"))))))))), - cons(mkBind("inRange",singleton(pair(doubleton(ap2(mkTuple(2),c1,c2),ci), pair(mkInt(l),ap2(varAnd,ap2(varLe,ap(conToTag,c1),ap(conToTag,ci)),ap2(varLe,ap(conToTag,ci),ap(conToTag,c2))))))), /* ToDo: share conToTag ci */ - NIL))); +static Bool local isEnumType(t) /* Determine whether t is an enumeration */ +Tycon t; { /* type (i.e. all constructors arity == 0) */ + if (isTycon(t) && (tycon(t).what==DATATYPE || tycon(t).what==NEWTYPE)) { + List cs = tycon(t).defn; + for (; hasCfun(cs); cs=tl(cs)) { + if (name(hd(cs)).arity!=0) { + return FALSE; + } + } + /* ToDo: correct? addCfunTable(t); */ + return TRUE; + } + return FALSE; } static List local mkIxBinds(line,h,n) /* build bindings for derived Ix on*/ @@ -384,9 +329,8 @@ Int n; { pats = cons(pr,cons(is,NIL)); /* Build [(ls,us),is] */ return cons(prodRange(line,singleton(pr),ls,us,is), - cons(prodIndex(line,pats,ls,us,is), - cons(prodInRange(line,pats,ls,us,is), - NIL))); + cons(prodIndex(line,pats,ls,us,is), + cons(prodInRange(line,pats,ls,us,is),NIL))); } static Cell local prodRange(line,pats,ls,us,is) @@ -401,7 +345,7 @@ Cell ls, us, is; { List e = NIL; for (; isAp(ls); ls=fun(ls), us=fun(us), is=fun(is)) { e = cons(ap(FROMQUAL,pair(arg(is), - ap(varRange,ap2(mkTuple(2), + ap(nameRange,ap2(mkTuple(2), arg(ls), arg(us))))),e); } @@ -423,11 +367,11 @@ Cell ls, us, is; { List xs = NIL; Cell e = NIL; for (; isAp(ls); ls=fun(ls), us=fun(us), is=fun(is)) { - xs = cons(ap2(varIndex,ap2(mkTuple(2),arg(ls),arg(us)),arg(is)),xs); + xs = cons(ap2(nameIndex,ap2(mkTuple(2),arg(ls),arg(us)),arg(is)),xs); } for (e=hd(xs); nonNull(xs=tl(xs));) { Cell x = hd(xs); - e = ap2(varPlus,x,ap2(varMult,ap(varRangeSize,arg(fun(x))),e)); + e = ap2(namePlus,x,ap2(nameMult,ap(nameRangeSize,arg(fun(x))),e)); } e = singleton(pair(pats,pair(mkInt(line),e))); return mkBind("index",e); @@ -441,33 +385,27 @@ Cell ls, us, is; { * inRange (X a b c, X p q r) (X x y z) * = inRange (a,p) x && inRange (b,q) y && inRange (c,r) z */ - Cell e = ap2(varInRange,ap2(mkTuple(2),arg(ls),arg(us)),arg(is)); + Cell e = ap2(nameInRange,ap2(mkTuple(2),arg(ls),arg(us)),arg(is)); while (ls=fun(ls), us=fun(us), is=fun(is), isAp(ls)) { - e = ap2(varAnd, - ap2(varInRange,ap2(mkTuple(2),arg(ls),arg(us)),arg(is)), + e = ap2(nameAnd, + ap2(nameInRange,ap2(mkTuple(2),arg(ls),arg(us)),arg(is)), e); } e = singleton(pair(pats,pair(mkInt(line),e))); return mkBind("inRange",e); } -#endif /* DERIVE_IX */ /* -------------------------------------------------------------------------- * Deriving Show: * ------------------------------------------------------------------------*/ -#if DERIVE_SHOW - -static Cell local mkAltShow Args((Int,Cell,Int)); -static Cell local showsPrecRhs Args((Cell,Cell)); - List deriveShow(t) /* Construct definition of text conversion */ Tycon t; { List alts = NIL; if (isTycon(t)) { /* deal with type constrs */ List cs = tycon(t).defn; for (; hasCfun(cs); cs=tl(cs)) { - alts = cons(mkAltShow(tycon(t).line,hd(cs),name(hd(cs)).arity), + alts = cons(mkAltShow(tycon(t).line,hd(cs),userArity(hd(cs))), alts); } alts = rev(alts); @@ -484,26 +422,29 @@ Int a; { List vs = getDiVars(a+1); Cell d = hd(vs); Cell pat = h; - while (vs=tl(vs), 0<a--) { + List pats = NIL; + Int i = 0; + for (vs=tl(vs); i<a; i++) { pat = ap(pat,hd(vs)); + vs = tl(vs); } - return pair(doubleton(d,pat), - pair(mkInt(line),showsPrecRhs(d,pat))); + pats = cons(d,cons(pat,NIL)); + return pair(pats,pair(mkInt(line),showsPrecRhs(d,pat,a))); } -#define consChar(c) ap(conCons,mkChar(c)) -#define shows0 ap(varShowsPrec,mkInt(0)) -#define shows10 ap(varShowsPrec,mkInt(10)) -#define showsOP ap(varCompose,consChar('(')) -#define showsOB ap(varCompose,consChar('{')) -#define showsCM ap(varCompose,consChar(',')) -#define showsSP ap(varCompose,consChar(' ')) -#define showsBQ ap(varCompose,consChar('`')) +#define shows0 ap(nameShowsPrec,mkInt(0)) +#define shows10 ap(nameShowsPrec,mkInt(10)) +#define showsOP ap(nameComp,consChar('(')) +#define showsOB ap(nameComp,consChar('{')) +#define showsCM ap(nameComp,consChar(',')) +#define showsSP ap(nameComp,consChar(' ')) +#define showsBQ ap(nameComp,consChar('`')) #define showsCP consChar(')') #define showsCB consChar('}') -static Cell local showsPrecRhs(d,pat) /* build a rhs for showsPrec for a */ -Cell d, pat; { /* given pattern, pat */ +static Cell local showsPrecRhs(d,pat,a) /* build a rhs for showsPrec for a */ +Cell d, pat; /* given pattern, pat */ +Int a; { Cell h = getHead(pat); List cfs = cfunSfuns; @@ -518,10 +459,10 @@ Cell d, pat; { /* given pattern, pat */ Int i = tupleOf(h); Cell rhs = showsCP; for (; i>1; --i) { - rhs = ap(showsCM,ap2(varCompose,ap(shows0,arg(pat)),rhs)); + rhs = ap(showsCM,ap2(nameComp,ap(shows0,arg(pat)),rhs)); pat = fun(pat); } - return ap(showsOP,ap2(varCompose,ap(shows0,arg(pat)),rhs)); + return ap(showsOP,ap2(nameComp,ap(shows0,arg(pat)),rhs)); } for (; nonNull(cfs) && h!=fst(hd(cfs)); cfs=tl(cfs)) { @@ -536,11 +477,11 @@ Cell d, pat; { /* given pattern, pat */ * = showString lab . showChar '=' . shows val */ Cell rhs = showsCB; - List vs = revDupOnto(snd(hd(cfs)),NIL); + List vs = dupOnto(snd(hd(cfs)),NIL); if (isAp(pat)) { for (;;) { - rhs = ap2(varCompose, - ap2(varShowField, + rhs = ap2(nameComp, + ap2(nameShowField, mkStr(textOf(hd(vs))), arg(pat)), rhs); @@ -553,16 +494,17 @@ Cell d, pat; { /* given pattern, pat */ } } } - rhs = ap2(varCompose,ap(varAppend,mkStr(name(h).text)),ap(showsOB,rhs)); + rhs = ap2(nameComp,ap(nameApp,mkStr(name(h).text)),ap(showsOB,rhs)); return rhs; - } else if (name(h).arity==0) { + } + else if (a==0) { /* To display a nullary constructor: * showsPrec d Foo = showString "Foo" */ - return ap(varAppend,mkStr(name(h).text)); + return ap(nameApp,mkStr(name(h).text)); } else { - Syntax s = syntaxOf(name(h).text); - if (name(h).arity==2 && assocOf(s)!=APPLIC) { + Syntax s = syntaxOf(h); + if (a==2 && assocOf(s)!=APPLIC) { /* For a binary constructor with prec p: * showsPrec d (a :* b) = showParen (d > p) * (showsPrec lp a . showChar ' ' . @@ -572,21 +514,23 @@ Cell d, pat; { /* given pattern, pat */ Int p = precOf(s); Int lp = (assocOf(s)==LEFT_ASS) ? p : (p+1); Int rp = (assocOf(s)==RIGHT_ASS) ? p : (p+1); - Cell rhs = ap(showsSP,ap2(varShowsPrec,mkInt(rp),arg(pat))); + Cell rhs = ap(showsSP,ap2(nameShowsPrec,mkInt(rp),arg(pat))); if (defaultSyntax(name(h).text)==APPLIC) { rhs = ap(showsBQ, - ap2(varCompose, - ap(varAppend,mkStr(name(h).text)), + ap2(nameComp, + ap(nameApp,mkStr(name(h).text)), ap(showsBQ,rhs))); } else { - rhs = ap2(varCompose,ap(varAppend,mkStr(name(h).text)),rhs); + rhs = ap2(nameComp,ap(nameApp,mkStr(name(h).text)),rhs); } - rhs = ap2(varCompose, - ap2(varShowsPrec,mkInt(lp),arg(fun(pat))), + + rhs = ap2(nameComp, + ap2(nameShowsPrec,mkInt(lp),arg(fun(pat))), ap(showsSP,rhs)); - rhs = ap2(varShowParen,ap2(varLe,mkInt(p+1),d),rhs); + rhs = ap2(nameShowParen,ap2(nameLe,mkInt(p+1),d),rhs); return rhs; - } else { + } + else { /* To display a non-nullary constructor with applicative syntax: * showsPrec d (Foo x y) = showParen (d>=10) * (showString "Foo" . @@ -595,10 +539,10 @@ Cell d, pat; { /* given pattern, pat */ */ Cell rhs = ap(showsSP,ap(shows10,arg(pat))); for (pat=fun(pat); isAp(pat); pat=fun(pat)) { - rhs = ap(showsSP,ap2(varCompose,ap(shows10,arg(pat)),rhs)); + rhs = ap(showsSP,ap2(nameComp,ap(shows10,arg(pat)),rhs)); } - rhs = ap2(varCompose,ap(varAppend,mkStr(name(h).text)),rhs); - rhs = ap2(varShowParen,ap2(varLe,mkInt(10),d),rhs); + rhs = ap2(nameComp,ap(nameApp,mkStr(name(h).text)),rhs); + rhs = ap2(nameShowParen,ap2(nameLe,mkInt(10),d),rhs); return rhs; } } @@ -612,31 +556,20 @@ Cell d, pat; { /* given pattern, pat */ #undef showsBQ #undef showsCP #undef showsCB -#undef consChar - -#endif /* DERIVE_SHOW */ /* -------------------------------------------------------------------------- * Deriving Read: * ------------------------------------------------------------------------*/ -#if DERIVE_READ - -static Cell local mkReadCon Args((Name,Cell,Cell)); -static Cell local mkReadPrefix Args((Cell)); -static Cell local mkReadInfix Args((Cell)); -static Cell local mkReadTuple Args((Cell)); -static Cell local mkReadRecord Args((Cell,List)); - #define Tuple2(f,s) ap2(mkTuple(2),f,s) -#define Lex(r) ap(varLex,r) +#define Lex(r) ap(nameLex,r) #define ZFexp(h,q) ap(FROMQUAL, pair(h,q)) -#define ReadsPrec(n,e) ap2(varReadsPrec,n,e) +#define ReadsPrec(n,e) ap2(nameReadsPrec,n,e) #define Lambda(v,e) ap(LAMBDA,pair(v, pair(mkInt(0),e))) -#define ReadParen(a,b,c) ap3(varReadParen,a,b,c) -#define ReadField(f,s) ap2(varReadField,f,s) -#define GT(l,r) ap2(varGt,l,r) -#define Append(a,b) ap2(varAppend,a,b) +#define ReadParen(a,b,c) ap(ap2(nameReadParen,a,b),c) +#define ReadField(f,s) ap2(nameReadField,f,s) +#define GT(l,r) ap2(nameGt,l,r) +#define Append(a,b) ap2(nameApp,a,b) /* Construct the readsPrec function of the form: * @@ -645,7 +578,7 @@ static Cell local mkReadRecord Args((Cell,List)); * ... * (readParen (d>pn) (\r -> [ (Cn ...,s) | ... ]) r) ... )) */ -List deriveRead(t) /* construct definition of text reader */ +List deriveRead(t) /* construct definition of text reader */ Cell t; { Cell alt = NIL; Cell exp = NIL; @@ -657,16 +590,17 @@ Cell t; { if (isTycon(t)) { List cs = tycon(t).defn; List exps = NIL; - for(; hasCfun(cs); cs=tl(cs)) { + for (; hasCfun(cs); cs=tl(cs)) { exps = cons(mkReadCon(hd(cs),d,r),exps); } /* reverse concatenate list of subexpressions */ exp = hd(exps); - for(exps=tl(exps); nonNull(exps); exps=tl(exps)) { - exp = ap2(varAppend,hd(exps),exp); + for (exps=tl(exps); nonNull(exps); exps=tl(exps)) { + exp = ap2(nameApp,hd(exps),exp); } line = tycon(t).line; - } else { /* Tuples */ + } + else { /* Tuples */ exp = ap(mkReadTuple(t),r); } /* printExp(stdout,exp); putc('\n',stdout); */ @@ -680,29 +614,30 @@ Cell t; { * * for a (non-tuple) constructor "con" of precedence "p". */ + static Cell local mkReadCon(con, d, r) /* generate reader for a constructor */ Name con; Cell d; Cell r; { Cell exp = NIL; Int p = 0; - Syntax s = syntaxOf(name(con).text); + Syntax s = syntaxOf(con); List cfs = cfunSfuns; for (; nonNull(cfs) && con!=fst(hd(cfs)); cfs=tl(cfs)) { } if (nonNull(cfs)) { exp = mkReadRecord(con,snd(hd(cfs))); - p = 9; - } else if (name(con).arity==2 && assocOf(s)!=APPLIC) { + return ReadParen(nameFalse, exp, r); + } + + if (userArity(con)==2 && assocOf(s)!=APPLIC) { exp = mkReadInfix(con); p = precOf(s); } else { exp = mkReadPrefix(con); p = 9; } - return ReadParen(name(con).arity==0 ? varFalse : GT(d,mkInt(p)), - exp, - r); + return ReadParen(userArity(con)==0 ? nameFalse : GT(d,mkInt(p)), exp, r); } /* Given an n-ary prefix constructor, generate a single lambda @@ -721,7 +656,7 @@ Cell r; { */ static Cell local mkReadPrefix(con) /* readsPrec for prefix constructor */ Cell con; { - Int arity = name(con).arity; + Int arity = userArity(con); Cell cn = mkStr(name(con).text); Cell r = inventVar(); Cell prev_s = inventVar(); @@ -758,7 +693,7 @@ Cell con; { static Cell local mkReadInfix( con ) Cell con; { - Syntax s = syntaxOf(name(con).text); + Syntax s = syntaxOf(con); Int p = precOf(s); Int lp = assocOf(s)==LEFT_ASS ? p : (p+1); Int rp = assocOf(s)==RIGHT_ASS ? p : (p+1); @@ -884,17 +819,13 @@ List fs; { #undef GT #undef Append -#endif /* DERIVE_READ */ - /* -------------------------------------------------------------------------- * Deriving Bounded: * ------------------------------------------------------------------------*/ #if DERIVE_BOUNDED -static List local mkBndBinds Args((Int,Cell,Int)); - -List deriveBounded(t) /* construct definition of bounds */ +List deriveBounded(t) /* construct definition of bounds */ Tycon t; { if (isEnumType(t)) { Cell last = tycon(t).defn; @@ -905,12 +836,12 @@ Tycon t; { return cons(mkBind("minBound",mkVarAlts(tycon(t).line,first)), cons(mkBind("maxBound",mkVarAlts(tycon(t).line,hd(last))), NIL)); - } else if (isTuple(t)) { /* Definitions for product types */ + } else if (isTuple(t)) { /* Definitions for product types */ return mkBndBinds(0,t,tupleOf(t)); } else if (isTycon(t) && cfunOf(hd(tycon(t).defn))==0) { return mkBndBinds(tycon(t).line, hd(tycon(t).defn), - name(hd(tycon(t).defn)).arity); + userArity(hd(tycon(t).defn))); } ERRMSG(tycon(t).line) "Can only derive instances of Bounded for enumeration and product types" @@ -925,18 +856,18 @@ Int n; { Cell minB = h; Cell maxB = h; while (n-- > 0) { - minB = ap(minB,varMinBound); - maxB = ap(maxB,varMaxBound); + minB = ap(minB,nameMinBnd); + maxB = ap(maxB,nameMaxBnd); } return cons(mkBind("minBound",mkVarAlts(line,minB)), - cons(mkBind("maxBound",mkVarAlts(line,maxB)), - NIL)); + cons(mkBind("maxBound",mkVarAlts(line,maxB)), + NIL)); } - #endif /* DERIVE_BOUNDED */ + /* -------------------------------------------------------------------------- - * Static Analysis control: + * Derivation control: * ------------------------------------------------------------------------*/ Void deriveControl(what) diff --git a/ghc/interpreter/dynamic.c b/ghc/interpreter/dynamic.c index f6d7fddd1551..843aa925c8f8 100644 --- a/ghc/interpreter/dynamic.c +++ b/ghc/interpreter/dynamic.c @@ -1,4 +1,4 @@ -/* -*- mode: hugs-c; -*- */ + /* -------------------------------------------------------------------------- * Dynamic loading (of .dll or .so files) for Hugs * @@ -7,8 +7,8 @@ * Hugs version 1.4, December 1997 * * $RCSfile: dynamic.c,v $ - * $Revision: 1.2 $ - * $Date: 1998/12/02 13:22:06 $ + * $Revision: 1.3 $ + * $Date: 1999/02/03 17:08:28 $ * ------------------------------------------------------------------------*/ #include "prelude.h" @@ -29,7 +29,7 @@ String fn; { void* lookupSymbol(file,symbol) ObjectFile file; String symbol; { - return dlsym(file,symbol) + return dlsym(file,symbol); } void* getDLLSymbol(dll,symbol) /* load dll and lookup symbol */ diff --git a/ghc/interpreter/errors.h b/ghc/interpreter/errors.h index 5bfd9664b666..98bb6cac88dc 100644 --- a/ghc/interpreter/errors.h +++ b/ghc/interpreter/errors.h @@ -1,18 +1,19 @@ -/* -*- mode: hugs-c; -*- */ + /* -------------------------------------------------------------------------- * Error handling support functions * - * Copyright (c) The University of Nottingham and Yale University, 1994-1997. - * All rights reserved. See NOTICE for details and conditions of use etc... - * Hugs version 1.4, December 1997 + * Hugs 98 is Copyright (c) Mark P Jones, Alastair Reid and the Yale + * Haskell Group 1994-99, and is distributed as Open Source software + * under the Artistic License; see the file "Artistic" that is included + * in the distribution for details. * * $RCSfile: errors.h,v $ - * $Revision: 1.2 $ - * $Date: 1998/12/02 13:22:07 $ + * $Revision: 1.3 $ + * $Date: 1999/02/03 17:08:28 $ * ------------------------------------------------------------------------*/ -extern Void internal Args((String)) HUGS_noreturn; -extern Void fatal Args((String)) HUGS_noreturn; +extern Void internal Args((String)) HUGS_noreturn; +extern Void fatal Args((String)) HUGS_noreturn; #if HUGS_FOR_WINDOWS #define Hilite() WinTextcolor(hWndText,RED); @@ -41,6 +42,13 @@ extern Void errAbort Args((Void)); extern sigProto(breakHandler); -#include "output.h" +extern Bool breakOn Args((Bool)); /* in machdep.c */ + +extern Void printExp Args((FILE *,Cell)); /* in output.c */ +extern Void printType Args((FILE *,Cell)); +extern Void printContext Args((FILE *,List)); +extern Void printPred Args((FILE *,Cell)); +extern Void printKind Args((FILE *,Kind)); +extern Void printKinds Args((FILE *,Kinds)); /*-------------------------------------------------------------------------*/ diff --git a/ghc/interpreter/free.c b/ghc/interpreter/free.c index 2d7344c8ace8..59eb322e0486 100644 --- a/ghc/interpreter/free.c +++ b/ghc/interpreter/free.c @@ -1,4 +1,4 @@ -/* -*- mode: hugs-c; -*- */ + /* -------------------------------------------------------------------------- * Free variable analysis * @@ -7,16 +7,16 @@ * Hugs version 1.4, December 1997 * * $RCSfile: free.c,v $ - * $Revision: 1.2 $ - * $Date: 1998/12/02 13:22:08 $ + * $Revision: 1.3 $ + * $Date: 1999/02/03 17:08:29 $ * ------------------------------------------------------------------------*/ #include "prelude.h" #include "storage.h" +#include "backend.h" #include "connect.h" #include "errors.h" -#include "stg.h" -#include "free.h" + /* -------------------------------------------------------------------------- * Local functions diff --git a/ghc/interpreter/hugs.c b/ghc/interpreter/hugs.c index 5f6a36873383..f456db3d94c1 100644 --- a/ghc/interpreter/hugs.c +++ b/ghc/interpreter/hugs.c @@ -1,37 +1,36 @@ -/* -*- mode: hugs-c; -*- */ + /* -------------------------------------------------------------------------- * Command interpreter * - * Copyright (c) The University of Nottingham and Yale University, 1994-1997. - * All rights reserved. See NOTICE for details and conditions of use etc... - * Hugs version 1.4, December 1997 + * Hugs 98 is Copyright (c) Mark P Jones, Alastair Reid and the Yale + * Haskell Group 1994-99, and is distributed as Open Source software + * under the Artistic License; see the file "Artistic" that is included + * in the distribution for details. * * $RCSfile: hugs.c,v $ - * $Revision: 1.2 $ - * $Date: 1998/12/02 13:22:09 $ + * $Revision: 1.3 $ + * $Date: 1999/02/03 17:08:29 $ * ------------------------------------------------------------------------*/ +#include <setjmp.h> +#include <ctype.h> +#include <stdio.h> + #include "prelude.h" -#include "version.h" #include "storage.h" #include "command.h" +#include "backend.h" #include "connect.h" -#include "charset.h" -#include "input.h" -#include "type.h" -#include "subst.h" /* for typeMatches */ -#include "link.h" /* for classShow, nameRunIO and namePrint */ -#include "static.h" -#include "compiler.h" -#include "interface.h" -#include "hugs.h" #include "errors.h" -#include <setjmp.h> -#include <ctype.h> +#include "version.h" +#include "link.h" + +#include "Rts.h" +#include "RtsAPI.h" +#include "Schedule.h" -#include <stdio.h> -#include "machdep.h" +Bool haskell98 = TRUE; /* TRUE => Haskell 98 compatibility*/ /* -------------------------------------------------------------------------- * Local function prototypes: @@ -51,12 +50,20 @@ static Void local readScripts Args((Int)); static Void local whatScripts Args((Void)); static Void local editor Args((Void)); static Void local find Args((Void)); +static Bool local startEdit Args((Int,String)); static Void local runEditor Args((Void)); +#if IGNORE_MODULES +#define findEvalModule() doNothing() +#else static Void local setModule Args((Void)); static Module local findEvalModule Args((Void)); +#endif static Void local evaluator Args((Void)); +static Void local stopAnyPrinting Args((Void)); static Void local showtype Args((Void)); +static String local objToStr Args((Module, Cell)); static Void local info Args((Void)); +static Void local printSyntax Args((Name)); static Void local showInst Args((Inst)); static Void local describe Args((Text)); static Void local listNames Args((Void)); @@ -85,6 +92,7 @@ static String local strCopy Args((String)); * Machine dependent code for Hugs interpreter: * ------------------------------------------------------------------------*/ +#include "machdep.c" #ifdef WANT_TIMER #include "timer.c" #endif @@ -93,8 +101,11 @@ static String local strCopy Args((String)); * Local data areas: * ------------------------------------------------------------------------*/ +static Bool printing = FALSE; /* TRUE => currently printing value*/ +static Bool showStats = FALSE; /* TRUE => print stats after eval */ static Bool listScripts = TRUE; /* TRUE => list scripts after loading*/ -static Bool addType = FALSE; /* TRUE => print type with value */ +static Bool addType = FALSE; /* TRUE => print type with value */ +static Bool useShow = TRUE; /* TRUE => use Text/show printer */ static Bool chaseImports = TRUE; /* TRUE => chase imports on load */ static Bool useDots = RISCOS; /* TRUE => use dots in progress */ static Bool quiet = FALSE; /* TRUE => don't show progress */ @@ -154,39 +165,13 @@ char *argv[]; { CStackBase = &argc; /* Save stack base for use in gc */ - /* The startup banner now includes my name. Hugs is provided free of */ - /* charge. I ask however that you show your appreciation for the many */ - /* hours of work involved by retaining my name in the banner. Thanks! */ + Printf("__ __ __ __ ____ ___ _______________________________________________\n"); + Printf("|| || || || || || ||__ Hugs 98: The Nottingham and Yale Haskell system\n"); + Printf("||___|| ||__|| ||__|| __|| Copyright (c) 1994-1999\n"); + Printf("||---|| ___|| World Wide Web: http://haskell.org/hugs\n"); + Printf("|| || Report bugs to: hugs-bugs@haskell.org\n"); + Printf("|| || Version: %s _______________________________________________\n\n",HUGS_VERSION); -#if SMALL_BANNER - Printf("Hugs 1.4, %s release.\n", HUGS_VERSION); - Printf("Copyright (c) The University of Nottingham and Yale University, 1994-1998.\n"); - Printf("Home page: http://haskell.org/hugs. Bug reports: hugs-bugs@haskell.org.\n"); -#else -#ifdef OLD_LOGO - Printf(" ___ ___ ___ ___ __________ __________ \n"); - Printf(" / / / / / / / / / _______/ / _______/ Hugs 1.4 \n"); - Printf(" / /___/ / / / / / / / _____ / /______ \n"); - Printf(" / ____ / / / / / / / /_ / /______ / The Nottingham and Yale\n"); - Printf(" / / / / / /___/ / / /___/ / _______/ / Haskell User's System \n"); - Printf(" /__/ /__/ /_________/ /_________/ /_________/ %s\n\n", HUGS_VERSION); - Printf("Copyright (c) The University of Nottingham and Yale University, 1994-1998.\n"); - Printf("Home page: http://haskell.org/hugs. Bug reports: hugs-bugs@haskell.org.\n"); -#else - /* There is now a new banner, designed to draw attention to the fact */ - /* that the version of Hugs being used is substantially different from */ - /* previous releases (and to correct the mistaken view that Hugs is */ - /* written in capitals). If you really prefer the old style banner, */ - /* you can still get it by compiling with -DOLD_LOGO. */ - - printf(" __ __ __ __ ____ ___ __________________________________________\n"); - printf(" || || || || || || ||__ Hugs 1.4: The Haskell User's Gofer System\n"); - printf(" ||___|| ||__|| ||__|| __|| (c) The University of Nottingham\n"); - printf(" ||---|| ___|| and Yale University, 1994-1998.\n"); - printf(" || || Report bugs to hugs-bugs@haskell.org\n"); - printf(" || || "HUGS_VERSION" __________________________________________\n\n"); -#endif -#endif #if SYMANTEC_C Printf(" Ported to Macintosh by Hans Aberg, compiled " __DATE__ ".\n\n"); #endif @@ -217,7 +202,6 @@ String argv[]; { scriptFile = 0; numScripts = 0; namesUpto = 1; - initCharTab(); #if HUGS_FOR_WINDOWS hugsEdit = strCopy(fromEnv("EDITOR","c:\\windows\notepad.exe")); @@ -226,11 +210,13 @@ String argv[]; { #else hugsEdit = strCopy(fromEnv("EDITOR",NULL)); #endif - hugsPath = strCopy(HUGSPATH); - readOptions("-p\"%s> \" -r$$"); + hugsPath = strCopy(HUGSPATH); readOptions("-p\"%s> \" -r$$"); #if USE_REGISTRY - readOptions(readRegString("Options","")); -#endif + projectPath = strCopy(readRegChildStrings(HKEY_LOCAL_MACHINE,ProjectRoot, + "HUGSPATH", PATHSEP, "")); + readOptions(readRegString(HKEY_LOCAL_MACHINE,HugsRoot,"Options","")); + readOptions(readRegString(HKEY_CURRENT_USER, HugsRoot,"Options","")); +#endif /* USE_REGISTRY */ readOptions(fromEnv("HUGSFLAGS","")); for (i=1; i<argc; ++i) { /* process command line arguments */ @@ -241,7 +227,8 @@ String argv[]; { } else { proj = argv[++i]; } - } else if (!processOption(argv[i])) { + } else if (argv[i] && argv[i][0]/* workaround for /bin/sh silliness*/ + && !processOption(argv[i])) { addScriptName(argv[i],TRUE); } } @@ -254,13 +241,19 @@ String argv[]; { DEBUG_LoadSymbols(argv[0]); #endif - scriptName[0] = strCopy(findMPathname(NULL,STD_PRELUDE)); + scriptName[0] = strCopy(findMPathname(NULL,STD_PRELUDE,hugsPath)); if (!scriptName[0]) { Printf("Prelude not found on current path: \"%s\"\n", hugsPath ? hugsPath : ""); fatal("Unable to load prelude"); } + if (haskell98) { + Printf("Haskell 98 mode: Restart with command line option -98 to enable extensions\n\n"); + } else { + Printf("Hugs mode: Restart with command line option +98 for Haskell 98 mode\n\n"); + } + everybody(INSTALL); evalModule = findText(""); /* evaluate wrt last module by default */ if (proj) { @@ -328,9 +321,13 @@ static Void local optionInfo() { /* Print information about command */ Printf(fmts,"rstr","Set repeat last expression string to str"); Printf(fmts,"Pstr","Set search path for modules to str"); Printf(fmts,"Estr","Use editor setting given by str"); + Printf(fmts,"cnum","Set constraint cutoff limit"); #if USE_PREPROCESSOR && (defined(HAVE_POPEN) || defined(HAVE__POPEN)) Printf(fmts,"Fstr","Set preprocessor filter to str"); #endif +#if PROFILING + Printf(fmts,"dnum","Gather profiling statistics every <num> reductions\n"); +#endif Printf("\nCurrent settings: "); togglesIn(TRUE); @@ -340,14 +337,26 @@ static Void local optionInfo() { /* Print information about command */ printString(prompt); Printf(" -r"); printString(repeatStr); + Printf(" -c%d",cutoff); Printf("\nSearch path : -P"); printString(hugsPath); +#if 0 +ToDo + if (projectPath!=NULL) { + Printf("\nProject Path : %s",projectPath); + } +#endif Printf("\nEditor setting : -E"); printString(hugsEdit); #if USE_PREPROCESSOR && (defined(HAVE_POPEN) || defined(HAVE__POPEN)) Printf("\nPreprocessor : -F"); printString(preprocessor); #endif +#if PROFILING + Printf("\nProfile interval: -d%d", profiling ? profInterval : 0); +#endif + Printf("\nCompatibility : %s", haskell98 ? "Haskell 98" + : "Hugs Extensions"); Putchar('\n'); } @@ -400,8 +409,12 @@ static String local optionsToStr() { /* convert options to string */ PUTStr('r',repeatStr); PUTStr('P',hugsPath); PUTStr('E',hugsEdit); + PUTInt('c',cutoff); PUTC(' '); #if USE_PREPROCESSOR && (defined(HAVE_POPEN) || defined(HAVE__POPEN)) PUTStr('F',preprocessor); +#endif +#if PROFILING + PUTInt('d',profiling ? profInterval : 0); #endif PUTC('\0'); return buffer; @@ -479,7 +492,17 @@ String s; { /* return FALSE if none found. */ return TRUE; } - default : toggleSet(*s,state); + default : if (strcmp("98",s)==0) { + if (heapBuilt() && ((state && !haskell98) || + (!state && haskell98))) { + FPrintf(stderr,"Haskell 98 compatibility cannot be changed while the interpreter is running\n"); + } else { + haskell98 = state; + } + return TRUE; + } else { + toggleSet(*s,state); + } break; } return TRUE; @@ -574,8 +597,9 @@ static struct cmd cmds[] = { {":reload", RELOAD}, {":gc", COLLECT}, {":edit", EDIT}, {":quit", QUIT}, {":set", SET}, {":find", FIND}, {":names", NAMES}, {":info", INFO}, {":project", PROJECT}, - {":module", SETMODULE}, - {":version", SHOWVERSION}, +#if !IGNORE_MODULES + {":module",SETMODULE}, +#endif {"", EVAL}, {0,0} }; @@ -590,10 +614,11 @@ static Void local menu() { Printf(":project <filename> use project file\n"); Printf(":edit <filename> edit file\n"); Printf(":edit edit last module\n"); +#if !IGNORE_MODULES Printf(":module <module> set module for evaluating expressions\n"); +#endif Printf("<expr> evaluate expression\n"); Printf(":type <expr> print type of expression\n"); - Printf(":version show Hugs version\n"); Printf(":? display this list of commands\n"); Printf(":set <options> set command line options\n"); Printf(":set help on command line options\n"); @@ -619,8 +644,10 @@ static Void local forHelp() { * Setting of command line options: * ------------------------------------------------------------------------*/ -struct options toggle[] = { /* List of command line toggles */ - {'t', "Print type after evaluation", &addType}, +struct options toggle[] = { /* List of command line toggles */ + {'s', "Print no. reductions/cells after eval", &showStats}, + {'t', "Print type after evaluation", &addType}, + /*ToDo?? {'f', "Terminate evaluation on first error", &failOnError},*/ {'g', "Print no. cells recovered after gc", &gcMessages}, {'l', "Literate modules as default", &literateScripts}, {'e', "Warn about errors in literate modules", &literateErrors}, @@ -722,9 +749,13 @@ Long len; { /* length of script file */ Printf("Reading file \"%s\":\n",fname); setLastEdit(fname,0); +#if 0 +ToDo: reinstate if (isInterfaceFile(fname)) { loadInterface(fname); - } else { + } else +#else + { needsImports = FALSE; parseScript(fname,len); /* process script file */ if (needsImports) @@ -733,6 +764,7 @@ Long len; { /* length of script file */ typeCheckDefns(); compileDefns(); } +#endif scriptFile = 0; return TRUE; } @@ -944,6 +976,7 @@ Int line; { * Read and evaluate an expression: * ------------------------------------------------------------------------*/ +#if !IGNORE_MODULES static Void local setModule(){/*set module in which to evaluate expressions*/ String s = readFilename(); if (!s) s = ""; /* :m clears the current module selection */ @@ -953,15 +986,16 @@ static Void local setModule(){/*set module in which to evaluate expressions*/ static Module local findEvalModule() { /*Module in which to eval expressions*/ Module m = findModule(evalModule); - if (isNull(m)) { + if (isNull(m)) m = lastModule(); - } return m; } +#endif static Void local evaluator() { /* evaluate expr and print value */ Type type, bd; - Kinds ks = NIL; + Kinds ks = NIL; + Cell temp = NIL; setCurrModule(findEvalModule()); scriptFile = 0; @@ -980,13 +1014,18 @@ static Void local evaluator() { /* evaluate expr and print value */ if (whatIs(bd)==QUAL) { ERRMSG(0) "Unresolved overloading" ETHEN - ERRTEXT "\n*** type : " ETHEN ERRTYPE(type); - ERRTEXT "\n*** expression : " ETHEN ERREXPR(inputExpr); + ERRTEXT "\n*** Type : " ETHEN ERRTYPE(type); + ERRTEXT "\n*** Expression : " ETHEN ERREXPR(inputExpr); ERRTEXT "\n" EEND; } - - /* ToDo: restore the code to print types, use show, etc */ + +#if PROFILING + if (profiling) + profilerLog("profile.hp"); + numReductions = 0; + garbageCollect(); +#endif #ifdef WANT_TIMER updateTimers(); @@ -1015,6 +1054,24 @@ static Void local evaluator() { /* evaluate expr and print value */ } } +static Void local stopAnyPrinting() { /* terminate printing of expression,*/ + if (printing) { /* after successful termination or */ + printing = FALSE; /* runtime error (e.g. interrupt) */ + Putchar('\n'); + if (showStats) { +#define plural(v) v, (v==1?"":"s") + /* Printf("(%lu reduction%s, ",plural(numReductions)); */ + Printf("%lu cell%s",plural(numCells)); + if (numGcs>0) + Printf(", %u garbage collection%s",plural(numGcs)); + Printf(")\n"); +#undef plural + } + FlushStdout(); + garbageCollect(); + } +} + /* -------------------------------------------------------------------------- * Print type of input expression: * ------------------------------------------------------------------------*/ @@ -1040,47 +1097,55 @@ static Void local showtype() { /* print type of expression (if any)*/ * about an object. * ------------------------------------------------------------------------*/ -static String local objToStr Args((Module, Cell)); - static String local objToStr(m,c) Module m; Cell c; { -#if DISPLAY_QUANTIFIERS +#if 1 || DISPLAY_QUANTIFIERS static char newVar[60]; switch (whatIs(c)) { - case NAME : if (m == name(c).mod) { - sprintf(newVar,"%s", textToStr(name(c).text)); - } else { - sprintf(newVar,"%s.%s",textToStr(module(name(c).mod).text), - textToStr(name(c).text)); - } - break; - case TYCON : if (m == tycon(c).mod) { - sprintf(newVar,"%s", textToStr(tycon(c).text)); - } else { - sprintf(newVar,"%s.%s",textToStr(module(tycon(c).mod).text), - textToStr(tycon(c).text)); - } - break; - case CLASS : if (m == cclass(c).mod) { - sprintf(newVar,"%s", textToStr(cclass(c).text)); - } else { - sprintf(newVar,"%s.%s",textToStr(module(cclass(c).mod).text), - textToStr(cclass(c).text)); - } - break; - default : internal("objToStr"); + case NAME : if (m == name(c).mod) { + sprintf(newVar,"%s", textToStr(name(c).text)); + } else { + sprintf(newVar,"%s.%s", + textToStr(module(name(c).mod).text), + textToStr(name(c).text)); + } + break; + + case TYCON : if (m == tycon(c).mod) { + sprintf(newVar,"%s", textToStr(tycon(c).text)); + } else { + sprintf(newVar,"%s.%s", + textToStr(module(tycon(c).mod).text), + textToStr(tycon(c).text)); + } + break; + + case CLASS : if (m == cclass(c).mod) { + sprintf(newVar,"%s", textToStr(cclass(c).text)); + } else { + sprintf(newVar,"%s.%s", + textToStr(module(cclass(c).mod).text), + textToStr(cclass(c).text)); + } + break; + + default : internal("objToStr"); } return newVar; #else static char newVar[33]; switch (whatIs(c)) { - case NAME : sprintf(newVar,"%s", textToStr(name(c).text)); - break; - case TYCON : sprintf(newVar,"%s", textToStr(tycon(c).text)); - break; - case CLASS : sprintf(newVar,"%s", textToStr(cclass(c).text)); - default : internal("objToStr"); + case NAME : sprintf(newVar,"%s", textToStr(name(c).text)); + break; + + case TYCON : sprintf(newVar,"%s", textToStr(tycon(c).text)); + break; + + case CLASS : sprintf(newVar,"%s", textToStr(cclass(c).text)); + break; + + default : internal("objToStr"); } return newVar; #endif @@ -1102,17 +1167,17 @@ static Void local info() { /* describe objects */ static Void local describe(t) /* describe an object */ Text t; { - Tycon tc = findTycon(t); - Class cl = findClass(t); - Name nm = findName(t); + Tycon tc = findTycon(t); + Class cl = findClass(t); + Name nm = findName(t); Module mod = findEvalModule(); if (nonNull(tc)) { /* as a type constructor */ - Type ty = tc; + Type t = tc; Int i; Inst in; for (i=0; i<tycon(tc).arity; ++i) { - ty = ap(ty,mkOffset(i)); + t = ap(t,mkOffset(i)); } Printf("-- type constructor"); if (kindExpert) { @@ -1122,7 +1187,7 @@ Text t; { Putchar('\n'); switch (tycon(tc).what) { case SYNONYM : Printf("type "); - printType(stdout,ty); + printType(stdout,t); Printf(" = "); printType(stdout,tycon(tc).defn); break; @@ -1134,9 +1199,11 @@ Text t; { } else { Printf("newtype "); } - printType(stdout,ty); + printType(stdout,t); + Putchar('\n'); + mapProc(printSyntax,cs); if (hasCfun(cs)) { - Printf("\n\n-- constructors:"); + Printf("\n-- constructors:"); } for (; hasCfun(cs); cs=tl(cs)) { Putchar('\n'); @@ -1145,7 +1212,7 @@ Text t; { printType(stdout,name(hd(cs)).type); } if (nonNull(cs)) { - Printf("\n\n-- selectors:"); + Printf("\n-- selectors:"); } for (; nonNull(cs); cs=tl(cs)) { Putchar('\n'); @@ -1157,7 +1224,7 @@ Text t; { break; case RESTRICTSYN : Printf("type "); - printType(stdout,ty); + printType(stdout,t); Printf(" = <restricted>"); break; } @@ -1176,28 +1243,30 @@ Text t; { List ins = cclass(cl).instances; Kinds ks = cclass(cl).kinds; if (nonNull(ks) && isNull(tl(ks)) && hd(ks)==STAR) { - printf("-- type class"); + Printf("-- type class"); } else { - printf("-- constructor class"); + Printf("-- constructor class"); if (kindExpert) { - printf(" with arity "); + Printf(" with arity "); printKinds(stdout,ks); } } - printf("\nclass "); + Putchar('\n'); + mapProc(printSyntax,cclass(cl).members); + Printf("class "); if (nonNull(cclass(cl).supers)) { printContext(stdout,cclass(cl).supers); - printf(" => "); + Printf(" => "); } printPred(stdout,cclass(cl).head); if (nonNull(cclass(cl).members)) { List ms = cclass(cl).members; - printf(" where"); + Printf(" where"); do { Type t = monotypeOf(name(hd(ms)).type); - printf("\n "); + Printf("\n "); printExp(stdout,hd(ms)); - printf(" :: "); + Printf(" :: "); if (isNull(tl(fst(snd(t))))) { t = snd(snd(t)); } else { @@ -1207,37 +1276,41 @@ Text t; { ms = tl(ms); } while (nonNull(ms)); } - putchar('\n'); + Putchar('\n'); if (nonNull(ins)) { - printf("\n-- instances:\n"); + Printf("\n-- instances:\n"); do { showInst(hd(ins)); ins = tl(ins); } while (nonNull(ins)); } - putchar('\n'); + Putchar('\n'); } if (nonNull(nm)) { /* as a function/name */ + printSyntax(nm); printExp(stdout,nm); - printf(" :: "); + Printf(" :: "); if (nonNull(name(nm).type)) { printType(stdout,name(nm).type); } else { - printf("<unknown type>"); + Printf("<unknown type>"); } if (isCfun(nm)) { - printf(" -- data constructor"); + Printf(" -- data constructor"); } else if (isMfun(nm)) { - printf(" -- class member"); + Printf(" -- class member"); } else if (isSfun(nm)) { - printf(" -- selector function"); + Printf(" -- selector function"); } - if (name(nm).primop) { - printf(" -- primitive"); +#if 0 + ToDo: reinstate + if (name(nm).primDef) { + Printf(" -- primitive"); } - printf("\n\n"); +#endif + Printf("\n\n"); } if (isNull(tc) && isNull(cl) && isNull(nm)) { @@ -1245,15 +1318,37 @@ Text t; { } } +static Void local printSyntax(nm) +Name nm; { + Syntax sy = syntaxOf(nm); + Text t = name(nm).text; + String s = textToStr(t); + if (sy != defaultSyntax(t)) { + Printf("infix"); + switch (assocOf(sy)) { + case LEFT_ASS : Putchar('l'); break; + case RIGHT_ASS : Putchar('r'); break; + case NON_ASS : break; + } + Printf(" %i ",precOf(sy)); + if (isascii(*s) && isalpha(*s)) { + Printf("`%s`",s); + } else { + Printf("%s",s); + } + Putchar('\n'); + } +} + static Void local showInst(in) /* Display instance decl header */ Inst in; { - printf("instance "); + Printf("instance "); if (nonNull(inst(in).specifics)) { printContext(stdout,inst(in).specifics); - printf(" => "); + Printf(" => "); } printPred(stdout,inst(in).head); - putchar('\n'); + Putchar('\n'); } /* -------------------------------------------------------------------------- @@ -1367,12 +1462,11 @@ String argv[]; { break; case PROJECT: project(); break; +#if !IGNORE_MODULES case SETMODULE : setModule(); break; - case SHOWVERSION : - Printf("Hugs 1.4, %s release.\n", HUGS_VERSION); - break; +#endif case EVAL : evaluator(); break; case TYPEOF : showtype(); @@ -1385,7 +1479,7 @@ String argv[]; { break; case SET : set(); break; - case SYSTEM : if (shellEsc(readLine())) + case SYSTEM : if (shellEsc(readLine())) Printf("Warning: Shell escape terminated abnormally\n"); break; case CHGDIR : changeDir(); @@ -1407,6 +1501,7 @@ String argv[]; { millisecs(userElapsed), millisecs(systElapsed)); #endif } + breakOn(FALSE); } /* -------------------------------------------------------------------------- @@ -1487,6 +1582,7 @@ static Void local failed() { /* Goal cannot be reached due to */ Void errHead(l) /* print start of error message */ Int l; { failed(); /* failed to reach target ... */ + stopAnyPrinting(); FPrintf(errorStream,"ERROR"); if (scriptFile) { @@ -1507,7 +1603,8 @@ Void errFail() { /* terminate error message and */ Void errAbort() { /* altern. form of error handling */ failed(); /* used when suitable error message*/ - errFail(); /* has already been printed */ + stopAnyPrinting(); /* has already been printed */ + errFail(); } Void internal(msg) /* handle internal error */ @@ -1518,6 +1615,7 @@ String msg; { MessageBox(hWndMain, buf, appName, MB_ICONHAND | MB_OK); #endif failed(); + stopAnyPrinting(); Printf("INTERNAL ERROR: %s\n",msg); FlushStdout(); longjmp(catch_error,1); @@ -1543,9 +1641,11 @@ sigHandler(breakHandler) { /* respond to break interrupt */ Hilite(); Printf("{Interrupted!}\n"); Lolite(); - breakOn(TRUE); + breakOn(TRUE); /* reinstall signal handler - redundant on BSD systems */ + /* but essential on POSIX (and other?) systems */ everybody(BREAK); failed(); + stopAnyPrinting(); FlushStdout(); clearerr(stdin); longjmp(catch_error,1); @@ -1745,6 +1845,25 @@ FILE* fp; { } #endif /* REDIRECT_OUTPUT && !HUGS_FOR_WINDOWS */ +/* -------------------------------------------------------------------------- + * Send message to each component of system: + * ------------------------------------------------------------------------*/ + +Void everybody(what) /* send command `what' to each component of*/ +Int what; { /* system to respond as appropriate ... */ + machdep(what); /* The order of calling each component is */ + storage(what); /* important for the INSTALL command */ + substitution(what); + input(what); + linkControl(what); + staticAnalysis(what); + deriveControl(what); + typeChecker(what); + translateControl(what); + compiler(what); + codegen(what); +} + /* -------------------------------------------------------------------------- * Hugs for Windows code (WinMain and related functions) diff --git a/ghc/interpreter/input.c b/ghc/interpreter/input.c index 94e8542f0193..5294b350ad15 100644 --- a/ghc/interpreter/input.c +++ b/ghc/interpreter/input.c @@ -1,34 +1,28 @@ -/* -*- mode: hugs-c; -*- */ + /* -------------------------------------------------------------------------- * Input functions, lexical analysis parsing etc... * - * Copyright (c) The University of Nottingham and Yale University, 1994-1997. - * All rights reserved. See NOTICE for details and conditions of use etc... - * Hugs version 1.4, December 1997 + * Hugs 98 is Copyright (c) Mark P Jones, Alastair Reid and the Yale + * Haskell Group 1994-99, and is distributed as Open Source software + * under the Artistic License; see the file "Artistic" that is included + * in the distribution for details. * * $RCSfile: input.c,v $ - * $Revision: 1.2 $ - * $Date: 1998/12/02 13:22:12 $ + * $Revision: 1.3 $ + * $Date: 1999/02/03 17:08:30 $ * ------------------------------------------------------------------------*/ #include "prelude.h" #include "storage.h" +#include "backend.h" #include "connect.h" -#include "charset.h" -#include "input.h" -#include "static.h" -#include "interface.h" #include "command.h" #include "errors.h" -#include "link.h" -#include "hugs.h" /* for target */ #include <ctype.h> #if HAVE_GETDELIM_H #include "getdelim.h" #endif -#include "machdep.h" /* for findPathname */ - #if HUGS_FOR_WINDOWS #undef IN #endif @@ -40,7 +34,6 @@ List tyconDefns = NIL; /* type constructor definitions */ List typeInDefns = NIL; /* type synonym restrictions */ List valDefns = NIL; /* value definitions in script */ -List opDefns = NIL; /* operator defns in script */ List classDefns = NIL; /* class defns in script */ List instDefns = NIL; /* instance defns in script */ List selDefns = NIL; /* list of selector lists */ @@ -66,6 +59,7 @@ String preprocessor = 0; * Local function prototypes: * ------------------------------------------------------------------------*/ +static Void local initCharTab Args((Void)); static Void local fileInput Args((String,Long)); static Bool local literateMode Args((String)); static Bool local linecmp Args((String,String)); @@ -122,41 +116,106 @@ static Text textBar, textMinus, textFrom, textArrow, textLazy; static Text textBang, textDot, textAll, textImplies; static Text textWildcard; -static Text textModule, textImport, textPrelude, textPreludeHugs; +static Text textModule, textImport; static Text textHiding, textQualified, textAsMod; static Text textExport, textInterface, textRequires, textUnsafe; -#if NPLUSK +Text textNum; /* Num */ +Text textPrelude; /* Prelude */ Text textPlus; /* (+) */ -#endif -Cell conPrelude; /* Prelude */ static Cell conMain; /* Main */ static Cell varMain; /* main */ -static Cell conUnit; /* () */ -static Cell conList; /* [] */ -static Cell conNil; /* [] */ -static Cell conPreludeUnit; /* Prelude.() */ -static Cell conPreludeList; /* Prelude.[] */ -static Cell conPreludeNil; /* Prelude.[] */ - static Cell varMinus; /* (-) */ +static Cell varPlus; /* (+) */ static Cell varBang; /* (!) */ static Cell varDot; /* (.) */ static Cell varHiding; /* hiding */ static Cell varQualified; /* qualified */ static Cell varAsMod; /* as */ -static Cell varNegate; -static Cell varFlip; -static Cell varEnumFrom; -static Cell varEnumFromThen; -static Cell varEnumFromTo; -static Cell varEnumFromThenTo; - static List imps; /* List of imports to be chased */ + +/* -------------------------------------------------------------------------- + * Character set handling: + * + * Hugs follows Haskell 1.3 in assuming that input uses the ISO-8859-1 + * character set. The following code provides methods for classifying + * input characters according to the lexical structure specified by the + * report. Hugs should still accept older programs because ASCII is + * essentially just a subset of the ISO character set. + * + * Notes: If you want to port Hugs to a machine that uses something + * substantially different from the ISO character set, then you will need + * to insert additional code to map between character sets. + * + * At some point, the following data structures may be exported in a .h + * file to allow the information contained here to be picked up in the + * implementation of LibChar is* primitives. + * + * Relies, implicitly but for this comment, on assumption that NUM_CHARS=256. + * ------------------------------------------------------------------------*/ + +static Bool charTabBuilt; +static unsigned char ctable[NUM_CHARS]; +#define isIn(c,x) (ctable[(unsigned char)(c)]&(x)) +#define isISO(c) (0<=(c) && (c)<NUM_CHARS) + +#define DIGIT 0x01 +#define SMALL 0x02 +#define LARGE 0x04 +#define SYMBOL 0x08 +#define IDAFTER 0x10 +#define SPACE 0x20 +#define PRINT 0x40 + +static Void local initCharTab() { /* Initialize char decode table */ +#define setRange(x,f,t) {Int i=f; while (i<=t) ctable[i++] |=x;} +#define setChar(x,c) ctable[c] |= (x) +#define setChars(x,s) {char *p=s; while (*p) ctable[(Int)*p++]|=x;} +#define setCopy(x,c) {Int i; \ + for (i=0; i<NUM_CHARS; ++i) \ + if (isIn(i,c)) \ + ctable[i]|=x; \ + } + + setRange(DIGIT, '0','9'); /* ASCII decimal digits */ + + setRange(SMALL, 'a','z'); /* ASCII lower case letters */ + setRange(SMALL, 223,246); /* ISO lower case letters */ + setRange(SMALL, 248,255); /* (omits division symbol, 247) */ + setChar (SMALL, '_'); + + setRange(LARGE, 'A','Z'); /* ASCII upper case letters */ + setRange(LARGE, 192,214); /* ISO upper case letters */ + setRange(LARGE, 216,222); /* (omits multiplication, 215) */ + + setRange(SYMBOL, 161,191); /* Symbol characters + ':' */ + setRange(SYMBOL, 215,215); + setChar (SYMBOL, 247); + setChars(SYMBOL, ":!#$%&*+./<=>?@\\^|-~"); + + setChar (IDAFTER, '\''); /* Characters in identifier */ + setCopy (IDAFTER, (DIGIT|SMALL|LARGE)); + + setChar (SPACE, ' '); /* ASCII space character */ + setChar (SPACE, 160); /* ISO non breaking space */ + setRange(SPACE, 9,13); /* special whitespace: \t\n\v\f\r */ + + setChars(PRINT, "(),;[]_`{}"); /* Special characters */ + setChars(PRINT, " '\""); /* Space and quotes */ + setCopy (PRINT, (DIGIT|SMALL|LARGE|SYMBOL)); + + charTabBuilt = TRUE; +#undef setRange +#undef setChar +#undef setChars +#undef setCopy +} + + /* -------------------------------------------------------------------------- * Single character input routines: * @@ -186,11 +245,11 @@ static String nextStringChar; /* next char in string buffer */ #if USE_READLINE /* for command line editors */ static String currentLine; /* editline or GNU readline */ static String nextChar; -#define nextConsoleChar() (unsigned char)(*nextChar=='\0' ? '\n' : *nextChar++) -extern Void add_history Args((String)); -extern String readline Args((String)); +#define nextConsoleChar() (unsigned char)(*nextChar=='\0' ? '\n' : *nextChar++) +extern Void add_history Args((String)); +extern String readline Args((String)); #else -#define nextConsoleChar() getc(stdin) +#define nextConsoleChar() getc(stdin) #endif static Int litLines; /* count defn lines in lit script */ @@ -266,12 +325,17 @@ String nm; /* named file (specified length is */ Long len; { /* used to set target for reading) */ #if USE_PREPROCESSOR && (defined(HAVE_POPEN) || defined(HAVE__POPEN)) if (preprocessor) { - char cmd[100]; - strncpy(cmd,preprocessor,100); - strncat(cmd," ",100); - strncat(cmd,nm,100); - cmd[99] = '\0'; /* paranoia */ + Int reallen = strlen(preprocessor) + 1 + strlen(nm) + 1; + char *cmd = malloc(reallen); + if (cmd == NULL) { + ERRMSG(0) "Unable to allocate memory for filter command." + EEND; + } + strcpy(cmd,preprocessor); + strcat(cmd," "); + strcat(cmd,nm); inputStream = popen(cmd,"r"); + free(cmd); } else { inputStream = fopen(nm,"r"); } @@ -312,9 +376,11 @@ String s; { row = 1; nextStringChar = s; + if (!charTabBuilt) + initCharTab(); } -static Bool local literateMode(nm) /* select literate mode for file */ +static Bool local literateMode(nm) /* Select literate mode for file */ String nm; { char *dot = strrchr(nm,'.'); /* look for last dot in file name */ if (dot) { @@ -327,12 +393,6 @@ String nm; { return literateScripts; /* otherwise, use the default */ } -Bool isInterfaceFile(nm) /* is nm an interface file? */ -String nm; { - char *dot = strrchr(nm,'.'); /* look for last dot in file name */ - return (dot && filenamecmp(dot+1,"myhi")==0); -} - /* This code originally came from Sigbjorn Finne (sof@dcs.gla.ac.uk). * I've removed the loop (since newLineSkip contains a loop too) and @@ -508,7 +568,7 @@ static Void local newlineSkip() { /* skip `\n' (supports lit scripts) */ litLines++; return; } - while (c0==' ' || c0=='\t')/* maybe line is blank? */ + while (c0 != '\n' && isIn(c0,SPACE)) /* maybe line is blank? */ skip(); if (c0=='\n' || c0==EOF) thisLineIs(BLANKLINE); @@ -566,7 +626,7 @@ static Void local closeAnyInput() { /* Close input stream, if open, */ * entry to the routine. * ------------------------------------------------------------------------*/ -#define MAX_TOKEN 500 +#define MAX_TOKEN 4000 #define startToken() tokPos = 0 #define saveTokenChar(c) if (tokPos<=MAX_TOKEN) saveChar(c); else ++tokPos #define saveChar(c) tokenStr[tokPos++]=(char)(c) @@ -610,29 +670,43 @@ static Text local readIdent() { /* read identifier */ static Cell local readRadixNumber(r) /* Read literal in specified radix */ Int r; { /* from input of the form 0c{digs} */ Int d; - startToken(); - saveTokenChar(c0); skip(); /* skip leading zero */ - if ((d=readHexDigit(c1))<0 || d>=r) { - /* Special case; no digits, lex as */ - /* if it had been written "0 c..." */ - saveTokenChar('0'); - } else { + if ((d=readHexDigit(c1))<0 || d>=r)/* Special case; no digits, lex as */ + return mkInt(0); /* if it had been written "0 c..." */ + else { Int n = 0; - saveTokenChar(c0); +#if BIGNUMS + Cell big = NIL; +#endif skip(); do { - saveTokenChar(c0); +#if BIGNUMS + if (nonNull(big)) + big = bigShift(big,d,r); + else if (overflows(n,r,d,MAXPOSINT)) + big = bigShift(bigInt(n),d,r); + else +#else + if (overflows(n,r,d,MAXPOSINT)) { + ERRMSG(row) "Integer literal out of range" + EEND; + } + else +#endif + n = r*n + d; skip(); d = readHexDigit(c0); } while (d>=0 && d<r); +#if BIGNUMS + return nonNull(big) ? big : mkInt(n); +#else + return mkInt(n); +#endif } - endToken(); - /* ToDo: return an INTCELL if small enough */ - return stringToBignum(tokenStr); } static Cell local readNumber() { /* read numeric constant */ + Int n = 0; Bool intTooLarge = FALSE; if (c0=='0') { @@ -644,14 +718,23 @@ static Cell local readNumber() { /* read numeric constant */ startToken(); do { + if (overflows(n,10,(c0-'0'),MAXPOSINT)) + intTooLarge = TRUE; + n = 10*n + (c0-'0'); saveTokenChar(c0); skip(); } while (isISO(c0) && isIn(c0,DIGIT)); if (c0!='.' || !isISO(c1) || !isIn(c1,DIGIT)) { endToken(); - /* ToDo: return an INTCELL if small enough */ - return stringToBignum(tokenStr); + if (!intTooLarge) + return mkInt(n); +#if BIGNUMS + return bigStr(tokenStr); +#else + ERRMSG(row) "Integer literal out of range" + EEND; +#endif } saveTokenChar(c0); /* save decimal point */ @@ -684,7 +767,12 @@ static Cell local readNumber() { /* read numeric constant */ } endToken(); - return stringToFloat(tokenStr); +#ifndef HAVE_LIBM + ERRMSG(row) "No floating point numbers in this implementation" + EEND; +#endif + + return mkFloat(stringToFloat(tokenStr)); } static Cell local readChar() { /* read character constant */ @@ -984,7 +1072,8 @@ String s; { /* escapes if any parts need them */ if (s) { String t = s; Char c; - while ((c = *t)!=0 && isISO(c) && isIn(c,PRINT) && c!='"' && !isIn(c,SPACE)) { + while ((c = *t)!=0 && isISO(c) + && isIn(c,PRINT) && c!='"' && !isIn(c,SPACE)) { t++; } if (*t) { @@ -999,7 +1088,7 @@ String s; { /* escapes if any parts need them */ } /* ------------------------------------------------------------------------- - * Handle special types of input for us in interpreter: + * Handle special types of input for use in interpreter: * -----------------------------------------------------------------------*/ Command readCommand(cmds,start,sys) /* read command at start of input */ @@ -1056,8 +1145,9 @@ String readFilename() { /* Read filename from input (if any)*/ skip(); while (c0!=EOF && c0!='\"') { Cell c = readAChar(TRUE); - if (nonNull(c)) + if (nonNull(c)) { saveTokenChar(charOf(c)); + } } if (c0=='"') skip(); @@ -1211,10 +1301,11 @@ static Int local yylex() { /* Read next input token ... */ push(yylval = mkInt(row)); /* default token value is line no. */ /* subsequent changes to yylval must also set top() to the same value */ - if (indentDepth>=0) /* layout rule(s) active ? */ + if (indentDepth>=0) { /* layout rule(s) active ? */ if (insertedToken) /* avoid inserting multiple `;'s */ insertedToken = FALSE; /* or putting `;' after `{' */ - else if (layout[indentDepth]!=HARD) + else + if (layout[indentDepth]!=HARD) { if (column<layout[indentDepth]) { unOffside(); return '}'; @@ -1223,6 +1314,8 @@ static Int local yylex() { /* Read next input token ... */ insertedToken = TRUE; return ';'; } + } + } /* ---------------------------------------------------------------------- * Now try to identify token type: @@ -1260,8 +1353,8 @@ static Int local yylex() { /* Read next input token ... */ } #if TREX - if (c0=='#' && isIn(c1,SMALL)) { /* Look for record selector name */ - Text it; + if (c0=='#' && isIn(c1,SMALL) && !haskell98) { + Text it; /* Look for record selector name */ skip(); it = readIdent(); top() = yylval = ap(RECSEL,mkExt(it)); @@ -1295,9 +1388,9 @@ static Int local yylex() { /* Read next input token ... */ } else { top() = yylval = mkCon(it); return identType; - } /* We could easily keep a record of*/ - } /* the qualifying name here ... */ - if (isIn(c0,(SMALL|LARGE)) || c0 == '_') { + } + } + if (isIn(c0,(SMALL|LARGE))) { Text it = readIdent(); if (it==textCase) return CASEXP; @@ -1310,7 +1403,7 @@ static Int local yylex() { /* Read next input token ... */ if (it==textWhere) lookAhead(WHERE); if (it==textLet) lookAhead(LET); if (it==textIn) return IN; - if (it==textInfix) return INFIX; + if (it==textInfix) return INFIXN; if (it==textInfixl) return INFIXL; if (it==textInfixr) return INFIXR; if (it==textForeign) return FOREIGN; @@ -1321,16 +1414,14 @@ static Int local yylex() { /* Read next input token ... */ if (it==textDo) lookAhead(DO); if (it==textClass) return TCLASS; if (it==textInstance) return TINSTANCE; - if (it==textModule) return MODULETOK; - if (it==textInterface) return INTERFACE; - if (it==textRequires) return REQUIRES; + if (it==textModule) return TMODULE; if (it==textImport) return IMPORT; if (it==textExport) return EXPORT; if (it==textHiding) return HIDING; if (it==textQualified) return QUALIFIED; if (it==textAsMod) return ASMOD; if (it==textWildcard) return '_'; - if (it==textAll) return ALL; + if (it==textAll && !haskell98) return ALL; if (it==textRepeat && reading==KEYBOARD) return repeatLast(); @@ -1349,6 +1440,7 @@ static Int local yylex() { /* Read next input token ... */ if (it==textBar) return '|'; if (it==textFrom) return FROM; if (it==textMinus) return '-'; + if (it==textPlus) return '+'; if (it==textBang) return '!'; if (it==textDot) return '.'; if (it==textArrow) return ARROW; @@ -1379,6 +1471,19 @@ static Int local repeatLast() { /* Obtain last expression entered */ return REPEAT; } +Syntax defaultSyntax(t) /* Find default syntax of var named*/ +Text t; { /* by t ... */ + String s = textToStr(t); + return isIn(s[0],SYMBOL) ? DEF_OPSYNTAX : APPLIC; +} + +Syntax syntaxOf(n) /* Find syntax for name */ +Name n; { + if (name(n).syntax==NO_SYNTAX) /* Return default if no syntax set */ + return defaultSyntax(name(n).text); + return name(n).syntax; +} + /* -------------------------------------------------------------------------- * main entry points to parser/lexer: * ------------------------------------------------------------------------*/ @@ -1394,24 +1499,57 @@ Int startWith; { /* determining whether to read a */ EEND; /* in the parser... */ } drop(); - assert(stackEmpty()); /* stack should now be empty */ + if (!stackEmpty()) /* stack should now be empty */ + internal("parseInput"); } -Void parseScript(nm,len) /* Read a script */ -String nm; -Long len; { /* Used to set a target for reading */ +#ifdef HSCRIPT +static String memPrefix = "@mem@"; +static Int lenMemPrefix = 5; /* strlen(memPrefix)*/ + +Void makeMemScript(mem,fname) +String mem; +String fname; { + strcat(fname,memPrefix); + itoa((int)mem, fname+strlen(fname), 10); +} + +Bool isMemScript(fname) +String fname; { + return (strstr(fname,memPrefix) != NULL); +} + +String memScriptString(fname) +String fname; { + String p = strstr(fname,memPrefix); + if (p) { + return (String)atoi(p+lenMemPrefix); + } else { + return NULL; + } +} + +Void parseScript(fname,len) /* Read a script, possibly from mem */ +String fname; +Long len; { input(RESET); - fileInput(nm,len); + if (isMemScript(fname)) { + char* s = memScriptString(fname); + stringInput(s); + } else { + fileInput(fname,len); + } parseInput(SCRIPT); } - -Void parseInterface(nm,len) /* Read a GHC interface file */ +#else +Void parseScript(nm,len) /* Read a script */ String nm; Long len; { /* Used to set a target for reading */ input(RESET); fileInput(nm,len); - parseInput(INTERFACE); + parseInput(SCRIPT); } +#endif Void parseExp() { /* Read an expression to evaluate */ parseInput(EXPR); @@ -1454,26 +1592,24 @@ Int what; { textLambda = findText("\\"); textBar = findText("|"); textMinus = findText("-"); + textPlus = findText("+"); textFrom = findText("<-"); textArrow = findText("->"); textLazy = findText("~"); textBang = findText("!"); textDot = findText("."); textImplies = findText("=>"); -#if NPLUSK - textPlus = findText("+"); -#endif + textPrelude = findText("Prelude"); + textNum = findText("Num"); textModule = findText("module"); - textInterface = findText("__interface"); - textRequires = findText("__requires"); textImport = findText("import"); - textExport = findText("__export"); textHiding = findText("hiding"); textQualified = findText("qualified"); textAsMod = findText("as"); textWildcard = findText("_"); textAll = findText("forall"); varMinus = mkVar(textMinus); + varPlus = mkVar(textPlus); varBang = mkVar(textBang); varDot = mkVar(textDot); varHiding = mkVar(textHiding); @@ -1481,22 +1617,6 @@ Int what; { varAsMod = mkVar(textAsMod); conMain = mkCon(findText("Main")); varMain = mkVar(findText("main")); - textPrelude = findText("Prelude"); - textPreludeHugs= findText("PreludeBuiltin"); - conPrelude = mkCon(textPrelude); - conNil = mkCon(findText("[]")); - conList = mkCon(findText("[]")); - conUnit = mkCon(findText("()")); - conPreludeNil = mkQCon(textPreludeHugs,findText("[]")); - conPreludeList = mkQCon(textPreludeHugs,findText("[]")); - conPreludeUnit = mkQCon(textPreludeHugs,findText("()")); - varNegate = mkQVar(textPreludeHugs,findText("negate")); - varFlip = mkQVar(textPreludeHugs,findText("flip")); - varEnumFrom = mkQVar(textPreludeHugs,findText("enumFrom")); - varEnumFromThen = mkQVar(textPreludeHugs,findText("enumFromThen")); - varEnumFromTo = mkQVar(textPreludeHugs,findText("enumFromTo")); - varEnumFromThenTo = mkQVar(textPreludeHugs,findText("enumFromThenTo")); - evalDefaults = NIL; input(RESET); @@ -1505,11 +1625,11 @@ Int what; { case RESET : tyconDefns = NIL; typeInDefns = NIL; valDefns = NIL; - opDefns = NIL; classDefns = NIL; instDefns = NIL; selDefns = NIL; genDefns = NIL; + //primDefns = NIL; unqualImports= NIL; foreignImports= NIL; foreignExports= NIL; @@ -1527,11 +1647,11 @@ Int what; { case MARK : mark(tyconDefns); mark(typeInDefns); mark(valDefns); - mark(opDefns); mark(classDefns); mark(instDefns); mark(selDefns); mark(genDefns); + //mark(primDefns); mark(unqualImports); mark(foreignImports); mark(foreignExports); @@ -1539,26 +1659,14 @@ Int what; { mark(evalDefaults); mark(inputExpr); mark(varMinus); - mark(varNegate); - mark(varFlip); - mark(varEnumFrom); - mark(varEnumFromThen); - mark(varEnumFromTo); - mark(varEnumFromThenTo); + mark(varPlus); mark(varBang); mark(varDot); mark(varHiding); mark(varQualified); mark(varAsMod); mark(varMain); - mark(conPrelude); mark(conMain); - mark(conNil); - mark(conList); - mark(conUnit); - mark(conPreludeNil); - mark(conPreludeList); - mark(conPreludeUnit); mark(imps); break; } diff --git a/ghc/interpreter/lift.c b/ghc/interpreter/lift.c index 3ea95d8c049c..4649901712da 100644 --- a/ghc/interpreter/lift.c +++ b/ghc/interpreter/lift.c @@ -1,4 +1,4 @@ -/* -*- mode: hugs-c; -*- */ + /* -------------------------------------------------------------------------- * Lambda Lifter * @@ -10,19 +10,16 @@ * Hugs version 1.4, December 1997 * * $RCSfile: lift.c,v $ - * $Revision: 1.2 $ - * $Date: 1998/12/02 13:22:17 $ + * $Revision: 1.3 $ + * $Date: 1999/02/03 17:08:31 $ * ------------------------------------------------------------------------*/ #include "prelude.h" #include "storage.h" +#include "backend.h" #include "connect.h" #include "errors.h" -#include "stg.h" -#include "lift.h" -#include "free.h" -#include "stgSubst.h" -/* #include "pp.h" */ + /* -------------------------------------------------------------------------- * Local function prototypes: diff --git a/ghc/interpreter/link.c b/ghc/interpreter/link.c index 13af689da93f..79d2bc6132e1 100644 --- a/ghc/interpreter/link.c +++ b/ghc/interpreter/link.c @@ -7,16 +7,14 @@ * Hugs version 1.4, December 1997 * * $RCSfile: link.c,v $ - * $Revision: 1.3 $ - * $Date: 1999/01/13 16:47:27 $ + * $Revision: 1.4 $ + * $Date: 1999/02/03 17:08:31 $ * ------------------------------------------------------------------------*/ #include "prelude.h" #include "storage.h" +#include "backend.h" #include "connect.h" -#include "static.h" -#include "translate.h" -#include "type.h" #include "errors.h" #include "Assembler.h" /* for asmPrimOps and AsmReps */ @@ -91,7 +89,7 @@ Class classFloating; Class classNum; Class classMonad; /* Monads and monads with a zero */ -Class classMonad0; +/*Class classMonad0;*/ List stdDefaults; /* standard default values */ @@ -138,6 +136,33 @@ Name nameInd; Name nameForce; +Name nameAnd; +Name nameHw; +Name nameConCmp; +Name nameCompAux; +Name nameEnFrTh; +Name nameEnFrTo; +Name nameEnFrom; +Name nameEnFrEn; +Name nameEnToEn; +Name nameEnInRng; +Name nameEnIndex; +Name nameEnRange; +Name nameRangeSize; +Name nameComp; +Name nameShowField; +Name nameApp; +Name nameShowParen; +Name nameReadParen; +Name nameLex; +Name nameReadField; +Name nameFlip; +Name nameFromTo; +Name nameFromThen; +Name nameFrom; +Name nameFromThenTo; +Name nameNegate; + /* these names are required before we've had a chance to do the right thing */ Name nameSel; Name nameUnsafeUnpackCString; @@ -184,9 +209,11 @@ Name nameMkMVar; /* MVar# -> MVar */ * * ------------------------------------------------------------------------*/ -static Tycon linkTycon( String s ); -static Tycon linkClass( String s ); -static Name linkName ( String s ); +static Tycon linkTycon ( String s ); +static Tycon linkClass ( String s ); +static Name linkName ( String s ); +static Void mkTypes (); + static Tycon linkTycon( String s ) { @@ -222,7 +249,7 @@ static Name linkName( String s ) static Name predefinePrim ( String s ); static Name predefinePrim ( String s ) { - Name nm = newName(findText(s)); + Name nm = newName(findText(s),NIL); name(nm).defn=PREDEFINED; return nm; } @@ -297,7 +324,7 @@ Void linkPreludeTC() { /* Hook to tycons and classes in */ classFloating = linkClass("Floating"); classNum = linkClass("Num"); classMonad = linkClass("Monad"); - classMonad0 = linkClass("MonadZero"); + /*classMonad0 = linkClass("MonadZero");*/ stdDefaults = NIL; stdDefaults = cons(typeDouble,stdDefaults); @@ -376,6 +403,17 @@ Void linkPreludeTC() { /* Hook to tycons and classes in */ } } +static Void mkTypes() +{ + arrow = fn(aVar,mkOffset(1)); + listof = ap(typeList,aVar); + predNum = ap(classNum,aVar); + predFractional = ap(classFractional,aVar); + predIntegral = ap(classIntegral,aVar); + predMonad = ap(classMonad,aVar); + /*predMonad0 = ap(classMonad0,aVar);*/ +} + Void linkPreludeCM() { /* Hook to cfuns and mfuns in */ static Bool initialised = FALSE; /* prelude when first loaded */ if (!initialised) { @@ -421,11 +459,13 @@ Void linkPreludeNames() { /* Hook to names defined in Prelude */ Text t = findText(asmPrimOps[i].name); Name n = findName(t); if (isNull(n)) { - n = newName(t); + n = newName(t,NIL); } name(n).line = 0; name(n).defn = NIL; - name(n).type = primType(asmPrimOps[i].monad,asmPrimOps[i].args,asmPrimOps[i].results); + name(n).type = primType(asmPrimOps[i].monad, + asmPrimOps[i].args, + asmPrimOps[i].results); name(n).arity = strlen(asmPrimOps[i].args); name(n).primop = &(asmPrimOps[i]); implementPrim(n); @@ -503,3 +543,189 @@ Int what; { } /*-------------------------------------------------------------------------*/ + + +#if 0 +--## this stuff from 98 +--## +--## +--## Void linkPreludeTC() { /* Hook to tycons and classes in */ +--## if (isNull(typeBool)) { /* prelude when first loaded */ +--## Int i; +--## +--## typeBool = findTycon(findText("Bool")); +--## typeChar = findTycon(findText("Char")); +--## typeString = findTycon(findText("String")); +--## typeInt = findTycon(findText("Int")); +--## typeInteger = findTycon(findText("Integer")); +--## typeDouble = findTycon(findText("Double")); +--## typeAddr = findTycon(findText("Addr")); +--## typeMaybe = findTycon(findText("Maybe")); +--## typeOrdering = findTycon(findText("Ordering")); +--## if (isNull(typeBool) || isNull(typeChar) || isNull(typeString) || +--## isNull(typeInt) || isNull(typeDouble) || isNull(typeInteger) || +--## isNull(typeAddr) || isNull(typeMaybe) || isNull(typeOrdering)) { +--## ERRMSG(0) "Prelude does not define standard types" +--## EEND; +--## } +--## stdDefaults = cons(typeInteger,cons(typeDouble,NIL)); +--## +--## classEq = findClass(findText("Eq")); +--## classOrd = findClass(findText("Ord")); +--## classIx = findClass(findText("Ix")); +--## classEnum = findClass(findText("Enum")); +--## classShow = findClass(findText("Show")); +--## classRead = findClass(findText("Read")); +--## #if EVAL_INSTANCES +--## classEval = findClass(findText("Eval")); +--## #endif +--## classBounded = findClass(findText("Bounded")); +--## if (isNull(classEq) || isNull(classOrd) || isNull(classRead) || +--## isNull(classShow) || isNull(classIx) || isNull(classEnum) || +--## #if EVAL_INSTANCES +--## isNull(classEval) || +--## #endif +--## isNull(classBounded)) { +--## ERRMSG(0) "Prelude does not define standard classes" +--## EEND; +--## } +--## +--## classReal = findClass(findText("Real")); +--## classIntegral = findClass(findText("Integral")); +--## classRealFrac = findClass(findText("RealFrac")); +--## classRealFloat = findClass(findText("RealFloat")); +--## classFractional = findClass(findText("Fractional")); +--## classFloating = findClass(findText("Floating")); +--## classNum = findClass(findText("Num")); +--## if (isNull(classReal) || isNull(classIntegral) || +--## isNull(classRealFrac) || isNull(classRealFloat) || +--## isNull(classFractional) || isNull(classFloating) || +--## isNull(classNum)) { +--## ERRMSG(0) "Prelude does not define numeric classes" +--## EEND; +--## } +--## predNum = ap(classNum,aVar); +--## predFractional = ap(classFractional,aVar); +--## predIntegral = ap(classIntegral,aVar); +--## +--## classMonad = findClass(findText("Monad")); +--## if (isNull(classMonad)) { +--## ERRMSG(0) "Prelude does not define Monad class" +--## EEND; +--## } +--## predMonad = ap(classMonad,aVar); +--## +--## #if IO_MONAD +--## { Type typeIO = findTycon(findText("IO")); +--## if (isNull(typeIO)) { +--## ERRMSG(0) "Prelude does not define IO monad constructor" +--## EEND; +--## } +--## typeProgIO = ap(typeIO,aVar); +--## } +--## #endif +--## +--## /* The following primitives are referred to in derived instances and +--## * hence require types; the following types are a little more general +--## * than we might like, but they are the closest we can get without a +--## * special datatype class. +--## */ +--## name(nameConCmp).type +--## = mkPolyType(starToStar,fn(aVar,fn(aVar,typeOrdering))); +--## name(nameEnRange).type +--## = mkPolyType(starToStar,fn(boundPair,listof)); +--## name(nameEnIndex).type +--## = mkPolyType(starToStar,fn(boundPair,fn(aVar,typeInt))); +--## name(nameEnInRng).type +--## = mkPolyType(starToStar,fn(boundPair,fn(aVar,typeBool))); +--## name(nameEnToEn).type +--## = mkPolyType(starToStar,fn(aVar,fn(typeInt,aVar))); +--## name(nameEnFrEn).type +--## = mkPolyType(starToStar,fn(aVar,typeInt)); +--## name(nameEnFrom).type +--## = mkPolyType(starToStar,fn(aVar,listof)); +--## name(nameEnFrTo).type +--## = name(nameEnFrTh).type +--## = mkPolyType(starToStar,fn(aVar,fn(aVar,listof))); +--## +--## #if EVAL_INSTANCES +--## addEvalInst(0,typeArrow,2,NIL); /* Add Eval instances for builtins */ +--## addEvalInst(0,typeList,1,NIL); +--## addEvalInst(0,typeUnit,0,NIL); +--## #endif +--## for (i=2; i<=NUM_DTUPLES; i++) {/* Add derived instances of tuples */ +--## #if EVAL_INSTANCES +--## addEvalInst(0,mkTuple(i),i,NIL); +--## #endif +--## addTupInst(classEq,i); +--## addTupInst(classOrd,i); +--## addTupInst(classShow,i); +--## addTupInst(classRead,i); +--## addTupInst(classIx,i); +--## } +--## } +--## } +--## +--## +--## static Void linkPreludeCM() { /* Hook to cfuns and mfuns in */ +--## if (isNull(nameFalse)) { /* prelude when first loaded */ +--## nameFalse = findName(findText("False")); +--## nameTrue = findName(findText("True")); +--## nameJust = findName(findText("Just")); +--## nameNothing = findName(findText("Nothing")); +--## nameLeft = findName(findText("Left")); +--## nameRight = findName(findText("Right")); +--## nameLT = findName(findText("LT")); +--## nameEQ = findName(findText("EQ")); +--## nameGT = findName(findText("GT")); +--## if (isNull(nameFalse) || isNull(nameTrue) || +--## isNull(nameJust) || isNull(nameNothing) || +--## isNull(nameLeft) || isNull(nameRight) || +--## isNull(nameLT) || isNull(nameEQ) || isNull(nameGT)) { +--## ERRMSG(0) "Prelude does not define standard constructors" +--## EEND; +--## } +--## +--## nameFromInt = findName(findText("fromInt")); +--## nameFromInteger = findName(findText("fromInteger")); +--## nameFromDouble = findName(findText("fromDouble")); +--## nameEq = findName(findText("==")); +--## nameCompare = findName(findText("compare")); +--## nameLe = findName(findText("<=")); +--## nameGt = findName(findText(">")); +--## nameShowsPrec = findName(findText("showsPrec")); +--## nameReadsPrec = findName(findText("readsPrec")); +--## nameIndex = findName(findText("index")); +--## nameInRange = findName(findText("inRange")); +--## nameRange = findName(findText("range")); +--## nameMult = findName(findText("*")); +--## namePlus = findName(findText("+")); +--## nameMinBnd = findName(findText("minBound")); +--## nameMaxBnd = findName(findText("maxBound")); +--## #if EVAL_INSTANCES +--## nameStrict = findName(findText("strict")); +--## nameSeq = findName(findText("seq")); +--## #endif +--## nameReturn = findName(findText("return")); +--## nameBind = findName(findText(">>=")); +--## nameMFail = findName(findText("fail")); +--## if (isNull(nameFromInt) || isNull(nameFromDouble) || +--## isNull(nameEq) || isNull(nameCompare) || +--## isNull(nameLe) || isNull(nameGt) || +--## isNull(nameShowsPrec) || isNull(nameReadsPrec) || +--## isNull(nameIndex) || isNull(nameInRange) || +--## isNull(nameRange) || isNull(nameMult) || +--## isNull(namePlus) || isNull(nameFromInteger) || +--## isNull(nameMinBnd) || isNull(nameMaxBnd) || +--## #if EVAL_INSTANCES +--## isNull(nameStrict) || isNull(nameSeq) || +--## #endif +--## isNull(nameReturn) || isNull(nameBind) || +--## isNull(nameMFail)) { +--## ERRMSG(0) "Prelude does not define standard members" +--## EEND; +--## } +--## } +--## } +--## +#endif diff --git a/ghc/interpreter/link.h b/ghc/interpreter/link.h index c4cc542267de..228e5b4dcf74 100644 --- a/ghc/interpreter/link.h +++ b/ghc/interpreter/link.h @@ -1,38 +1,8 @@ -/* -*- mode: hugs-c; -*- */ -extern Void linkPreludeTC Args((Void)); -extern Void linkPreludeCM Args((Void)); -extern Void linkPreludeNames Args((Void)); -extern Module modulePreludeHugs; - -/* -------------------------------------------------------------------------- - * Primitive constructor functions - * ------------------------------------------------------------------------*/ - -extern Name nameFalse, nameTrue; -extern Name nameNil, nameCons; -extern Name nameUnit; - -extern Name nameFromInt, nameFromDouble;/*coercion of numerics */ -extern Name nameFromInteger; -extern Name nameReturn, nameBind; /* for translating monad comps */ -extern Name nameZero; /* for monads with a zero */ -#if EVAL_INSTANCES -extern Name nameStrict, nameSeq; /* Members of class Eval */ -#endif - -extern Name nameId; -extern Name nameRunIO; -extern Name namePrint; +extern Cell conCons; extern Name nameForce; - -#if TREX -extern Name nameInsFld; /* Field insertion routine */ -extern Type typeRec; /* Record formation */ -extern Name nameNoRec; /* The empty record */ -extern Type typeNoRow; /* The empty row */ -#endif +extern Name nameRunIO; /* The following data constructors are used to box unboxed * arguments and are treated differently by the code generator. @@ -83,10 +53,6 @@ extern Name nameMkThreadId; extern Name nameMkMVar; #endif -extern Type typeArrow; /* Builtin type constructors */ - -#define fn(from,to) ap2(typeArrow,from,to) /* make type: from -> to */ - /* For every primitive type provided by the runtime system, * we construct a Haskell type using a declaration of the form: * @@ -149,34 +115,6 @@ extern Type typeException; #warning BIGNUMTYPE undefined #endif -extern List stdDefaults; /* List of standard default types */ - -extern Class classEq; /* `standard' classes */ -extern Class classOrd; -extern Class classShow; -extern Class classRead; -extern Class classIx; -extern Class classEnum; -extern Class classBounded; -#if EVAL_INSTANCES -extern Class classEval; -#endif - -extern Class classReal; /* `numeric' classes */ -extern Class classIntegral; -extern Class classRealFrac; -extern Class classRealFloat; -extern Class classFractional; -extern Class classFloating; -extern Class classNum; - -extern Class classMonad; /* Monads and monads with a zero */ -extern Class classMonad0; - -/* used in typechecker */ -extern Name nameError; -extern Name nameInd; - /* used while desugaring */ extern Name nameId; extern Name nameOtherwise; @@ -204,3 +142,10 @@ extern Name namePmFromInteger; extern Name nameMkIO; extern Name nameUnpackString; +extern Type arrow; /* mkOffset(0) -> mkOffset(1) */ +extern Type listof; /* [ mkOffset(0) ] */ +extern Cell predNum; /* Num (mkOffset(0)) */ +extern Cell predFractional; /* Fractional (mkOffset(0)) */ +extern Cell predIntegral; /* Integral (mkOffset(0)) */ +extern Cell predMonad; /* Monad (mkOffset(0)) */ + diff --git a/ghc/interpreter/machdep.c b/ghc/interpreter/machdep.c index 25cef1f28db1..7b5bbb20f9f9 100644 --- a/ghc/interpreter/machdep.c +++ b/ghc/interpreter/machdep.c @@ -1,28 +1,21 @@ -/* -*- mode: hugs-c; -*- */ + /* -------------------------------------------------------------------------- * Machine dependent code * RISCOS specific code provided by Bryan Scatergood, JBS * Macintosh specific code provided by Hans Aberg (haberg@matematik.su.se) + * HaskellScript code and recursive directory search provided by + * Daan Leijen (leijen@fwi.uva.nl) * - * Copyright (c) The University of Nottingham and Yale University, 1994-1997. - * All rights reserved. See NOTICE for details and conditions of use etc... - * Hugs version 1.4, December 1997 + * Hugs 98 is Copyright (c) Mark P Jones, Alastair Reid and the Yale + * Haskell Group 1994-99, and is distributed as Open Source software + * under the Artistic License; see the file "Artistic" that is included + * in the distribution for details. * * $RCSfile: machdep.c,v $ - * $Revision: 1.2 $ - * $Date: 1998/12/02 13:22:20 $ + * $Revision: 1.3 $ + * $Date: 1999/02/03 17:08:32 $ * ------------------------------------------------------------------------*/ -#include "prelude.h" -#include "storage.h" -#include "connect.h" -#include "hugs.h" /* for fromEnv */ -#include "errors.h" -#include "version.h" - -#include "machdep.h" - -#include <stdio.h> #ifdef HAVE_SIGNAL_H # include <signal.h> #endif @@ -107,13 +100,49 @@ extern unsigned _stklen = 8000; /* Allocate an 8k stack segment */ #include <unix.h> #endif +/* -------------------------------------------------------------------------- + * Prototypes for registry reading + * ------------------------------------------------------------------------*/ + +#if USE_REGISTRY + +/* where have we hidden things in the registry? */ +#if HSCRIPT +#define HScriptRoot ("SOFTWARE\\Haskell\\HaskellScript\\") +#endif + +#define HugsRoot ("SOFTWARE\\Haskell\\Hugs\\" HUGS_VERSION "\\") +#define ProjectRoot ("SOFTWARE\\Haskell\\Hugs\\Projects\\") + +static Bool local createKey Args((HKEY, String, PHKEY, REGSAM)); +static Bool local queryValue Args((HKEY, String, String, LPDWORD, LPBYTE, DWORD)); +static Bool local setValue Args((HKEY, String, String, DWORD, LPBYTE, DWORD)); +static String local readRegString Args((HKEY, String, String, String)); +static Int local readRegInt Args((String,Int)); +static Bool local writeRegString Args((String,String)); +static Bool local writeRegInt Args((String,Int)); + +static String local readRegChildStrings Args((HKEY, String, String, Char, String)); +#endif /* USE_REGISTRY */ + /* -------------------------------------------------------------------------- * Find information about a file: * ------------------------------------------------------------------------*/ +#if RISCOS +typedef struct { unsigned hi, lo; } Time; +#define timeChanged(now,thn) (now.hi!=thn.hi || now.lo!=thn.lo) +#define timeSet(var,tm) var.hi = tm.hi; var.lo = tm.lo +#else +typedef time_t Time; +#define timeChanged(now,thn) (now!=thn) +#define timeSet(var,tm) var = tm +#endif + +static Void local getFileInfo Args((String, Time *, Long *)); static Bool local readable Args((String)); -Void getFileInfo(f,tm,sz) /* find time stamp and size of file*/ +static Void local getFileInfo(f,tm,sz) /* find time stamp and size of file*/ String f; Time *tm; Long *sz; { @@ -201,7 +230,11 @@ String f; { * ------------------------------------------------------------------------*/ static String local hugsdir Args((Void)); +#if HSCRIPT +static String local hscriptDir Args((Void)); +#endif static String local RealPath Args((String)); +static int local pathCmp Args((String, String)); static String local normPath Args((String)); static Void local searchChr Args((Int)); static Void local searchStr Args((String)); @@ -226,7 +259,18 @@ static Bool local tryEndings Args((String)); #endif static String local hugsdir() { /* directory containing lib/Prelude.hs */ -#if HAVE_GETMODULEFILENAME && !DOS +#if HSCRIPT + /* In HaskellScript (Win32 only), we lookup InstallDir in the registry. */ + static char dir[FILENAME_MAX+1] = ""; + if (dir[0] == '\0') { /* not initialised yet */ + String s = readRegString(HKEY_LOCAL_MACHINE,HugsRoot,"InstallDir", + HUGSDIR); + if (s) { + strcpy(dir,s); + } + } + return dir; +#elif HAVE_GETMODULEFILENAME && !DOS /* On Windows, we can find the binary we're running and it's * conventional to put the libraries in the same place. */ @@ -251,7 +295,21 @@ static String local hugsdir() { /* directory containing lib/Prelude.hs */ return HUGSDIR; #endif } - + +#if HSCRIPT +static String local hscriptDir() { /* directory containing ?? what Daan? */ + static char dir[FILENAME_MAX+1] = ""; + if (dir[0] == '\0') { /* not initialised yet */ + String s = readRegString(HKEY_LOCAL_MACHINE,HScriptRoot,"InstallDir",""); + if (s) { + strcpy(dir,s); + } + } + return dir; +} +#endif + + static String local RealPath(s) /* Find absolute pathname of file */ String s; { #if HAVE__FULLPATH /* eg DOS */ @@ -267,7 +325,7 @@ String s; { return path; } -int pathCmp(p1,p2) /* Compare paths after normalisation */ +static int local pathCmp(p1,p2) /* Compare paths after normalisation */ String p1; String p2; { #if HAVE__FULLPATH /* eg DOS */ @@ -306,7 +364,11 @@ String s; { /* a pathname in some appropriate manner. */ #endif /* ! PATH_CANONICALIZATION */ } -static String endings[] = { "", ".myhi", ".hs", ".lhs", 0 }; +#if HSCRIPT +static String endings[] = { "", ".hs", ".lhs", ".hsx", ".hash", 0 }; +#else +static String endings[] = { "", ".hs", ".lhs", 0 }; +#endif static char searchBuf[FILENAME_MAX+1]; static Int searchPos; @@ -315,7 +377,7 @@ static Int searchPos; static Void local searchChr(c) /* Add single character to search buffer */ Int c; { if (searchPos<FILENAME_MAX) { - searchBuf[searchPos++] = c; + searchBuf[searchPos++] = (char)c; searchBuf[searchPos] = '\0'; } } @@ -341,17 +403,123 @@ String s; { return FALSE; } + + +#if SEARCH_DIR + +/* scandir, June 98 Daan Leijen + searches the base directory and its direct subdirectories for a file + + input: searchbuf contains SLASH terminated base directory + argument s contains the (base) filename + output: TRUE: searchBuf contains the full filename + FALSE: searchBuf is garbage, file not found +*/ + + +#ifdef HAVE_WINDOWS_H + +static Bool scanSubDirs(s) +String s; +{ + struct _finddata_t findInfo; + long handle; + int save; + + save = searchPos; + /* is it in the current directory ? */ + if (tryEndings(s)) return TRUE; + + searchReset(save); + searchStr("*"); + + /* initiate the search */ + handle = _findfirst( searchBuf, &findInfo ); + if (handle==-1) { errno = 0; return FALSE; } + + /* search all subdirectories */ + do { + /* if we have a valid sub directory */ + if (((findInfo.attrib & _A_SUBDIR) == _A_SUBDIR) && + (findInfo.name[0] != '.')) { + searchReset(save); + searchStr(findInfo.name); + searchChr(SLASH); + if (tryEndings(s)) { + return TRUE; + } + } + } while (_findnext( handle, &findInfo ) == 0); + + _findclose( handle ); + return FALSE; +} + +#elif defined(HAVE_FTW_H) + +#include <ftw.h> + +static char baseFile[FILENAME_MAX+1]; +static char basePath[FILENAME_MAX+1]; +static int basePathLen; + +static int scanitem( const char* path, + const struct stat* statinfo, + int info ) +{ + if (info == FTW_D) { /* is it a directory */ + searchReset(0); + searchStr(path); + searchChr(SLASH); + if (tryEndings(baseFile)) { + return 1; + } + } + return 0; +} + +static Bool scanSubDirs(s) +String s; +{ + int r; + strcpy(baseFile,s); + strcpy(basePath,searchBuf); + basePathLen = strlen(basePath); + + /* is it in the current directory ? */ + if (tryEndings(s)) return TRUE; + + /* otherwise scan the subdirectories */ + r = ftw( basePath, scanitem, 2 ); + errno = 0; + return (r > 0); +} + +#endif /* HAVE_WINDOWS_H || HAVE_FTW_H */ +#endif /* SEARCH_DIR */ + String findPathname(along,nm) /* Look for a file along specified path */ String along; /* Return NULL if file does not exist */ String nm; { - String s = findMPathname(along,nm); + /* AC, 1/21/99: modified to search hugsPath first, then projectPath */ + String s = findMPathname(along,nm,hugsPath); +#if USE_REGISTRY +#if 0 + ToDo: + if (s==NULL) { + s = findMPathname(along,nm,projectPath); + } +#endif /* 0 */ +#endif /* USE_REGISTRY */ return s ? s : normPath(searchBuf); } -String findMPathname(along,nm) /* Look for a file along specified path */ +/* AC, 1/21/99: modified to pass in path to search explicitly */ +String findMPathname(along,nm,path)/* Look for a file along specified path */ String along; /* If nonzero, a path prefix from along is */ -String nm; { /* used as the first prefix in the search. */ - String pathpt = hugsPath; +String nm; /* used as the first prefix in the search. */ +String path; { + String pathpt = path; searchReset(0); if (along) { /* Was a path for an existing file given? */ @@ -370,6 +538,7 @@ String nm; { /* used as the first prefix in the search. */ if (pathpt && *pathpt) { /* Otherwise, we look along the HUGSPATH */ Bool more = TRUE; do { + Bool recurse = FALSE; /* DL: shall we recurse ? */ searchReset(0); if (*pathpt) { if (*pathpt!=PATHSEP) { @@ -378,20 +547,37 @@ String nm; { /* used as the first prefix in the search. */ searchStr(hugsdir()); pathpt += 6; } - do +#if HSCRIPT + /* And another - we ought to generalise this stuff */ + else if (strncmp(pathpt,"{HScript}",9)==0) { + searchStr(hscriptDir()); + pathpt += 9; + } +#endif + do { searchChr(*pathpt++); - while (*pathpt && *pathpt!=PATHSEP); - searchChr(SLASH); + } while (*pathpt && *pathpt!=PATHSEP); + recurse = (pathpt[-1] == SLASH); + if (!recurse) { + searchChr(SLASH); + } } if (*pathpt==PATHSEP) pathpt++; else more = FALSE; - } - else + } else { more = FALSE; - if (tryEndings(nm)) + } +#if SEARCH_DIR + if (recurse ? scanSubDirs(nm) : tryEndings(nm)) { + return normPath(searchBuf); + } +#else + if (tryEndings(nm)) { return normPath(searchBuf); + } +#endif } while (more); } @@ -404,7 +590,9 @@ String nm; { /* used as the first prefix in the search. */ * eg substPath("a:b:c::d:e","x:y:z") = "a:b:c:x:y:z:d:e" * ------------------------------------------------------------------------*/ -String substPath(new,sub) /* substitute sub path into new path*/ +static String local substPath Args((String,String)); + +static String local substPath(new,sub) /* substitute sub path into new path*/ String new; String sub; { Bool substituted = FALSE; /* only allow one replacement */ @@ -433,34 +621,46 @@ String sub; { } +/* -------------------------------------------------------------------------- + * Get time/date stamp for inclusion in compiled files: + * ------------------------------------------------------------------------*/ + +#if PROFILING +String timeString() { /* return time&date string */ + time_t clock; /* must end with '\n' character */ + time(&clock); + return(ctime(&clock)); +} +#endif + /* -------------------------------------------------------------------------- * Garbage collection notification: * ------------------------------------------------------------------------*/ Bool gcMessages = FALSE; /* TRUE => print GC messages */ -Void gcStarted() { /* notify garbage collector start */ +Void gcStarted() { /* Notify garbage collector start */ #if HUGS_FOR_WINDOWS SaveCursor = SetCursor(GarbageCursor); #endif if (gcMessages) { - printf("{{Gc"); + Printf("{{Gc"); FlushStdout(); } } -Void gcScanning() { /* notify garbage collector scans */ +Void gcScanning() { /* Notify garbage collector scans */ if (gcMessages) { Putchar(':'); FlushStdout(); } } -Void gcRecovered(recovered) /* notify garbage collection done */ +Void gcRecovered(recovered) /* Notify garbage collection done */ Int recovered; { if (gcMessages) { - printf("%d}}",recovered); - fflush(stdout); + Printf("%d}}",recovered); + FlushStdout(); } #if HUGS_FOR_WINDOWS SetCursor(SaveCursor); @@ -571,7 +771,7 @@ Void gcCStack() { /* Garbage collect elements off */ #if (HAVE_TERMIO_H | HAVE_SGTTY_H | HAVE_TERMIOS_H) -/* This is believed to be redundant! ADR */ +/* grab the varargs prototype for ioctl */ #if HAVE_SYS_IOCTL_H # include <sys/ioctl.h> #endif @@ -735,8 +935,13 @@ Bool reqd; { /* or off otherwise, returning old */ if (broken) { /* repond to break signal received */ broken = FALSE; /* whilst break trap disabled */ sigRaise(breakHandler); + /* not reached */ } +#if HANDLERS_CANT_LONGJMP ctrlbrk(ignoreBreak); +#else + ctrlbrk(breakHandler); +#endif } else { ctrlbrk(ignoreBreak); } @@ -744,7 +949,9 @@ Bool reqd; { /* or off otherwise, returning old */ } static sigHandler(ignoreBreak) { /* record but don't respond to break*/ - ctrlbrk(ignoreBreak); + ctrlbrk(ignoreBreak); /* reinstall signal handler */ + /* redundant on BSD systems but essential */ + /* on POSIX and other systems */ broken = TRUE; interruptStgRts(); sigResume; @@ -794,7 +1001,7 @@ static Void local installHandlers() { /* Install handlers for all fatal */ * Shell escapes: * ------------------------------------------------------------------------*/ -Bool startEdit(line,nm) /* Start editor on file name at */ +static Bool local startEdit(line,nm) /* Start editor on file name at */ Int line; /* given line. Both name and line */ String nm; { /* or just line may be zero */ static char editorCmd[FILENAME_MAX+1]; @@ -977,15 +1184,16 @@ REGSAM samDesired; { == ERROR_SUCCESS; } -static Bool local queryValue(hKey, var, type, buf, bufSize) +static Bool local queryValue(hKey, regPath, var, type, buf, bufSize) HKEY hKey; +String regPath; String var; LPDWORD type; LPBYTE buf; DWORD bufSize; { HKEY hRootKey; - if (!createKey(hKey, &hRootKey, KEY_READ)) { + if (!createKey(hKey, regPath, &hRootKey, KEY_READ)) { return FALSE; } else { LONG res = RegQueryValueEx(hRootKey, var, NULL, type, buf, &bufSize); @@ -994,15 +1202,16 @@ DWORD bufSize; { } } -static Bool local setValue(hKey, var, type, buf, bufSize) +static Bool local setValue(hKey, regPath, var, type, buf, bufSize) HKEY hKey; +String regPath; String var; DWORD type; LPBYTE buf; DWORD bufSize; { HKEY hRootKey; - if (!createKey(hKey, &hRootKey, KEY_WRITE)) { + if (!createKey(hKey, regPath, &hRootKey, KEY_WRITE)) { return FALSE; } else { LONG res = RegSetValueEx(hRootKey, var, 0, type, buf, bufSize); @@ -1011,34 +1220,32 @@ DWORD bufSize; { } } -String readRegString(var,def) /* read String from registry */ +static String local readRegString(key,regPath,var,def) /* read String from registry */ +HKEY key; +String regPath; String var; String def; { static char buf[300]; DWORD type; - - if (queryValue(HKEY_CURRENT_USER, var, &type, buf, sizeof(buf)) + if (queryValue(key, regPath,var, &type, buf, sizeof(buf)) && type == REG_SZ) { return (String)buf; - } else if (queryValue(HKEY_LOCAL_MACHINE, var, &type, buf, sizeof(buf)) - && type == REG_SZ) { - return (String)buf; } else { - return NULL; + return def; } } - -Int readRegInt(var, def) /* read Int from registry */ + +static Int local readRegInt(var, def) /* read Int from registry */ String var; Int def; { DWORD buf; DWORD type; - if (queryValue(HKEY_CURRENT_USER, var, &type, + if (queryValue(HKEY_CURRENT_USER, HugsRoot, var, &type, (LPBYTE)&buf, sizeof(buf)) && type == REG_DWORD) { return (Int)buf; - } else if (queryValue(HKEY_LOCAL_MACHINE, var, &type, + } else if (queryValue(HKEY_LOCAL_MACHINE, HugsRoot, var, &type, (LPBYTE)&buf, sizeof(buf)) && type == REG_DWORD) { return (Int)buf; @@ -1047,20 +1254,20 @@ Int def; { } } -Bool writeRegString(var,val) /* write String to registry */ +static Bool local writeRegString(var,val) /* write String to registry */ String var; String val; { if (NULL == val) { val = ""; } - return setValue(HKEY_CURRENT_USER, var, + return setValue(HKEY_CURRENT_USER, HugsRoot, var, REG_SZ, (LPBYTE)val, lstrlen(val)+1); } -Bool writeRegInt(var,val) /* write String to registry */ +static Bool local writeRegInt(var,val) /* write String to registry */ String var; Int val; { - return setValue(HKEY_CURRENT_USER, var, + return setValue(HKEY_CURRENT_USER, HugsRoot, var, REG_DWORD, (LPBYTE)&val, sizeof(val)); } diff --git a/ghc/interpreter/optimise.c b/ghc/interpreter/optimise.c index f16d28416bf6..170a0c6119d9 100644 --- a/ghc/interpreter/optimise.c +++ b/ghc/interpreter/optimise.c @@ -1,4 +1,4 @@ -/* -*- mode: hugs-c; -*- */ + /* -------------------------------------------------------------------------- * Optimiser * @@ -7,16 +7,15 @@ * Hugs version 1.4, December 1997 * * $RCSfile: optimise.c,v $ - * $Revision: 1.2 $ - * $Date: 1998/12/02 13:22:23 $ + * $Revision: 1.3 $ + * $Date: 1999/02/03 17:08:33 $ * ------------------------------------------------------------------------*/ #include "prelude.h" #include "storage.h" +#include "backend.h" #include "connect.h" #include "errors.h" -#include "stg.h" -#include "optimise.h" /* -------------------------------------------------------------------------- * Local functions diff --git a/ghc/interpreter/output.c b/ghc/interpreter/output.c index 471dd51d3b46..b5ced32876fa 100644 --- a/ghc/interpreter/output.c +++ b/ghc/interpreter/output.c @@ -1,25 +1,26 @@ -/* -*- mode: hugs-c; -*- */ + /* -------------------------------------------------------------------------- * Unparse expressions and types - for use in error messages, type checker * and for debugging. * - * Copyright (c) The University of Nottingham and Yale University, 1994-1997. - * All rights reserved. See NOTICE for details and conditions of use etc... - * Hugs version 1.4, December 1997 + * Hugs 98 is Copyright (c) Mark P Jones, Alastair Reid and the Yale + * Haskell Group 1994-99, and is distributed as Open Source software + * under the Artistic License; see the file "Artistic" that is included + * in the distribution for details. * * $RCSfile: output.c,v $ - * $Revision: 1.2 $ - * $Date: 1998/12/02 13:22:24 $ + * $Revision: 1.3 $ + * $Date: 1999/02/03 17:08:33 $ * ------------------------------------------------------------------------*/ #include "prelude.h" #include "storage.h" #include "connect.h" -#include "input.h" /* for textPlus */ #include "errors.h" -#include "link.h" #include <ctype.h> +/*#define DEBUG_SHOWSC*/ /* Must also be set in compiler.c */ + #define DEPTH_LIMIT 15 /* -------------------------------------------------------------------------- @@ -48,7 +49,7 @@ static Void local unlexCharConst Args((Cell)); static Void local unlexStrConst Args((Text)); static Void local putSigType Args((Cell)); -static Void local putContext Args((List,Int)); +static Void local putContext Args((List,List,Int)); static Void local putPred Args((Cell,Int)); static Void local putType Args((Cell,Int,Int)); static Void local putTyVar Args((Int)); @@ -63,6 +64,9 @@ static Void local putKinds Args((Kinds)); * ------------------------------------------------------------------------*/ static FILE *outputStream; /* current output stream */ +#ifdef DEBUG_SHOWSC +static Int outColumn = 0; /* current output column number */ +#endif #define OPEN(b) if (b) putChr('('); #define CLOSE(b) if (b) putChr(')'); @@ -70,12 +74,18 @@ static FILE *outputStream; /* current output stream */ static Void local putChr(c) /* print single character */ Int c; { Putc(c,outputStream); +#ifdef DEBUG_SHOWSC + outColumn++; +#endif } static Void local putStr(s) /* print string */ String s; { for (; *s; s++) { Putc(*s,outputStream); +#ifdef DEBUG_SHOWSC + outColumn++; +#endif } } @@ -175,16 +185,33 @@ Cell e; { case COMP : putComp(fst(snd(e)),snd(snd(e))); break; + case MONADCOMP : putComp(fst(snd(snd(e))),snd(snd(snd(e)))); + break; + case CHARCELL : unlexCharConst(charOf(e)); break; - case INTCELL : putInt(intOf(e)); + case INTCELL : { Int i = intOf(e); + if (i<0 && d>=UMINUS_PREC) putChr('('); + putInt(i); + if (i<0 && d>=UMINUS_PREC) putChr(')'); + } break; - case BIGCELL : putStr(bignumToString(e)); +#if BIGNUMS + case NEGNUM : + case ZERONUM : + case POSNUM : xs = bigOut(e,NIL,d>=UMINUS_PREC); + for (; nonNull(xs); xs=tl(xs)) + putChr(charOf(arg(hd(xs)))); break; +#endif - case FLOATCELL : putStr(floatToString(e)); + case FLOATCELL : { Float f = floatOf(e); + if (f<0 && d>=UMINUS_PREC) putChr('('); + putStr(floatToString(f)); + if (f<0 && d>=UMINUS_PREC) putChr(')'); + } break; case STRCELL : unlexStrConst(textOf(e)); @@ -214,7 +241,7 @@ Cell e; { case LAMBDA : xs = fst(snd(e)); if (whatIs(xs)==BIGLAM) - xs = snd(snd(e)); + xs = snd(snd(xs)); while (nonNull(xs) && isDictVal(hd(xs))) xs = tl(xs); if (isNull(xs)) { @@ -270,7 +297,7 @@ Cell e; { putDepth--; } -static Void local putFlds(exp,fs) /* Output exp using labelled fields*/ +static Void local putFlds(exp,fs) /* Output exp using labelled fields*/ Cell exp; List fs; { put(ALWAYS,exp); @@ -288,7 +315,7 @@ List fs; { isVar(e) ? textOf(e) : inventText(); put(NEVER,f); - if (s!=t) { + if (haskell98 || s!=t) { putStr(" = "); put(NEVER,e); } @@ -336,8 +363,8 @@ Cell e; { #if !DEBUG_CODE Cell h = getHead(e); switch (whatIs(h)) { - case DICTVAR : return TRUE; - case NAME : return isDfun(h); + case DICTVAR : return TRUE; + case NAME : return isDfun(h); } #endif return FALSE; @@ -370,8 +397,8 @@ Cell e; { switch (whatIs(h)) { #if NPLUSK case ADDPAT : if (args==1) - putInfix(d,textPlus,syntaxOf(textPlus), - arg(e),snd(h)); + putInfix(d,textPlus,syntaxOf(namePlus), + arg(e),mkInt(intValOf(fun(e)))); else putStr("ADDPAT"); return; @@ -384,19 +411,22 @@ Cell e; { case NAME : if (args==1 && ((h==nameFromInt && isInt(arg(e))) || +#if BIGNUMS (h==nameFromInteger && isBignum(arg(e))) || +#endif (h==nameFromDouble && isFloat(arg(e))))) { put(d,arg(e)); return; } - sy = syntaxOf(t = name(h).text); + t = name(h).text; + sy = syntaxOf(h); break; case VARIDCELL : case VAROPCELL : case DICTVAR : case CONIDCELL : - case CONOPCELL : sy = syntaxOf(t = textOf(h)); + case CONOPCELL : sy = defaultSyntax(t = textOf(h)); break; #if TREX @@ -603,20 +633,29 @@ Cell t; { putType(t,NEVER,fr); /* Finally, print rest of type ... */ } -static Void local putContext(qs,fr) /* print context list */ +static Void local putContext(ps,qs,fr) /* print context list */ +List ps; List qs; Int fr; { - if (isNull(qs)) - putStr("()"); - else { - Int nq = length(qs); - if (nq!=1) putChr('('); + Int len = length(ps) + length(qs); + Int c = len; + if (len!=1) { + putChr('('); + } + for (; nonNull(ps); ps=tl(ps)) { + putPred(hd(ps),fr); + if (--c > 0) { + putStr(", "); + } + } + for (; nonNull(qs); qs=tl(qs)) { putPred(hd(qs),fr); - while (nonNull(qs=tl(qs))) { + if (--c > 0) { putStr(", "); - putPred(hd(qs),fr); } - if (nq!=1) putChr(')'); + } + if (len!=1) { + putChr(')'); } } @@ -649,16 +688,16 @@ Cell t; Int prec; Int fr; { switch(whatIs(t)) { - case TYCON : putStr(textToStr(tycon(t).text)); - break; + case TYCON : putStr(textToStr(tycon(t).text)); + break; - case TUPLE : { Int n = tupleOf(t); - putChr('('); - while (--n > 0) - putChr(','); - putChr(')'); - } - break; + case TUPLE : { Int n = tupleOf(t); + putChr('('); + while (--n > 0) + putChr(','); + putChr(')'); + } + break; case POLYTYPE : { Kinds ks = polySigOf(t); OPEN(prec>=ARROW_PREC); @@ -674,10 +713,17 @@ Int fr; { } break; + case CDICTS : case QUAL : OPEN(prec>=ARROW_PREC); - putContext(fst(snd(t)),fr); - putStr(" => "); - putType(snd(snd(t)),NEVER,fr); + if (whatIs(snd(snd(t)))==CDICTS) { + putContext(fst(snd(t)),fst(snd(snd(snd(t)))),fr); + putStr(" => "); + putType(snd(snd(snd(snd(t)))),NEVER,fr); + } else { + putContext(fst(snd(t)),NIL,fr); + putStr(" => "); + putType(snd(snd(t)),NEVER,fr); + } CLOSE(prec>=ARROW_PREC); break; @@ -685,61 +731,56 @@ Int fr; { case RANK2 : putType(snd(snd(t)),prec,fr); break; - case OFFSET : putTyVar(offsetOf(t)); - break; + case OFFSET : putTyVar(offsetOf(t)); + break; case VARIDCELL : case VAROPCELL : putChr('_'); unlexVar(textOf(t)); break; - case INTCELL : putChr('_'); - putInt(intOf(t)); - break; + case INTCELL : putChr('_'); + putInt(intOf(t)); + break; -/* #ifdef DEBUG_TYPES */ - case STAR : putChr('*'); - break; -/* #endif */ - - case AP : { Cell typeHead = getHead(t); - Bool brackets = (argCount!=0 && prec>=ALWAYS); - Int args = argCount; - - if (typeHead==typeList) { - if (argCount==1) { - putChr('['); - putType(arg(t),NEVER,fr); - putChr(']'); - return; - } - } - else if (typeHead==typeArrow) { - if (argCount==2) { - OPEN(prec>=ARROW_PREC); - putType(arg(fun(t)),ARROW_PREC,fr); - putStr(" -> "); - putType(arg(t),NEVER,fr); - CLOSE(prec>=ARROW_PREC); - return; - } - else if (argCount==1) { - putChr('('); - putType(arg(t),ARROW_PREC,fr); - putStr("->)"); - return; - } - } - else if (isTuple(typeHead)) { - if (argCount==tupleOf(typeHead)) { - putChr('('); - putTupleType(t,fr); - putChr(')'); - return; - } - } + case AP : { Cell typeHead = getHead(t); + Bool brackets = (argCount!=0 && prec>=ALWAYS); + Int args = argCount; + + if (typeHead==typeList) { + if (argCount==1) { + putChr('['); + putType(arg(t),NEVER,fr); + putChr(']'); + return; + } + } + else if (typeHead==typeArrow) { + if (argCount==2) { + OPEN(prec>=ARROW_PREC); + putType(arg(fun(t)),ARROW_PREC,fr); + putStr(" -> "); + putType(arg(t),NEVER,fr); + CLOSE(prec>=ARROW_PREC); + return; + } + else if (argCount==1) { + putChr('('); + putType(arg(t),ARROW_PREC,fr); + putStr("->)"); + return; + } + } + else if (isTuple(typeHead)) { + if (argCount==tupleOf(typeHead)) { + putChr('('); + putTupleType(t,fr); + putChr(')'); + return; + } + } #if TREX - else if (isExt(typeHead)) { + else if (isExt(typeHead)) { if (args==2) { String punc = "("; do { @@ -764,13 +805,13 @@ Int fr; { args-=2; } #endif - OPEN(brackets); - putApType(t,args,fr); - CLOSE(brackets); - } - break; + OPEN(brackets); + putApType(t,args,fr); + CLOSE(brackets); + } + break; - default : putStr("(bad type)"); + default : putStr("(bad type)"); } } @@ -885,7 +926,7 @@ Void printContext(fp,qs) /* print context on spec. stream */ FILE *fp; List qs; { outputStream = fp; - putContext(qs,0); + putContext(qs,NIL,0); } Void printPred(fp,pi) /* print predicate pi on stream */ @@ -903,7 +944,7 @@ Kind k; { } Void printKinds(fp,ks) /* print list of kinds on stream */ -FILE *fp; +FILE *fp; Kinds ks; { outputStream = fp; putKinds(ks); diff --git a/ghc/interpreter/parser.y b/ghc/interpreter/parser.y index f816a16c6858..69f1a28cc00e 100644 --- a/ghc/interpreter/parser.y +++ b/ghc/interpreter/parser.y @@ -1,17 +1,18 @@ -/* -*- mode: hugs-c; -*- */ + /* -------------------------------------------------------------------------- * Hugs parser (included as part of input.c) * - * Copyright (c) The University of Nottingham and Yale University, 1994-1997. - * All rights reserved. See NOTICE for details and conditions of use etc... - * Hugs version 1.4, December 1997 + * Expect 6 shift/reduce conflicts when passing this grammar through yacc, + * but don't worry; they should all be resolved in an appropriate manner. * - * Expect 24 shift/reduce conflicts when passing this grammar through yacc, - * but don't worry; they will all be resolved in an appropriate manner. + * Hugs 98 is Copyright (c) Mark P Jones, Alastair Reid and the Yale + * Haskell Group 1994-99, and is distributed as Open Source software + * under the Artistic License; see the file "Artistic" that is included + * in the distribution for details. * * $RCSfile: parser.y,v $ - * $Revision: 1.2 $ - * $Date: 1998/12/02 13:22:26 $ + * $Revision: 1.3 $ + * $Date: 1999/02/03 17:08:34 $ * ------------------------------------------------------------------------*/ %{ @@ -20,11 +21,18 @@ #endif #define defTycon(n,l,lhs,rhs,w) tyconDefn(intOf(l),lhs,rhs,w); sp-=n #define sigdecl(l,vs,t) ap(SIGDECL,triple(l,vs,t)) +#define fixdecl(l,ops,a,p) ap(FIXDECL,\ + triple(l,ops,mkInt(mkSyntax(a,intOf(p))))) #define grded(gs) ap(GUARDED,gs) #define bang(t) ap(BANG,t) #define only(t) ap(ONLY,t) #define letrec(bs,e) (nonNull(bs) ? ap(LETREC,pair(bs,e)) : e) +#define qualify(ps,t) (nonNull(ps) ? ap(QUAL,pair(ps,t)) : t) +#if IGNORE_MODULES +#define exportSelf() NIL +#else #define exportSelf() singleton(ap(MODULEENT,mkCon(module(currentModule).text))) +#endif #define yyerror(s) /* errors handled elsewhere */ #define YYSTYPE Cell @@ -32,8 +40,6 @@ static Cell local gcShadow Args((Int,Cell)); static Void local syntaxError Args((String)); static String local unexpected Args((Void)); static Cell local checkPrec Args((Cell)); -static Void local fixDefn Args((Syntax,Cell,Cell,List)); -static Void local setSyntax Args((Int,Syntax,Cell)); static Cell local buildTuple Args((List)); static List local checkContext Args((List)); static Cell local checkPred Args((Cell)); @@ -42,7 +48,6 @@ static Cell local checkTyLhs Args((Cell)); #if !TREX static Void local noTREX Args((String)); #endif -static Cell local tidyInfix Args((Cell)); /* For the purposes of reasonably portable garbage collection, it is * necessary to simulate the YACC stack on the Hugs stack to keep @@ -52,32 +57,31 @@ static Cell local tidyInfix Args((Cell)); * taking account of look-ahead tokens as described by gcShadow() * below. * - * Of the non-terminals used below, only start, topDecl, fixDecl & begin + * Of the non-terminals used below, only start, topDecl & begin * do not leave any values on the Hugs stack. The same is true for the * terminals EXPR and SCRIPT. At the end of a successful parse, there * should only be one element left on the stack, containing the result * of the parse. */ -#define gc0(e) gcShadow(0,e) -#define gc1(e) gcShadow(1,e) -#define gc2(e) gcShadow(2,e) -#define gc3(e) gcShadow(3,e) -#define gc4(e) gcShadow(4,e) -#define gc5(e) gcShadow(5,e) -#define gc6(e) gcShadow(6,e) -#define gc7(e) gcShadow(7,e) +#define gc0(e) gcShadow(0,e) +#define gc1(e) gcShadow(1,e) +#define gc2(e) gcShadow(2,e) +#define gc3(e) gcShadow(3,e) +#define gc4(e) gcShadow(4,e) +#define gc5(e) gcShadow(5,e) +#define gc6(e) gcShadow(6,e) +#define gc7(e) gcShadow(7,e) %} %token EXPR SCRIPT %token CASEXP OF DATA TYPE IF %token THEN ELSE WHERE LET IN -%token INFIX INFIXL INFIXR FOREIGN TNEWTYPE +%token INFIXN INFIXL INFIXR FOREIGN TNEWTYPE %token DEFAULT DERIVING DO TCLASS TINSTANCE -%token REPEAT ALL -%token VAROP VARID NUMLIT CHARLIT STRINGLIT -%token CONOP CONID +%token REPEAT ALL NUMLIT CHARLIT STRINGLIT +%token VAROP VARID CONOP CONID %token QVAROP QVARID QCONOP QCONID /*#if TREX*/ %token RECSELID @@ -86,273 +90,22 @@ static Cell local tidyInfix Args((Cell)); %token '|' '-' FROM ARROW '~' %token '!' IMPLIES '(' ',' ')' %token '[' ';' ']' '`' '.' -%token MODULETOK IMPORT HIDING QUALIFIED ASMOD -%token EXPORT INTERFACE REQUIRES UNSAFE +%token TMODULE IMPORT HIDING QUALIFIED ASMOD +%token EXPORT UNSAFE %% -/*- Top level script/module structure: ------------------------------------*/ +/*- Top level script/module structure -------------------------------------*/ start : EXPR exp wherePart {inputExpr = letrec($3,$2); sp-=2;} | SCRIPT topModule {valDefns = $2; sp-=1;} - | INTERFACE iface {sp-=1;} | error {syntaxError("input");} ; -/*- GHC interface file parsing: -------------------------------------------*/ - -/* Reading in an interface file is surprisingly like reading - * a normal Haskell module: we read in a bunch of declarations, - * construct symbol table entries, etc. The "only" differences - * are that there's no syntactic sugar to deal with and we don't - * have to read in expressions. - */ - -iface : INTERFACE ifaceName NUMLIT checkVersion ifaceDecls { $$ = gc5(NIL); } - | INTERFACE error {syntaxError("interface file");} - ; - -ifaceName : CONID {openGHCIface(textOf($1)); $$ = gc1(NIL);} - ; - -ifaceDecls: {$$=gc0(NIL);} - | ifaceDecl ';' ifaceDecls {$$=gc3(cons($1,$2));} - ; - -/* We use ifaceData in data decls so as to include () */ -ifaceDecl : IMPORT CONID NUMLIT { extern String scriptFile; - String fileName = findPathname(scriptFile,textToStr(textOf($2))); - addGHCImport(intOf($1),textOf($2),fileName); - $$ = gc3(NIL); - } - | EXPORT CONID ifaceEntities {} - | REQUIRES STRINGLIT { extern String scriptFile; - String fileName = findPathname(scriptFile,textToStr(textOf($2))); - loadSharedLib(fileName); - $$ = gc2(NIL); - } - | INFIXL optdigit op { fixDefn(LEFT_ASS,$1,$2,$3); $$ = gc3(NIL); } - | INFIXR optdigit op { fixDefn(RIGHT_ASS,$1,$2,$3); $$ = gc3(NIL); } - | INFIX optdigit op { fixDefn(NON_ASS,$1,$2,$3); $$ = gc3(NIL); } - | TINSTANCE ifaceQuant ifaceClass '=' ifaceVar { addGHCInstance(intOf($1),$2,$3,textOf($5)); $$ = gc5(NIL); } - | NUMLIT TYPE ifaceTCName ifaceTVBndrs '=' ifaceType { addGHCSynonym(intOf($2),$3,$4,$6); $$ = gc6(NIL); } - | NUMLIT DATA ifaceData ifaceTVBndrs ifaceConstrs ifaceSels { addGHCDataDecl(intOf($2),$3,$4,$5,$6); $$ = gc6(NIL); } - | NUMLIT TNEWTYPE ifaceTCName ifaceTVBndrs ifaceNewTypeConstr { addGHCNewType(intOf($2),$3,$4,$5); $$ = gc5(NIL); } - | NUMLIT TCLASS ifaceDeclContext ifaceTCName ifaceTVBndrs ifaceCSigs { addGHCClass(intOf($2),$3,$4,$5,$6); $$ = gc6(NIL); } - | NUMLIT ifaceVar COCO ifaceType { addGHCVar(intOf($3),textOf($2),$4); $$ = gc4(NIL); } - | error { syntaxError("interface declaration"); } - ; - -checkVersion - : NUMLIT { $$ = gc1(NIL); } - ; - -ifaceSels /* [(VarId,Type)] */ - : { $$ = gc0(NIL); } - | WHERE '{' ifaceSels1 '}' { $$ = gc4($3); } - ; - -ifaceSels1 /* [(VarId,Type)] */ - : ifaceSel { $$ = gc1(singleton($1)); } - | ifaceSel ';' ifaceSels1 { $$ = gc3(cons($1,$3)); } - ; - -ifaceSel /* (VarId,Type) */ - : ifaceVarName COCO ifaceType { $$ = gc3(pair($1,$3)); } - ; - -ifaceCSigs /* [(VarId,Type)] */ - : { $$ = gc0(NIL); } - | WHERE '{' ifaceCSigs1 '}' { $$ = gc4($3); } - ; - -ifaceCSigs1 /* [(VarId,Type)] */ - : ifaceCSig { $$ = gc1(singleton($1)); } - | ifaceCSig ';' ifaceCSigs1 { $$ = gc3(cons($1,$3)); } - ; - -ifaceCSig /* (VarId,Type) */ - : ifaceVarName COCO ifaceType { $$ = gc3(pair($1,$3)); } - | ifaceVarName '=' COCO ifaceType { $$ = gc4(pair($1,$4)); } /* has default method */ - ; - -ifaceConstrs /* [(ConId,[VarId],Type)] */ - : { $$ = gc0(NIL); } - | '=' ifaceConstrs1 { $$ = gc2($2); } - ; - -ifaceConstrs1 /* [(ConId,[VarId],Type)] */ - : ifaceConstr { $$ = gc1(singleton($1)); } - | ifaceConstr '|' ifaceConstrs1 { $$ = gc3(cons($1,$3)); } - ; - -/* We use ifaceData so as to include () */ -ifaceConstr /* (ConId,[VarId],Type) */ - : ifaceData COCO ifaceType { $$ = gc3(triple($1,NIL,$3)); } - | ifaceData '{' ifaceVarNames1 '}' COCO ifaceType { $$ = gc6(triple($1,$3,$6)); } - ; - -ifaceNewTypeConstr /* (ConId,Type) */ - : { $$ = gc0(NIL); } - | '=' ifaceDataName COCO ifaceType { $$ = gc4(pair($2,$4)); } - ; - -ifaceQuant /* Maybe ([(VarId,Kind)],[(ConId, [Type])]) */ - : { $$ = gc0(NIL); } - | ALL ifaceForall ifaceContext IMPLIES { $$ = gc4(pair($2,$3)); } - ; - -ifaceType - : ALL ifaceForall ifaceContext IMPLIES ifaceType { $$ = gc5(ap(POLYTYPE,triple($2,$3,$5))); } - | ifaceBType ARROW ifaceType { $$ = gc3(fn($1,$3)); } - | ifaceBType { $$ = gc1($1); } - ; - -ifaceForall /* [(VarId,Kind)] */ - : '[' ifaceTVBndrs ']' { $$ = gc3($2); } - ; - -ifaceDeclContext /* [(ConId, [Type])] */ - : { $$ = gc0(NIL); } - | '{' ifaceContextList1 '}' IMPLIES { $$ = gc4($2); } - ; - -ifaceContext /* [(ConId, [Type])] */ - : { $$ = gc0(NIL); } - | '{' ifaceContextList1 '}' { $$ = gc3($2); } - ; - -ifaceContextList1 /* [(ConId, [Type])] */ - : ifaceClass { $$ = gc1(singleton($1)); } - | ifaceClass ',' ifaceContextList1 { $$ = gc3(cons($1,$3)); } - ; - -ifaceClass /* (ConId, [Type]) */ - : ifaceQTCName ifaceATypes { $$ = gc2(pair($1,$2)); } - ; - -ifaceTypes2 - : ifaceType ',' ifaceType { $$ = gc3(doubleton($1,$3)); } - | ifaceType ',' ifaceTypes2 { $$ = gc3(cons($1,$3)); } - ; - -ifaceBType - : ifaceAType { $$ = gc1($1); } - | ifaceBType ifaceAType { $$ = gc2(ap($1,$2)); } - ; - -ifaceAType - : ifaceQTCName { $$ = gc1($1); } - | ifaceTVName { $$ = gc1($1); } - | '(' ')' { $$ = gc2(conPreludeUnit); } - | '(' ifaceTypes2 ')' { $$ = gc3(buildTuple($2)); } - | '[' ifaceType ']' { $$ = gc3(ap(conPreludeList,$2));} - | '{' ifaceQTCName ifaceATypes '}' { $$ = gc4(ap(DICTAP,pair($2,$3))); } - | '(' ifaceType ')' { $$ = gc3($2); } - ; - -ifaceATypes - : { $$ = gc0(NIL); } - | ifaceAType ifaceATypes { $$ = gc2(cons($1,$2)); } - ; - -ifaceEntities - : { $$ = gc0(NIL); } - | ifaceEntity ifaceEntities { $$ = gc2(cons($1,$2)); } - ; - -ifaceEntity - : ifaceEntityOcc {} - | ifaceEntityOcc ifaceStuffInside {} -| ifaceEntityOcc '|' ifaceStuffInside {} /* exporting datacons but not tycon */ - ; - -ifaceEntityOcc - : ifaceVar { $$ = gc1($1); } - | ifaceData { $$ = gc1($1); } - | ARROW { $$ = gc3(typeArrow); } - | '(' ARROW ')' { $$ = gc3(typeArrow); } /* why allow both? */ - ; - -ifaceStuffInside - : '{' ifaceValOccs '}' { $$ = gc1($1); } - ; - - -ifaceValOccs - : ifaceValOcc { $$ = gc1(singleton($1)); } - | ifaceValOcc ifaceValOccs { $$ = gc2(cons($1,$2)); } - ; - -ifaceValOcc - : ifaceVar {$$ = gc1($1); } - | ifaceData {$$ = gc1($1); } - ; - -ifaceVar : VARID {$$ = gc1($1); } - | VAROP {$$ = gc1($1); } - | '!' {$$ = gc1(varBang); } - | '.' {$$ = gc1(varDot); } - | '-' {$$ = gc1(varMinus);} - ; - -ifaceData /* ConId | QualConId */ - : CONID {$$ = gc1($1);} - | CONOP {$$ = gc1($1);} - | '(' ')' {$$ = gc2(conPreludeUnit);} - | '[' ']' {$$ = gc2(conPreludeList);} - ; - -ifaceVarName /* VarId */ - : ifaceVar { $$ = gc1($1); } - ; - -ifaceDataName /* ConId|QualConId */ - : ifaceData { $$ = gc1($1); } - ; - -ifaceVarNames1 /* [VarId] */ - : ifaceVarName { $$ = gc1(singleton($1)); } - | ifaceVarName ifaceVarNames1 { $$ = gc2(cons($1,$2)); } - ; - -ifaceTVName /* VarId */ - : VARID { $$ = gc1($1); } - ; - -ifaceTVBndrs /* [(VarId,Kind)] */ - : { $$ = gc0(NIL); } - | ifaceTVBndr ifaceTVBndrs { $$ = gc2(cons($1,$2)); } - ; - -ifaceTVBndr /* (VarId,Kind) */ - : ifaceTVName { $$ = gc1(pair($1,STAR)); } - | ifaceTVName COCO ifaceAKind { $$ = gc3(pair($1,$3)); } - ; - -ifaceKind - : ifaceAKind { $$ = gc1($1); } - | ifaceAKind ARROW ifaceKind { $$ = gc3(fn($1,$3)); } - ; - -ifaceAKind - : VAROP { $$ = gc1(STAR); } /* should be '*' */ - | '(' ifaceKind ')' { $$ = gc1($1); } - ; - -ifaceTCName - : CONID { $$ = gc1($1); } - | CONOP { $$ = gc1($1); } - | '(' ARROW ')' { $$ = gc3(typeArrow); } - | '[' ']' { $$ = gc1(conPreludeList); } - ; - -ifaceQTCName - : ifaceTCName { $$ = gc1($1); } - | QCONID { $$ = gc1($1); } - | QCONOP { $$ = gc1($1); } - ; - -/*- Haskell module header/import parsing: ---------------------------------*/ +/*- Haskell module header/import parsing: ----------------------------------- + * Syntax for Haskell modules (module headers and imports) is parsed but + * most of it is ignored. However, module names in import declarations + * are used, of course, if import chasing is turned on. + *-------------------------------------------------------------------------*/ /* In Haskell 1.2, the default module header was "module Main where" * In 1.3, this changed to "module Main(main) where". @@ -362,9 +115,9 @@ topModule : startMain begin modBody end { setExportList(singleton(ap(MODULEENT,mkCon(module(currentModule).text)))); $$ = gc3($3); } - | MODULETOK modname expspec WHERE '{' modBody end + | TMODULE modname expspec WHERE '{' modBody end {setExportList($3); $$ = gc7($6);} - | MODULETOK error {syntaxError("module definition");} + | TMODULE error {syntaxError("module definition");} ; /* To implement the Haskell module system, we have to keep track of the * current module. We rely on the use of LALR parsing to ensure that this @@ -375,7 +128,7 @@ startMain : /* empty */ {startModule(conMain); ; modname : CONID {startModule($1); $$ = gc1(NIL);} ; -modid : CONID {$$ = gc1($1);} +modid : CONID {$$ = $1;} | STRINGLIT { extern String scriptFile; String modName = findPathname(scriptFile,textToStr(textOf($1))); if (modName) { /* fillin pathname if known */ @@ -385,12 +138,9 @@ modid : CONID {$$ = gc1($1);} } } ; -modBody : topDecls {$$ = gc1($1);} - | fixDecls ';' topDecls {$$ = gc3($3);} +modBody : topDecls {$$ = $1;} | impDecls chase {$$ = gc2(NIL);} | impDecls ';' chase topDecls {$$ = gc4($4);} - | impDecls ';' chase fixDecls ';' topDecls - {$$ = gc6($6);} ; /*- Exports: --------------------------------------------------------------*/ @@ -406,28 +156,22 @@ exports : exports ',' export {$$ = gc3(cons($3,$1));} /* The qcon should be qconid. * Relaxing the rule lets us explicitly export (:) from the Prelude. */ -export : qvar {$$ = gc1($1);} - | qcon {$$ = gc1($1);} - | qcon2 '(' UPTO ')' {$$ = gc4(pair($1,DOTDOT));} - | qcon2 '(' qnames ')' {$$ = gc4(pair($1,$3));} - | MODULETOK modid {$$ = gc2(ap(MODULEENT,$2));} +export : qvar {$$ = $1;} + | qcon {$$ = $1;} + | qconid '(' UPTO ')' {$$ = gc4(pair($1,DOTDOT));} + | qconid '(' qnames ')' {$$ = gc4(pair($1,$3));} + | TMODULE modid {$$ = gc2(ap(MODULEENT,$2));} ; qnames : /* empty */ {$$ = gc0(NIL);} | ',' {$$ = gc1(NIL);} - | qnames1 {$$ = gc1($1);} + | qnames1 {$$ = $1;} | qnames1 ',' {$$ = gc2($1);} ; qnames1 : qnames1 ',' qname {$$ = gc3(cons($3,$1));} | qname {$$ = gc1(singleton($1));} ; -qname : qvar {$$ = gc1($1);} - | qcon {$$ = gc1($1);} - | '(' ')' {$$ = gc2(conPreludeUnit);} - | '[' ']' {$$ = gc2(conPreludeList);} - ; -qcon2 : '(' ')' {$$ = gc2(conPreludeUnit);} - | '[' ']' {$$ = gc2(conPreludeList);} - | qconid {$$ = gc1($1);} +qname : qvar {$$ = $1;} + | qcon {$$ = $1;} ; /*- Import declarations: --------------------------------------------------*/ @@ -467,50 +211,34 @@ impspec : /* empty */ {$$ = gc0(DOTDOT);} ; imports : /* empty */ {$$ = gc0(NIL);} | ',' {$$ = gc1(NIL);} - | imports1 {$$ = gc1($1);} + | imports1 {$$ = $1;} | imports1 ',' {$$ = gc2($1);} ; imports1 : imports1 ',' import {$$ = gc3(cons($3,$1));} | import {$$ = gc1(singleton($1));} ; -import : var {$$ = gc1($1);} - | CONID {$$ = gc1($1);} +import : var {$$ = $1;} + | CONID {$$ = $1;} | CONID '(' UPTO ')' {$$ = gc4(pair($1,DOTDOT));} | CONID '(' names ')' {$$ = gc4(pair($1,$3));} ; names : /* empty */ {$$ = gc0(NIL);} | ',' {$$ = gc1(NIL);} - | names1 {$$ = gc1($1);} + | names1 {$$ = $1;} | names1 ',' {$$ = gc2($1);} ; names1 : names1 ',' name {$$ = gc3(cons($3,$1));} | name {$$ = gc1(singleton($1));} ; -name : var {$$ = gc1($1);} - | con {$$ = gc1($1);} - ; - -/*- Fixity declarations: --------------------------------------------------*/ - -fixDecls : fixDecls ';' fixDecl {$$ = gc2(NIL);} - | fixDecl {$$ = gc0(NIL);} - ; -fixDecl : INFIXL optdigit ops {fixDefn(LEFT_ASS,$1,$2,$3); sp-=3;} - | INFIXR optdigit ops {fixDefn(RIGHT_ASS,$1,$2,$3);sp-=3;} - | INFIX optdigit ops {fixDefn(NON_ASS,$1,$2,$3); sp-=3;} - ; -optdigit : NUMLIT {$$ = gc1(checkPrec($1));} - | /* empty */ {$$ = gc0(mkInt(DEF_PREC));} - ; -ops : ops ',' op {$$ = gc3(cons($3,$1));} - | op {$$ = gc1(cons($1,NIL));} +name : var {$$ = $1;} + | con {$$ = $1;} ; /*- Top-level declarations: -----------------------------------------------*/ topDecls : /* empty */ {$$ = gc0(NIL);} | ';' {$$ = gc1(NIL);} - | topDecls1 {$$ = gc1($1);} + | topDecls1 {$$ = $1;} | topDecls1 ';' {$$ = gc2($1);} ; topDecls1 : topDecls1 ';' topDecl {$$ = gc2($1);} @@ -525,54 +253,59 @@ topDecl : TYPE tyLhs '=' type {defTycon(4,$3,$2,$4,SYNONYM);} | TYPE tyLhs '=' type IN invars {defTycon(6,$3,$2, ap($4,$6),RESTRICTSYN);} + | TYPE error {syntaxError("type definition");} | DATA btype2 '=' constrs deriving {defTycon(5,$3,checkTyLhs($2), ap(rev($4),$5),DATATYPE);} | DATA context IMPLIES tyLhs '=' constrs deriving {defTycon(7,$5,$4, - ap(ap(QUAL,pair($2,rev($6))), + ap(qualify($2,rev($6)), $7),DATATYPE);} | DATA btype2 {defTycon(2,$1,checkTyLhs($2), ap(NIL,NIL),DATATYPE);} | DATA context IMPLIES tyLhs {defTycon(4,$1,$4, - ap(ap(QUAL,pair($2,NIL)), + ap(qualify($2,NIL), NIL),DATATYPE);} + | DATA error {syntaxError("data definition");} | TNEWTYPE btype2 '=' nconstr deriving {defTycon(5,$3,checkTyLhs($2), ap($4,$5),NEWTYPE);} | TNEWTYPE context IMPLIES tyLhs '=' nconstr deriving {defTycon(7,$5,$4, - ap(ap(QUAL,pair($2,$6)), + ap(qualify($2,$6), $7),NEWTYPE);} + | TNEWTYPE error {syntaxError("newtype definition");} ; -tyLhs : tyLhs varid1 {$$ = gc2(ap($1,$2));} - | CONID {$$ = gc1($1);} - | '[' type ']' {$$ = gc3(ap(conList,$2));} - | '(' ')' {$$ = gc2(conUnit);} - | '(' typeTuple ')' {$$ = gc3(buildTuple($2));} +tyLhs : tyLhs varid {$$ = gc2(ap($1,$2));} + | CONID {$$ = $1;} | error {syntaxError("type defn lhs");} ; invars : invars ',' invar {$$ = gc3(cons($3,$1));} | invar {$$ = gc1(cons($1,NIL));} ; -invar : qvar COCO topType {$$ = gc3(sigdecl($2,singleton($1), - $3));} - | qvar {$$ = gc1($1);} +invar : var COCO topType {$$ = gc3(sigdecl($2,singleton($1), + $3));} + | var {$$ = $1;} ; -constrs : constrs '|' constr {$$ = gc3(cons($3,$1));} - | constr {$$ = gc1(cons($1,NIL));} +constrs : constrs '|' pconstr {$$ = gc3(cons($3,$1));} + | pconstr {$$ = gc1(cons($1,NIL));} ; -constr : '!' btype conop bbtype {$$ = gc4(ap2($3,bang($2),$4));} - | btype1 conop bbtype {$$ = gc3(ap2($2,$1,$3));} - | btype2 conop bbtype {$$ = gc3(ap2($2,$1,$3));} - | bpolyType conop bbtype {$$ = gc3(ap2($2,$1,$3));} - | btype2 {$$ = gc1($1);} - | btype3 {$$ = gc1($1);} - | btype4 {$$ = gc1($1);} +pconstr : ALL varids '.' qconstr {$$ = gc4(ap(POLYTYPE, + pair(rev($2),$4)));} + | qconstr {$$ = $1;} + ; +qconstr : context IMPLIES constr {$$ = gc3(qualify($1,$3));} + | constr {$$ = $1;} + ; +constr : '!' btype conop bbtype {$$ = gc4(ap(ap($3,bang($2)),$4));} + | btype1 conop bbtype {$$ = gc3(ap(ap($2,$1),$3));} + | btype2 conop bbtype {$$ = gc3(ap(ap($2,$1),$3));} + | bpolyType conop bbtype {$$ = gc3(ap(ap($2,$1),$3));} + | btype2 {$$ = $1;} + | btype3 {$$ = $1;} + | btype4 {$$ = $1;} | con '{' fieldspecs '}' {$$ = gc4(ap(LABC,pair($1,rev($3))));} - | '[' ']' {$$ = gc2(conNil);} - | '(' ')' {$$ = gc2(conUnit);} - | '(' typeTuple ')' {$$ = gc3(buildTuple($2));} + | con '{' '}' {$$ = gc3(ap(LABC,pair($1,NIL)));} | error {syntaxError("data type definition");} ; btype3 : btype2 '!' atype {$$ = gc3(ap($1,bang($3)));} @@ -586,17 +319,17 @@ btype4 : btype2 bpolyType {$$ = gc2(ap($1,$2));} | btype4 '!' atype {$$ = gc3(ap($1,bang($3)));} ; bbtype : '!' btype {$$ = gc2(bang($2));} - | btype {$$ = gc1($1);} - | bpolyType {$$ = gc1($1);} + | btype {$$ = $1;} + | bpolyType {$$ = $1;} + ; +nconstr : pconstr {$$ = gc1(singleton($1));} ; fieldspecs: fieldspecs ',' fieldspec {$$ = gc3(cons($3,$1));} | fieldspec {$$ = gc1(cons($1,NIL));} ; fieldspec : vars COCO polyType {$$ = gc3(pair(rev($1),$3));} | vars COCO type {$$ = gc3(pair(rev($1),$3));} - ; -nconstr : con atype {$$ = gc2(singleton(ap($1,$2)));} - | con bpolyType {$$ = gc2(singleton(ap($1,$2)));} + | vars COCO '!' type {$$ = gc4(pair(rev($1),bang($4)));} ; deriving : /* empty */ {$$ = gc0(NIL);} | DERIVING qconid {$$ = gc2(singleton($2));} @@ -633,6 +366,9 @@ unsafe_flag: /* empty */ {$$ = gc0(NIL);} topDecl : TCLASS crule wherePart {classDefn(intOf($1),$2,$3); sp-=3;} | TINSTANCE irule wherePart {instDefn(intOf($1),$2,$3); sp-=3;} | DEFAULT '(' dtypes ')' {defaultDefn(intOf($1),$3); sp-=4;} + | TCLASS error {syntaxError("class declaration");} + | TINSTANCE error {syntaxError("instance declaration");} + | DEFAULT error {syntaxError("default declaration");} ; crule : context IMPLIES btype2 {$$ = gc3(pair($1,checkPred($3)));} | btype2 {$$ = gc1(pair(NIL,checkPred($1)));} @@ -649,35 +385,35 @@ dtypes1 : dtypes1 ',' type {$$ = gc3(cons($3,$1));} /*- Type expressions: -----------------------------------------------------*/ -sigType : context IMPLIES type {$$ = gc3(ap(QUAL,pair($1,$3)));} - | type {$$ = gc1($1);} - ; -topType : context IMPLIES topType1 {$$ = gc3(ap(QUAL,pair($1,$3)));} - | topType1 {$$ = gc1($1);} +topType : context IMPLIES topType1 {$$ = gc3(qualify($1,$3));} + | topType1 {$$ = $1;} ; topType1 : bpolyType ARROW topType1 {$$ = gc3(fn($1,$3));} | btype1 ARROW topType1 {$$ = gc3(fn($1,$3));} | btype2 ARROW topType1 {$$ = gc3(fn($1,$3));} - | btype {$$ = gc1($1);} + | btype {$$ = $1;} ; -polyType : ALL varid1s '.' sigType {$$ = gc4(ap(POLYTYPE, +polyType : ALL varids '.' sigType {$$ = gc4(ap(POLYTYPE, pair(rev($2),$4)));} - | bpolyType {$$ = gc1($1);} + | bpolyType {$$ = $1;} ; bpolyType : '(' polyType ')' {$$ = gc3($2);} ; -varid1s : varid1s ',' varid1 {$$ = gc3(cons($3,$1));} - | varid1 {$$ = gc1(cons($1,NIL));} +varids : varids ',' varid {$$ = gc3(cons($3,$1));} + | varid {$$ = gc1(singleton($1));} + ; +sigType : context IMPLIES type {$$ = gc3(qualify($1,$3));} + | type {$$ = $1;} ; context : '(' ')' {$$ = gc2(NIL);} | btype2 {$$ = gc1(singleton(checkPred($1)));} | '(' btype2 ')' {$$ = gc3(singleton(checkPred($2)));} - | '(' btypes2 ')' {$$ = gc3(checkContext($2));} + | '(' btypes2 ')' {$$ = gc3(checkContext(rev($2)));} /*#if TREX*/ | lacks {$$ = gc1(singleton($1));} - | '(' lacks1 ')' {$$ = gc3(checkContext($2));} + | '(' lacks1 ')' {$$ = gc3(checkContext(rev($2)));} ; -lacks : varid1 '\\' varid1 { +lacks : varid '\\' varid { #if TREX $$ = gc3(ap(mkExt(textOf($3)),$1)); #else @@ -693,28 +429,28 @@ lacks1 : btypes2 ',' lacks {$$ = gc3(cons($3,$1));} ; /*#endif*/ -type : type1 {$$ = gc1($1);} - | btype2 {$$ = gc1($1);} +type : type1 {$$ = $1;} + | btype2 {$$ = $1;} ; -type1 : btype1 {$$ = gc1($1);} +type1 : btype1 {$$ = $1;} | btype1 ARROW type {$$ = gc3(fn($1,$3));} | btype2 ARROW type {$$ = gc3(fn($1,$3));} | error {syntaxError("type expression");} ; -btype : btype1 {$$ = gc1($1);} - | btype2 {$$ = gc1($1);} +btype : btype1 {$$ = $1;} + | btype2 {$$ = $1;} ; btype1 : btype1 atype {$$ = gc2(ap($1,$2));} - | atype1 {$$ = gc1($1);} + | atype1 {$$ = $1;} ; btype2 : btype2 atype {$$ = gc2(ap($1,$2));} - | qconid {$$ = gc1($1);} + | qconid {$$ = $1;} ; -atype : atype1 {$$ = gc1($1);} - | qconid {$$ = gc1($1);} +atype : atype1 {$$ = $1;} + | qconid {$$ = $1;} ; -atype1 : varid1 {$$ = gc1($1);} - | '(' ')' {$$ = gc2(conPreludeUnit);} +atype1 : varid {$$ = $1;} + | '(' ')' {$$ = gc2(typeUnit);} | '(' ARROW ')' {$$ = gc3(typeArrow);} | '(' type1 ')' {$$ = gc3($2);} | '(' btype2 ')' {$$ = gc3($2);} @@ -731,13 +467,10 @@ atype1 : varid1 {$$ = gc1($1);} } | '(' tfields '|' type ')' {$$ = gc5(revOnto($2,$4));} /*#endif*/ - | '[' type ']' {$$ = gc3(ap(conPreludeList,$2));} - | '[' ']' {$$ = gc2(conPreludeList);} + | '[' type ']' {$$ = gc3(ap(typeList,$2));} + | '[' ']' {$$ = gc2(typeList);} | '_' {$$ = gc1(inventVar());} ; -tupCommas : tupCommas ',' {$$ = gc2(mkTuple(tupleOf($1)+1));} - | ',' {$$ = gc1(mkTuple(2));} - ; btypes2 : btypes2 ',' btype2 {$$ = gc3(cons($3,$1));} | btype2 ',' btype2 {$$ = gc3(cons($3,cons($1,NIL)));} ; @@ -756,155 +489,224 @@ tfield : varid COCO type {$$ = gc3(ap(mkExt(textOf($1)),$3));} /*- Value declarations: ---------------------------------------------------*/ -decllist : '{' decls end {$$ = gc3($2);} +gendecl : INFIXN optDigit ops {$$ = gc3(fixdecl($1,$3,NON_ASS,$2));} + | INFIXN error {syntaxError("fixity decl");} + | INFIXL optDigit ops {$$ = gc3(fixdecl($1,$3,LEFT_ASS,$2));} + | INFIXL error {syntaxError("fixity decl");} + | INFIXR optDigit ops {$$ = gc3(fixdecl($1,$3,RIGHT_ASS,$2));} + | INFIXR error {syntaxError("fixity decl");} + | vars COCO topType {$$ = gc3(sigdecl($2,$1,$3));} + | vars COCO error {syntaxError("type signature");} ; -decls : /* empty */ {$$ = gc0(NIL);} - | ';' {$$ = gc1(NIL);} - | decls1 {$$ = gc1($1);} +optDigit : NUMLIT {$$ = gc1(checkPrec($1));} + | /* empty */ {$$ = gc0(mkInt(DEF_PREC));} + ; +ops : ops ',' op {$$ = gc3(cons($3,$1));} + | op {$$ = gc1(singleton($1));} + ; +vars : vars ',' var {$$ = gc3(cons($3,$1));} + | var {$$ = gc1(singleton($1));} + ; +decls : '{' decls0 end {$$ = gc3($2);} + | '{' decls1 end {$$ = gc3($2);} + ; +decls0 : /* empty */ {$$ = gc0(NIL);} + | decls0 ';' {$$ = gc2($1);} | decls1 ';' {$$ = gc2($1);} ; -decls1 : decls1 ';' decl {$$ = gc3(cons($3,$1));} - | decl {$$ = gc1(cons($1,NIL));} +decls1 : decls0 decl {$$ = gc2(cons($2,$1));} + ; +decl : gendecl {$$ = $1;} + | funlhs rhs {$$ = gc2(ap(FUNBIND,pair($1,$2)));} + | funlhs COCO type rhs {$$ = gc4(ap(FUNBIND, + pair($1,ap(RSIGN, + ap($4,$3)))));} + | pat0 rhs {$$ = gc2(ap(PATBIND,pair($1,$2)));} + ; +funlhs : funlhs0 {$$ = $1;} + | funlhs1 {$$ = $1;} + | npk {$$ = $1;} + ; +funlhs0 : pat10_vI varop pat0 {$$ = gc3(ap2($2,$1,$3));} + | infixPat varop pat0 {$$ = gc3(ap2($2,$1,$3));} + | NUMLIT varop pat0 {$$ = gc3(ap2($2,$1,$3));} + | var varop_pl pat0 {$$ = gc3(ap2($2,$1,$3));} + | var '+' pat0_INT {$$ = gc3(ap2(varPlus,$1,$3));} ; -/* Sneakily using qvars to eliminate a conflict... */ -decl : qvars COCO topType {$$ = gc3(sigdecl($2,$1,$3));} - | opExp rhs {$$ = gc2(pair($1,$2));} +funlhs1 : '(' funlhs0 ')' apat {$$ = gc4(ap($2,$4));} + | '(' funlhs1 ')' apat {$$ = gc4(ap($2,$4));} + | '(' npk ')' apat {$$ = gc4(ap($2,$4));} + | var apat {$$ = gc2(ap($1,$2));} + | funlhs1 apat {$$ = gc2(ap($1,$2));} ; rhs : rhs1 wherePart {$$ = gc2(letrec($2,$1));} | error {syntaxError("declaration");} ; rhs1 : '=' exp {$$ = gc2(pair($1,$2));} - | gdefs {$$ = gc1(grded(rev($1)));} + | gdrhs {$$ = gc1(grded(rev($1)));} ; -wherePart : WHERE decllist {$$ = gc2($2);} - | /*empty*/ {$$ = gc0(NIL);} +gdrhs : gdrhs gddef {$$ = gc2(cons($2,$1));} + | gddef {$$ = gc1(singleton($1));} ; -gdefs : gdefs gdef {$$ = gc2(cons($2,$1));} - | gdef {$$ = gc1(cons($1,NIL));} +gddef : '|' exp0 '=' exp {$$ = gc4(pair($3,pair($2,$4)));} ; -gdef : '|' exp '=' exp {$$ = gc4(pair($3,pair($2,$4)));} +wherePart : /* empty */ {$$ = gc0(NIL);} + | WHERE decls {$$ = gc2($2);} ; -vars : vars ',' var {$$ = gc3(cons($3,$1));} - | var {$$ = gc1(cons($1,NIL));} - ; -qvars : qvars ',' qvar {$$ = gc3(cons($3,$1));} - | qvar {$$ = gc1(cons($1,NIL));} - ; - +/*- Patterns: -------------------------------------------------------------*/ -var : varid {$$ = gc1($1);} - | '(' '-' ')' {$$ = gc3(varMinus);} +pat : npk {$$ = $1;} + | pat_npk {$$ = $1;} ; -varid : varid1 {$$ = gc1($1);} - | '(' VAROP ')' {$$ = gc3($2);} - | '(' '!' ')' {$$ = gc3(varBang);} - | '(' '.' ')' {$$ = gc3(varDot);} +pat_npk : pat0 COCO type {$$ = gc3(ap(ESIGN,pair($1,$3)));} + | pat0 {$$ = $1;} ; -varid1 : VARID {$$ = gc1($1);} - | HIDING {$$ = gc1(varHiding);} - | QUALIFIED {$$ = gc1(varQualified);} - | ASMOD {$$ = gc1(varAsMod);} +npk : var '+' NUMLIT {$$ = gc3(ap2(varPlus,$1,$3));} ; -qvar : qvarid {$$ = gc1($1);} - | '(' qvarsym ')' {$$ = gc3($2);} - | '(' '.' ')' {$$ = gc3(varDot);} - | '(' '!' ')' {$$ = gc3(varBang);} - | '(' '-' ')' {$$ = gc3(varMinus);} +pat0 : var {$$ = $1;} + | NUMLIT {$$ = $1;} + | pat0_vI {$$ = $1;} ; -qvarid : varid1 {$$ = gc1($1);} - | QVARID {$$ = gc1($1);} +pat0_INT : var {$$ = $1;} + | pat0_vI {$$ = $1;} ; - -op : varop {$$ = gc1($1);} - | conop {$$ = gc1($1);} - | '-' {$$ = gc1(varMinus);} +pat0_vI : pat10_vI {$$ = $1;} + | infixPat {$$ = gc1(ap(INFIX,$1));} ; -qop : qvarop {$$ = gc1($1);} - | qconop {$$ = gc1($1);} - | '-' {$$ = gc1(varMinus);} +infixPat : '-' pat10 {$$ = gc2(ap(NEG,only($2)));} + | var qconop pat10 {$$ = gc3(ap(ap($2,only($1)),$3));} + | var qconop '-' pat10 {$$ = gc4(ap(NEG,ap2($2,only($1),$4)));} + | NUMLIT qconop pat10 {$$ = gc3(ap(ap($2,only($1)),$3));} + | NUMLIT qconop '-' pat10 {$$ = gc4(ap(NEG,ap2($2,only($1),$4)));} + | pat10_vI qconop pat10 {$$ = gc3(ap(ap($2,only($1)),$3));} + | pat10_vI qconop '-' pat10 {$$ = gc4(ap(NEG,ap2($2,only($1),$4)));} + | infixPat qconop pat10 {$$ = gc3(ap(ap($2,$1),$3));} + | infixPat qconop '-' pat10 {$$ = gc4(ap(NEG,ap(ap($2,$1),$4)));} ; - -varop : VAROP {$$ = gc1($1);} - | '!' {$$ = gc1(varBang);} - | '.' {$$ = gc1(varDot);} - | '`' varid1 '`' {$$ = gc3($2);} +pat10 : fpat {$$ = $1;} + | apat {$$ = $1;} ; -qvarop : qvarsym {$$ = gc1($1);} - | '!' {$$ = gc1(varBang);} - | '.' {$$ = gc1(varDot);} - | '`' qvarid '`' {$$ = gc3($2);} +pat10_vI : fpat {$$ = $1;} + | apat_vI {$$ = $1;} ; -qvarsym : VAROP {$$ = gc1($1);} - | QVAROP {$$ = gc1($1);} +fpat : fpat apat {$$ = gc2(ap($1,$2));} + | gcon apat {$$ = gc2(ap($1,$2));} ; - -con : CONID {$$ = gc1($1);} - | '(' CONOP ')' {$$ = gc3($2);} +apat : NUMLIT {$$ = $1;} + | var {$$ = $1;} + | apat_vI {$$ = $1;} ; -qcon : qconid {$$ = gc1($1);} - | '(' qconsym ')' {$$ = gc3($2);} +apat_vI : var '@' apat {$$ = gc3(ap(ASPAT,pair($1,$3)));} + | gcon {$$ = $1;} + | qcon '{' patbinds '}' {$$ = gc4(ap(CONFLDS,pair($1,$3)));} + | CHARLIT {$$ = $1;} + | STRINGLIT {$$ = $1;} + | '_' {$$ = gc1(WILDCARD);} + | '(' pat_npk ')' {$$ = gc3($2);} + | '(' npk ')' {$$ = gc3($2);} + | '(' pats2 ')' {$$ = gc3(buildTuple($2));} + | '[' pats1 ']' {$$ = gc3(ap(FINLIST,rev($2)));} + | '~' apat {$$ = gc2(ap(LAZYPAT,$2));} +/*#if TREX*/ + | '(' patfields ')' { +#if TREX + $$ = gc3(revOnto($2,nameNoRec)); +#else + $$ = gc3(NIL); +#endif + } + | '(' patfields '|' pat ')' {$$ = gc5(revOnto($2,$4));} +/*#endif TREX*/ ; -qconid : CONID {$$ = gc1($1);} - | QCONID {$$ = gc1($1);} +pats2 : pats2 ',' pat {$$ = gc3(cons($3,$1));} + | pat ',' pat {$$ = gc3(cons($3,singleton($1)));} ; -qconsym : CONOP {$$ = gc1($1);} - | QCONOP {$$ = gc1($1);} +pats1 : pats1 ',' pat {$$ = gc3(cons($3,$1));} + | pat {$$ = gc1(singleton($1));} ; - -conop : CONOP {$$ = gc1($1);} - | '`' CONID '`' {$$ = gc3($2);} +patbinds : /* empty */ {$$ = gc0(NIL);} + | patbinds1 {$$ = gc1(rev($1));} + ; +patbinds1 : patbinds1 ',' patbind {$$ = gc3(cons($3,$1));} + | patbind {$$ = gc1(singleton($1));} ; -qconop : qconsym {$$ = gc1($1);} - | '`' qconid '`' {$$ = gc3($2);} +patbind : qvar '=' pat {$$ = gc3(pair($1,$3));} + | var {$$ = $1;} + ; +/*#if TREX*/ +patfields : patfields ',' patfield {$$ = gc3(cons($3,$1));} + | patfield {$$ = gc1(singleton($1));} ; +patfield : varid '=' pat { +#if TREX + $$ = gc3(ap(mkExt(textOf($1)),$3)); +#else + noTREX("a pattern"); +#endif + } + ; +/*#endif TREX*/ /*- Expressions: ----------------------------------------------------------*/ -exp : exp1 {$$ = gc1($1);} +exp : exp_err {$$ = $1;} | error {syntaxError("expression");} ; -exp1 : opExp COCO sigType {$$ = gc3(ap(ESIGN,pair($1,$3)));} - | opExp {$$ = gc1($1);} +exp_err : exp0a COCO sigType {$$ = gc3(ap(ESIGN,pair($1,$3)));} + | exp0 {$$ = $1;} + ; +exp0 : exp0a {$$ = $1;} + | exp0b {$$ = $1;} + ; +exp0a : infixExpa {$$ = gc1(ap(INFIX,$1));} + | exp10a {$$ = $1;} ; -opExp : opExp0 {$$ = gc1(tidyInfix($1));} - | pfxExp {$$ = gc1($1);} +exp0b : infixExpb {$$ = gc1(ap(INFIX,$1));} + | exp10b {$$ = $1;} ; -opExp0 : opExp0 qop '-' pfxExp {$$ = gc4(ap(NEG,ap(ap($2,$1),$4)));} - | opExp0 qop pfxExp {$$ = gc3(ap2($2,$1,$3));} - | '-' pfxExp {$$ = gc2(ap(NEG,only($2)));} - | pfxExp qop pfxExp {$$ = gc3(ap(ap($2,only($1)),$3));} - | pfxExp qop '-' pfxExp {$$ = gc4(ap(NEG, +infixExpa : infixExpa qop '-' exp10a {$$ = gc4(ap(NEG,ap(ap($2,$1),$4)));} + | infixExpa qop exp10a {$$ = gc3(ap(ap($2,$1),$3));} + | '-' exp10a {$$ = gc2(ap(NEG,only($2)));} + | exp10a qop '-' exp10a {$$ = gc4(ap(NEG, ap(ap($2,only($1)),$4)));} + | exp10a qop exp10a {$$ = gc3(ap(ap($2,only($1)),$3));} + ; +infixExpb : infixExpa qop '-' exp10b {$$ = gc4(ap(NEG,ap(ap($2,$1),$4)));} + | infixExpa qop exp10b {$$ = gc3(ap(ap($2,$1),$3));} + | '-' exp10b {$$ = gc2(ap(NEG,only($2)));} + | exp10a qop '-' exp10b {$$ = gc4(ap(NEG, + ap(ap($2,only($1)),$4)));} + | exp10a qop exp10b {$$ = gc3(ap(ap($2,only($1)),$3));} + ; +exp10a : CASEXP exp OF '{' alts end {$$ = gc6(ap(CASE,pair($2,rev($5))));} + | DO '{' stmts end {$$ = gc4(ap(DOCOMP,checkDo($3)));} + | appExp {$$ = $1;} ; -pfxExp : '\\' pats ARROW exp {$$ = gc4(ap(LAMBDA, +exp10b : '\\' pats ARROW exp {$$ = gc4(ap(LAMBDA, pair(rev($2), pair($3,$4))));} - | LET decllist IN exp {$$ = gc4(letrec($2,$4));} + | LET decls IN exp {$$ = gc4(letrec($2,$4));} | IF exp THEN exp ELSE exp {$$ = gc6(ap(COND,triple($2,$4,$6)));} - | CASEXP exp OF '{' alts end {$$ = gc6(ap(CASE,pair($2,rev($5))));} - | DO '{' stmts end {$$ = gc4(ap(DOCOMP,checkDo($3)));} - | appExp {$$ = gc1($1);} ; -pats : pats atomic {$$ = gc2(cons($2,$1));} - | atomic {$$ = gc1(cons($1,NIL));} +pats : pats apat {$$ = gc2(cons($2,$1));} + | apat {$$ = gc1(cons($1,NIL));} ; -appExp : appExp atomic {$$ = gc2(ap($1,$2));} - | atomic {$$ = gc1($1);} +appExp : appExp aexp {$$ = gc2(ap($1,$2));} + | aexp {$$ = $1;} ; -atomic : qvar {$$ = gc1($1);} - | qvar '@' atomic {$$ = gc3(ap(ASPAT,pair($1,$3)));} - | '~' atomic {$$ = gc2(ap(LAZYPAT,$2));} +aexp : qvar {$$ = $1;} + | qvar '@' aexp {$$ = gc3(ap(ASPAT,pair($1,$3)));} + | '~' aexp {$$ = gc2(ap(LAZYPAT,$2));} | '_' {$$ = gc1(WILDCARD);} - | qcon {$$ = gc1($1);} + | gcon {$$ = $1;} | qcon '{' fbinds '}' {$$ = gc4(ap(CONFLDS,pair($1,$3)));} - | atomic '{' fbinds '}' {$$ = gc4(ap(UPDFLDS, + | aexp '{' fbinds '}' {$$ = gc4(ap(UPDFLDS, triple($1,NIL,$3)));} - | '(' ')' {$$ = gc2(conPreludeUnit);} - | NUMLIT {$$ = gc1($1);} - | CHARLIT {$$ = gc1($1);} - | STRINGLIT {$$ = gc1($1);} - | REPEAT {$$ = gc1($1);} + | NUMLIT {$$ = $1;} + | CHARLIT {$$ = $1;} + | STRINGLIT {$$ = $1;} + | REPEAT {$$ = $1;} | '(' exp ')' {$$ = gc3($2);} | '(' exps2 ')' {$$ = gc3(buildTuple($2));} /*#if TREX*/ @@ -916,13 +718,12 @@ atomic : qvar {$$ = gc1($1);} #endif } | '(' vfields '|' exp ')' {$$ = gc5(revOnto($2,$4));} - | RECSELID {$$ = gc1($1);} + | RECSELID {$$ = $1;} /*#endif*/ | '[' list ']' {$$ = gc3($2);} - | '(' pfxExp qop ')' {$$ = gc4(ap($3,$2));} - | '(' qvarop atomic ')' {$$ = gc4(ap2(varFlip,$2,$3));} - | '(' qconop atomic ')' {$$ = gc4(ap2(varFlip,$2,$3));} - | '(' tupCommas ')' {$$ = gc3($2);} + | '(' exp10a qop ')' {$$ = gc4(ap($3,$2));} + | '(' qvarop_mi exp0 ')' {$$ = gc4(ap(ap(nameFlip,$2),$3));} + | '(' qconop exp0 ')' {$$ = gc4(ap(ap(nameFlip,$2),$3));} ; exps2 : exps2 ',' exp {$$ = gc3(cons($3,$1));} | exp ',' exp {$$ = gc3(cons($3,cons($1,NIL)));} @@ -931,7 +732,7 @@ exps2 : exps2 ',' exp {$$ = gc3(cons($3,$1));} vfields : vfields ',' vfield {$$ = gc3(cons($3,$1));} | vfield {$$ = gc1(singleton($1));} ; -vfield : qvarid '=' exp { +vfield : varid '=' exp { #if TREX $$ = gc3(ap(mkExt(textOf($1)),$3)); #else @@ -940,13 +741,13 @@ vfield : qvarid '=' exp { } ; /*#endif*/ -alts : alts1 {$$ = gc1($1);} +alts : alts1 {$$ = $1;} | alts1 ';' {$$ = gc2($1);} ; alts1 : alts1 ';' alt {$$ = gc3(cons($3,$1));} | alt {$$ = gc1(cons($1,NIL));} ; -alt : opExp altRhs wherePart {$$ = gc3(pair($1,letrec($3,$2)));} +alt : pat altRhs wherePart {$$ = gc3(pair($1,letrec($3,$2)));} ; altRhs : guardAlts {$$ = gc1(grded(rev($1)));} | ARROW exp {$$ = gc2(pair($1,$2));} @@ -955,18 +756,18 @@ altRhs : guardAlts {$$ = gc1(grded(rev($1)));} guardAlts : guardAlts guardAlt {$$ = gc2(cons($2,$1));} | guardAlt {$$ = gc1(cons($1,NIL));} ; -guardAlt : '|' opExp ARROW exp {$$ = gc4(pair($3,pair($2,$4)));} +guardAlt : '|' exp0 ARROW exp {$$ = gc4(pair($3,pair($2,$4)));} ; stmts : stmts1 ';' {$$ = gc2($1);} - | stmts1 {$$ = gc1($1);} + | stmts1 {$$ = $1;} ; stmts1 : stmts1 ';' stmt {$$ = gc3(cons($3,$1));} | stmt {$$ = gc1(cons($1,NIL));} ; -stmt : exp1 FROM exp {$$ = gc3(ap(FROMQUAL,pair($1,$3)));} - | LET decllist {$$ = gc2(ap(QWHERE,$2));} - | IF exp {$$ = gc2(ap(BOOLQUAL,$2));} - | exp1 {$$ = gc1(ap(DOQUAL,$1));} +stmt : exp_err FROM exp {$$ = gc3(ap(FROMQUAL,pair($1,$3)));} + | LET decls {$$ = gc2(ap(QWHERE,$2));} +/* | IF exp {$$ = gc2(ap(BOOLQUAL,$2));}*/ + | exp_err {$$ = gc1(ap(DOQUAL,$1));} ; fbinds : /* empty */ {$$ = gc0(NIL);} | fbinds1 {$$ = gc1(rev($1));} @@ -974,28 +775,111 @@ fbinds : /* empty */ {$$ = gc0(NIL);} fbinds1 : fbinds1 ',' fbind {$$ = gc3(cons($3,$1));} | fbind {$$ = gc1(singleton($1));} ; -fbind : var {$$ = gc1($1);} +fbind : var {$$ = $1;} | qvar '=' exp {$$ = gc3(pair($1,$3));} ; /*- List Expressions: -------------------------------------------------------*/ -list : /* empty */ {$$ = gc0(conPreludeNil);} - | exp {$$ = gc1(ap(FINLIST,cons($1,NIL)));} +list : exp {$$ = gc1(ap(FINLIST,cons($1,NIL)));} | exps2 {$$ = gc1(ap(FINLIST,rev($1)));} | exp '|' quals {$$ = gc3(ap(COMP,pair($1,rev($3))));} - | exp UPTO exp {$$ = gc3(ap2(varEnumFromTo,$1,$3));} - | exp ',' exp UPTO {$$ = gc4(ap2(varEnumFromThen,$1,$3));} - | exp UPTO {$$ = gc2(ap1(varEnumFrom,$1));} - | exp ',' exp UPTO exp {$$ = gc5(ap3(varEnumFromThenTo, - $1,$3,$5));} + | exp UPTO exp {$$ = gc3(ap(ap(nameFromTo,$1),$3));} + | exp ',' exp UPTO {$$ = gc4(ap(ap(nameFromThen,$1),$3));} + | exp UPTO {$$ = gc2(ap(nameFrom,$1));} + | exp ',' exp UPTO exp {$$ = gc5(ap(ap(ap(nameFromThenTo, + $1),$3),$5));} ; quals : quals ',' qual {$$ = gc3(cons($3,$1));} | qual {$$ = gc1(cons($1,NIL));} ; qual : exp FROM exp {$$ = gc3(ap(FROMQUAL,pair($1,$3)));} | exp {$$ = gc1(ap(BOOLQUAL,$1));} - | LET decllist {$$ = gc2(ap(QWHERE,$2));} + | LET decls {$$ = gc2(ap(QWHERE,$2));} + ; + +/*- Identifiers and symbols: ----------------------------------------------*/ + +gcon : qcon {$$ = $1;} + | '(' ')' {$$ = gc2(nameUnit);} + | '[' ']' {$$ = gc2(nameNil);} + | '(' tupCommas ')' {$$ = gc3($2);} + ; +tupCommas : tupCommas ',' {$$ = gc2(mkTuple(tupleOf($1)+1));} + | ',' {$$ = gc1(mkTuple(2));} + ; +varid : VARID {$$ = $1;} + | HIDING {$$ = gc1(varHiding);} + | QUALIFIED {$$ = gc1(varQualified);} + | ASMOD {$$ = gc1(varAsMod);} + ; +qconid : QCONID {$$ = $1;} + | CONID {$$ = $1;} + ; +var : varid {$$ = $1;} + | '(' VAROP ')' {$$ = gc3($2);} + | '(' '+' ')' {$$ = gc3(varPlus);} + | '(' '-' ')' {$$ = gc3(varMinus);} + | '(' '!' ')' {$$ = gc3(varBang);} + | '(' '.' ')' {$$ = gc3(varDot);} + ; +qvar : QVARID {$$ = $1;} + | '(' QVAROP ')' {$$ = gc3($2);} + | var {$$ = $1;} + ; +con : CONID {$$ = $1;} + | '(' CONOP ')' {$$ = gc3($2);} + ; +qcon : QCONID {$$ = $1;} + | '(' QCONOP ')' {$$ = gc3($2);} + | con {$$ = $1;} + ; +varop : '+' {$$ = gc1(varPlus);} + | '-' {$$ = gc1(varMinus);} + | varop_mipl {$$ = $1;} + ; +varop_mi : '+' {$$ = gc1(varPlus);} + | varop_mipl {$$ = $1;} + ; +varop_pl : '-' {$$ = gc1(varMinus);} + | varop_mipl {$$ = $1;} + ; +varop_mipl: VAROP {$$ = $1;} + | '`' varid '`' {$$ = gc3($2);} + | '!' {$$ = gc1(varBang);} + | '.' {$$ = gc1(varDot);} + ; +qvarop : '-' {$$ = gc1(varMinus);} + | qvarop_mi {$$ = $1;} + ; +qvarop_mi : QVAROP {$$ = $1;} + | '`' QVARID '`' {$$ = gc3($2);} + | varop_mi {$$ = $1;} + ; + +conop : CONOP {$$ = $1;} + | '`' CONID '`' {$$ = gc3($2);} + ; +qconop : QCONOP {$$ = $1;} + | '`' QCONID '`' {$$ = gc3($2);} + | conop {$$ = $1;} + ; +op : varop {$$ = $1;} + | conop {$$ = $1;} + ; +qop : qvarop {$$ = $1;} + | qconop {$$ = $1;} + ; + +/*- Stuff from STG hugs ---------------------------------------------------*/ + +qvarid : varid1 {$$ = gc1($1);} + | QVARID {$$ = gc1($1);} + +varid1 : VARID {$$ = gc1($1);} + | HIDING {$$ = gc1(varHiding);} + | QUALIFIED {$$ = gc1(varQualified);} + | ASMOD {$$ = gc1(varAsMod);} ; /*- Tricks to force insertion of leading and closing braces ---------------*/ @@ -1003,7 +887,7 @@ qual : exp FROM exp {$$ = gc3(ap(FROMQUAL,pair($1,$3)));} begin : error {yyerrok; goOffside(startColumn);} ; /* deal with trailing semicolon */ -end : '}' {$$ = gc1($1);} +end : '}' {$$ = $1;} | error {yyerrok; if (canUnOffside()) { unOffside(); @@ -1045,7 +929,7 @@ Cell e; { return e; } -static Void local syntaxError(s) /* report on syntax error */ +static Void local syntaxError(s) /* report on syntax error */ String s; { ERRMSG(row) "Syntax error in %s (unexpected %s)", s, unexpected() EEND; @@ -1062,7 +946,7 @@ static String local unexpected() { /* find name for unexpected token */ #define keyword(kw) sprintf(buffer,fmt,kwd,kw); return buffer; case INFIXL : keyword("infixl"); case INFIXR : keyword("infixr"); - case INFIX : keyword("infix"); + case INFIXN : keyword("infix"); case FOREIGN : keyword("foreign"); case UNSAFE : keyword("unsafe"); case TINSTANCE : keyword("instance"); @@ -1081,10 +965,7 @@ static String local unexpected() { /* find name for unexpected token */ case DERIVING : keyword("deriving"); case DEFAULT : keyword("default"); case IMPORT : keyword("import"); - case EXPORT : keyword("export"); - case MODULETOK : keyword("module"); - case INTERFACE : keyword("interface"); - case WILDCARD : keyword("_"); + case TMODULE : keyword("module"); case ALL : keyword("forall"); #undef keyword @@ -1138,54 +1019,30 @@ static String local unexpected() { /* find name for unexpected token */ } } -static Cell local checkPrec(p) /* Check for valid precedence value */ +static Cell local checkPrec(p) /* Check for valid precedence value*/ Cell p; { - if ((!isInt(p) || intOf(p)<MIN_PREC || intOf(p)>MAX_PREC) - && (!isBignum(p) || bignumOf(p)<MIN_PREC || bignumOf(p)>MAX_PREC) - ) { + if (!isInt(p) || intOf(p)<MIN_PREC || intOf(p)>MAX_PREC) { ERRMSG(row) "Precedence value must be an integer in the range [%d..%d]", MIN_PREC, MAX_PREC EEND; } - if (isBignum(p)) { - return mkInt(bignumOf(p)); - } else { - return p; - } -} - -static Void local fixDefn(a,line,p,ops)/* Declare syntax of operators */ -Syntax a; -Cell line; -Cell p; -List ops; { - Int l = intOf(line); - a = mkSyntax(a,intOf(p)); - map2Proc(setSyntax,l,a,ops); + return p; } -static Void local setSyntax(line,sy,op)/* set syntax of individ. operator */ -Int line; -Syntax sy; -Cell op; { - addSyntax(line,textOf(op),sy); - opDefns = cons(op,opDefns); -} - -static Cell local buildTuple(tup) /* build tuple (x1,...,xn) from list*/ -List tup; { /* [xn,...,x1] */ +static Cell local buildTuple(tup) /* build tuple (x1,...,xn) from */ +List tup; { /* list [xn,...,x1] */ Int n = 0; Cell t = tup; Cell x; - do { /* . . */ - x = fst(t); /* / \ / \ */ - fst(t) = snd(t); /* xn . . xn */ - snd(t) = x; /* . ===> . */ - x = t; /* . . */ - t = fun(x); /* . . */ - n++; /* / \ / \ */ - } while (nonNull(t)); /* x1 NIL (n) x1 */ + do { /* . . */ + x = fst(t); /* / \ / \ */ + fst(t) = snd(t); /* xn . . xn */ + snd(t) = x; /* . ===> . */ + x = t; /* . . */ + t = fun(x); /* . . */ + n++; /* / \ / \ */ + } while (nonNull(t)); /* x1 NIL (n) x1 */ fst(x) = mkTuple(n); return tup; } @@ -1231,228 +1088,16 @@ Cell c; { /* T a1 ... a */ ERRMSG(row) "Illegal left hand side in datatype definition" EEND; } + assert(0); return 0; /* NOTREACHED */ } #if !TREX static Void local noTREX(where) String where; { - ERRMSG(row) "Attempt to use Typed Records with Extensions\nwhile parsing %s. This feature is disabled in this build of Hugs.", - where + ERRMSG(row) "Attempt to use TREX records while parsing %s.\n", where ETHEN + ERRTEXT "(TREX is disabled in this build of Hugs)" EEND; } #endif -/* Expressions involving infix operators or unary minus are parsed as elements - * of the following type: - * - * data OpExp = Only Exp | Neg OpExp | Infix OpExp Op Exp - * - * (The algorithms here do not assume that negation can be applied only once, - * i.e., that - - x is a syntax error, as required by the Haskell report. - * Instead, that restriction is captured by the grammar itself, given above.) - * - * There are rules of precedence and grouping, expressed by two functions: - * - * prec :: Op -> Int; assoc :: Op -> Assoc (Assoc = {L, N, R}) - * - * OpExp values are rearranged accordingly when a complete expression has - * been read using a simple shift-reduce parser whose result may be taken - * to be a value of the following type: - * - * data Exp = Atom Int | Negate Exp | Apply Op Exp Exp | Error String - * - * The machine on which this parser is based can be defined as follows: - * - * tidy :: OpExp -> [(Op,Exp)] -> Exp - * tidy (Only a) [] = a - * tidy (Only a) ((o,b):ss) = tidy (Only (Apply o a b)) ss - * tidy (Infix a o b) [] = tidy a [(o,b)] - * tidy (Infix a o b) ((p,c):ss) - * | shift o p = tidy a ((o,b):(p,c):ss) - * | red o p = tidy (Infix a o (Apply p b c)) ss - * | ambig o p = Error "ambiguous use of operators" - * tidy (Neg e) [] = tidy (tidyNeg e) [] - * tidy (Neg e) ((o,b):ss) - * | nshift o = tidy (Neg (underNeg o b e)) ss - * | nred o = tidy (tidyNeg e) ((o,b):ss) - * | nambig o = Error "illegal use of negation" - * - * At each stage, the parser can either shift, reduce, accept, or error. - * The transitions when dealing with juxtaposed operators o and p are - * determined by the following rules: - * - * shift o p = (prec o > prec p) - * || (prec o == prec p && assoc o == L && assoc p == L) - * - * red o p = (prec o < prec p) - * || (prec o == prec p && assoc o == R && assoc p == R) - * - * ambig o p = (prec o == prec p) - * && (assoc o == N || assoc p == N || assoc o /= assoc p) - * - * The transitions when dealing with juxtaposed unary minus and infix operators - * are as follows. The precedence of unary minus (infixl 6) is hardwired in - * to these definitions, as it is to the definitions of the Haskell grammar - * in the official report. - * - * nshift o = (prec o > 6) - * nred o = (prec o < 6) || (prec o == 6 && assoc o == L) - * nambig o = prec o == 6 && (assoc o == R || assoc o == N) - * - * An OpExp of the form (Neg e) means negate the last thing in the OpExp e; - * we can force this negation using: - * - * tidyNeg :: OpExp -> OpExp - * tidyNeg (Only e) = Only (Negate e) - * tidyNeg (Infix a o b) = Infix a o (Negate b) - * tidyNeg (Neg e) = tidyNeg (tidyNeg e) - * - * On the other hand, if we want to sneak application of an infix operator - * under a negation, then we use: - * - * underNeg :: Op -> Exp -> OpExp -> OpExp - * underNeg o b (Only e) = Only (Apply o e b) - * underNeg o b (Neg e) = Neg (underNeg o b e) - * underNeg o b (Infix e p f) = Infix e p (Apply o f b) - * - * As a concession to efficiency, we lower the number of calls to syntaxOf - * by keeping track of the values of sye, sys throughout the process. The - * value APPLIC is used to indicate that the syntax value is unknown. - */ - -#define UMINUS_PREC 6 /* Change these settings at your */ -#define UMINUS_ASSOC LEFT_ASS /* own risk; they may not work! */ - -static Cell local tidyInfix(e) /* convert OpExp to Expr */ -Cell e; { /* :: OpExp */ - Cell s = NIL; /* :: [(Op,Exp)] */ - Syntax sye = APPLIC; /* Syntax of op in e (init unknown)*/ - Syntax sys = APPLIC; /* Syntax of op in s (init unknown)*/ - - for (;;) - switch (whatIs(e)) { - case ONLY : e = snd(e); - while (nonNull(s)) { - Cell next = arg(fun(s)); - arg(fun(s)) = e; - e = s; - s = next; - } - return e; - - case NEG : if (nonNull(s)) { - - if (sys==APPLIC) { /* calculate sys */ - sys = identSyntax(fun(fun(s))); - if (sys==APPLIC) sys=DEF_OPSYNTAX; - } - - if (precOf(sys)==UMINUS_PREC && /* nambig */ - assocOf(sys)!=UMINUS_ASSOC) { - ERRMSG(row) - "Ambiguous use of unary minus with \"%s\"", - textToStr(textOf(fun(fun(s)))) - EEND; - } - - if (precOf(sys)>UMINUS_PREC) { /* nshift */ - Cell e1 = snd(e); - Cell t = s; - s = arg(fun(s)); - while (whatIs(e1)==NEG) - e1 = snd(e1); - arg(fun(t)) = arg(e1); - arg(e1) = t; - sys = APPLIC; - continue; - } - - } - - /* Intentional fall-thru for nreduce and isNull(s) */ - { Cell prev = e; /* e := tidyNeg e */ - Cell temp = arg(prev); - Int nneg = 1; - for (; whatIs(temp)==NEG; nneg++) { - fun(prev) = varNegate; - prev = temp; - temp = arg(prev); - } - /* These special cases are required for - * pattern matching. - */ - if (isInt(arg(temp))) { /* special cases */ - if (nneg&1) /* for literals */ - arg(temp) = intNegate(arg(temp)); - } - else if (isBignum(arg(temp))) { - if (nneg&1) - arg(temp) = bignumNegate(arg(temp)); - } - else if (isFloat(arg(temp))) { - if (nneg&1) - arg(temp) = floatNegate(arg(temp)); - } - else { - fun(prev) = varNegate; - arg(prev) = arg(temp); - arg(temp) = e; - } - e = temp; - } - continue; - - default : if (isNull(s)) {/* Move operation onto empty stack */ - Cell next = arg(fun(e)); - s = e; - arg(fun(s)) = NIL; - e = next; - sys = sye; - sye = APPLIC; - } - else { /* deal with pair of operators */ - - if (sye==APPLIC) { /* calculate sys and sye */ - sye = identSyntax(fun(fun(e))); - if (sye==APPLIC) sye=DEF_OPSYNTAX; - } - if (sys==APPLIC) { - sys = identSyntax(fun(fun(s))); - if (sys==APPLIC) sys=DEF_OPSYNTAX; - } - - if (precOf(sye)==precOf(sys) && /* ambig */ - (assocOf(sye)!=assocOf(sys) || - assocOf(sye)==NON_ASS)) { - ERRMSG(row) - "Ambiguous use of operator \"%s\" with \"%s\"", - textToStr(textOf(fun(fun(e)))), - textToStr(textOf(fun(fun(s)))) - EEND; - } - - if (precOf(sye)>precOf(sys) || /* shift */ - (precOf(sye)==precOf(sys) && - assocOf(sye)==LEFT_ASS && - assocOf(sys)==LEFT_ASS)) { - Cell next = arg(fun(e)); - arg(fun(e)) = s; - s = e; - e = next; - sys = sye; - sye = APPLIC; - } - else { /* reduce */ - Cell next = arg(fun(s)); - arg(fun(s)) = arg(e); - arg(e) = s; - s = next; - sys = APPLIC; - /* sye unchanged */ - } - } - continue; - } -} - /*-------------------------------------------------------------------------*/ diff --git a/ghc/interpreter/preds.c b/ghc/interpreter/preds.c index 6a88cb8c4b92..fc5eaa16f5d1 100644 --- a/ghc/interpreter/preds.c +++ b/ghc/interpreter/preds.c @@ -1,10 +1,15 @@ -/* -*- mode: hugs-c; -*- */ + /* -------------------------------------------------------------------------- - * preds.c: Copyright (c) Mark P Jones 1991-1998. All rights reserved. - * See NOTICE for details and conditions of use etc... - * Hugs version 1.3c, March 1998 + * Part of the type checker dealing with predicates and entailment + * + * Hugs 98 is Copyright (c) Mark P Jones, Alastair Reid and the Yale + * Haskell Group 1994-99, and is distributed as Open Source software + * under the Artistic License; see the file "Artistic" that is included + * in the distribution for details. * - * Part of type checker dealing with predicates and entailment. + * $RCSfile: preds.c,v $ + * $Revision: 1.3 $ + * $Date: 1999/02/03 17:08:35 $ * ------------------------------------------------------------------------*/ /* -------------------------------------------------------------------------- @@ -19,10 +24,11 @@ static Void local qualifyBinding Args((List,Cell)); static Cell local qualifyExpr Args((Int,List,Cell)); static Void local overEvid Args((Cell,Cell)); -static Cell local scFind Args((Cell,Cell,Int,Cell,Int)); -static Cell local scEntail Args((List,Cell,Int)); -static Cell local entail Args((List,Cell,Int)); -static Cell local inEntail Args((List,Cell,Int)); +static Void local cutoffExceeded Args((Cell,Int,Cell,Int,List)); +static Cell local scFind Args((Cell,Cell,Int,Cell,Int,Int)); +static Cell local scEntail Args((List,Cell,Int,Int)); +static Cell local entail Args((List,Cell,Int,Int)); +static Cell local inEntail Args((List,Cell,Int,Int)); #if TREX static Cell local lacksNorm Args((Type,Int,Cell)); #endif @@ -167,12 +173,37 @@ Cell ev; { * * ------------------------------------------------------------------------*/ -static Cell local scFind(e,pi1,o1,pi,o) /* Use superclass entailment to */ +Int cutoff = 16; /* Used to limit depth of recursion*/ + +static Void local cutoffExceeded(pi,o,pi1,o1,ps) +Cell pi, pi1; /* Display error msg when cutoff */ +Int o, o1; +List ps; { + clearMarks(); + ERRMSG(0) + "\n*** The type checker has reached the cutoff limit while trying to\n" + ETHEN ERRTEXT + "*** determine whether:\n*** " ETHEN ERRPRED(copyPred(pi,o)); + ps = (isNull(pi1)) ? copyPreds(ps) : singleton(copyPred(pi1,o1)); + ERRTEXT + "\n*** can be deduced from:\n*** " ETHEN ERRCONTEXT(ps); + ERRTEXT + "\n*** This may indicate that the problem is undecidable. However,\n" + ETHEN ERRTEXT + "*** you may still try to increase the cutoff limit using the -c\n" + ETHEN ERRTEXT + "*** option and then try again. (The current setting is -c%d)\n", + cutoff + EEND; +} + +static Cell local scFind(e,pi1,o1,pi,o,d)/* Use superclass entailment to */ Cell e; /* find evidence for (pi,o) using */ Cell pi1; /* the evidence e for (pi1,o1). */ Int o1; Cell pi; -Int o; { +Int o; +Int d; { Class h1 = getHead(pi1); Class h = getHead(pi); @@ -185,8 +216,12 @@ Int o; { List dsels = cclass(h1).dsels; if (!matchPred(pi1,o1,cclass(h1).head,beta)) internal("scFind"); + + if (d++ >= cutoff) + cutoffExceeded(pi,o,pi1,o1,NIL); + for (; nonNull(scs); scs=tl(scs), dsels=tl(dsels)) { - Cell ev = scFind(ap(hd(dsels),e),hd(scs),beta,pi,o); + Cell ev = scFind(ap(hd(dsels),e),hd(scs),beta,pi,o,d); if (nonNull(ev)) return ev; } @@ -195,13 +230,14 @@ Int o; { return NIL; } -static Cell local scEntail(ps,pi,o) /* Calc evidence for (pi,o) from ps*/ +static Cell local scEntail(ps,pi,o,d) /* Calc evidence for (pi,o) from ps*/ List ps; /* Using superclasses and equality.*/ Cell pi; -Int o; { +Int o; +Int d; { for (; nonNull(ps); ps=tl(ps)) { Cell pi1 = hd(ps); - Cell ev = scFind(thd3(pi1),fst3(pi1),intOf(snd3(pi1)),pi,o); + Cell ev = scFind(thd3(pi1),fst3(pi1),intOf(snd3(pi1)),pi,o,d); if (nonNull(ev)) return ev; } @@ -256,18 +292,20 @@ Int o; { * to cause any further concern, except in pathological cases.) * ------------------------------------------------------------------------*/ -static Cell local entail(ps,pi,o) /* Calc evidence for (pi,o) from ps*/ +static Cell local entail(ps,pi,o,d) /* Calc evidence for (pi,o) from ps*/ List ps; /* Uses superclasses, equality, */ Cell pi; /* tautology, and construction */ -Int o; { - Cell ev = scEntail(ps,pi,o); - return nonNull(ev) ? ev : inEntail(ps,pi,o); +Int o; +Int d; { + Cell ev = scEntail(ps,pi,o,d); + return nonNull(ev) ? ev : inEntail(ps,pi,o,d); } -static Cell local inEntail(ps,pi,o) /* Calc evidence for (pi,o) from ps*/ +static Cell local inEntail(ps,pi,o,d) /* Calc evidence for (pi,o) from ps*/ List ps; /* using a top-level instance */ Cell pi; /* entailment */ -Int o; { +Int o; +Int d; { #if TREX if (isAp(pi) && isExt(fun(pi))) { /* Lacks predicates */ Cell e = fun(pi); @@ -295,18 +333,21 @@ Int o; { else { #endif Inst in = findInstFor(pi,o); /* Class predicates */ + if (nonNull(in)) { Int beta = typeOff; - Cell d = inst(in).builder; - Cell ds = inst(in).specifics; - for (; nonNull(ds); ds=tl(ds)) { - Cell ev = entail(ps,hd(ds),beta); + Cell e = inst(in).builder; + Cell es = inst(in).specifics; + if (d++ >= cutoff) + cutoffExceeded(pi,o,NIL,0,ps); + for (; nonNull(es); es=tl(es)) { + Cell ev = entail(ps,hd(es),beta,d); if (nonNull(ev)) - d = ap(d,ev); + e = ap(e,ev); else return NIL; } - return d; + return e; } return NIL; #if TREX @@ -323,7 +364,7 @@ Cell pi; { /* is tautological, and we can use */ emptySubstitution(); beta = newKindedVars(ks); /* (ks provides kinds for any */ ps = makePredAss(ps,beta); /* vars that appear in pi.) */ - ev = entail(ps,pi,beta); + ev = entail(ps,pi,beta,0); emptySubstitution(); return ev; } @@ -371,7 +412,7 @@ List qs; { /* returning equiv minimal subset */ while (0<n--) { Cell pi = hd(qs); - Cell ev = scEntail(tl(qs),fst3(pi),intOf(snd3(pi))); + Cell ev = scEntail(tl(qs),fst3(pi),intOf(snd3(pi)),0); if (nonNull(ev)) { overEvid(thd3(pi),ev); /* Overwrite dict var with evidence*/ qs = tl(qs); /* ... and discard predicate */ @@ -396,20 +437,24 @@ Int o; { /* superclass hierarchy */ * ------------------------------------------------------------------------*/ static Void local elimTauts() { /* Remove tautological constraints */ - List ps = preds; /* from preds */ - preds = NIL; - while (nonNull(ps)) { - Cell pi = hd(ps); - Cell ev = entail(NIL,fst3(pi),intOf(snd3(pi))); - if (nonNull(ev)) { - overEvid(thd3(pi),ev); - ps = tl(ps); - } - else { - List tmp = tl(ps); - tl(ps) = preds; - preds = ps; - ps = tmp; + if (haskell98) { /* from preds */ + reducePreds(); /* (or context reduce for Hask98) */ + } else { + List ps = preds; + preds = NIL; + while (nonNull(ps)) { + Cell pi = hd(ps); + Cell ev = entail(NIL,fst3(pi),intOf(snd3(pi)),0); + if (nonNull(ev)) { + overEvid(thd3(pi),ev); + ps = tl(ps); + } + else { + List tmp = tl(ps); + tl(ps) = preds; + preds = ps; + ps = tmp; + } } } } @@ -474,7 +519,7 @@ List sps; { /* context ps. sps = savePreds. */ Cell p = preds; Cell pi = fst3(hd(p)); Int o = intOf(snd3(hd(p))); - Cell ev = entail(ps,pi,o); + Cell ev = entail(ps,pi,o,0); preds = tl(preds); if (nonNull(ev)) /* Discharge if ps ||- (pi,o) */ @@ -582,11 +627,11 @@ List vs; { /* for variables vs subject to */ Bool defaulted = FALSE; #ifdef DEBUG_DEFAULTS - printf("Attempt to resolve variables "); + Printf("Attempt to resolve variables "); printExp(stdout,vs); - printf(" with context "); + Printf(" with context "); printContext(stdout,copyPreds(preds)); - printf("\n"); + Printf("\n"); #endif resetGenerics(); /* find type variables in ps */ @@ -601,16 +646,16 @@ List vs; { /* for variables vs subject to */ Int vn = intOf(hd(pvs)); #ifdef DEBUG_DEFAULTS - printf("is var %d included in ",vn); + Printf("is var %d included in ",vn); printExp(stdout,vs); - printf("?\n"); + Printf("?\n"); #endif if (!intIsMember(vn,vs)) defaulted |= resolveVar(vn); #ifdef DEBUG_DEFAULTS else - printf("Yes, so no ambiguity!\n"); + Printf("Yes, so no ambiguity!\n"); #endif } @@ -635,7 +680,7 @@ Int vn; { /* variable vn can be resolved */ */ #ifdef DEBUG_DEFAULTS - printf("Trying to default variable %d\n",vn); + Printf("Trying to default variable %d\n",vn); #endif for (; nonNull(ps); ps=tl(ps)) { @@ -649,7 +694,7 @@ Int vn; { /* variable vn can be resolved */ else if (c!=classEq && c!=classOrd && c!=classShow && c!=classRead && c!=classIx && c!=classEnum && #if EVAL_INSTANCES - c!=classEval && + c!=classEval && #endif c!=classBounded) return FALSE; @@ -676,18 +721,18 @@ Int vn; { /* variable vn can be resolved */ if (aNumClass) { List ds = defaultDefns; /* N.B. guaranteed to be monotypes */ #ifdef DEBUG_DEFAULTS - printf("Default conditions met, looking for type\n"); + Printf("Default conditions met, looking for type\n"); #endif for (; nonNull(ds); ds=tl(ds)) { List cs1 = cs; - while (nonNull(cs1) && nonNull(entail(NIL,ap(hd(cs1),hd(ds)),0))) + while (nonNull(cs1) && nonNull(entail(NIL,ap(hd(cs1),hd(ds)),0,0))) cs1 = tl(cs1); if (isNull(cs1)) { bindTv(vn,hd(ds),0); #ifdef DEBUG_DEFAULTS - printf("Default type for variable %d is ",vn); + Printf("Default type for variable %d is ",vn); printType(stdout,hd(ds)); - printf("\n"); + Printf("\n"); #endif return TRUE; } @@ -695,7 +740,7 @@ Int vn; { /* variable vn can be resolved */ } #ifdef DEBUG_DEFAULTS - printf("No default permitted/found\n"); + Printf("No default permitted/found\n"); #endif return FALSE; } diff --git a/ghc/interpreter/prelude.h b/ghc/interpreter/prelude.h index 6abd9aa5a705..8886a3af4fa9 100644 --- a/ghc/interpreter/prelude.h +++ b/ghc/interpreter/prelude.h @@ -1,4 +1,4 @@ -/* -*- mode: hugs-c; -*- */ + /* -------------------------------------------------------------------------- * Basic data type definitions, prototypes and standard macros including * machine dependent variations... @@ -8,8 +8,8 @@ * Hugs version 1.4, December 1997 * * $RCSfile: prelude.h,v $ - * $Revision: 1.2 $ - * $Date: 1998/12/02 13:22:33 $ + * $Revision: 1.3 $ + * $Date: 1999/02/03 17:08:36 $ * ------------------------------------------------------------------------*/ #include "config.h" @@ -228,14 +228,20 @@ extern int stricmp Args((const char *, const char*)); typedef unsigned Bool; #define TRUE 1 #define FALSE 0 -typedef char *String; -typedef int Int; -typedef long Long; -typedef int Char; -typedef unsigned int Word; /* at least 32 bits */ -typedef void* Ptr; -typedef void* Addr; -typedef Word* HpPtr; + +typedef char *String; +typedef int Int; +typedef long Long; +typedef int Char; +typedef unsigned int Unsigned; /* at least 32 bits */ +typedef void* Ptr; +typedef void* Addr; +typedef void* HpPtr; + +#define FloatImpType double +#define FloatPro double +#define FloatFMT "%.9g" + /* ToDo: this should probably go in dynamic.h - but then * storage.h has to include dynamic.h! diff --git a/ghc/interpreter/scc.c b/ghc/interpreter/scc.c index c4a349195436..809d54a874fb 100644 --- a/ghc/interpreter/scc.c +++ b/ghc/interpreter/scc.c @@ -1,27 +1,28 @@ -/* -*- mode: hugs-c; -*- */ + /* -------------------------------------------------------------------------- * Strongly connected components algorithm for static.c. * - * Copyright (c) The University of Nottingham and Yale University, 1994-1997. - * All rights reserved. See NOTICE for details and conditions of use etc... - * Hugs version 1.4, December 1997 + * Hugs 98 is Copyright (c) Mark P Jones, Alastair Reid and the Yale + * Haskell Group 1994-99, and is distributed as Open Source software + * under the Artistic License; see the file "Artistic" that is included + * in the distribution for details. * * $RCSfile: scc.c,v $ - * $Revision: 1.2 $ - * $Date: 1998/12/02 13:22:34 $ + * $Revision: 1.3 $ + * $Date: 1999/02/03 17:08:36 $ * ------------------------------------------------------------------------*/ #ifndef SCC_C #define SCC_C -#define visited(d) (isInt(DEPENDS(d))) /* binding already visited ? */ +#define visited(d) (isInt(DEPENDS(d))) /* binding already visited?*/ static Cell daSccs = NIL; static Int daCount; static Int local sccMin Args((Int,Int)); -static Int local sccMin(x,y) /* calculate minimum of x,y (unless */ -Int x,y; { /* y is zero) */ +static Int local sccMin(x,y) /* calculate minimum of x,y */ +Int x, y; { /* (unless y is zero) */ return (x<=y || y==0) ? x : y; } #endif diff --git a/ghc/interpreter/static.c b/ghc/interpreter/static.c index 601ef0a626c0..2cf01cd316f3 100644 --- a/ghc/interpreter/static.c +++ b/ghc/interpreter/static.c @@ -1,176 +1,218 @@ -/* -*- mode: hugs-c; -*- */ + /* -------------------------------------------------------------------------- * Static Analysis for Hugs * - * Copyright (c) The University of Nottingham and Yale University, 1994-1997. - * All rights reserved. See NOTICE for details and conditions of use etc... - * Hugs version 1.4, December 1997 + * Hugs 98 is Copyright (c) Mark P Jones, Alastair Reid and the Yale + * Haskell Group 1994-99, and is distributed as Open Source software + * under the Artistic License; see the file "Artistic" that is included + * in the distribution for details. * * $RCSfile: static.c,v $ - * $Revision: 1.2 $ - * $Date: 1998/12/02 13:22:35 $ + * $Revision: 1.3 $ + * $Date: 1999/02/03 17:08:37 $ * ------------------------------------------------------------------------*/ #include "prelude.h" #include "storage.h" +#include "backend.h" #include "connect.h" -#include "input.h" -#include "type.h" -#include "static.h" -#include "translate.h" -#include "hugs.h" /* for target */ #include "errors.h" #include "subst.h" -#include "link.h" -#include "modules.h" -#include "derive.h" /* -------------------------------------------------------------------------- * local function prototypes: * ------------------------------------------------------------------------*/ -static Module thisModule = 0; /* module currently being processed*/ - -static Void local kindError Args((Int,Constr,Constr,String,Kind,Int)); +static Void local kindError Args((Int,Constr,Constr,String,Kind,Int)); +#if !IGNORE_MODULES +static Void local checkQualImport Args((Pair)); +static Void local checkUnqualImport Args((Triple)); + +static Name local lookupName Args((Text,List)); +static List local checkSubentities Args((List,List,List,String,Text)); +static List local checkExportTycon Args((List,Text,Cell,Tycon)); +static List local checkExportClass Args((List,Text,Cell,Class)); +static List local checkExport Args((List,Text,Cell)); +static List local checkImportEntity Args((List,Module,Cell)); +static List local resolveImportList Args((Module,Cell)); +static Void local checkImportList Args((Pair)); + +static Void local importEntity Args((Module,Cell)); +static Void local importName Args((Module,Name)); +static Void local importTycon Args((Module,Tycon)); +static Void local importClass Args((Module,Class)); +static List local checkExports Args((List)); +#endif -static Void local checkTyconDefn Args((Tycon)); -static Void local depConstrs Args((Tycon,List,Cell)); -static List local addSels Args((Int,Name,List,List)); -static List local selectCtxt Args((List,List)); -static Void local checkSynonyms Args((List)); -static List local visitSyn Args((List,Tycon,List)); +static Void local checkTyconDefn Args((Tycon)); +static Void local depConstrs Args((Tycon,List,Cell)); +static List local addSels Args((Int,Name,List,List)); +static List local selectCtxt Args((List,List)); +static Void local checkSynonyms Args((List)); +static List local visitSyn Args((List,Tycon,List)); #if EVAL_INSTANCES -static Void local deriveEval Args((List)); -static List local calcEvalContexts Args((Tycon,List,List)); +static Void local deriveEval Args((List)); +static List local calcEvalContexts Args((Tycon,List,List)); +static Void local checkBanged Args((Name,Kinds,List,Type)); #endif -static Void local checkBanged Args((Name,Kinds,List,Type)); -static Type local instantiateSyn Args((Type,Type)); - -static Void local checkClassDefn Args((Class)); -static Void local depPredExp Args((Int,List,Cell)); -static Void local checkMems Args((Class,List,Cell)); -static Void local addMembers Args((Class)); -static Name local newMember Args((Int,Int,Cell,Type)); -static Name local newDSel Args((Class,Int)); -static Name local newDBuild Args((Class)); -static Text local generateText Args((String, Class)); -static Int local visitClass Args((Class)); - -static List local classBindings Args((String,Class,List)); -static Name local memberName Args((Class,Text)); -static List local numInsert Args((Int,Cell,List)); - -static List local typeVarsIn Args((Cell,List,List)); -static List local maybeAppendVar Args((Cell,List)); - -static Type local checkSigType Args((Int,String,Cell,Type)); -static Type local depTopType Args((Int,List,Type)); -static Type local depCompType Args((Int,List,Type)); -static Type local depTypeExp Args((Int,List,Type)); -static Type local depTypeVar Args((Int,List,Text)); -static Void local kindConstr Args((Int,Int,Int,Constr)); -static Kind local kindAtom Args((Int,Constr)); -static Void local kindPred Args((Int,Int,Int,Cell)); -static Void local kindType Args((Int,String,Type)); -static Void local fixKinds Args((Void)); - -static Void local kindTCGroup Args((List)); -static Void local initTCKind Args((Cell)); -static Void local kindTC Args((Cell)); -static Void local genTC Args((Cell)); - -static Void local checkInstDefn Args((Inst)); -static Void local insertInst Args((Inst)); -static Bool local instCompare Args((Inst,Inst)); -static Name local newInstImp Args((Inst)); -static Void local kindInst Args((Inst,Int)); -static Void local checkDerive Args((Tycon,List,List,Cell)); -static Void local addDerInst Args((Int,Class,List,List,Type,Int)); - -static Void local deriveContexts Args((List)); -static Void local initDerInst Args((Inst)); -static Void local calcInstPreds Args((Inst)); -static Void local maybeAddPred Args((Cell,Int,Int,List)); -static Cell local copyAdj Args((Cell,Int,Int)); -static Void local tidyDerInst Args((Inst)); - -static Void local addDerivImp Args((Inst)); - -static Void local checkDefaultDefns Args((Void)); - -static Void local checkForeignImport Args((Name)); -static Void local checkForeignExport Args((Name)); - -static Cell local checkPat Args((Int,Cell)); -static Cell local checkMaybeCnkPat Args((Int,Cell)); -static Cell local checkApPat Args((Int,Int,Cell)); -static Void local addPatVar Args((Int,Cell)); -static Name local conDefined Args((Int,Cell)); -static Void local checkIsCfun Args((Int,Name)); -static Void local checkCfunArgs Args((Int,Cell,Int)); -static Cell local applyBtyvs Args((Cell)); -static Cell local bindPat Args((Int,Cell)); -static Void local bindPats Args((Int,List)); - -static List local extractSigdecls Args((List)); -static List local extractBindings Args((List)); -static List local eqnsToBindings Args((List)); -static Void local notDefined Args((Int,List,Cell)); -static Cell local findBinding Args((Text,List)); -static Void local addSigDecl Args((List,Cell)); -static Void local setType Args((Int,Cell,Cell,List)); - -static List local dependencyAnal Args((List)); -static List local topDependAnal Args((List)); -static Void local addDepField Args((Cell)); -static Void local remDepField Args((List)); -static Void local remDepField1 Args((Cell)); -static Void local clearScope Args((Void)); -static Void local withinScope Args((List)); -static Void local leaveScope Args((Void)); - -static Void local depBinding Args((Cell)); -static Void local depDefaults Args((Class)); -static Void local depInsts Args((Inst)); -static Void local depClassBindings Args((List)); -static Void local depAlt Args((Cell)); -static Void local depRhs Args((Cell)); -static Void local depGuard Args((Cell)); -static Cell local depExpr Args((Int,Cell)); -static Void local depPair Args((Int,Cell)); -static Void local depTriple Args((Int,Cell)); -static Void local depComp Args((Int,Cell,List)); -static Void local depCaseAlt Args((Int,Cell)); -static Cell local depVar Args((Int,Cell)); -static Cell local depQVar Args((Int,Cell)); -static Void local depConFlds Args((Int,Cell,Bool)); -static Void local depUpdFlds Args((Int,Cell)); -static List local depFields Args((Int,Cell,List,Bool)); +static Type local instantiateSyn Args((Type,Type)); + +static Void local checkClassDefn Args((Class)); +static Void local depPredExp Args((Int,List,Cell)); +static Void local checkMems Args((Class,List,Cell)); +static Void local addMembers Args((Class)); +static Name local newMember Args((Int,Int,Cell,Type,Class)); +static Name local newDSel Args((Class,Int)); +static Name local newDBuild Args((Class)); +static Text local generateText Args((String,Class)); +static Int local visitClass Args((Class)); + +static List local classBindings Args((String,Class,List)); +static Name local memberName Args((Class,Text)); +static List local numInsert Args((Int,Cell,List)); + +static List local typeVarsIn Args((Cell,List,List)); +static List local maybeAppendVar Args((Cell,List)); + +static Type local checkSigType Args((Int,String,Cell,Type)); +static Type local depTopType Args((Int,List,Type)); +static Type local depCompType Args((Int,List,Type)); +static Type local depTypeExp Args((Int,List,Type)); +static Type local depTypeVar Args((Int,List,Text)); +static List local checkQuantVars Args((Int,List,List,Cell)); +static List local offsetTyvarsIn Args((Type,List)); +static Void local kindConstr Args((Int,Int,Int,Constr)); +static Kind local kindAtom Args((Int,Constr)); +static Void local kindPred Args((Int,Int,Int,Cell)); +static Void local kindType Args((Int,String,Type)); +static Void local fixKinds Args((Void)); + +static Void local kindTCGroup Args((List)); +static Void local initTCKind Args((Cell)); +static Void local kindTC Args((Cell)); +static Void local genTC Args((Cell)); + +static Void local checkInstDefn Args((Inst)); +static Void local insertInst Args((Inst)); +static Bool local instCompare Args((Inst,Inst)); +static Name local newInstImp Args((Inst)); +static Void local kindInst Args((Inst,Int)); +static Void local checkDerive Args((Tycon,List,List,Cell)); +static Void local addDerInst Args((Int,Class,List,List,Type,Int)); +static Void local deriveContexts Args((List)); +static Void local initDerInst Args((Inst)); +static Void local calcInstPreds Args((Inst)); +static Void local maybeAddPred Args((Cell,Int,Int,List)); +static Cell local copyAdj Args((Cell,Int,Int)); +static Void local tidyDerInst Args((Inst)); + +static Void local addDerivImp Args((Inst)); +static List local getDiVars Args((Int)); +static Cell local mkBind Args((String,List)); +static Cell local mkVarAlts Args((Int,Cell)); + +static List local makeDPats2 Args((Cell,Int)); + +static Bool local isEnumType Args((Tycon)); + +static Void local checkDefaultDefns Args((Void)); + +static Void local checkForeignImport Args((Name)); +static Void local checkForeignExport Args((Name)); + +static Name local addNewPrim Args((Int,Text,String,Cell)); + +static Cell local tidyInfix Args((Int,Cell)); +static Pair local attachFixity Args((Int,Cell)); +static Syntax local lookupSyntax Args((Text)); + +static Cell local checkPat Args((Int,Cell)); +static Cell local checkMaybeCnkPat Args((Int,Cell)); +static Cell local checkApPat Args((Int,Int,Cell)); +static Void local addToPatVars Args((Int,Cell)); +static Name local conDefined Args((Int,Cell)); +static Void local checkIsCfun Args((Int,Name)); +static Void local checkCfunArgs Args((Int,Cell,Int)); +static Cell local checkPatType Args((Int,String,Cell,Type)); +static Cell local applyBtyvs Args((Cell)); +static Cell local bindPat Args((Int,Cell)); +static Void local bindPats Args((Int,List)); + +static List local extractSigdecls Args((List)); +static List local extractFixdecls Args((List)); +static List local extractBindings Args((List)); +static List local getPatVars Args((Int,Cell,List)); +static List local addPatVar Args((Int,Cell,List)); +static List local eqnsToBindings Args((List,List,List,List)); +static Void local notDefined Args((Int,List,Cell)); +static Cell local findBinding Args((Text,List)); +static Cell local getAttr Args((List,Cell)); +static Void local addSigdecl Args((List,Cell)); +static Void local addFixdecl Args((List,List,List,List,Triple)); +static Void local dupFixity Args((Int,Text)); +static Void local missFixity Args((Int,Text)); + +static List local dependencyAnal Args((List)); +static List local topDependAnal Args((List)); +static Void local addDepField Args((Cell)); +static Void local remDepField Args((List)); +static Void local remDepField1 Args((Cell)); +static Void local clearScope Args((Void)); +static Void local withinScope Args((List)); +static Void local leaveScope Args((Void)); +static Void local saveSyntax Args((Cell,Cell)); + +static Void local depBinding Args((Cell)); +static Void local depDefaults Args((Class)); +static Void local depInsts Args((Inst)); +static Void local depClassBindings Args((List)); +static Void local depAlt Args((Cell)); +static Void local depRhs Args((Cell)); +static Void local depGuard Args((Cell)); +static Cell local depExpr Args((Int,Cell)); +static Void local depPair Args((Int,Cell)); +static Void local depTriple Args((Int,Cell)); +static Void local depComp Args((Int,Cell,List)); +static Void local depCaseAlt Args((Int,Cell)); +static Cell local depVar Args((Int,Cell)); +static Cell local depQVar Args((Int,Cell)); +static Void local depConFlds Args((Int,Cell,Bool)); +static Void local depUpdFlds Args((Int,Cell)); +static List local depFields Args((Int,Cell,List,Bool)); #if TREX -static Cell local depRecord Args((Int,Cell)); +static Cell local depRecord Args((Int,Cell)); #endif -static List local tcscc Args((List,List)); -static List local bscc Args((List)); +static List local tcscc Args((List,List)); +static List local bscc Args((List)); -static Void local addRSsigdecls Args((Pair)); -static Void local opDefined Args((List,Cell)); -static Void local allNoPrevDef Args((Cell)); -static Void local noPrevDef Args((Int,Cell)); -static Void local duplicateError Args((Int,Module,Text,String)); -static Void local checkTypeIn Args((Pair)); +static Void local addRSsigdecls Args((Pair)); +static Void local allNoPrevDef Args((Cell)); +static Void local noPrevDef Args((Int,Cell)); +#if IGNORE_MODULES +static Void local duplicateErrorAux Args((Int,Text,String)); +#define duplicateError(l,m,t,k) duplicateErrorAux(l,t,k) +#else +static Void local duplicateErrorAux Args((Int,Module,Text,String)); +#define duplicateError(l,m,t,k) duplicateErrorAux(l,m,t,k) +#endif +static Void local checkTypeIn Args((Pair)); /* -------------------------------------------------------------------------- * The code in this file is arranged in roughly the following order: * - Kind inference preliminaries + * - Module declarations * - Type declarations (data, type, newtype, type in) * - Class declarations * - Type signatures * - Instance declarations * - Default declarations + * - Primitive definitions * - Patterns + * - Infix expressions * - Value definitions * - Top-level static analysis and control + * - Haskell 98 compatibility tests * ------------------------------------------------------------------------*/ /* -------------------------------------------------------------------------- @@ -224,6 +266,443 @@ static List unkindTypes; /* types in need of kind annotation*/ Kind extKind; /* Kind of extension, *->row->row */ #endif +/* -------------------------------------------------------------------------- + * Static analysis of modules: + * ------------------------------------------------------------------------*/ + +#if HSCRIPT +String reloadModule; +#endif + +#if !IGNORE_MODULES +Void startModule(nm) /* switch to a new module */ +Cell nm; { + Module m; + if (!isCon(nm)) internal("startModule"); + if (isNull(m = findModule(textOf(nm)))) + m = newModule(textOf(nm)); + else if (!isPreludeScript()) { + /* You're allowed to break the rules in the Prelude! */ +#if HSCRIPT + reloadModule = textToStr(textOf(nm)); +#endif + ERRMSG(0) "Module \"%s\" already loaded", textToStr(textOf(nm)) + EEND; + } + setCurrModule(m); +} + +Void setExportList(exps) /* Add export list to current module */ +List exps; { + module(currentModule).exports = exps; +} + +Void addQualImport(orig,new) /* Add to qualified import list */ +Cell orig; /* Original name of module */ +Cell new; { /* Name module is called within this module (or NIL) */ + module(currentModule).qualImports = + cons(pair(isNull(new)?orig:new,orig),module(currentModule).qualImports); +} + +Void addUnqualImport(mod,entities) /* Add to unqualified import list */ +Cell mod; /* Name of module */ +List entities; { /* List of entity names */ + unqualImports = cons(pair(mod,entities),unqualImports); +} + +static Void local checkQualImport(i) /* Process qualified import */ +Pair i; { + Module m = findModid(snd(i)); + if (isNull(m)) { + ERRMSG(0) "Module \"%s\" not previously loaded", + textToStr(textOf(snd(i))) + EEND; + } + snd(i)=m; +} + +static Void local checkUnqualImport(i) /* Process unqualified import */ +Pair i; { + Module m = findModid(fst(i)); + if (isNull(m)) { + ERRMSG(0) "Module \"%s\" not previously loaded", + textToStr(textOf(fst(i))) + EEND; + } + fst(i)=m; +} + +static Name local lookupName(t,nms) /* find text t in list of Names */ +Text t; +List nms; { /* :: [Name] */ + for(; nonNull(nms); nms=tl(nms)) { + if (t == name(hd(nms)).text) + return hd(nms); + } + return NIL; +} + +static List local checkSubentities(imports,named,wanted,description,textParent) +List imports; +List named; /* :: [ Q?(Var|Con)(Id|Op) ] */ +List wanted; /* :: [Name] */ +String description; /* "<constructor>|<member> of <type>|<class>" */ +Text textParent; { + for(; nonNull(named); named=tl(named)) { + Pair x = hd(named); + /* ToDo: ignores qualifier; doesn't check that entity is in scope */ + Text t = isPair(snd(x)) ? qtextOf(x) : textOf(x); + Name n = lookupName(t,wanted); + if (isNull(n)) { + ERRMSG(0) "Entity \"%s\" is not a %s \"%s\"", + textToStr(t), + description, + textToStr(textParent) + EEND; + } + imports = cons(n,imports); + } + return imports; +} + +static List local checkImportEntity(imports,exporter,entity) +List imports; /* Accumulated list of things to import */ +Module exporter; +Cell entity; { /* Entry from import list */ + List oldImports = imports; + Text t = isIdent(entity) ? textOf(entity) : textOf(fst(entity)); + List es = module(exporter).exports; + for(; nonNull(es); es=tl(es)) { + Cell e = hd(es); /* :: Entity | (Entity, NIL|DOTDOT) */ + if (isPair(e)) { + Cell f = fst(e); + if (isTycon(f)) { + if (tycon(f).text == t) { + imports = cons(f,imports); + if (!isIdent(entity)) { + switch (tycon(f).what) { + case NEWTYPE: + case DATATYPE: + if (DOTDOT == snd(entity)) { + imports=dupOnto(tycon(f).defn,imports); + } else { + imports=checkSubentities(imports,snd(entity),tycon(f).defn,"constructor of type",t); + } + break; + default:; + /* deliberate fall thru */ + } + } + } + } else if (isClass(f)) { + if (cclass(f).text == t) { + imports = cons(f,imports); + if (!isIdent(entity)) { + if (DOTDOT == snd(entity)) { + return dupOnto(cclass(f).members,imports); + } else { + return checkSubentities(imports,snd(entity),cclass(f).members,"member of class",t); + } + } + } + } else { + internal("checkImportEntity2"); + } + } else if (isName(e)) { + if (isIdent(entity) && name(e).text == t) { + imports = cons(e,imports); + } + } else { + internal("checkImportEntity3"); + } + } + if (imports == oldImports) { + ERRMSG(0) "Unknown entity \"%s\" imported from module \"%s\"", + textToStr(t), + textToStr(module(exporter ).text) + EEND; + } + return imports; +} + +static List local resolveImportList(m,impList) +Module m; /* exporting module */ +Cell impList; { + List imports = NIL; + if (DOTDOT == impList) { + List es = module(m).exports; + for(; nonNull(es); es=tl(es)) { + Cell e = hd(es); + if (isName(e)) + imports = cons(e,imports); + else { + Cell c = fst(e); + List subentities = NIL; + imports = cons(c,imports); + if (isTycon(c) + && (tycon(c).what == DATATYPE + || tycon(c).what == NEWTYPE)) + subentities = tycon(c).defn; + else if (isClass(c)) + subentities = cclass(c).members; + if (DOTDOT == snd(e)) { + imports = dupOnto(subentities,imports); + } + } + } + } else { + map1Accum(checkImportEntity,imports,m,impList); + } + return imports; +} + +static Void local checkImportList(importSpec) /*Import a module unqualified*/ +Pair importSpec; { + Module m = fst(importSpec); + Cell impList = snd(importSpec); + + List imports = NIL; /* entities we want to import */ + List hidden = NIL; /* entities we want to hide */ + + if (moduleThisScript(m)) { + ERRMSG(0) "Module \"%s\" recursively imports itself", + textToStr(module(m).text) + EEND; + } + if (isPair(impList) && HIDDEN == fst(impList)) { + /* Somewhat inefficient - but obviously correct: + * imports = importsOf("module Foo") `setDifference` hidden; + */ + hidden = resolveImportList(m, snd(impList)); + imports = resolveImportList(m, DOTDOT); + } else { + imports = resolveImportList(m, impList); + } + for(; nonNull(imports); imports=tl(imports)) { + Cell e = hd(imports); + if (!cellIsMember(e,hidden)) + importEntity(m,e); + } + /* ToDo: hang onto the imports list for processing export list entries + * of the form "module Foo" + */ +} + +static Void local importEntity(source,e) +Module source; +Cell e; { + switch (whatIs(e)) { + case NAME : importName(source,e); + break; + case TYCON : importTycon(source,e); + break; + case CLASS : importClass(source,e); + break; + default: internal("importEntity"); + } +} + +static Void local importName(source,n) +Module source; +Name n; { + Name clash = addName(n); + if (nonNull(clash) && clash!=n) { + ERRMSG(0) "Entity \"%s\" imported from module \"%s\" already defined in module \"%s\"", + textToStr(name(n).text), + textToStr(module(source).text), + textToStr(module(name(clash).mod).text) + EEND; + } +} + +static Void local importTycon(source,tc) +Module source; +Tycon tc; { + Tycon clash=addTycon(tc); + if (nonNull(clash) && clash!=tc) { + ERRMSG(0) "Tycon \"%s\" imported from \"%s\" already defined in module \"%s\"", + textToStr(tycon(tc).text), + textToStr(module(source).text), + textToStr(module(tycon(clash).mod).text) + EEND; + } + if (nonNull(findClass(tycon(tc).text))) { + ERRMSG(0) "Import of type constructor \"%s\" clashes with class in module \"%s\"", + textToStr(tycon(tc).text), + textToStr(module(tycon(tc).mod).text) + EEND; + } +} + +static Void local importClass(source,c) +Module source; +Class c; { + Class clash=addClass(c); + if (nonNull(clash) && clash!=c) { + ERRMSG(0) "Class \"%s\" imported from \"%s\" already defined in module \"%s\"", + textToStr(cclass(c).text), + textToStr(module(source).text), + textToStr(module(cclass(clash).mod).text) + EEND; + } + if (nonNull(findTycon(cclass(c).text))) { + ERRMSG(0) "Import of class \"%s\" clashes with type constructor in module \"%s\"", + textToStr(cclass(c).text), + textToStr(module(source).text) + EEND; + } +} + +static List local checkExportTycon(exports,mt,spec,tc) +List exports; +Text mt; +Cell spec; +Tycon tc; { + if (DOTDOT == spec || SYNONYM == tycon(tc).what) { + return cons(pair(tc,DOTDOT), exports); + } else { + return cons(pair(tc,NIL), exports); + } +} + +static List local checkExportClass(exports,mt,spec,cl) +List exports; +Text mt; +Class cl; +Cell spec; { + if (DOTDOT == spec) { + return cons(pair(cl,DOTDOT), exports); + } else { + return cons(pair(cl,NIL), exports); + } +} + +static List local checkExport(exports,mt,e) /* Process entry in export list*/ +List exports; +Text mt; +Cell e; { + if (isIdent(e)) { + Cell export = NIL; + List origExports = exports; + if (nonNull(export=findQualName(e))) { + exports=cons(export,exports); + } + if (isQCon(e) && nonNull(export=findQualTycon(e))) { + exports = checkExportTycon(exports,mt,NIL,export); + } + if (isQCon(e) && nonNull(export=findQualClass(e))) { + /* opaque class export */ + exports = checkExportClass(exports,mt,NIL,export); + } + if (exports == origExports) { + ERRMSG(0) "Unknown entity \"%s\" exported from module \"%s\"", + identToStr(e), + textToStr(mt) + EEND; + } + return exports; + } else if (MODULEENT == fst(e)) { + Module m = findModid(snd(e)); + /* ToDo: shouldn't allow export of module we didn't import */ + if (isNull(m)) { + ERRMSG(0) "Unknown module \"%s\" exported from module \"%s\"", + textToStr(textOf(snd(e))), + textToStr(mt) + EEND; + } + if (m == currentModule) { + /* Exporting the current module exports local definitions */ + List xs; + for(xs=module(m).classes; nonNull(xs); xs=tl(xs)) { + if (cclass(hd(xs)).mod==m) + exports = checkExportClass(exports,mt,DOTDOT,hd(xs)); + } + for(xs=module(m).tycons; nonNull(xs); xs=tl(xs)) { + if (tycon(hd(xs)).mod==m) + exports = checkExportTycon(exports,mt,DOTDOT,hd(xs)); + } + for(xs=module(m).names; nonNull(xs); xs=tl(xs)) { + if (name(hd(xs)).mod==m) + exports = cons(hd(xs),exports); + } + } else { + /* Exporting other modules imports all things imported + * unqualified from it. + * ToDo: we reexport everything exported by a module - + * whether we imported it or not. This gives the wrong + * result for "module M(module N) where import N(x)" + */ + exports = dupOnto(module(m).exports,exports); + } + return exports; + } else { + Cell ident = fst(e); /* class name or type name */ + Cell parts = snd(e); /* members or constructors */ + Cell nm; + if (isQCon(ident) && nonNull(nm=findQualTycon(ident))) { + switch (tycon(nm).what) { + case SYNONYM: + if (DOTDOT!=parts) { + ERRMSG(0) "Explicit constructor list given for type synonym \"%s\" in export list of module \"%s\"", + identToStr(ident), + textToStr(mt) + EEND; + } + return cons(pair(nm,DOTDOT),exports); + case RESTRICTSYN: + ERRMSG(0) "Transparent export of restricted type synonym \"%s\" in export list of module \"%s\"", + identToStr(ident), + textToStr(mt) + EEND; + return exports; /* Not reached */ + case NEWTYPE: + case DATATYPE: + if (DOTDOT==parts) { + return cons(pair(nm,DOTDOT),exports); + } else { + exports = checkSubentities(exports,parts,tycon(nm).defn, + "constructor of type", + tycon(nm).text); + return cons(pair(nm,DOTDOT), exports); + } + default: + internal("checkExport1"); + } + } else if (isQCon(ident) && nonNull(nm=findQualClass(ident))) { + if (DOTDOT == parts) { + return cons(pair(nm,DOTDOT),exports); + } else { + exports = checkSubentities(exports,parts,cclass(nm).members, + "member of class",cclass(nm).text); + return cons(pair(nm,DOTDOT), exports); + } + } else { + ERRMSG(0) "Explicit export list given for non-class/datatype \"%s\" in export list of module \"%s\"", + identToStr(ident), + textToStr(mt) + EEND; + } + } + assert(0); return 0; /* NOTREACHED */ +} + +static List local checkExports(exports) +List exports; { + Module m = lastModule(); + Text mt = module(m).text; + List es = NIL; + + map1Accum(checkExport,es,mt,exports); + +#if DEBUG_MODULES + for(xs=es; nonNull(xs); xs=tl(xs)) { + Printf(" %s", textToStr(textOfEntity(hd(xs)))); + } +#endif + return es; +} +#endif + /* -------------------------------------------------------------------------- * Static analysis of type declarations: * @@ -265,6 +744,7 @@ Cell what; { /* SYNONYM/DATATYPE/etc... */ tycon(nw).arity = argCount; tycon(nw).what = what; if (what==RESTRICTSYN) { + h98DoesntSupport(line,"restricted type synonyms"); typeInDefns = cons(pair(nw,snd(rhs)),typeInDefns); rhs = fst(rhs); } @@ -370,7 +850,6 @@ Cell cd; { /* definitions (w or w/o deriving) */ List derivs = snd(cd); List compTypes = NIL; List sels = NIL; - Int ntvs = length(tyvars); Int i; for (i=0; i<tycon(t).arity; ++i) /* build representation for tycon */ @@ -380,6 +859,7 @@ Cell cd; { /* definitions (w or w/o deriving) */ ctxt = fst(snd(cs)); cs = snd(snd(cs)); map2Proc(depPredExp,line,tyvars,ctxt); + h98CheckCtxt(line,"context",TRUE,ctxt,NIL); } if (nonNull(cs) && isNull(tl(cs))) /* Single constructor datatype? */ @@ -387,8 +867,9 @@ Cell cd; { /* definitions (w or w/o deriving) */ for (; nonNull(cs); cs=tl(cs)) { /* For each constructor function: */ Cell con = hd(cs); - List sig = typeVarsIn(con,NIL,dupList(tyvars)); - Int etvs = length(sig); + List sig = dupList(tyvars); + List evs = NIL; /* locally quantified vars */ + List lps = NIL; /* locally bound predicates */ List ctxt1 = ctxt; /* constructor function context */ List scs = NIL; /* strict components */ List fs = NONE; /* selector names */ @@ -397,6 +878,27 @@ Cell cd; { /* definitions (w or w/o deriving) */ Int nr2 = 0; /* Number of rank 2 args */ Name n; /* name for constructor function */ + if (whatIs(con)==POLYTYPE) { /* Locally quantified vars */ + evs = fst(snd(con)); + con = snd(snd(con)); + sig = checkQuantVars(line,evs,sig,con); + } + + if (whatIs(con)==QUAL) { /* Local predicates */ + List us; + lps = fst(snd(con)); + for (us = typeVarsIn(lps,NIL,NIL); nonNull(us); us=tl(us)) + if (!varIsMember(textOf(hd(us)),evs)) { + ERRMSG(line) + "Variable \"%s\" in constraint is not locally bound", + textToStr(textOf(hd(us))) + EEND; + } + map2Proc(depPredExp,line,sig,lps); + con = snd(snd(con)); + arity = length(lps); + } + if (whatIs(con)==LABC) { /* Skeletize constr components */ Cell fls = snd(snd(con)); /* get field specifications */ con = fst(snd(con)); @@ -440,7 +942,7 @@ Cell cd; { /* definitions (w or w/o deriving) */ ctxt1 = selectCtxt(ctxt1,offsetTyvarsIn(con,NIL)); for (i=arity; isAp(con); i--) { /* Calculate type of constructor */ - Type t = fun(con); + Type ty = fun(con); Type cmp = arg(con); fun(con) = typeArrow; if (isPolyType(cmp)) { @@ -455,13 +957,13 @@ Cell cd; { /* definitions (w or w/o deriving) */ if (nonNull(derivs)) /* and build list of components */ compTypes = cons(cmp,compTypes); type = ap(con,type); - con = t; + con = ty; } if (nr2>0) /* Add rank 2 annotation */ type = ap(RANK2,pair(mkInt(nr2),type)); - if (etvs>ntvs) { /* Add existential annotation */ + if (nonNull(evs)) { /* Add existential annotation */ if (nonNull(derivs)) { ERRMSG(line) "Cannot derive instances for types" ETHEN ERRTEXT " with existentially typed components" @@ -472,11 +974,17 @@ Cell cd; { /* definitions (w or w/o deriving) */ "Cannot use selectors with existentially typed components" EEND; } - type = ap(EXIST,pair(mkInt(etvs-ntvs),type)); + type = ap(EXIST,pair(mkInt(length(evs)),type)); } + + if (nonNull(lps)) { /* Add local preds part to type */ + type = ap(CDICTS,pair(lps,type)); + } + if (nonNull(ctxt1)) { /* Add context part to type */ type = ap(QUAL,pair(ctxt1,type)); } + if (nonNull(sig)) { /* Add quantifiers to type */ List ts1 = sig; for (; nonNull(ts1); ts1=tl(ts1)) { @@ -487,20 +995,37 @@ Cell cd; { /* definitions (w or w/o deriving) */ n = findName(textOf(con)); /* Allocate constructor fun name */ if (isNull(n)) { - n = newName(textOf(con)); + n = newName(textOf(con),NIL); } else if (name(n).defn!=PREDEFINED) { duplicateError(line,name(n).mod,name(n).text, "constructor function"); } name(n).arity = arity; /* Save constructor fun details */ name(n).line = line; + name(n).parent = t; name(n).number = cfunNo(conNo++); name(n).type = type; if (tycon(t).what==NEWTYPE) { + if (nonNull(lps)) { + ERRMSG(line) + "A newtype constructor cannot have class constraints" + EEND; + } + if (arity!=1) { + ERRMSG(line) + "A newtype constructor must have exactly one argument" + EEND; + } + if (nonNull(scs)) { + ERRMSG(line) + "Illegal strictess annotation for newtype constructor" + EEND; + } name(n).defn = nameId; } else { implementCfun(n,scs); } + hd(cs) = n; if (fs!=NONE) { sels = addSels(line,n,fs,sels); @@ -518,15 +1043,33 @@ Cell cd; { /* definitions (w or w/o deriving) */ } } +Int userArity(c) /* Find arity for cfun, ignoring */ +Name c; { /* CDICTS parameters */ + Int a = name(c).arity; + Type t = name(c).type; + Int w; + if (isPolyType(t)) { + t = monotypeOf(t); + } + if ((w=whatIs(t))==QUAL) { + w = whatIs(t=snd(snd(t))); + } + if (w==CDICTS) { + a -= length(fst(snd(t))); + } + return a; +} + +static List cfunSfuns; /* List of (Cfun,[SelectorVar]) */ + /* - used for deriving Show */ + static List local addSels(line,c,fs,ss) /* Add fields to selector list */ Int line; /* line number of constructor */ Name c; /* corresponding constr function */ List fs; /* list of fields (varids) */ List ss; { /* list of existing selectors */ Int sn = 1; -#if DERIVE_SHOW | DERIVE_READ cfunSfuns = cons(pair(c,fs),cfunSfuns); -#endif for (; nonNull(fs); fs=tl(fs), ++sn) { List ns = ss; Text t = textOf(hd(fs)); @@ -540,6 +1083,7 @@ List ss; { /* list of existing selectors */ while (nonNull(ns) && t!=name(hd(ns)).text) { ns = tl(ns); } + if (nonNull(ns)) { name(hd(ns)).defn = cons(pair(c,mkInt(sn)),name(hd(ns)).defn); } else { @@ -549,7 +1093,7 @@ List ss; { /* list of existing selectors */ textToStr(t) EEND; } - n = newName(t); + n = newName(t,c); name(n).line = line; name(n).number = SELNAME; name(n).defn = singleton(pair(c,mkInt(sn))); @@ -608,8 +1152,9 @@ List syns; { List path1 = NIL; for (; nonNull(ds); ds=tl(ds)) { if (cellIsMember(hd(ds),syns)) { - if (isNull(path1)) + if (isNull(path1)) { path1 = cons(t,path); + } syns = visitSyn(path1,hd(ds),syns); } } @@ -618,6 +1163,7 @@ List syns; { return removeCell(t,syns); } +#if EVAL_INSTANCES /* -------------------------------------------------------------------------- * The following code is used in calculating contexts for the automatically * derived Eval instances for newtype and restricted type synonyms. This is @@ -626,7 +1172,6 @@ List syns; { * future. * ------------------------------------------------------------------------*/ -#if EVAL_INSTANCES static Void local deriveEval(tcs) /* Derive instances of Eval */ List tcs; { List ts1 = tcs; @@ -670,7 +1215,7 @@ List tcs; { for (; nonNull(scs); scs=tl(scs)) { Int i = intOf(hd(scs)); for (; n<i; n++) { - t = arg(t); + t = arg(t); } checkBanged(c,ks,ctxt,arg(fun(t))); } @@ -719,9 +1264,9 @@ List ps; { ctxt = singleton(ap(classEval,copyType(t,o))); break; } else if (isTuple(h) /* Check for tuples ... */ - || h==tc /* ... direct recursion */ - || cellIsMember(h,ps) /* ... mutual recursion */ - || tycon(h).what==DATATYPE) { /* ... or datatype. */ + || h==tc /* ... direct recursion */ + || cellIsMember(h,ps) /* ... mutual recursion */ + || tycon(h).what==DATATYPE) {/* ... or datatype. */ break; /* => empty context */ } else { Cell pi = ap(classEval,t); @@ -730,6 +1275,10 @@ List ps; { if (cellIsMember(h,ts)) { /* Not yet visited? */ ts = calcEvalContexts(h,removeCell(h,ts),cons(h,ts)); } +<<<<<<<<<<<<<< variant A +>>>>>>>>>>>>>> variant B + +======= end of combination if (nonNull(in=findInstFor(pi,o))) {/* Look for Eval instance */ List qs = inst(in).specifics; Int o1 = typeOff; @@ -750,10 +1299,10 @@ List ps; { } static Void local checkBanged(c,ks,ps,ty) -Name c; /* Check that banged component of c*/ -Kinds ks; /* with type ty is an instance of */ -List ps; /* Eval under the predicates in ps.*/ -Type ty; { /* (All types using ks) */ +Name c; /* Check that banged component of c */ +Kinds ks; /* with type ty is an instance of */ +List ps; /* Eval under the predicates in ps. */ +Type ty; { /* (All types using ks) */ Cell pi = ap(classEval,ty); if (isNull(provePred(ks,ps,pi))) { ERRMSG(name(c).line) "Illegal datatype strictness annotation:" ETHEN @@ -825,12 +1374,12 @@ Type env; { /* values for OFFSET type vars */ * stages of static analysis. * ------------------------------------------------------------------------*/ -Void classDefn(line,head,ms) /* process new class definition */ -Int line; /* definition line number */ -Cell head; /* class header :: ([Supers],Class)*/ -List ms; { /* class definition body */ - Text ct = textOf(getHead(snd(head))); - Int arity = argCount; +Void classDefn(line,head,ms) /* process new class definition */ +Int line; /* definition line number */ +Cell head; /* class header :: ([Supers],Class) */ +List ms; { /* class definition body */ + Text ct = textOf(getHead(snd(head))); + Int arity = argCount; if (nonNull(findClass(ct))) { ERRMSG(line) "Repeated definition of class \"%s\"", @@ -849,6 +1398,8 @@ List ms; { /* class definition body */ cclass(nw).members = ms; cclass(nw).level = 0; classDefns = cons(nw,classDefns); + if (arity!=1) + h98DoesntSupport(line,"multiple parameter classes"); } } @@ -863,7 +1414,7 @@ List ms; { /* class definition body */ * class definition: * - check that variables in header are distinct * - replace head by skeleton - * - check superclass declarations, replace by skeltons + * - check superclass declarations, replace by skeletons * - split body of class into members and declarations * - make new name entry for each member function * - record member function number (eventually an offset into dictionary!) @@ -876,11 +1427,13 @@ List ms; { /* class definition body */ * - check that extended class hierarchy does not contain any cycles * ------------------------------------------------------------------------*/ -static Void local checkClassDefn(c) /* validate class definition */ +static Void local checkClassDefn(c) /* validate class definition */ Class c; { List tyvars = NIL; Int args = cclass(c).arity - 1; Cell temp = cclass(c).head; + List fs = NIL; + List ss = NIL; for (; isAp(temp); temp=fun(temp)) { if (!isVar(arg(temp))) { @@ -904,10 +1457,14 @@ Class c; { tcDeps = NIL; /* find dependents */ map2Proc(depPredExp,cclass(c).line,tyvars,cclass(c).supers); + h98CheckCtxt(cclass(c).line,"class definition",FALSE,cclass(c).supers,NIL); cclass(c).numSupers = length(cclass(c).supers); cclass(c).defaults = extractBindings(cclass(c).members); /* defaults*/ - cclass(c).members = extractSigdecls(cclass(c).members); - map2Proc(checkMems,c,tyvars,cclass(c).members); + ss = extractSigdecls(cclass(c).members); + fs = extractFixdecls(cclass(c).members); + cclass(c).members = pair(ss,fs); + map2Proc(checkMems,c,tyvars,ss); + cclass(c).kinds = tcDeps; tcDeps = NIL; } @@ -924,6 +1481,8 @@ Cell pred; { h = fun(pred); } arg(pred) = depTypeExp(line,tyvars,arg(pred)); + if (args!=1) + h98DoesntSupport(line,"multiple parameter classes"); if (isQCon(h)) { /* standard class constraint */ Class c = findQualClass(h); @@ -937,8 +1496,9 @@ Cell pred; { textToStr(cclass(c).text) EEND; } - if (cellIsMember(c,classDefns) && !cellIsMember(c,tcDeps)) + if (cellIsMember(c,classDefns) && !cellIsMember(c,tcDeps)) { tcDeps = cons(c,tcDeps); + } } #if TREX else if (isExt(h)) { /* Lacks predicate */ @@ -974,7 +1534,7 @@ Cell m; { fst(snd(t)) = cons(cclass(c).head,fst(snd(t)));/* Add main predicate */ snd(snd(t)) = depTopType(line,tyvars,snd(snd(t))); - for (tvs=tyvars; nonNull(tvs); tvs=tl(tvs)) { /* Quantify */ + for (tvs=tyvars; nonNull(tvs); tvs=tl(tvs)){/* Quantify */ sig = ap(NIL,sig); } t = mkPolyType(sig,t); @@ -984,11 +1544,13 @@ Cell m; { if (isAmbiguous(t)) { ambigError(line,"class declaration",hd(vs),t); } + h98CheckType(line,"member type",hd(vs),t); } static Void local addMembers(c) /* Add definitions of member funs */ Class c; { /* and other parts of class struct.*/ - List ms = cclass(c).members; + List ms = fst(cclass(c).members); + List fs = snd(cclass(c).members); List ns = NIL; /* List of names */ Int mno; /* Member function number */ @@ -1002,12 +1564,27 @@ Class c; { /* and other parts of class struct.*/ List vs = rev(snd3(hd(ms))); Type t = thd3(hd(ms)); for (; nonNull(vs); vs=tl(vs)) { - ns = cons(newMember(line,mno++,hd(vs),t),ns); + ns = cons(newMember(line,mno++,hd(vs),t,c),ns); } } cclass(c).members = rev(ns); /* Save list of members */ cclass(c).numMembers = length(cclass(c).members); + for (; nonNull(fs); fs=tl(fs)) { /* fixity declarations */ + Int line = intOf(fst3(hd(fs))); + List ops = snd3(hd(fs)); + Syntax s = intOf(thd3(hd(fs))); + for (; nonNull(ops); ops=tl(ops)) { + Name n = nameIsMember(textOf(hd(ops)),cclass(c).members); + if (isNull(n)) { + missFixity(line,textOf(hd(ops))); + } else if (name(n).syntax!=NO_SYNTAX) { + dupFixity(line,textOf(hd(ops))); + } + name(n).syntax = s; + } + } + /* Not actually needed just yet; for the time being, dictionary code will not be passed through the type checker. @@ -1019,27 +1596,25 @@ Class c; { /* and other parts of class struct.*/ */ mno = cclass(c).numSupers + cclass(c).numMembers; - cclass(c).dcon = addPrimCfun(generateText("Make.%s",c),mno,0,0); - implementCfun(cclass(c).dcon,NIL); /* ADR addition */ -#if USE_NEWTYPE_FOR_DICTS + cclass(c).dcon = addPrimCfun(generateText("Make.%s",c),mno,0,NIL); if (mno==1) { /* Single entry dicts use newtype */ name(cclass(c).dcon).defn = nameId; name(hd(cclass(c).members)).number = mfunNo(0); } -#endif cclass(c).dbuild = newDBuild(c); cclass(c).defaults = classBindings("class",c,cclass(c).defaults); } -static Name local newMember(l,no,v,t) /* Make definition for member fn */ -Int l; -Int no; -Cell v; -Type t; { +static Name local newMember(l,no,v,t,parent) +Int l; /* Make definition for member fn */ +Int no; +Cell v; +Type t; +Class parent; { Name m = findName(textOf(v)); if (isNull(m)) { - m = newName(textOf(v)); + m = newName(textOf(v),parent); } else if (name(m).defn!=PREDEFINED) { ERRMSG(l) "Repeated definition for member function \"%s\"", textToStr(name(m).text) @@ -1060,7 +1635,7 @@ Int no; { char buf[16]; sprintf(buf,"sc%d.%s",no,"%s"); - s = newName(generateText(buf,c)); + s = newName(generateText(buf,c),c); name(s).line = cclass(c).line; name(s).arity = 1; name(s).number = DFUNNAME; @@ -1069,7 +1644,7 @@ Int no; { static Name local newDBuild(c) /* Make definition for builder */ Class c; { - Name b = newName(generateText("class.%s",c)); + Name b = newName(generateText("class.%s",c),c); name(b).line = cclass(c).line; name(b).arity = cclass(c).numSupers+1; return b; @@ -1102,7 +1677,7 @@ Class c; { /* class hierarchy is acyclic */ ERRMSG(cclass(c).line) "Class hierarchy for \"%s\" is not acyclic", textToStr(cclass(c).text) EEND; - } else if (cclass(c).level == 0) { /* visiting class for first time */ + } else if (cclass(c).level == 0) { /* visiting class for first time */ List scs = cclass(c).supers; Int lev = 0; cclass(c).level = (-1); @@ -1120,30 +1695,30 @@ Class c; { /* class hierarchy is acyclic */ * ------------------------------------------------------------------------*/ static List local classBindings(where,c,bs) -String where; /*check validity of bindings bs for*/ -Class c; /* class c (or an instance of c) */ +String where; /* Check validity of bindings bs */ +Class c; /* for class c (or an inst of c) */ List bs; { /* sort into approp. member order */ List nbs = NIL; for (; nonNull(bs); bs=tl(bs)) { - Cell b = hd(bs); + Cell b = hd(bs); + Cell body = snd(snd(b)); Name mnm; - if (!isVar(fst(b))) { /* only allows function bindings */ - ERRMSG(rhsLine(snd(snd(snd(b))))) - "Pattern binding illegal in %s declaration", where + if (!isVar(fst(b))) { /* Only allow function bindings */ + ERRMSG(rhsLine(snd(body))) + "Pattern binding illegal in %s declaration", where EEND; } if (isNull(mnm=memberName(c,textOf(fst(b))))) { - ERRMSG(rhsLine(snd(hd(snd(snd(b)))))) + ERRMSG(rhsLine(snd(hd(body)))) "No member \"%s\" in class \"%s\"", textToStr(textOf(fst(b))), textToStr(cclass(c).text) EEND; } - - snd(b) = snd(snd(b)); - nbs = numInsert(mfunOf(mnm)-1,b,nbs); + snd(b) = body; + nbs = numInsert(mfunOf(mnm)-1,b,nbs); } return nbs; } @@ -1160,8 +1735,8 @@ Text t; { /* return NIL if not a member */ return NIL; } -static List local numInsert(n,x,xs) /* insert x at nth position in xs, */ -Int n; /* filling gaps with NIL */ +static List local numInsert(n,x,xs) /* insert x at nth position in xs, */ +Int n; /* filling gaps with NIL */ Cell x; List xs; { List start = isNull(xs) ? cons(NIL,NIL) : xs; @@ -1194,9 +1769,10 @@ List vs; { /* listed in us. */ case VAROPCELL : if (nonNull(findBtyvs(textOf(ty))) || varIsMember(textOf(ty),us)) { return vs; - } else { + } else { return maybeAppendVar(ty,vs); - } + } + case POLYTYPE : return typeVarsIn(monotypeOf(ty),polySigOf(ty),vs); case QUAL : { List qs = fst(snd(ty)); @@ -1218,8 +1794,8 @@ List vs; { /* listed in us. */ return vs; } -static List local maybeAppendVar(v,vs) /* append variable to list if not */ -Cell v; /* already included */ +static List local maybeAppendVar(v,vs) /* append variable to list if not */ +Cell v; /* already included */ List vs; { Text t = textOf(v); List p = NIL; @@ -1238,6 +1814,7 @@ List vs; { } else { vs = cons(v,NIL); } + return vs; } @@ -1267,6 +1844,7 @@ Type type; { } else { type = depTopType(line,tvs,type); } + if (n>0) { if (n>=NUM_OFFSETS) { ERRMSG(line) "Too many type variables in %s\n", where @@ -1284,6 +1862,8 @@ Type type; { kindType(line,"type expression",type); fixKinds(); unkindTypes = sunk; + + h98CheckType(line,where,e,type); return type; } @@ -1295,7 +1875,7 @@ Type t; { Type t1 = t; Int nr2 = 0; Int i = 1; - for (; getHead(t1)==typeArrow; ++i) { + for (; getHead(t1)==typeArrow && argCount==2; ++i) { arg(fun(t1)) = depCompType(l,tvs,arg(fun(t1))); if (isPolyType(arg(fun(t1)))) { nr2 = i; @@ -1323,35 +1903,16 @@ Type t; { List nfr = NIL; if (isPolyType(t)) { List vs = fst(snd(t)); - List bvs = typeVarsIn(monotypeOf(t),NIL,NIL); - List us = vs; - for (; nonNull(us); us=tl(us)) { - Text u = textOf(hd(us)); - if (varIsMember(u,tl(us))) { - ERRMSG(l) "Duplicated quantified variable %s", - textToStr(u) - EEND; - } - if (varIsMember(u,tvs)) { - ERRMSG(l) "Local quantifier for %s hides an outer use", - textToStr(u) - EEND; - } - if (!varIsMember(u,bvs)) { - ERRMSG(l) "Locally quantified variable %s is not used", - textToStr(u) - EEND; - } - } - nfr = replicate(length(vs),NIL); - tvs = appendOnto(tvs,vs); - t = monotypeOf(t); + t = monotypeOf(t); + tvs = checkQuantVars(l,vs,tvs,t); + nfr = replicate(length(vs),NIL); } if (whatIs(t)==QUAL) { map2Proc(depPredExp,l,tvs,fst(snd(t))); snd(snd(t)) = depTypeExp(l,tvs,snd(snd(t))); - if (isAmbiguous(t)) + if (isAmbiguous(t)) { ambigError(l,"type component",NIL,t); + } } else { t = depTypeExp(l,tvs,t); } @@ -1396,7 +1957,7 @@ Type type; { } #if TREX - case EXT : + case EXT : h98DoesntSupport(line,"extensible records"); #endif case TYCON : case TUPLE : break; @@ -1426,11 +1987,66 @@ Text tv; { return mkOffset(offset); } +static List local checkQuantVars(line,vs,tvs,body) +Int line; +List vs; /* variables to quantify over */ +List tvs; /* variables already in scope */ +Cell body; { /* type/constr for scope of vars */ + if (nonNull(vs)) { + List bvs = typeVarsIn(body,NIL,NIL); + List us = vs; + for (; nonNull(us); us=tl(us)) { + Text u = textOf(hd(us)); + if (varIsMember(u,tl(us))) { + ERRMSG(line) "Duplicated quantified variable %s", + textToStr(u) + EEND; + } + if (varIsMember(u,tvs)) { + ERRMSG(line) "Local quantifier for %s hides an outer use", + textToStr(u) + EEND; + } + if (!varIsMember(u,bvs)) { + ERRMSG(line) "Locally quantified variable %s is not used", + textToStr(u) + EEND; + } + } + tvs = appendOnto(tvs,vs); + } + return tvs; +} + /* -------------------------------------------------------------------------- * Check for ambiguous types: * A type Preds => type is ambiguous if not (TV(P) `subset` TV(type)) * ------------------------------------------------------------------------*/ +static List local offsetTyvarsIn(t,vs) /* add list of offset tyvars in t */ +Type t; /* to list vs */ +List vs; { + switch (whatIs(t)) { + case AP : return offsetTyvarsIn(fun(t), + offsetTyvarsIn(arg(t),vs)); + + case OFFSET : if (cellIsMember(t,vs)) + return vs; + else + return cons(t,vs); + + case QUAL : return offsetTyvarsIn(snd(t),vs); + + case POLYTYPE : return offsetTyvarsIn(monotypeOf(t),vs); + /* slightly inaccurate, but won't matter here */ + + case EXIST : + case RANK2 : return offsetTyvarsIn(snd(snd(t)),vs); + + default : return vs; + } +} + Bool isAmbiguous(type) /* Determine whether type is */ Type type; { /* ambiguous */ if (isPolyType(type)) { @@ -1474,9 +2090,9 @@ Cell c; { Int n = argCount; #ifdef DEBUG_KINDS - printf("kindConstr: alpha=%d, m=%d, c=",alpha,m); + Printf("kindConstr: alpha=%d, m=%d, c=",alpha,m); printType(stdout,c); - printf("\n"); + Printf("\n"); #endif switch (whatIs(h)) { @@ -1488,14 +2104,16 @@ Cell c; { Kinds ks = polySigOf(t); Int m1 = 0; Int beta; - for (; isAp(ks); ks=tl(ks)) + for (; isAp(ks); ks=tl(ks)) { m1++; + } beta = newKindvars(m1); unkindTypes = cons(pair(mkInt(beta),t),unkindTypes); checkKind(line,beta,m1,monotypeOf(t),NIL,pt,STAR,0); } return; + case CDICTS : case QUAL : if (n!=0) { internal("kindConstr2"); } @@ -1528,7 +2146,7 @@ Cell c; { if (n==0) { /* trivial case, no arguments */ typeIs = kindAtom(alpha,c); - } else { /* non-trivial application */ + } else { /* non-trivial application */ static String app = "constructor application"; Cell a = c; Int i; @@ -1569,9 +2187,9 @@ Cell c; { #endif } #if DEBUG_KINDS - printf("kindAtom(%d,whatIs(%d)) on ",alpha,whatIs(c)); + Printf("kindAtom(%d,whatIs(%d)) on ",alpha,whatIs(c)); printType(stdout,c); - printf("\n"); + Printf("\n"); #endif internal("kindAtom"); return STAR;/* not reached */ @@ -1628,11 +2246,11 @@ static Void local fixKinds() { /* add kind annotations to types */ } } #ifdef DEBUG_KINDS - printf("Type expression: "); + Printf("Type expression: "); printType(stdout,snd(pr)); - printf(" :: "); + Printf(" :: "); printKind(stdout,polySigOf(snd(pr))); - printf("\n"); + Printf("\n"); #endif } } @@ -1701,8 +2319,8 @@ Cell c; { /* is well-kinded */ } } else { /* scan type exprs in class defn to*/ - List ms = cclass(c).members; /* determine the class signature */ - Int m = cclass(c).arity; + List ms = fst(cclass(c).members); + Int m = cclass(c).arity; /* determine the class signature */ Int beta = newKindvars(m); kindPred(cclass(c).line,beta,m,cclass(c).head); map3Proc(kindPred,cclass(c).line,beta,m,cclass(c).supers); @@ -1719,9 +2337,9 @@ Cell c; { /* given tycon/class */ if (isTycon(c)) { tycon(c).kind = copyKindvar(intOf(tycon(c).kind)); #ifdef DEBUG_KINDS - printf("%s :: ",textToStr(tycon(c).text)); + Printf("%s :: ",textToStr(tycon(c).text)); printKind(stdout,tycon(c).kind); - putchar('\n'); + Putchar('\n'); #endif } else { Kinds ks = cclass(c).kinds; @@ -1729,9 +2347,9 @@ Cell c; { /* given tycon/class */ hd(ks) = copyKindvar(intOf(hd(ks))); } #ifdef DEBUG_KINDS - printf("%s :: ",textToStr(cclass(c).text)); + Printf("%s :: ",textToStr(cclass(c).text)); printKinds(stdout,cclass(c).kinds); - putchar('\n'); + Putchar('\n'); #endif } } @@ -1747,10 +2365,10 @@ Cell c; { /* given tycon/class */ * stages of static analysis. * ------------------------------------------------------------------------*/ -Void instDefn(line,head,ms) /* process new instance definition */ -Int line; /* definition line number */ -Cell head; /* inst header :: (context,Class) */ -List ms; { /* instance members */ +Void instDefn(line,head,ms) /* process new instance definition */ +Int line; /* definition line number */ +Cell head; /* inst header :: (context,Class) */ +List ms; { /* instance members */ Inst nw = newInst(); inst(nw).line = line; inst(nw).specifics = fst(head); @@ -1776,14 +2394,48 @@ List ms; { /* instance members */ * ------------------------------------------------------------------------*/ Bool allowOverlap = FALSE; /* TRUE => allow overlapping insts */ +Name nameListMonad = NIL; /* builder function for List Monad */ static Void local checkInstDefn(in) /* Validate instance declaration */ Inst in; { Int line = inst(in).line; List tyvars = typeVarsIn(inst(in).head,NIL,NIL); + if (haskell98) { /* Check for `simple' type */ + List tvs = NIL; + Cell t = arg(inst(in).head); + for (; isAp(t); t=fun(t)) { + if (!isVar(arg(t))) { + ERRMSG(line) + "syntax error in instance head (variable expected)" + EEND; + } + if (varIsMember(textOf(arg(t)),tvs)) { + ERRMSG(line) "repeated type variable \"%s\" in instance head", + textToStr(textOf(arg(t))) + EEND; + } + tvs = cons(arg(t),tvs); + } + if (isVar(t)) { + ERRMSG(line) + "syntax error in instance head (constructor expected)" + EEND; + } + } + depPredExp(line,tyvars,inst(in).head); + + if (haskell98) { + Type h = getHead(arg(inst(in).head)); + if (isSynonym(h)) { + ERRMSG(line) "Cannot use type synonym in instance head" + EEND; + } + } + map2Proc(depPredExp,line,tyvars,inst(in).specifics); + h98CheckCtxt(line,"instance definition",FALSE,inst(in).specifics,NIL); inst(in).numSpecifics = length(inst(in).specifics); inst(in).c = getHead(inst(in).head); if (!isClass(inst(in).c)) { @@ -1801,13 +2453,25 @@ Inst in; { insertInst(in); if (nonNull(extractSigdecls(inst(in).implements))) { - ERRMSG(line) "Type signature decls not permitted in instance decl" + ERRMSG(line) + "Type signature declarations not permitted in instance declaration" + EEND; + } + if (nonNull(extractFixdecls(inst(in).implements))) { + ERRMSG(line) + "Fixity declarations not permitted in instance declaration" EEND; } inst(in).implements = classBindings("instance", inst(in).c, extractBindings(inst(in).implements)); inst(in).builder = newInstImp(in); + /*ToDo*/ +fprintf(stderr, "\npreludeLoaded query\n" ); + if (/*!preludeLoaded &&*/ isNull(nameListMonad) && isAp(inst(in).head) + && fun(inst(in).head)==classMonad && arg(inst(in).head)==typeList) { + nameListMonad = inst(in).builder; + } } static Void local insertInst(in) /* Insert instance into class */ @@ -1822,7 +2486,7 @@ Inst in; { Int beta = newKindedVars(inst(hd(ins)).kinds); if (unifyPred(inst(in).head,alpha,inst(hd(ins)).head,beta)) { Cell pi = copyPred(inst(in).head,alpha); - if (allowOverlap) { /* So long as one is more specific */ + if (allowOverlap && !haskell98) { Bool bef = instCompare(in,hd(ins)); Bool aft = instCompare(hd(ins),in); if (bef && !aft) { /* in comes strictly before hd(ins)*/ @@ -1866,7 +2530,7 @@ Inst ia, ib;{ static Name local newInstImp(in) /* Make definition for inst builder*/ Inst in; { - Name b = newName(inventText()); + Name b = newName(inventText(),in); name(b).line = inst(in).line; name(b).arity = inst(in).numSpecifics; name(b).number = DFUNNAME; @@ -1892,11 +2556,11 @@ Int freedom; { inst(in).kinds = cons(copyKindvar(beta+freedom),inst(in).kinds); } #ifdef DEBUG_KINDS - printf("instance "); + Printf("instance "); printPred(stdout,inst(in).head); - printf(" :: "); + Printf(" :: "); printKinds(stdout,inst(in).kinds); - putchar('\n'); + Putchar('\n'); #endif emptySubstitution(); } @@ -1960,9 +2624,6 @@ Int n; { } #if EVAL_INSTANCES -/* ADR addition */ -static List evalInsts = NIL; - Void addEvalInst(line,t,arity,ctxt) /* Add dummy instance for Eval */ Int line; Cell t; @@ -1983,8 +2644,6 @@ List ctxt; { kindInst(in,arity); cclass(classEval).instances = appendOnto(cclass(classEval).instances,singleton(in)); - /* ADR addition */ - evalInsts = cons(in,evalInsts); } #endif @@ -1994,13 +2653,13 @@ Class c; /* c *must* be ShowRecRow */ Ext e; { Inst in = newInst(); inst(in).c = c; - inst(in).head = ap(c,ap2(e,mkOffset(0),mkOffset(1))); + inst(in).head = ap(c,ap2(e,aVar,bVar)); inst(in).kinds = extKind; - inst(in).specifics = cons(ap(classShow,mkOffset(0)), - cons(ap(e,mkOffset(1)), - cons(ap(c,mkOffset(1)),NIL))); + inst(in).specifics = cons(ap(classShow,aVar), + cons(ap(e,bVar), + cons(ap(c,bVar),NIL))); inst(in).numSpecifics = 3; - inst(in).builder = implementRecShw(extText(e)); + inst(in).builder = implementRecShw(extText(e),in); cclass(c).instances = appendOnto(cclass(c).instances,singleton(in)); return in; } @@ -2010,13 +2669,13 @@ Class c; /* c *must* be EqRecRow */ Ext e; { Inst in = newInst(); inst(in).c = c; - inst(in).head = ap(c,ap2(e,mkOffset(0),mkOffset(1))); + inst(in).head = ap(c,ap2(e,aVar,bVar)); inst(in).kinds = extKind; - inst(in).specifics = cons(ap(classEq,mkOffset(0)), - cons(ap(e,mkOffset(1)), - cons(ap(c,mkOffset(1)),NIL))); + inst(in).specifics = cons(ap(classEq,aVar), + cons(ap(e,bVar), + cons(ap(c,bVar),NIL))); inst(in).numSpecifics = 3; - inst(in).builder = implementRecEq(extText(e)); + inst(in).builder = implementRecEq(extText(e),in); cclass(c).instances = appendOnto(cclass(c).instances,singleton(in)); return in; } @@ -2074,9 +2733,6 @@ List is; { } while (instsChanged); mapProc(tidyDerInst,is); /* Tidy up results */ -#if DERIVE_SHOW | DERIVE_READ - cfunSfuns = NIL; /* Only needed to derive Read/Show */ -#endif } static Void local initDerInst(in) /* Prepare instance for calculation*/ @@ -2093,11 +2749,11 @@ Inst in; { /* of derived instance context */ inst(in).numSpecifics = beta; #ifdef DEBUG_DERIVING - printf("initDerInst: "); + Printf("initDerInst: "); printPred(stdout,inst(in).head); - printf("\n"); + Printf("\n"); printContext(stdout,snd(snd(inst(in).specifics))); - printf("\n"); + Printf("\n"); #endif } @@ -2109,9 +2765,9 @@ Inst in; { /* of the context for a derived */ Int beta = inst(in).numSpecifics; #ifdef DEBUG_DERIVING - printf("calcInstPreds: "); + Printf("calcInstPreds: "); printPred(stdout,inst(in).head); - printf("\n"); + Printf("\n"); #endif while (nonNull(ps)) { @@ -2159,8 +2815,9 @@ Inst in; { /* of the context for a derived */ List qs = inst(in1).specifics; Int off = mkInt(typeOff); if (whatIs(qs)==DERIVE) { /* Still being derived */ - for (qs=fst(snd(qs)); nonNull(hd(qs)); qs=tl(qs)) + for (qs=fst(snd(qs)); nonNull(hd(qs)); qs=tl(qs)) { ps = cons(pair(hd(qs),off),ps); + } retain = cons(pair(off,qs),retain); } else { /* Previously def'd inst */ for (; nonNull(qs); qs=tl(qs)) { @@ -2238,14 +2895,15 @@ Inst in; { /* calculations */ clearMarks(); copyPred(inst(in).head,o); inst(in).specifics = simpleContext(ps,o); + h98CheckCtxt(inst(in).line,"derived instance",FALSE,inst(in).specifics,in); inst(in).numSpecifics = length(inst(in).specifics); #ifdef DEBUG_DERIVING - printf("Derived instance: "); + Printf("Derived instance: "); printContext(stdout,inst(in).specifics); - printf(" ||- "); + Printf(" ||- "); printPred(stdout,inst(in).head); - printf("\n"); + Printf("\n"); #endif } @@ -2258,42 +2916,21 @@ Inst in; { List imp = NIL; Type t = getHead(arg(inst(in).head)); Class c = inst(in).c; -#if DERIVE_EQ - if (c==classEq) + if (c==classEq) { imp = deriveEq(t); - else -#endif -#if DERIVE_ORD - if (c==classOrd) + } else if (c==classOrd) { imp = deriveOrd(t); - else -#endif -#if DERIVE_ENUM - if (c==classEnum) + } else if (c==classEnum) { imp = deriveEnum(t); - else -#endif -#if DERIVE_IX - if (c==classIx) + } else if (c==classIx) { imp = deriveIx(t); - else -#endif -#if DERIVE_SHOW - if (c==classShow) + } else if (c==classShow) { imp = deriveShow(t); - else -#endif -#if DERIVE_READ - if (c==classRead) + } else if (c==classRead) { imp = deriveRead(t); - else -#endif -#if DERIVE_BOUNDED - if (c==classBounded) + } else if (c==classBounded) { imp = deriveBounded(t); - else -#endif - { + } else { ERRMSG(inst(in).line) "Cannot derive instances of class \"%s\"", textToStr(cclass(inst(in).c).text) EEND; @@ -2307,6 +2944,7 @@ Inst in; { imp); } + /* -------------------------------------------------------------------------- * Default definitions; only one default definition is permitted in a * given script file. If no default is supplied, then a standard system @@ -2339,6 +2977,11 @@ static Void local checkDefaultDefns() { /* check that default types are */ } else { defaultDefns = stdDefaults; } + + if (isNull(classNum)) { + classNum = findClass(findText("Num")); + } + for (ds=defaultDefns; nonNull(ds); ds=tl(ds)) { if (isNull(provePred(NIL,NIL,ap(classNum,hd(ds))))) { ERRMSG(defaultLine) @@ -2348,6 +2991,8 @@ static Void local checkDefaultDefns() { /* check that default types are */ } } + +/*-- from STG --*/ /* -------------------------------------------------------------------------- * Foreign import declarations are Hugs' equivalent of GHC's ccall mechanism. * They are used to "import" C functions into a module. @@ -2369,7 +3014,7 @@ Cell type; { Int l = intOf(line); if (isNull(n)) { - n = newName(t); + n = newName(t,NIL); } else if (name(n).defn!=PREDEFINED) { ERRMSG(l) "Redeclaration of foreign \"%s\"", textToStr(t) EEND; @@ -2404,7 +3049,7 @@ Cell type; { Int l = intOf(line); if (isNull(n)) { - n = newName(t); + n = newName(t,NIL); } else if (name(n).defn!=PREDEFINED) { ERRMSG(l) "Redeclaration of foreign \"%s\"", textToStr(t) EEND; @@ -2425,6 +3070,63 @@ Name p; { implementForeignExport(p); } + + + +#if 0 +/*-- from 98 --*/ +/* -------------------------------------------------------------------------- + * Primitive definitions are usually only included in the first script + * file read - the prelude. A primitive definition associates a variable + * name with a string (which identifies a built-in primitive) and a type. + * ------------------------------------------------------------------------*/ + +Void primDefn(line,prims,type) /* Handle primitive definitions */ +Cell line; +List prims; +Cell type; { + primDefns = cons(triple(line,prims,type),primDefns); +} + +static List local checkPrimDefn(pd) /* Check primitive definition */ +Triple pd; { + Int line = intOf(fst3(pd)); + List prims = snd3(pd); + Type type = thd3(pd); + emptySubstitution(); + type = checkSigType(line,"primitive definition",fst(hd(prims)),type); + for (; nonNull(prims); prims=tl(prims)) { + Cell p = hd(prims); + Bool same = isVar(p); + Text pt = textOf(same ? p : fst(p)); + String pr = textToStr(textOf(same ? p : snd(p))); + hd(prims) = addNewPrim(line,pt,pr,type); + } + return snd3(pd); +} + +static Name local addNewPrim(l,vn,s,t) /* make binding of variable vn to */ +Int l; /* primitive function referred */ +Text vn; /* to by s, with given type t */ +String s; +Cell t;{ + Name n = findName(vn); + + if (isNull(n)) { + n = newName(vn,NIL); + } else if (name(n).defn!=PREDEFINED) { + duplicateError(l,name(n).mod,vn,"primitive"); + } + + addPrim(l,n,s,t); + return n; +} +#endif + + + + + /* -------------------------------------------------------------------------- * Static analysis of patterns: * @@ -2444,31 +3146,37 @@ Name p; { * complete pattern list (as is required on the lhs of a function defn). * ------------------------------------------------------------------------*/ -static List patVars; /* List of vars bound in pattern */ +static List patVars; /* List of vars bound in pattern */ -static Cell local checkPat(line,p) /* Check valid pattern syntax */ +static Cell local checkPat(line,p) /* Check valid pattern syntax */ Int line; Cell p; { switch (whatIs(p)) { case VARIDCELL : - case VAROPCELL : addPatVar(line,p); + case VAROPCELL : addToPatVars(line,p); break; + case INFIX : return checkPat(line,tidyInfix(line,snd(p))); + case AP : return checkMaybeCnkPat(line,p); case NAME : case QUALIDENT : - case CONIDCELL : + case CONIDCELL : case CONOPCELL : return checkApPat(line,0,p); +#if BIGNUMS + case ZERONUM : + case POSNUM : + case NEGNUM : +#endif case WILDCARD : case STRCELL : case CHARCELL : - case INTCELL : - case BIGCELL : case FLOATCELL : break; + case INTCELL : break; - case ASPAT : addPatVar(line,fst(snd(p))); + case ASPAT : addToPatVars(line,fst(snd(p))); snd(snd(p)) = checkPat(line,snd(snd(p))); break; @@ -2481,27 +3189,11 @@ Cell p; { case CONFLDS : depConFlds(line,p,TRUE); break; - case ESIGN : { Type t = snd(snd(p)); - List tvs = typeVarsIn(t,NIL,NIL); - for (; nonNull(tvs); tvs=tl(tvs)) { - Int beta = newKindvars(1); - hd(btyvars) = cons(pair(hd(tvs),mkInt(beta)), - hd(btyvars)); - } - t = checkSigType(line, - "pattern type", - fst(snd(p)), - t); - if (isPolyType(t) - || whatIs(t)==QUAL - || whatIs(t)==RANK2) { - ERRMSG(line) - "Illegal type in pattern annotation" - EEND; - } - snd(snd(p)) = t; - fst(snd(p)) = checkPat(line,fst(snd(p))); - } + case ESIGN : snd(snd(p)) = checkPatType(line, + "pattern", + fst(snd(p)), + snd(snd(p))); + fst(snd(p)) = checkPat(line,fst(snd(p))); break; default : ERRMSG(line) "Illegal pattern syntax" @@ -2510,25 +3202,24 @@ Cell p; { return p; } -static Cell local checkMaybeCnkPat(l,p) /* Check applicative pattern with */ -Int l; /* the possibility of n+k pattern */ +static Cell local checkMaybeCnkPat(l,p)/* Check applicative pattern with */ +Int l; /* the possibility of n+k pattern */ Cell p; { #if NPLUSK Cell h = getHead(p); if (argCount==2 && isVar(h) && textOf(h)==textPlus) { /* n+k */ Cell v = arg(fun(p)); - if (!isInt(arg(p)) && !isBignum(arg(p))) { - ERRMSG(l) "Second argument in (n+k) pattern must be an integer" - EEND; + if (!isInt(arg(p))) { + ERRMSG(l) "Second argument in (n+k) pattern must be an integer" + EEND; } -#if 0 /* can't call intOf - it might be a bignum */ if (intOf(arg(p))<=0) { - ERRMSG(l) "Integer k in (n+k) pattern must be > 0" - EEND; + ERRMSG(l) "Integer k in (n+k) pattern must be > 0" + EEND; } -#endif - overwrite2(fun(p),ADDPAT,arg(p)); + fst(fun(p)) = ADDPAT; + intValOf(fun(p)) = intOf(arg(p)); arg(p) = checkPat(l,v); return p; } @@ -2537,8 +3228,8 @@ Cell p; { } static Cell local checkApPat(line,args,p) -Int line; /* check validity of application */ -Int args; /* of constructor to arguments */ +Int line; /* check validity of application */ +Int args; /* of constructor to arguments */ Cell p; { switch (whatIs(p)) { case AP : fun(p) = checkApPat(line,args+1,fun(p)); @@ -2552,19 +3243,20 @@ Cell p; { break; #if TREX - case EXT : if (args!=2) { + case EXT : h98DoesntSupport(line,"extensible records"); + if (args!=2) { ERRMSG(line) "Illegal record pattern" EEND; } break; #endif - case QUALIDENT : - if (!isQCon(p)) { - ERRMSG(line) "Illegal use of qualified variable in pattern" - EEND; - } - /* deliberate fall through */ + case QUALIDENT : if (!isQCon(p)) { + ERRMSG(line) + "Illegal use of qualified variable in pattern" + EEND; + } + /* deliberate fall through */ case CONIDCELL : case CONOPCELL : p = conDefined(line,p); checkCfunArgs(line,p,args); @@ -2580,40 +3272,41 @@ Cell p; { return p; } -static Void local addPatVar(line,v) /* add variable v to list of vars */ -Int line; /* in current pattern, checking for*/ -Cell v; { /* repeated variables. */ - Text t = textOf(v); - List p = NIL; - List n = patVars; - - for (; nonNull(n); p=n, n=tl(n)) { - if (textOf(hd(n))==t) { - ERRMSG(line) "Repeated variable \"%s\" in pattern", - textToStr(t) - EEND; - } - } - if (isNull(p)) { +static Void local addToPatVars(line,v) /* Add variable v to list of vars */ +Int line; /* in current pattern, checking */ +Cell v; { /* for repeated variables. */ + Text t = textOf(v); + List p = NIL; + List n = patVars; + + for (; nonNull(n); p=n, n=tl(n)) { + if (textOf(hd(n))==t) { + ERRMSG(line) "Repeated variable \"%s\" in pattern", + textToStr(t) + EEND; + } + } + + if (isNull(p)) { patVars = cons(v,NIL); - } else { + } else { tl(p) = cons(v,NIL); - } + } } -static Name local conDefined(line,nm) /* check that nm is the name of a */ -Int line; /* previously defined constructor */ -Cell nm; { /* function. */ - Cell c=findQualName(line,nm); - if (isNull(c)) { +static Name local conDefined(line,nm) /* check that nm is the name of a */ +Int line; /* previously defined constructor */ +Cell nm; { /* function. */ + Name n = findQualName(nm); + if (isNull(n)) { ERRMSG(line) "Undefined constructor function \"%s\"", identToStr(nm) EEND; } - checkIsCfun(line,c); - return c; + checkIsCfun(line,n); + return n; } -static Void local checkIsCfun(line,c) /* Check that c is a constructor fn*/ +static Void local checkIsCfun(line,c) /* Check that c is a constructor fn */ Int line; Name c; { if (!isCfun(c)) { @@ -2624,20 +3317,41 @@ Name c; { } static Void local checkCfunArgs(line,c,args) -Int line; /* Check constructor applied with */ -Cell c; /* correct number of arguments */ +Int line; /* Check constructor applied with */ +Cell c; /* correct number of arguments */ Int args; { - if (name(c).arity!=args) { - ERRMSG(line) "Constructor function \"%s\" needs %d args in pattern", - textToStr(name(c).text), name(c).arity + Int a = userArity(c); + if (a!=args) { + ERRMSG(line) + "Constructor \"%s\" must have exactly %d argument%s in pattern", + textToStr(name(c).text), a, ((a==1)?"":"s") + EEND; + } +} + +static Cell local checkPatType(l,wh,e,t)/* Check type appearing in pattern */ +Int l; +String wh; +Cell e; +Type t; { + List tvs = typeVarsIn(t,NIL,NIL); + h98DoesntSupport(l,"pattern type annotations"); + for (; nonNull(tvs); tvs=tl(tvs)) { + Int beta = newKindvars(1); + hd(btyvars) = cons(pair(hd(tvs),mkInt(beta)), hd(btyvars)); + } + t = checkSigType(l,"pattern type",e,t); + if (isPolyType(t) || whatIs(t)==QUAL || whatIs(t)==RANK2) { + ERRMSG(l) "Illegal syntax in %s type annotation", wh EEND; } + return t; } static Cell local applyBtyvs(pat) /* Record bound type vars in pat */ Cell pat; { List bts = hd(btyvars); - btyvars = tl(btyvars); + leaveBtyvs(); if (nonNull(bts)) { pat = ap(BIGLAM,pair(bts,pat)); for (; nonNull(bts); bts=tl(bts)) { @@ -2652,14 +3366,18 @@ Cell pat; { * dependency and scope analysis. * ------------------------------------------------------------------------*/ -static List bounds; /* list of lists of bound vars */ -static List bindings; /* list of lists of binds in scope */ -static List depends; /* list of lists of dependents */ +static List bounds; /* list of lists of bound vars */ +static List bindings; /* list of lists of binds in scope */ +static List depends; /* list of lists of dependents */ + +/* bounds :: [[Var]] -- var equality used on Vars */ +/* bindings :: [[([Var],?)]] -- var equality used on Vars */ +/* depends :: [[Var]] -- pointer equality used on Vars */ -#define saveBvars() hd(bounds) /* list of bvars in current scope */ -#define restoreBvars(bs) hd(bounds)=bs /* restore list of bound variables */ +#define saveBvars() hd(bounds) /* list of bvars in current scope */ +#define restoreBvars(bs) hd(bounds)=bs /* restore list of bound variables */ -static Cell local bindPat(line,p) /* add new bound vars for pattern */ +static Cell local bindPat(line,p) /* add new bound vars for pattern */ Int line; Cell p; { patVars = NIL; @@ -2668,7 +3386,7 @@ Cell p; { return p; } -static Void local bindPats(line,ps) /* add new bound vars for patterns */ +static Void local bindPats(line,ps) /* add new bound vars for patterns */ Int line; List ps; { patVars = NIL; @@ -2684,7 +3402,9 @@ List ps; { * known. * * The result of parsing a list of value declarations is a list of Eqns: - * Eqn ::= (SIGDECL,(Line,[Var],type)) | (Expr,Rhs) + * Eqn ::= (SIGDECL,(Line,[Var],type)) + * | (FIXDECL,(Line,[Op],SyntaxInt)) + * | (Expr,Rhs) * The ordering of the equations in this list is the reverse of the original * ordering in the script parsed. This is a consequence of the structure of * the parser ... but also turns out to be most convenient for the static @@ -2713,15 +3433,16 @@ List ps; { * - Every variable named in a type signature declaration is defined by * one or more equations elsewhere in the script. * - No variable has more than one type declaration. + * - Similar properties for fixity declarations. * * ------------------------------------------------------------------------*/ -#define bindingType(b) fst(snd(b)) /* type (or types) for binding */ -#define fbindAlts(b) snd(snd(b)) /*alternatives for function binding*/ +#define bindingAttr(b) fst(snd(b)) /* type(s)/fixity(ies) for binding */ +#define fbindAlts(b) snd(snd(b)) /* alternatives for function binding*/ -static List local extractSigdecls(es) /* extract the SIGDECLS from list */ -List es; { /* of equations */ - List sigDecls = NIL; /* :: [(Line,[Var],Type)] */ +static List local extractSigdecls(es) /* Extract the SIGDECLS from list */ +List es; { /* of equations */ + List sigdecls = NIL; /* :: [(Line,[Var],Type)] */ for(; nonNull(es); es=tl(es)) { if (fst(hd(es))==SIGDECL) { /* type-declaration? */ @@ -2735,103 +3456,167 @@ List es; { /* of equations */ EEND; } } - sigDecls = cons(sig,sigDecls); /* discard SIGDECL tag */ + sigdecls = cons(sig,sigdecls); /* discard SIGDECL tag*/ } } - return sigDecls; + return sigdecls; } -static List local extractBindings(es) /* extract untyped bindings from */ -List es; { /* given list of equations */ +static List local extractFixdecls(es) /* Extract the FIXDECLS from list */ +List es; { /* of equations */ + List fixdecls = NIL; /* :: [(Line,SyntaxInt,[Op])] */ + + for(; nonNull(es); es=tl(es)) { + if (fst(hd(es))==FIXDECL) { /* fixity declaration?*/ + fixdecls = cons(snd(hd(es)),fixdecls); /* discard FIXDECL tag*/ + } + } + return fixdecls; +} + +static List local extractBindings(ds) /* extract untyped bindings from */ +List ds; { /* given list of equations */ Cell lastVar = NIL; /* = var def'd in last eqn (if any)*/ Int lastArity = 0; /* = number of args in last defn */ List bs = NIL; /* :: [Binding] */ - for(; nonNull(es); es=tl(es)) { - Cell e = hd(es); - - if (fst(e)!=SIGDECL) { - Int line = rhsLine(snd(e)); - Cell lhsHead = getHead(fst(e)); - - switch (whatIs(lhsHead)) { - case VARIDCELL : - case VAROPCELL : { /* function-binding? */ - Cell newAlt = pair(getArgs(fst(e)), snd(e)); - if (nonNull(lastVar) && textOf(lhsHead)==textOf(lastVar)) { - if (argCount!=lastArity) { - ERRMSG(line) - "Equations give different arities for \"%s\"", - textToStr(textOf(lhsHead)) - EEND; - } - fbindAlts(hd(bs)) = cons(newAlt,fbindAlts(hd(bs))); - } - else { - lastVar = lhsHead; - lastArity = argCount; - notDefined(line,bs,lhsHead); - bs = cons(pair(lhsHead, - pair(NIL, - singleton(newAlt))), - bs); - } + for(; nonNull(ds); ds=tl(ds)) { + Cell d = hd(ds); + if (fst(d)==FUNBIND) { /* Function bindings */ + Cell rhs = snd(snd(d)); + Int line = rhsLine(rhs); + Cell lhs = fst(snd(d)); + Cell v = getHead(lhs); + Cell newAlt = pair(getArgs(lhs),rhs); + if (!isVar(v)) { + internal("FUNBIND"); + } + if (nonNull(lastVar) && textOf(v)==textOf(lastVar)) { + if (argCount!=lastArity) { + ERRMSG(line) "Equations give different arities for \"%s\"", + textToStr(textOf(v)) + EEND; } - break; + fbindAlts(hd(bs)) = cons(newAlt,fbindAlts(hd(bs))); + } + else { + lastVar = v; + lastArity = argCount; + notDefined(line,bs,v); + bs = cons(pair(v,pair(NIL,singleton(newAlt))),bs); + } - case QUALIDENT: if (isQVar(lhsHead)) { - ERRMSG(line) "Binding for qualified variable \"%s\" not allowed", - identToStr(lhsHead) - EEND; - } - break; - /* deliberate fall through */ -#if TREX - case EXT : -#endif - case CONFLDS : - case CONOPCELL : - case CONIDCELL : - case FINLIST : - case TUPLE : - case NAME : - case LAZYPAT : - case ASPAT : lastVar = NIL; /* pattern-binding? */ - patVars = NIL; - enterBtyvs(); - fst(e) = checkPat(line,fst(e)); - if (isNull(patVars)) { - ERRMSG(line) - "No variables defined in lhs pattern" - EEND; - } - map2Proc(notDefined,line,bs,patVars); - bs = cons(pair(patVars,pair(NIL,e)),bs); - if (nonNull(hd(btyvars))) { - ERRMSG(line) - "Sorry, no type variables are allowed in pattern binding type annotations" - EEND; - } - leaveBtyvs(); - break; - - default : ERRMSG(line) "Improper left hand side" - EEND; + } else if (fst(d)==PATBIND) { /* Pattern bindings */ + Cell rhs = snd(snd(d)); + Int line = rhsLine(rhs); + Cell pat = fst(snd(d)); + while (whatIs(pat)==ESIGN) {/* Move type annotations to rhs */ + Cell p = fst(snd(pat)); + fst(snd(pat)) = rhs; + snd(snd(d)) = rhs = pat; + fst(snd(d)) = pat = p; + fst(rhs) = RSIGN; } + if (isVar(pat)) { /* Convert simple pattern bind to */ + notDefined(line,bs,pat);/* a function binding */ + bs = cons(pair(pat,pair(NIL,singleton(pair(NIL,rhs)))),bs); + } else { + List vs = getPatVars(line,pat,NIL); + if (isNull(vs)) { + ERRMSG(line) "No variables defined in lhs pattern" + EEND; + } + map2Proc(notDefined,line,bs,vs); + bs = cons(pair(vs,pair(NIL,snd(d))),bs); + } + lastVar = NIL; } } return bs; } -static List local eqnsToBindings(es) /*Convert list of equations to list*/ -List es; { /*of typed bindings */ +static List local getPatVars(line,p,vs) /* Find list of variables bound in */ +Int line; /* pattern p */ +Cell p; +List vs; { + switch (whatIs(p)) { + case AP : do { + vs = getPatVars(line,arg(p),vs); + p = fun(p); + } while (isAp(p)); + return vs; /* Ignore head of application */ + + case CONFLDS : { List pfs = snd(snd(p)); + for (; nonNull(pfs); pfs=tl(pfs)) { + if (isVar(hd(pfs))) { + vs = addPatVar(line,hd(pfs),vs); + } else { + vs = getPatVars(line,snd(hd(pfs)),vs); + } + } + } + return vs; + + case FINLIST : { List ps = snd(p); + for (; nonNull(ps); ps=tl(ps)) { + vs = getPatVars(line,hd(ps),vs); + } + } + return vs; + + case ESIGN : return getPatVars(line,fst(snd(p)),vs); + + case LAZYPAT : + case NEG : + case ONLY : + case INFIX : return getPatVars(line,snd(p),vs); + + case ASPAT : return addPatVar(line,fst(snd(p)), + getPatVars(line,snd(snd(p)),vs)); + + case VARIDCELL : + case VAROPCELL : return addPatVar(line,p,vs); + + case CONIDCELL : + case CONOPCELL : + case QUALIDENT : + case INTCELL : + case FLOATCELL : + case CHARCELL : + case STRCELL : + case NAME : + case WILDCARD : return vs; + + default : internal("getPatVars"); + } + return vs; +} + +static List local addPatVar(line,v,vs) /* Add var to list of previously */ +Int line; /* encountered variables */ +Cell v; +List vs; { + if (varIsMember(textOf(v),vs)) { + ERRMSG(line) "Repeated use of variable \"%s\" in pattern binding", + textToStr(textOf(v)) + EEND; + } + return cons(v,vs); +} + +static List local eqnsToBindings(es,ts,cs,ps) +List es; /* Convert list of equations to */ +List ts; /* list of typed bindings */ +List cs; +List ps; { List bs = extractBindings(es); - map1Proc(addSigDecl,bs,extractSigdecls(es)); + map1Proc(addSigdecl,bs,extractSigdecls(es)); + map4Proc(addFixdecl,bs,ts,cs,ps,extractFixdecls(es)); return bs; } -static Void local notDefined(line,bs,v) /* check if name already defined in*/ -Int line; /* list of bindings */ +static Void local notDefined(line,bs,v)/* check if name already defined in */ +Int line; /* list of bindings */ List bs; Cell v; { if (nonNull(findBinding(textOf(v),bs))) { @@ -2840,72 +3625,448 @@ Cell v; { } } -static Cell local findBinding(t,bs) /* look for binding for variable t */ -Text t; /* in list of bindings bs */ +static Cell local findBinding(t,bs) /* look for binding for variable t */ +Text t; /* in list of bindings bs */ List bs; { for (; nonNull(bs); bs=tl(bs)) { if (isVar(fst(hd(bs)))) { /* function-binding? */ if (textOf(fst(hd(bs)))==t) { return hd(bs); } - } else if (nonNull(varIsMember(t,fst(hd(bs))))) { /* pattern-binding? */ + } else if (nonNull(varIsMember(t,fst(hd(bs))))){/* pattern-binding?*/ return hd(bs); } } return NIL; } -static Void local addSigDecl(bs,sigDecl)/* add type information to bindings*/ -List bs; /* :: [Binding] */ -Cell sigDecl; { /* :: (Line,[Var],Type) */ - Int line = intOf(fst3(sigDecl)); - Cell vs = snd3(sigDecl); - Cell type = checkSigType(line,"type declaration",hd(vs),thd3(sigDecl)); - - map3Proc(setType,line,type,bs,vs); -} - -static Void local setType(line,type,bs,v) -Int line; /* Set type of variable */ -Cell type; -Cell v; -List bs; { +static Cell local getAttr(bs,v) /* Locate type/fixity attribute */ +List bs; /* for variable v in bindings bs */ +Cell v; { Text t = textOf(v); Cell b = findBinding(t,bs); - if (isNull(b)) { - ERRMSG(line) "Type declaration for variable \"%s\" with no body", - textToStr(t) - EEND; - } - - if (isVar(fst(b))) { /* function-binding? */ - if (isNull(bindingType(b))) { - bindingType(b) = type; - return; + if (isNull(b)) { /* No binding */ + return NIL; + } else if (isVar(fst(b))) { /* func binding? */ + if (isNull(bindingAttr(b))) { + bindingAttr(b) = pair(NIL,NIL); } - } else { /* pattern-binding? */ + return bindingAttr(b); + } else { /* pat binding? */ List vs = fst(b); - List ts = bindingType(b); + List as = bindingAttr(b); - if (isNull(ts)) { - bindingType(b) = ts = replicate(length(vs),NIL); + if (isNull(as)) { + bindingAttr(b) = as = replicate(length(vs),NIL); } + while (nonNull(vs) && t!=textOf(hd(vs))) { vs = tl(vs); - ts = tl(ts); + as = tl(as); } - if (nonNull(vs) && isNull(hd(ts))) { - hd(ts) = type; - return; + if (isNull(vs)) { + internal("getAttr"); + } else if (isNull(hd(as))) { + hd(as) = pair(NIL,NIL); } + return hd(as); } +} - ERRMSG(line) "Repeated type declaration for \"%s\"", textToStr(t) +static Void local addSigdecl(bs,sigdecl)/* add type information to bindings*/ +List bs; /* :: [Binding] */ +Cell sigdecl; { /* :: (Line,[Var],Type) */ + Int l = intOf(fst3(sigdecl)); + List vs = snd3(sigdecl); + Type type = checkSigType(l,"type declaration",hd(vs),thd3(sigdecl)); + + for (; nonNull(vs); vs=tl(vs)) { + Cell v = hd(vs); + Pair attr = getAttr(bs,v); + if (isNull(attr)) { + ERRMSG(l) "Missing binding for variable \"%s\" in type signature", + textToStr(textOf(v)) + EEND; + } else if (nonNull(fst(attr))) { + ERRMSG(l) "Repeated type signature for \"%s\"", + textToStr(textOf(v)) + EEND; + } + fst(attr) = type; + } +} + +static Void local addFixdecl(bs,ts,cs,ps,fixdecl) +List bs; +List ts; +List cs; +List ps; +Triple fixdecl; { + Int line = intOf(fst3(fixdecl)); + List ops = snd3(fixdecl); + Cell sy = thd3(fixdecl); + + for (; nonNull(ops); ops=tl(ops)) { + Cell op = hd(ops); + Text t = textOf(op); + Cell attr = getAttr(bs,op); + if (nonNull(attr)) { /* Found name in binding? */ + if (nonNull(snd(attr))) { + dupFixity(line,t); + } + snd(attr) = sy; + } else { /* Look in tycons, classes, prims */ + Name n = NIL; + List ts1 = ts; + List cs1 = cs; + List ps1 = ps; + for (; isNull(n) && nonNull(ts1); ts1=tl(ts1)) { /* tycons */ + Tycon tc = hd(ts1); + if (tycon(tc).what==DATATYPE || tycon(tc).what==NEWTYPE) { + n = nameIsMember(t,tycon(tc).defn); + } + } + for (; isNull(n) && nonNull(cs1); cs1=tl(cs1)) { /* classes */ + n = nameIsMember(t,cclass(hd(cs1)).members); + } + for (; isNull(n) && nonNull(ps1); ps1=tl(ps1)) { /* prims */ + n = nameIsMember(t,hd(ps1)); + } + + if (isNull(n)) { + missFixity(line,t); + } else if (name(n).syntax!=NO_SYNTAX) { + dupFixity(line,t); + } + name(n).syntax = intOf(sy); + } + } +} + +static Void local dupFixity(line,t) /* Report repeated fixity decl */ +Int line; +Text t; { + ERRMSG(line) + "Repeated fixity declaration for operator \"%s\"", textToStr(t) + EEND; +} + +static Void local missFixity(line,t) /* Report missing op for fixity */ +Int line; +Text t; { + ERRMSG(line) + "Cannot find binding for operator \"%s\" in fixity declaration", + textToStr(t) EEND; } +/* -------------------------------------------------------------------------- + * Dealing with infix operators: + * + * Expressions involving infix operators or unary minus are parsed as + * elements of the following type: + * + * data InfixExp = Only Exp | Neg InfixExp | Infix InfixExp Op Exp + * + * (The algorithms here do not assume that negation can be applied only once, + * i.e., that - - x is a syntax error, as required by the Haskell report. + * Instead, that restriction is captured by the grammar itself, given above.) + * + * There are rules of precedence and grouping, expressed by two functions: + * + * prec :: Op -> Int; assoc :: Op -> Assoc (Assoc = {L, N, R}) + * + * InfixExp values are rearranged accordingly when a complete expression + * has been read using a simple shift-reduce parser whose result may be taken + * to be a value of the following type: + * + * data Exp = Atom Int | Negate Exp | Apply Op Exp Exp | Error String + * + * The machine on which this parser is based can be defined as follows: + * + * tidy :: InfixExp -> [(Op,Exp)] -> Exp + * tidy (Only a) [] = a + * tidy (Only a) ((o,b):ss) = tidy (Only (Apply o a b)) ss + * tidy (Infix a o b) [] = tidy a [(o,b)] + * tidy (Infix a o b) ((p,c):ss) + * | shift o p = tidy a ((o,b):(p,c):ss) + * | red o p = tidy (Infix a o (Apply p b c)) ss + * | ambig o p = Error "ambiguous use of operators" + * tidy (Neg e) [] = tidy (tidyNeg e) [] + * tidy (Neg e) ((o,b):ss) + * | nshift o = tidy (Neg (underNeg o b e)) ss + * | nred o = tidy (tidyNeg e) ((o,b):ss) + * | nambig o = Error "illegal use of negation" + * + * At each stage, the parser can either shift, reduce, accept, or error. + * The transitions when dealing with juxtaposed operators o and p are + * determined by the following rules: + * + * shift o p = (prec o > prec p) + * || (prec o == prec p && assoc o == L && assoc p == L) + * + * red o p = (prec o < prec p) + * || (prec o == prec p && assoc o == R && assoc p == R) + * + * ambig o p = (prec o == prec p) + * && (assoc o == N || assoc p == N || assoc o /= assoc p) + * + * The transitions when dealing with juxtaposed unary minus and infix + * operators are as follows. The precedence of unary minus (infixl 6) is + * hardwired in to these definitions, as it is to the definitions of the + * Haskell grammar in the official report. + * + * nshift o = (prec o > 6) + * nred o = (prec o < 6) || (prec o == 6 && assoc o == L) + * nambig o = prec o == 6 && (assoc o == R || assoc o == N) + * + * An InfixExp of the form (Neg e) means negate the last thing in + * the InfixExp e; we can force this negation using: + * + * tidyNeg :: OpExp -> OpExp + * tidyNeg (Only e) = Only (Negate e) + * tidyNeg (Infix a o b) = Infix a o (Negate b) + * tidyNeg (Neg e) = tidyNeg (tidyNeg e) + * + * On the other hand, if we want to sneak application of an infix operator + * under a negation, then we use: + * + * underNeg :: Op -> Exp -> OpExp -> OpExp + * underNeg o b (Only e) = Only (Apply o e b) + * underNeg o b (Neg e) = Neg (underNeg o b e) + * underNeg o b (Infix e p f) = Infix e p (Apply o f b) + * + * As a concession to efficiency, we lower the number of calls to syntaxOf + * by keeping track of the values of sye, sys throughout the process. The + * value APPLIC is used to indicate that the syntax value is unknown. + * ------------------------------------------------------------------------*/ + +static Cell local tidyInfix(line,e) /* Convert infixExp to Exp */ +Int line; +Cell e; { /* :: OpExp */ + Cell s = NIL; /* :: [(Op,Exp)] */ + Syntax sye = APPLIC; /* Syntax of op in e (init unknown)*/ + Syntax sys = APPLIC; /* Syntax of op in s (init unknown)*/ + Cell d = e; + + while (fst(d)!=ONLY) { /* Attach fixities to operators */ + if (fst(d)==NEG) { + d = snd(d); + } else { + fun(fun(d)) = attachFixity(line,fun(fun(d))); + d = arg(fun(d)); + } + } + + for (;;) + switch (whatIs(e)) { + case ONLY : e = snd(e); + while (nonNull(s)) { + Cell next = arg(fun(s)); + arg(fun(s)) = e; + fun(fun(s)) = snd(fun(fun(s))); + e = s; + s = next; + } + return e; + + case NEG : if (nonNull(s)) { + if (sys==APPLIC) { /* calculate sys */ + sys = intOf(fst(fun(fun(s)))); + } + + if (precOf(sys)==UMINUS_PREC && /* nambig */ + assocOf(sys)!=UMINUS_ASSOC) { + ERRMSG(line) + "Ambiguous use of unary minus with \"" + ETHEN ERREXPR(snd(fun(fun(s)))); + ERRTEXT "\"" + EEND; + } + + if (precOf(sys)>UMINUS_PREC) { /* nshift */ + Cell e1 = snd(e); + Cell t = s; + s = arg(fun(s)); + while (whatIs(e1)==NEG) + e1 = snd(e1); + arg(fun(t)) = arg(e1); + fun(fun(t)) = snd(fun(fun(t))); + arg(e1) = t; + sys = APPLIC; + continue; + } + } + + /* Intentional fall-thru for nreduce and isNull(s) */ + + { Cell prev = e; /* e := tidyNeg e */ + Cell temp = arg(prev); + Int nneg = 1; + for (; whatIs(temp)==NEG; nneg++) { + fun(prev) = nameNegate; + prev = temp; + temp = arg(prev); + } + if (isInt(arg(temp))) { /* special cases */ + if (nneg&1) /* for literals */ + arg(temp) = mkInt(-intOf(arg(temp))); + } +#if BIGNUMS + else if (isBignum(arg(temp))) { + if (nneg&1) + arg(temp) = bigNeg(arg(temp)); + } +#endif + else if (isFloat(arg(temp))) { + if (nneg&1) + arg(temp) = mkFloat(-floatOf(arg(temp))); + } + else { + fun(prev) = nameNegate; + arg(prev) = arg(temp); + arg(temp) = e; + } + e = temp; + } + continue; + + default : if (isNull(s)) {/* Move operation onto empty stack */ + Cell next = arg(fun(e)); + s = e; + arg(fun(s)) = NIL; + e = next; + sys = sye; + sye = APPLIC; + } + else { /* deal with pair of operators */ + + if (sye==APPLIC) { /* calculate sys and sye */ + sye = intOf(fst(fun(fun(e)))); + } + if (sys==APPLIC) { + sys = intOf(fst(fun(fun(s)))); + } + + if (precOf(sye)==precOf(sys) && /* ambig */ + (assocOf(sye)!=assocOf(sys) || + assocOf(sye)==NON_ASS)) { + ERRMSG(line) "Ambiguous use of operator \"" + ETHEN ERREXPR(snd(fun(fun(e)))); + ERRTEXT "\" with \"" + ETHEN ERREXPR(snd(fun(fun(s)))); + ERRTEXT "\"" + EEND; + } + + if (precOf(sye)>precOf(sys) || /* shift */ + (precOf(sye)==precOf(sys) && + assocOf(sye)==LEFT_ASS && + assocOf(sys)==LEFT_ASS)) { + Cell next = arg(fun(e)); + arg(fun(e)) = s; + s = e; + e = next; + sys = sye; + sye = APPLIC; + } + else { /* reduce */ + Cell next = arg(fun(s)); + arg(fun(s)) = arg(e); + fun(fun(s)) = snd(fun(fun(s))); + arg(e) = s; + s = next; + sys = APPLIC; + /* sye unchanged */ + } + } + continue; + } +} + +static Pair local attachFixity(line,op) /* Attach fixity to operator in an */ +Int line; /* infix expression */ +Cell op; { + Syntax sy = DEF_OPSYNTAX; + + switch (whatIs(op)) { + case VAROPCELL : + case VARIDCELL : if ((sy=lookupSyntax(textOf(op)))==NO_SYNTAX) { + Name n = findName(textOf(op)); + if (isNull(n)) { + ERRMSG(line) "Undefined variable \"%s\"", + textToStr(textOf(op)) + EEND; + } + sy = syntaxOf(n); + op = n; + } + break; + + case CONOPCELL : + case CONIDCELL : sy = syntaxOf(op = conDefined(line,op)); + break; + + case QUALIDENT : { Name n = findQualName(op); + if (nonNull(n)) { + op = n; + sy = syntaxOf(n); + } else { + ERRMSG(line) + "Undefined qualified variable \"%s\"", + identToStr(op) + EEND; + } + } + break; + } + if (sy==APPLIC) { + sy = DEF_OPSYNTAX; + } + return pair(mkInt(sy),op); /* Pair fixity with (possibly) */ + /* translated operator */ +} + +static Syntax local lookupSyntax(t) /* Try to find fixity for var in */ +Text t; { /* enclosing bindings */ + List bounds1 = bounds; + List bindings1 = bindings; + + while (nonNull(bindings1)) { + if (nonNull(varIsMember(t,hd(bounds1)))) { + return DEF_OPSYNTAX; + } else { + Cell b = findBinding(t,hd(bindings1)); + if (nonNull(b)) { + Cell a = fst(snd(b)); + if (isVar(fst(b))) { /* Function binding */ + if (nonNull(a) && nonNull(snd(a))) { + return intOf(snd(a)); + } + } else { /* Pattern binding */ + List vs = fst(b); + while (nonNull(vs) && nonNull(a)) { + if (t==textOf(hd(vs))) { + if (nonNull(hd(a)) && isInt(snd(hd(a)))) { + return intOf(snd(hd(a))); + } + break; + } + vs = tl(vs); + a = tl(a); + } + } + return DEF_OPSYNTAX; + } + } + bounds1 = tl(bounds1); + bindings1 = tl(bindings1); + } + return NO_SYNTAX; +} + /* -------------------------------------------------------------------------- * To facilitate dependency analysis, lists of bindings are temporarily * augmented with an additional field, which is used in two ways: @@ -2919,76 +4080,113 @@ List bs; { * Using this extra field, the type of each list of declarations during * dependency analysis is [Binding'] where: * - * Binding' ::= (Var, (Dep, (Type, [Alt]))) -- function binding - * | ([Var], (Dep, ([Type], (Pat,Rhs)))) -- pattern binding + * Binding' ::= (Var, (Attr, (Dep, [Alt]))) -- function binding + * | ([Var], ([Attr], (Dep, (Pat,Rhs)))) -- pattern binding * * ------------------------------------------------------------------------*/ -#define depVal(d) (fst(snd(d))) /* Access to dependency information*/ - +#define depVal(d) (fst(snd(snd(d)))) /* Access to dependency information*/ + static List local dependencyAnal(bs) /* Separate lists of bindings into */ List bs; { /* mutually recursive groups in */ - /* order of dependency */ - mapProc(addDepField,bs); /* add extra field for dependents */ mapProc(depBinding,bs); /* find dependents of each binding */ bs = bscc(bs); /* sort to strongly connected comps*/ mapProc(remDepField,bs); /* remove dependency info field */ - return bs; -} - + return bs; +} + static List local topDependAnal(bs) /* Like dependencyAnal(), but at */ List bs; { /* top level, reporting on progress*/ - List xs; - Int i = 0; - - setGoal("Dependency analysis",(Target)(length(bs))); - mapProc(addDepField,bs); /* add extra field for dependents */ - for (xs=bs; nonNull(xs); xs=tl(xs)) { - emptySubstitution(); - depBinding(hd(xs)); - soFar((Target)(i++)); - } - bs = bscc(bs); /* sort to strongly connected comps*/ - mapProc(remDepField,bs); /* remove dependency info field */ - done(); - return bs; -} - -static Void local addDepField(b) /* add extra field to binding to */ -Cell b; { /* hold list of dependents */ - snd(b) = pair(NIL,snd(b)); -} - -static Void local remDepField(bs) /* remove dependency field from */ -List bs; { /* list of bindings */ - mapProc(remDepField1,bs); -} - -static Void local remDepField1(b) /* remove dependency field from */ -Cell b; { /* single binding */ - snd(b) = snd(snd(b)); -} - -static Void local clearScope() { /* initialise dependency scoping */ - bounds = NIL; - bindings = NIL; - depends = NIL; -} - -static Void local withinScope(bs) /* enter scope of bindings bs */ -List bs; { - bounds = cons(NIL,bounds); - bindings = cons(bs,bindings); - depends = cons(NIL,depends); -} - -static Void local leaveScope() { /* leave scope of last withinScope */ + List xs; + Int i = 0; + + setGoal("Dependency analysis",(Target)(length(bs))); + mapProc(addDepField,bs); /* add extra field for dependents */ + for (xs=bs; nonNull(xs); xs=tl(xs)) { + emptySubstitution(); + depBinding(hd(xs)); + soFar((Target)(i++)); + } + bs = bscc(bs); /* sort to strongly connected comps */ + mapProc(remDepField,bs); /* remove dependency info field */ + done(); + return bs; +} + +static Void local addDepField(b) /* add extra field to binding to */ +Cell b; { /* hold list of dependents */ + snd(snd(b)) = pair(NIL,snd(snd(b))); +} + +static Void local remDepField(bs) /* remove dependency field from */ +List bs; { /* list of bindings */ + mapProc(remDepField1,bs); +} + +static Void local remDepField1(b) /* remove dependency field from */ +Cell b; { /* single binding */ + snd(snd(b)) = snd(snd(snd(b))); +} + +static Void local clearScope() { /* initialise dependency scoping */ + bounds = NIL; + bindings = NIL; + depends = NIL; +} + +static Void local withinScope(bs) /* Enter scope of bindings bs */ +List bs; { + bounds = cons(NIL,bounds); + bindings = cons(bs,bindings); + depends = cons(NIL,depends); +} + +static Void local leaveScope() { /* Leave scope of last withinScope */ + List bs = hd(bindings); /* Remove fixity info from binds */ + Bool toplevel = isNull(tl(bindings)); + for (; nonNull(bs); bs=tl(bs)) { + Cell b = hd(bs); + if (isVar(fst(b))) { /* Variable binding */ + Cell a = fst(snd(b)); + if (isPair(a)) { + if (toplevel) { + saveSyntax(fst(b),snd(a)); + } + fst(snd(b)) = fst(a); + } + } else { /* Pattern binding */ + List vs = fst(b); + List as = fst(snd(b)); + while (nonNull(vs) && nonNull(as)) { + if (isPair(hd(as))) { + if (toplevel) { + saveSyntax(hd(vs),snd(hd(as))); + } + hd(as) = fst(hd(as)); + } + vs = tl(vs); + as = tl(as); + } + } + } bounds = tl(bounds); bindings = tl(bindings); depends = tl(depends); } +static Void local saveSyntax(v,sy) /* Save syntax of top-level var */ +Cell v; /* in corresponding Name */ +Cell sy; { + Name n = findName(textOf(v)); + if (isNull(n) || name(n).syntax!=NO_SYNTAX) { + internal("saveSyntax"); + } + if (nonNull(sy)) { + name(n).syntax = intOf(sy); + } +} + /* -------------------------------------------------------------------------- * As a side effect of the dependency analysis we also make the following * checks: @@ -3003,38 +4201,52 @@ static Void local leaveScope() { /* leave scope of last withinScope */ * - No free (i.e. unbound) variables are used in the declaration list. * ------------------------------------------------------------------------*/ -static Void local depBinding(b) /* find dependents of binding */ +static Void local depBinding(b) /* find dependents of binding */ Cell b; { - Cell defpart = snd(snd(snd(b))); /* definition part of binding */ + Cell defpart = snd(snd(snd(b))); /* definition part of binding */ hd(depends) = NIL; - if (isVar(fst(b))) { /* function-binding? */ + if (isVar(fst(b))) { /* function-binding? */ mapProc(depAlt,defpart); - if (isNull(fst(snd(snd(b))))) { /* Save dep info for implicitly */ - fst(snd(snd(b))) = ap(IMPDEPS,hd(depends)); /* typed var binds */ + if (isNull(fst(snd(b)))) { /* Save dep info if no type sig */ + fst(snd(b)) = pair(ap(IMPDEPS,hd(depends)),NIL); + } else if (isNull(fst(fst(snd(b))))) { + fst(fst(snd(b))) = ap(IMPDEPS,hd(depends)); } - } else { /* pattern-binding? */ + } else { /* pattern-binding? */ + Int line = rhsLine(snd(defpart)); + enterBtyvs(); + patVars = NIL; + fst(defpart) = checkPat(line,fst(defpart)); depRhs(snd(defpart)); +#if 0 + if (nonNull(hd(btyvars))) { + ERRMSG(line) + "Sorry, no type variables are allowed in pattern binding type annotations" + EEND; + } +#endif + fst(defpart) = applyBtyvs(fst(defpart)); } depVal(b) = hd(depends); } -static Void local depDefaults(c) /* dependency analysis on defaults */ -Class c; { /* from class definition */ +static Void local depDefaults(c) /* dependency analysis on defaults */ +Class c; { /* from class definition */ depClassBindings(cclass(c).defaults); } -static Void local depInsts(in) /* dependency analysis on instance */ -Inst in; { /* bindings */ +static Void local depInsts(in) /* dependency analysis on instance */ +Inst in; { /* bindings */ depClassBindings(inst(in).implements); } -static Void local depClassBindings(bs) /* dependency analysis on list of */ -List bs; { /* bindings, possibly containing */ - for (; nonNull(bs); bs=tl(bs)) { /* NIL bindings ... */ - if (nonNull(hd(bs))) { /* No need to add extra field for */ - mapProc(depAlt,snd(hd(bs))); /* dependency information ... */ +static Void local depClassBindings(bs) /* dependency analysis on list of */ +List bs; { /* bindings, possibly containing */ + for (; nonNull(bs); bs=tl(bs)) { /* NIL bindings ... */ + if (nonNull(hd(bs))) { /* No need to add extra field for */ + mapProc(depAlt,snd(hd(bs)));/* dependency information... */ } } } @@ -3055,7 +4267,7 @@ Cell r; { case GUARDED : mapProc(depGuard,snd(r)); break; - case LETREC : fst(snd(r)) = eqnsToBindings(fst(snd(r))); + case LETREC : fst(snd(r)) = eqnsToBindings(fst(snd(r)),NIL,NIL,NIL); withinScope(fst(snd(r))); fst(snd(r)) = dependencyAnal(fst(snd(r))); hd(depends) = fst(snd(r)); @@ -3063,17 +4275,24 @@ Cell r; { leaveScope(); break; + case RSIGN : snd(snd(r)) = checkPatType(rhsLine(fst(snd(r))), + "result", + rhsExpr(fst(snd(r))), + snd(snd(r))); + depRhs(fst(snd(r))); + break; + default : snd(r) = depExpr(intOf(fst(r)),snd(r)); break; } } -static Void local depGuard(g) /*find dependents of single guarded*/ -Cell g; { /* expression */ +static Void local depGuard(g) /* find dependents of single guarded*/ +Cell g; { /* expression */ depPair(intOf(fst(g)),snd(g)); } -static Cell local depExpr(line,e) /* find dependents of expression */ +static Cell local depExpr(line,e) /* find dependents of expression */ Int line; Cell e; { switch (whatIs(e)) { @@ -3090,6 +4309,8 @@ Cell e; { return conDefined(line,e); } + case INFIX : return depExpr(line,tidyInfix(line,snd(e))); + #if TREX case RECSEL : break; @@ -3111,13 +4332,17 @@ Cell e; { break; #endif +#if BIGNUMS + case ZERONUM : + case POSNUM : + case NEGNUM : +#endif case NAME : case TUPLE : case STRCELL : case CHARCELL : - case INTCELL : - case BIGCELL : - case FLOATCELL : break; + case FLOATCELL : + case INTCELL : break; case COND : depTriple(line,snd(e)); break; @@ -3125,7 +4350,7 @@ Cell e; { case FINLIST : map1Over(depExpr,line,snd(e)); break; - case LETREC : fst(snd(e)) = eqnsToBindings(fst(snd(e))); + case LETREC : fst(snd(e)) = eqnsToBindings(fst(snd(e)),NIL,NIL,NIL); withinScope(fst(snd(e))); fst(snd(e)) = dependencyAnal(fst(snd(e))); hd(depends) = fst(snd(e)); @@ -3171,7 +4396,7 @@ Cell e; { EEND; #endif - default : internal("in depExpr"); + default : internal("depExpr"); } return e; } @@ -3195,9 +4420,9 @@ static Void local depComp(l,e,qs) /* find dependents of comprehension*/ Int l; Cell e; List qs; { - if (isNull(qs)) + if (isNull(qs)) { fst(e) = depExpr(l,fst(e)); - else { + } else { Cell q = hd(qs); List qs1 = tl(qs); switch (whatIs(q)) { @@ -3211,7 +4436,7 @@ List qs; { } break; - case QWHERE : snd(q) = eqnsToBindings(snd(q)); + case QWHERE : snd(q) = eqnsToBindings(snd(q),NIL,NIL,NIL); withinScope(snd(q)); snd(q) = dependencyAnal(snd(q)); hd(depends) = snd(q); @@ -3254,8 +4479,9 @@ Cell e; { } n = findBinding(t,hd(bindings1)); /* look for t in var bindings */ if (nonNull(n)) { - if (!cellIsMember(n,hd(depends1))) - hd(depends1) = cons(n,hd(depends1)); + if (!cellIsMember(n,hd(depends1))) { + hd(depends1) = cons(n,hd(depends1)); + } return (isVar(fst(n)) ? fst(n) : e); } @@ -3269,27 +4495,31 @@ Cell e; { EEND; } - if (name(n).mod != thisModule) { +#if !IGNORE_MODULES + if (!moduleThisScript(name(n).mod)) { return n; } +#endif /* Later phases of the system cannot cope if we resolve references * to unprocessed objects too early. This is the main reason that * we cannot cope with recursive modules at the moment. */ - return n; + return e; } static Cell local depQVar(line,e)/* register occurrence of qualified variable */ Int line; Cell e; { - Cell n = findQualName(line,e); + Name n = findQualName(e); if (isNull(n)) { /* check global definitions */ ERRMSG(line) "Undefined qualified variable \"%s\"", identToStr(e) EEND; } +#if !IGNORE_MODULES if (name(n).mod != currentModule) { return n; } +#endif if (fst(e) == VARIDCELL) { e = mkVar(qtextOf(e)); } else { @@ -3316,7 +4546,7 @@ Bool isP; { if (!isP && isPair(name(c).defn)) { /* Check that banged fields defined*/ List scs = fst(name(c).defn); /* List of strict components */ Type t = name(c).type; - Int a = name(c).arity; + Int a = userArity(c); List fs = snd(snd(e)); List ss; if (isPolyType(t)) { /* Find tycon that c belongs to */ @@ -3325,6 +4555,9 @@ Bool isP; { if (whatIs(t)==QUAL) { t = snd(snd(t)); } + if (whatIs(t)==CDICTS) { + t = snd(snd(t)); + } while (0<a--) { t = arg(t); } @@ -3396,9 +4629,11 @@ Bool isP; { Name s; if (isVar(fb)) { /* expand var to var = var */ + h98DoesntSupport(l,"missing field bindings"); fb = hd(fs) = pair(fb,fb); } - s = findQualName(l,fst(fb)); /* check for selector */ + + s = findQualName(fst(fb)); /* check for selector */ if (nonNull(s) && isSfun(s)) { fst(fb) = s; } else { @@ -3409,8 +4644,9 @@ Bool isP; { if (isNull(ss)) { /* for first named selector */ List scs = name(s).defn; /* calculate list of constructors */ - for (; nonNull(scs); scs=tl(scs)) + for (; nonNull(scs); scs=tl(scs)) { cs = cons(fst(hd(scs)),cs); + } ss = singleton(s); /* initialize selector list */ } else { /* for subsequent selectors */ List ds = cs; /* intersect constructor lists */ @@ -3456,6 +4692,7 @@ Cell e; { /* to make construction and update */ List exts = NIL; /* more efficient. */ Cell r = e; + h98DoesntSupport(line,"extensible records"); do { /* build up list of extensions */ Text t = extText(fun(fun(r))); String s = textToStr(t); @@ -3484,6 +4721,7 @@ Cell e; { /* to make construction and update */ } #endif + /* -------------------------------------------------------------------------- * Several parts of this program require an algorithm for sorting a list * of values (with some added dependency information) into a list of strongly @@ -3496,7 +4734,7 @@ Cell e; { /* to make construction and update */ #define SCC2 tcscc /* make scc algorithm for Tycons */ #define LOWLINK tclowlink #define DEPENDS(c) (isTycon(c) ? tycon(c).kind : cclass(c).kinds) -#define SETDEPENDS(c,v) if(isTycon(c))tycon(c).kind=v;else cclass(c).kinds=v +#define SETDEPENDS(c,v) if(isTycon(c)) tycon(c).kind=v; else cclass(c).kinds=v #include "scc.c" #undef SETDEPENDS #undef DEPENDS @@ -3527,79 +4765,79 @@ Void checkExp() { /* Top level static check on Expr */ } Void checkDefns() { /* Top level static analysis */ +#if !IGNORE_MODULES + Module thisModule = lastModule(); +#endif staticAnalysis(RESET); - thisModule = lastModule(); + +#if !IGNORE_MODULES setCurrModule(thisModule); /* Resolve module references */ mapProc(checkQualImport, module(thisModule).qualImports); mapProc(checkUnqualImport,unqualImports); - - /* Add implicit import declarations - if Prelude has been loaded */ - { - Module modulePrelude = findModule(findText("Prelude")); - if (nonNull(modulePrelude)) { - /* Add "import Prelude" if there`s no explicit import */ - if (thisModule != modulePrelude - && isNull(cellAssoc(modulePrelude,unqualImports)) - && isNull(cellRevAssoc(modulePrelude,module(thisModule).qualImports))) { - unqualImports = cons(pair(modulePrelude,DOTDOT),unqualImports); - } - /* Add "import qualified Prelude" */ - module(thisModule).qualImports=cons(pair(conPrelude,modulePrelude), - module(thisModule).qualImports); - } + /* Add "import Prelude" if there`s no explicit import */ + if (thisModule!=modulePrelude + && isNull(cellAssoc(modulePrelude,unqualImports)) + && isNull(cellRevAssoc(modulePrelude,module(thisModule).qualImports))) { + unqualImports = cons(pair(modulePrelude,DOTDOT),unqualImports); + } else { + /* Every module (including the Prelude) implicitly contains + * "import qualified Prelude" + */ + module(thisModule).qualImports=cons(pair(mkCon(textPrelude),modulePrelude), + module(thisModule).qualImports); } - map1Proc(checkImportList, thisModule, unqualImports); + mapProc(checkImportList, unqualImports); +#endif linkPreludeTC(); /* Get prelude tycons and classes */ - setCurrModule(thisModule); - mapProc(checkTyconDefn,tyconDefns); /* validate tycon definitions */ checkSynonyms(tyconDefns); /* check synonym definitions */ mapProc(checkClassDefn,classDefns); /* process class definitions */ mapProc(kindTCGroup,tcscc(tyconDefns,classDefns)); /* attach kinds */ mapProc(addMembers,classDefns); /* add definitions for member funs */ mapProc(visitClass,classDefns); /* check class hierarchy */ + linkPreludeCM(); /* Get prelude cfuns and mfuns */ + /* ToDo: reinstate? + mapOver(checkPrimDefn,primDefns); */ /* check primitive declarations */ + instDefns = rev(instDefns); /* process instance definitions */ mapProc(checkInstDefn,instDefns); - linkPreludeCM(); /* Get prelude cfuns and mfuns */ setCurrModule(thisModule); - mapProc(addDerivImp,derivedInsts); /* Add impls for derived instances */ deriveContexts(derivedInsts); /* Calculate derived inst contexts */ #if EVAL_INSTANCES deriveEval(tyconDefns); /* Derive instances of Eval */ #endif - tyconDefns = NIL; instDefns = appendOnto(instDefns,derivedInsts); -#if EVAL_INSTANCES - instDefns = appendOnto(evalInsts,instDefns); /* ADR addition */ -#endif checkDefaultDefns(); /* validate default definitions */ mapProc(addRSsigdecls,typeInDefns); /* add sigdecls for RESTRICTSYN */ +#if 0 /* from STG */ valDefns = eqnsToBindings(valDefns);/* translate value equations */ map1Proc(opDefined,valDefns,opDefns);/*check all declared ops bound */ +#else /* from 98 */ + valDefns = eqnsToBindings(valDefns,tyconDefns,classDefns, NIL/*primDefns*/ ); + tyconDefns = NIL; + /* primDefns = NIL; */ +#endif mapProc(allNoPrevDef,valDefns); /* check against previous defns */ - linkPreludeNames(); /* Get prelude names */ - setCurrModule(thisModule); - - mapProc(checkForeignImport,foreignImports); /* check foreign imports */ - mapProc(checkForeignExport,foreignExports); /* check foreign exports */ + mapProc(checkForeignImport,foreignImports); /* check foreign imports */ + mapProc(checkForeignExport,foreignExports); /* check foreign exports */ foreignImports = NIL; foreignExports = NIL; +#if !IGNORE_MODULES /* Every top-level name has now been created - so we can build the */ /* export list. Note that this has to happen before dependency */ /* analysis so that references to Prelude.foo will be resolved */ /* when compiling the prelude. */ - /* Note too that this is just a little too late to catch the use of */ - /* qualified tycons (for the current module) in data declarations */ - module(thisModule).exports = checkExports(thisModule,module(thisModule).exports); + module(thisModule).exports = checkExports(module(thisModule).exports); +#endif mapProc(checkTypeIn,typeInDefns); /* check restricted synonym defns */ @@ -3627,21 +4865,8 @@ Pair pr; { } } -static Void local opDefined(bs,op) /* check that op bound in bs */ -List bs; /* (or in current module for */ -Cell op; { /* constructor functions etc...) */ - Name n; - - if (isNull(findBinding(textOf(op),bs)) - && (isNull(n=findName(textOf(op))) || name(n).mod != thisModule)) { - ERRMSG(0) "No top level definition for operator symbol \"%s\"", - textToStr(textOf(op)) - EEND; - } -} - -static Void local allNoPrevDef(b) /* ensure no previous bindings for */ -Cell b; { /* variables in new binding */ +static Void local allNoPrevDef(b) /* ensure no previous bindings for*/ +Cell b; { /* variables in new binding */ if (isVar(fst(b))) { noPrevDef(rhsLine(snd(hd(snd(snd(b))))),fst(b)); } else { @@ -3650,37 +4875,46 @@ Cell b; { /* variables in new binding */ } } -static Void local noPrevDef(line,v) /* ensure no previous binding for */ -Int line; /* new variable */ +static Void local noPrevDef(line,v) /* ensure no previous binding for */ +Int line; /* new variable */ Cell v; { Name n = findName(textOf(v)); if (isNull(n)) { - n = newName(textOf(v)); + n = newName(textOf(v),NIL); name(n).defn = PREDEFINED; } else if (name(n).defn!=PREDEFINED) { - ERRMSG(line) "Attempt to redefine variable \"%s\"", - textToStr(name(n).text) - EEND; + duplicateError(line,name(n).mod,name(n).text,"variable"); } name(n).line = line; } -static Void local duplicateError(line,mod,t,kind)/* report duplicate defn */ +#if IGNORE_MODULES +static Void local duplicateErrorAux(line,t,kind) /* report duplicate defn */ +Int line; +Text t; +String kind; { + ERRMSG(line) "Definition of %s \"%s\" clashes with import", kind, + textToStr(t) + EEND; +} +#else /* !IGNORE_MODULES */ +static Void local duplicateErrorAux(line,mod,t,kind)/* report duplicate defn */ Int line; Module mod; Text t; String kind; { if (mod == currentModule) { ERRMSG(line) "Repeated definition for %s \"%s\"", kind, - textToStr(t) + textToStr(t) EEND; } else { ERRMSG(line) "Definition of %s \"%s\" clashes with import", kind, - textToStr(t) + textToStr(t) EEND; } } +#endif /* !IGNORE_MODULES */ static Void local checkTypeIn(cvs) /* Check that vars in restricted */ Pair cvs; { /* synonym are defined */ @@ -3697,6 +4931,83 @@ Pair cvs; { /* synonym are defined */ } } +/* -------------------------------------------------------------------------- + * Haskell 98 compatibility tests: + * ------------------------------------------------------------------------*/ + +Bool h98Pred(allowArgs,pi) /* Check syntax of Hask98 predicate*/ +Bool allowArgs; +Cell pi; { + return isClass(getHead(pi)) && argCount==1 && + isOffset(getHead(arg(pi))) && (argCount==0 || allowArgs); +} + +Cell h98Context(allowArgs,ps) /* Check syntax of Hask98 context */ +Bool allowArgs; +List ps; { + for (; nonNull(ps); ps=tl(ps)) { + if (!h98Pred(allowArgs,hd(ps))) { + return hd(ps); + } + } + return NIL; +} + +Void h98CheckCtxt(line,wh,allowArgs,ps,in) +Int line; /* Report illegal context/predicate*/ +String wh; +Bool allowArgs; +List ps; +Inst in; { + if (haskell98) { + Cell pi = h98Context(allowArgs,ps); + if (nonNull(pi)) { + ERRMSG(line) "Illegal Haskell 98 class constraint in %s",wh ETHEN + if (nonNull(in)) { + ERRTEXT "\n*** Instance : " ETHEN ERRPRED(inst(in).head); + } + ERRTEXT "\n*** Constraint : " ETHEN ERRPRED(pi); + if (nonNull(ps) && nonNull(tl(ps))) { + ERRTEXT "\n*** Context : " ETHEN ERRCONTEXT(ps); + } + ERRTEXT "\n" + EEND; + } + } +} + +Void h98CheckType(line,wh,e,t) /* Check for Haskell 98 type */ +Int line; +String wh; +Cell e; +Type t; { + if (haskell98) { + Type ty = t; + if (isPolyType(t)) + t = monotypeOf(t); + if (whatIs(t)==QUAL) { + Cell pi = h98Context(TRUE,fst(snd(t))); + if (nonNull(pi)) { + ERRMSG(line) "Illegal Haskell 98 class constraint in %s",wh + ETHEN + ERRTEXT "\n*** Expression : " ETHEN ERREXPR(e); + ERRTEXT "\n*** Type : " ETHEN ERRTYPE(ty); + ERRTEXT "\n" + EEND; + } + } + } +} + +Void h98DoesntSupport(line,wh) /* Report feature missing in H98 */ +Int line; +String wh; { + if (haskell98) { + ERRMSG(line) "Haskell 98 does not support %s", wh + EEND; + } +} + /* -------------------------------------------------------------------------- * Static Analysis control: * ------------------------------------------------------------------------*/ @@ -3704,18 +5015,17 @@ Pair cvs; { /* synonym are defined */ Void staticAnalysis(what) Int what; { switch (what) { - case RESET : daSccs = NIL; + case RESET : cfunSfuns = NIL; + daSccs = NIL; patVars = NIL; bounds = NIL; bindings = NIL; depends = NIL; tcDeps = NIL; derivedInsts = NIL; -#if EVAL_INSTANCES - evalInsts = NIL; -#endif + diVars = NIL; + diNum = 0; unkindTypes = NIL; - thisModule = 0; break; case MARK : mark(daSccs); @@ -3725,9 +5035,8 @@ Int what; { mark(depends); mark(tcDeps); mark(derivedInsts); -#if EVAL_INSTANCES - mark(evalInsts); -#endif + mark(diVars); + mark(cfunSfuns); mark(unkindTypes); #if TREX mark(extKind); diff --git a/ghc/interpreter/stg.c b/ghc/interpreter/stg.c index 6b0029ff2884..032e01436c0e 100644 --- a/ghc/interpreter/stg.c +++ b/ghc/interpreter/stg.c @@ -1,4 +1,4 @@ -/* -*- mode: hugs-c; -*- */ + /* -------------------------------------------------------------------------- * STG syntax * @@ -7,15 +7,15 @@ * Hugs version 1.4, December 1997 * * $RCSfile: stg.c,v $ - * $Revision: 1.2 $ - * $Date: 1998/12/02 13:22:38 $ + * $Revision: 1.3 $ + * $Date: 1999/02/03 17:08:39 $ * ------------------------------------------------------------------------*/ #include "prelude.h" #include "storage.h" +#include "backend.h" #include "connect.h" #include "errors.h" -#include "stg.h" #include "link.h" /* for nameTrue/False */ #include "Assembler.h" /* for AsmRep and primops */ @@ -79,7 +79,7 @@ StgExpr makeStgLambda( List args, StgExpr body ) return body; } else { if (whatIs(body) == LAMBDA) { - return mkStgLambda(dupListOnto(args,stgLambdaArgs(body)), + return mkStgLambda(dupOnto(args,stgLambdaArgs(body)), stgLambdaBody(body)); } else { return mkStgLambda(args,body); @@ -150,3 +150,495 @@ StgVar mkStgVar( StgRhs rhs, Cell info ) } /*-------------------------------------------------------------------------*/ + +/* -------------------------------------------------------------------------- + * STG pretty printer + * + * Copyright (c) The University of Nottingham and Yale University, 1994-1997. + * All rights reserved. See NOTICE for details and conditions of use etc... + * Hugs version 1.4, December 1997 + * + * $RCSfile: stg.c,v $ + * $Revision: 1.3 $ + * $Date: 1999/02/03 17:08:39 $ + * ------------------------------------------------------------------------*/ + +/* -------------------------------------------------------------------------- + * Local functions + * ------------------------------------------------------------------------*/ + +static Void local pIndent Args((Int)); +static Void local unlexVar Args((Text)); +static Void local unlexCharConst Args((Cell)); +static Void local unlexStrConst Args((Text)); + +static Void local putStgVar Args((StgVar)); +static Void local putStgVars Args((List)); +static Void local putStgAtom Args((StgAtom a)); +static Void local putStgAtoms Args((List as)); +static Void local putStgBinds Args((List)); +static Void local putStgExpr Args((StgExpr)); +static Void local putStgRhs Args((StgRhs)); +static Void local putStgPat Args((StgPat)); +static Void local putStgPrimPat Args((StgPrimPat)); + +/* -------------------------------------------------------------------------- + * Basic output routines: + * ------------------------------------------------------------------------*/ + +static FILE *outputStream; /* current output stream */ +static Int outColumn = 0; /* current output column number */ + +static Void local putChr( Int c ); +static Void local putStr( String s ); +static Void local putInt( Int n ); +static Void local putPtr( Ptr p ); + +static Void local putChr(c) /* print single character */ +Int c; { + Putc(c,outputStream); + outColumn++; +} + +static Void local putStr(s) /* print string */ +String s; { + for (; *s; s++) { + Putc(*s,outputStream); + outColumn++; + } +} + +static Void local putInt(n) /* print integer */ +Int n; { + static char intBuf[16]; + sprintf(intBuf,"%d",n); + putStr(intBuf); +} + +static Void local putPtr(p) /* print pointer */ +Ptr p; { + static char intBuf[16]; + sprintf(intBuf,"%p",p); + putStr(intBuf); +} + +/* -------------------------------------------------------------------------- + * Indentation and showing names/constants + * ------------------------------------------------------------------------*/ + +static Void local pIndent(n) /* indent to particular position */ +Int n; { + outColumn = n; + while (0<n--) { + Putc(' ',outputStream); + } +} + +static Void local unlexVar(t) /* print text as a variable name */ +Text t; { /* operator symbols must be enclosed*/ + String s = textToStr(t); /* in parentheses... except [] ... */ + + if ((isascii(s[0]) && isalpha(s[0])) || s[0]=='_' || s[0]=='[' || s[0]=='(') + putStr(s); + else { + putChr('('); + putStr(s); + putChr(')'); + } +} + +static Void local unlexCharConst(c) +Cell c; { + putChr('\''); + putStr(unlexChar(c,'\'')); + putChr('\''); +} + +static Void local unlexStrConst(t) +Text t; { + String s = textToStr(t); + static Char SO = 14; /* ASCII code for '\SO' */ + Bool lastWasSO = FALSE; + Bool lastWasDigit = FALSE; + Bool lastWasEsc = FALSE; + + putChr('\"'); + for (; *s; s++) { + String ch = unlexChar(*s,'\"'); + Char c = ' '; + + if ((lastWasSO && *ch=='H') || + (lastWasEsc && lastWasDigit && isascii(*ch) && isdigit(*ch))) + putStr("\\&"); + + lastWasEsc = (*ch=='\\'); + lastWasSO = (*s==SO); + for (; *ch; c = *ch++) + putChr(*ch); + lastWasDigit = (isascii(c) && isdigit(c)); + } + putChr('\"'); +} + +/* -------------------------------------------------------------------------- + * Pretty printer for stg code: + * ------------------------------------------------------------------------*/ + +static Void putStgAlts ( Int left, List alts ); +static Void putStgPrimAlt ( Int left, List vs, StgExpr body ); + +static Void local putStgVar(StgVar v) +{ + if (isName(v)) { + unlexVar(name(v).text); + } else { + putStr("id"); + putInt(-v); + } +} + +static Void local putStgVars( List vs ) +{ + for(; nonNull(vs); vs=tl(vs)) { + putStgVar(hd(vs)); + putChr(' '); + } +} + +static Void local putStgAtom( StgAtom a ) +{ + switch (whatIs(a)) { + case STGVAR: + case NAME: + putStgVar(a); + break; + case CHARCELL: + unlexCharConst(charOf(a)); + putChr('#'); + break; + case INTCELL: + putInt(intOf(a)); + putChr('#'); + break; + case BIGCELL: + putStr(bignumToString(a)); + putChr('#'); + break; + case FLOATCELL: + putStr(floatToString(a)); + putChr('#'); + break; + case STRCELL: + unlexStrConst(textOf(a)); + break; + case PTRCELL: + putPtr(ptrOf(a)); + putChr('#'); + break; + default: + fprintf(stderr,"\nYoiks: "); printExp(stderr,a); + internal("putStgAtom"); + } +} + +Void putStgAtoms( List as ) +{ + putChr('{'); + while (nonNull(as)) { + putStgAtom(hd(as)); + as=tl(as); + if (nonNull(as)) { + putChr(','); + } + } + putChr('}'); +} + +Void putStgPat( StgPat pat ) +{ + putStgVar(pat); + if (nonNull(stgVarBody(pat))) { + StgDiscr d = stgConCon(stgVarBody(pat)); + List vs = stgConArgs(stgVarBody(pat)); + putChr('@'); + switch (whatIs(d)) { + case NAME: + { + unlexVar(name(d).text); + for (; nonNull(vs); vs=tl(vs)) { + putChr(' '); + putStgVar(hd(vs)); + } + break; + } + case TUPLE: + { + putChr('('); + putStgVar(hd(vs)); + vs=tl(vs); + while (nonNull(vs)) { + putChr(','); + putStgVar(hd(vs)); + vs=tl(vs); + } + putChr(')'); + break; + } + default: + fprintf(stderr,"\nYoiks: "); printExp(stderr,d); + internal("putStgPat"); + } + } +} + +Void putStgPrimPat( StgPrimPat pat ) +{ + putStgVar(pat); + if (nonNull(stgVarBody(pat))) { + StgExpr d = stgVarBody(pat); + putChr('@'); + switch (whatIs(d)) { + case INTCELL: + { + putInt(intOf(d)); + putChr('#'); + break; + } + default: + fprintf(stderr,"\nYoiks: "); printExp(stderr,d); + internal("putStgPrimPat"); + } + } + putChr(' '); +} + +Void putStgBinds(binds) /* pretty print locals */ +List binds; { + Int left = outColumn; + + putStr("let { "); + while (nonNull(binds)) { + Cell bind = hd(binds); + putStgVar(bind); + putStr(" = "); + putStgRhs(stgVarBody(bind)); + putStr("\n"); + binds = tl(binds); + if (nonNull(binds)) + pIndent(left+6); + } + pIndent(left); + putStr("} in "); +} + +static Void putStgAlts( Int left, List alts ) +{ + if (length(alts) == 1) { + StgCaseAlt alt = hd(alts); + putStr("{ "); + putStgPat(stgCaseAltPat(alt)); + putStr(" ->\n"); + pIndent(left); + putStgExpr(stgCaseAltBody(alt)); + putStr("}"); + } else { + putStr("{\n"); + for (; nonNull(alts); alts=tl(alts)) { + StgCaseAlt alt = hd(alts); + pIndent(left+2); + putStgPat(stgCaseAltPat(alt)); + putStr(" -> "); + putStgExpr(stgCaseAltBody(alt)); + putStr("\n"); + } + pIndent(left); + putStr("}\n"); + } +} + +static Void putStgPrimAlts( Int left, List alts ) +{ + if (length(alts) == 1) { + StgPrimAlt alt = hd(alts); + putStr("{ "); + mapProc(putStgPrimPat,stgPrimAltPats(alt)); + putStr(" ->\n"); + pIndent(left); + putStgExpr(stgPrimAltBody(alt)); + putStr("}"); + } else { + putStr("{\n"); + for (; nonNull(alts); alts=tl(alts)) { + StgPrimAlt alt = hd(alts); + pIndent(left+2); + mapProc(putStgPrimPat,stgPrimAltPats(alt)); + putStr(" -> "); + putStgExpr(stgPrimAltBody(alt)); + putStr("\n"); + } + pIndent(left); + putStr("}\n"); + } +} + +Void putStgExpr( StgExpr e ) /* pretty print expr */ +{ + switch (whatIs(e)) { + case LETREC: + putStgBinds(stgLetBinds(e)); + putStgExpr(stgLetBody(e)); + break; + case LAMBDA: + { + Int left = outColumn; + putStr("\\ "); + putStgVars(stgLambdaArgs(e)); + putStr("->\n"); + pIndent(left+2); + putStgExpr(stgLambdaBody(e)); + break; + } + case CASE: + { + Int left = outColumn; + putStr("case "); + putStgExpr(stgCaseScrut(e)); + putStr(" of "); + putStgAlts(left,stgCaseAlts(e)); + break; + } + case PRIMCASE: + { + Int left = outColumn; + putStr("case# "); + putStgExpr(stgPrimCaseScrut(e)); + putStr(" of "); + putStgPrimAlts(left,stgPrimCaseAlts(e)); + break; + } + case STGPRIM: + { + Cell op = stgPrimOp(e); + unlexVar(name(op).text); + putStgAtoms(stgPrimArgs(e)); + break; + } + case STGAPP: + putStgVar(stgAppFun(e)); + putStgAtoms(stgAppArgs(e)); + break; + case STGVAR: + case NAME: + putStgVar(e); + break; + default: + fprintf(stderr,"\nYoiks: "); printExp(stderr,e); + internal("putStgExpr"); + } +} + +Void putStgRhs( StgRhs e ) /* print lifted definition */ +{ + switch (whatIs(e)) { + case STGCON: + { + Name con = stgConCon(e); + if (isTuple(con)) { + putStr("Tuple"); + putInt(tupleOf(con)); + } else { + unlexVar(name(con).text); + } + putStgAtoms(stgConArgs(e)); + break; + } + default: + putStgExpr(e); + break; + } +} + +static void beginStgPP( FILE* fp ); +static void endStgPP( FILE* fp ); + +static void beginStgPP( FILE* fp ) +{ + outputStream = fp; + putChr('\n'); + outColumn = 0; +} + +static void endStgPP( FILE* fp ) +{ + fflush(fp); +} + +Void printStg(fp,b) /* Pretty print sc defn on fp */ +FILE *fp; +StgVar b; +{ + beginStgPP(fp); + putStgVar(b); + putStr(" = "); + putStgRhs(stgVarBody(b)); + putStr("\n"); + endStgPP(fp); +} + +#if DEBUG_PRINTER +Void ppStg( StgVar v ) +{ + if (debugCode) { + printStg(stdout,v); + } +} + +Void ppStgExpr( StgExpr e ) +{ + if (debugCode) { + beginStgPP(stdout); + putStgExpr(e); + endStgPP(stdout); + } +} + +Void ppStgRhs( StgRhs rhs ) +{ + if (debugCode) { + beginStgPP(stdout); + putStgRhs(rhs); + endStgPP(stdout); + } +} + +Void ppStgAlts( List alts ) +{ + if (debugCode) { + beginStgPP(stdout); + putStgAlts(0,alts); + endStgPP(stdout); + } +} + +extern Void ppStgPrimAlts( List alts ) +{ + if (debugCode) { + beginStgPP(stdout); + putStgPrimAlts(0,alts); + endStgPP(stdout); + } +} + +extern Void ppStgVars( List vs ) +{ + if (debugCode) { + beginStgPP(stdout); + printf("Vars: "); + putStgVars(vs); + printf("\n"); + endStgPP(stdout); + } +} +#endif + +/*-------------------------------------------------------------------------*/ diff --git a/ghc/interpreter/stgSubst.c b/ghc/interpreter/stgSubst.c index ccf0512ce668..7b3d9786a356 100644 --- a/ghc/interpreter/stgSubst.c +++ b/ghc/interpreter/stgSubst.c @@ -1,4 +1,4 @@ -/* -*- mode: hugs-c; -*- */ + /* -------------------------------------------------------------------------- * Substitute variables in an expression * @@ -7,17 +7,15 @@ * Hugs version 1.4, December 1997 * * $RCSfile: stgSubst.c,v $ - * $Revision: 1.2 $ - * $Date: 1998/12/02 13:22:40 $ + * $Revision: 1.3 $ + * $Date: 1999/02/03 17:08:40 $ * ------------------------------------------------------------------------*/ #include "prelude.h" #include "storage.h" +#include "backend.h" #include "connect.h" #include "errors.h" -#include "stg.h" - -#include "stgSubst.h" /* -------------------------------------------------------------------------- * Local function prototypes: diff --git a/ghc/interpreter/storage.c b/ghc/interpreter/storage.c index e88c53e14fc3..4f84aa1181d8 100644 --- a/ghc/interpreter/storage.c +++ b/ghc/interpreter/storage.c @@ -1,26 +1,24 @@ -/* -*- mode: hugs-c; -*- */ + /* -------------------------------------------------------------------------- * Primitives for manipulating global data structures * - * Copyright (c) The University of Nottingham and Yale University, 1994-1997. - * All rights reserved. See NOTICE for details and conditions of use etc... - * Hugs version 1.4, December 1997 + * Hugs 98 is Copyright (c) Mark P Jones, Alastair Reid and the Yale + * Haskell Group 1994-99, and is distributed as Open Source software + * under the Artistic License; see the file "Artistic" that is included + * in the distribution for details. * * $RCSfile: storage.c,v $ - * $Revision: 1.2 $ - * $Date: 1998/12/02 13:22:41 $ + * $Revision: 1.3 $ + * $Date: 1999/02/03 17:08:40 $ * ------------------------------------------------------------------------*/ #include "prelude.h" #include "storage.h" +#include "backend.h" #include "connect.h" -#include "charset.h" #include "errors.h" -#include "link.h" /* for nameCons */ #include <setjmp.h> -#include "machdep.h" /* gc-related functions */ - /*#define DEBUG_SHOWUSE*/ /* -------------------------------------------------------------------------- @@ -29,7 +27,9 @@ static Int local hash Args((String)); static Int local saveText Args((Text)); +#if !IGNORE_MODULES static Module local findQualifier Args((Text)); +#endif static Void local hashTycon Args((Tycon)); static List local insertTycon Args((Tycon,List)); static Void local hashName Args((Name)); @@ -39,11 +39,21 @@ static Bool local stringMatch Args((String,String)); static Bool local typeInvolves Args((Type,Type)); static Cell local markCell Args((Cell)); static Void local markSnd Args((Cell)); +static Cell local indirectChain Args((Cell)); +static Bool local isMarked Args((Cell)); static Cell local lowLevelLastIn Args((Cell)); static Cell local lowLevelLastOut Args((Cell)); -static Module local moduleOfScript Args((Script)); -static Script local scriptThisFile Args((Text)); - +/* from STG */ + Module local moduleOfScript Args((Script)); + Script local scriptThisFile Args((Text)); +/* from 98 */ +#if IO_HANDLES +static Void local freeHandle Args((Int)); +#endif +#if GC_STABLEPTRS +static Void local resetStablePtrs Args((Void)); +#endif +/* end */ /* -------------------------------------------------------------------------- * Text storage: @@ -95,34 +105,33 @@ Text t; { String identToStr(v) /*find string corresp to given ident or qualified name*/ Cell v; { - static char newVar[33]; - - assert(isPair(v)); - switch (fst(v)) { - case VARIDCELL : - case VAROPCELL : - case CONIDCELL : - case CONOPCELL : return text+textOf(v); - - case QUALIDENT : sprintf(newVar,"%s.%s", - text+qmodOf(v),text+qtextOf(v)); - return newVar; + if (!isPair(v)) { + internal("identToStr"); } - internal("identToStr 2"); -} - -Syntax identSyntax(v) /* find syntax of ident or qualified ident */ -Cell v; { - assert(isPair(v)); switch (fst(v)) { case VARIDCELL : case VAROPCELL : case CONIDCELL : - case CONOPCELL : return syntaxOf(textOf(v)); + case CONOPCELL : return text+textOf(v); - case QUALIDENT : return syntaxOf(qtextOf(v)); - } - internal("identSyntax 2"); + case QUALIDENT : { Text pos = textHw; + Text t = qmodOf(v); + while (pos+1 < savedText && text[t]!=0) { + text[pos++] = text[t++]; + } + if (pos+1 < savedText) { + text[pos++] = '.'; + } + t = qtextOf(v); + while (pos+1 < savedText && text[t]!=0) { + text[pos++] = text[t++]; + } + text[pos] = '\0'; + return text+textHw; + } + } + internal("identToStr2"); + assert(0); return 0; /* NOTREACHED */ } Text inventText() { /* return new unused variable name */ @@ -210,61 +219,6 @@ Text t; { /* at top of text table */ return savedText; } -/* -------------------------------------------------------------------------- - * Syntax storage: - * - * Operator declarations are stored in a table which associates Text values - * with Syntax values. - * ------------------------------------------------------------------------*/ - -static Int syntaxHw; /* next unused syntax table entry */ -static struct strSyntax { /* table of Text <-> Syntax values */ - Text text; - Syntax syntax; -} DEFTABLE(tabSyntax,NUM_SYNTAX); - -Syntax defaultSyntax(t) /* Find default syntax of var named */ -Text t; { /* by t ... */ - String s = textToStr(t); - return isIn(s[0],SYMBOL) ? DEF_OPSYNTAX : APPLIC; -} - -Syntax syntaxOf(t) /* look up syntax of operator symbol*/ -Text t; { - int i; - - for (i=0; i<syntaxHw; ++i) - if (tabSyntax[i].text==t) - return tabSyntax[i].syntax; - return defaultSyntax(t); -} - -Void addSyntax(line,t,sy) /* add (t,sy) to syntax table */ -Int line; -Text t; -Syntax sy; { - int i; - - for (i=0; i<syntaxHw; ++i) - if (tabSyntax[i].text==t) { - /* There's no problem with multiple identical fixity declarations. - * - but note that it's not allowed by the Haskell report. ADR - */ - if (tabSyntax[i].syntax == sy) return; - ERRMSG(line) "Attempt to redefine syntax of operator \"%s\"", - textToStr(t) - EEND; - } - - if (syntaxHw>=NUM_SYNTAX) { - ERRMSG(line) "Too many fixity declarations" - EEND; - } - - tabSyntax[syntaxHw].text = t; - tabSyntax[syntaxHw].syntax = sy; - syntaxHw++; -} /* -------------------------------------------------------------------------- * Ext storage: @@ -324,10 +278,10 @@ Text t; { tycon(tyconHw).kind = NIL; tycon(tyconHw).defn = NIL; tycon(tyconHw).what = NIL; - tycon(tyconHw).conToTag = NIL; - tycon(tyconHw).tagToCon = NIL; +#if !IGNORE_MODULES tycon(tyconHw).mod = currentModule; module(currentModule).tycons = cons(tyconHw,module(currentModule).tycons); +#endif tycon(tyconHw).nextTyconHash = tyconHash[h]; tyconHash[h] = tyconHw; @@ -348,7 +302,9 @@ Tycon tc; { Tycon oldtc = findTycon(tycon(tc).text); if (isNull(oldtc)) { hashTycon(tc); +#if !IGNORE_MODULES module(currentModule).tycons=cons(tc,module(currentModule).tycons); +#endif return tc; } else return oldtc; @@ -364,41 +320,38 @@ Tycon tc; { Tycon findQualTycon(id) /*locate (possibly qualified) Tycon in tycon table */ Cell id; { - assert(isPair(id)); + if (!isPair(id)) internal("findQualTycon"); switch (fst(id)) { case CONIDCELL : case CONOPCELL : return findTycon(textOf(id)); case QUALIDENT : { +#if IGNORE_MODULES + return findTycon(qtextOf(id)); +#else /* !IGNORE_MODULES */ Text t = qtextOf(id); Module m = findQualifier(qmodOf(id)); List es = NIL; - if (isNull(m)) - return NIL; - if (m==currentModule) { - /* The Haskell report (rightly) forbids this. - * We added it to let the Prelude refer to itself - * without having to import itself. - */ - return findTycon(t); - } + if (isNull(m)) return NIL; for(es=module(m).exports; nonNull(es); es=tl(es)) { Cell e = hd(es); if (isPair(e) && isTycon(fst(e)) && tycon(fst(e)).text==t) return fst(e); } return NIL; +#endif /* !IGNORE_MODULES */ } default : internal("findQualTycon2"); } + assert(0); return 0; /* NOTREACHED */ } Tycon addPrimTycon(t,kind,ar,what,defn) /* add new primitive type constr */ -Text t; -Kind kind; -Int ar; -Cell what; -Cell defn; { +Text t; +Kind kind; +Int ar; +Cell what; +Cell defn; { Tycon tc = newTycon(t); tycon(tc).line = 0; tycon(tc).kind = kind; @@ -455,18 +408,23 @@ List ts; { /* Null pattern matches every tycon*/ #define NAMEHSZ 256 /* Size of Name hash table */ #define nHash(x) ((x)%NAMEHSZ) /* hash fn :: Text->Int */ -/*static*/Name nameHw; /* next unused name */ +static Name nameHw; /* next unused name */ static Name DEFTABLE(nameHash,NAMEHSZ); /* Hash table storage */ struct strName DEFTABLE(tabName,NUM_NAME); /* Name table storage */ -Name newName(t) /* add new name to name table */ -Text t; { +Name newName(t,parent) /* Add new name to name table */ +Text t; +Cell parent; { + Int h = nHash(t); + if (nameHw-NAMEMIN >= NUM_NAME) { ERRMSG(0) "Name storage space exhausted" EEND; } name(nameHw).text = t; /* clear new name record */ name(nameHw).line = 0; + name(nameHw).syntax = NO_SYNTAX; + name(nameHw).parent = parent; name(nameHw).arity = 0; name(nameHw).number = EXECNAME; name(nameHw).defn = NIL; @@ -476,10 +434,12 @@ Text t; { name(nameHw).mod = currentModule; hashName(nameHw); module(currentModule).names=cons(nameHw,module(currentModule).names); + name(nameHw).nextNameHash = nameHash[h]; + nameHash[h] = nameHw; return nameHw++; } -Name findName(t) /* locate name in name table */ +Name findName(t) /* Locate name in name table */ Text t; { Name n = nameHash[nHash(t)]; @@ -490,30 +450,31 @@ Text t; { return n; } -Name addName(nm) /* Insert Name in name table - if no clash is caused */ -Name nm; { +Name addName(nm) /* Insert Name in name table - if */ +Name nm; { /* no clash is caused */ Name oldnm = findName(name(nm).text); if (isNull(oldnm)) { hashName(nm); +#if !IGNORE_MODULES module(currentModule).names=cons(nm,module(currentModule).names); +#endif return nm; - } else { + } else return oldnm; - } } -static Void local hashName(nm) /* Insert Name into hash table */ +static Void local hashName(nm) /* Insert Name into hash table */ Name nm; { - Text t = name(nm).text; - Int h = nHash(t); + Text t = name(nm).text; + Int h = nHash(t); name(nm).nextNameHash = nameHash[h]; nameHash[h] = nm; } -Name findQualName(line,id) /* locate (possibly qualified) name in name table */ -Int line; -Cell id; { - assert(isPair(id)); +Name findQualName(id) /* Locate (possibly qualified) name*/ +Cell id; { /* in name table */ + if (!isPair(id)) + internal("findQualName"); switch (fst(id)) { case VARIDCELL : case VAROPCELL : @@ -521,6 +482,9 @@ Cell id; { case CONOPCELL : return findName(textOf(id)); case QUALIDENT : { +#if IGNORE_MODULES + return findName(qtextOf(id)); +#else /* !IGNORE_MODULES */ Text t = qtextOf(id); Module m = findQualifier(qmodOf(id)); List es = NIL; @@ -540,8 +504,7 @@ Cell id; { List subentities = NIL; Cell c = fst(e); if (isTycon(c) - && (tycon(c).what == DATATYPE - || tycon(c).what == NEWTYPE)) + && (tycon(c).what==DATATYPE || tycon(c).what==NEWTYPE)) subentities = tycon(c).defn; else if (isClass(c)) subentities = cclass(c).members; @@ -553,9 +516,11 @@ Cell id; { } } return NIL; +#endif /* !IGNORE_MODULES */ } default : internal("findQualName2"); } + assert(0); return 0; /* NOTREACHED */ } /* -------------------------------------------------------------------------- @@ -567,7 +532,7 @@ Text t; Int arity; Int no; Int rep; { /* Really AsmRep */ - Name n = newName(t); + Name n = newName(t,NIL); name(n).arity = arity; name(n).number = cfunNo(no); name(n).type = NIL; @@ -580,12 +545,11 @@ Name s; /* selector s in constructor c. */ Name c; { List cns; cns = name(s).defn; - for (; nonNull(cns); cns=tl(cns)) { + for (; nonNull(cns); cns=tl(cns)) if (fst(hd(cns))==c) return intOf(snd(hd(cns))); - } internal("sfunPos"); - return 0;/*NOTREACHED*/ + return 0;/* NOTREACHED */ } static List local insertName(nm,ns) /* insert name nm into sorted list */ @@ -613,6 +577,7 @@ List addNamesMatching(pat,ns) /* Add names matching pattern pat */ String pat; /* to list of names ns */ List ns; { /* Null pattern matches every name */ Name nm; /* (Names with NIL type, or hidden */ +#if 1 for (nm=NAMEMIN; nm<nameHw; ++nm) /* or invented names are excluded) */ if (!inventedText(name(nm).text) && nonNull(name(nm).type)) { String str = textToStr(name(nm).text); @@ -620,6 +585,18 @@ List ns; { /* Null pattern matches every name */ ns = insertName(nm,ns); } return ns; +#else + List mns = module(currentModule).names; + for(; nonNull(mns); mns=tl(mns)) { + Name nm = hd(mns); + if (!inventedText(name(nm).text)) { + String str = textToStr(name(nm).text); + if (str[0]!='_' && (!pat || stringMatch(pat,str))) + ns = insertName(nm,ns); + } + } + return ns; +#endif } /* -------------------------------------------------------------------------- @@ -691,9 +668,6 @@ String str; { static Class classHw; /* next unused class */ static List classes; /* list of classes in current scope */ static Inst instHw; /* next unused instance record */ -#if USE_DICTHW -static Int dictHw; /* next unused dictionary number */ -#endif struct strClass DEFTABLE(tabClass,NUM_CLASSES); /* table of class records */ struct strInst far *tabInst; /* (pointer to) table of instances */ @@ -716,8 +690,10 @@ Text t; { cclass(classHw).defaults = NIL; cclass(classHw).instances = NIL; classes=cons(classHw,classes); +#if !IGNORE_MODULES cclass(classHw).mod = currentModule; module(currentModule).classes=cons(classHw,module(currentModule).classes); +#endif return classHw++; } @@ -737,36 +713,44 @@ Text t; { return NIL; } -Class addClass(c) /* Insert Class in class list - if no clash caused */ -Class c; { +Class addClass(c) /* Insert Class in class list */ +Class c; { /* - if no clash caused */ Class oldc = findClass(cclass(c).text); if (isNull(oldc)) { classes=cons(c,classes); +#if !IGNORE_MODULES module(currentModule).classes=cons(c,module(currentModule).classes); +#endif return c; - } else + } + else return oldc; } -Class findQualClass(c) /* look for (possibly qualified) class in class list */ -Cell c; { +Class findQualClass(c) /* Look for (possibly qualified) */ +Cell c; { /* class in class list */ if (!isQualIdent(c)) { return findClass(textOf(c)); } else { - Text t = qtextOf(c); - Module m = findQualifier(qmodOf(c)); +#if IGNORE_MODULES + return findClass(qtextOf(c)); +#else /* !IGNORE_MODULES */ + Text t = qtextOf(c); + Module m = findQualifier(qmodOf(c)); List es = NIL; - if (isNull(m)) return NIL; - for(es=module(m).exports; nonNull(es); es=tl(es)) { + if (isNull(m)) + return NIL; + for (es=module(m).exports; nonNull(es); es=tl(es)) { Cell e = hd(es); if (isPair(e) && isClass(fst(e)) && cclass(fst(e)).text==t) return fst(e); } +#endif } return NIL; } -Inst newInst() { /* add new instance to table */ +Inst newInst() { /* Add new instance to table */ if (instHw-INSTMIN >= NUM_INSTS) { ERRMSG(0) "Instance storage space exhausted" EEND; @@ -776,11 +760,22 @@ Inst newInst() { /* add new instance to table */ inst(instHw).specifics = NIL; inst(instHw).implements = NIL; inst(instHw).builder = NIL; - inst(instHw).mod = currentModule; + /* from STG */ inst(instHw).mod = currentModule; return instHw++; } +#ifdef DEBUG_DICTS +extern Void printInst Args((Inst)); + +Void printInst(in) +Inst in; { + Class cl = inst(in).c; + Printf("%s-", textToStr(cclass(cl).text)); + printType(stdout,inst(in).t); +} +#endif /* DEBUG_DICTS */ + Inst findFirstInst(tc) /* look for 1st instance involving */ Tycon tc; { /* the type constructor tc */ return findNextInst(tc,INSTMIN-1); @@ -816,11 +811,49 @@ Type tc; { Cell DEFTABLE(cellStack,NUM_STACK); /* Storage for cells on stack */ StackPtr sp; /* stack pointer */ +#if GIMME_STACK_DUMPS + +#define UPPER_DISP 5 /* # display entries on top of stack */ +#define LOWER_DISP 5 /* # display entries on bottom of stack*/ + +Void hugsStackOverflow() { /* Report stack overflow */ + extern Int rootsp; + extern Cell evalRoots[]; + + ERRMSG(0) "Control stack overflow" ETHEN + if (rootsp>=0) { + Int i; + if (rootsp>=UPPER_DISP+LOWER_DISP) { + for (i=0; i<UPPER_DISP; i++) { + ERRTEXT "\nwhile evaluating: " ETHEN + ERREXPR(evalRoots[rootsp-i]); + } + ERRTEXT "\n..." ETHEN + for (i=LOWER_DISP-1; i>=0; i--) { + ERRTEXT "\nwhile evaluating: " ETHEN + ERREXPR(evalRoots[i]); + } + } + else { + for (i=rootsp; i>=0; i--) { + ERRTEXT "\nwhile evaluating: " ETHEN + ERREXPR(evalRoots[i]); + } + } + } + ERRTEXT "\n" + EEND; +} + +#else /* !GIMME_STACK_DUMPS */ + Void hugsStackOverflow() { /* Report stack overflow */ ERRMSG(0) "Control stack overflow" EEND; } +#endif /* !GIMME_STACK_DUMPS */ + /* -------------------------------------------------------------------------- * Module storage: * @@ -838,6 +871,7 @@ Void hugsStackOverflow() { /* Report stack overflow */ * * ------------------------------------------------------------------------*/ +#if !IGNORE_MODULES static Module moduleHw; /* next unused Module */ struct Module DEFTABLE(tabModule,NUM_MODULE); /* Module storage */ Module currentModule; /* Module currently being processed*/ @@ -867,9 +901,8 @@ Module findModule(t) /* locate Module in module table */ Text t; { Module m; for(m=MODMIN; m<moduleHw; ++m) { - if (module(m).text==t) { + if (module(m).text==t) return m; - } } return NIL; } @@ -883,6 +916,7 @@ Cell c; { case CONIDCELL : return findModule(textOf(c)); default : internal("findModid"); } + assert(0); return 0; /* NOTREACHED */ } static local Module findQualifier(t) /* locate Module in import list */ @@ -896,10 +930,13 @@ Text t; { return modulePreludeHugs; } for (ms=module(currentModule).qualImports; nonNull(ms); ms=tl(ms)) { - if (textOf(fst(hd(ms)))==t) { + if (textOf(fst(hd(ms)))==t) return snd(hd(ms)); - } } +#if 1 /* mpj */ + if (module(currentModule).text==t) + return currentModule; +#endif return NIL; } @@ -908,17 +945,16 @@ Module m; { Int i; if (m!=currentModule) { currentModule = m; /* This is the only assignment to currentModule */ - for (i=0; i<TYCONHSZ; ++i) { + for (i=0; i<TYCONHSZ; ++i) tyconHash[i] = NIL; - } mapProc(hashTycon,module(m).tycons); - for (i=0; i<NAMEHSZ; ++i) { + for (i=0; i<NAMEHSZ; ++i) nameHash[i] = NIL; - } mapProc(hashName,module(m).names); classes = module(m).classes; } } +#endif /* !IGNORE_MODULES */ /* -------------------------------------------------------------------------- * Script file storage: @@ -935,15 +971,13 @@ typedef struct { /* record of storage state prior to */ Text textHw; Text nextNewText; Text nextNewDText; - Int syntaxHw; +#if !IGNORE_MODULES Module moduleHw; +#endif Tycon tyconHw; Name nameHw; Class classHw; Inst instHw; -#if USE_DICTHW - Int dictHw; -#endif #if TREX Ext extHw; #endif @@ -968,8 +1002,9 @@ String f; { /* of status for later restoration */ } #ifdef DEBUG_SHOWUSE showUse("Text", textHw, NUM_TEXT); - showUse("Syntax", syntaxHw, NUM_SYNTAX); +#if !IGNORE_MODULES showUse("Module", moduleHw-MODMIN, NUM_MODULE); +#endif showUse("Tycon", tyconHw-TYCMIN, NUM_TYCON); showUse("Name", nameHw-NAMEMIN, NUM_NAME); showUse("Class", classHw-CLASSMIN, NUM_CLASSES); @@ -983,21 +1018,34 @@ String f; { /* of status for later restoration */ scripts[scriptHw].textHw = textHw; scripts[scriptHw].nextNewText = nextNewText; scripts[scriptHw].nextNewDText = nextNewDText; - scripts[scriptHw].syntaxHw = syntaxHw; +#if !IGNORE_MODULES scripts[scriptHw].moduleHw = moduleHw; +#endif scripts[scriptHw].tyconHw = tyconHw; scripts[scriptHw].nameHw = nameHw; scripts[scriptHw].classHw = classHw; scripts[scriptHw].instHw = instHw; -#if USE_DICTHW - scripts[scriptHw].dictHw = dictHw; -#endif #if TREX scripts[scriptHw].extHw = extHw; #endif return scriptHw++; } +Bool isPreludeScript() { /* Test whether this is the Prelude*/ + return (scriptHw==0); +} + +#if !IGNORE_MODULES +Bool moduleThisScript(m) /* Test if given module is defined */ +Module m; { /* in current script file */ + return scriptHw<1 || m>=scripts[scriptHw-1].moduleHw; +} + +Module lastModule() { /* Return module in current script file */ + return (moduleHw>MODMIN ? moduleHw-1 : modulePrelude); +} +#endif /* !IGNORE_MODULES */ + #define scriptThis(nm,t,tag) Script nm(x) \ t x; { \ Script s=0; \ @@ -1012,18 +1060,18 @@ scriptThis(scriptThisInst,Inst,instHw) scriptThis(scriptThisClass,Class,classHw) #undef scriptThis -Module lastModule() { /* Return module in current script file */ - return (moduleHw-1); -} - -static Module local moduleOfScript(s) +Module moduleOfScript(s) Script s; { - return scripts[s-1].moduleHw; + return (s==0) ? modulePrelude : scripts[s-1].moduleHw; } +#if !IGNORE_MODULES String fileOfModule(m) Module m; { Script s; + if (m == modulePrelude) { + return STD_PRELUDE; + } for(s=0; s<scriptHw; ++s) { if (scripts[s].moduleHw == m) { return textToStr(scripts[s].file); @@ -1031,8 +1079,9 @@ Module m; { } return 0; } +#endif -static Script local scriptThisFile(f) +Script scriptThisFile(f) Text f; { Script s; for (s=0; s < scriptHw; ++s) { @@ -1040,6 +1089,9 @@ Text f; { return s+1; } } + if (f == findText(STD_PRELUDE)) { + return 0; + } return (-1); } @@ -1050,7 +1102,9 @@ Script sno; { /* to reading script sno */ textHw = scripts[sno].textHw; nextNewText = scripts[sno].nextNewText; nextNewDText = scripts[sno].nextNewDText; - syntaxHw = scripts[sno].syntaxHw; +#if !IGNORE_MODULES + moduleHw = scripts[sno].moduleHw; +#endif tyconHw = scripts[sno].tyconHw; nameHw = scripts[sno].nameHw; classHw = scripts[sno].classHw; @@ -1064,8 +1118,8 @@ Script sno; { /* to reading script sno */ for (i=moduleHw; i >= scripts[sno].moduleHw; --i) { if (module(i).objectFile) { - printf("closing objectFile for module %d\n",i); - dlclose(module(i).objectFile); + printf("[bogus] closing objectFile for module %d\n",i); + /*dlclose(module(i).objectFile);*/ } } moduleHw = scripts[sno].moduleHw; @@ -1079,6 +1133,21 @@ Script sno; { /* to reading script sno */ textHash[i][j] = NOTEXT; } +#if IGNORE_MODULES + for (i=0; i<TYCONHSZ; ++i) { + Tycon tc = tyconHash[i]; + while (nonNull(tc) && tc>=tyconHw) + tc = tycon(tc).nextTyconHash; + tyconHash[i] = tc; + } + + for (i=0; i<NAMEHSZ; ++i) { + Name n = nameHash[i]; + while (nonNull(n) && n>=nameHw) + n = name(n).nextNameHash; + nameHash[i] = n; + } +#else /* !IGNORE_MODULES */ currentModule=NIL; for (i=0; i<TYCONHSZ; ++i) { tyconHash[i] = NIL; @@ -1086,6 +1155,7 @@ Script sno; { /* to reading script sno */ for (i=0; i<NAMEHSZ; ++i) { nameHash[i] = NIL; } +#endif /* !IGNORE_MODULES */ for (i=CLASSMIN; i<classHw; i++) { List ins = cclass(i).instances; @@ -1119,15 +1189,36 @@ Script sno; { /* to reading script sno */ Int heapSize = DEFAULTHEAP; /* number of cells in heap */ Heap heapFst; /* array of fst component of pairs */ Heap heapSnd; /* array of snd component of pairs */ +#ifndef GLOBALfst Heap heapTopFst; +#endif +#ifndef GLOBALsnd Heap heapTopSnd; +#endif Bool consGC = TRUE; /* Set to FALSE to turn off gc from*/ /* C stack; use with extreme care! */ +#if PROFILING +Heap heapThd, heapTopThd; /* to keep record of producers */ +Int sysCount; /* record unattached cells */ +Name producer; /* current producer, if any */ +Bool profiling = FALSE; /* should profiling be performed */ +Int profInterval = MAXPOSINT; /* interval between samples */ +FILE *profile = 0; /* pointer to profiler log, if any */ +#endif +Long numCells; +Int numGcs; /* number of garbage collections */ Int cellsRecovered; /* number of cells recovered */ static Cell freeList; /* free list of unused cells */ static Cell lsave, rsave; /* save components of pair */ +#if GC_WEAKPTRS +static List weakPtrs; /* list of weak ptrs */ + /* reconstructed during every GC */ +List finalizers = NIL; +List liveWeakPtrs = NIL; +#endif + #if GC_STATISTICS static Int markCount, stackRoots; @@ -1137,19 +1228,19 @@ static Int markCount, stackRoots; #define startGC() \ if (gcMessages) { \ - printf("\n"); \ + Printf("\n"); \ fflush(stdout); \ } #define endGC() \ if (gcMessages) { \ - printf("\n"); \ + Printf("\n"); \ fflush(stdout); \ } #define start() markCount = 0 #define end(thing,rs) \ if (gcMessages) { \ - printf("GC: %-18s: %4d cells, %4d roots.\n", thing, markCount, rs); \ + Printf("GC: %-18s: %4d cells, %4d roots.\n", thing, markCount, rs); \ fflush(stdout); \ } #define recordMark() markCount++ @@ -1185,22 +1276,21 @@ Cell l, r; { /* heap, garbage collecting first */ freeList = snd(freeList); fst(c) = l; snd(c) = r; +#if PROFILING + thd(c) = producer; +#endif + numCells++; return c; } Void overwrite(dst,src) /* overwrite dst cell with src cell*/ -Pair dst, src; { /* both *MUST* be pairs */ - assert(isPair(dst) && isPair(src)); - fst(dst) = fst(src); - snd(dst) = snd(src); -} - -Void overwrite2(dst,src1,src2) /* overwrite dst cell with src cell*/ -Pair dst; -Cell src1, src2; { - assert(isPair(dst)); - fst(dst) = src1; - snd(dst) = src2; +Cell dst, src; { /* both *MUST* be pairs */ + if (isPair(dst) && isPair(src)) { + fst(dst) = fst(src); + snd(dst) = snd(src); + } + else + internal("overwrite"); } static Int *marks; @@ -1215,8 +1305,8 @@ static Cell local markCell(c) /* Traverse part of graph marking */ Cell c; { /* cells reachable from given root */ /* markCell(c) is only called if c */ /* is a pair */ - { register place = placeInSet(c); - register mask = maskInSet(c); + { register int place = placeInSet(c); + register int mask = maskInSet(c); if (marks[place]&mask) return c; else { @@ -1229,8 +1319,9 @@ Cell c; { /* cells reachable from given root */ fst(c) = markCell(fst(c)); markSnd(c); } - else if (isNull(fst(c)) || fst(c)>=BCSTAG) + else if (isNull(fst(c)) || fst(c)>=BCSTAG) { markSnd(c); + } return c; } @@ -1244,8 +1335,8 @@ ma: t = c; /* Keep pointer to original pair */ mb: if (!isPair(c)) return; - { register place = placeInSet(c); - register mask = maskInSet(c); + { register int place = placeInSet(c); + register int mask = maskInSet(c); if (marks[place]&mask) return; else { @@ -1285,14 +1376,128 @@ Void garbageCollect() { /* Run garbage collector ... */ gcStarted(); for (i=0; i<marksSize; ++i) /* initialise mark set to empty */ marks[i] = 0; - +#if GC_WEAKPTRS + weakPtrs = NIL; /* clear list of weak pointers */ +#endif everybody(MARK); /* Mark all components of system */ +#if IO_HANDLES + for (i=0; i<NUM_HANDLES; ++i) /* release any unused handles */ + if (nonNull(handles[i].hcell)) { + register place = placeInSet(handles[i].hcell); + register mask = maskInSet(handles[i].hcell); + if ((marks[place]&mask)==0) + freeHandle(i); + } +#endif +#if GC_MALLOCPTRS + for (i=0; i<NUM_MALLOCPTRS; ++i) /* release any unused mallocptrs */ + if (isPair(mallocPtrs[i].mpcell)) { + register place = placeInSet(mallocPtrs[i].mpcell); + register mask = maskInSet(mallocPtrs[i].mpcell); + if ((marks[place]&mask)==0) + incMallocPtrRefCnt(i,-1); + } +#endif /* GC_MALLOCPTRS */ +#if GC_WEAKPTRS + /* After GC completes, we scan the list of weak pointers that are + * still live and zap their contents unless the contents are still + * live (by some other means). + * Note that this means the contents must itself be heap allocated. + * This means it can't be a nullary constructor or an Int or a Name + * or lots of other things - hope this doesn't bite too hard. + */ + for (; nonNull(weakPtrs); weakPtrs=nextWeakPtr(weakPtrs)) { + Cell ptr = derefWeakPtr(weakPtrs); + if (isGenPair(ptr)) { + Int place = placeInSet(ptr); + Int mask = maskInSet(ptr); + if ((marks[place]&mask)==0) { + /* printf("Zapping weak pointer %d\n", ptr); */ + derefWeakPtr(weakPtrs) = NIL; + } else { + /* printf("Keeping weak pointer %d\n", ptr); */ + } + } else if (nonNull(ptr)) { + printf("Weak ptr contains object which isn't heap allocated %d\n", ptr); + } + } + + if (nonNull(liveWeakPtrs) || nonNull(finalizers)) { + Bool anyMarked; /* Weak pointers with finalizers */ + List wps; + List newFins = NIL; + + /* Step 1: iterate until we've found out what is reachable */ + do { + anyMarked = FALSE; + for (wps=liveWeakPtrs; nonNull(wps); wps=tl(wps)) { + Cell wp = hd(wps); + Cell k = fst(snd(wp)); + if (isNull(k)) { + internal("bad weak ptr"); + } + if (isMarked(k)) { + Cell vf = snd(snd(wp)); + if (!isMarked(fst(vf)) || !isMarked(snd(vf))) { + mark(fst(vf)); + mark(snd(vf)); + anyMarked = TRUE; + } + } + } + } while (anyMarked); + + /* Step 2: Now we know which weak pointers will die, so we can */ + /* remove them from the live set and gather their finalizers. But */ + /* note that we mustn't mark *anything* at this stage or we will */ + /* corrupt our view of what's alive, and what's dead. */ + wps = NIL; + while (nonNull(liveWeakPtrs)) { + Cell wp = hd(liveWeakPtrs); + List nx = tl(liveWeakPtrs); + Cell k = fst(snd(wp)); + if (!isMarked(k)) { /* If the key is dead, then*/ + Cell vf = snd(snd(wp)); /* stomp on weak pointer */ + fst(vf) = snd(vf); + snd(vf) = newFins; + newFins = vf; /* reuse because we can't */ + fst(snd(wp)) = NIL; /* reallocate here ... */ + snd(snd(wp)) = NIL; + snd(wp) = NIL; + liveWeakPtrs = nx; + } else { + tl(liveWeakPtrs) = wps; /* Otherwise, weak pointer */ + wps = liveWeakPtrs;/* survives to face another*/ + liveWeakPtrs = nx; /* garbage collection */ + } + } + + /* Step 3: Now we've identified the live cells and the newly */ + /* scheduled finalizers, but we had better make sure that they are */ + /* all marked now, including any internal structure, to ensure that*/ + /* they make it to the other side of gc. */ + for (liveWeakPtrs=wps; nonNull(wps); wps=tl(wps)) { + mark(snd(hd(wps))); + } + mark(liveWeakPtrs); + mark(newFins); + finalizers = revOnto(newFins,finalizers); + } + +#endif /* GC_WEAKPTRS */ gcScanning(); /* scan mark set */ mask = 1; place = 0; recovered = 0; j = 0; +#if PROFILING + if (profile) { + sysCount = 0; + for (i=NAMEMIN; i<nameHw; i++) + name(i).count = 0; + } +#endif freeList = NIL; for (i=1; i<=heapSize; i++) { if ((marks[place] & mask) == 0) { @@ -1301,6 +1506,12 @@ Void garbageCollect() { /* Run garbage collector ... */ freeList = -i; recovered++; } +#if PROFILING + else if (nonNull(thd(-i))) + name(thd(-i)).count++; + else + sysCount++; +#endif mask <<= 1; if (++j == bitsPerWord) { place++; @@ -1312,6 +1523,49 @@ Void garbageCollect() { /* Run garbage collector ... */ gcRecovered(recovered); breakOn(breakStat); /* restore break trapping if nec. */ +#if PROFILING + if (profile) { + fprintf(profile,"BEGIN_SAMPLE %ld.00\n",numReductions); +/* For the time being, we won't include the system count in the output: + if (sysCount>0) + fprintf(profile," SYSTEM %d\n",sysCount); +*/ + /* Accumulate costs in top level objects */ + for (i=NAMEMIN; i<nameHw; i++) { + Name cc = i; + /* Use of "while" instead of "if" is pure paranoia - ADR */ + while (isName(name(cc).parent)) + cc = name(cc).parent; + if (i != cc) { + name(cc).count += name(i).count; + name(i).count = 0; + } + } + for (i=NAMEMIN; i<nameHw; i++) + if (name(i).count>0) + if (isPair(name(i).parent)) { + Pair p = name(i).parent; + Cell f = fst(p); + fprintf(profile," "); + if (isClass(f)) + fprintf(profile,"%s",textToStr(cclass(f).text)); + else { + fprintf(profile,"%s_",textToStr(cclass(inst(f).c).text)); + /* Will hp2ps accept the spaces produced by this? */ + printPred(profile,inst(f).head); + } + fprintf(profile,"_%s %d\n", + textToStr(name(snd(p)).text), + name(i).count); + } else { + fprintf(profile," %s %d\n", + textToStr(name(i).text), + name(i).count); + } + fprintf(profile,"END_SAMPLE %ld.00\n",numReductions); + } +#endif + /* can only return if freeList is nonempty on return. */ if (recovered<minRecovery || isNull(freeList)) { ERRMSG(0) "Garbage collection fails to reclaim sufficient space" @@ -1320,6 +1574,22 @@ Void garbageCollect() { /* Run garbage collector ... */ cellsRecovered = recovered; } +#if PROFILING +Void profilerLog(s) /* turn heap profiling on, saving log*/ +String s; { /* in specified file */ + if ((profile=fopen(s,"w")) != NULL) { + fprintf(profile,"JOB \"Hugs Heap Profile\"\n"); + fprintf(profile,"DATE \"%s\"\n",timeString()); + fprintf(profile,"SAMPLE_UNIT \"reductions\"\n"); + fprintf(profile,"VALUE_UNIT \"cells\"\n"); + } + else { + ERRMSG(0) "Cannot open profile log file \"%s\"", s + EEND; + } +} +#endif + /* -------------------------------------------------------------------------- * Code for saving last expression entered: * @@ -1392,7 +1662,7 @@ Cell c; { /* except that Cells refering to */ * Miscellaneous operations on heap cells: * ------------------------------------------------------------------------*/ -/* profiling suggests that the number of calls to whatIs() is typically */ +/* Profiling suggests that the number of calls to whatIs() is typically */ /* rather high. The recoded version below attempts to improve the average */ /* performance for whatIs() using a binary search for part of the analysis */ @@ -1413,14 +1683,17 @@ register Cell c; { else return MODULE; else if (c>=OFFMIN) return OFFSET; #if TREX - else if (c>=EXTMIN) return EXT; + else return (c>=EXTMIN) ? + EXT : TUPLE; +#else + else return TUPLE; #endif - else return TUPLE; /* if (isPair(c)) { register Cell fstc = fst(c); return isTag(fstc) ? fstc : AP; } + if (c>=INTMIN) return INTCELL; if (c>=CHARMIN) return CHARCELL; if (c>=CLASSMIN) return CLASS; if (c>=INSTMIN) return INSTANCE; @@ -1447,6 +1720,11 @@ Cell c; Int depth; { if (0 == depth) { Printf("..."); +#if 0 /* Not in this version of Hugs */ + } else if (isPair(c) && !isGenPair(c)) { + extern Void printEvalCell Args((Cell, Int)); + printEvalCell(c,depth); +#endif } else { Int tag = whatIs(c); switch (tag) { @@ -1699,10 +1977,18 @@ Cell c; { Cell mkInt(n) /* make cell representing integer */ Int n; { - return isSmall(INTZERO+n) ? INTZERO+n : pair(INTCELL,n); + return (MINSMALLINT <= n && n <= MAXSMALLINT) + ? INTZERO+n + : pair(INTCELL,n); } -#if PTR_ON_HEAP +#if BIGNUMS +Bool isBignum(c) /* cell holds bignum value? */ +Cell c; { + return c==ZERONUM || (isPair(c) && (fst(c)==POSNUM || fst(c)==NEGNUM)); +} +#endif + #if SIZEOF_INTP == SIZEOF_INT typedef union {Int i; Ptr p;} IntOrPtr; Cell mkPtr(p) @@ -1717,28 +2003,45 @@ Ptr ptrOf(c) Cell c; { IntOrPtr x; - assert(isPtr(c)); + assert(fst(c) == PTRCELL); x.i = snd(c); return x.p; } +#elif SIZEOF_INTP == 2*SIZEOF_INT +typedef union {struct {Int i1; Int i2;} i; Ptr p;} IntOrPtr; +Cell mkPtr(p) +Ptr p; +{ + IntOrPtr x; + x.p = p; + return pair(PTRCELL,pair(mkInt(x.i.i1),mkInt(x.i.i2))); +} + +Ptr ptrOf(c) +Cell c; +{ + IntOrPtr x; + assert(fst(c) == PTRCELL); + x.i.i1 = intOf(fst(snd(c))); + x.i.i2 = intOf(snd(snd(c))); + return x.p; +} #else -/* For 8 byte addresses (used on the Alpha), we'll have to work harder */ -#error "PTR_ON_HEAP not supported on this architecture" -#endif -#endif +#warning "type Addr not supported on this architecture - don't use it" +Cell mkPtr(p) +Ptr p; +{ + ERRMSG(0) "mkPtr: type Addr not supported on this architecture" + EEND; +} -String stringNegate( s ) -String s; +Ptr ptrOf(c) +Cell c; { - if (s[0] == '-') { - return &s[1]; - } else { - static char t[100]; - t[0] = '-'; - strcpy(&t[1],s); /* ToDo: use strncpy instead */ - return t; - } + ERRMSG(0) "ptrOf: type Addr not supported on this architecture" + EEND; } +#endif /* -------------------------------------------------------------------------- * List operations: @@ -1747,7 +2050,7 @@ String s; Int length(xs) /* calculate length of list xs */ List xs; { Int n = 0; - for (n=0; nonNull(xs); ++n) + for (; nonNull(xs); ++n) xs = tl(xs); return n; } @@ -1765,19 +2068,20 @@ List xs, ys; { /* ys by modifying xs ... */ } } -List revDupOnto(xs,ys) /* non-destructively prepend xs backwards onto ys */ +List dupOnto(xs,ys) /* non-destructively prepend xs backwards onto ys */ List xs; List ys; { - for( ; nonNull(xs); xs=tl(xs)) { + for (; nonNull(xs); xs=tl(xs)) ys = cons(hd(xs),ys); - } return ys; } -List dupListOnto(xs,ys) /* Duplicate spine of list xs onto ys */ -List xs; -List ys; { - return revOnto(revDupOnto(xs,NIL),ys); +List dupList(xs) /* Duplicate spine of list xs */ +List xs; { + List ys = NIL; + for (; nonNull(xs); xs=tl(xs)) + ys = cons(hd(xs),ys); + return rev(ys); } List revOnto(xs,ys) /* Destructively reverse elements of*/ @@ -1793,16 +2097,27 @@ List xs, ys; { /* list xs onto list ys... */ return ys; } -Bool eqList(as,bs) -List as; -List bs; { - while (nonNull(as) && nonNull(bs) && hd(as)==hd(bs)) { - as=tl(as); - bs=tl(bs); +#if 0 +List delete(xs,y) /* Delete first use of y from xs */ +List xs; +Cell y; { + if (isNull(xs)) { + return xs; + } else if (hs(xs) == y) { + return tl(xs); + } else { + tl(xs) = delete(tl(xs),y); + return xs; } - return (isNull(as) && isNull(bs)); } +List minus(xs,ys) /* Delete members of ys from xs */ +List xs, ys; { + mapAccum(delete,xs,ys); + return xs; +} +#endif + Cell varIsMember(t,xs) /* Test if variable is a member of */ Text t; /* given list of variables */ List xs; { @@ -1812,6 +2127,15 @@ List xs; { return NIL; } +Name nameIsMember(t,ns) /* Test if name with text t is a */ +Text t; /* member of list of names xs */ +List ns; { + for (; nonNull(ns); ns=tl(ns)) + if (t==name(hd(ns)).text) + return hd(ns); + return NIL; +} + Cell intIsMember(n,xs) /* Test if integer n is member of */ Int n; /* given list of integers */ List xs; { @@ -1848,27 +2172,26 @@ List xs; { return NIL; } -List replicate(n,x) /* create list of n copies of x */ +List replicate(n,x) /* create list of n copies of x */ Int n; Cell x; { List xs=NIL; - assert(n>=0); - while (0<n--) { + while (0<n--) xs = cons(x,xs); - } return xs; } -List diffList(xs,ys) /* list difference: xs\ys */ -List xs, ys; { /* result contains all elements of */ - List result = NIL; /* `xs' not appearing in `ys' */ - while (nonNull(xs)) { - List next = tl(xs); - if (!cellIsMember(hd(xs),ys)) { - tl(xs) = result; - result = xs; +List diffList(from,take) /* list difference: from\take */ +List from, take; { /* result contains all elements of */ + List result = NIL; /* `from' not appearing in `take' */ + + while (nonNull(from)) { + List next = tl(from); + if (!cellIsMember(hd(from),take)) { + tl(from) = result; + result = from; } - xs = next; + from = next; } return rev(result); } @@ -1891,7 +2214,6 @@ Int n; /* specified length */ List xs; { List ys = xs; - assert(n>=0); if (n==0) return NIL; while (1<n-- && nonNull(xs)) @@ -1901,10 +2223,9 @@ List xs; { return ys; } -List splitAt(n,xs) /* drop n things from front of list */ +List splitAt(n,xs) /* drop n things from front of list*/ Int n; List xs; { - assert(n>=0); for(; n>0; --n) { xs = tl(xs); } @@ -1914,10 +2235,10 @@ List xs; { Cell nth(n,xs) /* extract n'th element of list */ Int n; List xs; { - assert(n>=0); for(; n>0 && nonNull(xs); --n, xs=tl(xs)) { } - assert(nonNull(xs)); + if (isNull(xs)) + internal("nth"); return hd(xs); } @@ -1965,7 +2286,6 @@ Cell e; { /* application: */ Cell nthArg(n,e) /* return nth arg in application */ Int n; /* of function to m args (m>=n) */ Cell e; { /* nthArg n (f x0 x1 ... xm) = xn */ - assert(n>=0); for (n=numArgs(e)-n-1; n>0; n--) e = fun(e); return arg(e); @@ -1992,6 +2312,254 @@ List args; { return f; } +/* -------------------------------------------------------------------------- + * Handle operations: + * ------------------------------------------------------------------------*/ + +#if IO_HANDLES +struct strHandle DEFTABLE(handles,NUM_HANDLES); + +Cell openHandle(s,hmode,binary) /* open handle to file named s in */ +String s; /* the specified hmode */ +Int hmode; +Bool binary; { + Int i; + + for (i=0; i<NUM_HANDLES && nonNull(handles[i].hcell); ++i) + ; /* Search for unused handle*/ + if (i>=NUM_HANDLES) { /* If at first we don't */ + garbageCollect(); /* succeed, garbage collect*/ + for (i=0; i<NUM_HANDLES && nonNull(handles[i].hcell); ++i) + ; /* and try again ... */ + } + if (i>=NUM_HANDLES) { /* ... before we give up */ + ERRMSG(0) "Too many handles open; cannot open \"%s\"", s + EEND; + } + else { /* prepare to open file */ + String stmode; + if (binary) { + stmode = (hmode&HAPPEND) ? "ab+" : + (hmode&HWRITE) ? "wb+" : + (hmode&HREAD) ? "rb" : (String)0; + } else { + stmode = (hmode&HAPPEND) ? "a+" : + (hmode&HWRITE) ? "w+" : + (hmode&HREAD) ? "r" : (String)0; + } + if (stmode && (handles[i].hfp=fopen(s,stmode))) { + handles[i].hmode = hmode; + return (handles[i].hcell = ap(HANDCELL,i)); + } + } + return NIL; +} + +static Void local freeHandle(n) /* release handle storage when no */ +Int n; { /* heap references to it remain */ + if (0<=n && n<NUM_HANDLES && nonNull(handles[n].hcell)) { + if (n>HSTDERR && handles[n].hmode!=HCLOSED && handles[n].hfp) { + fclose(handles[n].hfp); + handles[n].hfp = 0; + } + fst(handles[n].hcell) = snd(handles[n].hcell) = NIL; + handles[n].hcell = NIL; + } +} +#endif + +#if GC_MALLOCPTRS +/* -------------------------------------------------------------------------- + * Malloc Ptrs: + * ------------------------------------------------------------------------*/ + +struct strMallocPtr mallocPtrs[NUM_MALLOCPTRS]; + +/* It might GC (because it uses a table not a list) which will trash any + * unstable pointers. + * (It happens that we never use it with unstable pointers.) + */ +Cell mkMallocPtr(ptr,cleanup) /* create a new malloc pointer */ +Ptr ptr; +Void (*cleanup) Args((Ptr)); { + Int i; + for (i=0; i<NUM_MALLOCPTRS && mallocPtrs[i].refCount!=0; ++i) + ; /* Search for unused entry */ + if (i>=NUM_MALLOCPTRS) { /* If at first we don't */ + garbageCollect(); /* succeed, garbage collect*/ + for (i=0; i<NUM_MALLOCPTRS && mallocPtrs[i].refCount!=0; ++i) + ; /* and try again ... */ + } + if (i>=NUM_MALLOCPTRS) { /* ... before we give up */ + ERRMSG(0) "Too many ForeignObjs open" + EEND; + } + mallocPtrs[i].ptr = ptr; + mallocPtrs[i].cleanup = cleanup; + mallocPtrs[i].refCount = 1; + return (mallocPtrs[i].mpcell = ap(MPCELL,i)); +} + +Void incMallocPtrRefCnt(n,i) /* change ref count of MallocPtr */ +Int n; +Int i; { + if (!(0<=n && n<NUM_MALLOCPTRS && mallocPtrs[n].refCount > 0)) + internal("freeMallocPtr"); + mallocPtrs[n].refCount += i; + if (mallocPtrs[n].refCount <= 0) { + mallocPtrs[n].cleanup(mallocPtrs[n].ptr); + + mallocPtrs[n].ptr = 0; + mallocPtrs[n].cleanup = 0; + mallocPtrs[n].refCount = 0; + mallocPtrs[n].mpcell = NIL; + } +} +#endif /* GC_MALLOCPTRS */ + +/* -------------------------------------------------------------------------- + * Stable pointers + * This is a mechanism that allows the C world to manipulate pointers into the + * Haskell heap without having to worry that the garbage collector is going + * to delete it or move it around. + * The implementation and interface is based on my implementation in + * GHC - but, at least for now, is simplified by using a fixed size + * table of stable pointers. + * ------------------------------------------------------------------------*/ + +#if GC_STABLEPTRS + +/* Each entry in the stable pointer table is either a heap pointer + * or is not currently allocated. + * Unallocated entries are threaded together into a freelist. + * The last entry in the list contains the Cell 0; all other values + * contain a Cell whose value is the next free stable ptr in the list. + * It follows that stable pointers are strictly positive (>0). + */ +static Cell stablePtrTable[NUM_STABLEPTRS]; +static Int sptFreeList; +#define SPT(sp) stablePtrTable[(sp)-1] + +static Void local resetStablePtrs() { + Int i; + /* It would be easier to build the free list in the other direction + * but, when debugging, it's way easier to understand if the first + * pointer allocated is "1". + */ + for(i=1; i < NUM_STABLEPTRS; ++i) + SPT(i) = i+1; + SPT(NUM_STABLEPTRS) = 0; + sptFreeList = 1; +} + +Int mkStablePtr(c) /* Create a stable pointer */ +Cell c; { + Int i = sptFreeList; + if (i == 0) + return 0; + sptFreeList = SPT(i); + SPT(i) = c; + return i; +} + +Cell derefStablePtr(p) /* Dereference a stable pointer */ +Int p; { + if (!(1 <= p && p <= NUM_STABLEPTRS)) { + internal("derefStablePtr"); + } + return SPT(p); +} + +Void freeStablePtr(i) /* Free a stable pointer */ +Int i; { + SPT(i) = sptFreeList; + sptFreeList = i; +} + +#undef SPT +#endif /* GC_STABLEPTRS */ + +/* -------------------------------------------------------------------------- + * plugin support + * ------------------------------------------------------------------------*/ + +/*--------------------------------------------------------------------------- + * GreenCard entry points + * + * GreenCard generated code accesses Hugs data structures and functions + * (only) via these functions (which are stored in the virtual function + * table hugsAPI1. + *-------------------------------------------------------------------------*/ + +#if GREENCARD + +static Cell makeTuple Args((Int)); +static Cell makeInt Args((Int)); +static Cell makeChar Args((Char)); +static Char CharOf Args((Cell)); +static Cell makeFloat Args((FloatPro)); +static Void* derefMallocPtr Args((Cell)); +static Cell* Fst Args((Cell)); +static Cell* Snd Args((Cell)); + +static Cell makeTuple(n) Int n; { return mkTuple(n); } +static Cell makeInt(n) Int n; { return mkInt(n); } +static Cell makeChar(n) Char n; { return mkChar(n); } +static Char CharOf(n) Cell n; { return charOf(n); } +static Cell makeFloat(n) FloatPro n; { return mkFloat(n); } +static Void* derefMallocPtr(n) Cell n; { return derefMP(n); } +static Cell* Fst(n) Cell n; { return (Cell*)&fst(n); } +static Cell* Snd(n) Cell n; { return (Cell*)&snd(n); } + +HugsAPI1* hugsAPI1() { + static HugsAPI1 api; + static Bool initialised = FALSE; + if (!initialised) { + api.nameTrue = nameTrue; + api.nameFalse = nameFalse; + api.nameNil = nameNil; + api.nameCons = nameCons; + api.nameJust = nameJust; + api.nameNothing = nameNothing; + api.nameLeft = nameLeft; + api.nameRight = nameRight; + api.nameUnit = nameUnit; + api.nameIORun = nameIORun; + api.makeInt = makeInt; + api.makeChar = makeChar; + api.CharOf = CharOf; + api.makeFloat = makeFloat; + api.makeTuple = makeTuple; + api.pair = pair; + api.mkMallocPtr = mkMallocPtr; + api.derefMallocPtr = derefMallocPtr; + api.mkStablePtr = mkStablePtr; + api.derefStablePtr = derefStablePtr; + api.freeStablePtr = freeStablePtr; + api.eval = eval; + api.evalWithNoError = evalWithNoError; + api.evalFails = evalFails; + api.whnfArgs = &whnfArgs; + api.whnfHead = &whnfHead; + api.whnfInt = &whnfInt; + api.whnfFloat = &whnfFloat; + api.garbageCollect = garbageCollect; + api.stackOverflow = hugsStackOverflow; + api.internal = internal; + api.registerPrims = registerPrims; + api.addPrimCfun = addPrimCfun; + api.inventText = inventText; + api.Fst = Fst; + api.Snd = Snd; + api.cellStack = cellStack; + api.sp = &sp; + } + return &api; +} + +#endif /* GREENCARD */ + + /* -------------------------------------------------------------------------- * storage control: * ------------------------------------------------------------------------*/ @@ -2019,6 +2587,38 @@ Int what; { switch (what) { case RESET : clearStack(); + /* the next 2 statements are particularly important + * if you are using GLOBALfst or GLOBALsnd since the + * corresponding registers may be reset to their + * uninitialised initial values by a longjump. + */ + heapTopFst = heapFst + heapSize; + heapTopSnd = heapSnd + heapSize; +#if PROFILING + heapTopThd = heapThd + heapSize; + if (profile) { + garbageCollect(); + fclose(profile); +#if HAVE_HP2PS + system("hp2ps profile.hp"); +#endif + profile = 0; + } +#endif +#if IO_HANDLES + handles[HSTDIN].hmode = HREAD; + handles[HSTDOUT].hmode = HAPPEND; + handles[HSTDERR].hmode = HAPPEND; +#endif +#if GC_MALLOCPTRS + for (i=0; i<NUM_MALLOCPTRS; i++) + mallocPtrs[i].mpcell = NIL; +#endif +#if !HSCRIPT +#if GC_STABLEPTRS + resetStablePtrs(); +#endif +#endif consGC = TRUE; lsave = NIL; rsave = NIL; @@ -2029,12 +2629,14 @@ Int what; { case MARK : start(); for (i=NAMEMIN; i<nameHw; ++i) { + mark(name(i).parent); mark(name(i).defn); mark(name(i).stgVar); mark(name(i).type); } end("Names", nameHw-NAMEMIN); +#if !IGNORE_MODULES start(); for (i=MODMIN; i<moduleHw; ++i) { mark(module(i).tycons); @@ -2044,6 +2646,7 @@ Int what; { mark(module(i).qualImports); } end("Modules", moduleHw-MODMIN); +#endif start(); for (i=TYCMIN; i<tyconHw; ++i) { @@ -2068,8 +2671,8 @@ Int what; { start(); for (i=INSTMIN; i<instHw; ++i) { - mark(inst(i).kinds); mark(inst(i).head); + mark(inst(i).kinds); mark(inst(i).specifics); mark(inst(i).implements); } @@ -2085,6 +2688,24 @@ Int what; { mark(lsave); mark(rsave); end("Last expression", 3); +#if IO_HANDLES + start(); + mark(handles[HSTDIN].hcell); + mark(handles[HSTDOUT].hcell); + mark(handles[HSTDERR].hcell); + end("Standard handles", 3); +#endif + +#if GC_STABLEPTRS + start(); + for (i=0; i<NUM_STABLEPTRS; ++i) + mark(stablePtrTable[i]); + end("Stable pointers", NUM_STABLEPTRS); +#endif + +#if GC_WEAKPTRS + mark(finalizers); +#endif if (consGC) { start(); @@ -2105,12 +2726,24 @@ Int what; { heapTopFst = heapFst + heapSize; heapTopSnd = heapSnd + heapSize; +#if PROFILING + heapThd = heapAlloc(heapSize); + if (heapThd==(Heap)0) { + ERRMSG(0) "Cannot allocate profiler storage space" + EEND; + } + heapTopThd = heapThd + heapSize; + profile = 0; + if (0 == profInterval) + profInterval = heapSize / DEF_PROFINTDIV; +#endif for (i=1; i<heapSize; ++i) { fst(-i) = FREECELL; snd(-i) = -(i+1); } snd(-heapSize) = NIL; freeList = -1; + numGcs = 0; consGC = TRUE; lsave = NIL; rsave = NIL; @@ -2122,7 +2755,6 @@ Int what; { } TABALLOC(text, char, NUM_TEXT) - TABALLOC(tabSyntax, struct strSyntax, NUM_SYNTAX) TABALLOC(tyconHash, Tycon, TYCONHSZ) TABALLOC(tabTycon, struct strTycon, NUM_TYCON) TABALLOC(nameHash, Name, NAMEHSZ) @@ -2135,6 +2767,18 @@ Int what; { #endif clearStack(); +#if IO_HANDLES + TABALLOC(handles, struct strHandle, NUM_HANDLES) + for (i=0; i<NUM_HANDLES; i++) + handles[i].hcell = NIL; + handles[HSTDIN].hcell = ap(HANDCELL,HSTDIN); + handles[HSTDIN].hfp = stdin; + handles[HSTDOUT].hcell = ap(HANDCELL,HSTDOUT); + handles[HSTDOUT].hfp = stdout; + handles[HSTDERR].hcell = ap(HANDCELL,HSTDERR); + handles[HSTDERR].hfp = stderr; +#endif + textHw = 0; nextNewText = NUM_TEXT; nextNewDText = (-1); @@ -2143,14 +2787,24 @@ Int what; { for (i=0; i<TEXTHSZ; ++i) textHash[i][0] = NOTEXT; - syntaxHw = 0; +#if !IGNORE_MODULES moduleHw = MODMIN; +#endif tyconHw = TYCMIN; for (i=0; i<TYCONHSZ; ++i) tyconHash[i] = NIL; +#if GC_WEAKPTRS + finalizers = NIL; + liveWeakPtrs = NIL; +#endif + +#if GC_STABLEPTRS + resetStablePtrs(); +#endif + #if TREX extHw = EXTMIN; #endif diff --git a/ghc/interpreter/storage.h b/ghc/interpreter/storage.h index 4ea1d533ba38..6c0d89a105c2 100644 --- a/ghc/interpreter/storage.h +++ b/ghc/interpreter/storage.h @@ -1,15 +1,16 @@ -/* -*- mode: hugs-c; -*- */ + /* -------------------------------------------------------------------------- * Defines storage datatypes: Text, Name, Module, Tycon, Cell, List, Pair, * Triple, ... * - * Copyright (c) The University of Nottingham and Yale University, 1994-1997. - * All rights reserved. See NOTICE for details and conditions of use etc... - * Hugs version 1.4, December 1997 + * Hugs 98 is Copyright (c) Mark P Jones, Alastair Reid and the Yale + * Haskell Group 1994-99, and is distributed as Open Source software + * under the Artistic License; see the file "Artistic" that is included + * in the distribution for details. * * $RCSfile: storage.h,v $ - * $Revision: 1.2 $ - * $Date: 1998/12/02 13:22:43 $ + * $Revision: 1.3 $ + * $Date: 1999/02/03 17:08:41 $ * ------------------------------------------------------------------------*/ /* -------------------------------------------------------------------------- @@ -21,7 +22,7 @@ * ------------------------------------------------------------------------*/ typedef Int Text; /* text string */ -typedef Word Syntax; /* syntax (assoc,preced) */ +typedef Unsigned Syntax; /* syntax (assoc,preced) */ typedef Int Cell; /* general cell value */ typedef Cell far *Heap; /* storage of heap */ typedef Cell Pair; /* pair cell */ @@ -39,7 +40,7 @@ typedef Cell Class; /* type class */ typedef Cell Inst; /* instance of type class */ typedef Cell Triple; /* triple of cell values */ typedef Cell List; /* list of cells */ -typedef Cell Bignum; /* integer literal */ +typedef Cell Bignum; /* bignum integer */ typedef Cell Float; /* floating pt literal */ #if TREX typedef Cell Ext; /* extension label */ @@ -72,16 +73,20 @@ extern Syntax defaultSyntax Args((Text)); #define MAX_PREC 9 /* strongest binding operator */ #define FUN_PREC (MAX_PREC+2) /* binding of function symbols */ #define DEF_PREC MAX_PREC -#define APPLIC 00000 /* written applicatively */ -#define LEFT_ASS 02000 /* left associative infix */ -#define RIGHT_ASS 04000 /* right associative infix */ -#define NON_ASS 06000 /* non associative infix */ -#define DEF_ASS NON_ASS +#define APPLIC 0 /* written applicatively */ +#define LEFT_ASS 1 /* left associative infix */ +#define RIGHT_ASS 2 /* right associative infix */ +#define NON_ASS 3 /* non associative infix */ +#define DEF_ASS LEFT_ASS + +#define UMINUS_PREC 6 /* Change these settings at your */ +#define UMINUS_ASSOC LEFT_ASS /* own risk; they may not work! */ #define assocOf(x) ((x)&NON_ASS) -#define precOf(x) ((x)&(~NON_ASS)) -#define mkSyntax(a,p) ((a)|(p)) +#define precOf(x) ((x)>>2) +#define mkSyntax(a,p) ((a)|((p)<<2)) #define DEF_OPSYNTAX mkSyntax(DEF_ASS,DEF_PREC) +#define NO_SYNTAX (-1) extern Void addSyntax Args((Int,Text,Syntax)); extern Syntax syntaxOf Args((Text)); @@ -103,6 +108,14 @@ extern Int cellsRecovered; /* cells recovered by last gc */ #define fst(c) heapTopFst[c] #define snd(c) heapTopSnd[c] +#if PROFILING +extern Heap heapThd, heapTopThd; +#define thd(c) heapTopThd[c] +extern Name producer; +extern Bool profiling; +extern Int profInterval; +extern Void profilerLog Args((String)); +#endif extern Pair pair Args((Cell,Cell)); extern Void garbageCollect Args((Void)); @@ -140,6 +153,7 @@ extern Cell whatIs Args((Cell)); #define CONOPCELL 8 /* Operator constructor: snd :: Text */ #define STRCELL 9 /* String literal: snd :: Text */ #define INTCELL 10 /* Int literal: snd :: Int */ +#define ADDPAT 11 /* (_+k) pattern discr: snd :: Int */ #define FLOATCELL 15 /* Floating Pt literal: snd :: Text */ #define BIGCELL 16 /* Integer literal: snd :: Text */ #if PTR_ON_HEAP @@ -172,10 +186,24 @@ extern Bool isQCon Args((Cell)); extern Bool isQualIdent Args((Cell)); extern Bool isIdent Args((Cell)); -extern String stringNegate Args((String)); +#if 0 +Originally ... +#define isFloat(c) (isPair(c) && fst(c)==FLOATCELL) +extern Cell mkFloat Args((FloatPro)); +extern FloatPro floatOf Args((Cell)); +extern String floatToString Args((FloatPro)); +extern FloatPro stringToFloat Args((String)); +#else +#define isFloat(c) (isPair(c) && fst(c)==FLOATCELL) +#define stringToFloat(s) pair(FLOATCELL,findText(s)) +#define floatToString(f) textToStr(snd(f)) +#define floatEq(f1,f2) (snd(f1) == snd(f2)) +#define floatNegate(f) stringToFloat(stringNegate(floatToString(f))) +#define floatOf(f) atof(floatToString(f)) +#endif + + -#define intEq(x,y) (intOf(x) == intOf(y)) -#define intNegate(x) mkInt(-intOf(x)) #define isFloat(c) (isPair(c) && fst(c)==FLOATCELL) #define stringToFloat(s) pair(FLOATCELL,findText(s)) @@ -183,13 +211,10 @@ extern String stringNegate Args((String)); #define floatEq(f1,f2) (snd(f1) == snd(f2)) #define floatNegate(f) stringToFloat(stringNegate(floatToString(f))) #define floatOf(f) atof(floatToString(f)) +#define mkFloat(f) (f) /* ToDo: is this right? */ -#define isBignum(c) (isPair(c) && fst(c)==BIGCELL) -#define stringToBignum(s) pair(BIGCELL,findText(s)) #define bignumToString(b) textToStr(snd(b)) -#define bignumEq(b1,b2) (snd(b1) == snd(b2)) -#define bignumNegate(b) stringToBignum(stringNegate(bignumToString(b))) -#define bignumOf(b) atoi(bignumToString(b)) /* ToDo: overflow check */ + #if PTR_ON_HEAP #define isPtr(c) (isPair(c) && fst(c)==PTRCELL) @@ -215,58 +240,70 @@ extern Ptr ptrOf Args((Cell)); #define COMP 26 /* COMP snd :: (Exp,[Qual]) */ #define ASPAT 27 /* ASPAT snd :: (Var,Exp) */ #define ESIGN 28 /* ESIGN snd :: (Exp,Type) */ -#define CASE 29 /* CASE snd :: (Exp,[Alt]) */ -#define NUMCASE 30 /* NUMCASE snd :: (Exp,Disc,Rhs) */ -#define FATBAR 31 /* FATBAR snd :: (Exp,Exp) */ -#define LAZYPAT 32 /* LAZYPAT snd :: Exp */ +#define RSIGN 29 /* RSIGN snd :: (Rhs,Type) */ +#define CASE 30 /* CASE snd :: (Exp,[Alt]) */ +#define NUMCASE 31 /* NUMCASE snd :: (Exp,Disc,Rhs) */ +#define FATBAR 32 /* FATBAR snd :: (Exp,Exp) */ +#define LAZYPAT 33 /* LAZYPAT snd :: Exp */ #define DERIVE 35 /* DERIVE snd :: Cell */ -#if NPLUSK -#define ADDPAT 36 /* (_+k) pattern discr: snd :: Cell */ +#if BREAK_FLOATS +#define FLOATCELL 36 /* FLOATCELL snd :: (Int,Int) */ +#endif + +#if BIGNUMS +#define POSNUM 37 /* POSNUM snd :: [Int] */ +#define NEGNUM 38 /* NEGNUM snd :: [Int] */ #endif #define BOOLQUAL 39 /* BOOLQUAL snd :: Exp */ #define QWHERE 40 /* QWHERE snd :: [Decl] */ #define FROMQUAL 41 /* FROMQUAL snd :: (Exp,Exp) */ #define DOQUAL 42 /* DOQUAL snd :: Exp */ +#define MONADCOMP 43 /* MONADCOMP snd :: ((m,m0),(Exp,[Qual])*/ #define GUARDED 44 /* GUARDED snd :: [guarded exprs] */ -#define ARRAY 45 /* Array: snd :: (Bounds,[Values]) */ -#define MUTVAR 46 /* Mutvar: snd :: Cell */ +#define ARRAY 45 /* Array snd :: (Bounds,[Values]) */ +#define MUTVAR 46 /* Mutvar snd :: Cell */ +#if INTERNAL_PRIMS +#define HUGSOBJECT 47 /* HUGSOBJECT snd :: Cell */ +#endif #define POLYTYPE 50 /* POLYTYPE snd :: (Kind,Type) */ #define QUAL 51 /* QUAL snd :: ([Classes],Type) */ #define RANK2 52 /* RANK2 snd :: (Int,Type) */ #define EXIST 53 /* EXIST snd :: (Int,Type) */ -#define POLYREC 54 /* POLYREC: snd :: (Int,Type) */ -#define BIGLAM 55 /* BIGLAM: snd :: (vars,patterns) */ +#define POLYREC 54 /* POLYREC snd :: (Int,Type) */ +#define BIGLAM 55 /* BIGLAM snd :: (vars,patterns) */ +#define CDICTS 56 /* CDICTS snd :: ([Pred],Type) */ -#define LABC 60 /* LABC: snd :: (con,[(Vars,Type)]) */ -#define CONFLDS 61 /* CONFLDS: snd :: (con,[Field]) */ -#define UPDFLDS 62 /* UPDFLDS: snd :: (Exp,[con],[Field]) */ +#define LABC 60 /* LABC snd :: (con,[(Vars,Type)]) */ +#define CONFLDS 61 /* CONFLDS snd :: (con,[Field]) */ +#define UPDFLDS 62 /* UPDFLDS snd :: (Exp,[con],[Field]) */ #if TREX -#define RECORD 63 /* RECORD: snd :: [Val] */ -#define EXTCASE 64 /* EXTCASE: snd :: (Exp,Disc,Rhs) */ -#define RECSEL 65 /* RECSEL: snd :: Ext */ +#define RECORD 63 /* RECORD snd :: [Val] */ +#define EXTCASE 64 /* EXTCASE snd :: (Exp,Disc,Rhs) */ +#define RECSEL 65 /* RECSEL snd :: Ext */ #endif +#define IMPDEPS 68 /* IMPDEPS snd :: [Binding] */ #define QUALIDENT 70 /* Qualified identifier snd :: (Id,Id) */ #define HIDDEN 71 /* hiding import list snd :: [Entity] */ #define MODULEENT 72 /* module in export list snd :: con */ -#define ONLY 75 /* ONLY: snd :: Exp (used in parser)*/ -#define NEG 76 /* NEG: snd :: Exp (used in parser)*/ +#define INFIX 80 /* INFIX snd :: (see tidyInfix) */ +#define ONLY 81 /* ONLY snd :: Exp */ +#define NEG 82 /* NEG snd :: Exp */ -#define IMPDEPS 78 /* IMPDEFS: snd :: [Binding] */ - -#define STGVAR 80 /* STGVAR snd :: (StgRhs,info) */ -#define STGAPP 81 /* STGAPP snd :: (StgVar,[Arg]) */ -#define STGPRIM 82 /* STGPRIM snd :: (PrimOp,[Arg]) */ -#define STGCON 83 /* STGCON snd :: (StgCon,[Arg]) */ -#define PRIMCASE 84 /* PRIMCASE snd :: (Expr,[PrimAlt]) */ +#if SIZEOF_INTP != SIZEOF_INT +#define PTRCELL 90 /* C Heap Pointer snd :: (Int,Int) */ +#endif -/* Used when parsing GHC interface files */ -#define DICTAP 85 /* DICTTYPE snd :: (QClassId,[Type]) */ +#define STGVAR 92 /* STGVAR snd :: (StgRhs,info) */ +#define STGAPP 93 /* STGAPP snd :: (StgVar,[Arg]) */ +#define STGPRIM 94 /* STGPRIM snd :: (PrimOp,[Arg]) */ +#define STGCON 95 /* STGCON snd :: (StgCon,[Arg]) */ +#define PRIMCASE 96 /* PRIMCASE snd :: (Expr,[PrimAlt]) */ /* Last constructor tag must be less than SPECMIN */ @@ -287,6 +324,10 @@ extern Ptr ptrOf Args((Cell)); #define DOTDOT 106 /* ".." in import/export list */ +#if BIGNUMS +#define ZERONUM 108 /* The zero bignum (see POSNUM, NEGNUM) */ +#endif + #define NAME 110 /* whatIs code for isName */ #define TYCON 111 /* whatIs code for isTycon */ #define CLASS 112 /* whatIs code for isClass */ @@ -301,14 +342,17 @@ extern Ptr ptrOf Args((Cell)); #endif #define SIGDECL 120 /* Signature declaration */ -#define PREDEFINED 121 /* predefined name, not yet filled */ +#define FIXDECL 121 /* Fixity declaration */ +#define FUNBIND 122 /* Function binding */ +#define PATBIND 123 /* Pattern binding */ -#define DATATYPE 130 /* datatype type constructor */ -#define NEWTYPE 131 /* newtype type constructor */ -#define SYNONYM 132 /* synonym type constructor */ -#define RESTRICTSYN 133 /* synonym with restricted scope */ +#define DATATYPE 130 /* Datatype type constructor */ +#define NEWTYPE 131 /* Newtype type constructor */ +#define SYNONYM 132 /* Synonym type constructor */ +#define RESTRICTSYN 133 /* Synonym with restricted scope */ -#define NODEPENDS 135 /* stop calculation of deps in type check*/ +#define NODEPENDS 135 /* Stop calculation of deps in type check*/ +#define PREDEFINED 136 /* Predefined name, not yet filled */ /* -------------------------------------------------------------------------- * Tuple data/type constructors: @@ -355,6 +399,9 @@ extern Ext mkExt Args((Text)); #define MODMIN (OFFMIN+NUM_OFFSETS) +#if IGNORE_MODULES +#define setCurrModule(m) doNothing() +#else /* !IGNORE_MODULES */ #define isModule(c) (MODMIN<=(c) && (c)<TYCMIN) #define mkModule(n) (MODMIN+(n)) #define module(n) tabModule[(n)-MODMIN] @@ -392,6 +439,9 @@ extern Module findModule Args((Text)); extern Module findModid Args((Cell)); extern Void setCurrModule Args((Module)); +#define isPrelude(m) (m==modulePrelude) +#endif /* !IGNORE_MODULES */ + /* -------------------------------------------------------------------------- * Type constructor names: * ------------------------------------------------------------------------*/ @@ -404,13 +454,13 @@ extern Void setCurrModule Args((Module)); struct strTycon { Text text; Int line; +#if !IGNORE_MODULES Module mod; /* module that defines it */ +#endif Int arity; Kind kind; /* kind (includes arity) of Tycon */ Cell what; /* DATATYPE/SYNONYM/RESTRICTSYN... */ Cell defn; - Name conToTag; /* used in derived code */ - Name tagToCon; Tycon nextTyconHash; }; @@ -420,7 +470,7 @@ extern Tycon newTycon Args((Text)); extern Tycon findTycon Args((Text)); extern Tycon addTycon Args((Tycon)); extern Tycon findQualTycon Args((Cell)); -extern Tycon addPrimTycon Args((Text,Kind,Int,Cell,Cell)); +extern Tycon addPrimTycon Args((Text,Kind,Int,Cell,Cell)); #define isSynonym(h) (isTycon(h) && tycon(h).what==SYNONYM) #define mkPolyType(n,t) pair(POLYTYPE,pair(n,t)) @@ -441,6 +491,8 @@ struct strName { Text text; Int line; Module mod; /* module that defines it */ + Syntax syntax; + Cell parent; Int arity; Int number; Cell type; @@ -483,10 +535,10 @@ extern struct strName DECTABLE(tabName); #define mfunOf(n) ((-1)-name(n).number) #define mfunNo(i) ((-1)-(i)) -extern Name newName Args((Text)); +extern Name newName Args((Text,Cell)); extern Name findName Args((Text)); extern Name addName Args((Name)); -extern Name findQualName Args((Int,Cell)); +extern Name findQualName Args((Cell)); extern Name addPrimCfun Args((Text,Int,Int,Int)); extern Int sfunPos Args((Name,Name)); @@ -494,7 +546,7 @@ extern Int sfunPos Args((Name,Name)); * Type class values: * ------------------------------------------------------------------------*/ -#define INSTMIN (NAMEMIN+NUM_NAME) /* instances */ +#define INSTMIN (NAMEMIN+NUM_NAME) /* instances */ #define isInst(c) (INSTMIN<=(c) && (c)<CLASSMIN) #define mkInst(n) (INSTMIN+(n)) #define instOf(c) ((Int)((c)-INSTMIN)) @@ -522,22 +574,24 @@ struct strInst { #define cclass(n) tabClass[(n)-CLASSMIN] struct strClass { - Text text; /* Name of class */ - Int line; /* Line where declaration begins */ - Module mod; /* module that defines it */ - Int level; /* Level in class hierarchy */ - Int arity; /* Number of arguments */ - Kinds kinds; /* Kinds of constructors in class */ - Cell head; /* Head of class */ - Name dcon; /* Dictionay constructor function */ - List supers; /* :: [Pred] */ - Int numSupers; /* length(supers) */ - List dsels; /* Superclass dictionary selectors */ - List members; /* :: [Name] */ - Int numMembers; /* length(members) */ - Name dbuild; /* Default dictionary builder */ - List defaults; /* :: [Name] */ - List instances; /* :: [Inst] */ + Text text; /* Name of class */ + Int line; /* Line where declaration begins */ +#if !IGNORE_MODULES + Module mod; /* module that declares it */ +#endif + Int level; /* Level in class hierarchy */ + Int arity; /* Number of arguments */ + Kinds kinds; /* Kinds of constructors in class */ + Cell head; /* Head of class */ + Name dcon; /* Dictionary constructor function */ + List supers; /* :: [Pred] */ + Int numSupers; /* length(supers) */ + List dsels; /* Superclass dictionary selectors */ + List members; /* :: [Name] */ + Int numMembers; /* length(members) */ + Name dbuild; /* Default dictionary builder */ + List defaults; /* :: [Name] */ + List instances; /* :: [Inst] */ }; extern struct strClass DECTABLE(tabClass); @@ -567,15 +621,20 @@ extern Inst findNextInst Args((Tycon,Inst)); * ------------------------------------------------------------------------*/ #define INTMIN (CHARMIN+NUM_CHARS) -#define INTMAX MAXPOSINT +#define INTMAX (MAXPOSINT) #define isSmall(c) (INTMIN<=(c)) #define INTZERO (INTMIN/2 + INTMAX/2) +#define MINSMALLINT (INTMIN - INTZERO) +#define MAXSMALLINT (INTMAX - INTZERO) #define mkDigit(c) ((Cell)((c)+INTMIN)) #define digitOf(c) ((Int)((c)-INTMIN)) extern Bool isInt Args((Cell)); extern Int intOf Args((Cell)); extern Cell mkInt Args((Int)); +#if BIGNUMS +extern Bool isBignum Args((Cell)); +#endif /* -------------------------------------------------------------------------- * Implementation of triples: @@ -601,26 +660,25 @@ extern Cell mkInt Args((Int)); #define tl(c) snd(c) extern Int length Args((List)); -extern List appendOnto Args((List,List)); /* destructive */ -extern List revDupOnto Args((List,List)); /* non-destructive */ -extern List dupListOnto Args((List,List)); /* non-destructive */ -extern List revOnto Args((List,List)); /* destructive */ -#define reverse(xs) revDupOnto((xs),NIL) /* non-destructive */ -#define dupList(xs) dupListOnto((xs),NIL) /* non-destructive */ -#define rev(xs) revOnto((xs),NIL) /* destructive */ +extern List appendOnto Args((List,List)); /* destructive */ +extern List dupOnto Args((List,List)); +extern List dupList Args((List)); +extern List revOnto Args((List, List)); /* destructive */ +#define rev(xs) revOnto((xs),NIL) /* destructive */ extern Cell cellIsMember Args((Cell,List)); extern Cell cellAssoc Args((Cell,List)); extern Cell cellRevAssoc Args((Cell,List)); extern Bool eqList Args((List,List)); extern Cell varIsMember Args((Text,List)); +extern Name nameIsMember Args((Text,List)); extern Cell intIsMember Args((Int,List)); -extern List replicate Args((Int,Cell)); -extern List diffList Args((List,List)); /* destructive */ -extern List deleteCell Args((List,Cell)); /* non-destructive */ -extern List take Args((Int,List)); /* destructive */ -extern List splitAt Args((Int,List)); /* non-destructive */ +extern List replicate Args((Int,Cell)); +extern List diffList Args((List,List)); /* destructive */ +extern List deleteCell Args((List,Cell)); /* non-destructive */ +extern List take Args((Int,List)); /* destructive */ +extern List splitAt Args((Int,List)); /* non-destructive */ extern Cell nth Args((Int,List)); -extern List removeCell Args((Cell,List)); /* destructive */ +extern List removeCell Args((Cell,List)); /* destructive */ /* The following macros provide `inline expansion' of some common ways of * traversing, using and modifying lists: @@ -629,20 +687,22 @@ extern List removeCell Args((Cell,List)); /* destructive */ * with identifiers used elsewhere. */ -#define mapBasic(_init,_step) {List Zs=(_init);\ - for(;nonNull(Zs);Zs=tl(Zs)) \ - _step;} -#define mapModify(_init,_step) mapBasic(_init,hd(Zs)=_step) +#define mapBasic(_init,_step) {List Zs=(_init);\ + for(;nonNull(Zs);Zs=tl(Zs)) \ + _step;} +#define mapModify(_init,_step) mapBasic(_init,hd(Zs)=_step) -#define mapProc(_f,_xs) mapBasic(_xs,_f(hd(Zs))) -#define map1Proc(_f,_a,_xs) mapBasic(_xs,_f(_a,hd(Zs))) -#define map2Proc(_f,_a,_b,_xs) mapBasic(_xs,_f(_a,_b,hd(Zs))) -#define map3Proc(_f,_a,_b,_c,_xs) mapBasic(_xs,_f(_a,_b,_c,hd(Zs))) +#define mapProc(_f,_xs) mapBasic(_xs,_f(hd(Zs))) +#define map1Proc(_f,_a,_xs) mapBasic(_xs,_f(_a,hd(Zs))) +#define map2Proc(_f,_a,_b,_xs) mapBasic(_xs,_f(_a,_b,hd(Zs))) +#define map3Proc(_f,_a,_b,_c,_xs) mapBasic(_xs,_f(_a,_b,_c,hd(Zs))) +#define map4Proc(_f,_a,_b,_c,_d,_xs) mapBasic(_xs,_f(_a,_b,_c,_d,hd(Zs))) -#define mapOver(_f,_xs) mapModify(_xs,_f(hd(Zs))) -#define map1Over(_f,_a,_xs) mapModify(_xs,_f(_a,hd(Zs))) -#define map2Over(_f,_a,_b,_xs) mapModify(_xs,_f(_a,_b,hd(Zs))) -#define map3Over(_f,_a,_b,_c,_xs) mapModify(_xs,_f(_a,_b,_c,hd(Zs))) +#define mapOver(_f,_xs) mapModify(_xs,_f(hd(Zs))) +#define map1Over(_f,_a,_xs) mapModify(_xs,_f(_a,hd(Zs))) +#define map2Over(_f,_a,_b,_xs) mapModify(_xs,_f(_a,_b,hd(Zs))) +#define map3Over(_f,_a,_b,_c,_xs) mapModify(_xs,_f(_a,_b,_c,hd(Zs))) +#define map4Over(_f,_a,_b,_c,_d,_xs) mapModify(_xs,_f(_a,_b,_c,_d,hd(Zs))) /* This is just what you want for functions with accumulating parameters */ #define mapAccum(_f,_acc,_xs) mapBasic(_xs,_acc=_f(_acc,hd(Zs))) @@ -655,8 +715,8 @@ extern List removeCell Args((Cell,List)); /* destructive */ * ------------------------------------------------------------------------*/ #define ap(f,x) pair(f,x) -#define ap1(f,x) ap(f,x) -#define ap2(f,x,y) ap(ap(f,x),y) +#define ap1(f,x) ap(f,x) +#define ap2(f,x,y) ap(ap(f,x),y) #define ap3(f,x,y,z) ap(ap(ap(f,x),y),z) #define fun(c) fst(c) #define arg(c) snd(c) @@ -692,6 +752,8 @@ extern StackPtr sp; #define drop() sp-- #define top() stack(sp) #define pushed(n) stack(sp-(n)) +#define topfun(f) top()=ap((f),top()) +#define toparg(x) top()=ap(top(),(x)) extern Void hugsStackOverflow Args((Void)); @@ -701,7 +763,11 @@ extern Void hugsStackOverflow Args((Void)); * ------------------------------------------------------------------------*/ extern Script startNewScript Args((String)); +extern Bool moduleThisScript Args((Module)); +extern Module moduleOfScript Args((Script)); +extern Bool isPreludeScript Args((Void)); extern Module lastModule Args((Void)); +extern Script scriptThisFile Args((Text)); extern Script scriptThisName Args((Name)); extern Script scriptThisTycon Args((Tycon)); extern Script scriptThisInst Args((Inst)); @@ -709,13 +775,187 @@ extern Script scriptThisClass Args((Class)); extern String fileOfModule Args((Module)); extern Void dropScriptsFrom Args((Script)); +/* -------------------------------------------------------------------------- + * I/O Handles: + * ------------------------------------------------------------------------*/ + +#if IO_HANDLES +#define HSTDIN 0 /* Numbers for standard handles */ +#define HSTDOUT 1 +#define HSTDERR 2 + +struct strHandle { /* Handle description and status flags */ + Cell hcell; /* Heap representation of handle (or NIL) */ + FILE *hfp; /* Corresponding file pointer */ + Int hmode; /* Current mode: see below */ +}; + +#define HCLOSED 0000 /* no I/O permitted */ +#define HSEMICLOSED 0001 /* semiclosed reads only */ +#define HREAD 0002 /* set to enable reads from handle */ +#define HWRITE 0004 /* set to enable writes to handle */ +#define HAPPEND 0010 /* opened in append mode */ + +extern Cell openHandle Args((String,Int,Bool)); +extern struct strHandle DECTABLE(handles); +#endif + +/* -------------------------------------------------------------------------- + * Malloc Pointers + * ------------------------------------------------------------------------*/ + +#if GC_MALLOCPTRS +struct strMallocPtr { /* Malloc Ptr description */ + Cell mpcell; /* Back pointer to MPCELL */ + Void *ptr; /* Pointer into C world */ + Int refCount; /* Reference count */ + Void (*cleanup) Args((Void *)); /* Code to free the C pointer */ +}; + +extern struct strMallocPtr mallocPtrs[]; +extern Cell mkMallocPtr Args((Void *, Void (*)(Void *))); +extern Void freeMallocPtr Args((Cell)); +extern Void incMallocPtrRefCnt Args((Int, Int)); + +#define mpOf(c) snd(c) +#define derefMP(c) (mallocPtrs[(Int)mpOf(c)].ptr) +#endif /* GC_MALLOCPTRS */ + +/* -------------------------------------------------------------------------- + * Weak Pointers + * ------------------------------------------------------------------------*/ + +#if GC_WEAKPTRS +#define mkWeakPtr(c) pair(WEAKCELL,pair(c,NIL)) +#define derefWeakPtr(c) fst(snd(c)) +#define nextWeakPtr(c) snd(snd(c)) + +extern List finalizers; +extern List liveWeakPtrs; + +#endif /* GC_WEAKPTRS */ + +/* -------------------------------------------------------------------------- + * Stable pointers + * ------------------------------------------------------------------------*/ + +#if GC_STABLEPTRS +extern Int mkStablePtr Args((Cell)); +extern Cell derefStablePtr Args((Int)); +extern Void freeStablePtr Args((Int)); +#endif /* GC_STABLEPTRS */ + +/* -------------------------------------------------------------------------- + * Plugins + * ------------------------------------------------------------------------*/ + +#if PLUGINS +/* This is an exact copy of the declaration found in GreenCard.h */ + +typedef int HugsStackPtr; +typedef int HugsStablePtr; +typedef Pointer HugsForeign; + +typedef struct { + + /* evaluate next argument */ + int (*getInt ) Args(()); + unsigned int (*getWord ) Args(()); + void* (*getAddr ) Args(()); + float (*getFloat ) Args(()); + double (*getDouble) Args(()); + char (*getChar ) Args(()); + HugsForeign (*getForeign) Args(()); + HugsStablePtr (*getStablePtr) Args(()); + + /* push part of result */ + void (*putInt ) Args((int)); + void (*putWord ) Args((unsigned int)); + void (*putAddr ) Args((void*)); + void (*putFloat ) Args((double)); + void (*putDouble) Args((double)); + void (*putChar ) Args((char)); + void (*putForeign) Args((HugsForeign, void (*)(HugsForeign))); + void (*putStablePtr) Args((HugsStablePtr)); + + /* return n values in IO monad or Id monad */ + void (*returnIO) Args((HugsStackPtr, int)); + void (*returnId) Args((HugsStackPtr, int)); + int (*runIO) Args((int)); + + /* free a stable pointer */ + void (*freeStablePtr) Args((HugsStablePtr)); + + /* register the prim table */ + void (*registerPrims) Args((struct primInfo*)); + + /* garbage collect */ + void (*garbageCollect) Args(()); + +} HugsAPI2; + +extern HugsAPI2* hugsAPI2 Args((Void)); +typedef Void (*InitModuleFun2) Args((HugsAPI2*)); + +typedef struct { + Name nameTrue, nameFalse; + Name nameNil, nameCons; + Name nameJust, nameNothing; + Name nameLeft, nameRight; + Name nameUnit; + Name nameIORun; + + Cell (*makeInt) Args((Int)); + + Cell (*makeChar) Args((Char)); + Char (*CharOf) Args((Cell)); + + Cell (*makeFloat) Args((FloatPro)); + Cell (*makeTuple) Args((Int)); + Pair (*pair) Args((Cell,Cell)); + + Cell (*mkMallocPtr) Args((Void *, Void (*)(Void *))); + Void *(*derefMallocPtr) Args((Cell)); + + Int (*mkStablePtr) Args((Cell)); + Cell (*derefStablePtr) Args((Int)); + Void (*freeStablePtr) Args((Int)); + + Void (*eval) Args((Cell)); + Cell (*evalWithNoError) Args((Cell)); + Void (*evalFails) Args((StackPtr)); + Int *whnfArgs; + Cell *whnfHead; + Int *whnfInt; + Float *whnfFloat; + + Void (*garbageCollect) Args(()); + Void (*stackOverflow) Args(()); + Void (*internal) Args((String)) HUGS_noreturn; + + Void (*registerPrims) Args((struct primInfo*)); + Name (*addPrimCfun) Args((Text,Int,Int,Cell)); + Text (*inventText) Args(()); + + Cell *(*Fst) Args((Cell)); + Cell *(*Snd) Args((Cell)); + + Cell *cellStack; + StackPtr *sp; +} HugsAPI1; + +extern HugsAPI1* hugsAPI1 Args((Void)); +typedef Void (*InitModuleFun1) Args((HugsAPI1*)); +#endif /* PLUGINS */ + + /* -------------------------------------------------------------------------- * Misc: * ------------------------------------------------------------------------*/ -extern Void setLastExpr Args((Cell)); -extern Cell getLastExpr Args((Void)); +extern Void setLastExpr Args((Cell)); +extern Cell getLastExpr Args((Void)); extern List addTyconsMatching Args((String,List)); -extern List addNamesMatching Args((String,List)); +extern List addNamesMatching Args((String,List)); /*-------------------------------------------------------------------------*/ diff --git a/ghc/interpreter/subst.c b/ghc/interpreter/subst.c index 955eabb1320d..8643df4b6c1f 100644 --- a/ghc/interpreter/subst.c +++ b/ghc/interpreter/subst.c @@ -1,11 +1,16 @@ -/* -*- mode: hugs-c; -*- */ + /* -------------------------------------------------------------------------- - * subst.c: Copyright (c) Mark P Jones 1991-1998. All rights reserved. - * See NOTICE for details and conditions of use etc... - * Hugs version 1.3c, March 1998 - * * Provides an implementation for the `current substitution' used during * type and kind inference in both static analysis and type checking. + * + * Hugs 98 is Copyright (c) Mark P Jones, Alastair Reid and the Yale + * Haskell Group 1994-99, and is distributed as Open Source software + * under the Artistic License; see the file "Artistic" that is included + * in the distribution for details. + * + * $RCSfile: subst.c,v $ + * $Revision: 1.3 $ + * $Date: 1999/02/03 17:08:42 $ * ------------------------------------------------------------------------*/ #include "prelude.h" @@ -51,6 +56,7 @@ static Bool local varToTypeBind Args((Tyvar *,Type,Int)); #if TREX static Bool local inserter Args((Type,Int,Type,Int)); static Int local remover Args((Text,Type,Int)); +static Int local tailVar Args((Type,Int)); #endif static Bool local kvarToVarBind Args((Tyvar *,Tyvar *)); static Bool local kvarToTypeBind Args((Tyvar *,Type,Int)); @@ -166,9 +172,9 @@ Int n; { /* all of kind STAR */ tyvars[numTyvars-n].bound = NIL; tyvars[numTyvars-n].kind = STAR; #ifdef DEBUG_TYPES - printf("new type variable: _%d ::: ",numTyvars-n); + Printf("new type variable: _%d ::: ",numTyvars-n); printKind(stdout,tyvars[numTyvars-n].kind); - putchar('\n'); + Putchar('\n'); #endif } return beta; @@ -183,9 +189,9 @@ Kind k; { /* specified kinds */ tyvars[numTyvars].bound = NIL; tyvars[numTyvars].kind = fst(k); #ifdef DEBUG_TYPES - printf("new type variable: _%d ::: ",numTyvars); + Printf("new type variable: _%d ::: ",numTyvars); printKind(stdout,tyvars[numTyvars].kind); - putchar('\n'); + Putchar('\n'); #endif numTyvars++; } @@ -317,9 +323,9 @@ Int o; { tyv->bound = t; tyv->offs = o; #ifdef DEBUG_TYPES - printf("binding type variable: _%d to ",vn); + Printf("binding type variable: _%d to ",vn); printType(stdout,debugType(t,o)); - putchar('\n'); + Putchar('\n'); #endif } @@ -396,7 +402,7 @@ Int *ao; { /* expansion returned in (*at,*ao) */ * Marking fixed variables in type expressions: * ------------------------------------------------------------------------*/ -Void clearMarks() { /* set all unbound type vars to */ +Void clearMarks() { /* Set all unbound type vars to */ Int i; /* unused generic variables */ for (i=0; i<numTyvars; ++i) if (!isBound(tyvar(i))) @@ -405,6 +411,15 @@ Void clearMarks() { /* set all unbound type vars to */ nextGeneric = 0; } +Void markAllVars() { /* Set all unbound type vars to */ + Int i; /* be fixed vars */ + for (i=0; i<numTyvars; ++i) + if (!isBound(tyvar(i))) + tyvar(i)->offs = FIXED_TYVAR; + genericVars = NIL; + nextGeneric = 0; +} + Void resetGenerics() { /* Reset all generic vars to unused*/ Int i; for (i=0; i<numTyvars; ++i) @@ -428,8 +443,10 @@ Void markType(t,o) /* mark fixed vars in type (t,o) */ Type t; Int o; { switch (whatIs(t)) { + case POLYTYPE : + case QUAL : #if TREX - case EXT :st + case EXT : #endif case TYCON : case TUPLE : return; @@ -450,8 +467,6 @@ Int o; { case RANK2 : markType(snd(snd(t)),o); return; - case POLYTYPE : /* No need to mark generic types */ - return; default : internal("markType"); } @@ -474,8 +489,11 @@ Type copyTyvar(vn) /* calculate most general form of */ Int vn; { /* type bound to given type var */ Tyvar *tyv = tyvar(vn); - if (isBound(tyv)) + if ((tyv->bound)==SKOLEM) { + return mkInt(vn); + } else if (tyv->bound) { return copyType(tyv->bound,tyv->offs); + } switch (tyv->offs) { case FIXED_TYVAR : return mkInt(vn); @@ -586,7 +604,7 @@ Int n; { Type a = arg(fun(t)); if (isPolyType(a)) a = dropRank1(a,alpha,n); - as = ap2(typeArrow,a,as); + as = fn(a,as); t = arg(t); } t = ap(RANK2,pair(r,revOnto(as,t))); @@ -659,7 +677,7 @@ Int m; { for (i=intOf(r); i>0; i--) { Type a = arg(fun(t)); a = isPolyType(a) ? liftRank1Body(a,m) : copyType(a,alpha); - as = ap2(typeArrow,a,as); + as = fn(a,as); t = arg(t); } t = ap(RANK2,pair(r,revOnto(as,copyType(t,alpha)))); @@ -738,7 +756,7 @@ Int o; { #endif } #ifdef DEBUG_KINDS - printf("getKind c = %d, whatIs=%d\n",c,whatIs(c)); + Printf("getKind c = %d, whatIs=%d\n",c,whatIs(c)); #endif internal("getKind"); return STAR;/* not reached */ @@ -842,7 +860,7 @@ Tyvar *tyv1, *tyv2; { tyv1->bound = aVar; tyv1->offs = tyvNum(tyv2); #ifdef DEBUG_TYPES - printf("vv binding tyvar: _%d to _%d\n",tyvNum(tyv1),tyvNum(tyv2)); + Printf("vv binding tyvar: _%d to _%d\n",tyvNum(tyv1),tyvNum(tyv2)); #endif } return TRUE; @@ -868,9 +886,9 @@ Int o; { /* have synonym as outermost constr*/ tyv->bound = t; tyv->offs = o; #ifdef DEBUG_TYPES - printf("vt binding type variable: _%d to ",tyvNum(tyv)); + Printf("vt binding type variable: _%d to ",tyvNum(tyv)); printType(stdout,debugType(t,o)); - putchar('\n'); + Putchar('\n'); #endif return TRUE; } @@ -914,23 +932,27 @@ un: if (tyv1) Int a2 = argCount; #ifdef DEBUG_TYPES - printf("tt unifying types: "); + Printf("tt unifying types: "); printType(stdout,debugType(t1,o1)); - printf(" with "); + Printf(" with "); printType(stdout,debugType(t2,o2)); - putchar('\n'); + Putchar('\n'); #endif - if (isOffset(h1) || isInt(h1)) h1=NIL; /* represent var by NIL*/ if (isOffset(h2) || isInt(h2)) h2=NIL; #if TREX if (isExt(h1) || isExt(h2)) { - if (a1==2 && isExt(h1) && a2==2 && isExt(h2)) - return inserter(fun(t1),o1,t2,o2) && - unify(arg(t1),o1,aVar, - remover(extText(h1),t2,o2)); - else { + if (a1==2 && isExt(h1) && a2==2 && isExt(h2)) { + if (extText(h1)==extText(h2)) { + return unify(arg(fun(t1)),o1,arg(fun(t2)),o2) && + unify(arg(t1),o1,arg(t2),o2); + } else { + return inserter(t1,o1,t2,o2) && + unify(arg(t1),o1,aVar, + remover(extText(h1),t2,o2)); + } + } else { unifyFails = "rows are not compatible"; return FALSE; } @@ -1001,23 +1023,35 @@ un: if (tyv1) } #if TREX -static Bool local inserter(ins,o,r,or) /* Insert field into row (r,or) */ -Type ins; /* inserter (ins,o), where ins is */ -Int o; /* an applic of an EXT to a type. */ +static Bool local inserter(r1,o1,r,o) /* Insert first field in (r1,o1) */ +Type r1; /* into row (r,o), both of which */ +Int o1; /* are known to begin with an EXT */ Type r; -Int or; { - Text labt = extText(fun(ins)); /* Find the text of the label */ +Int o; { + Text labt = extText(fun(fun(r1))); /* Find the text of the label */ +#ifdef DEBUG_TYPES + Printf("inserting "); + printType(stdout,debugType(r1,o1)); + Printf(" into "); + printType(stdout,debugType(r,o)); + Putchar('\n'); +#endif for (;;) { Tyvar *tyv; - deRef(tyv,r,or); + deRef(tyv,r,o); if (tyv) { - Int beta = newTyvars(1); /* Extend row with new field */ + Int beta; /* Test for common tail */ + if (tailVar(arg(r1),o1)==tyvNum(tyv)) { + unifyFails = "distinct rows have common tail"; + return FALSE; + } + beta = newTyvars(1); /* Extend row with new field */ tyvar(beta)->kind = ROW; - return varToTypeBind(tyv,ap(ins,mkInt(beta)),o); + return varToTypeBind(tyv,ap(fun(r1),mkInt(beta)),o1); } else if (isAp(r) && isAp(fun(r)) && isExt(fun(fun(r)))) { if (labt==extText(fun(fun(r))))/* Compare existing fields */ - return unify(arg(ins),o,extField(r),or); + return unify(arg(fun(r1)),o1,extField(r),o); r = extRow(r); /* Or skip to next field */ } else { /* Nothing else will match */ @@ -1034,6 +1068,11 @@ Int o; { Tyvar *tyv; Int beta = newTyvars(1); tyvar(beta)->kind = ROW; +#ifdef DEBUG_TYPES + Printf("removing %s from",textToStr(l)); + printType(stdout,debugType(r,o)); + Putchar('\n'); +#endif deRef(tyv,r,o); if (tyv || !isAp(r) || !isAp(fun(r)) || !isExt(fun(fun(r)))) internal("remover"); @@ -1044,10 +1083,30 @@ Int o; { bindTv(beta,r,o); return beta; } + + +static Int local tailVar(r,o) /* Find var at tail end of a row */ +Type r; +Int o; { + for (;;) { + Tyvar *tyv; + deRef(tyv,r,o); + if (tyv) { + return tyvNum(tyv); + } + else if (isAp(r) && isAp(fun(r)) && isExt(fun(fun(r)))) { + r = extRow(r); + } + else { + return (-1); + } + } +} #endif + Bool typeMatches(type,mt) /* test if type matches monotype mt*/ -Type type, mt; { + Type type, mt; { /* imported from STG Hugs */ Bool result; if (isPolyType(type) || whatIs(type)==QUAL) return FALSE; @@ -1059,6 +1118,27 @@ Type type, mt; { return result; } + +#if IO_MONAD +Bool isProgType(ks,type) /* Test if type is of the form */ +List ks; /* IO t for some t. */ +Type type; { + Bool result; + Int alpha; + Int beta; + if (isPolyType(type) || whatIs(type)==QUAL) + return FALSE; + emptySubstitution(); + alpha = newKindedVars(ks); + beta = newTyvars(1); + bindOnlyAbove(beta); + result = unify(type,alpha,typeProgIO,beta); + unrestrictBind(); + emptySubstitution(); + return result; +} +#endif + /* -------------------------------------------------------------------------- * Matching predicates: * @@ -1140,6 +1220,11 @@ Int o; { return pi1==pi; } +#if TREX +static Cell trexShow = NIL; /* Used to test for show on records*/ +static Cell trexEq = NIL; /* Used to test for eq on records */ +#endif + Inst findInstFor(pi,o) /* Find matching instance for pred */ Cell pi; /* (pi,o), or otherwise NIL. If a */ Int o; { /* match is found, then tyvars from*/ @@ -1162,10 +1247,10 @@ Int o; { /* match is found, then tyvars from*/ unrestrictBind(); #if TREX - { Int showRow = strcmp(textToStr(cclass(c).text),"ShowRecRow"); - Int eqRow = strcmp(textToStr(cclass(c).text),"EqRecRow"); + { Bool wantShow = (c==findQualClass(trexShow)); + Bool wantEither = wantShow || (c==findQualClass(trexEq)); - if (showRow==0 || eqRow==0) { /* Generate instances of */ + if (wantEither) { /* Generate instances of */ Type t = arg(pi); /* ShowRecRow and EqRecRow */ Tyvar *tyv; /* on the fly */ Cell e; @@ -1179,8 +1264,7 @@ Int o; { /* match is found, then tyvars from*/ break; } if (isNull(in)) - in = (showRow==0) ? addRecShowInst(c,e) - : addRecEqInst(c,e); + in = (wantShow ? addRecShowInst(c,e) : addRecEqInst(c,e)); typeOff = newKindedVars(extKind); bindTv(typeOff,arg(fun(t)),o); bindTv(typeOff+1,arg(t),o); @@ -1298,7 +1382,7 @@ Tyvar *tyv1, *tyv2; { /* for kind variable bindings */ tyv1->bound = aVar; tyv1->offs = tyvNum(tyv2); #ifdef DEBUG_KINDS - printf("vv binding kvar: _%d to _%d\n",tyvNum(tyv1),tyvNum(tyv2)); + Printf("vv binding kvar: _%d to _%d\n",tyvNum(tyv1),tyvNum(tyv2)); #endif } return TRUE; @@ -1312,9 +1396,9 @@ Int o; { /* have synonym as outermost constr*/ tyv->bound = t; tyv->offs = o; #ifdef DEBUG_KINDS - printf("vt binding kind variable: _%d to ",tyvNum(tyv)); + Printf("vt binding kind variable: _%d to ",tyvNum(tyv)); printType(stdout,debugType(t,o)); - putchar('\n'); + Putchar('\n'); #endif return TRUE; } @@ -1340,11 +1424,11 @@ Int o1,o2; { return kvarToTypeBind(kyv2,k1,o1); /* k2 variable, k1 not */ else { #ifdef DEBUG_KINDS - printf("unifying kinds: "); + Printf("unifying kinds: "); printType(stdout,debugType(k1,o1)); - printf(" with "); + Printf(" with "); printType(stdout,debugType(k2,o2)); - putchar('\n'); + Putchar('\n'); #endif if (k1==STAR && k2==STAR) /* k1, k2 not vars */ return TRUE; @@ -1472,6 +1556,10 @@ Int what; { mark(typeIs); mark(predsAre); mark(genericVars); +#if TREX + mark(trexShow); + mark(trexEq); +#endif break; case INSTALL : substitution(RESET); @@ -1481,6 +1569,12 @@ Int what; { simpleKindCache[i] = NIL; varKindCache[i] = NIL; } +#if TREX + trexShow = mkQCon(findText("Trex"), + findText("ShowRecRow")); + trexEq = mkQCon(findText("Trex"), + findText("EqRecRow")); +#endif break; } } diff --git a/ghc/interpreter/subst.h b/ghc/interpreter/subst.h index 40f38c4d6b30..195b9261c11d 100644 --- a/ghc/interpreter/subst.h +++ b/ghc/interpreter/subst.h @@ -1,10 +1,15 @@ -/* -*- mode: hugs-c; -*- */ + /* -------------------------------------------------------------------------- - * subst.h: Copyright (c) Mark P Jones 1991-1998. All rights reserved. - * See NOTICE for details and conditions of use etc... - * Hugs version 1.3c, March 1998 - * * Definitions for substitution data structure and operations. + * + * Hugs 98 is Copyright (c) Mark P Jones, Alastair Reid and the Yale + * Haskell Group 1994-99, and is distributed as Open Source software + * under the Artistic License; see the file "Artistic" that is included + * in the distribution for details. + * + * $RCSfile: subst.h,v $ + * $Revision: 1.3 $ + * $Date: 1999/02/03 17:08:43 $ * ------------------------------------------------------------------------*/ typedef struct { /* Each type variable contains: */ @@ -28,8 +33,8 @@ extern List btyvars; /* explicitly scoped type vars */ #define tyvar(n) (tyvars+(n)) /* nth type variable */ #define tyvNum(t) ((t)-tyvars) /* and the corresp. inverse funct. */ #define isBound(t) (((t)->bound) && ((t)->bound!=SKOLEM)) -#define aVar mkOffset(0) /* Simple skeleton for type var */ -#define bVar mkOffset(1) /* Simple skeleton for type var */ +#define aVar mkOffset(0) /* Simple skeletons for type vars */ +#define bVar mkOffset(1) #define enterBtyvs() btyvars = cons(NIL,btyvars) #define leaveBtyvs() btyvars = tl(btyvars) @@ -62,6 +67,7 @@ extern Cell getDerefHead Args((Type,Int)); extern Void expandSyn Args((Tycon, Int, Type *, Int *)); extern Void clearMarks Args((Void)); +extern Void markAllVars Args((Void)); extern Void resetGenerics Args((Void)); extern Void markTyvar Args((Int)); extern Void markType Args((Type,Int)); @@ -103,6 +109,4 @@ extern Inst findInstFor Args((Cell,Int)); extern Bool sameSchemes Args((Type,Type)); -extern Bool typeMatches Args((Type,Type)); - /*-------------------------------------------------------------------------*/ diff --git a/ghc/interpreter/timer.c b/ghc/interpreter/timer.c index 0b0e697957dc..fc2d407a1080 100644 --- a/ghc/interpreter/timer.c +++ b/ghc/interpreter/timer.c @@ -1,4 +1,7 @@ -/* -*- mode: hugs-c; -*- */ +<<<<<<<<<<<<<< variant A + +>>>>>>>>>>>>>> variant B +======= end of combination /* -------------------------------------------------------------------------- * This file provides a simple mechanism for measuring elapsed time on Unix * machines (more precisely, on any machine with an rusage() function). @@ -21,13 +24,14 @@ * optimizations, means that there are much more significant overheads than * can be accounted for by small variations in Hugs code. * - * Copyright (c) The University of Nottingham and Yale University, 1994-1997. - * All rights reserved. See NOTICE for details and conditions of use etc... - * Hugs version 1.4, December 1997 + * Hugs 98 is Copyright (c) Mark P Jones, Alastair Reid and the Yale + * Haskell Group 1994-99, and is distributed as Open Source software + * under the Artistic License; see the file "Artistic" that is included + * in the distribution for details. * * $RCSfile: timer.c,v $ - * $Revision: 1.2 $ - * $Date: 1998/12/02 13:22:46 $ + * $Revision: 1.3 $ + * $Date: 1999/02/03 17:08:43 $ * ------------------------------------------------------------------------*/ diff --git a/ghc/interpreter/translate.c b/ghc/interpreter/translate.c index 5bac3c1c3d5b..d87fa3efcbe4 100644 --- a/ghc/interpreter/translate.c +++ b/ghc/interpreter/translate.c @@ -8,24 +8,18 @@ * Hugs version 1.4, December 1997 * * $RCSfile: translate.c,v $ - * $Revision: 1.3 $ - * $Date: 1999/01/13 16:47:26 $ + * $Revision: 1.4 $ + * $Date: 1999/02/03 17:08:44 $ * ------------------------------------------------------------------------*/ #include "prelude.h" #include "storage.h" +#include "backend.h" #include "connect.h" #include "errors.h" -#include "stg.h" -#include "compiler.h" -#include "pmc.h" /* for discrArity */ -#include "hugs.h" /* for debugCode */ -#include "type.h" /* for conToTagType, tagToConType */ #include "link.h" -#include "pp.h" #include "dynamic.h" #include "Assembler.h" -#include "translate.h" /* ---------------------------------------------------------------- */ @@ -155,7 +149,7 @@ StgExpr failExpr; } case GUARDED: { - List guards = reverse(snd(e)); + List guards = rev(snd(e)); e = failExpr; for(; nonNull(guards); guards=tl(guards)) { Cell g = hd(guards); @@ -492,6 +486,8 @@ static StgExpr forceArgs( List is, List args, StgExpr e ) return e; } +#if 0 +ToDo: reinstate eventually /* \ v -> case v of { ...; Ci _ _ -> i; ... } */ Void implementConToTag(t) Tycon t; { @@ -592,6 +588,7 @@ Tycon t; { if (etxt) free(etxt); } } +#endif Void implementCfun(c,scs) /* Build implementation for constr */ Name c; /* fun c. scs lists integers (1..)*/ @@ -826,7 +823,10 @@ String r_reps; { /* box results */ if (strcmp(r_reps,"B") == 0) { - StgPrimAlt altF = mkStgPrimAlt(singleton(mkStgPrimVar(mkInt(0),mkStgRep(INT_REP),NIL)), + StgPrimAlt altF = mkStgPrimAlt(singleton( + mkStgPrimVar(mkInt(0), + mkStgRep(INT_REP),NIL) + ), nameFalse); StgPrimAlt altT = mkStgPrimAlt(singleton(mkStgPrimVar(NIL,mkStgRep(INT_REP),NIL)), nameTrue); @@ -839,7 +839,7 @@ String r_reps; { b_args = mkBoxedVars(a_reps); u_args = mkUnboxedVars(a_reps); if (addState) { - List actual_args = appendOnto(extra_args,dupListOnto(u_args,singleton(s0))); + List actual_args = appendOnto(extra_args,dupOnto(u_args,singleton(s0))); StgRhs rhs = makeStgLambda(singleton(s0), unboxVars(a_reps,b_args,u_args, mkStgPrimCase(mkStgPrim(op,actual_args), diff --git a/ghc/interpreter/type.c b/ghc/interpreter/type.c index a95b8d02f8f8..40b7c03da7c0 100644 --- a/ghc/interpreter/type.c +++ b/ghc/interpreter/type.c @@ -1,36 +1,109 @@ -/* -*- mode: hugs-c; -*- */ + /* -------------------------------------------------------------------------- - * type.c: Copyright (c) Mark P Jones 1991-1998. All rights reserved. - * See NOTICE for details and conditions of use etc... - * Hugs version 1.3c, March 1998 - * * This is the Hugs type checker + * + * Hugs 98 is Copyright (c) Mark P Jones, Alastair Reid and the Yale + * Haskell Group 1994-99, and is distributed as Open Source software + * under the Artistic License; see the file "Artistic" that is included + * in the distribution for details. + * + * $RCSfile: type.c,v $ + * $Revision: 1.3 $ + * $Date: 1999/02/03 17:08:44 $ * ------------------------------------------------------------------------*/ #include "prelude.h" #include "storage.h" +#include "backend.h" #include "connect.h" -#include "input.h" -#include "static.h" -#include "hugs.h" /* for target */ -#include "pat.h" /* for failFree */ #include "errors.h" #include "subst.h" -#include "type.h" -#include "link.h" #include "Assembler.h" /* for AsmCTypes */ /*#define DEBUG_TYPES*/ /*#define DEBUG_KINDS*/ /*#define DEBUG_DEFAULTS*/ /*#define DEBUG_SELS*/ -/*#define DEBUG_CODE*/ /*#define DEBUG_DEPENDS*/ /*#define DEBUG_DERIVING*/ +/*#define DEBUG_CODE*/ Bool catchAmbigs = FALSE; /* TRUE => functions with ambig. */ /* types produce error */ +#if 1 +//ToDo: perhaps this should be somewhere else (link.c?) +//all this stuff came with 98, and not STG +Type typeArrow, typeList; /* Important primitive types */ +Type typeUnit; + +Module modulePrelude; + +static Type typeInt, typeDouble; +static Type typeInteger, typeAddr; +static Type typeString, typeChar; +static Type typeBool, typeMaybe; +static Type typeOrdering; + +Class classEq, classOrd; /* `standard' classes */ +Class classIx, classEnum; +Class classShow, classRead; +#if EVAL_INSTANCES +Class classEval; +#endif +Class classBounded; + +Class classReal, classIntegral; /* `numeric' classes */ +Class classRealFrac, classRealFloat; +Class classFractional, classFloating; +Class classNum; + +List stdDefaults; /* standard default values */ + +Name nameFromInt, nameFromDouble; /* coercion of numerics */ +Name nameFromInteger; +Name nameEq, nameCompare; /* derivable names */ +Name nameLe; +Name nameShowsPrec; +Name nameReadsPrec; +Name nameMinBnd, nameMaxBnd; +Name nameIndex, nameInRange; +Name nameRange; +Name nameMult, namePlus; +Name nameTrue, nameFalse; /* primitive boolean constructors */ +Name nameNil, nameCons; /* primitive list constructors */ +Name nameJust, nameNothing; /* primitive Maybe constructors */ +Name nameLeft, nameRight; /* primitive Either constructors */ +Name nameUnit; /* primitive Unit type constructor */ +Name nameLT, nameEQ; /* Ordering constructors */ +Name nameGT; +Class classMonad; /* Monads */ +Name nameReturn, nameBind; /* for translating monad comps */ +Name nameMFail; +Name nameGt; /* for readsPrec */ +#if EVAL_INSTANCES +Name nameStrict, nameSeq; /* Members of class Eval */ +#endif + +#if IO_MONAD +Type typeProgIO; /* For the IO monad, IO () */ +Name nameUserErr; /* loosely coupled IOError cfuns */ +Name nameNameErr, nameSearchErr; +#endif +#if IO_HANDLES +Name nameWriteErr, nameIllegal; +Name nameEOFErr; +#endif + +#if TREX +Type typeNoRow; /* Empty row */ +Type typeRec; /* Record formation */ +Name nameNoRec; /* Empty record */ +#endif + +//end ToDo +#endif + /* -------------------------------------------------------------------------- * Local function prototypes: * ------------------------------------------------------------------------*/ @@ -53,6 +126,8 @@ static Void local enterPendingBtyvs Args((Void)); static Void local leavePendingBtyvs Args((Void)); static Cell local patBtyvs Args((Cell)); static Void local doneBtyvs Args((Int)); +static Void local enterSkolVars Args((Void)); +static Void local leaveSkolVars Args((Int,Type,Int,Int)); static Void local typeError Args((Int,Cell,Cell,String,Type,Int)); static Void local reportTypeError Args((Int,Cell,Cell,String,Type,Type)); @@ -67,8 +142,8 @@ static Void local typeAlt Args((String,Cell,Cell,Type,Int,Int)); static Int local funcType Args((Int)); static Void local typeCase Args((Int,Int,Cell)); static Void local typeComp Args((Int,Type,Cell,List)); +static Cell local typeMonadComp Args((Int,Cell)); static Void local typeDo Args((Int,Cell)); -static Cell local compZero Args((List,Int)); static Void local typeConFlds Args((Int,Cell)); static Void local typeUpdFlds Args((Int,Cell)); static Cell local typeFreshPat Args((Int,Cell)); @@ -102,21 +177,26 @@ static Bool local equalTypes Args((Type,Type)); static Void local typeDefnGroup Args((List)); static Pair local typeSel Args((Name)); +static List offsetTyvarsIn Args((Type,List)); +static Type conToTagType Args((Tycon)); +static Type tagToConType Args((Tycon)); + + /* -------------------------------------------------------------------------- * Frequently used type skeletons: * ------------------------------------------------------------------------*/ -static Type arrow; /* mkOffset(0) -> mkOffset(1) */ +/* ToDo: move these to link.c and call them 'typeXXXX' */ + Type arrow; /* mkOffset(0) -> mkOffset(1) */ static Type boundPair; /* (mkOffset(0),mkOffset(0)) */ -static Type listof; /* [ mkOffset(0) ] */ + Type listof; /* [ mkOffset(0) ] */ static Type typeVarToVar; /* mkOffset(0) -> mkOffset(0) */ -static Cell predNum; /* Num (mkOffset(0)) */ -static Cell predFractional; /* Fractional (mkOffset(0)) */ -static Cell predIntegral; /* Integral (mkOffset(0)) */ + Cell predNum; /* Num (mkOffset(0)) */ + Cell predFractional; /* Fractional (mkOffset(0)) */ + Cell predIntegral; /* Integral (mkOffset(0)) */ static Kind starToStar; /* Type -> Type */ -static Cell predMonad; /* Monad (mkOffset(0)) */ -static Cell predMonad0; /* Monad0 (mkOffset(0)) */ + Cell predMonad; /* Monad (mkOffset(0)) */ /* -------------------------------------------------------------------------- * Assumptions: @@ -153,6 +233,8 @@ static List defnBounds; /*::[[(Var,Type)]] possibly ovrlded*/ static List varsBounds; /*::[[(Var,Type)]] not overloaded */ static List depends; /*::[?[Var]] dependents/NODEPENDS */ static List skolVars; /*::[[Var]] skolem vars */ +static List localEvs; /*::[[(Pred,offset,ev)]] */ +static List savedPs; /*::[[(Pred,offset,ev)]] */ static Cell dummyVar; /* Used to put extra tvars into ass*/ #define saveVarsAss() List saveAssump = hd(varsBounds) @@ -165,6 +247,8 @@ static Void local emptyAssumption() { /* set empty type assumption */ varsBounds = NIL; depends = NIL; skolVars = NIL; + localEvs = NIL; + savedPs = NIL; } static Void local enterBindings() { /* Add new level to assumption sets */ @@ -279,9 +363,9 @@ Cell v; { Int beta = newTyvars(1); addVarAssump(v,mkInt(beta)); #ifdef DEBUG_TYPES - printf("variable, assume "); + Printf("variable, assume "); printExp(stdout,v); - printf(" :: _%d\n",beta); + Printf(" :: _%d\n",beta); #endif return beta; } @@ -296,13 +380,19 @@ Type type; { ta = pair(POLYREC,pair(ta,type)); hd(defnBounds) = cons(pair(v,ta), hd(defnBounds)); #ifdef DEBUG_TYPES - printf("definition, assume "); + Printf("definition, assume "); printExp(stdout,v); - printf(" :: _%d\n",beta); + Printf(" :: _%d\n",beta); #endif bindTv(beta,typeIs,typeOff); /* Bind beta to new type skeleton */ } +/* -------------------------------------------------------------------------- + * Predicates: + * ------------------------------------------------------------------------*/ + +#include "preds.c" + /* -------------------------------------------------------------------------- * Bound and skolemized type variables: * ------------------------------------------------------------------------*/ @@ -360,7 +450,6 @@ Cell p; { snd(hd(bts)) = mkInt(beta); } } - skolVars = cons(NIL,skolVars); return p; } @@ -370,23 +459,54 @@ Int l; { hd(pendingBtyvs) = cons(pair(mkInt(l),hd(btyvars)),hd(pendingBtyvs)); hd(btyvars) = NIL; } +} + +static Void local enterSkolVars() { + skolVars = cons(NIL,skolVars); + localEvs = cons(NIL,localEvs); + savedPs = cons(preds,savedPs); + preds = NIL; +} + +static Void local leaveSkolVars(l,t,o,m) +Int l; +Type t; +Int o; +Int m; { + if (nonNull(hd(localEvs))) { /* Check for local predicates */ + List sks = hd(skolVars); + List sps = NIL; + if (isNull(sks)) { + internal("leaveSkolVars"); + } + markAllVars(); /* Mark all variables in current */ + do { /* substitution, then unmark sks. */ + tyvar(intOf(fst(hd(sks))))->offs = UNUSED_GENERIC; + sks = tl(sks); + } while (nonNull(sks)); + sps = elimPredsUsing(hd(localEvs),sps); + preds = revOnto(preds,sps); + } if (nonNull(hd(skolVars))) { /* Check that Skolem vars do not */ List vs; /* escape their scope */ + Int i = 0; clearMarks(); /* Look for occurences in the */ - markType(typeIs,typeOff); /* result type */ + for (; i<m; i++) /* inferred type */ + markTyvar(o+i); + markType(t,o); for (vs=hd(skolVars); nonNull(vs); vs=tl(vs)) { Int vn = intOf(fst(hd(vs))); if (tyvar(vn)->offs == FIXED_TYVAR) { Cell tv = copyTyvar(vn); - Type t = copyType(typeIs,typeOff); - ERRMSG(l) "Existentially quantified variable in result type" + Type ty = liftRank2(t,o,m); + ERRMSG(l) "Existentially quantified variable in inferred type" ETHEN - ERRTEXT "\nvariable : " ETHEN ERRTYPE(tv); - ERRTEXT "\nfrom pattern : " ETHEN ERREXPR(snd(hd(vs))); - ERRTEXT "\nresult type : " ETHEN ERRTYPE(t); + ERRTEXT "\n*** Variable : " ETHEN ERRTYPE(tv); + ERRTEXT "\n*** From pattern : " ETHEN ERREXPR(snd(hd(vs))); + ERRTEXT "\n*** Result type : " ETHEN ERRTYPE(ty); ERRTEXT "\n" EEND; } @@ -399,22 +519,20 @@ Int l; { for (vs=hd(skolVars); nonNull(vs); vs=tl(vs)) { Int vn = intOf(fst(hd(vs))); if (tyvar(vn)->offs == FIXED_TYVAR) { - ERRMSG(l) "Existentially quantified variable from pattern " + ERRMSG(l) + "Existentially quantified variable escapes from pattern " ETHEN ERREXPR(snd(hd(vs))); - ERRTEXT " appears in enclosing assumptions" /*so there!*/ + ERRTEXT "\n" EEND; } } } + localEvs = tl(localEvs); skolVars = tl(skolVars); + preds = revOnto(preds,hd(savedPs)); + savedPs = tl(savedPs); } -/* -------------------------------------------------------------------------- - * Predicates: - * ------------------------------------------------------------------------*/ - -#include "preds.c" - /* -------------------------------------------------------------------------- * Type errors: * ------------------------------------------------------------------------*/ @@ -433,9 +551,9 @@ Int o; { /* type inferred is (typeIs,typeOff) */ { List vs = genericVars; for (; nonNull(vs); vs=tl(vs)) { Int v = intOf(hd(vs)); - printf("%c :: ", ('a'+tyvar(v)->offs)); + Printf("%c :: ", ('a'+tyvar(v)->offs)); printKind(stdout,tyvar(v)->kind); - putchar('\n'); + Putchar('\n'); } } #endif @@ -511,13 +629,13 @@ Cell e; { static int number = 0; Cell retv; int mynumber = number++; - printf("%d) to check: ",mynumber); + Printf("%d) to check: ",mynumber); printExp(stdout,e); - putchar('\n'); + Putchar('\n'); retv = mytypeExpr(l,e); - printf("%d) result: ",mynumber); + Printf("%d) result: ",mynumber); printType(stdout,debugType(typeIs,typeOff)); - putchar('\n'); + Putchar('\n'); return retv; } static Cell local mytypeExpr(l,e) /* Determine type of expr/pattern */ @@ -545,35 +663,29 @@ Cell e; { case TUPLE : typeTuple(e); break; -#if OVERLOADED_CONSTANTS - case BIGCELL : { Int alpha = newTyvars(1); +#if BIGNUMS + case POSNUM : + case ZERONUM : + case NEGNUM : { Int alpha = newTyvars(1); inferType(aVar,alpha); - return ap2(nameFromInteger, - assumeEvid(predNum,alpha), - e); + return ap(ap(nameFromInteger, + assumeEvid(predNum,alpha)), + e); } - +#endif case INTCELL : { Int alpha = newTyvars(1); inferType(aVar,alpha); - return ap2(nameFromInt, - assumeEvid(predNum,alpha), - e); + return ap(ap(nameFromInt, + assumeEvid(predNum,alpha)), + e); } case FLOATCELL : { Int alpha = newTyvars(1); inferType(aVar,alpha); - return ap2(nameFromDouble, - assumeEvid(predFractional,alpha), - e); + return ap(ap(nameFromDouble, + assumeEvid(predFractional,alpha)), + e); } -#else - case BIGCELL : inferType(typeBignum,0); - break; - case INTCELL : inferType(typeInt,0); - break; - case FLOATCELL : inferType(typeFloat,0); - break; -#endif case STRCELL : inferType(typeString,0); break; @@ -592,10 +704,9 @@ Cell e; { #if TREX case EXT : { Int beta = newTyvars(2); Cell pi = ap(e,aVar); - Type t = fn(mkOffset(0), - fn(ap(typeRec,mkOffset(1)), - ap(typeRec,ap2(e,mkOffset(0), - mkOffset(1))))); + Type t = fn(aVar, + fn(ap(typeRec,bVar), + ap(typeRec,ap(ap(e,aVar),bVar)))); tyvar(beta+1)->kind = ROW; inferType(t,beta); return ap(e,assumeEvid(pi,beta+1)); @@ -616,9 +727,11 @@ Cell e; { break; case LETREC : enterBindings(); + enterSkolVars(); mapProc(typeBindings,fst(snd(e))); snd(snd(e)) = typeExpr(l,snd(snd(e))); leaveBindings(); + leaveSkolVars(l,typeIs,typeOff,0); break; case FINLIST : { Int beta = newTyvars(1); @@ -633,12 +746,7 @@ Cell e; { case DOCOMP : typeDo(l,e); break; - case COMP : { Int beta = newTyvars(1); - typeComp(l,listof,snd(e),snd(snd(e))); - bindTv(beta,typeIs,typeOff); - inferType(listof,beta); - } - break; + case COMP : return typeMonadComp(l,e); case CASE : { Int beta = newTyvars(2); /* discr result */ check(l,fst(snd(e)),NIL,discr,aVar,beta); @@ -659,8 +767,8 @@ Cell e; { case RECSEL : { Int beta = newTyvars(2); Cell pi = ap(snd(e),aVar); Type t = fn(ap(typeRec, - ap2(snd(e),mkOffset(0), - mkOffset(1))),aVar); + ap(ap(snd(e),aVar), + bVar)),aVar); tyvar(beta+1)->kind = ROW; inferType(t,beta); return ap(e,assumeEvid(pi,beta+1)); @@ -744,19 +852,35 @@ Cell e; { /* requires polymorphism, qualified*/ instantiate(typeIs); /* Deal with polymorphism ... */ if (nonNull(predsAre)) { /* ... and with qualified types. */ - Cell evs = NIL; - for (; nonNull(predsAre); predsAre=tl(predsAre)) + List evs = NIL; + for (; nonNull(predsAre); predsAre=tl(predsAre)) { evs = cons(assumeEvid(hd(predsAre),typeOff),evs); - if (!isName(h) || !isCfun(h)) + } + if (!isName(h) || !isCfun(h)) { h = applyToArgs(h,rev(evs)); + } + } + + if (whatIs(typeIs)==CDICTS) { /* Deal with local dictionaries */ + List evs = makePredAss(fst(snd(typeIs)),typeOff); + List ps = evs; + typeIs = snd(snd(typeIs)); + for (; nonNull(ps); ps=tl(ps)) { + h = ap(h,thd3(hd(ps))); + } + if (tcMode==EXPRESSION) { + preds = revOnto(evs,preds); + } else { + hd(localEvs) = revOnto(evs,hd(localEvs)); + } } if (whatIs(typeIs)==EXIST) { /* Deal with existential arguments */ Int n = intOf(fst(snd(typeIs))); typeIs = snd(snd(typeIs)); - if (!isCfun(h) || n>typeFree) + if (!isCfun(getHead(h)) || n>typeFree) { internal("typeAp2"); - else if (tcMode!=EXPRESSION) { + } else if (tcMode!=EXPRESSION) { Int alpha = typeOff + typeFree; for (; n>0; n--) { bindTv(alpha-n,SKOLEM,0); @@ -927,6 +1051,7 @@ Int m; { Bool added = FALSE; saveVarsAss(); + enterSkolVars(); if (whatIs(t)==RANK2) { if (n<(nr2=intOf(fst(snd(t))))) { ERRMSG(l) "Definition requires at least %d parameters on lhs", @@ -990,6 +1115,7 @@ Int m; { restoreVarsAss(); doneBtyvs(l); + leaveSkolVars(l,origt,o,m); } static Int local funcType(n) /*return skeleton for function type*/ @@ -1009,7 +1135,7 @@ Cell c; { /* rhs :: (var,beta+1) */ static String caseExpr = "case expression"; saveVarsAss(); - + enterSkolVars(); fst(c) = typeFreshPat(l,patBtyvs(fst(c))); shouldBe(l,fst(c),NIL,casePat,aVar,beta); snd(c) = typeRhs(snd(c)); @@ -1017,6 +1143,7 @@ Cell c; { /* rhs :: (var,beta+1) */ restoreVarsAss(); doneBtyvs(l); + leaveSkolVars(l,typeIs,typeOff,0); } static Void local typeComp(l,m,e,qs) /* type check comprehension */ @@ -1038,20 +1165,24 @@ List qs; { break; case QWHERE : enterBindings(); + enterSkolVars(); mapProc(typeBindings,snd(q)); typeComp(l,m,e,qs1); leaveBindings(); + leaveSkolVars(l,typeIs,typeOff,0); break; case FROMQUAL : { Int beta = newTyvars(1); saveVarsAss(); check(l,snd(snd(q)),NIL,genQual,m,beta); + enterSkolVars(); fst(snd(q)) = typeFreshPat(l,patBtyvs(fst(snd(q)))); shouldBe(l,fst(snd(q)),NIL,genQual,aVar,beta); typeComp(l,m,e,qs1); restoreVarsAss(); doneBtyvs(l); + leaveSkolVars(l,typeIs,typeOff,0); } break; @@ -1062,6 +1193,24 @@ List qs; { } } +static Cell local typeMonadComp(l,e) /* type check monad comprehension */ +Int l; +Cell e; { + Int alpha = newTyvars(1); + Int beta = newTyvars(1); + Cell mon = ap(mkInt(beta),aVar); + Cell m = assumeEvid(predMonad,beta); + tyvar(beta)->kind = starToStar; +#if !MONAD_COMPS + bindTv(beta,typeList,0); +#endif + + typeComp(l,mon,snd(e),snd(snd(e))); + bindTv(alpha,typeIs,typeOff); + inferType(mon,alpha); + return ap(MONADCOMP,pair(m,snd(e))); +} + static Void local typeDo(l,e) /* type check do-notation */ Int l; Cell e; { @@ -1074,20 +1223,7 @@ Cell e; { typeComp(l,mon,snd(e),snd(snd(e))); shouldBe(l,fst(snd(e)),NIL,finGen,mon,alpha); - snd(e) = pair(pair(m,compZero(snd(snd(e)),beta)),snd(e)); -} - -static Cell local compZero(qs,beta) /* return evidence for Monad0 beta */ -List qs; /* if needed for qualifiers qs */ -Int beta; { - for (; nonNull(qs); qs=tl(qs)) - switch (whatIs(hd(qs))) { - case FROMQUAL : if (failFree(fst(snd(hd(qs))))) - break; - /* intentional fall-thru */ - case BOOLQUAL : return assumeEvid(predMonad0,beta); - } - return NIL; + snd(e) = pair(m,snd(e)); } static Void local typeConFlds(l,e) /* Type check a construction */ @@ -1330,23 +1466,24 @@ Cell b; { /* gp with restricted overloading */ if (isVar(fst(b))) { /* function-binding? */ Cell t = fst(snd(b)); - if (whatIs(t)==IMPDEPS) /* Discard implicitly typed deps */ + if (whatIs(t)==IMPDEPS) { /* Discard implicitly typed deps */ fst(snd(b)) = t = NIL; /* in a restricted binding group. */ + } fst(snd(b)) = localizeBtyvs(t); restrictedAss(rhsLine(snd(hd(snd(snd(b))))), fst(b), t); - } - else { /* pattern-binding? */ + } else { /* pattern-binding? */ List vs = fst(b); List ts = fst(snd(b)); Int line = rhsLine(snd(snd(snd(b)))); - for (; nonNull(vs); vs=tl(vs)) + for (; nonNull(vs); vs=tl(vs)) { if (nonNull(ts)) { restrictedAss(line,hd(vs),hd(ts)=localizeBtyvs(hd(ts))); ts = tl(ts); - } - else + } else { restrictedAss(line,hd(vs),NIL); + } + } } } @@ -1408,20 +1545,20 @@ List bs; { fst(snd(hd(bs1))) = NIL; /* reset imps type fields */ #ifdef DEBUG_DEPENDS - printf("Binding group:"); + Printf("Binding group:"); for (bs1=imps; nonNull(bs1); bs1=tl(bs1)) { - printf(" [imp:"); + Printf(" [imp:"); for (bs=hd(bs1); nonNull(bs); bs=tl(bs)) - printf(" %s",textToStr(textOf(fst(hd(bs))))); - printf("]"); + Printf(" %s",textToStr(textOf(fst(hd(bs))))); + Printf("]"); } if (nonNull(exps)) { - printf(" [exp:"); + Printf(" [exp:"); for (bs=exps; nonNull(bs); bs=tl(bs)) - printf(" %s",textToStr(textOf(fst(hd(bs))))); - printf("]"); + Printf(" %s",textToStr(textOf(fst(hd(bs))))); + Printf("]"); } - printf("\n"); + Printf("\n"); #endif /* ---------------------------------------------------------------------- @@ -1458,8 +1595,9 @@ List bs; { normPreds(line); savePreds = elimOuterPreds(savePreds); - if (nonNull(preds) && resolveDefs(genvarAllAss(hd(defnBounds)))) + if (nonNull(preds) && resolveDefs(genvarAllAss(hd(defnBounds)))) { savePreds = elimOuterPreds(savePreds); + } map1Proc(genBind,preds,hd(imps)); if (nonNull(preds)) { @@ -1467,6 +1605,8 @@ List bs; { map1Proc(qualifyBinding,preds,hd(imps)); } + h98CheckType(line,"inferred type", + fst(hd(hd(defnBounds))),snd(hd(hd(defnBounds)))); hd(varsBounds) = revOnto(hd(defnBounds),hd(varsBounds)); } @@ -1528,8 +1668,10 @@ List bs; { resetGenerics(); /* Make sure we're general enough */ ps = copyPreds(ps); t = generalize(ps,liftRank2(t,o,m)); + if (!sameSchemes(t,fst(snd(b)))) tooGeneral(line,fst(b),fst(snd(b)),t); + h98CheckType(line,"inferred type",fst(b),t); if (nonNull(preds)) /* Check context was strong enough */ cantEstablish(line,extbind,fst(b),t,ps); @@ -1722,18 +1864,18 @@ Inst in; { /* member functions for instance in*/ for (ps=supers; nonNull(ps); ps=tl(ps)) { /* Superclass dictionaries */ Cell pi = hd(ps); - Cell ev = scEntail(params,fst3(pi),intOf(snd3(pi))); - if (isNull(ev)) - ev = inEntail(evids,fst3(pi),intOf(snd3(pi))); + Cell ev = scEntail(params,fst3(pi),intOf(snd3(pi)),0); + if (isNull(ev)) + ev = inEntail(evids,fst3(pi),intOf(snd3(pi)),0); if (isNull(ev)) { clearMarks(); ERRMSG(inst(in).line) "Cannot build superclass instance" ETHEN ERRTEXT "\n*** Instance : " ETHEN - ERRPRED(copyPred(inst(in).head,beta)); + ERRPRED(copyPred(inst(in).head,beta)); ERRTEXT "\n*** Context supplied : " ETHEN - ERRCONTEXT(copyPreds(params)); + ERRCONTEXT(copyPreds(params)); ERRTEXT "\n*** Required superclass : " ETHEN - ERRPRED(copyPred(fst3(pi),intOf(snd3(pi)))); + ERRPRED(copyPred(fst3(pi),intOf(snd3(pi)))); ERRTEXT "\n" EEND; } @@ -1814,13 +1956,13 @@ Int beta; { Type rt; #ifdef DEBUG_TYPES - printf("Type check member: "); + Printf("Type check member: "); printExp(stdout,mem); - printf(" :: "); + Printf(" :: "); printType(stdout,name(mem).type); - printf("\nfor the instance: "); + Printf("\nfor the instance: "); printPred(stdout,head); - printf("\n"); + Printf("\n"); #endif instantiate(name(mem).type); /* Find required type */ @@ -1835,9 +1977,9 @@ Int beta; { rt = generalize(qs,liftRank2(t,o,m)); #ifdef DEBUG_TYPES - printf("Required type is: "); + Printf("Required type is: "); printType(stdout,rt); - printf("\n"); + Printf("\n"); #endif hd(defnBounds) = NIL; /* Type check each alternative */ @@ -1869,9 +2011,9 @@ Int beta; { ps = copyPreds(ps); t = generalize(ps,liftRank2(t,o,m)); #ifdef DEBUG_TYPES - printf("Inferred type is: "); + Printf("Inferred type is: "); printType(stdout,t); - printf("\n"); + Printf("\n"); #endif if (!sameSchemes(t,rt)) tooGeneral(line,mem,rt,t); @@ -1905,10 +2047,14 @@ Cell b; { Int l = rhsLine(snd(pb)); tcMode = OLD_PATTERN; + enterPendingBtyvs(); + fst(pb) = patBtyvs(fst(pb)); check(l,fst(pb),NIL,lhsPat,aVar,beta); tcMode = EXPRESSION; snd(pb) = typeRhs(snd(pb)); shouldBe(l,rhsExpr(snd(pb)),NIL,rhs,aVar,beta); + doneBtyvs(l); + leavePendingBtyvs(); } } @@ -1930,11 +2076,20 @@ Cell e; { break; case LETREC : enterBindings(); + enterSkolVars(); mapProc(typeBindings,fst(snd(e))); snd(snd(e)) = typeRhs(snd(snd(e))); leaveBindings(); + leaveSkolVars(rhsLine(snd(snd(e))),typeIs,typeOff,0); break; + case RSIGN : fst(snd(e)) = typeRhs(fst(snd(e))); + shouldBe(rhsLine(fst(snd(e))), + rhsExpr(fst(snd(e))),NIL, + "result type", + snd(snd(e)),0); + return fst(snd(e)); + default : snd(e) = typeExpr(intOf(fst(e)),snd(e)); break; } @@ -1958,6 +2113,7 @@ Cell rhs; { switch (whatIs(rhs)) { case GUARDED : return snd(snd(hd(snd(rhs)))); case LETREC : return rhsExpr(snd(snd(rhs))); + case RSIGN : return rhsExpr(fst(snd(rhs))); default : return snd(rhs); } } @@ -1967,6 +2123,7 @@ Cell rhs; { /* a right hand side */ switch (whatIs(rhs)) { case GUARDED : return intOf(fst(hd(snd(rhs)))); case LETREC : return rhsLine(snd(snd(rhs))); + case RSIGN : return rhsLine(fst(snd(rhs))); default : return intOf(fst(rhs)); } } @@ -2010,9 +2167,9 @@ Type dt; { #ifdef DEBUG_TYPES printExp(stdout,v); - printf(" :: "); + Printf(" :: "); printType(stdout,snd(ass)); - printf("\n"); + Printf("\n"); #endif } @@ -2058,11 +2215,11 @@ Type t; { /* with qualifying preds qs */ } t = mkPolyType(k,t); #ifdef DEBUG_KINDS - printf("Generalized type: "); + Printf("Generalized type: "); printType(stdout,t); - printf(" ::: "); + Printf(" ::: "); printKind(stdout,k); - printf("\n"); + Printf("\n"); #endif } return t; @@ -2127,6 +2284,7 @@ Bool useDefs; { /* using defaults if reqd */ ctxt = copyPreds(preds); type = generalize(ctxt,copyType(type,beta)); inputExpr = qualifyExpr(0,preds,inputExpr); + h98CheckType(0,"inferred type",inputExpr,type); typeChecker(RESET); emptySubstitution(); return type; @@ -2140,6 +2298,7 @@ Void typeCheckDefns() { /* Type check top level bindings */ typeChecker(RESET); emptySubstitution(); + enterSkolVars(); enterBindings(); setGoal("Type checking",t); @@ -2191,6 +2350,14 @@ List bs; { /* (one top level scc) */ EEND; } + if (nonNull(hd(skolVars))) { + Cell b = hd(bs); + Name n = findName(isVar(fst(b)) ? textOf(fst(b)) : textOf(hd(fst(b)))); + Int l = nonNull(n) ? name(n).line : 0; + leaveSkolVars(l,typeUnit,0,0); + enterSkolVars(); + } + for (as=hd(varsBounds); nonNull(as); as=tl(as)) { Cell a = hd(as); /* add infered types to environment*/ Name n = findName(textOf(fst(a))); @@ -2213,9 +2380,9 @@ Name s; { /* particular selector, s. */ Int m; #ifdef DEBUG_SELS - printf("Selector %s, cns=",textToStr(name(s).text)); + Printf("Selector %s, cns=",textToStr(name(s).text)); printExp(stdout,cns); - putchar('\n'); + Putchar('\n'); #endif emptySubstitution(); @@ -2302,14 +2469,15 @@ Name s; { /* particular selector, s. */ map1Proc(qualify,preds,alts); #ifdef DEBUG_SELS - printf("Inferred arity = %d, type = ",name(s).arity); + Printf("Inferred arity = %d, type = ",name(s).arity); printType(stdout,name(s).type); - putchar('\n'); + Putchar('\n'); #endif return pair(s,alts); } + /* -------------------------------------------------------------------------- * Local function prototypes: * ------------------------------------------------------------------------*/ @@ -2320,7 +2488,7 @@ static Type local basicType Args((Char)); * * ------------------------------------------------------------------------*/ -List offsetTyvarsIn(t,vs) /* add list of offset tyvars in t */ +static List offsetTyvarsIn(t,vs) /* add list of offset tyvars in t */ Type t; /* to list vs */ List vs; { switch (whatIs(t)) { @@ -2347,6 +2515,7 @@ List vs; { static Type stateVar = NIL; static Type alphaVar = NIL; static Type betaVar = NIL; +static Type gammaVar = NIL; static Int nextVar = 0; static Void clearTyVars( void ) @@ -2354,6 +2523,7 @@ static Void clearTyVars( void ) stateVar = NIL; alphaVar = NIL; betaVar = NIL; + gammaVar = NIL; nextVar = 0; } @@ -2381,6 +2551,14 @@ static Type mkBetaVar( void ) return betaVar; } +static Type mkGammaVar( void ) +{ + if (isNull(gammaVar)) { + gammaVar = mkOffset(nextVar++); + } + return gammaVar; +} + static Type local basicType(k) Char k; { switch (k) { @@ -2445,10 +2623,13 @@ Char k; { return mkAlphaVar(); /* polymorphic */ case BETA_REP: return mkBetaVar(); /* polymorphic */ + case GAMMA_REP: + return mkGammaVar(); /* polymorphic */ default: printf("Kind: '%c'\n",k); internal("basicType"); } + assert(0); return 0; /* NOTREACHED */ } /* Generate type of primop based on list of arg types and result types: @@ -2508,7 +2689,7 @@ Type primType( Int /*AsmMonad*/ monad, String a_kinds, String r_kinds ) } /* forall a1 .. am. TC a1 ... am -> Int */ -Type conToTagType(t) +static Type conToTagType(t) Tycon t; { Type ty = t; List tvars = NIL; @@ -2526,7 +2707,7 @@ Tycon t; { } /* forall a1 .. am. Int -> TC a1 ... am */ -Type tagToConType(t) +static Type tagToConType(t) Tycon t; { Type ty = t; List tvars = NIL; @@ -2547,17 +2728,6 @@ Tycon t; { * Type checker control: * ------------------------------------------------------------------------*/ -Void mkTypes() -{ - arrow = fn(aVar,mkOffset(1)); - listof = ap(typeList,aVar); - predNum = ap(classNum,aVar); - predFractional = ap(classFractional,aVar); - predIntegral = ap(classIntegral,aVar); - predMonad = ap(classMonad,aVar); - predMonad0 = ap(classMonad0,aVar); -} - Void typeChecker(what) Int what; { switch (what) { @@ -2572,6 +2742,8 @@ Int what; { mark(depends); mark(pendingBtyvs); mark(skolVars); + mark(localEvs); + mark(savedPs); mark(dummyVar); mark(preds); mark(stdDefaults); @@ -2584,13 +2756,77 @@ Int what; { mark(predIntegral); mark(starToStar); mark(predMonad); - mark(predMonad0); +#if IO_MONAD + mark(typeProgIO); +#endif break; case INSTALL : typeChecker(RESET); dummyVar = inventVar(); + +#if !IGNORE_MODULES + modulePrelude = newModule(textPrelude); + setCurrModule(modulePrelude); +#endif + starToStar = simpleKind(1); + + typeUnit = addPrimTycon(findText("()"), + STAR,0,DATATYPE,NIL); + typeArrow = addPrimTycon(findText("(->)"), + simpleKind(2),2, + DATATYPE,NIL); + typeList = addPrimTycon(findText("[]"), + starToStar,1, + DATATYPE,NIL); + + arrow = fn(aVar,bVar); + listof = ap(typeList,aVar); + boundPair = ap(ap(mkTuple(2),aVar),aVar); + + nameUnit = addPrimCfun(findText("()"),0,0,typeUnit); + tycon(typeUnit).defn + = singleton(nameUnit); + + nameNil = addPrimCfun(findText("[]"),0,1, + mkPolyType(starToStar, + listof)); + nameCons = addPrimCfun(findText(":"),2,2, + mkPolyType(starToStar, + fn(aVar, + fn(listof, + listof)))); + name(nameCons).syntax + = mkSyntax(RIGHT_ASS,5); + + tycon(typeList).defn + = cons(nameNil,cons(nameCons,NIL)); + typeVarToVar = fn(aVar,aVar); +#if TREX + typeNoRow = addPrimTycon(findText("EmptyRow"), + ROW,0,DATATYPE,NIL); + typeRec = addPrimTycon(findText("Rec"), + pair(ROW,STAR),1, + DATATYPE,NIL); + nameNoRec = addPrimCfun(findText("EmptyRec"),0,0, + ap(typeRec,typeNoRow)); +#else + /* bogus definitions to avoid changing the prelude */ + addPrimCfun(findText("Rec"), 0,0,typeUnit); + addPrimCfun(findText("EmptyRow"), 0,0,typeUnit); + addPrimCfun(findText("EmptyRec"), 0,0,typeUnit); +#endif +#if IO_MONAD + nameUserErr = addPrimCfun(inventText(),1,1,NIL); + nameNameErr = addPrimCfun(inventText(),1,2,NIL); + nameSearchErr= addPrimCfun(inventText(),1,3,NIL); +#if IO_HANDLES + nameIllegal = addPrimCfun(inventText(),0,4,NIL); + nameWriteErr = addPrimCfun(inventText(),1,5,NIL); + nameEOFErr = addPrimCfun(inventText(),1,6,NIL); +#endif +#endif break; } } -- GitLab