diff options
-rw-r--r-- | ChangeLog | 33 | ||||
-rw-r--r-- | eval.c | 15 | ||||
-rw-r--r-- | lib.c | 45 | ||||
-rw-r--r-- | lib.h | 6 | ||||
-rw-r--r-- | match.c | 16 | ||||
-rw-r--r-- | parser.l | 4 | ||||
-rw-r--r-- | parser.y | 22 | ||||
-rw-r--r-- | stream.c | 2 | ||||
-rw-r--r-- | txr.1 | 31 |
9 files changed, 152 insertions, 22 deletions
@@ -1,5 +1,38 @@ 2011-12-06 Kaz Kylheku <kaz@kylheku.com> + * eval.c (op_unwind_protect): Fixed uninitialized variable + warning. + (eval_init): New functions registered: typeof and vector functions, + as well as length_list. + + * lib.c (length): Function renamed to length_list, because it is + list specific. + (length_vec, size_vec, vector_list): New functions. + (length): New function, generic over lists, vectors and strings. + + * lib.h (length_list, length_vec, size_vec, vector_list): Declared. + + * match.c (h_var, h_fun, robust_length, v_deffilter, v_fun): Use + length_list instead of length. + + * parser.l: Introduced # token. + + * parser.y (vector): New nonterminal. + (expr): vector is a kind of expr. + (chrlist): Bugfix: single-character syntax was not working; + for instance #\x to denote the charcter x. + (lit_char_helper): Use length_list instead of length. + + * stream.c (string_in_get_line): Bugfix: this was using + the wrong length function: length was being applied to a string. + The genericity of length makes that correct now, but changing + to length_str anyway. + + * txr.1: Blank sections created for functions. Vector syntax + documented. + +2011-12-06 Kaz Kylheku <kaz@kylheku.com> + * configure: Forgot to treat octal number in the processing of conftest.syms. Removed useless eval. @@ -630,7 +630,7 @@ static val op_unwind_protect(val form, val env) { val prot_form = second(form); val cleanup_forms = rest(rest(form)); - val result; + val result = nil; uw_catch_begin(nil, exsym, exvals); @@ -1061,13 +1061,14 @@ void eval_init(void) reg_fun(append_s, func_n0v(appendv)); reg_fun(list_s, func_n0v(identity)); reg_fun(intern(lit("identity"), user_package), identity_f); + reg_fun(intern(lit("typeof"), user_package), func_n1(typeof)); reg_fun(intern(lit("atom"), user_package), func_n1(atom)); reg_fun(intern(lit("null"), user_package), func_n1(nullp)); reg_fun(intern(lit("consp"), user_package), func_n1(consp)); reg_fun(intern(lit("listp"), user_package), func_n1(listp)); reg_fun(intern(lit("proper-listp"), user_package), func_n1(proper_listp)); - reg_fun(intern(lit("length"), user_package), func_n1(length)); + reg_fun(intern(lit("length-list"), user_package), func_n1(length_list)); reg_fun(intern(lit("mapcar"), user_package), func_n1v(mapcarv)); reg_fun(intern(lit("mappend"), user_package), func_n1v(mappendv)); @@ -1185,6 +1186,16 @@ void eval_init(void) reg_fun(intern(lit("compl-span-str"), user_package), func_n2(compl_span_str)); 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("vec-get-fill"), user_package), func_n1(vec_get_fill)); + reg_fun(intern(lit("vec-set-fill"), user_package), func_n2(vec_set_fill)); + reg_fun(intern(lit("vecref"), user_package), func_n2(vecref)); + reg_fun(intern(lit("vec-push"), user_package), func_n2(vec_push)); + reg_fun(intern(lit("length-vec"), user_package), func_n1(length_vec)); + reg_fun(intern(lit("size-vec"), user_package), func_n1(size_vec)); + reg_fun(intern(lit("vector-list"), user_package), func_n1(vector_list)); + reg_fun(intern(lit("length"), user_package), func_n1(length)); + eval_error_s = intern(lit("eval-error"), user_package); uw_register_subtype(eval_error_s, error_s); } @@ -719,7 +719,7 @@ val proper_listp(val obj) return (obj == nil) ? t : nil; } -val length(val list) +val length_list(val list) { cnum len = 0; while (consp(list)) { @@ -2310,6 +2310,31 @@ val vec_push(val vec, val item) return fill; } +val length_vec(val vec) +{ + type_check(vec, VEC); + return vec->v.vec[vec_fill]; +} + +val size_vec(val vec) +{ + type_check(vec, VEC); + return vec->v.vec[vec_alloc]; +} + +val vector_list(val list) +{ + val vec = vector(num(2)); + + if (!listp(list)) + uw_throwf(error_s, lit("vector_list: list expected, not ~s"), list, nao); + + for (; consp(list); list = cdr(list)) + vec_push(vec, car(list)); + + return vec; +} + static val lazy_stream_func(val env, val lcons) { val stream = car(env); @@ -2854,6 +2879,24 @@ val set_diff(val list1, val list2, val testfun, val keyfun) return out; } +val length(val seq) +{ + if (seq == nil) + return num(0); + else switch (type(seq)) { + case CONS: + case LCONS: + return length_list(seq); + case LIT: + case STR: + return length_str(seq); + case VEC: + return length_vec(seq); + default: + type_mismatch(lit("~s is not a sequence"), cons, nao); + } +} + val env(void) { if (env_list) { @@ -339,7 +339,7 @@ val nullp(val obj); val atom(val obj); val listp(val obj); val proper_listp(val obj); -val length(val list); +val length_list(val list); val getplist(val list, val key); val getplist_f(val list, val key, val *found); val proper_plist_to_alist(val list); @@ -456,6 +456,9 @@ val vec_set_fill(val vec, val fill); val vecref(val vec, val ind); val *vecref_l(val vec, val ind); val vec_push(val vec, val item); +val length_vec(val vec); +val size_vec(val vec); +val vector_list(val list); val lazy_stream_cons(val stream); val lazy_str(val list, val term, val limit); val lazy_str_force_upto(val lstr, val index); @@ -490,6 +493,7 @@ val merge(val list1, val list2, val lessfun, val keyfun); val sort(val list, val lessfun, val keyfun); val find(val list, val key, val testfun, val keyfun); val set_diff(val list1, val list2, val testfun, val keyfun); +val length(val seq); val env(void); val obj_print(val obj, val stream); @@ -447,7 +447,7 @@ static val h_var(match_line_ctx c, match_line_ctx *cout) val modifier = first(modifiers); val pair = assoc(c.bindings, sym); /* var exists already? */ - if (gt(length(modifiers), one)) { + if (gt(length_list(modifiers), one)) { sem_error(elem, lit("multiple modifiers on variable ~s"), sym, nao); } @@ -556,7 +556,7 @@ static val h_var(match_line_ctx c, match_line_ctx *cout) val next_modifier = first(fourth(pat)); val pair = assoc(c.bindings, second_sym); /* var exists already? */ - if (gt(length(next_modifiers), one)) { + if (gt(length_list(next_modifiers), one)) { sem_error(elem, lit("multiple modifiers on variable ~s"), second_sym, nao); } @@ -994,9 +994,9 @@ static val h_fun(match_line_ctx c, match_line_ctx *cout) val piter, aiter; val bindings_cp = copy_list(c.bindings); - if (!equal(length(args), length(params))) + if (!equal(length(args), length_list(params))) sem_error(elem, lit("function ~a takes ~a argument(s)"), - sym, length(params), nao); + sym, length_list(params), nao); for (piter = params, aiter = args; piter; piter = cdr(piter), aiter = cdr(aiter)) @@ -1462,7 +1462,7 @@ static val robust_length(val obj) return zero; if (atom(obj)) return negone; - return length(obj); + return length_list(obj); } static val bind_car(val bind_cons) @@ -2948,7 +2948,7 @@ static val v_deffilter(match_files_ctx *c) val table_evaled = txeval(specline, table, c->bindings); if (!all_satisfy(table_evaled, andf(func_n1(listp), - chain(func_n1(length), + chain(func_n1(length_list), curry_12_1(func_n2(ge), two), nao), chain(func_n1(rest), curry_123_1(func_n3(all_satisfy), @@ -3025,9 +3025,9 @@ static val v_fun(match_files_ctx *c) debug_check(specline, c->bindings, if2(consp(c->data), car(c->data)), c->data_lineno, nil); - if (!equal(length(args), length(params))) + if (!equal(length_list(args), length_list(params))) sem_error(specline, lit("function ~a takes ~a argument(s)"), - sym, length(params), nao); + sym, length_list(params), nao); for (piter = params, aiter = args; piter; piter = cdr(piter), aiter = cdr(aiter)) @@ -403,6 +403,10 @@ UONLY {U2}{U}|{U3}{U}{U}|{U4}{U}{U}{U} return '`'; } +<NESTED># { + return '#'; + } + <SPECIAL>@ { yy_pop_state(); yylval.lexeme = chk_strdup(L"@"); @@ -82,7 +82,7 @@ static val parsed_spec; %type <val> clause_parts additional_parts %type <val> output_clause define_clause try_clause catch_clauses_opt %type <val> line elems_opt elems clause_parts_h additional_parts_h -%type <val> text texts elem var var_op meta_expr +%type <val> text texts elem var var_op meta_expr vector %type <val> list exprs exprs_opt expr out_clauses out_clauses_opt out_clause %type <val> repeat_clause repeat_parts_opt o_line %type <val> o_elems_opt o_elems_opt2 o_elems o_elem o_var rep_elem rep_parts_opt @@ -605,6 +605,9 @@ o_var : IDENT { $$ = list(var_s, intern(string_own($1), nil), var_op : '*' { $$ = list(t, nao); } ; +vector : '#' list { $$ = rlcp(vector_list($2), $2); } + ; + list : '(' exprs ')' { $$ = rl($2, num($1)); } | '(' ')' { $$ = nil; } | ',' expr { val expr = $2; @@ -645,6 +648,7 @@ expr : IDENT { $$ = rl(intern(string_own($1), nil), rl($$, num(lineno)); } | NUMBER { $$ = num($1); } | list { $$ = $1; } + | vector { $$ = $1; } | meta_expr { $$ = $1; } | regex { $$ = cons(regex_compile(rest($1)), rest($1)); @@ -736,15 +740,17 @@ strlit : '"' '"' { $$ = null_string; } yybadtoken(yychar, lit("string literal")); } ; -chrlit : HASH_BACKSLASH IDENT { wchar_t ch = char_from_name($2); +chrlit : HASH_BACKSLASH IDENT { wchar_t ch; val str = string_own($2); + if ($2[1] == 0) + { ch = $2[0]; } + else + { ch = char_from_name($2); + if (ch == L'!') + { yyerrorf(lit("unknown character name: ~a"), + str, nao); }} end_of_char(); - if (ch == L'!') - { yyerrorf(lit("unknown character name: ~a"), - str, nao); } $$ = chr(ch); } - | HASH_BACKSLASH LITCHAR { $$ = chr($2); - end_of_char(); } | HASH_BACKSLASH error { $$ = nil; yybadtoken(yychar, lit("character literal")); } @@ -870,7 +876,7 @@ static val lit_char_helper(val litchars) val ret = nil; if (litchars) { - val len = length(litchars), iter, ix; + val len = length_list(litchars), iter, ix; ret = mkustring(len); for (iter = litchars, ix = zero; iter; @@ -313,7 +313,7 @@ static val string_in_get_line(val stream) val pos = cdr(pair); /* TODO: broken, should only scan to newline */ - if (lt(pos, length(string))) { + if (lt(pos, length_str(string))) { val result = sub_str(string, pos, nil); *cdr_l(pair) = length_str(string); return result; @@ -4269,6 +4269,13 @@ and not a quasiquote. .PP +.SS Vectors + +.IP #(...) + +A hash token followed by a list denotes a vector. For example #(1 2 a) +is a three-element vector containing the numbers 1 and 2, and the symbol a. + .SS Nested Quotes Quotes can be nested. What if it is necessary to unquote something in the @@ -4671,6 +4678,10 @@ Programs can define named functions with the defun operator The following are Lisp functions and variables built-in to TXR. +.SS Function identity + +.SS Function typeof + .SS Function cons .SS Functions car and first @@ -4695,7 +4706,7 @@ The following are Lisp functions and variables built-in to TXR. .SS Functions listp and proper-listp -.SS Function length +.SS Function length-list .SS Function mapcar @@ -4841,6 +4852,24 @@ The following are Lisp functions and variables built-in to TXR. .SS Function break-str +.SS Function vector + +.SS Function vec-get-fill + +.SS Function vec-set-fill + +.SS Function vecref + +.SS Function vec-push + +.SS Function length-vec + +.SS Function size-vec + +.SS Function vector-list + +.SS Function length + .SH APPENDIX A: NOTES ON EXOTIC REGULAR EXPRESSIONS |