Esempio n. 1
0
// =================================================================
//	Performs semantic analysis on this node.
// =================================================================
CASTNode* CMethodBodyASTNode::Semant(CSemanter* semanter)
{
	// Only semant once.
	if (Semanted == true)
	{
		return this;
	}
	Semanted = true;

	SemantChildren(semanter);

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

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

	SemantChildren(semanter);
	return this;
}
Esempio n. 3
0
// =================================================================
//	Performs semantic analysis on this node.
// =================================================================
CASTNode* CClassASTNode::Semant(CSemanter* semanter)
{ 
	SEMANT_TRACE("CClassASTNode=%s", Identifier.c_str());

	// Only semant once.
	if (Semanted == true)
	{
		//m_semanting = false;
		return this;
	}
	Semanted = true;
	
	// Check for duplicate identifiers (only if we are not an instanced class).
	if (GenericInstanceOf == NULL)
	{
		Parent->CheckForDuplicateIdentifier(semanter, Identifier, this);
	}
	
	if (IsGeneric		  == false ||
		GenericInstanceOf != NULL)
	{
	
		// Work out mangled identifier.
		if (MangledIdentifier == "")
		{
			MangledIdentifier = semanter->GetMangled("ls_" + Identifier);
		}

		// Interface cannot use inheritance.
		if (InheritedTypes.size() > 0 && IsInterface == true)
		{
			semanter->GetContext()->FatalError("Interfaces cannot inherit from other interfaces or classes.", Token);
		}		
		if (InheritedTypes.size() > 0 && IsStatic == true)
		{
			semanter->GetContext()->FatalError("Static classes cannot inherit from interfaces.", Token);
		}
		
		// Flag this class as semanting - we do this so we can detect
		// inheritance loops.
		if (m_semanting == true)
		{
			semanter->GetContext()->FatalError("Detected illegal cyclic inheritance of '" + Identifier + "'.", Token);
		}
		m_semanting = true;
	
		// Semant inherited types.
		bool foundSuper = false;
		for (auto iter = InheritedTypes.begin(); iter != InheritedTypes.end(); iter++)
		{
			CIdentifierDataType* type = *iter;
			CClassASTNode* node = type->SemantAsClass(semanter, this, true);

			if (type->Identifier == Identifier)
			{
				semanter->GetContext()->FatalError("Attempt to inherit class from itself.", Token);
			}

			if (node->IsInterface == true)
			{
				Interfaces.push_back(node);
			}
			else
			{
				if (foundSuper == true)
				{
					semanter->GetContext()->FatalError("Multiple inheritance is not supported. Use interfaces instead.", Token);
				}
				SuperClass = node;
				foundSuper = true;
			}
		}

		// Native classes are not allowed to implement interfaces.
		//if (IsNative == true && Interfaces.size() > 0)
		//{
		//	semanter->GetContext()->FatalError("Native classes cannot implement interfaces.", Token);
		//}

		// If no inherited types the we inherit from object.
		if (SuperClass == NULL && IsNative == false)
		{
			SuperClass = dynamic_cast<CClassASTNode*>(FindDeclaration(semanter, "object"));

			if (SuperClass == NULL)
			{
				semanter->GetContext()->FatalError("Could not find base class to inherit from.", Token);
			}
		}
		else if (SuperClass != NULL)
		{
			// Check super class is valid.
			if (SuperClass->IsSealed == true)
			{
				semanter->GetContext()->FatalError("Classes cannot inherit from sealed class.", Token);
			}
		
			// Cannot inherit in static classes.
			if (IsStatic == true)
			{
				semanter->GetContext()->FatalError("Static classes cannot inherit from other classes.", Token);
			}
		}
		
		// Semant inherited classes.
		if (SuperClass != NULL)
		{
			SuperClass->Semant(semanter);
		}
		for (auto iter = Interfaces.begin(); iter != Interfaces.end(); iter++)
		{
			CClassASTNode* interfaceClass = *iter;
			interfaceClass->Semant(semanter);
		}
	
		// Look for interface in parent classes.
		if (SuperClass != NULL)
		{
			for (auto iter = Interfaces.begin(); iter != Interfaces.end(); iter++)
			{
				CClassASTNode* interfaceClass = *iter;
				if (SuperClass->InheritsFromClass(semanter, interfaceClass) != NULL)
				{
					semanter->GetContext()->FatalError(CStringHelper::FormatString("Attempt to implement interface '%s' that is already implemented by a parent class.", interfaceClass->Identifier.c_str()), Token);
				}
			}
		}

		// Remove semanting flag.
		m_semanting = false;		
	}

	// If we are generic we only semant children of instanced classes.
	if (IsGeneric		  == false ||
		GenericInstanceOf != NULL)
	{
		// Create static class constructor.
		if (IsInterface == false)
		{
			CClassMemberASTNode* defaultCtor = FindClassMethod(semanter, "__"+Identifier+"_ClassConstructor", std::vector<CDataType*>(), false);
			if (defaultCtor == NULL)
			{
				CClassMemberASTNode* member		= new CClassMemberASTNode(NULL, Token);
				member->MemberType				= MemberType::Method;
				member->Identifier				= "__"+Identifier+"_ClassConstructor";
				member->AccessLevel				= AccessLevel::PUBLIC;
				member->Body					= new CMethodBodyASTNode(member, Token);
				member->IsConstructor			= true;
				member->IsStatic				= true;
				member->ReturnType				= new CVoidDataType(Token);
				member->IsExtension				= IsNative;
				Body->AddChild(member);

				ClassConstructor				= member; 
			}

			if (IsNative == false && IsEnum == false)
			{
				// Create instance constructor.
				CClassMemberASTNode* instanceCtor = FindClassMethod(semanter, "__"+Identifier+"_InstanceConstructor", std::vector<CDataType*>(), false);
				if (instanceCtor == NULL)
				{
					CClassMemberASTNode* member		= new CClassMemberASTNode(NULL, Token);
					member->MemberType				= MemberType::Method;
					member->Identifier				= "__"+Identifier+"_InstanceConstructor";
					member->AccessLevel				= AccessLevel::PUBLIC;
					member->Body					= new CMethodBodyASTNode(member, Token);
					member->IsConstructor			= true;
					member->IsStatic				= false;
					member->ReturnType				= new CVoidDataType(Token);
					Body->AddChild(member);

					InstanceConstructor				= member; 
				}
			}

			// If no argument-less constructor has been provided, lets create a default one.
			if (IsStatic == false && IsAbstract == false && IsInterface == false && IsNative == false && IsEnum == false)
			{
				CClassMemberASTNode* defaultCtor = FindClassMethod(semanter, Identifier, std::vector<CDataType*>(), false);
				if (defaultCtor == NULL)
				{
					CClassMemberASTNode* member = new CClassMemberASTNode(NULL, Token);
					member->MemberType			= MemberType::Method;
					member->Identifier			= Identifier;
					member->AccessLevel			= AccessLevel::PUBLIC;
					member->Body				= new CMethodBodyASTNode(member, Token);
					member->IsConstructor		= true;
					member->ReturnType			= new CVoidDataType(Token);
					Body->AddChild(member);
				}
			}
	
		}
		
		// Semant all members.
		SemantChildren(semanter);
	}

	return this;
}