+ SCM rest;
+ SCM sym_exp = SCM_CAR (x);
+ SCM_ASSYNT (scm_ilength (sym_exp) == 2, scm_s_bindings, s_atbind);
+ SCM_ASSYNT (SCM_SYMBOLP (SCM_CAR (sym_exp)), scm_s_bindings, s_atbind);
+ x = SCM_CDR (x);
+ for (rest = x; SCM_NIMP (rest); rest = SCM_CDR (rest))
+ if (SCM_EQ_P (SCM_CAR (sym_exp), SCM_CAAR (rest)))
+ scm_misc_error (s_atbind, scm_s_duplicate_bindings, SCM_EOL);
+ /* The first call to scm_sym2var will look beyond the current
+ module, while the second call wont. */
+ var = scm_sym2var (SCM_CAR (sym_exp), top_level, SCM_BOOL_F);
+ if (SCM_FALSEP (var))
+ var = scm_sym2var (SCM_CAR (sym_exp), top_level, SCM_BOOL_T);
+ vars = scm_cons (var, vars);
+ exps = scm_cons (SCM_CADR (sym_exp), exps);
+ }
+ return scm_cons (SCM_IM_BIND,
+ scm_cons (scm_cons (scm_reverse_x (vars, SCM_EOL), exps),
+ SCM_CDDR (xorig)));
+}
+
+
+SCM_SYNTAX(s_atcall_cc, "@call-with-current-continuation", scm_makmmacro, scm_m_cont);
+SCM_GLOBAL_SYMBOL(scm_sym_atcall_cc, s_atcall_cc);
+
+
+SCM
+scm_m_cont (SCM xorig, SCM env SCM_UNUSED)
+{
+ SCM_ASSYNT (scm_ilength (SCM_CDR (xorig)) == 1,
+ scm_s_expression, s_atcall_cc);
+ return scm_cons (SCM_IM_CONT, SCM_CDR (xorig));
+}
+
+
+SCM_SYNTAX (s_at_call_with_values, "@call-with-values", scm_makmmacro, scm_m_at_call_with_values);
+SCM_GLOBAL_SYMBOL(scm_sym_at_call_with_values, s_at_call_with_values);
+
+SCM
+scm_m_at_call_with_values (SCM xorig, SCM env SCM_UNUSED)
+{
+ SCM_ASSYNT (scm_ilength (SCM_CDR (xorig)) == 2,
+ scm_s_expression, s_at_call_with_values);
+ return scm_cons (SCM_IM_CALL_WITH_VALUES, SCM_CDR (xorig));
+}
+
+
+SCM_SYNTAX (s_future, "future", scm_makmmacro, scm_m_future);
+SCM_GLOBAL_SYMBOL (scm_sym_future, s_future);
+
+/* Like promises, futures are implemented as closures with an empty
+ * parameter list. Thus, (future <expression>) is transformed into
+ * (#@future '() <expression>), where the empty list represents the
+ * empty parameter list. This representation allows for easy creation
+ * of the closure during evaluation. */
+SCM
+scm_m_future (SCM xorig, SCM env SCM_UNUSED)
+{
+ SCM_ASSYNT (scm_ilength (xorig) == 2, scm_s_expression, s_future);
+ return scm_cons2 (SCM_IM_FUTURE, SCM_EOL, SCM_CDR (xorig));
+}
+
+
+SCM_SYNTAX (s_gset_x, "set!", scm_makmmacro, scm_m_generalized_set_x);
+SCM_SYMBOL (scm_sym_setter, "setter");
+
+SCM
+scm_m_generalized_set_x (SCM xorig, SCM env SCM_UNUSED)
+{
+ SCM x = SCM_CDR (xorig);
+ SCM_ASSYNT (2 == scm_ilength (x), scm_s_expression, s_set_x);
+ if (SCM_SYMBOLP (SCM_CAR (x)))
+ return scm_cons (SCM_IM_SET_X, x);
+ else if (SCM_CONSP (SCM_CAR (x)))
+ return scm_cons (scm_list_2 (scm_sym_setter, SCM_CAAR (x)),
+ scm_append (scm_list_2 (SCM_CDAR (x), SCM_CDR (x))));
+ else
+ scm_misc_error (s_set_x, scm_s_variable, SCM_EOL);
+}
+
+
+static const char* s_atslot_ref = "@slot-ref";
+
+/* @slot-ref is bound privately in the (oop goops) module from goops.c. As
+ * soon as the module system allows us to more freely create bindings in
+ * arbitrary modules during the startup phase, the code from goops.c should be
+ * moved here. */
+SCM
+scm_m_atslot_ref (SCM xorig, SCM env SCM_UNUSED)
+#define FUNC_NAME s_atslot_ref
+{
+ SCM x = SCM_CDR (xorig);
+ SCM_ASSYNT (scm_ilength (x) == 2, scm_s_expression, FUNC_NAME);
+ SCM_VALIDATE_INUM (SCM_ARG2, SCM_CADR (x));
+ return scm_cons (SCM_IM_SLOT_REF, x);
+}
+#undef FUNC_NAME
+
+
+static const char* s_atslot_set_x = "@slot-set!";
+
+/* @slot-set! is bound privately in the (oop goops) module from goops.c. As
+ * soon as the module system allows us to more freely create bindings in
+ * arbitrary modules during the startup phase, the code from goops.c should be
+ * moved here. */
+SCM
+scm_m_atslot_set_x (SCM xorig, SCM env SCM_UNUSED)
+#define FUNC_NAME s_atslot_set_x
+{
+ SCM x = SCM_CDR (xorig);
+ SCM_ASSYNT (scm_ilength (x) == 3, scm_s_expression, FUNC_NAME);
+ SCM_VALIDATE_INUM (SCM_ARG2, SCM_CADR (x));
+ return scm_cons (SCM_IM_SLOT_SET_X, x);
+}
+#undef FUNC_NAME
+
+
+#if SCM_ENABLE_ELISP
+
+SCM_SYNTAX (s_nil_cond, "nil-cond", scm_makmmacro, scm_m_nil_cond);
+
+SCM
+scm_m_nil_cond (SCM xorig, SCM env SCM_UNUSED)
+{
+ long len = scm_ilength (SCM_CDR (xorig));
+ SCM_ASSYNT (len >= 1 && (len & 1) == 1, scm_s_expression, "nil-cond");
+ return scm_cons (SCM_IM_NIL_COND, SCM_CDR (xorig));
+}
+
+
+SCM_SYNTAX (s_atfop, "@fop", scm_makmmacro, scm_m_atfop);
+
+SCM
+scm_m_atfop (SCM xorig, SCM env SCM_UNUSED)
+{
+ SCM x = SCM_CDR (xorig), var;
+ SCM_ASSYNT (scm_ilength (x) >= 1, scm_s_expression, "@fop");
+ var = scm_symbol_fref (SCM_CAR (x));
+ /* Passing the symbol name as the `subr' arg here isn't really
+ right, but without it it can be very difficult to work out from
+ the error message which function definition was missing. In any
+ case, we shouldn't really use SCM_ASSYNT here at all, but instead
+ something equivalent to (signal void-function (list SYM)) in
+ Elisp. */
+ SCM_ASSYNT (SCM_VARIABLEP (var),
+ "Symbol's function definition is void",
+ SCM_SYMBOL_CHARS (SCM_CAR (x)));
+ /* Support `defalias'. */
+ while (SCM_SYMBOLP (SCM_VARIABLE_REF (var)))
+ {
+ var = scm_symbol_fref (SCM_VARIABLE_REF (var));
+ SCM_ASSYNT (SCM_VARIABLEP (var),
+ "Symbol's function definition is void",
+ SCM_SYMBOL_CHARS (SCM_CAR (x)));
+ }
+ /* Use `var' here rather than `SCM_VARIABLE_REF (var)' because the
+ former allows for automatically picking up redefinitions of the
+ corresponding symbol. */
+ SCM_SETCAR (x, var);
+ /* If the variable contains a procedure, leave the
+ `transformer-macro' in place so that the procedure's arguments
+ get properly transformed, and change the initial @fop to
+ SCM_IM_APPLY. */
+ if (!SCM_MACROP (SCM_VARIABLE_REF (var)))
+ {
+ SCM_SETCAR (xorig, SCM_IM_APPLY);
+ return xorig;