]> gitweb.ps.run Git - iftint/blobdiff - main3.c
update
[iftint] / main3.c
diff --git a/main3.c b/main3.c
index b2c1e9d88a478c2619ed3701c0ae7689290bf210..d6162a465451e8140e1f617b56c953de13ac8821 100644 (file)
--- a/main3.c
+++ b/main3.c
@@ -1,11 +1,16 @@
-#include<stdint.h>
-#include<stdbool.h>
-#include<stdio.h>
+#include <stdint.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <string.h>
+#include <assert.h>
+
 
 // Global defines
 
 #define STR_SIZE 128
 
 // Global defines
 
 #define STR_SIZE 128
-#define BUF_SIZE 1024*1024
+#define MEMORY_SIZE 1024*1024
+#define EDIT_QUEUE_SIZE 10
 
 // Memory
 
 
 // Memory
 
@@ -13,6 +18,8 @@ static char g_memory[1024*1024];
 static int g_memory_index = 0;
 
 void * alloc(int num, int size) {
 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;
     void * result = g_memory + g_memory_index;
     for (int i = 0; i < num*size; i++)
         g_memory[g_memory_index+i] = 0;
@@ -22,6 +29,7 @@ void * alloc(int num, int size) {
 
 #define NEW(TYPE) ((TYPE *)alloc(1, sizeof(TYPE)))
 #define NEWARR(TYPE, NUM) ((TYPE *)alloc(NUM, sizeof(TYPE)))
 
 #define NEW(TYPE) ((TYPE *)alloc(1, sizeof(TYPE)))
 #define NEWARR(TYPE, NUM) ((TYPE *)alloc(NUM, sizeof(TYPE)))
+#define NEWSTR NEWARR(char, STR_SIZE)
 
 // getch
 
 
 // getch
 
@@ -82,7 +90,7 @@ void vt100Escape(const char * str, ...) {
 
 void vt100ClearScreen() { vt100Escape("[2J"); }
 void vt100CursorHome() { vt100Escape("[H"); }
 
 void vt100ClearScreen() { vt100Escape("[2J"); }
 void vt100CursorHome() { vt100Escape("[H"); }
-void vt100CursorPos(int v, int h) { vt100Escape("[%d;%dH", v, h); }
+void vt100CursorPos(int v, int h) { vt100Escape("[%d;%df", v, h); }
 void vt100SaveCursor() { vt100Escape("7"); }
 void vt100RestoreCursor() { vt100Escape("8"); }
 void vt100EnableAlternateBuffer() { vt100Escape("[?1049h"); }
 void vt100SaveCursor() { vt100Escape("7"); }
 void vt100RestoreCursor() { vt100Escape("8"); }
 void vt100EnableAlternateBuffer() { vt100Escape("[?1049h"); }
@@ -100,20 +108,26 @@ void vt100GetScreenSize(int * v, int * h) {
 #else
     struct winsize w;
     ioctl(STDOUT_FILENO, TIOCGWINSZ, &w);
 #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
 }
 
 // Node
 
 typedef enum NodeKind {
 #endif
 }
 
 // Node
 
 typedef enum NodeKind {
+    NK_Namespace,
+    NK_Struct,
     NK_Func,
     NK_Func,
-    NK_ArgList,
+    NK_VarList,
     NK_ExprList,
     NK_Var,
     NK_ExprList,
     NK_Var,
+    NK_VarDecl,
+    NK_VarType,
+    NK_Type,
     NK_Body,
     NK_If,
     NK_Body,
     NK_If,
+    NK_While,
     NK_Num,
     NK_Str,
     NK_Call,
     NK_Num,
     NK_Str,
     NK_Call,
@@ -123,12 +137,18 @@ typedef enum NodeKind {
 } NodeKind;
 
 const char *NK_STRINGS[NK_COUNT] = {
 } NodeKind;
 
 const char *NK_STRINGS[NK_COUNT] = {
+    "NK_Namespace",
+    "NK_Struct",
     "NK_Func",
     "NK_Func",
-    "NK_ArgList",
+    "NK_VarList",
     "NK_ExprList",
     "NK_Var",
     "NK_ExprList",
     "NK_Var",
+    "NK_VarDecl",
+    "NK_VarType",
+    "NK_Type",
     "NK_Body",
     "NK_If",
     "NK_Body",
     "NK_If",
+    "NK_While",
     "NK_Num",
     "NK_Str",
     "NK_Call",
     "NK_Num",
     "NK_Str",
     "NK_Call",
@@ -141,14 +161,14 @@ struct Node {
     void * data;
 
     int childCount;
     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 *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;
     for (int i = 0; i < index; i++)
         result = result->next;
     return result;
@@ -156,7 +176,7 @@ Node *NodeGetChild(Node *n, unsigned int index) {
 
 void NodeAppend(Node *n1, Node *n2) {
     if (n1->childCount == 0) {
 
 void NodeAppend(Node *n1, Node *n2) {
     if (n1->childCount == 0) {
-        n1->child = n2;
+        n1->chld = n2;
     }
     else {
         Node *lastChild = NodeGetChild(n1, n1->childCount-1);
     }
     else {
         Node *lastChild = NodeGetChild(n1, n1->childCount-1);
@@ -165,7 +185,7 @@ void NodeAppend(Node *n1, Node *n2) {
         n2->prev = lastChild;
         n2->next = NULL;
     }
         n2->prev = lastChild;
         n2->next = NULL;
     }
-    n2->parent = n1;
+    n2->prnt = n1;
     n1->childCount += 1;
 }
 
     n1->childCount += 1;
 }
 
@@ -198,10 +218,10 @@ Node *NodeRemove(Node *n1, Node *n2) {
     if (next != NULL)
         next->prev = prev;
     
     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;
     
 
     n1->childCount -= 1;
     
@@ -211,27 +231,87 @@ Node *NodeRemove(Node *n1, Node *n2) {
         return prev;
 }
 
         return prev;
 }
 
-void NodeDraw(Node *n, Node *selected) {
+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;
     static int indent = 0;
-    #define INDENT for (int i = 0; i < indent; i++) printf("  ");
-    
-    vt100DisableNegative();
-    if (n == selected) vt100EnableNegative();
+    #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) {
     switch (n->kind) {
-    case NK_Func:    { printf("fn %s ", n->data); NodeDraw(NodeGetChild(n, 0), selected); printf("\n"); INDENT NodeDraw(NodeGetChild(n, 1), selected); break;         }
-    case NK_ExprList:
-    case NK_ArgList: { printf("("); for (int i = 0; i < n->childCount; i++) { if (i != 0) printf(" "); NodeDraw(NodeGetChild(n, i), selected); } printf(")"); break; }
-    case NK_Var:     { printf("var %s", n->data); break;                                                                                                       }
-    case NK_Body:    { printf("{\n"); indent++; for (int i = 0; i < n->childCount; i++) { INDENT NodeDraw(NodeGetChild(n, i), selected); printf("\n"); } indent--; INDENT printf("}\n"); break;  }
-    case NK_If:      { printf("if "); NodeDraw(NodeGetChild(n, 0), selected); printf("\n"); INDENT NodeDraw(NodeGetChild(n, 1), selected); break;                     }
-    case NK_Num:     { printf("%s", n->data); break;                                                                                                     }
-    case NK_Str:     { printf("'%s'", n->data); break;                                                                                                     }
-    case NK_Call:    { printf("call %s ", n->data); NodeDraw(NodeGetChild(n, 0), selected); break;                                                             }
-    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), selected); } 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(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(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; }
     }
     }
-
-    vt100DisableNegative();
 }
 
 // Input
 }
 
 // Input
@@ -243,17 +323,20 @@ void NodeDraw(Node *n, Node *selected) {
 typedef enum Input {
     IN_None,
 
 typedef enum Input {
     IN_None,
 
-    IN_SPACE,
-    IN_D,
-
     IN_H,
     IN_J,
     IN_K,
     IN_L,
 
     IN_H,
     IN_J,
     IN_K,
     IN_L,
 
+    IN_SPACE,
+    IN_D,
+    IN_A,
+
     IN_F,
     IN_V,
     IN_F,
     IN_V,
+    IN_T,
     IN_I,
     IN_I,
+    IN_W,
     IN_N,
     IN_S,
     IN_C,
     IN_N,
     IN_S,
     IN_C,
@@ -267,17 +350,20 @@ typedef enum Input {
 const char *IN_STRINGS[IN_COUNT] = {
     "IN_None",
 
 const char *IN_STRINGS[IN_COUNT] = {
     "IN_None",
 
-    "IN_SPACE",
-    "IN_D",
-
     "IN_H",
     "IN_J",
     "IN_K",
     "IN_L",
 
     "IN_H",
     "IN_J",
     "IN_K",
     "IN_L",
 
+    "IN_SPACE",
+    "IN_D",
+    "IN_A",
+
     "IN_F",
     "IN_V",
     "IN_F",
     "IN_V",
+    "IN_T",
     "IN_I",
     "IN_I",
+    "IN_W",
     "IN_N",
     "IN_S",
     "IN_C",
     "IN_N",
     "IN_S",
     "IN_C",
@@ -292,17 +378,19 @@ Input InputGet() {
     while (true) {
         c = getch();
         switch (c) {
     while (true) {
         c = getch();
         switch (c) {
-            case ' ': return IN_SPACE;
-            case 'd': return IN_D;
-            
             case 'h': return IN_H;
             case 'j': return IN_J;
             case 'k': return IN_K;
             case 'l': return IN_L;
 
             case 'h': return IN_H;
             case 'j': return IN_J;
             case 'k': return IN_K;
             case 'l': return IN_L;
 
+            case ' ': return IN_SPACE;
+            case 'd': return IN_D;
+            
             case 'f': return IN_F;
             case 'v': return IN_V;
             case 'f': return IN_F;
             case 'v': return IN_V;
+            case 't': return IN_T;
             case 'i': return IN_I;
             case 'i': return IN_I;
+            case 'w': return IN_W;
             case 'n': return IN_N;
             case 's': return IN_S;
             case 'c': return IN_C;
             case 'n': return IN_N;
             case 's': return IN_S;
             case 'c': return IN_C;
@@ -316,17 +404,22 @@ Input InputGet() {
 typedef enum InputAction {
     IA_None,
 
 typedef enum InputAction {
     IA_None,
 
-    IA_StartEditing,
-    IA_Delete,
-
     IA_MoveLeft,
     IA_MoveUp,
     IA_MoveDown,
     IA_MoveRight,
 
     IA_MoveLeft,
     IA_MoveUp,
     IA_MoveDown,
     IA_MoveRight,
 
+    IA_StartEditing,
+    IA_Delete,
+
+    IA_AddNamespace,
+    IA_AddStruct,
     IA_AddFunc,
     IA_AddVar,
     IA_AddFunc,
     IA_AddVar,
+    IA_AddVarDecl,
+    IA_AddType,
     IA_AddIf,
     IA_AddIf,
+    IA_AddWhile,
     IA_AddNum,
     IA_AddStr,
     IA_AddCall,
     IA_AddNum,
     IA_AddStr,
     IA_AddCall,
@@ -338,33 +431,46 @@ typedef enum InputAction {
 const char *IA_STRINGS[IA_COUNT] = {
     "IA_None",
 
 const char *IA_STRINGS[IA_COUNT] = {
     "IA_None",
 
-    "IA_StartEditing",
-    "IA_Delete",
-
     "IA_MoveLeft",
     "IA_MoveUp",
     "IA_MoveDown",
     "IA_MoveRight",
 
     "IA_MoveLeft",
     "IA_MoveUp",
     "IA_MoveDown",
     "IA_MoveRight",
 
+    "IA_StartEditing",
+    "IA_Delete",
+
+    "IA_AddNamespace",
+    "IA_AddStruct",
     "IA_AddFunc",
     "IA_AddVar",
     "IA_AddFunc",
     "IA_AddVar",
+    "IA_AddVarDecl",
+    "IA_AddType",
     "IA_AddIf",
     "IA_AddIf",
+    "IA_AddWhile",
     "IA_AddNum",
     "IA_AddStr",
     "IA_AddCall",
     "IA_AddOp",
 };
 
     "IA_AddNum",
     "IA_AddStr",
     "IA_AddCall",
     "IA_AddOp",
 };
 
-void DrawInfo(InputAction actions[NK_COUNT][IN_COUNT], NodeKind nk) {
+typedef enum InputMode {
+    IM_Normal,
+    IM_Editing,
+} InputMode;
+
+void DrawInfo(InputAction actions[NK_COUNT][IN_COUNT], NodeKind nk, InputMode mode) {
     int v, h;
     vt100GetScreenSize(&v, &h);
 
     int line = 2;
 
     vt100CursorPos(line++, h-30);
     int v, h;
     vt100GetScreenSize(&v, &h);
 
     int line = 2;
 
     vt100CursorPos(line++, h-30);
-    printf("%s:", NK_STRINGS[nk]);
+    printf("%d:%d", v, h);
+    vt100CursorPos(line++, h-30);
 
 
-    for (int i = 0; i < IN_COUNT; i++) {
+    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-30);
         InputAction action = actions[nk][i];
         if (action != IA_None) {
             vt100CursorPos(line++, h-30);
@@ -373,26 +479,84 @@ void DrawInfo(InputAction actions[NK_COUNT][IN_COUNT], NodeKind nk) {
     }
 }
 
     }
 }
 
+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 *GetNode(InputAction actions[NK_COUNT][IN_COUNT]) {
-    Node *result = NEW(Node); result->kind = NK_Body;
+    Node *result = NEW(Node); result->data = NEWSTR; result->kind = NK_Namespace;
 
     Node * n = result;
 
     Node * n = result;
+    Node * q[EDIT_QUEUE_SIZE] = {0};
 
     Input in;
     InputAction action;
 
 
     Input in;
     InputAction action;
 
-    enum {
-        Mode_Normal,
-        Mode_Editing,
-    } mode = Mode_Normal;
+    InputMode mode = IM_Normal;
 
     while (true) {
         vt100ClearScreen();
         vt100CursorHome();
 
     while (true) {
         vt100ClearScreen();
         vt100CursorHome();
-        NodeDraw(result, n);
-        DrawInfo(actions, n->kind);
+        g_NodeDrawSelected = n;
+        NodeDraw(result);
+        g_NodeDrawSelected = NULL;
+        DrawInfo(actions, n->kind, mode);
 
 
-        if (mode == Mode_Editing) {
+        if (mode == IM_Editing) {
             int c = getch();
             char *s = (char*)n->data;
             int slen = strlen(s);
             int c = getch();
             char *s = (char*)n->data;
             int slen = strlen(s);
@@ -401,13 +565,16 @@ Node *GetNode(InputAction actions[NK_COUNT][IN_COUNT]) {
                 s[slen-1] = '\0';
             }
             else if (c == '\n' || c == '\r') {
                 s[slen-1] = '\0';
             }
             else if (c == '\n' || c == '\r') {
-                mode = Mode_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;
             }
         }
                 s[slen++] = (char)c;
             }
         }
-        else if (mode == Mode_Normal) {
+        else if (mode == IM_Normal) {
             in = InputGet();
 
             if (in == IN_Quit)
             in = InputGet();
 
             if (in == IN_Quit)
@@ -415,29 +582,42 @@ Node *GetNode(InputAction actions[NK_COUNT][IN_COUNT]) {
 
             action = actions[n->kind][in];
 
 
             action = actions[n->kind][in];
 
-            #define NA(NAME, PARENT, KIND) Node *NAME = NEW(Node); NAME->kind = KIND; NodeAppend(PARENT, NAME);
-            #define NS(NAME, PARENT, KIND) Node *NAME = NEW(Node); NAME->kind = KIND; NAME->data = NEWARR(char, STR_SIZE); NodeAppend(PARENT, NAME);
+            #define N(NAME, PARENT, KIND) Node *NAME = NEW(Node); NAME->kind = KIND; NodeAppend(PARENT, NAME);
+            #define S(NAME, PARENT, KIND) Node *NAME = NEW(Node); NAME->kind = KIND; NAME->data = NEWSTR; NodeAppend(PARENT, NAME);
 
             switch (action) {
 
             switch (action) {
-            case IA_StartEditing: { mode = Mode_Editing; break; }
-            case IA_Delete: { n = NodeRemove(n->parent, n); break; }
-
-            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_MoveRight: { if (n->next != NULL) n = n->next; break; }
             
-            case IA_AddFunc: { NS(n1, n, NK_Func) NA(n2, n1, NK_ArgList)  NA(n3, n1, NK_Body) n = n1; mode = Mode_Editing; break; }
-            case IA_AddVar:  { NS(n1, n, NK_Var)                                              n = n1; mode = Mode_Editing; break; }
-            case IA_AddIf:   { NA(n1, n, NK_If)   NA(n2, n1, NK_ExprList) NA(n3, n1, NK_Body) n = n1;                      break; }
-            case IA_AddNum:  { NS(n1, n, NK_Num)                                              n = n1; mode = Mode_Editing; break; }
-            case IA_AddStr:  { NS(n1, n, NK_Str)                                              n = n1; mode = Mode_Editing; break; }
-            case IA_AddCall: { NS(n1, n, NK_Call) NA(n2, n1, NK_ExprList)                     n = n1; mode = Mode_Editing; break; }
-            case IA_AddOp:   { NS(n1, n, NK_Op)                                               n = n1; mode = Mode_Editing; break; }
+            case IA_StartEditing: { 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 NA
-            #undef NS
+            #undef N
+            #undef S
         }
     }
 
         }
     }
 
@@ -445,24 +625,33 @@ Node *GetNode(InputAction actions[NK_COUNT][IN_COUNT]) {
 }
 
 
 }
 
 
-int main() {
-    // Setup
-    static InputAction actions[NK_COUNT][IN_COUNT];
-
+void SetupInputActions(InputAction actions[NK_COUNT][IN_COUNT]) {
     for (int i = 0; i < NK_COUNT; i++) {
         actions[i][IN_H] = IA_MoveLeft;
     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;
     }
 
         actions[i][IN_L] = IA_MoveRight;
     }
 
+    actions[NK_Namespace][IN_D] = IA_Delete;
+    actions[NK_Namespace][IN_SPACE] = IA_StartEditing;
+    actions[NK_Namespace][IN_N] = IA_AddNamespace;
+    actions[NK_Namespace][IN_S] = IA_AddStruct;
+    actions[NK_Namespace][IN_F] = IA_AddFunc;
+    
+    actions[NK_Struct][IN_D] = IA_Delete;
+    actions[NK_Struct][IN_SPACE] = IA_StartEditing;
+    actions[NK_Struct][IN_V] = IA_AddVarDecl;
+    actions[NK_Struct][IN_F] = IA_AddFunc;
+
     actions[NK_Func][IN_D] = IA_Delete;
     actions[NK_Func][IN_SPACE] = IA_StartEditing;
 
     actions[NK_Func][IN_D] = IA_Delete;
     actions[NK_Func][IN_SPACE] = IA_StartEditing;
 
-    actions[NK_ArgList][IN_V] = IA_AddVar;
+    actions[NK_VarList][IN_V] = IA_AddVarDecl;
     
     actions[NK_ExprList][IN_V] = IA_AddVar;
     actions[NK_ExprList][IN_I] = IA_AddIf;
     
     actions[NK_ExprList][IN_V] = IA_AddVar;
     actions[NK_ExprList][IN_I] = IA_AddIf;
+    actions[NK_ExprList][IN_W] = IA_AddWhile;
     actions[NK_ExprList][IN_N] = IA_AddNum;
     actions[NK_ExprList][IN_S] = IA_AddStr;
     actions[NK_ExprList][IN_C] = IA_AddCall;
     actions[NK_ExprList][IN_N] = IA_AddNum;
     actions[NK_ExprList][IN_S] = IA_AddStr;
     actions[NK_ExprList][IN_C] = IA_AddCall;
@@ -471,9 +660,20 @@ int main() {
     actions[NK_Var][IN_D] = IA_Delete;
     actions[NK_Var][IN_SPACE] = IA_StartEditing;
 
     actions[NK_Var][IN_D] = IA_Delete;
     actions[NK_Var][IN_SPACE] = IA_StartEditing;
 
+    actions[NK_VarDecl][IN_D] = IA_Delete;
+    actions[NK_VarDecl][IN_SPACE] = IA_StartEditing;
+
+    actions[NK_VarType][IN_SPACE] = IA_StartEditing;
+    actions[NK_VarType][IN_T] = IA_AddType;
+
+    actions[NK_Type][IN_D] = IA_Delete;
+    actions[NK_Type][IN_SPACE] = IA_StartEditing;
+    actions[NK_Type][IN_T] = IA_AddType;
+
     actions[NK_Body][IN_F] = IA_AddFunc;
     actions[NK_Body][IN_F] = IA_AddFunc;
-    actions[NK_Body][IN_V] = IA_AddVar;
+    actions[NK_Body][IN_V] = IA_AddVarDecl;
     actions[NK_Body][IN_I] = IA_AddIf;
     actions[NK_Body][IN_I] = IA_AddIf;
+    actions[NK_Body][IN_W] = IA_AddWhile;
     actions[NK_Body][IN_N] = IA_AddNum;
     actions[NK_Body][IN_S] = IA_AddStr;
     actions[NK_Body][IN_C] = IA_AddCall;
     actions[NK_Body][IN_N] = IA_AddNum;
     actions[NK_Body][IN_S] = IA_AddStr;
     actions[NK_Body][IN_C] = IA_AddCall;
@@ -481,6 +681,8 @@ int main() {
 
     actions[NK_If][IN_D] = IA_Delete;
 
 
     actions[NK_If][IN_D] = IA_Delete;
 
+    actions[NK_While][IN_D] = IA_Delete;
+
     actions[NK_Num][IN_D] = IA_Delete;
     actions[NK_Num][IN_SPACE] = IA_StartEditing;
 
     actions[NK_Num][IN_D] = IA_Delete;
     actions[NK_Num][IN_SPACE] = IA_StartEditing;
 
@@ -494,10 +696,17 @@ int main() {
     actions[NK_Op][IN_SPACE] = IA_StartEditing;
     actions[NK_Op][IN_V] = IA_AddVar;
     actions[NK_Op][IN_I] = IA_AddIf;
     actions[NK_Op][IN_SPACE] = IA_StartEditing;
     actions[NK_Op][IN_V] = IA_AddVar;
     actions[NK_Op][IN_I] = IA_AddIf;
+    actions[NK_Op][IN_W] = IA_AddWhile;
     actions[NK_Op][IN_N] = IA_AddNum;
     actions[NK_Op][IN_S] = IA_AddStr;
     actions[NK_Op][IN_C] = IA_AddCall;
     actions[NK_Op][IN_O] = IA_AddOp;
     actions[NK_Op][IN_N] = IA_AddNum;
     actions[NK_Op][IN_S] = IA_AddStr;
     actions[NK_Op][IN_C] = IA_AddCall;
     actions[NK_Op][IN_O] = IA_AddOp;
+}
+
+int main() {
+    // Setup
+    static InputAction actions[NK_COUNT][IN_COUNT];
+    SetupInputActions(actions);
 
     // Main
     vt100EnableAlternateBuffer();
 
     // Main
     vt100EnableAlternateBuffer();
@@ -508,11 +717,8 @@ int main() {
     vt100DisableAlternateBuffer();
     vt100ShowCursor();
 
     vt100DisableAlternateBuffer();
     vt100ShowCursor();
 
-    int v, h;
-    vt100GetScreenSize(&v, &h);
-    printf("Screen Size: %d | %d\n", v, h);
-
-    NodeDraw(n, NULL);
+    NodeDraw(n);
+    printf("\n");
 
     return 0;
 }
 
     return 0;
 }