/* Copyright 2017-2018,2021 Free Software Foundation, Inc. This file is part of Guile. Guile is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Guile is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Guile. If not, see . */ #ifdef HAVE_CONFIG_H # include #endif #include "eval.h" #include "gsubr.h" #include "keywords.h" #include "modules.h" #include "pairs.h" #include "ports.h" #include "srcprop.h" #include "threads.h" #include "variable.h" #include "syntax.h" /* The source field was added to syntax objects in Guile 3.0.6. However there can be older syntax objects present in compiled files that don't have the source field. If a syntax object has a source field, its tag will have HAS_SOURCE_WORD_FLAG set. */ #define HAS_SOURCE_WORD_FLAG 0x100 enum { TAG_WORD, EXPR_WORD, WRAP_WORD, MODULE_WORD, SOURCE_WORD, WORD_COUNT }; static int scm_is_syntax (SCM x) { return SCM_HAS_TYP7 (x, scm_tc7_syntax); } #define SCM_VALIDATE_SYNTAX(pos, scm) \ SCM_I_MAKE_VALIDATE_MSG2 (pos, scm, scm_is_syntax, "syntax object") SCM_DEFINE (scm_syntax_p, "syntax?", 1, 0, 0, (SCM obj), "Return @code{#t} if the argument @var{obj} is a syntax object,\n" "else @code{#f}.") #define FUNC_NAME s_scm_syntax_p { return scm_from_bool (scm_is_syntax (obj)); } #undef FUNC_NAME SCM_DEFINE (scm_make_syntax, "make-syntax", 3, 1, 0, (SCM exp, SCM wrap, SCM module, SCM source), "Make a new syntax object.") #define FUNC_NAME s_scm_make_syntax { if (SCM_UNBNDP (source)) source = scm_source_properties (exp); if (!scm_is_pair (source)) source = SCM_BOOL_F; SCM ret = scm_words (scm_tc7_syntax | HAS_SOURCE_WORD_FLAG, WORD_COUNT); SCM_SET_CELL_OBJECT (ret, EXPR_WORD, exp); SCM_SET_CELL_OBJECT (ret, WRAP_WORD, wrap); SCM_SET_CELL_OBJECT (ret, MODULE_WORD, module); SCM_SET_CELL_OBJECT (ret, SOURCE_WORD, source); return ret; } #undef FUNC_NAME SCM_DEFINE (scm_syntax_expression, "syntax-expression", 1, 0, 0, (SCM obj), "Return the expression contained in the syntax object @var{obj}.") #define FUNC_NAME s_scm_syntax_expression { SCM_VALIDATE_SYNTAX (1, obj); return SCM_CELL_OBJECT (obj, EXPR_WORD); } #undef FUNC_NAME SCM_DEFINE (scm_syntax_wrap, "syntax-wrap", 1, 0, 0, (SCM obj), "Return the wrap contained in the syntax object @var{obj}.") #define FUNC_NAME s_scm_syntax_wrap { SCM_VALIDATE_SYNTAX (1, obj); return SCM_CELL_OBJECT (obj, WRAP_WORD); } #undef FUNC_NAME SCM_DEFINE (scm_syntax_module, "syntax-module", 1, 0, 0, (SCM obj), "Return the module info contained in the syntax object @var{obj}.") #define FUNC_NAME s_scm_syntax_module { SCM_VALIDATE_SYNTAX (1, obj); return SCM_CELL_OBJECT (obj, MODULE_WORD); } #undef FUNC_NAME SCM_DEFINE (scm_syntax_source, "syntax-source", 1, 0, 0, (SCM obj), "Return the source location information for syntax object @var{obj}.") #define FUNC_NAME s_scm_syntax_source { SCM_VALIDATE_SYNTAX (1, obj); if (!(SCM_CELL_WORD (obj, TAG_WORD) & HAS_SOURCE_WORD_FLAG)) return SCM_BOOL_F; return SCM_CELL_OBJECT (obj, SOURCE_WORD); } #undef FUNC_NAME static SCM print_syntax_var; static void init_print_syntax_var (void) { print_syntax_var = scm_c_private_variable ("system syntax", "print-syntax"); } void scm_i_syntax_print (SCM obj, SCM port, scm_print_state *pstate) { static scm_i_pthread_once_t once = SCM_I_PTHREAD_ONCE_INIT; scm_i_pthread_once (&once, init_print_syntax_var); scm_call_2 (scm_variable_ref (print_syntax_var), obj, port); } void scm_init_syntax () { #include "syntax.x" }