diff options
author | Matthias Andreas Benkard <matthias@benkard.de> | 2008-06-27 15:01:07 +0200 |
---|---|---|
committer | Matthias Andreas Benkard <matthias@benkard.de> | 2008-06-27 15:01:07 +0200 |
commit | efad95ec36837acdcc1aa4012675aabf0b72c756 (patch) | |
tree | 28a1877f6dfa7f4106ab0663a6fb841e8fd9598f | |
parent | 189d02b12aa33fc18eaff9558675d9fa9d6ba668 (diff) |
MLKInterpreter: Correctly handle multiple values.
-rw-r--r-- | MLKInterpreter.h | 7 | ||||
-rw-r--r-- | MLKInterpreter.m | 82 | ||||
-rw-r--r-- | MLKReadEvalPrintLoop.m | 30 |
3 files changed, 76 insertions, 43 deletions
diff --git a/MLKInterpreter.h b/MLKInterpreter.h index 8fcc1ec..c149389 100644 --- a/MLKInterpreter.h +++ b/MLKInterpreter.h @@ -16,6 +16,7 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ +#import <Foundation/NSArray.h> #import <Foundation/NSObject.h> @class MLKLexicalContext, MLKLexicalEnvironment; @@ -24,7 +25,7 @@ @interface MLKInterpreter : NSObject +(void) initialize; -+(id) eval:(id)program - inLexicalContext:(MLKLexicalContext *)context - withEnvironment:(MLKLexicalEnvironment *)lexenv; ++(NSArray*) eval:(id)program + inLexicalContext:(MLKLexicalContext *)context + withEnvironment:(MLKLexicalEnvironment *)lexenv; @end diff --git a/MLKInterpreter.m b/MLKInterpreter.m index 7fc14d7..0b50312 100644 --- a/MLKInterpreter.m +++ b/MLKInterpreter.m @@ -34,6 +34,23 @@ #import <Foundation/NSString.h> +static id nullify (id value) +{ + if (value) + return value; + else + return [NSNull null]; +} + +static id denullify (id value) +{ + if (value == [NSNull null]) + return nil; + else + return value; +} + + static MLKPackage *cl; static MLKPackage *sys; static MLKSymbol *IF; @@ -80,9 +97,9 @@ static MLKSymbol *_LAMBDA; } -+(id) eval:(id)program - inLexicalContext:(MLKLexicalContext *)context - withEnvironment:(MLKLexicalEnvironment *)lexenv ++(NSArray*) eval:(id)program + inLexicalContext:(MLKLexicalContext *)context + withEnvironment:(MLKLexicalEnvironment *)lexenv { MLKDynamicContext *dynamicContext = [MLKDynamicContext currentContext]; @@ -102,18 +119,18 @@ static MLKSymbol *_LAMBDA; else if ([context variableIsLexical:program]) { //NSLog (@"Processing lexical variable."); - return [lexenv valueForSymbol:program]; + return [NSArray arrayWithObject:nullify([lexenv valueForSymbol:program])]; } else { //NSLog (@"Processing special variable."); - return [dynamicContext valueForSymbol:program]; + return [NSArray arrayWithObject:nullify([dynamicContext valueForSymbol:program])]; } } else if (![program isKindOfClass:[MLKCons class]]) { // Everything that is not a list or a symbol evaluates to itself. - return program; + return [NSArray arrayWithObject:nullify(program)]; } else { @@ -123,13 +140,15 @@ static MLKSymbol *_LAMBDA; { if (car == APPLY) { - MLKCons *rest = [self eval:[[[program cdr] cdr] car] - inLexicalContext:context - withEnvironment:lexenv]; + MLKCons *rest = denullify([[self eval:[[[program cdr] cdr] car] + inLexicalContext:context + withEnvironment:lexenv] + objectAtIndex:0]); - id <MLKFuncallable> function = [self eval:[[program cdr] car] - inLexicalContext:context - withEnvironment:lexenv]; + id <MLKFuncallable> function = denullify([[self eval:[[program cdr] car] + inLexicalContext:context + withEnvironment:lexenv] + objectAtIndex:0]); return [function applyToArray:(rest ? (id)[rest array] @@ -144,19 +163,21 @@ static MLKSymbol *_LAMBDA; id <MLKFuncallable> function; - function = [self eval:[MLKCons cons:_LAMBDA with:lambdaListAndBody] - inLexicalContext:context - withEnvironment:lexenv]; + function = denullify([[self eval:[MLKCons cons:_LAMBDA with:lambdaListAndBody] + inLexicalContext:context + withEnvironment:lexenv] + objectAtIndex:0]); [context addMacro:function forSymbol:name]; - return name; + return [NSArray arrayWithObject:nullify(name)]; } else if (car == EVAL) { - return [self eval:[self eval:[program cdr] - inLexicalContext:context - withEnvironment:lexenv] + return [self eval:denullify([[self eval:[program cdr] + inLexicalContext:context + withEnvironment:lexenv] + objectAtIndex:0]) inLexicalContext:[MLKLexicalContext globalContext] withEnvironment:[MLKLexicalEnvironment globalEnvironment]]; @@ -175,14 +196,14 @@ static MLKSymbol *_LAMBDA; lambdaListName:lambdaList context:context environment:lexenv]); - return closure; + return [NSArray arrayWithObject:nullify(closure)]; } else if (car == LET) { id declarations; id clauses; id body; - id result; + NSArray *result; MLKLexicalContext *ctx; MLKLexicalEnvironment *env; MLKDynamicContext *dynctx; @@ -240,9 +261,10 @@ static MLKSymbol *_LAMBDA; else { variable = [clause car]; - value = [self eval:[[clause cdr] car] - inLexicalContext:context - withEnvironment:lexenv]; + value = denullify([[self eval:[[clause cdr] car] + inLexicalContext:context + withEnvironment:lexenv] + objectAtIndex:0]); } if ([ctx variableIsLexical:variable]) @@ -293,7 +315,7 @@ static MLKSymbol *_LAMBDA; } else if (car == QUOTE) { - return [[program cdr] car]; + return [NSArray arrayWithObject:nullify([[program cdr] car])]; } else if (car == SETQ) { @@ -314,10 +336,11 @@ static MLKSymbol *_LAMBDA; while (rest) { - id result = [self eval:[rest car] - inLexicalContext:context - withEnvironment:lexenv]; - [args addObject:(result ? (id)result : (id)[NSNull null])]; + id result = [[self eval:[rest car] + inLexicalContext:context + withEnvironment:lexenv] + objectAtIndex:0]; + [args addObject:result]; rest = [rest cdr]; } @@ -338,6 +361,7 @@ static MLKSymbol *_LAMBDA; [NSException raise:@"MLKNoSuchOperatorException" format:@"%@ does not name a known operator.", [car descriptionForLisp]]; + return nil; } } } diff --git a/MLKReadEvalPrintLoop.m b/MLKReadEvalPrintLoop.m index 4ccc339..e9e90db 100644 --- a/MLKReadEvalPrintLoop.m +++ b/MLKReadEvalPrintLoop.m @@ -27,6 +27,7 @@ #import <Foundation/NSAutoreleasePool.h> #import <Foundation/NSException.h> +#import <Foundation/NSNull.h> #import <Foundation/NSString.h> #import <editline/history.h> @@ -87,7 +88,7 @@ static const char *prompt (EditLine *e) { if (line_length > 1) { NSAutoreleasePool *pool; - id result; + NSArray *results; id code; pool = [[NSAutoreleasePool alloc] init]; @@ -96,18 +97,25 @@ static const char *prompt (EditLine *e) { NS_DURING { + int i; + code = [MLKReader readFromString:[NSString stringWithUTF8String:line]]; - result = [MLKInterpreter eval:code - inLexicalContext:[MLKLexicalContext - globalContext] - withEnvironment:[MLKLexicalEnvironment - globalEnvironment]]; - - if (result) - printf ("%s\n", [[result descriptionForLisp] UTF8String]); - else - printf ("()\n"); + results = [MLKInterpreter eval:code + inLexicalContext:[MLKLexicalContext + globalContext] + withEnvironment:[MLKLexicalEnvironment + globalEnvironment]]; + + for (i = 0; i < [results count]; i++) + { + id result = [results objectAtIndex:i]; + if (result != [NSNull null]) + printf ("%s\n", [[result descriptionForLisp] UTF8String]); + else + printf ("()\n"); + } + } NS_HANDLER { |