281 lines
6.2 KiB
Objective-C
281 lines
6.2 KiB
Objective-C
#import "BrainFuck.h"
|
||
|
||
// Makes an NSArray work as an NSTableDataSource.
|
||
@implementation NSMutableArray (NSTableDataSource)
|
||
|
||
// just returns the item for the right row
|
||
- (id)tableView:(NSTableView *) aTableView
|
||
objectValueForTableColumn:(NSTableColumn *) aTableColumn
|
||
row:(int) rowIndex
|
||
{
|
||
NSString *returnValue;
|
||
|
||
if ([[aTableColumn identifier] isEqualToString:@"1"])
|
||
returnValue = [[NSNumber numberWithInt:rowIndex] stringValue];
|
||
|
||
if ([[aTableColumn identifier] isEqualToString:@"2"])
|
||
returnValue = [self objectAtIndex:rowIndex];
|
||
|
||
if ([[aTableColumn identifier] isEqualToString:@"3"])
|
||
{
|
||
NSNumber *myVal = [self objectAtIndex:rowIndex];
|
||
unichar myChar = [myVal intValue];
|
||
NSString *myStr = [NSString stringWithCharacters: &myChar length:1];
|
||
returnValue = myStr;
|
||
}
|
||
|
||
return returnValue;
|
||
}
|
||
|
||
// just returns the number of items we have.
|
||
- (int)numberOfRowsInTableView:(NSTableView *)aTableView
|
||
{
|
||
return [self count];
|
||
}
|
||
@end
|
||
|
||
@implementation BrainFuck
|
||
|
||
/*
|
||
Esta fun<75>‹o Ž chamada no arranque do programa
|
||
*/
|
||
- (void)awakeFromNib
|
||
{
|
||
myMemory = [[NSMutableArray alloc] initWithCapacity:32768];
|
||
|
||
// Inicializa o NSMutableArray com NSNumbers a 0
|
||
int i;
|
||
for(i=0; i < 32768; i++)
|
||
{
|
||
[myMemory addObject:[NSNumber numberWithInt:0]];
|
||
}
|
||
|
||
// Liga o myMemory ao memoryDisplay
|
||
[memoryDisplay setDataSource: myMemory];
|
||
|
||
[stepoutButton setEnabled: NO];
|
||
}
|
||
|
||
/*
|
||
Mete o conteudo da memoria todo a 0
|
||
*/
|
||
- (void)limpaMemoria
|
||
{
|
||
int i;
|
||
for(i=0; i < 32768; i++)
|
||
{
|
||
[myMemory replaceObjectAtIndex:i withObject:
|
||
[NSNumber numberWithInt:0]];
|
||
}
|
||
[memoryDisplay reloadData];
|
||
|
||
memoryPosition = 0;
|
||
}
|
||
|
||
|
||
- (IBAction)run:(id)sender
|
||
{
|
||
[self limpaMemoria];
|
||
|
||
programPosition = 1;
|
||
int i;
|
||
|
||
// Cria uma NSString com o conteudo da NSTextView de Input
|
||
NSString *myInput = [[inputCode textStorage] string];
|
||
// Copia o codigo para um array de ints (myCode)
|
||
|
||
// TODO: Meter isto a correr directamente da NSTextView ou do NSString
|
||
// TODO: ou ent‹o ignorar logo tudo non-bf aqui
|
||
for(i = 0; i < [myInput length]; i++) {
|
||
myCode[programPosition] = [myInput characterAtIndex:i];
|
||
programPosition++;
|
||
}
|
||
|
||
int programLen = programPosition; // "tamanho" do programa
|
||
|
||
for (programPosition = 0; programPosition < programLen; programPosition++)
|
||
{
|
||
[self doStep];
|
||
}
|
||
|
||
}
|
||
|
||
- (IBAction)singleStep:(id)sender
|
||
{
|
||
|
||
if (isRunning == NO)
|
||
{
|
||
isRunning = YES;
|
||
[runButton setEnabled: NO];
|
||
[inputCode setEditable: NO];
|
||
|
||
[myDrawer open];
|
||
|
||
[self limpaMemoria];
|
||
|
||
[memoryDisplay selectRow: memoryPosition byExtendingSelection: NO];
|
||
[memoryDisplay reloadData];
|
||
|
||
programPosition = 0;
|
||
|
||
NSString *myInput = [[inputCode textStorage] string];
|
||
int i;
|
||
for(i = 0; i < [myInput length]; i++) {
|
||
myCode[programPosition] = [myInput characterAtIndex:i];
|
||
programPosition++;
|
||
}
|
||
codeLength = programPosition;
|
||
programPosition = -1;
|
||
} else {
|
||
if (programPosition >= codeLength)
|
||
{
|
||
isRunning = NO;
|
||
[runButton setEnabled: YES];
|
||
[inputCode setEditable: YES];
|
||
}
|
||
|
||
if (inCycle == YES)
|
||
{
|
||
[stepoutButton setEnabled: YES];
|
||
} else {
|
||
[stepoutButton setEnabled: NO];
|
||
}
|
||
}
|
||
|
||
if (isRunning == YES)
|
||
{
|
||
[self doStep];
|
||
programPosition++;
|
||
|
||
while([self isBrainFuckCode: myCode[programPosition]] == FALSE)
|
||
{
|
||
programPosition++;
|
||
}
|
||
|
||
NSRange myRange = { programPosition, 1 };
|
||
[inputCode setSelectedRange: myRange];
|
||
}
|
||
|
||
}
|
||
|
||
- (BOOL)isBrainFuckCode:(char)c
|
||
{
|
||
char valid[8] = "><+-.,[]";
|
||
int i = 0;
|
||
for (i = 0; i <= 8; i++)
|
||
{
|
||
if (c == valid[i])
|
||
{
|
||
//NSLog(@"Valid BF code: %c",c);
|
||
return TRUE;
|
||
}
|
||
}
|
||
|
||
//NSLog(@"Not BF code: %c",c);
|
||
|
||
return FALSE;
|
||
}
|
||
|
||
- (IBAction)stepOut:(id)sender
|
||
{
|
||
|
||
}
|
||
|
||
|
||
- (void)doStep
|
||
{
|
||
// Todas estas variaveis s‹o para conseguir escrever em ASCII
|
||
// o valor da memoria em memoryPosition - BLEH!!!
|
||
|
||
// Apanha o valor da memoria em memoryPosition
|
||
NSNumber *memValue = [myMemory objectAtIndex:memoryPosition];
|
||
// Passa o valor para um unichar
|
||
unichar memChar = [memValue intValue];
|
||
|
||
// Variaveis temporarias para escrever na NSTextView
|
||
NSString *memCharStr;
|
||
|
||
switch(myCode[programPosition])
|
||
{
|
||
/* Adiciona um oo valor da memoria em mpointer */
|
||
case '+':
|
||
[myMemory replaceObjectAtIndex:memoryPosition withObject:
|
||
[NSNumber numberWithInt:[memValue intValue]+1]];
|
||
break;
|
||
/* Subtrai um ao valor da memoria em mpointer */
|
||
case '-':
|
||
[myMemory replaceObjectAtIndex:memoryPosition withObject:
|
||
[NSNumber numberWithInt:[memValue intValue]-1]];
|
||
break;
|
||
/* Incrementa mpointer */
|
||
case '>':
|
||
memoryPosition++;
|
||
break;
|
||
/* Subtrai mpointer */
|
||
case '<':
|
||
memoryPosition--;
|
||
break;
|
||
/* Imprime o valor na memoria em mpointer */
|
||
case '.':
|
||
// Mete a NSString com o valor do unichar c
|
||
memCharStr = [NSString stringWithCharacters: &memChar length:1];
|
||
[[outputText textStorage]
|
||
replaceCharactersInRange:NSMakeRange([[outputText textStorage] length],
|
||
0) withString:memCharStr];
|
||
[outputText scrollRangeToVisible:NSMakeRange([[outputText textStorage]
|
||
length], 0)];
|
||
break;
|
||
/* Le o valor e guarda-o na posicao de memoria actual */
|
||
case ',':
|
||
// TODO: Ainda n‹o est‡ implementado
|
||
break;
|
||
/* Start loop */
|
||
case '[':
|
||
if ([memValue intValue] == 0)
|
||
{
|
||
/* Find matching ] */
|
||
programPosition++;
|
||
/* If ciclos == 0 and myCode[programPosition] == ']' we found
|
||
* the matching brace */
|
||
while (ciclos > 0 || myCode[programPosition] != ']')
|
||
{
|
||
if (myCode[programPosition] == '[') ciclos++;
|
||
if (myCode[programPosition] == ']') ciclos--;
|
||
/* Go in right direction */
|
||
programPosition++;
|
||
inCycle = YES;
|
||
}
|
||
} else {
|
||
inCycle = YES;
|
||
}
|
||
break;
|
||
/* End loop */
|
||
case ']':
|
||
if ([memValue intValue] != 0)
|
||
{
|
||
/* Find matching [ */
|
||
programPosition--;
|
||
while (ciclos > 0 || myCode[programPosition] != '[')
|
||
{
|
||
if (myCode[programPosition] == '[') ciclos--;
|
||
if (myCode[programPosition] == ']') ciclos++;
|
||
/* Go left */
|
||
programPosition--;
|
||
}
|
||
programPosition--;
|
||
} else {
|
||
inCycle = NO;
|
||
}
|
||
break;
|
||
}
|
||
|
||
// Supostamente seleciona a linha da memoria actualmente escolhida
|
||
// mas ta quieto oh preto...
|
||
[memoryDisplay selectRow: memoryPosition byExtendingSelection: NO];
|
||
// Refresh na gaja!
|
||
[memoryDisplay reloadData];
|
||
|
||
}
|
||
|
||
@end
|