Show Posts

This section allows you to view all posts made by this member. Note that you can only see posts made in areas you currently have access to.


Topics - lerno

Pages: 1 2 3 [4] 5
46
Implementation Details / Keywords keywords keywords
« on: October 28, 2018, 11:36:12 AM »
First a quick note: I think the documentation is missing keywords. At least "func" isn't there and there might be more.

Anyway, I note that the types ixx and uxx are keywords in the language. Is there any reason why they are tokens instead of identifiers? Or is this just a consequence of borrowing from clang (c) where they are indeed tokens?

Furthermore, there are today keywords for things that are function lookalikes but are actually more like macros:

- elemsof
- enum_min
- enum_max
- sizeof

If the suggestion to use @ to indicate that the compiler does something special at this point, we could swap them for

- @elemsof
- @enum_min
- @enum_max
- @sizeof

This makes them reseved macro names rather than function names (I personally always found the sizeof operator a bit weird since it looked like a function but was a keyword)

The current list has 46 keywords. Eliminating the types and moving the above mentioned things to the "@ namespace", we get that down to 30.

47
Ideas / Nested comments alt second level of comments.
« on: October 27, 2018, 02:54:12 PM »
As far as I know C2 supports // and /* */ style comments.

I propose a third style of comments that are different from the above. I suggest /+ +/, which is what D uses. Alternatively this commenting style is simply complementing the current ones.

So a few different possible proposals:

1. Allow /* */ to nest

This path is taken by quite a few languages.

2. Introduce a new multi-line comment that is different from /* */ and will ignore any /* */ in the comments.

So:

Code: [Select]
/+
  all is commented */ /* */ /* out here
+/

/*
  all is commented +/ /+ +/ /+ out here
*/

/+ /+  +/ +/  <- parse error.

3. Same as (2) but allow the new comment to nest.

That is this *will* parse:

Code: [Select]
/+ /+  +/ +/

Any of those solutions would be an improvement.

48
General Discussion / Overview of syntax
« on: October 27, 2018, 02:41:05 PM »
I recommend the following two sites for overview of different types of syntax:

https://rosettacode.org
http://rigaux.org/language-study/syntax-across-languages.html

49
Ideas / Cast syntax
« on: October 27, 2018, 01:31:13 PM »
Currently the cast syntax is:

cast<new_type>(variable)

As Bas already mentioned, this looks out of place with the rest of the syntax.

I'm therefore going to list a few alternatives (including the current). For these examples I'm casting "foo" to an i32.
  • cast<i32>(foo)
  • @cast<i32>(foo)
  • cast(foo as i32)
  • @cast(foo as i32)
  • foo as i32
  • foo to i32
  • cast(foo, i32)
  • @cast(foo, i32)
  • foo->i32
  • (foo:i32)
  • cast(foo:i32)
  • @cast(foo:i32)
  • (foo::i32)
  • cast(foo::i32)
  • @cast(foo::i32)
  • i32(foo)
  • foo.as(i32)
  • cast(i32)foo
  • @cast(i32)foo
  • cast[i32](foo)
  • @cast[i32](foo)
  • [i32]foo
  • (i32)(foo)
  • foo :> i32


Those are the ones I've found (and I've done the @ variation for the keyword based ones.


50
General Discussion / Broken link to the forum
« on: October 27, 2018, 11:26:11 AM »
The link from the main c2lang.org to this forum is broken. You get unauthorized access when you use it. You can still edit the URL to enter the forum if you know it’s working but most new visitors might think the server is down.

51
Ideas / More on precedence rules
« on: October 26, 2018, 11:13:00 PM »
In Pony, all operators have mandatory ( ). That is going too far, but maybe we should require them where (1) two or more operators of the same precedence are chained. (2) and where the order of execution is important.

For example, consider a < b > c < d.

Under C/C2 rules that is (((a < b) > c) < d). Here it would be better to explicitly require ( ) be added.

With the new precedence rules == and < has the same precedence. Consequently a < b == c > b becomes ((a < b) == c) > b.

It's a nonsense expression and you should never really do that, but if you were relying on the C behaviour of (a < b) == (c > b) then it can be surprising, even though very few would use the version without parenthesis.

One could require parenthesis in these cases where there often is ambiguity, so the relational operators and possibly logical and/or as well.

It would go with the "don't make it possible to write incorrect code" idea.

52
Ideas / Real arrays
« on: October 26, 2018, 10:36:10 AM »
The "problem" with real arrays have been discussed previously, but I start a new topic here since those discussions are pretty much dead. Instead of arguing for why, let me just write the proposal.

1. All arrays are always passed by reference.

Code: [Select]
func void some_function(int[] x)
{
    x[0] = 1;
}

int[3] x = { 2, 3, 4 };
some_function(x);
assert(x[0] == 1);

2. Passing an array is structurally identical to passing in a struct with length + pointer.

This means that the array some_type[] is exactly equivalent to:

Code: [Select]
type struct
{
   pointer_size length; // <- decide whether this should be platform independent or not.
   some_type *start;
}

BTW, I considered whether we should allow variable bit sizes for the length variable. My conclusion is that it would make the feature too complex. Custom structs are better if that is desired.

3. As a consequence we can define slices on an array, simply by varying the start and length.

Note that the strategy here has to be different if we go with "restrict by default" compared to only using restrict like C does it (aliasing by default). In the latter case, much performance can be gained by having pointer + offset + length instead of pointer + length. If space is an issue for the latter, we can rewrite the struct in this manner:

Code: [Select]
type struct
{
   half_pointer_size offset;
   half_pointer_size length;
   some_type *ptr;
}

This way it's easy to analyse the original pointer, even for slices of that array, and arrays / slices can be used interchangeably.

4. Arrays have manual memory management.

Not much to say about that except for needing an custom allocator function for arrays as it must set the length in the returning data.

5. It should be possible to cast an array to a struct.

Array layout should be fixed with the language, and casting an array to a struct (using whatever fixed layout we decide on) is fine.

6. Undefined behaviour

Changing the value of an underlying pointer, length, offset of an array leads to undefined behaviour.

7. Optional bounds check

Bounds checking is optionally inserted on debug builds.

53
Ideas / A group of function pointers & a struct
« on: October 26, 2018, 12:47:23 AM »
About the only thing I really miss when writing C is when you really want a bunch of different plugins for the same code. It can be different types of loggers, or swapping the printing engine.

In C you typically do that by sending over a struct of function pointers + an opaque struct.

In OO we simply define an interface and implement it.

A simpler way, but one that doesn’t go all the way would be nice. Has this been discussed?

54
General Discussion / Mail of posts / this BBS
« on: October 25, 2018, 02:53:21 PM »
Somewhat unfortunate this forum does not seem to allow (or have enabled?) mail of new posts. I'm also a bit spoiled by modern forums that use markdown.

Can some improvement be made perhaps...? NodeBB is fairly straightforward to set up but the ideal would be some hosted forum that would be free for an open source project.

55
Ideas / C11's _Generic
« on: October 25, 2018, 11:19:44 AM »
I suggest support for a version of _Generic.

The functionality is simple:

Code: [Select]
#define to_num(x) _Generic((x), int:0, char:1, long:2, default:3)

int i = 2;
long x = 100;   

printf("%d / %d / %d\n", to_num(i), to_num(x), to_num(&x));

This prints "1 / 2 / 3"

Basically _Generic acts like a switch:

switch ("type of x") {
   case "int": 0
   case "char": 1
   case "long": 2
   default: 3
}

Because the non-taken paths aren't evaluated, this rather powerful in expressing "overloaded" math functions (to take an example)

This could be used to implement overloads for operators as well.

56
Ideas / Fix C operator precedence rules
« on: October 25, 2018, 12:49:12 AM »
C's precedence rules are not in fact, there are cases where they can be considered really bad.

These are the current rules in C2:

1. (),.*, ->*
2. !,~
3. *, /, %
4. -, +
5. <<, >>
6. >=, <=, >, <
7. ==, !=
8. &
9. ^
10. |
11. &&
12. ||
13. ?
14. =, *=, /=, %=, +=, -=, <<=, >>=, &=, ^=, |=
15. ,

I would suggest a flatter and more reasonable precedence order:

1. (),.*, ->*
2. !,~
3. *, /, %
4. <<, >>
5. &, ^, |
6. -, +
7. ==, !=, >=, <=, >, <
8. &&, ||
9. ?
10. =, *=, /=, %=, +=, -=, <<=, >>=, &=, ^=, |=
11 ,

This means that we cant write something like a || b && c || d && e and expect anything other left-to-right evaluation. In my opinion the operator precedence rules here are allowing hard-to-read code.

We're also removing the common pitfall of a << 3 + b << 2, it's no longer evaluated to (a << (3 + b)) << 2 but instead (a << 3) + (b << 2).

Flattening the bitwise operators follows the same rationale as for logical and/or. An expression such as a | b ^ c & d which has the evaluation of (a | (b ^ (c & d))) might be unexpected for many.

Moving the bitwise operators before comparisons finally allows us for the intuitive code of a & b == 0 instead of the currently required (a & b) == 0. I would say that the standard evaluation of a & (b == 0) is virtually never intended.

We'd be removing three levels of precedence and creating code that's easier to understand and remember. (And the bitwise operator precedence of C should be considered a bug more than anything.)

Other languages with similar precedence rules: Julia, Nim, Zig, Python.

57
General Discussion / Contribute / get into the code
« on: October 24, 2018, 10:05:33 PM »
If I'd like to contribute to the code, is there some area where one reasonably could do some minor cleanup / additions without having to understand the entire code and it's useful enough that you'd accept a pull req once it's done?

I noticed that there were two pull requests that wasn't accepted, if I spend some time doing additions I'd like to make sure it's somewhere helpful. So where could one start?

(BTW, the code is a bit inconsistent in its formatting, consider a style guide for the source)

58
Ideas / Expression blocks
« on: October 22, 2018, 09:41:37 PM »
GNU has an extremely useful extension in expression blocks using ({ ... })

The suggestion I have is to allow C2 to implement those as a standard. There are a few ways to pick the syntax (that I can think of):

  • Retain the GNU format
  • Let any block ending with an *unterminated* expression return the value of that statement e.g. { foo = bar(); foo } is an expression returning the value of foo, while { foo = bar(); foo(); } is a normal statement.
  • Use normal ( ) but allow statments. e.g. ( foo = bar(); foo )
  • Use something similar to the GNU format but write explicit return, e.g. [{ foo = bar(); return foo() }] it would still be equivalent to the code above.
Also note that the value-returning macro becomes easy to express for the versions with explicit return. It's simply a macro wrapped in an expression block.

59
Ideas / In-loop definitions
« on: October 22, 2018, 09:31:55 PM »
This is a features I was considering for my own language.

Basically we recognize that in cases like this, we unnecessarily leak information to the outer scope:

Code: [Select]
int result;
if ((result = do_something()) != ERR_RESULT) {
  do_something_with_result(result);
}

Object *obj;
while ((obj = next_object()) != NULL) {
   ... do stuff ...
}

We could extend the syntax with an declaration:

Code: [Select]
if (int result; (result = do_something()) != ERR_RESULT) {
  do_something_with_result(result);
}

while (Object obj; (obj = next_object()) != NULL) {
   ... do stuff ...
}

switch (int result; (result = value())) {
  ...
}
 

There are a few more possibilities for separator:

Code: [Select]
while (Object obj : (obj = next_object()) != NULL) { 
   ...
}

while (Object obj, (obj = next_object()) != NULL) { 
   ...
}

while (Object obj | (obj = next_object()) != NULL) { 
   ...
}

while (Object obj :: (obj = next_object()) != NULL) { 
   ...
}

Obviously this is simply about extending what we have in "for" to a more general case.

60
Ideas / Add defer
« on: October 22, 2018, 10:16:33 AM »
I suggest adding defer statements to C2. In the vein of the same feature in Zig, Jai, Go etc

Pages: 1 2 3 [4] 5