Hi! Could anybody give an example of pointers arithmetic in Hare?
```
export fn main() void = {
const mem = strings::toutf8("abc");
const ptr: *[]u8 = &mem; // cast reference to pointer
const offsetPtr = ptr - 8; // playing with pointers arithmetic
};
```
I am getting an error:
`Cannot promote lvalue const *[]u8 and rvalue [iconst min=8 max=8]`
You mean to do like?
const newPtr = ptr:uintptr - 1;
I am getting result at form:
140729276888207
Do I need to cast it back to hex to get a normal memory address?
пт, 15 мар. 2024 г. в 14:56, Lorenz (xha) <me@xha.li>:
>> you can cast to a uintptr and then to your arithmetic with that.
no, just cast it to a pointer type again (the original type) to get a
normal memory address.
On Fri, Mar 15, 2024 at 03:04:46PM +0300, Dmitry B wrote:
> You mean to do like?> const newPtr = ptr:uintptr - 1;> > I am getting result at form:> 140729276888207> > Do I need to cast it back to hex to get a normal memory address?> > пт, 15 мар. 2024 г. в 14:56, Lorenz (xha) <me@xha.li>:> >> > you can cast to a uintptr and then to your arithmetic with that.
Could you show me how to do it... please
I tried:
```
const mem = strings::toutf8("abc");
const ptr: *[]u8 = &mem;
fmt::println(&mem)!;
const newPtr = ptr:uintptr - 1;
const ptr2: *[]u8 = &newPtr;
fmt::println(ptr2)!;
```
It do not work:
`error: Initializer is not assignable to binding type`
пт, 15 мар. 2024 г. в 17:38, Lorenz (xha) <me@xha.li>:
>> no, just cast it to a pointer type again (the original type) to get a> normal memory address.>> On Fri, Mar 15, 2024 at 03:04:46PM +0300, Dmitry B wrote:> > You mean to do like?> > const newPtr = ptr:uintptr - 1;> >> > I am getting result at form:> > 140729276888207> >> > Do I need to cast it back to hex to get a normal memory address?> >> > пт, 15 мар. 2024 г. в 14:56, Lorenz (xha) <me@xha.li>:> > >> > > you can cast to a uintptr and then to your arithmetic with that.
i think that this is what you want:
```
use strings;
use fmt;
export fn main() void = {
const mem = strings::toutf8("abc");
const ptr: *[]u8 = &mem;
fmt::println(&mem)!;
const newPtr = ptr:uintptr - 1;
const ptr2: *[]u8 = newPtr: *[]u8;
fmt::println(ptr2)!;
};
```
On Sat, Mar 16, 2024 at 10:09:04AM +0300, Dmitry B wrote:
> Could you show me how to do it... please> > I tried:> ```> const mem = strings::toutf8("abc");> const ptr: *[]u8 = &mem;> fmt::println(&mem)!;> > const newPtr = ptr:uintptr - 1;> const ptr2: *[]u8 = &newPtr;> fmt::println(ptr2)!;> ```> It do not work:> `error: Initializer is not assignable to binding type`> > пт, 15 мар. 2024 г. в 17:38, Lorenz (xha) <me@xha.li>:> >> > no, just cast it to a pointer type again (the original type) to get a> > normal memory address.> >> > On Fri, Mar 15, 2024 at 03:04:46PM +0300, Dmitry B wrote:> > > You mean to do like?> > > const newPtr = ptr:uintptr - 1;> > >> > > I am getting result at form:> > > 140729276888207> > >> > > Do I need to cast it back to hex to get a normal memory address?> > >> > > пт, 15 мар. 2024 г. в 14:56, Lorenz (xha) <me@xha.li>:> > > >> > > > you can cast to a uintptr and then to your arithmetic with that.
Yes, that's it. Thanks!
Where can I read casting rules? What and to what can be casted?
Am I right to understand that everything after `:` is casting?
And is type declaration related to casting? Or is it's separate operation?
сб, 16 мар. 2024 г. в 10:18, Lorenz (xha) <me@xha.li>:
>> i think that this is what you want:>>> ```> use strings;> use fmt;>> export fn main() void = {> const mem = strings::toutf8("abc");> const ptr: *[]u8 = &mem;> fmt::println(&mem)!;>> const newPtr = ptr:uintptr - 1;> const ptr2: *[]u8 = newPtr: *[]u8;> fmt::println(ptr2)!;> };> ```>> On Sat, Mar 16, 2024 at 10:09:04AM +0300, Dmitry B wrote:> > Could you show me how to do it... please> >> > I tried:> > ```> > const mem = strings::toutf8("abc");> > const ptr: *[]u8 = &mem;> > fmt::println(&mem)!;> >> > const newPtr = ptr:uintptr - 1;> > const ptr2: *[]u8 = &newPtr;> > fmt::println(ptr2)!;> > ```> > It do not work:> > `error: Initializer is not assignable to binding type`> >> > пт, 15 мар. 2024 г. в 17:38, Lorenz (xha) <me@xha.li>:> > >> > > no, just cast it to a pointer type again (the original type) to get a> > > normal memory address.> > >> > > On Fri, Mar 15, 2024 at 03:04:46PM +0300, Dmitry B wrote:> > > > You mean to do like?> > > > const newPtr = ptr:uintptr - 1;> > > >> > > > I am getting result at form:> > > > 140729276888207> > > >> > > > Do I need to cast it back to hex to get a normal memory address?> > > >> > > > пт, 15 мар. 2024 г. в 14:56, Lorenz (xha) <me@xha.li>:> > > > >> > > > > you can cast to a uintptr and then to your arithmetic with that.
On Sat, Mar 16, 2024 at 10:58:55AM +0300, Dmitry B wrote:
> Yes, that's it. Thanks!> > Where can I read casting rules? What and to what can be casted?> Am I right to understand that everything after `:` is casting?
so the type after the : in bindings is a type hint; for example, if you have
```
let x = 0;
```
the type of x is now int, because, in a nutshell, this is the default type
of numbers.
if you have
```
let x: u32 = 0;
```
the type of x is now u32. however, this is because if we hint the literal
on the right side (the "0") that it should be a u32; the u32 is a type
hint here.
this would not work
```
let x: int = 0u32
```
because the initializing expression ("0u32") has the result type u32 and
is ignoring the type hint (which is int).
there is a lot more involved here. i think that type hint shematics are
not completly specified by the specification yet and therefore, if you
want to dig deeper, you should probably read the harec source code.
casts are afaik specified by the specification.
what is going on is mostly just logical if you think about it, so trial
and error will mostly also work :)
> And is type declaration related to casting? Or is it's separate operation?
that is a seperate operation. again, it's explained in detail in the
specification.
> > сб, 16 мар. 2024 г. в 10:18, Lorenz (xha) <me@xha.li>:> >> > i think that this is what you want:> >> >> > ```> > use strings;> > use fmt;> >> > export fn main() void = {> > const mem = strings::toutf8("abc");> > const ptr: *[]u8 = &mem;> > fmt::println(&mem)!;> >> > const newPtr = ptr:uintptr - 1;> > const ptr2: *[]u8 = newPtr: *[]u8;> > fmt::println(ptr2)!;> > };> > ```> >> > On Sat, Mar 16, 2024 at 10:09:04AM +0300, Dmitry B wrote:> > > Could you show me how to do it... please> > >> > > I tried:> > > ```> > > const mem = strings::toutf8("abc");> > > const ptr: *[]u8 = &mem;> > > fmt::println(&mem)!;> > >> > > const newPtr = ptr:uintptr - 1;> > > const ptr2: *[]u8 = &newPtr;> > > fmt::println(ptr2)!;> > > ```> > > It do not work:> > > `error: Initializer is not assignable to binding type`> > >> > > пт, 15 мар. 2024 г. в 17:38, Lorenz (xha) <me@xha.li>:> > > >> > > > no, just cast it to a pointer type again (the original type) to get a> > > > normal memory address.> > > >> > > > On Fri, Mar 15, 2024 at 03:04:46PM +0300, Dmitry B wrote:> > > > > You mean to do like?> > > > > const newPtr = ptr:uintptr - 1;> > > > >> > > > > I am getting result at form:> > > > > 140729276888207> > > > >> > > > > Do I need to cast it back to hex to get a normal memory address?> > > > >> > > > > пт, 15 мар. 2024 г. в 14:56, Lorenz (xha) <me@xha.li>:> > > > > >> > > > > > you can cast to a uintptr and then to your arithmetic with that.
Thanks a lot!
Could you show me how to access the field with pointer.
Let's assume that memory addressed to the right structure, and
`length` it's field:
```
const newPtr = ptr:uintptr - 8;
const ptr2: *[]u8 = newPtr: *[]u8;
fmt::println(ptr2)!;
let value = *ptr2;
fmt::println(value.*.length)!; // here
```
I tired to use Zig solution (I do not know it, but I googled how to do
same in it), but it do not work.
сб, 16 мар. 2024 г. в 11:43, Lorenz (xha) <me@xha.li>:
>> On Sat, Mar 16, 2024 at 10:58:55AM +0300, Dmitry B wrote:> > Yes, that's it. Thanks!> >> > Where can I read casting rules? What and to what can be casted?> > Am I right to understand that everything after `:` is casting?>> so the type after the : in bindings is a type hint; for example, if you have>> ```> let x = 0;> ```>> the type of x is now int, because, in a nutshell, this is the default type> of numbers.>> if you have>> ```> let x: u32 = 0;> ```>> the type of x is now u32. however, this is because if we hint the literal> on the right side (the "0") that it should be a u32; the u32 is a type> hint here.>> this would not work> ```> let x: int = 0u32> ```>> because the initializing expression ("0u32") has the result type u32 and> is ignoring the type hint (which is int).>> there is a lot more involved here. i think that type hint shematics are> not completly specified by the specification yet and therefore, if you> want to dig deeper, you should probably read the harec source code.>> casts are afaik specified by the specification.>> what is going on is mostly just logical if you think about it, so trial> and error will mostly also work :)>> > And is type declaration related to casting? Or is it's separate operation?>> that is a seperate operation. again, it's explained in detail in the> specification.>> >> > сб, 16 мар. 2024 г. в 10:18, Lorenz (xha) <me@xha.li>:> > >> > > i think that this is what you want:> > >> > >> > > ```> > > use strings;> > > use fmt;> > >> > > export fn main() void = {> > > const mem = strings::toutf8("abc");> > > const ptr: *[]u8 = &mem;> > > fmt::println(&mem)!;> > >> > > const newPtr = ptr:uintptr - 1;> > > const ptr2: *[]u8 = newPtr: *[]u8;> > > fmt::println(ptr2)!;> > > };> > > ```> > >> > > On Sat, Mar 16, 2024 at 10:09:04AM +0300, Dmitry B wrote:> > > > Could you show me how to do it... please> > > >> > > > I tried:> > > > ```> > > > const mem = strings::toutf8("abc");> > > > const ptr: *[]u8 = &mem;> > > > fmt::println(&mem)!;> > > >> > > > const newPtr = ptr:uintptr - 1;> > > > const ptr2: *[]u8 = &newPtr;> > > > fmt::println(ptr2)!;> > > > ```> > > > It do not work:> > > > `error: Initializer is not assignable to binding type`> > > >> > > > пт, 15 мар. 2024 г. в 17:38, Lorenz (xha) <me@xha.li>:> > > > >> > > > > no, just cast it to a pointer type again (the original type) to get a> > > > > normal memory address.> > > > >> > > > > On Fri, Mar 15, 2024 at 03:04:46PM +0300, Dmitry B wrote:> > > > > > You mean to do like?> > > > > > const newPtr = ptr:uintptr - 1;> > > > > >> > > > > > I am getting result at form:> > > > > > 140729276888207> > > > > >> > > > > > Do I need to cast it back to hex to get a normal memory address?> > > > > >> > > > > > пт, 15 мар. 2024 г. в 14:56, Lorenz (xha) <me@xha.li>:> > > > > > >> > > > > > > you can cast to a uintptr and then to your arithmetic with that.
Quoth Dmitry B:
>Hi! Could anybody give an example of pointers arithmetic in Hare?
While Lorenz’s answers aren’t bad, I want to add this: Pointers in
C and pointers in Hare have different semantics.
Yes, both in C and in Hare, a pointer is a “memory address.” But
in C, a pointer is used as an /iterator over an array/ (or over
a single object, as if it were a one-element array). Pointer
arithmetic is iterator arithmetic. A pointer pointing at a single
object and not into an array is a special case of the rules. And
on such a pointer, you wouldn’t—aren’t allowed to, by the
standard!—do arithmetic.
int a[5];
int *p = a; /* iterator pointing to the start of the array */
p += 2; /* advancing the iterator by two elements */
p = a + 5; /* iterator pointing at the end of the array;
i.e., one past the last element */
p = a + 10; /* this addition invokes undefined behavior */
int i;
p = &i; /* special case: pointer to a single object */
++p; /* fine: one past "last element;" just useless */
++p; /* undefined behavior */
extern void f(int *p, size_t n);
f(p + 2, 2); /* passing a "slice" */
/* iterating over an array */
for (int *p = a; p != sizeof a / sizeof *a; ++p)
;
In Hare, a Pointer is a re-assignable reference to an object, but
is not an iterator. Where you’d use a pointer into an array in C,
and do arithmetic on it, in Hare, you’d use either an index or
a slice, depending on what exactly it is you want to do.
let a: [5]int = [...];
let s: []int = a[1:4]; // slicing an array
s = s[1:]; // slicing further
let i = 0;
let j = 0;
let p = &i; // a reference to an object
*p; // you can dereference it
p = &j; // and you can re-assign it
fn f(s: []int);
f(a[2:4]); // passing a slice
// iterating over an array
for (let i = 0z; i < len(a); i += 1)
;
So yes, you can convert a pointer to an integer, do arithmetic on
it, and convert it back. Sometimes, there might even be
a justifiable reason to. But it’s quite likely that you don’t
have such a reason; that it’s a bad idea.
>>```>export fn main() void = {> const mem = strings::toutf8("abc");> const ptr: *[]u8 = &mem; // cast reference to pointer> const offsetPtr = ptr - 8; // playing with pointers arithmetic>};>```>I am getting an error:>`Cannot promote lvalue const *[]u8 and rvalue [iconst min=8 max=8]`
You’re getting the error because there is no arithmetic on
pointers. It doesn’t exist. Hare does not have
pointer-arithmetic.
It's become much clear how Hare works, but how I can print `type` of
data? Is it possible in Hare, or it's too low level?
And for example here.
```
const mem: *[10]u8 = alloc([0...]);
const ptr = &mem;
```
This code is works, but if I want to use type hint here? What type should I use?
I tried `uintptr` but it's wrong type here.
```
const ptr:uintptr = &mem;
```
сб, 16 мар. 2024 г. в 16:44, Lennart Jablonka <humm@ljabl.com>:
>> Quoth Dmitry B:> >Hi! Could anybody give an example of pointers arithmetic in Hare?>> While Lorenz’s answers aren’t bad, I want to add this: Pointers in> C and pointers in Hare have different semantics.>> Yes, both in C and in Hare, a pointer is a “memory address.” But> in C, a pointer is used as an /iterator over an array/ (or over> a single object, as if it were a one-element array). Pointer> arithmetic is iterator arithmetic. A pointer pointing at a single> object and not into an array is a special case of the rules. And> on such a pointer, you wouldn’t—aren’t allowed to, by the> standard!—do arithmetic.>> int a[5];> int *p = a; /* iterator pointing to the start of the array */> p += 2; /* advancing the iterator by two elements */> p = a + 5; /* iterator pointing at the end of the array;> i.e., one past the last element */> p = a + 10; /* this addition invokes undefined behavior */>> int i;> p = &i; /* special case: pointer to a single object */> ++p; /* fine: one past "last element;" just useless */> ++p; /* undefined behavior */>> extern void f(int *p, size_t n);> f(p + 2, 2); /* passing a "slice" */>> /* iterating over an array */> for (int *p = a; p != sizeof a / sizeof *a; ++p)> ;>> In Hare, a Pointer is a re-assignable reference to an object, but> is not an iterator. Where you’d use a pointer into an array in C,> and do arithmetic on it, in Hare, you’d use either an index or> a slice, depending on what exactly it is you want to do.>> let a: [5]int = [...];> let s: []int = a[1:4]; // slicing an array> s = s[1:]; // slicing further>> let i = 0;> let j = 0;> let p = &i; // a reference to an object> *p; // you can dereference it> p = &j; // and you can re-assign it>> fn f(s: []int);> f(a[2:4]); // passing a slice>> // iterating over an array> for (let i = 0z; i < len(a); i += 1)> ;>> So yes, you can convert a pointer to an integer, do arithmetic on> it, and convert it back. Sometimes, there might even be> a justifiable reason to. But it’s quite likely that you don’t> have such a reason; that it’s a bad idea.>> >> >```> >export fn main() void = {> > const mem = strings::toutf8("abc");> > const ptr: *[]u8 = &mem; // cast reference to pointer> > const offsetPtr = ptr - 8; // playing with pointers arithmetic> >};> >```> >I am getting an error:> >`Cannot promote lvalue const *[]u8 and rvalue [iconst min=8 max=8]`>> You’re getting the error because there is no arithmetic on> pointers. It doesn’t exist. Hare does not have> pointer-arithmetic.
And am I right understand that "*[*]str pointer to pointers"
```
const mem: *[*]str = alloc(["abc", "asd", "sdf"]);
```
I do not fully understand how that works.
It's point to start of the array and to what? To every element in array?
вс, 17 мар. 2024 г. в 11:59, Dmitry B <bubnenkoff@gmail.com>:
>> It's become much clear how Hare works, but how I can print `type` of> data? Is it possible in Hare, or it's too low level?>> And for example here.> ```> const mem: *[10]u8 = alloc([0...]);> const ptr = &mem;> ```>> This code is works, but if I want to use type hint here? What type should I use?> I tried `uintptr` but it's wrong type here.> ```> const ptr:uintptr = &mem;> ```>> сб, 16 мар. 2024 г. в 16:44, Lennart Jablonka <humm@ljabl.com>:> >> > Quoth Dmitry B:> > >Hi! Could anybody give an example of pointers arithmetic in Hare?> >> > While Lorenz’s answers aren’t bad, I want to add this: Pointers in> > C and pointers in Hare have different semantics.> >> > Yes, both in C and in Hare, a pointer is a “memory address.” But> > in C, a pointer is used as an /iterator over an array/ (or over> > a single object, as if it were a one-element array). Pointer> > arithmetic is iterator arithmetic. A pointer pointing at a single> > object and not into an array is a special case of the rules. And> > on such a pointer, you wouldn’t—aren’t allowed to, by the> > standard!—do arithmetic.> >> > int a[5];> > int *p = a; /* iterator pointing to the start of the array */> > p += 2; /* advancing the iterator by two elements */> > p = a + 5; /* iterator pointing at the end of the array;> > i.e., one past the last element */> > p = a + 10; /* this addition invokes undefined behavior */> >> > int i;> > p = &i; /* special case: pointer to a single object */> > ++p; /* fine: one past "last element;" just useless */> > ++p; /* undefined behavior */> >> > extern void f(int *p, size_t n);> > f(p + 2, 2); /* passing a "slice" */> >> > /* iterating over an array */> > for (int *p = a; p != sizeof a / sizeof *a; ++p)> > ;> >> > In Hare, a Pointer is a re-assignable reference to an object, but> > is not an iterator. Where you’d use a pointer into an array in C,> > and do arithmetic on it, in Hare, you’d use either an index or> > a slice, depending on what exactly it is you want to do.> >> > let a: [5]int = [...];> > let s: []int = a[1:4]; // slicing an array> > s = s[1:]; // slicing further> >> > let i = 0;> > let j = 0;> > let p = &i; // a reference to an object> > *p; // you can dereference it> > p = &j; // and you can re-assign it> >> > fn f(s: []int);> > f(a[2:4]); // passing a slice> >> > // iterating over an array> > for (let i = 0z; i < len(a); i += 1)> > ;> >> > So yes, you can convert a pointer to an integer, do arithmetic on> > it, and convert it back. Sometimes, there might even be> > a justifiable reason to. But it’s quite likely that you don’t> > have such a reason; that it’s a bad idea.> >> > >> > >```> > >export fn main() void = {> > > const mem = strings::toutf8("abc");> > > const ptr: *[]u8 = &mem; // cast reference to pointer> > > const offsetPtr = ptr - 8; // playing with pointers arithmetic> > >};> > >```> > >I am getting an error:> > >`Cannot promote lvalue const *[]u8 and rvalue [iconst min=8 max=8]`> >> > You’re getting the error because there is no arithmetic on> > pointers. It doesn’t exist. Hare does not have> > pointer-arithmetic.
sorry for the delayed response
On Sun Mar 17, 2024 at 8:59 AM UTC, Dmitry B wrote:
> It's become much clear how Hare works, but how I can print `type` of> data? Is it possible in Hare, or it's too low level?
there's not currently a way to do this, but in the future, it might be
possible to do this via the hosted typechecker (or, more helpfully for
the usecase you have in mind here, via a language server using said
typechecker)
> And for example here.> ```> const mem: *[10]u8 = alloc([0...]);> const ptr = &mem;> ```
the appropriate type hint here is `**[10]u8`: &x's result type is a
pointer to whatever x's result type was, which in this case was *[10]u8