about summary refs log tree commit diff
path: root/include/3cl.h
blob: 44664904cfdfe6c3635783e4ddf7c7b4d599a356 (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
#ifndef __3CL_H__
#define __3CL_H__

#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>


#ifndef CCL_STACKSIZE
#define CCL_STACKSIZE 8192
#endif

typedef int16_t CCLNum;   /**< Abstract type for numbers in ccl */
typedef size_t  CCLAddr;  /**< Abstract type for address in ccl */

/**
 * Type of CCLFrame
 */
enum CCLFrameType
{
    CCL_ROOT,    /**< Root frame, stores global variables    */
    CCL_PROC,    /**< Function frame, stores local variables */
    CCL_INFLOOP, /**< Infinity loop, stores start and repeat */
    CCL_REPLOOP, /**< Repeat loop, stores start and repeat   */
};

/**
 * Pair which contains variable's name and value
 */
struct CCLVariable
{
    struct CCLVariable *prev, *next;
    char                name;
    CCLNum              value;
};

/**
 * Pair which contains procedure's name and address
 */
struct CCLProcedure
{
    struct CCLProcedure *prev, *next;
    char                 name;
    CCLAddr              address;
};

/**
 * Pair with length of stack and stack itself
 */
struct CCLStack
{
    size_t  length;
    size_t  cur;
    CCLNum *stack;
};

/**
 * Linked list that stores current state and allows to do recursion with local variables.
 */
struct CCLFrame
{
    struct  CCLFrame      *prev, *next;  /**< Frames are connected as linked list */
    enum    CCLFrameType   type;         /**< Type of the frame                   */
    CCLAddr                ep;           /**< Execution point                     */
    union
    {
        /* Frame stores either variables (for procedures)... */
        struct
        {
            struct  CCLVariable vars;    /**< For root frame variables are global */
        };
        /* ...or start address and repeats left (for loops) */
        struct
        {
            CCLAddr start;               /**< Used by CCL_*LOOP                   */
            int     repeats;             /**< Used by CCL_REPLOOP                 */
        };
    };
};

/**
 * Main structure for 3cl. It contains root frame, stack and code it's executing.
 */
struct CCL
{
    struct CCLStack   stack;
    struct CCLFrame   rootframe;
    const char       *code;
    bool              stopped;
    int             (*in)();
    void            (*out)(int);
};

/**
 * Inits CCL.
 * @see ccl_free
 * @see ccl_exec
 * @param ccl The structure to init
 * @param code The code to execute
 * @param in Function to get input
 * @param out Function to show output
 * @return 0 on success, any other number otherwise
 */
int ccl_init(struct CCL *ccl, const char *code, int (*in)(), void (*out)(int));

/**
 * Frees all things that ware allocated in ccl_init.
 * @see ccl_init
 * @param ccl The structure to free
 */
void ccl_free(struct CCL *ccl);

/**
 * Executes inited CCL instance
 * @see ccl_init
 * @param ccl The strcture to execute
 */
void ccl_exec(struct CCL *ccl);

#endif /* __3CL_H__ */