### Sol Part 56: Asymptotically equivalent to a unicorn!

`https://derpicdn.net/img/download/2014/7/6/668821.png`
master
Graham Northup 5 年前

e6f565383f

1. 48
2. 11
ast.h
3. 28
astprint.c
4. 36
builtins.c
5. 247
lex.yy.c
6. 5570
parser.output
7. 871
parser.tab.c
8. 21
parser.tab.h
9. 97
parser.y
10. 52
runtime.c
11. 24
sol.h
12. 10
state.c
13. 3
tests/_lib.sol
14. 10
tests/lang_bparen.sol
15. 17
16. 4
tokenizer.lex

 `@ -21,31 +21,30 @@ while a < 10 do` `end` ``` ``` `-- "Pythonic" for loops; any expression can be used, so long as it` `-- returns a function that will be called until it returns StopIteration` `-- returns a function that will be called until it returns None` `for i in range(10) do print(i) end -- Note Lua-ish keyword delimiting` ``` ``` `-- "func" seems like a good compromise between "def" and "function" :D` `-- (This is a currying add function)` `func outer(a)` ` func inner(b)` ` return func inner(b, a=a)` ` return a+b` ` end` ` inner.closure.a = a` ` return inner` `end` ``` ``` `-- Alternatively...` `outer = lambda(a) lambda(b, a=a) a + b end end` ``` ``` `-- (...and this is an iterator)` `func count(j)` ` inner = func () -- Note: function definitions are expressions, like in Lua` ` inner = func (i = 0, max = j) -- Function definitions are expressions, like in Lua` ` if i >= max then` ` return StopIteration` ` return -- If no value is given, None is implied` ` else` ` i += 1` ` return i - 1` ` end` ` end` ` inner.closure.i = 0` ` inner.closure.max = j` ` return inner` `end` ``` ``` `@ -59,7 +58,7 @@ print({a=1, b=2, ["c"]=3, [4]=5, ["with more spaces"]={health=100, speed=2}})` `object = {__index = func(obj, idx) print("Index", obj, "with", idx); return idx end,` ` __setindex = func(obj, idx, val) print("Set index", idx, "of", obj, "to", val) end,` ` __call = func(obj, arg1, arg2) print("Called", obj, "with args", arg1, arg2); return arg1+arg2 end}` `-- No metatables, but __index can be assigned to another map, which has nearly the same effect :D` `-- No metatables, but __index can be assigned to another map, which has nearly the same effect` ``` ``` `-- Lua-ish error handling` `func bad(x)` `@ -68,10 +67,11 @@ func bad(x)` `end` ``` ``` `res = try(bad, {}) -- Returns 1 (or true), "thing"` `res = try(bad, None) -- Reurns 0 (or false), "Undefined method" -- you can't index None :P` `res = try(bad, None) -- Reurns 0 (or false), "Undefined method" -- you can't index None` `res = try(bad) -- Also fails; unbound arguments are assigned to None by default` `res = try(error, 1234) -- Fails, returning [0, 1234] -- errors can be any object` ``` ``` `-- Full suppport for self-modifying code, and invoking the compiler :D` `-- Full suppport for self-modifying code, and invoking the compiler` `func a() return 0 end` `func b() return 2 end` ``` ``` `@ -83,7 +83,7 @@ b.stmt = temp` `code = parse('print("Hi!"); return 4')` `a.stmt = code` `b.stmt = code` `-- a and b now return 4` `-- a and b now return 4 (and print "Hi!")` ``` ``` `parse('print("Good day!")')() -- Does the thing; shortcut is "exec"` `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` `Buiding/Installation` `--------------------` ``` ``` `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:` `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:` ``` ``` ````` `git submodule init` `@ -106,13 +106,7 @@ git submodule update` ``` ``` `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).)` ``` ``` `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:` ``` ``` ` ./build.sh` ` ` `This should build the executable runtime `sol` in the working directory (it is explicitly ignored, and won't be committed to the repo).` ``` ``` `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.)` `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).` ``` ``` `Running` `-------` `@ -138,7 +132,9 @@ Todo` ``` ``` `Most of what needs to be done is addressing these issues:` ``` ``` `**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.` `**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!` ``` ``` `**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.` ``` ``` `**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.` ``` ``` `@ -154,16 +150,6 @@ After those (but more practically, with them), the following will be coming:` ``` ``` `**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.` ``` ``` `**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).` ``` ``` `**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.` ``` ``` `**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.` ``` ``` `**Makefiles.** Being a non-conformist is fun, but will probably hurt in the long run :P` ``` ``` `**Documentation.** More thorough documentation will be coming soon, I promise.` ``` ``` `Contributing` `------------` ``` ```

#### 11 ast.h 查看文件

 `@ -129,8 +129,15 @@ typedef struct tag_identlist_node {` `} identlist_node;` ``` ``` `typedef struct {` ` char *name;` ` identlist_node *args;` ` identlist_node *clkeys;` ` exprlist_node *clvalues;` ` char *rest;` `} paramlist_node;` ``` ``` `typedef struct {` ` char *name;` ` paramlist_node *params;` ` stmt_node *body;` `} funcdecl_node;` ``` ``` `@ -257,6 +264,7 @@ stmtlist_node *stl_copy(stmtlist_node *);` `exprlist_node *exl_copy(exprlist_node *);` `assoclist_node *asl_copy(assoclist_node *);` `identlist_node *idl_copy(identlist_node *);` `paramlist_node *pl_copy(paramlist_node *);` ``` ``` `void st_free(stmt_node *);` `void ex_free(expr_node *);` `@ -264,6 +272,7 @@ void stl_free(stmtlist_node *);` `void exl_free(exprlist_node *);` `void asl_free(assoclist_node *);` `void idl_free(identlist_node *);` `void pl_free(paramlist_node *);` ``` ``` `void st_print(sol_state_t *, stmt_node *);` `void ex_print(sol_state_t *, expr_node *);`

#### 28 astprint.c 查看文件

 `@ -273,11 +273,29 @@ void prex(sol_state_t *state, expr_node *node, int lev) {` ` prlev(state, lev, "FuncDecl:");` ` lev++;` ` prlev(state, lev, "Name: %s", node->funcdecl->name);` ` prlev(state, lev, "Args:");` ` curi = node->funcdecl->args;` ` while(curi && curi->ident) {` ` prlev(state, lev + 1, curi->ident);` ` curi = curi->next;` ` prlev(state, lev, "Params:");` ` if(!node->funcdecl->params) {` ` prlev(state, lev + 1, "");` ` } else {` ` prlev(state, lev + 1, "Args:");` ` curi = node->funcdecl->params->args;` ` while(curi && curi->ident) {` ` prlev(state, lev + 2, curi->ident);` ` curi = curi->next;` ` }` ` prlev(state, lev + 1, "ClKeys:");` ` curi = node->funcdecl->params->clkeys;` ` while(curi && curi->ident) {` ` prlev(state, lev + 2, curi->ident);` ` curi = curi->next;` ` }` ` prlev(state, lev + 1, "ClValues:");` ` cure = node->funcdecl->params->clvalues;` ` while(cure && cure->expr) {` ` prex(state, cure->expr, lev + 2);` ` cure = cure->next;` ` }` ` prlev(state, lev + 1, "Rest: %s", node->funcdecl->params->rest);` ` }` ` prlev(state, lev, "Body:");` ` prst(state, node->funcdecl->body, lev + 1);`

#### 36 builtins.c 查看文件

 `@ -126,6 +126,17 @@ sol_object_t *sol_f_try(sol_state_t *state, sol_object_t *args) {` ` return ls;` `}` ``` ``` `sol_object_t *sol_f_apply(sol_state_t *state, sol_object_t *args) {` ` 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);` ` sol_list_append(state, rest, arglist);` ` sol_obj_free(arglist);` ` sol_list_insert(state, rest, 0, func);` ` sol_object_t *res = CALL_METHOD(state, func, call, rest);` ` sol_obj_free(rest);` ` sol_obj_free(func);` ` return res;` `}` ``` ``` `sol_object_t *sol_f_error(sol_state_t *state, sol_object_t *args) {` ` sol_object_t *arg = sol_list_get_index(state, args, 0), *res;` ` 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) {` ` sol_obj_free(index);` ` sol_obj_free(obj);` ` sol_obj_free(local);` ` return sol_incref(state->StopIteration);` ` return sol_incref(state->None);` ` }` ` temp[0] = obj->str[((size_t) index->buffer)];` ` 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) {` ` sol_obj_free(index);` ` sol_obj_free(obj);` ` sol_obj_free(local);` ` return sol_incref(state->StopIteration);` ` return sol_incref(state->None);` ` }` ` res = sol_incref(AS_OBJ(dsl_seq_iter_at(index->buffer)));` ` 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) {` ` sol_obj_free(index);` ` sol_obj_free(obj);` ` sol_obj_free(local);` ` return sol_incref(state->StopIteration);` ` return sol_incref(state->None);` ` }` ` res = sol_incref(AS_OBJ(dsl_seq_iter_at(index->buffer))->key);` ` 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) {` ` res = sol_new_string(state, (expr->funcdecl->name ? expr->funcdecl->name : ""));` ` } else if(sol_string_eq(state, str, "args")) {` ` res = sol_new_list(state);` ` curi = expr->funcdecl->args;` ` curi = expr->funcdecl->params ? expr->funcdecl->params->args : NULL;` ` while(curi) {` ` sol_list_insert(state, res, i++, sol_new_string(state, curi->ident));` ` curi = curi->next;` `@ -2117,11 +2128,18 @@ sol_object_t *sol_f_astnode_setindex(sol_state_t *state, sol_object_t *args) {` ` expr->funcdecl->name = strdup(sval->str);` ` sol_obj_free(sval);` ` } else if(sol_string_eq(state, str, "args") && sol_is_list(val)) {` ` idl_free(expr->funcdecl->args);` ` if(!expr->funcdecl->params) {` ` expr->funcdecl->params = malloc(sizeof(paramlist_node));` ` expr->funcdecl->params->args = NULL;` ` expr->funcdecl->params->clkeys = NULL;` ` expr->funcdecl->params->clvalues = NULL;` ` expr->funcdecl->params->rest = NULL;` ` }` ` idl_free(expr->funcdecl->params->args);` ` len = sol_list_len(state, val);` ` if(len > 0) {` ` curi = malloc(sizeof(identlist_node));` ` expr->funcdecl->args = curi;` ` expr->funcdecl->params->args = curi;` ` for(i = 0; i < len; i++) {` ` sval = sol_cast_string(state, sol_list_get_index(state, val, i));` ` curi->ident = strdup(sval->str);` `@ -2130,15 +2148,15 @@ sol_object_t *sol_f_astnode_setindex(sol_state_t *state, sol_object_t *args) {` ` curi = malloc(sizeof(identlist_node));` ` previ->next = curi;` ` }` ` if(expr->funcdecl->args == curi) {` ` expr->funcdecl->args = NULL;` ` if(expr->funcdecl->params->args == curi) {` ` expr->funcdecl->params->args = NULL;` ` }` ` free(curi);` ` if(previ) {` ` previ->next = NULL;` ` }` ` } else {` ` expr->funcdecl->args = NULL;` ` expr->funcdecl->params->args = NULL;` ` }` ` } else if(sol_string_eq(state, str, "body") && sol_is_aststmt(val)) {` ` st_free(expr->funcdecl->body);`

#### 247 lex.yy.c 查看文件

 `@ -360,8 +360,8 @@ static void yynoreturn yy_fatal_error (yyconst char* msg );` ` *yy_cp = '\0'; \` ` (yy_c_buf_p) = yy_cp;` ``` ``` `#define YY_NUM_RULES 72` `#define YY_END_OF_BUFFER 73` `#define YY_NUM_RULES 73` `#define YY_END_OF_BUFFER 74` `/* This struct is not used in this scanner,` ` but its presence is necessary. */` `struct yy_trans_info` `@ -369,24 +369,25 @@ struct yy_trans_info` ` flex_int32_t yy_verify;` ` flex_int32_t yy_nxt;` ` };` `static yyconst flex_int16_t yy_accept[148] =` `static yyconst flex_int16_t yy_accept[152] =` ` { 0,` ` 0, 0, 73, 72, 71, 34, 72, 67, 23, 26,` ` 72, 61, 62, 21, 19, 66, 20, 63, 22, 2,` ` 64, 65, 51, 40, 52, 69, 69, 69, 69, 59,` ` 60, 28, 69, 69, 69, 69, 69, 69, 69, 69,` ` 69, 69, 69, 69, 69, 69, 57, 27, 58, 29,` ` 71, 0, 50, 0, 3, 30, 46, 0, 4, 25,` ` 43, 41, 0, 42, 44, 1, 2, 56, 53, 49,` ` 54, 55, 69, 69, 69, 69, 48, 69, 69, 69,` ` 11, 69, 69, 69, 69, 69, 5, 10, 69, 69,` ` 69, 33, 69, 69, 69, 69, 47, 32, 68, 45,` ``` ``` ` 0, 70, 1, 69, 69, 69, 31, 69, 69, 69,` ` 17, 69, 9, 69, 69, 24, 35, 69, 69, 69,` ` 69, 69, 18, 37, 69, 69, 7, 69, 12, 69,` ` 69, 6, 36, 69, 39, 15, 69, 38, 69, 69,` ` 8, 69, 13, 14, 69, 16, 0` ` 0, 0, 74, 73, 72, 34, 73, 68, 23, 26,` ` 73, 62, 63, 21, 19, 67, 20, 64, 22, 2,` ` 65, 66, 51, 40, 52, 70, 70, 70, 70, 59,` ` 60, 28, 70, 70, 70, 70, 70, 70, 70, 70,` ` 70, 70, 70, 70, 70, 70, 57, 27, 58, 29,` ` 72, 61, 72, 0, 50, 0, 3, 30, 46, 0,` ` 4, 25, 43, 41, 0, 42, 44, 1, 2, 56,` ` 53, 49, 54, 55, 70, 70, 70, 70, 48, 70,` ` 70, 70, 11, 70, 70, 70, 70, 70, 5, 10,` ` 70, 70, 70, 33, 70, 70, 70, 70, 47, 32,` ``` ``` ` 72, 61, 69, 45, 0, 71, 1, 70, 70, 70,` ` 31, 70, 70, 70, 17, 70, 9, 70, 70, 24,` ` 35, 70, 70, 70, 70, 70, 18, 37, 70, 70,` ` 7, 70, 12, 70, 70, 6, 36, 70, 39, 15,` ` 70, 38, 70, 70, 8, 70, 13, 14, 70, 16,` ` 0` ` } ;` ``` ``` `static yyconst YY_CHAR yy_ec[256] =` `@ -431,102 +432,104 @@ static yyconst YY_CHAR yy_meta[53] =` ` 1, 1` ` } ;` ``` ``` `static yyconst flex_uint16_t yy_base[152] =` `static yyconst flex_uint16_t yy_base[156] =` ` { 0,` ` 0, 0, 161, 162, 51, 51, 155, 162, 162, 48,` ` 150, 162, 162, 45, 136, 162, 43, 162, 135, 43,` ` 162, 162, 41, 134, 46, 0, 124, 111, 109, 162,` ` 162, 130, 109, 106, 106, 105, 24, 29, 35, 116,` ` 103, 102, 100, 108, 37, 105, 162, 53, 162, 162,` ` 76, 137, 162, 135, 162, 162, 162, 130, 162, 116,` ` 162, 162, 134, 162, 162, 118, 64, 162, 162, 162,` ` 162, 162, 0, 95, 92, 86, 162, 98, 96, 88,` ` 0, 84, 94, 87, 82, 83, 0, 0, 83, 89,` ` 76, 0, 75, 85, 72, 80, 162, 162, 162, 162,` ``` ``` ` 114, 162, 98, 70, 79, 78, 0, 81, 65, 75,` ` 0, 57, 0, 68, 68, 0, 0, 52, 56, 62,` ` 56, 60, 0, 0, 55, 55, 0, 57, 0, 57,` ` 46, 0, 0, 54, 0, 0, 46, 0, 56, 44,` ` 0, 38, 0, 0, 49, 0, 162, 103, 105, 81,` ` 107` ` 0, 51, 169, 170, 52, 52, 163, 170, 170, 49,` ` 158, 170, 170, 46, 144, 170, 44, 170, 143, 44,` ` 170, 170, 42, 142, 47, 0, 132, 119, 117, 170,` ` 170, 138, 117, 114, 114, 113, 25, 41, 37, 124,` ` 111, 110, 108, 116, 38, 113, 170, 54, 170, 170,` ` 75, 170, 78, 145, 170, 143, 170, 170, 170, 138,` ` 170, 124, 170, 170, 142, 170, 170, 126, 71, 170,` ` 170, 170, 170, 170, 0, 103, 100, 94, 170, 106,` ` 104, 96, 0, 92, 102, 95, 90, 91, 0, 0,` ` 91, 97, 84, 0, 83, 93, 80, 88, 170, 170,` ``` ``` ` 88, 170, 170, 170, 122, 170, 106, 78, 87, 86,` ` 0, 89, 73, 83, 0, 72, 0, 83, 83, 0,` ` 0, 67, 71, 77, 71, 68, 0, 0, 63, 63,` ` 0, 65, 0, 65, 53, 0, 0, 61, 0, 0,` ` 53, 0, 63, 51, 0, 45, 0, 0, 51, 0,` ` 170, 104, 106, 81, 108` ` } ;` ``` ``` `static yyconst flex_int16_t yy_def[152] =` `static yyconst flex_int16_t yy_def[156] =` ` { 0,` ` 147, 1, 147, 147, 147, 147, 148, 147, 147, 147,` ` 149, 147, 147, 147, 147, 147, 147, 147, 147, 147,` ` 147, 147, 147, 147, 147, 150, 150, 150, 150, 147,` ` 147, 147, 150, 150, 150, 150, 150, 150, 150, 150,` ` 150, 150, 150, 150, 150, 150, 147, 147, 147, 147,` ` 147, 147, 147, 148, 147, 147, 147, 149, 147, 147,` ` 147, 147, 151, 147, 147, 147, 147, 147, 147, 147,` ` 147, 147, 150, 150, 150, 150, 147, 150, 150, 150,` ` 150, 150, 150, 150, 150, 150, 150, 150, 150, 150,` ` 150, 150, 150, 150, 150, 150, 147, 147, 147, 147,` ``` ``` ` 151, 147, 147, 150, 150, 150, 150, 150, 150, 150,` ` 150, 150, 150, 150, 150, 150, 150, 150, 150, 150,` ` 150, 150, 150, 150, 150, 150, 150, 150, 150, 150,` ` 150, 150, 150, 150, 150, 150, 150, 150, 150, 150,` ` 150, 150, 150, 150, 150, 150, 0, 147, 147, 147,` ` 147` ` 151, 1, 151, 151, 151, 151, 152, 151, 151, 151,` ` 153, 151, 151, 151, 151, 151, 151, 151, 151, 151,` ` 151, 151, 151, 151, 151, 154, 154, 154, 154, 151,` ` 151, 151, 154, 154, 154, 154, 154, 154, 154, 154,` ` 154, 154, 154, 154, 154, 154, 151, 151, 151, 151,` ` 151, 151, 151, 151, 151, 152, 151, 151, 151, 153,` ` 151, 151, 151, 151, 155, 151, 151, 151, 151, 151,` ` 151, 151, 151, 151, 154, 154, 154, 154, 151, 154,` ` 154, 154, 154, 154, 154, 154, 154, 154, 154, 154,` ` 154, 154, 154, 154, 154, 154, 154, 154, 151, 151,` ``` ``` ` 151, 151, 151, 151, 155, 151, 151, 154, 154, 154,` ` 154, 154, 154, 154, 154, 154, 154, 154, 154, 154,` ` 154, 154, 154, 154, 154, 154, 154, 154, 154, 154,` ` 154, 154, 154, 154, 154, 154, 154, 154, 154, 154,` ` 154, 154, 154, 154, 154, 154, 154, 154, 154, 154,` ` 0, 151, 151, 151, 151` ` } ;` ``` ``` `static yyconst flex_uint16_t yy_nxt[215] =` `static yyconst flex_uint16_t yy_nxt[223] =` ` { 0,` ` 4, 5, 5, 6, 7, 8, 9, 10, 11, 12,` ` 13, 14, 15, 16, 17, 18, 19, 20, 21, 22,` ` 23, 24, 25, 26, 27, 28, 29, 30, 31, 32,` ` 33, 34, 35, 36, 37, 38, 26, 39, 26, 40,` ` 41, 42, 43, 44, 26, 45, 26, 46, 47, 48,` ` 49, 50, 51, 51, 52, 56, 60, 63, 66, 84,` ` 67, 68, 69, 82, 64, 83, 61, 71, 72, 57,` ` 87, 85, 53, 94, 97, 86, 88, 51, 51, 66,` ` 95, 67, 73, 146, 145, 144, 143, 142, 141, 140,` ` 139, 138, 137, 136, 135, 134, 133, 132, 131, 130,` ``` ``` ` 129, 128, 98, 54, 54, 58, 58, 101, 101, 127,` ` 126, 125, 124, 123, 122, 103, 102, 121, 120, 119,` ` 118, 117, 116, 115, 114, 113, 112, 111, 110, 109,` ` 108, 107, 106, 105, 104, 103, 102, 100, 59, 55,` ` 99, 96, 93, 92, 91, 90, 89, 81, 80, 79,` ` 78, 77, 76, 75, 74, 70, 65, 62, 59, 55,` ` 147, 3, 147, 147, 147, 147, 147, 147, 147, 147,` ` 147, 147, 147, 147, 147, 147, 147, 147, 147, 147,` ` 147, 147, 147, 147, 147, 147, 147, 147, 147, 147,` ` 147, 147, 147, 147, 147, 147, 147, 147, 147, 147,` ``` ``` ` 147, 147, 147, 147, 147, 147, 147, 147, 147, 147,` ` 147, 147, 147, 147` ` 49, 50, 51, 53, 53, 54, 58, 62, 65, 68,` ` 52, 69, 70, 71, 84, 66, 85, 63, 73, 74,` ` 59, 86, 89, 55, 96, 99, 101, 53, 90, 53,` ` 53, 97, 75, 87, 102, 150, 68, 88, 69, 101,` ` 53, 149, 148, 147, 146, 145, 144, 102, 143, 142,` ``` ``` ` 141, 140, 139, 100, 56, 56, 60, 60, 105, 105,` ` 138, 137, 136, 135, 134, 133, 132, 131, 130, 129,` ` 128, 127, 126, 107, 106, 125, 124, 123, 122, 121,` ` 120, 119, 118, 117, 116, 115, 114, 113, 112, 111,` ` 110, 109, 108, 107, 106, 104, 61, 57, 103, 98,` ` 95, 94, 93, 92, 91, 83, 82, 81, 80, 79,` ` 78, 77, 76, 72, 67, 64, 61, 57, 151, 3,` ` 151, 151, 151, 151, 151, 151, 151, 151, 151, 151,` ` 151, 151, 151, 151, 151, 151, 151, 151, 151, 151,` ` 151, 151, 151, 151, 151, 151, 151, 151, 151, 151,` ``` ``` ` 151, 151, 151, 151, 151, 151, 151, 151, 151, 151,` ` 151, 151, 151, 151, 151, 151, 151, 151, 151, 151,` ` 151, 151` ` } ;` ``` ``` `static yyconst flex_int16_t yy_chk[215] =` `static yyconst flex_int16_t yy_chk[223] =` ` { 0,` ` 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,` ` 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,` ` 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,` ` 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,` ` 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,` ` 1, 1, 5, 5, 6, 10, 14, 17, 20, 38,` ` 20, 23, 23, 37, 17, 37, 14, 25, 25, 10,` ` 39, 38, 6, 45, 48, 38, 39, 51, 51, 67,` ` 45, 67, 150, 145, 142, 140, 139, 137, 134, 131,` ` 130, 128, 126, 125, 122, 121, 120, 119, 118, 115,` ``` ``` ` 114, 112, 48, 148, 148, 149, 149, 151, 151, 110,` ` 109, 108, 106, 105, 104, 103, 101, 96, 95, 94,` ` 93, 91, 90, 89, 86, 85, 84, 83, 82, 80,` ` 79, 78, 76, 75, 74, 66, 63, 60, 58, 54,` ` 52, 46, 44, 43, 42, 41, 40, 36, 35, 34,` ` 33, 32, 29, 28, 27, 24, 19, 15, 11, 7,` ` 3, 147, 147, 147, 147, 147, 147, 147, 147, 147,` ` 147, 147, 147, 147, 147, 147, 147, 147, 147, 147,` ` 147, 147, 147, 147, 147, 147, 147, 147, 147, 147,` ` 147, 147, 147, 147, 147, 147, 147, 147, 147, 147,` ``` ``` ` 147, 147, 147, 147, 147, 147, 147, 147, 147, 147,` ` 147, 147, 147, 147` ` 1, 1, 2, 5, 5, 6, 10, 14, 17, 20,` ` 2, 20, 23, 23, 37, 17, 37, 14, 25, 25,` ` 10, 38, 39, 6, 45, 48, 51, 51, 39, 53,` ` 53, 45, 154, 38, 51, 149, 69, 38, 69, 101,` ` 101, 146, 144, 143, 141, 138, 135, 101, 134, 132,` ``` ``` ` 130, 129, 126, 48, 152, 152, 153, 153, 155, 155,` ` 125, 124, 123, 122, 119, 118, 116, 114, 113, 112,` ` 110, 109, 108, 107, 105, 98, 97, 96, 95, 93,` ` 92, 91, 88, 87, 86, 85, 84, 82, 81, 80,` ` 78, 77, 76, 68, 65, 62, 60, 56, 54, 46,` ` 44, 43, 42, 41, 40, 36, 35, 34, 33, 32,` ` 29, 28, 27, 24, 19, 15, 11, 7, 3, 151,` ` 151, 151, 151, 151, 151, 151, 151, 151, 151, 151,` ` 151, 151, 151, 151, 151, 151, 151, 151, 151, 151,` ` 151, 151, 151, 151, 151, 151, 151, 151, 151, 151,` ``` ``` ` 151, 151, 151, 151, 151, 151, 151, 151, 151, 151,` ` 151, 151, 151, 151, 151, 151, 151, 151, 151, 151,` ` 151, 151` ` } ;` ``` ``` `static yy_state_type yy_last_accepting_state;` `@ -618,7 +621,7 @@ static void update_loc(YYLTYPE *yylloc, char *yytext){` `. { str_putc(*yytext); }` ``` ``` `*/` `#line 622 "lex.yy.c"` `#line 625 "lex.yy.c"` ``` ``` `#define INITIAL 0` ``` ``` `@ -809,6 +812,9 @@ extern int yylex \` `#endif` ``` ``` `#define YY_RULE_SETUP \` ` if ( yyleng > 0 ) \` ` YY_CURRENT_BUFFER_LVALUE->yy_at_bol = \` ` (yytext[yyleng - 1] == '\n'); \` ` YY_USER_ACTION` ``` ``` `/** The main scanner function which does all the work.` `@ -857,7 +863,7 @@ YY_DECL` `#line 85 "tokenizer.lex"` ``` ``` ``` ``` `#line 861 "lex.yy.c"` `#line 867 "lex.yy.c"` ``` ``` ` while ( /*CONSTCOND*/1 ) /* loops until end-of-file is reached */` ` {` `@ -872,6 +878,7 @@ YY_DECL` ` yy_bp = yy_cp;` ``` ``` ` yy_current_state = (yy_start);` ` yy_current_state += YY_AT_BOL();` `yy_match:` ` do` ` {` `@ -884,13 +891,13 @@ yy_match:` ` while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )` ` {` ` yy_current_state = (int) yy_def[yy_current_state];` ` if ( yy_current_state >= 148 )` ` if ( yy_current_state >= 152 )` ` yy_c = yy_meta[(unsigned int) yy_c];` ` }` ` yy_current_state = yy_nxt[yy_base[yy_current_state] + (flex_int16_t) yy_c];` ` ++yy_cp;` ` }` ` while ( yy_base[yy_current_state] != 162 );` ` while ( yy_base[yy_current_state] != 170 );` ``` ``` `yy_find_action:` ` yy_act = yy_accept[yy_current_state];` `@ -1219,66 +1226,71 @@ YY_RULE_SETUP` `case 61:` `YY_RULE_SETUP` `#line 207 "tokenizer.lex"` `{ return LPAREN; }` `{ return BLPAREN; } /* "Breaking" paren, not allowed to introduce a call_expr */` ` YY_BREAK` `case 62:` `YY_RULE_SETUP` `#line 209 "tokenizer.lex"` `{ return RPAREN; }` `{ return LPAREN; } ` ` YY_BREAK` `case 63:` `YY_RULE_SETUP` `#line 211 "tokenizer.lex"` `{ return DOT; }` `{ return RPAREN; }` ` YY_BREAK` `case 64:` `YY_RULE_SETUP` `#line 213 "tokenizer.lex"` `{ return COLON; }` `{ return DOT; }` ` YY_BREAK` `case 65:` `YY_RULE_SETUP` `#line 215 "tokenizer.lex"` `{ return SEMICOLON; }` `{ return COLON; }` ` YY_BREAK` `case 66:` `YY_RULE_SETUP` `#line 217 "tokenizer.lex"` `{ return COMMA; }` `{ return SEMICOLON; }` ` YY_BREAK` `case 67:` `YY_RULE_SETUP` `#line 219 "tokenizer.lex"` `{ return POUND; }` `{ return COMMA; }` ` YY_BREAK` `case 68:` `YY_RULE_SETUP` `#line 221 "tokenizer.lex"` `{ return TBANG; }` `{ return POUND; }` ` YY_BREAK` `case 69:` `YY_RULE_SETUP` `#line 223 "tokenizer.lex"` `{ *yylval = (void *) strdup(yytext); return IDENT; }` `{ return TBANG; }` ` YY_BREAK` `case 70:` `/* rule 70 can match eol */` `YY_RULE_SETUP` `#line 225 "tokenizer.lex"` `/* Skip comments */` `{ *yylval = (void *) strdup(yytext); return IDENT; }` ` YY_BREAK` `case 71:` `/* rule 71 can match eol */` `YY_RULE_SETUP` `#line 227 "tokenizer.lex"` `/* Skip whitespace */` `/* Skip comments */` ` YY_BREAK` `case 72:` `/* rule 72 can match eol */` `YY_RULE_SETUP` `#line 229 "tokenizer.lex"` `/* Skip whitespace */` ` YY_BREAK` `case 73:` `YY_RULE_SETUP` `#line 231 "tokenizer.lex"` `ECHO;` ` YY_BREAK` `#line 1282 "lex.yy.c"` `#line 1294 "lex.yy.c"` `case YY_STATE_EOF(INITIAL):` ` yyterminate();` ``` ``` `@ -1559,6 +1571,7 @@ static int yy_get_next_buffer (void)` ` char *yy_cp;` ` ` ` yy_current_state = (yy_start);` ` yy_current_state += YY_AT_BOL();` ``` ``` ` for ( yy_cp = (yytext_ptr) + YY_MORE_ADJ; yy_cp < (yy_c_buf_p); ++yy_cp )` ` {` `@ -1571,7 +1584,7 @@ static int yy_get_next_buffer (void)` ` while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )` ` {` ` yy_current_state = (int) yy_def[yy_current_state];` ` if ( yy_current_state >= 148 )` ` if ( yy_current_state >= 152 )` ` yy_c = yy_meta[(unsigned int) yy_c];` ` }` ` 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)` ` while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )` ` {` ` yy_current_state = (int) yy_def[yy_current_state];` ` if ( yy_current_state >= 148 )` ` if ( yy_current_state >= 152 )` ` yy_c = yy_meta[(unsigned int) yy_c];` ` }` ` yy_current_state = yy_nxt[yy_base[yy_current_state] + (flex_int16_t) yy_c];` ` yy_is_jam = (yy_current_state == 147);` ` yy_is_jam = (yy_current_state == 151);` ``` ``` ` return yy_is_jam ? 0 : yy_current_state;` `}` `@ -1719,6 +1732,8 @@ static int yy_get_next_buffer (void)` ` *(yy_c_buf_p) = '\0'; /* preserve yytext */` ` (yy_hold_char) = *++(yy_c_buf_p);` ``` ``` ` YY_CURRENT_BUFFER_LVALUE->yy_at_bol = (c == '\n');` ``` ``` ` return c;` `}` `#endif /* ifndef YY_NO_INPUT */` `@ -2279,7 +2294,7 @@ void yyfree (void * ptr )` ``` ``` `#define YYTABLES_NAME "yytables"` ``` ``` `#line 229 "tokenizer.lex"` `#line 231 "tokenizer.lex"` ``` ``` ``` ``` ``` ```

#### 21 parser.tab.h 查看文件

 `@ -95,16 +95,17 @@ extern int yydebug;` ` LSHIFT = 305,` ` LBRACE = 306,` ` RBRACE = 307,` ` LPAREN = 308,` ` RPAREN = 309,` ` LBRACKET = 310,` ` RBRACKET = 311,` ` DOT = 312,` ` COLON = 313,` ` SEMICOLON = 314,` ` COMMA = 315,` ` POUND = 316,` ` TBANG = 317` ` BLPAREN = 308,` ` LPAREN = 309,` ` RPAREN = 310,` ` LBRACKET = 311,` ` RBRACKET = 312,` ` DOT = 313,` ` COLON = 314,` ` SEMICOLON = 315,` ` COMMA = 316,` ` POUND = 317,` ` TBANG = 318` ` };` `#endif` ``` ```

#### 97 parser.y 查看文件

 `@ -20,7 +20,7 @@` `%token PLUS MINUS STAR SLASH PERCENT DSTAR BAND BOR BXOR BNOT LAND LOR LNOT` `%token ASSIGN ASSIGNPLUS ASSIGNMINUS ASSIGNSTAR ASSIGNSLASH ASSIGNDSTAR ASSIGNBAND ASSIGNBOR ASSIGNBXOR` `%token EQUAL NEQUAL LESS GREATER LESSEQ GREATEREQ RSHIFT LSHIFT` `%token LBRACE RBRACE LPAREN RPAREN LBRACKET RBRACKET DOT COLON SEMICOLON COMMA POUND` `%token LBRACE RBRACE BLPAREN LPAREN RPAREN LBRACKET RBRACKET DOT COLON SEMICOLON COMMA POUND` `%token TBANG` ``` ``` `%parse-param {stmt_node **program}` `@ -370,28 +370,28 @@ call_expr:` `;` ``` ``` `funcdecl_expr:` ` FUNC IDENT LPAREN ident_list RPAREN stmt_list END {` ` FUNC IDENT any_lparen param_list RPAREN stmt_list END {` ` \$\$ = NEW_EX();` ` AS_EX(\$\$)->type = EX_FUNCDECL;` ` AS_EX(\$\$)->funcdecl = NEW(funcdecl_node);` ` AS_EX(\$\$)->funcdecl->name = \$2;` ` AS_EX(\$\$)->funcdecl->args = \$4;` ` AS_EX(\$\$)->funcdecl->params = \$4;` ` AS_EX(\$\$)->funcdecl->body = \$6;` `}` `| FUNC LPAREN ident_list RPAREN stmt_list END {` `| FUNC any_lparen param_list RPAREN stmt_list END {` ` \$\$ = NEW_EX();` ` AS_EX(\$\$)->type = EX_FUNCDECL;` ` AS_EX(\$\$)->funcdecl = NEW(funcdecl_node);` ` AS_EX(\$\$)->funcdecl->name = NULL;` ` AS_EX(\$\$)->funcdecl->args = \$3;` ` AS_EX(\$\$)->funcdecl->params = \$3;` ` AS_EX(\$\$)->funcdecl->body = \$5;` `}` `| LAMBDA LPAREN ident_list RPAREN expr END {` `| LAMBDA any_lparen param_list RPAREN expr END {` ` \$\$ = NEW_EX();` ` AS_EX(\$\$)->type = EX_FUNCDECL;` ` AS_EX(\$\$)->funcdecl = NEW(funcdecl_node);` ` AS_EX(\$\$)->funcdecl->name = NULL;` ` AS_EX(\$\$)->funcdecl->args = \$3;` ` AS_EX(\$\$)->funcdecl->params = \$3;` ` AS_EX(\$\$)->funcdecl->body = NEW_ST();` ` AS_EX(\$\$)->funcdecl->body->type = ST_RET;` ` AS_EX(\$\$)->funcdecl->body->ret = NEW(ret_node);` `@ -452,7 +452,7 @@ gen_expr:` `;` ``` ``` `paren_expr:` ` LPAREN expr RPAREN { \$\$ = \$2; }` ` any_lparen expr RPAREN { \$\$ = \$2; }` `;` ``` ``` `expr_list:` `@ -493,6 +493,82 @@ ident_list:` `}` `;` ``` ``` `param_list:` ` /*empty*/ { \$\$ = NULL; }` `| param_list IDENT ASSIGN expr {` ` paramlist_node *pl = \$1;` ` identlist_node *curk;` ` exprlist_node *curv;` ` if(!pl) {` ` pl = NEW(paramlist_node);` ` pl->args = NULL;` ` pl->clkeys = NULL;` ` pl->clvalues = NULL;` ` pl->rest = NULL;` ` }` ` if(!pl->clkeys) {` ` pl->clkeys = NEW(identlist_node);` ` curk = pl->clkeys;` ` pl->clvalues = NEW(exprlist_node);` ` curv = pl->clvalues;` ` } else {` ` curk = pl->clkeys;` ` curv = pl->clvalues;` ` while(curk->next) {` ` curk = curk->next;` ` curv = curv->next;` ` }` ` curk->next = NEW(identlist_node);` ` curk = curk->next;` ` curv->next = NEW(exprlist_node);` ` curv = curv->next;` ` }` ` curk->ident = \$2;` ` curk->next = NULL;` ` curv->expr = \$4;` ` curv->next = NULL;` ` \$\$ = pl;` `}` `| param_list STAR IDENT {` ` paramlist_node *pl = \$1;` ` if(!pl) {` ` pl = NEW(paramlist_node);` ` pl->args = NULL;` ` pl->clkeys = NULL;` ` pl->clvalues = NULL;` ` pl->rest = NULL;` ` }` ` pl-> rest = \$3;` ` \$\$ = pl;` `}` `| param_list IDENT {` ` paramlist_node *pl = \$1;` ` identlist_node *cura;` ` if(!pl) {` ` pl = NEW(paramlist_node);` ` pl->args = NULL;` ` pl->clkeys = NULL;` ` pl->clvalues = NULL;` ` pl->rest = NULL;` ` }` ` if(!pl->args) {` ` pl->args = NEW(identlist_node);` ` cura = pl->args;` ` } else {` ` cura = pl->args;` ` while(cura->next) {` ` cura = cura->next;` ` }` ` cura->next = NEW(identlist_node);` ` cura = cura->next;` ` }` ` cura->ident = \$2;` ` cura->next = NULL;` ` \$\$ = pl;` `}` `| param_list COMMA { \$\$ = \$1; }` `;` ``` ``` `assoc_list:` ` /*empty*/ { \$\$ = NULL; }` `| assoc_item {` `@ -529,6 +605,11 @@ assoc_item:` `}` `;` ``` ``` `any_lparen:` ` LPAREN` `| BLPAREN` `;` ``` ``` `%%` ``` ``` `// TODO`

#### 52 runtime.c 查看文件

 `@ -177,7 +177,7 @@ expr_node *ex_copy(expr_node *old) {` ` } else {` ` new->funcdecl->name = NULL;` ` }` ` new->funcdecl->args = idl_copy(old->funcdecl->args);` ` new->funcdecl->params = pl_copy(old->funcdecl->params);` ` new->funcdecl->body = st_copy(old->funcdecl->body);` ` break;` ``` ``` `@ -288,6 +288,17 @@ identlist_node *idl_copy(identlist_node *old) {` ` return new;` `}` ``` ``` `paramlist_node *pl_copy(paramlist_node *old) {` ` paramlist_node *new;` ` if(!old) return NULL;` ` new = NEW(paramlist_node);` ` new->args = idl_copy(old->args);` ` new->clkeys = idl_copy(old->clkeys);` ` new->clvalues = exl_copy(old->clvalues);` ` new->rest = old->rest ? strdup(old->rest) : NULL;` ` return new;` `}` ``` ``` `void ex_free(expr_node *);` ``` ``` `void st_free(stmt_node *stmt) {` `@ -401,7 +412,7 @@ void ex_free(expr_node *expr) {` ` case EX_FUNCDECL:` ` free(expr->funcdecl->name);` ` st_free(expr->funcdecl->body);` ` idl_free(expr->funcdecl->args);` ` pl_free(expr->funcdecl->params);` ` free(expr->funcdecl);` ` break;` ``` ``` `@ -466,11 +477,20 @@ void idl_free(identlist_node *list) {` ` }` `}` ``` ``` `void pl_free(paramlist_node *list) {` ` if(!list) return;` ` idl_free(list->args);` ` idl_free(list->clkeys);` ` exl_free(list->clvalues);` ` if(list->rest) free(list->rest);` `}` ``` ``` `#define ERR_CHECK(state) do { if(sol_has_error(state)) longjmp(jmp, 1); } while(0)` `sol_object_t *sol_eval_inner(sol_state_t *state, expr_node *expr, jmp_buf jmp) {` ` sol_object_t *res, *left, *right, *lint, *rint, *value, *list, *vint, *iter, *item;` ` exprlist_node *cure;` ` assoclist_node *cura;` ` identlist_node *curi;` ` if(!expr) {` ` return sol_set_error_string(state, "Evaluate NULL expression");` ` }` `@ -761,8 +781,19 @@ sol_object_t *sol_eval_inner(sol_state_t *state, expr_node *expr, jmp_buf jmp) {` ` break;` ``` ``` ` case EX_FUNCDECL:` ` res = sol_new_func(state, expr->funcdecl->args, expr->funcdecl->body, expr->funcdecl->name);` ` res = sol_new_func(state, expr->funcdecl->params ? expr->funcdecl->params->args : NULL, expr->funcdecl->body, expr->funcdecl->name);` ` ERR_CHECK(state);` ` if(expr->funcdecl->params) {` ` res->rest = expr->funcdecl->params->rest ? strdup(expr->funcdecl->params->rest) : NULL;` ` curi = expr->funcdecl->params->clkeys;` ` cure = expr->funcdecl->params->clvalues;` ` while(curi) {` ` sol_map_borrow_name(state, res->closure, curi->ident, sol_eval_inner(state, cure->expr, jmp));` ` ERR_CHECK(state);` ` curi = curi->next;` ` cure = cure->next;` ` }` ` }` ` if(expr->funcdecl->name) {` ` sol_state_assign_l_name(state, expr->funcdecl->name, res);` ` ERR_CHECK(state);` `@ -821,7 +852,7 @@ sol_object_t *sol_eval_inner(sol_state_t *state, expr_node *expr, jmp_buf jmp) {` ` iter = CALL_METHOD(state, value, iter, list);` ` sol_obj_free(list);` ` } else {` ` iter = value;` ` iter = sol_incref(value);` ` }` ` if(!iter->ops->call || iter->ops->call == sol_f_not_impl) {` ` 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) {` ` sol_list_insert(state, list, 1, value);` ` sol_list_insert(state, list, 2, sol_new_map(state));` ` item = CALL_METHOD(state, iter, call, list);` ` while(item != state->StopIteration) {` ` while(item != state->None) {` ` sol_state_assign_l_name(state, expr->iter->var, item);` ` sol_exec(state, expr->iter->loop);` ` sol_obj_free(item);` ` if(state->ret || state->sflag == SF_BREAKING || sol_has_error(state)) {` ` item = sol_incref(state->StopIteration);` ` item = sol_incref(state->None);` ` continue;` ` }` ` state->sflag = SF_NORMAL;` `@ -937,6 +968,7 @@ sol_object_t *sol_f_func_call(sol_state_t *state, sol_object_t *args) {` ` sol_object_t *res, *scope, *value, *key;` ` identlist_node *curi;` ` dsl_seq_iter *iter;` ` int argcnt = 0;` ` iter = dsl_new_seq_iter(args->seq);` ` if(!args || dsl_seq_iter_is_invalid(iter) || sol_is_none(state, args)) {` ` 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) {` ` }` ` sol_obj_free(key);` ` curi = curi->next;` ` argcnt++;` ` }` ` }` ` if(value->rest) {` ` if(argcnt < sol_list_len(state, args) - 1) {` ` sol_map_borrow_name(state, scope, value->rest, sol_list_sublist(state, args, argcnt + 1));` ` } else {` ` sol_map_borrow_name(state, scope, value->rest, sol_new_list(state));` ` }` ` }` ` if(value->fname) {`

#### 24 sol.h 查看文件

 `@ -10,7 +10,7 @@` `#include "dsl/dsl.h"` ``` ``` `/** The version of the project, as made available through `debug.version`. */` `#define VERSION "0.2a3"` `#define VERSION "0.3a0"` `/** The hexadecimal version of the project, formatted 0xAAIIRPP where:` ` * ` ` * - AA is the two-digit major version` `@ -20,7 +20,7 @@` ` *` ` * This value is guaranteed to only monotonically increase by revision.` ` */` `#define HEXVER 0x0002A03` `#define HEXVER 0x0003A00` ``` ``` `#ifndef SOL_ICACHE_MIN` `/** The smallest integer to cache. */` `@ -156,7 +156,7 @@ typedef struct {` ` */` ``` ``` `typedef enum {` ` /** The singlet type--the type of None, as well as StopIteration and OutOfMemory. It is also the "default" type. */` ` /** The singlet type--the type of None, as well as OutOfMemory. It is also the "default" type. */` ` SOL_SINGLET,` ` /** The integer type, implemented as a long. */` ` SOL_INTEGER,` `@ -332,6 +332,8 @@ typedef struct sol_tag_object_t {` ` struct sol_tag_object_t *udata;` ` /** For `SOL_FUNCTION`, the name of the function if it was not declared anonymously (otherwise NULL). */` ` char *fname;` ` /* For `SOL_FUNCTION`, the name of an argument that receives extra parameters as a list (otherwise NULL). */` ` char *rest;` ` };` ` /** For `SOL_CFUNCTION`, the C function pointer. */` ` sol_cfunc_t cfunc;` `@ -390,9 +392,8 @@ typedef struct sol_tag_state_t {` ` sol_object_t *stderr; ///< Standard error stream object (type `SOL_STREAM`)` ` sol_object_t *None; ///< The all-important `None` object` ` sol_object_t *OutOfMemory; ///< The semi-important `OutOfMemory` object` ` sol_object_t *StopIteration; ///< The somewhat-important `StopIteration` object` ` sol_ops_t NullOps; ///< Basic, initialized operations. Not used by any extant object type.` ` sol_ops_t SingletOps; ///< Operations on singlets (`None`, `OutOfMemory`, `StopIteration`, etc.)` ` sol_ops_t SingletOps; ///< Operations on singlets (`None`, `OutOfMemory`, etc.)` ` sol_ops_t IntOps; ///< Operations on integers` ` sol_ops_t FloatOps; ///< Operations on floats` ` sol_ops_t StringOps; ///< Operations on strings` `@ -426,7 +427,7 @@ typedef struct sol_tag_state_t {` ` * This should be called once (and only once!) for every state; it does the important` ` * work of ensuring that the state is ready to execute code, including:` ` * ` ` * - Creating the initial singlet values `None`, `OutOfMemory`, and `StopIteration`,` ` * - Creating the initial singlet values `None` and `OutOfMemory`,` ` * - Creating and populating the operations on all internally-defined object types.` ` * - Initializing all built-in modules and methods.` ` * - Running any "init.sol" files.` `@ -676,6 +677,8 @@ sol_object_t *sol_f_tofloat(sol_state_t *, sol_object_t *);` `sol_object_t *sol_f_tostring(sol_state_t *, sol_object_t *);` `/// Built-in function try` `sol_object_t *sol_f_try(sol_state_t *, sol_object_t *);` `/// Built-in function apply` `sol_object_t *sol_f_apply(sol_state_t *, sol_object_t *);` `/// Built-in function error` `sol_object_t *sol_f_error(sol_state_t *, sol_object_t *);` `/// Built-in function type` `@ -871,7 +874,12 @@ sol_object_t *sol_f_stream_open(sol_state_t *, sol_object_t *);` ` * internal routines are special-cased for certain singlets.` ` */` `sol_object_t *sol_new_singlet(sol_state_t *, const char *);` `/** Creates a new integer object with the specified value. */` `/** Creates a new integer object with the specified value.` ` *` ` * If `icache_bypass` is off and this value is within [`SOL_ICACHE_MIN`,` ` * `SOL_ICACHE_MAX`] (as set at compile time), a new reference to a cached` ` * integer in the state is returned instead.` ` */` `sol_object_t *sol_new_int(sol_state_t *, long);` `/** Creates a new float object with the specified value. */` `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 *);` `/** Internal routine to return a new Sol list equivalent to its input up to the` ` * first n elements. */` `sol_object_t *sol_list_truncate(sol_state_t *, sol_object_t *, int);` `/** Utility routine to insert at the end of a Sol list. */` `/** Utility routine to concatenate Sol lists. */` `void sol_list_append(sol_state_t *, sol_object_t *, sol_object_t *);` `/** Utility macro to insert an object at the beginning of a Sol list. */` `#define sol_list_push(st, ls, obj) sol_list_insert(st, ls, 0, obj);`

#### 10 state.c 查看文件

 `@ -52,9 +52,6 @@ int sol_state_init(sol_state_t *state) {` ` if(!(state->OutOfMemory = sol_new_singlet(state, "OutOfMemory"))) {` ` goto cleanup;` ` }` ` if(!(state->StopIteration = sol_new_singlet(state, "StopIteration"))) {` ` goto cleanup;` ` }` ``` ``` ` // We can now use the normal error reporting mechanism, now` ` // that errors are distinguishable. Set that up now.` `@ -234,13 +231,14 @@ int sol_state_init(sol_state_t *state) {` ` state->stdout = sol_new_stream(state, stdout, MODE_WRITE);` ` state->stderr = sol_new_stream(state, stderr, MODE_WRITE);` ``` ``` ` // I'm going to buffer all of these together because I can.` ` // NB: None is actually a keyword in the language--it doesn't need to be a` ` // global (see parser.y)` ` sol_map_borrow_name(state, globals, "OutOfMemory", state->OutOfMemory);` ` sol_map_borrow_name(state, globals, "StopIteration", state->StopIteration);` ` sol_map_borrow_name(state, globals, "toint", sol_new_cfunc(state, sol_f_toint));` ` sol_map_borrow_name(state, globals, "tofloat", sol_new_cfunc(state, sol_f_tofloat));` ` sol_map_borrow_name(state, globals, "tostring", sol_new_cfunc(state, sol_f_tostring));` ` sol_map_borrow_name(state, globals, "try", sol_new_cfunc(state, sol_f_try));` ` sol_map_borrow_name(state, globals, "apply", sol_new_cfunc(state, sol_f_apply));` ` sol_map_borrow_name(state, globals, "error", sol_new_cfunc(state, sol_f_error));` ` sol_map_borrow_name(state, globals, "type", sol_new_cfunc(state, sol_f_type));` ` 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) {` `cleanup:` ` sol_obj_free(state->None);` ` sol_obj_free(state->OutOfMemory);` ` sol_obj_free(state->StopIteration);` ` return 0;` `}` ``` ``` `@ -517,7 +514,6 @@ void sol_state_cleanup(sol_state_t *state) {` ` sol_obj_free(state->error);` ` sol_obj_free(state->None);` ` sol_obj_free(state->OutOfMemory);` ` sol_obj_free(state->StopIteration);` ` sol_obj_free(state->stdin);` ` sol_obj_free(state->stdout);` ` sol_obj_free(state->stderr);`

#### 3 tests/_lib.sol 查看文件

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

#### 10 tests/lang_bparen.sol 查看文件

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

 `@ -0,0 +1,17 @@` `execfile("tests/_lib.sol")` ``` ``` `func pop2(a, b, *l) return l end` ``` ``` `assert_eq(pop2(1, 2, 3, 4, 5), [3, 4, 5], "rest param")` `assert_eq(pop2(1, 2), [], "rest param (at affinity)")` `assert_eq(pop2(), [], "rest param, (below affinity)")` ``` ``` `func count(i = 0) i += 1; return i end` ``` ``` `assert_eq(count(), 1, "count")` `assert_eq(count(), 2, "count")` `assert_eq(count(), 3, "count")` ``` ``` `func rg(start, stop) return func(i=start, stop=stop) if i >= stop then return end; i += 1; return i - 1 end end` ``` ``` `assert_eq(for i in rg(3, 10) do continue i end, [3, 4, 5, 6, 7, 8, 9], "iter over count")`
 `@ -204,7 +204,9 @@ None { return NONE; }` ``` ``` `"]" { return RBRACKET; }` ``` ``` `"(" { return LPAREN; }` `^[ \t]*"(" { return BLPAREN; } /* "Breaking" paren, not allowed to introduce a call_expr */` ``` ``` `"(" { return LPAREN; } ` ``` ``` `")" { return RPAREN; }` ``` ```