00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016 #include "../sexpress/sstring.hpp"
00017 #include "../sexpress/slocatn.hpp"
00018 #include "lcont.hpp"
00019 #include "lsymbol.hpp"
00020 #include "llambda.hpp"
00021
00022
00023 LispLambdaBody::LispLambdaBody(const LContextRef &a_cx,
00024 const SReference &a_lambda,
00025 const SReference &a_body)
00026 : context(a_cx), lambda_list(a_lambda), body(a_body)
00027 {
00028 DoAnalyseLambdaList(a_lambda, 0);
00029 }
00030
00031 LispLambdaBody::~LispLambdaBody()
00032 {
00033 delete[] lambda_vector;
00034 }
00035
00036 void LispLambdaBody::DoAnalyseLambdaList(const SReference &rest, int n)
00037 {
00038 SExpressionCons *dp = rest.DynamicCastGetPtr<SExpressionCons>();
00039 if(dp) {
00040 DoAnalyseLambdaList(dp->Cdr(), n+1);
00041 lambda_vector[n] =
00042 static_cast<LExpressionSymbol*>(dp->Car().GetPtr());
00043 INTELIB_ASSERT(dp->Car().DynamicCastGetPtr<LExpressionSymbol>(),
00044 IntelibX_lisp_not_a_symbol(dp->Car()));
00045 } else {
00046 lambda_vector = new LExpressionSymbol* [n];
00047 lambda_length = n;
00048 if(rest.IsEmptyList()) {
00049 lambda_rest = 0;
00050 } else {
00051 lambda_rest =
00052 static_cast<LExpressionSymbol*>(rest.GetPtr());
00053 INTELIB_ASSERT(rest.DynamicCastGetPtr<LExpressionSymbol>(),
00054 IntelibX_lisp_not_a_symbol(dp->Car()));
00055 }
00056 }
00057 }
00058
00060
00061
00062 IntelibTypeId LExpressionLambda::TypeId(&SExpressionFunction::TypeId);
00063
00064 LExpressionLambda::LExpressionLambda(const LContextRef &cx,
00065 const SReference &lambda,
00066 const SReference &body)
00067 : SExpressionFunction(TypeId, -1, -1), LispLambdaBody(cx, lambda, body)
00068 {
00069 min_param = lambda_length;
00070 max_param = lambda_rest ? -1 : lambda_length;
00071 }
00072
00073 LExpressionLambda::~LExpressionLambda()
00074 {}
00075
00076 static void do_bind_symbol(LExpressionSymbol *symb,
00077 const SReference &value,
00078 LContextRef &context,
00079 IntelibContinuation &lf)
00080 {
00081 if(symb->IsDynamic()) {
00082 lf.PushTodo(
00083 IntelibContinuation::assign_to,
00084 new SExpressionLocation(symb, &(symb->GetDynamicValueRef()))
00085 );
00086 lf.PushTodo(
00087 IntelibContinuation::quote_parameter,
00088 symb->GetDynamicValue()
00089 );
00090 symb->SetDynamicValue(value);
00091 } else {
00092 context->AddBinding(symb, value);
00093 }
00094 }
00095
00096 void LExpressionLambda::DoApply(int paramc, const SReference *paramv,
00097 IntelibContinuation &lf) const
00098 {
00099 LContextRef tempcontext(new LExpressionContext(context));
00100 for(int i = 0; i<min_param; i++) {
00101
00102 do_bind_symbol(lambda_vector[i], paramv[i], tempcontext, lf);
00103 }
00104 if(lambda_rest) {
00105 SReference ls(*PTheEmptyList);
00106 for(int i=paramc-1; i>=min_param; i--)
00107 ls = SReference(paramv[i], ls);
00108
00109 do_bind_symbol(lambda_rest, ls, tempcontext, lf);
00110 }
00111
00112 lf.PushTodo(LispContinuation::set_context, lf.GetContext());
00113 lf.PushTodo(LispContinuation::evaluate_progn, body);
00114 lf.PushTodo(LispContinuation::set_context, tempcontext);
00115 }
00116
00117 #if INTELIB_TEXT_REPRESENTATIONS == 1
00118 SString LExpressionLambda::TextRepresentation() const
00119 {
00120 SString str("#<CLOSURE ");
00121 str += lambda_list->TextRepresentation();
00122 str += body->TextRepresentation();
00123 str += ">";
00124 return str;
00125 }
00126 #endif
00127
00129
00130
00131 IntelibTypeId LExpressionMacro::TypeId(&SExpressionForm::TypeId);
00132
00133 LExpressionMacro::LExpressionMacro(const LContextRef &cx,
00134 const SReference &lambda,
00135 const SReference &body)
00136 : SExpressionForm(TypeId), LispLambdaBody(cx, lambda, body)
00137 {}
00138
00139 LExpressionMacro::~LExpressionMacro()
00140 {}
00141
00142 void LExpressionMacro::Call(const SReference ¶ms,
00143 IntelibContinuation &lf) const
00144 {
00145 LContextRef tempcontext(new LExpressionContext(context));
00146 const SReference *p = ¶ms;
00147 for(int i = 0; i<lambda_length; i++) {
00148
00149 do_bind_symbol(lambda_vector[i], p->Car(), tempcontext, lf);
00150 p = &(p->Cdr());
00151 }
00152 if(lambda_rest) {
00153
00154 do_bind_symbol(lambda_rest, *p, tempcontext, lf);
00155 } else {
00156 if(!p->IsEmptyList()) {
00157 throw IntelibX_too_many_params(*p);
00158 }
00159 }
00160
00161 lf.PushTodo(LispContinuation::take_result_as_form);
00162 lf.PushTodo(LispContinuation::set_context, lf.GetContext());
00163 lf.PushTodo(LispContinuation::evaluate_progn, body);
00164 lf.PushTodo(LispContinuation::set_context, tempcontext);
00165 }
00166
00167 #if INTELIB_TEXT_REPRESENTATIONS == 1
00168 SString LExpressionMacro::TextRepresentation() const
00169 {
00170 SString str("#<MACRO ");
00171 str += lambda_list->TextRepresentation();
00172 str += body->TextRepresentation();
00173 str += ">";
00174 return str;
00175 }
00176 #endif
00177
00179
00180
00181 IntelibTypeId
00182 LExpressionUserCFunction::TypeId(&SExpressionFunction::TypeId);
00183
00184 #if INTELIB_TEXT_REPRESENTATIONS == 1
00185 SString LExpressionUserCFunction::TextRepresentation() const
00186 {
00187 return "#<USER-DEFINED FUNCTION>";
00188 }
00189 #endif