// =================================================================
//	Performs semantic analysis on this node.
// =================================================================
CASTNode* CSliceExpressionASTNode::Semant(CSemanter* semanter)
{ 
	SEMANT_TRACE("CSliceExpressionASTNode");

	// Only semant once.
	if (Semanted == true)
	{
		return this;
	}
	Semanted = true;
	
	// Semant expressions.
	LeftValue = ReplaceChild(LeftValue, LeftValue->Semant(semanter));
	if (StartExpression != NULL)
	{
		StartExpression  = ReplaceChild(StartExpression, StartExpression->Semant(semanter));
	}
	if (EndExpression != NULL)
	{
		EndExpression    = ReplaceChild(EndExpression, EndExpression->Semant(semanter));
	}

	// Get expression references.
	CExpressionBaseASTNode* lValueBase    = dynamic_cast<CExpressionBaseASTNode*>(LeftValue);
	CExpressionBaseASTNode* startExprBase = dynamic_cast<CExpressionBaseASTNode*>(StartExpression);
	CExpressionBaseASTNode* endExprBase   = dynamic_cast<CExpressionBaseASTNode*>(EndExpression);
	
	// Cast index to integer.
	if (startExprBase != NULL)
	{
		StartExpression = ReplaceChild(startExprBase, startExprBase->CastTo(semanter, new CIntDataType(Token), Token));
	}
	if (endExprBase != NULL)
	{
		EndExpression   = ReplaceChild(endExprBase,   endExprBase->CastTo  (semanter, new CIntDataType(Token), Token));
	}

	// Valid object to slice?
	std::vector<CDataType*> argumentTypes;
	argumentTypes.push_back(new CIntDataType(Token));
	argumentTypes.push_back(new CIntDataType(Token));

	CClassASTNode* classNode = lValueBase->ExpressionResultType->GetClass(semanter);
	CClassMemberASTNode* memberNode = classNode->FindClassMethod(semanter, "GetSlice", argumentTypes, true, NULL, NULL);

	if (memberNode == NULL)
	{
		semanter->GetContext()->FatalError("Data type does not support slicing, no GetSlice method defined.", Token);
	}
	else
	{
		ExpressionResultType = memberNode->ReturnType;
	}

	return this;
}
Пример #2
0
void GpxRootElement::SetMetadata(GpxMetadataElement *metadata)
{
      bool b_was_cloned = true;

      if (!metadata)
            RemoveMetadata();
      else
      {
            if(my_metadata)
                  my_metadata = (GpxMetadataElement *)ReplaceChild(my_metadata, *metadata);
            else if (first_waypoint)
                  my_metadata = (GpxMetadataElement *)InsertBeforeChild(first_waypoint, *metadata);
            else if (first_route)
                  my_metadata = (GpxMetadataElement *)InsertBeforeChild(first_route, *metadata);
            else if (first_track)
                  my_metadata = (GpxMetadataElement *)InsertBeforeChild(first_track, *metadata);
            else if (my_extensions)
                  my_metadata = (GpxMetadataElement *)InsertBeforeChild(my_extensions, *metadata);
            else
            {
                  b_was_cloned = false;
                  my_metadata = (GpxMetadataElement *)LinkEndChild(metadata);
            }

            if(b_was_cloned)
            {
                  metadata->Clear();
                  delete metadata;
            }

      }
}
Пример #3
0
// =================================================================
//	Performs semantic analysis on this node.
// =================================================================
CASTNode* CCommaExpressionASTNode::Semant(CSemanter* semanter)
{ 
	// Only semant once.
	if (Semanted == true)
	{
		return this;
	}
	Semanted = true;
	
	// Semant expressions.
	LeftValue  = ReplaceChild(LeftValue,   LeftValue->Semant(semanter));
	RightValue = ReplaceChild(RightValue, RightValue->Semant(semanter)); 

	// Resulting type is always our right hand type.
	ExpressionResultType = dynamic_cast<CExpressionBaseASTNode*>(RightValue)->ExpressionResultType;

	return this;
}
// =================================================================
//	Performs semantic analysis on this node.
// =================================================================
CASTNode* CComparisonExpressionASTNode::Semant(CSemanter* semanter)
{ 
	SEMANT_TRACE("CComparisonExpressionASTNode");

	// Only semant once.
	if (Semanted == true)
	{
		return this;
	}
	Semanted = true;

	// Semant expressions.
	LeftValue  = ReplaceChild(LeftValue,   LeftValue->Semant(semanter));
	RightValue = ReplaceChild(RightValue, RightValue->Semant(semanter)); 

	// Get expression references.
	CExpressionBaseASTNode* leftValueBase  = dynamic_cast<CExpressionBaseASTNode*>(LeftValue);
	CExpressionBaseASTNode* rightValueBase = dynamic_cast<CExpressionBaseASTNode*>(RightValue);

	// Balance types.
	ExpressionResultType = semanter->BalanceDataTypes(leftValueBase->ExpressionResultType, 
														rightValueBase->ExpressionResultType);
	
	// Objects only permit equality operations.
	if (dynamic_cast<CObjectDataType*>(ExpressionResultType) != NULL &&
		Token.Type != TokenIdentifier::OP_EQUAL &&
		Token.Type != TokenIdentifier::OP_NOT_EQUAL)
	{
		semanter->GetContext()->FatalError(CStringHelper::FormatString("%s operator cannot be used on objects.", Token.Literal.c_str()), Token);
	}

	// Cast to resulting expression.
	LeftValue  = ReplaceChild(LeftValue,  leftValueBase->CastTo(semanter, ExpressionResultType, Token));
	RightValue = ReplaceChild(RightValue, rightValueBase->CastTo(semanter, ExpressionResultType, Token)); 

	CompareResultType = ExpressionResultType;
	ExpressionResultType = new CBoolDataType(Token);

	return this;
}
// =================================================================
// Performs semantic analysis of this node.
// =================================================================
CASTNode* CCaseStatementASTNode::Semant(CSemanter* semanter)
{	
	SEMANT_TRACE("CCaseStatementASTNode");

	// Only semant once.
	if (Semanted == true)
	{
		return this;
	}
	Semanted = true;

	// Find the switch statement we are part of.
	CASTNode* scope = this;
	CSwitchStatementASTNode* switchScope = NULL;

	while (scope != NULL && switchScope == NULL)
	{
		switchScope = dynamic_cast<CSwitchStatementASTNode*>(scope);
		scope = scope->Parent;
	}

	// Semant the expression.
	for (auto iter = Expressions.begin(); iter != Expressions.end(); iter++)
	{
		CASTNode* node = *iter;
		node = ReplaceChild(node, node->Semant(semanter));
		node = ReplaceChild(node, dynamic_cast<CExpressionBaseASTNode*>(node)->CastTo(semanter, switchScope->ExpressionStatement->ExpressionResultType, Token));
		(*iter) = node;
	}
	
	// Semant Body statement.
	if (BodyStatement != NULL)
	{
		BodyStatement = ReplaceChild(BodyStatement, BodyStatement->Semant(semanter));
	}

	return this;
}
Пример #6
0
Element *Element::ReplaceChild(Element *oldchild, Scm code) {
    Element *elm = GetElementFromObject(code);

    // if error with child, report error
    if (!elm)
        return NULL;

    // ensure elements are not added twice
    if (elm->GetParent() != NULL) {
        Error("element already has parent.");
        return NULL;
    }    
    
    ReplaceChild(oldchild, elm);
    return elm;
}
Пример #7
0
void GpxRootElement::SetExtensions(GpxExtensionsElement *extensions)
{
      if (!extensions)
            RemoveExtensions();
      else
      {
            if(!my_extensions)
                  my_extensions = (GpxExtensionsElement *)LinkEndChild(extensions);
            else
            {
                  my_extensions = (GpxExtensionsElement *)ReplaceChild(my_extensions, *extensions);
                  extensions->Clear();
                  delete extensions;
            }
      }
}
Пример #8
0
// =================================================================
//	Performs semantic analysis on this node.
// =================================================================
CASTNode* CThrowStatementASTNode::Semant(CSemanter* semanter)
{ 	
	Expression = dynamic_cast<CExpressionBaseASTNode*>(ReplaceChild(Expression, Expression->Semant(semanter)));

	CDataType* exception_base = FindDataType(semanter, "Exception", std::vector<CDataType*>());
	if (exception_base == NULL ||
		exception_base->GetClass(semanter) == NULL)
	{
		semanter->GetContext()->FatalError("Internal error, could not find base 'Exception' class.");
	}

	CDataType* catch_type = Expression->ExpressionResultType;
	if (catch_type == NULL ||
		catch_type->GetClass(semanter)->InheritsFromClass(semanter, exception_base->GetClass(semanter)) == false)
	{
		semanter->GetContext()->FatalError("Thrown exceptions must inherit from 'Exception' class.", Token);
	}

	return this;
}
Пример #9
0
void GpxTrkElement::SetProperty(const wxString &name, const wxString &value)
{
      //FIXME: doesn't care about order so it can be absolutely wrong, have to redo this code if it has to be used by something else than the constructor
      //then it can be made public
      //FIXME: can be reused for route and track
      GpxSimpleElement *element = new GpxSimpleElement(name, value);
      TiXmlElement *curelement = FirstChildElement();
      bool found = false;
      while(curelement)
      {
            if((const char *)curelement->Value() == (const char *)name.ToUTF8())
            {
                  ReplaceChild(curelement, *element);
                  element->Clear();
                  delete element;
                  break;
            }
            curelement = curelement->NextSiblingElement();
      }
      if (!found)
            LinkEndChild(element);
}
// =================================================================
//	Performs semantic analysis on this node.
// =================================================================
CASTNode* CMethodCallExpressionASTNode::Semant(CSemanter* semanter)
{ 
	SEMANT_TRACE("CMethodCallExpressionASTNode");

	// Only semant once.
	if (Semanted == true)
	{
		return this;
	}
	Semanted = true;

	// Get expression representations.
	CExpressionBaseASTNode* left_hand_expr	 = dynamic_cast<CExpressionBaseASTNode*>(LeftValue);
	CExpressionBaseASTNode* right_hand_expr  = dynamic_cast<CExpressionBaseASTNode*>(RightValue);

	// Semant left hand node.
	LeftValue  = ReplaceChild(LeftValue,   LeftValue->Semant(semanter));
	
	// Make sure we can access class.
	CClassASTNode* accessClass = left_hand_expr->ExpressionResultType->GetClass(semanter);
	if (accessClass == NULL)
	{
		semanter->GetContext()->FatalError(CStringHelper::FormatString("Invalid use of scoping operator."), Token);		
	}

	// Check we can access this class from here.
	accessClass->CheckAccess(semanter, this);

	// NOTE: Do not r-value semant identifier, we want to process that ourselves.
	CIdentifierExpressionASTNode* identNode = dynamic_cast<CIdentifierExpressionASTNode*>(RightValue);

	// Semant arguments.
	std::vector<CDataType*> argument_types;
	std::string argument_types_string;
	for (std::vector<CASTNode*>::iterator iter = ArgumentExpressions.begin(); iter < ArgumentExpressions.end(); iter++)
	{
		CExpressionBaseASTNode* node = dynamic_cast<CExpressionBaseASTNode*>((*iter)->Semant(semanter));
		argument_types.push_back(node->ExpressionResultType);

		if (iter != ArgumentExpressions.begin())
		{
			argument_types_string += ", ";
		}
		argument_types_string += node->ExpressionResultType->ToString();

		(*iter) = node;
	}

	// Make sure the identifier represents a valid field.
	CClassMemberASTNode* declaration = accessClass->FindClassMethod(semanter, identNode->Token.Literal, argument_types, false, NULL, this);
	if (declaration == NULL)
	{
		semanter->GetContext()->FatalError(CStringHelper::FormatString("Undefined method '%s(%s)' in class '%s'.", identNode->Token.Literal.c_str(), argument_types_string.c_str(), accessClass->ToString().c_str()), Token);		
	}

// UPDATE: Abstract method calling is fine. Remember we won't be able to instantiate classes that do not override all abstract methods.
//	if (declaration->IsAbstract == true)
//	{
//		semanter->GetContext()->FatalError(CStringHelper::FormatString("Cannot call method '%s(%s)' in class '%s', method is abstract.", identNode->Token.Literal.c_str(), argument_types_string.c_str(), accessClass->ToString().c_str()), Token);		
//	}
	
	ResolvedDeclaration = declaration;

	// Check we can access this field from here.
	declaration->CheckAccess(semanter, this);

	// HACK: This is really hackish and needs fixing!
	if (dynamic_cast<CThisExpressionASTNode*>(LeftValue) != NULL &&
		declaration->IsStatic == true)
	{		
		LeftValue = ReplaceChild(LeftValue, new CClassRefExpressionASTNode(NULL, Token));
		LeftValue->Token.Literal = declaration->FindClassScope(semanter)->Identifier;
		LeftValue->Semant(semanter);

		left_hand_expr	 = dynamic_cast<CExpressionBaseASTNode*>(LeftValue);
	}

	// Add default arguments if we do not have enough args to call.
	if (declaration->Arguments.size() > ArgumentExpressions.size())
	{
		for (unsigned int i = ArgumentExpressions.size(); i < declaration->Arguments.size() ; i++)
		{
			CASTNode* expr = declaration->Arguments.at(i)->AssignmentExpression->Clone(semanter);
			AddChild(expr);
			ArgumentExpressions.push_back(expr);

			expr->Semant(semanter);
		}
	}
	
	// Cast all arguments to correct data types.
	int index = 0;
	for (std::vector<CASTNode*>::iterator iter = ArgumentExpressions.begin(); iter != ArgumentExpressions.end(); iter++)
	{
		CDataType* dataType = declaration->Arguments.at(index++)->Type;

		CExpressionBaseASTNode* subnode = dynamic_cast<CExpressionBaseASTNode*>(*iter);
		subnode = dynamic_cast<CExpressionBaseASTNode*>(ReplaceChild(subnode, subnode->CastTo(semanter, dataType, Token)));
		(*iter) = subnode;
	}

	// If we are a class reference, we can only access static fields.
	bool isClassReference = (dynamic_cast<CClassReferenceDataType*>(left_hand_expr->ExpressionResultType) != NULL);
	if (isClassReference == true)
	{
		if (declaration->IsStatic == false)
		{
			semanter->GetContext()->FatalError(CStringHelper::FormatString("Cannot access instance method '%s' through class reference '%s'.", declaration->Identifier.c_str(), accessClass->ToString().c_str()), Token);	
		}
	}

	// If this is a constructor we are calling, make sure we are in a constructors scope, or its illegal!
	else
	{
		CClassMemberASTNode* methodScope = FindClassMethodScope(semanter);

		if (methodScope == NULL ||
			methodScope->IsConstructor == false)
		{
			if (declaration->IsConstructor == true)
			{
				semanter->GetContext()->FatalError("Calling constructors manually is only valid inside another constructors scope.", Token);	
			}
		}
	}

	// Resulting type is always our right hand type.
	ExpressionResultType = declaration->ReturnType;

	return this;
}