mirror of
https://git.savannah.gnu.org/git/guile.git
synced 2025-04-30 20:00:19 +02:00
* eval.c (s_bad_bindings, s_bad_binding, s_bad_exit_clause): New
static identifiers. (scm_m_do): Use ASSERT_SYNTAX to signal syntax errors. Be more specific about the kind of error that was detected. Avoid use of SCM_CDRLOC. Avoid unnecessary consing when creating the memoized code, this way also making sure that file name, line number information etc. remain available.
This commit is contained in:
parent
8ae95199fd
commit
a954ce1d25
2 changed files with 84 additions and 42 deletions
|
@ -1,3 +1,14 @@
|
||||||
|
2003-10-11 Dirk Herrmann <D.Herrmann@tu-bs.de>
|
||||||
|
|
||||||
|
* eval.c (s_bad_bindings, s_bad_binding, s_bad_exit_clause): New
|
||||||
|
static identifiers.
|
||||||
|
|
||||||
|
(scm_m_do): Use ASSERT_SYNTAX to signal syntax errors. Be more
|
||||||
|
specific about the kind of error that was detected. Avoid use of
|
||||||
|
SCM_CDRLOC. Avoid unnecessary consing when creating the memoized
|
||||||
|
code, this way also making sure that file name, line number
|
||||||
|
information etc. remain available.
|
||||||
|
|
||||||
2003-10-11 Dirk Herrmann <D.Herrmann@tu-bs.de>
|
2003-10-11 Dirk Herrmann <D.Herrmann@tu-bs.de>
|
||||||
|
|
||||||
* eval.c (memoize_as_thunk_prototype): New static function.
|
* eval.c (memoize_as_thunk_prototype): New static function.
|
||||||
|
|
115
libguile/eval.c
115
libguile/eval.c
|
@ -151,6 +151,22 @@ static const char s_missing_recipient[] = "Missing recipient in";
|
||||||
* detected, a 'Bad variable' error is signalled. */
|
* detected, a 'Bad variable' error is signalled. */
|
||||||
static const char s_bad_variable[] = "Bad variable";
|
static const char s_bad_variable[] = "Bad variable";
|
||||||
|
|
||||||
|
/* Bindings for forms like 'let' and 'do' have to be given in a proper,
|
||||||
|
* possibly empty list. If any other object is detected in a place where a
|
||||||
|
* list of bindings was required, a 'Bad bindings' error is signalled. */
|
||||||
|
static const char s_bad_bindings[] = "Bad bindings";
|
||||||
|
|
||||||
|
/* Depending on the syntactic context, a binding has to be in the format
|
||||||
|
* (<variable> <expression>) or (<variable> <expression1> <expression2>).
|
||||||
|
* If anything else is detected in a place where a binding was expected, a
|
||||||
|
* 'Bad binding' error is signalled. */
|
||||||
|
static const char s_bad_binding[] = "Bad binding";
|
||||||
|
|
||||||
|
/* If the exit form of a 'do' expression is not in the format
|
||||||
|
* (<test> <expression> ...)
|
||||||
|
* a 'Bad exit clause' error is signalled. */
|
||||||
|
static const char s_bad_exit_clause[] = "Bad exit clause";
|
||||||
|
|
||||||
|
|
||||||
/* Signal a syntax error. We distinguish between the form that caused the
|
/* Signal a syntax error. We distinguish between the form that caused the
|
||||||
* error and the enclosing expression. The error message will print out as
|
* error and the enclosing expression. The error message will print out as
|
||||||
|
@ -966,64 +982,79 @@ scm_m_delay (SCM expr, SCM env)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
SCM_SYNTAX(s_do, "do", scm_i_makbimacro, scm_m_do);
|
||||||
|
SCM_GLOBAL_SYMBOL(scm_sym_do, s_do);
|
||||||
|
|
||||||
/* DO gets the most radically altered syntax. The order of the vars is
|
/* DO gets the most radically altered syntax. The order of the vars is
|
||||||
* reversed here. In contrast, the order of the inits and steps is reversed
|
* reversed here. In contrast, the order of the inits and steps is reversed
|
||||||
* during the evaluation:
|
* during the evaluation:
|
||||||
|
|
||||||
(do ((<var1> <init1> <step1>)
|
(do ((<var1> <init1> <step1>)
|
||||||
(<var2> <init2>)
|
(<var2> <init2>)
|
||||||
... )
|
... )
|
||||||
(<test> <return>)
|
(<test> <return>)
|
||||||
<body>)
|
<body>)
|
||||||
|
|
||||||
;; becomes
|
;; becomes
|
||||||
|
|
||||||
(#@do (<init1> <init2> ... <initn>)
|
(#@do (<init1> <init2> ... <initn>)
|
||||||
(varn ... var2 var1)
|
(varn ... var2 var1)
|
||||||
(<test> <return>)
|
(<test> <return>)
|
||||||
(<body>)
|
(<body>)
|
||||||
<step1> <step2> ... <stepn>) ;; missing steps replaced by var
|
<step1> <step2> ... <stepn>) ;; missing steps replaced by var
|
||||||
*/
|
*/
|
||||||
|
|
||||||
SCM_SYNTAX(s_do, "do", scm_i_makbimacro, scm_m_do);
|
|
||||||
SCM_GLOBAL_SYMBOL(scm_sym_do, s_do);
|
|
||||||
|
|
||||||
SCM
|
SCM
|
||||||
scm_m_do (SCM xorig, SCM env SCM_UNUSED)
|
scm_m_do (SCM expr, SCM env SCM_UNUSED)
|
||||||
{
|
{
|
||||||
SCM bindings;
|
SCM variables = SCM_EOL;
|
||||||
SCM x = SCM_CDR (xorig);
|
SCM init_forms = SCM_EOL;
|
||||||
SCM vars = SCM_EOL;
|
SCM step_forms = SCM_EOL;
|
||||||
SCM inits = SCM_EOL;
|
SCM binding_idx;
|
||||||
SCM *initloc = &inits;
|
SCM cddr_expr;
|
||||||
SCM steps = SCM_EOL;
|
SCM exit_clause;
|
||||||
SCM *steploc = &steps;
|
SCM commands;
|
||||||
SCM_ASSYNT (scm_ilength (x) >= 2, s_test, "do");
|
SCM tail;
|
||||||
bindings = SCM_CAR (x);
|
|
||||||
SCM_ASSYNT (scm_ilength (bindings) >= 0, s_bindings, "do");
|
const SCM cdr_expr = SCM_CDR (expr);
|
||||||
while (!SCM_NULLP (bindings))
|
ASSERT_SYNTAX (scm_ilength (cdr_expr) >= 0, s_bad_expression, expr);
|
||||||
|
ASSERT_SYNTAX (scm_ilength (cdr_expr) >= 2, s_missing_expression, expr);
|
||||||
|
|
||||||
|
/* Collect variables, init and step forms. */
|
||||||
|
binding_idx = SCM_CAR (cdr_expr);
|
||||||
|
ASSERT_SYNTAX_2 (scm_ilength (binding_idx) >= 0,
|
||||||
|
s_bad_bindings, binding_idx, expr);
|
||||||
|
for (; !SCM_NULLP (binding_idx); binding_idx = SCM_CDR (binding_idx))
|
||||||
{
|
{
|
||||||
SCM binding = SCM_CAR (bindings);
|
const SCM binding = SCM_CAR (binding_idx);
|
||||||
long len = scm_ilength (binding);
|
const long length = scm_ilength (binding);
|
||||||
SCM_ASSYNT (len == 2 || len == 3, s_bindings, "do");
|
ASSERT_SYNTAX_2 (length == 2 || length == 3,
|
||||||
|
s_bad_binding, binding, expr);
|
||||||
|
|
||||||
{
|
{
|
||||||
SCM name = SCM_CAR (binding);
|
const SCM name = SCM_CAR (binding);
|
||||||
SCM init = SCM_CADR (binding);
|
const SCM init = SCM_CADR (binding);
|
||||||
SCM step = (len == 2) ? name : SCM_CADDR (binding);
|
const SCM step = (length == 2) ? name : SCM_CADDR (binding);
|
||||||
SCM_ASSYNT (SCM_SYMBOLP (name), s_variable, "do");
|
ASSERT_SYNTAX_2 (SCM_SYMBOLP (name), s_bad_variable, name, expr);
|
||||||
vars = scm_cons (name, vars);
|
variables = scm_cons (name, variables);
|
||||||
*initloc = scm_list_1 (init);
|
init_forms = scm_cons (init, init_forms);
|
||||||
initloc = SCM_CDRLOC (*initloc);
|
step_forms = scm_cons (step, step_forms);
|
||||||
*steploc = scm_list_1 (step);
|
|
||||||
steploc = SCM_CDRLOC (*steploc);
|
|
||||||
bindings = SCM_CDR (bindings);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
x = SCM_CDR (x);
|
init_forms = scm_reverse_x (init_forms, SCM_UNDEFINED);
|
||||||
SCM_ASSYNT (scm_ilength (SCM_CAR (x)) >= 1, s_test, "do");
|
step_forms = scm_reverse_x (step_forms, SCM_UNDEFINED);
|
||||||
x = scm_cons2 (SCM_CAR (x), SCM_CDR (x), steps);
|
|
||||||
x = scm_cons2 (inits, vars, x);
|
/* Memoize the test form and the exit sequence. */
|
||||||
return scm_cons (SCM_IM_DO, x);
|
cddr_expr = SCM_CDR (cdr_expr);
|
||||||
|
exit_clause = SCM_CAR (cddr_expr);
|
||||||
|
ASSERT_SYNTAX_2 (scm_ilength (exit_clause) >= 1,
|
||||||
|
s_bad_exit_clause, exit_clause, expr);
|
||||||
|
|
||||||
|
commands = SCM_CDR (cddr_expr);
|
||||||
|
tail = scm_cons2 (exit_clause, commands, step_forms);
|
||||||
|
tail = scm_cons2 (init_forms, variables, tail);
|
||||||
|
SCM_SETCAR (expr, SCM_IM_DO);
|
||||||
|
SCM_SETCDR (expr, tail);
|
||||||
|
return expr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue