summaryrefslogtreecommitdiff
path: root/src/core
diff options
context:
space:
mode:
authorPaul Buetow <paul@buetow.org>2009-10-30 14:54:34 +0000
committerPaul Buetow <paul@buetow.org>2009-10-30 14:54:34 +0000
commit1542ff3a3927916c23dabffff9533b58f63f4b54 (patch)
tree4a34357fc9723d4f65daa3b5a5de4099bcfd7424 /src/core
parent9eb12638e152d981492382cb534edb89a8625990 (diff)
parent1bc73e78278b630768723869d277d05404feae03 (diff)
Diffstat (limited to 'src/core')
-rw-r--r--src/core/convert.c216
-rw-r--r--src/core/convert.h55
-rw-r--r--src/core/function.c51
-rw-r--r--src/core/function.h46
-rw-r--r--src/core/functions.c985
-rw-r--r--src/core/functions.h64
-rw-r--r--src/core/garbage.c144
-rw-r--r--src/core/garbage.h60
-rw-r--r--src/core/interpret.c1070
-rw-r--r--src/core/interpret.h76
-rw-r--r--src/core/reference.c57
-rw-r--r--src/core/reference.h52
-rw-r--r--src/core/scanner.c374
-rw-r--r--src/core/scanner.h71
-rw-r--r--src/core/scope.c169
-rw-r--r--src/core/scope.h60
-rw-r--r--src/core/symbol.c122
-rw-r--r--src/core/symbol.h71
-rw-r--r--src/core/token.c422
-rw-r--r--src/core/token.h195
20 files changed, 4360 insertions, 0 deletions
diff --git a/src/core/convert.c b/src/core/convert.c
new file mode 100644
index 0000000..6844047
--- /dev/null
+++ b/src/core/convert.c
@@ -0,0 +1,216 @@
+/*:*
+ *: File: ./src/core/convert.c
+ *: A simple interpreter
+ *:
+ *: WWW : http://fype.buetow.org
+ *: AUTHOR : http://paul.buetow.org
+ *: E-Mail : fype at dev.buetow.org
+ *:
+ *: Copyright (c) 2005 - 2008, Paul Buetow
+ *: All rights reserved.
+ *:
+ *: Redistribution and use in source and binary forms, with or without modi-
+ *: fication, are permitted provided that the following conditions are met:
+ *: * Redistributions of source code must retain the above copyright
+ *: notice, this list of conditions and the following disclaimer.
+ *: * Redistributions in binary form must reproduce the above copyright
+ *: notice, this list of conditions and the following disclaimer in the
+ *: documentation and/or other materials provided with the distribution.
+ *: * Neither the name of P. B. Labs nor the names of its contributors may
+ *: be used to endorse or promote products derived from this software
+ *: without specific prior written permission.
+ *:
+ *: THIS SOFTWARE IS PROVIDED BY PAUL C. BUETOW AS IS'' AND ANY EXPRESS OR
+ *: IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ *: WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ *: DISCLAIMED. IN NO EVENT SHALL PAUL C. BUETOW BE LIABLE FOR ANY DIRECT,
+ *: INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ *: (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ *: SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ *: HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ *: STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ *: IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ *: POSSIBILITY OF SUCH DAMAGE.
+ *:*/
+
+#include "convert.h"
+#include "../data/array.h"
+
+void
+convert_to_integer(Token *p_token) {
+ switch (token_get_tt(p_token)) {
+ case TT_INTEGER:
+ break;
+ case TT_DOUBLE:
+ token_set_tt(p_token, TT_INTEGER);
+ token_set_ival(p_token, (int)token_get_dval(p_token));
+ break;
+ case TT_STRING:
+ token_set_tt(p_token, TT_INTEGER);
+ token_set_ival(p_token, atoi(token_get_val(p_token)));
+ break;
+ case TT_ARRAY:
+ token_set_tt(p_token, TT_INTEGER);
+ token_set_ival(p_token, array_get_size(p_token->p_array));
+ break;
+ default:
+ ERROR("Ouups(%s)", tt_get_name(token_get_tt(p_token)));
+ break;
+ }
+}
+
+int
+convert_to_integer_get(Token *p_token) {
+ switch (token_get_tt(p_token)) {
+ case TT_INTEGER:
+ return (token_get_ival(p_token));
+ case TT_DOUBLE:
+ return ((int) token_get_dval(p_token));
+ case TT_STRING:
+ return (atoi(token_get_val(p_token)));
+ case TT_ARRAY:
+ return (array_get_size(p_token->p_array));
+ break;
+ default:
+ ERROR("Ouups(%s)", tt_get_name(token_get_tt(p_token)));
+ }
+
+ return (0); /* Never reach this point */
+}
+
+void
+convert_to_double(Token *p_token) {
+ switch (token_get_tt(p_token)) {
+ case TT_INTEGER:
+ token_set_tt(p_token, TT_DOUBLE);
+ token_set_dval(p_token, token_get_ival(p_token));
+ break;
+ case TT_DOUBLE:
+ break;
+ case TT_STRING:
+ token_set_tt(p_token, TT_DOUBLE);
+ token_set_dval(p_token, atof(token_get_val(p_token)));
+ break;
+ case TT_ARRAY:
+ token_set_tt(p_token, TT_DOUBLE);
+ token_set_dval(p_token, array_get_size(p_token->p_array));
+ break;
+ default:
+ token_print_val(p_token);
+ ERROR("Datatype conversion error '%s'", token_get_val(p_token));
+ break;
+ }
+}
+
+void
+convert_to_string(Token *p_token) {
+ switch (token_get_tt(p_token)) {
+ case TT_INTEGER:
+ {
+ token_set_tt(p_token, TT_STRING);
+ char c_tmp[1024];
+ sprintf(c_tmp, "%d", token_get_ival(p_token));
+ int i_len = strlen(c_tmp);
+ p_token->c_val = realloc(p_token->c_val, sizeof(char) * (i_len + 1));
+ strcpy(p_token->c_val, c_tmp);
+ p_token->c_val[i_len] = 0;
+ }
+ break;
+ case TT_DOUBLE:
+ {
+ token_set_tt(p_token, TT_STRING);
+ char c_tmp[1024];
+ sprintf(c_tmp, "%f", token_get_dval(p_token));
+ int i_len = strlen(c_tmp);
+ p_token->c_val = realloc(p_token->c_val, sizeof(char) * (i_len + 1));
+ strcpy(p_token->c_val, c_tmp);
+ p_token->c_val[i_len] = 0;
+ }
+ case TT_ARRAY:
+ {
+ token_set_tt(p_token, TT_STRING);
+ char c_tmp[1024];
+ sprintf(c_tmp, "%d", array_get_size(p_token->p_array));
+ int i_len = strlen(c_tmp);
+ p_token->c_val = realloc(p_token->c_val, sizeof(char) * (i_len + 1));
+ strcpy(p_token->c_val, c_tmp);
+ p_token->c_val[i_len] = 0;
+ }
+ break;
+ case TT_STRING:
+ break;
+ default:
+ ERROR("Datatype conversion error");
+ break;
+ }
+}
+
+void
+convert_to_array(Token *p_token) {
+ ERROR("not yet implemented");
+}
+
+void
+convert_to_tt(Token *p_token, TokenType tt) {
+ switch (tt) {
+ case TT_INTEGER:
+ convert_to_integer(p_token);
+ break;
+ case TT_DOUBLE:
+ convert_to_double(p_token);
+ break;
+ case TT_STRING:
+ convert_to_string(p_token);
+ break;
+ case TT_ARRAY:
+ convert_to_array(p_token);
+ break;
+ default:
+ ERROR("Ouups!");
+ }
+}
+
+TokenType
+convert_to_highest(Token *p_token1, Token *p_token2) {
+ TokenType tt_highest = token_get_tt(p_token1);
+
+ if (tt_highest < token_get_tt(p_token2)) {
+ tt_highest = token_get_tt(p_token2);
+
+ convert_to_tt(p_token1, tt_highest);
+
+ } else {
+ convert_to_tt(p_token2, tt_highest);
+ }
+
+ return (tt_highest);
+}
+
+TokenType
+convert_function_arg_types_to_highest(Stack *p_stack_args, int i_args) {
+
+ if (i_args <= 0)
+ i_args = stack_size(p_stack_args);
+
+ StackIterator *p_iter = stackiterator_new(p_stack_args);
+ TokenType tt_highest = TT_INTEGER;
+
+ for (int i = 0; i < i_args && stackiterator_has_next(p_iter); ++i) {
+ Token *p_token = stackiterator_next(p_iter);
+ if (token_get_tt(p_token) > tt_highest)
+ tt_highest = token_get_tt(p_token);
+ }
+
+ stackiterator_delete(p_iter);
+ p_iter = stackiterator_new(p_stack_args);
+
+ for (int i = 0; i < i_args && stackiterator_has_next(p_iter); ++i) {
+ Token *p_token = stackiterator_next(p_iter);
+ convert_to_tt(p_token, tt_highest);
+ }
+
+ stackiterator_delete(p_iter);
+
+ return (tt_highest);
+}
+
diff --git a/src/core/convert.h b/src/core/convert.h
new file mode 100644
index 0000000..ed153d5
--- /dev/null
+++ b/src/core/convert.h
@@ -0,0 +1,55 @@
+/*:*
+ *: File: ./src/core/convert.h
+ *: A simple interpreter
+ *:
+ *: WWW : http://fype.buetow.org
+ *: AUTHOR : http://paul.buetow.org
+ *: E-Mail : fype at dev.buetow.org
+ *:
+ *: Copyright (c) 2005 - 2008, Paul Buetow
+ *: All rights reserved.
+ *:
+ *: Redistribution and use in source and binary forms, with or without modi-
+ *: fication, are permitted provided that the following conditions are met:
+ *: * Redistributions of source code must retain the above copyright
+ *: notice, this list of conditions and the following disclaimer.
+ *: * Redistributions in binary form must reproduce the above copyright
+ *: notice, this list of conditions and the following disclaimer in the
+ *: documentation and/or other materials provided with the distribution.
+ *: * Neither the name of P. B. Labs nor the names of its contributors may
+ *: be used to endorse or promote products derived from this software
+ *: without specific prior written permission.
+ *:
+ *: THIS SOFTWARE IS PROVIDED BY PAUL C. BUETOW AS IS'' AND ANY EXPRESS OR
+ *: IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ *: WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ *: DISCLAIMED. IN NO EVENT SHALL PAUL C. BUETOW BE LIABLE FOR ANY DIRECT,
+ *: INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ *: (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ *: SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ *: HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ *: STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ *: IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ *: POSSIBILITY OF SUCH DAMAGE.
+ *:*/
+
+#ifndef CONVERT_H
+#define CONVERT_H
+
+#include "../defines.h"
+
+#include "../data/stack.h"
+
+#include "token.h"
+
+int convert_to_integer_get(Token *p_token);
+void convert_to_integer(Token *p_token);
+void convert_to_double(Token *p_token);
+void convert_to_string(Token *p_token);
+void convert_to_array(Token *p_token);
+void convert_to_tt(Token *p_token, TokenType tt);
+TokenType convert_to_highest(Token *p_token1, Token *p_token2);
+TokenType convert_function_arg_types_to_highest(Stack *p_stack_args, int
+ i_args);
+
+#endif
diff --git a/src/core/function.c b/src/core/function.c
new file mode 100644
index 0000000..f16e74a
--- /dev/null
+++ b/src/core/function.c
@@ -0,0 +1,51 @@
+/*:*
+ *: File: ./src/core/function.c
+ *: A simple interpreter
+ *:
+ *: WWW : http://fype.buetow.org
+ *: AUTHOR : http://paul.buetow.org
+ *: E-Mail : fype at dev.buetow.org
+ *:
+ *: Copyright (c) 2005 - 2008, Paul Buetow
+ *: All rights reserved.
+ *:
+ *: Redistribution and use in source and binary forms, with or without modi-
+ *: fication, are permitted provided that the following conditions are met:
+ *: * Redistributions of source code must retain the above copyright
+ *: notice, this list of conditions and the following disclaimer.
+ *: * Redistributions in binary form must reproduce the above copyright
+ *: notice, this list of conditions and the following disclaimer in the
+ *: documentation and/or other materials provided with the distribution.
+ *: * Neither the name of P. B. Labs nor the names of its contributors may
+ *: be used to endorse or promote products derived from this software
+ *: without specific prior written permission.
+ *:
+ *: THIS SOFTWARE IS PROVIDED BY PAUL C. BUETOW AS IS'' AND ANY EXPRESS OR
+ *: IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ *: WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ *: DISCLAIMED. IN NO EVENT SHALL PAUL C. BUETOW BE LIABLE FOR ANY DIRECT,
+ *: INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ *: (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ *: SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ *: HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ *: STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ *: IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ *: POSSIBILITY OF SUCH DAMAGE.
+ *:*/
+
+#include "../defines.h"
+
+#include "function.h"
+
+Function*
+function_new() {
+ Function *p_function = malloc(sizeof(Function));
+
+ return (p_function);
+}
+
+void
+function_delete(Function *p_function) {
+ free(p_function);
+}
+
diff --git a/src/core/function.h b/src/core/function.h
new file mode 100644
index 0000000..6235d97
--- /dev/null
+++ b/src/core/function.h
@@ -0,0 +1,46 @@
+/*:*
+ *: File: ./src/core/function.h
+ *: A simple interpreter
+ *:
+ *: WWW : http://fype.buetow.org
+ *: AUTHOR : http://paul.buetow.org
+ *: E-Mail : fype at dev.buetow.org
+ *:
+ *: Copyright (c) 2005 - 2008, Paul Buetow
+ *: All rights reserved.
+ *:
+ *: Redistribution and use in source and binary forms, with or without modi-
+ *: fication, are permitted provided that the following conditions are met:
+ *: * Redistributions of source code must retain the above copyright
+ *: notice, this list of conditions and the following disclaimer.
+ *: * Redistributions in binary form must reproduce the above copyright
+ *: notice, this list of conditions and the following disclaimer in the
+ *: documentation and/or other materials provided with the distribution.
+ *: * Neither the name of P. B. Labs nor the names of its contributors may
+ *: be used to endorse or promote products derived from this software
+ *: without specific prior written permission.
+ *:
+ *: THIS SOFTWARE IS PROVIDED BY PAUL C. BUETOW AS IS'' AND ANY EXPRESS OR
+ *: IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ *: WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ *: DISCLAIMED. IN NO EVENT SHALL PAUL C. BUETOW BE LIABLE FOR ANY DIRECT,
+ *: INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ *: (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ *: SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ *: HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ *: STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ *: IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ *: POSSIBILITY OF SUCH DAMAGE.
+ *:*/
+
+#ifndef FUNCTION_H
+#define FUNCTION_H
+
+typedef struct {
+ char *c_name;
+} Function;
+
+Function* function_new();
+void function_delete(Function *p_function);
+
+#endif /* FUNCTION_H */
diff --git a/src/core/functions.c b/src/core/functions.c
new file mode 100644
index 0000000..e534e9a
--- /dev/null
+++ b/src/core/functions.c
@@ -0,0 +1,985 @@
+/*:*
+ *: File: ./src/core/functions.c
+ *: A simple interpreter
+ *:
+ *: WWW : http://fype.buetow.org
+ *: AUTHOR : http://paul.buetow.org
+ *: E-Mail : fype at dev.buetow.org
+ *:
+ *: Copyright (c) 2005 - 2008, Paul Buetow
+ *: All rights reserved.
+ *:
+ *: Redistribution and use in source and binary forms, with or without modi-
+ *: fication, are permitted provided that the following conditions are met:
+ *: * Redistributions of source code must retain the above copyright
+ *: notice, this list of conditions and the following disclaimer.
+ *: * Redistributions in binary form must reproduce the above copyright
+ *: notice, this list of conditions and the following disclaimer in the
+ *: documentation and/or other materials provided with the distribution.
+ *: * Neither the name of P. B. Labs nor the names of its contributors may
+ *: be used to endorse or promote products derived from this software
+ *: without specific prior written permission.
+ *:
+ *: THIS SOFTWARE IS PROVIDED BY PAUL C. BUETOW AS IS'' AND ANY EXPRESS OR
+ *: IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ *: WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ *: DISCLAIMED. IN NO EVENT SHALL PAUL C. BUETOW BE LIABLE FOR ANY DIRECT,
+ *: INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ *: (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ *: SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ *: HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ *: STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ *: IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ *: POSSIBILITY OF SUCH DAMAGE.
+ *:*/
+
+#include <stdlib.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include "functions.h"
+
+#include "convert.h"
+#include "scope.h"
+#include "symbol.h"
+
+#define _FUNCTIONS_ERROR(m,t) \
+ ERROR(\
+ "%s: Function error in %s line %d pos %d near '%s'", m, \
+ token_get_filename(t), \
+ token_get_line_nr(t), \
+ token_get_pos_nr(t), \
+ token_get_val(t) \
+ )
+
+Functions*
+functions_new() {
+ Functions *p_functions = malloc(sizeof(Functions));
+
+ p_functions->p_hash_functions = hash_new(1024);
+ functions_init(p_functions);
+
+ return (p_functions);
+}
+
+void
+functions_delete(Functions *p_functions) {
+ hash_delete(p_functions->p_hash_functions);
+ free(p_functions);
+}
+
+
+void
+_process(Interpret *p_interpret, Token *p_token_store, Token *p_token_op,
+ Token *p_token_op2, Token *p_token_next) {
+
+ TokenType tt_op = token_get_tt(p_token_op);
+ TokenType tt_op2 = p_token_op2 == NULL
+ ? TT_NONE
+ : token_get_tt(p_token_op2);
+
+#ifdef DEBUG_FUNCTION_PROCESS
+ if (p_token_op2 == NULL)
+ printf("DEBUG::FUNCTION::PROCESS: Operator %s\n", tt_get_name(tt_op));
+ else
+ printf("DEBUG::FUNCTION::PROCESS: Operator %s %s\n", tt_get_name(tt_op),
+ tt_get_name(tt_op2));
+
+ token_print(p_token_next);
+ printf("\n");
+ token_print(p_token_store);
+ printf("\n");
+#endif /* DEBUG_FUNCTION_PROCESS */
+
+ if (p_token_op2 != NULL) {
+ switch (tt_op) {
+ case TT_NOT:
+ switch (tt_op2) {
+ case TT_ASSIGN:
+ tt_op = TT_NEQ;
+ break;
+ default:
+ break;
+ }
+ break;
+ case TT_ASSIGN:
+ switch (tt_op2) {
+ case TT_ASSIGN:
+ tt_op = TT_EQ;
+ break;
+ default:
+ break;
+ }
+ break;
+ case TT_LT:
+ switch (tt_op2) {
+ case TT_ASSIGN:
+ tt_op = TT_LE;
+ break;
+ default:
+ break;
+ }
+ break;
+ case TT_GT:
+ switch (tt_op2) {
+ case TT_ASSIGN:
+ tt_op = TT_GE;
+ break;
+ default:
+ break;
+ }
+ break;
+ case TT_DDOT:
+ switch (tt_op2) {
+ case TT_LT:
+ tt_op = TT_LSHIFT;
+ break;
+ case TT_GT:
+ tt_op = TT_RSHIFT;
+ break;
+ default:
+ break;
+ }
+ break;
+ default:
+ break;
+ }
+ } else {
+ switch (tt_op) {
+ case TT_ASSIGN:
+ {
+ Token *p_token_assign = p_interpret->p_token_temp;
+ TokenType tt_assign = token_get_tt(p_token_assign);
+
+ if (tt_assign != TT_IDENT) {
+ _FUNCTIONS_ERROR("Can only assign to symbols",
+ p_token_store);
+ }
+
+ Symbol *p_symbol = scope_get(p_interpret->p_scope,
+ token_get_val(p_token_assign));
+
+ if (p_symbol == NULL) {
+ _FUNCTIONS_ERROR("No such symbol",
+ p_token_assign);
+ }
+
+ symbol_set_val(p_symbol, p_token_store);
+ symbol_set_sym(p_symbol, SYM_VARIABLE);
+
+ return;
+ }
+
+ break;
+ NO_DEFAULT;
+ }
+ }
+
+ p_token_next = token_new_copy(p_token_next);
+ TokenType tt_highest = convert_to_highest(p_token_store, p_token_next);
+
+#ifdef DEBUG_FUNCTION_PROCESS
+ printf("DEBUG::FUNCTION::PROCESS: ===> %s %s %s\n",
+ tt_get_name(tt_highest),
+ tt_get_name(tt_op),
+ tt_get_name(tt_highest));
+#endif /* DEBUG_FUNCTION_PROCESS */
+
+ switch (tt_op) {
+ case TT_ADD:
+ switch (tt_highest) {
+ case TT_INTEGER:
+ token_set_ival(p_token_store,
+ token_get_ival(p_token_next) +
+ token_get_ival(p_token_store));
+ break;
+ case TT_DOUBLE:
+ token_set_dval(p_token_store,
+ token_get_dval(p_token_next) +
+ token_get_dval(p_token_store));
+ break;
+ case TT_STRING:
+ token_set_ival(p_token_store,
+ atoi(token_get_val(p_token_next)) +
+ atoi(token_get_val(p_token_store)));
+ token_set_tt(p_token_store, TT_INTEGER);
+ break;
+ case TT_ARRAY:
+ array_append(p_token_store->p_array,
+ p_token_next->p_array);
+ break;
+ NO_DEFAULT;
+ }
+ break;
+ case TT_SUB:
+ switch (tt_highest) {
+ case TT_INTEGER:
+ token_set_ival(p_token_store,
+ token_get_ival(p_token_next) -
+ token_get_ival(p_token_store));
+ break;
+ case TT_DOUBLE:
+ token_set_dval(p_token_store,
+ token_get_dval(p_token_next) -
+ token_get_dval(p_token_store));
+ break;
+ case TT_STRING:
+ token_set_ival(p_token_store,
+ atoi(token_get_val(p_token_next)) -
+ atoi(token_get_val(p_token_store)));
+ token_set_tt(p_token_store, TT_INTEGER);
+ break;
+ case TT_ARRAY:
+ ERROR("TT_ARRAY - TT_ARRAY not yet implemented");
+ break;
+ NO_DEFAULT;
+ }
+ break;
+ case TT_MULT:
+ switch (tt_highest) {
+ case TT_INTEGER:
+ token_set_ival(p_token_store,
+ token_get_ival(p_token_next) *
+ token_get_ival(p_token_store));
+ break;
+ case TT_DOUBLE:
+ token_set_dval(p_token_store,
+ token_get_dval(p_token_next) *
+ token_get_dval(p_token_store));
+ break;
+ case TT_STRING:
+ token_set_ival(p_token_store,
+ atoi(token_get_val(p_token_next)) *
+ atoi(token_get_val(p_token_store)));
+ token_set_tt(p_token_store, TT_INTEGER);
+ break;
+ case TT_ARRAY:
+ ERROR("TT_ARRAY * TT_ARRAY not yet implemented");
+ break;
+ NO_DEFAULT;
+ }
+ break;
+ case TT_DIV:
+ switch (tt_highest) {
+ case TT_INTEGER:
+ token_set_ival(p_token_store,
+ (int) token_get_ival(p_token_next) /
+ token_get_ival(p_token_store));
+ break;
+ case TT_DOUBLE:
+ token_set_dval(p_token_store,
+ token_get_dval(p_token_next) /
+ token_get_dval(p_token_store));
+ break;
+ case TT_STRING:
+ token_set_dval(p_token_store,
+ atof(token_get_val(p_token_next)) /
+ atof(token_get_val(p_token_store)));
+ token_set_tt(p_token_store, TT_DOUBLE);
+ break;
+ case TT_ARRAY:
+ ERROR("TT_ARRAY / TT_ARRAY not yet implemented");
+ break;
+ NO_DEFAULT;
+ }
+ break;
+ case TT_EQ:
+ switch (tt_highest) {
+ case TT_INTEGER:
+ token_set_ival(p_token_store,
+ (int) token_get_ival(p_token_next) ==
+ token_get_ival(p_token_store));
+ break;
+ case TT_DOUBLE:
+ token_set_ival(p_token_store,
+ token_get_dval(p_token_next) ==
+ token_get_dval(p_token_store));
+ token_set_tt(p_token_store, TT_INTEGER);
+ break;
+ case TT_STRING:
+ token_set_ival(p_token_store,
+ strcmp(token_get_val(p_token_next),
+ token_get_val(p_token_store)) == 0);
+ token_set_tt(p_token_store, TT_INTEGER);
+ break;
+ case TT_ARRAY:
+ ERROR("TT_ARRAY eq TT_ARRAY not yet implemented");
+ break;
+ NO_DEFAULT;
+ }
+ break;
+ case TT_NEQ:
+ switch (tt_highest) {
+ case TT_INTEGER:
+ token_set_ival(p_token_store,
+ (int) token_get_ival(p_token_next) !=
+ token_get_ival(p_token_store));
+ break;
+ case TT_DOUBLE:
+ token_set_ival(p_token_store,
+ token_get_dval(p_token_next) !=
+ token_get_dval(p_token_store));
+ token_set_tt(p_token_store, TT_INTEGER);
+ break;
+ case TT_STRING:
+ token_set_ival(p_token_store,
+ strcmp(token_get_val(p_token_next),
+ token_get_val(p_token_store)) != 0);
+ token_set_tt(p_token_store, TT_INTEGER);
+ break;
+ case TT_ARRAY:
+ ERROR("ARRAY bla yet implemented");
+ break;
+ NO_DEFAULT;
+ }
+ break;
+ case TT_LE:
+ switch (tt_highest) {
+ case TT_INTEGER:
+ token_set_ival(p_token_store,
+ (int) token_get_ival(p_token_next) <=
+ token_get_ival(p_token_store));
+ break;
+ case TT_DOUBLE:
+ token_set_ival(p_token_store,
+ token_get_dval(p_token_next) <=
+ token_get_dval(p_token_store));
+ token_set_tt(p_token_store, TT_INTEGER);
+ break;
+ case TT_STRING:
+ token_set_ival(p_token_store,
+ strcmp(token_get_val(p_token_next),
+ token_get_val(p_token_store)) <= 0);
+ token_set_tt(p_token_store, TT_INTEGER);
+ break;
+ case TT_ARRAY:
+ ERROR("ARRAY bla yet implemented");
+ break;
+ NO_DEFAULT;
+ }
+ break;
+ case TT_GE:
+ switch (tt_highest) {
+ case TT_INTEGER:
+ token_set_ival(p_token_store,
+ (int) token_get_ival(p_token_next) >=
+ token_get_ival(p_token_store));
+ break;
+ case TT_DOUBLE:
+ token_set_ival(p_token_store,
+ token_get_dval(p_token_next) >=
+ token_get_dval(p_token_store));
+ token_set_tt(p_token_store, TT_INTEGER);
+ break;
+ case TT_STRING:
+ token_set_ival(p_token_store,
+ strcmp(token_get_val(p_token_next),
+ token_get_val(p_token_store)) >= 0);
+ token_set_tt(p_token_store, TT_INTEGER);
+ break;
+ case TT_ARRAY:
+ ERROR("ARRAY bla yet implemented");
+ break;
+ NO_DEFAULT;
+ }
+ break;
+ case TT_LT:
+ switch (tt_highest) {
+ case TT_INTEGER:
+ token_set_ival(p_token_store,
+ (int) token_get_ival(p_token_next) <
+ token_get_ival(p_token_store));
+ break;
+ case TT_DOUBLE:
+ token_set_ival(p_token_store,
+ token_get_dval(p_token_next) <
+ token_get_dval(p_token_store));
+ token_set_tt(p_token_store, TT_INTEGER);
+ break;
+ case TT_STRING:
+ token_set_ival(p_token_store,
+ strcmp(token_get_val(p_token_next),
+ token_get_val(p_token_store)) < 0);
+ token_set_tt(p_token_store, TT_INTEGER);
+ break;
+ case TT_ARRAY:
+ ERROR("ARRAY bla yet implemented");
+ break;
+ NO_DEFAULT;
+ }
+ break;
+ case TT_GT:
+ switch (tt_highest) {
+ case TT_INTEGER:
+ token_set_ival(p_token_store,
+ (int) token_get_ival(p_token_next) >
+ token_get_ival(p_token_store));
+ break;
+ case TT_DOUBLE:
+ token_set_ival(p_token_store,
+ token_get_dval(p_token_next) >
+ token_get_dval(p_token_store));
+ token_set_tt(p_token_store, TT_INTEGER);
+ break;
+ case TT_STRING:
+ token_set_ival(p_token_store,
+ strcmp(token_get_val(p_token_next),
+ token_get_val(p_token_store)) > 0);
+ token_set_tt(p_token_store, TT_INTEGER);
+ break;
+ case TT_ARRAY:
+ ERROR("ARRAY bla yet implemented");
+ break;
+ NO_DEFAULT;
+ }
+ break;
+ case TT_AND:
+ switch (tt_highest) {
+ case TT_INTEGER:
+ token_set_ival(p_token_store,
+ (int) token_get_ival(p_token_next) &
+ token_get_ival(p_token_store));
+ break;
+ case TT_DOUBLE:
+ token_set_ival(p_token_store,
+ (int) token_get_dval(p_token_next) &
+ (int) token_get_dval(p_token_store));
+ token_set_tt(p_token_store, TT_INTEGER);
+ break;
+ case TT_STRING:
+ token_set_ival(p_token_store,
+ atoi(token_get_val(p_token_next)) &
+ atoi(token_get_val(p_token_store)));
+ token_set_tt(p_token_store, TT_INTEGER);
+ break;
+ case TT_ARRAY:
+ ERROR("ARRAY bla yet implemented");
+ break;
+ NO_DEFAULT;
+ }
+ break;
+ case TT_OR:
+ switch (tt_highest) {
+ case TT_INTEGER:
+ token_set_ival(p_token_store,
+ (int) token_get_ival(p_token_next) |
+ token_get_ival(p_token_store));
+ break;
+ case TT_DOUBLE:
+ token_set_ival(p_token_store,
+ (int) token_get_dval(p_token_next) |
+ (int) token_get_dval(p_token_store));
+ token_set_tt(p_token_store, TT_INTEGER);
+ break;
+ case TT_STRING:
+ token_set_ival(p_token_store,
+ atoi(token_get_val(p_token_next)) |
+ atoi(token_get_val(p_token_store)));
+ token_set_tt(p_token_store, TT_INTEGER);
+ break;
+ case TT_ARRAY:
+ ERROR("ARRAY bla yet implemented");
+ break;
+ NO_DEFAULT;
+ }
+ break;
+ case TT_XOR:
+ switch (tt_highest) {
+ case TT_INTEGER:
+ token_set_ival(p_token_store,
+ (int) token_get_ival(p_token_next) ^
+ token_get_ival(p_token_store));
+ break;
+ case TT_DOUBLE:
+ token_set_ival(p_token_store,
+ (int) token_get_dval(p_token_next) ^
+ (int) token_get_dval(p_token_store));
+ token_set_tt(p_token_store, TT_INTEGER);
+ break;
+ case TT_STRING:
+ token_set_ival(p_token_store,
+ atoi(token_get_val(p_token_next)) ^
+ atoi(token_get_val(p_token_store)));
+ token_set_tt(p_token_store, TT_INTEGER);
+ break;
+ case TT_ARRAY:
+ ERROR("ARRAY bla yet implemented");
+ break;
+ NO_DEFAULT;
+ }
+ break;
+ case TT_LSHIFT:
+ switch (tt_highest) {
+ case TT_INTEGER:
+ token_set_ival(p_token_store,
+ (int) token_get_ival(p_token_next) <<
+ token_get_ival(p_token_store));
+ break;
+ case TT_DOUBLE:
+ token_set_ival(p_token_store,
+ (int) token_get_dval(p_token_next) <<
+ (int) token_get_dval(p_token_store));
+ token_set_tt(p_token_store, TT_INTEGER);
+ break;
+ case TT_STRING:
+ token_set_ival(p_token_store,
+ atoi(token_get_val(p_token_next)) <<
+ atoi(token_get_val(p_token_store)));
+ token_set_tt(p_token_store, TT_INTEGER);
+ break;
+ case TT_ARRAY:
+ ERROR("ARRAY bla yet implemented");
+ break;
+ NO_DEFAULT;
+ }
+ break;
+ case TT_RSHIFT:
+ switch (tt_highest) {
+ case TT_INTEGER:
+ token_set_ival(p_token_store,
+ (int) token_get_ival(p_token_next) >>
+ token_get_ival(p_token_store));
+ break;
+ case TT_DOUBLE:
+ token_set_ival(p_token_store,
+ (int) token_get_dval(p_token_next) >>
+ (int) token_get_dval(p_token_store));
+ token_set_tt(p_token_store, TT_INTEGER);
+ break;
+ case TT_STRING:
+ token_set_ival(p_token_store,
+ atoi(token_get_val(p_token_next)) >>
+ atoi(token_get_val(p_token_store)));
+ token_set_tt(p_token_store, TT_INTEGER);
+ break;
+ case TT_ARRAY:
+ ERROR("ARRAY bla yet implemented");
+ break;
+ NO_DEFAULT;
+ }
+ break;
+
+ default:
+ _FUNCTIONS_ERROR("No such function/operator", p_token_op);
+ }
+
+#ifdef DEBUG_FUNCTION_PROCESS
+ token_print(p_token_store);
+ printf("\n\n");
+#endif /* DEBUG_FUNCTION_PROCESS */
+
+ token_delete(p_token_next);
+}
+
+void
+function_process(Interpret *p_interpret, Token *p_token_op,
+ Token *p_token_op2, Stack *p_stack_args, int i_args) {
+
+ Token *p_token_store = token_new_copy(stack_pop(p_stack_args));
+
+ for (int i = 0; i < i_args -1 && !stack_empty(p_stack_args); ++i) {
+ Token *p_token_next = stack_pop(p_stack_args);
+
+ _process(p_interpret, p_token_store, p_token_op,
+ p_token_op2, p_token_next);
+ }
+
+ stack_push(p_stack_args, p_token_store);
+}
+
+_Bool
+function_is_buildin(Token *p_token_ident) {
+ /* TODO: optimize this function */
+ if (strcmp("assert", token_get_val(p_token_ident)) == 0)
+ return (true);
+
+ if (strcmp("decr", token_get_val(p_token_ident)) == 0)
+ return (true);
+
+ if (strcmp("double", token_get_val(p_token_ident)) == 0)
+ return (true);
+
+ if (strcmp("end", token_get_val(p_token_ident)) == 0)
+ return (true);
+
+ if (strcmp("exit", token_get_val(p_token_ident)) == 0)
+ return (true);
+
+ if (strcmp("fork", token_get_val(p_token_ident)) == 0)
+ return (true);
+
+ if (strcmp("gc", token_get_val(p_token_ident)) == 0)
+ return (true);
+
+ if (strcmp("incr", token_get_val(p_token_ident)) == 0)
+ return (true);
+
+ if (strcmp("ind", token_get_val(p_token_ident)) == 0)
+ return (true);
+
+ if (strcmp("integer", token_get_val(p_token_ident)) == 0)
+ return (true);
+
+ if (strcmp("len", token_get_val(p_token_ident)) == 0)
+ return (true);
+
+ if (strcmp("ln", token_get_val(p_token_ident)) == 0)
+ return (true);
+
+ if (strcmp("neg", token_get_val(p_token_ident)) == 0)
+ return (true);
+
+ if (strcmp("no", token_get_val(p_token_ident)) == 0)
+ return (true);
+
+ if (strcmp("put", token_get_val(p_token_ident)) == 0)
+ return (true);
+
+ if (strcmp("scope", token_get_val(p_token_ident)) == 0)
+ return (true);
+
+ if (strcmp("say", token_get_val(p_token_ident)) == 0)
+ return (true);
+
+ if (strcmp("string", token_get_val(p_token_ident)) == 0)
+ return (true);
+
+ if (strcmp("yes", token_get_val(p_token_ident)) == 0)
+ return (true);
+
+ if (strcmp("not", token_get_val(p_token_ident)) == 0)
+ return (true);
+
+ if (strcmp("refs", token_get_val(p_token_ident)) == 0)
+ return (true);
+
+ return (false);
+}
+
+void
+function_process_buildin(Interpret *p_interpret, Token *p_token_ident,
+ Stack *p_stack_args) {
+
+ Token *p_token = stack_top(p_stack_args);
+
+ if (token_get_tt(p_token) == TT_ARRAY) {
+ if (strcmp("len", token_get_val(p_token_ident)) == 0) {
+ stack_pop(p_stack_args);
+ stack_push(p_stack_args,
+ token_new_integer(array_get_used(p_token->p_array)));
+
+ } else if (strcmp("ind", token_get_val(p_token_ident)) == 0) {
+ stack_pop(p_stack_args);
+ stack_push(p_stack_args,
+ token_new_integer(array_get_ind(p_token->p_array)));
+
+ } else {
+ ArrayIterator *p_iter = arrayiterator_new(p_token->p_array);
+
+ while (arrayiterator_has_next(p_iter)) {
+ stack_push(p_stack_args, arrayiterator_next(p_iter));
+ function_process_buildin(p_interpret, p_token_ident,
+ p_stack_args);
+ stack_pop(p_stack_args);
+ }
+
+ arrayiterator_delete(p_iter);
+ }
+
+ return;
+ }
+
+ if (strcmp("assert", token_get_val(p_token_ident)) == 0) {
+ if (0 == stack_size(p_stack_args))
+ _FUNCTIONS_ERROR("No argument given", p_token_ident);
+
+ switch (token_get_tt(p_token)) {
+ case TT_INTEGER:
+ if (token_get_ival(p_token) == 0)
+ _FUNCTIONS_ERROR("Assert failed", p_token);
+ break;
+ case TT_DOUBLE:
+ if (token_get_dval(p_token) == 0)
+ _FUNCTIONS_ERROR("Assert failed", p_token);
+ break;
+ case TT_STRING:
+ if (atoi(token_get_val(p_token)) == 0)
+ _FUNCTIONS_ERROR("Assert failed", p_token);
+ break;
+ NO_DEFAULT;
+ }
+
+ } else if (strcmp("decr", token_get_val(p_token_ident)) == 0) {
+ if (0 == stack_size(p_stack_args))
+ _FUNCTIONS_ERROR("No argument given", p_token_ident);
+
+ switch (token_get_tt(p_token)) {
+ case TT_INTEGER:
+ token_set_ival(p_token, token_get_ival(p_token) - 1);
+ break;
+ case TT_DOUBLE:
+ token_set_dval(p_token, token_get_dval(p_token) - 1);
+ break;
+ case TT_STRING:
+ convert_to_integer(p_token);
+ token_set_ival(p_token, token_get_ival(p_token) - 1);
+ break;
+ NO_DEFAULT;
+ }
+
+ } else if (strcmp("double", token_get_val(p_token_ident)) == 0) {
+ if (0 == stack_size(p_stack_args))
+ _FUNCTIONS_ERROR("No argument given", p_token_ident);
+
+ Token *p_token = token_new_copy(stack_pop(p_stack_args));
+ convert_to_double(p_token);
+ stack_push(p_stack_args, p_token);
+
+ } else if (strcmp("end", token_get_val(p_token_ident)) == 0) {
+ exit(0);
+
+ } else if (strcmp("fork", token_get_val(p_token_ident)) == 0) {
+ Token *p_token = token_new_integer((int) fork());
+ stack_push(p_stack_args, p_token);
+
+ } else if (strcmp("gc", token_get_val(p_token_ident)) == 0) {
+ int i_count = garbage_collect();
+ Token *p_token = token_new_integer(i_count);
+ stack_push(p_stack_args, p_token);
+
+ } else if (strcmp("exit", token_get_val(p_token_ident)) == 0) {
+ if (0 == stack_size(p_stack_args))
+ _FUNCTIONS_ERROR("No argument given", p_token_ident);
+
+ p_token = token_new_copy(p_token);
+ convert_to_integer(p_token);
+ exit(token_get_ival(p_token));
+
+ } else if (strcmp("incr", token_get_val(p_token_ident)) == 0) {
+ if (0 == stack_size(p_stack_args))
+ _FUNCTIONS_ERROR("No argument given", p_token_ident);
+
+ switch (token_get_tt(p_token)) {
+ case TT_INTEGER:
+ token_set_ival(p_token, token_get_ival(p_token) + 1);
+ break;
+ case TT_DOUBLE:
+ token_set_dval(p_token, token_get_dval(p_token) + 1);
+ break;
+ case TT_STRING:
+ convert_to_integer(p_token);
+ token_set_ival(p_token, token_get_ival(p_token) + 1);
+ break;
+ NO_DEFAULT;
+ }
+
+ } else if (strcmp("ind", token_get_val(p_token_ident)) == 0) {
+ _FUNCTIONS_ERROR("Expected array", p_token_ident);
+
+ } else if (strcmp("integer", token_get_val(p_token_ident)) == 0) {
+ if (0 == stack_size(p_stack_args))
+ _FUNCTIONS_ERROR("No argument given", p_token_ident);
+
+ Token *p_token = token_new_copy(stack_pop(p_stack_args));
+ convert_to_integer(p_token);
+ stack_push(p_stack_args, p_token);
+
+ } else if (strcmp("len", token_get_val(p_token_ident)) == 0) {
+ if (0 == stack_size(p_stack_args))
+ _FUNCTIONS_ERROR("No argument given", p_token_ident);
+
+ Token *p_token = token_new_copy(stack_pop(p_stack_args));
+ convert_to_string(p_token);
+ token_set_tt(p_token, TT_INTEGER);
+ token_set_ival(p_token, strlen(token_get_val(p_token)));
+ stack_push(p_stack_args, p_token);
+
+ } else if (strcmp("ln", token_get_val(p_token_ident)) == 0) {
+ printf("\n");
+
+ } else if (strcmp("neg", token_get_val(p_token_ident)) == 0) {
+ if (0 == stack_size(p_stack_args))
+ _FUNCTIONS_ERROR("No argument given", p_token_ident);
+
+ Token *p_token = token_new_copy(stack_pop(p_stack_args));
+ stack_push(p_stack_args, p_token);
+
+ switch (token_get_tt(p_token)) {
+ case TT_INTEGER:
+ token_set_ival(p_token, -token_get_ival(p_token));
+ break;
+ case TT_DOUBLE:
+ token_set_dval(p_token, -token_get_dval(p_token));
+ break;
+ case TT_STRING:
+ token_set_ival(p_token, -atoi(token_get_val(p_token)));
+ token_set_tt(p_token, TT_INTEGER);
+ break;
+ NO_DEFAULT;
+ }
+
+ } else if (strcmp("no", token_get_val(p_token_ident)) == 0) {
+ Token *p_token = NULL;
+
+ if (0 == stack_size(p_stack_args)) {
+ p_token = token_new_integer(0);
+
+ } else {
+ p_token = token_new_copy(stack_pop(p_stack_args));
+
+ switch (token_get_tt(p_token)) {
+ case TT_INTEGER:
+ token_set_ival(p_token, !token_get_ival(p_token));
+ break;
+ case TT_DOUBLE:
+ token_set_dval(p_token, !token_get_dval(p_token));
+ break;
+ case TT_STRING:
+ token_set_ival(p_token, !atoi(token_get_val(p_token)));
+ token_set_tt(p_token, TT_INTEGER);
+ break;
+ NO_DEFAULT;
+ }
+ }
+
+ stack_push(p_stack_args, p_token);
+
+ } else if (strcmp("put", token_get_val(p_token_ident)) == 0) {
+ StackIterator *p_iter = stackiterator_new(p_stack_args);
+ while (stackiterator_has_next(p_iter)) {
+ Token *p_token = stackiterator_next(p_iter);
+ switch (token_get_tt(p_token)) {
+ case TT_INTEGER:
+ printf("%d", token_get_ival(p_token));
+ break;
+ case TT_DOUBLE:
+ printf("%f", token_get_dval(p_token));
+ break;
+ case TT_STRING:
+ printf("%s", token_get_val(p_token));
+ break;
+ NO_DEFAULT;
+ }
+ }
+ stackiterator_delete(p_iter);
+
+ } else if (strcmp("scope", token_get_val(p_token_ident)) == 0) {
+ scope_print(p_interpret->p_scope);
+
+ } else if (strcmp("say", token_get_val(p_token_ident)) == 0) {
+ StackIterator *p_iter = stackiterator_new(p_stack_args);
+ while (stackiterator_has_next(p_iter)) {
+ Token *p_token = stackiterator_next(p_iter);
+ switch (token_get_tt(p_token)) {
+ case TT_INTEGER:
+ printf("%d", token_get_ival(p_token));
+ break;
+ case TT_DOUBLE:
+ printf("%f", token_get_dval(p_token));
+ break;
+ case TT_STRING:
+ printf("%s", token_get_val(p_token));
+ break;
+ }
+ }
+ stackiterator_delete(p_iter);
+ printf("\n");
+
+ } else if (strcmp("string", token_get_val(p_token_ident)) == 0) {
+ if (0 == stack_size(p_stack_args))
+ _FUNCTIONS_ERROR("No argument given", p_token_ident);
+
+ Token *p_token = token_new_copy(stack_pop(p_stack_args));
+ convert_to_string(p_token);
+ stack_push(p_stack_args, p_token);
+
+ } else if (strcmp("yes", token_get_val(p_token_ident)) == 0) {
+ Token *p_token = NULL;
+
+ if (0 == stack_size(p_stack_args)) {
+ p_token = token_new_integer(1);
+
+ } else {
+ p_token = token_new_copy(stack_pop(p_stack_args));
+ token_set_ival(p_token, 1);
+ token_set_tt(p_token, TT_INTEGER);
+
+ }
+
+ stack_push(p_stack_args, p_token);
+
+ } else if (strcmp("not", token_get_val(p_token_ident)) == 0) {
+ if (0 == stack_size(p_stack_args))
+ _FUNCTIONS_ERROR("No argument given", p_token_ident);
+
+ Token *p_token = token_new_copy(stack_pop(p_stack_args));
+ stack_push(p_stack_args, p_token);
+
+ switch (token_get_tt(p_token)) {
+ case TT_INTEGER:
+ token_set_ival(p_token, !token_get_ival(p_token));
+ break;
+ case TT_DOUBLE:
+ token_set_dval(p_token, !token_get_dval(p_token));
+ break;
+ case TT_STRING:
+ token_set_ival(p_token, !atoi(token_get_val(p_token)));
+ token_set_tt(p_token, TT_INTEGER);
+ break;
+ NO_DEFAULT;
+ }
+
+ } else if (strcmp("refs", token_get_val(p_token_ident)) == 0) {
+ if (0 == stack_size(p_stack_args))
+ _FUNCTIONS_ERROR("No argument given", p_token_ident);
+
+ Token *p_token_top = stack_pop(p_stack_args);
+ Token *p_token = token_new_integer(p_token_top->i_ref_count);
+ stack_push(p_stack_args, p_token);
+ }
+}
+
+_Bool
+function_is_self_defined(Interpret *p_interpret) {
+ Symbol *p_symbol = scope_get(p_interpret->p_scope,
+ token_get_val(p_interpret->p_token));
+
+ if (p_symbol == NULL)
+ return (false);
+
+ switch (symbol_get_sym(p_symbol)) {
+ case SYM_PROCEDURE:
+ case SYM_FUNCTION:
+ return (true);
+ NO_DEFAULT;
+ }
+
+ return (false);
+}
+
+void
+function_process_self_defined(Interpret *p_interpret, Token *p_token_ident) {
+ Symbol *p_symbol = scope_get(p_interpret->p_scope,
+ token_get_val(p_token_ident));
+
+ switch (symbol_get_sym(p_symbol)) {
+ case SYM_PROCEDURE:
+ {
+ List *p_list_token = symbol_get_val(p_symbol);
+ interpret_subprocess(p_interpret, p_list_token);
+ }
+ break;
+ case SYM_FUNCTION:
+ {
+ List *p_list_token = symbol_get_val(p_symbol);
+ scope_up(p_interpret->p_scope);
+ interpret_subprocess(p_interpret, p_list_token);
+ scope_down(p_interpret->p_scope);
+ }
+ NO_DEFAULT;
+ }
+}
+
+void
+functions_init(Functions *p_functions) {
+}
diff --git a/src/core/functions.h b/src/core/functions.h
new file mode 100644
index 0000000..fc7a138
--- /dev/null
+++ b/src/core/functions.h
@@ -0,0 +1,64 @@
+/*:*
+ *: File: ./src/core/functions.h
+ *: A simple interpreter
+ *:
+ *: WWW : http://fype.buetow.org
+ *: AUTHOR : http://paul.buetow.org
+ *: E-Mail : fype at dev.buetow.org
+ *:
+ *: Copyright (c) 2005 - 2008, Paul Buetow
+ *: All rights reserved.
+ *:
+ *: Redistribution and use in source and binary forms, with or without modi-
+ *: fication, are permitted provided that the following conditions are met:
+ *: * Redistributions of source code must retain the above copyright
+ *: notice, this list of conditions and the following disclaimer.
+ *: * Redistributions in binary form must reproduce the above copyright
+ *: notice, this list of conditions and the following disclaimer in the
+ *: documentation and/or other materials provided with the distribution.
+ *: * Neither the name of P. B. Labs nor the names of its contributors may
+ *: be used to endorse or promote products derived from this software
+ *: without specific prior written permission.
+ *:
+ *: THIS SOFTWARE IS PROVIDED BY PAUL C. BUETOW AS IS'' AND ANY EXPRESS OR
+ *: IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ *: WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ *: DISCLAIMED. IN NO EVENT SHALL PAUL C. BUETOW BE LIABLE FOR ANY DIRECT,
+ *: INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ *: (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ *: SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ *: HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ *: STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ *: IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ *: POSSIBILITY OF SUCH DAMAGE.
+ *:*/
+
+#ifndef FUNCTIONS_H
+#define FUNCTIONS_H
+
+#include "token.h"
+
+#include "interpret.h"
+#include "../data/stack.h"
+#include "../data/hash.h"
+
+typedef struct {
+ Hash *p_hash_functions;
+} Functions;
+
+Functions* functions_new();
+void functions_delete(Functions *p_functions);
+void functions_init(Functions *p_functions);
+
+void function_process(Interpret *p_interp, Token *p_token_op,
+ Token *p_token_op2, Stack *p_stack_args,
+ int i_args);
+_Bool function_is_buildin(Token *p_token_ident);
+void function_process_buildin(Interpret *p_interpret,
+ Token *p_token_ident,
+ Stack *p_stack_args);
+_Bool function_is_self_defined(Interpret *p_interpret);
+void function_process_self_defined(Interpret *p_interpret,
+ Token *p_token_ident);
+
+#endif /* FUNCTIONS_H */
diff --git a/src/core/garbage.c b/src/core/garbage.c
new file mode 100644
index 0000000..544cbcb
--- /dev/null
+++ b/src/core/garbage.c
@@ -0,0 +1,144 @@
+/*:*
+ *: File: ./src/core/garbage.c
+ *: A simple interpreter
+ *:
+ *: WWW : http://fype.buetow.org
+ *: AUTHOR : http://paul.buetow.org
+ *: E-Mail : fype at dev.buetow.org
+ *:
+ *: Copyright (c) 2005 - 2008, Paul Buetow
+ *: All rights reserved.
+ *:
+ *: Redistribution and use in source and binary forms, with or without modi-
+ *: fication, are permitted provided that the following conditions are met:
+ *: * Redistributions of source code must retain the above copyright
+ *: notice, this list of conditions and the following disclaimer.
+ *: * Redistributions in binary form must reproduce the above copyright
+ *: notice, this list of conditions and the following disclaimer in the
+ *: documentation and/or other materials provided with the distribution.
+ *: * Neither the name of P. B. Labs nor the names of its contributors may
+ *: be used to endorse or promote products derived from this software
+ *: without specific prior written permission.
+ *:
+ *: THIS SOFTWARE IS PROVIDED BY PAUL C. BUETOW AS IS'' AND ANY EXPRESS OR
+ *: IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ *: WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ *: DISCLAIMED. IN NO EVENT SHALL PAUL C. BUETOW BE LIABLE FOR ANY DIRECT,
+ *: INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ *: (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ *: SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ *: HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ *: STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ *: IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ *: POSSIBILITY OF SUCH DAMAGE.
+ *:*/
+
+#include "garbage.h"
+
+#define _GARBAGE_ERROR(m) \
+ ERROR("%s: Garbage error", m);
+
+List *LIST_GARBAGE = NULL;
+
+typedef struct {
+ void (*p_func)(void*);
+ void (*p_print)(void*);
+ int *p_ref_count;
+ void *p_2free;
+ GarbageType type;
+} _Garbage;
+
+void
+garbage_init() {
+ LIST_GARBAGE = list_new();
+}
+
+void
+garbage_destroy() {
+ garbage_collect();
+ if (!list_empty(LIST_GARBAGE)) {
+ EPRINTF("The garbage collector still has %d registered items "
+ " which don't have a zero ref count!\n",
+ list_size(LIST_GARBAGE));
+
+ _GARBAGE_ERROR("Garbage left");
+ }
+
+ list_delete(LIST_GARBAGE);
+}
+
+int
+garbage_collect() {
+ ListIterator *p_iter = listiterator_new(LIST_GARBAGE);
+ List *p_list_garbage_new = list_new();
+ int i_count = 0;
+
+ while (listiterator_has_next(p_iter)) {
+ _Garbage *p_garbage = listiterator_next(p_iter);
+
+ if (p_garbage->p_ref_count == NULL || *p_garbage->p_ref_count <= 0) {
+#ifdef DEBUG_GC
+ printf("DEBUG::GC: Freeing ");
+ if (NULL != p_garbage->p_print)
+ (*p_garbage->p_print) (p_garbage->p_2free);
+ else
+ printf("0x%x\n", (int) p_garbage->p_2free);
+#endif /* DEBUG_GC */
+ (*p_garbage->p_func) (p_garbage->p_2free);
+ free(p_garbage);
+ ++i_count;
+
+ } else {
+ list_add_back(p_list_garbage_new, p_garbage);
+ }
+ }
+
+ listiterator_delete(p_iter);
+
+ list_delete(LIST_GARBAGE);
+ LIST_GARBAGE = p_list_garbage_new;
+#ifdef DEBUG_GC
+ printf("DEBUG::GC: Freed %d items\n", i_count);
+#endif /* DEBUG_GC */
+
+ return (i_count);
+}
+
+void
+garbage_add(void *p, GarbageType type) {
+ garbage_add2(p, free, NULL, type);
+}
+
+void
+garbage_add2(void *p,
+ void (*p_func)(void*),
+ int *p_ref_count,
+ GarbageType type) {
+ garbage_add3(p, free, p_func, NULL, type);
+}
+
+void
+garbage_add3(void *p,
+ void (*p_func)(void*),
+ void (*p_print)(void*),
+ int *p_ref_count,
+ GarbageType type) {
+
+ _Garbage *p_garbage = malloc(sizeof(_Garbage));
+
+ p_garbage->p_2free = p;
+ p_garbage->p_func = p_func;
+ p_garbage->p_print = p_print;
+ p_garbage->p_ref_count = p_ref_count;
+ p_garbage->type = type;
+
+ list_add_back(LIST_GARBAGE, p_garbage);
+}
+
+void
+garbage_add_token(Token *p_token) {
+ garbage_add3(p_token,
+ token_delete_cb,
+ token_print_cb,
+ &p_token->i_ref_count, GC_TOKEN);
+}
diff --git a/src/core/garbage.h b/src/core/garbage.h
new file mode 100644
index 0000000..2f93982
--- /dev/null
+++ b/src/core/garbage.h
@@ -0,0 +1,60 @@
+/*:*
+ *: File: ./src/core/garbage.h
+ *: A simple interpreter
+ *:
+ *: WWW : http://fype.buetow.org
+ *: AUTHOR : http://paul.buetow.org
+ *: E-Mail : fype at dev.buetow.org
+ *:
+ *: Copyright (c) 2005 - 2008, Paul Buetow
+ *: All rights reserved.
+ *:
+ *: Redistribution and use in source and binary forms, with or without modi-
+ *: fication, are permitted provided that the following conditions are met:
+ *: * Redistributions of source code must retain the above copyright
+ *: notice, this list of conditions and the following disclaimer.
+ *: * Redistributions in binary form must reproduce the above copyright
+ *: notice, this list of conditions and the following disclaimer in the
+ *: documentation and/or other materials provided with the distribution.
+ *: * Neither the name of P. B. Labs nor the names of its contributors may
+ *: be used to endorse or promote products derived from this software
+ *: without specific prior written permission.
+ *:
+ *: THIS SOFTWARE IS PROVIDED BY PAUL C. BUETOW AS IS'' AND ANY EXPRESS OR
+ *: IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ *: WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ *: DISCLAIMED. IN NO EVENT SHALL PAUL C. BUETOW BE LIABLE FOR ANY DIRECT,
+ *: INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ *: (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ *: SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ *: HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ *: STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ *: IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ *: POSSIBILITY OF SUCH DAMAGE.
+ *:*/
+
+#ifndef GARBAGE_H
+#define GARBAGE_H
+
+#include "../defines.h"
+#include "../data/list.h"
+#include "token.h"
+
+typedef enum {
+ GC_TOKEN,
+} GarbageType;
+
+void garbage_init();
+void garbage_destroy();
+int garbage_collect();
+void garbage_add(void *p, GarbageType type);
+void garbage_add2(void *p, void (*p_func)(void*),
+ int *p_ref_count,
+ GarbageType type);
+void garbage_add3(void *p, void (*p_func)(void*),
+ void (*p_print)(void*),
+ int *p_ref_count,
+ GarbageType type);
+void garbage_add_token(Token *p_token);
+
+#endif
diff --git a/src/core/interpret.c b/src/core/interpret.c
new file mode 100644
index 0000000..e471e72
--- /dev/null
+++ b/src/core/interpret.c
@@ -0,0 +1,1070 @@
+/*:*
+ *: File: ./src/core/interpret.c
+ *: A simple interpreter
+ *:
+ *: WWW : http://fype.buetow.org
+ *: AUTHOR : http://paul.buetow.org
+ *: E-Mail : fype at dev.buetow.org
+ *:
+ *: Copyright (c) 2005 - 2008, Paul Buetow
+ *: All rights reserved.
+ *:
+ *: Redistribution and use in source and binary forms, with or without modi-
+ *: fication, are permitted provided that the following conditions are met:
+ *: * Redistributions of source code must retain the above copyright
+ *: notice, this list of conditions and the following disclaimer.
+ *: * Redistributions in binary form must reproduce the above copyright
+ *: notice, this list of conditions and the following disclaimer in the
+ *: documentation and/or other materials provided with the distribution.
+ *: * Neither the name of P. B. Labs nor the names of its contributors may
+ *: be used to endorse or promote products derived from this software
+ *: without specific prior written permission.
+ *:
+ *: THIS SOFTWARE IS PROVIDED BY PAUL C. BUETOW AS IS'' AND ANY EXPRESS OR
+ *: IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ *: WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ *: DISCLAIMED. IN NO EVENT SHALL PAUL C. BUETOW BE LIABLE FOR ANY DIRECT,
+ *: INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ *: (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ *: SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ *: HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ *: STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ *: IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ *: POSSIBILITY OF SUCH DAMAGE.
+ *:*/
+
+#include "interpret.h"
+
+#include "../defines.h"
+#include "convert.h"
+#include "functions.h"
+#include "symbol.h"
+
+#define _INTERPRET_ERROR(m,t) \
+ ERROR(\
+ "%s: Interpret error in %s line %d pos %d near '%s'", m, \
+ token_get_filename(t), \
+ token_get_line_nr(t), \
+ token_get_pos_nr(t), \
+ token_get_val(t) \
+ )
+
+#define _CHECK if (p_interpret->p_token == NULL) return (0);
+#define _HAS_NEXT listiterator_has_next(p_interpret->p_iter)
+#define _NEXT_ORG _next(p_interpret);
+#define _NEXT if (!_next(p_interpret)) { return (2); }
+#define _NEXT2 _NEXT _NEXT
+#define _NEXT_TT _next_tt(p_interpret)
+#define _SKIP _next(p_interpret);
+
+int _block(Interpret *p_interpret);
+int _block_get(Interpret *p_interpret, List *p_list_block);
+int _block_skip(Interpret *p_interpret);
+int _compare(Interpret *p_interpret);
+int _control(Interpret *p_interpret);
+int _expression(Interpret *p_interpret);
+int _expression_(Interpret *p_interpret);
+int _expression_get(Interpret *p_interpret, List *p_list_block);
+int _func_decl(Interpret *p_interpret);
+int _next(Interpret *p_interpret);
+int _proc_decl(Interpret *p_interpret);
+int _product(Interpret *p_interpret);
+int _product2(Interpret *p_interpret);
+int _program(Interpret *p_interpret);
+int _statement(Interpret *p_interpret);
+int _sum(Interpret *p_interpret);
+int _term(Interpret *p_interpret);
+int _var_assign(Interpret *p_interpret);
+int _var_decl(Interpret *p_interpret);
+int _var_list(Interpret *p_interpret);
+void _print_lookahead(Interpret *p_interpret);
+
+Interpret*
+interpret_new(List *p_list_token, Hash *p_hash_syms) {
+ Interpret *p_interpret = malloc(sizeof(Interpret));
+
+ if (p_hash_syms != NULL) {
+ p_interpret->p_scope = scope_new(p_hash_syms);
+ p_interpret->b_scope_delete = true;
+
+ } else {
+ p_interpret->p_scope = NULL;
+ p_interpret->b_scope_delete = false;
+ }
+
+ p_interpret->p_list_token = p_list_token;
+ p_interpret->p_stack = stack_new();
+ p_interpret->tt = TT_NONE;
+ p_interpret->p_token = NULL;
+ p_interpret->tt_prev = TT_NONE;
+ p_interpret->p_token_prev = NULL;
+ p_interpret->p_token_temp = NULL;
+ p_interpret->ct = CONTROL_NONE;
+
+ return (p_interpret);
+}
+
+void
+interpret_delete(Interpret *p_interpret) {
+ if (!p_interpret)
+ return;
+
+ if (p_interpret->b_scope_delete)
+ scope_delete(p_interpret->p_scope);
+
+ stack_delete(p_interpret->p_stack);
+ free(p_interpret);
+}
+
+void
+_print_lookahead(Interpret *p_interpret) {
+ ListIterator *p_iter = p_interpret->p_iter;
+ ListIteratorState *p_state = listiterator_get_state(p_iter);
+
+ printf("LOOLAHEAD:\n");
+
+ token_print(p_interpret->p_token);
+ printf("\n");
+
+ while (listiterator_has_next(p_iter)) {
+ Token *p_token = listiterator_next(p_iter);
+ token_print(p_token);
+ printf("\n");
+ }
+
+ listiterator_set_state(p_iter, p_state);
+ listiteratorstate_delete(p_state);
+}
+
+int
+_next(Interpret *p_interpret) {
+ if (listiterator_has_next(p_interpret->p_iter)) {
+ p_interpret->p_token_prev = p_interpret->p_token;
+ p_interpret->tt_prev = p_interpret->tt;
+
+ p_interpret->p_token = listiterator_next(p_interpret->p_iter);
+ p_interpret->tt = token_get_tt(p_interpret->p_token);
+ return (1);
+ }
+
+ p_interpret->p_token = NULL;
+ p_interpret->tt = TT_NONE;
+ //printf("==>\n");
+
+ return (0);
+}
+
+TokenType
+_next_tt(Interpret *p_interpret) {
+ if (listiterator_has_next(p_interpret->p_iter)) {
+ Token *p_token = listiterator_current(p_interpret->p_iter);
+ return (token_get_tt(p_token));
+ }
+
+ return (TT_NONE);
+}
+
+int
+_program(Interpret *p_interpret) {
+ _CHECK TRACK
+
+ while (_statement(p_interpret) == 1)
+ garbage_collect();
+
+ return (1);
+}
+
+int
+_var_decl(Interpret *p_interpret) {
+ _CHECK TRACK
+
+ switch (p_interpret->tt) {
+ case TT_MY:
+ {
+ if (_NEXT_TT != TT_IDENT)
+ _INTERPRET_ERROR("'my' expects identifier", p_interpret->p_token);
+
+ _NEXT
+
+ Token *p_token_ident = p_interpret->p_token;
+
+ _var_assign(p_interpret);
+ _var_list(p_interpret);
+
+ if (p_interpret->tt == TT_SEMICOLON) {
+ _NEXT
+ return (1);
+
+ } else if (p_interpret->p_token != NULL) {
+ _INTERPRET_ERROR("Expected ';'", p_interpret->p_token);
+
+ } else {
+ _INTERPRET_ERROR("Expected ';' after", p_token_ident);
+ }
+ }
+ default:
+ break;
+ }
+
+ return (0);
+}
+
+int
+_var_assign(Interpret *p_interpret) {
+ _CHECK TRACK
+
+ if (p_interpret->tt == TT_IDENT) {
+ Token *p_token = p_interpret->p_token;
+ _NEXT
+
+ char *c_name = token_get_val(p_token);
+ if (scope_exists(p_interpret->p_scope, c_name)) {
+ _INTERPRET_ERROR("Symbol already defined", p_token);
+ }
+
+ if (p_interpret->tt == TT_ASSIGN) {
+ _NEXT
+
+ if (p_interpret->tt == TT_VID) {
+ _NEXT
+ if (p_interpret->tt != TT_IDENT)
+ _INTERPRET_ERROR("Expected identifier", p_interpret->p_token);
+
+ char *c_name_ = token_get_val(p_interpret->p_token);
+ Symbol *p_symbol = scope_get(p_interpret->p_scope, c_name_);
+
+ if (p_symbol == NULL)
+ _INTERPRET_ERROR("No such symbol", p_interpret->p_token);
+
+ symbol_ref_up(p_symbol);
+ scope_newset(p_interpret->p_scope, c_name, p_symbol);
+ _NEXT
+
+ } else {
+ Stack *p_stack = p_interpret->p_stack;
+ p_interpret->p_stack = stack_new();
+
+ if (_expression_(p_interpret)) {
+ function_process_buildin(p_interpret, p_token,
+ p_interpret->p_stack);
+
+ stack_merge(p_stack, p_interpret->p_stack);
+ stack_delete(p_interpret->p_stack);
+ p_interpret->p_stack = p_stack;
+
+ p_token = stack_top(p_interpret->p_stack);
+ Symbol *p_symbol = symbol_new(SYM_VARIABLE, p_token);
+ scope_newset(p_interpret->p_scope, c_name, p_symbol);
+ } else {
+ return (0);
+ }
+ }
+ } else {
+ Token *p_token = token_new_integer(0);
+ Symbol *p_symbol = symbol_new(SYM_VARIABLE, p_token);
+ scope_newset(p_interpret->p_scope, c_name, p_symbol);
+ }
+ }
+
+ return (1);
+}
+
+int
+_var_list(Interpret *p_interpret) {
+ _CHECK TRACK
+
+ if (p_interpret->tt == TT_COMMA) {
+ _NEXT
+ _var_assign(p_interpret);
+ _var_list(p_interpret);
+ }
+
+ return (1);
+}
+
+int
+_block_get(Interpret *p_interpret, List *p_list_block) {
+ if (p_interpret->tt != TT_PARANT_CL)
+ _INTERPRET_ERROR("Expected '{'", p_interpret->p_token);
+ _NEXT
+
+ int i_num_parant = 0;
+
+ for (;;) {
+ if (p_interpret->tt == TT_PARANT_CL) {
+ ++i_num_parant;
+
+ } else if (p_interpret->tt == TT_PARANT_CR) {
+ if (--i_num_parant == -1) {
+ _NEXT
+ break; /* for */
+ }
+ }
+
+ list_add_back(p_list_block, p_interpret->p_token);
+
+ _NEXT
+ }
+
+#ifdef DEBUG_BLOCK_GET
+ printf("DEBUG::BLOCK::GET: ====>\n");
+ list_iterate(p_list_block, token_print_cb);
+ printf("DEBUG::BLOCK::GET: <====\n");
+#endif /* DEBUG_BLOCK_GET */
+
+ return (1);
+}
+
+int
+_expression_get(Interpret *p_interpret, List *p_list_expression) {
+ for (;;) {
+ if (p_interpret->tt == TT_PARANT_CL) {
+ break; /* for */
+ }
+
+ list_add_back(p_list_expression, p_interpret->p_token);
+
+ _NEXT
+ }
+
+#ifdef DEBUG_EXPRESSION_GET
+ printf("DEBUG::EXPRESSION::GET: ====>\n");
+ list_iterate(p_list_expression, token_print_cb);
+ printf("DEBUG::EXPRESSION::GET: <====\n");
+#endif /* DEBUG_EXPRESSION_GET */
+
+ return (1);
+}
+
+int
+_block_skip(Interpret *p_interpret) {
+ if (p_interpret->tt != TT_PARANT_CL)
+ _INTERPRET_ERROR("Expected '{'", p_interpret->p_token);
+ _NEXT
+
+ int i_num_parant = 0;
+
+ for (;;) {
+ if (p_interpret->tt == TT_PARANT_CL) {
+ ++i_num_parant;
+
+ } else if (p_interpret->tt == TT_PARANT_CR) {
+ if (--i_num_parant == -1) {
+ _NEXT
+ break; /* for */
+ }
+ }
+
+ _NEXT
+ }
+
+ return (1);
+}
+
+int
+_proc_decl(Interpret *p_interpret) {
+ _CHECK TRACK
+
+ if (p_interpret->tt == TT_PROC) {
+ _NEXT
+
+ if (p_interpret->tt != TT_IDENT)
+ _INTERPRET_ERROR("Expected identifier", p_interpret->p_token);
+
+ Token *p_token_ident = p_interpret->p_token;
+ _NEXT
+
+ if (scope_exists(p_interpret->p_scope, token_get_val(p_token_ident))) {
+ _INTERPRET_ERROR("Symbol already defined", p_token_ident);
+ }
+
+ List *p_list_proc = list_new();
+
+ if (_block_get(p_interpret, p_list_proc)) {
+
+ Symbol *p_symbol = symbol_new(SYM_PROCEDURE, p_list_proc);
+ scope_newset(p_interpret->p_scope, token_get_val(p_token_ident),
+ p_symbol);
+
+ return (1);
+ }
+
+ list_delete(p_list_proc);
+ }
+
+ return (0);
+}
+
+int
+_func_decl(Interpret *p_interpret) {
+ _CHECK TRACK
+
+ if (p_interpret->tt == TT_FUNC) {
+ _NEXT
+
+ if (p_interpret->tt != TT_IDENT)
+ _INTERPRET_ERROR("Expected identifier", p_interpret->p_token);
+
+ Token *p_token_ident = p_interpret->p_token;
+ _NEXT
+
+ if (scope_exists(p_interpret->p_scope, token_get_val(p_token_ident))) {
+ _INTERPRET_ERROR("Symbol already defined", p_token_ident);
+ }
+
+ List *p_list_proc = list_new();
+
+ if (_block_get(p_interpret, p_list_proc)) {
+
+ Symbol *p_symbol = symbol_new(SYM_FUNCTION, p_list_proc);
+ scope_newset(p_interpret->p_scope, token_get_val(p_token_ident),
+ p_symbol);
+
+ return (1);
+ }
+
+ list_delete(p_list_proc);
+ }
+
+ return (0);
+}
+
+int
+_statement(Interpret *p_interpret) {
+ _CHECK TRACK
+
+ for (int i = 0; i < 2; ++i) {
+ if (_proc_decl(p_interpret)) return (1);
+ if (_func_decl(p_interpret)) return (1);
+ if (_var_decl(p_interpret)) return (1);
+ if (_control(p_interpret)) return (1);
+ if (_expression(p_interpret)) return (1);
+ if (_block(p_interpret)) return (1);
+ }
+
+ return (0);
+}
+
+int
+_block(Interpret *p_interpret) {
+ if (p_interpret->tt == TT_PARANT_CL) {
+ List *p_list_block = list_new();
+
+ if (_block_get(p_interpret, p_list_block)) {
+ scope_up(p_interpret->p_scope);
+ interpret_subprocess(p_interpret, p_list_block);
+ scope_down(p_interpret->p_scope);
+ list_delete(p_list_block);
+ return (1);
+ }
+
+ list_delete(p_list_block);
+ }
+
+ return (0);
+}
+
+int
+_expression(Interpret *p_interpret) {
+ _CHECK TRACK
+
+ if (_expression_(p_interpret)) {
+ TokenType tt = p_interpret->tt;
+ if (tt == TT_SEMICOLON || tt == TT_NONE) {
+ _NEXT
+
+ } else {
+ _INTERPRET_ERROR("Expected ';'", p_interpret->p_token);
+ }
+
+ stack_clear(p_interpret->p_stack);
+ return (1);
+ }
+
+ return (0);
+}
+
+int
+_expression_(Interpret *p_interpret) {
+ return (_compare(p_interpret));
+}
+
+int
+_control(Interpret *p_interpret) {
+ _CHECK TRACK
+
+ Token *p_token = p_interpret->p_token;
+
+ switch (p_interpret->tt) {
+ case TT_IF:
+ case TT_IFNOT:
+ {
+ TokenType tt = p_interpret->tt;
+ _NEXT
+ if (_expression_(p_interpret)) {
+ Token *p_token_top = stack_pop(p_interpret->p_stack);
+ List *p_list_block = list_new();
+ _block_get(p_interpret, p_list_block);
+ int ret = 0;
+
+ switch (tt) {
+ case TT_IF:
+ if (convert_to_integer_get(p_token_top)) {
+ scope_up(p_interpret->p_scope);
+ ret = interpret_subprocess(p_interpret, p_list_block);
+ scope_down(p_interpret->p_scope);
+ }
+ break;
+ case TT_IFNOT:
+ if (!convert_to_integer_get(p_token_top)) {
+ scope_up(p_interpret->p_scope);
+ ret = interpret_subprocess(p_interpret, p_list_block);
+ scope_down(p_interpret->p_scope);
+ }
+ break;
+ NO_DEFAULT;
+ }
+
+ list_delete(p_list_block);
+ return (1);
+
+ } else {
+ _INTERPRET_ERROR("Expected expression after control keyword", p_token);
+ }
+ }
+ break;
+ case TT_WHILE:
+ case TT_UNTIL:
+ {
+ TokenType tt = p_interpret->tt;
+ List *p_list_expr = list_new(), *p_list_block = list_new();
+ _Bool b_flag = true;
+
+ _NEXT
+
+ _expression_get(p_interpret, p_list_expr);
+ _block_get(p_interpret, p_list_block);
+ Token *p_token_backup = p_interpret->p_token;
+
+ do {
+ Stack *p_stack_backup = p_interpret->p_stack;
+ p_interpret->p_stack = stack_new();
+
+ ListIterator *p_iter_backup = p_interpret->p_iter;
+ p_interpret->p_iter = listiterator_new(p_list_expr);
+
+ _NEXT
+
+ /* Dont use if here, because we want to check the p_itnerpret->ct */
+ if (_expression_(p_interpret)) {
+ Token *p_token_top = stack_pop(p_interpret->p_stack);
+
+ if (p_token_top == NULL) {
+ printf("FOO\n");
+ exit(0);
+ }
+ if (tt == TT_WHILE) {
+ if (convert_to_integer_get(p_token_top)) {
+ scope_up(p_interpret->p_scope);
+ interpret_subprocess(p_interpret, p_list_block);
+ scope_down(p_interpret->p_scope);
+
+ } else {
+ b_flag = false;
+ }
+
+ } else if (tt == TT_UNTIL) {
+ if (!convert_to_integer_get(p_token_top)) {
+ scope_up(p_interpret->p_scope);
+ interpret_subprocess(p_interpret, p_list_block);
+ scope_down(p_interpret->p_scope);
+
+ } else {
+ b_flag = false;
+ }
+ }
+
+ /*
+ switch (p_interpret->ct) {
+ case CONTROL_BREAK:
+ p_interpret->ct = CONTROL_NONE;
+ b_flag = false;
+ break;
+ case CONTROL_NEXT:
+ p_interpret->ct = CONTROL_NONE;
+ break;
+ NO_DEFAULT;
+ }
+ */
+
+ } else {
+ _INTERPRET_ERROR("Expected expression after control keyword",
+ p_token);
+ }
+
+ listiterator_delete(p_interpret->p_iter);
+ p_interpret->p_iter = p_iter_backup;
+
+ stack_delete(p_interpret->p_stack);
+ p_interpret->p_stack = p_stack_backup;
+
+ } while (b_flag);
+
+ list_delete(p_list_expr);
+ list_delete(p_list_block);
+ p_interpret->p_token = p_token_backup;
+ p_interpret->tt = token_get_tt(p_token_backup);
+
+ return (1);
+ }
+ break;
+ NO_DEFAULT;
+ }
+
+ return (0);
+}
+
+int
+_compare(Interpret *p_interpret) {
+ _CHECK TRACK
+
+ if (_sum(p_interpret)) {
+ _Bool b_flag = true;
+
+ do {
+ switch (p_interpret->tt) {
+ case TT_NOT:
+ case TT_ASSIGN:
+ case TT_LT:
+ case TT_GT:
+ {
+ Token *p_token_op = p_interpret->p_token;
+ Token *p_token_op2 = NULL;
+ _NEXT
+
+ switch (p_interpret->tt) {
+ case TT_NOT:
+ case TT_ASSIGN:
+ case TT_LT:
+ case TT_GT:
+ p_token_op2 = p_interpret->p_token;
+ _NEXT
+ default:
+ break;
+ }
+
+ if (!_sum(p_interpret))
+ _INTERPRET_ERROR("Expected sum", p_interpret->p_token);
+
+ function_process(p_interpret, p_token_op, p_token_op2,
+ p_interpret->p_stack, 2);
+ }
+ break; /* case */
+
+ default:
+ b_flag = false;
+ break;
+
+ } /* switch */
+
+ } while (b_flag);
+
+ return (1);
+ }
+
+ return (0);
+}
+
+int
+_sum(Interpret *p_interpret) {
+ _CHECK TRACK
+
+ if (_product(p_interpret)) {
+ _Bool b_flag = true;
+
+ do {
+ Token *p_token_op2 = NULL, *p_token_tmp = NULL;
+
+ switch (p_interpret->tt) {
+ case TT_DDOT:
+ p_token_tmp = p_interpret->p_token;
+ _NEXT
+ case TT_ADD:
+ case TT_SUB:
+ case TT_AND:
+ case TT_OR:
+ case TT_XOR:
+ {
+ Token *p_token_op = p_interpret->p_token;
+ _NEXT
+
+ if (p_token_tmp != NULL) {
+ p_token_op2 = p_token_op;
+ p_token_op = p_token_tmp;;
+ }
+
+ if (!_product(p_interpret))
+ _INTERPRET_ERROR("Expected product", p_token_op);
+
+ function_process(p_interpret, p_token_op, p_token_op2,
+ p_interpret->p_stack, 2);
+
+ }
+ break; /* case */
+
+ default:
+ b_flag = false;
+ break;
+
+ } /* switch */
+
+ } while (b_flag);
+
+ return (1);
+ }
+
+ return (0);
+}
+
+int
+_product(Interpret *p_interpret) {
+ _CHECK TRACK
+
+ if (_product2(p_interpret)) {
+ _Bool b_flag = true;
+
+ do {
+ switch (p_interpret->tt) {
+ case TT_MULT:
+ case TT_DIV:
+ {
+ Token *p_token = p_interpret->p_token;
+ _NEXT
+
+ if (!_product2(p_interpret))
+ _INTERPRET_ERROR("Expected product2", p_token);
+
+ function_process(p_interpret, p_token, NULL,
+ p_interpret->p_stack, 2);
+
+ }
+ break; /* case */
+
+ default:
+ b_flag = false;
+ break;
+
+ } /* switch */
+
+ } while (b_flag);
+
+ return (1);
+ }
+
+ return (0);
+}
+
+int
+_product2(Interpret *p_interpret) {
+ _CHECK TRACK
+
+ if (_term(p_interpret)) {
+ _Bool b_flag = true;
+
+ do {
+ if (p_interpret->tt == TT_ASSIGN
+ && IS_NOT_OPERATOR(_NEXT_TT)) {
+ Token *p_token = p_interpret->p_token;
+ Token *p_token_temp = p_interpret->p_token_prev;
+ _NEXT
+
+ if (!_expression_(p_interpret))
+ _INTERPRET_ERROR("Expected expression", p_token);
+
+ p_interpret->p_token_temp = p_token_temp;
+ function_process(p_interpret, p_token, NULL,
+ p_interpret->p_stack, 2);
+ p_interpret->p_token_temp = NULL;
+
+ } else {
+ b_flag = false;
+ break;
+ } /* if */
+ } while (b_flag);
+
+ return (1);
+ }
+
+ return (0);
+}
+
+int
+_term(Interpret *p_interpret) {
+ _CHECK TRACK
+
+ switch (p_interpret->tt) {
+ case TT_ARRAY:
+ case TT_STRING:
+ case TT_INTEGER:
+ case TT_DOUBLE:
+ stack_push(p_interpret->p_stack, p_interpret->p_token);
+ // Checks if the term is the last element of an array
+ // say ["element"] # The "element"
+ // or of a function
+ // func foo { say 1 } # The 1
+ if (_NEXT_TT != TT_PARANT_AR && _NEXT_TT != TT_PARANT_CR)
+ _NEXT
+ return (1);
+
+ case TT_IDENT:
+ {
+ if (_NEXT_TT != TT_ASSIGN) {
+ if (_NEXT_TT == TT_PARANT_AL) {
+ Token *p_token_var = p_interpret->p_token;
+ char *c_name = token_get_val(p_token_var);
+ Symbol *p_symbol = scope_get(p_interpret->p_scope, c_name);
+
+ if (p_symbol == NULL)
+ _INTERPRET_ERROR("No such symbol", p_token_var);
+ Token *p_token_array = symbol_get_val(p_symbol);
+ Array *p_array = TOKEN_GET_ARRAY(p_token_array);
+ if (p_array == NULL)
+ _INTERPRET_ERROR("Expected an array", p_interpret->p_token);
+
+ _NEXT2
+ Token *p_token_val = array_get(p_array,
+ convert_to_integer_get(p_interpret->p_token));
+ stack_push(p_interpret->p_stack, p_token_val);
+ _NEXT
+
+ return (1);
+
+ } else if (function_is_buildin(p_interpret->p_token)) {
+ Token *p_token = p_interpret->p_token;
+ Stack *p_stack = p_interpret->p_stack;
+ p_interpret->p_stack = stack_new();
+
+ if (_HAS_NEXT) {
+ _NEXT
+ //if (_expression_(p_interpret));
+ _expression_(p_interpret);
+
+ } else {
+ _SKIP
+ }
+
+ function_process_buildin(p_interpret, p_token,
+ p_interpret->p_stack);
+
+ stack_merge(p_stack, p_interpret->p_stack);
+ stack_delete(p_interpret->p_stack);
+ p_interpret->p_stack = p_stack;
+
+ return (1);
+
+ } else if (function_is_self_defined(p_interpret)) {
+ Token *p_token = p_interpret->p_token;
+ Stack *p_stack = p_interpret->p_stack;
+ p_interpret->p_stack = stack_new();
+
+ _NEXT
+ if (_expression_(p_interpret));
+
+ function_process_self_defined(p_interpret, p_token);
+
+ if (stack_empty(p_interpret->p_stack)) {
+ Token *p_token = token_new_dummy();
+ token_set_tt(p_token, TT_INTEGER);
+ token_set_ival(p_token, 0);
+ stack_push(p_interpret->p_stack, p_token);
+ }
+
+ stack_merge(p_stack, p_interpret->p_stack);
+ stack_delete(p_interpret->p_stack);
+ p_interpret->p_stack = p_stack;
+
+ return (1);
+ }
+ }
+
+ /* It is not a function, it is a variable or some sort of */
+
+ char *c_name = token_get_val(p_interpret->p_token);
+ Symbol *p_symbol = scope_get(p_interpret->p_scope, c_name);
+
+ if (p_symbol == NULL)
+ _INTERPRET_ERROR("No such symbol", p_interpret->p_token);
+
+ SymbolType st = symbol_get_sym(p_symbol);
+
+ switch (st) {
+ case SYM_VARIABLE:
+ stack_push(p_interpret->p_stack, symbol_get_val(p_symbol));
+ _NEXT
+ return (1);
+
+ /* Example: proc foo { foo = "Hello"; } foo; say foo; */
+ case SYM_PROCEDURE:
+ stack_push(p_interpret->p_stack, symbol_get_val(p_symbol));
+ _NEXT
+ return (1);
+
+ NO_DEFAULT;
+ }
+ }
+ break;
+ case TT_DEFINED:
+ {
+ _NEXT
+ if (p_interpret->tt != TT_IDENT)
+ _INTERPRET_ERROR("Expexted identifier for 'defined'",
+ p_interpret->p_token);
+
+ char *c_name = token_get_val(p_interpret->p_token);
+ Token *p_token = token_new_integer(0);
+
+ if (scope_exists(p_interpret->p_scope, c_name))
+ token_set_ival(p_token, 1);
+
+ stack_push(p_interpret->p_stack, p_token);
+
+ _NEXT;
+ return (1);
+ }
+ break;
+
+ case TT_UNDEF:
+ {
+ _NEXT
+ if (p_interpret->tt != TT_IDENT)
+ _INTERPRET_ERROR("Expexted identifier for 'defined'",
+ p_interpret->p_token);
+
+ char *c_name = token_get_val(p_interpret->p_token);
+ Token *p_token = NULL;
+ Symbol *p_symbol = NULL;
+
+ if ((p_symbol = scope_remove(p_interpret->p_scope, c_name))) {
+ symbol_delete(p_symbol);
+ p_token = token_new_integer(1);
+
+ } else {
+ p_token = token_new_integer(0);
+ }
+
+ stack_push(p_interpret->p_stack, p_token);
+
+ _NEXT;
+ return (1);
+ }
+ break;
+
+ case TT_SYMS:
+ {
+ _NEXT
+ if (p_interpret->tt != TT_IDENT)
+ _INTERPRET_ERROR("Expexted identifier for 'syms'",
+ p_interpret->p_token);
+
+ char *c_name = token_get_val(p_interpret->p_token);
+ Symbol *p_symbol = scope_get(p_interpret->p_scope, c_name);
+ if (p_symbol == NULL)
+ _INTERPRET_ERROR("No such symbol", p_interpret->p_token);
+
+
+ Token *p_token_num_refs = token_new_integer(p_symbol->i_refs);
+ stack_push(p_interpret->p_stack, p_token_num_refs);
+
+ _NEXT;
+ return (1);
+ }
+ break;
+
+ case TT_PARANT_AL:
+ {
+ Token *p_token_arr = token_new_array(ARRAY_SIZE);
+ Array *p_array = p_token_arr->p_array;
+
+ _NEXT
+ // Get the array elements
+ while (p_interpret->tt != TT_PARANT_AR) {
+ TokenType tt = tt = p_interpret->tt;
+ if (tt != TT_COMMA && tt != TT_SEMICOLON) {
+ UNLESS (_expression_(p_interpret)) {
+ Token *p_token = p_interpret->p_token;
+ _INTERPRET_ERROR("Expected expression", p_token);
+ }
+
+ array_unshift(p_array, stack_pop(p_interpret->p_stack));
+ }
+
+ _NEXT
+ }
+
+ stack_push(p_interpret->p_stack, p_token_arr);
+ _NEXT
+ return (1);
+ }
+ break;
+
+ case TT_PARANT_L:
+ {
+ Token *p_token = p_interpret->p_token;
+ _NEXT
+
+ if (_expression_(p_interpret)) {
+ if (p_interpret->tt != TT_PARANT_R)
+ _INTERPRET_ERROR("Expected ')'", p_token);
+
+ } else {
+ _INTERPRET_ERROR("Expected expression", p_token);
+ }
+ }
+ _NEXT
+ return (1);
+
+ default:
+ break;
+ }
+
+ return (0);
+}
+
+int
+interpret_process(Interpret *p_interpret) {
+ p_interpret->p_iter = listiterator_new(p_interpret->p_list_token);
+
+ _NEXT
+ _program(p_interpret);
+
+ listiterator_delete(p_interpret->p_iter);
+
+ return (1);
+}
+
+
+int
+interpret_subprocess(Interpret *p_interpret, List *p_list_token) {
+ Interpret *p_interpret_sub = interpret_new(p_list_token,
+ NULL);
+
+ p_interpret_sub->p_scope = p_interpret->p_scope;
+
+ int i_ret = interpret_process(p_interpret_sub);
+ p_interpret->ct = p_interpret_sub->ct;
+
+ interpret_delete(p_interpret_sub);
+
+ return (i_ret);
+}
+
+void
+interpret_run(Fype *p_fype) {
+ Interpret *p_interpret =
+ interpret_new(p_fype->p_list_token, p_fype->p_hash_syms);
+
+ interpret_process(p_interpret);
+
+ interpret_delete(p_interpret);
+}
+
diff --git a/src/core/interpret.h b/src/core/interpret.h
new file mode 100644
index 0000000..28c6f2b
--- /dev/null
+++ b/src/core/interpret.h
@@ -0,0 +1,76 @@
+/*:*
+ *: File: ./src/core/interpret.h
+ *: A simple interpreter
+ *:
+ *: WWW : http://fype.buetow.org
+ *: AUTHOR : http://paul.buetow.org
+ *: E-Mail : fype at dev.buetow.org
+ *:
+ *: Copyright (c) 2005 - 2008, Paul Buetow
+ *: All rights reserved.
+ *:
+ *: Redistribution and use in source and binary forms, with or without modi-
+ *: fication, are permitted provided that the following conditions are met:
+ *: * Redistributions of source code must retain the above copyright
+ *: notice, this list of conditions and the following disclaimer.
+ *: * Redistributions in binary form must reproduce the above copyright
+ *: notice, this list of conditions and the following disclaimer in the
+ *: documentation and/or other materials provided with the distribution.
+ *: * Neither the name of P. B. Labs nor the names of its contributors may
+ *: be used to endorse or promote products derived from this software
+ *: without specific prior written permission.
+ *:
+ *: THIS SOFTWARE IS PROVIDED BY PAUL C. BUETOW AS IS'' AND ANY EXPRESS OR
+ *: IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ *: WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ *: DISCLAIMED. IN NO EVENT SHALL PAUL C. BUETOW BE LIABLE FOR ANY DIRECT,
+ *: INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ *: (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ *: SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ *: HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ *: STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ *: IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ *: POSSIBILITY OF SUCH DAMAGE.
+ *:*/
+
+#ifndef INTERPRET_H
+#define INTERPRET_H
+
+#include "../data/list.h"
+#include "../data/stack.h"
+#include "../data/hash.h"
+
+#include "../fype.h"
+
+#include "garbage.h"
+#include "scope.h"
+#include "token.h"
+
+typedef enum {
+ CONTROL_NONE,
+ CONTROL_NEXT,
+ CONTROL_BREAK,
+} ControlType;
+
+typedef struct {
+ List *p_list_token;
+ Scope *p_scope;
+ _Bool b_scope_delete;
+ Stack *p_stack;
+ ControlType ct;
+
+ ListIterator *p_iter;
+ Token *p_token;
+ TokenType tt;
+ Token *p_token_prev;
+ TokenType tt_prev;
+ Token *p_token_temp;
+} Interpret;
+
+Interpret* interpret_new(List *p_list_token, Hash *p_hash_syms);
+void interpret_delete(Interpret *p_interpret);
+void interpret_run(Fype *p_type);
+int interpret_process(Interpret *p_interpret);
+int interpret_subprocess(Interpret *p_interpret, List *p_list_token);
+
+#endif /* INTERPRET_H */
diff --git a/src/core/reference.c b/src/core/reference.c
new file mode 100644
index 0000000..fdbbb86
--- /dev/null
+++ b/src/core/reference.c
@@ -0,0 +1,57 @@
+/*:*
+ *: File: ./src/core/reference.c
+ *: A simple interpreter
+ *:
+ *: WWW : http://fype.buetow.org
+ *: AUTHOR : http://paul.buetow.org
+ *: E-Mail : fype at dev.buetow.org
+ *:
+ *: Copyright (c) 2005 - 2008, Paul Buetow
+ *: All rights reserved.
+ *:
+ *: Redistribution and use in source and binary forms, with or without modi-
+ *: fication, are permitted provided that the following conditions are met:
+ *: * Redistributions of source code must retain the above copyright
+ *: notice, this list of conditions and the following disclaimer.
+ *: * Redistributions in binary form must reproduce the above copyright
+ *: notice, this list of conditions and the following disclaimer in the
+ *: documentation and/or other materials provided with the distribution.
+ *: * Neither the name of P. B. Labs nor the names of its contributors may
+ *: be used to endorse or promote products derived from this software
+ *: without specific prior written permission.
+ *:
+ *: THIS SOFTWARE IS PROVIDED BY PAUL C. BUETOW AS IS'' AND ANY EXPRESS OR
+ *: IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ *: WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ *: DISCLAIMED. IN NO EVENT SHALL PAUL C. BUETOW BE LIABLE FOR ANY DIRECT,
+ *: INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ *: (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ *: SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ *: HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ *: STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ *: IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ *: POSSIBILITY OF SUCH DAMAGE.
+ *:*/
+
+#include "reference.h"
+
+Reference*
+reference_new(Symbol *p_symbol) {
+ Reference *p_reference = malloc(sizeof(Reference));
+
+ symbol_ref_up(p_symbol);
+ p_reference->p_symbol = p_symbol;
+
+ return (p_reference);
+}
+
+void
+reference_delete_cb(void *p_void) {
+ reference_delete(p_void);
+}
+
+void
+reference_delete(Reference *p_reference) {
+ symbol_delete(p_reference->p_symbol);
+ free(p_reference);
+}
diff --git a/src/core/reference.h b/src/core/reference.h
new file mode 100644
index 0000000..0d16a2a
--- /dev/null
+++ b/src/core/reference.h
@@ -0,0 +1,52 @@
+/*:*
+ *: File: ./src/core/reference.h
+ *: A simple interpreter
+ *:
+ *: WWW : http://fype.buetow.org
+ *: AUTHOR : http://paul.buetow.org
+ *: E-Mail : fype at dev.buetow.org
+ *:
+ *: Copyright (c) 2005 - 2008, Paul Buetow
+ *: All rights reserved.
+ *:
+ *: Redistribution and use in source and binary forms, with or without modi-
+ *: fication, are permitted provided that the following conditions are met:
+ *: * Redistributions of source code must retain the above copyright
+ *: notice, this list of conditions and the following disclaimer.
+ *: * Redistributions in binary form must reproduce the above copyright
+ *: notice, this list of conditions and the following disclaimer in the
+ *: documentation and/or other materials provided with the distribution.
+ *: * Neither the name of P. B. Labs nor the names of its contributors may
+ *: be used to endorse or promote products derived from this software
+ *: without specific prior written permission.
+ *:
+ *: THIS SOFTWARE IS PROVIDED BY PAUL C. BUETOW AS IS'' AND ANY EXPRESS OR
+ *: IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ *: WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ *: DISCLAIMED. IN NO EVENT SHALL PAUL C. BUETOW BE LIABLE FOR ANY DIRECT,
+ *: INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ *: (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ *: SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ *: HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ *: STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ *: IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ *: POSSIBILITY OF SUCH DAMAGE.
+ *:*/
+
+#ifndef REFERENCE_H
+#define REFERENCE_H
+
+#include "../defines.h"
+#include "symbol.h"
+
+#define reference_get_sym(r) (r->p_symbol)
+
+typedef struct {
+ Symbol *p_symbol;
+} Reference;
+
+Reference* reference_new(Symbol *p_symbol);
+void reference_delete_cb(void *p_void);
+void reference_delete(Reference *p_reference);
+
+#endif /* REFERENCE_H */
diff --git a/src/core/scanner.c b/src/core/scanner.c
new file mode 100644
index 0000000..266650c
--- /dev/null
+++ b/src/core/scanner.c
@@ -0,0 +1,374 @@
+/*:*
+ *: File: ./src/core/scanner.c
+ *: A simple interpreter
+ *:
+ *: WWW : http://fype.buetow.org
+ *: AUTHOR : http://paul.buetow.org
+ *: E-Mail : fype at dev.buetow.org
+ *:
+ *: Copyright (c) 2005 - 2008, Paul Buetow
+ *: All rights reserved.
+ *:
+ *: Redistribution and use in source and binary forms, with or without modi-
+ *: fication, are permitted provided that the following conditions are met:
+ *: * Redistributions of source code must retain the above copyright
+ *: notice, this list of conditions and the following disclaimer.
+ *: * Redistributions in binary form must reproduce the above copyright
+ *: notice, this list of conditions and the following disclaimer in the
+ *: documentation and/or other materials provided with the distribution.
+ *: * Neither the name of P. B. Labs nor the names of its contributors may
+ *: be used to endorse or promote products derived from this software
+ *: without specific prior written permission.
+ *:
+ *: THIS SOFTWARE IS PROVIDED BY PAUL C. BUETOW AS IS'' AND ANY EXPRESS OR
+ *: IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ *: WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ *: DISCLAIMED. IN NO EVENT SHALL PAUL C. BUETOW BE LIABLE FOR ANY DIRECT,
+ *: INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ *: (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ *: SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ *: HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ *: STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ *: IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ *: POSSIBILITY OF SUCH DAMAGE.
+ *:*/
+
+#include "scanner.h"
+
+#include <ctype.h>
+#include <string.h>
+
+const char _TOKENENDS[] = "}])+-*/={([<>;:,.!";
+#define _ADD_SEMICOLON_INDEX 2
+int _CODESTR_INDEX = 0;
+
+Scanner*
+scanner_new(List *p_list_token, Tupel *p_tupel_argv) {
+ Scanner *p_scanner = malloc(sizeof(Scanner));
+
+ Dat *p_dat_string = p_tupel_argv->a;
+
+ if (dat_empty(p_dat_string))
+ ERROR("No source given");
+
+ if (argv_checkopts("e", p_tupel_argv)) {
+ p_scanner->c_codestring = dat_pop(p_dat_string);
+ p_scanner->c_filename = NULL;
+ p_scanner->fp = NULL;
+
+ } else {
+ p_scanner->c_codestring = NULL;
+ p_scanner->c_filename = dat_pop(p_dat_string);
+ p_scanner->fp = fopen(p_scanner->c_filename, "r");
+
+ if (!p_scanner->fp)
+ ERROR("Could not open '%s' for reading!", p_scanner->c_filename);
+ }
+
+ p_scanner->p_list_token = p_list_token;
+
+ p_scanner->i_current_line_nr = 1;
+ p_scanner->i_current_pos_nr = 0;
+
+ p_scanner->i_num_tokenends = strlen(_TOKENENDS);
+ p_scanner->tt_last = TT_NONE;
+
+ return p_scanner;
+}
+
+void
+scanner_delete(Scanner *p_scanner) {
+ if (p_scanner->fp)
+ fclose(p_scanner->fp);
+ free(p_scanner);
+}
+
+void
+_add_semicolon_to_list(Scanner *p_scanner) {
+ int i_token_len = 1;
+ char *c_token = calloc(2, sizeof(char*));
+ c_token[0] = ';';
+ c_token[1] = '\0';
+ scanner_add_token(p_scanner, &c_token, &i_token_len, TT_SEMICOLON);
+}
+
+void
+scanner_post_task(Scanner *p_scanner) {
+ List *p_list_token = scanner_get_list_token(p_scanner);
+ ListIterator *p_iter = listiterator_new(p_list_token);
+
+ Token *pt_last[] = { NULL, NULL };
+ TokenType tt_last[] = { TT_NONE, TT_NONE };
+
+ while (listiterator_has_next(p_iter)) {
+ ListElem *p_le = listiterator_next_elem(p_iter);
+ Token *p_token = p_le->p_val;
+ TokenType tt_cur = token_get_tt(p_token);
+
+ if (pt_last[0]) {
+ if (tt_cur == TT_INTEGER && tt_last[1] == TT_DOT
+ && tt_last[0] == TT_INTEGER) {
+
+ token_ref_down(pt_last[0]);
+ token_ref_down(pt_last[1]);
+
+ char *c_2 = token_get_val(p_token);
+ char *c_0 = token_get_val(pt_last[0]);
+ int i_len = strlen(c_2) + strlen(c_0) + 1;
+ char *c_new = calloc(i_len+1, sizeof(char));
+
+ sprintf(c_new, "%s.%s", c_0, c_2);
+ free(c_2);
+ c_new[i_len] = 0;
+
+ token_set_val(p_token, c_new);
+ token_set_tt(p_token, TT_DOUBLE);
+ token_set_dval(p_token, atof(c_new));
+
+ list_remove_elem(p_list_token, p_le->p_prev);
+ list_remove_elem(p_list_token, p_le->p_prev);
+
+ pt_last[0] = pt_last[1] = NULL;
+ tt_last[0] = tt_last[1] = TT_NONE;
+ }
+ }
+
+ tt_last[0] = tt_last[1];
+ tt_last[1] = tt_cur;
+
+ pt_last[0] = pt_last[1];
+ pt_last[1] = p_token;
+ }
+
+ listiterator_delete(p_iter);
+}
+
+_Bool
+_scanner_has_next_char(Scanner *p_scanner) {
+ if (p_scanner->fp)
+ return !feof(p_scanner->fp);
+
+ return p_scanner->c_codestring[_CODESTR_INDEX] != 0;
+}
+
+char
+_scanner_get_next_char(Scanner *p_scanner) {
+ if (p_scanner->fp)
+ return fgetc(p_scanner->fp);
+
+ return (p_scanner->c_codestring[_CODESTR_INDEX++]);
+}
+
+void
+scanner_run(Fype *p_fype) {
+ Scanner *p_scanner = scanner_new(p_fype->p_list_token,
+ p_fype->p_tupel_argv);
+
+ int i_token_len = 0;
+ char *c_token = malloc(sizeof(char));
+
+ c_token[0] = 0;
+
+ while ( _scanner_has_next_char(p_scanner) ) {
+ char c = _scanner_get_next_char(p_scanner);
+ ++p_scanner->i_current_pos_nr;
+
+ switch (c) {
+ case '#':
+ {
+ c = _scanner_get_next_char(p_scanner);
+ ++p_scanner->i_current_pos_nr;
+ _Bool b_multi_comment = c == '*';
+
+ do {
+ c = _scanner_get_next_char(p_scanner);
+ ++p_scanner->i_current_pos_nr;
+ if (c == '\n') {
+ ++p_scanner->i_current_line_nr;
+ p_scanner->i_current_pos_nr = 0;
+
+ if (!b_multi_comment)
+ break;
+
+ } else if (b_multi_comment && c == '*' &&
+ _scanner_has_next_char(p_scanner)) {
+ if ( (c = _scanner_get_next_char(p_scanner)) == '#')
+ break;
+
+ else if (c == '\n')
+ ++p_scanner->i_current_line_nr;
+ }
+
+ } while ( _scanner_has_next_char(p_scanner) );
+ }
+
+ break;
+
+ case '"':
+ if (i_token_len) {
+ TokenType tt_cur = scanner_get_tt_cur(c_token);
+ scanner_add_token(p_scanner, &c_token, &i_token_len, tt_cur);
+ }
+ {
+ int i_num_nl = 0;
+ //_Bool flag = false;
+ do {
+ c = _scanner_get_next_char(p_scanner);
+ if ( c == '\n' ) {
+ ++i_num_nl;
+ p_scanner->i_current_pos_nr = 0;
+
+ i_token_len += 2;
+ c_token = realloc(c_token, sizeof(char) * (i_token_len + 1));
+ c_token[i_token_len-2] = '\\';
+ c_token[i_token_len-1] = 'n';
+ c_token[i_token_len] = 0;
+
+ } else if (c == '"') {
+ if (i_token_len && c_token[i_token_len-1] == '\\') {
+ c_token[i_token_len-1] = '"';
+
+ } else {
+ //flag = true;
+ break;
+ }
+
+ } else {
+ ++i_token_len;
+ c_token = realloc(c_token, sizeof(char) * (i_token_len + 1));
+ c_token[i_token_len-1] = c;
+ c_token[i_token_len] = 0;
+ }
+
+ } while ( _scanner_has_next_char(p_scanner) );
+
+ scanner_add_token(p_scanner, &c_token, &i_token_len, TT_STRING);
+
+ if (i_num_nl)
+ p_scanner->i_current_line_nr += i_num_nl;
+
+ //if (flag)
+ // _add_semicolon_to_list(p_scanner);
+ }
+
+ break;
+
+ case '\n':
+ case '\t':
+ case ' ':
+ if (i_token_len) {
+ TokenType tt_cur = scanner_get_tt_cur(c_token);
+ scanner_add_token(p_scanner, &c_token, &i_token_len, tt_cur);
+ }
+
+ if (c == '\n') {
+ ++p_scanner->i_current_line_nr;
+ p_scanner->i_current_pos_nr = 0;
+ }
+
+ break;
+
+ default:
+ if (i_token_len) {
+ TokenType tt_cur = scanner_get_tt_cur(c_token);
+ if (tt_cur == TT_PARANT_CR && p_scanner->tt_last == TT_STRING)
+ _add_semicolon_to_list(p_scanner);
+
+ char d = c_token[i_token_len-1];
+ if ((!isalpha(d) && !isdigit(d) /*&& d != '-'*/) &&
+ (isalpha(c) || isdigit(c))) {
+
+ scanner_add_token(p_scanner, &c_token, &i_token_len, tt_cur);
+
+ } else {
+ for (int i = 0; i < p_scanner->i_num_tokenends; ++i) {
+ if (_TOKENENDS[i] == c) {
+ scanner_add_token(p_scanner, &c_token,
+ &i_token_len, tt_cur);
+ if (i < _ADD_SEMICOLON_INDEX)
+ _add_semicolon_to_list(p_scanner);
+ break;
+ }
+ }
+ }
+ }
+
+ ++i_token_len;
+ c_token = realloc(c_token, sizeof(char) * i_token_len + 1);
+ c_token[i_token_len-1] = c;
+ c_token[i_token_len] = 0;
+ }
+ }
+
+ if (argv_checkopts("e", p_fype->p_tupel_argv) && i_token_len) {
+ TokenType tt_cur = scanner_get_tt_cur(c_token);
+ scanner_add_token(p_scanner, &c_token, &i_token_len, tt_cur);
+ }
+
+ /* Check if there is a ; missing */
+ List *p_list_token = scanner_get_list_token(p_scanner);
+ Token *p_last_token = list_last(p_list_token);
+ if (token_get_tt(p_last_token) != TT_SEMICOLON)
+ _add_semicolon_to_list(p_scanner);
+
+ scanner_post_task(p_scanner);
+
+ char *c_filename = scanner_get_filename(p_scanner);
+ scanner_delete(p_scanner);
+
+ if (argv_checkopts("TV", p_fype->p_tupel_argv))
+ list_iterate(p_fype->p_list_token, token_print_cb);
+
+ char *c_basename = NULL;
+ if (c_filename) {
+ int i_len = strlen(c_filename) - 3;
+ c_basename = calloc(i_len+1, sizeof(char));
+ strncpy(c_basename, c_filename, i_len);
+ c_basename[i_len] = 0;
+
+ } else {
+ char *c_basename = calloc(1, sizeof(char));
+ c_basename[0] = 0;
+ }
+
+ p_fype->c_basename = c_basename;
+}
+
+void
+scanner_add_token(Scanner *p_scanner, char **cc_token, int *p_token_len,
+ TokenType tt_cur) {
+
+ List *p_list_token = scanner_get_list_token(p_scanner);
+ Token *p_token = token_new(*cc_token, tt_cur,
+ p_scanner->i_current_line_nr,
+ p_scanner->i_current_pos_nr,
+ p_scanner->c_filename);
+
+ list_add_back(p_list_token, p_token);
+ token_ref_up(p_token);
+
+ *cc_token = malloc(sizeof(char));
+ (*cc_token)[0] = 0;
+ *p_token_len = 0;
+
+ p_scanner->tt_last = tt_cur;
+}
+
+TokenType
+scanner_get_tt_cur(char *c_token) {
+ if (isdigit(c_token[0]))
+ return TT_INTEGER;
+
+ if (c_token[0] == '-' && 1 < strlen(c_token) && isdigit(c_token[1]))
+ return TT_INTEGER;
+
+ TokenType tt_cur = get_tt(c_token);
+
+ return tt_cur == TT_NONE ? TT_IDENT : tt_cur;
+}
+
+void
+scanner_cleanup_list_token_cb(void *p_void) {
+ Token *p_token = p_void;
+ token_delete(p_token);
+}
diff --git a/src/core/scanner.h b/src/core/scanner.h
new file mode 100644
index 0000000..bf4825d
--- /dev/null
+++ b/src/core/scanner.h
@@ -0,0 +1,71 @@
+/*:*
+ *: File: ./src/core/scanner.h
+ *: A simple interpreter
+ *:
+ *: WWW : http://fype.buetow.org
+ *: AUTHOR : http://paul.buetow.org
+ *: E-Mail : fype at dev.buetow.org
+ *:
+ *: Copyright (c) 2005 - 2008, Paul Buetow
+ *: All rights reserved.
+ *:
+ *: Redistribution and use in source and binary forms, with or without modi-
+ *: fication, are permitted provided that the following conditions are met:
+ *: * Redistributions of source code must retain the above copyright
+ *: notice, this list of conditions and the following disclaimer.
+ *: * Redistributions in binary form must reproduce the above copyright
+ *: notice, this list of conditions and the following disclaimer in the
+ *: documentation and/or other materials provided with the distribution.
+ *: * Neither the name of P. B. Labs nor the names of its contributors may
+ *: be used to endorse or promote products derived from this software
+ *: without specific prior written permission.
+ *:
+ *: THIS SOFTWARE IS PROVIDED BY PAUL C. BUETOW AS IS'' AND ANY EXPRESS OR
+ *: IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ *: WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ *: DISCLAIMED. IN NO EVENT SHALL PAUL C. BUETOW BE LIABLE FOR ANY DIRECT,
+ *: INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ *: (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ *: SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ *: HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ *: STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ *: IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ *: POSSIBILITY OF SUCH DAMAGE.
+ *:*/
+
+#ifndef SCANNER_H
+#define SCANNER_H
+
+#include <stdio.h>
+#include <ctype.h>
+
+#include "token.h"
+#include "../fype.h"
+#include "../data/dat.h"
+
+#define scanner_get_list_token(s) s->p_list_token
+#define scanner_get_fp(s) s->fp
+#define scanner_get_filename(s) s->c_filename
+#define scanner_get_codestring(s) s->c_codestring
+
+typedef struct {
+ int i_current_line_nr;
+ int i_current_pos_nr;
+ int i_num_tokenends;
+ char *c_filename;
+ char *c_codestring;
+ FILE *fp;
+ List *p_list_token;
+ TokenType tt_last;
+} Scanner;
+
+Scanner *scanner_new(List *p_list_token, Tupel *p_tupel_argv);
+void scanner_post_task(Scanner *p_scanner);
+void scanner_delete(Scanner *p_scanner);
+void scanner_run(Fype *p_fype);
+void scanner_add_token(Scanner *p_scanner, char **cc_token, int *p_token_len,
+ TokenType tt_cur);
+TokenType scanner_get_tt_cur(char *c_token);
+void scanner_cleanup_list_token_cb(void *p_void);
+
+#endif
diff --git a/src/core/scope.c b/src/core/scope.c
new file mode 100644
index 0000000..acbec1f
--- /dev/null
+++ b/src/core/scope.c
@@ -0,0 +1,169 @@
+/*:*
+ *: File: ./src/core/scope.c
+ *: A simple interpreter
+ *:
+ *: WWW : http://fype.buetow.org
+ *: AUTHOR : http://paul.buetow.org
+ *: E-Mail : fype at dev.buetow.org
+ *:
+ *: Copyright (c) 2005 - 2008, Paul Buetow
+ *: All rights reserved.
+ *:
+ *: Redistribution and use in source and binary forms, with or without modi-
+ *: fication, are permitted provided that the following conditions are met:
+ *: * Redistributions of source code must retain the above copyright
+ *: notice, this list of conditions and the following disclaimer.
+ *: * Redistributions in binary form must reproduce the above copyright
+ *: notice, this list of conditions and the following disclaimer in the
+ *: documentation and/or other materials provided with the distribution.
+ *: * Neither the name of P. B. Labs nor the names of its contributors may
+ *: be used to endorse or promote products derived from this software
+ *: without specific prior written permission.
+ *:
+ *: THIS SOFTWARE IS PROVIDED BY PAUL C. BUETOW AS IS'' AND ANY EXPRESS OR
+ *: IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ *: WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ *: DISCLAIMED. IN NO EVENT SHALL PAUL C. BUETOW BE LIABLE FOR ANY DIRECT,
+ *: INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ *: (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ *: SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ *: HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ *: STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ *: IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ *: POSSIBILITY OF SUCH DAMAGE.
+ *:*/
+
+#include "garbage.h"
+#include "scope.h"
+#include "symbol.h"
+
+Scope*
+scope_new(Hash *p_hash_syms) {
+ Scope *p_scope = malloc(sizeof(Scope));
+
+ p_scope->p_hash_global = p_hash_syms;
+ p_scope->p_stack_scopes = stack_new();
+
+ return (p_scope);
+}
+
+void
+scope_delete(Scope *p_scope) {
+ while (!stack_empty(p_scope->p_stack_scopes))
+ scope_down(p_scope);
+
+ stack_delete(p_scope->p_stack_scopes);
+
+ free(p_scope);
+}
+
+void
+scope_up(Scope *p_scope) {
+ stack_push(p_scope->p_stack_scopes, hash_new(1024));
+}
+
+void
+scope_down(Scope *p_scope) {
+ Hash *p_hash_syms = stack_pop(p_scope->p_stack_scopes);
+ hash_iterate(p_hash_syms, symbol_cleanup_hash_syms_cb);
+ hash_delete(p_hash_syms);
+}
+
+static Hash*
+_scope_get_hash(Scope *p_scope, char *c_key) {
+ StackIterator *p_iter = stackiterator_new(p_scope->p_stack_scopes);
+
+ while (stackiterator_has_next(p_iter)) {
+ Hash *p_hash_syms = stackiterator_next(p_iter);
+ Symbol *p_symbol = hash_get(p_hash_syms, c_key);
+
+ if (p_symbol != NULL) {
+ stackiterator_delete(p_iter);
+ return (p_hash_syms);
+ }
+ }
+
+ stackiterator_delete(p_iter);
+
+ if (hash_get(p_scope->p_hash_global, c_key))
+ return (p_scope->p_hash_global);
+
+ return (NULL);
+}
+
+Symbol*
+scope_get(Scope *p_scope, char *c_key) {
+ Hash *p_hash_syms = _scope_get_hash(p_scope, c_key);
+
+ if (p_hash_syms == NULL)
+ return (NULL);
+
+ return (hash_get(p_hash_syms, c_key));
+}
+
+Symbol*
+scope_remove(Scope *p_scope, char *c_key) {
+ Hash *p_hash_syms = _scope_get_hash(p_scope, c_key);
+
+ if (p_hash_syms == NULL)
+ return (NULL);
+
+ Symbol *p_symbol = hash_remove(p_hash_syms, c_key);
+
+ return (p_symbol);
+}
+
+_Bool
+scope_exists(Scope *p_scope, char *c_key) {
+ return (scope_get(p_scope, c_key) != NULL);
+}
+
+_Bool
+scope_reset(Scope *p_scope, char *c_key, Symbol *p_symbol) {
+ Hash *p_hash_syms = _scope_get_hash(p_scope, c_key);
+
+ if (p_hash_syms == NULL)
+ return (false);
+
+ hash_remove(p_hash_syms, c_key);
+ hash_insert(p_hash_syms, c_key, p_symbol);
+
+ return (true);
+}
+
+_Bool
+scope_newset(Scope *p_scope, char *c_key, Symbol *p_symbol) {
+ Hash *p_hash_syms = NULL;
+
+ if (stack_empty(p_scope->p_stack_scopes)) {
+ if (hash_get(p_scope->p_hash_global, c_key) != NULL)
+ return (false);
+
+ p_hash_syms = p_scope->p_hash_global;
+
+ } else {
+ p_hash_syms = stack_top(p_scope->p_stack_scopes);
+ }
+
+ hash_insert(p_hash_syms, c_key, p_symbol);
+
+ return (true);
+}
+
+void
+_scope_print_cb(void *p_void, int i_level) {
+ Hash *p_hash_syms = p_void;
+ if (i_level > 0)
+ printf("%d level(s) up:\n", i_level);
+ hash_iterate_key(p_hash_syms, symbol_print_cb);
+}
+
+void
+scope_print(Scope *p_scope) {
+ printf("Scopes:\n");
+ printf("Scope stack size: %d\n", stack_size(p_scope->p_stack_scopes));
+ printf("Global symbols:\n");
+ hash_iterate_key(p_scope->p_hash_global, symbol_print_cb);
+ printf("Local symbols:\n");
+ stack_iterate_level(p_scope->p_stack_scopes, _scope_print_cb);
+}
diff --git a/src/core/scope.h b/src/core/scope.h
new file mode 100644
index 0000000..16ddbd8
--- /dev/null
+++ b/src/core/scope.h
@@ -0,0 +1,60 @@
+/*:*
+ *: File: ./src/core/scope.h
+ *: A simple interpreter
+ *:
+ *: WWW : http://fype.buetow.org
+ *: AUTHOR : http://paul.buetow.org
+ *: E-Mail : fype at dev.buetow.org
+ *:
+ *: Copyright (c) 2005 - 2008, Paul Buetow
+ *: All rights reserved.
+ *:
+ *: Redistribution and use in source and binary forms, with or without modi-
+ *: fication, are permitted provided that the following conditions are met:
+ *: * Redistributions of source code must retain the above copyright
+ *: notice, this list of conditions and the following disclaimer.
+ *: * Redistributions in binary form must reproduce the above copyright
+ *: notice, this list of conditions and the following disclaimer in the
+ *: documentation and/or other materials provided with the distribution.
+ *: * Neither the name of P. B. Labs nor the names of its contributors may
+ *: be used to endorse or promote products derived from this software
+ *: without specific prior written permission.
+ *:
+ *: THIS SOFTWARE IS PROVIDED BY PAUL C. BUETOW AS IS'' AND ANY EXPRESS OR
+ *: IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ *: WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ *: DISCLAIMED. IN NO EVENT SHALL PAUL C. BUETOW BE LIABLE FOR ANY DIRECT,
+ *: INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ *: (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ *: SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ *: HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ *: STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ *: IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ *: POSSIBILITY OF SUCH DAMAGE.
+ *:*/
+
+#ifndef SCOPE_H
+#define SCOPE_H
+
+#include "../data/hash.h"
+#include "../data/stack.h"
+#include "../defines.h"
+#include "symbol.h"
+
+typedef struct {
+ Hash *p_hash_global;
+ Stack *p_stack_scopes;
+} Scope;
+
+Scope* scope_new(Hash *p_hash_syms);
+void scope_delete(Scope *p_scope);
+Symbol *scope_get(Scope *p_scope, char *c_key);
+Symbol *scope_remove(Scope *p_scope, char *c_key);
+_Bool scope_exists(Scope *p_scope, char *c_key);
+_Bool scope_newset(Scope *p_scope, char *c_key, Symbol *p_symbol);
+_Bool scope_reset(Scope *p_scope, char *c_key, Symbol *p_symbol);
+void scope_down(Scope *p_scope);
+void scope_up(Scope *p_scope);
+void scope_print(Scope *p_scope);
+
+#endif /* SCOPE_H */
diff --git a/src/core/symbol.c b/src/core/symbol.c
new file mode 100644
index 0000000..375ff84
--- /dev/null
+++ b/src/core/symbol.c
@@ -0,0 +1,122 @@
+/*:*
+ *: File: ./src/core/symbol.c
+ *: A simple interpreter
+ *:
+ *: WWW : http://fype.buetow.org
+ *: AUTHOR : http://paul.buetow.org
+ *: E-Mail : fype at dev.buetow.org
+ *:
+ *: Copyright (c) 2005 - 2008, Paul Buetow
+ *: All rights reserved.
+ *:
+ *: Redistribution and use in source and binary forms, with or without modi-
+ *: fication, are permitted provided that the following conditions are met:
+ *: * Redistributions of source code must retain the above copyright
+ *: notice, this list of conditions and the following disclaimer.
+ *: * Redistributions in binary form must reproduce the above copyright
+ *: notice, this list of conditions and the following disclaimer in the
+ *: documentation and/or other materials provided with the distribution.
+ *: * Neither the name of P. B. Labs nor the names of its contributors may
+ *: be used to endorse or promote products derived from this software
+ *: without specific prior written permission.
+ *:
+ *: THIS SOFTWARE IS PROVIDED BY PAUL C. BUETOW AS IS'' AND ANY EXPRESS OR
+ *: IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ *: WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ *: DISCLAIMED. IN NO EVENT SHALL PAUL C. BUETOW BE LIABLE FOR ANY DIRECT,
+ *: INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ *: (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ *: SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ *: HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ *: STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ *: IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ *: POSSIBILITY OF SUCH DAMAGE.
+ *:*/
+
+#include "symbol.h"
+
+#include "../data/list.h"
+#include "token.h"
+
+Symbol*
+symbol_new(SymbolType sym, void *p_val) {
+ Symbol *p_symbol = malloc(sizeof(Symbol));
+
+ p_symbol->sym = sym;
+ p_symbol->p_val = p_val;
+ p_symbol->i_refs = 1;
+
+ return p_symbol;
+}
+
+void
+symbol_delete(Symbol *p_symbol) {
+ if (--p_symbol->i_refs == 0) {
+ switch (symbol_get_sym(p_symbol)) {
+ case SYM_PROCEDURE:
+ {
+ List *p_list_token = symbol_get_val(p_symbol);
+ list_delete(p_list_token);
+ }
+ case SYM_ARRAY:
+ symbol_delete(symbol_get_val(p_symbol));
+ break;
+ NO_DEFAULT;
+ }
+ free(p_symbol);
+ }
+}
+
+void
+symbol_cleanup_hash_syms_cb(void *p_void) {
+ symbol_delete(p_void);
+}
+
+void
+symbol_print(Symbol *p_symbol, char *c_key) {
+ printf("%s: %s", sym_get_name(p_symbol->sym), c_key);
+
+ switch (p_symbol->sym) {
+ case SYM_BUILDIN:
+ case SYM_CONSTANT:
+ break;
+ case SYM_PROCEDURE:
+ case SYM_FUNCTION:
+ //list_iterate(symbol_get_val(p_symbol), token_print_cb);
+ break;
+ case SYM_ARRAY:
+ break;
+ case SYM_VARIABLE:
+ printf(" ");
+ token_print(symbol_get_val(p_symbol));
+ break;
+ }
+
+ printf("\n");
+}
+
+void
+symbol_print_cb(void *p_void, char *c_key) {
+ symbol_print(p_void, c_key);
+}
+
+char*
+sym_get_name(SymbolType sym) {
+ switch (sym) {
+ case SYM_CONSTANT:
+ return ("SYM_CONSTANT");
+ case SYM_ARRAY:
+ return ("SYM_ARRAY");
+ case SYM_VARIABLE:
+ return ("SYM_VARIABLE");
+ case SYM_BUILDIN:
+ return ("SYM_BUILDIN");
+ case SYM_PROCEDURE:
+ return ("SYM_PROCEDURE");
+ case SYM_FUNCTION:
+ return ("SYM_FUNCTION");
+ }
+
+ // Never reach this point
+ return ("NONE");
+}
diff --git a/src/core/symbol.h b/src/core/symbol.h
new file mode 100644
index 0000000..2f6cc10
--- /dev/null
+++ b/src/core/symbol.h
@@ -0,0 +1,71 @@
+/*:*
+ *: File: ./src/core/symbol.h
+ *: A simple interpreter
+ *:
+ *: WWW : http://fype.buetow.org
+ *: AUTHOR : http://paul.buetow.org
+ *: E-Mail : fype at dev.buetow.org
+ *:
+ *: Copyright (c) 2005 - 2008, Paul Buetow
+ *: All rights reserved.
+ *:
+ *: Redistribution and use in source and binary forms, with or without modi-
+ *: fication, are permitted provided that the following conditions are met:
+ *: * Redistributions of source code must retain the above copyright
+ *: notice, this list of conditions and the following disclaimer.
+ *: * Redistributions in binary form must reproduce the above copyright
+ *: notice, this list of conditions and the following disclaimer in the
+ *: documentation and/or other materials provided with the distribution.
+ *: * Neither the name of P. B. Labs nor the names of its contributors may
+ *: be used to endorse or promote products derived from this software
+ *: without specific prior written permission.
+ *:
+ *: THIS SOFTWARE IS PROVIDED BY PAUL C. BUETOW AS IS'' AND ANY EXPRESS OR
+ *: IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ *: WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ *: DISCLAIMED. IN NO EVENT SHALL PAUL C. BUETOW BE LIABLE FOR ANY DIRECT,
+ *: INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ *: (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ *: SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ *: HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ *: STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ *: IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ *: POSSIBILITY OF SUCH DAMAGE.
+ *:*/
+
+#ifndef SYMBOL_H
+#define SYMBOL_H
+
+#include "../defines.h"
+
+#define symbol_set_val(s,v) s->p_val = v
+#define symbol_set_sym(s,st) s->sym = st
+#define symbol_get_val(s) s->p_val
+#define symbol_get_sym(s) s->sym
+#define symbol_ref_up(s) ++s->i_refs
+#define IS_A_FUNCTION(s) (s == SYM_INLINEFUNCTION || s == SYM_FUNCTION)
+#define IS_NOT_A_FUNCTION(s) !IS_A_FUNCTION(s)
+
+typedef enum {
+ SYM_BUILDIN,
+ SYM_CONSTANT,
+ SYM_FUNCTION,
+ SYM_PROCEDURE,
+ SYM_ARRAY,
+ SYM_VARIABLE,
+} SymbolType;
+
+typedef struct {
+ SymbolType sym;
+ void *p_val;
+ unsigned i_refs;
+} Symbol;
+
+Symbol* symbol_new(SymbolType sym, void *p_val);
+void symbol_delete(Symbol *p_symbol);
+void symbol_cleanup_hash_syms_cb(void *p_void);
+void symbol_print(Symbol *p_symbol, char *c_key);
+void symbol_print_cb(void *p_void, char *c_key);
+char* sym_get_name(SymbolType sym);
+
+#endif
diff --git a/src/core/token.c b/src/core/token.c
new file mode 100644
index 0000000..092836f
--- /dev/null
+++ b/src/core/token.c
@@ -0,0 +1,422 @@
+/*:*
+ *: File: ./src/core/token.c
+ *: A simple interpreter
+ *:
+ *: WWW : http://fype.buetow.org
+ *: AUTHOR : http://paul.buetow.org
+ *: E-Mail : fype at dev.buetow.org
+ *:
+ *: Copyright (c) 2005 - 2008, Paul Buetow
+ *: All rights reserved.
+ *:
+ *: Redistribution and use in source and binary forms, with or without modi-
+ *: fication, are permitted provided that the following conditions are met:
+ *: * Redistributions of source code must retain the above copyright
+ *: notice, this list of conditions and the following disclaimer.
+ *: * Redistributions in binary form must reproduce the above copyright
+ *: notice, this list of conditions and the following disclaimer in the
+ *: documentation and/or other materials provided with the distribution.
+ *: * Neither the name of P. B. Labs nor the names of its contributors may
+ *: be used to endorse or promote products derived from this software
+ *: without specific prior written permission.
+ *:
+ *: THIS SOFTWARE IS PROVIDED BY PAUL C. BUETOW AS IS'' AND ANY EXPRESS OR
+ *: IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ *: WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ *: DISCLAIMED. IN NO EVENT SHALL PAUL C. BUETOW BE LIABLE FOR ANY DIRECT,
+ *: INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ *: (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ *: SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ *: HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ *: STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ *: IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ *: POSSIBILITY OF SUCH DAMAGE.
+ *:*/
+
+#include "token.h"
+
+#include "garbage.h"
+
+#define CHECK(...) if (!strcmp(c_token, __VA_ARGS__)) return
+
+long TOKEN_ID_COUNTER = 0;
+
+TokenType
+get_tt(char *c_token) {
+ CHECK("if") TT_IF;
+ CHECK("ifnot") TT_IFNOT;
+ CHECK("else") TT_ELSE;
+ CHECK("break") TT_BREAK;
+ CHECK("while") TT_WHILE;
+ CHECK("until") TT_UNTIL;
+ CHECK("int") TT_INT;
+ CHECK("next") TT_NEXT;
+ CHECK("defined") TT_DEFINED;
+ CHECK("undef") TT_UNDEF;
+ CHECK("syms") TT_SYMS;
+ CHECK("ret") TT_RET;
+ CHECK("const") TT_CONST;
+ CHECK("proc") TT_PROC;
+ CHECK("func") TT_FUNC;
+ CHECK("my") TT_MY;
+ CHECK("arr") TT_ARR;
+ CHECK("!") TT_NOT;
+ CHECK("!=") TT_NEQ;
+ CHECK("=~") TT_RE;
+ CHECK("(") TT_PARANT_L;
+ CHECK(")") TT_PARANT_R;
+ CHECK("[") TT_PARANT_AL;
+ CHECK("]") TT_PARANT_AR;
+ CHECK("*") TT_MULT;
+ CHECK("+") TT_ADD;
+ CHECK("++") TT_INCR;
+ CHECK(",") TT_COMMA;
+ CHECK("-") TT_SUB;
+ CHECK("--") TT_DECR;
+ CHECK(".") TT_DOT;
+ CHECK("/") TT_DIV;
+ CHECK("\\") TT_VID;
+ CHECK(":") TT_DDOT;
+ CHECK("==") TT_EQ;
+ CHECK(";") TT_SEMICOLON;
+ CHECK("<<") TT_LSHIFT;
+ CHECK(">>") TT_RSHIFT;
+ CHECK("and") TT_AND;
+ CHECK("&") TT_AAND;
+ CHECK("or") TT_OR;
+ CHECK("xor") TT_XOR;
+ CHECK("=") TT_ASSIGN;
+ CHECK("<") TT_LT;
+ CHECK(">") TT_GT;
+ CHECK(">=") TT_GE;
+ CHECK("<=") TT_LE;
+ CHECK("{") TT_PARANT_CL;
+ CHECK("}") TT_PARANT_CR;
+
+ return TT_NONE;
+}
+
+#define CASE(t,r) case t: return r;
+
+char*
+tt_get_name(TokenType tt_cur) {
+ switch (tt_cur) {
+ CASE(START_TERMINALS, "START_TERMINALS")
+ CASE(START_TYPES, "START_TYPES")
+ CASE(START_NUMERICAL, "START_NUMERICAL")
+ CASE(START_ASSIGNABLES, "START_ASSIGNABLES")
+ CASE(TT_IDENT, "TT_IDENT")
+ CASE(TT_DOUBLE,"TT_DOUBLE")
+ CASE(TT_STRING,"TT_STRING")
+ CASE(TT_ARRAY,"TT_ARRAY")
+ CASE(TT_INTEGER,"TT_INTEGER")
+ CASE(TT_BOOL,"TT_BOOL")
+ CASE(END_ASSIGNABLES, "END_ASSIGNABLES")
+ CASE(END_NUMERICAL, "END_NUMERICAL")
+ CASE(END_TYPES, "END_TYPES")
+
+ // Keywords
+ CASE(START_KEYWORDS, "START_KEYWORDS")
+ CASE(TT_ELSE,"TT_ELSE")
+ CASE(TT_BREAK,"TT_BREAK")
+ CASE(TT_IF,"TT_IF")
+ CASE(TT_IFNOT,"TT_IFNOT")
+ CASE(TT_RET,"TT_RET")
+ CASE(TT_CONST,"TT_CONST")
+ CASE(TT_PROC,"TT_PROC")
+ CASE(TT_FUNC,"TT_FUNC")
+ CASE(TT_MY,"TT_MY")
+ CASE(TT_ARR,"TT_ARR")
+ CASE(TT_WHILE,"TT_WHILE")
+ CASE(TT_UNTIL,"TT_UNTIL")
+ CASE(TT_NEXT,"TT_NEXT")
+ CASE(TT_DEFINED,"TT_DEFINED")
+ CASE(TT_UNDEF,"TT_UNDEF")
+ CASE(TT_SYMS,"TT_SYMS")
+ CASE(TT_INT,"TT_INT")
+ CASE(END_KEYWORDS, "END_KEYWORDS")
+
+ // Braces
+ CASE(START_PARANTS, "START_PARANTS")
+ CASE(TT_PARANT_CL,"TT_PARANT_CL")
+ CASE(TT_PARANT_CR,"TT_PARANT_CR")
+ CASE(TT_PARANT_AL,"TT_PARANT_AL")
+ CASE(TT_PARANT_AR,"TT_PARANT_AR")
+ CASE(TT_PARANT_L,"TT_PARANT_L")
+ CASE(TT_PARANT_R,"TT_PARANT_R")
+ CASE(END_PARANTS, "END_PARANTS")
+
+ // Operators
+ CASE(START_OPERATORS, "START_OPERATORS")
+ CASE(TT_ADD,"TT_ADD")
+ CASE(TT_ASSIGN,"TT_ASSIGN")
+ CASE(TT_COMMA,"TT_COMMA")
+ CASE(TT_DDOT,"TT_DDOT")
+ CASE(TT_DECR,"TT_DECR")
+ CASE(TT_DIV,"TT_DIV")
+ CASE(TT_VID,"TT_VID")
+ CASE(TT_DOT,"TT_DOT")
+ CASE(TT_EQ,"TT_EQ")
+ CASE(TT_LE,"TT_LE")
+ CASE(TT_LT,"TT_LT")
+ CASE(TT_GE,"TT_GE")
+ CASE(TT_GT,"TT_GT")
+ CASE(TT_INCR,"TT_INCR")
+ CASE(TT_LSHIFT,"TT_LSHIFT")
+ CASE(TT_RSHIFT,"TT_RSHIFT")
+ CASE(TT_AND,"TT_AND")
+ CASE(TT_AAND,"TT_AAND")
+ CASE(TT_OR,"TT_OR")
+ CASE(TT_XOR,"TT_XOR")
+ CASE(TT_NOT,"TT_NOT")
+ CASE(TT_MULT,"TT_MULT")
+ CASE(TT_NEQ,"TT_NEQ")
+ CASE(TT_RE,"TT_RE")
+ CASE(TT_NOTEQ,"TT_NOTEQ")
+ CASE(TT_SEMICOLON,"TT_SEMICOLON")
+ CASE(TT_SUB,"TT_SUB")
+ CASE(END_OPERATORS, "END_OPERATORS")
+ CASE(END_TERMINALS, "END_TERMINALS")
+
+ // Diverse
+ CASE(TT_NONE,"TT_NONE")
+ CASE(TT_END_OF_CODE,"TT_END_OF_CODE")
+ }
+
+ // Never reach this point
+ return "XXXXXXX";
+}
+
+Token*
+token_new(char *c_val, TokenType tt_cur, int i_line_nr,
+ int i_pos_nr, char *c_filename) {
+ Token *p_token = token_new_dummy();
+
+ p_token->c_val = c_val;
+ p_token->i_val = 0;
+ p_token->d_val = 0;
+ p_token->tt_cur = tt_cur;
+ p_token->i_line_nr = i_line_nr;
+ p_token->i_pos_nr = i_pos_nr;
+ p_token->c_filename = c_filename;
+ p_token->p_array = NULL;
+
+ switch (tt_cur) {
+ case TT_INTEGER:
+ p_token->i_val = atoi(c_val);
+ break;
+ case TT_DOUBLE:
+ {
+ p_token->d_val = atof(c_val);
+ break;
+ }
+ case TT_ARRAY:
+ {
+ p_token->p_array = array_new();
+ break;
+ }
+ NO_DEFAULT;
+ }
+
+ return p_token;
+}
+
+Token*
+token_new_integer(int i_val) {
+ Token *p_token = token_new_dummy();
+ token_set_tt(p_token, TT_INTEGER);
+ token_set_ival(p_token, i_val);
+
+ return (p_token);
+}
+
+Token*
+token_new_double(double d_val) {
+ Token *p_token = token_new_dummy();
+ token_set_tt(p_token, TT_DOUBLE);
+ token_set_dval(p_token, d_val);
+
+ return (p_token);
+}
+
+Token*
+token_new_string(char *c_val) {
+ Token *p_token = token_new_dummy();
+ token_set_tt(p_token, TT_STRING);
+
+ p_token->c_val = calloc(strlen(c_val)+1, sizeof(char));
+ strcpy(p_token->c_val, c_val);
+
+ return (p_token);
+}
+
+Token*
+token_new_array(int i_size) {
+ Token *p_token = token_new_dummy();
+
+ token_set_tt(p_token, TT_ARRAY);
+ p_token->p_array = array_new();
+
+ array_resize(p_token->p_array, i_size);
+
+ return (p_token);
+}
+
+
+Token*
+token_new_(char *c_val, TokenType tt_cur, char *c_filename) {
+ return token_new(c_val, tt_cur, -1, -1, c_filename);
+}
+
+Token*
+token_new_dummy() {
+ Token *p_token = malloc(sizeof(Token));
+
+ p_token->c_val = NULL;
+ p_token->tt_cur = TT_NONE;
+ p_token->i_line_nr = -1;
+ p_token->i_pos_nr = -1;
+ p_token->c_filename = NULL;
+ p_token->u_token_id = TOKEN_ID_COUNTER++;
+ p_token->i_ref_count = 0;
+ p_token->p_array = NULL;
+
+ /* Register the token in the garbage collector */
+ garbage_add_token(p_token);
+
+ return p_token;
+}
+
+Token*
+token_new_copy(Token *p_token) {
+ Token *p_token_copy = malloc(sizeof(Token));
+ p_token->u_token_id = TOKEN_ID_COUNTER++;
+
+ if (p_token_copy == NULL)
+ ERROR("Memory alloc error");
+
+ p_token->p_array = NULL;
+ token_copy_vals(p_token_copy, p_token);
+ p_token_copy->i_ref_count = 0;
+
+ /* Register the token in the garbage collector */
+ garbage_add_token(p_token_copy);
+
+ return (p_token_copy);
+}
+
+void token_copy_vals(Token *p_token_to, Token *p_token_from) {
+ int i_len;
+
+ if (p_token_from->c_val) {
+ i_len = strlen(p_token_from->c_val);
+ p_token_to->c_val = calloc(i_len+1, sizeof(char));
+ strcpy(p_token_to->c_val, p_token_from->c_val);
+
+ } else {
+ p_token_to->c_val = NULL;
+ }
+
+ p_token_to->tt_cur = p_token_from->tt_cur;
+ p_token_to->i_val = p_token_from->i_val;
+ p_token_to->d_val = p_token_from->d_val;
+ p_token_to->i_line_nr = p_token_from->i_line_nr;
+ p_token_to->i_pos_nr = p_token_from->i_pos_nr;
+ p_token_to->c_filename = p_token_from->c_filename;
+
+ if (NULL != p_token_from->p_array)
+ // Copy all tokens by reference (pointers)
+ p_token_to->p_array = array_new_copy(p_token_from->p_array);
+}
+
+void
+token_delete_cb(void *p_void) {
+ token_delete(p_void);
+}
+
+void
+token_ref_down_cb(void *p_void) {
+ Token *p_token = p_void;
+ token_ref_down(p_token);
+}
+
+void*
+token_copy_cb(void *p_void) {
+ return (token_new_copy(p_void));
+}
+
+void
+token_delete(Token *p_token) {
+ if (token_ref_down(p_token) <= 0) {
+ if (p_token->i_ref_count == 0) {
+#ifdef DEBUG_TOKEN_REFCOUNT
+ printf("DEBUG::TOKEN::REFCOUNT: Token ref count is 0 == %d\n",
+ p_token->i_ref_count);
+#endif /* DEBUG_TOKEN_REFCOUNT */
+ if (p_token->c_val)
+ free(p_token->c_val);
+
+ if (NULL != p_token->p_array)
+ array_delete_iterate(p_token->p_array, token_delete_cb);
+
+ free(p_token);
+ }
+#ifdef DEBUG_TOKEN_REFCOUNT
+ else {
+ printf("DEBUG::TOKEN::REFCOUNT: Token ref count is 0 > %d\n",
+ p_token->i_ref_count);
+ }
+#endif /* DEBUG_TOKEN_REFCOUNT */
+ }
+#ifdef DEBUG_TOKEN_REFCOUNT
+ else {
+ printf("DEBUG::TOKEN::REFCOUNT: Token ref count is 0 < %d\n",
+ p_token->i_ref_count);
+ }
+#endif /* DEBUG_TOKEN_REFCOUNT */
+}
+
+void
+token_print(Token *p_token) {
+ printf("(id=%05u, line=%05d, pos=%04d, type=%s, val=%s, ival=%d, dval=%f,"
+ " refs=%d)",
+ p_token->u_token_id,
+ p_token->i_line_nr,
+ p_token->i_pos_nr,
+ tt_get_name(p_token->tt_cur),
+ p_token->c_val,
+ p_token->i_val,
+ p_token->d_val,
+ p_token->i_ref_count);
+}
+
+void
+token_print_val(Token *p_token) {
+ TokenType tt = token_get_tt(p_token);
+ switch (tt) {
+ case TT_INTEGER:
+ printf("(%s, %d)", tt_get_name(tt), token_get_ival(p_token));
+ break;
+ case TT_DOUBLE:
+ printf("(%s, %f)", tt_get_name(tt), token_get_dval(p_token));
+ break;
+ case TT_STRING:
+ printf("(%s, %s)", tt_get_name(tt), token_get_val(p_token));
+ break;
+ case TT_ARRAY:
+ printf("(%s, size:%d)", tt_get_name(tt),
+ array_get_size(p_token->p_array));
+ break;
+ default:
+ ERROR("Ouups(%s)!", tt_get_name(tt));
+ }
+}
+
+void
+token_print_cb(void *p_void) {
+ Token *p_token = p_void;
+ printf("Token ");
+ token_print(p_token);
+ printf("\n");
+}
+
diff --git a/src/core/token.h b/src/core/token.h
new file mode 100644
index 0000000..fe4ff52
--- /dev/null
+++ b/src/core/token.h
@@ -0,0 +1,195 @@
+/*:*
+ *: File: ./src/core/token.h
+ *: A simple interpreter
+ *:
+ *: WWW : http://fype.buetow.org
+ *: AUTHOR : http://paul.buetow.org
+ *: E-Mail : fype at dev.buetow.org
+ *:
+ *: Copyright (c) 2005 - 2008, Paul Buetow
+ *: All rights reserved.
+ *:
+ *: Redistribution and use in source and binary forms, with or without modi-
+ *: fication, are permitted provided that the following conditions are met:
+ *: * Redistributions of source code must retain the above copyright
+ *: notice, this list of conditions and the following disclaimer.
+ *: * Redistributions in binary form must reproduce the above copyright
+ *: notice, this list of conditions and the following disclaimer in the
+ *: documentation and/or other materials provided with the distribution.
+ *: * Neither the name of P. B. Labs nor the names of its contributors may
+ *: be used to endorse or promote products derived from this software
+ *: without specific prior written permission.
+ *:
+ *: THIS SOFTWARE IS PROVIDED BY PAUL C. BUETOW AS IS'' AND ANY EXPRESS OR
+ *: IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ *: WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ *: DISCLAIMED. IN NO EVENT SHALL PAUL C. BUETOW BE LIABLE FOR ANY DIRECT,
+ *: INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ *: (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ *: SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ *: HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ *: STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ *: IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ *: POSSIBILITY OF SUCH DAMAGE.
+ *:*/
+
+#ifndef TOKEN_H
+#define TOKEN_H
+
+#include "../defines.h"
+#include "../data/array.h"
+
+#define IS_TERMINAL(t) (START_TERMINALS < t && t < END_TERMINALS)
+#define IS_NOT_TERMINAL(t) !IS_TERMINAL(t)
+#define IS_TYPE(t) (START_TYPES < t && t < END_TYPES)
+#define IS_NOT_TYPE(t) !IS_TYPE(t)
+#define IS_KEYWORD(t) (START_KEYWORDS < t && t < END_KEYWORDS)
+#define IS_NOT_KEYWORD(t) !IS_KEYWORD(t)
+#define IS_OPERATOR(t) (START_OPERATORS < t && t < END_OPERATORS)
+#define IS_NOT_OPERATOR(t) !IS_OPERATOR(t)
+#define IS_NON_TERMINAL(t) (START_NON_TERMINALS < t && t < END_NON_TERMINALS)
+#define IS_NOT_NON_TERMINAL(t) !IS_NON_TERMINAL(t)
+#define IS_IDENT(t) (t == TT_IDENT)
+#define IS_NOT_IDENT(t) !(IS_IDENT(t))
+#define IS_ASSIGNABLE(t) (START_ASSIGNABLES < t && t < END_ASSIGNABLES)
+#define IS_NUMERICAL(t) (START_NUMERICAL < t && t < END_NUMERICAL)
+#define IS_NOT_NUMERICAL(t) !(IS_NUMERICAL(t))
+
+#define token_get_filename(t) \
+ (t->c_filename != NULL ? t->c_filename : "Code string")
+#define token_get_line_nr(t) t->i_line_nr
+#define token_get_pos_nr(t) t->i_pos_nr
+#define token_get_tt(t) (t ? t->tt_cur : TT_NONE)
+#define token_get_val(t) t->c_val
+#define token_get_ival(t) t->i_val
+#define token_get_dval(t) t->d_val
+#define token_set_tt(t,tt) t->tt_cur = tt
+#define token_set_val(t,c) t->c_val = c
+#define token_set_ival(t,i) t->i_val = i
+#define token_set_dval(t,d) t->d_val = d
+#define token_set_pos(t, l, p) t->i_line_nr = l; t->i_pos_nr = p
+#define token_get_posnr(t) t->i_pos_nr
+#define token_get_linenr(t) t->i_line_nr
+#define token_ref_up(t) ++t->i_ref_count
+#define token_ref_down(t) --t->i_ref_count
+#define TOKEN_GET_ARRAY(t) t->p_array
+
+typedef enum {
+ // Diverse
+ TT_NONE,
+ TT_END_OF_CODE,
+ TT_BOOL, // Temporaly disabled, maybe NUMERICAL in future again
+
+ // Diverse types
+ START_TERMINALS,
+ START_TYPES,
+ START_ASSIGNABLES,
+ START_NUMERICAL,
+ TT_INTEGER,
+ TT_DOUBLE,
+ END_NUMERICAL,
+ TT_STRING,
+ TT_ARRAY,
+ END_ASSIGNABLES,
+ TT_IDENT,
+ END_TYPES,
+
+ // Keywords
+ START_KEYWORDS,
+ TT_ELSE,
+ TT_BREAK,
+ TT_IF,
+ TT_IFNOT,
+ TT_RET,
+ TT_CONST,
+ TT_PROC,
+ TT_FUNC,
+ TT_MY,
+ TT_ARR,
+ TT_WHILE,
+ TT_UNTIL,
+ TT_NEXT,
+ TT_INT,
+ TT_DEFINED,
+ TT_UNDEF,
+ TT_SYMS,
+ END_KEYWORDS,
+
+ START_PARANTS,
+ TT_PARANT_CL,
+ TT_PARANT_CR,
+ TT_PARANT_AL,
+ TT_PARANT_AR,
+ TT_PARANT_L,
+ TT_PARANT_R,
+ END_PARANTS,
+
+ // Operators
+ START_OPERATORS,
+ TT_ADD,
+ TT_AND,
+ TT_AAND,
+ TT_ASSIGN,
+ TT_COMMA,
+ TT_DDOT,
+ TT_DECR,
+ TT_DIV,
+ TT_DOT,
+ TT_EQ,
+ TT_GE,
+ TT_GT,
+ TT_INCR,
+ TT_LE,
+ TT_LSHIFT,
+ TT_LT,
+ TT_MULT,
+ TT_NEQ,
+ TT_NOT,
+ TT_NOTEQ,
+ TT_OR,
+ TT_RE,
+ TT_RSHIFT,
+ TT_SEMICOLON,
+ TT_SUB,
+ TT_VID,
+ TT_XOR,
+ END_OPERATORS,
+
+ END_TERMINALS,
+
+} TokenType;
+
+typedef struct {
+ TokenType tt_cur;
+ char *c_val;
+ int i_val;
+ double d_val;
+ int i_line_nr;
+ int i_pos_nr;
+ char *c_filename;
+ unsigned int u_token_id;
+ int i_ref_count;
+ Array *p_array;
+} Token;
+
+Token* token_new(char *c_val, TokenType tt_cur, int i_line_nr,
+ int i_pos_nr, char *c_filename);
+Token* token_new_integer(int i_val);
+Token* token_new_couble(double d_val);
+Token* token_new_string(char *c_val);
+Token* token_new_array(int i_size);
+Token* token_new_copy(Token *p_token);
+Token* token_new_(char *c_val, TokenType tt_cur, char *c_filename);
+Token* token_new_dummy();
+void token_copy_vals(Token *p_token_to, Token *p_token_from);
+void token_delete(Token *p_token);
+void token_delete_cb(void *p_token);
+void token_ref_down_cb(void *p_token);
+void* token_copy_cb(void *p_token);
+char* tt_get_name(TokenType tt_cur);
+void token_print_cb(void *p_void);
+void token_print(Token *p_token);
+void token_print_val(Token *p_token);
+TokenType get_tt(char *c_token);
+
+#endif