/* $Id: lextype.c,v 1.2 2009/01/04 15:42:14 kiesling Exp $ */

/*
  This file is part of Ctalk.
  Copyright © 2005-2009  Robert Kiesling, ctalk@ctalklang.org.
  Permission is granted to copy this software provided that this copyright
  notice is included in all source code modules.

  This library is free software; you can redistribute it and/or
  modify it under the terms of the GNU Lesser General Public
  License as published by the Free Software Foundation; either
  version 2 of the License, or (at your option) any later version.

  This library 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
  Lesser General Public License for more details.

  You should have received a copy of the GNU General Public License
  along with this program; if not, write to the Free Software Foundation, 
  Inc., 51 Franklin St., Fifth Floor, Boston, MA 02110-1301 USA.
*/

#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <ctype.h>
#include "object.h"
#include "message.h"
#include "ctalk.h"
#include "lex.h"
#include "typeof.h"

/*
 *    Convenience function for lexical ().
 *    
 */

int _lextype (char *s) {

  int c_type;
  MESSAGE *m;
  long long idx;
  int lexical_type;

  c_type = ERROR;

  /* Lexically analyze a single token. */

  m = new_message ();
  idx = 0;

  lexical_type = lexical (s, &idx, m);

  delete_message (m);

  switch (lexical_type)
    {
    case INTEGER:
      c_type = INTEGER_T;
      break;
    case DOUBLE:
      c_type = DOUBLE_T;
      break;
    case LONG:
      c_type = LONG_T;
      break;
    case LONGLONG:
      c_type = LONGLONG_T;
      break;
    case LITERAL:
      c_type = LITERAL_T;
      break;
    case LITERAL_CHAR:
      c_type = LITERAL_CHAR_T;
      break;
    case LABEL:
      c_type = PTR_T;
    default:
      break;
    }

  return c_type;

}

static int __is_subclass_of (char *classname, char *superclassname) {

  OBJECT *class_object, *superclass_object;

  if ((class_object = __ctalkGetClass (classname)) == NULL)
    return FALSE;
    
  for (superclass_object = class_object -> __o_superclass;
       superclass_object && *superclass_object -> __o_superclassname;
       superclass_object = superclass_object -> __o_superclass)
    if (!strcmp (superclass_object -> __o_name, superclassname))
      return TRUE;

  return FALSE;
}

int lextype_of_class (char *s) {
  if (!strcmp (s, INTEGER_CLASSNAME) ||
      __is_subclass_of (s, INTEGER_CLASSNAME))
    return INTEGER_T;

  if (!strcmp (s, LONGINTEGER_CLASSNAME) ||
      __is_subclass_of (s, LONGINTEGER_CLASSNAME))
    return LONGLONG_T;
    
  if (!strcmp (s, FLOAT_CLASSNAME) ||
      __is_subclass_of (s, FLOAT_CLASSNAME))
    return FLOAT_T;

  if (!strcmp (s, STRING_CLASSNAME) ||
      __is_subclass_of (s, STRING_CLASSNAME))
    return PTR_T;

  if (!strcmp (s, CHARACTER_CLASSNAME))
    return INTEGER_T;

  if (!strcmp (s, COLLECTION_CLASSNAME) ||
      __is_subclass_of (s, COLLECTION_CLASSNAME))
    return PTR_T;

  if (!strcmp (s, SYMBOL_CLASSNAME) ||
      __is_subclass_of (s, SYMBOL_CLASSNAME))
    return PTR_T;

  if (!strcmp (s, OBJECT_CLASSNAME) ||
      __is_subclass_of (s, OBJECT_CLASSNAME))
    return PTR_T;

/*    _warning ("Unimplemented class %s in lextype_of_class.  Lexical type defaulting to int.\n", s); */
  
  return INTEGER_T;
}
