void Class::addMethod(std::string name, Type* t, std::vector<Argument*>* args, Stm* body, int method_state) { // Add this argument at the beginning of arg list if (!args) args = new std::vector<Argument*>(); // TODO Do not do this for static methods if (!(method_state == 1)) { args->insert(args->begin(), new Argument(new TypeClass(this), "this")); } TypeFunction* tf = new TypeFunction(t); tf->setVirtual(method_state == 2); tf->setClass(this); cy::Function* f = new cy::Function(tf, args, body); f->setOriginalName(name); this->methods->push_back(f); // Do specific operation tf->setStatic(false); f->setStatic(false); switch (method_state) { case 1: // Method is static tf->setStatic(true); f->setStatic(true); break; case 2: // Virtual method f->setVirtual(true); tf->setVirtual(true); this->setVTable(); // Set pointer to vtable attribute this->virtual_methods->push_back(f); break; case 3: // Overriden method tf->setOverridden(true); if (!this->getParent()) { throw __FILE__ "(" QUOTE(__LINE__) "): Method " + name + " is overridden, but no super class."; } std::vector<Type*>* types = new std::vector<Type*>(); std::vector<Argument*>::iterator itarg; for (itarg = args->begin(); itarg != args->end(); itarg++) { types->push_back((*itarg)->getType()); } // Verify method with same name and same types exists in if (!this->getParent()->getMethod(name, types)) { throw __FILE__ "(" QUOTE(__LINE__) "): Method " + name + " is overridden, but not in super class."; } delete types; break; } }
void VisitorNodeTyper::visit(ExprSymbol *n){ // TODO Set flag if global or local if (this->cur_class) { Type* t = this->cur_class->getAttrType(n->getName()); // Get type from class if (!t) // If no type returned, it might be an unmangled method name { if (this->look_for_mangled) { TypeFunction* tf = new TypeFunction(); tf->setClass(this->cur_class); tf->setName(n->getName()); t = tf; } else { throw __FILE__ "(" QUOTE(__LINE__) "): Attribute " + n->getName() + " not found in class" + this->cur_class->getName() + "."; } } n->setType(t); } else { Variable* v = this->symt->get(n->getName()); if (!v) // Symbol not found { if (this->look_for_mangled) // Look for an unmangled name { TypeFunction* tf = new TypeFunction(); tf->setName(n->getName()); tf->setStatic(true); tf->setVirtual(false); n->setType(tf); } else { throw __FILE__ "(" QUOTE(__LINE__) "): Variable " + n->getName() + " not found."; } } else { n->setType(v->getType()); } } }
void VisitorNodeTyper::visit(class ExprCall *n) { ExprSymbol* sym = dynamic_cast<ExprSymbol*>(n->getCallee()); TypeFunction* tf = 0; // If there are arguments, pass through them to find there types if (n->getArgs()) { for (std::vector<Expr*>::iterator it = n->getArgs()->begin(); it != n->getArgs()->end(); it++) { (*it)->accept(*this); } } // Set looking for mangled mode to avoid not in symbol table exception bool old_look_for_mangled = this->look_for_mangled; this->look_for_mangled = true; n->getCallee()->accept(*this); this->look_for_mangled = old_look_for_mangled; tf = dynamic_cast<TypeFunction*>(n->getCallee()->getType()); std::vector<Signature*>* ss = 0; Class* cur_class = 0; if (!tf->getClass()) { ss = this->sigs[tf->getName()]; } else { std::map<std::string, std::vector<Signature*>* >* spc; cur_class = tf->getClass(); while (cur_class != 0) { spc = this->sigs_per_class[cur_class]; if (spc) { ss = (*spc)[tf->getName()]; if (ss) { break; } } cur_class = cur_class->getParent(); } if (!spc) throw __FILE__ "(" QUOTE(__LINE__) "): No signature table for class " + tf->getClass()->getName() + "."; } // TODO optimize if (!ss) throw __FILE__ "(" QUOTE(__LINE__) "): Symbol " + tf->getName() + " not in signature tables."; // Select good function std::vector<Signature*>::iterator it; bool insert_this = false; std::vector<Type*>* choosen_sig = 0; for (it = ss->begin(); it != ss->end(); it++) { // Test for method if (areCompatible(n->getArgs(), (*it)->getTypes(), true)) { if (tf->getClass()) { tf = tf->getClass()->getMethodType((*it)->getMangledName()); n->getCallee()->setType(tf); } tf->setName((*it)->getMangledName()); if (choosen_sig) throw __FILE__ "(" QUOTE(__LINE__) "): Overloading ambiguity !"; tf->setStatic(false); choosen_sig = (*it)->getTypes(); // Function is non static, get left part of callee and add it on front of arg stack (this) insert_this = true; } // Test for function OR static method else if(areCompatible(n->getArgs(), (*it)->getTypes())) { if (tf->getClass()) { tf = tf->getClass()->getMethodType((*it)->getMangledName()); n->getCallee()->setType(tf); } tf->setName((*it)->getMangledName()); if (choosen_sig) throw __FILE__ "(" QUOTE(__LINE__) "): Overloading ambiguity !"; choosen_sig = (*it)->getTypes(); tf->setStatic(true); if (sym) { sym->setName((*it)->getMangledName()); } } } if (!choosen_sig) throw __FILE__ "(" QUOTE(__LINE__) "): No method " + tf->getName()+ " found."; if (insert_this) { ExprOP2* e2 = dynamic_cast<ExprOP2*>(n->getCallee()); if (!e2) throw __FILE__ "(" QUOTE(__LINE__) "): Callee must be OP2."; n->getArgs()->insert(n->getArgs()->begin(), e2->getLeft()); } // Set expected types to arguments (derived class to parent class) std::vector<Expr*>::iterator ite; std::vector<Type*>::iterator itt; itt = choosen_sig->begin(); for (ite = n->getArgs()->begin(); ite != n->getArgs()->end(); ite++, itt++) { (*ite)->setType(*itt); } if (sym) { n->getCallee()->accept(*this); tf = dynamic_cast<TypeFunction*>(n->getCallee()->getType()); if (!tf) throw __FILE__ "(" QUOTE(__LINE__) "): Callee value must be of type TypeFunction."; } else { tf->setType(tf->getClass()->getMethodReturnType(tf->getName())); } n->setType(tf->getType()); }