Recent Posts

Pages: [1] 2 3 ... 10
1
Ideas / Re: Remove const
« Last post by lerno on July 31, 2019, 05:56:33 PM »
D has all of this in the way you write it.
2
Ideas / Re: Remove const
« Last post by bas on July 15, 2019, 10:00:01 PM »
(thought experiment using in/out)
Trying to convert const (in combination with pointers) to in/out gives the following:

All examples below as function arguments:

oldnewmeaning
const char*in char*contents may only be read
char*out char*contents may be written, but must be considered uninitialized for reading at moment of call
inout char*contents may be read and written
char**out char**contents may be written, but must be considered uninitialized for reading at moment of call
inout char**contents may be read and written

NOTE that for the char* case, that in the old situation only read+write can be expressed, while in the new
situation, both read-write (inout) AND write-only (out) (or uninitialized reads) can be expressed!

3
Ideas / Re: Remove const
« Last post by bas on July 15, 2019, 07:29:02 PM »
I was recently struggling with the '
Code: [Select]
const int* const' syntax.  This is not yet supported in C2.
To narrow the discussion, I think only const in combination with pointers are an issue.
Code: [Select]
const i32 Max = 10; is no issue. It is roughly equivalent of using a define in C.

Another note for Alias types in C2:
Code: [Select]
type IntP int*;  // alias type
const IntP ip = a; // is a 'const IntP' ... but weird, 'const IntP' is different from 'const int*'

I always use the keyword const in combination with pointer arguments to indicate that the destination
is not changed. This is indeed more of an API thing. Also I recently had to work with a lot of UEFI
code. This is C code with many macros. One is that they use IN and OUT in all the header files. These
expend to nothing and are used like

Code: [Select]
void example(IN Buffer* buffer, OUT Result* result);

This is also use in other languages like Ada:

Code: [Select]
procedure TEST01 ( In_State : IN VECT_B ; Out_State : IN OUT VECT_B );

I think words like IN/OUT read quite naturally. But to include them in C2, we would have
to decide on what this means with pointers or pointers-to-pointers. I can think of the following use-cases:

  • passing pointer - the dest may not be modified
  • passing pointer - the dest may be modified
  • passing pointer-pointer - the param may be modified, normal out-param case
  • passing multiple-dimension pointer arg - dest may not be modified

The goal here should be making the code more readable (or easier to understand),
not allowing extra compiler-optimizations. Or does anyone know if const unlocks some
very powerfull optimizations?

4
Ideas / Re: Remove const
« Last post by lerno on July 14, 2019, 08:35:44 PM »
5
Ideas / Remove const
« Last post by lerno on July 14, 2019, 08:27:14 PM »
Const, as used in C, is often not doing what people think it's doing, and does not offer the protection people think it is protecting.

For pointers, a pointer to a constant struct is saying "using this pointer we will not modify the struct itself (but we may modify what the struct refers to)"

Because of const-ness, functions must guarantee const-ness if they are to be useful. Consider a function foo(int* ptr) it is not allowed to pass a (const int)* pointer to such a function, even if the function does not actually modify the memory region that the pointer points to. For maximal usefulness, functions are therefore forced to declare constness, that is, it should always be foo(i(const int)* ptr)

A valid point is that by declaring an inparameter const it communicates that the function does not modify the parameter, but the injury done by *requiring* could be said to outweigh the benefits.

To try to retain the advantages of const, which avoiding the syntax pollution const can mean, this is a thing C2 could do:

1. A function declares itself const or not const entirely. This is usually a more important distinction than whether each parameter is const or not:

func void foo(int *ptr) const { ... } – will not alter the contents of anything related to the in-pointer. That is, if the signature instead would have been func void foo(int **ptr) const we would not have been allowed to do *ptr = nor **ptr =

The other use that one would retain is declaring global constants.
6
Ideas / Re: Built-in managed pointers
« Last post by lerno on March 24, 2019, 05:19:15 PM »
Rust is very high maintenance in regards to memory management, but I think we should look for a small effort that can take us maybe 70% of the way.
7
Ideas / Re: Defer on functions.
« Last post by lerno on March 24, 2019, 04:21:54 PM »
That's why the defer is part of the function signature and not of the function itself, acting as a decorator macro.

It has some interesting consequences: what about the function pointer?

We could also consider this even simpler by introducing a qualifier, eg

Code: [Select]
// func const FILE open(...) { ... } =>
func const managed FILE open(...) { ... }

And here any struct that is "managed" must have a "StructName.release(StructName *struct)" call.

There are various ways to do it actually.
8
Ideas / Re: Defer on functions.
« Last post by bas on March 24, 2019, 11:20:23 AM »
Interesting idea. I recently read an article about functional languages where one of the basic requirements
of a function call in any language was that the caller could predict its own state after the call returned. This is
not the case anymore when defers are added by the called function..
9
Ideas / Re: Built-in managed pointers
« Last post by bas on March 24, 2019, 11:18:44 AM »
Managed pointers are part of the core design of a language. Rust for example was built around some
management ideas. In those languages you cannot do without something like this. I don't see how
introducing an ideas like this wouldn't alter a C-like language completely.

I think programming in C requires some skill and experience, but like handling a chainsaw. :)
I prefer cutting a tree with a chainsaw (never actually tried though) than with a plastic toy.. (Not comparing
Rust with a toy!). Once you have some experience in C, memory management is not that hard.
10
Ideas / Defer on functions.
« Last post by lerno on March 22, 2019, 11:35:51 AM »
What if functions could add defer to the scope where they are invoked?

Here is some code:

Code: [Select]
func bool do_stuff(i32 resource_id)
{
  Resource *x = get_resource(resource_id);
  defer release_resource(x);
  if (!play_around_with(x)) return false;
  do_some_other_thing(x);
  return foo(x);
}

This is fine, the resource is released no matter what path is taken. However, this always requires the defer.

I envisioned a defer sugar, like this:

Code: [Select]
func bool do_stuff(i32 resource_id)
{
  Resource* x = get_resource(resource_id) @defer(release_resource);
  if (!play_around_with(x)) return false;
  do_some_other_thing(x);
  return foo(x);
}

This would sort of make it more succinct and would also make it possible to use it in an expression.

However, what if there was a "safe" version?

Code: [Select]
func Resource get_resource_with_release(i32 resource_id) @defer(release_resource)
{ ... }

This would be fully equivalent to the code with defer above, but could then be written as:

Code: [Select]
func bool do_stuff(i32 resource_id)
{
  Resource* x = get_resource_with_release(resource_id); // inserts an implicit defer!
  if (!play_around_with(x)) return false;
  do_some_other_thing(x);
  return foo(x);
}

Although resource management is a fine example of this, it's *really* nice for refcounting as if you write the following imaginary code:

Code: [Select]
Foo@ foo = @rcmalloc(sizeof(Foo)); // What is the refcount of foo after this?
foo_something(@rcmalloc(sizeof(Foo))); // Does this leak?

If @rcmalloc returns 1, then rc would be 2 in the first case (except if we have special handling of assignment of RC) and a leak on the second line.
However, if @rcmalloc returns 0, then the second line also leaks.

However, if we let @rcmalloc return rc = 1 AND have the profile of @defer(release), then an implicit defer would ensure that in the scope where called the rc would eventually be decreased (unless assigned to). And this is basically what @autorelease in ObjC does too, but in a less controlled manner.

Even if the above example doesn't make sense, or refcounting shouldn't have language support, it's still a very good way to cheaply enable manual RC built on top of the language.

 
Pages: [1] 2 3 ... 10