]> gitweb.ps.run Git - iftint/blob - main3.c
Test with custom printf
[iftint] / main3.c
1 #include <stdint.h>
2 #include <stdbool.h>
3 #include <stdio.h>
4 #include <stdarg.h>
5
6
7 // Global defines
8
9 #define STR_SIZE 128
10 #define BUF_SIZE 1024*1024
11
12 // Memory
13
14 static char g_memory[1024*1024];
15 static int g_memory_index = 0;
16
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;
22     return result;
23 }
24
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)
28
29 // getch
30
31 #ifdef _WIN32
32 #include <windows.h>
33 #include <conio.h>
34 #else
35 #include <sys/ioctl.h>
36 #include <termios.h>
37 #include <unistd.h>
38 #include <stdio.h>
39
40 /* reads from keypress, doesn't echo */
41 int getch(void)
42 {
43     struct termios oldattr, newattr;
44     int ch;
45     tcgetattr( STDIN_FILENO, &oldattr );
46     newattr = oldattr;
47     newattr.c_lflag &= ~( ICANON | ECHO ); // no ECHO for echo(?)
48     tcsetattr( STDIN_FILENO, TCSANOW, &newattr );
49     ch = getchar();
50     tcsetattr( STDIN_FILENO, TCSANOW, &oldattr );
51     return ch;
52 }
53
54 /* ungets keypress */
55 void ungetch(int ch)
56 {
57     struct termios oldattr, newattr;
58     tcgetattr( STDIN_FILENO, &oldattr );
59     newattr = oldattr;
60     newattr.c_lflag &= ~( ICANON | ECHO );
61     tcsetattr( STDIN_FILENO, TCSANOW, &newattr );
62     ungetc(ch, stdin);
63     tcsetattr( STDIN_FILENO, TCSANOW, &oldattr );
64 }
65 #endif
66
67 int
68 peekch() {
69     int c = getch();
70     ungetch(c);
71     return c;
72 }
73
74 // VT100
75
76 #define ASCII_ESC 27
77
78 void vt100Escape(const char * str, ...) {
79     va_list args;
80     va_start(args, str);
81
82     printf("%c", ASCII_ESC);
83     vprintf(str, args);
84 }
85
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) {
98 #ifdef _WIN32
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;
103 #else
104     struct winsize w;
105     ioctl(STDOUT_FILENO, TIOCGWINSZ, &w);
106     *h = w.ws_row;
107     *v = w.ws_col;
108 #endif
109 }
110
111 // Node
112
113 typedef enum NodeKind {
114     NK_Namespace,
115     NK_Struct,
116     NK_Func,
117     NK_VarList,
118     NK_ExprList,
119     NK_Var,
120     NK_VarDecl,
121     NK_VarType,
122     NK_Type,
123     NK_Body,
124     NK_If,
125     NK_While,
126     NK_Num,
127     NK_Str,
128     NK_Call,
129     NK_Op,
130
131     NK_COUNT
132 } NodeKind;
133
134 const char *NK_STRINGS[NK_COUNT] = {
135     "NK_Namespace",
136     "NK_Struct",
137     "NK_Func",
138     "NK_VarList",
139     "NK_ExprList",
140     "NK_Var",
141     "NK_VarDecl",
142     "NK_VarType",
143     "NK_Type",
144     "NK_Body",
145     "NK_If",
146     "NK_While",
147     "NK_Num",
148     "NK_Str",
149     "NK_Call",
150     "NK_Op",
151 };
152
153 typedef struct Node Node;
154 struct Node {
155     NodeKind kind;
156     void * data;
157
158     int childCount;
159     Node *next, *prev, *parent, *child;
160 };
161
162 Node *NodeGetChild(Node *n, unsigned int index) {
163     if (index >= n->childCount)
164         return NULL;
165     
166     Node *result = n->child;
167     for (int i = 0; i < index; i++)
168         result = result->next;
169     return result;
170 }
171
172 void NodeAppend(Node *n1, Node *n2) {
173     if (n1->childCount == 0) {
174         n1->child = n2;
175     }
176     else {
177         Node *lastChild = NodeGetChild(n1, n1->childCount-1);
178
179         lastChild->next = n2;
180         n2->prev = lastChild;
181         n2->next = NULL;
182     }
183     n2->parent = n1;
184     n1->childCount += 1;
185 }
186
187 void NodeInsert(Node *n1, Node *n2, unsigned int index) {
188     if (index >= n1->childCount-1) {
189         NodeAppend(n1, n2);
190         return;
191     }
192
193     Node *insertAfter = NodeGetChild(n1, index);
194     Node *insertBefore = NodeGetChild(n1, index+1);
195
196     insertAfter->next = n2;
197     insertBefore->prev = n2;
198     n2->prev = insertAfter;
199     n2->next = insertBefore;
200
201     n1->childCount += 1;
202 }
203
204 Node *NodeRemove(Node *n1, Node *n2) {
205     if (n1 == NULL)
206         return n2;
207     
208     Node *prev = n2->prev;
209     Node *next = n2->next;
210
211     if (prev != NULL)
212         prev->next = next;
213     if (next != NULL)
214         next->prev = prev;
215     
216     n2->prev = n2->next = n2->parent = NULL;
217
218     if (n2 == n1->child)
219         n1->child = next;
220
221     n1->childCount -= 1;
222     
223     if (prev == NULL)
224         return n1;
225     else
226         return prev;
227 }
228
229 void NodeDraw(Node *n);
230 Node *g_NodeDrawSelected;
231
232 void Printf(char* format, ...)
233 {
234   va_list argp;
235   va_start(argp, format);
236   while (*format != '\0') {
237     if (*format == '%') {
238       format++;
239       if (*format == '%') {
240         putchar('%');
241       } else if (*format == 'n') {
242         Node *n = va_arg(argp, Node*);
243         NodeDraw(n);
244       } else if (*format == 's') {
245         char *s = va_arg(argp, char*);
246         printf("%s", s);
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));
252         }
253         format++;
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));
259         }
260         format++;
261       } else {
262         fputs("Not implemented", stdout);
263       }
264     } else if (*format == '_') {
265         static bool highlighted = false;
266         if (highlighted) {
267             vt100DisableNegative();
268             highlighted = false;
269         }
270         else if (g_NodeDrawSelected == n) {
271             vt100EnableNegative();
272             highlighted = true;
273         }
274     } else {
275       putchar(*format);
276     }
277     format++;
278   }
279   va_end(argp);
280 }
281
282 void NodeDraw(Node *n) {
283     static int indent = 0;
284     #define INDENT printf("\n"); for (int i = 0; i < indent; i++) printf("  ");
285     
286     #define PRINTF(...) do { if (n == g_NodeDrawSelected) vt100EnableNegative(); printf(__VA_ARGS__); vt100DisableNegative(); } while(0);
287
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; }
292     // case NK_VarList:
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; }
296     // case NK_VarType:
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; }
305     // }
306
307     switch (n->kind) {
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; }
311     case NK_VarList:
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; }
315     case NK_VarType:
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; }
324     }
325 }
326
327 // Input
328
329 #define KEY_CTRL_C 3
330 #define KEY_BACKSPACE1 8
331 #define KEY_BACKSPACE2 127
332
333 typedef enum Input {
334     IN_None,
335
336     IN_SPACE,
337     IN_D,
338     IN_A,
339
340     IN_H,
341     IN_J,
342     IN_K,
343     IN_L,
344
345     IN_F,
346     IN_V,
347     IN_T,
348     IN_I,
349     IN_W,
350     IN_N,
351     IN_S,
352     IN_C,
353     IN_O,
354
355     IN_Quit,
356
357     IN_COUNT
358 } Input;
359
360 const char *IN_STRINGS[IN_COUNT] = {
361     "IN_None",
362
363     "IN_SPACE",
364     "IN_D",
365     "IN_A",
366
367     "IN_H",
368     "IN_J",
369     "IN_K",
370     "IN_L",
371
372     "IN_F",
373     "IN_V",
374     "IN_T",
375     "IN_I",
376     "IN_W",
377     "IN_N",
378     "IN_S",
379     "IN_C",
380     "IN_O",
381
382     "IN_Quit",
383 };
384
385 Input InputGet() {
386     int c;
387
388     while (true) {
389         c = getch();
390         switch (c) {
391             case ' ': return IN_SPACE;
392             case 'd': return IN_D;
393             
394             case 'h': return IN_H;
395             case 'j': return IN_J;
396             case 'k': return IN_K;
397             case 'l': return IN_L;
398
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;
408
409             case 'q': return IN_Quit;
410         }
411     }
412 }
413
414 typedef enum InputAction {
415     IA_None,
416
417     IA_StartEditing,
418     IA_Delete,
419
420     IA_MoveLeft,
421     IA_MoveUp,
422     IA_MoveDown,
423     IA_MoveRight,
424
425     IA_AddNamespace,
426     IA_AddStruct,
427     IA_AddFunc,
428     IA_AddVar,
429     IA_AddVarDecl,
430     IA_AddType,
431     IA_AddIf,
432     IA_AddWhile,
433     IA_AddNum,
434     IA_AddStr,
435     IA_AddCall,
436     IA_AddOp,
437
438     IA_COUNT
439 } InputAction;
440
441 const char *IA_STRINGS[IA_COUNT] = {
442     "IA_None",
443
444     "IA_StartEditing",
445     "IA_Delete",
446
447     "IA_MoveLeft",
448     "IA_MoveUp",
449     "IA_MoveDown",
450     "IA_MoveRight",
451
452     "IA_AddNamespace",
453     "IA_AddStruct",
454     "IA_AddFunc",
455     "IA_AddVar",
456     "IA_AddVarDecl",
457     "IA_AddType",
458     "IA_AddIf",
459     "IA_AddWhile",
460     "IA_AddNum",
461     "IA_AddStr",
462     "IA_AddCall",
463     "IA_AddOp",
464 };
465
466 typedef enum InputMode {
467     IM_Normal,
468     IM_Editing,
469 } InputMode;
470
471 void DrawInfo(InputAction actions[NK_COUNT][IN_COUNT], NodeKind nk, InputMode mode) {
472     int v, h;
473     vt100GetScreenSize(&v, &h);
474
475     int line = 2;
476
477     vt100CursorPos(line++, h-30);
478     printf("%s:%s", NK_STRINGS[nk], (mode == IM_Normal ? "" : " (editing)"));
479
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]);
485         }
486     }
487 }
488
489 Node *GetNode(InputAction actions[NK_COUNT][IN_COUNT]) {
490     Node *result = NEW(Node); result->data = NEWSTR; result->kind = NK_Namespace;
491
492     Node * n = result;
493
494     Input in;
495     InputAction action;
496
497     InputMode mode = IM_Normal;
498
499     while (true) {
500         vt100ClearScreen();
501         vt100CursorHome();
502         g_NodeDrawSelected = n;
503         NodeDraw(result);
504         g_NodeDrawSelected = NULL;
505         DrawInfo(actions, n->kind, mode);
506
507         if (mode == IM_Editing) {
508             int c = getch();
509             char *s = (char*)n->data;
510             int slen = strlen(s);
511             
512             if (c == KEY_BACKSPACE1 || c == KEY_BACKSPACE2) {
513                 s[slen-1] = '\0';
514             }
515             else if (c == '\n' || c == '\r') {
516                 mode = IM_Normal;
517             }
518             else if (slen < STR_SIZE) {
519                 s[slen++] = (char)c;
520             }
521         }
522         else if (mode == IM_Normal) {
523             in = InputGet();
524
525             if (in == IN_Quit)
526                 break;
527
528             action = actions[n->kind][in];
529
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);
532
533             switch (action) {
534             case IA_StartEditing: { mode = IM_Editing; break; }
535             case IA_Delete: { n = NodeRemove(n->parent, n); break; }
536
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; }
541             
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; }
554             }
555
556             #undef NA
557             #undef NS
558         }
559     }
560
561     return result;
562 }
563
564
565 int main() {
566     // Setup
567     static InputAction actions[NK_COUNT][IN_COUNT];
568
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;
574     }
575
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;
581     
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;
586
587     actions[NK_Func][IN_D] = IA_Delete;
588     actions[NK_Func][IN_SPACE] = IA_StartEditing;
589
590     actions[NK_VarList][IN_V] = IA_AddVarDecl;
591     
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;
599
600     actions[NK_Var][IN_D] = IA_Delete;
601     actions[NK_Var][IN_SPACE] = IA_StartEditing;
602
603     actions[NK_VarDecl][IN_D] = IA_Delete;
604     actions[NK_VarDecl][IN_SPACE] = IA_StartEditing;
605
606     actions[NK_VarType][IN_SPACE] = IA_StartEditing;
607     actions[NK_VarType][IN_T] = IA_AddType;
608
609     actions[NK_Type][IN_D] = IA_Delete;
610     actions[NK_Type][IN_SPACE] = IA_StartEditing;
611     actions[NK_Type][IN_T] = IA_AddType;
612
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;
621
622     actions[NK_If][IN_D] = IA_Delete;
623
624     actions[NK_While][IN_D] = IA_Delete;
625
626     actions[NK_Num][IN_D] = IA_Delete;
627     actions[NK_Num][IN_SPACE] = IA_StartEditing;
628
629     actions[NK_Str][IN_D] = IA_Delete;
630     actions[NK_Str][IN_SPACE] = IA_StartEditing;
631
632     actions[NK_Call][IN_D] = IA_Delete;
633     actions[NK_Call][IN_SPACE] = IA_StartEditing;
634
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;
644
645     // Main
646     vt100EnableAlternateBuffer();
647     vt100HideCursor();
648
649     Node *n = GetNode(actions);
650
651     vt100DisableAlternateBuffer();
652     vt100ShowCursor();
653
654     int v, h;
655     vt100GetScreenSize(&v, &h);
656     printf("Screen Size: %d | %d\n", v, h);
657
658     NodeDraw(n);
659
660     return 0;
661 }