Recent Posts

Pages: 1 2 3 [4] 5 6 ... 10
31
Implementation Details / Re: CTC (partial, full, none)
« Last post by lerno on February 12, 2019, 12:47:59 AM »
Of what use is CTC partial? I don't really see it.
32
Ideas / Explicit non-null-ness
« Last post by lerno on February 02, 2019, 12:28:24 PM »
I suggest we reuse & arg to mean a pointer that is guaranteed to be non-null.

Consider the following methods:

Code: [Select]
Foo& foo();
Foo* foo2();
void bar(Foo& f);
void bar2(Foo* f);

Unlike in C++, both Foo& and Foo* are pointer, the former guaranteed to be not null.

Code: [Select]
Foo *f1 = foo(); // Non null to nullable ok
Foo &f2 = foo2(); // Nullable to non null not allowed

A check allows conversion:

Code: [Select]
Foo *f = foo2();
assert(f);
Foo &f2 = f;

Or:

Code: [Select]
Foo *f = foo2();
Foo &f2 = f ? f : foo();

With the elvis operator:

Code: [Select]
Foo &f = foo2() ?: foo();

Using pointer without nullcheck is a warning:

Code: [Select]
Foo* f = foo2();
return f.a; // warn, f may be null.

Solution is adding the assert test, or supress null warning with an attribute

Code: [Select]
Foo *f = foo2();
return f.a @(notnull);
33
Implementation Details / Re: C2 in C
« Last post by lerno on February 01, 2019, 10:37:40 PM »
I know, but the parser is sometimes hardcoded to identify types (or sometimes even just built in types). This should be relaxed in order to allow more compile time evaluation – which in turn opens up for semantic macros.
34
Ideas / Re: Require explicit (un)initialization.
« Last post by lerno on January 31, 2019, 12:43:19 AM »
I like the reuse of void.

In regards to int a; initialized to zero implicitly - I understand the thought that this is counter to whar one usually expects. On the other habd this makes static and local variables behave exactly the same way and it simplifies how one reasons about struct init.

For example, it is more natural to expect Foo f = { .one_field = 1 } to actually zero out all other fields in the struct if we have implicit zeroing.

An alternative would be to disallow int a; completely, requiring it to either be initialized to ”void” or some value. On the other hand, that would then also need to be true for göobals, and I don’t know if this added requirement for statics is something that would be appreciated.
35
Ideas / Re: Require explicit (un)initialization.
« Last post by chqrlie on January 30, 2019, 09:06:15 PM »
I don't like mandatory initialization either, but implicit initialization to the zero value of the type is confusing too. The compiler should just issue an error, not a warning when it detects that a variable is used before intialization. There are border cases where it is difficult, or plain impossible to determine if a variable was initialized or not, requiring explicit initialization in these cases is OK IMHO. This is basically what I get with `-Wall -Werror`.

Regarding a possible syntax to specify uninitialized status, I would suggest:

Code: [Select]
int a = void;  // a not initialized, warning if used before later assignment.
This could be used to tell the compiler that a variable is no longer valid and thus prevent its use in further computations. For example:

Code: [Select]
free(p);
p = void;
return p;   // error: use of an invalid value.

36
Ideas / Require explicit (un)initialization.
« Last post by lerno on January 30, 2019, 06:07:18 PM »
Instead of warning on non-initialized variables and explicitly initializing, consider the following change:

Code: [Select]
int a; // a initialized to 0, as if it was static.
int a = 10; // a initialized to 10
int a = uninitialized; // a not initialized, warning if used before later assignment.

Alternatives to uninitialized:

Code: [Select]
int a = ---;
int a = *;
int a = ?;
37
Ideas / Re: Macro-system design
« Last post by lerno on January 30, 2019, 10:48:55 AM »
All of the above ties into the generics proposal. The generics being a way to create packets of macros basically, but has space advantages.
38
Ideas / Re: Macro-system design
« Last post by lerno on January 30, 2019, 10:47:08 AM »
Allowing nested macros could allow us to do recursive macro resolution, which opens up compile time execution.
39
Ideas / Re: Macro-system design
« Last post by lerno on January 30, 2019, 10:41:04 AM »
In the case of the inline body I think this would be reasonable:

Code: [Select]
public macro foreach(thelist, @body(Element *) ) {
   Element* iname = thelist.first;
   while (iname != nil) {
      @body(iname);
      iname = iname.next;
   }
}

Or a version that is more flexible:
Code: [Select]
public macro foreach(thelist, @body(typeof(thelist.first)) ) {
   typeof(thelist.first) iname = thelist.first;
   while (iname != nil) {
      @body(iname);
      iname = iname.next;
   }
}

Usage:

Code: [Select]
foreach(list, Element *i) { // <- Note type declaration!
   i.print();
}

Since type is going to appear very often, we could make a shortcut for it, like $@ as prefix meaning "typeof".

We then get

Code: [Select]
public macro foreach(thelist, @body($@thelist.first) ) {
   $@thelist.first iname = thelist.first;
   while (iname != nil) {
      @body(iname);
      iname = iname.next;
   }
}

Possibly we could even write the code like this:

Code: [Select]
public macro foreach(thelist, @body($element_type) ) {
   $element_type iname = thelist.first;
   while (iname != nil) {
      @body(iname);
      iname = iname.next;
   }
}

In this case $element_type works like "auto", but is also assigned the type, which then can be referred to in the signature.
40
Ideas / Re: Macro-system design
« Last post by lerno on January 30, 2019, 10:33:30 AM »
1. I think it's a bad idea to syntax check the macros using types (the "List" type) there. In order to show constraints, prefer contracts like in the Go2 proposal. Such a contract can include type if one wants to.

Possibility (1) inline require/contract

Code: [Select]
public macro foreach(thelist, iname) {
   @require {
      thelist.first;
      thelist.first.next == thelist.first;
   }
   Element* iname = thelist.first;
   while (iname != nil) {
       // macro body should be here, How to specify?
      iname = iname.next;
   }
}

We can then continue making this even more general:

Code: [Select]
public macro foreach(thelist, iname) {
   @require {
      thelist.first;
      thelist.first.next == thelist.first;
   }
   typeof(iname.first) iname = thelist.first;
   while (iname != nil) {
       // macro body should be here, How to specify?
      iname = iname.next;
   }
}

I suggest the use of compile time variables to clean up things:

Code: [Select]
public macro foreach(thelist, iname) {
   @require {
      thelist.first;
      thelist.first.next == thelist.first;
   }
   $element_type = typeof(iname.first); // Not visible after compilation
   $element_type iname = thelist.first;
   while (iname != nil) {
       // macro body should be here, How to specify?
      iname = iname.next;
   }
}

The alternative to inline contracts are external ones:

Code: [Select]
type List contract {
   self.first;
   self.first.next == self.first;
}

public macro foreach(@List thelist, iname) {
   $element_type = typeof(iname.first); // Not visible after compilation
   $element_type iname = thelist.first;
   while (iname != nil) {
       // macro body should be here, How to specify?
      iname = iname.next;
   }
}

Pages: 1 2 3 [4] 5 6 ... 10