jamen / Ginger (http://ging3r.org/)

No description has been added.

Clone this repository (size: 558.9 KB): HTTPS / SSH
$ hg clone http://bitbucket.org/jamen/ginger/
commit 20: 46cf4e66fbcd
parent 19: 6a6759dde047
branch: default
Minor changes.
jamesdeanpalmer
2 months ago

Changed (Δ934 bytes):

raw changeset »

src/ginger.h (73 lines added, 51 lines removed)

Up to file-list src/ginger.h:

1
1
/*
2
2
  Copyright 2009 by James Dean Palmer and others.
3
3
4
  Licensed under the Apache License, Version 2.0 (the "License"); 
5
  you may not use this file except in compliance with the License. 
6
  You may obtain a copy of the License at 
7
 
8
    http://www.apache.org/licenses/LICENSE-2.0 
9
 
10
  Unless required by applicable law or agreed to in writing, software 
11
  distributed under the License is distributed on an "AS IS" BASIS, 
12
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
13
  See the License for the specific language governing permissions and 
14
  limitations under the License. 
15
 
4
  Licensed under the Apache License, Version 2.0 (the "License");
5
  you may not use this file except in compliance with the License.
6
  You may obtain a copy of the License at
7
8
    http://www.apache.org/licenses/LICENSE-2.0
9
10
  Unless required by applicable law or agreed to in writing, software
11
  distributed under the License is distributed on an "AS IS" BASIS,
12
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
  See the License for the specific language governing permissions and
14
  limitations under the License.
15
16
16
  Please report all bugs and problems to "bugs@ging3r.org".
17
17
*/
18
18
19
19
#ifndef GINGER_H
20
20
#define GINGER_H
21
21
22
#define DEBUG
22
//#define DEBUG 1
23
23
//#define GC_DEBUG
24
24
25
25
/// Section 0: Includes
35
35
36
36
/// This is the primary reference used internally by Ginger.  It can hold
37
37
/// immediate (chars, fixed ints, symbols, etc.) and non-immediates (a pointer
38
/// to more complex data structures (foreign objects, floats, dictionaries, 
38
/// to more complex data structures (foreign objects, floats, dictionaries,
39
39
/// etc.)
40
40
41
41
#define GIN_OBJ void*
@@ -64,6 +64,7 @@ typedef struct {
64
64
} Frame_Narg;
65
65
66
66
typedef struct {
67
  GIN_OBJ dispatch_table;
67
68
  GIN_OBJ type_index;
68
69
  GIN_OBJ left;
69
70
  GIN_OBJ right;
@@ -72,6 +73,7 @@ typedef struct {
72
73
} GingerDictionaryCell;
73
74
74
75
typedef struct {
76
  GIN_OBJ dispatch_table;
75
77
  GIN_OBJ type_index;
76
78
  GIN_OBJ root;
77
79
} GingerDictionary;
@@ -85,7 +87,7 @@ typedef struct GingerClassDefinition_t {
85
87
  GIN_OBJ unmake;
86
88
} GingerClassDefinition;
87
89
88
/// Function are first class objects and we have to maintain some metadata 
90
/// Function are first class objects and we have to maintain some metadata
89
91
/// for them.
90
92
91
93
typedef struct {
@@ -97,6 +99,7 @@ typedef struct {
97
99
/// This is the primary object type.
98
100
99
101
typedef struct {
102
  GIN_OBJ dispatch_table;
100
103
  GIN_OBJ type_index;
101
104
  union {
102
105
    void*  f0;
@@ -108,67 +111,75 @@ typedef struct {
108
111
  };
109
112
  union {
110
113
    void* f1;
114
    Frame* previous_lexical_frame;
111
115
  };
112
116
  union {
113
117
    void* f2;
114
118
    long  str_length;
115
    Frame* previous_lexical_frame;
116
119
  };
117
120
} GingerObject;
118
121
119
122
typedef struct {
123
  GIN_OBJ dispatch_table;
120
124
  GIN_OBJ type_index;
121
125
  double value;
122
126
} GingerFlonum;
123
127
124
128
typedef struct {
129
  GIN_OBJ dispatch_table;
125
130
  GIN_OBJ type_index;
126
131
  long value;
127
132
} GingerInteger;
128
133
129
134
typedef struct {
135
  GIN_OBJ dispatch_table;
130
136
  GIN_OBJ type_index;
131
137
  unsigned long length;
132
138
  unsigned long value[];
133
139
} GingerBinary;
134
140
135
141
typedef struct {
142
  GIN_OBJ dispatch_table;
136
143
  GIN_OBJ type_index;
137
144
  long length;
145
  long pool_length;
138
146
  GIN_OBJ *value;
139
147
} GingerVector;
140
148
141
149
typedef struct {
150
  GIN_OBJ dispatch_table;
142
151
  GIN_OBJ type_index;
143
152
  GIN_OBJ index;  // Always NIM
144
153
  //  GIN_OBJ make;
145
154
  //  GIN_OBJ unmake;
146
155
  GIN_OBJ(*c_make) ();
147
156
  void(*c_unmake) (GIN_OBJ);
148
     
157
149
158
} GingerType;
150
159
151
160
typedef struct {
152
161
  short num_bytes;
153
162
  short visited;
163
  short active;
154
164
} GCFastAllocHeader;
155
165
156
166
typedef struct GCSysAllocHeader_t {
157
167
  short num_bytes;
158
168
  short visited;
169
  short active;
159
170
  short requires_cleanup;
160
171
  struct GCSysAllocHeader_t* next;
161
172
} GCSysAllocHeader;
162
173
163
174
typedef struct GarbageCollector_t {
164
  void* fast_heap_alpha;
165
  void* fast_heap_beta;
175
  char* fast_heap_alpha;
176
  char* fast_heap_beta;
166
177
167
178
  // not set until collection starts
168
  void* fast_heap_alpha_end;
169
  void* fast_heap_beta_end;
179
  char* fast_heap_alpha_end;
180
  char* fast_heap_beta_end;
170
181
171
  void* alpha_allocation_cursor;
182
  char* alpha_allocation_cursor;
172
183
  int   alpha_remaining_bytes;
173
184
174
185
  void (*collection_callback)(struct GarbageCollector_t* data);
@@ -197,7 +208,7 @@ typedef struct GarbageCollector_t {
197
208
  // their cleanup method called.
198
209
  GCSysAllocHeader* pending_cleanup;
199
210
200
  // Items on the persistent_list do not need to be referenced 
211
  // Items on the persistent_list do not need to be referenced
201
212
  // during collections and are only freed at the end of the program.
202
213
  GCSysAllocHeader* persistent_list;
203
214
@@ -206,16 +217,21 @@ typedef struct GarbageCollector_t {
206
217
/// Section 2: Macro definitions
207
218
///
208
219
209
#define GIN_GC_MB 5
220
#define GIN_GC_MB 50
210
221
#define GIN_GC_INIT mm = gc_new(1024*1024*GIN_GC_MB); gc_set_collection_callback(mm, collect);
211
222
#define GIN_ALLOCATE(v, type, size) safe_allocate = (GIN_OBJ)gc_allocate(mm, size); \
212
223
v = (type)safe_allocate;
213
224
225
#define GIN_ALLOCATE_FRAME(v, type, size) safe_allocate = (GIN_OBJ)gc_allocate_call(mm, size); \
226
v = (type)safe_allocate;
227
228
#define GIN_DEALLOCATE_FRAME(v) gc_deallocate_call(mm, v);
229
214
230
#define GIN_ALLOCATE_WITH_CLEANUP(v, type, size) safe_allocate = (GIN_OBJ)gc_allocate_system(mm, size); \
215
231
v = (type)safe_allocate; \
216
232
gc_mark_as_requiring_cleanup(mm, v);
217
233
218
/// Calls are split into two macros.  First we allocate the call frame with 
234
/// Calls are split into two macros.  First we allocate the call frame with
219
235
/// CALL_ALLOCATE.  Then you copy any parameters.  Then use CALL.
220
236
221
237
#define CALL_ALLOCATE(function) \
@@ -240,11 +256,12 @@ gc_mark_as_requiring_cleanup(mm, v);
240
256
position_ ## seed : \
241
257
  result0 = frame->next_frame->result; \
242
258
  frame->next_frame->previous_frame = 0; \
243
  frame->next_frame = 0; \
259
  frame->next_frame->previous_lexical_frame = 0; \
244
260
  ENDDEBUG \
245
  DEALLOCATE_FRAME___ ## function (frame->next_frame)
261
  DEALLOCATE_FRAME___ ## function (frame->next_frame) \
262
  frame->next_frame = 0;
246
263
247
#define CALLN(previous_lframe,function,seed,result0,varn)	\
264
#define CALLN(previous_lframe,function,seed,result0,varn)       \
248
265
  ALLOCATE_FRAME___ ## function (frame->next_frame) \
249
266
  frame->next_frame->previous_lexical_frame = previous_lframe; \
250
267
  frame->next_frame->previous_frame = frame; \
@@ -263,13 +280,14 @@ position_ ## seed : \
263
280
position_ ## seed : \
264
281
  result0 = frame->next_frame->result; \
265
282
  frame->next_frame->previous_frame = 0; \
266
  frame->next_frame = 0; \
267
  DEALLOCATE_FRAME___ ## function (frame->next_frame)
283
  frame->next_frame->previous_lexical_frame = 0; \
284
  DEALLOCATE_FRAME___ ## function (frame->next_frame);  \
285
  frame->next_frame = 0;
268
286
269
287
// 1. if it's not a function and has no args, return the value.
270
288
// 2. if it's not a function and has args - we need to determine the method to call. then do 3.
271
289
// 3. if it is a function, use the signature to properly order the arguments and make the call.
272
#define CALLNDYNAMIC(function,seed,result0,varn)	\
290
#define CALLNDYNAMIC(function,seed,result0,varn)        \
273
291
  if ((varn == GIN_NULL) && !(GIN_IS_FUNCTION(function))) result0 = function; \
274
292
  else { \
275
293
  if (!GIN_IS_FUNCTION(function)) { \
@@ -294,9 +312,10 @@ position_ ## seed : \
294
312
position_ ## seed : \
295
313
  result0 = frame->next_frame->result; \
296
314
  frame->next_frame->previous_frame = 0; \
315
  frame->next_frame->previous_lexical_frame = 0; \
316
  GIN_DEALLOCATE_FRAME(frame->next_frame); \
297
317
  frame->next_frame = 0; \
298
318
}
299
  //DEALLOCATE_FRAME___ ## function (frame->next_frame)
300
319
301
320
#define GLOBALS int next_seed = 5000; \
302
321
GIN_OBJ calln_temp; \
@@ -308,7 +327,7 @@ GIN_OBJ safe_allocate; \
308
327
GarbageCollector* mm; \
309
328
int gin_argc; \
310
329
char **gin_argv; \
311
int gin_debug = 0; \
330
int gin_debug = 1; \
312
331
int gin_debug_max_depth = -1; \
313
332
int debug_depth = 0; \
314
333
int debug_depth_iterator = 0; \
@@ -328,19 +347,19 @@ GIN_OBJ ginExec (GIN_OBJ fn, GIN_OBJ arg
328
347
329
348
#define END_CODE end_code_return: return frame->result;  \
330
349
} \
331
int main(int argc, char *argv[]) {			\
350
int main(int argc, char *argv[]) {                      \
332
351
  gin_argc = argc; \
333
352
  gin_argv = argv; \
334
353
  GIN_GC_INIT; \
335
354
  frame = 0; \
336
  GIN_ALLOCATE(frame, Frame*, sizeof(Frame));	\
337
  frame->previous_frame = 0;			\
355
  GIN_ALLOCATE_FRAME(frame, Frame*, sizeof(Frame));     \
356
  frame->previous_frame = 0;                    \
338
357
  frame->result = 0; \
339
358
  frame->next_frame = 0;  \
340
  frame->previous_lexical_frame = 0;		\
359
  frame->previous_lexical_frame = 0;            \
341
360
  ginExec(0, GIN_NULL); \
342
361
  GIN_OBJ main_fn; \
343
  GIN_NEW_FN(main_fn, &(gin_function_table[0]), 0);	\
362
  GIN_NEW_FN(main_fn, &(gin_function_table[0]), 0);     \
344
363
  ginExec(main_fn, GIN_NULL); \
345
364
  return 0; \
346
365
}
@@ -350,7 +369,7 @@ int main(int argc, char *argv[]) { \
350
369
#define END_FUNCTION() frame = frame->previous_frame; \
351
370
  goto *(frame->next_frame->return_address);
352
371
353
// GIN_OBJ is defined as a void* but in reality it can hold 
372
// GIN_OBJ is defined as a void* but in reality it can hold
354
373
// pointers (non-immediates) and certain useful primitives
355
374
// (immediates).  The following describes how the bit string
356
375
// works:
@@ -465,7 +484,7 @@ int main(int argc, char *argv[]) { \
465
484
#define GIN_TYPE_BOOL GIN_IM_FROM_INT(13)
466
485
#define GIN_TYPE_NULL GIN_IM_FROM_INT(14)
467
486
#define GIN_TYPE_CHAR GIN_IM_FROM_INT(15)
468
//#define GIN_TYPE_FOREIGN 
487
//#define GIN_TYPE_FOREIGN
469
488
470
489
/*
471
490
#define GIN_TYPE_STR8 1
@@ -541,11 +560,11 @@ int main(int argc, char *argv[]) { \
541
560
 v = safe_pair;
542
561
#define GIN_NEW_FIXNUM(v,a) v=GIN_IM_FROM_INT(a);
543
562
/* #define GIN_NEW_INTEGER_FROM_INT(v, a) GIN_ALLOCATE_WITH_CLEANUP(v, GingerInteger*, sizeof(GingerInteger)); \ */
544
/* ((GingerInteger*)v)->type_index = GIN_TYPE_INT;				\ */
563
/* ((GingerInteger*)v)->type_index = GIN_TYPE_INT;                              \ */
545
564
/* mpz_init_set_si(((GingerInteger*)v)->value, a); */
546
565
/* #define GIN_NEW_INTEGER_FROM_STR(v, a) GIN_ALLOCATE_WITH_CLEANUP(v, GingerInteger*, sizeof(GingerInteger)); \ */
547
/* ((GingerInteger*)v)->type_index = GIN_TYPE_INT;				\ */
548
/* printf("herez!!?\n\n");						\ */
566
/* ((GingerInteger*)v)->type_index = GIN_TYPE_INT;                              \ */
567
/* printf("herez!!?\n\n");                                              \ */
549
568
/* mpz_init ((((GingerInteger*)v)->value));  */
550
569
/* mpz_init_set_str((((GingerInteger*)v)->value), a, 10); */
551
570
#define GIN_NEW_FN(v,a,frame) GIN_ALLOCATE(v, void*, sizeof(GingerObject)); \
@@ -563,14 +582,14 @@ memcpy(((GingerObject*)v)->str8_value, a
563
582
#define GIN_NEW_EMPTY_STR8(v) GIN_ALLOCATE(v, void*, sizeof(GingerObject)); \
564
583
((GingerObject*)v)->type_index = GIN_TYPE_STR8; \
565
584
((GingerObject*)v)->str_length = 0;
566
#define GIN_NEW_STR16(v,a) GIN_ALLOCATE(v, void*, sizeof(GingerObject));	\
585
#define GIN_NEW_STR16(v,a) GIN_ALLOCATE(v, void*, sizeof(GingerObject));        \
567
586
((GingerObject*)v)->type_index = GIN_TYPE_STR16; \
568
587
((GingerObject*)v)->str16_value = a;
569
588
#define GIN_NEW_SYM(v,a) v=GIN_IM_FROM_SYM(a);
570
589
#define GIN_NEW_LABEL(v,a) v=GIN_IM_FROM_LABEL(a);
571
590
#define GIN_NEW_BOOL(v,a) v=GIN_IM_FROM_BOOL(a);
572
591
#define GIN_NEW_OBJ(v,a) v=a;
573
#define GIN_NEW_FLONUM(v,a) GIN_ALLOCATE(v, void*, sizeof(GingerFlonum));	\
592
#define GIN_NEW_FLONUM(v,a) GIN_ALLOCATE(v, void*, sizeof(GingerFlonum));       \
574
593
((GingerFlonum*)v)->type_index = GIN_TYPE_FLONUM; \
575
594
((GingerFlonum*)v)->value = a;
576
595
#define GIN_NEW_NIM(v) GIN_ALLOCATE(v, void*, sizeof(GingerObject));
@@ -604,14 +623,14 @@ GIN_NIM_SET_STREAM_MODE(v,m);
604
623
((GingerObject*)v)->type_index = GIN_TYPE_STRING_STREAM; \
605
624
GIN_NIM_SET_STRING_STREAM_LENGTH(v,strlen(s)); \
606
625
GIN_NIM_SET_STRING_STREAM_POSITION(v,0);                        \
607
GIN_ALLOCATE(((GingerObject*)v)->str8_value, char*, strlen(s)+1);	\
626
GIN_ALLOCATE(((GingerObject*)v)->str8_value, char*, strlen(s)+1);       \
608
627
memcpy(((GingerObject*)v)->str8_value, s, strlen(s)+1);
609
628
610
629
#define GIN_NEW_EMPTY_STRING_STREAM(v,m) GIN_ALLOCATE(v, void*, sizeof(GingerObject)); \
611
630
((GingerObject*)v)->type_index = GIN_TYPE_STRING_STREAM; \
612
631
GIN_NIM_SET_STRING_STREAM_LENGTH(v,0); \
613
632
GIN_NIM_SET_STRING_STREAM_POSITION(v,0);              \
614
GIN_ALLOCATE(((GingerObject*)v)->str8_value, char*, 1);	\
633
GIN_ALLOCATE(((GingerObject*)v)->str8_value, char*, 1); \
615
634
((GingerObject*)v)->str8_value[0] = 0;
616
635
617
636
@@ -684,11 +703,11 @@ GIN_ALLOCATE(v, void*, sizeof(GingerObje
684
703
// GC_DEFAULT_FAST_PAGE_SIZE
685
704
//
686
705
// 5 MB default fast memory page size.  Two of these will be
687
// allocated for a total of 10MB.  Larger sizes result in less 
706
// allocated for a total of 10MB.  Larger sizes result in less
688
707
// frequent data collections with no other impact besides
689
708
// the use of the memory itself.  Smaller allocations are certainly
690
709
// viable when memory is tight.
691
#define  GC_DEFAULT_FAST_PAGE_SIZE (5*1024*1024)
710
#define  GC_DEFAULT_FAST_PAGE_SIZE (20*1024*1024)
692
711
693
712
694
713
// GC_FAST_HEAP_THRESHOLD
@@ -701,10 +720,10 @@ GIN_ALLOCATE(v, void*, sizeof(GingerObje
701
720
//
702
721
// This is also the size limit of how many bytes may need to be
703
722
// copied over per single long-lived object.  Larger sizes will
704
// make the program faster only IF objects of the larger size 
723
// make the program faster only IF objects of the larger size
705
724
// are usually short-lived.  If they're more often long-lived,
706
725
// the program will run slower due to frequent recopying.
707
// This value should always been some fraction of the 
726
// This value should always been some fraction of the
708
727
// fast_heap_page_size - the heap threshold vs the page size
709
728
// should be a fraction of (a guess here:) 1/100 or smaller.
710
729
#if !defined(GC_FAST_HEAP_THRESHOLD)
@@ -729,6 +748,8 @@ extern void gc_report(GarbageCollector *
729
748
extern void gc_mark_as_requiring_cleanup(GarbageCollector *mm, void *m);
730
749
extern void* gc_get_next_pending_cleanup(GarbageCollector *mm);
731
750
extern void gc_analyze(GarbageCollector* mm, void* addr);
751
extern void* gc_allocate_call(GarbageCollector* mm, int num_bytes);
752
extern void gc_deallocate_call(GarbageCollector* mm, void* data);
732
753
733
754
extern GIN_OBJ ginExec (GIN_OBJ fn, GIN_OBJ args);
734
755
extern void GIN_display(GIN_OBJ x, GIN_OBJ out, int was_not_cdr);
@@ -753,6 +774,7 @@ extern void collect (GarbageCollector* m
753
774
754
775
extern GIN_OBJ gin_getenv(GIN_OBJ name, GIN_OBJ default_value);
755
776
extern GIN_OBJ gin_file_exists(GIN_OBJ filename);
777
extern GIN_OBJ gin_string_to_value(GIN_OBJ str);
756
778
757
779
/// Section 4: Global variables
758
780
///