#include <antlr4-runtime.h>
#include <Public/Public.h>
#include "Public/TAC.h"
#include "GoParser.h"
#include "GoLexer.h"
#include "GoParserListener.h"
#include "GoParserBaseListener.h"
#include "ICG/GoTo3code.h"
#include "ICG/Utils.h"
#include "ICG/StmtICG/ForStmt.h"

using namespace std;

string GoTo3code::CreateLocalVar(){
	string Local;
	bool CheckResult = 0;
	do
	{
		Local = "T" + to_string(GoTo3code::LocalIndex);
		GoTo3code::LocalIndex++;
		shared_ptr<Symbol> tmp;
		if(currentScope->resolve(Local,tmp)==SUCCESS){
			CheckResult=1; // 临时变量与已经定义的变量重名
		}
		else{
			CheckResult=0;
		}
	}
	while(CheckResult);
	/* TODO: 判断tmp类型 */
	std::shared_ptr<Symbol> symbol= make_shared<Symbol>(Local,currentScope,Symbol::SymbolType::VAR,defineTmpType());
	GoTo3code::currentScope->para_define(symbol);
	return Local;
}

string GoTo3code::CreateElseLabel(){
	string Local;
	bool CheckResult = 0;
	Local = to_string(GoTo3code::IFIndex);
	GoTo3code::IFIndex++;
	return Local;
}

string GoTo3code::CreateForLabel(){
	string Local;
	bool CheckResult = 0;
	Local = to_string(GoTo3code::ForIndex);
	GoTo3code::ForIndex++;
	return Local;
}

string GoTo3code::ToString(TACOP num){
	switch (num)
	{
		case TACOP::ADD:    	return "ADD";
		case TACOP::SUB:    	return "SUB";
		case TACOP::DIV:    	return "DIV";
		case TACOP::MUL:   		return "MUL";
		case TACOP::ASSIGN: 	return "ASSIGN";
		case TACOP::CALL:    	return "CALL";
		case TACOP::PARA:    	return "PARA";
		case TACOP::RET:    	return "RET";
		case TACOP::ENDCALL:	return "ENDCALL";
		case TACOP::FUN_RET:	return "FUN_RET";
		case TACOP::FUN_PARA:	return "FUN_PARA";
		case TACOP::IFGE:		return "IFGE";
		case TACOP::IFLE:		return "IFLE";
		case TACOP::IFGT:		return "IFGT";
		case TACOP::IFLT:		return "IFLT";
		case TACOP::IFEQ:		return "IFEQ";
		case TACOP::IFNEQ:		return "IFNEQ";
		case TACOP::GOTO:		return "GOTO";
		case TACOP::LABEL: 		return "LABEL";
		case TACOP::CREATLIST: 		return "CREATLIST";
		default: 				return "";
	}
}

string GoTo3code::ToString(TACOPERANDTYPE num){
	switch (num)
	{
		case TACOPERANDTYPE::VAR:      	return "VAR";
		case TACOPERANDTYPE::NULL_:    	return "NULL_";
		case TACOPERANDTYPE::IMM: 	   	return "IMM";
		case TACOPERANDTYPE::PTR: 	   	return "PTR";
		case TACOPERANDTYPE::LABEL:		return "LABEL";
		default:  						return "----";
	}
}

TACOPERANDTYPE GoTo3code::OperandTypereslove(string name){
	if(ptrs[name]==1){
		return TACOPERANDTYPE::PTR;
	}
	if((name[0] >= '0' && name[0] <= '9') || name[0] == '-')
	{
		return TACOPERANDTYPE::IMM;
	}
	return TACOPERANDTYPE::VAR;
}

bool GoTo3code::is_digit(string s){
	if(s[0]=='-') s=s.substr(1,s.size()-1);
	for(auto c:s){
		if((c>= '0' && c<= '9')) continue;
		else return false;
	}
	return true;
}

void GoTo3code::Go23file(string filename){
	ofstream outfile;
	outfile.open(filename, ios::out);
	outfile.clear();

	for(auto p : TACBlocks)
	{
		auto block=p.second;
		for(auto it: *block){

			outfile << setw(4) <<it.line << " Operater: " << setw(10) <<ToString(it.op) << " src1: " <<  setw(7) <<ToString(it.src1.OperType) + ":" << setw(7) <<it.src1.value << "      src2:" <<  setw(7) <<ToString(it.src2.OperType) + ":" << setw(7) <<it.src2.value << "      dst: " <<  setw(7) <<ToString(it.dst.OperType) + ":" << setw(7) <<it.dst.value << endl;
		}
		outfile<<"----------------------\n";

	}
	outfile.close();
}

void GoTo3code::Go23file_(string filename){
	ofstream outfile;
	outfile.open(filename, ios::out);
	outfile.clear();

	for(auto p : TACBlocks)
	{
		auto block=p.second;
		for(auto it: *block){

			outfile <<it.line << "\t"  <<ToString(it.op) << "\t"  <<it.src1.value << "\t" <<it.src2.value  << "\t" <<it.dst.value<< "\t"  << endl;
		}
		outfile<<"----------------------\n";

	}
	outfile.close();
}

// 第一个参数，改成函数名字
void GoTo3code::push_line(TACOP op, Operand src1, Operand src2, Operand dst){
	TACBlocks[curFun]->push_back(TACLine(GoTo3code::LineIndex, op, src1, src2, dst, currentScope));
	GoTo3code::LineIndex ++;
}

void GoTo3code::myPrint(std::shared_ptr<Scope> currentScope){
    for(auto it:currentScope->para_symbols) {
		LOG(INFO) << "para_symbol: " << it.first;
    }
    for(auto it:currentScope->fun_symbols) {
		LOG(INFO) << "fun_symbol: " << it.first;
    }
}

void GoTo3code::addScope(){
	std::shared_ptr<Scope> scope(new Scope(currentScope));
	// scopes.put(ctx,scope);
	allScopes.push_back(scope);
	currentScope=scope;
}

void GoTo3code::popScope(){
    myPrint(currentScope);
    currentScope=currentScope->enclosing_scope;
}

void GoTo3code::exitPackageClause(GoParser::PackageClauseContext *ctx)
{

}
void GoTo3code::enterPackageClause(GoParser::PackageClauseContext *ctx){}


void GoTo3code::enterInteger(GoParser::IntegerContext *ctx){}
void GoTo3code::exitInteger(GoParser::IntegerContext *ctx){
	values->put(ctx,ctx->DECIMAL_LIT()->getText());
}


void GoTo3code::enterBasicLit(GoParser::BasicLitContext *ctx){}
void GoTo3code::exitBasicLit(GoParser::BasicLitContext *ctx){
	if (ctx->integer()){
		// string dst = CreateLocalVar();
		string BasicLitValue = values->get(ctx->integer());
		// push_line(TACOP::ASSIGN, Operand(BasicLitValue,TACOPERANDTYPE::IMM),Operand("",TACOPERANDTYPE::NULL_), Operand(dst,TACOPERANDTYPE::VAR));
		// values->put(ctx, dst);
		values->put(ctx, BasicLitValue);
	}
}


void GoTo3code::enterOperand(GoParser::OperandContext *ctx){}
void GoTo3code::exitOperand(GoParser::OperandContext *ctx){
	if (ctx->literal()){
		string OperandValue = values->get(ctx->literal());
		values->put(ctx, OperandValue);
	}
	if (ctx->expression()){
		string OperandValue = values->get(ctx->expression());
		values->put(ctx, OperandValue);
	}
	if (ctx->operandName()){
		string OperandValue = values->get(ctx->operandName());
		values->put(ctx, OperandValue);
	}
}

void GoTo3code::enterLiteral(GoParser::LiteralContext *ctx){

}
void GoTo3code::exitLiteral(GoParser::LiteralContext *ctx){
	if (ctx->basicLit()){
		string LiteralValue = values->get(ctx->basicLit());

		values->put(ctx, LiteralValue+DELIMITER);
	}
}

void GoTo3code::enterPrimaryExpr(GoParser::PrimaryExprContext *ctx){}
void GoTo3code::exitPrimaryExpr(GoParser::PrimaryExprContext *ctx){

	/* 是函数调用 */
	if(ctx->arguments()){
		vector<string> primaryExpr_value;

		/*看是否定义*/
		shared_ptr<vector<string>> fun_identity;
		fun_identity=ctx_decoder(values->get(ctx->primaryExpr()));
		string identity=(*fun_identity)[0];
		std::shared_ptr<Symbol> fun_symbol;
		if(currentScope->resolve(identity,fun_symbol)==FAIL){
			LOG(FATAL) << "Undefined function: " << identity;
			cout << "Undefined function: " << identity<<endl;
			exit(-1);
		}
		/*找到了函数*/
		std::shared_ptr<vector<string>> arguments_values=ctx_decoder(values->get(ctx->arguments()));
		/*判断参数数量合理*/

		if(fun_symbol->fun_para_type_list->size()!=arguments_values->size()){
			LOG(FATAL) << "Undefined function: " << identity;
			cout<<"Wrong parameter number for : "<<identity<<endl;
			exit(-1);
		}

		/*函数调用*/
		string blank="";
		for(auto ret: *fun_symbol->fun_ret_type_list){
			// TODO:CreateLocalVar应当传入不同变量的type
			string tmp=CreateLocalVar();
			push_line (TACOP::RET, Operand(tmp, OperandTypereslove(tmp)), Operand(blank, TACOPERANDTYPE::NULL_), Operand(blank, TACOPERANDTYPE::NULL_));
			primaryExpr_value.push_back(tmp);
		}
		for(auto para: *arguments_values){
			push_line (TACOP::PARA, Operand(para, OperandTypereslove(para)), Operand(blank, TACOPERANDTYPE::NULL_), Operand(blank, TACOPERANDTYPE::NULL_));
		}
		push_line (TACOP::CALL, Operand(identity, OperandTypereslove(identity)), Operand(blank, TACOPERANDTYPE::NULL_), Operand(blank, TACOPERANDTYPE::NULL_));
		values->put(ctx, ctx_encoder(primaryExpr_value));

	}
	/*数*/
	else if (ctx->operand()){

		string PrimaryExprValue = values->get(ctx->operand());
		values->put(ctx, PrimaryExprValue);
	}
	/* 数组 */
	else if(ctx->index()){
		shared_ptr<vector<string>> array_name;
		array_name=ctx_decoder(values->get(ctx->primaryExpr()));
		string identity=(*array_name)[0];

		// 名字不是数组而是变量
		std::shared_ptr<Symbol> array_symbol;
		currentScope->resolve(identity,array_symbol);
		// cout<<"0000 "<<array_symbol->name<<endl;
		// cout<<"1111 "<<array_symbol->array_length<<endl;
		// cout<<"2222 "<<array_symbol->is_array<<endl;
		if(!array_symbol->is_array){
			LOG(FATAL) << "Only array can be indexed: " << identity;
			cout << "Only array can be indexed: " << identity<<endl;
			exit(-1);
		}


		shared_ptr<vector<string>> array_index;
		array_index=ctx_decoder(values->get(ctx->index()->expression()));
		string index_s=(*array_index)[0];
		if( 1 !=array_index->size()){
			LOG(FATAL) << "wrong number of array index input";
			cout<<"wrong number of array index input"<<endl;
			exit(-1);
		}

		// 若编译时可判断数组越界
		if(is_digit(index_s)){
			int idx = std::stoi(index_s);
			if(idx > array_symbol->array_length-1 || idx<0){
				LOG(FATAL) << "Array index out of bound: " << identity;
				cout << "Array index out of bound: " << identity<<endl;
				cout<<idx<<' '<<array_symbol->array_length<<endl;
				exit(-1);
			}
		}

		string tmp_ptr_offset = CreateLocalVar();
		string int_size="4";
		push_line (TACOP::MUL,
				   Operand(int_size, OperandTypereslove(int_size)),
				   Operand(index_s, OperandTypereslove(index_s)),
				   Operand(tmp_ptr_offset, OperandTypereslove(tmp_ptr_offset))
		);
		string tmp_ptr = CreateLocalVar();
		push_line (TACOP::ADD,
				   Operand(identity,OperandTypereslove(identity)),
				   Operand(tmp_ptr_offset, OperandTypereslove(tmp_ptr_offset)),
				   Operand(tmp_ptr, OperandTypereslove(tmp_ptr))
		);
		//todo map
		ptrs[tmp_ptr]=1;

		values->put(ctx, tmp_ptr);
	}

}

void GoTo3code::enterExpression(GoParser::ExpressionContext *ctx){}
void GoTo3code::exitExpression(GoParser::ExpressionContext *ctx){
}

void GoTo3code::enterUnaryOperation(GoParser::UnaryOperationContext *ctx){}
void GoTo3code::exitUnaryOperation(GoParser::UnaryOperationContext *ctx){

}

void GoTo3code::enterPrimaryExpression(GoParser::PrimaryExpressionContext *ctx){}
void GoTo3code::exitPrimaryExpression(GoParser::PrimaryExpressionContext *ctx){
	string ExpresionValue = values->get(ctx->primaryExpr());
	values->put(ctx, ExpresionValue);
}

void GoTo3code::enterPlusMinusOperation(GoParser::PlusMinusOperationContext *ctx){}
void GoTo3code::exitPlusMinusOperation(GoParser::PlusMinusOperationContext *ctx){
	std::shared_ptr<vector<string>> left=ctx_decoder(values->get(ctx->expression(0)));
	std::shared_ptr<vector<string>> right=ctx_decoder(values->get(ctx->expression(1)));
	/*判断value是否只有一个*/
	if(left->size()!=1 || right->size()!=1){
		LOG(FATAL) << "wrong literal number1";
		cout<<"wrong literal number1"<<endl;
		exit(-1);
	}
	string dst = CreateLocalVar();
	vector<string> plusMinusOperation_values;
	plusMinusOperation_values.push_back(dst);

	if(ctx->PLUS())
	{
		push_line (TACOP::ADD, Operand((*left)[0], OperandTypereslove((*left)[0])),  Operand((*right)[0], OperandTypereslove((*right)[0])), Operand(dst, OperandTypereslove(dst)));
	}
	else if(ctx->MINUS())
	{
		push_line (TACOP::SUB, Operand((*left)[0], OperandTypereslove((*left)[0])),  Operand((*right)[0], OperandTypereslove((*right)[0])), Operand(dst, OperandTypereslove(dst)));
	}
	values->put(ctx, ctx_encoder(plusMinusOperation_values));
}

void GoTo3code::enterRelationOperation(GoParser::RelationOperationContext *ctx){}
void GoTo3code::exitRelationOperation(GoParser::RelationOperationContext *ctx){
	std::shared_ptr<vector<string>> left=ctx_decoder(values->get(ctx->expression(0)));
	std::shared_ptr<vector<string>> right=ctx_decoder(values->get(ctx->expression(1)));
	if(left->size()!=1 || right->size()!=1){
		LOG(FATAL) << "wrong literal number1";
		cout<<"wrong literal number1"<<endl;
		exit(-1);
	}
	// vector<string> plusMinusOperation_values;
	// plusMinusOperation_values.push_back(dst);

	// expression 在for 下的情况，需要添加ifexp 并且反过来 将condition_loop信息写入forstatement里面
	if(ctx->parent->parent->children[0]->getText() == "for" && ctx->parent->parent->children[1] == ctx->parent)
	{
		std::string dst,dst_;
		ForStmt tmp = forvalues->get(ctx->parent->parent);
		dst = "ENDFOR" + tmp.CurIndex;
		dst_ = "FORLOOP" + tmp.CurIndex;
		TACLine tmpline;
		if(ctx->EQUALS())
		{
			tmpline = TACLine(GoTo3code::LineIndex, TACOP::IFEQ, Operand((*left)[0], OperandTypereslove((*left)[0])), Operand((*right)[0], OperandTypereslove((*right)[0])), Operand(dst_, TACOPERANDTYPE::LABEL), currentScope);

			push_line (TACOP::IFNEQ, Operand((*left)[0], OperandTypereslove((*left)[0])),  Operand((*right)[0], OperandTypereslove((*right)[0])), Operand(dst, TACOPERANDTYPE::LABEL));
		}
		else if(ctx->NOT_EQUALS())
		{
			tmpline = TACLine(GoTo3code::LineIndex, TACOP::IFNEQ, Operand((*left)[0], OperandTypereslove((*left)[0])), Operand((*right)[0], OperandTypereslove((*right)[0])), Operand(dst_, TACOPERANDTYPE::LABEL), currentScope);

			push_line (TACOP::IFEQ, Operand((*left)[0], OperandTypereslove((*left)[0])),  Operand((*right)[0], OperandTypereslove((*right)[0])), Operand(dst, TACOPERANDTYPE::LABEL));
		}
		else if(ctx->GREATER())
		{
			tmpline = TACLine(GoTo3code::LineIndex, TACOP::IFGT, Operand((*left)[0], OperandTypereslove((*left)[0])), Operand((*right)[0], OperandTypereslove((*right)[0])), Operand(dst_, TACOPERANDTYPE::LABEL), currentScope);

			push_line (TACOP::IFLE, Operand((*left)[0], OperandTypereslove((*left)[0])),  Operand((*right)[0], OperandTypereslove((*right)[0])), Operand(dst, TACOPERANDTYPE::LABEL));
		}
		else if(ctx->GREATER_OR_EQUALS())
		{
			tmpline = TACLine(GoTo3code::LineIndex, TACOP::IFGE, Operand((*left)[0], OperandTypereslove((*left)[0])), Operand((*right)[0], OperandTypereslove((*right)[0])), Operand(dst_, TACOPERANDTYPE::LABEL), currentScope);

			push_line (TACOP::IFLT, Operand((*left)[0], OperandTypereslove((*left)[0])),  Operand((*right)[0], OperandTypereslove((*right)[0])), Operand(dst, TACOPERANDTYPE::LABEL));
		}
		else if(ctx->LESS())
		{
			tmpline = TACLine(GoTo3code::LineIndex, TACOP::IFLT, Operand((*left)[0], OperandTypereslove((*left)[0])), Operand((*right)[0], OperandTypereslove((*right)[0])), Operand(dst_, TACOPERANDTYPE::LABEL), currentScope);

			push_line (TACOP::IFGE, Operand((*left)[0], OperandTypereslove((*left)[0])),  Operand((*right)[0], OperandTypereslove((*right)[0])), Operand(dst, TACOPERANDTYPE::LABEL));
		}
		else if(ctx->LESS_OR_EQUALS())
		{
			tmpline = TACLine(GoTo3code::LineIndex, TACOP::IFLE, Operand((*left)[0], OperandTypereslove((*left)[0])), Operand((*right)[0], OperandTypereslove((*right)[0])), Operand(dst_, TACOPERANDTYPE::LABEL), currentScope);

			push_line (TACOP::IFGT, Operand((*left)[0], OperandTypereslove((*left)[0])),  Operand((*right)[0], OperandTypereslove((*right)[0])), Operand(dst, TACOPERANDTYPE::LABEL));
		}
		tmp.LoopCon = tmpline;
		forvalues->put(ctx->parent->parent, tmp);
	}

	// expression 在if 下的情况，需要添加ifexp 并且反过来
	if(ctx->parent->getText().find("if") == 0 && ctx == ctx->parent->children[1])
	{
		std::string dst;
		if(ctx->parent->getText().find("else") != -1)//有else，就goto else
		{
			dst = "ELSE" + ifvalues->get(ctx->parent);
		}
		else
		{
			dst = "ENDIF" + ifvalues->get(ctx->parent);
		}

		if(ctx->EQUALS())
		{
			push_line (TACOP::IFNEQ, Operand((*left)[0], OperandTypereslove((*left)[0])),  Operand((*right)[0], OperandTypereslove((*right)[0])), Operand(dst, TACOPERANDTYPE::LABEL));
		}
		else if(ctx->NOT_EQUALS())
		{
			push_line (TACOP::IFEQ, Operand((*left)[0], OperandTypereslove((*left)[0])),  Operand((*right)[0], OperandTypereslove((*right)[0])), Operand(dst, TACOPERANDTYPE::LABEL));
		}
		else if(ctx->GREATER())
		{
			push_line (TACOP::IFLE, Operand((*left)[0], OperandTypereslove((*left)[0])),  Operand((*right)[0], OperandTypereslove((*right)[0])), Operand(dst, TACOPERANDTYPE::LABEL));
		}
		else if(ctx->GREATER_OR_EQUALS())
		{
			push_line (TACOP::IFLT, Operand((*left)[0], OperandTypereslove((*left)[0])),  Operand((*right)[0], OperandTypereslove((*right)[0])), Operand(dst, TACOPERANDTYPE::LABEL));
		}
		else if(ctx->LESS())
		{
			push_line (TACOP::IFGE, Operand((*left)[0], OperandTypereslove((*left)[0])),  Operand((*right)[0], OperandTypereslove((*right)[0])), Operand(dst, TACOPERANDTYPE::LABEL));
		}
		else if(ctx->LESS_OR_EQUALS())
		{
			push_line (TACOP::IFGT, Operand((*left)[0], OperandTypereslove((*left)[0])),  Operand((*right)[0], OperandTypereslove((*right)[0])), Operand(dst, TACOPERANDTYPE::LABEL));
		}
		// values->put(ctx, ctx_encoder(plusMinusOperation_values));

		// push_line (TACOP::IFEXP, Operand(dst, OperandTypereslove(dst)), Operand("",TACOPERANDTYPE::NULL_), Operand("",TACOPERANDTYPE::NULL_));


	}

}

void GoTo3code::enterMulDivOperation(GoParser::MulDivOperationContext *ctx){}
void GoTo3code::exitMulDivOperation(GoParser::MulDivOperationContext *ctx){
	std::shared_ptr<vector<string>> left=ctx_decoder(values->get(ctx->expression(0)));
	std::shared_ptr<vector<string>> right=ctx_decoder(values->get(ctx->expression(1)));
	/*判断value是否只有一个*/

	if(left->size()!=1 || right->size()!=1){
		LOG(FATAL) << "wrong literal number2";
		cout<<"wrong literal number2"<<endl;
		exit(-1);
	}
	string dst = CreateLocalVar();
	vector<string> mulDivOperation_values;
	mulDivOperation_values.push_back(dst);

	if(ctx->STAR())
	{
		push_line (TACOP::MUL, Operand((*left)[0], OperandTypereslove((*left)[0])),  Operand((*right)[0], OperandTypereslove((*right)[0])), Operand(dst, OperandTypereslove(dst)));
	}
	else if(ctx->DIV())
	{
		push_line (TACOP::DIV, Operand((*left)[0], OperandTypereslove((*left)[0])),  Operand((*right)[0], OperandTypereslove((*right)[0])), Operand(dst, OperandTypereslove(dst)));
	}
	values->put(ctx, ctx_encoder(mulDivOperation_values));

}

void GoTo3code::enterLogicalOrOperation(GoParser::LogicalOrOperationContext *ctx){}
void GoTo3code::exitLogicalOrOperation(GoParser::LogicalOrOperationContext *ctx){

}

void GoTo3code::enterLogicalAndOperation(GoParser::LogicalAndOperationContext *ctx){}
void GoTo3code::exitLogicalAndOperation(GoParser::LogicalAndOperationContext *ctx){

}



void GoTo3code::enterSourceFile(GoParser::SourceFileContext *ctx){
	globalScope=make_shared<Scope>();
	currentScope = globalScope;
	std::shared_ptr<TACBlock> currentBlock=make_shared<TACBlock>();
	TACBlocks[curFun]=currentBlock;
}

void GoTo3code::exitSourceFile(GoParser::SourceFileContext *ctx){
	cout<<"exit source file"<<endl;
}

void GoTo3code::enterImportDecl(GoParser::ImportDeclContext *ctx){}
void GoTo3code::exitImportDecl(GoParser::ImportDeclContext *ctx){}

void GoTo3code::enterImportSpec(GoParser::ImportSpecContext *ctx){}
void GoTo3code::exitImportSpec(GoParser::ImportSpecContext *ctx){}

void GoTo3code::enterImportPath(GoParser::ImportPathContext *ctx){}
void GoTo3code::exitImportPath(GoParser::ImportPathContext *ctx){}

void GoTo3code::enterDeclaration(GoParser::DeclarationContext *ctx){}
void GoTo3code::exitDeclaration(GoParser::DeclarationContext *ctx){}

void GoTo3code::enterConstDecl(GoParser::ConstDeclContext *ctx){}
void GoTo3code::exitConstDecl(GoParser::ConstDeclContext *ctx){}

void GoTo3code::enterConstSpec(GoParser::ConstSpecContext *ctx){}
void GoTo3code::exitConstSpec(GoParser::ConstSpecContext *ctx){}

void GoTo3code::enterIdentifierList(GoParser::IdentifierListContext *ctx){}
void GoTo3code::exitIdentifierList(GoParser::IdentifierListContext *ctx){}

void GoTo3code::enterExpressionList(GoParser::ExpressionListContext *ctx){}
void GoTo3code::exitExpressionList(GoParser::ExpressionListContext *ctx){
	vector<string> expression_values;
	for(int i=0;i<ctx->expression().size();++i){
		string s=values->get(ctx->expression(i));
		std::shared_ptr<vector<string>> vs=ctx_decoder(s);
		for(auto each: *vs){
			expression_values.push_back(each);
		}
	}
	values->put(ctx,ctx_encoder(expression_values));
}

void GoTo3code::enterTypeDecl(GoParser::TypeDeclContext *ctx){}
void GoTo3code::exitTypeDecl(GoParser::TypeDeclContext *ctx){}

void GoTo3code::enterTypeSpec(GoParser::TypeSpecContext *ctx){}
void GoTo3code::exitTypeSpec(GoParser::TypeSpecContext *ctx){}

void GoTo3code::enterFunctionDecl(GoParser::FunctionDeclContext *ctx){

	string identifier=ctx->IDENTIFIER()->getText();
	/*判断是否函数名字重复*/
	if(currentScope->cur_resolve(identifier)==SUCCESS){
		LOG(FATAL) <<"Redeclaration of funciton:"<<identifier;
		cout<<"Redeclaration of funciton:"<<identifier<<endl;
		exit(-1);
	}

	/* 更改目前的function */
	curFun=identifier;
	std::shared_ptr<TACBlock> currentBlock=make_shared<TACBlock>();
	TACBlocks[curFun]=currentBlock;

	/* 构建fun symbol */
	std::shared_ptr<vector<Symbol::Type>> funRetTypeList=make_shared<vector<Symbol::Type>>();
	std::shared_ptr<vector<Symbol::Type>> funParaList=make_shared<vector<Symbol::Type>>();
	/*函数ret参数*/
	if(!ctx->signature()->result() || ctx->signature()->result()->parameters()->parameterDecl().size()==0){ // 无返回值
		// do nothing
	}
	else{  // 有返回值
		int n=ctx->signature()->result()->parameters()->parameterDecl().size();
		for(int i=0;i<n;++i){
			string eachType=ctx->signature()->result()->parameters()->parameterDecl(i)->type_()->typeName()->getText();
			Symbol::Type eachSType=Symbol::toType(eachType);
			funRetTypeList->push_back(eachSType);
		}
	}

	/*函数para参数*/
	//无参数
	if(ctx->signature()->parameters()->parameterDecl().size()==0){
		// do nothing
	}
	else{ //有参数
		int n=ctx->signature()->parameters()->parameterDecl().size();
		for(int i=0;i<n;++i){
			string eachType=ctx->signature()->parameters()->parameterDecl(i)->type_()->typeName()->getText();
			Symbol::Type eachSType=Symbol::toType(eachType);
			for(int j=0;j<ctx->signature()->parameters()->parameterDecl(i)->identifierList()->IDENTIFIER().size();++j){
				funParaList->push_back(eachSType);
			}
		}
	}

	std::shared_ptr<Symbol> symbol= make_shared<Symbol>(identifier,currentScope,Symbol::SymbolType::FUN,funRetTypeList, funParaList);
	std::shared_ptr<Scope> scope=make_shared<Scope>(currentScope);
	GoTo3code::currentScope->fun_define(symbol);
	currentScope=scope;

	/*打印 FUN_PARA*/
	for(int i=0;i<ctx->signature()->parameters()->parameterDecl().size();++i){
		// int n=ctx->signature()->parameters()->parameterDecl()->identifierList()->IDENTIFIER().size();
		int para_number=ctx->signature()->parameters()->parameterDecl(i)->identifierList()->IDENTIFIER().size();
		for(int j=0;j<para_number;++j){
			std::string fun_para = ctx->signature()->parameters()->parameterDecl(i)->identifierList()->IDENTIFIER(j)->getText();
			push_line (TACOP::FUN_PARA, Operand(fun_para, OperandTypereslove(fun_para)), Operand("", TACOPERANDTYPE::NULL_), Operand("", TACOPERANDTYPE::NULL_));
		}
	}

}
void GoTo3code::exitFunctionDecl(GoParser::FunctionDeclContext *ctx){
	curFun="global";
	popScope();
}

void GoTo3code::enterMethodDecl(GoParser::MethodDeclContext *ctx){}
void GoTo3code::exitMethodDecl(GoParser::MethodDeclContext *ctx){}

void GoTo3code::enterReceiver(GoParser::ReceiverContext *ctx){}
void GoTo3code::exitReceiver(GoParser::ReceiverContext *ctx){}

void GoTo3code::enterVarDecl(GoParser::VarDeclContext *ctx){}
void GoTo3code::exitVarDecl(GoParser::VarDeclContext *ctx){}

void GoTo3code::enterVarSpec(GoParser::VarSpecContext *ctx){

}
void GoTo3code::exitVarSpec(GoParser::VarSpecContext *ctx){
	/*是否是数组*/
	bool is_array=0;
	int array_length=0;
	/*如果是数组*/
	if(ctx->type_() && ctx->type_()->typeLit()){
		is_array=1;
		/*如果是数组，长度是多少*/
		shared_ptr<vector<string>> right_values;
		right_values=ctx_decoder(values->get(ctx->type_()->typeLit()->arrayType()->arrayLength()->expression()));
		// 数量是否是1
		if( 1 !=right_values->size()){
			LOG(FATAL)<<"wrong number of array length input";
			cout<<"wrong number of array length input"<<endl;
			exit(-1);
		}
		string array_length_s=(*right_values)[0];

		if(is_digit(array_length_s)){
			array_length=std::stoi(array_length_s);
			// 数组长度不为负数
			if(array_length<1){
				LOG(FATAL)<<"array length should >=1";
				cout<<"array length should >=1"<<endl;
				exit(-1);
			}
		}
		else{
			LOG(FATAL)<<"array decleration need static capacity";
			cout<<"array decleration need static capacity"<<endl;
			exit(-1);
		}
	}

	int n = ctx->identifierList()->IDENTIFIER().size();
	for(int i=0;i<n;++i){
		string varname = ctx->identifierList()->IDENTIFIER(i)->getText();
		Symbol::Type type;
		if(!ctx->type_()){
			type=defineTmpType();
		}
		else{
			/* 变量 */
			if(ctx->type_()->typeName()){
				string stype = ctx->type_()->typeName()->getText();
				type = Symbol::toType(stype);
			}
			/* 数组 */
			else if(ctx->type_()->typeLit() && ctx->type_()->typeLit()->arrayType()){
				string stype = ctx->type_()->typeLit()->arrayType()->elementType()->getText();
				type = Symbol::toType(stype);
			}

		}

		/*如果已经定义了，报错*/
		if(currentScope->cur_resolve(varname)){
			LOG(FATAL)<<"Redeclaration of parameter:"<<varname;
			cout<<"Redeclaration of parameter:"<<varname<<endl;
			exit(-1);
		}
		/*不重复，新建*/
		std::shared_ptr<Symbol> symbol=make_shared<Symbol>(varname,currentScope,Symbol::SymbolType::VAR,type,is_array,array_length);
		if(is_array){
			push_line (TACOP::CREATLIST, Operand(varname, OperandTypereslove(varname)), Operand(std::to_string(array_length), OperandTypereslove(std::to_string(array_length))), Operand("INT", TACOPERANDTYPE::NULL_));
		}
		GoTo3code::currentScope->para_define(symbol);
	}

	/*定义时赋值*/
	// 仅仅有变量
	if(ctx->expressionList()){
		shared_ptr<vector<string>> right_values;
		right_values=ctx_decoder(values->get(ctx->expressionList()));
		/*数量是否匹配*/
		if(n!=right_values->size()){
			LOG(FATAL)<<"wrong number matched";
			cout<<"wrong number matched"<<endl;
			exit(-1);
		}
		/*赋值*/
		for(int i=0;i<n;++i){
			push_line(TACOP::ASSIGN, Operand((*right_values)[i], OperandTypereslove((*right_values)[i])),Operand("", TACOPERANDTYPE::NULL_),Operand(ctx->identifierList()->IDENTIFIER(i)->getText(), OperandTypereslove(ctx->identifierList()->IDENTIFIER(i)->getText())));
		}
	}
	// TODO:数组compositeLit


}

void GoTo3code::enterBlock(GoParser::BlockContext *ctx){
	//for 情况
	if(ctx->parent->children[0]->getText() == "for")
	{
		push_line(TACOP::LABEL,Operand("FORLOOP" + forvalues->get(ctx->parent).CurIndex, TACOPERANDTYPE::LABEL),Operand("", TACOPERANDTYPE::NULL_),Operand("", TACOPERANDTYPE::NULL_));
	}
	//if else 情况
	if (ctx->parent->children[4] == ctx && ctx->parent->children[3]->getText() == "else"){
		push_line(TACOP::LABEL,Operand("ELSE" + ifvalues->get(ctx->parent), TACOPERANDTYPE::LABEL),Operand("", TACOPERANDTYPE::NULL_),Operand("", TACOPERANDTYPE::NULL_));
	}
	addScope();

}
void GoTo3code::exitBlock(GoParser::BlockContext *ctx){
	//for 情况
	if(ctx->parent->children[0]->getText() == "for")
	{
		ForStmt fortmp = forvalues->get(ctx->parent);
		TACLine updateCondition = fortmp.UpdateCon;
		TACLine loopCondition = fortmp.LoopCon;
		push_line(updateCondition.op, updateCondition.src1, updateCondition.src2, updateCondition.dst);
		push_line(loopCondition.op, loopCondition.src1, loopCondition.src2, loopCondition.dst);

	}

	//if 情况
	if (ctx->parent->children[2] == ctx && ctx->parent->children[0]->getText() == "if"){
		push_line(TACOP::GOTO,Operand("ENDIF" + ifvalues->get(ctx->parent), TACOPERANDTYPE::LABEL),Operand("", TACOPERANDTYPE::NULL_),Operand("", TACOPERANDTYPE::NULL_));
	}
	popScope();


}

void GoTo3code::enterStatementList(GoParser::StatementListContext *ctx){}
void GoTo3code::exitStatementList(GoParser::StatementListContext *ctx){}

void GoTo3code::enterStatement(GoParser::StatementContext *ctx){

}
void GoTo3code::exitStatement(GoParser::StatementContext *ctx){}

void GoTo3code::enterSimpleStmt(GoParser::SimpleStmtContext *ctx){}
void GoTo3code::exitSimpleStmt(GoParser::SimpleStmtContext *ctx){}

void GoTo3code::enterExpressionStmt(GoParser::ExpressionStmtContext *ctx){}
void GoTo3code::exitExpressionStmt(GoParser::ExpressionStmtContext *ctx){}

void GoTo3code::enterSendStmt(GoParser::SendStmtContext *ctx){}
void GoTo3code::exitSendStmt(GoParser::SendStmtContext *ctx){}

void GoTo3code::enterIncDecStmt(GoParser::IncDecStmtContext *ctx){}
void GoTo3code::exitIncDecStmt(GoParser::IncDecStmtContext *ctx){
	if (ctx->children[1]->getText() == "++")
	{
		std::shared_ptr<vector<string>> left_values;
		left_values=ctx_decoder(values->get(ctx->expression()));
		if(left_values->size()!=1){
			LOG(FATAL)<<"too many parameter for incdec \"++\"";
			cout<<"too many parameter for incdec \"++\""<<endl;
			exit(-1);
		}

		//for statement 的情况，不写入3code，但是要记录在forstmt里面，作为update的条件
		if(ctx->parent->parent->parent->children[0]->getText() == "for" && ctx->parent->parent == ctx->parent->parent->parent->children[1])
		{
			string varname = (*left_values)[0];
			string varvalue = "1";
			ForStmt fortmp =  forvalues->get(ctx->parent->parent->parent);
			TACLine tmpline = TACLine(GoTo3code::LineIndex, TACOP::ADD, Operand(varname, OperandTypereslove(varname)), Operand(varvalue, OperandTypereslove(varvalue)), Operand(varname, OperandTypereslove(varname)), currentScope);
			fortmp.UpdateCon = tmpline;
			forvalues->put(ctx->parent->parent->parent, fortmp);
		}
		//普通情况，block里面，写入3code
		else
		{
			string varname = (*left_values)[0];
			string varvalue = "1";
			push_line (TACOP::ADD, Operand(varname, OperandTypereslove(varname)), Operand(varvalue, OperandTypereslove(varvalue)), Operand(varname, OperandTypereslove(varname)));

		}
	}
}

void GoTo3code::enterAssignment(GoParser::AssignmentContext *ctx){}
void GoTo3code::exitAssignment(GoParser::AssignmentContext *ctx){


	if(ctx->assign_op()->getText() == "=")
	{
		std::shared_ptr<vector<string>> left_values;
		std::shared_ptr<vector<string>> right_values;
		left_values=ctx_decoder(values->get(ctx->expressionList(0)));
		right_values=ctx_decoder(values->get(ctx->expressionList(1)));
		/*左右参数量是否相等*/
		if(left_values->size()!=right_values->size()){
			LOG(FATAL)<<"not equal number parameter for assign";
			cout<<"not equal number parameter for assign"<<endl;
			exit(-1);
		}

		/*ok*/
		for(int i = 0; i < left_values->size(); i++)
		{
			string varname = (*left_values)[i];
			string varvalue = (*right_values)[i];

			// // 数组赋值
			// if(varname[varname.size()-1]==']'){
			// 	tmp s="[";
			// 	int identity_end=varname.find(tmp);

			// }
			// // 普通变量赋值
			// else{
			// cout<<"zyx:"<<"OperandTypereslove(varname):"<<ToString(OperandTypereslove(varname))<<endl;
			push_line (TACOP::ASSIGN, Operand(varvalue, OperandTypereslove(varvalue)), Operand("", TACOPERANDTYPE::NULL_), Operand(varname, OperandTypereslove(varname)));
			// }

		}
	}
	// 未实现数组的
	if(ctx->assign_op()->getText() == "+=")
	{
		std::shared_ptr<vector<string>> left_values;
		std::shared_ptr<vector<string>> right_values;
		left_values=ctx_decoder(values->get(ctx->expressionList(0)));
		right_values=ctx_decoder(values->get(ctx->expressionList(1)));
		/*左右参数量是否相等*/
		if(left_values->size()!=1 || right_values->size() != 1){
			LOG(FATAL)<<"too many parameter for assign \"+=\"";
			cout<<"too many parameter for assign \"+=\""<<endl;
			exit(-1);
		}

		//for statement 的情况，不写入3code，但是要记录在forstmt里面，作为update的条件
		if(ctx->parent->parent->parent->children[0]->getText() == "for" && ctx->parent->parent == ctx->parent->parent->parent->children[1])
		{
			string varname = (*left_values)[0];
			string varvalue = (*right_values)[0];
			ForStmt fortmp =  forvalues->get(ctx->parent->parent->parent);
			TACLine tmpline = TACLine(GoTo3code::LineIndex, TACOP::ADD, Operand(varname, OperandTypereslove(varname)), Operand(varvalue, OperandTypereslove(varvalue)), Operand(varname, OperandTypereslove(varname)), currentScope);
			fortmp.UpdateCon = tmpline;
			forvalues->put(ctx->parent->parent->parent, fortmp);
		}
		//普通情况，block里面，写入3code
		else
		{
			string varname = (*left_values)[0];
			string varvalue = (*right_values)[0];
			push_line (TACOP::ADD, Operand(varname, OperandTypereslove(varname)), Operand(varvalue, OperandTypereslove(varvalue)), Operand(varname, OperandTypereslove(varname)));

		}
	}
}

void GoTo3code::enterAssign_op(GoParser::Assign_opContext *ctx){}
void GoTo3code::exitAssign_op(GoParser::Assign_opContext *ctx){}

void GoTo3code::enterShortVarDecl(GoParser::ShortVarDeclContext *ctx){}
void GoTo3code::exitShortVarDecl(GoParser::ShortVarDeclContext *ctx){
	int n = ctx->identifierList()->IDENTIFIER().size();

	for(int i=0;i<n;++i){
		string varname = ctx->identifierList()->IDENTIFIER(i)->getText();
		Symbol::Type type;
		type=defineTmpType();
		/*如果已经定义了，报错*/
		// 不报错

		// if(currentScope->cur_resolve(varname)==SUCCESS){
		// 	cout<<"Redeclaration of parameter:"<<varname<<endl;
		// 	exit(-1);
		// }
		/*不重复，新建*/
		std::shared_ptr<Symbol> symbol=make_shared<Symbol>(varname,currentScope,Symbol::SymbolType::VAR,type);
		GoTo3code::currentScope->para_define(symbol);
	}




	/* TODO:如果是函数调用怎么办？？ */
	if(ctx->expressionList()){
		shared_ptr<vector<string>> right_values;
		right_values=ctx_decoder(values->get(ctx->expressionList()));
		/*数量是否匹配*/
		if(n!=right_values->size()){
			LOG(FATAL) << "wrong number match";
			cout<<"wrong number match"<<endl;
			exit(-1);
		}
		/*赋值*/
		for(int i=0;i<n;++i){
			push_line(TACOP::ASSIGN, Operand((*right_values)[i], OperandTypereslove((*right_values)[i])),Operand("", TACOPERANDTYPE::NULL_),Operand(ctx->identifierList()->IDENTIFIER(i)->getText(), OperandTypereslove(ctx->identifierList()->IDENTIFIER(i)->getText())));
		}
	}
	if (ctx->parent->parent->parent->children[0]->getText() == "for" && ctx->parent->parent->parent->children[1] == ctx->parent->parent)
	{
		//init 变量添加进forstmt结构体，方便在forstmt结束后销毁变量
		ForStmt tmp = forvalues->get(ctx->parent->parent->parent);
		for(int i=0;i<n;++i){
		string varname = ctx->identifierList()->IDENTIFIER(i)->getText();
		tmp.newParas.push_back(varname);
		}
		forvalues->put(ctx->parent->parent->parent, tmp);
	}
}

void GoTo3code::enterEmptyStmt(GoParser::EmptyStmtContext *ctx){}
void GoTo3code::exitEmptyStmt(GoParser::EmptyStmtContext *ctx){}

void GoTo3code::enterLabeledStmt(GoParser::LabeledStmtContext *ctx){}
void GoTo3code::exitLabeledStmt(GoParser::LabeledStmtContext *ctx){}

void GoTo3code::enterReturnStmt(GoParser::ReturnStmtContext *ctx){}
void GoTo3code::exitReturnStmt(GoParser::ReturnStmtContext *ctx){
	std::shared_ptr<vector<string>> return_values;
	return_values=ctx_decoder(values->get(ctx->expressionList()));
	/*是否声明*/
	for(auto i:(*return_values)){
		shared_ptr<Symbol> tmp;
		if(currentScope->resolve(i,tmp)==FAIL){
			LOG(FATAL) << "Undefined: " << i;
			exit(-1);
		}
	}
	/*生成TAC*/
	for(auto i:(*return_values)){
		push_line (TACOP::FUN_RET, Operand(i, OperandTypereslove(i)), Operand("", TACOPERANDTYPE::NULL_), Operand("", TACOPERANDTYPE::NULL_));
	}
}

void GoTo3code::enterBreakStmt(GoParser::BreakStmtContext *ctx){}
void GoTo3code::exitBreakStmt(GoParser::BreakStmtContext *ctx){}

void GoTo3code::enterContinueStmt(GoParser::ContinueStmtContext *ctx){}
void GoTo3code::exitContinueStmt(GoParser::ContinueStmtContext *ctx){}

void GoTo3code::enterGotoStmt(GoParser::GotoStmtContext *ctx){}
void GoTo3code::exitGotoStmt(GoParser::GotoStmtContext *ctx){}

void GoTo3code::enterFallthroughStmt(GoParser::FallthroughStmtContext *ctx){}
void GoTo3code::exitFallthroughStmt(GoParser::FallthroughStmtContext *ctx){}

void GoTo3code::enterDeferStmt(GoParser::DeferStmtContext *ctx){}
void GoTo3code::exitDeferStmt(GoParser::DeferStmtContext *ctx){}

void GoTo3code::enterIfStmt(GoParser::IfStmtContext *ctx){
	std::string iftmp = CreateElseLabel();
	ifvalues->put(ctx, iftmp);
}
void GoTo3code::exitIfStmt(GoParser::IfStmtContext *ctx){
	push_line(TACOP::LABEL,Operand("ENDIF" + ifvalues->get(ctx),TACOPERANDTYPE::LABEL),Operand("",TACOPERANDTYPE::NULL_),Operand("",TACOPERANDTYPE::NULL_));
}

void GoTo3code::enterSwitchStmt(GoParser::SwitchStmtContext *ctx){}
void GoTo3code::exitSwitchStmt(GoParser::SwitchStmtContext *ctx){}

void GoTo3code::enterExprSwitchStmt(GoParser::ExprSwitchStmtContext *ctx){}
void GoTo3code::exitExprSwitchStmt(GoParser::ExprSwitchStmtContext *ctx){}

void GoTo3code::enterExprCaseClause(GoParser::ExprCaseClauseContext *ctx){}
void GoTo3code::exitExprCaseClause(GoParser::ExprCaseClauseContext *ctx){}

void GoTo3code::enterExprSwitchCase(GoParser::ExprSwitchCaseContext *ctx){}
void GoTo3code::exitExprSwitchCase(GoParser::ExprSwitchCaseContext *ctx){}

void GoTo3code::enterTypeSwitchStmt(GoParser::TypeSwitchStmtContext *ctx){}
void GoTo3code::exitTypeSwitchStmt(GoParser::TypeSwitchStmtContext *ctx){}

void GoTo3code::enterTypeSwitchGuard(GoParser::TypeSwitchGuardContext *ctx){}
void GoTo3code::exitTypeSwitchGuard(GoParser::TypeSwitchGuardContext *ctx){}

void GoTo3code::enterTypeCaseClause(GoParser::TypeCaseClauseContext *ctx){}
void GoTo3code::exitTypeCaseClause(GoParser::TypeCaseClauseContext *ctx){}

void GoTo3code::enterTypeSwitchCase(GoParser::TypeSwitchCaseContext *ctx){}
void GoTo3code::exitTypeSwitchCase(GoParser::TypeSwitchCaseContext *ctx){}

void GoTo3code::enterTypeList(GoParser::TypeListContext *ctx){}
void GoTo3code::exitTypeList(GoParser::TypeListContext *ctx){}

void GoTo3code::enterSelectStmt(GoParser::SelectStmtContext *ctx){}
void GoTo3code::exitSelectStmt(GoParser::SelectStmtContext *ctx){}

void GoTo3code::enterCommClause(GoParser::CommClauseContext *ctx){}
void GoTo3code::exitCommClause(GoParser::CommClauseContext *ctx){}

void GoTo3code::enterCommCase(GoParser::CommCaseContext *ctx){}
void GoTo3code::exitCommCase(GoParser::CommCaseContext *ctx){}

void GoTo3code::enterRecvStmt(GoParser::RecvStmtContext *ctx){}
void GoTo3code::exitRecvStmt(GoParser::RecvStmtContext *ctx){}

void GoTo3code::enterForStmt(GoParser::ForStmtContext *ctx){
	std::string tmp = CreateForLabel();
	ForStmt newfor = ForStmt(tmp);
	cout << newfor.CurIndex<<endl;
	forvalues->put(ctx, newfor);
	addScope();
}
void GoTo3code::exitForStmt(GoParser::ForStmtContext *ctx){
	ForStmt tmp = forvalues->get(ctx);
	popScope();
	// for (auto para : tmp.newParas)
	// {
	// 	currentScope->para_delete(para);
	// }
	push_line(TACOP::LABEL,Operand("ENDFOR" + forvalues->get(ctx).CurIndex,TACOPERANDTYPE::LABEL),Operand("",TACOPERANDTYPE::NULL_),Operand("",TACOPERANDTYPE::NULL_));
}

void GoTo3code::enterForClause(GoParser::ForClauseContext *ctx){}
void GoTo3code::exitForClause(GoParser::ForClauseContext *ctx){}

void GoTo3code::enterRangeClause(GoParser::RangeClauseContext *ctx){}
void GoTo3code::exitRangeClause(GoParser::RangeClauseContext *ctx){}

void GoTo3code::enterGoStmt(GoParser::GoStmtContext *ctx){}
void GoTo3code::exitGoStmt(GoParser::GoStmtContext *ctx){}

void GoTo3code::enterType_(GoParser::Type_Context *ctx){}
void GoTo3code::exitType_(GoParser::Type_Context *ctx){}

void GoTo3code::enterTypeName(GoParser::TypeNameContext *ctx){}
void GoTo3code::exitTypeName(GoParser::TypeNameContext *ctx){}

void GoTo3code::enterTypeLit(GoParser::TypeLitContext *ctx){}
void GoTo3code::exitTypeLit(GoParser::TypeLitContext *ctx){}

void GoTo3code::enterArrayType(GoParser::ArrayTypeContext *ctx){}
void GoTo3code::exitArrayType(GoParser::ArrayTypeContext *ctx){}

void GoTo3code::enterArrayLength(GoParser::ArrayLengthContext *ctx){}
void GoTo3code::exitArrayLength(GoParser::ArrayLengthContext *ctx){}

void GoTo3code::enterElementType(GoParser::ElementTypeContext *ctx){}
void GoTo3code::exitElementType(GoParser::ElementTypeContext *ctx){}

void GoTo3code::enterPointerType(GoParser::PointerTypeContext *ctx){}
void GoTo3code::exitPointerType(GoParser::PointerTypeContext *ctx){}

void GoTo3code::enterInterfaceType(GoParser::InterfaceTypeContext *ctx){}
void GoTo3code::exitInterfaceType(GoParser::InterfaceTypeContext *ctx){}

void GoTo3code::enterSliceType(GoParser::SliceTypeContext *ctx){}
void GoTo3code::exitSliceType(GoParser::SliceTypeContext *ctx){}

void GoTo3code::enterMapType(GoParser::MapTypeContext *ctx){}
void GoTo3code::exitMapType(GoParser::MapTypeContext *ctx){}

void GoTo3code::enterChannelType(GoParser::ChannelTypeContext *ctx){}
void GoTo3code::exitChannelType(GoParser::ChannelTypeContext *ctx){}

void GoTo3code::enterMethodSpec(GoParser::MethodSpecContext *ctx){}
void GoTo3code::exitMethodSpec(GoParser::MethodSpecContext *ctx){}

void GoTo3code::enterFunctionType(GoParser::FunctionTypeContext *ctx){}
void GoTo3code::exitFunctionType(GoParser::FunctionTypeContext *ctx){}

void GoTo3code::enterSignature(GoParser::SignatureContext *ctx){}
void GoTo3code::exitSignature(GoParser::SignatureContext *ctx){}

void GoTo3code::enterResult(GoParser::ResultContext *ctx){}
void GoTo3code::exitResult(GoParser::ResultContext *ctx){}

void GoTo3code::enterParameters(GoParser::ParametersContext *ctx){}
void GoTo3code::exitParameters(GoParser::ParametersContext *ctx){}

void GoTo3code::enterParameterDecl(GoParser::ParameterDeclContext *ctx){
	if(ctx->identifierList()){  /* x int */

		int n=ctx->identifierList()->IDENTIFIER().size();
		for(int i=0;i<n;++i){

			string integer=ctx->identifierList()->IDENTIFIER(i)->getText();
			// Symbol::Type type=ctx->type_()->typeName()->getText();
			string stype=ctx->type_()->typeName()->getText();
			Symbol::Type type=Symbol::toType(stype);
			std::shared_ptr<Symbol> symbol= make_shared<Symbol>(integer,currentScope,Symbol::SymbolType::VAR,type);
			GoTo3code::currentScope->para_define(symbol);
		}

	}

}
void GoTo3code::exitParameterDecl(GoParser::ParameterDeclContext *ctx){}

void GoTo3code::enterConversion(GoParser::ConversionContext *ctx){}
void GoTo3code::exitConversion(GoParser::ConversionContext *ctx){}

void GoTo3code::enterNonNamedType(GoParser::NonNamedTypeContext *ctx){}
void GoTo3code::exitNonNamedType(GoParser::NonNamedTypeContext *ctx){}



void GoTo3code::enterOperandName(GoParser::OperandNameContext *ctx){}
void GoTo3code::exitOperandName(GoParser::OperandNameContext *ctx){
	shared_ptr<Symbol> tmp;
	if(currentScope->resolve(ctx->IDENTIFIER()->getText(),tmp)==FAIL){
		LOG(FATAL) << "Undefined: " << ctx->IDENTIFIER()->getText();
		exit(-1);
	}
	values->put(ctx,ctx->IDENTIFIER()->getText()+DELIMITER);
}

void GoTo3code::enterQualifiedIdent(GoParser::QualifiedIdentContext *ctx){}
void GoTo3code::exitQualifiedIdent(GoParser::QualifiedIdentContext *ctx){}

void GoTo3code::enterCompositeLit(GoParser::CompositeLitContext *ctx){}
void GoTo3code::exitCompositeLit(GoParser::CompositeLitContext *ctx){}

void GoTo3code::enterLiteralType(GoParser::LiteralTypeContext *ctx){}
void GoTo3code::exitLiteralType(GoParser::LiteralTypeContext *ctx){}

void GoTo3code::enterLiteralValue(GoParser::LiteralValueContext *ctx){}
void GoTo3code::exitLiteralValue(GoParser::LiteralValueContext *ctx){}

void GoTo3code::enterElementList(GoParser::ElementListContext *ctx){}
void GoTo3code::exitElementList(GoParser::ElementListContext *ctx){}

void GoTo3code::enterKeyedElement(GoParser::KeyedElementContext *ctx){}
void GoTo3code::exitKeyedElement(GoParser::KeyedElementContext *ctx){}

void GoTo3code::enterKey(GoParser::KeyContext *ctx){}
void GoTo3code::exitKey(GoParser::KeyContext *ctx){}

void GoTo3code::enterElement(GoParser::ElementContext *ctx){}
void GoTo3code::exitElement(GoParser::ElementContext *ctx){}

void GoTo3code::enterStructType(GoParser::StructTypeContext *ctx){}
void GoTo3code::exitStructType(GoParser::StructTypeContext *ctx){}

void GoTo3code::enterFieldDecl(GoParser::FieldDeclContext *ctx){}
void GoTo3code::exitFieldDecl(GoParser::FieldDeclContext *ctx){}

void GoTo3code::enterString_(GoParser::String_Context *ctx){}
void GoTo3code::exitString_(GoParser::String_Context *ctx){}

void GoTo3code::enterEmbeddedField(GoParser::EmbeddedFieldContext *ctx){}
void GoTo3code::exitEmbeddedField(GoParser::EmbeddedFieldContext *ctx){}

void GoTo3code::enterFunctionLit(GoParser::FunctionLitContext *ctx){}
void GoTo3code::exitFunctionLit(GoParser::FunctionLitContext *ctx){}

void GoTo3code::enterIndex(GoParser::IndexContext *ctx){}
void GoTo3code::exitIndex(GoParser::IndexContext *ctx){}

void GoTo3code::enterSlice_(GoParser::Slice_Context *ctx){}
void GoTo3code::exitSlice_(GoParser::Slice_Context *ctx){}

void GoTo3code::enterTypeAssertion(GoParser::TypeAssertionContext *ctx){}
void GoTo3code::exitTypeAssertion(GoParser::TypeAssertionContext *ctx){}

void GoTo3code::enterArguments(GoParser::ArgumentsContext *ctx){}
void GoTo3code::exitArguments(GoParser::ArgumentsContext *ctx){
	if(ctx->expressionList()){
		values->put(ctx, values->get(ctx->expressionList()));
	}
}

void GoTo3code::enterMethodExpr(GoParser::MethodExprContext *ctx){}
void GoTo3code::exitMethodExpr(GoParser::MethodExprContext *ctx){}

void GoTo3code::enterReceiverType(GoParser::ReceiverTypeContext *ctx){}
void GoTo3code::exitReceiverType(GoParser::ReceiverTypeContext *ctx){}

void GoTo3code::enterEoss(GoParser::EossContext *ctx){}
void GoTo3code::exitEoss(GoParser::EossContext *ctx){}

void GoTo3code::visitTerminal(antlr4::tree::TerminalNode *node){}
void GoTo3code::visitErrorNode(antlr4::tree::ErrorNode *node){}
void GoTo3code::enterEveryRule(antlr4::ParserRuleContext *ctx){}
void GoTo3code::exitEveryRule(antlr4::ParserRuleContext *ctx){}
