From 2d5f634d0d28a0762835afa01dd1e9eb212e4803 Mon Sep 17 00:00:00 2001 From: Nakidai Date: Tue, 25 Mar 2025 14:35:06 +0300 Subject: Implement all instructions Something doesn't work, though --- Makefile | 1 + cccl.c | 4 +-- cccl.h | 8 ++++-- executor.c | 96 ++++++++++++++++++++++++++++++++++++++++---------------------- parser.c | 6 ++-- str.c | 57 +++++++++++++++++++++++++++++++++++++ 6 files changed, 131 insertions(+), 41 deletions(-) create mode 100644 str.c diff --git a/Makefile b/Makefile index e503ccb..a1a5d01 100644 --- a/Makefile +++ b/Makefile @@ -3,6 +3,7 @@ OBJS += executor.o OBJS += main.o OBJS += parser.o OBJS += readfile.o +OBJS += str.o OBJS += tokenizer.o RM ?= rm -f diff --git a/cccl.c b/cccl.c index 64da3b1..234fa7e 100644 --- a/cccl.c +++ b/cccl.c @@ -14,6 +14,6 @@ void cccl(struct cccl_File file) struct cccl_Node *parsed = cccl_parse(tokens, tokens_amount, 0, 0); - struct cccl_Variables scope; - cccl_execute(parsed, &scope); + struct cccl_Variables scope = {0}; + cccl_execute(parsed, &scope, 0); } diff --git a/cccl.h b/cccl.h index 37b0970..5452b26 100644 --- a/cccl.h +++ b/cccl.h @@ -65,7 +65,7 @@ enum cccl_ExecutorStatus { cccl_Executr_OK = 0, cccl_Executor_ERROR, - cccl_EXECUTOR_CONTINUE, + cccl_Executor_CONTINUE, cccl_Executor_END, }; @@ -95,6 +95,10 @@ int cccl_allocfile(const char *path, struct cccl_File *file); void cccl(struct cccl_File file); size_t cccl_tokenize(const char *code, size_t size, struct cccl_Token tokens[], size_t tokens_length); struct cccl_Node *cccl_parse(struct cccl_Token tokens[], size_t tokens_length, enum cccl_NodeType type, char value); -enum cccl_ExecutorStatus cccl_execute(struct cccl_Node *code, struct cccl_Variables *scope); +enum cccl_ExecutorStatus cccl_execute(struct cccl_Node *code, struct cccl_Variables *scope, size_t depth); + +const char *strtoken(enum cccl_TokenType type); +const char *strnode(enum cccl_NodeType type); +const char *strstatus(enum cccl_ExecutorStatus status); #endif /* __CCCL_H__ */ diff --git a/executor.c b/executor.c index 0458f1c..e39df2c 100644 --- a/executor.c +++ b/executor.c @@ -41,19 +41,25 @@ static short *get_variable(char name, struct cccl_Variables *scope) return NULL; } -enum cccl_ExecutorStatus cccl_execute(struct cccl_Node *code, struct cccl_Variables *scope) +enum cccl_ExecutorStatus cccl_execute(struct cccl_Node *code, struct cccl_Variables *scope, size_t depth) { + if (verbose) + if (code->value) + fprintf(stderr, "Executing %s with %d [%c], %lu nodes, depth %lu\n", strnode(code->type), code->value, code->value, code->in_length, depth); + else + fprintf(stderr, "Executing %s, %lu nodes, depth %lu\n", strnode(code->type), code->in_length, depth); switch (code->type) { case cccl_Node_CODE: { - int res; + enum cccl_ExecutorStatus res; for (size_t i = 0; i < code->in_length; ++i) - if ((res = cccl_execute(code->in[i], scope)) != 0) - goto code_end; -code_end: - if (res == cccl_Executor_ERROR) - return res; + switch ((res = cccl_execute(code->in[i], scope, depth + 1))) + { + case cccl_Executor_ERROR: return res; + case cccl_Executor_CONTINUE: return cccl_Executor_ERROR; + case cccl_Executor_END: goto end; + } } break; case cccl_Node_PUSHZERO: { @@ -197,56 +203,78 @@ code_end: size_t i = geti(code->value); struct cccl_Variables localscope = {0}; - int res; + enum cccl_ExecutorStatus res; for (size_t j = 0; j < functions[i].length; ++j) - if ((res = cccl_execute(functions[i].body[j], &localscope)) != 0) - goto call_end; -call_end: - if (res == cccl_Executor_ERROR) - return res; + switch ((res = cccl_execute(functions[i].body[j], &localscope, depth + 1))) + { + case cccl_Executor_ERROR: return res; + case cccl_Executor_CONTINUE: return cccl_Executor_ERROR; + case cccl_Executor_END: goto end; + } } break; case cccl_Node_INFINITE: { - int res; + short *p; if (code->value == '_') - for (;;) - for (size_t i = 0; i < code->in_length; ++i) - if ((res = cccl_execute(code->in[i], scope)) != 0) - goto infinite_end; - - short *p = get_variable(code->value, scope); - if (!p) - errx(1, "Cannot loop using non-existent variable %c", code->value); + { + short n = 1; + p = &n; + } else + { + short *p = get_variable(code->value, scope); + if (!p) + errx(1, "Cannot loop over non-existent variable %c", code->value); + } + enum cccl_ExecutorStatus res; while (*p > 0) for (size_t i = 0; i < code->in_length; ++i) - if ((res = cccl_execute(code->in[i], scope)) != 0) - goto infinite_end; -infinite_end: - if (res == cccl_Executor_ERROR) - return res; + switch ((res = cccl_execute(code->in[i], scope, depth + 1))) + { + case cccl_Executor_ERROR: return res; + case cccl_Executor_CONTINUE: break; + case cccl_Executor_END: goto end; + } } break; case cccl_Node_REPEAT: { short *p = get_variable(code->value, scope); if (!p) - errx(1, "Cannot loop using non-existent variable %c", code->value); + errx(1, "Cannot loop over non-existent variable %c", code->value); else if (*p < 0) errx(1, "Cannot iterate %c=%d times", code->value, *p); - int res; + enum cccl_ExecutorStatus res; for (size_t i = 0; i < *p; ++i) for (size_t j = 0; j < code->in_length; ++j) - if ((res = cccl_execute(code->in[j], scope)) != 0) - goto repeat_end; -repeat_end: - if (res == cccl_Executor_ERROR) - return res; + switch ((res = cccl_execute(code->in[j], scope, depth + 1))) + { + case cccl_Executor_ERROR: return res; + case cccl_Executor_CONTINUE: break; + case cccl_Executor_END: goto end; + } }; case cccl_Node_CONDITIONAL: { + assert(stack.length >= 1); + short *p = get_variable(code->value, scope); + if (code->value == '_') + errx(1, "_ is not allowed with '%c'", '?'); + if (!p) + errx(1, "Cannot check non-existent variable %c", code->value); + + enum cccl_ExecutorStatus res; + if (stack.buffer[stack.length - 1] == *p) + for (size_t i = 0; i < code->in_length; ++i) + switch ((res = cccl_execute(code->in[i], scope, depth + 1))) + { + case cccl_Executor_ERROR: return res; + case cccl_Executor_CONTINUE: return res; + case cccl_Executor_END: goto end; + } } break; } +end: return 0; } diff --git a/parser.c b/parser.c index 267bcb5..a2f5484 100644 --- a/parser.c +++ b/parser.c @@ -55,7 +55,7 @@ struct cccl_Node *cccl_parse(struct cccl_Token tokens[], size_t tokens_length, e for (size_t i = 0; i < tokens_length; ++i) { if (verbose) - fprintf(stderr, "T:[%c:%d] ", tokens[i].value, tokens[i].type); + fprintf(stderr, "T:[%c:%s] ", tokens[i].value, strtoken(tokens[i].type)); switch (tokens[i].type) { case cccl_Token_COMMAND: case cccl_Token_COMMANDWITHARG: case cccl_Token_BLOCKSTART: @@ -123,8 +123,8 @@ struct cccl_Node *cccl_parse(struct cccl_Token tokens[], size_t tokens_length, e errx(1, "No matching bracket for %c", opening); end: - putchar('\n'); - puts("Exploring inner..."); + if (verbose) + fputs("\nExploring inner...\n", stderr); res->in[res->in_length - 1] = cccl_parse( tokens + oldi + 1, i - oldi - 1, diff --git a/str.c b/str.c new file mode 100644 index 0000000..4277938 --- /dev/null +++ b/str.c @@ -0,0 +1,57 @@ +#include "cccl.h" + +#include + + +const char *strtoken(enum cccl_TokenType type) +{ + switch (type) + { + break; case cccl_Token_IDENTIFIER: return "IDENTIFIER"; + break; case cccl_Token_COMMAND: return "COMMAND"; + break; case cccl_Token_COMMANDWITHARG: return "COMMANDWITHARG"; + break; case cccl_Token_BLOCKSTART: return "BLOCKSTART"; + break; case cccl_Token_BLOCKEND: return "BLOCKEND"; + } + return NULL; +} + +const char *strnode(enum cccl_NodeType type) +{ + switch (type) + { + break; case cccl_Node_CODE: return "CODE"; + break; case cccl_Node_PUSHZERO: return "PUSHZERO"; + break; case cccl_Node_INCREMENT: return "INCREMENT"; + break; case cccl_Node_DECREMENT: return "DECREMENT"; + break; case cccl_Node_ADD: return "ADD"; + break; case cccl_Node_SUBTRACT: return "SUBTRACT"; + break; case cccl_Node_REVERSE: return "REVERSE"; + break; case cccl_Node_ASSIGN: return "ASSIGN"; + break; case cccl_Node_DELETE: return "DELETE"; + break; case cccl_Node_PUSHVAR: return "PUSHVAR"; + break; case cccl_Node_ASSIGNLOCAL: return "ASSIGNLOCAL"; + break; case cccl_Node_OUTPUT: return "OUTPUT"; + break; case cccl_Node_INPUT: return "INPUT"; + break; case cccl_Node_CALL: return "CALL"; + break; case cccl_Node_END: return "END"; + break; case cccl_Node_CONTINUE: return "CONTINUE"; + break; case cccl_Node_PROCEDURE: return "PROCEDURE"; + break; case cccl_Node_INFINITE: return "INFINITE"; + break; case cccl_Node_REPEAT: return "REPEAT"; + break; case cccl_Node_CONDITIONAL: return "CONDITIONAL"; + } + return NULL; +} + +const char *strstatus(enum cccl_ExecutorStatus status) +{ + switch (status) + { + break; case cccl_Executr_OK: return "OK"; + break; case cccl_Executor_ERROR: return "ERROR"; + break; case cccl_Executor_CONTINUE: return "CONTINUE"; + break; case cccl_Executor_END: return "END"; + } + return NULL; +} -- cgit 1.4.1