#include "common/cs_varint.h"
#include "mjs_internal.h"
#include "mjs_bcode.h"
#include "mjs_core.h"
#include "mjs_tok.h"
static void add_lineno_map_item(struct pstate *pstate) {
if (pstate->last_emitted_line_no < pstate->line_no) {
int offset = pstate->cur_idx - pstate->start_bcode_idx;
size_t offset_llen = cs_varint_llen(offset);
size_t lineno_llen = cs_varint_llen(pstate->line_no);
mbuf_resize(&pstate->offset_lineno_map,
pstate->offset_lineno_map.size + offset_llen + lineno_llen);
cs_varint_encode(offset, (uint8_t *) pstate->offset_lineno_map.buf +
pstate->offset_lineno_map.len,
offset_llen);
pstate->offset_lineno_map.len += offset_llen;
cs_varint_encode(pstate->line_no,
(uint8_t *) pstate->offset_lineno_map.buf +
pstate->offset_lineno_map.len,
lineno_llen);
pstate->offset_lineno_map.len += lineno_llen;
pstate->last_emitted_line_no = pstate->line_no;
}
}
MJS_PRIVATE void emit_byte(struct pstate *pstate, uint8_t byte) {
add_lineno_map_item(pstate);
mbuf_insert(&pstate->mjs->bcode_gen, pstate->cur_idx, &byte, sizeof(byte));
pstate->cur_idx += sizeof(byte);
}
MJS_PRIVATE void emit_int(struct pstate *pstate, int64_t n) {
struct mbuf *b = &pstate->mjs->bcode_gen;
size_t llen = cs_varint_llen(n);
add_lineno_map_item(pstate);
mbuf_insert(b, pstate->cur_idx, NULL, llen);
cs_varint_encode(n, (uint8_t *) b->buf + pstate->cur_idx, llen);
pstate->cur_idx += llen;
}
MJS_PRIVATE void emit_str(struct pstate *pstate, const char *ptr, size_t len) {
struct mbuf *b = &pstate->mjs->bcode_gen;
size_t llen = cs_varint_llen(len);
add_lineno_map_item(pstate);
mbuf_insert(b, pstate->cur_idx, NULL, llen + len);
cs_varint_encode(len, (uint8_t *) b->buf + pstate->cur_idx, llen);
memcpy(b->buf + pstate->cur_idx + llen, ptr, len);
pstate->cur_idx += llen + len;
}
MJS_PRIVATE int mjs_bcode_insert_offset(struct pstate *p, struct mjs *mjs,
size_t offset, size_t v) {
int llen = (int) cs_varint_llen(v);
int diff = llen - MJS_INIT_OFFSET_SIZE;
assert(offset < mjs->bcode_gen.len);
if (diff > 0) {
mbuf_resize(&mjs->bcode_gen, mjs->bcode_gen.size + diff);
}
memmove(mjs->bcode_gen.buf + offset + llen,
mjs->bcode_gen.buf + offset + MJS_INIT_OFFSET_SIZE,
mjs->bcode_gen.len - offset - MJS_INIT_OFFSET_SIZE);
mjs->bcode_gen.len += diff;
cs_varint_encode(v, (uint8_t *) mjs->bcode_gen.buf + offset, llen);
if (p->cur_idx >= (int) offset) {
p->cur_idx += diff;
}
return diff;
}
MJS_PRIVATE void mjs_bcode_part_add(struct mjs *mjs,
const struct mjs_bcode_part *bp) {
mbuf_append(&mjs->bcode_parts, bp, sizeof(*bp));
}
MJS_PRIVATE struct mjs_bcode_part *mjs_bcode_part_get(struct mjs *mjs,
int num) {
assert(num < mjs_bcode_parts_cnt(mjs));
return (struct mjs_bcode_part *) (mjs->bcode_parts.buf +
num * sizeof(struct mjs_bcode_part));
}
MJS_PRIVATE struct mjs_bcode_part *mjs_bcode_part_get_by_offset(struct mjs *mjs,
size_t offset) {
int i;
int parts_cnt = mjs_bcode_parts_cnt(mjs);
struct mjs_bcode_part *bp = NULL;
if (offset >= mjs->bcode_len) {
return NULL;
}
for (i = 0; i < parts_cnt; i++) {
bp = mjs_bcode_part_get(mjs, i);
if (offset < bp->start_idx + bp->data.len) {
break;
}
}
assert(i < parts_cnt);
return bp;
}
MJS_PRIVATE int mjs_bcode_parts_cnt(struct mjs *mjs) {
return mjs->bcode_parts.len / sizeof(struct mjs_bcode_part);
}
MJS_PRIVATE void mjs_bcode_commit(struct mjs *mjs) {
struct mjs_bcode_part bp;
memset(&bp, 0, sizeof(bp));
mbuf_trim(&mjs->bcode_gen);
bp.data.p = mjs->bcode_gen.buf;
bp.data.len = mjs->bcode_gen.len;
mbuf_init(&mjs->bcode_gen, 0);
bp.start_idx = mjs->bcode_len;
bp.exec_res = MJS_ERRS_CNT;
mjs_bcode_part_add(mjs, &bp);
mjs->bcode_len += bp.data.len;
}