void SymbolCheckVisitor::visit(ASTFunction& ast) { ScopedScope scope(mScopeStack); ScopedValue<ASTFunction*> scopedfunction(&mpFunction, &ast, mpFunction); ASSERT_PTR(mpFunction); visitChildren(ast); // <-- arguments if ( ast.isConstructor() && ast.getName() != mpClass->getName() ) { error(E0005, UTEXT("Function ") + ast.getName() + UTEXT(" must have a return type (or equal class name as constructor)."), ast); } if ( ast.hasBody() ) { if ( ast.getModifiers().isAbstract() ) { error(E0006, UTEXT("Abstract function ") + ast.getName() + UTEXT(" should not have a body."), ast); } else { checkReturn(ast); ast.getBody().accept(*this); } } else if ( !ast.getModifiers().isAbstract() && !ast.getModifiers().isPureNative() ) { error(E0007, UTEXT("Function ") + ast.getName() + UTEXT(" requires a body."), ast); } mCurrentType.clear(); }
/// Read-Eval-Print-Loop static void repl(CEnv& cenv, ExecutionEngine* engine) { while (1) { std::cout << "> "; std::cout.flush(); SExp exp = readExpression(std::cin); try { AST* ast = parseExpression(exp); if (ast->evaluatable()) { ASTPrototype* proto = new ASTPrototype(false, "", vector<string>()); ASTFunction* func = new ASTFunction(proto, ast); Function* code = func->Funcgen(cenv); void* fp = engine->getPointerToFunction(code); double (*f)() = (double (*)())fp; std::cout << f() << endl; } else { Value* code = ast->Codegen(cenv); std::cout << "Generated code:" << endl; code->dump(); } } catch (SyntaxError e) { std::cerr << "Syntax error: " << e.what() << endl; } } }
void ASTFunctionTable::reindex(int base) { // skip the static and variable init blocks, as they are created in a later stage int resourceindex = base; for ( std::size_t index = 2; index < mFunctions.size(); ++index ) { ASTFunction* pfunction = mFunctions[index]; pfunction->setResourceIndex(resourceindex++); } }
void ResourceCheckVisitor::visit(ASTFunction& ast) { if ( !ast.getModifiers().isPureNative() && !ast.getModifiers().isAbstract() ) { mOffset = 0; ast.getBody().accept(*this); ast.setLocalVariableCount(mOffset - ast.getArguments().size()); } }
String DxBuilder::buildFunction(const ASTFunction& function) { String code; const ASTAnnotation* panno = function.findAnnotation(UTEXT("maxvertexcount")); if ( panno != NULL ) { code += UTEXT("[maxvertexcount({0})]").arg(0, panno->intvalue); } code += function.mpType->toDirectX() + ' ' + function.mName + '('; for ( std::size_t index = 0; index < function.mArguments.size(); ++index ) { const ASTFunctionArgument* parg = function.mArguments[index]; if ( index > 0 ) { code += UTEXT(", "); } else { const ASTAnnotation* panno = function.findAnnotation(UTEXT("inputtype")); if ( panno != NULL ) { code += panno->strvalue + L' '; } } if ( !parg->mpType->getTemplateClass().isEmpty() ) { // hack!! maybe we should support for pre-argument values like in, inout, out code += UTEXT("inout "); } code += parg->mpType->toDirectX() + ' ' + parg->mName; if ( parg->mArraySize > -1 ) { String conv; code += L'['; code += NumberConverter::getInstance().format(conv, parg->mArraySize) + L']'; } } code += ')'; if ( !function.mReturn.isEmpty() ) { code += UTEXT(" : ") + function.mReturn; } code += UTEXT("\n{") + function.mBody + UTEXT("}\n"); return code; }
void ASTNaryFunctionNode::reduceOperatorsToBinary() { unsigned int numChildren = getNumChildren(); /* number of children should be greater than 2 */ if (numChildren < 3) return; /* only work with times and plus */ int type = getType(); if (type != AST_TIMES && type != AST_PLUS) return; ASTFunction* op = new ASTFunction( getExtendedType() ); ASTFunction* op2 = new ASTFunction( getExtendedType() ); // add the first two children to the first node op->addChild(getChild(0)); op->addChild(getChild(1)); op2->addChild(op); for (unsigned int n = 2; n < numChildren; n++) { op2->addChild(getChild(n)); } swapChildren(op2); // valgrind says we are leaking a lot of memory here // but we cannot delete op2 since its children are the children of the // current element // neither addChild not swapChildren make copies of things // we could remove the children and delete the object // removeChild does not destroy the object // merely removes it from the mChildren vector unsigned int i = op2->getNumChildren(); while (i > 0) { op2->removeChild(i-1); i--; } delete op2; setReducedToBinary(true); reduceOperatorsToBinary(); }
void OOCheckVisitor::visit(ASTFunction& ast) { mpFunction = * ScopedScope scope(mScopeStack); ast.getArgumentNodes().accept(*this); if ( ast.hasAnnotations() ) { if ( ast.getAnnotations().contains(UTEXT("override")) ) { // check if the base class still has this function } } if ( ast.isConstructor() ) { // abstract classes can not have native constructors /* if ( ast.getModifiers().isNative() && mpClass->getModifiers().isAbstract() ) { mContext.getLog().error("Abstract class " + mpClass->getFullName() + " can not have native constructors."); } */ } else { if ( mpClass->hasBaseClass() ) { ASTClass& baseclass = mpClass->getBaseClass(); ASTFunction* pbasefunc = baseclass.findExactMatch(ast.getName(), ast.getSignature()); if ( pbasefunc != NULL ) { ast.setBaseFunction(*pbasefunc); } } } if ( ast.hasBody() ) { mHasNativeCall = false; ast.getBody().accept(*this); if ( mHasNativeCall ) { ast.getModifiers().setNative(true); } } }
void ASTFunctionTable::insert(ASTFunction& function) { for ( std::size_t index = 2; index < mFunctions.size(); index++ ) { ASTFunction* pfunction = mFunctions[index]; if ( pfunction->getName() == function.getName() && pfunction->getSignature().exactMatch(function.getSignature()) ) // for now do not allow derived types { mFunctions[index] = &function; return; } } mFunctions.push_back(&function); }
void ASTNaryFunctionNode::writeNodeOfType(XMLOutputStream& stream, int type, bool inChildNode) const { if (inChildNode == false) { stream.startElement("apply"); ASTBase::writeStartEndElement(stream); } unsigned int numChildren = getNumChildren(); { for (unsigned int i = 0; i < numChildren; i++) { if (ASTFunctionBase::getChild(i)->getType() == type) { ASTFunction* fun = dynamic_cast<ASTFunction*>(ASTFunctionBase::getChild(i)); if (fun != NULL) { fun->writeNodeOfType(stream, type, true); } else { ASTNode* newAST = dynamic_cast<ASTNode*>(ASTFunctionBase::getChild(i)); if (newAST != NULL) { newAST->writeNodeOfType(stream, type, true); } } } else { ASTFunctionBase::getChild(i)->write(stream); } } } if (inChildNode == false) { stream.endElement("apply"); } }
int ASTSemanticsNode::swapChildren(ASTFunction* that) { int success = LIBSBML_OPERATION_FAILED; // the original ast nodes did not have a type for semantics // so we actually want to swap the children of the child // of this sematics node // catch case when this node has no children if (getNumChildren() == 0 || getNumChildren() > 1) { return LIBSBML_INVALID_OBJECT; } if (getChild(0)->isFunctionNode() == false) { return LIBSBML_INVALID_OBJECT; } ASTNode * child0 = dynamic_cast<ASTNode*>(getChild(0)); if (child0 == NULL) { return LIBSBML_INVALID_OBJECT; } ASTFunction * childFunc = child0->getFunction(); ASTFunction * child = new ASTFunction(child0->getExtendedType()); child->syncMembersAndTypeFrom(childFunc, child0->getExtendedType()); success = child->swapChildren(that); if (success == LIBSBML_OPERATION_SUCCESS) { this->removeChild(0); this->addChild(child); } return success; }
void SymbolCheckVisitor::checkReturn(const ASTFunction& function) { checkUnknown(function.getType()); if ( !function.getType().isVoid() ) { // ensure that we have a return statement bool hasunreachablecode = false; if ( !function.getBody().hasReturn(hasunreachablecode) ) { error(E0045, UTEXT("Function ") + function.getName() + UTEXT(" should return a value of type ") + function.getType().toString(), function.getPosition()); } else if ( hasunreachablecode ) { warning(W0003, UTEXT("Unreachable code in ") + function.getName(), function.getPosition()); } } }
bool ASTNaryFunctionNode::read(XMLInputStream& stream, const std::string& reqd_prefix) { bool read = false; ASTBase * child = NULL; const XMLToken element = stream.peek (); ASTBase::checkPrefix(stream, reqd_prefix, element); const char* name = element.getName().c_str(); int type = getTypeFromName(name); setType(type); ASTBase::read(stream, reqd_prefix); unsigned int numChildrenAdded = 0; if (getExpectedNumChildren() > 0) { while (stream.isGood() && numChildrenAdded < getExpectedNumChildren()) { stream.skipText(); name = stream.peek().getName().c_str(); if (representsNumber(ASTBase::getTypeFromName(name)) == true) { child = new ASTNumber(); } else { child = new ASTFunction(); } read = child->read(stream, reqd_prefix); stream.skipText(); if (read == true && addChild(child) == LIBSBML_OPERATION_SUCCESS) { numChildrenAdded++; } else { delete child; child = NULL; read = false; break; } } } else { stream.skipPastEnd(element); read = true; } if (read == true && type == AST_FUNCTION_ROOT && getExpectedNumChildren() == 1 && ASTFunctionBase::getChild(0)->getType() != AST_QUALIFIER_DEGREE) { /* HACK TO REPLICATE OLD BEHAVIOUR */ /* we need to add the qualifier child for the degree 2 */ ASTFunction * degree = new ASTFunction(AST_QUALIFIER_DEGREE); ASTNumber * int2 = new ASTNumber(AST_INTEGER); int2->setInteger(2); degree->addChild(int2->deepCopy()); this->prependChild(degree->deepCopy()); delete int2; delete degree; } //if (read == false) //{ // stream.skipPastEnd(element); //} return read; }
bool ASTNaryFunctionNode::isSqrt() const { bool valid = false; if (getType() == AST_FUNCTION_ROOT) { // a sqrt can have either one child that is not the degree qualifier // or two where the first is the degree of 2 if (getNumChildren() == 1) { /* HACK to replicate OLD AST whic says a sqrt must have two children*/ valid = false; //ASTBase * base1 = getChild(0); //if (base1->isQualifier() == false) //{ // valid = true; //} } else if (getNumChildren() == 2) { ASTBase * base1 = ASTFunctionBase::getChild(0); ASTFunction* fun = dynamic_cast<ASTFunction*>(base1); if (fun != NULL) { if (fun->getType() == AST_QUALIFIER_DEGREE && fun->getNumChildren() == 1) { ASTBase *base2 = fun->getChild(0); if (base2->getType() == AST_INTEGER) { ASTNumber *child = static_cast<ASTNumber*>(base2); if (child->getInteger() == 2) { valid = true; } } } } else { // here we are working the ASTNode so the casting // is more difficult ASTNode* newAST = dynamic_cast<ASTNode*>(base1); if (newAST != NULL && newAST->getType() == AST_QUALIFIER_DEGREE && newAST->getNumChildren() == 1) { ASTNode* newAST1 = newAST->getChild(0); if (newAST1->getType() == AST_INTEGER) { if (newAST1->getInteger() == 2) { valid = true; } } } else { if (newAST != NULL && newAST->getType() == AST_INTEGER) { if (newAST->getInteger() == 2) { valid = true; } } } } } } return valid; }
bool ASTNaryFunctionNode::isLog10() const { bool valid = false; if (getType() == AST_FUNCTION_LOG) { // a log can have either one child that is not the logbase qualifier // or two where the first is the logbase of 10 if (getNumChildren() == 1) { ASTBase * base1 = ASTFunctionBase::getChild(0); if (base1->isQualifier() == false) { valid = true; } } else if (getNumChildren() == 2) { ASTBase * base1 = ASTFunctionBase::getChild(0); ASTFunction* fun = dynamic_cast<ASTFunction*>(base1); if (fun != NULL) { if (fun->getType() == AST_QUALIFIER_LOGBASE && fun->getNumChildren() == 1) { ASTBase *base2 = fun->getChild(0); if (base2->getType() == AST_INTEGER) { ASTNumber *child = static_cast<ASTNumber*>(base2); if (child->getInteger() == 10) { valid = true; } } } } else { // here we are working the ASTNode so the casting // is more difficult ASTNode* newAST = dynamic_cast<ASTNode*>(base1); if (newAST != NULL && newAST->getType() == AST_QUALIFIER_LOGBASE && newAST->getNumChildren() == 1 ) { ASTNode* newAST1 = newAST->getChild(0); if (newAST1->getType() == AST_INTEGER) { if (newAST1->getInteger() == 10) { valid = true; } } } else { if (newAST != NULL && newAST->getType() == AST_INTEGER) { if (newAST->getInteger() == 10) { valid = true; } } } } } } return valid; }
bool ASTBinaryFunctionNode::isSqrt() const { bool valid = false; ASTBase * base1 = NULL; if (getType() == AST_FUNCTION_ROOT) { if (getNumChildren() == 2) { base1 = getChild(0); ASTFunction* fun = dynamic_cast<ASTFunction*>(base1); if (fun != NULL) { if (fun->getType() == AST_QUALIFIER_DEGREE && fun->getNumChildren() == 1) { ASTBase *base2 = fun->getChild(0); if (base2->getType() == AST_INTEGER) { ASTNumber *child = static_cast<ASTNumber*>(base2); if (child->getInteger() == 2) { valid = true; } } } } else { // here we are working the ASTNode so the casting // is more difficult ASTNode* newAST = dynamic_cast<ASTNode*>(base1); if (newAST != NULL && newAST->getType() == AST_QUALIFIER_DEGREE && newAST->getNumChildren() == 1) { ASTNode* newAST1 = newAST->getChild(0); if (newAST1->getType() == AST_INTEGER) { if (newAST1->getInteger() == 2) { valid = true; } } } else { if (newAST != NULL && newAST->getType() == AST_INTEGER) { if (newAST->getInteger() == 2) { valid = true; } } } } } } return valid; }
void CodeGeneratorVisitor::visit(ASTFunction& ast) { CIL::Function* pfunction = new CIL::Function(); pfunction->setName(ast.getName()); pfunction->setReturnType(toCilType(ast.getType())); pfunction->setModifiers(toCilModifiers(ast.getModifiers())); // copy the arguments const ASTNodes& nodes = ast.getArgumentNodes(); for ( int index = 0; index < nodes.size(); ++index ) { const ASTFunctionArgument& arg = static_cast<const ASTFunctionArgument&>(nodes[index]); pfunction->addArgument(toCilType(arg.getVariable().getType())); } if ( ast.hasAnnotations() ) { const ASTAnnotations& annotations = ast.getAnnotations(); for ( int index = 0; index < annotations.size(); ++index ) { const ASTAnnotation& anno = annotations[index]; pfunction->addAnnotation(anno.mName); } } if ( !ast.getModifiers().isPureNative() ) { mCurrentType.clear(); if ( ast.hasBody() ) { mpFunction = * mBuilder.start(); ScopedScope scope(mScopeStack); const ASTBlock& block = ast.getBody(); block.accept(*this); mBuilder.end(); // set the generated content pfunction->setInstructions(mBuilder.getInstructions()); pfunction->setGuards(mBuilder.getGuards()); pfunction->setSwitchTables(mBuilder.getSwitchTables()); } // copy the locals const ASTTypeList& locals = ast.getLocals(); for ( int index = 0; index < locals.size(); ++index ) { const ASTType& local = locals[index]; yasc::Type* ptype = yasc::Type::fromString(local.toString()); pfunction->addLocal(ptype); } // clean up the code body to save memory ast.cleanup(); } mpClass->getCompiledClass().add(pfunction); }