diff --git a/buffer.h b/buffer.h new file mode 100644 index 0000000..dc4b7f7 --- /dev/null +++ b/buffer.h @@ -0,0 +1,128 @@ +#ifndef __buffer_h +#define __buffer_h + +#include +#include +#include +#include + +#define BUFFER_INITIALISER { 0, 0, 0 } + +#define DECLARE_BUFFER(TYPE, NAME) \ + \ +typedef struct \ +{ \ + TYPE *contents; \ + size_t position; \ + size_t capacity; \ +} NAME; \ + \ +extern inline NAME *new##NAME(NAME *b) \ +{ \ + return calloc(1, sizeof(NAME)); \ +} \ + \ +extern inline NAME *NAME##_release(NAME *b) \ +{ \ + if (b->contents) free(b->contents); \ + memset(b, 0, sizeof(NAME)); \ + return b; \ +} \ + \ +extern inline void NAME##_delete(NAME *b) \ +{ \ + NAME##_release(b); \ + free(b); \ +} \ + \ +extern inline void NAME##_clear(NAME *b) \ +{ \ + b->position= 0; \ +} \ + \ +extern inline size_t NAME##_position(NAME *b) \ +{ \ + return b->position; \ +} \ + \ +extern inline void NAME##_errorBounds(NAME *b, ssize_t index) \ +{ \ + fprintf(stderr, "index %zi out of bounds for "#NAME" of size %zi\n", index, b->capacity); \ + abort(); \ +} \ + \ +extern inline void NAME##_errorMemory(NAME *b) \ +{ \ + fprintf(stderr, "out of memory typing to grow "#NAME" of size %zi\n", b->capacity); \ + abort(); \ +} \ + \ +extern inline TYPE NAME##_get(NAME *b, ssize_t index) \ +{ \ + if (index >= 0) { \ + if (index < b->position) return b->contents[index]; \ + } \ + else { \ + if (b->position + index >= 0) return b->contents[b->position + index]; \ + } \ + NAME##_errorBounds(b, index); \ + abort(); \ + /* NOTREACHED */ \ +} \ + \ +extern inline NAME *NAME##_grow(NAME *b, size_t size) \ +{ \ + if (0 == size) size= 2; \ + if (b->capacity < size) { \ + b->contents= b->contents \ + ? realloc(b->contents, sizeof(TYPE) * size) \ + : malloc ( sizeof(TYPE) * size); \ + if (!b->contents) NAME##_errorMemory(b); \ + memset(b->contents + b->capacity, 0, sizeof(TYPE) * (size - b->capacity)); \ + b->capacity= size; \ + } \ + return b; \ +} \ + \ +extern inline TYPE NAME##_append(NAME *b, TYPE value) \ +{ \ + if (b->position == b->capacity) NAME##_grow(b, b->capacity * 2); \ + return b->contents[b->position++]= value; \ +} \ + \ +extern inline void NAME##_appendAll(NAME *b, const TYPE *s, size_t len) \ +{ \ + while (len--) NAME##_append(b, *s++); \ +} \ + \ +extern inline TYPE *NAME##_buffer(NAME *b) \ +{ \ + return b->contents; \ +} + +#define DECLARE_STRING_BUFFER(TYPE, NAME) \ + \ +DECLARE_BUFFER(TYPE, NAME); \ + \ +extern inline TYPE *NAME##_appendString(NAME *b, TYPE *string) \ +{ \ + for (TYPE *ptr= string; *ptr; ++ptr) NAME##_append(b, *string++); \ + return string; \ +} \ + \ +extern inline TYPE *NAME##_contents(NAME *b) \ +{ \ + NAME##_append(b, 0); \ + b->position--; \ + return b->contents; \ +} + +#define buffer_do(T, V, B) \ + for ( size_t index_of_##V= 0; \ + index_of_##V < (B)->position; \ + index_of_##V = (B)->position ) \ + for ( T V; \ + index_of_##V < (B)->position && (V= (B)->contents[index_of_##V], 1); \ + ++index_of_##V ) + +#endif // __buffer_h diff --git a/object.c b/object.c index 28ec8ea..c70adc0 100644 --- a/object.c +++ b/object.c @@ -87,7 +87,6 @@ struct Symbol { typedef oop (*primitive_t)(oop params); - struct Function { type_t type; primitive_t primitive; @@ -173,9 +172,12 @@ void *memcheck(void *ptr) return ptr; } +#include "buffer.h" +DECLARE_STRING_BUFFER(char, StringBuffer); + void print(oop ast); void println(oop ast); - +void printOn(StringBuffer *buf, oop obj); int getInteger(oop obj) { @@ -456,106 +458,95 @@ oop map_values(oop map) return values; } -void map_print(oop map, int ident) +void map_printOn(StringBuffer *buf, oop map, int ident) { assert(is(Map, map)); if (ident == 0) { - printf("{"); - map_print(map, ident + 1); - printf("}"); + StringBuffer_append(buf, '{'); + map_printOn(buf, map, ident + 1); + StringBuffer_append(buf, '}'); return; } for (size_t i = 0; i < map_size(map); i++) { - printf("\n"); + StringBuffer_append(buf, '\n'); for (size_t i = 0; i < ident; i++) { - printf("|"); - printf(" "); + if (isatty(fileno(stdout))) { + StringBuffer_appendString(buf, "\033[90m|\033[0m"); + } else { + StringBuffer_appendString(buf, "|"); + } + StringBuffer_appendString(buf, " "); } // todo: a key could be a map itself - print(get(map, Map, elements)[i].key); - printf(": "); + printOn(buf, get(map, Map, elements)[i].key); + StringBuffer_appendString(buf, ": "); oop rhs = get(map, Map, elements)[i].value; if (getType(rhs) == Map) { - map_print(rhs, ident + 1); + map_printOn(buf, rhs, ident + 1); } else { - print(rhs); + printOn(buf, rhs); } - if (i < map_size(map) - 1) printf(","); - if (ident == 1 && i == map_size(map) - 1) printf("\n"); + if (i < map_size(map) - 1) StringBuffer_append(buf, ','); + if (ident == 1 && i == map_size(map) - 1) StringBuffer_append(buf, '\n'); } - return; -} - - -char *toString(oop ast) -{ - int length; - assert(ast); - switch (getType(ast)) { - case Undefined: - return "null"; - case Integer: - //TODO - length = snprintf(NULL, 0, "%d", getInteger(ast)); - printf("length is %i\n", length); - printf("%i", getInteger(ast)); - return "null"; - case String: - return get(ast, String, value); - case Symbol: - return get(ast, Symbol, name); - case Function: - // TODO - if (get(ast, Function, primitive) == NULL) { - printf("Function:"); - } else { - printf("Primitive:"); - } - print(get(ast, Function, name)); - printf("("); - print(get(ast, Function, param)); - printf(")"); - case Map: - // TODO - map_print(ast, 0); - } - assert(0); } -void print(oop ast) +void printOn(StringBuffer *buf, oop obj) { - assert(ast); - switch (getType(ast)) { - case Undefined: - printf("null"); - return; - case Integer: - printf("%i", getInteger(ast)); - return; - case String: - printf("%s", get(ast, String, value)); - return; - case Symbol: - printf("%s", get(ast, Symbol, name)); - return; - case Function: - if (get(ast, Function, primitive) == NULL) { - printf("Function:"); - } else { - printf("Primitive:"); + assert(obj); + switch (getType(obj)) { + case Undefined: { + StringBuffer_appendString(buf, "null"); + return; + } + case Integer: { + char tmp[32]; + int length = snprintf(tmp, sizeof(tmp), "%i", getInteger(obj)); + StringBuffer_appendAll(buf, tmp, length); + return; + } + case String: { + StringBuffer_appendAll(buf, get(obj, String, value), string_size(obj)); + return; + } + case Symbol: { + char *name= get(obj, Symbol, name); + StringBuffer_appendString(buf, name); + return; + } + case Function: { + if (get(obj, Function, primitive) == NULL) { + StringBuffer_appendString(buf, "Function:"); + } else { + StringBuffer_appendString(buf, "Primitive:"); + } + printOn(buf, get(obj, Function, name)); + StringBuffer_append(buf, '('); + printOn(buf, get(obj, Function, param)); + StringBuffer_append(buf, ')'); + return; + } + case Map: { + map_printOn(buf, obj, 0); + return; } - print(get(ast, Function, name)); - printf("("); - print(get(ast, Function, param)); - printf(")"); - return; - case Map: - map_print(ast, 0); - return; } assert(0); } +char *printString(oop obj) +{ + static StringBuffer buf= BUFFER_INITIALISER; + StringBuffer_clear(&buf); + printOn(&buf, obj); + return StringBuffer_contents(&buf); +} + +void print(oop obj) +{ + fputs(printString(obj), stdout); +} + void println(oop ast) { print(ast); diff --git a/parse.leg b/parse.leg index 22d1980..a423b73 100644 --- a/parse.leg +++ b/parse.leg @@ -86,7 +86,7 @@ DO_PROTOS() #undef _DO int opt_v= 0; -oop mrAST= null; +oop mrAST= &_null; typedef struct input_t { @@ -1852,18 +1852,22 @@ oop evalArgs(oop scope, oop args) oop AST= NULL; -void readEvalPrint(char *fileName) { +void readEvalPrint(char *fileName) +{ inputStackPush(fileName); + input_t *top= inputStack; jbRecPush(); jb_record *jtop= jbs; int jbt= sigsetjmp(jbs->jb, 0); if (0 == jbt) { - while (inputStack && yyparse()) { + while (yyparse()) { if (opt_v > 1) printf("%s:%i: ", get(inputStack->name, String, value), inputStack->lineNumber); if (!yylval) { fclose(inputStack->file); + if (top == inputStack) break; inputStackPop(); + assert(inputStack); continue; } // EOF if (opt_v > 1) println(yylval); @@ -1871,6 +1875,8 @@ void readEvalPrint(char *fileName) { if (opt_v > 0) println(res); assert(jbs == jtop); } + assert(inputStack); + inputStackPop(); jbRecPop(); return; } diff --git a/test3.txt b/test3.txt new file mode 100644 index 0000000..6332136 --- /dev/null +++ b/test3.txt @@ -0,0 +1,3 @@ +println(666) +import "test-proto.txt" +println(12) \ No newline at end of file