muSE v372 ...
Download - for macosx, for win32.
Summary of changes between v343 and v372 -
- Features: Simple module support, more flexible xml reader, polymorphic get and put.
- APIs: memports, muse_read_xml_node and muse_raise_error
- Bug fixes: GC fixes, muse_pread() and anonymous symbols.
Detailed changes -
Features
- Support for simple modules.
- The xml reader has been made slightly flexible in dealing with non-standard input. In xml tag attributes, attrib="value" and attrib='value' are standard but attrib=value is not. Since a lot of html code uses attrib=value form, this is also now accepted by the parser. Note that this is still not enough to accept old html files because they might contain non-xhtml tags such as <br> which should be <br/> in xhtml.
- Added a notion of a 'prop' view for getting and setting properties of arbitrary native objects. Properties are accessed and modified using (get obj prop) and (put obj prop value). i.e. get and put are now polymorphic over all object types that support the 'prop' view. See muse_prop_view_t struct for the interface.
- Added new "box" type in the same spirit as R5RS boxes.
- A symbol of the form ".name" will be expanded into the expression (-> self 'name) at read time. This makes it easy to refer to object properties from within method bodies.
- Made module names behave like "do", except that within the scope of the module expression's body, symbols are interpreted in the scope of the module - irrespective
of whether the module expression is at the global level or within a closure creating expression.
This feature is made possible by the introduction of a new "scope view" - id 'scop' - which lets an object provide a hook into the closure creation code to introduce local bindings that aren't visible in the s-expression itself.
The scope view lets us define context sensitive forms. Ultimately, all binding introducing forms - define, let, case, fn, fn: and gfn - can be implemented by providing a different scope view for each so that there is a constant testing overhead during closure creation instead of depending on the number of such special forms that need to be supported.
New APIs
- Memport objects can be created from the C api.
- muse_read_xml_node is now exposed in the C api.
- Added muse_raise_error() for raising muSE exceptions in native code.
Bug fixes
- (major): The main process structure was being prematurely destroyed before the gc function call returned. As a consequence, the area around the process's stack got corrupted and muse_destroy_env() won't exit cleanly. This went undetected because the primary use was via the repl which can be exited only using (exit) which terminates the whole process.
- (major): Major GC bug that crept in from a process related tweak to make the gc run atomically. Ever since the tweak (to wrap muse_gc_impl() within an atomic block) the gc never ran but simply grew the heap. FIXED! Whew! (I'd been wondering for a while why a gc never got triggered and the heap was grown instead during several large data set experiments, but didn't probe further. Lesson learnt - pay attention to your hunches!)
- (minor): muse_pread() wouldn't return EOF if there were only spaces or comments before end of file (or port in general). Modified it so that if only spaces and/or comments are found before it hits EOF, it dutifully fails.
* (minor): Anonymous symbols cannot have the sym itself as the head value any more due to process architecture. So changed the head value of anonymous symbols to () (or MUSE_NIL). Since this affects the gensym operator which converts an anonymous symbol into a permanently interned symbol, muse_intern_symbol was also modified to change the head value of an interned anonymous symbol to refer to the proper symbol location in the symbol vectors of all processes.
Other changes
- Native objects are no longer evaluated lazily when they appear in the function position. They are treated like any other native function. This allows us to define native objects which evaluate their arguments inside a special kind of context.
To compensate for this loss, the "lazy" operator's definition has been modified (and simplified) to cause a function application (native or user defined) to be
postponed until forced. Using the new "lazy" operator, you can use tail recursion with native functions too.