コード例 #1
0
ファイル: SelectorValue.cpp プロジェクト: astitcher/selectors
inline void promoteNumeric(Value& v1, Value& v2)
{
    if (!numeric(v1) || !numeric(v2)) return;
    if (sameType(v1,v2)) return;
    switch (v1.type) {
    case Value::T_INEXACT: v2 = double(v2.i); return;
    case Value::T_EXACT:   v1 = double(v1.i); return;
    default:               assert(false);
    }
}
コード例 #2
0
ファイル: SelectorValue.cpp プロジェクト: astitcher/selectors
bool operator!=(Value v1, Value v2)
{
    promoteNumeric(v1, v2);
    if (!sameType(v1,v2)) return false;

    switch (v1.type) {
    case Value::T_BOOL:    return  v1.b != v2.b;
    case Value::T_STRING:  return *v1.s != *v2.s;
    case Value::T_EXACT:   return  v1.i != v2.i;
    case Value::T_INEXACT: return  v1.x != v2.x;
    default:               return false;
    }
}
コード例 #3
0
ファイル: semantic.cpp プロジェクト: miguel-ferreira/czero
bool Semantic::sameType(Type l, Type r) {
  return sameType(&l, &r);
}
コード例 #4
0
ファイル: semantic.cpp プロジェクト: miguel-ferreira/czero
void Semantic::newSym(Symbol::Map &map, Symbol s) {
  if (s.stype == Symbol::FUNC || s.stype == Symbol::VAR) {
    if (map.find(s.id) != map.end())
      if (s.stype != map[s.id].stype)
	error("multiple definition of symbol " + s.id);
    if (aid.find(s.id) != aid.end())
      error("symbol name collides with type " + s.id);
    
    if (s.stype == Symbol::FUNC) {
      if (s.decl != NULL) {
	if (map[s.id].decl != NULL) {
	  if (!sameType(s.decl->type, map[s.id].decl->type))
	    error("inconsistent declaration of function " + s.id);
	  else {
	    ArgItem * ptr = s.decl->list;
	    ArgItem * old = map[s.id].decl->list;
	    while (ptr != NULL) {
	      if (old == NULL) {
		error("inconsistent declaration of function " + s.id);
		break;
	      }
	      
	      if (!sameType(ptr->arg->type, old->arg->type)) {
		error("inconsistent declaration of function " + s.id);
		break;
	      }
	      
	      ptr = ptr->next;
	      old = old->next;
	    }
	    if (old != NULL)
	      error("inconsistent declaration of function " + s.id);
	  }
	}
	else {
	  if (map[s.id].defn != NULL) {	    
	    if (!sameType(s.decl->type, map[s.id].defn->type))
	      error("inconsistent declaration of function " + s.id);
	    else {
	      ArgItem * ptr = s.decl->list;
	      ArgItem * old = map[s.id].defn->args;
	      while (ptr != NULL) {
		if (old == NULL) {
		  error("inconsistent declaration of function " + s.id);
		  break;
		}
		
		if (!sameType(ptr->arg->type, old->arg->type)) {
		  error("inconsistent declaration of function " + s.id);
		  break;
		}
		
		ptr = ptr->next;
		old = old->next;
	      }
	      if (old != NULL)
		error("inconsistent declaration of function " + s.id);
	    }
	  }
	  map[s.id] = s;
	}
      }
      else if (s.defn != NULL) {	
	if (map[s.id].defn != NULL)
	  error("multiple definition of function " + s.id);
	else {
	  map[s.id] = s;
	  if (map[s.id].decl != NULL) {
	    if (!sameType(s.defn->type, map[s.id].decl->type))
	      error("inconsistent definition of function " + s.id);
	    else {
	      ArgItem * ptr = s.defn->args;
	      ArgItem * old = map[s.id].decl->list;
	      while (ptr != NULL) {
		if (old == NULL) {
		  error("inconsistent definition of function " + s.id);
		  break;
		}
		
		if (!sameType(ptr->arg->type, old->arg->type)) {
		  error("inconsistent definition of function " + s.id);
		  break;
		}
		
		ptr = ptr->next;
		old = old->next;
	      }
	      if (old != NULL)
		error("inconsistent definition of function " + s.id);
	    }
	  }
	  map[s.id].defn = s.defn;
	}
      }
    }
    else if (s.stype == Symbol::VAR)
      map[s.id] = s;
  }
  else if (s.stype == Symbol::TYPE) {    
    if (map.find(s.id) != map.end())
      error("redeclaration of type " + s.id);
    for (auto it : vid)
      if (it.find(s.id) != it.end())
	error("type name collides with symbol " + s.id);

    if (map.find(s.id) == map.end())
      map[s.id] = s;
  }
  else if (s.stype == Symbol::STRCT) {
    if (s.defn != NULL && map.find(s.id) != map.end()
	&& map[s.id].defn != NULL)
      error("redefinition of struct " + s.id);
    if ((s.decl != NULL && map.find(s.id) == map.end())
	|| s.defn != NULL)
      map[s.id] = s;
  }
}
コード例 #5
0
ファイル: semantic.cpp プロジェクト: miguel-ferreira/czero
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);
  }
}
コード例 #6
0
ファイル: semantic.cpp プロジェクト: miguel-ferreira/czero
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");
  }
}