Пример #1
0
data_type_t typecheck_expression(node_t* root)
{
	data_type_t toReturn;

	if(outputStage == 10)
		fprintf( stderr, "Type checking expression %s\n", root->expression_type.text);

	toReturn = te(root);
		
	//Insert additional checking here
	switch(root->expression_type.index)
	{
		case FUNC_CALL_E:
			/* check number of arguments */
			fprintf(stderr, "");	/*hack to avoid some wierd error */
			function_symbol_t *func = malloc(sizeof(function_symbol_t));
			func = function_get(root->children[0]->label);
			if(root->children[1] != NULL && func->nArguments != root->children[1]->n_children)
				type_error(root);
			else
				for(int i = 0; i < func->nArguments; i++)
					if(root->children[1] != NULL && !equal_types(func->argument_types[i], root->children[1]->children[i]->data_type))
						type_error(root);
			return func->return_type;
		break;
		
		case CLASS_FIELD_E: 	/* add code to compute the 
					 * type of class_field_access
					 * expressions
					 */
			return root->children[1]->data_type;
		break;
	}
}
Пример #2
0
data_type_t typecheck_assignment(node_t* root)
{
    data_type_t left  = root->children[0]->typecheck(root->children[0]);
    data_type_t right = root->children[1]->typecheck(root->children[1]);

    if (equal_types(left, right)) {
        return left;
    }
    type_error(root);
}
Пример #3
0
data_type_t typecheck_expression(node_t* root)
{
    data_type_t toReturn;

    if(outputStage == 10)
        fprintf( stderr, "Type checking expression %s\n", root->expression_type.text);

    toReturn = te(root);

    //Insert additional checking here

    if (root->expression_type.index == FUNC_CALL_E || root->expression_type.index == METH_CALL_E) {
        function_symbol_t *function_symbol = root->function_entry;
        node_t *argument_list = root->children[root->n_children-1];
        if (argument_list != NULL) {
            if (function_symbol->nArguments != argument_list->n_children) {
                type_error(root);
            }
            for (int i=0; i < argument_list->n_children; i++) {
                data_type_t param_type = argument_list->children[i]->data_type;
                if (param_type.base_type == NO_TYPE) {
                    param_type = argument_list->children[i]->typecheck(argument_list->children[i]);
                }
                if (!equal_types(
                            function_symbol->argument_types[i],
                            param_type
                        )) {
                    type_error(root);
                }
            }
        } else if (function_symbol->nArguments != 0) {
            type_error(root);
        }

        // Set return type on root node
        // so it can be checked easily from print statements
        root->data_type = root->function_entry->return_type;

        toReturn = function_symbol->return_type;
    } else if (root->expression_type.index == CLASS_FIELD_E) {
        data_type_t right = root->children[1]->typecheck(root->children[1]);
        root->children[1]->data_type = right;
        toReturn = right;
    }
    return toReturn;
}
Пример #4
0
data_type_t typecheck_assignment(node_t* root)
{
	data_type_t type1;
	data_type_t type2;
	type1 = root->children[0]->typecheck(root->children[0]);
	type2 = root->children[1]->typecheck(root->children[1]);
	if(type1.base_type == NO_TYPE)
		type1 = root->children[0]->entry->type;
	if(type2.base_type == NO_TYPE)
		type2 = root->children[1]->entry->type;
	
	else if(type1.base_type == CLASS_TYPE) /* class type is a special case where the class names needs to be equal */
		type2 = root->children[1]->data_type;
	
	if(!equal_types(type1, type2))
		type_error(root);
	
	return type1;
}
Пример #5
0
bool check_assignment(struct assignment *assignment, struct symtable *syms)
{
  if(assignment->e1->exprtype == identtype)
  {
    if(find_var(syms->variables,assignment->e1->val.ident) != NULL && 
        find_var(syms->variables,assignment->e1->val.ident)->constante)
    {
      error(assignment->pos, "assignment of read-only variable %s", assignment->e1->val.ident);
      return false;
    }
  }
  char *t1 = check_expr(assignment->e1, syms);
  char *t2 = check_expr(assignment->e2, syms);
  if (!t1 || !t2)
    return false;
  if (!equal_types(t1, t2, syms))
  {
    error(assignment->pos, "incompatible types: %s and %s.", t1, t2);
    return false;
  }
  return true;
}
Пример #6
0
char *check_expr(struct expr *e, struct symtable *syms)
{
  e->type = NULL;
  switch(e->exprtype)
  {
    case valtype:
      switch(e->val.val->valtype)
      {
        case nulltype:
          e->type = strdup("nul");
          break;
        case chartype:
          e->type = strdup(TYPE_CHAR);
          break;
        case stringtype:
          e->type = strdup(TYPE_STRING);
          break;
        case booltype:
          e->type = strdup(TYPE_BOOLEAN);
          break;
        case inttype:
          e->type = strdup(TYPE_INT);
          break;
        case realtype:
          e->type = strdup(TYPE_REAL);
          break;
      }
      break;
    case identtype:
      {
        struct var_sym *var = find_var(syms->variables, e->val.ident);
        if (var)
        {
          e->type = strdup(var->type->name);
          e->argref = var->argref;
        }
        else
          error(e->pos, "Use of undeclared variable %s", e->val.ident);
        break;
      }
    case funcalltype:
      {
        struct type *rettype;
        if (check_funcall(&e->val.funcall, syms, &rettype))
        {
          if (rettype)
            e->type = strdup(rettype->name);
          else
            error(e->pos, "cannot use a procedure as an expression");
        }
        break;
      }
    case binopexprtype:
      {
        char *t1 = check_expr(e->val.binopexpr.e1, syms);
        char *t2 = check_expr(e->val.binopexpr.e2, syms);
        if (!t1 || !t2)
          break;
        if (equal_types(t1, t2, syms))
        {
          if(e->val.binopexpr.op == EQ 
              || e->val.binopexpr.op == LT
              || e->val.binopexpr.op == GT
              || e->val.binopexpr.op == LE
              || e->val.binopexpr.op == NEQ
              || e->val.binopexpr.op == GE)
          {
            e->type = strdup(TYPE_BOOLEAN);
          }
          else
          {
            e->type = strdup(t1);
          }
        }
        else
          error(e->pos, "incompatible types: %s and %s", t1, t2);
        break;
      }

    case unopexprtype:
      {
        char *t1 = check_expr(e->val.unopexpr.e, syms);
        if(t1)
          e->type = strdup(t1);
        break;
      }

    case arrayexprtype:
      {
        char *tname = check_expr(e->val.arrayexpr.e1, syms);
        struct type *t = find_type(syms->types, tname);
        if (e->val.arrayexpr.indices.size != t->type_val.array_type->dims.size)
        {
          error(e->pos, "array has %d dimensions, not %d",
              t->type_val.array_type->dims.size,
              e->val.arrayexpr.indices.size);
        }
        else
        {
          for (unsigned i = 0; i < e->val.arrayexpr.indices.size; ++i)
          {
            char *tidx = check_expr(e->val.arrayexpr.indices.data[i], syms);
            if (strcmp(tidx, TYPE_INT) != 0)
              error(e->val.arrayexpr.indices.data[i]->pos, "index should be an integer");
          }
          e->type = strdup(t->type_val.array_type->type->name);
        }
      }
      break;

    case structelttype:
      {
        char *record = check_expr(e->val.structelt.record, syms);
        if (record)
        {
          struct type *t = find_type(syms->types, record);
          fieldlist_t fields = t->type_val.records_type->fields;
          unsigned i = 0;
          for (; i < fields.size; ++i)
          {
            if (equal_types(fields.data[i]->ident, e->val.structelt.field, syms))
            {
              e->type = strdup(fields.data[i]->type);
              break;
            }
          }
          if (i >= fields.size)
            error(e->val.structelt.record->pos,
                "field %s doesn't exist in this record type",
                e->val.structelt.field);
        }
        break;
      }

    case dereftype:
      {
        char *tname = check_expr(e->val.deref.e, syms);
        if (tname)
        {
          struct type *t = find_type(syms->types, tname);
          if (t->type_kind != pointer_t)
            error(e->pos, "expression is not a pointer, cannot be dereferenced");
          else
            e->type = strdup(t->type_val.pointer_type->type);
        }
        break;
      }
  }
  return e->type;
}
Пример #7
0
bool check_inst(struct instruction *i, struct type *ret, struct symtable *syms)
{
  switch(i->kind)
  {
    case funcall:
      {
        struct type *res;
        return check_funcall(i->instr.funcall, syms, &res);
      }

    case assignment:
      return check_assignment(i->instr.assignment, syms);

    case ifthenelse:
      {
        struct ifthenelse* e = i->instr.ifthenelse;

        char *t1 = check_expr(e->cond, syms);
        if (!t1)
          return false;
        if(strcmp(t1, TYPE_BOOLEAN) == 0)
        {
          for(unsigned int i =0; i < e->instructions.size; ++i)
          {
            if (!check_inst(list_nth(e->instructions, i), ret, syms))
            {
              return false;
            }
          }
          for(unsigned int i =0; i < e->elseblock.size; ++i)
          {
            if(!check_inst(list_nth(e->elseblock,i), ret, syms))
            {
              return false;
            }
          }
          return true;
        }

        error(e->cond->pos, "condition should be a boolean");
        return false;
      }

    case switchcase:
      {
        char *t1 = check_expr(i->instr.switchcase->cond, syms);
        if(!t1)
          return false;
        for(unsigned int l = 0; l < i->instr.switchcase->caseblocklist.size; ++l)
        {
          for( unsigned int j = 0; j < i->instr.switchcase->caseblocklist.data[l]->exprlist.size; ++j)
          {
            char *t2 =
              check_expr(i->instr.switchcase->caseblocklist.data[l]->exprlist.data[j],
                  syms);
            if(!t2)
              return false;
            if (!equal_types(t1, t2, syms))
            {
              error(i->instr.switchcase->cond->pos,
                  "different types between switch and case\n");
              return false;
            }
          }
          for(int unsigned k = 0;
              k < i->instr.switchcase->caseblocklist.data[l]->instructions.size; ++k)
          {
            if(!check_inst(i->instr.switchcase->caseblocklist.data[l]->instructions.data[k], ret, syms))
              return false;
          }

        }
        for(unsigned int l = 0; l < i->instr.switchcase->otherwiseblock.size; ++l)
        {
          if(!check_inst(i->instr.switchcase->otherwiseblock.data[l], ret, syms))
            return false;

        }
        return true;
        break;
      }

    case dowhile:
      {
        struct dowhile* e = i->instr.dowhile;
        char *t = check_expr(e->cond, syms);
        if(strcmp(t, TYPE_BOOLEAN) == 0)
        {
          for(unsigned int i = 0; i < e->instructions.size; ++i)
          {
            if(!check_inst(list_nth(e->instructions,i), ret, syms))
              return false;
          }
          return true;
        }
        error(e->cond->pos, "condition should be a boolean");
        return false;
      }
      break;

    case whiledo:
      {
        struct whiledo* e = i->instr.whiledo;
        if(strcmp(check_expr(e->cond, syms), TYPE_BOOLEAN) == 0)
        {
          for(unsigned int i = 0; i < e->instructions.size; ++i)
            if(!check_inst(list_nth(e->instructions,i), ret, syms))
              return false;
          return true;
        }
        error(e->cond->pos, "condition should be a boolean");
        return false;
      }
      break;

    case forloop:
      {
        struct forloop* e = i->instr.forloop;
        char *upto_type = check_expr(e->upto, syms);
        if(upto_type && check_assignment(e->assignment, syms))
        {
          if (strcmp(upto_type, TYPE_INT) != 0)
          {
            error(e->upto->pos, "expected int expression");
            return false;
          }
          else if (strcmp(e->assignment->e1->type, TYPE_INT) != 0)
          {
            error(e->assignment->e1->pos, "expected int expression");
            return false;
          }
          else if (strcmp(e->assignment->e2->type, TYPE_INT) != 0)
          {
            error(e->assignment->e2->pos, "expected int expression");
            return false;
          }
          else
          {
            for(unsigned int i = 0; i < e->instructions.size; ++i)
              if(!check_inst(list_nth(e->instructions, i), ret, syms))
                return false;
            return true;
          }
        }
        return false;
      }
      break;

    case returnstmt:
      {
        if (!ret)
        {
          error(i->instr.returnstmt->expr->pos,
              "algorithm is a procedure, no return statement expected");
          return false;
        }
        char *t = check_expr(i->instr.returnstmt->expr, syms);
        if (!t)
          return false;
        if(equal_types(t, ret->name, syms))
          return true;
        error(i->instr.returnstmt->expr->pos, "expected type %s, not %s", ret->name, t);
        return false;
      }
  }
  return false;

}
Пример #8
0
bool check_funcall(struct funcall *f, struct symtable *syms, struct type **res)
{
  if (strcmp(f->fun_ident, "allouer") == 0)
  {
    if (f->args.size == 1)
    {
      if(!check_expr(f->args.data[0]->e, syms))
      {
        *res = NULL;
        return false;
      }
    }
    *res = NULL;
    return true;
  }

  else if (((strcmp(f->fun_ident, "ecrire") == 0) && current_lang == LANG_FR) ||
           ((strcmp(f->fun_ident, "write") == 0) && current_lang == LANG_EN))
  {
    for (unsigned i = 0; i < f->args.size; ++i)
    {
      if (!check_expr(f->args.data[i]->e, syms))
      {
        *res = NULL;
        return false;
      }
    }
    *res = NULL;
    return true;
  }
  else if (strcmp(f->fun_ident, "lire") == 0)
  {
      if(f->args.size != 1 
          && f->args.data[0]->e->exprtype != identtype 
          && !find_var(syms->variables, f->args.data[0]->e->val.ident))
      {
        *res = NULL;
       return false;
      }
      f->args.data[0]->e->type = strdup(find_var(
            syms->variables, f->args.data[0]->e->val.ident)->type->name);
      *res = NULL;
      return true;
  }
  else if (strcmp(f->fun_ident, "liberer") == 0)
  {
    if (f->args.size == 1)
    {
      if (!check_expr(f->args.data[0]->e, syms))
      {
        *res = NULL;
        return false;
      }
      *res = NULL;
      return true;
    }
    else
    {
      error(f->pos, "liberer expects one argument, not %d", f->args.size);
      *res = NULL;
      return false;
    }
  }

  struct function *proto = get_function(syms->functions, f->fun_ident);
  if (!proto)
  {
    error(f->pos, "implicit declaration of function %s", f->fun_ident);
    *res = NULL;
    return false;
  }
  else if (proto->arg.size != f->args.size)
  {
    error(f->pos, "function %s expects %d arguments but %d were given",
        f->fun_ident, proto->arg.size, f->args.size);
    *res = NULL;
    return false;
  }
  else
  {
    bool ok = true;
    for (unsigned i = 0; i < proto->arg.size; ++i)
    {
      char *argtype = check_expr(f->args.data[i]->e, syms);
      if (argtype)
      {
        if (!equal_types(proto->arg.data[i]->type->name, argtype, syms))
        {
          error(f->pos,
              "wrong type for argument %d in function %s", i + 1, f->fun_ident);
          ok = false;
        }
        else if (proto->arg.data[i]->global)
        {
          if (f->args.data[i]->e->exprtype == valtype)
          {
            error(f->args.data[i]->e->pos,
                "cannot pass a value as a global parameter");
            ok = false;
          }
          else
            f->args.data[i]->global = true;
        }
      }
    }
    if (ok)
      *res = proto->ret;
  }
  return true;
}
Пример #9
0
bool check_const(struct const_decl* cons, struct symtable* syms, bool global)
{
  struct var_sym *var_sym = find_var(syms->variables, cons->ident);
  if (var_sym && !var_sym->global)
  {
    error(cons->pos, "conflicting name: %s", cons->ident);
    return false;
  }
  struct var_sym* sym = malloc(sizeof(struct var_sym));
  switch(cons->val->valtype)
  {
    case nulltype:
      sym->type = malloc(sizeof(struct pointer));
      sym->type->type_kind = pointer_t;
      sym->type->name = strdup("nul");
      break;
    case chartype:
      if(equal_types(cons->type,TYPE_CHAR,syms))
        sym->type = find_type(syms->types, TYPE_CHAR);
      else
      {
        error(cons->pos,"incompatible type : %s and TYPE_CHAR", cons->type);
        return false;
      }
      break;
    case stringtype:
      if(equal_types(cons->type,TYPE_STRING,syms))
        sym->type = find_type(syms->types, TYPE_STRING);
      else
      {
        error(cons->pos,"incompatible type : %s and chaine", cons->type);
        return false;
      }
      break;
    case inttype:
      if(equal_types(cons->type,TYPE_INT,syms))
        sym->type = find_type(syms->types, TYPE_INT);
      else
      {
        error(cons->pos,"incompatible type : %s and entier", cons->type);
        return false;
      }
      break;
    case realtype:
      if(equal_types(cons->type,TYPE_REAL,syms))
        sym->type = find_type(syms->types, TYPE_REAL);
      else
      {
        error(cons->pos,"incompatible type : %s and reel", cons->type);
        return false;
      }
      break;
    case booltype:
      if(equal_types(cons->type,TYPE_BOOLEAN,syms))
        sym->type = find_type(syms->types, TYPE_BOOLEAN);
      else
      {
        error(cons->pos,"incompatible type : %s and booleen", cons->type);
        return false;
      }
      break;
  }
  sym->ident = cons->ident;
  sym->argref = false;
  sym->global = global;
  sym->constante = true;
  add_var(syms->variables, sym);
  return true;
}
Пример #10
0
bool add_types(struct symtable *syms, typedecllist_t typelist)
{
  bool correct = true;
  for(unsigned i = 0; i < typelist.size; ++i)
  {
    struct type_decl* type_decl = list_nth(typelist, i);
    struct type_def*  type_def  = type_decl->type_def;
    struct type* type = malloc(sizeof(struct type));
    type->name = strdup(type_decl->ident);
    switch(type_def->type_type)
    {
      case enum_type:
        {
          type->type_kind = enum_t;
          struct enum_type* _enum = malloc(sizeof(struct enum_type));
          _enum->idents = type_def->def.enum_def->identlist;
          type->type_val.enum_type = _enum;
          add_type(syms->types, type);
        }
        break;
      case array_type:
        {
          type->type_kind = array_t;

          struct array* array = malloc(sizeof(struct array));
          if((array->type = find_type(syms->types, type_def->def.array_def->elt_type))
              == NULL)
          {
            error(type_def->pos, "Unknown type");
            correct = false;
          }
          for(unsigned int i = 0; i < type_def->def.array_def->dims.size; ++i)
          {
            struct expr * dim = type_def->def.array_def->dims.data[i];
            if (!check_expr(dim, syms))
              break;
            switch(dim->exprtype)
            {
              case valtype:
                if(dim->val.val->valtype != inttype)
                {
                  error(type_def->pos, "dimension is not an integer");
                  correct = false;
                }
                break;
              case identtype:
                if(!equal_types(find_var(syms->variables, dim->val.ident)->type->name, TYPE_INT, syms))
                {
                  error(dim->pos, "identifier \"%s\" is not an integer", dim->val.ident);
                  correct = false;
                  break;
                }
                if(find_var(syms->variables, dim->val.ident)->type == NULL)
                {
                  error(type_def->pos, "identifier is undeclared");
                  correct = false;
                  break;
                }
                if(!find_var(syms->variables, dim->val.ident)->constante)
                {
                  error(type_def->pos, "identifier is not a constante");
                  correct = false;
                }
                break;
              default:
                error(type_def->pos, "array type is not an int or an indentifier");
                correct = false;

            }

          }
          array->dims = type_def->def.array_def->dims;
          /* list_init(array->dims); */
          /* for (unsigned i = 0; i < type_def->def.array_def->dims.size; ++i) */
          /* { */
          /*   list_push_back(array->dims, */
          /*       type_def->def.array_def->dims.data[i]); */
          /* } */
          type->type_val.array_type = array;
          add_type(syms->types, type);
        }
        break;
      case struct_type:
        {
          type->type_kind = records_t;

          struct records* record = malloc(sizeof(struct records));
          fieldlist_t fields;
          list_init(fields);

          vardecllist_t varlist = type_def->def.record_def->var_decl;

          for(unsigned int i = 0 ; i < varlist.size; ++i)
          {
            struct single_var_decl* var = list_nth(varlist, i);

            for(unsigned int j = 0; j < var->var_idents.size; ++j)
            {
              if (!find_type(syms->types, var->type_ident))
              {
                error(var->pos, "type %s doesn't exist", var->type_ident);
                correct = false;
              }
              else
              {
                struct field* field = malloc(sizeof(struct field));
                field->ident = strdup(list_nth(var->var_idents,j));
                field->type = strdup(var->type_ident);
                list_push_back(fields, field);
              }
            }
          }
          record->fields = fields;
          type->type_val.records_type = record;
          add_type(syms->types, type);
        }
        break;
      case pointer_type:
        {
          type->type_kind = pointer_t;
          type->type_val.pointer_type = malloc(sizeof(struct pointer));
          char *pointed_type = 
            type_decl->type_def->def.pointer_def->pointed_type_ident;;
          bool pointed_type_exists = false;
          if (strcmp(pointed_type, TYPE_INT) == 0
              || strcmp(pointed_type, TYPE_BOOLEAN) == 0
              || strcmp(pointed_type, TYPE_STRING) == 0
              || strcmp(pointed_type, TYPE_REAL) == 0
              || strcmp(pointed_type, TYPE_CHAR) == 0)
            pointed_type_exists = true;
          for(unsigned i = 0; i < typelist.size && !pointed_type_exists; ++i)
          {
            if (strcmp(typelist.data[i]->ident, pointed_type) == 0)
            {
              pointed_type_exists = true;
              break;
            }
          }
          if (pointed_type_exists)
          {
            type->type_val.pointer_type->type = strdup(pointed_type);
            add_type(syms->types, type);
          }
          else
          {
            error(type_decl->pos, "pointed type does not exist");
            correct = false;
          }
        }
        break;
    }
  }
  return correct;
}