From aebf7f00f76bd091c7ba603bccc925eac19826bc Mon Sep 17 00:00:00 2001 From: Yuichi Nishiwaki Date: Mon, 4 Nov 2013 22:38:23 -0500 Subject: [PATCH] initial bytevector support --- include/picrin/blob.h | 15 +++++++++++++++ include/picrin/value.h | 2 ++ src/blob.c | 15 +++++++++++++++ src/codegen.c | 3 ++- src/expand.c | 3 ++- src/gc.c | 8 ++++++++ src/parse.y | 11 +++++++++++ src/port.c | 11 +++++++++++ src/scan.l | 25 +++++++++++++++++++++++++ 9 files changed, 91 insertions(+), 2 deletions(-) create mode 100644 include/picrin/blob.h create mode 100644 src/blob.c diff --git a/include/picrin/blob.h b/include/picrin/blob.h new file mode 100644 index 00000000..6c37c2ce --- /dev/null +++ b/include/picrin/blob.h @@ -0,0 +1,15 @@ +#ifndef BLOB_H__ +#define BLOB_H__ + +struct pic_blob { + PIC_OBJECT_HEADER + char *data; + int len; +}; + +#define pic_blob_p(v) (pic_type(v) == PIC_TT_BLOB) +#define pic_blob_ptr(v) ((struct pic_blob *)(v).u.data) + +struct pic_blob *pic_blob_new(pic_state *, char *, int len); + +#endif diff --git a/include/picrin/value.h b/include/picrin/value.h index 93126b13..cdc47a2c 100644 --- a/include/picrin/value.h +++ b/include/picrin/value.h @@ -41,6 +41,7 @@ enum pic_tt { PIC_TT_PAIR, PIC_TT_STRING, PIC_TT_VECTOR, + PIC_TT_BLOB, PIC_TT_PROC, PIC_TT_PORT, PIC_TT_ENV @@ -73,6 +74,7 @@ struct pic_vector { struct pic_proc; struct pic_port; +struct pic_blob; #define pic_obj_ptr(o) ((struct pic_object *)(o).u.data) #define pic_pair_ptr(o) ((struct pic_pair *)(o).u.data) diff --git a/src/blob.c b/src/blob.c new file mode 100644 index 00000000..a6adcc1f --- /dev/null +++ b/src/blob.c @@ -0,0 +1,15 @@ +#include + +#include "picrin.h" +#include "picrin/blob.h" + +struct pic_blob * +pic_blob_new(pic_state *pic, char *dat, int len) +{ + struct pic_blob *bv; + + bv = (struct pic_blob *)pic_obj_alloc(pic, sizeof(struct pic_blob), PIC_TT_BLOB); + bv->data = strndup(dat, len); + bv->len = len; + return bv; +} diff --git a/src/codegen.c b/src/codegen.c index 5e555df5..507fd7da 100644 --- a/src/codegen.c +++ b/src/codegen.c @@ -518,7 +518,8 @@ codegen(codegen_state *state, pic_value obj, bool tailpos) break; } case PIC_TT_STRING: - case PIC_TT_VECTOR: { + case PIC_TT_VECTOR: + case PIC_TT_BLOB: { int pidx; pidx = pic->plen++; pic->pool[pidx] = obj; diff --git a/src/expand.c b/src/expand.c index b0866a5a..91a4e181 100644 --- a/src/expand.c +++ b/src/expand.c @@ -134,7 +134,8 @@ expand(pic_state *pic, pic_value obj, struct syntactic_env *env) case PIC_TT_CHAR: case PIC_TT_EOF: case PIC_TT_STRING: - case PIC_TT_VECTOR: { + case PIC_TT_VECTOR: + case PIC_TT_BLOB: { return obj; } case PIC_TT_PROC: diff --git a/src/gc.c b/src/gc.c index aebd05e2..1d0a3285 100644 --- a/src/gc.c +++ b/src/gc.c @@ -5,6 +5,7 @@ #include "picrin/irep.h" #include "picrin/proc.h" #include "picrin/port.h" +#include "picrin/blob.h" #if GC_DEBUG # include @@ -187,6 +188,9 @@ gc_mark_object(pic_state *pic, struct pic_object *obj) } break; } + case PIC_TT_BLOB: { + break; + } case PIC_TT_NIL: case PIC_TT_BOOL: case PIC_TT_FLOAT: @@ -285,6 +289,10 @@ gc_finalize_object(pic_state *pic, struct pic_object *obj) pic_free(pic, ((struct pic_vector *)obj)->data); break; } + case PIC_TT_BLOB: { + pic_free(pic, ((struct pic_blob *)obj)->data); + break; + } case PIC_TT_STRING: { pic_free(pic, (void*)((struct pic_string *)obj)->str); break; diff --git a/src/parse.y b/src/parse.y index 79f590b8..47f59434 100644 --- a/src/parse.y +++ b/src/parse.y @@ -4,6 +4,7 @@ #include "picrin.h" #include "picrin/pair.h" +#include "picrin/blob.h" #define YYERROR_VERBOSE 1 @@ -35,6 +36,10 @@ void yylex_destroy(); double f; char *cstr; char c; + struct { + char *dat; + int len, capa; + } blob; pic_value datum; } @@ -44,6 +49,7 @@ void yylex_destroy(); %token tFLOAT %token tSYMBOL tSTRING %token tCHAR +%token tBYTEVECTOR %type program_data %type datum simple_datum compound_datum abbrev @@ -111,6 +117,11 @@ simple_datum { $$ = pic_char_value($1); } + | tBYTEVECTOR + { + $$ = pic_obj_value(pic_blob_new(p->pic, $1.dat, $1.len)); + free($1.dat); + } ; compound_datum diff --git a/src/port.c b/src/port.c index 575632a8..7c3c0157 100644 --- a/src/port.c +++ b/src/port.c @@ -4,6 +4,7 @@ #include "picrin.h" #include "picrin/proc.h" #include "picrin/port.h" +#include "picrin/blob.h" static void write_pair(pic_state *pic, struct pic_pair *pair); static void write_str(pic_state *pic, struct pic_string *str); @@ -67,6 +68,16 @@ write(pic_state *pic, pic_value obj) } printf(")"); break; + case PIC_TT_BLOB: + printf("#u8("); + for (i = 0; i < pic_blob_ptr(obj)->len; ++i) { + printf("%d", pic_blob_ptr(obj)->data[i]); + if (i + 1 < pic_blob_ptr(obj)->len) { + printf(" "); + } + } + printf(")"); + break; case PIC_TT_ENV: printf("#", pic_env_ptr(obj)); break; diff --git a/src/scan.l b/src/scan.l index 9dd6ac1e..e326fa9e 100644 --- a/src/scan.l +++ b/src/scan.l @@ -33,6 +33,9 @@ infnan "+inf.0"|"-inf.0"|"+nan.0"|"-nan.0" /* string */ %x STRING + /* bytevector */ +%x BYTEVECTOR + %% [ \t\n\r] /* skip whitespace */ @@ -83,6 +86,28 @@ infnan "+inf.0"|"-inf.0"|"+nan.0"|"-nan.0" return tCHAR; } +"#u8(" { + BEGIN(BYTEVECTOR); + yylvalp->blob.len = 0; + yylvalp->blob.capa = 10; + yylvalp->blob.dat = calloc(10, 1); +} +[ \r\n\t] +{uinteger} { + int i = atoi(yytext); + if (0 > i || i > 255) + REJECT; + yylvalp->blob.dat[yylvalp->blob.len++] = (char)i; + if (yylvalp->blob.len > yylvalp->blob.capa) { + yylvalp->blob.capa *= 2; + yylvalp->blob.dat = realloc(yylvalp->blob.dat, yylvalp->blob.capa); + } +} +")" { + BEGIN(INITIAL); + return tBYTEVECTOR; +} + %% int