gscheme/Primitive.m

2498 lines
48 KiB
Objective-C

#import "Primitive.h"
#import "VScheme.h"
#import "SchemeDelegate.h"
inline BOOL isBoolean(id item)
{
return [item isKindOfClass:[Boolean class]];
}
inline BOOL isChar(id item)
{
return [item isKindOfClass:[Char class]];
}
inline BOOL isInt(id item)
{
return [item isKindOfClass:[Int class]];
}
inline BOOL isDouble(id item)
{
return [item isKindOfClass:[Double class]];
}
inline BOOL isSymbol(id item)
{
return [item isKindOfClass:[Symbol class]];
}
inline BOOL isString(id item)
{
return [item isKindOfClass:[String class]];
}
inline BOOL isPair(id item)
{
return [item isKindOfClass:[Pair class]];
}
inline BOOL isVector(id item)
{
return [item isKindOfClass:[Vector class]];
}
inline BOOL isTriple(id item)
{
return [item isKindOfClass:[Triple class]];
}
inline BOOL isPrimitive(id item)
{
return [item isKindOfClass:[Primitive class]];
}
inline BOOL isEval(id item)
{
return [item isKindOfClass:[PRMEval class]];
}
inline BOOL isClosure(id item)
{
return [item isKindOfClass:[Closure class]];
}
inline BOOL isThunk(id item)
{
return [item isKindOfClass:[Thunk class]];
}
BOOL isFalse(id item)
{
if(item==[NSNull null]){
return YES;
}
if([item isKindOfClass:[Boolean class]]){
return ([item boolVal]==YES ? NO : YES);
}
return NO;
}
BOOL isEqual(id itema, id itemb)
{
if([itema class]!=[itemb class]){
return NO;
}
if(isChar(itema)){
return ([itema charVal]==[itemb charVal] ? YES : NO);
}
else if(isInt(itema)){
return ([itema intVal]==[itemb intVal] ? YES : NO);
}
else if(isDouble(itema)){
return ([itema doubleVal]==[itemb doubleVal] ? YES : NO);
}
else if(isBoolean(itema)){
return ([itema boolVal]==[itemb boolVal] ? YES : NO);
}
else if(isString(itema)){
return [[itema strVal] isEqual:[itemb strVal]];
}
else if(isSymbol(itema)){
return [[itema symVal] isEqual:[itemb symVal]];
}
return (itema==itemb ? YES : NO);
}
@implementation Primitive
- init
{
[super init];
value = [NSNull null];
errmsg = nil;
return self;
}
- (NUMTYPE)checkArgsNumeric:(NSMutableArray *)args offset:(int)offs
{
int pos;
NUMTYPE res = NT_INTEGERS;
for(pos=offs; pos<[args count]; pos++){
id arg = [args objectAtIndex:pos];
if(isInt(arg)==NO){
if(isDouble(arg)==NO){
return NT_OTHER;
}
res = NT_DOUBLE;
}
}
return res;
}
- (BOOL)evalVM:(id)vm Args:(NSMutableArray *)args offset:(int)offs
{
[self notImplemented: _cmd];
return NO;
}
- (NSString *)primName
{
[self notImplemented: _cmd];
return @"_not_implemented";
}
- value
{
return value;
}
- errmsg
{
if([errmsg isKindOfClass:[NSConstantString class]]==NO){
[errmsg autorelease];
}
return errmsg;
}
@end
@implementation PRMVectorPred
- (NSString *)primName
{
return @"vector?";
}
- (BOOL)evalVM:(id)vm Args:(NSMutableArray *)args offset:(int)offs
{
id item;
if(offs+1!=[args count]){
errmsg = @"vector? takes one argument";
return NO;
}
item = [args objectAtIndex:offs];
value = [[Boolean alloc] initSCMBoolean:isVector(item)];
return YES;
}
@end
@implementation PRMPairPred
- (NSString *)primName
{
return @"pair?";
}
- (BOOL)evalVM:(id)vm Args:(NSMutableArray *)args offset:(int)offs
{
id item;
if(offs+1!=[args count]){
errmsg = @"pair? takes one argument";
return NO;
}
item = [args objectAtIndex:offs];
value = [[Boolean alloc] initSCMBoolean:isPair(item)];
return YES;
}
@end
@implementation PRMNullPred
- (NSString *)primName
{
return @"null?";
}
- (BOOL)evalVM:(id)vm Args:(NSMutableArray *)args offset:(int)offs
{
id item;
if(offs+1!=[args count]){
errmsg = @"null? takes one argument";
return NO;
}
item = [args objectAtIndex:offs];
value = [[Boolean alloc]
initSCMBoolean:(item==[NSNull null] ? YES : NO)];
return YES;
}
@end
@implementation PRMZeroPred
- (NSString *)primName
{
return @"zero?";
}
- (BOOL)evalVM:(id)vm Args:(NSMutableArray *)args offset:(int)offs
{
NUMTYPE nt = [self checkArgsNumeric:args offset:offs];
id item;
BOOL res = NO;
if(offs+1!=[args count]){
errmsg = @"zero? takes one argument";
return NO;
}
item = [args objectAtIndex:offs];
if(nt==NT_OTHER){
errmsg = @"Argument to zero? must be numeric";
return NO;
}
if(nt==NT_INTEGERS){
if(![item intVal]){
res = YES;
}
}
else{
if([item doubleVal]==(double)0.0){
res = YES;
}
}
value = [[Boolean alloc] initSCMBoolean:res];
return YES;
}
@end
@implementation PRMNumberPred
- (NSString *)primName
{
return @"number?";
}
- (BOOL)evalVM:(id)vm Args:(NSMutableArray *)args offset:(int)offs
{
NUMTYPE nt = [self checkArgsNumeric:args offset:offs];
id item;
BOOL res = NO;
if(offs+1!=[args count]){
errmsg = @"number? takes one argument";
return NO;
}
item = [args objectAtIndex:offs];
res = (nt!=NT_OTHER ? YES : NO);
value = [[Boolean alloc] initSCMBoolean:res];
return YES;
}
@end
@implementation PRMEqPred
- (NSString *)primName
{
return @"eq?";
}
- (BOOL)evalVM:(id)vm Args:(NSMutableArray *)args offset:(int)offs
{
id itema, itemb;
BOOL res = NO;
if(offs+2!=[args count]){
errmsg = @"eq? takes two arguments";
return NO;
}
itema = [args objectAtIndex:offs];
itemb = [args objectAtIndex:offs+1];
value = [[Boolean alloc] initSCMBoolean:isEqual(itema, itemb)];
return YES;
}
@end
@implementation PRMNot
- (NSString *)primName
{
return @"not";
}
- (BOOL)evalVM:(id)vm Args:(NSMutableArray *)args offset:(int)offs
{
id item;
if(offs+1!=[args count]){
errmsg = @"not takes one argument";
return NO;
}
item = [args objectAtIndex:offs];
value = [[Boolean alloc] initSCMBoolean:isFalse(item)];
return YES;
}
@end
@implementation PRMNumEqual
- (NSString *)primName
{
return @"=";
}
- (BOOL)evalVM:(id)vm Args:(NSMutableArray *)args offset:(int)offs
{
int icur, ires = 0; double dcur, dres = 0;
int pos = offs;
NUMTYPE nt = [self checkArgsNumeric:args offset:offs];
BOOL res = YES;
if(nt==NT_OTHER){
errmsg = @"Arguments to = must be numeric";
return NO;
}
if(nt==NT_INTEGERS){
ires = [[args objectAtIndex:offs] intVal];
for(pos=offs+1; pos<[args count]; pos++){
icur = [[args objectAtIndex:pos] intVal];
if(!(ires==icur)){
res = NO;
break;
}
ires = icur;
}
}
else{
dres = [[args objectAtIndex:offs] doubleVal];
for(pos=offs+1; pos<[args count]; pos++){
dcur = [[args objectAtIndex:pos] doubleVal];
if(!(dres==dcur)){
res = NO;
break;
}
dres = dcur;
}
}
value = [[Boolean alloc] initSCMBoolean:res];
return YES;
}
@end
@implementation PRMNumLT
- (NSString *)primName
{
return @"<";
}
- (BOOL)evalVM:(id)vm Args:(NSMutableArray *)args offset:(int)offs
{
int icur, ires = 0; double dcur, dres = 0;
int pos = offs;
NUMTYPE nt = [self checkArgsNumeric:args offset:offs];
BOOL res = YES;
if(nt==NT_OTHER){
errmsg = @"Arguments to < must be numeric";
return NO;
}
if(nt==NT_INTEGERS){
ires = [[args objectAtIndex:offs] intVal];
for(pos=offs+1; pos<[args count]; pos++){
icur = [[args objectAtIndex:pos] intVal];
if(!(ires<icur)){
res = NO;
break;
}
ires = icur;
}
}
else{
dres = [[args objectAtIndex:offs] doubleVal];
for(pos=offs+1; pos<[args count]; pos++){
dcur = [[args objectAtIndex:pos] doubleVal];
if(!(dres<dcur)){
res = NO;
break;
}
dres = dcur;
}
}
value = [[Boolean alloc] initSCMBoolean:res];
return YES;
}
@end
@implementation PRMNumGT
- (NSString *)primName
{
return @">";
}
- (BOOL)evalVM:(id)vm Args:(NSMutableArray *)args offset:(int)offs
{
int icur, ires = 0; double dcur, dres = 0;
int pos = offs;
NUMTYPE nt = [self checkArgsNumeric:args offset:offs];
BOOL res = YES;
if(nt==NT_OTHER){
errmsg = @"Arguments to > must be numeric";
return NO;
}
if(nt==NT_INTEGERS){
ires = [[args objectAtIndex:offs] intVal];
for(pos=offs+1; pos<[args count]; pos++){
icur = [[args objectAtIndex:pos] intVal];
if(!(ires>icur)){
res = NO;
break;
}
ires = icur;
}
}
else{
dres = [[args objectAtIndex:offs] doubleVal];
for(pos=offs+1; pos<[args count]; pos++){
dcur = [[args objectAtIndex:pos] doubleVal];
if(!(dres>dcur)){
res = NO;
break;
}
dres = dcur;
}
}
value = [[Boolean alloc] initSCMBoolean:res];
return YES;
}
@end
@implementation PRMPlus
- (NSString *)primName
{
return @"+";
}
- (BOOL)evalVM:(id)vm Args:(NSMutableArray *)args offset:(int)offs
{
int ires = 0; double dres = 0;
int pos = offs;
NUMTYPE nt = [self checkArgsNumeric:args offset:offs];
if(nt==NT_OTHER){
errmsg = @"Arguments to + must be numeric";
return NO;
}
if(nt==NT_INTEGERS){
for(pos=offs; pos<[args count]; pos++){
ires += [[args objectAtIndex:pos] intVal];
}
value = [[Int alloc] initSCMInt:ires];
return YES;
}
for(pos=offs; pos<[args count]; pos++){
dres += [[args objectAtIndex:pos] doubleVal];
}
value = [[Double alloc] initSCMDouble:dres];
return YES;
}
@end
@implementation PRMTimes
- (NSString *)primName
{
return @"*";
}
- (BOOL)evalVM:(id)vm Args:(NSMutableArray *)args offset:(int)offs
{
int ires = 1; double dres = 1;
int pos = offs;
NUMTYPE nt = [self checkArgsNumeric:args offset:offs];
if(nt==NT_OTHER){
errmsg = @"Arguments to * must be numeric";
return NO;
}
if(nt==NT_INTEGERS){
for(pos=offs; pos<[args count]; pos++){
ires *= [[args objectAtIndex:pos] intVal];
}
value = [[Int alloc] initSCMInt:ires];
return YES;
}
for(pos=offs; pos<[args count]; pos++){
dres *= [[args objectAtIndex:pos] doubleVal];
}
value = [[Double alloc] initSCMDouble:dres];
return YES;
}
@end
@implementation PRMMinus
- (NSString *)primName
{
return @"-";
}
- (BOOL)evalVM:(id)vm Args:(NSMutableArray *)args offset:(int)offs
{
int ires = 1; double dres = 1;
int pos = offs;
NUMTYPE nt = [self checkArgsNumeric:args offset:offs];
if(offs==[args count]){
errmsg = @"- needs at least one argument";
return NO;
}
if(nt==NT_OTHER){
errmsg = @"Arguments to - must be numeric";
return NO;
}
if(nt==NT_INTEGERS){
ires = [[args objectAtIndex:offs] intVal];
if(offs+1==[args count]){
ires = -ires;
}
else{
for(pos=offs+1; pos<[args count]; pos++){
ires -= [[args objectAtIndex:pos] intVal];
}
}
value = [[Int alloc] initSCMInt:ires];
return YES;
}
dres = [[args objectAtIndex:offs] doubleVal];
if(offs+1==[args count]){
dres = -dres;
}
else{
for(pos=offs+1; pos<[args count]; pos++){
dres -= [[args objectAtIndex:pos] doubleVal];
}
}
value = [[Double alloc] initSCMDouble:dres];
return YES;
}
@end
@implementation PRMDivide
- (NSString *)primName
{
return @"/";
}
- (BOOL)evalVM:(id)vm Args:(NSMutableArray *)args offset:(int)offs
{
int ires = 1; double dres = 1;
int pos = offs;
NUMTYPE nt = [self checkArgsNumeric:args offset:offs];
if(offs==[args count]){
errmsg = @"/ needs at least one argument";
return NO;
}
if(nt==NT_OTHER){
errmsg = @"Arguments to / must be numeric";
return NO;
}
if(nt==NT_INTEGERS){
ires = [[args objectAtIndex:offs] intVal];
if(offs+1==[args count]){
if(ires!=1){
errmsg = @"no integer fractions";
return NO;
}
}
else{
for(pos=offs+1; pos<[args count]; pos++){
ires /= [[args objectAtIndex:pos] intVal];
}
}
value = [[Int alloc] initSCMInt:ires];
return YES;
}
dres = [[args objectAtIndex:offs] doubleVal];
if(offs+1==[args count]){
dres = ((double)1.0)/dres;
}
else{
for(pos=offs+1; pos<[args count]; pos++){
dres /= [[args objectAtIndex:pos] doubleVal];
}
}
value = [[Double alloc] initSCMDouble:dres];
return YES;
}
@end
@implementation PRMRandom
- (NSString *)primName
{
return @"random";
}
- (BOOL)evalVM:(id)vm Args:(NSMutableArray *)args offset:(int)offs
{
NUMTYPE nt = [self checkArgsNumeric:args offset:offs];
if(offs+1!=[args count]){
errmsg = @"random takes exactly one argument";
return NO;
}
if(nt==NT_OTHER){
errmsg = @"argument to random must be numeric";
return NO;
}
if(nt==NT_INTEGERS){
int v = [[args objectAtIndex:offs] intVal];
value = [[Int alloc] initSCMInt:(lrand48() % v)];
}
else{
double v = [[args objectAtIndex:offs] doubleVal];
value = [[Double alloc] initSCMDouble:(drand48() * v)];
}
return YES;
}
@end
@implementation PRMQuotient
- (NSString *)primName
{
return @"quotient";
}
- (BOOL)evalVM:(id)vm Args:(NSMutableArray *)args offset:(int)offs
{
NUMTYPE nt = [self checkArgsNumeric:args offset:offs];
int a, b;
if(offs+2!=[args count]){
errmsg = @"quotient takes exactly two arguments";
return NO;
}
if(nt!=NT_INTEGERS){
errmsg = @"Arguments to quotient must be integers";
return NO;
}
a = [[args objectAtIndex:offs] intVal];
b = [[args objectAtIndex:offs+1] intVal];
if(!b){
errmsg = @"divide by zero error in quotient";
return NO;
}
value = [[Int alloc] initSCMInt:(a/b)];
return YES;
}
@end
@implementation PRMRemainder
- (NSString *)primName
{
return @"remainder";
}
- (BOOL)evalVM:(id)vm Args:(NSMutableArray *)args offset:(int)offs
{
NUMTYPE nt = [self checkArgsNumeric:args offset:offs];
int a, b;
if(offs+2!=[args count]){
errmsg = @"remainder takes exactly two arguments";
return NO;
}
if(nt!=NT_INTEGERS){
errmsg = @"Arguments to remainder must be integers";
return NO;
}
a = [[args objectAtIndex:offs] intVal];
b = [[args objectAtIndex:offs+1] intVal];
if(!b){
errmsg = @"divide by zero error in remainder";
return NO;
}
value = [[Int alloc] initSCMInt:(a%b)];
return YES;
}
@end
@implementation PRMList
- (NSString *)primName
{
return @"list";
}
- (BOOL)evalVM:(id)vm Args:(NSMutableArray *)args offset:(int)offs
{
id res = [NSNull null];
int pos;
for(pos=[args count]-1; pos>=offs; pos--){
res = [Pair newCar:[args objectAtIndex:pos] Cdr:res];
}
value = res;
return YES;
}
@end
@implementation PRMCons
- (NSString *)primName
{
return @"cons";
}
- (BOOL)evalVM:(id)vm Args:(NSMutableArray *)args offset:(int)offs
{
if(offs+2!=[args count]){
errmsg = @"cons takes exactly two arguments";
return NO;
}
value = [Pair
newCar:[args objectAtIndex:offs]
Cdr:[args objectAtIndex:offs+1]];
return YES;
}
@end
@implementation PRMCar
- (NSString *)primName
{
return @"car";
}
- (BOOL)evalVM:(id)vm Args:(NSMutableArray *)args offset:(int)offs
{
id item;
if(offs+1!=[args count]){
errmsg = @"car takes exactly one argument";
return NO;
}
item = [args objectAtIndex:offs];
if(isPair(item)==NO){
errmsg = @"argument to car must be a pair";
return NO;
}
value = [item car];
return YES;
}
@end
@implementation PRMCdr
- (NSString *)primName
{
return @"cdr";
}
- (BOOL)evalVM:(id)vm Args:(NSMutableArray *)args offset:(int)offs
{
id item;
if(offs+1!=[args count]){
errmsg = @"cdr takes exactly one argument";
return NO;
}
item = [args objectAtIndex:offs];
if(isPair(item)==NO){
errmsg = @"argument to cdr must be a pair";
return NO;
}
value = [item cdr];
return YES;
}
@end
@implementation PRMSetCar
- (NSString *)primName
{
return @"set-car!";
}
- (BOOL)evalVM:(id)vm Args:(NSMutableArray *)args offset:(int)offs
{
id item;
if(offs+2!=[args count]){
errmsg = @"set-car! takes two arguments";
return NO;
}
item = [args objectAtIndex:offs];
if(isPair(item)==NO){
errmsg = @"argument to set-car! must be a pair";
return NO;
}
[item setcar:[args objectAtIndex:(offs+1)]];
value = [item car];
return YES;
}
@end
@implementation PRMSetCdr
- (NSString *)primName
{
return @"set-cdr!";
}
- (BOOL)evalVM:(id)vm Args:(NSMutableArray *)args offset:(int)offs
{
id item;
if(offs+2!=[args count]){
errmsg = @"set-cdr! takes two arguments";
return NO;
}
item = [args objectAtIndex:offs];
if(isPair(item)==NO){
errmsg = @"argument to set-cdr! must be a pair";
return NO;
}
[item setcdr:[args objectAtIndex:(offs+1)]];
value = [item cdr];
return YES;
}
@end
@implementation PRMDisplay
- (NSString *)primName
{
return @"display";
}
- (BOOL)evalVM:(id)vm Args:(NSMutableArray *)args offset:(int)offs
{
id item;
NSString *res;
if(offs+1!=[args count]){
errmsg = @"display takes one argument";
return NO;
}
item = [args objectAtIndex:offs];
if(isString(item)){
res = [NSString
stringWithFormat:@"%@", [item strVal]];
}
else if(isChar(item)){
res = [NSString
stringWithFormat:@"%c", [item charVal]];
}
else{
res = [VScheme valToString:item];
}
[vm appendToOutput:res];
value = [NSNull null];
return YES;
}
@end
@implementation PRMNewline
- (NSString *)primName
{
return @"newline";
}
- (BOOL)evalVM:(id)vm Args:(NSMutableArray *)args offset:(int)offs
{
id item;
if(offs!=[args count]){
errmsg = @"newline takes no arguments";
return NO;
}
[vm appendToOutput:@"\n"];
value = [NSNull null];
return YES;
}
@end
@implementation PRMDrawMove
- (NSString *)primName
{
return @"draw-move";
}
- (BOOL)evalVM:(id)vm Args:(NSMutableArray *)args offset:(int)offs
{
NUMTYPE nt = [self checkArgsNumeric:args offset:offs];
DrawInst inst;
if(offs+2!=[args count]){
errmsg = @"draw-move takes two arguments";
return NO;
}
if(nt==NT_OTHER){
errmsg = @"Arguments to draw-move must be numeric";
return NO;
}
inst.what = DRAW_MOVE;
inst.data.coord.x = [[args objectAtIndex:offs] doubleVal];
inst.data.coord.y = [[args objectAtIndex:offs+1] doubleVal];
[vm recordImgInst:inst];
value = [NSNull null];
return YES;
}
@end
@implementation PRMDrawLine
- (NSString *)primName
{
return @"draw-line";
}
- (BOOL)evalVM:(id)vm Args:(NSMutableArray *)args offset:(int)offs
{
NUMTYPE nt = [self checkArgsNumeric:args offset:offs];
DrawInst inst;
if(offs+2!=[args count]){
errmsg = @"draw-line takes two arguments";
return NO;
}
if(nt==NT_OTHER){
errmsg = @"Arguments to draw-line must be numeric";
return NO;
}
inst.what = DRAW_LINE;
inst.data.coord.x = [[args objectAtIndex:offs] doubleVal];
inst.data.coord.y = [[args objectAtIndex:offs+1] doubleVal];
[vm recordImgInst:inst];
value = [NSNull null];
return YES;
}
@end
@implementation PRMDrawColor
- (NSString *)primName
{
return @"draw-color";
}
- (BOOL)evalVM:(id)vm Args:(NSMutableArray *)args offset:(int)offs
{
NUMTYPE nt = [self checkArgsNumeric:args offset:offs];
DrawInst inst;
if(offs+3!=[args count]){
errmsg = @"draw-color takes three arguments";
return NO;
}
if(nt==NT_OTHER){
errmsg = @"Arguments to draw-color must be numeric";
return NO;
}
inst.what = DRAW_COLOR;
inst.data.color[0] = [[args objectAtIndex:offs] doubleVal];
inst.data.color[1] = [[args objectAtIndex:offs+1] doubleVal];
inst.data.color[2] = [[args objectAtIndex:offs+2] doubleVal];
if(inst.data.color[0]<(float)0 ||
inst.data.color[0]>(float)255){
errmsg = @"red color component out of range (0..255)";
return NO;
}
if(inst.data.color[1]<(float)0 ||
inst.data.color[1]>(float)255){
errmsg = @"green color component out of range (0..255)";
return NO;
}
if(inst.data.color[2]<(float)0 ||
inst.data.color[2]>(float)255){
errmsg = @"blue color component out of range (0..255)";
return NO;
}
inst.data.color[0]/=(float)255;
inst.data.color[1]/=(float)255;
inst.data.color[2]/=(float)255;
[vm recordImgInst:inst];
value = [NSNull null];
return YES;
}
@end
@implementation PRMDrawCircle
- (NSString *)primName
{
return @"draw-circle";
}
- (BOOL)evalVM:(id)vm Args:(NSMutableArray *)args offset:(int)offs
{
NUMTYPE nt = [self checkArgsNumeric:args offset:offs];
DrawInst inst;
if(offs+1!=[args count]){
errmsg = @"draw-circle takes one argument";
return NO;
}
if(nt==NT_OTHER){
errmsg = @"Argument to draw-circle must be numeric";
return NO;
}
inst.what = DRAW_CIRCLE;
inst.data.radius = [[args objectAtIndex:offs] doubleVal];
[vm recordImgInst:inst];
value = [NSNull null];
return YES;
}
@end
@implementation PRMFillCircle
- (NSString *)primName
{
return @"fill-circle";
}
- (BOOL)evalVM:(id)vm Args:(NSMutableArray *)args offset:(int)offs
{
NUMTYPE nt = [self checkArgsNumeric:args offset:offs];
DrawInst inst;
if(offs+1!=[args count]){
errmsg = @"fill-circle takes one argument";
return NO;
}
if(nt==NT_OTHER){
errmsg = @"Argument to fill-circle must be numeric";
return NO;
}
inst.what = FILL_CIRCLE;
inst.data.radius = [[args objectAtIndex:offs] doubleVal];
[vm recordImgInst:inst];
value = [NSNull null];
return YES;
}
@end
@implementation PRMDrawRect
- (NSString *)primName
{
return @"draw-rect";
}
- (BOOL)evalVM:(id)vm Args:(NSMutableArray *)args offset:(int)offs
{
NUMTYPE nt = [self checkArgsNumeric:args offset:offs];
DrawInst inst;
if(offs+2!=[args count]){
errmsg = @"draw-rect takes two arguments";
return NO;
}
if(nt==NT_OTHER){
errmsg = @"Arguments to draw-rect must be numeric";
return NO;
}
inst.what = DRAW_RECT;
inst.data.size =
NSMakeSize([[args objectAtIndex:offs] doubleVal],
[[args objectAtIndex:offs+1] doubleVal]);
[vm recordImgInst:inst];
value = [NSNull null];
return YES;
}
@end
@implementation PRMFillRect
- (NSString *)primName
{
return @"fill-rect";
}
- (BOOL)evalVM:(id)vm Args:(NSMutableArray *)args offset:(int)offs
{
NUMTYPE nt = [self checkArgsNumeric:args offset:offs];
DrawInst inst;
if(offs+2!=[args count]){
errmsg = @"fill-rect takes two arguments";
return NO;
}
if(nt==NT_OTHER){
errmsg = @"Argument to fill-rect must be numeric";
return NO;
}
inst.what = FILL_RECT;
inst.data.size =
NSMakeSize([[args objectAtIndex:offs] doubleVal],
[[args objectAtIndex:offs+1] doubleVal]);
[vm recordImgInst:inst];
value = [NSNull null];
return YES;
}
@end
@implementation PRMDrawFont
- (NSString *)primName
{
return @"draw-font";
}
- (BOOL)evalVM:(id)vm Args:(NSMutableArray *)args offset:(int)offs
{
DrawInst inst;
if(offs+2!=[args count]){
errmsg = @"draw-font takes two arguments";
return NO;
}
String *fontName = [args objectAtIndex:offs];
if(isString(fontName)==NO){
errmsg = @"draw-font: font name must be a string";
return NO;
}
NSString *fontNameStr = [fontName strVal];
if([[[NSFontManager sharedFontManager]
availableFonts] containsObject:fontNameStr]==NO){
errmsg =
[[NSString alloc]
initWithFormat:@"draw-font: no such font (%@)", fontNameStr];
return NO;
}
id size = [args objectAtIndex:offs+1];
if(isInt(size)==NO && isDouble(size)==NO){
errmsg = @"draw-font: size must be a number";
return NO;
}
float sizeVal = (float)[size doubleVal];
NSFont *font = [NSFont fontWithName:fontNameStr size:sizeVal];
[font retain];
inst.what = DRAW_FONT;
inst.data.font = font;
[vm recordImgInst:inst];
value = [NSNull null];
return YES;
}
@end
@implementation PRMDrawString
- (NSString *)primName
{
return @"draw-string";
}
- (BOOL)evalVM:(id)vm Args:(NSMutableArray *)args offset:(int)offs
{
DrawInst inst;
if(offs+1!=[args count]){
errmsg = @"draw-string takes one argument";
return NO;
}
String *str = [args objectAtIndex:offs];
if(isString(str)==NO){
errmsg = @"draw-string: string required";
return NO;
}
NSString *string = [NSString stringWithString:[str strVal]];
[string retain];
inst.what = DRAW_STRING;
inst.data.string = string;
[vm recordImgInst:inst];
value = [NSNull null];
return YES;
}
@end
@implementation PRMDrawShow
- (NSString *)primName
{
return @"draw-show";
}
- (BOOL)evalVM:(id)vm Args:(NSMutableArray *)args offset:(int)offs
{
if(offs!=[args count]){
errmsg = @"draw-show takes no argument";
return NO;
}
[vm produceImage];
[vm clearImage];
value = [NSNull null];
return YES;
}
@end
@implementation PRMSin
- (NSString *)primName
{
return @"sin";
}
- (BOOL)evalVM:(id)vm Args:(NSMutableArray *)args offset:(int)offs
{
NUMTYPE nt = [self checkArgsNumeric:args offset:offs];
double res;
if(offs+1!=[args count]){
errmsg = @"sin takes one argument";
return NO;
}
if(nt==NT_OTHER){
errmsg = @"Argument to sin must be numeric";
return NO;
}
res = sin([[args objectAtIndex:offs] doubleVal]);
value = [[Double alloc] initSCMDouble:res];
return YES;
}
@end
@implementation PRMCos
- (NSString *)primName
{
return @"cos";
}
- (BOOL)evalVM:(id)vm Args:(NSMutableArray *)args offset:(int)offs
{
NUMTYPE nt = [self checkArgsNumeric:args offset:offs];
double res;
if(offs+1!=[args count]){
errmsg = @"cos takes one argument";
return NO;
}
if(nt==NT_OTHER){
errmsg = @"Argument to cos must be numeric";
return NO;
}
res = cos([[args objectAtIndex:offs] doubleVal]);
value = [[Double alloc] initSCMDouble:res];
return YES;
}
@end
@implementation PRMTan
- (NSString *)primName
{
return @"tan";
}
- (BOOL)evalVM:(id)vm Args:(NSMutableArray *)args offset:(int)offs
{
NUMTYPE nt = [self checkArgsNumeric:args offset:offs];
double res;
if(offs+1!=[args count]){
errmsg = @"tan takes one argument";
return NO;
}
if(nt==NT_OTHER){
errmsg = @"Argument to tan must be numeric";
return NO;
}
res = tan([[args objectAtIndex:offs] doubleVal]);
value = [[Double alloc] initSCMDouble:res];
return YES;
}
@end
@implementation PRMExp
- (NSString *)primName
{
return @"exp";
}
- (BOOL)evalVM:(id)vm Args:(NSMutableArray *)args offset:(int)offs
{
NUMTYPE nt = [self checkArgsNumeric:args offset:offs];
double res;
if(offs+1!=[args count]){
errmsg = @"exp takes one argument";
return NO;
}
if(nt==NT_OTHER){
errmsg = @"Argument to exp must be numeric";
return NO;
}
res = exp([[args objectAtIndex:offs] doubleVal]);
value = [[Double alloc] initSCMDouble:res];
return YES;
}
@end
@implementation PRMLog
- (NSString *)primName
{
return @"log";
}
- (BOOL)evalVM:(id)vm Args:(NSMutableArray *)args offset:(int)offs
{
NUMTYPE nt = [self checkArgsNumeric:args offset:offs];
double v, res;
if(offs+1!=[args count]){
errmsg = @"log takes one argument";
return NO;
}
if(nt==NT_OTHER){
errmsg = @"Argument to log must be numeric";
return NO;
}
v = [[args objectAtIndex:offs] doubleVal];
if(v<=0.0){
errmsg = @"Argument to log must be positive";
return NO;
}
res = log(v);
value = [[Double alloc] initSCMDouble:res];
return YES;
}
@end
@implementation PRMATan
- (NSString *)primName
{
return @"atan";
}
- (BOOL)evalVM:(id)vm Args:(NSMutableArray *)args offset:(int)offs
{
NUMTYPE nt = [self checkArgsNumeric:args offset:offs];
double res, v;
if(offs+1!=[args count]){
errmsg = @"atan takes one argument";
return NO;
}
if(nt==NT_OTHER){
errmsg = @"Argument to atan must be numeric";
return NO;
}
v = [[args objectAtIndex:offs] doubleVal];
res = atan(v);
value = [[Double alloc] initSCMDouble:res];
return YES;
}
@end
@implementation PRMASin
- (NSString *)primName
{
return @"asin";
}
- (BOOL)evalVM:(id)vm Args:(NSMutableArray *)args offset:(int)offs
{
NUMTYPE nt = [self checkArgsNumeric:args offset:offs];
double res, v;
if(offs+1!=[args count]){
errmsg = @"asin takes one argument";
return NO;
}
if(nt==NT_OTHER){
errmsg = @"Argument to asin must be numeric";
return NO;
}
v = [[args objectAtIndex:offs] doubleVal];
if(v<(double)-1.0 || (double)1.0<v){
errmsg = @"Argument to asin out of range";
return NO;
}
res = asin(v);
value = [[Double alloc] initSCMDouble:res];
return YES;
}
@end
@implementation PRMACos
- (NSString *)primName
{
return @"acos";
}
- (BOOL)evalVM:(id)vm Args:(NSMutableArray *)args offset:(int)offs
{
NUMTYPE nt = [self checkArgsNumeric:args offset:offs];
double res, v;
if(offs+1!=[args count]){
errmsg = @"acos takes one argument";
return NO;
}
if(nt==NT_OTHER){
errmsg = @"Argument to acos must be numeric";
return NO;
}
v = [[args objectAtIndex:offs] doubleVal];
if(v<(double)-1.0 || (double)1.0<v){
errmsg = @"Argument to acos out of range";
return NO;
}
res = acos(v);
value = [[Double alloc] initSCMDouble:res];
return YES;
}
@end
@implementation PRMSqrt
- (NSString *)primName
{
return @"sqrt";
}
- (BOOL)evalVM:(id)vm Args:(NSMutableArray *)args offset:(int)offs
{
NUMTYPE nt = [self checkArgsNumeric:args offset:offs];
double v, res; int ires;
id item;
if(offs+1!=[args count]){
errmsg = @"sqrt takes one argument";
return NO;
}
if(nt==NT_OTHER){
errmsg = @"Argument to sqrt must be numeric";
return NO;
}
item = [args objectAtIndex:offs]; v = [item doubleVal];
if(v<0){
errmsg = @"Argument to sqrt must not be negative";
return NO;
}
res = sqrt([item doubleVal]);
ires = (int)res;
if(nt==NT_INTEGERS && ires*ires==[item intVal]){
value = [[Int alloc] initSCMInt:ires];
}
else{
value = [[Double alloc] initSCMDouble:res];
}
return YES;
}
@end
@implementation PRMMakeVector
- (NSString *)primName
{
return @"make-vector";
}
- (BOOL)evalVM:(id)vm Args:(NSMutableArray *)args offset:(int)offs
{
id filler;
id count;
int cval;
if(offs+1==[args count]){
filler = [NSNull null];
}
else if(offs+2==[args count]){
filler = [args objectAtIndex:offs+1];
}
else{
errmsg = @"make-vector takes one or two arguments";
return NO;
}
count = [args objectAtIndex:offs];
if(isInt(count)==NO){
errmsg = @"make-vector: integer required";
return NO;
}
cval = [count intVal];
if(cval<0){
errmsg = @"make-vector: non-negative integer required";
return NO;
}
value = [Vector newWithItem:filler count:cval];
return YES;
}
@end
@implementation PRMListToVector
- (NSString *)primName
{
return @"list->vector";
}
- (BOOL)evalVM:(id)vm Args:(NSMutableArray *)args offset:(int)offs
{
id list;
if(offs+1!=[args count]){
errmsg = @"list->vector takes one argument";
return NO;
}
list = [args objectAtIndex:offs];
if(isPair(list)==NO && list!=[NSNull null]){
errmsg = @"list->vector: list required";
return NO;
}
value = [Vector newFromList:list];
return YES;
}
@end
@implementation PRMVectorToList
- (NSString *)primName
{
return @"vector->list";
}
- (BOOL)evalVM:(id)vm Args:(NSMutableArray *)args offset:(int)offs
{
Vector *vect;
Pair *result;
id *data;
int index;
if(offs+1!=[args count]){
errmsg = @"vector->list takes one argument";
return NO;
}
vect = [args objectAtIndex:offs];
if(isVector(vect)==NO){
errmsg = @"vector->list: vector required";
return NO;
}
data = [vect entries];
for(index=[vect count]-1, result=(Pair *)[NSNull null];
index>=0; index--){
result =
[Pair newCar:data[index] Cdr:result];
}
value = result;
return YES;
}
@end
@implementation PRMVectorLength
- (NSString *)primName
{
return @"vector-length";
}
- (BOOL)evalVM:(id)vm Args:(NSMutableArray *)args offset:(int)offs
{
Vector *vect;
if(offs+1!=[args count]){
errmsg = @"vector-length takes one argument";
return NO;
}
vect = [args objectAtIndex:offs];
if(isVector(vect)==NO){
errmsg = @"vector-length: vector required";
return NO;
}
value = [[Int alloc] initSCMInt:[vect count]];
return YES;
}
@end
@implementation PRMVectorRef
- (NSString *)primName
{
return @"vector-ref";
}
- (BOOL)evalVM:(id)vm Args:(NSMutableArray *)args offset:(int)offs
{
id *data;
Vector *vect;
int count, index;
Int *ind;
if(offs+2!=[args count]){
errmsg = @"vector-ref takes two arguments";
return NO;
}
vect = [args objectAtIndex:offs];
if(isVector(vect)==NO){
errmsg = @"vector-ref: vector required";
return NO;
}
data = [vect entries]; count = [vect count];
ind = [args objectAtIndex:offs+1];
if(isInt(ind)==NO){
errmsg = @"vector-ref: integer required";
return NO;
}
index = [ind intVal];
if(index<0 || index>=count){
errmsg = @"vector-ref: index out of bounds";
return NO;
}
value = data[index];
return YES;
}
@end
@implementation PRMVectorSet
- (NSString *)primName
{
return @"vector-set!";
}
- (BOOL)evalVM:(id)vm Args:(NSMutableArray *)args offset:(int)offs
{
id *data;
Vector *vect;
int count, index;
Int *ind;
id obj;
if(offs+3!=[args count]){
errmsg = @"vector-set! takes three arguments";
return NO;
}
vect = [args objectAtIndex:offs];
if(isVector(vect)==NO){
errmsg = @"vector-set!: vector required";
return NO;
}
data = [vect entries]; count = [vect count];
ind = [args objectAtIndex:offs+1];
if(isInt(ind)==NO){
errmsg = @"vector-set!: integer required";
return NO;
}
index = [ind intVal];
if(index<0 || index>=count){
errmsg = @"vector-set!: index out of bounds";
return NO;
}
obj = [args objectAtIndex:offs+2];
data[index] = obj; [obj retain];
value = obj;
return YES;
}
@end
@implementation PRMVectorFill
- (NSString *)primName
{
return @"vector-fill!";
}
- (BOOL)evalVM:(id)vm Args:(NSMutableArray *)args offset:(int)offs
{
id *data;
Vector *vect;
int count, index;
id obj;
if(offs+2!=[args count]){
errmsg = @"vector-fill! takes two arguments";
return NO;
}
vect = [args objectAtIndex:offs];
if(isVector(vect)==NO){
errmsg = @"vector-fill!: vector required";
return NO;
}
data = [vect entries]; count = [vect count];
obj = [args objectAtIndex:offs+1];
for(index=0; index<count; index++){
data[index] = obj; [obj retain];
}
value = obj;
return YES;
}
@end
@implementation PRMSymToStr
- (NSString *)primName
{
return @"symbol->string";
}
- (BOOL)evalVM:(id)vm Args:(NSMutableArray *)args offset:(int)offs
{
if(offs+1!=[args count]){
errmsg = @"symbol->string takes one argument";
return NO;
}
Symbol *sym = [args objectAtIndex:offs];
if(isSymbol(sym)==NO){
errmsg = @"symbol->string: symbol required";
return NO;
}
value = [[String alloc]
initSCMString:(char *)[[sym symVal] cString]];
return YES;
}
@end
@implementation PRMStrToSym
- (NSString *)primName
{
return @"string->symbol";
}
- (BOOL)evalVM:(id)vm Args:(NSMutableArray *)args offset:(int)offs
{
if(offs+1!=[args count]){
errmsg = @"string->symbol takes one argument";
return NO;
}
String *str = [args objectAtIndex:offs];
if(isString(str)==NO){
errmsg = @"string->symbol: string required";
return NO;
}
value = [[Symbol alloc]
initSCMSymbol:(char *)[[str strVal] cString]];
return YES;
}
@end
@implementation PRMStringSize
- (NSString *)primName
{
return @"string-size";
}
- (BOOL)evalVM:(id)vm Args:(NSMutableArray *)args offset:(int)offs
{
if(offs+3!=[args count]){
errmsg = @"string-size takes three arguments";
return NO;
}
String *str = [args objectAtIndex:offs];
if(isString(str)==NO){
errmsg = @"string-size: string required";
return NO;
}
String *fontName = [args objectAtIndex:offs+1];
if(isString(fontName)==NO){
errmsg = @"string-size: font name must be a string";
return NO;
}
NSString *fontNameStr = [fontName strVal];
if([[[NSFontManager sharedFontManager]
availableFonts] containsObject:fontNameStr]==NO){
errmsg =
[[NSString alloc]
initWithFormat:@"string-size: no such font (%@)", fontNameStr];
return NO;
}
id size = [args objectAtIndex:offs+2];
if(isInt(size)==NO && isDouble(size)==NO){
errmsg = @"string-size: size must be a number";
return NO;
}
float sizeVal = (float)[size doubleVal];
NSFont *font = [NSFont fontWithName:fontNameStr size:sizeVal];
NSDictionary *attr =
[NSDictionary dictionaryWithObjectsAndKeys:font, NSFontAttributeName, nil];
NSSize result = [[str strVal] sizeWithAttributes:attr];
value =
[Pair
newCar:[[Double alloc] initSCMDouble:result.width]
Cdr:[[Double alloc] initSCMDouble:result.height]];
return YES;
}
@end
@implementation PRMStringLength
- (NSString *)primName
{
return @"string-length";
}
- (BOOL)evalVM:(id)vm Args:(NSMutableArray *)args offset:(int)offs
{
if(offs+1!=[args count]){
errmsg = @"string-length takes three arguments";
return NO;
}
String *str = [args objectAtIndex:offs];
if(isString(str)==NO){
errmsg = @"string-length: string required";
return NO;
}
value = [[Int alloc] initSCMInt:[[str strVal] length]];
return YES;
}
@end
@implementation PRMCharToInt
- (NSString *)primName
{
return @"char->integer";
}
- (BOOL)evalVM:(id)vm Args:(NSMutableArray *)args offset:(int)offs
{
if(offs+1!=[args count]){
errmsg = @"char->integer takes one argument";
return NO;
}
Char *ch = [args objectAtIndex:offs];
if(isChar(ch)==NO){
errmsg = @"char->integer: character required";
return NO;
}
value = [[Int alloc]
initSCMInt:(long int)[ch charVal]];
return YES;
}
@end
@implementation PRMIntToChar
- (NSString *)primName
{
return @"integer->char";
}
- (BOOL)evalVM:(id)vm Args:(NSMutableArray *)args offset:(int)offs
{
if(offs+1!=[args count]){
errmsg = @"integer->char takes one argument";
return NO;
}
Int *i = [args objectAtIndex:offs];
if(isInt(i)==NO){
errmsg = @"integer->char: character required";
return NO;
}
value = [[Char alloc]
initSCMChar:(char)[i intVal]];
return YES;
}
@end
@implementation PRMStringRef
- (NSString *)primName
{
return @"string-ref";
}
- (BOOL)evalVM:(id)vm Args:(NSMutableArray *)args offset:(int)offs
{
if(offs+2!=[args count]){
errmsg = @"string-ref takes two argument";
return NO;
}
String *str = [args objectAtIndex:offs];
if(isString(str)==NO){
errmsg = @"string-ref: string required";
return NO;
}
Int *i = [args objectAtIndex:offs+1];
if(isInt(i)==NO){
errmsg = @"string-ref: integer position required";
return NO;
}
int pos = [i intVal];
NSString *theStr = [str strVal];
if(pos>=[theStr length]){
errmsg = @"string-ref: index out of range";
return NO;
}
value = [[Char alloc] initSCMChar:[theStr characterAtIndex:pos]];
return YES;
}
@end
@implementation PRMListToStr
- (NSString *)primName
{
return @"list->string";
}
- (BOOL)evalVM:(id)vm Args:(NSMutableArray *)args offset:(int)offs
{
if(offs+1!=[args count]){
errmsg = @"list->string takes one argument";
return NO;
}
Pair *p = [args objectAtIndex:offs];
if(isPair(p)==NO && [NSNull null]!=(id)p){
errmsg = @"list->string: pair required";
return NO;
}
int cpos = 0, cmax = 0;
while(isPair(p)){
if(isChar([p car])==NO){
errmsg = @"list->string: character required";
return NO;
}
p = [p cdr];
cmax++;
}
char buf[cmax+1];
p = [args objectAtIndex:offs];
while(isPair(p)){
Char *ch = [p car];
buf[cpos++] = [ch charVal];
p = [p cdr];
}
buf[cpos] = 0;
value = [[String alloc] initSCMString:buf];
return YES;
}
@end
@implementation PRMStrToList
- (NSString *)primName
{
return @"string->list";
}
- (BOOL)evalVM:(id)vm Args:(NSMutableArray *)args offset:(int)offs
{
if(offs+1!=[args count]){
errmsg = @"string->list takes one argument";
return NO;
}
String *str = [args objectAtIndex:offs];
if(isString(str)==NO){
errmsg = @"string->list: string required";
return NO;
}
NSString *theStr = [str strVal];
id result = [NSNull null];
int cmax = [theStr length], cpos;
cpos = cmax-1;
while(cpos>=0){
char c = [theStr characterAtIndex:cpos];
result =
[Pair
newCar:[[Char alloc] initSCMChar:c]
Cdr:result];
cpos--;
}
value = result;
return YES;
}
@end
@implementation PRMStringAppend
- (NSString *)primName
{
return @"string-append";
}
- (BOOL)evalVM:(id)vm Args:(NSMutableArray *)args offset:(int)offs
{
NSString *result = @"";
int cpos = offs, cmax = [args count];
while(cpos<cmax){
String *str = [args objectAtIndex:cpos];
if(isString(str)==NO){
errmsg = @"string-append: string required";
return NO;
}
result = [result stringByAppendingString:[str strVal]];
cpos++;
}
value = [[String alloc] initSCMString:(char *)[result cString]];
return YES;
}
@end
@implementation PRMMakeString
- (NSString *)primName
{
return @"make-string";
}
- (BOOL)evalVM:(id)vm Args:(NSMutableArray *)args offset:(int)offs
{
if(offs+1!=[args count] && offs+2!=[args count]){
errmsg = @"make-string takes one or two arguments";
return NO;
}
Int *i = [args objectAtIndex:offs];
if(isInt(i)==NO){
errmsg = @"make-string: integer required";
return NO;
}
int pos = 0, count = [i intVal];
char fill = ' ';
if(offs+2==[args count]){
Char *ch = [args objectAtIndex:offs+1];
if(isChar(ch)==NO){
errmsg = @"make-string: character required";
return NO;
}
fill = [ch charVal];
}
char buf[count+1];
while(pos<count){
buf[pos++] = fill;
}
buf[pos] = 0;
value = [[String alloc] initSCMString:buf];
return YES;
}
@end
@implementation PRMNumberToStr
- (NSString *)primName
{
return @"number->string";
}
- (BOOL)evalVM:(id)vm Args:(NSMutableArray *)args offset:(int)offs
{
if(offs+1!=[args count] && offs+2!=[args count]){
errmsg = @"number->string takes one or two arguments";
return NO;
}
id n = [args objectAtIndex:offs];
if(isInt(n)==NO && isDouble(n)==NO){
errmsg = @"number->string: int or double required";
return NO;
}
if(isDouble(n)){
NSNumber *num = [NSNumber numberWithDouble:[n doubleVal]];
value = [[String alloc] initSCMString:(char *)[[num description] cString]];
return YES;
}
int radix = 10;
if(offs+2==[args count]){
Int *r = [args objectAtIndex:offs+1];
if(isInt(r)==NO){
errmsg = @"number->string: radix must be an integer";
return NO;
}
radix = [r intVal];
if(radix<2 || radix>36){
errmsg = @"number->string: radix must be >= 2 and <= 36";
return NO;
}
}
int number = [n intVal];
if(radix==10 || !number){
NSNumber *num = [NSNumber numberWithInt:number];
value = [[String alloc] initSCMString:(char *)[[num description] cString]];
return YES;
}
int sign = 1;
if(number<0){
sign = -1;
number = -number;
}
NSString *result = @"";
while(number>0){
int digit = number % radix;
result =
[[NSString stringWithFormat:@"%c",
(digit<10 ? '0' + digit : 'A' + digit-10)]
stringByAppendingString:result];
number /= radix;
}
if(sign==-1){
result = [NSString stringWithFormat:@"-%@", result];
}
value = [[String alloc] initSCMString:(char *)[result cString]];
return YES;
}
@end
@implementation PRMFormat
- (NSString *)primName
{
return @"format";
}
- (BOOL)evalVM:(id)vm Args:(NSMutableArray *)args offset:(int)offs
{
if(offs==[args count]){
errmsg = @"format needs at least one argument";
return NO;
}
String *fmt = [args objectAtIndex:offs++];
if(isString(fmt)==NO){
errmsg = @"format: string required";
return NO;
}
const char *fmtStr = [[fmt strVal] cString];
NSString *result = @"";
while(*fmtStr){
NSString *item;
if(fmtStr[0]=='~'){
if(fmtStr[1]){
switch(fmtStr[1]){
case 'a':
case 's':
if(offs==[args count]){
errmsg = @"format: ran out of arguments";
return NO;
}
id cur = [args objectAtIndex:offs++];
if(isString(cur)){
item = [NSString stringWithFormat:@"%@", [cur strVal]];
}
else if(isChar(cur)){
item = [NSString stringWithFormat:@"%c", [cur charVal]];
}
else{
item = [VScheme valToString:cur];
}
break;
case '%':
item = @"\n";
break;
case '~':
item = @"~";
}
fmtStr++;
}
}
else{
item = [NSString stringWithCString:fmtStr length:1];
}
result = [result stringByAppendingString:item];
fmtStr++;
}
value = [[String alloc] initSCMString:(char *)[result cString]];
return YES;
}
@end
@implementation PRMBrowseEnvironment
- (NSString *)primName
{
return @"browse-environment";
}
- (BOOL)evalVM:(id)vm Args:(NSMutableArray *)args offset:(int)offs
{
id win;
if(offs!=[args count]){
errmsg = @"browse-environment takes no arguments";
return NO;
}
win = [[EnvWindow alloc] initWithEnv:[[vm envStack] lastObject]];
[[vm delegate] envWindow:win];
value = [NSNull null];
return YES;
}
@end
@implementation PRMEval
- (NSString *)primName
{
return @"eval";
}
@end