Skip to content

Commit

Permalink
[cpp] implemented member access
Browse files Browse the repository at this point in the history
  • Loading branch information
harrand committed May 16, 2024
1 parent 27861a7 commit 402b20c
Show file tree
Hide file tree
Showing 4 changed files with 101 additions and 5 deletions.
15 changes: 14 additions & 1 deletion cpp/src/ast.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ struct ast
}
bool operator==(const bool_literal& rhs) const = default;
};

struct identifier
{
std::string iden;
Expand All @@ -51,6 +52,17 @@ struct ast
bool operator==(const identifier& rhs) const = default;
};

struct member_access
{
boxed_expression lhs;
std::string rhs;
std::string to_string() const
{
return std::format("member_access({}.{})", lhs->to_string(), rhs);
}
bool operator==(const member_access& rhs) const = default;
};

struct unary_operator
{
lex::token op;
Expand Down Expand Up @@ -145,6 +157,7 @@ struct ast
ast::decimal_literal,
ast::bool_literal,
ast::identifier,
ast::member_access,
ast::variable_declaration,
ast::function_call,
ast::return_statement,
Expand Down Expand Up @@ -216,7 +229,7 @@ struct ast

struct node
{
using payload_t = std::variant<std::monostate, integer_literal, decimal_literal, bool_literal, identifier, function_call, if_statement, for_statement, expression, return_statement, variable_declaration, function_definition, struct_definition, block, meta_region>;
using payload_t = std::variant<std::monostate, integer_literal, decimal_literal, bool_literal, identifier, member_access, function_call, if_statement, for_statement, expression, return_statement, variable_declaration, function_definition, struct_definition, block, meta_region>;
payload_t payload = std::monostate{};
srcloc meta = {};
std::vector<node> children = {};
Expand Down
51 changes: 51 additions & 0 deletions cpp/src/parse.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@ namespace parse
bool reduce_from_bool_literal(std::size_t offset);
// given an ast::identifier subtree at the offset, try to reduce its surrounding tokens/atoms into something bigger. returns true on success, false otherwise.
bool reduce_from_identifier(std::size_t offset);
// given an ast::member_access subtree at the offset, try to reduce its surrounding tokens/atoms into something bigger. returns true on success, false otherwise.
bool reduce_from_member_access(std::size_t offset);
// given an ast::variable_declaration subtree at the offset, try to reduce its surrounding tokens/atoms into something bigger. returns true on success, false otherwise.
bool reduce_from_variable_declaration(std::size_t offset);
// given an ast::function_call subtree at the offset, try to reduce its surrounding tokens/atoms into something bigger. returns true on success, false otherwise.
Expand Down Expand Up @@ -517,6 +519,19 @@ namespace parse
return true;
}
retr.undo();
auto dot = retr.retrieve<lex::token>();
if(dot.has_value() && dot->t == lex::type::dot)
{
if(!retr.avail()){return false;}
auto rhs_iden = retr.retrieve<ast::identifier>();
if(!rhs_iden.has_value())
{
return false;
}
retr.reduce_to(ast::member_access{.lhs = ast::expression{.expr =value, .capped = false}, .rhs = rhs_iden->iden}, meta);
return true;
}
retr.undo();

// getting difficult here...
// at some point we need to know whether an identifier should remain an identifier or become an expression
Expand Down Expand Up @@ -570,6 +585,26 @@ namespace parse
return false;
}

bool parser_state::reduce_from_member_access(std::size_t offset)
{
retriever retr{*this, offset};
srcloc meta;
auto value = retr.must_retrieve<ast::member_access>(&meta);

if(!retr.avail()){return false;}
bool capped = false;

auto semicolon = retr.retrieve<lex::token>();
capped = (semicolon.has_value() && semicolon->t == lex::type::semicolon);
if(!capped)
{
retr.undo();
}

retr.reduce_to(ast::expression{.expr = value, .capped = capped}, meta);
return true;
}

bool parser_state::reduce_from_variable_declaration(std::size_t offset)
{
retriever retr{*this, offset};
Expand Down Expand Up @@ -644,6 +679,18 @@ namespace parse
return true;
}
}
else if(tok->t == lex::type::dot)
{
// could be a member access.
if(!retr.avail()){return false;}
auto iden = retr.retrieve<ast::identifier>();
if(!iden.has_value())
{
return false;
}
retr.reduce_to(ast::member_access{.lhs = value, .rhs = iden->iden}, meta);
return true;
}
}
}
// as expressions can either be within a block or standalone, the only way we know for sure its standalone is if its the very first subtree.
Expand Down Expand Up @@ -1125,6 +1172,10 @@ namespace parse
{
ret = this->reduce_from_identifier(i);
},
[&](ast::member_access arg)
{
ret = this->reduce_from_member_access(i);
},
[&](ast::variable_declaration arg)
{
ret = this->reduce_from_variable_declaration(i);
Expand Down
19 changes: 17 additions & 2 deletions cpp/src/semal.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -605,6 +605,23 @@ namespace semal
return maybe_function->return_ty;
}

type member_access(const data& d, const ast::member_access& payload)
{
type lhs_ty = expression(d, *payload.lhs);
d.assert_that(lhs_ty.is_struct(), std::format("detected use of member-access token `.`. the left-hand-side of the token must be a struct type, which \"{}\" is not.", lhs_ty.name()));
struct_type struct_ty = lhs_ty.as_struct();
for(std::size_t i = 0; i < struct_ty.data_members.size(); i++)
{
const auto& member = struct_ty.data_members[i];
if(member.member_name == payload.rhs)
{
return *member.ty;
}
}
d.fatal_error(std::format("struct \"{}\" has no data member named \"{}\"", struct_ty.name, payload.rhs));
return type::undefined();
}

type return_statement(const data& d, const ast::return_statement& payload)
{
const function_t* maybe_parent = d.state.try_find_parent_function(d.tree, d.path);
Expand Down Expand Up @@ -744,12 +761,10 @@ namespace semal
{
ret = function_call(d, call);
},
/*
[&](ast::member_access mem)
{
ret = member_access(d, mem);
},
*/
[&](ast::expression expr)
{
ret = expression(d, expr);
Expand Down
21 changes: 19 additions & 2 deletions samples/scratchpad.psy
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,38 @@

hio : i64 := 64;

nesteddata :: struct
{
flak : i64;
}

mydata :: struct
{
member : i64 := 5;
member2 : i64 := 69;
nested : nesteddata;
}
xyz : mydata;
xyz.member;

get_data :: () -> mydata
{
ret : mydata;
(ret.nested.flak) = 9;
return ret;
}
//class :: typedef := mydata;

putchar :: (ch : i64) -> u0 := extern;
dub :: (val : i64) -> i64
{
get_data().member = 5;
//ptr : i8& := __builtin_malloc(123);
//defer __builtin_free(ptr);

is_cringe : bool := (true == false);
val = deref ref val;
val = (val + val);
val = (val + (get_data().member));
v : i64&;
val = (val * val * val * (deref v));
deref v = 862;
Expand All @@ -44,7 +61,7 @@ morb :: (par0 : i64) -> f64
poggers2 : i64;
poggers3 : i64;
//morb2 :: (par0 : i64) -> u0 := extern;
complicated(poggers, dub(5), 3);
complicated(poggers, dub(5), get_data().member2);
complicated(--complicated(1, 2, 3), dub(5), 690);

if poggers1 == 59
Expand Down

0 comments on commit 402b20c

Please sign in to comment.