new curly bracket coding convention

This commit is contained in:
cozis
2022-04-04 00:07:33 +02:00
parent 29e80c6319
commit 07137b50c6
28 changed files with 4036 additions and 4059 deletions
+39 -38
View File
@@ -42,10 +42,10 @@ fun parse(str) {
return none; return none;
} }
return parseAnyValue(ctx); return parseAny(ctx);
} }
fun parseArrayValue(ctx) { fun parseArray(ctx) {
assert(current(ctx) == '['); assert(current(ctx) == '[');
@@ -67,7 +67,7 @@ fun parseArrayValue(ctx) {
while true: { while true: {
child = parseAnyValue(ctx); child = parseAny(ctx);
if child == none: if child == none:
return none; return none;
@@ -103,7 +103,7 @@ fun parseArrayValue(ctx) {
return arr; return arr;
} }
fun parseObjectValue(ctx) { fun parseObject(ctx) {
assert(current(ctx) == '{'); assert(current(ctx) == '{');
@@ -130,7 +130,7 @@ fun parseObjectValue(ctx) {
return none; return none;
} }
key = parseStringValue(ctx); key = parseString(ctx);
if key == none: if key == none:
return none; return none;
@@ -146,7 +146,7 @@ fun parseObjectValue(ctx) {
skip(ctx, isSpace); skip(ctx, isSpace);
child = parseAnyValue(ctx); child = parseAny(ctx);
if child == none: if child == none:
return none; return none;
@@ -182,7 +182,7 @@ fun parseObjectValue(ctx) {
return obj; return obj;
} }
fun parseStringValue(ctx) { fun parseString(ctx) {
next(ctx); # Skip the '"'. next(ctx); # Skip the '"'.
@@ -207,7 +207,7 @@ fun parseStringValue(ctx) {
return buff; return buff;
} }
fun parseNumberValue(ctx) { fun parseNumber(ctx) {
assert(isDigit(current(ctx))); assert(isDigit(current(ctx)));
@@ -251,49 +251,50 @@ fun parseNumberValue(ctx) {
return parsed; return parsed;
} }
fun parseAnyValue(ctx) { fun parseAny(ctx) {
print('Parsing value\n');
assert(not ended(ctx)); assert(not ended(ctx));
if current(ctx) == '[': if current(ctx) == '[':
return parseArrayValue(ctx); return parseArray(ctx);
if current(ctx) == '{': if current(ctx) == '{':
return parseObjectValue(ctx); return parseObject(ctx);
if current(ctx) == '"': if current(ctx) == '"':
return parseStringValue(ctx); return parseString(ctx);
if isDigit(current(ctx)): if isDigit(current(ctx)):
return parseNumberValue(ctx); return parseNumber(ctx);
error("Not implemented yet"); error("Not implemented yet");
} }
tests = [ #tests = ['', '1', '10', '1.10', '"jeje"', '[]', '[1,2,3]', ' [ ] ', ' [ 1 , 2 , 3 ]', '{}', ' { } ', '{"hoy":4}', ' { "hoy" : 4 } '];
'',
'1',
'10',
'1.10',
'"jeje"',
'[]',
'[1,2,3]',
' [ ] ',
' [ 1 , 2 , 3 ]',
'{}',
' { } ',
'{"hoy":4}',
' { "hoy" : 4 } ',
'a'
];
i = 0; #i = 0;
while i < count(tests): { #while i < count(tests): {
r = parse(tests[i]); # r = parse(tests[i]);
if r == none: # if r == none:
print('\nTest ', i, ' failed\n'); # print('\nTest ', i, ' failed\n');
else # else
print(tests[i], ' -> ', r, '\n'); # print(tests[i], ' -> ', r, '\n');
i = i + 1; # i = i + 1;
} #}
file = files.openFile('examples/large-file.json', files.READ);
if file == none:
error("Failed to open file");
buff = newBuffer(30000000);
if buff == none:
error("Failed to create buffer");
n = files.read(file, buff);
text = bufferToString(sliceBuffer(buff, 0, n));
print(parse(text));
+59 -60
View File
@@ -64,10 +64,10 @@ static Object *bin_unicode(Runtime *runtime, Object **argv, unsigned int argc, E
uint32_t ret = 0; uint32_t ret = 0;
if(!Object_IsString(argv[0])) if(!Object_IsString(argv[0]))
{ {
Error_Report(error, 0, "Argument #%d is not a string", 1); Error_Report(error, 0, "Argument #%d is not a string", 1);
return NULL; return NULL;
} }
const char *string; const char *string;
int n; int n;
@@ -76,10 +76,10 @@ static Object *bin_unicode(Runtime *runtime, Object **argv, unsigned int argc, E
return NULL; return NULL;
if(n == 0) if(n == 0)
{ {
Error_Report(error, 0, "Argument #%d is an empty string", 1); Error_Report(error, 0, "Argument #%d is an empty string", 1);
return NULL; return NULL;
} }
int k = utf8_sequence_to_utf32_codepoint(string,n,&ret); int k = utf8_sequence_to_utf32_codepoint(string,n,&ret);
@@ -111,31 +111,31 @@ static Object *bin_input(Runtime *runtime, Object **argv, unsigned int argc, Err
int size = 0, cap = sizeof(maybe)-1; int size = 0, cap = sizeof(maybe)-1;
while(1) while(1)
{
char c = getc(stdin);
if(c == '\n')
break;
if(size == cap)
{ {
char c = getc(stdin); int newcap = cap*2;
char *tmp = realloc(str, newcap + 1);
if(c == '\n') if(tmp == NULL)
break; {
if(str != maybe) free(str);
Error_Report(error, 1, "No memory");
return NULL;
}
if(size == cap) str = tmp;
{ cap = newcap;
int newcap = cap*2;
char *tmp = realloc(str, newcap + 1);
if(tmp == NULL)
{
if(str != maybe) free(str);
Error_Report(error, 1, "No memory");
return NULL;
}
str = tmp;
cap = newcap;
}
str[size++] = c;
} }
str[size++] = c;
}
str[size] = '\0'; str[size] = '\0';
Object *res = Object_FromString(str, size, Runtime_GetHeap(runtime), error); Object *res = Object_FromString(str, size, Runtime_GetHeap(runtime), error);
@@ -150,11 +150,11 @@ static Object *bin_assert(Runtime *runtime, Object **argv, unsigned int argc, Er
{ {
for(unsigned int i = 0; i < argc; i += 1) for(unsigned int i = 0; i < argc; i += 1)
if(!Object_ToBool(argv[i], error)) if(!Object_ToBool(argv[i], error))
{ {
if(!error->occurred) if(!error->occurred)
Error_Report(error, 0, "Assertion failed"); Error_Report(error, 0, "Assertion failed");
return NULL; return NULL;
} }
return Object_NewNone(Runtime_GetHeap(runtime), error); return Object_NewNone(Runtime_GetHeap(runtime), error);
} }
@@ -179,48 +179,47 @@ static Object *bin_strcat(Runtime *runtime, Object **argv, unsigned int argc, Er
unsigned int total_count = 0; unsigned int total_count = 0;
for(unsigned int i = 0; i < argc; i += 1) for(unsigned int i = 0; i < argc; i += 1)
{
if(!Object_IsString(argv[i]))
{ {
if(!Object_IsString(argv[i])) Error_Report(error, 0, "Argument #%d is not a string", i+1);
{ return NULL;
Error_Report(error, 0, "Argument #%d is not a string", i+1);
return NULL;
}
total_count += Object_Count(argv[i], error);
if(error->occurred)
return NULL;
} }
total_count += Object_Count(argv[i], error);
if(error->occurred)
return NULL;
}
char starting[128]; char starting[128];
char *buffer = starting; char *buffer = starting;
if(total_count > sizeof(starting)-1) if(total_count > sizeof(starting)-1)
{ {
buffer = malloc(total_count+1); buffer = malloc(total_count+1);
if(buffer == NULL) if(buffer == NULL)
{ {
Error_Report(error, 1, "No memory"); Error_Report(error, 1, "No memory");
return NULL; return NULL;
}
} }
}
Object *result = NULL; Object *result = NULL;
for(unsigned int i = 0, written = 0; i < argc; i += 1) for(unsigned int i = 0, written = 0; i < argc; i += 1)
{ {
int n; int n;
const char *s; const char *s = Object_ToString(argv[i], &n,
Runtime_GetHeap(runtime), error);
s = Object_ToString(argv[i], &n, Runtime_GetHeap(runtime), error); if(error->occurred)
goto done;
if(error->occurred) memcpy(buffer + written, s, n);
goto done; written += n;
}
memcpy(buffer + written, s, n);
written += n;
}
buffer[total_count] = '\0'; buffer[total_count] = '\0';
+93 -93
View File
@@ -43,16 +43,16 @@ static Object *bin_openFile(Runtime *runtime, Object **argv, unsigned int argc,
assert(argc == 2); assert(argc == 2);
if(!Object_IsString(argv[0])) if(!Object_IsString(argv[0]))
{ {
Error_Report(error, 0, "Expected first argument to be a string, but it's a %s", Object_GetName(argv[0])); Error_Report(error, 0, "Expected first argument to be a string, but it's a %s", Object_GetName(argv[0]));
return NULL; return NULL;
} }
if(!Object_IsInt(argv[1])) if(!Object_IsInt(argv[1]))
{ {
Error_Report(error, 0, "Expected second argument to be an int, but it's a %s", Object_GetName(argv[1])); Error_Report(error, 0, "Expected second argument to be an int, but it's a %s", Object_GetName(argv[1]));
return NULL; return NULL;
} }
Heap *heap = Runtime_GetHeap(runtime); Heap *heap = Runtime_GetHeap(runtime);
@@ -71,24 +71,24 @@ static Object *bin_openFile(Runtime *runtime, Object **argv, unsigned int argc,
const char *mode2; const char *mode2;
switch(mode) switch(mode)
{ {
case MD_READ: case MD_READ:
mode2 = "r"; mode2 = "r";
break; break;
case MD_READ | MD_WRITE: case MD_READ | MD_WRITE:
mode2 = "w+"; mode2 = "w+";
break; break;
case MD_READ | MD_APPEND: case MD_READ | MD_APPEND:
case MD_READ | MD_WRITE | MD_APPEND: case MD_READ | MD_WRITE | MD_APPEND:
mode2 = "a"; mode2 = "a";
break; break;
default: default:
assert(0); assert(0);
break; break;
} }
fp = fopen(path, mode2); fp = fopen(path, mode2);
@@ -108,16 +108,16 @@ static Object *bin_read(Runtime *runtime, Object **argv, unsigned int argc, Erro
// Arg 2: count // Arg 2: count
if(!Object_IsFile(argv[0])) if(!Object_IsFile(argv[0]))
{ {
Error_Report(error, 0, "Expected first argument to be a file, but it's a %s", Object_GetName(argv[0])); Error_Report(error, 0, "Expected first argument to be a file, but it's a %s", Object_GetName(argv[0]));
return NULL; return NULL;
} }
if(!Object_IsBuffer(argv[1])) if(!Object_IsBuffer(argv[1]))
{ {
Error_Report(error, 0, "Expected second argument to be a buffer, but it's a %s", Object_GetName(argv[1])); Error_Report(error, 0, "Expected second argument to be a buffer, but it's a %s", Object_GetName(argv[1]));
return NULL; return NULL;
} }
Heap *heap = Runtime_GetHeap(runtime); Heap *heap = Runtime_GetHeap(runtime);
@@ -129,26 +129,26 @@ static Object *bin_read(Runtime *runtime, Object **argv, unsigned int argc, Erro
int read_size; int read_size;
if(Object_IsNone(argv[2])) if(Object_IsNone(argv[2]))
{ {
read_size = buff_size; read_size = buff_size;
} }
else if(Object_IsInt(argv[2])) else if(Object_IsInt(argv[2]))
{ {
long long int temp = Object_ToInt(argv[2], error); long long int temp = Object_ToInt(argv[2], error);
if(error->occurred) if(error->occurred)
return NULL;
read_size = temp; // TODO: Handle potential overflow.
if(read_size > buff_size)
read_size = buff_size;
}
else
{
Error_Report(error, 0, "Expected third argument to be an int or none, but it's a %s", Object_GetName(argv[0]));
return NULL; return NULL;
}
read_size = temp; // TODO: Handle potential overflow.
if(read_size > buff_size)
read_size = buff_size;
}
else
{
Error_Report(error, 0, "Expected third argument to be an int or none, but it's a %s", Object_GetName(argv[0]));
return NULL;
}
FILE *fp = Object_ToStream(argv[0], error); FILE *fp = Object_ToStream(argv[0], error);
@@ -169,16 +169,16 @@ static Object *bin_write(Runtime *runtime, Object **argv, unsigned int argc, Err
// Arg 2: count // Arg 2: count
if(!Object_IsFile(argv[0])) if(!Object_IsFile(argv[0]))
{ {
Error_Report(error, 0, "Expected first argument to be a file, but it's a %s", Object_GetName(argv[0])); Error_Report(error, 0, "Expected first argument to be a file, but it's a %s", Object_GetName(argv[0]));
return NULL; return NULL;
} }
if(!Object_IsBuffer(argv[1])) if(!Object_IsBuffer(argv[1]))
{ {
Error_Report(error, 0, "Expected second argument to be a buffer, but it's a %s", Object_GetName(argv[1])); Error_Report(error, 0, "Expected second argument to be a buffer, but it's a %s", Object_GetName(argv[1]));
return NULL; return NULL;
} }
Heap *heap = Runtime_GetHeap(runtime); Heap *heap = Runtime_GetHeap(runtime);
@@ -190,26 +190,26 @@ static Object *bin_write(Runtime *runtime, Object **argv, unsigned int argc, Err
int write_size; int write_size;
if(Object_IsNone(argv[2])) if(Object_IsNone(argv[2]))
{ {
write_size = buff_size; write_size = buff_size;
} }
else if(Object_IsInt(argv[2])) else if(Object_IsInt(argv[2]))
{ {
long long int temp = Object_ToInt(argv[2], error); long long int temp = Object_ToInt(argv[2], error);
if(error->occurred) if(error->occurred)
return NULL;
write_size = temp; // TODO: Handle potential overflow.
if(write_size > buff_size)
write_size = buff_size;
}
else
{
Error_Report(error, 0, "Expected third argument to be an int or none, but it's a %s", Object_GetName(argv[0]));
return NULL; return NULL;
}
write_size = temp; // TODO: Handle potential overflow.
if(write_size > buff_size)
write_size = buff_size;
}
else
{
Error_Report(error, 0, "Expected third argument to be an int or none, but it's a %s", Object_GetName(argv[0]));
return NULL;
}
FILE *fp = Object_ToStream(argv[0], error); FILE *fp = Object_ToStream(argv[0], error);
@@ -228,10 +228,10 @@ static Object *bin_openDir(Runtime *runtime, Object **argv, unsigned int argc, E
// Arg 0: path // Arg 0: path
if(!Object_IsString(argv[0])) if(!Object_IsString(argv[0]))
{ {
Error_Report(error, 0, "Expected first argument to be a string, but it's a %s", Object_GetName(argv[0])); Error_Report(error, 0, "Expected first argument to be a string, but it's a %s", Object_GetName(argv[0]));
return NULL; return NULL;
} }
Heap *heap = Runtime_GetHeap(runtime); Heap *heap = Runtime_GetHeap(runtime);
@@ -248,10 +248,10 @@ static Object *bin_openDir(Runtime *runtime, Object **argv, unsigned int argc, E
Object *dob = Object_FromDIR(dir, heap, error); Object *dob = Object_FromDIR(dir, heap, error);
if(error->occurred) if(error->occurred)
{ {
(void) closedir(dir); (void) closedir(dir);
return NULL; return NULL;
} }
return dob; return dob;
} }
@@ -263,10 +263,10 @@ static Object *bin_nextDirItem(Runtime *runtime, Object **argv, unsigned int arg
// Arg 0: path // Arg 0: path
if(!Object_IsDir(argv[0])) if(!Object_IsDir(argv[0]))
{ {
Error_Report(error, 0, "Expected first argument to be a directory, but it's a %s", Object_GetName(argv[0])); Error_Report(error, 0, "Expected first argument to be a directory, but it's a %s", Object_GetName(argv[0]));
return NULL; return NULL;
} }
DIR *dir = Object_ToDIR(argv[0], error); DIR *dir = Object_ToDIR(argv[0], error);
@@ -282,15 +282,15 @@ static Object *bin_nextDirItem(Runtime *runtime, Object **argv, unsigned int arg
struct dirent *ent = readdir(dir); struct dirent *ent = readdir(dir);
if(ent == NULL) if(ent == NULL)
{ {
if(errno == 0) if(errno == 0)
// Nothing left to read. // Nothing left to read.
return Object_NewNone(heap, error); return Object_NewNone(heap, error);
// An error occurred. // An error occurred.
Error_Report(error, 1, "Failed to read directory item"); Error_Report(error, 1, "Failed to read directory item");
return NULL; return NULL;
} }
return Object_FromString(ent->d_name, -1, heap, error); return Object_FromString(ent->d_name, -1, heap, error);
} }
+45 -45
View File
@@ -33,54 +33,54 @@
#include "math.h" #include "math.h"
#define WRAP_FUNC(name) \ #define WRAP_FUNC(name) \
static Object *bin_ ## name(Runtime *runtime, Object **argv, unsigned int argc, Error *error) \ static Object *bin_ ## name(Runtime *runtime, Object **argv, unsigned int argc, Error *error) \
{ \ { \
assert(argc == 1); \ assert(argc == 1); \
\ \
if(Object_IsFloat(argv[0])) \ if(Object_IsFloat(argv[0])) \
{ \ { \
double v = Object_ToFloat(argv[0], error); \ double v = Object_ToFloat(argv[0], error); \
\ \
if(error->occurred) \ if(error->occurred) \
return NULL; \ return NULL; \
\ \
return Object_FromFloat(name(v), Runtime_GetHeap(runtime), error); \ return Object_FromFloat(name(v), Runtime_GetHeap(runtime), error); \
} \ } \
else \ else \
{ \ { \
Error_Report(error, 0, "Expected first argument to be a float, but it's a %s", Object_GetName(argv[0]));\ Error_Report(error, 0, "Expected first argument to be a float, but it's a %s", Object_GetName(argv[0]));\
return NULL; \ return NULL; \
} \ } \
} }
#define WRAP_FUNC_2(name) \ #define WRAP_FUNC_2(name) \
static Object *bin_ ## name(Runtime *runtime, Object **argv, unsigned int argc, Error *error) \ static Object *bin_ ## name(Runtime *runtime, Object **argv, unsigned int argc, Error *error) \
{ \ { \
assert(argc == 2); \ assert(argc == 2); \
\ \
if(!Object_IsFloat(argv[0])) \ if(!Object_IsFloat(argv[0])) \
{ \ { \
Error_Report(error, 0, "Expected first argument to be a float, but it's a %s", Object_GetName(argv[0]));\ Error_Report(error, 0, "Expected first argument to be a float, but it's a %s", Object_GetName(argv[0]));\
return NULL; \ return NULL; \
} \ } \
\ \
if(!Object_IsFloat(argv[1])) \ if(!Object_IsFloat(argv[1])) \
{ \ { \
Error_Report(error, 0, "Expected second argument to be a float, but it's a %s", Object_GetName(argv[1]));\ Error_Report(error, 0, "Expected second argument to be a float, but it's a %s", Object_GetName(argv[1]));\
return NULL; \ return NULL; \
} \ } \
\ \
double v1 = Object_ToFloat(argv[0], error); \ double v1 = Object_ToFloat(argv[0], error); \
\ \
if(error->occurred) \ if(error->occurred) \
return NULL; \ return NULL; \
\ \
double v2 = Object_ToFloat(argv[1], error); \ double v2 = Object_ToFloat(argv[1], error); \
\ \
if(error->occurred) \ if(error->occurred) \
return NULL; \ return NULL; \
\ \
return Object_FromFloat(name(v1, v2), Runtime_GetHeap(runtime), error); \ return Object_FromFloat(name(v1, v2), Runtime_GetHeap(runtime), error); \
} }
WRAP_FUNC(ceil) WRAP_FUNC(ceil)
+167 -169
View File
@@ -131,51 +131,51 @@ void Executable_Free(Executable *exe)
assert(exe->refs >= 0); assert(exe->refs >= 0);
if(exe->refs == 0) if(exe->refs == 0)
{ {
if(exe->src) if(exe->src)
Source_Free(exe->src); Source_Free(exe->src);
free(exe); free(exe);
} }
} }
void Executable_Dump(Executable *exe) void Executable_Dump(Executable *exe)
{ {
for(int i = 0; i < exe->bodyl; i += 1) for(int i = 0; i < exe->bodyl; i += 1)
{
Opcode opcode;
Operand ops[MAX_OPS];
int opc = MAX_OPS;
(void) Executable_Fetch(exe, i, &opcode, ops, &opc);
const InstrInfo *info = instr_table + exe->body[i].opcode;
fprintf(stderr, "%d: %s ", i, info->name);
for(int j = 0; j < opc; j += 1)
{ {
Opcode opcode; switch(ops[j].type)
Operand ops[MAX_OPS]; {
int opc = MAX_OPS; case OPTP_INT:
fprintf(stderr, "%lld ", ops[j].as_int);
break;
(void) Executable_Fetch(exe, i, &opcode, ops, &opc); case OPTP_FLOAT:
fprintf(stderr, "%f ", ops[j].as_float);
break;
const InstrInfo *info = instr_table + exe->body[i].opcode; case OPTP_STRING:
fprintf(stderr, "[%s] ", ops[j].as_string);
break;
fprintf(stderr, "%d: %s ", i, info->name); case OPTP_PROMISE:
UNREACHABLE;
for(int j = 0; j < opc; j += 1) break;
{ }
switch(ops[j].type)
{
case OPTP_INT:
fprintf(stderr, "%lld ", ops[j].as_int);
break;
case OPTP_FLOAT:
fprintf(stderr, "%f ", ops[j].as_float);
break;
case OPTP_STRING:
fprintf(stderr, "[%s] ", ops[j].as_string);
break;
case OPTP_PROMISE:
UNREACHABLE;
break;
}
}
fprintf(stderr, "\n");
} }
fprintf(stderr, "\n");
}
} }
_Bool Executable_SetSource(Executable *exe, Source *src) _Bool Executable_SetSource(Executable *exe, Source *src)
@@ -232,46 +232,46 @@ _Bool Executable_Fetch(Executable *exe, int index, Opcode *opcode, Operand *ops,
int i; int i;
if(ops && opc) if(ops && opc)
{
int k = MIN(*opc, info->opcount);
for(i = 0; i < k; i += 1)
{ {
int k = MIN(*opc, info->opcount); OperandType type = info->optypes[i];
assert(type != OPTP_PROMISE);
for(i = 0; i < k; i += 1) switch(type)
{
case OPTP_STRING:
{ {
OperandType type = info->optypes[i]; int data_offset = instr->operands[i].as_int;
assert(type != OPTP_PROMISE);
switch(type) { assert(data_offset < exe->headl);
case OPTP_STRING: ops[i].type = OPTP_STRING;
{ ops[i].as_string = exe->head + data_offset;
int data_offset = instr->operands[i].as_int; break;
assert(data_offset < exe->headl);
ops[i].type = OPTP_STRING;
ops[i].as_string = exe->head + data_offset;
break;
}
case OPTP_INT:
ops[i].type = OPTP_INT;
ops[i].as_int = instr->operands[i].as_int;
break;
case OPTP_FLOAT:
ops[i].type = OPTP_FLOAT;
ops[i].as_int = instr->operands[i].as_int;
break;
case OPTP_PROMISE:
UNREACHABLE;
break;
}
} }
*opc = MIN(*opc, info->opcount); case OPTP_INT:
ops[i].type = OPTP_INT;
ops[i].as_int = instr->operands[i].as_int;
break;
case OPTP_FLOAT:
ops[i].type = OPTP_FLOAT;
ops[i].as_int = instr->operands[i].as_int;
break;
case OPTP_PROMISE:
UNREACHABLE;
break;
}
} }
*opc = MIN(*opc, info->opcount);
}
return 1; return 1;
} }
@@ -298,10 +298,10 @@ Executable *ExeBuilder_Finalize(ExeBuilder *exeb, Error *error)
assert(exeb != NULL); assert(exeb != NULL);
if(exeb->promc > 0) if(exeb->promc > 0)
{ {
Error_Report(error, 0, "There are still %d unfulfilled promises", exeb->promc); Error_Report(error, 0, "There are still %d unfulfilled promises", exeb->promc);
return 0; return 0;
} }
Executable *exe; Executable *exe;
{ {
@@ -313,10 +313,10 @@ Executable *ExeBuilder_Finalize(ExeBuilder *exeb, Error *error)
void *temp = malloc(sizeof(Executable) + data_size + code_size); void *temp = malloc(sizeof(Executable) + data_size + code_size);
if(temp == NULL) if(temp == NULL)
{ {
Error_Report(error, 1, "No memory"); Error_Report(error, 1, "No memory");
return NULL; return NULL;
} }
exe = temp; exe = temp;
exe->headl = data_size; exe->headl = data_size;
@@ -369,13 +369,13 @@ _Bool ExeBuilder_Append(ExeBuilder *exeb, Error *error, Opcode opcode, Operand *
const InstrInfo *info = instr_table + opcode; const InstrInfo *info = instr_table + opcode;
if(opc != info->opcount) if(opc != info->opcount)
{ {
// ERROR: Too many operands were provided. // ERROR: Too many operands were provided.
Error_Report(error, 0, Error_Report(error, 0,
"Instruction %s expects %d operands, but %d were provided", "Instruction %s expects %d operands, but %d were provided",
info->name, info->opcount, opc); info->name, info->opcount, opc);
return 0; return 0;
} }
assert(opc <= MAX_OPS); assert(opc <= MAX_OPS);
@@ -383,106 +383,104 @@ _Bool ExeBuilder_Append(ExeBuilder *exeb, Error *error, Opcode opcode, Operand *
Instruction *instr = BucketList_Append2(exeb->code, NULL, sizeof(Instruction)); Instruction *instr = BucketList_Append2(exeb->code, NULL, sizeof(Instruction));
if(instr == NULL) if(instr == NULL)
{ {
Error_Report(error, 1, "No memory"); Error_Report(error, 1, "No memory");
return 0; return 0;
} }
instr->opcode = opcode; instr->opcode = opcode;
instr->offset = off; instr->offset = off;
instr->length = len; instr->length = len;
for(int i = 0; i < opc; i += 1) for(int i = 0; i < opc; i += 1)
{
// Check that the expected type and the provided one
// match, or that the provided type is a promise with
// the same size of the expected type.
{ {
// Check that the expected type and the provided one OperandType expected_type = info->optypes[i];
// match, or that the provided type is a promise with OperandType provided_type = opv[i].type;
// the same size of the expected type.
assert(expected_type != OPTP_PROMISE);
if(provided_type == OPTP_PROMISE)
{ {
OperandType expected_type = info->optypes[i]; assert(opv[i].as_promise != NULL);
OperandType provided_type = opv[i].type;
assert(expected_type != OPTP_PROMISE); if(expected_type == OPTP_STRING)
if(provided_type == OPTP_PROMISE)
{
assert(opv[i].as_promise != NULL);
if(expected_type == OPTP_STRING)
{
Error_Report(error, 0, "Promise values can't be provided as string operands");
return 0;
}
if(Promise_Size(opv[i].as_promise) != operand_type_sizes[expected_type])
{
Error_Report(error, 0,
"Provided promise has a value size of %d, "
"but since %s %s was expected, the promise "
"size must be %d",
Promise_Size(opv[i].as_promise),
operand_type_arts[expected_type],
operand_type_names[expected_type],
operand_type_sizes[expected_type]);
return 0;
}
}
else if(expected_type != provided_type)
{
// ERROR: Wrong operand type provided.
Error_Report(error, 0,
"Instruction %s expects %s %s as operand %d, but %s %s was provided instead",
info->name,
operand_type_arts[expected_type],
operand_type_names[expected_type],
i,
operand_type_arts[provided_type],
operand_type_names[provided_type]
);
return 0;
}
}
// Do the copying of the operands.
switch(opv[i].type)
{ {
case OPTP_STRING: Error_Report(error, 0, "Promise values can't be provided as string operands");
return 0;
instr->operands[i].as_int = BucketList_Size(exeb->data);
if(!BucketList_Append(exeb->data, opv[i].as_string, strlen(opv[i].as_string)+1))
{
Error_Report(error, 1, "No memory");
return 0;
}
break;
case OPTP_PROMISE:
assert(info->optypes[i] != OPTP_STRING);
// This must be incremented before subscribing
// since the counter-decrementing callback may
// be called immediately if the promise was
// already fulfilled.
exeb->promc += 1;
if(!Promise_Subscribe2(opv[i].as_promise, &instr->operands[i], exeb, promise_callback))
{
Error_Report(error, 1, "No memory");
return 0;
}
break;
case OPTP_INT:
instr->operands[i].as_int = opv[i].as_int;
break;
case OPTP_FLOAT:
instr->operands[i].as_float = opv[i].as_float;
break;
} }
if(Promise_Size(opv[i].as_promise) != operand_type_sizes[expected_type])
{
Error_Report(error, 0,
"Provided promise has a value size of %d, "
"but since %s %s was expected, the promise "
"size must be %d",
Promise_Size(opv[i].as_promise),
operand_type_arts[expected_type],
operand_type_names[expected_type],
operand_type_sizes[expected_type]);
return 0;
}
}
else if(expected_type != provided_type)
{
// ERROR: Wrong operand type provided.
Error_Report(error, 0,
"Instruction %s expects %s %s as operand %d, but %s %s was provided instead",
info->name,
operand_type_arts[expected_type],
operand_type_names[expected_type],
i,
operand_type_arts[provided_type],
operand_type_names[provided_type]
);
return 0;
}
} }
// Do the copying of the operands.
switch(opv[i].type)
{
case OPTP_STRING:
instr->operands[i].as_int = BucketList_Size(exeb->data);
if(!BucketList_Append(exeb->data, opv[i].as_string, strlen(opv[i].as_string)+1))
{
Error_Report(error, 1, "No memory");
return 0;
}
break;
case OPTP_PROMISE:
assert(info->optypes[i] != OPTP_STRING);
// This must be incremented before subscribing
// since the counter-decrementing callback may
// be called immediately if the promise was
// already fulfilled.
exeb->promc += 1;
if(!Promise_Subscribe2(opv[i].as_promise, &instr->operands[i], exeb, promise_callback))
{
Error_Report(error, 1, "No memory");
return 0;
}
break;
case OPTP_INT:
instr->operands[i].as_int = opv[i].as_int;
break;
case OPTP_FLOAT:
instr->operands[i].as_float = opv[i].as_float;
break;
}
}
} }
return 1; return 1;
+556 -557
View File
File diff suppressed because it is too large Load Diff
+1123 -1144
View File
File diff suppressed because it is too large Load Diff
+138 -139
View File
@@ -57,14 +57,14 @@ static void print_error(const char *type, Error *error)
#ifdef DEBUG #ifdef DEBUG
if(error->file != NULL) if(error->file != NULL)
{ {
if(error->line > 0 && error->func != NULL) if(error->line > 0 && error->func != NULL)
fprintf(stderr, " (Reported in %s:%d in %s)", error->file, error->line, error->func); fprintf(stderr, " (Reported in %s:%d in %s)", error->file, error->line, error->func);
else if(error->line > 0 && error->func == NULL) else if(error->line > 0 && error->func == NULL)
fprintf(stderr, " (Reported in %s:%d)", error->file, error->line); fprintf(stderr, " (Reported in %s:%d)", error->file, error->line);
else if(error->line < 1 && error->func != NULL) else if(error->line < 1 && error->func != NULL)
fprintf(stderr, " (Reported in %s in %s)", error->file, error->func); fprintf(stderr, " (Reported in %s in %s)", error->file, error->func);
} }
#endif #endif
fprintf(stderr, "\n"); fprintf(stderr, "\n");
@@ -78,10 +78,10 @@ static Executable *build(Source *src)
BPAlloc *alloc = BPAlloc_Init(-1); BPAlloc *alloc = BPAlloc_Init(-1);
if(alloc == NULL) if(alloc == NULL)
{ {
fprintf(stderr, "Internal Error: Couldn't allocate bump-pointer allocator to hold the AST.\n"); fprintf(stderr, "Internal Error: Couldn't allocate bump-pointer allocator to hold the AST.\n");
return 0; return 0;
} }
Error error; Error error;
Error_Init(&error); Error_Init(&error);
@@ -91,13 +91,13 @@ static Executable *build(Source *src)
AST *ast = parse(src, alloc, &error); AST *ast = parse(src, alloc, &error);
if(ast == NULL) if(ast == NULL)
{ {
assert(error.occurred); assert(error.occurred);
print_error("Parsing", &error); print_error("Parsing", &error);
Error_Free(&error); Error_Free(&error);
BPAlloc_Free(alloc); BPAlloc_Free(alloc);
return 0; return 0;
} }
exe = compile(ast, alloc, &error); exe = compile(ast, alloc, &error);
@@ -106,12 +106,12 @@ static Executable *build(Source *src)
BPAlloc_Free(alloc); BPAlloc_Free(alloc);
if(exe == NULL) if(exe == NULL)
{ {
assert(error.occurred); assert(error.occurred);
print_error("Compilation", &error); print_error("Compilation", &error);
Error_Free(&error); Error_Free(&error);
return 0; return 0;
} }
return exe; return exe;
} }
@@ -123,18 +123,18 @@ static _Bool interpret(Source *src)
if(exe == NULL) if(exe == NULL)
return 0; return 0;
Runtime *runt = Runtime_New(-1, -1, NULL, NULL); Runtime *runt = Runtime_New(-1, 1024*1024, NULL, NULL);
if(runt == NULL) if(runt == NULL)
{ {
Error error; Error error;
Error_Init(&error); Error_Init(&error);
Error_Report(&error, 1, "Couldn't initialize runtime"); Error_Report(&error, 1, "Couldn't initialize runtime");
print_error(NULL, &error); print_error(NULL, &error);
Error_Free(&error); Error_Free(&error);
Executable_Free(exe); Executable_Free(exe);
return 0; return 0;
} }
// We use a [RuntimeError] instead of a simple [Error] // We use a [RuntimeError] instead of a simple [Error]
// because the [RuntimeError] makes a snapshot of the // because the [RuntimeError] makes a snapshot of the
@@ -148,14 +148,14 @@ static _Bool interpret(Source *src)
Object *bins = Object_NewStaticMap(bins_basic, runt, (Error*) &error); Object *bins = Object_NewStaticMap(bins_basic, runt, (Error*) &error);
if(bins == NULL) if(bins == NULL)
{ {
assert(error.base.occurred == 1); assert(error.base.occurred == 1);
print_error(NULL, (Error*) &error); print_error(NULL, (Error*) &error);
RuntimeError_Free(&error); RuntimeError_Free(&error);
Executable_Free(exe); Executable_Free(exe);
Runtime_Free(runt); Runtime_Free(runt);
return 0; return 0;
} }
Runtime_SetBuiltins(runt, bins); Runtime_SetBuiltins(runt, bins);
@@ -165,16 +165,16 @@ static _Bool interpret(Source *src)
// now because it may be moved by the garbage collector. // now because it may be moved by the garbage collector.
if(o == NULL) if(o == NULL)
{ {
print_error("Runtime", (Error*) &error); print_error("Runtime", (Error*) &error);
if(error.snapshot == NULL) if(error.snapshot == NULL)
fprintf(stderr, "No snapshot available.\n"); fprintf(stderr, "No snapshot available.\n");
else else
Snapshot_Print(error.snapshot, stderr); Snapshot_Print(error.snapshot, stderr);
RuntimeError_Free(&error); RuntimeError_Free(&error);
} }
Runtime_Free(runt); Runtime_Free(runt);
Executable_Free(exe); Executable_Free(exe);
@@ -201,12 +201,12 @@ static _Bool interpret_file(const char *file)
Source *src = Source_FromFile(file, &error); Source *src = Source_FromFile(file, &error);
if(src == NULL) if(src == NULL)
{ {
assert(error.occurred == 1); assert(error.occurred == 1);
print_error(NULL, &error); print_error(NULL, &error);
Error_Free(&error); Error_Free(&error);
return 0; return 0;
} }
_Bool r = interpret(src); _Bool r = interpret(src);
@@ -222,12 +222,12 @@ static _Bool interpret_code(const char *code)
Source *src = Source_FromString(NULL, code, -1, &error); Source *src = Source_FromString(NULL, code, -1, &error);
if(src == NULL) if(src == NULL)
{ {
assert(error.occurred); assert(error.occurred);
print_error(NULL, &error); print_error(NULL, &error);
Error_Free(&error); Error_Free(&error);
return 0; return 0;
} }
_Bool r = interpret(src); _Bool r = interpret(src);
@@ -243,12 +243,12 @@ static _Bool disassemble_file(const char *file)
Source *src = Source_FromFile(file, &error); Source *src = Source_FromFile(file, &error);
if(src == NULL) if(src == NULL)
{ {
assert(error.occurred == 1); assert(error.occurred == 1);
print_error(NULL, &error); print_error(NULL, &error);
Error_Free(&error); Error_Free(&error);
return 0; return 0;
} }
_Bool r = disassemble(src); _Bool r = disassemble(src);
@@ -264,12 +264,12 @@ static _Bool disassemble_code(const char *code)
Source *src = Source_FromString(NULL, code, -1, &error); Source *src = Source_FromString(NULL, code, -1, &error);
if(src == NULL) if(src == NULL)
{ {
assert(error.occurred); assert(error.occurred);
print_error(NULL, &error); print_error(NULL, &error);
Error_Free(&error); Error_Free(&error);
return 0; return 0;
} }
_Bool r = disassemble(src); _Bool r = disassemble(src);
@@ -282,82 +282,81 @@ int main(int argc, char **argv)
assert(argc > 0); assert(argc > 0);
if(argc == 1) if(argc == 1)
{
// $ noja
fprintf(stderr, "Error: Incorrect usage.\n\n");
fprintf(stderr, usage);
return -1;
}
if(!strcmp(argv[1], "run"))
{
Error error;
Error_Init(&error);
if(argc == 2)
{ {
// $ noja Error_Report(&error, 0, "Missing source file");
fprintf(stderr, "Error: Incorrect usage.\n\n"); print_error(NULL, &error);
fprintf(stderr, usage); Error_Free(&error);
return -1; return -1;
} }
if(!strcmp(argv[1], "run")) _Bool r;
if(!strcmp(argv[2], "inline"))
{ {
Error error; if(argc == 3)
Error_Init(&error); {
Error_Report(&error, 0, "Missing source string");
if(argc == 2) print_error(NULL, &error);
{ Error_Free(&error);
Error_Report(&error, 0, "Missing source file"); return -1;
print_error(NULL, &error); }
Error_Free(&error); r = interpret_code(argv[3]);
return -1;
}
_Bool r;
if(!strcmp(argv[2], "inline"))
{
if(argc == 3)
{
Error_Report(&error, 0, "Missing source string");
print_error(NULL, &error);
Error_Free(&error);
return -1;
}
r = interpret_code(argv[3]);
}
else
r = interpret_file(argv[2]);
return r ? 0 : -1;
} }
else
r = interpret_file(argv[2]);
return r ? 0 : -1;
}
if(!strcmp(argv[1], "dis")) if(!strcmp(argv[1], "dis"))
{
Error error;
Error_Init(&error);
if(argc == 2)
{ {
Error error; Error_Report(&error, 0, "Missing source file");
Error_Init(&error); print_error(NULL, &error);
Error_Free(&error);
if(argc == 2) return -1;
{
Error_Report(&error, 0, "Missing source file");
print_error(NULL, &error);
Error_Free(&error);
return -1;
}
_Bool r;
if(!strcmp(argv[2], "inline"))
{
if(argc == 3)
{
Error_Report(&error, 0, "Missing source string");
print_error(NULL, &error);
Error_Free(&error);
return -1;
}
r = disassemble_code(argv[3]);
}
else
r = disassemble_file(argv[2]);
return r ? 0 : -1;
} }
_Bool r;
if(!strcmp(argv[2], "inline"))
{
if(argc == 3)
{
Error_Report(&error, 0, "Missing source string");
print_error(NULL, &error);
Error_Free(&error);
return -1;
}
r = disassemble_code(argv[3]);
}
else
r = disassemble_file(argv[2]);
return r ? 0 : -1;
}
if(!strcmp(argv[1], "help")) if(!strcmp(argv[1], "help"))
{ {
fprintf(stdout, usage); fprintf(stdout, usage);
return 0; return 0;
} }
fprintf(stderr, "Error: Incorrect usage.\n\n"); fprintf(stderr, "Error: Incorrect usage.\n\n");
fprintf(stderr, usage); fprintf(stderr, usage);
+156 -154
View File
@@ -137,10 +137,10 @@ Heap *Heap_New(int size)
heap->collecting = 0; heap->collecting = 0;
if(heap->body == NULL) if(heap->body == NULL)
{ {
free(heap); free(heap);
return NULL; return NULL;
} }
#if USING_VALGRIND #if USING_VALGRIND
VALGRIND_CREATE_MEMPOOL(heap, 0, 0); VALGRIND_CREATE_MEMPOOL(heap, 0, 0);
@@ -160,23 +160,23 @@ void Heap_Free(Heap *heap)
Error_Init(&error); Error_Init(&error);
for(int i = 0; i < heap->pend_used; i += 1) for(int i = 0; i < heap->pend_used; i += 1)
{
heap->pend[i].destructor(heap->pend[i].object, &error);
if(error.occurred)
{ {
heap->pend[i].destructor(heap->pend[i].object, &error); // Errors occurred! We can't do anything about
if(error.occurred) // it now though.
{ Error_Free(&error);
// Errors occurred! We can't do anything about Error_Init(&error);
// it now though.
Error_Free(&error);
Error_Init(&error);
}
} }
}
while(heap->oflow) while(heap->oflow)
{ {
OflowAlloc *prev = heap->oflow->prev; OflowAlloc *prev = heap->oflow->prev;
free(heap->oflow); free(heap->oflow);
heap->oflow = prev; heap->oflow = prev;
} }
free(heap->pend); free(heap->pend);
free(heap->body); free(heap->body);
@@ -208,42 +208,42 @@ void *Heap_Malloc(Heap *heap, TypeObject *type, Error *err)
_Bool requires_destruct = type->free != NULL; _Bool requires_destruct = type->free != NULL;
if(requires_destruct) if(requires_destruct)
{
// This type of object requires
// a destructor to be called.
if(heap->pend == NULL)
{ {
// This type of object requires int n = 8;
// a destructor to be called.
heap->pend = malloc(n * sizeof(PendingDestruct));
if(heap->pend == NULL) if(heap->pend == NULL)
{ {
int n = 8; Error_Report(err, 1, "No memory");
return NULL;
}
heap->pend = malloc(n * sizeof(PendingDestruct)); heap->pend_used = 0;
heap->pend_size = n;
if(heap->pend == NULL)
{
Error_Report(err, 1, "No memory");
return NULL;
}
heap->pend_used = 0;
heap->pend_size = n;
}
else if(heap->pend_size == heap->pend_used)
{
int factor = 2;
void *new_pend = realloc(heap->pend, factor * heap->pend_size * sizeof(PendingDestruct));
if(new_pend == NULL)
{
Error_Report(err, 1, "No memory");
return NULL;
}
heap->pend = new_pend;
heap->pend_size *= factor;
}
assert(heap->pend_size > heap->pend_used);
} }
else if(heap->pend_size == heap->pend_used)
{
int factor = 2;
void *new_pend = realloc(heap->pend, factor * heap->pend_size * sizeof(PendingDestruct));
if(new_pend == NULL)
{
Error_Report(err, 1, "No memory");
return NULL;
}
heap->pend = new_pend;
heap->pend_size *= factor;
}
assert(heap->pend_size > heap->pend_used);
}
int size = type->size; int size = type->size;
@@ -290,23 +290,23 @@ void *Heap_RawMalloc(Heap *heap, int size, Error *err)
padding = heap->used - padding; padding = heap->used - padding;
if(heap->used + size > heap->size) if(heap->used + size > heap->size)
{ {
OflowAlloc *oflow = malloc(sizeof(OflowAlloc) + size); OflowAlloc *oflow = malloc(sizeof(OflowAlloc) + size);
if(oflow == 0) if(oflow == 0)
return 0; return 0;
oflow->prev = heap->oflow; oflow->prev = heap->oflow;
heap->oflow = oflow; heap->oflow = oflow;
addr = oflow->body; addr = oflow->body;
} }
else else
{ {
assert(heap->used + size <= heap->size); assert(heap->used + size <= heap->size);
addr = heap->body + heap->used; addr = heap->body + heap->used;
heap->used += size; heap->used += size;
} }
heap->total += size + padding; heap->total += size + padding;
@@ -326,10 +326,10 @@ _Bool Heap_StartCollection(Heap *heap, Error *error)
void *new_body = malloc(heap->size); void *new_body = malloc(heap->size);
if(new_body == NULL) if(new_body == NULL)
{ {
Error_Report(error, 1, "No memory"); Error_Report(error, 1, "No memory");
return 0; return 0;
} }
heap->old_body = heap->body; heap->old_body = heap->body;
heap->old_used = heap->used; heap->old_used = heap->used;
@@ -351,57 +351,57 @@ _Bool Heap_StopCollection(Heap *heap)
assert(heap->collecting == 1); assert(heap->collecting == 1);
if(heap->collection_failed) if(heap->collection_failed)
{ {
free(heap->old_body); free(heap->old_body);
return 0; return 0;
} }
/* Call destructors here */ /* Call destructors here */
{ {
int i = 0; int i = 0;
while(i < heap->pend_used) while(i < heap->pend_used)
{
Object *obj = heap->pend[i].object;
if(obj->flags & Object_MOVED)
{ {
Object *obj = heap->pend[i].object; heap->pend[i].object = ((MovedObject*) heap->pend[i].object)->new_location;
i += 1;
if(obj->flags & Object_MOVED)
{
heap->pend[i].object = ((MovedObject*) heap->pend[i].object)->new_location;
i += 1;
}
else
{
// We need to call the destructor.
heap->pend[i].destructor(obj, heap->error);
if(heap->error->occurred)
return 0; // There will be leaks.
heap->pend[i] = heap->pend[heap->pend_used-1];
heap->pend_used -= 1;
}
} }
else
{
// We need to call the destructor.
heap->pend[i].destructor(obj, heap->error);
if(heap->error->occurred)
return 0; // There will be leaks.
heap->pend[i] = heap->pend[heap->pend_used-1];
heap->pend_used -= 1;
}
}
if(heap->pend_size / 2 > heap->pend_used) if(heap->pend_size / 2 > heap->pend_used)
{ {
// Downsize // Downsize
void *temp = realloc(heap->pend, heap->pend_size / 2 * sizeof(PendingDestruct)); void *temp = realloc(heap->pend, heap->pend_size / 2 * sizeof(PendingDestruct));
if(temp != NULL) if(temp != NULL)
{ {
heap->pend = temp; heap->pend = temp;
heap->pend_size /= 2; heap->pend_size /= 2;
}
} }
}
} }
while(heap->old_oflow) while(heap->old_oflow)
{ {
OflowAlloc *prev = heap->old_oflow->prev; OflowAlloc *prev = heap->old_oflow->prev;
free(heap->old_oflow); free(heap->old_oflow);
heap->old_oflow = prev; heap->old_oflow = prev;
} }
free(heap->old_body); free(heap->old_body);
@@ -425,10 +425,10 @@ void Heap_CollectExtension(void **referer, unsigned int size, void *userp)
void *new_location = Heap_RawMalloc(heap, size, heap->error); void *new_location = Heap_RawMalloc(heap, size, heap->error);
if(new_location == NULL) if(new_location == NULL)
{ {
heap->collection_failed = 1; heap->collection_failed = 1;
return; return;
} }
memcpy(new_location, old_location, size); memcpy(new_location, old_location, size);
@@ -453,62 +453,64 @@ void Heap_CollectReference(Object **referer, void *userp)
*referer = ((MovedObject*) old_location)->new_location; *referer = ((MovedObject*) old_location)->new_location;
else else
{
Object *new_location;
// This object wasn't moved to
// the new heap yet.
if(old_location->flags & Object_STATIC)
// The object doesn't need to be moved
// since it was statically allocated.
new_location = old_location;
else
{ {
Object *new_location; // Get some information.
TypeObject *type = old_location->type;
int size = type->size;
// This object wasn't moved to // Copy the object to a new location.
// the new heap yet. {
new_location = Heap_RawMalloc(heap, size, heap->error);
if(old_location->flags & Object_STATIC) if(new_location == NULL)
// The object doesn't need to be moved
// since it was statically allocated.
new_location = old_location;
else
{ {
// Get some information. heap->collection_failed = 1;
TypeObject *type = old_location->type; return;
int size = type->size;
// Copy the object to a new location.
{
new_location = Heap_RawMalloc(heap, size, heap->error);
if(new_location == NULL)
{
heap->collection_failed = 1;
return;
}
memcpy(new_location, old_location, size);
}
// Set the old location as moved and
// leave the reference to the new
// location.
{
old_location->flags |= Object_MOVED;
assert((int) sizeof(MovedObject) <= size);
((MovedObject*) old_location)->new_location = new_location;
}
heap->movedcount += 1;
} }
// Collect the reference to the type. memcpy(new_location, old_location, size);
if((Object*) new_location->type != new_location) }
Heap_CollectReference((Object**) &new_location->type, heap);
// Collect all of the references to // Set the old location as moved and
// extensions allocate using the GC'd // leave the reference to the new
// heap. // location.
Object_WalkExtensions(new_location, Heap_CollectExtension, heap); {
old_location->flags |= Object_MOVED;
// Now collect all of the children. assert((int) sizeof(MovedObject) <= size);
Object_WalkReferences(new_location, Heap_CollectReference, heap); ((MovedObject*) old_location)->new_location = new_location;
}
// Update the referer heap->movedcount += 1;
*referer = new_location;
} }
// Collect the reference to the type.
if((Object*) new_location->type != new_location)
Heap_CollectReference((Object**) &new_location->type, heap);
// Collect all of the references to
// extensions allocate using the GC'd
// heap.
Object_WalkExtensions(new_location,
Heap_CollectExtension, heap);
// Now collect all of the children.
Object_WalkReferences(new_location,
Heap_CollectReference, heap);
// Update the referer
*referer = new_location;
}
} }
+148 -148
View File
@@ -102,22 +102,22 @@ Object *Object_NewBuffer(int size, Heap *heap, Error *error)
unsigned char *body; unsigned char *body;
if(size > THRESHOLD) if(size > THRESHOLD)
{ {
body = malloc(sizeof(unsigned char) * size); body = malloc(sizeof(unsigned char) * size);
if(body == NULL) if(body == NULL)
{ {
Error_Report(error, 1, "No memory"); Error_Report(error, 1, "No memory");
return NULL; return NULL;
}
} }
}
else else
{ {
body = Heap_RawMalloc(heap, sizeof(unsigned char) * size, error); body = Heap_RawMalloc(heap, sizeof(unsigned char) * size, error);
if(body == NULL) if(body == NULL)
return NULL; return NULL;
} }
obj->size = size; obj->size = size;
obj->body = body; obj->body = body;
@@ -141,112 +141,112 @@ static _Bool buffer_free(Object *self, Error *error)
Object *Object_SliceBuffer(Object *buffer, int offset, int length, Heap *heap, Error *error) Object *Object_SliceBuffer(Object *buffer, int offset, int length, Heap *heap, Error *error)
{ {
if(buffer->type != &t_buffer && buffer->type != &t_buffer_slice) if(buffer->type != &t_buffer && buffer->type != &t_buffer_slice)
{ {
Error_Report(error, 0, "Not a buffer or a buffer slice"); Error_Report(error, 0, "Not a buffer or a buffer slice");
return NULL; return NULL;
} }
BufferSliceObject *slice; BufferSliceObject *slice;
if(buffer->type == &t_buffer) if(buffer->type == &t_buffer)
{
BufferObject *original = (BufferObject*) buffer;
if(offset == 0 && length == original->size)
return buffer;
slice = (BufferSliceObject*) Heap_Malloc(heap, &t_buffer_slice, error);
if(slice == NULL)
return NULL;
if(offset < 0 || offset >= original->size)
{ {
BufferObject *original = (BufferObject*) buffer; Error_Report(error, 0, "offset out of range");
return NULL;
if(offset == 0 && length == original->size)
return buffer;
slice = (BufferSliceObject*) Heap_Malloc(heap, &t_buffer_slice, error);
if(slice == NULL)
return NULL;
if(offset < 0 || offset >= original->size)
{
Error_Report(error, 0, "offset out of range");
return NULL;
}
if(length < 0 || length >= original->size)
{
Error_Report(error, 0, "length out of range");
return NULL;
}
if(offset + length > original->size)
{
Error_Report(error, 0, "slice out of range");
return NULL;
}
slice->sliced = original;
slice->offset = offset;
slice->length = length;
} }
if(length < 0 || length >= original->size)
{
Error_Report(error, 0, "length out of range");
return NULL;
}
if(offset + length > original->size)
{
Error_Report(error, 0, "slice out of range");
return NULL;
}
slice->sliced = original;
slice->offset = offset;
slice->length = length;
}
else else
{
assert(buffer->type == &t_buffer_slice);
slice = (BufferSliceObject*) Heap_Malloc(heap, &t_buffer_slice, error);
if(slice == NULL)
return NULL;
BufferSliceObject *original = (BufferSliceObject*) buffer;
if(offset < 0 || offset >= original->length)
{ {
assert(buffer->type == &t_buffer_slice); Error_Report(error, 0, "offset out of range");
return NULL;
slice = (BufferSliceObject*) Heap_Malloc(heap, &t_buffer_slice, error);
if(slice == NULL)
return NULL;
BufferSliceObject *original = (BufferSliceObject*) buffer;
if(offset < 0 || offset >= original->length)
{
Error_Report(error, 0, "offset out of range");
return NULL;
}
if(length < 0 || length >= original->length)
{
Error_Report(error, 0, "length out of range");
return NULL;
}
if(offset + length > original->length)
{
Error_Report(error, 0, "slice out of range");
return NULL;
}
slice->sliced = original->sliced;
slice->offset = original->offset + offset;
slice->length = length;
} }
if(length < 0 || length >= original->length)
{
Error_Report(error, 0, "length out of range");
return NULL;
}
if(offset + length > original->length)
{
Error_Report(error, 0, "slice out of range");
return NULL;
}
slice->sliced = original->sliced;
slice->offset = original->offset + offset;
slice->length = length;
}
return (Object*) slice; return (Object*) slice;
} }
void *Object_GetBufferAddrAndSize(Object *obj, int *size, Error *error) void *Object_GetBufferAddrAndSize(Object *obj, int *size, Error *error)
{ {
if(obj->type != &t_buffer && obj->type != &t_buffer_slice) if(obj->type != &t_buffer && obj->type != &t_buffer_slice)
{ {
Error_Report(error, 0, "Not a buffer or a buffer slice"); Error_Report(error, 0, "Not a buffer or a buffer slice");
return NULL; return NULL;
} }
if(obj->type == &t_buffer) if(obj->type == &t_buffer)
{ {
BufferObject *buffer = (BufferObject*) obj; BufferObject *buffer = (BufferObject*) obj;
if(size) if(size)
*size = buffer->size; *size = buffer->size;
return buffer->body; return buffer->body;
} }
else else
{ {
assert(obj->type == &t_buffer_slice); assert(obj->type == &t_buffer_slice);
BufferSliceObject *slice = (BufferSliceObject*) obj; BufferSliceObject *slice = (BufferSliceObject*) obj;
if(size) if(size)
*size = slice->length; *size = slice->length;
return slice->sliced->body + slice->offset; return slice->sliced->body + slice->offset;
} }
} }
static Object *buffer_select(Object *self, Object *key, Heap *heap, Error *error) static Object *buffer_select(Object *self, Object *key, Heap *heap, Error *error)
@@ -258,10 +258,10 @@ static Object *buffer_select(Object *self, Object *key, Heap *heap, Error *error
assert(error != NULL); assert(error != NULL);
if(!Object_IsInt(key)) if(!Object_IsInt(key))
{ {
Error_Report(error, 0, "Non integer key"); Error_Report(error, 0, "Non integer key");
return NULL; return NULL;
} }
int idx = Object_ToInt(key, error); int idx = Object_ToInt(key, error);
assert(error->occurred == 0); assert(error->occurred == 0);
@@ -269,10 +269,10 @@ static Object *buffer_select(Object *self, Object *key, Heap *heap, Error *error
BufferObject *buffer = (BufferObject*) self; BufferObject *buffer = (BufferObject*) self;
if(idx < 0 || idx >= buffer->size) if(idx < 0 || idx >= buffer->size)
{ {
Error_Report(error, 0, "Out of range index"); Error_Report(error, 0, "Out of range index");
return NULL; return NULL;
} }
unsigned char byte = buffer->body[idx]; unsigned char byte = buffer->body[idx];
@@ -288,10 +288,10 @@ static Object *slice_select(Object *self, Object *key, Heap *heap, Error *error)
assert(error != NULL); assert(error != NULL);
if(!Object_IsInt(key)) if(!Object_IsInt(key))
{ {
Error_Report(error, 0, "Non integer key"); Error_Report(error, 0, "Non integer key");
return NULL; return NULL;
} }
int idx = Object_ToInt(key, error); int idx = Object_ToInt(key, error);
assert(error->occurred == 0); assert(error->occurred == 0);
@@ -299,10 +299,10 @@ static Object *slice_select(Object *self, Object *key, Heap *heap, Error *error)
BufferSliceObject *slice = (BufferSliceObject*) self; BufferSliceObject *slice = (BufferSliceObject*) self;
if(idx < 0 || idx >= slice->length) if(idx < 0 || idx >= slice->length)
{ {
Error_Report(error, 0, "Out of range index"); Error_Report(error, 0, "Out of range index");
return NULL; return NULL;
} }
unsigned char byte = slice->sliced->body[slice->offset + idx]; unsigned char byte = slice->sliced->body[slice->offset + idx];
@@ -321,27 +321,27 @@ static _Bool buffer_insert(Object *self, Object *key, Object *val, Heap *heap, E
BufferObject *buffer = (BufferObject*) self; BufferObject *buffer = (BufferObject*) self;
if(!Object_IsInt(key)) if(!Object_IsInt(key))
{ {
Error_Report(error, 0, "Non integer key"); Error_Report(error, 0, "Non integer key");
return NULL; return NULL;
} }
int idx = Object_ToInt(key, error); int idx = Object_ToInt(key, error);
assert(error->occurred == 0); assert(error->occurred == 0);
if(idx < 0 || idx >= buffer->size) if(idx < 0 || idx >= buffer->size)
{ {
Error_Report(error, 0, "Out of range index"); Error_Report(error, 0, "Out of range index");
return NULL; return NULL;
} }
long long int qword = Object_ToInt(val, error); long long int qword = Object_ToInt(val, error);
if(qword > 255 || qword < 0) if(qword > 255 || qword < 0)
{ {
Error_Report(error, 0, "Not in range [0, 255]"); Error_Report(error, 0, "Not in range [0, 255]");
return NULL; return NULL;
} }
unsigned char byte = qword & 0xff; unsigned char byte = qword & 0xff;
@@ -364,27 +364,27 @@ static _Bool slice_insert(Object *self, Object *key, Object *val, Heap *heap, Er
BufferSliceObject *slice = (BufferSliceObject*) self; BufferSliceObject *slice = (BufferSliceObject*) self;
if(!Object_IsInt(key)) if(!Object_IsInt(key))
{ {
Error_Report(error, 0, "Non integer key"); Error_Report(error, 0, "Non integer key");
return NULL; return NULL;
} }
int idx = Object_ToInt(key, error); int idx = Object_ToInt(key, error);
assert(error->occurred == 0); assert(error->occurred == 0);
if(idx < 0 || idx >= slice->length) if(idx < 0 || idx >= slice->length)
{ {
Error_Report(error, 0, "Out of range index"); Error_Report(error, 0, "Out of range index");
return NULL; return NULL;
} }
long long int qword = Object_ToInt(val, error); long long int qword = Object_ToInt(val, error);
if(qword > 255 || qword < 0) if(qword > 255 || qword < 0)
{ {
Error_Report(error, 0, "Not in range [0, 255]"); Error_Report(error, 0, "Not in range [0, 255]");
return NULL; return NULL;
} }
unsigned char byte = qword & 0xff; unsigned char byte = qword & 0xff;
@@ -414,26 +414,26 @@ static void print_bytes(FILE *fp, unsigned char *addr, int size)
fprintf(fp, "["); fprintf(fp, "[");
for(int i = 0; i < size; i += 1) for(int i = 0; i < size; i += 1)
{ {
unsigned char byte, low, high; unsigned char byte, low, high;
byte = addr[i]; byte = addr[i];
low = byte & 0xf; low = byte & 0xf;
high = byte >> 4; high = byte >> 4;
assert(low < 16); assert(low < 16);
assert(high < 16); assert(high < 16);
char c1, c2; char c1, c2;
c1 = low < 10 ? low + '0' : low - 10 + 'A'; c1 = low < 10 ? low + '0' : low - 10 + 'A';
c2 = high < 10 ? high + '0' : high - 10 + 'A'; c2 = high < 10 ? high + '0' : high - 10 + 'A';
fprintf(fp, "%c%c", c2, c1); fprintf(fp, "%c%c", c2, c1);
if(i+1 < size) if(i+1 < size)
fprintf(fp, ", "); fprintf(fp, ", ");
} }
fprintf(fp, "]"); fprintf(fp, "]");
} }
+10 -10
View File
@@ -58,10 +58,10 @@ Object *Object_NewClosure(Object *parent, Object *new_map, Heap *heap, Error *er
return NULL; return NULL;
if(parent != NULL && parent->type != &t_closure) if(parent != NULL && parent->type != &t_closure)
{ {
Error_Report(error, 0, "Object is not a closure"); Error_Report(error, 0, "Object is not a closure");
return NULL; return NULL;
} }
obj->prev = (ClosureObject*) parent; obj->prev = (ClosureObject*) parent;
obj->vars = new_map; obj->vars = new_map;
@@ -76,14 +76,14 @@ static Object *select(Object *self, Object *key, Heap *heap, Error *err)
Object *selected = NULL; Object *selected = NULL;
while(closure != NULL && selected == NULL) while(closure != NULL && selected == NULL)
{ {
selected = Object_Select(closure->vars, key, heap, err); selected = Object_Select(closure->vars, key, heap, err);
if(err->occurred) if(err->occurred)
return NULL; return NULL;
closure = closure->prev; closure = closure->prev;
} }
return selected; return selected;
} }
+4 -4
View File
@@ -64,10 +64,10 @@ Object *Object_FromDIR(DIR *handle, Heap *heap, Error *error)
DIR *Object_ToDIR(Object *obj, Error *error) DIR *Object_ToDIR(Object *obj, Error *error)
{ {
if(!Object_IsDir(obj)) if(!Object_IsDir(obj))
{ {
Error_Report(error, 0, "Object is not a directory"); Error_Report(error, 0, "Object is not a directory");
return NULL; return NULL;
} }
return ((DirObject*) obj)->dir; return ((DirObject*) obj)->dir;
} }
+4 -4
View File
@@ -52,10 +52,10 @@ _Bool Object_IsFile(Object *obj)
FILE *Object_ToStream(Object *obj, Error *error) FILE *Object_ToStream(Object *obj, Error *error)
{ {
if(!Object_IsFile(obj)) if(!Object_IsFile(obj))
{ {
Error_Report(error, 0, "Object is not a file"); Error_Report(error, 0, "Object is not a file");
return NULL; return NULL;
} }
return ((FileObject*) obj)->fp; return ((FileObject*) obj)->fp;
} }
+35 -35
View File
@@ -89,10 +89,10 @@ static Object *copy(Object *self, Heap *heap, Error *err)
if(ls2 == NULL) return NULL; if(ls2 == NULL) return NULL;
for(int i = 0; i < ls->count; i += 1) for(int i = 0; i < ls->count; i += 1)
{ {
ls2->vals[i] = Object_Copy(ls->vals[i], heap, err); ls2->vals[i] = Object_Copy(ls->vals[i], heap, err);
if(err->occurred) return NULL; if(err->occurred) return NULL;
} }
ls2->count = ls->count; ls2->count = ls->count;
@@ -168,10 +168,10 @@ static Object *select(Object *self, Object *key, Heap *heap, Error *error)
assert(error != NULL); assert(error != NULL);
if(!Object_IsInt(key)) if(!Object_IsInt(key))
{ {
Error_Report(error, 0, "Non integer key"); Error_Report(error, 0, "Non integer key");
return NULL; return NULL;
} }
int idx = Object_ToInt(key, error); int idx = Object_ToInt(key, error);
assert(error->occurred == 0); assert(error->occurred == 0);
@@ -179,10 +179,10 @@ static Object *select(Object *self, Object *key, Heap *heap, Error *error)
ListObject *list = (ListObject*) self; ListObject *list = (ListObject*) self;
if(idx < 0 || idx >= list->count) if(idx < 0 || idx >= list->count)
{ {
Error_Report(error, 0, "Out of range index"); Error_Report(error, 0, "Out of range index");
return NULL; return NULL;
} }
return list->vals[idx]; return list->vals[idx];
} }
@@ -223,33 +223,33 @@ static _Bool insert(Object *self, Object *key, Object *val, Heap *heap, Error *e
ListObject *list = (ListObject*) self; ListObject *list = (ListObject*) self;
if(!Object_IsInt(key)) if(!Object_IsInt(key))
{ {
Error_Report(error, 0, "Non integer key"); Error_Report(error, 0, "Non integer key");
return NULL; return NULL;
} }
int idx = Object_ToInt(key, error); int idx = Object_ToInt(key, error);
assert(error->occurred == 0); assert(error->occurred == 0);
if(idx < 0 || idx > list->count) if(idx < 0 || idx > list->count)
{ {
Error_Report(error, 0, "Out of range index"); Error_Report(error, 0, "Out of range index");
return NULL; return NULL;
} }
if(idx == list->count) if(idx == list->count)
{ {
if(list->count == list->capacity) if(list->count == list->capacity)
if(!grow(list, heap, error)) if(!grow(list, heap, error))
return 0; return 0;
list->vals[list->count] = val; list->vals[list->count] = val;
list->count += 1; list->count += 1;
} }
else else
{ {
list->vals[idx] = val; list->vals[idx] = val;
} }
return 1; return 1;
} }
@@ -267,11 +267,11 @@ static void print(Object *self, FILE *fp)
fprintf(fp, "["); fprintf(fp, "[");
for(int i = 0; i < list->count; i += 1) for(int i = 0; i < list->count; i += 1)
{ {
Object_Print(list->vals[i], fp); Object_Print(list->vals[i], fp);
if(i+1 < list->count) if(i+1 < list->count)
fprintf(fp, ", "); fprintf(fp, ", ");
} }
fprintf(fp, "]"); fprintf(fp, "]");
} }
+115 -115
View File
@@ -75,22 +75,22 @@ static Object *copy(Object *self, Heap *heap, Error *err)
if(m2 == NULL) return NULL; if(m2 == NULL) return NULL;
for(int i = 0; i < m1->count; i += 1) for(int i = 0; i < m1->count; i += 1)
{ {
Object *key, *key_cpy; Object *key, *key_cpy;
Object *val, *val_cpy; Object *val, *val_cpy;
key = m1->keys[i]; key = m1->keys[i];
val = m1->vals[i]; val = m1->vals[i];
key_cpy = Object_Copy(key, heap, err); key_cpy = Object_Copy(key, heap, err);
if(key_cpy == NULL) return NULL; if(key_cpy == NULL) return NULL;
val_cpy = Object_Copy(val, heap, err); val_cpy = Object_Copy(val, heap, err);
if(val_cpy == NULL) return NULL; if(val_cpy == NULL) return NULL;
if(!Object_Insert(m2, key_cpy, val_cpy, heap, err)) if(!Object_Insert(m2, key_cpy, val_cpy, heap, err))
return NULL; return NULL;
} }
return (Object*) m2; return (Object*) m2;
} }
@@ -103,8 +103,8 @@ static int hash(Object *self)
// The hash of the map is the sum of the // The hash of the map is the sum of the
// hashes of each key and each item. // hashes of each key and each item.
for(int i = 0; i < m->count; i += 1) for(int i = 0; i < m->count; i += 1)
h += Object_Hash(m->keys[i]) h += Object_Hash(m->keys[i])
+ Object_Hash(m->vals[i]); + Object_Hash(m->vals[i]);
return h; return h;
} }
@@ -151,10 +151,10 @@ static void walk(Object *self, void (*callback)(Object **referer, void *userp),
MapObject *map = (MapObject*) self; MapObject *map = (MapObject*) self;
for(int i = 0; i < map->count; i += 1) for(int i = 0; i < map->count; i += 1)
{ {
callback(&map->keys[i], userp); callback(&map->keys[i], userp);
callback(&map->vals[i], userp); callback(&map->vals[i], userp);
} }
} }
static void walkexts(Object *self, void (*callback)(void **referer, unsigned int size, void *userp), void *userp) static void walkexts(Object *self, void (*callback)(void **referer, unsigned int size, void *userp), void *userp)
@@ -187,36 +187,36 @@ static Object *select(Object *self, Object *key, Heap *heap, Error *error)
int i = hash & mask; int i = hash & mask;
while(1) while(1)
{
int k = map->mapper[i];
if(k == -1)
{ {
int k = map->mapper[i]; // Empty slot.
// This key is not present.
if(k == -1) return NULL;
{
// Empty slot.
// This key is not present.
return NULL;
}
else
{
// Found an item.
// Is it the right one?
assert(k >= 0);
if(Object_Compare(key, map->keys[k], error))
// Found it!
return map->vals[k];
if(error->occurred)
// Key doesn't implement compare.
return 0;
// Not the one we wanted.
}
pert >>= 5;
i = (i * 5 + pert + 1) & mask;
} }
else
{
// Found an item.
// Is it the right one?
assert(k >= 0);
if(Object_Compare(key, map->keys[k], error))
// Found it!
return map->vals[k];
if(error->occurred)
// Key doesn't implement compare.
return 0;
// Not the one we wanted.
}
pert >>= 5;
i = (i * 5 + pert + 1) & mask;
}
UNREACHABLE; UNREACHABLE;
return NULL; return NULL;
@@ -237,42 +237,42 @@ static _Bool grow(MapObject *map, Heap *heap, Error *error)
return 0; return 0;
for(int i = 0; i < map->count; i += 1) for(int i = 0; i < map->count; i += 1)
{ {
keys[i] = map->keys[i]; keys[i] = map->keys[i];
vals[i] = map->vals[i]; vals[i] = map->vals[i];
} }
for(int i = 0; i < new_mapper_size; i += 1) for(int i = 0; i < new_mapper_size; i += 1)
mapper[i] = -1; mapper[i] = -1;
// Rehash everything. // Rehash everything.
for(int i = 0; i < map->count; i += 1) for(int i = 0; i < map->count; i += 1)
{
// This won't trigger an error because the key
// surely has a hash method since we already
// hashed it once.
int hash = Object_Hash(keys[i]);
int mask = new_mapper_size - 1;
int pert = hash;
int j = hash & mask;
while(1)
{ {
// This won't trigger an error because the key if(mapper[j] == -1)
// surely has a hash method since we already {
// hashed it once. // No collision.
int hash = Object_Hash(keys[i]); // Insert here.
mapper[j] = i;
break;
}
int mask = new_mapper_size - 1; // Collided. Find a new place.
int pert = hash; pert >>= 5;
j = (j * 5 + pert + 1) & mask;
int j = hash & mask;
while(1)
{
if(mapper[j] == -1)
{
// No collision.
// Insert here.
mapper[j] = i;
break;
}
// Collided. Find a new place.
pert >>= 5;
j = (j * 5 + pert + 1) & mask;
}
} }
}
// Done. // Done.
map->mapper = mapper; map->mapper = mapper;
@@ -304,45 +304,45 @@ static _Bool insert(Object *self, Object *key, Object *val, Heap *heap, Error *e
int i = hash & mask; int i = hash & mask;
while(1) while(1)
{
int k = map->mapper[i];
if(k == -1)
{ {
int k = map->mapper[i]; // Empty slot. We can insert it here.
Object *key_copy = Object_Copy(key, heap, error);
if(k == -1) if(key_copy == NULL)
{ return NULL;
// Empty slot. We can insert it here.
Object *key_copy = Object_Copy(key, heap, error);
if(key_copy == NULL) map->mapper[i] = map->count;
return NULL; map->keys[map->count] = key_copy;
map->vals[map->count] = val;
map->mapper[i] = map->count; map->count += 1;
map->keys[map->count] = key_copy; return 1;
map->vals[map->count] = val;
map->count += 1;
return 1;
}
else
{
assert(k >= 0);
if(Object_Compare(key, map->keys[k], error))
{
// Already inserted.
// Overwrite the value.
map->vals[k] = val;
return 1;
}
if(error->occurred)
// Key doesn't implement compare.
return 0;
// Collision.
}
pert >>= 5;
i = (i * 5 + pert + 1) & mask;
} }
else
{
assert(k >= 0);
if(Object_Compare(key, map->keys[k], error))
{
// Already inserted.
// Overwrite the value.
map->vals[k] = val;
return 1;
}
if(error->occurred)
// Key doesn't implement compare.
return 0;
// Collision.
}
pert >>= 5;
i = (i * 5 + pert + 1) & mask;
}
UNREACHABLE; UNREACHABLE;
return 0; return 0;
@@ -361,13 +361,13 @@ static void print(Object *self, FILE *fp)
fprintf(fp, "{"); fprintf(fp, "{");
for(int i = 0; i < map->count; i += 1) for(int i = 0; i < map->count; i += 1)
{ {
Object_Print(map->keys[i], fp); Object_Print(map->keys[i], fp);
fprintf(fp, ": "); fprintf(fp, ": ");
Object_Print(map->vals[i], fp); Object_Print(map->vals[i], fp);
if(i+1 < map->count) if(i+1 < map->count)
fprintf(fp, ", "); fprintf(fp, ", ");
} }
fprintf(fp, "}"); fprintf(fp, "}");
} }
+21 -18
View File
@@ -68,6 +68,9 @@ static TypeObject t_string = {
static int char_index_to_offset(StringObject *str, int idx) static int char_index_to_offset(StringObject *str, int idx)
{ {
if(str->count == str->bytes)
return idx;
// Iterate over a string to find the first byte of // Iterate over a string to find the first byte of
// the utf-8 character number [idx]. // the utf-8 character number [idx].
@@ -75,13 +78,13 @@ static int char_index_to_offset(StringObject *str, int idx)
last_code_len = 0; last_code_len = 0;
while(idx > 0) while(idx > 0)
{ {
last_code_len = utf8_sequence_to_utf32_codepoint(str->body + scanned_bytes, str->bytes - scanned_bytes, NULL); last_code_len = utf8_sequence_to_utf32_codepoint(str->body + scanned_bytes, str->bytes - scanned_bytes, NULL);
scanned_bytes += last_code_len; scanned_bytes += last_code_len;
idx -= 1; idx -= 1;
assert(scanned_bytes <= str->bytes); assert(scanned_bytes <= str->bytes);
} }
assert(idx == 0); assert(idx == 0);
return scanned_bytes; return scanned_bytes;
@@ -93,10 +96,10 @@ static Object *select(Object *self, Object *key, Heap *heap, Error *error)
assert(key != NULL && heap != NULL && error != NULL); assert(key != NULL && heap != NULL && error != NULL);
if(!Object_IsInt(key)) if(!Object_IsInt(key))
{ {
Error_Report(error, 0, "Non integer key"); Error_Report(error, 0, "Non integer key");
return NULL; return NULL;
} }
int idx = Object_ToInt(key, error); int idx = Object_ToInt(key, error);
assert(error->occurred == 0); assert(error->occurred == 0);
@@ -104,10 +107,10 @@ static Object *select(Object *self, Object *key, Heap *heap, Error *error)
StringObject *str = (StringObject*) self; StringObject *str = (StringObject*) self;
if(idx < 0 || idx >= str->count) if(idx < 0 || idx >= str->count)
{ {
Error_Report(error, 0, "Out of range index"); Error_Report(error, 0, "Out of range index");
return NULL; return NULL;
} }
int byteoffset = char_index_to_offset(str, idx); int byteoffset = char_index_to_offset(str, idx);
int codelength = utf8_sequence_to_utf32_codepoint(str->body + byteoffset, str->bytes - byteoffset, NULL); int codelength = utf8_sequence_to_utf32_codepoint(str->body + byteoffset, str->bytes - byteoffset, NULL);
@@ -143,10 +146,10 @@ Object *Object_FromString(const char *str, int len, Heap *heap, Error *error)
int count = utf8_strlen(str, len); int count = utf8_strlen(str, len);
if(count < 0) if(count < 0)
{ {
Error_Report(error, 0, "Invalid UTF-8 sequence"); Error_Report(error, 0, "Invalid UTF-8 sequence");
return NULL; return NULL;
} }
StringObject *strobj = Heap_Malloc(heap, &t_string, error); StringObject *strobj = Heap_Malloc(heap, &t_string, error);
+72 -72
View File
@@ -86,10 +86,10 @@ unsigned int Object_GetDeepSize(const Object *obj, Error *err)
assert(type); assert(type);
if(type->deepsize == NULL) if(type->deepsize == NULL)
{ {
Error_Report(err, 0, "Object %s doesn't implement %s", Object_GetName(obj), __func__); Error_Report(err, 0, "Object %s doesn't implement %s", Object_GetName(obj), __func__);
return 0; return 0;
} }
return type->deepsize(obj); return type->deepsize(obj);
} }
@@ -112,10 +112,10 @@ Object *Object_Copy(Object *obj, Heap *heap, Error *err)
assert(type != NULL); assert(type != NULL);
if(type->copy == NULL) if(type->copy == NULL)
{ {
Error_Report(err, 0, "Object %s doesn't implement %s", Object_GetName(obj), __func__); Error_Report(err, 0, "Object %s doesn't implement %s", Object_GetName(obj), __func__);
return NULL; return NULL;
} }
return type->copy(obj, heap, err); return type->copy(obj, heap, err);
} }
@@ -129,10 +129,10 @@ Object *Object_Call(Object *obj, Object **argv, unsigned int argc, Heap *heap, E
assert(type); assert(type);
if(type->call == NULL) if(type->call == NULL)
{ {
Error_Report(err, 0, "Object %s doesn't implement %s", Object_GetName(obj), __func__); Error_Report(err, 0, "Object %s doesn't implement %s", Object_GetName(obj), __func__);
return NULL; return NULL;
} }
return type->call(obj, argv, argc, heap, err); return type->call(obj, argv, argc, heap, err);
} }
@@ -160,10 +160,10 @@ Object *Object_Select(Object *coll, Object *key, Heap *heap, Error *err)
assert(type); assert(type);
if(type->select == NULL) if(type->select == NULL)
{ {
Error_Report(err, 0, "Object %s doesn't implement %s", Object_GetName(coll), __func__); Error_Report(err, 0, "Object %s doesn't implement %s", Object_GetName(coll), __func__);
return NULL; return NULL;
} }
return type->select(coll, key, heap, err); return type->select(coll, key, heap, err);
} }
@@ -178,10 +178,10 @@ Object *Object_Delete(Object *coll, Object *key, Heap *heap, Error *err)
assert(type); assert(type);
if(type->delete == NULL) if(type->delete == NULL)
{ {
Error_Report(err, 0, "Object %s doesn't implement %s", Object_GetName(coll), __func__); Error_Report(err, 0, "Object %s doesn't implement %s", Object_GetName(coll), __func__);
return NULL; return NULL;
} }
return type->delete(coll, key, heap, err); return type->delete(coll, key, heap, err);
} }
@@ -196,10 +196,10 @@ _Bool Object_Insert(Object *coll, Object *key, Object *val, Heap *heap, Error *e
assert(type); assert(type);
if(type->insert == NULL) if(type->insert == NULL)
{ {
Error_Report(err, 0, "Object %s doesn't implement %s", Object_GetName(coll), __func__); Error_Report(err, 0, "Object %s doesn't implement %s", Object_GetName(coll), __func__);
return 0; return 0;
} }
return type->insert(coll, key, val, heap, err); return type->insert(coll, key, val, heap, err);
} }
@@ -213,10 +213,10 @@ int Object_Count(Object *coll, Error *err)
assert(type); assert(type);
if(type->count == NULL) if(type->count == NULL)
{ {
Error_Report(err, 0, "Object %s doesn't implement %s", Object_GetName(coll), __func__); Error_Report(err, 0, "Object %s doesn't implement %s", Object_GetName(coll), __func__);
return -1; return -1;
} }
return type->count(coll); return type->count(coll);
} }
@@ -230,10 +230,10 @@ Object *Object_Next(Object *iter, Heap *heap, Error *err)
assert(type); assert(type);
if(type->next == NULL) if(type->next == NULL)
{ {
Error_Report(err, 0, "Object %s doesn't implement %s", Object_GetName(iter), __func__); Error_Report(err, 0, "Object %s doesn't implement %s", Object_GetName(iter), __func__);
return NULL; return NULL;
} }
return type->next(iter, heap, err); return type->next(iter, heap, err);
} }
@@ -247,10 +247,10 @@ Object *Object_Prev(Object *iter, Heap *heap, Error *err)
assert(type); assert(type);
if(type->prev == NULL) if(type->prev == NULL)
{ {
Error_Report(err, 0, "Object %s doesn't implement %s", Object_GetName(iter), __func__); Error_Report(err, 0, "Object %s doesn't implement %s", Object_GetName(iter), __func__);
return NULL; return NULL;
} }
return type->prev(iter, heap, err); return type->prev(iter, heap, err);
} }
@@ -289,19 +289,19 @@ long long int Object_ToInt(Object *obj, Error *err)
assert(obj); assert(obj);
if(!Object_IsInt(obj)) if(!Object_IsInt(obj))
{ {
Error_Report(err, 0, "Object is not an integer"); Error_Report(err, 0, "Object is not an integer");
return 0; return 0;
} }
const TypeObject *type = Object_GetType(obj); const TypeObject *type = Object_GetType(obj);
assert(type); assert(type);
if(type->to_int == NULL) if(type->to_int == NULL)
{ {
Error_Report(err, 0, "Object %s doesn't implement %s", Object_GetName(obj), __func__); Error_Report(err, 0, "Object %s doesn't implement %s", Object_GetName(obj), __func__);
return 0; return 0;
} }
return type->to_int(obj, err); return type->to_int(obj, err);
} }
@@ -312,19 +312,19 @@ _Bool Object_ToBool(Object *obj, Error *err)
assert(obj); assert(obj);
if(!Object_IsBool(obj)) if(!Object_IsBool(obj))
{ {
Error_Report(err, 0, "Object is not a boolean"); Error_Report(err, 0, "Object is not a boolean");
return 0; return 0;
} }
const TypeObject *type = Object_GetType(obj); const TypeObject *type = Object_GetType(obj);
assert(type); assert(type);
if(type->to_bool == NULL) if(type->to_bool == NULL)
{ {
Error_Report(err, 0, "Object %s doesn't implement %s", Object_GetName(obj), __func__); Error_Report(err, 0, "Object %s doesn't implement %s", Object_GetName(obj), __func__);
return 0; return 0;
} }
return type->to_bool(obj, err); return type->to_bool(obj, err);
} }
@@ -335,19 +335,19 @@ double Object_ToFloat(Object *obj, Error *err)
assert(obj); assert(obj);
if(!Object_IsFloat(obj)) if(!Object_IsFloat(obj))
{ {
Error_Report(err, 0, "Object is not a floating"); Error_Report(err, 0, "Object is not a floating");
return 0; return 0;
} }
const TypeObject *type = Object_GetType(obj); const TypeObject *type = Object_GetType(obj);
assert(type); assert(type);
if(type->to_float == NULL) if(type->to_float == NULL)
{ {
Error_Report(err, 0, "Object %s doesn't implement %s", Object_GetName(obj), __func__); Error_Report(err, 0, "Object %s doesn't implement %s", Object_GetName(obj), __func__);
return 0; return 0;
} }
return type->to_float(obj, err); return type->to_float(obj, err);
} }
@@ -358,19 +358,19 @@ const char *Object_ToString(Object *obj, int *size, Heap *heap, Error *err)
assert(obj != NULL); assert(obj != NULL);
if(!Object_IsString(obj)) if(!Object_IsString(obj))
{ {
Error_Report(err, 0, "Object is not a string"); Error_Report(err, 0, "Object is not a string");
return NULL; return NULL;
} }
const TypeObject *type = Object_GetType(obj); const TypeObject *type = Object_GetType(obj);
assert(type); assert(type);
if(type->to_string == NULL) if(type->to_string == NULL)
{ {
Error_Report(err, 0, "Object %s doesn't implement %s", Object_GetName(obj), __func__); Error_Report(err, 0, "Object %s doesn't implement %s", Object_GetName(obj), __func__);
return NULL; return NULL;
} }
return type->to_string(obj, size, heap, err); return type->to_string(obj, size, heap, err);
} }
@@ -385,10 +385,10 @@ _Bool Object_Compare(Object *obj1, Object *obj2, Error *error)
return 0; return 0;
if(obj1->type->op_eql == NULL) if(obj1->type->op_eql == NULL)
{ {
Error_Report(error, 0, "Object %s doesn't implement %s", Object_GetName(obj1), __func__); Error_Report(error, 0, "Object %s doesn't implement %s", Object_GetName(obj1), __func__);
return 0; return 0;
} }
return obj1->type->op_eql(obj1, obj2); return obj1->type->op_eql(obj1, obj2);
} }
+32 -34
View File
@@ -59,9 +59,7 @@ static void walk(Object *self, void (*callback)(Object **referer, void *userp),
static Object *call(Object *self, Object **argv, unsigned int argc, Heap *heap, Error *error) static Object *call(Object *self, Object **argv, unsigned int argc, Heap *heap, Error *error)
{ {
assert(self != NULL); assert(self != NULL && heap != NULL && error != NULL);
assert(heap != NULL);
assert(error != NULL);
FunctionObject *func = (FunctionObject*) self; FunctionObject *func = (FunctionObject*) self;
@@ -76,36 +74,36 @@ static Object *call(Object *self, Object **argv, unsigned int argc, Heap *heap,
int expected_argc = func->argc; int expected_argc = func->argc;
if(expected_argc < (int) argc) if(expected_argc < (int) argc)
{ {
// Nothing to be done. By using // Nothing to be done. By using
// the right argc the additional // the right argc the additional
// arguments are ignored implicitly. // arguments are ignored implicitly.
argv2 = argv; argv2 = argv;
} }
else if(expected_argc > (int) argc) else if(expected_argc > (int) argc)
{
// Some arguments are missing.
argv2 = malloc(sizeof(Object*) * expected_argc);
if(argv2 == NULL)
{ {
// Some arguments are missing. Error_Report(error, 1, "No memory");
argv2 = malloc(sizeof(Object*) * expected_argc); return NULL;
if(argv2 == NULL)
{
Error_Report(error, 1, "No memory");
return NULL;
}
// Copy the provided arguments.
for(int i = 0; i < (int) argc; i += 1)
argv2[i] = argv[i];
// Set the unspecified arguments to none.
for(int i = argc; i < expected_argc; i += 1)
{
argv2[i] = Object_NewNone(heap, error);
if(argv2[i] == NULL)
return 0;
}
} }
// Copy the provided arguments.
for(int i = 0; i < (int) argc; i += 1)
argv2[i] = argv[i];
// Set the unspecified arguments to none.
for(int i = argc; i < expected_argc; i += 1)
{
argv2[i] = Object_NewNone(heap, error);
if(argv2[i] == NULL)
return 0;
}
}
else else
// The right amount of arguments was provided. // The right amount of arguments was provided.
argv2 = argv; argv2 = argv;
@@ -176,10 +174,10 @@ Object *Object_FromNojaFunction(Runtime *runtime, Executable *exe, int index, in
Executable *exe_copy = Executable_Copy(exe); Executable *exe_copy = Executable_Copy(exe);
if(exe_copy == NULL) if(exe_copy == NULL)
{ {
Error_Report(error, 1, "Failed to copy executable"); Error_Report(error, 1, "Failed to copy executable");
return NULL; return NULL;
} }
func->runtime = runtime; func->runtime = runtime;
func->exe = exe_copy; func->exe = exe_copy;
+38 -38
View File
@@ -64,48 +64,48 @@ static Object *call(Object *self, Object **argv, unsigned int argc, Heap *heap,
int expected_argc = func->argc; int expected_argc = func->argc;
if(expected_argc < 0 || expected_argc == (int) argc) if(expected_argc < 0 || expected_argc == (int) argc)
{ {
// The function is variadic or the right // The function is variadic or the right
// amount of arguments was provided. // amount of arguments was provided.
argv2 = argv; argv2 = argv;
argc2 = argc; argc2 = argc;
} }
else if(expected_argc < (int) argc) else if(expected_argc < (int) argc)
{ {
// Nothing to be done. By using // Nothing to be done. By using
// the right argc the additional // the right argc the additional
// arguments are ignored implicitly. // arguments are ignored implicitly.
argv2 = argv; argv2 = argv;
argc2 = expected_argc; argc2 = expected_argc;
} }
else if(expected_argc > (int) argc) else if(expected_argc > (int) argc)
{
// Some arguments are missing.
argv2 = malloc(sizeof(Object*) * expected_argc);
argc2 = expected_argc;
if(argv2 == NULL)
{ {
// Some arguments are missing. Error_Report(error, 1, "No memory");
argv2 = malloc(sizeof(Object*) * expected_argc); return NULL;
argc2 = expected_argc;
if(argv2 == NULL)
{
Error_Report(error, 1, "No memory");
return NULL;
}
// Copy the provided arguments.
for(int i = 0; i < (int) argc; i += 1)
argv2[i] = argv[i];
// Set the unspecified arguments to none.
for(int i = argc; i < expected_argc; i += 1)
{
argv2[i] = Object_NewNone(heap, error);
if(argv2[i] == NULL)
{
free(argv2);
return NULL;
}
}
} }
// Copy the provided arguments.
for(int i = 0; i < (int) argc; i += 1)
argv2[i] = argv[i];
// Set the unspecified arguments to none.
for(int i = argc; i < expected_argc; i += 1)
{
argv2[i] = Object_NewNone(heap, error);
if(argv2[i] == NULL)
{
free(argv2);
return NULL;
}
}
}
else UNREACHABLE; else UNREACHABLE;
assert(func->callback != NULL); assert(func->callback != NULL);
+15 -15
View File
@@ -120,22 +120,22 @@ static Object *select(Object *self, Object *key, Heap *heap, Error *error)
for(int i = 0; map->slots[i].name != NULL; i += 1) for(int i = 0; map->slots[i].name != NULL; i += 1)
if(!strcmp(name, map->slots[i].name)) if(!strcmp(name, map->slots[i].name))
{
StaticMapSlot slot = map->slots[i];
Object *obj;
switch(slot.kind)
{ {
StaticMapSlot slot = map->slots[i]; case SM_BOOL: return Object_FromBool(slot.as_bool, heap, error);
Object *obj; case SM_INT: return Object_FromInt(slot.as_int, heap, error);
switch(slot.kind) case SM_FLOAT: return Object_FromFloat(slot.as_float, heap, error);
{ case SM_FUNCT: return Object_FromNativeFunction(map->runt, slot.as_funct, slot.argc, heap, error);
case SM_BOOL: return Object_FromBool(slot.as_bool, heap, error); case SM_STRING: return Object_FromString(slot.as_string, slot.length, heap, error);
case SM_INT: return Object_FromInt(slot.as_int, heap, error); case SM_SMAP: return Object_NewStaticMap(slot.as_smap, map->runt, error);
case SM_FLOAT: return Object_FromFloat(slot.as_float, heap, error); case SM_NONE: return Object_NewNone(heap, error);
case SM_FUNCT: return Object_FromNativeFunction(map->runt, slot.as_funct, slot.argc, heap, error); case SM_TYPE: return (Object*) slot.as_type;
case SM_STRING: return Object_FromString(slot.as_string, slot.length, heap, error); default: assert(0); break;
case SM_SMAP: return Object_NewStaticMap(slot.as_smap, map->runt, error);
case SM_NONE: return Object_NewNone(heap, error);
case SM_TYPE: return (Object*) slot.as_type;
default: assert(0); break;
}
return obj;
} }
return obj;
}
return NULL; return NULL;
} }
+906 -907
View File
File diff suppressed because it is too large Load Diff
+32 -32
View File
@@ -80,11 +80,11 @@ BPAlloc *BPAlloc_Init2(int first_size, int chunk_size,
first_size = chunk_size; first_size = chunk_size;
if(fn_malloc == NULL) if(fn_malloc == NULL)
{ {
userp = NULL; userp = NULL;
fn_malloc = default_fn_malloc; fn_malloc = default_fn_malloc;
fn_free = default_fn_free; fn_free = default_fn_free;
} }
void *temp = fn_malloc(userp, sizeof(BPAlloc) + sizeof(BPAllocChunk) + first_size + PADDING); void *temp = fn_malloc(userp, sizeof(BPAlloc) + sizeof(BPAllocChunk) + first_size + PADDING);
@@ -124,11 +124,11 @@ BPAlloc *BPAlloc_Init3(void *mem, int mem_size, int chunk_size,
chunk_size = CHUNK_SIZE; chunk_size = CHUNK_SIZE;
if(fn_malloc == NULL) if(fn_malloc == NULL)
{ {
userp = NULL; userp = NULL;
fn_malloc = default_fn_malloc; fn_malloc = default_fn_malloc;
fn_free = default_fn_free; fn_free = default_fn_free;
} }
int required = sizeof(BPAlloc) int required = sizeof(BPAlloc)
+ sizeof(BPAllocChunk) + sizeof(BPAllocChunk)
@@ -170,14 +170,14 @@ void BPAlloc_Free(BPAlloc *alloc)
BPAllocChunk *chunk = alloc->tail; BPAllocChunk *chunk = alloc->tail;
while(chunk->prev) while(chunk->prev)
{ {
BPAllocChunk *prev = chunk->prev; BPAllocChunk *prev = chunk->prev;
if(alloc->fn_free) if(alloc->fn_free)
alloc->fn_free(alloc->userp, chunk); alloc->fn_free(alloc->userp, chunk);
chunk = prev; chunk = prev;
} }
if(!(alloc->flags & FG_STATIC)) if(!(alloc->flags & FG_STATIC))
if(alloc->fn_free) if(alloc->fn_free)
@@ -195,26 +195,26 @@ void *BPAlloc_Malloc(BPAlloc *alloc, int req_size)
alloc->used = (alloc->used & ~7) + 8; alloc->used = (alloc->used & ~7) + 8;
if(alloc->used + req_size > alloc->size) if(alloc->used + req_size > alloc->size)
{ {
// If the chunk size is lower than the // If the chunk size is lower than the
// requested size, then set the chunk // requested size, then set the chunk
// size to the requested size. // size to the requested size.
int chunk_size = MAX(alloc->minsize, req_size + PADDING); int chunk_size = MAX(alloc->minsize, req_size + PADDING);
assert(alloc->fn_malloc != NULL); assert(alloc->fn_malloc != NULL);
BPAllocChunk *chunk = alloc->fn_malloc(alloc->userp, sizeof(BPAllocChunk) + chunk_size); BPAllocChunk *chunk = alloc->fn_malloc(alloc->userp, sizeof(BPAllocChunk) + chunk_size);
if(chunk == NULL) if(chunk == NULL)
return NULL; return NULL;
chunk->prev = alloc->tail; chunk->prev = alloc->tail;
alloc->tail = chunk; alloc->tail = chunk;
alloc->size = chunk_size; alloc->size = chunk_size;
alloc->used = PADDING; alloc->used = PADDING;
if(alloc->used & 7) if(alloc->used & 7)
alloc->used = (alloc->used & ~7) + 8; alloc->used = (alloc->used & ~7) + 8;
} }
void *addr = alloc->tail->body + alloc->used; void *addr = alloc->tail->body + alloc->used;
+45 -45
View File
@@ -109,42 +109,42 @@ _Bool BucketList_Append(BucketList *blist, const void *data, int size)
int not_copied_yet = size; int not_copied_yet = size;
while(not_copied_yet > 0) while(not_copied_yet > 0)
{
// Copy until there's nothing left
// or until the current bucket is
// full. If the bucket is already
// full, add another one.
int left_in_bucket = blist->tail->size - blist->tail->used;
if(left_in_bucket == 0)
{ {
// Copy until there's nothing left Bucket *new_bucket = make_bucket(blist->alloc, MIN_BUCKET_SIZE);
// or until the current bucket is
// full. If the bucket is already
// full, add another one.
int left_in_bucket = blist->tail->size - blist->tail->used; if(new_bucket == NULL)
return 0;
if(left_in_bucket == 0) append_bucket(blist, new_bucket);
{
Bucket *new_bucket = make_bucket(blist->alloc, MIN_BUCKET_SIZE);
if(new_bucket == NULL)
return 0;
append_bucket(blist, new_bucket);
}
// Decide how much to copy.
int copying = MIN(not_copied_yet, left_in_bucket);
// Copy into the bucket.
{
char *dst = blist->tail->body + blist->tail->used;
if(data == NULL)
memset(dst, 0, copying);
else
memcpy(dst, data + size - not_copied_yet, copying);
blist->tail->used += copying;
}
not_copied_yet -= copying;
} }
// Decide how much to copy.
int copying = MIN(not_copied_yet, left_in_bucket);
// Copy into the bucket.
{
char *dst = blist->tail->body + blist->tail->used;
if(data == NULL)
memset(dst, 0, copying);
else
memcpy(dst, data + size - not_copied_yet, copying);
blist->tail->used += copying;
}
not_copied_yet -= copying;
}
blist->size += size; blist->size += size;
return 1; return 1;
} }
@@ -158,16 +158,16 @@ void *BucketList_Append2(BucketList *blist, const void *data, int size)
// current bucket, add another one with // current bucket, add another one with
// enough space. // enough space.
if(blist->tail->used + size > blist->tail->size) if(blist->tail->used + size > blist->tail->size)
{ {
int bucket_size = MAX(MIN_BUCKET_SIZE, size); int bucket_size = MAX(MIN_BUCKET_SIZE, size);
Bucket *new_bucket = make_bucket(blist->alloc, bucket_size); Bucket *new_bucket = make_bucket(blist->alloc, bucket_size);
if(new_bucket == NULL) if(new_bucket == NULL)
return 0; return 0;
append_bucket(blist, new_bucket); append_bucket(blist, new_bucket);
} }
void *addr = blist->tail->body + blist->tail->used; void *addr = blist->tail->body + blist->tail->used;
@@ -195,15 +195,15 @@ void BucketList_Copy(BucketList *blist, void *dest, int len)
Bucket *bucket = blist->head; Bucket *bucket = blist->head;
while(bucket && copied < len) while(bucket && copied < len)
{ {
int copying = MIN(len - copied, bucket->used); int copying = MIN(len - copied, bucket->used);
assert(copying >= 0); assert(copying >= 0);
memcpy((char*) dest + copied, bucket->body, copying); memcpy((char*) dest + copied, bucket->body, copying);
copied += copying; copied += copying;
bucket = bucket->next; bucket = bucket->next;
} }
} }
BPAlloc *BucketList_GetAlloc(BucketList *blist) BPAlloc *BucketList_GetAlloc(BucketList *blist)
+18 -18
View File
@@ -87,29 +87,29 @@ void _Error_Report2(Error *err, _Bool internal,
assert(p > -1); assert(p > -1);
if((unsigned int) p > sizeof(err->message2)-1) if((unsigned int) p > sizeof(err->message2)-1)
{ {
char *temp = malloc(p+1); char *temp = malloc(p+1);
if(temp == NULL) if(temp == NULL)
{
err->truncated = 1;
err->message = err->message2;
err->length = sizeof(err->message2)-1;
}
else
{
snprintf(temp, p+1, fmt, va2);
err->truncated = 0;
err->message = temp;
err->length = p;
}
}
else
{ {
err->truncated = 0; err->truncated = 1;
err->message = err->message2; err->message = err->message2;
err->length = sizeof(err->message2)-1;
}
else
{
snprintf(temp, p+1, fmt, va2);
err->truncated = 0;
err->message = temp;
err->length = p; err->length = p;
} }
}
else
{
err->truncated = 0;
err->message = err->message2;
err->length = p;
}
va_end(va2); va_end(va2);
+21 -21
View File
@@ -87,14 +87,14 @@ void Promise_Resolve(Promise *promise, const void *data, int size)
Gap *gap = promise->gaps; Gap *gap = promise->gaps;
while(gap) while(gap)
{ {
memcpy(gap->dest, data, size); memcpy(gap->dest, data, size);
if(gap->callback) if(gap->callback)
gap->callback(gap->userp); gap->callback(gap->userp);
gap = gap->next; gap = gap->next;
} }
promise->gaps = NULL; promise->gaps = NULL;
} }
@@ -112,25 +112,25 @@ _Bool Promise_Subscribe2(Promise *promise, void *dest, void *userp, void (*callb
assert(dest != NULL); assert(dest != NULL);
if(promise->set == 0) if(promise->set == 0)
{ {
Gap *gap = BPAlloc_Malloc(promise->alloc, sizeof(Gap)); Gap *gap = BPAlloc_Malloc(promise->alloc, sizeof(Gap));
if(gap == NULL) if(gap == NULL)
return 0; return 0;
gap->next = promise->gaps; gap->next = promise->gaps;
gap->dest = dest; gap->dest = dest;
gap->userp = userp; gap->userp = userp;
gap->callback = callback; gap->callback = callback;
promise->gaps = gap; promise->gaps = gap;
} }
else else
{ {
memcpy(dest, promise->body, promise->size); memcpy(dest, promise->body, promise->size);
if(callback) if(callback)
callback(userp); callback(userp);
} }
return 1; return 1;
} }
+37 -37
View File
@@ -86,36 +86,36 @@ Source *Source_FromFile(const char *file, Error *error)
fp = fopen(file, "rb"); fp = fopen(file, "rb");
if(fp == NULL) if(fp == NULL)
{ {
if(errno == ENOENT) if(errno == ENOENT)
Error_Report(error, 0, "File \"%s\" doesn't exist", file); Error_Report(error, 0, "File \"%s\" doesn't exist", file);
else else
Error_Report(error, 1, "Call to fopen failed (%s, errno = %d)", strerror(errno), errno); Error_Report(error, 1, "Call to fopen failed (%s, errno = %d)", strerror(errno), errno);
return NULL; return NULL;
} }
if(fseek(fp, 0, SEEK_END)) if(fseek(fp, 0, SEEK_END))
{ {
Error_Report(error, 1, "Call to fseek failed (%s, errno = %d)", strerror(errno), errno); Error_Report(error, 1, "Call to fseek failed (%s, errno = %d)", strerror(errno), errno);
fclose(fp); fclose(fp);
return NULL; return NULL;
} }
size = ftell(fp); size = ftell(fp);
if(size < 0) if(size < 0)
{ {
Error_Report(error, 1, "Call to ftell failed (%s, errno = %d)", strerror(errno), errno); Error_Report(error, 1, "Call to ftell failed (%s, errno = %d)", strerror(errno), errno);
fclose(fp); fclose(fp);
return NULL; return NULL;
} }
if(fseek(fp, 0, SEEK_SET)) if(fseek(fp, 0, SEEK_SET))
{ {
Error_Report(error, 1, "Call to fseek failed (%s, errno = %d)", strerror(errno), errno); Error_Report(error, 1, "Call to fseek failed (%s, errno = %d)", strerror(errno), errno);
fclose(fp); fclose(fp);
return NULL; return NULL;
} }
} }
// Allocate the source structure. // Allocate the source structure.
@@ -126,11 +126,11 @@ Source *Source_FromFile(const char *file, Error *error)
s = malloc(sizeof(Source) + namel + size + 2); s = malloc(sizeof(Source) + namel + size + 2);
if(s == NULL) if(s == NULL)
{ {
Error_Report(error, 1, "No memory"); Error_Report(error, 1, "No memory");
fclose(fp); fclose(fp);
return NULL; return NULL;
} }
s->name = (char*) (s + 1); s->name = (char*) (s + 1);
s->body = s->name + namel + 1; s->body = s->name + namel + 1;
@@ -146,12 +146,12 @@ Source *Source_FromFile(const char *file, Error *error)
int p = fread(s->body, 1, size, fp); int p = fread(s->body, 1, size, fp);
if(p != size) if(p != size)
{ {
Error_Report(error, 1, "Call to fread failed, %d bytes out of %d were read (%s, errno = %d)", p, size, strerror(errno), errno); Error_Report(error, 1, "Call to fread failed, %d bytes out of %d were read (%s, errno = %d)", p, size, strerror(errno), errno);
fclose(fp); fclose(fp);
free(s); free(s);
return NULL; return NULL;
} }
s->body[s->size] = '\0'; s->body[s->size] = '\0';
} }
@@ -172,10 +172,10 @@ Source *Source_FromString(const char *name, const char *body, int size, Error *e
void *memory = malloc(sizeof(Source) + namel + size + 2); void *memory = malloc(sizeof(Source) + namel + size + 2);
if(memory == NULL) if(memory == NULL)
{ {
Error_Report(error, 1, "No memory"); Error_Report(error, 1, "No memory");
return NULL; return NULL;
} }
Source *s = memory; Source *s = memory;
s->name = (char*) (s + 1); s->name = (char*) (s + 1);
+8 -8
View File
@@ -135,15 +135,15 @@ _Bool Stack_Push(Stack *s, void *item)
Stack *Stack_Copy(Stack *s, _Bool readonly) Stack *Stack_Copy(Stack *s, _Bool readonly)
{ {
if(Stack_IsReadOnlyCopy(s)) if(Stack_IsReadOnlyCopy(s))
{ {
// Reference is readonly, // Reference is readonly,
// so the copy must be // so the copy must be
// readonly. // readonly.
readonly = 1; readonly = 1;
// Remove readonly bit. // Remove readonly bit.
s = unmark(s); s = unmark(s);
} }
s->refs += 1; s->refs += 1;
+110 -110
View File
@@ -60,46 +60,46 @@
int utf8_sequence_from_utf32_codepoint(char *utf8_data, int nbytes, uint32_t utf32_code) int utf8_sequence_from_utf32_codepoint(char *utf8_data, int nbytes, uint32_t utf32_code)
{ {
if(utf32_code < 128) if(utf32_code < 128)
{ {
if(nbytes < 1) if(nbytes < 1)
return -1; return -1;
utf8_data[0] = utf32_code; utf8_data[0] = utf32_code;
return 1; return 1;
} }
if(utf32_code < 2048) if(utf32_code < 2048)
{ {
if(nbytes < 2) if(nbytes < 2)
return -1; return -1;
utf8_data[0] = 0xc0 | (utf32_code >> 6); utf8_data[0] = 0xc0 | (utf32_code >> 6);
utf8_data[1] = 0x80 | (utf32_code & 0x3f); utf8_data[1] = 0x80 | (utf32_code & 0x3f);
return 2; return 2;
} }
if(utf32_code < 65536) if(utf32_code < 65536)
{ {
if(nbytes < 3) if(nbytes < 3)
return -1; return -1;
utf8_data[0] = 0xe0 | (utf32_code >> 12); utf8_data[0] = 0xe0 | (utf32_code >> 12);
utf8_data[1] = 0x80 | ((utf32_code >> 6) & 0x3f); utf8_data[1] = 0x80 | ((utf32_code >> 6) & 0x3f);
utf8_data[2] = 0x80 | (utf32_code & 0x3f); utf8_data[2] = 0x80 | (utf32_code & 0x3f);
return 3; return 3;
} }
if(utf32_code <= 0x10ffff) if(utf32_code <= 0x10ffff)
{ {
if(nbytes < 4) if(nbytes < 4)
return -1; return -1;
utf8_data[0] = 0xf0 | (utf32_code >> 18); utf8_data[0] = 0xf0 | (utf32_code >> 18);
utf8_data[1] = 0x80 | ((utf32_code >> 12) & 0x3f); utf8_data[1] = 0x80 | ((utf32_code >> 12) & 0x3f);
utf8_data[2] = 0x80 | ((utf32_code >> 6) & 0x3f); utf8_data[2] = 0x80 | ((utf32_code >> 6) & 0x3f);
utf8_data[3] = 0x80 | (utf32_code & 0x3f); utf8_data[3] = 0x80 | (utf32_code & 0x3f);
return 4; return 4;
} }
// Code is out of range for UTF-8. // Code is out of range for UTF-8.
return -1; return -1;
@@ -148,71 +148,71 @@ int utf8_sequence_to_utf32_codepoint(const char *utf8_data, int nbytes, uint32_t
return -1; return -1;
if(utf8_data[0] & 0x80) if(utf8_data[0] & 0x80)
{ {
// May be UTF-8. // May be UTF-8.
if((unsigned char) utf8_data[0] >= 0xF0) if((unsigned char) utf8_data[0] >= 0xF0)
{ {
// 4 bytes. // 4 bytes.
// 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx // 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
if(nbytes < 4) if(nbytes < 4)
return -1; return -1;
uint32_t temp uint32_t temp
= (((uint32_t) utf8_data[0] & 0x07) << 18) = (((uint32_t) utf8_data[0] & 0x07) << 18)
| (((uint32_t) utf8_data[1] & 0x3f) << 12) | (((uint32_t) utf8_data[1] & 0x3f) << 12)
| (((uint32_t) utf8_data[2] & 0x3f) << 6) | (((uint32_t) utf8_data[2] & 0x3f) << 6)
| (((uint32_t) utf8_data[3] & 0x3f)); | (((uint32_t) utf8_data[3] & 0x3f));
if(temp > 0x10ffff) if(temp > 0x10ffff)
return -1; return -1;
*utf32_code = temp; *utf32_code = temp;
return 4; return 4;
} }
if((unsigned char) utf8_data[0] >= 0xE0) if((unsigned char) utf8_data[0] >= 0xE0)
{ {
// 3 bytes. // 3 bytes.
// 1110xxxx 10xxxxxx 10xxxxxx // 1110xxxx 10xxxxxx 10xxxxxx
if(nbytes < 3) if(nbytes < 3)
return -1; return -1;
uint32_t temp uint32_t temp
= (((uint32_t) utf8_data[0] & 0x0f) << 12) = (((uint32_t) utf8_data[0] & 0x0f) << 12)
| (((uint32_t) utf8_data[1] & 0x3f) << 6) | (((uint32_t) utf8_data[1] & 0x3f) << 6)
| (((uint32_t) utf8_data[2] & 0x3f)); | (((uint32_t) utf8_data[2] & 0x3f));
if(temp > 0x10ffff) if(temp > 0x10ffff)
return -1; return -1;
*utf32_code = temp; *utf32_code = temp;
return 3; return 3;
} }
if((unsigned char) utf8_data[0] >= 0xC0) if((unsigned char) utf8_data[0] >= 0xC0)
{ {
// 2 bytes. // 2 bytes.
// 110xxxxx 10xxxxxx // 110xxxxx 10xxxxxx
if(nbytes < 2) if(nbytes < 2)
return -1; return -1;
*utf32_code *utf32_code
= (((uint32_t) utf8_data[0] & 0x1f) << 6) = (((uint32_t) utf8_data[0] & 0x1f) << 6)
| (((uint32_t) utf8_data[1] & 0x3f)); | (((uint32_t) utf8_data[1] & 0x3f));
assert(*utf32_code <= 0x10ffff); assert(*utf32_code <= 0x10ffff);
return 2; return 2;
} }
// 1 byte // 1 byte
// 10xxxxxx // 10xxxxxx
*utf32_code = (uint32_t) utf8_data[0] & 0x3f; *utf32_code = (uint32_t) utf8_data[0] & 0x3f;
return 1; return 1;
} }
// It's ASCII // It's ASCII
// 0xxxxxxx // 0xxxxxxx
@@ -255,40 +255,40 @@ int utf8_strlen(const char *utf8_data, int nbytes)
int i = 0; int i = 0;
while(i < nbytes) while(i < nbytes)
{ {
#if ASSUME_ASCII #if ASSUME_ASCII
{ {
int ASCII_start = i; int ASCII_start = i;
// Skip through ASCII // Skip through ASCII
while(i < nbytes && (utf8_data[i] & 0x80) == 0) while(i < nbytes && (utf8_data[i] & 0x80) == 0)
i += 1; i += 1;
int ASCII_end = i; int ASCII_end = i;
len += (ASCII_end - ASCII_start); len += (ASCII_end - ASCII_start);
// Either we scanned through all of the // Either we scanned through all of the
// string, or we encountered some unicode. // string, or we encountered some unicode.
if(i == nbytes) if(i == nbytes)
// String ended. // String ended.
break; break;
} }
#endif #endif
// Found unicode. // Found unicode.
{ {
int n = utf8_sequence_to_utf32_codepoint(utf8_data + i, nbytes - i, NULL); int n = utf8_sequence_to_utf32_codepoint(utf8_data + i, nbytes - i, NULL);
if(n < 1) if(n < 1)
return -1; return -1;
i += n; i += n;
len += 1; len += 1;
}
} }
}
return len; return len;
} }
@@ -347,11 +347,11 @@ int utf8_prev(const char *utf8_data, int nbytes, int idx, uint32_t *utf32_code)
// to go faster. // to go faster.
if((utf8_data[tail] & 0x80) == 0) if((utf8_data[tail] & 0x80) == 0)
{ {
if(utf32_code) if(utf32_code)
*utf32_code = utf8_data[tail]; *utf32_code = utf8_data[tail];
return tail; return tail;
} }
} }
#endif #endif
@@ -362,11 +362,11 @@ int utf8_prev(const char *utf8_data, int nbytes, int idx, uint32_t *utf32_code)
idx -= 1; idx -= 1;
if(idx == -1) if(idx == -1)
{ {
// No head sequence byte was found, // No head sequence byte was found,
// so this isn't valid UTF-8. // so this isn't valid UTF-8.
return -1; return -1;
} }
// The index of the head byte. // The index of the head byte.
int head = idx; int head = idx;