int main(int argc, char** argv) {
	SgProject* proj = frontend(argc,argv);
	SgFunctionDeclaration* mainDecl = SageInterface::findMain(proj);
	SgFunctionDefinition* mainDef = mainDecl->get_definition();
	std::vector<SgNode*> ifExps;
	ifExps = NodeQuery::querySubTree(mainDef, V_SgIfStmt);
	for (int i = 0; i < ifExps.size(); i++) {
		getIfConds(isSgIfStmt(ifExps[i]), isSgScopeStatement(mainDef));
	}
	
	std::vector<SgNode*> assignNodes = NodeQuery::querySubTree(mainDef, V_SgVariableDeclaration);
	std::cout << assignNodes.size() << " nodes found" << std::endl;
	std::vector<SgBinaryOp*> bin_ops;
	std::vector<SgUnaryOp*> un_ops;
	std::vector<SgNode*> other;
	std::vector<SgExpression*> results;
	for (std::vector<SgNode*>::iterator i = assignNodes.begin(); i != assignNodes.end(); i++) {
	
		SgVariableDeclaration* vdecl = isSgVariableDeclaration(*i);
		SgInitializedNamePtrList vlst = vdecl->get_variables();
		SgInitializedName* initName = isSgInitializedName((*(vlst.begin())));
		SgExpression* exp = isSgAssignInitializer(initName->get_initializer())->get_operand();
		std::cout << exp->class_name() << std::endl;
		if (!isSgFunctionCallExp(exp)) {
			getExps(exp, isSgInitializedName(*i), results, 0);
		
	
	std::cout << "prefixes" << std::endl;
	for (int j = 0; j < prefixes.size(); j++) {
	        SgExprStatement* expSt = SageBuilder::buildExprStatement_nfi(prefixes[j]);
		SageInterface::insertStatement(isSgVariableDeclaration(*i),expSt,true);
		
		std::cout << prefixes[j]->class_name() << std::endl;
	}
	std::cout << "results" << std::endl;
	for (int j = 0; j < results.size(); j++) {
		std::cout << results[j]->class_name() << std::endl;
	}
	std::cout << "postfixes" << std::endl;
	for (int j = 0; j < postfixes.size(); j++) {
		SgExprStatement* expSt = SageBuilder::buildExprStatement_nfi(postfixes[j]);
                SageInterface::insertStatement(isSgVariableDeclaration(*i),expSt,false);
		std::cout << postfixes[j]->class_name() << std::endl;
	}
	
	replaceExps(exp,vdecl);
	simplifyExps(exp);
	}
		
	}
			
	backend(proj);
	return 0;
}
void getExps(SgExpression* exp, SgInitializedName* prevPost, std::vector<SgExpression*>& result, int tabcount) {
	
	if (isSgVarRefExp(exp)) {
		return;
	}
	else if (isSgUnaryOp(exp)) {
		if (isSgMinusMinusOp(exp) || isSgPlusPlusOp(exp)) {
			SgExpression* operand = (isSgUnaryOp(exp))->get_operand();
			
			bool prefix = (isSgUnaryOp(exp)->get_mode() == SgUnaryOp::prefix);
				if (prefix) {
					SgExpression* exp_cpy = SageInterface::copyExpression(exp);
					prefixes.push_back(exp_cpy);
				}
				else {
					SgExpression* exp_cpy = SageInterface::copyExpression(exp);
					postfixes.push_back(exp_cpy);
				}
			
			
		}
		
		return;
	}
	else if (isSgBinaryOp(exp)) {
		result.push_back(exp);
		getExps(isSgBinaryOp(exp)->get_lhs_operand(), prevPost, result,tabcount+1);
		getExps(isSgBinaryOp(exp)->get_rhs_operand(), prevPost, result,tabcount+1);
		return;
	}
	else {
		result.push_back(exp);
		return;
	}
	return;
}
llvm::Value* minipascal::NMethodCall::codeGen(CodeGenContext* context)
{
        std::cout << "Generating code for " << getOutput() << std::endl;
        llvm::Value* retvalue = specialMethodCall(context);
        if(retvalue == NULL)
        {
                CodeGenContext::BlockStack* stack = &(context->blockstack);
                CodeGenContext::BlockStack::reverse_iterator rit;
                SymbolTable::iterator it;
                for(rit = stack->rbegin(); rit != stack->rend(); ++rit)
                {
                        it = (*rit)->getLocals()->find(getName());
                        if(it != context->getCurBlock()->getLocals()->end())
                        {
                                setType(it->second->declaration->getType());
                                
                                llvm::Function* function = context->getModule()->getFunction(getName().c_str());
                                std::vector<llvm::Value*> args;
                                const minipascal::Exps_list* exps = getExps();
                                minipascal::Exps_list::const_iterator eit;
                                for(eit = exps->begin(); eit != exps->end(); ++eit)
                                {
                                        llvm::Value* arg = (*eit)->codeGen(context);
                                        if(arg == NULL) return NULL;
                                        args.push_back(arg);
                                }
                                
                                // args check
                                try{
                                        NMethodDeclaration* method = boost::polymorphic_cast<NMethodDeclaration*>(it->second->declaration);
                                        Decls_list* decls = method->getArgs();
                                        Decls_list::iterator dit;
                                        for(dit = decls->begin(), eit = exps->begin(); dit != decls->end() && eit != exps->end(); ++eit, ++dit)
                                        {
                                                if(!((*dit)->getType()->compare((*eit)->getType())))
                                                {
                                                        showError("Function " + getName() + " args doesn't match");
                                                        setFail(true);
                                                        context->fail = true;
                                                        return NULL;
                                                }
                                        }
                                        if(dit != decls->end())
                                        {
                                                showError("Function " + getName() + " args isn't enough");
                                                setFail(true);
                                                context->fail = true;
                                                return NULL;
                                        }
                                        if(eit != exps->end())
                                        {
                                                showError("Function " + getName() + " args is too many");
                                                setFail(true);
                                                context->fail = true;
                                                return NULL;
                                        }
                                        
                                }catch(std::bad_cast& e){
                                        showError("No such function : " + getName());
                                        setFail(true);
                                        context->fail = true;
                                        return NULL;
                                }
                                
                                return context->builder->CreateCall<>(function, args.begin(), args.end(), "");
                        }
                }
        }
        else
        {
                std::vector<llvm::Value*> args;
                const minipascal::Exps_list* exps = getExps();
                minipascal::Exps_list::const_iterator eit;
                for(eit = exps->begin(); eit != exps->end(); ++eit)
                {
                        llvm::Value* arg = (*eit)->codeGen(context);
                        if(arg == NULL) return NULL;
                        args.push_back(arg);
                }
                return context->builder->CreateCall<>(retvalue, args.begin(), args.end(), "");
        }
        
        showError("No such function : " + getName());
        setFail(true);
        context->fail = true;
        return NULL;
}