Showing posts with label release. Show all posts
Showing posts with label release. Show all posts

February 19, 2024

0.6.5: Changelog

Bumping up the version number was motivated by the breaking syntax change done recently. We do not offer specific builds for a given version number anymore since we provide automatic builds (with builds history) on each new master commit. Though, the changelog for new version number changes will still be provided...and this one is pretty big as it covers about 5000 commits! Hope this will help users who might have missed some changes to catch up.

613 PRs were merged, 2415 fix commits were pushed, among which 902 are closing issues tracked on Github. The most notable new features and changes are listed below with eventual links to docs or previous blog posts describing or mentioning them:

Main new features

  • New datatypes: money!, ref!, point2D!, point3D!.
  • New codecs: RedbinJSONCSV
  • New high-performance run-time lexer with instrumentation support.(blog)(doc)
  • Interpreter instrumentation support (debugger, tracer, profiler).(doc)
  • New powerful APPLY native, with deep interpreter support.(blog)
  • Dynamic refinements support.(blog)
  • Adds compress and uncompress natives with gzib, zlib and deflate algorithms support.
  • Adds gpio:// port with GPIO dialect for RaspberryPi.(blog)
  • Adds TAB navigation support to View. (blog)
  • Adds raw strings syntax support.(doc)
  • Swaps map! and construction syntax. (blog)
  • Hashtables are now used for fast lookups in contexts.
  • Custom dtoa library implementation to load and form float values.
  • Standard library and garbage collector stability vastly improved.

Finished or almost finished features in branches::
  • Full IO ports with async support, including new IPv6! datatype.(branch)
  • TextUI backend to View.(PR)
  • XML codec.(PR)

Other general new features or changes

  • New natives: TRANSCODE, SCAN, AS-MONEY, ENHEX.
  • New functions: SINGLE?, LAST?, DT, TRANSCODE-TRACE, TRACE, CLOCK, NO-REACT, DO-NO-SYNC
  • New routines: SET-TRACE, TRACING?
  • Extends EMPTY? to support map! values.
  • Allows NONE as value in map!.
  • Adds REMOVE/KEY support for removing map! entries.
  • Adds FOREACH support for map!.
  • Add new-lines automatically when converting maps to blocks.
  • Supports issue!, money! and refinement! as key in map
  • Allows any-string! series to be matched against binary input in PARSE.
  • Adds Accept-Charset and User-agent to HTTP header.
  • Update libcrypto version requirement on Linux platforms.
  • Adds support for native port actors.
  • Extends ROUND/TO to support time!.
  • Adds a cross-platform threading library to Red runtime library.
  • Adds a FIFO MPMC queue to Red runtime library.
  • Adds history support to Red console.
  • Extends GET native to accept any-word! as argument.
  • FIND is now returning FALSE instead of NONE when used on bitsets.
  • Deprecates FIND on objects (redundant with IN).
  • Adds ABOUT function to console.
  • Preprocessor: fetch-next now supports set-words/paths, get/lit-args, object/series paths.
  • COMPLEMENT is now allowed on tuples.
  • Adds RANDOM/SECURE.
  • SORT support of /skip & /all & /compare integer extended to strings, vectors and binaries.
  • Extends FIND/LAST to support hash!.
  • Allows FINDing by datatype and typeset on hash! series.
  • Removes percent-encoding from files, use double-quotes when needed instead.
  • Adds SYSTEM/CATALOG/ACCESSORS.
  • Allows pair! for COPY/PART argument on series.
  • Allows LOOP and REPEAT to take a float argument as counter.
  • Extends REDUCE/INTO to support hash! destination.
  • Extends BODY-OF to support action! and native! values.
  • REPLACE reimplemented.
  • Adds support for REVERSE/SKIP.
  • Extends VALUE? native supports any-word! argument.
  • Enable image! in red/core on Linux.
  • Adds GC support to libRed.
  • Extends DISTANCE? to support pair! arguments.
  • Adds /KEEP refinement to TRY.
  • Implements RENAME action for FILE! datatype.
  • Adds routine arguments type-checking support to compiler.
  • Accelerates the output speed of LIST-DIR.
  • Allows error! values to be modified by users.
  • Adds [trace] and [no-trace] function attributs.
  • Faster/simpler EMPTY? function implementation.
  • Forces the inclusion of Git information in the runtime.
  • Optimization for appending values into hashs.
  • Extends CHANGE to support image! argument.
  • PICK on pair!, date! and time! values now support named accessors as index argument.
  • Adds PICK action to event! datatype.
  • Makes RECYCLE returns the allocated memory total by default.
  • Cleaner implementation of deep reactive paths support.
  • Internalizes SYSTEM/STATE/NEAR value.
  • Compound scalar datatypes (pair!date!time! and tuple!) will now emit ON-CHANGE events when one of their component is changed using an access path (both in compiled and interpreted code).
  • Adds reactivity support to bitset! values.
  • Adds support for REFLECT action on bitset! values.
  • Reports a proper path in compiled path errors.
  • Adds memory usage before/after a GC cycle in debug output.
  • Measures GC time in debug mode.
  • [ARM] Adds "division by zero" and "division overflow" checks in debug mode.

Parse

  • KEEP PICK on paren expressions now merges list of values to collected block.
  • Optimizes Parse's KEEP memory usage on strings/binaries.
  • Removes the end checking in iteration rules.
  • Speed optimizations for `TO <token>` rules.
  • Adds a fast path for `TO/THRU end` rules.
  • New set of optimizations for looping on a char! value in PARSE.

VID

  • Smarter merging of actors in a style with custom actors in the instance.
  • Added password flag for hidden input
  • Adds scrollable flag.
  • defines VID origin and spacing values per backend.
  • adds next and prev as default options to VID-made faces.

View

  • Adds a calendar widget.
  • Adds support for tri-state checkboxes.
  • Significant GTK backend improvements and upgrades to match other backends.
  • Better handling of DPI changes.
  • Handles pause and scroll-lock keys.
  • Now EVENT/PICKED is a float wheel delta-value in on-wheel event.
  • Improves user experience when closing window that contains a large number of faces.
  • Scale the font size with Ctrl + mouse wheel in GUI console.
  • Adds stop-events function to easily exit a View events loop.
  • Adds resize-ns and resize-ew mouse cursors.
  • Adds bounds option to /options facet for restricted dragging area.
  • Adds new /sync refinement to VIEW function. 
  • Adds /color facet info to DUMP-FACE output.
  • Improves memory usage when changing /draw facet content.
  • Adds support for semi-transparent no-border top-level windows (Windows).
  • Minimal dark mode support on GUI console.

Draw

  • Switch command parameters to point2D! and float! for subpixel precision.(blog)
  • New Direct2D backend for Windows.
  • Add line-pattern command for drawing dashed lines.
  • Extends scale command to support percent! values.
  • Supports image mapping to arbitrary quadrilateral.
  • Removes matrix-order command in DRAW.

Red/System

  • Adds subroutines to R/S functions.(blog)
  • Implements system/io/* instrinsics for CPU I/O read/write instructions.
  • Adds system/stack/push-all and system/stack/pop-all intrinsics.(blog)
  • Support for atomic operations using system/atomic/* intrinsics.(blog)
  • Adds #inline directive to R/S for including assembled binary code.
  • Implements support for integer hardware division (ARMv7+).
  • Generates optimized code for divisions by a power of 2 literal (ARM).
  • Vastly improved loop counter handling robustness.
  • Full support for special float values (-0.0, 1.#NaN, 1.#INF, -1.#INF).
  • Drops support for % and // operators on float types.
  • Adds support for function pointers in literal arrays.
  • Switches to 16-bytes stack alignment on Linux.
  • Adds log-2 function to standard library.
  • Allows cross-referenced aliased fields in structs defined in same context.
  • Support multiple variable assignments.
  • Allows grouping arguments and local variables type specification.
  • Relax lexical format of hexadecimal literals.
  • Allows get-paths pointers on function nested in contexts.
  • Adds support for simple pointer to pointer type.
  • Allows function! type to be specified for local variables.

Toolchain

  • Optimizes critical section in linker, twice faster linking time now on average.
  • Adds --show-func-map compilation option.
  • Various minor improvements to PE format support.
  • Adds working Linux-musl target.
  • Expands libRedRT to support View backend.
  • Adds --no-view option for Red binaries.
  • Shows the global words used by the toolchain in the compilation report.
  • Adds new Pico compilation target.

March 26, 2017

0.6.2: LibRed and Macros

It is with great pleasure that we announce the 0.6.2 release of the Red programming language and toolchain. This release is the second heaviest one we have ever made (after the 0.6.0), weighing about 1200 commits! It was intended initially to be a minor one, but the needs for preprocessing support for Red runtime code arose, so it was the right time to make a first iteration into the land of macros. Moreover, the work on libRedRT (described below) gave us the opportunity to fulfill one of the goals we had for Red: become embeddable. This is now a reality, thanks to libRed. So the main features of this release are:

  • Macros and preprocessor support
  • Fast compilation using libRedRT
  • LibRed for embedding Red anywhere

Macros

The Red macros and preprocessing abilities have been the topic of a previous article, so I invite you to discover them (and hopefully enjoy!) if you have not yet done so.

In addition to this article, it is worth mentioning that a feature called pre-load has been implemented since then (you can read about it down below), which can be used as an entry point for user-provided reader macros, and allow easier support for non-standard syntax. This is a minor feature, as Rebol-like languages already come strongly equipped for string parsing and processing, thanks to the Parse dialect.


Development and release modes for compilation

The biggest change introduced by this new version is the splitting of the compilation process in two modes, which are controlled by different command-line options:

  • development: (-c) only user code is compiled (new mode).
  • release: (-r) both user code and Red runtime library are compiled together.

When using -c, the Red runtime library is pre-compiled to a dynamic library called libRedRT ("RT" for RunTime), stored in the hidden red/ folder. When libRedRT is already present, only user code is compiled resulting in drastically shorter compilation times.

When -r option is used, the toolchain compiles user code in release mode, compiling with it all dependencies (including Red runtime library).

Here are a couple of simple benchmarks to show the (huge) difference in performance, using hello.red and view-test.red scripts compiled in both modes:


Another benchmark is compiling the Red tests suite (~18000 tests), unified way combines the tests into the minimum number of compilation units, while split way compiles each test file separately:


Measured on a Corei7 4Ghz Win7/64-bit machine.

Such performance results in significant daily productivity gains, both for the Red team, and Red users. It was worth the time and effort it took to properly convert the runtime library into a shared library. Though, the full support for modular compilation will come in 0.8.0, which will result in drastic cuts for the compilation time in release mode too.

Such fast compilation mode also works for Red scripts that embed Red/System code. Two cases are possible:
  1. Red/System code does not contain any call to Red runtime library.
  2. Red/System code contains one or several calls to Red runtime library.
In the first case, nothing needs to be done, the usage rules described above apply.

In the second case, a custom version of libRedRT is required, but the toolchain will take care of the process, it just requires the user to compile once using -u option, then simply use -c for next compilations. If new functions from the runtime library are called, then a new custom library needs to be rebuilt.

When compiling a custom run-time library, cleaning libRedRT files is needed to get rid of any outdated versions. The toolchain provides a red clear command which will remove all current libRedRT related files. Note that when upgrading the red binary to a newer version, it will automatically upgrade libRedRT on first invocation.

Any Red user code can be compiled in development mode, with the exception of objects with multiple inheritance, which is not supported by libRedRT (so can only be compiled in release mode).


Embedding Red using libRed

LibRed is the embeddable version of the Red interpreter + runtime library. It includes Parse dialect, reactive programming and our GUI system (View engine, VID dialect, Draw dialect). It exposes an interface to the host language through an API, which is C-compatible, so that any language that can embed C shared libraries, can also embed libRed.

The libRed API has been designed to be as simple and as straightforward as possible. See for yourself in the API documentation. The role of that API is to provide the required hooks for interfacing the Red runtime and interpreter with the host language. A high-level binding can eventually be built on top of the libRed C-level API, that will best map Red features, to the host language features.

A libRed HelloWorld in C:
    #include "red.h"

    int main() {
        redOpen();
        redPrint(redString("Hello World!"));
        redClose();
        return 0;
    }
A libRed graphic HelloWorld in C:
    #include "red.h"

    int main() {
        redOpen();
        redDo("view [text {Hello World!}]");
        redClose();
        return 0;
    }

In addition to the C-level API, we provide also a binding for VisualBasic for Applications, which can be used to embed Red into Microsoft Office applications!

Here is a demo showing side-by-side an Excel/VB window and a Red window playing Pong game:


All the code for this demo fits in a single page of VB code! You can get the required files from here. In that same Excel file, you will find two other simple examples of integration of Red with Excel sheets, which look like this:



Building libRed is straightforward:
    red build libred
That will build libRed with the cdecl ABI, suitable for integration with any C-compatible host. For VBA and MS Office, the stdcall ABI is required, which is achieved using:
    red build libred stdcall
The building process will also result in creating a libRed/ directory locally, expanding some extra files required for linking libRed properly.

Currently, full bindings are provided for C and VisualBasic. Experimental bindings are also available for RustAdobe AIR and C#.

This is a first iteration for libRed, we have plans for improving it, and for providing proper multi-instances support (currently limited at one instance per process).


Changes in 0.6.2

Core language
  • New datatypes: tag!, email!
  • New action: to
  • New natives: as, call
  • New functions: tag?, email?, hex-to-rgb, sqrt, class-of, face?, distance?, expand-directives, to-*, rejoin
  • Adds integers auto-promotion to floats on loading and on some integer operations.

If you need to preprocess the input to LOAD, you can now do it easily by plugging a function into system/lexer/pre-load. This feature is mostly meant for pre-processing the console's input, though it could also be used for changing some Red syntactic rules. For example:
    system/lexer/pre-load: func [src part][replace/all src comma space]

    >> [1,2,3,abd,"hello"]
    == [1 2 3 abd "hello"]
Another usage could be to translate words on-the-fly in the console:
    system/lexer/pre-load: function [src part][
        parse src [
            any [
                s: [
                    "affiche"       (new: "print")
                    | "si"          (new: "if")
                    | "tant que"    (new: "while")
                    | "pair?"       (new: "even?")
                    | "impair?"     (new: "odd?")
                ] e: (s: change/part s new e) :s
                | skip
            ]
        ]
    ]

    >> i: 10 tant que [i > 0][si impair? i [affiche i] i: i - 1]
    9
    7
    5
    3
    1

In addition to several small fixes, load now offers a /trap refinement, which enables manual error management when loading a string series. Instead of raising an error, load/trap will just stop and return a block made of:
  • a block of successfully loaded values.
  • the input string at the position where the lexer failed.
  • an error! value (or none! value if the tail of the string has been reached).

Command-line argument processing has been mostly rewritten to provide a consistent experience across platforms and type of binaries (red executables, console executables, compiled user scripts and, to a lesser extent, Red/System executables). The new features are:
  • system/options/script refers to the script name (string! or none!).
  • system/options/args refers to a list of tokenized arguments (block! or none!).
  • system/script/args refers to the original command-line (string! or none!).
  • full Unicode support for red executable's arguments on Windows.
  • single-quoted arguments are accepted on all platforms (same as double quotes)
  • multiple nested quotes are treated as just one level of quoting when splitting the command-line.

Datatypes conversions are now fully supported in Red! The to action is now officially supported, and make action has been completed. The usual to-<type> helper functions you can find in Rebol, are also now defined. All the conversion rules are documented in an Excel matrix for now.

Call

Calling external applications is also now possible thanks to the contributed code for call function by Bruno Anselme, which has now been integrated into the runtime library. Use help call to explore all the options offered. Note that the /console option, which redirects I/O from child process, is not supported currently by the Red GUI console (it works fine from within the Red CLI console).

View and VID dialect

A number of small changes and fixes have been provided both in View and VID, among them:
  • box, h1 to h5 styles added to VID.
  • Colors in VID can now be specified as hex values, using #rgb or #rrggbb formats.
  • Adds support for no-border flag to area and field face types.
  • Adds now option to rate keyword in VID, to fire on-time actor at once.
  • The wheel event  and on-wheel actor are now available for handling mouse wheel events.
  • Default tab size for area changed to 4 spaces.
  • View now uses DirectWrite to draw text in base face (except WindowsXP).
  • Better handling of default fonts.
  • Enhanced GUI console, with new settings window with pre-selected colors picker.
  • A hint text can now be specified in a field options block and a hint keyword has been added to VID. For example:



Draw dialect

Big additions were made to Draw, most thanks to massive contributions from Zamlox:

  • Matrix operations support: matrix, invert-matrix, reset-matrix, matrix-order, push, rotate, scale, translate, skew, transform.
  • A new clip command is available for defining a clipped drawing/filling region.
  • A Shape sub-dialect has been added for more complex shapes drawing and filling.
  • A crop option is now available for image command.
  • pen and fill-pen have been vastly extended to allow drawing and filling with gradients, patterns, arbitrary shapes and images. Have a look at some of the new capabilities (source):



Parse dialect

In addition to some fixes, a few new features were added:
  • insert command now also support position argument (like change).
  • added pick option to keep, so user can control how keep captures the matched input:
    • keep collects matched values as a series if many, or as a value if only one.
    • keep pick collects all the matched values separately in a block.
    • keep copy <word> collects all the matched values as a single series (of same type as input).

Red/System dialect

  • Support for float! / float32! conversions from/to integer!.
  • Adds system/cpu/overflow? field for reading CPU's integer overflow state.
  • Adds support for importing variables from shared libraries.
  • Allows loading of libraries from current folder and PATH environment variable on macOS.
  • Now #call directive supports function calls with refinements.
  • Default ABI for exported functions is now settable through export-ABI entry in config object.
  • Renamed log and log10 imports from libC, respectively to log-2 and log-10.
  • Now size? accepts a context path argument.
  • Improved error reporting for "missing argument" errors.

Other changes

  • A prototype Red/.Net bridge has been introduced.
  • New --config [...] command-line option, for passing a block of compiler settings.
  • Added -s and --show-expanded command-line options to output expanded version of compiled source code.
  • Added /target option to react?.
  • Added /seek and /lines option to write.
  • Added /expand refinement to do for preprocessor invocation.
  • Added math function for evaluating code using math precedence rules.
  • CTRL-L key combination can now clear the GUI console's screen.
  • Checksum function can now trigger object on-deep-change event.
  • Now keep returns its argument (collect function).
  • Added temporary rejoin function.
  • Added 'class reflective property to objects.
  • Added class-of accessor (only objects).
  • Nicer handling of line breaks in molded image! binary buffer.
  • Now #include is converted to do in interpreted code (using macros).
  • Zero? function is now a native and supports time! values.

Also, more than 150 issues have been fixed (and wishes granted) during the last months, 22 issues marked as bugs are left open.

Last but not least, our documentation on Gitbook (which is an ongoing work) has been moved to Asciidoc format now, thanks to the efforts of Tovim. That new format will provide us better options for a more accurate control of the styles and layout.

A big thank goes to all contributors who pushed code or who opened tickets clearly identifying issues.

What's Next?

Since 0.6.1, we have adjusted the Red roadmap to work on two releases in parallel. This means that while 0.6.2 was progressing, 0.6.3 was advancing at the same time, is now almost ready, and will be merged into master in a couple of days (if you happen to have a Mac, it contains the macOS GUI backend for Red!). As soon as 0.6.3 is out, 0.7.0 will start (full async I/O), while 0.6.4 (Android) is being worked on. That should provide us a higher number of new releases this year, while still implementing large new features. So far, such approach has worked pretty well.

In the meantime, and as usual, enjoy playing with Red!

December 22, 2014

0.5.0: Objects support

We are bumping the version number up higher as we are bringing a new foundational layer and important construct to Red: object! datatype and contexts support.

Supporting objects in the Red interpreter is relatively easy and straightforward. But adding those features in the compiler has proven to be more complex than expected, especially for access-path support, paths being especially tricky to process, given their highly dynamic nature. Though, I have pushed Red beyond the edges I was planning to stop at for objects support, and the result so far is really exciting!

Object model

Just a short reminder mainly intended for newcomers. Red implements the same object concept as Rebol, called prototype-based objects. Creating new objects is done by cloning existing objects or the base object! value. During the creation process, existing field values can be modified and new fields can be added. It is a very simple and efficient model to encapsulate your Red code. There is also a lot to say about words binding and contexts, but that topic is too long for this blog entry, we will address that in the future documentation.

Object creation

The syntax for creating a new object is:
    make object! <spec>
 
    <spec>: specification block
Shorter alternative syntaxes (just handy shortcuts):
    object  <spec>
    context <spec>
The specification block can contain any valid Red code. Words set at the root level of that block will be collected and will constitute the new object's fields.

Example:
    make object! [a: 123]
    
    object [a: 123 b: "hello"]
    
    c: context [
       list: []     
       push: func [value][append list value]
    ]
You can put any valid code into a specification block, it will be evaluated during the object construction, and only then.

Example:
    probe obj: object [
        a: 123
        print b: "hello"
        c: mold 3 + 4
    ]
will output:
    hello
    make object! [
        a: 123
        b: "hello"
        c: "7"
    ]
Objects can also be nested easily:
    obj: object [
        a: 123
        b: object [
            c: "hello"
            d: object [
                data: none
            ]
        ]
    ]

Another way to create an object is to use the copy action which does not require a specification block, so does just a simple cloning of the object. Existing functions will be re-bound to the new object.

Syntax:
    copy <object>
Object access paths

In order to access object fields, the common path syntax is used (words separated by a slash character). Each word (or expression) in a path is evaluated in the context given by the left side of the path. Evaluation of a word referring to a function will result in invoking the function, with its optional refinements.

Example:
    book: object [
        title: author: none
        show: does [print [mold title "was written by" author]]
    ]

    book/title: "The Time Machine"
    book/author: "H.G.Wells"
    print book/title
    book/show
will output:
    The Time Machine
    "The Time Machine" was written by H.G.Wells
SELF reference

A special keyword named self has been reserved when self-referencing the object is required.

Example:
    book: object [
        title: author: none
        list-fields: does [words-of self]
    ]
    book/list-fields
will output:
    [title author list-fields]
Object inheritance

While cloning produces exact replicas of the prototype object, it is also possible to extend it in the process, using make action.

Syntax:
    make <prototype> <spec>

    <prototype> : object that will be cloned and extended
    <spec>      : specification block
Example:
    a: object [value: 123]
    
    c: make a [
        increment: does [value: value + 1]
    ]
    
    print c/increment
    print c/increment
will output:
    124
    125
It is also possible to use another object as <spec> argument. In such case, both objects are merged to form a new one. The second object takes priority in case both objects share same field names.
 
Example:
    a: object [
        value: 123
        show: does [print value]
    ]
    b: object [value: 99]
    
    c: make a b
    c/show
will output:
    99
Detecting changes in objects

Sometimes, it can be very useful to detect changes in an object. Red allows you to achieve that by defining a function in the object that will be called just after a word is set. This event is generated only when words are set using a path access (so inside the object, you can set words safely). This is just a first incursion in the realm of metaobject protocols, we will extend that support in the future.

In order to catch the changes, you just need to implement the following function in your object:
    on-change*: func [word [word!] old new][...]
    
    word : field name that was just affected by a change
    old  : value referred by the word just before the change
    new  : new value referred by the word
It is allowed to overwrite the word just changed if required. You can directly set the field name or use set:
    set word <value>
Example:
    book: object [
        title: author: year: none
  
        on-change*: func [word old new /local msg][
            if all [
                word = 'year
                msg: case [
                    new >  2014 ["space-time anomaly detected!"]
                    new < -3000 ["papyrus scrolls not allowed!"]
                 ]
            ][
               print ["Error:" msg]
            ]
        ]
    ]

    book/title: "Moby-Dick"
    book/year: -4000
will output:
    Error: papyrus scrolls not allowed!
Extended actions and natives for objects

You can use set on an object to set all fields at the same time. get on an object will return a block of all the fields values. get can also be used on a get-path!.

Example:
    obj: object [a: 123 b: "hello"]
    probe get obj
    set obj none
    ?? obj
    set obj [hello 0]
    ?? obj
    probe :obj/a
will output:
    [123 "hello"]
    obj: make object! [
        a: none
        b: none
    ]
    obj: make object! [
        a: 'hello
        b: 0
    ]
    hello

Find action gives you a simple way to check for a field name in an object. If found it will return true, else none.

Select action does the same check as find, but returns the field value for matched word.

    obj: object [a: 123]
    probe find obj 'a
    probe select obj 'a
    probe find obj 'hello
will output:
    true
    123
    none
The in native will allow you to bind a word to a target context:
    a: 0
    obj: object [a: 123]
    probe a
    probe get in obj 'a
will output:
    0
    123

Bind native is also available, but not completly finished nor tested.

Reflectors

Some reflective functions are provided to more easily access objects internal structure.

  • words-of returns a block of field names.
  • values-of returns a block of field values.
  • body-of returns the object's content in a block form.

Example:
     a: object [a: 123 b: "hello"]
     probe words-of a
     probe values-of a
     probe body-of a
will output:
    [a b]
    [123 "hello"]
    [a: 123 b: "hello"]
SYSTEM object

The system object is a special object used to hold many values required by the runtime library. You can explore it using the new extended help function, that now accepts object paths.
red>> help system
`system` is an object! of value:
    version          string!   0.5.0
    build            string!   21-Dec-2014/19:27:05+8:00
    words            function! Return a block of global words available
    platform         function! Return a word identifying the operating system
    catalog          object!   [datatypes actions natives errors]
    state            object!   [interpreted? last-error]
    modules          block!    []
    codecs           object!   []
    schemes          object!   []
    ports            object!   []
    locale           object!   [language language* locale locale* months da...
    options          object!   [boot home path script args do-arg debug sec...
    script           object!   [title header parent path args]
    standard         object!   [header]
    view             object!   [screen event-port metrics]
    lexer            object!   [make-number make-float make-hexa make-char ...
Note: not all system fields are yet defined or used.

Future evolutions

As this release already took a lot of time, some of the planned features are postponed to future releases. Here are a few of them.

Sometimes, it is convenient to be able to add fields to an object in-place, without having to recreate it, losing lexical binding information in the process. To achieve that, a new extend native will be added, working like originaly intended in Rebol3.

In order to help the Red compiler produce shorter and faster code, a new #alias compilation directive will be introduced. This directive will allow users to turn an object definition into a "virtual" type that can be used in type spec blocks. For example:
    #alias book!: object [
        title: author: year: none
        banner: does [form reduce [author "wrote" title "in" year]]
    ]
    
    display: func [b [book!]][
        print b/banner
    ]
This addition would not only permit finer-grained type checking for arguments, but also help the user better document their code.

Another possible change will be in the output mold produces for an object. Currently such output will start with "make object!", this might be changed to just "object", in order to be shorter and easier to read in addition to be more consistent to the way function! values are molded.

Fixed issues

In order to make this release happen as quickly as possible, we have not fixed all the open tickets that were planned to be fixed in this release, but we still managed to fix a few of them. The other pending tickets will be fixed in the upcoming minor releases.

I should also mention that 537 new tests were added to cover objects features. The coverage is already good, but we probably need more of them to cover edge cases.

That's all for this blog article! :-)

I will publish another blog entry about additional information regarding the implementation strategy used by the compiler for supporting contexts and object paths.

As we have almost completed other significant features during the last months, you should expect new minor releases happening very quickly in the next weeks. They will include:

  • New cross-platform console engine written entirely in Red (no dependencies).
  • New Android toolchain for creating APK files 100% ported to Red (no dependencies).
  • Full error and exceptions support at Red level.
  • Redbin initial implementation (not started yet).

Also, the work for 0.6.0 has started already (GUI support), even if its at prototype stage right now. I plan to release a first minimal version in the next few weeks (we will extend it step by step until 1.0).

Hope the waiting for the new release was worth it. ;-)

November 30, 2013

0.4.1: Introducing Parse


One of the greatest feature of the Rebol language has always been its parsing engine, simply called Parse. It is an amazing piece of design from Carl Sassenrath, that spared all Rebol users for the last 15 years, from the pain of having to use the famously unmaintainable regexps. Now, Parse is also available to Red users, in an enhanced version!

So, in short, what is Parse? It is an embedded DSL (we call them "dialects" in the Rebol world) for parsing input series using grammar rules. The Parse dialect is an enhanced member of the TDPL family. Parse's common usages are for checking, validating, extracting, modifying input data or even implementing embedded and external DSLs.

The parse function call syntax is straightforward:
    parse <input> <rules>  

    <input>: any series value (string, file, block, path, ...)
    <rules>: a block! value with valid Parse dialect content
Here are a few examples, even if you don't know Red and Parse dialect, you can still "get" most of them, unlike regexps.  You can copy/paste them directly into the Red console.

Some simple examples of string or block input validation using grammar rules:
    parse "a plane" [["a" | "the"] space "plane"]
    parse "the car" [["a" | "the"] space ["plane" | "car"]]

    parse "123" ["1" "2" ["4" | "3"]]
    parse "abbccc" ["a" 2 "b" 3 "c"]
    parse "aaabbb" [copy letters some "a" (n: length? letters) n "b"]

    parse [a] ['b | 'a | 'c]
    parse [hello nice world] [3 word!]
    parse [a a a b b b] [copy words some 'a (n: length? words) n 'b]

How to parse an IPv4 address accurately:
    four:     charset "01234"
    half:     charset "012345"
    non-zero: charset "123456789"
    digit:    union non-zero charset "0"

    byte: [
          "25" half
        | "2" four digit
        | "1" digit digit
        | non-zero digit
        | digit
    ]
    ipv4: [byte dot byte dot byte dot byte]

    parse "192.168.10.1" ipv4
    parse "127.0.0.1"    ipv4
    parse "99.1234"      ipv4
    parse "10.12.260.1"  ipv4

    data: {
        ID: 121.34
        Version: 1.2.3-5.6
        Your IP address is: 85.94.114.88.
        NOTE: Your IP Address could be different tomorrow.
    }
    parse data [some [copy value ipv4 | skip]]
    probe value                      ; will ouput: "85.94.114.88"


A crude, but practical email address validator:
    digit:   charset "0123456789"
    letters: charset [#"a" - #"z" #"A" - #"Z"]
    special: charset "-"
    chars:   union union letters special digit
    word:    [some chars]
    host:    [word]
    domain:  [word some [dot word]]
    email:   [host "@" domain]

    parse "john@doe.com" email
    parse "n00b@lost.island.org" email
    parse "h4x0r-l33t@domain.net" email

Validating math expressions in string form (from Rebol/Core manual):
    expr:    [term ["+" | "-"] expr | term]
    term:    [factor ["*" | "/"] term | factor]
    factor:  [primary "**" factor | primary]
    primary: [some digit | "(" expr ")"]
    digit:   charset "0123456789"
    
    parse "1+2*(3-2)/4" expr        ; will return true
    parse "1-(3/)+2" expr           ; will return false

Creating a simple parser for a subset of HTML:
    html: {
        <html>
            <head><title>Test</title></head>
            <body><div><u>Hello</u> <b>World</b></div></body>
        </html>
    }

    ws: charset reduce [space tab cr lf]

    parse html tags: [
        collect [any [
            ws
            | "</" thru ">" break
            | "<" copy name to ">" skip keep (load name) opt tags
            | keep to "<"
        ]]
    ]

    ; will produce the following tree of blocks as output of parse:
     [
         html [
             head [
                 title ["Test"]
             ]
             body [
                 div [
                     u ["Hello"]
                     b ["World"]
                 ]
             ]
         ]
     ]

The Parse dialect

Parse's core principles are:
  • Advance input series by matching grammar rules until top-level rule failure (returning false) or input exhaustion (returning true). (*)
  • Ordered choices (e.g. in ["a" | "ab"] rule, the second one will never succeed).
  • Rules composability (unlimited).
  • Limited backtracking: only input and rules positions are backtracked, other changes remain.
  • Two modes: string-parsing (for example: external DSL) or block-parsing (for example: embedded DSL).
(*) If collect keyword is used in any rule in its simplest form, a block will be returned by parse no matter if the root rule succeeded or not.


The Parse rules can be made from:
  • keyword : a dialect reserved word (see the tables below).
  • word : word will be evaluated and its value used as a rule.
  • word: : set the word to the current input position.
  • :word : resume input at the position referenced by the word.
  • integer value : specify an iterated rule with a fixed number or a range of iterations.
  • value : match the input to a value
  • | : backtrack and match next alternate rule
  • [rules] : a block of sub-rules
  • (expression) : escape the Parse dialect, evaluate a Red expression and return to the Parse dialect.

The following keywords are currently available in Red's Parse implementation. They can be composed together freely.

Matching

ahead rule : look-ahead rule, match the rule, but do not advance input.
end: return success if current input position is at end.
none: always return success (catch-all rule).
not rule: invert the result of the sub-rule.
opt rule: look-ahead rule, optionally match the rule.
quote value: match next value literally (for dialect escaping needs).
skip: advance the input by one element (a character or a value).
thru rule: advance input until rule matches, input is set past the match.
to rule: advance input until rule matches, input is set at head of the match.

Control flow

break: break out of a matching loop, returning success.
if (expr): evaluate the Red expression, if false or none, fail and backtrack.
into rule: switch input to matched series (string or block) and parse it with rule.
fail: force current rule to fail and backtrack.
then: regardless of failure or success of what follows, skip the next alternate rule.
reject: break out of a matching loop, returning failure.

Iteration

any rule: repeat rule zero or more times until failure or if input does not advance.
some rule: repeat rule one or more times until failure or if input does not advance.
while rule: repeat rule zero or more times until failure regardless of input advancing.

Extraction

collect [rule]: return a block of collected values from the matched rule.
collect set word [rule]: collect values from the matched rule, in a block and set the word to it.
collect into word [rule]: collect values from the matched rule and insert them in the block referred by word.
copy word rule: set the word to a copy of the matched input.
keep rule: append a copy of the matched input to the collecting block.
keep (expr): append the last value from the Red expression to the collecting block.
set word rule: set the word to the first value of the matched input.

Modification

insert only value: insert[/only] a value at the current input position and advance input after the value.
remove rule: remove the matched input.

The core principles mention two modes for parsing. This is necessary in Red (as in Rebol) because of the two basic series datatypes we have: string! and block!. The string! datatype is currently an array of Unicode codepoints (Red will support an array of characters in a future version) while the block! datatype is an array of arbitrary Red values (including other blocks).

In practice, this results in some minor differences in Parse dialect usage. For example, it is possible to define arbitrary sets of characters using the new bitset! datatype, which are useful only for string! parsing in order to match with a large number of characters in one time. Here is an example using only bitsets matching and iterators:
    letter: charset [#"a" - #"z"]
    digit:  charset "0123456789"

    parse "hello 123 world" [5 letter space 3 digit space some letter]

The Bitset! datatype

A bitset value is an array of bits that is used to store boolean values. In the context of Parse, bitsets are very useful to represent arbitrary sets of characters across the whole Unicode range, that can be matched against an input character, in a single operation. As bitset! is introduced in this 0.4.1 release, it is worth having an overview of the features supported. Basically, it is on par with Rebol3 bitset! implementation.

In order to create a bitset, you need to provide one or several characters as base specification. They can be provided in different forms: codepoint integer values, char! values, string! values, a range or a group of previous elements. The creation of a new bitset is done using the following syntax:
    make bitset! <spec>

    <spec>: char!, integer!, string! or block!
For example:
    ; create an empty bitset with places at least for 50 bits
    make bitset! 50

    ; create a bitset with bit 65 set
    make bitset! #"A"

    ; create a bitset with bits 104 and 105 set
    make bitset! "hi"

    ; create and set bits using different values representations
    make bitset! [120 "hello" #"A"]

    ; create a bitset using ranges of values
    make bitset! [#"0" - #"9" #"a" - #"z"]
Ranges are defined using two values (char! or integer! allowed) separate by a dash word.

Bitsets are auto-sized to fit the specification value(s) provided. The size is rounded to the upper byte bound.

A shortcut charset function is also provided for practical usage, so you can write:
    charset "ABCDEF"
    charset [120 "hello" #"A"]
    charset [#"0" - #"9" #"a" - #"z"]

For reading and writing single bits, the path notation is the simplest way to go:
    bs: charset [#"a" - #"z"]
    bs/97     ; will return true
    bs/40     ; will return false
    bs/97: false
    bs/97     ; will return false
(Note: bitset indexing is zero-based.)

Additionally, the following actions are supported by bitset! datatype:
pick, poke, find, insert, append, copy, remove, clear, length?, mold, form

See the Rebol3 bitset documentation for more info about usage of these actions.

In order to cope with the wide range of Unicode characters, bits outside of the bitsets are treated as virtual bits, so they can be tested and set without errors, the bitset size will auto-expand according to the needs. But that is still not enough to deal with big ranges, like for example a bitset for all Unicode characters except digits. For such cases, it is possible to define a complemented bitset that represents the complement range of the specified bits. This makes possible to have large bitsets while using only a tiny memory portion.

Complemented bitsets are created the same way as normal bitsets, but they need to start with the not word and always use a block! for their specification:
    ; all characters except digits
    charset [not "0123456789"]

    ; all characters but hexadecimal symbols
    charset [not "ABCDEF" #"0" - #"9"]

    ; all characters except whitespaces
    charset reduce ['not space tab cr lf]

Set operations are also possible, but only union is currently implemented in Red (it is the most used anyway for bitsets). With union, you can merge two bitsets together to form a new one, which is very useful in practice:
    digit: charset "0123456789"
    lower: charset [#"a" - #"z"]
    upper: charset [#"A" - #"Z"]

    letters:  union lower upper
    hexa:     union upper digit
    alphanum: union letters digit

Parse implementation

Parse dialect has been implemented as a FSM which differs from the Rebol3 implementation that relies on recursive function calls. The FSM approach makes possible several interesting features, like the ability to stop the parsing and resume it later, or even serialize the parsing state, send it remotely and reload it to continue the parsing. Such features could now be implemented with minimal efforts.

Red Parse implementation is about 1300 lines of Red/System code, with a significant part of it spent on optimized iteration loops for common cases. About 770 unit tests have been hand-written to cover the basic Parse features.

The current Parse runs as an interpreter, which is fast enough for most use-cases you will have. For cases where maximum performance is required, work has started on a Parse static compiler to soon provide the fastest possible speed to Parse-intensive Red apps. The generated code is pure Red/System code and should be about a magnitude faster on average than the interpreted version. When Red will be self-hosted, a Parse JIT compiler will be provided to deal with the cases that the static compiler cannot process.

As Red gets more features, Parse will continue to be improved to take advantage of them. Among other future improvements, binary! parsing will be added as soon as binary! datatype is available, and stream parsing will be possible when port! datatype will be there.

The Red Parse also exposes a public event-oriented API in form of an optional callback function that can be passed to parse using the /trace refinement.
    parse/trace <input> <rules> <callback>

    <callback> specification:

    func [
        event   [word!]   ; Trace events
        match?  [logic!]  ; Result of last matching operation
        rule    [block!]  ; Current rule at current position
        input   [series!] ; Input series at next position to match
        stack   [block!]  ; Internal parse rules stack
        return: [logic!]  ; TRUE: continue parsing, FALSE: exit
    ]

    Events list:
    - push    : once a rule or block has been pushed on stack
    - pop     : before a rule or block is popped from stack
    - fetch   : before a new rule is fetched
    - match   : after a value matching occurs
    - iterate : after a new iteration pass begins (ANY, SOME, ...)
    - paren   : after a paren expression was evaluated
    - end     : after end of input has been reached
This API will be extended in the future to get more fine-grained events. This API could be used to provide Parse with tracing, stats, debugging, ... Let's see what Red users will come up with! ;-)

A default callback has been implemented for tracing purposes. It can be accessed using the handy parse-trace function wrapper:
    parse-trace <input> <rules>

You can try it with simple parsing rules to see the resulting output.


What about DSL support?

Parse is a powerful tool for implementing DSL parsers (both embedded and externals), thanks to its ability to inline Red expressions directly into the rules, allowing to easily link the DSL syntax with its corresponding semantics. To illustrate that, here is a simple interpreter for a famous obfuscated language, written using Parse:
    bf: function [prog [string!]][
        size: 30000
        cells: make string! size
        append/dup cells null size

        parse prog [
            some [
                  ">" (cells: next cells)
                | "<" (cells: back cells)
                | "+" (cells/1: cells/1 + 1)
                | "-" (cells/1: cells/1 - 1)
                | "." (prin cells/1)
                | "," (cells/1: first input "")
                | "[" [if (cells/1 = null) thru "]" | none]
                | "]" [
                   pos: if (cells/1 <> null)
                   (pos: find/reverse pos #"[") :pos
                   | none
                  ]
                | skip
            ]
        ]
    ]

    ; This code will print a Hello World! message
    bf {
        ++++++++++[>+++++++>++++++++++>+++>+<<<<-]>++.>+.+++++++..+++.
        >++.<<+++++++++++++++.>.+++.------.--------.>+.>.
    }

    ; This one will print a famous quote
    bf {
        ++++++++[>+>++>+++>++++>+++++>++++++>+++++++>++++++++>
        +++++++++>++++++++++>+++++++++++>++++++++++++>++++++++
        +++++>++++++++++++++>+++++++++++++++>++++++++++++++++<
        <<<<<<<<<<<<<<<-]>>>>>>>>>>>----.++++<<<<<<<<<<<>>>>>>>
        >>>>>>.<<<<<<<<<<<<<>>>>>>>>>>>>>---.+++<<<<<<<<<<<<<>>
        >>>>>>>>>>>>++.--<<<<<<<<<<<<<<>>>>>>>>>>>>>---.+++<<<<
        <<<<<<<<<>>>>.<<<<>>>>>>>>>>>>>+.-<<<<<<<<<<<<<>>>>>>>>
        >>>>>>+++.---<<<<<<<<<<<<<<>>>>.<<<<>>>>>>>>>>>>>>--.++
        <<<<<<<<<<<<<<>>>>>>>>>>>>>>-.+<<<<<<<<<<<<<<>>>>.<<<<>
        >>>>>>>>>>>>>+++.---<<<<<<<<<<<<<<>>>>>>>>>>>>>>.<<<<<<
        <<<<<<<<>>>>>>>>>>>>>>-.+<<<<<<<<<<<<<<>>>>>>>>>>>>>>-.
        +<<<<<<<<<<<<<<>>>>>>>>>>>>>>--.++<<<<<<<<<<<<<<>>>>+.-
        <<<<.
    }
Note: this implementation is limited to one-level of "[...]" nesting to keep it as short as possible. A complete, but a bit more longer and complex implementation using Parse only, is availaible here.

So, such approach works incredibly well for small DSLs. For more sophisticated ones, Parse still works fine, but it might be less helpful as the DSL semantics get more complex. Implementing an interpreter or compiler for a more advanced DSL is not a trivial task for most users. Red will address that in the future by providing a meta-DSL wrapper on top of Parse, exposing a higher-level API to build more sophisticated DSL by abstracting away core parts of an interpreter or compiler. A DSL for building other DSLs is not a crazy idea, it already exists in a very powerful form as the Rascal language for example. What Red will provide, will be just one step in that direction, but nothing as sophisticated (and complex) as Rascal.

Other changes in this release
Just to mention other changes in this release, now that we got rid of the 800 pound gorilla in the room. This release brings a significant number of bug fixes, both for Red and Red/System. Also, thanks to qtxie, the ELF file emitter is now on par with the other ones when producing shared libraries.

Thanks to all the people involved in helping for this big release, including design fixes and improvements, testing, bug reporting and test writing.

Enjoy! :-)

September 27, 2013

0.4.0: Red goes binary!

What's that?!

As we are getting closer to the end of the alpha period, we are now moving to a more convenient way to use and distribute the Red toolchain. So far, you needed to download a Rebol interpreter and the sources from Github separately, and run it using, a bit verbose, command-lines. This is fine for developping Red  with contributors that are interested in the inner workings of the toolchain, but for the end users, the goal has always been to provide a simpler and much more convenient way, like Rebol teached us in the past.

So, from now, you can get Red as a single binary (< 1 MB) from the new Download page. Yes, all of Red toolchain and runtime is packed in that small binary, even the REPL is built-in!

The Red repo landing page has been reworked to show Red usage in binary form, all previous command-line options are present, a new one (-c) has been introduced. Here is a short overview of the main options:

Launch the REPL:
    $ red 
Run a Red script directly (interpreted):
    $ red <script>
Compile a script as executable with default name in working path:
    $ red -c <script>
Compile a script as shared library with default name in working path:
    $ red -dlib <script>
Compile a script as executable with alternative name:
    $ red -o <new> <script>
Compile a script as executable with default name in other folder:
    $ red -o <path/> <script>
Compile a script as executable with new name in other folder:
    $ red  -o <path/new> <script>
Cross-compile to another platform:
    $ red -t Windows <script>
Display a description of all possible options:
    $ red -h
Notice that -c option is implied when -o or -t are used. It is designed to keep command-lines as simple and short as possible.

Moreover, for standalone Red/System programs, the Red binary will be able to compile them directly, no special option needed, they will be recognized automatically.

Thanks very much to Tamás Herman for helping with setting up the build farm and providing the Mac OSX machine, and thanks to the HackJam hackerspace group from Hong-Kong for the hosting!

Other changes

  • In addition to that new binary form, 17 issues have been fixed since the 0.3.3 release about a month ago (not counting regression tickets).
  • The work on objects support is half-done, objects are working fine with advanced semantics on the interpreter (see object branch), now the focus will be to support them at the Red compiler level.

What's next?

As we are moving closer to the beta state, version numbers will increase faster, e.g., once objects will be done, the release will be the 0.5.0, while 0.6.0 will bring full I/O support. Between these major versions, smaller versions should be still possible, this means that the release cycle should accelerate with at least one release each month from now on. So, what you should expect in the next ones?

0.4.x
  • Simple I/O support: (just read, write and exists? on files)
  • PARSE support
  • Pre-compiled runtime (much faster compilation times)
0.5.0
  • Full object support
0.5.x
  • VID-like cross-platform dialect binding to native widgets.
  • Mezzanine functions additions
  • Redbin (accurate Red values serialization in binary format)
  • Full errors management
  • Red-level exceptions handling

Enjoy!


March 23, 2013

0.3.2: REPL release

Time has finally come to release the new REPL for Red. A preview version has been pushed last Christmas, since then a lot of work has been done on several fronts (about 310 new commits, excluding merges): interpreter (DO), runtime lexer (LOAD) and console. But before going into details for the REPL, here is an overview of the changes in this new release:

  • New datatypes: routine!, issue!, file!
  • New natives: do, load, reduce, compose, switch, case, stats, platform?, quit
  • New natives: remove
  • New mezzanines functions: ??, empty?
  • 38 issues from previous releases fixed.
  • Unit tests for Red raised to 5602 for a total of 17671 tests (including Red/System ones).
  • Notable improvements:
    • Paren! expressions in paths now supported.
    • Mold output for string! and char! deeply improved, special characters are now correctly escaped.
    • Improved and more accurate support for unset! values processing.
    • Prin and print now reduce their arguments.

Red REPL

This is the biggest part of this new release. The REPL has several components:
  • The interpreter: it is a full Red interpreter supporting all Red language features, except Red/System code. In the current version, though, exit and return are not yet implemented, they need some special low-level support from Red/System, so couldn't make it for this release. The interpreter can be invoked from compiled code using the do native. It has been developped in Red/System and is about 700 LOC long. All Red compiler tests are run against the interpreter too, all are passing except for the unimplemented yet exit and return (6 tests).
  • The runtime lexer: it is the runtime counterpart to the compiler's lexer and, is in charge of loading input string source code into Red and converting it into blocks of values. It can be invoked from compiled code using the load native. The runtime lexer current version only support Latin-1 encoding, a full Unicode lexer will replace it soon (it is a work in progress).
  • The console: it is the visible part of the REPL for most users. The current version is minimal but works on most of supported platforms (including the RaspberryPi). It has limited editing abilities, and history doesn't work on Mac OS X, but it supports a Rebol-like multi-line input mode for blocks and strings. We will provide a much better console in the next release, with a cross-platform abstraction layer that feature-wise, will put all platforms on par.
The interpreter and runtime lexer and now part of Red's standard library, so they are bundled with every compiled Red script. The overhead is about 30KB in the final binary, making it almost unnoticeable. The console is a separate script, that can be compiled easily producing a small standalone binary.

An important feature of the Red interpreter is that it is not only meant for the REPL support, but is actually used by the compiler to solve some code patterns that are too dynamic to be statically analyzed and compiled. Moreover, the interpreter has the ability to call pre-compiled code, so as soon as possible, it can drop back to native code execution. Both compiled and interpreted code are deeply collaborating to provide the most flexible language semantics while ensuring the maximum performances. With the future addition of a JIT-compiler, we will be able to reach the optimal internal architecture.

Red Collaborative Execution Model

On the more practical side, to compile the console, from Red root folder, just do:
do/args %red.r "red/tests/console.red"

That will give you a console binary in the working folder. When you run it, you should see:

-=== Red Console alpha version ===-
(only Latin-1 input supported) 
 
red>> 
This is the Red prompt where you can input any valid Red expression, they will be evaluated on Enter key pressed. Use q or quit to exit the console. Remember that there is no yet proper error management, current error messages are hardcoded, and in some cases, you will be thrown out of the console (that is why it is still an alpha version as stated by the console banner). Note that it is possible to copy/paste Red scripts directly into the console.

Anyway, feel free to experiment.

Routines

In order to more easily interface Red and Red/System, a new function datatype has been added: routine!. A routine is Red/System function defined in a Red program. The routine specification takes Red datatypes as arguments and return value, and the routine will automatically convert them to appropriate Red/System types when called. For example:
increment: routine [
    n       [integer!]
    return: [integer!]
][
    n + 1
]
Here you can see how the Red integer! argument get marshalled forth and back to Red/System integer! datatype for you. For now, routines automatically converts integer! and logic! datatypes this way. Other Red datatypes are passed as their Red/System counterparts as defined in Red's runtime (see %red/runtime/datatypes/structures.reds). Optional arguments are not supported by routines, as such feature does not exist in Red/System for now.

You can now very easily extend Red with routines using the full power of Red/System! Compiled routines can be run from interpreter too.

Project management

We are now moving to Trello for tracking the tasks about Red development. The short-term ToDo list is pretty accurate and updated regularly, you can now follow us more closely. We only started using it a month ago, so not all the tasks (especially the mid-term/long-term ones) are inserted there yet.

Thanks for all the support received for getting this major release out!
Cheers!

Fork me on GitHub