1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
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");
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->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);
}
|