// =================================================================
//	Performs finalization on this node.
//
//	TODO: Move this into semant, we only have it in here because
//		  if we do a checkAccess in semant we will get a null
//		  reference exception if we are still assinging this
//		  nodes parents (in the case of implicit boxing)
//
// =================================================================
CASTNode* CNewExpressionASTNode::Finalize(CSemanter* semanter)
{
	// Grab arguments.
	std::vector<CDataType*> argument_datatypes;
	for (auto iter = ArgumentExpressions.begin(); iter != ArgumentExpressions.end(); iter++)
	{
		CExpressionBaseASTNode* node = dynamic_cast<CExpressionBaseASTNode*>(*iter);
		argument_datatypes.push_back(node->ExpressionResultType);
	}

	// Create new object.
	if (dynamic_cast<CArrayDataType*>(DataType) == NULL)
	{		
		// Check class is valid.
		CClassASTNode* classNode = DataType->GetClass(semanter);

		// Check we can find a constructor.
		CClassMemberASTNode* node = classNode->FindClassMethod(semanter, classNode->Identifier, argument_datatypes, false);
		if (node == NULL)
		{
			semanter->GetContext()->FatalError(CStringHelper::FormatString("Could not find suitable constructor to instantiate class '%s'.", DataType->ToString().c_str()), Token);
		}

		// Now to do the actual finalization - checking if access is valid!
		node->CheckAccess(semanter, this);
	}

	return this;
}
Ejemplo n.º 2
0
// =================================================================
//	Creates a clone of this node.
// =================================================================
CASTNode* CClassASTNode::Clone(CSemanter* semanter)
{
	CClassASTNode* clone = new CClassASTNode(NULL, Token);
	
	//clone->MangledIdentifier = this->MangledIdentifier;
	clone->IsNative			  = this->IsNative;
	clone->Identifier		 = this->Identifier;
	clone->AccessLevel		 = this->AccessLevel;
	clone->IsStatic			 = this->IsStatic;
	clone->IsAbstract		 = this->IsAbstract;
	clone->IsInterface		 = this->IsInterface;
	clone->IsSealed			 = this->IsSealed;
	clone->IsGeneric		 = this->IsGeneric;
	clone->InheritsNull		 = this->InheritsNull;
	clone->GenericTypeTokens = this->GenericTypeTokens;
	clone->InheritedTypes	 = this->InheritedTypes;	
	clone->HasBoxClass		 = this->HasBoxClass;
	clone->BoxClassIdentifier = this->BoxClassIdentifier;
	clone->IsEnum			 = this->IsEnum;
	clone->Body				 = dynamic_cast<CClassBodyASTNode*>(this->Body->Clone(semanter));
	clone->ObjectDataType	 = new CObjectDataType(Token, clone);
	clone->AddChild(clone->Body);

	if (ClassConstructor != NULL)
	{
		for (auto iter = clone->Body->Children.begin(); iter != clone->Body->Children.end(); iter++)
		{
			CClassMemberASTNode* member = dynamic_cast<CClassMemberASTNode*>(*iter);
			if (member != NULL)
			{
				if (member->Identifier == ClassConstructor->Identifier)
				{
					clone->ClassConstructor = member;
					break;
				}
			}
		}
	}
	
	if (InstanceConstructor != NULL)
	{
		for (auto iter = clone->Body->Children.begin(); iter != clone->Body->Children.end(); iter++)
		{
			CClassMemberASTNode* member = dynamic_cast<CClassMemberASTNode*>(*iter);
			if (member != NULL)
			{
				if (member->Identifier == InstanceConstructor->Identifier)
				{
					clone->InstanceConstructor = member;
					break;
				}
			}
		}
	}
	
	return clone;
}
// =================================================================
//	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;
}
// =================================================================
//	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;
}
// =================================================================
//	Performs semantic analysis on this node.
// =================================================================
CASTNode* CNewExpressionASTNode::Semant(CSemanter* semanter)
{
	SEMANT_TRACE("CNewExpressionASTNode");

	// Semant data types.
	DataType = DataType->Semant(semanter, this);

	// Semant arguments.
	std::vector<CDataType*> argument_datatypes;
	for (auto iter = ArgumentExpressions.begin(); iter != ArgumentExpressions.end(); iter++)
	{
		CExpressionBaseASTNode* node = dynamic_cast<CExpressionBaseASTNode*>(*iter);
		node = dynamic_cast<CExpressionBaseASTNode*>(node->Semant(semanter));
		argument_datatypes.push_back(node->ExpressionResultType);
		(*iter) = node;
	}

	// Semant array initializer.
	if (ArrayInitializer != NULL)
	{
		ArrayInitializer->Semant(semanter);
	}

	// Create new array of objects.
	if (IsArray == true)
	{
		// Cast all arguments to correct data types.
		int index = 0;
		for (auto iter = ArgumentExpressions.begin(); iter != ArgumentExpressions.end(); iter++)
		{
			CExpressionBaseASTNode* subnode = dynamic_cast<CExpressionBaseASTNode*>(*iter);
			subnode->Parent->ReplaceChild(subnode, subnode = dynamic_cast<CExpressionBaseASTNode*>(subnode->CastTo(semanter, new CIntDataType(Token), Token)));
			(*iter) = subnode;
		}

		ExpressionResultType = DataType;
	}

	// Create a new object!
	else
	{		
		// Make sure DT is a class.
		if (dynamic_cast<CObjectDataType*>(DataType) == NULL)
		{
			semanter->GetContext()->FatalError(CStringHelper::FormatString("Cannot instantiate primitive data type '%s'.", DataType->ToString().c_str()), Token);
		}

		// Check class is valid.
		CClassASTNode* classNode = DataType->GetClass(semanter);
		if (classNode->IsInterface == true)
		{
			semanter->GetContext()->FatalError(CStringHelper::FormatString("Cannot instantiate interface '%s'.", DataType->ToString().c_str()), Token);
		}
		if (classNode->IsAbstract == true)
		{
			semanter->GetContext()->FatalError(CStringHelper::FormatString("Cannot instantiate abstract class '%s'.", DataType->ToString().c_str()), Token);
		}
		if (classNode->IsStatic == true)
		{
			semanter->GetContext()->FatalError(CStringHelper::FormatString("Cannot instantiate static class '%s'.", DataType->ToString().c_str()), Token);
		}
		if (classNode->IsNative == true)
		{
			semanter->GetContext()->FatalError(CStringHelper::FormatString("Cannot instantiate native class '%s'.", DataType->ToString().c_str()), Token);
		}

		classNode->IsInstanced = true;
		classNode->InstancedBy = this;

		// Check we can find a constructor.
		CClassMemberASTNode* node = classNode->FindClassMethod(semanter, classNode->Identifier, argument_datatypes, false);
		if (node == NULL)
		{
			semanter->GetContext()->FatalError(CStringHelper::FormatString("No suitable constructor to instantiate class '%s'.", DataType->ToString().c_str()), Token);
		}

	//	if (classNode->Identifier == "MapPair")
	//	{
	//		printf("WUT");
	//	}

		ResolvedConstructor = node;

		// Cast all arguments to correct data types.
		int index = 0;
		for (auto iter = ArgumentExpressions.begin(); iter != ArgumentExpressions.end(); iter++)
		{
			CDataType* dataType = node->Arguments.at(index++)->Type;

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

			(*iter) = subnode_casted;
		}

		ExpressionResultType = DataType;
	}

	// Check we can create new object.
	if (dynamic_cast<CArrayDataType*>(DataType) == NULL)
	{		
		// Check class is valid.
		CClassASTNode* classNode = DataType->GetClass(semanter);

		// Check we can find a constructor.
		CClassMemberASTNode* node = classNode->FindClassMethod(semanter, classNode->Identifier, argument_datatypes, false);
		if (node == NULL)
		{
			semanter->GetContext()->FatalError(CStringHelper::FormatString("Could not find suitable constructor to instantiate class '%s'.", DataType->ToString().c_str()), Token);
		}
	}

	return this;
}
Ejemplo n.º 6
0
// =================================================================
//	Instantiates a copy of this class if its a generic, or just
//	returns the class if its not generic.
// =================================================================
CClassASTNode* CClassASTNode::GenerateClassInstance(CSemanter* semanter, CASTNode* referenceNode, std::vector<CDataType*> generic_arguments)
{
	if (IsGeneric == true)
	{
		if (generic_arguments.size() != GenericTypeTokens.size())
		{
			if (generic_arguments.size() == 0)
			{
				semanter->GetContext()->FatalError(CStringHelper::FormatString("Class '%s' is generic and expects generic arguments.", Token.Literal.c_str()), referenceNode->Token);
			}
			else
			{
				semanter->GetContext()->FatalError(CStringHelper::FormatString("Incorrect number of generic arguments given to class '%s' during instantiation.", Token.Literal.c_str()), referenceNode->Token);
			}
		}

		// Instance with these data types already exists?
		for (auto iter = GenericInstances.begin(); iter != GenericInstances.end(); iter++)
		{
			CClassASTNode* instance = *iter;
			bool argumentsMatch = true;
			
			for (unsigned int i = 0; i < instance->GenericInstanceTypes.size(); i++)
			{
				if (!instance->GenericInstanceTypes.at(i)->IsEqualTo(semanter, generic_arguments.at(i)))
				{
					argumentsMatch = false;
					break;
				}
			}

			if (argumentsMatch == true)
			{
				return instance;
			}
		}

		// Nope, time to create it.
		CClassASTNode* astNode			= dynamic_cast<CClassASTNode*>(this->Clone(semanter));
		astNode->Parent					= Parent; // We set the derived node to our parent so it can correctly find things in its scope, but so that it can't be found by others.
		astNode->GenericInstanceOf		= this;
		astNode->GenericInstanceTypes	= generic_arguments;
		GenericInstances.push_back(astNode);

		// Create alias's for all generic type tokens.		
		for (unsigned int i = 0; i < generic_arguments.size(); i++)
		{
			CToken&		token	= GenericTypeTokens.at(i);
			CDataType*	type	= generic_arguments.at(i);
			
			CAliasASTNode* alias = new CAliasASTNode(astNode->Body, this->Token, token.Literal, type);
			astNode->Body->AddChild(alias);
			alias->Semant(semanter);
		}

		// Semant our new instance.
		astNode->Semant(semanter);

		return astNode;
	}
	else
	{
		if (generic_arguments.size() > 0)
		{
			semanter->GetContext()->FatalError(CStringHelper::FormatString("Class '%s' is not generic and cannot be instantiated.", Token.Literal.c_str()), referenceNode->Token);
		}
		return this;
	}
}
Ejemplo n.º 7
0
// =================================================================
//	Performs finalization on this class.
// =================================================================
CASTNode* CClassASTNode::Finalize(CSemanter* semanter)
{
	// If we are generic, only finalize instances.
	if (IsGeneric == false || GenericInstanceOf != NULL)
	{
		// Check for hiding variables and methods.
		for (auto iter = Body->Children.begin(); iter != Body->Children.end(); iter++)
		{
			CClassMemberASTNode* node = dynamic_cast<CClassMemberASTNode*>(*iter);
			if (node != NULL)
			{
				CClassASTNode* scope = SuperClass;
				while (scope != NULL)
				{
					for (auto iter2 = scope->Body->Children.begin(); iter2 != scope->Body->Children.end(); iter2++)
					{
						CClassMemberASTNode* node2 = dynamic_cast<CClassMemberASTNode*>(*iter2);
						if (node2 != NULL &&
							node->Identifier == node2->Identifier &&
							(
								(node->IsOverride == false && node2->IsVirtual == true) ||
								(node->MemberType == MemberType::Field || node2->MemberType == MemberType::Field) 
							))
						{
							if (node->MemberType  == MemberType::Method ||
								node2->MemberType == MemberType::Method)
							{
								semanter->GetContext()->FatalError(CStringHelper::FormatString("Method '%s' in class '%s' hides existing declaration in class '%s'.", node->Identifier.c_str(), ToString().c_str(), scope->ToString().c_str()), node->Token);
							}
							else
							{
								semanter->GetContext()->FatalError(CStringHelper::FormatString("Member '%s' in class '%s' hides existing declaration in class '%s'.", node->Identifier.c_str(), ToString().c_str(), scope->ToString().c_str()), node->Token);
							}
						}
					}
					scope = scope->SuperClass;
				}			
			}
		}

		// Flag us as abstract if we have any abstract methods in our inheritance tree.	
		if (IsAbstract == false)
		{
			CClassASTNode* scope = this;
			std::vector<CClassMemberASTNode*> members;
			while (scope != NULL && IsAbstract == false)
			{
				// Look for abstract methods in this scope.		
				for (auto iter = scope->Body->Children.begin(); iter != scope->Body->Children.end() && IsAbstract == false; iter++)
				{
					CClassMemberASTNode* member = dynamic_cast<CClassMemberASTNode*>(*iter);
					if (member != NULL && member->MemberType == MemberType::Method)
					{
						// If member is abstract, check it is implemented in the members we have 
						// see higher in the inheritance tree so far.
						if (member->IsAbstract == true)
						{
							bool found = false;
							for (auto iter2 = members.begin(); iter2 != members.end(); iter2++)
							{
								CClassMemberASTNode* sub_member = *iter2;
								
								if (sub_member->EqualToMember(semanter, member))
								{
									found = true;
									break;
								}
							}

							// If not found, this class is abstract!
							if (found == false)
							{
								if (IsInstanced == true)
								{
									semanter->GetContext()->FatalError(CStringHelper::FormatString("Cannot instantiate abstract class '%s'.", ToString().c_str()), InstancedBy->Token);
								}
								IsAbstract = true;
							}
						}
						else
						{
							members.push_back(member);
						}
					}
				}

				// Move up the inheritance tree.
				scope = scope->SuperClass;
			}
		}

		// Throw errors if we do not implement all interface functions.	
		for (auto iter = Interfaces.begin(); iter != Interfaces.end(); iter++)
		{
			CClassASTNode* interfaceClass = *iter;
			for (auto iter2 = interfaceClass->Body->Children.begin(); iter2 != interfaceClass->Body->Children.end(); iter2++)
			{
				CClassMemberASTNode* member = dynamic_cast<CClassMemberASTNode*>(*iter2);
				if (member != NULL &&
					member->MemberType == MemberType::Method)
				{
					std::vector<CDataType*> argument_data_types;
					for (auto iter3 = member->Arguments.begin(); iter3 != member->Arguments.end(); iter3++)
					{
						CVariableStatementASTNode* arg = *iter3;
						argument_data_types.push_back(arg->Type);
					}

					if (FindClassMethod(semanter, member->Identifier, argument_data_types, true, NULL, this) == NULL)
					{
						semanter->GetContext()->FatalError(CStringHelper::FormatString("Class does not implement method '%s' of interface '%s'.", member->Identifier.c_str(), interfaceClass->Identifier.c_str()), Token);
					}
				}
			}
		}

		// Finalize children.
		FinalizeChildren(semanter);
	}

	// Finalize generic instances.
	else if (IsGeneric == true)
	{
		for (auto iter = GenericInstances.begin(); iter != GenericInstances.end(); iter++)
		{
			(*iter)->Finalize(semanter);
		}
	}

	return this;
}
Ejemplo n.º 8
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;
}