Logo Search packages:      
Sourcecode: fauhdlc version File versions

RegisterBuiltins.cpp

/* $Id: RegisterBuiltins.cpp 4323 2009-01-27 13:48:12Z potyra $
 *
 * RegisterBuiltins: can register builtin functions for a given type
 * declaration.
 *
 * Copyright (C) 2008-2009 FAUmachine Team <info@faumachine.org>.
 * This program is free software. You can redistribute it and/or modify it
 * under the terms of the GNU General Public License, either version 2 of
 * the License, or (at your option) any later version. See COPYING.
 */


#include "frontend/misc/RegisterBuiltins.hpp"

#include <string>
#include <cassert>
#include <iostream>
#include "frontend/ast/SimpleName.hpp"
#include "frontend/ast/FunctionDeclaration.hpp"
#include "frontend/ast/UnconstrainedArrayType.hpp"
#include "frontend/ast/EnumerationType.hpp"
#include "frontend/ast/RecordType.hpp"
#include "frontend/ast/ConstInteger.hpp"
#include "frontend/ast/ConstReal.hpp"
#include "frontend/visitor/TopDownVisitor.hpp"
#include "frontend/misc/SymbolTable.hpp"
#include "frontend/reporting/CompileError.hpp"
#include "frontend/reporting/ErrorRegistry.hpp"
#include "frontend/visitor/ResolveTypes.hpp"

namespace ast {

void
00034 RegisterBuiltins::regTypeOps(SymbolDeclaration &type, SymbolTable &s)
{
      /* FIXME: deriving from NullVisitor is enough. However for debugging
       *        purposes (no calls for wrong nodes, we'll stay with 
       *        TopDownVisitor).
       */
      class Dispatcher : public TopDownVisitor {
      public:
            //! c'tor
            /** @param r RegisterBuiltins instance.
             */
            Dispatcher(SymbolTable &st) : symTab(st) {}

            virtual void visit(RangeConstraintType &t) {
                  if (t.baseType == BASE_TYPE_UNSET) {
                        RegisterBuiltins::determineBaseType(t, 
                                                this->symTab);
                  }
                  if (t.baseType == BASE_TYPE_UNSET) {
                        // type error occured, bail out.
                        return;
                  }
                  RegisterBuiltins::registerTypeOps(t, this->symTab);
            }

            virtual void visit(PhysicalType &t) {
                  RegisterBuiltins::registerTypeOps(t, this->symTab);
            }

            virtual void visit(EnumerationType &t) {
                  RegisterBuiltins::registerTypeOps(t, this->symTab);
            }

            virtual void visit(RecordType &t) {
                  RegisterBuiltins::registerTypeOps(t, this->symTab);
            }
            virtual void visit(SubtypeIndication &t) {
                  //skip. subtypes inherit operations of base types.
            }
            virtual void visit(UnconstrainedArrayType &t) {
                  RegisterBuiltins::registerTypeOps(t, this->symTab);
            }

      private:
            virtual void process(AstNode &t) {
                  std::cerr << "BANG: found no type node: " << t 
                        << " at " << t.location << std::endl;
                  assert(false);    // not a type or no visit method for
                              // given type in Dispatcher
            }

            SymbolTable &symTab;
      };

      Dispatcher d = Dispatcher(s);
      type.accept(d);
}


void
00094 RegisterBuiltins::registerTypeOps(RangeConstraintType &type, SymbolTable &s)
{
      /* FIXME split between integer and float types? */


      if (type.baseType == BASE_TYPE_INTEGER) {
            // relational operators
            // equality, inequality: any type except file and protected
            RegisterBuiltins::boolBinOp("=", 
                  type, 
                  new BoolEqual<ConstInteger, universal_integer>(s),
                  new GCBuiltinsEqual(),
                  s);
            RegisterBuiltins::boolBinOp("/=", 
                  type, 
                  new BoolNotEqual<ConstInteger, universal_integer>(s),
                  new GCBuiltinsInEqual(),
                  s);
            // ordering: any scalar and discrete array (= 1-dim array of 
            // discrete type)
            RegisterBuiltins::boolBinOp("<", 
                  type, 
                  new BoolLess<ConstInteger, universal_integer>(s),
                  new GCBuiltinsLess(),
                  s);
            RegisterBuiltins::boolBinOp("<=", 
                  type, 
                  new BoolLessOrEqual<ConstInteger, universal_integer>(s),
                  new GCBuiltinsLessEqual(),
                  s);
            RegisterBuiltins::boolBinOp(">", 
                  type, 
                  new BoolGreater<ConstInteger, universal_integer>(s),
                  new GCBuiltinsGreater(),
                  s);
            RegisterBuiltins::boolBinOp(">=", 
                  type, 
                  new BoolGreaterOrEqual<ConstInteger, universal_integer>(s),
                  new GCBuiltinsGreaterEqual(),
                  s);

            // adding operators (any numeric type)
            RegisterBuiltins::binOpSameType("+", 
                  type, 
                  new BinaryPlus<ConstInteger, universal_integer>(),
                  new GCBuiltinsPlus(),
                  s);
            RegisterBuiltins::binOpSameType("-",
                  type, 
                  new BinaryMinus<ConstInteger, universal_integer>(),
                  new GCBuiltinsMinus(),
                  s);
            // (no concatenation for RangeConstraintType)
            // multiplying operators
            RegisterBuiltins::binOpSameType("*", 
                  type, 
                  new BinaryMult<ConstInteger, universal_integer>(),
                  new GCBuiltinsMult(),
                  s);
            RegisterBuiltins::binOpSameType("/", 
                  type,
                  new BinaryDiv<ConstInteger, universal_integer>(),
                  new GCBuiltinsDiv(),
                  s);

            // sign operators (idendity, negation). Any numeric type.
            RegisterBuiltins::unOpSameType("+", 
                  type, 
                  new UnaryPlus<ConstInteger, universal_integer>(),
                  new GCBuiltinsIdentity(),
                  s);
            RegisterBuiltins::unOpSameType("-", 
                  type, 
                  new UnaryMinus<ConstInteger, universal_integer>(),
                  new GCBuiltinsUnaryMinus(),
                  s);

            RegisterBuiltins::unOpSameType("abs", 
                  type, 
                  new UnaryAbs<ConstInteger, universal_integer>(),
                  new GCBuiltinsAnd(),
                  s);

            // modulus/remainder
            RegisterBuiltins::binOpSameType("mod", 
                  type, 
                  new BinaryMod(),
                  NULL, /* FIXME */
                  s);
            RegisterBuiltins::binOpSameType("rem", 
                  type, 
                  new BinaryRem(),
                  NULL, /* FIXME */
                  s);
      } else {
            // relational operators
            // equality, inequality: any type except file and protected
            RegisterBuiltins::boolBinOp("=", 
                  type, 
                  new BoolEqual<ConstReal, universal_real>(s), 
                  new GCBuiltinsEqual(),
                  s);
            RegisterBuiltins::boolBinOp("/=", 
                  type, 
                  new BoolNotEqual<ConstReal, universal_real>(s),
                  new GCBuiltinsInEqual(),
                  s);
            // ordering: any scalar and discrete array (= 1-dim array of 
            // discrete type)
            RegisterBuiltins::boolBinOp("<", 
                  type, 
                  new BoolLess<ConstReal, universal_real>(s),
                  new GCBuiltinsLess(),
                  s);
            RegisterBuiltins::boolBinOp("<=", 
                  type, 
                  new BoolLessOrEqual<ConstReal, universal_real>(s),
                  new GCBuiltinsLessEqual(),
                  s);
            RegisterBuiltins::boolBinOp(">", 
                  type, 
                  new BoolGreater<ConstReal, universal_real>(s),
                  new GCBuiltinsGreater(),
                  s);
            RegisterBuiltins::boolBinOp(">=", 
                  type, 
                  new BoolGreaterOrEqual<ConstReal, universal_real>(s),
                  new GCBuiltinsGreaterEqual(),
                  s);

            // adding operators (any numeric type)
            RegisterBuiltins::binOpSameType("+", 
                  type, 
                  new BinaryPlus<ConstReal, universal_real>(),
                  new GCBuiltinsPlus(),
                  s);
            RegisterBuiltins::binOpSameType("-",
                  type, 
                  new BinaryMinus<ConstReal, universal_real>(),
                  new GCBuiltinsMinus(),
                  s);
            // (no concatenation for RangeConstraintType)
            // multiplying operators
            RegisterBuiltins::binOpSameType("*", 
                  type, 
                  new BinaryMult<ConstReal, universal_real>(),
                  new GCBuiltinsMult(),
                  s);
            RegisterBuiltins::binOpSameType("/", 
                  type,
                  new BinaryDiv<ConstInteger, universal_integer>(),
                  new GCBuiltinsDiv(),
                  s);
            // sign operators (idendity, negation). Any numeric type.
            RegisterBuiltins::unOpSameType("+", 
                  type, 
                  new UnaryPlus<ConstReal, universal_real>(), 
                  new GCBuiltinsIdentity(),
                  s);
            RegisterBuiltins::unOpSameType("-", 
                  type, 
                  new UnaryMinus<ConstReal, universal_real>(),
                  new GCBuiltinsUnaryMinus(),
                  s);
            RegisterBuiltins::unOpSameType("abs", 
                  type, 
                  new UnaryAbs<ConstReal, universal_real>(), 
                  new GCBuiltinsAnd(),
                  s);
      }
      
      // miscellaneous
      RegisterBuiltins::binOp("**", type, "integer", type, s);
}

void
00270 RegisterBuiltins::registerTypeOps(PhysicalType &type, SymbolTable &s)
{
      // relational operators
      // equality, inequality: any type except file and protected
      RegisterBuiltins::boolBinOp("=", 
            type, 
            new BoolEqual<ConstInteger, universal_integer>(s),
            new GCBuiltinsEqual(),
            s);
      RegisterBuiltins::boolBinOp("/=", 
            type, 
            new BoolNotEqual<ConstInteger, universal_integer>(s),
            new GCBuiltinsInEqual(),
            s);
      // ordering: any scalar and discrete array (= 1-dim array of 
      // discrete type)
      RegisterBuiltins::boolBinOp("<", 
            type, 
            new BoolLess<ConstInteger, universal_integer>(s),
            new GCBuiltinsLess(),
            s);
      RegisterBuiltins::boolBinOp("<=", 
            type, 
            new BoolLessOrEqual<ConstInteger, universal_integer>(s),
            new GCBuiltinsLessEqual(),
            s);
      RegisterBuiltins::boolBinOp(">", 
            type, 
            new BoolGreater<ConstInteger, universal_integer>(s),
            new GCBuiltinsGreater(),
            s);
      RegisterBuiltins::boolBinOp(">=", 
            type, 
            new BoolGreaterOrEqual<ConstInteger, universal_integer>(s),
            new GCBuiltinsGreaterEqual(),
            s);
      // adding operators (any numeric type)
      RegisterBuiltins::binOpSameType("+", 
            type, 
            new BinaryPlus<ConstInteger, universal_integer>(),
            new GCBuiltinsPlus(),
            s);
      RegisterBuiltins::binOpSameType("-", 
            type, 
            new BinaryMinus<ConstInteger, universal_integer>(),
            new GCBuiltinsMinus(),
            s);
      // (no concatenation for physical types)
      // sign operators (idendity, negation). Any numeric type.
      RegisterBuiltins::unOpSameType("+", 
            type, 
            new UnaryPlus<ConstInteger, universal_integer>(),
            new GCBuiltinsIdentity(),
            s);
      RegisterBuiltins::unOpSameType("-", 
            type, 
            new UnaryMinus<ConstInteger, universal_integer>(),
            new GCBuiltinsUnaryMinus(),
            s);
      // multiplying operators (physical types only)
      FunctionDeclaration *f;
      f = RegisterBuiltins::binOp("*", type, "integer", type, s);
      f->builtin = new BinaryMult<ConstInteger, universal_integer>();
      f->gcBuiltin = new GCBuiltinsMult();

      // FIXME builtins!
      RegisterBuiltins::binOp("*", type, "real", type, s);
      // int -> int -> int
      f = RegisterBuiltins::binOp("*", "integer", type, type, s);
      f->builtin = new BinaryMult<ConstInteger, universal_integer>();
      f->gcBuiltin = new GCBuiltinsMult();

      // FIXME builtins!
      RegisterBuiltins::binOp("*", "real", type, type, s);
      
      f = RegisterBuiltins::binOp("/", type, "integer", type, s);
      f->builtin = new BinaryDiv<ConstInteger, universal_integer>();
      f->gcBuiltin = new GCBuiltinsDiv();

      // FIXME builtins!
      RegisterBuiltins::binOp("/", type, "real", type, s);

      TypeDeclaration *univ_int = 
            s.getStdStandardType("__universal_integer__");

      RegisterBuiltins::binOp("/", type, type, *univ_int, s);
      // miscellaneous
      RegisterBuiltins::unOpSameType("abs", 
            type, 
            new UnaryAbs<ConstInteger, universal_integer>(),
            new GCBuiltinsAbs(),
            s);
}

void
00365 RegisterBuiltins::registerTypeOps(
      UnconstrainedArrayType &type, 
      SymbolTable &s
)
{
      // relational operators
      // equality, inequality: any type except file and protected
      // FIXME builtins
      RegisterBuiltins::boolBinOp("=", type, NULL, NULL, s);
      // FIXME builtins
      RegisterBuiltins::boolBinOp("/=", type, NULL, NULL, s);

      if (type.numIndices != 1) {
            return;
      }

      TypeDeclaration *elementType = type.containerType;
      assert(elementType != NULL);

      // concatenation (1-dim arrays)
      RegisterBuiltins::binOp("&", type, type, type, s);
      RegisterBuiltins::binOp("&", type, *elementType, type, s);
      RegisterBuiltins::binOp("&", *elementType, type, type, s);
      RegisterBuiltins::binOp("&", *elementType, *elementType, type, s);

      if (! RegisterBuiltins::isDiscreteType(elementType)) {
            return;
      }

      // ordering: any scalar and discrete array (= 1-dim array of 
      // discrete type)
      // FIXME builtins
      RegisterBuiltins::boolBinOp("<", type, NULL, NULL, s);
      RegisterBuiltins::boolBinOp("<=", type, NULL, NULL, s);
      RegisterBuiltins::boolBinOp(">", type, NULL, NULL, s);
      RegisterBuiltins::boolBinOp(">=", type, NULL, NULL, s);


      if (! RegisterBuiltins::isBoolOrBit(elementType, s)) {
            return;
      }

      // shift operators (1-dim array of bool or bit)
      RegisterBuiltins::binOp("sll", type, "integer", type, s);
      RegisterBuiltins::binOp("srl", type, "integer", type, s);
      RegisterBuiltins::binOp("sla", type, "integer", type, s);
      RegisterBuiltins::binOp("sra", type, "integer", type, s);
      RegisterBuiltins::binOp("rol", type, "integer", type, s);
      RegisterBuiltins::binOp("ror", type, "integer", type, s);
}

void
00417 RegisterBuiltins::registerTypeOps(EnumerationType &type, SymbolTable &s)
{
      // relational operators
      // equality, inequality: any type except file and protected
      RegisterBuiltins::boolBinOp("=", 
            type, 
            new BoolEqual<ConstInteger, universal_integer>(s),
            new GCBuiltinsEqual(),
            s);
      RegisterBuiltins::boolBinOp("/=", 
            type, 
            new BoolNotEqual<ConstInteger, universal_integer>(s),
            new GCBuiltinsInEqual(),
            s);
      // ordering: any scalar and discrete array (= 1-dim array of 
      // discrete type)
      RegisterBuiltins::boolBinOp("<", 
            type, 
            new BoolLess<ConstInteger, universal_integer>(s),
            new GCBuiltinsLess(),
            s);
      RegisterBuiltins::boolBinOp("<=", 
            type, 
            new BoolLessOrEqual<ConstInteger, universal_integer>(s),
            new GCBuiltinsLessEqual(),
            s);
      RegisterBuiltins::boolBinOp(">", 
            type, 
            new BoolGreater<ConstInteger, universal_integer>(s),
            new GCBuiltinsGreater(),
            s);
      RegisterBuiltins::boolBinOp(">=", 
            type, 
            new BoolGreaterOrEqual<ConstInteger, universal_integer>(s),
            new GCBuiltinsGreaterEqual(),
            s);
}

void
00456 RegisterBuiltins::registerTypeOps(RecordType &type, SymbolTable &s)
{
      // relational operators
      // equality, inequality: any type except file and protected
      // FIXME builtins
      RegisterBuiltins::boolBinOp("=", type, NULL, NULL, s);
      RegisterBuiltins::boolBinOp("/=", type, NULL, NULL, s);
}

SubtypeIndication*
00466 RegisterBuiltins::generateSubtypeIndic(
      const TypeDeclaration &type
)
{
      SubtypeIndication *subtypeI = new SubtypeIndication(&type, 
                              Location("RegisterBuiltins."));
      return subtypeI;
}

ConstantDeclaration*
00476 RegisterBuiltins::generateArgument(
      const TypeDeclaration &type, 
      const SymbolTable &s
)
{
      SubtypeIndication *si = 
            RegisterBuiltins::generateSubtypeIndic(type);
      ConstantDeclaration *ret = new ConstantDeclaration(
                              new std::string("__anonymous__"),
                              NULL,       /* initializier */
                              si,   /* SubtypeIndication */
                              false,
                              type.location);
      return ret;
}

FunctionDeclaration*
00493 RegisterBuiltins::boolBinOp(
      const char *declName, 
      const TypeDeclaration &opType,
      BuiltinFunction *bf,
      GCBuiltins *gcBf,
      SymbolTable &s
)
{
      TypeDeclaration *ret = s.getStdStandardType("boolean");
      FunctionDeclaration *f = 
            RegisterBuiltins::binOp(declName, opType, opType, *ret, s);
      f->builtin = bf;
      f->gcBuiltin = gcBf;
      return f;
}

FunctionDeclaration*
00510 RegisterBuiltins::binOpSameType(
      const char *declName,
      const TypeDeclaration &opType,
      BuiltinFunction *bf,
      GCBuiltins *gcBf,
      SymbolTable &s
)
{
      FunctionDeclaration *f = 
            RegisterBuiltins::binOp(declName, opType, opType, opType, s);
      f->builtin = bf;
      f->gcBuiltin = gcBf;
      return f;
}

FunctionDeclaration*
00526 RegisterBuiltins::unOpSameType(
      const char *declName,
      const TypeDeclaration &opType,
      BuiltinFunction *bf,
      GCBuiltins *gcBf,
      SymbolTable &s
)
{
      std::string *n = new std::string(declName);
      std::list<ValDeclaration*> *args = new std::list<ValDeclaration*>();

      args->push_back(RegisterBuiltins::generateArgument(opType, s));

      FunctionDeclaration *ret = new FunctionDeclaration(
                  n,    // name of function
                  args,       // arguments
                  RegisterBuiltins::generateSubtypeIndic(opType),
                  true,       // is pure?
                  opType.location);

      ret->isBuiltin = true;
      ret->builtin = bf;
      ret->gcBuiltin = gcBf;
      
      s.registerSymbol(SYMBOL_FUNCTION, *ret);
      return ret;
}

FunctionDeclaration*
00555 RegisterBuiltins::binOp(
      const char *declName,
      const TypeDeclaration &left,
      const TypeDeclaration &right,
      const TypeDeclaration &returnT,
      SymbolTable &s
)
{
      std::list<ValDeclaration*> *args = new std::list<ValDeclaration*>();

      args->push_back(RegisterBuiltins::generateArgument(left, s));
      args->push_back(RegisterBuiltins::generateArgument(right, s));

      FunctionDeclaration *ret = new FunctionDeclaration(
                  new std::string(declName), // name of function
                  args,       // arguments
                  RegisterBuiltins::generateSubtypeIndic(returnT),
                  true,       // is pure?
                  returnT.location);
      ret->isBuiltin = true;

      s.registerSymbol(SYMBOL_FUNCTION, *ret);
      return ret;
}

FunctionDeclaration*
00581 RegisterBuiltins::binOp(
      const char *declName,
      const char *left,
      const TypeDeclaration &right,
      const TypeDeclaration &returnT,
      SymbolTable &s
)
{
      TypeDeclaration *l = s.getStdStandardType(left);
      return RegisterBuiltins::binOp(declName, *l, right, returnT, s);
}

FunctionDeclaration*
00594 RegisterBuiltins::binOp(
      const char *declName,
      const TypeDeclaration &left,
      const char *right,
      const TypeDeclaration &returnT,
      SymbolTable &s
)
{
      TypeDeclaration *r = s.getStdStandardType(right);
      return RegisterBuiltins::binOp(declName, left, *r, returnT, s);
}

bool
00607 RegisterBuiltins::isDiscreteType(const TypeDeclaration *type)
{
      // integer type or enumeration type.
      if (type == NULL) {
            return false;
      }

      const EnumerationType *et = 
            dynamic_cast<const EnumerationType*>(type);

      if (et != NULL) {
            return true;
      }

      const RangeConstraintType *rt = 
            dynamic_cast<const RangeConstraintType*>(type);
      
      if (rt == NULL) {
            return false;
      }

      switch(rt->baseType) {
      case BASE_TYPE_INTEGER:
            return true;
      case BASE_TYPE_REAL:
            return false;
      case BASE_TYPE_UNSET:
            return false;
      default:
            assert(false);
      }

      return false;
}

bool
00643 RegisterBuiltins::isBoolOrBit(const TypeDeclaration *type, SymbolTable &s)
{
      const TypeDeclaration *reference = s.getStdStandardType("boolean");
      
      if (reference == type) {
            return true;
      }

      reference = s.getStdStandardType("bit");
      if (reference == type) {
            return true;
      }

      return false;
}

void
00660 RegisterBuiltins::determineBaseType(RangeConstraintType &t, SymbolTable &s)
{
      ResolveTypes r = ResolveTypes(s);
      t.accept(r);
}

}; /* namespace ast */

Generated by  Doxygen 1.6.0   Back to index