Skip to content

Commit

Permalink
Merge branch 'master' into issue-12
Browse files Browse the repository at this point in the history
  • Loading branch information
EduardoLR10 authored Mar 12, 2024
2 parents 60d58b7 + 65a6796 commit 620899d
Showing 14 changed files with 252 additions and 38 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/build.yml
Original file line number Diff line number Diff line change
@@ -12,4 +12,4 @@ jobs:
nix_path: nixpkgs=channel:nixos-unstable
- uses: DeterminateSystems/magic-nix-cache-action@v2
- run: echo "experimental-features = nix-command flakes" >> ~/.config/nix/nix.conf
- run: nix run .#build -L
- run: nix build .#chime
3 changes: 2 additions & 1 deletion Chime/Headers/Opcode.h
Original file line number Diff line number Diff line change
@@ -39,7 +39,8 @@ typedef enum : uint64_t {
OP_PLUS_STAR = 28,
// Other
OP_NOP = 29,
OP_TOTAL = 30
OP_SYSCALL = 30,
OP_TOTAL = 31
} OPCODE;

#endif /* Opcode_h */
5 changes: 5 additions & 0 deletions Chime/Headers/Parser.h
Original file line number Diff line number Diff line change
@@ -4,6 +4,11 @@
#import <Foundation/Foundation.h>
#include <stdint.h>

#define IS_LABEL YES
#define IS_NOT_LABEL NO
#define MAX_STRING_SIZE 2147483647
#define WORD_SIZE 4

@interface Parser : NSObject

@property(retain) NSArray *program;
14 changes: 14 additions & 0 deletions Chime/Headers/Utilities.h
Original file line number Diff line number Diff line change
@@ -4,6 +4,12 @@
#include "Opcode.h"
#import <Foundation/Foundation.h>

typedef struct {
NSUInteger remainder;
NSUInteger howManyWords;
BOOL trailingWord;
} Word_Manager;

bool findInEnumerator(NSEnumerator *, id);

uint32_t from64To32(uint64_t value);
@@ -18,4 +24,12 @@ void errorMissingLoadFilePath();

void errorMissingSaveFilePath();

NSArray *padWords(NSMutableArray *words, NSUInteger desiredSize);

Word_Manager howManyWords(NSUInteger length);

NSMutableArray *packString(NSString *string);

NSString *unpackString(id startPointer, NSMutableArray *array);

#endif /* Utilities_h */
25 changes: 25 additions & 0 deletions Chime/Headers/VM+Syscalls.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#import "VM.h"
#import <Foundation/Foundation.h>

#include <stdint.h>

typedef enum : uint64_t {
SYSCALL_READ = 0,
SYSCALL_WRITE = 1,
SYSCALL_OPEN = 2,
SYSCALL_SEMGET = 64,
SYSCALL_SEMOP = 65,
SYSCALL_SEMCTL = 66,
} SYSCALL_OPCODE;

typedef enum : uint64_t {
STDIN_FILENO = 0, // File number of stdin;
STDOUT_FILENO = 1, // File number of stdout;
STDERR_FILENO = 2, // File number of stderr;
} WRITE_DEVICE_OPCODE;

@interface VM (Syscalls)

- (void)instructionSyscall;

@end
50 changes: 19 additions & 31 deletions Chime/Parser.m
Original file line number Diff line number Diff line change
@@ -2,11 +2,6 @@
#import "Headers/Opcode.h"
#import "Headers/Utilities.h"

#define IS_LABEL YES
#define IS_NOT_LABEL NO
#define MAX_STRING_SIZE 2147483647
#define WORD_SIZE 4

@implementation Parser

- (Parser *)init {
@@ -88,6 +83,21 @@ BOOL isVariableLine(NSString *line) {
}
}

NSString *pureString(NSString *string, NSUInteger physicalLinesCounter) {
NSRange firstQuotePosition = [string rangeOfString:@"\""];
if (firstQuotePosition.location == NSNotFound) {
@throw [NSException
exceptionWithName:@"Could not find beginning of String"
reason:[NSString
stringWithFormat:@"Could not find \" token to identify beginning of string in line %lu",
physicalLinesCounter]
userInfo:nil];
} else {
return [string substringFromIndex:firstQuotePosition.location];
}
}


NSString *popFirstChar(NSString *string) {
return [string substringFromIndex:1];
}
@@ -140,10 +150,11 @@ BOOL checkBothStringEnds(NSString *string) {

- (void)handleStringCase:(NSString *)line
withLineCounter:(NSUInteger *)logicalLinesCounter {
NSString *stringCandidate = tokenAt(line, 1);
if (!isChimeString(stringCandidate)) {
// TODO: We are checking the string condition twice in here and 3 lines below.
if (!isChimeString(tokenAt(line, 1))) {
return;
}
NSString *stringCandidate = pureString(line, _physicalLinesCounter);

if (!checkBothStringEnds(stringCandidate)) {
@throw [NSException
@@ -254,29 +265,6 @@ - (void)handleInstructions:(BOOL)isLabel
}
}

NSMutableArray *packString(NSString *string) {
NSMutableArray *pack = [[NSMutableArray alloc] init];
NSUInteger counter = 0;
uint32_t buffer = 0;
NSData *stringData = [string dataUsingEncoding:NSUTF8StringEncoding];
const char *bytes = [stringData bytes];
for (int i = 0; i < [stringData length]; i++) {
buffer = buffer << 8;
buffer |= (char)bytes[i];
counter++;
if (counter == WORD_SIZE) {
[pack addObject:@(buffer)];
buffer = 0;
counter = 0;
}
}
if (counter != 0) {
[pack addObject:@(buffer << (8 * (WORD_SIZE - counter)))];
}

return pack;
}

- (void)handleStringLine:(NSString *)chimeString
fill:(NSMutableArray *)bytecodes {
NSString *content = popBothEnds(chimeString);
@@ -306,7 +294,7 @@ - (void)handleLine:(NSString *)line
} else if (isAddressLine(check)) {
[self handleAddressLine:line fill:bytecodes];
} else if (isChimeString(check)) {
[self handleStringLine:check fill:bytecodes];
[self handleStringLine:(pureString(line, _physicalLinesCounter)) fill:bytecodes];
} else {
[self handleInstructions:labelInfo with:line fill:bytecodes];
}
74 changes: 74 additions & 0 deletions Chime/Utilities.m
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#import <Foundation/Foundation.h>

#include "Headers/Utilities.h"
#include "Headers/Parser.h"

bool findInEnumerator(NSEnumerator *enumerator, id target) {
bool found = false;
@@ -123,4 +124,77 @@ void errorExtraArguments(char *arg) {
}

return cmds;

NSArray *padWords(NSMutableArray *words, NSUInteger desiredSize) {
while ([words count] < desiredSize) {
[words addObject:@((uint32_t)0)];
}
return [words copy];
}

Word_Manager howManyWords(NSUInteger length) {
NSUInteger remainder = length % WORD_SIZE;
NSUInteger trailingWord = remainder ? 1 : 0;
NSUInteger howManyWords = (length / WORD_SIZE) + trailingWord;
return (Word_Manager) {
.remainder = remainder,
.trailingWord = trailingWord,
.howManyWords = howManyWords,
};
}

NSMutableArray *packString(NSString *string) {
NSMutableArray *pack = [[NSMutableArray alloc] init];
NSUInteger counter = 0;
uint32_t buffer = 0;
NSData *stringData = [string dataUsingEncoding:NSUTF8StringEncoding];
const char *bytes = [stringData bytes];
for (int i = 0; i < [stringData length]; i++) {
buffer = buffer << 8;
buffer |= (char)bytes[i];
counter++;
if (counter == WORD_SIZE) {
[pack addObject:@(buffer)];
buffer = 0;
counter = 0;
}
}
if (counter != 0) {
[pack addObject:@(buffer << (8 * (WORD_SIZE - counter)))];
}

return pack;
}

uint32_t bigEndian(uint32_t word) {
char bytes[4];
bytes[0] = word >> 24;
bytes[1] = word >> 16;
bytes[2] = word >> 8;
bytes[3] = word;

uint32_t *magic = (uint32_t*) bytes;
return *magic;
}

NSString *unpackString(id startPointer, NSMutableArray *array) {
NSUInteger counter = [startPointer integerValue];
NSUInteger length = [[array objectAtIndex:counter] integerValue];
counter++; // Jump length word;

Word_Manager wm = howManyWords(length);
NSMutableData *data = [NSMutableData dataWithLength:length];

NSUInteger byteCounter = 0;
for (int i = 0; i < wm.howManyWords; i++) {
// This is changing the endianness of the sequence of bytes in order for us to get an array of chars in the correct order
uint32_t bigEndianedChunk = bigEndian([array[i + counter] integerValue]);
char *stringChunk = (char *) &bigEndianedChunk;

NSUInteger bytesInTheWord = (i == wm.howManyWords - 1 && wm.trailingWord) ? wm.remainder : WORD_SIZE;

[data replaceBytesInRange:(NSMakeRange (byteCounter, byteCounter + bytesInTheWord)) withBytes:stringChunk];
byteCounter += WORD_SIZE;
}
return [NSString stringWithUTF8String:[data bytes]];
}
70 changes: 70 additions & 0 deletions Chime/VM+Syscalls.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
#import "Headers/Utilities.h"
#import "Headers/VM+Syscalls.h"
#import "Headers/VM.h"
#import <Foundation/Foundation.h>

#include <unistd.h>
#include <stdio.h>
#include <sys/sem.h>

@implementation VM (Syscalls)

- (void)syscallRead {
@try {
id readDeviceID = [self.dataStack pop];
id contentPointer = [self.dataStack pop];
NSUInteger pointer = [contentPointer integerValue];
NSUInteger length = [[self.memoryRAM objectAtIndex:pointer] integerValue];
pointer++;

Word_Manager wm = howManyWords(length);
char stringContent[length];
ssize_t bytesWritten = read([readDeviceID integerValue], stringContent, length);
NSUInteger upperLimit = wm.howManyWords;
NSArray *treatedInput = padWords(packString(@(stringContent)), upperLimit);

[self.memoryRAM replaceObjectsInRange:(NSMakeRange (pointer, upperLimit))
withObjectsFromArray:treatedInput];
[self.dataStack push:@(bytesWritten)];
} @catch (NSException *exception) {
@throw exception;
}
}

- (void)syscallWrite {
@try {
id writeDeviceID = [self.dataStack pop];
id contentPointer = [self.dataStack pop];

NSString *content = unpackString(contentPointer, self.memoryRAM);
const char *stringContent = [content UTF8String];

ssize_t bytesWritten = write([writeDeviceID integerValue], stringContent, strlen(stringContent));
[self.dataStack push:@(bytesWritten)];
} @catch (NSException *exception) {
@throw exception;
}
}

- (void)instructionSyscall {
@try {
id syscallOpcode = [self.dataStack pop];
if ([syscallOpcode isEqualTo:@(SYSCALL_WRITE)]) {
NSLog(@"WRITE SYSCALL");
[self syscallWrite];
} else if ([syscallOpcode isEqualTo:@(SYSCALL_READ)]) {
NSLog(@"READ SYSCALL");
[self syscallRead];
} else {
@throw [NSException
exceptionWithName:@"Unrecognized syscall opcode"
reason:[NSString stringWithFormat:
@"Could not find syscall with opcode %lu", [syscallOpcode integerValue]]
userInfo:nil];
}
} @catch (NSException *exception) {
@throw exception;
}
}

@end
8 changes: 6 additions & 2 deletions Chime/VM.m
Original file line number Diff line number Diff line change
@@ -8,6 +8,7 @@
#import "Headers/Parser.h"
#import "Headers/Utilities.h"
#import "Headers/VM+Instructions.h"
#import "Headers/VM+Syscalls.h"

#include <stdlib.h>

@@ -95,7 +96,7 @@ - (void)Evaluate {
id opcode = [self collectNextInstruction];
if ([opcode isEqualTo:@(OP_HALT)]) {
NSLog(@"HALTING");
NSLog(@"%lu", [[_dataStack peek] integerValue]);
NSLog(@"%li", [[_dataStack peek] integerValue]);
// NSLog(@"RAM: %@", _memoryRAM);
return;
} else if ([opcode isEqualTo:@(OP_PUSH_A)]) {
@@ -183,7 +184,10 @@ - (void)Evaluate {
NSLog(@"STORE R PLUS");
[self instructionOpStoreRPlus];
} else if ([opcode isEqualTo:@(OP_NOP)]) {
NSLog(@"NOP");
NSLog(@"NOP");
} else if ([opcode isEqualTo:@(OP_SYSCALL)]) {
NSLog(@"SYSCALL");
[self instructionSyscall];
} else {
NSLog(@"DEFAULT");
return;
4 changes: 2 additions & 2 deletions flake.nix
Original file line number Diff line number Diff line change
@@ -27,7 +27,7 @@
src = ./.;
installPhase = ''
mkdir -p $out/bin
${clang} -Wall -O2 -pthread -fPIC -Wunused-command-line-argument -lobjc -lgnustep-base -fobjc-runtime=gnustep-2.0 -I${gnustepBaseDev}/include -I${gnustepMake}/include -I${gnustepLibObjc}/include -L${gnustepLibObjc}/lib -L${gnustepBaseLib}/lib -I./Chime/Headers ./Chime/VM+Instructions.m ./Chime/VM.m ./Chime/Stack.m ./Chime/Utilities.m ./Chime/Parser.m ./Chime/Main.m -o $out/bin/chime'';
${clang} -Wall -O2 -pthread -fPIC -Wunused-command-line-argument -lobjc -lgnustep-base -fobjc-runtime=gnustep-2.0 -I${gnustepBaseDev}/include -I${gnustepMake}/include -I${gnustepLibObjc}/include -L${gnustepLibObjc}/lib -L${gnustepBaseLib}/lib -I./Chime/Headers ./Chime/VM+Syscalls.m ./Chime/VM+Instructions.m ./Chime/VM.m ./Chime/Stack.m ./Chime/Utilities.m ./Chime/Parser.m ./Chime/Main.m -o $out/bin/chime'';
};
});

@@ -46,7 +46,7 @@
type = "app";
program = toString (pkgs.writeShellScript "execute-program" ''
output=$(${mktemp})
${clang} -Wall -O2 -pthread -fPIC -Wunused-command-line-argument -lobjc -lgnustep-base -fobjc-runtime=gnustep-2.0 -I${gnustepBaseDev}/include -I${gnustepMake}/include -I${gnustepLibObjc}/include -L${gnustepLibObjc}/lib -L${gnustepBaseLib}/lib -I./Chime/Headers ./Chime/VM+Instructions.m ./Chime/VM.m ./Chime/Stack.m ./Chime/Utilities.m ./Chime/Parser.m ./Chime/Main.m -o $output
${clang} -Wall -O2 -pthread -fPIC -Wunused-command-line-argument -lobjc -lgnustep-base -fobjc-runtime=gnustep-2.0 -I${gnustepBaseDev}/include -I${gnustepMake}/include -I${gnustepLibObjc}/include -L${gnustepLibObjc}/lib -L${gnustepBaseLib}/lib -I./Chime/Headers ./Chime/VM+Syscalls.m ./Chime/VM+Instructions.m ./Chime/VM.m ./Chime/Stack.m ./Chime/Utilities.m ./Chime/Parser.m ./Chime/Main.m -o $output && $output/chime
'');
};

3 changes: 2 additions & 1 deletion keywords.lemos
Original file line number Diff line number Diff line change
@@ -27,4 +27,5 @@ plus
double
/2
+*
nop
nop
syscall
14 changes: 14 additions & 0 deletions samples/syscalls/read.chf
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
:main literal literal literal syscall
&readSyscallContent
*stdinDevice
*readSyscall
literal literal literal syscall halt
&readSyscallContent
*stdoutDevice
*writeSyscall

>stdinDevice #0
>readSyscall #0
>stdoutDevice #1
>writeSyscall #1
:readSyscallContent "000000000000000000000000000000"
Loading

0 comments on commit 620899d

Please sign in to comment.