Skip to content

Commit

Permalink
[cpp] member access can now be used on both: non-variable pointers (e…
Browse files Browse the repository at this point in the history
…quivalent of -> in C). previously non-variables werent supported for member access at all. e.g `get_foo().id = 5` would fail to compile. in addition, variable pointers i.e `my_foo.id = 5` works in two scenarios: normal member access (. in C) and pointer access (-> in C but for a variable)
  • Loading branch information
harrand committed May 24, 2024
1 parent 6cbd081 commit f2bf719
Show file tree
Hide file tree
Showing 3 changed files with 51 additions and 92 deletions.
29 changes: 24 additions & 5 deletions cpp/src/codegen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1032,11 +1032,30 @@ namespace code
value member_access(const data& d, ast::member_access payload)
{
value lhs_var = expression(d, *payload.lhs);
d.ctx.assert_that(lhs_var.ty.is_pointer(), error_code::type, "lhs of member access should be a variable that resolves to a pointer type. instead it resolved to \"{}\"", lhs_var.ty.name());
lhs_var.ty = lhs_var.ty.dereference();
type initial_ty = lhs_var.ty;
if(lhs_var.is_variable)
{
initial_ty = initial_ty.dereference();
}
// at this point, we expect the following:
// if its a variable, we expect either a struct* (member access) or a struct** (pointer access) as variable is a pointer (alloca) under-the-hood.
if(lhs_var.is_variable)
{
d.ctx.assert_that(lhs_var.ty.is_pointer(), error_code::ice, "somehow, lhs of member access is a variable thats not considered a pointer (alloca) under-the-hood. please submit a bug report.");
// lets convert it down to a struct* so the common code below works.
// if its a double pointer, we dereference it once (pointer access).
if(lhs_var.ty.dereference().is_pointer())
{
lhs_var = get_variable_val(lhs_var, d);
}
// else its a single pointer, we do nothing (member access)
}
else // if its not a variable, it must be a struct* (pointer access only. normal member access only makes sense with variables.)
{
}
d.ctx.assert_that(lhs_var.ty.is_pointer() && lhs_var.ty.dereference().is_struct(), error_code::type, "lhs of member access (non variable) *must* be a pointer-to-struct. instead you provided me with a \"{}\"", initial_ty.name());

d.ctx.assert_that(lhs_var.ty.is_struct(), error_code::type, "lhs identifier of member access is not a struct type, but instead a \"{}\"", lhs_var.ty.name());
struct_type struct_ty = lhs_var.ty.as_struct();
struct_type struct_ty = lhs_var.ty.dereference().as_struct();
// which data member are we?
// note: if we dont match to a data member here, then the code must be ill-formed.
std::optional<std::size_t> data_member_idx = std::nullopt;
Expand All @@ -1051,7 +1070,7 @@ namespace code
}
d.ctx.assert_that(data_member_idx.has_value(), error_code::codegen, "access to non-existent data member named \"{}\" within struct \"{}\"", payload.rhs, struct_ty.name);
// get the data member via GEP
llvm::Type* llvm_struct_ty = as_llvm_type(lhs_var.ty, d.state);
llvm::Type* llvm_struct_ty = as_llvm_type(type::from_struct(struct_ty), d.state);
llvm::Value* ret = builder->CreateStructGEP(llvm_struct_ty, lhs_var.llv, data_member_idx.value());
return
{
Expand Down
7 changes: 6 additions & 1 deletion cpp/src/semal.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -705,7 +705,12 @@ namespace semal
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()));
type initial_ty = lhs_ty;
if(lhs_ty.is_pointer())
{
lhs_ty = lhs_ty.dereference();
}
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 or a pointer-to-struct type, which \"{}\" is not.", initial_ty.name()));
struct_type struct_ty = lhs_ty.as_struct();
for(std::size_t i = 0; i < struct_ty.data_members.size(); i++)
{
Expand Down
107 changes: 21 additions & 86 deletions samples/scratchpad.psy
Original file line number Diff line number Diff line change
@@ -1,100 +1,35 @@
putchar :: (ch : i8 weak) -> u0 := extern;
print_digit :: (digit : i64 weak) -> u0
{
// ascii 48 == '0'
putchar(48 + digit);
}
"yogi bear";"gaming";"straightming";
'\t';

is_odd :: (val : i64) -> bool
{
mystr : i8& const := "well met";

half : i64 := (val / 2);
low_half : i64 := ((val - 1) / 2);
return (half == low_half);
}

animal :: struct
{
id : i64;
}

get_fox :: () -> animal
puts :: (str : i8& const) -> u0 := extern;
main :: () -> i64
{
//ret : animal := animal
//{
// .id := 2
//};
//ret : animal;
//ret.id = 5;
//return ret;

//return animal
//{
// .id := 8
//};
ret : animal;
return ret;
puts("hello world!");

mydata : data := data{.id := 0};
print_id(mydata);
mydata.id = 1;
print_id(mydata);

ptr : data& := ref mydata;
(deref ptr).id = 2;
print_id(mydata);
ptr.id = 3;
print_id(mydata);
return 0;
}

puts :: (str : i8& const) -> u0 := extern;
print_hello :: () -> u0
putchar :: (ch : i8) -> u0 := extern;
print_id :: (in : data) -> u0
{
buffer : i8& := __builtin_malloc(6 * (sizeof i8));
defer __builtin_free(buffer);

three : i64 const := 3;

// 97 = 'a'
// so n'th letter of alphabet = (97 + (n - 1))
buffer[0] = 'h';
buffer[1] = 'e';
buffer[2] = 'l';
buffer[three] = 'l';
buffer[4] = 'o';
buffer[5] = '\0';
puts(buffer);

literal : i8& const := "hello\tagain!";
puts(literal);
putchar('0' + (in.id@i8));
putchar('\n');
}

main :: () -> i64
data :: struct
{
print_hello();

putchar(10);
my_fox : animal := get_fox();
print_digit(my_fox.id);
putchar(10);
i : i64 weak := 0;
for i = 0, i != 10, i = (i + 1)
{
j : i64 const := i;
print_digit(i);
print_digit(j);
}
putchar(10);
print_digit(1);
print_digit(2);
print_digit(3);

if is_odd(23456)
{
print_digit(8);
}
else
{
print_digit(9);
}
return 0;
id : i64 := 0;
}

== default : build ==
{
set_build_type(debug);
set_linkage_type(executable);
set_output_name("scratchpad");
}

0 comments on commit f2bf719

Please sign in to comment.