Commit 8bef2630 authored by Bednárek David RNDr. Ph.D.'s avatar Bednárek David RNDr. Ph.D.
Browse files

framework reports duplicate definitions and prohibits invalid types

additional error message types
parent cedcf32f
......@@ -22,6 +22,11 @@ namespace cecko {
err_def_s UNCHAR{ "Unknown character '", "'" };
err_def_s NOFILE{ "Unable to open input file \"", "\"" };
err_def_s UNDEF_IDF{ "Undefined identifier \"", "\"" };
err_def_s DUPLICATE_IDF{ "Identifier \"", "\" was already declared in this scope" };
err_def_s DUPLICATE_TAG{ "Tag \"", "\" was already declared as another kind in this scope" };
err_def_s DUPLICATE_FUNCTION_DEFINITION{ "Function \"", "\" was already defined" };
err_def_s DUPLICATE_STRUCT_DEFINITION{ "Struct \"", "\" was already defined" };
err_def_s DUPLICATE_ENUM_DEFINITION{ "Enum \"", "\" was already defined" };
err_def_n INTERNAL{ "INTERNAL ERROR" };
err_def_n EMPTYCHAR{ "Empty character" };
......@@ -37,6 +42,9 @@ namespace cecko {
err_def_n NOT_POINTER{ "Expression is not a pointer" };
err_def_n NOT_NUMBER_OR_POINTER{ "Expression is not a number or pointer" };
err_def_n INCOMPATIBLE{ "Incompatible operand(s)" };
err_def_n INVALID_FUNCTION_TYPE{ "Invalid function type constructed" };
err_def_n INVALID_ARRAY_TYPE{ "Invalid array type constructed" };
err_def_n INVALID_VARIABLE_TYPE{ "Invalid variable type" };
}
std::string context::escape(std::string_view s)
......@@ -63,4 +71,168 @@ namespace cecko {
errors::err_def_n & e = err;
out() << "Error (line " << loc << "): " << e[0] << std::endl;
}
context* CKContext::get_ctx()
{
return static_cast<context*>(this);
}
CKStructTypeObs CKContext::declare_struct_type(const CIName& n, loc_t loc)
{
if (!!conflicting_tag_struct(n))
{
get_ctx()->message(errors::DUPLICATE_TAG, loc, n);
}
if (!!loctable_)
{
return loctable_->declare_struct_type(n, module_->getContext(), loc);
}
else
{
return globtable_->declare_struct_type(n, module_->getContext(), loc);
}
}
CKStructTypeObs CKContext::define_struct_type_open(const CIName& n, loc_t loc)
{
if (!!conflicting_tag_struct(n))
{
get_ctx()->message(errors::DUPLICATE_TAG, loc, n);
}
CKStructTypeObs tp;
if (!!loctable_)
{
tp = loctable_->declare_struct_type_here(n, module_->getContext(), loc);
}
else
{
tp = globtable_->declare_struct_type_here(n, module_->getContext(), loc);
}
if (tp->is_defined())
{
get_ctx()->message(errors::DUPLICATE_STRUCT_DEFINITION, loc, n);
}
tp->set_def_loc(loc);
return tp;
}
CKEnumTypeObs CKContext::declare_enum_type(const CIName& n, loc_t loc)
{
if (!!conflicting_tag_enum(n))
{
get_ctx()->message(errors::DUPLICATE_TAG, loc, n);
}
if (!!loctable_)
{
return loctable_->declare_enum_type(n, get_int_type(), loc);
}
else
{
return globtable_->declare_enum_type(n, get_int_type(), loc);
}
}
CKEnumTypeObs CKContext::define_enum_type_open(const CIName& n, loc_t loc)
{
if (!!conflicting_tag_enum(n))
{
get_ctx()->message(errors::DUPLICATE_TAG, loc, n);
}
CKEnumTypeObs tp;
if (!!loctable_)
{
tp = loctable_->declare_enum_type_here(n, get_int_type(), loc);
}
else
{
tp = globtable_->declare_enum_type_here(n, get_int_type(), loc);
}
if (tp->is_defined())
{
get_ctx()->message(errors::DUPLICATE_ENUM_DEFINITION, loc, n);
}
tp->set_def_loc(loc);
return tp;
}
CKTypedefConstObs CKContext::define_typedef(const std::string& name, const CKTypeRefPack& type_pack, loc_t loc)
{
if (!!conflicting_idf(name))
{
get_ctx()->message(errors::DUPLICATE_IDF, loc, name);
}
if (!!loctable_)
{
return loctable_->declare_typedef(name, type_pack, loc);
}
else
{
return globtable_->declare_typedef(name, type_pack, loc);
}
}
CKConstantConstObs CKContext::define_constant(const std::string& name, CKIRConstantIntObs value, loc_t loc)
{
if (!!conflicting_idf(name))
{
get_ctx()->message(errors::DUPLICATE_IDF, loc, name);
}
if (!!loctable_)
{
return loctable_->declare_constant(name, get_int_type(), value, loc);
}
else
{
return globtable_->declare_constant(name, get_int_type(), value, loc);
}
}
void CKContext::define_var(const std::string& name, const CKTypeRefPack& type_pack, loc_t loc)
{
if (type_pack.type->is_void() || type_pack.type->is_function())
{
get_ctx()->message(errors::INVALID_VARIABLE_TYPE, loc);
}
if (!!conflicting_idf(name))
{
get_ctx()->message(errors::DUPLICATE_IDF, loc, name);
return;
}
if (!!loctable_)
{
loctable_->varDefine(alloca_builder_, name, type_pack, loc);
}
else
{
globtable_->varDefine(module_, name, type_pack, loc);
}
}
CKFunctionObs CKContext::declare_function(const CIName& n, CKTypeObs type, loc_t loc)
{
if (!type->is_function())
{
get_ctx()->message(errors::INVALID_FUNCTION_TYPE, loc);
}
auto function_type = dynamic_cast<CKFunctionTypeObs>(type);
if (!!conflicting_idf_function(n, function_type))
{
get_ctx()->message(errors::DUPLICATE_IDF, loc, n);
}
return globtable_->declare_function(n, module_, function_type, loc);
}
void CKContext::enter_function(CKFunctionObs f, CKFunctionFormalPackArray pack, loc_t loc)
{
if (f->is_defined())
{
get_ctx()->message(errors::DUPLICATE_FUNCTION_DEFINITION, loc, f->get_name());
}
assert(!loctable_);
// FUNCTION PROLOG
auto BB0 = CKCreateBasicBlock("prolog", f->get_function_ir());
alloca_builder_.SetInsertPoint(BB0);
loctable_ = f->define(globtable_, alloca_builder_, std::move(pack));
start_bb_ = CKCreateBasicBlock("start", f->get_function_ir());
builder_.SetInsertPoint(start_bb_);
}
}
\ No newline at end of file
......@@ -61,10 +61,17 @@ namespace cecko {
extern err_def_s BADINT; ///< Malformed integer literal
extern err_def_s BADESCAPE; ///< Malformed escape sequence
extern err_def_s UNCHAR; ///< Invalid character
extern err_def_s NOFILE; ///< Cannot open input file
extern err_def_s UNDEF_IDF; ///< Undefined identifier of constant/variable/function
//extern err_def_s UNDEF_TYPEIDF; ///< Undefined type identifier
/// @cond INTERNAL
extern err_def_s NOFILE; ///< Cannot open input file (reported by the framework)
extern err_def_s DUPLICATE_IDF; ///< Duplicate identifier (reported by the framework)
extern err_def_s DUPLICATE_TAG; ///< Duplicate tag (reported by the framework)
extern err_def_s DUPLICATE_FUNCTION_DEFINITION; ///< Duplicate function definition (reported by the framework)
extern err_def_s DUPLICATE_STRUCT_DEFINITION; ///< Duplicate function definition (reported by the framework)
extern err_def_s DUPLICATE_ENUM_DEFINITION; ///< Duplicate function definition (reported by the framework)
/// @endcond
extern err_def_n INTERNAL; ///< Internal error
extern err_def_n EMPTYCHAR; ///< Empty character literal
extern err_def_n MULTICHAR_LONG; ///< Too long character literal
......@@ -79,6 +86,11 @@ namespace cecko {
extern err_def_n NOT_POINTER; ///< Expression is not a pointer
extern err_def_n NOT_NUMBER_OR_POINTER; ///< Expression is not a number or pointer
extern err_def_n INCOMPATIBLE; ///< Incompatible operands
extern err_def_n INVALID_FUNCTION_TYPE; ///< Invalid function type constructed
extern err_def_n INVALID_ARRAY_TYPE; ///< Invalid array type constructed
/// @cond INTERNAL
extern err_def_n INVALID_VARIABLE_TYPE; ///< Invalid variable type (reported by the framework)
/// @endcond
}
/// @cond COVERAGE
......
......@@ -226,7 +226,7 @@ namespace cecko {
{
return constants_.find(n);
}
CKNamedObs CKGlobalTable::find(const CIName& n)
CKNamedObs CKGlobalTable::find_here(const CIName& n)
{
auto pc = find_constant_here(n);
if (pc)
......@@ -237,6 +237,23 @@ namespace cecko {
auto p = fncs_.find(n);
return p;
}
bool CKGlobalTable::conflicting_idf(const CIName& n)
{
return find_idf_here_universal(n) || !!vars_.find(n) || !!fncs_.find(n);
}
bool CKGlobalTable::conflicting_idf_function(const CIName& n, CKFunctionTypeObs type)
{
if (find_idf_here_universal(n) || !!vars_.find(n))
return true;
auto p = fncs_.find(n);
return !!p && p->get_function_type() != type;
}
CKNamedObs CKGlobalTable::find(const CIName& n)
{
return find_here(n);
}
void CKGlobalTable::dump(CIOStream& os) const
{
......@@ -325,14 +342,23 @@ namespace cecko {
return p;
return parent_scope_->find_typedef(n);
}
CKNamedObs CKLocalTable::find(const CIName& n)
CKNamedObs CKLocalTable::find_here(const CIName& n)
{
auto pc = find_constant_here(n);
if (pc)
return pc;
auto pv = vars_.find(n);
if (pv)
return pv;
return pv;
}
bool CKLocalTable::conflicting_idf(const CIName& n)
{
return find_idf_here_universal(n) || !!vars_.find(n);
}
CKNamedObs CKLocalTable::find(const CIName& n)
{
auto p = find_here(n);
if (p)
return p;
return parent_scope_->find(n);
}
CKLocalTableObs CKLocalTable::get_local()
......@@ -351,6 +377,21 @@ namespace cecko {
return parent_scope_->get_local();
}
bool CKUniversalTable::conflicting_tag_enum(const CIName& n)
{
return !!strts_.find(n);
}
bool CKUniversalTable::conflicting_tag_struct(const CIName& n)
{
return !!enmts_.find(n);
}
bool CKUniversalTable::find_idf_here_universal(const CIName& n)
{
return !!typedefs_.find(n) || !!constants_.find(n);
}
void CKUniversalTable::dump_universal(CIOStream& os, const std::string& indent) const
{
//os << "// --- ENUMS ---" << std::endl;
......@@ -469,17 +510,6 @@ namespace cecko {
{
}
void CKContext::enter_function(CKFunctionObs f, CKFunctionFormalPackArray pack, loc_t loc)
{
assert(!loctable_);
// FUNCTION PROLOG
auto BB0 = CKCreateBasicBlock("prolog", f->get_function_ir());
alloca_builder_.SetInsertPoint(BB0);
loctable_ = f->define(globtable_, alloca_builder_, std::move(pack));
start_bb_ = CKCreateBasicBlock("start", f->get_function_ir());
builder_.SetInsertPoint(start_bb_);
}
void CKContext::exit_function()
{
assert(loctable_);
......@@ -503,99 +533,55 @@ namespace cecko {
assert(loctable_);
}
CKStructTypeObs CKContext::declare_struct_type(const CIName& n, loc_t loc)
bool CKContext::conflicting_tag_enum(const std::string& name)
{
if (!!loctable_)
{
return loctable_->declare_struct_type(n, module_->getContext(), loc);
}
else
{
return globtable_->declare_struct_type(n, module_->getContext(), loc);
}
}
CKStructTypeObs CKContext::define_struct_type_open(const CIName& n, loc_t loc)
{
CKStructTypeObs tp;
if (!!loctable_)
{
tp = loctable_->declare_struct_type_here(n, module_->getContext(), loc);
return loctable_->conflicting_tag_enum(name);
}
else
{
tp = globtable_->declare_struct_type_here(n, module_->getContext(), loc);
return globtable_->conflicting_tag_enum(name);
}
tp->set_def_loc(loc); // !!! DUPLICITE DEFINITION ???
return tp;
}
void CKContext::define_struct_type_close(CKStructTypeObs type, const CKStructItemArray& items)
{
type->finalize(items);
}
CKEnumTypeObs CKContext::declare_enum_type(const CIName& n, loc_t loc)
bool CKContext::conflicting_tag_struct(const std::string& name)
{
if (!!loctable_)
{
return loctable_->declare_enum_type(n, get_int_type(), loc);
return loctable_->conflicting_tag_struct(name);
}
else
{
return globtable_->declare_enum_type(n, get_int_type(), loc);
return globtable_->conflicting_tag_struct(name);
}
}
CKEnumTypeObs CKContext::define_enum_type_open(const CIName& n, loc_t loc)
{
CKEnumTypeObs tp;
bool CKContext::conflicting_idf(const std::string& name)
{
if (!!loctable_)
{
tp = loctable_->declare_enum_type_here(n, get_int_type(), loc);
return loctable_->conflicting_idf(name);
}
else
{
tp = globtable_->declare_enum_type_here(n, get_int_type(), loc);
return globtable_->conflicting_idf(name);
}
tp->set_def_loc(loc); // !!! DUPLICITE DEFINITION ???
return tp;
}
void CKContext::define_enum_type_close(CKEnumTypeObs type, CKConstantObsVector items)
{
type->finalize(std::move(items));
}
CKTypedefConstObs CKContext::define_typedef(const std::string& name, const CKTypeRefPack& type_pack, loc_t loc)
bool CKContext::conflicting_idf_function(const CIName& name, CKFunctionTypeObs type)
{
if (!!loctable_)
{
return loctable_->declare_typedef(name, type_pack, loc);
}
else
{
return globtable_->declare_typedef(name, type_pack, loc);
}
return globtable_->conflicting_idf_function(name, type);
}
CKConstantConstObs CKContext::define_constant(const std::string& name, CKIRConstantIntObs value, loc_t loc)
void CKContext::define_struct_type_close(CKStructTypeObs type, const CKStructItemArray& items)
{
if (!!loctable_)
{
return loctable_->declare_constant(name, get_int_type(), value, loc);
}
else
{
return globtable_->declare_constant(name, get_int_type(), value, loc);
}
type->finalize(items);
}
void CKContext::define_var(const std::string& name, const CKTypeRefPack& type_pack, loc_t loc)
void CKContext::define_enum_type_close(CKEnumTypeObs type, CKConstantObsVector items)
{
if (!!loctable_)
{
loctable_->varDefine(alloca_builder_, name, type_pack, loc);
}
else
{
globtable_->varDefine(module_, name, type_pack, loc);
}
type->finalize(std::move(items));
}
CKNamedObs CKContext::find(const CIName& n)
{
if (!!loctable_)
......@@ -632,6 +618,35 @@ namespace cecko {
}
}
CKArrayTypeObs CKContext::get_array_type(CKTypeObs element_type, CKIRConstantIntObs size)
{
if (element_type->is_void() || element_type->is_function())
{
// cannot create array of void/function
return nullptr;
}
return typetable_->get_array_type(element_type, size);
}
CKFunctionTypeObs CKContext::get_function_type(CKTypeObs ret_type, CKTypeObsArray arg_types, bool variadic)
{
if (ret_type->is_array() || ret_type->is_function())
{
// cannot return array/function
return nullptr;
}
for (auto&& a : arg_types)
{
if (a->is_void() || a->is_array() || a->is_function())
{
// cannot pass void/array/function
// note: Cecko does not support implicit array/function-to-pointer conversion on argument declarations
return nullptr;
}
}
return typetable_->get_function_type(ret_type, std::move(arg_types), variadic);
}
void CKTables::declare_library()
{
auto t_void = typetable_.get_void_type();
......
......@@ -730,9 +730,9 @@ namespace cecko {
: CKAbstractNamed(def_loc), type_pack_(type_pack)
{}
/// @endcond
virtual bool is_var() const { return true; }
virtual CKTypeObs get_type() const { return type_pack_.type; }
virtual bool is_const() const { return type_pack_.is_const; }
virtual bool is_var() const override { return true; }
virtual CKTypeObs get_type() const override { return type_pack_.type; }
virtual bool is_const() const override { return type_pack_.is_const; }
//const CKTypeRefPack& get_type_pack() const { return type_pack_; }
/// @cond INTERNAL
void dump(CIOStream& os, const std::string& indent) const;
......@@ -748,7 +748,7 @@ namespace cecko {
CKGlobalVar(CKTypeRefPack type_pack, CKIRConstantObs address, loc_t def_loc)
: CKVar(type_pack, def_loc), address_(address)
{}
virtual CKIRValueObs get_ir() const { return address_; }
virtual CKIRValueObs get_ir() const override { return address_; }
CKIRConstantObs get_address() const { return address_; }
/// @endcond
private:
......@@ -842,6 +842,9 @@ namespace cecko {
CKConstantConstObs declare_constant(const CIName& name, CKTypeObs type, CKIRConstantIntObs value, loc_t def_loc);
CKTypedefConstObs find_typedef_here(const CIName& n) const;
CKNamedObs find_constant_here(const CIName& n);
bool conflicting_tag_enum(const std::string& name);
bool conflicting_tag_struct(const std::string& name);
bool find_idf_here_universal(const CIName& n);
void dump_universal(CIOStream& os, const std::string& indent) const;
private:
CINamedStorage< CKStructType> strts_;
......@@ -877,8 +880,11 @@ namespace cecko {
CKFunctionObs declare_function(const CIName& n, CKIRModuleObs M, CKFunctionTypeObs type, const CIName& irname);
CKFunctionObs find_function(const CIName& n);
CKFunctionConstObs find_function(const CIName& n) const;
virtual CKTypedefConstObs find_typedef(const CIName& n) const;
virtual CKNamedObs find(const CIName& n);
virtual CKTypedefConstObs find_typedef(const CIName& n) const override;
virtual CKNamedObs find(const CIName& n) override;
CKNamedObs find_here(const CIName& n);
bool conflicting_idf(const CIName& n);
bool conflicting_idf_function(const CIName& n, CKFunctionTypeObs type);
void dump(CIOStream& os) const;
private:
......@@ -894,7 +900,7 @@ namespace cecko {
CKLocalVar(CKTypeRefPack type_pack, CKIRAllocaInstObs address, loc_t def_loc, bool is_arg)
: CKVar(type_pack, def_loc), address_(address), is_arg_(is_arg)
{}
virtual CKIRValueObs get_ir() const { return address_; }
virtual CKIRValueObs get_ir() const override { return address_; }
CKIRAllocaInstObs get_address() const { return address_; }
bool is_arg() const { return is_arg_; }
/// @endcond
......@@ -921,12 +927,14 @@ namespace cecko {
CKLocalVarObs varDefine(CKIRBuilderRef builder, const CIName& name, const CKTypeRefPack& type_pack, loc_t def_loc);
virtual CKTypedefConstObs find_typedef(const CIName& n) const;
virtual CKNamedObs find(const CIName& n);
virtual CKTypedefConstObs find_typedef(const CIName& n) const override;
virtual CKNamedObs find(const CIName& n) override;
CKNamedObs find_here(const CIName& n);
bool conflicting_idf(const CIName& n);
void dump(CIOStream& os, const std::string & indent) const;
virtual CKLocalTableObs get_local();
virtual CKLocalTableObs get_local() override;
CKLocalTableObs create_block();
CKLocalTableObs parent_block() const;
......@@ -993,6 +1001,8 @@ namespace cecko {
using CKTablesObs = CKTables*;
/// @endcond
class context;
/// Semantic layer of compiler context
struct CKContext {
/// @cond INTERNAL
......@@ -1031,9 +1041,9 @@ namespace cecko {
/// A pointer type descriptor
CKPtrTypeObs get_pointer_type(const CKTypeRefPack& pack) { return typetable_->get_pointer_type(pack); }
/// An array type descriptor
CKArrayTypeObs get_array_type(CKTypeObs element_type, CKIRConstantIntObs size) { return typetable_->get_array_type(element_type, size); }
CKArrayTypeObs get_array_type(CKTypeObs element_type, CKIRConstantIntObs size);
/// A function type descriptor
CKFunctionTypeObs get_function_type(CKTypeObs ret_type, CKTypeObsArray arg_types, bool variadic = false) { return typetable_->get_function_type(ret_type, std::move(arg_types), variadic); }
CKFunctionTypeObs get_function_type(CKTypeObs ret_type, CKTypeObsArray arg_types, bool variadic = false);
/// @}
/// @name Named struct types
......@@ -1083,10 +1093,7 @@ namespace cecko {
/// @{
/// Declare a function (with or without body)
CKFunctionObs declare_function(const CIName& n, CKFunctionTypeObs type, loc_t loc)
{
return globtable_->declare_function(n, module_, type, loc);
}
CKFunctionObs declare_function(const CIName& n, CKTypeObs type, loc_t loc);
/// @}
/// @name Finding named objects
......@@ -1147,6 +1154,11 @@ namespace cecko {
{
return data_layout_;
}
bool conflicting_idf(const std::string& name);
bool conflicting_idf_function(const std::string& name, CKFunctionTypeObs type);
bool conflicting_tag_enum(const std::string& name);
bool conflicting_tag_struct(const std::string& name);
/// @endcond
private:
CKTypeTableObs typetable_;
......@@ -1158,6 +1170,8 @@ namespace cecko {
CKIRBuilder builder_;
CKIRBasicBlockObs start_bb_;
CKIRDataLayoutObs data_layout_;
context* get_ctx();
};
}
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment