Looking good
This commit is contained in:
@@ -1,2 +1,2 @@
|
|||||||
all:
|
all:
|
||||||
gcc src/basic.c src/file.c src/parse.c src/assemble.c src/eval.c src/main.c -o wl -Wall -Wextra -O0 -g3
|
gcc src/basic.c src/file.c src/parse.c src/assemble.c src/eval.c src/main.c -o wl -Wall -Wextra -O0 -g3
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
let a = 5
|
|
||||||
let b = 5
|
|
||||||
|
|
||||||
if a == b: print "a and b are the same\n"
|
fun a(name)
|
||||||
else print "they are not the same!\n"
|
<a>My name is \(name)</a>
|
||||||
|
|
||||||
|
a("Francesco")
|
||||||
|
|||||||
@@ -1,46 +0,0 @@
|
|||||||
|
|
||||||
let title = "My Website"
|
|
||||||
|
|
||||||
let posts = [
|
|
||||||
{
|
|
||||||
name: "Post Title 1",
|
|
||||||
date: "1 Jan 2025",
|
|
||||||
comments: [
|
|
||||||
{ author: "User 1", date: "1 Jan 2025", content: "This is a comment" },
|
|
||||||
{ author: "User 2", date: "2 Jan 2025", content: "Second comment" },
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Post Title 2",
|
|
||||||
date: "4 July 2022",
|
|
||||||
comments: [
|
|
||||||
{ author: "User 1", date: "1 Jan 2025", content: "This is a comment" },
|
|
||||||
{ author: "User 2", date: "2 Jan 2025", content: "Second comment" },
|
|
||||||
]
|
|
||||||
},
|
|
||||||
]
|
|
||||||
|
|
||||||
fun render_comment(c)
|
|
||||||
<div class="comment">
|
|
||||||
<a>\c.author (\c.date)</a>
|
|
||||||
<p>\c.content</p>
|
|
||||||
<div class="comment-children">
|
|
||||||
\for child in c.children:
|
|
||||||
render_comment(child)
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<title>\title</title>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<a>This is regular text</a>
|
|
||||||
\for post in posts:
|
|
||||||
<div class="post">
|
|
||||||
<a>\post.title (\post.date)</a>
|
|
||||||
\for comment in post.comments:
|
|
||||||
render_comment(comment)
|
|
||||||
</div>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
|
|||||||
+847
-530
File diff suppressed because it is too large
Load Diff
+10
-2
@@ -6,6 +6,13 @@
|
|||||||
enum {
|
enum {
|
||||||
OPCODE_NOPE = 0x00,
|
OPCODE_NOPE = 0x00,
|
||||||
OPCODE_EXIT = 0x23,
|
OPCODE_EXIT = 0x23,
|
||||||
|
OPCODE_GROUP = 0x25,
|
||||||
|
OPCODE_GPOP = 0x26,
|
||||||
|
OPCODE_GPRINT = 0x27,
|
||||||
|
OPCODE_GTRUNC = 0x28,
|
||||||
|
OPCODE_GCOALESCE = 0x29,
|
||||||
|
OPCODE_GOVERWRITE = 0x2A,
|
||||||
|
OPCODE_GPACK = 0x2B,
|
||||||
OPCODE_PUSHI = 0x01,
|
OPCODE_PUSHI = 0x01,
|
||||||
OPCODE_PUSHF = 0x02,
|
OPCODE_PUSHF = 0x02,
|
||||||
OPCODE_PUSHS = 0x03,
|
OPCODE_PUSHS = 0x03,
|
||||||
@@ -28,7 +35,6 @@ enum {
|
|||||||
OPCODE_JUMP = 0x13,
|
OPCODE_JUMP = 0x13,
|
||||||
OPCODE_JIFP = 0x14,
|
OPCODE_JIFP = 0x14,
|
||||||
OPCODE_CALL = 0x15,
|
OPCODE_CALL = 0x15,
|
||||||
OPCODE_VARS = 0x22,
|
|
||||||
OPCODE_RET = 0x16,
|
OPCODE_RET = 0x16,
|
||||||
OPCODE_APPEND = 0x17,
|
OPCODE_APPEND = 0x17,
|
||||||
OPCODE_INSERT1 = 0x18,
|
OPCODE_INSERT1 = 0x18,
|
||||||
@@ -47,7 +53,9 @@ typedef struct {
|
|||||||
int errlen;
|
int errlen;
|
||||||
} AssembleResult;
|
} AssembleResult;
|
||||||
|
|
||||||
void print_program(Program p);
|
int parse_program_header(Program p, String *code, String *data, char *errbuf, int errmax);
|
||||||
|
void print_program(Program program);
|
||||||
|
char *print_instruction(char *p, char *data);
|
||||||
AssembleResult assemble(Node *root, Arena *arena, char *errbuf, int errmax);
|
AssembleResult assemble(Node *root, Arena *arena, char *errbuf, int errmax);
|
||||||
|
|
||||||
#endif // WL_ASSEMBLE_INCLUDED
|
#endif // WL_ASSEMBLE_INCLUDED
|
||||||
+201
-75
@@ -9,6 +9,7 @@
|
|||||||
|
|
||||||
#define FRAME_LIMIT 128
|
#define FRAME_LIMIT 128
|
||||||
#define EVAL_STACK_LIMIT 128
|
#define EVAL_STACK_LIMIT 128
|
||||||
|
#define GROUP_LIMIT 128
|
||||||
|
|
||||||
#define HEAP_BASE 0xFEEDBEEFFEEDBEEF
|
#define HEAP_BASE 0xFEEDBEEFFEEDBEEF
|
||||||
|
|
||||||
@@ -84,8 +85,8 @@ typedef struct {
|
|||||||
} StringValue;
|
} StringValue;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
int base;
|
int group;
|
||||||
int return_off;
|
int return_addr;
|
||||||
} Frame;
|
} Frame;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
@@ -100,12 +101,15 @@ typedef struct {
|
|||||||
int errmax;
|
int errmax;
|
||||||
int errlen;
|
int errlen;
|
||||||
|
|
||||||
int frame_depth;
|
int num_frames;
|
||||||
Frame frames[FRAME_LIMIT];
|
Frame frames[FRAME_LIMIT];
|
||||||
|
|
||||||
int eval_depth;
|
int eval_depth;
|
||||||
Value eval_stack[EVAL_STACK_LIMIT];
|
Value eval_stack[EVAL_STACK_LIMIT];
|
||||||
|
|
||||||
|
int num_groups;
|
||||||
|
int groups[GROUP_LIMIT];
|
||||||
|
|
||||||
} Eval;
|
} Eval;
|
||||||
|
|
||||||
#define VALUE_NONE ((Value) 0)
|
#define VALUE_NONE ((Value) 0)
|
||||||
@@ -224,7 +228,7 @@ Value make_float(Eval *e, float x)
|
|||||||
return ((Value) v) | 7;
|
return ((Value) v) | 7;
|
||||||
}
|
}
|
||||||
|
|
||||||
Value make_str(Eval *e, String x)
|
Value make_str(Eval *e, String x) // TODO: This should reuse the string contents when possible
|
||||||
{
|
{
|
||||||
StringValue *v = alloc(e->a, (int) sizeof(StringValue) + x.len, 8);
|
StringValue *v = alloc(e->a, (int) sizeof(StringValue) + x.len, 8);
|
||||||
if (v == NULL) {
|
if (v == NULL) {
|
||||||
@@ -276,6 +280,8 @@ b32 valeq(Value a, Value b);
|
|||||||
|
|
||||||
int map_select(Eval *e, Value map, Value key, Value *val)
|
int map_select(Eval *e, Value map, Value key, Value *val)
|
||||||
{
|
{
|
||||||
|
(void) e;
|
||||||
|
|
||||||
MapValue *p = get_map(map);
|
MapValue *p = get_map(map);
|
||||||
MapItems *batch = &p->head;
|
MapItems *batch = &p->head;
|
||||||
while (batch) {
|
while (batch) {
|
||||||
@@ -319,8 +325,37 @@ int map_insert(Eval *e, Value map, Value key, Value val)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
Value *array_select(Eval *e, Value array, uint32_t key)
|
void value_print(Value v);
|
||||||
|
|
||||||
|
void map_print(Value v)
|
||||||
{
|
{
|
||||||
|
printf("{ ");
|
||||||
|
|
||||||
|
MapValue *p = get_map(v);
|
||||||
|
MapItems *batch = &p->head;
|
||||||
|
while (batch) {
|
||||||
|
|
||||||
|
int num = ITEMS_PER_MAP_BATCH;
|
||||||
|
if (batch->next == NULL)
|
||||||
|
num = p->tail_count;
|
||||||
|
|
||||||
|
for (int i = 0; i < num; i++) {
|
||||||
|
value_print(batch->keys[i]);
|
||||||
|
printf(": ");
|
||||||
|
value_print(batch->items[i]);
|
||||||
|
printf(", ");
|
||||||
|
}
|
||||||
|
|
||||||
|
batch = batch->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("}");
|
||||||
|
}
|
||||||
|
|
||||||
|
Value *array_select(Eval *e, Value array, int key)
|
||||||
|
{
|
||||||
|
(void) e;
|
||||||
|
|
||||||
ArrayValue *p = get_array(array);
|
ArrayValue *p = get_array(array);
|
||||||
ArrayItems *batch = &p->head;
|
ArrayItems *batch = &p->head;
|
||||||
int cursor = 0;
|
int cursor = 0;
|
||||||
@@ -362,6 +397,25 @@ int array_append(Eval *e, Value array, Value val)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void array_print(Value v)
|
||||||
|
{
|
||||||
|
ArrayValue *p = get_array(v);
|
||||||
|
ArrayItems *batch = &p->head;
|
||||||
|
int cursor = 0;
|
||||||
|
while (batch) {
|
||||||
|
|
||||||
|
int num = ITEMS_PER_MAP_BATCH;
|
||||||
|
if (batch->next == NULL)
|
||||||
|
num = p->tail_count;
|
||||||
|
|
||||||
|
for (int i = 0; i < num; i++)
|
||||||
|
value_print(batch->items[i]);
|
||||||
|
|
||||||
|
batch = batch->next;
|
||||||
|
cursor += num;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
b32 valeq(Value a, Value b)
|
b32 valeq(Value a, Value b)
|
||||||
{
|
{
|
||||||
Type t1 = type_of(a);
|
Type t1 = type_of(a);
|
||||||
@@ -438,9 +492,58 @@ b32 valgrt(Value a, Value b)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void value_print(Value v)
|
||||||
|
{
|
||||||
|
switch (type_of(v)) {
|
||||||
|
|
||||||
|
case TYPE_NONE:
|
||||||
|
printf("none");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TYPE_BOOL:
|
||||||
|
printf(v == VALUE_TRUE ? "true" : "false");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TYPE_INT:
|
||||||
|
printf("%" LLD, get_int(v));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TYPE_FLOAT:
|
||||||
|
printf("%lf", get_float(v));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TYPE_MAP:
|
||||||
|
map_print(v);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TYPE_ARRAY:
|
||||||
|
array_print(v);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TYPE_STRING:
|
||||||
|
{
|
||||||
|
String s = get_str(v);
|
||||||
|
printf("%.*s", s.len, s.ptr);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TYPE_ERROR:
|
||||||
|
printf("error");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
fflush(stdout);
|
||||||
|
}
|
||||||
|
|
||||||
int step(Eval *e)
|
int step(Eval *e)
|
||||||
{
|
{
|
||||||
uint8_t opcode = e->code.ptr[e->off++];
|
uint8_t opcode = e->code.ptr[e->off];
|
||||||
|
/*
|
||||||
|
printf("%-3d: ", e->off);
|
||||||
|
print_instruction(e->code.ptr + e->off, e->data.ptr);
|
||||||
|
printf("\n");
|
||||||
|
*/
|
||||||
|
e->off++;
|
||||||
|
|
||||||
switch (opcode) {
|
switch (opcode) {
|
||||||
|
|
||||||
case OPCODE_NOPE:
|
case OPCODE_NOPE:
|
||||||
@@ -455,6 +558,77 @@ int step(Eval *e)
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case OPCODE_GROUP:
|
||||||
|
{
|
||||||
|
e->groups[e->num_groups++] = e->eval_depth;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case OPCODE_GPOP:
|
||||||
|
{
|
||||||
|
int group = e->groups[--e->num_groups];
|
||||||
|
e->eval_depth = group;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case OPCODE_GPRINT:
|
||||||
|
{
|
||||||
|
for (int i = e->groups[e->num_groups-1]; i < e->eval_depth; i++)
|
||||||
|
value_print(e->eval_stack[i]);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case OPCODE_GCOALESCE:
|
||||||
|
{
|
||||||
|
e->num_groups--;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case OPCODE_GTRUNC:
|
||||||
|
{
|
||||||
|
uint32_t num;
|
||||||
|
memcpy(&num, (uint8_t*) e->code.ptr + e->off, sizeof(uint32_t));
|
||||||
|
e->off += (int) sizeof(uint32_t);
|
||||||
|
|
||||||
|
int group_size = e->eval_depth - e->groups[e->num_groups-1];
|
||||||
|
|
||||||
|
if (group_size < (int) num) {
|
||||||
|
for (int i = 0; i < (int) num - group_size; i++)
|
||||||
|
e->eval_stack[e->eval_depth + i] = VALUE_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
e->eval_depth = e->groups[e->num_groups-1] + num;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case OPCODE_GOVERWRITE:
|
||||||
|
{
|
||||||
|
int current = e->groups[e->num_groups-1];
|
||||||
|
int parent = e->groups[e->num_groups-2];
|
||||||
|
|
||||||
|
int current_size = e->eval_depth - current;
|
||||||
|
|
||||||
|
for (int i = 0; i < current_size; i++)
|
||||||
|
e->eval_stack[parent + i] = e->eval_stack[current + i];
|
||||||
|
|
||||||
|
e->num_groups--;
|
||||||
|
e->eval_depth = parent + current_size;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case OPCODE_GPACK:
|
||||||
|
{
|
||||||
|
Value array = make_array(e);
|
||||||
|
if (array == VALUE_ERROR)
|
||||||
|
return -1;
|
||||||
|
for (int i = e->groups[e->num_groups-1]; i < e->eval_depth; i++)
|
||||||
|
array_append(e, array, e->eval_stack[i]);
|
||||||
|
|
||||||
|
e->eval_depth = e->groups[--e->num_groups];
|
||||||
|
e->eval_stack[e->eval_depth++] = array;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
case OPCODE_PUSHN:
|
case OPCODE_PUSHN:
|
||||||
{
|
{
|
||||||
e->eval_stack[e->eval_depth++] = VALUE_NONE;
|
e->eval_stack[e->eval_depth++] = VALUE_NONE;
|
||||||
@@ -510,7 +684,10 @@ int step(Eval *e)
|
|||||||
memcpy(&idx, (uint8_t*) e->code.ptr + e->off, sizeof(uint8_t));
|
memcpy(&idx, (uint8_t*) e->code.ptr + e->off, sizeof(uint8_t));
|
||||||
e->off += sizeof(uint8_t);
|
e->off += sizeof(uint8_t);
|
||||||
|
|
||||||
e->eval_stack[e->eval_depth++] = e->eval_stack[e->frames[e->frame_depth-1].base + idx];
|
int group = e->frames[e->num_frames-1].group;
|
||||||
|
Value v = e->eval_stack[e->groups[group] + idx];
|
||||||
|
|
||||||
|
e->eval_stack[e->eval_depth++] = v;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -542,6 +719,7 @@ int step(Eval *e)
|
|||||||
|
|
||||||
case OPCODE_POP:
|
case OPCODE_POP:
|
||||||
{
|
{
|
||||||
|
assert(e->num_groups == 0 || e->eval_depth > e->groups[e->num_groups-1]);
|
||||||
e->eval_depth--;
|
e->eval_depth--;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -889,8 +1067,8 @@ int step(Eval *e)
|
|||||||
memcpy(&x, (uint8_t*) e->code.ptr + e->off, (int) sizeof(x));
|
memcpy(&x, (uint8_t*) e->code.ptr + e->off, (int) sizeof(x));
|
||||||
e->off += (int) sizeof(x);
|
e->off += (int) sizeof(x);
|
||||||
|
|
||||||
Frame *f = &e->frames[e->frame_depth-1];
|
Frame *f = &e->frames[e->num_frames-1];
|
||||||
e->eval_stack[f->base + x] = e->eval_stack[--e->eval_depth];
|
e->eval_stack[e->groups[f->group] + x] = e->eval_stack[--e->eval_depth];
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -923,50 +1101,23 @@ int step(Eval *e)
|
|||||||
|
|
||||||
case OPCODE_CALL:
|
case OPCODE_CALL:
|
||||||
{
|
{
|
||||||
uint8_t num;
|
|
||||||
memcpy(&num, (uint8_t*) e->code.ptr + e->off, sizeof(uint8_t));
|
|
||||||
e->off += (int) sizeof(uint8_t);
|
|
||||||
|
|
||||||
uint32_t off;
|
uint32_t off;
|
||||||
memcpy(&off, (uint8_t*) e->code.ptr + e->off, sizeof(uint32_t));
|
memcpy(&off, (uint8_t*) e->code.ptr + e->off, sizeof(uint32_t));
|
||||||
e->off += (int) sizeof(uint32_t);
|
e->off += (int) sizeof(uint32_t);
|
||||||
|
|
||||||
// Push a dummy value for the return value
|
if (e->num_frames == FRAME_LIMIT) {
|
||||||
e->eval_stack[e->eval_depth++] = VALUE_NONE;
|
|
||||||
|
|
||||||
if (e->frame_depth == FRAME_LIMIT) {
|
|
||||||
eval_report(e, "Frame limit reached");
|
eval_report(e, "Frame limit reached");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
Frame *f = &e->frames[e->frame_depth++];
|
e->frames[e->num_frames++] = (Frame) {.return_addr=e->off, .group=e->num_groups-1};
|
||||||
f->base = e->eval_depth;
|
|
||||||
f->return_off = e->off;
|
|
||||||
|
|
||||||
e->off = off;
|
e->off = off;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case OPCODE_VARS:
|
|
||||||
{
|
|
||||||
uint32_t num;
|
|
||||||
memcpy(&num, e->code.ptr + e->off, sizeof(uint32_t));
|
|
||||||
e->off += sizeof(uint32_t);
|
|
||||||
|
|
||||||
e->eval_depth += num;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case OPCODE_RET:
|
case OPCODE_RET:
|
||||||
{
|
{
|
||||||
Frame *f = &e->frames[--e->frame_depth];
|
e->off = e->frames[--e->num_frames].return_addr;
|
||||||
|
|
||||||
assert(e->eval_depth > f->base);
|
|
||||||
Value r = e->eval_stack[--e->eval_depth];
|
|
||||||
|
|
||||||
e->off = f->return_off;
|
|
||||||
e->eval_depth = f->base;
|
|
||||||
|
|
||||||
e->eval_stack[e->eval_depth-1] = r;
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -1076,18 +1227,7 @@ int step(Eval *e)
|
|||||||
case OPCODE_PRINT:
|
case OPCODE_PRINT:
|
||||||
{
|
{
|
||||||
Value v = e->eval_stack[e->eval_depth-1];
|
Value v = e->eval_stack[e->eval_depth-1];
|
||||||
|
value_print(v);
|
||||||
switch (type_of(v)) {
|
|
||||||
case TYPE_NONE : printf("none"); break;
|
|
||||||
case TYPE_BOOL : printf(v == VALUE_TRUE ? "true" : "false"); break;
|
|
||||||
case TYPE_INT : printf("%" LLD, get_int(v)); break;
|
|
||||||
case TYPE_FLOAT : printf("%lf", get_float(v)); break;
|
|
||||||
case TYPE_MAP : printf("map"); break;
|
|
||||||
case TYPE_ARRAY : printf("array"); break;
|
|
||||||
case TYPE_STRING: printf("%.*s", get_str(v).len, get_str(v).ptr); break;
|
|
||||||
case TYPE_ERROR : printf("error"); break;
|
|
||||||
}
|
|
||||||
fflush(stdout);
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -1101,42 +1241,27 @@ int step(Eval *e)
|
|||||||
|
|
||||||
int eval(Program p, Arena *a, char *errbuf, int errmax)
|
int eval(Program p, Arena *a, char *errbuf, int errmax)
|
||||||
{
|
{
|
||||||
if (p.len < 3 * sizeof(uint32_t)) {
|
String code;
|
||||||
snprintf(errbuf, errmax, "Invalid program");
|
String data;
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
uint32_t magic;
|
|
||||||
uint32_t code_size;
|
|
||||||
uint32_t data_size;
|
|
||||||
memcpy(&magic, p.ptr + 0, sizeof(uint32_t));
|
|
||||||
memcpy(&code_size, p.ptr + 4, sizeof(uint32_t));
|
|
||||||
memcpy(&data_size, p.ptr + 8, sizeof(uint32_t));
|
|
||||||
|
|
||||||
if (magic != 0xFEEDBEEF) {
|
int ret = parse_program_header(p, &code, &data, errbuf, errmax);
|
||||||
snprintf(errbuf, errmax, "Invalid program");
|
if (ret < 0)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
|
||||||
|
|
||||||
if (code_size + data_size + 3 * sizeof(uint32_t) != p.len) {
|
|
||||||
snprintf(errbuf, errmax, "Invalid program");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
Eval e = {
|
Eval e = {
|
||||||
.code = { p.ptr + 3 * sizeof(uint32_t), code_size },
|
.code=code,
|
||||||
.data = { p.ptr + 3 * sizeof(uint32_t) + code_size, data_size },
|
.data=data,
|
||||||
.off=0,
|
.off=0,
|
||||||
.a=a,
|
.a=a,
|
||||||
.errbuf=errbuf,
|
.errbuf=errbuf,
|
||||||
.errmax=errmax,
|
.errmax=errmax,
|
||||||
.errlen=0,
|
.errlen=0,
|
||||||
.frame_depth=0,
|
.num_frames=0,
|
||||||
.eval_depth=0,
|
.eval_depth=0,
|
||||||
|
.num_groups=0,
|
||||||
};
|
};
|
||||||
|
|
||||||
Frame *f = &e.frames[e.frame_depth++];
|
e.frames[e.num_frames++] = (Frame) { 0, 0 };
|
||||||
f->base = 0;
|
|
||||||
f->return_off = 0;
|
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
int ret = step(&e);
|
int ret = step(&e);
|
||||||
@@ -1144,5 +1269,6 @@ int eval(Program p, Arena *a, char *errbuf, int errmax)
|
|||||||
if (ret == 1) break;
|
if (ret == 1) break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
e.num_frames--;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
+3
-3
@@ -25,8 +25,8 @@ int main(void)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
//print_node(parse_result.node);
|
print_node(parse_result.node);
|
||||||
//printf("\n");
|
printf("\n");
|
||||||
|
|
||||||
AssembleResult assemble_result = assemble(parse_result.node, &a, err, COUNT(err));
|
AssembleResult assemble_result = assemble(parse_result.node, &a, err, COUNT(err));
|
||||||
if (assemble_result.errlen) {
|
if (assemble_result.errlen) {
|
||||||
@@ -34,7 +34,7 @@ int main(void)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
//print_program(assemble_result.program);
|
print_program(assemble_result.program);
|
||||||
|
|
||||||
ret = eval(assemble_result.program, &a, err, COUNT(err));
|
ret = eval(assemble_result.program, &a, err, COUNT(err));
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
|
|||||||
+57
-8
@@ -203,8 +203,19 @@ Node *alloc_node(Parser *p)
|
|||||||
|
|
||||||
Token next_token(Parser *p)
|
Token next_token(Parser *p)
|
||||||
{
|
{
|
||||||
while (p->s.cur < p->s.len && is_space(p->s.src[p->s.cur]))
|
for (;;) {
|
||||||
p->s.cur++;
|
while (p->s.cur < p->s.len && is_space(p->s.src[p->s.cur]))
|
||||||
|
p->s.cur++;
|
||||||
|
|
||||||
|
if (!consume_str(&p->s, S("<!--")))
|
||||||
|
break;
|
||||||
|
|
||||||
|
while (p->s.cur < p->s.len) {
|
||||||
|
if (consume_str(&p->s, S("-->")))
|
||||||
|
break;
|
||||||
|
p->s.cur++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (p->s.cur == p->s.len)
|
if (p->s.cur == p->s.len)
|
||||||
return (Token) { .type=TOKEN_END };
|
return (Token) { .type=TOKEN_END };
|
||||||
@@ -406,6 +417,7 @@ Token next_token_or_newline(Parser *p)
|
|||||||
enum {
|
enum {
|
||||||
IGNORE_GRT = 1 << 0,
|
IGNORE_GRT = 1 << 0,
|
||||||
IGNORE_LSS = 1 << 1,
|
IGNORE_LSS = 1 << 1,
|
||||||
|
IGNORE_DIV = 1 << 2,
|
||||||
};
|
};
|
||||||
|
|
||||||
Node *parse_stmt(Parser *p, int opflags);
|
Node *parse_stmt(Parser *p, int opflags);
|
||||||
@@ -429,6 +441,7 @@ Node *parse_html(Parser *p)
|
|||||||
Node *param_head;
|
Node *param_head;
|
||||||
Node **param_tail = ¶m_head;
|
Node **param_tail = ¶m_head;
|
||||||
|
|
||||||
|
b32 no_body = false;
|
||||||
for (;;) {
|
for (;;) {
|
||||||
|
|
||||||
int param_offset = p->s.cur;
|
int param_offset = p->s.cur;
|
||||||
@@ -437,8 +450,20 @@ Node *parse_html(Parser *p)
|
|||||||
Node *attr_value;
|
Node *attr_value;
|
||||||
|
|
||||||
t = next_token(p);
|
t = next_token(p);
|
||||||
|
|
||||||
if (t.type == TOKEN_OPER_GRT)
|
if (t.type == TOKEN_OPER_GRT)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
if (t.type == TOKEN_OPER_DIV) {
|
||||||
|
t = next_token(p);
|
||||||
|
if (t.type != TOKEN_OPER_GRT) {
|
||||||
|
parser_report(p, "Invalid token '/' inside an HTML tag");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
no_body = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
if (t.type != TOKEN_IDENT) {
|
if (t.type != TOKEN_IDENT) {
|
||||||
parser_report(p, "Invalid token inside HTML tag");
|
parser_report(p, "Invalid token inside HTML tag");
|
||||||
return NULL;
|
return NULL;
|
||||||
@@ -449,7 +474,7 @@ Node *parse_html(Parser *p)
|
|||||||
t = next_token(p);
|
t = next_token(p);
|
||||||
if (t.type == TOKEN_OPER_ASS) {
|
if (t.type == TOKEN_OPER_ASS) {
|
||||||
|
|
||||||
attr_value = parse_expr(p, IGNORE_GRT);
|
attr_value = parse_expr(p, IGNORE_GRT | IGNORE_DIV);
|
||||||
if (attr_value == NULL)
|
if (attr_value == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
@@ -476,13 +501,26 @@ Node *parse_html(Parser *p)
|
|||||||
Node *head;
|
Node *head;
|
||||||
Node **tail = &head;
|
Node **tail = &head;
|
||||||
|
|
||||||
for (;;) {
|
if (!no_body) for (;;) {
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
|
|
||||||
int off = p->s.cur;
|
int off = p->s.cur;
|
||||||
while (p->s.cur < p->s.len && p->s.src[p->s.cur] != '<' && p->s.src[p->s.cur] != '\\')
|
|
||||||
p->s.cur++;
|
for (;;) {
|
||||||
|
|
||||||
|
while (p->s.cur < p->s.len && p->s.src[p->s.cur] != '<' && p->s.src[p->s.cur] != '\\')
|
||||||
|
p->s.cur++;
|
||||||
|
|
||||||
|
if (!consume_str(&p->s, S("<!--")))
|
||||||
|
break;
|
||||||
|
|
||||||
|
while (p->s.cur < p->s.len) {
|
||||||
|
if (consume_str(&p->s, S("-->")))
|
||||||
|
break;
|
||||||
|
p->s.cur++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (p->s.cur > off) {
|
if (p->s.cur > off) {
|
||||||
|
|
||||||
@@ -715,9 +753,13 @@ int precedence(Token t, int flags)
|
|||||||
return 3;
|
return 3;
|
||||||
|
|
||||||
case TOKEN_OPER_MUL:
|
case TOKEN_OPER_MUL:
|
||||||
case TOKEN_OPER_DIV:
|
|
||||||
case TOKEN_OPER_MOD:
|
case TOKEN_OPER_MOD:
|
||||||
return 3;
|
return 4;
|
||||||
|
|
||||||
|
case TOKEN_OPER_DIV:
|
||||||
|
if (flags & IGNORE_DIV)
|
||||||
|
return -1;
|
||||||
|
return 4;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
@@ -1481,6 +1523,13 @@ void print_node(Node *node)
|
|||||||
{
|
{
|
||||||
switch (node->type) {
|
switch (node->type) {
|
||||||
|
|
||||||
|
case NODE_PRINT:
|
||||||
|
{
|
||||||
|
printf("print ");
|
||||||
|
print_node(node->left);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
case NODE_BLOCK:
|
case NODE_BLOCK:
|
||||||
{
|
{
|
||||||
printf("{");
|
printf("{");
|
||||||
|
|||||||
Reference in New Issue
Block a user