1. 27 Aug, 2001 1 commit
  2. 24 Aug, 2001 1 commit
  3. 20 Aug, 2001 1 commit
    • simonpj's avatar
      [project @ 2001-08-20 11:00:18 by simonpj] · e80b5e1a
      simonpj authored
      Remove the identity-substitution "optimisation" from zip_ty_env.
      	-- There used to be a special case for when
      	--	ty == TyVarTy tv
      	-- (a not-uncommon case) in which case the substitution was dropped.
      	-- But the type-tidier changes the print-name of a type variable without
      	-- changing the unique, and that led to a bug.   Why?  Pre-tidying, we had
      	-- a type {Foo t}, where Foo is a one-method class.  So Foo is really a newtype.
      	-- And it happened that t was the type variable of the class.  Post-tiding,
      	-- it got turned into {Foo t2}.  The ext-core printer expanded this using
      	-- sourceTypeRep, but that said "Oh, t == t2" because they have the same unique,
      	-- and so generated a rep type mentioning t not t2.
      	-- Simplest fix is to nuke the "optimisation"
  4. 17 Aug, 2001 1 commit
    • apt's avatar
      [project @ 2001-08-17 17:18:51 by apt] · 1dfaee31
      apt authored
      How I spent my summer vacation.
      The format of the primops.txt.pp file has been enhanced to allow
      (latex-style) primop descriptions to be included.  There is a new flag
      to genprimopcode that generates documentation including these
      descriptions. A first cut at descriptions of the more interesting
      primops has been made, and the file has been reordered a bit.
      31-bit words
      The front end now can cope with the possibility of 31-bit (or even 30-bit)
      Int# and Word# types.  The only current use of this is to generate
      external .core files that can be translated into OCAML source files
      (OCAML uses a one-bit tag to distinguish integers from pointers).
      The only way to get this right now is by hand-defining the preprocessor
      symbol WORD_SIZE_IN_BITS, which is normally set automatically from
      the familiar WORD_SIZE_IN_BYTES.
      Just in case 31-bit words are used, we now have Int32# and Word32# primitive types
      and an associated family of operators, paralleling the existing 64-bit
      stuff.  Of course, none of the operators actually need to be implemented
      in the absence of a 31-bit backend.
      There has also been some minor re-jigging of the 32 vs. 64 bit stuff.
      See the description at the top of primops.txt.pp file for more details.
      Note that, for the first time, the *type* of a primop can now depend
      on the target word size.
      Also, the family of primops intToInt8#, intToInt16#, etc.
      have been renamed narrow8Int#, narrow16Int#, etc., to emphasize
      that they work on Int#'s and don't actually convert between types.
      As another part of coping with the possibility of 31-bit ints,
      the addr2Int# and int2Addr# primops are now thoroughly deprecated
      (and not even defined in the 31-bit case) and all uses
      of them have been removed except from the (deprecated) module
      Addr# should now be treated as a proper abstract type, and has these suitable operators:
      nullAddr# : Int# -> Addr# (ignores its argument; nullary primops cause problems at various places)
      plusAddr# :  Addr# -> Int# -> Addr#
      minusAddr : Addr# -> Addr# -> Int#
      remAddr# : Addr# -> Int# -> Int#
      Obviously, these don't allow completely arbitrary offsets if 31-bit ints are
      in use, but they should do for all practical purposes.
      It is also still possible to generate an address constant, and there is a built-in rule
      that makes use of this to remove the nullAddr# calls.
      There is a new compile flag -fno-code that causes GHC to quit after generating .hi files
      and .core files (if requested) but before generating STG.
      Z-encoded names for tuples have been rationalized; e.g.,
      Z3H now means an unboxed 3-tuple, rather than an unboxed
      tuple with 3 commas (i.e., a 4-tuple)!
      Removed misc. litlits in hslibs/lang
      Misc. small changes to external core format.  The external core description
      has also been substantially updated, and incorporates the automatically-generated
      primop documentation; its in the repository at /papers/ext-core/core.tex.
      A little make-system addition to allow passing CPP options to compiler and
      library builds.
  5. 25 Jul, 2001 1 commit
    • simonpj's avatar
      [project @ 2001-07-25 09:19:41 by simonpj] · a47868d5
      simonpj authored
      	Another long-standing infelicity!
      CoreTidy was throwing away demand info on let-binders.
      This meant that CorePrep would build a let (thunk) instead of
      a case, even if the Id is sure to be demanded.
      Easily fixed by making CoreTidy retain the demand info.
      This demand-analysis stuff is having the excellent side effect
      of flushing out performance bugs!
  6. 23 Jul, 2001 1 commit
    • simonpj's avatar
      [project @ 2001-07-23 10:54:46 by simonpj] · f6cd95ff
      simonpj authored
      	Switch to the new demand analyser
      This commit makes the new demand analyser the main beast,
      with the old strictness analyser as a backup.  When
      DEBUG is on, the old strictness analyser is run too, and the
      results compared.
      WARNING: this isn't thorougly tested yet, so expect glitches.
      Delay updating for a few days if the HEAD is mission critical
      for you.
      But do try it out.  I'm away for 2.5 weeks from Thursday, so
      it would be good to shake out any glaring bugs before then.
  7. 20 Jul, 2001 3 commits
    • simonpj's avatar
      [project @ 2001-07-20 16:48:20 by simonpj] · 5d095cc1
      simonpj authored
      This commit adds the very convenient function
        Subst.substTyWith :: [TyVar] -> [Type] -> Type -> Type
      and uses it in various places.
    • simonpj's avatar
      [project @ 2001-07-20 16:47:55 by simonpj] · e3defabc
      simonpj authored
      	More newtype squashing
      Recursive newtypes were confusing the worker/wrapper generator.
      This is because I originally got rid of opaque newtypes altogether,
      then put them back for recursive ones only, and forgot to reinstate
      the cunning stuff in the w/w stuff.
      (Discovered by Sigbjorn; thanks!)
    • simonpj's avatar
      [project @ 2001-07-20 10:05:37 by simonpj] · 98a74c9d
      simonpj authored
      	Correct a bug in exprArity
      This long-standing bug meant that exprArity gave over-pessimistic
      answers.  e.g.
      	\x -> f x
      where nothing is known about f.  We were getting
      	0 (for f)
      	-1 (for the argument)
      	+1 (for the lambda)
      The right answer is of course 1.
  8. 19 Jul, 2001 1 commit
  9. 17 Jul, 2001 1 commit
    • simonpj's avatar
      [project @ 2001-07-17 15:28:30 by simonpj] · fdc83001
      simonpj authored
      	First cut at the demand analyser
      This demand analyser is intended to replace the strictness/absence
      analyser, and the CPR analyser.
      This commit adds it to the compiler, but in an entirely non-invasive
      	If you build the compiler without -DDEBUG,
      	you won't get it at all.
      	If you build the compiler with -DDEBUG,
      	you'll get the demand analyser, but the existing
      	strictness analyser etc are still there.  All the
      	demand analyser does is to compare its output with
      	the existing stuff and report differences.
      There's no cross-module stuff for demand info yet.
      The strictness/demand info is put the IdInfo as
      Eventually we'll remove the old ones.
  10. 28 Jun, 2001 1 commit
  11. 25 Jun, 2001 3 commits
    • simonpj's avatar
      [project @ 2001-06-25 14:36:04 by simonpj] · a5ded1f8
      simonpj authored
      Import wibbles
    • simonpj's avatar
      [project @ 2001-06-25 08:09:57 by simonpj] · d069cec2
      simonpj authored
      	Squash newtypes
      This commit squashes newtypes and their coerces, from the typechecker
      onwards.  The original idea was that the coerces would not get in the
      way of optimising transformations, but despite much effort they continue
      to do so.   There's no very good reason to retain newtype information
      beyond the typechecker, so now we don't.
      Main points:
      * The post-typechecker suite of Type-manipulating functions is in
      types/Type.lhs, as before.   But now there's a new suite in types/TcType.lhs.
      The difference is that in the former, newtype are transparent, while in
      the latter they are opaque.  The typechecker should only import TcType,
      not Type.
      * The operations in TcType are all non-monadic, and most of them start with
      "tc" (e.g. tcSplitTyConApp).  All the monadic operations (used exclusively
      by the typechecker) are in a new module, typecheck/TcMType.lhs
      * I've grouped newtypes with predicate types, thus:
      	data Type = TyVarTy Tyvar | ....
      		  | SourceTy SourceType
      	data SourceType = NType TyCon [Type]
      			| ClassP Class [Type]
      			| IParam Type
      [SourceType was called PredType.]  This is a little wierd in some ways,
      because NTypes can't occur in qualified types.   However, the idea is that
      a SourceType is a type that is opaque to the type checker, but transparent
      to the rest of the compiler, and newtypes fit that as do implicit parameters
      and dictionaries.
      * Recursive newtypes still retain their coreces, exactly as before. If
      they were transparent we'd get a recursive type, and that would make
      various bits of the compiler diverge (e.g. things which do type comparison).
      * I've removed types/Unify.lhs (non-monadic type unifier and matcher),
      merging it into TcType.
      Ditto typecheck/TcUnify.lhs (monadic unifier), merging it into TcMType.
    • simonpj's avatar
      [project @ 2001-06-25 08:08:32 by simonpj] · 3622a7de
      simonpj authored
      	Add a new case optimisation
      I found that lib/std/PrelCError had a case-expression that was
      generating terrible code.   Something like this
      	x | p `is` 1 -> e1
      	  | p `is` 2 -> e2
      where @is@ was something like
      	p `is` n = p /= (-1) && p == n
      This gave rise to a horrible sequence of cases
      	case p of
      	  (-1) -> $j p
      	  1    -> e1
      	  DEFAULT -> $j p
      and similarly in cascade for all the join points!
      Solution: add the following transformation:
      	case e of		=====>     case e of
      	  C _ -> <expr>			     D v -> ....v....
      	  D v -> ....v....		     DEFAULT -> <expr>
      	  DEFAULT -> <expr>
      The point is that we merge common RHSs, at least for the DEFAULT case.
      [One could do something more elaborate but I've never seen it needed.]
      This transformation is implemented in SimplUtils.mkCase
      *** WARNING ***
      	To make this transformation easy, I have switched the convention
      	for DEFAULT clauses.  They must now occur FIRST in the list of
      	alternatives for a Core case expression.  (The semantics is
      	unchanged: they still are a catch-all case.)
      	The reason is that DEFAULT clauses sometimes need special treatment,
      	and it's a lot easier to find them at the front.
      	The easiest way to be insensitive to this change is to use
      	CoreUtils.findDefault to pull the default clause out.
      I've made the (surprisingly few) changes consequent on this changed
      of convention, but they aren't in this commit.  Instead they are part
      of the big commit on newtypes I'm doing at the same time.
  12. 12 Jun, 2001 1 commit
  13. 04 Jun, 2001 1 commit
    • simonpj's avatar
      [project @ 2001-06-04 16:49:15 by simonpj] · f08a180a
      simonpj authored
      	Make exprArity give the right answer
      		MERGE INTO 5.00.2
      This fixes a fairly long-standing bug in exprArity, dating from
      the time we allowed arguments to be non-atoms. If f had arity
      2, it was saying that
      	f (factorial x)
      had arity 2, as well, which is plain wrong.
  14. 01 Jun, 2001 1 commit
  15. 25 May, 2001 1 commit
    • simonpj's avatar
      [project @ 2001-05-25 08:55:03 by simonpj] · 3af411e9
      simonpj authored
      	Wibbles to Don's runtime-types commit
      There was an upside down predicate which utterly broke the compiler.
      While I was about it
      * I changed the global flag to
        with command line option
      	-fruntime-types (was -fkeep-stg-types)
      * I moved isRuntimeArg, isRuntimeVar to CoreSyn
  16. 24 May, 2001 2 commits
    • dsyme's avatar
      [project @ 2001-05-24 15:10:19 by dsyme] · 508aae27
      dsyme authored
      Various changes for ILX backend and type-passing compilers, code reviewed by SimonPJ
    • simonpj's avatar
      [project @ 2001-05-24 13:59:09 by simonpj] · cbdeae8f
      simonpj authored
      	More stuff towards generalising 'foreign' declarations
      This is the second step towards generalising 'foreign' declarations to
      handle langauges other than C.  Now I can handle
        foreign import dotnet type T
        foreign import dotnet "void Foo.Baz.f( T )" f :: T -> IO ()
      			** WARNING **
      	I believe that all the foreign stuff for C should
      	work exactly as before, but I have not tested it
      	thoroughly.  Sven, Manuel, Marcin: please give it a
      	whirl and compare old with new output.
      Lots of fiddling around with data types.  The main changes are
      * HsDecls.lhs
      	The ForeignDecl type and its friends
      	Note also the ForeignType constructor to TyClDecl
      * ForeignCall.lhs
      	Here's where the stuff that survives right through
      	compilation lives
      * TcForeign.lhs DsForeign.lhs
      	Substantial changes driven by the new data types
      * Parser.y ParseIface.y RnSource
      	Just what you'd expect
  17. 22 May, 2001 1 commit
    • simonpj's avatar
      [project @ 2001-05-22 13:43:14 by simonpj] · f16228e4
      simonpj authored
      	Towards generalising 'foreign' declarations
      This is a first step towards generalising 'foreign' declarations to
      handle langauges other than C.  Quite a lot of files are touched,
      but nothing has really changed.  Everything should work exactly as
      	But please be on your guard for ccall-related bugs.
      Main things
      Basic data types: ForeignCall.lhs
      * Remove absCSyn/CallConv.lhs
      * Add prelude/ForeignCall.lhs.  This defines the ForeignCall
        type and its variants
      * Define ForeignCall.Safety to say whether a call is unsafe
        or not (was just a boolean).  Lots of consequential chuffing.
      * Remove all CCall stuff from PrimOp, and put it in ForeignCall
      Take CCallOp out of the PrimOp type (where it was always a glitch)
      * Add IdInfo.FCallId variant to the type IdInfo.GlobalIdDetails,
      	along with predicates Id.isFCallId, Id.isFCallId_maybe
      * Add StgSyn.StgOp, to sum PrimOp with FCallOp, because it
        *is* useful to sum them together in Stg and AbsC land.  If
        nothing else, it minimises changes.
      Also generally rename "CCall" stuff to "FCall" where it's generic
      to all foreign calls.
  18. 18 May, 2001 1 commit
    • simonpj's avatar
      [project @ 2001-05-18 08:46:18 by simonpj] · b4775e5e
      simonpj authored
      	Get unbox-strict-fields right
      The problem was that when a library was compiled *without* -funbox-strict-fields,
      and the main program was compiled *with* that flag, we were wrongly treating
      the fields of imported data types as unboxed.
      To fix this I added an extra constructor to StrictnessMark to express whether
      the "!" annotation came from an interface file (don't fiddle) or a source
      file (decide whether to unbox).
      On the way I tided things up:
      * StrictnessMark moves to Demand.lhs, and doesn't have the extra DataCon
        fields that kept it in DataCon before.
      * HsDecls.BangType has one constructor, not three, with a StrictnessMark field.
      * DataCon keeps track of its strictness signature (dcRepStrictness), but not
        its "user strict marks" (which were never used)
      * All the functions, like getUniquesDs, that used to take an Int saying how
        many uniques to allocate, now return an infinite list. This saves arguments
        and hassle.  But it involved touching quite a few files.
      * rebuildConArgs takes a list of Uniques to use as its unique supply.  This
        means I could combine DsUtils.rebuildConArgs with MkId.rebuildConArgs
        (hooray; the main point of the previous change)
      I also tidied up one or two error messages
  19. 14 May, 2001 2 commits
    • sewardj's avatar
      [project @ 2001-05-14 16:40:54 by sewardj] · 7e8d0a0b
      sewardj authored
      Record-selector unfolding fix #2
    • simonpj's avatar
      [project @ 2001-05-14 12:03:41 by simonpj] · ea8abf4c
      simonpj authored
      ****	MERGE WITH 5.00 BRANCH     ********
      	Expose record selectors with correct unfoldings
      The problem was that there was that with "ghc --make" we were
      passing on record selectors to importing modules in their un-tidied
      form.  The idea was that they have very stylised bindings so they
      don't need tidying.  But they do, because they may mention error
      messages that get floated out.
      Here's the comment from CoreTidy.lhs
      -- MINOR-HACK ALERT: we *do* tidy record selectors.  Reason: they mention error
      -- messages, which may be floated out:
      --	x_field pt = case pt of
      --			Rect x y -> y
      --			Pol _ _  -> error "buggle wuggle"
      -- The error message will be floated out so we'll get
      --	lvl5 = error "buggle wuggle"
      --	x_field pt = case pt of
      --			Rect x y -> y
      --			Pol _ _  -> lvl5
      -- When this happens, it's vital that the Id exposed to importing modules
      -- (by ghci) mentions lvl5 in its unfolding, not the un-tidied version.
      -- What about the Id in the TyCon?  It probably shouldn't be in the TyCon at
      -- all, but in any case it will have the error message inline so it won't matter.
  20. 04 May, 2001 1 commit
  21. 02 May, 2001 1 commit
  22. 01 May, 2001 1 commit
  23. 30 Apr, 2001 1 commit
    • qrczak's avatar
      [project @ 2001-04-30 20:07:49 by qrczak] · 09d0b4a4
      qrczak authored
      Fix the inlining bug: exprIsConApp_maybe didn't recognize constructor
      applications inside notes.
      I'm not sure if it's the right place to fix. Should notes be ignored
      in other uses of collectArgs? Perhaps they should be ignored inside
      the loop of collectArgs? And why the function marked as inline was
      not inlined even though it's not a constructor application?
  24. 05 Apr, 2001 1 commit
    • simonpj's avatar
      [project @ 2001-04-05 11:28:36 by simonpj] · f05b6981
      simonpj authored
      	Better arity stuff
      * CoreToStg now has a local function, predictArity, to
        predict the code-gen arity of a function. Better not to
        use CoreUtils.exprArity, because predictArity is a very
        local thing
      * CoreUtils.exprArity is freed to do a better job.  Comments
      exprArity is a cheap-and-cheerful version of exprEtaExpandArity.
      It tells how many things the expression can be applied to before doing
      any work.  It doesn't look inside cases, lets, etc.  The idea is that
      exprEtaExpandArity will do the hard work, leaving something that's easy
      for exprArity to grapple with.  In particular, Simplify uses exprArity to
      compute the ArityInfo for the Id.
      Originally I thought that it was enough just to look for top-level lambdas, but
      it isn't.  I've seen this
      	foo = PrelBase.timesInt
      We want foo to get arity 2 even though the eta-expander will leave it
      unchanged, in the expectation that it'll be inlined.  But occasionally it
      isn't, because foo is blacklisted (used in a rule).
      Similarly, see the ok_note check in exprEtaExpandArity.  So
      	f = __inline_me (\x -> e)
      won't be eta-expanded.
      And in any case it seems more robust to have exprArity be a bit more intelligent.
  25. 23 Mar, 2001 2 commits
    • simonpj's avatar
      [project @ 2001-03-23 10:47:21 by simonpj] · 08002107
      simonpj authored
      Comments, plus dead code elim
    • simonpj's avatar
      [project @ 2001-03-23 10:46:27 by simonpj] · 644c1be9
      simonpj authored
      	Correct size calculations for INLINE notes
      Amazingly, CoreUnfold.size_up wasn't treating an InlineMe note
      as small.  (InlineMe was only dealt with at top level.)  As
      the comment now says:
       	-- This can be important.  If you have an instance decl like this:
       	-- 	instance Foo a => Foo [a] where
       	--	   {-# INLINE op1, op2 #-}
       	--	   op1 = ...
       	--	   op2 = ...
       	-- then we'll get a dfun which is a pair of two INLINE lambdas
      This fixes a problem Manuel encountered.
  26. 19 Mar, 2001 4 commits
    • simonpj's avatar
      [project @ 2001-03-19 16:26:09 by simonpj] · e9c3ce32
      simonpj authored
      Comments only
    • simonpj's avatar
      [project @ 2001-03-19 16:20:44 by simonpj] · 4fb9c8aa
      simonpj authored
      	Be more gung-ho about INLINE pragmas
      When we see 
      	{-# INLINE f #-}
      	f = g $ h
      should we inline f inside a lambda?  Previously we said 'no'
      because f looks like a redex, but that's a great mistake sometimes.
      So this commit is more gung-ho: if you say INLINE that's what you get.
      The changes are to exprIsDupable and exprIsCheap.
    • simonmar's avatar
      [project @ 2001-03-19 16:17:44 by simonmar] · ff39a56b
      simonmar authored
      exprIsAtom shouldn't return True for an SCC.
    • simonpj's avatar
      [project @ 2001-03-19 16:13:22 by simonpj] · 17d765ce
      simonpj authored
      	Improve orphan-module resolution
      Consider the following rule (and there are lots of these in
      the Prelude):
      	fromIntegral T = fromIntegral_T
      where T is defined in the module being compiled.
      is an orphan.  Of course it isn't, an declaring it an orphan would
      make the whole module an orphan module, which is bad.
      This commit arranges to determine orphan rules, and the orphan-hood
      of a module, much later than before.  (Before mi_orphan was set by
      the renamer, now it is set by MkIface.)
  27. 14 Mar, 2001 1 commit
  28. 13 Mar, 2001 2 commits
    • simonpj's avatar
      [project @ 2001-03-13 14:58:25 by simonpj] · 788faebb
      simonpj authored
      	Nuke ClassContext
      This commit tidies up a long-standing inconsistency in GHC.
      The context of a class or instance decl used to be restricted
      to predicates of the form
      	C t1 .. tn
      	type ClassContext = [(Class,[Type])]
      but everywhere else in the compiler we used
      	type ThetaType = [PredType]
      where PredType can be any sort of constraint (= predicate).
      The inconsistency actually led to a crash, when compiling
      	class (?x::Int) => C a where {}
      I've tidied all this up by nuking ClassContext altogether, and using
      PredType throughout.  Lots of modified files, but all in
      more-or-less trivial ways.
      I've also added a check that the context of a class or instance
      decl doesn't include a non-inheritable predicate like (?x::Int).
      Other things
       * rename constructor 'Class' from type TypeRep.Pred to 'ClassP'
         (makes it easier to grep for)
       * rename constructor HsPClass  => HsClassP
      		      HsPIParam => HsIParam
    • simonmar's avatar
      [project @ 2001-03-13 12:50:29 by simonmar] · 10cbc75d
      simonmar authored
      Some rearrangements that Simon & I have been working on recently:
          - CoreSat is now CorePrep, and is a general "prepare-for-code-
            generation" pass.  It does cloning, saturation of constructors &
            primops, A-normal form, and a couple of other minor fiddlings.
          - CoreTidy no longer does cloning, and minor fiddlings.  It doesn't
            need the unique supply any more, so that's removed.
          - CoreToStg now collects CafInfo and the list of CafRefs for each
            binding.  The SRT pass is much simpler now.
          - IdInfo now has a CgInfo field for "code generator info".  It currently
            contains arity (the actual code gen arity which affects the calling
            convention as opposed to the ArityInfo which is a measure of how
            many arguments the Id can be applied to before it does any work), and
            Previously we overloaded the ArityInfo field to contain both
            codegen arity and simplifier arity.  Things are cleaner now.
          - CgInfo is collected by CoreToStg, and passed back into CoreTidy in
            a loop.  The compiler will complain rather than going into a black
            hole if the CgInfo is pulled on too early.
          - Worker info in an interface file now comes with arity info attached.
            Previously the main arity info was overloaded for this purpose, but
            it lead to a few hacks in the compiler, this tidies things up somewhat.
      Bottom line: we removed several fragilities, and tidied up a number of
      things.  Code size should be smaller, but we'll see...
  29. 08 Mar, 2001 1 commit
    • simonpj's avatar
      [project @ 2001-03-08 12:07:38 by simonpj] · 51a571c0
      simonpj authored
      	A major hygiene pass
      1. The main change here is to
      	Move what was the "IdFlavour" out of IdInfo,
      	and into the varDetails field of a Var
         It was a mess before, because the flavour was a permanent attribute
         of an Id, whereas the rest of the IdInfo was ephemeral.  It's
         all much tidier now.
         Main places to look:
      	   Var.lhs	Defn of VarDetails
      	   IdInfo.lhs	Defn of GlobalIdDetails
         The main remaining infelicity is that SpecPragmaIds are right down
         in Var.lhs, which seems unduly built-in for such an ephemeral thing.
         But that is no worse than before.
      2. Tidy up the HscMain story a little.  Move mkModDetails from MkIface
         into CoreTidy (where it belongs more nicely)
         This was partly forced by (1) above, because I didn't want to make
         DictFun Ids into a separate kind of Id (which is how it was before).
         Not having them separate means we have to keep a list of them right
         through, rather than pull them out of the bindings at the end.
      3. Add NameEnv as a separate module (to join NameSet).
      4. Remove unnecessary {-# SOURCE #-} imports from FieldLabel.