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;%df", 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 Node *g_NodeDrawSelected;
231 void NodeDraw(Node *n) {
232 static int indent = 0;
233 #define INDENT printf("\n"); for (int i = 0; i < indent; i++) printf(" ");
235 #define PRINTF(...) do { if (n == g_NodeDrawSelected) vt100EnableNegative(); printf(__VA_ARGS__); vt100DisableNegative(); } while(0);
238 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; }
239 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; }
240 case NK_Func: { PRINTF("fn"); printf(" %s ", n->data); NodeDraw(NodeGetChild(n, 0)); printf(" "); NodeDraw(NodeGetChild(n, 1)); break; }
242 case NK_ExprList: { PRINTF("("); for (int i = 0; i < n->childCount; i++) { if (i != 0) printf(", "); NodeDraw(NodeGetChild(n, i)); } PRINTF(")"); break; }
243 case NK_Var: { PRINTF("[%s]", n->data); break; }
244 case NK_VarDecl: { PRINTF("[%s : ", n->data); NodeDraw(NodeGetChild(n, 0)); printf("]"); break; }
246 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; }
247 case NK_Body: { PRINTF("{"); indent++; for (int i = 0; i < n->childCount; i++) { INDENT NodeDraw(NodeGetChild(n, i)); } indent--; INDENT PRINTF("}"); break; }
248 case NK_If: { PRINTF("if"); printf(" "); NodeDraw(NodeGetChild(n, 0)); INDENT NodeDraw(NodeGetChild(n, 1)); break; }
249 case NK_While: { PRINTF("while"); printf(" "); NodeDraw(NodeGetChild(n, 0)); INDENT NodeDraw(NodeGetChild(n, 1)); break; }
250 case NK_Num: { PRINTF("%s", n->data); break; }
251 case NK_Str: { PRINTF("'%s'", n->data); break; }
252 case NK_Call: { PRINTF("!%s ", n->data); NodeDraw(NodeGetChild(n, 0)); break; }
253 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; }
260 #define KEY_BACKSPACE1 8
261 #define KEY_BACKSPACE2 127
290 const char *IN_STRINGS[IN_COUNT] = {
321 case 'h': return IN_H;
322 case 'j': return IN_J;
323 case 'k': return IN_K;
324 case 'l': return IN_L;
326 case ' ': return IN_SPACE;
327 case 'd': return IN_D;
329 case 'f': return IN_F;
330 case 'v': return IN_V;
331 case 't': return IN_T;
332 case 'i': return IN_I;
333 case 'w': return IN_W;
334 case 'n': return IN_N;
335 case 's': return IN_S;
336 case 'c': return IN_C;
337 case 'o': return IN_O;
339 case 'q': return IN_Quit;
344 typedef enum InputAction {
371 const char *IA_STRINGS[IA_COUNT] = {
396 typedef enum InputMode {
401 void DrawInfo(InputAction actions[NK_COUNT][IN_COUNT], NodeKind nk, InputMode mode) {
403 vt100GetScreenSize(&v, &h);
407 vt100CursorPos(line++, h-10);
408 printf("%s:%s", NK_STRINGS[nk], (mode == IM_Normal ? "" : " (editing)"));
410 for (int i = IN_L+1; i < IN_COUNT; i++) {
411 InputAction action = actions[nk][i];
412 if (action != IA_None) {
413 vt100CursorPos(line++, h-10);
414 printf("%s %s", IN_STRINGS[i], IA_STRINGS[action]);
419 Node *GetNode(InputAction actions[NK_COUNT][IN_COUNT]) {
420 Node *result = NEW(Node); result->data = NEWSTR; result->kind = NK_Namespace;
427 InputMode mode = IM_Normal;
432 g_NodeDrawSelected = n;
434 g_NodeDrawSelected = NULL;
435 DrawInfo(actions, n->kind, mode);
437 if (mode == IM_Editing) {
439 char *s = (char*)n->data;
440 int slen = strlen(s);
442 if (c == KEY_BACKSPACE1 || c == KEY_BACKSPACE2) {
445 else if (c == '\n' || c == '\r') {
448 else if (slen < STR_SIZE) {
452 else if (mode == IM_Normal) {
458 action = actions[n->kind][in];
460 #define N(NAME, PARENT, KIND) Node *NAME = NEW(Node); NAME->kind = KIND; NodeAppend(PARENT, NAME);
461 #define S(NAME, PARENT, KIND) Node *NAME = NEW(Node); NAME->kind = KIND; NAME->data = NEWSTR; NodeAppend(PARENT, NAME);
464 case IA_MoveLeft: { if (n->prev != NULL) n = n->prev; break; }
465 case IA_MoveDown: { if (n->child != NULL) n = n->child; break; }
466 case IA_MoveUp: { if (n->parent != NULL) n = n->parent; break; }
467 case IA_MoveRight: { if (n->next != NULL) n = n->next; break; }
469 case IA_StartEditing: { mode = IM_Editing; break; }
470 case IA_Delete: { n = NodeRemove(n->parent, n); break; }
472 case IA_AddNamespace: { S(n1, n, NK_Namespace) n = n1; mode = IM_Editing; break; }
473 case IA_AddStruct: { S(n1, n, NK_Struct) n = n1; mode = IM_Editing; break; }
474 case IA_AddFunc: { S(n1, n, NK_Func) N(n2, n1, NK_VarList) N(n3, n1, NK_Body) n = n1; mode = IM_Editing; break; }
475 case IA_AddVar: { S(n1, n, NK_Var) n = n1; mode = IM_Editing; break; }
476 case IA_AddVarDecl: { S(n1, n, NK_VarDecl) S(n2, n1, NK_VarType) n = n1; mode = IM_Editing; break; }
477 case IA_AddType: { S(n1, n, NK_Type) n = n1; mode = IM_Editing; break; }
478 case IA_AddIf: { N(n1, n, NK_If) N(n2, n1, NK_ExprList) N(n3, n1, NK_Body) n = n2; break; }
479 case IA_AddWhile: { N(n1, n, NK_While) N(n2, n1, NK_ExprList) N(n3, n1, NK_Body) n = n2; break; }
480 case IA_AddNum: { S(n1, n, NK_Num) n = n1; mode = IM_Editing; break; }
481 case IA_AddStr: { S(n1, n, NK_Str) n = n1; mode = IM_Editing; break; }
482 case IA_AddCall: { S(n1, n, NK_Call) N(n2, n1, NK_ExprList) n = n1; mode = IM_Editing; break; }
483 case IA_AddOp: { S(n1, n, NK_Op) n = n1; mode = IM_Editing; break; }
495 void SetupInputActions(InputAction actions[NK_COUNT][IN_COUNT]) {
496 for (int i = 0; i < NK_COUNT; i++) {
497 actions[i][IN_H] = IA_MoveLeft;
498 actions[i][IN_J] = IA_MoveUp;
499 actions[i][IN_K] = IA_MoveDown;
500 actions[i][IN_L] = IA_MoveRight;
503 actions[NK_Namespace][IN_D] = IA_Delete;
504 actions[NK_Namespace][IN_SPACE] = IA_StartEditing;
505 actions[NK_Namespace][IN_N] = IA_AddNamespace;
506 actions[NK_Namespace][IN_S] = IA_AddStruct;
507 actions[NK_Namespace][IN_F] = IA_AddFunc;
509 actions[NK_Struct][IN_D] = IA_Delete;
510 actions[NK_Struct][IN_SPACE] = IA_StartEditing;
511 actions[NK_Struct][IN_V] = IA_AddVarDecl;
512 actions[NK_Struct][IN_F] = IA_AddFunc;
514 actions[NK_Func][IN_D] = IA_Delete;
515 actions[NK_Func][IN_SPACE] = IA_StartEditing;
517 actions[NK_VarList][IN_V] = IA_AddVarDecl;
519 actions[NK_ExprList][IN_V] = IA_AddVar;
520 actions[NK_ExprList][IN_I] = IA_AddIf;
521 actions[NK_ExprList][IN_W] = IA_AddWhile;
522 actions[NK_ExprList][IN_N] = IA_AddNum;
523 actions[NK_ExprList][IN_S] = IA_AddStr;
524 actions[NK_ExprList][IN_C] = IA_AddCall;
525 actions[NK_ExprList][IN_O] = IA_AddOp;
527 actions[NK_Var][IN_D] = IA_Delete;
528 actions[NK_Var][IN_SPACE] = IA_StartEditing;
530 actions[NK_VarDecl][IN_D] = IA_Delete;
531 actions[NK_VarDecl][IN_SPACE] = IA_StartEditing;
533 actions[NK_VarType][IN_SPACE] = IA_StartEditing;
534 actions[NK_VarType][IN_T] = IA_AddType;
536 actions[NK_Type][IN_D] = IA_Delete;
537 actions[NK_Type][IN_SPACE] = IA_StartEditing;
538 actions[NK_Type][IN_T] = IA_AddType;
540 actions[NK_Body][IN_F] = IA_AddFunc;
541 actions[NK_Body][IN_V] = IA_AddVarDecl;
542 actions[NK_Body][IN_I] = IA_AddIf;
543 actions[NK_Body][IN_W] = IA_AddWhile;
544 actions[NK_Body][IN_N] = IA_AddNum;
545 actions[NK_Body][IN_S] = IA_AddStr;
546 actions[NK_Body][IN_C] = IA_AddCall;
547 actions[NK_Body][IN_O] = IA_AddOp;
549 actions[NK_If][IN_D] = IA_Delete;
551 actions[NK_While][IN_D] = IA_Delete;
553 actions[NK_Num][IN_D] = IA_Delete;
554 actions[NK_Num][IN_SPACE] = IA_StartEditing;
556 actions[NK_Str][IN_D] = IA_Delete;
557 actions[NK_Str][IN_SPACE] = IA_StartEditing;
559 actions[NK_Call][IN_D] = IA_Delete;
560 actions[NK_Call][IN_SPACE] = IA_StartEditing;
562 actions[NK_Op][IN_D] = IA_Delete;
563 actions[NK_Op][IN_SPACE] = IA_StartEditing;
564 actions[NK_Op][IN_V] = IA_AddVar;
565 actions[NK_Op][IN_I] = IA_AddIf;
566 actions[NK_Op][IN_W] = IA_AddWhile;
567 actions[NK_Op][IN_N] = IA_AddNum;
568 actions[NK_Op][IN_S] = IA_AddStr;
569 actions[NK_Op][IN_C] = IA_AddCall;
570 actions[NK_Op][IN_O] = IA_AddOp;
575 static InputAction actions[NK_COUNT][IN_COUNT];
576 SetupInputActions(actions);
579 vt100EnableAlternateBuffer();
582 Node *n = GetNode(actions);
584 vt100DisableAlternateBuffer();