Skip to content

Commit

Permalink
[cpp] properly implemented const
Browse files Browse the repository at this point in the history
  • Loading branch information
harrand committed May 17, 2024
1 parent 51a548f commit a6635f3
Show file tree
Hide file tree
Showing 5 changed files with 48 additions and 27 deletions.
5 changes: 5 additions & 0 deletions cpp/src/lex.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -390,6 +390,11 @@ namespace lex

bool breaks_word(const tokenise_state& state, std::string_view str)
{
if(str.starts_with(" const"))
{
// don't break on a space if its immediately followed by const.
return false;
}
if(state.in_integer_literal() && str.starts_with("."))
{
return false;
Expand Down
46 changes: 23 additions & 23 deletions cpp/src/semal.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,20 +45,29 @@ namespace semal
{
type ret = type::undefined();
std::string cur_type = "";
auto check_const = [&cur_type, &ret, &type_name](){if(type_name == "const"){ret.qualifiers = static_cast<type_qualifier>(static_cast<int>(ret.qualifiers) | qualifier_const);}};
for(std::size_t i = 0; i < type_name.size(); i++)
{
char c = type_name[i];
if(c == '&')
if(std::string_view(type_name.data() + i).starts_with(" const"))
{
check_const();
ret = get_type_from_name(cur_type).pointer_to();
cur_type = "";
if(ret.is_undefined())
{
ret = get_type_from_name(cur_type);
}
ret.qualifiers = (type_qualifier)((int)ret.qualifiers | qualifier_const);
i += sizeof(" const") - 2;
continue;
}
else if(c == ' ')
char c = type_name[i];
if(c == '&')
{
check_const();
ret = get_type_from_name(cur_type);
if(ret.is_undefined())
{
ret = get_type_from_name(cur_type).pointer_to();
}
else
{
ret = ret.pointer_to();
}
cur_type = "";
}
else
Expand All @@ -68,25 +77,14 @@ namespace semal
}
if(cur_type.size())
{
std::string without_qualifiers = cur_type;
auto iter = without_qualifiers.find("const");
if(iter != std::string::npos)
{
without_qualifiers.erase(iter, sizeof("const") - 1); // -1 as sizeof includes null terminator
}
type_qualifier quals = iter != std::string::npos ? qualifier_const : qualifier_none;
if(!ret.is_undefined())
{
ret.qualifiers = quals;
}
if(ret.is_undefined())
{
// try a struct.
for(const auto& [struct_name, structdata] : this->struct_decls)
{
if(cur_type == struct_name)
{
ret = type::from_struct(structdata.ty, quals);
ret = type::from_struct(structdata.ty);
break;
}
}
Expand All @@ -98,7 +96,7 @@ namespace semal
{
if(cur_type == primitive_type_names[i])
{
ret = type::from_primitive(static_cast<primitive_type>(i), quals);
ret = type::from_primitive(static_cast<primitive_type>(i));
break;
}
}
Expand Down Expand Up @@ -550,6 +548,7 @@ namespace semal
switch(payload.op.t)
{
case lex::type::operator_equals:
d.assert_that(!lhs.is_const(), std::format("lhs of assignment is const: \"{}\"", lhs.name()));
d.assert_that(lhs == rhs, std::format("cannot assign from type \"{}\" to a type \"{}\"", lhs.name(), rhs.name()));
return rhs;
break;
Expand Down Expand Up @@ -701,6 +700,7 @@ namespace semal

const auto& ty = d.state.get_type_from_name(payload.type_name);
d.assert_that(!ty.is_undefined(), std::format("undefined type \"{}\"", payload.type_name));
d.assert_that(payload.type_name == ty.name(), std::format("parse-type-from-string error. input string: \"{}\". output type.name(): \"{}\"", payload.type_name, ty.name()));
d.state.register_local_variable
({
.ty = ty,
Expand All @@ -711,7 +711,7 @@ namespace semal
if(payload.initialiser.has_value())
{
type expr_ty = expression(d, *payload.initialiser.value());
d.assert_that(expr_ty == ty, std::format("initialiser of variable \"{}\" is of type \"{}\", which does not match the variable's type of \"{}\". perhaps you forgot to insert a cast?", payload.var_name, expr_ty.name(), ty.name()));
d.assert_that(expr_ty.without_qualifiers() == ty.without_qualifiers(), std::format("initialiser of variable \"{}\" is of type \"{}\", which does not match the variable's type of \"{}\". perhaps you forgot to insert a cast?", payload.var_name, expr_ty.name(), ty.name()));
}
return ty;
}
Expand Down
16 changes: 12 additions & 4 deletions cpp/src/type.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,11 @@ bool type::is_void() const
&& !this->is_pointer();
}

bool type::is_const() const
{
return this->qualifiers & qualifier_const;
}

primitive_type type::as_primitive() const
{
diag::assert_that(this->is_primitive(), error_code::ice, "attempt to resolve non-primitive type \"{}\" as a primitive", this->name());
Expand Down Expand Up @@ -181,10 +186,6 @@ std::string type::name() const
}
else
{
if(qualstr.size() && qualstr.front() == ' ')
{
qualstr.erase(qualstr.begin());
}
ret = std::format("{}&{}", std::get<util::box<type>>(this->ty)->name(), qualstr);
}

Expand All @@ -207,6 +208,13 @@ type type::pointer_to(type_qualifier quals) const
};
}

type type::without_qualifiers() const
{
type ret = *this;
ret.qualifiers = qualifier_none;
return ret;
}

/*static*/type type::undefined()
{
return
Expand Down
3 changes: 3 additions & 0 deletions cpp/src/type.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -93,13 +93,16 @@ struct type
bool is_floating_point_type() const;
bool is_void() const;

bool is_const() const;

primitive_type as_primitive() const;
struct_type as_struct() const;

std::string name() const;

type dereference() const;
type pointer_to(type_qualifier quals = qualifier_none) const;
type without_qualifiers() const;

static type undefined();
static type from_primitive(primitive_type t, type_qualifier quals = qualifier_none);
Expand Down
5 changes: 5 additions & 0 deletions samples/scratchpad.psy
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,11 @@ get_data :: () -> mydata
putchar :: (ch : i8) -> u0 := extern;
dub :: (val : i64) -> i64
{
vvptr : i64&& const;
deref vvptr = (55@i64&);
vv : i64 := 5;
vv = 50;

get_data().member = 5;
ptr : i8& := __builtin_malloc(123@u64);
longptr : i64& := (ptr@i64&);
Expand Down

0 comments on commit a6635f3

Please sign in to comment.