NO_INLINE JsVar *jspeFactorMember(JsVar *a, JsVar **parentResult) {
  /* The parent if we're executing a method call */
  JsVar *parent = 0;

  while (lex->tk=='.' || lex->tk=='[') {
    if (lex->tk == '.') { // ------------------------------------- Record Access
      JSP_ASSERT_MATCH('.');
      if (jslIsIDOrReservedWord()) {
        if (JSP_SHOULD_EXECUTE) {
          // Note: name will go away when we parse something else!
          const char *name = jslGetTokenValueAsString();

          JsVar *aVar = jsvSkipNameWithParent(a,true,parent);
          JsVar *child = 0;
          if (aVar)
            child = jspGetNamedField(aVar, name, true);
          if (!child) {
            if (!jsvIsUndefined(aVar)) {
              // if no child found, create a pointer to where it could be
              // as we don't want to allocate it until it's written
              JsVar *nameVar = jslGetTokenValueAsVar();
              child = jsvCreateNewChild(aVar, nameVar, 0);
              jsvUnLock(nameVar);
            } else {
              // could have been a string...
              jsExceptionHere(JSET_ERROR, "Cannot read property '%s' of undefined", name);
            }
          }
          jsvUnLock(parent);
          parent = aVar;
          jsvUnLock(a);
          a = child;
        }
        // skip over current token (we checked above that it was an ID or reserved word)
        jslGetNextToken();
      } else {
        // incorrect token - force a match fail by asking for an ID
        JSP_MATCH_WITH_RETURN(LEX_ID, a);
      }
    } else if (lex->tk == '[') { // ------------------------------------- Array Access
      JsVar *index;
      JSP_ASSERT_MATCH('[');
      if (!jspCheckStackPosition()) return parent;
      index = jsvSkipNameAndUnLock(jspeAssignmentExpression());
      JSP_MATCH_WITH_CLEANUP_AND_RETURN(']', jsvUnLock2(parent, index);, a);
      if (JSP_SHOULD_EXECUTE) {
        index = jsvAsArrayIndexAndUnLock(index);
        JsVar *aVar = jsvSkipNameWithParent(a,true,parent);
        JsVar *child = 0;
        if (aVar)
          child = jspGetVarNamedField(aVar, index, true);

        if (!child) {
          if (jsvHasChildren(aVar)) {
            // if no child found, create a pointer to where it could be
            // as we don't want to allocate it until it's written
            child = jsvCreateNewChild(aVar, index, 0);
          } else {
            jsExceptionHere(JSET_ERROR, "Field or method %q does not already exist, and can't create it on %t", index, aVar);
          }
        }
        jsvUnLock(parent);
        parent = jsvLockAgainSafe(aVar);
        jsvUnLock(a);
        a = child;
        jsvUnLock(aVar);
      }
      jsvUnLock(index);
    } else {
      assert(0);
    }
  }

  if (parentResult) *parentResult = parent;
  else jsvUnLock(parent);
  return a;
}
NO_INLINE JsVar *jspeFactorMember(JsVar *a, JsVar **parentResult) {
   
  JsVar *parent = 0;

  while (lex->tk=='.' || lex->tk=='[') {
    if (lex->tk == '.') {  
      JSP_ASSERT_MATCH('.');
      if (jslIsIDOrReservedWord()) {
        if (JSP_SHOULD_EXECUTE) {
           
          const char *name = jslGetTokenValueAsString();

          JsVar *aVar = jsvSkipNameWithParent(a,true,parent);
          JsVar *child = 0;
          if (aVar)
            child = jspGetNamedField(aVar, name, true);
          if (!child) {
            if (!jsvIsUndefined(aVar)) {
               
               
              JsVar *nameVar = jslGetTokenValueAsVar();
              child = jsvCreateNewChild(aVar, nameVar, 0);
              jsvUnLock(nameVar);
            } else {
               
              jsExceptionHere(JSET_ERROR, "Cannot read property '%s' of undefined", name);
            }
          }
          jsvUnLock(parent);
          parent = aVar;
          jsvUnLock(a);
          a = child;
        }
         
        jslGetNextToken();
      } else {
         
        JSP_MATCH_WITH_RETURN(LEX_ID, a);
      }
    } else if (lex->tk == '[') {  
      JsVar *index;
      JSP_ASSERT_MATCH('[');
      if (!jspCheckStackPosition()) return parent;
      index = jsvSkipNameAndUnLock(jspeAssignmentExpression());
      JSP_MATCH_WITH_CLEANUP_AND_RETURN(']', jsvUnLock2(parent, index);, a);
      if (JSP_SHOULD_EXECUTE) {
        index = jsvAsArrayIndexAndUnLock(index);
        JsVar *aVar = jsvSkipNameWithParent(a,true,parent);
        JsVar *child = 0;
        if (aVar)
          child = jspGetVarNamedField(aVar, index, true);

        if (!child) {
          if (jsvHasChildren(aVar)) {
             
             
            child = jsvCreateNewChild(aVar, index, 0);
          } else {
            jsExceptionHere(JSET_ERROR, "Field or method %q does not already exist, and can't create it on %t", index, aVar);
          }
        }
        jsvUnLock(parent);
        parent = jsvLockAgainSafe(aVar);
        jsvUnLock(a);
        a = child;
        jsvUnLock(aVar);
      }
      jsvUnLock(index);
    } else {
      assert(0);
    }
  }

  if (parentResult) *parentResult = parent;
  else jsvUnLock(parent);
  return a;
}