diff --git a/main.wl b/main.wl
index 1f5e905..5d360c1 100644
--- a/main.wl
+++ b/main.wl
@@ -1,6 +1,4 @@
-func(1, 3, 5);
-
title = "My Website";
posts = [
@@ -27,22 +25,21 @@ fun render_comment(c)
$c.author; ($c.date;)
$post.title; ($post.date;)
- $for comment in post.comments: {
+ $ for comment in post.comments:
render_comment(comment);
- }
}
diff --git a/src/assemble.c b/src/assemble.c
index bfa0d74..51c2f2f 100644
--- a/src/assemble.c
+++ b/src/assemble.c
@@ -2,6 +2,19 @@
#include "assemble.h"
#define MAX_SCOPES 32
+#define MAX_VARS 1024
+#define MAX_STRING_LITERALS 1024
+
+typedef struct FunctionCall FunctionCall;
+struct FunctionCall {
+ FunctionCall *next;
+ String name;
+ int off;
+};
+
+typedef struct {
+ String name;
+} Variable;
typedef enum {
SCOPE_FUNC,
@@ -13,14 +26,122 @@ typedef enum {
typedef struct {
ScopeType type;
+ int var_base;
// TODO
+ FunctionCall *calls;
} Scope;
typedef struct {
- int depth;
+ char *ptr;
+ int len;
+ int cap;
+ b32 err;
+} OutputBuffer;
+
+typedef struct {
+
+ Arena *a;
+
+ OutputBuffer out;
+
+ int num_vars;
+ Variable vars[MAX_VARS];
+
+ int num_scopes;
Scope scopes[MAX_SCOPES];
+
+ int strings_len;
+ int strings_cap;
+ char *strings;
+
} Assembler;
+int add_string_literal(Assembler *a, String str)
+{
+ if (a->strings_cap - a->strings_len < str.len) {
+ int c = MAX(2 * a->strings_cap, a->strings_len + str.len);
+ char *p = malloc(c);
+ if (p == NULL) {
+ // TODO
+ }
+ if (a->strings_cap) {
+ memcpy(p, a->strings, a->strings_len);
+ free(a->strings);
+ }
+
+ a->strings = p;
+ a->strings_cap = c;
+ }
+
+ int off = a->strings_len;
+ memcpy(a->strings + a->strings_len, str.ptr, str.len);
+ a->strings_len += str.len;
+
+ return off;
+}
+
+void append_mem(OutputBuffer *out, void *ptr, int len)
+{
+ if (out->err)
+ return;
+
+ if (out->cap - out->len < len) {
+
+ int new_cap = MAX(512, 2 * out->cap);
+ char *new_ptr = malloc(new_cap);
+ if (new_ptr == NULL) {
+ out->err = true;
+ return;
+ }
+
+ if (out->cap) {
+ memcpy(new_ptr, out->ptr, out->len);
+ free(out->ptr);
+ }
+
+ out->ptr = new_ptr;
+ out->cap = new_cap;
+ }
+
+ memcpy(out->ptr + out->len, ptr, len);
+ out->len += len;
+}
+
+void patch_mem(OutputBuffer *out, int off, void *ptr, int len)
+{
+ if (out->err)
+ return;
+
+ memcpy(out->ptr + off, ptr, len);
+}
+
+int append_u8(OutputBuffer *out, uint8_t x)
+{
+ int off = out->len;
+ append_mem(out, &x, (int) sizeof(x));
+ return off;
+}
+
+int append_u32(OutputBuffer *out, uint32_t x)
+{
+ int off = out->len;
+ append_mem(out, &x, (int) sizeof(x));
+ return off;
+}
+
+int append_f64(OutputBuffer *out, double x)
+{
+ int off = out->len;
+ append_mem(out, &x, (int) sizeof(x));
+ return off;
+}
+
+void patch_with_current_offset(OutputBuffer *out, int off)
+{
+ uint32_t x = out->len;
+ patch_mem(out, off, &x, (int) sizeof(x));
+}
+
int count_nodes(Node *head)
{
int n = 0;
@@ -32,41 +153,85 @@ int count_nodes(Node *head)
return n;
}
-void assemble_node(Node *node)
+int declare_var(Assembler *a, String name)
+{
+ if (a->num_vars == MAX_VARS)
+ return -1;
+ // TODO: check if the variable exists already
+ int idx = a->num_vars++;
+ a->vars[idx] = (Variable) { name };
+ return idx - a->scopes[a->num_scopes-1].var_base;
+}
+
+void assemble_html_node_inner(Assembler *a, Node *node, OutputBuffer *tmp)
+{
+ append_u8(tmp, '<');
+ append_mem(tmp, node->tagname.ptr, node->tagname.len);
+
+ Node *attr = node->params;
+ while (attr) {
+ append_u8(tmp, ' ');
+ append_mem(tmp, attr->attr_name.ptr, attr->attr_name.len);
+ if (attr->attr_value) {
+ append_u8(tmp, '=');
+ // TODO
+ }
+ attr = attr->next;
+ }
+ append_u8(tmp, '>');
+
+ Node *child = node->child;
+ while (child) {
+ // TODO
+ child = child->next;
+ }
+
+ append_u8(tmp, '<');
+ append_u8(tmp, '/');
+ append_mem(tmp, node->tagname.ptr, node->tagname.len);
+ append_u8(tmp, '>');
+}
+
+void assemble_html_node(Assembler *a, Node *node)
+{
+ OutputBuffer tmp;
+ assemble_html_node_inner(a, node, &tmp);
+}
+
+void assemble_node(Assembler *a, Node *node)
{
switch (node->type) {
case NODE_FUNC_DECL:
{
- append_u8 (out, OPCODE_JUMP);
- append_u64(out, xxx);
+ append_u8(&a->out, OPCODE_JUMP);
+ int p1 = append_u32(&a->out, 0);
+
+ // TODO: resolve references
int arg_count = count_nodes(node->func_args);
- Node *preallocated[32];
- Node *args = preallocated;
- if (arg_count > COUNT(preallocated)) {
- args = malloc(arg_count * sizeof(Node*));
- if (args == NULL) {
- // TODO
- }
+ Node *args[32];
+ if (arg_count > COUNT(args)) {
+ // TODO
}
for (int i = arg_count-1; i >= 0; i--) {
- append_u8 (out, OPCODE_ASS);
- append_u64(out, xxx);
+ int idx = declare_var(a, args[i]->sval);
+ if (idx < 0) {
+ // TODO
+ }
+ append_u8(&a->out, OPCODE_SETV);
+ append_u8(&a->out, idx);
}
if (is_expr(node->func_body)) {
- assemble_node(node->func_body);
- append_u8(out, OPCODE_RET);
+ assemble_node(a, node->func_body);
+ append_u8(&a->out, OPCODE_RET);
} else
- assemble_node(node->func_body);
+ assemble_node(a, node->func_body);
- append_u8(out, OPCODE_NOPE);
-
- if (args != preallocated)
- free(args);
+ patch_with_current_offset(&a->out, p1);
}
break;
@@ -78,19 +243,50 @@ void assemble_node(Node *node)
int arg_count = 0;
Node *arg = args;
while (arg) {
- assemble_node(arg);
+ assemble_node(a, arg);
arg_count++;
arg = arg->next;
}
- assemble_node(arg);
- append_u8(OPCODE_CALL);
- append_u32(arg_count);
-
if (func->type == NODE_VALUE_VAR) {
+ assemble_node(a, arg);
+ append_u8(&a->out, OPCODE_SCALL);
+ append_u8(&a->out, arg_count);
+ int p = append_u32(&a->out, 0);
+
+ FunctionCall *call = alloc(a->a, sizeof(FunctionCall), _Alignof(FunctionCall));
+ if (call == NULL) {
+ // TODO
+ }
+ call->name = func->sval;
+ call->off = p;
+
+ Scope *scope = &a->scopes[a->num_scopes-1];
+
+ call->next = scope->calls;
+ scope->calls = call;
+
+ } else {
+ assemble_node(a, func);
+ assemble_node(a, arg);
+ append_u8(&a->out, OPCODE_DCALL);
+ append_u8(&a->out, arg_count);
+ }
+ }
+ break;
+
+ case NODE_VAR_DECL:
+ {
+ int idx = declare_var(a, node->var_name);
+ if (idx < 0) {
// TODO
}
+ if (node->var_value) {
+ assemble_node(a, node->var_value);
+ append_u8(&a->out, OPCODE_SETV);
+ append_u8(&a->out, idx);
+ }
}
break;
@@ -98,9 +294,9 @@ void assemble_node(Node *node)
{
Node *stmt = node->child;
while (stmt) {
- assemble_node(stmt);
+ assemble_node(a, stmt);
if (is_expr(stmt))
- append_u8(out, OPCODE_POP);
+ append_u8(&a->out, OPCODE_POP);
stmt = stmt->next;
}
}
@@ -108,134 +304,258 @@ void assemble_node(Node *node)
case NODE_IFELSE:
{
- assemble_node(node->cond);
+ // If there is no else branch:
+ //
+ //