瀏覽代碼

Escape sequences

Kajetan Johannes Hammerle 5 天之前
父節點
當前提交
b7d10ab3e3
共有 17 個文件被更改,包括 178 次插入109 次删除
  1. 3 1
      examples/term.basic
  2. 55 8
      src/SystemFunctions.c
  3. 14 0
      src/Tokenizer.c
  4. 7 7
      test/Add.basic
  5. 10 10
      test/Array.basic
  6. 18 18
      test/Condition.basic
  7. 3 0
      test/Escape.basic
  8. 3 0
      test/Escape.basic_result
  9. 3 3
      test/For.basic
  10. 4 4
      test/Function.basic
  11. 3 3
      test/Function2.basic
  12. 6 6
      test/Function3.basic
  13. 7 7
      test/If.basic
  14. 27 27
      test/Logic.basic
  15. 3 3
      test/Print.basic
  16. 9 9
      test/Var.basic
  17. 3 3
      test/While.basic

+ 3 - 1
examples/term.basic

@@ -1,6 +1,7 @@
-setPrintNewline(0)
 hideCursor()
 clear()
+resetCursor()
+flush()
 
 x = getWidth() / 2
 y = getHeight() / 2
@@ -25,6 +26,7 @@ for i = 0 to 500
     moveCursorRight(x)
     moveCursorDown(y)
     print("X")
+    flush()
     sleep(0, 1000000)
 end
 sleep(2, 0)

+ 55 - 8
src/SystemFunctions.c

@@ -3,7 +3,9 @@
 #include <stdio.h>
 #include <string.h>
 #include <sys/ioctl.h>
+#include <termios.h>
 #include <threads.h>
+#include <unistd.h>
 
 #include "Memory.h"
 
@@ -12,7 +14,8 @@
     return false
 
 static u32 seed = 0;
-static bool printNewline = true;
+static bool rawMode = false;
+static struct termios originalTerminal;
 
 static bool sfPrint(Code* c, Value* r, Value* vs, i32 n) {
     for(i32 i = 0; i < n; i++) {
@@ -25,15 +28,13 @@ static bool sfPrint(Code* c, Value* r, Value* vs, i32 n) {
                 break;
         }
     }
-    if(printNewline) {
-        putchar('\n');
-    }
     RETURN_INT(0);
 }
 
-static bool sfSetPrintNewline(Code*, Value* r, Value* vs, i32) {
-    printNewline = vs[0].data;
-    RETURN_INT(0);
+static bool sfPrintLine(Code* c, Value* r, Value* vs, i32 n) {
+    bool b = sfPrint(c, r, vs, n);
+    putchar('\n');
+    return b;
 }
 
 #define ESC "\33["
@@ -155,6 +156,48 @@ static bool sfGetAllocations(Code* c, Value* r, Value*, i32) {
     RETURN_INT(counter);
 }
 
+static bool sfEnterRawTerminal(Code* c, Value* r, Value*, i32) {
+    if(rawMode) {
+        RETURN_INT(0);
+    }
+    if(tcgetattr(STDIN_FILENO, &originalTerminal)) {
+        SET_ERROR("Cannot safe current terminal mode");
+        return true;
+    }
+    struct termios raw = originalTerminal;
+    raw.c_iflag &= ~(tcflag_t)(ICRNL | IXON);
+    raw.c_lflag &= ~(tcflag_t)(ECHO | ICANON | IEXTEN | ISIG);
+    raw.c_cc[VMIN] = 0;
+    raw.c_cc[VTIME] = 0;
+    if(tcsetattr(STDIN_FILENO, TCSANOW, &raw)) {
+        SET_ERROR("Cannot enter raw terminal mode");
+        return true;
+    }
+    RETURN_INT(0);
+}
+
+static bool sfLeaveRawTerminal(Code* c, Value* r, Value*, i32) {
+    if(!rawMode) {
+        RETURN_INT(0);
+    }
+    if(tcsetattr(STDIN_FILENO, TCSAFLUSH, &originalTerminal)) {
+        SET_ERROR("Cannot leave raw terminal mode");
+        return true;
+    }
+    RETURN_INT(0);
+}
+
+static bool sfReadChar(Code*, Value* r, Value*, i32) {
+    u8 ch = 0;
+    ssize_t bytes = read(STDIN_FILENO, &ch, 1);
+    RETURN_INT(bytes <= 0 ? '\0' : ch);
+}
+
+static bool sfFlush(Code*, Value* r, Value*, i32) {
+    fflush(stdout);
+    RETURN_INT(0);
+}
+
 typedef struct {
     SystemFunction function;
     i32 arguments;
@@ -163,7 +206,7 @@ typedef struct {
 
 static FunctionEntry systemFunctions[] = {
     {sfPrint, -1, "print"},
-    {sfSetPrintNewline, 1, "setPrintNewline"},
+    {sfPrintLine, -1, "printLine"},
     {sfClear, 0, "clear"},
     {sfSleep, 2, "sleep"},
     {sfGetWidth, 0, "getWidth"},
@@ -179,6 +222,10 @@ static FunctionEntry systemFunctions[] = {
     {sfRandom, 2, "random"},
     {sfArray, 1, "array"},
     {sfGetAllocations, 0, "getAllocations"},
+    {sfEnterRawTerminal, 0, "enterRawTerminal"},
+    {sfLeaveRawTerminal, 0, "leaveRawTerminal"},
+    {sfReadChar, 0, "readChar"},
+    {sfFlush, 0, "flush"},
 };
 static constexpr i32 amount = sizeof(systemFunctions) / sizeof(FunctionEntry);
 

+ 14 - 0
src/Tokenizer.c

@@ -120,6 +120,17 @@ static const char* tokenizerAddNumber(TState* t, const char* s) {
     return s;
 }
 
+static char mapEscapeSequence(TState* t, const char* s) {
+    static char map[][2] = {
+        {'n', '\n'}, {'t', '\t'}, {'r', '\r'}, {'\\', '\\'}, {'#', '\0'}};
+    for(size_t i = 0; map[i][0] != '#'; i++) {
+        if(s[1] == map[i][0]) {
+            return map[i][1];
+        }
+    }
+    THROW_ERROR("Unknown escape sequence");
+}
+
 static const char* tokenizerAddString(TState* t, const char* s) {
     tAddToken(t, TT_STRING);
     size_t index = 0;
@@ -133,6 +144,9 @@ static const char* tokenizerAddString(TState* t, const char* s) {
             break;
         } else if(index >= sizeof(buffer) - 1) {
             THROW_ERROR("Too long string");
+        } else if(c == '\\') {
+            c = mapEscapeSequence(t, s);
+            s++;
         }
         buffer[index++] = c;
     }

+ 7 - 7
test/Add.basic

@@ -1,8 +1,8 @@
-print(1 + 20)
-print(1 + 20 + 4)
-print(1 + 20 + 4 + 6)
+printLine(1 + 20)
+printLine(1 + 20 + 4)
+printLine(1 + 20 + 4 + 6)
 # dummy comment
-print(5 - 6) # another dummy
-print(5 * 6)
-print(16 / 5)
-print(1 + 2 * 3)
+printLine(5 - 6) # another dummy
+printLine(5 * 6)
+printLine(16 / 5)
+printLine(1 + 2 * 3)

+ 10 - 10
test/Array.basic

@@ -1,6 +1,6 @@
-print(getAllocations())
+printLine(getAllocations())
 a = array(5)
-print(getAllocations())
+printLine(getAllocations())
 a[0] = 5
 a[1] = 20
 a[2] = 40
@@ -8,26 +8,26 @@ a[3] = 60
 a[4] = 80
 
 for i = 0 to 4
-    print(a[i])
+    printLine(a[i])
 end
 
 b = array(7)
-print(getAllocations())
+printLine(getAllocations())
 c = array(7)
-print(getAllocations())
+printLine(getAllocations())
 for i = 0 to 40
     a = array(5)
 end
-print(getAllocations())
+printLine(getAllocations())
 
 d = array(5)
-print(getAllocations())
+printLine(getAllocations())
 d[0] = array(3)
 d[1] = array(4)
 d[2] = d
-print(d)
-print(getAllocations())
+printLine(d)
+printLine(getAllocations())
 
 d = 5
-print(getAllocations())
+printLine(getAllocations())
 

+ 18 - 18
test/Condition.basic

@@ -1,23 +1,23 @@
-print(3 < 5)
-print(5 < 3)
-print(3 < 3)
+printLine(3 < 5)
+printLine(5 < 3)
+printLine(3 < 3)
 
-print(3 > 5)
-print(5 > 3)
-print(3 > 3)
+printLine(3 > 5)
+printLine(5 > 3)
+printLine(3 > 3)
 
-print(3 == 5)
-print(5 == 3)
-print(3 == 3)
+printLine(3 == 5)
+printLine(5 == 3)
+printLine(3 == 3)
 
-print(3 != 5)
-print(5 != 3)
-print(3 != 3)
+printLine(3 != 5)
+printLine(5 != 3)
+printLine(3 != 3)
 
-print(3 <= 5)
-print(5 <= 3)
-print(3 <= 3)
+printLine(3 <= 5)
+printLine(5 <= 3)
+printLine(3 <= 3)
 
-print(3 >= 5)
-print(5 >= 3)
-print(3 >= 3)
+printLine(3 >= 5)
+printLine(5 >= 3)
+printLine(3 >= 3)

+ 3 - 0
test/Escape.basic

@@ -0,0 +1,3 @@
+print("\\\n")
+print("\r\n")
+print("\tx\n")

+ 3 - 0
test/Escape.basic_result

@@ -0,0 +1,3 @@
+\
+
+	x

+ 3 - 3
test/For.basic

@@ -1,10 +1,10 @@
 for i = 0 to 5
-    print(i)
+    printLine(i)
 end
 
 for x = 0 to 2
     for y = 0 to 3
-        print(x, " ", y)
+        printLine(x, " ", y)
     end
 end
 
@@ -16,7 +16,7 @@ for x = 0 to 10
         if y == 3
             continue
         end
-        print(x, " ", y)
+        printLine(x, " ", y)
     end
     if x == 1
         break

+ 4 - 4
test/Function.basic

@@ -1,6 +1,6 @@
 function wusi()
-    print("hi there")
-    print("great")
+    printLine("hi there")
+    printLine("great")
 end
 
 wusi()
@@ -9,8 +9,8 @@ gusi()
 wusi()
 
 function gusi()
-    print("baum")
-    print("wow")
+    printLine("baum")
+    printLine("wow")
 end
 
 gusi()

+ 3 - 3
test/Function2.basic

@@ -3,15 +3,15 @@ d = 5
 
 function wusi(a, b)
     d = 10
-    print(a + b + $c + d)
+    printLine(a + b + $c + d)
 end
 
 wusi(5, 6)
-print(d)
+printLine(d)
 
 function mod()
     $d = 12
 end
 
 mod()
-print(d)
+printLine(d)

+ 6 - 6
test/Function3.basic

@@ -7,8 +7,8 @@ function wusi(a, b)
 end
 
 wusi(5, 6)
-print(wusi(3, 4))
-print(wusi(5, 4))
+printLine(wusi(3, 4))
+printLine(wusi(5, 4))
 
 function fac(n)
     if n == 0
@@ -20,7 +20,7 @@ end
 function baum()
 end
 
-print(fac(4))
-print(fac(5))
-print(baum())
-print(baum())
+printLine(fac(4))
+printLine(fac(5))
+printLine(baum())
+printLine(baum())

+ 7 - 7
test/If.basic

@@ -1,22 +1,22 @@
 if 1
-  print("wusi")
+  printLine("wusi")
   if 0
-    print("wusi4")
+    printLine("wusi4")
   end
   if 1
-    print("wusi2")
+    printLine("wusi2")
   end
 end
 
 if 1 + 1
-  print("wusi3")
+  printLine("wusi3")
 end
 
 if 0
-  print("gusi")
+  printLine("gusi")
   if 1
-    print("gusi2")
+    printLine("gusi2")
   end
 end
 
-print("end")
+printLine("end")

+ 27 - 27
test/Logic.basic

@@ -1,31 +1,31 @@
-print(0 && 0)
-print(1 && 0)
-print(0 && 1)
-print(1 && 1)
+printLine(0 && 0)
+printLine(1 && 0)
+printLine(0 && 1)
+printLine(1 && 1)
 
-print(0 || 0)
-print(1 || 0)
-print(0 || 1)
-print(1 || 1)
+printLine(0 || 0)
+printLine(1 || 0)
+printLine(0 || 1)
+printLine(1 || 1)
 
-print(0 && 0 && 0)
-print(1 && 0 && 0)
-print(0 && 1 && 0)
-print(1 && 1 && 0)
-print(0 && 0 && 1)
-print(1 && 0 && 1)
-print(0 && 1 && 1)
-print(1 && 1 && 1)
+printLine(0 && 0 && 0)
+printLine(1 && 0 && 0)
+printLine(0 && 1 && 0)
+printLine(1 && 1 && 0)
+printLine(0 && 0 && 1)
+printLine(1 && 0 && 1)
+printLine(0 && 1 && 1)
+printLine(1 && 1 && 1)
 
-print(0 || 0 || 0)
-print(1 || 0 || 0)
-print(0 || 1 || 0)
-print(1 || 1 || 0)
-print(0 || 0 || 1)
-print(1 || 0 || 1)
-print(0 || 1 || 1)
-print(1 || 1 || 1)
+printLine(0 || 0 || 0)
+printLine(1 || 0 || 0)
+printLine(0 || 1 || 0)
+printLine(1 || 1 || 0)
+printLine(0 || 0 || 1)
+printLine(1 || 0 || 1)
+printLine(0 || 1 || 1)
+printLine(1 || 1 || 1)
 
-print(!3)
-print(!!3)
-print(!!!3)
+printLine(!3)
+printLine(!!3)
+printLine(!!!3)

+ 3 - 3
test/Print.basic

@@ -1,3 +1,3 @@
-print("Hi")
-print(6)
-print("Hi there ", 8, " great")
+printLine("Hi")
+printLine(6)
+printLine("Hi there ", 8, " great")

+ 9 - 9
test/Var.basic

@@ -2,16 +2,16 @@ abc = 5
 wusi = 10
 baum = 12 + wusi
 
-print(abc)
-print(wusi)
-print(baum)
-print(nothing)
+printLine(abc)
+printLine(wusi)
+printLine(baum)
+printLine(nothing)
 
 wusi = 6
 
-print(abc)
-print(wusi)
-print(baum)
-print(nothing)
+printLine(abc)
+printLine(wusi)
+printLine(baum)
+printLine(nothing)
 
-print(abc + wusi + baum)
+printLine(abc + wusi + baum)

+ 3 - 3
test/While.basic

@@ -1,6 +1,6 @@
 i = 0
 while i <= 5
-    print(i)
+    printLine(i)
     i = i + 1
 end
 
@@ -8,7 +8,7 @@ x = 0
 while x <= 2
     y = 0
     while y <= 3
-        print(x, " ", y)
+        printLine(x, " ", y)
         y = y + 1
     end
     x = x + 1
@@ -26,7 +26,7 @@ while x <= 10
             y = y + 1
             continue
         end
-        print(x, " ", y)
+        printLine(x, " ", y)
         y = y + 1
     end
     if x == 1