-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathpermmem.mc
131 lines (109 loc) · 3.87 KB
/
permmem.mc
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
121
122
123
124
125
126
127
128
129
130
131
/** ========================================================================
Permanent memory. Permanent memory is not garbage collected.
perm_alloc and intern_permexp
See mc.h for the types expstruct and expptr
======================================================================== **/
#define PERMHEAP_DIM (1<<20)
char permheap[PERMHEAP_DIM];
int permheap_freeptr;
void * perm_alloc(int size){
if(permheap_freeptr + size > PERMHEAP_DIM)berror("perm heap exhausted");
void * result = &permheap[permheap_freeptr];
permheap_freeptr += size;
return result;
}
#define PERMEXP_HASH_DIM (1 << 15)
expptr permexp_hash_table[PERMEXP_HASH_DIM];
int permexp_count;
expptr intern_permexp(char constr, expptr a1, expptr a2){
unsigned int j = (constr + 729*((long int) a1) + 125*((long int) a2)) & PERMEXP_HASH_DIM-1;
for(int i = j;1;i++){
if(i == PERMEXP_HASH_DIM)i=0;
expptr oldexp = permexp_hash_table[i];
if(oldexp == NULL){
if(permexp_count >= (2*PERMEXP_HASH_DIM)/3)berror("permanent expression hash table exhausted");
permexp_count++;
expptr newexp = perm_alloc(sizeof(expstruct));
newexp->plist = NULL;
newexp->internal = NULL;
newexp->constructor = constr;
newexp->arg1 = a1;
newexp->arg2 = a2;
permexp_hash_table[i] = newexp;
return newexp;
}else{
if(oldexp -> constructor == constr && oldexp->arg1 == a1 && oldexp-> arg2 == a2)return oldexp;
}
}
}
/** ========================================================================
permanent strings
======================================================================== **/
#define PERMSTRING_HASH_DIM 10000
char * permstring_hash_table[PERMSTRING_HASH_DIM];
int permstring_count;
int permstring_key(char * s){
int i, key;
key=0;
for(i=0;s[i] != 0;i++){
key = (1458*key + s[i]);
}
key = key&(PERMSTRING_HASH_DIM-1);
while(permstring_hash_table[key] != NULL
&& strcmp(permstring_hash_table[key], s) != 0){
key++;
if(key==PERMSTRING_HASH_DIM)key=0;
}
return key;
}
char * string_to_perm(char * s){
int key = permstring_key(s);
if(permstring_hash_table[key]==NULL){
if(permstring_count >= (2*PERMSTRING_HASH_DIM)/3)berror("string hash table exhausted");
char * s2 = perm_alloc(strlen(s) + 1);
strcpy(s2,s);
permstring_hash_table[key] = s2;
permstring_count++;
}
return permstring_hash_table[key];
}
void init_perm_memory(){
permheap_freeptr = 0;
for(int i=0;i<PERMEXP_HASH_DIM;i++)permexp_hash_table[i] = NULL;
permexp_count = 0;
for(int i=0;i<PERMSTRING_HASH_DIM;i++)permstring_hash_table[i]=NULL;
permstring_count = 0;
}
/** ========================================================================
permanent properties of permanent expressions
========================================================================**/
void perm_addprop(expptr e, expptr key, void * val){
if(e == NULL)berror("attempt to add a property of the null expression");
plist new = (plist) perm_alloc(sizeof(pliststruct));
new->key = key;
new->value = val;
new->rest = e->plist;
e-> plist = new;
}
void perm_setprop(expptr e, expptr key, void * val){
if(e == NULL)berror("attempt to set a property of the null expression");
plist cell = getprop_cell(e, key);
if(cell != NULL){
cell->value = val;
return;}
perm_addprop(e,key,val);
}
void perm_setprop_int(expptr e, expptr key, int x){
char buffer[8]; //buffer is a pointer.
int * y = (int *) buffer;
*y = x;
perm_setprop(e,key, * (expptr *) buffer);
}
/** ========================================================================
exp_to_perm
======================================================================== **/
expptr expptr_to_perm(expptr exp){
if(!exp)return NULL;
if (atomp(exp))return intern_permexp('A', (expptr) string_to_perm((char *) exp->arg1), NULL);
return stack_exp(exp->constructor,expptr_to_perm(exp->arg1),expptr_to_perm(exp->arg2));
}