summaryrefslogtreecommitdiff
path: root/src/puzzles/puzzle.c
blob: 22f7a4d56dbe0eac77d29a6ef094be26165a0eb9 (plain)
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);
}