(This is my home account which I don’t have access to at work.
I will upload the file around 19.00 EST.)
*** What is ratlast?
ratlast is an extension gives Ruby the power and flexibility of FORTH,
using John Walker’s ATLAST system.
ATLAST is a F-83 style system that includes floating point
and string primitives, as well as systems FORTH standards such
as CREATE and DOES>. It is very powerful, flexible, fast, and
easy to extend. On the fly compiling is trivial.
Most of all, it is a -lot- of fun to use!
*** Example
Here is a little magic :-). We create a linear equation ax+b and
give it the name ‘linear’. For the example, we know the slope (3)
and intercept (17) and the x varies. We then evaluate the function
and print the result.
(For the FORTHists in the audience, the stack is 4-bytes wide for
all integers, hence the 4 + …)
$ cat ex1.rb
require 'Atlast’
t = Atlast.new
t.eval(": linear ( a b – ) create swap , , does> dup >r @ * r> 4 + @ + ;")
t.eval(“3 17 linear aline”)
x = 1
until x >= 10
t.eval("#{x} aline .")
puts "x=#{x} : 3x + 17 = #{t.capture[0]}"
x += 1
t.clear # clear the capture buffer
end
(This is my home account which I don’t have access to at work.
I will upload the file around 19.00 EST.)
*** What is ratlast?
ratlast is an extension gives Ruby the power and flexibility of FORTH,
using John Walker’s ATLAST system.
ATLAST is a F-83 style system that includes floating point
and string primitives, as well as systems FORTH standards such
as CREATE and DOES>. It is very powerful, flexible, fast, and
easy to extend. On the fly compiling is trivial.
Most of all, it is a -lot- of fun to use!
*** Example
Here is a little magic :-). We create a linear equation ax+b and
give it the name ‘linear’. For the example, we know the slope (3)
and intercept (17) and the x varies. We then evaluate the function
and print the result.
(For the FORTHists in the audience, the stack is 4-bytes wide for
all integers, hence the 4 + …)
$ cat ex1.rb
require ‘Atlast’
t = Atlast.new
t.eval(“: linear ( a b – ) create swap , , does> dup >r @ * r> 4 + @ +
;”)
t.eval(“3 17 linear aline”)
x = 1
until x >= 10
t.eval(“#{x} aline .”)
puts “x=#{x} : 3x + 17 = #{t.capture[0]}”
x += 1
t.clear # clear the capture buffer
end
I'm not nocking ya and I don't have a clue about FORTH... so... why
would I use FORTH instead of Ruby?
FORTH is good for some things that Ruby is less strong on. One of the
main “advantages” of FORTH is that when you define a word, you are
actually extending the language. The mechanism for doing this is
very efficient.
The main idea that I have for ratlast is as a user-extensible command
language for Ruby applications. For example, what do you do if you have
a running Ruby system that you can’t take down, yet you have to add some
functionality? That is very easy to do using ratlast.
Not convinced? Me either ;-). I did this cause I could, really. FORTH
is an excellent language and unusual language, and, as I said, a lot
of fun to work with. It has a very quick test cycle that encourages
on-the-spot testing. Try it and you’ll see.
t.eval(": linear ( a b – ) create swap , , does> dup >r @ * r> 4 + @
;") t.eval(“3 17 linear aline”)
Ah, yes, I can see how that’s so much more intuitive than …
def linear(x)
3 * x + 17
end
hmmmmm.
Not quite. The colon definition of linear is more like a lambda
function in lisp, it defines a series of functions, for “a*x + b”.
The binding of a and b happens in the “linear aline” part. I think
you can do this in Ruby using closures.
Only ribbing you, there, but you have to admit the FORTH code tends to
obscure what’s going on just a little :-).
Beauty is in the eye …
It reminds me of Postscript code
Postscript was based on FORTH.
I seem to recall reading a rumour that the boot code for Sun
workstations was written in FORTH, but never found out whether that was
true.
Type L1-A
4 5 + .
: 2* 2 * . ;
7 2*
-laugh-
It is (was) FORTH. I think there is an open firmware project
that is based on FORTH.
LOADER(8) FreeBSD System Manager’s Manual LOADER(8)
NAME
loader - kernel bootstrapping final stage
DESCRIPTION
The program called loader is the final stage of FreeBSD’s kernel boot-
strapping process. On IA32 (i386) architectures, it is a BTX client. It
is linked statically to libstand(3) and usually located in the directory
/boot.
It provides a scripting language that can be used to automate tasks, do
pre-configuration or assist in recovery procedures. This scripting lan-
guage is roughly divided in two main components. The smaller one is a
set of commands designed for direct use by the casual user, called
"builtin commands" for historical reasons. The main drive behind these
commands is user-friendlyness. The bigger component is an ANS Forth com-
patible Forth interpreter based on ficl, by John Sadler.
···
Harry Ohlsen (harryo@zip.com.au) wrote:
I seem to recall reading a rumour that the boot code for Sun
workstations was written in FORTH, but never found out whether that
was true.
$CFLAGS << " -DALIGNMENT -DEXPORT"
if Config::CONFIG[“CC”] =~ /gcc/
$CFLAGS += " -Wall -fwritable-strings"
end
into extconf.rb then it should make okay. It did under cygwin
though I have yet to check it against linux (later today, if I
get the time).
I almost have ratlast 0.2 ready to release. This adds a number
of control and performance items, like breaking loops, memory
stats for the interpreter, and so on. Also, I plan on having
Atlast#eval return the first element in the capture array so
you could do something like:
t = Atlast.new
n = t.eval(“342 406 gcd .”)
puts “gcd = #{n}”
The main idea that I have for ratlast is as a user-extensible command
language for Ruby applications. For example, what do you do if you have
a running Ruby system that you can’t take down, yet you have to add some
functionality? That is very easy to do using ratlast.
I like this idea. It’s possible to generate C code, compile it, and load
the dynamic lib, but that requires a C compiler, takes a fair amount of
cpu time, etc. If you want to trade run speed for compile speed,
Forth-like code is worth a look.
What kind of code-threading model do you use? Token, direct, indirect,
jump? If you’re using jump-threaded code, you can have bits of inline
assembly code, so performance could approach compiled C.
Do you plan to provide any kind of API to ruby objects, so you can
access instance vars, call methods, etc.?
t.eval(": linear ( a b – ) create swap , , does> dup >r @ * r> 4 + @
;") t.eval(“3 17 linear aline”)
Ah, yes, I can see how that’s so much more intuitive than …
def linear(x)
3 * x + 17
end
hmmmmm.
Not quite. The colon definition of linear is more like a lambda
function in lisp, it defines a series of functions, for “a*x + b”.
The binding of a and b happens in the “linear aline” part. I think
you can do this in Ruby using closures.
But closures can do something quite different–they can share a variable
binding with the enclosing scope:
a = 1
b = 2
linear = proc { proc {|x|a*x+b} }
l1 = linear
p l1[5] # ==> 7
a = 10
p l1[5] # ==> 52
If you want linear to behave more like the Forth example:
I'm not nocking ya and I don't have a clue about FORTH... so... why
would I use FORTH instead of Ruby?
FORTH is good for some things that Ruby is less strong on. One of the
main “advantages” of FORTH is that when you define a word, you are
actually extending the language. The mechanism for doing this is
very efficient.
The main idea that I have for ratlast is as a user-extensible command
language for Ruby applications. For example, what do you do if you have
a running Ruby system that you can’t take down, yet you have to add some
functionality? That is very easy to do using ratlast.
Actually, that’s easy to do using Ruby.
Phil
“Or perhaps the truth is less interesting than the facts?”
Amy Weiss (accusing theregister.co.uk of engaging in ‘tabloid journalism’)
Senior VP, Communications
Recording Industry Association of America
$CFLAGS << " -DALIGNMENT -DEXPORT"
if Config::CONFIG[“CC”] =~ /gcc/
$CFLAGS += " -Wall -fwritable-strings"
end
into extconf.rb then it should make okay. It did under cygwin
though I have yet to check it against linux (later today, if I
get the time).
I almost have ratlast 0.2 ready to release. This adds a number
of control and performance items, like breaking loops, memory
stats for the interpreter, and so on. Also, I plan on having
Atlast#eval return the first element in the capture array so
you could do something like:
t = Atlast.new
n = t.eval(“342 406 gcd .”)
puts “gcd = #{n}”
Regards,
-mark.
Thanks working fine now, look forward to 0.2,
Am running in a Tk.Text window with the output fed into
another Tk.Text window.
It would be nice to be have all Atlasts’ error messages available.
What kind of code-threading model do you use? Token, direct, indirect,
jump? If you’re using jump-threaded code, you can have bits of inline
assembly code, so performance could approach compiled C.
Indirect threading, I think. To tell you the truth, I haven’t
studied the inner workings of ATLAST, yet. That will be part
of the next adventure.
Do you plan to provide any kind of API to ruby objects, so you can
access instance vars, call methods, etc.?
I hadn’t planned on doing so. Part of the idea was to keep
everything as simple and clean as possible. So, do in Forth
what it does best, and the same in Ruby.
What would you see as the advantages of doing this?
t.eval(": linear ( a b – ) create swap , , does> dup >r @ * r> 4 + @
;") t.eval(“3 17 linear aline”)
But closures can do something quite different–they can share a variable
binding with the enclosing scope:
a = 1
b = 2
linear = proc { proc {|x|a*x+b} }
This is also (almost) true of the Forth code. Here, the binding
happens at the line
3 17 linear aline
I could have written this code:
i = j = 1
until i <= 10
t.eval(“#{i} #{j} linear aline_#{i}”) # rename the fn to avoid conflict
x = rand(100)
t.eval(“#{x} aline_#{i}”)
puts “x=#{x} : #{i}x + #{j} = #{t.caputure[0]}”
i += 1
j += 5
t.clear
end
I think this is the same as closures, or have I misunderstood?
The main idea that I have for ratlast is as a user-extensible command
language for Ruby applications. For example, what do you do if you have
a running Ruby system that you can’t take down, yet you have to add some
functionality? That is very easy to do using ratlast.
The main idea that I have for ratlast is as a user-extensible command
language for Ruby applications. For example, what do you do if you have
a running Ruby system that you can’t take down, yet you have to add some
functionality? That is very easy to do using ratlast.