894 lines
13 KiB
Objective-C
894 lines
13 KiB
Objective-C
|
|
#import "SchemeTypes.h"
|
|
|
|
@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(mark==currentMark){
|
|
return;
|
|
}
|
|
|
|
mark = currentMark;
|
|
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(mark==currentMark){
|
|
return;
|
|
}
|
|
|
|
mark = currentMark;
|
|
|
|
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(mark==currentMark){
|
|
return;
|
|
}
|
|
|
|
mark = currentMark;
|
|
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:(NSMapTable *)entries
|
|
{
|
|
return [[super alloc]
|
|
initParent:par Data:entries];
|
|
}
|
|
|
|
- initParent:(Environment *)par Data:(NSMapTable *)entries
|
|
{
|
|
[super init];
|
|
|
|
parent = par;
|
|
[parent retain];
|
|
|
|
data = entries; // [entries mutableCopy];
|
|
// [data retain];
|
|
|
|
return self;
|
|
}
|
|
|
|
- (int)chainLength
|
|
{
|
|
return (parent==nil ? 1 : 1+[parent chainLength]);
|
|
}
|
|
|
|
- (NSMapTable *)lookup:(NSString *)sym
|
|
{
|
|
if(NSMapGet(data, sym)!=NULL){
|
|
return data;
|
|
}
|
|
|
|
return (parent==nil ? NULL : [parent lookup:sym]);
|
|
}
|
|
|
|
- (Environment *)parent
|
|
{
|
|
return parent;
|
|
}
|
|
|
|
- (NSMapTable *)data
|
|
{
|
|
return data;
|
|
}
|
|
|
|
- setMarkToCurrent
|
|
{
|
|
NSMapEnumerator enumerator = NSEnumerateMapTable(data);
|
|
id item;
|
|
|
|
if(mark==currentMark){
|
|
return;
|
|
}
|
|
|
|
mark = currentMark;
|
|
|
|
id key, val;
|
|
while(NSNextMapEnumeratorPair
|
|
(&enumerator, (void**)&key, (void**)&val)){
|
|
if(MARKABLE(val)){
|
|
[val setMarkToCurrent];
|
|
}
|
|
}
|
|
|
|
if(MARKABLE(parent)){
|
|
[parent setMarkToCurrent];
|
|
}
|
|
|
|
return self;
|
|
}
|
|
|
|
- (void)free
|
|
{
|
|
NSFreeMapTable(data);
|
|
[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];
|
|
Int *num = [[Int alloc] initSCMInt: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;
|
|
if(arg1!=nil){
|
|
[arg1 retain];
|
|
}
|
|
|
|
items[1] = arg2;
|
|
if(arg2!=nil){
|
|
[arg2 retain];
|
|
}
|
|
|
|
items[2] = arg3;
|
|
if(arg3!=nil){
|
|
[arg3 retain];
|
|
}
|
|
|
|
return self;
|
|
}
|
|
|
|
- (int)tag
|
|
{
|
|
return tag;
|
|
}
|
|
|
|
- (int)intarg1
|
|
{
|
|
return [items[0] intVal];
|
|
}
|
|
|
|
- setIntArg1:(int)val
|
|
{
|
|
// items[0] = [NSNumber numberWithInt:val];
|
|
items[0] = [[Int alloc] initSCMInt:val];
|
|
[items[0] retain];
|
|
return self;
|
|
}
|
|
|
|
- arg1
|
|
{
|
|
return items[0];
|
|
}
|
|
|
|
- arg2
|
|
{
|
|
return items[1];
|
|
}
|
|
|
|
- arg3
|
|
{
|
|
return items[2];
|
|
}
|
|
|
|
- setMarkToCurrent
|
|
{
|
|
if(mark==currentMark){
|
|
return;
|
|
}
|
|
|
|
mark = currentMark;
|
|
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
|
|
|
|
- initSCMStringLEX:(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;
|
|
}
|
|
|
|
- initSCMString:(char *)val
|
|
{
|
|
[super init];
|
|
|
|
value = [NSString stringWithCString:val];
|
|
[value retain];
|
|
|
|
return self;
|
|
}
|
|
|
|
- (NSString *)strVal
|
|
{
|
|
return value;
|
|
}
|
|
|
|
- (void)free
|
|
{
|
|
[value release];
|
|
[super free];
|
|
}
|
|
|
|
@end
|
|
|
|
#define BASE_CAPACITY 16
|
|
|
|
@implementation ByteCodes
|
|
|
|
+ new
|
|
{
|
|
id inst = [super alloc];
|
|
[inst init];
|
|
return inst;
|
|
}
|
|
|
|
- init
|
|
{
|
|
[super init];
|
|
|
|
capacity = BASE_CAPACITY;
|
|
length = 0;
|
|
data = (id *)NSZoneMalloc(NSDefaultMallocZone(), capacity*sizeof(id));
|
|
|
|
root = NO;
|
|
source = nil;
|
|
|
|
return self;
|
|
}
|
|
|
|
- prependTriple:(Triple *)theTriple
|
|
{
|
|
if(length==capacity){
|
|
capacity *= 2;
|
|
data = (id *)NSZoneRealloc(NSDefaultMallocZone(), data, capacity*sizeof(id));
|
|
}
|
|
|
|
memmove(data+1, data, length*sizeof(id));
|
|
length++;
|
|
|
|
data[0] = theTriple;
|
|
[theTriple retain];
|
|
|
|
return self;
|
|
}
|
|
|
|
- addTriple:(Triple *)theTriple
|
|
{
|
|
if(length==capacity){
|
|
capacity *= 2;
|
|
data = (id *)NSZoneRealloc(NSDefaultMallocZone(), data, capacity*sizeof(id));
|
|
}
|
|
|
|
data[length++] = theTriple;
|
|
[theTriple retain];
|
|
|
|
return self;
|
|
}
|
|
|
|
- appendByteCodes:(ByteCodes *)codes
|
|
{
|
|
unsigned int otherLength = [codes length];
|
|
id *otherData = [codes codes];
|
|
|
|
if(length+otherLength>capacity){
|
|
while(length+otherLength>capacity){
|
|
capacity *= 2;
|
|
}
|
|
data = (id *)NSZoneRealloc(NSDefaultMallocZone(), data, capacity*sizeof(id));
|
|
}
|
|
|
|
unsigned int pos;
|
|
for(pos=0; pos<otherLength; pos++){
|
|
data[length] = otherData[pos];
|
|
[data[length] retain];
|
|
length++;
|
|
}
|
|
|
|
return self;
|
|
}
|
|
|
|
|
|
- (id *)codes
|
|
{
|
|
return data;
|
|
}
|
|
|
|
- (unsigned int)length
|
|
{
|
|
return length;
|
|
}
|
|
|
|
|
|
- setMarkToCurrent
|
|
{
|
|
if(mark==currentMark){
|
|
return;
|
|
}
|
|
|
|
mark = currentMark;
|
|
|
|
unsigned int index;
|
|
for(index=0; index<length; index++){
|
|
id obj = data[index];
|
|
if(MARKABLE(obj)){
|
|
[obj setMarkToCurrent];
|
|
}
|
|
}
|
|
|
|
if(MARKABLE(source)){
|
|
[source setMarkToCurrent];
|
|
}
|
|
|
|
return self;
|
|
}
|
|
|
|
- (BOOL)root
|
|
{
|
|
return root;
|
|
}
|
|
|
|
- setRoot:(BOOL)rflag
|
|
{
|
|
root = rflag;
|
|
return self;
|
|
}
|
|
|
|
- source
|
|
{
|
|
return source;
|
|
}
|
|
|
|
- setSource:(id)src
|
|
{
|
|
source = src;
|
|
[src retain];
|
|
return self;
|
|
}
|
|
|
|
- (void)free
|
|
{
|
|
NSZoneFree(NSDefaultMallocZone(), data);
|
|
[super free];
|
|
}
|
|
|
|
@end
|