// TLGlobals.m // by David Phillip Oster // September 2007 // // Cocoa centric lisp // // Copyright 2007 David Phillip Oster // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #import "TLLisp.h" static NSMutableArray *gTLSymbolTableStack = nil; static NSMutableDictionary *gTLTopLevel; TLAtom *gTLOpenParen; TLAtom *gTLCloseParen; TLAtom *gTLSingleQuote; TLAtom *gTLT; TLAtom *gTLLambda; TLAtom *TLInternAndSet(NSString *name, Class applies) { TLAtom *atom = TLIntern(name); [atom setValue:(TLID *)applies]; return atom; } void TLInit(void) { if (nil == gTLSymbolTableStack) { gTLSymbolTableStack = [[NSMutableArray alloc] init]; gTLTopLevel = [NSMutableDictionary dictionary]; [gTLSymbolTableStack addObject:gTLTopLevel]; gTLOpenParen = TLIntern(@"("); gTLCloseParen = TLIntern(@")"); gTLSingleQuote = TLIntern(@"'"); gTLT = TLIntern(@"T"); unichar c = 0x3BB; NSMutableString *lambda = [NSMutableString stringWithCharacters:&c length:1]; gTLLambda = TLIntern(lambda); TLInternAndSet(@"progn", [TLFuncprogn class]); TLInternAndSet(@"prog0", [TLFuncprog0 class]); TLInternAndSet(@"'", [TLFuncquote class]); TLInternAndSet(@"set", [TLFuncset class]); TLInternAndSet(@"perform", [TLFuncPerformSelector class]); TLInternAndSet(@"class", [TLFuncClassFromString class]); TLInternAndSet(@"if", [TLFunctlIf class]); TLInternAndSet(@"while", [TLFunctlWhile class]); TLInternAndSet(@"and", [TLFunctlAnd class]); TLInternAndSet(@"or", [TLFunctlOr class]); TLInternAndSet(@"+", [TLFuncplus class]); TLInternAndSet(@"-", [TLFuncminus class]); TLInternAndSet(@"*", [TLFunctimes class]); TLInternAndSet(@"/", [TLFuncdivide class]); TLInternAndSet(@"=", [TLFunceq class]); TLInternAndSet(@">", [TLFuncgt class]); TLInternAndSet(@"<", [TLFunclt class]); TLInternAndSet(@">=", [TLFuncge class]); TLInternAndSet(@"<=", [TLFuncle class]); TLInternAndSet(@"print", [TLFuncprint class]); TLInternAndSet(@"list", [TLFunclist class]); TLInternAndSet(@"count", [TLFunccount class]); TLInternAndSet(@"at", [TLFuncAtIndex class]); TLInternAndSet(@"insert", [TLFuncInsertAtIndex class]); TLInternAndSet(@"remove", [TLFuncRemoveAtIndex class]); TLInternAndSet(@"replace", [TLFuncReplaceAtIndexWith class]); // property support TLInternAndSet(@"propertyForKey", [TLFuncPropertyForKey class]); TLInternAndSet(@"removePropertyForKey", [TLFuncRemovePropertyForKey class]); TLInternAndSet(@"setPropertyForKey", [TLFuncSetPropertyForKey class]); TLInternAndSet(@"propertyKeys", [TLFuncPropertyKeys class]); TLInternAndSet(@"nil", nil); } } void TLShutdown(void) { int i; for(i = [gTLSymbolTableStack count] - 1;0 <= i; --i){ gTLTopLevel = [gTLSymbolTableStack lastObject]; NSArray *allKeys = [gTLTopLevel allKeys]; NSEnumerator *enumerator = [allKeys objectEnumerator]; NSString *key; while (nil != (key = [enumerator nextObject])) { TLAtom *atom = [gTLTopLevel objectForKey:key]; [atom setOwner:nil]; // break the backlink, since we are dieing [atom setValue:nil]; // break the default cycle, since we are dieing } [gTLSymbolTableStack removeLastObject]; } [gTLSymbolTableStack release]; gTLSymbolTableStack = nil; gTLTopLevel = nil; } NSMutableDictionary *TLTopLevel(void) { return gTLTopLevel; } TLAtom *TLIntern(NSString *name) { TLAtom *atom = [gTLTopLevel objectForKey:name]; if (nil == atom) { atom = [[[TLAtom alloc] initWithOwner:gTLTopLevel] autorelease]; [gTLTopLevel setObject:atom forKey:name]; [atom setValue:atom]; } return atom; } // bind an NSArray of atoms to the values: args returns a token for unbinding. // note that the array here called "args" is really the call: the first element is the lambda expression we'll be evaluating TLID *TLBind(NSArray *formals, NSArray *args) { NSMutableDictionary *tokenDict = [NSMutableDictionary dictionary]; int i, iCount = [formals count]; for(i = 0; i < iCount; ++i) { NSString *key; key = [[formals objectAtIndex:i] name]; TLID *val = [args objectAtIndex:i+1]; TLAtom *atom = [gTLTopLevel objectForKey:key]; TLID *oldValue = [atom value]; if (nil != oldValue) { [tokenDict setObject:oldValue forKey:[NSValue valueWithPointer:atom]]; } [atom setValue:val]; } return tokenDict; } // unbind, using the token. void TLUnbind(TLID *token) { NSMutableDictionary *tokenDict = (NSMutableDictionary *) token; NSArray *allKeys = [tokenDict allKeys]; NSEnumerator *enumerator = [allKeys objectEnumerator]; NSValue *key; while (nil != (key = [enumerator nextObject])) { TLID *oldValue = [tokenDict objectForKey:key]; TLAtom *atom = [key pointerValue]; [atom setValue:oldValue]; } }