Main Page | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Class Members | File Members

schcont.cpp

Go to the documentation of this file.
00001 // +-------------------------------------------------------------------------+
00002 // |               I__n__t__e__L__i__b           0.6.10 development          |
00003 // | Copyright (c) Andrey Vikt. Stolyarov <crocodil_AT_croco.net> 2000-2007. |
00004 // |                                                                         |
00005 // | This is free software. The library part is available under              |
00006 // |                               GNU LESSER GENERAL PUBLIC LICENSE v.2.1.  |
00007 // | GNU LGPL v2.1 is found in docs/gnu_gpl2.txt,  or at  http://www.gnu.org |
00008 // |     Please see also docs/readme.txt and visit http://www.intelib.org    |
00009 // |                                                                         |
00010 // | !!! THERE IS NO WARRANTY OF ANY KIND, NEITHER EXPRESSED NOR IMPLIED !!! |
00011 // +-------------------------------------------------------------------------+
00012 
00013 
00014 
00015 
00016 #include "../sexpress/iexcept.hpp"
00017 #include "../sexpress/sstring.hpp"
00018 #include "scheme.hpp"
00019 #include "schcont.hpp"
00020 #include "schsymb.hpp"
00021 #include "schfun.hpp"
00022 
00023 
00025 
00026 IntelibTypeId SchExpressionContext::TypeId(&SExpression::TypeId, false);
00027 
00028 SchExpressionContext::SchExpressionContext()
00029     : SExpression(TypeId)
00030 {}
00031 
00032 SchExpressionContext::SchExpressionContext(SchContextRef a_prev)
00033     : SExpression(TypeId), prev(a_prev)
00034 {}
00035 
00036 SchExpressionContext::~SchExpressionContext()
00037 {}
00038 
00039 void SchExpressionContext::AddBinding(const SchExpressionSymbol *symb,
00040                                       const SReference& val)
00041 {
00042     (*tbl.AddBinding((unsigned long)symb)) = val;
00043 }
00044 
00045 SReference*
00046 SchExpressionContext::GetBinding(const SchExpressionSymbol *symb) const
00047 {
00048     SReference *res = tbl.GetBinding((unsigned long)symb);
00049     if(res) return res;
00050     if(prev.GetPtr()) {
00051         return prev->GetBinding(symb);
00052     } else {
00053         return 0;
00054     }
00055 }
00056 
00057 SReference*
00058 SchExpressionContext::ProvideBinding(const SchExpressionSymbol *symb)
00059 {
00060     SReference *res = GetBinding(symb);
00061     if(!res) res = tbl.AddBinding((unsigned long)symb);
00062     return res;
00063 }
00064 
00065 SReference SchExpressionContext::GetAllSymbols() const
00066 {
00067     SReference ret;
00068     if(prev.GetPtr()) {
00069         ret = prev->GetAllSymbols();
00070     } else {
00071         ret = *PTheEmptyList;
00072     }
00073     IntelibBindTable::Iterator iter(tbl);
00074     unsigned long key;
00075     SReference t;
00076     while(iter.GetNext(key, t)) {
00077         ret = SReference((SchExpressionSymbol*)key, ret);
00078     }
00079     return ret;
00080 }
00081 
00082 SString SchExpressionContext::TextRepresentation() const
00083 {
00084     return "#<SCHEME-CONTEXT>";
00085 }
00086 
00088 
00089 void SchemeContinuation::CustomCommand(int opcode, const SReference& param)
00090 {
00091     switch(opcode) {
00092         case case_check:
00093             CaseCheck(param);
00094             break;
00095         default:
00096                 // this will just throw an exception
00097             IntelibContinuation::CustomCommand(opcode, param);
00098     }
00099 }
00100 
00101 static bool eqv_memberp(const SReference &a, const SReference &ls)
00102 {
00103     SExpressionCons *dp = ls.DynamicCastGetPtr<SExpressionCons>();
00104     if(!dp) return false;
00105     return a.IsEql(dp->Car()) || eqv_memberp(a, dp->Cdr());
00106 }
00107 
00108 void SchemeContinuation::CaseCheck(const SReference& expr)
00109 {
00110     SReference val;
00111     PopResult(val);
00112     if(eqv_memberp(val, expr)) {
00113         // that's it, push true
00114         PushResult(*PTheSchemeBooleanTrue);
00115     } else {
00116         // that's not it, return value back
00117         PushResult(val);
00118         PushResult(*PTheSchemeBooleanFalse);
00119     }
00120 }
00121 
00122 void SchemeContinuation::JustEvaluate(const SReference& expr)
00123 {
00124     if(!expr.GetPtr()) throw IntelibX_unexpected_unbound_value();
00125     const IntelibTypeId *t;
00126     for(t=&(expr->TermType()); t; t=t->Prev()) {
00127         if(*t == SExpressionCons::TypeId) {
00128             EvaluateForm(static_cast<SExpressionCons*>(expr.GetPtr()));
00129             return;
00130         } else
00131         if(*t == SchExpressionSymbol::TypeId) {
00132             SchExpressionSymbol *sym =
00133                 static_cast<SchExpressionSymbol*>(expr.GetPtr());
00134             SReference &res = GetSymbolValue(sym); 
00135             if(!res.GetPtr())
00136                 throw IntelibX_scheme_symbol_has_no_value(expr);
00137             ReferenceReturn(res, expr);
00138             return;
00139         }
00140     }
00141     // no parent means that it's a regular constant...
00142     // it is always self-evaluated
00143     PushResult(expr);
00144 }
00145 
00146 #if 0
00147 void SchemeContinuation::DoFunctionCall(const SReference &fun_ref,
00148                                      int paramscount,
00149                                      const SReference *paramsvector)
00150 {
00151     SExpressionFunction *fun =
00152         fun_ref.DynamicCastGetPtr<SExpressionFunction>();
00153     if(!fun) {
00154         throw IntelibX_scheme_not_a_function(fun_ref);
00155     }
00156     fun->Apply(paramscount, paramsvector, *this);
00157 }
00158 #endif
00159 
00160 
00161 void SchemeContinuation::EvaluateForm(SExpressionCons *form)
00162 {
00163 #if 0 // INTELIB_CONTINUATION_KEEPS_STACK_INFO == 1
00164     int keepstack_position = todo_stack_pointer;
00165 #endif
00166     SchExpressionSymbol *sym =
00167         form->Car().DynamicCastGetPtr<SchExpressionSymbol>();
00168     if(sym) {
00169         SReference &val = GetSymbolValue(sym); 
00170         if(!val.GetPtr())
00171             throw IntelibX_scheme_symbol_has_no_value(form->Car());
00172         SExpressionForm *f = val.DynamicCastGetPtr<SExpressionForm>();
00173         if(f) { // special symbol
00174             f->Call(form->Cdr(), *this);
00175         } else {
00176             PushResult(val);
00177             SExpressionCons *cdr =
00178                 form->Cdr().DynamicCastGetPtr<SExpressionCons>();
00179             if(cdr) {
00180                 PlaceFormToStack(cdr, 1);
00181             } else {
00182                 PushTodo(0);
00183             }
00184         }
00185     } else {
00186         PlaceFormToStack(form, 0);
00187     }
00188 #if 0 // INTELIB_CONTINUATION_KEEPS_STACK_INFO == 1
00189     todo_stack[keepstack_position].stack_info = SReference(*form);
00190 #endif
00191 }
00192 
00193 SReference& SchemeContinuation::GetSymbolValue(SchExpressionSymbol *sym) const
00194 {
00195     SReference *lexval = 0;
00196     if(GetContext().GetPtr()) {
00197         lexval = GetContext()->GetBinding(sym);
00198     }
00199     if(lexval)
00200         return *lexval;
00201     else
00202         return sym->GetGlobalValue();
00203 }
00204 
00205 #if 0
00206 IntelibX_scheme_not_a_function::
00207 IntelibX_scheme_not_a_function(SReference a_param) 
00208     : IntelibX("scheme: not a function", a_param) {}
00209 #endif
00210 
00211 IntelibX_scheme_not_a_context::
00212 IntelibX_scheme_not_a_context(SReference a_param) 
00213     : IntelibX("scheme: not a context", a_param) {}
00214 
00215 IntelibX_scheme_symbol_has_no_value::
00216 IntelibX_scheme_symbol_has_no_value(SReference a_param) 
00217     : IntelibX("scheme: symbol has no value", a_param) {}
00218 

Generated on Tue Dec 18 00:39:44 2007 for InteLib by  doxygen 1.4.1