gnu-arch-users
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Gnu-arch-users] arch roadmap 2 (and "what's tom up to")


From: Tom Lord
Subject: [Gnu-arch-users] arch roadmap 2 (and "what's tom up to")
Date: Mon, 28 Jun 2004 12:55:56 -0700 (PDT)

This is the first of three messages, the third of which will be 
delayed a little bit.

The messages begin to introduce furth, a new extension language that I
plan to add to tla (and use for other purposes as well).   They are:


        1. First Furth intro (for C hackers)
           What is furth and how does it work?

        2. First Furth intro (in general)
           What is furth and what does it look like?

        3. Arch Roadmap 
           Where's arch going and where does furth fit in.





                    Furth in Too Small a Nutshell

  [This is not yet an accurate or complete tutorial though it 
   will grow up to be one as furth progresses.]

  A furth program is a list of commands.   Each command is read and
  then executed.   

  Every _thing_ in furth is both a _value_ and a _command_.  There is
  no distinction between commands and values: they are synonyms.
  Two examples of commands in furth are:

        2               ; the command "integer constant 2"
        :print          ; the "print" command

  and so two trivial Furth programs are:

        "hello world\(nl)"      ; push the string "hello world\n" on the stack
        :display                ; write it to stdout

  and

        2 2 :+          ; push 2 on the stack twice, then replace
                        ; those with their sum

        :print          ; print the result


  So, yes, furth is one of those annoying languages like Forth or
  Postscript that uses RPN.



* Quoting

  The command "2" is considered "self-quoting" because, when executed,
  it pushes itself on the data stack.    The command ":print" is not
  self-quoting.   What if you want to push the command :print on the
  stack rather than executing it?   The quoting syntax does that:


        |:print         ; | == quote.   Push the :print command on
                        ; the stack.

        :print          ; print the value on top of the stack.

  The output of that program is the string ":print".


* All Values are Dictionaries

  As in many other high-level languages, all values are dictionaries.
  Here is one example of a (self-quoting) value:

        #(x_coord => 0  y_coord => 1)

  You can read and modify (most) dictionaries in unsurprising ways:

        #(x_coord => 0  y_coord => 1)   ; push on stack

        |y_coord                        ; push (quoted) field name on stack


        :ref                            ; pop name and dictionary,
                                        ; push binding

        :print

  That program prints "1".

  Even something like the value "2" is a dictionary, although it's not
  a very interesting one.   You can't modify the dictionary "2" (it's
  "immutable" aka "read-only").   And, the dictinoary "2" has no
  fields.

        2 |y-coord :ref :print

  prints ":hcf" which is what furth uses for "no defined binding".
  You can read ":hcf" as "Holy Cow, Fred!" (expressing your surprise
  about a missing binding) or, more properly, as "halt and catch
  fire".   ":hcf", in addition to being the "undefined value", is also
  the the "halt and catch fire" command which causes the VM to
  shut-down while indicating an error condition.

  Speaking of :hcf,  the following furth program is a reasonable
  implementation of the unix standard utility `/bin/false':

        :hcf

  You can implement `/bin/true' instead with:

        :halt

* Complex Commands

  You can group commands in parentheses, forming a list.  For example:

        (2 2 +)

  is a complex command with three subcommands.  When executed, the
  complex command executes the subcommands in sequence.

  Complex commands also provide flow control.   For example, the
  complex command:

        :(if a b)

  pops a value from the stack.  If that value is "#f" (aka "false")
  then b is executed.   Otherwise, a is executed.

  Additional flow of control complex commands (e.g., loops) are also
  provided although, ultimately, these can all be regarded as library
  routines that reduce to more primitive constructs.


* Namespaces and $env

  Every value is a dictionary.  At every point during the execution of
  a program, one value, called $env, "the environment", is
  distinguished as the default dictionary in which to look up or
  define values.

  Thus this program:

        42 |x :def
        x x :* :print

  is equivalent to:

        42 $env |x :define                              ; 42 |x :def
        :$env |x :ref   :$env |x :ref   :* :print       ; x x :* :print

  You can switch default namespaces with commands such as:

        :set-$env
        :ref-$env

  Namespaces have single inheritence.   You can construct a new
  namespace, specifying that it inherits bindings from some other
  namespace.



* The Stack and $tuple

  Furth is stack oriented.   The program fragment:

        2 3

  pushes the numbers 2 and 3 on the stack.

  The register $tuple contains the entire stack.   For example,
  if the above fragment is executed, starting with an
  empty stack, then at the end of the fragment we know:

        $tuple = #(2 3)

  Other commands can use that notation to define what they do.
  For example, the :+ command could be described:


        :+
          before        $tuple = #( ... a b)
        =>
          after         $tuple = #( ... a+b)


  The tuple is a first class value just like any other.  For example, 
  here is an interesting definition:


        :$tuple
          before        $tuple = #( ... a)
        =>
          after         $tuple = #( ... a #( ... a))

  (in other words, the command $tuple pushes a copy of the entire
  stack onto the stack).


* Variable Capture

  A command of the form:

        :(capture name0 name1 .... nameN)

  empties the data stack, creating a new namespace which inherits from
  the current $env, has bindings for each NAME0 ... NAMEN, and takes
  the values of those bindings from the old stack.  The new namespace
  is stored in $env.

  This is, in essense, the "callee-side" of a function-call
  convention.   For example, this program:


        1 2 3 :(capture a b c)
        a :print
        b :print
        c :print

   prints the values 1, 2, and 3.

   One complement of capture is:

        :pop-$env

   with an unsurprising meaning, illustrated by this program


        1 |x :def
        2 :(capture x)

        x :print
        :pop-$env
        x :print

   which prints "2" then "1".


* $inx and $next

  Whenever a command is about to be executed, $inx contains that
  command.   The register $next contains the "rest of the program".
  Normally, a command does what it needs to do and then moves the
  value in $next to $inx.  That way, on the next cycle, "the rest
  of the program" begins execution.

  In furth, three commands are of particular interest:

        :goto
        before
          $inx = :goto
          $next = <X>
          $tuple = #( ... a)
        =>
        after
          $inx = a
          $next = :hcf
          $tuple = #( ... )

   is an absolute "goto".  And:

        :jsr  ("jump to subroutine")
        before
          $inx = :jsr
          $next = <X>
          $tuple = #( ... a)
        =>
        after
          $inx = a
          $next = <X>
          $tuple = #( ... )

   is a kind of subroutine call.  Finally, there is the famous
   command (from other languages):


        :call/cc ("call with current continuation)
        before
          $inx = :call/cc
          $next = <X>
          $tuple = #( ... a)
        =>
        after
          $inx = a
          $next = <X>
          $tuple = #(... <X>)

  All flow of control constructs you are familiar with can be 
  implemented in terms of :goto, :call/cc, and :if.  The addition
  of :jsr is just an optimization, the same effect could be achieved
  by prepending a ":drop" ("drop from stack") command to every 
  subroutine.  I.e.,:

        <X> :jsr

   is equivalent to:

        |(:drop <X>) :call/cc  
        

* $global

  $global is the final register.   It functions as an alternative to
  $env.   By convention, $env is used to hold lexical environments
  ("local variables", more or less) and $global is used to hold
  dynamic environments ("global variables", sort of).


* That's About It

  That's about it for core Furth.   I haven't enumerated obvious
  things (such as the list of arithmetic operators or the list of
  commands for operating on arrays).   But I have given the core 
  concepts that provide flow of control and variables.

  Furth is obviously very low-level in the sense that (virtual)
  machine registers are available and can be directly manipulated.
  On the other hand:

        1) Furth has facilities for "syntactic extension" which
           haven't been described here (since they aren't done yet).
           So, you can define a higher-level language that
           "hides" the registers yet compiles in a fairly trivial
           way to Furth.   To name one example, it would be easy 
           to implement a Scheme-on-Furth this way.

         2) Yes, registers are exposed but that doesn't mean that
            furth is "low level" in the sense of "hard to program".
            



* "Hey, where's my language?"

  This brief proto-tutorial has left out some things you might
  have expected.

  For example, no standard way is provided for defining a new command,
  written in Furth.

  You can sort-of see how to do that: presumably you want to define a
  name in the $env dictionary and somehow arrange for that name to be
  "callable" as a command.   But no details have been given.

  That's because there's more than one way to do it.  Those kinds of
  features are things that will have to be built up in furth libraries
  and in standard extensions to furth.  The greater flexability of the
  current approach makes it worth definiing on its own, first.


-t


;;; arch-tag: Tom Lord Mon Jun 28 12:48:52 2004 (furth/README.furth)


----

Like my work on GNU arch, Pika Scheme, and other technical contributions 
to the public sphere?   Show your support!

https://www.paypal.com/xclick/business=lord%40emf.net&item_name=support+for+arch+and+other+free+software+efforts+by+tom+lord&no_note=1&tax=0&currency_code=USD

and

address@hidden for www.moneybookers.com payments.


-----

  "Hello, all of you boys and girls,
   I'd like to take you to the inside world."
                           - Claypool





reply via email to

[Prev in Thread] Current Thread [Next in Thread]