From e06f7bf3747644bb04e1516bfe5ba2ddd9c651a1 Mon Sep 17 00:00:00 2001 From: Stefan Urbanek Date: Thu, 30 Jun 2005 21:10:02 +0000 Subject: [PATCH] added actor class git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/steptalk/trunk@21382 72102866-910b-0410-8b05-ffd578937521 --- ChangeLog | 11 +- Examples/Smalltalk/actor.st | 48 +++++ Frameworks/StepTalk/GNUmakefile | 2 + Frameworks/StepTalk/STActor.h | 44 +++++ Frameworks/StepTalk/STActor.m | 221 ++++++++++++++++++++++++ Frameworks/StepTalk/ScriptingInfo.plist | 1 + Languages/Smalltalk/STCompiler.m | 8 +- Tools/STExecutor.m | 4 +- 8 files changed, 332 insertions(+), 7 deletions(-) create mode 100644 Examples/Smalltalk/actor.st create mode 100644 Frameworks/StepTalk/STActor.h create mode 100644 Frameworks/StepTalk/STActor.m diff --git a/ChangeLog b/ChangeLog index ab40d35..f78b1cf 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,13 @@ -2005 Jul 19 Stefan Urbanek +2005 June 30 + + * STActor: new class + * Examples/Smalltalk/actor - new actor example + +2005 June 19 + + Version 0.9.0 + +2005 June 19 Stefan Urbanek * STEnvironment: search class name namespace when no object is found for given name and full scripting is enabled. diff --git a/Examples/Smalltalk/actor.st b/Examples/Smalltalk/actor.st new file mode 100644 index 0000000..0ab711e --- /dev/null +++ b/Examples/Smalltalk/actor.st @@ -0,0 +1,48 @@ +| actor engine source method | + + actor := STActor actorInEnvironment:Environment. +"Set ivars" + + ivars := NSMutableDictionary dictionary. + ivars setObject:1 forKey:'number'. + actor setInstanceVariables:ivars. + +" Get the proper engine " + engine := STEngine engineForLanguageWithName:'Smalltalk'. + +" This is the source of new method " + source := 'increment + number := number + 1. ^self'. + +" Create method " + method := engine methodFromSource:source + forReceiver:actor + inEnvironment:Environment. + +" Add the method to the actor " + actor addMethod:method. + +" Add another method with an argument " + source := 'setNumber:i number := i. ^self'. + method := engine methodFromSource:source + forReceiver:actor + inEnvironment:Environment. + actor addMethod:method. + + source := 'print + Transcript showLine: (\'The number is \', + (number description)). ^self'. + method := engine methodFromSource:source + forReceiver:actor + inEnvironment:Environment. + actor addMethod:method. + +" Send it! " + actor print. + actor increment. + actor print. + actor increment. + actor print. + actor setNumber:10. + actor print. + \ No newline at end of file diff --git a/Frameworks/StepTalk/GNUmakefile b/Frameworks/StepTalk/GNUmakefile index 34fd6ff..5e4fcdb 100644 --- a/Frameworks/StepTalk/GNUmakefile +++ b/Frameworks/StepTalk/GNUmakefile @@ -27,6 +27,7 @@ FRAMEWORK_NAME = StepTalk StepTalk_OBJC_FILES = \ NSInvocation+additions.m \ + STActor.m \ STBehaviourInfo.m \ STBundleInfo.m \ STClassInfo.m \ @@ -58,6 +59,7 @@ StepTalk_OBJC_FILES = \ # STDistantEnvironment.m \ STEPTALK_HEADER_FILES = \ + STActor.h \ STBundleInfo.h \ STContext.h \ STConversation.h \ diff --git a/Frameworks/StepTalk/STActor.h b/Frameworks/StepTalk/STActor.h new file mode 100644 index 0000000..78c2d23 --- /dev/null +++ b/Frameworks/StepTalk/STActor.h @@ -0,0 +1,44 @@ +/** + STActor + StepTalk actor + + Copyright (c) 2002 Free Software Foundation + + Written by: Stefan Urbanek + Date: 2005 June 30 + License: LGPL + + This file is part of the StepTalk project. +*/ + +#import + +#import "STMethod.h" + +@class NSMutableDictionary; +@class NSDictionary; +@class NSArray; +@class STEnvironment; + +@interface STActor:NSObject +{ + NSMutableDictionary *ivars; + NSMutableDictionary *methodDictionary; + + STEnvironment *environment; +} ++ actorInEnvironment:(STEnvironment *)env; +- initWithEnvironment:(STEnvironment *)env; +- (void)setEnvironment:(STEnvironment *)env; +- (STEnvironment *)environment; + +- (void)setObject:(id)anObject forVariable:(NSString *)aName; +- (id)objectForVariable:(NSString *)aName; + +- (void)addMethod:(id )aMethod; +- (id )methodWithName:(NSString *)aName; +- (void)removeMethod:(id )aMethod; +- (void)removeMethodWithName:(NSString *)aName; +- (NSArray *)methodNames; +- (NSDictionary *)methodDictionary; +@end diff --git a/Frameworks/StepTalk/STActor.m b/Frameworks/StepTalk/STActor.m new file mode 100644 index 0000000..dd22ab0 --- /dev/null +++ b/Frameworks/StepTalk/STActor.m @@ -0,0 +1,221 @@ +/** + STActor + StepTalk actor + + Copyright (c) 2002 Free Software Foundation + + Written by: Stefan Urbanek + Date: 2005 June 30 + License: LGPL + + This file is part of the StepTalk project. +*/ + +#import "STActor.h" + +#import "NSInvocation+additions.h" +#import "STEngine.h" +#import "STExterns.h" +#import "STObjCRuntime.h" + +#import +#import +#import +#import +#import +#import + +@implementation STActor +/** Return new instance of script object without any instance variables */ ++ actorInEnvironment:(STEnvironment *)env +{ + return AUTORELEASE([[self alloc] initWithEnvironment:env]); +} ++ actor +{ + return AUTORELEASE([[self alloc] init]); +} +- init +{ + self = [super init]; + methodDictionary = [[NSMutableDictionary alloc] init]; + ivars = [[NSMutableDictionary alloc] init]; + return self; +} +- initWithEnvironment:(STEnvironment *)env; +{ + self = [self init]; + [self setEnvironment:env]; + + return self; +} +- (void)dealloc +{ + RELEASE(methodDictionary); + RELEASE(ivars); + [super dealloc]; +} + +- (void)setValue:(id)value forKey:(NSString *)key +{ + /* FIXME: this is not optimal */ + if([ivars valueForKey:key] != nil) + { + [ivars setValue:value forKey:key]; + } + else + { + [super setValue:value forKey:key]; + } +} +- (id)valueForKey:(NSString *)key +{ + id value = nil; + + value = [ivars valueForKey:key]; + + if(value == nil) + { + value = [super valueForKey:key]; + } + return value; +} + +- (NSArray *)instanceVariableNames +{ + return [ivars allKeys]; +} +- (void)setInstanceVariables:(NSDictionary *)dictionary +{ + [ivars removeAllObjects]; + [ivars addEntriesFromDictionary:dictionary]; +} +- (NSDictionary *)instanceVarables +{ + return [NSDictionary dictionaryWithDictionary:ivars]; +} +- (void)addMethod:(id )aMethod +{ + [methodDictionary setObject:aMethod forKey:[aMethod methodName]]; +} +- (id )methodWithName:(NSString *)aName +{ + return [methodDictionary objectForKey:aName]; +} +- (void)removeMethod:(id )aMethod +{ + [self notImplemented:_cmd]; +} +- (void)removeMethodWithName:(NSString *)aName +{ + [methodDictionary removeObjectForKey:aName]; +} +- (NSArray *)methodNames +{ + return [methodDictionary allKeys]; +} +- (NSDictionary *)methodDictionary +{ + return [NSDictionary dictionaryWithDictionary:methodDictionary]; +} +/** Set object's environment. Note: This method should be replaced by +some other, more clever mechanism. */ +- (void)setEnvironment:(STEnvironment *)env +{ + ASSIGN(environment, env); +} +- (STEnvironment *)environment +{ + return environment; +} +- (BOOL)respondsToSelector:(SEL)aSelector +{ + if( [super respondsToSelector:(SEL)aSelector] ) + { + return YES; + } + + return ([methodDictionary objectForKey:NSStringFromSelector(aSelector)] != nil); +} + +- (NSMethodSignature *)methodSignatureForSelector:(SEL)sel +{ + NSMethodSignature *signature = nil; + + signature = [super methodSignatureForSelector:sel]; + + if(!signature) + { + signature = STConstructMethodSignatureForSelector(sel); + } + + return signature; +} + +- (void) forwardInvocation:(NSInvocation *)invocation +{ + STEngine *engine; + id method; + NSString *methodName = NSStringFromSelector([invocation selector]); + NSMutableArray *args; + id arg; + int index; + int count; + id retval = nil; + + method = [methodDictionary objectForKey:methodName]; + + if(!method) + { + [NSException raise:@"STActorException" + format:@"No script object method with name '%@'", + methodName]; + return; + } + + engine = [STEngine engineForLanguageWithName:[method languageName]]; + + /* Get arguments as array */ + count = [[invocation methodSignature] numberOfArguments]; + args = [NSMutableArray array]; + + for(index = 2; index < count; index++) + { + arg = [invocation getArgumentAsObjectAtIndex:index]; + + if (arg == nil) + { + [args addObject:STNil]; + } + else + { + [args addObject:arg]; + } + } + + retval = [engine executeMethod:method + forReceiver:self + withArguments:args + inEnvironment:environment]; + + [invocation setReturnValue:&retval]; +} +- (void)encodeWithCoder:(NSCoder *)coder +{ + // [super encodeWithCoder: coder]; + + [coder encodeObject:methodDictionary]; + [coder encodeObject:ivars]; +} + +- initWithCoder:(NSCoder *)decoder +{ + self = [super init]; //[super initWithCoder: decoder]; + + [decoder decodeValueOfObjCType: @encode(id) at: &methodDictionary]; + [decoder decodeValueOfObjCType: @encode(id) at: &ivars]; + return self; +} + + +@end diff --git a/Frameworks/StepTalk/ScriptingInfo.plist b/Frameworks/StepTalk/ScriptingInfo.plist index 4dfac15..e2b59e6 100644 --- a/Frameworks/StepTalk/ScriptingInfo.plist +++ b/Frameworks/StepTalk/ScriptingInfo.plist @@ -2,6 +2,7 @@ ScriptingInfoClass = StepTalkScriptingInfo; Classes = ( + STActor, STEnvironment, STLanguage, STScript, diff --git a/Languages/Smalltalk/STCompiler.m b/Languages/Smalltalk/STCompiler.m index bcf59ed..e155e05 100644 --- a/Languages/Smalltalk/STCompiler.m +++ b/Languages/Smalltalk/STCompiler.m @@ -189,7 +189,7 @@ extern int STCparse(void *context); int parsRetval = 0; - NSDebugLLog(@"STCompiler", @"Compile method", aString); + NSDebugLLog(@"STCompiler", @"Compile method for receiver %@", [receiverObject className]); if(!environment) { @@ -493,12 +493,12 @@ extern int STCparse(void *context); NS_DURING /* test whether variable is an ivar s*/ obj = [receiver valueForKey:varName]; - NSDebugLLog(@"STCompiler", "New name: receiver variable %@", varName); + NSDebugLLog(@"STCompiler", @"New name: receiver variable %@", varName); [receiverVars addObject:varName]; NS_HANDLER if([[localException name] isEqualToString:NSUndefinedKeyException]) { - NSDebugLLog(@"STCompiler", "New name: extern %@", varName); + NSDebugLLog(@"STCompiler", @"New name: extern %@", varName); /* receiver has no such variable */ [externVars addObject:varName]; } @@ -510,7 +510,7 @@ extern int STCparse(void *context); } else { - NSDebugLLog(@"STCompiler", "New name: extern %@ (nil receiver)", varName); + NSDebugLLog(@"STCompiler", @"New name: extern %@ (nil receiver)", varName); [externVars addObject:varName]; } diff --git a/Tools/STExecutor.m b/Tools/STExecutor.m index 63f7810..f9e9a97 100644 --- a/Tools/STExecutor.m +++ b/Tools/STExecutor.m @@ -164,7 +164,7 @@ const char *STExecutorCommonOptions = { NSDebugLog(@"Executing script '%@'",file); - env = [conversation environment]; + env = [conversation context]; [env setObject:args forName:@"Args"]; [env setObject:env forName:@"Environment"]; @@ -216,7 +216,7 @@ const char *STExecutorCommonOptions = NSString *name; NSArray *objects; - dict = [[conversation environment] objectDictionary]; + dict = [[conversation context] objectDictionary]; objects = [[dict allKeys] sortedArrayUsingSelector:@selector(compare:)];