#include <stdbool.h>
#include <stdio.h>
#include <stdarg.h>
+#include <string.h>
+#include <assert.h>
// Global defines
#define STR_SIZE 128
-#define BUF_SIZE 1024*1024
+#define MEMORY_SIZE 1024*1024
+#define EDIT_QUEUE_SIZE 10
// Memory
static int g_memory_index = 0;
void * alloc(int num, int size) {
+ assert(g_memory_index + num*size < MEMORY_SIZE);
+
void * result = g_memory + g_memory_index;
for (int i = 0; i < num*size; i++)
g_memory[g_memory_index+i] = 0;
#else
struct winsize w;
ioctl(STDOUT_FILENO, TIOCGWINSZ, &w);
- *h = w.ws_row;
- *v = w.ws_col;
+ *h = w.ws_col;
+ *v = w.ws_row;
#endif
}
void * data;
int childCount;
- Node *next, *prev, *parent, *child;
+ Node *next, *prev, *prnt, *chld;
};
Node *NodeGetChild(Node *n, unsigned int index) {
if (index >= n->childCount)
return NULL;
- Node *result = n->child;
+ Node *result = n->chld;
for (int i = 0; i < index; i++)
result = result->next;
return result;
void NodeAppend(Node *n1, Node *n2) {
if (n1->childCount == 0) {
- n1->child = n2;
+ n1->chld = n2;
}
else {
Node *lastChild = NodeGetChild(n1, n1->childCount-1);
n2->prev = lastChild;
n2->next = NULL;
}
- n2->parent = n1;
+ n2->prnt = n1;
n1->childCount += 1;
}
if (next != NULL)
next->prev = prev;
- n2->prev = n2->next = n2->parent = NULL;
+ n2->prev = n2->next = n2->prnt = NULL;
- if (n2 == n1->child)
- n1->child = next;
+ if (n2 == n1->chld)
+ n1->chld = next;
n1->childCount -= 1;
return prev;
}
+void NodeDraw(Node *n);
Node *g_NodeDrawSelected;
+void Printf(Node *n, char* format, ...)
+{
+ va_list argp;
+ va_start(argp, format);
+ while (*format != '\0') {
+ if (*format == '%') {
+ format++;
+ if (*format == '%') {
+ putchar('%');
+ } else if (*format == 'n') {
+ Node *n = va_arg(argp, Node*);
+ NodeDraw(n);
+ } else if (*format == 's') {
+ char *s = va_arg(argp, char*);
+ printf("%s", s);
+ if (g_NodeDrawSelected == n && s == n->data)
+ printf("%c", ' ');
+ } else if (*format == ',' && format[1] == 'n') {
+ Node *n = va_arg(argp, Node*);
+ for (int i = 0; i < n->childCount; i++) {
+ if (i > 0) printf(", ");
+ NodeDraw(NodeGetChild(n, i));
+ }
+ format++;
+ } else if (*format == ';' && format[1] == 'n') {
+ Node *n = va_arg(argp, Node*);
+ for (int i = 0; i < n->childCount; i++) {
+ if (i == 0) printf("\n");
+ NodeDraw(NodeGetChild(n, i));
+ printf("\n");
+ }
+ format++;
+ } else {
+ fputs("Not implemented", stderr);
+ }
+ } else if (*format == '_') {
+ static bool highlighted = false;
+ // Node *n = va_arg(argp, Node*);
+ if (highlighted) {
+ vt100DisableNegative();
+ highlighted = false;
+ }
+ else if (g_NodeDrawSelected == n) {
+ vt100EnableNegative();
+ highlighted = true;
+ }
+ } else {
+ putchar(*format);
+ }
+ format++;
+ }
+ va_end(argp);
+}
+
void NodeDraw(Node *n) {
static int indent = 0;
#define INDENT printf("\n"); for (int i = 0; i < indent; i++) printf(" ");
#define PRINTF(...) do { if (n == g_NodeDrawSelected) vt100EnableNegative(); printf(__VA_ARGS__); vt100DisableNegative(); } while(0);
switch (n->kind) {
- case NK_Namespace: { PRINTF("namespace"); printf(" %s {", n->data); indent++; for (int i = 0; i < n->childCount; i++) { INDENT NodeDraw(NodeGetChild(n, i)); } indent--; INDENT printf("}"); break; }
- case NK_Struct: { PRINTF("struct"); printf(" %s {", n->data); indent++; for (int i = 0; i < n->childCount; i++) { INDENT NodeDraw(NodeGetChild(n, i)); } indent--; INDENT printf("}"); break; }
- case NK_Func: { PRINTF("fn"); printf(" %s ", n->data); NodeDraw(NodeGetChild(n, 0)); printf(" "); NodeDraw(NodeGetChild(n, 1)); break; }
+ case NK_Namespace: { Printf(n, "_namespace %s {_%;n_}_\n", n->data, n); break; }
+ case NK_Struct: { Printf(n, "_struct %s {_%;n_}_\n", n->data, n); break; }
+ case NK_Func: { Printf(n, "_fn %s_ %n %n", n->data, NodeGetChild(n, 0), NodeGetChild(n, 1)); break; }
case NK_VarList:
- case NK_ExprList: { PRINTF("("); for (int i = 0; i < n->childCount; i++) { if (i != 0) printf(", "); NodeDraw(NodeGetChild(n, i)); } PRINTF(")"); break; }
- case NK_Var: { PRINTF("[%s]", n->data); break; }
- case NK_VarDecl: { PRINTF("[%s : ", n->data); NodeDraw(NodeGetChild(n, 0)); printf("]"); break; }
+ case NK_ExprList: { Printf(n, "_(_%,n_)_", n); break; }
+ case NK_Var: { Printf(n, "_%s_", n->data); break; }
+ case NK_VarDecl: { Printf(n, "_%s:_ %n", n->data, NodeGetChild(n, 0)); break; }
case NK_VarType:
- case NK_Type: { PRINTF("%s", n->data); for (int i = 0; i < n->childCount; i++) { printf("%s", i == 0 ? "<" : ", "); NodeDraw(NodeGetChild(n, i)); if (i == n->childCount-1) printf(">"); } break; }
- case NK_Body: { PRINTF("{"); indent++; for (int i = 0; i < n->childCount; i++) { INDENT NodeDraw(NodeGetChild(n, i)); } indent--; INDENT PRINTF("}"); break; }
- case NK_If: { PRINTF("if"); printf(" "); NodeDraw(NodeGetChild(n, 0)); INDENT NodeDraw(NodeGetChild(n, 1)); break; }
- case NK_While: { PRINTF("while"); printf(" "); NodeDraw(NodeGetChild(n, 0)); INDENT NodeDraw(NodeGetChild(n, 1)); break; }
- case NK_Num: { PRINTF("%s", n->data); break; }
- case NK_Str: { PRINTF("'%s'", n->data); break; }
- case NK_Call: { PRINTF("!%s ", n->data); NodeDraw(NodeGetChild(n, 0)); break; }
- case NK_Op: { if (n->childCount <= 1) { PRINTF("%s", n->data); printf(" "); } for (int i = 0; i < n->childCount; i++) { if (i != 0) { printf(" "); PRINTF("%s", n->data); printf(" "); } NodeDraw(NodeGetChild(n, i)); } break; }
+ case NK_Type: { Printf(n, "_%s%s%,n%s_", n->data, (n->childCount > 0 ? "<" : ""), n, (n->childCount > 0 ? ">" : "")); break; }
+ case NK_Body: { Printf(n, "_{_%;n_}_", n); break; }
+ case NK_If: { Printf(n, "_if_ %n %n", NodeGetChild(n, 0), NodeGetChild(n, 1)); break; }
+ case NK_While: { Printf(n, "_while_ %n %n", NodeGetChild(n, 0), NodeGetChild(n, 1)); break; }
+ case NK_Num: { Printf(n, "_%s_", n->data); break; }
+ case NK_Str: { Printf(n, "_'%s'_", n->data); break; }
+ case NK_Call: { Printf(n, "_%s_(%n)", n->data, NodeGetChild(n, 0)); break; }
+ case NK_Op: { for (int i = 0; i < n->childCount; i++) { if (n->childCount == 0 || i != 0) { Printf(n, " _%s_ ", n->data); } NodeDraw(NodeGetChild(n, i)); } break; }
}
}
int line = 2;
- vt100CursorPos(line++, h-10);
+ vt100CursorPos(line++, h-30);
+ printf("%d:%d", v, h);
+ vt100CursorPos(line++, h-30);
+
printf("%s:%s", NK_STRINGS[nk], (mode == IM_Normal ? "" : " (editing)"));
for (int i = IN_L+1; i < IN_COUNT; i++) {
InputAction action = actions[nk][i];
if (action != IA_None) {
- vt100CursorPos(line++, h-10);
+ vt100CursorPos(line++, h-30);
printf("%s %s", IN_STRINGS[i], IA_STRINGS[action]);
}
}
}
+bool ValidChar(NodeKind nk, int c) {
+ const char *allow = NULL;
+ const char *block = NULL;
+
+ switch (nk) {
+ case NK_Namespace:
+ case NK_Struct:
+ case NK_Func:
+ case NK_Var:
+ case NK_VarDecl:
+ case NK_VarType:
+ case NK_Type:
+ case NK_Str:
+ case NK_Call:
+ case NK_Op:
+ block = "";
+ break;
+
+ case NK_Num:
+ allow = "+-.0123456789";
+ break;
+
+ case NK_VarList:
+ case NK_ExprList:
+ case NK_Body:
+ case NK_If:
+ case NK_While:
+ allow = "";
+ break;
+ }
+
+ if (allow != NULL) {
+ char a;
+ for (int i = 0; (a = allow[i]) != '\0'; i++) {
+ if (a == c) return true;
+ }
+ return false;
+ }
+ else if (block != NULL) {
+ char b;
+ for (int i = 0; (b = block[i]) != '\0'; i++) {
+ if (b == c) return false;
+ }
+ return true;
+ }
+ else {
+ return false;
+ }
+}
+
+Node *PopEditQueue(Node ** q) {
+ Node *result = q[0];
+ for (int i = 0; i < EDIT_QUEUE_SIZE-1 && q[i] != NULL; i++) {
+ q[i] = q[i+1];
+ }
+ return result;
+}
+
Node *GetNode(InputAction actions[NK_COUNT][IN_COUNT]) {
Node *result = NEW(Node); result->data = NEWSTR; result->kind = NK_Namespace;
Node * n = result;
+ Node * q[EDIT_QUEUE_SIZE] = {0};
Input in;
InputAction action;
s[slen-1] = '\0';
}
else if (c == '\n' || c == '\r') {
- mode = IM_Normal;
+ if (q[0] == NULL)
+ mode = IM_Normal;
+ else
+ n = PopEditQueue(q);
}
- else if (slen < STR_SIZE) {
+ else if (slen < STR_SIZE && ValidChar(n->kind, c)) {
s[slen++] = (char)c;
}
}
#define S(NAME, PARENT, KIND) Node *NAME = NEW(Node); NAME->kind = KIND; NAME->data = NEWSTR; NodeAppend(PARENT, NAME);
switch (action) {
- case IA_MoveLeft: { if (n->prev != NULL) n = n->prev; break; }
- case IA_MoveDown: { if (n->child != NULL) n = n->child; break; }
- case IA_MoveUp: { if (n->parent != NULL) n = n->parent; break; }
+ case IA_MoveLeft: { if (n->prev != NULL) n = n->prev; break; }
+ case IA_MoveDown: { if (n->chld != NULL) n = n->chld; break; }
+ case IA_MoveUp: { if (n->prnt != NULL) n = n->prnt; break; }
case IA_MoveRight: { if (n->next != NULL) n = n->next; break; }
case IA_StartEditing: { mode = IM_Editing; break; }
- case IA_Delete: { n = NodeRemove(n->parent, n); break; }
-
- case IA_AddNamespace: { S(n1, n, NK_Namespace) n = n1; mode = IM_Editing; break; }
- case IA_AddStruct: { S(n1, n, NK_Struct) n = n1; mode = IM_Editing; break; }
- case IA_AddFunc: { S(n1, n, NK_Func) N(n2, n1, NK_VarList) N(n3, n1, NK_Body) n = n1; mode = IM_Editing; break; }
- case IA_AddVar: { S(n1, n, NK_Var) n = n1; mode = IM_Editing; break; }
- case IA_AddVarDecl: { S(n1, n, NK_VarDecl) S(n2, n1, NK_VarType) n = n1; mode = IM_Editing; break; }
- case IA_AddType: { S(n1, n, NK_Type) n = n1; mode = IM_Editing; break; }
- case IA_AddIf: { N(n1, n, NK_If) N(n2, n1, NK_ExprList) N(n3, n1, NK_Body) n = n2; break; }
- case IA_AddWhile: { N(n1, n, NK_While) N(n2, n1, NK_ExprList) N(n3, n1, NK_Body) n = n2; break; }
- case IA_AddNum: { S(n1, n, NK_Num) n = n1; mode = IM_Editing; break; }
- case IA_AddStr: { S(n1, n, NK_Str) n = n1; mode = IM_Editing; break; }
- case IA_AddCall: { S(n1, n, NK_Call) N(n2, n1, NK_ExprList) n = n1; mode = IM_Editing; break; }
- case IA_AddOp: { S(n1, n, NK_Op) n = n1; mode = IM_Editing; break; }
+ case IA_Delete: { n = NodeRemove(n->prnt, n); break; }
+
+ case IA_AddNamespace: { S(n1, n, NK_Namespace) n=n1; mode=IM_Editing; break; }
+ case IA_AddStruct: { S(n1, n, NK_Struct) n=n1; mode=IM_Editing; break; }
+ case IA_AddFunc: { S(n1, n, NK_Func)
+ N(n2, n1, NK_VarList)
+ N(n3, n1, NK_Body) n=n1; mode=IM_Editing; break; }
+ case IA_AddVar: { S(n1, n, NK_Var) n=n1; mode=IM_Editing; break; }
+ case IA_AddVarDecl: { S(n1, n, NK_VarDecl) n=n1;
+ S(n2, n1, NK_VarType) q[0]=n2; mode=IM_Editing; break; }
+ case IA_AddType: { S(n1, n, NK_Type) n=n1; mode=IM_Editing; break; }
+ case IA_AddIf: { N(n1, n, NK_If)
+ N(n2, n1, NK_ExprList)
+ N(n3, n1, NK_Body) n=n2; break; }
+ case IA_AddWhile: { N(n1, n, NK_While)
+ N(n2, n1, NK_ExprList)
+ N(n3, n1, NK_Body) n=n2; break; }
+ case IA_AddNum: { S(n1, n, NK_Num) n=n1; mode=IM_Editing; break; }
+ case IA_AddStr: { S(n1, n, NK_Str) n=n1; mode=IM_Editing; break; }
+ case IA_AddCall: { S(n1, n, NK_Call)
+ N(n2, n1, NK_ExprList) n=n1; mode=IM_Editing; break; }
+ case IA_AddOp: { S(n1, n, NK_Op) n=n1; mode=IM_Editing; break; }
}
#undef N
- #undef N
+ #undef S
}
}
void SetupInputActions(InputAction actions[NK_COUNT][IN_COUNT]) {
for (int i = 0; i < NK_COUNT; i++) {
actions[i][IN_H] = IA_MoveLeft;
- actions[i][IN_J] = IA_MoveUp;
- actions[i][IN_K] = IA_MoveDown;
+ actions[i][IN_J] = IA_MoveDown;
+ actions[i][IN_K] = IA_MoveUp;
actions[i][IN_L] = IA_MoveRight;
}