Sunday, May 16, 2010

Parsing Prefixes

Luke (docl in the #retro irc channel) has contributed an update to the prefix handling code that adds support for parsing prefixes. This allows for some interesting stuff we couldn't do before:

  : __$ ( $-n ) hex >number decimal ;
  : __% ( $-n ) binary >number decimal ;

These allow for parsing numbers as hex or binary, based on a prefix. Luke has gone much further though:

{
   variable end
   : pad 1024 here + ;
   : keep ( - ) @compiler 0; drop keepString literal, ;
   : >pad ( $-$ ) pad over getLength 1+ copy pad keep ;
   : >$ ( n- ) !@end end ++ ;
   : "? ( -f ) @end @1- char: " = ;
   : chop ( $-$ ) end -- 0 !@end ;
   : "; ( $-$ ) "? if chop >pad rdrop ;then ;
   : __" ( "-a )
     dup dup getLength + !end
     "; 32 >$ repeat "; key dup emit >$ again ; parsing prefix
}

With this, we can do strings without a leading space:

  : hello ( - ) "hello, world!" type cr ;

Luke's __" is now part of RetroForth 10.6. I've also added __$, __#, __%, and __' (parsing hex, decimal, binary, and single characters). This restores more of the functionality dropped between 9.3 and 10.0, and adds some new features to the table.

Sunday, May 2, 2010

Prefixes

The Rx Core now has prefixes, and they're better than ever before. For those who aren't familiar with them from Retro 9.x, a prefix is a single character that is placed before a name. The notfound handler will check to see if a word exists without the prefix; if so, it passes the xt of the word on the stack to a prefix handler word.

Ok, so in Retro we have five basic prefixes: @ ! + - & these correspond to fetch, store, increment by, decrement by, and address of.

@ and ! correspond to @ and ! (pretty obvious); + and - corespond to +! and -!; and & corresponds to either ' or ['].

Their usage is intended to help cleanup code flow a bit. We can do things like:

&words execute ( execute 'words' )
@here ( return the value at 'here' )
@foo +bar ( increment 'bar' by the value in 'foo' )

If you want to define more prefixes, it's easy to do. For instance, say we want a prefix that returns the dictionary header of a word. notfound will give us the xt, so we can lay down a stub:

: __~ ( a-d ) ; immediate prefix

Note the two _ characters. This is a common attribute of prefix names: the must be three characters long, and start with two underscores. The word prefix moves our word to the prefixes vocabulary. This isn't necessary, but does prove useful by making it easy to disable prefixes globally.

Ok, so filling in the details:

: __~ ( a-d ) xt->d ; immediate prefix

At first glance this looks ok. Testing it reveals a problem:

: __~ ( a-d ) xt->d ; immediate prefix
: foo ~words ;
foo .s
reset
foo .s

To fix this we need to compile as a literal into a definition. Still pretty easy as far as things go because .data will do this for us:

: __~ ( a-d ) xt->d .data ; immediate prefix
: foo ~words ;
foo .s
reset
foo .s

Now we have a working prefix. Take a look at at the implementation of the default prefixes to get ideas on implementing more complex ones. Careful use can enable significant cleanups to messy code, but in some cases it will be better to use discrete words to aid overall readability. Like all advanced features, prefixes should be learned, then used where they will help.

Saturday, May 1, 2010

Fossil and Captchas

I've begun moving to Fossil for my version control needs.

Rx Core: http://rx-core.org/dev/rx.fossil

Retro Forth: http://rx-core.org/dev/retroforth.fossil

The pastebin was clogged with spam posts. I deleted over 2k of them, and added a captcha to hopefully reduce the number of new ones.