10 #define BUF_SIZE 1024*1024
14 static char g_memory[1024*1024];
15 static int g_memory_index = 0;
17 void * alloc(int num, int size) {
18 void * result = g_memory + g_memory_index;
19 for (int i = 0; i < num*size; i++)
20 g_memory[g_memory_index+i] = 0;
21 g_memory_index += num*size;
25 #define NEW(TYPE) ((TYPE *)alloc(1, sizeof(TYPE)))
26 #define NEWARR(TYPE, NUM) ((TYPE *)alloc(NUM, sizeof(TYPE)))
27 #define NEWSTR NEWARR(char, STR_SIZE)
35 #include <sys/ioctl.h>
40 /* reads from keypress, doesn't echo */
43 struct termios oldattr, newattr;
45 tcgetattr( STDIN_FILENO, &oldattr );
47 newattr.c_lflag &= ~( ICANON | ECHO ); // no ECHO for echo(?)
48 tcsetattr( STDIN_FILENO, TCSANOW, &newattr );
50 tcsetattr( STDIN_FILENO, TCSANOW, &oldattr );
57 struct termios oldattr, newattr;
58 tcgetattr( STDIN_FILENO, &oldattr );
60 newattr.c_lflag &= ~( ICANON | ECHO );
61 tcsetattr( STDIN_FILENO, TCSANOW, &newattr );
63 tcsetattr( STDIN_FILENO, TCSANOW, &oldattr );
78 void vt100Escape(const char * str, ...) {
82 printf("%c", ASCII_ESC);
86 void vt100ClearScreen() { vt100Escape("[2J"); }
87 void vt100CursorHome() { vt100Escape("[H"); }
88 void vt100CursorPos(int v, int h) { vt100Escape("[%d;%dH", v, h); }
89 void vt100SaveCursor() { vt100Escape("7"); }
90 void vt100RestoreCursor() { vt100Escape("8"); }
91 void vt100EnableAlternateBuffer() { vt100Escape("[?1049h"); }
92 void vt100DisableAlternateBuffer() { vt100Escape("[?1049l"); }
93 void vt100EnableNegative() { vt100Escape("[7m"); }
94 void vt100DisableNegative() { vt100Escape("[27m"); }
95 void vt100ShowCursor() { vt100Escape("[?25h"); }
96 void vt100HideCursor() { vt100Escape("[?25l"); }
97 void vt100GetScreenSize(int * v, int * h) {
99 CONSOLE_SCREEN_BUFFER_INFO csbi;
100 GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi);
101 *h = csbi.srWindow.Right - csbi.srWindow.Left + 1;
102 *v = csbi.srWindow.Bottom - csbi.srWindow.Top + 1;
105 ioctl(STDOUT_FILENO, TIOCGWINSZ, &w);
113 typedef enum NodeKind {
134 const char *NK_STRINGS[NK_COUNT] = {
153 typedef struct Node Node;
159 Node *next, *prev, *parent, *child;
162 Node *NodeGetChild(Node *n, unsigned int index) {
163 if (index >= n->childCount)
166 Node *result = n->child;
167 for (int i = 0; i < index; i++)
168 result = result->next;
172 void NodeAppend(Node *n1, Node *n2) {
173 if (n1->childCount == 0) {
177 Node *lastChild = NodeGetChild(n1, n1->childCount-1);
179 lastChild->next = n2;
180 n2->prev = lastChild;
187 void NodeInsert(Node *n1, Node *n2, unsigned int index) {
188 if (index >= n1->childCount-1) {
193 Node *insertAfter = NodeGetChild(n1, index);
194 Node *insertBefore = NodeGetChild(n1, index+1);
196 insertAfter->next = n2;
197 insertBefore->prev = n2;
198 n2->prev = insertAfter;
199 n2->next = insertBefore;
204 Node *NodeRemove(Node *n1, Node *n2) {
208 Node *prev = n2->prev;
209 Node *next = n2->next;
216 n2->prev = n2->next = n2->parent = NULL;
229 void NodeDraw(Node *n);
230 Node *g_NodeDrawSelected;
232 void Printf(char* format, ...)
235 va_start(argp, format);
236 while (*format != '\0') {
237 if (*format == '%') {
239 if (*format == '%') {
241 } else if (*format == 'n') {
242 Node *n = va_arg(argp, Node*);
244 } else if (*format == 's') {
245 char *s = va_arg(argp, char*);
247 } else if (*format == ',' && format[1] == 'n') {
248 Node *n = va_arg(argp, Node*);
249 for (int i = 0; i < n->childCount; i++) {
250 if (n > 0) printf(", ");
251 NodeDraw(NodeGetChild(n, i));
254 } else if (*format == ';' && format[1] == 'n') {
255 Node *n = va_arg(argp, Node*);
256 for (int i = 0; i < n->childCount; i++) {
257 if (n > 0) printf("\n");
258 NodeDraw(NodeGetChild(n, i));
262 fputs("Not implemented", stdout);
264 } else if (*format == '_') {
265 static bool highlighted = false;
267 vt100DisableNegative();
270 else if (g_NodeDrawSelected == n) {
271 vt100EnableNegative();
282 void NodeDraw(Node *n) {
283 static int indent = 0;
284 #define INDENT printf("\n"); for (int i = 0; i < indent; i++) printf(" ");
286 #define PRINTF(...) do { if (n == g_NodeDrawSelected) vt100EnableNegative(); printf(__VA_ARGS__); vt100DisableNegative(); } while(0);
288 // switch (n->kind) {
289 // 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("}\n"); break; }
290 // 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("}\n"); break; }
291 // case NK_Func: { PRINTF("fn"); printf(" %s ", n->data); NodeDraw(NodeGetChild(n, 0)); INDENT NodeDraw(NodeGetChild(n, 1)); break; }
293 // case NK_ExprList: { PRINTF("("); for (int i = 0; i < n->childCount; i++) { if (i != 0) printf(", "); NodeDraw(NodeGetChild(n, i)); } PRINTF(")"); break; }
294 // case NK_Var: { PRINTF("[%s]", n->data); break; }
295 // case NK_VarDecl: { PRINTF("[%s : ", n->data); NodeDraw(NodeGetChild(n, 0)); printf("]"); break; }
297 // 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; }
298 // case NK_Body: { PRINTF("{"); indent++; for (int i = 0; i < n->childCount; i++) { INDENT NodeDraw(NodeGetChild(n, i)); } indent--; INDENT PRINTF("}\n"); break; }
299 // case NK_If: { PRINTF("if"); printf(" "); NodeDraw(NodeGetChild(n, 0)); INDENT NodeDraw(NodeGetChild(n, 1)); break; }
300 // case NK_While: { PRINTF("while"); printf(" "); NodeDraw(NodeGetChild(n, 0)); INDENT NodeDraw(NodeGetChild(n, 1)); break; }
301 // case NK_Num: { PRINTF("%s", n->data); break; }
302 // case NK_Str: { PRINTF("'%s'", n->data); break; }
303 // case NK_Call: { PRINTF("!%s ", n->data); NodeDraw(NodeGetChild(n, 0)); break; }
304 // 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; }
308 case NK_Namespace: { Printf("_namespace_ %s {%;n}\n", n->data, n); break; }
309 case NK_Struct: { Printf("_struct_ %s {%;n}\n", n->data, n); break; }
310 case NK_Func: { Printf("_fn_ %s %n %n", n->data, NodeGetChild(n, 0), NodeGetChild(n, 1)); break; }
312 case NK_ExprList: { Printf("_(_%,n_)_", n); break; }
313 case NK_Var: { Printf("_[_%s_]_", n->data); break; }
314 case NK_VarDecl: { Printf("_[_%s : %n_]_", n->data, NodeGetChild(n, 0)); break; }
316 case NK_Type: { Printf("%s%s%,n%s", n->data, (n->childCount > 0 ? "<" : ""), n, (n->childCount > 0 ? "<" : "")); break; }
317 case NK_Body: { Printf("_{_%;n_}_"); break; }
318 case NK_If: { Printf("_if_ %n %n", NodeGetChild(n, 0), NodeGetChild(n, 1)); break; }
319 case NK_While: { Printf("_while_ %n %n", NodeGetChild(n, 0), NodeGetChild(n, 1)); break; }
320 case NK_Num: { Printf("_%s_", n->data); break; }
321 case NK_Str: { Printf("_'%s'_", n->data); break; }
322 case NK_Call: { Printf("_!%s_%n", n->data, NodeGetChild(n, 0)); break; }
323 case NK_Op: { if (n->childCount <= 1) Printf("_%s_ ", n->data); for (int i = 0; i < n->childCount; i++) { if (i != 0) { Printf(" _%s_ ", n->data); } NodeDraw(NodeGetChild(n, i)); } break; }
330 #define KEY_BACKSPACE1 8
331 #define KEY_BACKSPACE2 127
360 const char *IN_STRINGS[IN_COUNT] = {
391 case ' ': return IN_SPACE;
392 case 'd': return IN_D;
394 case 'h': return IN_H;
395 case 'j': return IN_J;
396 case 'k': return IN_K;
397 case 'l': return IN_L;
399 case 'f': return IN_F;
400 case 'v': return IN_V;
401 case 't': return IN_T;
402 case 'i': return IN_I;
403 case 'w': return IN_W;
404 case 'n': return IN_N;
405 case 's': return IN_S;
406 case 'c': return IN_C;
407 case 'o': return IN_O;
409 case 'q': return IN_Quit;
414 typedef enum InputAction {
441 const char *IA_STRINGS[IA_COUNT] = {
466 typedef enum InputMode {
471 void DrawInfo(InputAction actions[NK_COUNT][IN_COUNT], NodeKind nk, InputMode mode) {
473 vt100GetScreenSize(&v, &h);
477 vt100CursorPos(line++, h-30);
478 printf("%s:%s", NK_STRINGS[nk], (mode == IM_Normal ? "" : " (editing)"));
480 for (int i = 0; i < IN_COUNT; i++) {
481 InputAction action = actions[nk][i];
482 if (action != IA_None) {
483 vt100CursorPos(line++, h-30);
484 printf("%s %s", IN_STRINGS[i], IA_STRINGS[action]);
489 Node *GetNode(InputAction actions[NK_COUNT][IN_COUNT]) {
490 Node *result = NEW(Node); result->data = NEWSTR; result->kind = NK_Namespace;
497 InputMode mode = IM_Normal;
502 g_NodeDrawSelected = n;
504 g_NodeDrawSelected = NULL;
505 DrawInfo(actions, n->kind, mode);
507 if (mode == IM_Editing) {
509 char *s = (char*)n->data;
510 int slen = strlen(s);
512 if (c == KEY_BACKSPACE1 || c == KEY_BACKSPACE2) {
515 else if (c == '\n' || c == '\r') {
518 else if (slen < STR_SIZE) {
522 else if (mode == IM_Normal) {
528 action = actions[n->kind][in];
530 #define N(NAME, PARENT, KIND) Node *NAME = NEW(Node); NAME->kind = KIND; NodeAppend(PARENT, NAME);
531 #define S(NAME, PARENT, KIND) Node *NAME = NEW(Node); NAME->kind = KIND; NAME->data = NEWSTR; NodeAppend(PARENT, NAME);
534 case IA_StartEditing: { mode = IM_Editing; break; }
535 case IA_Delete: { n = NodeRemove(n->parent, n); break; }
537 case IA_MoveLeft: { if (n->prev != NULL) n = n->prev; break; }
538 case IA_MoveDown: { if (n->child != NULL) n = n->child; break; }
539 case IA_MoveUp: { if (n->parent != NULL) n = n->parent; break; }
540 case IA_MoveRight: { if (n->next != NULL) n = n->next; break; }
542 case IA_AddNamespace: { S(n1, n, NK_Namespace) n = n1; mode = IM_Editing; break; }
543 case IA_AddStruct: { S(n1, n, NK_Struct) n = n1; mode = IM_Editing; break; }
544 case IA_AddFunc: { S(n1, n, NK_Func) N(n2, n1, NK_VarList) N(n3, n1, NK_Body) n = n1; mode = IM_Editing; break; }
545 case IA_AddVar: { S(n1, n, NK_Var) n = n1; mode = IM_Editing; break; }
546 case IA_AddVarDecl: { S(n1, n, NK_VarDecl) S(n2, n1, NK_VarType) n = n1; mode = IM_Editing; break; }
547 case IA_AddType: { S(n1, n, NK_Type) n = n1; mode = IM_Editing; break; }
548 case IA_AddIf: { N(n1, n, NK_If) N(n2, n1, NK_ExprList) N(n3, n1, NK_Body) n = n2; break; }
549 case IA_AddWhile: { N(n1, n, NK_While) N(n2, n1, NK_ExprList) N(n3, n1, NK_Body) n = n2; break; }
550 case IA_AddNum: { S(n1, n, NK_Num) n = n1; mode = IM_Editing; break; }
551 case IA_AddStr: { S(n1, n, NK_Str) n = n1; mode = IM_Editing; break; }
552 case IA_AddCall: { S(n1, n, NK_Call) N(n2, n1, NK_ExprList) n = n1; mode = IM_Editing; break; }
553 case IA_AddOp: { S(n1, n, NK_Op) n = n1; mode = IM_Editing; break; }
567 static InputAction actions[NK_COUNT][IN_COUNT];
569 for (int i = 0; i < NK_COUNT; i++) {
570 actions[i][IN_H] = IA_MoveLeft;
571 actions[i][IN_J] = IA_MoveUp;
572 actions[i][IN_K] = IA_MoveDown;
573 actions[i][IN_L] = IA_MoveRight;
576 actions[NK_Namespace][IN_D] = IA_Delete;
577 actions[NK_Namespace][IN_SPACE] = IA_StartEditing;
578 actions[NK_Namespace][IN_N] = IA_AddNamespace;
579 actions[NK_Namespace][IN_S] = IA_AddStruct;
580 actions[NK_Namespace][IN_F] = IA_AddFunc;
582 actions[NK_Struct][IN_D] = IA_Delete;
583 actions[NK_Struct][IN_SPACE] = IA_StartEditing;
584 actions[NK_Struct][IN_V] = IA_AddVarDecl;
585 actions[NK_Struct][IN_F] = IA_AddFunc;
587 actions[NK_Func][IN_D] = IA_Delete;
588 actions[NK_Func][IN_SPACE] = IA_StartEditing;
590 actions[NK_VarList][IN_V] = IA_AddVarDecl;
592 actions[NK_ExprList][IN_V] = IA_AddVar;
593 actions[NK_ExprList][IN_I] = IA_AddIf;
594 actions[NK_ExprList][IN_W] = IA_AddWhile;
595 actions[NK_ExprList][IN_N] = IA_AddNum;
596 actions[NK_ExprList][IN_S] = IA_AddStr;
597 actions[NK_ExprList][IN_C] = IA_AddCall;
598 actions[NK_ExprList][IN_O] = IA_AddOp;
600 actions[NK_Var][IN_D] = IA_Delete;
601 actions[NK_Var][IN_SPACE] = IA_StartEditing;
603 actions[NK_VarDecl][IN_D] = IA_Delete;
604 actions[NK_VarDecl][IN_SPACE] = IA_StartEditing;
606 actions[NK_VarType][IN_SPACE] = IA_StartEditing;
607 actions[NK_VarType][IN_T] = IA_AddType;
609 actions[NK_Type][IN_D] = IA_Delete;
610 actions[NK_Type][IN_SPACE] = IA_StartEditing;
611 actions[NK_Type][IN_T] = IA_AddType;
613 actions[NK_Body][IN_F] = IA_AddFunc;
614 actions[NK_Body][IN_V] = IA_AddVarDecl;
615 actions[NK_Body][IN_I] = IA_AddIf;
616 actions[NK_Body][IN_W] = IA_AddWhile;
617 actions[NK_Body][IN_N] = IA_AddNum;
618 actions[NK_Body][IN_S] = IA_AddStr;
619 actions[NK_Body][IN_C] = IA_AddCall;
620 actions[NK_Body][IN_O] = IA_AddOp;
622 actions[NK_If][IN_D] = IA_Delete;
624 actions[NK_While][IN_D] = IA_Delete;
626 actions[NK_Num][IN_D] = IA_Delete;
627 actions[NK_Num][IN_SPACE] = IA_StartEditing;
629 actions[NK_Str][IN_D] = IA_Delete;
630 actions[NK_Str][IN_SPACE] = IA_StartEditing;
632 actions[NK_Call][IN_D] = IA_Delete;
633 actions[NK_Call][IN_SPACE] = IA_StartEditing;
635 actions[NK_Op][IN_D] = IA_Delete;
636 actions[NK_Op][IN_SPACE] = IA_StartEditing;
637 actions[NK_Op][IN_V] = IA_AddVar;
638 actions[NK_Op][IN_I] = IA_AddIf;
639 actions[NK_Op][IN_W] = IA_AddWhile;
640 actions[NK_Op][IN_N] = IA_AddNum;
641 actions[NK_Op][IN_S] = IA_AddStr;
642 actions[NK_Op][IN_C] = IA_AddCall;
643 actions[NK_Op][IN_O] = IA_AddOp;
646 vt100EnableAlternateBuffer();
649 Node *n = GetNode(actions);
651 vt100DisableAlternateBuffer();
655 vt100GetScreenSize(&v, &h);
656 printf("Screen Size: %d | %d\n", v, h);