New in Kokogut-0.7.1, a release with preliminary PDF documentation: * The Kogut Programming Language Reference in PDF (incomplete yet) replaces the old language reference in HTML. * A unit testing framework in module Testing.Units. Define a structure of tests: - TestGroup "name" {...} - define a group of test cases and subgroups. - TestCase "name" {...} - define a test case. - SetUp "name" {...} {...} - define actions to be performed before and after each test in the current group; the second action is optional. - SetUpOnce "name" {...} {...} - like SetUp, but do only once instead of for each test. - local TimeLimit n {...} - specify a different time limit for each test defined here; default: 10 seconds. Inside test cases and set up / tear down actions: - TestMessage "message" {...} - give a message for test failures inside this region. - AssertFalse() - unconditional failure. - Assert cond - failure unless cond is true. - Assert obj cond - failure unless 'cond obj' is true. - x->AssertIs y - failure unless 'x %Is y' - AssertFails body cond - failure unless 'body()' fails with exn such that 'cond exn' is true. - Env - when set up actions set fields of this object, they are available in the corresponding test cases and tear down actions; Close is applied to them after tear down actions automatically. Running tests: - RunTests "name" - runs all tests, or tests specified by command line parameters: --help display program usage --list show all test names (not implemented yet) --test=NAME run these tests; can be given multiple times, but no tests selected means to run all test; NAME is a "/"-separated path of test groups, possibly ending in a test case --report=none do not display anything on stdout --report=default display test failures only --report=full display test passes and failures --log=FILENAME write full report to this file; default: the name given to RunTests with ".log" appended NAME same as --test=NAME * Created some basic tests of the Core library, run by 'make test'. * Renamed: - {Lock,Unlock,IsLocked}ReadWillWrite -> {Lock,Unlock,IsLocked}Update - ChangeLockTo{Write,Read} -> {Lock,Unlock}WriteUpdating Unified mutexes with read-write locks: mutexes now support {Lock,Unlock,IsLocked}{Read,Update} and {Lock,Unlock}{WriteUpdating} (plain locking means locking for writing). Removed the old READ_WRITE_LOCK type. IsLockedRead returns True also when the current thread has locked the mutex for writing or updating. IsLockedUpdate - also for writing. Wait can be used with any kind of lock, and unlocks all locks the current thread holds for the mutex associated with the condition. A read lock is always granted if the current thread already holds a read lock, even if there are waiting writers. Otherwise an unnecessary deadlock could occur. * Changed the design of weak references such that removal of dead weak references is synchronous: DeadWeakRefs() creates a collection for dead weak references, of type DEAD_WEAK_REFS. Weak references of type WEAK_REF are created as follows: - WeakRef key - WeakRef key dead data... - WeakPair key value - WeakPair key value dead data... where 'value' defaults to 'key', and 'dead' is a dead-weak-refs. A weak-ref by itself doesn't keep its key nor value alive. It enforces the relationship: as long as the weak ref and the key are alive, the value is kept alive too. 'weakRef absent present' enters 'present value' if the key is alive, or 'absent()' otherwise. By default 'present' is 'Identity' and 'absent' is '{Null}'. If the key dies before its weak ref dies, and there is an associated dead-weak-refs, the weak ref is added to the dead-weak-refs. 'EachDeadWeakRef dead body', for each contained weak-ref, applies 'body' to the weak-ref and its associated data. This is typically used to remove dead weak references from the container they are stored in, such as a weak dictionary. Weak-ref functions are now exported by Prelude instead of Threads. * Method dictionaries and the supertype cache do not keep entries for local types which are garbage collected. * Object-ids have observable unique indices (id.index). Indices can be reused when object-ids die. As before, object-ids are hashable (hashes are not necessarily unique) and comparable (the ordering corresponds to indices). The ordering of object-ids no longer corresponds to the time of their creation. * Revised the rules of signal blocking: the state is (all, async) as before, but both components have the full range of natural numbers. Synchronous mode means all == 0 & async > 0. Basic transitions of the blocking state (exported by Prelude now instead of Threads): - BlockSignals: all = all + 1 - UnblockSignals: all = all - 1 - BlockAsyncSignals: async = async + 1 - UnblockAsyncSignals: async = async - 1 - BlockSyncSignals: all = all + 1; async = async - 1 - UnblockSyncSignals: async = async + 1; all = all - 1 New read-only variable SignalBlockingState returns the blocking state as a pair (all, async). * Revised signal handling by lazy lists. The following are basic building blocks of a lazy list: - Lazy compute - LazySync prepare complete - LazySync prepare - LazyAsync prepare complete - LazyAsync prepare The following calls can be put in 'complete': - CommitLazySync prepare complete - CommitLazySync prepare - CommitLazyAsync prepare complete - CommitLazyAsync prepare As before, 'compute' is a nullary function which gives the value, 'prepare' is a nullary function which gives some data, and 'complete' is an unary function which transforms the data to the value. An absent 'complete' defaults to 'Identity'. CommitLazy{Sync,Async} reverts to the 'prepare' stage with new computing functions stored in the variable. 'compute' and 'complete' are evaluated with signals blocked. 'prepare' is evaluated with async signals blocked (in sync variants) or in unchanged signal blocking state (in async variabnts). If 'compute' or 'complete' fails, the lazy list becomes broken. If 'prepare' fails, the lazy list is reverted to the uncomputed state (or another thread tries to compute it if it was waiting). * A type may be final, which means that it may not have subtypes other than those defined when it was not final. The final state is stored in the field 'final' of a type, and can be set in the definition of the type with 'final:True' or 'final:False' or later with 'MakeTypeFinal type'. The default is final when the type is not abstract. A final type cannot be made nonfinal again. Standard concrete types are final. Most standard abstract types are nonfinal, but some are final too: BOOL, LIST, VIEW_PART. Unnamed functions have a final concrete type UNNAMED_FUNCTION, with a nonfinal abstract type FUNCTION as its supertype. * Redesigned the method of passing Kogut names to C code: An input to a C fragment can have one the following forms, in addition to an expression: - 'c_con Con index' - where Con is a constructor name, and index is the 0-based case number, expands to the object descriptor (type ko_descr_t) - 'c_con Con' - equivalent to 'c_con Con 0' - 'c_entry obj arity' - expands to the given fast entry (type ko_code_t) - 'c_entry obj' - expands to the list entry (type ko_code_t) In all these cases the label providing the C name is optional, defaulting to the concatenation of the arguments of c_con or c_entry. Removed c_type syntax in an input to a C fragment; c_con is used instead. c_type definition now defines both the type and the object descriptor. The descriptor has a Kogut name so it can be exported and imported by modules, but this name is usable only in c_con and does not correspond to any Kogut object. The syntax of a C type definition is: - c_type NAME supertypes... Con defC... - c_type NAME supertypes... { c_con Con defC...; ... } where defC... is the C move code (a string literal), with an optional C finalize code (a string literal), optional C save code (a string literal), and optional behavior (a list containing function cases). c_export is similar to c_define, but the code is exported from the module and will be inserted into any other module which imports this module and contains any C fragments. It should include declarations which would be suitable for a C header file. c_export is always public. An imported c_export is reexported by a module which contains any c_export itself. An empty 'c_export()' forces the reexport without adding any new declarations. c_defineName and c_exportName take C inputs, which are made global with #define in the whole module, or also in importing modules in the case of c_exportName. An imported c_exportName is reexported by a module which contains any c_export. The C names should be chosen to be reasonably unique. The C entity thus named is automatically forced to be extern on the C level even if it is private in Kogut, in the case of c_exportName. If the --c-export-file=FILE option is given, the C exports are written to the specified file instead of being put in *.koi files, and this file will be included by importing modules instead of copying declarations literally. If --c-export-dir=DIR is given, the file will be created relative to this directory instead of the current directory. A C export file has two purposes: reduce the size of *.koi files, and make possible to include the declarations into separately compiled C/C++ files. These options may also be given by a *.kop file. * Added kokoc option --trace to augment code with logging of various operations (primarily function calls) to the filename given in the KO_TRACE environment variable. Logging is enabled if this variable is set. The file is appended if it already exists. In the trace only values of some standard types are shown in detail. Other objects are shown as '', and parts of compound values are generally replaced with '_'. At the beginning of the trace various symbols are replaced with '_', which happens when an object associated with the symbol (such as a type with the given name) has been used before its module has been initialized, and thus the symbol is not yet available to the tracing machinery. * Functions Real and Imag in module Math preserve inexactness of a number as a whole: they return an inexact result if either component of a complex number is inexact. Internally the components of a complex number can still be inexact independentently from each other. New function InexactLike in module Math returns its first argument, but forced to be inexact if the second argument is inexact. It is dispatched on both arguments. * Changed parameter order of HashSetBy and {,Weak}HashDictBy: the transformation function is last. * New function Compare for 3-way comparison, dispatched on both arguments. Its methods should be consistent with the following method which is the default: method Compare x y { if [ (x < y) {#'<'} (x == y) {#'='} (x > y) {#'>'} _ {Fail (NotOrdered x y)} ] }; * 'x->IsInRange max' is equivalent to 'x->IsInRange 0 max'. * New immutable sets and dictionaries of types TREE_{SET,DICT}{,_BY} with constructors Tree{Set,Dict}{,By} and constants EmptyTree{Set,Dict}. Their keys must support ordering, and are kept sorted. These collections support {,Get,Remove}{First,Last}, which mean the minimum or maximum key respectively. They are implemented as left-leaning red-black trees. Algorithms are based on the work of Robert Sedgewick: , . * New functions Remove{First,Last}Gen. * VIEW_PART has two subtypes VIEW_PART_FLAT, VIEW_PART_NOT_FLAT which reflect whether the underlying sequence is a flat-sequence. Values of types VIEW_PART ensure that bounds are ints, and store them in the normalized form (0 <= begin <= end <= size). Creating a view-part with out of range bounds clips them. An attempt to access elements outside the viewed part is properly detected. Part or RemovePart of a view-part always does a copy of the underlying sequence. ViewPart of a view-part is flattened to a single-level view-part. * Fill{,New}Inf return values of separate types FILL{,_NEW}_INF instead of GENERATOR. Values of types ALLOCATE and FILL{,_NEW} ensure that the size is an int, and store it in the normalized form (size >= 0). {Range,Between}Back are explicitly used for a negative step, instead of overloading {Range,Between}. {Range,Between}{,Back} with an explicit step work correctly even when the range limit is near the limit of the domain of the values and the next step would go outside the domain. An implicit step of 1 or -1 is assumed to not overstep the domain limit. * New type INDEXED of flat dictionaries with a fixed set of keys. Bounds specify the set of keys and must have the following generic functions defined: - 'KeyTranslation bounds' - returns a pair of the size and a function with parameters: key absent present, which attempts to convert 'key' to an unique index in the range of the size, and enters 'present index' or 'absent()'. - 'KeyRange bounds' - returns a sequence of the keys in the order corresponding to the mapping. In particular the following values can specify the bounds: - an int - 0 to limit (exclusive). - 'first %To last' - keys between first and last, which must support binary '-' (returning and int), '_+1', '<', and '=='. - 'FixedKeys keys' - a sequence of explicitly enumerated keys, which must be hashable. - 'bounds1, bounds2' - a Cartesian product of two bounds. An indexed dictionary has the following fields: - bounds - the bounds. - values - a flat mutable sequence storing the values. - keyToIndex - cached right component of 'KeyTranslation bounds'. The following functions are provided: - 'Indexed bounds values' - an indexed dictionary backed by the given sequence of values. The 'values' object is used directly, without copying. Its size must correspond to the bounds. - 'AllocateIndexed con bounds srcs...' - an indexed dictionary backed by 'con (Allocate size)', and then populated by 'srcs'. - 'FillIndexed con bounds value srcs...' - an indexed dictionary backed by 'con (Fill size value)', and then populated by 'srcs'. - 'FillNewIndexed con bounds fun srcs...' - an indexed dictionary backed by 'con (FillNew size fun)', and then populated by 'srcs'. - 'NewIndexed con bounds fun' - an indexed dictionary backed by 'con (KeyRange bounds->MapGen fun)'. In each case 'srcs' must be collections of pairs. * New function RandomElement in module Random. * New functions System.Processes: - ProcessId - getpid - ParentProcessId - getppid - ProcessGroupId - getpgrp, getpgid - NewProcessGroup, SetProcessGroup - setpgrp, setpgid - SessionId - getsid - NewSession - setsid * Redesigned forking options. Retaining other threads in the child process is no longer supported. There is one function ForkProcess with an optional body and with keyword parameters. ForkProcess locks an internal mutex to prevent concurrent forking. Each function registered AtForkProcess is called with one argument being a nullary function which calls the rest of the functions, does the fork, and returns #child in the child process, or the PID of the child process in the parent process. Keyword parameter 'syncThreads' specifies whether to wait for other threads to reach a safe point before forking. The default is True. If it is true, each thread except the one doing the fork is sent FORK_PROCESS_SIGNAL. The signal has a field 'sync' holding a nullary function which waits until the fork is done, and returns in the parent process; the thread no longer exists in the child thread. The default handler of this signal calls the 'sync' function. When ForkProcess is called without a body, its result is #child in the child process, or the PID of the child process in the parent process. When ForkProcess is called with a body, the child process executes the body and exits instead of returning from ForkProcess. In this case an additional keyword parameter 'blockSignals' is supported, which indicates whether signals in the child process should be blocked once or unblocked, relative to complete unblocking rather than to the state outside the fork. The default is False. A default AtForkProcess handler flushes StdOut and StdErr. If this might collide with a concurrently working thread, these streams should be rebound to null output streams around the fork. * New function RunProcess in module System.Processes: like RunProgram, but applying the function supplied as the last argument instead of running an external program. Keyword parameters of RunProcess and RunProgram: - mode - one of: - #replace - just apply the function, don't fork at all - #background - return the tuple of the child process pid and the pipes created for redirection. - #wait - wait until the process finishes, return the value of the body of RunProcess if it completes normally, or the exit code of the child process, or propagate the exception via serialization if the body fails, or propagate the signal as an exception if it was killed with a signal. The default is #wait, unless redirect is not Null which forces the mode to be #background. - syncThreads, blockSignals - passed to ForkProcess. RunProgram changes the default of syncThreads to False. - processGroup - the process group for the child process, or #new for a new one, or Null for leaving it in the same group as the parent; Null by default. - stdIn, stdOut, stdErr - a stream to redirect the given standard stream to, closing the original in the both processes, or leaveOpen:stream when it should be left open in both processes, or Null for no redirection. A stream which is not left open is changed into blocking mode. - redirect - #stdIn, #stdOut, #stdErr, or a tuple of them, denoting standard streams for which redirection pipes are created, or Null for no redirections. This forces mode:#background. - close - a list of streams to close in the child process. - closeInParent - a list of streams to close in the parent process. - directory - the directory name to change to in the child process, or Null for no change. - environment - a list of (name, value) pairs of additional environment variables to set in the child process. - prepare - an additional action to perform at the beginning of the child process, or Null for nothing. The difference between prepare and the body of RunProcess is that for mode #background the parent process waits until prepare completes, and exceptions from prepare are propagated to the parent process via serialization. If prepare is not Null, the body takes a single argument which is the result of prepare. - passResult - for RunProcess in mode #wait, whether to serialize the result of the body and return it instead of the exit code. - signal - for mode #wait, the function to use to cancel the child process if the thread of the parent process waiting for the child process is canceled, or Null when it should not be canceled automatically; Null by default. The function takes the child pid and the exception as arguments. * When an adopted thread exits, WaitForThread behaves as if the thread finished returning Null. * Variable DetectDeadlock exported by module Threads: if true (the default, which behaves as before), the scheduler detects a deadlock ands sends the thread handling system signals a Deadlock signal or aborts the program if that thread does not respond to signals. This behavior can be turned off because deadlock detection can have false positives when foreign threads have not been adopted by Kogut yet. * Changed the usage of EachThread: - EachThread existing starting ending body - EachThread existing ending body All arguments except 'body' will be called with one argument: a thread. 'existing' is called by the thread doing 'EachThread' for each currently existing thread which has not yet completed nor has not been garbage collected. Then 'body' is called with no arguments. While 'body' is running, 'starting' (which is the same as 'existing' if not given explicitly) is called by newly created threads, and 'ending' is called by threads going to complete. EachThread now includes finalizer threads and adopted threads. * Mutexes and read-write locks are now exported by Prelude instead of Threads. * New function IsLocked, and new functions in module Threads: IsLockedRead, IsLockedWrite, IsLockedReadWillWrite. They check whether the current thread has locked the mutex or read-write lock, not whether some other thread has done it. * Renamed Code to CharCode. * Renamed ExitProgramImmediately to ExitProgramNow. * Renamed exception RECURSIVE_LOCK to LOCK_ALREADY_LOCKED. * Changed the module syntax to have module contents in braces. * Removed 'pat1->fun args... = pat2' pattern syntax. A pattern looking like an assignment to an application means to use the source of the assignment as the last argument of the application, like in expressions and definitions. 'where' syntax is back: 'pat1->where fun args... = pat2' means '(pat1 & tmp)->match (fun tmp args...) = pat2'. 'pat1->maybe fun args... = pat2' means 'pat1->where fun args... {[]} [_] = pat2\_'. In conditional patterns, 'where', and 'maybe' patterns, a '_' marker as the function or as one of the arguments specifies the position to put the subject, instead of inserting it as the first argument. * Removed the pat^_ syntax for pat^OBJECT. Use just pat instead. * Removed 'inc' and 'dec' syntax. * Removed 'optional' syntax. Use 'if' with explicit lists instead. * 'case' syntax is more similar to 'if': - 'case expr... [pat... {then} ...]' remains unchanged. - 'case expr... ?pat... {then} {else}' is equivalent to 'case expr... [pat... {then} _... {else}]'. - 'case expr... ?pat... {then}' is now equivalent to 'case expr... ?pat... {then} {}'. * 'IfNotNull obj notNull' is equivalent to 'if (obj %Is Null) {Null} {notNull obj}'. Removed functions: EncodeCString{ASCII,Latin1}OrNull, {Encode,Decode}CString{,Ptr}OrNull, {Encode,Decode}CCharOrNull. * New pattern 'pat->ofType types...' ensures that the subject has one of the given types, and fails with BAD_TYPE otherwise. * The following functions are now defined for any number of arguments: - '+', '*', BitOr, BitAnd (previously 2) - Min, Max, GCD (previously >0) * New functions for bit operations: - x %BitAndNot y = x %BitAnd BitNot y - x->TestBit i = x %BitAnd 1->BitShift i ~%Is 0 - x->SetBit i = x %BitOr 1->BitShift i - x->ClearBit i = x %BitAndNot 1->BitShift i - CountBits x - number of bits set in x (Inf for x<0) - FindBit x i absent present - find the smallest j>=i such that x->TestBit j; enter present j if it exists, absent() otherwise; default i is 0, default present is Identity SizeInBits 0 %Is 0. Redefined SizeInBits for negative numbers: SizeInBits x %Is SizeInBits (BitNot x). * Removed DefaultRational; Ratio is always used instead. Context-sensitive division was not a good idea. * Subtraction of times returns a ratio instead of using DefaultReal. * Find and FindBack no longer have the starting index parameter. Use them with PartGen or ViewPart instead. Find, FindBack and FindPart take 'absent present' or 'absent' as last parameters, and enter 'present index' when the index is found or 'absent()' otherwise. * Touch is exported from module Threads instead of Prelude. * 'Touch result obj' is equivalent to 'let x = result; Touch obj; x'. * A semicolon-separated sequence of definitions which denotes an expression as a whole doesn't have to end with an expression. If it ends with a proper definition, its value is Null. Looking for the last definition descends into subsequences of definitions created by 'define', 'public', 'private', 'ifDefined' etc. 'method' is treated as a definition instead of an expression. * Function parameters and definitions on the toplevel of a function body belong to the same scope: conflicts are disallowed, and forward references are allowed. * The syntax like 'arr@0.x' means the likely intended 'arr@(0).x' rather than 'arr@(0.) x', by introducing a special token consisting of '@' and an integer literal. * Names introduced by --switch / -D without a definition are usable only in 'ifDefined', without getting a dummy definition as Null. The same effect can be obtained in the source by 'defined name' (possibly with multiple names at once). * Escape sequence "\_" in strings skips whitespace until end of line and the end of line itself, but leaves the indentation of the next line in the string. This is useful at the beginning of a multiline indented string. * '()' is treated as a single token instead of two. * For clarity, there must be a space or comment between one of these tokens: name _ literal () .field @intLit %op op% ) ] } ... ! and one of these: name _ literal label: %op op% ( [ { ? => ~ * Renamed CloseAll to EnsureAll. * SigQuit (generated by Ctrl-\ on Unix by default) shows a stack trace if propagated to the toplevel. * Elements of AtUnhandledException receive only one argument: the exception. The stack trace is available from StackTrace(). To enter the rest of the handlers, a handler should propagate the exception. * New functions MapList, MapPartialList, MapJoinList, SelectList, RejectList, UniqueList, UniqueListBy - variants of old functions which return the same result as a list. * New function UnnamedFunction to complement NamedFunction. * New dynamic variables for limiting the amount of information returned by Show: - MaxShowDepth - the maximum depth of nested parens or brackets in Show output (parens around simple values like negative numbers don't count); an integer or Infinity, Infinity by default - MaxShowSize - the maximum number of collection elements in Show output; an integer or Infinity, Infinity by default New function 'ShowCompound parens body' for Show methods: "_" if the number of nested parens would exceed MaxShowDepth, otherwise 'body()' wrapped in parens if 'parens'. Show format revised to use '_' or '_...' when the depth or the size is getting too large. Strings are truncated with "\...". The stack trace on unhandled exception is shown with MaxShowDepth=3 and MaxShowSize=20. * Printable characters in strings and symbols are shown unescaped if they could be encoded using DefaultEncoding. * Module Calendar: - Renamed DATE to DATE_TIME, and Date to DateTime. - New type DATE with constructor Date holds just the year, month, and day, together with the computed day of year and day of week, without a specific hour or time zone. Subtraction of dates gives the diffrence in days. * New functions: Numerator, Denominator, for integers and rationals. * Floats and named functions are hashable. * New field 'public' of symbols. Private symbols are serialized as fresh symbols, preserving sharing within a serialized stream. * Float Null is NaN. Int and Ratio return Null for NaN instead of failing. Removed InfFloat, NegInfFloat, and NaNFloat. Use Float Inf, Float NegInf, and Float Null instead. * DecodeFloat returns the sign as a separate field, encodes 0 with the exponent of -Inf, and infinity and NaN with the exponent of Inf. * Renamed Sqrt to SqRt. * Renamed ScaleFloat to ScaleReal. * Flush mode #sync replaced with #whole, which means to consume the whole buffer passed to WriteSomeTo or FilterBlock, but not necessarily write the output to the raw file. The default flushLines of StdOut and sockets is now #sync instead of #soft. The default flushAll of StdErr is #sync. Copy{Byte,Char}Stream is applicable to FILTERED_{BYTE,CHAR}_OUTPUT. Flushing an LZMA stream in mode #sync or #reset is equivalent to flush mode #end. The original LZMA implementation does not provide flushing more softly. * Added a byte stream type TIED_OUTPUT which flushes another stream on each write. StdErr is now tied to StdOut. * Raw files have field fd: Unix file descriptor. * FILE_MODE: fields usr, grp, oth contain triples of rusr, wusr, xusr; rgrp, wgrp, xgrp; roth, woth, xoth. * Replaced DOES_NOT_MATCH exception with NO_MATCH which includes the objects which did not match, and split ALL_CONDITIONS_FALSE out of it. Exception type BAD_ARGUMENTS unifies the old BAD_ARGUMENTS with TOO_{FEW,MANY}_ARGUMENTS, and contains the argument values and information about allowed arities. ShowException shows the argument values if the arity matches, otherwise shows only information about the arity. Exceptions of types NO_METHOD, NO_SUPER_METHOD, NOT_DISPATCHED, and METHOD_CONFLICT include the arity. Exceptions of types NO_METHOD and NO_SUPER_METHOD include the key arguments instead of their types. Renamed NOT_VARIABLE to NOT_SETTABLE. Swapped arguments of NOT_SUPERTYPE exception: now they are the potential subtype and supertype. * Read-write locks detect errors when the lock should be locked for reading but it's not, or when it should not but it is. * New library FAM providing a binding to File Access Monitor or Gamin. * New library DBus providing a basic binding to D-Bus, usable but incomplete. * Module Network.Sockets in library Network: functions ServerSocket and ClientSocket accept an additional keyword argument 'options' which should be a list of (level, option, value) triples for SocketOption. * Option --module-root=ROOT (module-root in *.kop) allows to exclude a common module name prefix from filenames. The root is a dot-separated sequence of module name elements. An --ifaces option (ifaces in *.kop) can include the common root of modules in this directory, appended to the directory name after "=". If --iface-dir=DIR option is given (iface-dir in *.kop), *.koi files will be created relative to this directory, based on the module name rather than the source filename. The directory can include a module root after "="; if absent, the module root given by the module-root option is assumed. * Dependencies are generated for all interfaces, even those with absolute paths. * Compiler notes renamed to notices. * The compiler issues a notice if the base filename does not match the base module name, in case of a module which is not the main module. * A separate --link-main option specifies a *.o file with C main() function to link. Make it 'none' to remove the default. The option is called 'link-main' in *.kop. * Fractional seconds in file timestamps are supported on some systems. * Python 3.0a2 is supported by the Python binding. The IsPython3 variable is defined when the Python version is at least Python3. This affects the semantics of various operations, e.g. Python3 strings are Unicode. The new 'bytes', 'bytearray' and 'memoryview' types are supported: PyBYTES, PyBytes, FromPyBytes, PyBYTE_ARRAY, PyByteArray, PyMEMORY_VIEW. In Python3 FromPyBytes supports anything which supports the new getbuffer interface with PyBUF_SIMPLE. In Python2 PyBytes and FromPyBytes have the semantics of the now removed functions ByteArrayToPyString and PyStringToByteArray. In Python3 the following names are aliases of other names: - PySTRING - PyUNICODE - PyString - PyUnicode - FromPyString - FromPyUnicode - PyINT - PyLONG - PyInt - PyLong - FromPyInt - FromPyLong PyCLASS and PyINSTANCE are present only in Python2. Renamed: - Py{Get,Set}{SpecialAttr} -> PySpecialAttr - RawPyGet{,Special}Attr -> RawPy{,Special}Attr - RawPyGetItem -> RawPyItem When a Kogut function is stored in a Python class and is then retrieved through an instance, it is transformed into a bound method, like in Python. Updated the set of Python exception types. Finalization of Python objects wrapped in Kogut is no longer done in foreign mode. This avoids a high thread switching overhead. Renamed LetFromPython to MethodFromPython. * Foreign.Perl: InitPerl function removed, initialization is now called automatically. * Unicode character properties and text segmentation rules updated to Unicode 5.1.0. * EncodeInt and DecodeInt treat the last bit of the byte array as the sign bit instead of passing it as a separate value. * Changed serialization format and some hash formulas. * -ftree-vrp (enabled by -O2) is buggy in gcc-4.3.0. We detect this and add -fno-tree-vrp if needed. * pselect, ppoll, or epoll_pwait are used if available, for reliable signal handling around polling. * LZMA compressor and decompressor updated from version 4.43 to 4.53. * Improved detection of dubious forward references which could never be executed before the corresponding definition. * kogut-mode.el: Improved indentation rules. Characters inserted directly after line indenting command (TAB or C-j) can change the indent which has just been made. * KoCalc: new functions real, imag. * New small example: MazeGen. * Improved out of memory detection: on a 32-bit architecture we proceed as if there were at most 1GB of RAM, because otherwise address space fragmentation might prevent us from using the available memory. * License: updated the wording of the linking exception, as section 6 of LGPL version 2 corresponds to section 4 of LGPL version 3. * Bugs fixed: - Checking that a supertype is a type had the condition backwards if the check was done at runtime (thanks for Pippijn van Steenhoven for the report). - Fixed a crash when GC shrinks a BOOL_ARRAY too much. - Fixed exception handling and signal blocking when interrupting a condition wait. - Foreign threads and process forking now properly ensure epoll initialization. - A method is allowed to contain cases with different fixed arities. - IsEmpty for HASH_SET_BY works. - Fixed a possible failure in the optimizer for forward-referenced 'let name = {fun}' at the toplevel. - Fixed a rare crash when a dying weak ref or readline keymap is the key of a weak reference. - Fixed a rare crash when a lazy variable uses local rebindings of dynamic variables. - Fixed memory management of readline keymaps. - LZMA compressors and decompressors are closed properly. - The mangler is more robust when faced with jumps. In particular it works with code generated by gcc-4.3.0. - If the boot directory is present, it takes preference over an installed kokoc if no --with-ko-compiler=... is given. New in Kokogut-0.7.0 (27 November 2006), a cleaned up release: * Changed the syntax: - 'if' and 'ifDefined' are written without 'else', and are limited to one or two branches: - if cond {expr1} - if cond {expr1} {expr2} Alternatively any number of cases can be written in brackets, with '_' replacing 'else'. If no case matches in the bracketed variant, 'if' fails, and 'ifDefined' is an error. - 'def' is used for functions, 'method' for methods; 'let' remains only in the form 'let pat = expr' - Dispatched parameters of generic functions are written without parentheses: - def DoRemove coll! key {}; and types of specialized parameters of methods are written with '^' instead of '!', also without parentheses: - method DoRemove coll^HASH_DICT key {...}; - Function cases are put in brackets if there is more than one case. The opening bracket may be prefixed with a label, which specifies an internal name for recursive calls, which is 'again' by default. - Constructors are written without the equal sign between the type name and the constructor name. - A constructor name followed by brace-enclosed definitions defines a singleton object with an explicitly specified behavior. - 'subtypes T {definitions}' makes an existing type the implicit supertype of definitions. - '~' has a high priority, equal to 'label:', but when it's used before a function being applied, it covers the whole application. - A space in a string can be escaped by "\s" instead of "\ " (reverted the change made in version 0.6.1), because a backslash followed by spaces and then a newline should be ignored. * New functions: - ReverseGen, IterateBack - DoReject - TryRemove, TryCut - GetLast, TryCutLast - PartGen{,Back}, IteratePart{,Back} - EndsWith - Size{Is,AtMost}, Count{Is,AtMost,AtLeast} - MapDictPartial - SortGen{,By} - incremental sorting - Shuffle{,List,Gen} in module Random - FillInf, FillNewInf - Variable{Byte,Char}{Input,Output} - change the underlying stream at any time - Partial{Byte,Char}Output - shield lower layers from flush:#end and closing - WantGarbageCollect in module Threads - With{,Cancelable}AsyncExit in module Threads - Ignore - ?_... {} - Apply - ?f xs... {f xs...} - Unsafe{Min,Max}{,Int}, UnsafeVector in module Unsafe - EncodeInt, DecodeInt - conversion between ints and byte arrays - WriteStackTrace * Removed functions: - IsNull - JoinString - MapNext - MapPairs, MapPairsGen - Join - FinalizeWeakRef - use Close * Renamed functions: - Is -> HasType - IsTrue -> Identity - IsFalse -> '~' - Using_ -> Ensure - TouchObject -> Touch - JoinGen -> Join - ViewSequence -> PureIterator - Intersect -> Intersection - {BYTE,CHAR}_APPEND_INPUT -> APPEND_{BYTE,CHAR}_INPUT - {Byte,Char}AppendInput -> Append{Byte,Char}Input - {BYTE,CHAR}_COPY_INPUT -> PEEK_{BYTE,CHAR}_INPUT - {Byte,Char}CopyInput -> Peek{Byte,Char}Input - {BYTE,CHAR}_BUFFERED_{INPUT,OUTPUT} -> BUFFERED_{BYTE,CHAR}_{INPUT,OUTPUT} - {Byte,Char}Buffered{Input,Output} -> Buffered{Byte,Char}{Input,Output} - {BYTE,CHAR}_FILTERED_{INPUT,OUTPUT} -> FILTERED_{BYTE,CHAR}_{INPUT,OUTPUT} - {Byte,Char}Filtered{Input,Output} -> Filtered{Byte,Char}{Input,Output} - Escape -> WithExit - {,Cancelable}TimeLimit -> With{,Cancelable}TimeLimit - FileStatus -> TargetFileStatus - FileOrLinkStatus -> FileStatus - NamedFunction -> NamedCommand in module TextUI.ReadLine * Changed standard equality predicates: - 'Is' is strict equality. It compares the immutable structure of two objects. It differs from 'IsSame' only by not distinguishing the identity of value objects. An object is always equal to itself, even NaN, and objects with different types are always different. '0.0 ~%Is (-0.0)'. Dictionary lookup, 'IsIn', 'IsEqual', and literal patterns use 'Is'. A pattern 'is expr' is equivalent to 'when Is expr'. 'Is' is dispatched on the first argument only. The cases when both arguments are the same object or when they have different types are handled before dispatching. The default interpretation of 'Is' for types without a specialization is 'IsSame'. - '==' is arithmetic equality. It is defined for types which define '<', and for complex numbers. The definition should be compatible with '<' and '<='. * Removed 'when', 'where', and 'is' patterns. Changed the syntax of 'if', 'match', and 'define' patterns to include a pattern to match the subject against: - 'pat1->if cond' - 'pat1->match expr pat2' - 'pat1->define {def}' New patterns: - 'pat1->fun args...' (with an arbitrary predicate) - matches when the subject matches 'pat1', and 'subj->fun args...' is true. - 'pat1->fun args... = pat2' (with an arbitrary function) - matches when the subject matches 'pat1', and 'subj->fun args...' matches pat2. - 'pat1->with fields' - matches when the subject matches 'pat1', and each field matches. A field is either 'label:pat' which specifies the symbol and a pattern to match the field value against, or a name which specifies both at once. The argument before '%op' or '->fun' can be omitted, defaulting to '_'. This applies both to expressions (i.e. partial application) and patterns. If the keyword or function is negated with '~' in patterns with 'if', 'match', or a function, the negation doesn't apply to matching the subject against 'pat1'. For example 'x ~%Is 0' binds the subject to x if it's not 0, while '~(x %Is 0)' succeeds when x is not 0 but doesn't bind anything. * Using/4 and Ensure/4 have changed the argument order: obtain commit rollback body. * The first argument of Ensure is optional, defaulting to {}. * Using and Ensure: if the body fails, and releasing the resource fails too, the exception from the body has priority and is rethrown. CloseAll: if several actions fail, the earliest exception has priority. * Revised the rules of signal blocking: - The blocking state is still an (all, async) pair, but 'all' may no longer be infinite. - Explicit changes of the blocking state: BlockSignals increases 'all', UnblockSignals decreases 'all', BlockAsyncSignals sets 'async' to 1, UnblockSyncSignals sets 'async' to 1 and decreases 'all'. - Trying to unblock signals which are already unblocked fails. This is most likely an program error. - Signal handlers, exception handlers, and the 'commit' part of Using and Ensure increase 'all' by 1. The 'rollback' part of Using and Ensure increases 'all' by 2. In the case of an exception handler the state is changed wrt. the context of 'try'. - ThreadBlockSignals starts with all=1 and async=0. - Removed SignalsBlocked and AsyncSignalsBlocked. - When relocking a mutex or read-write lock with signals unblocked, signals are processed until a signal handler fails. * FindPart returns the haystack size on failure instead of Null. * Renamed 'start' to 'begin' when talking about index ranges, in particular in fields of 'ViewPart'. * EnvironmentVar{,s} renamed to EnvVar{,s}, moved from module System.Environment to Prelude, and environment variable names have been changed from strings to symbols. * Renamed Unix functions to be more consistent with Unix names or with one another: - CreateDirectory -> MakeDirectory - DeleteFile -> RemoveFile - SymLink -> MakeSymLink - ReadLink -> ReadSymLink - GetCurrentDirectory -> CurrentDirectory - SetCurrentDirectory -> ChangeDirectory - IsFile -> IsRegularFile - DirectoryContents{,Gen,Lazy} -> FileList{,Gen,Lazy} - contents of modules System.Directories and System.FileStatus moved to module System.Files * ICONV_ENCODING and IConvEncoding moved from Prelude to Encodings.IConv module (Core library). BlockingMode moved from Prelude to System.Files module (Unix library). * CopyStream function has been split into CopyByteStream and CopyCharStream. * New functions in module System.Files: - Make{Link,FIFO,Node} - Change{Mode,Owner,Time} * New library LZMA, providing LZMA compression scheme implemented by Igor Pavlov, used in 7zip. * When there is a name conflict between an implicitly imported definition and some other definition, the explicit definition is preferred and this is not an error. A note is shown though. * '|' patterns bind names which are common to subpatterns. * 'HasType' accepts multiple types and is true when the object matches any of the types. * Method definitions accept ','-separated sets of types. Multiple methods are defined, for each combination of the types. * 'private' and 'public' can be prefixes of definitions, e.g. 'private def F() {...};'. * Added macros inc and dec: 'inc v d' is 'v = v + d' (but v is computed only once), 'inc v' is 'inc v 1', and dec is analogous with '-'. * First-class modules are created by modules themselves instead of each time they are used. The format of module contents has been changed. * Expression of the form 'module Module.Name' evaluates to the module object of the given module. It can be used even before this module has been compiled. * Items of registered lists are unregistered only with 'Close' on the key returned by 'Register'. Applying the key is no longer supported. 'RegisterEvent' returns an event object; it can be unregistered with 'Close' instead of by applying it directly. * Old weak references has been split into two concepts: weak references and finalizers, with a changed semantics. 'WeakRef' - create a weak reference from a key object, a value object (which by default is the same as the key), and a close function. A weak reference by itself doesn't keep its key nor value alive. It enforces a relationship: as long as the weak reference and the key are alive, the value is kept alive too. 'weakRef absent present' returns 'present value' if the key is alive or 'absent()' otherwise. By default 'present' is 'Identity' and 'absent' is '{Null}'. If the key dies before its weak reference dies, the associated close function is scheduled for execution: it will be applied to the weak reference. It is meant to remove the weak reference from a data structure it is contained in. If the weak reference dies before the key dies, the close function is not executed. 'Finalizer' - create a finalizer from a key object and a close function. A finalizer doesn't keep its key alive; it is kept alive by the key. When the key dies, the close function is scheduled for execution: it will be applied to no arguments. The 'Close' method of a finalizer executes its close function immediately (or waits until it finishes if it's currently being executed), making the finalizer inactive. Collecting long chains of weak references is more efficient: O(N) rather than O(N^2). This change was inspired by http://www.haible.de/bruno/papers/cs/weak/WeakDatastructures-writeup.html but uses a different algorithm. Differences from the previous design: A weak reference is not kept alive by its key. A finalizer doesn't have an associated value and cannot be used to obtain a value. Explicit finalization is supported only for finalizers. Killing (deactivation without executing the close function) is not supported for either type. The close function of a weak reference gets the weak reference as the argument. A consequence of the change is that a value at a live key in a weak dictionary, if it refers to the weak dictionary itself, no longer keeps the dictionary alive. * Spelling "FileName" changed to "Filename" in ReadLine functions: FilenameCompletionFunction, FilenameQuoteCharacters, FilenameCompletionDesired, FilenameQuotingDesired, FilenameQuotingFunction, FilenameDequotingFunction. * Find and FindBack accept multiple sequences. The starting index is mandatory in this case. * Implemented Union, Difference, and Intersection. * Functions First, GetFirst, RemoveFirst, DoRemoveFirst, DoCutFirst, TryCutFirst are applicable to all collections, not just sequences, and in the case of sets and dictionaries operate on an arbitrarily picked element. * ReverseList can be applied to two collections: ReverseList x y == List (ReverseList x) y * Conversion of collections to strings and to character arrays flattens them recursively. * Generators and lazy lists are compared and hashed by elements. * Get, GetFirst, and TryCutFirst don't have separate specializations without explicit 'absent' argument. IsEqual doesn't have separate specializations without explicit element equality predicate. Sort doesn't have separate specializations without explicit element comparison predicate. List doesn't have separate specializations without explicit 'rest' argument. * Functions Min and Max are separately dispatched generic functions instead of always using '<'. When applied to numbers, they should be understood as arithmetic operations. When any argument is inexact, the result is inexact as well. They return the correct answer for 0.0 and -0.0. When any argument is NaN, the result is NaN. * GCD takes an arbitrary number of arguments. * The default Keys implementation is supposed to be the only one: it's now a constructor instead of a generic function defaulting to applying a private constructor. * IsOdd doesn't have a separate specialization but is defined as ~IsEven. * New syntax of expressions: 'match expression pattern' returns True if the expression matches the pattern. * Partial application is supported by '[]', '\', ',', 'if', 'case', 'match', and 'loop'. * New type of variable 'forward x', which may not be read until assigned, and which may be assigned only once. * A dynamic variable with no initial value has no global value at all instead of being initialized to Null. * Unused names and imports are noted. A note is like a warning but doesn't cause a non-zero exit code. * The 'Touch' function ignores its argument. It has three roles: - Silence the note about an unused name. - Ensure that the object is not garbage collected at this point yet (old 'TouchObject'). - Ensure that the name is available to C code. * When a multithreaded program is exiting, all other threads are canceled and waited for, and GC is performed. * When a thread is about to be garbage collected, it is kicked using ThreadKicked signal, so it has a chance to clean up. Threads with signals blocked are garbage collected silently. * ThreadBlockSignals blocks the signals once instead of absolutely, so BlockSignalsLess in the body unblocks them. * Event queues: EventReady can be called in two ways: - EventReady commit - EventReady commit rollback The commit function is executed when this event is taken, and the rollback function is executed when it is determined that it will not be taken. The rollback function may call EventNotReady if it determines that the event is no longer ready, i.e. that something has happened between it has notified that it's ready and it has been chosen as the first event to be taken. The argument of EventNotReady is a function which continues waiting. * The last argument of Flush{,To} is now optional, defaulting to #sync. * Supertypes of exceptions are used more consistently: - PROGRAM_ERROR - should not happen in a correct program, a library is used in a wrong way - EXTERNAL_ERROR - data given to the program is corrupted or the environment is uncooperative - RESOURCE_ERROR - an operation needs more resources than are currently available - EXIT - a non-local exit is in progress - SPECIAL_RESULT - this exception should be catched immediately by the context, it carries out-of-band information * Object ids are ordered. The order corresponds to the time of their creation. * ObjectId() creates an anonymous object id, not associated with any object, but hashable and ordered like other object ids. * Foreign threads are now more robust. Renamed KO_{UNBLOCK,BLOCK}_OTHER_THREADS* to KO_{ENTER,LEAVE}_FOREIGN*. Removed KO_{UNBLOCK,BLOCK}_OTHER_THREADS_OR_{BLOCK,UNBLOCK}_TIMER. KO_{ENTER,LEAVE}_FOREIGN* can be used instead, which now avoid physical creation of a new thread if there are no other threads which are running, waiting for I/O, sleeping, nor handling system signals. It is allowed to call KO_LEAVE_FOREIGN in an OS thread which has not been created by Kogut. The thread is adopted as a Kogut thread, with signals unblocked. The same Kogut thread is used to represent this thread until it finishes. New functions ko_{disallow,allow}_foreign_no_signals for disallowing other threads temporarily to just acquire access to the runtime, without running Kogut code. Mismatched KO_{ENTER,LEAVE}_FOREIGN* are detected at runtime when possible. * c_eval has an optional name of the result, written before inputs. If present, the result should be stored in this C variable, which is protected against GC. If absent, result should be stored into the unprotected KO_RESULT as before. * FileExists, IsRegularFile and IsDirectory use lstat instead of stat. * Unneeded symbols are freed from memory. * Local variables which become dead at a particular point of code are cleared, so the garbage collector doesn't unnecessarily retain objects they pointed to. * Renamed some environment variables controlling the runtime: - KO_HEAP_LIMIT_RATIO -> KO_GC_FACTOR (default: 1.5) - KO_MIN_HEAP_LIMIT -> KO_GC_SIZE (default: 4M) - KO_HEAP_SIZE_RATIO -> KO_GROW_FACTOR (default: 1.5) - KO_MIN_HEAP_SIZE -> KO_GROW_SIZE (default: 4M) - KO_TICK_FREQUENCY -> KO_TIMER (default: 100) * Improved detection of low memory condition: - If more than KO_MAX_MEMORY (default: RAM minus 64M, or half of RAM, whichever is larger) is used, OutOfMemory is signaled. This replaces KO_MAX_HEAP_SIZE which measured live heap size rather than allocated memory. - If more than KO_MIN_MEMORY (default: 1/4 of RAM) is used, and less than KO_MIN_FREE_MEMORY (default: 64M) is going to remain free (including buffers and swap), OutOfMemory is signaled. * KO_SHOW_STATS=1 and Kogut.Stats include GC time and maximum GC pause as both real and CPU time. * On Linux Kogut.Stats includes SystemStats which returns information from sysinfo(), mostly memory sizes. * If the 'inexact' option of Show is not Null, it means to show a point when the number is not shown exactly, rather than when it does not have an exact type. * 'precision' and 'fracPrecision' options for Show may be 'Inf'. * New show option showPrecision:True|False, default False - whether to add trailing zeros to suggest the precision of inexact numbers. * Conflicts in serialization unique names are reported. * When an object could not be serialized, a deserializer will fail in a predictable way. * Names of types, functions, and singletons are symbols, not strings. * Added functions which allow to locally extend or override serialization rules: - DefineSerializationRules {changes} - package serialization rules, expressed by executable code which defines them, into an object. - UseSerializationRules rules {body} - apply the packaged serialization rules during evaluation of body. * RecordSerialization accepts an optional argument: list of field names. If it's present, the type doesn't have to be a record type. * Changes in the Python binding: - RawPyCall, RawPyGetAttr, and RawPyGetItem are almost the same as the ordinary application and '@', but wrap the resulting Python object in Kogut without trying to convert it. - Removed RawPy{Set,Has,Del}Attr, RawPySetItem, PyDef{Class,Init,Method}. - Renamed PyIs -> PyHasType, PyExceptionIs -> PyExceptionHasType. - Python types are called PyNONE, PyINT, PyLONG, PyFLOAT, PyBOOL, PySTRING, PyUNICODE, PyTUPLE, PyLIST, PyDICT, PyTYPE, PyOBJECT, PySUPER, PyCLASS, PyINSTANCE, PyMETHOD, PyCLASS_METHOD, PySTATIC_METHOD, PyPROPERTY. - New types PySET, PyFROZEN_SET, PyENUMERATE, PyREVERSED, PySLICE. - Constructors of Python types have a Kogut-like interface. They are called PyInt, PyLong, PyFloat, PyString, PyUnicode, PyTuple, PyList, PyDict, PySet, PyFrozenSet, PyEnumerate, PyReversed, PyClass, PyMethod, PySlice. - New functions Py{Get,Set,Has,Del}SpecialAttr, PyCallSpecialMethod, PyType, PySymbol, ByteArrayToPyString, PyStringToByteArray. - Python exception types are available to Kogut: PyVALUE_ERROR etc. 'Fail (PyException type value)' raises a Python exception. - Attributes of Kogut objects as seen from Python don't necessarily correspond to Kogut fields, but can be defined per Kogut type with PyDef{Get,Set,Del}{,Special}Attr and PyDef{,Raw}{,Special}Method. - PyImport and PyAddModule take symbols, not strings. - Translation of collection interfaces between Python and Kogut is more consistent and more complete. In particular the semantics of iteration over dictionaries respects the convention of the language (key/value pairs in Kogut, keys only in Python). - Serialization / pickling works across languages. Detection of sharing works only within a subgraph of objects of one language though. * Python code can run concurrently with Kogut code. Python code may be called from multiple Kogut threads and vice versa. It is now safe to call Kogut from __del__ methods of Python objects. Switching between Python and Kogut is much slower however, and minimal supported version of Python is now 2.3. * Fixed a few issues with Python 2.5. * Perl code can run concurrently with Kogut code. Perl can only be called from a single thread. * KeyNotFound exception includes the key. * 'local', 'try', and 'handle' don't require braces in their bodies, and in the successful continuation of 'try'. These arguments may be arbitrary expressions, where braces denote a function and thus have the same meaning as before. * Names which are defined but not used are reported, unless they start with an underscore. * Stack traces include exceptions thrown during stack unwinding. * RunProgram passes the exception to the parent process if the program could not be executed. * Improved handling of the non-blocking mode of standard streams. If pthreads are used, the mode is queried at startup and is used to choose the method of ensuring that only the current thread is blocked by I/O. If pthreads are not used, standard streams are made non-blocking, and the original mode is restored before exiting or before ExecProgram (except when the current process is a child of ForkProcess{,CloneThreads,KillThreads}). * Unicode character database updated to Unicode 5.0.0. * New example: Connect Four game (koc4). * kocals supports variables, named functions, conditionals, comparisons. New kocalc constants: inff, nan, e. New functions: min, max, isdivisible, iseven, rationalize, isnumber, isnull, ispair, isbool, isexact, isfloat, isfinite, isinfinite, isnan, ratio, float. Running kocalc with arguments evaluates them and exits. * Small examples moved from directory tests to examples/small. * New small examples: KnightsTour, Sudoku. Sudoku was translated from a Lisp program by Frank Buß * ctags is a ctags config file to be put into ~/.ctags or included from it. * 'kokoc --depend' uses the real parser of the compiler instead of matching lines with regexps. * kokoc accepts C++ sources (extensions .cc, .cxx, .cpp, .c++). Kokogut headers are compatible with C++. Communication between Kogut and C++ must be done through extern "C" functions. * kogut-mode.el: M-q fills paragraphs in comments and strings. Automatic indentation reimplemented with slightly different rules. Local variables which look like standard macros but are not applied to arguments are highlighted as regular names. * Changed hash formula for integers. * Changed serialization format. * More efficient code is generated: lots of minor improvements, in particular related to loops (lambda-lifting, tighter tail recursion, reduced chained calls), mutable variables (they are not materialized as objects when possible), generic function dispatch (inlined code), objects with lots of fields (symbol lookup) etc. Option -O affects the generated C code by turning on some optimizations; the code may be longer. -O and -O1 through -O9 are equivalent (though they might be different for the C compiler), -O0 reverts to the default. * Fixed incorrect code generated by gcc-4.2.0 (gcc-4.1.0 was fine), by reducing pointer type punning and making one function not inline. Generated code still violates strict rules of pointer aliasing in C, but this would be hard to avoid, and it works now. * In version 0.6.1 the runtime was being compiled without optimization. * Bugs fixed: - Crash when a GC occurs during creating an IConv encoder or decoder. - Sorting was not stable. - Find for LIST with a non-zero starting index was wrong. - Declared supertypes are checked for being actually types. - Fixed QuotRem, Mod, and DivMod for mixed ints and floats. - Fixed IsDivisible when the second argument is a literal power for 2. - Fixed adding an already existing element to HASH_SET_BY. - Pipes created for redirected processes are set to blocking mode. - The timer is recreated after ForkProcess{,CloneThreads,KillThreads}. - CPU time statistics have overflowed after 36 minutes. New in Kokogut-0.6.1 (25 January 2006), a release with readline interface and settable default numeric types: * kokoc doesn't pass -O2 to gcc by default. It accepts options beginning with -O and passes them to gcc. * Assignment returns Null rather than the assigned value. * The sigsafe library is used when available, . It is recommended, otherwise signal handling will have race conditions. When building sigsafe, set debug=0 in SConstruct. * New functions: - GetOrSet dict key absent - set dict@key to absent() if it did not exist, and return it - Unsafe{Eq,NE,LT,GT,LE,GE,Neg}Int in module Unsafe - Cplx in module Math (replaced) - convert an arbitrary representation of complex numbers into CPLX - WithoutWaiting in module Threads - CloseAll - execute all actions even if some of them fail - ReadByteArrayFrom - read a fixed number of bytes - ReadBlockAt, WriteBlockAt, ReadBlockAhead, CanReadAhead - I/O at the specific position, without moving the file pointer - AttachDynamic - attach the current dynamic environment to a function, i.e. make a function which is executed with bindings of dynamic variables taken from the place of AttachDynamic * Renamed: - HandlerOfSystemSignals -> SystemSignalHandler - {Text,Binary}Reader -> {Text,Binary}Input - {Text,Binary}Writer -> {Text,Binary}Output - ReadBlock -> ReadSomeFrom - WriteBlock -> WriteSomeTo - FLUSHING_OTHER -> TIED_INPUT - FlushingOther -> TiedInput - {,BYTE_,CHAR_}INPUT_FILTER -> {,BYTE_,CHAR_}FILTERED_INPUT - {Byte,Char}InputFilter -> {Byte,Char}FilteredInput - INPUT_DECODER -> DECODING_INPUT - InputDecoder -> DecodingInput - {,BYTE_,CHAR_}OUTPUT_FILTER -> {,BYTE_,CHAR_}FILTERED_OUTPUT - {Byte,Char}OutputFilter -> {Byte,Char}FilteredOutput - OUTPUT_ENCODER -> ENCODING_OUTPUT - OutputEncoder -> EncodingOutput - {,BYTE_,CHAR_}INPUT_BUFFER -> {,BYTE_,CHAR_}BUFFERED_INPUT - {Byte,Char}InputBuffer -> {Byte,Char}BufferedInput - {,BYTE_,CHAR_}OUTPUT_BUFFER -> {,BYTE_,CHAR_}BUFFERED_OUTPUT - {Byte,Char}OutputBuffer -> {Byte,Char}BufferedOutput - Compress{GZip,BZip2} -> {GZip,BZip2}Output - Decompress{GZip,BZip2} -> {GZip,BZip2}Input * Removed: - E in module Math; use Exp 1 instead - Cplx in module Math (there is a different Cplx now); use a+b*I instead - HandleSystemSignals; use SystemSignalHandler variable instead - ProcessSyncSignals; correct handling of synchronous signals is generally done by waiting primitives - WithInfiniteBuffer * ByteCopyInput and CharCopyInput make a view of the given stream, array or string, which can be read without changing the original. The stream must support ReadBlockAhead, which in practice means that it should be buffered (the buffer will grow) or seekable. * Reversed the result of FilterBlock: it returns True when output did overflow. FilterBlock is no longer called with Null as the input buffer (which used to be equivalent to an empty array). Revised the meaning of flush. If it's not #none and there is room in the output buffer, FilterBlock should not leave anything in the input buffer. * Non-Unix line separators are supported: - 'LineSepDecodingInput input lineSep' wraps input such that the given lineSep is translated to "\n" - 'LineSepEncodingOutput output lineSep' wraps output such that "\n" is translated to the given lineSep - TextReader and TextWriter have a named parameter lineSep An output lineSep is #lf (Unix), #cr (classic Mac), or #crlf (Windows). The default is the value of the dynamic variable DefaultLineSep, except that for sockets the default is #crlf. The default value of DefaultLineSep is the local convention of the platform. An input lineSep can be one of the above, or #auto which accepts any of these separators. The default is #auto. Setting lineSep to #cr in either direction actually swaps "\n" and "\r". Since setting an input lineSep to #crlf translates "\r\n" to "\n", where the program treats "\n" after translation as line separator, in this case either "\n" or "\r\n" separate lines. * Elaborated the issue of specifying character encodings: - supertype ENCODING for encodings - function Encoding converts an encoding descriptor (i.e. either encoding or encoding name) to an encoding - dictionary NamedEncodings and function NamedEncoding are used internally to convert names to encodings * EncodingError and DecodingError store the encoding for debugging. The other field of DecodingError is now called bytes, not byte, and holds the list of bytes which caused the error, or the empty list in case of an unexpected end of bytes. ReplaceCodingErrors skips its size in input. * "\0;" characters in strings passed to C (e.g. file names) are detected and reported as errors of type NUL_ENCODING_ERROR. * More encodings are supported natively, without using iconv (in addition to Latin1Encoding): - ASCIIEncoding - UTF8Encoding - UTF{16,32}{BE,LE}Encoding - UTF{16,32}Encoding with an argument which is meaningful for the encoder: #be (prepend the BE BOM and use BE), #le (prepend the LE BOM and use LE), #noBOM (don't prepend any BOM unless needed and use BE). The "UTF-16" and "UTF-32" names correspond to UTF{16,32}Encoding #be. * UTF8EscapedBytesEncoding is an extension of UTF-8 where any byte sequence can be decoded into a string and yields the same byte sequence when encoded again. Bytes which would be invalid in UTF-8 and 0 bytes are prefixed with U+0000 and stored as a character between U+0080 and U+00FF or U+0000. On encoding only those character sequences prefixed with U+0000 are valid which would be invalid in true UTF-8, so different strings encode to different byte sequences. Valid UTF-8 byte sequences which don't contain 0 bytes yield the same results as in true UTF-8. The idea is based on UnixEncoding in Mono but slightly different. If the environment variable KO_UTF8_ESCAPED_BYTES is set to 1 and the default encoding (as determined by KO_DEFAULT_ENCODING or the locale) is "UTF-8", then it means UTF8EscapedBytesEncoding instead of UTF8Encoding. Specyfying "UTF-8" in the program explicitly always means true UTF-8. * Parameters of the default StdIn, StdOut and StdErr (encoding, line separator, buffering) are determined the first time these streams are used, rather than at the beginning of the program. Global bindings of dynamic variables are consulted to determine the parameters, i.e. they must be assigned to instead of being locally rebound to take effect here. Accessing the default StdIn has a side effect of accessing StdOut, because of OutputFlushingInput. * ProgramName and Parameters are converted from byte strings using DefaultEncoding each time they are accessed, until they have been assigned or locally rebound. This implies that the program can catch decoding errors. * DefaultEncoding is determined the first time it is needed. This implies that the program can install additional encodings before the name of the default encoding is mapped to the actual encoding. * The value of a lazy variable is computed in the dynamic environment from the place of its definition. * New library ReadLine provides an interface to GNU Readline. * New library Digest with modules Digest, Digest.SHA1, and Digest.MD5. SHA1 code is derived from RFC 3174. MD5 code is derived from the RSA Data Security, Inc. MD5 Message-Digest Algorithm (RFC 1321). * Removed library QSort. It was not useful (sorting is implemented natively), just intended as an example of callbacks, which are now better demonstrated in ReadLine, and it was subtly wrong with respect to GC. * It's easier to use optionally available libraries: appending "?" to the name of a library silences the warning if the library is not found. * Inf and NegInf are considered REAL, and allowed as real and imaginary parts of complex numbers. They are stronger than InfFloat and NegInfFloat in comparisons and arithmetic. * New option for showing numbers: inexactSpecial. If not Null, it overrides special for inexact infinity and inexact NaN. * Transcendental functions return exact numbers when possible, e.g. 64 %Power (2/3) is exactly 16, Log (9/25) (125/27) is -2/3, and Exp (-Inf) is 0. Not all cases of complex rationals are covered though because the author doesn't know needed algorithms. * Dynamic variable DefaultReal holds a function which converts a real number to some specific type. The default is Float. DefaultReal determines the type of irrational function results derived from rational arguments, the type of literals with a decimal point or exponent, and the conversion used in default implementations of functions for real arguments. Setting DefaultReal to Ratio works for literals but causes transcendental functions to loop for most exact arguments, because their definitions for INT and RATIO use DefaultReal if they are unable to find a rational result. * Similarly to DefaultReal, the dynamic variable DefaultRational holds a function which converts a rational number to some specific type. The default is Ratio. DefaultRational determines the type of rational but non-integer function results derived from integer arguments, and the conversion used in default implementations of functions for rational arguments. DefaultRational can be set to Float, in which case e.g. division of integers produces a float instead of a ratio. * Some arithmetic functions have default definitions which convert arguments using Int, Ratio, DefaultReal and Cplx: - Int, '+', '-', '*', Quot, Rem, QuotRem, Div, Mod, DivMod, BitNot, BitAnd, BitOr, BitXor, BitShift, SizeInBits, Ratio, '/', Float, ScaleFloat, Conj, Sqrt, Phase, Exp, Log, Power, Sin, Cos, SinCos, Tan, SinH, CosH, SinCosH, TanH, ASin, ACos, ATan, ASinH, ACosH, ATanH Other arithmetic functions have default definitions in terms of other operations rather than by conversion: - Abs, Signum, Sqr, IsDivisible, IsEven, Floor, Ceiling, Trunc, Round, GCD, Hypot Special cases: - '==', '<', '<=' - default implementations convert real numbers to Ratio instead of DefaultFloat - IsFinite, IsInfinite, IsNaN, SignBit, DecodeFloat - defined for each concrete type separately, without default implementations * Float arrays accept any real numbers as elements and convert them to floats. * Inferring regions where signals can be processed has been fixed and made more consistent. In particular: - Locking a mutex or read-write lock with signals unblocked is interruptible. - In synchronous mode only one signal at a time is handled. Any further signals are handled only if the reason to wait still holds. - GarbageCollect, MaybeGarbageCollect and Close in synchronous mode are no longer interruptible. - WaitForProcess in synchronous mode processes a pending system signal only if it would actually wait. - If a signal is sent before the target thread started waiting in synchronous mode, further signals are correctly blocked while handling the signal. - If a signal is sent before the target thread is going to wait for opening a file or for a process in synchronous mode, the signal is handled before waiting. - The time window when handling a system signal sent just before a blocking system call is delayed after the system call returns is reduced in case of some functions. Unfortunately with standard Unix APIs it cannot be entirely eliminated. The following operations are interruptible in synchronous mode when they have to wait: - Wait - WaitForThread - accessing a lazy list - Sleep - SleepForever - Take, TakeFirst - opening a fifo - reading from or writing to a pipe, fifo, socket, or a device which may block (like a terminal) - Connect, Accept - WaitForProcess The following operations may cause the thread to wait but are not interruptible in synchronous mode: - Lock - Unlock, Wait (when relocking at the end) - LockRead, LockWrite, LockReadWillWrite, ChangeLockToWrite - UnlockRead, UnlockWrite, UnlockReadWillWrite, ChangeLockToRead (when relocking at the end) - accessing a lazy variable - executing a module - FinalizeWeakRef - returning from a C callback in a wrong order, if pthreads are not available * Functions Using and Using_ accept also 4 arguments, with separate functions for rollback and commit instead of the single release, called depending on whether the body failed. * Changed event queues: - The event is specified as a single action which either returns, or fails, or calls EventReady with an argument being an action to be performed when this event is taken. - There is no attempt to detect whether the final action waits. * New algorithm for generating random numbers: ISAAC by Bob Jenkins . Provided by module Random.ISAAC. The constructor is RandomStateISAAC. The constructor for Mersenne Twister in Random.MT got renamed to RandomStateMT, but module Random reexports it under the name RandomState. * In strings \cX denotes a control character when X is an ASCII letter or one of these characters: @ [ \ ] ^ _ ? * In strings "\ " is a space instead of "\s". This is useful after a backslash and line break. * If libffi is available, we provide the LibFFI library which just links to libffi and adds options to compiler invocations; it doesn't provide any modules. Libffi is useful to wrap function closures in C function pointers, among other things. * Parsec no longer requires characters to be comparable, but they must be hashable. * CopyStream no longer flushes the output stream at the end. * The Calc example moved to examples directory and installed under the name kocalc. It now supports float constants and more functions. Type '?' for help. * Bugs fixed: - SizeInBits returned wrong results for small negative numbers. - IsEven was wrong with an earlier version of GMP than 3.1. - Log was sometimes returning NaN instead of a complex number. - Passing strings to C using EncodeSizedCString truncated the last character if there were any non-ASCII characters. - NextPermutation was repeating a permutation when some of inputs were equal. - There were memory leaks in dividing big integers into ratios. - Get for WEAK_HASH_DICT{,_BY} no longer holds the lock when applying absent and present. - Fixed the logic of estimating the amount of external memory (e.g. from malloc) to trigger GC earlier. New in Kokogut-0.6.0 (29 October 2005), a release with imperative iterators and number formatting: * Changed the default iteration protocol and the nature of generators. There were two major problems with old iterators: the primary iteration function, Traverse, executed the same action for each element, and thus too often clients needed to use a different and less efficient mechanism (Next); and while the interface of generators didn't rely on mutable state, some generators worked correctly only when used linearly. Now the function Iterate starts iteration and returns a stateful iterator. When an iterator is applied to two arguments, by convention called 'absent' and 'present', it checks whether there are more elements; if yes, it cuts the next element and enters 'present elem', otherwise it enters 'absent()'. It may be called again after the end. The function Iterate can be applied to any number of collections. In general it returns a multi-iterator which applies 'present' to the appropriate number of elements, until any collection ends. A generator is a "virtual" collection designed to be iterated over. It's created by 'Generate {code}', where the code makes a new iterator; when the generator is applied to no arguments or when Iterate is applied to it, it executes the code. Most generators may be iterated over multiple times, but some of them (e.g. those reading from files) may not. * New: - GetFirst, TryCutFirst - MapPartial, MapPartialGen - like Map and MapGen, but you may Pass() instead of providing an element - ReverseList, MapReverseList - reversing with the output going to a list, more efficient than Reverse{,Gen} with conversion - MapSepBy, MapEndBy - Average, MapAverage - MinimumBy, MaximumBy - EmptyIterator, EmptyGenerator - NextPermutation - takes a list and an optional less-than predicate, returns the lexicographically next permutation or Null if it was already the last one - ReadBytes{,Gen,Lazy}From - ReadChars{,From} - now returns an array - ReadLines{,From} - now returns a list - SkipLine{,From} - AnyCharExcept in module Parsec - DirectoryContents - now returns a list - {,Neg}InfFloat, NaNFloat, IsInfinite, IsNaN, SignBit - Hypot in module Math - SizeInBits - {Min,Max}SmallInt, IsSmallInt, Unsafe{Eq,NE,Quot,Rem,Div,Mod, IsDivisible,IsEven,ShiftL,ShiftR,SizeVector,AtVector} in module Unsafe * Renamed: - Rest -> RemoveFirst - Some -> Any - ListSort{,By} -> SortList{,By} - NextMany -> MapNext - Iterator -> ViewSequence - Generate -> Collect (new) - Gen{Map,Join,MapJoin,MapPairs,Select,Reject,Unique,UniqueBy} -> {Map,Join,MapJoin,MapPairs,Select,Reject,Unique,UniqueBy}Gen - Read{Chars,Lines}{,From} (old) -> Read{Chars,Lines}Lazy{,From} - GenRead{Chars,Lines}{,From} -> Read{Chars,Lines}Gen{,From} - DirectoryContents (old) -> DirectoryContentsLazy - GenDirectoryContents -> DirectoryContentsGen - ProgramOutputLines (old) -> ProgramOutputLinesLazy - GenProgramOutputLines -> ProgramOutputLinesGen - COLLECTION_EMPTY, CollectionEmpty -> EMPTY_COLLECTION, EmptyCollection - TimeAfter -> AbsoluteTime * Removed: - Unfold, Iterate (old), IterateIncl, Collect (old), GenCollect - using macro; use Using and Using_ functions instead - IsNegZero; compare with 0 and use SignBit instead * Function String no longer converts elements of sequences with String again. It used to be inconsistent, depending on the sequence type. * {Select,Reject}{,Gen} may be applied to more than one collection. Returned elements come from the first collection. * Removed SetWhenAbsent. Added SetDefault instead, which applies the given function to no arguments instead of to the key. This was the most common usage. * Function Sqr moved from module Math to Prelude. * Options for Show for numbers (the implementation is based on the paper "Printing Floating-Point Numbers Quickly and Accurately" by Robert G. Burger and R. Kent Dybvig): - base:b, default 10 - number base, between 2 and 36. This option does not apply to the exponent which is always shown in decimal if present at all. No base marker is added automatically, it can be injected through the sign option if wanted. - mixed:False|True, default True - when showing a vulgar fraction with the absolute value greater than 1, whether to show the integral part separately instead of writing an improper fraction. - scientific:False|True|(min, max), default (-4, 15) for floats and (-4, Inf) for ints and ratios - whether to use the scientific format. If it's a pair and fixedDigits is not Null, it's treated the same as False. Otherwise a pair determines the range of exponents (corresponding to the range between b^min and b^max of the absolute value of numbers) outside which the scientific format it always used. Sufficiently large numbers inside the range still use the scientific format if not all their integral digits would be precise. Scientific format is never used with vulgar fractions. - fixedDigits:n|Null, default Null - number of digits shown after the point, either for the regular format (absolute precision) or for the scientific format (relative precision). Trailing zeros are added as needed. Null means to show as few digits as possible for maintaining full precision. - digits:n, default 1 - minimal number of digits shown before the point. Leading zeros are added as needed. This option does not apply to the scientific format. If digits == 0, the number 0 can show no digits at all, unless other options imply otherwise. - inexact:Null|0|1, default Null - if not Null, inexact numbers always show the point and the given minimal number of digits after the point. This allows to distinguish integers, ratios and floats based on their printed representations. - precision:n|Null, default Null - number of digits assumed to be accurate (relative precision). Null means to assume the inherent precision of the type. This option also limits the maximal number of significant digits shown, unless overridden by fixedDigits. - fracPrecision:n|Null, default Null - like precision, but expressed in digits after the point (absolute precision). - sign:(pos, neg), default ("", "-") - sign markers. - imagSign:(add, sub, pos, neg), default ("+", "-", "", "-") - sign markers for the imaginary part. First two are used when the real part is shown, last two when not. - imag:(timesI, i), default ("*I", "I") - timesI is added after the imaginary part, except when it's 1 or -1, in which case i is used. - special:(inf, nan), default ("Inf", "NaN") - how to show infinity and not-a-number. - mixedSign:(pos, neg), default ("+", "-") - written between the integral and fractional part, if the mixed fraction format is used. - slash:str, default "/" - written between numerator and denominator if the vulgar fraction format is used. - case:#upper|#lower, default #upper - the case of letters used as digits above 9. - point:str, default "." - how to show the point. - insignificant:ch, default "0" - how to show trailing insignificant digits. They might have to be shown if fixedDigits is big enough, or if a large number is shown with scientific forced to False. Scheme uses "#" for this purpose. - exp:str, default "e" - the exponent marker. - expSign:(pos, neg), default ("+", "-") - sign option for the exponent. - expDigits:n, default 2 - digits option for the exponent. Ratios are shown as vulgar fractions when fixedDigits, precision and fracPrecision are all Null, even if the scientific option would imply the scientific format, because it would be unclear how many digits to show. For complex numbers the imaginary part is not shown if it's equal to 0; the real part is not shown if it's equal to 0 and the imaginary part is shown; the absolute value of the imaginary part is shown as a mere imaginary unit instead of a number multiplied by the imaginary unit if the number is equal to 1. If inexact is Null, equality here permits also floats, except negative zero. * Changed rules of weak references. Previously a key of a weak reference was considered dead if it was reachable only through finalizers. This meant that one could safely reference a key from its own finalizer, but finalizers could not rely on other objects being usable when they are run. Now the key keeps just the value alive, and finalizers are considered strongly reachable until they are run, together with everything they need. The finalizer may not refer to the key, or the key will never be finalized. You can use finalizers to constrain the order of finalization. A consequence for usage is that an object might have to be split into two parts: an outer part which has a weak reference attached and refers to the inner part, and an inner part which is referenced from the finalizer. * In synchronous mode signals are only handled while waiting for a thread, I/O, a timeout, or while sleeping forever; and only when actually waiting. They are not handled while waiting for a mutex, a read-write lock, a lazy variable, a weak reference finalizer; or when the reason to wake up is true immediately. Lazy variables no longer support CommitLazy with bouncing between obtaining a resource (in synchronous mode) and computing the value (with signals blocked). Lazy lists however support the old semantics of lazy variables with respect to signals, and support CommitLazy. Thus the obtaining phase can wait for another lazy list while being interruptible. * Event queues: a mechanism for serializing multiple sources of events. An event is in general handled in two phases: one function waits until it is ready, and another one confirms that you want to handle it now. Confirming some events has side effects (e.g. reading a line from a text stream removes it from the stream) and thus it might be important to confirm only one event at a time. 'EventQueue()' makes a new event queue, of type EVENT_QUEUE. 'RegisterEvent queue can do' adds to the queue a new source of an event, where 'can' is a nullary function which waits until the event is ready, and 'do' is a nullary function which confirms the event. 'TakeEvent queue' waits until one of the events happens, and returns the result of the 'do' function of the first event which was ready. A given event is handled at most once. The 'do' function is applied with signals in synchronous mode, and with one signal pending, of type NOT_YET. If it would have to wait for the event, this means that the event is no longer ready, or that it was only partially ready and we must wait for more data. In this case the 'do' function will handle the signal and fail, and TakeEvent will continue waiting. This implies that 'do' should behave sensibly if restarted after being interrupted synchronously. If the event needs no confirmation, the 'do' function might not do anything but return a value; 'do' will only be applied after 'can' returns. The 'do' function usually tags the result so it can be distinguished from other events. Examples of functions to be used in 'can' which are suitable for various functions used in 'do' (they are new): - CanReadFrom for ReadBlock, ReadByteFrom, ReadChar{,From} - CanReadLineFrom for ReadLine{,From} - CanWriteTo for WriteBlock, Flush{,To}; WithInfiniteBuffer can be used before to fill the buffer with data for flushing - CanPut for Put - CanTake for Take - CanTakeFirst for TakeFirst - CanTakeEvent for TakeEvent - CanConnect for Connect in module Network.Sockets; BeginConnect can be used before to initiate asynchronous Connect - CanAccept for Accept in module Network.Sockets; BeginAccept can be used before to initiate asynchronous Accept - CanReceive for Receive{,From} in module Network.Sockets - CanSend for Send{,To} in module Network.Sockets - CanReadFrom RawStdIn for GetCh in module TextUI.Curses Examples of events which need no confirmation: Sleep, Wait (if we know that the condition won't become false again), WaitForThread. Examples of events where waiting for them to be ready without confirming them is unimplementable, so they are always confirmed when waiting finishes even if they are not handled immediately: Open{Raw,Text,Binary}File, WaitForProcess. * Registering a value in a registered list is done with the Register function, instead of applying the registered list itself. Registered lists are sequences: they are operated on using Iterate, TryCutFirst and other generic sequence functions. Iteration over a registered list now takes a snapshot of its state from the beginning of the iteration; this round is not affected by changes of the state after the iteration has started. * If the body of a 'try' case is prefixed with 'handled:', the exception is considered handled when the body is executed. This means that the stack is unwound and the signal blocking state is restored. * If an object we extend or a feature we include is prefixed with a label, the base object is available under this label instead of 'base'. * New syntax of a definition: 'ref name = expr' is equivalent to 'let (ref name) = expr'. New syntax of a pattern: 'set variable' is equivalent to 'private tmp & define {variable = tmp}'. * 'case e ?x => ...' is equivalent to 'case e [x {...}]'. * In character output buffers flushLines is #none by default, except for StdOut, StdErr, and sockets, where it's #soft as before. * DefaultBufferSize is a dynamic variable instead of a constant, used by CopyStream. * Swapped arguments of ShowParensIf. * New functions ShowException and ShowSourceLoc instead of specializing the generic Show. By default Show should format the value in a way which is suitable as a subexpression of another value. * DecodeFloat returns the mantissa normalized, such that changing it by 1 yields the smallest increment of the original value. * New test: Hamming. * Unicode character database updated to Unicode 4.1.0. * Programs which use a deep stack don't use so much time in GC because minor GC now scans only the changed part of the stack. * Detection of pthreads should be more portable. * Bugs fixed: - Functions operating on flat sequences where the sequence size is a valid index (e.g. AddPart or IsGraphemeClusterBoundary) did not accept that index in Kokogut-0.5.3. - IsWordBoundary was True before control characters, should be False. - Python sys.argv is set to Kogut Parameters. Not sure whether this was a bug but pygtk crashed when there was no sys.argv. New in Kokogut-0.5.3 (29 March 2005), a release with pthreads and serialization: * There are three variants of ForkProcess in module System.Processes: - ForkProcess - other threads are stopped at a point where signals are unblocked; the process is forked; in the child process threads are canceled, and in the parent they are resumed - ForkProcessCloneThreads - all threads continue running in both processes - ForkProcessKillThreads - other threads are killed immediately with no cleanup (used before ExecProgram) * Kogut threads can optionally make use of OS threads, like in Haskell, to improve parallelism of foreign functions. The design is described in a paper by Simon Marlow, Simon Peyton Jones, and Wolfgang Thaller "Extending the Haskell Foreign Function Interface with Concurrency" A Kogut thread can be bound to an OS thread or unbound; conversely, an OS thread can be bound to a Kogut thread or be one of worker threads for executing unbound Kogut threads. The main thread and threads which currently run callbacks are bound. C code can unblock other threads during a computation which doesn't access the runtime, by bracketing it in KO_UNBLOCK_OTHER_THREADS() / KO_BLOCK_OTHER_THREADS() (the latter processes signals if they were unblocked and may throw an exception). These macros merely stop the timer if pthreads are not used. If ko_interrupt_by_signal(sig) is called before KO_UNBLOCK_OTHER_THREADS(), then a Kogut signal sent to this thread while it executes a foreign call will cause the given Unix signal to be generated to wake it up from a syscall. This state lasts until the next KO_BLOCK_OTHER_THREADS(). There is no problem with callbacks returning out of order when pthreads are used because they are run in separate OS threads. Since it's impossible to fork a process together with other pthreads, in the child process after ForkProcess and ForkProcessCloneThreads all threads other than the one doing the fork become unbound. If such orphaned thread returns from a callback, or if it was executing foreign code at the time of the fork, it is killed as with ForkProcessKillThreads, because the code it was supposed to return to was executing in another pthread which doesn't exist here. Switching between different bound threads, or between a bound and an unbound thread, is slower than switching between unbound threads. Since the main thread is bound, it can be useful to run the main computation in a different thread if it synchronizes with other threads a lot. * Serialization framework: - SerializeContext / DeserializeContext create an object which maintains serialization / deserialization of a sequence of objects. Their argument is a byte stream to write / read serialized objects to / from. A context manintains a dictionary of objects seen so far, to preserve sharing and cycles. Using the same context for several objects of the same type usually produces a smaller result. - 'Serialize context object' writes the object using the context. 'Deserialize context' reads an object using the context and returns it. - Function Serialization defines an unique name of a type and specifies how to serialize / deserialize objects of this type. SingletonSerialization and RecordSerialization allow to quickly define serializers and deserializers for singletons and records. Unique names should be globally unique (they are used to find the deserializer), so for types outside Prelude they should be qualified with a module name. - Only type objects for which serialization has been defined, or which have been registered with TypeSerialization, can be serialized. Only functions registered with FunctionSerialization can be serialized. - Only objects of types for which serialization has been explicitly defined are serializable. You cannot serialize lazy lists, generators, threads, handles to external resources like files, nor various transient objects like mutexes. Serializing a private symbol gives back a public symbol with the same name. - Serialized streams can be concatenated and read as one stream. * The initializer of a lazy variable is run with signals blocked. This is usually desirable, because otherwise an asynchronous exception could destroy a lazy variable which happened to be evaluated at that time. This semantics also applies to initializing modules other than the main module. For functions like ReadLines it would have an unhelpful effect of blocking signals while waiting for a resource. For these cases there is an additional way of constructing a lazy variable which avoids this problem. The definition: lazy name {obtain} ?resource {compute} and the function for lazy lists: Lazy {obtain} ?resource {compute} split the computation of the value of the lazy variable into two parts. The "obtain" part is run with only asynchronous signals blocked. If it fails (possibly due to an asynchronous exception), the exception is not recorded in the lazy variable, and the computation will be restarted when the variable is later evaluated again. If this part succeeds, the "compute" part is run as for a plain lazy variable: with all signals blocked, and with an exception being recorded in the variable forever. In the "compute" part, or during computation of the value of a plain lazy variable, you can call a new function CommitLazy with two arguments: the new "obtain" and "compute". This function throws a special exception which causes the lazy variable to go back to obtaining and processing a resource using the new functions. If the "obtain" part fails, any further restart will use the new functions. Operations which transform lazy lists to other lazy lists generally preserve the state of blocking signals. For example while Map waits for the next element of the input, synchronous signals are not blocked, and in the case of an exception the computation will resume when the result is later evaluated again; and while Map evaluates the function for some element, all signals are blocked and an exception causes the result to always fail when evaluated again. * Locking a read-write lock for reading blocks signals too, to avoid a deadlock when a signal handler would lock it again for writing. * New types BOOL_ARRAY and FLOAT_ARRAY. * New functions: - ReadByteFrom, PeekByteFrom, UnreadByteFrom, WriteByteTo - to be used with byte streams; function names with Char now work on char streams only - Sqr in module Math - square of a number - RandomBool and RandomBoolFrom in module Random - QueueSignal in module Threads - put a signal at the beginning of the signal queue of the current thread (SignalThread puts at end); makes possible to implement Erlang-style processing of selected signals while leaving other signals in the queue - ExitProgramImmediately - with no cleanup, from any thread - CloseOnExec in module System.Processes - get or set the FD_CLOEXEC flag of a descriptor - TouchObject in module Threads - takes one argument and does nothing, ensures that the object not garbage collected at this point yet * Virtual mutable variable HandlerOfSystemSignals in module Threads holds the thread which handles system signals. It is automatically changed to the main thread when the previous thread terminates. * Removed function LazyAppend. * New type REGISTERED_LIST which holds a list of registered items. Function RegisteredList() return a new list. An item is added to the beginning of a list by applying the list to the item. The result of this application is an object which can be used to unregister the item by applying it to no arguments. Adding an item is thread-safe. There are two ways to process items: - TraverseRegistered list nil cons - non-destructively - as long as there are remaining items, apply cons to the next item and a nullary function which traverses the rest of the list. otherwise return nil(); registering items while TraverseRegistered is running causes them to be processed this round, before remaining items - TraverseRegisteredUntilNow list nil cons - like TraverseRegistered, but registering items while TraverseRegisteredUntilNow is running doesn't cause them to be processed this round; this is faster - CutRegistered list absent present - destructively - if there is some item, remove the first item and apply present to it; otherwise return absent() If an item is registered multiple times, it is processed that many times, in the reverse order of registration. Unregistering an item while TraverseRegistered or TraverseRegisteredUntilNow is running causes it to be skipped if it's not already too late. Some existing registered lists of handlers: - AtExit - all handlers are run at program exit (but not after the body of ForkProcess nor before ExecProgram); a handler is a nullary function applied for side effects - AtUnhandledException - the first handler is run when an exception has not been caught and is going to terminate the program (before AtExit, and including the body of ForkProcess); a handler is a function with three parameters: the exception, the stack trace, and a nullary function which runs older handlers; a handler should return the exit code of the process; if a handler itself fails, older handlers handle its exception - AtForkProcess - the first handler is run by ForkProcess and ForkProcessCloneThreads (but not by ForkProcessKillThreads); a handler is a function with one parameter: a nullary function which runs older handlers and does the fork; the parameter should be applied exactly once and its result should be returned By default StdOut and StdErr are flushed at exit and fork. * FinalizeWeakRef waits until the finalizer completes if it's called during finalization. * In synchronous mode signals are processed only when the thread is actually going to block, not just when it calls a function which might block. * Threads which had to be preempted are penalized, so next time they don't hog CPU so much and interactive threads can be more responsive. As an exception, threads which are blocking signals are not penalized (perhaps they hold a lock which should be released soon). * A condition may be created without the predicate, but then a predicate must be given for Wait. * Importing under a changed name is changed back to newName:origName from origName:newName. * First-class module objects and a mechanism for qualifying imported names with module names: When a module is imported as 'use M:Full.Module.Name', then the name M is bound to an object of type MODULE. It can be used to access the contents of the module as a structure. For M being such a module name, M.name is resolved at compile time and 'ref M.name' exposes the original type of the variable object; for an ordinary constant M such expression would have type FUNCTION, even if the constant was bound to the same module value by 'let'. Some functions for examining modules are provided: - ModuleName module - the fully qualified name of the module as a list of symbols - ModuleContents module - contents of a module; for example if a module looks like this: module Some.Module; reexport Original.Module; // 'Foo' is a constant defined there dynamic Bar; reexport Baz:Module.Baz []; then its contents are presented like this: [ (#Foo, #const, Foo, [#Original #Module #Foo]) (#Bar, #var, ref Bar, [#Some #Module #Bar]) (#Baz, #module, Baz, [#Some #Module #Baz]) ] Modules are compared and hashed by their full names. When the same module is imported several times, it doesn't necessarily yield the same module object each time. * Inside a method definition the name 'super' is bound to a function which calls the next method, after the method it appears in. It may be called with different arguments than the current method was called with. The order of matching methods for the new arguments determines which method is next. * Types, generic functions, and modules can be built dynamically. This is mainly for a future interpreter, details are not described here. * The preferred forms of 'function' are: - function [param... {body} ...] - function ?param... {body} The old form 'function param... {body} ...' is deprecated. 'handle' and 'receive' also accept the analogous syntax without brackets when there is only one signal to handle. * 'function', 'loop' and 'receive' accept 'label:' before the cases which specifies a different name to be used instead of 'again'. * Changed heuristics for tuning the old heap size. Important variables: - KO_HEAP_LIMIT_RATIO, KO_MIN_HEAP_LIMIT (default: 2.0, 4MB) - the amount of old data which will trigger the next GC depends on the amount of live data after the previous GC: limit = live * KO_HEAP_LIMIT_RATIO + KO_MIN_HEAP_LIMIT - KO_HEAP_SIZE_RATIO, KO_MIN_HEAP_SIZE (default: 1.5, 4MB) - the size of the newly allocated old heap depends on the amount of used space before the GC: size = used * KO_HEAP_SIZE_RATIO + KO_MIN_HEAP_SIZE * New module Kogut.Stats for time, memory and thread statistics. When KoTetris is started with -s, it displays current statistics. * Documentation is licensed under the FDL. * SigInfo is exported when SIGINFO is supported (BSD). * Only interfaces intended for public use are installed (the lists of files are in lib/*/interfaces). * kogut-mode.el improvements: indentation is better; Emacs is instructed how to locate errors reported by kokoc. * Arrays which have much of their elements removed are physically shrunk during GC. * Bugs fixed: - ProcessSyncSignals was not blocking signals in signal handlers - The compiler failed on local types (thanks to Daniel Ehrenberg for reporting) New in Kokogut-0.5.2 (26 January 2005), a release with networking and with improved threads: * New type OBJECT_ID which is useful for dictionaries based on object identity. 'ObjectId obj' returns a hashable value representing the identity of obj, such that a given object each time yields the same object id. This is similar to Haskell's stable names. An object id doesn't keep the original object alive, can't be used to access it, and is not kept alive by the object either. If an object id is garbage collected, the new object id of the same object will not necessarily have the same hash value. The ObjectId function is primarily used as the key transformation function of HashDictBy and HashSetBy. * New types WEAK_HASH_DICT and WEAK_HASH_DICT_BY which do not keep their keys alive: keys which become garbage collected magically disappear from the dictionary. * Threads are no longer hashable. You can use ObjectId for dictionaries indexed by threads. * Weak references may also be applied to 1 or 2 arguments to reliably detect whether the key is dead: - weakRef() - return the value or Null - weakRef absent - return the value or 'absent()' - weakRef absent present - return 'present value' or 'absent()' * You can temporarily unlock a mutex using the Unlock function. * New type READ_WRITE_LOCK of locks, created by ReadWriteLock(). Functions LockRead and LockWrite establish a region where multiple readers or a single writer are allowed at a time. Functions UnlockRead and UnlockWrite temporarily unlock a lock. Function LockReadWillWrite locks a lock for reading, but declares that later it will possibly be upgraded to writing. Function UnlockReadWillWrite temporarily unlocks it. Only one thread at a time can have this kind of lock, to avoid deadlocks. It differs from a lock for writing in that it can be shared with regular readers. Function ChangeLockToWrite upgrades this kind of lock to writing, waiting for regular readers to exit the protected region first, and preventing other threads from entering it. It atomically downgrades the lock back at the end, without waiting. Function ChangeLockToRead does the opposite. The state upgraded to writing is the same as the state resulting from LockWrite. Neither upgrading nor downgrading allows another writer to intervene. This implementation does not keep track of which threads obtained which locks for reading, and thus performing UnlockRead by a thread which has not locked the lock for reading causes undefined behavior. Locking a lock for writing by a thread which already has locked it for reading causes a deadlock instead of an exception. * New test ReadersWriters which demonstrates the semantics of ReadWriteLock using curses animation. * New test Elevator which demonstrates non-trivial use of conditions. * The issue of blocking signals reworked again. The blocking state now consists of two parts: - all - the number of reasons for blocking all signals (a natural number or Inf) - async - whether asynchronous signals are blocked (0 or 1) When all == 0 & async == 0 (the default), signals are handled immediately. When all == 0 & async == 1, signals are handled only when the thread is suspended. In other cases all signals are blocked. Primitive building blocks of changes of blocking state (scoped over a subcomputation): - BlockSignals: all = Inf, async = 1 - UnblockSignals: all = 0, async = 0 - BlockSignalsMore: all = all + 1 - BlockSignalsLess: all = all - 1 (stays at 0 if it was 0) - BlockAsyncSignals: async = 1 - UnblockSyncSignals: all = 0 Implicit changes of blocking state by other operations: - handling an exception: BlockSignals - handling a signal: BlockSignals - using, LockRead, UnlockRead, LockReadWillWrite, UnlockReadWillWrite: - in the "acquire" part: BlockAsyncSignals - in the main part: no change - in the "release" part: BlockSignals - Lock, LockWrite, ChangeLockToWrite: - in the "lock" part: BlockAsyncSignals - in the main part: BlockSignalsMore - in the "unlock" part: BlockSignals - Unlock, Wait, UnlockWrite, ChangeLockToRead: - in the "unlock" part: BlockAsyncSignals - in the main part: BlockSignalsLess - in the "relock" part: BlockSignals * Deadlock of all threads is detected and reported as a Deadlock signal sent to the thread which handles system signals. If the program intentionally waits for system signals and does nothing else, it should do so only using 'receive' or 'SleepForever'. * ForkProcesses called with a process body leaves only the current thread in the child process. All others are killed immediately. When the body finishes or fails, the child process is terminated by _Exit(), without unwinding the stack. * RunProgram has a new named parameter redirect which replaces RunProgramRedirecting. If the redirect parameter is not Null, it may be #stdIn, #stdOut, #stdErr, or a tuple of them. It causes the return value to be a tuple of the pid and other ends of pipes redirected to specified standard streams. In this case the mode is ignored, it behaves as if it was #background. * WaitForThread is used as follows: - WaitForThread thread - WaitForThread thread ?exn {failed} - WaitForThread thread ?exn {failed} ?result {finished} * TimeLimit is used as follows: - TimeLimit {body} time {tooLong} - TimeLimit {body} time {tooLong} ?result {finished} The OUT_OF_TIME exception has been removed. * System signals use type SYSTEM_SIGNAL with field 'code', instead of INT. * Basic networking support in the Network library, module Network.Sockets, based on BSD sockets interface: - Address families and protocol families of type FAMILY: InetFamily, Inet6Family (optional), and UnixFamily. - Socket types of type SOCKET_TYPE: AnyType, DgramType, RawType (optional), SeqPacketType, and StreamType. - Protocols are represented by strings or numbers. Function GetProtocolInfo resolves a protocol to a record of type PROTOCOL_INFO with fields code, name, and aliases. - Sockets of type SOCKET. It may be the same as RAW_FILE (currently it is always the same). Function Socket creates an unconnected socket. It has keyword parameters family (default: DefaultFamily, which is Inet6Family or InetFamily by default), type (default: StreamType), and protocol (default: depends on the family and type). - Function SocketPair creates a pair of sockets connected to each other. It has the same arguments as Socket. - Addresses of type ADDRESS with fields family and data. Data is exposed as a byte array whose format depends on the family and on the system. Data is also exposed as a set of fields which depend on the address family: - InetFamily: port (0..65535), addr (a list of 4 bytes); some constants for the addr field: InetAddrAny, InetAddrBroadcast and InetAddrLoopback - Inet6Family: port (0..65535), flowInfo (0..2**31-1), addr (a list of 16 bytes), scopeId (0..2**31-1); some constants for the addr field: Inet6AddrAny, Inet6AddrLoopback; some predicates on the addr field: IsInet6AddrUnspecified, IsInet6AddrLoopback, IsInet6AddrMulticast, IsInet6AddrLinkLocal, IsInet6AddrSiteLocal, IsInet6AddrV4Mapped, IsInet6AddrV4Compat, IsInet6AddrMcNodeLocal, IsInet6AddrMcLinkLocal, IsInet6AddrMcSiteLocal, IsInet6AddrMcOrgLocal, IsInet6AddrMcGlobal - UnixFamily: path (string) There is a constructor Address with parameter family and named parameters: either data or family-dependent fields. The UnspecAddress constant can be used with Connect for clearing the default destination of datagram sockets. Even though data is a mutable byte array, addresses are immutable; a new array is created each time the data field is accessed. Addresses are compared and hashed by value. - Function GetAddrInfo resolves a host (string) and port (string or number) to a list of records of type ADDR_INFO with fields family, type, protocol, address, and canonName. Either the host or the port may be missing, but not both. Other keyword parameters of GetAddrInfo are family (default: find out automatically), type (default: StreamType), protocol (default: depends on the family and type), and flags: passive, canonName, numericHost, numericServ, v4Mapped, all, addrConfig (default: v4Mapped and addrConfig are True, others are False). - Function GetFirstAddrInfo returns the first element of the list returned by GetAddrInfo. - Function GetNameInfo translates an address to a pair of strings: host and port. It takes keyword parameters after the address: noFQDN, numericHost, nameReqd, numericServ, numericScope, and dgram. - Functions Connect and Bind take a socket and keyword parameters: either address, or arguments for GetFirstAddrInfo. - Function Listen takes a socket and a keyword parameter backlog (default: DefaultBacklog, which is 5 by default). - Function Accept takes a socket and returns a pair: a socket for the connection and the peer address. - Function Shutdown takes a socket and a symbol #read, #write, or #both. - Functions GetSocketName and GetPeerName take a socket and return an address. - Function SocketOption takes a socket, protocol level (SocketLevel, IPProtoIP, IPProtoIPv6, IPProtoICMP, IPProtoRAW, IPProtoTCP, IPProtoUDP), option name (#acceptConn, #broadcast, #debug, #dontRoute, #error, #keepAlive, #linger, #oobInline, #rcvBuf, #rcvLoWat, #rcvTimeO, #reuseAddr, #sndBuf, #sndLoWat, #sndTimeO, #type, #noDelay), and either gets the socket option, or takes the new value as the last argument and sets the option. The type of the value depends on the option name. - Function Receive takes a socket, byte array to fill, maximum size, and keyword parameters: peek, oob, and waitAll; it returns a boolean indicating the end of transmission. Function ReceiveFrom takes the same parameters and returns the sender address or Null if the address is unavailable. - Function Send takes a socket, byte array to send, maximum size, and keyword parameters: eor and oob. Function SendTo additionally takes the recipient address after the socket. - Function SocketStreams exposes a socket as a pair of streams: input stream and output stream of bytes. Closing both streams closes the socket. - Functions SocketTextStreams and SocketBinaryStreams expose a socket as a pair of {Text,Binary}{Reader,Writer}. They ensure that the writer is flushed before asking for input. They take keyword parameters for readers and writers. - Function ClientSocket is a convenience wrapper for Socket and Connect. Function ServerSocket is a convenience wrapper for Socket, Bind, and Listen. They take combined keyword parameters for the functions they use. The family of the address (if the address is given) or the result of resolving the name (if the host or port are given) influences the family, type and protocol of the socket. - Functions {ClientSocket,Accept}{,Text,Binary}Streams are convenience wrappers for {ClientSocket,Accept} and Socket{,Text,Binary}Streams. They take combined keyword parameters for the functions they use. * The default encoding may be overridden by the environment variable KO_DEFAULT_ENCODING. * Generators should generally be assumed to be safe to be traversed multiple times. The Iterator function, which ensures that a generator performs the work only once, should be treated as a hint for optimization rather than a device for correctness. Collect, ReadChars, ReadLines, ReadCharsFrom, ReadLinesFrom and DirectoryContents return lazy lists instead of generators. Old versions are available under names prefixed with Gen - they are faster but should only be used when the resulting generator is known to be consumed only once. * Removed function KeywordAllowOther. New function KeywordAndRest which is like Keyword, except that arguments which dit not match any keyword are appended to the result instead of being an error. * Renamed: - ExtractKeyword -> SplitKeyword - CollectGarbage -> GarbageCollect - MaybeCollectGarbage -> MaybeGarbageCollect * New functions: - KillWeakRef - like FinalizeWeakRef but without actually running the finalizer - SignalsBlocked, AsyncSignalsBlocked - determine the status of signal blocking (booleans only) - ProcessSyncSignals() - process signals if synchronous signals are unblocked - CancelableTimeLimit - like TimeLimit, but allow the action to cancel the timeout earlier, which is useful for ensuring a time limit on entering a protected region (note: this function establishes American spelling in Kogut names) * New abstract type SYSTEM_ERROR, a supertype of IO_ERROR and other similar errors. IO_ERROR is limited to errno codes, and you should catch SYSTEM_ERROR to include errors from getaddrinfo, Windows errors etc. (when they are implemented). * New type C_PTR in module Foreign.C, used for passing raw C pointers in Kogut code. * Concurrent initialization of a module by separate threads works. * New function StackTrace which returns the stack trace, currently in the form of a list of locations on the stack from top to bottom. Its argument is the number of top frames to skip (perhaps they belong to error handling code). * ForkProcess called with a block prints the stack trace if the block fails. * New module Unsafe with fast but unchecked operations on small ints (Unsafe{LT,GT,LE,GE,Add,Sub,Neg,Abs,Mul,Mul2,Div2,Not,And,Or,Xor}; IsSame can be used for equality), pairs (Unsafe{Left,Right}) and lists (Unsafe{Cons,First,Rest}). * New pattern syntax 'dynamic name', analogous to 'var name'. * Exceptions of types NOT_A_FUNCTION, BAD_TYPE and NO_FIELD include the bad object instead of its type. * {Byte,Char}{Input,Output}Buffer take keyword parameters instead of positional parameters. Added parameter flushAll, the level of flushing performed automatically after WriteTo, default: #none. Parameter flush renamed to flushLines, default changed to #soft. Flushing parameters to input buffers are accepted but ignored, to allow using the same set of options for input and output buffers. FlushingOther take keyword parameter flush, default: #soft. These parameters are dynamic variables. * epoll can be used for multiplexing I/O, available since Linux 2.6. epoll scales better than poll or select with lots of threads. Since epoll had a memory leak in Linux versions 2.6.0 to 2.6.7, Kokogut doesn't use it when ./configure is run on these kernels. You can override this choice by --with-epoll or --without-epoll. * Sleep is more accurate when using poll or epoll (near the end of the delay gettimeofday is called in a loop). * Garbage collection might be performed when all threads are idle. * On Linux sysinfo() is used to tune GC parameters: KO_MAX_HEAP_SIZE is set to half of totalram and KO_MAX_STACK_SIZE is set to a quarter of totalram. * In ncurses older than 5.4 patchlevel 20041002 wide character API was broken, so it's not used even if present. * Fixed NFC. Unicode specification had a bug in its NFC description: . Our implementation was affected. * Bugs fixed: - another weak reference bug which caused them to be sometimes finalized when the key is alive - when you close a file a thread is waiting for, the thread gets an exception instead of trying to use a closed fd - PyFormat did not work at all New in Kokogut-0.5.1 (10 November 2004), a release with Tetris: * New example: Tetris game. * Dates are aware of time zones and daylight saving time. The format of the timeZone field in DATE and the dynamic TimeZone variable is (tz, dst), where tz is the offset from GMT in seconds (positive = East) and dst is a flag which tells whether daylight saving time is in effect. The tz value includes the change caused by dst, i.e. dst doesn't affect interpretation of the time. The TimeZone variable is used for the current date, for conversion from TIME to DATE, and when making a date from fields with timeZone field missing or Null. If the TimeZone variable is Null too, which is the default, then the system-dependent default time zone for the given time is used. If the default is used to interpret a date composed of fields, rather than to set fields from a known time, the result is inherently ambiguous near the autumn clock adjustment. TimeNow() has been renamed to Time(), and DateNow() to Date(). The same functions with more arguments perform conversions as before. dayOfYear can no longer be provided in input. The equivalent effect can be obtained by setting the corresponding day of January. * The predicate associated with a condition variable is written explicitly, as the second argument of the Condition constructor or as the second argument of Wait. The Wait function begins by evaluating the predicate, and waits until it becomes true. * Reworked the issue of blocking signals. There are three states of a thread: - all signals are unblocked (the default) - all signals are blocked - synchronous mode: asynchronous signals are blocked, but they will be temporarily unblocked during an operation which suspends execution of the thread (other than obtaining a mutex or waiting for a C callback to return in the right order), i.e. waiting for a condition, waiting for a thread, waiting for a lazy variable, sleeping for some time, sleeping forever, waiting for I/O. Functions BlockSignals and UnblockSignals work as before, except that nesting levels are no longer counted: they unconditionally change the state during execution of their body. New function BlockAsyncSignals enters synchronous mode if signals were unblocked, and UnblockSyncSignals enters synchronous mode if they were blocked. Locking a mutex, obtaining a resource, and releasing a resource implicitly blocks asynchronous signals. Similarly, handling an exception and handling a signal blocks all signals. * Unknown signals are rethrown as exceptions directly instead of being wrapped in the UnhandledSignal exception. * A syntax for establising one-time signal handlers: - receive [pat {expr} ...] - receive [pat {expr} ...] time {expr} This expression waits for an asynchronous signal to come, or process the next signal immediately if it has been queued while signals were blocked. If the signal matches one of the patterns, computation continues with the corresponding expression. A timeout with a timeout handler can be specified. The name 'again' is implicitly defined in these expressions as a nullary function which waits for signals again. A case 'sig {Signal sig; again()}' is implicitly added at the end in order to process unmatched signals using their default handler. This behavior differs from 'receive' in Erlang which leaves unmatched signals in the queue. Signal blocking status does not affect the behavior of 'receive', but usually it only makes sense when signals are blocked. * The default signal handler (initial value of the Signal dynamic variable) is a generic function DefaultSignalHandler. * Stack overflow and heap overflow can be handled: When the stack of a thread grows too large (settable by the KO_MAX_STACK_SIZE environment variable, default = 128M), the thread receives StackOverflow signal. When the old heap grows too large (settable by KO_MAX_HEAP_SIZE as before, but the default is now 512M), the thread designated for handling system signals receives OutOfMemory signal. If the program does not reduce memory usage below limits despite signals, the signals will continue to be generated from time to time. But when the runtime really needs more memory and malloc() fails, the program will die with a fatal error. It only has a chance to handle these signals if limits are triggered before the memory is actually exhausted. * HandleSystemSignals is exported by the Threads module instead of System.Signals from Unix library, because now it applies not only to Unix signals. * Recursive locking of a mutex and recursive computation of a lazy variable are detected, and fail instead of deadlocking. * New test: Monitor (a somewhat more convenient but slower alternative to a mutex with conditions). * Additional private variable definitions, typically used in 'ifDefined', can be provided on kokoc command line (-Dname or -Dname=value) and in *.kop files ('switch = name' or 'switch = name=value'). * Functions ByteInputFilter, CharInputFilter, InputDecoder, ByteOutputFilter, CharOutputFilter, OutputEncoder may be rarely used explicitly. Instead, convenience wrappers have been added: - CopyByteInput, CopyCharInput, CopyByteOutput, CopyCharOutput (instead of ByteCopyingFilter and CharCopyingFilter) - CompressGZip, DecompressGZip, CompressBZip2, DecompressBZip2 (in addition to GZipCompressor, GZipDecompressor, BZip2Compressor and BZip2Decompressor, which are still useful with FilterArray). * WaitForProcess changes: - keyword parameter nonBlock has been renamed to block with the opposite meaning (default is True) - returns #wait (instead of Null) when the given process has not finished yet (possible only when block is False), and Null (instead of failing) when there are no processes to wait for. * Curses module provides ResizeTerm function when the underlying API is available, to be used in SigWinCh handler before redrawing the screen. * Renamed: - c_inline -> c_define - Timeout -> TimeAfter - JoinThread -> WaitForThread (in Threads) - {,W}Clear -> {,W}ClearScr (in Curses, to avoid name conflict with Prelude) - Box -> WBox (in Curses) - Color{Black,Blue,...} -> {Black,Blue,...} (in Curses) - Sleep is exported from Prelude rather than Threads * New functions: - TimeLimit (in Signals) - Box (in Curses) - {,Mv}{,W}{H,V}Line (in Curses) - RestoreCurses (in Curses) - to be called after SigTStp handling - UseDefaultColors, AssumeDefaultColors, DefaultColor (in Curses) - mixing default colors with specified colors, if the underlying curses library supports this * Removed WaitForSignal (use receive), TimedWait (use TimeLimit with Wait) and TimedJoinThread (use TimeLimit with WaitForThread). * New module System.Errors (in Unix library) with IOError constants. * Bugs fixed: - scheduler could hang, or not wake up a thread when it should - GZip library did not link in Kokogut-0.5.0 - AddChStr in Curses could crash - WeakRef could be finalized when the key is still alive - A thread started with ThreadBlockSignals could process signals if preempted just after it began executing * Improved portability with {Free,Net,Open}BSD, MacOS X, Solaris, and old versions of curses and gmp. New in Kokogut-0.5.0 (24 October 2004), a release with threads: * Threads, exported by module Threads. Overview of the interface: - Starting threads: Thread {body}, ThreadBlockSignals {body} - Current thread ID: CurrentThread - Mutexes: Mutex(), Lock mutex {body} - Condition variables: Condition mutex, Wait condition, TimedWait condition time, Notify condition, Notify1 condition - Doing nothing for some time: Sleep time, Yield() - Waiting for a thread to finish: JoinThread thread, TimedJoinThread thread time - Receiving asynchronous signals: BlockSignals {body}, UnblockSignals {body}, WaitForSignal(), SleepForever() - Sending signals: SignalThread thread signal, CancelThread thread, Signal signal; cancelling a thread throws ThreadExit exception in it by default - A box is empty or full, the thread will wait for the appropriate state (Haskell's MVar): Box(), Box value, Put box value, Take box - A queue with elements, the thread trying to take a value will wait until it is available: Queue(), PutLast queue elem, TakeFirst queue * Unix signals are translated to Kogut signals. They are represented by integers. Named constants for signals are in the System.Signals module from the Unix library. The function HandleSystemSignals() designates the current thread for receiving Unix signals; if it terminates, the main thread starts receiving them again. * New syntax for establishing signal handlers: - handle [pat {expr} ...] {body} - handle [pat {expr} ...] The old handler is available inside the new handler under the name 'super'. Signals which match no patterns are forwarded to the old handler automatically. If there is no handler for a signal, execution fails with the UnhandledSignal exception, except when it's a ThreadCancel signal as sent by CancelThread function (which is rethrown as ThreadCancel exception), or a Unix signal (which causes the default Unix reaction for that signal). If a thread other than the main thread doesn't catch an exception, and nobody joins the thread, the exception is silently dropped. If somebody joins it, he will receive the same exception. The program finishes when the main thread finishes. All other threads are instantly killed in this case. * New syntax for obtaining resources: - using {obtain} ?x {release} ?x {body} - using {obtain} ?x {body} // release defaults to Close - using {changeState} {restoreState} {body} This supersedes functions Using and Finally, which are usually unsafe in the presence of asynchronous exceptions. * Signals are automatically blocked during exception handling, signal handling, obtaining and releasing resources, and using a mutex. They are unblocked when the mutex is implicitly released for waiting for a condition. Nested blocking of signals requires the appropriate number of nested unblocking. Unblocking signals when they are already unblocked is an error. * If the value of a lazy variable is being computed, other threads trying to get the value will wait until it is available. * Added dynamically scoped variables of type DYNAMIC, similar to special variables in Lisp. They are defined by 'dynamic variable = value' or 'dynamic variable'; in the second form Null is assumed as the initial value. They are read and written like normal variables, and localized by 'local variable value {body}'. A localized binding shadows the previous binding of the same variable in the dynamic scope of the body. Dynamic bindings are inherited by newly created threads. Various global variables which set default parameters for some operations, like StdIn/StdOut/StdErr and DefaultEncoding, have been changed to dynamic variables. Language used for special case mapping rules is passed in dynamic variable Language instead of explicit parameter of case mapping functions. The name Signal actually refers to a dynamic variable which holds a function. * Type TIME represents a point of time. The current time is returned by TimeNow(). You can add/subtract numbers of seconds to/from times (of any real type), compare times, and subtract two times obtaining the number of seconds between them as a FLOAT. A time is internally represented by an integer number of ticks from the epoch (1970-01-01). You can construct a time from the number of ticks with the Time function, and get the number of ticks with time.ticks. The constant TicksPerSecond is exported. In Kokogut ticks are nanoseconds, but the resolution of TimeNow() is at most microseconds (gettimeofday). * A timeout (e.g. for Sleep) is specified as the duration in seconds or as the wakeup time of type TIME. Unix FileInfo returns file times as type TIME. * Module Calendar provides operations on dates expressed in Grerorian calendar. Type DATE represents a time with a time zone, split into fields year, month, day, dayOfYear, dayOfWeek (0 = Sunday), hour, minute, second, tick, and timeZone (difference in minutes). Dates can be compared; representations of the same time which differ only in the time zone compare as equal. You can construct a date with the Date function with keyword parameters corresponding to date fields. The Date function also converts a time to a date, using the time zone stored in the dynamic variable TimeZone. Conversely, the Time function converts a date to a time. DateNow() returns the current date. The Change function, generally used for records, supports changing fields in dates. Fields of a date may be provided out of range. In the resulting date they will be recalculated appropriately, causing adjustments of other fields. You may specify either a month with a day, or dayOfYear, and the other will be computed. You may not specify dayOfWeek as input. * KoScheme computation and input can be interrupted by ^C. * New function Collect ?give {body}, which generates elements to which give is applied inside body. Implementation of this function needs control inversion, which is done here with threads. * New pattern syntax 'is TYPE', equivalent to 'when Is TYPE'. * Added weak references of type WEAK_REF, based on the design in Glasgow Haskell. They are created by 'WeakRef key {finalizer}' or 'WeakRef key value {finalizer}'; in the first form the value is assumed to be the same as the key. You can get the value back by applying the weak reference to no arguments. A weak reference by itself doesn't keep its key, value nor finalizer alive. Instead it causes the key to keep the value and finalizer alive; this relationship exists no matter whether the weak reference is reachable. When a key remains referenced only by weak references, their values and finalizers, it is scheduled for finalization. Finalization happens in a thread started by the garbage collector. The value in the weak reference is reset to Null, the finalizer is detached from it, and is applied to no arguments for side effects. You can run the finalizer earlier manually by using FinalizeWeakRef function. It closes the relationship between the involved objects before the key becomes unreachable. A finalizer may resurrect the key by storing it in some accessible data structure. The finalizer will not be run again in this case. You can use weak references for just attaching finalizers to objects: make a weak reference and forget it. It's a bad idea to do that for statically allocated objects or small integers, as they will never be freed. Finalizers are not necessarily run at program exit. * Conditional compilation: the construct 'ifDefined cond {then} ...' can be used as an expression, pattern, or definition. Available forms of conditions: - name - true when the name was defined above or outside - module name - true when the module can be used - _ - always true (useful in the last case) - cond1 & cond2, cond1 | cond2, ~cond - combinations of conditions. If no condition is true, this construct expands to Null in expression context, a pattern which never matches in pattern context, and the empty definition in definition context. * Dynamic linking is supported on Linux/x86. The -fPIC flag is not used because it makes Kogut programs run twice slower, at least on x86; only some architectures permit building shared libraries without -fPIC. Unfortunately startup of a program using shared libraries built without -fPIC is slower, because it has to resolve lots of references. * Option --encoding on kokoc command line or encoding in *.kop specifies the character encoding of the source. * Non-ASCII characters may be used in names. * New functions: - MapMinimum, MapMaximum, MapSum, MapProduct - like composition of Map with Minumum etc., but defined more efficiently using Fold - Count - the number of elements of a collection satisfying a predicate * Renamed: - VARIABLE -> VAR - Persistent -> Iterator - SendSignal -> SignalProcess (in Unix.Signals) * Importing under a changed name is written origName:newName instead of newName:origName. * Fixed printing of stack traces which was broken almost forever. A function was shown in a trace only during its suspension for the first function call inside it. * Record constructor applications are inlined, constant records are allocated statically. Separate invocations of record constructors don't necessarily produce distinct objects (this was always intended as allowed behavior: records are pure structured value types). * Major internal changes in the frontend of the compiler (a new compilation phase has been added in the middle). Their effects - other than improved maintainability of the compiler - are small; sometimes slightly more efficient code is generated. Also other optimizations in other parts of the compiler. * Arithmetic on small ints is faster (avoids a function call). * Named functions have 'again' defined inside them too, like functions associated with 'loop', 'function' and specializations, even though you could also use their own names. This makes possible to consistently use the 'again' name for looping, including plain recursion. * kokoc-0.4.1 is now required for bootstrapping. New in Kokogut-0.4.2 (27 August 2004), a release with Perl bridge and complex numbers: * Perl bridge (module Foreign.Perl in library Perl). * Complex numbers (in module Math). Supported by KoScheme too. * Emacs mode for Kogut: kogut-mode.el. Provides syntax highlighting and automatic indentation. * Operator ** renamed to Power function, to free the core language from the dependency on complex numbers. * New functions: - Unfold - generate elements produced by a Next-like function - MapPairs, GenMapPairs - process each pair of consecutive elements (overlapped) - CharEqIgnoreCase, StringEqIgnoreCase (in Parsec) - Cons (in Parsec) - IfNull - convenience wrapper for if and IsNull - EncodingName - get the encoding name as a string; system encodings are represented by strings themselves, but other encodings are other objects * Renamed functions: - ReverseMap -> MapReverse (it applies the function in order according to the input, not output, so it's map and then reverse) * Curses binding uses the wide character API when it's available, overridable by ./configure --with-curses-chars=narrow|wide. The Curses module has been renamed to TextUI.Curses. Both variants yield the same Kogut interface. Names on the Kogut side correspond to the narrow character API, except one case: the interface of chtype values has been changed to mimic cchar_t. The type is called CCHAR in Kogut, and it conceptually includes an ATTR value instead of individual attributes. Its constructor, CChar, takes positional parameters instead of named parameters as before. Wide character support in ncurses-5.4 is currently buggy: add_wch ignores attributes and color of the character to be displayed, and get_wch doesn't recode keys from the locale encoding if it's different from UTF-8. * Coding errors are handled differently. Instead of a separate argument of functions which take an encoding, which used to specify how errors should be handled, converters by default fail on error. There is a wrapper for encodings, called ReplaceCodingErrors, which changes this behavior to substitute "?" on encoding and "\xFFFD;" on decoding. * OpenRawFile, CreateRawFile, OpenTextFile, CreateTextFile, and CreateDirectory take 'mode' keyword parameter. Functions for creating file modes are exported by System.FileStatus module from Unix library as before. This module exports two additional variables: DefaultFileMode and DefaultDirectoryMode. * New abstract supertype OUT_OF_RESOURCE of NOT_SUPPORTED, OUT_OF_MEMORY, and ARITHMETIC_OVERFLOW. * Kokogut should work on MacOS X, thanks to Mike Edgar and Daniel Ehrenberg. New in Kokogut-0.4.1 (31 July 2004), a release with improved sequences and random numbers: * Renamed Has to IsIn with swapped parameters. * Lazy lists are now "even", not "odd" - That is, a lazy list does not known whether it's empty until it is forced. And when it is forced, both its first and rest are evaluated. This means that the head of a lazy list is lazy. There is a single lazy list constructor called Lazy, which takes a function which evaluates either to a pair of first & rest, or Null. A lazy list is forced by taking its field called 'value'. There is no LazyCons, nor LAZY_CONS & LAZY_NIL subtypes. LazyAppend is still supported but perhaps it should be changed somehow. * Changed the interface of Next function, which was possible since lazy lists are even. It has one argument, and returns either a pair of first & rest, or Null. * Removed LookAheadWhich function from Parsec because a composition of LookAhead and Which works without unwanted extra evaluation, since lazy lists are now even. * New function ViewPart and type VIEW_PART, which makes a virtual copy of a part of a sequence. It's also used for iteration over indexed sequences instead of a lazy list. * Removed Iterator, IndexedIterator and LINKED_SEQUENCE. Renamed INDEXED_SEQUENCE to FLAT_SEQUENCE. The primary ways of consuming sequences are Traverse and Next. Collections except flat sequences must implement Traverse. They may also implement Next if they offer a more efficient implementation than conversion to a lazy list. * New functions: - FindPart - find a subsequence, return its index or Null - SplitSep, SplitEnd, SplitSeps - split a sequence on elements satisfying a predicate - SepBy, EndBy - insert a separator between every pair of elements or after every element - a generator - Persistent - ensure that elements of a sequence can be evaluated multiple times; it's usually the identity but it turns a generator into a lazy list - CutPart - functional equivalent of DoCutPart, i.e. the pair of Part and RemovePart - NextMany - iteration over many collections in parallel - ReverseOrder - for sorting in descending order - IsHSpace - horizontal whitespace - ProgramOutputLines - like ProgramOutput, but split by lines - a generator * New functions in Parsec: - ManyThen, ManyThen_, ManyBefore - parsing sequences until an end is matched (manyTill in original Parsec is our ManyBefore) - Somewhere, ReplaceAll, ReplaceFirst, ReplaceAtBegin, ReplaceAtEnd - wrappers for common tasks - Matches, Extract - convenience wrappers for Parse - Except - negative lookahead - OrReturn, OrCompute - more efficient than 'Or% Return x' - AHSpace, HSpaces, HSpaces1 - horizontal whitespace - NotSpace - Negation of ASpace * Renamed functions: - IterateWithLast -> IterateIncl - HasPrefix -> BeginsWith * Renamed functions in Parsec: - Recurse -> CallParser - FollowedBy -> Before - NotFollowedBy -> NotBefore - SepBy{,1} -> ManySep{,1} - SepEndBy{,1} -> ManyEnd{,1} - EndOfInput -> End * Removed functions: - JoinString (use SepBy and String) - ReturnNil, ReturnNull, EndBy, EndBy1 (in Parsec) * Modules for random numbers: - Random.Common - functions RandomFrom and RandomFloatFrom - Random.MT - implementation of the Mersenne Twister algorithm , type RANDOM_STATE with a constructor RandomState - Random - reexports the above modules, maintains a default random state (seeded with time and process ID) in global variable DefaultRandomState, provides functions Random and RandomFloat which use the default state. * Allocate, Fill and FillNew with a negative size are treated as empty. * The second element of Find and FindBack is optional, defaulting to 0 and size of the sequence respectively. * Functions ExecProgram, RunProgram, RunProgramRedirecting, ProgramOutput and ProgramOutputLines (in System.Processes) accept a command as a single string as an alternative to a program name with a list of arguments. A command is equivalent to "/bin/sh" ["-c" command]. New in Kokogut-0.4.0 (21 July 2004), a floating point release with Scheme: * An example Kogut program: KoScheme, a Scheme interpreter. Does not implement macros and complex numbers yet, but otherwise should conform to R5RS. * Type FLOAT, float literals, and arithmetic on floats is supported. * Swapped 2nd and 3rd argument of Iterate function, it's now 'Iterate start stop next' - because next is usually the most complex argument, and because it's consistent with Range. * Renamed functions: - Gcd -> GCD - IsAlpha -> IsLetter - IsAlphaNum -> IsLetterNum * New types: - EMPTY_INPUT (EmptyInput) - /dev/null - APPEND_INPUT (ByteAppendInput, CharAppendInput) - cat - COPYING_FILTER (ByteCopyingFilter, CharCopyingFilter) - tee * New functions: - iteration: 'Until start stop next' (iterates next on start until it satisfies stop, and returns the final value) - variant of Iterate which includes the last value: IterateWithLast - lazy append for lazy lists: LazyAppend - merge adjacent equivalent elements (Unix uniq): GenUnique, GenUniqueBy, Unique, UniqueBy - convert to list and sort: ListSort, ListSortBy - Unicode normalization: NFC, NFD, NFKC, NFKD - Unicode combining class: CombiningClass - simple single-character case mapping: UpperCaseChar, LowerCaseChar, TitleCaseChar - convert to FLOAT: Float (not implemented for strings yet) - round to a whole number or to a multiple of another number: Floor, Ceiling, Trunc, Round - find a simple rational which approximates a given number: Rationalize - bit shifts (positive shift: left, negative: right): BitShift - check the kind of a FLOAT number: IsFinite, IsNegZero - conversion between a FLOAT number and an INT pair (base, exponent): DecodeFloat, ScaleFloat - check whether a sequence is a prefix of another: HasPrefix * New modules: - Math - Pi, E, Sqrt, Exp, Log, Sin, Cos, Tan, ASin, ACos, ATan - Parsing.Parsec - a monadic parsing library, based on Haskell's Parsec by Daan Leijen * Shortcut syntax 'loop {body}' generalized to 'loop init... ?params... {body}' (equivalent to 'loop init... [params... {body}]', similar to named let in Scheme). * Show for INT supports new keyword arguments in addition to base:b and case:(#upper|#lower): - sign:(plus, minus) - how to show the sign; default: ("", "-") - showBase:s - how to show the base; default: "" - digits:n - minimal number of digits; default: 1 The implementation of Show for FLOAT is temporary, will be improved. * New tests: Parsec, ParseLib, AlgolQueue. New in Kokogut-0.3.0 (27 June 2004), a cleaned up release with improved Unicode support: * Kokogut-0.2.3 or newer is required to compile the compiler. * Removed deprecated features: - 'case' patterns (use 'match' or 'where') - 'is' function (use 'Is') - 'Conditionally' function (use 'optional' syntax) * Renamed collection functions to use the Do prefix for mutable variants instead of different verbs: - Insert{,First,Last,Part} -> DoAdd{...} - Delete{,First,Last,Part,Front,Back} -> DoRemove{...} - Cut{,First,Last,Part,Front,Back} -> DoCut{...} - Take{Front,Back} -> Cut{Front,Back} - InsertAll -> DoUnion - DeleteAll -> DoDifference - CutWhole -> DoCutWhole * New functions: - string padding: Right, Left, Center - sign of a number: Signum - generate iterated applications of a function until the result satisfies a predicate: Iterate - generate values of a dictionary: Values - character properties: CharCategory, IsAlpha, IsAlphaNum, IsControl, IsDigit, IsGraph, IsLower, IsMark, IsPrint, IsPunct, IsSpace, IsSymbol, IsUpper - text boundaries: IsGraphemeClusterBoundary, IsWordBoundary - case mapping: UpperCase, LowerCase, TitleCase, IgnoreCase - digit values: DigitToInt, IntToDigit * Renamed Iterate to Traverse. * 'Range n' is equivalent to 'Range 0 n'. * New functions: ',' and '\\', which generalize the corresponding builtin syntax to any number of arguments (greater than zero in the case of '\\'). * HashDict and HashSet are reimplemented, they are faster now. * New types: HASH_DICT_BY and HASH_SET_BY, which transform keys by a function for hashing and comparison with other keys. * New kind of C snippet, c_case: c_case [output] [input] [aux] " C code which must goto one of the labels defined below " [ label1:{branch1} label2:{branch2} ] * '=' can be used in patterns to visually separate the last argument of a macro application, like in expressions. * The generated code no longer needs the gcc extension of a non-empty initialization of a flexible array member of a static object. The code should now be easy to port to compilers other than GCC. * The mangler supports Intel C Compiler in addition to GCC. * A C compiler produces much less warnings even if they are enabled. Some hard to avoid warnings have remained though. * Maximum memory size defaults to 1024GB on 64-bit architectures. New in Kokogut-0.2.3 (14 June 2004), a yet more portable release with keyword parameters: * Portability improved again, thanks to SourceForge's compile farm and Arkadiusz Miskiewicz. Supported are yet earlier versions of gcc (down to 2.95.4), gmp (down to 2.0), Perl (down to 5.005_03), and bzip2 (down to 0.9.5). Actually it might work with even earlier versions, I haven't had an opportunity to test. * Fixed code which caused warnings on non-x86 architectures. The mangler now supports x86_64 (amd64) in addition to x86. Various fixes for FreeBSD have been applied. An embarrassing bug in Latin1 conversion has been fixed. Kokogut has been successfully built on other x86-linux boxes, on alpha-linux, x86_64-linux, and x86-freebsd. * Parameters 'interface-dir', 'include-dir' and 'library-dir' in *.kop and in kokoc invocation renamed to 'ifaces', 'includes' and 'libs'. * Added ./configure options --with-(gmp|iconv|gzip|bzip2|curses|python)-(includes|libs)=DIR * Prelude no longer exports many names which are not an official part of Kogut but implementation details of Kokogut. Foreign.C module exports some of these names, those useful for interfacing with C. * 'case' pattern renamed to 'match', to distinguish it visually from 'case' expression. 'case' is temporarily retained for compatibility with compiler sources. * A pattern 'where fun args... pat' is equivalent to 'x & match (fun x args...) pat', where x is a fresh name. This is analogous to 'when fun args...' being equivalent to 'x & if (fun x args...)'. * A Keyword function designed to be used in a pattern: '(where Keyword param1:default1 param2:default2 [pat1 pat2])...' which parses keyword arguments and binds patterns to their values, or to the default values if arguments with appropriate names are not given. If multiple arguments with the same name are given, the last one wins. * A KeywordAllowOther function which is similar to Keyword but does not fail if an unknown keyword or a non-keyword argument is found. * An ExtractKeyword function with two arguments, an argument list and a list of symbols, which partitions the argument list into two parts: arguments named with the given symbols, and other arguments. * Function 'is' renamed to 'Is'. Consistency is more important than the fact that 'when Is FOO' uses a funny combination of letter case. The name 'is' is temporarily retained for compatibility with compiler sources. New in Kokogut-0.2.2 (8 June 2004), a portability fix release: * Fixed a nasty bug in the mangler which manifested when kokogut was compiled with gcc-3.3.2. * Improved several portability issues: for earlier versions of gcc (flexible array members, local definitions after statements, broken stdbool.h included by other headers), GMP (mpz_ui_sub), zlib (Z_RLE), and Python (support versions 2.2 and 2.3, disable building the Python library on earlier versions). * Daniel Ehrenberg has written the Kogut FAQ. Thanks! * kogut.html includes a picture of a rooster that I've made. This might become the logo of the language :-) * TODO translated from Polish to English. * Added construct 'use Module except:[name list]' and similarly with reexport. * In the System.FileStatus module added interface to inspecting and making FileMode values (mode_t), and reading the mode and {a,m,c}time fields of FileStatus (struct stat). Renamed fields of FileStatus to lowercase. * In the System.Directories module added SymLink and ReadLink functions. New in Kokogut-0.2.1 (4 June 2004), a GC tuning release: * Environment variables can be used to tune the memory manager: - KO_MIN_STACK_SIZE - Initial stack size. Will grow as needed. Default: 64k. - KO_YOUNG_HEAP_SIZE - Size of the young heap. A larger size reduces the cost of garbage collection slightly, unless it causes things to no longer fit in processor cache, where the effect starts to be the opposite. Default: 64k. - KO_HEAP_RATIO, KO_HEAP_INCREMENT - The size of the old heap is approximately amount_of_live_data * KO_HEAP_RATIO + KO_HEAP_INCREMENT. Larger values reduce the cost of garbage collection but use more memory. The heap must fit twice in memory during a major garbage collection. Default: ratio = 1.5, increment = 4M. - KO_MIN_HEAP_SIZE, KO_MAX_HEAP_SIZE - Bounds of the old heap size. If the amount of live data is more than the maximum, the program is aborted. Default: min = 1M, max = 1G. - KO_MARKED_SIZE, KO_MARKED_RESERVE, KO_CHANGED_OBJECTS_SIZE - Initial sizes of various less important pools. Default: marked_size = 64k, marked_reserve = 1k, changed_size = 1k. - KO_SHOW_STATS - If set to 1, a statistics about time, memory and garbage collection will be printed to stderr after the program finishes. It also causes one extra major garbage collection, not counted in the statistics (to make other figures more accurate). Maximum memory used is sampled at major GCs. Memory sizes can be specified as a decimal number of bytes, with optional suffix k/M/G (case-insensitive, multipliers are 1024**N) and a possible decimal point. The heap ratio should be a real number from range 1..10. * The compiler proper uses less memory and is faster (about 1/3 faster, not counting the slowest stage: GCC). * Added 'optional' macro: 'optional cond {then}' is equivalent to '(if cond {[then]} else {[]})...'. Multiple conditions are allowed. * Added options -vs, -va, -vq, -vc, -vall (--verbose-source, --verbose-abstract, --verbose-sequential, --verbose-ccode, --verbose-all) which dump particular intermediate results of compiler phases to standard output. New in Kokogut-0.2.0 (29 May 2004), a priority tweaking release: * Added doc/NEWS file. * You can regenerate complete contents of the boot subdirectory from scratch using 'make install-boot'. * '~' operator has higher priority, between '->' and '%'. * '~foo _ 3' is interpreted as '?x {~foo x 3}' rather than '~?x {foo x 3}', which would always fail anyway. * 'label:' and '$' have the same priority. '.field', '@key' and '...' also have the same priority. This cuts down the number of priority levels, and it causes some errors to be detected at expansion time instead of parsing time. * Removed Not, All, Any. They were not used in practice, and now we have more convenient ways for negating functions. New in Kokogut-0.1.2 (25 May 2004), a release which can bootstrap from the previous one: * Package format changed from tar.gz to tar.bz2. * You can also bootstrap from a previously installed version if it's recent enough. The release is split into two packages: - kokogut-.tar.bz2 - only real sources, requires having a previously installed version to build. - kokogut--boot.tar.bz2 - includes also the boot subdirectory which contains C files to be usef for bootstrap. * Added script ./make-package to build tarballs automatically. * Project registered at SourceForge, awaiting approval. New in Kokogut-0.1.1 (25 May 2004), a portable bootstrapping release: * Reorganized bootstrapping. The version used for bootstrap consists of generated C files rather than Linux binaries. * 'make install' is implemented. * You can override various things ./configure tries to detect, e.g. which libraries to build and how to determine the default character encoding. New in Kokogut-0.1 (21 May 2004), a release for langsmiths: * First somewhat public release, announced only on langsmiths for now.