/*
	This file is part of solidity.
	solidity is free software: you can redistribute it and/or modify
	it under the terms of the GNU General Public License as published by
	the Free Software Foundation, either version 3 of the License, or
	(at your option) any later version.
	solidity is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU General Public License for more details.
	You should have received a copy of the GNU General Public License
	along with solidity.  If not, see .
*/
// SPDX-License-Identifier: GPL-3.0
/**
 * @author julius 
 * @date 2019
 * Converts the AST from JSON format to ASTNode
 */
#pragma once
#include 
#include 
#include 
#include 
#include 
#include 
#include 
namespace solidity::frontend
{
/**
 * Component that imports an AST from json format to the internal format
 */
class ASTJsonImporter
{
public:
	ASTJsonImporter(langutil::EVMVersion _evmVersion)
		:m_evmVersion(_evmVersion)
	{}
	/// Converts the AST from JSON-format to ASTPointer
	/// @a _sourceList used to provide source names for the ASTs
	/// @returns map of sourcenames to their respective ASTs
	std::map> jsonToSourceUnit(std::map const& _sourceList);
private:
	// =========== general creation functions ==============
	/// Sets the source location and nodeID
	/// @returns the ASTNode Object class of the respective JSON node,
	template 
	ASTPointer createASTNode(Json::Value const& _node, Args&&... _args);
	/// @returns the sourceLocation-object created from the string in the JSON node
	langutil::SourceLocation const createSourceLocation(Json::Value const& _node);
	/// Creates an ASTNode for a given JSON-ast of unknown type
	/// @returns Pointer to a new created ASTNode
	ASTPointer convertJsonToASTNode(Json::Value const& _ast);
	/// @returns a pointer to the more specific subclass of ASTNode
	/// as indicated by the nodeType field of the json
	template
	ASTPointer convertJsonToASTNode(Json::Value const& _node);
	/// \defgroup nodeCreators JSON to AST-Nodes
	///@{
	ASTPointer createSourceUnit(Json::Value const& _node, std::string const& _srcName);
	ASTPointer createPragmaDirective(Json::Value const& _node);
	ASTPointer createImportDirective(Json::Value const& _node);
	ASTPointer createContractDefinition(Json::Value const& _node);
	ASTPointer createInheritanceSpecifier(Json::Value const& _node);
	ASTPointer createUsingForDirective(Json::Value const& _node);
	ASTPointer createStructDefinition(Json::Value const& _node);
	ASTPointer createEnumDefinition(Json::Value const& _node);
	ASTPointer createEnumValue(Json::Value const& _node);
	ASTPointer createParameterList(Json::Value const& _node);
	ASTPointer createOverrideSpecifier(Json::Value const& _node);
	ASTPointer createFunctionDefinition(Json::Value const& _node);
	ASTPointer createVariableDeclaration(Json::Value const& _node);
	ASTPointer createModifierDefinition(Json::Value const& _node);
	ASTPointer createModifierInvocation(Json::Value const& _node);
	ASTPointer createEventDefinition(Json::Value const& _node);
	ASTPointer createElementaryTypeName(Json::Value const& _node);
	ASTPointer createUserDefinedTypeName(Json::Value const& _node);
	ASTPointer createFunctionTypeName(Json::Value const& _node);
	ASTPointer createMapping(Json::Value const& _node);
	ASTPointer createArrayTypeName(Json::Value const& _node);
	ASTPointer createInlineAssembly(Json::Value const& _node);
	ASTPointer createBlock(Json::Value const& _node);
	ASTPointer createPlaceholderStatement(Json::Value const& _node);
	ASTPointer createIfStatement(Json::Value const& _node);
	ASTPointer createTryCatchClause(Json::Value const& _node);
	ASTPointer createTryStatement(Json::Value const& _node);
	ASTPointer createWhileStatement(Json::Value const& _node, bool _isDoWhile);
	ASTPointer createForStatement(Json::Value const& _node);
	ASTPointer createContinue(Json::Value const& _node);
	ASTPointer createBreak(Json::Value const& _node);
	ASTPointer createReturn(Json::Value const& _node);
	ASTPointer createThrow(Json::Value const& _node);
	ASTPointer createEmitStatement(Json::Value const& _node);
	ASTPointer createVariableDeclarationStatement(Json::Value const& _node);
	ASTPointer createExpressionStatement(Json::Value const& _node);
	ASTPointer createConditional(Json::Value const& _node);
	ASTPointer createAssignment(Json::Value const& _node);
	ASTPointer createTupleExpression(Json::Value const& _node);
	ASTPointer createUnaryOperation(Json::Value const& _node);
	ASTPointer createBinaryOperation(Json::Value const& _node);
	ASTPointer createFunctionCall(Json::Value const& _node);
	ASTPointer createFunctionCallOptions(Json::Value const& _node);
	ASTPointer createNewExpression(Json::Value const& _node);
	ASTPointer createMemberAccess(Json::Value const& _node);
	ASTPointer createIndexAccess(Json::Value const& _node);
	ASTPointer createIndexRangeAccess(Json::Value const& _node);
	ASTPointer createIdentifier(Json::Value const& _node);
	ASTPointer createElementaryTypeNameExpression(Json::Value const& _node);
	ASTPointer createLiteral(Json::Value const& _node);
	ASTPointer createDocumentation(Json::Value const& _node);
	///@}
	// =============== general helper functions ===================
	/// @returns the member of a given JSON object, throws if member does not exist
	Json::Value member(Json::Value const& _node, std::string const& _name);
	/// @returns the appropriate TokenObject used in parsed Strings (pragma directive or operator)
	Token scanSingleToken(Json::Value const& _node);
	template
	///@returns nullptr or an ASTPointer cast to a specific Class
	ASTPointer nullOrCast(Json::Value const& _json);
	/// @returns nullptr or ASTString, given an JSON string or an empty field
	ASTPointer nullOrASTString(Json::Value const& _json, std::string const& _name);
	// ============== JSON to definition helpers ===============
	/// \defgroup typeHelpers Json to ast-datatype helpers
	/// {@
	ASTPointer memberAsASTString(Json::Value const& _node, std::string const& _name);
	bool memberAsBool(Json::Value const& _node, std::string const& _name);
	Visibility visibility(Json::Value const& _node);
	StateMutability stateMutability(Json::Value const& _node);
	VariableDeclaration::Location location(Json::Value const& _node);
	ContractKind contractKind(Json::Value const& _node);
	Token literalTokenKind(Json::Value const& _node);
	Literal::SubDenomination subdenomination(Json::Value const& _node);
	///@}
	// =========== member variables ===============
	/// Stores filepath as sourcenames to AST in JSON format
	std::map m_sourceList;
	/// list of filepaths (used as sourcenames)
	std::vector> m_sourceLocations;
	/// filepath to AST
	std::map> m_sourceUnits;
	std::string m_currentSourceName;
	/// IDs already used by the nodes
	std::set m_usedIDs;
	/// Configured EVM version
	langutil::EVMVersion m_evmVersion;
};
}