121 lines
		
	
	
		
			3.4 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			121 lines
		
	
	
		
			3.4 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| #include <stddef.h>
 | |
| #include <stdio.h>
 | |
| #include <string.h>
 | |
| 
 | |
| #include "include/ast.h"
 | |
| #include "include/exec.h"
 | |
| #include "include/htab.h"
 | |
| #include "include/stack.h"
 | |
| #include "include/util.h"
 | |
| 
 | |
| extern AST* root;
 | |
| 
 | |
| ASTNumData exec_start(AST* ast) {
 | |
|     scope = stack_init();
 | |
| 
 | |
|     // Global scope. Just dummy values for testing.
 | |
|     HTab* global = htab_init();
 | |
| 
 | |
|     // n = 42.02
 | |
|     char* name = malloc(2); // TODO: Write a macro for this pattern.
 | |
|     strcpy(name, "n");
 | |
|     AST* n = ast_init(
 | |
|         AST_TYPE_VDEF,
 | |
|         ast_vdef_data_init(
 | |
|             name, ast_init(AST_TYPE_NUM, ast_num_data_init(42.02))
 | |
|         )
 | |
|     );
 | |
| 
 | |
|     htab_ins(
 | |
|         global, ((ASTVDefData*)n->data)->name, ((ASTVDefData*)n->data)->val
 | |
|     );
 | |
| 
 | |
|     // Push global namespace to `scope`.
 | |
|     stack_push(scope, global);
 | |
| 
 | |
|     return exec_exp(ast, scope);
 | |
| }
 | |
| 
 | |
| ASTNumData exec_exp(AST* ast, Stack* scope) {
 | |
|     log_dbg("Started execution.");
 | |
|     switch (ast->type) {
 | |
|         case AST_TYPE_BLOCK: return exec_block(ast, scope);
 | |
|         case AST_TYPE_CALL:  return exec_call(ast, scope);
 | |
|         case AST_TYPE_NUM:   return *(ASTNumData*)ast->data;
 | |
|         case AST_TYPE_VREF:  return exec_vref(ast, scope);
 | |
|         case AST_TYPE_VDEF:  return exec_vdef(ast, scope);
 | |
|         default:             printf("what\n"); exit(1);
 | |
|     }
 | |
| }
 | |
| 
 | |
| ASTNumData exec_block(AST* ast, Stack* scope) {
 | |
|     ASTBlockData* block = (ASTBlockData*)ast->data;
 | |
| 
 | |
|     // Loop through all but last ast.
 | |
|     for (int i = 0; i < block->ln - 1; i++) exec_exp(block->inside[i], scope);
 | |
| 
 | |
|     return exec_exp(block->inside[block->ln - 1], scope);
 | |
| }
 | |
| 
 | |
| ASTNumData exec_call(AST* ast, Stack* scope) {
 | |
|     log_dbg("Started call execution.");
 | |
|     fflush(stdout);
 | |
|     ASTCallData* calldata = (ASTCallData*)ast->data;
 | |
|     if (calldata->argc >= 1) {
 | |
|         if (!strcmp(calldata->to, "sum")) {
 | |
|             double total = exec_exp(calldata->argv[0], scope);
 | |
| 
 | |
|             for (size_t i = 1; i < calldata->argc;
 | |
|                  total += exec_exp(calldata->argv[i++], scope));
 | |
| 
 | |
|             return total;
 | |
|         } else if (!strcmp(calldata->to, "sub")) {
 | |
|             double total = exec_exp(calldata->argv[0], scope);
 | |
| 
 | |
|             for (size_t i = 1; i < calldata->argc;
 | |
|                  total -= exec_exp(calldata->argv[i++], scope));
 | |
| 
 | |
|             return total;
 | |
|         } else if (!strcmp(calldata->to, "mul")) {
 | |
|             double total = exec_exp(calldata->argv[0], scope);
 | |
| 
 | |
|             for (size_t i = 1; i < calldata->argc;
 | |
|                  total *= exec_exp(calldata->argv[i++], scope));
 | |
| 
 | |
|             return total;
 | |
|         } else if (!strcmp(calldata->to, "div")) {
 | |
|             double total = exec_exp(calldata->argv[0], scope);
 | |
| 
 | |
|             for (size_t i = 1; i < calldata->argc;
 | |
|                  total /= exec_exp(calldata->argv[i++], scope));
 | |
| 
 | |
|             return total;
 | |
|         }
 | |
|     }
 | |
|     return -1000;
 | |
| }
 | |
| 
 | |
| ASTNumData exec_vdef(AST* ast, Stack* scope) {
 | |
|     ASTVDefData* data = (ASTVDefData*)ast->data;
 | |
|     AST* val = data->val;
 | |
|     char* key = data->name;
 | |
|     htab_ins(scope->val[0], key, val);
 | |
|     return exec_exp(val, scope);
 | |
| }
 | |
| 
 | |
| ASTNumData exec_vref(AST* ast, Stack* scope) {
 | |
|     log_dbg("attempting to reference var");
 | |
|     ASTVrefData* vref = (ASTVrefData*)ast->data;
 | |
| 
 | |
|     char* key = vref->to;
 | |
|     AST* val;
 | |
| 
 | |
|     val = htab_get(scope->val[0], key);
 | |
|     if (val != NULL) return exec_exp(val, scope);
 | |
|     else log_dbg("didn't find def");
 | |
| 
 | |
|     return *ast_num_data_init(101.0);
 | |
| }
 | |
| 
 | |
| void exec_print(double n) { printf("= %lf\n", n); }
 |