1
Fork 0
mirror of https://git.savannah.gnu.org/git/guile.git synced 2025-05-20 03:30:27 +02:00

Syntax objects are comparable with equal?

* libguile/eq.c (scm_equal_p, scm_raw_ihash): Add cases for syntax
  objects, which should be comparable with equal?.
* test-suite/tests/syntax.test ("syntax objects"): Add tests.
This commit is contained in:
Andy Wingo 2017-04-21 11:04:08 +02:00
parent 02cf38514d
commit 2e5f7d8f6d
3 changed files with 53 additions and 0 deletions

View file

@ -33,6 +33,7 @@
#include "libguile/vectors.h"
#include "libguile/hashtab.h"
#include "libguile/bytevectors.h"
#include "libguile/syntax.h"
#include "libguile/struct.h"
#include "libguile/goops.h"
@ -362,6 +363,16 @@ scm_equal_p (SCM x, SCM y)
case scm_tc7_vector:
case scm_tc7_wvect:
return scm_i_vector_equal_p (x, y);
case scm_tc7_syntax:
if (scm_is_false (scm_equal_p (scm_syntax_wrap (x),
scm_syntax_wrap (y))))
return SCM_BOOL_F;
if (scm_is_false (scm_equal_p (scm_syntax_module (x),
scm_syntax_module (y))))
return SCM_BOOL_F;
x = scm_syntax_expression (x);
y = scm_syntax_expression (y);
goto tailrecurse;
}
/* Otherwise just return false. Dispatching to the generic is the wrong thing

View file

@ -35,6 +35,7 @@
#include "libguile/ports.h"
#include "libguile/strings.h"
#include "libguile/symbols.h"
#include "libguile/syntax.h"
#include "libguile/vectors.h"
#include "libguile/validate.h"
@ -333,6 +334,14 @@ scm_raw_ihash (SCM obj, size_t depth)
h ^= scm_raw_ihash (scm_c_vector_ref (obj, h % len), i);
return h;
}
case scm_tc7_syntax:
{
unsigned long h;
h = scm_raw_ihash (scm_syntax_expression (obj), depth);
h ^= scm_raw_ihash (scm_syntax_wrap (obj), depth);
h ^= scm_raw_ihash (scm_syntax_module (obj), depth);
return h;
}
case scm_tcs_cons_imcar:
case scm_tcs_cons_nimcar:
if (depth)

View file

@ -20,6 +20,7 @@
(define-module (test-suite test-syntax)
#:use-module (ice-9 regex)
#:use-module (ice-9 local-eval)
#:use-module ((system syntax) #:select (syntax?))
#:use-module (test-suite lib))
@ -1617,6 +1618,38 @@
(length #'(x …))))
env))))
(with-test-prefix "syntax objects"
(let ((interpreted (eval '#'(foo bar baz) (current-module)))
(interpreted-bis (eval '#'(foo bar baz) (current-module)))
(compiled ((@ (system base compile) compile) '#'(foo bar baz)
#:env (current-module))))
;; Guile's expander doesn't wrap lists.
(pass-if "interpreted syntax object?"
(and (list? interpreted)
(and-map syntax? interpreted)))
(pass-if "compiled syntax object?"
(and (list? compiled)
(and-map syntax? compiled)))
(pass-if "interpreted syntax objects are not vectors"
(not (vector? interpreted)))
(pass-if "compiled syntax objects are not vectors"
(not (vector? compiled)))
(pass-if-equal "syntax objects comparable with equal? (eval/eval)"
interpreted interpreted-bis)
(pass-if-equal "syntax objects comparable with equal? (eval/compile)"
interpreted compiled)
(pass-if-equal "syntax objects hash the same (eval/eval)"
(hash interpreted most-positive-fixnum)
(hash interpreted-bis most-positive-fixnum))
(pass-if-equal "syntax objects hash the same (eval/compile)"
(hash interpreted most-positive-fixnum)
(hash compiled most-positive-fixnum))))
;;; Local Variables:
;;; eval: (put 'pass-if-syntax-error 'scheme-indent-function 1)
;;; eval: (put 'with-ellipsis 'scheme-indent-function 1)