about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/3cl.c74
-rw-r--r--src/cccl.c394
-rw-r--r--src/instruction.c18
-rw-r--r--src/instruction/decrement.c8
-rw-r--r--src/instruction/increment.c8
-rw-r--r--src/instruction/nop.c7
-rw-r--r--src/instruction/pushzero.c10
-rw-r--r--src/main.c25
-rw-r--r--src/operation.c133
-rw-r--r--src/readfile.c39
-rw-r--r--src/stack.c22
-rw-r--r--src/utils.c5
12 files changed, 199 insertions, 544 deletions
diff --git a/src/3cl.c b/src/3cl.c
new file mode 100644
index 0000000..c8016a9
--- /dev/null
+++ b/src/3cl.c
@@ -0,0 +1,74 @@
+#include "3cl.h"
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "instruction.h"
+
+
+int ccl_init(struct CCL *ccl, const char *code, int (*in)(), void (*out)(int))
+{
+    *ccl = (struct CCL)
+    {
+        .code = code,
+        .in = in,
+        .out = out,
+        .rootframe = (struct CCLFrame)
+        {
+            .prev = NULL, .next = NULL,
+            .type = CCL_ROOT,
+            .ep = 0,
+            .vars = (struct CCLVariable)
+            {
+                .prev = NULL,
+                .next = NULL,
+                .name = '_',
+                .value = 0
+            },
+        },
+        .stack = (struct CCLStack)
+        {
+            .length = CCL_STACKSIZE,
+            .stack = (CCLNum *)malloc(CCL_STACKSIZE)
+        },
+    };
+
+    return errno;
+}
+
+void ccl_free(struct CCL *ccl)
+{
+    free(ccl->stack.stack);
+    if (ccl->rootframe.next != NULL)
+    {
+        for (struct CCLFrame *frame = ccl->rootframe.next, *new;;)
+        {
+            if (frame->vars.next != NULL)
+            {
+                for (struct CCLVariable *var = frame->vars.next, *new;;)
+                {
+                    if (var->next == NULL)
+                        break;
+                    new = var->next;
+                    free(var);
+                    var = new;
+                }
+            }
+
+            if (frame->next == NULL)
+                break;
+            new = frame->next;
+            free(frame);
+            frame = new;
+        }
+    }
+}
+
+void ccl_exec(struct CCL *ccl)
+{
+    struct CCLFrame *curframe = &ccl->rootframe;
+
+    for (;;++curframe->ep)
+        curframe = ccl_instruction(ccl, curframe);
+}
diff --git a/src/cccl.c b/src/cccl.c
deleted file mode 100644
index e2bb788..0000000
--- a/src/cccl.c
+++ /dev/null
@@ -1,394 +0,0 @@
-#include "cccl.h"
-#include "types.h"
-
-#include <cvector/cvector.h>
-#include <errno.h>
-#include <stdbool.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "operation.h"
-#include "platform/getch.h"
-#include "utils.h"
-
-
-static cccl pc = {0};
-static const s8 *const name_allowed   = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
-static const s8 *const name_allowed_  = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_";
-static const s8 *const all_allowed    = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_{}[]()?;@=!&$%<>^+-*~#:/ \n\t";
-static const s8 *const skippable      = " \t\n";
-static const s8 *const open_brackets  = "[({?";
-static const s8 *const close_brackets = "])};";
-
-static void cccl_varpair_free(void *p)
-{
-    cvector_free(*(cccl_varpair **)p);
-}
-
-void cccl_init(s8 *filename)
-{
-    memset(&pc, 0, sizeof(pc));
-
-    cvector_init(pc.stack,      1, NULL);
-    cvector_init(pc.variables,  1, NULL);
-    cvector_init(pc.procedures, 1, NULL);
-    cvector_init(pc.lv_stack,   1, cccl_varpair_free);
-    cvector_init(pc.ep_stack,   1, NULL);
-    if (errno) die(1, strerror(errno));
-
-    pc.filename = filename;
-    cccl_operation_init(&pc);
-}
-
-void cccl_free()
-{
-    cvector_free(pc.stack);
-    cvector_free(pc.variables);
-    cvector_free(pc.procedures);
-    cvector_free(pc.lv_stack);
-    cvector_free(pc.ep_stack);
-    free(pc.code);
-}
-
-void cccl_read(void)
-{
-    s8 chr;
-    FILE *file = fopen(pc.filename, "r");
-    if (errno) die(1, strerror(errno));
-        fseek(file, 0, SEEK_END);
-        pc.size = ftell(file);
-        fseek(file, 0, SEEK_SET);
-        pc.code = calloc(pc.size + 1, sizeof(s8));
-
-        for (u32 i = 0; i < pc.size; ++i)
-        {
-            if ((chr = fgetc(file)) == EOF)
-            {
-                if (errno)
-                {
-                    fclose(file);
-                    die(1, strerror(errno));
-                }
-                else
-                {
-                    break;
-                }
-            }
-            pc.code[i] = chr;
-        }
-    fclose(file);
-}
-
-static void check_symbol(void)
-{
-    if (!strchr(all_allowed, pc.code[pc.ep]))
-        die(1, "illegal character (%u at %d)", pc.code[pc.ep], pc.ep);
-}
-
-static void require_stack_size(u32 size, i32 start)
-{
-    if (cvector_size(pc.stack) < size)
-        die(1, "stack size is %d, but %d is required (%c at %d)", cvector_size(pc.stack), size, pc.code[start], start);
-}
-
-static i32 require_variable_local(s8 name)
-{
-    if (cvector_size(pc.lv_stack) > 0)
-        for (i32 i = 0; i < cvector_size(pc.lv_stack[cvector_size(pc.lv_stack) - 1]); ++i)
-            if (pc.lv_stack[cvector_size(pc.lv_stack) - 1][i].name == name)
-                return i;
-    return -1;
-}
-
-static i32 require_variable(s8 name)
-{
-    for (i32 i = 0; i < cvector_size(pc.variables); ++i)
-        if (pc.variables[i].name == name)
-            return i;
-    return -1;
-}
-
-static i32 require_procedure(s8 name)
-{
-    for (i32 i = 0; i < cvector_size(pc.procedures); ++i)
-        if (pc.procedures[i].name == name)
-            return i;
-    return -1;
-}
-
-static i32 find_bracket(i32 start)
-{
-    i32 start_length = cvector_size(pc.br_stack);
-    cccl_brpair brpair;
-    for (i32 pointer = pc.ep+1; pointer < pc.size; ++pointer)
-    {
-        check_symbol();
-        if (strchr(skippable, pc.code[pointer])) continue;
-        else if (strchr(open_brackets, pc.code[pointer]))
-        {
-            brpair = (cccl_brpair){.pointer=pointer, .bracket=close_brackets[strchr(open_brackets, pc.code[pointer]) - open_brackets]};
-            cvector_push_back(pc.br_stack, brpair);
-        }
-        else if (strchr(close_brackets, pc.code[pointer]))
-        {
-            if (pc.code[pointer] != pc.br_stack[cvector_size(pc.br_stack) - 1].bracket)
-                die(1, "invalid bracket (%c at %d for %c at %d)", pc.code[pointer], pointer, pc.code[pc.br_stack[cvector_size(pc.br_stack) - 1].pointer], pc.br_stack[cvector_size(pc.br_stack) - 1].pointer);
-            cvector_pop_back(pc.br_stack);
-        }
-        if (cvector_size(pc.br_stack) < start_length) return pointer;
-    }
-    die(1, "unclosed bracket (%c at %d)", pc.code[start], start);
-}
-
-static s8 read_operand(bool allow_underscore)
-{
-    i32 start = pc.ep;
-    for (++pc.ep; pc.ep < pc.size; ++pc.ep)
-    {
-        check_symbol();
-        if (strchr(skippable, pc.code[pc.ep])) continue;
-        if (!strchr(allow_underscore ? name_allowed_ : name_allowed, pc.code[pc.ep]))
-            die(1, "invalid operand name (%c at %d for %c at %d)", pc.code[pc.ep], pc.ep, pc.code[start], start);
-        return pc.code[pc.ep];
-    }
-    die(1, "no operand (for %c at %d)", pc.code[start], start);
-}
-
-void cccl_run(void)
-{
-    i32 variable, start, var, bracket;
-    cccl_varpair varpair;
-    cccl_pointer pointer;
-    cccl_brpair  brpair;
-    s8 operand;
-    bool is_comment;
-    for (pc.ep = 0; pc.ep < pc.size; ++pc.ep)
-    {
-        if (is_comment && pc.code[pc.ep] == '\n')
-            is_comment = false;
-        else if (is_comment)
-            continue;
-        check_symbol();
-        start = pc.ep;
-        switch (pc.code[pc.ep])
-        {
-        case ' ':
-        case '\t':
-        case ';':
-            break;
-        case '/':
-            is_comment = true;
-            break;
-        case '^':
-            cvector_push_back(pc.stack, 0);
-            break;
-        case '+':
-            require_stack_size(1, pc.ep);
-            ++pc.stack[cvector_size(pc.stack) - 1];
-            break;
-        case '-':
-            require_stack_size(1, pc.ep);
-            --pc.stack[cvector_size(pc.stack) - 1];
-            break;
-        case '*':
-            require_stack_size(2, pc.ep);
-            pc.stack[cvector_size(pc.stack) - 2] += pc.stack[cvector_size(pc.stack) - 1];
-            cvector_pop_back(pc.stack);
-            break;
-        case '~':
-            require_stack_size(2, pc.ep);
-            pc.stack[cvector_size(pc.stack) - 2] -= pc.stack[cvector_size(pc.stack) - 1];
-            cvector_pop_back(pc.stack);
-            break;
-        case '%':
-            operand = read_operand(true);
-            i16 *to_reverse = NULL;
-            i32 size;
-            if (operand == '_')
-            {
-                size = cvector_size(pc.stack);
-            }
-            else
-            {
-                if ((var = require_variable_local(operand)) == -1)
-                {
-                    if ((var = require_variable(operand)) == -1)
-                        die(1, "no %c variable found (%% at %d)", operand, start);
-                    else
-                        size = pc.lv_stack[cvector_size(pc.lv_stack) - 1][var].value;
-                } else
-                {
-                    size = pc.variables[var].value;
-                }
-            }
-            if (size < 1)
-                die(1, "invalid argument %d, should be not less than 1 (%% at %d)", size, start);
-            require_stack_size(size, start);
-            cvector_init(to_reverse, size, NULL);
-            for (int i = 0; i < size; ++i)
-            {
-                cvector_push_back(to_reverse, pc.stack[cvector_size(pc.stack) - 1]);
-                cvector_pop_back(pc.stack);
-            }
-            for (int i = 0; i < size; ++i)
-                cvector_push_back(pc.stack, to_reverse[i]);
-            cvector_free(to_reverse);
-            break;
-        case '=':
-            operand = read_operand(true);
-            require_stack_size(1, start);
-            varpair = (cccl_varpair){.name=operand, .value=pc.stack[cvector_size(pc.stack) - 1]};
-            if (operand != '_')
-            {
-                if ((var = require_variable_local(operand)) == -1)
-                    if ((var = require_variable(operand)) == -1)
-                        cvector_push_back(pc.variables, varpair);
-                    else
-                        pc.variables[var] = varpair;
-                else
-                    pc.lv_stack[cvector_size(pc.lv_stack) - 1][var] = varpair;
-            }
-            cvector_pop_back(pc.stack);
-            break;
-        case '!':
-            operand = read_operand(false);
-            if ((var = require_variable_local(operand)) == -1)
-                if ((var = require_variable(operand)) == -1)
-                    die(1, "no %c variable found (! at %d)", operand, start);
-                else
-                    cvector_erase(pc.variables, var);
-            else
-                cvector_erase(pc.lv_stack[cvector_size(pc.lv_stack) - 1], var);
-            break;
-        case '$':
-            operand = read_operand(false);
-            i16 value;
-            if ((var = require_variable_local(operand)) == -1)
-                if ((var = require_variable(operand)) == -1)
-                    die(1, "no %c variable found ($ at %d)", operand, start);
-                else
-                    value = pc.variables[var].value;
-            else
-                value = pc.lv_stack[cvector_size(pc.lv_stack) - 1][var].value;
-            cvector_push_back(pc.stack, value);
-            break;
-        case '&':
-            operand = read_operand(false);
-            if (cvector_size(pc.lv_stack) == 0)
-                die(1, "local variables cannot be created in global scope (& at %d)", start);
-            varpair = (cccl_varpair){.name=operand, .value=0};
-            if (require_variable_local(operand) == -1)
-                cvector_push_back(pc.lv_stack[cvector_size(pc.lv_stack) - 1], varpair);
-            break;
-        case '<':
-            operand = read_operand(false);
-            if ((var = require_variable_local(operand)) == -1)
-                if ((var = require_variable(operand)) == -1)
-                    die(1, "no %c variable found (< at %d)", operand, start);
-                else
-                    printf("%c", pc.variables[var].value);
-            else
-                printf("%c", pc.lv_stack[cvector_size(pc.lv_stack) - 1][var].value);
-            break;
-        case '>':
-            operand = read_operand(false);
-            i16 *to_store;
-            if ((var = require_variable_local(operand)) == -1)
-                if ((var = require_variable(operand)) == -1)
-                    die(1, "no %c variable found (> at %d)", operand, start);
-                else
-                    to_store = &pc.variables[var].value;
-            else
-                to_store = &pc.lv_stack[cvector_size(pc.lv_stack) - 1][var].value;
-            *to_store = getch();
-            break;
-        case '@':
-            operand = read_operand(false);
-            if ((var = require_procedure(operand)) == -1)
-                die(1, "no %c procedure found (@ at %d)", operand, start);
-            pointer = (cccl_pointer){.value=pc.ep, .meta=0};
-            cvector_push_back(pc.ep_stack, pointer);
-            pc.ep = pc.procedures[var].value;
-            break;
-        case '#':
-            if (cvector_size(pc.lv_stack) == 0)
-                exit(0);
-            pc.ep = pc.ep_stack[cvector_size(pc.ep_stack) - 1].value;
-            if (pc.ep_stack[cvector_size(pc.ep_stack) - 1].meta != -1)
-                cvector_pop_back(pc.ep_stack);
-            cvector_pop_back(pc.ep_stack);
-            break;
-        case ':':
-            if (pc.ep_stack[cvector_size(pc.ep_stack) - 1].meta == -1)
-            {
-                die(1, "not in a loop (: at %d)", start);
-            } else if (pc.ep_stack[cvector_size(pc.ep_stack) - 1].meta == 0)
-            {
-                pc.ep = pc.ep_stack[cvector_size(pc.ep_stack) - 1].value;
-                cvector_pop_back(pc.ep_stack);
-                cvector_pop_back(pc.ep_stack);
-            } else
-            {
-                if (pc.ep_stack[cvector_size(pc.ep_stack) - 1].meta > 0)
-                    --pc.ep_stack[cvector_size(pc.ep_stack) - 1].meta;
-                pc.ep = pc.ep_stack[cvector_size(pc.ep_stack) - 2].value;
-            }
-            break;
-        case '}':
-            pc.ep = pc.ep_stack[cvector_size(pc.ep_stack) - 1].value;
-            cvector_pop_back(pc.ep_stack);
-            break;
-        case ')':
-            pc.ep = pc.ep_stack[cvector_size(pc.ep_stack) - 2].value;
-            break;
-        case ']':
-            if (pc.ep_stack[cvector_size(pc.ep_stack) - 1].meta == 0)
-            {
-                pc.ep = pc.ep_stack[cvector_size(pc.ep_stack) - 1].value;
-                cvector_pop_back(pc.ep_stack);
-                cvector_pop_back(pc.ep_stack);
-            } else
-            {
-                --pc.ep_stack[cvector_size(pc.ep_stack) - 1].meta;
-                pc.ep = pc.ep_stack[cvector_size(pc.ep_stack) - 2].value;
-            }
-            break;
-        case '(':
-            pointer = (cccl_pointer){.value=start, .meta=-2};
-            brpair = (cccl_brpair){.pointer=start, .bracket=')'};
-            cvector_push_back(pc.br_stack, brpair);
-            bracket = find_bracket(start);
-            cvector_push_back(pc.ep_stack, pointer);
-            pointer.value = bracket;
-            cvector_push_back(pc.ep_stack, pointer);
-            break;
-        case '?':
-            operand = read_operand(false);
-            if ((var = require_variable_local(operand)) == -1)
-                if ((var = require_variable(operand)) == -1)
-                    die(1, "no %c variable found (? at %d)", operand, start);
-                else
-                    var = pc.variables[var].value;
-            else
-                var = pc.lv_stack[cvector_size(pc.lv_stack) - 1][var].value;
-            if (var != pc.stack[cvector_size(pc.stack) - 1])
-            {
-                brpair = (cccl_brpair){.pointer=start, .bracket='?'};
-                cvector_push_back(pc.br_stack, brpair);
-                bracket = find_bracket(start);
-                pc.ep = bracket;
-            }
-            break;
-        }
-    }
-    printf("Stack: ^^^\n");
-    for (int i = 0; i < cvector_size(pc.stack); ++i)
-        printf("%d\n", pc.stack[i]);
-    printf("Variables:\n");
-    for (int i = 0; i < cvector_size(pc.variables); ++i)
-        printf("%c:%d\n", pc.variables[i].name, pc.variables[i].value);
-    printf("Call stack:\n");
-    for (int i = 0; i < cvector_size(pc.ep_stack); ++i)
-        printf("%d(%d)", pc.ep_stack[i].value, pc.ep_stack[i].meta);
-}
diff --git a/src/instruction.c b/src/instruction.c
new file mode 100644
index 0000000..8597d74
--- /dev/null
+++ b/src/instruction.c
@@ -0,0 +1,18 @@
+#include "instruction.h"
+
+#include "3cl.h"
+
+struct CCLFrame *ccl_instruction(struct CCL *ccl, struct CCLFrame *frame)
+{
+    CCLInstruction instruction;
+    switch (ccl->code[frame->ep])
+    {
+    case '\n': /* FALLTHROUGH */
+    case ' ' : /* FALLTHROUGH */
+    case '\t': instruction = ccl_instruction_nop;
+    case '^' : instruction = ccl_instruction_pushzero;
+    case '+' : instruction = ccl_instruction_increment;
+    case '-' : instruction = ccl_instruction_decrement;
+    }
+    return instruction(ccl, frame);
+}
diff --git a/src/instruction/decrement.c b/src/instruction/decrement.c
new file mode 100644
index 0000000..f7f54dd
--- /dev/null
+++ b/src/instruction/decrement.c
@@ -0,0 +1,8 @@
+#include "3cl.h"
+#include "instruction.h"
+
+struct CCLFrame *ccl_instruction_decrement(struct CCL *ccl, struct CCLFrame *frame)
+{
+    --ccl->stack.stack[ccl->stack.cur];
+    return frame;
+}
diff --git a/src/instruction/increment.c b/src/instruction/increment.c
new file mode 100644
index 0000000..51697f1
--- /dev/null
+++ b/src/instruction/increment.c
@@ -0,0 +1,8 @@
+#include "3cl.h"
+#include "instruction.h"
+
+struct CCLFrame *ccl_instruction_increment(struct CCL *ccl, struct CCLFrame *frame)
+{
+    ++ccl->stack.stack[ccl->stack.cur];
+    return frame;
+}
diff --git a/src/instruction/nop.c b/src/instruction/nop.c
new file mode 100644
index 0000000..8e05396
--- /dev/null
+++ b/src/instruction/nop.c
@@ -0,0 +1,7 @@
+#include "3cl.h"
+#include "instruction.h"
+
+struct CCLFrame *ccl_instruction_nop(struct CCL *ccl, struct CCLFrame *frame)
+{
+    return frame;
+}
diff --git a/src/instruction/pushzero.c b/src/instruction/pushzero.c
new file mode 100644
index 0000000..ef380cd
--- /dev/null
+++ b/src/instruction/pushzero.c
@@ -0,0 +1,10 @@
+#include "3cl.h"
+#include "instruction.h"
+
+#include "stack.h"
+
+struct CCLFrame *ccl_instruction_pushzero(struct CCL *ccl, struct CCLFrame *frame)
+{
+    ccl_stack_push(&ccl->stack, 0);
+    return frame;
+}
diff --git a/src/main.c b/src/main.c
index 0d69855..2df5779 100644
--- a/src/main.c
+++ b/src/main.c
@@ -1,5 +1,4 @@
 #include "main.h"
-#include "types.h"
 
 #include <getopt.h>
 #include <stdbool.h>
@@ -7,15 +6,16 @@
 #include <stdlib.h>
 #include <stdnoreturn.h>
 
-#include "cccl.h"
 #include "platform/getch.h"
+#include "3cl.h"
+#include "readfile.h"
 
 
-const s8 *program_name;
+const char *program_name;
 
-static const s8 *const usage_message =
+static const char *const usage_message =
     "usage: %s [-h] file\n";
-static const s8 *const usage_description =
+static const char *const usage_description =
     "ccl language interpreter\n"
     "Arguments:\n"
     "  file         file to execute\n"
@@ -35,12 +35,12 @@ noreturn void usage(bool full)
     exit(full ? 0 : 1);
 }
 
-int main(i32 argc, s8 **argv)
+int main(int argc, char **argv)
 {
     program_name = argv[0];
     getch_init();
 
-    i32 ch;
+    int ch;
     while ((ch = getopt_long(argc, argv, "h", long_options, NULL)) != EOF)
     {
         switch (ch)
@@ -56,10 +56,9 @@ int main(i32 argc, s8 **argv)
     if (argv[optind] == NULL)
         usage(false);
 
-    cccl_init(argv[optind]);
-        cccl_read();
-        cccl_run();
-    cccl_free();
-
-    return 0;
+    char *code = readfile(argv[optind]);
+    struct CCL ccl;
+    ccl_init(&ccl, code, getch, (void(*)(int))putchar);
+    free(code);
+    ccl_free(&ccl);
 }
diff --git a/src/operation.c b/src/operation.c
deleted file mode 100644
index c56e381..0000000
--- a/src/operation.c
+++ /dev/null
@@ -1,133 +0,0 @@
-#include "operation.h"
-#include "types.h"
-
-#include <cvector/cvector.h>
-#include <stdbool.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "cccl.h"
-#include "utils.h"
-
-
-static cccl *pc;
-static bool is_comment;
-static i32  current;
-
-static const s8 *const name_allowed             = "_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
-static const s8 *const all_allowed              = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_{}[]()?;@=!&$%<>^+-*~#:/ \n\t";
-static const s8 *const skippable                = " \t\n";
-static const s8 *const open_brackets            = "[({?";
-static const s8 *const close_brackets           = "])};";
-
-static void check_symbol(void)
-{
-    if (!strchr(all_allowed, pc->code[pc->ep]))
-        die(1, "illegal character (%u at %d)", pc->code[pc->ep], pc->ep);
-}
-
-static s8 read_operand(bool allow_underscore)
-{
-    i32 start = pc->ep;
-    for (++pc->ep; pc->ep < pc->size; ++pc->ep)
-    {
-        check_symbol();
-        if (strchr(skippable, pc->code[pc->ep]))
-            continue;
-        if (!strchr(allow_underscore ? name_allowed : name_allowed + 1, pc->code[pc->ep]))
-            die(
-                1, "invalid operand name (%c at %d for %c at %d)",
-                pc->code[pc->ep], pc->ep,
-                pc->code[start], start
-            );
-        return pc->code[pc->ep];
-    }
-    die(
-        1, "no operand (for %c at %d)",
-        pc->code[start], start
-    );
-}
-
-static void require_stack_size(u32 size)
-{
-    if (cvector_size(pc->stack) < size)
-        die(1, "stack size is %d, but %d is required (%c at %d)", cvector_size(pc->stack), size, pc->code[current], current);
-}
-
-static void op_noth(void) {}
-
-static void op_comment(void)
-{
-    is_comment = !is_comment;
-}
-
-static void op_pushzero(void)
-{
-    cvector_push_back(pc->stack, 0);
-}
-
-static void op_increment(void)
-{
-    require_stack_size(1);
-    ++*cvector_back(pc->stack);
-}
-
-static void op_decrement(void)
-{
-    require_stack_size(1);
-    --*cvector_back(pc->stack);
-}
-
-static void op_add(void)
-{
-    require_stack_size(2);
-    *(cvector_back(pc->stack) - 1) += *cvector_back(pc->stack);
-    cvector_pop_back(pc->stack);
-}
-
-static void op_sub(void)
-{
-    require_stack_size(2);
-    *(cvector_back(pc->stack) - 1) -= *cvector_back(pc->stack);
-    cvector_pop_back(pc->stack);
-}
-
-static void op_reverse(void)
-{
-    s8 operand = read_operand(true);
-    i16 *to_reverse = NULL;
-    i32 size;
-
-    if (operand == '_')
-        size = cvector_size(pc->stack);
-}
-
-void cccl_operation_init(cccl *pcp)
-{
-    pc = pcp;
-    is_comment = false;
-    current = 0;
-}
-
-cccl_operation cccl_select_operation(void)
-{
-    if (is_comment && pc->code[pc->ep] == '\n')
-        return op_comment;
-    if (is_comment)
-        return op_noth;
-
-    current = pc->ep;
-    check_symbol();
-
-    switch (pc->code[pc->ep])
-    {
-    case ' ':  /* FALLTHROUGH */
-    case '\t': /* FALLTHROUGH */
-    case ';':  return op_noth;
-    case '/':  return op_comment;
-    case '^':  return op_pushzero;
-    case '+':  return op_increment;
-    case '-':  return op_decrement;
-    default:   die(1, "You shouldn't be there!");
-    }
-}
diff --git a/src/readfile.c b/src/readfile.c
new file mode 100644
index 0000000..8a0ff2e
--- /dev/null
+++ b/src/readfile.c
@@ -0,0 +1,39 @@
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "utils.h"
+
+
+char *readfile(const char *name)
+{
+    char *code, chr;
+    FILE *file = fopen(name, "r");
+    if (errno) die(1, strerror(errno));
+        fseek(file, 0, SEEK_END);
+        size_t size = ftell(file);
+        fseek(file, 0, SEEK_SET);
+        code = calloc(size + 1, sizeof(*code));
+
+        for (int i = 0; i < size; ++i)
+        {
+            if ((chr = fgetc(file)) == EOF)
+            {
+                if (errno)
+                {
+                    fclose(file);
+                    die(1, strerror(errno));
+                }
+                else
+                {
+                    break;
+                }
+            }
+            code[i] = chr;
+        }
+        code[size - 1] = '\0';
+    fclose(file);
+
+    return code;
+}
diff --git a/src/stack.c b/src/stack.c
new file mode 100644
index 0000000..3a1f697
--- /dev/null
+++ b/src/stack.c
@@ -0,0 +1,22 @@
+#include "3cl.h"
+
+#include <stdlib.h>
+
+
+static inline void resize(struct CCLStack *stack)
+{
+    stack->length *= 2;
+    stack->stack = realloc(stack->stack, stack->length * sizeof(*stack->stack));
+}
+
+void ccl_stack_push(struct CCLStack *stack, CCLNum num)
+{
+    if (stack->cur + 1 == stack->length)
+        resize(stack);
+    stack->stack[++stack->cur] = num;
+}
+
+CCLNum ccl_stack_pop(struct CCLStack *stack, CCLNum num)
+{
+    return stack->stack[stack->cur--];
+}
diff --git a/src/utils.c b/src/utils.c
index 978396c..ba5638f 100644
--- a/src/utils.c
+++ b/src/utils.c
@@ -1,6 +1,3 @@
-#include "utils.h"
-#include "types.h"
-
 #include <stdarg.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -9,7 +6,7 @@
 #include "main.h"
 
 
-noreturn void die(i32 code, s8 *fmt, ...)
+noreturn void die(int code, char *fmt, ...)
 {
     va_list args;