= SLRUBY

This S-Lang module provides bindings to the Ruby interpreter.

== FEATURES

=== Calling Ruby from S-Lang

The module provides five ways to call Ruby from S-Lang:
* rb_load_file("filename");
* rb_eval("some ruby code");
* rb_call_function("function name", optional parameters);
* rb_call_method(ruby object, "method name", optional parameters);
* rubyobject.methodname(optional parameters);

'.foo?' methods can be called as '.foo_p()':
  variable File = rb_eval("File")
  File.exists_p("/some/file")

Except for rb_load_file(), they all return a value to S-Lang.  See "passing
values from Ruby" for more on these return values. The () after
rubyobject.methodname are necessary, even if they are empty. See "pasing
values to Ruby" for more on the parameters.

=== Calling S-Lang from Ruby

S-Lang functions in the global namespace can be called from Ruby using the
+SLang+ module. There is a difference between Ruby and S-Lang here. Ruby
functions always return one value. Multiple values are simulated by using
arrays, that is

 def m1
   return 1, 2, 3
 end

is equivalent to

 def m1
   return [1, 2, 3]
 end

 a,b,c = 1,2,3

is equivalent to

 a,b,c = [1,2,3]

however

 a = 1

is NOT the same as

 a = [1]

S-Lang functions can return 0, 1, or more values. So when calling S-Lang
functions from Ruby, we always return an array.

S-Lang:

 define m1()
 {
    return 1, 2, 3;
 }

Ruby:

 a, b, c = SLang.m1

If your S-Lang function returns one value, beware that it's returned as an array
of length 1:

 define m2()
 {
    return 1;
 }

Ruby:

 a = SLang.m2[0]

S-Lang variables are also accessible from Ruby as 'SLang.foo'. This will
always return just one value. The downside is that you have to know that
e.g. in JED 'what_column' is a function but 'what_line' is a read-only
variable:

 column = SLang.what_column[0]
 line = SLang.what_line

It's also possible to change S-Lang variables in Ruby:
 SLang.TAB=6
will set the TAB width in JED to 6. You *must* use a '.' because
 SLang::TAB=6
would create a new constant in the +SLang+ module that would be set to 6, but
would not change S-Lang's 'TAB' variable. So accessing S-Lang variables with
'::' is not supported.

You can also include the +SLang+ module in a class and call S-Lang functions
directly as instance methods.
 class Foo
   include SLang
   column = what_column[0]
 end

For S-Lang namespaces, you can use the +SLang+.+import_namespace+ function:
 SLang.import_namespace "listing", "Listing"
 SLang::Listing.get_confirmation("#{dest} exists. Overwrite")

=== Pasing values from Ruby
* Ruby strings are converted to bstrings
* Ruby symbols are converted to strings
* Fixnums are converted to integers
* Bignums and Floats are converted to doubles
* Hashes, objects and other ruby types are converted to opaque 
  Ruby_Value_Type objects in S-Lang. These Ruby_Value_Type objects can be
  used with rb_call_method() or with the object.method() syntax described under
  "calling Ruby from S-Lang". They also have some extra syntax defined:
  * 'object[]' calls the '[]' method of the object
  * 'object[] =' calls the '[]=' method of the object
  * 'object.foo =' .. calls its 'foo=' method
* Ruby arrays are recursively converted to S-Lang lists.

=== Pasing values to Ruby
* Strings and bstrings are converted to Strings
* Integers up to 2 ^ 31 are converted to Fixnums
* Integers over 2 ^ 31 are converted to Bignums
* Floats and doubles are converted to Floats
* S-Lang arrays and lists are recursively converted to Ruby arrays.
* References are converted to +SLangProc+ objects, which are a subclass of
  +Proc+. You probably don't need this, but it's used in slruby.sl to make
  S-Lang functions callable from Ruby.
* If the last parameter passed to Ruby is a reference, it is converted to a
  block. This lets you yield to S-Lang functions from Ruby.
* Converting other S-Lang datatypes to Ruby isn't supported.

== REQUIREMENTS

* S-Lang 2.1
* Ruby 1.8.5, 1.8.6 or 1.9.0 revision 17914 or greater.


== INSTALL

Build and install the module in three steps:

 ruby extconf.rb
 make
 sudo make install
