diff options
author | Kaz Kylheku <kaz@kylheku.com> | 2012-01-25 21:04:11 -0800 |
---|---|---|
committer | Kaz Kylheku <kaz@kylheku.com> | 2012-01-25 21:04:11 -0800 |
commit | 807e57014e153e9c8df24ef1515dded78b5fa068 (patch) | |
tree | 15896b4c52bf4439f2ccac40846675531a2bd95d | |
parent | 31f335160a38e1a3f5202e93a5ac28f32ad3c27d (diff) | |
download | txr-807e57014e153e9c8df24ef1515dded78b5fa068.tar.gz txr-807e57014e153e9c8df24ef1515dded78b5fa068.tar.bz2 txr-807e57014e153e9c8df24ef1515dded78b5fa068.zip |
* eval.c (eval_init): New functions registered.
* lib.c (sub_list, replace_list, vectorp): New functions.
(sub_vec): Allow negative indices from end of array.
(replace_vec): New function.
* lib.h (sub_list, replace_list, vectorp, replace_vec): Declared.
* parser.l (DOTDOT): Scan .. as new token.
* parser.y (DOTDOT): New token.
(expr): New syntax with DOTDOT.
(yybadtoken): Handle DOTDOT.
* txr.vim: Added new functions. Also missing append* and dwim.
* txr.1: Updated.
-rw-r--r-- | ChangeLog | 20 | ||||
-rw-r--r-- | eval.c | 4 | ||||
-rw-r--r-- | lib.c | 167 | ||||
-rw-r--r-- | lib.h | 4 | ||||
-rw-r--r-- | parser.l | 5 | ||||
-rw-r--r-- | parser.y | 5 | ||||
-rw-r--r-- | txr.1 | 20 | ||||
-rw-r--r-- | txr.vim | 8 |
8 files changed, 224 insertions, 9 deletions
@@ -1,5 +1,25 @@ 2012-01-25 Kaz Kylheku <kaz@kylheku.com> + * eval.c (eval_init): New functions registered. + + * lib.c (sub_list, replace_list, vectorp): New functions. + (sub_vec): Allow negative indices from end of array. + (replace_vec): New function. + + * lib.h (sub_list, replace_list, vectorp, replace_vec): Declared. + + * parser.l (DOTDOT): Scan .. as new token. + + * parser.y (DOTDOT): New token. + (expr): New syntax with DOTDOT. + (yybadtoken): Handle DOTDOT. + + * txr.vim: Added new functions. Also missing append* and dwim. + + * txr.1: Updated. + +2012-01-25 Kaz Kylheku <kaz@kylheku.com> + * txr.vim (txr_chr): Fix for highlighting named characters like #\newline. @@ -1698,6 +1698,8 @@ void eval_init(void) reg_fun(intern(lit("rplacd"), user_package), func_n2(rplacd)); reg_fun(intern(lit("first"), user_package), func_n1(car)); reg_fun(intern(lit("rest"), user_package), func_n1(cdr)); + reg_fun(intern(lit("sub-list"), user_package), func_n3(sub_list)); + reg_fun(intern(lit("replace-list"), user_package), func_n4(replace_list)); reg_fun(append_s, func_n0v(appendv)); reg_fun(intern(lit("append*"), user_package), func_n0v(lazy_appendv)); reg_fun(list_s, func_n0v(identity)); @@ -1867,6 +1869,7 @@ void eval_init(void) reg_fun(intern(lit("break-str"), user_package), func_n2(break_str)); reg_fun(intern(lit("vector"), user_package), func_n1(vector)); + reg_fun(intern(lit("vectorp"), user_package), func_n1(vectorp)); reg_fun(intern(lit("vec-set-length"), user_package), func_n2(vec_set_length)); reg_fun(vecref_s, func_n2(vecref)); reg_fun(intern(lit("vec-push"), user_package), func_n2(vec_push)); @@ -1876,6 +1879,7 @@ void eval_init(void) reg_fun(intern(lit("list-vector"), user_package), func_n1(list_vector)); reg_fun(intern(lit("copy-vec"), user_package), func_n1(copy_vec)); reg_fun(intern(lit("sub-vec"), user_package), func_n3(sub_vec)); + reg_fun(intern(lit("replace-vec"), user_package), func_n4(replace_vec)); reg_fun(intern(lit("cat-vec"), user_package), func_n1(cat_vec)); reg_fun(intern(lit("assoc"), user_package), func_n2(assoc)); @@ -407,6 +407,95 @@ val nappend2(val list1, val list2) return out; } +val sub_list(val list, val from, val to) +{ + val len = nil; + + if (!list) + return nil; + + if (from == nil) + from = zero; + else if (lt(from, zero)) + from = plus(from, len ? len : len = length(list)); + + if (to && lt(to, zero)) + to = plus(to, len ? len : len = length(list)); + + if (to && gt(from, to)) { + return nil; + } else if (!to || (len && ge(to, len))) { + val iter, i; + + for (i = zero, iter = list; iter; iter = cdr(iter), i = plus(i, one)) { + if (ge(i, from)) + break; + } + return iter; + } else { + val iter, i; + list_collect_decl (out, ptail); + + for (i = zero, iter = list; iter; iter = cdr(iter), i = plus(i, one)) { + if (ge(i, to)) + break; + if (ge(i, from)) + list_collect(ptail, car(iter)); + } + + return out; + } +} + +val replace_list(val list, val from, val to, val items) +{ + val len = nil; + + if (!list) + return items; + + if (from == nil) + from = zero; + else if (lt(from, zero)) + from = plus(from, len ? len : len = length(list)); + + if (to && lt(to, zero)) + to = plus(to, len ? len : len = length(list)); + + if (!to || (len && ge(to, len))) { + if (zerop(from)) { + return (listp(items)) ? items : list_vector(items); + } else { + val iter, i; + list_collect_decl (out, ptail); + + for (i = zero, iter = list; iter; iter = cdr(iter), i = plus(i, one)) { + if (ge(i, from)) + break; + list_collect (ptail, car(iter)); + } + + list_collect_nconc(ptail, listp(items) ? items : list_vector(items)); + return out; + } + } else { + val iter, i; + list_collect_decl (out, ptail); + + for (i = zero, iter = list; iter; iter = cdr(iter), i = plus(i, one)) { + if (ge(i, to)) + break; + if (lt(i, from)) + list_collect(ptail, car(iter)); + } + + list_collect_nconc(ptail, append2(listp(items) ? items + : list_vector(items), + iter)); + return out; + } +} + static val lazy_appendv_func(val env, val lcons) { cons_bind (last, lists, env); @@ -2471,6 +2560,11 @@ val vector(val length) return vec; } +val vectorp(val vec) +{ + return (is_ptr(vec) && type(vec) == VEC) ? t : nil; +} + val vec_set_length(val vec, val length) { type_check(vec, VEC); @@ -2593,14 +2687,18 @@ val sub_vec(val vec_in, val from, val to) { val len = length_vec(vec_in); - if (from == nil || lt(from, zero)) + if (from == nil) from = zero; + else if (lt(from, zero)) + from = plus(from, len); + if (to == nil) to = length_vec(vec_in); else if (lt(to, zero)) - to = zero; - from = min2(from, len); - to = min2(to, len); + to = plus(to, len); + + from = max2(zero, min2(from, len)); + to = max2(zero, min2(to, len)); if (ge(from, to)) { return vector(zero); @@ -2621,6 +2719,67 @@ val sub_vec(val vec_in, val from, val to) } } +val replace_vec(val vec_in, val from, val to, val items) +{ + val len = length_vec(vec_in); + val len_it = length(items); + val len_rep; + + if (from == nil) + from = zero; + else if (lt(from, zero)) + from = plus(from, len); + + if (to == nil) + to = length_vec(vec_in); + else if (lt(to, zero)) + to = plus(to, len); + + from = max2(zero, min2(from, len)); + to = max2(zero, min2(to, len)); + + len_rep = minus(to, from); + + if (gt(len_rep, len_it)) { + val len_diff = minus(len_rep, len_it); + cnum t = c_num(to); + cnum l = c_num(len); + + memmove(vec_in->v.vec + t - c_num(len_diff), + vec_in->v.vec + t, + l * sizeof vec_in->v.vec); + + vec_in->v.vec[vec_length] = minus(len, len_diff); + to = plus(from, len_it); + } else if (lt(len_rep, len_it)) { + val len_diff = minus(len_it, len_rep); + cnum t = c_num(to); + cnum l = c_num(len); + + vec_set_length(vec_in, plus(len, len_diff)); + + memmove(vec_in->v.vec + t + c_num(len_diff), + vec_in->v.vec + t, + l * sizeof vec_in->v.vec); + to = plus(from, len_it); + } + + if (zerop(len_it)) + return vec_in; + if (vectorp(items)) { + memcpy(vec_in->v.vec + c_num(from), items->v.vec, + sizeof *vec_in->v.vec * c_num(len_it)); + } else { + val iter; + cnum f = c_num(from); + cnum t = c_num(to); + + for (iter = items; iter && f != t; iter = cdr(iter), f++) + vec_in->v.vec[f] = car(iter); + } + return vec_in; +} + val cat_vec(val list) { cnum total = 0; @@ -334,6 +334,8 @@ val reverse(val in); val append2(val list1, val list2); val nappend2(val list1, val list2); val appendv(val lists); +val sub_list(val list, val from, val to); +val replace_list(val list, val from, val to, val items); val lazy_appendv(val lists); val ldiff(val list1, val list2); val flatten(val list); @@ -503,6 +505,7 @@ val andf(val first_fun, ...); val orf(val first_fun, ...); val swap_12_21(val fun); val vector(val length); +val vectorp(val vec); val vec_set_length(val vec, val fill); val vecref(val vec, val ind); val *vecref_l(val vec, val ind); @@ -513,6 +516,7 @@ val vector_list(val list); val list_vector(val vector); val copy_vec(val vec); val sub_vec(val vec_in, val from, val to); +val replace_vec(val vec_in, val from, val to, val items); val cat_vec(val list); val lazy_stream_cons(val stream); val lazy_str(val list, val term, val limit); @@ -408,6 +408,11 @@ UONLY {U2}{U}|{U3}{U}{U}|{U4}{U}{U}{U} return '#'; } +<NESTED>\.\. { + yylval.lineno = lineno; + return DOTDOT; + } + <SPECIAL>@ { yy_pop_state(); yylval.lexeme = chk_strdup(L"@"); @@ -72,7 +72,7 @@ static val parsed_spec; %token <lineno> UNTIL COLL OUTPUT REPEAT REP SINGLE FIRST LAST EMPTY %token <lineno> MOD MODLAST DEFINE TRY CATCH FINALLY %token <lineno> ERRTOK /* deliberately not used in grammar */ -%token <lineno> HASH_BACKSLASH +%token <lineno> HASH_BACKSLASH DOTDOT %token <val> NUMBER @@ -106,6 +106,7 @@ static val parsed_spec; %left '&' %right '~' '*' '?' '+' '%' %right '.' REGCHAR LITCHAR +%right DOTDOT %% @@ -711,6 +712,7 @@ expr : IDENT { $$ = rl(intern(string_own($1), nil), | chrlit { $$ = rl($1, num(lineno)); } | strlit { $$ = $1; } | quasilit { $$ = $1; } + | expr DOTDOT expr { $$ = list(cons_s, $1, $3, nao); } ; regex : '/' regexpr '/' { $$ = cons(regex_s, $2); end_of_regex(); @@ -1064,6 +1066,7 @@ void yybadtoken(int tok, val context) case LITCHAR: problem = lit("string literal character"); break; case METAPAR: problem = lit("@("); break; case METABKT: problem = lit("@["); break; + case DOTDOT: problem = lit(".."); break; } if (problem != 0) @@ -4363,6 +4363,18 @@ with the innermost quote. The quote between the commas protects the (+ 1 2) from repeated evaluations: the two unquotes call for two evaluations, but we only want (+ 1 2) to be evaluated once. +.SS The .. notation + +In TXR Lisp, there is a special "dotdot" notation consiting of a pair of dots. +This can be written between successive atoms or compound expressions, and is a +shorthand for cons. + +That is to say, A .. B translates to (cons A B), and so for instance +(a b .. (c d) e .. f . g) means (a (cons b (c d)) (cons e f) . g). + +This is a syntactic sugar in certain situations in which a cons +is used to represent a pair of numbers or other objects. + .SS The DWIM Brackets .IP [...] @@ -5519,6 +5531,10 @@ Examples: (list 1) -> (1) (list 'a 'b) -> (a b) +.SS Function sub-list + +.SS Function replace-list + .SS Function atom .TP @@ -6281,6 +6297,8 @@ Certain object types have a custom equal function. .SS Function vector +.SS Function vectorp + .SS Function vec-set-length .SS Function vecref @@ -6299,6 +6317,8 @@ Certain object types have a custom equal function. .SS Function sub-vec +.SS Function replace-vec + .SS Function cat-vec .SS Function assoc @@ -26,17 +26,17 @@ syn keyword txr_keyword contained define try catch finally throw syn keyword txr_keyword contained defex throw deffilter filter eof eol do syn keyword txl_keyword contained progn prog1 let syn let* lambda call fun -syn keyword txl_keyword contained cond if and or +syn keyword txl_keyword contained cond if and or dwim syn keyword txl_keyword contained defvar defun inc dec set push pop flip syn keyword txl_keyword contained for for* dohash unwind-protect block syn keyword txl_keyword contained return return-from gen delay syn keyword txl_keyword contained each each* collect-each collect-each* syn keyword txl_keyword contained cons make-lazy-cons lcons-fun car cdr -syn keyword txl_keyword contained rplaca rplacd first rest append list +syn keyword txl_keyword contained rplaca rplacd first rest append append* list syn keyword txl_keyword contained identity typeof atom null not consp listp syn keyword txl_keyword contained proper-listp length-list mapcar mappend apply -syn keyword txl_keyword contained mapcar* mappend* +syn keyword txl_keyword contained mapcar* mappend* sub-list replace-list syn keyword txl_keyword contained reduce-left reduce-right syn keyword txl_keyword contained second third fourth fifth sixth copy-list nreverse syn keyword txl_keyword contained reverse ldiff flatten lazy-flatten @@ -71,7 +71,7 @@ syn keyword txl_keyword contained chr-str-set span-str compl-span-str break-str syn keyword txl_keyword contained vector vec-set-length vecref syn keyword txl_keyword contained vec-push length-vec size-vec vector-list syn keyword txl_keyword contained list-vector copy-vec sub-vec cat-vec -syn keyword txl_keyword contained assoc assq acons acons-new +syn keyword txl_keyword contained replace-vec assoc assq acons acons-new syn keyword txl_keyword contained aconsq-new alist-remove alist-nremove copy-cons syn keyword txl_keyword contained copy-alist merge sort find set-diff length |