macdevcenter.com
oreilly.comSafari Books Online.Conferences.

advertisement

AddThis Social Bookmark Button

Embedding F-Script into Cocoa Applications
Pages: 1, 2, 3

Using the FSInterpreter Class

The technique described above is very easy to use and suitable for numerous situations. Nonetheless, certain cases require more control and additional functionalities.



In such cases we can look to the FSInterpreter class, which offers total control of the F-Script interpreter. Among other things, this class offers:

  • Easier and more powerful error management.
  • Context conservation, in other words, the possibility of executing different bits of F-Script code at different times in the same workspace.

An FSInterpreter instance represents an F-Script interpreter associated with a workspace. It is easily created in Objective-C:

FSInterpreter *myInterpreter = [[FSInterpreter alloc] init];

An interpreter enables you to add variables in the associated workspace or to modify the value of existing variables:

[myInterpreter setObject:[NSDate date] forIdentifier:@"myDate"];

An interpreter enables you to consult the value of a variable in the workspace:

 BOOL found;

id result = [myInterpreter objectForIdentifier:@"myDate" found:&found];

It's also possible to retrieve the list of names of variables defined in the workspace, in the form of an array of NSStrings:

NSArray *identifiers = [myInterpreter identifiers];

To execute F-Script code, pass a character string containing this code to the execute: method of the interpreter. You will get back an FSInterpreterResult object. The following example uses the F-Script "hello world" code:

FSInterpreterResult *result = [myInterpreter execute:@"sys log:'hello world'"];

The FSInterpreterResult object offers complete control over the execution result. The isSyntaxError, isExecutionError, and isOk methods return a Boolean, which enables us to know the status of the result. In the event of an error, the errorMessage and errorRange methods enable us to obtain the error message and relevant location in the F-Script source code. The inspectBlocksInCallStack method lets us open the graphical inspector of the blocks present in the callstack corresponding to the error. If execution does not throw an error, the result method enables us to get the result of the evaluation of the F-Script code.

To illustrate this API, here's a complete program, to be compiled in Project Builder like a Foundation Tool and launched from the Project Builder or a UNIX terminal window. It's a command line interface for F-Script: the program reads a command from its standard input, executes it, prints the result on its standard output and then starts again. Note that this is a non-graphical program (does not use the application kit). It therefore does not allow the F-Script graphic functionalities to be used.

#import <stdio.h>
#import <Foundation/Foundation.h>
#import <FScript/FScript.h>

int main (int argc, char **argv, char **env)
{ 
  FSInterpreter *interpreter;
  FSInterpreterResult *execResult;
  char c_command[10000]; 
  NSString *command; 

  NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
  interpreter = [[FSInterpreter alloc] init]; // create the interpreter
  [pool release];
  
  while(1)
  {
    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
    
    command = [NSString  stringWithCString:fgets(c_command, 10000, stdin)];    
    execResult = [interpreter execute:command]; // execute the F-Script command

    if ([execResult isOk]) // test status of the result
    {
      id result = [execResult result]; 

      // print the result
      if (result == nil) puts("nil");
      else               puts([[result printString] cString]);
      if (![result isKindOfClass:[FSVoid class]]) putchar('\n'); 
    }
    else
    { 
      // print an error message
      puts([[NSString stringWithFormat:@"%@ , 
        character %d\n",[execResult errorMessage],[execResult errorRange].location] 
        cString]);
    }
    [pool release];
  } 
  return 0;      
}

FSInterpreterView Component and Palette for Interface Builder

The FSInterpreterView class -- a subclass of NSView -- offers an interactive, command line interface-type F-Script graphical component. The component has its own F-Script interpreter and is ready to use. It may be instantiated and manipulated by program.

Screenshot.
An FSInterpreterView.

This object has methods that allow you to modify the font size, display a service message for the user, insert a command or retrieve the associated FSInterpreter object. The following simple program opens a window containing an FSInterpreter View.

#import <Cocoa/Cocoa.h>
#import <FScript/FScript.h>

int main(int argc, const char *argv[])
{
  NSApplication *NSApp    = [NSApplication sharedApplication];
  NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

  // Create a window
  NSWindow *mainWindow  = [[NSWindow alloc]
initWithContentRect:NSMakeRect(100,100,500,400) styleMask:NSClosableWindowMask | 
  NSTitledWindowMask backing:NSBackingStoreBuffered defer:false];
  
  // Create an FSInterpreterView
  FSInterpreterView *fscriptView = [[[FSInterpreterView alloc] 
     initWithFrame:NSMakeRect(0,0,0,0)] 
     autorelease];
  
  // Insert the FSInterpreterView inside the window
  [mainWindow setContentView:fscriptView];

  [fscriptView setFontSize:16]; // We want big fonts !

  [mainWindow orderFront:nil];
  [pool release];
  [NSApp run];
  return 0; 
}

A FSInterpreterView may also be manipulated directly from Interface Builder using the FScriptPalette.palette.

Screen shot.
The F-Script palette for Interface Builder.

The palette enables an FSInterpreterView to be placed in a graphical interface using a simple drag and drop movement.

It also offers another functionality--live mode--which enables F-Script to be used directly from Interface Builder, without being in test mode. In live mode, it is possible to set up connections between interface objects and F-Script objects (for example, set up a connection between a button and a block) and to save everything in the nib file. Using this feature it is possible to build a graphical application entirely from Interface Builder by associating F-Script code blocks with interface elements.

Screen shot.
F-Script live mode in Interface Builder: connecting F-Script to a button.

To use live mode, first you instantiate an F-Script interpreter. To do so, simply drag and drop from the F-Script palette to any other window. The instantiated FSInterpreterView object contains the F-Script interpreter, which enables operation in live mode. To activate this mode, double-click on the instance of FSInterpreterView. An active F-Script window appears from which it will be possible to configure interface objects (and their outlets) by using F-Script instructions directly. The FSInterpreterView is used for setting up connections between the F-Script interpreter and external objects (see Figure 4).

Final Thoughts

In this article we showed how Objective-C developers can embed F-Script into their applications. But what about existing, third-party, applications? Here comes F-Script Anywhere.

This is an amazing new tool, built by Nicholas Riley, which lets you dynamically embed F-Script at runtime into any Cocoa application and lets you take control of the objects inside the application and freely play with them. You can get F-Script Anywhere from Nicholas' Web site.

Also, don't forget to drop by the F-Script site to keep up on latest releases that you can download. You might also want to read the previous articles in this series, and take a look at their TalkBacks. Enjoy!

Philippe Mougin specializes in object-oriented technologies and enterprise systems. He is the creator of F-Script, an open-source object-oriented scripting language for Cocoa.


Return to the Mac DevCenter.