-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathinterpret.c
117 lines (103 loc) · 3.7 KB
/
interpret.c
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
#include <pthread.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <gmp.h>
#include <time.h>
#include <ctype.h>
#include <netdb.h>
#include <curl/curl.h>
#include <errno.h>
#include "memory_forth.h"
#include "forth_bot.h"
void *env_interpret_thread(void *arg) {
Env *env = (Env *)arg;
while (env->thread_running) {
Command *cmd = dequeue(env);
if (cmd) {
interpret(cmd->cmd, &env->main_stack, env);
free(cmd);
} else {
pthread_mutex_lock(&env->queue_mutex);
if (env->thread_running && env->queue_head == env->queue_tail) {
struct timespec ts;
clock_gettime(CLOCK_REALTIME, &ts);
ts.tv_sec += 7200; // 2 heures
if (pthread_cond_timedwait(&env->queue_cond, &env->queue_mutex, &ts) == ETIMEDOUT) {
if (env->queue_head == env->queue_tail && env->thread_running) {
char msg[512];
snprintf(msg, sizeof(msg), "Environment for %s inactive, freeing...", env->nick);
send_to_channel(msg);
freeEnv(env->nick);
pthread_mutex_unlock(&env->queue_mutex);
return NULL;
}
}
}
pthread_mutex_unlock(&env->queue_mutex);
}
}
return NULL;
}
void interpret(char *input, Stack *stack, Env *env) {
if (!env) {
send_to_channel("DEBUG: env is NULL");
return;
}
env->error_flag = 0;
env->compile_error = 0;
if (env->compiling) {
// send_to_channel("Continuing previous compilation...");
}
char *saveptr;
char *token = strtok_r(input, " \t\n", &saveptr);
while (token && !env->error_flag && !env->compile_error) {
if (strcmp(token, "(") == 0) {
char *end = strstr(saveptr, ")");
if (end) saveptr = end + 1;
else saveptr = NULL;
token = strtok_r(NULL, " \t\n", &saveptr);
continue;
}
compileToken(token, &saveptr, env);
if (env->compile_error && env->compiling) {
break;
}
if (!saveptr) break;
token = strtok_r(NULL, " \t\n", &saveptr);
}
if (env->compiling && !env->compile_error && env->control_stack_top == 0) {
if (strchr(input, ';')) {
if (env->current_word_index >= 0 && env->current_word_index < env->dictionary.capacity) {
CompiledWord *dict_word = &env->dictionary.words[env->current_word_index];
if (dict_word->name) free(dict_word->name);
if (dict_word->code) free(dict_word->code);
for (int j = 0; j < dict_word->string_count; j++) {
if (dict_word->strings[j]) free(dict_word->strings[j]);
}
if (dict_word->strings) free(dict_word->strings);
*dict_word = env->currentWord;
env->currentWord.name = NULL;
env->currentWord.code = NULL;
env->currentWord.strings = NULL;
}
env->compiling = 0;
env->control_stack_top = 0;
env->current_word_index = -1;
}
} else if (env->compiling && env->compile_error) {
set_error(env, "Definition discarded due to error");
freeCurrentWord(env);
env->compiling = 0;
env->control_stack_top = 0;
env->current_word_index = -1;
env->compile_error = 0;
env->dictionary.count--;
env->main_stack.top = -1;
env->return_stack.top = -1;
}
}