865 lines
12 KiB
Objective-C
865 lines
12 KiB
Objective-C
|
|
#import "SchemeTypes.h"
|
|
|
|
@implementation NSMutableArray (Wrap)
|
|
|
|
- (void)addObjWRP:(id)anObject
|
|
{
|
|
[anObject retain];
|
|
[self addObject:anObject];
|
|
return;
|
|
}
|
|
|
|
- (void)replaceObjWRPAtIndex:(unsigned)index withObject:(id)anObject
|
|
{
|
|
[anObject retain];
|
|
[self replaceObjectAtIndex:index withObject:anObject];
|
|
return;
|
|
}
|
|
|
|
- (void)prependObjWRP:(id)anObject
|
|
{
|
|
[anObject retain];
|
|
[self insertObject:anObject atIndex:0];
|
|
return;
|
|
}
|
|
|
|
@end
|
|
|
|
@implementation NSMutableDictionary (Wrap)
|
|
|
|
- (void)setObjWRP:(id)anObject forKey:(id)aKey
|
|
{
|
|
[anObject retain];
|
|
[self setObject:anObject forKey:aKey];
|
|
return;
|
|
}
|
|
|
|
@end
|
|
|
|
@implementation SCMType
|
|
|
|
static int allocatedAfterGC = 0;
|
|
static NSMutableSet *scmobjects = nil;
|
|
static NSMutableSet *scmmarkables = nil;
|
|
static int currentMark = -1;
|
|
static int totalAllocated = 0;
|
|
|
|
|
|
+ (int)allocatedAfterGC
|
|
{
|
|
return allocatedAfterGC;
|
|
}
|
|
|
|
+ (int)totalAllocated
|
|
{
|
|
return totalAllocated;
|
|
}
|
|
|
|
+ (int)nextMark
|
|
{
|
|
currentMark++;
|
|
return currentMark;
|
|
}
|
|
|
|
+ addToMarkables:(id)item
|
|
{
|
|
NSValue *entry =
|
|
[NSValue valueWithBytes:&item objCType:@encode(id)];
|
|
|
|
if(scmmarkables==nil){
|
|
scmmarkables = [NSMutableSet setWithCapacity:1];
|
|
[scmmarkables retain];
|
|
}
|
|
|
|
[scmmarkables addObject:entry];
|
|
|
|
return self;
|
|
}
|
|
|
|
+ removeFromMarkables:(id)item
|
|
{
|
|
NSValue *entry =
|
|
[NSValue valueWithBytes:&item objCType:@encode(id)];
|
|
|
|
if(scmmarkables==nil){
|
|
scmmarkables = [NSMutableSet setWithCapacity:1];
|
|
[scmmarkables retain];
|
|
}
|
|
|
|
[scmmarkables removeObject:entry];
|
|
|
|
return self;
|
|
}
|
|
|
|
+ currentMarkForMarkables
|
|
{
|
|
NSEnumerator *enumerator;
|
|
NSValue *curval;
|
|
id markable;
|
|
|
|
if(scmmarkables==nil){
|
|
scmmarkables = [NSMutableSet setWithCapacity:1];
|
|
}
|
|
enumerator = [scmmarkables objectEnumerator];
|
|
|
|
while((curval = (NSValue *)[enumerator nextObject])!=nil){
|
|
[curval getValue:&markable];
|
|
if(MARKABLE(markable)){
|
|
[markable setMarkToCurrent];
|
|
}
|
|
}
|
|
|
|
return self;
|
|
}
|
|
|
|
+ runGC
|
|
{
|
|
NSMutableSet *nextobjects = [NSMutableSet setWithCapacity:1];
|
|
NSEnumerator *enumerator = [scmobjects objectEnumerator];
|
|
// NSValue *curval;
|
|
SCMType *current;
|
|
|
|
while((current = (SCMType *)[enumerator nextObject])!=nil){
|
|
// [curval getValue:¤t];
|
|
if([current mark]!=currentMark){
|
|
[current free];
|
|
}
|
|
else{
|
|
[nextobjects addObject:current]; // curval];
|
|
}
|
|
}
|
|
|
|
[scmobjects release];
|
|
|
|
scmobjects = nextobjects;
|
|
[scmobjects retain];
|
|
|
|
allocatedAfterGC = totalAllocated = [scmobjects count];
|
|
}
|
|
|
|
+ alloc
|
|
{
|
|
id inst = [super alloc];
|
|
/* NSValue *entry =
|
|
[NSValue valueWithBytes:&inst objCType:@encode(id)]; */
|
|
|
|
if(scmobjects==nil){
|
|
scmobjects = [NSMutableSet setWithCapacity:1];
|
|
[scmobjects retain];
|
|
}
|
|
|
|
[scmobjects addObject:inst]; // entry];
|
|
totalAllocated++;
|
|
|
|
return [inst setMark:-1];
|
|
}
|
|
|
|
|
|
- (int)mark
|
|
{
|
|
return mark;
|
|
}
|
|
|
|
- setMark:(int)newMark
|
|
{
|
|
mark = newMark;
|
|
return self;
|
|
}
|
|
|
|
- setMarkToCurrent
|
|
{
|
|
mark = currentMark;
|
|
return self;
|
|
}
|
|
|
|
|
|
- (void)free
|
|
{
|
|
int count = [self retainCount];
|
|
|
|
while(count>2){ // count>1 (leave one release for the set)
|
|
count--;
|
|
[self release];
|
|
}
|
|
|
|
[super release];
|
|
}
|
|
@end
|
|
|
|
@implementation Pair
|
|
|
|
+ (int)length:(Pair *)list
|
|
{
|
|
return (list==(Pair *)[NSNull null] ?
|
|
0 : 1+[self length:[list cdr]]);
|
|
}
|
|
|
|
+ newCar:(id)carval Cdr:(id)cdrval
|
|
{
|
|
return [[super alloc] initCar:carval Cdr:cdrval];
|
|
}
|
|
|
|
- initCar:(id)carval Cdr:(id)cdrval
|
|
{
|
|
car = carval; [car retain];
|
|
cdr = cdrval; [cdr retain];
|
|
|
|
return self;
|
|
}
|
|
|
|
|
|
- car
|
|
{
|
|
return car;
|
|
}
|
|
|
|
- cdr
|
|
{
|
|
return cdr;
|
|
}
|
|
|
|
- setcar:(id)carval
|
|
{
|
|
car = carval; [car retain];
|
|
return self;
|
|
}
|
|
|
|
- setcdr:(id)cdrval
|
|
{
|
|
cdr = cdrval; [cdr retain];
|
|
return self;
|
|
}
|
|
|
|
- setMarkToCurrent
|
|
{
|
|
if([self mark]==currentMark){
|
|
return;
|
|
}
|
|
|
|
[super setMarkToCurrent];
|
|
if(MARKABLE(car)){
|
|
[car setMarkToCurrent];
|
|
}
|
|
if(MARKABLE(cdr)){
|
|
[cdr setMarkToCurrent];
|
|
}
|
|
|
|
return self;
|
|
}
|
|
|
|
|
|
@end
|
|
|
|
@implementation Vector
|
|
|
|
+ newFromList:(Pair *)list
|
|
{
|
|
return [[super alloc]
|
|
initWithList:list];
|
|
}
|
|
|
|
+ newWithItem:(id)item count:(int)cval
|
|
{
|
|
return [[super alloc]
|
|
initWithItem:item count:cval];
|
|
}
|
|
|
|
|
|
- initWithList:(Pair *)list
|
|
{
|
|
Pair *current = list;
|
|
int index = 0, length = [Pair length:list];
|
|
|
|
count = length;
|
|
data = NSZoneMalloc([self zone], length*sizeof(id));
|
|
|
|
while(isPair(current)){
|
|
data[index] = [current car]; [data[index++] retain];
|
|
current = [current cdr];
|
|
}
|
|
|
|
return self;
|
|
}
|
|
|
|
- initWithItem:(id)item count:(int)cval
|
|
{
|
|
count = cval;
|
|
data = NSZoneMalloc([self zone], cval*sizeof(id));
|
|
|
|
while(cval--){
|
|
data[cval] = item; [item retain];
|
|
}
|
|
|
|
return self;
|
|
}
|
|
|
|
|
|
- (id *)entries
|
|
{
|
|
return data;
|
|
}
|
|
|
|
- (unsigned)count
|
|
{
|
|
return count;
|
|
}
|
|
|
|
- setMarkToCurrent
|
|
{
|
|
int index;
|
|
|
|
if([self mark]==currentMark){
|
|
return;
|
|
}
|
|
|
|
[super setMarkToCurrent];
|
|
|
|
for(index=0; index<count; index++){
|
|
id obj = data[index];
|
|
if(MARKABLE(obj)){
|
|
[obj setMarkToCurrent];
|
|
}
|
|
}
|
|
|
|
return self;
|
|
}
|
|
|
|
|
|
- (void)free
|
|
{
|
|
NSZoneFree([self zone], data);
|
|
[super free];
|
|
}
|
|
|
|
@end
|
|
|
|
@implementation Closure
|
|
|
|
+ newArgs:(id)argsval Body:(id)codes Env:(id)envval
|
|
{
|
|
return [[super alloc]
|
|
initArgs:argsval Body:codes Env:envval];
|
|
}
|
|
|
|
- initArgs:(id)argsval Body:(id)codes Env:(id)envval
|
|
{
|
|
[super init];
|
|
args = argsval; [args retain];
|
|
body = codes; [body retain];
|
|
env = envval; [env retain];
|
|
|
|
return self;
|
|
}
|
|
|
|
- args
|
|
{
|
|
return args;
|
|
}
|
|
|
|
- body
|
|
{
|
|
return body;
|
|
}
|
|
|
|
- env
|
|
{
|
|
return env;
|
|
}
|
|
|
|
- setMarkToCurrent
|
|
{
|
|
if([self mark]==currentMark){
|
|
return;
|
|
}
|
|
|
|
[super setMarkToCurrent];
|
|
if(MARKABLE(args)){
|
|
[args setMarkToCurrent];
|
|
}
|
|
if(MARKABLE(body)){
|
|
[body setMarkToCurrent];
|
|
}
|
|
if(MARKABLE(env)){
|
|
[env setMarkToCurrent];
|
|
}
|
|
|
|
return self;
|
|
}
|
|
|
|
@end
|
|
|
|
@implementation Thunk
|
|
|
|
+ newArgp:(int)argpval Envp:(int)envpval Codep:(int)codepval
|
|
{
|
|
return [[super alloc]
|
|
initArgp:argpval Envp:envpval Codep:codepval];
|
|
}
|
|
|
|
- initArgp:(int)argpval Envp:(int)envpval Codep:(int)codepval
|
|
{
|
|
argp = argpval;
|
|
envp = envpval;
|
|
codep = codepval;
|
|
return self;
|
|
}
|
|
|
|
- (int)argp
|
|
{
|
|
return argp;
|
|
}
|
|
|
|
- setArgp:(int)argpval
|
|
{
|
|
argp = argpval;
|
|
return self;
|
|
}
|
|
|
|
- (int)envp
|
|
{
|
|
return envp;
|
|
}
|
|
|
|
- setEnvp:(int)envpval
|
|
{
|
|
envp = envpval;
|
|
return self;
|
|
}
|
|
|
|
- (int)codep
|
|
{
|
|
return codep;
|
|
}
|
|
|
|
- setCodep:(int)codepval
|
|
{
|
|
codep = codepval;
|
|
return self;
|
|
}
|
|
|
|
@end
|
|
|
|
|
|
|
|
@implementation Environment
|
|
|
|
+ newParent:(Environment *)par Data:(NSMutableDictionary *)entries
|
|
{
|
|
return [[super alloc]
|
|
initParent:par Data:entries];
|
|
}
|
|
|
|
- initParent:(Environment *)par Data:(NSMutableDictionary *)entries
|
|
{
|
|
[super init];
|
|
|
|
parent = par;
|
|
[parent retain];
|
|
|
|
data = entries; // [entries mutableCopy];
|
|
[data retain];
|
|
|
|
return self;
|
|
}
|
|
|
|
- (int)chainLength
|
|
{
|
|
return (parent==nil ? 1 : 1+[parent chainLength]);
|
|
}
|
|
|
|
- (NSMutableDictionary *)lookup:(NSString *)sym
|
|
{
|
|
if([data objectForKey:sym]!=nil){
|
|
return data;
|
|
}
|
|
|
|
return (parent==nil ? nil : [parent lookup:sym]);
|
|
}
|
|
|
|
- (Environment *)parent
|
|
{
|
|
return parent;
|
|
}
|
|
|
|
- (NSMutableDictionary *)data
|
|
{
|
|
return data;
|
|
}
|
|
|
|
- setMarkToCurrent
|
|
{
|
|
NSEnumerator *enumerator = [data objectEnumerator];
|
|
id item;
|
|
|
|
if([self mark]==currentMark){
|
|
return;
|
|
}
|
|
|
|
[super setMarkToCurrent];
|
|
while((item = [enumerator nextObject])!=nil){
|
|
if(MARKABLE(item)){
|
|
[item setMarkToCurrent];
|
|
}
|
|
}
|
|
|
|
if(MARKABLE(parent)){
|
|
[parent setMarkToCurrent];
|
|
}
|
|
|
|
return self;
|
|
}
|
|
|
|
#define GSI_MAP_NOCLEAN 1
|
|
|
|
#include <base/GSIMap.h>
|
|
|
|
@interface GSMutableDictionary : NSDictionary
|
|
{
|
|
@public
|
|
GSIMapTable_t map;
|
|
}
|
|
@end
|
|
|
|
typedef struct {
|
|
@defs(GSMutableDictionary)
|
|
} *GSMDictPtr;
|
|
|
|
- (void)free
|
|
{
|
|
GSIMapEmptyMap(&(((GSMDictPtr)data)->map));
|
|
while([data retainCount]>1){
|
|
[data release];
|
|
}
|
|
|
|
[super free];
|
|
}
|
|
|
|
@end
|
|
|
|
|
|
@implementation Triple
|
|
|
|
+ newTag:(int)tagval
|
|
{
|
|
return [[super alloc]
|
|
initTag:tagval
|
|
Arg1:nil Arg2:nil Arg3:nil];
|
|
}
|
|
|
|
+ newTag:(int)tagval IntArg1:(int)arg1;
|
|
{
|
|
NSNumber *num = [NSNumber numberWithInt:arg1];
|
|
return [[super alloc]
|
|
initTag:tagval
|
|
Arg1:num Arg2:nil Arg3:nil];
|
|
}
|
|
|
|
+ newTag:(int)tagval Arg1:(id)arg1
|
|
{
|
|
return [[super alloc]
|
|
initTag:tagval
|
|
Arg1:arg1 Arg2:nil Arg3:nil];
|
|
}
|
|
|
|
+ newTag:(int)tagval Arg1:(id)arg1 Arg2:(id)arg2
|
|
{
|
|
return [[super alloc]
|
|
initTag:tagval
|
|
Arg1:arg1 Arg2:arg2 Arg3:nil];
|
|
}
|
|
|
|
+ newTag:(int)tagval Arg1:(id)arg1 Arg2:(id)arg2 Arg3:(id)arg3
|
|
{
|
|
return [[super alloc]
|
|
initTag:tagval
|
|
Arg1:arg1 Arg2:arg2 Arg3:arg3];
|
|
}
|
|
|
|
|
|
- initTag:(int)tagval Arg1:(id)arg1 Arg2:(id)arg2 Arg3:(id)arg3
|
|
{
|
|
tag = tagval;
|
|
|
|
items[0] = arg1; [arg1 retain];
|
|
items[1] = arg2; [arg2 retain];
|
|
items[2] = arg3; [arg3 retain];
|
|
|
|
return self;
|
|
}
|
|
|
|
- (int)tag
|
|
{
|
|
return tag;
|
|
}
|
|
|
|
- (int)intarg1
|
|
{
|
|
return [items[0] intValue];
|
|
}
|
|
|
|
- setIntArg1:(int)val
|
|
{
|
|
items[0] = [NSNumber numberWithInt:val];
|
|
return self;
|
|
}
|
|
|
|
- arg1
|
|
{
|
|
return items[0];
|
|
}
|
|
|
|
- arg2
|
|
{
|
|
return items[1];
|
|
}
|
|
|
|
- arg3
|
|
{
|
|
return items[2];
|
|
}
|
|
|
|
- setMarkToCurrent
|
|
{
|
|
if([self mark]==currentMark){
|
|
return;
|
|
}
|
|
|
|
[super setMarkToCurrent];
|
|
if(MARKABLE(items[0])){
|
|
[items[0] setMarkToCurrent];
|
|
}
|
|
if(MARKABLE(items[1])){
|
|
[items[1] setMarkToCurrent];
|
|
}
|
|
if(MARKABLE(items[2])){
|
|
[items[2] setMarkToCurrent];
|
|
}
|
|
|
|
return self;
|
|
}
|
|
|
|
@end
|
|
|
|
@implementation Boolean
|
|
|
|
- initSCMBoolean:(BOOL)val
|
|
{
|
|
[super init];
|
|
value = val;
|
|
return self;
|
|
}
|
|
|
|
- (BOOL)boolVal
|
|
{
|
|
return value;
|
|
}
|
|
|
|
@end
|
|
|
|
@implementation Char
|
|
|
|
- initSCMChar:(char)val
|
|
{
|
|
[super init];
|
|
value = val;
|
|
return self;
|
|
}
|
|
|
|
- (char)charVal
|
|
{
|
|
return value;
|
|
}
|
|
|
|
@end
|
|
|
|
@implementation Int
|
|
|
|
- initSCMInt:(long int)val
|
|
{
|
|
[super init];
|
|
value = val;
|
|
return self;
|
|
}
|
|
|
|
- (long int)intVal
|
|
{
|
|
return value;
|
|
}
|
|
|
|
- (double)doubleVal
|
|
{
|
|
return (double)value;
|
|
}
|
|
|
|
@end
|
|
|
|
@implementation Double
|
|
|
|
- initSCMDouble:(double)val
|
|
{
|
|
[super init];
|
|
value = val;
|
|
return self;
|
|
}
|
|
|
|
- (double)doubleVal
|
|
{
|
|
return value;
|
|
}
|
|
|
|
@end
|
|
|
|
@implementation Symbol
|
|
|
|
- initSCMSymbol:(char *)val
|
|
{
|
|
[super init];
|
|
value = [NSString stringWithCString:val];
|
|
[value retain];
|
|
return self;
|
|
}
|
|
|
|
- (NSString *)symVal
|
|
{
|
|
return value;
|
|
}
|
|
|
|
- (void)free
|
|
{
|
|
[value release];
|
|
[super free];
|
|
}
|
|
|
|
@end
|
|
|
|
@implementation String
|
|
|
|
- initSCMString:(char *)val
|
|
{
|
|
char *cp, *buf, *from, *to;
|
|
int len = strlen(val);
|
|
|
|
[super init];
|
|
|
|
cp = strdup(val); from = cp+1; cp[len-1] = 0;
|
|
buf = to = malloc(len-1);
|
|
|
|
while(*from){
|
|
if(*from == '\\'){
|
|
from++;
|
|
}
|
|
*to++ = *from++;
|
|
}
|
|
*to = 0;
|
|
|
|
value = [NSString stringWithCString:buf];
|
|
[value retain];
|
|
|
|
free(buf);
|
|
free(cp);
|
|
|
|
return self;
|
|
}
|
|
|
|
- (NSString *)strVal
|
|
{
|
|
return value;
|
|
}
|
|
|
|
- (void)free
|
|
{
|
|
[value release];
|
|
[super free];
|
|
}
|
|
|
|
@end
|
|
|
|
@implementation ByteCodes
|
|
|
|
+ new
|
|
{
|
|
id inst = [super alloc];
|
|
[inst initWithMutableArray:[NSMutableArray arrayWithCapacity:1]];
|
|
return inst;
|
|
}
|
|
|
|
- initWithMutableArray:(NSMutableArray *)theData
|
|
{
|
|
[super init];
|
|
data = theData;
|
|
[data retain];
|
|
|
|
return self;
|
|
}
|
|
|
|
- prependTriple:(Triple *)theTriple
|
|
{
|
|
[data prependObjWRP:theTriple];
|
|
return self;
|
|
}
|
|
|
|
- addTriple:(Triple *)theTriple
|
|
{
|
|
[data addObjWRP:theTriple];
|
|
return self;
|
|
}
|
|
|
|
- appendByteCodes:(ByteCodes *)codes
|
|
{
|
|
[data addObjectsFromArray:[codes codes]];
|
|
return self;
|
|
}
|
|
|
|
|
|
- (NSMutableArray *)codes
|
|
{
|
|
return data;
|
|
}
|
|
|
|
- setMarkToCurrent
|
|
{
|
|
int index, count = [data count];
|
|
|
|
if([self mark]==currentMark){
|
|
return;
|
|
}
|
|
|
|
[super setMarkToCurrent];
|
|
|
|
for(index=0; index<count; index++){
|
|
id obj = [data objectAtIndex:index];
|
|
if(MARKABLE(obj)){
|
|
[obj setMarkToCurrent];
|
|
}
|
|
}
|
|
|
|
return self;
|
|
}
|
|
|
|
@interface GSMutableArray : NSMutableArray
|
|
{
|
|
@public
|
|
id *_contents_array;
|
|
unsigned _count;
|
|
unsigned _capacity;
|
|
int _grow_factor;
|
|
}
|
|
@end
|
|
|
|
typedef struct {
|
|
@defs(GSMutableArray)
|
|
} *GSMArrayPtr;
|
|
|
|
- (void)free
|
|
{
|
|
((GSMArrayPtr)data)->_count = 0;
|
|
while([data retainCount]>1){
|
|
[data release];
|
|
}
|
|
|
|
[super free];
|
|
}
|
|
|
|
@end
|