reorganized build-ins and implement a circular queue as an example

This commit is contained in:
cozis
2022-08-18 19:01:26 +02:00
parent b5b3a3e315
commit 782985e8b7
36 changed files with 486 additions and 259 deletions
+7
View File
@@ -142,6 +142,13 @@ ls[0 + 2]; # OK!
ls[true or false]; # Runtime error!!
```
To append a value to a list, increasing it's size, you can just insert the new value at the first unused position (which will have index equal to the current list size). As we'll see in the built-in chapter, to get the size of a list one can use the `count` function. Which means appending to a list can be done like this:
```py
ls = [1, 2, 3];
ls[count(ls)] = 4;
# Now ls is [1, 2, 3, 4]
```
## Maps
Maps are defined as a list of key-value pairs:
```py
+44
View File
@@ -0,0 +1,44 @@
# Built-Ins
int
bool
float
String
print
import
unicode
type
unicode
chr
count
input
assert
error
string.cat
buffer.new
buffer.sliceUp
buffer.toString
math.PI
math.E
math.floor
math.ceil
math.cos
math.sin
math.tan
math.acos
math.asin
math.atan
math.atan2
math.exp
math.log
math.log10
math.pow
math.sqrt
files.READ
files.WRITE
files.APPEND
files.openFile
files.openDir
files.nextDirItem
files.read
files.write
+48
View File
@@ -0,0 +1,48 @@
fun dummy() {}
Func = type(dummy);
NFunc = type(print); # The function type is not a build-in at the moment,
# but we can define it manually.
fun copyList(list: List) {
list2 = [];
i = 0;
while i < count(list): {
list2[i] = list[i];
i = i+1;
}
return list2;
}
fun numericLess(a: int | float, b: int | float)
return a < b;
fun bubbleSort(list: List, less: NFunc | Func = numericLess) {
list2 = copyList(list);
do {
swapped = false;
i = 0;
while i < count(list2)-1 and not swapped: {
if less(list2[i+1], list2[i]): {
swapped = true;
tmp = list2[i+1];
list2[i+1] = list2[i];
list2[i] = tmp;
}
i = i + 1;
}
} while swapped;
return list2;
}
unordered_list = [3, 2, 1, 6, -2];
ordered_list = bubbleSort(unordered_list);
print(ordered_list, '\n'); # [-2, 1, 2, 3, 6]
-10
View File
@@ -1,10 +0,0 @@
fun x(a, b, c)
print('a = ', a, '\nb = ', b, '\nc = ', c, '\n\n');
x(1, 2, 3, 4, 5);
x(1, 2, 3, 4);
x(1, 2, 3);
x(1, 2);
x(1);
x();
-40
View File
@@ -1,40 +0,0 @@
fun copy(L) {
L2 = [];
i = 0;
while i < count(L): {
L2[i] = L[i];
i = i + 1;
}
return L2;
}
fun bubbleSort(L, less) {
if less == none:
fun less(a, b) return a < b;
L = copy(L);
do {
swapped = false;
i = 0;
while i < count(L)-1 and not swapped: {
if less(L[i+1], L[i]): {
swapped = true;
tmp = L[i+1];
L[i+1] = L[i];
L[i] = tmp;
}
i = i + 1;
}
} while swapped;
return L;
}
print(bubbleSort([3, 2, 1, 6, 0-2]));
-21
View File
@@ -1,21 +0,0 @@
b = newBuffer(16);
b[2] = 10;
print(b, '\n');
fun toArray(buffer) {
i = 0;
r = [];
while i < count(buffer): {
r[i] = buffer[i];
i = i+1;
}
return r;
}
print(toArray(b), '\n');
+142
View File
@@ -0,0 +1,142 @@
# This script implements a circular queue and
# it's relative tests!
fun newCircularQueue(T: Type = int, max: int = 3) {
if T == None:
error("Invalid type");
if max <= 0:
error("Maximum queue size must be positive");
list = [];
i = 0;
while i < max: {
list[i] = none;
i = i+1;
}
return {
max: max,
head: 0,
tail: 0,
list: list,
type: T
};
}
fun getSize(queue: Map) {
size = none;
if queue.tail == queue.head: {
if queue.list[queue.tail] == none: {
size = 0;
} else {
size = queue.max;
}
} else if queue.tail < queue.head: {
size = queue.head
- queue.tail;
} else {
size = queue.head
+ queue.max
- queue.tail;
}
return size;
}
fun append(queue: Map, value) {
if type(value) != queue.type:
error("Invalid type");
size = getSize(queue);
queue.list[queue.head] = value;
if size == queue.max: {
queue.tail = queue.tail+1;
if queue.tail == queue.max:
queue.tail = 0;
}
queue.head = queue.head+1;
if queue.head == queue.max:
queue.head = 0;
}
fun pop(queue: Map) {
if getSize(queue) == 0:
return none;
value = queue.list[queue.tail];
queue.list[queue.tail] = none;
queue.tail = queue.tail+1;
if queue.tail == queue.max:
queue.tail = 0;
return value;
}
{
utils = import("../utils.noja");
queue = newCircularQueue(int, 3);
assert(getSize(queue) == 0);
assert(queue.head == 0);
assert(queue.tail == 0);
append(queue, 1);
assert(queue.head == 1);
assert(queue.tail == 0);
assert(getSize(queue) == 1);
assert(utils.compareAny(queue.list, [1, none, none]));
append(queue, 2);
assert(queue.head == 2);
assert(queue.tail == 0);
assert(getSize(queue) == 2);
assert(utils.compareAny(queue.list, [1, 2, none]));
append(queue, 3);
assert(queue.head == 0);
assert(queue.tail == 0);
assert(getSize(queue) == 3);
assert(utils.compareAny(queue.list, [1, 2, 3]));
append(queue, 4);
assert(queue.head == 1);
assert(queue.tail == 1);
assert(getSize(queue) == 3);
assert(utils.compareAny(queue.list, [4, 2, 3]));
v = pop(queue);
assert(v == 2);
assert(queue.head == 1);
assert(queue.tail == 2);
assert(getSize(queue) == 2);
assert(utils.compareAny(queue.list, [4, none, 3]));
v = pop(queue);
assert(v == 3);
assert(queue.head == 1);
assert(queue.tail == 0);
assert(getSize(queue) == 1);
assert(utils.compareAny(queue.list, [4, none, none]));
v = pop(queue);
assert(v == 4);
assert(queue.head == 1);
assert(queue.tail == 1);
assert(getSize(queue) == 0);
assert(utils.compareAny(queue.list, [none, none, none]));
v = pop(queue);
assert(v == none);
assert(queue.head == 1);
assert(queue.tail == 1);
assert(getSize(queue) == 0);
assert(utils.compareAny(queue.list, [none, none, none]));
}
@@ -1,10 +1,15 @@
# Implementation of a stack using a linked list.
fun Stack_New(T)
fun Stack_New(T) {
if T == None:
return none, "The type can't be None";
return { count: 0, head: none, type: T };
}
fun Stack_Push(stack: Map, value) {
assert(stack.type != None);
if type(value) != stack.type:
error("Invalid type");
+2 -2
View File
@@ -1,2 +1,2 @@
a = 1;
myName = "Francesco";
myAge = 25;
+9 -3
View File
@@ -1,4 +1,10 @@
vars, err = import("examples/imported.noja");
print("vars=[", vars, "]\n");
print("err=[", err, "]\n");
vars, err = import("imported.noja");
if vars == none: {
print("L'import è fallito!! (", err, ")\n");
return none;
}
me = {name: vars.myName, age: vars.myAge};
print(me, "\n");
+2 -2
View File
@@ -149,7 +149,7 @@ fun parseString(context: Map) {
while context.cur < count(context.str)
and context.str[context.cur] != '"': {
# TODO: Support special characters such as \n, \t ecc
buffer = strcat(buffer, context.str[context.cur]);
buffer = string.cat(buffer, context.str[context.cur]);
context.cur = context.cur + 1;
}
@@ -228,7 +228,7 @@ fun parseValue(context: Map) {
val, err = parseFalse(context);
else {
val = none;
err = strcat("Unexepected character \"", c, "\" where a value was expected");
err = string.cat("Unexepected character \"", c, "\" where a value was expected");
}
return val, err;
}
+1 -1
View File
@@ -1,5 +1,5 @@
json = import("json.noja");
utils = import("utils.noja");
utils = import("../utils.noja");
assert(json.parse("null") == none);
assert(json.parse("true") == true);
-5
View File
@@ -1,5 +0,0 @@
l = [1, 2, 3, 4];
print('The list contains ', count(l), ' items.\n');
print('The list is: ', l, '.\n');
+2
View File
@@ -1,3 +1,5 @@
# This script reads the contents of the specified
# folder, and then prints all of the containd files.
dirname = '.';
dir = files.openDir(dirname);
+12 -5
View File
@@ -1,8 +1,15 @@
# This script reads the contents of a file.
name = 'examples/algorithms/bubble_sort.noja';
buff = buffer.new(1024);
handle, err = files.openFile(name, files.READ);
if handle == none:
error(err);
n = files.read(handle, buff);
resl = buffer.toString(buffer.sliceUp(buff, 0, n));
buff = newBuffer(1024);
name = 'examples/bubble_sort.noja';
hdle = files.openFile(name, files.READ);
n = files.read(hdle, buff);
resl = bufferToString(sliceBuffer(buff, 0, n));
print('Read ', n, ' bytes.\n');
print(resl);
-6
View File
@@ -1,6 +0,0 @@
A = 'Hello';
B = ', ';
C = 'world';
D = strcat(A, B, C);
print(D, '\n');
+7 -132
View File
@@ -35,11 +35,13 @@
#include "math.h"
#include "basic.h"
#include "files.h"
#include "string.h"
#include "buffer.h"
#include "../utils/utf8.h"
#include "../utils/defs.h"
#include "../objects/objects.h"
#include "../compiler/compile.h"
#include "../runtime/runtime.h"
#include "../compiler/compile.h"
static int bin_print(Runtime *runtime, Object **argv, unsigned int argc, Object *rets[static MAX_RETS], Error *error)
{
@@ -364,129 +366,6 @@ static int bin_error(Runtime *runtime, Object **argv, unsigned int argc, Object
return -1;
}
static int bin_strcat(Runtime *runtime, Object **argv, unsigned int argc, Object *rets[static MAX_RETS], Error *error)
{
unsigned int total_count = 0;
for(unsigned int i = 0; i < argc; i += 1)
{
if(!Object_IsString(argv[i]))
{
Error_Report(error, 0, "Argument #%d is not a string", i+1);
return -1;
}
total_count += Object_Count(argv[i], error);
if(error->occurred)
return -1;
}
char starting[128];
char *buffer = starting;
if(total_count > sizeof(starting)-1)
{
buffer = malloc(total_count+1);
if(buffer == NULL)
{
Error_Report(error, 1, "No memory");
return -1;
}
}
Object *result = NULL;
for(unsigned int i = 0, written = 0; i < argc; i += 1)
{
int n;
const char *s = Object_ToString(argv[i], &n,
Runtime_GetHeap(runtime), error);
if(error->occurred)
goto done;
memcpy(buffer + written, s, n);
written += n;
}
buffer[total_count] = '\0';
result = Object_FromString(buffer, total_count, Runtime_GetHeap(runtime), error);
done:
if(starting != buffer)
free(buffer);
if(result == NULL)
return -1;
rets[0] = result;
return 1;
}
static int bin_newBuffer(Runtime *runtime, Object **argv, unsigned int argc, Object *rets[static MAX_RETS], Error *error)
{
UNUSED(argc);
ASSERT(argc == 1);
long long int size = Object_ToInt(argv[0], error);
if(error->occurred == 1)
return -1;
Object *temp = Object_NewBuffer(size, Runtime_GetHeap(runtime), error);
if(temp == NULL)
return -1;
rets[0] = temp;
return 1;
}
static int bin_sliceBuffer(Runtime *runtime, Object **argv, unsigned int argc, Object *rets[static MAX_RETS], Error *error)
{
UNUSED(argc);
ASSERT(argc == 3);
long long int offset = Object_ToInt(argv[1], error);
if(error->occurred == 1) return -1;
long long int length = Object_ToInt(argv[2], error);
if(error->occurred == 1) return -1;
Object *temp = Object_SliceBuffer(argv[0], offset, length, Runtime_GetHeap(runtime), error);
if(temp == NULL)
return -1;
rets[0] = temp;
return 1;
}
static int bin_bufferToString(Runtime *runtime, Object **argv, unsigned int argc, Object *rets[static MAX_RETS], Error *error)
{
UNUSED(argc);
ASSERT(argc == 1);
void *buffaddr;
int buffsize;
buffaddr = Object_GetBufferAddrAndSize(argv[0], &buffsize, error);
if(error->occurred)
return -1;
Object *temp = Object_FromString(buffaddr, buffsize, Runtime_GetHeap(runtime), error);
if(temp == NULL)
return -1;
rets[0] = temp;
return 1;
}
void bins_basic_init(StaticMapSlot slots[])
{
slots[0].as_type = Object_GetTypeType();
@@ -512,17 +391,13 @@ StaticMapSlot bins_basic[] = {
{ "Map", SM_TYPE, .as_type = NULL /* Until bins_basic_init is called */ },
{ "File", SM_TYPE, .as_type = NULL /* Until bins_basic_init is called */ },
{ "Dir", SM_TYPE, .as_type = NULL /* Until bins_basic_init is called */ },
{ "math", SM_SMAP, .as_smap = bins_math, },
{ "math", SM_SMAP, .as_smap = bins_math, },
{ "files", SM_SMAP, .as_smap = bins_files, },
{ "files", SM_SMAP, .as_smap = bins_files, },
{ "buffer", SM_SMAP, .as_smap = bins_buffer, },
{ "string", SM_SMAP, .as_smap = bins_string, },
{ "import", SM_FUNCT, .as_funct = bin_import, .argc = 1, },
{ "newBuffer", SM_FUNCT, .as_funct = bin_newBuffer, .argc = 1 },
{ "sliceBuffer", SM_FUNCT, .as_funct = bin_sliceBuffer, .argc = 3 },
{ "bufferToString", SM_FUNCT, .as_funct = bin_bufferToString, .argc = 1 },
{ "strcat", SM_FUNCT, .as_funct = bin_strcat, .argc = -1 },
{ "type", SM_FUNCT, .as_funct = bin_type, .argc = 1 },
{ "unicode", SM_FUNCT, .as_funct = bin_unicode, .argc = 1 },
{ "chr", SM_FUNCT, .as_funct = bin_chr, .argc = 1 },
+70
View File
@@ -0,0 +1,70 @@
#include "buffer.h"
#include "../utils/defs.h"
#include "../runtime/runtime.h"
static int bin_new(Runtime *runtime, Object **argv, unsigned int argc, Object *rets[static MAX_RETS], Error *error)
{
UNUSED(argc);
ASSERT(argc == 1);
long long int size = Object_ToInt(argv[0], error);
if(error->occurred == 1)
return -1;
Object *temp = Object_NewBuffer(size, Runtime_GetHeap(runtime), error);
if(temp == NULL)
return -1;
rets[0] = temp;
return 1;
}
static int bin_sliceUp(Runtime *runtime, Object **argv, unsigned int argc, Object *rets[static MAX_RETS], Error *error)
{
UNUSED(argc);
ASSERT(argc == 3);
long long int offset = Object_ToInt(argv[1], error);
if(error->occurred == 1) return -1;
long long int length = Object_ToInt(argv[2], error);
if(error->occurred == 1) return -1;
Object *temp = Object_SliceBuffer(argv[0], offset, length, Runtime_GetHeap(runtime), error);
if(temp == NULL)
return -1;
rets[0] = temp;
return 1;
}
static int bin_toString(Runtime *runtime, Object **argv, unsigned int argc, Object *rets[static MAX_RETS], Error *error)
{
UNUSED(argc);
ASSERT(argc == 1);
void *buffaddr;
int buffsize;
buffaddr = Object_GetBufferAddrAndSize(argv[0], &buffsize, error);
if(error->occurred)
return -1;
Object *temp = Object_FromString(buffaddr, buffsize, Runtime_GetHeap(runtime), error);
if(temp == NULL)
return -1;
rets[0] = temp;
return 1;
}
StaticMapSlot bins_buffer[] = {
{ "new", SM_FUNCT, .as_funct = bin_new, .argc = 1 },
{ "sliceUp", SM_FUNCT, .as_funct = bin_sliceUp, .argc = 3 },
{ "toString", SM_FUNCT, .as_funct = bin_toString, .argc = 1 },
};
+2
View File
@@ -0,0 +1,2 @@
#include "../runtime/runtime.h"
extern StaticMapSlot bins_buffer[];
+30 -2
View File
@@ -38,6 +38,8 @@ enum {
MD_APPEND = 2,
};
#include <errno.h>
static int bin_openFile(Runtime *runtime, Object **argv, unsigned int argc, Object *rets[static MAX_RETS], Error *error)
{
UNUSED(argc);
@@ -94,8 +96,34 @@ static int bin_openFile(Runtime *runtime, Object **argv, unsigned int argc, Obje
fp = fopen(path, mode2);
if(fp == NULL)
return 0;
if(fp == NULL) {
Object *o_none = Object_NewNone(heap, error);
if(o_none == NULL)
return -1;
const char *errdesc;
switch(errno) {
case EACCES: errdesc = "Can't access file"; break;
case EPERM: errdesc = "Permission denied"; break;
case EEXIST: errdesc = "File or folder already exists"; break;
case EISDIR: errdesc = "Entity is a directory"; break;
case ENOTDIR: errdesc = "Entity is not a directory"; break;
case ELOOP: errdesc = "Too many symbolic links"; break;
case ENAMETOOLONG: errdesc = "Entity name is too long"; break;
case ENFILE: errdesc = "Open descriptors limit reached"; break;
case ENOENT: errdesc = "File or folder doesn't exist"; break;
default: errdesc = "Unexpected error"; break;
}
Object *o_error = Object_FromString(errdesc, -1, heap, error);
if(o_error == NULL)
return -1;
rets[0] = o_none;
rets[1] = o_error;
return 2;
}
}
rets[0] = Object_FromStream(fp, heap, error);
+71
View File
@@ -0,0 +1,71 @@
#include <string.h>
#include <stdlib.h>
#include "string.h"
#include "../utils/defs.h"
#include "../runtime/runtime.h"
static int bin_cat(Runtime *runtime, Object **argv, unsigned int argc, Object *rets[static MAX_RETS], Error *error)
{
unsigned int total_count = 0;
for(unsigned int i = 0; i < argc; i += 1)
{
if(!Object_IsString(argv[i]))
{
Error_Report(error, 0, "Argument #%d is not a string", i+1);
return -1;
}
total_count += Object_Count(argv[i], error);
if(error->occurred)
return -1;
}
char starting[128];
char *buffer = starting;
if(total_count > sizeof(starting)-1)
{
buffer = malloc(total_count+1);
if(buffer == NULL)
{
Error_Report(error, 1, "No memory");
return -1;
}
}
Object *result = NULL;
for(unsigned int i = 0, written = 0; i < argc; i += 1)
{
int n;
const char *s = Object_ToString(argv[i], &n,
Runtime_GetHeap(runtime), error);
if(error->occurred)
goto done;
memcpy(buffer + written, s, n);
written += n;
}
buffer[total_count] = '\0';
result = Object_FromString(buffer, total_count, Runtime_GetHeap(runtime), error);
done:
if(starting != buffer)
free(buffer);
if(result == NULL)
return -1;
rets[0] = result;
return 1;
}
StaticMapSlot bins_string[] = {
{ "cat", SM_FUNCT, .as_funct = bin_cat, .argc = -1 },
};
+2
View File
@@ -0,0 +1,2 @@
#include "../runtime/runtime.h"
extern StaticMapSlot bins_string[];
+3 -3
View File
@@ -40,13 +40,13 @@ struct ClosureObject {
};
static void walk(Object *self, void (*callback)(Object **referer, void *userp), void *userp);
static Object *select(Object *self, Object *key, Heap *heap, Error *err);
static Object *select_(Object *self, Object *key, Heap *heap, Error *err);
static TypeObject t_closure = {
.base = (Object) { .type = &t_type, .flags = Object_STATIC },
.name = "closure",
.size = sizeof(ClosureObject),
.select = select,
.select = select_,
.walk = walk,
};
@@ -69,7 +69,7 @@ Object *Object_NewClosure(Object *parent, Object *new_map, Heap *heap, Error *er
return (Object*) obj;
}
static Object *select(Object *self, Object *key, Heap *heap, Error *err)
static Object *select_(Object *self, Object *key, Heap *heap, Error *err)
{
ClosureObject *closure = (ClosureObject*) self;
+3 -3
View File
@@ -38,7 +38,7 @@ typedef struct {
Object **vals;
} ListObject;
static Object *select(Object *self, Object *key, Heap *heap, Error *err);
static Object *select_(Object *self, Object *key, Heap *heap, Error *err);
static _Bool insert(Object *self, Object *key, Object *val, Heap *heap, Error *err);
static int count(Object *self);
static void print(Object *obj, FILE *fp);
@@ -53,7 +53,7 @@ static TypeObject t_list = {
.size = sizeof (ListObject),
.copy = copy,
.hash = hash,
.select = select,
.select = select_,
.insert = insert,
.count = count,
.print = print,
@@ -158,7 +158,7 @@ static void walkexts(Object *self, void (*callback)(void **referer, unsigned int
callback((void**) &list->vals, sizeof(Object) * list->capacity, userp);
}
static Object *select(Object *self, Object *key, Heap *heap, Error *error)
static Object *select_(Object *self, Object *key, Heap *heap, Error *error)
{
UNUSED(heap);
ASSERT(self != NULL);
+3 -3
View File
@@ -39,7 +39,7 @@ typedef struct {
Object **vals;
} MapObject;
static Object *select(Object *self, Object *key, Heap *heap, Error *err);
static Object *select_(Object *self, Object *key, Heap *heap, Error *err);
static _Bool insert(Object *self, Object *key, Object *val, Heap *heap, Error *err);
static int count(Object *self);
static void print(Object *self, FILE *fp);
@@ -54,7 +54,7 @@ static TypeObject t_map = {
.size = sizeof (MapObject),
.copy = copy,
.hash = hash,
.select = select,
.select = select_,
.insert = insert,
.count = count,
.print = print,
@@ -174,7 +174,7 @@ static void walkexts(Object *self, void (*callback)(void **referer, unsigned int
callback((void**) &map->vals, sizeof(Object*) * capacity, userp);
}
static Object *select(Object *self, Object *key, Heap *heap, Error *error)
static Object *select_(Object *self, Object *key, Heap *heap, Error *error)
{
UNUSED(heap);
ASSERT(self != NULL);
+3 -3
View File
@@ -48,7 +48,7 @@ static void print(Object *obj, FILE *fp);
static char *to_string(Object *self, int *size, Heap *heap, Error *err);
static _Bool op_eql(Object *self, Object *other);
static void walkexts(Object *self, void (*callback)(void **referer, unsigned int size, void *userp), void *userp);
static Object *select(Object *self, Object *key, Heap *heap, Error *error);
static Object *select_(Object *self, Object *key, Heap *heap, Error *error);
static TypeObject t_string = {
.base = (Object) { .type = &t_type, .flags = Object_STATIC },
@@ -59,7 +59,7 @@ static TypeObject t_string = {
.count = count,
.copy = copy,
.print = print,
.select = select,
.select = select_,
.to_string = to_string,
.op_eql = op_eql,
.walkexts = walkexts,
@@ -89,7 +89,7 @@ static int char_index_to_offset(StringObject *str, int idx)
return scanned_bytes;
}
static Object *select(Object *self, Object *key, Heap *heap, Error *error)
static Object *select_(Object *self, Object *key, Heap *heap, Error *error)
{
ASSERT(self != NULL && self->type == &t_string);
ASSERT(key != NULL && heap != NULL && error != NULL);
+3 -3
View File
@@ -57,7 +57,7 @@ typedef struct {
const StaticMapSlot *slots;
} StaticMapObject;
static Object *select(Object *self, Object *key, Heap *heap, Error *err);
static Object *select_(Object *self, Object *key, Heap *heap, Error *err);
static Object *copy(Object *self, Heap *heap, Error *err);
static int hash(Object *self);
@@ -67,7 +67,7 @@ static TypeObject t_staticmap = {
.size = sizeof (StaticMapObject),
.copy = copy,
.hash = hash,
.select = select,
.select = select_,
};
static Object *copy(Object *self, Heap *heap, Error *err)
@@ -103,7 +103,7 @@ Object *Object_NewStaticMap(StaticMapSlot slots[], void (*initfn)(StaticMapSlot[
return (Object*) obj;
}
static Object *select(Object *self, Object *key, Heap *heap, Error *error)
static Object *select_(Object *self, Object *key, Heap *heap, Error *error)
{
assert(self != NULL);
assert(self->type == &t_staticmap);
+7 -7
View File
@@ -27,6 +27,8 @@
** | with The Noja Interpreter. If not, see <http://www.gnu.org/licenses/>. |
** +--------------------------------------------------------------------------+
*/
#include <stdio.h>
#include <stdlib.h> // just for [abort]
#ifndef MAX
#define MAX(x, y) ((x) > (y) ? (x) : (y))
@@ -46,16 +48,14 @@
#define ASSERT(X) \
do { \
if(!(X)) { \
fprintf(stderr, "Assertion failure %s:%d (in %s): [" #X "] is false\n", __FILE__, __LINE__, __func__); \
fprintf(stderr, "Assertion failure %s:%d (in %s): [%s] is false\n", __FILE__, __LINE__, __func__, #X); \
abort(); \
} \
} while(0);
#define UNREACHABLE \
do { \
if(!(x)) { \
fprintf(stderr, "ABORT at %s:%d (in %s): Reached code assumed to be unreachable\n", __FILE__, __LINE__, __func__); \
abort(); \
} \
#define UNREACHABLE \
do { \
fprintf(stderr, "ABORT at %s:%d (in %s): Reached code assumed to be unreachable\n", __FILE__, __LINE__, __func__); \
abort(); \
} while(0);
#else
#define ASSERT(x)