- :hexfloat - 22 Updates
- About my new invention that is a Fast Mutex.. - 2 Updates
- neos - the universal compiler that can compile any programming language - 1 Update
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:
Post a Comment