summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2012-01-25 21:04:11 -0800
committerKaz Kylheku <kaz@kylheku.com>2012-01-25 21:04:11 -0800
commit807e57014e153e9c8df24ef1515dded78b5fa068 (patch)
tree15896b4c52bf4439f2ccac40846675531a2bd95d
parent31f335160a38e1a3f5202e93a5ac28f32ad3c27d (diff)
downloadtxr-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--ChangeLog20
-rw-r--r--eval.c4
-rw-r--r--lib.c167
-rw-r--r--lib.h4
-rw-r--r--parser.l5
-rw-r--r--parser.y5
-rw-r--r--txr.120
-rw-r--r--txr.vim8
8 files changed, 224 insertions, 9 deletions
diff --git a/ChangeLog b/ChangeLog
index 50f68bbc..7d1199a2 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -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.
diff --git a/eval.c b/eval.c
index f8acd8aa..e844f0a0 100644
--- a/eval.c
+++ b/eval.c
@@ -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));
diff --git a/lib.c b/lib.c
index 7496385b..496b0cdc 100644
--- a/lib.c
+++ b/lib.c
@@ -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;
diff --git a/lib.h b/lib.h
index 6c2ab7ed..fda6a9fc 100644
--- a/lib.h
+++ b/lib.h
@@ -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);
diff --git a/parser.l b/parser.l
index 7875f81b..d9883e6c 100644
--- a/parser.l
+++ b/parser.l
@@ -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"@");
diff --git a/parser.y b/parser.y
index 8a3e8bbb..a3d28df1 100644
--- a/parser.y
+++ b/parser.y
@@ -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)
diff --git a/txr.1 b/txr.1
index ff753b36..dc6625e5 100644
--- a/txr.1
+++ b/txr.1
@@ -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
diff --git a/txr.vim b/txr.vim
index a49ca11a..1ca420bc 100644
--- a/txr.vim
+++ b/txr.vim
@@ -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