wingo pushed a commit to branch wip-whippet in repository guile. commit 383b67c9f1ca4539cb33b566c330fbe689037326 Author: Andy Wingo <wi...@pobox.com> AuthorDate: Mon Jun 16 13:35:34 2025 +0200
Give syntax transformers a static tc16 * libguile/scm.h: Allocate a tc16 for syntax transformers. * libguile/expand.c: Adapt to renamings. * libguile/eq.c: * libguile/goops.c: * libguile/print.c: Add tc16 cases. * libguile/macros.h: * libguile/macros.c (scm_i_make_primitive_syntax_transformer): (scm_i_primitive_syntax_transformer): Rename internal functions from scm_i_make_primitive_macro, etc. Use new representation. (scm_make_syntax_transformer): Update for new representation. --- libguile/eq.c | 1 + libguile/expand.c | 5 ++- libguile/goops.c | 3 +- libguile/macros.c | 124 +++++++++++++++++++++++++++++++++--------------------- libguile/macros.h | 9 ++-- libguile/print.c | 3 ++ libguile/scm.h | 3 +- 7 files changed, 92 insertions(+), 56 deletions(-) diff --git a/libguile/eq.c b/libguile/eq.c index 5e559848f..f85ad43d7 100644 --- a/libguile/eq.c +++ b/libguile/eq.c @@ -392,6 +392,7 @@ scm_equal_p (SCM x, SCM y) case scm_tc16_mutex: case scm_tc16_continuation: case scm_tc16_directory: + case scm_tc16_syntax_transformer: return SCM_BOOL_F; default: abort (); diff --git a/libguile/expand.c b/libguile/expand.c index be95578e3..7b28cb6d2 100644 --- a/libguile/expand.c +++ b/libguile/expand.c @@ -148,7 +148,8 @@ SCM_SYMBOL (syntax_error_key, "syntax-error"); #define SCM_SYNTAX(STR, CFN) \ SCM_SNARF_HERE(static SCM CFN (SCM xorig, SCM env)) \ -SCM_SNARF_INIT(scm_c_define (STR, scm_i_make_primitive_macro (STR, CFN))) +SCM_SNARF_INIT(scm_c_define \ + (STR, scm_i_make_primitive_syntax_transformer (STR, CFN))) /* True primitive syntax */ @@ -296,7 +297,7 @@ expand (SCM exp, SCM env) macro = expand_env_ref_macro (env, car); if (scm_is_true (macro)) - trans = scm_i_macro_primitive (macro); + trans = scm_i_primitive_syntax_transformer (macro); if (trans) return trans (exp, env); diff --git a/libguile/goops.c b/libguile/goops.c index db71dc8d8..e21a504e4 100644 --- a/libguile/goops.c +++ b/libguile/goops.c @@ -41,7 +41,6 @@ #include "gsubr-internal.h" #include "hashtab.h" #include "keywords.h" -#include "macros.h" #include "modules.h" #include "numbers.h" #include "pairs.h" @@ -357,6 +356,8 @@ SCM_DEFINE (scm_class_of, "class-of", 1, 0, 0, return class_continuation; case scm_tc16_directory: return class_directory; + case scm_tc16_syntax_transformer: + return class_unknown; default: abort (); } diff --git a/libguile/macros.c b/libguile/macros.c index e26ed651c..15478c7cd 100644 --- a/libguile/macros.c +++ b/libguile/macros.c @@ -1,4 +1,4 @@ -/* Copyright 1995-1998,2000-2003,2006,2008-2012,2018-2019 +/* Copyright 1995-1998,2000-2003,2006,2008-2012,2018-2019,2025 Free Software Foundation, Inc. This file is part of Guile. @@ -38,27 +38,49 @@ #include "macros.h" -static scm_t_bits scm_tc16_macro; +struct scm_syntax_transformer +{ + scm_t_bits tag; + scm_t_macro_primitive primitive; + SCM name; + SCM type; + SCM binding; +}; + +static inline int +scm_is_syntax_transformer (SCM x) +{ + return SCM_HAS_TYP16 (x, scm_tc16_syntax_transformer); +} -#define SCM_MACROP(x) SCM_SMOB_PREDICATE (scm_tc16_macro, (x)) -#define SCM_MACRO_PRIMITIVE(m) ((scm_t_macro_primitive)SCM_SMOB_DATA (m)) -#define SCM_MACRO_NAME(m) (SCM_SMOB_OBJECT_2 (m)) -#define SCM_MACRO_TYPE(m) (SCM_SMOB_OBJECT_3 (m)) -#define SCM_MACRO_BINDING(m) (SCM_CELL_OBJECT ((m), 4)) -#define SCM_VALIDATE_MACRO(p,v) SCM_MAKE_VALIDATE ((p), (v), MACROP) +static inline struct scm_syntax_transformer* +scm_to_syntax_transformer (SCM x) +{ + if (!scm_is_syntax_transformer (x)) + abort (); + return (struct scm_syntax_transformer *)SCM_UNPACK_POINTER (x); +} +static inline SCM +scm_from_syntax_transformer (struct scm_syntax_transformer *m) +{ + return SCM_PACK_POINTER (m); +} -SCM_API scm_t_bits scm_tc16_macro; +#define SCM_MACROP(x) scm_is_syntax_transformer (x) +#define SCM_VALIDATE_MACRO(p,v) SCM_MAKE_VALIDATE ((p), (v), MACROP) -static int -macro_print (SCM macro, SCM port, scm_print_state *pstate) +int +scm_i_print_syntax_transformer (SCM macro, SCM port, scm_print_state *pstate) { - if (scm_is_false (SCM_MACRO_TYPE (macro))) + struct scm_syntax_transformer *tx = scm_to_syntax_transformer (macro); + + if (scm_is_false (tx->type)) scm_puts ("#<primitive-syntax-transformer ", port); else scm_puts ("#<syntax-transformer ", port); - scm_iprin1 (scm_macro_name (macro), port, pstate); + scm_iprin1 (tx->name, port, pstate); scm_putc ('>', port); return 1; @@ -68,20 +90,24 @@ SCM_SYMBOL (sym_primitive_macro, "primitive-macro"); /* Return a mmacro that is known to be one of guile's built in macros. */ SCM -scm_i_make_primitive_macro (const char *name, scm_t_macro_primitive fn) -{ - SCM z = scm_words (scm_tc16_macro, 5); - SCM_SET_SMOB_DATA_N (z, 1, (scm_t_bits)fn); - SCM_SET_SMOB_OBJECT_N (z, 2, scm_from_utf8_symbol (name)); - SCM_SET_SMOB_OBJECT_N (z, 3, sym_primitive_macro); - SCM_SET_SMOB_OBJECT_N (z, 4, SCM_BOOL_F); - return z; +scm_i_make_primitive_syntax_transformer (const char *name, + scm_t_macro_primitive fn) +{ + struct scm_syntax_transformer *tx = scm_gc_malloc (sizeof (*tx), + "syntax transformer"); + tx->tag = scm_tc16_syntax_transformer; + tx->primitive = fn; + tx->name = scm_from_utf8_symbol (name); + tx->type = sym_primitive_macro; + tx->binding = SCM_BOOL_F; + + return scm_from_syntax_transformer (tx); } scm_t_macro_primitive -scm_i_macro_primitive (SCM macro) +scm_i_primitive_syntax_transformer (SCM macro) { - return SCM_MACRO_PRIMITIVE (macro); + return scm_to_syntax_transformer (macro)->primitive; } @@ -92,30 +118,34 @@ SCM_DEFINE (scm_make_syntax_transformer, "make-syntax-transformer", 3, 0, 0, "syntax expander. Users should not call this function.") #define FUNC_NAME s_scm_make_syntax_transformer { - SCM z; - SCM (*prim)(SCM,SCM) = NULL; + if (scm_is_true (name)) + SCM_VALIDATE_SYMBOL (1, name); + + SCM_VALIDATE_SYMBOL (2, type); + + struct scm_syntax_transformer *tx = scm_gc_malloc (sizeof (*tx), + "syntax transformer"); + tx->tag = scm_tc16_syntax_transformer; + tx->primitive = NULL; + tx->name = name; + tx->type = type; + tx->binding = binding; if (scm_is_true (name)) { SCM existing_var; - - SCM_VALIDATE_SYMBOL (1, name); existing_var = scm_module_variable (scm_current_module (), name); if (scm_is_true (existing_var) - && scm_is_true (scm_variable_bound_p (existing_var)) - && SCM_MACROP (SCM_VARIABLE_REF (existing_var))) - prim = SCM_MACRO_PRIMITIVE (SCM_VARIABLE_REF (existing_var)); + && scm_is_true (scm_variable_bound_p (existing_var))) + { + SCM val = SCM_VARIABLE_REF (existing_var); + if (scm_is_syntax_transformer (val)) + tx->primitive = scm_to_syntax_transformer (val)->primitive; + } } - SCM_VALIDATE_SYMBOL (2, type); - - z = scm_words (scm_tc16_macro, 5); - SCM_SET_SMOB_DATA_N (z, 1, prim); - SCM_SET_SMOB_OBJECT_N (z, 2, name); - SCM_SET_SMOB_OBJECT_N (z, 3, type); - SCM_SET_SMOB_OBJECT_N (z, 4, binding); - return z; + return scm_from_syntax_transformer (tx); } #undef FUNC_NAME @@ -127,7 +157,7 @@ SCM_DEFINE (scm_macro_p, "macro?", 1, 0, 0, "procedure has its name due to historical reasons.") #define FUNC_NAME s_scm_macro_p { - return scm_from_bool (SCM_MACROP (obj)); + return scm_from_bool (scm_is_syntax_transformer (obj)); } #undef FUNC_NAME @@ -139,7 +169,7 @@ SCM_DEFINE (scm_macro_type, "macro-type", 1, 0, 0, #define FUNC_NAME s_scm_macro_type { SCM_VALIDATE_MACRO (1, m); - return SCM_MACRO_TYPE (m); + return scm_to_syntax_transformer (m)->type; } #undef FUNC_NAME @@ -149,7 +179,7 @@ SCM_DEFINE (scm_macro_name, "macro-name", 1, 0, 0, #define FUNC_NAME s_scm_macro_name { SCM_VALIDATE_MACRO (1, m); - return SCM_MACRO_NAME (m); + return scm_to_syntax_transformer (m)->name; } #undef FUNC_NAME @@ -162,13 +192,13 @@ SCM_DEFINE (scm_macro_transformer, "macro-transformer", 1, 0, 0, #define FUNC_NAME s_scm_macro_transformer { SCM_VALIDATE_MACRO (1, m); + SCM binding = scm_macro_binding (m); /* here we rely on knowledge of how psyntax represents macro bindings, but hey, there is code out there that calls this function, and expects to get a procedure in return... */ - if (scm_is_true (scm_procedure_p (SCM_MACRO_BINDING (m)))) - return SCM_MACRO_BINDING (m); - else - return SCM_BOOL_F; + if (scm_is_true (scm_procedure_p (binding))) + return binding; + return SCM_BOOL_F; } #undef FUNC_NAME @@ -180,7 +210,7 @@ SCM_DEFINE (scm_macro_binding, "macro-binding", 1, 0, 0, #define FUNC_NAME s_scm_macro_binding { SCM_VALIDATE_MACRO (1, m); - return SCM_MACRO_BINDING (m); + return scm_to_syntax_transformer (m)->binding; } #undef FUNC_NAME @@ -219,8 +249,6 @@ scm_syntax_session_id (void) void scm_init_macros () { - scm_tc16_macro = scm_make_smob_type ("macro", 0); - scm_set_smob_print (scm_tc16_macro, macro_print); #include "macros.x" syntax_session_id = fresh_syntax_session_id(); diff --git a/libguile/macros.h b/libguile/macros.h index fda7191b8..3227d0680 100644 --- a/libguile/macros.h +++ b/libguile/macros.h @@ -1,7 +1,7 @@ #ifndef SCM_MACROS_H #define SCM_MACROS_H -/* Copyright 1998,2000-2003,2006,2008-2010,2018 +/* Copyright 1998,2000-2003,2006,2008-2010,2018,2025 Free Software Foundation, Inc. This file is part of Guile. @@ -36,9 +36,12 @@ SCM_API SCM scm_macro_name (SCM m); SCM_API SCM scm_macro_binding (SCM m); SCM_API SCM scm_macro_transformer (SCM m); -SCM_INTERNAL SCM scm_i_make_primitive_macro (const char *name, +SCM_INTERNAL int scm_i_print_syntax_transformer (SCM macro, SCM port, + scm_print_state *pstate); +SCM_INTERNAL +SCM scm_i_make_primitive_syntax_transformer (const char *name, scm_t_macro_primitive fn); -SCM_INTERNAL scm_t_macro_primitive scm_i_macro_primitive (SCM m); +SCM_INTERNAL scm_t_macro_primitive scm_i_primitive_syntax_transformer (SCM m); SCM_INTERNAL void scm_init_macros (void); diff --git a/libguile/print.c b/libguile/print.c index 0395bfede..256fd8a2a 100644 --- a/libguile/print.c +++ b/libguile/print.c @@ -805,6 +805,9 @@ iprin1 (SCM exp, SCM port, scm_print_state *pstate) case scm_tc16_directory: scm_i_print_directory (exp, port, pstate); break; + case scm_tc16_syntax_transformer: + scm_i_print_syntax_transformer (exp, port, pstate); + break; default: abort (); } diff --git a/libguile/scm.h b/libguile/scm.h index cff85c669..e9d24bed1 100644 --- a/libguile/scm.h +++ b/libguile/scm.h @@ -513,9 +513,8 @@ typedef uintptr_t scm_t_bits; #define scm_tc16_mutex 0x027f #define scm_tc16_continuation 0x037f #define scm_tc16_directory 0x047f +#define scm_tc16_syntax_transformer 0x057f /* -#define scm_tc16_hook 0x097f -#define scm_tc16_macro 0x0a7f #define scm_tc16_malloc 0x0b7f #define scm_tc16_port_with_print_state 0x0d7f #define scm_tc16_promise 0x0e7f