diff options
| -rw-r--r-- | src/puzzles/puzzle.c | 104 | ||||
| -rw-r--r-- | src/puzzles/puzzle.h | 32 | ||||
| -rw-r--r-- | src/scenes/puzzleScene.c | 25 | ||||
| -rw-r--r-- | src/scenes/resultView.c | 10 | ||||
| -rw-r--r-- | src/scenes/scenes.h | 2 | ||||
| -rw-r--r-- | src/ui_elements/TextEditor.c | 142 | ||||
| -rw-r--r-- | src/ui_elements/UI.c | 3 | ||||
| -rw-r--r-- | src/ui_elements/UI.h | 6 | ||||
| -rw-r--r-- | src/utils/stringBuilder.c | 26 | ||||
| -rw-r--r-- | src/utils/stringBuilder.h | 3 | ||||
| -rw-r--r-- | src/wren_inter/wren_inter.c | 70 | ||||
| -rw-r--r-- | src/wren_inter/wren_inter.h | 6 |
12 files changed, 351 insertions, 78 deletions
diff --git a/src/puzzles/puzzle.c b/src/puzzles/puzzle.c index cbad998..22f7a4d 100644 --- a/src/puzzles/puzzle.c +++ b/src/puzzles/puzzle.c @@ -1,21 +1,121 @@ #include "puzzle.h" +#include "../wren_inter/wren_inter.h" #include <stdlib.h> #include <string.h> +#include <wren.h> + +/// Returns 1 test puzzle for the GetTestPuzzle segment +Test *getTestPuzzleTests() { + Test *outp = malloc(sizeof(Test)); + outp->RecieverName = strdup("main"); + outp->MainMethodSignature = strdup("call(_)"); + + outp->argc = 1; + outp->argv = malloc(sizeof(PuzzleIO)); + outp->argv->type = WREN_TYPE_STRING; + outp->argv->value = strdup("Hello"); + + outp->ExpectedResult.type = WREN_TYPE_STRING; + outp->ExpectedResult.value = strdup("Hello"); + return outp; +} Puzzle *GetTestPuzzle() { Puzzle *outp = malloc(sizeof(Puzzle)); if (outp == NULL) return NULL; outp->Name = strdup("Test puzzle"); - outp->Description = strdup("In this puzzle you will have to return the input string\n-\n-\n-\n-\n-\n-\n-\n-\n-\n-\n-\n-\n-\n-\n-\n-\n-\n-\n-\n-\n-\n-\n-\n-\n-\n-\n-\n-\n-\n-\n-\n-\n-\n-\n-\nThis is a line that should be somewhere down"); + outp->Description = strdup("In this puzzle you will have to return the input string"); + outp->InitialCode = strdup( "var main = Fn.new { |name| \n System.print(\"Hello, %(name)!\")\n}\n\nmain.call(\"world\")"); + outp->TestC = 1; + outp->Tests = getTestPuzzleTests(); return outp; } +void FreeTests(Test *Tests, size_t TestC) { + if (TestC == 0 || Tests == NULL) return; + for (size_t i = 0; i < TestC; i++) { + Test *t = &Tests[i]; + free(t->RecieverName); + free(t->MainMethodSignature); + free(t->argv); + } + free(Tests); +} + void FreePuzzle(Puzzle *self) { if (self == NULL) return; if (self->Name != NULL) free(self->Name); if (self->Description != NULL) free(self->Description); - if (self->Tests != NULL) free(self->Tests); + if (self->InitialCode != NULL) free(self->InitialCode); + FreeTests(self->Tests, self->TestC); free(self); } + + +enum PUZZLE_TEST_RESULT RunTest(Test *test, WrenVM *vm) { + // TODO: finish this + return RESULT_OK; +} + +// Returns the res ptr. Does not modify the address +SubmitionResult *TryEvaluateUserCode(WrenVM *vm, char *script, SubmitionResult *res) { + WrenInterpretResult result = wrenInterpret(vm, "main", script); + res->result = RESULT_OK; + switch (result) { + case WREN_RESULT_COMPILE_ERROR: + res->result = RESULT_COMPTIME_ERR; + return res; + case WREN_RESULT_RUNTIME_ERROR: + res->result = RESULT_RUNTIME_ERR; + return res; + default: break; + } + return res; +} + +// Frees the vm. Does not modify the self address. +SubmitionResult *PrepareResult(SubmitionResult *self, + WrenVM *vm, + enum PUZZLE_TEST_RESULT result) { + if (vm == NULL || self == NULL) return self; + self->result = result; + self->stdout = GetMachineOutput(vm); + InterpreterFreeMachine(vm); + return self; +} + +SubmitionResult *SubmitSolution(Puzzle *self, char *script) { + if (self == NULL || script == NULL) return NULL; + SubmitionResult *res = malloc(sizeof(SubmitionResult)); + + WrenVM *vm = InterpreterPrepareMachine(); + if (vm == NULL) { + res->result = RESULT_INIT_ERROR; + return res; + } + + res = TryEvaluateUserCode(vm, script, res); + if (res->result != RESULT_OK) { + return PrepareResult(res, vm, res->result); + } + + for (size_t i = 0; i < self->TestC; i++) { + enum PUZZLE_TEST_RESULT test_res = RunTest(&self->Tests[i], vm); + switch (test_res) { + case WREN_RESULT_COMPILE_ERROR: + return PrepareResult(res, vm, RESULT_COMPTIME_ERR); + case WREN_RESULT_RUNTIME_ERROR: + return PrepareResult(res, vm, RESULT_RUNTIME_ERR); + default: break; + } + } + + return PrepareResult(res, vm, RESULT_OK); +} + +void FreeSunmitionResult(SubmitionResult *res) { + if (res->stdout != NULL) free(res->stdout); + free(res); +} diff --git a/src/puzzles/puzzle.h b/src/puzzles/puzzle.h index d530a89..6c72a18 100644 --- a/src/puzzles/puzzle.h +++ b/src/puzzles/puzzle.h @@ -3,6 +3,16 @@ #ifndef PUZZLE_H +enum PUZZLE_TEST_RESULT : char { + RESULT_OK = 0, + RESULT_COMPTIME_NO_ENTRY, + RESULT_COMPTIME_ERR, + RESULT_RUNTIME_ERR, + // TODO: add async evaluation to prevent `while (true)` situation + RESULT_TIMEOUT, + RESULT_INIT_ERROR, +}; + // This is a param that would be placed in a slot // https://wren.io/embedding/slots-and-handles.html#writing-slots typedef struct { @@ -13,22 +23,32 @@ typedef struct { } PuzzleIO; typedef struct { + // https://wren.io/embedding/calling-wren-from-c.html#setting-up-a-receiver + char *RecieverName; // https://wren.io/embedding/calling-wren-from-c.html#getting-a-method-handle char *MainMethodSignature; size_t argc; PuzzleIO *argv; + PuzzleIO ExpectedResult; } Test; + +/// The user submitted code should be evaluated by this point. +/// The entry point should be registered and the absence of the +/// Main method signatire will be concidered an error +enum PUZZLE_TEST_RESULT RunTest(Test *test, WrenVM *vm); + typedef struct { char *Name; char *Description; + char *InitialCode; /// The tests that are accessible for an end user size_t TestC; Test *Tests; } Puzzle; - + // TODO void ReadPuzzleFromFile(const char *path); @@ -36,5 +56,15 @@ void FreePuzzle(Puzzle *self); /// A prebuilt puzzle. Used for debuging Puzzle *GetTestPuzzle(); +typedef struct { + char *stdout; + enum PUZZLE_TEST_RESULT result; +} SubmitionResult; + +// Don't put anything in out_res, it will be overriten. +// The stdout of the VM will be there +SubmitionResult *SubmitSolution(Puzzle *self, char *script); +void FreeSunmitionResult(SubmitionResult *res); + #define PUZZLE_H #endif // PUZZLE_H diff --git a/src/scenes/puzzleScene.c b/src/scenes/puzzleScene.c index 5590bb8..57ac15d 100644 --- a/src/scenes/puzzleScene.c +++ b/src/scenes/puzzleScene.c @@ -72,7 +72,7 @@ bool drawPuzzleScene(void *self) { // return true; Rectangle pane1, pane2; - GetPanesSplit(&pane1, &pane2, body, 0.5, 0.4); + GetPanesSplit(&pane1, &pane2, body, 0.35, 0.4); DrawRecBordered(pane1, WHITE, COLORSCHEME_ORANGE, BORDER); DrawRecBordered(pane2, WHITE, COLORSCHEME_ORANGE, BORDER); @@ -85,12 +85,19 @@ bool drawPuzzleScene(void *self) { bool updatePuzzleScene(void *self) { puzzleSceneData *data = ((Scene *)self)->data; - HandleKeyboard(data->EditorInfo); + + Rectangle body = GetBodyRect(); + Rectangle pane1, pane2; + GetPanesSplit(&pane1, &pane2, body, 0.35, 0.4); + UpdateTextArea(data->EditorInfo, pane2); + if (IsKeyPressed(KEY_F5)) { - char *txt = GetText(data->EditorInfo); - char *outp = EvaluateScript(txt); - free(txt); - AddScene(CreateResultView(outp)); + char *script = GetText(data->EditorInfo); + // char *outp = EvaluateScript(txt); + // free(txt); + // AddScene(CreateResultView(outp)); + SubmitionResult *res = SubmitSolution(data->PuzzlePtr, script); + AddScene(CreateResultView(res)); } return true; @@ -122,8 +129,12 @@ Scene *CreatePuzzleScene(Puzzle *puzzle) { EditorDisplayParams->scroll_h = 0; EditorDisplayParams->scroll_v = 0; } - data->EditorInfo = CreateTextArea(EditorDisplayParams); + if (puzzle->InitialCode != NULL) { + data->EditorInfo = CreateTextAreaFromText(EditorDisplayParams, puzzle->InitialCode); + } else { + data->EditorInfo = CreateTextArea(EditorDisplayParams); + } outp->data = data; return outp; diff --git a/src/scenes/resultView.c b/src/scenes/resultView.c index b433bd0..033d17e 100644 --- a/src/scenes/resultView.c +++ b/src/scenes/resultView.c @@ -11,7 +11,7 @@ static const int BORDER = 2; static const int SCROLL_SPEED = 10; typedef struct { - char *value; + SubmitionResult *value; int scroll; /// For the fun popping up effect float scroll_up; @@ -57,17 +57,20 @@ bool drawResultView(void *self) { // DrawBackground(); Rectangle body = GetResultViewBodyRect(data->scroll_up); DrawRecBordered(body, WHITE, COLORSCHEME_ORANGE, BORDER); - DrawTextInRec(body, data->value, + DrawTextInRec(body, data->value->stdout, GetMainFont(), 20, COLORSCHEME_BROWN, 3, &data->scroll); return true; } void deinitResultView(void *self) { TraceLog(LOG_INFO, "Deleting a result view"); + ResultViewData *data = ((Scene *)self)->data; + if (data->value != NULL) FreeSunmitionResult(data->value); + free(data); free((Scene *)self); } -Scene *CreateResultView(char *result) { +Scene *CreateResultView(SubmitionResult *result) { TraceLog(LOG_INFO, "Creating a main menu"); Scene *outp = malloc(sizeof(Scene)); outp->Draw = drawResultView; @@ -80,6 +83,7 @@ Scene *CreateResultView(char *result) { free(outp); return NULL; } + data->value = result; data->scroll = 0; data->scroll_up = 1; diff --git a/src/scenes/scenes.h b/src/scenes/scenes.h index 37da761..b7fdf02 100644 --- a/src/scenes/scenes.h +++ b/src/scenes/scenes.h @@ -30,6 +30,6 @@ bool UpdateScene(); Scene *CreateMainMenu(); Scene *CreatePuzzleScene(Puzzle *puzzle); -Scene *CreateResultView(char *result); +Scene *CreateResultView(SubmitionResult *result); #endif // SCENES_H diff --git a/src/ui_elements/TextEditor.c b/src/ui_elements/TextEditor.c index 06cfc41..3cf34ff 100644 --- a/src/ui_elements/TextEditor.c +++ b/src/ui_elements/TextEditor.c @@ -5,6 +5,7 @@ #include "../resources/resources.h" #include <ctype.h> #include <raylib.h> +#include <stdio.h> #include <stdlib.h> #include <string.h> @@ -218,18 +219,18 @@ void MoveCursorRight(TextArea *ta) { void MoveCursorRightWord(TextArea *ta) { if (ta == NULL || ta->CurrentNode == NULL) return; + size_t line_len = ta->CurrentNode->len; + if (ta->CursorPosition.x == line_len) { + MoveCursorRight(ta); + return; + } + bool current_type = IsSkippable(GetCurrentChar(ta)); do { ta->CursorPosition.x += 1; - } while (IsSkippable(GetCurrentChar(ta))); + } while (IsSkippable(GetCurrentChar(ta)) == current_type); - size_t line_len = ta->CurrentNode->len; if (ta->CursorPosition.x > line_len) { - if (ta->CurrentNode->NextNode == NULL) { - ta->CursorPosition.x = line_len; - return; - } - MoveCursorDown(ta); - ta->CursorPosition.x = 0; + ta->CursorPosition.x = line_len; } } @@ -254,9 +255,18 @@ void MoveCursorLeft(TextArea *ta) { void MoveCursorLeftWord(TextArea *ta) { if (ta == NULL || ta->CurrentNode == NULL) return; + if (ta->CursorPosition.x == 0) { + MoveCursorLeft(ta); + return; + } + char prev_symbol = ta->CurrentNode->text[(int)ta->CursorPosition.x - 1]; + bool current_type = IsSkippable(prev_symbol); + do { ta->CursorPosition.x -= 1; - } while (IsSkippable(GetCurrentChar(ta)) && ta->CursorPosition.x > 0); + } while (IsSkippable(GetCurrentChar(ta)) == current_type && ta->CursorPosition.x >= 0); + + ta->CursorPosition.x += 1; if (ta->CursorPosition.x < 0) { if (ta->CursorPosition.y == 0 || ta->CurrentNode->PrevNode == NULL) { @@ -273,6 +283,15 @@ void MoveCursorHome(TextArea *ta) { ta->CursorPosition.x = 0; } +size_t GetStartingSpaces(char *string) { + if (string == NULL) return 0; + size_t idx = 0, len = strlen(string); + while (string[idx] != 0 && string[idx] == ' ') + idx++; + if (string[idx] == 0) return 0; // no starting spaces + return idx; +} + void BreakLine(TextArea *ta) { if (ta == NULL || ta->CurrentNode == NULL) return; if (ta->CursorPosition.x == 0) { @@ -287,24 +306,44 @@ void BreakLine(TextArea *ta) { return; } + TextNode *next_node = (TextNode *)ta->CurrentNode->NextNode; size_t current_node_len = strlen(ta->CurrentNode->text); + size_t spaces_len = GetStartingSpaces(ta->CurrentNode->text); + size_t needed_space = spaces_len; + + size_t after_str_len = 0; + char *after_str = NULL; + if (ta->CursorPosition.x < current_node_len) { - char *after_str = (ta->CurrentNode->text + (int)ta->CursorPosition.x); - size_t after_str_len = strlen(after_str); - if (((TextNode *)ta->CurrentNode->NextNode)->cap < after_str_len) { - if (!AddSpaceDetermined(ta->CurrentNode->NextNode, after_str_len)) { - TraceLog(LOG_ERROR, "Failed to push a node: the space reservaton failed"); - } + after_str = (ta->CurrentNode->text + (int)ta->CursorPosition.x); + after_str_len = strlen(after_str); + needed_space += after_str_len; + } + + if (next_node->cap < needed_space + 1) { + if (!AddSpaceDetermined(ta->CurrentNode->NextNode, needed_space + 1)) { + TraceLog(LOG_ERROR, "Failed to push a node: the space reservaton failed"); + return; } - strcpy(((TextNode *)ta->CurrentNode->NextNode)->text, after_str); - ((TextNode *)ta->CurrentNode->NextNode)->len = after_str_len; + } + + for (int i = 0; i < spaces_len; ++i) { + next_node->text[i] = ' '; + } + next_node->text[spaces_len] = 0x0; + + if (after_str != NULL) { + strcpy(next_node->text + spaces_len, after_str); + ((TextNode *)ta->CurrentNode->NextNode)->len = after_str_len + spaces_len; for (int i = ta->CursorPosition.x; i < current_node_len; i++) { ta->CurrentNode->text[i] = 0x0; } ta->CurrentNode->len -= after_str_len; } + + next_node->len = strlen(next_node->text); ta->CursorPosition.y += 1; - ta->CursorPosition.x = 0; + ta->CursorPosition.x = spaces_len; ta->CurrentNode = ta->CurrentNode->NextNode; EnsureCursorIsInFrame(ta); } @@ -358,7 +397,9 @@ void DeleteChar(TextArea *ta) { ta->CurrentNode->text[line_len - 1] = 0x0; } else { char *after_str = (ta->CurrentNode->text + (int)ta->CursorPosition.x); - strcpy(ta->CurrentNode->text + (int)ta->CursorPosition.x - 1, after_str); + // Including a zero terminator here + size_t after_str_len = strlen(after_str) + 1; + memmove(ta->CurrentNode->text + (int)ta->CursorPosition.x - 1, after_str, after_str_len); } ta->CursorPosition.x -= 1; ta->CurrentNode->len -= 1; @@ -366,6 +407,54 @@ void DeleteChar(TextArea *ta) { EnsureCursorIsInFrame(ta); } +TextArea *CreateTextAreaFromText(TextAreaDisplayParams *DisplayParams, char *text) { + if (DisplayParams == NULL || text == NULL) return NULL; + TextArea *outp = CreateTextArea(DisplayParams); + if (outp == NULL) return NULL; + + const char *line_start = text; + const char *next_newline = NULL; + + while (line_start != NULL) { + next_newline = strchr(line_start, '\n'); + + size_t part_len = next_newline - line_start; + if (next_newline == NULL) part_len = strlen(line_start); + + if (!PushNode(outp)) { + TraceLog(LOG_ERROR, "Failed to push a node: the initializator returned NULL"); + break; + } + + TextNode *node = (TextNode *)outp->CurrentNode; + + if (part_len > 0) { + if (node->cap < part_len) { + if (!AddSpaceDetermined(node, part_len)) { + TraceLog(LOG_ERROR, "Failed to reserve space for node text"); + break; + } + } + + strncpy(node->text, line_start, part_len); + node->text[part_len] = 0x0; + node->len = part_len; + } else { + node->len = 0; + if (node->text != NULL && node->cap > 0) { + node->text[0] = '\0'; + } + } + + outp->CurrentNode = outp->CurrentNode->NextNode; + if (next_newline != NULL) line_start = next_newline + 1; + else line_start = NULL; + } + + outp->CurrentNode = outp->StartNode; + return outp; +} + bool IsKeyPressedFix(int key) { return IsKeyPressed(key) || IsKeyPressedRepeat(key); } @@ -474,6 +563,13 @@ void HandleScroll(TextArea *ta, Rectangle rec) { } } +void UpdateTextArea(TextArea *ta, Rectangle rec) { + HandleKeyboard(ta); + if (IsMouseInRec(rec)) { + HandleScroll(ta, rec); + } +} + /// draws a text area on the screen. Main draw entry point void DrawTextArea(TextArea *ta, Rectangle rec) { // those are used to move a cursor in frame when typing @@ -481,11 +577,6 @@ void DrawTextArea(TextArea *ta, Rectangle rec) { ta->DisplayParams->_area_width = rec.width; TextAreaDisplayParams *params = ta->DisplayParams; - // int vertical_acc = rec.y - *scroll; - - if (IsMouseInRec(rec)) { - HandleScroll(ta, rec); - } Vector2 pos = { .x = rec.x + params->spacing - params->scroll_h, @@ -500,7 +591,8 @@ void DrawTextArea(TextArea *ta, Rectangle rec) { TextNode *node = ta->StartNode; BeginScissorMode(rec.x, rec.y, rec.width, rec.height); while (node != NULL) { - DrawTextEx(*params->font, node->text, pos, params->font_size, params->spacing, COLORSCHEME_BROWN); + DrawTextEx(*params->font, node->text, pos, + params->font_size, params->spacing, COLORSCHEME_BROWN); if (node == ta->CurrentNode) DrawCursor(ta, pos, cursorPos.x); node = node->NextNode; diff --git a/src/ui_elements/UI.c b/src/ui_elements/UI.c index c653731..ffb66ba 100644 --- a/src/ui_elements/UI.c +++ b/src/ui_elements/UI.c @@ -1,7 +1,7 @@ #include "UI.h" #include <raylib.h> -const int MAX_LINES = 256; +const int MAX_LINES = 8192; const int SPACING_H = 1; void DrawRecBordered(Rectangle rec, Color bg, Color border_color, int border_width) { @@ -66,6 +66,7 @@ void DrawTextInRec(Rectangle rec, char *text, Font *font, int height, Color colo BeginScissorMode(rec.x, rec.y, rec.width, rec.height); for (int i = 1; i < lines; i++) { + if (i == MAX_LINES) break; Vector2 pos = { .x = rec.x, .y = vertical_acc }; char *line_start = text + spans[i-1]; int line_length = spans[i] - spans[i-1]; diff --git a/src/ui_elements/UI.h b/src/ui_elements/UI.h index f461cf5..bab154c 100644 --- a/src/ui_elements/UI.h +++ b/src/ui_elements/UI.h @@ -53,11 +53,11 @@ typedef struct { } TextArea; TextArea *CreateTextArea(TextAreaDisplayParams *DisplayParams); +TextArea *CreateTextAreaFromText(TextAreaDisplayParams *DisplayParams, char *text); + void DrawTextArea(TextArea *ta, Rectangle rec); -void InsertChar(TextArea *ta, char new_char); -void DeleteChar(TextArea *ta); +void UpdateTextArea(TextArea *ta, Rectangle rec); -void HandleKeyboard(TextArea *ta); char *GetText(TextArea *ta); void FreeTextArea(TextArea *ta); diff --git a/src/utils/stringBuilder.c b/src/utils/stringBuilder.c index 805fb34..485a83b 100644 --- a/src/utils/stringBuilder.c +++ b/src/utils/stringBuilder.c @@ -2,7 +2,7 @@ #include <stdlib.h> #include <string.h> -void AppendStringBuilder(StringBuilder *sb, const char *str, char separator) { +void AppendStringBuilder(StringBuilder *sb, const char *str) { size_t str_len = strlen(str); if (sb->val == NULL) { sb->val = malloc(str_len + 1); @@ -10,17 +10,33 @@ void AppendStringBuilder(StringBuilder *sb, const char *str, char separator) { memcpy(sb->val, str, str_len); sb->len = str_len; } else { - char *appended = realloc(sb->val, sb->len + str_len + 2); + char *appended = realloc(sb->val, sb->len + str_len + 1); if (appended == NULL) return; sb->val = appended; - sb->val[sb->len] = separator; - memcpy(sb->val + sb->len + 1, str, str_len); - sb->len = sb->len + str_len + 1; + memcpy(sb->val + sb->len, str, str_len); + sb->len = sb->len + str_len; } sb->val[sb->len] = 0x0; } +void AppendStringBuilderSep(StringBuilder *sb, const char *str, char separator) { + size_t str_len = strlen(str); + if (sb->val == NULL) { + AppendStringBuilder(sb, str); + return; + } + + char *appended = realloc(sb->val, sb->len + str_len + 2); + if (appended == NULL) return; + sb->val = appended; + + sb->val[sb->len] = separator; + memcpy(sb->val + sb->len + 1, str, str_len); + sb->len = sb->len + str_len + 1; + sb->val[sb->len] = 0x0; +} + void FreeStringBuilder(StringBuilder *sb) { if (sb->val != NULL) { free(sb->val); diff --git a/src/utils/stringBuilder.h b/src/utils/stringBuilder.h index a9730a2..07da46f 100644 --- a/src/utils/stringBuilder.h +++ b/src/utils/stringBuilder.h @@ -8,7 +8,8 @@ typedef struct { size_t len; } StringBuilder; -void AppendStringBuilder(StringBuilder *sb, const char *str, char separator); +void AppendStringBuilder(StringBuilder *sb, const char *str); +void AppendStringBuilderSep(StringBuilder *sb, const char *str, char separator); void FreeStringBuilder(StringBuilder *sb); #endif // SB_H diff --git a/src/wren_inter/wren_inter.c b/src/wren_inter/wren_inter.c index 69df112..10ecc93 100644 --- a/src/wren_inter/wren_inter.c +++ b/src/wren_inter/wren_inter.c @@ -1,51 +1,42 @@ #include "wren_inter.h" #include "../utils/stringBuilder.h" +#include <stddef.h> #include <string.h> #include <raylib.h> #include <stdio.h> #include <wren.h> -StringBuilder stdout_sb = {0}; - void writeFn(WrenVM* vm, const char* text) { - AppendStringBuilder(&stdout_sb, text, '\n'); + StringBuilder* sb = (StringBuilder*)wrenGetUserData(vm); + AppendStringBuilder(sb, text); } - + void errorFn(WrenVM* vm, WrenErrorType errorType, const char* module, const int line, const char* msg) { + StringBuilder* sb = (StringBuilder*)wrenGetUserData(vm); switch (errorType) { case WREN_ERROR_COMPILE: - { - // TraceLog(LOG_ERROR, "[%s line %d] [Error] %s", module, line, msg); - AppendStringBuilder(&stdout_sb, "Comptime error: ", '\n'); - AppendStringBuilder(&stdout_sb, msg, ' '); - } break; + AppendStringBuilder(sb, "Comptime error: "); + AppendStringBuilder(sb, msg); + break; case WREN_ERROR_STACK_TRACE: - { - AppendStringBuilder(&stdout_sb, "Stack trace: ", '\n'); - AppendStringBuilder(&stdout_sb, msg, ' '); - // TraceLog(LOG_ERROR, "[%s line %d] in %s", module, line, msg); - } break; + AppendStringBuilder(sb, "Stack trace: "); + AppendStringBuilder(sb, msg); + break; case WREN_ERROR_RUNTIME: - { - AppendStringBuilder(&stdout_sb, "Runtime error: ", '\n'); - AppendStringBuilder(&stdout_sb, msg, ' '); - // TraceLog(LOG_ERROR, "[Runtime Error] %s", msg); - } break; + AppendStringBuilder(sb, "Runtime error: "); + AppendStringBuilder(sb, msg); + break; } } char *EvaluateScript(char *script) { TraceLog(LOG_INFO, "Evaluating %s...", script); - WrenConfiguration config; - wrenInitConfiguration(&config); - config.writeFn = writeFn; - config.errorFn = errorFn; + WrenVM *vm = InterpreterPrepareMachine(); - WrenVM* vm = wrenNewVM(&config); if (vm == NULL) { TraceLog(LOG_ERROR, "Failed to initialize a wren vm"); return NULL; @@ -57,11 +48,32 @@ char *EvaluateScript(char *script) { case WREN_RESULT_COMPILE_ERROR: break; case WREN_RESULT_RUNTIME_ERROR: break; } - printf("Wren outp: %s", stdout_sb.val); - wrenFreeVM(vm); - if (stdout_sb.val == NULL) return NULL; - char *outp = strdup(stdout_sb.val); - FreeStringBuilder(&stdout_sb); + char *outp = GetMachineOutput(vm); + InterpreterFreeMachine(vm); + return outp; } + +WrenVM *InterpreterPrepareMachine() { + WrenConfiguration config; + wrenInitConfiguration(&config); + config.writeFn = writeFn; + config.errorFn = errorFn; + + StringBuilder *stdout_sb = calloc(1, sizeof(StringBuilder)); + config.userData = stdout_sb; + return wrenNewVM(&config); +} + +char *GetMachineOutput(WrenVM *vm) { + StringBuilder* sb = (StringBuilder*)wrenGetUserData(vm); + if (sb == NULL || sb->val == NULL) return NULL; + return strdup(sb->val); +} + +void InterpreterFreeMachine(WrenVM *vm) { + StringBuilder* sb = (StringBuilder*)wrenGetUserData(vm); + if (sb != NULL && sb->val != NULL) free(sb); + wrenFreeVM(vm); +} diff --git a/src/wren_inter/wren_inter.h b/src/wren_inter/wren_inter.h index 981a606..100f946 100644 --- a/src/wren_inter/wren_inter.h +++ b/src/wren_inter/wren_inter.h @@ -1,6 +1,12 @@ #ifndef WREN_INTER_H #define WREN_INTER_H +#include <wren.h> + char *EvaluateScript(char *script); +WrenVM *InterpreterPrepareMachine(); +char *GetMachineOutput(WrenVM *vm); +void InterpreterFreeMachine(WrenVM *vm); + #endif // WREN_INTER_H |
