Monday, May 27, 2019

Digest for comp.lang.c++@googlegroups.com - 25 updates in 3 topics

Chris Vine <chris@cvine--nospam--.freeserve.co.uk>: May 21 11:47AM +0100

On Tue, 21 May 2019 09:25:19 +0200
> well defined in the C++ standard and that it is portable across different
> platforms. Fortunately, it works on the platforms that I use.
> Or is there a method that is clearly supported by the C++ standard?
 
The problem with aliasing arising from type punning concerns
dereferencing pointers which do not represent the "dynamic type" (in C
the "effective type") of the object being pointed to. The compiler is
entitled to assume that the object obtain by dereferencing, say, an
int* is actually an int and not a float. Does your case fall foul of
this?
 
A memcpy() is just another form of assignment: it so happens that
with a cast the dynamic type of the result of the cast remains the
source type, but with memcpy() it becomes the type of the destination.
However I can see that memcpy() might be problematic with device
registers because I don't think it has any atomicity guarantees. I
guess in that case using a union with volatile members might be the
answer: it is probably supported by your compiler. I don't actually
know what the standard says about unions with volatile members - when I
get a chance I must look it up.
 
Chris
Paavo Helde <myfirstname@osa.pri.ee>: May 22 07:35PM +0300

On 22.05.2019 19:02, Bart wrote:
 
>> 9223372036854775807 + 1 == -9223372036854775808
 
> In itself it's not that useful. What is useful is that if it happens:
 
> * It is not undefined behaviour
 
Meaning it cannot be defined to behave in other and potentially more
useful ways in special circumstances.
 
> * It produces the same consistent, predictable results
 
It does not, because you have defined addition as "at least 64 bits".
You should define it as "exactly 64 bits" to get consistent and
predictable results.
 
> * Those results can help in detecting whether there was an overflow, if
> that was unintentional
 
That was my question, what is the intentional use?
 
Detecting overflow by results only works in case of a single addition.
Which means most unintentional uses go undetected.
 
If the overflow were defined as an error, then it could be always detected.
 
> * It matches the same behaviour as many other languages and compilers
 
Who cares? You certainly don't. Besides, the hardware has evolved a lot
since those languages were designed, I suspect doing consistent overflow
detection might not reduce performance significantly because the memory
bus runs several times slower anyway nowadays.
 
> * If you do 9223372036854775807 plus 1, then minus 1, you will get back
> 9223372036854775807.
 
In case of a single addition - yes. With more complicated expressions -
no. And why should I want to do that anyway?
 
> might do:
> a+b
> asm jo overflow
 
This is different from your original claim that addition just uses
silent signed overflow. Now it appears there is another side-channel
result. This actually is already much better, especially if the overflow
flag is consistently set and remains sticky after evaluating more
complex expressions (kind of NaN propagation in floating-point
calculations, signalling that something went wrong along the way).
 
> to detect overflow. Although this wouldn't translate to C because of the
> ASM, you don't want the a+b to be undefined behaviour.
 
> * Generally, you just want to mainly use signed rather than unsigned.
 
Agreed. But this is not for overflow. Rather vice versa, signed ints
help to *avoid* overflow around zero which is a common plague for unsigned.
 
> Some operations (eg. converting signed int to and from float is
> supported in hardware by x64, but not unsigned.). Then you don't want to
> worry about the possibility of UB.
 
Always yielding an error would not be UB, and would be much better than
silently producing invalid results.
Ben Bacarisse <ben.usenet@bsb.me.uk>: May 20 09:24PM +0100

> can be stored in a union at any time."
 
> Which would imply that reading from a non-active member is the same as
> reading from an uninitialized variable.
 
I didn't think that was quite enough, though it should have been enough
to prompt me to look for some more details. As you say it implies as
much as it says! Tim has very helpfully provided a thorough collection
of quotes.
 
--
Ben.
blt_14rUt9Szv@2mu00w.co.uk: May 21 08:26AM

On Mon, 20 May 2019 19:04:59 +0100
>> 1.234000
 
>> Sorry, what was that you were saying?
 
>Sorry, what exactly do you think you were proving?
 
Are you having a slow brain day or something? You said it wouldn't work on
new compilers with optimisation. I just proved it did just as I've said it
works on every compiler I've ever tried it on.
 
>Your crap code with undefined behaviour looks as if it is too
>inconsequential for g++ to optimize against it. gcc/g++ will however
 
LOL, oh please, give it up before you make a complete fool of yourself :)
 
>warn that your code is non fit for purpose - it tells you that it
>breaks strict aliasing rules.
 
Clang doesn't and clang is a better compiler all round IMO.
"Fred.Zwarts" <F.Zwarts@KVI.nl>: May 21 01:43PM +0200

"Chris Vine" schreef in bericht
news:20190521114749.d756ce67e9563bfa8c3fd2da@cvine--nospam--.freeserve.co.uk...
>entitled to assume that the object obtain by dereferencing, say, an
>int* is actually an int and not a float. Does your case fall foul of
>this?
 
Device registers normally do not use floating point types. They usually
contain integer values, or bit patterns. But even if they contain a floating
point type, it may not match the format of the host system, so one has to
separate the manitissa and the exponent and construct a floating point value
from it.
I always use pointers to uint8_t, uint16_t, uint32_t or uint64_t to access
such registers. I don't think that will be a problem.
 
Paavo Helde <myfirstname@osa.pri.ee>: May 21 07:50PM +0300

On 21.05.2019 16:52, Juha Nieminen wrote:
> chance of losing accuracy when it's read back, for the simple
> reason that the base-10 representation cannot accurately represent
> every single base-2 floating point value.
 
With enough digits, a decimal (as well as any other) representation can
get arbitrarily close to any real value, so it can also get arbitrarily
close the any value represented exactly in base-2. It is not needed to
represent the base-2 value exactly, it is just enough to provide any
base-10 value which is rounded to the correct base-2 value.
 
Historically there were indeed some round-trip bugs when serializing
floating-point values, but AFAIK these bugs got fixed in the C runtime
libraries about 10-20 years ago or so. Plus there are libraries which
ensure the minimum number of decimal digits for perfect round-trip.
 
Maybe you wanted to say that ensuring a proper round-trip is trickier in
base-10 than in base-16 and it may easily waste more bytes than strictly
necessary?
"Fred.Zwarts" <F.Zwarts@KVI.nl>: May 21 09:25AM +0200

"Chris Vine" schreef in bericht
news:20190520174928.c77ab71214afbd6375a5bbce@cvine--nospam--.freeserve.co.uk...
>it will be optimized out where a cast would (but for strict aliasing)
>work, and will still work where casting wouldn't (such as when casting
>would result in misalignment).
 
I need type punning often when accessing device registers. E.g., for a given
VME address it makes a difference whether it is accessed in D8 mode (byte
access), D16 (16-bit) mode or D32 (32-bit) mode. memcpy for device registers
is a bad idea, because it is not defined what bit-size will be used for the
copy.
I have the feeling that only type punning, in combination with a volatile
declaration is a good method for this purpose. But I am not sure that it is
well defined in the C++ standard and that it is portable across different
platforms. Fortunately, it works on the platforms that I use.
Or is there a method that is clearly supported by the C++ standard?
David Brown <david.brown@hesbynett.no>: May 20 10:01PM +0200

On 20/05/2019 21:06, Tim Rentsch wrote:
 
<snip detailed explanation and references>
 
 
> Taken together I think these passages make the case pretty
> airtight.
 
Thank you. I can see why I failed to find a simple, clear reference
covering this case!
scott@slp53.sl.home (Scott Lurndal): May 21 07:53PM

>On Tue, 21 May 2019 11:49:13 +0100
 
>The code works and always has done. A pointer is always the same size for
>every type and always will be.
 
Actually at least one major processor vendor has been thinking about
changing this in the future.....
 
And it certainly wasn't true in the past.
Paavo Helde <myfirstname@osa.pri.ee>: May 22 09:16PM +0300

On 22.05.2019 20:24, Hans Bos wrote:
 
> But there is no guarantee that the radix is 2.
> Suppose my system has doubles with radix 10.
> What, in that case, is the exact hex representation of 0.1?
 
Right, the actual requirement is just "Hexadecimal floating-point
formatting ignores the stream precision specification". I guess it could
round all numbers to 0 if it wanted.
Bonita Montero <Bonita.Montero@gmail.com>: May 21 08:47PM +0200

> communicates better to the reader, but I believe for reasons having to
> do with a shortcoming of C++03 Herb Sutter and Andrei Alexandrescu
> recommended used `static_cast` in their old coding guidelines book.
 
static_cast, reinterpret_cast or C-style-cast - pure syntatic sugar.
blt_4zFq6df@yjohgzcnb.gov.uk: May 22 03:48PM

On Wed, 22 May 2019 00:18:13 +0200
>> changing this in the future.....
 
>> And it certainly wasn't true in the past.
 
>It is not true at the moment either. There are more processors around
 
So which architectures have a variable number of memory addressing bits
depending on what C type is stored at the address then?
Manfred <noname@invalid.add>: May 20 09:38PM +0200

On 5/20/19 7:26 PM, Ben Bacarisse wrote:
 
> I've cut the quoted text because your reply appears to be about the
> above, not what I wrote (though I may have misunderstood).
 
> <cut>
<recut>
 
>> Reading from not active member
>> is undefined ...
 
> Do you know where this is stated?
 
I think it is a consequence of the first sentence:
9.5 p1:
"...at most one of the non-static data members can be active at any
time, that is, the value of at most one of the non-static data members
can be stored in a union at any time."
 
Which would imply that reading from a non-active member is the same as
reading from an uninitialized variable.
 
But, 9.2 p19 explicitly allows the case of reading the common initial
sequence.
David Brown <david.brown@hesbynett.no>: May 21 11:57PM +0200

On 21/05/2019 16:45, Bart wrote:
>> and their standards that matter.
 
> But how can code that expresses exactly the same thing be fine in one
> language and not in another?
 
That's a meaningless question. If the code expresses exactly the same
thing in different languages, then it is fine in those languages. Code
that does not have defined behaviour in a language is not expressing
anything at all - totally regardless of whether similar looking code has
a meaning in a different language.
 
 
 
> And here apparently the same code can be also be fine in a particular
> dialect of C or C++, or even using a particular set of compiler options,
> but be 'crap' when someone changes the compiler or option.
 
Now you are beginning to understand!
 
Code has to be written in a programming language. If the words and
symbols you use don't make sense in that language, then the code is
wrong - even if the same words and symbols make sense in a different
language or different language variation.
 
 
 
>   11111110111001100110011001100110011001100110011001100110011010
 
> No faffing about with unions or *(int64_t*)&x casts (which won't work on
> 0.1), which apparently have UB anyway, or memcpy.)
 
Your language is not C. In C, you do this differently - as you can't
access the float via a pointer to a 64-bit integer type, and there is no
pre-defined method of printing in binary anyway. Why does it bother you
so much that you have to write different things in different languages?
 
>> your language is "better" than C?
 
> It's 'better' in that it allows this sort of obvious stuff that people
> want to write, while C doesn't.
 
I don't believe that many people /do/ want to write this sort of thing,
and it is certainly not "obvious". (The implementation, and assembly
level, is obvious. But we are not programming in assembly.)
 
I can appreciate that /you/ want to use concepts like this, and thus it
makes sense to have it as a feature in your personal language. But I
have long ago given up trying to understand /why/ you want to do it or
why you find these things so useful in your coding. Perhaps they just
happen to be helpful in writing compilers and translators.
Bart <bc@freeuk.com>: May 22 06:35PM +0100

On 22/05/2019 17:35, Paavo Helde wrote:
>> * It is not undefined behaviour
 
> Meaning it cannot be defined to behave in other and potentially more
> useful ways in special circumstances.
 
No. But it also means you know exactly what it will or won't do.
Otherwise what you get depends on the whim of the compiler (eg. see below).
 
 
> It does not, because you have defined addition as "at least 64 bits".
> You should define it as "exactly 64 bits" to get consistent and
> predictable results.
 
No, that simply means this, in this table of operand sizes and operation
sizes:
 
Largest operand My Lang Most Windows Cs
 
8 bits evaluated as 64 bits 32 bits
16 64 32
32 64 32
64 64 64
128 128 (128 where supported)
 
So the operation will be usually be 64, and 128 bits in the rare case of
those larger operands (which anyway are not standard C so 'A+B' would
not appear in the C source). In C, even on 64-bit hardware, most
operands below 64 bits will be operated on at 32 bits. This is another
point of incompatibility to deal with.
 
 
 
>> * Those results can help in detecting whether there was an overflow, if
>> that was unintentional
 
> That was my question, what is the intentional use?
 
And I said there needn't be one. This is after all fixed-width binary
computer arithmetic; there are well-known limitations, tied to
well-known hardware behaviours that are common to both signed and
unsigned arithmetic. And we are using language with fairly primitive
machine-oriented types.
 
It's mainly C (and hence C++) that have decided to apply UB in the case
of signed arithmetic, in order to give compilers a licence to do
whatever the hell they like, it seems.
 
If I want different behaviour without those limitations then I might use
a float type, or for exact integer results I could use a big-number
type. But very few cases of ordinary, everyday computation really need
to resort to that.
 
 
> If the overflow were defined as an error, then it could be always detected.
 
>> * It matches the same behaviour as many other languages and compilers
 
> Who cares? You certainly don't.
 
Take this program:
 
#include <stdio.h>
int main(void) {
int a=0x7FFFFFFE;
for (int i=0; i<6; ++i) printf("%d\n", a++);
}
 
What output is expected? Well, /I/ would at least expect 6 lines of
output, and expect each line to be different, like this:
 
2147483646
2147483647
-2147483648
-2147483647
-2147483646
-2147483645
 
With nearly all C compilers, I get exactly with. Except with optimised
gcc I get:
 
2147483646
2147483647
2147483647
2147483647
2147483647
2147483647
 
Now let's modify the heart of that program to this:
 
int a=0x7FFFFFFC;
for (int i=0; i<10; ++i) printf("%d\n", a++);
 
What output now? Well, how about 10 lines of output, all different, like
this:
 
2147483644
2147483645
2147483646
2147483647
-2147483648
-2147483647
-2147483646
-2147483645
-2147483644
-2147483643
 
This is from my own C compiler, but every other compiler I have produces
the same, including gcc-O0, EXCEPT for gcc-O3 which generates this:
 
2147483644
2147483645
2147483646
2147483647
-2147483648
-2147483647
-2147483646
-2147483645
-2147483644
-2147483643
-2147483642
-2147483641
-2147483640
-2147483639
-2147483638
-2147483637
.....
....
 
It goes on forever.
 
So on the one hand you have the predictable output that common sense
tells you is what should happen. On the other hand, using UB, you get
two different lots of unexpected behaviour, neither of which matches the
common sense compilers.
 
Is /that/ is supposed to be preferable?
 
How on earth could an clear 0 to 9 loop turn into an endless loop?
Ian Collins <ian-news@hotmail.com>: May 22 11:55PM +1200

On 22/05/2019 22:14, Bart wrote:
 
> I thought this was some magic incantation to wave away all errors. But I
> tried it on my test (a 2900-Loc Linux version of the C file), and the
> lines of errors and warnings went up from 1100 to 2100!
 
C++ has much stricter type conversion rules than C.
 
> (Input was this file: https://github.com/sal55/qx/blob/master/jpeg.c,
> generated by an older compiler as new ones have dropped the C target.)
 
Just compile as C and disable the (generally harmless) warnings.
 
$ gcc -std=c99 jpeg.c -Wno-format -c
$
 
--
Ian.
Chris Vine <chris@cvine--nospam--.freeserve.co.uk>: May 21 04:28PM +0100

On Tue, 21 May 2019 15:45:48 +0100
> > and their standards that matter.
 
> But how can code that expresses exactly the same thing be fine in one
> language and not in another?
 
What a weird thing to say. Code that expresses exactly the same thing
can be fine in one language but not in another because the respective
standards for those languages say so.
 
In setting a standard, it is a matter of choice for the language
designer involving trade-offs between amongst other things optimization
opportunities, convenience to the programmer, language complexity and
safety.
David Brown <david.brown@hesbynett.no>: May 21 03:45PM +0200

On 21/05/2019 09:25, Fred.Zwarts wrote:
>> work, and will still work where casting wouldn't (such as when casting
>> would result in misalignment).
 
> I need type punning often when accessing device registers.
 
That is strange. I work with device registers all the time, and I
rarely use type punning.
 
The usual way to access hardware registers is via "volatile uint32_t *"
or similar pointers, with the size you want to use. Often you use
structs rather than individual pointers, but it boils down to the same
kind of volatile accesses.
 
"Type punning" is when you have told the compiler that object A is of
type T, and you know want to access it while pretending it is type U.
You are not doing that, as far as I can tell.
 
> across different platforms. Fortunately, it works on the platforms that
> I use.
> Or is there a method that is clearly supported by the C++ standard?
 
Exactly how "volatile" works, and in particular for accesses via an
absolute address cast to a pointer-to-volatile, is not as clearly
defined as it could be in C and C++. C17 clarifies it - maybe newer C++
standards inherit this improvement. But all compilers have implemented
it in the same obvious manner.
Keith Thompson <kst-u@mib.org>: May 22 11:04AM -0700

blt_xfnfdm@x1c.ac.uk writes:
[...]
> baldur$ ./a.out
> 1.234000
 
> Sorry, what was that you were saying?
 
Sorry, what does a C program, compiled with a C compiler, prove about
C++?
 
Yes, you're likely to get similar results if you compile it as C++ --
which is consistent with the behavior being undefined.
 
--
Keith Thompson (The_Other_Keith) kst-u@mib.org <http://www.ghoti.net/~kst>
Will write code for food.
void Void(void) { Void(); } /* The recursive call of the void */
blt_1d31iu1a18@dxekg86ut76lwln.org: May 21 07:28PM

On Tue, 21 May 2019 11:49:13 +0100
 
>The "it" which doesn't work is type punning through casting pointers.
>Your silly toy code with undefined behaviour proves absolutely
>nothing. An example has already been given up-thread of the
 
Me: "The code works on every compiler I've ever tried"
 
You: "But it won't work on modern compilers with optimisation!"
 
Me: [Shows code doing exactly that with 2 compilers]
 
You: "Oh well, its just silly toy code blah blah feeble backpedal blah blah"
 
>differences which can arise in code emitted, depending on whether the
>-fno-strict-aliasing switch is applied or not.
 
And someone else explained what happened which was nothing to do with type
punning.
 
>"ignore that because although gcc warns that it breaks strict aliasing,
>clang doesn't". If that is your approach to programming then "crap
>code" seems like too mild a description.
 
The code works and always has done. A pointer is always the same size for
every type and always will be.
 
However, feel free to provide a proper example where it fails or you can just
keep on farting out indignant hot air. You choice.
Bart <bc@freeuk.com>: May 21 12:35PM +0100

On 21/05/2019 11:49, Chris Vine wrote:
 
> The "it" which doesn't work is type punning through casting pointers.
> Your silly toy code with undefined behaviour proves absolutely
> nothing.
 
Undefined behaviour because the language says so.
 
>> Clang doesn't and clang is a better compiler all round IMO.
 
> So the standard says clearly that it is undefined behaviour
 
Only because the language says so.
 
but you say
> "ignore that because although gcc warns that it breaks strict aliasing,
> clang doesn't". If that is your approach to programming then "crap
> code" seems like too mild a description.
 
It's only 'crap code' because the language says so.
 
My opinion is that such code can be valid, and it can be well-defined
(within a range of machines that might be the only ones you're
interested in). Or the behaviour might be specific to that a range of
machines. But that's OK because we're low-level programmers and we know
what we're doing, right?
 
My approach is not to use C or C++, partly because all their silly rules
on UB (which seem to only exist to enable extreme optimisations) make
life harder.
 
And to use alternative languages. But if those other languages can
successfully run the same code on the same machines without UB, then
what are C and C++ playing at?
 
This is a recent bit of code I used (expressed here as C, and inside a
struct definition):
 
...
union { // anonymous union
int32_t modelist[4];
int32_t mode;
};
 
I want to be able to access (read or write) the first 4 bytes of that
union interchangeably as either .mode or .modelist[0], including writing
as .modelist[0] then reading immediately as .mode.
 
Isn't that technically UB in C or C++? I don't know, but the important
thing is that I don't need to care!
 
As for type-punning, in the alternate language I use it is an official
feature! int->float type-punning, in C-like syntax, might be written as
(float@)a, where a is an int, and it can also work as (float@)(a+b).
 
(The C/C++ idiom would be *(float*)&a which only works on lvalues.)
 
I don't see it as being anything different from this:
 
a: dd 0 # 32-bit location
mov [a],eax # write 32-bit int
movd xmm0,[a] # read as 32-bit float
 
What does the code mean? Well if eax contained 0x3F800000, then it's
writing the binary representation of the IEEE float32 value 1.0.
 
And the [a] could be [esi] where esi contains a pointer that is
interpreted as int32_t* then float32* on successive lines.
 
All perfectly reasonable things that you might want to do.
Bonita Montero <Bonita.Montero@gmail.com>: May 21 06:23PM +0200

> void *p = malloc(sizeof(float));
> float *fp = p;
> *fp = 1.0f;
 
LOL.
Horizon68 <horizon@horizon.com>: May 21 03:27PM -0700

Hello..
 
 
About my new invention that is a Fast Mutex..
 
I have just invented a Fast mutex with the following characteristics:
 
1- Starvation-free
2- Good fairness
3- It reduces very efficiently the cache coherence traffic
4- Very good fast path performance
 
But can you please run the following windows 64-bit benchmark of it and
report to me the results, but you need to have 8 cores or more, here is
the benchmark of mine:
 
https://sites.google.com/site/scalable68/benchmark-of-my-new-fast-mutex
 
 
 
Thank you,
Amine Moulay Ramdane.
Horizon68 <horizon@horizon.com>: May 21 03:32PM -0700

On 5/21/2019 3:27 PM, Horizon68 wrote:
 
> https://sites.google.com/site/scalable68/benchmark-of-my-new-fast-mutex
 
> Thank you,
> Amine Moulay Ramdane.
 
 
And please report also to me how many cores you have.
 
 
Thank you,
Amine Moulay Ramdane.
Mr Flibble <flibbleREMOVETHISBIT@i42.co.uk>: May 21 11:46PM +0100

Hi!
 
neos progress report time!
 
neos now fully parses my "neoscript" fibonacci example/test program!
Semantic concepts are emitted now all that needs to be done is to add
semantic concept folding and semantic concept bytecode emission so I can
run the program!
 
Compilation session (scroll to bottom to see test program source code):
 
neos 1.0.0.0 ED-209
Loading schema 'neoscript.neos'...
Language: Default neoGFX scripting language
Version: 1.0.0
Copyright (C) 2019 Leigh Johnston
emit: <3> language.keyword ()
emit: <4> string.utf8.character.alpha (n)
emit: <5> string.utf8.character.alpha (e)
emit: <5> string.utf8.character.alpha (o)
emit: <5> string.utf8.character.alpha (s)
emit: <5> string.utf8.character.period (.)
emit: <6> string.utf8.character.alpha (s)
emit: <7> string.utf8.character.alpha (t)
emit: <7> string.utf8.character.alpha (r)
emit: <7> string.utf8.character.alpha (i)
emit: <7> string.utf8.character.alpha (n)
emit: <7> string.utf8.character.alpha (g)
emit: <4> module.package.name ()
emit: <3> module.package.import ()
emit: <3> module.package.instantiate ()
emit: <3> language.keyword ()
emit: <4> string.utf8.character.alpha (n)
emit: <5> string.utf8.character.alpha (e)
emit: <5> string.utf8.character.alpha (o)
emit: <5> string.utf8.character.alpha (s)
emit: <5> string.utf8.character.period (.)
emit: <6> string.utf8.character.alpha (s)
emit: <7> string.utf8.character.alpha (t)
emit: <7> string.utf8.character.alpha (r)
emit: <7> string.utf8.character.alpha (e)
emit: <7> string.utf8.character.alpha (a)
emit: <7> string.utf8.character.alpha (m)
emit: <4> module.package.name ()
emit: <3> module.package.import ()
emit: <3> module.package.instantiate ()
emit: <3> language.keyword ()
emit: <4> language.keyword ()
emit: <5> string.utf8.character.alpha (t)
emit: <6> string.utf8.character.alpha (o)
emit: <6> string.utf8.character.underscore (_)
emit: <6> string.utf8.character.alpha (s)
emit: <6> string.utf8.character.alpha (t)
emit: <6> string.utf8.character.alpha (r)
emit: <6> string.utf8.character.alpha (i)
emit: <6> string.utf8.character.alpha (n)
emit: <6> string.utf8.character.alpha (g)
emit: <5> language.identifier ()
emit: <10> string.utf8.character.alpha (x)
emit: <10> language.identifier ()
emit: <9> language.function.parameter ()
emit: <11> language.type.i32 ()
emit: <7> language.function.parameters ()
emit: <10> language.type.string ()
emit: <9> language.function.return ()
emit: <4> language.function.signature ()
emit: <4> language.function.import ()
emit: <3> language.keyword ()
emit: <4> language.keyword ()
emit: <5> string.utf8.character.alpha (t)
emit: <6> string.utf8.character.alpha (o)
emit: <6> string.utf8.character.underscore (_)
emit: <6> string.utf8.character.alpha (i)
emit: <6> string.utf8.character.alpha (n)
emit: <6> string.utf8.character.alpha (t)
emit: <6> string.utf8.character.alpha (e)
emit: <6> string.utf8.character.alpha (g)
emit: <6> string.utf8.character.alpha (e)
emit: <6> string.utf8.character.alpha (r)
emit: <5> language.identifier ()
emit: <10> string.utf8.character.alpha (s)
emit: <10> language.identifier ()
emit: <9> language.function.parameter ()
emit: <11> language.type.string ()
emit: <7> language.function.parameters ()
emit: <10> language.type.i32 ()
emit: <9> language.function.return ()
emit: <4> language.function.signature ()
emit: <4> language.function.import ()
emit: <3> language.keyword ()
emit: <4> language.keyword ()
emit: <5> string.utf8.character.alpha (i)
emit: <6> string.utf8.character.alpha (n)
emit: <6> string.utf8.character.alpha (p)
emit: <6> string.utf8.character.alpha (u)
emit: <6> string.utf8.character.alpha (t)
emit: <5> language.identifier ()
emit: <10> string.utf8.character.alpha (s)
emit: <10> language.identifier ()
emit: <9> language.function.parameter ()
emit: <11> language.keyword ()
emit: <10> language.function.parameter.direction.out ()
emit: <12> language.type.string ()
emit: <7> language.function.parameters ()
emit: <4> language.function.signature ()
emit: <4> language.function.import ()
emit: <3> language.keyword ()
emit: <4> language.keyword ()
emit: <5> string.utf8.character.alpha (p)
emit: <6> string.utf8.character.alpha (r)
emit: <6> string.utf8.character.alpha (i)
emit: <6> string.utf8.character.alpha (n)
emit: <6> string.utf8.character.alpha (t)
emit: <5> language.identifier ()
emit: <10> string.utf8.character.alpha (s)
emit: <10> language.identifier ()
emit: <9> language.function.parameter ()
emit: <11> language.keyword ()
emit: <10> language.function.parameter.direction.in ()
emit: <12> language.type.string ()
emit: <7> language.function.parameters ()
emit: <4> language.function.signature ()
emit: <4> language.function.import ()
emit: <3> language.keyword ()
emit: <4> language.keyword ()
emit: <5> string.utf8.character.alpha (a)
emit: <6> string.utf8.character.alpha (d)
emit: <6> string.utf8.character.alpha (d)
emit: <5> language.identifier ()
emit: <10> string.utf8.character.alpha (x)
emit: <10> language.identifier ()
emit: <9> language.function.parameter ()
emit: <12> string.utf8.character.alpha (y)
emit: <12> language.identifier ()
emit: <11> language.function.parameter ()
emit: <13> language.type.i32 ()
emit: <7> language.function.parameters ()
emit: <10> language.type.i32 ()
emit: <9> language.function.return ()
emit: <4> language.function.signature ()
emit: <8> language.keyword ()
emit: <13> string.utf8.character.alpha (x)
emit: <13> language.identifier ()
emit: <12> math.expression.operand ()
emit: <15> string.utf8.character.alpha (y)
emit: <15> language.identifier ()
emit: <14> math.expression.operand ()
emit: <10> math.operator.add ()
emit: <9> math.expression ()
emit: <9> language.function.return ()
emit: <7> language.statement ()
emit: <5> language.function.scope ()
emit: <4> language.function ()
emit: <3> language.keyword ()
emit: <4> language.keyword ()
emit: <5> string.utf8.character.alpha (f)
emit: <6> string.utf8.character.alpha (i)
emit: <6> string.utf8.character.alpha (b)
emit: <5> language.identifier ()
emit: <10> string.utf8.character.alpha (x)
emit: <10> language.identifier ()
emit: <9> language.function.parameter ()
emit: <11> language.type.i32 ()
emit: <7> language.function.parameters ()
emit: <10> language.type.i32 ()
emit: <9> language.function.return ()
emit: <4> language.function.signature ()
emit: <8> language.keyword ()
emit: <17> string.utf8.character.alpha (x)
emit: <17> language.identifier ()
emit: <16> math.expression.operand ()
emit: <13> math.expression ()
emit: <12> boolean.expression.operand ()
emit: <18> math.universal.number.digit (1)
emit: <18> math.universal.number ()
emit: <18> math.expression.operand ()
emit: <15> math.expression ()
emit: <14> boolean.expression.operand ()
emit: <12> boolean.operator.relational.equal ()
emit: <10> boolean.expression ()
emit: <13> language.keyword ()
emit: <17> math.universal.number.digit (1)
emit: <17> math.universal.number ()
emit: <17> math.expression.operand ()
emit: <14> math.expression ()
emit: <14> language.function.return ()
emit: <12> language.statement ()
emit: <11> logic.operator.if ()
emit: <14> language.keyword ()
emit: <16> language.keyword ()
emit: <21> string.utf8.character.alpha (a)
emit: <22> string.utf8.character.alpha (d)
emit: <22> string.utf8.character.alpha (d)
emit: <21> language.identifier ()
emit: <27> string.utf8.character.alpha (f)
emit: <28> string.utf8.character.alpha (i)
emit: <28> string.utf8.character.alpha (b)
emit: <27> language.identifier ()
emit: <33> string.utf8.character.alpha (x)
emit: <33> language.identifier ()
emit: <32> math.expression.operand ()
emit: <34> math.universal.number.digit (1)
emit: <34> math.universal.number ()
emit: <34> math.expression.operand ()
emit: <30> math.operator.subtract ()
emit: <29> math.expression ()
emit: <28> language.function.argument ()
emit: <29> language.function.call ()
emit: <26> math.expression.operand ()
emit: <23> math.expression ()
emit: <22> language.function.argument ()
emit: <29> string.utf8.character.alpha (f)
emit: <30> string.utf8.character.alpha (i)
emit: <30> string.utf8.character.alpha (b)
emit: <29> language.identifier ()
emit: <35> string.utf8.character.alpha (x)
emit: <35> language.identifier ()
emit: <34> math.expression.operand ()
emit: <36> math.universal.number.digit (2)
emit: <36> math.universal.number ()
emit: <36> math.expression.operand ()
emit: <32> math.operator.subtract ()
emit: <31> math.expression ()
emit: <30> language.function.argument ()
emit: <31> language.function.call ()
emit: <28> math.expression.operand ()
emit: <25> math.expression ()
emit: <24> language.function.argument ()
emit: <25> language.function.call ()
emit: <20> math.expression.operand ()
emit: <17> math.expression ()
emit: <17> language.function.return ()
emit: <15> language.statement ()
emit: <14> logic.operator.else ()
emit: <7> language.statement ()
emit: <5> language.function.scope ()
emit: <4> language.function ()
emit: <3> language.keyword ()
emit: <4> language.keyword ()
emit: <5> string.utf8.character.alpha (m)
emit: <6> string.utf8.character.alpha (a)
emit: <6> string.utf8.character.alpha (i)
emit: <6> string.utf8.character.alpha (n)
emit: <5> language.identifier ()
emit: <4> language.function.signature ()
emit: <8> string.utf8.character.alpha (s)
emit: <8> language.identifier ()
emit: <7> language.function.local ()
emit: <9> language.type.string ()
emit: <5> language.function.locals ()
emit: <5> language.function.locals ()
emit: <13> string.utf8.character.alpha (i)
emit: <14> string.utf8.character.alpha (n)
emit: <14> string.utf8.character.alpha (p)
emit: <14> string.utf8.character.alpha (u)
emit: <14> string.utf8.character.alpha (t)
emit: <13> language.identifier ()
emit: <19> string.utf8.character.alpha (s)
emit: <19> language.identifier ()
emit: <18> math.expression.operand ()
emit: <15> math.expression ()
emit: <14> language.function.argument ()
emit: <15> language.function.call ()
emit: <12> math.expression.operand ()
emit: <9> math.expression ()
emit: <8> language.statement ()
emit: <9> language.function.return ()
emit: <8> language.statement ()
emit: <13> string.utf8.character.alpha (p)
emit: <14> string.utf8.character.alpha (r)
emit: <14> string.utf8.character.alpha (i)
emit: <14> string.utf8.character.alpha (n)
emit: <14> string.utf8.character.alpha (t)
emit: <13> language.identifier ()
emit: <19> string.utf8.character.alpha (s)
emit: <19> language.identifier ()
emit: <18> math.expression.operand ()
emit: <22> string.utf8.character (:)
emit: <22> string.utf8.character ( )
emit: <21> string.utf8 ()
emit: <20> math.expression.operand ()
emit: <16> math.operator.add ()
emit: <23> string.utf8.character.alpha (t)
emit: <24> string.utf8.character.alpha (o)
emit: <24> string.utf8.character.underscore (_)
emit: <24> string.utf8.character.alpha (s)
emit: <24> string.utf8.character.alpha (t)
emit: <24> string.utf8.character.alpha (r)
emit: <24> string.utf8.character.alpha (i)
emit: <24> string.utf8.character.alpha (n)
emit: <24> string.utf8.character.alpha (g)
emit: <23> language.identifier ()
emit: <29> string.utf8.character.alpha (f)
emit: <30> string.utf8.character.alpha (i)
emit: <30> string.utf8.character.alpha (b)
emit: <29> language.identifier ()
emit: <35> string.utf8.character.alpha (t)
emit: <36> string.utf8.character.alpha (o)
emit: <36> string.utf8.character.underscore (_)
emit: <36> string.utf8.character.alpha (i)
emit: <36> string.utf8.character.alpha (n)
emit: <36> string.utf8.character.alpha (t)
emit: <36> string.utf8.character.alpha (e)
emit: <36> string.utf8.character.alpha (g)
emit: <36> string.utf8.character.alpha (e)
emit: <36> string.utf8.character.alpha (r)
emit: <35> language.identifier ()
emit: <41> string.utf8.character.alpha (s)
emit: <41> language.identifier ()
emit: <40> math.expression.operand ()
emit: <37> math.expression ()
emit: <36> language.function.argument ()
emit: <37> language.function.call ()
emit: <34> math.expression.operand ()
emit: <31> math.expression ()
emit: <30> language.function.argument ()
emit: <31> language.function.call ()
emit: <28> math.expression.operand ()
emit: <25> math.expression ()
emit: <24> language.function.argument ()
emit: <25> language.function.call ()
emit: <22> math.expression.operand ()
emit: <18> math.operator.add ()
emit: <15> math.expression ()
emit: <14> language.function.argument ()
emit: <15> language.function.call ()
emit: <12> math.expression.operand ()
emit: <9> math.expression ()
emit: <8> language.statement ()
emit: <9> language.function.return ()
emit: <8> language.statement ()
emit: <6> language.function.scope ()
emit: <5> language.function ()
Compilation time: 326.358ms
neoscript]cte 0
neoscript]l examples/neoscript/fibonacci.neo
Compilation time: 31.001ms
neoscript]list
-- neoscript example: Fibonacci
 
using neos.string;
using neos.stream;
 
import fn to_string(x : i32) -> string;
import fn to_integer(s : string) -> i32;
import proc input(s : out string);
import proc print(s : in string);
 
-- functions are pure
def fn add(x, y : i32) -> i32
{
return x + y;
}
def fn fib(x : i32) -> i32
{
if (x = 1)
return 1;
else
return add(fib(x-1), fib(x-2));
}
 
-- procedures are impure
def proc main()
s : string;
{
input(s);
print(s + ": " + to_string(fib(to_integer(s))));
}
neoscript]
 
I am quite happy with a compilation speed of 30ms for this but there are
no doubt further optimizations I can make.
 
/Flibble
 
--
"You won't burn in hell. But be nice anyway." – Ricky Gervais
 
"I see Atheists are fighting and killing each other again, over who
doesn't believe in any God the most. Oh, no..wait.. that never happens." –
Ricky Gervais
 
"Suppose it's all true, and you walk up to the pearly gates, and are
confronted by God," Bryne asked on his show The Meaning of Life. "What
will Stephen Fry say to him, her, or it?"
"I'd say, bone cancer in children? What's that about?" Fry replied.
"How dare you? How dare you create a world to which there is such misery
that is not our fault. It's not right, it's utterly, utterly evil."
"Why should I respect a capricious, mean-minded, stupid God who creates a
world that is so full of injustice and pain. That's what I would say."
You received this digest because you're subscribed to updates for this group. You can change your settings on the group membership page.
To unsubscribe from this group and stop receiving emails from it send an email to comp.lang.c+++unsubscribe@googlegroups.com.

No comments: