diff options
| -rw-r--r-- | .editorconfig | 11 | ||||
| -rw-r--r-- | CMakeLists.txt | 12 | ||||
| -rw-r--r-- | README.md | 4 | ||||
| -rw-r--r-- | include/3cl.h | 118 | ||||
| -rw-r--r-- | include/cccl.h | 52 | ||||
| -rw-r--r-- | include/instruction.h | 16 | ||||
| -rw-r--r-- | include/main.h | 5 | ||||
| -rw-r--r-- | include/operation.h | 12 | ||||
| -rw-r--r-- | include/readfile.h | 6 | ||||
| -rw-r--r-- | include/stack.h | 9 | ||||
| -rw-r--r-- | include/thirdparty/cvector/LICENSE | 21 | ||||
| -rw-r--r-- | include/thirdparty/cvector/cvector.h | 483 | ||||
| -rw-r--r-- | include/types.h | 19 | ||||
| -rw-r--r-- | include/utils.h | 5 | ||||
| -rw-r--r-- | src/3cl.c | 74 | ||||
| -rw-r--r-- | src/cccl.c | 394 | ||||
| -rw-r--r-- | src/instruction.c | 18 | ||||
| -rw-r--r-- | src/instruction/decrement.c | 8 | ||||
| -rw-r--r-- | src/instruction/increment.c | 8 | ||||
| -rw-r--r-- | src/instruction/nop.c | 7 | ||||
| -rw-r--r-- | src/instruction/pushzero.c | 10 | ||||
| -rw-r--r-- | src/main.c | 25 | ||||
| -rw-r--r-- | src/operation.c | 133 | ||||
| -rw-r--r-- | src/readfile.c | 39 | ||||
| -rw-r--r-- | src/stack.c | 22 | ||||
| -rw-r--r-- | src/utils.c | 5 |
26 files changed, 370 insertions, 1146 deletions
diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..f1bc949 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,11 @@ +root = true + +[*] +charset = utf-8 +end_of_line = lf +insert_final_newline = true + +[*.{c,h}] +indent_size = 4 +indent_style = space +trim_trailing_whitespace = true diff --git a/CMakeLists.txt b/CMakeLists.txt index 1c3f5ac..45742b9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -7,10 +7,17 @@ endif() add_executable( "${PROJECT_NAME}" - src/cccl.c + src/3cl.c + src/instruction.c + src/instruction/nop.c + src/instruction/pushzero.c + src/instruction/increment.c + src/instruction/decrement.c src/main.c - src/utils.c src/platform/getch.c + src/readfile.c + src/stack.c + src/utils.c ) set(CMAKE_EXPORT_COMPILE_COMMANDS ON CACHE INTERNAL "") @@ -19,4 +26,3 @@ set_target_properties("${PROJECT_NAME}" PROPERTIES C_STANDARD 11) set_target_properties("${PROJECT_NAME}" PROPERTIES C_EXTENSIONS FALSE) target_include_directories("${PROJECT_NAME}" PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/include") -target_include_directories("${PROJECT_NAME}" PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/include/thirdparty") diff --git a/README.md b/README.md index c22bef2..6982998 100644 --- a/README.md +++ b/README.md @@ -24,7 +24,3 @@ directory Also I think you can use some wrapper of the cmake with gui (or iirc cmake has its own gui app) - -Dependencies --- -- [cvector](https://github.com/eteran/c-vector) (header only, so included in the source) diff --git a/include/3cl.h b/include/3cl.h new file mode 100644 index 0000000..a6b9065 --- /dev/null +++ b/include/3cl.h @@ -0,0 +1,118 @@ +#ifndef __3CL_H__ +#define __3CL_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; + 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__ */ diff --git a/include/cccl.h b/include/cccl.h deleted file mode 100644 index 119adf5..0000000 --- a/include/cccl.h +++ /dev/null @@ -1,52 +0,0 @@ -#ifndef __CCCL_H__ -#define __CCCL_H__ - -#include "types.h" - -#include <stdbool.h> - - -typedef struct cccl_varpair -{ - i16 value; - s8 name; -} cccl_varpair; - -typedef struct cccl_procpair -{ - i32 value; - s8 name; -} cccl_procpair; - -typedef struct cccl_pointer -{ - i32 value; - i32 meta; -} cccl_pointer; - -typedef struct cccl_brpair -{ - i32 pointer; - s8 bracket; -} cccl_brpair; - -typedef struct cccl -{ - cccl_varpair *variables; /* Array with variables */ - cccl_procpair *procedures; /* Array with procedures */ - i16 *stack; /* User stack */ - cccl_brpair *br_stack; /* Stack for brackets */ - cccl_varpair **lv_stack; /* Local variable stack */ - cccl_pointer *ep_stack; /* Call stack */ - i32 ep; /* Pointer to current symbol */ - s8 *code; /* Code being executed */ - s8 *filename; /* File being executed */ - i32 size; /* File size */ -} cccl; - -void cccl_init(s8 *filename); -void cccl_read(void); -void cccl_run(void); -void cccl_free(void); - -#endif /* __CCCL_H__ */ diff --git a/include/instruction.h b/include/instruction.h new file mode 100644 index 0000000..449c760 --- /dev/null +++ b/include/instruction.h @@ -0,0 +1,16 @@ +#ifndef __CCL_INSTRUCTION_H__ +#define __CCL_INSTRUCTION_H__ + +#include "3cl.h" + + +typedef struct CCLFrame *(*CCLInstruction)(struct CCL *ccl, struct CCLFrame *frame); + +struct CCLFrame *ccl_instruction_nop(struct CCL *ccl, struct CCLFrame *frame); +struct CCLFrame *ccl_instruction_pushzero(struct CCL *ccl, struct CCLFrame *frame); +struct CCLFrame *ccl_instruction_increment(struct CCL *ccl, struct CCLFrame *frame); +struct CCLFrame *ccl_instruction_decrement(struct CCL *ccl, struct CCLFrame *frame); + +struct CCLFrame *ccl_instruction(struct CCL *ccl, struct CCLFrame *frame); + +#endif /* __CCL_INSTRUCTION_H__ */ diff --git a/include/main.h b/include/main.h index 9cdf6ac..ad3bdc6 100644 --- a/include/main.h +++ b/include/main.h @@ -1,9 +1,6 @@ #ifndef __MAIN_H__ #define __MAIN_H__ -#include "types.h" - - -extern const s8 *program_name; +extern const char *program_name; #endif /* __MAIN_H__ */ diff --git a/include/operation.h b/include/operation.h deleted file mode 100644 index ce487da..0000000 --- a/include/operation.h +++ /dev/null @@ -1,12 +0,0 @@ -#ifndef __OPERATION_H__ -#define __OPERATION_H__ - -#include "cccl.h" - - -typedef void (*cccl_operation)(void); - -void cccl_operation_init(cccl *pc); -cccl_operation cccl_select_operation(void); - -#endif /* __OPERATION_H__ */ diff --git a/include/readfile.h b/include/readfile.h new file mode 100644 index 0000000..5358fc7 --- /dev/null +++ b/include/readfile.h @@ -0,0 +1,6 @@ +#ifndef __READFILE_H__ +#define __READFILE_H__ + +char *readfile(const char *name); + +#endif /* __READFILE_H__ */ diff --git a/include/stack.h b/include/stack.h new file mode 100644 index 0000000..27cc2f0 --- /dev/null +++ b/include/stack.h @@ -0,0 +1,9 @@ +#ifndef __CCL_STACK_H__ +#define __CCL_STACK_H__ + +#include "3cl.h" + +void ccl_stack_push(struct CCLStack *stack, CCLNum num); +CCLNum ccl_stack_pop(struct CCLStack *stack); + +#endif /* __CCL_STACK_H__ */ diff --git a/include/thirdparty/cvector/LICENSE b/include/thirdparty/cvector/LICENSE deleted file mode 100644 index 2eb0839..0000000 --- a/include/thirdparty/cvector/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2015 Evan Teran - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/include/thirdparty/cvector/cvector.h b/include/thirdparty/cvector/cvector.h deleted file mode 100644 index 7be970d..0000000 --- a/include/thirdparty/cvector/cvector.h +++ /dev/null @@ -1,483 +0,0 @@ -/* - * Copyright (c) 2015 Evan Teran - * - * License: The MIT License (MIT) - */ - -#ifndef CVECTOR_H_ -#define CVECTOR_H_ - -#ifndef CVECTOR_LOGARITHMIC_GROWTH -#define CVECTOR_LOGARITHMIC_GROWTH -#endif - -/* cvector heap implemented using C library malloc() */ - -/* in case C library malloc() needs extra protection, - * allow these defines to be overridden. - */ -#ifndef cvector_clib_free -#include <stdlib.h> /* for free */ -#define cvector_clib_free free -#endif -#ifndef cvector_clib_malloc -#include <stdlib.h> /* for malloc */ -#define cvector_clib_malloc malloc -#endif -#ifndef cvector_clib_calloc -#include <stdlib.h> /* for calloc */ -#define cvector_clib_calloc calloc -#endif -#ifndef cvector_clib_realloc -#include <stdlib.h> /* for realloc */ -#define cvector_clib_realloc realloc -#endif -#ifndef cvector_clib_assert -#include <assert.h> /* for assert */ -#define cvector_clib_assert assert -#endif -#ifndef cvector_clib_memcpy -#include <string.h> /* for memcpy */ -#define cvector_clib_memcpy memcpy -#endif -#ifndef cvector_clib_memmove -#include <string.h> /* for memmove */ -#define cvector_clib_memmove memmove -#endif - -/* NOTE: Similar to C's qsort and bsearch, you will receive a T* - * for a vector of Ts. This means that you cannot use `free` directly - * as a destructor. Instead if you have for example a cvector_vector_type(int *) - * you will need to supply a function which casts `elem_ptr` to an `int**` - * and then does a free on what that pointer points to: - * - * ex: - * - * void free_int(void *p) { free(*(int **)p); } - */ -typedef void (*cvector_elem_destructor_t)(void *elem_ptr); - -typedef struct cvector_metadata_t { - size_t size; - size_t capacity; - cvector_elem_destructor_t elem_destructor; -} cvector_metadata_t; - -/** - * @brief cvector_vector_type - The vector type used in this library - */ -#define cvector_vector_type(type) type * - -/** - * @brief cvector - Syntactic sugar to retrieve a vector type - * - * @param type The type of vector to act on. - */ -#define cvector(type) cvector_vector_type(type) - -/* - * @brief cvector_iterator - The iterator type used for cvector - */ -#define cvector_iterator(type) cvector_vector_type(type) - -/** - * @brief cvector_vec_to_base - For internal use, converts a vector pointer to a metadata pointer - * @param vec - the vector - * @return the metadata pointer of the vector - * @internal - */ -#define cvector_vec_to_base(vec) \ - (&((cvector_metadata_t *)(vec))[-1]) - -/** - * @brief cvector_base_to_vec - For internal use, converts a metadata pointer to a vector pointer - * @param ptr - pointer to the metadata - * @return the vector - * @internal - */ -#define cvector_base_to_vec(ptr) \ - ((void *)&((cvector_metadata_t *)(ptr))[1]) - -/** - * @brief cvector_capacity - gets the current capacity of the vector - * @param vec - the vector - * @return the capacity as a size_t - */ -#define cvector_capacity(vec) \ - ((vec) ? cvector_vec_to_base(vec)->capacity : (size_t)0) - -/** - * @brief cvector_size - gets the current size of the vector - * @param vec - the vector - * @return the size as a size_t - */ -#define cvector_size(vec) \ - ((vec) ? cvector_vec_to_base(vec)->size : (size_t)0) - -/** - * @brief cvector_elem_destructor - get the element destructor function used - * to clean up elements - * @param vec - the vector - * @return the function pointer as cvector_elem_destructor_t - */ -#define cvector_elem_destructor(vec) \ - ((vec) ? cvector_vec_to_base(vec)->elem_destructor : NULL) - -/** - * @brief cvector_empty - returns non-zero if the vector is empty - * @param vec - the vector - * @return non-zero if empty, zero if non-empty - */ -#define cvector_empty(vec) \ - (cvector_size(vec) == 0) - -/** - * @brief cvector_reserve - Requests that the vector capacity be at least enough - * to contain n elements. If n is greater than the current vector capacity, the - * function causes the container to reallocate its storage increasing its - * capacity to n (or greater). - * @param vec - the vector - * @param n - Minimum capacity for the vector. - * @return void - */ -#define cvector_reserve(vec, n) \ - do { \ - size_t cv_cap__ = cvector_capacity(vec); \ - if (cv_cap__ < (n)) { \ - cvector_grow((vec), (n)); \ - } \ - } while (0) - -/* - * @brief cvector_init - Initialize a vector. The vector must be NULL for this to do anything. - * @param vec - the vector - * @param capacity - vector capacity to reserve - * @param elem_destructor_fn - element destructor function - * @return void - */ -#define cvector_init(vec, capacity, elem_destructor_fn) \ - do { \ - if (!(vec)) { \ - cvector_reserve((vec), capacity); \ - cvector_set_elem_destructor((vec), (elem_destructor_fn)); \ - } \ - } while (0) - -/** - * @brief cvector_erase - removes the element at index i from the vector - * @param vec - the vector - * @param i - index of element to remove - * @return void - */ -#define cvector_erase(vec, i) \ - do { \ - if (vec) { \ - const size_t cv_sz__ = cvector_size(vec); \ - if ((i) < cv_sz__) { \ - cvector_elem_destructor_t elem_destructor__ = cvector_elem_destructor(vec); \ - if (elem_destructor__) { \ - elem_destructor__(&(vec)[i]); \ - } \ - cvector_set_size((vec), cv_sz__ - 1); \ - cvector_clib_memmove( \ - (vec) + (i), \ - (vec) + (i) + 1, \ - sizeof(*(vec)) * (cv_sz__ - 1 - (i))); \ - } \ - } \ - } while (0) - -/** - * @brief cvector_clear - erase all of the elements in the vector - * @param vec - the vector - * @return void - */ -#define cvector_clear(vec) \ - do { \ - if (vec) { \ - cvector_elem_destructor_t elem_destructor__ = cvector_elem_destructor(vec); \ - if (elem_destructor__) { \ - size_t i__; \ - for (i__ = 0; i__ < cvector_size(vec); ++i__) { \ - elem_destructor__(&(vec)[i__]); \ - } \ - } \ - cvector_set_size(vec, 0); \ - } \ - } while (0) - -/** - * @brief cvector_free - frees all memory associated with the vector - * @param vec - the vector - * @return void - */ -#define cvector_free(vec) \ - do { \ - if (vec) { \ - void *p1__ = cvector_vec_to_base(vec); \ - cvector_elem_destructor_t elem_destructor__ = cvector_elem_destructor(vec); \ - if (elem_destructor__) { \ - size_t i__; \ - for (i__ = 0; i__ < cvector_size(vec); ++i__) { \ - elem_destructor__(&(vec)[i__]); \ - } \ - } \ - cvector_clib_free(p1__); \ - } \ - } while (0) - -/** - * @brief cvector_begin - returns an iterator to first element of the vector - * @param vec - the vector - * @return a pointer to the first element (or NULL) - */ -#define cvector_begin(vec) \ - (vec) - -/** - * @brief cvector_end - returns an iterator to one past the last element of the vector - * @param vec - the vector - * @return a pointer to one past the last element (or NULL) - */ -#define cvector_end(vec) \ - ((vec) ? &((vec)[cvector_size(vec)]) : NULL) - -/* user request to use logarithmic growth algorithm */ -#ifdef CVECTOR_LOGARITHMIC_GROWTH - -/** - * @brief cvector_compute_next_grow - returns an the computed size in next vector grow - * size is increased by multiplication of 2 - * @param size - current size - * @return size after next vector grow - */ -#define cvector_compute_next_grow(size) \ - ((size) ? ((size) << 1) : 1) - -#else - -/** - * @brief cvector_compute_next_grow - returns an the computed size in next vector grow - * size is increased by 1 - * @param size - current size - * @return size after next vector grow - */ -#define cvector_compute_next_grow(size) \ - ((size) + 1) - -#endif /* CVECTOR_LOGARITHMIC_GROWTH */ - -/** - * @brief cvector_push_back - adds an element to the end of the vector - * @param vec - the vector - * @param value - the value to add - * @return void - */ -#define cvector_push_back(vec, value) \ - do { \ - size_t cv_cap__ = cvector_capacity(vec); \ - if (cv_cap__ <= cvector_size(vec)) { \ - cvector_grow((vec), cvector_compute_next_grow(cv_cap__)); \ - } \ - (vec)[cvector_size(vec)] = (value); \ - cvector_set_size((vec), cvector_size(vec) + 1); \ - } while (0) - -/** - * @brief cvector_insert - insert element at position pos to the vector - * @param vec - the vector - * @param pos - position in the vector where the new elements are inserted. - * @param val - value to be copied (or moved) to the inserted elements. - * @return void - */ -#define cvector_insert(vec, pos, val) \ - do { \ - size_t cv_cap__ = cvector_capacity(vec); \ - if (cv_cap__ <= cvector_size(vec)) { \ - cvector_grow((vec), cvector_compute_next_grow(cv_cap__)); \ - } \ - if ((pos) < cvector_size(vec)) { \ - cvector_clib_memmove( \ - (vec) + (pos) + 1, \ - (vec) + (pos), \ - sizeof(*(vec)) * ((cvector_size(vec)) - (pos))); \ - } \ - (vec)[(pos)] = (val); \ - cvector_set_size((vec), cvector_size(vec) + 1); \ - } while (0) - -/** - * @brief cvector_pop_back - removes the last element from the vector - * @param vec - the vector - * @return void - */ -#define cvector_pop_back(vec) \ - do { \ - cvector_elem_destructor_t elem_destructor__ = cvector_elem_destructor(vec); \ - if (elem_destructor__) { \ - elem_destructor__(&(vec)[cvector_size(vec) - 1]); \ - } \ - cvector_set_size((vec), cvector_size(vec) - 1); \ - } while (0) - -/** - * @brief cvector_copy - copy a vector - * @param from - the original vector - * @param to - destination to which the function copy to - * @return void - */ -#define cvector_copy(from, to) \ - do { \ - if ((from)) { \ - cvector_grow(to, cvector_size(from)); \ - cvector_set_size(to, cvector_size(from)); \ - cvector_clib_memcpy((to), (from), cvector_size(from) * sizeof(*(from))); \ - } \ - } while (0) - -/** - * @brief cvector_swap - exchanges the content of the vector by the content of another vector of the same type - * @param vec - the original vector - * @param other - the other vector to swap content with - * @param type - the type of both vectors - * @return void - */ -#define cvector_swap(vec, other, type) \ - do { \ - if (vec && other) { \ - cvector_vector_type(type) cv_swap__ = vec; \ - vec = other; \ - other = cv_swap__; \ - } \ - } while (0) - -/** - * @brief cvector_set_capacity - For internal use, sets the capacity variable of the vector - * @param vec - the vector - * @param size - the new capacity to set - * @return void - * @internal - */ -#define cvector_set_capacity(vec, size) \ - do { \ - if (vec) { \ - cvector_vec_to_base(vec)->capacity = (size); \ - } \ - } while (0) - -/** - * @brief cvector_set_size - For internal use, sets the size variable of the vector - * @param vec - the vector - * @param size - the new capacity to set - * @return void - * @internal - */ -#define cvector_set_size(vec, _size) \ - do { \ - if (vec) { \ - cvector_vec_to_base(vec)->size = (_size); \ - } \ - } while (0) - -/** - * @brief cvector_set_elem_destructor - set the element destructor function - * used to clean up removed elements. The vector must NOT be NULL for this to do anything. - * @param vec - the vector - * @param elem_destructor_fn - function pointer of type cvector_elem_destructor_t used to destroy elements - * @return void - */ -#define cvector_set_elem_destructor(vec, elem_destructor_fn) \ - do { \ - if (vec) { \ - cvector_vec_to_base(vec)->elem_destructor = (elem_destructor_fn); \ - } \ - } while (0) - -/** - * @brief cvector_grow - For internal use, ensures that the vector is at least <count> elements big - * @param vec - the vector - * @param count - the new capacity to set - * @return void - * @internal - */ -#define cvector_grow(vec, count) \ - do { \ - const size_t cv_sz__ = (count) * sizeof(*(vec)) + sizeof(cvector_metadata_t); \ - if (vec) { \ - void *cv_p1__ = cvector_vec_to_base(vec); \ - void *cv_p2__ = cvector_clib_realloc(cv_p1__, cv_sz__); \ - cvector_clib_assert(cv_p2__); \ - (vec) = cvector_base_to_vec(cv_p2__); \ - } else { \ - void *cv_p__ = cvector_clib_malloc(cv_sz__); \ - cvector_clib_assert(cv_p__); \ - (vec) = cvector_base_to_vec(cv_p__); \ - cvector_set_size((vec), 0); \ - cvector_set_elem_destructor((vec), NULL); \ - } \ - cvector_set_capacity((vec), (count)); \ - } while (0) - -/** - * @brief cvector_shrink_to_fit - requests the container to reduce its capacity to fit its size - * @param vec - the vector - * @return void - */ -#define cvector_shrink_to_fit(vec) \ - do { \ - if (vec) { \ - const size_t cv_sz___ = cvector_size(vec); \ - cvector_grow(vec, cv_sz___); \ - } \ - } while (0) - -/** - * @brief cvector_at - returns a reference to the element at position n in the vector. - * @param vec - the vector - * @param n - position of an element in the vector. - * @return the element at the specified position in the vector. - */ -#define cvector_at(vec, n) \ - ((vec) ? (((int)(n) < 0 || (size_t)(n) >= cvector_size(vec)) ? NULL : &(vec)[n]) : NULL) - -/** - * @brief cvector_front - returns a reference to the first element in the vector. Unlike member cvector_begin, which returns an iterator to this same element, this function returns a direct reference. - * @return a reference to the first element in the vector container. - */ -#define cvector_front(vec) \ - ((vec) ? ((cvector_size(vec) > 0) ? cvector_at(vec, 0) : NULL) : NULL) - -/** - * @brief cvector_back - returns a reference to the last element in the vector.Unlike member cvector_end, which returns an iterator just past this element, this function returns a direct reference. - * @return a reference to the last element in the vector. - */ -#define cvector_back(vec) \ - ((vec) ? ((cvector_size(vec) > 0) ? cvector_at(vec, cvector_size(vec) - 1) : NULL) : NULL) - -/** - * @brief cvector_resize - resizes the container to contain count elements. - * @param vec - the vector - * @param count - new size of the vector - * @param value - the value to initialize new elements with - * @return void - */ -#define cvector_resize(vec, count, value) \ - do { \ - if (vec) { \ - size_t cv_sz_count__ = (size_t)(count); \ - size_t cv_sz__ = cvector_vec_to_base(vec)->size; \ - if (cv_sz_count__ > cv_sz__) { \ - cvector_reserve((vec), cv_sz_count__); \ - cvector_set_size((vec), cv_sz_count__); \ - do { \ - (vec)[cv_sz__++] = (value); \ - } while (cv_sz__ < cv_sz_count__); \ - } else { \ - while (cv_sz_count__ < cv_sz__--) { \ - cvector_pop_back(vec); \ - } \ - } \ - } \ - } while (0) - -#endif /* CVECTOR_H_ */ diff --git a/include/types.h b/include/types.h deleted file mode 100644 index 4bf1da9..0000000 --- a/include/types.h +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef __TYPES_H__ -#define __TYPES_H__ - -#include <stdint.h> - - -typedef char s8; - -typedef uint8_t u8; -typedef uint16_t u16; -typedef uint32_t u32; -typedef uint64_t i64; - -typedef int8_t i8; -typedef int16_t i16; -typedef int32_t i32; -typedef uint64_t i64; - -#endif /* __TYPES_H__ */ diff --git a/include/utils.h b/include/utils.h index 29c59f1..40bb642 100644 --- a/include/utils.h +++ b/include/utils.h @@ -3,9 +3,6 @@ #include <stdnoreturn.h> -#include "types.h" - - -noreturn void die(i32 code, s8 *fmt, ...); +noreturn void die(int code, char *fmt, ...); #endif /* __UTILS_H__ */ 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; |