Newer
Older
#include <stdio.h>
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
#include "heap.h"
void * heap_alloc_alligned ( Heap * heap, size_t len, size_t align ) {
size_t pos = (size_t) heap -> next;
size_t rem = pos % align;
if ( rem )
heap -> next = heap -> next + align - rem;
if ( heap -> next + len >= heap -> end )
return NULL;
void * ret = heap -> next;
heap -> next += len;
return ret;
}
void * heap_alloc ( Heap * heap, size_t len ) {
size_t pos = (size_t) heap -> next;
size_t rem = pos % 8;
if ( rem )
heap -> next = heap -> next + 8 - rem;
if ( heap -> next + len >= heap -> end )
return NULL;
void * ret = heap -> next;
heap -> next += len;
return ret;
}
void heap_init ( Heap * heap, size_t heap_size ) {
heap -> begin = (u8*) malloc ( heap_size );
heap -> next = heap -> begin;
heap -> end = heap -> begin + heap_size;
}
void heap_destroy ( Heap * heap ) {
free ( heap -> begin );
}
int compare_entry ( const void * a, const void * b ) {
return str_cmp ( ((SimpleEntry*) a) -> name, ((SimpleEntry*) b) -> name );
}
bool value_to_bool ( Value * value ) {
if ( value -> kind == VALUE_NULL )
return false;
if ( value -> kind == VALUE_BOOLEAN )
return ((BoolValue*) value ) -> boolean;
return true;
}
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
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
Value * try_operator ( Heap * heap, Value * object, Value ** arguments, size_t argc, Str * name ) {
switch ( object -> kind ) {
case VALUE_INTEGER: {
if ( argc != 1 ) {
fprintf ( stderr, "Invalid argument count for integer operation %.*s.\n", (int) name -> len, name -> str );
exit ( 10 );
}
IntValue * this = (IntValue*) object;
bool is_int = arguments [ 0 ] -> kind == VALUE_INTEGER;
if ( is_int ) {
IntValue * other = (IntValue*) arguments [ 0 ];
if ( str_eq ( *name, STR ("+") ) )
return make_int ( heap, this -> integer + other -> integer );
if ( str_eq ( *name, STR ("-") ) )
return make_int ( heap, this -> integer - other -> integer );
if ( str_eq ( *name, STR ("*") ) )
return make_int ( heap, this -> integer * other -> integer );
if ( str_eq ( *name, STR ("/") ) )
return make_int ( heap, this -> integer / other -> integer );
if ( str_eq ( *name, STR ("%") ) )
return make_int ( heap, this -> integer % other -> integer );
if ( str_eq ( *name, STR ("<=") ) )
return make_bool ( heap, this -> integer <= other -> integer );
if ( str_eq ( *name, STR (">=") ) )
return make_bool ( heap, this -> integer >= other -> integer );
if ( str_eq ( *name, STR ("<") ) )
return make_bool ( heap, this -> integer < other -> integer );
if ( str_eq ( *name, STR (">") ) )
return make_bool ( heap, this -> integer > other -> integer );
if ( str_eq ( *name, STR ("==") ) )
return make_bool ( heap, this -> integer == other -> integer );
if ( str_eq ( *name, STR ("!=") ) )
return make_bool ( heap, this -> integer != other -> integer );
break;
}
if ( str_eq ( *name, STR ("==") ) )
return make_bool ( heap, false );
if ( str_eq ( *name, STR ("!=") ) )
return make_bool ( heap, true );
break;
}
case VALUE_BOOLEAN: {
if ( argc != 1 ) {
fprintf ( stderr, "Invalid argument count for bool operation %.*s.\n", (int) name -> len, name -> str );
exit ( 10 );
}
BoolValue * this = (BoolValue*) object;
bool is_bool = arguments [ 0 ] -> kind == VALUE_BOOLEAN;
if ( is_bool ) {
BoolValue * other = (BoolValue*) arguments [ 0 ];
if ( str_eq ( *name, STR ("&") ) )
return make_bool ( heap, this -> boolean & other -> boolean );
if ( str_eq ( *name, STR ("|") ) )
return make_bool ( heap, this -> boolean | other -> boolean );
if ( str_eq ( *name, STR ("==") ) )
return make_bool ( heap, this -> boolean == other -> boolean );
if ( str_eq ( *name, STR ("!=") ) )
return make_bool ( heap, this -> boolean != other -> boolean );
break;
}
if ( str_eq ( *name, STR ("==") ) )
return make_bool ( heap, false );
if ( str_eq ( *name, STR ("!=") ) )
return make_bool ( heap, true );
break;
}
case VALUE_NULL: {
if ( argc != 1 ) {
fprintf ( stderr, "Invalid amount of arguments for null operation %.*s.\n", (int) name -> len, name -> str );
exit ( 10 );
}
if ( str_eq ( *name, STR ("==") ) )
return make_bool ( heap, arguments [ 0 ] -> kind == VALUE_NULL ? true : false );
if ( str_eq ( *name, STR ("!=") ) )
return make_bool ( heap, arguments [ 0 ] -> kind != VALUE_NULL ? true : false );
break;
}
case VALUE_ARRAY:
if ( str_eq ( *name, STR ("get") ) ) {
if ( argc != 1 || arguments [ 0 ] -> kind != VALUE_INTEGER ) {
fprintf ( stderr, "Invalid argument for array get.\n" );
exit ( 11 );
}
ArrayValue * array = (ArrayValue*) object;
i32 index = ((IntValue*) arguments [ 0 ]) -> integer;
if ( index < 0 || index >= array -> length ) {
fprintf ( stderr, "Index is out of bounds.\n" );
exit ( 11 );
}
return array -> elements [ index ];
}
if ( str_eq ( *name, STR ("set") ) ) {
if ( argc != 2 || arguments [ 0 ] -> kind != VALUE_INTEGER ) {
fprintf ( stderr, "Invalid arguments for array set.\n" );
exit ( 12 );
}
ArrayValue * array = (ArrayValue*) object;
i32 index = ((IntValue*) arguments [ 0 ]) -> integer;
if ( index < 0 || index >= array -> length ) {
fprintf ( stderr, "Index is out of bounds.\n" );
exit ( 12 );
}
array -> elements [ index ] = arguments [ 1 ];
return arguments [ 1 ];
}
break;
default:
break;
}
return NULL;
}
Value * get_base ( Value * object ) {
Value * curr = object;
while ( curr -> kind == VALUE_OBJECT )
curr = ((ObjectValue *) curr) -> extends;
return curr;
}
Value ** get_object_field ( Value * object, Str name ) {
Value * next = object;
ObjectValue * curr;
do {
curr = (ObjectValue*) next;
for ( size_t i = 0; i < curr -> member_cnt; ++i )
if ( str_eq ( curr -> members [ i ] . name, name ) )
return & curr -> members [ i ] . value;
next = curr -> extends;
} while ( next -> kind == VALUE_OBJECT );
return NULL;
}
Value * find_current_object_field ( Value * object, Str name ) {
ObjectValue * curr = (ObjectValue*) object;
for ( size_t i = 0; i < curr -> member_cnt; ++i )
if ( str_eq ( curr -> members [ i ] . name, name ) )
return curr -> members [ i ] . value;
return NULL;
}
Value * make_int ( Heap * heap, i32 val ) {
IntValue * value = heap_alloc ( heap, sizeof (IntValue) );
*value = (IntValue) { .kind = (Value) { .kind = VALUE_INTEGER }, .integer = val };
return (Value*) value;
}
Value * make_bool ( Heap * heap, bool val ) {
BoolValue * value = heap_alloc ( heap, sizeof (BoolValue) );
*value = (BoolValue) { .kind = (Value) { .kind = VALUE_BOOLEAN }, .boolean = val };
return (Value*) value;
}
Value * make_function ( Heap * heap, AstFunction * function ) {
FunctionValue * value = heap_alloc ( heap, sizeof (FunctionValue) );
*value = (FunctionValue) { .kind = (Value) { .kind = VALUE_FUNCTION }, .function = function };
return (Value*) value;
}
Value * make_cfunction ( Heap * heap, ConstantFunction function ) {
CFunctionValue * value = heap_alloc ( heap, sizeof (CFunctionValue) );
*value = (CFunctionValue) { .kind = (Value) { .kind = VALUE_FUNCTION }, .function = function };
return (Value*) value;
}
Value * make_array ( Heap * heap, size_t len ) {
ArrayValue * value = heap_alloc ( heap, sizeof (ArrayValue) + len * sizeof (Value*) );
*value = (ArrayValue) { .kind = (Value) { .kind = VALUE_ARRAY }, .length = len };
return (Value*) value;
}
Value * make_object ( Heap * heap, size_t member_cnt ) {
ObjectValue * value = heap_alloc ( heap, sizeof (ObjectValue) + member_cnt * sizeof (SimpleEntry) );
*value = (ObjectValue) { .kind = (Value) { .kind = VALUE_OBJECT }, .member_cnt = member_cnt };
return (Value*) value;
}
Value * make_null ( Heap * heap ) {
NullValue * value = heap_alloc ( heap, sizeof (NullValue) );
*value = (NullValue) { .kind = (Value) { .kind = VALUE_NULL } };
return (Value*) value;
}