Best way to for F-Script validation?

39 views
Skip to first unread message

Vyacheslav Artemev

unread,
Feb 7, 2012, 11:55:37 PM2/7/12
to F-Script
Currently i develop Cocoa application with embedded F-Script. So, i
have F-Script editor in my app. Question is what are the best way to
validate F-Script code without executing it?

Jonathan Mitchell

unread,
Feb 8, 2012, 8:34:18 AM2/8/12
to f-sc...@googlegroups.com, Vyacheslav Artemev

I use the following.
Basically we build a block from our source and trap any exceptions that result.
The only small issue is the need to access framework non public API.

Regards

Jonathan Mitchell
Mugginsoft LLP

================================================
KosmicTask - the Integrated Scripting Environment for OS X.
http://www.mugginsoft.com/KosmicTask
================================================

#import <FScript/FScript.h>
#import "BlockStackElem.h" // on user search path

- (BOOL)build {

NSString *resultString = @"";

// get script source
NSString *source = [self scriptSourceWithError:YES];
if (!source) return NO;

@try {

// make a block. raises on compilation or syntax error
//
// http://www.fscript.org/documentation/EmbeddingFScriptIntoCocoa/index.htm
//
FSBlock *block = [source asBlock];
(void)block;
}
@catch (NSException* e) {
NSDictionary *userInfo = [e userInfo];

// the exception reason has the error string but no line number info
// (this could perhaps be calculated from the character indicies in
// BlockStackElem)
NSArray *blockStack = [userInfo objectForKey:@"FScriptBlockStack"];

// block stack elem is not part of the public API
// hence we import it separately.
// FSInterpreterResult does supply all error info
// but it is returned only as result of execution
BlockStackElem *blockStackElem = [blockStack objectAtIndex:0];

// report error
self.error = [NSString stringWithFormat:@"%@", [blockStackElem errorStr]];

// get error range
NSUInteger firstCharIndex = [blockStackElem firstCharIndex];
NSUInteger lastCharIndex = [blockStackElem lastCharIndex];

NSRange range = NSMakeRange(firstCharIndex, lastCharIndex - firstCharIndex);
self.errorInfo = [NSMutableDictionary dictionaryWithCapacity:2];
[self.errorInfo setObject:NSStringFromRange(range) forKey:MGSRangeErrorKey];
[self.errorInfo setObject:self.error forKey:NSLocalizedFailureReasonErrorKey]; // required
}

return [self processBuildResult:resultString];
}

Philippe Mougin

unread,
Feb 8, 2012, 1:26:12 PM2/8/12
to F-Script
On Feb 8, 2:34 pm, Jonathan Mitchell <jonathan_mitch...@yahoo.com>
wrote:
> On 8 Feb 2012, at 04:55, Vyacheslav Artemev wrote:
>
> > Currently i develop Cocoa application with embedded F-Script. So, i
> > have F-Script editor in my app. Question is what are the best way to
> > validate F-Script code without executing it?
>
> I use the following.
> Basically we build a block from our source and trap any exceptions that result.
> The only small issue is the need to access framework non public API.
>
> Regards
>
> Jonathan Mitchell
> Mugginsoft LLP
>
> ================================================
> KosmicTask - the Integrated Scripting Environment for OS X.http://www.mugginsoft.com/KosmicTask
> ================================================
>
> #import <FScript/FScript.h>
> #import "BlockStackElem.h"    // on user search path
>
> - (BOOL)build {
>
>         NSString *resultString = @"";
>
>         // get script source
>         NSString *source = [self scriptSourceWithError:YES];
>         if (!source) return NO;
>
>         @try {
>
>                 // make a block. raises on compilation or syntax error
>                 //
>                 //http://www.fscript.org/documentation/EmbeddingFScriptIntoCocoa/index.htm
>                 //
>                 FSBlock *block = [source asBlock];
>                 (void)block;
>         }
>         @catch (NSException* e) {
>                 NSDictionary *userInfo = [e userInfo];
>
>                 // the exception reason has the error string but no line number info
>                 // (this could perhaps be calculated from the character indicies in
>                 // BlockStackElem)
>                 NSArray *blockStack = [userInfo objectForKey:@"FScriptBlockStack"];
>
>                 // block stack elem is not part of the public API
>                 // hence we import it separately.
>                 // FSInterpreterResult does supply all error info
>                 // but it is returned only as result of execution
>                 BlockStackElem *blockStackElem = [blockStack objectAtIndex:0];
>
>                 // report error
>                 self.error = [NSString stringWithFormat:@"%@", [blockStackElem errorStr]];
>
>                 // get error range
>                 NSUInteger firstCharIndex = [blockStackElem firstCharIndex];
>                 NSUInteger lastCharIndex = [blockStackElem lastCharIndex];
>
>                  NSRange range =  NSMakeRange(firstCharIndex, lastCharIndex - firstCharIndex);
>                 self.errorInfo = [NSMutableDictionary dictionaryWithCapacity:2];
>                 [self.errorInfo setObject:NSStringFromRange(range) forKey:MGSRangeErrorKey];
>                 [self.errorInfo setObject:self.error forKey:NSLocalizedFailureReasonErrorKey];  // required
>         }
>
>         return [self processBuildResult:resultString];
> }

Hi,

An alternative, that avoid touching private APIs, is to use the method
"asBlockOnError:" defined in the FSNSString category (or the method
"blockFromString:onError:" in FSSystem).

For example:

[source asBlockOnError:[@"[:msg :start :end | {msg, start, end}]"
asBlock]];

This will either return an FSBlock instance (if there is no syntax
error) or an array with error information (if there is a syntax
error).

A second alternative is to use FSInterpreter's execute method after
patching the source code you want to validate in a way that will
prevent it to execute, as shown here:

FSInterpreterResult *result = [myInterpreter execute:[NSString
stringWithFormat:@"[%@]", source]];

If you then use the error range provided by FSInterpreterResult,
remember to decrement the location by one.

Philippe

Vyacheslav Artemev

unread,
Feb 8, 2012, 1:51:33 PM2/8/12
to f-sc...@googlegroups.com
Awesome! Thank you very much!

2012/2/8 Philippe Mougin <pmo...@acm.org>

--
You received this message because you are subscribed to the Google Groups "F-Script" group.
To post to this group, send email to f-sc...@googlegroups.com.
To unsubscribe from this group, send email to f-script+u...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/f-script?hl=en.


Reply all
Reply to author
Forward
0 new messages