|
|
@@ -2,34 +2,189 @@
|
|
|
|
|
|
#include <stdio.h>
|
|
|
#include <string.h>
|
|
|
+#include <sys/ioctl.h>
|
|
|
+#include <threads.h>
|
|
|
+
|
|
|
+#include "Memory.h"
|
|
|
+
|
|
|
+#define RETURN_INT(value) \
|
|
|
+ *r = INT_VALUE(value); \
|
|
|
+ return false
|
|
|
+
|
|
|
+static u32 seed = 0;
|
|
|
+static bool printNewline = true;
|
|
|
|
|
|
static bool sfPrint(Code* c, Value* r, Value* vs, i32 n) {
|
|
|
for(i32 i = 0; i < n; i++) {
|
|
|
Value* v = vs + i;
|
|
|
switch(v->type) {
|
|
|
case VT_INT32: printf("%d", v->data); break;
|
|
|
+ case VT_ARRAY: printf("array"); break;
|
|
|
case VT_CONSTANT_STRING:
|
|
|
printf("%s", c->code.data + v->data);
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
|
- putchar('\n');
|
|
|
- *r = INT_VALUE(0);
|
|
|
+ if(printNewline) {
|
|
|
+ putchar('\n');
|
|
|
+ }
|
|
|
+ RETURN_INT(0);
|
|
|
+}
|
|
|
+
|
|
|
+static bool sfSetPrintNewline(Code*, Value* r, Value* vs, i32) {
|
|
|
+ printNewline = vs[0].data;
|
|
|
+ RETURN_INT(0);
|
|
|
+}
|
|
|
+
|
|
|
+#define ESC "\33["
|
|
|
+#define esc(s) fputs(ESC s, stdout)
|
|
|
+
|
|
|
+static bool sfClear(Code*, Value* r, Value*, i32) {
|
|
|
+ esc("2J");
|
|
|
+ RETURN_INT(0);
|
|
|
+}
|
|
|
+
|
|
|
+static bool sfGetWidth(Code*, Value* r, Value*, i32) {
|
|
|
+ struct winsize w;
|
|
|
+ if(ioctl(0, TIOCGWINSZ, &w)) {
|
|
|
+ RETURN_INT(0);
|
|
|
+ }
|
|
|
+ RETURN_INT(w.ws_col);
|
|
|
+}
|
|
|
+
|
|
|
+static bool sfGetHeight(Code*, Value* r, Value*, i32) {
|
|
|
+ struct winsize w;
|
|
|
+ if(ioctl(0, TIOCGWINSZ, &w)) {
|
|
|
+ RETURN_INT(0);
|
|
|
+ }
|
|
|
+ RETURN_INT(w.ws_row);
|
|
|
+}
|
|
|
+
|
|
|
+static bool sfClearLine(Code*, Value* r, Value*, i32) {
|
|
|
+ esc("2K\r");
|
|
|
+ RETURN_INT(0);
|
|
|
+}
|
|
|
+
|
|
|
+static bool sfHideCursor(Code*, Value* r, Value*, i32) {
|
|
|
+ esc("?25l");
|
|
|
+ RETURN_INT(0);
|
|
|
+}
|
|
|
+
|
|
|
+static bool sfShowCursor(Code*, Value* r, Value*, i32) {
|
|
|
+ esc("?25h");
|
|
|
+ RETURN_INT(0);
|
|
|
+}
|
|
|
+
|
|
|
+static bool sfResetCursor(Code*, Value* r, Value*, i32) {
|
|
|
+ esc("H");
|
|
|
+ RETURN_INT(0);
|
|
|
+}
|
|
|
+
|
|
|
+static bool sfMoveCursorLeft(Code*, Value* r, Value* vs, i32) {
|
|
|
+ if(vs[0].data > 0) {
|
|
|
+ printf(ESC "%dD", vs[0].data);
|
|
|
+ }
|
|
|
+ RETURN_INT(0);
|
|
|
+}
|
|
|
+
|
|
|
+static bool sfMoveCursorRight(Code*, Value* r, Value* vs, i32) {
|
|
|
+ if(vs[0].data > 0) {
|
|
|
+ printf(ESC "%dC", vs[0].data);
|
|
|
+ }
|
|
|
+ RETURN_INT(0);
|
|
|
+}
|
|
|
+
|
|
|
+static bool sfMoveCursorUp(Code*, Value* r, Value* vs, i32) {
|
|
|
+ if(vs[0].data > 0) {
|
|
|
+ printf(ESC "%dA", vs[0].data);
|
|
|
+ }
|
|
|
+ RETURN_INT(0);
|
|
|
+}
|
|
|
+
|
|
|
+static bool sfMoveCursorDown(Code*, Value* r, Value* vs, i32) {
|
|
|
+ if(vs[0].data > 0) {
|
|
|
+ printf(ESC "%dB", vs[0].data);
|
|
|
+ }
|
|
|
+ RETURN_INT(0);
|
|
|
+}
|
|
|
+
|
|
|
+static bool sfSleep(Code*, Value* r, Value* vs, i32) {
|
|
|
+ struct timespec t = {.tv_sec = vs[0].data, .tv_nsec = vs[1].data};
|
|
|
+ thrd_sleep(&t, nullptr);
|
|
|
+ RETURN_INT(0);
|
|
|
+}
|
|
|
+
|
|
|
+static bool sfRandom(Code*, Value* r, Value* vs, i32) {
|
|
|
+ seed = seed * 1664525u + 1013904223u;
|
|
|
+ u32 s = seed % (u32)(vs[1].data + 1 - vs[0].data);
|
|
|
+ RETURN_INT(vs[0].data + (i32)s);
|
|
|
+}
|
|
|
+
|
|
|
+static bool codeAllocate(Code* c, Value* v, i32 n) {
|
|
|
+ v->type = VT_ARRAY;
|
|
|
+ v->data = -1;
|
|
|
+ if(n <= 0) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ codeRunCollector(c);
|
|
|
+ size_t s = sizeof(Allocation) + ((size_t)n + 1) * sizeof(Value);
|
|
|
+ Allocation* a = memoryAllocate(s);
|
|
|
+ if(a == nullptr) {
|
|
|
+ SET_ERROR("Out of memory");
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ memset(a, 0, s);
|
|
|
+ a->next = c->allocations;
|
|
|
+ c->allocations = a;
|
|
|
+ a->values[0].type = VT_INT32;
|
|
|
+ a->values[0].data = n;
|
|
|
+ v->data = memoryConvertToIndex(a);
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
+static bool sfArray(Code* c, Value* r, Value* vs, i32) {
|
|
|
+ return codeAllocate(c, r, vs[0].data);
|
|
|
+}
|
|
|
+
|
|
|
+static bool sfGetAllocations(Code* c, Value* r, Value*, i32) {
|
|
|
+ codeRunCollector(c);
|
|
|
+ i32 counter = 0;
|
|
|
+ for(Allocation* a = c->allocations; a != nullptr; a = a->next) {
|
|
|
+ counter++;
|
|
|
+ }
|
|
|
+ RETURN_INT(counter);
|
|
|
+}
|
|
|
+
|
|
|
typedef struct {
|
|
|
SystemFunction function;
|
|
|
i32 arguments;
|
|
|
const char* name;
|
|
|
} FunctionEntry;
|
|
|
|
|
|
-static FunctionEntry systemFunctions[] = {{sfPrint, -1, "print"}};
|
|
|
+static FunctionEntry systemFunctions[] = {
|
|
|
+ {sfPrint, -1, "print"},
|
|
|
+ {sfSetPrintNewline, 1, "setPrintNewline"},
|
|
|
+ {sfClear, 0, "clear"},
|
|
|
+ {sfSleep, 2, "sleep"},
|
|
|
+ {sfGetWidth, 0, "getWidth"},
|
|
|
+ {sfGetHeight, 0, "getHeight"},
|
|
|
+ {sfClearLine, 0, "clearLine"},
|
|
|
+ {sfHideCursor, 0, "hideCursor"},
|
|
|
+ {sfShowCursor, 0, "showCursor"},
|
|
|
+ {sfResetCursor, 0, "resetCursor"},
|
|
|
+ {sfMoveCursorLeft, 1, "moveCursorLeft"},
|
|
|
+ {sfMoveCursorRight, 1, "moveCursorRight"},
|
|
|
+ {sfMoveCursorUp, 1, "moveCursorUp"},
|
|
|
+ {sfMoveCursorDown, 1, "moveCursorDown"},
|
|
|
+ {sfRandom, 2, "random"},
|
|
|
+ {sfArray, 1, "array"},
|
|
|
+ {sfGetAllocations, 0, "getAllocations"},
|
|
|
+};
|
|
|
static constexpr i32 amount = sizeof(systemFunctions) / sizeof(FunctionEntry);
|
|
|
|
|
|
i32 getSystemFunctionIndex(const char* s) {
|
|
|
for(i32 i = 0; i < amount; i++) {
|
|
|
- if(strcmp(systemFunctions->name, s) == 0) {
|
|
|
+ if(strcmp(systemFunctions[i].name, s) == 0) {
|
|
|
return i;
|
|
|
}
|
|
|
}
|
|
|
@@ -49,3 +204,9 @@ SystemFunction getSystemFunction(i32 index) {
|
|
|
}
|
|
|
return nullptr;
|
|
|
}
|
|
|
+
|
|
|
+void initSystemFunctions() {
|
|
|
+ struct timespec t = {};
|
|
|
+ timespec_get(&t, TIME_UTC);
|
|
|
+ seed = (u32)t.tv_nsec;
|
|
|
+}
|