bootstrap.h 16.4 KB
Newer Older
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
/*
 * Cherry programming language
 * Copyright (C) 2013 Christoph Mueller
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once

#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <setjmp.h>
#include <string.h>

struct cherry_environment;
struct cherry_value;

#define TRUE 1
#define FALSE 0

typedef void*       pointer_t;
typedef const void* const_pointer_t;

typedef uint8_t     byte_t;
typedef int64_t     fixnum_t;
typedef double      float_t;
typedef char        boolean_t;
typedef uint32_t    unicode_t;

typedef uint32_t    flags_t;

typedef struct cherry_value* (*primitive_t)(struct cherry_environment* env, struct cherry_value* args);

enum cherry_value_type {
    EMPTYLIST, BOOLEAN, DOT,
	FIXNUM, FLOAT, STRING, CHAR, PAIR,
    TUPLE, SYMBOL, PRIMITIVE, PROCEDURE
};


struct cherry_value {
    enum cherry_value_type tag;

	union {
        // trivial
		boolean_t boolean_value;
		fixnum_t fixnum_value;
		float_t float_value;
		unicode_t char_value;
		primitive_t fun_value;
		const byte_t* string_value;
		const byte_t* symbol_value;

        // lists
        struct {
          struct cherry_value* head;
          struct cherry_value* tail;
        } pair;

        // tuples
        struct {
          struct cherry_value** data;
          size_t size;
        } tuple;

        // procedures
        struct {
          struct cherry_value* param;
          struct cherry_value* body;
          struct cherry_environment* env;
        } proc;
    };
};

#define TYPE(value) (value->tag)

#define IS_NULL(value) (value->tag == EMPTYLIST)
#define IS_BOOLEAN(value) (value->tag == BOOLEAN)
#define IS_DOT(value) (value->tag == DOT)
#define IS_FIXNUM(value) (value->tag == FIXNUM)
#define IS_STRING(value) (value->tag == STRING)
#define IS_SYMBOL(value) (value->tag == SYMBOL)
#define IS_FLOAT(value) (value->tag == FLOAT)
#define IS_CHAR(value) (value->tag == CHAR)
#define IS_PAIR(value) (value->tag == PAIR)
#define IS_PRIMITIVE(value) (value->tag == PRIMITIVE)
#define IS_PROCEDURE(value) (value->tag == PROCEDURE)

#define HEAD(obj) (obj->pair.head)
#define TAIL(obj) (obj->pair.tail)

#define TUPLE_DATA(obj) (obj->tuple.data)
#define TUPLE_SIZE(obj) (obj->tuple.size)

#define PROC_PARAM(obj) (obj->proc.param)
#define PROC_BODY(obj) (obj->proc.body)
#define PROC_ENV(obj) (obj->proc.env)

#define cherry_string_size(STR) (strlen(STR) + 1)

const byte_t*           cherry_string_dup(const byte_t* str);

struct cherry_value*	cherry_fixnum_from_string(const byte_t* str, int base);
struct cherry_value*	cherry_float_from_string(const byte_t* str);
struct cherry_value*	cherry_char_from_string(const byte_t* str);
struct cherry_value*	cherry_symbol_from_string(const byte_t* str);
struct cherry_value*	cherry_string_from_string(const byte_t* str);

struct cherry_value*    cherry_value_alloc(void);
struct cherry_value*    cherry_symbol(const byte_t* symbol_value);
struct cherry_value* 	cherry_fixnum(fixnum_t value);
struct cherry_value* 	cherry_float(float_t float_value);
struct cherry_value* 	cherry_string(const byte_t* string_value);
struct cherry_value* 	cherry_char(unicode_t char_value);
struct cherry_value*    cherry_primitive(primitive_t fun_value);

struct cherry_value*    cherry_value_dup(struct cherry_value* value);


struct cherry_value*	cherry_list(struct cherry_value* val, ...);
132
struct cherry_value*    cherry_list_cons(struct cherry_value* head, struct cherry_value* tail);
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
183
184
185
186
187
188
struct cherry_value*    cherry_list_reverse(struct cherry_value* value);

struct cherry_value*    cherry_tuple_new(size_t size);

struct cherry_value*	cherry_procedure(struct cherry_environment* env, struct cherry_value* param, struct cherry_value* body);

// ----------------------------------------------------------------------------
// Symboltables and Environment
// ----------------------------------------------------------------------------

struct cherry_symbollist;
struct cherry_exception;

struct cherry_symbollist*	cherry_symbollist(void);
struct cherry_value*		cherry_symbollist_get(struct cherry_symbollist* table, const byte_t* name);

#define EXCEPTION_JUMP(env) env->exception_stack->jump
#define EXCEPTION_DATA(env) env->exception_stack->data

struct cherry_exception {
	jmp_buf jump;
	struct cherry_value* data;
	struct cherry_exception* next;
};


struct cherry_environment {
    struct cherry_exception* exception_stack;
    struct cherry_symbollist* mapping;
};

struct cherry_environment*  cherry_env_push(struct cherry_environment* env);
struct cherry_environment*  cherry_env_pop(struct cherry_environment* env);
struct cherry_value*        cherry_env_lookup(struct cherry_environment* env, struct cherry_value* symbol);
int                         cherry_env_add(struct cherry_environment* env, struct cherry_value* symbol, struct cherry_value* value);


struct cherry_environment* 	cherry_env_push_exception_point(struct cherry_environment* env);
struct cherry_environment* 	cherry_env_pop_exception_point(struct cherry_environment* env);
void						cherry_env_raise(struct cherry_environment* env, struct cherry_value* e);



struct cherry_environment*  cherry_environment(void);

extern struct cherry_symbollist*    cherry_global_symbollist;

extern struct cherry_value*         cherry_emptylist;
extern struct cherry_value*         cherry_true;
extern struct cherry_value*         cherry_false;
extern struct cherry_value*         cherry_dot;
extern struct cherry_value*         cherry_symbol_quote;
extern struct cherry_value*         cherry_symbol_define;
extern struct cherry_value*         cherry_symbol_let;
extern struct cherry_value*         cherry_symbol_lambda;
extern struct cherry_value*         cherry_symbol_if;
189
extern struct cherry_value*         cherry_symbol_loop;
190
191
192
193
194
195
196
197
198
199
200

extern struct cherry_value*         cherry_symbol_begin;
extern struct cherry_value*         cherry_symbol_try;
extern struct cherry_value*         cherry_symbol_catch;

// org.cherry.core
struct cherry_value*    cherry_core_type(struct cherry_environment* env, struct cherry_value* args);
struct cherry_value*    cherry_core_raise(struct cherry_environment* env, struct cherry_value* args);

struct cherry_value*    cherry_core_cons(struct cherry_environment* env, struct cherry_value* args);
struct cherry_value*    cherry_core_list(struct cherry_environment* env, struct cherry_value* args);
201
struct cherry_value*    cherry_core_is_null(struct cherry_environment* env, struct cherry_value* args);
202
203
204
struct cherry_value*    cherry_core_head(struct cherry_environment* env, struct cherry_value* args);
struct cherry_value*    cherry_core_tail(struct cherry_environment* env, struct cherry_value* args);
struct cherry_value*    cherry_core_length(struct cherry_environment* env, struct cherry_value* args);
205
struct cherry_value*    cherry_core_nth(struct cherry_environment* env, struct cherry_value* args);
206

207
208
209
210
211
212
213
struct cherry_value*    cherry_core_map(struct cherry_environment* env, struct cherry_value* args);
struct cherry_value*    cherry_core_list_to_string(struct cherry_environment* env, struct cherry_value* args);
struct cherry_value*    cherry_core_list_to_tuple(struct cherry_environment* env, struct cherry_value* args);

struct cherry_value*    cherry_core_make_list(struct cherry_environment* env, struct cherry_value* args);
struct cherry_value*    cherry_core_make_tuple(struct cherry_environment* env, struct cherry_value* args);

214
struct cherry_value*    cherry_core_string_to_list(struct cherry_environment* env, struct cherry_value* args);
215
struct cherry_value*    cherry_core_string_to_fixnum(struct cherry_environment* env, struct cherry_value* args);
216
struct cherry_value*    cherry_core_string_to_tuple(struct cherry_environment* env, struct cherry_value* args);
217
218
219
220
221
222
223
224

struct cherry_value*    cherry_core_tuple(struct cherry_environment* env, struct cherry_value* args);

struct cherry_value*    cherry_core_add(struct cherry_environment* env, struct cherry_value* args);
struct cherry_value*    cherry_core_sub(struct cherry_environment* env, struct cherry_value* args);
struct cherry_value*    cherry_core_mul(struct cherry_environment* env, struct cherry_value* args);
struct cherry_value*    cherry_core_div(struct cherry_environment* env, struct cherry_value* args);

Chris Müller's avatar
Chris Müller committed
225
226
227
228
229
230
231
232
233
struct cherry_value*    cherry_core_not(struct cherry_environment* env, struct cherry_value* args);
struct cherry_value*    cherry_core_and(struct cherry_environment* env, struct cherry_value* args);
struct cherry_value*    cherry_core_or(struct cherry_environment* env, struct cherry_value* args);
struct cherry_value*    cherry_core_greater(struct cherry_environment* env, struct cherry_value* args);
struct cherry_value*    cherry_core_less(struct cherry_environment* env, struct cherry_value* args);
struct cherry_value*    cherry_core_greater_equal(struct cherry_environment* env, struct cherry_value* args);
struct cherry_value*    cherry_core_less_equal(struct cherry_environment* env, struct cherry_value* args);
struct cherry_value*    cherry_core_equal(struct cherry_environment* env, struct cherry_value* args);

234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
// org.cherry.io
struct cherry_value*    cherry_io_println(struct cherry_environment* env, struct cherry_value* args);

// org.cherry.system
struct cherry_value*    cherry_system_exit(struct cherry_environment* env, struct cherry_value* args);


// ----------------------------------------------------------------------------
// Evaluation
// ----------------------------------------------------------------------------

#define IS_FALSE(obj) (IS_BOOLEAN(obj) && !obj->boolean_value)

#define IS_TRUE(obj) (!IS_FALSE(obj))

#define IS_SELF_EVALUATING(value) \
250
  (IS_BOOLEAN(value) || IS_FIXNUM(value) || IS_CHAR(value) || IS_STRING(value) || IS_FLOAT(value) || IS_PROCEDURE(value))
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274

#define IS_LIST(obj) (IS_PAIR(obj) || IS_NULL(obj))

#define IS_VARIABLE(value) \
  IS_SYMBOL(value)

#define IS_TAGGED(value, symbol) \
  (IS_PAIR(value) && IS_SYMBOL(HEAD(value)) && HEAD(value) == symbol)

#define IS_QUOTE(value) \
  IS_TAGGED(value, cherry_symbol_quote)

#define IS_DEFINE(value) \
  IS_TAGGED(value, cherry_symbol_define)

#define IS_LET(value) \
  IS_TAGGED(value, cherry_symbol_let)

#define IS_IF(value) \
  IS_TAGGED(value, cherry_symbol_if)

#define IS_LAMBDA(value) \
  IS_TAGGED(value, cherry_symbol_lambda)

275
276
277
#define IS_LOOP(value) \
  IS_TAGGED(value, cherry_symbol_loop)

278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
#define IS_BEGIN(value) \
  IS_TAGGED(value, cherry_symbol_begin)

#define IS_TRY(value) \
  IS_TAGGED(value, cherry_symbol_try)

#define IS_CATCH(value) \
  IS_TAGGED(value, cherry_symbol_catch)

#define IS_APPLICATION(value) \
  IS_PAIR(value)

#define TEXT_OF_QUOTATION(value) \
	HEAD(TAIL(value))

struct cherry_value*    cherry_eval(struct cherry_environment* env, struct cherry_value* exp);



// ----------------------------------------------------------------------------
// Print
// ----------------------------------------------------------------------------

void cherry_print(FILE* out, struct cherry_value* value);


// ----------------------------------------------------------------------------
// Default
// ----------------------------------------------------------------------------

void cherry_initialize(struct cherry_value* arguments);

struct cherry_array;

#define DEFAULT 0
#define SUPRESS_COMMENTS 1

struct cherry_context {
  const char* filename;
  const byte_t* begin;  
  const byte_t* src;
  uint32_t line;
  struct cherry_array* buffer;
  flags_t flags;
};


struct cherry_context*   cherry_context(const byte_t* source, const char* filename, flags_t flags);
struct cherry_context*   cherry_context_repl(const byte_t* source);
void                     cherry_context_repl_set_source(struct cherry_context* c, const byte_t* source);

void                     cherry_error(struct cherry_context* context, const char* format, ...);

enum cherry_tok {
  TOK_EOF,
  TOK_ROUNDLEFTBRACE,
  TOK_ROUNDRIGHTBRACE,
  TOK_SQUARELEFTBRACE,
  TOK_SQUARERIGHTBRACE,
  TOK_COMMENT,
  TOK_DOT,
  TOK_STRING,
  TOK_CHAR,
  TOK_HEX,
  TOK_DEC,
  TOK_OCT,
  TOK_BIN,
  TOK_FLOAT,
  TOK_SYMBOL,
  TOK_TRUE,
  TOK_FALSE,
  TOK_QUOTE
};


const byte_t*           cherry_tok_to_string(enum cherry_tok token);

enum cherry_tok     	cherry_lex(struct cherry_context* context);
const byte_t*           cherry_pos(struct cherry_context* context);
void                    cherry_rewind(struct cherry_context* context, const byte_t* pos);

const byte_t*       	cherry_token_string(struct cherry_context* context);
size_t              	cherry_token_length(struct cherry_context* context);

struct cherry_value*    cherry_read(struct cherry_context* context);


struct cherry_array;
struct cherry_ptrarray;

struct cherry_array*    cherry_array_new(size_t init_capacity);

size_t                  cherry_array_size(struct cherry_array* array);
size_t                  cherry_array_capacity(struct cherry_array* array);


size_t                  cherry_array_ensure(struct cherry_array* array, size_t min_capacity);
size_t                  cherry_array_trim(struct cherry_array* array);

void                    cherry_array_append(struct cherry_array* array, const_pointer_t data, size_t size);
int                     cherry_array_insert(struct cherry_array* array, size_t index, const_pointer_t data, size_t size);
int                     cherry_array_remove(struct cherry_array* array, size_t index, size_t size);
int		                cherry_array_replace(struct cherry_array* array, size_t index, const_pointer_t data, size_t size);
void			        cherry_array_clear(struct cherry_array* array);

pointer_t               cherry_array_clone(struct cherry_array* array);
pointer_t               cherry_array_get(struct cherry_array* array, size_t index);



struct cherry_ptrarray* cherry_ptrarray_new(size_t init_capacity);

size_t                  cherry_ptrarray_size(struct cherry_ptrarray* array);
size_t                  cherry_ptrarray_capacity(struct cherry_ptrarray* array);

size_t                  cherry_ptrarray_ensure(struct cherry_ptrarray* array, size_t min_capacity);
size_t                  cherry_ptrarray_trim(struct cherry_ptrarray* array);


void                    cherry_ptrarray_append(struct cherry_ptrarray* array, pointer_t ptr);
int                     cherry_ptrarray_insert(struct cherry_ptrarray* array, size_t index, pointer_t ptr);
pointer_t               cherry_ptrarray_remove(struct cherry_ptrarray* array, size_t index);
pointer_t			    cherry_ptrarray_replace(struct cherry_ptrarray* array, size_t index, pointer_t ptr);
void			        cherry_ptrarray_clear(struct cherry_ptrarray* array);

pointer_t               cherry_ptrarray_get(struct cherry_ptrarray* array, size_t index);

int                     cherry_unicode_isblank(unicode_t ch);
int                     cherry_unicode_isspace(unicode_t ch);
int                     cherry_unicode_isalpha(unicode_t ch);
int                     cherry_unicode_isalnum(unicode_t ch);
int                     cherry_unicode_isdigit(unicode_t ch);
int                     cherry_unicode_ishex(unicode_t ch);
int                     cherry_unicode_isoct(unicode_t ch);
int                     cherry_unicode_isprint(unicode_t ch);
int                     cherry_unicode_isgraph(unicode_t ch);
int                     cherry_unicode_ispunct(unicode_t ch);
int                     cherry_unicode_iscntrl(unicode_t ch);

int 			        cherry_unicode_to_utf8(byte_t* out, unicode_t ch);

int		                cherry_utf8_validate(const byte_t* str);
int		                cherry_utf8_compare(const byte_t* str1, const byte_t* str2);

byte_t*                 cherry_utf8_chr(const byte_t* str, unicode_t character);
byte_t*                 cherry_utf8_rchr(const byte_t* str, unicode_t character);
byte_t*                 cherry_utf8_str(const byte_t* str1, const byte_t* str2);

size_t                  cherry_utf8_size(const byte_t* str);
size_t                  cherry_utf8_len(const byte_t* str);
unicode_t               cherry_utf8_get(const byte_t* str);
size_t                  cherry_utf8_codepoints(const byte_t* str);

byte_t*                 cherry_utf8_next(const byte_t* str);
byte_t*                 cherry_utf8_prev(const byte_t* str);