summaryrefslogtreecommitdiff
path: root/src/core/interpret.c
diff options
context:
space:
mode:
authorPaul Buetow <paul@buetow.org>2008-05-15 23:28:07 +0000
committerPaul Buetow <paul@buetow.org>2008-05-15 23:28:07 +0000
commitbe839900419c7a74c4a46efd279d0ca16b35dc1f (patch)
tree1355c8f238d1c58ffd5cb8803bcc2adf987e79aa /src/core/interpret.c
parent33c945e58f86267b0d3bdca4c3421155e11eb0d9 (diff)
Moved stuff into trunk.
Diffstat (limited to 'src/core/interpret.c')
-rw-r--r--src/core/interpret.c946
1 files changed, 946 insertions, 0 deletions
diff --git a/src/core/interpret.c b/src/core/interpret.c
new file mode 100644
index 0000000..97e19c2
--- /dev/null
+++ b/src/core/interpret.c
@@ -0,0 +1,946 @@
+/*:*
+ *: File: ./src/core/interpret.c
+ *: A simple interpreter
+ *:
+ *: WWW : http://fype.buetow.org
+ *: E-Mail : fype@dev.buetow.org
+ *:
+ *: Copyright (c) 2005 2006 2007 2008, Paul Buetow (http://www.pblabs.net)
+ *: 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 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 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 "function.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 if (!_next(p_interpret)) { return (2); }
+#define _NEXT_TT _next_tt(p_interpret)
+#define _SKIP _next(p_interpret);
+
+void _print_lookahead(Interpret *p_interpret);
+int _next(Interpret *p_interpret);
+int _program(Interpret *p_interpret);
+int _var_decl(Interpret *p_interpret);
+int _var_assign(Interpret *p_interpret);
+int _var_list(Interpret *p_interpret);
+int _expression_get(Interpret *p_interpret, List *p_list_block);
+int _block_get(Interpret *p_interpret, List *p_list_block);
+int _block_skip(Interpret *p_interpret);
+int _proc_decl(Interpret *p_interpret);
+int _func_decl(Interpret *p_interpret);
+int _statement(Interpret *p_interpret);
+int _block(Interpret *p_interpret);
+int _expression(Interpret *p_interpret);
+int _expression_(Interpret *p_interpret);
+int _control(Interpret *p_interpret);
+int _compare(Interpret *p_interpret);
+int _sum(Interpret *p_interpret);
+int _product(Interpret *p_interpret);
+int _product2(Interpret *p_interpret);
+int _term(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;
+
+ 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
+
+ if (p_interpret->tt == 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);
+ }
+ }
+
+ 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
+
+ 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("====> BLOCK\n");
+ list_iterate(p_list_block, token_print_cb);
+ printf("<==== BLOCK\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("====> EXPRESSION\n");
+ list_iterate(p_list_expression, token_print_cb);
+ printf("<==== EXPRESSION\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)) {
+ if (p_interpret->tt == TT_SEMICOLON) {
+ _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_EQ:
+ case TT_NEQ:
+ case TT_LT:
+ case TT_GT:
+ case TT_LE:
+ case TT_GE:
+ {
+ Token *p_token = p_interpret->p_token;
+ _NEXT
+
+ if (!_sum(p_interpret))
+ _INTERPRET_ERROR("Expected sum", p_interpret->p_token);
+
+ function_process(p_interpret, p_token, 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 {
+ switch (p_interpret->tt) {
+ case TT_ADD:
+ case TT_SUB:
+ {
+ Token *p_token = p_interpret->p_token;
+ _NEXT
+
+ if (!_product(p_interpret))
+ _INTERPRET_ERROR("Expected product", p_token);
+
+ function_process(p_interpret, p_token, 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, 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 {
+ switch (p_interpret->tt) {
+ case TT_ASSIGN:
+ {
+ 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, p_interpret->p_stack, 2);
+ p_interpret->p_token_temp = NULL;
+
+ }
+ break; /* case */
+
+ default:
+ b_flag = false;
+ break;
+
+ } /* switch */
+
+ } while (b_flag);
+
+ return (1);
+ }
+
+ return (0);
+}
+
+int
+_term(Interpret *p_interpret) {
+ _CHECK TRACK
+
+ switch (p_interpret->tt) {
+ case TT_INTEGER:
+ case TT_DOUBLE:
+ case TT_STRING:
+ stack_push(p_interpret->p_stack, p_interpret->p_token);
+ _NEXT
+ return (1);
+
+ case TT_IDENT:
+ {
+ if (_NEXT_TT != TT_ASSIGN) {
+ 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));
+
+ } 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_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);
+}
+