Browse Source

Sol Part 56: Asymptotically equivalent to a unicorn!

https://derpicdn.net/img/download/2014/7/6/668821.png
Graham Northup 5 years ago
parent
commit
e6f565383f
Signed by: Grissess <grissess@nexusg.org> GPG Key ID: 5D000E6F539376FB
16 changed files with 3889 additions and 3156 deletions
  1. 17
    27
      README.md
  2. 10
    1
      ast.h
  3. 23
    5
      astprint.c
  4. 27
    9
      builtins.c
  5. 131
    116
      lex.yy.c
  6. 3025
    2545
      parser.output
  7. 460
    411
      parser.tab.c
  8. 11
    10
      parser.tab.h
  9. 89
    8
      parser.y
  10. 46
    6
      runtime.c
  11. 16
    8
      sol.h
  12. 3
    7
      state.c
  13. 1
    2
      tests/_lib.sol
  14. 10
    0
      tests/lang_bparen.sol
  15. 17
    0
      tests/lang_variadic.sol
  16. 3
    1
      tokenizer.lex

+ 17
- 27
README.md View File

@@ -21,31 +21,30 @@ while a < 10 do
21 21
 end
22 22
 
23 23
 -- "Pythonic" for loops; any expression can be used, so long as it
24
+-- returns a function that will be called until it returns None
24 25
 for i in range(10) do print(i) end -- Note Lua-ish keyword delimiting
25 26
 
26 27
 -- "func" seems like a good compromise between "def" and "function" :D
27 28
 -- (This is a currying add function)
28 29
 func outer(a)
29
-  func inner(b)
30
+  return func inner(b, a=a)
30 31
     return a+b
31 32
   end
32
-  inner.closure.a = a
33
-  return inner
34 33
 end
35 34
 
35
+-- Alternatively...
36
+outer = lambda(a) lambda(b, a=a) a + b end end
37
+
36 38
 -- (...and this is an iterator)
37 39
 func count(j)
38
-  inner = func () -- Note: function definitions are expressions, like in Lua
40
+  inner = func (i = 0, max = j)  -- Function definitions are expressions, like in Lua
39 41
     if i >= max then
40
-      return StopIteration
42
+      return  -- If no value is given, None is implied
41 43
     else
42 44
       i += 1
43 45
       return i - 1
44 46
     end
45 47
   end
46
-  inner.closure.i = 0
47
-  inner.closure.max = j
48 48
   return inner
49 49
 end
50 50
 
@@ -59,7 +58,7 @@ print({a=1, b=2, ["c"]=3, [4]=5, ["with more spaces"]={health=100, speed=2}})
59 58
 object = {__index = func(obj, idx) print("Index", obj, "with", idx); return idx end,
60 59
           __setindex = func(obj, idx, val) print("Set index", idx, "of", obj, "to", val) end,
61 60
           __call = func(obj, arg1, arg2) print("Called", obj, "with args", arg1, arg2); return arg1+arg2 end}
61
+-- No metatables, but __index can be assigned to another map, which has nearly the same effect
62 62
 
63 63
 -- Lua-ish error handling
64 64
 func bad(x)
@@ -68,10 +67,11 @@ func bad(x)
68 67
 end
69 68
 
70 69
 res = try(bad, {}) -- Returns 1 (or true), "thing"
71
-res = try(bad, None) -- Reurns 0 (or false), "Undefined method" -- you can't index None :P
70
+res = try(bad, None) -- Reurns 0 (or false), "Undefined method" -- you can't index None
72 71
 res = try(bad) -- Also fails; unbound arguments are assigned to None by default
72
+res = try(error, 1234) -- Fails, returning [0, 1234] -- errors can be any object
73 73
 
74
+-- Full suppport for self-modifying code, and invoking the compiler
74 75
 func a() return 0 end
75 76
 func b() return 2 end
76 77
 
@@ -83,7 +83,7 @@ b.stmt = temp
83 83
 code = parse('print("Hi!"); return 4')
84 84
 a.stmt = code
85 85
 b.stmt = code
86
+-- a and b now return 4 (and print "Hi!")
86 87
 
87 88
 parse('print("Good day!")')() -- Does the thing; shortcut is "exec"
88 89
 q = parse('8 + 13 * 2').stmtlist[0].expr() -- Returns the value (should be...34?); shortcut "eval"
@@ -97,7 +97,7 @@ That's a really brief taste; you can look at the `test.sol` file for a larger co
97 97
 Buiding/Installation
98 98
 --------------------
99 99
 
100
-First off, *you should clone this repository with --recurive* if you want to get the submodules in one go. If you've already cloned it, don't worry; just run this:
100
+First off, *you should clone this repository with --recursive* if you want to get the submodules in one go. If you've already cloned it, don't worry; just run this:
101 101
 
102 102
 ```
103 103
 git submodule init
@@ -106,13 +106,7 @@ git submodule update
106 106
 
107 107
 This should pull in the requisite build dependencies. (For more on this, see git's documentation on [Cloning a Project with Submodules](http://git-scm.com/book/en/v2/Git-Tools-Submodules#Cloning-a-Project-with-Submodules).)
108 108
 
109
-Because makefiles aren't hipster enough, the build system for Sol presently consists of exclusively .sh files, and it's presently hardcoded to use gcc, and include debugging symbols (this will be fixed eventually). If you're on any POSIX-y platform, you should be able to clone this repo and run:
110
-
111
-    ./build.sh
112
-    
113
-This should build the executable runtime `sol` in the working directory (it is explicitly ignored, and won't be committed to the repo).
114
-
115
-If, at any time, you change the grammar definitions (`tokenizer.lex`, `parser.y`), you will need to run `./buildgrammar.sh` first. This will build the appropriate parser and tokenizer C files, which will be built into the executable. (Building these files will require Flex and Bison; consult your platform's documentation on acquiring them.)
109
+A typical `make` should suffice to build the project. There is no `make install` yet, as there's no agreed-upon location for its support files. The executable runtime `sol` should be in the working directory (it is explicitly ignored, and won't be committed to the repo).
116 110
 
117 111
 Running
118 112
 -------
@@ -138,7 +132,9 @@ Todo
138 132
 
139 133
 Most of what needs to be done is addressing these issues:
140 134
 
141
-**Sol is a mess.** At present, there are numerous memory leaks (as checked with valgrind) due to some particularly relaxed refcount handling, as well as problems with the parse trees containing pointer clones, causing double frees when trying to free the trees proper (which I don't do because crashes--there goes several kilobytes of memory already...). The objects themselves are a bit non-optimal, just as well; a new integer is created every time one needs to be returned, such as during every arithmetic operation, even if they're transient (such as partial evaluations of large expressions). The map is especially abhorrent--indexing it does a linear scan and calls the `cmp` operation on each key. A `hash` operation will probably be implemented to help with this.
135
+**Sol leaks memory.** As confirmed with Valgrind (running memcheck), a normal Sol run loses some objects. A great deal of work has been invested in finding and fixing these bugs, but they remain elusive. If you have any insight into something which causes Sol to leak, please file an issue!
136
+
137
+**Sol is slow.** Sol pressures the heap pretty heavily by creating a new object ("returning a new reference") for most operations. At least one bottleneck was addressed with the "icache" (integer cache), which speeds up comparisons significantly, but Sol nonetheless rapidly creates, destroys, and copies strings in very critical execution paths. The map implementation is particularly egregious, and is currently an associative array.
142 138
 
143 139
 **The API is unstable.** There will definitely be some changes to the API, mostly to *help* with integration. At present, some operations on behalf of Sol embedders are a little messy and require intrinsic knowledge of the language specifics. The refcounting scheme, as mentioned previously, requires about four lines of code per function that should be a one-liner, for example.
144 140
 
@@ -154,16 +150,6 @@ After those (but more practically, with them), the following will be coming:
154 150
 
155 151
 **Code consolidation and refactoring.** There are quite a few instances of repetitive code that need to be addressed, and can be refactored out into functions in their own right. This should also improve usability.
156 152
 
157
-**Redefinition of print.** `ob_print` is a debug utility meant to be used from GDB, so it intentionally was not designed with state access in mind. `sol_ops_t.tostring` was always intended to be what generated object representations, and these need to be updated to match how `ob_print` does it (but better).
158
-
159
-**Proper stream/file support.** Currently, printing happens to `stdout` implicitly through `printf`. By adding an object abstraction layer, Sol code can redirect output (like Python's `sys.stdout`). This will be especially useful in environments where `stdout` is invisible or obscured, like Windows GUI applications.
160
-
161
-**Optimization.** As mentioned above, a few critical operations are quite slow. This will probably require some higher-caliber data structures than the ones I have now, most of which will probably be relegated to DSL for code reuse.
162
-
163
-**Makefiles.** Being a non-conformist is fun, but will probably hurt in the long run :P
164
-
165
-**Documentation.** More thorough documentation will be coming soon, I promise.
166
-
167 153
 Contributing
168 154
 ------------
169 155
 

+ 10
- 1
ast.h View File

@@ -129,8 +129,15 @@ typedef struct tag_identlist_node {
129 129
 } identlist_node;
130 130
 
131 131
 typedef struct {
132
-	char *name;
133 132
 	identlist_node *args;
133
+	identlist_node *clkeys;
134
+	exprlist_node *clvalues;
135
+	char *rest;
136
+} paramlist_node;
137
+
138
+typedef struct {
139
+	char *name;
140
+	paramlist_node *params;
134 141
 	stmt_node *body;
135 142
 } funcdecl_node;
136 143
 
@@ -257,6 +264,7 @@ stmtlist_node *stl_copy(stmtlist_node *);
257 264
 exprlist_node *exl_copy(exprlist_node *);
258 265
 assoclist_node *asl_copy(assoclist_node *);
259 266
 identlist_node *idl_copy(identlist_node *);
267
+paramlist_node *pl_copy(paramlist_node *);
260 268
 
261 269
 void st_free(stmt_node *);
262 270
 void ex_free(expr_node *);
@@ -264,6 +272,7 @@ void stl_free(stmtlist_node *);
264 272
 void exl_free(exprlist_node *);
265 273
 void asl_free(assoclist_node *);
266 274
 void idl_free(identlist_node *);
275
+void pl_free(paramlist_node *);
267 276
 
268 277
 void st_print(sol_state_t *, stmt_node *);
269 278
 void ex_print(sol_state_t *, expr_node *);

+ 23
- 5
astprint.c View File

@@ -273,11 +273,29 @@ void prex(sol_state_t *state, expr_node *node, int lev) {
273 273
 			prlev(state, lev, "FuncDecl:");
274 274
 			lev++;
275 275
 			prlev(state, lev, "Name: %s", node->funcdecl->name);
276
-			prlev(state, lev, "Args:");
277
-			curi = node->funcdecl->args;
278
-			while(curi && curi->ident) {
279
-				prlev(state, lev + 1, curi->ident);
280
-				curi = curi->next;
276
+			prlev(state, lev, "Params:");
277
+			if(!node->funcdecl->params) {
278
+				prlev(state, lev + 1, "<NULL>");
279
+			} else {
280
+				prlev(state, lev + 1, "Args:");
281
+				curi = node->funcdecl->params->args;
282
+				while(curi && curi->ident) {
283
+					prlev(state, lev + 2, curi->ident);
284
+					curi = curi->next;
285
+				}
286
+				prlev(state, lev + 1, "ClKeys:");
287
+				curi = node->funcdecl->params->clkeys;
288
+				while(curi && curi->ident) {
289
+					prlev(state, lev + 2, curi->ident);
290
+					curi = curi->next;
291
+				}
292
+				prlev(state, lev + 1, "ClValues:");
293
+				cure = node->funcdecl->params->clvalues;
294
+				while(cure && cure->expr) {
295
+					prex(state, cure->expr, lev + 2);
296
+					cure = cure->next;
297
+				}
298
+				prlev(state, lev + 1, "Rest: %s", node->funcdecl->params->rest);
281 299
 			}
282 300
 			prlev(state, lev, "Body:");
283 301
 			prst(state, node->funcdecl->body, lev + 1);

+ 27
- 9
builtins.c View File

@@ -126,6 +126,17 @@ sol_object_t *sol_f_try(sol_state_t *state, sol_object_t *args) {
126 126
 	return ls;
127 127
 }
128 128
 
129
+sol_object_t *sol_f_apply(sol_state_t *state, sol_object_t *args) {
130
+	sol_object_t *func = sol_list_get_index(state, args, 0), *arglist = sol_list_get_index(state, args, 1), *rest = sol_list_sublist(state, args, 2);
131
+	sol_list_append(state, rest, arglist);
132
+	sol_obj_free(arglist);
133
+	sol_list_insert(state, rest, 0, func);
134
+	sol_object_t *res = CALL_METHOD(state, func, call, rest);
135
+	sol_obj_free(rest);
136
+	sol_obj_free(func);
137
+	return res;
138
+}
139
+
129 140
 sol_object_t *sol_f_error(sol_state_t *state, sol_object_t *args) {
130 141
 	sol_object_t *arg = sol_list_get_index(state, args, 0), *res;
131 142
 	res = sol_set_error(state, arg);
@@ -522,7 +533,7 @@ sol_object_t *sol_f_iter_str(sol_state_t *state, sol_object_t *args) {
522 533
 		sol_obj_free(index);
523 534
 		sol_obj_free(obj);
524 535
 		sol_obj_free(local);
525
-		return sol_incref(state->StopIteration);
536
+		return sol_incref(state->None);
526 537
 	}
527 538
 	temp[0] = obj->str[((size_t) index->buffer)];
528 539
 	res = sol_new_string(state, temp);
@@ -546,7 +557,7 @@ sol_object_t *sol_f_iter_list(sol_state_t *state, sol_object_t *args) {
546 557
 		sol_obj_free(index);
547 558
 		sol_obj_free(obj);
548 559
 		sol_obj_free(local);
549
-		return sol_incref(state->StopIteration);
560
+		return sol_incref(state->None);
550 561
 	}
551 562
 	res = sol_incref(AS_OBJ(dsl_seq_iter_at(index->buffer)));
552 563
 	dsl_seq_iter_next(index->buffer);
@@ -568,7 +579,7 @@ sol_object_t *sol_f_iter_map(sol_state_t *state, sol_object_t *args) {
568 579
 		sol_obj_free(index);
569 580
 		sol_obj_free(obj);
570 581
 		sol_obj_free(local);
571
-		return sol_incref(state->StopIteration);
582
+		return sol_incref(state->None);
572 583
 	}
573 584
 	res = sol_incref(AS_OBJ(dsl_seq_iter_at(index->buffer))->key);
574 585
 	dsl_seq_iter_next(index->buffer);
@@ -1773,7 +1784,7 @@ sol_object_t *sol_f_astnode_index(sol_state_t *state, sol_object_t *args) {
1773 1784
 						res = sol_new_string(state, (expr->funcdecl->name ? expr->funcdecl->name : ""));
1774 1785
 					} else if(sol_string_eq(state, str, "args")) {
1775 1786
 						res = sol_new_list(state);
1776
-						curi = expr->funcdecl->args;
1787
+						curi = expr->funcdecl->params ? expr->funcdecl->params->args : NULL;
1777 1788
 						while(curi) {
1778 1789
 							sol_list_insert(state, res, i++, sol_new_string(state, curi->ident));
1779 1790
 							curi = curi->next;
@@ -2117,11 +2128,18 @@ sol_object_t *sol_f_astnode_setindex(sol_state_t *state, sol_object_t *args) {
2117 2128
 						expr->funcdecl->name = strdup(sval->str);
2118 2129
 						sol_obj_free(sval);
2119 2130
 					} else if(sol_string_eq(state, str, "args") && sol_is_list(val)) {
2120
-						idl_free(expr->funcdecl->args);
2131
+						if(!expr->funcdecl->params) {
2132
+							expr->funcdecl->params = malloc(sizeof(paramlist_node));
2133
+							expr->funcdecl->params->args = NULL;
2134
+							expr->funcdecl->params->clkeys = NULL;
2135
+							expr->funcdecl->params->clvalues = NULL;
2136
+							expr->funcdecl->params->rest = NULL;
2137
+						}
2138
+						idl_free(expr->funcdecl->params->args);
2121 2139
 						len = sol_list_len(state, val);
2122 2140
 						if(len > 0) {
2123 2141
 							curi = malloc(sizeof(identlist_node));
2124
-							expr->funcdecl->args = curi;
2142
+							expr->funcdecl->params->args = curi;
2125 2143
 							for(i = 0; i < len; i++) {
2126 2144
 								sval = sol_cast_string(state, sol_list_get_index(state, val, i));
2127 2145
 								curi->ident = strdup(sval->str);
@@ -2130,15 +2148,15 @@ sol_object_t *sol_f_astnode_setindex(sol_state_t *state, sol_object_t *args) {
2130 2148
 								curi = malloc(sizeof(identlist_node));
2131 2149
 								previ->next = curi;
2132 2150
 							}
2133
-							if(expr->funcdecl->args == curi) {
2134
-								expr->funcdecl->args = NULL;
2151
+							if(expr->funcdecl->params->args == curi) {
2152
+								expr->funcdecl->params->args = NULL;
2135 2153
 							}
2136 2154
 							free(curi);
2137 2155
 							if(previ) {
2138 2156
 								previ->next = NULL;
2139 2157
 							}
2140 2158
 						} else {
2141
-							expr->funcdecl->args = NULL;
2159
+							expr->funcdecl->params->args = NULL;
2142 2160
 						}
2143 2161
 					} else if(sol_string_eq(state, str, "body") && sol_is_aststmt(val)) {
2144 2162
 						st_free(expr->funcdecl->body);

+ 131
- 116
lex.yy.c View File

@@ -360,8 +360,8 @@ static void yynoreturn yy_fatal_error (yyconst char* msg  );
360 360
 	*yy_cp = '\0'; \
361 361
 	(yy_c_buf_p) = yy_cp;
362 362
 
363
-#define YY_NUM_RULES 72
364
-#define YY_END_OF_BUFFER 73
363
+#define YY_NUM_RULES 73
364
+#define YY_END_OF_BUFFER 74
365 365
 /* This struct is not used in this scanner,
366 366
    but its presence is necessary. */
367 367
 struct yy_trans_info
@@ -369,24 +369,25 @@ struct yy_trans_info
369 369
 	flex_int32_t yy_verify;
370 370
 	flex_int32_t yy_nxt;
371 371
 	};
372
-static yyconst flex_int16_t yy_accept[148] =
372
+static yyconst flex_int16_t yy_accept[152] =
373 373
     {   0,
374
-        0,    0,   73,   72,   71,   34,   72,   67,   23,   26,
375
-       72,   61,   62,   21,   19,   66,   20,   63,   22,    2,
376
-       64,   65,   51,   40,   52,   69,   69,   69,   69,   59,
377
-       60,   28,   69,   69,   69,   69,   69,   69,   69,   69,
378
-       69,   69,   69,   69,   69,   69,   57,   27,   58,   29,
379
-       71,    0,   50,    0,    3,   30,   46,    0,    4,   25,
380
-       43,   41,    0,   42,   44,    1,    2,   56,   53,   49,
381
-       54,   55,   69,   69,   69,   69,   48,   69,   69,   69,
382
-       11,   69,   69,   69,   69,   69,    5,   10,   69,   69,
383
-       69,   33,   69,   69,   69,   69,   47,   32,   68,   45,
384
-
385
-        0,   70,    1,   69,   69,   69,   31,   69,   69,   69,
386
-       17,   69,    9,   69,   69,   24,   35,   69,   69,   69,
387
-       69,   69,   18,   37,   69,   69,    7,   69,   12,   69,
388
-       69,    6,   36,   69,   39,   15,   69,   38,   69,   69,
389
-        8,   69,   13,   14,   69,   16,    0
374
+        0,    0,   74,   73,   72,   34,   73,   68,   23,   26,
375
+       73,   62,   63,   21,   19,   67,   20,   64,   22,    2,
376
+       65,   66,   51,   40,   52,   70,   70,   70,   70,   59,
377
+       60,   28,   70,   70,   70,   70,   70,   70,   70,   70,
378
+       70,   70,   70,   70,   70,   70,   57,   27,   58,   29,
379
+       72,   61,   72,    0,   50,    0,    3,   30,   46,    0,
380
+        4,   25,   43,   41,    0,   42,   44,    1,    2,   56,
381
+       53,   49,   54,   55,   70,   70,   70,   70,   48,   70,
382
+       70,   70,   11,   70,   70,   70,   70,   70,    5,   10,
383
+       70,   70,   70,   33,   70,   70,   70,   70,   47,   32,
384
+
385
+       72,   61,   69,   45,    0,   71,    1,   70,   70,   70,
386
+       31,   70,   70,   70,   17,   70,    9,   70,   70,   24,
387
+       35,   70,   70,   70,   70,   70,   18,   37,   70,   70,
388
+        7,   70,   12,   70,   70,    6,   36,   70,   39,   15,
389
+       70,   38,   70,   70,    8,   70,   13,   14,   70,   16,
390
+        0
390 391
     } ;
391 392
 
392 393
 static yyconst YY_CHAR yy_ec[256] =
@@ -431,102 +432,104 @@ static yyconst YY_CHAR yy_meta[53] =
431 432
         1,    1
432 433
     } ;
433 434
 
434
-static yyconst flex_uint16_t yy_base[152] =
435
+static yyconst flex_uint16_t yy_base[156] =
435 436
     {   0,
436
-        0,    0,  161,  162,   51,   51,  155,  162,  162,   48,
437
-      150,  162,  162,   45,  136,  162,   43,  162,  135,   43,
438
-      162,  162,   41,  134,   46,    0,  124,  111,  109,  162,
439
-      162,  130,  109,  106,  106,  105,   24,   29,   35,  116,
440
-      103,  102,  100,  108,   37,  105,  162,   53,  162,  162,
441
-       76,  137,  162,  135,  162,  162,  162,  130,  162,  116,
442
-      162,  162,  134,  162,  162,  118,   64,  162,  162,  162,
443
-      162,  162,    0,   95,   92,   86,  162,   98,   96,   88,
444
-        0,   84,   94,   87,   82,   83,    0,    0,   83,   89,
445
-       76,    0,   75,   85,   72,   80,  162,  162,  162,  162,
446
-
447
-      114,  162,   98,   70,   79,   78,    0,   81,   65,   75,
448
-        0,   57,    0,   68,   68,    0,    0,   52,   56,   62,
449
-       56,   60,    0,    0,   55,   55,    0,   57,    0,   57,
450
-       46,    0,    0,   54,    0,    0,   46,    0,   56,   44,
451
-        0,   38,    0,    0,   49,    0,  162,  103,  105,   81,
452
-      107
437
+        0,   51,  169,  170,   52,   52,  163,  170,  170,   49,
438
+      158,  170,  170,   46,  144,  170,   44,  170,  143,   44,
439
+      170,  170,   42,  142,   47,    0,  132,  119,  117,  170,
440
+      170,  138,  117,  114,  114,  113,   25,   41,   37,  124,
441
+      111,  110,  108,  116,   38,  113,  170,   54,  170,  170,
442
+       75,  170,   78,  145,  170,  143,  170,  170,  170,  138,
443
+      170,  124,  170,  170,  142,  170,  170,  126,   71,  170,
444
+      170,  170,  170,  170,    0,  103,  100,   94,  170,  106,
445
+      104,   96,    0,   92,  102,   95,   90,   91,    0,    0,
446
+       91,   97,   84,    0,   83,   93,   80,   88,  170,  170,
447
+
448
+       88,  170,  170,  170,  122,  170,  106,   78,   87,   86,
449
+        0,   89,   73,   83,    0,   72,    0,   83,   83,    0,
450
+        0,   67,   71,   77,   71,   68,    0,    0,   63,   63,
451
+        0,   65,    0,   65,   53,    0,    0,   61,    0,    0,
452
+       53,    0,   63,   51,    0,   45,    0,    0,   51,    0,
453
+      170,  104,  106,   81,  108
453 454
     } ;
454 455
 
455
-static yyconst flex_int16_t yy_def[152] =
456
+static yyconst flex_int16_t yy_def[156] =
456 457
     {   0,
457
-      147,    1,  147,  147,  147,  147,  148,  147,  147,  147,
458
-      149,  147,  147,  147,  147,  147,  147,  147,  147,  147,
459
-      147,  147,  147,  147,  147,  150,  150,  150,  150,  147,
460
-      147,  147,  150,  150,  150,  150,  150,  150,  150,  150,
461
-      150,  150,  150,  150,  150,  150,  147,  147,  147,  147,
462
-      147,  147,  147,  148,  147,  147,  147,  149,  147,  147,
463
-      147,  147,  151,  147,  147,  147,  147,  147,  147,  147,
464
-      147,  147,  150,  150,  150,  150,  147,  150,  150,  150,
465
-      150,  150,  150,  150,  150,  150,  150,  150,  150,  150,
466
-      150,  150,  150,  150,  150,  150,  147,  147,  147,  147,
467
-
468
-      151,  147,  147,  150,  150,  150,  150,  150,  150,  150,
469
-      150,  150,  150,  150,  150,  150,  150,  150,  150,  150,
470
-      150,  150,  150,  150,  150,  150,  150,  150,  150,  150,
471
-      150,  150,  150,  150,  150,  150,  150,  150,  150,  150,
472
-      150,  150,  150,  150,  150,  150,    0,  147,  147,  147,
473
-      147
458
+      151,    1,  151,  151,  151,  151,  152,  151,  151,  151,
459
+      153,  151,  151,  151,  151,  151,  151,  151,  151,  151,
460
+      151,  151,  151,  151,  151,  154,  154,  154,  154,  151,
461
+      151,  151,  154,  154,  154,  154,  154,  154,  154,  154,
462
+      154,  154,  154,  154,  154,  154,  151,  151,  151,  151,
463
+      151,  151,  151,  151,  151,  152,  151,  151,  151,  153,
464
+      151,  151,  151,  151,  155,  151,  151,  151,  151,  151,
465
+      151,  151,  151,  151,  154,  154,  154,  154,  151,  154,
466
+      154,  154,  154,  154,  154,  154,  154,  154,  154,  154,
467
+      154,  154,  154,  154,  154,  154,  154,  154,  151,  151,
468
+
469
+      151,  151,  151,  151,  155,  151,  151,  154,  154,  154,
470
+      154,  154,  154,  154,  154,  154,  154,  154,  154,  154,
471
+      154,  154,  154,  154,  154,  154,  154,  154,  154,  154,
472
+      154,  154,  154,  154,  154,  154,  154,  154,  154,  154,
473
+      154,  154,  154,  154,  154,  154,  154,  154,  154,  154,
474
+        0,  151,  151,  151,  151
474 475
     } ;
475 476
 
476
-static yyconst flex_uint16_t yy_nxt[215] =
477
+static yyconst flex_uint16_t yy_nxt[223] =
477 478
     {   0,
478 479
         4,    5,    5,    6,    7,    8,    9,   10,   11,   12,
479 480
        13,   14,   15,   16,   17,   18,   19,   20,   21,   22,
480 481
        23,   24,   25,   26,   27,   28,   29,   30,   31,   32,
481 482
        33,   34,   35,   36,   37,   38,   26,   39,   26,   40,
482 483
        41,   42,   43,   44,   26,   45,   26,   46,   47,   48,
483
-       49,   50,   51,   51,   52,   56,   60,   63,   66,   84,
484
-       67,   68,   69,   82,   64,   83,   61,   71,   72,   57,
485
-       87,   85,   53,   94,   97,   86,   88,   51,   51,   66,
486
-       95,   67,   73,  146,  145,  144,  143,  142,  141,  140,
487
-      139,  138,  137,  136,  135,  134,  133,  132,  131,  130,
488
-
489
-      129,  128,   98,   54,   54,   58,   58,  101,  101,  127,
490
-      126,  125,  124,  123,  122,  103,  102,  121,  120,  119,
491
-      118,  117,  116,  115,  114,  113,  112,  111,  110,  109,
492
-      108,  107,  106,  105,  104,  103,  102,  100,   59,   55,
493
-       99,   96,   93,   92,   91,   90,   89,   81,   80,   79,
494
-       78,   77,   76,   75,   74,   70,   65,   62,   59,   55,
495
-      147,    3,  147,  147,  147,  147,  147,  147,  147,  147,
496
-      147,  147,  147,  147,  147,  147,  147,  147,  147,  147,
497
-      147,  147,  147,  147,  147,  147,  147,  147,  147,  147,
498
-      147,  147,  147,  147,  147,  147,  147,  147,  147,  147,
499
-
500
-      147,  147,  147,  147,  147,  147,  147,  147,  147,  147,
501
-      147,  147,  147,  147
484
+       49,   50,   51,   53,   53,   54,   58,   62,   65,   68,
485
+       52,   69,   70,   71,   84,   66,   85,   63,   73,   74,
486
+       59,   86,   89,   55,   96,   99,  101,   53,   90,   53,
487
+       53,   97,   75,   87,  102,  150,   68,   88,   69,  101,
488
+       53,  149,  148,  147,  146,  145,  144,  102,  143,  142,
489
+
490
+      141,  140,  139,  100,   56,   56,   60,   60,  105,  105,
491
+      138,  137,  136,  135,  134,  133,  132,  131,  130,  129,
492
+      128,  127,  126,  107,  106,  125,  124,  123,  122,  121,
493
+      120,  119,  118,  117,  116,  115,  114,  113,  112,  111,
494
+      110,  109,  108,  107,  106,  104,   61,   57,  103,   98,
495
+       95,   94,   93,   92,   91,   83,   82,   81,   80,   79,
496
+       78,   77,   76,   72,   67,   64,   61,   57,  151,    3,
497
+      151,  151,  151,  151,  151,  151,  151,  151,  151,  151,
498
+      151,  151,  151,  151,  151,  151,  151,  151,  151,  151,
499
+      151,  151,  151,  151,  151,  151,  151,  151,  151,  151,
500
+
501
+      151,  151,  151,  151,  151,  151,  151,  151,  151,  151,
502
+      151,  151,  151,  151,  151,  151,  151,  151,  151,  151,
503
+      151,  151
502 504
     } ;
503 505
 
504
-static yyconst flex_int16_t yy_chk[215] =
506
+static yyconst flex_int16_t yy_chk[223] =
505 507
     {   0,
506 508
         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
507 509
         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
508 510
         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
509 511
         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
510 512
         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
511
-        1,    1,    5,    5,    6,   10,   14,   17,   20,   38,
512
-       20,   23,   23,   37,   17,   37,   14,   25,   25,   10,
513
-       39,   38,    6,   45,   48,   38,   39,   51,   51,   67,
514
-       45,   67,  150,  145,  142,  140,  139,  137,  134,  131,
515
-      130,  128,  126,  125,  122,  121,  120,  119,  118,  115,
516
-
517
-      114,  112,   48,  148,  148,  149,  149,  151,  151,  110,
518
-      109,  108,  106,  105,  104,  103,  101,   96,   95,   94,
519
-       93,   91,   90,   89,   86,   85,   84,   83,   82,   80,
520
-       79,   78,   76,   75,   74,   66,   63,   60,   58,   54,
521
-       52,   46,   44,   43,   42,   41,   40,   36,   35,   34,
522
-       33,   32,   29,   28,   27,   24,   19,   15,   11,    7,
523
-        3,  147,  147,  147,  147,  147,  147,  147,  147,  147,
524
-      147,  147,  147,  147,  147,  147,  147,  147,  147,  147,
525
-      147,  147,  147,  147,  147,  147,  147,  147,  147,  147,
526
-      147,  147,  147,  147,  147,  147,  147,  147,  147,  147,
527
-
528
-      147,  147,  147,  147,  147,  147,  147,  147,  147,  147,
529
-      147,  147,  147,  147
513
+        1,    1,    2,    5,    5,    6,   10,   14,   17,   20,
514
+        2,   20,   23,   23,   37,   17,   37,   14,   25,   25,
515
+       10,   38,   39,    6,   45,   48,   51,   51,   39,   53,
516
+       53,   45,  154,   38,   51,  149,   69,   38,   69,  101,
517
+      101,  146,  144,  143,  141,  138,  135,  101,  134,  132,
518
+
519
+      130,  129,  126,   48,  152,  152,  153,  153,  155,  155,
520
+      125,  124,  123,  122,  119,  118,  116,  114,  113,  112,
521
+      110,  109,  108,  107,  105,   98,   97,   96,   95,   93,
522
+       92,   91,   88,   87,   86,   85,   84,   82,   81,   80,
523
+       78,   77,   76,   68,   65,   62,   60,   56,   54,   46,
524
+       44,   43,   42,   41,   40,   36,   35,   34,   33,   32,
525
+       29,   28,   27,   24,   19,   15,   11,    7,    3,  151,
526
+      151,  151,  151,  151,  151,  151,  151,  151,  151,  151,
527
+      151,  151,  151,  151,  151,  151,  151,  151,  151,  151,
528
+      151,  151,  151,  151,  151,  151,  151,  151,  151,  151,
529
+
530
+      151,  151,  151,  151,  151,  151,  151,  151,  151,  151,
531
+      151,  151,  151,  151,  151,  151,  151,  151,  151,  151,
532
+      151,  151
530 533
     } ;
531 534
 
532 535
 static yy_state_type yy_last_accepting_state;
@@ -618,7 +621,7 @@ static void update_loc(YYLTYPE *yylloc, char *yytext){
618 621
 <STRING>. { str_putc(*yytext); }
619 622
 
620 623
 */
621
-#line 622 "lex.yy.c"
624
+#line 625 "lex.yy.c"
622 625
 
623 626
 #define INITIAL 0
624 627
 
@@ -809,6 +812,9 @@ extern int yylex \
809 812
 #endif
810 813
 
811 814
 #define YY_RULE_SETUP \
815
+	if ( yyleng > 0 ) \
816
+		YY_CURRENT_BUFFER_LVALUE->yy_at_bol = \
817
+				(yytext[yyleng - 1] == '\n'); \
812 818
 	YY_USER_ACTION
813 819
 
814 820
 /** The main scanner function which does all the work.
@@ -857,7 +863,7 @@ YY_DECL
857 863
 #line 85 "tokenizer.lex"
858 864
 
859 865
 
860
-#line 861 "lex.yy.c"
866
+#line 867 "lex.yy.c"
861 867
 
862 868
 	while ( /*CONSTCOND*/1 )		/* loops until end-of-file is reached */
863 869
 		{
@@ -872,6 +878,7 @@ YY_DECL
872 878
 		yy_bp = yy_cp;
873 879
 
874 880
 		yy_current_state = (yy_start);
881
+		yy_current_state += YY_AT_BOL();
875 882
 yy_match:
876 883
 		do
877 884
 			{
@@ -884,13 +891,13 @@ yy_match:
884 891
 			while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
885 892
 				{
886 893
 				yy_current_state = (int) yy_def[yy_current_state];
887
-				if ( yy_current_state >= 148 )
894
+				if ( yy_current_state >= 152 )
888 895
 					yy_c = yy_meta[(unsigned int) yy_c];
889 896
 				}
890 897
 			yy_current_state = yy_nxt[yy_base[yy_current_state] + (flex_int16_t) yy_c];
891 898
 			++yy_cp;
892 899
 			}
893
-		while ( yy_base[yy_current_state] != 162 );
900
+		while ( yy_base[yy_current_state] != 170 );
894 901
 
895 902
 yy_find_action:
896 903
 		yy_act = yy_accept[yy_current_state];
@@ -1219,66 +1226,71 @@ YY_RULE_SETUP
1219 1226
 case 61:
1220 1227
 YY_RULE_SETUP
1221 1228
 #line 207 "tokenizer.lex"
1222
-{ return LPAREN; }
1229
+{ return BLPAREN; } /* "Breaking" paren, not allowed to introduce a call_expr */
1223 1230
 	YY_BREAK
1224 1231
 case 62:
1225 1232
 YY_RULE_SETUP
1226 1233
 #line 209 "tokenizer.lex"
1227
-{ return RPAREN; }
1234
+{ return LPAREN; } 
1228 1235
 	YY_BREAK
1229 1236
 case 63:
1230 1237
 YY_RULE_SETUP
1231 1238
 #line 211 "tokenizer.lex"
1232
-{ return DOT; }
1239
+{ return RPAREN; }
1233 1240
 	YY_BREAK
1234 1241
 case 64:
1235 1242
 YY_RULE_SETUP
1236 1243
 #line 213 "tokenizer.lex"
1237
-{ return COLON; }
1244
+{ return DOT; }
1238 1245
 	YY_BREAK
1239 1246
 case 65:
1240 1247
 YY_RULE_SETUP
1241 1248
 #line 215 "tokenizer.lex"
1242
-{ return SEMICOLON; }
1249
+{ return COLON; }
1243 1250
 	YY_BREAK
1244 1251
 case 66:
1245 1252
 YY_RULE_SETUP
1246 1253
 #line 217 "tokenizer.lex"
1247
-{ return COMMA; }
1254
+{ return SEMICOLON; }
1248 1255
 	YY_BREAK
1249 1256
 case 67:
1250 1257
 YY_RULE_SETUP
1251 1258
 #line 219 "tokenizer.lex"
1252
-{ return POUND; }
1259
+{ return COMMA; }
1253 1260
 	YY_BREAK
1254 1261
 case 68:
1255 1262
 YY_RULE_SETUP
1256 1263
 #line 221 "tokenizer.lex"
1257
-{ return TBANG; }
1264
+{ return POUND; }
1258 1265
 	YY_BREAK
1259 1266
 case 69:
1260 1267
 YY_RULE_SETUP
1261 1268
 #line 223 "tokenizer.lex"
1262
-{ *yylval = (void *) strdup(yytext); return IDENT; }
1269
+{ return TBANG; }
1263 1270
 	YY_BREAK
1264 1271
 case 70:
1265
-/* rule 70 can match eol */
1266 1272
 YY_RULE_SETUP
1267 1273
 #line 225 "tokenizer.lex"
1268
-/* Skip comments */
1274
+{ *yylval = (void *) strdup(yytext); return IDENT; }
1269 1275
 	YY_BREAK
1270 1276
 case 71:
1271 1277
 /* rule 71 can match eol */
1272 1278
 YY_RULE_SETUP
1273 1279
 #line 227 "tokenizer.lex"
1274
-/* Skip whitespace */
1280
+/* Skip comments */
1275 1281
 	YY_BREAK
1276 1282
 case 72:
1283
+/* rule 72 can match eol */
1277 1284
 YY_RULE_SETUP
1278 1285
 #line 229 "tokenizer.lex"
1286
+/* Skip whitespace */
1287
+	YY_BREAK
1288
+case 73:
1289
+YY_RULE_SETUP
1290
+#line 231 "tokenizer.lex"
1279 1291
 ECHO;
1280 1292
 	YY_BREAK
1281
-#line 1282 "lex.yy.c"
1293
+#line 1294 "lex.yy.c"
1282 1294
 case YY_STATE_EOF(INITIAL):
1283 1295
 	yyterminate();
1284 1296
 
@@ -1559,6 +1571,7 @@ static int yy_get_next_buffer (void)
1559 1571
 	char *yy_cp;
1560 1572
     
1561 1573
 	yy_current_state = (yy_start);
1574
+	yy_current_state += YY_AT_BOL();
1562 1575
 
1563 1576
 	for ( yy_cp = (yytext_ptr) + YY_MORE_ADJ; yy_cp < (yy_c_buf_p); ++yy_cp )
1564 1577
 		{
@@ -1571,7 +1584,7 @@ static int yy_get_next_buffer (void)
1571 1584
 		while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
1572 1585
 			{
1573 1586
 			yy_current_state = (int) yy_def[yy_current_state];
1574
-			if ( yy_current_state >= 148 )
1587
+			if ( yy_current_state >= 152 )
1575 1588
 				yy_c = yy_meta[(unsigned int) yy_c];
1576 1589
 			}
1577 1590
 		yy_current_state = yy_nxt[yy_base[yy_current_state] + (flex_int16_t) yy_c];
@@ -1599,11 +1612,11 @@ static int yy_get_next_buffer (void)
1599 1612
 	while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
1600 1613
 		{
1601 1614
 		yy_current_state = (int) yy_def[yy_current_state];
1602
-		if ( yy_current_state >= 148 )
1615
+		if ( yy_current_state >= 152 )
1603 1616
 			yy_c = yy_meta[(unsigned int) yy_c];
1604 1617
 		}
1605 1618
 	yy_current_state = yy_nxt[yy_base[yy_current_state] + (flex_int16_t) yy_c];
1606
-	yy_is_jam = (yy_current_state == 147);
1619
+	yy_is_jam = (yy_current_state == 151);
1607 1620
 
1608 1621
 		return yy_is_jam ? 0 : yy_current_state;
1609 1622
 }
@@ -1719,6 +1732,8 @@ static int yy_get_next_buffer (void)
1719 1732
 	*(yy_c_buf_p) = '\0';	/* preserve yytext */
1720 1733
 	(yy_hold_char) = *++(yy_c_buf_p);
1721 1734
 
1735
+	YY_CURRENT_BUFFER_LVALUE->yy_at_bol = (c == '\n');
1736
+
1722 1737
 	return c;
1723 1738
 }
1724 1739
 #endif	/* ifndef YY_NO_INPUT */
@@ -2279,7 +2294,7 @@ void yyfree (void * ptr )
2279 2294
 
2280 2295
 #define YYTABLES_NAME "yytables"
2281 2296
 
2282
-#line 229 "tokenizer.lex"
2297
+#line 231 "tokenizer.lex"
2283 2298
 
2284 2299
 
2285 2300
 

+ 3025
- 2545
parser.output
File diff suppressed because it is too large
View File


+ 460
- 411
parser.tab.c
File diff suppressed because it is too large
View File


+ 11
- 10
parser.tab.h View File

@@ -95,16 +95,17 @@ extern int yydebug;
95 95
     LSHIFT = 305,
96 96
     LBRACE = 306,
97 97
     RBRACE = 307,
98
-    LPAREN = 308,
99
-    RPAREN = 309,
100
-    LBRACKET = 310,
101
-    RBRACKET = 311,
102
-    DOT = 312,
103
-    COLON = 313,
104
-    SEMICOLON = 314,
105
-    COMMA = 315,
106
-    POUND = 316,
107
-    TBANG = 317
98
+    BLPAREN = 308,
99
+    LPAREN = 309,
100
+    RPAREN = 310,
101
+    LBRACKET = 311,
102
+    RBRACKET = 312,
103
+    DOT = 313,
104
+    COLON = 314,
105
+    SEMICOLON = 315,
106
+    COMMA = 316,
107
+    POUND = 317,
108
+    TBANG = 318
108 109
   };
109 110
 #endif
110 111
 

+ 89
- 8
parser.y View File

@@ -20,7 +20,7 @@
20 20
 %token PLUS MINUS STAR SLASH PERCENT DSTAR BAND BOR BXOR BNOT LAND LOR LNOT
21 21
 %token ASSIGN ASSIGNPLUS ASSIGNMINUS ASSIGNSTAR ASSIGNSLASH ASSIGNDSTAR ASSIGNBAND ASSIGNBOR ASSIGNBXOR
22 22
 %token EQUAL NEQUAL LESS GREATER LESSEQ GREATEREQ RSHIFT LSHIFT
23
-%token LBRACE RBRACE LPAREN RPAREN LBRACKET RBRACKET DOT COLON SEMICOLON COMMA POUND
23
+%token LBRACE RBRACE BLPAREN LPAREN RPAREN LBRACKET RBRACKET DOT COLON SEMICOLON COMMA POUND
24 24
 %token TBANG
25 25
 
26 26
 %parse-param {stmt_node **program}
@@ -370,28 +370,28 @@ call_expr:
370 370
 ;
371 371
 
372 372
 funcdecl_expr:
373
-  FUNC IDENT LPAREN ident_list RPAREN stmt_list END {
373
+  FUNC IDENT any_lparen param_list RPAREN stmt_list END {
374 374
 	$$ = NEW_EX();
375 375
 	AS_EX($$)->type = EX_FUNCDECL;
376 376
 	AS_EX($$)->funcdecl = NEW(funcdecl_node);
377 377
 	AS_EX($$)->funcdecl->name = $2;
378
-	AS_EX($$)->funcdecl->args = $4;
378
+	AS_EX($$)->funcdecl->params = $4;
379 379
 	AS_EX($$)->funcdecl->body = $6;
380 380
 }
381
-| FUNC LPAREN ident_list RPAREN stmt_list END {
381
+| FUNC any_lparen param_list RPAREN stmt_list END {
382 382
 	$$ = NEW_EX();
383 383
 	AS_EX($$)->type = EX_FUNCDECL;
384 384
 	AS_EX($$)->funcdecl = NEW(funcdecl_node);
385 385
 	AS_EX($$)->funcdecl->name = NULL;
386
-	AS_EX($$)->funcdecl->args = $3;
386
+	AS_EX($$)->funcdecl->params = $3;
387 387
 	AS_EX($$)->funcdecl->body = $5;
388 388
 }
389
-| LAMBDA LPAREN ident_list RPAREN expr END {
389
+| LAMBDA any_lparen param_list RPAREN expr END {
390 390
 	$$ = NEW_EX();
391 391
 	AS_EX($$)->type = EX_FUNCDECL;
392 392
 	AS_EX($$)->funcdecl = NEW(funcdecl_node);
393 393
 	AS_EX($$)->funcdecl->name = NULL;
394
-	AS_EX($$)->funcdecl->args = $3;
394
+	AS_EX($$)->funcdecl->params = $3;
395 395
 	AS_EX($$)->funcdecl->body = NEW_ST();
396 396
 	AS_EX($$)->funcdecl->body->type = ST_RET;
397 397
 	AS_EX($$)->funcdecl->body->ret = NEW(ret_node);
@@ -452,7 +452,7 @@ gen_expr:
452 452
 ;
453 453
 
454 454
 paren_expr:
455
-  LPAREN expr RPAREN { $$ = $2; }
455
+  any_lparen expr RPAREN { $$ = $2; }
456 456
 ;
457 457
 
458 458
 expr_list:
@@ -493,6 +493,82 @@ ident_list:
493 493
 }
494 494
 ;
495 495
 
496
+param_list:
497
+  /*empty*/ { $$ = NULL; }
498
+| param_list IDENT ASSIGN expr {
499
+	paramlist_node *pl = $1;
500
+	identlist_node *curk;
501
+	exprlist_node *curv;
502
+	if(!pl) {
503
+		pl = NEW(paramlist_node);
504
+		pl->args = NULL;
505
+		pl->clkeys = NULL;
506
+		pl->clvalues = NULL;
507
+		pl->rest = NULL;
508
+	}
509
+	if(!pl->clkeys) {
510
+		pl->clkeys = NEW(identlist_node);
511
+		curk = pl->clkeys;
512
+		pl->clvalues = NEW(exprlist_node);
513
+		curv = pl->clvalues;
514
+	} else {
515
+		curk = pl->clkeys;
516
+		curv = pl->clvalues;
517
+		while(curk->next) {
518
+			curk = curk->next;
519
+			curv = curv->next;
520
+		}
521
+		curk->next = NEW(identlist_node);
522
+		curk = curk->next;
523
+		curv->next = NEW(exprlist_node);
524
+		curv = curv->next;
525
+	}
526
+	curk->ident = $2;
527
+	curk->next = NULL;
528
+	curv->expr = $4;
529
+	curv->next = NULL;
530
+	$$ = pl;
531
+}
532
+| param_list STAR IDENT {
533
+	paramlist_node *pl = $1;
534
+	if(!pl) {
535
+		pl = NEW(paramlist_node);
536
+		pl->args = NULL;
537
+		pl->clkeys = NULL;
538
+		pl->clvalues = NULL;
539
+		pl->rest = NULL;
540
+	}
541
+	pl-> rest = $3;
542
+	$$ = pl;
543
+}
544
+| param_list IDENT {
545
+	paramlist_node *pl = $1;
546
+	identlist_node *cura;
547
+	if(!pl) {
548
+		pl = NEW(paramlist_node);
549
+		pl->args = NULL;
550
+		pl->clkeys = NULL;
551
+		pl->clvalues = NULL;
552
+		pl->rest = NULL;
553
+	}
554
+	if(!pl->args) {
555
+		pl->args = NEW(identlist_node);
556
+		cura = pl->args;
557
+	} else {
558
+		cura = pl->args;
559
+		while(cura->next) {
560
+			cura = cura->next;
561
+		}
562
+		cura->next = NEW(identlist_node);
563
+		cura = cura->next;
564
+	}
565
+	cura->ident = $2;
566
+	cura->next = NULL;
567
+	$$ = pl;
568
+}
569
+| param_list COMMA { $$ = $1; }
570
+;
571
+
496 572
 assoc_list:
497 573
   /*empty*/ { $$ = NULL; }
498 574
 | assoc_item {
@@ -529,6 +605,11 @@ assoc_item:
529 605
 }
530 606
 ;
531 607
 
608
+any_lparen:
609
+  LPAREN
610
+| BLPAREN
611
+;
612
+
532 613
 %%
533 614
 
534 615
 // TODO

+ 46
- 6
runtime.c View File

@@ -177,7 +177,7 @@ expr_node *ex_copy(expr_node *old) {
177 177
 			} else {
178 178
 				new->funcdecl->name = NULL;
179 179
 			}
180
-			new->funcdecl->args = idl_copy(old->funcdecl->args);
180
+			new->funcdecl->params = pl_copy(old->funcdecl->params);
181 181
 			new->funcdecl->body = st_copy(old->funcdecl->body);
182 182
 			break;
183 183
 
@@ -288,6 +288,17 @@ identlist_node *idl_copy(identlist_node *old) {
288 288
 	return new;
289 289
 }
290 290
 
291
+paramlist_node *pl_copy(paramlist_node *old) {
292
+	paramlist_node *new;
293
+	if(!old) return NULL;
294
+	new = NEW(paramlist_node);
295
+	new->args = idl_copy(old->args);
296
+	new->clkeys = idl_copy(old->clkeys);
297
+	new->clvalues = exl_copy(old->clvalues);
298
+	new->rest = old->rest ? strdup(old->rest) : NULL;
299
+	return new;
300
+}
301
+
291 302
 void ex_free(expr_node *);
292 303
 
293 304
 void st_free(stmt_node *stmt) {
@@ -401,7 +412,7 @@ void ex_free(expr_node *expr) {
401 412
 		case EX_FUNCDECL:
402 413
 			free(expr->funcdecl->name);
403 414
 			st_free(expr->funcdecl->body);
404
-			idl_free(expr->funcdecl->args);
415
+			pl_free(expr->funcdecl->params);
405 416
 			free(expr->funcdecl);
406 417
 			break;
407 418
 
@@ -466,11 +477,20 @@ void idl_free(identlist_node *list) {
466 477
 	}
467 478
 }
468 479
 
480
+void pl_free(paramlist_node *list) {
481
+	if(!list) return;
482
+	idl_free(list->args);
483
+	idl_free(list->clkeys);
484
+	exl_free(list->clvalues);
485
+	if(list->rest) free(list->rest);
486
+}
487
+
469 488
 #define ERR_CHECK(state) do { if(sol_has_error(state)) longjmp(jmp, 1); } while(0)
470 489
 sol_object_t *sol_eval_inner(sol_state_t *state, expr_node *expr, jmp_buf jmp) {
471 490
 	sol_object_t *res, *left, *right, *lint, *rint, *value, *list, *vint, *iter, *item;
472 491
 	exprlist_node *cure;
473 492
 	assoclist_node *cura;
493
+	identlist_node *curi;
474 494
 	if(!expr) {
475 495
 		return sol_set_error_string(state, "Evaluate NULL expression");
476 496
 	}
@@ -761,8 +781,19 @@ sol_object_t *sol_eval_inner(sol_state_t *state, expr_node *expr, jmp_buf jmp) {
761 781
 			break;
762 782
 
763 783
 		case EX_FUNCDECL:
764
-			res = sol_new_func(state, expr->funcdecl->args, expr->funcdecl->body, expr->funcdecl->name);
784
+			res = sol_new_func(state, expr->funcdecl->params ? expr->funcdecl->params->args : NULL, expr->funcdecl->body, expr->funcdecl->name);
765 785
 			ERR_CHECK(state);
786
+			if(expr->funcdecl->params) {
787
+				res->rest = expr->funcdecl->params->rest ? strdup(expr->funcdecl->params->rest) : NULL;
788
+				curi = expr->funcdecl->params->clkeys;
789
+				cure = expr->funcdecl->params->clvalues;
790
+				while(curi) {
791
+					sol_map_borrow_name(state, res->closure, curi->ident, sol_eval_inner(state, cure->expr, jmp));
792
+					ERR_CHECK(state);
793
+					curi = curi->next;
794
+					cure = cure->next;
795
+				}
796
+			}
766 797
 			if(expr->funcdecl->name) {
767 798
 				sol_state_assign_l_name(state, expr->funcdecl->name, res);
768 799
 				ERR_CHECK(state);
@@ -821,7 +852,7 @@ sol_object_t *sol_eval_inner(sol_state_t *state, expr_node *expr, jmp_buf jmp) {
821 852
 				iter = CALL_METHOD(state, value, iter, list);
822 853
 				sol_obj_free(list);
823 854
 			} else {
824
-				iter = value;
855
+				iter = sol_incref(value);
825 856
 			}
826 857
 			if(!iter->ops->call || iter->ops->call == sol_f_not_impl) {
827 858
 				sol_obj_free(sol_set_error_string(state, "Iterate over non-iterable"));
@@ -832,12 +863,12 @@ sol_object_t *sol_eval_inner(sol_state_t *state, expr_node *expr, jmp_buf jmp) {
832 863
 			sol_list_insert(state, list, 1, value);
833 864
 			sol_list_insert(state, list, 2, sol_new_map(state));
834 865
 			item = CALL_METHOD(state, iter, call, list);
835
-			while(item != state->StopIteration) {
866
+			while(item != state->None) {
836 867
 				sol_state_assign_l_name(state, expr->iter->var, item);
837 868
 				sol_exec(state, expr->iter->loop);
838 869
 				sol_obj_free(item);
839 870
 				if(state->ret || state->sflag == SF_BREAKING || sol_has_error(state)) {
840
-					item = sol_incref(state->StopIteration);
871
+					item = sol_incref(state->None);
841 872
 					continue;
842 873
 				}
843 874
 				state->sflag = SF_NORMAL;
@@ -937,6 +968,7 @@ sol_object_t *sol_f_func_call(sol_state_t *state, sol_object_t *args) {
937 968
 	sol_object_t *res, *scope, *value, *key;
938 969
 	identlist_node *curi;
939 970
 	dsl_seq_iter *iter;
971
+	int argcnt = 0;
940 972
 	iter = dsl_new_seq_iter(args->seq);
941 973
 	if(!args || dsl_seq_iter_is_invalid(iter) || sol_is_none(state, args)) {
942 974
 		printf("WARNING: No parameters to function call (expecting function)\n");
@@ -964,6 +996,14 @@ sol_object_t *sol_f_func_call(sol_state_t *state, sol_object_t *args) {
964 996
 			}
965 997
 			sol_obj_free(key);
966 998
 			curi = curi->next;
999
+			argcnt++;
1000
+		}
1001
+	}
1002
+	if(value->rest) {
1003
+		if(argcnt < sol_list_len(state, args) - 1) {
1004
+			sol_map_borrow_name(state, scope, value->rest, sol_list_sublist(state, args, argcnt + 1));
1005
+		} else {
1006
+			sol_map_borrow_name(state, scope, value->rest, sol_new_list(state));
967 1007
 		}
968 1008
 	}
969 1009
 	if(value->fname) {

+ 16
- 8
sol.h View File

@@ -10,7 +10,7 @@
10 10
 #include "dsl/dsl.h"
11 11
 
12 12
 /** The version of the project, as made available through `debug.version`. */
13
-#define VERSION "0.2a3"
13
+#define VERSION "0.3a0"
14 14
 /** The hexadecimal version of the project, formatted 0xAAIIRPP where:
15 15
  * 
16 16
  * - AA is the two-digit major version
@@ -20,7 +20,7 @@
20 20
  *
21 21
  * This value is guaranteed to only monotonically increase by revision.
22 22
  */
23
-#define HEXVER 0x0002A03
23
+#define HEXVER 0x0003A00
24 24
 
25 25
 #ifndef SOL_ICACHE_MIN
26 26
 /** The smallest integer to cache. */
@@ -156,7 +156,7 @@ typedef struct {
156 156
  */
157 157
 
158 158
 typedef enum {
159
-	/** The singlet type--the type of None, as well as StopIteration and OutOfMemory. It is also the "default" type. */
159
+	/** The singlet type--the type of None, as well as OutOfMemory. It is also the "default" type. */
160 160
 	SOL_SINGLET,
161 161
 	/** The integer type, implemented as a long. */
162 162
 	SOL_INTEGER,
@@ -332,6 +332,8 @@ typedef struct sol_tag_object_t {
332 332
 			struct sol_tag_object_t *udata;
333 333
 			/** For `SOL_FUNCTION`, the name of the function if it was not declared anonymously (otherwise NULL). */
334 334
 			char *fname;
335
+			/* For `SOL_FUNCTION`, the name of an argument that receives extra parameters as a list (otherwise NULL). */
336
+			char *rest;
335 337
 		};
336 338
 		/** For `SOL_CFUNCTION`, the C function pointer. */
337 339
 		sol_cfunc_t cfunc;
@@ -390,9 +392,8 @@ typedef struct sol_tag_state_t {
390 392
 	sol_object_t *stderr; ///< Standard error stream object (type `SOL_STREAM`)
391 393
 	sol_object_t *None; ///< The all-important `None` object
392 394
 	sol_object_t *OutOfMemory; ///< The semi-important `OutOfMemory` object
393
-	sol_object_t *StopIteration; ///< The somewhat-important `StopIteration` object
394 395
 	sol_ops_t NullOps; ///< Basic, initialized operations. Not used by any extant object type.
395
-	sol_ops_t SingletOps; ///< Operations on singlets (`None`, `OutOfMemory`, `StopIteration`, etc.)
396
+	sol_ops_t SingletOps; ///< Operations on singlets (`None`, `OutOfMemory`, etc.)
396 397
 	sol_ops_t IntOps; ///< Operations on integers
397 398
 	sol_ops_t FloatOps; ///< Operations on floats
398 399
 	sol_ops_t StringOps; ///< Operations on strings
@@ -426,7 +427,7 @@ typedef struct sol_tag_state_t {
426 427
  * This should be called once (and only once!) for every state; it does the important
427 428
  * work of ensuring that the state is ready to execute code, including:
428 429
  * 
429
- * - Creating the initial singlet values `None`, `OutOfMemory`, and `StopIteration`,
430
+ * - Creating the initial singlet values `None` and `OutOfMemory`,
430 431
  * - Creating and populating the operations on all internally-defined object types.
431 432
  * - Initializing all built-in modules and methods.
432 433
  * - Running any "init.sol" files.
@@ -676,6 +677,8 @@ sol_object_t *sol_f_tofloat(sol_state_t *, sol_object_t *);
676 677
 sol_object_t *sol_f_tostring(sol_state_t *, sol_object_t *);
677 678
 /// Built-in function try
678 679
 sol_object_t *sol_f_try(sol_state_t *, sol_object_t *);
680
+/// Built-in function apply
681
+sol_object_t *sol_f_apply(sol_state_t *, sol_object_t *);
679 682
 /// Built-in function error
680 683
 sol_object_t *sol_f_error(sol_state_t *, sol_object_t *);
681 684
 /// Built-in function type
@@ -871,7 +874,12 @@ sol_object_t *sol_f_stream_open(sol_state_t *, sol_object_t *);
871 874
  * internal routines are special-cased for certain singlets.
872 875
  */
873 876
 sol_object_t *sol_new_singlet(sol_state_t *, const char *);
874
-/** Creates a new integer object with the specified value. */
877
+/** Creates a new integer object with the specified value.
878
+ *
879
+ * If `icache_bypass` is off and this value is within [`SOL_ICACHE_MIN`,
880
+ * `SOL_ICACHE_MAX`] (as set at compile time), a new reference to a cached
881
+ * integer in the state is returned instead.
882
+ */
875 883
 sol_object_t *sol_new_int(sol_state_t *, long);
876 884
 /** Creates a new float object with the specified value. */
877 885
 sol_object_t *sol_new_float(sol_state_t *, double);
@@ -924,7 +932,7 @@ sol_object_t *sol_list_copy(sol_state_t *, sol_object_t *);
924 932
 /** Internal routine to return a new Sol list equivalent to its input up to the
925 933
  *   first n elements. */
926 934
 sol_object_t *sol_list_truncate(sol_state_t *, sol_object_t *, int);
927
-/** Utility routine to insert at the end of a Sol list. */
935
+/** Utility routine to concatenate Sol lists. */
928 936
 void sol_list_append(sol_state_t *, sol_object_t *, sol_object_t *);
929 937
 /** Utility macro to insert an object at the beginning of a Sol list. */
930 938
 #define sol_list_push(st, ls, obj) sol_list_insert(st, ls, 0, obj);

+ 3
- 7
state.c View File

@@ -52,9 +52,6 @@ int sol_state_init(sol_state_t *state) {
52 52
 	if(!(state->OutOfMemory = sol_new_singlet(state, "OutOfMemory"))) {
53 53
 		goto cleanup;
54 54
 	}
55
-	if(!(state->StopIteration = sol_new_singlet(state, "StopIteration"))) {
56
-		goto cleanup;
57
-	}
58 55
 
59 56
 	// We can now use the normal error reporting mechanism, now
60 57
 	// that errors are distinguishable. Set that up now.
@@ -234,13 +231,14 @@ int sol_state_init(sol_state_t *state) {
234 231
 	state->stdout = sol_new_stream(state, stdout, MODE_WRITE);
235 232
 	state->stderr = sol_new_stream(state, stderr, MODE_WRITE);
236 233
 
237
-	// I'm going to buffer all of these together because I can.
234
+	// NB: None is actually a keyword in the language--it doesn't need to be a
235
+	// global (see parser.y)
238 236
 	sol_map_borrow_name(state, globals, "OutOfMemory", state->OutOfMemory);
239
-	sol_map_borrow_name(state, globals, "StopIteration", state->StopIteration);
240 237
 	sol_map_borrow_name(state, globals, "toint", sol_new_cfunc(state, sol_f_toint));
241 238
 	sol_map_borrow_name(state, globals, "tofloat", sol_new_cfunc(state, sol_f_tofloat));
242 239
 	sol_map_borrow_name(state, globals, "tostring", sol_new_cfunc(state, sol_f_tostring));
243 240
 	sol_map_borrow_name(state, globals, "try", sol_new_cfunc(state, sol_f_try));
241
+	sol_map_borrow_name(state, globals, "apply", sol_new_cfunc(state, sol_f_apply));
244 242
 	sol_map_borrow_name(state, globals, "error", sol_new_cfunc(state, sol_f_error));
245 243
 	sol_map_borrow_name(state, globals, "type", sol_new_cfunc(state, sol_f_type));
246 244
 	sol_map_borrow_name(state, globals, "prepr", sol_new_cfunc(state, sol_f_prepr));
@@ -507,7 +505,6 @@ int sol_state_init(sol_state_t *state) {
507 505
 cleanup:
508 506
 	sol_obj_free(state->None);
509 507
 	sol_obj_free(state->OutOfMemory);
510
-	sol_obj_free(state->StopIteration);
511 508
 	return 0;
512 509
 }
513 510
 
@@ -517,7 +514,6 @@ void sol_state_cleanup(sol_state_t *state) {
517 514
 	sol_obj_free(state->error);
518 515
 	sol_obj_free(state->None);
519 516
 	sol_obj_free(state->OutOfMemory);
520
-	sol_obj_free(state->StopIteration);
521 517
 	sol_obj_free(state->stdin);
522 518
 	sol_obj_free(state->stdout);
523 519
 	sol_obj_free(state->stderr);

+ 1
- 2
tests/_lib.sol View File

@@ -1,4 +1,4 @@
1
-func assert(x, msg)
1
+func assert(x, msg, _test_count = 0)
2 2
 	_test_count += 1
3 3
 	io.stdout:write('Test ' + tostring(_test_count) + ': ' + msg)
4 4
 	if !x then
@@ -6,7 +6,6 @@ func assert(x, msg)
6 6
 	end
7 7
 	print("...passed")
8 8
 end
9
-assert.closure._test_count = 0
10 9
 
11 10
 func assert_eq(x, y, msg)
12 11
 	assert(x == y, "equality: " + tostring(x) + " == " + tostring(y) + ": " + msg)

+ 10
- 0
tests/lang_bparen.sol View File

@@ -0,0 +1,10 @@
1
+execfile("tests/_lib.sol")
2
+
3
+func dont_call_me(a) error("dont_call_me was called: " + tostring(a)) end
4
+
5
+('after func_decl')  -- SHOULD be just a ST_EXPR
6
+assert(1, "After funcdecl")
7
+
8
+dont_call_me
9
+('after st_expr')
10
+assert(1, "After st_expr")

+ 17
- 0
tests/lang_variadic.sol View File

@@ -0,0 +1,17 @@
1
+execfile("tests/_lib.sol")
2
+
3
+func pop2(a, b, *l) return l end
4
+
5
+assert_eq(pop2(1, 2, 3, 4, 5), [3, 4, 5], "rest param")
6
+assert_eq(pop2(1, 2), [], "rest param (at affinity)")
7
+assert_eq(pop2(), [], "rest param, (below affinity)")
8
+
9
+func count(i = 0) i += 1; return i end
10
+
11
+assert_eq(count(), 1, "count")
12
+assert_eq(count(), 2, "count")
13
+assert_eq(count(), 3, "count")
14
+
15
+func rg(start, stop) return func(i=start, stop=stop) if i >= stop then return end; i += 1; return i - 1 end end
16
+
17
+assert_eq(for i in rg(3, 10) do continue i end, [3, 4, 5, 6, 7, 8, 9], "iter over count")

+ 3
- 1
tokenizer.lex View File

@@ -204,7 +204,9 @@ None { return NONE; }
204 204
 
205 205
 "]" { return RBRACKET; }
206 206
 
207
-"(" { return LPAREN; }
207
+^[ \t]*"(" { return BLPAREN; } /* "Breaking" paren, not allowed to introduce a call_expr */
208
+
209
+"(" { return LPAREN; } 
208 210
 
209 211
 ")" { return RPAREN; }
210 212
 

Loading…
Cancel
Save