static void buffer_close(su_state *s, reader_buffer_t *buffer) { if (buffer->reader) { buffer->reader(NULL, buffer->data); su_allocate(s, buffer->buffer, 0); } su_allocate(s, buffer, 0); }
void lambda(su_state *s, prototype_t *prot, int narg) { unsigned i, tmp; value_t v; function_t *func = su_allocate(s, NULL, sizeof(function_t)); func->narg = narg; func->prot = prot; func->num_const = prot->num_const; func->num_ups = prot->num_ups; func->constants = su_allocate(s, NULL, sizeof(value_t) * prot->num_const); func->upvalues = su_allocate(s, NULL, sizeof(value_t) * prot->num_ups); for (i = 0; i < func->num_const; i++) func->constants[i] = create_value(s, &prot->constants[i]); for (i = 0; i < func->num_ups; i++) { tmp = s->frame_top - prot->upvalues[i].lv; tmp = s->frames[tmp].stack_top + prot->upvalues[i].idx + 1; func->upvalues[i] = s->stack[tmp]; } gc_insert_object(s, (gc_t*)func, SU_FUNCTION); v.type = SU_FUNCTION; v.obj.func = func; push_value(s, &v); }
static void free_object(su_state *s, gc_t *obj) { function_t *func; if (obj->type == SU_FUNCTION) { func = (function_t*)obj; su_allocate(s, func->constants, 0); su_allocate(s, func->upvalues, 0); } else if (obj->type == PROTOTYPE) { free_prot(s, (prototype_t*)obj); } else if (obj->type == SU_LOCAL) { /* Remove from the local registry. */ } su_allocate(s, obj, 0); }
gc_t *string_from_cache(su_state *s, const char *str, unsigned size) { value_t v; string_cache_t entry; string_cache_t *entries; unsigned hash = murmur(str, size, 0); unsigned index = (unsigned)bit_count((int)hash) - 8; int i; if (index < 16) { entries = s->string_cache[index]; for (i = 0; i < STRING_CACHE_SIZE; i++) { if (entries[i].hash == hash && !memcmp(entries[i].str->str, str, size)) return &entries[i].str->gc; } } v.type = SU_STRING; v.obj.ptr = su_allocate(s, NULL, sizeof(string_t) + size); v.obj.str->size = size; memcpy(v.obj.str->str, str, size); v.obj.str->str[size] = '\0'; v.obj.str->hash = hash; if (index < 16) { entry.hash = hash; entry.str = v.obj.str; entries[s->string_cache_head[index]] = entry; s->string_cache_head[index] = (s->string_cache_head[index] + 1) % STRING_CACHE_SIZE; } gc_insert_object(s, v.obj.gc_object, SU_STRING); return v.obj.gc_object; }
static int buffer_read(su_state *s, reader_buffer_t *buffer, void *dest, size_t num_bytes) { unsigned dest_offset = 0; do { const void *res; size_t size = buffer->reader ? (buffer->len - buffer->offset) : num_bytes; size_t num = num_bytes < size ? num_bytes : size; memcpy(((char*)dest) + dest_offset, &buffer->buffer[buffer->offset], num); buffer->offset += num; dest_offset += num; num_bytes -= num; if (!buffer->reader) break; if (num_bytes == 0) return 0; res = buffer->reader(&size, buffer->data); if (!res || size == 0) return -1; while (buffer->size < size) { buffer->size = buffer->size * 2 + 1; buffer->buffer = su_allocate(s, buffer->buffer, buffer->size); } buffer->offset = 0; buffer->len = size; memcpy(buffer->buffer, res, size); } while (num_bytes); return 0; }
void su_string_begin(su_state *s, const char *str) { size_t len = str ? strlen(str) : 0; s->string_builder = (string_t*)su_allocate(s, s->string_builder, sizeof(string_t) + len); s->string_builder->size = (unsigned)len; s->string_builder->hash = 0; if (str) memcpy(s->string_builder->str, str, len); }
char *su_string_mem(su_state *s, unsigned size) { unsigned offset; assert(s->string_builder); offset = s->string_builder->size; s->string_builder->size += size; s->string_builder = (string_t*)su_allocate(s, (void*)s->string_builder, sizeof(string_t) + s->string_builder->size); return s->string_builder->str + offset; }
void *su_newdata(su_state *s, unsigned size, const su_data_class_t *vt) { value_t v; v.type = SU_NATIVEDATA; v.obj.data = (native_data_t*)su_allocate(s, NULL, sizeof(native_data_t) + size - 1); v.obj.data->vt = (su_data_class_t*)vt; gc_insert_object(s, v.obj.gc_object, SU_NATIVEDATA); push_value(s, &v); return (void*)v.obj.data->data; }
static reader_buffer_t *buffer_open(su_state *s, su_reader reader, void *data) { reader_buffer_t *buffer = (reader_buffer_t*)su_allocate(s, NULL, sizeof(reader_buffer_t)); buffer->reader = reader; buffer->data = data; buffer->offset = 0; buffer->size = 0; buffer->len = 0; buffer->buffer = reader ? NULL : data; return buffer; }
int su_clambda(su_state *s, su_nativefunc f) { value_t v; int id = s->msi->num_c_lambdas; su_assert(s, s->main_state == s, MAIN_STATE_ONLY_MSG); s->msi->c_lambdas = (value_t*)su_allocate(s, s->msi->c_lambdas, sizeof(value_t) * (++s->msi->num_c_lambdas)); if (f) { v.type = SU_NATIVEFUNC; v.obj.nfunc = f; s->msi->c_lambdas[id] = v; } else { s->msi->c_lambdas[id] = *STK(-1); s->stack_top--; } return id; }
static const_string_t *read_string(su_state *s, reader_buffer_t *buffer) { const_string_t *str; unsigned size; if (buffer_read(s, buffer, &size, sizeof(unsigned))) return NULL; str = su_allocate(s, NULL, sizeof(unsigned) + size + 1); if (buffer_read(s, buffer, str->str, size)) return NULL; str->size = size; str->str[size] = '\0'; return str; }
int su_load(su_state *s, su_reader reader, void *data) { prototype_t *prot = su_allocate(s, NULL, sizeof(prototype_t)); reader_buffer_t *buffer = buffer_open(s, reader, data); if (verify_header(s, buffer)) { buffer_close(s, buffer); return -1; } if (read_prototype(s, buffer, prot)) { buffer_close(s, buffer); return -1; } buffer_close(s, buffer); gc_insert_object(s, &prot->gc, PROTOTYPE); lambda(s, prot, -1); return 0; }
static void free_prot(su_state *s, prototype_t *prot) { int i; su_allocate(s, prot->inst, 0); su_allocate(s, prot->lineinf, 0); su_allocate(s, prot->upvalues, 0); for (i = 0; i < prot->num_const; i++) { if (prot->constants[i].id == CSTRING) su_allocate(s, prot->constants[i].obj.str, 0); } su_allocate(s, prot->constants, 0); for (i = 0; i < prot->num_prot; i++) free_prot(s, &prot->prot[i]); su_allocate(s, prot->prot, 0); }
int su_compile(su_state *s, const char *code, const char *name, char **inline_c, char **result, size_t *size) { const char *tmp; size_t buffer_size; lua_State *L = lua_open(); su_state *sc = su_init(su_allocator(s)); su_libinit(sc); ___saurus(sc); luaL_openlibs(L); luaopen_writebin(L); if (luaL_loadstring(L, compiler_code)) { *result = dup(s, lua_tostring(L, -1)); if (size) *size = strlen(*result); lua_close(L); su_close(sc); return -1; } if (lua_pcall(L, 0, 0, 0)) { lua_getglobal(L, "saurus_error"); if (lua_isnil(L, -1)) lua_pop(L, 1); *result = dup(s, lua_tostring(L, -1)); if (size) *size = strlen(*result); lua_close(L); su_close(sc); return -2; } lua_getglobal(L, "repl"); lua_pushstring(L, code); lua_pushstring(L, name ? name : "?"); if (lua_pcall(L, 2, 1, 0)) { lua_getglobal(L, "saurus_error"); if (lua_isnil(L, -1)) { lua_pop(L, 1); *result = dup(s, lua_tostring(L, -1)); } else { *result = dup(s, lua_tostring(L, -1)); } if (size) *size = strlen(*result); lua_close(L); su_close(sc); return -3; } tmp = lua_tolstring(L, -1, &buffer_size); *result = (char*)su_allocate(s, NULL, buffer_size); memcpy(*result, tmp, buffer_size); if (size) *size = buffer_size; if (inline_c) { lua_getglobal(L, "c_code"); if (lua_isnil(L, -1)) tmp = lua_tostring(L, -1); *inline_c = (char*)su_allocate(s, NULL, strlen(tmp) + 1); strcpy(*inline_c, tmp); } lua_close(L); su_close(sc); return 0; }
int read_prototype(su_state *s, reader_buffer_t *buffer, prototype_t *prot) { unsigned i; memset(prot, 0, sizeof(prototype_t)); assert(sizeof(unsigned) == 4); assert(sizeof(instruction_t) == 4); READ(&prot->num_inst, sizeof(unsigned)); prot->inst = su_allocate(s, NULL, sizeof(instruction_t) * prot->num_inst); for (i = 0; i < prot->num_inst; i++) READ(&prot->inst[i], sizeof(instruction_t)); READ(&prot->num_const, sizeof(unsigned)); prot->constants = su_allocate(s, NULL, sizeof(const_t) * prot->num_const); for (i = 0; i < prot->num_const; i++) { READ(&prot->constants[i].id, sizeof(char)); switch (prot->constants[i].id) { case CSTRING: prot->constants[i].obj.str = read_string(s, buffer); if (!prot->constants[i].obj.str) goto error; break; case CNUMBER: READ(&prot->constants[i].obj.num, sizeof(double)); break; case CTRUE: case CFALSE: case CNIL: break; default: assert(0); } } READ(&prot->num_ups, sizeof(unsigned)); prot->upvalues = su_allocate(s, NULL, sizeof(upvalue_t) * prot->num_ups); for (i = 0; i < prot->num_ups; i++) READ(&prot->upvalues[i], sizeof(upvalue_t)); READ(&prot->num_prot, sizeof(unsigned)); prot->prot = su_allocate(s, NULL, sizeof(prototype_t) * prot->num_prot); for (i = 0; i < prot->num_prot; i++) { if (read_prototype(s, buffer, &prot->prot[i])) goto error; } prot->name = read_string(s, buffer); if (!prot->name) goto error; READ(&prot->num_lineinf, sizeof(unsigned)); prot->lineinf = su_allocate(s, NULL, sizeof(int) * prot->num_lineinf); for (i = 0; i < prot->num_lineinf; i++) READ(&prot->lineinf[i], sizeof(unsigned)); return 0; error: /* TODO: Deleate the rest of the objects. */ return -1; }
void su_string_ch(su_state *s, char ch) { assert(s->string_builder); s->string_builder = (string_t*)su_allocate(s, (void*)s->string_builder, sizeof(string_t) + (++s->string_builder->size)); s->string_builder->str[s->string_builder->size - 1] = ch; }
static char *dup(su_state *s, const char *str) { char *tmp = (char*)su_allocate(s, NULL, strlen(str) + 1); strcpy(tmp, str); return tmp; }