// ================================================================= // 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; }
// ================================================================= // 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; }
// ================================================================= // 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; } }
// ================================================================= // 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; }
// ================================================================= // 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; }