December 15, 2012

Red v0.3.1: functions support added


This new milestone brings (finally) functions to Red along with other new features and fixes. Let's first have a quick overview of 0.3.1 release content:

  • function support
  • path get/set notation support
  • refinement support for native functions
  • expressions in parentheses compilation
  • new datatypes: function!, paren!, path!, lit-path!, get-path!, set-path!
  • new actions and natives: find, select, copy, reflect, type?, halt,...
  • extended mold, form and comparison operators to all new and existing datatypes
  • many new mezzanines functions
  • modulo and remainder operators on floats implemented for ARM backend
  • Quick-Test testing framework ported to Red
  • a truckload of new unit tests
  • many bugfixes
  • about 200 new commits to the Github repository
  • updated Red/System formal description document

Functions

They are declared using a similar syntax to REBOL, with some extensions. The specification block looks like this:

    [arg1 [type1] arg2 [type2]...return: [type] /local var1 [type-v1]...]

  • Arguments and local variables are declared in the same way as in REBOL
  • A return value type can be optionally specified
  • Local words can have a type specifier

All type specifiers are optional, adding them will not only allow the compiler to make additional type checkings but also generate faster code in some cases (once the optimizations added to the Red compiler).

Note: argument and return value type checking have not been implemented yet, they need typeset! and error! datatypes to be implemented first.

Functions can be built using several constructors:

  • function: automatically collects local variables, like `funct` in REBOL.

    twice: function [a [integer!] /one return: [integer!]][
    c: 2
      a: a * c
    either one [a + 1][a]
    ]

  • func: low-level function constructor, everything needs to be manually specified.

     twice: func [a [integer!] /one return: [integer!] /local c][
      c: 2
      a: a * c
      either one [a + 1][a]
    ]

  • has: no argument, just lists local words.

    globals: [1 2 3 _]
    
    foobar: has [list][
      if list: find globals '_ [clear list]
    ]

  • does: no argument, no local words.

    quit: does [
      print "Goodbye cruel world!"
      halt
    ]

Early exit points are also there in form of exit and return functions.

    foobar: func [a [integer!] b [integer! none!]][
      if none? b [return none]
      if b = 0 [
         print "Error: division by zero"
         exit
      ]
  a / b
    ]
 
Refinements are also fully supported, when not used, their value is set to false (while in REBOL it is set to none).

Still some features are not yet implemented:

  • building a function at runtime (requires the ability to JIT-compile source code)
  • passing a function as argument (pending)
  • tail recursion optimization

Currently functions are using a local context on stack, so their life-time is very short. For indefinite extent support, a closure! type will be added in the next months.

Path support

Path datatypes were added (path!, lit-path!, get-path!, set-path!) to the runtime library and compiler, allowing the use of path notation as syntactic sugar for series access. Getting and setting values using path notation are supported.

Some usage examples:

    list: [a 5 b [c 8] d #"e" name: "John"]
    
    probe list/2 ;-- outputs 5
    probe list/7 ;-- outputs name:
    probe list/a ;-- outputs 5
    probe list/4/2 ;-- outputs 8
    probe list/b/c ;-- outputs 8
    probe list/name ;-- outputs "John"
    
    list/b/c: 0
    probe list/b/c ;-- outputs 0
    
    index: 3
    probe list/:index ;-- outputs b
    list/:index: 'z
    probe list/:index ;-- outputs z
    
Note: notice how words lookups in blocks can work with any word datatypes.


Paren expressions

Paren! datatype and expressions in parentheses compilation support has been added too. They are mainly useful with infix operators in order to force a given execution priority. Example:

    print (1 + 2) * (3 + 4) ;-- outputs 21


New built-in functions

  • actions: findselectcopyreflect
  • natives: type?, halt, function, func, does, has, exit, return
  • mezzanines: probe, first, second, third, fourth, fifth, last, spec-of, body-of and all <datatype>? type testing functions.

Existing native or action functions were extended with refinements (like mold and form). See the boot.red script for more details.

Testing

The Quick-Test framework from Peter WA Wood was ported to Red and now powers all the current 1800+ unit tests written in Red itself, mostly added by Peter.

About 32 issues/bugs in both Red and Red/System were fixed in this new release.

Red/System formal description

Last but not least, Rudolf updated his Red/System formal description document [PDF, 162KB] to include the additional features like namespaces. Many thanks to him for his remarkable work and support to Red project!

What's next?

Objects support is next priority along with new natives like switch and case. Typesets and error handling will probably be added very soon too. Once that part done, the next focus will be to add I/O support!


Many thanks to all the people that have made significant donations in last months to Red project, allowing me to continue to work full time on it! It is really making a big difference, as shown by Red increased progress speed since this summer. Thanks again!

Cheers!

Fork me on GitHub