//
// Cforall Version 1.0.0 Copyright (C) 2015 University of Waterloo
//
// The contents of this file are covered under the licence agreement in the
// file "LICENCE" distributed with Cforall.
//
// TypeData.h -- 
//
// Author           : Rodolfo G. Esteves
// Created On       : Sat May 16 15:18:36 2015
// Last Modified By : Peter A. Buhr
// Last Modified On : Fri Feb 26 14:21:38 2016
// Update Count     : 19
//

#ifndef TYPEDATA_H
#define TYPEDATA_H

#include <list>

#include "ParseNode.h"
#include "SynTree/Type.h"

struct TypeData {
	enum Kind { Unknown, Basic, Pointer, Array, Function, Aggregate, AggregateInst,
				Enum, EnumConstant, Symbolic, SymbolicInst, Variable, Tuple, Typeof, Builtin, Attr } kind;

	TypeData( Kind k = Unknown );
	~TypeData();
	void print( std::ostream &, int indent = 0 ) const;
	TypeData * clone() const;

	Type * build() const;
	FunctionType * buildFunction() const;

	TypeData * base;
	std::list< DeclarationNode::Qualifier > qualifiers;
	DeclarationNode * forall;

	struct Basic_t {
		std::list< DeclarationNode::BasicType > typeSpec;
		std::list< DeclarationNode::Modifier > modifiers;
	};

	struct Aggregate_t {
		DeclarationNode::Aggregate kind;
		std::string name;
		DeclarationNode * params;
		ExpressionNode  * actuals;						// holds actual parameters later applied to AggInst
		DeclarationNode * fields;
	};

	struct AggInst_t {
		TypeData * aggregate;
		ExpressionNode * params;
	};

	struct Array_t {
		ExpressionNode * dimension;
		bool isVarLen;
		bool isStatic;
	};

	struct Enumeration_t {
		std::string name;
		DeclarationNode * constants;
	};

	struct Function_t {
		DeclarationNode * params;
		DeclarationNode * idList;						// old-style
		DeclarationNode * oldDeclList;
		StatementNode * body;
		bool hasBody;
		bool newStyle;
	};

	struct Symbolic_t {
		std::string name;
		bool isTypedef;									// false => TYPEGENname, true => TYPEDEFname
		DeclarationNode * params;
		ExpressionNode * actuals;
		DeclarationNode * assertions;
	};

	struct Variable_t {
		DeclarationNode::TypeClass tyClass;
		std::string name;
		DeclarationNode * assertions;
	};

	struct Tuple_t {
		DeclarationNode * members;
	};
  
	struct Typeof_t {
		ExpressionNode * expr;
	};

	struct Builtin_t {
		DeclarationNode::BuiltinType type;
	};

	struct Attr_t {
		std::string name;
		ExpressionNode * expr;
		DeclarationNode * type;
	};

	union {
		Basic_t * basic;
		Aggregate_t * aggregate;
		AggInst_t * aggInst;
		Array_t * array;
		Enumeration_t * enumeration;
		Function_t * function;
		Symbolic_t * symbolic;
		Variable_t * variable;
		Tuple_t * tuple;
		Typeof_t * typeexpr;
		Attr_t * attr;
		Builtin_t * builtin;
	};

	TypeData * extractAggregate( bool toplevel = true ) const;
	// helper function for DeclNodeImpl::build
	Declaration * buildDecl( std::string name, DeclarationNode::StorageClass sc, Expression * bitfieldWidth, bool isInline, bool isNoreturn, LinkageSpec::Type linkage, Initializer * init = 0 ) const;
	// helper functions for build()
	Type::Qualifiers buildQualifiers() const;
	Type * buildBasicType() const;
	PointerType * buildPointer() const;
	ArrayType * buildArray() const;
	AggregateDecl * buildAggregate() const;
	ReferenceToType * buildAggInst() const;
	NamedTypeDecl * buildSymbolic( const std::string &name, DeclarationNode::StorageClass sc ) const;
	TypeDecl* buildVariable() const;
	EnumDecl* buildEnum() const;
	TypeInstType * buildSymbolicInst() const;
	TupleType * buildTuple() const;
	TypeofType * buildTypeof() const;
	AttrType * buildAttr() const;
};

#endif // TYPEDATA_H

// Local Variables: //
// tab-width: 4 //
// mode: c++ //
// compile-command: "make install" //
// End: //
