Beispiel #1
0
Type Semantic::expType(Exp * e) {
  if (e->v == Exp::ICONST_T) {
    return Type(Type::INT_T);
  }
  else if (e->v == Exp::STRLIT_T) {
    return Type(Type::STRING_T);
  }
  else if (e->v == Exp::CHRLIT_T) {
    return Type(Type::CHAR_T);
  }
  else if (e->v == Exp::BOLLIT_T) {
    return Type(Type::BOOL_T);
  }
  else if (e->v == Exp::NULL_T) {
    //return NULL??
    return Type(Type::VOID_T);
  }
  else if (e->v == Exp::ID_T) {
    return *getSym(e->id).type;
  }
  else if (e->v == Exp::UNOP_T) {
    if (e->id == "~" || e->id == "!") {
      return Type(Type::BOOL_T);
    }
    else if (e->id == "++" || e->id == "--") {
      return Type(Type::INT_T);
    }
    else if (e->id == "-") {
      return expType(e->l);
      //return *getSym(e->l->id).type;
    }
  }
  else if (e->v == Exp::BINOP_T) {
    if (e->id == "<" || e->id == ">" || e->id == "<=" || e->id == ">=" || e->id == "!=" || e->id == "==" 
	|| e->id == "&" || e->id == "^" || e->id == "|" || e->id == "&&" || e->id == "||") {
      return Type(Type::BOOL_T);
    }
    else if (e->id == "+" || e->id == "*" || e->id == "-" || e->id == "/" || e->id == "%") {
      return Type(Type::INT_T);
    }
  }
  else if (e->v == Exp::IFLINE_T) {
    return Type(Type::VOID_T);
  }
  else if (e->v == Exp::FCALL_T) {
    return Type(Type::INT_T);
    //return *getSym(e->id).type;
  }
  else if (e->v == Exp::ACC_T || e->v == Exp::DOT_T) {
    return *getSym(e->id).type;
  }
  else if (e->v == Exp::SUBSC_T) {
    return Type(Type::VECTOR_T);
  }
  else if (e->v == Exp::ALLOC_T || e->v == Exp::ALLOCARRAY_T) {
    return Type(Type::POINTER_T);
  }

  throw std::runtime_error("Expression is not of any desired type.");
}
Beispiel #2
0
Datei: PROCS.C Projekt: 8l/dcc
void adjustActArgType (COND_EXPR *exp, hlType forType, PPROC pproc)
/* Checks to determine whether the expression (actual argument) has the
 * same type as the given type (from the procedure's formal list).  If not,
 * the actual argument gets modified */
{ hlType actType;
  Int offset, offL, size;

	if (exp == NULL)
		return;

	actType = expType (exp, pproc);
	if ((actType != forType) && (exp->type == IDENTIFIER))
	{
		switch (forType) {
		  case TYPE_UNKNOWN: case TYPE_BYTE_SIGN:
		  case TYPE_BYTE_UNSIGN: case TYPE_WORD_SIGN:
		  case TYPE_WORD_UNSIGN: case TYPE_LONG_SIGN:
		  case TYPE_LONG_UNSIGN: case TYPE_RECORD:
				break;

		  case TYPE_PTR:
		  case TYPE_CONST:
				break;

		  case TYPE_STR:
				switch (actType) {
				  case TYPE_CONST:
					/* It's an offset into image where a string is
					 * found.  Point to the string.	*/
					offL = exp->expr.ident.idNode.kte.kte;
					if (prog.fCOM)
						offset = (pproc->state.r[rDS]<<4) + offL + 0x100;
					else
						offset = (pproc->state.r[rDS]<<4) + offL;
					exp->expr.ident.idNode.strIdx = offset;
					exp->expr.ident.idType = STRING;
					break;

				  case TYPE_PTR:
					/* It's a pointer to a char rather than a pointer to 
					 * an integer */
					/***HERE - modify the type ****/
					break;

				  case TYPE_WORD_SIGN:

					break;
				} /* eos */
				break;
		}
	}
}
Beispiel #3
0
void Semantic::traverse(Exp * cur) {
  if (cur->v == Exp::ICONST_T || cur->v == Exp::STRLIT_T ||
      cur->v == Exp::CHRLIT_T || cur->v == Exp::BOLLIT_T ||
      cur->v == Exp::NULL_T) {
    //we're dealing with a constant here, ensure int constant in 0 2^31
    if (cur->v == Exp::ICONST_T)
      if (cur->id.length() == std::string("2147483647").length() && cur->id > "2147483647")
	error("integer literal constants must be < 2^31");
  }
  else if (cur->v == Exp::ID_T) {
    //variable
    getSym(cur->id);
  }
  else if (cur->v == Exp::UNOP_T) {
    //ensure subexp type is char or int
    Type l = expType(cur->l);
    if (!(sameType(l, Type(Type::INT_T)) || sameType(l, Type(Type::CHAR_T)) || sameType(l, Type(Type::BOOL_T))))
      error("unop must be applied to expression of type int or char");
    traverse(cur->l);
  }
  else if (cur->v == Exp::BINOP_T) {
    //if <=, <, >, >= ensure int or char
    //if != or == ensure int bool char t[] or t*
    Type l = expType(cur->l), r = expType(cur->r);
    if (cur->id == "==" || cur->id == "!=");
      
    if (!(sameType(l, Type(Type::INT_T)) || sameType(l, Type(Type::CHAR_T)) || sameType(l, Type(Type::BOOL_T))))
      error("binop must be applied to expression of type int or char or bool");
    else if (!(sameType(r, Type(Type::INT_T)) || sameType(r, Type(Type::CHAR_T)) || sameType(r, Type(Type::BOOL_T))))
      error("binop must be applied to expression of type int or char or bool");
    traverse(cur->l);
    traverse(cur->r);
  }
  else if (cur->v == Exp::IFLINE_T) {
    Type l = expType(cur->l);
    if (!(sameType(l, Type(Type::INT_T)) || sameType(l, Type(Type::CHAR_T)) || sameType(l, Type(Type::BOOL_T))))
      error("Condition must be of type bool");
    traverse(cur->l);
    traverse(cur->m);
    traverse(cur->r);
  }
  else if (cur->v == Exp::FCALL_T) {
    if (cur->id == "print" || cur->id == "read_int") return;
    
    Symbol func = getSym(cur->id);
    if (func.decl == NULL && func.defn == NULL) {
      error("call to undeclared function " + cur->id);
      return;
    }
    ArgItem * ptr = (func.decl != NULL) ? func.decl->list : func.defn->args;
    ExpItem * old = cur->args;
    while (ptr != NULL) {
      if (old == NULL) {
	error("bad argument passed to function " + cur->id);
	break;
      }

      if (!sameType(*(ptr->arg->type), expType(old->exp))) {
	error("bad argument passed to function " + cur->id);
	break;
      }
      traverse(old->exp);
      ptr = ptr->next;
      old = old->next;
    }
    if (old != NULL)
      error("bad argument passed to function " + cur->id);
  }
  else if (cur->v == Exp::DOT_T) {
    //see if type has that field
    Type t = expType(cur->l);
    if (t.v != Type::STRUCT_T)
      error("accessing field in a non-struct type");
    Symbol s = getFromMap(sid, t.str);
    bool hasField = false;
    ArgItem * ptr = s.defn->args;
    while (ptr != NULL) {
      if (ptr->arg->ID == cur->id) {
	hasField = true;
	break;
      }
      ptr = ptr->next;
    }
    if (!hasField)
      error("accessing non existing struct field " + cur->id);
  }
  else if (cur->v == Exp::ACC_T) {
    //see if type has that field
    Type t = expType(cur->l);
    if (t.v != Type::POINTER_T || t.type->v != Type::STRUCT_T)
      error("referencing field in a pointer to struct type");
    Symbol s = getFromMap(sid, t.type->str);
    bool hasField = false;
    ArgItem * ptr = s.defn->args;
    while (ptr != NULL) {
      if (ptr->arg->ID == cur->id) {
	hasField = true;
	break;
      }
      ptr = ptr->next;
    }
    if (!hasField)
      error("referencing non existing struct field " + cur->id);
  }
  else if (cur->v == Exp::SUBSC_T) {
    //see if subst is char or int and other type is vector
    Type l = expType(cur->l);
    Type r = expType(cur->r);
    if (l.v != Type::VECTOR_T)
      error("accessing index in non-vector type");
    if (!(sameType(r, Type(Type::INT_T)) || sameType(r, Type(Type::CHAR_T)) || sameType(r, Type(Type::BOOL_T))))
      error("index type must be int or char");
    traverse(cur->l);
    traverse(cur->r);
  }
  else if (cur->v == Exp::ALLOC_T) {
    //return the little thing allocated in memory (heap?)
    if (cur->t->v != Type::STRUCT_T)
      error("cannot alloc non-struct type");
  }
  else if (cur->v == Exp::ALLOCARRAY_T) {
    //return the little thing[] allocated in memory (heap?)
    Type r = expType(cur->l);
    if (!(sameType(r, Type(Type::INT_T)) || sameType(r, Type(Type::CHAR_T)) || sameType(r, Type(Type::BOOL_T))))
      error("alloc_array size must be type int");
    traverse(cur->l);
  }
}
Beispiel #4
0
void Semantic::traverse(Stmt * cur) {
  if (cur->v == Stmt::LIST_T) {
    pushScope();
    traverse(cur->list);
    popScope();
  }
  else if (cur->v == Stmt::IF_T || cur->v == Stmt::WHILE_T) {
    if (cur->v == Stmt::WHILE_T) loops.push(cur);
    Type t = expType(cur->exp);
    traverse(cur->exp);
    if (t.v == Type::INT_T || t.v == Type::CHAR_T) {
      //warning
      pushScope();
      traverse(cur->left);
      popScope();
    }
    else if (t.v == Type::BOOL_T) {
      pushScope();
      traverse(cur->left);
      popScope();
    }
    else
      error("Condition must be of type bool");
    if (cur->v == Stmt::WHILE_T) loops.pop();
  }
  else if (cur->v == Stmt::FOR_T) {
    loops.push(cur);
    pushScope();
    traverse(cur->left);
    Type t = expType(cur->exp);
    traverse(cur->exp);
    if (t.v == Type::INT_T || t.v == Type::CHAR_T) {
      //warning
      pushScope();
      traverse(cur->stmt);
      popScope();
    }
    else if (t.v == Type::BOOL_T) {
      pushScope();
      traverse(cur->stmt);
      popScope();
    }
    else
      error("Condition must be of type bool");
    if (hasDecl(cur->right))
      error("For loop-end statement must not include declarations");
    traverse(cur->right);
    popScope();
    loops.pop();
  }
  else if (cur->v == Stmt::RETURN_T) {
    //check current function return type and compare it with this
    if (!sameType(expType(cur->exp), *getSym(curF).defn->type))
      error("return expression type differs from function " + curF + " signature");
    if (cur->exp != NULL)
      traverse(cur->exp);
  }
  else if (cur->v == Stmt::ASSERT_T) {
    //check argument type to be of bool
    if (!sameType(expType(cur->exp), Type(Type::BOOL_T)))
      error("assert expression type must be bool");
    traverse(cur->exp);
  }
  else if (cur->v == Stmt::ERROR_T) {
    //call error function with argment string
    if (!sameType(expType(cur->exp), Type(Type::STRING_T)))
      error("error argument must be of type string");
    traverse(cur->exp);
  }
  else if (cur->v == Stmt::ASSIGN_T) {
    //check if lhs and rhs same type, ensure rhs and lhs is not a struct
    Type l = lvalType(cur->lval), r = expType(cur->exp);
    traverse(cur->exp);
    
    if (cur->op == "=") {
      if (!sameType(l, r))
	error("lval and expression have different types");
    }
    else if (cur->op == ">>=") {
      if (!(sameType(l, Type(Type::INT_T)) || sameType(l, Type(Type::CHAR_T))))
	error("lval from right shift must be of type int or char");
      if (!sameType(r, Type(Type::INT_T)))
	error("shift ammount must be of type int");
    }
    else if (cur->op == "<<=") {
      if (!(sameType(l, Type(Type::INT_T)) || sameType(l, Type(Type::CHAR_T))))
	error("lval from left shift must be of type int or char");
      if (!sameType(r, Type(Type::INT_T)))
	error("shift ammount must be of type int");
    }
    else if (cur->op == "+=") {
      if (!(sameType(l, Type(Type::INT_T)) || sameType(l, Type(Type::CHAR_T))))
	error("lval from add assign must be of type int or char");
      if (!(sameType(r, Type(Type::INT_T)) || sameType(r, Type(Type::CHAR_T))))
	error("expression from add assign must be of type int or char");
    }
    else if (cur->op == "-=") {
      if (!(sameType(l, Type(Type::INT_T)) || sameType(l, Type(Type::CHAR_T))))
	error("lval from sub assign must be of type int or char");
      if (!(sameType(r, Type(Type::INT_T)) || sameType(r, Type(Type::CHAR_T))))
	error("expression from sub assign must be of type int or char");
    }
    else if (cur->op == "*=") {
      if (!(sameType(l, Type(Type::INT_T)) || sameType(l, Type(Type::CHAR_T))))
	error("lval from mul assign must be of type int or char");
      if (!(sameType(r, Type(Type::INT_T)) || sameType(r, Type(Type::CHAR_T))))
	error("expression from mul assign must be of type int or char");
    }
    else if (cur->op == "/=") {
      if (!(sameType(l, Type(Type::INT_T)) || sameType(l, Type(Type::CHAR_T))))
	error("lval from div assign must be of type int or char");
      if (!(sameType(r, Type(Type::INT_T)) || sameType(r, Type(Type::CHAR_T))))
	error("expression from div assign must be of type int or char");
    }
    else if (cur->op == "%=") {
      if (!(sameType(l, Type(Type::INT_T)) || sameType(l, Type(Type::CHAR_T))))
	error("lval from mod assign must be of type int or char");
      if (!(sameType(r, Type(Type::INT_T)) || sameType(r, Type(Type::CHAR_T))))
	error("expression from mod assign must be of type int or char");
    }
    else if (cur->op == "&=") {
      if (!(sameType(l, Type(Type::INT_T)) || sameType(l, Type(Type::CHAR_T)) || sameType(l, Type(Type::BOOL_T))))
	error("lval from and assign must be of type int or char or bool");
      if (!(sameType(r, Type(Type::INT_T)) || sameType(r, Type(Type::CHAR_T)) || sameType(r, Type(Type::BOOL_T))))
	error("expression from and assign must be of type int or char or bool");
    }
    else if (cur->op == "^=") {
      if (!(sameType(l, Type(Type::INT_T)) || sameType(l, Type(Type::CHAR_T)) || sameType(l, Type(Type::BOOL_T))))
	error("lval from xor assign must be of type int or char or bool");
      if (!(sameType(r, Type(Type::INT_T)) || sameType(r, Type(Type::CHAR_T)) || sameType(r, Type(Type::BOOL_T))))
	error("expression from xor assign must be of type int or char or bool");
    }
    else if (cur->op == "|=") {
      if (!(sameType(l, Type(Type::INT_T)) || sameType(l, Type(Type::CHAR_T)) || sameType(l, Type(Type::BOOL_T))))
	error("lval from or assign must be of type int or char or bool");
      if (!(sameType(r, Type(Type::INT_T)) || sameType(r, Type(Type::CHAR_T)) || sameType(r, Type(Type::BOOL_T))))
	error("expression from or assign must be of type int or char or bool");
    }
  }
  else if (cur->v == Stmt::INC_T) {
    //check if lhs is int or char
    Type l = lvalType(cur->lval);
    if (!(sameType(l, Type(Type::INT_T)) || sameType(l, Type(Type::CHAR_T))))
      error("lval from increment must be of type int or char");
    
  }
  else if (cur->v == Stmt::DEC_T) {
    //check if lhs is int or char
    Type l = lvalType(cur->lval);
    if (!(sameType(l, Type(Type::INT_T)) || sameType(l, Type(Type::CHAR_T))))
      error("lval from decrement must be of type int or char");
    
  }
  else if (cur->v == Stmt::EXP_T) {
    traverse(cur->exp);
  }
  else if (cur->v == Stmt::DECL_T) {
    //declaring a variable
    newSym(vid.back(), Symbol(cur->arg->ID, cur->arg->type));
  }
  else if (cur->v == Stmt::DECLI_T) {
    //declaring and assigning a variable
    newSym(vid.back(), Symbol(cur->arg->ID, cur->arg->type));
  }
  else if (cur->v == Stmt::BREAK_T) {
    //check most recent loop
    if (loops.empty())
      error("break statement does not have a loop");
  }
  else if (cur->v == Stmt::CONT_T) {
    if (loops.empty())
      error("continue statement does not have a loop");
  }
}