summaryrefslogtreecommitdiff
path: root/interpreter.c
blob: 333b8c92543fdac34258498a9141a4a2c4287391 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>

#include "interpreter.h"
#include "util.h"


int namehash(const char *name,int mod){
	int h=0;
	for(int i=0;name[i];i++)h+=name[i];
	return h%mod;
}


#define VMAP_HASHSZ (61)

typedef struct Vllist{
	char *name;
	AST *value;
	struct Vllist *next;
} Vllist;

typedef struct Scope{
	Vllist *vmap[VMAP_HASHSZ];
	struct Scope *next;
} Scope;


typedef struct Symbolstore{
	int sz,len;
	char **syms;
} Symbolstore;


struct InterState{
	Scope *scope;
	Symbolstore ss;
};


Scope* scope_make(void){
	Scope *scope=malloc(1,Scope);
	memset(scope->vmap,0,VMAP_HASHSZ*sizeof(Vllist*));
	scope->next=NULL;
	return scope;
}


InterState* inter_make(void){
	InterState *is=malloc(1,InterState);
	is->scope=scope_make();
	is->ss.sz=16;
	is->ss.len=0;
	is->ss.syms=malloc(is->ss.sz,char*);
	return is;
}

static void scope_destroy(Scope *scope,bool recursive){
	do {
		for(int i=0;i<VMAP_HASHSZ;i++){
			while(scope->vmap[i]){
				Vllist *ll=scope->vmap[i];
				free(ll->name);
				ast_free(ll->value);
				scope->vmap[i]=ll->next;
				free(ll);
			}
		}
		Scope *next=scope->next;
		free(scope);
		scope=next;
	} while(recursive&&scope);
}

void inter_destroy(InterState *is){
	assert(is);
	scope_destroy(is->scope,true);
	for(int i=0;i<is->ss.len;i++)free(is->ss.syms[i]);
	free(is->ss.syms);
}


static void intern_symbols(InterState *is,AST *ast){
	switch(ast->type){
		case AST_LIST:
			for(int i=0;i<ast->l.len;i++)intern_symbols(is,ast->l.nodes[i]);
			break;

		case AST_SYMBOL:{
			if(ast->s.symid>=0&&ast->s.symid<is->ss.len&&strcmp(ast->s.name,is->ss.syms[ast->s.symid])==0){
				break;
			}
			int i;
			for(i=0;i<is->ss.len;i++){
				if(strcmp(is->ss.syms[i],ast->s.name)==0)break;
			}
			if(i<is->ss.len){
				ast->s.symid=i;
				break;
			}
			if(is->ss.len==is->ss.sz){
				is->ss.sz*=2;
				is->ss.syms=realloc(is->ss.syms,is->ss.sz,char*);
			}
			is->ss.syms[is->ss.len++]=copystring(ast->s.name);
			break;
		}

		case AST_WORD:
		case AST_NUMBER:
		case AST_STRING:
			break;
	}
}

void inter_runcode(InterState *is,AST *ast){
	intern_symbols(is,ast);
}