• Main Page
  • Related Pages
  • Modules
  • Namespaces
  • Classes
  • Files
  • File List
  • File Members

src/interp/VarInterp.cpp

00001 /*
00002  *   This file is part of the Standard Portable Library (SPL).
00003  *
00004  *   SPL is free software: you can redistribute it and/or modify
00005  *   it under the terms of the GNU General Public License as published by
00006  *   the Free Software Foundation, either version 3 of the License, or
00007  *   (at your option) any later version.
00008  *
00009  *   SPL is distributed in the hope that it will be useful,
00010  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  *   GNU General Public License for more details.
00013  *
00014  *   You should have received a copy of the GNU General Public License
00015  *   along with SPL.  If not, see <http://www.gnu.org/licenses/>.
00016  */
00017 #include <spl/interp/jsfunctions/GlobalToString.h>
00018 #include <spl/interp/VarInterp.h>
00019 
00020 StackFrame::StackFrame()
00021 :       m_stack(), 
00022         m_program(),
00023         m_context(), 
00024         m_contextObj(),
00025         m_pc(0), 
00026         m_outer(NULL), 
00027         m_enterStack()
00028 {
00029 }
00030 
00031 StackFrame::StackFrame(JsMethodPtr context)
00032 :       m_stack(), 
00033         m_program(context->GetProgramPtr()),
00034         m_context(), 
00035         m_contextObj(),
00036         m_pc(0), 
00037         m_outer(NULL), 
00038         m_enterStack()
00039 {
00040         JsObjectPtr op = (JsObjectPtr)context;
00041         m_contextObj = (IJsObjectPtr)op;
00042         m_context = VariantPtr(new Variant(m_contextObj));
00043 }
00044 
00045 StackFrame::StackFrame(JsMethodPtr context, StackFrame *outer)
00046 :       m_stack(),
00047         m_program(context->GetProgramPtr()),
00048         m_context(), 
00049         m_contextObj(),
00050         m_pc(0), 
00051         m_outer(outer), 
00052         m_enterStack()
00053 {
00054         JsObjectPtr op = (JsObjectPtr)context;
00055         m_contextObj = (IJsObjectPtr)op;
00056         m_context = VariantPtr(new Variant(m_contextObj));
00057 }
00058 
00059 StackFrame::StackFrame(const StackFrame& frm)
00060 :       m_stack(frm.m_stack), 
00061         m_program(frm.m_program),
00062         m_context(frm.m_context), 
00063         m_contextObj(frm.m_contextObj), 
00064         m_pc(frm.m_pc), 
00065         m_outer(frm.m_outer), 
00066         m_enterStack(frm.m_enterStack)
00067 {
00068 }
00069 
00070 StackFrame::~StackFrame()
00071 {
00072         while (GetStack().Count() > 0)
00073         {
00074                 PopStack();
00075         }
00076 }
00077 
00078 StackFrame& StackFrame::operator =(const StackFrame& frm)
00079 {
00080         m_context = frm.m_context;
00081         m_contextObj = frm.m_contextObj;
00082         m_pc = frm.m_pc;
00083         m_outer = frm.m_outer;
00084         m_stack = frm.m_stack;
00085         m_enterStack = frm.m_enterStack;
00086         m_program = frm.m_program;
00087         return *this;
00088 }
00089 
00090 void StackFrame::DefineProperty()
00091 {
00092         StringPtr name = GetStack().Peek()->ToString();
00093         PopStack();
00094         m_stack.Add(ContextObject()->GetProperty(*name));
00095 }
00096 
00097 VariantPtr StackFrame::FindProperty(const Variant& propName)
00098 {
00099         StringPtr name = propName.ToString();
00100 
00101         if (ContextObject()->HasProperty(*name))
00102         {
00103                 return ContextObject()->GetProperty(*name);
00104         }
00105 
00106         StackFrame *outer = m_outer;
00107 
00108         while (NULL != outer)
00109         {
00110                 if (outer->ContextObject()->HasProperty(*name))
00111                 {
00112                         return outer->ContextObject()->GetProperty(*name);
00113                 }
00114                 outer = outer->NextFrame();
00115         }
00116 
00117         return ContextObject()->GetProperty(*name);
00118 }
00119 
00120 void StackFrame::InitArgs(Vector<VariantPtr> args)
00121 {
00122         ASSERT(NULL != m_program);
00123 
00124         int x = 0;
00125         for(; x < args.Count(); x++)
00126         {
00127                 m_stack.Add(args.ElementAt(x));
00128         }
00129         while (x < m_program->ArgumentCount())
00130         {
00131                 m_stack.Add(VariantPtr(new Variant()));
00132                 x++;
00133         }
00134 }
00135 
00136 VariantPtr StackFrame::GetThis()
00137 {
00138         ASSERT (m_contextObj->MajicNumber() == JSMETHOD_MAJIC);
00139         return m_context;
00140 }
00141 
00142 Vector<VariantPtr> StackFrame::GetArgs()
00143 {
00144         Vector<VariantPtr> args;
00145         ASSERT (0 != m_enterStack.Count());
00146 
00147         int pos = m_enterStack.Peek() + 1;
00148         
00149         for (int x = pos; x < m_stack.Count(); x++)
00150         {
00151                 args.Add(m_stack.ElementAt(x));
00152         }
00153         return args;
00154 }
00155 
00156 #if defined(DEBUG) || defined(_DEBUG)
00157 void StackFrame::CheckMem() const
00158 {
00159         m_context.CheckMem();
00160         m_stack.CheckMem();
00161         m_enterStack.CheckMem();
00162 }
00163 
00164 void StackFrame::ValidateMem() const
00165 {
00166         m_context.ValidateMem();
00167         m_stack.ValidateMem();
00168         m_enterStack.ValidateMem();
00169 }
00170 #endif
00171 
00172 VarInterp::VarInterp()
00173 : m_stackFrames()
00174 {
00175 }
00176 
00177 VarInterp::VarInterp(VariantPtr method, Vector<VariantPtr>& args)
00178 : m_stackFrames()
00179 {
00180         PrepareToExecute(method, args);
00181 }
00182 
00183 VarInterp::~VarInterp()
00184 {
00185 }
00186 
00187 #if defined(DEBUG) || defined(_DEBUG)
00188 void VarInterp::CheckMem() const
00189 {
00190         m_stackFrames.CheckMem();
00191 }
00192 
00193 void VarInterp::ValidateMem() const
00194 {
00195         m_stackFrames.ValidateMem();
00196 }
00197 #endif
00198 
00199 RefCountPtr<IJsObject> VarInterp::CreateDefaultContext(Program& prog)
00200 {
00201         JsMethod *method = new JsMethod(prog);
00202         RefCountPtr<IJsObject> ctx(method);
00203         
00204         RefCountPtr<IJsObject> obj(new JsMethod(Program()));
00205         ctx->SetProperty("Object", VariantPtr(new Variant(obj)));
00206 
00207         ctx->SetProperty("toString", VariantPtr(new Variant(IJsObjectPtr(new GlobalToString()))));
00208         
00209         return ctx;
00210 }
00211 
00212 void VarInterp::PrepareToExecute(VariantPtr method, Vector<VariantPtr>& args)
00213 {
00214         m_stackFrames.Clear();
00215 
00216         IJsObjectPtr methodObj = method->ToObject();
00217         ASSERT(methodObj->MajicNumber() == JSMETHOD_MAJIC);
00218 
00219         m_stackFrames.Add((JsMethodPtr)methodObj);
00220 
00221         Frame().InitArgs(args);
00222 }
00223 
00224 bool VarInterp::Execute(bool continueAfterLine)
00225 {
00226         while (Frame().CanContinue())
00227         {
00228                 Instruction i = Frame().PreExecute();
00229                 switch (i.opCode)
00230                 {
00231                         case JSOP_NOP:
00232                                 break;
00233 
00234                         case JSOP_PUSH:
00235                                 break;
00236 
00237                         case JSOP_THIS:
00238                                 Frame().GetStack().Add(Frame().GetThis());
00239                                 break;
00240 
00241                         case JSOP_DEREF:
00242                                 ValidateMem();
00243                                 {
00244                                         VariantPtr propName = Frame().GetStack().Peek();
00245                                         PopStack();
00246                                         VariantPtr prop = Frame().GetStack().Peek();
00247                                         PopStack();
00248 
00249                                         if (prop->IsObject())
00250                                         {
00251                                                 VariantPtr innerProp = prop->ToObject()->GetProperty(*propName->ToString());
00252                                                 Frame().GetStack().Add(innerProp);
00253                                         }
00254                                         else
00255                                         {
00256                                                 Frame().GetStack().Add(VariantPtr(new Variant()));
00257                                         }
00258                                         ValidateMem();
00259                                 }
00260                                 break;
00261 
00262                         case JSOP_FINDPROP:
00263                                 ValidateMem();
00264                                 {
00265                                         VariantPtr prop = Frame().FindProperty(*Frame().GetStack().Peek());
00266                                         PopStack();
00267                                         ValidateMem();
00268                                         prop.ValidateMem();
00269                                         Frame().GetStack().Add(prop);
00270                                         ValidateMem();
00271                                 }
00272                                 break;
00273 
00274                         case JSOP_DEFPROP:
00275                                 Frame().DefineProperty();
00276                                 break;
00277                                 
00278                         case JSOP_NEW:
00279                                 {
00280                                         VariantPtr prop = Frame().FindProperty(*Frame().GetStack().Peek());
00281                                         PopStack();
00282                                         ValidateMem();
00283                                         prop.ValidateMem();
00284                                         
00285                                         if (prop->IsObject())
00286                                         {
00287                                                 IJsObjectPtr ijsprop = prop->ToObject();
00288                                                 PushStack(ijsprop->New());
00289                                         }
00290                                         else
00291                                         {
00292                                                 PushStack(VariantPtr(new Variant()));
00293                                         }                                       
00294                                 }
00295                                 break;
00296                                 
00297                         case JSOP_ASSIGN:
00298                                 {
00299                                         ValidateMem();
00300                                         VariantPtr val = Frame().GetStack().Peek();
00301                                         PopStack();
00302                                         ValidateMem();
00303                                         *Frame().GetStack().PeekRef() = *val->ToRValue();
00304                                         ValidateMem();
00305                                         PopStack();
00306                                 }
00307                                 ValidateMem();
00308                                 break;
00309 
00310                         case JSOP_ADD:
00311                                 {
00312                                         VariantPtr v1 = Frame().GetStack().Pop();
00313                                         *Frame().GetStack().Peek() = *v1->Add(*Frame().GetStack().Peek());
00314                                 }
00315                                 break;
00316 
00317                         case JSOP_ENTER:
00318                                 Frame().EnterBlock();
00319                                 break;
00320 
00321                         case JSOP_LEAVE:
00322                                 Frame().LeaveBlock();
00323                                 break;
00324                                                         
00325                         case JSOP_CALL:
00326                                 {
00327                                         VariantPtr vpm(Frame().GetCallThis());
00328                                         
00329                                         if (!vpm->IsObject())
00330                                         {
00331                                                 PushStack(VariantPtr(new Variant()));
00332                                                 break;
00333                                         }
00334 
00335                                         IJsObjectPtr jom = vpm->ToObject();
00336                                         if(jom->MajicNumber() != JSMETHOD_MAJIC)
00337                                         {
00338                                                 PushStack(VariantPtr(new Variant()));
00339                                                 break;
00340                                         }
00341 
00342                                         JsMethod *pm = (JsMethod *)jom.Get();
00343                                         if (pm->IsNative())
00344                                         {
00345                                                 VariantPtr ret = pm->Call(pm, Frame().GetArgs());
00346                                                 Frame().LeaveBlock();
00347                                                 PushStack(ret);
00348                                         }
00349                                         else
00350                                         {
00351                                                 StackFrame frm((JsMethodPtr)jom, &m_stackFrames.ElementAtRef(m_stackFrames.Count()-1));
00352                                                 frm.InitArgs(Frame().GetArgs());
00353                                                 m_stackFrames.Add(frm);
00354                                         }
00355                                 }
00356                                 break;
00357 
00358                         case JSOP_RET:
00359                                 {
00360                                         VariantPtr ret = ReturnValue();
00361                                         m_stackFrames.Pop();
00362                                         Frame().LeaveBlock();
00363                                         PushStack(ret);
00364                                 }
00365                                 break;
00366 
00367                         case JSOP_LINE:
00368                                 // can continue after debug line.
00369                                 return true;
00370 
00371                         default:
00372                                 throw new Exception("Internal error in VarInterp::Execute");
00373                 }
00374         }
00375         
00376         // exit is not the result of a LINE debug op.
00377         return false;
00378 }