txlyre 6 days ago
parent
commit
f894d919ed
1 changed files with 97 additions and 2 deletions
  1. 97 2
      qic.c

+ 97 - 2
qic.c

@@ -351,8 +351,13 @@ typedef struct {
     T_NUMBER,
     T_STRING,
     T_FSTRING,
+    T_USTRING,
     T_NAME,
 
+    T_TRUE,
+    T_FALSE,
+    T_NIL,
+
     T_VAR,
     T_LET,
     T_CONST,
@@ -675,6 +680,8 @@ token_t *tokenize_string(char *source, size_t *pos) {
   return token(T_STRING, buffer_read(text));
 }
 
+int NEEDS_UTF8 = 0;
+
 token_t *next_token(char *source, size_t *pos) {
   if (!source[*pos])
     return token(T_EOF, NULL);
@@ -689,6 +696,17 @@ token_t *next_token(char *source, size_t *pos) {
     token_t *t = tokenize_string(source, pos);
     t->tag = T_FSTRING;
 
+    return t;
+  } else if (source[*pos] == 'u' &&
+            (source[(*pos) + 1] == '"' || source[(*pos) + 1] == '\'' ||
+             source[(*pos) + 1] == '`')) {
+    (*pos)++;
+
+    token_t *t = tokenize_string(source, pos);
+    t->tag = T_USTRING;
+
+    NEEDS_UTF8 = 1;
+
     return t;
   } else if (source[*pos] == '0' &&
              (source[(*pos) + 1] == 'x' || source[(*pos) + 1] == 'b' ||
@@ -842,6 +860,12 @@ token_t *next_token(char *source, size_t *pos) {
       return TK(INCLUDE);
     else if (strcmp(name, "macro") == 0)
       return TK(MACRO);
+    else if (strcmp(name, "true") == 0)
+      return TK(TRUE);
+    else if (strcmp(name, "false") == 0)
+      return TK(FALSE);
+    else if (strcmp(name, "nil") == 0)
+      return TK(NIL);
 
     return token(T_NAME, name);
   } else if (strncmp(&source[*pos], "==", 2) == 0 && ++(*pos) && ++(*pos))
@@ -1549,7 +1573,7 @@ node_t *parse_primary(list_t *tokens, size_t *pos) {
     EXPECT(RCB, "}");
 
     return NODEH(TABLE, table);
-  } else if (MATCH(NUMBER) || MATCH(STRING) || MATCH(FSTRING) || MATCH(NAME))
+  } else if (MATCH(NUMBER) || MATCH(STRING) || MATCH(FSTRING) || MATCH(USTRING) || MATCH(NAME) || MATCH(TRUE) || MATCH(FALSE) || MATCH(NIL))
     return NODET(LITERAL, tokens->data[(*pos) - 1]);
 
   if (MATCH(RPAR)) {
@@ -2631,7 +2655,7 @@ node_t *parse_mprimary(list_t *tokens, size_t *pos) {
     EXPECT(RPAR, ")");
 
     return a;
-  } else if (MATCH(NAME)) {
+  } else if (MATCH(NAME) || MATCH(TRUE) || MATCH(FALSE) || MATCH(NIL)) {
     token_t *t = tokens->data[(*pos) - 1];
 
     int macro = 0;
@@ -3493,6 +3517,45 @@ const char *STD[][2] = {
              "    return bytes([0xf0 | ((c >> 18) & 0x7), 0x80 | ((c >> 12) & "
              "0x3f), 0x80 | ((c >> 6) & 0x3f), 0x80 | (c & 0x3f)])\n"
              "  throw \"malformed codepoint\"\n"
+             "}\n"
+             "class ustr {\n"
+             "  _ucs = nil\n"
+             "  constructor (this, s=\"\") {\n"
+             "    if type(s) == \"list\" && all(map(func (x): type(x) == \"number\", s)) {\n"
+             "      this._ucs = s\n"
+             "      return\n"
+             "    }\n"
+             "    s = str(s)\n"
+             "    this._ucs = []\n"
+             "    for var i = 0; i < len(s) {\n"
+             "      let [c, l] = utf8_decode(slice(s, i))\n"
+             "      this._ucs.push(c)\n"
+             "      i += l\n"
+             "    }\n"
+             "  }\n"
+             "  nth (this, i): str(utf8_encode(this._ucs[i]))\n"
+             "  __type (this): \"ustr\"\n"
+             "  __str (this) {\n"
+             "    var s = \"\"\n"
+             "    for var uc of this._ucs\n"
+             "      s += str(utf8_encode(uc))\n"
+             "    return s\n"
+             "  }\n"
+             "  __len (this): len(this._ucs)\n"
+             "  __index (this, i): this._ucs[i]\n"
+             "  __index_set (this): throw\n"
+             "  __iter (this): this._ucs\n"
+             "  __list (this): list_copy(this._ucs)\n"
+             "  __add (this, other) {\n"
+             "    if type(other) != \"ustr\"\n"
+             "      throw\n"
+             "    return ustr(this._ucs + other._ucs)\n"
+             "  }\n"
+             "  __equals (this, other) {\n"
+             "    if type(other) != \"ustr\"\n"
+             "      return false\n"
+             "    return this._ucs == other._ucs\n"
+             "  }\n"
              "}\n"},
 
     {"thread",
@@ -4911,6 +4974,10 @@ void compile_node(buffer_t *gbuf, buffer_t *buf, list_t *ctx, table_t *ltab,
       EMIT("__%s%d(state)", PREFIX, gid);
     } break;
 
+    case T_USTRING:      
+      EMIT("qi_call(state, qi_get(state, \"ustr\"), qi_list_push(qi_list_make(), qi_make_string(state, \"%s\")))", node->t->text);
+      break;
+
     case T_NAME: {
       char *name = node->t->text;
       node_t *n = const_get(name);
@@ -4921,6 +4988,10 @@ void compile_node(buffer_t *gbuf, buffer_t *buf, list_t *ctx, table_t *ltab,
         EMIT("qi_get(state, \"%s\")", name);
     } break;
 
+    case T_TRUE: EMIT("state->_true"); break;
+    case T_FALSE: EMIT("state->_false"); break;
+    case T_NIL: EMIT("state->nil"); break;
+
     default:
       COMPILE_ERROR("not yet implemented");
     }
@@ -5376,6 +5447,9 @@ void compile_node(buffer_t *gbuf, buffer_t *buf, list_t *ctx, table_t *ltab,
       EMIT(")) {\n");
     }
 
+    CTXPUSH("scope");
+    EMIT("qi_new_scope(state);\n");
+
     LPUSH(gid);
     CTXPUSH("for");
     compile_node(gbuf, buf, ctx, ltab, lstk, sstk, lbl, node->d);
@@ -5391,9 +5465,15 @@ void compile_node(buffer_t *gbuf, buffer_t *buf, list_t *ctx, table_t *ltab,
     CTXPOP();
     LPOP();
 
+    CTXPOP();
+    EMIT("qi_old_scope(state);\n");
+
     EMIT("}\n");
 
+    EMIT("goto __exit%d;\n", gid);
     EMIT("__break%d:;\n", gid);
+    EMIT("qi_old_scope(state);\n");
+    EMIT("__exit%d:;\n", gid);
 
     CTXPOP();
     EMIT("qi_old_scope(state);\n");
@@ -5447,6 +5527,9 @@ void compile_node(buffer_t *gbuf, buffer_t *buf, list_t *ctx, table_t *ltab,
            "qi_make_number(state, i)));\n",
            node->t->text, varname);
 
+    CTXPUSH("scope");
+    EMIT("qi_new_scope(state);\n");
+
     LPUSH(gid);
     CTXPUSH("for");
     compile_node(gbuf, buf, ctx, ltab, lstk, sstk, lbl, node->b);
@@ -5454,9 +5537,16 @@ void compile_node(buffer_t *gbuf, buffer_t *buf, list_t *ctx, table_t *ltab,
     LPOP();
 
     EMIT("__continue%d:;\n", gid);
+
+    CTXPOP();
+    EMIT("qi_old_scope(state);\n");
+
     EMIT("}\n");
 
+    EMIT("goto __exit%d;\n", gid);
     EMIT("__break%d:;\n", gid);
+    EMIT("qi_old_scope(state);\n");
+    EMIT("__exit%d:;\n", gid);
 
     CTXPOP();
     EMIT("qi_old_scope(state);\n");
@@ -5831,6 +5921,11 @@ void compile_into(char *source, buffer_t *gbuf, buffer_t *buf, list_t *ctx,
                   table_t *ltab, int_stack_t *lstk, int_stack_t *sstk,
                   list_t *lbl) {
   node_t *n = parse(source);
+  if (NEEDS_UTF8) {
+    NEEDS_UTF8 = 0;
+
+    require_once(gbuf, buf, ctx, ltab, lstk, sstk, lbl, "utf8");
+  }
 
   compile_node(gbuf, buf, ctx, ltab, lstk, sstk, lbl, n);
 }