//
// 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.
//
// LabelTypeChecker.cc -- 
//
// Author           : Rodolfo G. Esteves
// Created On       : Mon May 18 07:44:20 2015
// Last Modified By : Rob Schluntz
// Last Modified On : Wed Jun 24 16:24:48 2015
// Update Count     : 3
//

#include <list>
#include <cassert>

#include "SynTree/Type.h"
#include "SynTree/Statement.h"
#include "SynTree/Expression.h"
#include "SynTree/Declaration.h"

#include "LabelTypeChecker.h"

namespace ControlStruct {
	void LabelTypeChecker::visit(UntypedExpr *untypedExpr) {
		assert( untypedExpr != 0 );
		NameExpr *fname;
		if ( ((fname = dynamic_cast<NameExpr *>(untypedExpr->get_function())) != 0) 
			 && fname->get_name() == std::string("&&") )
			std::cerr << "Taking the label of an address." << std::endl;
		else {
			acceptAll( untypedExpr->get_results(), *this );
			acceptAll( untypedExpr->get_args(), *this );
		} // if
		return;
	}

	void LabelTypeChecker::visit(CompoundStmt *compoundStmt) {
		index.enterScope();
		acceptAll( compoundStmt->get_kids(), *this );
		index.leaveScope();
	}

	void LabelTypeChecker::visit(DeclStmt *declStmt) {
		declStmt->accept( index );

		//ObjectDecl *odecl = 0;
		// if ( ( odecl = dynamic_cast<ObjectDecl *>(declStmt->get_decl()) ) != 0 ) {
		return;
	}

	void LabelTypeChecker::visit(BranchStmt *branchStmt) {
		if ( branchStmt->get_type() != BranchStmt::Goto ) return;
		Expression *target;
		if ( (target = branchStmt->get_computedTarget()) == 0 ) return;

		NameExpr *name;
		if ( ((name = dynamic_cast<NameExpr *>(target)) == 0) )
			return; // Not a name expression
	
		std::list< DeclarationWithType * > interps;
		index.lookupId(name->get_name(), interps);
		if ( interps.size() != 1)
			// in case of multiple declarations
			throw SemanticError("Illegal label expression: " + name->get_name() );

		PointerType *ptr;
		if ( (ptr = dynamic_cast<PointerType *>(interps.front()->get_type())) != 0 )
			if ( dynamic_cast<VoidType *>(ptr->get_base()) != 0 )
				return;
			else
				throw SemanticError("Wrong type of parameter for computed goto");
		else
			throw SemanticError("Wrong type of parameter for computed goto");

		return;
	}
} // namespace ControlStruct

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