Luna's REPL

Luna’s REPL (Read-Eval-Print Loop) reveals a tremendous amount about the internals of the compiler / scripter. First, the namespaces used include “Luna.Types” and “Luna.Functions,” which we will get to in time:

usingSystem;

usingSystem.IO;

usingLuna;

usingLuna.Types;

usingLuna.Functions;

The namespace provided is “Luna.REPL,” so other programs might embed Luna and have a scripter to invoke:

namespaceLuna.REPL

{

      public class REPL

      {

“Start” has several overloads so that it can take input from any TextReader and send output to any TextWriter:

            public static void Start(TextReader input, TextWriter output)

            {

First off, create an instance of type “Luna,” the main purpose of which is to store an InteractionEnvironment, which is a Dictionary for installing and looking up the values, or “bindings” of variables:

                  Luna Luna = new Luna(input, output);

Next, write some banner text and get to the business of reading, evaluating, and printing in a loop that goes on forever:

                  output.WriteLine("\nWelcome to Luna " + Luna.Version + "\n");

                  while (true)

                  {

                        output.Write("luna>");

                        object result;

                        try

                        {

                              object sexp = Read.CSApply(input);

That last line of code reveals the pattern for invoking functions. “Read” is an implementation of the Scheme primitive by the same name. In Scheme, one would write “(read input)”, and the implementation of the same procedure call in C# is Read.CSApply(input). So, it’s easy to generalize and represent every Scheme function with a C# class of the same name that supports a “CSApply” method to arguments. Applying a function to its arguments; that’s the pattern to exploit via virtual functions. “Apply” is the Scheme primitive, and Luna supports it as a virtual function, too, usually by simply calling the static “CSApply.” I do not know what Luna’s author meant by the abbreviation “CS”. The return value of “Read.CSApply” is of type “object” and represents an “S-Expression,” the base data type in Scheme.

                              result = Eval.CSApply(sexp, Luna.InteractionEnvironment);

That line of code applies “Eval” to the s-expression returned by “Read” and returns a result. The next code block catches any exception thrown above and assigns it to the result of the current iteration of the loop, and if the object happens to be the global instance of “Exit.Bye,”, break out of the forever loop :

                        }

                        catch (Exception e)

                        {

                              result = e;

                        }

                        if (result == Exit.Bye)

                        {

                              Write.CSApply("Good Bye.", output);

                              break;

                        }

If everything has been OK so far, Apply “Write,” to the result on the output, and toss in a newline for hygiene. “Write” is pretty much the same thing as “Print”:

                        else

                        {

                              Write.CSApply (result, output);

                              output.WriteLine();

                        }

                  }

            }

 

Here are a few convenience overloads and a “Main” routine that simply calls the most generic of them:

            public static void Start(TextReader input)

            {Start(input, System.Console.Out);}

            public static void Start(TextWriter output)

            {Start(System.Console.In, output);}

            public static void Start()

            {Start(System.Console.In, System.Console.Out);}

            public static void Main(String[] argv)

            {Start();}

      }

}

Next time, we’ll get into “Read” and see how it creates S-expressions.

 

 

Published Monday, February 23, 2004 5:44 PM by brianbec

Comments

No Comments

Leave a Comment

(required) 
(required) 
(optional)
(required)