txlyre 5 hours ago
parent
commit
60e8520884
1 changed files with 64 additions and 1 deletions
  1. 64 1
      qic.c

+ 64 - 1
qic.c

@@ -1529,9 +1529,12 @@ node_t *parse_block(list_t *tokens, size_t *pos) {
   EXPECT(LCB, "{");
 
   list_t *stmts = list_new();
-  while (!AT(EOF) && !AT(RCB))
+  while (!AT(EOF) && !AT(RCB)) {
     list_push(stmts, parse_stmt(tokens, pos));
 
+    MATCH(SEMI);
+  }
+
   EXPECT(RCB, "}");
 
   return NODEL(PROGRAM, stmts);
@@ -2504,9 +2507,67 @@ const char *STD[][2] = {
     "func is_char(c): return type(c) == \"string\" && len(c) == 1\n"
   },
 
+  {"math", NULL},
+
   {NULL, NULL}
 };
 
+const struct {
+  const char *name;
+  const char *fname;
+  int arity;
+} MATHFUNCS[] = {
+  { "ceil", NULL, 1 },
+  { "floor", NULL, 1 },
+  { "trunc", NULL, 1 },
+  { "round", NULL, 1 },
+  { "abs", "fabs", 1 },
+  { "exp", NULL, 1 },
+  { "sqrt", NULL, 1 },
+  { "sinh", NULL, 1 },
+  { "cosh", NULL, 1 },
+  { "tanh", NULL, 1 },
+  { "asinh", NULL, 1 },
+  { "acosh", NULL, 1 },
+  { "atanh", NULL, 1 },
+  { "sin", NULL, 1 },
+  { "cos", NULL, 1 },
+  { "tan", NULL, 1 },
+  { "asin", NULL, 1 },
+  { "acos", NULL, 1 },
+  { "atan", NULL, 1 },
+  { "atan2", NULL, 2 },
+  { "hypot", NULL, 2 },
+  { "random", "rand", 0 },
+
+  { NULL, 0 }
+};
+
+void genmathlib(void) {
+  buffer_t *buffer = buffer_new();
+
+  buffer_appends(buffer, "let Math = {\"tau\": 6.283185307179586, \"pi\": 3.141592653589793, \"e\": 2.718281828459045, \"inf\": INFINITY, \"nan\": NAN, ");
+
+  for (size_t i = 0; MATHFUNCS[i].name; i++) {
+    if (MATHFUNCS[i].arity == 0)
+      buffer_fmt(buffer, "\"%s\": func () { inline `return qi_make_number(state, %s())` }", MATHFUNCS[i].name, MATHFUNCS[i].fname? MATHFUNCS[i].fname: MATHFUNCS[i].name);
+    else if (MATHFUNCS[i].arity == 1)
+      buffer_fmt(buffer, "\"%s\": func (x) { if type(x) != \"number\" { throw \"expected first argument to be: number, but got: \" + type(x) } inline `double n = %s(qi_get(state, \"x\")->value.number)`; inline `return qi_make_number(state, n)` }", MATHFUNCS[i].name, MATHFUNCS[i].fname? MATHFUNCS[i].fname: MATHFUNCS[i].name);
+    else
+      buffer_fmt(buffer, "\"%s\": func (x, y) { if type(x) != \"number\" { throw \"expected first argument to be: number, but got: \" + type(x) } if type(y) != \"number\" { throw \"expected second argument to be: number, but got: \" + type(y) } inline `double n = %s(qi_get(state, \"x\")->value.number, qi_get(state, \"y\")->value.number)`; inline `return qi_make_number(state, n)` }", MATHFUNCS[i].name, MATHFUNCS[i].fname? MATHFUNCS[i].fname: MATHFUNCS[i].name);
+
+    if (MATHFUNCS[i + 1].name)
+      buffer_append(buffer, ',');
+  }
+
+  buffer_append(buffer, '}');
+
+  size_t i;
+  for (i = 0; strcmp(STD[i][0], "math") != 0; i++) ;
+
+  STD[i][1] = buffer_read(buffer);
+}
+
 char *unescape(char *s) {
   buffer_t *buf = buffer_new();
 
@@ -3173,6 +3234,8 @@ int main(int argc, char **argv) {
   REQUIRED = list_new();
   CONSTANTS = table_new();
 
+  genmathlib();
+
   char *out = compile_file("<stdin>", stdin);
 
   fwrite(out, sizeof(char), strlen(out), stdout);