Esempio n. 1
0
bool gmCodeGenPrivate::GenStmtForEach(const gmCodeTreeNode * a_node, gmByteCodeGen * a_byteCode)
{
  unsigned int breakAddress, continueAddress, loc1, loc2;

  // Generate table
  if(!Generate(a_node->m_children[0], a_byteCode))
  {
    return false;
  }

  PushLoop();

  // Push the first iterator
  a_byteCode->Emit(BC_PUSHINT, (gmuint32) -2); // first iterator value.

  continueAddress = a_byteCode->Tell();

  // Generate call
  const char * keyVar = s_tempVarName1;
  if(a_node->m_children[2]) keyVar = a_node->m_children[2]->m_data.m_string;
  const char * valueVar = a_node->m_children[1]->m_data.m_string;

  gmuint16 keyOffset = (gmuint16) m_currentFunction->SetVariableType(keyVar, CTVT_LOCAL);
  gmuint16 valueOffset = (gmuint16) m_currentFunction->SetVariableType(valueVar, CTVT_LOCAL);
  gmuint32 opcode = (keyOffset << 16) | (valueOffset & 0xffff);

  loc1 = a_byteCode->Tell();
  a_byteCode->Emit(BC_FOREACH, opcode);

  // Skip space for jump
  loc2 = a_byteCode->Skip(SIZEOF_BC_BRA);

  // Generate body
  if(!Generate(a_node->m_children[3], a_byteCode))
  {
    PopLoop();
    return false;
  }

  a_byteCode->EmitPtr(BC_BRA, (gmuint32) loc1);
  breakAddress = a_byteCode->Seek(loc2);
  a_byteCode->EmitPtr(BC_BRZ, breakAddress);
  a_byteCode->Seek(breakAddress);

  // pop table and iterator
  a_byteCode->Emit(BC_POP2);

  ApplyPatches(m_loopStack[m_currentLoop].m_breaks, a_byteCode, breakAddress);
  ApplyPatches(m_loopStack[m_currentLoop].m_continues, a_byteCode, continueAddress);

  PopLoop();
  return true;
}
Esempio n. 2
0
bool gmCodeGenPrivate::GenStmtFork(const gmCodeTreeNode * a_node, gmByteCodeGen * a_byteCode)
{
   GM_ASSERT(a_node->m_type == CTNT_STATEMENT && a_node->m_subType == CTNST_FORK );
   
   gmuint32 loc1,loc2;

   // create the var for the thread id
   const char * valname = 0;
   gmuint32 valref = 0;
   if ( a_node->m_children[1])
   {
      valname = a_node->m_children[1]->m_data.m_string;
      valref = m_currentFunction->SetVariableType( valname, CTVT_LOCAL );
   }

   loc1 = a_byteCode->Skip( SIZEOF_BC_BRA );
   
   if (!valname) a_byteCode->Emit( BC_POP );   // if not specified then just pop
   else a_byteCode->Emit( BC_SETLOCAL, valref );   // store the thread id
   if (!Generate(a_node->m_children[0], a_byteCode )) return false;
   a_byteCode->Emit( BC_RET );
   
   loc2 = a_byteCode->Seek( loc1 );
   a_byteCode->Emit( BC_FORK, loc2 );
   a_byteCode->Seek( loc2 );
   
   if (!valname) a_byteCode->Emit( BC_POP );   // if not specified then just pop
   else a_byteCode->Emit( BC_SETLOCAL, valref );   // store the thread id
   
   return true;
}
Esempio n. 3
0
bool gmCodeGenPrivate::GenDeclVariable(const gmCodeTreeNode * a_node, gmByteCodeGen * a_byteCode)
{
  GM_ASSERT(a_node->m_type == CTNT_DECLARATION && a_node->m_subType == CTNDT_VARIABLE);
  GM_ASSERT(m_currentFunction);
  m_currentFunction->SetVariableType(a_node->m_children[0]->m_data.m_string, (gmCodeTreeVariableType) a_node->m_subTypeType);
  return true;
}
Esempio n. 4
0
bool gmCodeGenPrivate::GenExprFunction(const gmCodeTreeNode * a_node, gmByteCodeGen * a_byteCode)
{
  GM_ASSERT(a_node->m_type == CTNT_EXPRESSION && a_node->m_subType == CTNET_FUNCTION);

  gmptr id = m_hooks->GetFunctionId();
  a_byteCode->EmitPtr(BC_PUSHFN, id);

  // Create the function
  PushFunction();

  // Get a debug function name as the name of the variable the function is assigned to
  if(m_debug && a_node->m_parent && a_node->m_parent->m_type == CTNT_EXPRESSION && a_node->m_parent->m_subType == CTNET_OPERATION &&
     (a_node->m_parent->m_subTypeType == CTNOT_ASSIGN || a_node->m_parent->m_subTypeType == CTNOT_ASSIGN_FIELD) && a_node->m_parent->m_children[1] == a_node)
  {
    const gmCodeTreeNode * debugName = a_node->m_parent->m_children[0];
    if(debugName && debugName->m_type == CTNT_EXPRESSION && debugName->m_subType == CTNET_IDENTIFIER)
    {
    }
    else if(debugName->m_type == CTNT_EXPRESSION && debugName->m_subType == CTNET_OPERATION && 
            debugName->m_subTypeType == CTNOT_DOT)
    {
      debugName = debugName->m_children[1];
    }
    else
    {
      debugName = NULL;
    }

    if(debugName)
    {
      GM_ASSERT(debugName->m_type == CTNT_EXPRESSION && debugName->m_subType == CTNET_IDENTIFIER);
      m_currentFunction->m_debugName = debugName->m_data.m_string;
    }
  }

  // Parameters
  const gmCodeTreeNode * params = a_node->m_children[0];
  int numParams = 0;
  while(params)
  {
    const gmCodeTreeNode * param = params->m_children[0];
    GM_ASSERT(param->m_type == CTNT_EXPRESSION && param->m_subType == CTNET_IDENTIFIER);
    if(m_currentFunction->SetVariableType(param->m_data.m_string, CTVT_LOCAL) != numParams)
    {
      if(m_log) m_log->LogEntry("error (%d) parameter %s already declared", param->m_lineNumber, param->m_data.m_string);
      PopFunction();
      return false;
    }
    ++numParams;
    params = params->m_sibling;
  }

  // Generate the code
  bool res = Generate(a_node->m_children[1], &m_currentFunction->m_byteCode);

  // Generate a return incase the function didnt have one.
  m_currentFunction->m_byteCode.Emit(BC_RET);

  if(res)
  {
    // Create a locals table
    const char ** locals = NULL;
    if(m_debug)
    {
      locals = (const char **) alloca(sizeof(const char *) * m_currentFunction->m_numLocals);
      memset(locals, 0, sizeof(const char *) * m_currentFunction->m_numLocals);

      for(gmuint v = 0; v < m_currentFunction->m_variables.Count(); ++v)
      {
        Variable &variable = m_currentFunction->m_variables[v];
        if(variable.m_offset != -1)
        {
          locals[variable.m_offset] = variable.m_symbol;
        }
      }
    }

    // Add the function to the hooks.

    gmSortDebugLines(m_currentFunction->m_lineInfo);
    
    gmFunctionInfo info;
    info.m_id = id;
    info.m_root = false;
    info.m_byteCode = m_currentFunction->m_byteCode.GetData();
    info.m_byteCodeLength = m_currentFunction->m_byteCode.Tell();
    info.m_numParams = numParams;
    info.m_numLocals = m_currentFunction->m_numLocals - numParams;
    info.m_symbols = locals;
    info.m_maxStackSize = m_currentFunction->m_byteCode.GetMaxTos();
    info.m_lineInfoCount = m_currentFunction->m_lineInfo.Count();
    info.m_lineInfo = m_currentFunction->m_lineInfo.GetData();
    info.m_debugName = m_currentFunction->m_debugName;
    m_hooks->AddFunction(info);

    //gmByteCodePrint(stdout, info.m_byteCode, info.m_byteCodeLength);
  }

  PopFunction();
  
  return res;
}
Esempio n. 5
0
bool gmCodeGenPrivate::GenExprOpAssign(const gmCodeTreeNode * a_node, gmByteCodeGen * a_byteCode)
{
  GM_ASSERT(a_node->m_type == CTNT_EXPRESSION && a_node->m_subType == CTNET_OPERATION);

  // value on left hand side must be an l-value... ie, a dot, array or identifier.
  const gmCodeTreeNode * lValue = a_node->m_children[0];
  int type = 0;

  if(lValue->m_type == CTNT_EXPRESSION && lValue->m_subType == CTNET_OPERATION && lValue->m_subTypeType == CTNOT_DOT)
  {
    // Generate half l-value
    if(!Generate(lValue->m_children[0], a_byteCode)) return false;
    type = 0;
  }
  else if(lValue->m_type == CTNT_EXPRESSION && lValue->m_subType == CTNET_OPERATION && lValue->m_subTypeType == CTNOT_ARRAY_INDEX)
  {
    // Generate half l-value
    if(!Generate(lValue->m_children[0], a_byteCode)) return false;
    if(!Generate(lValue->m_children[1], a_byteCode)) return false;
    type = 1;
  }
  else if(lValue->m_type == CTNT_EXPRESSION && lValue->m_subType == CTNET_IDENTIFIER)
  {
    type = 2;
  }
  else
  {
    if(m_log) m_log->LogEntry("error (%d) illegal l-value for '=' operator", a_node->m_lineNumber);
    return false;
  }

  // Generate r-value
  if(!Generate(a_node->m_children[1], a_byteCode)) return false;

  // complete assignment
  if(type == 0)
  {
    a_byteCode->EmitPtr(BC_SETDOT, m_hooks->GetSymbolId(lValue->m_children[1]->m_data.m_string));
  }
  else if(type == 1)
  {
    a_byteCode->Emit(BC_SETIND);
  }
  else if(type == 2)
  {
    gmCodeTreeVariableType vtype;
    int offset = m_currentFunction->GetVariableOffset(lValue->m_data.m_string, vtype);

    // if local, set local regardless
    // if member set this
    // if global, set global
    // set and add local

    if((lValue->m_flags & gmCodeTreeNode::CTN_MEMBER) > 0)
    {
      return a_byteCode->EmitPtr(BC_SETTHIS, m_hooks->GetSymbolId(lValue->m_data.m_string));
    }
    if(offset >= 0 && vtype == CTVT_LOCAL)
    {
      return a_byteCode->Emit(BC_SETLOCAL, (gmuint32) offset);
    }
    else if(offset == -1)
    {
      if(vtype == CTVT_MEMBER)
      {
        return a_byteCode->EmitPtr(BC_SETTHIS, m_hooks->GetSymbolId(lValue->m_data.m_string));
      }
      else if(vtype == CTVT_GLOBAL)
      {
        return a_byteCode->EmitPtr(BC_SETGLOBAL, m_hooks->GetSymbolId(lValue->m_data.m_string));
      }
      if(m_log) m_log->LogEntry("internal error");
      return false;
    }

    offset = m_currentFunction->SetVariableType(lValue->m_data.m_string, CTVT_LOCAL);
    return a_byteCode->Emit(BC_SETLOCAL, (gmuint32) offset);
  }
  else
  {
    // paranoia
    if(m_log) m_log->LogEntry("internal error");
    return false;
  }

  return true;
}
Esempio n. 6
0
bool gmCodeGenPrivate::GenExprOpPreIncDec(const gmCodeTreeNode * a_node, gmByteCodeGen * a_byteCode)
{
  GM_ASSERT(a_node->m_type == CTNT_EXPRESSION && a_node->m_subType == CTNET_OPERATION);

  // Make sure child 0 is an l-value
  const gmCodeTreeNode * lValue = a_node->m_children[0];
  int type = 0;

  if(lValue->m_type == CTNT_EXPRESSION && lValue->m_subType == CTNET_OPERATION && lValue->m_subTypeType == CTNOT_DOT)
  {
    // Generate half l-value
    if(!Generate(lValue->m_children[0], a_byteCode)) return false;
    a_byteCode->Emit(BC_DUP);
    a_byteCode->EmitPtr(BC_GETDOT, m_hooks->GetSymbolId(lValue->m_children[1]->m_data.m_string));
    type = 0;
  }
  else if(lValue->m_type == CTNT_EXPRESSION && lValue->m_subType == CTNET_OPERATION && lValue->m_subTypeType == CTNOT_ARRAY_INDEX)
  {
    // Generate half l-value
    if(!Generate(lValue->m_children[0], a_byteCode)) return false;
    if(!Generate(lValue->m_children[1], a_byteCode)) return false;
    a_byteCode->Emit(BC_DUP2);
    a_byteCode->Emit(BC_GETIND);
    type = 1;
  }
  else if(lValue->m_type == CTNT_EXPRESSION && lValue->m_subType == CTNET_IDENTIFIER)
  {
    if(!Generate(lValue, a_byteCode)) return false;
    type = 2;
  }
  else
  {
    if(m_log) m_log->LogEntry("illegal l-value for '++/--' operator, line %d", a_node->m_lineNumber);
    return false;
  }

  // Perform inc/dec
  switch(a_node->m_subTypeType)
  {
    case CTNOT_PRE_INC : a_byteCode->Emit(BC_OP_INC); break;
    case CTNOT_PRE_DEC : a_byteCode->Emit(BC_OP_DEC); break;
    default :
    {
      if(m_log) m_log->LogEntry("unkown operator");
      return false;
    }
  }

  // Write back the value
  if(type == 0)
  {
    int offset = m_currentFunction->SetVariableType(s_tempVarName0, CTVT_LOCAL);
    a_byteCode->Emit(BC_DUP);
    a_byteCode->Emit(BC_SETLOCAL, (gmuint32) offset);
    a_byteCode->EmitPtr(BC_SETDOT, m_hooks->GetSymbolId(lValue->m_children[1]->m_data.m_string));
    a_byteCode->Emit(BC_GETLOCAL, (gmuint32) offset);
  }
  else if(type == 1)
  {
    int offset = m_currentFunction->SetVariableType(s_tempVarName0, CTVT_LOCAL);
    a_byteCode->Emit(BC_DUP);
    a_byteCode->Emit(BC_SETLOCAL, (gmuint32) offset);
    a_byteCode->Emit(BC_SETIND);
    a_byteCode->Emit(BC_GETLOCAL, (gmuint32) offset);
  }
  else if(type == 2)
  {
    a_byteCode->Emit(BC_DUP);
    gmCodeTreeVariableType vtype;
    int offset = m_currentFunction->GetVariableOffset(lValue->m_data.m_string, vtype);

    // if local, set local regardless
    // if member set this
    // if global, set global
    // set and add local

    if((lValue->m_flags & gmCodeTreeNode::CTN_MEMBER) > 0)
    {
      return a_byteCode->EmitPtr(BC_SETTHIS, m_hooks->GetSymbolId(lValue->m_data.m_string));
    }

    if(offset >= 0 && vtype == CTVT_LOCAL)
    {
      return a_byteCode->Emit(BC_SETLOCAL, (gmuint32) offset);
    }
    else if(offset == -1)
    {
      if(vtype == CTVT_MEMBER)
      {
        return a_byteCode->EmitPtr(BC_SETTHIS, m_hooks->GetSymbolId(lValue->m_data.m_string));
      }
      else if(vtype == CTVT_GLOBAL)
      {
        return a_byteCode->EmitPtr(BC_SETGLOBAL, m_hooks->GetSymbolId(lValue->m_data.m_string));
      }
      if(m_log) m_log->LogEntry("internal error");
      return false;
    }

    offset = m_currentFunction->SetVariableType(lValue->m_data.m_string, CTVT_LOCAL);
    return a_byteCode->Emit(BC_SETLOCAL, (gmuint32) offset);
  }
  else
  {
    // paranoia
    if(m_log) m_log->LogEntry("internal error");
    return false;
  }

  return true;
}