summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndy Wingo <wingo@pobox.com>2012-03-06 11:19:06 +0100
committerAndy Wingo <wingo@pobox.com>2012-03-06 11:19:06 +0100
commit4164dd6d1f97505748a8476f2524efff87be4bb0 (patch)
treec5e472fa6f2b928f575807486e240de0cdccd261
parentf6e6b5181aaf068d06709d94e765b9ff5ecb2eaa (diff)
downloadguile-4164dd6d1f97505748a8476f2524efff87be4bb0.tar.gz
optimize symbol printing
* libguile/print.h: Remove internal declaration of scm_i_print_symbol_name. * libguile/print.c (symbol_has_extended_read_syntax): Optimize to avoid calling symbol_to_string if we know the symbol cannot be mistaken for a number. (print_normal_symbol): Optimize to call display_string directly, instead of jumping through scm_display. (print_symbol): Rename from scm_i_print_symbol_name. (scm_print_symbol_name, iprin1): Adapt to print_symbol name change.
-rw-r--r--libguile/print.c79
-rw-r--r--libguile/print.h3
2 files changed, 60 insertions, 22 deletions
diff --git a/libguile/print.c b/libguile/print.c
index fd0cc3da9..1f447bb99 100644
--- a/libguile/print.c
+++ b/libguile/print.c
@@ -332,6 +332,7 @@ quote_keywordish_symbols (void)
(INITIAL_IDENTIFIER_MASK \
| UC_CATEGORY_MASK_Nd | UC_CATEGORY_MASK_Mc | UC_CATEGORY_MASK_Me)
+/* FIXME: Cache this information on the symbol, somehow. */
static int
symbol_has_extended_read_syntax (SCM sym)
{
@@ -344,26 +345,56 @@ symbol_has_extended_read_syntax (SCM sym)
c = scm_i_symbol_ref (sym, 0);
- /* Single dot; conflicts with dotted-pair notation. */
- if (len == 1 && c == '.')
- return 1;
-
- /* Other initial-character constraints. */
- if (c == '\'' || c == '`' || c == ',' || c == '"' || c == ';' || c == '#')
- return 1;
+ switch (c)
+ {
+ case '\'':
+ case '`':
+ case ',':
+ case '"':
+ case ';':
+ case '#':
+ /* Some initial-character constraints. */
+ return 1;
- /* Keywords can be identified by trailing colons too. */
- if (c == ':' || scm_i_symbol_ref (sym, len - 1) == ':')
- return quote_keywordish_symbols ();
+ case ':':
+ /* Symbols that look like keywords. */
+ return quote_keywordish_symbols ();
- /* Number-ish symbols. */
- if (scm_is_true (scm_i_string_to_number (scm_symbol_to_string (sym), 10)))
- return 1;
+ case '.':
+ /* Single dot conflicts with dotted-pair notation. */
+ if (len == 1)
+ return 1;
+ /* Fall through to check numbers. */
+ case '+':
+ case '-':
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ /* Number-ish symbols. Numbers with radixes already caught be #
+ above. */
+ if (scm_is_true (scm_i_string_to_number (scm_symbol_to_string (sym), 10)))
+ return 1;
+ break;
+
+ default:
+ break;
+ }
/* Other disallowed first characters. */
if (!uc_is_general_category_withtable (c, INITIAL_IDENTIFIER_MASK))
return 1;
+ /* Keywords can be identified by trailing colons too. */
+ if (scm_i_symbol_ref (sym, len - 1) == ':')
+ return quote_keywordish_symbols ();
+
/* Otherwise, any character that's in the identifier category mask is
fine to pass through as-is, provided it's not one of the ASCII
delimiters like `;'. */
@@ -382,7 +413,16 @@ symbol_has_extended_read_syntax (SCM sym)
static void
print_normal_symbol (SCM sym, SCM port)
{
- scm_display (scm_symbol_to_string (sym), port);
+ size_t len;
+ scm_t_string_failed_conversion_handler strategy;
+
+ len = scm_i_symbol_length (sym);
+ strategy = scm_i_get_conversion_strategy (port);
+
+ if (scm_i_is_narrow_symbol (sym))
+ display_string (scm_i_symbol_chars (sym), 1, len, port, strategy);
+ else
+ display_string (scm_i_symbol_wide_chars (sym), 0, len, port, strategy);
}
static void
@@ -421,8 +461,8 @@ print_extended_symbol (SCM sym, SCM port)
}
/* FIXME: allow R6RS hex escapes instead of #{...}#. */
-void
-scm_i_print_symbol_name (SCM sym, SCM port)
+static void
+print_symbol (SCM sym, SCM port)
{
if (symbol_has_extended_read_syntax (sym))
print_extended_symbol (sym, port);
@@ -434,7 +474,7 @@ void
scm_print_symbol_name (const char *str, size_t len, SCM port)
{
SCM symbol = scm_from_utf8_symboln (str, len);
- scm_i_print_symbol_name (symbol, port);
+ print_symbol (symbol, port);
}
/* Print generally. Handles both write and display according to PSTATE.
@@ -597,13 +637,13 @@ iprin1 (SCM exp, SCM port, scm_print_state *pstate)
case scm_tc7_symbol:
if (scm_i_symbol_is_interned (exp))
{
- scm_i_print_symbol_name (exp, port);
+ print_symbol (exp, port);
scm_remember_upto_here_1 (exp);
}
else
{
scm_puts_unlocked ("#<uninterned-symbol ", port);
- scm_i_print_symbol_name (exp, port);
+ print_symbol (exp, port);
scm_putc_unlocked (' ', port);
scm_uintprint (SCM_UNPACK (exp), 16, port);
scm_putc_unlocked ('>', port);
@@ -1002,7 +1042,6 @@ static size_t
display_string (const void *str, int narrow_p,
size_t len, SCM port,
scm_t_string_failed_conversion_handler strategy)
-
{
scm_t_port *pt;
diff --git a/libguile/print.h b/libguile/print.h
index 64d1f4bd8..4a3c2f5c0 100644
--- a/libguile/print.h
+++ b/libguile/print.h
@@ -3,7 +3,7 @@
#ifndef SCM_PRINT_H
#define SCM_PRINT_H
-/* Copyright (C) 1995,1996,1998,2000,2001, 2003, 2004, 2006, 2008, 2010 Free Software Foundation, Inc.
+/* Copyright (C) 1995,1996,1998,2000,2001, 2003, 2004, 2006, 2008, 2010, 2012 Free Software Foundation, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
@@ -82,7 +82,6 @@ SCM_API void scm_intprint (scm_t_intmax n, int radix, SCM port);
SCM_API void scm_uintprint (scm_t_uintmax n, int radix, SCM port);
SCM_API void scm_ipruk (char *hdr, SCM ptr, SCM port);
SCM_API void scm_iprlist (char *hdr, SCM exp, int tlr, SCM port, scm_print_state *pstate);
-SCM_INTERNAL void scm_i_print_symbol_name (SCM sym, SCM port);
SCM_API void scm_print_symbol_name (const char *str, size_t len, SCM port);
SCM_API void scm_prin1 (SCM exp, SCM port, int writingp);
SCM_API void scm_iprin1 (SCM exp, SCM port, scm_print_state *pstate);