diff options
author | Kaz Kylheku <kaz@kylheku.com> | 2012-03-14 13:27:06 -0700 |
---|---|---|
committer | Kaz Kylheku <kaz@kylheku.com> | 2012-03-14 13:27:06 -0700 |
commit | 0592949de3e274b7d9700ec74466b541055c3bca (patch) | |
tree | 7782121888bf42e1719834cf23594b51bb3ce4a4 | |
parent | 96f072cfdb5d1eac3e32dbdb15704b0a32258a37 (diff) | |
download | txr-0592949de3e274b7d9700ec74466b541055c3bca.tar.gz txr-0592949de3e274b7d9700ec74466b541055c3bca.tar.bz2 txr-0592949de3e274b7d9700ec74466b541055c3bca.zip |
Allow quasi-quoting over hash table literals,
to express dynamic hash table construction
* eval.c (expand_qquote): Recognize hash-construct
forms: expand the hash arguments and pairs separately,
then rewrite to a new hash-construct form.
(eval-init): hash-construct intrinsic function added.
* hash.c (hash_construct_s): New symbol variable.
(hash_construct): New function.
(hash_init): Initialize hash_construct_s.
* hash.h (hash_construct_s, hash_construct): Declared.
* parser.y (hash): Rule rewritten to emit either a literal
hash table object, or a hash-construct form, based on
whether quasiquote unquotes occur within the syntax.
(hash_from_notation): Function removed.
-rw-r--r-- | ChangeLog | 21 | ||||
-rw-r--r-- | eval.c | 5 | ||||
-rw-r--r-- | hash.c | 14 | ||||
-rw-r--r-- | hash.h | 2 | ||||
-rw-r--r-- | parser.y | 23 |
5 files changed, 50 insertions, 15 deletions
@@ -1,3 +1,24 @@ +2012-03-14 Kaz Kylheku <kaz@kylheku.com> + + Allow quasi-quoting over hash table literals, + to express dynamic hash table construction + + * eval.c (expand_qquote): Recognize hash-construct + forms: expand the hash arguments and pairs separately, + then rewrite to a new hash-construct form. + (eval-init): hash-construct intrinsic function added. + + * hash.c (hash_construct_s): New symbol variable. + (hash_construct): New function. + (hash_init): Initialize hash_construct_s. + + * hash.h (hash_construct_s, hash_construct): Declared. + + * parser.y (hash): Rule rewritten to emit either a literal + hash table object, or a hash-construct form, based on + whether quasiquote unquotes occur within the syntax. + (hash_from_notation): Function removed. + 2012-03-13 Kaz Kylheku <kaz@kylheku.com> Change: @(block) requires @(end) from now on. @@ -1383,6 +1383,10 @@ static val expand_qquote(val qquoted_form) } else if (sym == qquote_s) { return rlcp(expand_qquote(expand_qquote(second(qquoted_form))), qquoted_form); + } else if (sym == hash_construct_s) { + val args = expand_qquote(second(qquoted_form)); + val pairs = expand_qquote(rest(rest(qquoted_form))); + return rlcp(list(sym, args, pairs, nao), qquoted_form); } else { val f = car(qquoted_form); val r = cdr(qquoted_form); @@ -2196,6 +2200,7 @@ void eval_init(void) reg_fun(intern(lit("make-hash"), user_package), func_n3(make_hash)); reg_fun(intern(lit("hash"), user_package), func_n0v(hashv)); + reg_fun(intern(lit("hash-construct"), user_package), func_n2(hash_construct)); reg_fun(gethash_s, func_n3o(gethash_n, 2)); reg_fun(intern(lit("sethash"), user_package), func_n3(sethash)); reg_fun(intern(lit("pushhash"), user_package), func_n3(pushhash)); @@ -65,6 +65,7 @@ struct hash_iter { }; val weak_keys_k, weak_vals_k, equal_based_k; +val hash_construct_s; /* * Dynamic list built up during gc. @@ -580,9 +581,22 @@ val hashv(val args) return make_hash(wkeys, wvals, equal); } +val hash_construct(val hashv_args, val pairs) +{ + val hash = hashv(hashv_args); + + for (; pairs; pairs = cdr(pairs)) { + val pair = car(pairs); + sethash(hash, first(pair), second(pair)); + } + + return hash; +} + void hash_init(void) { weak_keys_k = intern(lit("weak-keys"), keyword_package); weak_vals_k = intern(lit("weak-vals"), keyword_package); equal_based_k = intern(lit("equal-based"), keyword_package); + hash_construct_s = intern(lit("hash-construct"), user_package); } @@ -25,6 +25,7 @@ */ extern val weak_keys_k, weak_vals_k, equal_based_k; +extern val hash_construct_s; val make_hash(val weak_keys, val weak_vals, val equal_based); val *gethash_l(val hash, val key, val *new_p); @@ -44,6 +45,7 @@ val hash_next(val *iter); val hash_eql(val obj); val hash_equal(val obj); val hashv(val args); +val hash_construct(val hashv_args, val pairs); void hash_process_weak(void); @@ -51,6 +51,7 @@ static val o_elems_transform(val output_form); static val define_transform(val define_form); static val lit_char_helper(val litchars); static val optimize_text(val text_form); +static val unquotes_occur(val quoted_form); static val choose_quote(val quoted_form); static wchar_t char_from_name(wchar_t *name); static val hash_from_notation(val notation); @@ -671,7 +672,13 @@ o_var : IDENT { $$ = list(var_s, intern(string_own($1), nil), vector : '#' list { $$ = rlcp(vector_list($2), $2); } ; -hash : HASH_H list { $$ = rlcp(hash_from_notation($2), num($1)); } +hash : HASH_H list { if (unquotes_occur($2)) + $$ = rlcp(cons(hash_construct_s, $2), + num($1)); + else + $$ = rlcp(hash_construct(first($2), + rest($2)), + num($1)); } ; list : '(' exprs ')' { $$ = rl($2, num($1)); } @@ -1074,19 +1081,6 @@ static wchar_t char_from_name(wchar_t *name) return L'!'; /* code meaning not found */ } -static val hash_from_notation(val notation) -{ - val hash = hashv(first(notation)); - val iter = rest(notation); - - for (; iter; iter = cdr(iter)) { - val entry = car(iter); - sethash(hash, first(entry), second(entry)); - } - - return hash; -} - val get_spec(void) { return parsed_spec; @@ -1163,4 +1157,3 @@ void yybadtoken(int tok, val context) else yyerrorf(lit("unexpected ~s"), chr(tok), nao); } - |