From jay.krell at cornell.edu Sat Sep 1 22:28:48 2012 From: jay.krell at cornell.edu (Jay K) Date: Sat, 1 Sep 2012 20:28:48 +0000 Subject: [M3devel] saving indentation? Message-ID: "saving indentation" So..let me try this yet one more time. Modula-3 has some interesting and almost unique characteristics. Optional safety and compiling to native code is fairly unique. The syntax in general is limited. I have great difficulty getting comfortable with it. I end up writing much less readable code. I would really really like "to get easy cases out of the way early" and "straightline" the code mostly -- I don't want to indent like crazy and read through if after if after if. Similarly, I want to initialize variables when I declare them, but not indent like crazy. Horizontal space is valuable. Not leaving variables uninitialized is valuable. Avoiding horrendous if/if/if/else if/else if/else "ladders" is often valuable. It is hard to have all of these in Modula-3, but easy in C++ and C9x. Here I have a string that I am checking if it starts with one of two prefixes and followed by an integer. I would LIKE to write it like so: var-or-const name := M3ID.ToText(proc.name); var-or-const length := Text.Length(name); FOR i := FIRST(u.handler_name_prefixes) TO LAST(u.handler_name_prefixes) DO var-or-const prefix := u.handler_name_prefixes[i]; var-or-const prefix_length := Text.Length(prefix); IF length <= prefix_length OR NOT TextUtils.StartsWith(name, prefix) THEN continue; END; var-or-const end = Text.Sub(name, prefix_length); FOR i := 0 TO Text.Length(end) - 1 DO IF NOT Text.GetChar(end, i) IN ASCII.Digits THEN RETURN FALSE; END; END; RETURN TRUE; END; RETURN FALSE; but Modula-3 doesn't have "continue", right, and var/with imply indentation, So I have to write: WITH name = M3ID.ToText(proc.name), length = Text.Length(name) DO FOR i := FIRST(u.handler_name_prefixes) TO LAST(u.handler_name_prefixes) DO WITH prefix = u.handler_name_prefixes[i], prefix_length = Text.Length(prefix) DO IF length > prefix_length AND TextUtils.StartsWith(name, prefix) THEN WITH end = Text.Sub(name, prefix_length) DO FOR i := 0 TO Text.Length(end) - 1 DO IF NOT Text.GetChar(end, i) IN ASCII.Digits THEN RETURN FALSE; END; END; RETURN TRUE; END; END; END; END; END; RETURN FALSE; Isn't the first much more readable? Is there anything to do about this? Am I crazy? Introducing variables "anywhere", without a need to open a block, is considered one of the most conservative features of C++. It is in C9x. The downside of it is that you can't as easily look at the top of a function and guestimate how much stack it uses. Furthermore, I want "const" to mean "relatively const" -- do whatever codegen is needed to initialize it, but then don't let me change thereafter. Not "the compiler can evaluate it at compile time". It is useful, it reveals code to be "psuedo functional". The more of this const there is, the easier it is for the compiler and human to reason about. I guess this is what WITH is for though. I guess I should try putting those at the start of functions instead of var. - Jay -------------- next part -------------- An HTML attachment was scrubbed... URL: From dragisha at m3w.org Sat Sep 1 23:18:13 2012 From: dragisha at m3w.org (=?utf-8?Q?Dragi=C5=A1a_Duri=C4=87?=) Date: Sat, 1 Sep 2012 23:18:13 +0200 Subject: [M3devel] saving indentation? In-Reply-To: References: Message-ID: <2C3D358D-3BD9-45B9-851F-2584C2BBE92F@m3w.org> It is only normal to have such an attitude when coming from "save typing" language/world/mindset. If nothing else, C is economic. :) Correct me if I am wrong but - continue is hidden goto. When you are attuned to it, it's nice and cozy. When you are not, you look around a lot, scratching your head. break, continue, goto? Just recently a friend explained to me how goto is totally legitimate way to handle exit from a procedure - and he said it is sooo readable?. So is break and continue, when you are in a right groove. I don't think I am :). Variable declaration everywhere (it reminded me of Javascript for a moment, and I had chills :) - it looks nice but it is obviously not great rogramming style. C9x probably has some solution to "name already defined in this same scope" and similar, but it looks clumsy in any case. I try not to overuse WITH. From time to time I find local variables or extra block much more readable. Of course, in your case you'll sacrifice C9x economy - variable setting is not its initialization. But, You'll save some horizontal space and skip few WITH's. As for horizontal space? You are not kidding here? Or you have some reason to not like widescreen laptops? If there is one thing my macbook has in abundance - it is horizontal space. Of course, I am totally on the other side of programming language spectre. My background is Modula-2 (25 yrs) and Modula-3 (cca 15yrs). Everything else is secondary to these two. So, I am probably missing a lot of C9x viewpoint issues. On Sep 1, 2012, at 10:28 PM, Jay K wrote: > I would LIKE to write it like so: > > > var-or-const name := M3ID.ToText(proc.name); > var-or-const length := Text.Length(name); > FOR i := FIRST(u.handler_name_prefixes) TO LAST(u.handler_name_prefixes) DO > var-or-const prefix := u.handler_name_prefixes[i]; > var-or-const prefix_length := Text.Length(prefix); > IF length <= prefix_length OR NOT TextUtils.StartsWith(name, prefix) THEN > continue; > END; > var-or-const end = Text.Sub(name, prefix_length); > FOR i := 0 TO Text.Length(end) - 1 DO > IF NOT Text.GetChar(end, i) IN ASCII.Digits THEN > RETURN FALSE; > END; > END; > RETURN TRUE; > END; > RETURN FALSE; > > > but Modula-3 doesn't have "continue", right, and var/with imply indentation, > So I have to write: > WITH name = M3ID.ToText(proc.name), > length = Text.Length(name) DO > FOR i := FIRST(u.handler_name_prefixes) TO LAST(u.handler_name_prefixes) DO > WITH prefix = u.handler_name_prefixes[i], > prefix_length = Text.Length(prefix) DO > IF length > prefix_length AND TextUtils.StartsWith(name, prefix) THEN > WITH end = Text.Sub(name, prefix_length) DO > FOR i := 0 TO Text.Length(end) - 1 DO > IF NOT Text.GetChar(end, i) IN ASCII.Digits THEN > RETURN FALSE; > END; > END; > RETURN TRUE; > END; > END; > END; > END; > END; > RETURN FALSE; -------------- next part -------------- An HTML attachment was scrubbed... URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 495 bytes Desc: Message signed with OpenPGP using GPGMail URL: From jay.krell at cornell.edu Sun Sep 2 07:27:55 2012 From: jay.krell at cornell.edu (Jay K) Date: Sun, 2 Sep 2012 05:27:55 +0000 Subject: [M3devel] saving indentation? In-Reply-To: <2C3D358D-3BD9-45B9-851F-2584C2BBE92F@m3w.org> References: , <2C3D358D-3BD9-45B9-851F-2584C2BBE92F@m3w.org> Message-ID: Correct, goto is actually an excellent and useful feature, if you don't have exceptions and/or try/finally and/or destructors. I use it a lot when I program C. A lot. It is popular. Esp. in code that must handle all error cases and never leak. In sloppy/buggy code, well... There are approximately the following styles of C and C++. Let's write a function that copies files, the psuedo code is: FILE* from = fopen(from_path, "rb"); FILE* to = fopen(to_path, "wb"); const size_t buffer_size = 0x10000; void* buffer = malloc(buffer_size); size_t bytes_read; while (bytes_read = fread(from, buffer, buffer_size)) { fwrite(to, buffer, bytes_read); } free(buffer); fclose(to); fclose(from); Let's handle all errors and not leak. -- repeated inline cleanup at return FILE* from = fopen(from_path, "rb"); if (!from) return; FILE* to = fopen(to_path, "wb"); if (!to) { fclose(from); return; } const size_t buffer_size = 0x10000; void* buffer = malloc(buffer_size); if (!buffer) { fclose(to); fclose(from); return; } size_t bytes_read; while (bytes_read = fread(from, buffer, buffer_size)) { fwrite(to, buffer, bytes_read); } free(buffer); fclose(to); fclose(from); I deem this style totally unacceptable. You end up repeating code. For N resources, you end up with n + n - 1 + n - 2 + ... 1 code, or n squared. -- similar to repeated inline cleanup, but defer checks FILE* from = fopen(from_path, "rb"); FILE* to = fopen(to_path, "wb"); const size_t buffer_size = 0x10000; void* buffer = malloc(buffer_size); if (!buffer || !to || !from) { if (!to) fclose(to); if (!from) fclose(from); return; } size_t bytes_read; while (bytes_read = fread(from, buffer, buffer_size)) { fwrite(to, buffer, bytes_read); } free(buffer); fclose(to); fclose(from); This is a bad style. It has some of the repeation of "repeated inline cleanup". Let's say fopen(from) runs out of memory, but fopen(to) uses less memory and succeeds. That isn't good -- once out of memory, if you really can't succeed, best to limit resource usage. Also, often the later resource allocation depends on the earlier. That is, this is somewhat of a special case. -- fully nested if, cleanup everything just once const size_t buffer_size = 0x10000; FILE* from = fopen(from_path, "rb"); if (from) { FILE* to = fopen(to_path, "wb"); if (to) { void* buffer = malloc(buffer_size); if (buffer) { size_t bytes_read; while (bytes_read = fread(from, buffer, buffer_size)) { fwrite(to, buffer, bytes_read); } free(buffer); } fclose(to); } fclose(from); } This code has no repetition. However, imagine if you are going to return error_no_memory vs. error_open_to_failed vs. error_open_from_failed..then you have to fill in the elses, and its gets messier. I already don't like the loss of horizontal space, seriously. I think this style is also unacceptable. Some people I know claim it is readable. At least by them. Sure, it isn't impossible to understand. But it is clearly not the way to write code that must be read and written by many people. I can't explain it well. I think it should be obvious to anyone. But yet people disagree. -- try/finally, nested const size_t buffer_size = 0x10000; FILE* from = fopen(from_path, "rb"); if (from) { FILE* to = fopen(to_path, "wb"); if (to) { try { void* buffer = malloc(buffer_size); if (buffer) { try { size_t bytes_read; while (bytes_read = fread(from, buffer, buffer_size)) { fwrite(to, buffer, bytes_read); } } finally { free(buffer); } } finally { fclose(to); } } finally { fclose(from); } } If you have to be exception safe, I guess this is an improvement. But it is clearly bad (once you keep reading). Again you might have to fill in "else" to return specific errors. -- try/finally no nesting const size_t buffer_size = 0x10000; void* buffer = 0; FILE* to = 0; FILE* from = 0; try { from = fopen(from_path, "rb"); if (!from) return error_open_from_failed; } FILE* to = fopen(to_path, "wb"); if (!to) return error_open_to_failed; void* buffer = malloc(buffer_size); if (!buffer) return error_out_of_memory; size_t bytes_read; while (bytes_read = fread(from, buffer, buffer_size)) { fwrite(to, buffer, bytes_read); } } finally { free(buffer); if (to) fclose(to); if (from) fclose(from); } This isn't bad. Except, you know, try/finally doesn't exist in standard C and C++. It exists just fine in Microsoft C. It sort of exists in standard C++. And it sort of does and doesn't exist in Microsoft C++. I will explain. First, the above is valid Microsoft C, assuming #define try __try, #define finally __finally. Second, in C++ you can do: catch(...) { cleanup throw; // rethrow } In Microsoft C++, which does have __try/__except/__finally, you cannot use __try/__except/__finally in a function that has locals with destructors. This is both easy to workaround and solvable in the compiler/runtime, but not trivial in the compiler/runtime and almost nobody seems to care. but notice, I don't believe "return is an exception" so that doesn't help in the above. You can only have one "frame handler" per frame. There are separate "frame handlers" for "SEH" (__try/__except/__finally) than for C++ EH. You can split your function up to workaround it. The runtime could hypothetically provide one unified handler. The compiler could hyoptheticaly split your function for you. Let's move on. -- C++ destructors. struct Buffer_t { void* p; Buffer_t(void*q = 0) : p(q) { } ~Buffer_t() { free(p); } void* operator=(void*q) { p = q; return q; } operator void*() { return p; } }; struct File_t { FILE* f; File_t(FILE*g = 0) : f(g) { } ~File_t() { if (f) fclose(f); } FILE* operator=(File_t*g) { f = g; return g; } operator FILE*() { return f; } }; These classes need more filling out, but this is enough for here/now. const size_t buffer_size = 0x10000; File_t from = fopen(from_path, "rb"); if (!from) return error_open_from_failed; // or raise an exception File_t to = fopen(to_path, "wb"); if (!to) return error_open_to_failed; // or raise an exception Buffer_t buffer = malloc(buffer_size); if (!buffer) return error_out_of_memory; // or raise an exception size_t bytes_read; while (bytes_read = fread(from, buffer, buffer_size)) fwrite(to, buffer, bytes_read); This is, essentially, perfect. You need a library, and you need to constantly evolve it, but it isn't hard. You can use early return or raise exceptions. It becomes very difficult to either fail to initialize data or to leak -- the cardinal sins of C code are gone. The default behavior is correct. It becomes also a bit of work to miss an error check -- if you use exceptions. You regain all you horizontal space. You get all the easy cases out of the way right away. There is no duplication. It is just great. Now, let's say we don't have C++ but we have C. The best you can do is this: const size_t buffer_size = 0x10000; FILE* from = { 0 }; FILE* to = { 0 }; void* buffer = { 0 }; from = fopen(from_path, "rb"); if (!from) { error = error_open_from_failed; goto Exit; } to = fopen(to_path, "wb"); if (!to) { error = error_open_to_failed; goto Exit; } buffer = malloc(buffer_size); if (!buffer) { error = error_out_of_memory; goto Exit; } size_t bytes_read; while (bytes_read = fread(from, buffer, buffer_size)) fwrite(to, buffer, bytes_read); Exit: free(buffer); /* NULL ok */ if (from) fclose(from); if (to) fclose(to); This gets the easy cases out of the way early. Doesn't leak. Doesn't have nested ifs "like crazy". Doesn't give up horizontal space rapidly. And please release this is only for 3 resources. Imagine you have 10. All the bad cases get much worse. The acceptable cases remain just as good. You might say "but break up your code into smaller functions". But it doesn't take much to give up 80 columns in the indent-heavy styles. goto is good. At least if you don't have try/finally and/or destructors. Otherwise goto is indeed rarely needed. Multiple returns per function are bad, if you don't have try/finally and/or destructors -- otherwise multiple returns aren't needed. Modula-3 does have "exit" which is like "break". But it is lacking "cotinue". - Jay Subject: Re: [M3devel] saving indentation? From: dragisha at m3w.org Date: Sat, 1 Sep 2012 23:18:13 +0200 CC: m3devel at elegosoft.com To: jay.krell at cornell.edu It is only normal to have such an attitude when coming from "save typing" language/world/mindset. If nothing else, C is economic. :) Correct me if I am wrong but - continue is hidden goto. When you are attuned to it, it's nice and cozy. When you are not, you look around a lot, scratching your head. break, continue, goto. Just recently a friend explained to me how goto is totally legitimate way to handle exit from a procedure - and he said it is sooo readable.. So is break and continue, when you are in a right groove. I don't think I am :). Variable declaration everywhere (it reminded me of Javascript for a moment, and I had chills :) - it looks nice but it is obviously not great rogramming style. C9x probably has some solution to "name already defined in this same scope" and similar, but it looks clumsy in any case. I try not to overuse WITH. From time to time I find local variables or extra block much more readable. Of course, in your case you'll sacrifice C9x economy - variable setting is not its initialization. But, You'll save some horizontal space and skip few WITH's. As for horizontal space. You are not kidding here? Or you have some reason to not like widescreen laptops? If there is one thing my macbook has in abundance - it is horizontal space. Of course, I am totally on the other side of programming language spectre. My background is Modula-2 (25 yrs) and Modula-3 (cca 15yrs). Everything else is secondary to these two. So, I am probably missing a lot of C9x viewpoint issues. On Sep 1, 2012, at 10:28 PM, Jay K wrote:I would LIKE to write it like so: var-or-const name := M3ID.ToText(proc.name); var-or-const length := Text.Length(name); FOR i := FIRST(u.handler_name_prefixes) TO LAST(u.handler_name_prefixes) DO var-or-const prefix := u.handler_name_prefixes[i]; var-or-const prefix_length := Text.Length(prefix); IF length <= prefix_length OR NOT TextUtils.StartsWith(name, prefix) THEN continue; END; var-or-const end = Text.Sub(name, prefix_length); FOR i := 0 TO Text.Length(end) - 1 DO IF NOT Text.GetChar(end, i) IN ASCII.Digits THEN RETURN FALSE; END; END; RETURN TRUE; END; RETURN FALSE; but Modula-3 doesn't have "continue", right, and var/with imply indentation, So I have to write: WITH name = M3ID.ToText(proc.name), length = Text.Length(name) DO FOR i := FIRST(u.handler_name_prefixes) TO LAST(u.handler_name_prefixes) DO WITH prefix = u.handler_name_prefixes[i], prefix_length = Text.Length(prefix) DO IF length > prefix_length AND TextUtils.StartsWith(name, prefix) THEN WITH end = Text.Sub(name, prefix_length) DO FOR i := 0 TO Text.Length(end) - 1 DO IF NOT Text.GetChar(end, i) IN ASCII.Digits THEN RETURN FALSE; END; END; RETURN TRUE; END; END; END; END; END; RETURN FALSE; -------------- next part -------------- An HTML attachment was scrubbed... URL: From dragisha at m3w.org Sun Sep 2 09:22:32 2012 From: dragisha at m3w.org (=?utf-8?Q?Dragi=C5=A1a_Duri=C4=87?=) Date: Sun, 2 Sep 2012 09:22:32 +0200 Subject: [M3devel] saving indentation? In-Reply-To: References: , <2C3D358D-3BD9-45B9-851F-2584C2BBE92F@m3w.org> Message-ID: Excellent post. I may use it to explain to friends Why Modula-3 :). Point remains, Modula-3 does not need any of this sugar, because it has TRY-FINALLY. If you really have complex code in need of continue, why don't add inner loop where EXIT will, in fact, just finish inner body and return immediately to outer body (your loop you wish to continue)? It surely is extra level of indentation, but is better than deep IF. dd -- Divided by a common language Dragi?a Duri? dragisha at m3w.org On Sep 2, 2012, at 7:27 AM, Jay K wrote: > goto is good. > At least if you don't have try/finally and/or destructors. > Otherwise goto is indeed rarely needed. > > Multiple returns per function are bad, if you don't have > try/finally and/or destructors -- otherwise multiple returns aren't needed. > > > Modula-3 does have "exit" which is like "break". > But it is lacking "cotinue". -------------- next part -------------- An HTML attachment was scrubbed... URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 495 bytes Desc: Message signed with OpenPGP using GPGMail URL: From jay.krell at cornell.edu Sun Sep 2 09:34:56 2012 From: jay.krell at cornell.edu (Jay K) Date: Sun, 2 Sep 2012 07:34:56 +0000 Subject: [M3devel] saving indentation? In-Reply-To: References: , , <2C3D358D-3BD9-45B9-851F-2584C2BBE92F@m3w.org>, , Message-ID: 1) Was my post cut off, or you did that? 2) I've spoken to a number of C++ programmers who want/wanted try/finally. The answer has often been, that they "just" need to expand their library slightly, and use destructors instead. Indeed, I think it is inarguable that destructors allow for smaller source code, and just as readable. The cleanup is written once, per type, not many times, per instance. You know that for every fopen, or every FILE* variable, you need fclose somewhere. Somewhere generally being when the variable goes out of scope. How about the compiler puts it in for you, in the easy/obvious place? However I did forget a style. That I have never used. Because I could never quite grok how to implement it, and/or it depends on the preprocessor. There is something you can do in C++ something like this: FILE* from = fopen(from_path, "rb"); if (!from) return error_unable_to_open_from; AT_EXIT(fclose(from)); FILE* to = fopen(to_path, "rb"); if (!to) return error_unable_to_open_fto; AT_EXIT(fclose(to); Where this "AT_EXIT" thing is some magic. One of the points to consider is how close to initialization can one state the cleanup. That is a good thing about this "AT_EXIT". Let me give you a little more C++-salesmanship. First, the opposite. Or rather, "classic C++ salesmanship". Some people speak of "smart pointers" in C++. These are typically classes with operator= and such, that upon assignment will increment a reference count, and upon destruction will decrement. They are generally "drop-in replacements" for "regular pointers". I claim this is kind of close to the point, but also kind of misses the point. These types should be viewed as "regular types", with appropriate constructor/destructor/operator= that can be freely conveniently efficiently thrown around like anything else, and they always do the right thing. "regular pointers" should be termed more like "dumb pointers". There is no place in "modern C++" for a plain "dumb pointer", except at low levels to implement "regular pointers". This is kind of a shift of mindset. One that many people resist. But it seems good and right. There is more to my usual C++ pitch. Some languages have garbage collection. So "pointers" don't need such "fanciness" as reference counting, "smart pointers". But instead there is a big complicatched machinery behind the scenes. Similarly, some languages have "synchronized" or "lock". Here again, the syntax is approximately perfect and you can't fail to release a lock. However these are both special purpose mechanisms, for memory and for locks. What about closing files, network connections, database connections? C++ does a good job of providing a general purpose mechanism, rather than having the compiler and runtime special-case two specific resources. Operator overloading fits here too. C, Java, Modula-3 special case a few types -- int, float, string, and provide some infix operators. No user-defined type is given this power. In C++, user-defined types and language-defined types have approximately equal powers. - Jay From: dragisha at m3w.org Date: Sun, 2 Sep 2012 09:22:32 +0200 To: jay.krell at cornell.edu CC: m3devel at elegosoft.com Subject: Re: [M3devel] saving indentation? Excellent post. I may use it to explain to friends Why Modula-3 :). Point remains, Modula-3 does not need any of this sugar, because it has TRY-FINALLY. If you really have complex code in need of continue, why don't add inner loop where EXIT will, in fact, just finish inner body and return immediately to outer body (your loop you wish to continue)? It surely is extra level of indentation, but is better than deep IF. dd --Divided by a common language Dragi?a Duri?dragisha at m3w.org On Sep 2, 2012, at 7:27 AM, Jay K wrote:goto is good. At least if you don't have try/finally and/or destructors. Otherwise goto is indeed rarely needed. Multiple returns per function are bad, if you don't have try/finally and/or destructors -- otherwise multiple returns aren't needed. Modula-3 does have "exit" which is like "break". But it is lacking "cotinue". -------------- next part -------------- An HTML attachment was scrubbed... URL: From dragisha at m3w.org Sun Sep 2 10:25:34 2012 From: dragisha at m3w.org (=?utf-8?Q?Dragi=C5=A1a_Duri=C4=87?=) Date: Sun, 2 Sep 2012 10:25:34 +0200 Subject: [M3devel] saving indentation? In-Reply-To: References: , , <2C3D358D-3BD9-45B9-851F-2584C2BBE92F@m3w.org>, , Message-ID: <3F78947B-937A-4CB4-BC35-B69D3E4FE08E@m3w.org> With C++ you don't have "big complicatched machinery" behind the scenes, serving clearly defined language. It's complicatchion is right in front of you. You have big nasty complicated language in front of a programmer and in front of compiler implementor. For what? For fanciness of infix operator? Garbage collection and WeakRef mechanism are bringing destructor-like functionality to any type you wish. To me, it is a lot more important than fancy infix. -- Divided by a common language Dragi?a Duri? dragisha at m3w.org On Sep 2, 2012, at 9:34 AM, Jay K wrote: > There is more to my usual C++ pitch. > Some languages have garbage collection. So "pointers" don't need such "fanciness" as reference counting, "smart pointers". But instead there is a big complicatched machinery behind the scenes. > Similarly, some languages have "synchronized" or "lock". Here again, the syntax is approximately perfect and you can't fail to release a lock. > > > However these are both special purpose mechanisms, for memory and for locks. > > > What about closing files, network connections, database connections? > C++ does a good job of providing a general purpose mechanism, rather than having the compiler and runtime special-case two specific resources. Operator overloading fits here too. C, Java, Modula-3 special case a few types -- int, float, string, and provide some infix operators. No user-defined type is given this power. In C++, user-defined types and language-defined types have approximately equal powers. -------------- next part -------------- An HTML attachment was scrubbed... URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 495 bytes Desc: Message signed with OpenPGP using GPGMail URL: From rodney_bates at lcwb.coop Sun Sep 2 16:41:33 2012 From: rodney_bates at lcwb.coop (Rodney M. Bates) Date: Sun, 02 Sep 2012 09:41:33 -0500 Subject: [M3devel] Bitfields and endianness Message-ID: <5043701D.6030102@lcwb.coop> Pardon me for showing my frustration, but I think it is about time to consider what the *language* says about bit fields. The language says: ------------------------------------------------------------------------- A declaration of a packed type has the form: TYPE T = BITS n FOR Base where Base is a type and n is an integer-valued constant expression. The values of type T are the same as the values of type Base, but variables of type T that occur in records, objects, or arrays will occupy exactly n bits and be packed adjacent to the preceding field or element. For example, a variable of type ARRAY [0..255] OF BITS 1 FOR BOOLEAN is an array of 256 booleans, each of which occupies one bit of storage. The values allowed for n are implementation-dependent. An illegal value for n is a static error. The legality of a packed type can depend on its context; for example, an implementation could prohibit packed integers from spanning word boundaries. ------------------------------------------------------------------------- First off, the last paragraph clearly says that a compiler cannot just silently violate the layout rules given above. If it places restrictions, it has to refuse with an error message. Everyone is aware of "will occupy exactly n bits", but I have lost count of the number of times I see posts that imply the writer has missed "packed adjacent to the preceding field or element". This means there can be no padding added by the compiler, neither for alignment nor any other reason. With this rule, size, alignment, and padding can be completely controlled by the programmer. Note that there are no other rules about record/object layout, so a compiler is free to reorder them if none have a packed type. This is not actually happening in our compiler. If there is a mix, a group consisting of one non-packed field and all its immediately following packed fields would have to be kept together, but different groups could be reordered. So if you only want to avoid extra padding to save space or something, mixed packed/nonpacked fields might be useful, but for full layout control to match some external software or standard, you really would want to make them all packed. That leaves endianness, which the language says nothing about, that I can find. Apparently, the compiler(s) lay out packed fields in the endianness of the target machine. Which raises a big pet peeve of mine. Big-endian is fine, but so-called little-endian is an inconsistent system. It numbers bits and bytes right-to-left only within a field. Between fields (and array elements), it is still left-to-right. Ditto for input and output, which is always left-to-right by bytes, regardless of the size of contained fields, which i/o software and hardware would have no way of knowing about anyway. Ditto for instruction stream readout. (Ever try to figure out how to write a consistent memory dump for a little-endian machine? Mercifully, we don't much use them anymore, but there was a time.) The compiler lays out in increasing bit numbers, which get reduced later (in little-endian) to bytes via right-to-left ordering of bits within bytes and also multiple byte-fragments of a single field. The result is that you cannot in general, use one set of endian rules to duplicate the way things would be done in the other. Dragi?a's original example shows this clearly. The standard he is trying to match lays things out in big-endian. In a little-endian reinterpretation of this layout, some fields have fragments that are discontiguous, as well as out of sequence. So to use a little-endian version of Modula-3's packing rules (as the compiler is doing, since it is compiling for a little-endian target), he would have to do his own bit-twiddling of the fragments to get a field in or out of the record. Which pretty well defeats the purpose of having a packed record layout. It would be more-or-less as easy, and probably a lot clearer to just treat as ARRAY OF Word.T or such and bit twiddle on that. I think the clear conclusion is that the language's system is incomplete, and to fix it, we need a way to specify the endianness used to lay out a record/object with packed fields (and arrays too) independent of that of the target machine. Whether that is a pragma or in the core of the language is a secondary question, although I prefer a true language syntax, just because pragmas, in theory, are not supposed to change the behavioral semantics of a program. We also need to specify in the language, what the actual rules are for little-endian, where it is far from obvious, due to its endian-confusedness. From dragisha at m3w.org Sun Sep 2 16:45:54 2012 From: dragisha at m3w.org (=?utf-8?Q?Dragi=C5=A1a_Duri=C4=87?=) Date: Sun, 2 Sep 2012 16:45:54 +0200 Subject: [M3devel] Bitfields and endianness In-Reply-To: <5043701D.6030102@lcwb.coop> References: <5043701D.6030102@lcwb.coop> Message-ID: Rodney put it as clear as possible. We already have packing and alignment issues dictated by language definition. What we need is to make sense out of packing, fix endiannes and pack left to right. Period. On Sep 2, 2012, at 4:41 PM, Rodney M. Bates wrote: > Pardon me for showing my frustration, but I think it is about > time to consider what the *language* says about bit fields. > > The language says: > ------------------------------------------------------------------------- > A declaration of a packed type has the form: > > TYPE T = BITS n FOR Base > > where Base is a type and n is an integer-valued constant > expression. The values of type T are the same as the values of type > Base, but variables of type T that occur in records, objects, or > arrays will occupy exactly n bits and be packed adjacent to the > preceding field or element. For example, a variable of type > > ARRAY [0..255] OF BITS 1 FOR BOOLEAN > > is an array of 256 booleans, each of which occupies one bit of storage. > > The values allowed for n are implementation-dependent. An illegal > value for n is a static error. The legality of a packed type can > depend on its context; for example, an implementation could prohibit > packed integers from spanning word boundaries. > ------------------------------------------------------------------------- > > First off, the last paragraph clearly says that a compiler cannot just > silently violate the layout rules given above. If it places > restrictions, it has to refuse with an error message. > > Everyone is aware of "will occupy exactly n bits", but I have lost > count of the number of times I see posts that imply the writer has > missed "packed adjacent to the preceding field or element". This > means there can be no padding added by the compiler, neither for > alignment nor any other reason. With this rule, size, alignment, and > padding can be completely controlled by the programmer. > > Note that there are no other rules about record/object layout, so a > compiler is free to reorder them if none have a packed type. This is > not actually happening in our compiler. If there is a mix, a group > consisting of one non-packed field and all its immediately following > packed fields would have to be kept together, but different groups > could be reordered. So if you only want to avoid extra padding to > save space or something, mixed packed/nonpacked fields might be > useful, but for full layout control to match some external software or > standard, you really would want to make them all packed. > > That leaves endianness, which the language says nothing about, that I > can find. Apparently, the compiler(s) lay out packed fields in the > endianness of the target machine. > > Which raises a big pet peeve of mine. Big-endian is fine, but > so-called little-endian is an inconsistent system. It numbers bits > and bytes right-to-left only within a field. Between fields (and > array elements), it is still left-to-right. Ditto for input and > output, which is always left-to-right by bytes, regardless of the size > of contained fields, which i/o software and hardware would have no way > of knowing about anyway. Ditto for instruction stream readout. (Ever > try to figure out how to write a consistent memory dump for a > little-endian machine? Mercifully, we don't much use them anymore, > but there was a time.) > > The compiler lays out in increasing bit numbers, which get reduced > later (in little-endian) to bytes via right-to-left ordering of bits > within bytes and also multiple byte-fragments of a single field. > > The result is that you cannot in general, use one set of endian rules > to duplicate the way things would be done in the other. Dragi?a's > original example shows this clearly. The standard he is trying to > match lays things out in big-endian. In a little-endian > reinterpretation of this layout, some fields have fragments that are > discontiguous, as well as out of sequence. > > So to use a little-endian version of Modula-3's packing rules (as the > compiler is doing, since it is compiling for a little-endian target), > he would have to do his own bit-twiddling of the fragments to get a > field in or out of the record. Which pretty well defeats the purpose > of having a packed record layout. It would be more-or-less as easy, > and probably a lot clearer to just treat as ARRAY OF Word.T or such > and bit twiddle on that. > > I think the clear conclusion is that the language's system is > incomplete, and to fix it, we need a way to specify the endianness > used to lay out a record/object with packed fields (and arrays too) > independent of that of the target machine. Whether that is a pragma > or in the core of the language is a secondary question, although I > prefer a true language syntax, just because pragmas, in theory, are > not supposed to change the behavioral semantics of a program. > > We also need to specify in the language, what the actual rules are for > little-endian, where it is far from obvious, due to its > endian-confusedness. > > -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 495 bytes Desc: Message signed with OpenPGP using GPGMail URL: From jay.krell at cornell.edu Sun Sep 2 21:32:36 2012 From: jay.krell at cornell.edu (Jay K) Date: Sun, 2 Sep 2012 19:32:36 +0000 Subject: [M3devel] Bitfields and endianness In-Reply-To: References: <5043701D.6030102@lcwb.coop>, Message-ID: I'm struck by: "The values allowed for n are implementation-dependent. An illegal value for n is a static error. The legality of a packed type can depend on its context; for example, an implementation could prohibit packed integers from spanning word boundaries." Stuff is left up to the implementation, not the language definition. - Jay > From: dragisha at m3w.org > Date: Sun, 2 Sep 2012 16:45:54 +0200 > To: rodney_bates at lcwb.coop > CC: m3devel at elegosoft.com > Subject: Re: [M3devel] Bitfields and endianness > > Rodney put it as clear as possible. We already have packing and alignment issues dictated by language definition. What we need is to make sense out of packing, fix endiannes and pack left to right. Period. > > > On Sep 2, 2012, at 4:41 PM, Rodney M. Bates wrote: > > > Pardon me for showing my frustration, but I think it is about > > time to consider what the *language* says about bit fields. > > > > The language says: > > ------------------------------------------------------------------------- > > A declaration of a packed type has the form: > > > > TYPE T = BITS n FOR Base > > > > where Base is a type and n is an integer-valued constant > > expression. The values of type T are the same as the values of type > > Base, but variables of type T that occur in records, objects, or > > arrays will occupy exactly n bits and be packed adjacent to the > > preceding field or element. For example, a variable of type > > > > ARRAY [0..255] OF BITS 1 FOR BOOLEAN > > > > is an array of 256 booleans, each of which occupies one bit of storage. > > > > The values allowed for n are implementation-dependent. An illegal > > value for n is a static error. The legality of a packed type can > > depend on its context; for example, an implementation could prohibit > > packed integers from spanning word boundaries. > > ------------------------------------------------------------------------- > > > > First off, the last paragraph clearly says that a compiler cannot just > > silently violate the layout rules given above. If it places > > restrictions, it has to refuse with an error message. > > > > Everyone is aware of "will occupy exactly n bits", but I have lost > > count of the number of times I see posts that imply the writer has > > missed "packed adjacent to the preceding field or element". This > > means there can be no padding added by the compiler, neither for > > alignment nor any other reason. With this rule, size, alignment, and > > padding can be completely controlled by the programmer. > > > > Note that there are no other rules about record/object layout, so a > > compiler is free to reorder them if none have a packed type. This is > > not actually happening in our compiler. If there is a mix, a group > > consisting of one non-packed field and all its immediately following > > packed fields would have to be kept together, but different groups > > could be reordered. So if you only want to avoid extra padding to > > save space or something, mixed packed/nonpacked fields might be > > useful, but for full layout control to match some external software or > > standard, you really would want to make them all packed. > > > > That leaves endianness, which the language says nothing about, that I > > can find. Apparently, the compiler(s) lay out packed fields in the > > endianness of the target machine. > > > > Which raises a big pet peeve of mine. Big-endian is fine, but > > so-called little-endian is an inconsistent system. It numbers bits > > and bytes right-to-left only within a field. Between fields (and > > array elements), it is still left-to-right. Ditto for input and > > output, which is always left-to-right by bytes, regardless of the size > > of contained fields, which i/o software and hardware would have no way > > of knowing about anyway. Ditto for instruction stream readout. (Ever > > try to figure out how to write a consistent memory dump for a > > little-endian machine? Mercifully, we don't much use them anymore, > > but there was a time.) > > > > The compiler lays out in increasing bit numbers, which get reduced > > later (in little-endian) to bytes via right-to-left ordering of bits > > within bytes and also multiple byte-fragments of a single field. > > > > The result is that you cannot in general, use one set of endian rules > > to duplicate the way things would be done in the other. Dragi?a's > > original example shows this clearly. The standard he is trying to > > match lays things out in big-endian. In a little-endian > > reinterpretation of this layout, some fields have fragments that are > > discontiguous, as well as out of sequence. > > > > So to use a little-endian version of Modula-3's packing rules (as the > > compiler is doing, since it is compiling for a little-endian target), > > he would have to do his own bit-twiddling of the fragments to get a > > field in or out of the record. Which pretty well defeats the purpose > > of having a packed record layout. It would be more-or-less as easy, > > and probably a lot clearer to just treat as ARRAY OF Word.T or such > > and bit twiddle on that. > > > > I think the clear conclusion is that the language's system is > > incomplete, and to fix it, we need a way to specify the endianness > > used to lay out a record/object with packed fields (and arrays too) > > independent of that of the target machine. Whether that is a pragma > > or in the core of the language is a secondary question, although I > > prefer a true language syntax, just because pragmas, in theory, are > > not supposed to change the behavioral semantics of a program. > > > > We also need to specify in the language, what the actual rules are for > > little-endian, where it is far from obvious, due to its > > endian-confusedness. > > > > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From jay.krell at cornell.edu Sun Sep 2 21:34:28 2012 From: jay.krell at cornell.edu (Jay K) Date: Sun, 2 Sep 2012 19:34:28 +0000 Subject: [M3devel] saving indentation? In-Reply-To: <3F78947B-937A-4CB4-BC35-B69D3E4FE08E@m3w.org> References: , , <2C3D358D-3BD9-45B9-851F-2584C2BBE92F@m3w.org>, , , <3F78947B-937A-4CB4-BC35-B69D3E4FE08E@m3w.org> Message-ID: WeakRef isn't great. Cleanup is delayed until local memory pressure exists. Not when resource obviously goes out of scope and could be cleaned up right away. - Jay Subject: Re: [M3devel] saving indentation? From: dragisha at m3w.org Date: Sun, 2 Sep 2012 10:25:34 +0200 CC: m3devel at elegosoft.com To: jay.krell at cornell.edu With C++ you don't have "big complicatched machinery" behind the scenes, serving clearly defined language. It's complicatchion is right in front of you. You have big nasty complicated language in front of a programmer and in front of compiler implementor. For what? For fanciness of infix operator? Garbage collection and WeakRef mechanism are bringing destructor-like functionality to any type you wish. To me, it is a lot more important than fancy infix. --Divided by a common language Dragi?a Duri?dragisha at m3w.org On Sep 2, 2012, at 9:34 AM, Jay K wrote:There is more to my usual C++ pitch. Some languages have garbage collection. So "pointers" don't need such "fanciness" as reference counting, "smart pointers". But instead there is a big complicatched machinery behind the scenes. Similarly, some languages have "synchronized" or "lock". Here again, the syntax is approximately perfect and you can't fail to release a lock. However these are both special purpose mechanisms, for memory and for locks. What about closing files, network connections, database connections? C++ does a good job of providing a general purpose mechanism, rather than having the compiler and runtime special-case two specific resources. Operator overloading fits here too. C, Java, Modula-3 special case a few types -- int, float, string, and provide some infix operators. No user-defined type is given this power. In C++, user-defined types and language-defined types have approximately equal powers. -------------- next part -------------- An HTML attachment was scrubbed... URL: From dragisha at m3w.org Sun Sep 2 21:50:59 2012 From: dragisha at m3w.org (=?utf-8?Q?Dragi=C5=A1a_Duri=C4=87?=) Date: Sun, 2 Sep 2012 21:50:59 +0200 Subject: [M3devel] saving indentation? In-Reply-To: References: , , <2C3D358D-3BD9-45B9-851F-2584C2BBE92F@m3w.org>, , , <3F78947B-937A-4CB4-BC35-B69D3E4FE08E@m3w.org> Message-ID: What it does is - cleanup and disable leak. I don't know where you got this "memory pressure" idea. AFAIK (and I hopebelieve I know few things about memory subsystem) it happens in cycles. No time pressure on collection but it just happens, sometimes faster and maybe (when no mutators are active for long time) sometimes slower. For situations like this, background thread will probably fix slowing down. -- Divided by a common language Dragi?a Duri? dragisha at m3w.org On Sep 2, 2012, at 9:34 PM, Jay K wrote: > WeakRef isn't great. Cleanup is delayed until local memory pressure exists. Not when resource obviously goes out of scope and could be cleaned up right away. > > - Jay > > > Subject: Re: [M3devel] saving indentation? > From: dragisha at m3w.org > Date: Sun, 2 Sep 2012 10:25:34 +0200 > CC: m3devel at elegosoft.com > To: jay.krell at cornell.edu > > With C++ you don't have "big complicatched machinery" behind the scenes, serving clearly defined language. It's complicatchion is right in front of you. > > You have big nasty complicated language in front of a programmer and in front of compiler implementor. For what? For fanciness of infix operator? > > Garbage collection and WeakRef mechanism are bringing destructor-like functionality to any type you wish. To me, it is a lot more important than fancy infix. > > -- > Divided by a common language > > Dragi?a Duri? > dragisha at m3w.org > > > > > On Sep 2, 2012, at 9:34 AM, Jay K wrote: > > There is more to my usual C++ pitch. > Some languages have garbage collection. So "pointers" don't need such "fanciness" as reference counting, "smart pointers". But instead there is a big complicatched machinery behind the scenes. > Similarly, some languages have "synchronized" or "lock". Here again, the syntax is approximately perfect and you can't fail to release a lock. > > > However these are both special purpose mechanisms, for memory and for locks. > > > What about closing files, network connections, database connections? > C++ does a good job of providing a general purpose mechanism, rather than having the compiler and runtime special-case two specific resources. Operator overloading fits here too. C, Java, Modula-3 special case a few types -- int, float, string, and provide some infix operators. No user-defined type is given this power. In C++, user-defined types and language-defined types have approximately equal powers. -------------- next part -------------- An HTML attachment was scrubbed... URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 495 bytes Desc: Message signed with OpenPGP using GPGMail URL: From dragisha at m3w.org Sun Sep 2 21:52:54 2012 From: dragisha at m3w.org (=?utf-8?Q?Dragi=C5=A1a_Duri=C4=87?=) Date: Sun, 2 Sep 2012 21:52:54 +0200 Subject: [M3devel] Bitfields and endianness In-Reply-To: References: <5043701D.6030102@lcwb.coop>, Message-ID: <437995F7-5F02-4432-A939-BE6084D85C09@m3w.org> Of course it is. That is why we have this pragma/language change thread. Rodneys proposal is to clean language definition and enforce few things in language. Make them logical/right. -- Divided by a common language Dragi?a Duri? dragisha at m3w.org On Sep 2, 2012, at 9:32 PM, Jay K wrote: > I'm struck by: > > "The values allowed for n are implementation-dependent. An illegal > value for n is a static error. The legality of a packed type can > depend on its context; for example, an implementation could prohibit > packed integers from spanning word boundaries." > > Stuff is left up to the implementation, not the language definition. > > > - Jay > > > > From: dragisha at m3w.org > > Date: Sun, 2 Sep 2012 16:45:54 +0200 > > To: rodney_bates at lcwb.coop > > CC: m3devel at elegosoft.com > > Subject: Re: [M3devel] Bitfields and endianness > > > > Rodney put it as clear as possible. We already have packing and alignment issues dictated by language definition. What we need is to make sense out of packing, fix endiannes and pack left to right. Period. > > > > > > On Sep 2, 2012, at 4:41 PM, Rodney M. Bates wrote: > > > > > Pardon me for showing my frustration, but I think it is about > > > time to consider what the *language* says about bit fields. > > > > > > The language says: > > > ------------------------------------------------------------------------- > > > A declaration of a packed type has the form: > > > > > > TYPE T = BITS n FOR Base > > > > > > where Base is a type and n is an integer-valued constant > > > expression. The values of type T are the same as the values of type > > > Base, but variables of type T that occur in records, objects, or > > > arrays will occupy exactly n bits and be packed adjacent to the > > > preceding field or element. For example, a variable of type > > > > > > ARRAY [0..255] OF BITS 1 FOR BOOLEAN > > > > > > is an array of 256 booleans, each of which occupies one bit of storage. > > > > > > The values allowed for n are implementation-dependent. An illegal > > > value for n is a static error. The legality of a packed type can > > > depend on its context; for example, an implementation could prohibit > > > packed integers from spanning word boundaries. > > > ------------------------------------------------------------------------- > > > > > > First off, the last paragraph clearly says that a compiler cannot just > > > silently violate the layout rules given above. If it places > > > restrictions, it has to refuse with an error message. > > > > > > Everyone is aware of "will occupy exactly n bits", but I have lost > > > count of the number of times I see posts that imply the writer has > > > missed "packed adjacent to the preceding field or element". This > > > means there can be no padding added by the compiler, neither for > > > alignment nor any other reason. With this rule, size, alignment, and > > > padding can be completely controlled by the programmer. > > > > > > Note that there are no other rules about record/object layout, so a > > > compiler is free to reorder them if none have a packed type. This is > > > not actually happening in our compiler. If there is a mix, a group > > > consisting of one non-packed field and all its immediately following > > > packed fields would have to be kept together, but different groups > > > could be reordered. So if you only want to avoid extra padding to > > > save space or something, mixed packed/nonpacked fields might be > > > useful, but for full layout control to match some external software or > > > standard, you really would want to make them all packed. > > > > > > That leaves endianness, which the language says nothing about, that I > > > can find. Apparently, the compiler(s) lay out packed fields in the > > > endianness of the target machine. > > > > > > Which raises a big pet peeve of mine. Big-endian is fine, but > > > so-called little-endian is an inconsistent system. It numbers bits > > > and bytes right-to-left only within a field. Between fields (and > > > array elements), it is still left-to-right. Ditto for input and > > > output, which is always left-to-right by bytes, regardless of the size > > > of contained fields, which i/o software and hardware would have no way > > > of knowing about anyway. Ditto for instruction stream readout. (Ever > > > try to figure out how to write a consistent memory dump for a > > > little-endian machine? Mercifully, we don't much use them anymore, > > > but there was a time.) > > > > > > The compiler lays out in increasing bit numbers, which get reduced > > > later (in little-endian) to bytes via right-to-left ordering of bits > > > within bytes and also multiple byte-fragments of a single field. > > > > > > The result is that you cannot in general, use one set of endian rules > > > to duplicate the way things would be done in the other. Dragi?a's > > > original example shows this clearly. The standard he is trying to > > > match lays things out in big-endian. In a little-endian > > > reinterpretation of this layout, some fields have fragments that are > > > discontiguous, as well as out of sequence. > > > > > > So to use a little-endian version of Modula-3's packing rules (as the > > > compiler is doing, since it is compiling for a little-endian target), > > > he would have to do his own bit-twiddling of the fragments to get a > > > field in or out of the record. Which pretty well defeats the purpose > > > of having a packed record layout. It would be more-or-less as easy, > > > and probably a lot clearer to just treat as ARRAY OF Word.T or such > > > and bit twiddle on that. > > > > > > I think the clear conclusion is that the language's system is > > > incomplete, and to fix it, we need a way to specify the endianness > > > used to lay out a record/object with packed fields (and arrays too) > > > independent of that of the target machine. Whether that is a pragma > > > or in the core of the language is a secondary question, although I > > > prefer a true language syntax, just because pragmas, in theory, are > > > not supposed to change the behavioral semantics of a program. > > > > > > We also need to specify in the language, what the actual rules are for > > > little-endian, where it is far from obvious, due to its > > > endian-confusedness. > > > > > > > > -------------- next part -------------- An HTML attachment was scrubbed... URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 495 bytes Desc: Message signed with OpenPGP using GPGMail URL: From dragisha at m3w.org Mon Sep 3 00:25:56 2012 From: dragisha at m3w.org (=?utf-8?Q?Dragi=C5=A1a_Duri=C4=87?=) Date: Mon, 3 Sep 2012 00:25:56 +0200 Subject: [M3devel] How small can Modula-3 runtime be? Message-ID: <1C4D2B15-8A41-4CB8-9FCB-EB8CF8756ECB@m3w.org> Question is - if we go embedded, how small can we go? Obviously, we need full Linux kernel, pthreads and all. But what about total RAM? Flash (persistent storage)? dd -- Divided by a common language Dragi?a Duri? dragisha at m3w.org -------------- next part -------------- An HTML attachment was scrubbed... URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 495 bytes Desc: Message signed with OpenPGP using GPGMail URL: From mika at async.caltech.edu Mon Sep 3 00:34:00 2012 From: mika at async.caltech.edu (Mika Nystrom) Date: Sun, 02 Sep 2012 15:34:00 -0700 Subject: [M3devel] How small can Modula-3 runtime be? In-Reply-To: <1C4D2B15-8A41-4CB8-9FCB-EB8CF8756ECB@m3w.org> References: <1C4D2B15-8A41-4CB8-9FCB-EB8CF8756ECB@m3w.org> Message-ID: <20120902223400.49EB81A2095@async.async.caltech.edu> =?utf-8?Q?Dragi=C5=A1a_Duri=C4=87?= writes: ... > >Question is - if we go embedded, how small can we go? > >Obviously, we need full Linux kernel, pthreads and all. But what about = >total RAM? Flash (persistent storage)?=20 > >dd Modula-3 has been run without a kernel. http://resolver.caltech.edu/CaltechCSTR:1993.cs-tr-93-15 Table 3.0, page 49, for byte counts of the runtime. I have the source code somewhere. It's a modified version of the old SRC M3 compiler, which compiles M3 to C. Mika From dragisha at m3w.org Mon Sep 3 09:45:46 2012 From: dragisha at m3w.org (=?utf-8?Q?Dragi=C5=A1a_Duri=C4=87?=) Date: Mon, 3 Sep 2012 09:45:46 +0200 Subject: [M3devel] How small can Modula-3 runtime be? In-Reply-To: <20120902223400.49EB81A2095@async.async.caltech.edu> References: <1C4D2B15-8A41-4CB8-9FCB-EB8CF8756ECB@m3w.org> <20120902223400.49EB81A2095@async.async.caltech.edu> Message-ID: Bare hardware would be too much a task for me now, but those numbers are great. I can spare few tens of KILObytes anytime :). Right now I am looking around for cross-compiling setup. Anyone did it in work environment? (not only for bootstrap) -- Divided by a common language Dragi?a Duri? dragisha at m3w.org On Sep 3, 2012, at 12:34 AM, Mika Nystrom wrote: > =?utf-8?Q?Dragi=C5=A1a_Duri=C4=87?= writes: > ... >> >> Question is - if we go embedded, how small can we go? >> >> Obviously, we need full Linux kernel, pthreads and all. But what about = >> total RAM? Flash (persistent storage)?=20 >> >> dd > > Modula-3 has been run without a kernel. > > http://resolver.caltech.edu/CaltechCSTR:1993.cs-tr-93-15 > > Table 3.0, page 49, for byte counts of the runtime. > > I have the source code somewhere. It's a modified version of the old SRC M3 > compiler, which compiles M3 to C. > > Mika > > -------------- next part -------------- An HTML attachment was scrubbed... URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 495 bytes Desc: Message signed with OpenPGP using GPGMail URL: From dabenavidesd at yahoo.es Mon Sep 3 15:34:41 2012 From: dabenavidesd at yahoo.es (Daniel Alejandro Benavides D.) Date: Mon, 3 Sep 2012 14:34:41 +0100 (BST) Subject: [M3devel] How small can Modula-3 runtime be? In-Reply-To: Message-ID: <1346679281.68335.YahooMailClassic@web29701.mail.ird.yahoo.com> Hi: it can run on smart cards, they ran OS and all there so, using a CLASP machine, you can run in silicon card: http://www.dsse.ecs.soton.ac.uk/techreports/95-03/1997/dsse-tr-97-8.ps.gz Thanks in advance --- El lun, 3/9/12, Dragi?a Duri? escribi?: De: Dragi?a Duri? Asunto: Re: [M3devel] How small can Modula-3 runtime be? Para: "Mika Nystrom" CC: m3devel at elegosoft.com Fecha: lunes, 3 de septiembre, 2012 02:45 Bare hardware would be too much a task for me now, but those numbers are great. I can spare few tens of KILObytes anytime :). Right now I am looking around for cross-compiling setup. Anyone did it in work environment? (not only for bootstrap) --Divided by a common language Dragi?a Duri?dragisha at m3w.org On Sep 3, 2012, at 12:34 AM, Mika Nystrom wrote: =?utf-8?Q?Dragi=C5=A1a_Duri=C4=87?= writes: ... Question is - if we go embedded, how small can we go? Obviously, we need full Linux kernel, pthreads and all. But what about = total RAM? Flash (persistent storage)?=20 dd Modula-3 has been run without a kernel. http://resolver.caltech.edu/CaltechCSTR:1993.cs-tr-93-15 Table 3.0, page 49, for byte counts of the runtime. I have the source code somewhere. ?It's a modified version of the old SRC M3 compiler, which compiles M3 to C. ???Mika -------------- next part -------------- An HTML attachment was scrubbed... URL: From dragisha at m3w.org Mon Sep 3 17:32:44 2012 From: dragisha at m3w.org (=?utf-8?Q?Dragi=C5=A1a_Duri=C4=87?=) Date: Mon, 3 Sep 2012 17:32:44 +0200 Subject: [M3devel] How small can Modula-3 runtime be? In-Reply-To: <1346679281.68335.YahooMailClassic@web29701.mail.ird.yahoo.com> References: <1346679281.68335.YahooMailClassic@web29701.mail.ird.yahoo.com> Message-ID: Theoretically, many things are possible. But, with great smart cards having 4KB of RAM, and 100+KM of ROM (program memory) I am a bit sceptic here. It's good somebody played with that, but Pascal and Modula-2 are many times more logical choice for really low end hardware. More than enough to talk APDU :). My interest is DVB receiver. There is usually RAM in tens/hundreds of megabytes and Flash in tens at least. And CPU with MMU, to run decent kernel. Lots of interesting devices, also. Ever implemented TCP/IP bare bones? My team did, and while interesting project, it's nothing to write home about :). -- Divided by a common language Dragi?a Duri? dragisha at m3w.org On Sep 3, 2012, at 3:34 PM, Daniel Alejandro Benavides D. wrote: > Hi: > it can run on smart cards, they ran OS and all there so, using a CLASP machine, you can run in silicon card: > http://www.dsse.ecs.soton.ac.uk/techreports/95-03/1997/dsse-tr-97-8.ps.gz > > Thanks in advance > > --- El lun, 3/9/12, Dragi?a Duri? escribi?: > > De: Dragi?a Duri? > Asunto: Re: [M3devel] How small can Modula-3 runtime be? > Para: "Mika Nystrom" > CC: m3devel at elegosoft.com > Fecha: lunes, 3 de septiembre, 2012 02:45 > > Bare hardware would be too much a task for me now, but those numbers are great. I can spare few tens of KILObytes anytime :). > > Right now I am looking around for cross-compiling setup. Anyone did it in work environment? (not only for bootstrap) > > -- > Divided by a common language > > Dragi?a Duri? > dragisha at m3w.org > > > > > On Sep 3, 2012, at 12:34 AM, Mika Nystrom wrote: > >> =?utf-8?Q?Dragi=C5=A1a_Duri=C4=87?= writes: >> ... >>> >>> Question is - if we go embedded, how small can we go? >>> >>> Obviously, we need full Linux kernel, pthreads and all. But what about = >>> total RAM? Flash (persistent storage)?=20 >>> >>> dd >> >> Modula-3 has been run without a kernel. >> >> http://resolver.caltech.edu/CaltechCSTR:1993.cs-tr-93-15 >> >> Table 3.0, page 49, for byte counts of the runtime. >> >> I have the source code somewhere. It's a modified version of the old SRC M3 >> compiler, which compiles M3 to C. >> >> Mika >> >> > -------------- next part -------------- An HTML attachment was scrubbed... URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 495 bytes Desc: Message signed with OpenPGP using GPGMail URL: From dabenavidesd at yahoo.es Mon Sep 3 17:49:02 2012 From: dabenavidesd at yahoo.es (Daniel Alejandro Benavides D.) Date: Mon, 3 Sep 2012 16:49:02 +0100 (BST) Subject: [M3devel] How small can Modula-3 runtime be? In-Reply-To: Message-ID: <1346687342.7043.YahooMailClassic@web29702.mail.ird.yahoo.com> Hi all: the main issue for not running common firm-ware is is trust, and so you need cultivate trust (using certification or verified compiler) you need either a safe language or a safe subset of it. (e.g look how many times you need to reload the firmware in an MP4 player, etc, it tell you why you need trust) For sure there are many people who used Modula-2 in the distant past, but today HW poses other challenges, for instance a GC heap is much bigger than UNSAFE one, but Modula-3 has both you can select which parts of your system uses which RT, and you can still depend on your language to detect static type errors like ESC/Modula-3. If I would recode a RT in a safe language I would use Modula-3 for this reason, so, either for network packet transceiver or video on demand one, you need a trusted framework for objects? on transfer, Obliq is for that, even if it's interpreted, it gives? you more expressive power so you will probably have a smaller code on a tiny interpreter. Thanks in advance --- El lun, 3/9/12, Dragi?a Duri? escribi?: De: Dragi?a Duri? Asunto: Re: [M3devel] How small can Modula-3 runtime be? Para: "Daniel Alejandro Benavides D." CC: m3devel at elegosoft.com Fecha: lunes, 3 de septiembre, 2012 10:32 Theoretically, many things are possible. But, with great smart cards having 4KB of RAM, and 100+KM of ROM (program memory) I am a bit sceptic here. It's good somebody played with that, but Pascal and Modula-2 are many times more logical choice for really low end hardware. More than enough to talk APDU :). My interest is DVB receiver. There is usually RAM in tens/hundreds of megabytes and Flash in tens at least. And CPU with MMU, to run decent kernel. Lots of interesting devices, also. Ever implemented TCP/IP bare bones? My team did, and while interesting project, it's nothing to write home about :).? --Divided by a common language Dragi?a Duri?dragisha at m3w.org On Sep 3, 2012, at 3:34 PM, Daniel Alejandro Benavides D. wrote: Hi: it can run on smart cards, they ran OS and all there so, using a CLASP machine, you can run in silicon card: http://www.dsse.ecs.soton.ac.uk/techreports/95-03/1997/dsse-tr-97-8.ps.gz Thanks in advance --- El lun, 3/9/12, Dragi?a Duri? escribi?: De: Dragi?a Duri? Asunto: Re: [M3devel] How small can Modula-3 runtime be? Para: "Mika Nystrom" CC: m3devel at elegosoft.com Fecha: lunes, 3 de septiembre, 2012 02:45 Bare hardware would be too much a task for me now, but those numbers are great. I can spare few tens of KILObytes anytime :). Right now I am looking around for cross-compiling setup. Anyone did it in work environment? (not only for bootstrap) --Divided by a common language Dragi?a Duri?dragisha at m3w.org On Sep 3, 2012, at 12:34 AM, Mika Nystrom wrote: =?utf-8?Q?Dragi=C5=A1a_Duri=C4=87?= writes: ... Question is - if we go embedded, how small can we go? Obviously, we need full Linux kernel, pthreads and all. But what about = total RAM? Flash (persistent storage)?=20 dd Modula-3 has been run without a kernel. http://resolver.caltech.edu/CaltechCSTR:1993.cs-tr-93-15 Table 3.0, page 49, for byte counts of the runtime. I have the source code somewhere. ?It's a modified version of the old SRC M3 compiler, which compiles M3 to C. ???Mika -------------- next part -------------- An HTML attachment was scrubbed... URL: From dragisha at m3w.org Mon Sep 3 18:27:12 2012 From: dragisha at m3w.org (=?utf-8?Q?Dragi=C5=A1a_Duri=C4=87?=) Date: Mon, 3 Sep 2012 18:27:12 +0200 Subject: [M3devel] How small can Modula-3 runtime be? In-Reply-To: <1346687342.7043.YahooMailClassic@web29702.mail.ird.yahoo.com> References: <1346687342.7043.YahooMailClassic@web29702.mail.ird.yahoo.com> Message-ID: Trust is great. Safe "JTAG like" mechanism is even greater:). So you can always un-brick your device, whatever reason for bricking was in first place. Be it malicious firmware, or just buggy one. No need to advocate Modula-3 to me :). I am just being real. Modula-3 is not for smart cards I am dealing with. Period :). Obliq is Modula-3 runtime + other code. Nothing small there, at least not smaller than Modula-3 :). -- Divided by a common language Dragi?a Duri? dragisha at m3w.org On Sep 3, 2012, at 5:49 PM, Daniel Alejandro Benavides D. wrote: > Hi all: > the main issue for not running common firm-ware is is trust, and so you need cultivate trust (using certification or verified compiler) you need either a safe language or a safe subset of it. (e.g look how many times you need to reload the firmware in an MP4 player, etc, it tell you why you need trust) > For sure there are many people who used Modula-2 in the distant past, but today HW poses other challenges, for instance a GC heap is much bigger than UNSAFE one, but Modula-3 has both you can select which parts of your system uses which RT, and you can still depend on your language to detect static type errors like ESC/Modula-3. > If I would recode a RT in a safe language I would use Modula-3 for this reason, so, either for network packet transceiver or video on demand one, you need a trusted framework for objects on transfer, Obliq is for that, even if it's interpreted, it gives you more expressive power so you will probably have a smaller code on a tiny interpreter. > Thanks in advance > > --- El lun, 3/9/12, Dragi?a Duri? escribi?: > > De: Dragi?a Duri? > Asunto: Re: [M3devel] How small can Modula-3 runtime be? > Para: "Daniel Alejandro Benavides D." > CC: m3devel at elegosoft.com > Fecha: lunes, 3 de septiembre, 2012 10:32 > > Theoretically, many things are possible. > > But, with great smart cards having 4KB of RAM, and 100+KM of ROM (program memory) I am a bit sceptic here. It's good somebody played with that, but Pascal and Modula-2 are many times more logical choice for really low end hardware. More than enough to talk APDU :). > > My interest is DVB receiver. There is usually RAM in tens/hundreds of megabytes and Flash in tens at least. And CPU with MMU, to run decent kernel. Lots of interesting devices, also. > > Ever implemented TCP/IP bare bones? My team did, and while interesting project, it's nothing to write home about :). > > -- > Divided by a common language > > Dragi?a Duri? > dragisha at m3w.org > > > > > On Sep 3, 2012, at 3:34 PM, Daniel Alejandro Benavides D. wrote: > >> Hi: >> it can run on smart cards, they ran OS and all there so, using a CLASP machine, you can run in silicon card: >> http://www.dsse.ecs.soton.ac.uk/techreports/95-03/1997/dsse-tr-97-8.ps.gz >> >> Thanks in advance >> >> --- El lun, 3/9/12, Dragi?a Duri? escribi?: >> >> De: Dragi?a Duri? >> Asunto: Re: [M3devel] How small can Modula-3 runtime be? >> Para: "Mika Nystrom" >> CC: m3devel at elegosoft.com >> Fecha: lunes, 3 de septiembre, 2012 02:45 >> >> Bare hardware would be too much a task for me now, but those numbers are great. I can spare few tens of KILObytes anytime :). >> >> Right now I am looking around for cross-compiling setup. Anyone did it in work environment? (not only for bootstrap) >> >> -- >> Divided by a common language >> >> Dragi?a Duri? >> dragisha at m3w.org >> >> >> >> >> On Sep 3, 2012, at 12:34 AM, Mika Nystrom wrote: >> >>> =?utf-8?Q?Dragi=C5=A1a_Duri=C4=87?= writes: >>> ... >>>> >>>> Question is - if we go embedded, how small can we go? >>>> >>>> Obviously, we need full Linux kernel, pthreads and all. But what about = >>>> total RAM? Flash (persistent storage)?=20 >>>> >>>> dd >>> >>> Modula-3 has been run without a kernel. >>> >>> http://resolver.caltech.edu/CaltechCSTR:1993.cs-tr-93-15 >>> >>> Table 3.0, page 49, for byte counts of the runtime. >>> >>> I have the source code somewhere. It's a modified version of the old SRC M3 >>> compiler, which compiles M3 to C. >>> >>> Mika >>> >>> >> > -------------- next part -------------- An HTML attachment was scrubbed... URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 495 bytes Desc: Message signed with OpenPGP using GPGMail URL: From dabenavidesd at yahoo.es Mon Sep 3 18:58:55 2012 From: dabenavidesd at yahoo.es (Daniel Alejandro Benavides D.) Date: Mon, 3 Sep 2012 17:58:55 +0100 (BST) Subject: [M3devel] How small can Modula-3 runtime be? In-Reply-To: Message-ID: <1346691535.42369.YahooMailClassic@web29706.mail.ird.yahoo.com> Hi all: Oh, no, not my intention, and less to pray for DEC reassurance, but they wrote software and HW for their systems with Modula-3, it might not be clear waht kind of HW but let's say it was on micro processors, not like VAXen but theoretical work on that is more interesting (a mainframe-class machine with lots of HW aids for the compiler is something wanted). For instance memory module playing with Quest, etc. If you want an embedded language that's Obliq, if you want a real sublanguage Baby is. Objects are stack allocated Thanks in advance --- El lun, 3/9/12, Dragi?a Duri? escribi?: De: Dragi?a Duri? Asunto: Re: [M3devel] How small can Modula-3 runtime be? Para: "Daniel Alejandro Benavides D." CC: m3devel at elegosoft.com Fecha: lunes, 3 de septiembre, 2012 11:27 Trust is great. Safe "JTAG like" mechanism is even greater:). So you can always un-brick your device, whatever reason for bricking was in first place. Be it malicious firmware, or just buggy one. No need to advocate Modula-3 to me :). I am just being real. Modula-3 is not for smart cards I am dealing with. Period :). Obliq is Modula-3 runtime + other code. Nothing small there, at least not smaller than Modula-3 :). --Divided by a common language Dragi?a Duri?dragisha at m3w.org On Sep 3, 2012, at 5:49 PM, Daniel Alejandro Benavides D. wrote: Hi all: the main issue for not running common firm-ware is is trust, and so you need cultivate trust (using certification or verified compiler) you need either a safe language or a safe subset of it. (e.g look how many times you need to reload the firmware in an MP4 player, etc, it tell you why you need trust) For sure there are many people who used Modula-2 in the distant past, but today HW poses other challenges, for instance a GC heap is much bigger than UNSAFE one, but Modula-3 has both you can select which parts of your system uses which RT, and you can still depend on your language to detect static type errors like ESC/Modula-3. If I would recode a RT in a safe language I would use Modula-3 for this reason, so, either for network packet transceiver or video on demand one, you need a trusted framework for objects? on transfer, Obliq is for that, even if it's interpreted, it gives? you more expressive power so you will probably have a smaller code on a tiny interpreter. Thanks in advance --- El lun, 3/9/12, Dragi?a Duri? escribi?: De: Dragi?a Duri? Asunto: Re: [M3devel] How small can Modula-3 runtime be? Para: "Daniel Alejandro Benavides D." CC: m3devel at elegosoft.com Fecha: lunes, 3 de septiembre, 2012 10:32 Theoretically, many things are possible. But, with great smart cards having 4KB of RAM, and 100+KM of ROM (program memory) I am a bit sceptic here. It's good somebody played with that, but Pascal and Modula-2 are many times more logical choice for really low end hardware. More than enough to talk APDU :). My interest is DVB receiver. There is usually RAM in tens/hundreds of megabytes and Flash in tens at least. And CPU with MMU, to run decent kernel. Lots of interesting devices, also. Ever implemented TCP/IP bare bones? My team did, and while interesting project, it's nothing to write home about :).? --Divided by a common language Dragi?a Duri?dragisha at m3w.org On Sep 3, 2012, at 3:34 PM, Daniel Alejandro Benavides D. wrote: Hi: it can run on smart cards, they ran OS and all there so, using a CLASP machine, you can run in silicon card: http://www.dsse.ecs.soton.ac.uk/techreports/95-03/1997/dsse-tr-97-8.ps.gz Thanks in advance --- El lun, 3/9/12, Dragi?a Duri? escribi?: De: Dragi?a Duri? Asunto: Re: [M3devel] How small can Modula-3 runtime be? Para: "Mika Nystrom" CC: m3devel at elegosoft.com Fecha: lunes, 3 de septiembre, 2012 02:45 Bare hardware would be too much a task for me now, but those numbers are great. I can spare few tens of KILObytes anytime :). Right now I am looking around for cross-compiling setup. Anyone did it in work environment? (not only for bootstrap) --Divided by a common language Dragi?a Duri?dragisha at m3w.org On Sep 3, 2012, at 12:34 AM, Mika Nystrom wrote: =?utf-8?Q?Dragi=C5=A1a_Duri=C4=87?= writes: ... Question is - if we go embedded, how small can we go? Obviously, we need full Linux kernel, pthreads and all. But what about = total RAM? Flash (persistent storage)?=20 dd Modula-3 has been run without a kernel. http://resolver.caltech.edu/CaltechCSTR:1993.cs-tr-93-15 Table 3.0, page 49, for byte counts of the runtime. I have the source code somewhere. ?It's a modified version of the old SRC M3 compiler, which compiles M3 to C. ???Mika -------------- next part -------------- An HTML attachment was scrubbed... URL: From hosking at cs.purdue.edu Tue Sep 4 16:11:44 2012 From: hosking at cs.purdue.edu (Antony Hosking) Date: Tue, 4 Sep 2012 10:11:44 -0400 Subject: [M3devel] M3CG Message-ID: <47B9A237-FD0B-4E40-9F12-938BC3D00E9E@cs.purdue.edu> Jay, I?ve been looking over some of your changes to M3CG interfaces. You?ll notice that I removed your import of Cstdlib.int into M3CG_Ops.i3. It does not belong there. The type as declared: TypeUID = BITS 32 FOR [-16_7fffffff-1 .. 16_7fffffff]; is correct as is. It is a 32 bit value that encodes a particular subrange, REGARDLESS of target machine. It is improper to change that definition to rely on some C type. I also have some other questions. Why did you add the type Cardinal.T? This seems entirely unnecessary, since targets don?t have a Cardinal type. The only type they have is a target integer. All other Modula-3 ordinal types should be simulated in the compiler using TInt.T. I would advise that it be removed. Also, I don?t understand why you changed descriptions of the primitive types to use this Cardinal.T instead of the original CARDINAL to hold information about the bit size, alignment, and byte size. There is no situation in which a host will need to emulate the behavior of CARDINAL for these values (all can be represented using CARDINAL no matter what the host). I am concerned that these changes reflect a desire on your part to change the world to fit your specific needs (whether justified or not). The interfaces defined in M3CG were carefully designed and inherit from a long code-chain going back to the 1980?s and have not see huge changes since then. I strongly advise against making changes unless you have good reason, because there are a number of tools that rely on M3CG (not just those in the public sources). I am going to do a pass to revert some of your changes, since they are causing a number of my systems to fail to build. (cf. Niagara on tinderbox). I strongly advise that you try to use a private branch when developing new functionality. We as a community can then go through a revision process to vet substantive changes before merging them into the trunk. ? Tony From dabenavidesd at yahoo.es Tue Sep 4 17:09:04 2012 From: dabenavidesd at yahoo.es (Daniel Alejandro Benavides D.) Date: Tue, 4 Sep 2012 16:09:04 +0100 (BST) Subject: [M3devel] M3CG In-Reply-To: <47B9A237-FD0B-4E40-9F12-938BC3D00E9E@cs.purdue.edu> Message-ID: <1346771344.7996.YahooMailClassic@web29702.mail.ird.yahoo.com> Hi all: Although I haven't followed closely recent developments I think Abstract machines interface are needed to better interface the system. Currently reliance in M3CGen as door-step to other compilers could make things less stable admittedly, but we need to take account of the compiler view internally and externally, where are proofs of this per-se view I don't know but If you can read this abstract (2nd paragraph, first part) of: http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.33.5167 I could abstract INTERFACES but Larch Style seems correct path (and I know of a tool called Benton for LM3 to retrieve specification requirements from knowledge base) I could extract some info from it and try to recover automaton specification and from there a specification that can readily tract the compiler (Internal language) from one of the two other and backwards SOURCE and OBJECT (and so interfaces to debug, link and load). Thanks in advance --- El mar, 4/9/12, Antony Hosking escribi?: De: Antony Hosking Asunto: [M3devel] M3CG Para: "Jay K" CC: "m3devel at elegosoft.com developers" Fecha: martes, 4 de septiembre, 2012 09:11 Jay, I?ve been looking over some of your changes to M3CG interfaces.? You?ll notice that I removed your import of Cstdlib.int into M3CG_Ops.i3.? It does not belong there.? The type as declared: TypeUID = BITS 32 FOR [-16_7fffffff-1 .. 16_7fffffff]; is correct as is.? It is a 32 bit value that encodes a particular subrange, REGARDLESS of target machine.? It is improper to change that definition to rely on some C type. I also have some other questions.? Why did you add the type Cardinal.T?? This seems entirely unnecessary, since targets don?t have a Cardinal type.? The only type they have is a target integer.? All other Modula-3 ordinal types should be simulated in the compiler using TInt.T.? I would advise that it be removed.? Also, I don?t understand why you changed descriptions of the primitive types to use this Cardinal.T instead of the original CARDINAL to hold information about the bit size, alignment, and byte size.? There is no situation in which a host will need to emulate the behavior of CARDINAL for these values (all can be represented using CARDINAL no matter what the host). I am concerned that these changes reflect a desire on your part to change the world to fit your specific needs (whether justified or not).? The interfaces defined in M3CG were carefully designed and inherit from a long code-chain going back to the 1980?s and have not see huge changes since then.? I strongly advise against making changes unless you have good reason, because there are a number of tools that rely on M3CG (not just those in the public sources). I am going to do a pass to revert some of your changes, since they are causing a number of my systems to fail to build.? (cf. Niagara on tinderbox). I strongly advise that you try to use a private branch when developing new functionality.? We as a community can then go through a revision process to vet substantive changes before merging them into the trunk. ? Tony -------------- next part -------------- An HTML attachment was scrubbed... URL: From jay.krell at cornell.edu Tue Sep 4 18:09:49 2012 From: jay.krell at cornell.edu (Jay) Date: Tue, 4 Sep 2012 09:09:49 -0700 Subject: [M3devel] M3CG In-Reply-To: <47B9A237-FD0B-4E40-9F12-938BC3D00E9E@cs.purdue.edu> References: <47B9A237-FD0B-4E40-9F12-938BC3D00E9E@cs.purdue.edu> Message-ID: <62BAB949-DBD6-405D-A6E8-0F416DEB586B@gmail.com> "BITS" seems to not provide any useful value. It only makes it so you can't put the type into a portable unpacked record, which is what I was doing. I either have to pack my record somehow (counting target-dependent bits??) or lay out the fields carefully in some way that all targets allow. The problem was that some targets didn't like the layout. Given the stated range, that you'll get enough bits to store it, what is the point in giving the size too? Isn't providing just the range and no particular size, sufficient & more abstract? Granted, I went the other way. I don't remember but guessing: Cardinal.T would be, like CARDINAL vs. INTEGER: only slightly subtley useful: same as TInt.T, but disallows negative numbers. Most likely I ran into places where a host integer/cardinal did not necessarily suffice, and so a target type was called for. I know we have places that need to use target types but don't yet. Specifically for the sizes of things like records & arrays. Otherwise we have hacks where 64bit systems declare 32bit limits. - Jay (briefly/pocket-sized-computer-aka-phone) On Sep 4, 2012, at 7:11 AM, Antony Hosking wrote: > Jay, > > I?ve been looking over some of your changes to M3CG interfaces. You?ll notice that I removed your import of Cstdlib.int into M3CG_Ops.i3. It does not belong there. The type as declared: > > TypeUID = BITS 32 FOR [-16_7fffffff-1 .. 16_7fffffff]; > > is correct as is. It is a 32 bit value that encodes a particular subrange, REGARDLESS of target machine. It is improper to change that definition to rely on some C type. > > I also have some other questions. Why did you add the type Cardinal.T? This seems entirely unnecessary, since targets don?t have a Cardinal type. The only type they have is a target integer. All other Modula-3 ordinal types should be simulated in the compiler using TInt.T. I would advise that it be removed. Also, I don?t understand why you changed descriptions of the primitive types to use this Cardinal.T instead of the original CARDINAL to hold information about the bit size, alignment, and byte size. There is no situation in which a host will need to emulate the behavior of CARDINAL for these values (all can be represented using CARDINAL no matter what the host). > > I am concerned that these changes reflect a desire on your part to change the world to fit your specific needs (whether justified or not). The interfaces defined in M3CG were carefully designed and inherit from a long code-chain going back to the 1980?s and have not see huge changes since then. I strongly advise against making changes unless you have good reason, because there are a number of tools that rely on M3CG (not just those in the public sources). > > I am going to do a pass to revert some of your changes, since they are causing a number of my systems to fail to build. (cf. Niagara on tinderbox). > > I strongly advise that you try to use a private branch when developing new functionality. We as a community can then go through a revision process to vet substantive changes before merging them into the trunk. > > ? Tony > From dabenavidesd at yahoo.es Tue Sep 4 18:18:18 2012 From: dabenavidesd at yahoo.es (Daniel Alejandro Benavides D.) Date: Tue, 4 Sep 2012 17:18:18 +0100 (BST) Subject: [M3devel] M3CG In-Reply-To: <62BAB949-DBD6-405D-A6E8-0F416DEB586B@gmail.com> Message-ID: <1346775498.85928.YahooMailClassic@web29705.mail.ird.yahoo.com> Hi all: strictly speaking isn't allowed target typing if that's what you are referring to. Thanks in advance --- El mar, 4/9/12, Jay escribi?: De: Jay Asunto: Re: [M3devel] M3CG Para: "Antony Hosking" CC: "m3devel at elegosoft.com developers" , "Jay K" Fecha: martes, 4 de septiembre, 2012 11:09 "BITS" seems to not provide any useful value. It only makes it so you can't put the type into a portable unpacked record, which is what I was doing. I either have to pack my record somehow (counting target-dependent bits??) or lay out the fields carefully in some way that all targets allow. The problem was that some targets didn't like the layout. Given the stated range, that you'll get enough bits to store it, what is the point in giving the size too? Isn't providing just the range and no particular size, sufficient & more abstract? Granted, I went the other way. I don't remember but guessing: Cardinal.T would be, like CARDINAL vs. INTEGER: only slightly subtley useful: same as TInt.T, but disallows negative numbers. Most likely I ran into places where a host integer/cardinal did not necessarily suffice, and so a target type was called for. I know we have places that need to? use target types but don't yet. Specifically for the sizes of things like records & arrays. Otherwise we have hacks where 64bit systems declare 32bit limits. - Jay (briefly/pocket-sized-computer-aka-phone) On Sep 4, 2012, at 7:11 AM, Antony Hosking wrote: > Jay, > > I?ve been looking over some of your changes to M3CG interfaces.? You?ll notice that I removed your import of Cstdlib.int into M3CG_Ops.i3.? It does not belong there.? The type as declared: > > TypeUID = BITS 32 FOR [-16_7fffffff-1 .. 16_7fffffff]; > > is correct as is.? It is a 32 bit value that encodes a particular subrange, REGARDLESS of target machine.? It is improper to change that definition to rely on some C type. > > I also have some other questions.? Why did you add the type Cardinal.T?? This seems entirely unnecessary, since targets don?t have a Cardinal type.? The only type they have is a target integer.? All other Modula-3 ordinal types should be simulated in the compiler using TInt.T.? I would advise that it be removed.? Also, I don?t understand why you changed descriptions of the primitive types to use this Cardinal.T instead of the original CARDINAL to hold information about the bit size, alignment, and byte size.? There is no situation in which a host will need to emulate the behavior of CARDINAL for these values (all can be represented using CARDINAL no matter what the host). > > I am concerned that these changes reflect a desire on your part to change the world to fit your specific needs (whether justified or not).? The interfaces defined in M3CG were carefully designed and inherit from a long code-chain going back to the 1980?s and have not see huge changes since then.? I strongly advise against making changes unless you have good reason, because there are a number of tools that rely on M3CG (not just those in the public sources). > > I am going to do a pass to revert some of your changes, since they are causing a number of my systems to fail to build.? (cf. Niagara on tinderbox). > > I strongly advise that you try to use a private branch when developing new functionality.? We as a community can then go through a revision process to vet substantive changes before merging them into the trunk. > > ? Tony > -------------- next part -------------- An HTML attachment was scrubbed... URL: From hosking at cs.purdue.edu Tue Sep 4 19:05:34 2012 From: hosking at cs.purdue.edu (Antony Hosking) Date: Tue, 4 Sep 2012 13:05:34 -0400 Subject: [M3devel] M3CG In-Reply-To: <62BAB949-DBD6-405D-A6E8-0F416DEB586B@gmail.com> References: <47B9A237-FD0B-4E40-9F12-938BC3D00E9E@cs.purdue.edu> <62BAB949-DBD6-405D-A6E8-0F416DEB586B@gmail.com> Message-ID: <3FC36B77-1F30-462C-9688-285D50351455@cs.purdue.edu> On Sep 4, 2012, at 12:09 PM, Jay wrote: > "BITS" seems to not provide any useful value. It only makes it so you can't put the type into a portable unpacked record, which is what I was doing. I either have to pack my record somehow (counting target-dependent bits??) or lay out the fields carefully in some way that all targets allow. The problem was that some targets didn't like the layout. For M3CG.TypeUID the BITS 32 enforces that it is always representable in 32 bits. This is a fundamental invariant of the compiler and run-time system. Removing it might allow bug creep. You don?t need to pack your record. You just need a field sufficiently large to hold the value of a type id. In this instance an INTEGER field would suffice, or you can use the same subrange. > Given the stated range, that you'll get enough bits to store it, what is the point in giving the size too? Isn't providing just the range and no particular size, sufficient & more abstract? Granted, I went the other way. Only if an implementation chooses to store a subrange in as few bits as necessary. Yes, CM3 does this, but it is not guaranteed by the language spec. Here the size is the critical invariant. > I don't remember but guessing: > > > Cardinal.T would be, like CARDINAL vs. INTEGER: only slightly subtley useful: same as TInt.T, but disallows negative numbers. But for what purpose. The target does not have CARDINAL. It only has a target integer. > Most likely I ran into places where a host integer/cardinal did not necessarily suffice, and so a target type was called for. > > > I know we have places that need to use target types but don't yet. Specifically for the sizes of things like records & arrays. Otherwise we have hacks where 64bit systems declare 32bit limits. Again, TInt.T suffices for all of these. > > > - Jay (briefly/pocket-sized-computer-aka-phone) > > On Sep 4, 2012, at 7:11 AM, Antony Hosking wrote: > >> Jay, >> >> I?ve been looking over some of your changes to M3CG interfaces. You?ll notice that I removed your import of Cstdlib.int into M3CG_Ops.i3. It does not belong there. The type as declared: >> >> TypeUID = BITS 32 FOR [-16_7fffffff-1 .. 16_7fffffff]; >> >> is correct as is. It is a 32 bit value that encodes a particular subrange, REGARDLESS of target machine. It is improper to change that definition to rely on some C type. >> >> I also have some other questions. Why did you add the type Cardinal.T? This seems entirely unnecessary, since targets don?t have a Cardinal type. The only type they have is a target integer. All other Modula-3 ordinal types should be simulated in the compiler using TInt.T. I would advise that it be removed. Also, I don?t understand why you changed descriptions of the primitive types to use this Cardinal.T instead of the original CARDINAL to hold information about the bit size, alignment, and byte size. There is no situation in which a host will need to emulate the behavior of CARDINAL for these values (all can be represented using CARDINAL no matter what the host). >> >> I am concerned that these changes reflect a desire on your part to change the world to fit your specific needs (whether justified or not). The interfaces defined in M3CG were carefully designed and inherit from a long code-chain going back to the 1980?s and have not see huge changes since then. I strongly advise against making changes unless you have good reason, because there are a number of tools that rely on M3CG (not just those in the public sources). >> >> I am going to do a pass to revert some of your changes, since they are causing a number of my systems to fail to build. (cf. Niagara on tinderbox). >> >> I strongly advise that you try to use a private branch when developing new functionality. We as a community can then go through a revision process to vet substantive changes before merging them into the trunk. >> >> ? Tony >> From jay.krell at cornell.edu Tue Sep 4 22:47:05 2012 From: jay.krell at cornell.edu (Jay K) Date: Tue, 4 Sep 2012 20:47:05 +0000 Subject: [M3devel] M3CG In-Reply-To: <3FC36B77-1F30-462C-9688-285D50351455@cs.purdue.edu> References: <47B9A237-FD0B-4E40-9F12-938BC3D00E9E@cs.purdue.edu> <62BAB949-DBD6-405D-A6E8-0F416DEB586B@gmail.com>, <3FC36B77-1F30-462C-9688-285D50351455@cs.purdue.edu> Message-ID: RECORD HoldsTypeUID: typeuid: [FIRST(TypeUID)..LAST(TypeUID)]; END? But what if I'm really just a holder/passer of this thing, and I never interpret it. Now TypeUID can't be changed to LONGREAL or somesuch. Ideally some code wouldn't care and still be correct. The idea is to hold the thing, pass it on, without knowing what it is. I want a field with the same type. Why does it matter if TypeUID is representable in 32 bits? Isn't the range the interface? If it wasn't for readability of all the F's, I think TypeUID = [-16_7FFFFFFF - 1 .. 16_7FFFFFFF]; is best. Do we really care about few or many bits that occupies? Cstdint.int32_t I agree is a bit lazy. Maybe something like Word.Shift(1, 31) .. Word.Not(Word.Shift(1, 31)) ? A bit wordy but ok.Maybe not correct. Not clear the start is negative.Maybe needs to be more like: (-Word.Not(Word.Shift(1, 31))) - 1 .. Word.Not(Word.Shift(1, 31)) But these bit twiddlings might then confuse people.So maybe having to count F's is better.. :( You know, what about being 32bits in size would be part of an interface? I don't think much/anything, but maybe. Do we do/allow things like bit operations on it? Index into it a certain number of bits? Take the address and assume BYTESIZE == 4? I could see those maybe occuring. Maybe. But I'm pretty sure they values are fairly abstract/opaque and the best anyone can do is format them as strings and compare them for e.g. sorting purposes, but must assume they are fairly sparse. Btw, whenever the matter of "portability to signed-magnitude" or one's complement comes up, I admit I get a bit confused. Two's complement is very ingrained in my world view. I agree TInt.T suffices. Just like CARDINAL isn't needed, INTEGER suffices. Cardinal.T just disallows negative numbers earlier, or at lower level, etc. If we had to use TInt.T and add checks in a few places that it >= 0, ok. It seems a little nice to put the checking in. - Jay > Subject: Re: M3CG > From: hosking at cs.purdue.edu > Date: Tue, 4 Sep 2012 13:05:34 -0400 > CC: m3devel at elegosoft.com > To: jay.krell at cornell.edu > > On Sep 4, 2012, at 12:09 PM, Jay wrote: > > > "BITS" seems to not provide any useful value. It only makes it so you can't put the type into a portable unpacked record, which is what I was doing. I either have to pack my record somehow (counting target-dependent bits??) or lay out the fields carefully in some way that all targets allow. The problem was that some targets didn't like the layout. > > For M3CG.TypeUID the BITS 32 enforces that it is always representable in 32 bits. This is a fundamental invariant of the compiler and run-time system. Removing it might allow bug creep. You don?t need to pack your record. You just need a field sufficiently large to hold the value of a type id. In this instance an INTEGER field would suffice, or you can use the same subrange. > > > Given the stated range, that you'll get enough bits to store it, what is the point in giving the size too? Isn't providing just the range and no particular size, sufficient & more abstract? Granted, I went the other way. > > Only if an implementation chooses to store a subrange in as few bits as necessary. Yes, CM3 does this, but it is not guaranteed by the language spec. Here the size is the critical invariant. > > > I don't remember but guessing: > > > > > > Cardinal.T would be, like CARDINAL vs. INTEGER: only slightly subtley useful: same as TInt.T, but disallows negative numbers. > > But for what purpose. The target does not have CARDINAL. It only has a target integer. > > > Most likely I ran into places where a host integer/cardinal did not necessarily suffice, and so a target type was called for. > > > > > > I know we have places that need to use target types but don't yet. Specifically for the sizes of things like records & arrays. Otherwise we have hacks where 64bit systems declare 32bit limits. > > Again, TInt.T suffices for all of these. > > > > > > > - Jay (briefly/pocket-sized-computer-aka-phone) > > > > On Sep 4, 2012, at 7:11 AM, Antony Hosking wrote: > > > >> Jay, > >> > >> I?ve been looking over some of your changes to M3CG interfaces. You?ll notice that I removed your import of Cstdlib.int into M3CG_Ops.i3. It does not belong there. The type as declared: > >> > >> TypeUID = BITS 32 FOR [-16_7fffffff-1 .. 16_7fffffff]; > >> > >> is correct as is. It is a 32 bit value that encodes a particular subrange, REGARDLESS of target machine. It is improper to change that definition to rely on some C type. > >> > >> I also have some other questions. Why did you add the type Cardinal.T? This seems entirely unnecessary, since targets don?t have a Cardinal type. The only type they have is a target integer. All other Modula-3 ordinal types should be simulated in the compiler using TInt.T. I would advise that it be removed. Also, I don?t understand why you changed descriptions of the primitive types to use this Cardinal.T instead of the original CARDINAL to hold information about the bit size, alignment, and byte size. There is no situation in which a host will need to emulate the behavior of CARDINAL for these values (all can be represented using CARDINAL no matter what the host). > >> > >> I am concerned that these changes reflect a desire on your part to change the world to fit your specific needs (whether justified or not). The interfaces defined in M3CG were carefully designed and inherit from a long code-chain going back to the 1980?s and have not see huge changes since then. I strongly advise against making changes unless you have good reason, because there are a number of tools that rely on M3CG (not just those in the public sources). > >> > >> I am going to do a pass to revert some of your changes, since they are causing a number of my systems to fail to build. (cf. Niagara on tinderbox). > >> > >> I strongly advise that you try to use a private branch when developing new functionality. We as a community can then go through a revision process to vet substantive changes before merging them into the trunk. > >> > >> ? Tony > >> > -------------- next part -------------- An HTML attachment was scrubbed... URL: From jay.krell at cornell.edu Wed Sep 5 08:55:56 2012 From: jay.krell at cornell.edu (Jay K) Date: Wed, 5 Sep 2012 06:55:56 +0000 Subject: [M3devel] m3commit down again? Message-ID: m3commit down again? -------------- next part -------------- An HTML attachment was scrubbed... URL: From dragisha at m3w.org Wed Sep 5 09:40:41 2012 From: dragisha at m3w.org (=?utf-8?Q?Dragi=C5=A1a_Duri=C4=87?=) Date: Wed, 5 Sep 2012 09:40:41 +0200 Subject: [M3devel] M3CG In-Reply-To: References: <47B9A237-FD0B-4E40-9F12-938BC3D00E9E@cs.purdue.edu> <62BAB949-DBD6-405D-A6E8-0F416DEB586B@gmail.com>, <3FC36B77-1F30-462C-9688-285D50351455@cs.purdue.edu> Message-ID: <228002BB-DE75-4320-A70F-CBB82A23D758@m3w.org> Why holding/passing of this value in INTEGER would be a problem? As long as range checks are passed on "assignment boundaries", it is all well. It is how Modula-3 does things. -- Divided by a common language Dragi?a Duri? dragisha at m3w.org On Sep 4, 2012, at 10:47 PM, Jay K wrote: > RECORD HoldsTypeUID: > typeuid: [FIRST(TypeUID)..LAST(TypeUID)]; > END? > > > But what if I'm really just a holder/passer of this thing, > and I never interpret it. Now TypeUID can't be changed > to LONGREAL or somesuch. Ideally some code wouldn't care > and still be correct. > > > The idea is to hold the thing, pass it on, without knowing > what it is. I want a field with the same type. > > > Why does it matter if TypeUID is representable in 32 bits? > Isn't the range the interface? > If it wasn't for readability of all the F's, I think > TypeUID = [-16_7FFFFFFF - 1 .. 16_7FFFFFFF]; is best. > > > Do we really care about few or many bits that occupies? > > > Cstdint.int32_t I agree is a bit lazy. > Maybe something like Word.Shift(1, 31) .. Word.Not(Word.Shift(1, 31)) ? > A bit wordy but ok. > Maybe not correct. Not clear the start is negative. > Maybe needs to be more like: > > (-Word.Not(Word.Shift(1, 31))) - 1 .. Word.Not(Word.Shift(1, 31)) > > > But these bit twiddlings might then confuse people. > So maybe having to count F's is better.. :( > > > You know, what about being 32bits in size would be part of an interface? > I don't think much/anything, but maybe. > > > Do we do/allow things like bit operations on it? Index into it a certain number > of bits? Take the address and assume BYTESIZE == 4? > I could see those maybe occuring. Maybe. > > > But I'm pretty sure they values are fairly abstract/opaque and the best anyone can do > is format them as strings and compare them for e.g. sorting purposes, but must > assume they are fairly sparse. > > > Btw, whenever the matter of "portability to signed-magnitude" or one's complement > comes up, I admit I get a bit confused. Two's complement is very ingrained > in my world view. > > > I agree TInt.T suffices. > Just like CARDINAL isn't needed, INTEGER suffices. > Cardinal.T just disallows negative numbers earlier, or at lower level, etc. > If we had to use TInt.T and add checks in a few places that it >= 0, ok. > It seems a little nice to put the checking in. > > > - Jay > > > > > > Subject: Re: M3CG > > From: hosking at cs.purdue.edu > > Date: Tue, 4 Sep 2012 13:05:34 -0400 > > CC: m3devel at elegosoft.com > > To: jay.krell at cornell.edu > > > > On Sep 4, 2012, at 12:09 PM, Jay wrote: > > > > > "BITS" seems to not provide any useful value. It only makes it so you can't put the type into a portable unpacked record, which is what I was doing. I either have to pack my record somehow (counting target-dependent bits??) or lay out the fields carefully in some way that all targets allow. The problem was that some targets didn't like the layout. > > > > For M3CG.TypeUID the BITS 32 enforces that it is always representable in 32 bits. This is a fundamental invariant of the compiler and run-time system. Removing it might allow bug creep. You don?t need to pack your record. You just need a field sufficiently large to hold the value of a type id. In this instance an INTEGER field would suffice, or you can use the same subrange. > > > > > Given the stated range, that you'll get enough bits to store it, what is the point in giving the size too? Isn't providing just the range and no particular size, sufficient & more abstract? Granted, I went the other way. > > > > Only if an implementation chooses to store a subrange in as few bits as necessary. Yes, CM3 does this, but it is not guaranteed by the language spec. Here the size is the critical invariant. > > > > > I don't remember but guessing: > > > > > > > > > Cardinal.T would be, like CARDINAL vs. INTEGER: only slightly subtley useful: same as TInt.T, but disallows negative numbers. > > > > But for what purpose. The target does not have CARDINAL. It only has a target integer. > > > > > Most likely I ran into places where a host integer/cardinal did not necessarily suffice, and so a target type was called for. > > > > > > > > > I know we have places that need to use target types but don't yet. Specifically for the sizes of things like records & arrays. Otherwise we have hacks where 64bit systems declare 32bit limits. > > > > Again, TInt.T suffices for all of these. > > > > > > > > > > > - Jay (briefly/pocket-sized-computer-aka-phone) > > > > > > On Sep 4, 2012, at 7:11 AM, Antony Hosking wrote: > > > > > >> Jay, > > >> > > >> I?ve been looking over some of your changes to M3CG interfaces. You?ll notice that I removed your import of Cstdlib.int into M3CG_Ops.i3. It does not belong there. The type as declared: > > >> > > >> TypeUID = BITS 32 FOR [-16_7fffffff-1 .. 16_7fffffff]; > > >> > > >> is correct as is. It is a 32 bit value that encodes a particular subrange, REGARDLESS of target machine. It is improper to change that definition to rely on some C type. > > >> > > >> I also have some other questions. Why did you add the type Cardinal.T? This seems entirely unnecessary, since targets don?t have a Cardinal type. The only type they have is a target integer. All other Modula-3 ordinal types should be simulated in the compiler using TInt.T. I would advise that it be removed. Also, I don?t understand why you changed descriptions of the primitive types to use this Cardinal.T instead of the original CARDINAL to hold information about the bit size, alignment, and byte size. There is no situation in which a host will need to emulate the behavior of CARDINAL for these values (all can be represented using CARDINAL no matter what the host). > > >> > > >> I am concerned that these changes reflect a desire on your part to change the world to fit your specific needs (whether justified or not). The interfaces defined in M3CG were carefully designed and inherit from a long code-chain going back to the 1980?s and have not see huge changes since then. I strongly advise against making changes unless you have good reason, because there are a number of tools that rely on M3CG (not just those in the public sources). > > >> > > >> I am going to do a pass to revert some of your changes, since they are causing a number of my systems to fail to build. (cf. Niagara on tinderbox). > > >> > > >> I strongly advise that you try to use a private branch when developing new functionality. We as a community can then go through a revision process to vet substantive changes before merging them into the trunk. > > >> > > >> ? Tony > > >> > > -------------- next part -------------- An HTML attachment was scrubbed... URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 495 bytes Desc: Message signed with OpenPGP using GPGMail URL: From hosking at cs.purdue.edu Wed Sep 5 16:33:58 2012 From: hosking at cs.purdue.edu (Antony Hosking) Date: Wed, 5 Sep 2012 10:33:58 -0400 Subject: [M3devel] M3CG In-Reply-To: <228002BB-DE75-4320-A70F-CBB82A23D758@m3w.org> References: <47B9A237-FD0B-4E40-9F12-938BC3D00E9E@cs.purdue.edu> <62BAB949-DBD6-405D-A6E8-0F416DEB586B@gmail.com>, <3FC36B77-1F30-462C-9688-285D50351455@cs.purdue.edu> <228002BB-DE75-4320-A70F-CBB82A23D758@m3w.org> Message-ID: <87DABD01-259D-4373-8C77-9570869AF6FD@cs.purdue.edu> Precisely. On Sep 5, 2012, at 3:40 AM, Dragi?a Duri? wrote: > Why holding/passing of this value in INTEGER would be a problem? As long as range checks are passed on "assignment boundaries", it is all well. > > It is how Modula-3 does things. > > -- > Divided by a common language > > Dragi?a Duri? > dragisha at m3w.org > > > > > On Sep 4, 2012, at 10:47 PM, Jay K wrote: > >> RECORD HoldsTypeUID: >> typeuid: [FIRST(TypeUID)..LAST(TypeUID)]; >> END? >> >> >> But what if I'm really just a holder/passer of this thing, >> and I never interpret it. Now TypeUID can't be changed >> to LONGREAL or somesuch. Ideally some code wouldn't care >> and still be correct. >> >> >> The idea is to hold the thing, pass it on, without knowing >> what it is. I want a field with the same type. >> >> >> Why does it matter if TypeUID is representable in 32 bits? >> Isn't the range the interface? >> If it wasn't for readability of all the F's, I think >> TypeUID = [-16_7FFFFFFF - 1 .. 16_7FFFFFFF]; is best. >> >> >> Do we really care about few or many bits that occupies? >> >> >> Cstdint.int32_t I agree is a bit lazy. >> Maybe something like Word.Shift(1, 31) .. Word.Not(Word.Shift(1, 31)) ? >> A bit wordy but ok. >> Maybe not correct. Not clear the start is negative. >> Maybe needs to be more like: >> >> (-Word.Not(Word.Shift(1, 31))) - 1 .. Word.Not(Word.Shift(1, 31)) >> >> >> But these bit twiddlings might then confuse people. >> So maybe having to count F's is better.. :( >> >> >> You know, what about being 32bits in size would be part of an interface? >> I don't think much/anything, but maybe. >> >> >> Do we do/allow things like bit operations on it? Index into it a certain number >> of bits? Take the address and assume BYTESIZE == 4? >> I could see those maybe occuring. Maybe. >> >> >> But I'm pretty sure they values are fairly abstract/opaque and the best anyone can do >> is format them as strings and compare them for e.g. sorting purposes, but must >> assume they are fairly sparse. >> >> >> Btw, whenever the matter of "portability to signed-magnitude" or one's complement >> comes up, I admit I get a bit confused. Two's complement is very ingrained >> in my world view. >> >> >> I agree TInt.T suffices. >> Just like CARDINAL isn't needed, INTEGER suffices. >> Cardinal.T just disallows negative numbers earlier, or at lower level, etc. >> If we had to use TInt.T and add checks in a few places that it >= 0, ok. >> It seems a little nice to put the checking in. >> >> >> - Jay >> >> >> >> >> > Subject: Re: M3CG >> > From: hosking at cs.purdue.edu >> > Date: Tue, 4 Sep 2012 13:05:34 -0400 >> > CC: m3devel at elegosoft.com >> > To: jay.krell at cornell.edu >> > >> > On Sep 4, 2012, at 12:09 PM, Jay wrote: >> > >> > > "BITS" seems to not provide any useful value. It only makes it so you can't put the type into a portable unpacked record, which is what I was doing. I either have to pack my record somehow (counting target-dependent bits??) or lay out the fields carefully in some way that all targets allow. The problem was that some targets didn't like the layout. >> > >> > For M3CG.TypeUID the BITS 32 enforces that it is always representable in 32 bits. This is a fundamental invariant of the compiler and run-time system. Removing it might allow bug creep. You don?t need to pack your record. You just need a field sufficiently large to hold the value of a type id. In this instance an INTEGER field would suffice, or you can use the same subrange. >> > >> > > Given the stated range, that you'll get enough bits to store it, what is the point in giving the size too? Isn't providing just the range and no particular size, sufficient & more abstract? Granted, I went the other way. >> > >> > Only if an implementation chooses to store a subrange in as few bits as necessary. Yes, CM3 does this, but it is not guaranteed by the language spec. Here the size is the critical invariant. >> > >> > > I don't remember but guessing: >> > > >> > > >> > > Cardinal.T would be, like CARDINAL vs. INTEGER: only slightly subtley useful: same as TInt.T, but disallows negative numbers. >> > >> > But for what purpose. The target does not have CARDINAL. It only has a target integer. >> > >> > > Most likely I ran into places where a host integer/cardinal did not necessarily suffice, and so a target type was called for. >> > > >> > > >> > > I know we have places that need to use target types but don't yet. Specifically for the sizes of things like records & arrays. Otherwise we have hacks where 64bit systems declare 32bit limits. >> > >> > Again, TInt.T suffices for all of these. >> > >> > > >> > > >> > > - Jay (briefly/pocket-sized-computer-aka-phone) >> > > >> > > On Sep 4, 2012, at 7:11 AM, Antony Hosking wrote: >> > > >> > >> Jay, >> > >> >> > >> I?ve been looking over some of your changes to M3CG interfaces. You?ll notice that I removed your import of Cstdlib.int into M3CG_Ops.i3. It does not belong there. The type as declared: >> > >> >> > >> TypeUID = BITS 32 FOR [-16_7fffffff-1 .. 16_7fffffff]; >> > >> >> > >> is correct as is. It is a 32 bit value that encodes a particular subrange, REGARDLESS of target machine. It is improper to change that definition to rely on some C type. >> > >> >> > >> I also have some other questions. Why did you add the type Cardinal.T? This seems entirely unnecessary, since targets don?t have a Cardinal type. The only type they have is a target integer. All other Modula-3 ordinal types should be simulated in the compiler using TInt.T. I would advise that it be removed. Also, I don?t understand why you changed descriptions of the primitive types to use this Cardinal.T instead of the original CARDINAL to hold information about the bit size, alignment, and byte size. There is no situation in which a host will need to emulate the behavior of CARDINAL for these values (all can be represented using CARDINAL no matter what the host). >> > >> >> > >> I am concerned that these changes reflect a desire on your part to change the world to fit your specific needs (whether justified or not). The interfaces defined in M3CG were carefully designed and inherit from a long code-chain going back to the 1980?s and have not see huge changes since then. I strongly advise against making changes unless you have good reason, because there are a number of tools that rely on M3CG (not just those in the public sources). >> > >> >> > >> I am going to do a pass to revert some of your changes, since they are causing a number of my systems to fail to build. (cf. Niagara on tinderbox). >> > >> >> > >> I strongly advise that you try to use a private branch when developing new functionality. We as a community can then go through a revision process to vet substantive changes before merging them into the trunk. >> > >> >> > >> ? Tony >> > >> >> > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From jay.krell at cornell.edu Wed Sep 5 16:50:57 2012 From: jay.krell at cornell.edu (Jay K) Date: Wed, 5 Sep 2012 14:50:57 +0000 Subject: [M3devel] M3CG In-Reply-To: <87DABD01-259D-4373-8C77-9570869AF6FD@cs.purdue.edu> References: <47B9A237-FD0B-4E40-9F12-938BC3D00E9E@cs.purdue.edu>, <62BAB949-DBD6-405D-A6E8-0F416DEB586B@gmail.com>, , <3FC36B77-1F30-462C-9688-285D50351455@cs.purdue.edu>, , <228002BB-DE75-4320-A70F-CBB82A23D758@m3w.org>, <87DABD01-259D-4373-8C77-9570869AF6FD@cs.purdue.edu> Message-ID: This seems quite wrong from a simple engineering/design/factoring/abstraction point of view. Imagine I have a few of these things. They are subranges or enums. That fit in a smaller size. Wouldn't it be nice, to just use the type directly and get the space savings? Opportunistically? What if the type is a REAL or a LONGINT? I want the type to be opaque/abstract where that is easy and cheap and this certainly seems like an easy/cheap place to have slightly valuable opacity. Isn't it really good, more than "just nice" to let the type change and have a lot of code work just as well? Because they didn't copy around knowledge of what the type is? What if the type changes? Anyone just copying it around by exact restated typename is unaffected. Anyone who looked at and decided to restate the definition might type might be broken. And again, really -- you want to sacrifice both performance and abstraction when both are easily kept better? That is, I'm all for range checks to keep things "safe", safety is important, but in this case you can easily preserve safety w/o adding range checks. We do have enums at this layer. Would you suggest I take the ORD of all of those and store them in INTEGERs too? I am really surprised. - Jay From: hosking at cs.purdue.edu Date: Wed, 5 Sep 2012 10:33:58 -0400 To: dragisha at m3w.org CC: m3devel at elegosoft.com; jay.krell at cornell.edu Subject: Re: [M3devel] M3CG Precisely. On Sep 5, 2012, at 3:40 AM, Dragi?a Duri? wrote:Why holding/passing of this value in INTEGER would be a problem? As long as range checks are passed on "assignment boundaries", it is all well. It is how Modula-3 does things. --Divided by a common language Dragi?a Duri?dragisha at m3w.org On Sep 4, 2012, at 10:47 PM, Jay K wrote:RECORD HoldsTypeUID: typeuid: [FIRST(TypeUID)..LAST(TypeUID)]; END? But what if I'm really just a holder/passer of this thing, and I never interpret it. Now TypeUID can't be changed to LONGREAL or somesuch. Ideally some code wouldn't care and still be correct. The idea is to hold the thing, pass it on, without knowing what it is. I want a field with the same type. Why does it matter if TypeUID is representable in 32 bits? Isn't the range the interface? If it wasn't for readability of all the F's, I think TypeUID = [-16_7FFFFFFF - 1 .. 16_7FFFFFFF]; is best. Do we really care about few or many bits that occupies? Cstdint.int32_t I agree is a bit lazy. Maybe something like Word.Shift(1, 31) .. Word.Not(Word.Shift(1, 31)) ? A bit wordy but ok. Maybe not correct. Not clear the start is negative. Maybe needs to be more like: (-Word.Not(Word.Shift(1, 31))) - 1 .. Word.Not(Word.Shift(1, 31)) But these bit twiddlings might then confuse people. So maybe having to count F's is better.. :( You know, what about being 32bits in size would be part of an interface? I don't think much/anything, but maybe. Do we do/allow things like bit operations on it? Index into it a certain number of bits? Take the address and assume BYTESIZE == 4? I could see those maybe occuring. Maybe. But I'm pretty sure they values are fairly abstract/opaque and the best anyone can do is format them as strings and compare them for e.g. sorting purposes, but must assume they are fairly sparse. Btw, whenever the matter of "portability to signed-magnitude" or one's complement comes up, I admit I get a bit confused. Two's complement is very ingrained in my world view. I agree TInt.T suffices. Just like CARDINAL isn't needed, INTEGER suffices. Cardinal.T just disallows negative numbers earlier, or at lower level, etc. If we had to use TInt.T and add checks in a few places that it >= 0, ok. It seems a little nice to put the checking in. - Jay > Subject: Re: M3CG > From: hosking at cs.purdue.edu > Date: Tue, 4 Sep 2012 13:05:34 -0400 > CC: m3devel at elegosoft.com > To: jay.krell at cornell.edu > > On Sep 4, 2012, at 12:09 PM, Jay wrote: > > > "BITS" seems to not provide any useful value. It only makes it so you can't put the type into a portable unpacked record, which is what I was doing. I either have to pack my record somehow (counting target-dependent bits??) or lay out the fields carefully in some way that all targets allow. The problem was that some targets didn't like the layout. > > For M3CG.TypeUID the BITS 32 enforces that it is always representable in 32 bits. This is a fundamental invariant of the compiler and run-time system. Removing it might allow bug creep. You don't need to pack your record. You just need a field sufficiently large to hold the value of a type id. In this instance an INTEGER field would suffice, or you can use the same subrange. > > > Given the stated range, that you'll get enough bits to store it, what is the point in giving the size too? Isn't providing just the range and no particular size, sufficient & more abstract? Granted, I went the other way. > > Only if an implementation chooses to store a subrange in as few bits as necessary. Yes, CM3 does this, but it is not guaranteed by the language spec. Here the size is the critical invariant. > > > I don't remember but guessing: > > > > > > Cardinal.T would be, like CARDINAL vs. INTEGER: only slightly subtley useful: same as TInt.T, but disallows negative numbers. > > But for what purpose. The target does not have CARDINAL. It only has a target integer. > > > Most likely I ran into places where a host integer/cardinal did not necessarily suffice, and so a target type was called for. > > > > > > I know we have places that need to use target types but don't yet. Specifically for the sizes of things like records & arrays. Otherwise we have hacks where 64bit systems declare 32bit limits. > > Again, TInt.T suffices for all of these. > > > > > > > - Jay (briefly/pocket-sized-computer-aka-phone) > > > > On Sep 4, 2012, at 7:11 AM, Antony Hosking wrote: > > > >> Jay, > >> > >> I've been looking over some of your changes to M3CG interfaces. You'll notice that I removed your import of Cstdlib.int into M3CG_Ops.i3. It does not belong there. The type as declared: > >> > >> TypeUID = BITS 32 FOR [-16_7fffffff-1 .. 16_7fffffff]; > >> > >> is correct as is. It is a 32 bit value that encodes a particular subrange, REGARDLESS of target machine. It is improper to change that definition to rely on some C type. > >> > >> I also have some other questions. Why did you add the type Cardinal.T? This seems entirely unnecessary, since targets don't have a Cardinal type. The only type they have is a target integer. All other Modula-3 ordinal types should be simulated in the compiler using TInt.T. I would advise that it be removed. Also, I don't understand why you changed descriptions of the primitive types to use this Cardinal.T instead of the original CARDINAL to hold information about the bit size, alignment, and byte size. There is no situation in which a host will need to emulate the behavior of CARDINAL for these values (all can be represented using CARDINAL no matter what the host). > >> > >> I am concerned that these changes reflect a desire on your part to change the world to fit your specific needs (whether justified or not). The interfaces defined in M3CG were carefully designed and inherit from a long code-chain going back to the 1980's and have not see huge changes since then. I strongly advise against making changes unless you have good reason, because there are a number of tools that rely on M3CG (not just those in the public sources). > >> > >> I am going to do a pass to revert some of your changes, since they are causing a number of my systems to fail to build. (cf. Niagara on tinderbox). > >> > >> I strongly advise that you try to use a private branch when developing new functionality. We as a community can then go through a revision process to vet substantive changes before merging them into the trunk. > >> > >> - Tony > >> > -------------- next part -------------- An HTML attachment was scrubbed... URL: From hosking at cs.purdue.edu Wed Sep 5 17:18:08 2012 From: hosking at cs.purdue.edu (Antony Hosking) Date: Wed, 5 Sep 2012 11:18:08 -0400 Subject: [M3devel] M3CG In-Reply-To: References: <47B9A237-FD0B-4E40-9F12-938BC3D00E9E@cs.purdue.edu>, <62BAB949-DBD6-405D-A6E8-0F416DEB586B@gmail.com>, , <3FC36B77-1F30-462C-9688-285D50351455@cs.purdue.edu>, , <228002BB-DE75-4320-A70F-CBB82A23D758@m3w.org>, <87DABD01-259D-4373-8C77-9570869AF6FD@cs.purdue.edu> Message-ID: <71BE165D-B2DA-494D-9608-CCC581A32E4F@cs.purdue.edu> Remind me again why you can?t use TypeUID as is? There is nothing in the language spec that prohibits packed types in records. On Sep 5, 2012, at 10:50 AM, Jay K wrote: > This seems quite wrong from a simple engineering/design/factoring/abstraction point of view. > > > Imagine I have a few of these things. They are subranges or enums. That fit in a smaller size. > Wouldn't it be nice, to just use the type directly and get the space savings? Opportunistically? > What if the type is a REAL or a LONGINT? > I want the type to be opaque/abstract where that is easy and cheap and this certainly seems like an easy/cheap place to have slightly valuable opacity. > Isn't it really good, more than "just nice" to let the type change and have a lot of code work just as well? > Because they didn't copy around knowledge of what the type is? > What if the type changes? > Anyone just copying it around by exact restated typename is unaffected. > Anyone who looked at and decided to restate the definition might type might be broken. > > > And again, really -- you want to sacrifice both performance and abstraction when both are easily kept better? > That is, I'm all for range checks to keep things "safe", safety is important, but in this case you can easily preserve safety w/o adding range checks. > > > We do have enums at this layer. > Would you suggest I take the ORD of all of those and store them in INTEGERs too? > > > I am really surprised. > > > - Jay > > > From: hosking at cs.purdue.edu > Date: Wed, 5 Sep 2012 10:33:58 -0400 > To: dragisha at m3w.org > CC: m3devel at elegosoft.com; jay.krell at cornell.edu > Subject: Re: [M3devel] M3CG > > Precisely. > > > On Sep 5, 2012, at 3:40 AM, Dragi?a Duri? wrote: > > Why holding/passing of this value in INTEGER would be a problem? As long as range checks are passed on "assignment boundaries", it is all well. > > It is how Modula-3 does things. > > -- > Divided by a common language > > Dragi?a Duri? > dragisha at m3w.org > > > > > On Sep 4, 2012, at 10:47 PM, Jay K wrote: > > RECORD HoldsTypeUID: > typeuid: [FIRST(TypeUID)..LAST(TypeUID)]; > END? > > > But what if I'm really just a holder/passer of this thing, > and I never interpret it. Now TypeUID can't be changed > to LONGREAL or somesuch. Ideally some code wouldn't care > and still be correct. > > > The idea is to hold the thing, pass it on, without knowing > what it is. I want a field with the same type. > > > Why does it matter if TypeUID is representable in 32 bits? > Isn't the range the interface? > If it wasn't for readability of all the F's, I think > TypeUID = [-16_7FFFFFFF - 1 .. 16_7FFFFFFF]; is best. > > > Do we really care about few or many bits that occupies? > > > Cstdint.int32_t I agree is a bit lazy. > Maybe something like Word.Shift(1, 31) .. Word.Not(Word.Shift(1, 31)) ? > A bit wordy but ok. > Maybe not correct. Not clear the start is negative. > Maybe needs to be more like: > > (-Word.Not(Word.Shift(1, 31))) - 1 .. Word.Not(Word.Shift(1, 31)) > > > But these bit twiddlings might then confuse people. > So maybe having to count F's is better.. :( > > > You know, what about being 32bits in size would be part of an interface? > I don't think much/anything, but maybe. > > > Do we do/allow things like bit operations on it? Index into it a certain number > of bits? Take the address and assume BYTESIZE == 4? > I could see those maybe occuring. Maybe. > > > But I'm pretty sure they values are fairly abstract/opaque and the best anyone can do > is format them as strings and compare them for e.g. sorting purposes, but must > assume they are fairly sparse. > > > Btw, whenever the matter of "portability to signed-magnitude" or one's complement > comes up, I admit I get a bit confused. Two's complement is very ingrained > in my world view. > > > I agree TInt.T suffices. > Just like CARDINAL isn't needed, INTEGER suffices. > Cardinal.T just disallows negative numbers earlier, or at lower level, etc. > If we had to use TInt.T and add checks in a few places that it >= 0, ok. > It seems a little nice to put the checking in. > > > - Jay > > > > > > Subject: Re: M3CG > > From: hosking at cs.purdue.edu > > Date: Tue, 4 Sep 2012 13:05:34 -0400 > > CC: m3devel at elegosoft.com > > To: jay.krell at cornell.edu > > > > On Sep 4, 2012, at 12:09 PM, Jay wrote: > > > > > "BITS" seems to not provide any useful value. It only makes it so you can't put the type into a portable unpacked record, which is what I was doing. I either have to pack my record somehow (counting target-dependent bits??) or lay out the fields carefully in some way that all targets allow. The problem was that some targets didn't like the layout. > > > > For M3CG.TypeUID the BITS 32 enforces that it is always representable in 32 bits. This is a fundamental invariant of the compiler and run-time system. Removing it might allow bug creep. You don't need to pack your record. You just need a field sufficiently large to hold the value of a type id. In this instance an INTEGER field would suffice, or you can use the same subrange. > > > > > Given the stated range, that you'll get enough bits to store it, what is the point in giving the size too? Isn't providing just the range and no particular size, sufficient & more abstract? Granted, I went the other way. > > > > Only if an implementation chooses to store a subrange in as few bits as necessary. Yes, CM3 does this, but it is not guaranteed by the language spec. Here the size is the critical invariant. > > > > > I don't remember but guessing: > > > > > > > > > Cardinal.T would be, like CARDINAL vs. INTEGER: only slightly subtley useful: same as TInt.T, but disallows negative numbers. > > > > But for what purpose. The target does not have CARDINAL. It only has a target integer. > > > > > Most likely I ran into places where a host integer/cardinal did not necessarily suffice, and so a target type was called for. > > > > > > > > > I know we have places that need to use target types but don't yet. Specifically for the sizes of things like records & arrays. Otherwise we have hacks where 64bit systems declare 32bit limits. > > > > Again, TInt.T suffices for all of these. > > > > > > > > > > > - Jay (briefly/pocket-sized-computer-aka-phone) > > > > > > On Sep 4, 2012, at 7:11 AM, Antony Hosking wrote: > > > > > >> Jay, > > >> > > >> I've been looking over some of your changes to M3CG interfaces. You'll notice that I removed your import of Cstdlib.int into M3CG_Ops.i3. It does not belong there. The type as declared: > > >> > > >> TypeUID = BITS 32 FOR [-16_7fffffff-1 .. 16_7fffffff]; > > >> > > >> is correct as is. It is a 32 bit value that encodes a particular subrange, REGARDLESS of target machine. It is improper to change that definition to rely on some C type. > > >> > > >> I also have some other questions. Why did you add the type Cardinal.T? This seems entirely unnecessary, since targets don't have a Cardinal type. The only type they have is a target integer. All other Modula-3 ordinal types should be simulated in the compiler using TInt.T. I would advise that it be removed. Also, I don't understand why you changed descriptions of the primitive types to use this Cardinal.T instead of the original CARDINAL to hold information about the bit size, alignment, and byte size. There is no situation in which a host will need to emulate the behavior of CARDINAL for these values (all can be represented using CARDINAL no matter what the host). > > >> > > >> I am concerned that these changes reflect a desire on your part to change the world to fit your specific needs (whether justified or not). The interfaces defined in M3CG were carefully designed and inherit from a long code-chain going back to the 1980's and have not see huge changes since then. I strongly advise against making changes unless you have good reason, because there are a number of tools that rely on M3CG (not just those in the public sources). > > >> > > >> I am going to do a pass to revert some of your changes, since they are causing a number of my systems to fail to build. (cf. Niagara on tinderbox). > > >> > > >> I strongly advise that you try to use a private branch when developing new functionality. We as a community can then go through a revision process to vet substantive changes before merging them into the trunk. > > >> > > >> - Tony > > >> > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From hosking at cs.purdue.edu Wed Sep 5 17:36:03 2012 From: hosking at cs.purdue.edu (Antony Hosking) Date: Wed, 5 Sep 2012 11:36:03 -0400 Subject: [M3devel] M3CG In-Reply-To: <71BE165D-B2DA-494D-9608-CCC581A32E4F@cs.purdue.edu> References: <47B9A237-FD0B-4E40-9F12-938BC3D00E9E@cs.purdue.edu>, <62BAB949-DBD6-405D-A6E8-0F416DEB586B@gmail.com>, , <3FC36B77-1F30-462C-9688-285D50351455@cs.purdue.edu>, , <228002BB-DE75-4320-A70F-CBB82A23D758@m3w.org>, <87DABD01-259D-4373-8C77-9570869AF6FD@cs.purdue.edu> <71BE165D-B2DA-494D-9608-CCC581A32E4F@cs.purdue.edu> Message-ID: As I recall you were having trouble with alignment, right? In which case, why not pad your record type out to a reasonably aligned value? As in: CONST PadRange = Word.LeftShift(1, BITSIZE(ADDRESS) - BITSIZE(TypeUID)) - 1; RECORD t: TypeUID; pad: BITS BITSIZE(ADDRESS) - 32 FOR [0..PadRange]; END; On Sep 5, 2012, at 11:18 AM, Antony Hosking wrote: > Remind me again why you can?t use TypeUID as is? > There is nothing in the language spec that prohibits packed types in records. > > On Sep 5, 2012, at 10:50 AM, Jay K wrote: > >> This seems quite wrong from a simple engineering/design/factoring/abstraction point of view. >> >> >> Imagine I have a few of these things. They are subranges or enums. That fit in a smaller size. >> Wouldn't it be nice, to just use the type directly and get the space savings? Opportunistically? >> What if the type is a REAL or a LONGINT? >> I want the type to be opaque/abstract where that is easy and cheap and this certainly seems like an easy/cheap place to have slightly valuable opacity. >> Isn't it really good, more than "just nice" to let the type change and have a lot of code work just as well? >> Because they didn't copy around knowledge of what the type is? >> What if the type changes? >> Anyone just copying it around by exact restated typename is unaffected. >> Anyone who looked at and decided to restate the definition might type might be broken. >> >> >> And again, really -- you want to sacrifice both performance and abstraction when both are easily kept better? >> That is, I'm all for range checks to keep things "safe", safety is important, but in this case you can easily preserve safety w/o adding range checks. >> >> >> We do have enums at this layer. >> Would you suggest I take the ORD of all of those and store them in INTEGERs too? >> >> >> I am really surprised. >> >> >> - Jay >> >> >> From: hosking at cs.purdue.edu >> Date: Wed, 5 Sep 2012 10:33:58 -0400 >> To: dragisha at m3w.org >> CC: m3devel at elegosoft.com; jay.krell at cornell.edu >> Subject: Re: [M3devel] M3CG >> >> Precisely. >> >> >> On Sep 5, 2012, at 3:40 AM, Dragi?a Duri? wrote: >> >> Why holding/passing of this value in INTEGER would be a problem? As long as range checks are passed on "assignment boundaries", it is all well. >> >> It is how Modula-3 does things. >> >> -- >> Divided by a common language >> >> Dragi?a Duri? >> dragisha at m3w.org >> >> >> >> >> On Sep 4, 2012, at 10:47 PM, Jay K wrote: >> >> RECORD HoldsTypeUID: >> typeuid: [FIRST(TypeUID)..LAST(TypeUID)]; >> END? >> >> >> But what if I'm really just a holder/passer of this thing, >> and I never interpret it. Now TypeUID can't be changed >> to LONGREAL or somesuch. Ideally some code wouldn't care >> and still be correct. >> >> >> The idea is to hold the thing, pass it on, without knowing >> what it is. I want a field with the same type. >> >> >> Why does it matter if TypeUID is representable in 32 bits? >> Isn't the range the interface? >> If it wasn't for readability of all the F's, I think >> TypeUID = [-16_7FFFFFFF - 1 .. 16_7FFFFFFF]; is best. >> >> >> Do we really care about few or many bits that occupies? >> >> >> Cstdint.int32_t I agree is a bit lazy. >> Maybe something like Word.Shift(1, 31) .. Word.Not(Word.Shift(1, 31)) ? >> A bit wordy but ok. >> Maybe not correct. Not clear the start is negative. >> Maybe needs to be more like: >> >> (-Word.Not(Word.Shift(1, 31))) - 1 .. Word.Not(Word.Shift(1, 31)) >> >> >> But these bit twiddlings might then confuse people. >> So maybe having to count F's is better.. :( >> >> >> You know, what about being 32bits in size would be part of an interface? >> I don't think much/anything, but maybe. >> >> >> Do we do/allow things like bit operations on it? Index into it a certain number >> of bits? Take the address and assume BYTESIZE == 4? >> I could see those maybe occuring. Maybe. >> >> >> But I'm pretty sure they values are fairly abstract/opaque and the best anyone can do >> is format them as strings and compare them for e.g. sorting purposes, but must >> assume they are fairly sparse. >> >> >> Btw, whenever the matter of "portability to signed-magnitude" or one's complement >> comes up, I admit I get a bit confused. Two's complement is very ingrained >> in my world view. >> >> >> I agree TInt.T suffices. >> Just like CARDINAL isn't needed, INTEGER suffices. >> Cardinal.T just disallows negative numbers earlier, or at lower level, etc. >> If we had to use TInt.T and add checks in a few places that it >= 0, ok. >> It seems a little nice to put the checking in. >> >> >> - Jay >> >> >> >> >> > Subject: Re: M3CG >> > From: hosking at cs.purdue.edu >> > Date: Tue, 4 Sep 2012 13:05:34 -0400 >> > CC: m3devel at elegosoft.com >> > To: jay.krell at cornell.edu >> > >> > On Sep 4, 2012, at 12:09 PM, Jay wrote: >> > >> > > "BITS" seems to not provide any useful value. It only makes it so you can't put the type into a portable unpacked record, which is what I was doing. I either have to pack my record somehow (counting target-dependent bits??) or lay out the fields carefully in some way that all targets allow. The problem was that some targets didn't like the layout. >> > >> > For M3CG.TypeUID the BITS 32 enforces that it is always representable in 32 bits. This is a fundamental invariant of the compiler and run-time system. Removing it might allow bug creep. You don't need to pack your record. You just need a field sufficiently large to hold the value of a type id. In this instance an INTEGER field would suffice, or you can use the same subrange. >> > >> > > Given the stated range, that you'll get enough bits to store it, what is the point in giving the size too? Isn't providing just the range and no particular size, sufficient & more abstract? Granted, I went the other way. >> > >> > Only if an implementation chooses to store a subrange in as few bits as necessary. Yes, CM3 does this, but it is not guaranteed by the language spec. Here the size is the critical invariant. >> > >> > > I don't remember but guessing: >> > > >> > > >> > > Cardinal.T would be, like CARDINAL vs. INTEGER: only slightly subtley useful: same as TInt.T, but disallows negative numbers. >> > >> > But for what purpose. The target does not have CARDINAL. It only has a target integer. >> > >> > > Most likely I ran into places where a host integer/cardinal did not necessarily suffice, and so a target type was called for. >> > > >> > > >> > > I know we have places that need to use target types but don't yet. Specifically for the sizes of things like records & arrays. Otherwise we have hacks where 64bit systems declare 32bit limits. >> > >> > Again, TInt.T suffices for all of these. >> > >> > > >> > > >> > > - Jay (briefly/pocket-sized-computer-aka-phone) >> > > >> > > On Sep 4, 2012, at 7:11 AM, Antony Hosking wrote: >> > > >> > >> Jay, >> > >> >> > >> I've been looking over some of your changes to M3CG interfaces. You'll notice that I removed your import of Cstdlib.int into M3CG_Ops.i3. It does not belong there. The type as declared: >> > >> >> > >> TypeUID = BITS 32 FOR [-16_7fffffff-1 .. 16_7fffffff]; >> > >> >> > >> is correct as is. It is a 32 bit value that encodes a particular subrange, REGARDLESS of target machine. It is improper to change that definition to rely on some C type. >> > >> >> > >> I also have some other questions. Why did you add the type Cardinal.T? This seems entirely unnecessary, since targets don't have a Cardinal type. The only type they have is a target integer. All other Modula-3 ordinal types should be simulated in the compiler using TInt.T. I would advise that it be removed. Also, I don't understand why you changed descriptions of the primitive types to use this Cardinal.T instead of the original CARDINAL to hold information about the bit size, alignment, and byte size. There is no situation in which a host will need to emulate the behavior of CARDINAL for these values (all can be represented using CARDINAL no matter what the host). >> > >> >> > >> I am concerned that these changes reflect a desire on your part to change the world to fit your specific needs (whether justified or not). The interfaces defined in M3CG were carefully designed and inherit from a long code-chain going back to the 1980's and have not see huge changes since then. I strongly advise against making changes unless you have good reason, because there are a number of tools that rely on M3CG (not just those in the public sources). >> > >> >> > >> I am going to do a pass to revert some of your changes, since they are causing a number of my systems to fail to build. (cf. Niagara on tinderbox). >> > >> >> > >> I strongly advise that you try to use a private branch when developing new functionality. We as a community can then go through a revision process to vet substantive changes before merging them into the trunk. >> > >> >> > >> - Tony >> > >> >> > > From jay.krell at cornell.edu Wed Sep 5 20:34:06 2012 From: jay.krell at cornell.edu (Jay K) Date: Wed, 5 Sep 2012 18:34:06 +0000 Subject: [M3devel] M3CG In-Reply-To: References: <47B9A237-FD0B-4E40-9F12-938BC3D00E9E@cs.purdue.edu>, , <62BAB949-DBD6-405D-A6E8-0F416DEB586B@gmail.com>, , , <3FC36B77-1F30-462C-9688-285D50351455@cs.purdue.edu>, , , , <228002BB-DE75-4320-A70F-CBB82A23D758@m3w.org>, , <87DABD01-259D-4373-8C77-9570869AF6FD@cs.purdue.edu>, , <71BE165D-B2DA-494D-9608-CCC581A32E4F@cs.purdue.edu>, Message-ID: I should really insert padding manually? I don't know if I like that or not. My code is/was something like: TYPE T1 = RECORD text: TEXT; typeid: TypeUID; END; and that errors on some platforms. I'm not using "Multipass" right now, but it does still hold possible value.We can remove multipass from m3makefile for nowif that helps. Given a similar problem in C, I would do something like: /* TypeUID must fit in 32 bits, for some reason. */C_ASSERT(sizeof(TypeUID) <= sizeof(UINT32));Where C_ASSERT is in windows.h and looks like:/* compile time assert */ #define C_ASSERT(expression) typedef char __cassert__[(expression) ? 1 : -1]; or somesuch. The error message isn't great when it fails. People also name this "static_assert". It is popular. It doesn't prohibit it from having padding around it, but it does assert it fits in 32 bits. I recall we can do similar in Modula-3. TYPE assertTypeUIDFitsIn32Bits = ARRAY [0..ORD(BITSIZE(TypeUID) <= 32)] OF INTEGER; or to be more certain: TYPE assertTypeUIDFitsIn32Bits = ARRAY [0..-ORD(BITSIZE(TypeUID) <= 32)] OF INTEGER; I'm not sure 0..0 is illegal, but I think 0 .. 1 is. (I sure do miss macros...this is too much syntax for a compile time assert...) Can we just put <* ASSERT BITSIZE(TypeUID) <= 32 *> in the .i3 file? Or elsewhere? - Jay > From: hosking at cs.purdue.edu > Date: Wed, 5 Sep 2012 11:36:03 -0400 > To: jay.krell at cornell.edu > CC: m3devel at elegosoft.com > Subject: Re: [M3devel] M3CG > > As I recall you were having trouble with alignment, right? > > In which case, why not pad your record type out to a reasonably aligned value? As in: > > CONST PadRange = Word.LeftShift(1, BITSIZE(ADDRESS) - BITSIZE(TypeUID)) - 1; > RECORD > t: TypeUID; > pad: BITS BITSIZE(ADDRESS) - 32 FOR [0..PadRange]; > END; > > > > On Sep 5, 2012, at 11:18 AM, Antony Hosking wrote: > > > Remind me again why you can't use TypeUID as is? > > There is nothing in the language spec that prohibits packed types in records. > > > > On Sep 5, 2012, at 10:50 AM, Jay K wrote: > > > >> This seems quite wrong from a simple engineering/design/factoring/abstraction point of view. > >> > >> > >> Imagine I have a few of these things. They are subranges or enums. That fit in a smaller size. > >> Wouldn't it be nice, to just use the type directly and get the space savings? Opportunistically? > >> What if the type is a REAL or a LONGINT? > >> I want the type to be opaque/abstract where that is easy and cheap and this certainly seems like an easy/cheap place to have slightly valuable opacity. > >> Isn't it really good, more than "just nice" to let the type change and have a lot of code work just as well? > >> Because they didn't copy around knowledge of what the type is? > >> What if the type changes? > >> Anyone just copying it around by exact restated typename is unaffected. > >> Anyone who looked at and decided to restate the definition might type might be broken. > >> > >> > >> And again, really -- you want to sacrifice both performance and abstraction when both are easily kept better? > >> That is, I'm all for range checks to keep things "safe", safety is important, but in this case you can easily preserve safety w/o adding range checks. > >> > >> > >> We do have enums at this layer. > >> Would you suggest I take the ORD of all of those and store them in INTEGERs too? > >> > >> > >> I am really surprised. > >> > >> > >> - Jay > >> > >> > >> From: hosking at cs.purdue.edu > >> Date: Wed, 5 Sep 2012 10:33:58 -0400 > >> To: dragisha at m3w.org > >> CC: m3devel at elegosoft.com; jay.krell at cornell.edu > >> Subject: Re: [M3devel] M3CG > >> > >> Precisely. > >> > >> > >> On Sep 5, 2012, at 3:40 AM, Dragi?a Duri? wrote: > >> > >> Why holding/passing of this value in INTEGER would be a problem? As long as range checks are passed on "assignment boundaries", it is all well. > >> > >> It is how Modula-3 does things. > >> > >> -- > >> Divided by a common language > >> > >> Dragi?a Duri? > >> dragisha at m3w.org > >> > >> > >> > >> > >> On Sep 4, 2012, at 10:47 PM, Jay K wrote: > >> > >> RECORD HoldsTypeUID: > >> typeuid: [FIRST(TypeUID)..LAST(TypeUID)]; > >> END? > >> > >> > >> But what if I'm really just a holder/passer of this thing, > >> and I never interpret it. Now TypeUID can't be changed > >> to LONGREAL or somesuch. Ideally some code wouldn't care > >> and still be correct. > >> > >> > >> The idea is to hold the thing, pass it on, without knowing > >> what it is. I want a field with the same type. > >> > >> > >> Why does it matter if TypeUID is representable in 32 bits? > >> Isn't the range the interface? > >> If it wasn't for readability of all the F's, I think > >> TypeUID = [-16_7FFFFFFF - 1 .. 16_7FFFFFFF]; is best. > >> > >> > >> Do we really care about few or many bits that occupies? > >> > >> > >> Cstdint.int32_t I agree is a bit lazy. > >> Maybe something like Word.Shift(1, 31) .. Word.Not(Word.Shift(1, 31)) ? > >> A bit wordy but ok. > >> Maybe not correct. Not clear the start is negative. > >> Maybe needs to be more like: > >> > >> (-Word.Not(Word.Shift(1, 31))) - 1 .. Word.Not(Word.Shift(1, 31)) > >> > >> > >> But these bit twiddlings might then confuse people. > >> So maybe having to count F's is better.. :( > >> > >> > >> You know, what about being 32bits in size would be part of an interface? > >> I don't think much/anything, but maybe. > >> > >> > >> Do we do/allow things like bit operations on it? Index into it a certain number > >> of bits? Take the address and assume BYTESIZE == 4? > >> I could see those maybe occuring. Maybe. > >> > >> > >> But I'm pretty sure they values are fairly abstract/opaque and the best anyone can do > >> is format them as strings and compare them for e.g. sorting purposes, but must > >> assume they are fairly sparse. > >> > >> > >> Btw, whenever the matter of "portability to signed-magnitude" or one's complement > >> comes up, I admit I get a bit confused. Two's complement is very ingrained > >> in my world view. > >> > >> > >> I agree TInt.T suffices. > >> Just like CARDINAL isn't needed, INTEGER suffices. > >> Cardinal.T just disallows negative numbers earlier, or at lower level, etc. > >> If we had to use TInt.T and add checks in a few places that it >= 0, ok. > >> It seems a little nice to put the checking in. > >> > >> > >> - Jay > >> > >> > >> > >> > >> > Subject: Re: M3CG > >> > From: hosking at cs.purdue.edu > >> > Date: Tue, 4 Sep 2012 13:05:34 -0400 > >> > CC: m3devel at elegosoft.com > >> > To: jay.krell at cornell.edu > >> > > >> > On Sep 4, 2012, at 12:09 PM, Jay wrote: > >> > > >> > > "BITS" seems to not provide any useful value. It only makes it so you can't put the type into a portable unpacked record, which is what I was doing. I either have to pack my record somehow (counting target-dependent bits??) or lay out the fields carefully in some way that all targets allow. The problem was that some targets didn't like the layout. > >> > > >> > For M3CG.TypeUID the BITS 32 enforces that it is always representable in 32 bits. This is a fundamental invariant of the compiler and run-time system. Removing it might allow bug creep. You don't need to pack your record. You just need a field sufficiently large to hold the value of a type id. In this instance an INTEGER field would suffice, or you can use the same subrange. > >> > > >> > > Given the stated range, that you'll get enough bits to store it, what is the point in giving the size too? Isn't providing just the range and no particular size, sufficient & more abstract? Granted, I went the other way. > >> > > >> > Only if an implementation chooses to store a subrange in as few bits as necessary. Yes, CM3 does this, but it is not guaranteed by the language spec. Here the size is the critical invariant. > >> > > >> > > I don't remember but guessing: > >> > > > >> > > > >> > > Cardinal.T would be, like CARDINAL vs. INTEGER: only slightly subtley useful: same as TInt.T, but disallows negative numbers. > >> > > >> > But for what purpose. The target does not have CARDINAL. It only has a target integer. > >> > > >> > > Most likely I ran into places where a host integer/cardinal did not necessarily suffice, and so a target type was called for. > >> > > > >> > > > >> > > I know we have places that need to use target types but don't yet. Specifically for the sizes of things like records & arrays. Otherwise we have hacks where 64bit systems declare 32bit limits. > >> > > >> > Again, TInt.T suffices for all of these. > >> > > >> > > > >> > > > >> > > - Jay (briefly/pocket-sized-computer-aka-phone) > >> > > > >> > > On Sep 4, 2012, at 7:11 AM, Antony Hosking wrote: > >> > > > >> > >> Jay, > >> > >> > >> > >> I've been looking over some of your changes to M3CG interfaces. You'll notice that I removed your import of Cstdlib.int into M3CG_Ops.i3. It does not belong there. The type as declared: > >> > >> > >> > >> TypeUID = BITS 32 FOR [-16_7fffffff-1 .. 16_7fffffff]; > >> > >> > >> > >> is correct as is. It is a 32 bit value that encodes a particular subrange, REGARDLESS of target machine. It is improper to change that definition to rely on some C type. > >> > >> > >> > >> I also have some other questions. Why did you add the type Cardinal.T? This seems entirely unnecessary, since targets don't have a Cardinal type. The only type they have is a target integer. All other Modula-3 ordinal types should be simulated in the compiler using TInt.T. I would advise that it be removed. Also, I don't understand why you changed descriptions of the primitive types to use this Cardinal.T instead of the original CARDINAL to hold information about the bit size, alignment, and byte size. There is no situation in which a host will need to emulate the behavior of CARDINAL for these values (all can be represented using CARDINAL no matter what the host). > >> > >> > >> > >> I am concerned that these changes reflect a desire on your part to change the world to fit your specific needs (whether justified or not). The interfaces defined in M3CG were carefully designed and inherit from a long code-chain going back to the 1980's and have not see huge changes since then. I strongly advise against making changes unless you have good reason, because there are a number of tools that rely on M3CG (not just those in the public sources). > >> > >> > >> > >> I am going to do a pass to revert some of your changes, since they are causing a number of my systems to fail to build. (cf. Niagara on tinderbox). > >> > >> > >> > >> I strongly advise that you try to use a private branch when developing new functionality. We as a community can then go through a revision process to vet substantive changes before merging them into the trunk. > >> > >> > >> > >> - Tony > >> > >> > >> > > > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From dragisha at m3w.org Wed Sep 5 21:02:22 2012 From: dragisha at m3w.org (=?utf-8?Q?Dragi=C5=A1a_Duri=C4=87?=) Date: Wed, 5 Sep 2012 21:02:22 +0200 Subject: [M3devel] M3CG In-Reply-To: References: <47B9A237-FD0B-4E40-9F12-938BC3D00E9E@cs.purdue.edu>, <62BAB949-DBD6-405D-A6E8-0F416DEB586B@gmail.com>, , <3FC36B77-1F30-462C-9688-285D50351455@cs.purdue.edu>, , <228002BB-DE75-4320-A70F-CBB82A23D758@m3w.org>, <87DABD01-259D-4373-8C77-9570869AF6FD@cs.purdue.edu> <71BE165D-B2DA-494D-9608-CCC581A32E4F@cs.purdue.edu> Message-ID: This problem is artifical one. Unpacked field going in RECORD/OBJECT after packed field is automatically aligned by type/CPU rules. Only packed field is not aligned. -- Divided by a common language Dragi?a Duri? dragisha at m3w.org On Sep 5, 2012, at 5:36 PM, Antony Hosking wrote: > As I recall you were having trouble with alignment, right? > > In which case, why not pad your record type out to a reasonably aligned value? As in: > > CONST PadRange = Word.LeftShift(1, BITSIZE(ADDRESS) - BITSIZE(TypeUID)) - 1; > RECORD > t: TypeUID; > pad: BITS BITSIZE(ADDRESS) - 32 FOR [0..PadRange]; > END; > > > > On Sep 5, 2012, at 11:18 AM, Antony Hosking wrote: > >> Remind me again why you can?t use TypeUID as is? >> There is nothing in the language spec that prohibits packed types in records. >> >> On Sep 5, 2012, at 10:50 AM, Jay K wrote: >> >>> This seems quite wrong from a simple engineering/design/factoring/abstraction point of view. >>> >>> >>> Imagine I have a few of these things. They are subranges or enums. That fit in a smaller size. >>> Wouldn't it be nice, to just use the type directly and get the space savings? Opportunistically? >>> What if the type is a REAL or a LONGINT? >>> I want the type to be opaque/abstract where that is easy and cheap and this certainly seems like an easy/cheap place to have slightly valuable opacity. >>> Isn't it really good, more than "just nice" to let the type change and have a lot of code work just as well? >>> Because they didn't copy around knowledge of what the type is? >>> What if the type changes? >>> Anyone just copying it around by exact restated typename is unaffected. >>> Anyone who looked at and decided to restate the definition might type might be broken. >>> >>> >>> And again, really -- you want to sacrifice both performance and abstraction when both are easily kept better? >>> That is, I'm all for range checks to keep things "safe", safety is important, but in this case you can easily preserve safety w/o adding range checks. >>> >>> >>> We do have enums at this layer. >>> Would you suggest I take the ORD of all of those and store them in INTEGERs too? >>> >>> >>> I am really surprised. >>> >>> >>> - Jay >>> >>> >>> From: hosking at cs.purdue.edu >>> Date: Wed, 5 Sep 2012 10:33:58 -0400 >>> To: dragisha at m3w.org >>> CC: m3devel at elegosoft.com; jay.krell at cornell.edu >>> Subject: Re: [M3devel] M3CG >>> >>> Precisely. >>> >>> >>> On Sep 5, 2012, at 3:40 AM, Dragi?a Duri? wrote: >>> >>> Why holding/passing of this value in INTEGER would be a problem? As long as range checks are passed on "assignment boundaries", it is all well. >>> >>> It is how Modula-3 does things. >>> >>> -- >>> Divided by a common language >>> >>> Dragi?a Duri? >>> dragisha at m3w.org >>> >>> >>> >>> >>> On Sep 4, 2012, at 10:47 PM, Jay K wrote: >>> >>> RECORD HoldsTypeUID: >>> typeuid: [FIRST(TypeUID)..LAST(TypeUID)]; >>> END? >>> >>> >>> But what if I'm really just a holder/passer of this thing, >>> and I never interpret it. Now TypeUID can't be changed >>> to LONGREAL or somesuch. Ideally some code wouldn't care >>> and still be correct. >>> >>> >>> The idea is to hold the thing, pass it on, without knowing >>> what it is. I want a field with the same type. >>> >>> >>> Why does it matter if TypeUID is representable in 32 bits? >>> Isn't the range the interface? >>> If it wasn't for readability of all the F's, I think >>> TypeUID = [-16_7FFFFFFF - 1 .. 16_7FFFFFFF]; is best. >>> >>> >>> Do we really care about few or many bits that occupies? >>> >>> >>> Cstdint.int32_t I agree is a bit lazy. >>> Maybe something like Word.Shift(1, 31) .. Word.Not(Word.Shift(1, 31)) ? >>> A bit wordy but ok. >>> Maybe not correct. Not clear the start is negative. >>> Maybe needs to be more like: >>> >>> (-Word.Not(Word.Shift(1, 31))) - 1 .. Word.Not(Word.Shift(1, 31)) >>> >>> >>> But these bit twiddlings might then confuse people. >>> So maybe having to count F's is better.. :( >>> >>> >>> You know, what about being 32bits in size would be part of an interface? >>> I don't think much/anything, but maybe. >>> >>> >>> Do we do/allow things like bit operations on it? Index into it a certain number >>> of bits? Take the address and assume BYTESIZE == 4? >>> I could see those maybe occuring. Maybe. >>> >>> >>> But I'm pretty sure they values are fairly abstract/opaque and the best anyone can do >>> is format them as strings and compare them for e.g. sorting purposes, but must >>> assume they are fairly sparse. >>> >>> >>> Btw, whenever the matter of "portability to signed-magnitude" or one's complement >>> comes up, I admit I get a bit confused. Two's complement is very ingrained >>> in my world view. >>> >>> >>> I agree TInt.T suffices. >>> Just like CARDINAL isn't needed, INTEGER suffices. >>> Cardinal.T just disallows negative numbers earlier, or at lower level, etc. >>> If we had to use TInt.T and add checks in a few places that it >= 0, ok. >>> It seems a little nice to put the checking in. >>> >>> >>> - Jay >>> >>> >>> >>> >>>> Subject: Re: M3CG >>>> From: hosking at cs.purdue.edu >>>> Date: Tue, 4 Sep 2012 13:05:34 -0400 >>>> CC: m3devel at elegosoft.com >>>> To: jay.krell at cornell.edu >>>> >>>> On Sep 4, 2012, at 12:09 PM, Jay wrote: >>>> >>>>> "BITS" seems to not provide any useful value. It only makes it so you can't put the type into a portable unpacked record, which is what I was doing. I either have to pack my record somehow (counting target-dependent bits??) or lay out the fields carefully in some way that all targets allow. The problem was that some targets didn't like the layout. >>>> >>>> For M3CG.TypeUID the BITS 32 enforces that it is always representable in 32 bits. This is a fundamental invariant of the compiler and run-time system. Removing it might allow bug creep. You don't need to pack your record. You just need a field sufficiently large to hold the value of a type id. In this instance an INTEGER field would suffice, or you can use the same subrange. >>>> >>>>> Given the stated range, that you'll get enough bits to store it, what is the point in giving the size too? Isn't providing just the range and no particular size, sufficient & more abstract? Granted, I went the other way. >>>> >>>> Only if an implementation chooses to store a subrange in as few bits as necessary. Yes, CM3 does this, but it is not guaranteed by the language spec. Here the size is the critical invariant. >>>> >>>>> I don't remember but guessing: >>>>> >>>>> >>>>> Cardinal.T would be, like CARDINAL vs. INTEGER: only slightly subtley useful: same as TInt.T, but disallows negative numbers. >>>> >>>> But for what purpose. The target does not have CARDINAL. It only has a target integer. >>>> >>>>> Most likely I ran into places where a host integer/cardinal did not necessarily suffice, and so a target type was called for. >>>>> >>>>> >>>>> I know we have places that need to use target types but don't yet. Specifically for the sizes of things like records & arrays. Otherwise we have hacks where 64bit systems declare 32bit limits. >>>> >>>> Again, TInt.T suffices for all of these. >>>> >>>>> >>>>> >>>>> - Jay (briefly/pocket-sized-computer-aka-phone) >>>>> >>>>> On Sep 4, 2012, at 7:11 AM, Antony Hosking wrote: >>>>> >>>>>> Jay, >>>>>> >>>>>> I've been looking over some of your changes to M3CG interfaces. You'll notice that I removed your import of Cstdlib.int into M3CG_Ops.i3. It does not belong there. The type as declared: >>>>>> >>>>>> TypeUID = BITS 32 FOR [-16_7fffffff-1 .. 16_7fffffff]; >>>>>> >>>>>> is correct as is. It is a 32 bit value that encodes a particular subrange, REGARDLESS of target machine. It is improper to change that definition to rely on some C type. >>>>>> >>>>>> I also have some other questions. Why did you add the type Cardinal.T? This seems entirely unnecessary, since targets don't have a Cardinal type. The only type they have is a target integer. All other Modula-3 ordinal types should be simulated in the compiler using TInt.T. I would advise that it be removed. Also, I don't understand why you changed descriptions of the primitive types to use this Cardinal.T instead of the original CARDINAL to hold information about the bit size, alignment, and byte size. There is no situation in which a host will need to emulate the behavior of CARDINAL for these values (all can be represented using CARDINAL no matter what the host). >>>>>> >>>>>> I am concerned that these changes reflect a desire on your part to change the world to fit your specific needs (whether justified or not). The interfaces defined in M3CG were carefully designed and inherit from a long code-chain going back to the 1980's and have not see huge changes since then. I strongly advise against making changes unless you have good reason, because there are a number of tools that rely on M3CG (not just those in the public sources). >>>>>> >>>>>> I am going to do a pass to revert some of your changes, since they are causing a number of my systems to fail to build. (cf. Niagara on tinderbox). >>>>>> >>>>>> I strongly advise that you try to use a private branch when developing new functionality. We as a community can then go through a revision process to vet substantive changes before merging them into the trunk. >>>>>> >>>>>> - Tony >>>>>> >>>> >> > -------------- next part -------------- An HTML attachment was scrubbed... URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 495 bytes Desc: Message signed with OpenPGP using GPGMail URL: From dragisha at m3w.org Wed Sep 5 21:06:03 2012 From: dragisha at m3w.org (=?utf-8?Q?Dragi=C5=A1a_Duri=C4=87?=) Date: Wed, 5 Sep 2012 21:06:03 +0200 Subject: [M3devel] M3CG In-Reply-To: References: <47B9A237-FD0B-4E40-9F12-938BC3D00E9E@cs.purdue.edu>, , <62BAB949-DBD6-405D-A6E8-0F416DEB586B@gmail.com>, , , <3FC36B77-1F30-462C-9688-285D50351455@cs.purdue.edu>, , , , <228002BB-DE75-4320-A70F-CBB82A23D758@m3w.org>, , <87DABD01-259D-4373-8C77-9570869AF6FD@cs.purdue.edu>, , <71BE165D-B2DA-494D-9608-CCC581A32E4F@cs.purdue.edu>, Message-ID: <75BA621E-ED58-497C-93C9-1DE0B6DF7636@m3w.org> TEXT is pointer sized, so typeid is aligned to pointer boundary. As would be INTEGER or any other field you can put there. I don't think problem you are having with this is with "packed nature" od TypeUID. -- Divided by a common language Dragi?a Duri? dragisha at m3w.org On Sep 5, 2012, at 8:34 PM, Jay K wrote: > My code is/was something like: > > TYPE T1 = RECORD > text: TEXT; > typeid: TypeUID; > END; > > > and that errors on some platforms. > -------------- next part -------------- An HTML attachment was scrubbed... URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 495 bytes Desc: Message signed with OpenPGP using GPGMail URL: From dabenavidesd at yahoo.es Wed Sep 5 21:10:53 2012 From: dabenavidesd at yahoo.es (Daniel Alejandro Benavides D.) Date: Wed, 5 Sep 2012 20:10:53 +0100 (BST) Subject: [M3devel] M3CG In-Reply-To: Message-ID: <1346872253.12543.YahooMailClassic@web29706.mail.ird.yahoo.com> Hi all: in .lm3 files you could easily see that as well. But needs asking again HP about it and some work. Thanks in advance --- El mi?, 5/9/12, Jay K escribi?: De: Jay K Asunto: Re: [M3devel] M3CG Para: "Tony" CC: "m3devel" Fecha: mi?rcoles, 5 de septiembre, 2012 13:34 I should really insert padding manually? I don't know if I like that or not. ? My code is/was something like: ? TYPE T1 = RECORD? ??? text: TEXT;? ??? typeid: TypeUID;? ? END; ? and that errors on some platforms. ? I'm not using "Multipass" right now, but it does still hold possible value. We can remove multipass from m3makefile for nowif that helps. ? ? Given a similar problem in C, I would do something like: ? /* TypeUID must fit in 32 bits, for some reason.?*/ C_ASSERT(sizeof(TypeUID) <= sizeof(UINT32)); Where C_ASSERT is in windows.h and looks like: /* compile time assert */ ?#define C_ASSERT(expression) typedef char __cassert__[(expression) ? 1 : -1]; ?or somesuch. The error message isn't great when it fails. ? People also name this "static_assert". It is popular. ? ?It doesn't prohibit it from having padding around it,? but it does assert it fits in 32 bits. ?I recall we can do similar in Modula-3. ? TYPE assertTypeUIDFitsIn32Bits = ARRAY [0..ORD(BITSIZE(TypeUID) <= 32)] OF INTEGER; ? or to be more certain: ? TYPE assertTypeUIDFitsIn32Bits = ARRAY [0..-ORD(BITSIZE(TypeUID) <= 32)] OF INTEGER; I'm not sure 0..0 is illegal, but I think 0 .. 1 is. (I sure do miss macros...this is too much syntax for a compile time assert...) Can we just put <* ASSERT BITSIZE(TypeUID) <= 32 *> in the .i3 file? Or elsewhere? ? ?- Jay ? > From: hosking at cs.purdue.edu > Date: Wed, 5 Sep 2012 11:36:03 -0400 > To: jay.krell at cornell.edu > CC: m3devel at elegosoft.com > Subject: Re: [M3devel] M3CG > > As I recall you were having trouble with alignment, right? > > In which case, why not pad your record type out to a reasonably aligned value? As in: > > CONST PadRange = Word.LeftShift(1, BITSIZE(ADDRESS) - BITSIZE(TypeUID)) - 1; > RECORD > t: TypeUID; > pad: BITS BITSIZE(ADDRESS) - 32 FOR [0..PadRange]; > END; > > > > On Sep 5, 2012, at 11:18 AM, Antony Hosking wrote: > > > Remind me again why you can't use TypeUID as is? > > There is nothing in the language spec that prohibits packed types in records. > > > > On Sep 5, 2012, at 10:50 AM, Jay K wrote: > > > >> This seems quite wrong from a simple engineering/design/factoring/abstraction point of view. > >> > >> > >> Imagine I have a few of these things. They are subranges or enums. That fit in a smaller size. > >> Wouldn't it be nice, to just use the type directly and get the space savings? Opportunistically? > >> What if the type is a REAL or a LONGINT? > >> I want the type to be opaque/abstract where that is easy and cheap and this certainly seems like an easy/cheap place to have slightly valuable opacity. > >> Isn't it really good, more than "just nice" to let the type change and have a lot of code work just as well? > >> Because they didn't copy around knowledge of what the type is? > >> What if the type changes? > >> Anyone just copying it around by exact restated typename is unaffected. > >> Anyone who looked at and decided to restate the definition might type might be broken. > >> > >> > >> And again, really -- you want to sacrifice both performance and abstraction when both are easily kept better? > >> That is, I'm all for range checks to keep things "safe", safety is important, but in this case you can easily preserve safety w/o adding range checks. > >> > >> > >> We do have enums at this layer. > >> Would you suggest I take the ORD of all of those and store them in INTEGERs too? > >> > >> > >> I am really surprised. > >> > >> > >> - Jay > >> > >> > >> From: hosking at cs.purdue.edu > >> Date: Wed, 5 Sep 2012 10:33:58 -0400 > >> To: dragisha at m3w.org > >> CC: m3devel at elegosoft.com; jay.krell at cornell.edu > >> Subject: Re: [M3devel] M3CG > >> > >> Precisely. > >> > >> > >> On Sep 5, 2012, at 3:40 AM, Dragi?a Duri? wrote: > >> > >> Why holding/passing of this value in INTEGER would be a problem? As long as range checks are passed on "assignment boundaries", it is all well. > >> > >> It is how Modula-3 does things. > >> > >> -- > >> Divided by a common language > >> > >> Dragi?a Duri? > >> dragisha at m3w.org > >> > >> > >> > >> > >> On Sep 4, 2012, at 10:47 PM, Jay K wrote: > >> > >> RECORD HoldsTypeUID: > >> typeuid: [FIRST(TypeUID)..LAST(TypeUID)]; > >> END? > >> > >> > >> But what if I'm really just a holder/passer of this thing, > >> and I never interpret it. Now TypeUID can't be changed > >> to LONGREAL or somesuch. Ideally some code wouldn't care > >> and still be correct. > >> > >> > >> The idea is to hold the thing, pass it on, without knowing > >> what it is. I want a field with the same type. > >> > >> > >> Why does it matter if TypeUID is representable in 32 bits? > >> Isn't the range the interface? > >> If it wasn't for readability of all the F's, I think > >> TypeUID = [-16_7FFFFFFF - 1 .. 16_7FFFFFFF]; is best. > >> > >> > >> Do we really care about few or many bits that occupies? > >> > >> > >> Cstdint.int32_t I agree is a bit lazy. > >> Maybe something like Word.Shift(1, 31) .. Word.Not(Word.Shift(1, 31)) ? > >> A bit wordy but ok. > >> Maybe not correct. Not clear the start is negative. > >> Maybe needs to be more like: > >> > >> (-Word.Not(Word.Shift(1, 31))) - 1 .. Word.Not(Word.Shift(1, 31)) > >> > >> > >> But these bit twiddlings might then confuse people. > >> So maybe having to count F's is better.. :( > >> > >> > >> You know, what about being 32bits in size would be part of an interface? > >> I don't think much/anything, but maybe. > >> > >> > >> Do we do/allow things like bit operations on it? Index into it a certain number > >> of bits? Take the address and assume BYTESIZE == 4? > >> I could see those maybe occuring. Maybe. > >> > >> > >> But I'm pretty sure they values are fairly abstract/opaque and the best anyone can do > >> is format them as strings and compare them for e.g. sorting purposes, but must > >> assume they are fairly sparse. > >> > >> > >> Btw, whenever the matter of "portability to signed-magnitude" or one's complement > >> comes up, I admit I get a bit confused. Two's complement is very ingrained > >> in my world view. > >> > >> > >> I agree TInt.T suffices. > >> Just like CARDINAL isn't needed, INTEGER suffices. > >> Cardinal.T just disallows negative numbers earlier, or at lower level, etc. > >> If we had to use TInt.T and add checks in a few places that it >= 0, ok. > >> It seems a little nice to put the checking in. > >> > >> > >> - Jay > >> > >> > >> > >> > >> > Subject: Re: M3CG > >> > From: hosking at cs.purdue.edu > >> > Date: Tue, 4 Sep 2012 13:05:34 -0400 > >> > CC: m3devel at elegosoft.com > >> > To: jay.krell at cornell.edu > >> > > >> > On Sep 4, 2012, at 12:09 PM, Jay wrote: > >> > > >> > > "BITS" seems to not provide any useful value. It only makes it so you can't put the type into a portable unpacked record, which is what I was doing. I either have to pack my record somehow (counting target-dependent bits??) or lay out the fields carefully in some way that all targets allow. The problem was that some targets didn't like the layout. > >> > > >> > For M3CG.TypeUID the BITS 32 enforces that it is always representable in 32 bits. This is a fundamental invariant of the compiler and run-time system. Removing it might allow bug creep. You don't need to pack your record. You just need a field sufficiently large to hold the value of a type id. In this instance an INTEGER field would suffice, or you can use the same subrange. > >> > > >> > > Given the stated range, that you'll get enough bits to store it, what is the point in giving the size too? Isn't providing just the range and no particular size, sufficient & more abstract? Granted, I went the other way. > >> > > >> > Only if an implementation chooses to store a subrange in as few bits as necessary. Yes, CM3 does this, but it is not guaranteed by the language spec. Here the size is the critical invariant. > >> > > >> > > I don't remember but guessing: > >> > > > >> > > > >> > > Cardinal.T would be, like CARDINAL vs. INTEGER: only slightly subtley useful: same as TInt.T, but disallows negative numbers. > >> > > >> > But for what purpose. The target does not have CARDINAL. It only has a target integer. > >> > > >> > > Most likely I ran into places where a host integer/cardinal did not necessarily suffice, and so a target type was called for. > >> > > > >> > > > >> > > I know we have places that need to use target types but don't yet. Specifically for the sizes of things like records & arrays. Otherwise we have hacks where 64bit systems declare 32bit limits. > >> > > >> > Again, TInt.T suffices for all of these. > >> > > >> > > > >> > > > >> > > - Jay (briefly/pocket-sized-computer-aka-phone) > >> > > > >> > > On Sep 4, 2012, at 7:11 AM, Antony Hosking wrote: > >> > > > >> > >> Jay, > >> > >> > >> > >> I've been looking over some of your changes to M3CG interfaces. You'll notice that I removed your import of Cstdlib.int into M3CG_Ops.i3. It does not belong there. The type as declared: > >> > >> > >> > >> TypeUID = BITS 32 FOR [-16_7fffffff-1 .. 16_7fffffff]; > >> > >> > >> > >> is correct as is. It is a 32 bit value that encodes a particular subrange, REGARDLESS of target machine. It is improper to change that definition to rely on some C type. > >> > >> > >> > >> I also have some other questions. Why did you add the type Cardinal.T? This seems entirely unnecessary, since targets don't have a Cardinal type. The only type they have is a target integer. All other Modula-3 ordinal types should be simulated in the compiler using TInt.T. I would advise that it be removed. Also, I don't understand why you changed descriptions of the primitive types to use this Cardinal.T instead of the original CARDINAL to hold information about the bit size, alignment, and byte size. There is no situation in which a host will need to emulate the behavior of CARDINAL for these values (all can be represented using CARDINAL no matter what the host). > >> > >> > >> > >> I am concerned that these changes reflect a desire on your part to change the world to fit your specific needs (whether justified or not). The interfaces defined in M3CG were carefully designed and inherit from a long code-chain going back to the 1980's and have not see huge changes since then. I strongly advise against making changes unless you have good reason, because there are a number of tools that rely on M3CG (not just those in the public sources). > >> > >> > >> > >> I am going to do a pass to revert some of your changes, since they are causing a number of my systems to fail to build. (cf. Niagara on tinderbox). > >> > >> > >> > >> I strongly advise that you try to use a private branch when developing new functionality. We as a community can then go through a revision process to vet substantive changes before merging them into the trunk. > >> > >> > >> > >> - Tony > >> > >> > >> > > > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From hosking at cs.purdue.edu Wed Sep 5 22:41:43 2012 From: hosking at cs.purdue.edu (Antony Hosking) Date: Wed, 5 Sep 2012 16:41:43 -0400 Subject: [M3devel] M3CG In-Reply-To: References: <47B9A237-FD0B-4E40-9F12-938BC3D00E9E@cs.purdue.edu>, , <62BAB949-DBD6-405D-A6E8-0F416DEB586B@gmail.com>, , , <3FC36B77-1F30-462C-9688-285D50351455@cs.purdue.edu>, , , , <228002BB-DE75-4320-A70F-CBB82A23D758@m3w.org>, , <87DABD01-259D-4373-8C77-9570869AF6FD@cs.purdue.edu>, , <71BE165D-B2DA-494D-9608-CCC581A32E4F@cs.purdue.edu>, Message-ID: Jay, why don?t you just us a local subrange for your fields in the records and then simply assign to/from TypeUID values? RECORD typeid: [-16_7fffffff-1 .. 16_7fffffff] END; You won?t pay any penalty for range checks since the subranges are exactly the same. On Sep 5, 2012, at 2:34 PM, Jay K wrote: > I should really insert padding manually? > I don't know if I like that or not. > > > My code is/was something like: > > TYPE T1 = RECORD > text: TEXT; > typeid: TypeUID; > END; > > > and that errors on some platforms. > > > I'm not using "Multipass" right now, but it does still hold possible value. > We can remove multipass from m3makefile for nowif that helps. > > > Given a similar problem in C, I would do something like: > > /* TypeUID must fit in 32 bits, for some reason. */ > C_ASSERT(sizeof(TypeUID) <= sizeof(UINT32)); > Where C_ASSERT is in windows.h and looks like: > /* compile time assert */ > #define C_ASSERT(expression) typedef char __cassert__[(expression) ? 1 : -1]; > or somesuch. The error message isn't great when it fails. > > People also name this "static_assert". It is popular. > > It doesn't prohibit it from having padding around it, but it does assert it fits in 32 bits. > > I recall we can do similar in Modula-3. > > TYPE assertTypeUIDFitsIn32Bits = ARRAY [0..ORD(BITSIZE(TypeUID) <= 32)] OF INTEGER; > or to be more certain: > TYPE assertTypeUIDFitsIn32Bits = ARRAY [0..-ORD(BITSIZE(TypeUID) <= 32)] OF INTEGER; > > I'm not sure 0..0 is illegal, but I think 0 .. 1 is. > > (I sure do miss macros...this is too much syntax for a compile time assert...) > > Can we just put <* ASSERT BITSIZE(TypeUID) <= 32 *> in the .i3 file? Or elsewhere? > > > - Jay > > > From: hosking at cs.purdue.edu > > Date: Wed, 5 Sep 2012 11:36:03 -0400 > > To: jay.krell at cornell.edu > > CC: m3devel at elegosoft.com > > Subject: Re: [M3devel] M3CG > > > > As I recall you were having trouble with alignment, right? > > > > In which case, why not pad your record type out to a reasonably aligned value? As in: > > > > CONST PadRange = Word.LeftShift(1, BITSIZE(ADDRESS) - BITSIZE(TypeUID)) - 1; > > RECORD > > t: TypeUID; > > pad: BITS BITSIZE(ADDRESS) - 32 FOR [0..PadRange]; > > END; > > > > > > > > On Sep 5, 2012, at 11:18 AM, Antony Hosking wrote: > > > > > Remind me again why you can't use TypeUID as is? > > > There is nothing in the language spec that prohibits packed types in records. > > > > > > On Sep 5, 2012, at 10:50 AM, Jay K wrote: > > > > > >> This seems quite wrong from a simple engineering/design/factoring/abstraction point of view. > > >> > > >> > > >> Imagine I have a few of these things. They are subranges or enums. That fit in a smaller size. > > >> Wouldn't it be nice, to just use the type directly and get the space savings? Opportunistically? > > >> What if the type is a REAL or a LONGINT? > > >> I want the type to be opaque/abstract where that is easy and cheap and this certainly seems like an easy/cheap place to have slightly valuable opacity. > > >> Isn't it really good, more than "just nice" to let the type change and have a lot of code work just as well? > > >> Because they didn't copy around knowledge of what the type is? > > >> What if the type changes? > > >> Anyone just copying it around by exact restated typename is unaffected. > > >> Anyone who looked at and decided to restate the definition might type might be broken. > > >> > > >> > > >> And again, really -- you want to sacrifice both performance and abstraction when both are easily kept better? > > >> That is, I'm all for range checks to keep things "safe", safety is important, but in this case you can easily preserve safety w/o adding range checks. > > >> > > >> > > >> We do have enums at this layer. > > >> Would you suggest I take the ORD of all of those and store them in INTEGERs too? > > >> > > >> > > >> I am really surprised. > > >> > > >> > > >> - Jay > > >> > > >> > > >> From: hosking at cs.purdue.edu > > >> Date: Wed, 5 Sep 2012 10:33:58 -0400 > > >> To: dragisha at m3w.org > > >> CC: m3devel at elegosoft.com; jay.krell at cornell.edu > > >> Subject: Re: [M3devel] M3CG > > >> > > >> Precisely. > > >> > > >> > > >> On Sep 5, 2012, at 3:40 AM, Dragi?a Duri? wrote: > > >> > > >> Why holding/passing of this value in INTEGER would be a problem? As long as range checks are passed on "assignment boundaries", it is all well. > > >> > > >> It is how Modula-3 does things. > > >> > > >> -- > > >> Divided by a common language > > >> > > >> Dragi?a Duri? > > >> dragisha at m3w.org > > >> > > >> > > >> > > >> > > >> On Sep 4, 2012, at 10:47 PM, Jay K wrote: > > >> > > >> RECORD HoldsTypeUID: > > >> typeuid: [FIRST(TypeUID)..LAST(TypeUID)]; > > >> END? > > >> > > >> > > >> But what if I'm really just a holder/passer of this thing, > > >> and I never interpret it. Now TypeUID can't be changed > > >> to LONGREAL or somesuch. Ideally some code wouldn't care > > >> and still be correct. > > >> > > >> > > >> The idea is to hold the thing, pass it on, without knowing > > >> what it is. I want a field with the same type. > > >> > > >> > > >> Why does it matter if TypeUID is representable in 32 bits? > > >> Isn't the range the interface? > > >> If it wasn't for readability of all the F's, I think > > >> TypeUID = [-16_7FFFFFFF - 1 .. 16_7FFFFFFF]; is best. > > >> > > >> > > >> Do we really care about few or many bits that occupies? > > >> > > >> > > >> Cstdint.int32_t I agree is a bit lazy. > > >> Maybe something like Word.Shift(1, 31) .. Word.Not(Word.Shift(1, 31)) ? > > >> A bit wordy but ok. > > >> Maybe not correct. Not clear the start is negative. > > >> Maybe needs to be more like: > > >> > > >> (-Word.Not(Word.Shift(1, 31))) - 1 .. Word.Not(Word.Shift(1, 31)) > > >> > > >> > > >> But these bit twiddlings might then confuse people. > > >> So maybe having to count F's is better.. :( > > >> > > >> > > >> You know, what about being 32bits in size would be part of an interface? > > >> I don't think much/anything, but maybe. > > >> > > >> > > >> Do we do/allow things like bit operations on it? Index into it a certain number > > >> of bits? Take the address and assume BYTESIZE == 4? > > >> I could see those maybe occuring. Maybe. > > >> > > >> > > >> But I'm pretty sure they values are fairly abstract/opaque and the best anyone can do > > >> is format them as strings and compare them for e.g. sorting purposes, but must > > >> assume they are fairly sparse. > > >> > > >> > > >> Btw, whenever the matter of "portability to signed-magnitude" or one's complement > > >> comes up, I admit I get a bit confused. Two's complement is very ingrained > > >> in my world view. > > >> > > >> > > >> I agree TInt.T suffices. > > >> Just like CARDINAL isn't needed, INTEGER suffices. > > >> Cardinal.T just disallows negative numbers earlier, or at lower level, etc. > > >> If we had to use TInt.T and add checks in a few places that it >= 0, ok. > > >> It seems a little nice to put the checking in. > > >> > > >> > > >> - Jay > > >> > > >> > > >> > > >> > > >> > Subject: Re: M3CG > > >> > From: hosking at cs.purdue.edu > > >> > Date: Tue, 4 Sep 2012 13:05:34 -0400 > > >> > CC: m3devel at elegosoft.com > > >> > To: jay.krell at cornell.edu > > >> > > > >> > On Sep 4, 2012, at 12:09 PM, Jay wrote: > > >> > > > >> > > "BITS" seems to not provide any useful value. It only makes it so you can't put the type into a portable unpacked record, which is what I was doing. I either have to pack my record somehow (counting target-dependent bits??) or lay out the fields carefully in some way that all targets allow. The problem was that some targets didn't like the layout. > > >> > > > >> > For M3CG.TypeUID the BITS 32 enforces that it is always representable in 32 bits. This is a fundamental invariant of the compiler and run-time system. Removing it might allow bug creep. You don't need to pack your record. You just need a field sufficiently large to hold the value of a type id. In this instance an INTEGER field would suffice, or you can use the same subrange. > > >> > > > >> > > Given the stated range, that you'll get enough bits to store it, what is the point in giving the size too? Isn't providing just the range and no particular size, sufficient & more abstract? Granted, I went the other way. > > >> > > > >> > Only if an implementation chooses to store a subrange in as few bits as necessary. Yes, CM3 does this, but it is not guaranteed by the language spec. Here the size is the critical invariant. > > >> > > > >> > > I don't remember but guessing: > > >> > > > > >> > > > > >> > > Cardinal.T would be, like CARDINAL vs. INTEGER: only slightly subtley useful: same as TInt.T, but disallows negative numbers. > > >> > > > >> > But for what purpose. The target does not have CARDINAL. It only has a target integer. > > >> > > > >> > > Most likely I ran into places where a host integer/cardinal did not necessarily suffice, and so a target type was called for. > > >> > > > > >> > > > > >> > > I know we have places that need to use target types but don't yet. Specifically for the sizes of things like records & arrays. Otherwise we have hacks where 64bit systems declare 32bit limits. > > >> > > > >> > Again, TInt.T suffices for all of these. > > >> > > > >> > > > > >> > > > > >> > > - Jay (briefly/pocket-sized-computer-aka-phone) > > >> > > > > >> > > On Sep 4, 2012, at 7:11 AM, Antony Hosking wrote: > > >> > > > > >> > >> Jay, > > >> > >> > > >> > >> I've been looking over some of your changes to M3CG interfaces. You'll notice that I removed your import of Cstdlib.int into M3CG_Ops.i3. It does not belong there. The type as declared: > > >> > >> > > >> > >> TypeUID = BITS 32 FOR [-16_7fffffff-1 .. 16_7fffffff]; > > >> > >> > > >> > >> is correct as is. It is a 32 bit value that encodes a particular subrange, REGARDLESS of target machine. It is improper to change that definition to rely on some C type. > > >> > >> > > >> > >> I also have some other questions. Why did you add the type Cardinal.T? This seems entirely unnecessary, since targets don't have a Cardinal type. The only type they have is a target integer. All other Modula-3 ordinal types should be simulated in the compiler using TInt.T. I would advise that it be removed. Also, I don't understand why you changed descriptions of the primitive types to use this Cardinal.T instead of the original CARDINAL to hold information about the bit size, alignment, and byte size. There is no situation in which a host will need to emulate the behavior of CARDINAL for these values (all can be represented using CARDINAL no matter what the host). > > >> > >> > > >> > >> I am concerned that these changes reflect a desire on your part to change the world to fit your specific needs (whether justified or not). The interfaces defined in M3CG were carefully designed and inherit from a long code-chain going back to the 1980's and have not see huge changes since then. I strongly advise against making changes unless you have good reason, because there are a number of tools that rely on M3CG (not just those in the public sources). > > >> > >> > > >> > >> I am going to do a pass to revert some of your changes, since they are causing a number of my systems to fail to build. (cf. Niagara on tinderbox). > > >> > >> > > >> > >> I strongly advise that you try to use a private branch when developing new functionality. We as a community can then go through a revision process to vet substantive changes before merging them into the trunk. > > >> > >> > > >> > >> - Tony > > >> > >> > > >> > > > > > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From dragisha at m3w.org Wed Sep 5 23:22:13 2012 From: dragisha at m3w.org (=?utf-8?Q?Dragi=C5=A1a_Duri=C4=87?=) Date: Wed, 5 Sep 2012 23:22:13 +0200 Subject: [M3devel] M3CG In-Reply-To: References: <47B9A237-FD0B-4E40-9F12-938BC3D00E9E@cs.purdue.edu>, , <62BAB949-DBD6-405D-A6E8-0F416DEB586B@gmail.com>, , , <3FC36B77-1F30-462C-9688-285D50351455@cs.purdue.edu>, , , , <228002BB-DE75-4320-A70F-CBB82A23D758@m3w.org>, , <87DABD01-259D-4373-8C77-9570869AF6FD@cs.purdue.edu>, , <71BE165D-B2DA-494D-9608-CCC581A32E4F@cs.purdue.edu>, Message-ID: Why not? -- Divided by a common language Dragi?a Duri? dragisha at m3w.org On Sep 5, 2012, at 8:34 PM, Jay K wrote: > Can we just put <* ASSERT BITSIZE(TypeUID) <= 32 *> in the .i3 file? Or elsewhere? > -------------- next part -------------- An HTML attachment was scrubbed... URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 495 bytes Desc: Message signed with OpenPGP using GPGMail URL: From dabenavidesd at yahoo.es Thu Sep 6 01:10:52 2012 From: dabenavidesd at yahoo.es (Daniel Alejandro Benavides D.) Date: Thu, 6 Sep 2012 00:10:52 +0100 (BST) Subject: [M3devel] M3CG In-Reply-To: Message-ID: <1346886652.18210.YahooMailClassic@web29701.mail.ird.yahoo.com> Hi all: you can't check any expression in an INTERFACE, because it'd be illegal syntax. You can check do so in a Larch /Modula-3 actually. Thanks in advance ? --- El mi?, 5/9/12, Dragi?a Duri? escribi?: De: Dragi?a Duri? Asunto: Re: [M3devel] M3CG Para: "Jay K" CC: "m3devel" Fecha: mi?rcoles, 5 de septiembre, 2012 16:22 Why not? --Divided by a common language Dragi?a Duri?dragisha at m3w.org On Sep 5, 2012, at 8:34 PM, Jay K wrote: Can we just put <* ASSERT BITSIZE(TypeUID) <= 32 *> in the .i3 file? Or elsewhere? ? -------------- next part -------------- An HTML attachment was scrubbed... URL: From jay.krell at cornell.edu Thu Sep 6 02:37:04 2012 From: jay.krell at cornell.edu (Jay) Date: Wed, 5 Sep 2012 17:37:04 -0700 Subject: [M3devel] M3CG In-Reply-To: <75BA621E-ED58-497C-93C9-1DE0B6DF7636@m3w.org> References: <47B9A237-FD0B-4E40-9F12-938BC3D00E9E@cs.purdue.edu> <62BAB949-DBD6-405D-A6E8-0F416DEB586B@gmail.com> <3FC36B77-1F30-462C-9688-285D50351455@cs.purdue.edu> <228002BB-DE75-4320-A70F-CBB82A23D758@m3w.org> <87DABD01-259D-4373-8C77-9570869AF6FD@cs.purdue.edu> <71BE165D-B2DA-494D-9608-CCC581A32E4F@cs.purdue.edu> <75BA621E-ED58-497C-93C9-1DE0B6DF7636@m3w.org> Message-ID: <66CA9F64-96B9-443B-A5C9-BDF08649057C@gmail.com> > I don't think problem you are having with this is with "packed nature" od TypeUID It totally was. Fix was removing "BITS 32" from TypeUID. - Jay (briefly/pocket-sized-computer-aka-phone) On Sep 5, 2012, at 12:06 PM, Dragi?a Duri? wrote: > I don't think problem you are having with this is with "packed nature" od TypeUID -------------- next part -------------- An HTML attachment was scrubbed... URL: From jay.krell at cornell.edu Thu Sep 6 02:52:54 2012 From: jay.krell at cornell.edu (Jay) Date: Wed, 5 Sep 2012 17:52:54 -0700 Subject: [M3devel] M3CG In-Reply-To: References: <47B9A237-FD0B-4E40-9F12-938BC3D00E9E@cs.purdue.edu> <62BAB949-DBD6-405D-A6E8-0F416DEB586B@gmail.com> <3FC36B77-1F30-462C-9688-285D50351455@cs.purdue.edu> <228002BB-DE75-4320-A70F-CBB82A23D758@m3w.org> <87DABD01-259D-4373-8C77-9570869AF6FD@cs.purdue.edu> <71BE165D-B2DA-494D-9608-CCC581A32E4F@cs.purdue.edu> Message-ID: I'll try it. It satisfies me: if it is even needed. Tony? - Jay (briefly/pocket-sized-computer-aka-phone) On Sep 5, 2012, at 2:22 PM, Dragi?a Duri? wrote: > Why not? > -- > Divided by a common language > > Dragi?a Duri? > dragisha at m3w.org > > > > > On Sep 5, 2012, at 8:34 PM, Jay K wrote: > >> Can we just put <* ASSERT BITSIZE(TypeUID) <= 32 *> in the .i3 file? Or elsewhere? >> > -------------- next part -------------- An HTML attachment was scrubbed... URL: From jay.krell at cornell.edu Thu Sep 6 02:56:39 2012 From: jay.krell at cornell.edu (Jay) Date: Wed, 5 Sep 2012 17:56:39 -0700 Subject: [M3devel] M3CG In-Reply-To: References: <47B9A237-FD0B-4E40-9F12-938BC3D00E9E@cs.purdue.edu> <62BAB949-DBD6-405D-A6E8-0F416DEB586B@gmail.com> <3FC36B77-1F30-462C-9688-285D50351455@cs.purdue.edu> <228002BB-DE75-4320-A70F-CBB82A23D758@m3w.org> <87DABD01-259D-4373-8C77-9570869AF6FD@cs.purdue.edu> <71BE165D-B2DA-494D-9608-CCC581A32E4F@cs.purdue.edu> Message-ID: <38AA75B5-97B7-4D45-8B7D-45F88ED28D25@gmail.com> And if TypeUID changes? I want to store a TypeUID. I want to treat it opaquely/abstractly. It can change & I'd still store it correctly & efficiently. I should not go looking at it & cloning it. That seems like sound engineering. ? - Jay (briefly/pocket-sized-computer-aka-phone) On Sep 5, 2012, at 1:41 PM, Antony Hosking wrote: > Jay, why don?t you just us a local subrange for your fields in the records and then simply assign to/from TypeUID values? > > RECORD typeid: [-16_7fffffff-1 .. 16_7fffffff] END; > > You won?t pay any penalty for range checks since the subranges are exactly the same. > > On Sep 5, 2012, at 2:34 PM, Jay K wrote: > >> I should really insert padding manually? >> I don't know if I like that or not. >> >> >> My code is/was something like: >> >> TYPE T1 = RECORD >> text: TEXT; >> typeid: TypeUID; >> END; >> >> >> and that errors on some platforms. >> >> >> I'm not using "Multipass" right now, but it does still hold possible value. >> We can remove multipass from m3makefile for nowif that helps. >> >> >> Given a similar problem in C, I would do something like: >> >> /* TypeUID must fit in 32 bits, for some reason. */ >> C_ASSERT(sizeof(TypeUID) <= sizeof(UINT32)); >> Where C_ASSERT is in windows.h and looks like: >> /* compile time assert */ >> #define C_ASSERT(expression) typedef char __cassert__[(expression) ? 1 : -1]; >> or somesuch. The error message isn't great when it fails. >> >> People also name this "static_assert". It is popular. >> >> It doesn't prohibit it from having padding around it, but it does assert it fits in 32 bits. >> >> I recall we can do similar in Modula-3. >> >> TYPE assertTypeUIDFitsIn32Bits = ARRAY [0..ORD(BITSIZE(TypeUID) <= 32)] OF INTEGER; >> or to be more certain: >> TYPE assertTypeUIDFitsIn32Bits = ARRAY [0..-ORD(BITSIZE(TypeUID) <= 32)] OF INTEGER; >> >> I'm not sure 0..0 is illegal, but I think 0 .. 1 is. >> >> (I sure do miss macros...this is too much syntax for a compile time assert...) >> >> Can we just put <* ASSERT BITSIZE(TypeUID) <= 32 *> in the .i3 file? Or elsewhere? >> >> >> - Jay >> >> > From: hosking at cs.purdue.edu >> > Date: Wed, 5 Sep 2012 11:36:03 -0400 >> > To: jay.krell at cornell.edu >> > CC: m3devel at elegosoft.com >> > Subject: Re: [M3devel] M3CG >> > >> > As I recall you were having trouble with alignment, right? >> > >> > In which case, why not pad your record type out to a reasonably aligned value? As in: >> > >> > CONST PadRange = Word.LeftShift(1, BITSIZE(ADDRESS) - BITSIZE(TypeUID)) - 1; >> > RECORD >> > t: TypeUID; >> > pad: BITS BITSIZE(ADDRESS) - 32 FOR [0..PadRange]; >> > END; >> > >> > >> > >> > On Sep 5, 2012, at 11:18 AM, Antony Hosking wrote: >> > >> > > Remind me again why you can't use TypeUID as is? >> > > There is nothing in the language spec that prohibits packed types in records. >> > > >> > > On Sep 5, 2012, at 10:50 AM, Jay K wrote: >> > > >> > >> This seems quite wrong from a simple engineering/design/factoring/abstraction point of view. >> > >> >> > >> >> > >> Imagine I have a few of these things. They are subranges or enums. That fit in a smaller size. >> > >> Wouldn't it be nice, to just use the type directly and get the space savings? Opportunistically? >> > >> What if the type is a REAL or a LONGINT? >> > >> I want the type to be opaque/abstract where that is easy and cheap and this certainly seems like an easy/cheap place to have slightly valuable opacity. >> > >> Isn't it really good, more than "just nice" to let the type change and have a lot of code work just as well? >> > >> Because they didn't copy around knowledge of what the type is? >> > >> What if the type changes? >> > >> Anyone just copying it around by exact restated typename is unaffected. >> > >> Anyone who looked at and decided to restate the definition might type might be broken. >> > >> >> > >> >> > >> And again, really -- you want to sacrifice both performance and abstraction when both are easily kept better? >> > >> That is, I'm all for range checks to keep things "safe", safety is important, but in this case you can easily preserve safety w/o adding range checks. >> > >> >> > >> >> > >> We do have enums at this layer. >> > >> Would you suggest I take the ORD of all of those and store them in INTEGERs too? >> > >> >> > >> >> > >> I am really surprised. >> > >> >> > >> >> > >> - Jay >> > >> >> > >> >> > >> From: hosking at cs.purdue.edu >> > >> Date: Wed, 5 Sep 2012 10:33:58 -0400 >> > >> To: dragisha at m3w.org >> > >> CC: m3devel at elegosoft.com; jay.krell at cornell.edu >> > >> Subject: Re: [M3devel] M3CG >> > >> >> > >> Precisely. >> > >> >> > >> >> > >> On Sep 5, 2012, at 3:40 AM, Dragi?a Duri? wrote: >> > >> >> > >> Why holding/passing of this value in INTEGER would be a problem? As long as range checks are passed on "assignment boundaries", it is all well. >> > >> >> > >> It is how Modula-3 does things. >> > >> >> > >> -- >> > >> Divided by a common language >> > >> >> > >> Dragi?a Duri? >> > >> dragisha at m3w.org >> > >> >> > >> >> > >> >> > >> >> > >> On Sep 4, 2012, at 10:47 PM, Jay K wrote: >> > >> >> > >> RECORD HoldsTypeUID: >> > >> typeuid: [FIRST(TypeUID)..LAST(TypeUID)]; >> > >> END? >> > >> >> > >> >> > >> But what if I'm really just a holder/passer of this thing, >> > >> and I never interpret it. Now TypeUID can't be changed >> > >> to LONGREAL or somesuch. Ideally some code wouldn't care >> > >> and still be correct. >> > >> >> > >> >> > >> The idea is to hold the thing, pass it on, without knowing >> > >> what it is. I want a field with the same type. >> > >> >> > >> >> > >> Why does it matter if TypeUID is representable in 32 bits? >> > >> Isn't the range the interface? >> > >> If it wasn't for readability of all the F's, I think >> > >> TypeUID = [-16_7FFFFFFF - 1 .. 16_7FFFFFFF]; is best. >> > >> >> > >> >> > >> Do we really care about few or many bits that occupies? >> > >> >> > >> >> > >> Cstdint.int32_t I agree is a bit lazy. >> > >> Maybe something like Word.Shift(1, 31) .. Word.Not(Word.Shift(1, 31)) ? >> > >> A bit wordy but ok. >> > >> Maybe not correct. Not clear the start is negative. >> > >> Maybe needs to be more like: >> > >> >> > >> (-Word.Not(Word.Shift(1, 31))) - 1 .. Word.Not(Word.Shift(1, 31)) >> > >> >> > >> >> > >> But these bit twiddlings might then confuse people. >> > >> So maybe having to count F's is better.. :( >> > >> >> > >> >> > >> You know, what about being 32bits in size would be part of an interface? >> > >> I don't think much/anything, but maybe. >> > >> >> > >> >> > >> Do we do/allow things like bit operations on it? Index into it a certain number >> > >> of bits? Take the address and assume BYTESIZE == 4? >> > >> I could see those maybe occuring. Maybe. >> > >> >> > >> >> > >> But I'm pretty sure they values are fairly abstract/opaque and the best anyone can do >> > >> is format them as strings and compare them for e.g. sorting purposes, but must >> > >> assume they are fairly sparse. >> > >> >> > >> >> > >> Btw, whenever the matter of "portability to signed-magnitude" or one's complement >> > >> comes up, I admit I get a bit confused. Two's complement is very ingrained >> > >> in my world view. >> > >> >> > >> >> > >> I agree TInt.T suffices. >> > >> Just like CARDINAL isn't needed, INTEGER suffices. >> > >> Cardinal.T just disallows negative numbers earlier, or at lower level, etc. >> > >> If we had to use TInt.T and add checks in a few places that it >= 0, ok. >> > >> It seems a little nice to put the checking in. >> > >> >> > >> >> > >> - Jay >> > >> >> > >> >> > >> >> > >> >> > >> > Subject: Re: M3CG >> > >> > From: hosking at cs.purdue.edu >> > >> > Date: Tue, 4 Sep 2012 13:05:34 -0400 >> > >> > CC: m3devel at elegosoft.com >> > >> > To: jay.krell at cornell.edu >> > >> > >> > >> > On Sep 4, 2012, at 12:09 PM, Jay wrote: >> > >> > >> > >> > > "BITS" seems to not provide any useful value. It only makes it so you can't put the type into a portable unpacked record, which is what I was doing. I either have to pack my record somehow (counting target-dependent bits??) or lay out the fields carefully in some way that all targets allow. The problem was that some targets didn't like the layout. >> > >> > >> > >> > For M3CG.TypeUID the BITS 32 enforces that it is always representable in 32 bits. This is a fundamental invariant of the compiler and run-time system. Removing it might allow bug creep. You don't need to pack your record. You just need a field sufficiently large to hold the value of a type id. In this instance an INTEGER field would suffice, or you can use the same subrange. >> > >> > >> > >> > > Given the stated range, that you'll get enough bits to store it, what is the point in giving the size too? Isn't providing just the range and no particular size, sufficient & more abstract? Granted, I went the other way. >> > >> > >> > >> > Only if an implementation chooses to store a subrange in as few bits as necessary. Yes, CM3 does this, but it is not guaranteed by the language spec. Here the size is the critical invariant. >> > >> > >> > >> > > I don't remember but guessing: >> > >> > > >> > >> > > >> > >> > > Cardinal.T would be, like CARDINAL vs. INTEGER: only slightly subtley useful: same as TInt.T, but disallows negative numbers. >> > >> > >> > >> > But for what purpose. The target does not have CARDINAL. It only has a target integer. >> > >> > >> > >> > > Most likely I ran into places where a host integer/cardinal did not necessarily suffice, and so a target type was called for. >> > >> > > >> > >> > > >> > >> > > I know we have places that need to use target types but don't yet. Specifically for the sizes of things like records & arrays. Otherwise we have hacks where 64bit systems declare 32bit limits. >> > >> > >> > >> > Again, TInt.T suffices for all of these. >> > >> > >> > >> > > >> > >> > > >> > >> > > - Jay (briefly/pocket-sized-computer-aka-phone) >> > >> > > >> > >> > > On Sep 4, 2012, at 7:11 AM, Antony Hosking wrote: >> > >> > > >> > >> > >> Jay, >> > >> > >> >> > >> > >> I've been looking over some of your changes to M3CG interfaces. You'll notice that I removed your import of Cstdlib.int into M3CG_Ops.i3. It does not belong there. The type as declared: >> > >> > >> >> > >> > >> TypeUID = BITS 32 FOR [-16_7fffffff-1 .. 16_7fffffff]; >> > >> > >> >> > >> > >> is correct as is. It is a 32 bit value that encodes a particular subrange, REGARDLESS of target machine. It is improper to change that definition to rely on some C type. >> > >> > >> >> > >> > >> I also have some other questions. Why did you add the type Cardinal.T? This seems entirely unnecessary, since targets don't have a Cardinal type. The only type they have is a target integer. All other Modula-3 ordinal types should be simulated in the compiler using TInt.T. I would advise that it be removed. Also, I don't understand why you changed descriptions of the primitive types to use this Cardinal.T instead of the original CARDINAL to hold information about the bit size, alignment, and byte size. There is no situation in which a host will need to emulate the behavior of CARDINAL for these values (all can be represented using CARDINAL no matter what the host). >> > >> > >> >> > >> > >> I am concerned that these changes reflect a desire on your part to change the world to fit your specific needs (whether justified or not). The interfaces defined in M3CG were carefully designed and inherit from a long code-chain going back to the 1980's and have not see huge changes since then. I strongly advise against making changes unless you have good reason, because there are a number of tools that rely on M3CG (not just those in the public sources). >> > >> > >> >> > >> > >> I am going to do a pass to revert some of your changes, since they are causing a number of my systems to fail to build. (cf. Niagara on tinderbox). >> > >> > >> >> > >> > >> I strongly advise that you try to use a private branch when developing new functionality. We as a community can then go through a revision process to vet substantive changes before merging them into the trunk. >> > >> > >> >> > >> > >> - Tony >> > >> > >> >> > >> > >> > > >> > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From hosking at cs.purdue.edu Thu Sep 6 04:06:36 2012 From: hosking at cs.purdue.edu (Antony Hosking) Date: Wed, 5 Sep 2012 22:06:36 -0400 Subject: [M3devel] M3CG In-Reply-To: <38AA75B5-97B7-4D45-8B7D-45F88ED28D25@gmail.com> References: <47B9A237-FD0B-4E40-9F12-938BC3D00E9E@cs.purdue.edu> <62BAB949-DBD6-405D-A6E8-0F416DEB586B@gmail.com> <3FC36B77-1F30-462C-9688-285D50351455@cs.purdue.edu> <228002BB-DE75-4320-A70F-CBB82A23D758@m3w.org> <87DABD01-259D-4373-8C77-9570869AF6FD@cs.purdue.edu> <71BE165D-B2DA-494D-9608-CCC581A32E4F@cs.purdue.edu> <38AA75B5-97B7-4D45-8B7D-45F88ED28D25@gmail.com> Message-ID: Jay, I just checked in the following to M3CG.i3: TYPE Int32 = [-16_7fffffff-1 .. 16_7fffffff]; TypeUID = BITS 32 FOR Int32; Feel free to use M3CG.Int32. At least this way, if anything changes TypeUID it will be clear that someone might be relying on TypeUID. Antony Hosking | Associate Professor | Computer Science | Purdue University 305 N. University Street | West Lafayette | IN 47907 | USA Mobile +1 765 427 5484 On Sep 5, 2012, at 8:56 PM, Jay wrote: > And if TypeUID changes? > > I want to store a TypeUID. I want to treat it opaquely/abstractly. It can change & I'd still store it correctly & efficiently. I should not go looking at it & cloning it. That seems like sound engineering. ? > > - Jay (briefly/pocket-sized-computer-aka-phone) > > On Sep 5, 2012, at 1:41 PM, Antony Hosking wrote: > >> Jay, why don?t you just us a local subrange for your fields in the records and then simply assign to/from TypeUID values? >> >> RECORD typeid: [-16_7fffffff-1 .. 16_7fffffff] END; >> >> You won?t pay any penalty for range checks since the subranges are exactly the same. >> >> On Sep 5, 2012, at 2:34 PM, Jay K wrote: >> >>> I should really insert padding manually? >>> I don't know if I like that or not. >>> >>> >>> My code is/was something like: >>> >>> TYPE T1 = RECORD >>> text: TEXT; >>> typeid: TypeUID; >>> END; >>> >>> >>> and that errors on some platforms. >>> >>> >>> I'm not using "Multipass" right now, but it does still hold possible value. >>> We can remove multipass from m3makefile for nowif that helps. >>> >>> >>> Given a similar problem in C, I would do something like: >>> >>> /* TypeUID must fit in 32 bits, for some reason. */ >>> C_ASSERT(sizeof(TypeUID) <= sizeof(UINT32)); >>> Where C_ASSERT is in windows.h and looks like: >>> /* compile time assert */ >>> #define C_ASSERT(expression) typedef char __cassert__[(expression) ? 1 : -1]; >>> or somesuch. The error message isn't great when it fails. >>> >>> People also name this "static_assert". It is popular. >>> >>> It doesn't prohibit it from having padding around it, but it does assert it fits in 32 bits. >>> >>> I recall we can do similar in Modula-3. >>> >>> TYPE assertTypeUIDFitsIn32Bits = ARRAY [0..ORD(BITSIZE(TypeUID) <= 32)] OF INTEGER; >>> or to be more certain: >>> TYPE assertTypeUIDFitsIn32Bits = ARRAY [0..-ORD(BITSIZE(TypeUID) <= 32)] OF INTEGER; >>> >>> I'm not sure 0..0 is illegal, but I think 0 .. 1 is. >>> >>> (I sure do miss macros...this is too much syntax for a compile time assert...) >>> >>> Can we just put <* ASSERT BITSIZE(TypeUID) <= 32 *> in the .i3 file? Or elsewhere? >>> >>> >>> - Jay >>> >>> > From: hosking at cs.purdue.edu >>> > Date: Wed, 5 Sep 2012 11:36:03 -0400 >>> > To: jay.krell at cornell.edu >>> > CC: m3devel at elegosoft.com >>> > Subject: Re: [M3devel] M3CG >>> > >>> > As I recall you were having trouble with alignment, right? >>> > >>> > In which case, why not pad your record type out to a reasonably aligned value? As in: >>> > >>> > CONST PadRange = Word.LeftShift(1, BITSIZE(ADDRESS) - BITSIZE(TypeUID)) - 1; >>> > RECORD >>> > t: TypeUID; >>> > pad: BITS BITSIZE(ADDRESS) - 32 FOR [0..PadRange]; >>> > END; >>> > >>> > >>> > >>> > On Sep 5, 2012, at 11:18 AM, Antony Hosking wrote: >>> > >>> > > Remind me again why you can't use TypeUID as is? >>> > > There is nothing in the language spec that prohibits packed types in records. >>> > > >>> > > On Sep 5, 2012, at 10:50 AM, Jay K wrote: >>> > > >>> > >> This seems quite wrong from a simple engineering/design/factoring/abstraction point of view. >>> > >> >>> > >> >>> > >> Imagine I have a few of these things. They are subranges or enums. That fit in a smaller size. >>> > >> Wouldn't it be nice, to just use the type directly and get the space savings? Opportunistically? >>> > >> What if the type is a REAL or a LONGINT? >>> > >> I want the type to be opaque/abstract where that is easy and cheap and this certainly seems like an easy/cheap place to have slightly valuable opacity. >>> > >> Isn't it really good, more than "just nice" to let the type change and have a lot of code work just as well? >>> > >> Because they didn't copy around knowledge of what the type is? >>> > >> What if the type changes? >>> > >> Anyone just copying it around by exact restated typename is unaffected. >>> > >> Anyone who looked at and decided to restate the definition might type might be broken. >>> > >> >>> > >> >>> > >> And again, really -- you want to sacrifice both performance and abstraction when both are easily kept better? >>> > >> That is, I'm all for range checks to keep things "safe", safety is important, but in this case you can easily preserve safety w/o adding range checks. >>> > >> >>> > >> >>> > >> We do have enums at this layer. >>> > >> Would you suggest I take the ORD of all of those and store them in INTEGERs too? >>> > >> >>> > >> >>> > >> I am really surprised. >>> > >> >>> > >> >>> > >> - Jay >>> > >> >>> > >> >>> > >> From: hosking at cs.purdue.edu >>> > >> Date: Wed, 5 Sep 2012 10:33:58 -0400 >>> > >> To: dragisha at m3w.org >>> > >> CC: m3devel at elegosoft.com; jay.krell at cornell.edu >>> > >> Subject: Re: [M3devel] M3CG >>> > >> >>> > >> Precisely. >>> > >> >>> > >> >>> > >> On Sep 5, 2012, at 3:40 AM, Dragi?a Duri? wrote: >>> > >> >>> > >> Why holding/passing of this value in INTEGER would be a problem? As long as range checks are passed on "assignment boundaries", it is all well. >>> > >> >>> > >> It is how Modula-3 does things. >>> > >> >>> > >> -- >>> > >> Divided by a common language >>> > >> >>> > >> Dragi?a Duri? >>> > >> dragisha at m3w.org >>> > >> >>> > >> >>> > >> >>> > >> >>> > >> On Sep 4, 2012, at 10:47 PM, Jay K wrote: >>> > >> >>> > >> RECORD HoldsTypeUID: >>> > >> typeuid: [FIRST(TypeUID)..LAST(TypeUID)]; >>> > >> END? >>> > >> >>> > >> >>> > >> But what if I'm really just a holder/passer of this thing, >>> > >> and I never interpret it. Now TypeUID can't be changed >>> > >> to LONGREAL or somesuch. Ideally some code wouldn't care >>> > >> and still be correct. >>> > >> >>> > >> >>> > >> The idea is to hold the thing, pass it on, without knowing >>> > >> what it is. I want a field with the same type. >>> > >> >>> > >> >>> > >> Why does it matter if TypeUID is representable in 32 bits? >>> > >> Isn't the range the interface? >>> > >> If it wasn't for readability of all the F's, I think >>> > >> TypeUID = [-16_7FFFFFFF - 1 .. 16_7FFFFFFF]; is best. >>> > >> >>> > >> >>> > >> Do we really care about few or many bits that occupies? >>> > >> >>> > >> >>> > >> Cstdint.int32_t I agree is a bit lazy. >>> > >> Maybe something like Word.Shift(1, 31) .. Word.Not(Word.Shift(1, 31)) ? >>> > >> A bit wordy but ok. >>> > >> Maybe not correct. Not clear the start is negative. >>> > >> Maybe needs to be more like: >>> > >> >>> > >> (-Word.Not(Word.Shift(1, 31))) - 1 .. Word.Not(Word.Shift(1, 31)) >>> > >> >>> > >> >>> > >> But these bit twiddlings might then confuse people. >>> > >> So maybe having to count F's is better.. :( >>> > >> >>> > >> >>> > >> You know, what about being 32bits in size would be part of an interface? >>> > >> I don't think much/anything, but maybe. >>> > >> >>> > >> >>> > >> Do we do/allow things like bit operations on it? Index into it a certain number >>> > >> of bits? Take the address and assume BYTESIZE == 4? >>> > >> I could see those maybe occuring. Maybe. >>> > >> >>> > >> >>> > >> But I'm pretty sure they values are fairly abstract/opaque and the best anyone can do >>> > >> is format them as strings and compare them for e.g. sorting purposes, but must >>> > >> assume they are fairly sparse. >>> > >> >>> > >> >>> > >> Btw, whenever the matter of "portability to signed-magnitude" or one's complement >>> > >> comes up, I admit I get a bit confused. Two's complement is very ingrained >>> > >> in my world view. >>> > >> >>> > >> >>> > >> I agree TInt.T suffices. >>> > >> Just like CARDINAL isn't needed, INTEGER suffices. >>> > >> Cardinal.T just disallows negative numbers earlier, or at lower level, etc. >>> > >> If we had to use TInt.T and add checks in a few places that it >= 0, ok. >>> > >> It seems a little nice to put the checking in. >>> > >> >>> > >> >>> > >> - Jay >>> > >> >>> > >> >>> > >> >>> > >> >>> > >> > Subject: Re: M3CG >>> > >> > From: hosking at cs.purdue.edu >>> > >> > Date: Tue, 4 Sep 2012 13:05:34 -0400 >>> > >> > CC: m3devel at elegosoft.com >>> > >> > To: jay.krell at cornell.edu >>> > >> > >>> > >> > On Sep 4, 2012, at 12:09 PM, Jay wrote: >>> > >> > >>> > >> > > "BITS" seems to not provide any useful value. It only makes it so you can't put the type into a portable unpacked record, which is what I was doing. I either have to pack my record somehow (counting target-dependent bits??) or lay out the fields carefully in some way that all targets allow. The problem was that some targets didn't like the layout. >>> > >> > >>> > >> > For M3CG.TypeUID the BITS 32 enforces that it is always representable in 32 bits. This is a fundamental invariant of the compiler and run-time system. Removing it might allow bug creep. You don't need to pack your record. You just need a field sufficiently large to hold the value of a type id. In this instance an INTEGER field would suffice, or you can use the same subrange. >>> > >> > >>> > >> > > Given the stated range, that you'll get enough bits to store it, what is the point in giving the size too? Isn't providing just the range and no particular size, sufficient & more abstract? Granted, I went the other way. >>> > >> > >>> > >> > Only if an implementation chooses to store a subrange in as few bits as necessary. Yes, CM3 does this, but it is not guaranteed by the language spec. Here the size is the critical invariant. >>> > >> > >>> > >> > > I don't remember but guessing: >>> > >> > > >>> > >> > > >>> > >> > > Cardinal.T would be, like CARDINAL vs. INTEGER: only slightly subtley useful: same as TInt.T, but disallows negative numbers. >>> > >> > >>> > >> > But for what purpose. The target does not have CARDINAL. It only has a target integer. >>> > >> > >>> > >> > > Most likely I ran into places where a host integer/cardinal did not necessarily suffice, and so a target type was called for. >>> > >> > > >>> > >> > > >>> > >> > > I know we have places that need to use target types but don't yet. Specifically for the sizes of things like records & arrays. Otherwise we have hacks where 64bit systems declare 32bit limits. >>> > >> > >>> > >> > Again, TInt.T suffices for all of these. >>> > >> > >>> > >> > > >>> > >> > > >>> > >> > > - Jay (briefly/pocket-sized-computer-aka-phone) >>> > >> > > >>> > >> > > On Sep 4, 2012, at 7:11 AM, Antony Hosking wrote: >>> > >> > > >>> > >> > >> Jay, >>> > >> > >> >>> > >> > >> I've been looking over some of your changes to M3CG interfaces. You'll notice that I removed your import of Cstdlib.int into M3CG_Ops.i3. It does not belong there. The type as declared: >>> > >> > >> >>> > >> > >> TypeUID = BITS 32 FOR [-16_7fffffff-1 .. 16_7fffffff]; >>> > >> > >> >>> > >> > >> is correct as is. It is a 32 bit value that encodes a particular subrange, REGARDLESS of target machine. It is improper to change that definition to rely on some C type. >>> > >> > >> >>> > >> > >> I also have some other questions. Why did you add the type Cardinal.T? This seems entirely unnecessary, since targets don't have a Cardinal type. The only type they have is a target integer. All other Modula-3 ordinal types should be simulated in the compiler using TInt.T. I would advise that it be removed. Also, I don't understand why you changed descriptions of the primitive types to use this Cardinal.T instead of the original CARDINAL to hold information about the bit size, alignment, and byte size. There is no situation in which a host will need to emulate the behavior of CARDINAL for these values (all can be represented using CARDINAL no matter what the host). >>> > >> > >> >>> > >> > >> I am concerned that these changes reflect a desire on your part to change the world to fit your specific needs (whether justified or not). The interfaces defined in M3CG were carefully designed and inherit from a long code-chain going back to the 1980's and have not see huge changes since then. I strongly advise against making changes unless you have good reason, because there are a number of tools that rely on M3CG (not just those in the public sources). >>> > >> > >> >>> > >> > >> I am going to do a pass to revert some of your changes, since they are causing a number of my systems to fail to build. (cf. Niagara on tinderbox). >>> > >> > >> >>> > >> > >> I strongly advise that you try to use a private branch when developing new functionality. We as a community can then go through a revision process to vet substantive changes before merging them into the trunk. >>> > >> > >> >>> > >> > >> - Tony >>> > >> > >> >>> > >> > >>> > > >>> > >> -------------- next part -------------- An HTML attachment was scrubbed... URL: From hosking at cs.purdue.edu Thu Sep 6 04:07:24 2012 From: hosking at cs.purdue.edu (Antony Hosking) Date: Wed, 5 Sep 2012 22:07:24 -0400 Subject: [M3devel] M3CG In-Reply-To: References: <47B9A237-FD0B-4E40-9F12-938BC3D00E9E@cs.purdue.edu> <62BAB949-DBD6-405D-A6E8-0F416DEB586B@gmail.com> <3FC36B77-1F30-462C-9688-285D50351455@cs.purdue.edu> <228002BB-DE75-4320-A70F-CBB82A23D758@m3w.org> <87DABD01-259D-4373-8C77-9570869AF6FD@cs.purdue.edu> <71BE165D-B2DA-494D-9608-CCC581A32E4F@cs.purdue.edu> <38AA75B5-97B7-4D45-8B7D-45F88ED28D25@gmail.com> Message-ID: On Sep 5, 2012, at 10:06 PM, Antony Hosking wrote: > Jay, I just checked in the following to M3CG.i3: > > TYPE > Int32 = [-16_7fffffff-1 .. 16_7fffffff]; > TypeUID = BITS 32 FOR Int32; > > Feel free to use M3CG.Int32. > At least this way, if anything changes TypeUID it will be clear that someone might be relying on TypeUID. I meant Int32. > > > Antony Hosking | Associate Professor | Computer Science | Purdue University > 305 N. University Street | West Lafayette | IN 47907 | USA > Mobile +1 765 427 5484 > > > > > > On Sep 5, 2012, at 8:56 PM, Jay wrote: > >> And if TypeUID changes? >> >> I want to store a TypeUID. I want to treat it opaquely/abstractly. It can change & I'd still store it correctly & efficiently. I should not go looking at it & cloning it. That seems like sound engineering. ? >> >> - Jay (briefly/pocket-sized-computer-aka-phone) >> >> On Sep 5, 2012, at 1:41 PM, Antony Hosking wrote: >> >>> Jay, why don?t you just us a local subrange for your fields in the records and then simply assign to/from TypeUID values? >>> >>> RECORD typeid: [-16_7fffffff-1 .. 16_7fffffff] END; >>> >>> You won?t pay any penalty for range checks since the subranges are exactly the same. >>> >>> On Sep 5, 2012, at 2:34 PM, Jay K wrote: >>> >>>> I should really insert padding manually? >>>> I don't know if I like that or not. >>>> >>>> >>>> My code is/was something like: >>>> >>>> TYPE T1 = RECORD >>>> text: TEXT; >>>> typeid: TypeUID; >>>> END; >>>> >>>> >>>> and that errors on some platforms. >>>> >>>> >>>> I'm not using "Multipass" right now, but it does still hold possible value. >>>> We can remove multipass from m3makefile for nowif that helps. >>>> >>>> >>>> Given a similar problem in C, I would do something like: >>>> >>>> /* TypeUID must fit in 32 bits, for some reason. */ >>>> C_ASSERT(sizeof(TypeUID) <= sizeof(UINT32)); >>>> Where C_ASSERT is in windows.h and looks like: >>>> /* compile time assert */ >>>> #define C_ASSERT(expression) typedef char __cassert__[(expression) ? 1 : -1]; >>>> or somesuch. The error message isn't great when it fails. >>>> >>>> People also name this "static_assert". It is popular. >>>> >>>> It doesn't prohibit it from having padding around it, but it does assert it fits in 32 bits. >>>> >>>> I recall we can do similar in Modula-3. >>>> >>>> TYPE assertTypeUIDFitsIn32Bits = ARRAY [0..ORD(BITSIZE(TypeUID) <= 32)] OF INTEGER; >>>> or to be more certain: >>>> TYPE assertTypeUIDFitsIn32Bits = ARRAY [0..-ORD(BITSIZE(TypeUID) <= 32)] OF INTEGER; >>>> >>>> I'm not sure 0..0 is illegal, but I think 0 .. 1 is. >>>> >>>> (I sure do miss macros...this is too much syntax for a compile time assert...) >>>> >>>> Can we just put <* ASSERT BITSIZE(TypeUID) <= 32 *> in the .i3 file? Or elsewhere? >>>> >>>> >>>> - Jay >>>> >>>> > From: hosking at cs.purdue.edu >>>> > Date: Wed, 5 Sep 2012 11:36:03 -0400 >>>> > To: jay.krell at cornell.edu >>>> > CC: m3devel at elegosoft.com >>>> > Subject: Re: [M3devel] M3CG >>>> > >>>> > As I recall you were having trouble with alignment, right? >>>> > >>>> > In which case, why not pad your record type out to a reasonably aligned value? As in: >>>> > >>>> > CONST PadRange = Word.LeftShift(1, BITSIZE(ADDRESS) - BITSIZE(TypeUID)) - 1; >>>> > RECORD >>>> > t: TypeUID; >>>> > pad: BITS BITSIZE(ADDRESS) - 32 FOR [0..PadRange]; >>>> > END; >>>> > >>>> > >>>> > >>>> > On Sep 5, 2012, at 11:18 AM, Antony Hosking wrote: >>>> > >>>> > > Remind me again why you can't use TypeUID as is? >>>> > > There is nothing in the language spec that prohibits packed types in records. >>>> > > >>>> > > On Sep 5, 2012, at 10:50 AM, Jay K wrote: >>>> > > >>>> > >> This seems quite wrong from a simple engineering/design/factoring/abstraction point of view. >>>> > >> >>>> > >> >>>> > >> Imagine I have a few of these things. They are subranges or enums. That fit in a smaller size. >>>> > >> Wouldn't it be nice, to just use the type directly and get the space savings? Opportunistically? >>>> > >> What if the type is a REAL or a LONGINT? >>>> > >> I want the type to be opaque/abstract where that is easy and cheap and this certainly seems like an easy/cheap place to have slightly valuable opacity. >>>> > >> Isn't it really good, more than "just nice" to let the type change and have a lot of code work just as well? >>>> > >> Because they didn't copy around knowledge of what the type is? >>>> > >> What if the type changes? >>>> > >> Anyone just copying it around by exact restated typename is unaffected. >>>> > >> Anyone who looked at and decided to restate the definition might type might be broken. >>>> > >> >>>> > >> >>>> > >> And again, really -- you want to sacrifice both performance and abstraction when both are easily kept better? >>>> > >> That is, I'm all for range checks to keep things "safe", safety is important, but in this case you can easily preserve safety w/o adding range checks. >>>> > >> >>>> > >> >>>> > >> We do have enums at this layer. >>>> > >> Would you suggest I take the ORD of all of those and store them in INTEGERs too? >>>> > >> >>>> > >> >>>> > >> I am really surprised. >>>> > >> >>>> > >> >>>> > >> - Jay >>>> > >> >>>> > >> >>>> > >> From: hosking at cs.purdue.edu >>>> > >> Date: Wed, 5 Sep 2012 10:33:58 -0400 >>>> > >> To: dragisha at m3w.org >>>> > >> CC: m3devel at elegosoft.com; jay.krell at cornell.edu >>>> > >> Subject: Re: [M3devel] M3CG >>>> > >> >>>> > >> Precisely. >>>> > >> >>>> > >> >>>> > >> On Sep 5, 2012, at 3:40 AM, Dragi?a Duri? wrote: >>>> > >> >>>> > >> Why holding/passing of this value in INTEGER would be a problem? As long as range checks are passed on "assignment boundaries", it is all well. >>>> > >> >>>> > >> It is how Modula-3 does things. >>>> > >> >>>> > >> -- >>>> > >> Divided by a common language >>>> > >> >>>> > >> Dragi?a Duri? >>>> > >> dragisha at m3w.org >>>> > >> >>>> > >> >>>> > >> >>>> > >> >>>> > >> On Sep 4, 2012, at 10:47 PM, Jay K wrote: >>>> > >> >>>> > >> RECORD HoldsTypeUID: >>>> > >> typeuid: [FIRST(TypeUID)..LAST(TypeUID)]; >>>> > >> END? >>>> > >> >>>> > >> >>>> > >> But what if I'm really just a holder/passer of this thing, >>>> > >> and I never interpret it. Now TypeUID can't be changed >>>> > >> to LONGREAL or somesuch. Ideally some code wouldn't care >>>> > >> and still be correct. >>>> > >> >>>> > >> >>>> > >> The idea is to hold the thing, pass it on, without knowing >>>> > >> what it is. I want a field with the same type. >>>> > >> >>>> > >> >>>> > >> Why does it matter if TypeUID is representable in 32 bits? >>>> > >> Isn't the range the interface? >>>> > >> If it wasn't for readability of all the F's, I think >>>> > >> TypeUID = [-16_7FFFFFFF - 1 .. 16_7FFFFFFF]; is best. >>>> > >> >>>> > >> >>>> > >> Do we really care about few or many bits that occupies? >>>> > >> >>>> > >> >>>> > >> Cstdint.int32_t I agree is a bit lazy. >>>> > >> Maybe something like Word.Shift(1, 31) .. Word.Not(Word.Shift(1, 31)) ? >>>> > >> A bit wordy but ok. >>>> > >> Maybe not correct. Not clear the start is negative. >>>> > >> Maybe needs to be more like: >>>> > >> >>>> > >> (-Word.Not(Word.Shift(1, 31))) - 1 .. Word.Not(Word.Shift(1, 31)) >>>> > >> >>>> > >> >>>> > >> But these bit twiddlings might then confuse people. >>>> > >> So maybe having to count F's is better.. :( >>>> > >> >>>> > >> >>>> > >> You know, what about being 32bits in size would be part of an interface? >>>> > >> I don't think much/anything, but maybe. >>>> > >> >>>> > >> >>>> > >> Do we do/allow things like bit operations on it? Index into it a certain number >>>> > >> of bits? Take the address and assume BYTESIZE == 4? >>>> > >> I could see those maybe occuring. Maybe. >>>> > >> >>>> > >> >>>> > >> But I'm pretty sure they values are fairly abstract/opaque and the best anyone can do >>>> > >> is format them as strings and compare them for e.g. sorting purposes, but must >>>> > >> assume they are fairly sparse. >>>> > >> >>>> > >> >>>> > >> Btw, whenever the matter of "portability to signed-magnitude" or one's complement >>>> > >> comes up, I admit I get a bit confused. Two's complement is very ingrained >>>> > >> in my world view. >>>> > >> >>>> > >> >>>> > >> I agree TInt.T suffices. >>>> > >> Just like CARDINAL isn't needed, INTEGER suffices. >>>> > >> Cardinal.T just disallows negative numbers earlier, or at lower level, etc. >>>> > >> If we had to use TInt.T and add checks in a few places that it >= 0, ok. >>>> > >> It seems a little nice to put the checking in. >>>> > >> >>>> > >> >>>> > >> - Jay >>>> > >> >>>> > >> >>>> > >> >>>> > >> >>>> > >> > Subject: Re: M3CG >>>> > >> > From: hosking at cs.purdue.edu >>>> > >> > Date: Tue, 4 Sep 2012 13:05:34 -0400 >>>> > >> > CC: m3devel at elegosoft.com >>>> > >> > To: jay.krell at cornell.edu >>>> > >> > >>>> > >> > On Sep 4, 2012, at 12:09 PM, Jay wrote: >>>> > >> > >>>> > >> > > "BITS" seems to not provide any useful value. It only makes it so you can't put the type into a portable unpacked record, which is what I was doing. I either have to pack my record somehow (counting target-dependent bits??) or lay out the fields carefully in some way that all targets allow. The problem was that some targets didn't like the layout. >>>> > >> > >>>> > >> > For M3CG.TypeUID the BITS 32 enforces that it is always representable in 32 bits. This is a fundamental invariant of the compiler and run-time system. Removing it might allow bug creep. You don't need to pack your record. You just need a field sufficiently large to hold the value of a type id. In this instance an INTEGER field would suffice, or you can use the same subrange. >>>> > >> > >>>> > >> > > Given the stated range, that you'll get enough bits to store it, what is the point in giving the size too? Isn't providing just the range and no particular size, sufficient & more abstract? Granted, I went the other way. >>>> > >> > >>>> > >> > Only if an implementation chooses to store a subrange in as few bits as necessary. Yes, CM3 does this, but it is not guaranteed by the language spec. Here the size is the critical invariant. >>>> > >> > >>>> > >> > > I don't remember but guessing: >>>> > >> > > >>>> > >> > > >>>> > >> > > Cardinal.T would be, like CARDINAL vs. INTEGER: only slightly subtley useful: same as TInt.T, but disallows negative numbers. >>>> > >> > >>>> > >> > But for what purpose. The target does not have CARDINAL. It only has a target integer. >>>> > >> > >>>> > >> > > Most likely I ran into places where a host integer/cardinal did not necessarily suffice, and so a target type was called for. >>>> > >> > > >>>> > >> > > >>>> > >> > > I know we have places that need to use target types but don't yet. Specifically for the sizes of things like records & arrays. Otherwise we have hacks where 64bit systems declare 32bit limits. >>>> > >> > >>>> > >> > Again, TInt.T suffices for all of these. >>>> > >> > >>>> > >> > > >>>> > >> > > >>>> > >> > > - Jay (briefly/pocket-sized-computer-aka-phone) >>>> > >> > > >>>> > >> > > On Sep 4, 2012, at 7:11 AM, Antony Hosking wrote: >>>> > >> > > >>>> > >> > >> Jay, >>>> > >> > >> >>>> > >> > >> I've been looking over some of your changes to M3CG interfaces. You'll notice that I removed your import of Cstdlib.int into M3CG_Ops.i3. It does not belong there. The type as declared: >>>> > >> > >> >>>> > >> > >> TypeUID = BITS 32 FOR [-16_7fffffff-1 .. 16_7fffffff]; >>>> > >> > >> >>>> > >> > >> is correct as is. It is a 32 bit value that encodes a particular subrange, REGARDLESS of target machine. It is improper to change that definition to rely on some C type. >>>> > >> > >> >>>> > >> > >> I also have some other questions. Why did you add the type Cardinal.T? This seems entirely unnecessary, since targets don't have a Cardinal type. The only type they have is a target integer. All other Modula-3 ordinal types should be simulated in the compiler using TInt.T. I would advise that it be removed. Also, I don't understand why you changed descriptions of the primitive types to use this Cardinal.T instead of the original CARDINAL to hold information about the bit size, alignment, and byte size. There is no situation in which a host will need to emulate the behavior of CARDINAL for these values (all can be represented using CARDINAL no matter what the host). >>>> > >> > >> >>>> > >> > >> I am concerned that these changes reflect a desire on your part to change the world to fit your specific needs (whether justified or not). The interfaces defined in M3CG were carefully designed and inherit from a long code-chain going back to the 1980's and have not see huge changes since then. I strongly advise against making changes unless you have good reason, because there are a number of tools that rely on M3CG (not just those in the public sources). >>>> > >> > >> >>>> > >> > >> I am going to do a pass to revert some of your changes, since they are causing a number of my systems to fail to build. (cf. Niagara on tinderbox). >>>> > >> > >> >>>> > >> > >> I strongly advise that you try to use a private branch when developing new functionality. We as a community can then go through a revision process to vet substantive changes before merging them into the trunk. >>>> > >> > >> >>>> > >> > >> - Tony >>>> > >> > >> >>>> > >> > >>>> > > >>>> > >>> > -------------- next part -------------- An HTML attachment was scrubbed... URL: From jay.krell at cornell.edu Thu Sep 6 10:13:40 2012 From: jay.krell at cornell.edu (Jay K) Date: Thu, 6 Sep 2012 08:13:40 +0000 Subject: [M3devel] M3CG In-Reply-To: References: <47B9A237-FD0B-4E40-9F12-938BC3D00E9E@cs.purdue.edu> <62BAB949-DBD6-405D-A6E8-0F416DEB586B@gmail.com> <3FC36B77-1F30-462C-9688-285D50351455@cs.purdue.edu> <228002BB-DE75-4320-A70F-CBB82A23D758@m3w.org> <87DABD01-259D-4373-8C77-9570869AF6FD@cs.purdue.edu> <71BE165D-B2DA-494D-9608-CCC581A32E4F@cs.purdue.edu> <38AA75B5-97B7-4D45-8B7D-45F88ED28D25@gmail.com> , Message-ID: I'm really confused but the approach and mentality here.I believe I understand that this is not C or C++ and that thereare things to be gained from that. First, let me restate the "less important" questions.The questions I care less about. What is the interface or abstract contractual properties of TypeUID?It is exactly 32 bits in size? I doubt it, but it could be. At least 32 bits in size? Well, that is kind of unavoidable, assuming a binary computer, a computer that actually uses bits. No more than 32 bits in size? It can store the subrange -16_7FFFFFF - 1 .. 16_7FFFFFF? That seems to me to be "part of" the interface, and possibly the entire interface. Assuming a computing device that uses "bits", that does imply at least 32 bits. It actually conceivably does not rule out requiring 33 bits, as signed-magnitude requires 33 bits to represent -16_7FFFFFF - 1. I'm willing to believe we are not portable beyond two's complement systems. And where are these properties assumed and violating them wouldcause problems? parse.c says:/*------------------------------------------------------------- type uids ---*//* Modula-3 type uids are unsigned 32-bit values. They are passed as signed decimal integers in the intermediate code, but converted to 6-byte, base 62 strings of characters from here to the debugger. To avoid surprises downstream, these generated strings are legal C identifiers. */ #define UID_SIZE 6#define NO_UID (0xFFFFFFFFUL) (Notice this does NOT agree with TypeUID -- it says they are unsigned.But the subrange includes negative numbers. I should check this andthe history...) I'm hoping we delete parse.c within a year, but that's another matter.The C-generating backend is coming along nicely. So there is a dependency that they be representable within 6 base-62digits. Which I believe actually allows for a larger range, at leastslightly. Ok, as I said, this isn't critical.I'm willing to believe it must fit in 32 bits.I'm skeptical that it must not include extra padding bits within a struct (whichis what the historical definition is). Now, let's move on to my very very simple desireto store these things in records, and pass them on toother M3CG.T implementations. Hypothetical dumb code, that should be simple and work.Yes, I know this is dumb, but it demonstrates the point. TYPE T1 = RECORD text: TEXT; type: TypeUID END; M3CG.T cg1, cg2; PROCEDURE declare_whatevere(text: TEXT; type: TypeUID)VAR t1: T1;BEGIN t1.text := text; t1.type := type; cg1.declare_whatever(t1.text, t1.type); cg2.declare_whatever(t1.text, t1.type);END declare_whatevere; It should be that easy, right?Surely this is reasonable? TypeUID could be INTEGER, a subrange, an enum, REAL, BOOLEANREFANY, UNTRACED REF of anything, it could be a RECORDwith arbitrary fields. This would work.It doesn't care about packing or padding.It doesn't assume TypeUID is a subrange and declare the similar: TYPE T1 = RECORD text: TEXT; type: FIRST(TypeUID) ... LAST(TypeUID) END; If TypeUID changes to one of several other kinds of things,it continues to work and be correct. Granted, if TypeUID became some sort of "OBJECT", maybe withsome sort of "copy" or "clone" METHOD, then maybe this becomes wrong.(This is an area where C++ is very interesting -- user defined typescan behave like values and be copied around correctly w/o regardto the concrete implementation/representation; it is up to the typeimplementer to make it work if he deems it. But I digress.) Now I see a few unavoidable options. 1) TypeUID can be any size. TypeUID = [-16_7FFFFFF - 1 .. 16_7FFFFFFF]; 2) TypeUID must fit in 32 bits, but padding can be insertedbefore/after it: TypeUID = [-16_7FFFFFF - 1 .. 16_7FFFFFFF];<* ASSERT BITSIZE(TypeUID) >= 32 *> That is essentially what I did, but without the assertion.Cstdint.int32_t is just a lazy way of stating the same thing.Granted, with an apparent interest in the size.But, again, that might be an over specification. 3) We are super afraid of making any changes and TypeUIDreally cannot change at all, but it is reasonbleto allow new code like I showed. UnpackedTypeUID = [-16_7FFFFFF - 1 .. 16_7FFFFFFF]; (* for new code to use *)TypeUID = BITS 32 FOR TypeUID; (* extreme compatibility *) I really don't think "Int32" is the way.It doesn't belong here. Public in M3CG/Target.It is not what I should store in a record to hold a TypeUID. Again, imagine TypeUID is opaque/abstract to me.I just need to copy it around and pass it on to other M3CG implementations.It could chane to REAL for all I care.I don't want to be referencing some very concrete/transparent "Int32",when I'm not doing anything that depends on that implementation detail. I even question somewhat the subrange. In the future 32 bit hosts and targets will disappear.We will have only 64bit and 128bit. What should TypeUID be in that world? Is the point really that it be an "INTEGER" that "fits"on any host or target? Now, I grant... I might need to convert a TypeUID to a string.Here we are faced with a recurring dilemna.Either TypeUID is a thick/complete abtraction, and we providecommon operations:INTERFACE TypeUID; (* declared here for performance; actually abstract; * use only with functions in this interface *)TYPE T = [-16_7FFFFFF - 1 .. 16_7FFFFFFF]; PROCEDURE Compare(a,b:T): [-1..1]; (* like for qsort *)PROCEDURE Equal(a,b:T): BOOLEAN;PROCEDURE ToText(a:T): TEXT;PROCEDURE Copy(from:T; VAR to:T);PROCEDURE Init(VAR a:T);PROCEDURE New():T; END TypeUID; MODULE TypeUID; (* for now, just an integer *) PROCEDURE Compare(a,b:T): [-1..1] (* like for qsort *)BEGIN (* DO NOT USE SUBTRACTION HERE. *) IF a < b THEN RETURN -1; END; ELSIF a > b THEN RETURN 1; END; ELSE RETURN 0; END;END Compare; PROCEDURE Equal(a,b:T): BOOLEAN =BEGIN RETURN a = b;END Equal; PROCEDURE ToText(a:T): TEXTBEGIN return Fmt.Int(a);END ToText; PROCEDURE Copy(from:T; VAR to:T) =BEGIN to := from;END Copy; PROCEDURE Init(VAR a:T);BEGIN a := 0;END Init; PROCEDURE New():T;BEGIN RETURN 0;END New; END TypeUID; OR TypeUID is very transparent, everyone knows it is an integerand everyone just does integer "operations" on it.And it probably can never change.But hopefully they never get added. Note of course that the abstract variation isn't very goodat protecting the abstration. It is probably desirable to be able to say: INTERFACE TYPE T; (* fully opaque *) MODULE REVEAL T = INTEGER; I understand this is hard to do efficiently.You either need a really good "cross-module compiler",or you need to heap allocate them all.A simple compiler that produces efficient code motivatesrevealing the type in public.That is unfortunate.For example, adding TypeUIDs is probably nonsenseand worth prohibiting. But by publically revealingit is an INTEGER (essentially), extra unintended operationsare allowed on it. (C++ solves... since you can have a class that is small,and the clients know the size, and allocate room for it,yet all the data members could be private. The languageis complicated, but the goal of allowing powerful efficient userdefined types is a good one, and achieved very well) - Jay Subject: Re: [M3devel] M3CG From: hosking at cs.purdue.edu Date: Wed, 5 Sep 2012 22:07:24 -0400 CC: m3devel at elegosoft.com To: jay.krell at cornell.edu On Sep 5, 2012, at 10:06 PM, Antony Hosking wrote:Jay, I just checked in the following to M3CG.i3: TYPE Int32 = [-16_7fffffff-1 .. 16_7fffffff]; TypeUID = BITS 32 FOR Int32; Feel free to use M3CG.Int32.At least this way, if anything changes TypeUID it will be clear that someone might be relying on TypeUID. I meant Int32. Antony Hosking | Associate Professor | Computer Science | Purdue University305 N. University Street | West Lafayette | IN 47907 | USAMobile +1 765 427 5484 On Sep 5, 2012, at 8:56 PM, Jay wrote:And if TypeUID changes? I want to store a TypeUID. I want to treat it opaquely/abstractly. It can change & I'd still store it correctly & efficiently. I should not go looking at it & cloning it. That seems like sound engineering. ? - Jay (briefly/pocket-sized-computer-aka-phone) On Sep 5, 2012, at 1:41 PM, Antony Hosking wrote: Jay, why don't you just us a local subrange for your fields in the records and then simply assign to/from TypeUID values? RECORD typeid: [-16_7fffffff-1 .. 16_7fffffff] END; You won't pay any penalty for range checks since the subranges are exactly the same. On Sep 5, 2012, at 2:34 PM, Jay K wrote:I should really insert padding manually? I don't know if I like that or not. My code is/was something like: TYPE T1 = RECORD text: TEXT; typeid: TypeUID; END; and that errors on some platforms. I'm not using "Multipass" right now, but it does still hold possible value. We can remove multipass from m3makefile for nowif that helps. Given a similar problem in C, I would do something like: /* TypeUID must fit in 32 bits, for some reason. */ C_ASSERT(sizeof(TypeUID) <= sizeof(UINT32)); Where C_ASSERT is in windows.h and looks like: /* compile time assert */ #define C_ASSERT(expression) typedef char __cassert__[(expression) ? 1 : -1]; or somesuch. The error message isn't great when it fails. People also name this "static_assert". It is popular. It doesn't prohibit it from having padding around it, but it does assert it fits in 32 bits. I recall we can do similar in Modula-3. TYPE assertTypeUIDFitsIn32Bits = ARRAY [0..ORD(BITSIZE(TypeUID) <= 32)] OF INTEGER; or to be more certain: TYPE assertTypeUIDFitsIn32Bits = ARRAY [0..-ORD(BITSIZE(TypeUID) <= 32)] OF INTEGER; I'm not sure 0..0 is illegal, but I think 0 .. 1 is. (I sure do miss macros...this is too much syntax for a compile time assert...) Can we just put <* ASSERT BITSIZE(TypeUID) <= 32 *> in the .i3 file? Or elsewhere? - Jay > From: hosking at cs.purdue.edu > Date: Wed, 5 Sep 2012 11:36:03 -0400 > To: jay.krell at cornell.edu > CC: m3devel at elegosoft.com > Subject: Re: [M3devel] M3CG > > As I recall you were having trouble with alignment, right? > > In which case, why not pad your record type out to a reasonably aligned value? As in: > > CONST PadRange = Word.LeftShift(1, BITSIZE(ADDRESS) - BITSIZE(TypeUID)) - 1; > RECORD > t: TypeUID; > pad: BITS BITSIZE(ADDRESS) - 32 FOR [0..PadRange]; > END; > > > > On Sep 5, 2012, at 11:18 AM, Antony Hosking wrote: > > > Remind me again why you can't use TypeUID as is? > > There is nothing in the language spec that prohibits packed types in records. > > > > On Sep 5, 2012, at 10:50 AM, Jay K wrote: > > > >> This seems quite wrong from a simple engineering/design/factoring/abstraction point of view. > >> > >> > >> Imagine I have a few of these things. They are subranges or enums. That fit in a smaller size. > >> Wouldn't it be nice, to just use the type directly and get the space savings? Opportunistically? > >> What if the type is a REAL or a LONGINT? > >> I want the type to be opaque/abstract where that is easy and cheap and this certainly seems like an easy/cheap place to have slightly valuable opacity. > >> Isn't it really good, more than "just nice" to let the type change and have a lot of code work just as well? > >> Because they didn't copy around knowledge of what the type is? > >> What if the type changes? > >> Anyone just copying it around by exact restated typename is unaffected. > >> Anyone who looked at and decided to restate the definition might type might be broken. > >> > >> > >> And again, really -- you want to sacrifice both performance and abstraction when both are easily kept better? > >> That is, I'm all for range checks to keep things "safe", safety is important, but in this case you can easily preserve safety w/o adding range checks. > >> > >> > >> We do have enums at this layer. > >> Would you suggest I take the ORD of all of those and store them in INTEGERs too? > >> > >> > >> I am really surprised. > >> > >> > >> - Jay > >> > >> > >> From: hosking at cs.purdue.edu > >> Date: Wed, 5 Sep 2012 10:33:58 -0400 > >> To: dragisha at m3w.org > >> CC: m3devel at elegosoft.com; jay.krell at cornell.edu > >> Subject: Re: [M3devel] M3CG > >> > >> Precisely. > >> > >> > >> On Sep 5, 2012, at 3:40 AM, Dragi?a Duri? wrote: > >> > >> Why holding/passing of this value in INTEGER would be a problem? As long as range checks are passed on "assignment boundaries", it is all well. > >> > >> It is how Modula-3 does things. > >> > >> -- > >> Divided by a common language > >> > >> Dragi?a Duri? > >> dragisha at m3w.org > >> > >> > >> > >> > >> On Sep 4, 2012, at 10:47 PM, Jay K wrote: > >> > >> RECORD HoldsTypeUID: > >> typeuid: [FIRST(TypeUID)..LAST(TypeUID)]; > >> END? > >> > >> > >> But what if I'm really just a holder/passer of this thing, > >> and I never interpret it. Now TypeUID can't be changed > >> to LONGREAL or somesuch. Ideally some code wouldn't care > >> and still be correct. > >> > >> > >> The idea is to hold the thing, pass it on, without knowing > >> what it is. I want a field with the same type. > >> > >> > >> Why does it matter if TypeUID is representable in 32 bits? > >> Isn't the range the interface? > >> If it wasn't for readability of all the F's, I think > >> TypeUID = [-16_7FFFFFFF - 1 .. 16_7FFFFFFF]; is best. > >> > >> > >> Do we really care about few or many bits that occupies? > >> > >> > >> Cstdint.int32_t I agree is a bit lazy. > >> Maybe something like Word.Shift(1, 31) .. Word.Not(Word.Shift(1, 31)) ? > >> A bit wordy but ok. > >> Maybe not correct. Not clear the start is negative. > >> Maybe needs to be more like: > >> > >> (-Word.Not(Word.Shift(1, 31))) - 1 .. Word.Not(Word.Shift(1, 31)) > >> > >> > >> But these bit twiddlings might then confuse people. > >> So maybe having to count F's is better.. :( > >> > >> > >> You know, what about being 32bits in size would be part of an interface? > >> I don't think much/anything, but maybe. > >> > >> > >> Do we do/allow things like bit operations on it? Index into it a certain number > >> of bits? Take the address and assume BYTESIZE == 4? > >> I could see those maybe occuring. Maybe. > >> > >> > >> But I'm pretty sure they values are fairly abstract/opaque and the best anyone can do > >> is format them as strings and compare them for e.g. sorting purposes, but must > >> assume they are fairly sparse. > >> > >> > >> Btw, whenever the matter of "portability to signed-magnitude" or one's complement > >> comes up, I admit I get a bit confused. Two's complement is very ingrained > >> in my world view. > >> > >> > >> I agree TInt.T suffices. > >> Just like CARDINAL isn't needed, INTEGER suffices. > >> Cardinal.T just disallows negative numbers earlier, or at lower level, etc. > >> If we had to use TInt.T and add checks in a few places that it >= 0, ok. > >> It seems a little nice to put the checking in. > >> > >> > >> - Jay > >> > >> > >> > >> > >> > Subject: Re: M3CG > >> > From: hosking at cs.purdue.edu > >> > Date: Tue, 4 Sep 2012 13:05:34 -0400 > >> > CC: m3devel at elegosoft.com > >> > To: jay.krell at cornell.edu > >> > > >> > On Sep 4, 2012, at 12:09 PM, Jay wrote: > >> > > >> > > "BITS" seems to not provide any useful value. It only makes it so you can't put the type into a portable unpacked record, which is what I was doing. I either have to pack my record somehow (counting target-dependent bits??) or lay out the fields carefully in some way that all targets allow. The problem was that some targets didn't like the layout. > >> > > >> > For M3CG.TypeUID the BITS 32 enforces that it is always representable in 32 bits. This is a fundamental invariant of the compiler and run-time system. Removing it might allow bug creep. You don't need to pack your record. You just need a field sufficiently large to hold the value of a type id. In this instance an INTEGER field would suffice, or you can use the same subrange. > >> > > >> > > Given the stated range, that you'll get enough bits to store it, what is the point in giving the size too? Isn't providing just the range and no particular size, sufficient & more abstract? Granted, I went the other way. > >> > > >> > Only if an implementation chooses to store a subrange in as few bits as necessary. Yes, CM3 does this, but it is not guaranteed by the language spec. Here the size is the critical invariant. > >> > > >> > > I don't remember but guessing: > >> > > > >> > > > >> > > Cardinal.T would be, like CARDINAL vs. INTEGER: only slightly subtley useful: same as TInt.T, but disallows negative numbers. > >> > > >> > But for what purpose. The target does not have CARDINAL. It only has a target integer. > >> > > >> > > Most likely I ran into places where a host integer/cardinal did not necessarily suffice, and so a target type was called for. > >> > > > >> > > > >> > > I know we have places that need to use target types but don't yet. Specifically for the sizes of things like records & arrays. Otherwise we have hacks where 64bit systems declare 32bit limits. > >> > > >> > Again, TInt.T suffices for all of these. > >> > > >> > > > >> > > > >> > > - Jay (briefly/pocket-sized-computer-aka-phone) > >> > > > >> > > On Sep 4, 2012, at 7:11 AM, Antony Hosking wrote: > >> > > > >> > >> Jay, > >> > >> > >> > >> I've been looking over some of your changes to M3CG interfaces. You'll notice that I removed your import of Cstdlib.int into M3CG_Ops.i3. It does not belong there. The type as declared: > >> > >> > >> > >> TypeUID = BITS 32 FOR [-16_7fffffff-1 .. 16_7fffffff]; > >> > >> > >> > >> is correct as is. It is a 32 bit value that encodes a particular subrange, REGARDLESS of target machine. It is improper to change that definition to rely on some C type. > >> > >> > >> > >> I also have some other questions. Why did you add the type Cardinal.T? This seems entirely unnecessary, since targets don't have a Cardinal type. The only type they have is a target integer. All other Modula-3 ordinal types should be simulated in the compiler using TInt.T. I would advise that it be removed. Also, I don't understand why you changed descriptions of the primitive types to use this Cardinal.T instead of the original CARDINAL to hold information about the bit size, alignment, and byte size. There is no situation in which a host will need to emulate the behavior of CARDINAL for these values (all can be represented using CARDINAL no matter what the host). > >> > >> > >> > >> I am concerned that these changes reflect a desire on your part to change the world to fit your specific needs (whether justified or not). The interfaces defined in M3CG were carefully designed and inherit from a long code-chain going back to the 1980's and have not see huge changes since then. I strongly advise against making changes unless you have good reason, because there are a number of tools that rely on M3CG (not just those in the public sources). > >> > >> > >> > >> I am going to do a pass to revert some of your changes, since they are causing a number of my systems to fail to build. (cf. Niagara on tinderbox). > >> > >> > >> > >> I strongly advise that you try to use a private branch when developing new functionality. We as a community can then go through a revision process to vet substantive changes before merging them into the trunk. > >> > >> > >> > >> - Tony > >> > >> > >> > > > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From jay.krell at cornell.edu Thu Sep 6 10:29:59 2012 From: jay.krell at cornell.edu (Jay K) Date: Thu, 6 Sep 2012 08:29:59 +0000 Subject: [M3devel] M3CG_Rd.m3 Message-ID: http://modula3.elegosoft.com/cgi-bin/cvsweb.cgi/cm3/m3-sys/m3middle/src/M3CG_Rd.m3.diff?r1=1.14;r2=1.15;f=u Tony, now I'm reviewing your changes (CVS sure doesn't make this easy!)Apparent problem here.Granted, I could have left a comment in the code as to what was going on.(not that the vast bulk of m3-sys is well commented!) Revision 1.15: download - view: text, markup, annotated - select for diffsTue Sep 4 16:52:46 2012 (41 hours, 23 minutes ago) by hoskingBranches: MAINCVS tags: HEADDiff to: previous 1.14: preferred, unifiedChanges since revision 1.14: +2 -2 linesBest to retain error checking on return values from Convert.ToInt. See here: Revision 1.14: download - view: text, markup, annotated - select for diffsWed Aug 22 16:15:40 2012 (2 weeks ago) by jkrellBranches: MAINDiff to: previous 1.13: preferred, unifiedChanges since revision 1.13: +2 -2 lineswhen printing variables and procedures:e.g: begin_procedure p.32 store v.33 0 Addr Addr instead: begin_procedure p.32.Makefile__NoteSourceFile store v.33.file 0 Addr Addr i.e. much more readablegranted, less compact, not "normalized" (redundant data) I verified that m3cgcat still roundtrips. Not that I ever tried that before, but that is what the design implied the ability to do. Not that it is likely important these days/years/decades. The delimiting "." is chosen to stop integer parsingIt is presumed names don't contain spaces, or whatever,that M3CG_Rd is ok with this extra output from M3CG_Wr.I only tried with one file. Note that I hacked M3CG_Rd__CvtInt to not complain about the extra text.It might be better to have it verify it some, like that it is dotfollowed by star or a valid pair of "__" delimited identifiers. -------------- next part -------------- An HTML attachment was scrubbed... URL: From jay.krell at cornell.edu Thu Sep 6 10:40:46 2012 From: jay.krell at cornell.edu (Jay K) Date: Thu, 6 Sep 2012 08:40:46 +0000 Subject: [M3devel] a "need" for multi-pass m3cg (or different order of calls) Message-ID: /* The following is legal C but not C++: */ struct Foo_t;typedef struct Foo_t Foo_t;static struct Foo_t Foo; /* illegal C++; C forward/tentative definition */ int F1(void) { return *(int*)&Foo; } struct Foo_t { int i; };static Foo_t Foo = { 123 }; This is a reason that either1) I "need" to make M3C.m3 "multi pass"2) or at least buffer everything in memoryin multiple pieces and then concat at the end I could also make it less efficient: struct Foo_t; /* segment */ typedef struct Foo_t Foo_t; static struct Foo_t * /*const*/ Foo; int F1(void) { return *(int*)&Foo; } struct Foo_t { int i; }; static Foo_t _Foo = { 123 }; static Foo_t* /*const*/ Foo = &_Foo; But that seems unfortunate. I will want to generate C++ at some point, for efficient portable exceptionhandling. But that comes later. Also later, the C code needs a reordering in order to refer to fields in "segments". - Jay -------------- next part -------------- An HTML attachment was scrubbed... URL: From jay.krell at cornell.edu Thu Sep 6 10:52:19 2012 From: jay.krell at cornell.edu (Jay K) Date: Thu, 6 Sep 2012 08:52:19 +0000 Subject: [M3devel] fyi: state of C backend Message-ID: Here is what you can do now, it is maghor progress. edit cm3cg.common to "unfold nested procs" for all targets cm3 -keepm3cgcat m3-sys/cm3/AMD64_DARWIN/Makefile.mc -out-c:1.cgcc -m64 -c 1.c I also added a direct nested function call to Makefile.m3to get more coverage.Makefile.m3 already included taking the address ofa nested function, and an exception or finally block.(It appears that exception/finally blocks are givena parameter by the frontend, which is the static_link,whereas other nested functions are not; maybe I'm confused). It looks right as far as I've looked.Granted, it is hard to see much of anything.I still have to put in case_jump.It is only valid C, not C++.It is kind of horrendous, but we kind of knew that. Due to the low level nature of M3CG. Approximate plan: add case_jump double check if init_float is correct double check what EVAL function_call() does -- need to be sure we emit it compile more stuff .. lots of stuff .. will likely hit problems... link stuff -- will likely hit problems -- run stuff -- will likely hit problems .. things to fix but could be postponed: a fair number of warnings, about unused helper functions, unused labels for call_indirect, I cast the function pointer to return-type (*)(), pretty awful. For C++, return_type (*)(...); when it is good and stable and usable: move static helper functions into m3core integrate it into cm3 properly much later: use C++ exception handling consider: Can C++ be used to more portably efficiently pass the static link? Or it is only useful for one level? Or it only makes a difference on NT/x86? Point is...hopefully people can start believing in this thing.Maybe provide feedback, suggest changes.Still there is a ways to go.It is just a step beyond "printing random stuff", in that the random stuffgets a fair amount done, and is compilable, at least for one randomly selectedmodule. (Makefile.m3 is not just a trivial few lines, nor is it some comphrensivestress test as far as I know.) - Jay -------------- next part -------------- An HTML attachment was scrubbed... URL: From dragisha at m3w.org Thu Sep 6 13:15:23 2012 From: dragisha at m3w.org (=?utf-8?Q?Dragi=C5=A1a_Duri=C4=87?=) Date: Thu, 6 Sep 2012 13:15:23 +0200 Subject: [M3devel] =?windows-1252?q?M3CG=5FRd=2Em3=85_CVS_fun_=3A=29?= In-Reply-To: References: Message-ID: <7BB90E2F-6A41-4650-865C-B6CBFA887FF5@m3w.org> Old problem called version control system used :). Other, almost all of them natively distributed, version control system surely are making (at least some of us) drool :). I made CVS -> subversion step long time ago. Never looked back, nor too much forward. subversion does a lot and does it nicely. -- Divided by a common language Dragi?a Duri? dragisha at m3w.org On Sep 6, 2012, at 10:29 AM, Jay K wrote: > Tony, now I'm reviewing your changes (CVS sure doesn't make this easy!) > -------------- next part -------------- An HTML attachment was scrubbed... URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 495 bytes Desc: Message signed with OpenPGP using GPGMail URL: From hosking at cs.purdue.edu Thu Sep 6 15:19:56 2012 From: hosking at cs.purdue.edu (Antony Hosking) Date: Thu, 6 Sep 2012 09:19:56 -0400 Subject: [M3devel] =?windows-1252?q?M3CG=5FRd=2Em3=85_CVS_fun_=3A=29?= In-Reply-To: <7BB90E2F-6A41-4650-865C-B6CBFA887FF5@m3w.org> References: <7BB90E2F-6A41-4650-865C-B6CBFA887FF5@m3w.org> Message-ID: I find CVS mode in emacs with emacs diff works wonderfully well. On Sep 6, 2012, at 7:15 AM, Dragi?a Duri? wrote: > Old problem called version control system used :). > > Other, almost all of them natively distributed, version control system surely are making (at least some of us) drool :). > > I made CVS -> subversion step long time ago. Never looked back, nor too much forward. subversion does a lot and does it nicely. > > -- > Divided by a common language > > Dragi?a Duri? > dragisha at m3w.org > > > > > On Sep 6, 2012, at 10:29 AM, Jay K wrote: > >> Tony, now I'm reviewing your changes (CVS sure doesn't make this easy!) > -------------- next part -------------- An HTML attachment was scrubbed... URL: From dragisha at m3w.org Thu Sep 6 15:22:09 2012 From: dragisha at m3w.org (=?utf-8?Q?Dragi=C5=A1a_Duri=C4=87?=) Date: Thu, 6 Sep 2012 15:22:09 +0200 Subject: [M3devel] =?windows-1252?q?M3CG=5FRd=2Em3=85_CVS_fun_=3A=29?= In-Reply-To: References: <7BB90E2F-6A41-4650-865C-B6CBFA887FF5@m3w.org> Message-ID: <1D9BAA16-74B0-4389-B58A-0C335C38972E@m3w.org> Lots of things work very well with emacs. Although I prefer Aquamacs :) -- Divided by a common language Dragi?a Duri? dragisha at m3w.org On Sep 6, 2012, at 3:19 PM, Antony Hosking wrote: > I find CVS mode in emacs with emacs diff works wonderfully well. > > On Sep 6, 2012, at 7:15 AM, Dragi?a Duri? wrote: > >> Old problem called version control system used :). >> >> Other, almost all of them natively distributed, version control system surely are making (at least some of us) drool :). >> >> I made CVS -> subversion step long time ago. Never looked back, nor too much forward. subversion does a lot and does it nicely. >> >> -- >> Divided by a common language >> >> Dragi?a Duri? >> dragisha at m3w.org >> >> >> >> >> On Sep 6, 2012, at 10:29 AM, Jay K wrote: >> >>> Tony, now I'm reviewing your changes (CVS sure doesn't make this easy!) >> > -------------- next part -------------- An HTML attachment was scrubbed... URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 495 bytes Desc: Message signed with OpenPGP using GPGMail URL: From hosking at cs.purdue.edu Thu Sep 6 15:24:39 2012 From: hosking at cs.purdue.edu (Antony Hosking) Date: Thu, 6 Sep 2012 09:24:39 -0400 Subject: [M3devel] M3CG_Rd.m3 In-Reply-To: References: Message-ID: <52A90EA3-BA31-426F-8FE8-5339FC6218DE@cs.purdue.edu> Yes, that is a HACK. How do you know that your change to include the name doesn?t break other parts of the tool chain. Yes, I know that numbers are less readable, but the binding between name and numbers is explicit in the code. I?ve never found it to be too difficult to manage with. I think in this instance it would be better to revert to the numbers. Short-term convenience for potential sacrifice of robustness represents a step backward. On Sep 6, 2012, at 4:29 AM, Jay K wrote: > http://modula3.elegosoft.com/cgi-bin/cvsweb.cgi/cm3/m3-sys/m3middle/src/M3CG_Rd.m3.diff?r1=1.14;r2=1.15;f=u > > > Tony, now I'm reviewing your changes (CVS sure doesn't make this easy!) > Apparent problem here. > Granted, I could have left a comment in the code as to what was going on. > (not that the vast bulk of m3-sys is well commented!) > > > > Revision 1.15: download - view: text, markup, annotated - select for diffs > Tue Sep 4 16:52:46 2012 (41 hours, 23 minutes ago) by hosking > Branches: MAIN > CVS tags: HEAD > Diff to: previous 1.14: preferred, unified > Changes since revision 1.14: +2 -2 lines > Best to retain error checking on return values from Convert.ToInt. > > > See here: > > Revision 1.14: download - view: text, markup, annotated - select for diffs > Wed Aug 22 16:15:40 2012 (2 weeks ago) by jkrell > Branches: MAIN > Diff to: previous 1.13: preferred, unified > Changes since revision 1.13: +2 -2 lines > when printing variables and procedures: > e.g: > begin_procedure p.32 > store v.33 0 Addr Addr > > instead: > begin_procedure p.32.Makefile__NoteSourceFile > store v.33.file 0 Addr Addr > > i.e. much more readable > granted, less compact, not "normalized" (redundant data) > > I verified that m3cgcat still roundtrips. > Not that I ever tried that before, but that is what > the design implied the ability to do. Not that > it is likely important these days/years/decades. > > The delimiting "." is chosen to stop integer parsing > It is presumed names don't contain spaces, or whatever, > that M3CG_Rd is ok with this extra output from M3CG_Wr. > I only tried with one file. > > Note that I hacked M3CG_Rd__CvtInt to not complain about the extra text. > It might be better to have it verify it some, like that it is dot > followed by star or a valid pair of "__" delimited identifiers. -------------- next part -------------- An HTML attachment was scrubbed... URL: From hosking at cs.purdue.edu Thu Sep 6 19:26:24 2012 From: hosking at cs.purdue.edu (Antony Hosking) Date: Thu, 6 Sep 2012 13:26:24 -0400 Subject: [M3devel] M3CG In-Reply-To: References: <47B9A237-FD0B-4E40-9F12-938BC3D00E9E@cs.purdue.edu> <62BAB949-DBD6-405D-A6E8-0F416DEB586B@gmail.com> <3FC36B77-1F30-462C-9688-285D50351455@cs.purdue.edu> <228002BB-DE75-4320-A70F-CBB82A23D758@m3w.org> <87DABD01-259D-4373-8C77-9570869AF6FD@cs.purdue.edu> <71BE165D-B2DA-494D-9608-CCC581A32E4F@cs.purdue.edu> <38AA75B5-97B7-4D45-8B7D-45F88ED28D25@gmail.com> , Message-ID: <6C2A07CC-92D4-4359-877D-C17B30170E0A@cs.purdue.edu> Yes, they have exactly 32 bits in size to guarantee that all targets can use them. Various tools expect this, notably m3gdb and the run-time system. Tools may manipulate them as INTEGER, but really they should be thought of as Word.T (which anyway is INTEGER on all targets). The subrange just captures the range of values they can take on if interpreted as a 2s complement signed 32-bit integer. They will likely always be manipulable as INTEGER. That will not change. So, if you want to store them in records you can easily just store as INTEGER. If you want to avoid the range check you can declare the field to be the same subrange. If anything changes in their representation it won?t stop you manipulating as INTEGER. If the subrange changes, which it won?t then you?ll at least get a range check failure at run time or a compiler warning. So. Use INTEGER. Live long and prosper. On Sep 6, 2012, at 4:13 AM, Jay K wrote: > I'm really confused but the approach and mentality here. > I believe I understand that this is not C or C++ and that there > are things to be gained from that. > > > > First, let me restate the "less important" questions. > The questions I care less about. > > > > What is the interface or abstract contractual properties of TypeUID? > It is exactly 32 bits in size? > I doubt it, but it could be. > At least 32 bits in size? > Well, that is kind of unavoidable, assuming a binary computer, > a computer that actually uses bits. > > > > No more than 32 bits in size? > > > > It can store the subrange -16_7FFFFFF - 1 .. 16_7FFFFFF? > That seems to me to be "part of" the interface, and possibly > the entire interface. Assuming a computing device that uses "bits", > that does imply at least 32 bits. > It actually conceivably does not rule out requiring 33 bits, > as signed-magnitude requires 33 bits to represent -16_7FFFFFF - 1. > I'm willing to believe we are not portable beyond two's complement systems. > > > > And where are these properties assumed and violating them would > cause problems? > > > parse.c says: > /*------------------------------------------------------------- type uids ---*/ > /* Modula-3 type uids are unsigned 32-bit values. They are passed as signed > decimal integers in the intermediate code, but converted to 6-byte, base 62 > strings of characters from here to the debugger. To avoid surprises downstream, > these generated strings are legal C identifiers. */ > > #define UID_SIZE 6 > #define NO_UID (0xFFFFFFFFUL) > > > (Notice this does NOT agree with TypeUID -- it says they are unsigned. > But the subrange includes negative numbers. I should check this and > the history...) > > > I'm hoping we delete parse.c within a year, but that's another matter. > The C-generating backend is coming along nicely. > > > So there is a dependency that they be representable within 6 base-62 > digits. Which I believe actually allows for a larger range, at least > slightly. > > > Ok, as I said, this isn't critical. > I'm willing to believe it must fit in 32 bits. > I'm skeptical that it must not include extra padding bits within a struct (which > is what the historical definition is). > > > Now, let's move on to my very very simple desire > to store these things in records, and pass them on to > other M3CG.T implementations. > > > Hypothetical dumb code, that should be simple and work. > Yes, I know this is dumb, but it demonstrates the point. > > > TYPE T1 = RECORD text: TEXT; type: TypeUID END; > > > M3CG.T cg1, cg2; > > > PROCEDURE declare_whatevere(text: TEXT; type: TypeUID) > VAR t1: T1; > BEGIN > t1.text := text; > t1.type := type; > cg1.declare_whatever(t1.text, t1.type); > cg2.declare_whatever(t1.text, t1.type); > END declare_whatevere; > > > It should be that easy, right? > Surely this is reasonable? > > > > TypeUID could be INTEGER, a subrange, an enum, REAL, BOOLEAN > REFANY, UNTRACED REF of anything, it could be a RECORD > with arbitrary fields. This would work. > It doesn't care about packing or padding. > It doesn't assume TypeUID is a subrange and declare the similar: > > > TYPE T1 = RECORD text: TEXT; type: FIRST(TypeUID) ... LAST(TypeUID) END; > > > If TypeUID changes to one of several other kinds of things, > it continues to work and be correct. > > > Granted, if TypeUID became some sort of "OBJECT", maybe with > some sort of "copy" or "clone" METHOD, then maybe this becomes wrong. > (This is an area where C++ is very interesting -- user defined types > can behave like values and be copied around correctly w/o regard > to the concrete implementation/representation; it is up to the type > implementer to make it work if he deems it. But I digress.) > > > Now I see a few unavoidable options. > > > 1) TypeUID can be any size. > > TypeUID = [-16_7FFFFFF - 1 .. 16_7FFFFFFF]; > > > 2) TypeUID must fit in 32 bits, but padding can be inserted > before/after it: > > > TypeUID = [-16_7FFFFFF - 1 .. 16_7FFFFFFF]; > <* ASSERT BITSIZE(TypeUID) >= 32 *> > > > That is essentially what I did, but without the assertion. > Cstdint.int32_t is just a lazy way of stating the same thing. > Granted, with an apparent interest in the size. > But, again, that might be an over specification. > > > 3) We are super afraid of making any changes and TypeUID > really cannot change at all, but it is reasonble > to allow new code like I showed. > > > UnpackedTypeUID = [-16_7FFFFFF - 1 .. 16_7FFFFFFF]; (* for new code to use *) > TypeUID = BITS 32 FOR TypeUID; (* extreme compatibility *) > > > I really don't think "Int32" is the way. > It doesn't belong here. Public in M3CG/Target. > It is not what I should store in a record to hold a TypeUID. > > > Again, imagine TypeUID is opaque/abstract to me. > I just need to copy it around and pass it on to other M3CG implementations. > It could chane to REAL for all I care. > I don't want to be referencing some very concrete/transparent "Int32", > when I'm not doing anything that depends on that implementation detail. > > > I even question somewhat the subrange. > > > In the future 32 bit hosts and targets will disappear. > We will have only 64bit and 128bit. > > > What should TypeUID be in that world? > > > Is the point really that it be an "INTEGER" that "fits" > on any host or target? > > > > Now, I grant... I might need to convert a TypeUID to a string. > Here we are faced with a recurring dilemna. > Either TypeUID is a thick/complete abtraction, and we provide > common operations: > INTERFACE TypeUID; > > > (* declared here for performance; actually abstract; > * use only with functions in this interface *) > TYPE T = [-16_7FFFFFF - 1 .. 16_7FFFFFFF]; > > PROCEDURE Compare(a,b:T): [-1..1]; (* like for qsort *) > PROCEDURE Equal(a,b:T): BOOLEAN; > PROCEDURE ToText(a:T): TEXT; > PROCEDURE Copy(from:T; VAR to:T); > PROCEDURE Init(VAR a:T); > PROCEDURE New():T; > > END TypeUID; > > MODULE TypeUID; > > (* for now, just an integer *) > > PROCEDURE Compare(a,b:T): [-1..1] (* like for qsort *) > BEGIN > (* DO NOT USE SUBTRACTION HERE. *) > IF a < b THEN RETURN -1; END; > ELSIF a > b THEN RETURN 1; END; > ELSE RETURN 0; END; > END Compare; > > PROCEDURE Equal(a,b:T): BOOLEAN = > BEGIN > RETURN a = b; > END Equal; > > PROCEDURE ToText(a:T): TEXT > BEGIN > return Fmt.Int(a); > END ToText; > > PROCEDURE Copy(from:T; VAR to:T) = > BEGIN > to := from; > END Copy; > > PROCEDURE Init(VAR a:T); > BEGIN > a := 0; > END Init; > > PROCEDURE New():T; > BEGIN > RETURN 0; > END New; > > END TypeUID; > > > OR TypeUID is very transparent, everyone knows it is an integer > and everyone just does integer "operations" on it. > And it probably can never change. > But hopefully they never get added. > > > Note of course that the abstract variation isn't very good > at protecting the abstration. > > > It is probably desirable to be able to say: > > INTERFACE > > TYPE T; (* fully opaque *) > > MODULE > > REVEAL T = INTEGER; > > > I understand this is hard to do efficiently. > You either need a really good "cross-module compiler", > or you need to heap allocate them all. > A simple compiler that produces efficient code motivates > revealing the type in public. > That is unfortunate. > For example, adding TypeUIDs is probably nonsense > and worth prohibiting. But by publically revealing > it is an INTEGER (essentially), extra unintended operations > are allowed on it. > > > (C++ solves... since you can have a class that is small, > and the clients know the size, and allocate room for it, > yet all the data members could be private. The language > is complicated, but the goal of allowing powerful efficient user > defined types is a good one, and achieved very well) > > > > - Jay > > > > > > Subject: Re: [M3devel] M3CG > From: hosking at cs.purdue.edu > Date: Wed, 5 Sep 2012 22:07:24 -0400 > CC: m3devel at elegosoft.com > To: jay.krell at cornell.edu > > On Sep 5, 2012, at 10:06 PM, Antony Hosking wrote: > > Jay, I just checked in the following to M3CG.i3: > > TYPE > Int32 = [-16_7fffffff-1 .. 16_7fffffff]; > TypeUID = BITS 32 FOR Int32; > > Feel free to use M3CG.Int32. > At least this way, if anything changes TypeUID it will be clear that someone might be relying on TypeUID. > > I meant Int32. > > > > Antony Hosking | Associate Professor | Computer Science | Purdue University > 305 N. University Street | West Lafayette | IN 47907 | USA > Mobile +1 765 427 5484 > > > > > > On Sep 5, 2012, at 8:56 PM, Jay wrote: > > And if TypeUID changes? > > I want to store a TypeUID. I want to treat it opaquely/abstractly. It can change & I'd still store it correctly & efficiently. I should not go looking at it & cloning it. That seems like sound engineering. ? > > - Jay (briefly/pocket-sized-computer-aka-phone) > > On Sep 5, 2012, at 1:41 PM, Antony Hosking wrote: > > Jay, why don't you just us a local subrange for your fields in the records and then simply assign to/from TypeUID values? > > RECORD typeid: [-16_7fffffff-1 .. 16_7fffffff] END; > > You won't pay any penalty for range checks since the subranges are exactly the same. > > On Sep 5, 2012, at 2:34 PM, Jay K wrote: > > I should really insert padding manually? > I don't know if I like that or not. > > > My code is/was something like: > > TYPE T1 = RECORD > text: TEXT; > typeid: TypeUID; > END; > > > and that errors on some platforms. > > > I'm not using "Multipass" right now, but it does still hold possible value. > We can remove multipass from m3makefile for nowif that helps. > > > Given a similar problem in C, I would do something like: > > /* TypeUID must fit in 32 bits, for some reason. */ > C_ASSERT(sizeof(TypeUID) <= sizeof(UINT32)); > Where C_ASSERT is in windows.h and looks like: > /* compile time assert */ > #define C_ASSERT(expression) typedef char __cassert__[(expression) ? 1 : -1]; > or somesuch. The error message isn't great when it fails. > > People also name this "static_assert". It is popular. > > It doesn't prohibit it from having padding around it, but it does assert it fits in 32 bits. > > I recall we can do similar in Modula-3. > > TYPE assertTypeUIDFitsIn32Bits = ARRAY [0..ORD(BITSIZE(TypeUID) <= 32)] OF INTEGER; > or to be more certain: > TYPE assertTypeUIDFitsIn32Bits = ARRAY [0..-ORD(BITSIZE(TypeUID) <= 32)] OF INTEGER; > > I'm not sure 0..0 is illegal, but I think 0 .. 1 is. > > (I sure do miss macros...this is too much syntax for a compile time assert...) > > Can we just put <* ASSERT BITSIZE(TypeUID) <= 32 *> in the .i3 file? Or elsewhere? > > > - Jay > > > From: hosking at cs.purdue.edu > > Date: Wed, 5 Sep 2012 11:36:03 -0400 > > To: jay.krell at cornell.edu > > CC: m3devel at elegosoft.com > > Subject: Re: [M3devel] M3CG > > > > As I recall you were having trouble with alignment, right? > > > > In which case, why not pad your record type out to a reasonably aligned value? As in: > > > > CONST PadRange = Word.LeftShift(1, BITSIZE(ADDRESS) - BITSIZE(TypeUID)) - 1; > > RECORD > > t: TypeUID; > > pad: BITS BITSIZE(ADDRESS) - 32 FOR [0..PadRange]; > > END; > > > > > > > > On Sep 5, 2012, at 11:18 AM, Antony Hosking wrote: > > > > > Remind me again why you can't use TypeUID as is? > > > There is nothing in the language spec that prohibits packed types in records. > > > > > > On Sep 5, 2012, at 10:50 AM, Jay K wrote: > > > > > >> This seems quite wrong from a simple engineering/design/factoring/abstraction point of view. > > >> > > >> > > >> Imagine I have a few of these things. They are subranges or enums. That fit in a smaller size. > > >> Wouldn't it be nice, to just use the type directly and get the space savings? Opportunistically? > > >> What if the type is a REAL or a LONGINT? > > >> I want the type to be opaque/abstract where that is easy and cheap and this certainly seems like an easy/cheap place to have slightly valuable opacity. > > >> Isn't it really good, more than "just nice" to let the type change and have a lot of code work just as well? > > >> Because they didn't copy around knowledge of what the type is? > > >> What if the type changes? > > >> Anyone just copying it around by exact restated typename is unaffected. > > >> Anyone who looked at and decided to restate the definition might type might be broken. > > >> > > >> > > >> And again, really -- you want to sacrifice both performance and abstraction when both are easily kept better? > > >> That is, I'm all for range checks to keep things "safe", safety is important, but in this case you can easily preserve safety w/o adding range checks. > > >> > > >> > > >> We do have enums at this layer. > > >> Would you suggest I take the ORD of all of those and store them in INTEGERs too? > > >> > > >> > > >> I am really surprised. > > >> > > >> > > >> - Jay > > >> > > >> > > >> From: hosking at cs.purdue.edu > > >> Date: Wed, 5 Sep 2012 10:33:58 -0400 > > >> To: dragisha at m3w.org > > >> CC: m3devel at elegosoft.com; jay.krell at cornell.edu > > >> Subject: Re: [M3devel] M3CG > > >> > > >> Precisely. > > >> > > >> > > >> On Sep 5, 2012, at 3:40 AM, Dragi?a Duri? wrote: > > >> > > >> Why holding/passing of this value in INTEGER would be a problem? As long as range checks are passed on "assignment boundaries", it is all well. > > >> > > >> It is how Modula-3 does things. > > >> > > >> -- > > >> Divided by a common language > > >> > > >> Dragi?a Duri? > > >> dragisha at m3w.org > > >> > > >> > > >> > > >> > > >> On Sep 4, 2012, at 10:47 PM, Jay K wrote: > > >> > > >> RECORD HoldsTypeUID: > > >> typeuid: [FIRST(TypeUID)..LAST(TypeUID)]; > > >> END? > > >> > > >> > > >> But what if I'm really just a holder/passer of this thing, > > >> and I never interpret it. Now TypeUID can't be changed > > >> to LONGREAL or somesuch. Ideally some code wouldn't care > > >> and still be correct. > > >> > > >> > > >> The idea is to hold the thing, pass it on, without knowing > > >> what it is. I want a field with the same type. > > >> > > >> > > >> Why does it matter if TypeUID is representable in 32 bits? > > >> Isn't the range the interface? > > >> If it wasn't for readability of all the F's, I think > > >> TypeUID = [-16_7FFFFFFF - 1 .. 16_7FFFFFFF]; is best. > > >> > > >> > > >> Do we really care about few or many bits that occupies? > > >> > > >> > > >> Cstdint.int32_t I agree is a bit lazy. > > >> Maybe something like Word.Shift(1, 31) .. Word.Not(Word.Shift(1, 31)) ? > > >> A bit wordy but ok. > > >> Maybe not correct. Not clear the start is negative. > > >> Maybe needs to be more like: > > >> > > >> (-Word.Not(Word.Shift(1, 31))) - 1 .. Word.Not(Word.Shift(1, 31)) > > >> > > >> > > >> But these bit twiddlings might then confuse people. > > >> So maybe having to count F's is better.. :( > > >> > > >> > > >> You know, what about being 32bits in size would be part of an interface? > > >> I don't think much/anything, but maybe. > > >> > > >> > > >> Do we do/allow things like bit operations on it? Index into it a certain number > > >> of bits? Take the address and assume BYTESIZE == 4? > > >> I could see those maybe occuring. Maybe. > > >> > > >> > > >> But I'm pretty sure they values are fairly abstract/opaque and the best anyone can do > > >> is format them as strings and compare them for e.g. sorting purposes, but must > > >> assume they are fairly sparse. > > >> > > >> > > >> Btw, whenever the matter of "portability to signed-magnitude" or one's complement > > >> comes up, I admit I get a bit confused. Two's complement is very ingrained > > >> in my world view. > > >> > > >> > > >> I agree TInt.T suffices. > > >> Just like CARDINAL isn't needed, INTEGER suffices. > > >> Cardinal.T just disallows negative numbers earlier, or at lower level, etc. > > >> If we had to use TInt.T and add checks in a few places that it >= 0, ok. > > >> It seems a little nice to put the checking in. > > >> > > >> > > >> - Jay > > >> > > >> > > >> > > >> > > >> > Subject: Re: M3CG > > >> > From: hosking at cs.purdue.edu > > >> > Date: Tue, 4 Sep 2012 13:05:34 -0400 > > >> > CC: m3devel at elegosoft.com > > >> > To: jay.krell at cornell.edu > > >> > > > >> > On Sep 4, 2012, at 12:09 PM, Jay wrote: > > >> > > > >> > > "BITS" seems to not provide any useful value. It only makes it so you can't put the type into a portable unpacked record, which is what I was doing. I either have to pack my record somehow (counting target-dependent bits??) or lay out the fields carefully in some way that all targets allow. The problem was that some targets didn't like the layout. > > >> > > > >> > For M3CG.TypeUID the BITS 32 enforces that it is always representable in 32 bits. This is a fundamental invariant of the compiler and run-time system. Removing it might allow bug creep. You don't need to pack your record. You just need a field sufficiently large to hold the value of a type id. In this instance an INTEGER field would suffice, or you can use the same subrange. > > >> > > > >> > > Given the stated range, that you'll get enough bits to store it, what is the point in giving the size too? Isn't providing just the range and no particular size, sufficient & more abstract? Granted, I went the other way. > > >> > > > >> > Only if an implementation chooses to store a subrange in as few bits as necessary. Yes, CM3 does this, but it is not guaranteed by the language spec. Here the size is the critical invariant. > > >> > > > >> > > I don't remember but guessing: > > >> > > > > >> > > > > >> > > Cardinal.T would be, like CARDINAL vs. INTEGER: only slightly subtley useful: same as TInt.T, but disallows negative numbers. > > >> > > > >> > But for what purpose. The target does not have CARDINAL. It only has a target integer. > > >> > > > >> > > Most likely I ran into places where a host integer/cardinal did not necessarily suffice, and so a target type was called for. > > >> > > > > >> > > > > >> > > I know we have places that need to use target types but don't yet. Specifically for the sizes of things like records & arrays. Otherwise we have hacks where 64bit systems declare 32bit limits. > > >> > > > >> > Again, TInt.T suffices for all of these. > > >> > > > >> > > > > >> > > > > >> > > - Jay (briefly/pocket-sized-computer-aka-phone) > > >> > > > > >> > > On Sep 4, 2012, at 7:11 AM, Antony Hosking wrote: > > >> > > > > >> > >> Jay, > > >> > >> > > >> > >> I've been looking over some of your changes to M3CG interfaces. You'll notice that I removed your import of Cstdlib.int into M3CG_Ops.i3. It does not belong there. The type as declared: > > >> > >> > > >> > >> TypeUID = BITS 32 FOR [-16_7fffffff-1 .. 16_7fffffff]; > > >> > >> > > >> > >> is correct as is. It is a 32 bit value that encodes a particular subrange, REGARDLESS of target machine. It is improper to change that definition to rely on some C type. > > >> > >> > > >> > >> I also have some other questions. Why did you add the type Cardinal.T? This seems entirely unnecessary, since targets don't have a Cardinal type. The only type they have is a target integer. All other Modula-3 ordinal types should be simulated in the compiler using TInt.T. I would advise that it be removed. Also, I don't understand why you changed descriptions of the primitive types to use this Cardinal.T instead of the original CARDINAL to hold information about the bit size, alignment, and byte size. There is no situation in which a host will need to emulate the behavior of CARDINAL for these values (all can be represented using CARDINAL no matter what the host). > > >> > >> > > >> > >> I am concerned that these changes reflect a desire on your part to change the world to fit your specific needs (whether justified or not). The interfaces defined in M3CG were carefully designed and inherit from a long code-chain going back to the 1980's and have not see huge changes since then. I strongly advise against making changes unless you have good reason, because there are a number of tools that rely on M3CG (not just those in the public sources). > > >> > >> > > >> > >> I am going to do a pass to revert some of your changes, since they are causing a number of my systems to fail to build. (cf. Niagara on tinderbox). > > >> > >> > > >> > >> I strongly advise that you try to use a private branch when developing new functionality. We as a community can then go through a revision process to vet substantive changes before merging them into the trunk. > > >> > >> > > >> > >> - Tony > > >> > >> > > >> > > > > > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From jay.krell at cornell.edu Thu Sep 6 21:34:11 2012 From: jay.krell at cornell.edu (Jay) Date: Thu, 6 Sep 2012 12:34:11 -0700 Subject: [M3devel] M3CG In-Reply-To: <6C2A07CC-92D4-4359-877D-C17B30170E0A@cs.purdue.edu> References: <47B9A237-FD0B-4E40-9F12-938BC3D00E9E@cs.purdue.edu> <62BAB949-DBD6-405D-A6E8-0F416DEB586B@gmail.com> <3FC36B77-1F30-462C-9688-285D50351455@cs.purdue.edu> <228002BB-DE75-4320-A70F-CBB82A23D758@m3w.org> <87DABD01-259D-4373-8C77-9570869AF6FD@cs.purdue.edu> <71BE165D-B2DA-494D-9608-CCC581A32E4F@cs.purdue.edu> <38AA75B5-97B7-4D45-8B7D-45F88ED28D25@gmail.com> <6C2A07CC-92D4-4359-877D-C17B30170E0A@cs.purdue.edu> Message-ID: <443476F7-C0F2-4C51-A6F3-EDCDD6586363@gmail.com> What is wrong with the options of providing the "unpacked" name or the assertion option (granted, the assertion was probably wrong)? - Jay (briefly/pocket-sized-computer-aka-phone) On Sep 6, 2012, at 10:26 AM, Antony Hosking wrote: > Yes, they have exactly 32 bits in size to guarantee that all targets can use them. Various tools expect this, notably m3gdb and the run-time system. Tools may manipulate them as INTEGER, but really they should be thought of as Word.T (which anyway is INTEGER on all targets). The subrange just captures the range of values they can take on if interpreted as a 2s complement signed 32-bit integer. They will likely always be manipulable as INTEGER. That will not change. > > So, if you want to store them in records you can easily just store as INTEGER. If you want to avoid the range check you can declare the field to be the same subrange. > If anything changes in their representation it won?t stop you manipulating as INTEGER. If the subrange changes, which it won?t then you?ll at least get a range check failure at run time or a compiler warning. > > So. Use INTEGER. > > Live long and prosper. > > On Sep 6, 2012, at 4:13 AM, Jay K wrote: > >> I'm really confused but the approach and mentality here. >> I believe I understand that this is not C or C++ and that there >> are things to be gained from that. >> >> >> >> First, let me restate the "less important" questions. >> The questions I care less about. >> >> >> >> What is the interface or abstract contractual properties of TypeUID? >> It is exactly 32 bits in size? >> I doubt it, but it could be. > >> At least 32 bits in size? >> Well, that is kind of unavoidable, assuming a binary computer, >> a computer that actually uses bits. >> >> >> >> No more than 32 bits in size? >> >> >> >> It can store the subrange -16_7FFFFFF - 1 .. 16_7FFFFFF? >> That seems to me to be "part of" the interface, and possibly >> the entire interface. Assuming a computing device that uses "bits", >> that does imply at least 32 bits. >> It actually conceivably does not rule out requiring 33 bits, >> as signed-magnitude requires 33 bits to represent -16_7FFFFFF - 1. >> I'm willing to believe we are not portable beyond two's complement systems. >> >> >> >> And where are these properties assumed and violating them would >> cause problems? >> >> >> parse.c says: >> /*------------------------------------------------------------- type uids ---*/ >> /* Modula-3 type uids are unsigned 32-bit values. They are passed as signed >> decimal integers in the intermediate code, but converted to 6-byte, base 62 >> strings of characters from here to the debugger. To avoid surprises downstream, >> these generated strings are legal C identifiers. */ >> >> #define UID_SIZE 6 >> #define NO_UID (0xFFFFFFFFUL) >> >> >> (Notice this does NOT agree with TypeUID -- it says they are unsigned. >> But the subrange includes negative numbers. I should check this and >> the history...) >> >> >> I'm hoping we delete parse.c within a year, but that's another matter. >> The C-generating backend is coming along nicely. >> >> >> So there is a dependency that they be representable within 6 base-62 >> digits. Which I believe actually allows for a larger range, at least >> slightly. >> >> >> Ok, as I said, this isn't critical. >> I'm willing to believe it must fit in 32 bits. >> I'm skeptical that it must not include extra padding bits within a struct (which >> is what the historical definition is). >> >> >> Now, let's move on to my very very simple desire >> to store these things in records, and pass them on to >> other M3CG.T implementations. >> >> >> Hypothetical dumb code, that should be simple and work. >> Yes, I know this is dumb, but it demonstrates the point. >> >> >> TYPE T1 = RECORD text: TEXT; type: TypeUID END; >> >> >> M3CG.T cg1, cg2; >> >> >> PROCEDURE declare_whatevere(text: TEXT; type: TypeUID) >> VAR t1: T1; >> BEGIN >> t1.text := text; >> t1.type := type; >> cg1.declare_whatever(t1.text, t1.type); >> cg2.declare_whatever(t1.text, t1.type); >> END declare_whatevere; >> >> >> It should be that easy, right? >> Surely this is reasonable? >> >> >> >> TypeUID could be INTEGER, a subrange, an enum, REAL, BOOLEAN >> REFANY, UNTRACED REF of anything, it could be a RECORD >> with arbitrary fields. This would work. >> It doesn't care about packing or padding. >> It doesn't assume TypeUID is a subrange and declare the similar: >> >> >> TYPE T1 = RECORD text: TEXT; type: FIRST(TypeUID) ... LAST(TypeUID) END; >> >> >> If TypeUID changes to one of several other kinds of things, >> it continues to work and be correct. >> >> >> Granted, if TypeUID became some sort of "OBJECT", maybe with >> some sort of "copy" or "clone" METHOD, then maybe this becomes wrong. >> (This is an area where C++ is very interesting -- user defined types >> can behave like values and be copied around correctly w/o regard >> to the concrete implementation/representation; it is up to the type >> implementer to make it work if he deems it. But I digress.) >> >> >> Now I see a few unavoidable options. >> >> >> 1) TypeUID can be any size. >> >> TypeUID = [-16_7FFFFFF - 1 .. 16_7FFFFFFF]; >> >> >> 2) TypeUID must fit in 32 bits, but padding can be inserted >> before/after it: >> >> >> TypeUID = [-16_7FFFFFF - 1 .. 16_7FFFFFFF]; >> <* ASSERT BITSIZE(TypeUID) >= 32 *> >> >> >> That is essentially what I did, but without the assertion. >> Cstdint.int32_t is just a lazy way of stating the same thing. >> Granted, with an apparent interest in the size. >> But, again, that might be an over specification. >> >> >> 3) We are super afraid of making any changes and TypeUID >> really cannot change at all, but it is reasonble >> to allow new code like I showed. >> >> >> UnpackedTypeUID = [-16_7FFFFFF - 1 .. 16_7FFFFFFF]; (* for new code to use *) >> TypeUID = BITS 32 FOR TypeUID; (* extreme compatibility *) >> >> >> I really don't think "Int32" is the way. >> It doesn't belong here. Public in M3CG/Target. >> It is not what I should store in a record to hold a TypeUID. >> >> >> Again, imagine TypeUID is opaque/abstract to me. >> I just need to copy it around and pass it on to other M3CG implementations. >> It could chane to REAL for all I care. >> I don't want to be referencing some very concrete/transparent "Int32", >> when I'm not doing anything that depends on that implementation detail. >> >> >> I even question somewhat the subrange. >> >> >> In the future 32 bit hosts and targets will disappear. >> We will have only 64bit and 128bit. >> >> >> What should TypeUID be in that world? >> >> >> Is the point really that it be an "INTEGER" that "fits" >> on any host or target? >> >> >> >> Now, I grant... I might need to convert a TypeUID to a string. >> Here we are faced with a recurring dilemna. >> Either TypeUID is a thick/complete abtraction, and we provide >> common operations: >> INTERFACE TypeUID; >> >> >> (* declared here for performance; actually abstract; >> * use only with functions in this interface *) >> TYPE T = [-16_7FFFFFF - 1 .. 16_7FFFFFFF]; >> >> PROCEDURE Compare(a,b:T): [-1..1]; (* like for qsort *) >> PROCEDURE Equal(a,b:T): BOOLEAN; >> PROCEDURE ToText(a:T): TEXT; >> PROCEDURE Copy(from:T; VAR to:T); >> PROCEDURE Init(VAR a:T); >> PROCEDURE New():T; >> >> END TypeUID; >> >> MODULE TypeUID; >> >> (* for now, just an integer *) >> >> PROCEDURE Compare(a,b:T): [-1..1] (* like for qsort *) >> BEGIN >> (* DO NOT USE SUBTRACTION HERE. *) >> IF a < b THEN RETURN -1; END; >> ELSIF a > b THEN RETURN 1; END; >> ELSE RETURN 0; END; >> END Compare; >> >> PROCEDURE Equal(a,b:T): BOOLEAN = >> BEGIN >> RETURN a = b; >> END Equal; >> >> PROCEDURE ToText(a:T): TEXT >> BEGIN >> return Fmt.Int(a); >> END ToText; >> >> PROCEDURE Copy(from:T; VAR to:T) = >> BEGIN >> to := from; >> END Copy; >> >> PROCEDURE Init(VAR a:T); >> BEGIN >> a := 0; >> END Init; >> >> PROCEDURE New():T; >> BEGIN >> RETURN 0; >> END New; >> >> END TypeUID; >> >> >> OR TypeUID is very transparent, everyone knows it is an integer >> and everyone just does integer "operations" on it. >> And it probably can never change. >> But hopefully they never get added. >> >> >> Note of course that the abstract variation isn't very good >> at protecting the abstration. >> >> >> It is probably desirable to be able to say: >> >> INTERFACE >> >> TYPE T; (* fully opaque *) >> >> MODULE >> >> REVEAL T = INTEGER; >> >> >> I understand this is hard to do efficiently. >> You either need a really good "cross-module compiler", >> or you need to heap allocate them all. >> A simple compiler that produces efficient code motivates >> revealing the type in public. >> That is unfortunate. >> For example, adding TypeUIDs is probably nonsense >> and worth prohibiting. But by publically revealing >> it is an INTEGER (essentially), extra unintended operations >> are allowed on it. >> >> >> (C++ solves... since you can have a class that is small, >> and the clients know the size, and allocate room for it, >> yet all the data members could be private. The language >> is complicated, but the goal of allowing powerful efficient user >> defined types is a good one, and achieved very well) >> >> >> >> - Jay >> >> >> >> >> >> Subject: Re: [M3devel] M3CG >> From: hosking at cs.purdue.edu >> Date: Wed, 5 Sep 2012 22:07:24 -0400 >> CC: m3devel at elegosoft.com >> To: jay.krell at cornell.edu >> >> On Sep 5, 2012, at 10:06 PM, Antony Hosking wrote: >> >> Jay, I just checked in the following to M3CG.i3: >> >> TYPE >> Int32 = [-16_7fffffff-1 .. 16_7fffffff]; >> TypeUID = BITS 32 FOR Int32; >> >> Feel free to use M3CG.Int32. >> At least this way, if anything changes TypeUID it will be clear that someone might be relying on TypeUID. >> >> I meant Int32. >> >> >> >> Antony Hosking | Associate Professor | Computer Science | Purdue University >> 305 N. University Street | West Lafayette | IN 47907 | USA >> Mobile +1 765 427 5484 >> >> >> >> >> >> On Sep 5, 2012, at 8:56 PM, Jay wrote: >> >> And if TypeUID changes? >> >> I want to store a TypeUID. I want to treat it opaquely/abstractly. It can change & I'd still store it correctly & efficiently. I should not go looking at it & cloning it. That seems like sound engineering. ? >> >> - Jay (briefly/pocket-sized-computer-aka-phone) >> >> On Sep 5, 2012, at 1:41 PM, Antony Hosking wrote: >> >> Jay, why don't you just us a local subrange for your fields in the records and then simply assign to/from TypeUID values? >> >> RECORD typeid: [-16_7fffffff-1 .. 16_7fffffff] END; >> >> You won't pay any penalty for range checks since the subranges are exactly the same. >> >> On Sep 5, 2012, at 2:34 PM, Jay K wrote: >> >> I should really insert padding manually? >> I don't know if I like that or not. >> >> >> My code is/was something like: >> >> TYPE T1 = RECORD >> text: TEXT; >> typeid: TypeUID; >> END; >> >> >> and that errors on some platforms. >> >> >> I'm not using "Multipass" right now, but it does still hold possible value. >> We can remove multipass from m3makefile for nowif that helps. >> >> >> Given a similar problem in C, I would do something like: >> >> /* TypeUID must fit in 32 bits, for some reason. */ >> C_ASSERT(sizeof(TypeUID) <= sizeof(UINT32)); >> Where C_ASSERT is in windows.h and looks like: >> /* compile time assert */ >> #define C_ASSERT(expression) typedef char __cassert__[(expression) ? 1 : -1]; >> or somesuch. The error message isn't great when it fails. >> >> People also name this "static_assert". It is popular. >> >> It doesn't prohibit it from having padding around it, but it does assert it fits in 32 bits. >> >> I recall we can do similar in Modula-3. >> >> TYPE assertTypeUIDFitsIn32Bits = ARRAY [0..ORD(BITSIZE(TypeUID) <= 32)] OF INTEGER; >> or to be more certain: >> TYPE assertTypeUIDFitsIn32Bits = ARRAY [0..-ORD(BITSIZE(TypeUID) <= 32)] OF INTEGER; >> >> I'm not sure 0..0 is illegal, but I think 0 .. 1 is. >> >> (I sure do miss macros...this is too much syntax for a compile time assert...) >> >> Can we just put <* ASSERT BITSIZE(TypeUID) <= 32 *> in the .i3 file? Or elsewhere? >> >> >> - Jay >> >> > From: hosking at cs.purdue.edu >> > Date: Wed, 5 Sep 2012 11:36:03 -0400 >> > To: jay.krell at cornell.edu >> > CC: m3devel at elegosoft.com >> > Subject: Re: [M3devel] M3CG >> > >> > As I recall you were having trouble with alignment, right? >> > >> > In which case, why not pad your record type out to a reasonably aligned value? As in: >> > >> > CONST PadRange = Word.LeftShift(1, BITSIZE(ADDRESS) - BITSIZE(TypeUID)) - 1; >> > RECORD >> > t: TypeUID; >> > pad: BITS BITSIZE(ADDRESS) - 32 FOR [0..PadRange]; >> > END; >> > >> > >> > >> > On Sep 5, 2012, at 11:18 AM, Antony Hosking wrote: >> > >> > > Remind me again why you can't use TypeUID as is? >> > > There is nothing in the language spec that prohibits packed types in records. >> > > >> > > On Sep 5, 2012, at 10:50 AM, Jay K wrote: >> > > >> > >> This seems quite wrong from a simple engineering/design/factoring/abstraction point of view. >> > >> >> > >> >> > >> Imagine I have a few of these things. They are subranges or enums. That fit in a smaller size. >> > >> Wouldn't it be nice, to just use the type directly and get the space savings? Opportunistically? >> > >> What if the type is a REAL or a LONGINT? >> > >> I want the type to be opaque/abstract where that is easy and cheap and this certainly seems like an easy/cheap place to have slightly valuable opacity. >> > >> Isn't it really good, more than "just nice" to let the type change and have a lot of code work just as well? >> > >> Because they didn't copy around knowledge of what the type is? >> > >> What if the type changes? >> > >> Anyone just copying it around by exact restated typename is unaffected. >> > >> Anyone who looked at and decided to restate the definition might type might be broken. >> > >> >> > >> >> > >> And again, really -- you want to sacrifice both performance and abstraction when both are easily kept better? >> > >> That is, I'm all for range checks to keep things "safe", safety is important, but in this case you can easily preserve safety w/o adding range checks. >> > >> >> > >> >> > >> We do have enums at this layer. >> > >> Would you suggest I take the ORD of all of those and store them in INTEGERs too? >> > >> >> > >> >> > >> I am really surprised. >> > >> >> > >> >> > >> - Jay >> > >> >> > >> >> > >> From: hosking at cs.purdue.edu >> > >> Date: Wed, 5 Sep 2012 10:33:58 -0400 >> > >> To: dragisha at m3w.org >> > >> CC: m3devel at elegosoft.com; jay.krell at cornell.edu >> > >> Subject: Re: [M3devel] M3CG >> > >> >> > >> Precisely. >> > >> >> > >> >> > >> On Sep 5, 2012, at 3:40 AM, Dragi?a Duri? wrote: >> > >> >> > >> Why holding/passing of this value in INTEGER would be a problem? As long as range checks are passed on "assignment boundaries", it is all well. >> > >> >> > >> It is how Modula-3 does things. >> > >> >> > >> -- >> > >> Divided by a common language >> > >> >> > >> Dragi?a Duri? >> > >> dragisha at m3w.org >> > >> >> > >> >> > >> >> > >> >> > >> On Sep 4, 2012, at 10:47 PM, Jay K wrote: >> > >> >> > >> RECORD HoldsTypeUID: >> > >> typeuid: [FIRST(TypeUID)..LAST(TypeUID)]; >> > >> END? >> > >> >> > >> >> > >> But what if I'm really just a holder/passer of this thing, >> > >> and I never interpret it. Now TypeUID can't be changed >> > >> to LONGREAL or somesuch. Ideally some code wouldn't care >> > >> and still be correct. >> > >> >> > >> >> > >> The idea is to hold the thing, pass it on, without knowing >> > >> what it is. I want a field with the same type. >> > >> >> > >> >> > >> Why does it matter if TypeUID is representable in 32 bits? >> > >> Isn't the range the interface? >> > >> If it wasn't for readability of all the F's, I think >> > >> TypeUID = [-16_7FFFFFFF - 1 .. 16_7FFFFFFF]; is best. >> > >> >> > >> >> > >> Do we really care about few or many bits that occupies? >> > >> >> > >> >> > >> Cstdint.int32_t I agree is a bit lazy. >> > >> Maybe something like Word.Shift(1, 31) .. Word.Not(Word.Shift(1, 31)) ? >> > >> A bit wordy but ok. >> > >> Maybe not correct. Not clear the start is negative. >> > >> Maybe needs to be more like: >> > >> >> > >> (-Word.Not(Word.Shift(1, 31))) - 1 .. Word.Not(Word.Shift(1, 31)) >> > >> >> > >> >> > >> But these bit twiddlings might then confuse people. >> > >> So maybe having to count F's is better.. :( >> > >> >> > >> >> > >> You know, what about being 32bits in size would be part of an interface? >> > >> I don't think much/anything, but maybe. >> > >> >> > >> >> > >> Do we do/allow things like bit operations on it? Index into it a certain number >> > >> of bits? Take the address and assume BYTESIZE == 4? >> > >> I could see those maybe occuring. Maybe. >> > >> >> > >> >> > >> But I'm pretty sure they values are fairly abstract/opaque and the best anyone can do >> > >> is format them as strings and compare them for e.g. sorting purposes, but must >> > >> assume they are fairly sparse. >> > >> >> > >> >> > >> Btw, whenever the matter of "portability to signed-magnitude" or one's complement >> > >> comes up, I admit I get a bit confused. Two's complement is very ingrained >> > >> in my world view. >> > >> >> > >> >> > >> I agree TInt.T suffices. >> > >> Just like CARDINAL isn't needed, INTEGER suffices. >> > >> Cardinal.T just disallows negative numbers earlier, or at lower level, etc. >> > >> If we had to use TInt.T and add checks in a few places that it >= 0, ok. >> > >> It seems a little nice to put the checking in. >> > >> >> > >> >> > >> - Jay >> > >> >> > >> >> > >> >> > >> >> > >> > Subject: Re: M3CG >> > >> > From: hosking at cs.purdue.edu >> > >> > Date: Tue, 4 Sep 2012 13:05:34 -0400 >> > >> > CC: m3devel at elegosoft.com >> > >> > To: jay.krell at cornell.edu >> > >> > >> > >> > On Sep 4, 2012, at 12:09 PM, Jay wrote: >> > >> > >> > >> > > "BITS" seems to not provide any useful value. It only makes it so you can't put the type into a portable unpacked record, which is what I was doing. I either have to pack my record somehow (counting target-dependent bits??) or lay out the fields carefully in some way that all targets allow. The problem was that some targets didn't like the layout. >> > >> > >> > >> > For M3CG.TypeUID the BITS 32 enforces that it is always representable in 32 bits. This is a fundamental invariant of the compiler and run-time system. Removing it might allow bug creep. You don't need to pack your record. You just need a field sufficiently large to hold the value of a type id. In this instance an INTEGER field would suffice, or you can use the same subrange. >> > >> > >> > >> > > Given the stated range, that you'll get enough bits to store it, what is the point in giving the size too? Isn't providing just the range and no particular size, sufficient & more abstract? Granted, I went the other way. >> > >> > >> > >> > Only if an implementation chooses to store a subrange in as few bits as necessary. Yes, CM3 does this, but it is not guaranteed by the language spec. Here the size is the critical invariant. >> > >> > >> > >> > > I don't remember but guessing: >> > >> > > >> > >> > > >> > >> > > Cardinal.T would be, like CARDINAL vs. INTEGER: only slightly subtley useful: same as TInt.T, but disallows negative numbers. >> > >> > >> > >> > But for what purpose. The target does not have CARDINAL. It only has a target integer. >> > >> > >> > >> > > Most likely I ran into places where a host integer/cardinal did not necessarily suffice, and so a target type was called for. >> > >> > > >> > >> > > >> > >> > > I know we have places that need to use target types but don't yet. Specifically for the sizes of things like records & arrays. Otherwise we have hacks where 64bit systems declare 32bit limits. >> > >> > >> > >> > Again, TInt.T suffices for all of these. >> > >> > >> > >> > > >> > >> > > >> > >> > > - Jay (briefly/pocket-sized-computer-aka-phone) >> > >> > > >> > >> > > On Sep 4, 2012, at 7:11 AM, Antony Hosking wrote: >> > >> > > >> > >> > >> Jay, >> > >> > >> >> > >> > >> I've been looking over some of your changes to M3CG interfaces. You'll notice that I removed your import of Cstdlib.int into M3CG_Ops.i3. It does not belong there. The type as declared: >> > >> > >> >> > >> > >> TypeUID = BITS 32 FOR [-16_7fffffff-1 .. 16_7fffffff]; >> > >> > >> >> > >> > >> is correct as is. It is a 32 bit value that encodes a particular subrange, REGARDLESS of target machine. It is improper to change that definition to rely on some C type. >> > >> > >> >> > >> > >> I also have some other questions. Why did you add the type Cardinal.T? This seems entirely unnecessary, since targets don't have a Cardinal type. The only type they have is a target integer. All other Modula-3 ordinal types should be simulated in the compiler using TInt.T. I would advise that it be removed. Also, I don't understand why you changed descriptions of the primitive types to use this Cardinal.T instead of the original CARDINAL to hold information about the bit size, alignment, and byte size. There is no situation in which a host will need to emulate the behavior of CARDINAL for these values (all can be represented using CARDINAL no matter what the host). >> > >> > >> >> > >> > >> I am concerned that these changes reflect a desire on your part to change the world to fit your specific needs (whether justified or not). The interfaces defined in M3CG were carefully designed and inherit from a long code-chain going back to the 1980's and have not see huge changes since then. I strongly advise against making changes unless you have good reason, because there are a number of tools that rely on M3CG (not just those in the public sources). >> > >> > >> >> > >> > >> I am going to do a pass to revert some of your changes, since they are causing a number of my systems to fail to build. (cf. Niagara on tinderbox). >> > >> > >> >> > >> > >> I strongly advise that you try to use a private branch when developing new functionality. We as a community can then go through a revision process to vet substantive changes before merging them into the trunk. >> > >> > >> >> > >> > >> - Tony >> > >> > >> >> > >> > >> > > >> > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From jay.krell at cornell.edu Thu Sep 6 21:46:30 2012 From: jay.krell at cornell.edu (Jay) Date: Thu, 6 Sep 2012 12:46:30 -0700 Subject: [M3devel] M3CG_Rd.m3 In-Reply-To: <52A90EA3-BA31-426F-8FE8-5339FC6218DE@cs.purdue.edu> References: <52A90EA3-BA31-426F-8FE8-5339FC6218DE@cs.purdue.edu> Message-ID: Does there really exist other code that parses this stuff? Anything is possible but one needs to make judgement calls & confident guesses. I would imagine everyone should read them with M3CG_Rd. And that everyone would really use the binary form usually, that the verbose text is really for humans. Heck, I assume that we even have a persistent format only to workaround the gcc backend license. My use is temporary convenience but a bit of a while & very convenient. Anyway, I could add a runtime flag to trigger this change if necessary. All the backends (gcc, x86, C) do their own tracing as well..almost the same as this ouput, some redundancy there, but it helps to have it output while the backend is running & not just using a tool on the side -- you can see right away where it got too before failing an assertion or such. - Jay (briefly/pocket-sized-computer-aka-phone) On Sep 6, 2012, at 6:24 AM, Antony Hosking wrote: > Yes, that is a HACK. > How do you know that your change to include the name doesn?t break other parts of the tool chain. > Yes, I know that numbers are less readable, but the binding between name and numbers is explicit in the code. > I?ve never found it to be too difficult to manage with. > I think in this instance it would be better to revert to the numbers. Short-term convenience for potential sacrifice of robustness represents a step backward. > > On Sep 6, 2012, at 4:29 AM, Jay K wrote: > >> http://modula3.elegosoft.com/cgi-bin/cvsweb.cgi/cm3/m3-sys/m3middle/src/M3CG_Rd.m3.diff?r1=1.14;r2=1.15;f=u >> >> >> Tony, now I'm reviewing your changes (CVS sure doesn't make this easy!) >> Apparent problem here. >> Granted, I could have left a comment in the code as to what was going on. >> (not that the vast bulk of m3-sys is well commented!) >> >> >> >> Revision 1.15: download - view: text, markup, annotated - select for diffs >> Tue Sep 4 16:52:46 2012 (41 hours, 23 minutes ago) by hosking >> Branches: MAIN >> CVS tags: HEAD >> Diff to: previous 1.14: preferred, unified >> Changes since revision 1.14: +2 -2 lines >> Best to retain error checking on return values from Convert.ToInt. >> >> >> See here: >> >> Revision 1.14: download - view: text, markup, annotated - select for diffs >> Wed Aug 22 16:15:40 2012 (2 weeks ago) by jkrell >> Branches: MAIN >> Diff to: previous 1.13: preferred, unified >> Changes since revision 1.13: +2 -2 lines >> when printing variables and procedures: >> e.g: >> begin_procedure p.32 >> store v.33 0 Addr Addr >> >> instead: >> begin_procedure p.32.Makefile__NoteSourceFile >> store v.33.file 0 Addr Addr >> >> i.e. much more readable >> granted, less compact, not "normalized" (redundant data) >> >> I verified that m3cgcat still roundtrips. >> Not that I ever tried that before, but that is what >> the design implied the ability to do. Not that >> it is likely important these days/years/decades. >> >> The delimiting "." is chosen to stop integer parsing >> It is presumed names don't contain spaces, or whatever, >> that M3CG_Rd is ok with this extra output from M3CG_Wr. >> I only tried with one file. >> >> Note that I hacked M3CG_Rd__CvtInt to not complain about the extra text. >> It might be better to have it verify it some, like that it is dot >> followed by star or a valid pair of "__" delimited identifiers. > -------------- next part -------------- An HTML attachment was scrubbed... URL: From hosking at cs.purdue.edu Thu Sep 6 22:00:49 2012 From: hosking at cs.purdue.edu (Antony Hosking) Date: Thu, 6 Sep 2012 16:00:49 -0400 Subject: [M3devel] M3CG In-Reply-To: <443476F7-C0F2-4C51-A6F3-EDCDD6586363@gmail.com> References: <47B9A237-FD0B-4E40-9F12-938BC3D00E9E@cs.purdue.edu> <62BAB949-DBD6-405D-A6E8-0F416DEB586B@gmail.com> <3FC36B77-1F30-462C-9688-285D50351455@cs.purdue.edu> <228002BB-DE75-4320-A70F-CBB82A23D758@m3w.org> <87DABD01-259D-4373-8C77-9570869AF6FD@cs.purdue.edu> <71BE165D-B2DA-494D-9608-CCC581A32E4F@cs.purdue.edu> <38AA75B5-97B7-4D45-8B7D-45F88ED28D25@gmail.com> <6C2A07CC-92D4-4359-877D-C17B30170E0A@cs.purdue.edu> <443476F7-C0F2-4C51-A6F3-EDCDD6586363@gmail.com> Message-ID: It?s overkill. These values can always be manipulated non-persistently as INTEGER. That solves your problem. On Sep 6, 2012, at 3:34 PM, Jay wrote: > What is wrong with the options of providing the "unpacked" name or the assertion option (granted, the assertion was probably wrong)? > > - Jay (briefly/pocket-sized-computer-aka-phone) > > On Sep 6, 2012, at 10:26 AM, Antony Hosking wrote: > >> Yes, they have exactly 32 bits in size to guarantee that all targets can use them. Various tools expect this, notably m3gdb and the run-time system. Tools may manipulate them as INTEGER, but really they should be thought of as Word.T (which anyway is INTEGER on all targets). The subrange just captures the range of values they can take on if interpreted as a 2s complement signed 32-bit integer. They will likely always be manipulable as INTEGER. That will not change. >> >> So, if you want to store them in records you can easily just store as INTEGER. If you want to avoid the range check you can declare the field to be the same subrange. >> If anything changes in their representation it won?t stop you manipulating as INTEGER. If the subrange changes, which it won?t then you?ll at least get a range check failure at run time or a compiler warning. >> >> So. Use INTEGER. >> >> Live long and prosper. >> >> On Sep 6, 2012, at 4:13 AM, Jay K wrote: >> >>> I'm really confused but the approach and mentality here. >>> I believe I understand that this is not C or C++ and that there >>> are things to be gained from that. >>> >>> >>> >>> First, let me restate the "less important" questions. >>> The questions I care less about. >>> >>> >>> >>> What is the interface or abstract contractual properties of TypeUID? >>> It is exactly 32 bits in size? >>> I doubt it, but it could be. >> >>> At least 32 bits in size? >>> Well, that is kind of unavoidable, assuming a binary computer, >>> a computer that actually uses bits. >>> >>> >>> >>> No more than 32 bits in size? >>> >>> >>> >>> It can store the subrange -16_7FFFFFF - 1 .. 16_7FFFFFF? >>> That seems to me to be "part of" the interface, and possibly >>> the entire interface. Assuming a computing device that uses "bits", >>> that does imply at least 32 bits. >>> It actually conceivably does not rule out requiring 33 bits, >>> as signed-magnitude requires 33 bits to represent -16_7FFFFFF - 1. >>> I'm willing to believe we are not portable beyond two's complement systems. >>> >>> >>> >>> And where are these properties assumed and violating them would >>> cause problems? >>> >>> >>> parse.c says: >>> /*------------------------------------------------------------- type uids ---*/ >>> /* Modula-3 type uids are unsigned 32-bit values. They are passed as signed >>> decimal integers in the intermediate code, but converted to 6-byte, base 62 >>> strings of characters from here to the debugger. To avoid surprises downstream, >>> these generated strings are legal C identifiers. */ >>> >>> #define UID_SIZE 6 >>> #define NO_UID (0xFFFFFFFFUL) >>> >>> >>> (Notice this does NOT agree with TypeUID -- it says they are unsigned. >>> But the subrange includes negative numbers. I should check this and >>> the history...) >>> >>> >>> I'm hoping we delete parse.c within a year, but that's another matter. >>> The C-generating backend is coming along nicely. >>> >>> >>> So there is a dependency that they be representable within 6 base-62 >>> digits. Which I believe actually allows for a larger range, at least >>> slightly. >>> >>> >>> Ok, as I said, this isn't critical. >>> I'm willing to believe it must fit in 32 bits. >>> I'm skeptical that it must not include extra padding bits within a struct (which >>> is what the historical definition is). >>> >>> >>> Now, let's move on to my very very simple desire >>> to store these things in records, and pass them on to >>> other M3CG.T implementations. >>> >>> >>> Hypothetical dumb code, that should be simple and work. >>> Yes, I know this is dumb, but it demonstrates the point. >>> >>> >>> TYPE T1 = RECORD text: TEXT; type: TypeUID END; >>> >>> >>> M3CG.T cg1, cg2; >>> >>> >>> PROCEDURE declare_whatevere(text: TEXT; type: TypeUID) >>> VAR t1: T1; >>> BEGIN >>> t1.text := text; >>> t1.type := type; >>> cg1.declare_whatever(t1.text, t1.type); >>> cg2.declare_whatever(t1.text, t1.type); >>> END declare_whatevere; >>> >>> >>> It should be that easy, right? >>> Surely this is reasonable? >>> >>> >>> >>> TypeUID could be INTEGER, a subrange, an enum, REAL, BOOLEAN >>> REFANY, UNTRACED REF of anything, it could be a RECORD >>> with arbitrary fields. This would work. >>> It doesn't care about packing or padding. >>> It doesn't assume TypeUID is a subrange and declare the similar: >>> >>> >>> TYPE T1 = RECORD text: TEXT; type: FIRST(TypeUID) ... LAST(TypeUID) END; >>> >>> >>> If TypeUID changes to one of several other kinds of things, >>> it continues to work and be correct. >>> >>> >>> Granted, if TypeUID became some sort of "OBJECT", maybe with >>> some sort of "copy" or "clone" METHOD, then maybe this becomes wrong. >>> (This is an area where C++ is very interesting -- user defined types >>> can behave like values and be copied around correctly w/o regard >>> to the concrete implementation/representation; it is up to the type >>> implementer to make it work if he deems it. But I digress.) >>> >>> >>> Now I see a few unavoidable options. >>> >>> >>> 1) TypeUID can be any size. >>> >>> TypeUID = [-16_7FFFFFF - 1 .. 16_7FFFFFFF]; >>> >>> >>> 2) TypeUID must fit in 32 bits, but padding can be inserted >>> before/after it: >>> >>> >>> TypeUID = [-16_7FFFFFF - 1 .. 16_7FFFFFFF]; >>> <* ASSERT BITSIZE(TypeUID) >= 32 *> >>> >>> >>> That is essentially what I did, but without the assertion. >>> Cstdint.int32_t is just a lazy way of stating the same thing. >>> Granted, with an apparent interest in the size. >>> But, again, that might be an over specification. >>> >>> >>> 3) We are super afraid of making any changes and TypeUID >>> really cannot change at all, but it is reasonble >>> to allow new code like I showed. >>> >>> >>> UnpackedTypeUID = [-16_7FFFFFF - 1 .. 16_7FFFFFFF]; (* for new code to use *) >>> TypeUID = BITS 32 FOR TypeUID; (* extreme compatibility *) >>> >>> >>> I really don't think "Int32" is the way. >>> It doesn't belong here. Public in M3CG/Target. >>> It is not what I should store in a record to hold a TypeUID. >>> >>> >>> Again, imagine TypeUID is opaque/abstract to me. >>> I just need to copy it around and pass it on to other M3CG implementations. >>> It could chane to REAL for all I care. >>> I don't want to be referencing some very concrete/transparent "Int32", >>> when I'm not doing anything that depends on that implementation detail. >>> >>> >>> I even question somewhat the subrange. >>> >>> >>> In the future 32 bit hosts and targets will disappear. >>> We will have only 64bit and 128bit. >>> >>> >>> What should TypeUID be in that world? >>> >>> >>> Is the point really that it be an "INTEGER" that "fits" >>> on any host or target? >>> >>> >>> >>> Now, I grant... I might need to convert a TypeUID to a string. >>> Here we are faced with a recurring dilemna. >>> Either TypeUID is a thick/complete abtraction, and we provide >>> common operations: >>> INTERFACE TypeUID; >>> >>> >>> (* declared here for performance; actually abstract; >>> * use only with functions in this interface *) >>> TYPE T = [-16_7FFFFFF - 1 .. 16_7FFFFFFF]; >>> >>> PROCEDURE Compare(a,b:T): [-1..1]; (* like for qsort *) >>> PROCEDURE Equal(a,b:T): BOOLEAN; >>> PROCEDURE ToText(a:T): TEXT; >>> PROCEDURE Copy(from:T; VAR to:T); >>> PROCEDURE Init(VAR a:T); >>> PROCEDURE New():T; >>> >>> END TypeUID; >>> >>> MODULE TypeUID; >>> >>> (* for now, just an integer *) >>> >>> PROCEDURE Compare(a,b:T): [-1..1] (* like for qsort *) >>> BEGIN >>> (* DO NOT USE SUBTRACTION HERE. *) >>> IF a < b THEN RETURN -1; END; >>> ELSIF a > b THEN RETURN 1; END; >>> ELSE RETURN 0; END; >>> END Compare; >>> >>> PROCEDURE Equal(a,b:T): BOOLEAN = >>> BEGIN >>> RETURN a = b; >>> END Equal; >>> >>> PROCEDURE ToText(a:T): TEXT >>> BEGIN >>> return Fmt.Int(a); >>> END ToText; >>> >>> PROCEDURE Copy(from:T; VAR to:T) = >>> BEGIN >>> to := from; >>> END Copy; >>> >>> PROCEDURE Init(VAR a:T); >>> BEGIN >>> a := 0; >>> END Init; >>> >>> PROCEDURE New():T; >>> BEGIN >>> RETURN 0; >>> END New; >>> >>> END TypeUID; >>> >>> >>> OR TypeUID is very transparent, everyone knows it is an integer >>> and everyone just does integer "operations" on it. >>> And it probably can never change. >>> But hopefully they never get added. >>> >>> >>> Note of course that the abstract variation isn't very good >>> at protecting the abstration. >>> >>> >>> It is probably desirable to be able to say: >>> >>> INTERFACE >>> >>> TYPE T; (* fully opaque *) >>> >>> MODULE >>> >>> REVEAL T = INTEGER; >>> >>> >>> I understand this is hard to do efficiently. >>> You either need a really good "cross-module compiler", >>> or you need to heap allocate them all. >>> A simple compiler that produces efficient code motivates >>> revealing the type in public. >>> That is unfortunate. >>> For example, adding TypeUIDs is probably nonsense >>> and worth prohibiting. But by publically revealing >>> it is an INTEGER (essentially), extra unintended operations >>> are allowed on it. >>> >>> >>> (C++ solves... since you can have a class that is small, >>> and the clients know the size, and allocate room for it, >>> yet all the data members could be private. The language >>> is complicated, but the goal of allowing powerful efficient user >>> defined types is a good one, and achieved very well) >>> >>> >>> >>> - Jay >>> >>> >>> >>> >>> >>> Subject: Re: [M3devel] M3CG >>> From: hosking at cs.purdue.edu >>> Date: Wed, 5 Sep 2012 22:07:24 -0400 >>> CC: m3devel at elegosoft.com >>> To: jay.krell at cornell.edu >>> >>> On Sep 5, 2012, at 10:06 PM, Antony Hosking wrote: >>> >>> Jay, I just checked in the following to M3CG.i3: >>> >>> TYPE >>> Int32 = [-16_7fffffff-1 .. 16_7fffffff]; >>> TypeUID = BITS 32 FOR Int32; >>> >>> Feel free to use M3CG.Int32. >>> At least this way, if anything changes TypeUID it will be clear that someone might be relying on TypeUID. >>> >>> I meant Int32. >>> >>> >>> >>> Antony Hosking | Associate Professor | Computer Science | Purdue University >>> 305 N. University Street | West Lafayette | IN 47907 | USA >>> Mobile +1 765 427 5484 >>> >>> >>> >>> >>> >>> On Sep 5, 2012, at 8:56 PM, Jay wrote: >>> >>> And if TypeUID changes? >>> >>> I want to store a TypeUID. I want to treat it opaquely/abstractly. It can change & I'd still store it correctly & efficiently. I should not go looking at it & cloning it. That seems like sound engineering. ? >>> >>> - Jay (briefly/pocket-sized-computer-aka-phone) >>> >>> On Sep 5, 2012, at 1:41 PM, Antony Hosking wrote: >>> >>> Jay, why don't you just us a local subrange for your fields in the records and then simply assign to/from TypeUID values? >>> >>> RECORD typeid: [-16_7fffffff-1 .. 16_7fffffff] END; >>> >>> You won't pay any penalty for range checks since the subranges are exactly the same. >>> >>> On Sep 5, 2012, at 2:34 PM, Jay K wrote: >>> >>> I should really insert padding manually? >>> I don't know if I like that or not. >>> >>> >>> My code is/was something like: >>> >>> TYPE T1 = RECORD >>> text: TEXT; >>> typeid: TypeUID; >>> END; >>> >>> >>> and that errors on some platforms. >>> >>> >>> I'm not using "Multipass" right now, but it does still hold possible value. >>> We can remove multipass from m3makefile for nowif that helps. >>> >>> >>> Given a similar problem in C, I would do something like: >>> >>> /* TypeUID must fit in 32 bits, for some reason. */ >>> C_ASSERT(sizeof(TypeUID) <= sizeof(UINT32)); >>> Where C_ASSERT is in windows.h and looks like: >>> /* compile time assert */ >>> #define C_ASSERT(expression) typedef char __cassert__[(expression) ? 1 : -1]; >>> or somesuch. The error message isn't great when it fails. >>> >>> People also name this "static_assert". It is popular. >>> >>> It doesn't prohibit it from having padding around it, but it does assert it fits in 32 bits. >>> >>> I recall we can do similar in Modula-3. >>> >>> TYPE assertTypeUIDFitsIn32Bits = ARRAY [0..ORD(BITSIZE(TypeUID) <= 32)] OF INTEGER; >>> or to be more certain: >>> TYPE assertTypeUIDFitsIn32Bits = ARRAY [0..-ORD(BITSIZE(TypeUID) <= 32)] OF INTEGER; >>> >>> I'm not sure 0..0 is illegal, but I think 0 .. 1 is. >>> >>> (I sure do miss macros...this is too much syntax for a compile time assert...) >>> >>> Can we just put <* ASSERT BITSIZE(TypeUID) <= 32 *> in the .i3 file? Or elsewhere? >>> >>> >>> - Jay >>> >>> > From: hosking at cs.purdue.edu >>> > Date: Wed, 5 Sep 2012 11:36:03 -0400 >>> > To: jay.krell at cornell.edu >>> > CC: m3devel at elegosoft.com >>> > Subject: Re: [M3devel] M3CG >>> > >>> > As I recall you were having trouble with alignment, right? >>> > >>> > In which case, why not pad your record type out to a reasonably aligned value? As in: >>> > >>> > CONST PadRange = Word.LeftShift(1, BITSIZE(ADDRESS) - BITSIZE(TypeUID)) - 1; >>> > RECORD >>> > t: TypeUID; >>> > pad: BITS BITSIZE(ADDRESS) - 32 FOR [0..PadRange]; >>> > END; >>> > >>> > >>> > >>> > On Sep 5, 2012, at 11:18 AM, Antony Hosking wrote: >>> > >>> > > Remind me again why you can't use TypeUID as is? >>> > > There is nothing in the language spec that prohibits packed types in records. >>> > > >>> > > On Sep 5, 2012, at 10:50 AM, Jay K wrote: >>> > > >>> > >> This seems quite wrong from a simple engineering/design/factoring/abstraction point of view. >>> > >> >>> > >> >>> > >> Imagine I have a few of these things. They are subranges or enums. That fit in a smaller size. >>> > >> Wouldn't it be nice, to just use the type directly and get the space savings? Opportunistically? >>> > >> What if the type is a REAL or a LONGINT? >>> > >> I want the type to be opaque/abstract where that is easy and cheap and this certainly seems like an easy/cheap place to have slightly valuable opacity. >>> > >> Isn't it really good, more than "just nice" to let the type change and have a lot of code work just as well? >>> > >> Because they didn't copy around knowledge of what the type is? >>> > >> What if the type changes? >>> > >> Anyone just copying it around by exact restated typename is unaffected. >>> > >> Anyone who looked at and decided to restate the definition might type might be broken. >>> > >> >>> > >> >>> > >> And again, really -- you want to sacrifice both performance and abstraction when both are easily kept better? >>> > >> That is, I'm all for range checks to keep things "safe", safety is important, but in this case you can easily preserve safety w/o adding range checks. >>> > >> >>> > >> >>> > >> We do have enums at this layer. >>> > >> Would you suggest I take the ORD of all of those and store them in INTEGERs too? >>> > >> >>> > >> >>> > >> I am really surprised. >>> > >> >>> > >> >>> > >> - Jay >>> > >> >>> > >> >>> > >> From: hosking at cs.purdue.edu >>> > >> Date: Wed, 5 Sep 2012 10:33:58 -0400 >>> > >> To: dragisha at m3w.org >>> > >> CC: m3devel at elegosoft.com; jay.krell at cornell.edu >>> > >> Subject: Re: [M3devel] M3CG >>> > >> >>> > >> Precisely. >>> > >> >>> > >> >>> > >> On Sep 5, 2012, at 3:40 AM, Dragi?a Duri? wrote: >>> > >> >>> > >> Why holding/passing of this value in INTEGER would be a problem? As long as range checks are passed on "assignment boundaries", it is all well. >>> > >> >>> > >> It is how Modula-3 does things. >>> > >> >>> > >> -- >>> > >> Divided by a common language >>> > >> >>> > >> Dragi?a Duri? >>> > >> dragisha at m3w.org >>> > >> >>> > >> >>> > >> >>> > >> >>> > >> On Sep 4, 2012, at 10:47 PM, Jay K wrote: >>> > >> >>> > >> RECORD HoldsTypeUID: >>> > >> typeuid: [FIRST(TypeUID)..LAST(TypeUID)]; >>> > >> END? >>> > >> >>> > >> >>> > >> But what if I'm really just a holder/passer of this thing, >>> > >> and I never interpret it. Now TypeUID can't be changed >>> > >> to LONGREAL or somesuch. Ideally some code wouldn't care >>> > >> and still be correct. >>> > >> >>> > >> >>> > >> The idea is to hold the thing, pass it on, without knowing >>> > >> what it is. I want a field with the same type. >>> > >> >>> > >> >>> > >> Why does it matter if TypeUID is representable in 32 bits? >>> > >> Isn't the range the interface? >>> > >> If it wasn't for readability of all the F's, I think >>> > >> TypeUID = [-16_7FFFFFFF - 1 .. 16_7FFFFFFF]; is best. >>> > >> >>> > >> >>> > >> Do we really care about few or many bits that occupies? >>> > >> >>> > >> >>> > >> Cstdint.int32_t I agree is a bit lazy. >>> > >> Maybe something like Word.Shift(1, 31) .. Word.Not(Word.Shift(1, 31)) ? >>> > >> A bit wordy but ok. >>> > >> Maybe not correct. Not clear the start is negative. >>> > >> Maybe needs to be more like: >>> > >> >>> > >> (-Word.Not(Word.Shift(1, 31))) - 1 .. Word.Not(Word.Shift(1, 31)) >>> > >> >>> > >> >>> > >> But these bit twiddlings might then confuse people. >>> > >> So maybe having to count F's is better.. :( >>> > >> >>> > >> >>> > >> You know, what about being 32bits in size would be part of an interface? >>> > >> I don't think much/anything, but maybe. >>> > >> >>> > >> >>> > >> Do we do/allow things like bit operations on it? Index into it a certain number >>> > >> of bits? Take the address and assume BYTESIZE == 4? >>> > >> I could see those maybe occuring. Maybe. >>> > >> >>> > >> >>> > >> But I'm pretty sure they values are fairly abstract/opaque and the best anyone can do >>> > >> is format them as strings and compare them for e.g. sorting purposes, but must >>> > >> assume they are fairly sparse. >>> > >> >>> > >> >>> > >> Btw, whenever the matter of "portability to signed-magnitude" or one's complement >>> > >> comes up, I admit I get a bit confused. Two's complement is very ingrained >>> > >> in my world view. >>> > >> >>> > >> >>> > >> I agree TInt.T suffices. >>> > >> Just like CARDINAL isn't needed, INTEGER suffices. >>> > >> Cardinal.T just disallows negative numbers earlier, or at lower level, etc. >>> > >> If we had to use TInt.T and add checks in a few places that it >= 0, ok. >>> > >> It seems a little nice to put the checking in. >>> > >> >>> > >> >>> > >> - Jay >>> > >> >>> > >> >>> > >> >>> > >> >>> > >> > Subject: Re: M3CG >>> > >> > From: hosking at cs.purdue.edu >>> > >> > Date: Tue, 4 Sep 2012 13:05:34 -0400 >>> > >> > CC: m3devel at elegosoft.com >>> > >> > To: jay.krell at cornell.edu >>> > >> > >>> > >> > On Sep 4, 2012, at 12:09 PM, Jay wrote: >>> > >> > >>> > >> > > "BITS" seems to not provide any useful value. It only makes it so you can't put the type into a portable unpacked record, which is what I was doing. I either have to pack my record somehow (counting target-dependent bits??) or lay out the fields carefully in some way that all targets allow. The problem was that some targets didn't like the layout. >>> > >> > >>> > >> > For M3CG.TypeUID the BITS 32 enforces that it is always representable in 32 bits. This is a fundamental invariant of the compiler and run-time system. Removing it might allow bug creep. You don't need to pack your record. You just need a field sufficiently large to hold the value of a type id. In this instance an INTEGER field would suffice, or you can use the same subrange. >>> > >> > >>> > >> > > Given the stated range, that you'll get enough bits to store it, what is the point in giving the size too? Isn't providing just the range and no particular size, sufficient & more abstract? Granted, I went the other way. >>> > >> > >>> > >> > Only if an implementation chooses to store a subrange in as few bits as necessary. Yes, CM3 does this, but it is not guaranteed by the language spec. Here the size is the critical invariant. >>> > >> > >>> > >> > > I don't remember but guessing: >>> > >> > > >>> > >> > > >>> > >> > > Cardinal.T would be, like CARDINAL vs. INTEGER: only slightly subtley useful: same as TInt.T, but disallows negative numbers. >>> > >> > >>> > >> > But for what purpose. The target does not have CARDINAL. It only has a target integer. >>> > >> > >>> > >> > > Most likely I ran into places where a host integer/cardinal did not necessarily suffice, and so a target type was called for. >>> > >> > > >>> > >> > > >>> > >> > > I know we have places that need to use target types but don't yet. Specifically for the sizes of things like records & arrays. Otherwise we have hacks where 64bit systems declare 32bit limits. >>> > >> > >>> > >> > Again, TInt.T suffices for all of these. >>> > >> > >>> > >> > > >>> > >> > > >>> > >> > > - Jay (briefly/pocket-sized-computer-aka-phone) >>> > >> > > >>> > >> > > On Sep 4, 2012, at 7:11 AM, Antony Hosking wrote: >>> > >> > > >>> > >> > >> Jay, >>> > >> > >> >>> > >> > >> I've been looking over some of your changes to M3CG interfaces. You'll notice that I removed your import of Cstdlib.int into M3CG_Ops.i3. It does not belong there. The type as declared: >>> > >> > >> >>> > >> > >> TypeUID = BITS 32 FOR [-16_7fffffff-1 .. 16_7fffffff]; >>> > >> > >> >>> > >> > >> is correct as is. It is a 32 bit value that encodes a particular subrange, REGARDLESS of target machine. It is improper to change that definition to rely on some C type. >>> > >> > >> >>> > >> > >> I also have some other questions. Why did you add the type Cardinal.T? This seems entirely unnecessary, since targets don't have a Cardinal type. The only type they have is a target integer. All other Modula-3 ordinal types should be simulated in the compiler using TInt.T. I would advise that it be removed. Also, I don't understand why you changed descriptions of the primitive types to use this Cardinal.T instead of the original CARDINAL to hold information about the bit size, alignment, and byte size. There is no situation in which a host will need to emulate the behavior of CARDINAL for these values (all can be represented using CARDINAL no matter what the host). >>> > >> > >> >>> > >> > >> I am concerned that these changes reflect a desire on your part to change the world to fit your specific needs (whether justified or not). The interfaces defined in M3CG were carefully designed and inherit from a long code-chain going back to the 1980's and have not see huge changes since then. I strongly advise against making changes unless you have good reason, because there are a number of tools that rely on M3CG (not just those in the public sources). >>> > >> > >> >>> > >> > >> I am going to do a pass to revert some of your changes, since they are causing a number of my systems to fail to build. (cf. Niagara on tinderbox). >>> > >> > >> >>> > >> > >> I strongly advise that you try to use a private branch when developing new functionality. We as a community can then go through a revision process to vet substantive changes before merging them into the trunk. >>> > >> > >> >>> > >> > >> - Tony >>> > >> > >> >>> > >> > >>> > > >>> > >> -------------- next part -------------- An HTML attachment was scrubbed... URL: From hosking at cs.purdue.edu Thu Sep 6 23:07:25 2012 From: hosking at cs.purdue.edu (Antony Hosking) Date: Thu, 6 Sep 2012 17:07:25 -0400 Subject: [M3devel] M3CG_Rd.m3 In-Reply-To: References: <52A90EA3-BA31-426F-8FE8-5339FC6218DE@cs.purdue.edu> Message-ID: <77DBB844-B0B4-46B4-9E56-D5AFE4BC2235@cs.purdue.edu> Why not simply write it out as an extra field of the command in the text. That way you don?t need to hack the check on Int.Convert. So, wherever there is VName(u, v) M3CG_Wr would also have Txt(.name). SImilarly, when M3CG_Rd has Scan_var it would follow that with Scan_text. It just seems more principled to have both sides grok the same format instead of relying on CvtInt silently ignoring some non-integer suffix. On Sep 6, 2012, at 3:46 PM, Jay wrote: > Does there really exist other code that parses this stuff? Anything is possible but one needs to make judgement calls & confident guesses. > > > I would imagine everyone should read them with M3CG_Rd. And that everyone would really use the binary form usually, that the verbose text is really for humans. > > > Heck, I assume that we even have a persistent format only to workaround the gcc backend license. > > > My use is temporary convenience but a bit of a while & very convenient. Anyway, I could add a runtime flag to trigger this change if necessary. > > > All the backends (gcc, x86, C) do their own tracing as well..almost the same as this ouput, some redundancy there, but it helps to have it output while the backend is running & not just using a tool on the side -- you can see right away where it got too before failing an assertion or such. > > > > - Jay (briefly/pocket-sized-computer-aka-phone) > > On Sep 6, 2012, at 6:24 AM, Antony Hosking wrote: > >> Yes, that is a HACK. >> How do you know that your change to include the name doesn?t break other parts of the tool chain. >> Yes, I know that numbers are less readable, but the binding between name and numbers is explicit in the code. >> I?ve never found it to be too difficult to manage with. >> I think in this instance it would be better to revert to the numbers. Short-term convenience for potential sacrifice of robustness represents a step backward. >> >> On Sep 6, 2012, at 4:29 AM, Jay K wrote: >> >>> http://modula3.elegosoft.com/cgi-bin/cvsweb.cgi/cm3/m3-sys/m3middle/src/M3CG_Rd.m3.diff?r1=1.14;r2=1.15;f=u >>> >>> >>> Tony, now I'm reviewing your changes (CVS sure doesn't make this easy!) >>> Apparent problem here. >>> Granted, I could have left a comment in the code as to what was going on. >>> (not that the vast bulk of m3-sys is well commented!) >>> >>> >>> >>> Revision 1.15: download - view: text, markup, annotated - select for diffs >>> Tue Sep 4 16:52:46 2012 (41 hours, 23 minutes ago) by hosking >>> Branches: MAIN >>> CVS tags: HEAD >>> Diff to: previous 1.14: preferred, unified >>> Changes since revision 1.14: +2 -2 lines >>> Best to retain error checking on return values from Convert.ToInt. >>> >>> >>> See here: >>> >>> Revision 1.14: download - view: text, markup, annotated - select for diffs >>> Wed Aug 22 16:15:40 2012 (2 weeks ago) by jkrell >>> Branches: MAIN >>> Diff to: previous 1.13: preferred, unified >>> Changes since revision 1.13: +2 -2 lines >>> when printing variables and procedures: >>> e.g: >>> begin_procedure p.32 >>> store v.33 0 Addr Addr >>> >>> instead: >>> begin_procedure p.32.Makefile__NoteSourceFile >>> store v.33.file 0 Addr Addr >>> >>> i.e. much more readable >>> granted, less compact, not "normalized" (redundant data) >>> >>> I verified that m3cgcat still roundtrips. >>> Not that I ever tried that before, but that is what >>> the design implied the ability to do. Not that >>> it is likely important these days/years/decades. >>> >>> The delimiting "." is chosen to stop integer parsing >>> It is presumed names don't contain spaces, or whatever, >>> that M3CG_Rd is ok with this extra output from M3CG_Wr. >>> I only tried with one file. >>> >>> Note that I hacked M3CG_Rd__CvtInt to not complain about the extra text. >>> It might be better to have it verify it some, like that it is dot >>> followed by star or a valid pair of "__" delimited identifiers. >> -------------- next part -------------- An HTML attachment was scrubbed... URL: From hosking at cs.purdue.edu Thu Sep 6 23:13:14 2012 From: hosking at cs.purdue.edu (Antony Hosking) Date: Thu, 6 Sep 2012 17:13:14 -0400 Subject: [M3devel] a "need" for multi-pass m3cg (or different order of calls) In-Reply-To: References: Message-ID: <63514538-FEF2-46DE-BE41-85E2D2CF37CD@cs.purdue.edu> I?ll respond to this in more detail, but briefly, I object strongly to a multipass m3cg. If you need multiple passes then you probably need a different internal representation (just like m3cg has a different internal representation). M3CG is a simple single-pass linear representation of a program. If you need multiple passes to understand it then that is your problem. I imagine that any backend will itself need to be multipass anyway (if it is to do something useful). I think your C backend should be multipass too. It certainly will need to read M3CG IR and import it into some reasonable internal representation. This is exactly the strategy I am taking with M3CG to LLVM IR. I will have some minor tweaks to M3CG just to lift its level of abstraction slightly (to better communicate typed indexing of arrays and fields, for example). But I see no need to make M3CG do any more heavy lifting. On Sep 6, 2012, at 4:40 AM, Jay K wrote: > /* The following is legal C but not C++: */ > > > struct Foo_t; > typedef struct Foo_t Foo_t; > static struct Foo_t Foo; /* illegal C++; C forward/tentative definition */ > > int F1(void) { return *(int*)&Foo; } > > struct Foo_t { int i; }; > static Foo_t Foo = { 123 }; > > > This is a reason that either > 1) I "need" to make M3C.m3 "multi pass" > 2) or at least buffer everything in memory > in multiple pieces and then concat at the end > > > I could also make it less efficient: > > > struct Foo_t; /* segment */ > typedef struct Foo_t Foo_t; > static struct Foo_t * /*const*/ Foo; > > > int F1(void) { return *(int*)&Foo; } > > > struct Foo_t { int i; }; > static Foo_t _Foo = { 123 }; > static Foo_t* /*const*/ Foo = &_Foo; > > But that seems unfortunate. > > > I will want to generate C++ at some point, for efficient portable exception > handling. But that comes later. > > > Also later, the C code needs a reordering in order to refer to fields in "segments". > > > - Jay -------------- next part -------------- An HTML attachment was scrubbed... URL: From jay.krell at cornell.edu Fri Sep 7 04:23:01 2012 From: jay.krell at cornell.edu (Jay K) Date: Fri, 7 Sep 2012 02:23:01 +0000 Subject: [M3devel] a "need" for multi-pass m3cg (or different order of calls) In-Reply-To: <63514538-FEF2-46DE-BE41-85E2D2CF37CD@cs.purdue.edu> References: , <63514538-FEF2-46DE-BE41-85E2D2CF37CD@cs.purdue.edu> Message-ID: I'm not really suggesting any change to any existing code.. Though, the frontend, I gather, is already multi-pass, so it might be nice if it did things in an order more convenient for backends.e.g. it'd be nice if all the import_procedure calls came in before any begin_procedure;as it stands, many come in early, and then more come in in the middle of code. I'm motivating that my C/C++ generating backend could benefit from internally having multiple passes. Which might be convenient to implement via a general mechanism for combining multiple "partial" passes. Such mechanism would naturally "temporarily persist" a faithful m3cg representation in memory. Very similar to the existing temporary binary files we feed to parse.c, but without all the encoding for compactness. i.e. an array of records I guess I'll still try to ignore this matter for now. I'm getting by with one pass that generates invalid C++ but valid C. Possibly I can provide a "nicely reordering m3cg" that buffers it all up and then plays it back in a slightly better order, that is more amenable to a simple implementation, e.g. again getting all the import_procedure calls in before any begin_procedure. Moving all the init_* calls to near the start instead of near the end. etc. i.e. I'm not really sure multiple passes are needed, it's just thatthe current ordering is kind of surprising sometimes. - JaySubject: Re: [M3devel] a "need" for multi-pass m3cg (or different order of calls) From: hosking at cs.purdue.edu Date: Thu, 6 Sep 2012 17:13:14 -0400 CC: m3devel at elegosoft.com To: jay.krell at cornell.edu I?ll respond to this in more detail, but briefly, I object strongly to a multipass m3cg. If you need multiple passes then you probably need a different internal representation (just like m3cg has a different internal representation). M3CG is a simple single-pass linear representation of a program. If you need multiple passes to understand it then that is your problem. I imagine that any backend will itself need to be multipass anyway (if it is to do something useful). I think your C backend should be multipass too. It certainly will need to read M3CG IR and import it into some reasonable internal representation. This is exactly the strategy I am taking with M3CG to LLVM IR. I will have some minor tweaks to M3CG just to lift its level of abstraction slightly (to better communicate typed indexing of arrays and fields, for example). But I see no need to make M3CG do any more heavy lifting. On Sep 6, 2012, at 4:40 AM, Jay K wrote:/* The following is legal C but not C++: */ struct Foo_t;typedef struct Foo_t Foo_t;static struct Foo_t Foo; /* illegal C++; C forward/tentative definition */ int F1(void) { return *(int*)&Foo; } struct Foo_t { int i; };static Foo_t Foo = { 123 }; This is a reason that either1) I "need" to make M3C.m3 "multi pass"2) or at least buffer everything in memoryin multiple pieces and then concat at the end I could also make it less efficient: struct Foo_t; /* segment */ typedef struct Foo_t Foo_t; static struct Foo_t * /*const*/ Foo; int F1(void) { return *(int*)&Foo; } struct Foo_t { int i; }; static Foo_t _Foo = { 123 }; static Foo_t* /*const*/ Foo = &_Foo; But that seems unfortunate. I will want to generate C++ at some point, for efficient portable exceptionhandling. But that comes later. Also later, the C code needs a reordering in order to refer to fields in "segments". - Jay -------------- next part -------------- An HTML attachment was scrubbed... URL: From hendrik at topoi.pooq.com Fri Sep 7 20:21:02 2012 From: hendrik at topoi.pooq.com (Hendrik Boom) Date: Fri, 7 Sep 2012 14:21:02 -0400 Subject: [M3devel] a "need" for multi-pass m3cg (or different order of calls) In-Reply-To: References: Message-ID: <20120907182102.GA14787@topoi.pooq.com> On Thu, Sep 06, 2012 at 08:40:46AM +0000, Jay K wrote: > /* The following is legal C but not C++: */ > > struct Foo_t;typedef struct Foo_t Foo_t;static struct Foo_t Foo; > /* illegal C++; C forward/tentative definition */ > int F1(void) { return *(int*)&Foo; } > struct Foo_t { int i; };static Foo_t Foo = { 123 }; The analogous problem in LLVM is why I couldn't use the LLV<-parse-tree building tools to generate LLVM code from Algol 68. Which is kind of stupid, since it shouldn't actually *need* any of this type information until the parse tree is complete and it starts to generate code. But it insists on having a completely defined type before it allows me to enter code involving it into the still-incomplete parse tree, which it's designed to let me sprout in any order I choose. - hendrik From hosking at cs.purdue.edu Fri Sep 7 22:10:19 2012 From: hosking at cs.purdue.edu (Antony Hosking) Date: Fri, 7 Sep 2012 16:10:19 -0400 Subject: [M3devel] a "need" for multi-pass m3cg (or different order of calls) In-Reply-To: References: , <63514538-FEF2-46DE-BE41-85E2D2CF37CD@cs.purdue.edu> Message-ID: Sorry, I should have read more closely. You are right. Yes, I do believe that when generating C code you will need multiple passes to accumulate stuff to be dumped out together. For example, I assume that to handle nested functions that you will construct a local "frame" struct for the function, containing a pointer to it?s outer scope frame struct plus all the local variables having "up_level==true". There is no other way to do static chains portably in C. A pointer to this frame struct will serve as the static link to inner-scope functions. On Sep 6, 2012, at 10:23 PM, Jay K wrote: > I'm not really suggesting any change to any existing code.. > > > Though, the frontend, I gather, is already multi-pass, > so it might be nice if it did things in an order more > convenient for backends. > e.g. it'd be nice if all the import_procedure calls came in before any begin_procedure; > as it stands, many come in early, and then more come in in the middle of code. > > > I'm motivating that my C/C++ generating backend could > benefit from internally having multiple passes. > > > Which might be convenient to implement via a general > mechanism for combining multiple "partial" passes. > > > Such mechanism would naturally "temporarily persist" > a faithful m3cg representation in memory. > Very similar to the existing temporary binary files > we feed to parse.c, but without all the encoding for > compactness. i.e. an array of records > > > I guess I'll still try to ignore this matter for now. > I'm getting by with one pass that generates invalid C++ but valid C. > > > Possibly I can provide a "nicely reordering m3cg" > that buffers it all up and then plays it back > in a slightly better order, that is more amenable > to a simple implementation, e.g. again getting > all the import_procedure calls in before any begin_procedure. > > > Moving all the init_* calls to near the start instead of near the end. > etc. > > > i.e. I'm not really sure multiple passes are needed, it's just that > the current ordering is kind of surprising sometimes. > > > > - Jay > Subject: Re: [M3devel] a "need" for multi-pass m3cg (or different order of calls) > From: hosking at cs.purdue.edu > Date: Thu, 6 Sep 2012 17:13:14 -0400 > CC: m3devel at elegosoft.com > To: jay.krell at cornell.edu > > I?ll respond to this in more detail, but briefly, I object strongly to a multipass m3cg. If you need multiple passes then you probably need a different internal representation (just like m3cg has a different internal representation). M3CG is a simple single-pass linear representation of a program. If you need multiple passes to understand it then that is your problem. I imagine that any backend will itself need to be multipass anyway (if it is to do something useful). I think your C backend should be multipass too. It certainly will need to read M3CG IR and import it into some reasonable internal representation. This is exactly the strategy I am taking with M3CG to LLVM IR. I will have some minor tweaks to M3CG just to lift its level of abstraction slightly (to better communicate typed indexing of arrays and fields, for example). But I see no need to make M3CG do any more heavy lifting. > > On Sep 6, 2012, at 4:40 AM, Jay K wrote: > > /* The following is legal C but not C++: */ > > > struct Foo_t; > typedef struct Foo_t Foo_t; > static struct Foo_t Foo; /* illegal C++; C forward/tentative definition */ > > int F1(void) { return *(int*)&Foo; } > > struct Foo_t { int i; }; > static Foo_t Foo = { 123 }; > > > This is a reason that either > 1) I "need" to make M3C.m3 "multi pass" > 2) or at least buffer everything in memory > in multiple pieces and then concat at the end > > > I could also make it less efficient: > > > struct Foo_t; /* segment */ > typedef struct Foo_t Foo_t; > static struct Foo_t * /*const*/ Foo; > > > int F1(void) { return *(int*)&Foo; } > > > struct Foo_t { int i; }; > static Foo_t _Foo = { 123 }; > static Foo_t* /*const*/ Foo = &_Foo; > > But that seems unfortunate. > > > I will want to generate C++ at some point, for efficient portable exception > handling. But that comes later. > > > Also later, the C code needs a reordering in order to refer to fields in "segments". > > > - Jay -------------- next part -------------- An HTML attachment was scrubbed... URL: From jay.krell at cornell.edu Fri Sep 7 23:29:35 2012 From: jay.krell at cornell.edu (Jay) Date: Fri, 7 Sep 2012 14:29:35 -0700 Subject: [M3devel] M3CG_Rd.m3 In-Reply-To: <77DBB844-B0B4-46B4-9E56-D5AFE4BC2235@cs.purdue.edu> References: <52A90EA3-BA31-426F-8FE8-5339FC6218DE@cs.purdue.edu> <77DBB844-B0B4-46B4-9E56-D5AFE4BC2235@cs.purdue.edu> Message-ID: <6D7E8B00-D7A2-45B1-ADD0-C4C21748D900@gmail.com> Ah. That is also an incompatible change but slightly cleaner. Ok? - Jay (briefly/pocket-sized-computer-aka-phone) On Sep 6, 2012, at 2:07 PM, Antony Hosking wrote: > Why not simply write it out as an extra field of the command in the text. > That way you don?t need to hack the check on Int.Convert. > > So, wherever there is VName(u, v) M3CG_Wr would also have Txt(.name). > SImilarly, when M3CG_Rd has Scan_var it would follow that with Scan_text. > It just seems more principled to have both sides grok the same format instead of relying on CvtInt silently ignoring some non-integer suffix. > > On Sep 6, 2012, at 3:46 PM, Jay wrote: > >> Does there really exist other code that parses this stuff? Anything is possible but one needs to make judgement calls & confident guesses. >> >> >> I would imagine everyone should read them with M3CG_Rd. And that everyone would really use the binary form usually, that the verbose text is really for humans. >> >> >> Heck, I assume that we even have a persistent format only to workaround the gcc backend license. >> >> >> My use is temporary convenience but a bit of a while & very convenient. Anyway, I could add a runtime flag to trigger this change if necessary. >> >> >> All the backends (gcc, x86, C) do their own tracing as well..almost the same as this ouput, some redundancy there, but it helps to have it output while the backend is running & not just using a tool on the side -- you can see right away where it got too before failing an assertion or such. >> >> >> >> - Jay (briefly/pocket-sized-computer-aka-phone) >> >> On Sep 6, 2012, at 6:24 AM, Antony Hosking wrote: >> >>> Yes, that is a HACK. >>> How do you know that your change to include the name doesn?t break other parts of the tool chain. >>> Yes, I know that numbers are less readable, but the binding between name and numbers is explicit in the code. >>> I?ve never found it to be too difficult to manage with. >>> I think in this instance it would be better to revert to the numbers. Short-term convenience for potential sacrifice of robustness represents a step backward. >>> >>> On Sep 6, 2012, at 4:29 AM, Jay K wrote: >>> >>>> http://modula3.elegosoft.com/cgi-bin/cvsweb.cgi/cm3/m3-sys/m3middle/src/M3CG_Rd.m3.diff?r1=1.14;r2=1.15;f=u >>>> >>>> >>>> Tony, now I'm reviewing your changes (CVS sure doesn't make this easy!) >>>> Apparent problem here. >>>> Granted, I could have left a comment in the code as to what was going on. >>>> (not that the vast bulk of m3-sys is well commented!) >>>> >>>> >>>> >>>> Revision 1.15: download - view: text, markup, annotated - select for diffs >>>> Tue Sep 4 16:52:46 2012 (41 hours, 23 minutes ago) by hosking >>>> Branches: MAIN >>>> CVS tags: HEAD >>>> Diff to: previous 1.14: preferred, unified >>>> Changes since revision 1.14: +2 -2 lines >>>> Best to retain error checking on return values from Convert.ToInt. >>>> >>>> >>>> See here: >>>> >>>> Revision 1.14: download - view: text, markup, annotated - select for diffs >>>> Wed Aug 22 16:15:40 2012 (2 weeks ago) by jkrell >>>> Branches: MAIN >>>> Diff to: previous 1.13: preferred, unified >>>> Changes since revision 1.13: +2 -2 lines >>>> when printing variables and procedures: >>>> e.g: >>>> begin_procedure p.32 >>>> store v.33 0 Addr Addr >>>> >>>> instead: >>>> begin_procedure p.32.Makefile__NoteSourceFile >>>> store v.33.file 0 Addr Addr >>>> >>>> i.e. much more readable >>>> granted, less compact, not "normalized" (redundant data) >>>> >>>> I verified that m3cgcat still roundtrips. >>>> Not that I ever tried that before, but that is what >>>> the design implied the ability to do. Not that >>>> it is likely important these days/years/decades. >>>> >>>> The delimiting "." is chosen to stop integer parsing >>>> It is presumed names don't contain spaces, or whatever, >>>> that M3CG_Rd is ok with this extra output from M3CG_Wr. >>>> I only tried with one file. >>>> >>>> Note that I hacked M3CG_Rd__CvtInt to not complain about the extra text. >>>> It might be better to have it verify it some, like that it is dot >>>> followed by star or a valid pair of "__" delimited identifiers. >>> > -------------- next part -------------- An HTML attachment was scrubbed... URL: From hendrik at topoi.pooq.com Sat Sep 8 02:36:19 2012 From: hendrik at topoi.pooq.com (Hendrik Boom) Date: Fri, 7 Sep 2012 20:36:19 -0400 Subject: [M3devel] a "need" for multi-pass m3cg (or different order of calls) In-Reply-To: References: <63514538-FEF2-46DE-BE41-85E2D2CF37CD@cs.purdue.edu> Message-ID: <20120908003619.GA9672@topoi.pooq.com> On Fri, Sep 07, 2012 at 04:10:19PM -0400, Antony Hosking wrote: > Sorry, I should have read more closely. You are right. > Yes, I do believe that when generating C code you will need multiple > passes to accumulate stuff to be dumped out together. > For example, I assume that to handle nested functions that you will > construct a local "frame" struct for the function, containing a > pointer to it?s outer scope frame struct plus all the local variables > having "up_level==true". There is no other way to do static chains > portably in C. A pointer to this frame struct will serve as the > static link to inner-scope functions. This is why I (once I had machines with gigabytes of RAM) devised the following data structure in RAM: It's a string with insertion points. Initially, it's empty, with one insertion point. At any insertion point, anytine, you can insert a string or an insertion point, either before or after the insertion point. Thus at any place in code generation where you might have to accumulate declarations while you go on generating code that uses them elsewhere, you set up two insertion points -- one where the declarations go, and one where the other code goes. When you're done, you just write it all out in sequence. It eats storage, but is very simple to use. In the old days, about four decades ago, I was thinking of bulding such a data structure on disk. Instead I generated code with a lot of macro-time GOTO statemtents to rearrange the code as needed. Using RAM is so much easier. -- hendrik > > > On Sep 6, 2012, at 10:23 PM, Jay K wrote: > > > I'm not really suggesting any change to any existing code.. > > > > > > Though, the frontend, I gather, is already multi-pass, > > so it might be nice if it did things in an order more > > convenient for backends. > > e.g. it'd be nice if all the import_procedure calls came in before any begin_procedure; > > as it stands, many come in early, and then more come in in the middle of code. > > > > > > I'm motivating that my C/C++ generating backend could > > benefit from internally having multiple passes. > > > > > > Which might be convenient to implement via a general > > mechanism for combining multiple "partial" passes. > > > > > > Such mechanism would naturally "temporarily persist" > > a faithful m3cg representation in memory. > > Very similar to the existing temporary binary files > > we feed to parse.c, but without all the encoding for > > compactness. i.e. an array of records > > > > > > I guess I'll still try to ignore this matter for now. > > I'm getting by with one pass that generates invalid C++ but valid C. > > > > > > Possibly I can provide a "nicely reordering m3cg" > > that buffers it all up and then plays it back > > in a slightly better order, that is more amenable > > to a simple implementation, e.g. again getting > > all the import_procedure calls in before any begin_procedure. You could use a mechanism like mine. I could send you my C code for it if you like. Or you could write the inport procedure calls out to one file and the begin_procedures to another and subsequently concatenate them. -- hendrik From jay.krell at cornell.edu Sat Sep 8 03:58:17 2012 From: jay.krell at cornell.edu (Jay K) Date: Sat, 8 Sep 2012 01:58:17 +0000 Subject: [M3devel] a "need" for multi-pass m3cg (or different order of calls) In-Reply-To: <20120908003619.GA9672@topoi.pooq.com> References: , <63514538-FEF2-46DE-BE41-85E2D2CF37CD@cs.purdue.edu>, , , <20120908003619.GA9672@topoi.pooq.com> Message-ID: That is kind of what I need, but it can be done in a specific way. currently I have: print(u, "blah blah") I can instead go through and say: gen_code(u, "blah blah")gen_declaration(u, "blah blah")gen_segment_initializer(u, segment, "blah blah") each function is tied to a specific variablelater I'll just print all the variables OR I can decompose it into passes.Have several very small m3cg implementations.That share data.One that just pays attention to import_procedures. Builds up data for those. Other later passes would mark in that what they used.One that just pays attention to initializers. Builds up data for those.Very late pass would go through various data and print it all. It is surprising what one pass with minimal separate buffers can do.e.g. you need buffering to build up parameter lists.Actually, I guess Iwekeep around all the "procs", and their associated data, for the lifetime of a unit.An "IR" if you will -- just some structs/records with pointers. The "frame" stuff I think I already have correct and working.But maybe not.It seems declare_locals sometimes happen before any code, sometimes in the middle of code.I at least handle the case where up_level locals are declared before there is any code.If they come in at arbitrary points in the code, that might be too late.I can put in checks for that. Not difficult. Anyway... I'll get it figured out... hopefully within a few weeks cm3 will link, and then I'll move on to try to apply this backend to AMD64_NT. Once that is working there will be some controversy what to do with it for existing targets, and directions of like, making it the one and only target.(That will require a fair amount of work, as I've said, the current C output is target-specific, due to endian, wordsize, jmpbuf size, and Win32 vs. Posix...Win32 vs. Posix is particularly difficult to deal with......eh... I guess what we there is generate both/all sets of C code and then the problem is really at the "makefile" level...so maybe that's not difficult...hm..actually I think this is wrong..I think we can have separate interfaces, with different types/constants, imported into common code.....maybe we do something like generate headers that are #included.....under #ifdef....? I don't know..later, much much later....) - Jay > Date: Fri, 7 Sep 2012 20:36:19 -0400 > From: hendrik at topoi.pooq.com > To: m3devel at elegosoft.com > Subject: Re: [M3devel] a "need" for multi-pass m3cg (or different order of calls) > > On Fri, Sep 07, 2012 at 04:10:19PM -0400, Antony Hosking wrote: > > Sorry, I should have read more closely. You are right. > > Yes, I do believe that when generating C code you will need multiple > > passes to accumulate stuff to be dumped out together. > > For example, I assume that to handle nested functions that you will > > construct a local "frame" struct for the function, containing a > > pointer to it?s outer scope frame struct plus all the local variables > > having "up_level==true". There is no other way to do static chains > > portably in C. A pointer to this frame struct will serve as the > > static link to inner-scope functions. > > This is why I (once I had machines with gigabytes of RAM) devised the > following data structure in RAM: > > It's a string with insertion points. Initially, it's empty, with one > insertion point. At any insertion point, anytine, you can insert a > string or an insertion point, either before or after the insertion point. > > Thus at any place in code generation where you might have to accumulate > declarations while you go on generating code that uses them elsewhere, > you set up two insertion points -- one where the declarations go, and > one where the other code goes. > > When you're done, you just write it all out in sequence. > > It eats storage, but is very simple to use. > > In the old days, about four decades ago, I was thinking of bulding such > a data structure on disk. Instead I generated code with a lot of > macro-time GOTO statemtents to rearrange the code as needed. > > Using RAM is so much easier. > > -- hendrik > > > > > > > On Sep 6, 2012, at 10:23 PM, Jay K wrote: > > > > > I'm not really suggesting any change to any existing code.. > > > > > > > > > Though, the frontend, I gather, is already multi-pass, > > > so it might be nice if it did things in an order more > > > convenient for backends. > > > e.g. it'd be nice if all the import_procedure calls came in before any begin_procedure; > > > as it stands, many come in early, and then more come in in the middle of code. > > > > > > > > > I'm motivating that my C/C++ generating backend could > > > benefit from internally having multiple passes. > > > > > > > > > Which might be convenient to implement via a general > > > mechanism for combining multiple "partial" passes. > > > > > > > > > Such mechanism would naturally "temporarily persist" > > > a faithful m3cg representation in memory. > > > Very similar to the existing temporary binary files > > > we feed to parse.c, but without all the encoding for > > > compactness. i.e. an array of records > > > > > > > > > I guess I'll still try to ignore this matter for now. > > > I'm getting by with one pass that generates invalid C++ but valid C. > > > > > > > > > Possibly I can provide a "nicely reordering m3cg" > > > that buffers it all up and then plays it back > > > in a slightly better order, that is more amenable > > > to a simple implementation, e.g. again getting > > > all the import_procedure calls in before any begin_procedure. > > You could use a mechanism like mine. I could send you my C code for it > if you like. Or you could write the inport procedure calls out to one > file and the begin_procedures to another and subsequently concatenate > them. > > -- hendrik -------------- next part -------------- An HTML attachment was scrubbed... URL: From hosking at cs.purdue.edu Sat Sep 8 04:20:25 2012 From: hosking at cs.purdue.edu (Antony Hosking) Date: Fri, 7 Sep 2012 22:20:25 -0400 Subject: [M3devel] M3CG_Rd.m3 In-Reply-To: <6D7E8B00-D7A2-45B1-ADD0-C4C21748D900@gmail.com> References: <52A90EA3-BA31-426F-8FE8-5339FC6218DE@cs.purdue.edu> <77DBB844-B0B4-46B4-9E56-D5AFE4BC2235@cs.purdue.edu> <6D7E8B00-D7A2-45B1-ADD0-C4C21748D900@gmail.com> Message-ID: <795EDE14-EE14-40C1-AB7A-964120101B30@cs.purdue.edu> I?m thinking more of a comment... Both M3CG_Rd and M3CG_Wr would be compatible. Antony Hosking | Associate Professor | Computer Science | Purdue University 305 N. University Street | West Lafayette | IN 47907 | USA Mobile +1 765 427 5484 On Sep 7, 2012, at 5:29 PM, Jay wrote: > Ah. That is also an incompatible change but slightly cleaner. Ok? > > - Jay (briefly/pocket-sized-computer-aka-phone) > > On Sep 6, 2012, at 2:07 PM, Antony Hosking wrote: > >> Why not simply write it out as an extra field of the command in the text. >> That way you don?t need to hack the check on Int.Convert. >> >> So, wherever there is VName(u, v) M3CG_Wr would also have Txt(.name). >> SImilarly, when M3CG_Rd has Scan_var it would follow that with Scan_text. >> It just seems more principled to have both sides grok the same format instead of relying on CvtInt silently ignoring some non-integer suffix. >> >> On Sep 6, 2012, at 3:46 PM, Jay wrote: >> >>> Does there really exist other code that parses this stuff? Anything is possible but one needs to make judgement calls & confident guesses. >>> >>> >>> I would imagine everyone should read them with M3CG_Rd. And that everyone would really use the binary form usually, that the verbose text is really for humans. >>> >>> >>> Heck, I assume that we even have a persistent format only to workaround the gcc backend license. >>> >>> >>> My use is temporary convenience but a bit of a while & very convenient. Anyway, I could add a runtime flag to trigger this change if necessary. >>> >>> >>> All the backends (gcc, x86, C) do their own tracing as well..almost the same as this ouput, some redundancy there, but it helps to have it output while the backend is running & not just using a tool on the side -- you can see right away where it got too before failing an assertion or such. >>> >>> >>> >>> - Jay (briefly/pocket-sized-computer-aka-phone) >>> >>> On Sep 6, 2012, at 6:24 AM, Antony Hosking wrote: >>> >>>> Yes, that is a HACK. >>>> How do you know that your change to include the name doesn?t break other parts of the tool chain. >>>> Yes, I know that numbers are less readable, but the binding between name and numbers is explicit in the code. >>>> I?ve never found it to be too difficult to manage with. >>>> I think in this instance it would be better to revert to the numbers. Short-term convenience for potential sacrifice of robustness represents a step backward. >>>> >>>> On Sep 6, 2012, at 4:29 AM, Jay K wrote: >>>> >>>>> http://modula3.elegosoft.com/cgi-bin/cvsweb.cgi/cm3/m3-sys/m3middle/src/M3CG_Rd.m3.diff?r1=1.14;r2=1.15;f=u >>>>> >>>>> >>>>> Tony, now I'm reviewing your changes (CVS sure doesn't make this easy!) >>>>> Apparent problem here. >>>>> Granted, I could have left a comment in the code as to what was going on. >>>>> (not that the vast bulk of m3-sys is well commented!) >>>>> >>>>> >>>>> >>>>> Revision 1.15: download - view: text, markup, annotated - select for diffs >>>>> Tue Sep 4 16:52:46 2012 (41 hours, 23 minutes ago) by hosking >>>>> Branches: MAIN >>>>> CVS tags: HEAD >>>>> Diff to: previous 1.14: preferred, unified >>>>> Changes since revision 1.14: +2 -2 lines >>>>> Best to retain error checking on return values from Convert.ToInt. >>>>> >>>>> >>>>> See here: >>>>> >>>>> Revision 1.14: download - view: text, markup, annotated - select for diffs >>>>> Wed Aug 22 16:15:40 2012 (2 weeks ago) by jkrell >>>>> Branches: MAIN >>>>> Diff to: previous 1.13: preferred, unified >>>>> Changes since revision 1.13: +2 -2 lines >>>>> when printing variables and procedures: >>>>> e.g: >>>>> begin_procedure p.32 >>>>> store v.33 0 Addr Addr >>>>> >>>>> instead: >>>>> begin_procedure p.32.Makefile__NoteSourceFile >>>>> store v.33.file 0 Addr Addr >>>>> >>>>> i.e. much more readable >>>>> granted, less compact, not "normalized" (redundant data) >>>>> >>>>> I verified that m3cgcat still roundtrips. >>>>> Not that I ever tried that before, but that is what >>>>> the design implied the ability to do. Not that >>>>> it is likely important these days/years/decades. >>>>> >>>>> The delimiting "." is chosen to stop integer parsing >>>>> It is presumed names don't contain spaces, or whatever, >>>>> that M3CG_Rd is ok with this extra output from M3CG_Wr. >>>>> I only tried with one file. >>>>> >>>>> Note that I hacked M3CG_Rd__CvtInt to not complain about the extra text. >>>>> It might be better to have it verify it some, like that it is dot >>>>> followed by star or a valid pair of "__" delimited identifiers. >>>> >> -------------- next part -------------- An HTML attachment was scrubbed... URL: From hendrik at topoi.pooq.com Sat Sep 8 04:59:20 2012 From: hendrik at topoi.pooq.com (Hendrik Boom) Date: Fri, 7 Sep 2012 22:59:20 -0400 Subject: [M3devel] a "need" for multi-pass m3cg (or different order of calls) In-Reply-To: References: <63514538-FEF2-46DE-BE41-85E2D2CF37CD@cs.purdue.edu> <20120908003619.GA9672@topoi.pooq.com> Message-ID: <20120908025920.GB9672@topoi.pooq.com> On Sat, Sep 08, 2012 at 01:58:17AM +0000, Jay K wrote: > That is kind of what I need, but it can be done in a specific way. currently I have: print(u, "blah blah") I can instead go through and say: gen_code(u, "blah blah")gen_declaration(u, "blah blah")gen_segment_initializer(u, segment, "blah blah") each function is tied to a specific variablelater I'll just print all the variables OR I can decompose it into passes.Have several very small m3cg implementations.That share data.One that just pays attention to import_procedures. Builds up data for those. Other later passes would mark in that what they used.One that just pays attention to initializers. Builds up data for those.Very late pass would go through various data and print it all. It is surprising what one pass with minimal separate buffers can do.e.g. you need buffering to build up parameter lists.Actually, I guess Iwekeep around all the "procs", and their associated data, for the lifetime of a unit.An "IR" if you will -- just some structs/records with pointers. The "frame" stuff I think I already have cor > rect and working.But maybe not.It seems declare_locals sometimes happen before any code, sometimes in the middle of code.I at least handle the case where up_level locals are declared before there is any code.If they come in at arbitrary points in the code, that might be too late.I can put in checks for that. Not difficult. Anyway... I'll get it figured out... hopefully within a few weeks cm3 will link, and then I'll move on to try to apply this backend to AMD64_NT. Once that is working there will be some controversy what to do with it for existing targets, and directions of like, making it the one and only target.(That will require a fair amount of work, as I've said, the current C output is target-specific, due to endian, wordsize, jmpbuf size, and Win32 vs. Posix...Win32 vs. Posix is particularly difficult to deal with......eh... I guess what we there is generate both/all sets of C code and then the problem is really at the "makefile" level...so maybe that's not difficult...hm..actually I think this is w > rong..I think we can have separate interfaces, with different types/constants, imported into common code.....maybe we do something like generate headers that are #included.....under #ifdef....? I don't know..later, much much later....) - Jay I don't know if it would help to look at what the smarteiffel compiler does. It also generates C code, so it may have to face the same problems. It might be useful if your and its object code were compatible, too. Hmm. More current is Gambit/C, a conpiler that generates C code for Scheme sosurce. Too many of these garbage-collected languages won't talk to one another. I know; I'm drifting off to pie in the sky. -- hendrik From jay.krell at cornell.edu Sat Sep 8 06:06:09 2012 From: jay.krell at cornell.edu (Jay K) Date: Sat, 8 Sep 2012 04:06:09 +0000 Subject: [M3devel] M3CG_Rd.m3 In-Reply-To: <795EDE14-EE14-40C1-AB7A-964120101B30@cs.purdue.edu> References: <52A90EA3-BA31-426F-8FE8-5339FC6218DE@cs.purdue.edu> <77DBB844-B0B4-46B4-9E56-D5AFE4BC2235@cs.purdue.edu> <6D7E8B00-D7A2-45B1-ADD0-C4C21748D900@gmail.com>, <795EDE14-EE14-40C1-AB7A-964120101B30@cs.purdue.edu> Message-ID: They can occur anywhere and are always skipped?I can try it.Not a big deal.I'm pretty far up the learning curve by now. :) - Jay Subject: Re: [M3devel] M3CG_Rd.m3 From: hosking at cs.purdue.edu Date: Fri, 7 Sep 2012 22:20:25 -0400 CC: m3devel at elegosoft.com To: jay.krell at cornell.edu I?m thinking more of a comment... Both M3CG_Rd and M3CG_Wr would be compatible. Antony Hosking | Associate Professor | Computer Science | Purdue University305 N. University Street | West Lafayette | IN 47907 | USAMobile +1 765 427 5484 On Sep 7, 2012, at 5:29 PM, Jay wrote:Ah. That is also an incompatible change but slightly cleaner. Ok? - Jay (briefly/pocket-sized-computer-aka-phone) On Sep 6, 2012, at 2:07 PM, Antony Hosking wrote: Why not simply write it out as an extra field of the command in the text.That way you don?t need to hack the check on Int.Convert. So, wherever there is VName(u, v) M3CG_Wr would also have Txt(.name).SImilarly, when M3CG_Rd has Scan_var it would follow that with Scan_text.It just seems more principled to have both sides grok the same format instead of relying on CvtInt silently ignoring some non-integer suffix. On Sep 6, 2012, at 3:46 PM, Jay wrote:Does there really exist other code that parses this stuff? Anything is possible but one needs to make judgement calls & confident guesses. I would imagine everyone should read them with M3CG_Rd. And that everyone would really use the binary form usually, that the verbose text is really for humans. Heck, I assume that we even have a persistent format only to workaround the gcc backend license. My use is temporary convenience but a bit of a while & very convenient. Anyway, I could add a runtime flag to trigger this change if necessary. All the backends (gcc, x86, C) do their own tracing as well..almost the same as this ouput, some redundancy there, but it helps to have it output while the backend is running & not just using a tool on the side -- you can see right away where it got too before failing an assertion or such. - Jay (briefly/pocket-sized-computer-aka-phone) On Sep 6, 2012, at 6:24 AM, Antony Hosking wrote: Yes, that is a HACK.How do you know that your change to include the name doesn?t break other parts of the tool chain.Yes, I know that numbers are less readable, but the binding between name and numbers is explicit in the code.I?ve never found it to be too difficult to manage with.I think in this instance it would be better to revert to the numbers. Short-term convenience for potential sacrifice of robustness represents a step backward. On Sep 6, 2012, at 4:29 AM, Jay K wrote:http://modula3.elegosoft.com/cgi-bin/cvsweb.cgi/cm3/m3-sys/m3middle/src/M3CG_Rd.m3.diff?r1=1.14;r2=1.15;f=u Tony, now I'm reviewing your changes (CVS sure doesn't make this easy!)Apparent problem here.Granted, I could have left a comment in the code as to what was going on.(not that the vast bulk of m3-sys is well commented!) Revision 1.15: download - view: text, markup, annotated - select for diffsTue Sep 4 16:52:46 2012 (41 hours, 23 minutes ago) by hoskingBranches: MAINCVS tags: HEADDiff to: previous 1.14: preferred, unifiedChanges since revision 1.14: +2 -2 linesBest to retain error checking on return values from Convert.ToInt. See here: Revision 1.14: download - view: text, markup, annotated - select for diffsWed Aug 22 16:15:40 2012 (2 weeks ago) by jkrellBranches: MAINDiff to: previous 1.13: preferred, unifiedChanges since revision 1.13: +2 -2 lineswhen printing variables and procedures:e.g: begin_procedure p.32 store v.33 0 Addr Addr instead: begin_procedure p.32.Makefile__NoteSourceFile store v.33.file 0 Addr Addr i.e. much more readablegranted, less compact, not "normalized" (redundant data) I verified that m3cgcat still roundtrips. Not that I ever tried that before, but that is what the design implied the ability to do. Not that it is likely important these days/years/decades. The delimiting "." is chosen to stop integer parsingIt is presumed names don't contain spaces, or whatever,that M3CG_Rd is ok with this extra output from M3CG_Wr.I only tried with one file. Note that I hacked M3CG_Rd__CvtInt to not complain about the extra text.It might be better to have it verify it some, like that it is dotfollowed by star or a valid pair of "__" delimited identifiers. -------------- next part -------------- An HTML attachment was scrubbed... URL: From dragisha at m3w.org Sat Sep 8 09:23:14 2012 From: dragisha at m3w.org (=?utf-8?Q?Dragi=C5=A1a_Duri=C4=87?=) Date: Sat, 8 Sep 2012 09:23:14 +0200 Subject: [M3devel] pre-report Message-ID: <40145A43-9420-4ECF-899C-3CC015ED2B99@m3w.org> Just got this, many times in a row :) === % cm3 --- building in ../AMD64_DARWIN --- new source -> compiling Descriptors.m3 *** *** runtime error: *** <*ASSERT*> failed. *** file "../src/values/Formal.m3", line 689 *** zsh: abort cm3 % cm3 -? Critical Mass Modula-3 version d5.9.0 last updated: 2010-07-21 compiled: 2011-03-23 04:04:18 configuration: /usr/local/cm3/bin/cm3.cfg host: AMD64_DARWIN target: AMD64_DARWIN -- Divided by a common language Dragi?a Duri? dragisha at m3w.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 495 bytes Desc: Message signed with OpenPGP using GPGMail URL: From jay.krell at cornell.edu Sat Sep 8 09:56:09 2012 From: jay.krell at cornell.edu (Jay K) Date: Sat, 8 Sep 2012 07:56:09 +0000 Subject: [M3devel] "C-generating backend progress report, that nobody asked for" :) Message-ID: This directory has a bunch of the .mc/.ic files that constitute cm3 (not the whole system, but m3core, libm3, sysutils, m3front, m3middle, m3quake, m3back..)Maybe I forgot some.This represents a lot of success.I give line counts to show I'm actually doing anything. jbook2:t1 jay$ gcc -m64 -c *.cASCII.ic.c:332:3: warning: integer constant is so large that it is unsignedASCII.ic.c:332: warning: this decimal constant is unsigned only in ISO C90FPU.ic.c:195: warning: conflicting types for built-in function ?ldexp?Interval.ic.c:432:3: warning: integer constant is so large that it is unsignedInterval.ic.c:432: warning: this decimal constant is unsigned only in ISO C90M3CG_BinRd.mc.c: In function ?M3CG_BinRd__Scan_type?:M3CG_BinRd.mc.c:3494: warning: comparison is always false due to limited range of data typeM3Process.mc.c: In function ?M3Process__Interrupt?:M3Process.mc.c:268: error: ?Usignal__SIGINT? undeclared (first use in this function)M3Process.mc.c:268: error: (Each undeclared identifier is reported only onceM3Process.mc.c:268: error: for each function it appears in.)M3Process.mc.c: In function ?M3Process__Abort?:M3Process.mc.c:333: error: ?Usignal__SIGKILL? undeclared (first use in this function)Math.ic.c:294: warning: conflicting types for built-in function ?cabs?Math.ic.c:302: warning: conflicting types for built-in function ?ldexp?Math.ic.c:325: warning: conflicting types for built-in function ?jn?Math.ic.c:335: warning: conflicting types for built-in function ?yn?Rect.ic.c:657:3: warning: integer constant is so large that it is unsignedRect.ic.c:657: warning: this decimal constant is unsigned only in ISO C90Rect.ic.c:659:3: warning: integer constant is so large that it is unsignedRect.ic.c:659: warning: this decimal constant is unsigned only in ISO C90Region.ic.c:518:3: warning: integer constant is so large that it is unsignedRegion.ic.c:518: warning: this decimal constant is unsigned only in ISO C90Region.ic.c:520:3: warning: integer constant is so large that it is unsignedRegion.ic.c:520: warning: this decimal constant is unsigned only in ISO C90TWord.mc.c: In function ?TWord__Or?:TWord.mc.c:2411: warning: comparison is always false due to limited range of data typeTWord.mc.c:2411: warning: comparison is always false due to limited range of data typeTWord.mc.c: In function ?TWord__Xor?:TWord.mc.c:2470: warning: comparison is always false due to limited range of data typeTWord.mc.c:2470: warning: comparison is always false due to limited range of data typeTextConv.ic.c:361:3: warning: integer constant is so large that it is unsignedTextConv.ic.c:361: warning: this decimal constant is unsigned only in ISO C90jbook2:t1 jay$ ls -l *.mc *.ic |wc -l 700jbook2:t1 jay$ ls -l *.c |wc -l 700jbook2:t1 jay$ wc -l *.c | grep total 662454 total -------------- next part -------------- An HTML attachment was scrubbed... URL: From dragisha at m3w.org Sat Sep 8 10:00:27 2012 From: dragisha at m3w.org (=?utf-8?Q?Dragi=C5=A1a_Duri=C4=87?=) Date: Sat, 8 Sep 2012 10:00:27 +0200 Subject: [M3devel] =?windows-1252?q?pre-report=3B_and_the_verdict_is=3A_pa?= =?windows-1252?q?cked_field_used_as_a_formal=85_ASSERT_instead_of_warning?= =?windows-1252?q?/error?= In-Reply-To: <40145A43-9420-4ECF-899C-3CC015ED2B99@m3w.org> References: <40145A43-9420-4ECF-899C-3CC015ED2B99@m3w.org> Message-ID: -- Divided by a common language Dragi?a Duri? dragisha at m3w.org On Sep 8, 2012, at 9:23 AM, Dragi?a Duri? wrote: > Just got this, many times in a row :) > > === > % cm3 > --- building in ../AMD64_DARWIN --- > > new source -> compiling Descriptors.m3 > > > *** > *** runtime error: > *** <*ASSERT*> failed. > *** file "../src/values/Formal.m3", line 689 > *** > > zsh: abort cm3 > > > % cm3 -? > Critical Mass Modula-3 version d5.9.0 > last updated: 2010-07-21 > compiled: 2011-03-23 04:04:18 > configuration: /usr/local/cm3/bin/cm3.cfg > host: AMD64_DARWIN > target: AMD64_DARWIN > > -- > Divided by a common language > > Dragi?a Duri? > dragisha at m3w.org > > > > -------------- next part -------------- An HTML attachment was scrubbed... URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 495 bytes Desc: Message signed with OpenPGP using GPGMail URL: From jay.krell at cornell.edu Sat Sep 8 10:15:51 2012 From: jay.krell at cornell.edu (Jay K) Date: Sat, 8 Sep 2012 08:15:51 +0000 Subject: [M3devel] types in check_hi/lo/range? Message-ID: check_lo (t: IType; READONLY i: Target.Int; code: RuntimeError);(* IF (s0.t < i) THEN abort(code) *) check_hi (t: IType; READONLY i: Target.Int; code: RuntimeError);(* IF (i < s0.t) THEN abort(code) *) check_range (t: IType; READONLY a, b: Target.Int; code: RuntimeError);(* IF (s0.t < a) OR (b < s0.t) THEN abort(code) *) Is it a good idea to consider "t" to apply to "i", "a", and "b", not just "s0"? I was just using TInt.ToText but I'm putting in the diligence nowof appending U for UINT8/UINT16/UINT32and LL or I64 for INT64.On integer literals. Thank you, - Jay -------------- next part -------------- An HTML attachment was scrubbed... URL: From jay.krell at cornell.edu Sat Sep 8 11:50:19 2012 From: jay.krell at cornell.edu (Jay K) Date: Sat, 8 Sep 2012 09:50:19 +0000 Subject: [M3devel] C math interop.. Message-ID: This also occured in FPU.ic Math.ic.c:217: error: conflicting types for ?signgam?/usr/include/architecture/i386/math.h:543: error: previous declaration of ?signgam? was hereMath.ic.c:298: warning: conflicting types for built-in function ?cabs?Math.ic.c:302: error: conflicting types for ?frexp?Math.ic.c:306: error: conflicting types for ?ldexp?Math.ic.c:310: error: conflicting types for ?modf?Math.ic.c:329: error: conflicting types for ?jn?Math.ic.c:339: error: conflicting types for ?yn? Generally int vs. INTEGER confusion.To fix these errors, I'm going to provide C wrappers for these functions, and everything else in the file. This hints at some new way to do interop, fast like the old way, but with static checking,where the generated C #includes the relevant .h files.But this is a bit abstraction bending -- the backend isn't supposed to be doing these checks.The frontend does.You'd have to have changes in the <* extern *> pragma like - this isn't an actual function signature, necessarily..and the address can'tnecessarily be taken, but something close enough to this will materialize from a C header - specify the C header Imagine a world with a good C backend, and a good other one.Modules that interoperate with C could be sent off to the C backend automatically. Anyway, just crazy stuff, nothing really happening here beyond I'll add C wrappers. :) When I get to it, #include along with our declarations..it will be interestingto see if things match. And ...There will be problems. We have one UINT32 type in the generated C.Win32 has unsigned int and unsigned long used kind of interchangably.There will be clashes. - Jay -------------- next part -------------- An HTML attachment was scrubbed... URL: From jay.krell at cornell.edu Sat Sep 8 11:54:32 2012 From: jay.krell at cornell.edu (Jay K) Date: Sat, 8 Sep 2012 09:54:32 +0000 Subject: [M3devel] C math interop.. In-Reply-To: References: Message-ID: hm. The advantage of not having wrappers, is you can declare things that don't exist.Maybe only on some platforms.So I'll probably fix the declarations.For scaleb/ldexp/sqrt too.(similar to what I did for strcat/strcpy in Cstring.i3 -- no wrappers, to avoid OpenBSD link warning/error) Later, - Jay From: jay.krell at cornell.edu To: m3devel at elegosoft.com Date: Sat, 8 Sep 2012 09:50:19 +0000 Subject: [M3devel] C math interop.. This also occured in FPU.ic Math.ic.c:217: error: conflicting types for ?signgam?/usr/include/architecture/i386/math.h:543: error: previous declaration of ?signgam? was hereMath.ic.c:298: warning: conflicting types for built-in function ?cabs?Math.ic.c:302: error: conflicting types for ?frexp?Math.ic.c:306: error: conflicting types for ?ldexp?Math.ic.c:310: error: conflicting types for ?modf?Math.ic.c:329: error: conflicting types for ?jn?Math.ic.c:339: error: conflicting types for ?yn? Generally int vs. INTEGER confusion.To fix these errors, I'm going to provide C wrappers for these functions, and everything else in the file. This hints at some new way to do interop, fast like the old way, but with static checking,where the generated C #includes the relevant .h files.But this is a bit abstraction bending -- the backend isn't supposed to be doing these checks.The frontend does.You'd have to have changes in the <* extern *> pragma like - this isn't an actual function signature, necessarily..and the address can'tnecessarily be taken, but something close enough to this will materialize from a C header - specify the C header Imagine a world with a good C backend, and a good other one.Modules that interoperate with C could be sent off to the C backend automatically. Anyway, just crazy stuff, nothing really happening here beyond I'll add C wrappers. :) When I get to it, #include along with our declarations..it will be interestingto see if things match. And ...There will be problems. We have one UINT32 type in the generated C.Win32 has unsigned int and unsigned long used kind of interchangably.There will be clashes. - Jay -------------- next part -------------- An HTML attachment was scrubbed... URL: From dragisha at m3w.org Sun Sep 9 08:32:38 2012 From: dragisha at m3w.org (=?utf-8?Q?Dragi=C5=A1a_Duri=C4=87?=) Date: Sun, 9 Sep 2012 08:32:38 +0200 Subject: [M3devel] "C-generating backend progress report, that nobody asked for" :) In-Reply-To: References: Message-ID: Extremelly Good Thing. Cleaning up of whole system needed to generate new backend also enables other people to do things in future. I hope somebody will take on LLVM :). -- Divided by a common language Dragi?a Duri? dragisha at m3w.org On Sep 8, 2012, at 9:56 AM, Jay K wrote: > This directory has a bunch of the .mc/.ic files that constitute cm3 (not the whole system, but m3core, libm3, sysutils, m3front, m3middle, m3quake, m3back..) > Maybe I forgot some. > This represents a lot of success. > I give line counts to show I'm actually doing anything. > > > jbook2:t1 jay$ gcc -m64 -c *.c > ASCII.ic.c:332:3: warning: integer constant is so large that it is unsigned > ASCII.ic.c:332: warning: this decimal constant is unsigned only in ISO C90 > FPU.ic.c:195: warning: conflicting types for built-in function ?ldexp? > Interval.ic.c:432:3: warning: integer constant is so large that it is unsigned > Interval.ic.c:432: warning: this decimal constant is unsigned only in ISO C90 > M3CG_BinRd.mc.c: In function ?M3CG_BinRd__Scan_type?: > M3CG_BinRd.mc.c:3494: warning: comparison is always false due to limited range of data type > M3Process.mc.c: In function ?M3Process__Interrupt?: > M3Process.mc.c:268: error: ?Usignal__SIGINT? undeclared (first use in this function) > M3Process.mc.c:268: error: (Each undeclared identifier is reported only once > M3Process.mc.c:268: error: for each function it appears in.) > M3Process.mc.c: In function ?M3Process__Abort?: > M3Process.mc.c:333: error: ?Usignal__SIGKILL? undeclared (first use in this function) > Math.ic.c:294: warning: conflicting types for built-in function ?cabs? > Math.ic.c:302: warning: conflicting types for built-in function ?ldexp? > Math.ic.c:325: warning: conflicting types for built-in function ?jn? > Math.ic.c:335: warning: conflicting types for built-in function ?yn? > Rect.ic.c:657:3: warning: integer constant is so large that it is unsigned > Rect.ic.c:657: warning: this decimal constant is unsigned only in ISO C90 > Rect.ic.c:659:3: warning: integer constant is so large that it is unsigned > Rect.ic.c:659: warning: this decimal constant is unsigned only in ISO C90 > Region.ic.c:518:3: warning: integer constant is so large that it is unsigned > Region.ic.c:518: warning: this decimal constant is unsigned only in ISO C90 > Region.ic.c:520:3: warning: integer constant is so large that it is unsigned > Region.ic.c:520: warning: this decimal constant is unsigned only in ISO C90 > TWord.mc.c: In function ?TWord__Or?: > TWord.mc.c:2411: warning: comparison is always false due to limited range of data type > TWord.mc.c:2411: warning: comparison is always false due to limited range of data type > TWord.mc.c: In function ?TWord__Xor?: > TWord.mc.c:2470: warning: comparison is always false due to limited range of data type > TWord.mc.c:2470: warning: comparison is always false due to limited range of data type > TextConv.ic.c:361:3: warning: integer constant is so large that it is unsigned > TextConv.ic.c:361: warning: this decimal constant is unsigned only in ISO C90 > jbook2:t1 jay$ ls -l *.mc *.ic |wc -l > 700 > jbook2:t1 jay$ ls -l *.c |wc -l > 700 > jbook2:t1 jay$ wc -l *.c | grep total > 662454 total > > -------------- next part -------------- An HTML attachment was scrubbed... URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 495 bytes Desc: Message signed with OpenPGP using GPGMail URL: From hendrik at topoi.pooq.com Sun Sep 9 16:39:43 2012 From: hendrik at topoi.pooq.com (Hendrik Boom) Date: Sun, 9 Sep 2012 10:39:43 -0400 Subject: [M3devel] "C-generating backend progress report, that nobody asked for" :) In-Reply-To: References: Message-ID: <20120909143943.GA32665@topoi.pooq.com> On Sun, Sep 09, 2012 at 08:32:38AM +0200, Dragi?a Duri? wrote: > Extremelly Good Thing. > > Cleaning up of whole system needed to generate new backend also enables other people to do things in future. > > I hope somebody will take on LLVM :). LLVM is very much a slightly lower-level C. It even has a declaration-before-use rules. Some of them even apply to the methods for parse-tree construction (though it's supposed to be random access). I suspect the best way to take on LLVM will be to start from Jay's C generator. -- hendrik From hosking at cs.purdue.edu Sun Sep 9 16:48:42 2012 From: hosking at cs.purdue.edu (Antony Hosking) Date: Sun, 9 Sep 2012 10:48:42 -0400 Subject: [M3devel] "C-generating backend progress report, that nobody asked for" :) In-Reply-To: References: Message-ID: I?m looking at it... First step is to lift slightly the level of M3CG to use properly typed memory access, instead of untyped address + offset. On Sep 9, 2012, at 2:32 AM, Dragi?a Duri? wrote: > I hope somebody will take on LLVM :). > -------------- next part -------------- An HTML attachment was scrubbed... URL: From jay.krell at cornell.edu Sun Sep 9 16:53:32 2012 From: jay.krell at cornell.edu (Jay) Date: Sun, 9 Sep 2012 07:53:32 -0700 Subject: [M3devel] "C-generating backend progress report, that nobody asked for" :) In-Reply-To: References: Message-ID: <84C67B7F-A915-4DE8-B14C-44E6F87DE85D@gmail.com> Btw, can this include "segment"/globals? Can they each be separate named variables? At least some of them? - Jay (briefly/pocket-sized-computer-aka-phone) On Sep 9, 2012, at 7:48 AM, Antony Hosking wrote: > I?m looking at it... > > First step is to lift slightly the level of M3CG to use properly typed memory access, instead of untyped address + offset. > > On Sep 9, 2012, at 2:32 AM, Dragi?a Duri? wrote: > >> I hope somebody will take on LLVM :). >> > -------------- next part -------------- An HTML attachment was scrubbed... URL: From hosking at cs.purdue.edu Sun Sep 9 17:05:08 2012 From: hosking at cs.purdue.edu (Antony Hosking) Date: Sun, 9 Sep 2012 11:05:08 -0400 Subject: [M3devel] "C-generating backend progress report, that nobody asked for" :) In-Reply-To: <84C67B7F-A915-4DE8-B14C-44E6F87DE85D@gmail.com> References: <84C67B7F-A915-4DE8-B14C-44E6F87DE85D@gmail.com> Message-ID: Yes, agreed, these need to be properly typed too. First step will be to lift the M3CG interface. Problem: The compiler needs to control layout so that the run-time system knows where to find things. This means that we need to assert alignments and layouts produced by the backend are the same as those in the front-end. LLVM has nice ways to do this. How will we do it in the C backend? Does C have sufficient control over alignment? On Sep 9, 2012, at 10:53 AM, Jay wrote: > Btw, can this include "segment"/globals? Can they each be separate named variables? At least some of them? > > > - Jay (briefly/pocket-sized-computer-aka-phone) > > On Sep 9, 2012, at 7:48 AM, Antony Hosking wrote: > >> I?m looking at it... >> >> First step is to lift slightly the level of M3CG to use properly typed memory access, instead of untyped address + offset. >> >> On Sep 9, 2012, at 2:32 AM, Dragi?a Duri? wrote: >> >>> I hope somebody will take on LLVM :). >>> >> -------------- next part -------------- An HTML attachment was scrubbed... URL: From dragisha at m3w.org Sun Sep 9 20:49:17 2012 From: dragisha at m3w.org (=?utf-8?Q?Dragi=C5=A1a_Duri=C4=87?=) Date: Sun, 9 Sep 2012 20:49:17 +0200 Subject: [M3devel] "C-generating backend progress report, that nobody asked for" :) In-Reply-To: References: <84C67B7F-A915-4DE8-B14C-44E6F87DE85D@gmail.com> Message-ID: Can we have network order packing too, while you are lifting level of description? On Sep 9, 2012, at 5:05 PM, Antony Hosking wrote: > Yes, agreed, these need to be properly typed too. > First step will be to lift the M3CG interface. > Problem: The compiler needs to control layout so that the run-time system knows where to find things. This means that we need to assert alignments and layouts produced by the backend are the same as those in the front-end. LLVM has nice ways to do this. How will we do it in the C backend? Does C have sufficient control over alignment? > > On Sep 9, 2012, at 10:53 AM, Jay wrote: > >> Btw, can this include "segment"/globals? Can they each be separate named variables? At least some of them? >> >> >> - Jay (briefly/pocket-sized-computer-aka-phone) >> >> On Sep 9, 2012, at 7:48 AM, Antony Hosking wrote: >> >>> I?m looking at it... >>> >>> First step is to lift slightly the level of M3CG to use properly typed memory access, instead of untyped address + offset. >>> >>> On Sep 9, 2012, at 2:32 AM, Dragi?a Duri? wrote: >>> >>>> I hope somebody will take on LLVM :). >>>> >>> > -------------- next part -------------- An HTML attachment was scrubbed... URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 495 bytes Desc: Message signed with OpenPGP using GPGMail URL: From hosking at cs.purdue.edu Sun Sep 9 21:22:02 2012 From: hosking at cs.purdue.edu (Antony Hosking) Date: Sun, 9 Sep 2012 15:22:02 -0400 Subject: [M3devel] "C-generating backend progress report, that nobody asked for" :) In-Reply-To: References: <84C67B7F-A915-4DE8-B14C-44E6F87DE85D@gmail.com> Message-ID: <9748E313-E0EF-45FA-A01F-DE0C58FDDED7@cs.purdue.edu> I mis-spoke. I think LLVM can cope with much the same as we currently have. Front-end will continue to compute alignments and layouts. We can assert the front-end?s datalayout by passing it to LLVM explicitly, which will complain if it does not match the actual target. This is a rather nice feature of LLVM in that it allows us to retain control while having LLVM optimize accordingly. On Sep 9, 2012, at 11:05 AM, Antony Hosking wrote: > Yes, agreed, these need to be properly typed too. > First step will be to lift the M3CG interface. > Problem: The compiler needs to control layout so that the run-time system knows where to find things. This means that we need to assert alignments and layouts produced by the backend are the same as those in the front-end. LLVM has nice ways to do this. How will we do it in the C backend? Does C have sufficient control over alignment? > > On Sep 9, 2012, at 10:53 AM, Jay wrote: > >> Btw, can this include "segment"/globals? Can they each be separate named variables? At least some of them? >> >> >> - Jay (briefly/pocket-sized-computer-aka-phone) >> >> On Sep 9, 2012, at 7:48 AM, Antony Hosking wrote: >> >>> I?m looking at it... >>> >>> First step is to lift slightly the level of M3CG to use properly typed memory access, instead of untyped address + offset. >>> >>> On Sep 9, 2012, at 2:32 AM, Dragi?a Duri? wrote: >>> >>>> I hope somebody will take on LLVM :). >>>> >>> > -------------- next part -------------- An HTML attachment was scrubbed... URL: From jay.krell at cornell.edu Sun Sep 9 22:05:05 2012 From: jay.krell at cornell.edu (Jay) Date: Sun, 9 Sep 2012 13:05:05 -0700 Subject: [M3devel] "C-generating backend progress report, that nobody asked for" :) In-Reply-To: References: <84C67B7F-A915-4DE8-B14C-44E6F87DE85D@gmail.com> Message-ID: Alignment: I'd like to understand what the runtime really needs. Can't it produce data structures that contain the addresses of things, no matter where they end up? Or offsets? As well, can't we have the frontend be very conservative? Align each basic int & float type to its size, even if not required? Didn't I already do that? E.g. 64 bit ints don't generally need 64bit alignment on 32 bit targets, but I'm ok giving it. Front end can insert padding explicitly. (this area bit me, you may recall, gcc/cygwin was aligning 64bit double float to 64bits, adding in padding where frontend didn't..I had to peel the onion quite a bit to debug that...) We could also generate compile-time asserts that frontend & backend layouts match. ? Anyway, yes, gcc and Visual C++ have extensions that inhibit any padding-for-alignment. If push-comes-to shove, we can use such extensions. gcc extensions are commonly available in other compilers also. Probably in Sun cc & clang for example. I'm not sure we need this, but it is available. In the shorter term the need is maybe more likely. (eventually, I still dream of testing on AIX, VMs, Irix, HPUX -- not gcc, & maybe a K&R option. :) ) I also wonder about a hybrid where the frontend computes suggested but not mandatory offsets/layout. Provide integers & symbols, like. So to keep existing backends working more easily. Maybe that is a waste of effort. Packing: indeed, I would like to eliminate the endian-dependentness in the frontend. And word-size knowledge. (Yes, I know I repeat myself.) - Jay (briefly/pocket-sized-computer-aka-phone) On Sep 9, 2012, at 11:49 AM, Dragi?a Duri? wrote: > Can we have network order packing too, while you are lifting level of description? > > > On Sep 9, 2012, at 5:05 PM, Antony Hosking wrote: > >> Yes, agreed, these need to be properly typed too. >> First step will be to lift the M3CG interface. >> Problem: The compiler needs to control layout so that the run-time system knows where to find things. This means that we need to assert alignments and layouts produced by the backend are the same as those in the front-end. LLVM has nice ways to do this. How will we do it in the C backend? Does C have sufficient control over alignment? >> >> On Sep 9, 2012, at 10:53 AM, Jay wrote: >> >>> Btw, can this include "segment"/globals? Can they each be separate named variables? At least some of them? >>> >>> >>> - Jay (briefly/pocket-sized-computer-aka-phone) >>> >>> On Sep 9, 2012, at 7:48 AM, Antony Hosking wrote: >>> >>>> I?m looking at it... >>>> >>>> First step is to lift slightly the level of M3CG to use properly typed memory access, instead of untyped address + offset. >>>> >>>> On Sep 9, 2012, at 2:32 AM, Dragi?a Duri? wrote: >>>> >>>>> I hope somebody will take on LLVM :). >>>>> >>>> >> > -------------- next part -------------- An HTML attachment was scrubbed... URL: From jay.krell at cornell.edu Sun Sep 9 22:07:55 2012 From: jay.krell at cornell.edu (Jay) Date: Sun, 9 Sep 2012 13:07:55 -0700 Subject: [M3devel] "C-generating backend progress report, that nobody asked for" :) In-Reply-To: <9748E313-E0EF-45FA-A01F-DE0C58FDDED7@cs.purdue.edu> References: <84C67B7F-A915-4DE8-B14C-44E6F87DE85D@gmail.com> <9748E313-E0EF-45FA-A01F-DE0C58FDDED7@cs.purdue.edu> Message-ID: <4CD63AEF-523B-423F-9690-7DEDBF8BEFFC@gmail.com> The current method stinks for stock debugging. As I understand, globals are combined into structs & the fields all have generated names, & global records are flattened therein. It works. But stock debuggers see garbage. - Jay (briefly/pocket-sized-computer-aka-phone) On Sep 9, 2012, at 12:22 PM, Antony Hosking wrote: > I mis-spoke. I think LLVM can cope with much the same as we currently have. Front-end will continue to compute alignments and layouts. We can assert the front-end?s datalayout by passing it to LLVM explicitly, which will complain if it does not match the actual target. This is a rather nice feature of LLVM in that it allows us to retain control while having LLVM optimize accordingly. > > On Sep 9, 2012, at 11:05 AM, Antony Hosking wrote: > >> Yes, agreed, these need to be properly typed too. >> First step will be to lift the M3CG interface. >> Problem: The compiler needs to control layout so that the run-time system knows where to find things. This means that we need to assert alignments and layouts produced by the backend are the same as those in the front-end. LLVM has nice ways to do this. How will we do it in the C backend? Does C have sufficient control over alignment? >> >> On Sep 9, 2012, at 10:53 AM, Jay wrote: >> >>> Btw, can this include "segment"/globals? Can they each be separate named variables? At least some of them? >>> >>> >>> - Jay (briefly/pocket-sized-computer-aka-phone) >>> >>> On Sep 9, 2012, at 7:48 AM, Antony Hosking wrote: >>> >>>> I?m looking at it... >>>> >>>> First step is to lift slightly the level of M3CG to use properly typed memory access, instead of untyped address + offset. >>>> >>>> On Sep 9, 2012, at 2:32 AM, Dragi?a Duri? wrote: >>>> >>>>> I hope somebody will take on LLVM :). >>>>> >>>> >> > -------------- next part -------------- An HTML attachment was scrubbed... URL: From jay.krell at cornell.edu Sun Sep 9 22:27:47 2012 From: jay.krell at cornell.edu (Jay) Date: Sun, 9 Sep 2012 13:27:47 -0700 Subject: [M3devel] "C-generating backend progress report, that nobody asked for" :) In-Reply-To: <4CD63AEF-523B-423F-9690-7DEDBF8BEFFC@gmail.com> References: <84C67B7F-A915-4DE8-B14C-44E6F87DE85D@gmail.com> <9748E313-E0EF-45FA-A01F-DE0C58FDDED7@cs.purdue.edu> <4CD63AEF-523B-423F-9690-7DEDBF8BEFFC@gmail.com> Message-ID: <1CABCD12-94EA-4BDD-9753-7C5402732D1F@gmail.com> If the records are fixed..that helps a lot, & not clear what is ideal actually..the re cords do then offer kind of nice syntax for access..but constants vs variables are split. I'd also prefer seperate variables to give the optimizer a chance to remove unused globals. That seems valuable.. Like, transform to idiomatic C where reasonable & possible... - Jay (briefly/pocket-sized-computer-aka-phone) On Sep 9, 2012, at 1:07 PM, Jay wrote: > The current method stinks for stock debugging. As I understand, globals are combined into structs & the fields all have generated names, & global records are flattened therein. > > > It works. But stock debuggers see garbage. > > > - Jay (briefly/pocket-sized-computer-aka-phone) > > On Sep 9, 2012, at 12:22 PM, Antony Hosking wrote: > >> I mis-spoke. I think LLVM can cope with much the same as we currently have. Front-end will continue to compute alignments and layouts. We can assert the front-end?s datalayout by passing it to LLVM explicitly, which will complain if it does not match the actual target. This is a rather nice feature of LLVM in that it allows us to retain control while having LLVM optimize accordingly. >> >> On Sep 9, 2012, at 11:05 AM, Antony Hosking wrote: >> >>> Yes, agreed, these need to be properly typed too. >>> First step will be to lift the M3CG interface. >>> Problem: The compiler needs to control layout so that the run-time system knows where to find things. This means that we need to assert alignments and layouts produced by the backend are the same as those in the front-end. LLVM has nice ways to do this. How will we do it in the C backend? Does C have sufficient control over alignment? >>> >>> On Sep 9, 2012, at 10:53 AM, Jay wrote: >>> >>>> Btw, can this include "segment"/globals? Can they each be separate named variables? At least some of them? >>>> >>>> >>>> - Jay (briefly/pocket-sized-computer-aka-phone) >>>> >>>> On Sep 9, 2012, at 7:48 AM, Antony Hosking wrote: >>>> >>>>> I?m looking at it... >>>>> >>>>> First step is to lift slightly the level of M3CG to use properly typed memory access, instead of untyped address + offset. >>>>> >>>>> On Sep 9, 2012, at 2:32 AM, Dragi?a Duri? wrote: >>>>> >>>>>> I hope somebody will take on LLVM :). >>>>>> >>>>> >>> >> -------------- next part -------------- An HTML attachment was scrubbed... URL: From hosking at cs.purdue.edu Mon Sep 10 02:54:12 2012 From: hosking at cs.purdue.edu (Antony Hosking) Date: Sun, 9 Sep 2012 20:54:12 -0400 Subject: [M3devel] "C-generating backend progress report, that nobody asked for" :) In-Reply-To: <4CD63AEF-523B-423F-9690-7DEDBF8BEFFC@gmail.com> References: <84C67B7F-A915-4DE8-B14C-44E6F87DE85D@gmail.com> <9748E313-E0EF-45FA-A01F-DE0C58FDDED7@cs.purdue.edu> <4CD63AEF-523B-423F-9690-7DEDBF8BEFFC@gmail.com> Message-ID: <43C4B30F-24AB-4421-923B-9F32C1807AF5@cs.purdue.edu> Stock debuggers are designed for C. They generally will not be able to grok M3. Better to use M3 run-time type information as per m3gdb. See 10.1145/143103.143112. On Sep 9, 2012, at 4:07 PM, Jay wrote: > The current method stinks for stock debugging. As I understand, globals are combined into structs & the fields all have generated names, & global records are flattened therein. > > > It works. But stock debuggers see garbage. > > > - Jay (briefly/pocket-sized-computer-aka-phone) > > On Sep 9, 2012, at 12:22 PM, Antony Hosking wrote: > >> I mis-spoke. I think LLVM can cope with much the same as we currently have. Front-end will continue to compute alignments and layouts. We can assert the front-end?s datalayout by passing it to LLVM explicitly, which will complain if it does not match the actual target. This is a rather nice feature of LLVM in that it allows us to retain control while having LLVM optimize accordingly. >> >> On Sep 9, 2012, at 11:05 AM, Antony Hosking wrote: >> >>> Yes, agreed, these need to be properly typed too. >>> First step will be to lift the M3CG interface. >>> Problem: The compiler needs to control layout so that the run-time system knows where to find things. This means that we need to assert alignments and layouts produced by the backend are the same as those in the front-end. LLVM has nice ways to do this. How will we do it in the C backend? Does C have sufficient control over alignment? >>> >>> On Sep 9, 2012, at 10:53 AM, Jay wrote: >>> >>>> Btw, can this include "segment"/globals? Can they each be separate named variables? At least some of them? >>>> >>>> >>>> - Jay (briefly/pocket-sized-computer-aka-phone) >>>> >>>> On Sep 9, 2012, at 7:48 AM, Antony Hosking wrote: >>>> >>>>> I?m looking at it... >>>>> >>>>> First step is to lift slightly the level of M3CG to use properly typed memory access, instead of untyped address + offset. >>>>> >>>>> On Sep 9, 2012, at 2:32 AM, Dragi?a Duri? wrote: >>>>> >>>>>> I hope somebody will take on LLVM :). >>>>>> >>>>> >>> >> -------------- next part -------------- An HTML attachment was scrubbed... URL: From hendrik at topoi.pooq.com Mon Sep 10 03:23:57 2012 From: hendrik at topoi.pooq.com (Hendrik Boom) Date: Sun, 9 Sep 2012 21:23:57 -0400 Subject: [M3devel] "C-generating backend progress report, that nobody asked for" :) In-Reply-To: References: <84C67B7F-A915-4DE8-B14C-44E6F87DE85D@gmail.com> Message-ID: <20120910012357.GA7685@topoi.pooq.com> On Sun, Sep 09, 2012 at 01:05:05PM -0700, Jay wrote: > > As well, can't we have the frontend be very conservative? Align each > basic int & float type to its size, even if not required? Didn't I > already do that? E.g. 64 bit ints don't generally need 64bit alignment > on 32 bit targets, but I'm ok giving it. Front end can insert padding ? explicitly. (this area bit me, you may recall, gcc/cygwin was aligning > 64bit double float to 64bits, adding in padding where frontend > didn't..I had to peel the onion quite a bit to debug that...) The worst case of alignment weirdness I've encountered was on an IBM workstation sometime in the late 80's/early nineties. A structure was aligned on a double-boundary iff its first fiels of its first fiels of its first field (go doewn the first-fields until you've broken up all those nested structures) ... was a double. Doubles anywhere else in the structure didn't count and only demanded a float boundaty. Or it was somethign like that. I've always wondered why. -- hendrik From hosking at cs.purdue.edu Mon Sep 10 04:00:39 2012 From: hosking at cs.purdue.edu (Antony Hosking) Date: Sun, 9 Sep 2012 22:00:39 -0400 Subject: [M3devel] C math interop.. In-Reply-To: References: Message-ID: I don?t understand. Are you saying that the M3 declarations of these externals are wrong? On Sep 8, 2012, at 5:54 AM, Jay K wrote: > hm. The advantage of not having wrappers, is you can declare things that don't exist. > Maybe only on some platforms. > So I'll probably fix the declarations. > For scaleb/ldexp/sqrt too. > (similar to what I did for strcat/strcpy in Cstring.i3 -- no wrappers, to avoid OpenBSD link warning/error) > > Later, > - Jay > > From: jay.krell at cornell.edu > To: m3devel at elegosoft.com > Date: Sat, 8 Sep 2012 09:50:19 +0000 > Subject: [M3devel] C math interop.. > > This also occured in FPU.ic > > Math.ic.c:217: error: conflicting types for ?signgam? > /usr/include/architecture/i386/math.h:543: error: previous declaration of ?signgam? was here > Math.ic.c:298: warning: conflicting types for built-in function ?cabs? > Math.ic.c:302: error: conflicting types for ?frexp? > Math.ic.c:306: error: conflicting types for ?ldexp? > Math.ic.c:310: error: conflicting types for ?modf? > Math.ic.c:329: error: conflicting types for ?jn? > Math.ic.c:339: error: conflicting types for ?yn? > > > Generally int vs. INTEGER confusion. > To fix these errors, I'm going to provide C wrappers for these functions, and everything else in the file. > > > This hints at some new way to do interop, fast like the old way, but with static checking, > where the generated C #includes the relevant .h files. > But this is a bit abstraction bending -- the backend isn't supposed to be doing these checks. > The frontend does. > You'd have to have changes in the <* extern *> pragma like > - this isn't an actual function signature, necessarily..and the address can't > necessarily be taken, but something close enough to this will materialize from a C header > - specify the C header > > > Imagine a world with a good C backend, and a good other one. > Modules that interoperate with C could be sent off to the C backend automatically. > > > Anyway, just crazy stuff, nothing really happening here beyond I'll add C wrappers. :) > > > When I get to it, #include along with our declarations..it will be interesting > to see if things match. And ... > There will be problems. We have one UINT32 type in the generated C. > Win32 has unsigned int and unsigned long used kind of interchangably. > There will be clashes. > > > - Jay -------------- next part -------------- An HTML attachment was scrubbed... URL: From hosking at cs.purdue.edu Mon Sep 10 04:03:24 2012 From: hosking at cs.purdue.edu (Antony Hosking) Date: Sun, 9 Sep 2012 22:03:24 -0400 Subject: [M3devel] pre-report In-Reply-To: <40145A43-9420-4ECF-899C-3CC015ED2B99@m3w.org> References: <40145A43-9420-4ECF-899C-3CC015ED2B99@m3w.org> Message-ID: <91BD5809-66C2-4072-95A3-A98236F30CC3@cs.purdue.edu> What?s the source code? Testcase please... On Sep 8, 2012, at 3:23 AM, Dragi?a Duri? wrote: > Just got this, many times in a row :) > > === > % cm3 > --- building in ../AMD64_DARWIN --- > > new source -> compiling Descriptors.m3 > > > *** > *** runtime error: > *** <*ASSERT*> failed. > *** file "../src/values/Formal.m3", line 689 > *** > > zsh: abort cm3 > > > % cm3 -? > Critical Mass Modula-3 version d5.9.0 > last updated: 2010-07-21 > compiled: 2011-03-23 04:04:18 > configuration: /usr/local/cm3/bin/cm3.cfg > host: AMD64_DARWIN > target: AMD64_DARWIN > > -- > Divided by a common language > > Dragi?a Duri? > dragisha at m3w.org > > > > From jay.krell at cornell.edu Mon Sep 10 07:34:48 2012 From: jay.krell at cornell.edu (Jay K) Date: Mon, 10 Sep 2012 05:34:48 +0000 Subject: [M3devel] C math interop.. In-Reply-To: References: , Message-ID: Yes. At least slightly -- int vs. INTEGER. I will fix them. The case of Cstring.strcat/strcpy is different. They end up as Type.Addr strcat(Type.Addr dest, Type.Addr source); I have some leeway in what Type.Addr ends up as, but no choice is right there. My main choices are char*, unsigned char* and void*. (At some point, I'm serious about having a K&R option, so void* will fall out of favor, but I'm using char* now anyway, since I can do math on it more conveniently. I've run into slightly interesting K&R compilers twice in the past few years -- on Irix and HPUX.) It is possible I changed them from int to INTEGER anyway. Some notion I had of passing "register-sized" things being "better". I can check. But at the moment I'm sure using int or whatever ANSI C says, is the way to go. - Jay Subject: Re: [M3devel] C math interop.. From: hosking at cs.purdue.edu Date: Sun, 9 Sep 2012 22:00:39 -0400 CC: m3devel at elegosoft.com To: jay.krell at cornell.edu I don?t understand. Are you saying that the M3 declarations of these externals are wrong? On Sep 8, 2012, at 5:54 AM, Jay K wrote:hm. The advantage of not having wrappers, is you can declare things that don't exist.Maybe only on some platforms.So I'll probably fix the declarations.For scaleb/ldexp/sqrt too.(similar to what I did for strcat/strcpy in Cstring.i3 -- no wrappers, to avoid OpenBSD link warning/error) Later, - Jay From: jay.krell at cornell.edu To: m3devel at elegosoft.com Date: Sat, 8 Sep 2012 09:50:19 +0000 Subject: [M3devel] C math interop.. This also occured in FPU.ic Math.ic.c:217: error: conflicting types for ?signgam?/usr/include/architecture/i386/math.h:543: error: previous declaration of ?signgam? was hereMath.ic.c:298: warning: conflicting types for built-in function ?cabs?Math.ic.c:302: error: conflicting types for ?frexp?Math.ic.c:306: error: conflicting types for ?ldexp?Math.ic.c:310: error: conflicting types for ?modf?Math.ic.c:329: error: conflicting types for ?jn?Math.ic.c:339: error: conflicting types for ?yn? Generally int vs. INTEGER confusion.To fix these errors, I'm going to provide C wrappers for these functions, and everything else in the file. This hints at some new way to do interop, fast like the old way, but with static checking,where the generated C #includes the relevant .h files.But this is a bit abstraction bending -- the backend isn't supposed to be doing these checks.The frontend does.You'd have to have changes in the <* extern *> pragma like - this isn't an actual function signature, necessarily..and the address can'tnecessarily be taken, but something close enough to this will materialize from a C header - specify the C header Imagine a world with a good C backend, and a good other one.Modules that interoperate with C could be sent off to the C backend automatically. Anyway, just crazy stuff, nothing really happening here beyond I'll add C wrappers. :) When I get to it, #include along with our declarations..it will be interestingto see if things match. And ...There will be problems. We have one UINT32 type in the generated C.Win32 has unsigned int and unsigned long used kind of interchangably.There will be clashes. - Jay -------------- next part -------------- An HTML attachment was scrubbed... URL: From jay.krell at cornell.edu Mon Sep 10 07:47:13 2012 From: jay.krell at cornell.edu (Jay K) Date: Mon, 10 Sep 2012 05:47:13 +0000 Subject: [M3devel] "C-generating backend progress report, that nobody asked for" :) In-Reply-To: <43C4B30F-24AB-4421-923B-9F32C1807AF5@cs.purdue.edu> References: <84C67B7F-A915-4DE8-B14C-44E6F87DE85D@gmail.com> <9748E313-E0EF-45FA-A01F-DE0C58FDDED7@cs.purdue.edu> <4CD63AEF-523B-423F-9690-7DEDBF8BEFFC@gmail.com>, <43C4B30F-24AB-4421-923B-9F32C1807AF5@cs.purdue.edu> Message-ID: Please, no. Stock gdb and stock Visual C++ and stock cdb/ntsd/windbg ought to work well with Modula-3. I expect they will pretty good pretty soon, and we should try to make them even better maybe... by making globals visible in a reasonable fashion. m3gdb isn't supported on Darwin and HP-UX (no stabs), at least. If the gcc backend becomes obsolete and deleted...m3gdb would be the last of the forked always-going-stale never-merging GPL stuff... i.e. another ripe target... - Jay Subject: Re: [M3devel] "C-generating backend progress report, that nobody asked for" :) From: hosking at cs.purdue.edu Date: Sun, 9 Sep 2012 20:54:12 -0400 CC: dragisha at m3w.org; m3devel at elegosoft.com To: jay.krell at cornell.edu Stock debuggers are designed for C. They generally will not be able to grok M3. Better to use M3 run-time type information as per m3gdb. See 10.1145/143103.143112. On Sep 9, 2012, at 4:07 PM, Jay wrote:The current method stinks for stock debugging. As I understand, globals are combined into structs & the fields all have generated names, & global records are flattened therein. It works. But stock debuggers see garbage. - Jay (briefly/pocket-sized-computer-aka-phone) On Sep 9, 2012, at 12:22 PM, Antony Hosking wrote: I mis-spoke. I think LLVM can cope with much the same as we currently have. Front-end will continue to compute alignments and layouts. We can assert the front-end's datalayout by passing it to LLVM explicitly, which will complain if it does not match the actual target. This is a rather nice feature of LLVM in that it allows us to retain control while having LLVM optimize accordingly. On Sep 9, 2012, at 11:05 AM, Antony Hosking wrote:Yes, agreed, these need to be properly typed too.First step will be to lift the M3CG interface.Problem: The compiler needs to control layout so that the run-time system knows where to find things. This means that we need to assert alignments and layouts produced by the backend are the same as those in the front-end. LLVM has nice ways to do this. How will we do it in the C backend? Does C have sufficient control over alignment? On Sep 9, 2012, at 10:53 AM, Jay wrote:Btw, can this include "segment"/globals? Can they each be separate named variables? At least some of them? - Jay (briefly/pocket-sized-computer-aka-phone) On Sep 9, 2012, at 7:48 AM, Antony Hosking wrote: I'm looking at it... First step is to lift slightly the level of M3CG to use properly typed memory access, instead of untyped address + offset. On Sep 9, 2012, at 2:32 AM, Dragi?a Duri? wrote:I hope somebody will take on LLVM :). -------------- next part -------------- An HTML attachment was scrubbed... URL: From dragisha at m3w.org Mon Sep 10 09:41:00 2012 From: dragisha at m3w.org (=?utf-8?Q?Dragi=C5=A1a_Duri=C4=87?=) Date: Mon, 10 Sep 2012 09:41:00 +0200 Subject: [M3devel] pre-report In-Reply-To: <91BD5809-66C2-4072-95A3-A98236F30CC3@cs.purdue.edu> References: <40145A43-9420-4ECF-899C-3CC015ED2B99@m3w.org> <91BD5809-66C2-4072-95A3-A98236F30CC3@cs.purdue.edu> Message-ID: MODULE TestCase EXPORTS Main; PROCEDURE Do(VAR b: ARRAY OF CHAR) = BEGIN END Do; VAR arg: RECORD a: BITS 1 FOR BOOLEAN; (* case 2 is this, case 1 is: comment a out :) *) b: BITS 24 FOR ARRAY [0..2] OF CHAR; END; BEGIN Do(arg.b); END TestCase. -- Divided by a common language Dragi?a Duri? dragisha at m3w.org On Sep 10, 2012, at 4:03 AM, Antony Hosking wrote: > What?s the source code? > Testcase please... > > On Sep 8, 2012, at 3:23 AM, Dragi?a Duri? wrote: > >> Just got this, many times in a row :) >> >> === >> % cm3 >> --- building in ../AMD64_DARWIN --- >> >> new source -> compiling Descriptors.m3 >> >> >> *** >> *** runtime error: >> *** <*ASSERT*> failed. >> *** file "../src/values/Formal.m3", line 689 >> *** >> >> zsh: abort cm3 >> >> >> % cm3 -? >> Critical Mass Modula-3 version d5.9.0 >> last updated: 2010-07-21 >> compiled: 2011-03-23 04:04:18 >> configuration: /usr/local/cm3/bin/cm3.cfg >> host: AMD64_DARWIN >> target: AMD64_DARWIN >> >> -- >> Divided by a common language >> >> Dragi?a Duri? >> dragisha at m3w.org >> >> >> >> > -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 495 bytes Desc: Message signed with OpenPGP using GPGMail URL: From hosking at cs.purdue.edu Mon Sep 10 18:11:42 2012 From: hosking at cs.purdue.edu (Antony Hosking) Date: Mon, 10 Sep 2012 12:11:42 -0400 Subject: [M3devel] pre-report In-Reply-To: References: <40145A43-9420-4ECF-899C-3CC015ED2B99@m3w.org> <91BD5809-66C2-4072-95A3-A98236F30CC3@cs.purdue.edu> Message-ID: I?m trying to get a sense for what the correct behavior of the compiler should be in this case. I think that the passing of the unaligned ARRAY OF CHAR as an open array parameter should be disallowed. There is no way to communicate the alignment in the dope vector built for the open array formal. In which case, the fix is the following patch to Formal.m3, disallowing a formal parameter for a *** Formal.m3.~1.16.~ Wed Sep 5 11:03:31 2012 --- Formal.m3 Mon Sep 10 12:07:46 2012 *************** *** 356,361 **** --- 356,362 ---- ELSIF Type.IsEqual (t, te, NIL) THEN Expr.NeedsAddress (e); ELSIF ArrayType.Split (t, index, elt) + AND ArrayType.Split (te, index, elt) AND Type.IsAssignable (t, te) THEN Expr.NeedsAddress (e); ELSE Can anyone think if this will break any existing code? I can?t think of anything where it will break (assigning something that does not have array type to a formal parameter of array type). On Sep 10, 2012, at 3:41 AM, Dragi?a Duri? wrote: > MODULE TestCase EXPORTS Main; > > PROCEDURE Do(VAR b: ARRAY OF CHAR) = > BEGIN > END Do; > > VAR > arg: RECORD > a: BITS 1 FOR BOOLEAN; (* case 2 is this, case 1 is: comment a out :) *) > b: BITS 24 FOR ARRAY [0..2] OF CHAR; > END; > > BEGIN > Do(arg.b); > END TestCase. > > -- > Divided by a common language > > Dragi?a Duri? > dragisha at m3w.org > > > > > On Sep 10, 2012, at 4:03 AM, Antony Hosking wrote: > >> What?s the source code? >> Testcase please... >> >> On Sep 8, 2012, at 3:23 AM, Dragi?a Duri? wrote: >> >>> Just got this, many times in a row :) >>> >>> === >>> % cm3 >>> --- building in ../AMD64_DARWIN --- >>> >>> new source -> compiling Descriptors.m3 >>> >>> >>> *** >>> *** runtime error: >>> *** <*ASSERT*> failed. >>> *** file "../src/values/Formal.m3", line 689 >>> *** >>> >>> zsh: abort cm3 >>> >>> >>> % cm3 -? >>> Critical Mass Modula-3 version d5.9.0 >>> last updated: 2010-07-21 >>> compiled: 2011-03-23 04:04:18 >>> configuration: /usr/local/cm3/bin/cm3.cfg >>> host: AMD64_DARWIN >>> target: AMD64_DARWIN >>> >>> -- >>> Divided by a common language >>> >>> Dragi?a Duri? >>> dragisha at m3w.org >>> >>> >>> >>> >> > From hosking at cs.purdue.edu Mon Sep 10 18:17:59 2012 From: hosking at cs.purdue.edu (Antony Hosking) Date: Mon, 10 Sep 2012 12:17:59 -0400 Subject: [M3devel] pre-report In-Reply-To: References: <40145A43-9420-4ECF-899C-3CC015ED2B99@m3w.org> <91BD5809-66C2-4072-95A3-A98236F30CC3@cs.purdue.edu> Message-ID: <92BD790D-6AC4-4170-9515-A8842011CF2B@cs.purdue.edu> I?ve gone ahead and committed the "fix" to prohibit treating BITS FOR ARRAY OF X as assignable to VAR formals that are ARRAY OF X. There is no way to communicate the alignment of any BITS FOR ARRAY in its containing structure (RECORD, etc.). From the language spec: Implementations are allowed to forbid VAR or READONLY parameters of packed types. On Sep 10, 2012, at 12:11 PM, Antony Hosking wrote: > I?m trying to get a sense for what the correct behavior of the compiler should be in this case. I think that the passing of the unaligned ARRAY OF CHAR as an open array parameter should be disallowed. There is no way to communicate the alignment in the dope vector built for the open array formal. > > In which case, the fix is the following patch to Formal.m3, disallowing a formal parameter for a > > *** Formal.m3.~1.16.~ Wed Sep 5 11:03:31 2012 > --- Formal.m3 Mon Sep 10 12:07:46 2012 > *************** > *** 356,361 **** > --- 356,362 ---- > ELSIF Type.IsEqual (t, te, NIL) THEN > Expr.NeedsAddress (e); > ELSIF ArrayType.Split (t, index, elt) > + AND ArrayType.Split (te, index, elt) > AND Type.IsAssignable (t, te) THEN > Expr.NeedsAddress (e); > ELSE > > > Can anyone think if this will break any existing code? I can?t think of anything where it will break (assigning something that does not have array type to a formal parameter of array type). > > On Sep 10, 2012, at 3:41 AM, Dragi?a Duri? wrote: > >> MODULE TestCase EXPORTS Main; >> >> PROCEDURE Do(VAR b: ARRAY OF CHAR) = >> BEGIN >> END Do; >> >> VAR >> arg: RECORD >> a: BITS 1 FOR BOOLEAN; (* case 2 is this, case 1 is: comment a out :) *) >> b: BITS 24 FOR ARRAY [0..2] OF CHAR; >> END; >> >> BEGIN >> Do(arg.b); >> END TestCase. >> >> -- >> Divided by a common language >> >> Dragi?a Duri? >> dragisha at m3w.org >> >> >> >> >> On Sep 10, 2012, at 4:03 AM, Antony Hosking wrote: >> >>> What?s the source code? >>> Testcase please... >>> >>> On Sep 8, 2012, at 3:23 AM, Dragi?a Duri? wrote: >>> >>>> Just got this, many times in a row :) >>>> >>>> === >>>> % cm3 >>>> --- building in ../AMD64_DARWIN --- >>>> >>>> new source -> compiling Descriptors.m3 >>>> >>>> >>>> *** >>>> *** runtime error: >>>> *** <*ASSERT*> failed. >>>> *** file "../src/values/Formal.m3", line 689 >>>> *** >>>> >>>> zsh: abort cm3 >>>> >>>> >>>> % cm3 -? >>>> Critical Mass Modula-3 version d5.9.0 >>>> last updated: 2010-07-21 >>>> compiled: 2011-03-23 04:04:18 >>>> configuration: /usr/local/cm3/bin/cm3.cfg >>>> host: AMD64_DARWIN >>>> target: AMD64_DARWIN >>>> >>>> -- >>>> Divided by a common language >>>> >>>> Dragi?a Duri? >>>> dragisha at m3w.org >>>> >>>> >>>> >>>> >>> >> > From dabenavidesd at yahoo.es Mon Sep 10 23:30:04 2012 From: dabenavidesd at yahoo.es (Daniel Alejandro Benavides D.) Date: Mon, 10 Sep 2012 22:30:04 +0100 (BST) Subject: [M3devel] pre-report In-Reply-To: <92BD790D-6AC4-4170-9515-A8842011CF2B@cs.purdue.edu> Message-ID: <1347312604.95916.YahooMailClassic@web29705.mail.ird.yahoo.com> Hi all: I have read they are equally treated by the compiler, why do you make that illegal? If the compiler hasn't as isn't implemented it is an implementation limitation, but that shouldn't affect? other compilers that we might want to be source compatible with (I know of a front end but it's "confidential" that throws Attribute Grammar). Thanks in advance --- El lun, 10/9/12, Antony Hosking escribi?: De: Antony Hosking Asunto: Re: [M3devel] pre-report Para: "Dragi?a Duri?" CC: "m3devel" Fecha: lunes, 10 de septiembre, 2012 11:17 I?ve gone ahead and committed the "fix" to prohibit treating BITS FOR ARRAY OF X as assignable to VAR formals that are ARRAY OF X.? There is no way to communicate the alignment of any BITS FOR ARRAY in its containing structure (RECORD, etc.). >From the language spec: Implementations are allowed to forbid VAR or READONLY parameters of packed types. On Sep 10, 2012, at 12:11 PM, Antony Hosking wrote: > I?m trying to get a sense for what the correct behavior of the compiler should be in this case. I think that the passing of the unaligned ARRAY OF CHAR as an open array parameter should be disallowed.? There is no way to communicate the alignment in the dope vector built for the open array formal. > > In which case, the fix is the following patch to Formal.m3, disallowing a formal parameter for a > > *** Formal.m3.~1.16.~??? Wed Sep? 5 11:03:31 2012 > --- Formal.m3??? Mon Sep 10 12:07:46 2012 > *************** > *** 356,361 **** > --- 356,362 ---- >? ? ? ? ? ? ? ELSIF Type.IsEqual (t, te, NIL) THEN >? ? ? ? ? ? ? ? Expr.NeedsAddress (e); >? ? ? ? ? ? ? ELSIF ArrayType.Split (t, index, elt) > +? ? ? ? ? ? ???AND ArrayType.Split (te, index, elt) >? ? ? ? ? ? ? ? AND Type.IsAssignable (t, te) THEN >? ? ? ? ? ? ? ? Expr.NeedsAddress (e); >? ? ? ? ? ? ? ELSE > > > Can anyone think if this will break any existing code?? I can?t think of anything where it will break (assigning something that does not have array type to a formal parameter of array type). > > On Sep 10, 2012, at 3:41 AM, Dragi?a Duri? wrote: > >> MODULE TestCase EXPORTS Main; >> >> PROCEDURE Do(VAR b: ARRAY OF CHAR) = >> BEGIN >> END Do; >> >> VAR >> arg: RECORD >>???a: BITS 1 FOR BOOLEAN; (* case 2 is this, case 1 is: comment a out :) *) >>???b: BITS 24 FOR ARRAY [0..2] OF CHAR; >> END; >> >> BEGIN >> Do(arg.b); >> END TestCase. >> >> -- >> Divided by a common language >> >> Dragi?a Duri? >> dragisha at m3w.org >> >> >> >> >> On Sep 10, 2012, at 4:03 AM, Antony Hosking wrote: >> >>> What?s the source code? >>> Testcase please... >>> >>> On Sep 8, 2012, at 3:23 AM, Dragi?a Duri? wrote: >>> >>>> Just got this, many times in a row :) >>>> >>>> === >>>> % cm3 >>>> --- building in ../AMD64_DARWIN --- >>>> >>>> new source -> compiling Descriptors.m3 >>>> >>>> >>>> *** >>>> *** runtime error: >>>> ***? ? <*ASSERT*> failed. >>>> ***? ? file "../src/values/Formal.m3", line 689 >>>> *** >>>> >>>> zsh: abort? ? ? cm3 >>>> >>>> >>>> % cm3 -? >>>> Critical Mass Modula-3 version d5.9.0 >>>> last updated: 2010-07-21 >>>> compiled: 2011-03-23 04:04:18 >>>> configuration: /usr/local/cm3/bin/cm3.cfg >>>> host: AMD64_DARWIN >>>> target: AMD64_DARWIN >>>> >>>> -- >>>> Divided by a common language >>>> >>>> Dragi?a Duri? >>>> dragisha at m3w.org >>>> >>>> >>>> >>>> >>> >> > -------------- next part -------------- An HTML attachment was scrubbed... URL: From dabenavidesd at yahoo.es Mon Sep 10 23:56:58 2012 From: dabenavidesd at yahoo.es (Daniel Alejandro Benavides D.) Date: Mon, 10 Sep 2012 22:56:58 +0100 (BST) Subject: [M3devel] "C-generating backend progress report, that nobody asked for" :) In-Reply-To: Message-ID: <1347314218.15461.YahooMailClassic@web29706.mail.ird.yahoo.com> Hi all: Jay, are you considering Clang as target? Thanks in advance --- El lun, 10/9/12, Jay K escribi?: De: Jay K Asunto: Re: [M3devel] "C-generating backend progress report, that nobody asked for" :) Para: "Tony" CC: "m3devel" Fecha: lunes, 10 de septiembre, 2012 00:47 Please, no. Stock gdb and stock Visual C++ and stock cdb/ntsd/windbg ought to work well with Modula-3. I expect they will pretty good pretty soon, and we should try to make them even better maybe... by making globals visible in a reasonable fashion. m3gdb isn't supported on Darwin and HP-UX (no stabs), at least. If the gcc backend becomes obsolete and deleted...m3gdb would be the last of the forked always-going-stale never-merging GPL stuff... i.e. another ripe target... ?- Jay Subject: Re: [M3devel] "C-generating backend progress report, that nobody asked for" :) From: hosking at cs.purdue.edu Date: Sun, 9 Sep 2012 20:54:12 -0400 CC: dragisha at m3w.org; m3devel at elegosoft.com To: jay.krell at cornell.edu Stock debuggers are designed for C. ?They generally will not be able to grok M3. ?Better to use M3 run-time type information as per m3gdb. ?See?10.1145/143103.143112. On Sep 9, 2012, at 4:07 PM, Jay wrote: The current method stinks for stock debugging. As I understand, globals are combined into structs & the fields all have generated names, & global records are flattened therein. It works. But stock debuggers see garbage. ?- Jay (briefly/pocket-sized-computer-aka-phone) On Sep 9, 2012, at 12:22 PM, Antony Hosking wrote: I mis-spoke. ?I think LLVM can cope with much the same as we currently have. ?Front-end will continue to compute alignments and layouts. ?We can assert the front-end's datalayout by passing it to LLVM explicitly, which will complain if it does not match the actual target. ?This is a rather nice feature of LLVM in that it allows us to retain control while having LLVM optimize accordingly. On Sep 9, 2012, at 11:05 AM, Antony Hosking wrote: Yes, agreed, these need to be properly typed too.First step will be to lift the M3CG interface.Problem: The compiler needs to control layout so that the run-time system knows where to find things. ?This means that we need to assert alignments and layouts produced by the backend are the same as those in the front-end. ?LLVM has nice ways to do this. ?How will we do it in the C backend? ?Does C have sufficient control over alignment? On Sep 9, 2012, at 10:53 AM, Jay wrote: Btw, can this include "segment"/globals? Can they each be separate named variables? At least some of them? ?- Jay (briefly/pocket-sized-computer-aka-phone) On Sep 9, 2012, at 7:48 AM, Antony Hosking wrote: I'm looking at it... First step is to lift slightly the level of M3CG to use properly typed memory access, instead of untyped address + offset. On Sep 9, 2012, at 2:32 AM, Dragi?a Duri? wrote: I hope somebody will take on LLVM :). -------------- next part -------------- An HTML attachment was scrubbed... URL: From hosking at cs.purdue.edu Tue Sep 11 02:07:27 2012 From: hosking at cs.purdue.edu (Antony Hosking) Date: Mon, 10 Sep 2012 20:07:27 -0400 Subject: [M3devel] "C-generating backend progress report, that nobody asked for" :) In-Reply-To: References: <84C67B7F-A915-4DE8-B14C-44E6F87DE85D@gmail.com> <9748E313-E0EF-45FA-A01F-DE0C58FDDED7@cs.purdue.edu> <4CD63AEF-523B-423F-9690-7DEDBF8BEFFC@gmail.com>, <43C4B30F-24AB-4421-923B-9F32C1807AF5@cs.purdue.edu> Message-ID: <00232380-526C-46E5-B334-11F902A64997@cs.purdue.edu> Stock gdb won?t ever parse M3 expressions nor print M3 values. So, there will always have to be some M3 support added. I would much prefer providing M3 library support for source debuggers to parse and print. I have no idea whether gdb has ever considered some of the extensibility support I pointed at in the link below. Antony Hosking | Associate Professor | Computer Science | Purdue University 305 N. University Street | West Lafayette | IN 47907 | USA Mobile +1 765 427 5484 On Sep 10, 2012, at 1:47 AM, Jay K wrote: > Please, no. > > Stock gdb and stock Visual C++ and stock cdb/ntsd/windbg ought to work well with Modula-3. > I expect they will pretty good pretty soon, and we should try to make them even better maybe... > by making globals visible in a reasonable fashion. > > > m3gdb isn't supported on Darwin and HP-UX (no stabs), at least. > If the gcc backend becomes obsolete and deleted...m3gdb would be the last of the > forked always-going-stale never-merging GPL stuff... i.e. another ripe target... > > > > - Jay > > Subject: Re: [M3devel] "C-generating backend progress report, that nobody asked for" :) > From: hosking at cs.purdue.edu > Date: Sun, 9 Sep 2012 20:54:12 -0400 > CC: dragisha at m3w.org; m3devel at elegosoft.com > To: jay.krell at cornell.edu > > Stock debuggers are designed for C. They generally will not be able to grok M3. Better to use M3 run-time type information as per m3gdb. See 10.1145/143103.143112. > > > On Sep 9, 2012, at 4:07 PM, Jay wrote: > > The current method stinks for stock debugging. As I understand, globals are combined into structs & the fields all have generated names, & global records are flattened therein. > > > It works. But stock debuggers see garbage. > > > - Jay (briefly/pocket-sized-computer-aka-phone) > > On Sep 9, 2012, at 12:22 PM, Antony Hosking wrote: > > I mis-spoke. I think LLVM can cope with much the same as we currently have. Front-end will continue to compute alignments and layouts. We can assert the front-end's datalayout by passing it to LLVM explicitly, which will complain if it does not match the actual target. This is a rather nice feature of LLVM in that it allows us to retain control while having LLVM optimize accordingly. > > On Sep 9, 2012, at 11:05 AM, Antony Hosking wrote: > > Yes, agreed, these need to be properly typed too. > First step will be to lift the M3CG interface. > Problem: The compiler needs to control layout so that the run-time system knows where to find things. This means that we need to assert alignments and layouts produced by the backend are the same as those in the front-end. LLVM has nice ways to do this. How will we do it in the C backend? Does C have sufficient control over alignment? > > On Sep 9, 2012, at 10:53 AM, Jay wrote: > > Btw, can this include "segment"/globals? Can they each be separate named variables? At least some of them? > > > - Jay (briefly/pocket-sized-computer-aka-phone) > > On Sep 9, 2012, at 7:48 AM, Antony Hosking wrote: > > I'm looking at it... > > First step is to lift slightly the level of M3CG to use properly typed memory access, instead of untyped address + offset. > > On Sep 9, 2012, at 2:32 AM, Dragi?a Duri? wrote: > > I hope somebody will take on LLVM :). -------------- next part -------------- An HTML attachment was scrubbed... URL: From hosking at cs.purdue.edu Tue Sep 11 02:11:00 2012 From: hosking at cs.purdue.edu (Antony Hosking) Date: Mon, 10 Sep 2012 20:11:00 -0400 Subject: [M3devel] pre-report In-Reply-To: <1347312604.95916.YahooMailClassic@web29705.mail.ird.yahoo.com> References: <1347312604.95916.YahooMailClassic@web29705.mail.ird.yahoo.com> Message-ID: <20C7DDD8-7E79-4BEC-9F89-8502F63CD883@cs.purdue.edu> Not true. There are several mentions that packed types and their base types are not equal. In some circumstances they may be assignable. But in this case (aliasing a packed array using VAR) there is no way to communicate the packed-ness of the actual parameter to the callee. On Sep 10, 2012, at 5:30 PM, "Daniel Alejandro Benavides D." wrote: > > Hi all: > I have read they are equally treated by the compiler, why do you make that illegal? > If the compiler hasn't as isn't implemented it is an implementation limitation, but that shouldn't affect other compilers that we might want to be source compatible with (I know of a front end but it's "confidential" that throws Attribute Grammar). > Thanks in advance > > --- El lun, 10/9/12, Antony Hosking escribi?: > > De: Antony Hosking > Asunto: Re: [M3devel] pre-report > Para: "Dragi?a Duri?" > CC: "m3devel" > Fecha: lunes, 10 de septiembre, 2012 11:17 > > I?ve gone ahead and committed the "fix" to prohibit treating BITS FOR ARRAY OF X as assignable to VAR formals that are ARRAY OF X. There is no way to communicate the alignment of any BITS FOR ARRAY in its containing structure (RECORD, etc.). > > From the language spec: > > Implementations are allowed to forbid VAR or READONLY parameters of packed types. > > On Sep 10, 2012, at 12:11 PM, Antony Hosking wrote: > > > I?m trying to get a sense for what the correct behavior of the compiler should be in this case. I think that the passing of the unaligned ARRAY OF CHAR as an open array parameter should be disallowed. There is no way to communicate the alignment in the dope vector built for the open array formal. > > > > In which case, the fix is the following patch to Formal.m3, disallowing a formal parameter for a > > > > *** Formal.m3.~1.16.~ Wed Sep 5 11:03:31 2012 > > --- Formal.m3 Mon Sep 10 12:07:46 2012 > > *************** > > *** 356,361 **** > > --- 356,362 ---- > > ELSIF Type.IsEqual (t, te, NIL) THEN > > Expr.NeedsAddress (e); > > ELSIF ArrayType.Split (t, index, elt) > > + AND ArrayType.Split (te, index, elt) > > AND Type.IsAssignable (t, te) THEN > > Expr.NeedsAddress (e); > > ELSE > > > > > > Can anyone think if this will break any existing code? I can?t think of anything where it will break (assigning something that does not have array type to a formal parameter of array type). > > > > On Sep 10, 2012, at 3:41 AM, Dragi?a Duri? wrote: > > > >> MODULE TestCase EXPORTS Main; > >> > >> PROCEDURE Do(VAR b: ARRAY OF CHAR) = > >> BEGIN > >> END Do; > >> > >> VAR > >> arg: RECORD > >> a: BITS 1 FOR BOOLEAN; (* case 2 is this, case 1 is: comment a out :) *) > >> b: BITS 24 FOR ARRAY [0..2] OF CHAR; > >> END; > >> > >> BEGIN > >> Do(arg.b); > >> END TestCase. > >> > >> -- > >> Divided by a common language > >> > >> Dragi?a Duri? > >> dragisha at m3w.org > >> > >> > >> > >> > >> On Sep 10, 2012, at 4:03 AM, Antony Hosking wrote: > >> > >>> What?s the source code? > >>> Testcase please... > >>> > >>> On Sep 8, 2012, at 3:23 AM, Dragi?a Duri? wrote: > >>> > >>>> Just got this, many times in a row :) > >>>> > >>>> === > >>>> % cm3 > >>>> --- building in ../AMD64_DARWIN --- > >>>> > >>>> new source -> compiling Descriptors.m3 > >>>> > >>>> > >>>> *** > >>>> *** runtime error: > >>>> *** <*ASSERT*> failed. > >>>> *** file "../src/values/Formal.m3", line 689 > >>>> *** > >>>> > >>>> zsh: abort cm3 > >>>> > >>>> > >>>> % cm3 -? > >>>> Critical Mass Modula-3 version d5.9.0 > >>>> last updated: 2010-07-21 > >>>> compiled: 2011-03-23 04:04:18 > >>>> configuration: /usr/local/cm3/bin/cm3.cfg > >>>> host: AMD64_DARWIN > >>>> target: AMD64_DARWIN > >>>> > >>>> -- > >>>> Divided by a common language > >>>> > >>>> Dragi?a Duri? > >>>> dragisha at m3w.org > >>>> > >>>> > >>>> > >>>> > >>> > >> > > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From dabenavidesd at yahoo.es Tue Sep 11 03:14:46 2012 From: dabenavidesd at yahoo.es (Daniel Alejandro Benavides D.) Date: Tue, 11 Sep 2012 02:14:46 +0100 (BST) Subject: [M3devel] pre-report In-Reply-To: <20C7DDD8-7E79-4BEC-9F89-8502F63CD883@cs.purdue.edu> Message-ID: <1347326086.46231.YahooMailClassic@web29702.mail.ird.yahoo.com> Hi all: I'm not talking about packed types but values, they must be the same! Anyway, if you are talking about types I guess that's bigger question IMHO, so pass on to somebody, anyone? Thanks in advance --- El lun, 10/9/12, Antony Hosking escribi?: De: Antony Hosking Asunto: Re: [M3devel] pre-report Para: "Daniel Alejandro Benavides D." CC: "Dragi?a Duri?" , "m3devel" Fecha: lunes, 10 de septiembre, 2012 19:11 Not true. ?There are several mentions that packed types and their base types are not equal. ?In some circumstances they may be assignable. ?But in this case (aliasing a packed array using VAR) there is no way to communicate the packed-ness of the actual parameter to the callee. On Sep 10, 2012, at 5:30 PM, "Daniel Alejandro Benavides D." wrote: Hi all: I have read they are equally treated by the compiler, why do you make that illegal? If the compiler hasn't as isn't implemented it is an implementation limitation, but that shouldn't affect? other compilers that we might want to be source compatible with (I know of a front end but it's "confidential" that throws Attribute Grammar). Thanks in advance --- El lun, 10/9/12, Antony Hosking escribi?: De: Antony Hosking Asunto: Re: [M3devel] pre-report Para: "Dragi?a Duri?" CC: "m3devel" Fecha: lunes, 10 de septiembre, 2012 11:17 I?ve gone ahead and committed the "fix" to prohibit treating BITS FOR ARRAY OF X as assignable to VAR formals that are ARRAY OF X.? There is no way to communicate the alignment of any BITS FOR ARRAY in its containing structure (RECORD, etc.). >From the language spec: Implementations are allowed to forbid VAR or READONLY parameters of packed types. On Sep 10, 2012, at 12:11 PM, Antony Hosking wrote: > I?m trying to get a sense for what the correct behavior of the compiler should be in this case. I think that the passing of the unaligned ARRAY OF CHAR as an open array parameter should be disallowed.? There is no way to communicate the alignment in the dope vector built for the open array formal. > > In which case, the fix is the following patch to Formal.m3, disallowing a formal parameter for a > > *** Formal.m3.~1.16.~??? Wed Sep? 5 11:03:31 2012 > --- Formal.m3??? Mon Sep 10 12:07:46 2012 > *************** > *** 356,361 **** > --- 356,362 ---- >? ? ? ? ? ? ? ELSIF Type.IsEqual (t, te, NIL) THEN >? ? ? ? ? ? ? ? Expr.NeedsAddress (e); >? ? ? ? ? ? ? ELSIF ArrayType.Split (t, index, elt) > +? ? ? ? ? ? ???AND ArrayType.Split (te, index, elt) >? ? ? ? ? ? ? ? AND Type.IsAssignable (t, te) THEN >? ? ? ? ? ? ? ? Expr.NeedsAddress (e); >? ? ? ? ? ? ? ELSE > > > Can anyone think if this will break any existing code?? I can?t think of anything where it will break (assigning something that does not have array type to a formal parameter of array type). > > On Sep 10, 2012, at 3:41 AM, Dragi?a Duri? wrote: > >> MODULE TestCase EXPORTS Main; >> >> PROCEDURE Do(VAR b: ARRAY OF CHAR) = >> BEGIN >> END Do; >> >> VAR >> arg: RECORD >>???a: BITS 1 FOR BOOLEAN; (* case 2 is this, case 1 is: comment a out :) *) >>???b: BITS 24 FOR ARRAY [0..2] OF CHAR; >> END; >> >> BEGIN >> Do(arg.b); >> END TestCase. >> >> -- >> Divided by a common language >> >> Dragi?a Duri? >> dragisha at m3w.org >> >> >> >> >> On Sep 10, 2012, at 4:03 AM, Antony Hosking wrote: >> >>> What?s the source code? >>> Testcase please... >>> >>> On Sep 8, 2012, at 3:23 AM, Dragi?a Duri? wrote: >>> >>>> Just got this, many times in a row :) >>>> >>>> === >>>> % cm3 >>>> --- building in ../AMD64_DARWIN --- >>>> >>>> new source -> compiling Descriptors.m3 >>>> >>>> >>>> *** >>>> *** runtime error: >>>> ***? ? <*ASSERT*> failed. >>>> ***? ? file "../src/values/Formal.m3", line 689 >>>> *** >>>> >>>> zsh: abort? ? ? cm3 >>>> >>>> >>>> % cm3 -? >>>> Critical Mass Modula-3 version d5.9.0 >>>> last updated: 2010-07-21 >>>> compiled: 2011-03-23 04:04:18 >>>> configuration: /usr/local/cm3/bin/cm3.cfg >>>> host: AMD64_DARWIN >>>> target: AMD64_DARWIN >>>> >>>> -- >>>> Divided by a common language >>>> >>>> Dragi?a Duri? >>>> dragisha at m3w.org >>>> >>>> >>>> >>>> >>> >> > -------------- next part -------------- An HTML attachment was scrubbed... URL: From hosking at cs.purdue.edu Tue Sep 11 04:28:44 2012 From: hosking at cs.purdue.edu (Antony Hosking) Date: Mon, 10 Sep 2012 22:28:44 -0400 Subject: [M3devel] pre-report In-Reply-To: <1347326086.46231.YahooMailClassic@web29702.mail.ird.yahoo.com> References: <1347326086.46231.YahooMailClassic@web29702.mail.ird.yahoo.com> Message-ID: <42DA95AA-8FC4-4DF5-84F3-D623FD83380B@cs.purdue.edu> Subtyping rules We write T <: U to indicate that T is a subtype of U and U is a supertype of T. If T <: U, then every value of type T is also a value of type U. The converse does not hold: for example, a record or array type with packed fields contains the same values as the corresponding type with unpacked fields, but there is no subtype relation between them. On Sep 10, 2012, at 9:14 PM, "Daniel Alejandro Benavides D." wrote: > > Hi all: > I'm not talking about packed types but values, they must be the same! > Anyway, if you are talking about types I guess that's bigger question IMHO, so pass on to somebody, anyone? > Thanks in advance > > --- El lun, 10/9/12, Antony Hosking escribi?: > > De: Antony Hosking > Asunto: Re: [M3devel] pre-report > Para: "Daniel Alejandro Benavides D." > CC: "Dragi?a Duri?" , "m3devel" > Fecha: lunes, 10 de septiembre, 2012 19:11 > > Not true. There are several mentions that packed types and their base types are not equal. In some circumstances they may be assignable. But in this case (aliasing a packed array using VAR) there is no way to communicate the packed-ness of the actual parameter to the callee. > > On Sep 10, 2012, at 5:30 PM, "Daniel Alejandro Benavides D." wrote: > >> >> Hi all: >> I have read they are equally treated by the compiler, why do you make that illegal? >> If the compiler hasn't as isn't implemented it is an implementation limitation, but that shouldn't affect other compilers that we might want to be source compatible with (I know of a front end but it's "confidential" that throws Attribute Grammar). >> Thanks in advance >> >> --- El lun, 10/9/12, Antony Hosking escribi?: >> >> De: Antony Hosking >> Asunto: Re: [M3devel] pre-report >> Para: "Dragi?a Duri?" >> CC: "m3devel" >> Fecha: lunes, 10 de septiembre, 2012 11:17 >> >> I?ve gone ahead and committed the "fix" to prohibit treating BITS FOR ARRAY OF X as assignable to VAR formals that are ARRAY OF X. There is no way to communicate the alignment of any BITS FOR ARRAY in its containing structure (RECORD, etc.). >> >> From the language spec: >> >> Implementations are allowed to forbid VAR or READONLY parameters of packed types. >> >> On Sep 10, 2012, at 12:11 PM, Antony Hosking wrote: >> >> > I?m trying to get a sense for what the correct behavior of the compiler should be in this case. I think that the passing of the unaligned ARRAY OF CHAR as an open array parameter should be disallowed. There is no way to communicate the alignment in the dope vector built for the open array formal. >> > >> > In which case, the fix is the following patch to Formal.m3, disallowing a formal parameter for a >> > >> > *** Formal.m3.~1.16.~ Wed Sep 5 11:03:31 2012 >> > --- Formal.m3 Mon Sep 10 12:07:46 2012 >> > *************** >> > *** 356,361 **** >> > --- 356,362 ---- >> > ELSIF Type.IsEqual (t, te, NIL) THEN >> > Expr.NeedsAddress (e); >> > ELSIF ArrayType.Split (t, index, elt) >> > + AND ArrayType.Split (te, index, elt) >> > AND Type.IsAssignable (t, te) THEN >> > Expr.NeedsAddress (e); >> > ELSE >> > >> > >> > Can anyone think if this will break any existing code? I can?t think of anything where it will break (assigning something that does not have array type to a formal parameter of array type). >> > >> > On Sep 10, 2012, at 3:41 AM, Dragi?a Duri? wrote: >> > >> >> MODULE TestCase EXPORTS Main; >> >> >> >> PROCEDURE Do(VAR b: ARRAY OF CHAR) = >> >> BEGIN >> >> END Do; >> >> >> >> VAR >> >> arg: RECORD >> >> a: BITS 1 FOR BOOLEAN; (* case 2 is this, case 1 is: comment a out :) *) >> >> b: BITS 24 FOR ARRAY [0..2] OF CHAR; >> >> END; >> >> >> >> BEGIN >> >> Do(arg.b); >> >> END TestCase. >> >> >> >> -- >> >> Divided by a common language >> >> >> >> Dragi?a Duri? >> >> dragisha at m3w.org >> >> >> >> >> >> >> >> >> >> On Sep 10, 2012, at 4:03 AM, Antony Hosking wrote: >> >> >> >>> What?s the source code? >> >>> Testcase please... >> >>> >> >>> On Sep 8, 2012, at 3:23 AM, Dragi?a Duri? wrote: >> >>> >> >>>> Just got this, many times in a row :) >> >>>> >> >>>> === >> >>>> % cm3 >> >>>> --- building in ../AMD64_DARWIN --- >> >>>> >> >>>> new source -> compiling Descriptors.m3 >> >>>> >> >>>> >> >>>> *** >> >>>> *** runtime error: >> >>>> *** <*ASSERT*> failed. >> >>>> *** file "../src/values/Formal.m3", line 689 >> >>>> *** >> >>>> >> >>>> zsh: abort cm3 >> >>>> >> >>>> >> >>>> % cm3 -? >> >>>> Critical Mass Modula-3 version d5.9.0 >> >>>> last updated: 2010-07-21 >> >>>> compiled: 2011-03-23 04:04:18 >> >>>> configuration: /usr/local/cm3/bin/cm3.cfg >> >>>> host: AMD64_DARWIN >> >>>> target: AMD64_DARWIN >> >>>> >> >>>> -- >> >>>> Divided by a common language >> >>>> >> >>>> Dragi?a Duri? >> >>>> dragisha at m3w.org >> >>>> >> >>>> >> >>>> >> >>>> >> >>> >> >> >> > >> > -------------- next part -------------- An HTML attachment was scrubbed... URL: From jay.krell at cornell.edu Tue Sep 11 04:51:50 2012 From: jay.krell at cornell.edu (Jay K) Date: Tue, 11 Sep 2012 02:51:50 +0000 Subject: [M3devel] "C-generating backend progress report, that nobody asked for" :) In-Reply-To: <00232380-526C-46E5-B334-11F902A64997@cs.purdue.edu> References: <84C67B7F-A915-4DE8-B14C-44E6F87DE85D@gmail.com> <9748E313-E0EF-45FA-A01F-DE0C58FDDED7@cs.purdue.edu> <4CD63AEF-523B-423F-9690-7DEDBF8BEFFC@gmail.com>, <43C4B30F-24AB-4421-923B-9F32C1807AF5@cs.purdue.edu> , <00232380-526C-46E5-B334-11F902A64997@cs.purdue.edu> Message-ID: > Stock gdb won't ever parse M3 expressions nor print M3 values. 1) it comes close enough; I think; the languages aren't so different 2) you are maybe somewhat ignoring GUI debuggers, built off of gdb or otherwise; in that case, the textual expression of things matters less -- at least for input > I would much prefer providing M3 library support for source debuggers to parse and print. On Windows the debuggers are extensible to varying degrees.cdb/ntsd/windbg you can write "pluings" for.Visual Studio you can plugin languages for clearly, as it already supports multiple. I don't know if the interfaces are public. But I still expect...hypothetical still I realize.. we can come close enough, suchthat forking gdb won't be worth it. Extending other compilers, maybe. - Jay Subject: Re: [M3devel] "C-generating backend progress report, that nobody asked for" :) From: hosking at cs.purdue.edu Date: Mon, 10 Sep 2012 20:07:27 -0400 CC: dragisha at m3w.org; m3devel at elegosoft.com To: jay.krell at cornell.edu Stock gdb won't ever parse M3 expressions nor print M3 values.So, there will always have to be some M3 support added.I would much prefer providing M3 library support for source debuggers to parse and print.I have no idea whether gdb has ever considered some of the extensibility support I pointed at in the link below. Antony Hosking | Associate Professor | Computer Science | Purdue University305 N. University Street | West Lafayette | IN 47907 | USAMobile +1 765 427 5484 On Sep 10, 2012, at 1:47 AM, Jay K wrote:Please, no. Stock gdb and stock Visual C++ and stock cdb/ntsd/windbg ought to work well with Modula-3. I expect they will pretty good pretty soon, and we should try to make them even better maybe... by making globals visible in a reasonable fashion. m3gdb isn't supported on Darwin and HP-UX (no stabs), at least. If the gcc backend becomes obsolete and deleted...m3gdb would be the last of the forked always-going-stale never-merging GPL stuff... i.e. another ripe target... - Jay Subject: Re: [M3devel] "C-generating backend progress report, that nobody asked for" :) From: hosking at cs.purdue.edu Date: Sun, 9 Sep 2012 20:54:12 -0400 CC: dragisha at m3w.org; m3devel at elegosoft.com To: jay.krell at cornell.edu Stock debuggers are designed for C. They generally will not be able to grok M3. Better to use M3 run-time type information as per m3gdb. See 10.1145/143103.143112. On Sep 9, 2012, at 4:07 PM, Jay wrote:The current method stinks for stock debugging. As I understand, globals are combined into structs & the fields all have generated names, & global records are flattened therein. It works. But stock debuggers see garbage. - Jay (briefly/pocket-sized-computer-aka-phone) On Sep 9, 2012, at 12:22 PM, Antony Hosking wrote: I mis-spoke. I think LLVM can cope with much the same as we currently have. Front-end will continue to compute alignments and layouts. We can assert the front-end's datalayout by passing it to LLVM explicitly, which will complain if it does not match the actual target. This is a rather nice feature of LLVM in that it allows us to retain control while having LLVM optimize accordingly. On Sep 9, 2012, at 11:05 AM, Antony Hosking wrote:Yes, agreed, these need to be properly typed too.First step will be to lift the M3CG interface.Problem: The compiler needs to control layout so that the run-time system knows where to find things. This means that we need to assert alignments and layouts produced by the backend are the same as those in the front-end. LLVM has nice ways to do this. How will we do it in the C backend? Does C have sufficient control over alignment? On Sep 9, 2012, at 10:53 AM, Jay wrote:Btw, can this include "segment"/globals? Can they each be separate named variables? At least some of them? - Jay (briefly/pocket-sized-computer-aka-phone) On Sep 9, 2012, at 7:48 AM, Antony Hosking wrote: I'm looking at it... First step is to lift slightly the level of M3CG to use properly typed memory access, instead of untyped address + offset. On Sep 9, 2012, at 2:32 AM, Dragi?a Duri? wrote:I hope somebody will take on LLVM :). -------------- next part -------------- An HTML attachment was scrubbed... URL: From dabenavidesd at yahoo.es Tue Sep 11 06:00:33 2012 From: dabenavidesd at yahoo.es (Daniel Alejandro Benavides D.) Date: Tue, 11 Sep 2012 05:00:33 +0100 (BST) Subject: [M3devel] pre-report In-Reply-To: <42DA95AA-8FC4-4DF5-84F3-D623FD83380B@cs.purdue.edu> Message-ID: <1347336033.29674.YahooMailClassic@web29701.mail.ird.yahoo.com> Hi all: Good point Antony, but they are NOT antisymmetric. I don't know about rules of the types you are talking about, my point is the compiler implementor (i.e you) must be free to implement both in both ways, that is you can select what to represent in? one or? in the other and should not affect the compiler behavior, that's why as DEC-SRC didn't implement? it, it should be able to read code in both cases. See for that p. 35: http://www.cs.virginia.edu/~weimer/2007-615/lectures/weimer-615-19.pdf Thanks in advance --- El lun, 10/9/12, Antony Hosking escribi?: De: Antony Hosking Asunto: Re: [M3devel] pre-report Para: "Daniel Alejandro Benavides D." CC: "Dragi?a Duri?" , "m3devel" Fecha: lunes, 10 de septiembre, 2012 21:28 Subtyping rulesWe write?T <: U?to indicate that?T?is a subtype of?U?and?U?is a supertype of?T.If?T <: U, then every value of type?T?is also a value of type?U. The converse does not hold: for example, a record or array type with packed fields contains the same values as the corresponding type with unpacked fields, but there is no subtype relation between them. On Sep 10, 2012, at 9:14 PM, "Daniel Alejandro Benavides D." wrote: Hi all: I'm not talking about packed types but values, they must be the same! Anyway, if you are talking about types I guess that's bigger question IMHO, so pass on to somebody, anyone? Thanks in advance --- El lun, 10/9/12, Antony Hosking escribi?: De: Antony Hosking Asunto: Re: [M3devel] pre-report Para: "Daniel Alejandro Benavides D." CC: "Dragi?a Duri?" , "m3devel" Fecha: lunes, 10 de septiembre, 2012 19:11 Not true. ?There are several mentions that packed types and their base types are not equal. ?In some circumstances they may be assignable. ?But in this case (aliasing a packed array using VAR) there is no way to communicate the packed-ness of the actual parameter to the callee. On Sep 10, 2012, at 5:30 PM, "Daniel Alejandro Benavides D." wrote: Hi all: I have read they are equally treated by the compiler, why do you make that illegal? If the compiler hasn't as isn't implemented it is an implementation limitation, but that shouldn't affect? other compilers that we might want to be source compatible with (I know of a front end but it's "confidential" that throws Attribute Grammar). Thanks in advance --- El lun, 10/9/12, Antony Hosking escribi?: De: Antony Hosking Asunto: Re: [M3devel] pre-report Para: "Dragi?a Duri?" CC: "m3devel" Fecha: lunes, 10 de septiembre, 2012 11:17 I?ve gone ahead and committed the "fix" to prohibit treating BITS FOR ARRAY OF X as assignable to VAR formals that are ARRAY OF X.? There is no way to communicate the alignment of any BITS FOR ARRAY in its containing structure (RECORD, etc.). >From the language spec: Implementations are allowed to forbid VAR or READONLY parameters of packed types. On Sep 10, 2012, at 12:11 PM, Antony Hosking wrote: > I?m trying to get a sense for what the correct behavior of the compiler should be in this case. I think that the passing of the unaligned ARRAY OF CHAR as an open array parameter should be disallowed.? There is no way to communicate the alignment in the dope vector built for the open array formal. > > In which case, the fix is the following patch to Formal.m3, disallowing a formal parameter for a > > *** Formal.m3.~1.16.~??? Wed Sep? 5 11:03:31 2012 > --- Formal.m3??? Mon Sep 10 12:07:46 2012 > *************** > *** 356,361 **** > --- 356,362 ---- >? ? ? ? ? ? ? ELSIF Type.IsEqual (t, te, NIL) THEN >? ? ? ? ? ? ? ? Expr.NeedsAddress (e); >? ? ? ? ? ? ? ELSIF ArrayType.Split (t, index, elt) > +? ? ? ? ? ? ???AND ArrayType.Split (te, index, elt) >? ? ? ? ? ? ? ? AND Type.IsAssignable (t, te) THEN >? ? ? ? ? ? ? ? Expr.NeedsAddress (e); >? ? ? ? ? ? ? ELSE > > > Can anyone think if this will break any existing code?? I can?t think of anything where it will break (assigning something that does not have array type to a formal parameter of array type). > > On Sep 10, 2012, at 3:41 AM, Dragi?a Duri? wrote: > >> MODULE TestCase EXPORTS Main; >> >> PROCEDURE Do(VAR b: ARRAY OF CHAR) = >> BEGIN >> END Do; >> >> VAR >> arg: RECORD >>???a: BITS 1 FOR BOOLEAN; (* case 2 is this, case 1 is: comment a out :) *) >>???b: BITS 24 FOR ARRAY [0..2] OF CHAR; >> END; >> >> BEGIN >> Do(arg.b); >> END TestCase. >> >> -- >> Divided by a common language >> >> Dragi?a Duri? >> dragisha at m3w.org >> >> >> >> >> On Sep 10, 2012, at 4:03 AM, Antony Hosking wrote: >> >>> What?s the source code? >>> Testcase please... >>> >>> On Sep 8, 2012, at 3:23 AM, Dragi?a Duri? wrote: >>> >>>> Just got this, many times in a row :) >>>> >>>> === >>>> % cm3 >>>> --- building in ../AMD64_DARWIN --- >>>> >>>> new source -> compiling Descriptors.m3 >>>> >>>> >>>> *** >>>> *** runtime error: >>>> ***? ? <*ASSERT*> failed. >>>> ***? ? file "../src/values/Formal.m3", line 689 >>>> *** >>>> >>>> zsh: abort? ? ? cm3 >>>> >>>> >>>> % cm3 -? >>>> Critical Mass Modula-3 version d5.9.0 >>>> last updated: 2010-07-21 >>>> compiled: 2011-03-23 04:04:18 >>>> configuration: /usr/local/cm3/bin/cm3.cfg >>>> host: AMD64_DARWIN >>>> target: AMD64_DARWIN >>>> >>>> -- >>>> Divided by a common language >>>> >>>> Dragi?a Duri? >>>> dragisha at m3w.org >>>> >>>> >>>> >>>> >>> >> > -------------- next part -------------- An HTML attachment was scrubbed... URL: From dragisha at m3w.org Tue Sep 11 08:07:35 2012 From: dragisha at m3w.org (=?utf-8?Q?Dragi=C5=A1a_Duri=C4=87?=) Date: Tue, 11 Sep 2012 08:07:35 +0200 Subject: [M3devel] pre-report In-Reply-To: <92BD790D-6AC4-4170-9515-A8842011CF2B@cs.purdue.edu> References: <40145A43-9420-4ECF-899C-3CC015ED2B99@m3w.org> <91BD5809-66C2-4072-95A3-A98236F30CC3@cs.purdue.edu> <92BD790D-6AC4-4170-9515-A8842011CF2B@cs.purdue.edu> Message-ID: <94A06B7F-5135-49DF-9FDC-49B849546F50@m3w.org> I have no problem with compiler forbidding it, it is logical. And much better than compiler crash, or internal CG error :). And my example caught both. Thank you for the fix! -- Divided by a common language Dragi?a Duri? dragisha at m3w.org On Sep 10, 2012, at 6:17 PM, Antony Hosking wrote: > I?ve gone ahead and committed the "fix" to prohibit treating BITS FOR ARRAY OF X as assignable to VAR formals that are ARRAY OF X. There is no way to communicate the alignment of any BITS FOR ARRAY in its containing structure (RECORD, etc.). > > From the language spec: > > Implementations are allowed to forbid VAR or READONLY parameters of packed types. > > On Sep 10, 2012, at 12:11 PM, Antony Hosking wrote: > >> I?m trying to get a sense for what the correct behavior of the compiler should be in this case. I think that the passing of the unaligned ARRAY OF CHAR as an open array parameter should be disallowed. There is no way to communicate the alignment in the dope vector built for the open array formal. >> >> In which case, the fix is the following patch to Formal.m3, disallowing a formal parameter for a >> >> *** Formal.m3.~1.16.~ Wed Sep 5 11:03:31 2012 >> --- Formal.m3 Mon Sep 10 12:07:46 2012 >> *************** >> *** 356,361 **** >> --- 356,362 ---- >> ELSIF Type.IsEqual (t, te, NIL) THEN >> Expr.NeedsAddress (e); >> ELSIF ArrayType.Split (t, index, elt) >> + AND ArrayType.Split (te, index, elt) >> AND Type.IsAssignable (t, te) THEN >> Expr.NeedsAddress (e); >> ELSE >> >> >> Can anyone think if this will break any existing code? I can?t think of anything where it will break (assigning something that does not have array type to a formal parameter of array type). >> >> On Sep 10, 2012, at 3:41 AM, Dragi?a Duri? wrote: >> >>> MODULE TestCase EXPORTS Main; >>> >>> PROCEDURE Do(VAR b: ARRAY OF CHAR) = >>> BEGIN >>> END Do; >>> >>> VAR >>> arg: RECORD >>> a: BITS 1 FOR BOOLEAN; (* case 2 is this, case 1 is: comment a out :) *) >>> b: BITS 24 FOR ARRAY [0..2] OF CHAR; >>> END; >>> >>> BEGIN >>> Do(arg.b); >>> END TestCase. >>> >>> -- >>> Divided by a common language >>> >>> Dragi?a Duri? >>> dragisha at m3w.org >>> >>> >>> >>> >>> On Sep 10, 2012, at 4:03 AM, Antony Hosking wrote: >>> >>>> What?s the source code? >>>> Testcase please... >>>> >>>> On Sep 8, 2012, at 3:23 AM, Dragi?a Duri? wrote: >>>> >>>>> Just got this, many times in a row :) >>>>> >>>>> === >>>>> % cm3 >>>>> --- building in ../AMD64_DARWIN --- >>>>> >>>>> new source -> compiling Descriptors.m3 >>>>> >>>>> >>>>> *** >>>>> *** runtime error: >>>>> *** <*ASSERT*> failed. >>>>> *** file "../src/values/Formal.m3", line 689 >>>>> *** >>>>> >>>>> zsh: abort cm3 >>>>> >>>>> >>>>> % cm3 -? >>>>> Critical Mass Modula-3 version d5.9.0 >>>>> last updated: 2010-07-21 >>>>> compiled: 2011-03-23 04:04:18 >>>>> configuration: /usr/local/cm3/bin/cm3.cfg >>>>> host: AMD64_DARWIN >>>>> target: AMD64_DARWIN >>>>> >>>>> -- >>>>> Divided by a common language >>>>> >>>>> Dragi?a Duri? >>>>> dragisha at m3w.org >>>>> >>>>> >>>>> >>>>> >>>> >>> >> > -------------- next part -------------- An HTML attachment was scrubbed... URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 495 bytes Desc: Message signed with OpenPGP using GPGMail URL: From jay.krell at cornell.edu Thu Sep 13 23:07:36 2012 From: jay.krell at cornell.edu (Jay K) Date: Thu, 13 Sep 2012 21:07:36 +0000 Subject: [M3devel] C backend In-Reply-To: <20120913100905.28F5CCC85C@birch.elegosoft.com> References: <20120913100905.28F5CCC85C@birch.elegosoft.com> Message-ID: With this little change, I can compile all of cm3 to C and the compile that. "cm3" as in the builder/compiler/frontend/quake, not the entire cm3 system. Next is to get copy main.c *.c *.h (the stuff written in C), andtry to link it.. Note: it might be nice to get better types to the backend, e.g.instead ofADDRESS strcat(ADDRESS, ADDRESS);char* strcat(char*, const char*); - Jay > Date: Thu, 13 Sep 2012 12:09:05 +0000 > To: m3commit at elegosoft.com > From: jkrell at elego.de > Subject: [M3commit] CVS Update: cm3 > > CVSROOT: /usr/cvs > Changes by: jkrell at birch. 12/09/13 12:09:05 > > Modified files: > cm3/m3-sys/m3back/src/: M3C.m3 > > Log message: > do our own integer to text conversions > workaround more bad declarations: ldexp signgam cabs frexp modf jn yn -------------- next part -------------- An HTML attachment was scrubbed... URL: From dragisha at m3w.org Fri Sep 14 08:51:28 2012 From: dragisha at m3w.org (=?utf-8?Q?Dragi=C5=A1a_Duri=C4=87?=) Date: Fri, 14 Sep 2012 08:51:28 +0200 Subject: [M3devel] "C-generating backend progress report, that nobody asked for" :) In-Reply-To: <00232380-526C-46E5-B334-11F902A64997@cs.purdue.edu> References: <84C67B7F-A915-4DE8-B14C-44E6F87DE85D@gmail.com> <9748E313-E0EF-45FA-A01F-DE0C58FDDED7@cs.purdue.edu> <4CD63AEF-523B-423F-9690-7DEDBF8BEFFC@gmail.com>, <43C4B30F-24AB-4421-923B-9F32C1807AF5@cs.purdue.edu> <00232380-526C-46E5-B334-11F902A64997@cs.purdue.edu> Message-ID: <633CB871-FC4D-4DD6-B350-87AB56418A1F@m3w.org> Got this Ramsey paper.. My first thought was - why wait for gdb, why reinvent debugging..? In my book, debugger is one more reason to jump over to LLVM bandwagon. I really like what GCC people did and do. Great minds, great hackers. And no less people than anybody else. And I am perfectly aware just how bad they (RMS for sure, probably others) feel about Modula-3. It is logical thing to do - shrug these problems off. After two decades of catching up with their cryptic changes, ever changing undocumented behavior, rewriting of specific support modules? C backend is good thing to have, and kudos to Jay for it. But? LLVM is what we really need. TIA -- Divided by a common language Dragi?a Duri? dragisha at m3w.org On Sep 11, 2012, at 2:07 AM, Antony Hosking wrote: > Stock gdb won?t ever parse M3 expressions nor print M3 values. > So, there will always have to be some M3 support added. > I would much prefer providing M3 library support for source debuggers to parse and print. > I have no idea whether gdb has ever considered some of the extensibility support I pointed at in the link below. > > Antony Hosking | Associate Professor | Computer Science | Purdue University > 305 N. University Street | West Lafayette | IN 47907 | USA > Mobile +1 765 427 5484 > > > > > > On Sep 10, 2012, at 1:47 AM, Jay K wrote: > >> Please, no. >> >> Stock gdb and stock Visual C++ and stock cdb/ntsd/windbg ought to work well with Modula-3. >> I expect they will pretty good pretty soon, and we should try to make them even better maybe... >> by making globals visible in a reasonable fashion. >> >> >> m3gdb isn't supported on Darwin and HP-UX (no stabs), at least. >> If the gcc backend becomes obsolete and deleted...m3gdb would be the last of the >> forked always-going-stale never-merging GPL stuff... i.e. another ripe target... >> >> >> >> - Jay >> >> Subject: Re: [M3devel] "C-generating backend progress report, that nobody asked for" :) >> From: hosking at cs.purdue.edu >> Date: Sun, 9 Sep 2012 20:54:12 -0400 >> CC: dragisha at m3w.org; m3devel at elegosoft.com >> To: jay.krell at cornell.edu >> >> Stock debuggers are designed for C. They generally will not be able to grok M3. Better to use M3 run-time type information as per m3gdb. See 10.1145/143103.143112. >> >> >> On Sep 9, 2012, at 4:07 PM, Jay wrote: >> >> The current method stinks for stock debugging. As I understand, globals are combined into structs & the fields all have generated names, & global records are flattened therein. >> >> >> It works. But stock debuggers see garbage. >> >> >> - Jay (briefly/pocket-sized-computer-aka-phone) >> >> On Sep 9, 2012, at 12:22 PM, Antony Hosking wrote: >> >> I mis-spoke. I think LLVM can cope with much the same as we currently have. Front-end will continue to compute alignments and layouts. We can assert the front-end's datalayout by passing it to LLVM explicitly, which will complain if it does not match the actual target. This is a rather nice feature of LLVM in that it allows us to retain control while having LLVM optimize accordingly. >> >> On Sep 9, 2012, at 11:05 AM, Antony Hosking wrote: >> >> Yes, agreed, these need to be properly typed too. >> First step will be to lift the M3CG interface. >> Problem: The compiler needs to control layout so that the run-time system knows where to find things. This means that we need to assert alignments and layouts produced by the backend are the same as those in the front-end. LLVM has nice ways to do this. How will we do it in the C backend? Does C have sufficient control over alignment? >> >> On Sep 9, 2012, at 10:53 AM, Jay wrote: >> >> Btw, can this include "segment"/globals? Can they each be separate named variables? At least some of them? >> >> >> - Jay (briefly/pocket-sized-computer-aka-phone) >> >> On Sep 9, 2012, at 7:48 AM, Antony Hosking wrote: >> >> I'm looking at it... >> >> First step is to lift slightly the level of M3CG to use properly typed memory access, instead of untyped address + offset. >> >> On Sep 9, 2012, at 2:32 AM, Dragi?a Duri? wrote: >> >> I hope somebody will take on LLVM :). > -------------- next part -------------- An HTML attachment was scrubbed... URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 495 bytes Desc: Message signed with OpenPGP using GPGMail URL: From jay.krell at cornell.edu Fri Sep 14 10:01:17 2012 From: jay.krell at cornell.edu (Jay K) Date: Fri, 14 Sep 2012 08:01:17 +0000 Subject: [M3devel] friendly reminder/request for cooperative suspend Message-ID: friendly reminder/request: I'd like to see the system changed to use cooperative suspend. Combined with a C backend, that would greatly expand portability and remove existing target-dependent code (i.e. already ported) from the system. I'm not confident that GetThreadContext works on "wow64".It'd fix that. We can compute the top/bottom of the stack fairly portably -- address of locals.We can capture current context/registers via setjmp.Or maybe getcontext.(We should find out about setjmp/longjmp munging -- what gets munged? Everything? Just non-gc-roots? Only after longjmp?)Itanium is special -- there is a second stack growing up from the same base. I'd like this way more than LLVM. Maybe I can work on. Maybe. I believe typical production Java VMs use cooperative suspend. - Jay -------------- next part -------------- An HTML attachment was scrubbed... URL: From jay.krell at cornell.edu Fri Sep 14 10:41:51 2012 From: jay.krell at cornell.edu (Jay K) Date: Fri, 14 Sep 2012 08:41:51 +0000 Subject: [M3devel] -check_procs? Message-ID: The front end has a lot of internal options. Here is one: -check_procs. It has one effect: PROCEDURE Gen_Call_indirect (t: Type; cc: CallingConvention) = BEGIN IF Host.doProcChk THEN Check_nil (RuntimeError.BadMemoryReference); END; Does it really make sense that we use this for NT/x86 and only NT/x86?I kind of think we should use it never or use it always.Or use it on all but NT/x86 -- where the exception handling mechanism is pretty well defined and easy to program. We use it on NT/x86 only (the opposite of my suggestion). Using it always would bloat our code but trivially give us "safe" portable/consistent behavior.The Modula-3 code would stop right away by calling portable code.Instead of triggering whatever platform-specific signal/exception. I happened on this code...looking at other stuff...obvious reasons if you look around... - Jay -------------- next part -------------- An HTML attachment was scrubbed... URL: From jay.krell at cornell.edu Fri Sep 14 10:57:55 2012 From: jay.krell at cornell.edu (Jay K) Date: Fri, 14 Sep 2012 08:57:55 +0000 Subject: [M3devel] adapting C backend into system Message-ID: I'm moving ahead..will change PPC_DARWIN on my system to generate C.My system is 64bit capable MacBook.It can run PowerPC (I'm not upgrading the OS to one that omits Rosetta!)PowerPC emulation isn't adequate for our preemptive suspend, but ok. I suspect PPC_DARWIN is little used enough, that when I'm satisfied that it works,I can commit it and nobody will complain. So then.. M3BackendMode_t = { (* The primary modes are currently 0 and 3. *) IntegratedObject, (* "0" -- don't call m3_backend, M3CG produces object code *) IntegratedAssembly, (* "1" -- don't call m3_backend, M3CG produces assembly code *) ExternalObject, (* "2" -- call m3_backend, it produces object code *) ExternalAssembly (* "3" -- call m3_backend, it produces assembly code *) }; ExternalObject can be made to work w/o changing cm3.I would build a separate driver like-m3cgcat.I would change the config/quake m3_backend to call it.Heck, ExternalAssembly could be made to work. (on Posix. maybe on NT, but pointless) But that's not really the right way.I should add a new mode called IntegratedC.Agreed?Or just C.ExternalC would be kind of dumb..it'd be to use like-m3cgcat from m3_backend, and then in cm3 we'd call compile_c(). You might as well have m3_backend call compile_c andcall it IntegratedObject. Agreed? New mode called "C"? Think ahead.I want to generate C++, for portable/efficient exception handling.But not yet. Would that be yet another mode? If I don't change cm3 and add a mode, I'm "stuck" writing out the .mc files, reading them back, running a little driver. There is some developer convenience there, but it is needlessly inefficient when things are working. I guess I might have a chance with IntegratedObject.M3C.m3 would call out to quake. Think ahead..I need a cross/boot story.That writes out the .c files and stops.Ok..shouldn't be difficult..Seems kind of better therefore to add a mode, so the cm3 knows about this but M3C does not.Having the backend call out to quake is a bit odd. But the way we configure and detect the C compiler is too much quake code to abandon. I don't want to bake that into M3C.m3. Thoughts? Thanks, - Jay -------------- next part -------------- An HTML attachment was scrubbed... URL: From jay.krell at cornell.edu Fri Sep 14 12:58:14 2012 From: jay.krell at cornell.edu (Jay K) Date: Fri, 14 Sep 2012 10:58:14 +0000 Subject: [M3devel] calling conventions.. Message-ID: Our calling convention handling seems kind of messed up. results_on_left: this could be removed; frontend could presume backends know how to return structs by value It appears we set it "wrong" currently, e.g. on AMD64_DARWIN, but it only matters for interop with unusual C code. standard_structs: this could be removed; frontend could presume backend can pass structs by value m3x86 already implements this It should be easier for most other backends, including m3cc. args_left_to_right: this could be removed; frontend could presume it is always true, and backend could do the reversing; m3cc already does It is currently a convenience for M3x86.m3 though. Which leaves the only thing about a calling convention its name/id. And then, as I proposed years ago, you might as well let allplatforms support all calling convention names, even if theyare meaningless. That way you could unfork large swaths of <*extern*>that vary only because Win32 specifies a calling convention.Heck, look at how NT/amd64 C compiler works -- it accepts and ignorescalling conventions too, for source compatibility with NT/x86. (You see, I'm looking at all the code that looks at "backend mode".) - Jay -------------- next part -------------- An HTML attachment was scrubbed... URL: From jay.krell at cornell.edu Fri Sep 14 13:34:37 2012 From: jay.krell at cornell.edu (Jay K) Date: Fri, 14 Sep 2012 11:34:37 +0000 Subject: [M3devel] GenerateCGMain "plan" .. unreachable code... Message-ID: http://modula3.elegosoft.com/cgi-bin/cvsweb.cgi/cm3/m3-sys/cm3/src/Builder.m3?rev=1.1.1.1;content-type=text%2Fplain PROCEDURE GenerateCGMain (s: State; Main_O: TEXT) = VAR ... plan : [0..3] := 0; .. no uses of "plan" ... if plan = 2 that can't happen. Clearly the point was to check the backend mode. or set plan := ORD(mode) (no point in that; elsewhere they do that and increment by 4 if bootstrapping..kind of messy this code..it seems it could be better factored...) Might as well we chuck the option m3main_in_c and always do it that way? - Jay -------------- next part -------------- An HTML attachment was scrubbed... URL: From jay.krell at cornell.edu Fri Sep 14 15:14:44 2012 From: jay.krell at cornell.edu (Jay K) Date: Fri, 14 Sep 2012 13:14:44 +0000 Subject: [M3devel] C backend progress Message-ID: cd m3-libs/m3corerm -rf PPC_DARWINCM3_TARGET=PPC_DARWIN cm3 very turnkey! small cm3/config changes... no external driver/process/"mc" files... => success..it compiles and links...haven't run any of the code :) cd ../libm3CM3_TARGET=PPC_DARWIN cm3 =>Sx.m3.c: In function ?Sx__ISO_Latin_printing?:Sx.m3.c:4063: warning: comparison is always true due to limited range of data typeSx.m3.c: In function ?Sx__SetReadMacro?:Sx.m3.c:6058: warning: passing argument 1 of ?m3_set_difference? makes integer from pointer without a castSx.m3.c:6058: warning: passing argument 2 of ?m3_set_difference? from incompatible pointer typeSx.m3.c:6058: warning: passing argument 3 of ?m3_set_difference? from incompatible pointer typeSx.m3.c:6058: error: too few arguments to function ?m3_set_difference?Sx.m3.c:6061: error: syntax error before ?memcpy?Sx.m3.c:6187: warning: passing argument 1 of ?m3_set_union? makes integer from pointer without a castSx.m3.c:6187: warning: passing argument 2 of ?m3_set_union? from incompatible pointer typeSx.m3.c:6187: warning: passing argument 3 of ?m3_set_union? from incompatible pointer typeSx.m3.c:6187: error: too few arguments to function ?m3_set_union?Sx.m3.c:6190: error: syntax error before ?memcpy? compile_c => 1 surely simple problems.. - Jay -------------- next part -------------- An HTML attachment was scrubbed... URL: From jay.krell at cornell.edu Fri Sep 14 15:20:48 2012 From: jay.krell at cornell.edu (Jay K) Date: Fri, 14 Sep 2012 13:20:48 +0000 Subject: [M3devel] changed to "builder" for C backend Message-ID: attached are a good stab at the changes..they are working for me..thoughts?approval?I can wait for things to be working more... -------------- next part -------------- An HTML attachment was scrubbed... URL: -------------- next part -------------- An embedded and charset-unspecified text was scrubbed... Name: 3.txt URL: From hosking at cs.purdue.edu Fri Sep 14 16:51:37 2012 From: hosking at cs.purdue.edu (Antony Hosking) Date: Fri, 14 Sep 2012 10:51:37 -0400 Subject: [M3devel] changed to "builder" for C backend In-Reply-To: References: Message-ID: Let?s hold off on committing the change to the trunk until you?ve had a chance to do more testing. On Sep 14, 2012, at 9:20 AM, Jay K wrote: > attached are a good stab at the changes..they are working for me.. > thoughts? > approval? > I can wait for things to be working more... What?s not working? > > <3.txt> -------------- next part -------------- An HTML attachment was scrubbed... URL: From hosking at cs.purdue.edu Fri Sep 14 17:10:03 2012 From: hosking at cs.purdue.edu (Antony Hosking) Date: Fri, 14 Sep 2012 11:10:03 -0400 Subject: [M3devel] friendly reminder/request for cooperative suspend In-Reply-To: References: Message-ID: <71F41B96-DD1F-4A0A-9D7B-4DF925462EA4@cs.purdue.edu> Yes, this is on the top of my list of things to do. Plus fix some atomics bugs. atomics plus cooperative suspend gives us a much better story on locks too. We could even have a proper memory model like C++11. LLVM would also be great (better even than the C backend) because we?d get some decent optimization passes. On Sep 14, 2012, at 4:01 AM, Jay K wrote: > friendly reminder/request: I'd like to see the system changed to use cooperative suspend. > > > Combined with a C backend, that would greatly expand portability and remove existing target-dependent code (i.e. already ported) from the system. > > > I'm not confident that GetThreadContext works on "wow64". > It'd fix that. > > > We can compute the top/bottom of the stack fairly portably -- address of locals. > We can capture current context/registers via setjmp. > Or maybe getcontext. > (We should find out about setjmp/longjmp munging -- what gets munged? Everything? Just non-gc-roots? Only after longjmp?) > Itanium is special -- there is a second stack growing up from the same base. > > > I'd like this way more than LLVM. > > > Maybe I can work on. Maybe. > > > I believe typical production Java VMs use cooperative suspend. > > > - Jay -------------- next part -------------- An HTML attachment was scrubbed... URL: From hosking at cs.purdue.edu Fri Sep 14 17:05:37 2012 From: hosking at cs.purdue.edu (Antony Hosking) Date: Fri, 14 Sep 2012 11:05:37 -0400 Subject: [M3devel] -check_procs? In-Reply-To: References: Message-ID: The question is: what does calling a NIL procedure do on the target? I suggest leave it for now as is for the targets that don?t do the check. What is the exception handling story for NT/x86? Why does it not work to use exception on NIL call for that target? On Sep 14, 2012, at 4:41 AM, Jay K wrote: > The front end has a lot of internal options. > > > Here is one: -check_procs. > > It has one effect: > > > PROCEDURE Gen_Call_indirect (t: Type; cc: CallingConvention) = > BEGIN > IF Host.doProcChk THEN Check_nil (RuntimeError.BadMemoryReference); END; > > > Does it really make sense that we use this for NT/x86 and only NT/x86? > I kind of think we should use it never or use it always. > Or use it on all but NT/x86 -- where the exception handling mechanism is pretty well defined and easy to program. We use it on NT/x86 only (the opposite of my suggestion). > > > Using it always would bloat our code but trivially give us "safe" portable/consistent behavior. > The Modula-3 code would stop right away by calling portable code. > Instead of triggering whatever platform-specific signal/exception. > > > I happened on this code...looking at other stuff...obvious reasons if you look around... > > > - Jay -------------- next part -------------- An HTML attachment was scrubbed... URL: From jay.krell at cornell.edu Fri Sep 14 22:08:07 2012 From: jay.krell at cornell.edu (Jay K) Date: Fri, 14 Sep 2012 20:08:07 +0000 Subject: [M3devel] changed to "builder" for C backend In-Reply-To: References: , Message-ID: > What?s not working? Builder-wise, it looks good. Backend-wise: m3core compiles and links; libm3 gets to:new source -> compiling ConvertPacking.m3m3front ../src/pickle/ver2/ConvertPacking.m3 -w1gcc -gstabs+ -fPIC -m32 -arch ppc -I/cm3/pkg/m3core/src/unix/Common -I/cm3/pkg/m3core/src -I/cm3/pkg/m3core/src/Csupport/Common -I/cm3/pkg/m3core/src/Csupport/big-endian -I/cm3/pkg/m3core/src/Csupport/libgcc -I/cm3/pkg/m3core/src/runtime/common -I/cm3/pkg/m3core/src/runtime/POSIX -I/cm3/pkg/m3core/src/runtime/ex_frame -I/cm3/pkg/m3core/src/thread/Common -I/cm3/pkg/m3core/src/thread/PTHREAD -I/cm3/pkg/m3core/src/C/Common -I/cm3/pkg/m3core/src/float/C99 -I/cm3/pkg/m3core/src/time/POSIX -I../src/os/POSIX -I../src/uid/POSIX -c ConvertPacking.m3.c -o ConvertPacking.moConvertPacking.m3.c: In function ?ConvertPacking__Init?:ConvertPacking.m3.c:9856: error: incompatible type for argument 1 of ?ConvertPacking__GetWordKind?ConvertPacking.m3.c:9856: error: incompatible type for argument 2 of ?ConvertPacking__GetWordKind?...other errors I haven't run anything. My plan is not to run anything until I can compile/link cm3, and then run that. Hm.. -- all those -I options aren't really desired. They were for compiling user-written C code in libm3...not for backend-generated C. But that isn't really a problem. I also know some stuff needs work, like supporting arbitrary struct sizes.I predeclare up to a certain size. - Jay From: hosking at cs.purdue.edu Date: Fri, 14 Sep 2012 10:51:37 -0400 To: jay.krell at cornell.edu CC: m3devel at elegosoft.com Subject: Re: [M3devel] changed to "builder" for C backend Let?s hold off on committing the change to the trunk until you?ve had a chance to do more testing. On Sep 14, 2012, at 9:20 AM, Jay K wrote:attached are a good stab at the changes..they are working for me..thoughts?approval?I can wait for things to be working more... What?s not working? <3.txt> -------------- next part -------------- An HTML attachment was scrubbed... URL: From jay.krell at cornell.edu Fri Sep 14 22:11:18 2012 From: jay.krell at cornell.edu (Jay K) Date: Fri, 14 Sep 2012 20:11:18 +0000 Subject: [M3devel] -check_procs? In-Reply-To: References: , Message-ID: Calling NIL on NT/x86 is very well defined.It is the same as reading/writing NIL.You get a "structured exception" that you can catch using __try/__except. > Why does it not work to use exception on NIL call for that target? Who says it doesn't? Our current implementation suggests it doesn't, but that doesn't mean anything. Current implementation is often backwards. Maybe we install signal handlers on other platforms, but we don't put in the equivalant high-level __try/__except on NT/x86.Maybe we should provide a "ThreadBase" in C. But it's not like the process just jumps off into the weeds and does random stuff.Debuggers break right and show a callstack. Without all that extra Modula-3 runtime stuff... - Jay Subject: Re: [M3devel] -check_procs? From: hosking at cs.purdue.edu Date: Fri, 14 Sep 2012 11:05:37 -0400 CC: m3devel at elegosoft.com To: jay.krell at cornell.edu The question is: what does calling a NIL procedure do on the target? I suggest leave it for now as is for the targets that don?t do the check. What is the exception handling story for NT/x86? Why does it not work to use exception on NIL call for that target? On Sep 14, 2012, at 4:41 AM, Jay K wrote:The front end has a lot of internal options. Here is one: -check_procs. It has one effect: PROCEDURE Gen_Call_indirect (t: Type; cc: CallingConvention) = BEGIN IF Host.doProcChk THEN Check_nil (RuntimeError.BadMemoryReference); END; Does it really make sense that we use this for NT/x86 and only NT/x86?I kind of think we should use it never or use it always.Or use it on all but NT/x86 -- where the exception handling mechanism is pretty well defined and easy to program. We use it on NT/x86 only (the opposite of my suggestion). Using it always would bloat our code but trivially give us "safe" portable/consistent behavior.The Modula-3 code would stop right away by calling portable code.Instead of triggering whatever platform-specific signal/exception. I happened on this code...looking at other stuff...obvious reasons if you look around... - Jay -------------- next part -------------- An HTML attachment was scrubbed... URL: From jay.krell at cornell.edu Fri Sep 14 22:24:19 2012 From: jay.krell at cornell.edu (Jay K) Date: Fri, 14 Sep 2012 20:24:19 +0000 Subject: [M3devel] backend mode integratedassembly Message-ID: There is a backend mode for an integrated backend that generates assembly.This is dead code, right?Remove it? <* ASSERT FALSE *> (but then I get warnings about unreachable code -- comment it out? - Jay -------------- next part -------------- An HTML attachment was scrubbed... URL: From hosking at cs.purdue.edu Fri Sep 14 23:07:28 2012 From: hosking at cs.purdue.edu (Antony Hosking) Date: Fri, 14 Sep 2012 17:07:28 -0400 Subject: [M3devel] backend mode integratedassembly In-Reply-To: References: Message-ID: <09E3C8E2-B969-4294-80A2-222700E537C8@cs.purdue.edu> On Sep 14, 2012, at 4:24 PM, Jay K wrote: > There is a backend mode for an integrated backend that generates assembly. > This is dead code, right? > Remove it? > <* ASSERT FALSE *> (but then I get warnings about unreachable code -- comment it out? There is nothing to be gained from removing it. Maybe someone will want to experiment/resurrect. -------------- next part -------------- An HTML attachment was scrubbed... URL: From jay.krell at cornell.edu Fri Sep 14 23:24:49 2012 From: jay.krell at cornell.edu (Jay) Date: Fri, 14 Sep 2012 14:24:49 -0700 Subject: [M3devel] friendly reminder/request for cooperative suspend In-Reply-To: <71F41B96-DD1F-4A0A-9D7B-4DF925462EA4@cs.purdue.edu> References: <71F41B96-DD1F-4A0A-9D7B-4DF925462EA4@cs.purdue.edu> Message-ID: <74FF0573-8502-4698-AEE0-38A8E41343A8@gmail.com> A C backend offers lots of optimizations via the C compiler.. - Jay (briefly/pocket-sized-computer-aka-phone) On Sep 14, 2012, at 8:10 AM, Antony Hosking wrote: > Yes, this is on the top of my list of things to do. > Plus fix some atomics bugs. > atomics plus cooperative suspend gives us a much better story on locks too. > We could even have a proper memory model like C++11. > > LLVM would also be great (better even than the C backend) because we?d get some decent optimization passes. > > > On Sep 14, 2012, at 4:01 AM, Jay K wrote: > >> friendly reminder/request: I'd like to see the system changed to use cooperative suspend. >> >> >> Combined with a C backend, that would greatly expand portability and remove existing target-dependent code (i.e. already ported) from the system. >> >> >> I'm not confident that GetThreadContext works on "wow64". >> It'd fix that. >> >> >> We can compute the top/bottom of the stack fairly portably -- address of locals. >> We can capture current context/registers via setjmp. >> Or maybe getcontext. >> (We should find out about setjmp/longjmp munging -- what gets munged? Everything? Just non-gc-roots? Only after longjmp?) >> Itanium is special -- there is a second stack growing up from the same base. >> >> >> I'd like this way more than LLVM. >> >> >> Maybe I can work on. Maybe. >> >> >> I believe typical production Java VMs use cooperative suspend. >> >> >> - Jay > -------------- next part -------------- An HTML attachment was scrubbed... URL: From jay.krell at cornell.edu Sat Sep 15 00:44:49 2012 From: jay.krell at cornell.edu (Jay K) Date: Fri, 14 Sep 2012 22:44:49 +0000 Subject: [M3devel] backend mode integratedassembly In-Reply-To: <09E3C8E2-B969-4294-80A2-222700E537C8@cs.purdue.edu> References: , <09E3C8E2-B969-4294-80A2-222700E537C8@cs.purdue.edu> Message-ID: It somewhat gets in the way of reading/writing the code.It bit-rots. I kind of think this area needs a bit of a reworking.There could/should be more code sharing. (Or maybe actually less infrastructure.) If anyone really did write an integrated backend that produced assembly, they could/should then have that backend go ahead and have that backend call the assembler. Maybe. The -boot and -keep flags should perhaps be passed on the backend. By this measure, I might as well just call my C backend "IntegratedObject", and have it call out to quake/config to run the C compiler -- heck, esp. if RunCC was made part of Builder.i3 instead of just Builder.m3 (or passed down as a function pointer -- I guess otherwise there might be a circular dependency). I nearly did that.I guess I was too lazy to teach my backend how to call out to the C compiler via quake, rather than reuse Builder.m3. That is...I'm not sure there should be any modes at all.There should be "types" which is just which Interface.T implementation of M3CG to instantiate.They would all be "IntegratedObject".C backend would like I said, generate C itself, then call out to quake/compile_c.(It could almost just be "cc foo.c -o foo.o", but that isn't quite adequate/portable). IntegratedAssembly would generate assemlby, then call out to quake/assemble, if it doesn't know otherwise. m3cc/m3back/m3cg would be a very thin wrapper over m3cg.Everything but open/close would call down to m3cg_binwr.At close time, it would call out to quake/config to run the assembler, if not bootstrapping. I like it -- no modes, just specific types. They would all be treated as "IntegratedObject". Question would how much sharing/commonality is there really. I guess it doesn't matter much... I guess "externals" backends are convenient, to test?So going though m3cg_binwr is nice?So then you get commonality there? I'm still not sure that belongs in Builder.m3, vs. "M3CG_ExternalViaBinWr".Which could know about the boot/keep flags and keep the .mc files.. - Jay Subject: Re: [M3devel] backend mode integratedassembly From: hosking at cs.purdue.edu Date: Fri, 14 Sep 2012 17:07:28 -0400 CC: m3devel at elegosoft.com To: jay.krell at cornell.edu On Sep 14, 2012, at 4:24 PM, Jay K wrote:There is a backend mode for an integrated backend that generates assembly.This is dead code, right?Remove it? <* ASSERT FALSE *> (but then I get warnings about unreachable code -- comment it out? There is nothing to be gained from removing it.Maybe someone will want to experiment/resurrect. -------------- next part -------------- An HTML attachment was scrubbed... URL: From jay.krell at cornell.edu Sat Sep 15 01:52:26 2012 From: jay.krell at cornell.edu (Jay K) Date: Fri, 14 Sep 2012 23:52:26 +0000 Subject: [M3devel] backend mode integratedassembly In-Reply-To: <17CC0C59-58FC-4BF5-8297-9273E24F7357@gmail.com> References: <09E3C8E2-B969-4294-80A2-222700E537C8@cs.purdue.edu> , <17CC0C59-58FC-4BF5-8297-9273E24F7357@gmail.com> Message-ID: > Cross compiles can produce assembler It works this way today, but I don't see the point in the future.M3x86.m3 generates object files, always.It is widely wished to have C compilers output object files directly instead of assembly, and many do, but not gcc.M3C.m3 will always generate C. Though there is an analog in there in my theoretical ideas..if there was just one mode -- IntegratedObject -- then M3C.m3 would internally call quake/config to compile C to .o. Unless bootstrapping, then it would keep as C. I think "bootstrapping" isn't likely infrastructurally/consistently defined, or shouldn't be. It is up to each backend to interpret it, paired with some next-step-in-the-bootstrap-pipeline. Just because a backend "usually" generates object files, doesn't mean bootstrapping stops at assembly. It depends. On a backend-by-backend basis. I think. Anyway, I'll leave it alone and move on with more pressing/fun matters.Apparently I didn't really compile all of "cm3", but still a lot. I'll keep iterating. I'm at libm3. Hopefully I don't hit problems at each step -- that the previous testing did cover a lot. Ok either way... ..Jay CC: hosking at cs.purdue.edu; m3devel at elegosoft.com From: antony.hosking at gmail.com Subject: Re: [M3devel] backend mode integratedassembly Date: Fri, 14 Sep 2012 19:40:43 -0400 To: jay.krell at cornell.edu Sent from my iPhone On Sep 14, 2012, at 18:44, Jay K wrote: It somewhat gets in the way of reading/writing the code. It bit-rots. I kind of think this area needs a bit of a reworking. There could/should be more code sharing. (Or maybe actually less infrastructure.) If anyone really did write an integrated backend that produced assembly, they could/should then have that backend go ahead and have that backend call the assembler. Maybe. Cross compiles can produce assembler. So maybe worth keeping. The -boot and -keep flags should perhaps be passed on the backend. By this measure, I might as well just call my C backend "IntegratedObject", and have it call out to quake/config to run the C compiler -- heck, esp. if RunCC was made part of Builder.i3 instead of just Builder.m3 (or passed down as a function pointer -- I guess otherwise there might be a circular dependency). I think using the tool chain is fine. It gives flexibility and a format humans can read from one to the next. I nearly did that. I guess I was too lazy to teach my backend how to call out to the C compiler via quake, rather than reuse Builder.m3. That is...I'm not sure there should be any modes at all. There should be "types" which is just which Interface.T implementation of M3CG to instantiate. They would all be "IntegratedObject". C backend would like I said, generate C itself, then call out to quake/compile_c. (It could almost just be "cc foo.c -o foo.o", but that isn't quite adequate/portable). IntegratedAssembly would generate assemlby, then call out to quake/assemble, if it doesn't know otherwise. m3cc/m3back/m3cg would be a very thin wrapper over m3cg. Everything but open/close would call down to m3cg_binwr. At close time, it would call out to quake/config to run the assembler, if not bootstrapping. I like it -- no modes, just specific types. They would all be treated as "IntegratedObject". Question would how much sharing/commonality is there really. I guess it doesn't matter much... I guess "externals" backends are convenient, to test? So going though m3cg_binwr is nice? So then you get commonality there? I'm still not sure that belongs in Builder.m3, vs. "M3CG_ExternalViaBinWr". Which could know about the boot/keep flags and keep the .mc files.. - Jay Subject: Re: [M3devel] backend mode integratedassembly From: hosking at cs.purdue.edu Date: Fri, 14 Sep 2012 17:07:28 -0400 CC: m3devel at elegosoft.com To: jay.krell at cornell.edu On Sep 14, 2012, at 4:24 PM, Jay K wrote:There is a backend mode for an integrated backend that generates assembly.This is dead code, right?Remove it? <* ASSERT FALSE *> (but then I get warnings about unreachable code -- comment it out? There is nothing to be gained from removing it.Maybe someone will want to experiment/resurrect. -------------- next part -------------- An HTML attachment was scrubbed... URL: From dabenavidesd at yahoo.es Sat Sep 15 02:03:17 2012 From: dabenavidesd at yahoo.es (Daniel Alejandro Benavides D.) Date: Sat, 15 Sep 2012 01:03:17 +0100 (BST) Subject: [M3devel] backend mode integratedassembly In-Reply-To: Message-ID: <1347667397.93684.YahooMailClassic@web29705.mail.ird.yahoo.com> Hi all: C is not assembler pure, it has macros, and that's a macroassembler. OK, if you want to eliminate code that isn't dead (because it doesn't exist technically speaking and probably never exist so it can't be dead), it's just a ifdef'ed out idea perhaps nobody will use it, so why process it? as comment anyway? Keep it or drop it. Do what you would like to do with it, if want to use it leave it, if not why comment it? Thanks in advance --- El vie, 14/9/12, Jay K escribi?: De: Jay K Asunto: [M3devel] backend mode integratedassembly Para: "m3devel" Fecha: viernes, 14 de septiembre, 2012 15:24 There is a backend mode for an integrated backend that generates assembly.This is dead code, right?Remove it? <* ASSERT FALSE *> (but then I get warnings about unreachable code -- comment it out? ?- Jay -------------- next part -------------- An HTML attachment was scrubbed... URL: From jay.krell at cornell.edu Sun Sep 16 00:29:05 2012 From: jay.krell at cornell.edu (Jay K) Date: Sat, 15 Sep 2012 22:29:05 +0000 Subject: [M3devel] struct complaints and C backend update Message-ID: It'd be nice if declare_procedure gave the size of returned structs.I guess I could deduce it maybe from the "_result" variable or some of thedeclare_ stuff with typeids that I ignore or something.I've reworked my code to use "standard structs", even though I'd rather not.I'd rather return them by value and have the C compiler deal with it. Efficiency and ABI correctness is lost.NT/amd64 passes 1, 2, 4, and 8 byte structs in registers, or somesuch.NT/x86 I think passes some small structs in registers too. If we returned structs by value, the left-or-right matter would be solved too. Not that ABI correctness is all that important -- so little C code passesor returns structs by value anyway, let alone C code we need to interoperate with. But I'd still like to give the C compiler more of the work. It SEEMS that local declared procedures take struct parametersas type "struct", with size, and I can pass them with a somewhat strong type.It SEEMS that imported procedures take them by untyped "address".I've reworked my code here. To pass structs by pointer and copy theminto a local. I'd rather just pass them by value and have the C compilerdeal with it. I can now compile and link cm3 for {I386,AMD64,PPC}_DARWIN, usingthe C backend. It crashes..in RTLinker__InitRunTime.traceLink does manage to output a fair amount before crashing,which is itself actually quite impressive.This is difficult work though! I've also reworked structs slightly to compose them of short, int, INT64in order to raise their alignment, if needed. I still predeclare a bunch of struct sizes.I need to make a second pass over the data to discover them all.Or do something higher level still, not just go by size. If I try to compile the entire system, I don't get too far beyondcm3 before I hit a C compiler error, something exception handling related. - Jay -------------- next part -------------- An HTML attachment was scrubbed... URL: From jay.krell at cornell.edu Sun Sep 16 10:32:33 2012 From: jay.krell at cornell.edu (Jay K) Date: Sun, 16 Sep 2012 08:32:33 +0000 Subject: [M3devel] config support for C backend (USE_C_BACKEND = TRUE) Message-ID: cm3cfg.common: if not defined("USE_C_BACKEND") USE_C_BACKEND = FALSEend if USE_C_BACKEND M3_BACKEND_MODE = "ExternalObject" proc m3_backend(source, object, optimize, debug) is ret_code = try_exec("@m3cgcat", "-in-binary:" & source, "-out-c:" & source & ".c") if not equal(ret_code, 0) return ret_code end return compile_c(source & ".c", object, [ ], FALSE, TRUE)end end so, say: USE_C_BACKEND = TRUE in config file to use C backend.It certainly doesn't work yet.I switched PPC_DARWIN to it.But note, again, it doesn't work. It does a lot, seemingly correctly, but not yet enough. A C mode in the "builder" would still be more efficient. - Jay -------------- next part -------------- An HTML attachment was scrubbed... URL: From dragisha at m3w.org Sun Sep 16 11:00:51 2012 From: dragisha at m3w.org (=?utf-8?Q?Dragi=C5=A1a_Duri=C4=87?=) Date: Sun, 16 Sep 2012 11:00:51 +0200 Subject: [M3devel] friendly reminder/request for cooperative suspend In-Reply-To: <71F41B96-DD1F-4A0A-9D7B-4DF925462EA4@cs.purdue.edu> References: <71F41B96-DD1F-4A0A-9D7B-4DF925462EA4@cs.purdue.edu> Message-ID: <7A992795-1446-4AD1-AADE-58BCFC2DEFB8@m3w.org> Can we have clang as a reference compiler, one we target with our C++ backend? -- Divided by a common language Dragi?a Duri? dragisha at m3w.org On Sep 14, 2012, at 5:10 PM, Antony Hosking wrote: > Yes, this is on the top of my list of things to do. > Plus fix some atomics bugs. > atomics plus cooperative suspend gives us a much better story on locks too. > We could even have a proper memory model like C++11. > > LLVM would also be great (better even than the C backend) because we?d get some decent optimization passes. > > > On Sep 14, 2012, at 4:01 AM, Jay K wrote: > >> friendly reminder/request: I'd like to see the system changed to use cooperative suspend. >> >> >> Combined with a C backend, that would greatly expand portability and remove existing target-dependent code (i.e. already ported) from the system. >> >> >> I'm not confident that GetThreadContext works on "wow64". >> It'd fix that. >> >> >> We can compute the top/bottom of the stack fairly portably -- address of locals. >> We can capture current context/registers via setjmp. >> Or maybe getcontext. >> (We should find out about setjmp/longjmp munging -- what gets munged? Everything? Just non-gc-roots? Only after longjmp?) >> Itanium is special -- there is a second stack growing up from the same base. >> >> >> I'd like this way more than LLVM. >> >> >> Maybe I can work on. Maybe. >> >> >> I believe typical production Java VMs use cooperative suspend. >> >> >> - Jay > -------------- next part -------------- An HTML attachment was scrubbed... URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 495 bytes Desc: Message signed with OpenPGP using GPGMail URL: From jay.krell at cornell.edu Sun Sep 16 23:31:12 2012 From: jay.krell at cornell.edu (Jay K) Date: Sun, 16 Sep 2012 21:31:12 +0000 Subject: [M3devel] friendly reminder/request for cooperative suspend In-Reply-To: <7A992795-1446-4AD1-AADE-58BCFC2DEFB8@m3w.org> References: <71F41B96-DD1F-4A0A-9D7B-4DF925462EA4@cs.purdue.edu>, <7A992795-1446-4AD1-AADE-58BCFC2DEFB8@m3w.org> Message-ID: I'm targeting ANSI C. Maybe with a K&R option. (K&R has been useful surprisingly recently -- the bundled HPUX/HPPA compiler is K&R, it is there just to recompile "data" and relink the kernel; and on my Irix install I happened upon a bundled compiler that I recall might have been K&R). And then later an option for C++, specifically for exception handling. And an option to use __try/__except/__finally on NT, and maybe similar in other systems if I can test them (VMS, Tru64, Ultrix, but really, setjmp for non-mainstream platforms is fine, esp. given a C++ option). And maybe C++ to optimize static chain handling. Hopefully nothing else will be particularly compiler specific. But for now I'm just testing with whatever is in my Mac. - Jay Subject: Re: [M3devel] friendly reminder/request for cooperative suspend From: dragisha at m3w.org Date: Sun, 16 Sep 2012 11:00:51 +0200 CC: jay.krell at cornell.edu; m3devel at elegosoft.com To: hosking at cs.purdue.edu Can we have clang as a reference compiler, one we target with our C++ backend? --Divided by a common language Dragi?a Duri?dragisha at m3w.org On Sep 14, 2012, at 5:10 PM, Antony Hosking wrote:Yes, this is on the top of my list of things to do.Plus fix some atomics bugs.atomics plus cooperative suspend gives us a much better story on locks too.We could even have a proper memory model like C++11. LLVM would also be great (better even than the C backend) because we'd get some decent optimization passes. On Sep 14, 2012, at 4:01 AM, Jay K wrote:friendly reminder/request: I'd like to see the system changed to use cooperative suspend. Combined with a C backend, that would greatly expand portability and remove existing target-dependent code (i.e. already ported) from the system. I'm not confident that GetThreadContext works on "wow64".It'd fix that. We can compute the top/bottom of the stack fairly portably -- address of locals.We can capture current context/registers via setjmp.Or maybe getcontext.(We should find out about setjmp/longjmp munging -- what gets munged? Everything? Just non-gc-roots? Only after longjmp?)Itanium is special -- there is a second stack growing up from the same base. I'd like this way more than LLVM. Maybe I can work on. Maybe. I believe typical production Java VMs use cooperative suspend. - Jay -------------- next part -------------- An HTML attachment was scrubbed... URL: From jay.krell at cornell.edu Tue Sep 18 00:04:33 2012 From: jay.krell at cornell.edu (Jay K) Date: Mon, 17 Sep 2012 22:04:33 +0000 Subject: [M3devel] update.. In-Reply-To: <20120917110712.03421CC85A@birch.elegosoft.com> References: <20120917110712.03421CC85A@birch.elegosoft.com> Message-ID: > ..it still crashes in RTLinker.InitRuntime, but it gets > significantly further correction, it gets to the main module! RunMainBody: ../src/runtime/common/RTTipe.i3(2) ../src/runtime/common/RTPacking.i3(3) ../src/runtime/common/RT0.i3(3) ../src/runtime/common/RTHooks.i3(3) ../src/runtime/common/RTTipe.m3(4)RunMainBody: exec: ../src/runtime/common/RTTipe.i3(3)RunMainBody: exec: ../src/runtime/common/RTTipe.m3(3)AddUnitI: ../src/runtime/common/RTException.m3(3) Program received signal EXC_BAD_ACCESS, Could not access memory.Reason: KERN_PROTECTION_FAILURE at address: 0x000000340x00033396 in Makefile__ScanCommandLine1 () at Makefile.mc.c:54075407 (*(volatile INT32*)&L_103)=(INT32)(((INT32)(((INT32)(((INT32)(((INT32)(*(volatile UINT32*)(52+(ADDRESS)*(volatile ADDRESS*)(272+(ADDRESS)&M_Makefile))))))-((INT32)(((INT32)M3_INT32(1)))))))));(gdb) bt#0 0x00033396 in Makefile__ScanCommandLine1 () at Makefile.mc.c:5407#1 0x0003a166 in Main__DoIt () at Main.mc.c:359#2 0x0003b2c2 in Main_M3 (mode=) at Main.mc.c:1790#3 0x0035d760 in RTLinker__AddUnit (b=0x3b29c "U??S??\024?") at RTLinker.mc.c:963#4 0x00002902 in main (argc=1, argv=0xbffff8dc, envp=0xbffff8e4) at _m3main.c:16(gdb) very nice - Jay > Date: Mon, 17 Sep 2012 13:07:11 +0000 > To: m3commit at elegosoft.com > From: jkrell at elego.de > Subject: [M3commit] CVS Update: cm3 > > CVSROOT: /usr/cvs > Changes by: jkrell at birch. 12/09/17 13:07:11 > > Modified files: > cm3/m3-sys/m3back/src/: M3C.m3 > > Log message: > is_const => const > const => const_text > 4 space indentation (work in progress) > add target/wordsize at top of C > restore "static" on non-exported globals (important! avoids duplicates > and errors) > > and then most importantly, pad out segments to their declared sizes > very important -- to get the zeros at the end instead of garbage > this fixes crashing at "startup" (in RTLinker.InitRuntime) > ..it still crashes in RTLinker.InitRuntime, but it gets > significantly further > -------------- next part -------------- An HTML attachment was scrubbed... URL: From dabenavidesd at yahoo.es Tue Sep 18 19:16:51 2012 From: dabenavidesd at yahoo.es (Daniel Alejandro Benavides D.) Date: Tue, 18 Sep 2012 18:16:51 +0100 (BST) Subject: [M3devel] update.. In-Reply-To: Message-ID: <1347988611.47742.YahooMailClassic@web29706.mail.ird.yahoo.com> Hi all: I wonder if this Initialization runtime has done well at that, because that Main body doesn't start is not something of safe nature, all Main Modules must be safe on Modula-3. Jay I can collaborate if you assign me something (for now on i386 later on x64), but we need to agree on how to do it (and if that implies be verbose in C let's do so) if I may say so. I have read some research going on C safety based on determining minimum RT assumptions of all compilers and platforms, but I don't know the current state of? that work. Model checking could be next stop, given the amount of static analyzer tools for C, etc, but again I don't know the state of the art of that research. Thanks in advance --- El lun, 17/9/12, Jay K escribi?: De: Jay K Asunto: [M3devel] update.. Para: "m3devel" Fecha: lunes, 17 de septiembre, 2012 17:04 ?> ..it still crashes in RTLinker.InitRuntime, but it gets ?> significantly further correction, it gets to the main module! RunMainBody: ../src/runtime/common/RTTipe.i3(2)? ../src/runtime/common/RTPacking.i3(3)? ../src/runtime/common/RT0.i3(3)? ../src/runtime/common/RTHooks.i3(3)? ../src/runtime/common/RTTipe.m3(4)RunMainBody: exec: ../src/runtime/common/RTTipe.i3(3)RunMainBody: exec: ../src/runtime/common/RTTipe.m3(3)AddUnitI: ../src/runtime/common/RTException.m3(3) Program received signal EXC_BAD_ACCESS, Could not access memory.Reason: KERN_PROTECTION_FAILURE at address: 0x000000340x00033396 in Makefile__ScanCommandLine1 () at Makefile.mc.c:54075407 (*(volatile INT32*)&L_103)=(INT32)(((INT32)(((INT32)(((INT32)(((INT32)(*(volatile UINT32*)(52+(ADDRESS)*(volatile ADDRESS*)(272+(ADDRESS)&M_Makefile))))))-((INT32)(((INT32)M3_INT32(1)))))))));(gdb) bt#0 ?0x00033396 in Makefile__ScanCommandLine1 () at Makefile.mc.c:5407#1 ?0x0003a166 in Main__DoIt () at Main.mc.c:359#2 ?0x0003b2c2 in Main_M3 (mode=) at Main.mc.c:1790#3 ?0x0035d760 in RTLinker__AddUnit (b=0x3b29c "U??S??\024?") at RTLinker.mc.c:963#4 ?0x00002902 in main (argc=1, argv=0xbffff8dc, envp=0xbffff8e4) at _m3main.c:16(gdb)? very nice ?- Jay > Date: Mon, 17 Sep 2012 13:07:11 +0000 > To: m3commit at elegosoft.com > From: jkrell at elego.de > Subject: [M3commit] CVS Update: cm3 > > CVSROOT: /usr/cvs > Changes by: jkrell at birch. 12/09/17 13:07:11 > > Modified files: > cm3/m3-sys/m3back/src/: M3C.m3 > > Log message: > is_const => const > const => const_text > 4 space indentation (work in progress) > add target/wordsize at top of C > restore "static" on non-exported globals (important! avoids duplicates > and errors) > > and then most importantly, pad out segments to their declared sizes > very important -- to get the zeros at the end instead of garbage > this fixes crashing at "startup" (in RTLinker.InitRuntime) > ..it still crashes in RTLinker.InitRuntime, but it gets > significantly further > -------------- next part -------------- An HTML attachment was scrubbed... URL: From jay.krell at cornell.edu Wed Sep 19 03:28:23 2012 From: jay.krell at cornell.edu (Jay K) Date: Wed, 19 Sep 2012 01:28:23 +0000 Subject: [M3devel] update and static link stuff... Message-ID: latest debugging/exploration... RTLinker.m3 has some indirect call (function call through a pointer).Here are two of them: PROCEDURE FixImports (m: RT0.ModulePtr) = VAR imp: RT0.ImportPtr; BEGIN IF (m = NIL) THEN RETURN; END; TraceModule("FixImports: ", m); imp := m.imports; WHILE (imp # NIL) DO IF (imp.import = NIL) THEN imp.import := imp.binder (0); END; (* line 83 *) imp := imp.next; END; END FixImports; PROCEDURE AddUnit (b: RT0.Binder) = VAR m: RT0.ModulePtr; BEGIN IF (b = NIL) THEN RETURN END; m := b(0); (* line 122 *) IF (m = NIL) THEN RETURN END; AddUnitI(m); END AddUnit; m3front sometimes "knows" that an indirect call cannot be to a closure,so sometimes it does "static link stuff", sometimes not, UserProc.m3: ELSIF CouldBeClosure (proc) THEN ce.tmp := GenClosureCall (p_temp, cg_result, p_type, callConv); CG.Free (p_temp); ELSE CG.Push (p_temp); CG.Gen_Call_indirect (cg_result, callConv); ce.tmp := Marker.EmitExceptionTest (p_type, need_value := TRUE); CG.Free (p_temp); END; PROCEDURE GenClosureCall (p_temp: CG.Val; result: CG.Type; sig: Type.T; cc: CG.CallingConvention): CG.Val = VAR skip := CG.Next_label (); BEGIN CG.If_closure (p_temp, CG.No_label, skip, CG.Maybe); CG.Push (p_temp); CG.Closure_frame (); CG.Pop_static_link (); (* *** *) CG.Push (p_temp); CG.Closure_proc (); CG.Store_temp (p_temp); CG.Set_label (skip); CG.Push (p_temp); CG.Gen_Call_indirect (result, cc); RETURN Marker.EmitExceptionTest (sig, need_value := TRUE); END GenClosureCall; >From the two examples and guessing at what the code means, I guesswe can't "store closures", like in globals or record fields.They can be parameters and locals.And that is how the compiler knows some things can't be closures.? Aside:The backends are relatively untyped.There is a lot of type information available, but isn't really used."Following that idea.." whenever my C backend calls through a function pointer,it casts to a function pointer that can accept any parameters: #ifdef __cplusplus#define M3_DOTDOTDOT ...#else#define M3_DOTDOTDOT#endif (recall that in C void Foo(void) is a function accepts no parameters, but void Foo()is a function that accepts anything; if you do use "..." in C, gcc complains about thelack of any preceding parameters.) (((*)(M3_DOTDOTDOT))function_pointer)(parameters any number of them) so, now, let's look at those indirect calls in the generated C (slightly simplified): This first one can't be a closure: /* line 83 "../src/runtime/common/RTLinker.m3" */ (*(volatile ADDRESS*)&L_7)=(ADDRESS)(((ADDRESS)(*(volatile ADDRESS*)(4+(ADDRESS)*(volatile ADDRESS*)&imp)))); /* start_call_indirect */ if(!(*(volatile ADDRESS*)&L_7))M_RTLinker_CRASH(2660); /* call_indirect */ /* declare_temp => declare_local */ /* declare_local ADDRESS L_10 */ {ADDRESS L_9 M3_INIT; /* store */ (*(volatile ADDRESS*)&L_9)=(ADDRESS)(((ADDRESS)(((ADDRESS (__stdcall*)(M3_DOTDOTDOT))*(volatile ADDRESS*)&L_7)(((INT32)(((INT32)M3_INT32(0)))))))); /* line 83 "../src/runtime/common/RTLinker.m3" */ /* load */ and this one can be, you can see the telltale check for -1, the closure marker: /* line 122 "../src/runtime/common/RTLinker.m3" */ if((((INT32)(*(volatile INT32*)*(volatile ADDRESS*)&L_13)))!=(((INT32)(((INT32)M3_INT32(-1))))))goto L12; /* set_label */ L13:; /* load */ /* load_indirect */ /* declare_temp => declare_local */ /* declare_local ADDRESS L_16 */ {ADDRESS L_15 M3_INIT; /* pop_static_link */ /* store */ (*(volatile ADDRESS*)&L_15)=(ADDRESS)(((ADDRESS)(*(volatile ADDRESS*)(8+(ADDRESS)*(volatile ADDRESS*)&L_13)))); /* load */ /* load_indirect */ /* store */ (*(volatile ADDRESS*)&L_13)=(ADDRESS)(((ADDRESS)(*(volatile ADDRESS*)(4+(ADDRESS)*(volatile ADDRESS*)&L_13)))); /* line 122 "../src/runtime/common/RTLinker.m3" */ /* set_label */ L12:; /* load */ /* check_nil */ if(!(*(volatile ADDRESS*)&L_13))M_RTLinker_CRASH(3908); /* call_indirect */ /* free_temp */ /* declare_temp => declare_local */ /* declare_local ADDRESS L_18 */ {ADDRESS L_17 M3_INIT; /* store */ (*(volatile ADDRESS*)&L_17)=(ADDRESS)(((ADDRESS)(((ADDRESS (__stdcall*)(M3_DOTDOTDOT))*(volatile ADDRESS*)&L_13)(L_15,((INT32)(((INT32)M3_INT32(0)))))))); These are actually both calls to "binders", which take one parameter, integer "mode". They are both via pointers. But the compiler thinks the second one might be a closure.So we get pop_static_link. Following the pattern of M3x86.m3, I therefore pass the static link, unconditionally. This is not right! For now I'm going to try putting the static link LAST in parameter lists, instead of first. I expect that will work.Thanks to printf! :)(on all but one implementation I know of, printf("", 1, 2, 3) is safe and predictable -- you can pass any number of extra parameters to a function and they will be ignored; the stack will not become imbalanced. Anyone with a broad knowledge of calling conventions confirm?) The right fix is to use more type information, possibly that which I'm already given.That is going to require multiple passes and a somewhat more sophisticated in-memorystate. Currently I have just a bunch of strings, occasionally an array of strings.Not all the data is recieved is received in an ideal order. i.e. This should all work, pretty well, but it kind of needs a substantial "rewrite". - Jay -------------- next part -------------- An HTML attachment was scrubbed... URL: From mika at async.caltech.edu Wed Sep 19 03:41:17 2012 From: mika at async.caltech.edu (Mika Nystrom) Date: Tue, 18 Sep 2012 18:41:17 -0700 Subject: [M3devel] update and static link stuff... In-Reply-To: References: Message-ID: <20120919014117.7873F1A207D@async.async.caltech.edu> Jay K writes: >From the two examples and guessing at what the code means=2C I guesswe can'= >t "store closures"=2C like in globals or record fields.They can be paramete= >rs and locals.And that is how the compiler knows some things can't be closu= >res.?=20 Yes I think that's right. From the way the Green Book is worded it looks like the issue of passing an inner procedure was a bit of an afterthought. You can't assign them to anything but you can pass them as parameters. And you're right about printf. All architectures I know of support the passing of "the wrong number of parameters" without mangling the stack. Mika From jay.krell at cornell.edu Wed Sep 19 22:15:12 2012 From: jay.krell at cornell.edu (Jay K) Date: Wed, 19 Sep 2012 20:15:12 +0000 Subject: [M3devel] next little step In-Reply-To: <20120919045546.5CD402474003@birch.elegosoft.com> References: <20120919045546.5CD402474003@birch.elegosoft.com> Message-ID: And the problem here is that ETimer__Push contains a parameter "t" and a local in a nested block "t". ETimer_Push(t) { { t stuff with inner t } stuff with outer t } Normally this'd be dealt with begin_block/end_block. However because import_procedure comes in at arbitrary times, and is needed to remain in scope from there on, I ignore begin/end_block -- and the braces above aren't present. Longer term I will move all the declarations from import_procedure up to global scope, and then honor begin/end_block. Would be nice if frontend did this but oh well. So for now I munge all parameters/locals (except "_static_link") with a unique number on the end, so these two aren't the same. Now we get much further. We get to cm3 trying to open files, the files aren't present, it raises an exception. Raising an exception doesn't work due to a small stupid error of extra work I did. I wasn't adding static_links to exception handlers because they already have a parameter. Likely fix is to stop special casing exception handlers. (Btw, Tony -- we should have m3cg.try m3cg.finally m3cg.except whatever that means (what are the parameters? I guess types?) and maybe: m3cg.understands_try m3cg.understands_finally m3cg.understands_except whatever that means and maybe: m3cg.is_pass_through which means, something like, the backend doesn't really understand anything, please make all the calls and a later backend might ignore some -- if it is workable to make ignored calls. I'll try to think about later, much later. And come up wwith something that doesn't break existing backends. Obvious goals: a new backend that understands try/finally/except has a enough information to a) use setjmp/longjmp or b) use Microsoft C source __try/__except/__finally and the VMS/Tru64/Ultrix equivalents or c) use C++ source try/except/finally or d) use the IA64 ABI ? or e) generate Java source or bytecodesMaybe even a goal where you could layer a thin new filter m3cg on top of an older one and all the thin new filter m3cg does is change try/except/finally to setjmp/longjmp. That'd be nifty if we could achieve it. Some sort of "dynamic chaining of m3cg". ) I also wasn't defining structs right for a bit there.struct {short a; char b;} m3_struct3_t isn't really guaranteed 3 bytes. We might have a problem there.So I have:struct {char a[3];} m3_struct3_t isn't really guaranteed 3 bytes. but we might cast and read a 2 byte integer out of that, and the alignment could be off.x86/AMD64 don't care so I'm ignoring it.The higher level IR might/will fix it. We'll see. Also probably this doesn't happen -- if I actually have a record with a uint16 or uint32, the front end will pad it up in size.. There's still something I need to fix here..not urgent.. Later, - Jay > Date: Wed, 19 Sep 2012 06:55:39 +0000 > To: m3commit at elegosoft.com > From: jkrell at elego.de > Subject: [M3commit] CVS Update: cm3 > > CVSROOT: /usr/cvs > Changes by: jkrell at birch. 12/09/19 06:55:39 > > Modified files: > cm3/m3-sys/m3back/src/: M3C.m3 > > Log message: > put line directives in comments (for now) > put static_link last instead of first > This lets us get much further: > RunMainBody: exec: ../src/etimer/ETimer.m3(3) > > Program received signal EXC_BAD_ACCESS, Could not access memory. > Reason: KERN_PROTECTION_FAILURE at address: 0x00000004 > 0x00343511 in ETimer__Push (t=0x16bc1b8 "??B") at ETimer.mc.c:743 > 743 (*(volatile INT32*)(4+(ADDRESS)*(volatile ADDRESS*)&L_14))=(INT32)(((INT32)(((INT32)(((INT32)(*(volatile INT32*)(4+(ADDRESS)*(volatile ADDRESS*)&L_14)))+((INT32)(((INT32)1)))))))); > (gdb) > > (before at Main(0) we ran the body, which was wrong) > > print min32 and min64 as -max32 and -max64-1 to fix warning > -------------- next part -------------- An HTML attachment was scrubbed... URL: From jay.krell at cornell.edu Thu Sep 20 03:30:33 2012 From: jay.krell at cornell.edu (Jay K) Date: Thu, 20 Sep 2012 01:30:33 +0000 Subject: [M3devel] next little step In-Reply-To: References: <20120919045546.5CD402474003@birch.elegosoft.com>, Message-ID: With this fixed I get yet much further. All way to RTCollector.m3: PROCEDURE CleanBetween (h, he: RefHeader; clean: BOOLEAN) = BEGIN WHILE h < he DO <* ASSERT Word.And (LOOPHOLE (h, INTEGER), 3) = 0 *> <* ASSERT NOT h.forwarded *> and that assert failed. Ideas? Maybe you'll be able to look into this Tony? In the meantime, I've moved my attention to m3-sys/m3tests and fix problemsthey show -- I was reminded I have a thorough bit insert/extract test there,and I'm not sure I didn't implement it backwards in C, and that assertion failureis related to Word.Insert...but I think my Word.Insert is correct...Anyway, m3-sys/m3tests have revealed another problem...probably a frontend one...I"ll send another mail. - Jay From: jay.krell at cornell.edu To: m3devel at elegosoft.com Date: Wed, 19 Sep 2012 20:15:12 +0000 Subject: Re: [M3devel] next little step And the problem here is that ETimer__Push contains a parameter "t" and a local in a nested block "t". ETimer_Push(t) { { t stuff with inner t } stuff with outer t } Normally this'd be dealt with begin_block/end_block. However because import_procedure comes in at arbitrary times, and is needed to remain in scope from there on, I ignore begin/end_block -- and the braces above aren't present. Longer term I will move all the declarations from import_procedure up to global scope, and then honor begin/end_block. Would be nice if frontend did this but oh well. So for now I munge all parameters/locals (except "_static_link") with a unique number on the end, so these two aren't the same. Now we get much further. We get to cm3 trying to open files, the files aren't present, it raises an exception. Raising an exception doesn't work due to a small stupid error of extra work I did. I wasn't adding static_links to exception handlers because they already have a parameter. Likely fix is to stop special casing exception handlers. (Btw, Tony -- we should have m3cg.try m3cg.finally m3cg.except whatever that means (what are the parameters? I guess types?) and maybe: m3cg.understands_try m3cg.understands_finally m3cg.understands_except whatever that means and maybe: m3cg.is_pass_through which means, something like, the backend doesn't really understand anything, please make all the calls and a later backend might ignore some -- if it is workable to make ignored calls. I'll try to think about later, much later. And come up wwith something that doesn't break existing backends. Obvious goals: a new backend that understands try/finally/except has a enough information to a) use setjmp/longjmp or b) use Microsoft C source __try/__except/__finally and the VMS/Tru64/Ultrix equivalents or c) use C++ source try/except/finally or d) use the IA64 ABI ? or e) generate Java source or bytecodes Maybe even a goal where you could layer a thin new filter m3cg on top of an older one and all the thin new filter m3cg does is change try/except/finally to setjmp/longjmp. That'd be nifty if we could achieve it. Some sort of "dynamic chaining of m3cg". ) I also wasn't defining structs right for a bit there. struct {short a; char b;} m3_struct3_t isn't really guaranteed 3 bytes. We might have a problem there. So I have: struct {char a[3];} m3_struct3_t isn't really guaranteed 3 bytes. but we might cast and read a 2 byte integer out of that, and the alignment could be off. x86/AMD64 don't care so I'm ignoring it. The higher level IR might/will fix it. We'll see. Also probably this doesn't happen -- if I actually have a record with a uint16 or uint32, the front end will pad it up in size.. There's still something I need to fix here..not urgent.. Later, - Jay > Date: Wed, 19 Sep 2012 06:55:39 +0000 > To: m3commit at elegosoft.com > From: jkrell at elego.de > Subject: [M3commit] CVS Update: cm3 > > CVSROOT: /usr/cvs > Changes by: jkrell at birch. 12/09/19 06:55:39 > > Modified files: > cm3/m3-sys/m3back/src/: M3C.m3 > > Log message: > put line directives in comments (for now) > put static_link last instead of first > This lets us get much further: > RunMainBody: exec: ../src/etimer/ETimer.m3(3) > > Program received signal EXC_BAD_ACCESS, Could not access memory. > Reason: KERN_PROTECTION_FAILURE at address: 0x00000004 > 0x00343511 in ETimer__Push (t=0x16bc1b8 "??B") at ETimer.mc.c:743 > 743 (*(volatile INT32*)(4+(ADDRESS)*(volatile ADDRESS*)&L_14))=(INT32)(((INT32)(((INT32)(((INT32)(*(volatile INT32*)(4+(ADDRESS)*(volatile ADDRESS*)&L_14)))+((INT32)(((INT32)1)))))))); > (gdb) > > (before at Main(0) we ran the body, which was wrong) > > print min32 and min64 as -max32 and -max64-1 to fix warning > -------------- next part -------------- An HTML attachment was scrubbed... URL: From jay.krell at cornell.edu Thu Sep 20 03:31:20 2012 From: jay.krell at cornell.edu (Jay K) Date: Thu, 20 Sep 2012 01:31:20 +0000 Subject: [M3devel] Areas that may need attention in the frontend? Message-ID: Areas that may need attention in the frontend? TryFinStmt.m3: CG.Start_call_direct (p.handler.cg_proc, p.handler.level, CG.Type.Void); (* Shouldn't we pass the activation parameter here? What value do we pass? *) CG.Call_direct (p.handler.cg_proc, CG.Type.Void); I'm wondering this too...like..what is the interfaceto except/finally blocks? It appears they take two, or one, or zero parameters,depending on intepretation and context. two parameters: _static_link exception stuff one parameter: _static_link zero parameters: the above I think the right implmentation (assuming no significantchange to nested functions, which Tony is thinking about:) )is one parameter: exception stuff and the implied/popped static_link, always. For now, I think I'll not prototype these and use K&R definitions, yuck! Maybe generating C++ with overloads is a good idea?? values/Procedure.m3: ELSIF (cur.token = TK.tSEMI) THEN t.body := NEW (Body, self := t); ProcBody.Push (t.body); (* try accepting the Modula-2 syntax *) Error.ID (id, "expecting \'=\' before procedure body"); Probably everything after the error should be removed?Or this is an example trying to recover from parse errorsand doing best effort? - Jay -------------- next part -------------- An HTML attachment was scrubbed... URL: From hosking at cs.purdue.edu Thu Sep 20 04:39:58 2012 From: hosking at cs.purdue.edu (Antony Hosking) Date: Wed, 19 Sep 2012 22:39:58 -0400 Subject: [M3devel] Areas that may need attention in the frontend? In-Reply-To: References: Message-ID: On Sep 19, 2012, at 9:31 PM, Jay K wrote: > Areas that may need attention in the frontend? > > > TryFinStmt.m3: > > CG.Start_call_direct (p.handler.cg_proc, p.handler.level, CG.Type.Void); > (* Shouldn't we pass the activation parameter here? > What value do we pass? *) > CG.Call_direct (p.handler.cg_proc, CG.Type.Void); The level let?s you compute that. > I'm wondering this too...like..what is the interface > to except/finally blocks? ? > It appears they take two, or one, or zero parameters, > depending on intepretation and context. > > > two parameters: > _static_link > exception stuff > > > one parameter: > _static_link > > > zero parameters: > the above > > > I think the right implmentation (assuming no significant > change to nested functions, which Tony is thinking about:) ) > is one parameter: > > exception stuff > > and the implied/popped static_link, always. > > > For now, I think I'll not prototype these and use K&R definitions, yuck! That works. > Maybe generating C++ with overloads is a good idea?? > > > > values/Procedure.m3: > > ELSIF (cur.token = TK.tSEMI) THEN > t.body := NEW (Body, self := t); > ProcBody.Push (t.body); > (* try accepting the Modula-2 syntax *) > Error.ID (id, "expecting \'=\' before procedure body"); > > > Probably everything after the error should be removed? > Or this is an example trying to recover from parse errors > and doing best effort? Yes. > > > - Jay -------------- next part -------------- An HTML attachment was scrubbed... URL: From jay.krell at cornell.edu Thu Sep 20 06:33:43 2012 From: jay.krell at cornell.edu (Jay) Date: Wed, 19 Sep 2012 21:33:43 -0700 Subject: [M3devel] Areas that may need attention in the frontend? In-Reply-To: References: Message-ID: Clarification: the "questioning comment" is not mine, it is there in the code. I suspect it is a good question & that the code isn't what it should be. - Jay (briefly/pocket-sized-computer-aka-phone) On Sep 19, 2012, at 7:39 PM, Antony Hosking wrote: > On Sep 19, 2012, at 9:31 PM, Jay K wrote: > >> Areas that may need attention in the frontend? >> >> >> TryFinStmt.m3: >> >> CG.Start_call_direct (p.handler.cg_proc, p.handler.level, CG.Type.Void); >> (* Shouldn't we pass the activation parameter here? >> What value do we pass? *) >> CG.Call_direct (p.handler.cg_proc, CG.Type.Void); > > The level let?s you compute that. > >> I'm wondering this too...like..what is the interface >> to except/finally blocks? > > ? > >> It appears they take two, or one, or zero parameters, >> depending on intepretation and context. >> >> >> two parameters: >> _static_link >> exception stuff >> >> >> one parameter: >> _static_link >> >> >> zero parameters: >> the above >> >> >> I think the right implmentation (assuming no significant >> change to nested functions, which Tony is thinking about:) ) >> is one parameter: >> >> exception stuff >> >> and the implied/popped static_link, always. >> >> >> For now, I think I'll not prototype these and use K&R definitions, yuck! > > That works. > >> Maybe generating C++ with overloads is a good idea?? >> >> >> >> values/Procedure.m3: >> >> ELSIF (cur.token = TK.tSEMI) THEN >> t.body := NEW (Body, self := t); >> ProcBody.Push (t.body); >> (* try accepting the Modula-2 syntax *) >> Error.ID (id, "expecting \'=\' before procedure body"); >> >> >> Probably everything after the error should be removed? >> Or this is an example trying to recover from parse errors >> and doing best effort? > > Yes. > >> >> >> - Jay > -------------- next part -------------- An HTML attachment was scrubbed... URL: From jay.krell at cornell.edu Thu Sep 20 13:37:21 2012 From: jay.krell at cornell.edu (Jay K) Date: Thu, 20 Sep 2012 11:37:21 +0000 Subject: [M3devel] Areas that may need attention in the frontend? In-Reply-To: References: , Message-ID: I think this isn't right. I understand the static link is implied by level > 0. But the activation/exception parameter should be always passed or never passed. Or there should be two functions -- one that takes an exception, one that doesn't, and one calls the other. Or pass it as null if there isn't an exception. I should really not have to resort to K&R and passing varying numbers of parameters. I still have to look at a few test cases to see when each parameter is used.Maybe I'm confused. The other thing, you want the code to stay? - Jay CC: jay.krell at cornell.edu; m3devel at elegosoft.com From: jay.krell at cornell.edu Subject: Re: [M3devel] Areas that may need attention in the frontend? Date: Wed, 19 Sep 2012 21:33:43 -0700 To: hosking at cs.purdue.edu Clarification: the "questioning comment" is not mine, it is there in the code. I suspect it is a good question & that the code isn't what it should be. - Jay (briefly/pocket-sized-computer-aka-phone) On Sep 19, 2012, at 7:39 PM, Antony Hosking wrote: On Sep 19, 2012, at 9:31 PM, Jay K wrote:Areas that may need attention in the frontend? TryFinStmt.m3: CG.Start_call_direct (p.handler.cg_proc, p.handler.level, CG.Type.Void); (* Shouldn't we pass the activation parameter here? What value do we pass? *) CG.Call_direct (p.handler.cg_proc, CG.Type.Void); The level let?s you compute that. I'm wondering this too...like..what is the interfaceto except/finally blocks? ? It appears they take two, or one, or zero parameters,depending on intepretation and context. two parameters: _static_link exception stuff one parameter: _static_link zero parameters: the above I think the right implmentation (assuming no significantchange to nested functions, which Tony is thinking about:) )is one parameter: exception stuff and the implied/popped static_link, always. For now, I think I'll not prototype these and use K&R definitions, yuck! That works. Maybe generating C++ with overloads is a good idea?? values/Procedure.m3: ELSIF (cur.token = TK.tSEMI) THEN t.body := NEW (Body, self := t); ProcBody.Push (t.body); (* try accepting the Modula-2 syntax *) Error.ID (id, "expecting \'=\' before procedure body"); Probably everything after the error should be removed?Or this is an example trying to recover from parse errorsand doing best effort? Yes. - Jay -------------- next part -------------- An HTML attachment was scrubbed... URL: From hosking at cs.purdue.edu Thu Sep 20 14:16:59 2012 From: hosking at cs.purdue.edu (Antony Hosking) Date: Thu, 20 Sep 2012 08:16:59 -0400 Subject: [M3devel] Areas that may need attention in the frontend? In-Reply-To: References: , Message-ID: <85381A4A-1D3C-47E8-9D15-50893BBE4B1E@cs.purdue.edu> On Sep 20, 2012, at 7:37 AM, Jay K wrote: > I think this isn't right. I understand the static link is implied by level > 0. But the activation/exception parameter should be always passed or never passed. Or there should be two functions -- one that takes an exception, one that doesn't, and one calls the other. Or pass it as null if there isn't an exception. > > I should really not have to resort to K&R and passing varying numbers of parameters. > > I still have to look at a few test cases to see when each parameter is used. > Maybe I'm confused. > > The other thing, you want the code to stay? For now, yes. > > - Jay > > > CC: jay.krell at cornell.edu; m3devel at elegosoft.com > From: jay.krell at cornell.edu > Subject: Re: [M3devel] Areas that may need attention in the frontend? > Date: Wed, 19 Sep 2012 21:33:43 -0700 > To: hosking at cs.purdue.edu > > Clarification: the "questioning comment" is not mine, it is there in the code. I suspect it is a good question & that the code isn't what it should be. > > - Jay (briefly/pocket-sized-computer-aka-phone) > > On Sep 19, 2012, at 7:39 PM, Antony Hosking wrote: > > On Sep 19, 2012, at 9:31 PM, Jay K wrote: > > Areas that may need attention in the frontend? > > > TryFinStmt.m3: > > CG.Start_call_direct (p.handler.cg_proc, p.handler.level, CG.Type.Void); > (* Shouldn't we pass the activation parameter here? > What value do we pass? *) > CG.Call_direct (p.handler.cg_proc, CG.Type.Void); > > The level let?s you compute that. > > I'm wondering this too...like..what is the interface > to except/finally blocks? > > ? > > It appears they take two, or one, or zero parameters, > depending on intepretation and context. > > > two parameters: > _static_link > exception stuff > > > one parameter: > _static_link > > > zero parameters: > the above > > > I think the right implmentation (assuming no significant > change to nested functions, which Tony is thinking about:) ) > is one parameter: > > exception stuff > > and the implied/popped static_link, always. > > > For now, I think I'll not prototype these and use K&R definitions, yuck! > > That works. > > Maybe generating C++ with overloads is a good idea?? > > > > values/Procedure.m3: > > ELSIF (cur.token = TK.tSEMI) THEN > t.body := NEW (Body, self := t); > ProcBody.Push (t.body); > (* try accepting the Modula-2 syntax *) > Error.ID (id, "expecting \'=\' before procedure body"); > > > Probably everything after the error should be removed? > Or this is an example trying to recover from parse errors > and doing best effort? > > Yes. > > > > - Jay -------------- next part -------------- An HTML attachment was scrubbed... URL: From jay.krell at cornell.edu Thu Sep 20 14:52:03 2012 From: jay.krell at cornell.edu (Jay K) Date: Thu, 20 Sep 2012 12:52:03 +0000 Subject: [M3devel] unreachable finally => link error Message-ID: Here is a bug in the current system, with current backend.Possibly I introduced it. MODULE Main;PROCEDURE F1() = BEGIN RETURN; TRY FINALLY END; END F1;BEGIN F1(); END Main. book2:c139 jay$ cm3 -keep--- building in AMD64_DARWIN --- new source -> compiling Main.m3"../Main.m3", line 2: warning: unreachable statement1 warning encountered -> linking pgmUndefined symbols: "_Main_M3_LINE_2.1099", referenced from: _L_1 in Main.mold: symbol(s) not foundcollect2: ld returned 1 exit status m3_link => 1linker failed linking: pgmFatal Error: package build failed M3_LINE_2 is removed, besides the renamed. - Jay -------------- next part -------------- An HTML attachment was scrubbed... URL: From jay.krell at cornell.edu Thu Sep 20 22:10:03 2012 From: jay.krell at cornell.edu (Jay K) Date: Thu, 20 Sep 2012 20:10:03 +0000 Subject: [M3devel] Areas that may need attention in the frontend? In-Reply-To: <85381A4A-1D3C-47E8-9D15-50893BBE4B1E@cs.purdue.edu> References: , , <85381A4A-1D3C-47E8-9D15-50893BBE4B1E@cs.purdue.edu> Message-ID: This is still bugging me. My current plan is that for exception handlers (functions that end _M3_LINE_number or I3), I will generate the "usual" function Foo, and the function FooDirect. I will set a field in my Proc variable pointing to "direct". Whenever I make a direct call, I'll call the direct function. When I take the address, e.g. for an indirect call, I'll call the "regular" one.The indirect version will take two parameters -- activation and static link, static link list, the direct one will take one, static link. I kind of think this a bug in the frontend. It might even be a bug with other backends.It is rare for a finally block to look at the exception that was raised. This only affects finally blocks. It doesn't affect except blocks.They aren't ever "separate little functions", but rather chunks of code entered/exited via goto. I do need to investigate more though. Perhaps the frontend notices if a finally block calls Compiler.ThisException() and does something different? Inside a finally block, can I call a function, that itself calls Compiler.ThisException()? That would make it impossible for the frontend to fix up. Unless maybe it was pessimistic and observed any function call in a finally block as a sign to do things differently. Compiler.ThisException() is available in finally blocks, right?Otherwise the parameter would ever be passed (i.e. in RTExFrame.m3) The analog in Microsoft "SEH" isn't complete.A finally block can call BOOL AbnormalTermination() to find out if you "fell off the end" of the __try or called __leave, or raised an exception or returned. (return is kind of unfortunately "abnormal" -- and incurs runtime cost).But access to "the exception" is only available in __except filters and maybe __except blocks.Not __finally blocks. "All these Digital systems" and "all these exception handling systems" seem to have commom threads running through them, similar features, similar syntax, and similar implementation strategies. That's why I bring it up. - Jay Subject: Re: [M3devel] Areas that may need attention in the frontend? From: hosking at cs.purdue.edu Date: Thu, 20 Sep 2012 08:16:59 -0400 CC: m3devel at elegosoft.com To: jay.krell at cornell.edu On Sep 20, 2012, at 7:37 AM, Jay K wrote:I think this isn't right. I understand the static link is implied by level > 0. But the activation/exception parameter should be always passed or never passed. Or there should be two functions -- one that takes an exception, one that doesn't, and one calls the other. Or pass it as null if there isn't an exception. I should really not have to resort to K&R and passing varying numbers of parameters. I still have to look at a few test cases to see when each parameter is used.Maybe I'm confused. The other thing, you want the code to stay? For now, yes. - Jay CC: jay.krell at cornell.edu; m3devel at elegosoft.com From: jay.krell at cornell.edu Subject: Re: [M3devel] Areas that may need attention in the frontend? Date: Wed, 19 Sep 2012 21:33:43 -0700 To: hosking at cs.purdue.edu Clarification: the "questioning comment" is not mine, it is there in the code. I suspect it is a good question & that the code isn't what it should be. - Jay (briefly/pocket-sized-computer-aka-phone) On Sep 19, 2012, at 7:39 PM, Antony Hosking wrote: On Sep 19, 2012, at 9:31 PM, Jay K wrote:Areas that may need attention in the frontend? TryFinStmt.m3: CG.Start_call_direct (p.handler.cg_proc, p.handler.level, CG.Type.Void); (* Shouldn't we pass the activation parameter here? What value do we pass? *) CG.Call_direct (p.handler.cg_proc, CG.Type.Void); The level let?s you compute that. I'm wondering this too...like..what is the interfaceto except/finally blocks? ? It appears they take two, or one, or zero parameters,depending on intepretation and context. two parameters: _static_link exception stuff one parameter: _static_link zero parameters: the above I think the right implmentation (assuming no significantchange to nested functions, which Tony is thinking about:) )is one parameter: exception stuff and the implied/popped static_link, always. For now, I think I'll not prototype these and use K&R definitions, yuck! That works. Maybe generating C++ with overloads is a good idea?? values/Procedure.m3: ELSIF (cur.token = TK.tSEMI) THEN t.body := NEW (Body, self := t); ProcBody.Push (t.body); (* try accepting the Modula-2 syntax *) Error.ID (id, "expecting \'=\' before procedure body"); Probably everything after the error should be removed?Or this is an example trying to recover from parse errorsand doing best effort? Yes. - Jay -------------- next part -------------- An HTML attachment was scrubbed... URL: From jay.krell at cornell.edu Thu Sep 20 22:37:43 2012 From: jay.krell at cornell.edu (Jay K) Date: Thu, 20 Sep 2012 20:37:43 +0000 Subject: [M3devel] Areas that may need attention in the frontend? In-Reply-To: References: , , , , , , <85381A4A-1D3C-47E8-9D15-50893BBE4B1E@cs.purdue.edu>, Message-ID: Eh. Better yet, I'll just pass an extra parameter to direct calls to exception handlers.It is a gross special case. The backend shouldn't know anything about these functions. (* workaround frontend bug? *) IF proc.is_exception_handler THEN push(u, Type.Addr, "0"); pop_parameter_helper(u, "0"); END; Again though, I need to see what happens with the other backends. The other backends pass the static_link in a special way (do all callingconventions really have an extra, special register?), so that is part of their out.Plus that you can pass more parameters than are used.So they pass a static link in a special register, and one or zero parameters for the activation.The lingering question is what happens in finally blocks that access the activation but there isn't one.In my case it will be nil, with the above hack.For the other backends I think it is arbitrary garbage. - Jay From: jay.krell at cornell.edu To: hosking at cs.purdue.edu Date: Thu, 20 Sep 2012 20:10:03 +0000 CC: m3devel at elegosoft.com Subject: Re: [M3devel] Areas that may need attention in the frontend? This is still bugging me. My current plan is that for exception handlers (functions that end _M3_LINE_number or I3), I will generate the "usual" function Foo, and the function FooDirect. I will set a field in my Proc variable pointing to "direct". Whenever I make a direct call, I'll call the direct function. When I take the address, e.g. for an indirect call, I'll call the "regular" one.The indirect version will take two parameters -- activation and static link, static link list, the direct one will take one, static link. I kind of think this a bug in the frontend. It might even be a bug with other backends.It is rare for a finally block to look at the exception that was raised. This only affects finally blocks. It doesn't affect except blocks.They aren't ever "separate little functions", but rather chunks of code entered/exited via goto. I do need to investigate more though. Perhaps the frontend notices if a finally block calls Compiler.ThisException() and does something different? Inside a finally block, can I call a function, that itself calls Compiler.ThisException()? That would make it impossible for the frontend to fix up. Unless maybe it was pessimistic and observed any function call in a finally block as a sign to do things differently. Compiler.ThisException() is available in finally blocks, right?Otherwise the parameter would ever be passed (i.e. in RTExFrame.m3) The analog in Microsoft "SEH" isn't complete.A finally block can call BOOL AbnormalTermination() to find out if you "fell off the end" of the __try or called __leave, or raised an exception or returned. (return is kind of unfortunately "abnormal" -- and incurs runtime cost).But access to "the exception" is only available in __except filters and maybe __except blocks.Not __finally blocks. "All these Digital systems" and "all these exception handling systems" seem to have commom threads running through them, similar features, similar syntax, and similar implementation strategies. That's why I bring it up. - Jay Subject: Re: [M3devel] Areas that may need attention in the frontend? From: hosking at cs.purdue.edu Date: Thu, 20 Sep 2012 08:16:59 -0400 CC: m3devel at elegosoft.com To: jay.krell at cornell.edu On Sep 20, 2012, at 7:37 AM, Jay K wrote:I think this isn't right. I understand the static link is implied by level > 0. But the activation/exception parameter should be always passed or never passed. Or there should be two functions -- one that takes an exception, one that doesn't, and one calls the other. Or pass it as null if there isn't an exception. I should really not have to resort to K&R and passing varying numbers of parameters. I still have to look at a few test cases to see when each parameter is used.Maybe I'm confused. The other thing, you want the code to stay? For now, yes. - Jay CC: jay.krell at cornell.edu; m3devel at elegosoft.com From: jay.krell at cornell.edu Subject: Re: [M3devel] Areas that may need attention in the frontend? Date: Wed, 19 Sep 2012 21:33:43 -0700 To: hosking at cs.purdue.edu Clarification: the "questioning comment" is not mine, it is there in the code. I suspect it is a good question & that the code isn't what it should be. - Jay (briefly/pocket-sized-computer-aka-phone) On Sep 19, 2012, at 7:39 PM, Antony Hosking wrote: On Sep 19, 2012, at 9:31 PM, Jay K wrote:Areas that may need attention in the frontend? TryFinStmt.m3: CG.Start_call_direct (p.handler.cg_proc, p.handler.level, CG.Type.Void); (* Shouldn't we pass the activation parameter here? What value do we pass? *) CG.Call_direct (p.handler.cg_proc, CG.Type.Void); The level let?s you compute that. I'm wondering this too...like..what is the interfaceto except/finally blocks? ? It appears they take two, or one, or zero parameters,depending on intepretation and context. two parameters: _static_link exception stuff one parameter: _static_link zero parameters: the above I think the right implmentation (assuming no significantchange to nested functions, which Tony is thinking about:) )is one parameter: exception stuff and the implied/popped static_link, always. For now, I think I'll not prototype these and use K&R definitions, yuck! That works. Maybe generating C++ with overloads is a good idea?? values/Procedure.m3: ELSIF (cur.token = TK.tSEMI) THEN t.body := NEW (Body, self := t); ProcBody.Push (t.body); (* try accepting the Modula-2 syntax *) Error.ID (id, "expecting \'=\' before procedure body"); Probably everything after the error should be removed?Or this is an example trying to recover from parse errorsand doing best effort? Yes. - Jay -------------- next part -------------- An HTML attachment was scrubbed... URL: From jay.krell at cornell.edu Thu Sep 20 22:49:35 2012 From: jay.krell at cornell.edu (Jay K) Date: Thu, 20 Sep 2012 20:49:35 +0000 Subject: [M3devel] test p223 .so vs. .dylib in expected output Message-ID: Olaf, here's an easy bug to understand that you introduced.It is a bug in the test code, not a bug otherewise.Think about how to fix it?I think in this case, we can just have expected-output.1, expected-output.2, expected-output.3, etc. as needed.The "check" code can enumerate and as long as the output matches any one of the expected outputs, pass.That is, even if Linux somehow accidentally outputs "dylib" or Darwin output "so", we'd claim success.There are "tighter" alternatives. You could have expected-output.Linux, expected-output.Darwin, expected-output.NT, expected-output.Solaris, expected-output.FreeBSD, but many of them are identical and it is unnecessary per-target work.Maybe expected-output-so and expected-output-dylib, and the checker can enumerate expected-output-*. I don't think expected-output-I386_DARWIN, expected-output-I386_LINUX, etc. is the way to go, but it is an option. Too much repetition/bloat. The test suite is handy btw. The C backend passes most of the tests already. :) --- ../src/p2/p223/stdout.build 2009-12-15 03:04:02.000000000 -0800+++ ../src/p2/p223/I386_DARWIN/stdout.build 2012-09-20 13:44:54.000000000 -0700@@ -1,11 +1,13 @@ make_dir(PKG_INSTALL & "/p223/" & TARGET) install_file(".M3EXPORTS", PKG_INSTALL & "/p223/" & TARGET, "0664") make_dir(LIB_INSTALL)-install_file("liblib.so.5", LIB_INSTALL, "0775")+install_file("liblib.5.2.dylib", LIB_INSTALL, "0775") symbolic_link_file(PKG_INSTALL & "/p223/" & TARGET & "/liblib.a", LIB_INSTALL & "/liblib.a")-symbolic_link_file("liblib.so.5", LIB_INSTALL & "/liblib.so")-symbolic_link_file(LIB_INSTALL & "/liblib.so.5", PKG_INSTALL & "/p223/" & TARGET & "/liblib.so")-symbolic_link_file(LIB_INSTALL & "/liblib.so.5", PKG_INSTALL & "/p223/" & TARGET & "/liblib.so.5")+symbolic_link_file("liblib.5.2.dylib", LIB_INSTALL & "/liblib.dylib")+symbolic_link_file("liblib.5.2.dylib", LIB_INSTALL & "/liblib.5.dylib")+symbolic_link_file(LIB_INSTALL & "/liblib.5.2.dylib", PKG_INSTALL & "/p223/" & TARGET & "/liblib.dylib")+symbolic_link_file(LIB_INSTALL & "/liblib.5.2.dylib", PKG_INSTALL & "/p223/" & TARGET & "/liblib.5.dylib")+symbolic_link_file(LIB_INSTALL & "/liblib.5.2.dylib", PKG_INSTALL & "/p223/" & TARGET & "/liblib.5.2.dylib") install_file("liblib.a", PKG_INSTALL & "/p223/" & TARGET, "0664") install_file("liblib.m3x", PKG_INSTALL & "/p223/" & TARGET, "0664") install_file(".M3WEB", PKG_INSTALL & "/p223/" & TARGET, "0664") -------------- next part -------------- An HTML attachment was scrubbed... URL: From wagner at elegosoft.com Fri Sep 21 00:06:56 2012 From: wagner at elegosoft.com (Olaf Wagner) Date: Fri, 21 Sep 2012 00:06:56 +0200 Subject: [M3devel] Fw: Rel 3.8.6. on XP Message-ID: <20120921000656.6586fc72845b26ae4812533f@elegosoft.com> Begin forwarded message: Date: Thu, 20 Sep 2012 15:01:06 +0200 From: Michael Moeller To: m3-support at elego.de Subject: Rel 3.8.6. on XP Dear developer team, I just tried out release 5.8.6. While the cm3 compiler works fine on SuSE Linux I have difficulties to make it run on XP. Setup was done using cm3-NT386-REL.msi which also set the path environment variable. Calling any of the exe files from a cmd shell simply gives me a 'can't execute' error, though. Btw, the browser refuses to connect to your 'known problems' pages because it considers them untrusted sites. Regards, Michael -- Olaf Wagner -- elego Software Solutions GmbH -- http://www.elegosoft.com Gustav-Meyer-Allee 25 / Geb?ude 12, 13355 Berlin, Germany phone: +49 30 23 45 86 96 mobile: +49 177 2345 869 fax: +49 30 23 45 86 95 Gesch?ftsf?hrer: Michael Diers, Olaf Wagner | Sitz: Berlin Handelregister: Amtsgericht Charlottenburg HRB 77719 | USt-IdNr: DE163214194 From dabenavidesd at yahoo.es Fri Sep 21 00:20:05 2012 From: dabenavidesd at yahoo.es (Daniel Alejandro Benavides D.) Date: Thu, 20 Sep 2012 23:20:05 +0100 (BST) Subject: [M3devel] Fw: Rel 3.8.6. on XP In-Reply-To: <20120921000656.6586fc72845b26ae4812533f@elegosoft.com> Message-ID: <1348179605.48270.YahooMailClassic@web29705.mail.ird.yahoo.com> Hi all: I'm not a Win expert, but telling from that message RT errors follows that RT isn't there for you. You need, MS VS? if you are XP escribi?: De: Olaf Wagner Asunto: [M3devel] Fw: Rel 3.8.6. on XP Para: m3devel at elegosoft.com Fecha: jueves, 20 de septiembre, 2012 17:06 Begin forwarded message: Date: Thu, 20 Sep 2012 15:01:06 +0200 From: Michael Moeller To: m3-support at elego.de Subject: Rel 3.8.6. on XP Dear developer team, I just tried out release 5.8.6. While the cm3 compiler works fine on SuSE Linux I have difficulties to make it run on XP. Setup was done using cm3-NT386-REL.msi which also set the path environment variable. Calling any of the exe files from a cmd shell simply gives me a 'can't execute' error, though. Btw, the browser refuses to connect to your 'known problems' pages because it considers them untrusted sites. Regards, Michael -- Olaf Wagner -- elego Software Solutions GmbH -- http://www.elegosoft.com ? ? ? ? ? ? ???Gustav-Meyer-Allee 25 / Geb?ude 12, 13355 Berlin, Germany phone: +49 30 23 45 86 96? mobile: +49 177 2345 869? fax: +49 30 23 45 86 95 Gesch?ftsf?hrer: Michael Diers, Olaf Wagner | Sitz: Berlin Handelregister: Amtsgericht Charlottenburg HRB 77719 | USt-IdNr: DE163214194 -------------- next part -------------- An HTML attachment was scrubbed... URL: From jay.krell at cornell.edu Fri Sep 21 01:10:34 2012 From: jay.krell at cornell.edu (Jay K) Date: Thu, 20 Sep 2012 23:10:34 +0000 Subject: [M3devel] Fw: Rel 3.8.6. on XP In-Reply-To: <20120921000656.6586fc72845b26ae4812533f@elegosoft.com> References: <20120921000656.6586fc72845b26ae4812533f@elegosoft.com> Message-ID: Bing for "vcredist".I don't remember if we use 2005 or 2008 or a service pack thereof, but you are safe to install "extra". - Jay > Date: Fri, 21 Sep 2012 00:06:56 +0200 > From: wagner at elegosoft.com > To: m3devel at elegosoft.com > Subject: [M3devel] Fw: Rel 3.8.6. on XP > > Begin forwarded message: > > Date: Thu, 20 Sep 2012 15:01:06 +0200 > From: Michael Moeller > To: m3-support at elego.de > Subject: Rel 3.8.6. on XP > > > Dear developer team, > > I just tried out release 5.8.6. While the cm3 compiler works fine on > SuSE Linux > I have difficulties to make it run on XP. Setup was done using > cm3-NT386-REL.msi > which also set the path environment variable. Calling any of the exe > files from a cmd > shell simply gives me a 'can't execute' error, though. > > Btw, the browser refuses to connect to your 'known problems' pages because > it considers them untrusted sites. > > Regards, > Michael > > > -- > Olaf Wagner -- elego Software Solutions GmbH -- http://www.elegosoft.com > Gustav-Meyer-Allee 25 / Geb?ude 12, 13355 Berlin, Germany > phone: +49 30 23 45 86 96 mobile: +49 177 2345 869 fax: +49 30 23 45 86 95 > Gesch?ftsf?hrer: Michael Diers, Olaf Wagner | Sitz: Berlin > Handelregister: Amtsgericht Charlottenburg HRB 77719 | USt-IdNr: DE163214194 > -------------- next part -------------- An HTML attachment was scrubbed... URL: From jay.krell at cornell.edu Fri Sep 21 01:18:59 2012 From: jay.krell at cornell.edu (Jay K) Date: Thu, 20 Sep 2012 23:18:59 +0000 Subject: [M3devel] uplevel locals declared after function starts.. Message-ID: We get uplevel locals declared while within a function.So I think I'll bite the bullet and make multiple passes now.Otherwise I build up the frame struct "too early".I need to see all the locals -- all the uplevels, early in a function. There is also a chance they don't all have unique names. I do NOT expect I should have separate frames/static_links per-scope,just per-function. I could put structs inside the frame, named after the line they starton or such.. that might be prettier and more readable, or not. The structs could then be unioned at some point -- parallel scopescan/should share storage. M3C.m3:PROCEDURE declare_local(...)BEGIN...IF u.in_proc THEN ExtraScope_Open(u); print(u, var.Declare() & " M3_INIT;"); <* ASSERT up_level = FALSE *> this fails ELSE IF up_level THEN u.current_proc.uplevels := TRUE; END; u.current_proc.locals.addhi(var); END; RETURN var;END declare_local; == package /Users/jay/dev2/cm3/m3-libs/m3tk-misc == ...new source -> compiling Args.m3 ****** runtime error:*** <*ASSERT*> failed.*** file "../src/M3C.m3", line 1778*** m3_backend => 1536m3cc (aka cm3cg) failed compiling: Args.mc I'm guessing the code is here: PROCEDURE Errors(h: Handle; indent: CARDINAL := 0): Text.T RAISES {}= BEGIN IF h.errors = 0 THEN <*FATAL Fatal*> BEGIN RAISE Fatal; END; ELSE VAR texts := NEW(REF ARRAY OF TEXT, h.errors * 2); (* allocates space for all the error messages + padding *) pos: CARDINAL := 0; padding := Fmt.Pad("", indent); fmt: Text.T; <*INLINE*> PROCEDURE Add(t: Text.T) RAISES {}= BEGIN texts[pos] := t; INC(pos) END Add; <*INLINE*> PROCEDURE PaddedAdd(t: Text.T) RAISES {}= BEGIN Add(padding); Add(t) END PaddedAdd; see how "texts" is both uplevel and "not at the start" of the function. This is going to take a few days to deal with. Compiler can compile itself, and a large swath of the system now.I didn't use the self-built compiler, but I will do that next. It probably works.Very good. - Jay -------------- next part -------------- An HTML attachment was scrubbed... URL: From rcolebur at SCIRES.COM Fri Sep 21 05:07:56 2012 From: rcolebur at SCIRES.COM (Coleburn, Randy) Date: Thu, 20 Sep 2012 23:07:56 -0400 Subject: [M3devel] EXT: Fw: Rel 3.8.6. on XP In-Reply-To: <20120921000656.6586fc72845b26ae4812533f@elegosoft.com> References: <20120921000656.6586fc72845b26ae4812533f@elegosoft.com> Message-ID: I prepared some CMD files and a set of instructions for setting up cm3 on Windows a long time back. Not quite sure where those instructions are now, but the scripts are still in the CVS repository. Once you've installed the minimal distribution on Windows, you can use my scripts to rebuild the entire system from source code. These scripts also help with setting up your command line environment. I'll try to explain below... The scripts I wrote to assist in rebuilding cm3 from source code are in: scripts\dev\windows There are some more scripts in: scripts\install\windows that first must be put in your "cm3\bin" folder for everything to work. In particular, cm3CommandShell.CMD, sets up your command shell window to work properly with all the right paths and environment variables. On my system, I have cm3 stored on my C: drive as follows: C:\cm3 C:\cm3\bin C:\cm3\lib C:\cm3\pkg C:\cm3\doc C:\cm3\examples C:\cm3\man Etc. C:\cm3\Sandbox The Sandbox folder is where I keep a copy of the entire source tree from the CVS repository. So on my system, you would find the scripts I referenced in: C:\cm3\Sandbox\scripts And you would also have: C:\cm3\Sandbox\m3-sys C:\cm3\Sandbox\m3-libs Etc. If you "CD to C:\cm3\Sandbox\scripts\dev\windows" and then run "RCC_upgradeCM3 -help", it will give you some basic help on what that script does. The goal was to provide on Windows 2000/XP the functionality of the "upgrade.sh" script. So, in summary, you should be able to get a current (up-to-date) working CM3 on Windows by doing the following: 0. Ensure you have the free Visual C++ Express (or a paid version) installed (see Prerequisite below). 1. Install the most recent cm3 minimal binary distribution for Windows as per the regular instructions. (Basically, you are just unzipping the files to your hard drive in C:\cm3 ) 2. Grab all the sources from the CVS repository and store them in C:\cm3\Sandbox. 3. Open a Windows command shell window. 4. COPY C:\cm3\Sandbox\scripts\install\windows\*.CMD C:\cm3\bin (Actually, the RCC_upgradeCM3 script will do this for you, but it can't hurt to do it here.) 5. CD C:\cm3\Sandbox\scripts\dev\windows 6. .\RCC_upgradeCM3 -all (NOTE: ".\RCC_upgradeCM3 -min" would build a "minimal" cm3 system, whereas "-all" builds all packages.) PREREQUISITE: Your Windows system has to have Microsoft Visual Studio for C/C++ installed so that the C source files can be compiled and so that you have a linker for building programs and libraries. Depending on which visual studio version you use, you may have to edit C:\cm3\bin\cm3CommandShell.CMD to tell it where to find the VCVarsAll.BAT file. Look under the section labeled :DEFAULTS. There are examples for VC98, 2003, VS8.0, VS9.0, VS10.0. The FREE "express" editions of Visual Studio work fine. The one I've been using is Microsoft Visual Studio 2010 Express, making sure to install at least the Visual C++ 2010. Finally, if you don't want to rebuild all the sources and you just want to run the cm3 compiler et al, you should complete steps 0, 1, 3, and 4 above, then from the command prompt: C:\cm3\bin\cm3CommandShell.CMD The above script will set up your command shell window with all the right environment variables and paths. Optionally, the file: C:\cm3\Sandbox\scripts\install\windows\cm3CommandPromptHere.reg can be used to add an entry to your Windows registry that lets you right-mouse-click on a folder in Windows Explorer and choose "cm3 Command Prompt Here" from the pull-down menu. This action will open up a new command shell window and automatically run the script to set up the environment and paths for you to use cm3. This is the easiest way and is what I do. For your reference, the contents of this file are: Windows Registry Editor Version 5.00 [HKEY_LOCAL_MACHINE\SOFTWARE\Classes\Folder\shell\cm3 Prompt] @="cm3 Command Prompt Here" [HKEY_LOCAL_MACHINE\SOFTWARE\Classes\Folder\shell\cm3 Prompt\Command] @="Cmd.exe /c \"pushd %L && C:\\cm3\\bin\\cm3CommandShell.CMD\"" Hope this helps a bit. Olaf, you may want to put this info on the web site for folks new to cm3 on Windows. Regards, Randy Coleburn -----Original Message----- From: Olaf Wagner [mailto:wagner at elegosoft.com] Sent: Thursday, September 20, 2012 6:07 PM To: m3devel at elegosoft.com Subject: EXT:[M3devel] Fw: Rel 3.8.6. on XP Begin forwarded message: Date: Thu, 20 Sep 2012 15:01:06 +0200 From: Michael Moeller To: m3-support at elego.de Subject: Rel 3.8.6. on XP Dear developer team, I just tried out release 5.8.6. While the cm3 compiler works fine on SuSE Linux I have difficulties to make it run on XP. Setup was done using cm3-NT386-REL.msi which also set the path environment variable. Calling any of the exe files from a cmd shell simply gives me a 'can't execute' error, though. Btw, the browser refuses to connect to your 'known problems' pages because it considers them untrusted sites. Regards, Michael -- Olaf Wagner -- elego Software Solutions GmbH -- http://www.elegosoft.com Gustav-Meyer-Allee 25 / Geb?ude 12, 13355 Berlin, Germany phone: +49 30 23 45 86 96 mobile: +49 177 2345 869 fax: +49 30 23 45 86 95 Gesch?ftsf?hrer: Michael Diers, Olaf Wagner | Sitz: Berlin Handelregister: Amtsgericht Charlottenburg HRB 77719 | USt-IdNr: DE163214194 From jay.krell at cornell.edu Fri Sep 21 07:03:10 2012 From: jay.krell at cornell.edu (Jay K) Date: Fri, 21 Sep 2012 05:03:10 +0000 Subject: [M3devel] trampolines and uplevel locals declared after function starts.. In-Reply-To: References: , Message-ID: > Did you take a look at the LLVM IR I sent? T Sorry, I couldn't quickly make sense of it. :(I have to read up on LLVM or study your code more.(This is why I favor a C backend -- I'm already an expert and there is far more C expertise in the world than LLVM expertise..I think.. and other reasons like portability..) Mention of "trampolines" was worrisome though.That usually means "runtime generated code, often on the stack". True here? If not, nevermindIf so: There is no good solution here, but I think runtime generated code is mostly a losing battle..at least on the stack. If you dedicate a little bit of special purpose platform-specific code to it, and you don't mind it being slow, and you deal with the lifetime management, then it becomes viable.e.g. on Windows, you use VirtualAlloc(MEM_EXECUTE).On other platforms you use mprotect I think. And/or mmap? mmap(PROT_EXEC)?But you end up allocating memory in large chunks, like at least 4K or 64K.(You can also write out little temporary .so/.dll files, but that is unnecessarily inefficient.) I've seen code that calls mprotect against the stack. Yuck.The stack is nonexecutable on purpose -- for security (assuming there is any C or C++ code in the process). If you read the libffi mailing list, you see they are constantly in this arms race.There is a slow steady trickle of problems making the libffi code executable.For Darwin/ARM they came up with a trick to avoid generating code, since the platform doesn't allow unsigned code to run. Pluses/minuses: runtime generated code:Producing the code is fast, on historical systems that don't make it difficult to execute memory, e.g. on the stack.Running the code is fast.Pointers to closures become compatible with C -- you can pass a pointer to a closure as a callback to or C++ and it works.Highly target-dependent. The unusual Modula-3 method:Also fast.Calling function pointers is different and larger and slower.C code cannot call function pointers to nested functions. That is the main downside.Only slightly target-dependent -- in its choice of closure marker.I think we should change the closure marker slightly -- its size should be target-dependent, it should only be 4 bytes on SPARC64, MIPS64, PPC64, Alpha, AMD64 -- so the alignment check can be skipped. And it should possibly be larger than 4 or 8 bytes on IA64.But someone needs to read up on all the various instruction encodings and verify that 4 or 8 0xFF bytes are really invalid and won't occur.But most likely if 4 bytes of 0xFF are a good marker on MIPS32, PPC32, SPARC32, I386, they are also probably a good marker on MIPS64, PPC64, SPARC64, AMD64. And Alpha.Another option is to use something like "jmp marker". i.e. a jump to an address that is used just be the marker. It might not be a constant though. Maybe it is relocated. But you want it to be the same across all dynamic linked code, actually. We might want to have calls through a function pointer go through a helper function, to keep it small. Hm.. I wonder..maybe a closure can be generated fairly portably actually.Maybe you just need one little wrapper per function signature. And most would really be the same.Let me think on this..hm..well..you could do it if you have a special static link register probably. I need to think about this more. Do "all" the calling conventions provide a special extra register for "static link"? And is that often used for C++ "this"? In that case, there is a way.. Ultimately, I should point out, the idea of passing a closure to C is actually very useful.One should be able to pass an "object method pointer".So some language construct or pragma might be nice there -- to force down the runtime generated code path.But usually the C function that wants a function pointer also takes a "void* context", so maybe not so needed. Or maybe folks would just use "libffi" for that. - Jay CC: m3devel at elegosoft.com From: antony.hosking at gmail.com Subject: Re: [M3devel] uplevel locals declared after function starts.. Date: Thu, 20 Sep 2012 19:38:27 -0400 To: jay.krell at cornell.edu Agreed. You need to backpatch the uplevel locals. I would accumulate all of them. Did you take a look at the LLVM IR I sent? That's how I plan to so it. Sent from my iPhone On Sep 20, 2012, at 19:18, Jay K wrote: We get uplevel locals declared while within a function.So I think I'll bite the bullet and make multiple passes now.Otherwise I build up the frame struct "too early".I need to see all the locals -- all the uplevels, early in a function. There is also a chance they don't all have unique names. I do NOT expect I should have separate frames/static_links per-scope,just per-function. I could put structs inside the frame, named after the line they starton or such.. that might be prettier and more readable, or not. The structs could then be unioned at some point -- parallel scopescan/should share storage. M3C.m3:PROCEDURE declare_local(...)BEGIN...IF u.in_proc THEN ExtraScope_Open(u); print(u, var.Declare() & " M3_INIT;"); <* ASSERT up_level = FALSE *> this fails ELSE IF up_level THEN u.current_proc.uplevels := TRUE; END; u.current_proc.locals.addhi(var); END; RETURN var;END declare_local; == package /Users/jay/dev2/cm3/m3-libs/m3tk-misc == ...new source -> compiling Args.m3 ****** runtime error:*** <*ASSERT*> failed.*** file "../src/M3C.m3", line 1778*** m3_backend => 1536m3cc (aka cm3cg) failed compiling: Args.mc I'm guessing the code is here: PROCEDURE Errors(h: Handle; indent: CARDINAL := 0): Text.T RAISES {}= BEGIN IF h.errors = 0 THEN <*FATAL Fatal*> BEGIN RAISE Fatal; END; ELSE VAR texts := NEW(REF ARRAY OF TEXT, h.errors * 2); (* allocates space for all the error messages + padding *) pos: CARDINAL := 0; padding := Fmt.Pad("", indent); fmt: Text.T; <*INLINE*> PROCEDURE Add(t: Text.T) RAISES {}= BEGIN texts[pos] := t; INC(pos) END Add; <*INLINE*> PROCEDURE PaddedAdd(t: Text.T) RAISES {}= BEGIN Add(padding); Add(t) END PaddedAdd; see how "texts" is both uplevel and "not at the start" of the function. This is going to take a few days to deal with. Compiler can compile itself, and a large swath of the system now.I didn't use the self-built compiler, but I will do that next. It probably works.Very good. - Jay -------------- next part -------------- An HTML attachment was scrubbed... URL: From hosking at cs.purdue.edu Fri Sep 21 15:33:48 2012 From: hosking at cs.purdue.edu (Antony Hosking) Date: Fri, 21 Sep 2012 09:33:48 -0400 Subject: [M3devel] Areas that may need attention in the frontend? In-Reply-To: References: , , , , , , <85381A4A-1D3C-47E8-9D15-50893BBE4B1E@cs.purdue.edu>, Message-ID: I haven?t looked at what the front-end does with exception handlers in a long time. I?ll try to look soon. Let me know what you find out. Antony Hosking | Associate Professor | Computer Science | Purdue University 305 N. University Street | West Lafayette | IN 47907 | USA Mobile +1 765 427 5484 On Sep 20, 2012, at 4:37 PM, Jay K wrote: > Eh. Better yet, I'll just pass an extra parameter to direct calls to exception handlers. > It is a gross special case. The backend shouldn't know anything about these functions. > > > (* workaround frontend bug? *) > IF proc.is_exception_handler THEN > push(u, Type.Addr, "0"); > pop_parameter_helper(u, "0"); > END; > > > Again though, I need to see what happens with the other backends. > > > The other backends pass the static_link in a special way (do all calling > conventions really have an extra, special register?), so that is part of their out. > Plus that you can pass more parameters than are used. > So they pass a static link in a special register, and one or zero parameters for the activation. > The lingering question is what happens in finally blocks that access the activation but there isn't one. > In my case it will be nil, with the above hack. > For the other backends I think it is arbitrary garbage. > > > - Jay > > > From: jay.krell at cornell.edu > To: hosking at cs.purdue.edu > Date: Thu, 20 Sep 2012 20:10:03 +0000 > CC: m3devel at elegosoft.com > Subject: Re: [M3devel] Areas that may need attention in the frontend? > > This is still bugging me. My current plan is that for exception handlers (functions that end _M3_LINE_number or I3), I will generate the "usual" function Foo, and the function FooDirect. I will set a field in my Proc variable pointing to "direct". Whenever I make a direct call, I'll call the direct function. When I take the address, e.g. for an indirect call, I'll call the "regular" one. > The indirect version will take two parameters -- activation and static link, static link list, the direct one will take one, static link. > > > I kind of think this a bug in the frontend. > > > It might even be a bug with other backends. > It is rare for a finally block to look at the exception that was raised. > > > This only affects finally blocks. > > > It doesn't affect except blocks. > They aren't ever "separate little functions", but rather chunks of code entered/exited via goto. > > > > I do need to investigate more though. > > > Perhaps the frontend notices if a finally block calls Compiler.ThisException() and does something different? > > > Inside a finally block, can I call a function, that itself calls Compiler.ThisException()? That would make it impossible for the frontend to fix up. Unless maybe it was pessimistic and observed any function call in a finally block as a sign to do things differently. > > > Compiler.ThisException() is available in finally blocks, right? > Otherwise the parameter would ever be passed (i.e. in RTExFrame.m3) > > > The analog in Microsoft "SEH" isn't complete. > A finally block can call BOOL AbnormalTermination() to find out if you "fell off the end" of the __try or called __leave, or raised an exception or returned. (return is kind of unfortunately "abnormal" -- and incurs runtime cost). > But access to "the exception" is only available in __except filters and maybe __except blocks. > Not __finally blocks. > > > "All these Digital systems" and "all these exception handling systems" seem to have commom threads running through them, similar features, similar syntax, and similar implementation strategies. That's why I bring it up. > > > - Jay > > > Subject: Re: [M3devel] Areas that may need attention in the frontend? > From: hosking at cs.purdue.edu > Date: Thu, 20 Sep 2012 08:16:59 -0400 > CC: m3devel at elegosoft.com > To: jay.krell at cornell.edu > > > > On Sep 20, 2012, at 7:37 AM, Jay K wrote: > > I think this isn't right. I understand the static link is implied by level > 0. But the activation/exception parameter should be always passed or never passed. Or there should be two functions -- one that takes an exception, one that doesn't, and one calls the other. Or pass it as null if there isn't an exception. > > I should really not have to resort to K&R and passing varying numbers of parameters. > > I still have to look at a few test cases to see when each parameter is used. > Maybe I'm confused. > > The other thing, you want the code to stay? > > For now, yes. > > > - Jay > > > CC: jay.krell at cornell.edu; m3devel at elegosoft.com > From: jay.krell at cornell.edu > Subject: Re: [M3devel] Areas that may need attention in the frontend? > Date: Wed, 19 Sep 2012 21:33:43 -0700 > To: hosking at cs.purdue.edu > > Clarification: the "questioning comment" is not mine, it is there in the code. I suspect it is a good question & that the code isn't what it should be. > > - Jay (briefly/pocket-sized-computer-aka-phone) > > On Sep 19, 2012, at 7:39 PM, Antony Hosking wrote: > > On Sep 19, 2012, at 9:31 PM, Jay K wrote: > > Areas that may need attention in the frontend? > > > TryFinStmt.m3: > > CG.Start_call_direct (p.handler.cg_proc, p.handler.level, CG.Type.Void); > (* Shouldn't we pass the activation parameter here? > What value do we pass? *) > CG.Call_direct (p.handler.cg_proc, CG.Type.Void); > > The level let?s you compute that. > > I'm wondering this too...like..what is the interface > to except/finally blocks? > > ? > > It appears they take two, or one, or zero parameters, > depending on intepretation and context. > > > two parameters: > _static_link > exception stuff > > > one parameter: > _static_link > > > zero parameters: > the above > > > I think the right implmentation (assuming no significant > change to nested functions, which Tony is thinking about:) ) > is one parameter: > > exception stuff > > and the implied/popped static_link, always. > > > For now, I think I'll not prototype these and use K&R definitions, yuck! > > That works. > > Maybe generating C++ with overloads is a good idea?? > > > > values/Procedure.m3: > > ELSIF (cur.token = TK.tSEMI) THEN > t.body := NEW (Body, self := t); > ProcBody.Push (t.body); > (* try accepting the Modula-2 syntax *) > Error.ID (id, "expecting \'=\' before procedure body"); > > > Probably everything after the error should be removed? > Or this is an example trying to recover from parse errors > and doing best effort? > > Yes. > > > > - Jay -------------- next part -------------- An HTML attachment was scrubbed... URL: From hosking at cs.purdue.edu Fri Sep 21 15:50:21 2012 From: hosking at cs.purdue.edu (Antony Hosking) Date: Fri, 21 Sep 2012 09:50:21 -0400 Subject: [M3devel] trampolines and uplevel locals declared after function starts.. In-Reply-To: References: , Message-ID: <0FF69FC1-6CFE-4FC7-8889-C363E91A64C6@cs.purdue.edu> I think we should leave the CG interfaces as they are already (for static links). I can see how to generate LLVM IR easily with things the way they are. And you are already working to it. I wasn?t suggesting that you use trampolines, though I think it would be easy enough to do. But I am going to use the LLVM nest approach to pass frame pointers. That way I?ll get the efficient native static link passing code. On Sep 21, 2012, at 1:03 AM, Jay K wrote: > > Did you take a look at the LLVM IR I sent? T > > Sorry, I couldn't quickly make sense of it. :( > I have to read up on LLVM or study your code more. > (This is why I favor a C backend -- I'm already an expert and there is far more C expertise in the world than LLVM expertise..I think.. and other reasons like portability..) > > > Mention of "trampolines" was worrisome though. > That usually means "runtime generated code, often on the stack". True here? > > > If not, nevermind > If so: > > > > There is no good solution here, but I think runtime generated code is mostly a losing battle..at least on the stack. If you dedicate a little bit of special purpose platform-specific code to it, and you don't mind it being slow, and you deal with the lifetime management, then it becomes viable. > e.g. on Windows, you use VirtualAlloc(MEM_EXECUTE). > On other platforms you use mprotect I think. And/or mmap? mmap(PROT_EXEC)? > But you end up allocating memory in large chunks, like at least 4K or 64K. > (You can also write out little temporary .so/.dll files, but that is unnecessarily inefficient.) > > > I've seen code that calls mprotect against the stack. Yuck. > The stack is nonexecutable on purpose -- for security (assuming there is any C or C++ code in the process). > > > If you read the libffi mailing list, you see they are constantly in this arms race. > There is a slow steady trickle of problems making the libffi code executable. > For Darwin/ARM they came up with a trick to avoid generating code, since the platform doesn't allow unsigned code to run. > > > > Pluses/minuses: > > > runtime generated code: > Producing the code is fast, on historical systems that don't make it difficult to execute memory, e.g. on the stack. > Running the code is fast. > Pointers to closures become compatible with C -- you can pass a pointer to a closure as a callback to or C++ and it works. > Highly target-dependent. > > > The unusual Modula-3 method: > Also fast. > Calling function pointers is different and larger and slower. > C code cannot call function pointers to nested functions. That is the main downside. > Only slightly target-dependent -- in its choice of closure marker. > I think we should change the closure marker slightly -- its size should be target-dependent, it should only be 4 bytes on SPARC64, MIPS64, PPC64, Alpha, AMD64 -- so the alignment check can be skipped. And it should possibly be larger than 4 or 8 bytes on IA64. > But someone needs to read up on all the various instruction encodings and verify that 4 or 8 0xFF bytes are really invalid and won't occur. > But most likely if 4 bytes of 0xFF are a good marker on MIPS32, PPC32, SPARC32, I386, they are also probably a good marker on MIPS64, PPC64, SPARC64, AMD64. And Alpha. > Another option is to use something like "jmp marker". i.e. a jump to an address that is used just be the marker. It might not be a constant though. Maybe it is relocated. But you want it to be the same across all dynamic linked code, actually. > > > We might want to have calls through a function pointer go through a helper function, to keep it small. > > > > Hm.. I wonder..maybe a closure can be generated fairly portably actually. > Maybe you just need one little wrapper per function signature. And most would really be the same. > Let me think on this..hm..well..you could do it if you have a special static link register probably. I need to think about this more. Do "all" the calling conventions provide a special extra register for "static link"? And is that often used for C++ "this"? In that case, there is a way.. > > > > Ultimately, I should point out, the idea of passing a closure to C is actually very useful. > One should be able to pass an "object method pointer". > So some language construct or pragma might be nice there -- to force down the runtime generated code path. > But usually the C function that wants a function pointer also takes a "void* context", so maybe not so needed. > > > Or maybe folks would just use "libffi" for that. > > > > - Jay > > CC: m3devel at elegosoft.com > From: antony.hosking at gmail.com > Subject: Re: [M3devel] uplevel locals declared after function starts.. > Date: Thu, 20 Sep 2012 19:38:27 -0400 > To: jay.krell at cornell.edu > > Agreed. You need to backpatch the uplevel locals. I would accumulate all of them. Did you take a look at the LLVM IR I sent? That's how I plan to so it. > > Sent from my iPhone > > On Sep 20, 2012, at 19:18, Jay K wrote: > > We get uplevel locals declared while within a function. > So I think I'll bite the bullet and make multiple passes now. > Otherwise I build up the frame struct "too early". > I need to see all the locals -- all the uplevels, early in a function. > > > There is also a chance they don't all have unique names. > > > I do NOT expect I should have separate frames/static_links per-scope, > just per-function. > > > I could put structs inside the frame, named after the line they start > on or such.. that might be prettier and more readable, or not. > > > The structs could then be unioned at some point -- parallel scopes > can/should share storage. > > > M3C.m3: > PROCEDURE declare_local(...) > BEGIN > ... > IF u.in_proc THEN > ExtraScope_Open(u); > print(u, var.Declare() & " M3_INIT;"); > <* ASSERT up_level = FALSE *> this fails > ELSE > IF up_level THEN > u.current_proc.uplevels := TRUE; > END; > u.current_proc.locals.addhi(var); > END; > RETURN var; > END declare_local; > > > == package /Users/jay/dev2/cm3/m3-libs/m3tk-misc == > > ... > new source -> compiling Args.m3 > > > *** > *** runtime error: > *** <*ASSERT*> failed. > *** file "../src/M3C.m3", line 1778 > *** > > m3_backend => 1536 > m3cc (aka cm3cg) failed compiling: Args.mc > > > I'm guessing the code is here: > > > PROCEDURE Errors(h: Handle; indent: CARDINAL := 0): Text.T RAISES {}= > BEGIN > IF h.errors = 0 THEN > <*FATAL Fatal*> BEGIN RAISE Fatal; END; > ELSE > > VAR > texts := NEW(REF ARRAY OF TEXT, h.errors * 2); > (* allocates space for all the error messages + padding *) > pos: CARDINAL := 0; > padding := Fmt.Pad("", indent); > fmt: Text.T; > > <*INLINE*> PROCEDURE Add(t: Text.T) RAISES {}= > BEGIN texts[pos] := t; INC(pos) END Add; > <*INLINE*> PROCEDURE PaddedAdd(t: Text.T) RAISES {}= > BEGIN Add(padding); Add(t) END PaddedAdd; > > > > see how "texts" is both uplevel and "not at the start" of the function. > > > This is going to take a few days to deal with. > > > Compiler can compile itself, and a large swath of the system now. > I didn't use the self-built compiler, but I will do that next. It probably works. > Very good. > > > - Jay -------------- next part -------------- An HTML attachment was scrubbed... URL: From jay.krell at cornell.edu Fri Sep 21 16:27:46 2012 From: jay.krell at cornell.edu (Jay K) Date: Fri, 21 Sep 2012 14:27:46 +0000 Subject: [M3devel] trampolines and uplevel locals declared after function starts.. In-Reply-To: <0FF69FC1-6CFE-4FC7-8889-C363E91A64C6@cs.purdue.edu> References: , , , , <0FF69FC1-6CFE-4FC7-8889-C363E91A64C6@cs.purdue.edu> Message-ID: Are you going to use trampolines? Runtime generated code? On the stack? I kind of hope not.There are advantages and disadvantages either way.Actually..hm..if LLVM makes it easy, well, then, that is a big advantage..given how much I have wrestled with this stuff... For example, try writing a nested function using gcc on MacOSX -- you get a warning/error and you have to throw an extra flag to enable nested functions. Another concern here is object code compatibility between the backends? Maybe?What I'm not generating isn't compatible, I'm afraid, and making it compatible might be difficult.It might work to generate C++ and use "this" for the static link. That might be compatible -- if static link and "this" coincide. There is evidence they do (NT/x86) but I haven't researched the various architectures. You know, a few times already I haven't been careful about mixing object code across backends, and I got crashes.. considering how static links work, not surprising.. - Jay From: hosking at cs.purdue.edu Date: Fri, 21 Sep 2012 09:50:21 -0400 To: jay.krell at cornell.edu CC: m3devel at elegosoft.com; antony.hosking at gmail.com Subject: Re: [M3devel] trampolines and uplevel locals declared after function starts.. I think we should leave the CG interfaces as they are already (for static links). I can see how to generate LLVM IR easily with things the way they are. And you are already working to it. I wasn?t suggesting that you use trampolines, though I think it would be easy enough to do. But I am going to use the LLVM nest approach to pass frame pointers. That way I?ll get the efficient native static link passing code. On Sep 21, 2012, at 1:03 AM, Jay K wrote: > Did you take a look at the LLVM IR I sent? T Sorry, I couldn't quickly make sense of it. :( I have to read up on LLVM or study your code more. (This is why I favor a C backend -- I'm already an expert and there is far more C expertise in the world than LLVM expertise..I think.. and other reasons like portability..) Mention of "trampolines" was worrisome though. That usually means "runtime generated code, often on the stack". True here? If not, nevermind If so: There is no good solution here, but I think runtime generated code is mostly a losing battle..at least on the stack. If you dedicate a little bit of special purpose platform-specific code to it, and you don't mind it being slow, and you deal with the lifetime management, then it becomes viable. e.g. on Windows, you use VirtualAlloc(MEM_EXECUTE). On other platforms you use mprotect I think. And/or mmap? mmap(PROT_EXEC)? But you end up allocating memory in large chunks, like at least 4K or 64K. (You can also write out little temporary .so/.dll files, but that is unnecessarily inefficient.) I've seen code that calls mprotect against the stack. Yuck. The stack is nonexecutable on purpose -- for security (assuming there is any C or C++ code in the process). If you read the libffi mailing list, you see they are constantly in this arms race. There is a slow steady trickle of problems making the libffi code executable. For Darwin/ARM they came up with a trick to avoid generating code, since the platform doesn't allow unsigned code to run. Pluses/minuses: runtime generated code: Producing the code is fast, on historical systems that don't make it difficult to execute memory, e.g. on the stack. Running the code is fast. Pointers to closures become compatible with C -- you can pass a pointer to a closure as a callback to or C++ and it works. Highly target-dependent. The unusual Modula-3 method: Also fast. Calling function pointers is different and larger and slower. C code cannot call function pointers to nested functions. That is the main downside. Only slightly target-dependent -- in its choice of closure marker. I think we should change the closure marker slightly -- its size should be target-dependent, it should only be 4 bytes on SPARC64, MIPS64, PPC64, Alpha, AMD64 -- so the alignment check can be skipped. And it should possibly be larger than 4 or 8 bytes on IA64. But someone needs to read up on all the various instruction encodings and verify that 4 or 8 0xFF bytes are really invalid and won't occur. But most likely if 4 bytes of 0xFF are a good marker on MIPS32, PPC32, SPARC32, I386, they are also probably a good marker on MIPS64, PPC64, SPARC64, AMD64. And Alpha. Another option is to use something like "jmp marker". i.e. a jump to an address that is used just be the marker. It might not be a constant though. Maybe it is relocated. But you want it to be the same across all dynamic linked code, actually. We might want to have calls through a function pointer go through a helper function, to keep it small. Hm.. I wonder..maybe a closure can be generated fairly portably actually. Maybe you just need one little wrapper per function signature. And most would really be the same. Let me think on this..hm..well..you could do it if you have a special static link register probably. I need to think about this more. Do "all" the calling conventions provide a special extra register for "static link"? And is that often used for C++ "this"? In that case, there is a way.. Ultimately, I should point out, the idea of passing a closure to C is actually very useful. One should be able to pass an "object method pointer". So some language construct or pragma might be nice there -- to force down the runtime generated code path. But usually the C function that wants a function pointer also takes a "void* context", so maybe not so needed. Or maybe folks would just use "libffi" for that. - Jay CC: m3devel at elegosoft.com From: antony.hosking at gmail.com Subject: Re: [M3devel] uplevel locals declared after function starts.. Date: Thu, 20 Sep 2012 19:38:27 -0400 To: jay.krell at cornell.edu Agreed. You need to backpatch the uplevel locals. I would accumulate all of them. Did you take a look at the LLVM IR I sent? That's how I plan to so it. Sent from my iPhone On Sep 20, 2012, at 19:18, Jay K wrote: We get uplevel locals declared while within a function.So I think I'll bite the bullet and make multiple passes now.Otherwise I build up the frame struct "too early".I need to see all the locals -- all the uplevels, early in a function. There is also a chance they don't all have unique names. I do NOT expect I should have separate frames/static_links per-scope,just per-function. I could put structs inside the frame, named after the line they starton or such.. that might be prettier and more readable, or not. The structs could then be unioned at some point -- parallel scopescan/should share storage. M3C.m3:PROCEDURE declare_local(...)BEGIN...IF u.in_proc THEN ExtraScope_Open(u); print(u, var.Declare() & " M3_INIT;"); <* ASSERT up_level = FALSE *> this fails ELSE IF up_level THEN u.current_proc.uplevels := TRUE; END; u.current_proc.locals.addhi(var); END; RETURN var;END declare_local; == package /Users/jay/dev2/cm3/m3-libs/m3tk-misc == ...new source -> compiling Args.m3 ****** runtime error:*** <*ASSERT*> failed.*** file "../src/M3C.m3", line 1778*** m3_backend => 1536m3cc (aka cm3cg) failed compiling: Args.mc I'm guessing the code is here: PROCEDURE Errors(h: Handle; indent: CARDINAL := 0): Text.T RAISES {}= BEGIN IF h.errors = 0 THEN <*FATAL Fatal*> BEGIN RAISE Fatal; END; ELSE VAR texts := NEW(REF ARRAY OF TEXT, h.errors * 2); (* allocates space for all the error messages + padding *) pos: CARDINAL := 0; padding := Fmt.Pad("", indent); fmt: Text.T; <*INLINE*> PROCEDURE Add(t: Text.T) RAISES {}= BEGIN texts[pos] := t; INC(pos) END Add; <*INLINE*> PROCEDURE PaddedAdd(t: Text.T) RAISES {}= BEGIN Add(padding); Add(t) END PaddedAdd; see how "texts" is both uplevel and "not at the start" of the function. This is going to take a few days to deal with. Compiler can compile itself, and a large swath of the system now.I didn't use the self-built compiler, but I will do that next. It probably works.Very good. - Jay -------------- next part -------------- An HTML attachment was scrubbed... URL: From hosking at cs.purdue.edu Fri Sep 21 16:40:44 2012 From: hosking at cs.purdue.edu (Antony Hosking) Date: Fri, 21 Sep 2012 10:40:44 -0400 Subject: [M3devel] trampolines and uplevel locals declared after function starts.. In-Reply-To: References: , , , , <0FF69FC1-6CFE-4FC7-8889-C363E91A64C6@cs.purdue.edu> Message-ID: Backend compatibility is not something we need to aim for. Different backends will generate different object code. I do plan to use the LLVM mechanisms to pass static links as they are the only way to do so. They use a trampoline to grab the static link for function pointers, but I won?t do that. I?ll compute the static link explicitly so that closures will be constructed in the usual way (triple comprising ?1, function pointer, static link). On Sep 21, 2012, at 10:27 AM, Jay K wrote: > Are you going to use trampolines? Runtime generated code? On the stack? I kind of hope not. > There are advantages and disadvantages either way. > Actually..hm..if LLVM makes it easy, well, then, that is a big advantage..given how much I have wrestled with this stuff... > > > For example, try writing a nested function using gcc on MacOSX -- you get a warning/error and you have to throw an extra flag to enable nested functions. > > > Another concern here is object code compatibility between the backends? Maybe? > What I'm not generating isn't compatible, I'm afraid, and making it compatible might be difficult. > It might work to generate C++ and use "this" for the static link. That might be compatible -- if static link and "this" coincide. There is evidence they do (NT/x86) but I haven't researched the various architectures. > > > You know, a few times already I haven't been careful about mixing object code across backends, and I got crashes.. considering how static links work, not surprising.. > > > > - Jay > From: hosking at cs.purdue.edu > Date: Fri, 21 Sep 2012 09:50:21 -0400 > To: jay.krell at cornell.edu > CC: m3devel at elegosoft.com; antony.hosking at gmail.com > Subject: Re: [M3devel] trampolines and uplevel locals declared after function starts.. > > I think we should leave the CG interfaces as they are already (for static links). I can see how to generate LLVM IR easily with things the way they are. And you are already working to it. I wasn?t suggesting that you use trampolines, though I think it would be easy enough to do. But I am going to use the LLVM nest approach to pass frame pointers. That way I?ll get the efficient native static link passing code. > > On Sep 21, 2012, at 1:03 AM, Jay K wrote: > > > Did you take a look at the LLVM IR I sent? T > > Sorry, I couldn't quickly make sense of it. :( > I have to read up on LLVM or study your code more. > (This is why I favor a C backend -- I'm already an expert and there is far more C expertise in the world than LLVM expertise..I think.. and other reasons like portability..) > > > Mention of "trampolines" was worrisome though. > That usually means "runtime generated code, often on the stack". True here? > > > If not, nevermind > If so: > > > > There is no good solution here, but I think runtime generated code is mostly a losing battle..at least on the stack. If you dedicate a little bit of special purpose platform-specific code to it, and you don't mind it being slow, and you deal with the lifetime management, then it becomes viable. > e.g. on Windows, you use VirtualAlloc(MEM_EXECUTE). > On other platforms you use mprotect I think. And/or mmap? mmap(PROT_EXEC)? > But you end up allocating memory in large chunks, like at least 4K or 64K. > (You can also write out little temporary .so/.dll files, but that is unnecessarily inefficient.) > > > I've seen code that calls mprotect against the stack. Yuck. > The stack is nonexecutable on purpose -- for security (assuming there is any C or C++ code in the process). > > > If you read the libffi mailing list, you see they are constantly in this arms race. > There is a slow steady trickle of problems making the libffi code executable. > For Darwin/ARM they came up with a trick to avoid generating code, since the platform doesn't allow unsigned code to run. > > > > Pluses/minuses: > > > runtime generated code: > Producing the code is fast, on historical systems that don't make it difficult to execute memory, e.g. on the stack. > Running the code is fast. > Pointers to closures become compatible with C -- you can pass a pointer to a closure as a callback to or C++ and it works. > Highly target-dependent. > > > The unusual Modula-3 method: > Also fast. > Calling function pointers is different and larger and slower. > C code cannot call function pointers to nested functions. That is the main downside. > Only slightly target-dependent -- in its choice of closure marker. > I think we should change the closure marker slightly -- its size should be target-dependent, it should only be 4 bytes on SPARC64, MIPS64, PPC64, Alpha, AMD64 -- so the alignment check can be skipped. And it should possibly be larger than 4 or 8 bytes on IA64. > But someone needs to read up on all the various instruction encodings and verify that 4 or 8 0xFF bytes are really invalid and won't occur. > But most likely if 4 bytes of 0xFF are a good marker on MIPS32, PPC32, SPARC32, I386, they are also probably a good marker on MIPS64, PPC64, SPARC64, AMD64. And Alpha. > Another option is to use something like "jmp marker". i.e. a jump to an address that is used just be the marker. It might not be a constant though. Maybe it is relocated. But you want it to be the same across all dynamic linked code, actually. > > > We might want to have calls through a function pointer go through a helper function, to keep it small. > > > > Hm.. I wonder..maybe a closure can be generated fairly portably actually. > Maybe you just need one little wrapper per function signature. And most would really be the same. > Let me think on this..hm..well..you could do it if you have a special static link register probably. I need to think about this more. Do "all" the calling conventions provide a special extra register for "static link"? And is that often used for C++ "this"? In that case, there is a way.. > > > > Ultimately, I should point out, the idea of passing a closure to C is actually very useful. > One should be able to pass an "object method pointer". > So some language construct or pragma might be nice there -- to force down the runtime generated code path. > But usually the C function that wants a function pointer also takes a "void* context", so maybe not so needed. > > > Or maybe folks would just use "libffi" for that. > > > > - Jay > > CC: m3devel at elegosoft.com > From: antony.hosking at gmail.com > Subject: Re: [M3devel] uplevel locals declared after function starts.. > Date: Thu, 20 Sep 2012 19:38:27 -0400 > To: jay.krell at cornell.edu > > Agreed. You need to backpatch the uplevel locals. I would accumulate all of them. Did you take a look at the LLVM IR I sent? That's how I plan to so it. > > Sent from my iPhone > > On Sep 20, 2012, at 19:18, Jay K wrote: > > We get uplevel locals declared while within a function. > So I think I'll bite the bullet and make multiple passes now. > Otherwise I build up the frame struct "too early". > I need to see all the locals -- all the uplevels, early in a function. > > > There is also a chance they don't all have unique names. > > > I do NOT expect I should have separate frames/static_links per-scope, > just per-function. > > > I could put structs inside the frame, named after the line they start > on or such.. that might be prettier and more readable, or not. > > > The structs could then be unioned at some point -- parallel scopes > can/should share storage. > > > M3C.m3: > PROCEDURE declare_local(...) > BEGIN > ... > IF u.in_proc THEN > ExtraScope_Open(u); > print(u, var.Declare() & " M3_INIT;"); > <* ASSERT up_level = FALSE *> this fails > ELSE > IF up_level THEN > u.current_proc.uplevels := TRUE; > END; > u.current_proc.locals.addhi(var); > END; > RETURN var; > END declare_local; > > > == package /Users/jay/dev2/cm3/m3-libs/m3tk-misc == > > ... > new source -> compiling Args.m3 > > > *** > *** runtime error: > *** <*ASSERT*> failed. > *** file "../src/M3C.m3", line 1778 > *** > > m3_backend => 1536 > m3cc (aka cm3cg) failed compiling: Args.mc > > > I'm guessing the code is here: > > > PROCEDURE Errors(h: Handle; indent: CARDINAL := 0): Text.T RAISES {}= > BEGIN > IF h.errors = 0 THEN > <*FATAL Fatal*> BEGIN RAISE Fatal; END; > ELSE > > VAR > texts := NEW(REF ARRAY OF TEXT, h.errors * 2); > (* allocates space for all the error messages + padding *) > pos: CARDINAL := 0; > padding := Fmt.Pad("", indent); > fmt: Text.T; > > <*INLINE*> PROCEDURE Add(t: Text.T) RAISES {}= > BEGIN texts[pos] := t; INC(pos) END Add; > <*INLINE*> PROCEDURE PaddedAdd(t: Text.T) RAISES {}= > BEGIN Add(padding); Add(t) END PaddedAdd; > > > > see how "texts" is both uplevel and "not at the start" of the function. > > > This is going to take a few days to deal with. > > > Compiler can compile itself, and a large swath of the system now. > I didn't use the self-built compiler, but I will do that next. It probably works. > Very good. > > > - Jay -------------- next part -------------- An HTML attachment was scrubbed... URL: From jay.krell at cornell.edu Sat Sep 22 20:00:36 2012 From: jay.krell at cornell.edu (Jay K) Date: Sat, 22 Sep 2012 18:00:36 +0000 Subject: [M3devel] m3cg shift value/count types Message-ID: M3CG_Ops.i3: shift (t: IType); (* s1.t := Word.Shift (s1.t, s0.t); pop *)rotate (t: IType); (* s1.t := Word.Rotate (s1.t, s0.t); pop *) This doesn't seem right to me. s0 is signed.s1 is not I have it implemented as: #define m3_shift_T(T) static T m3_shift_##T(T value,INTEGER shift)... where T is UINT32 or UINT64. "shift" can vary..I'll look at the frontend... - Jay -------------- next part -------------- An HTML attachment was scrubbed... URL: From jay.krell at cornell.edu Sat Sep 22 20:11:44 2012 From: jay.krell at cornell.edu (Jay K) Date: Sat, 22 Sep 2012 18:11:44 +0000 Subject: [M3devel] why MOD 10000 in line number for exception handlers? Message-ID: m3front/stmts/TryFinStmt.m3 forigin : INTEGER; ... last_name : INTEGER := 0; next_uid : INTEGER := 0;... PROCEDURE HandlerName (uid: INTEGER): TEXT = CONST Insert = ARRAY BOOLEAN OF TEXT { "_M3_LINE_", "_I3_LINE_" }; BEGIN RETURN M3ID.ToText (Module.Name (NIL)) & Insert [Module.IsInterface ()] & Fmt.Int (uid); END HandlerName; PROCEDURE Check (p: P; VAR cs: Stmt.CheckState) = VAR zz: Scope.T; oc: Stmt.Outcomes; name: INTEGER; BEGIN... p.viaProc := TRUE; name := p.forigin MOD 10000; p.handler.name := HandlerName (name); IF (name = last_name) THEN INC (next_uid); p.handler.name := p.handler.name & "_" & Fmt.Int (next_uid); ELSE last_name := name; next_uid := 0; END; So the names of exception handlers are usuallythe module name, followed by _M3_LINE_ or _I3_LINE_ followedby a line number. BUT the line number is taken MOD 10000and, something like, if the line number occasionally clashes,we append another number... Why? Now, I can see that multiple lines can have the same name: TRY TRY EXCEPT EXCEPTon one line. and the code should have a comment like that. But why the MOD 10000? Is that in case INTEGER is 16 bits??To keep the lengths of the names bounded?? I suggest the code look more like: p.viaProc := TRUE; name := p.forigin; p.handler.name := HandlerName (name); (* Handle the case of multiple exception handlers on the same line. * "TRY TRY EXCEPT EXCEPT" by appending _1, _2 to the second, third, * etc. handlers. *) IF (name = last_name) THEN INC (next_uid); p.handler.name := p.handler.name & "_" & Fmt.Int (next_uid); ELSE last_name := name; next_uid := 0; END; At first I didn't think of multiple exception handlers on the same line.But now that I thought of that, my real agenda is wrong -- to eliminatethe second number entirely. For now I'm stuck recognizing these patterns in my backend, becauseother oddities on the frontend (that I'm still convinced are a bug). I'd also be willing to append _0 or _1 for the first exception handler on a line,for more consistency, at the cost of more noise for the overwhelmingly common case.You know..if there were always two numbers, it would have saved me time...since I coded at first to recognize just one number, then later hit a problem when two occured. - Jay -------------- next part -------------- An HTML attachment was scrubbed... URL: From jay.krell at cornell.edu Sat Sep 22 20:28:14 2012 From: jay.krell at cornell.edu (Jay K) Date: Sat, 22 Sep 2012 18:28:14 +0000 Subject: [M3devel] m3cg shift value/count types In-Reply-To: References: Message-ID: It looks like what I have (shown) is correct.The shift count is always an INTEGER.32bit targets have: Shift(Word32, Int32); Shift(Word64, Int32); 64bit targets have:Shift(Word32, Int64); Shift(Word64, Int64); I might have something wrong where I didn't show.The M3CG_Ops.i3 comment is wrong.The type of the value to shift and the count are never the same. The only place the frontend uses this is builtinWord/Shift.mg.Everywhere else, when I looked quickly, is explicit ShiftLeft or ShiftRight.For those the count is unsigned.Oh. Those look wrong too.The front end uses an integer-based subrange for the parameter: m3front/builtinWord/Shift.mg:PROCEDURE Initialize (r: INTEGER) =... sub := SubrangeType.New (TInt.Zero, max, Int.T, FALSE); So it is: 32bit targets:ShiftLeft or Right(Word32, Word32); ShiftLeft or Right(Word64, Word32); 64bit targets:ShiftLeft or Right(Word32, Word64); ShiftLeft or Right(Word64, Word64); which also doesn't agree with M3CG_Ops.i3. Possibly "Rep" should abstract out the shift count type and not just the value to shift.Perhaps it should be: 32bit and 64 bit targets:ShiftLeft or Right(Word32, Word32); ShiftLeft or Right(Word64, Word64); and perhaps it should be: 32bit:Shift(Word32, Int32); Shift(Word64, Int64); 64bit:Shift(Word32, Int64); Shift(Word64, Int64); there are arguments for various combinations and what we have isn't crazy.It just disagrees with comments in M3CG_Ops.i3. The shift count doesn't really need to be widened to match the value. If this were C with its prevalent "int", shift could remain just 32 bits always. (or even 16) But Modula-3 favors INTEGER/ptrdiff_t and widening even when 32bits is plenty. - Jay From: jay.krell at cornell.edu To: m3devel at elegosoft.com Date: Sat, 22 Sep 2012 18:00:36 +0000 Subject: [M3devel] m3cg shift value/count types M3CG_Ops.i3: shift (t: IType); (* s1.t := Word.Shift (s1.t, s0.t); pop *)rotate (t: IType); (* s1.t := Word.Rotate (s1.t, s0.t); pop *) This doesn't seem right to me. s0 is signed.s1 is not I have it implemented as: #define m3_shift_T(T) static T m3_shift_##T(T value,INTEGER shift)... where T is UINT32 or UINT64. "shift" can vary..I'll look at the frontend... - Jay -------------- next part -------------- An HTML attachment was scrubbed... URL: From jay.krell at cornell.edu Sat Sep 22 20:39:23 2012 From: jay.krell at cornell.edu (Jay K) Date: Sat, 22 Sep 2012 18:39:23 +0000 Subject: [M3devel] m3cg shift value/count types In-Reply-To: References: , Message-ID: Correction, I don't think 64bit targets have: Shift(Word32, Int64); ShiftLeft or Right(Word32, Word64); And historically, without LONGINT the differences were smaller, it was: 32bit:Shift(Word32, Int32); ShiftLeft or Right(Word32, Word32); 64bit:Shift(Word64, Int64); ShiftLeft or Right(Word64, Word64); The differences were only in signed-ness, not size.And, oh, I might have the input-signedness to shift_left/right wrong here. Anyway, I'll likely adjust the comments in M3CG_Ops.i3 and my code in M3C.m3.And maybe review the other backends.There isn't any sort of runtime stack imbalance implied by these mixed up sizes.I'm not sure the sign mixups matter or not.I'd have to do some experiments. Certainly I'm more nervous about signedness mixups now.I had this code, which is very wrong: #define m3_shift_T(T) static T m3_shift_##T(T value,INTEGER shift){if((shift>=(sizeof(T)*8))||(shift<=-(sizeof(T)*8)))... shift is signedsizeof is unsignedshift got treated as unsignedsmall negative numbers got treated as large positive numbersshifting by, e.g. -1, resulted in 0, instead of a right shift by 1. - Jay From: jay.krell at cornell.edu To: m3devel at elegosoft.com Date: Sat, 22 Sep 2012 18:28:14 +0000 Subject: Re: [M3devel] m3cg shift value/count types It looks like what I have (shown) is correct.The shift count is always an INTEGER.32bit targets have: Shift(Word32, Int32); Shift(Word64, Int32); 64bit targets have:Shift(Word32, Int64); Shift(Word64, Int64); I might have something wrong where I didn't show.The M3CG_Ops.i3 comment is wrong.The type of the value to shift and the count are never the same. The only place the frontend uses this is builtinWord/Shift.mg.Everywhere else, when I looked quickly, is explicit ShiftLeft or ShiftRight.For those the count is unsigned.Oh. Those look wrong too.The front end uses an integer-based subrange for the parameter: m3front/builtinWord/Shift.mg:PROCEDURE Initialize (r: INTEGER) =... sub := SubrangeType.New (TInt.Zero, max, Int.T, FALSE); So it is: 32bit targets:ShiftLeft or Right(Word32, Word32); ShiftLeft or Right(Word64, Word32); 64bit targets:ShiftLeft or Right(Word32, Word64); ShiftLeft or Right(Word64, Word64); which also doesn't agree with M3CG_Ops.i3. Possibly "Rep" should abstract out the shift count type and not just the value to shift.Perhaps it should be: 32bit and 64 bit targets:ShiftLeft or Right(Word32, Word32); ShiftLeft or Right(Word64, Word64); and perhaps it should be: 32bit:Shift(Word32, Int32); Shift(Word64, Int64); 64bit:Shift(Word32, Int64); Shift(Word64, Int64); there are arguments for various combinations and what we have isn't crazy.It just disagrees with comments in M3CG_Ops.i3. The shift count doesn't really need to be widened to match the value. If this were C with its prevalent "int", shift could remain just 32 bits always. (or even 16) But Modula-3 favors INTEGER/ptrdiff_t and widening even when 32bits is plenty. - Jay From: jay.krell at cornell.edu To: m3devel at elegosoft.com Date: Sat, 22 Sep 2012 18:00:36 +0000 Subject: [M3devel] m3cg shift value/count types M3CG_Ops.i3: shift (t: IType); (* s1.t := Word.Shift (s1.t, s0.t); pop *)rotate (t: IType); (* s1.t := Word.Rotate (s1.t, s0.t); pop *) This doesn't seem right to me. s0 is signed.s1 is not I have it implemented as: #define m3_shift_T(T) static T m3_shift_##T(T value,INTEGER shift)... where T is UINT32 or UINT64. "shift" can vary..I'll look at the frontend... - Jay -------------- next part -------------- An HTML attachment was scrubbed... URL: From jay.krell at cornell.edu Sun Sep 23 02:13:58 2012 From: jay.krell at cornell.edu (Jay K) Date: Sun, 23 Sep 2012 00:13:58 +0000 Subject: [M3devel] type of count to m3cg.copy_n is signed? Message-ID: I'm just rereading M3C.m3, cleaning stuff up. I'm looking at copy_n. It takes a type to copy and a count of that type, on the stack.I have to multiply by the byte size of the type and call memcpy or memmove. I'm curious how to handle the count, and converting it for the multiplication and pass of to memcpy/memmove.I would rather like to assume it is always Target.Word.cg_type. The only pass the frontend calls copy_n is here: cg.copy_n (Target.Integer.cg_type, t, overlap); Is that really intended? Am I supposed to output a runtime check that the value is positive? Similarly nearby in the frontend, in Copy_n: cg.div (Target.Integer.cg_type, Sign.Positive, Sign.Positive); Might as well that be Target.Word.cg_type? (My meta-point is I still believe signed types over used, both in a lot of C code and definitely in Modula-3.And CARDINAL doesn't really cut it -- unsigned types shouldn't have their range cut in half..) - Jay -------------- next part -------------- An HTML attachment was scrubbed... URL: From jay.krell at cornell.edu Tue Sep 25 08:18:03 2012 From: jay.krell at cornell.edu (Jay K) Date: Tue, 25 Sep 2012 06:18:03 +0000 Subject: [M3devel] 32bit limits Message-ID: m3cg should use Target.Int or LONGINT a bunch more...The size of a struct.The number of elements in an array.The number of fields in a struct.The number of elements in an enum.etc. - Jay -------------- next part -------------- An HTML attachment was scrubbed... URL: From rodney_bates at lcwb.coop Wed Sep 26 05:23:44 2012 From: rodney_bates at lcwb.coop (Rodney M. Bates) Date: Tue, 25 Sep 2012 22:23:44 -0500 Subject: [M3devel] m3cg shift value/count types In-Reply-To: References: , Message-ID: <50627540.1090307@lcwb.coop> Signed and unsigned integers are inherently confusing and have no easy linguistic solution that doesn't involve tradeoffs. Modula-3 and C have significantly different mechanisms. Correctly translating the former into the latter inevitably is going to require generating some not-so-pretty code. The C and Modula-2 way is to have distinct signed and unsigned types. Usually, the unsigned type is full-range. The builtin operators are overloaded and in general, have different definitions when applied to a signed vs. an unsigned type. Type conversions, implicit or explicit, must be done for an operator to have mixed signed/unsigned operands. The Modula-3 way is to have only a (normally) signed INTEGER type, but different operators with different names, that apply either a signed or unsigned interpretation to the bits of this one type. All the builtins that syntactically use operator notation ('+', etc.) are unconditionally signed. The only unsigned operators are (pseudo-) functions in Word.i3. Note that Word.T = INTEGER. Having on occasions done very careful mixed signed/unsigned code in both Modula-2 and Modula-3, I like the Modula-3 way a bit better. It doesn't really make a lot of difference in how hard you have to think about the signedness of every operand and operator, but it does at least greatly simplify the definition of the language's rules and the difficulty of understanding and remembering them. Compared to Modula-2 (where any signedness type conversions must be explicit), Modula-3 does make it easier to go into denial and ignore the problem. Since C will apply the conversions implicitly, it makes it just as easy to deny, while requiring a lot more semantic rules. So translating Modula-3 to C involves changing the way signed/unsigned operators are done. I don't think there is any way to get it right other than to translate all types into C signed types and explicitly cast every value to/from the corresponding unsigned type exactly when the translation of an operation from Word is applied. (Well, making everything unsigned would work, but generate far more frequent ugly C code.) I suppose a set of macros for the unsigned operators might make for prettier C code. C's casts are inconsistent about when they are true type conversions (defined by a mapping between the abstract values of the two types) and the equivalent of LOOPHOLE (defined by just reinterpreting the same bits via a different set of representation rules). For translating operators in Word, you need a LOOPHOLE equivalent. Fortunately, as I read Harbison and Steele, C's casts in this case can pretty well be depended on to have this meaning. So then back-end shift operators, since only Word has source language equivalents for them, really should always treat the to-be-shifted operand as unsigned, despite the fact that the operand has the back- end equivalent of a signed type. This should be true in any back-end, not just a C-generating one. I suppose this could require explicit casts in the M3CG representation, but that is exactly the pedantic way output from a front-end should be. On 09/22/2012 01:39 PM, Jay K wrote: > Correction, I don't think 64bit targets have: > > Shift(Word32, Int64); > ShiftLeft or Right(Word32, Word64); > > > And historically, without LONGINT the differences were smaller, it was: > > 32bit: > Shift(Word32, Int32); > ShiftLeft or Right(Word32, Word32); > > 64bit: > Shift(Word64, Int64); > ShiftLeft or Right(Word64, Word64); > > The differences were only in signed-ness, not size. > And, oh, I might have the input-signedness to shift_left/right wrong here. > > > Anyway, I'll likely adjust the comments in M3CG_Ops.i3 and my code in M3C.m3. > And maybe review the other backends. > There isn't any sort of runtime stack imbalance implied by these mixed up sizes. > I'm not sure the sign mixups matter or not. > I'd have to do some experiments. > > Certainly I'm more nervous about signedness mixups now. > I had this code, which is very wrong: > > > #define m3_shift_T(T) static T m3_shift_##T(T value,INTEGER shift) > {if((shift>=(sizeof(T)*8))||(shift<=-(sizeof(T)*8)))... > > > shift is signed > sizeof is unsigned > shift got treated as unsigned > small negative numbers got treated as large positive numbers > shifting by, e.g. -1, resulted in 0, instead of a right shift by 1. > > > - Jay > > > > ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -- > From: jay.krell at cornell.edu > To: m3devel at elegosoft.com > Date: Sat, 22 Sep 2012 18:28:14 +0000 > Subject: Re: [M3devel] m3cg shift value/count types > > It looks like what I have (shown) is correct. > The shift count is always an INTEGER. > 32bit targets have: > > > Shift(Word32, Int32); > Shift(Word64, Int32); > > > 64bit targets have: > Shift(Word32, Int64); > Shift(Word64, Int64); > > > I might have something wrong where I didn't show. > The M3CG_Ops.i3 comment is wrong. > The type of the value to shift and the count are never the same. > > > The only place the frontend uses this is builtinWord/Shift.mg. > Everywhere else, when I looked quickly, is explicit ShiftLeft or ShiftRight. > For those the count is unsigned. > Oh. Those look wrong too. > The front end uses an integer-based subrange for the parameter: > > m3front/builtinWord/Shift.mg: > PROCEDURE Initialize (r: INTEGER) = > ... > sub := SubrangeType.New (TInt.Zero, max, Int.T, FALSE); > > > So it is: > > > 32bit targets: > ShiftLeft or Right(Word32, Word32); > ShiftLeft or Right(Word64, Word32); > > > 64bit targets: > ShiftLeft or Right(Word32, Word64); > ShiftLeft or Right(Word64, Word64); > > > which also doesn't agree with M3CG_Ops.i3. > > > Possibly "Rep" should abstract out the shift count type and not just the value to shift. > Perhaps it should be: > > 32bit and 64 bit targets: > ShiftLeft or Right(Word32, Word32); > ShiftLeft or Right(Word64, Word64); > > and perhaps it should be: > > 32bit: > Shift(Word32, Int32); > Shift(Word64, Int64); > > > 64bit: > Shift(Word32, Int64); > Shift(Word64, Int64); > > > there are arguments for various combinations and what we have isn't crazy. > It just disagrees with comments in M3CG_Ops.i3. > The shift count doesn't really need to be widened to match the value. > If this were C with its prevalent "int", shift could remain just 32 bits always. (or even 16) > But Modula-3 favors INTEGER/ptrdiff_t and widening even when 32bits is plenty. > > > > - Jay > > ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -- > From: jay.krell at cornell.edu > To: m3devel at elegosoft.com > Date: Sat, 22 Sep 2012 18:00:36 +0000 > Subject: [M3devel] m3cg shift value/count types > > M3CG_Ops.i3: > > shift (t: IType); (* s1.t := Word.Shift (s1.t, s0.t); pop *) > rotate (t: IType); (* s1.t := Word.Rotate (s1.t, s0.t); pop *) > > > This doesn't seem right to me. > > s0 is signed. > s1 is not > > I have it implemented as: > > #define m3_shift_T(T) static T m3_shift_##T(T value,INTEGER shift)... > > where T is UINT32 or UINT64. > > "shift" can vary..I'll look at the frontend... > > - Jay From jay.krell at cornell.edu Wed Sep 26 10:11:00 2012 From: jay.krell at cornell.edu (Jay K) Date: Wed, 26 Sep 2012 08:11:00 +0000 Subject: [M3devel] M3CG_Ops.Public vs. M3CG.T Message-ID: M3CG_Ops.i3: child: M3CG.T := NIL;(* The default methods simply call the corresponding method in 'child', hence a vanilla 'M3CG.T' can be used as a filter where you override only the methods of interest. *) 1) I am not keen on fixing this, but I feel this was clearly a mistake. M3CG_Ops.Public should have been "purely abstract" with no defaultimplementation.M3CG_Filter.T or somesuch could have been as described. 2) I am fixing:M3CG.T is overused.Most uses should be M3CG_Ops.Public.It is ok to derive from -- though that was a mistake.But functions that take or return M3CG.T should really betaking and returning M3CG_Ops.Public. - Jay -------------- next part -------------- An HTML attachment was scrubbed... URL: From hosking at cs.purdue.edu Wed Sep 26 16:42:26 2012 From: hosking at cs.purdue.edu (Antony Hosking) Date: Wed, 26 Sep 2012 10:42:26 -0400 Subject: [M3devel] M3CG_Ops.Public vs. M3CG.T In-Reply-To: References: Message-ID: I disagree. M3CG.T is more abstract than M3CG_Ops. The revelation of M3CG.T <: M3CG_Ops.Public is in M3CG_Ops. If you want the ops you simply import that interface to get the revelation. Please don?t make pervasive changes in interfaces that some of us are developing against. On Sep 26, 2012, at 4:11 AM, Jay K wrote: > M3CG_Ops.i3: > > > child: M3CG.T := NIL; > (* The default methods simply call the corresponding method in 'child', > hence a vanilla 'M3CG.T' can be used as a filter where you override > only the methods of interest. *) > > 1) > > I am not keen on fixing this, but I feel this was clearly a mistake. > > M3CG_Ops.Public should have been "purely abstract" with no default > implementation. > M3CG_Filter.T or somesuch could have been as described. > > > 2) I am fixing: > M3CG.T is overused. > Most uses should be M3CG_Ops.Public. > It is ok to derive from -- though that was a mistake. > But functions that take or return M3CG.T should really be > taking and returning M3CG_Ops.Public. > > > - Jay > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From jay.krell at cornell.edu Wed Sep 26 17:36:34 2012 From: jay.krell at cornell.edu (Jay K) Date: Wed, 26 Sep 2012 15:36:34 +0000 Subject: [M3devel] M3CG_Ops.Public vs. M3CG.T In-Reply-To: References: , Message-ID: It is not pervasive.It is like one line in about six files. M3CG.T => M3CG_Ops.Publics. I guess you are saying that M3CG.T is merely the extremely abstract ROOT, where M3CG_Ops.Public has a bunch of methods? Then I might argue that M3CG.T is overly abstract -- it is like void* instead of pointer just with a bunch of methods. This isn't quite right, doesn't compilte, but rougly: Index: M3CG_BinRd.i3===================================================================RCS file: /usr/cvs/cm3/m3-sys/m3middle/src/M3CG_BinRd.i3,vretrieving revision 1.2diff -u -r1.2 M3CG_BinRd.i3--- M3CG_BinRd.i3 12 Feb 2001 15:25:47 -0000 1.2+++ M3CG_BinRd.i3 26 Sep 2012 15:34:32 -0000@@ -3,9 +3,9 @@ INTERFACE M3CG_BinRd; -IMPORT M3CG, Rd;+IMPORT M3CG_Ops, Rd; -PROCEDURE Inhale (rd: Rd.T; cg: M3CG.T);+PROCEDURE Inhale (rd: Rd.T; cg: M3CG_Ops.Public); (* Parse the binary intermediate code M3CG calls from 'rd' and call 'cg' to implement them. *) Index: M3CG_BinRd.m3===================================================================RCS file: /usr/cvs/cm3/m3-sys/m3middle/src/M3CG_BinRd.m3,vretrieving revision 1.19diff -u -r1.19 M3CG_BinRd.m3--- M3CG_BinRd.m3 4 Sep 2012 14:29:54 -0000 1.19+++ M3CG_BinRd.m3 26 Sep 2012 15:34:32 -0000@@ -20,7 +20,7 @@ TYPE State = RECORD rd : Rd.T;- cg : M3CG.T;+ cg : M3CG_Ops.Public; buf : InputBuffer; buf_len: CARDINAL; buf_ptr: CARDINAL;@@ -200,7 +200,7 @@ Cmd {Bop.fetch_and_xor, fetch_and_xor} }; -PROCEDURE Inhale (rd: Rd.T; cg: M3CG.T) =+PROCEDURE Inhale (rd: Rd.T; cg: M3CG_Ops.Public) = VAR s: State; op: M3CG.Name; cmd: INTEGER; BEGIN s.rd := rd;Index: M3CG_BinWr.i3===================================================================RCS file: /usr/cvs/cm3/m3-sys/m3middle/src/M3CG_BinWr.i3,vretrieving revision 1.2diff -u -r1.2 M3CG_BinWr.i3--- M3CG_BinWr.i3 12 Feb 2001 15:25:47 -0000 1.2+++ M3CG_BinWr.i3 26 Sep 2012 15:34:32 -0000@@ -3,9 +3,9 @@ INTERFACE M3CG_BinWr; -IMPORT M3CG, Wr;+IMPORT M3CG_Ops, Wr; -PROCEDURE New (wr: Wr.T): M3CG.T;+PROCEDURE New (wr: Wr.T): M3CG_Ops.Public; (* returns a fresh, initialized code generator that writes its calls as binary intermediate code on 'wr'. See M3CG_Binary for the binary format. *)Index: M3CG_BinWr.m3===================================================================RCS file: /usr/cvs/cm3/m3-sys/m3middle/src/M3CG_BinWr.m3,vretrieving revision 1.23diff -u -r1.23 M3CG_BinWr.m3--- M3CG_BinWr.m3 4 Sep 2012 15:20:09 -0000 1.23+++ M3CG_BinWr.m3 26 Sep 2012 15:34:32 -0000@@ -27,7 +27,7 @@ END; TYPE- U = M3CG.T OBJECT+ U = M3CG_Ops.Public OBJECT wr : Wr.T := NIL; buf : M3Buf.T := NIL; buf_len : INTEGER := 0;@@ -375,7 +375,7 @@ (*---------------------------------------------------------------------------*) -PROCEDURE New (output: Wr.T): M3CG.T =+PROCEDURE New (output: Wr.T): M3CG_Ops.Public = VAR mbuf := M3Buf.New (); BEGIN M3Buf.AttachDrain (mbuf, output);Index: M3CG_Check.i3===================================================================RCS file: /usr/cvs/cm3/m3-sys/m3middle/src/M3CG_Check.i3,vretrieving revision 1.1.1.1diff -u -r1.1.1.1 M3CG_Check.i3--- M3CG_Check.i3 14 Jan 2001 13:40:37 -0000 1.1.1.1+++ M3CG_Check.i3 26 Sep 2012 15:34:32 -0000@@ -7,11 +7,11 @@ INTERFACE M3CG_Check; -IMPORT M3CG;+IMPORT M3CG_Ops; -PROCEDURE New (child: M3CG.T;+PROCEDURE New (child: M3CG_Ops.Public; clean_jumps, clean_stores: BOOLEAN;- nested_calls, nested_procs: BOOLEAN): M3CG.T;+ nested_calls, nested_procs: BOOLEAN): M3CG_Ops.Public; (* returns a fresh, initialized code generator that passes its calls to 'child' and checks that the stream obeys the M3CG restrictions. If 'clean_jumps', it also checks that the stack is empty at everyIndex: M3CG_Check.m3===================================================================RCS file: /usr/cvs/cm3/m3-sys/m3middle/src/M3CG_Check.m3,vretrieving revision 1.17diff -u -r1.17 M3CG_Check.m3--- M3CG_Check.m3 4 Sep 2012 14:47:43 -0000 1.17+++ M3CG_Check.m3 26 Sep 2012 15:34:33 -0000@@ -32,7 +32,7 @@ }; TYPE- U = M3CG.T OBJECT+ U = M3CG_Ops.Public OBJECT clean_stores := FALSE; clean_jumps := FALSE; nested_calls := TRUE;===================================================================RCS file: /usr/cvs/cm3/m3-sys/m3middle/src/M3CG_Ops.i3,vretrieving revision 1.12diff -u -r1.12 M3CG_Ops.i3--- M3CG_Ops.i3 16 Aug 2012 13:12:35 -0000 1.12+++ M3CG_Ops.i3 26 Sep 2012 15:34:33 -0000@@ -30,7 +30,7 @@ Public = OBJECT (*------------------------------------------------ READONLY configuration ---*) -child: M3CG.T := NIL;+child: Public := NIL; (* The default methods simply call the corresponding method in 'child', hence a vanilla 'M3CG.T' can be used as a filter where you override only the methods of interest. *)Index: M3CG_Rd.i3===================================================================RCS file: /usr/cvs/cm3/m3-sys/m3middle/src/M3CG_Rd.i3,vretrieving revision 1.1.1.1diff -u -r1.1.1.1 M3CG_Rd.i3--- M3CG_Rd.i3 14 Jan 2001 13:40:37 -0000 1.1.1.1+++ M3CG_Rd.i3 26 Sep 2012 15:34:33 -0000@@ -7,9 +7,9 @@ INTERFACE M3CG_Rd; -IMPORT M3CG, Rd;+IMPORT M3CG_Ops, Rd; -PROCEDURE Inhale (rd: Rd.T; cg: M3CG.T);+PROCEDURE Inhale (rd: Rd.T; cg: M3CG_Ops.Public); (* Parse the M3CG calls from 'rd' and call 'cg' to implement them. *) END M3CG_Rd.Index: M3CG_Rd.m3===================================================================RCS file: /usr/cvs/cm3/m3-sys/m3middle/src/M3CG_Rd.m3,vretrieving revision 1.15diff -u -r1.15 M3CG_Rd.m3--- M3CG_Rd.m3 4 Sep 2012 14:52:46 -0000 1.15+++ M3CG_Rd.m3 26 Sep 2012 15:34:33 -0000@@ -22,7 +22,7 @@ TYPE State = RECORD rd : Rd.T;- cg : M3CG.T;+ cg : M3CG_Ops.Public; ch : CHAR; (* current scan character *) buf : InputBuffer; buf_len: CARDINAL;@@ -206,7 +206,7 @@ cmds: IntIntTbl.T := NIL; types: IntIntTbl.T := NIL; -PROCEDURE Inhale (rd: Rd.T; cg: M3CG.T) =+PROCEDURE Inhale (rd: Rd.T; cg: M3CG_Ops.Public) = VAR s: State; op: M3CG.Name; cmd: INTEGER; BEGIN s.rd := rd;Index: M3CG_Wr.i3===================================================================RCS file: /usr/cvs/cm3/m3-sys/m3middle/src/M3CG_Wr.i3,vretrieving revision 1.1.1.1diff -u -r1.1.1.1 M3CG_Wr.i3--- M3CG_Wr.i3 14 Jan 2001 13:40:37 -0000 1.1.1.1+++ M3CG_Wr.i3 26 Sep 2012 15:34:33 -0000@@ -7,9 +7,9 @@ INTERFACE M3CG_Wr; -IMPORT M3CG, Wr;+IMPORT M3CG_Ops, Wr; -PROCEDURE New (wr: Wr.T): M3CG.T;+PROCEDURE New (wr: Wr.T): M3CG_Ops.Public; (* returns a fresh, initialized code generator that writes its calls as readable ASCII on 'wr'. *) Index: M3CG_Wr.m3===================================================================RCS file: /usr/cvs/cm3/m3-sys/m3middle/src/M3CG_Wr.m3,vretrieving revision 1.18diff -u -r1.18 M3CG_Wr.m3--- M3CG_Wr.m3 22 Aug 2012 14:15:40 -0000 1.18+++ M3CG_Wr.m3 26 Sep 2012 15:34:33 -0000@@ -27,7 +27,7 @@ END; TYPE- U = M3CG.T OBJECT+ U = M3CG_Ops.Public OBJECT wr : Wr.T := NIL; buf : M3Buf.T := NIL; buf_len : INTEGER := 0;@@ -375,7 +375,7 @@ (*---------------------------------------------------------------------------*) -PROCEDURE New (output: Wr.T): M3CG.T =+PROCEDURE New (output: Wr.T): M3CG_Ops.Public = VAR mbuf := M3Buf.New (); BEGIN M3Buf.AttachDrain (mbuf, output);Index: Target.i3=================================================================== - Jay From: hosking at cs.purdue.edu Date: Wed, 26 Sep 2012 10:42:26 -0400 To: jay.krell at cornell.edu CC: m3devel at elegosoft.com Subject: Re: [M3devel] M3CG_Ops.Public vs. M3CG.T I disagree. M3CG.T is more abstract than M3CG_Ops. The revelation of M3CG.T <: M3CG_Ops.Public is in M3CG_Ops. If you want the ops you simply import that interface to get the revelation. Please don?t make pervasive changes in interfaces that some of us are developing against. On Sep 26, 2012, at 4:11 AM, Jay K wrote:M3CG_Ops.i3: child: M3CG.T := NIL;(* The default methods simply call the corresponding method in 'child', hence a vanilla 'M3CG.T' can be used as a filter where you override only the methods of interest. *) 1) I am not keen on fixing this, but I feel this was clearly a mistake. M3CG_Ops.Public should have been "purely abstract" with no defaultimplementation.M3CG_Filter.T or somesuch could have been as described. 2) I am fixing:M3CG.T is overused.Most uses should be M3CG_Ops.Public.It is ok to derive from -- though that was a mistake.But functions that take or return M3CG.T should really betaking and returning M3CG_Ops.Public. - Jay -------------- next part -------------- An HTML attachment was scrubbed... URL: From hosking at cs.purdue.edu Wed Sep 26 17:58:01 2012 From: hosking at cs.purdue.edu (Antony Hosking) Date: Wed, 26 Sep 2012 11:58:01 -0400 Subject: [M3devel] M3CG_Ops.Public vs. M3CG.T In-Reply-To: References: , Message-ID: Yes, M3CG.T is the most abstract type. Please don?t make this change. On Sep 26, 2012, at 11:36 AM, Jay K wrote: > It is not pervasive. > It is like one line in about six files. M3CG.T => M3CG_Ops.Publics. > > > I guess you are saying that M3CG.T is merely the extremely abstract ROOT, where M3CG_Ops.Public has a bunch of methods? Then I might argue that M3CG.T is overly abstract -- it is like void* instead of pointer just with a bunch of methods. > > > This isn't quite right, doesn't compilte, but rougly: > > Index: M3CG_BinRd.i3 > =================================================================== > RCS file: /usr/cvs/cm3/m3-sys/m3middle/src/M3CG_BinRd.i3,v > retrieving revision 1.2 > diff -u -r1.2 M3CG_BinRd.i3 > --- M3CG_BinRd.i3 12 Feb 2001 15:25:47 -0000 1.2 > +++ M3CG_BinRd.i3 26 Sep 2012 15:34:32 -0000 > @@ -3,9 +3,9 @@ > > INTERFACE M3CG_BinRd; > > -IMPORT M3CG, Rd; > +IMPORT M3CG_Ops, Rd; > > -PROCEDURE Inhale (rd: Rd.T; cg: M3CG.T); > +PROCEDURE Inhale (rd: Rd.T; cg: M3CG_Ops.Public); > (* Parse the binary intermediate code M3CG calls from 'rd' > and call 'cg' to implement them. *) > > Index: M3CG_BinRd.m3 > =================================================================== > RCS file: /usr/cvs/cm3/m3-sys/m3middle/src/M3CG_BinRd.m3,v > retrieving revision 1.19 > diff -u -r1.19 M3CG_BinRd.m3 > --- M3CG_BinRd.m3 4 Sep 2012 14:29:54 -0000 1.19 > +++ M3CG_BinRd.m3 26 Sep 2012 15:34:32 -0000 > @@ -20,7 +20,7 @@ > TYPE > State = RECORD > rd : Rd.T; > - cg : M3CG.T; > + cg : M3CG_Ops.Public; > buf : InputBuffer; > buf_len: CARDINAL; > buf_ptr: CARDINAL; > @@ -200,7 +200,7 @@ > Cmd {Bop.fetch_and_xor, fetch_and_xor} > }; > > -PROCEDURE Inhale (rd: Rd.T; cg: M3CG.T) = > +PROCEDURE Inhale (rd: Rd.T; cg: M3CG_Ops.Public) = > VAR s: State; op: M3CG.Name; cmd: INTEGER; > BEGIN > s.rd := rd; > Index: M3CG_BinWr.i3 > =================================================================== > RCS file: /usr/cvs/cm3/m3-sys/m3middle/src/M3CG_BinWr.i3,v > retrieving revision 1.2 > diff -u -r1.2 M3CG_BinWr.i3 > --- M3CG_BinWr.i3 12 Feb 2001 15:25:47 -0000 1.2 > +++ M3CG_BinWr.i3 26 Sep 2012 15:34:32 -0000 > @@ -3,9 +3,9 @@ > > INTERFACE M3CG_BinWr; > > -IMPORT M3CG, Wr; > +IMPORT M3CG_Ops, Wr; > > -PROCEDURE New (wr: Wr.T): M3CG.T; > +PROCEDURE New (wr: Wr.T): M3CG_Ops.Public; > (* returns a fresh, initialized code generator that writes its > calls as binary intermediate code on 'wr'. See M3CG_Binary > for the binary format. *) > Index: M3CG_BinWr.m3 > =================================================================== > RCS file: /usr/cvs/cm3/m3-sys/m3middle/src/M3CG_BinWr.m3,v > retrieving revision 1.23 > diff -u -r1.23 M3CG_BinWr.m3 > --- M3CG_BinWr.m3 4 Sep 2012 15:20:09 -0000 1.23 > +++ M3CG_BinWr.m3 26 Sep 2012 15:34:32 -0000 > @@ -27,7 +27,7 @@ > END; > > TYPE > - U = M3CG.T OBJECT > + U = M3CG_Ops.Public OBJECT > wr : Wr.T := NIL; > buf : M3Buf.T := NIL; > buf_len : INTEGER := 0; > @@ -375,7 +375,7 @@ > > (*---------------------------------------------------------------------------*) > > -PROCEDURE New (output: Wr.T): M3CG.T = > +PROCEDURE New (output: Wr.T): M3CG_Ops.Public = > VAR mbuf := M3Buf.New (); > BEGIN > M3Buf.AttachDrain (mbuf, output); > Index: M3CG_Check.i3 > =================================================================== > RCS file: /usr/cvs/cm3/m3-sys/m3middle/src/M3CG_Check.i3,v > retrieving revision 1.1.1.1 > diff -u -r1.1.1.1 M3CG_Check.i3 > --- M3CG_Check.i3 14 Jan 2001 13:40:37 -0000 1.1.1.1 > +++ M3CG_Check.i3 26 Sep 2012 15:34:32 -0000 > @@ -7,11 +7,11 @@ > > INTERFACE M3CG_Check; > > -IMPORT M3CG; > +IMPORT M3CG_Ops; > > -PROCEDURE New (child: M3CG.T; > +PROCEDURE New (child: M3CG_Ops.Public; > clean_jumps, clean_stores: BOOLEAN; > - nested_calls, nested_procs: BOOLEAN): M3CG.T; > + nested_calls, nested_procs: BOOLEAN): M3CG_Ops.Public; > (* returns a fresh, initialized code generator that passes its calls > to 'child' and checks that the stream obeys the M3CG restrictions. > If 'clean_jumps', it also checks that the stack is empty at every > Index: M3CG_Check.m3 > =================================================================== > RCS file: /usr/cvs/cm3/m3-sys/m3middle/src/M3CG_Check.m3,v > retrieving revision 1.17 > diff -u -r1.17 M3CG_Check.m3 > --- M3CG_Check.m3 4 Sep 2012 14:47:43 -0000 1.17 > +++ M3CG_Check.m3 26 Sep 2012 15:34:33 -0000 > @@ -32,7 +32,7 @@ > }; > > TYPE > - U = M3CG.T OBJECT > + U = M3CG_Ops.Public OBJECT > clean_stores := FALSE; > clean_jumps := FALSE; > nested_calls := TRUE; > =================================================================== > RCS file: /usr/cvs/cm3/m3-sys/m3middle/src/M3CG_Ops.i3,v > retrieving revision 1.12 > diff -u -r1.12 M3CG_Ops.i3 > --- M3CG_Ops.i3 16 Aug 2012 13:12:35 -0000 1.12 > +++ M3CG_Ops.i3 26 Sep 2012 15:34:33 -0000 > @@ -30,7 +30,7 @@ > Public = OBJECT > (*------------------------------------------------ READONLY configuration ---*) > > -child: M3CG.T := NIL; > +child: Public := NIL; > (* The default methods simply call the corresponding method in 'child', > hence a vanilla 'M3CG.T' can be used as a filter where you override > only the methods of interest. *) > Index: M3CG_Rd.i3 > =================================================================== > RCS file: /usr/cvs/cm3/m3-sys/m3middle/src/M3CG_Rd.i3,v > retrieving revision 1.1.1.1 > diff -u -r1.1.1.1 M3CG_Rd.i3 > --- M3CG_Rd.i3 14 Jan 2001 13:40:37 -0000 1.1.1.1 > +++ M3CG_Rd.i3 26 Sep 2012 15:34:33 -0000 > @@ -7,9 +7,9 @@ > > INTERFACE M3CG_Rd; > > -IMPORT M3CG, Rd; > +IMPORT M3CG_Ops, Rd; > > -PROCEDURE Inhale (rd: Rd.T; cg: M3CG.T); > +PROCEDURE Inhale (rd: Rd.T; cg: M3CG_Ops.Public); > (* Parse the M3CG calls from 'rd' and call 'cg' to implement them. *) > > END M3CG_Rd. > Index: M3CG_Rd.m3 > =================================================================== > RCS file: /usr/cvs/cm3/m3-sys/m3middle/src/M3CG_Rd.m3,v > retrieving revision 1.15 > diff -u -r1.15 M3CG_Rd.m3 > --- M3CG_Rd.m3 4 Sep 2012 14:52:46 -0000 1.15 > +++ M3CG_Rd.m3 26 Sep 2012 15:34:33 -0000 > @@ -22,7 +22,7 @@ > TYPE > State = RECORD > rd : Rd.T; > - cg : M3CG.T; > + cg : M3CG_Ops.Public; > ch : CHAR; (* current scan character *) > buf : InputBuffer; > buf_len: CARDINAL; > @@ -206,7 +206,7 @@ > cmds: IntIntTbl.T := NIL; > types: IntIntTbl.T := NIL; > > -PROCEDURE Inhale (rd: Rd.T; cg: M3CG.T) = > +PROCEDURE Inhale (rd: Rd.T; cg: M3CG_Ops.Public) = > VAR s: State; op: M3CG.Name; cmd: INTEGER; > BEGIN > s.rd := rd; > Index: M3CG_Wr.i3 > =================================================================== > RCS file: /usr/cvs/cm3/m3-sys/m3middle/src/M3CG_Wr.i3,v > retrieving revision 1.1.1.1 > diff -u -r1.1.1.1 M3CG_Wr.i3 > --- M3CG_Wr.i3 14 Jan 2001 13:40:37 -0000 1.1.1.1 > +++ M3CG_Wr.i3 26 Sep 2012 15:34:33 -0000 > @@ -7,9 +7,9 @@ > > INTERFACE M3CG_Wr; > > -IMPORT M3CG, Wr; > +IMPORT M3CG_Ops, Wr; > > -PROCEDURE New (wr: Wr.T): M3CG.T; > +PROCEDURE New (wr: Wr.T): M3CG_Ops.Public; > (* returns a fresh, initialized code generator that writes its > calls as readable ASCII on 'wr'. *) > > Index: M3CG_Wr.m3 > =================================================================== > RCS file: /usr/cvs/cm3/m3-sys/m3middle/src/M3CG_Wr.m3,v > retrieving revision 1.18 > diff -u -r1.18 M3CG_Wr.m3 > --- M3CG_Wr.m3 22 Aug 2012 14:15:40 -0000 1.18 > +++ M3CG_Wr.m3 26 Sep 2012 15:34:33 -0000 > @@ -27,7 +27,7 @@ > END; > > TYPE > - U = M3CG.T OBJECT > + U = M3CG_Ops.Public OBJECT > wr : Wr.T := NIL; > buf : M3Buf.T := NIL; > buf_len : INTEGER := 0; > @@ -375,7 +375,7 @@ > > (*---------------------------------------------------------------------------*) > > -PROCEDURE New (output: Wr.T): M3CG.T = > +PROCEDURE New (output: Wr.T): M3CG_Ops.Public = > VAR mbuf := M3Buf.New (); > BEGIN > M3Buf.AttachDrain (mbuf, output); > Index: Target.i3 > =================================================================== > > > - Jay > > From: hosking at cs.purdue.edu > Date: Wed, 26 Sep 2012 10:42:26 -0400 > To: jay.krell at cornell.edu > CC: m3devel at elegosoft.com > Subject: Re: [M3devel] M3CG_Ops.Public vs. M3CG.T > > I disagree. M3CG.T is more abstract than M3CG_Ops. The revelation of M3CG.T <: M3CG_Ops.Public is in M3CG_Ops. If you want the ops you simply import that interface to get the revelation. Please don?t make pervasive changes in interfaces that some of us are developing against. > > On Sep 26, 2012, at 4:11 AM, Jay K wrote: > > M3CG_Ops.i3: > > > child: M3CG.T := NIL; > (* The default methods simply call the corresponding method in 'child', > hence a vanilla 'M3CG.T' can be used as a filter where you override > only the methods of interest. *) > > 1) > > I am not keen on fixing this, but I feel this was clearly a mistake. > > M3CG_Ops.Public should have been "purely abstract" with no default > implementation. > M3CG_Filter.T or somesuch could have been as described. > > > 2) I am fixing: > M3CG.T is overused. > Most uses should be M3CG_Ops.Public. > It is ok to derive from -- though that was a mistake. > But functions that take or return M3CG.T should really be > taking and returning M3CG_Ops.Public. > > > - Jay -------------- next part -------------- An HTML attachment was scrubbed... URL: From jay.krell at cornell.edu Wed Sep 26 21:30:12 2012 From: jay.krell at cornell.edu (Jay) Date: Wed, 26 Sep 2012 12:30:12 -0700 Subject: [M3devel] M3CG_Ops.Public vs. M3CG.T In-Reply-To: References: Message-ID: Ok but this seems not great.. - Jay (briefly/pocket-sized-computer-aka-phone) On Sep 26, 2012, at 8:58 AM, Antony Hosking wrote: > Yes, M3CG.T is the most abstract type. > Please don?t make this change. > > On Sep 26, 2012, at 11:36 AM, Jay K wrote: > >> It is not pervasive. >> It is like one line in about six files. M3CG.T => M3CG_Ops.Publics. >> >> >> I guess you are saying that M3CG.T is merely the extremely abstract ROOT, where M3CG_Ops.Public has a bunch of methods? Then I might argue that M3CG.T is overly abstract -- it is like void* instead of pointer just with a bunch of methods. >> >> >> This isn't quite right, doesn't compilte, but rougly: >> >> Index: M3CG_BinRd.i3 >> =================================================================== >> RCS file: /usr/cvs/cm3/m3-sys/m3middle/src/M3CG_BinRd.i3,v >> retrieving revision 1.2 >> diff -u -r1.2 M3CG_BinRd.i3 >> --- M3CG_BinRd.i3 12 Feb 2001 15:25:47 -0000 1.2 >> +++ M3CG_BinRd.i3 26 Sep 2012 15:34:32 -0000 >> @@ -3,9 +3,9 @@ >> >> INTERFACE M3CG_BinRd; >> >> -IMPORT M3CG, Rd; >> +IMPORT M3CG_Ops, Rd; >> >> -PROCEDURE Inhale (rd: Rd.T; cg: M3CG.T); >> +PROCEDURE Inhale (rd: Rd.T; cg: M3CG_Ops.Public); >> (* Parse the binary intermediate code M3CG calls from 'rd' >> and call 'cg' to implement them. *) >> >> Index: M3CG_BinRd.m3 >> =================================================================== >> RCS file: /usr/cvs/cm3/m3-sys/m3middle/src/M3CG_BinRd.m3,v >> retrieving revision 1.19 >> diff -u -r1.19 M3CG_BinRd.m3 >> --- M3CG_BinRd.m3 4 Sep 2012 14:29:54 -0000 1.19 >> +++ M3CG_BinRd.m3 26 Sep 2012 15:34:32 -0000 >> @@ -20,7 +20,7 @@ >> TYPE >> State = RECORD >> rd : Rd.T; >> - cg : M3CG.T; >> + cg : M3CG_Ops.Public; >> buf : InputBuffer; >> buf_len: CARDINAL; >> buf_ptr: CARDINAL; >> @@ -200,7 +200,7 @@ >> Cmd {Bop.fetch_and_xor, fetch_and_xor} >> }; >> >> -PROCEDURE Inhale (rd: Rd.T; cg: M3CG.T) = >> +PROCEDURE Inhale (rd: Rd.T; cg: M3CG_Ops.Public) = >> VAR s: State; op: M3CG.Name; cmd: INTEGER; >> BEGIN >> s.rd := rd; >> Index: M3CG_BinWr.i3 >> =================================================================== >> RCS file: /usr/cvs/cm3/m3-sys/m3middle/src/M3CG_BinWr.i3,v >> retrieving revision 1.2 >> diff -u -r1.2 M3CG_BinWr.i3 >> --- M3CG_BinWr.i3 12 Feb 2001 15:25:47 -0000 1.2 >> +++ M3CG_BinWr.i3 26 Sep 2012 15:34:32 -0000 >> @@ -3,9 +3,9 @@ >> >> INTERFACE M3CG_BinWr; >> >> -IMPORT M3CG, Wr; >> +IMPORT M3CG_Ops, Wr; >> >> -PROCEDURE New (wr: Wr.T): M3CG.T; >> +PROCEDURE New (wr: Wr.T): M3CG_Ops.Public; >> (* returns a fresh, initialized code generator that writes its >> calls as binary intermediate code on 'wr'. See M3CG_Binary >> for the binary format. *) >> Index: M3CG_BinWr.m3 >> =================================================================== >> RCS file: /usr/cvs/cm3/m3-sys/m3middle/src/M3CG_BinWr.m3,v >> retrieving revision 1.23 >> diff -u -r1.23 M3CG_BinWr.m3 >> --- M3CG_BinWr.m3 4 Sep 2012 15:20:09 -0000 1.23 >> +++ M3CG_BinWr.m3 26 Sep 2012 15:34:32 -0000 >> @@ -27,7 +27,7 @@ >> END; >> >> TYPE >> - U = M3CG.T OBJECT >> + U = M3CG_Ops.Public OBJECT >> wr : Wr.T := NIL; >> buf : M3Buf.T := NIL; >> buf_len : INTEGER := 0; >> @@ -375,7 +375,7 @@ >> >> (*---------------------------------------------------------------------------*) >> >> -PROCEDURE New (output: Wr.T): M3CG.T = >> +PROCEDURE New (output: Wr.T): M3CG_Ops.Public = >> VAR mbuf := M3Buf.New (); >> BEGIN >> M3Buf.AttachDrain (mbuf, output); >> Index: M3CG_Check.i3 >> =================================================================== >> RCS file: /usr/cvs/cm3/m3-sys/m3middle/src/M3CG_Check.i3,v >> retrieving revision 1.1.1.1 >> diff -u -r1.1.1.1 M3CG_Check.i3 >> --- M3CG_Check.i3 14 Jan 2001 13:40:37 -0000 1.1.1.1 >> +++ M3CG_Check.i3 26 Sep 2012 15:34:32 -0000 >> @@ -7,11 +7,11 @@ >> >> INTERFACE M3CG_Check; >> >> -IMPORT M3CG; >> +IMPORT M3CG_Ops; >> >> -PROCEDURE New (child: M3CG.T; >> +PROCEDURE New (child: M3CG_Ops.Public; >> clean_jumps, clean_stores: BOOLEAN; >> - nested_calls, nested_procs: BOOLEAN): M3CG.T; >> + nested_calls, nested_procs: BOOLEAN): M3CG_Ops.Public; >> (* returns a fresh, initialized code generator that passes its calls >> to 'child' and checks that the stream obeys the M3CG restrictions. >> If 'clean_jumps', it also checks that the stack is empty at every >> Index: M3CG_Check.m3 >> =================================================================== >> RCS file: /usr/cvs/cm3/m3-sys/m3middle/src/M3CG_Check.m3,v >> retrieving revision 1.17 >> diff -u -r1.17 M3CG_Check.m3 >> --- M3CG_Check.m3 4 Sep 2012 14:47:43 -0000 1.17 >> +++ M3CG_Check.m3 26 Sep 2012 15:34:33 -0000 >> @@ -32,7 +32,7 @@ >> }; >> >> TYPE >> - U = M3CG.T OBJECT >> + U = M3CG_Ops.Public OBJECT >> clean_stores := FALSE; >> clean_jumps := FALSE; >> nested_calls := TRUE; >> =================================================================== >> RCS file: /usr/cvs/cm3/m3-sys/m3middle/src/M3CG_Ops.i3,v >> retrieving revision 1.12 >> diff -u -r1.12 M3CG_Ops.i3 >> --- M3CG_Ops.i3 16 Aug 2012 13:12:35 -0000 1.12 >> +++ M3CG_Ops.i3 26 Sep 2012 15:34:33 -0000 >> @@ -30,7 +30,7 @@ >> Public = OBJECT >> (*------------------------------------------------ READONLY configuration ---*) >> >> -child: M3CG.T := NIL; >> +child: Public := NIL; >> (* The default methods simply call the corresponding method in 'child', >> hence a vanilla 'M3CG.T' can be used as a filter where you override >> only the methods of interest. *) >> Index: M3CG_Rd.i3 >> =================================================================== >> RCS file: /usr/cvs/cm3/m3-sys/m3middle/src/M3CG_Rd.i3,v >> retrieving revision 1.1.1.1 >> diff -u -r1.1.1.1 M3CG_Rd.i3 >> --- M3CG_Rd.i3 14 Jan 2001 13:40:37 -0000 1.1.1.1 >> +++ M3CG_Rd.i3 26 Sep 2012 15:34:33 -0000 >> @@ -7,9 +7,9 @@ >> >> INTERFACE M3CG_Rd; >> >> -IMPORT M3CG, Rd; >> +IMPORT M3CG_Ops, Rd; >> >> -PROCEDURE Inhale (rd: Rd.T; cg: M3CG.T); >> +PROCEDURE Inhale (rd: Rd.T; cg: M3CG_Ops.Public); >> (* Parse the M3CG calls from 'rd' and call 'cg' to implement them. *) >> >> END M3CG_Rd. >> Index: M3CG_Rd.m3 >> =================================================================== >> RCS file: /usr/cvs/cm3/m3-sys/m3middle/src/M3CG_Rd.m3,v >> retrieving revision 1.15 >> diff -u -r1.15 M3CG_Rd.m3 >> --- M3CG_Rd.m3 4 Sep 2012 14:52:46 -0000 1.15 >> +++ M3CG_Rd.m3 26 Sep 2012 15:34:33 -0000 >> @@ -22,7 +22,7 @@ >> TYPE >> State = RECORD >> rd : Rd.T; >> - cg : M3CG.T; >> + cg : M3CG_Ops.Public; >> ch : CHAR; (* current scan character *) >> buf : InputBuffer; >> buf_len: CARDINAL; >> @@ -206,7 +206,7 @@ >> cmds: IntIntTbl.T := NIL; >> types: IntIntTbl.T := NIL; >> >> -PROCEDURE Inhale (rd: Rd.T; cg: M3CG.T) = >> +PROCEDURE Inhale (rd: Rd.T; cg: M3CG_Ops.Public) = >> VAR s: State; op: M3CG.Name; cmd: INTEGER; >> BEGIN >> s.rd := rd; >> Index: M3CG_Wr.i3 >> =================================================================== >> RCS file: /usr/cvs/cm3/m3-sys/m3middle/src/M3CG_Wr.i3,v >> retrieving revision 1.1.1.1 >> diff -u -r1.1.1.1 M3CG_Wr.i3 >> --- M3CG_Wr.i3 14 Jan 2001 13:40:37 -0000 1.1.1.1 >> +++ M3CG_Wr.i3 26 Sep 2012 15:34:33 -0000 >> @@ -7,9 +7,9 @@ >> >> INTERFACE M3CG_Wr; >> >> -IMPORT M3CG, Wr; >> +IMPORT M3CG_Ops, Wr; >> >> -PROCEDURE New (wr: Wr.T): M3CG.T; >> +PROCEDURE New (wr: Wr.T): M3CG_Ops.Public; >> (* returns a fresh, initialized code generator that writes its >> calls as readable ASCII on 'wr'. *) >> >> Index: M3CG_Wr.m3 >> =================================================================== >> RCS file: /usr/cvs/cm3/m3-sys/m3middle/src/M3CG_Wr.m3,v >> retrieving revision 1.18 >> diff -u -r1.18 M3CG_Wr.m3 >> --- M3CG_Wr.m3 22 Aug 2012 14:15:40 -0000 1.18 >> +++ M3CG_Wr.m3 26 Sep 2012 15:34:33 -0000 >> @@ -27,7 +27,7 @@ >> END; >> >> TYPE >> - U = M3CG.T OBJECT >> + U = M3CG_Ops.Public OBJECT >> wr : Wr.T := NIL; >> buf : M3Buf.T := NIL; >> buf_len : INTEGER := 0; >> @@ -375,7 +375,7 @@ >> >> (*---------------------------------------------------------------------------*) >> >> -PROCEDURE New (output: Wr.T): M3CG.T = >> +PROCEDURE New (output: Wr.T): M3CG_Ops.Public = >> VAR mbuf := M3Buf.New (); >> BEGIN >> M3Buf.AttachDrain (mbuf, output); >> Index: Target.i3 >> =================================================================== >> >> >> - Jay >> >> From: hosking at cs.purdue.edu >> Date: Wed, 26 Sep 2012 10:42:26 -0400 >> To: jay.krell at cornell.edu >> CC: m3devel at elegosoft.com >> Subject: Re: [M3devel] M3CG_Ops.Public vs. M3CG.T >> >> I disagree. M3CG.T is more abstract than M3CG_Ops. The revelation of M3CG.T <: M3CG_Ops.Public is in M3CG_Ops. If you want the ops you simply import that interface to get the revelation. Please don?t make pervasive changes in interfaces that some of us are developing against. >> >> On Sep 26, 2012, at 4:11 AM, Jay K wrote: >> >> M3CG_Ops.i3: >> >> >> child: M3CG.T := NIL; >> (* The default methods simply call the corresponding method in 'child', >> hence a vanilla 'M3CG.T' can be used as a filter where you override >> only the methods of interest. *) >> >> 1) >> >> I am not keen on fixing this, but I feel this was clearly a mistake. >> >> M3CG_Ops.Public should have been "purely abstract" with no default >> implementation. >> M3CG_Filter.T or somesuch could have been as described. >> >> >> 2) I am fixing: >> M3CG.T is overused. >> Most uses should be M3CG_Ops.Public. >> It is ok to derive from -- though that was a mistake. >> But functions that take or return M3CG.T should really be >> taking and returning M3CG_Ops.Public. >> >> >> - Jay > -------------- next part -------------- An HTML attachment was scrubbed... URL: From hosking at cs.purdue.edu Wed Sep 26 21:53:26 2012 From: hosking at cs.purdue.edu (Antony Hosking) Date: Wed, 26 Sep 2012 15:53:26 -0400 Subject: [M3devel] M3CG_Ops.Public vs. M3CG.T In-Reply-To: References: Message-ID: <93DDAC8D-8917-4558-B99A-A99C3F767F42@cs.purdue.edu> Are you saying that you don?t like importing M3CG as well as M3CG_Ops? On Sep 26, 2012, at 3:30 PM, Jay wrote: > Ok but this seems not great.. > > - Jay (briefly/pocket-sized-computer-aka-phone) > > On Sep 26, 2012, at 8:58 AM, Antony Hosking wrote: > >> Yes, M3CG.T is the most abstract type. >> Please don?t make this change. >> >> On Sep 26, 2012, at 11:36 AM, Jay K wrote: >> >>> It is not pervasive. >>> It is like one line in about six files. M3CG.T => M3CG_Ops.Publics. >>> >>> >>> I guess you are saying that M3CG.T is merely the extremely abstract ROOT, where M3CG_Ops.Public has a bunch of methods? Then I might argue that M3CG.T is overly abstract -- it is like void* instead of pointer just with a bunch of methods. >>> >>> >>> This isn't quite right, doesn't compilte, but rougly: >>> >>> Index: M3CG_BinRd.i3 >>> =================================================================== >>> RCS file: /usr/cvs/cm3/m3-sys/m3middle/src/M3CG_BinRd.i3,v >>> retrieving revision 1.2 >>> diff -u -r1.2 M3CG_BinRd.i3 >>> --- M3CG_BinRd.i3 12 Feb 2001 15:25:47 -0000 1.2 >>> +++ M3CG_BinRd.i3 26 Sep 2012 15:34:32 -0000 >>> @@ -3,9 +3,9 @@ >>> >>> INTERFACE M3CG_BinRd; >>> >>> -IMPORT M3CG, Rd; >>> +IMPORT M3CG_Ops, Rd; >>> >>> -PROCEDURE Inhale (rd: Rd.T; cg: M3CG.T); >>> +PROCEDURE Inhale (rd: Rd.T; cg: M3CG_Ops.Public); >>> (* Parse the binary intermediate code M3CG calls from 'rd' >>> and call 'cg' to implement them. *) >>> >>> Index: M3CG_BinRd.m3 >>> =================================================================== >>> RCS file: /usr/cvs/cm3/m3-sys/m3middle/src/M3CG_BinRd.m3,v >>> retrieving revision 1.19 >>> diff -u -r1.19 M3CG_BinRd.m3 >>> --- M3CG_BinRd.m3 4 Sep 2012 14:29:54 -0000 1.19 >>> +++ M3CG_BinRd.m3 26 Sep 2012 15:34:32 -0000 >>> @@ -20,7 +20,7 @@ >>> TYPE >>> State = RECORD >>> rd : Rd.T; >>> - cg : M3CG.T; >>> + cg : M3CG_Ops.Public; >>> buf : InputBuffer; >>> buf_len: CARDINAL; >>> buf_ptr: CARDINAL; >>> @@ -200,7 +200,7 @@ >>> Cmd {Bop.fetch_and_xor, fetch_and_xor} >>> }; >>> >>> -PROCEDURE Inhale (rd: Rd.T; cg: M3CG.T) = >>> +PROCEDURE Inhale (rd: Rd.T; cg: M3CG_Ops.Public) = >>> VAR s: State; op: M3CG.Name; cmd: INTEGER; >>> BEGIN >>> s.rd := rd; >>> Index: M3CG_BinWr.i3 >>> =================================================================== >>> RCS file: /usr/cvs/cm3/m3-sys/m3middle/src/M3CG_BinWr.i3,v >>> retrieving revision 1.2 >>> diff -u -r1.2 M3CG_BinWr.i3 >>> --- M3CG_BinWr.i3 12 Feb 2001 15:25:47 -0000 1.2 >>> +++ M3CG_BinWr.i3 26 Sep 2012 15:34:32 -0000 >>> @@ -3,9 +3,9 @@ >>> >>> INTERFACE M3CG_BinWr; >>> >>> -IMPORT M3CG, Wr; >>> +IMPORT M3CG_Ops, Wr; >>> >>> -PROCEDURE New (wr: Wr.T): M3CG.T; >>> +PROCEDURE New (wr: Wr.T): M3CG_Ops.Public; >>> (* returns a fresh, initialized code generator that writes its >>> calls as binary intermediate code on 'wr'. See M3CG_Binary >>> for the binary format. *) >>> Index: M3CG_BinWr.m3 >>> =================================================================== >>> RCS file: /usr/cvs/cm3/m3-sys/m3middle/src/M3CG_BinWr.m3,v >>> retrieving revision 1.23 >>> diff -u -r1.23 M3CG_BinWr.m3 >>> --- M3CG_BinWr.m3 4 Sep 2012 15:20:09 -0000 1.23 >>> +++ M3CG_BinWr.m3 26 Sep 2012 15:34:32 -0000 >>> @@ -27,7 +27,7 @@ >>> END; >>> >>> TYPE >>> - U = M3CG.T OBJECT >>> + U = M3CG_Ops.Public OBJECT >>> wr : Wr.T := NIL; >>> buf : M3Buf.T := NIL; >>> buf_len : INTEGER := 0; >>> @@ -375,7 +375,7 @@ >>> >>> (*---------------------------------------------------------------------------*) >>> >>> -PROCEDURE New (output: Wr.T): M3CG.T = >>> +PROCEDURE New (output: Wr.T): M3CG_Ops.Public = >>> VAR mbuf := M3Buf.New (); >>> BEGIN >>> M3Buf.AttachDrain (mbuf, output); >>> Index: M3CG_Check.i3 >>> =================================================================== >>> RCS file: /usr/cvs/cm3/m3-sys/m3middle/src/M3CG_Check.i3,v >>> retrieving revision 1.1.1.1 >>> diff -u -r1.1.1.1 M3CG_Check.i3 >>> --- M3CG_Check.i3 14 Jan 2001 13:40:37 -0000 1.1.1.1 >>> +++ M3CG_Check.i3 26 Sep 2012 15:34:32 -0000 >>> @@ -7,11 +7,11 @@ >>> >>> INTERFACE M3CG_Check; >>> >>> -IMPORT M3CG; >>> +IMPORT M3CG_Ops; >>> >>> -PROCEDURE New (child: M3CG.T; >>> +PROCEDURE New (child: M3CG_Ops.Public; >>> clean_jumps, clean_stores: BOOLEAN; >>> - nested_calls, nested_procs: BOOLEAN): M3CG.T; >>> + nested_calls, nested_procs: BOOLEAN): M3CG_Ops.Public; >>> (* returns a fresh, initialized code generator that passes its calls >>> to 'child' and checks that the stream obeys the M3CG restrictions. >>> If 'clean_jumps', it also checks that the stack is empty at every >>> Index: M3CG_Check.m3 >>> =================================================================== >>> RCS file: /usr/cvs/cm3/m3-sys/m3middle/src/M3CG_Check.m3,v >>> retrieving revision 1.17 >>> diff -u -r1.17 M3CG_Check.m3 >>> --- M3CG_Check.m3 4 Sep 2012 14:47:43 -0000 1.17 >>> +++ M3CG_Check.m3 26 Sep 2012 15:34:33 -0000 >>> @@ -32,7 +32,7 @@ >>> }; >>> >>> TYPE >>> - U = M3CG.T OBJECT >>> + U = M3CG_Ops.Public OBJECT >>> clean_stores := FALSE; >>> clean_jumps := FALSE; >>> nested_calls := TRUE; >>> =================================================================== >>> RCS file: /usr/cvs/cm3/m3-sys/m3middle/src/M3CG_Ops.i3,v >>> retrieving revision 1.12 >>> diff -u -r1.12 M3CG_Ops.i3 >>> --- M3CG_Ops.i3 16 Aug 2012 13:12:35 -0000 1.12 >>> +++ M3CG_Ops.i3 26 Sep 2012 15:34:33 -0000 >>> @@ -30,7 +30,7 @@ >>> Public = OBJECT >>> (*------------------------------------------------ READONLY configuration ---*) >>> >>> -child: M3CG.T := NIL; >>> +child: Public := NIL; >>> (* The default methods simply call the corresponding method in 'child', >>> hence a vanilla 'M3CG.T' can be used as a filter where you override >>> only the methods of interest. *) >>> Index: M3CG_Rd.i3 >>> =================================================================== >>> RCS file: /usr/cvs/cm3/m3-sys/m3middle/src/M3CG_Rd.i3,v >>> retrieving revision 1.1.1.1 >>> diff -u -r1.1.1.1 M3CG_Rd.i3 >>> --- M3CG_Rd.i3 14 Jan 2001 13:40:37 -0000 1.1.1.1 >>> +++ M3CG_Rd.i3 26 Sep 2012 15:34:33 -0000 >>> @@ -7,9 +7,9 @@ >>> >>> INTERFACE M3CG_Rd; >>> >>> -IMPORT M3CG, Rd; >>> +IMPORT M3CG_Ops, Rd; >>> >>> -PROCEDURE Inhale (rd: Rd.T; cg: M3CG.T); >>> +PROCEDURE Inhale (rd: Rd.T; cg: M3CG_Ops.Public); >>> (* Parse the M3CG calls from 'rd' and call 'cg' to implement them. *) >>> >>> END M3CG_Rd. >>> Index: M3CG_Rd.m3 >>> =================================================================== >>> RCS file: /usr/cvs/cm3/m3-sys/m3middle/src/M3CG_Rd.m3,v >>> retrieving revision 1.15 >>> diff -u -r1.15 M3CG_Rd.m3 >>> --- M3CG_Rd.m3 4 Sep 2012 14:52:46 -0000 1.15 >>> +++ M3CG_Rd.m3 26 Sep 2012 15:34:33 -0000 >>> @@ -22,7 +22,7 @@ >>> TYPE >>> State = RECORD >>> rd : Rd.T; >>> - cg : M3CG.T; >>> + cg : M3CG_Ops.Public; >>> ch : CHAR; (* current scan character *) >>> buf : InputBuffer; >>> buf_len: CARDINAL; >>> @@ -206,7 +206,7 @@ >>> cmds: IntIntTbl.T := NIL; >>> types: IntIntTbl.T := NIL; >>> >>> -PROCEDURE Inhale (rd: Rd.T; cg: M3CG.T) = >>> +PROCEDURE Inhale (rd: Rd.T; cg: M3CG_Ops.Public) = >>> VAR s: State; op: M3CG.Name; cmd: INTEGER; >>> BEGIN >>> s.rd := rd; >>> Index: M3CG_Wr.i3 >>> =================================================================== >>> RCS file: /usr/cvs/cm3/m3-sys/m3middle/src/M3CG_Wr.i3,v >>> retrieving revision 1.1.1.1 >>> diff -u -r1.1.1.1 M3CG_Wr.i3 >>> --- M3CG_Wr.i3 14 Jan 2001 13:40:37 -0000 1.1.1.1 >>> +++ M3CG_Wr.i3 26 Sep 2012 15:34:33 -0000 >>> @@ -7,9 +7,9 @@ >>> >>> INTERFACE M3CG_Wr; >>> >>> -IMPORT M3CG, Wr; >>> +IMPORT M3CG_Ops, Wr; >>> >>> -PROCEDURE New (wr: Wr.T): M3CG.T; >>> +PROCEDURE New (wr: Wr.T): M3CG_Ops.Public; >>> (* returns a fresh, initialized code generator that writes its >>> calls as readable ASCII on 'wr'. *) >>> >>> Index: M3CG_Wr.m3 >>> =================================================================== >>> RCS file: /usr/cvs/cm3/m3-sys/m3middle/src/M3CG_Wr.m3,v >>> retrieving revision 1.18 >>> diff -u -r1.18 M3CG_Wr.m3 >>> --- M3CG_Wr.m3 22 Aug 2012 14:15:40 -0000 1.18 >>> +++ M3CG_Wr.m3 26 Sep 2012 15:34:33 -0000 >>> @@ -27,7 +27,7 @@ >>> END; >>> >>> TYPE >>> - U = M3CG.T OBJECT >>> + U = M3CG_Ops.Public OBJECT >>> wr : Wr.T := NIL; >>> buf : M3Buf.T := NIL; >>> buf_len : INTEGER := 0; >>> @@ -375,7 +375,7 @@ >>> >>> (*---------------------------------------------------------------------------*) >>> >>> -PROCEDURE New (output: Wr.T): M3CG.T = >>> +PROCEDURE New (output: Wr.T): M3CG_Ops.Public = >>> VAR mbuf := M3Buf.New (); >>> BEGIN >>> M3Buf.AttachDrain (mbuf, output); >>> Index: Target.i3 >>> =================================================================== >>> >>> >>> - Jay >>> >>> From: hosking at cs.purdue.edu >>> Date: Wed, 26 Sep 2012 10:42:26 -0400 >>> To: jay.krell at cornell.edu >>> CC: m3devel at elegosoft.com >>> Subject: Re: [M3devel] M3CG_Ops.Public vs. M3CG.T >>> >>> I disagree. M3CG.T is more abstract than M3CG_Ops. The revelation of M3CG.T <: M3CG_Ops.Public is in M3CG_Ops. If you want the ops you simply import that interface to get the revelation. Please don?t make pervasive changes in interfaces that some of us are developing against. >>> >>> On Sep 26, 2012, at 4:11 AM, Jay K wrote: >>> >>> M3CG_Ops.i3: >>> >>> >>> child: M3CG.T := NIL; >>> (* The default methods simply call the corresponding method in 'child', >>> hence a vanilla 'M3CG.T' can be used as a filter where you override >>> only the methods of interest. *) >>> >>> 1) >>> >>> I am not keen on fixing this, but I feel this was clearly a mistake. >>> >>> M3CG_Ops.Public should have been "purely abstract" with no default >>> implementation. >>> M3CG_Filter.T or somesuch could have been as described. >>> >>> >>> 2) I am fixing: >>> M3CG.T is overused. >>> Most uses should be M3CG_Ops.Public. >>> It is ok to derive from -- though that was a mistake. >>> But functions that take or return M3CG.T should really be >>> taking and returning M3CG_Ops.Public. >>> >>> >>> - Jay >> -------------- next part -------------- An HTML attachment was scrubbed... URL: From jay.krell at cornell.edu Thu Sep 27 07:14:27 2012 From: jay.krell at cornell.edu (Jay K) Date: Thu, 27 Sep 2012 05:14:27 +0000 Subject: [M3devel] M3CG_Ops.Public vs. M3CG.T In-Reply-To: <93DDAC8D-8917-4558-B99A-A99C3F767F42@cs.purdue.edu> References: , , , , , <93DDAC8D-8917-4558-B99A-A99C3F767F42@cs.purdue.edu> Message-ID: No. I'm ok with that. My point is, that basically, there are two really good forms ofinterface that have the right level of revelation and hiding.I don't see much point for in-between. The two forms..they are kind of canonical C and C++ forms, butthey both map to Modula-3. One form is a fully opaque type and a bunch of functionsthat take that type as the first parameter. Like this: struct Window_t; typedef struct Window_t* Window_t; Window_t* Window_Create(...); /* create is special -- first parameter isn't Window_t* */ void Window_Close(Window_t*...); void Window_SetTitle(Window_t*...); TEXT Window_GetTitle(Window_t*...); It maps directly to Modula-3.Though I'm not sure exactly how. Window.i3:INTERFACE Window;TYPE T <: ROOT;PROCEDURE Close(T);PROCEDURE SetTitle(T, TEXT);PROCEDURE GetTitle(T): TEXT; The other form is a bunch of pure virtual functions, nodata, no non-virtual functions. This is what COM prescribes.And "Create" is special. struct Window_t{ virtual void Close() = 0; virtual void SetTitle(TEXT) = 0; virtual TEXT GetTitle() = 0;}; Window_t* Window_Create(...); This maps well to Modula-3 as well: Window.i3:T <: OBJECT METHODS PROCEDURE Close(); PROCEDURE SetTitle(TEXT); PROCEDURE GetTitle(): TEXT;END; The in-between, which I'm not sure is all that worthwhile,is where C++ offers "protected", and "worse", "private".Really "private" doesn't belong in a header. In the case of M3CG, I don't think we have any need for in-between.I think currently clients either know it is <: ROOT or <: Ops.Public. I don't see the point in hiding <: Ops.Public.You might as well let every client know that.They just pass them around by value/reference, and not callany methods/member-functions, but I don't see that hidingthem helps anything. Typical "operating system" interfaces look like what I showed first,except that Window_t* is replaced by "int" or "void*". Which I think ismostly inferior. void* at least allows for basically the same implementationstrategies, including casting it to int and indexing into a table, buthaving different pointer types allows for a little bit of type-safetyin the clients (i.e. avoiding passing a Windows_t* to File_Read). - Jay From: hosking at cs.purdue.edu Date: Wed, 26 Sep 2012 15:53:26 -0400 To: jay.krell at cornell.edu CC: m3devel at elegosoft.com Subject: Re: [M3devel] M3CG_Ops.Public vs. M3CG.T Are you saying that you don?t like importing M3CG as well as M3CG_Ops? On Sep 26, 2012, at 3:30 PM, Jay wrote:Ok but this seems not great.. - Jay (briefly/pocket-sized-computer-aka-phone) On Sep 26, 2012, at 8:58 AM, Antony Hosking wrote: Yes, M3CG.T is the most abstract type.Please don?t make this change. On Sep 26, 2012, at 11:36 AM, Jay K wrote:It is not pervasive.It is like one line in about six files. M3CG.T => M3CG_Ops.Publics. I guess you are saying that M3CG.T is merely the extremely abstract ROOT, where M3CG_Ops.Public has a bunch of methods? Then I might argue that M3CG.T is overly abstract -- it is like void* instead of pointer just with a bunch of methods. This isn't quite right, doesn't compilte, but rougly: Index: M3CG_BinRd.i3===================================================================RCS file: /usr/cvs/cm3/m3-sys/m3middle/src/M3CG_BinRd.i3,vretrieving revision 1.2diff -u -r1.2 M3CG_BinRd.i3--- M3CG_BinRd.i3 12 Feb 2001 15:25:47 -0000 1.2+++ M3CG_BinRd.i3 26 Sep 2012 15:34:32 -0000@@ -3,9 +3,9 @@ INTERFACE M3CG_BinRd; -IMPORT M3CG, Rd;+IMPORT M3CG_Ops, Rd; -PROCEDURE Inhale (rd: Rd.T; cg: M3CG.T);+PROCEDURE Inhale (rd: Rd.T; cg: M3CG_Ops.Public); (* Parse the binary intermediate code M3CG calls from 'rd' and call 'cg' to implement them. *) Index: M3CG_BinRd.m3===================================================================RCS file: /usr/cvs/cm3/m3-sys/m3middle/src/M3CG_BinRd.m3,vretrieving revision 1.19diff -u -r1.19 M3CG_BinRd.m3--- M3CG_BinRd.m3 4 Sep 2012 14:29:54 -0000 1.19+++ M3CG_BinRd.m3 26 Sep 2012 15:34:32 -0000@@ -20,7 +20,7 @@ TYPE State = RECORD rd : Rd.T;- cg : M3CG.T;+ cg : M3CG_Ops.Public; buf : InputBuffer; buf_len: CARDINAL; buf_ptr: CARDINAL;@@ -200,7 +200,7 @@ Cmd {Bop.fetch_and_xor, fetch_and_xor} }; -PROCEDURE Inhale (rd: Rd.T; cg: M3CG.T) =+PROCEDURE Inhale (rd: Rd.T; cg: M3CG_Ops.Public) = VAR s: State; op: M3CG.Name; cmd: INTEGER; BEGIN s.rd := rd;Index: M3CG_BinWr.i3===================================================================RCS file: /usr/cvs/cm3/m3-sys/m3middle/src/M3CG_BinWr.i3,vretrieving revision 1.2diff -u -r1.2 M3CG_BinWr.i3--- M3CG_BinWr.i3 12 Feb 2001 15:25:47 -0000 1.2+++ M3CG_BinWr.i3 26 Sep 2012 15:34:32 -0000@@ -3,9 +3,9 @@ INTERFACE M3CG_BinWr; -IMPORT M3CG, Wr;+IMPORT M3CG_Ops, Wr; -PROCEDURE New (wr: Wr.T): M3CG.T;+PROCEDURE New (wr: Wr.T): M3CG_Ops.Public; (* returns a fresh, initialized code generator that writes its calls as binary intermediate code on 'wr'. See M3CG_Binary for the binary format. *)Index: M3CG_BinWr.m3===================================================================RCS file: /usr/cvs/cm3/m3-sys/m3middle/src/M3CG_BinWr.m3,vretrieving revision 1.23diff -u -r1.23 M3CG_BinWr.m3--- M3CG_BinWr.m3 4 Sep 2012 15:20:09 -0000 1.23+++ M3CG_BinWr.m3 26 Sep 2012 15:34:32 -0000@@ -27,7 +27,7 @@ END; TYPE- U = M3CG.T OBJECT+ U = M3CG_Ops.Public OBJECT wr : Wr.T := NIL; buf : M3Buf.T := NIL; buf_len : INTEGER := 0;@@ -375,7 +375,7 @@ (*---------------------------------------------------------------------------*) -PROCEDURE New (output: Wr.T): M3CG.T =+PROCEDURE New (output: Wr.T): M3CG_Ops.Public = VAR mbuf := M3Buf.New (); BEGIN M3Buf.AttachDrain (mbuf, output);Index: M3CG_Check.i3===================================================================RCS file: /usr/cvs/cm3/m3-sys/m3middle/src/M3CG_Check.i3,vretrieving revision 1.1.1.1diff -u -r1.1.1.1 M3CG_Check.i3--- M3CG_Check.i3 14 Jan 2001 13:40:37 -0000 1.1.1.1+++ M3CG_Check.i3 26 Sep 2012 15:34:32 -0000@@ -7,11 +7,11 @@ INTERFACE M3CG_Check; -IMPORT M3CG;+IMPORT M3CG_Ops; -PROCEDURE New (child: M3CG.T;+PROCEDURE New (child: M3CG_Ops.Public; clean_jumps, clean_stores: BOOLEAN;- nested_calls, nested_procs: BOOLEAN): M3CG.T;+ nested_calls, nested_procs: BOOLEAN): M3CG_Ops.Public; (* returns a fresh, initialized code generator that passes its calls to 'child' and checks that the stream obeys the M3CG restrictions. If 'clean_jumps', it also checks that the stack is empty at everyIndex: M3CG_Check.m3===================================================================RCS file: /usr/cvs/cm3/m3-sys/m3middle/src/M3CG_Check.m3,vretrieving revision 1.17diff -u -r1.17 M3CG_Check.m3--- M3CG_Check.m3 4 Sep 2012 14:47:43 -0000 1.17+++ M3CG_Check.m3 26 Sep 2012 15:34:33 -0000@@ -32,7 +32,7 @@ }; TYPE- U = M3CG.T OBJECT+ U = M3CG_Ops.Public OBJECT clean_stores := FALSE; clean_jumps := FALSE; nested_calls := TRUE;===================================================================RCS file: /usr/cvs/cm3/m3-sys/m3middle/src/M3CG_Ops.i3,vretrieving revision 1.12diff -u -r1.12 M3CG_Ops.i3--- M3CG_Ops.i3 16 Aug 2012 13:12:35 -0000 1.12+++ M3CG_Ops.i3 26 Sep 2012 15:34:33 -0000@@ -30,7 +30,7 @@ Public = OBJECT (*------------------------------------------------ READONLY configuration ---*) -child: M3CG.T := NIL;+child: Public := NIL; (* The default methods simply call the corresponding method in 'child', hence a vanilla 'M3CG.T' can be used as a filter where you override only the methods of interest. *)Index: M3CG_Rd.i3===================================================================RCS file: /usr/cvs/cm3/m3-sys/m3middle/src/M3CG_Rd.i3,vretrieving revision 1.1.1.1diff -u -r1.1.1.1 M3CG_Rd.i3--- M3CG_Rd.i3 14 Jan 2001 13:40:37 -0000 1.1.1.1+++ M3CG_Rd.i3 26 Sep 2012 15:34:33 -0000@@ -7,9 +7,9 @@ INTERFACE M3CG_Rd; -IMPORT M3CG, Rd;+IMPORT M3CG_Ops, Rd; -PROCEDURE Inhale (rd: Rd.T; cg: M3CG.T);+PROCEDURE Inhale (rd: Rd.T; cg: M3CG_Ops.Public); (* Parse the M3CG calls from 'rd' and call 'cg' to implement them. *) END M3CG_Rd.Index: M3CG_Rd.m3===================================================================RCS file: /usr/cvs/cm3/m3-sys/m3middle/src/M3CG_Rd.m3,vretrieving revision 1.15diff -u -r1.15 M3CG_Rd.m3--- M3CG_Rd.m3 4 Sep 2012 14:52:46 -0000 1.15+++ M3CG_Rd.m3 26 Sep 2012 15:34:33 -0000@@ -22,7 +22,7 @@ TYPE State = RECORD rd : Rd.T;- cg : M3CG.T;+ cg : M3CG_Ops.Public; ch : CHAR; (* current scan character *) buf : InputBuffer; buf_len: CARDINAL;@@ -206,7 +206,7 @@ cmds: IntIntTbl.T := NIL; types: IntIntTbl.T := NIL; -PROCEDURE Inhale (rd: Rd.T; cg: M3CG.T) =+PROCEDURE Inhale (rd: Rd.T; cg: M3CG_Ops.Public) = VAR s: State; op: M3CG.Name; cmd: INTEGER; BEGIN s.rd := rd;Index: M3CG_Wr.i3===================================================================RCS file: /usr/cvs/cm3/m3-sys/m3middle/src/M3CG_Wr.i3,vretrieving revision 1.1.1.1diff -u -r1.1.1.1 M3CG_Wr.i3--- M3CG_Wr.i3 14 Jan 2001 13:40:37 -0000 1.1.1.1+++ M3CG_Wr.i3 26 Sep 2012 15:34:33 -0000@@ -7,9 +7,9 @@ INTERFACE M3CG_Wr; -IMPORT M3CG, Wr;+IMPORT M3CG_Ops, Wr; -PROCEDURE New (wr: Wr.T): M3CG.T;+PROCEDURE New (wr: Wr.T): M3CG_Ops.Public; (* returns a fresh, initialized code generator that writes its calls as readable ASCII on 'wr'. *) Index: M3CG_Wr.m3===================================================================RCS file: /usr/cvs/cm3/m3-sys/m3middle/src/M3CG_Wr.m3,vretrieving revision 1.18diff -u -r1.18 M3CG_Wr.m3--- M3CG_Wr.m3 22 Aug 2012 14:15:40 -0000 1.18+++ M3CG_Wr.m3 26 Sep 2012 15:34:33 -0000@@ -27,7 +27,7 @@ END; TYPE- U = M3CG.T OBJECT+ U = M3CG_Ops.Public OBJECT wr : Wr.T := NIL; buf : M3Buf.T := NIL; buf_len : INTEGER := 0;@@ -375,7 +375,7 @@ (*---------------------------------------------------------------------------*) -PROCEDURE New (output: Wr.T): M3CG.T =+PROCEDURE New (output: Wr.T): M3CG_Ops.Public = VAR mbuf := M3Buf.New (); BEGIN M3Buf.AttachDrain (mbuf, output);Index: Target.i3=================================================================== - Jay From: hosking at cs.purdue.edu Date: Wed, 26 Sep 2012 10:42:26 -0400 To: jay.krell at cornell.edu CC: m3devel at elegosoft.com Subject: Re: [M3devel] M3CG_Ops.Public vs. M3CG.T I disagree. M3CG.T is more abstract than M3CG_Ops. The revelation of M3CG.T <: M3CG_Ops.Public is in M3CG_Ops. If you want the ops you simply import that interface to get the revelation. Please don?t make pervasive changes in interfaces that some of us are developing against. On Sep 26, 2012, at 4:11 AM, Jay K wrote:M3CG_Ops.i3: child: M3CG.T := NIL;(* The default methods simply call the corresponding method in 'child', hence a vanilla 'M3CG.T' can be used as a filter where you override only the methods of interest. *) 1) I am not keen on fixing this, but I feel this was clearly a mistake. M3CG_Ops.Public should have been "purely abstract" with no defaultimplementation.M3CG_Filter.T or somesuch could have been as described. 2) I am fixing:M3CG.T is overused.Most uses should be M3CG_Ops.Public.It is ok to derive from -- though that was a mistake.But functions that take or return M3CG.T should really betaking and returning M3CG_Ops.Public. - Jay -------------- next part -------------- An HTML attachment was scrubbed... URL: From jay.krell at cornell.edu Thu Sep 27 21:00:30 2012 From: jay.krell at cornell.edu (Jay K) Date: Thu, 27 Sep 2012 19:00:30 +0000 Subject: [M3devel] M3CG_Ops.Public vs. M3CG.T In-Reply-To: References: , , , , , , , , , , <93DDAC8D-8917-4558-B99A-A99C3F767F42@cs.purdue.edu>, Message-ID: One thing I missed is that IMPORT M3CG; Give you an M3CG.T that you can only pass around. Add IMPORT M3CG_Ops I think it was and then you can make all the method calls on an M3CG.T. I don't see that the first intermediate step is useful, but oh well. Everyone might as well just IMPORT M3CG_Ops. It is kind of interesting that "private" and "protected" are kind of available in Modula-3, or at least one clump therein, by moving part of the interface into a separate file. I say one clump, because I don't think you can do this: FooRoot.i3: TYPE Foo <: ROOT; Foo1.i3: TYPE Foo <: OBJECT METHODS PROCEDURE F1(); END; Foo2.i3:TYPE Foo <: OBJECT METHODSPROCEDURE F2();END; Foo.m3: REVEAL Foo = OBJECT METHODS PROCEDURE F1(); PROCEDURE F2(); END; I think you can only have just: FooRoot.i3: TYPE Foo <: ROOT; Foo1.i3: TYPE Foo <: OBJECT METHODS PROCEDURE F1(); END; Foo.m3: REVEAL Foo = OBJECT METHODS PROCEDURE F1(); PROCEDURE F2(); END; It'd also be useful if you could do like this: Stream.i3: Reader = OBJECT METHODS PROCEDURE Read(); END; Writer = OBJECT METHODS PROCEDURE Write(); END; TYPE Stream <: Reader; TYPE Stream <: Writer; Stream.m3: REVEAL Stream = OBJECT METHODS PROCEDURE Read(); PROCEDURE Write(); END; i.e. -- multiple inheritance. I realize you can reveal in multiple linear steps though...which I'm not going to give an example of right now.. so it isn't just "one clump", but if you reveal "multiple clumps", they need to form a linear chain, right? You can't "mix" as I showed for read/write. ? - Jay From: jay.krell at cornell.edu To: hosking at cs.purdue.edu Date: Thu, 27 Sep 2012 05:14:27 +0000 CC: m3devel at elegosoft.com Subject: Re: [M3devel] M3CG_Ops.Public vs. M3CG.T No. I'm ok with that. My point is, that basically, there are two really good forms ofinterface that have the right level of revelation and hiding.I don't see much point for in-between. The two forms..they are kind of canonical C and C++ forms, butthey both map to Modula-3. One form is a fully opaque type and a bunch of functionsthat take that type as the first parameter. Like this: struct Window_t; typedef struct Window_t* Window_t; Window_t* Window_Create(...); /* create is special -- first parameter isn't Window_t* */ void Window_Close(Window_t*...); void Window_SetTitle(Window_t*...); TEXT Window_GetTitle(Window_t*...); It maps directly to Modula-3.Though I'm not sure exactly how. Window.i3:INTERFACE Window;TYPE T <: ROOT;PROCEDURE Close(T);PROCEDURE SetTitle(T, TEXT);PROCEDURE GetTitle(T): TEXT; The other form is a bunch of pure virtual functions, nodata, no non-virtual functions. This is what COM prescribes.And "Create" is special. struct Window_t{ virtual void Close() = 0; virtual void SetTitle(TEXT) = 0; virtual TEXT GetTitle() = 0;}; Window_t* Window_Create(...); This maps well to Modula-3 as well: Window.i3:T <: OBJECT METHODS PROCEDURE Close(); PROCEDURE SetTitle(TEXT); PROCEDURE GetTitle(): TEXT;END; The in-between, which I'm not sure is all that worthwhile,is where C++ offers "protected", and "worse", "private".Really "private" doesn't belong in a header. In the case of M3CG, I don't think we have any need for in-between.I think currently clients either know it is <: ROOT or <: Ops.Public. I don't see the point in hiding <: Ops.Public.You might as well let every client know that.They just pass them around by value/reference, and not callany methods/member-functions, but I don't see that hidingthem helps anything. Typical "operating system" interfaces look like what I showed first,except that Window_t* is replaced by "int" or "void*". Which I think ismostly inferior. void* at least allows for basically the same implementationstrategies, including casting it to int and indexing into a table, buthaving different pointer types allows for a little bit of type-safetyin the clients (i.e. avoiding passing a Windows_t* to File_Read). - Jay From: hosking at cs.purdue.edu Date: Wed, 26 Sep 2012 15:53:26 -0400 To: jay.krell at cornell.edu CC: m3devel at elegosoft.com Subject: Re: [M3devel] M3CG_Ops.Public vs. M3CG.T Are you saying that you don?t like importing M3CG as well as M3CG_Ops? On Sep 26, 2012, at 3:30 PM, Jay wrote:Ok but this seems not great.. - Jay (briefly/pocket-sized-computer-aka-phone) On Sep 26, 2012, at 8:58 AM, Antony Hosking wrote: Yes, M3CG.T is the most abstract type.Please don?t make this change. On Sep 26, 2012, at 11:36 AM, Jay K wrote:It is not pervasive.It is like one line in about six files. M3CG.T => M3CG_Ops.Publics. I guess you are saying that M3CG.T is merely the extremely abstract ROOT, where M3CG_Ops.Public has a bunch of methods? Then I might argue that M3CG.T is overly abstract -- it is like void* instead of pointer just with a bunch of methods. This isn't quite right, doesn't compilte, but rougly: Index: M3CG_BinRd.i3===================================================================RCS file: /usr/cvs/cm3/m3-sys/m3middle/src/M3CG_BinRd.i3,vretrieving revision 1.2diff -u -r1.2 M3CG_BinRd.i3--- M3CG_BinRd.i3 12 Feb 2001 15:25:47 -0000 1.2+++ M3CG_BinRd.i3 26 Sep 2012 15:34:32 -0000@@ -3,9 +3,9 @@ INTERFACE M3CG_BinRd; -IMPORT M3CG, Rd;+IMPORT M3CG_Ops, Rd; -PROCEDURE Inhale (rd: Rd.T; cg: M3CG.T);+PROCEDURE Inhale (rd: Rd.T; cg: M3CG_Ops.Public); (* Parse the binary intermediate code M3CG calls from 'rd' and call 'cg' to implement them. *) Index: M3CG_BinRd.m3===================================================================RCS file: /usr/cvs/cm3/m3-sys/m3middle/src/M3CG_BinRd.m3,vretrieving revision 1.19diff -u -r1.19 M3CG_BinRd.m3--- M3CG_BinRd.m3 4 Sep 2012 14:29:54 -0000 1.19+++ M3CG_BinRd.m3 26 Sep 2012 15:34:32 -0000@@ -20,7 +20,7 @@ TYPE State = RECORD rd : Rd.T;- cg : M3CG.T;+ cg : M3CG_Ops.Public; buf : InputBuffer; buf_len: CARDINAL; buf_ptr: CARDINAL;@@ -200,7 +200,7 @@ Cmd {Bop.fetch_and_xor, fetch_and_xor} }; -PROCEDURE Inhale (rd: Rd.T; cg: M3CG.T) =+PROCEDURE Inhale (rd: Rd.T; cg: M3CG_Ops.Public) = VAR s: State; op: M3CG.Name; cmd: INTEGER; BEGIN s.rd := rd;Index: M3CG_BinWr.i3===================================================================RCS file: /usr/cvs/cm3/m3-sys/m3middle/src/M3CG_BinWr.i3,vretrieving revision 1.2diff -u -r1.2 M3CG_BinWr.i3--- M3CG_BinWr.i3 12 Feb 2001 15:25:47 -0000 1.2+++ M3CG_BinWr.i3 26 Sep 2012 15:34:32 -0000@@ -3,9 +3,9 @@ INTERFACE M3CG_BinWr; -IMPORT M3CG, Wr;+IMPORT M3CG_Ops, Wr; -PROCEDURE New (wr: Wr.T): M3CG.T;+PROCEDURE New (wr: Wr.T): M3CG_Ops.Public; (* returns a fresh, initialized code generator that writes its calls as binary intermediate code on 'wr'. See M3CG_Binary for the binary format. *)Index: M3CG_BinWr.m3===================================================================RCS file: /usr/cvs/cm3/m3-sys/m3middle/src/M3CG_BinWr.m3,vretrieving revision 1.23diff -u -r1.23 M3CG_BinWr.m3--- M3CG_BinWr.m3 4 Sep 2012 15:20:09 -0000 1.23+++ M3CG_BinWr.m3 26 Sep 2012 15:34:32 -0000@@ -27,7 +27,7 @@ END; TYPE- U = M3CG.T OBJECT+ U = M3CG_Ops.Public OBJECT wr : Wr.T := NIL; buf : M3Buf.T := NIL; buf_len : INTEGER := 0;@@ -375,7 +375,7 @@ (*---------------------------------------------------------------------------*) -PROCEDURE New (output: Wr.T): M3CG.T =+PROCEDURE New (output: Wr.T): M3CG_Ops.Public = VAR mbuf := M3Buf.New (); BEGIN M3Buf.AttachDrain (mbuf, output);Index: M3CG_Check.i3===================================================================RCS file: /usr/cvs/cm3/m3-sys/m3middle/src/M3CG_Check.i3,vretrieving revision 1.1.1.1diff -u -r1.1.1.1 M3CG_Check.i3--- M3CG_Check.i3 14 Jan 2001 13:40:37 -0000 1.1.1.1+++ M3CG_Check.i3 26 Sep 2012 15:34:32 -0000@@ -7,11 +7,11 @@ INTERFACE M3CG_Check; -IMPORT M3CG;+IMPORT M3CG_Ops; -PROCEDURE New (child: M3CG.T;+PROCEDURE New (child: M3CG_Ops.Public; clean_jumps, clean_stores: BOOLEAN;- nested_calls, nested_procs: BOOLEAN): M3CG.T;+ nested_calls, nested_procs: BOOLEAN): M3CG_Ops.Public; (* returns a fresh, initialized code generator that passes its calls to 'child' and checks that the stream obeys the M3CG restrictions. If 'clean_jumps', it also checks that the stack is empty at everyIndex: M3CG_Check.m3===================================================================RCS file: /usr/cvs/cm3/m3-sys/m3middle/src/M3CG_Check.m3,vretrieving revision 1.17diff -u -r1.17 M3CG_Check.m3--- M3CG_Check.m3 4 Sep 2012 14:47:43 -0000 1.17+++ M3CG_Check.m3 26 Sep 2012 15:34:33 -0000@@ -32,7 +32,7 @@ }; TYPE- U = M3CG.T OBJECT+ U = M3CG_Ops.Public OBJECT clean_stores := FALSE; clean_jumps := FALSE; nested_calls := TRUE;===================================================================RCS file: /usr/cvs/cm3/m3-sys/m3middle/src/M3CG_Ops.i3,vretrieving revision 1.12diff -u -r1.12 M3CG_Ops.i3--- M3CG_Ops.i3 16 Aug 2012 13:12:35 -0000 1.12+++ M3CG_Ops.i3 26 Sep 2012 15:34:33 -0000@@ -30,7 +30,7 @@ Public = OBJECT (*------------------------------------------------ READONLY configuration ---*) -child: M3CG.T := NIL;+child: Public := NIL; (* The default methods simply call the corresponding method in 'child', hence a vanilla 'M3CG.T' can be used as a filter where you override only the methods of interest. *)Index: M3CG_Rd.i3===================================================================RCS file: /usr/cvs/cm3/m3-sys/m3middle/src/M3CG_Rd.i3,vretrieving revision 1.1.1.1diff -u -r1.1.1.1 M3CG_Rd.i3--- M3CG_Rd.i3 14 Jan 2001 13:40:37 -0000 1.1.1.1+++ M3CG_Rd.i3 26 Sep 2012 15:34:33 -0000@@ -7,9 +7,9 @@ INTERFACE M3CG_Rd; -IMPORT M3CG, Rd;+IMPORT M3CG_Ops, Rd; -PROCEDURE Inhale (rd: Rd.T; cg: M3CG.T);+PROCEDURE Inhale (rd: Rd.T; cg: M3CG_Ops.Public); (* Parse the M3CG calls from 'rd' and call 'cg' to implement them. *) END M3CG_Rd.Index: M3CG_Rd.m3===================================================================RCS file: /usr/cvs/cm3/m3-sys/m3middle/src/M3CG_Rd.m3,vretrieving revision 1.15diff -u -r1.15 M3CG_Rd.m3--- M3CG_Rd.m3 4 Sep 2012 14:52:46 -0000 1.15+++ M3CG_Rd.m3 26 Sep 2012 15:34:33 -0000@@ -22,7 +22,7 @@ TYPE State = RECORD rd : Rd.T;- cg : M3CG.T;+ cg : M3CG_Ops.Public; ch : CHAR; (* current scan character *) buf : InputBuffer; buf_len: CARDINAL;@@ -206,7 +206,7 @@ cmds: IntIntTbl.T := NIL; types: IntIntTbl.T := NIL; -PROCEDURE Inhale (rd: Rd.T; cg: M3CG.T) =+PROCEDURE Inhale (rd: Rd.T; cg: M3CG_Ops.Public) = VAR s: State; op: M3CG.Name; cmd: INTEGER; BEGIN s.rd := rd;Index: M3CG_Wr.i3===================================================================RCS file: /usr/cvs/cm3/m3-sys/m3middle/src/M3CG_Wr.i3,vretrieving revision 1.1.1.1diff -u -r1.1.1.1 M3CG_Wr.i3--- M3CG_Wr.i3 14 Jan 2001 13:40:37 -0000 1.1.1.1+++ M3CG_Wr.i3 26 Sep 2012 15:34:33 -0000@@ -7,9 +7,9 @@ INTERFACE M3CG_Wr; -IMPORT M3CG, Wr;+IMPORT M3CG_Ops, Wr; -PROCEDURE New (wr: Wr.T): M3CG.T;+PROCEDURE New (wr: Wr.T): M3CG_Ops.Public; (* returns a fresh, initialized code generator that writes its calls as readable ASCII on 'wr'. *) Index: M3CG_Wr.m3===================================================================RCS file: /usr/cvs/cm3/m3-sys/m3middle/src/M3CG_Wr.m3,vretrieving revision 1.18diff -u -r1.18 M3CG_Wr.m3--- M3CG_Wr.m3 22 Aug 2012 14:15:40 -0000 1.18+++ M3CG_Wr.m3 26 Sep 2012 15:34:33 -0000@@ -27,7 +27,7 @@ END; TYPE- U = M3CG.T OBJECT+ U = M3CG_Ops.Public OBJECT wr : Wr.T := NIL; buf : M3Buf.T := NIL; buf_len : INTEGER := 0;@@ -375,7 +375,7 @@ (*---------------------------------------------------------------------------*) -PROCEDURE New (output: Wr.T): M3CG.T =+PROCEDURE New (output: Wr.T): M3CG_Ops.Public = VAR mbuf := M3Buf.New (); BEGIN M3Buf.AttachDrain (mbuf, output);Index: Target.i3=================================================================== - Jay From: hosking at cs.purdue.edu Date: Wed, 26 Sep 2012 10:42:26 -0400 To: jay.krell at cornell.edu CC: m3devel at elegosoft.com Subject: Re: [M3devel] M3CG_Ops.Public vs. M3CG.T I disagree. M3CG.T is more abstract than M3CG_Ops. The revelation of M3CG.T <: M3CG_Ops.Public is in M3CG_Ops. If you want the ops you simply import that interface to get the revelation. Please don?t make pervasive changes in interfaces that some of us are developing against. On Sep 26, 2012, at 4:11 AM, Jay K wrote:M3CG_Ops.i3: child: M3CG.T := NIL;(* The default methods simply call the corresponding method in 'child', hence a vanilla 'M3CG.T' can be used as a filter where you override only the methods of interest. *) 1) I am not keen on fixing this, but I feel this was clearly a mistake. M3CG_Ops.Public should have been "purely abstract" with no defaultimplementation.M3CG_Filter.T or somesuch could have been as described. 2) I am fixing:M3CG.T is overused.Most uses should be M3CG_Ops.Public.It is ok to derive from -- though that was a mistake.But functions that take or return M3CG.T should really betaking and returning M3CG_Ops.Public. - Jay -------------- next part -------------- An HTML attachment was scrubbed... URL: From rcolebur at SCIRES.COM Thu Sep 27 21:48:14 2012 From: rcolebur at SCIRES.COM (Coleburn, Randy) Date: Thu, 27 Sep 2012 15:48:14 -0400 Subject: [M3devel] M3CG_Ops.Public vs. M3CG.T In-Reply-To: References: , , , , , <93DDAC8D-8917-4558-B99A-A99C3F767F42@cs.purdue.edu> Message-ID: Jay: Note that Modula-3 also has partial revelation. (BTW, I like the design tenants of Modula-3. I believe in them and have been successful using them. This is a Modula-3 forum. I know you seem to like C++, but I grow weary of the barrage of C/C++ from you. I would like to see less criticism of Modula-3 and more of how we are going to keep the CM3 implementation evolving toward the best implementation of the language specification possible on a wide array of modern platforms. If there is a perceived need for a language change, a specific proposal should be presented and vetted as a separate thread of discussion. My 2 cents.) --Randy Coleburn From: jayk123 at hotmail.com [mailto:jayk123 at hotmail.com] On Behalf Of Jay K Sent: Thursday, September 27, 2012 1:14 AM To: Tony Cc: m3devel Subject: EXT:Re: [M3devel] M3CG_Ops.Public vs. M3CG.T No. I'm ok with that. My point is, that basically, there are two really good forms of interface that have the right level of revelation and hiding. I don't see much point for in-between. The two forms..they are kind of canonical C and C++ forms, but they both map to Modula-3. One form is a fully opaque type and a bunch of functions that take that type as the first parameter. Like this: struct Window_t; typedef struct Window_t* Window_t; Window_t* Window_Create(...); /* create is special -- first parameter isn't Window_t* */ void Window_Close(Window_t*...); void Window_SetTitle(Window_t*...); TEXT Window_GetTitle(Window_t*...); It maps directly to Modula-3. Though I'm not sure exactly how. Window.i3: INTERFACE Window; TYPE T <: ROOT; PROCEDURE Close(T); PROCEDURE SetTitle(T, TEXT); PROCEDURE GetTitle(T): TEXT; The other form is a bunch of pure virtual functions, no data, no non-virtual functions. This is what COM prescribes. And "Create" is special. struct Window_t { virtual void Close() = 0; virtual void SetTitle(TEXT) = 0; virtual TEXT GetTitle() = 0; }; Window_t* Window_Create(...); This maps well to Modula-3 as well: Window.i3: T <: OBJECT METHODS PROCEDURE Close(); PROCEDURE SetTitle(TEXT); PROCEDURE GetTitle(): TEXT; END; The in-between, which I'm not sure is all that worthwhile, is where C++ offers "protected", and "worse", "private". Really "private" doesn't belong in a header. In the case of M3CG, I don't think we have any need for in-between. I think currently clients either know it is <: ROOT or <: Ops.Public. I don't see the point in hiding <: Ops.Public. You might as well let every client know that. They just pass them around by value/reference, and not call any methods/member-functions, but I don't see that hiding them helps anything. Typical "operating system" interfaces look like what I showed first, except that Window_t* is replaced by "int" or "void*". Which I think is mostly inferior. void* at least allows for basically the same implementation strategies, including casting it to int and indexing into a table, but having different pointer types allows for a little bit of type-safety in the clients (i.e. avoiding passing a Windows_t* to File_Read). - Jay ________________________________ From: hosking at cs.purdue.edu Date: Wed, 26 Sep 2012 15:53:26 -0400 To: jay.krell at cornell.edu CC: m3devel at elegosoft.com Subject: Re: [M3devel] M3CG_Ops.Public vs. M3CG.T Are you saying that you don't like importing M3CG as well as M3CG_Ops? On Sep 26, 2012, at 3:30 PM, Jay > wrote: Ok but this seems not great.. - Jay (briefly/pocket-sized-computer-aka-phone) On Sep 26, 2012, at 8:58 AM, Antony Hosking > wrote: Yes, M3CG.T is the most abstract type. Please don't make this change. On Sep 26, 2012, at 11:36 AM, Jay K > wrote: It is not pervasive. It is like one line in about six files. M3CG.T => M3CG_Ops.Publics. I guess you are saying that M3CG.T is merely the extremely abstract ROOT, where M3CG_Ops.Public has a bunch of methods? Then I might argue that M3CG.T is overly abstract -- it is like void* instead of pointer just with a bunch of methods. This isn't quite right, doesn't compilte, but rougly: Index: M3CG_BinRd.i3 =================================================================== RCS file: /usr/cvs/cm3/m3-sys/m3middle/src/M3CG_BinRd.i3,v retrieving revision 1.2 diff -u -r1.2 M3CG_BinRd.i3 --- M3CG_BinRd.i3 12 Feb 2001 15:25:47 -0000 1.2 +++ M3CG_BinRd.i3 26 Sep 2012 15:34:32 -0000 @@ -3,9 +3,9 @@ INTERFACE M3CG_BinRd; -IMPORT M3CG, Rd; +IMPORT M3CG_Ops, Rd; -PROCEDURE Inhale (rd: Rd.T; cg: M3CG.T); +PROCEDURE Inhale (rd: Rd.T; cg: M3CG_Ops.Public); (* Parse the binary intermediate code M3CG calls from 'rd' and call 'cg' to implement them. *) Index: M3CG_BinRd.m3 =================================================================== RCS file: /usr/cvs/cm3/m3-sys/m3middle/src/M3CG_BinRd.m3,v retrieving revision 1.19 diff -u -r1.19 M3CG_BinRd.m3 --- M3CG_BinRd.m3 4 Sep 2012 14:29:54 -0000 1.19 +++ M3CG_BinRd.m3 26 Sep 2012 15:34:32 -0000 @@ -20,7 +20,7 @@ TYPE State = RECORD rd : Rd.T; - cg : M3CG.T; + cg : M3CG_Ops.Public; buf : InputBuffer; buf_len: CARDINAL; buf_ptr: CARDINAL; @@ -200,7 +200,7 @@ Cmd {Bop.fetch_and_xor, fetch_and_xor} }; -PROCEDURE Inhale (rd: Rd.T; cg: M3CG.T) = +PROCEDURE Inhale (rd: Rd.T; cg: M3CG_Ops.Public) = VAR s: State; op: M3CG.Name; cmd: INTEGER; BEGIN s.rd := rd; Index: M3CG_BinWr.i3 =================================================================== RCS file: /usr/cvs/cm3/m3-sys/m3middle/src/M3CG_BinWr.i3,v retrieving revision 1.2 diff -u -r1.2 M3CG_BinWr.i3 --- M3CG_BinWr.i3 12 Feb 2001 15:25:47 -0000 1.2 +++ M3CG_BinWr.i3 26 Sep 2012 15:34:32 -0000 @@ -3,9 +3,9 @@ INTERFACE M3CG_BinWr; -IMPORT M3CG, Wr; +IMPORT M3CG_Ops, Wr; -PROCEDURE New (wr: Wr.T): M3CG.T; +PROCEDURE New (wr: Wr.T): M3CG_Ops.Public; (* returns a fresh, initialized code generator that writes its calls as binary intermediate code on 'wr'. See M3CG_Binary for the binary format. *) Index: M3CG_BinWr.m3 =================================================================== RCS file: /usr/cvs/cm3/m3-sys/m3middle/src/M3CG_BinWr.m3,v retrieving revision 1.23 diff -u -r1.23 M3CG_BinWr.m3 --- M3CG_BinWr.m3 4 Sep 2012 15:20:09 -0000 1.23 +++ M3CG_BinWr.m3 26 Sep 2012 15:34:32 -0000 @@ -27,7 +27,7 @@ END; TYPE - U = M3CG.T OBJECT + U = M3CG_Ops.Public OBJECT wr : Wr.T := NIL; buf : M3Buf.T := NIL; buf_len : INTEGER := 0; @@ -375,7 +375,7 @@ (*---------------------------------------------------------------------------*) -PROCEDURE New (output: Wr.T): M3CG.T = +PROCEDURE New (output: Wr.T): M3CG_Ops.Public = VAR mbuf := M3Buf.New (); BEGIN M3Buf.AttachDrain (mbuf, output); Index: M3CG_Check.i3 =================================================================== RCS file: /usr/cvs/cm3/m3-sys/m3middle/src/M3CG_Check.i3,v retrieving revision 1.1.1.1 diff -u -r1.1.1.1 M3CG_Check.i3 --- M3CG_Check.i3 14 Jan 2001 13:40:37 -0000 1.1.1.1 +++ M3CG_Check.i3 26 Sep 2012 15:34:32 -0000 @@ -7,11 +7,11 @@ INTERFACE M3CG_Check; -IMPORT M3CG; +IMPORT M3CG_Ops; -PROCEDURE New (child: M3CG.T; +PROCEDURE New (child: M3CG_Ops.Public; clean_jumps, clean_stores: BOOLEAN; - nested_calls, nested_procs: BOOLEAN): M3CG.T; + nested_calls, nested_procs: BOOLEAN): M3CG_Ops.Public; (* returns a fresh, initialized code generator that passes its calls to 'child' and checks that the stream obeys the M3CG restrictions. If 'clean_jumps', it also checks that the stack is empty at every Index: M3CG_Check.m3 =================================================================== RCS file: /usr/cvs/cm3/m3-sys/m3middle/src/M3CG_Check.m3,v retrieving revision 1.17 diff -u -r1.17 M3CG_Check.m3 --- M3CG_Check.m3 4 Sep 2012 14:47:43 -0000 1.17 +++ M3CG_Check.m3 26 Sep 2012 15:34:33 -0000 @@ -32,7 +32,7 @@ }; TYPE - U = M3CG.T OBJECT + U = M3CG_Ops.Public OBJECT clean_stores := FALSE; clean_jumps := FALSE; nested_calls := TRUE; =================================================================== RCS file: /usr/cvs/cm3/m3-sys/m3middle/src/M3CG_Ops.i3,v retrieving revision 1.12 diff -u -r1.12 M3CG_Ops.i3 --- M3CG_Ops.i3 16 Aug 2012 13:12:35 -0000 1.12 +++ M3CG_Ops.i3 26 Sep 2012 15:34:33 -0000 @@ -30,7 +30,7 @@ Public = OBJECT (*------------------------------------------------ READONLY configuration ---*) -child: M3CG.T := NIL; +child: Public := NIL; (* The default methods simply call the corresponding method in 'child', hence a vanilla 'M3CG.T' can be used as a filter where you override only the methods of interest. *) Index: M3CG_Rd.i3 =================================================================== RCS file: /usr/cvs/cm3/m3-sys/m3middle/src/M3CG_Rd.i3,v retrieving revision 1.1.1.1 diff -u -r1.1.1.1 M3CG_Rd.i3 --- M3CG_Rd.i3 14 Jan 2001 13:40:37 -0000 1.1.1.1 +++ M3CG_Rd.i3 26 Sep 2012 15:34:33 -0000 @@ -7,9 +7,9 @@ INTERFACE M3CG_Rd; -IMPORT M3CG, Rd; +IMPORT M3CG_Ops, Rd; -PROCEDURE Inhale (rd: Rd.T; cg: M3CG.T); +PROCEDURE Inhale (rd: Rd.T; cg: M3CG_Ops.Public); (* Parse the M3CG calls from 'rd' and call 'cg' to implement them. *) END M3CG_Rd. Index: M3CG_Rd.m3 =================================================================== RCS file: /usr/cvs/cm3/m3-sys/m3middle/src/M3CG_Rd.m3,v retrieving revision 1.15 diff -u -r1.15 M3CG_Rd.m3 --- M3CG_Rd.m3 4 Sep 2012 14:52:46 -0000 1.15 +++ M3CG_Rd.m3 26 Sep 2012 15:34:33 -0000 @@ -22,7 +22,7 @@ TYPE State = RECORD rd : Rd.T; - cg : M3CG.T; + cg : M3CG_Ops.Public; ch : CHAR; (* current scan character *) buf : InputBuffer; buf_len: CARDINAL; @@ -206,7 +206,7 @@ cmds: IntIntTbl.T := NIL; types: IntIntTbl.T := NIL; -PROCEDURE Inhale (rd: Rd.T; cg: M3CG.T) = +PROCEDURE Inhale (rd: Rd.T; cg: M3CG_Ops.Public) = VAR s: State; op: M3CG.Name; cmd: INTEGER; BEGIN s.rd := rd; Index: M3CG_Wr.i3 =================================================================== RCS file: /usr/cvs/cm3/m3-sys/m3middle/src/M3CG_Wr.i3,v retrieving revision 1.1.1.1 diff -u -r1.1.1.1 M3CG_Wr.i3 --- M3CG_Wr.i3 14 Jan 2001 13:40:37 -0000 1.1.1.1 +++ M3CG_Wr.i3 26 Sep 2012 15:34:33 -0000 @@ -7,9 +7,9 @@ INTERFACE M3CG_Wr; -IMPORT M3CG, Wr; +IMPORT M3CG_Ops, Wr; -PROCEDURE New (wr: Wr.T): M3CG.T; +PROCEDURE New (wr: Wr.T): M3CG_Ops.Public; (* returns a fresh, initialized code generator that writes its calls as readable ASCII on 'wr'. *) Index: M3CG_Wr.m3 =================================================================== RCS file: /usr/cvs/cm3/m3-sys/m3middle/src/M3CG_Wr.m3,v retrieving revision 1.18 diff -u -r1.18 M3CG_Wr.m3 --- M3CG_Wr.m3 22 Aug 2012 14:15:40 -0000 1.18 +++ M3CG_Wr.m3 26 Sep 2012 15:34:33 -0000 @@ -27,7 +27,7 @@ END; TYPE - U = M3CG.T OBJECT + U = M3CG_Ops.Public OBJECT wr : Wr.T := NIL; buf : M3Buf.T := NIL; buf_len : INTEGER := 0; @@ -375,7 +375,7 @@ (*---------------------------------------------------------------------------*) -PROCEDURE New (output: Wr.T): M3CG.T = +PROCEDURE New (output: Wr.T): M3CG_Ops.Public = VAR mbuf := M3Buf.New (); BEGIN M3Buf.AttachDrain (mbuf, output); Index: Target.i3 =================================================================== - Jay ________________________________ From: hosking at cs.purdue.edu Date: Wed, 26 Sep 2012 10:42:26 -0400 To: jay.krell at cornell.edu CC: m3devel at elegosoft.com Subject: Re: [M3devel] M3CG_Ops.Public vs. M3CG.T I disagree. M3CG.T is more abstract than M3CG_Ops. The revelation of M3CG.T <: M3CG_Ops.Public is in M3CG_Ops. If you want the ops you simply import that interface to get the revelation. Please don't make pervasive changes in interfaces that some of us are developing against. On Sep 26, 2012, at 4:11 AM, Jay K > wrote: M3CG_Ops.i3: child: M3CG.T := NIL; (* The default methods simply call the corresponding method in 'child', hence a vanilla 'M3CG.T' can be used as a filter where you override only the methods of interest. *) 1) I am not keen on fixing this, but I feel this was clearly a mistake. M3CG_Ops.Public should have been "purely abstract" with no default implementation. M3CG_Filter.T or somesuch could have been as described. 2) I am fixing: M3CG.T is overused. Most uses should be M3CG_Ops.Public. It is ok to derive from -- though that was a mistake. But functions that take or return M3CG.T should really be taking and returning M3CG_Ops.Public. - Jay -------------- next part -------------- An HTML attachment was scrubbed... URL: From jay.krell at cornell.edu Fri Sep 28 04:49:01 2012 From: jay.krell at cornell.edu (Jay K) Date: Fri, 28 Sep 2012 02:49:01 +0000 Subject: [M3devel] generics w/o explicit instantiation in build system? Message-ID: Given GENERIC INTERFACE Vector(T); I'd like to say: TYPE Foo = REF RECORD ... END; VAR foo := NEW(Sequence(Foo)); without messing around with any Quake code. Is this really so much to ask? Today instead I have to either mess around with Quake,or store REFANY and constantly NARROW them.Like storing a void* in a container, but safer and slower. C++, Java, and C# all provide about the same thing here. >From a language point of view, I think this is easy.The only complication is what name to give the thing internally.There are a few obvious choice: Prepend/append the current module/interface. This is easiest. But might lead to some bloat. Prepend/append a hash. Or maybe nothing. This provides for single instancing, It either requires builder or linker cooperation. Mark the code as "file level static" using whatever mechanism C does. This is presumably easy and might lead to some bloat. Given a 64bit Sequence(INTEGER), Sequence(LONGINT), the Microsoft linker will automatically combine any resulting code -- when optimization, it combines duplicate code that is "the same" but has different names. Note that it is easy to inhibit, e.g.: int F1() { static int i; return ++i; } int F2() { static int i; return ++i; } are NOT the same, because they must reference different "i". Thoughts? - Jay -------------- next part -------------- An HTML attachment was scrubbed... URL: From jay.krell at cornell.edu Fri Sep 28 04:57:03 2012 From: jay.krell at cornell.edu (Jay K) Date: Fri, 28 Sep 2012 02:57:03 +0000 Subject: [M3devel] deeper meaning of in_memory? Message-ID: In M3CG, what is the deeper meaning of in_memory?I know it means -- "put the thing in memory".But why and exactly what? Presumably it can also be in a register, just that the in-memory value must be kept up to date.Like, stores should be volatile, but reads don't have to be?Does it mean the value will be used in an exception/finally handler?Maybe reads do need to be volatile? Maybe it is accessed by another thread w/o a lock? If I take the address of something, is that good enough? I should just look where m3front uses it, I know.For now I'll probably take it to mean "volatile".I already mark all structs as volatile. But I don't make everything volatile (like how m3cc long did). Thanks, - Jay -------------- next part -------------- An HTML attachment was scrubbed... URL: From jay.krell at cornell.edu Fri Sep 28 09:18:19 2012 From: jay.krell at cornell.edu (Jay K) Date: Fri, 28 Sep 2012 07:18:19 +0000 Subject: [M3devel] STL algorithms? sort/unique? Message-ID: I have an IntSeq.T with a bunch of integers. What is a good terse efficient idiom for sort and unique? In C++ I would say: vector a; a.push_back(...); a.push_back(...); std::sort(a.begin(), a.end()); a.resize(std::unique(a.begin(), a.end()) - a.begin()); for (auto i = a.begin(); i != a.end(); ++i) { do stuff with *i } Nice, terse, efficient. In Modula-3? I know that unique is one of the easiest algorithms to manually write inline,but I shouldn't have to. (I'm really trying to stay in Modula-3 here, but it is definitely a struggle. :( ) Thank you, - Jay -------------- next part -------------- An HTML attachment was scrubbed... URL: From mika at async.caltech.edu Fri Sep 28 09:56:56 2012 From: mika at async.caltech.edu (mika at async.caltech.edu) Date: Fri, 28 Sep 2012 00:56:56 -0700 Subject: [M3devel] STL algorithms? sort/unique? In-Reply-To: References: Message-ID: <20120928075656.751E21A2082@async.async.caltech.edu> You're using the wrong (abstract) data structure if you want sort and unique. A "sequence" is meant to be accessed sequentially... Not knowing precisely what you're doing it sounds like you might want a SortedTable... you can get unique on insert and access it in increasing or decreasing order. Mika Jay K writes: >--_d2a02ece-d492-410e-88fb-fb53737d7219_ >Content-Type: text/plain; charset="iso-8859-1" >Content-Transfer-Encoding: quoted-printable > > I have an IntSeq.T with a bunch of integers. =20 > What is a good terse efficient idiom for sort and unique? =20 > > In C++ I would say: vector a=3B a.push_back(...)=3B = > a.push_back(...)=3B std::sort(a.begin()=2C a.end())=3B = > a.resize(std::unique(a.begin()=2C a.end()) - a.begin())=3B for (aut= >o i =3D a.begin()=3B i !=3D a.end()=3B ++i) { > do stuff with *i }=20 > Nice=2C terse=2C efficient. In Modula-3? =20 > >I know that unique is one of the easiest algorithms to manually write inlin= >e=2Cbut I shouldn't have to. > >(I'm really trying to stay in Modula-3 here=2C but it is definitely a strug= >gle. :( ) > >Thank you=2C - Jay > > = > >--_d2a02ece-d492-410e-88fb-fb53737d7219_ >Content-Type: text/html; charset="iso-8859-1" >Content-Transfer-Encoding: quoted-printable > > > > >
 =3B  =3B =3BI have = >an IntSeq.T with a bunch of integers. =3B  =3B =3B
n style=3D"font-size: 12pt=3B "> =3B  =3B-size: 12pt=3B "> =3BWhat is a good terse efficient idiom for so= >rt and unique? =3B  =3B<= >span style=3D"font-size: 12pt=3B "> =3B

>
 =3B  =3B In C++ I would say:ze: 12pt=3B "> =3B  =3B&= >nbsp=3B
 =3B  = >=3B =3Bvector<=3Bin= >t>=3B a=3B =3B  =3Ban style=3D"font-size: 12pt=3B "> =3B
ont-size: 12pt=3B "> =3B  =3B=3B "> =3Ba.push_back(...)=3B> =3B  =3B =3B>
 =3B  =3Bn> =3Ba.push_back(...)=3Ban style=3D"font-size: 12pt=3B "> =3B  =3Bt-size: 12pt=3B "> =3B
=3B "> =3B  =3B =3B<= >/span>std::sort(a.begin()=2C a.end())=3B> =3B  =3B =3B>
 =3B  =3Ban style=3D"font-size: 12pt=3B "> =3Ba.resize(std::unique(a.begi= >n()=2C a.end()) - a.begin())=3B =3B= >  =3B =3B
iv> =3B  =3B for (auto i =3D a.= >begin()=3B i !=3D a.end()=3B ++i)
: 12pt=3B "> =3B  =3B {
 =3B  =3B  =3B do stuff with= > *i
 =3B  =3B = >}
 =3B

ze: 12pt=3B "> =3B  =3B&= >nbsp=3BNice=2C terse=2C efficient."> =3B  =3B =3Bn>
 =3B  =3Bpan style=3D"font-size: 12pt=3B "> =3BIn Modula-3?"font-size: 12pt=3B "> =3B  =3Bt=3B "> =3B


I know that = >unique is one of the easiest algorithms to manually write inline=2C
iv>but I shouldn't have to.


(I'm re= >ally trying to stay in Modula-3 here=2C but it is definitely a struggle. :(= > )


Thank you=2C
 =3B-= > Jay


>= > >--_d2a02ece-d492-410e-88fb-fb53737d7219_-- From mika at async.caltech.edu Fri Sep 28 10:04:48 2012 From: mika at async.caltech.edu (mika at async.caltech.edu) Date: Fri, 28 Sep 2012 01:04:48 -0700 Subject: [M3devel] STL algorithms? sort/unique? In-Reply-To: <20120928075656.751E21A2082@async.async.caltech.edu> References: <20120928075656.751E21A2082@async.async.caltech.edu> Message-ID: <20120928080448.C80DD1A2082@async.async.caltech.edu> BTW I had the same experience when I first started using Modula-3. It was painful to jump through all its hoops, coming from C, where you can do whatever you want to whatever bits happen to be sloshing around your machine. C++ from what I have seen mainly lets you do that to more bits in fewer lines of code. But after a while I really came to appreciate the value of things like the language's telling me I'm using the wrong data structure instead of just letting me use the same "nice, terse, efficient" syntax to write a crappy program :-) mika writes: >You're using the wrong (abstract) data structure if you want sort and unique. > >A "sequence" is meant to be accessed sequentially... > >Not knowing precisely what you're doing it sounds like you might want a >SortedTable... you can get unique on insert and access it in increasing >or decreasing order. > > Mika > >Jay K writes: >>--_d2a02ece-d492-410e-88fb-fb53737d7219_ >>Content-Type: text/plain; charset="iso-8859-1" >>Content-Transfer-Encoding: quoted-printable >> >> I have an IntSeq.T with a bunch of integers. =20 >> What is a good terse efficient idiom for sort and unique? =20 >> >> In C++ I would say: vector a=3B a.push_back(...)=3B = >> a.push_back(...)=3B std::sort(a.begin()=2C a.end())=3B = >> a.resize(std::unique(a.begin()=2C a.end()) - a.begin())=3B for (aut= >>o i =3D a.begin()=3B i !=3D a.end()=3B ++i) { >> do stuff with *i }=20 >> Nice=2C terse=2C efficient. In Modula-3? =20 >> >>I know that unique is one of the easiest algorithms to manually write inlin= >>e=2Cbut I shouldn't have to. >> >>(I'm really trying to stay in Modula-3 here=2C but it is definitely a strug= >>gle. :( ) >> >>Thank you=2C - Jay >> >> = >> >>--_d2a02ece-d492-410e-88fb-fb53737d7219_ >>Content-Type: text/html; charset="iso-8859-1" >>Content-Transfer-Encoding: quoted-printable >> >> >> >> >>
 =3B  =3B =3BI have = >>an IntSeq.T with a bunch of integers. =3B  =3B =3B
>n style=3D"font-size: 12pt=3B "> =3B  =3B>-size: 12pt=3B "> =3BWhat is a good terse efficient idiom for so= >>rt and unique? =3B  =3B<= >>span style=3D"font-size: 12pt=3B "> =3B

>>
 =3B  =3B In C++ I would say:>ze: 12pt=3B "> =3B  =3B&= >>nbsp=3B
 =3B  = >>=3B =3Bvector<=3Bin= >>t>=3B a=3B =3B  =3B>an style=3D"font-size: 12pt=3B "> =3B
>ont-size: 12pt=3B "> =3B  =3B>=3B "> =3Ba.push_back(...)=3B>> =3B  =3B =3B>>
 =3B  =3B>n> =3Ba.push_back(...)=3B>an style=3D"font-size: 12pt=3B "> =3B  =3B>t-size: 12pt=3B "> =3B
>=3B "> =3B  =3B =3B<= >>/span>std::sort(a.begin()=2C a.end())=3B>> =3B  =3B =3B>>
 =3B  =3B>an style=3D"font-size: 12pt=3B "> =3Ba.resize(std::unique(a.begi= >>n()=2C a.end()) - a.begin())=3B =3B= >>  =3B =3B
>iv> =3B  =3B for (auto i =3D a.= >>begin()=3B i !=3D a.end()=3B ++i)
>: 12pt=3B "> =3B  =3B {
 =3B  =3B  =3B do stuff with= >> *i
 =3B  =3B = >>}
 =3B

>ze: 12pt=3B "> =3B  =3B&= >>nbsp=3BNice=2C terse=2C efficient.>"> =3B  =3B =3B>n>
 =3B  =3B>pan style=3D"font-size: 12pt=3B "> =3BIn Modula-3?>"font-size: 12pt=3B "> =3B  =3B>t=3B "> =3B


I know that = >>unique is one of the easiest algorithms to manually write inline=2C
>iv>but I shouldn't have to.


(I'm re= >>ally trying to stay in Modula-3 here=2C but it is definitely a struggle. :(= >> )


Thank you=2C
 =3B-= >> Jay


>>= >> >>--_d2a02ece-d492-410e-88fb-fb53737d7219_-- From jay.krell at cornell.edu Fri Sep 28 12:26:19 2012 From: jay.krell at cornell.edu (Jay K) Date: Fri, 28 Sep 2012 10:26:19 +0000 Subject: [M3devel] STL algorithms? sort/unique? In-Reply-To: <20120928080448.C80DD1A2082@async.async.caltech.edu> References: <20120928075656.751E21A2082@async.async.caltech.edu>, <20120928080448.C80DD1A2082@async.async.caltech.edu> Message-ID: The following is very efficient: run through a bunch of records, picking out one number from some of themappend those numbers to a growing vectorsort the vectorunique the vector sequence allows for random access..but only via a function...or maybe an iterator STL has this wonderful separation of algorithms from containers, via iterators.I suspect very few other libraries do.And it could be that most languages don't support it.It doesn't appear I can easily sort a sequence, unless I copy the data out into an array -- gross inefficiency. I've hacked something very manual together..and it is taking forever to get it to work. It turns out I can reasonably well bound the size of the data, so I'm using an open array...and I have to keep track of my position instead of using addhi/push_back.Not happy.At some point I might give up and write the backend in C++..at which point I might as well write a C++ frontend anywa. I absolutely do not want a sorted table and unique upon insert.That is much less efficient.What I'm describing uses temporarily larger working set but vastly less CPU.An array that gets sorted/uniqued occasionally, like just once.And not ongoing maintainence for every single add. - Jay > To: jay.krell at cornell.edu > CC: m3devel at elegosoft.com > Subject: Re: [M3devel] STL algorithms? sort/unique? > Date: Fri, 28 Sep 2012 01:04:48 -0700 > From: mika at async.caltech.edu > > > BTW I had the same experience when I first started using Modula-3. > It was painful to jump through all its hoops, coming from C, where you > can do whatever you want to whatever bits happen to be sloshing around > your machine. C++ from what I have seen mainly lets you do that to > more bits in fewer lines of code. > > But after a while I really came to appreciate the value of things like the > language's telling me I'm using the wrong data structure instead of > just letting me use the same "nice, terse, efficient" syntax to write > a crappy program :-) > > mika writes: > >You're using the wrong (abstract) data structure if you want sort and unique. > > > >A "sequence" is meant to be accessed sequentially... > > > >Not knowing precisely what you're doing it sounds like you might want a > >SortedTable... you can get unique on insert and access it in increasing > >or decreasing order. > > > > Mika > > > >Jay K writes: > >>--_d2a02ece-d492-410e-88fb-fb53737d7219_ > >>Content-Type: text/plain; charset="iso-8859-1" > >>Content-Transfer-Encoding: quoted-printable > >> > >> I have an IntSeq.T with a bunch of integers. =20 > >> What is a good terse efficient idiom for sort and unique? =20 > >> > >> In C++ I would say: vector a=3B a.push_back(...)=3B = > >> a.push_back(...)=3B std::sort(a.begin()=2C a.end())=3B = > >> a.resize(std::unique(a.begin()=2C a.end()) - a.begin())=3B for (aut= > >>o i =3D a.begin()=3B i !=3D a.end()=3B ++i) { > >> do stuff with *i }=20 > >> Nice=2C terse=2C efficient. In Modula-3? =20 > >> > >>I know that unique is one of the easiest algorithms to manually write inlin= > >>e=2Cbut I shouldn't have to. > >> > >>(I'm really trying to stay in Modula-3 here=2C but it is definitely a strug= > >>gle. :( ) > >> > >>Thank you=2C - Jay > >> > >> = > >> > >>--_d2a02ece-d492-410e-88fb-fb53737d7219_ > >>Content-Type: text/html; charset="iso-8859-1" > >>Content-Transfer-Encoding: quoted-printable > >> > >> > >> > >> > >>
 =3B  =3B =3BI have = > >>an IntSeq.T with a bunch of integers. =3B  =3B =3B
>>n style=3D"font-size: 12pt=3B "> =3B  =3B >>-size: 12pt=3B "> =3BWhat is a good terse efficient idiom for so= > >>rt and unique? =3B  =3B<= > >>span style=3D"font-size: 12pt=3B "> =3B

>>>
 =3B  =3B In C++ I would say: >>ze: 12pt=3B "> =3B  =3B&= > >>nbsp=3B
 =3B  = > >>=3B =3Bvector<=3Bin= > >>t>=3B a=3B =3B  =3B >>an style=3D"font-size: 12pt=3B "> =3B
>>ont-size: 12pt=3B "> =3B  =3B >>=3B "> =3Ba.push_back(...)=3B >>> =3B  =3B =3B >>>
 =3B  =3B >>n> =3Ba.push_back(...)=3B >>an style=3D"font-size: 12pt=3B "> =3B  =3B >>t-size: 12pt=3B "> =3B
>>=3B "> =3B  =3B =3B<= > >>/span>std::sort(a.begin()=2C a.end())=3B >>> =3B  =3B =3B >>>
 =3B  =3B >>an style=3D"font-size: 12pt=3B "> =3Ba.resize(std::unique(a.begi= > >>n()=2C a.end()) - a.begin())=3B =3B= > >>  =3B =3B
>>iv> =3B  =3B for (auto i =3D a.= > >>begin()=3B i !=3D a.end()=3B ++i)
>>: 12pt=3B "> =3B  =3B {
 =3B  =3B  =3B do stuff with= > >> *i
 =3B  =3B = > >>}
 =3B

>>ze: 12pt=3B "> =3B  =3B&= > >>nbsp=3BNice=2C terse=2C efficient. >>"> =3B  =3B =3B >>n>
 =3B  =3B >>pan style=3D"font-size: 12pt=3B "> =3BIn Modula-3? >>"font-size: 12pt=3B "> =3B  =3B >>t=3B "> =3B


I know that = > >>unique is one of the easiest algorithms to manually write inline=2C
>>iv>but I shouldn't have to.


(I'm re= > >>ally trying to stay in Modula-3 here=2C but it is definitely a struggle. :(= > >> )


Thank you=2C
 =3B-= > >> Jay


> >>= > >> > >>--_d2a02ece-d492-410e-88fb-fb53737d7219_-- -------------- next part -------------- An HTML attachment was scrubbed... URL: From jay.krell at cornell.edu Fri Sep 28 13:05:16 2012 From: jay.krell at cornell.edu (Jay K) Date: Fri, 28 Sep 2012 11:05:16 +0000 Subject: [M3devel] what "M3CG_MultiPass" is for In-Reply-To: <20120928105015.BF8D8CC92D@birch.elegosoft.com> References: <20120928105015.BF8D8CC92D@birch.elegosoft.com> Message-ID: Tony, this should demonstrate the direction I'm taking.See esp. "GetStructSizes_t" in M3C.m3.I'm able to insert additional passes over a straightforward in-memory form of M3CG.I'll be adding more. Just in M3C.m3.I think it will provide for a nice factoring of the code. - Jay > Date: Fri, 28 Sep 2012 12:50:15 +0000 > To: m3commit at elegosoft.com > From: jkrell at elego.de > Subject: [M3commit] CVS Update: cm3 > > CVSROOT: /usr/cvs > Changes by: jkrell at birch. 12/09/28 12:50:15 > > Modified files: > cm3/m3-sys/m3back/src/: M3C.m3 > ./: M3C.m3 > cm3/m3-sys/m3middle/src/: M3CG_DoNothing.i3 M3CG_DoNothing.m3 > M3CG_MultiPass.i3 M3CG_MultiPass.m3 > m3makefile > > Log message: > first use of multipass: > make an extra pass to discover all struct sizes, > so all structs can be predeclared, and no extra > (eventually to be replaced by better typing, but this > is useful in the current context) > > Also, to ensure M3C.T implements all METHODS of M3CG_Ops.Public, > derive it from M3CG_AssertFalse.T instead of the bogus M3CG.T. > > M3CG_MultiPass: > in end_unit, flatten into plain public array instead of slower sequence > separate out per-op also, since sometims that provides for optimization > -------------- next part -------------- An HTML attachment was scrubbed... URL: From jay.krell at cornell.edu Fri Sep 28 21:31:15 2012 From: jay.krell at cornell.edu (Jay K) Date: Fri, 28 Sep 2012 19:31:15 +0000 Subject: [M3devel] deeper meaning of in_memory? In-Reply-To: References: , Message-ID: > structs volatile Mainly paranoia.But I do wonder if the breakage I saw in gcc's "sra" optimization pass (structure replaced by aggregate) by feeding it trees can be reproduced from C. I should look into that... - Jay Subject: Re: [M3devel] deeper meaning of in_memory? From: hosking at cs.purdue.edu Date: Fri, 28 Sep 2012 10:11:49 -0400 CC: m3devel at elegosoft.com To: jay.krell at cornell.edu in_memory does not mean volatile. It is simply a sign that its address is needed.So, yes, taking its address is good enough.An example of a local in memory is something passed by VAR. So, NOT VOLATILE. Why do structs need to be C volatile? On Sep 27, 2012, at 10:57 PM, Jay K wrote:In M3CG, what is the deeper meaning of in_memory?I know it means -- "put the thing in memory".But why and exactly what? Presumably it can also be in a register, just that the in-memory value must be kept up to date.Like, stores should be volatile, but reads don't have to be?Does it mean the value will be used in an exception/finally handler?Maybe reads do need to be volatile? Maybe it is accessed by another thread w/o a lock? If I take the address of something, is that good enough? I should just look where m3front uses it, I know.For now I'll probably take it to mean "volatile".I already mark all structs as volatile. But I don't make everything volatile (like how m3cc long did). Thanks, - Jay -------------- next part -------------- An HTML attachment was scrubbed... URL: From jay.krell at cornell.edu Sat Sep 29 00:47:27 2012 From: jay.krell at cornell.edu (Jay K) Date: Fri, 28 Sep 2012 22:47:27 +0000 Subject: [M3devel] deeper meaning of in_memory? In-Reply-To: <1DE4822C-E51B-41CE-A626-4BB72AE9D7C9@cs.purdue.edu> References: , , <1DE4822C-E51B-41CE-A626-4BB72AE9D7C9@cs.purdue.edu> Message-ID: I don't know. It makes me nervous.I though we effectively turn off TBAA in m3cc, and I can imagine what our trees looke like in C, and it seems my C code might look about the same. As well, you know..it seems like a bug in gcc, at which point, your system of thinking about things breaks down and we have to understand the actual buggy behavior instead of the expected reasonable behavior. For now I'm not passing any optimizer flags to the C compiler. I don't remember if I tried that yet. I have to keep in mind priorities: support uplevel locals in sub-blocks -- so m3-tk compiles reorder stuff so module data is initialized, or at least fully declared, up front -- so the code is valid C++ -- I currently run afoul of a corner case and generate valid C that isn't valid C++ maybe only output helper functions that are used -- i.e. work on gcc -Wall -- this is easy with the multipass support move all imports/declarations up front, instead of at arbitrary places -- just slight cleanliess -- easy with the multipass support only declare frame types when needed -- easy now too, slightly cleaner code Work on getting structs/records declared strongly typed -- should be easy.Work on making loads/stores be field access -- slightly challenging to do this efficiently, since we have to map offset/sizes to fields. Somewhere along the line also, I have to stop producing all these temporary strings and produce a proper typed hiearchical representation -- like an "expression", a "plus node" with two sub expressions. So for example, I don't cast same type to same type. It will actually likely resemble the gcc trees! Sprinkling volatile on every variable declaration (but not access) is not a big deal right now.And volatile might be a good idea -- separate mail on this. - Jay Subject: Re: [M3devel] deeper meaning of in_memory? From: hosking at cs.purdue.edu Date: Fri, 28 Sep 2012 18:27:30 -0400 CC: m3devel at elegosoft.com To: jay.krell at cornell.edu Good question. But if you are good about making the structs anonymous and taking their address then TBAA in C should not give you problems. On Sep 28, 2012, at 3:31 PM, Jay K wrote:> structs volatile Mainly paranoia.But I do wonder if the breakage I saw in gcc's "sra" optimization pass (structure replaced by aggregate) by feeding it trees can be reproduced from C. I should look into that... - Jay Subject: Re: [M3devel] deeper meaning of in_memory? From: hosking at cs.purdue.edu Date: Fri, 28 Sep 2012 10:11:49 -0400 CC: m3devel at elegosoft.com To: jay.krell at cornell.edu in_memory does not mean volatile. It is simply a sign that its address is needed.So, yes, taking its address is good enough.An example of a local in memory is something passed by VAR. So, NOT VOLATILE. Why do structs need to be C volatile? On Sep 27, 2012, at 10:57 PM, Jay K wrote:In M3CG, what is the deeper meaning of in_memory?I know it means -- "put the thing in memory".But why and exactly what? Presumably it can also be in a register, just that the in-memory value must be kept up to date.Like, stores should be volatile, but reads don't have to be?Does it mean the value will be used in an exception/finally handler?Maybe reads do need to be volatile? Maybe it is accessed by another thread w/o a lock? If I take the address of something, is that good enough? I should just look where m3front uses it, I know.For now I'll probably take it to mean "volatile".I already mark all structs as volatile. But I don't make everything volatile (like how m3cc long did). Thanks, - Jay -------------- next part -------------- An HTML attachment was scrubbed... URL: From jay.krell at cornell.edu Sat Sep 29 01:19:19 2012 From: jay.krell at cornell.edu (Jay K) Date: Fri, 28 Sep 2012 23:19:19 +0000 Subject: [M3devel] volatile, frames, and precise GC? Message-ID: I repeatedly read that "precise GC" is difficult/impossible to achieve when producing C. That the C compiler will stash things in registers, it will spill the registers to difficult/impossible to know locations. And this is close to true, and it worse than people realize (or at least I ralized) -- non-volatile registers get spilled in functions you call. They get spilled to varying places depending on the current callstack. So instead of "precise GC", runtimes resort to looking at registers and scanning every location in the stack. Including garbage left behind by returned functions (unless you zero the frame/registers upon function exit). Including confusing integers for pointers possibly (mostly unlikely, but consider a 32bit program processing a large file, over 4GB in size, and storing some file offsets -- they'll be all over the place). So, the question is..what to do? What can be done? What about a design where locals and params are put in "frame" struct, and everything is volatile? Then what?Put the frame struct pointer somewhere? (for that matter -- no struct, no fixed layout, but take the address of each local and put it..somewhere?) Of course, integers and floats, don't care.They can be left "free floating" as usual (unless they are uplevel, of course). What would one then do? Clearly this is the point of M3CG.init_offset. But what would one do in portable C or C++?Maintain a per-thread linked list of frame pointers?i.e. arrange for portable stack walking? Somewhat alternatively, combine this with preemptive suspend?One could imagine having two sets of locals -- "normal" "free floating" non-volatile ones and the frame. Preemptive suspend is I think best implemented by occasionally calling out to a function.But it can be done occasionally reading a global, and either acting on its value, or the global's page being made inaccessible and triggering a fault. "acting on its value" make for larger code; triggering a fault is slow and less portable, but is the smallest code. I like the idea of calling a function. So then, to further develop the idea..and slow things down more...before calling the "Should I Suspend" function, one could store all the "free floating" locals into the frame, and load them back up after the call. Better yet, "should I suspend" could return a boolean as to if any live data was moved, and only if that is true would the non-volatiles be restored from the volatiles. But that is still kind of big and slow. It is worse than this though.It isn't just calls out to suspend, it is called to any function, which themselves might call out to suspend. You'd want to "home" all locals to the "frame" before any function call, and restore them afterward. To be fair, this is analogous to how things work anyway, with regard to register save/restore.Compiler would be left with no registers to save/restore..we'd be doing it for it, essentially. Do we have a moving/compacting GC? I think so. I think it is desirable. To prevent heap fragmentation.If the GC didn't move/compact, then this idea can be done a little more efficiently -- then you just have to expose live data to the GC at findable places. But you don't have to keep it in sync as aggressively. You could just make all writes volatile, but not reads, for example. Alternatively...one would have to study how well C compilers optimize..but maybe something in between..maybe put everything in frame struct, not volatile, take the address of the struct before any function call (heck -- pass it as an extra last parameter..given how we violate function signatures already)..and leave the C comiler to save/restore as needed -- i.e. if a variable is dead, it wouldn't bother.Just because something is in a frame struct, doesn't mean the C compiler won't enregister it across runs of code. Thoughts?Ideas? - Jay -------------- next part -------------- An HTML attachment was scrubbed... URL: From jay.krell at cornell.edu Sat Sep 29 02:06:01 2012 From: jay.krell at cornell.edu (Jay K) Date: Sat, 29 Sep 2012 00:06:01 +0000 Subject: [M3devel] volatile, frames, and precise GC? In-Reply-To: References: Message-ID: I hate to sound like Daniel, but Binging for "precise garbage collection" finds promising stuff.e.g. "Magpie" that transforms C:http://www.cs.utah.edu/~regehr/papers/ismm15-rafkind.pdf http://www.cs.utah.edu/~awick/awick-dissertation.pdf A Java to C compiler with precise GC:http://www.cs.york.ac.uk/rts/docs/CODES-EMSOFT-CASES-2006/cases/p35.pdf They (Magpie) do include elements I allude to -- taking the addresses of locals, having a runtime walkable frame list.. I haven't gotten to the parts that talk about the performance. :) We should work toward resembling these systems? - Jay From: jay.krell at cornell.edu To: m3devel at elegosoft.com Date: Fri, 28 Sep 2012 23:19:19 +0000 Subject: [M3devel] volatile, frames, and precise GC? I repeatedly read that "precise GC" is difficult/impossible to achieve when producing C. That the C compiler will stash things in registers, it will spill the registers to difficult/impossible to know locations. And this is close to true, and it worse than people realize (or at least I ralized) -- non-volatile registers get spilled in functions you call. They get spilled to varying places depending on the current callstack. So instead of "precise GC", runtimes resort to looking at registers and scanning every location in the stack. Including garbage left behind by returned functions (unless you zero the frame/registers upon function exit). Including confusing integers for pointers possibly (mostly unlikely, but consider a 32bit program processing a large file, over 4GB in size, and storing some file offsets -- they'll be all over the place). So, the question is..what to do? What can be done? What about a design where locals and params are put in "frame" struct, and everything is volatile? Then what? Put the frame struct pointer somewhere? (for that matter -- no struct, no fixed layout, but take the address of each local and put it..somewhere?) Of course, integers and floats, don't care. They can be left "free floating" as usual (unless they are uplevel, of course). What would one then do? Clearly this is the point of M3CG.init_offset. But what would one do in portable C or C++? Maintain a per-thread linked list of frame pointers? i.e. arrange for portable stack walking? Somewhat alternatively, combine this with preemptive suspend? One could imagine having two sets of locals -- "normal" "free floating" non-volatile ones and the frame. Preemptive suspend is I think best implemented by occasionally calling out to a function. But it can be done occasionally reading a global, and either acting on its value, or the global's page being made inaccessible and triggering a fault. "acting on its value" make for larger code; triggering a fault is slow and less portable, but is the smallest code. I like the idea of calling a function. So then, to further develop the idea..and slow things down more...before calling the "Should I Suspend" function, one could store all the "free floating" locals into the frame, and load them back up after the call. Better yet, "should I suspend" could return a boolean as to if any live data was moved, and only if that is true would the non-volatiles be restored from the volatiles. But that is still kind of big and slow. It is worse than this though. It isn't just calls out to suspend, it is called to any function, which themselves might call out to suspend. You'd want to "home" all locals to the "frame" before any function call, and restore them afterward. To be fair, this is analogous to how things work anyway, with regard to register save/restore. Compiler would be left with no registers to save/restore..we'd be doing it for it, essentially. Do we have a moving/compacting GC? I think so. I think it is desirable. To prevent heap fragmentation. If the GC didn't move/compact, then this idea can be done a little more efficiently -- then you just have to expose live data to the GC at findable places. But you don't have to keep it in sync as aggressively. You could just make all writes volatile, but not reads, for example. Alternatively...one would have to study how well C compilers optimize..but maybe something in between..maybe put everything in frame struct, not volatile, take the address of the struct before any function call (heck -- pass it as an extra last parameter..given how we violate function signatures already)..and leave the C comiler to save/restore as needed -- i.e. if a variable is dead, it wouldn't bother. Just because something is in a frame struct, doesn't mean the C compiler won't enregister it across runs of code. Thoughts? Ideas? - Jay -------------- next part -------------- An HTML attachment was scrubbed... URL: From jay.krell at cornell.edu Sat Sep 29 03:51:42 2012 From: jay.krell at cornell.edu (Jay K) Date: Sat, 29 Sep 2012 01:51:42 +0000 Subject: [M3devel] volatile, frames, and precise GC? In-Reply-To: References: , Message-ID: Clarification: I'm not worried that we have bugs, esp. via routing through my C backend, esp. routed through an optimization C compiler. I can see that what I'm going isn't so different than using the gcc backend. I'm suggesting that we endeavor to have precise GC. That we be precise instead of "conservative". The "Magpie" paper says they saw significant gains. "Conservative" ended up too conservative. Programs has to be restarted fairly often to free up memory. "Precise" let them run programs longer/forever, because they succeded much more at actually collecting garbage. I need to read more there though..like what of the performance costs. The Java paper too. > just now unless you think you might be hiding pointers from the collector > (say in thread-locals like pthread thread-specifics). Not a worry I have. We do have that one thread local, of course. But isn't traced. (I'm really hoping to remove/move/optimize it in some modes, as I've said -- when generating Microsoft C or C++ or perhaps Digital/Tru64/VMS C, we can do something much better.) > Going the volatile route is severe overkill and will destroy performance. What about the manual save/restore at function call boundaries, but not otherwise volatile? (It is cool to be in the compiler and be able to consider these transforms. Though my "framework" is still getting there -- so far "too much single pass" and "too many strings" -- I will be fixing these...) - Jay Subject: Re: [M3devel] volatile, frames, and precise GC? From: hosking at cs.purdue.edu Date: Fri, 28 Sep 2012 21:41:59 -0400 CC: m3devel at elegosoft.com To: jay.krell at cornell.edu Jay, the situation is not quite so bad as that, so long as we know where to find all of the potential pointers from the imprecise stacks. The collector we have now is a non-moving collector for anything referenced from the imprecise stacks (it is "conservative"). Bad things happen if we allow references to get stashed in places we can?t find them. Otherwise we will be ok. I don?t believe there are optimizations that current C compilers perform that will prevent us finding all the candidate pointers. This is the reason that the Boehm (conservative) collector is able to function with C and C++, where it is fairly widely used. There are techniques for improving precision for stack references but at some performance cost, as you allude to. But, my advice is not to worry about this just now unless you think you might be hiding pointers from the collector (say in thread-locals like pthread thread-specifics). Going the volatile route is severe overkill and will destroy performance. On Sep 28, 2012, at 7:19 PM, Jay K wrote:I repeatedly read that "precise GC" is difficult/impossible to achieve when producing C. That the C compiler will stash things in registers, it will spill the registers to difficult/impossible to know locations. And this is close to true, and it worse than people realize (or at least I ralized) -- non-volatile registers get spilled in functions you call. They get spilled to varying places depending on the current callstack. So instead of "precise GC", runtimes resort to looking at registers and scanning every location in the stack. Including garbage left behind by returned functions (unless you zero the frame/registers upon function exit). Including confusing integers for pointers possibly (mostly unlikely, but consider a 32bit program processing a large file, over 4GB in size, and storing some file offsets -- they'll be all over the place). So, the question is..what to do? What can be done? What about a design where locals and params are put in "frame" struct, and everything is volatile? Then what? Put the frame struct pointer somewhere? (for that matter -- no struct, no fixed layout, but take the address of each local and put it..somewhere?) Of course, integers and floats, don't care. They can be left "free floating" as usual (unless they are uplevel, of course). What would one then do? Clearly this is the point of M3CG.init_offset. But what would one do in portable C or C++? Maintain a per-thread linked list of frame pointers? i.e. arrange for portable stack walking? Somewhat alternatively, combine this with preemptive suspend? One could imagine having two sets of locals -- "normal" "free floating" non-volatile ones and the frame. Preemptive suspend is I think best implemented by occasionally calling out to a function. But it can be done occasionally reading a global, and either acting on its value, or the global's page being made inaccessible and triggering a fault. "acting on its value" make for larger code; triggering a fault is slow and less portable, but is the smallest code. I like the idea of calling a function. So then, to further develop the idea..and slow things down more...before calling the "Should I Suspend" function, one could store all the "free floating" locals into the frame, and load them back up after the call. Better yet, "should I suspend" could return a boolean as to if any live data was moved, and only if that is true would the non-volatiles be restored from the volatiles. But that is still kind of big and slow. It is worse than this though. It isn't just calls out to suspend, it is called to any function, which themselves might call out to suspend. You'd want to "home" all locals to the "frame" before any function call, and restore them afterward. To be fair, this is analogous to how things work anyway, with regard to register save/restore. Compiler would be left with no registers to save/restore..we'd be doing it for it, essentially. Do we have a moving/compacting GC? I think so. I think it is desirable. To prevent heap fragmentation. If the GC didn't move/compact, then this idea can be done a little more efficiently -- then you just have to expose live data to the GC at findable places. But you don't have to keep it in sync as aggressively. You could just make all writes volatile, but not reads, for example. Alternatively...one would have to study how well C compilers optimize..but maybe something in between..maybe put everything in frame struct, not volatile, take the address of the struct before any function call (heck -- pass it as an extra last parameter..given how we violate function signatures already)..and leave the C comiler to save/restore as needed -- i.e. if a variable is dead, it wouldn't bother. Just because something is in a frame struct, doesn't mean the C compiler won't enregister it across runs of code. Thoughts? Ideas? - Jay -------------- next part -------------- An HTML attachment was scrubbed... URL: From hosking at cs.purdue.edu Sat Sep 29 05:38:56 2012 From: hosking at cs.purdue.edu (Antony Hosking) Date: Fri, 28 Sep 2012 23:38:56 -0400 Subject: [M3devel] volatile, frames, and precise GC? In-Reply-To: References: Message-ID: <1436593A-7661-473F-A865-4B65BEFEAA0C@cs.purdue.edu> None of these techniques stack up against having the compiler cooperate and emit proper stack descriptors. We will have better luck with LLVM. On Sep 28, 2012, at 8:06 PM, Jay K wrote: > I hate to sound like Daniel, but Binging for "precise garbage collection" finds promising stuff. > e.g. > > > "Magpie" that transforms C: > http://www.cs.utah.edu/~regehr/papers/ismm15-rafkind.pdf > http://www.cs.utah.edu/~awick/awick-dissertation.pdf > > > A Java to C compiler with precise GC: > http://www.cs.york.ac.uk/rts/docs/CODES-EMSOFT-CASES-2006/cases/p35.pdf > > > They (Magpie) do include elements I allude to -- taking the addresses of locals, having a runtime walkable frame list.. I haven't gotten to the parts that talk about the performance. :) > > > We should work toward resembling these systems? > > > - Jay > From: jay.krell at cornell.edu > To: m3devel at elegosoft.com > Date: Fri, 28 Sep 2012 23:19:19 +0000 > Subject: [M3devel] volatile, frames, and precise GC? > > I repeatedly read that "precise GC" is difficult/impossible to achieve when producing C. > > > That the C compiler will stash things in registers, it will spill the registers to difficult/impossible to know locations. And this is close to true, and it worse than people realize (or at least I ralized) -- non-volatile registers get spilled in functions you call. They get spilled to varying places depending on the current callstack. > > > So instead of "precise GC", runtimes resort to looking at registers and scanning every location in the stack. Including garbage left behind by returned functions (unless you zero the frame/registers upon function exit). Including confusing integers for pointers possibly (mostly unlikely, but consider a 32bit program processing a large file, over 4GB in size, and storing some file offsets -- they'll be all over the place). > > > So, the question is..what to do? What can be done? > > > What about a design where locals and params are put in "frame" struct, and everything is volatile? > > > Then what? > Put the frame struct pointer somewhere? > (for that matter -- no struct, no fixed layout, but take the address of each local and put it..somewhere?) > > > Of course, integers and floats, don't care. > They can be left "free floating" as usual (unless they are uplevel, of course). > > > What would one then do? > > > Clearly this is the point of M3CG.init_offset. > > > But what would one do in portable C or C++? > Maintain a per-thread linked list of frame pointers? > i.e. arrange for portable stack walking? > > > Somewhat alternatively, combine this with preemptive suspend? > One could imagine having two sets of locals -- "normal" "free floating" non-volatile ones and the frame. > > > Preemptive suspend is I think best implemented by occasionally calling out to a function. > But it can be done occasionally reading a global, and either acting on its value, or the global's page being made inaccessible and triggering a fault. "acting on its value" make for larger code; triggering a fault is slow and less portable, but is the smallest code. I like the idea of calling a function. > > > So then, to further develop the idea..and slow things down more...before calling the "Should I Suspend" function, one could store all the "free floating" locals into the frame, and load them back up after the call. Better yet, "should I suspend" could return a boolean as to if any live data was moved, and only if that is true would the non-volatiles be restored from the volatiles. > > > But that is still kind of big and slow. > > > It is worse than this though. > It isn't just calls out to suspend, it is called to any function, which themselves might call out to suspend. You'd want to "home" all locals to the "frame" before any function call, and restore them afterward. > > > To be fair, this is analogous to how things work anyway, with regard to register save/restore. > Compiler would be left with no registers to save/restore..we'd be doing it for it, essentially. > > > Do we have a moving/compacting GC? I think so. I think it is desirable. To prevent heap fragmentation. > If the GC didn't move/compact, then this idea can be done a little more efficiently -- then you just have to expose live data to the GC at findable places. But you don't have to keep it in sync as aggressively. You could just make all writes volatile, but not reads, for example. > > > Alternatively...one would have to study how well C compilers optimize..but maybe something in between..maybe put everything in frame struct, not volatile, take the address of the struct before any function call (heck -- pass it as an extra last parameter..given how we violate function signatures already)..and leave the C comiler to save/restore as needed -- i.e. if a variable is dead, it wouldn't bother. > Just because something is in a frame struct, doesn't mean the C compiler won't enregister it across runs of code. > > > Thoughts? > Ideas? > > > - Jay -------------- next part -------------- An HTML attachment was scrubbed... URL: From hosking at cs.purdue.edu Sat Sep 29 03:41:59 2012 From: hosking at cs.purdue.edu (Antony Hosking) Date: Fri, 28 Sep 2012 21:41:59 -0400 Subject: [M3devel] volatile, frames, and precise GC? In-Reply-To: References: Message-ID: Jay, the situation is not quite so bad as that, so long as we know where to find all of the potential pointers from the imprecise stacks. The collector we have now is a non-moving collector for anything referenced from the imprecise stacks (it is "conservative"). Bad things happen if we allow references to get stashed in places we can?t find them. Otherwise we will be ok. I don?t believe there are optimizations that current C compilers perform that will prevent us finding all the candidate pointers. This is the reason that the Boehm (conservative) collector is able to function with C and C++, where it is fairly widely used. There are techniques for improving precision for stack references but at some performance cost, as you allude to. But, my advice is not to worry about this just now unless you think you might be hiding pointers from the collector (say in thread-locals like pthread thread-specifics). Going the volatile route is severe overkill and will destroy performance. On Sep 28, 2012, at 7:19 PM, Jay K wrote: > I repeatedly read that "precise GC" is difficult/impossible to achieve when producing C. > > > That the C compiler will stash things in registers, it will spill the registers to difficult/impossible to know locations. And this is close to true, and it worse than people realize (or at least I ralized) -- non-volatile registers get spilled in functions you call. They get spilled to varying places depending on the current callstack. > > > So instead of "precise GC", runtimes resort to looking at registers and scanning every location in the stack. Including garbage left behind by returned functions (unless you zero the frame/registers upon function exit). Including confusing integers for pointers possibly (mostly unlikely, but consider a 32bit program processing a large file, over 4GB in size, and storing some file offsets -- they'll be all over the place). > > > So, the question is..what to do? What can be done? > > > What about a design where locals and params are put in "frame" struct, and everything is volatile? > > > Then what? > Put the frame struct pointer somewhere? > (for that matter -- no struct, no fixed layout, but take the address of each local and put it..somewhere?) > > > Of course, integers and floats, don't care. > They can be left "free floating" as usual (unless they are uplevel, of course). > > > What would one then do? > > > Clearly this is the point of M3CG.init_offset. > > > But what would one do in portable C or C++? > Maintain a per-thread linked list of frame pointers? > i.e. arrange for portable stack walking? > > > Somewhat alternatively, combine this with preemptive suspend? > One could imagine having two sets of locals -- "normal" "free floating" non-volatile ones and the frame. > > > Preemptive suspend is I think best implemented by occasionally calling out to a function. > But it can be done occasionally reading a global, and either acting on its value, or the global's page being made inaccessible and triggering a fault. "acting on its value" make for larger code; triggering a fault is slow and less portable, but is the smallest code. I like the idea of calling a function. > > > So then, to further develop the idea..and slow things down more...before calling the "Should I Suspend" function, one could store all the "free floating" locals into the frame, and load them back up after the call. Better yet, "should I suspend" could return a boolean as to if any live data was moved, and only if that is true would the non-volatiles be restored from the volatiles. > > > But that is still kind of big and slow. > > > It is worse than this though. > It isn't just calls out to suspend, it is called to any function, which themselves might call out to suspend. You'd want to "home" all locals to the "frame" before any function call, and restore them afterward. > > > To be fair, this is analogous to how things work anyway, with regard to register save/restore. > Compiler would be left with no registers to save/restore..we'd be doing it for it, essentially. > > > Do we have a moving/compacting GC? I think so. I think it is desirable. To prevent heap fragmentation. > If the GC didn't move/compact, then this idea can be done a little more efficiently -- then you just have to expose live data to the GC at findable places. But you don't have to keep it in sync as aggressively. You could just make all writes volatile, but not reads, for example. > > > Alternatively...one would have to study how well C compilers optimize..but maybe something in between..maybe put everything in frame struct, not volatile, take the address of the struct before any function call (heck -- pass it as an extra last parameter..given how we violate function signatures already)..and leave the C comiler to save/restore as needed -- i.e. if a variable is dead, it wouldn't bother. > Just because something is in a frame struct, doesn't mean the C compiler won't enregister it across runs of code. > > > Thoughts? > Ideas? > > > - Jay -------------- next part -------------- An HTML attachment was scrubbed... URL: From hosking at cs.purdue.edu Sat Sep 29 00:27:30 2012 From: hosking at cs.purdue.edu (Antony Hosking) Date: Fri, 28 Sep 2012 18:27:30 -0400 Subject: [M3devel] deeper meaning of in_memory? In-Reply-To: References: , Message-ID: <1DE4822C-E51B-41CE-A626-4BB72AE9D7C9@cs.purdue.edu> Good question. But if you are good about making the structs anonymous and taking their address then TBAA in C should not give you problems. On Sep 28, 2012, at 3:31 PM, Jay K wrote: > > structs volatile > > Mainly paranoia. > But I do wonder if the breakage I saw in gcc's "sra" optimization pass (structure replaced by aggregate) by feeding it trees can be reproduced from C. I should look into that... > > > - Jay > > Subject: Re: [M3devel] deeper meaning of in_memory? > From: hosking at cs.purdue.edu > Date: Fri, 28 Sep 2012 10:11:49 -0400 > CC: m3devel at elegosoft.com > To: jay.krell at cornell.edu > > in_memory does not mean volatile. It is simply a sign that its address is needed. > So, yes, taking its address is good enough. > An example of a local in memory is something passed by VAR. > > So, NOT VOLATILE. > > Why do structs need to be C volatile? > > On Sep 27, 2012, at 10:57 PM, Jay K wrote: > > In M3CG, what is the deeper meaning of in_memory? > I know it means -- "put the thing in memory". > But why and exactly what? > Presumably it can also be in a register, just that the in-memory value must be kept up to date. > Like, stores should be volatile, but reads don't have to be? > Does it mean the value will be used in an exception/finally handler? > Maybe reads do need to be volatile? Maybe it is accessed by another thread w/o a lock? > > > If I take the address of something, is that good enough? > > > I should just look where m3front uses it, I know. > For now I'll probably take it to mean "volatile". > I already mark all structs as volatile. But I don't make everything volatile (like how m3cc long did). > > > Thanks, > - Jay -------------- next part -------------- An HTML attachment was scrubbed... URL: From hosking at cs.purdue.edu Fri Sep 28 16:11:49 2012 From: hosking at cs.purdue.edu (Antony Hosking) Date: Fri, 28 Sep 2012 10:11:49 -0400 Subject: [M3devel] deeper meaning of in_memory? In-Reply-To: References: Message-ID: in_memory does not mean volatile. It is simply a sign that its address is needed. So, yes, taking its address is good enough. An example of a local in memory is something passed by VAR. So, NOT VOLATILE. Why do structs need to be C volatile? On Sep 27, 2012, at 10:57 PM, Jay K wrote: > In M3CG, what is the deeper meaning of in_memory? > I know it means -- "put the thing in memory". > But why and exactly what? > Presumably it can also be in a register, just that the in-memory value must be kept up to date. > Like, stores should be volatile, but reads don't have to be? > Does it mean the value will be used in an exception/finally handler? > Maybe reads do need to be volatile? Maybe it is accessed by another thread w/o a lock? > > > If I take the address of something, is that good enough? > > > I should just look where m3front uses it, I know. > For now I'll probably take it to mean "volatile". > I already mark all structs as volatile. But I don't make everything volatile (like how m3cc long did). > > > Thanks, > - Jay > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From hosking at cs.purdue.edu Sat Sep 29 04:16:13 2012 From: hosking at cs.purdue.edu (Antony Hosking) Date: Fri, 28 Sep 2012 22:16:13 -0400 Subject: [M3devel] volatile, frames, and precise GC? In-Reply-To: References: , Message-ID: I don?t doubt that we would get gains from precise GC. I would just much rather rely on a decent compiler infrastructure (like LLVM) to deliver precision for us than get into the games that Magpie plays. As for the manual save/restore at function boundaries: yes that is killer overhead. Better to have cooperative stack scanning at thread safepoints. On Sep 28, 2012, at 9:51 PM, Jay K wrote: > Clarification: I'm not worried that we have bugs, esp. via routing through my C backend, esp. routed through an optimization C compiler. I can see that what I'm going isn't so different than using the gcc backend. > > > I'm suggesting that we endeavor to have precise GC. > That we be precise instead of "conservative". > > > The "Magpie" paper says they saw significant gains. > "Conservative" ended up too conservative. > Programs has to be restarted fairly often to free up memory. > "Precise" let them run programs longer/forever, because they succeded much more at actually collecting garbage. I need to read more there though..like what of the performance costs. The Java paper too. > > > > just now unless you think you might be hiding pointers from the collector > > (say in thread-locals like pthread thread-specifics). > > > Not a worry I have. We do have that one thread local, of course. But isn't traced. > (I'm really hoping to remove/move/optimize it in some modes, as I've said -- when generating Microsoft C or C++ or perhaps Digital/Tru64/VMS C, we can do something much better.) > > > > Going the volatile route is severe overkill and will destroy performance. > > > > What about the manual save/restore at function call boundaries, but not otherwise volatile? > > > (It is cool to be in the compiler and be able to consider these transforms. Though my "framework" is still getting there -- so far "too much single pass" and "too many strings" -- I will be fixing these...) > > > - Jay > > Subject: Re: [M3devel] volatile, frames, and precise GC? > From: hosking at cs.purdue.edu > Date: Fri, 28 Sep 2012 21:41:59 -0400 > CC: m3devel at elegosoft.com > To: jay.krell at cornell.edu > > Jay, the situation is not quite so bad as that, so long as we know where to find all of the potential pointers from the imprecise stacks. The collector we have now is a non-moving collector for anything referenced from the imprecise stacks (it is "conservative"). Bad things happen if we allow references to get stashed in places we can?t find them. Otherwise we will be ok. I don?t believe there are optimizations that current C compilers perform that will prevent us finding all the candidate pointers. This is the reason that the Boehm (conservative) collector is able to function with C and C++, where it is fairly widely used. There are techniques for improving precision for stack references but at some performance cost, as you allude to. But, my advice is not to worry about this just now unless you think you might be hiding pointers from the collector (say in thread-locals like pthread thread-specifics). Going the volatile route is severe overkill and will destroy performance. > > On Sep 28, 2012, at 7:19 PM, Jay K wrote: > > I repeatedly read that "precise GC" is difficult/impossible to achieve when producing C. > > > That the C compiler will stash things in registers, it will spill the registers to difficult/impossible to know locations. And this is close to true, and it worse than people realize (or at least I ralized) -- non-volatile registers get spilled in functions you call. They get spilled to varying places depending on the current callstack. > > > So instead of "precise GC", runtimes resort to looking at registers and scanning every location in the stack. Including garbage left behind by returned functions (unless you zero the frame/registers upon function exit). Including confusing integers for pointers possibly (mostly unlikely, but consider a 32bit program processing a large file, over 4GB in size, and storing some file offsets -- they'll be all over the place). > > > So, the question is..what to do? What can be done? > > > What about a design where locals and params are put in "frame" struct, and everything is volatile? > > > Then what? > Put the frame struct pointer somewhere? > (for that matter -- no struct, no fixed layout, but take the address of each local and put it..somewhere?) > > > Of course, integers and floats, don't care. > They can be left "free floating" as usual (unless they are uplevel, of course). > > > What would one then do? > > > Clearly this is the point of M3CG.init_offset. > > > But what would one do in portable C or C++? > Maintain a per-thread linked list of frame pointers? > i.e. arrange for portable stack walking? > > > Somewhat alternatively, combine this with preemptive suspend? > One could imagine having two sets of locals -- "normal" "free floating" non-volatile ones and the frame. > > > Preemptive suspend is I think best implemented by occasionally calling out to a function. > But it can be done occasionally reading a global, and either acting on its value, or the global's page being made inaccessible and triggering a fault. "acting on its value" make for larger code; triggering a fault is slow and less portable, but is the smallest code. I like the idea of calling a function. > > > So then, to further develop the idea..and slow things down more...before calling the "Should I Suspend" function, one could store all the "free floating" locals into the frame, and load them back up after the call. Better yet, "should I suspend" could return a boolean as to if any live data was moved, and only if that is true would the non-volatiles be restored from the volatiles. > > > But that is still kind of big and slow. > > > It is worse than this though. > It isn't just calls out to suspend, it is called to any function, which themselves might call out to suspend. You'd want to "home" all locals to the "frame" before any function call, and restore them afterward. > > > To be fair, this is analogous to how things work anyway, with regard to register save/restore. > Compiler would be left with no registers to save/restore..we'd be doing it for it, essentially. > > > Do we have a moving/compacting GC? I think so. I think it is desirable. To prevent heap fragmentation. > If the GC didn't move/compact, then this idea can be done a little more efficiently -- then you just have to expose live data to the GC at findable places. But you don't have to keep it in sync as aggressively. You could just make all writes volatile, but not reads, for example. > > > Alternatively...one would have to study how well C compilers optimize..but maybe something in between..maybe put everything in frame struct, not volatile, take the address of the struct before any function call (heck -- pass it as an extra last parameter..given how we violate function signatures already)..and leave the C comiler to save/restore as needed -- i.e. if a variable is dead, it wouldn't bother. > Just because something is in a frame struct, doesn't mean the C compiler won't enregister it across runs of code. > > > Thoughts? > Ideas? > > > - Jay -------------- next part -------------- An HTML attachment was scrubbed... URL: From dabenavidesd at yahoo.es Fri Sep 28 18:07:31 2012 From: dabenavidesd at yahoo.es (Daniel Alejandro Benavides D.) Date: Fri, 28 Sep 2012 17:07:31 +0100 (BST) Subject: [M3devel] STL algorithms? sort/unique? In-Reply-To: Message-ID: <1348848451.80680.YahooMailClassic@web29705.mail.ird.yahoo.com> Hi all: so what's the matter on writing GENERIC MODULE List: http://modula3.elegosoft.com/cm3/doc/help/gen_html/libm3/src/list/List.mg.html What are vectors, object arrays in C++? What is the difference between an array and a vector? More operations, it seems, I guess you don't need a vector for that (and why for just an int)? ?List module is a dynamic structure of Objects, RT errors are caught in ESC so it's clear how and when to use it, hopefully. Thanks in advance --- El vie, 28/9/12, Jay K escribi?: De: Jay K Asunto: [M3devel] STL algorithms? sort/unique? Para: "m3devel" Fecha: viernes, 28 de septiembre, 2012 02:18 ? ??I have an IntSeq.T with a bunch of integers.? ?? ? ??What is a good terse efficient idiom for sort and unique?? ?? ? ? In C++ I would say:? ??? ??vector a;? ??? ??a.push_back(...);? ??? ??a.push_back(...);? ??? ??std::sort(a.begin(), a.end());? ??? ??a.resize(std::unique(a.begin(), a.end()) - a.begin());? ??? ? for (auto i = a.begin(); i != a.end(); ++i)? ? { ? ? ? do stuff with *i? ? }? ? ??Nice, terse, efficient.? ??? ??In Modula-3?? ?? I know that unique is one of the easiest algorithms to manually write inline,but I shouldn't have to. (I'm really trying to stay in Modula-3 here, but it is definitely a struggle. :( ) Thank you,?- Jay -------------- next part -------------- An HTML attachment was scrubbed... URL: From mika at async.caltech.edu Sat Sep 29 20:29:48 2012 From: mika at async.caltech.edu (mika at async.caltech.edu) Date: Sat, 29 Sep 2012 11:29:48 -0700 Subject: [M3devel] STL algorithms? sort/unique? In-Reply-To: References: <20120928075656.751E21A2082@async.async.caltech.edu>, <20120928080448.C80DD1A2082@async.async.caltech.edu> Message-ID: <20120929182948.6589C1A2082@async.async.caltech.edu> Well that depends on how you maintain the vector, no? SortedTable uses "treaps" which are supposed to be good data structures. Too new to have made it into Knuth, last I checked. The amortized cost of your operations shouldn't be much worse than with your method, with the additional benefit that the sorted order is maintained dynamically. The separation of algorithms from containers sounds a bit like a bug. You have to be careful so you don't shoot yourself in the foot there! (Sorting a list using an algorithm that randomly accesses elements, say...) The Modula-3 approach is that you figure out what you want to do, pick the ADT you want that provides the minimal set of operations, import that interface, then instantiate a more carefully chosen implementation of the ADT. The language itself obviously can be coaxed into supporting the algorithm/data structure separation but no one uses it that way as far as I know. (Modula-3 generics are not that well explored, actually. I suspect there are many things you can do with them that no one has tried.) Mika Jay K writes: >--_7877d7e8-cb4a-4989-bdcd-d406e5b1f51f_ >Content-Type: text/plain; charset="iso-8859-1" >Content-Transfer-Encoding: quoted-printable > >The following is very efficient: > >run through a bunch of records=2C picking out one number from some of thema= >ppend those numbers to a growing vectorsort the vectorunique the vector > >sequence allows for random access..but only via a function...or maybe an it= >erator > >STL has this wonderful separation of algorithms from containers=2C via iter= >ators.I suspect very few other libraries do.And it could be that most langu= >ages don't support it.It doesn't appear I can easily sort a sequence=2C unl= >ess I copy the data out into an array -- gross inefficiency. > >I've hacked something very manual together..and it is taking forever to get= > it to work. It turns out I can reasonably well bound the size of the data= >=2C so I'm using an open array...and I have to keep track of my position in= >stead of using addhi/push_back.Not happy.At some point I might give up and = >write the backend in C++..at which point I might as well write a C++ fronte= >nd anywa. > > >I absolutely do not want a sorted table and unique upon insert.That is much= > less efficient.What I'm describing uses temporarily larger working set but= > vastly less CPU.An array that gets sorted/uniqued occasionally=2C like jus= >t once.And not ongoing maintainence for every single add. > > > - Jay > > >> To: jay.krell at cornell.edu >> CC: m3devel at elegosoft.com >> Subject: Re: [M3devel] STL algorithms? sort/unique? >> Date: Fri=2C 28 Sep 2012 01:04:48 -0700 >> From: mika at async.caltech.edu >>=20 >>=20 >> BTW I had the same experience when I first started using Modula-3. >> It was painful to jump through all its hoops=2C coming from C=2C where yo= >u >> can do whatever you want to whatever bits happen to be sloshing around >> your machine. C++ from what I have seen mainly lets you do that to >> more bits in fewer lines of code. >>=20 >> But after a while I really came to appreciate the value of things like th= >e >> language's telling me I'm using the wrong data structure instead of >> just letting me use the same "nice=2C terse=2C efficient" syntax to write >> a crappy program :-) >>=20 >> mika writes: >> >You're using the wrong (abstract) data structure if you want sort and un= >ique. >> > >> >A "sequence" is meant to be accessed sequentially... >> > >> >Not knowing precisely what you're doing it sounds like you might want a >> >SortedTable... you can get unique on insert and access it in increasing >> >or decreasing order. >> > >> > Mika >> > >> >Jay K writes: >> >>--_d2a02ece-d492-410e-88fb-fb53737d7219_ >> >>Content-Type: text/plain=3B charset=3D"iso-8859-1" >> >>Content-Transfer-Encoding: quoted-printable >> >> >> >> I have an IntSeq.T with a bunch of integers. =3D20 >> >> What is a good terse efficient idiom for sort and unique? =3D20 >> >> >> >> In C++ I would say: vector a=3D3B a.push_back(..= >.)=3D3B =3D >> >> a.push_back(...)=3D3B std::sort(a.begin()=3D2C a.end())= >=3D3B =3D >> >> a.resize(std::unique(a.begin()=3D2C a.end()) - a.begin())=3D3B = >for (aut=3D >> >>o i =3D3D a.begin()=3D3B i !=3D3D a.end()=3D3B ++i) { >> >> do stuff with *i }=3D20 >> >> Nice=3D2C terse=3D2C efficient. In Modula-3? =3D20 >> >> >> >>I know that unique is one of the easiest algorithms to manually write i= >nlin=3D >> >>e=3D2Cbut I shouldn't have to. >> >> >> >>(I'm really trying to stay in Modula-3 here=3D2C but it is definitely a= > strug=3D >> >>gle. :( ) >> >> >> >>Thank you=3D2C - Jay >> >> >> >> =3D >> >> >> >>--_d2a02ece-d492-410e-88fb-fb53737d7219_ >> >>Content-Type: text/html=3B charset=3D"iso-8859-1" >> >>Content-Transfer-Encoding: quoted-printable >> >> >> >> >> >> >> >> >> >>
 =3D3B  =3D3B&nb= >sp=3D3BI have =3D >> >>an IntSeq.T with a bunch of integers. =3D3B  =3D3B =3D3B>
> >>n style=3D3D"font-size: 12pt=3D3B "> =3D3B  =3D3Btyle=3D3D"font=3D >> >>-size: 12pt=3D3B "> =3D3BWhat is a good terse efficient idio= >m for so=3D >> >>rt and unique? =3D3B  = >=3D3B<=3D >> >>span style=3D3D"font-size: 12pt=3D3B "> =3D3B

= >
> >>>
 =3D3B  =3D3B In C++ I would say:3D"font-si=3D >> >>ze: 12pt=3D3B "> =3D3B  =3D3B 12pt=3D3B ">&=3D >> >>nbsp=3D3B
&nbs= >p=3D3B  =3D >> >>=3D3B =3D3Bve= >ctor<=3D3Bin=3D >> >>t>=3D3B a=3D3B =3D3B &nbs= >p=3D3B> >>an style=3D3D"font-size: 12pt=3D3B "> =3D3B
style=3D3D"f=3D >> >>ont-size: 12pt=3D3B "> =3D3B  =3D3B-size: 12pt=3D >> >>=3D3B "> =3D3Ba.push_back(...)=3D3Be: 12pt=3D3B "=3D >> >>> =3D3B  =3D3B&n= >bsp=3D3B> >>>
 =3D3B &nb= >sp=3D3B> >>n> =3D3Ba.push_back(= >...)=3D3B> >>an style=3D3D"font-size: 12pt=3D3B "> =3D3B  =3D3Bstyle=3D3D"fon=3D >> >>t-size: 12pt=3D3B "> =3D3B
ize: 12pt=3D >> >>=3D3B "> =3D3B  =3D3B3B "> =3D3B<=3D >> >>/span>std::sort(a.begin()=3D2C a.end())=3D3B 12pt=3D3B "=3D >> >>> =3D3B  =3D3B&n= >bsp=3D3B> >>>
 =3D3B  =3D= >3B> >>an style=3D3D"font-size: 12pt=3D3B "> =3D3Ba.resize(std::uni= >que(a.begi=3D >> >>n()=3D2C a.end()) - a.begin())=3D3BB "> =3D3B=3D >> >>  =3D3B =3D3Bpan>
> >>iv> =3D3B  =3D3B for (a= >uto i =3D3D a.=3D >> >>begin()=3D3B i !=3D3D a.end()=3D3B ++i)
3D"font-size=3D >> >>: 12pt=3D3B "> =3D3B  =3D3B {
 =3D3B  =3D3B  =3D= >3B do stuff with=3D >> >> *i
 =3D3B= >  =3D3B =3D >> >>}
 =3D3B

"font-si=3D >> >>ze: 12pt=3D3B "> =3D3B  =3D3B 12pt=3D3B ">&=3D >> >>nbsp=3D3BNice=3D2C terse=3D2C efficient.ze: 12pt=3D3B =3D >> >>"> =3D3B  =3D3B&= >nbsp=3D3B> >>n>
 =3D3B  = >=3D3B> >>pan style=3D3D"font-size: 12pt=3D3B "> =3D3BIn Modula-3?n style=3D3D=3D >> >>"font-size: 12pt=3D3B "> =3D3B  =3D3Bnt-size: 12p=3D >> >>t=3D3B "> =3D3B


I kn= >ow that =3D >> >>unique is one of the easiest algorithms to manually write inline=3D2Cdiv>> >>iv>but I shouldn't have to.


(I'= >m re=3D >> >>ally trying to stay in Modula-3 here=3D2C but it is definitely a strugg= >le. :(=3D >> >> )


Thank you=3D2C
&nb= >sp=3D3B-=3D >> >> Jay


>> >>=3D >> >> >> >>--_d2a02ece-d492-410e-88fb-fb53737d7219_-- > = > >--_7877d7e8-cb4a-4989-bdcd-d406e5b1f51f_ >Content-Type: text/html; charset="iso-8859-1" >Content-Transfer-Encoding: quoted-printable > > > > >
2pt=3B ">The following is very efficient:

<= >br>
run through a bunch of records=2C picking out one number from= > some of them
append those numbers to a growing vector
= >sort the vector
unique the vector


div>
sequence allows for random access..but only via a function...>
or maybe an iterator


STL has = >this wonderful separation of algorithms from containers=2C via iterators.div>
I suspect very few other libraries do.
And it could be t= >hat most languages don't support it.
It doesn't appear I can easi= >ly sort a sequence=2C unless I copy the data out into an array -- gross ine= >fficiency.


I've hacked something ve= >ry manual together..and it is taking forever to get it to work.
&= >nbsp=3B It turns out I can reasonably well bound the size of the data=2C so= > I'm using an open array...and I have to keep track of my position instead = >of using addhi/push_back.
Not happy.
At some point I mi= >ght give up and write the backend in C++..at which point I might as well wr= >ite a C++ frontend anywa.



>
I absolutely do not want a sorted table and unique upon insert.
= >
That is much less efficient.
What I'm describing uses tempor= >arily larger working set but vastly less CPU.
An array that gets = >sorted/uniqued occasionally=2C like just once.
And not ongoing ma= >intainence for every single add.


r>
 =3B- Jay



aceholder">
>=3B To: jay.krell at cornell.edu
>=3B CC: m3devel at ele= >gosoft.com
>=3B Subject: Re: [M3devel] STL algorithms? sort/unique?>>=3B Date: Fri=2C 28 Sep 2012 01:04:48 -0700
>=3B From: mika at async.= >caltech.edu
>=3B
>=3B
>=3B BTW I had the same experience w= >hen I first started using Modula-3.
>=3B It was painful to jump throug= >h all its hoops=2C coming from C=2C where you
>=3B can do whatever you= > want to whatever bits happen to be sloshing around
>=3B your machine.= > C++ from what I have seen mainly lets you do that to
>=3B more bits = >in fewer lines of code.
>=3B
>=3B But after a while I really cam= >e to appreciate the value of things like the
>=3B language's telling m= >e I'm using the wrong data structure instead of
>=3B just letting me u= >se the same "nice=2C terse=2C efficient" syntax to write
>=3B a crappy= > program :-)
>=3B
>=3B mika writes:
>=3B >=3BYou're using= > the wrong (abstract) data structure if you want sort and unique.
>=3B= > >=3B
>=3B >=3BA "sequence" is meant to be accessed sequentially..= >.
>=3B >=3B
>=3B >=3BNot knowing precisely what you're doing = >it sounds like you might want a
>=3B >=3BSortedTable... you can get = >unique on insert and access it in increasing
>=3B >=3Bor decreasing = >order.
>=3B >=3B
>=3B >=3B Mika
>=3B >=3B
>=3B= > >=3BJay K writes:
>=3B >=3B>=3B--_d2a02ece-d492-410e-88fb-fb537= >37d7219_
>=3B >=3B>=3BContent-Type: text/plain=3B charset=3D"iso-8= >859-1"
>=3B >=3B>=3BContent-Transfer-Encoding: quoted-printable>>=3B >=3B>=3B
>=3B >=3B>=3B I have an IntSeq.T with a bu= >nch of integers. =3D20
>=3B >=3B>=3B What is a good terse eff= >icient idiom for sort and unique? =3D20
>=3B >=3B>=3B
>=3B = >>=3B>=3B In C++ I would say: vector<=3Bint>=3B a=3D3B = > a.push_back(...)=3D3B =3D
>=3B >=3B>=3B a.push_back(...)= >=3D3B std::sort(a.begin()=3D2C a.end())=3D3B =3D
>=3B >= >=3B>=3B a.resize(std::unique(a.begin()=3D2C a.end()) - a.begin())=3D3B = > for (aut=3D
>=3B >=3B>=3Bo i =3D3D a.begin()=3D3B i !=3D3D a.= >end()=3D3B ++i) {
>=3B >=3B>=3B do stuff with *i }=3D20= >
>=3B >=3B>=3B Nice=3D2C terse=3D2C efficient. In Modula= >-3? =3D20
>=3B >=3B>=3B
>=3B >=3B>=3BI know that unique= > is one of the easiest algorithms to manually write inlin=3D
>=3B >= >=3B>=3Be=3D2Cbut I shouldn't have to.
>=3B >=3B>=3B
>=3B &g= >t=3B>=3B(I'm really trying to stay in Modula-3 here=3D2C but it is defini= >tely a strug=3D
>=3B >=3B>=3Bgle. :( )
>=3B >=3B>=3B
&= >gt=3B >=3B>=3BThank you=3D2C - Jay
>=3B >=3B>=3B
>=3B >= >=3B>=3B =3D
>=3B >=3B>=3B
>=3B >=3B>=3B--_d2= >a02ece-d492-410e-88fb-fb53737d7219_
>=3B >=3B>=3BContent-Type: tex= >t/html=3B charset=3D"iso-8859-1"
>=3B >=3B>=3BContent-Transfer-Enc= >oding: quoted-printable
>=3B >=3B>=3B
>=3B >=3B>=3B<=3B= >html>=3B
>=3B >=3B>=3B<=3Bhead>=3B
>=3B >=3B>=3B<= >=3Bstyle>=3B<=3B!--
>=3B >=3B>=3B.hmmessage P
>=3B >=3B= >>=3B{
>=3B >=3B>=3Bmargin:0px=3D3B
>=3B >=3B>=3Bpadding= >:0px
>=3B >=3B>=3B}
>=3B >=3B>=3Bbody.hmmessage
>=3B= > >=3B>=3B{
>=3B >=3B>=3Bfont-size: 12pt=3D3B
>=3B >=3B&= >gt=3Bfont-family:Calibri
>=3B >=3B>=3B}
>=3B >=3B>=3B--&g= >t=3B<=3B/style>=3B<=3B/head>=3B
>=3B >=3B>=3B<=3Bbody cl= >ass=3D3D'hmmessage'>=3B<=3Bdiv dir=3D3D'ltr'>=3B&=3Bnbsp=3D3B &= >=3Bnbsp=3D3B&=3Bnbsp=3D3BI have =3D
>=3B >=3B>=3Ban IntSeq.T wi= >th a bunch of integers.&=3Bnbsp=3D3B &=3Bnbsp=3D3B&=3Bnbsp=3D3B<= >=3Bbr>=3B<=3Bdiv>=3B<=3Bspa=3D
>=3B >=3B>=3Bn style=3D3D"f= >ont-size: 12pt=3D3B ">=3B&=3Bnbsp=3D3B &=3Bnbsp=3D3B<=3B/span>= >=3B<=3Bspan style=3D3D"font=3D
>=3B >=3B>=3B-size: 12pt=3D3B "&g= >t=3B&=3Bnbsp=3D3B<=3B/span>=3BWhat is a good terse efficient idiom f= >or so=3D
>=3B >=3B>=3Brt and unique?<=3Bspan style=3D3D"font-siz= >e: 12pt=3D3B ">=3B&=3Bnbsp=3D3B &=3Bnbsp=3D3B<=3B/span>=3B<= >=3B=3D
>=3B >=3B>=3Bspan style=3D3D"font-size: 12pt=3D3B ">=3B&a= >mp=3Bnbsp=3D3B<=3B/span>=3B<=3B/div>=3B<=3Bdiv>=3B<=3Bbr>= >=3B<=3B/div>=3B<=3Bdiv=3D
>=3B >=3B>=3B>=3B<=3Bbr>=3B&= >lt=3B/div>=3B<=3Bdiv>=3B&=3Bnbsp=3D3B &=3Bnbsp=3D3B In C++ I wo= >uld say:<=3Bspan style=3D3D"font-si=3D
>=3B >=3B>=3Bze: 12pt=3D3= >B ">=3B&=3Bnbsp=3D3B &=3Bnbsp=3D3B<=3B/span>=3B<=3Bspan style= >=3D3D"font-size: 12pt=3D3B ">=3B&=3B=3D
>=3B >=3B>=3Bnbsp=3D3= >B<=3B/span>=3B<=3B/div>=3B<=3Bdiv>=3B<=3Bspan style=3D3D"font= >-size: 12pt=3D3B ">=3B&=3Bnbsp=3D3B &=3Bnbsp=3D
>=3B >=3B>= >=3B=3D3B<=3B/span>=3B<=3Bspan style=3D3D"font-size: 12pt=3D3B ">=3B= >&=3Bnbsp=3D3B<=3B/span>=3Bvector&=3Blt=3D3Bin=3D
>=3B >=3B= >>=3Bt&=3Bgt=3D3B a=3D3B<=3Bspan style=3D3D"font-size: 12pt=3D3B ">= >=3B&=3Bnbsp=3D3B &=3Bnbsp=3D3B<=3B/span>=3B<=3Bsp=3D
>=3B = >>=3B>=3Ban style=3D3D"font-size: 12pt=3D3B ">=3B&=3Bnbsp=3D3B<= >=3B/span>=3B<=3B/div>=3B<=3Bdiv>=3B<=3Bspan style=3D3D"f=3D
= >>=3B >=3B>=3Bont-size: 12pt=3D3B ">=3B&=3Bnbsp=3D3B &=3Bnbsp= >=3D3B<=3B/span>=3B<=3Bspan style=3D3D"font-size: 12pt=3D
>=3B &g= >t=3B>=3B=3D3B ">=3B&=3Bnbsp=3D3B<=3B/span>=3Ba.push_back(...)=3D= >3B<=3Bspan style=3D3D"font-size: 12pt=3D3B "=3D
>=3B >=3B>=3B>= >=3B&=3Bnbsp=3D3B &=3Bnbsp=3D3B<=3B/span>=3B<=3Bspan style=3D3D"= >font-size: 12pt=3D3B ">=3B&=3Bnbsp=3D3B<=3B/span=3D
>=3B >=3B= >>=3B>=3B<=3B/div>=3B<=3Bdiv>=3B<=3Bdiv>=3B<=3Bspan style= >=3D3D"font-size: 12pt=3D3B ">=3B&=3Bnbsp=3D3B &=3Bnbsp=3D3B<=3B/s= >pa=3D
>=3B >=3B>=3Bn>=3B<=3Bspan style=3D3D"font-size: 12pt=3D= >3B ">=3B&=3Bnbsp=3D3B<=3B/span>=3Ba.push_back(...)=3D3B<=3Bsp=3D= >
>=3B >=3B>=3Ban style=3D3D"font-size: 12pt=3D3B ">=3B&=3Bnbs= >p=3D3B &=3Bnbsp=3D3B<=3B/span>=3B<=3Bspan style=3D3D"fon=3D
>= >=3B >=3B>=3Bt-size: 12pt=3D3B ">=3B&=3Bnbsp=3D3B<=3B/span>=3B&= >lt=3B/div>=3B<=3Bdiv>=3B<=3Bspan style=3D3D"font-size: 12pt=3D
&= >gt=3B >=3B>=3B=3D3B ">=3B&=3Bnbsp=3D3B &=3Bnbsp=3D3B<=3B/span= >>=3B<=3Bspan style=3D3D"font-size: 12pt=3D3B ">=3B&=3Bnbsp=3D3B<= >=3B=3D
>=3B >=3B>=3B/span>=3Bstd::sort(a.begin()=3D2C a.end())= >=3D3B<=3Bspan style=3D3D"font-size: 12pt=3D3B "=3D
>=3B >=3B>=3B= >>=3B&=3Bnbsp=3D3B &=3Bnbsp=3D3B<=3B/span>=3B<=3Bspan style=3D= >3D"font-size: 12pt=3D3B ">=3B&=3Bnbsp=3D3B<=3B/span=3D
>=3B >= >=3B>=3B>=3B<=3B/div>=3B<=3Bdiv>=3B<=3Bspan style=3D3D"font-si= >ze: 12pt=3D3B ">=3B&=3Bnbsp=3D3B &=3Bnbsp=3D3B<=3B/span>=3B<= >=3Bsp=3D
>=3B >=3B>=3Ban style=3D3D"font-size: 12pt=3D3B ">=3B&a= >mp=3Bnbsp=3D3B<=3B/span>=3Ba.resize(std::unique(a.begi=3D
>=3B >= >=3B>=3Bn()=3D2C a.end()) - a.begin())=3D3B<=3Bspan style=3D3D"font-size= >: 12pt=3D3B ">=3B&=3Bnbsp=3D3B=3D
>=3B >=3B>=3B &=3Bnbsp= >=3D3B<=3B/span>=3B<=3Bspan style=3D3D"font-size: 12pt=3D3B ">=3B&am= >p=3Bnbsp=3D3B<=3B/span>=3B<=3B/div>=3B<=3Bd=3D
>=3B >=3B&g= >t=3Biv>=3B<=3Bspan style=3D3D"font-size: 12pt=3D3B ">=3B&=3Bnbsp= >=3D3B &=3Bnbsp=3D3B for (auto i =3D3D a.=3D
>=3B >=3B>=3Bbegin(= >)=3D3B i !=3D3D a.end()=3D3B ++i)<=3B/span>=3B<=3B/div>=3B<=3Bdiv= >>=3B<=3Bspan style=3D3D"font-size=3D
>=3B >=3B>=3B: 12pt=3D3B = >">=3B&=3Bnbsp=3D3B &=3Bnbsp=3D3B {<=3Bbr>=3B&=3Bnbsp=3D3B &a= >mp=3Bnbsp=3D3B &=3Bnbsp=3D3B do stuff with=3D
>=3B >=3B>=3B *i&= >lt=3B/span>=3B<=3B/div>=3B<=3Bdiv>=3B<=3Bspan style=3D3D"font-s= >ize: 12pt=3D3B ">=3B&=3Bnbsp=3D3B &=3Bnbsp=3D3B =3D
>=3B >= >=3B>=3B}<=3B/span>=3B<=3B/div>=3B<=3Bdiv>=3B&=3Bnbsp=3D3B&= >lt=3B/div>=3B<=3Bdiv>=3B<=3Bbr>=3B<=3B/div>=3B<=3Bdiv>=3B= ><=3Bspan style=3D3D"font-si=3D
>=3B >=3B>=3Bze: 12pt=3D3B ">= >=3B&=3Bnbsp=3D3B &=3Bnbsp=3D3B<=3B/span>=3B<=3Bspan style=3D3D"= >font-size: 12pt=3D3B ">=3B&=3B=3D
>=3B >=3B>=3Bnbsp=3D3B<= >=3B/span>=3BNice=3D2C terse=3D2C efficient.<=3Bspan style=3D3D"font-siz= >e: 12pt=3D3B =3D
>=3B >=3B>=3B">=3B&=3Bnbsp=3D3B &=3Bnbsp= >=3D3B<=3B/span>=3B<=3Bspan style=3D3D"font-size: 12pt=3D3B ">=3B&am= >p=3Bnbsp=3D3B<=3B/spa=3D
>=3B >=3B>=3Bn>=3B<=3B/div>=3B<= >=3Bdiv>=3B<=3Bspan style=3D3D"font-size: 12pt=3D3B ">=3B&=3Bnbsp= >=3D3B &=3Bnbsp=3D3B<=3B/span>=3B<=3Bs=3D
>=3B >=3B>=3Bpan= > style=3D3D"font-size: 12pt=3D3B ">=3B&=3Bnbsp=3D3B<=3B/span>=3BIn= > Modula-3?<=3Bspan style=3D3D=3D
>=3B >=3B>=3B"font-size: 12pt= >=3D3B ">=3B&=3Bnbsp=3D3B &=3Bnbsp=3D3B<=3B/span>=3B<=3Bspan s= >tyle=3D3D"font-size: 12p=3D
>=3B >=3B>=3Bt=3D3B ">=3B&=3Bnbsp= >=3D3B<=3B/span>=3B<=3B/div>=3B<=3Bdiv>=3B<=3Bbr>=3B<=3B/d= >iv>=3B<=3Bdiv>=3B<=3Bbr>=3B<=3B/div>=3B<=3Bdiv>=3BI know = >that =3D
>=3B >=3B>=3Bunique is one of the easiest algorithms to m= >anually write inline=3D2C<=3B/div>=3B<=3Bd=3D
>=3B >=3B>=3Bi= >v>=3Bbut I shouldn't have to.<=3B/div>=3B<=3Bdiv>=3B<=3Bbr>= >=3B<=3B/div>=3B<=3Bdiv>=3B<=3Bbr>=3B<=3B/div>=3B<=3Bdiv&g= >t=3B(I'm re=3D
>=3B >=3B>=3Bally trying to stay in Modula-3 here= >=3D2C but it is definitely a struggle. :(=3D
>=3B >=3B>=3B )<=3B= >/div>=3B<=3Bdiv>=3B<=3Bbr>=3B<=3B/div>=3B<=3Bdiv>=3B<= >=3Bbr>=3B<=3B/div>=3B<=3Bdiv>=3BThank you=3D2C<=3B/div>=3B<= >=3Bdiv>=3B&=3Bnbsp=3D3B-=3D
>=3B >=3B>=3B Jay<=3B/div>=3B= ><=3Bbr>=3B<=3Bbr>=3B<=3B/div>=3B <=3B/div>=3B<= >=3B/body>=3B
>=3B >=3B>=3B<=3B/html>=3B=3D
>=3B >=3B&= >gt=3B
>=3B >=3B>=3B--_d2a02ece-d492-410e-88fb-fb53737d7219_--
<= >/div>
>= > >--_7877d7e8-cb4a-4989-bdcd-d406e5b1f51f_-- From jay.krell at cornell.edu Sat Sep 29 20:55:18 2012 From: jay.krell at cornell.edu (Jay K) Date: Sat, 29 Sep 2012 18:55:18 +0000 Subject: [M3devel] deeper meaning of in_memory? In-Reply-To: References: , Message-ID: I can just ignore in_memory?I will end up taking the address for one reason or another anyway?VAR parameters..hm..is it conceivable I'm passing them by valueand the compiler can compile itself successfully anyway?Is the indirection added besides the in_memory boolean? I can check easily of course.I will. - Jay From: hosking at cs.purdue.edu Date: Fri, 28 Sep 2012 10:11:49 -0400 To: jay.krell at cornell.edu CC: m3devel at elegosoft.com Subject: Re: [M3devel] deeper meaning of in_memory? in_memory does not mean volatile. It is simply a sign that its address is needed.So, yes, taking its address is good enough.An example of a local in memory is something passed by VAR. So, NOT VOLATILE. Why do structs need to be C volatile? On Sep 27, 2012, at 10:57 PM, Jay K wrote:In M3CG, what is the deeper meaning of in_memory?I know it means -- "put the thing in memory".But why and exactly what? Presumably it can also be in a register, just that the in-memory value must be kept up to date.Like, stores should be volatile, but reads don't have to be?Does it mean the value will be used in an exception/finally handler?Maybe reads do need to be volatile? Maybe it is accessed by another thread w/o a lock? If I take the address of something, is that good enough? I should just look where m3front uses it, I know.For now I'll probably take it to mean "volatile".I already mark all structs as volatile. But I don't make everything volatile (like how m3cc long did). Thanks, - Jay -------------- next part -------------- An HTML attachment was scrubbed... URL: From jay.krell at cornell.edu Sat Sep 29 21:10:40 2012 From: jay.krell at cornell.edu (Jay K) Date: Sat, 29 Sep 2012 19:10:40 +0000 Subject: [M3devel] STL algorithms? sort/unique? In-Reply-To: <20120929182948.6589C1A2082@async.async.caltech.edu> References: <20120928075656.751E21A2082@async.async.caltech.edu>, <20120928080448.C80DD1A2082@async.async.caltech.edu> , <20120929182948.6589C1A2082@async.async.caltech.edu> Message-ID: > The separation of algorithms from containers sounds a bit like a bug. It isn't. It is a leap that allows for far greater code reuse. Efficiently.(You could do it inefficiently with lots of function pointers -- templates allowfor inlinability. C++ beats C for performance here.) Imagine I have written quicksort.In C++ we have at least the following worthwhile "array-like" data structures: The builtin arrays. Like Modula-3 fixed arrays. Arrays you get with new[]. Like Modula-3 open arrays, but they don't expose their size. std::vector<>. Like Modula-3 "sequence" -- a simple growable array. Grows by a constant factor greater than 1 (typically 2), so that long runs of "appends" are amortized cheap. std::deque<>. More like Modula-3 sequence, in that you can amortized cheap at/remove from the front or the back. I believe this can be implemented as simply an "offset array". Element 0 starts in the middle, and whenever you grow it, you "center" it -- equal gaps at front and back. Now, with the iterator/algorithm separation, one quicksort implementation can be applied to all these types. The input to "quicksort" is "random access iterators", which is very much like a "pointer", but isn't necessarily a pointer. It can be incremented, decremented, added to an integer, subtracted from another iterator, have an integer subtracted from it, dereferenced, and assigned and compared with other iterators of the same type -- all constant time fast operations. There are "input iterators" which can, roughly speaking, only be incremented and dereferenced. They are all some containers can expose and all some algorithms require -- for example, a singly linked list and linear search. There are "bidirectional iterators" which can, roughly speaking, only be incremented and decremented and dereferenced. Doubly linked lists expose these. There are "output iterators".They are similar to "input". input streams (cin, like stdin) exposes an input iterator.You can copy from it.Copy is another simple reusable algorithm. output streams (cout, like stdout) exposes an output iterator.You can copy to it. There are many more examples.Of course, besides quick sort, there is a stable sort.There is finding sequences.There is binary_search.There is upper_bound/lower_bound/equal_range which are like binary_search.There is unique.There is partition.Many many more, "built in" to the library.That work with multiple "built in" containers, and can work with custom containers as well. I strongly recommend you read up on this stuff.It is really quite illimuninating. Good stuff.Teaches us how to better factor our code.And to strive for better factoring, when we find people have invented/discovered such things. "Iterators" already do occur in Modula-3 libraries. All I want is a sorted vector that "closely knows" when it is being written vs. read, and when there are a series of writes with no intervening reads, it can amortize down the cost of maintaining the ordering. I hand coded something.It took me a while to get it to work due to stupid small details.The result is significantly worse than I would have gotten in C++.Bigger code. Slower code. More copies. More heap allocations.I can eliminate one of the allocations by merging the next step.But in C++ I naturally wouldn't have had it anyway.Not great. - Jay > To: jay.krell at cornell.edu > CC: mika at async.caltech.edu; m3devel at elegosoft.com > Subject: Re: [M3devel] STL algorithms? sort/unique? > Date: Sat, 29 Sep 2012 11:29:48 -0700 > From: mika at async.caltech.edu > > > Well that depends on how you maintain the vector, no? > > SortedTable uses "treaps" which are supposed to be good data structures. > Too new to have made it into Knuth, last I checked. The amortized cost > of your operations shouldn't be much worse than with your method, with > the additional benefit that the sorted order is maintained dynamically. > > The separation of algorithms from containers sounds a bit like a bug. > You have to be careful so you don't shoot yourself in the foot there! > (Sorting a list using an algorithm that randomly accesses elements, > say...) > > The Modula-3 approach is that you figure out what you want to do, pick > the ADT you want that provides the minimal set of operations, import > that interface, then instantiate a more carefully chosen implementation > of the ADT. The language itself obviously can be coaxed into supporting the > algorithm/data structure separation but no one uses it that way as > far as I know. (Modula-3 generics are not that well explored, actually. > I suspect there are many things you can do with them that no one has > tried.) > > Mika > > Jay K writes: > >--_7877d7e8-cb4a-4989-bdcd-d406e5b1f51f_ > >Content-Type: text/plain; charset="iso-8859-1" > >Content-Transfer-Encoding: quoted-printable > > > >The following is very efficient: > > > >run through a bunch of records=2C picking out one number from some of thema= > >ppend those numbers to a growing vectorsort the vectorunique the vector > > > >sequence allows for random access..but only via a function...or maybe an it= > >erator > > > >STL has this wonderful separation of algorithms from containers=2C via iter= > >ators.I suspect very few other libraries do.And it could be that most langu= > >ages don't support it.It doesn't appear I can easily sort a sequence=2C unl= > >ess I copy the data out into an array -- gross inefficiency. > > > >I've hacked something very manual together..and it is taking forever to get= > > it to work. It turns out I can reasonably well bound the size of the data= > >=2C so I'm using an open array...and I have to keep track of my position in= > >stead of using addhi/push_back.Not happy.At some point I might give up and = > >write the backend in C++..at which point I might as well write a C++ fronte= > >nd anywa. > > > > > >I absolutely do not want a sorted table and unique upon insert.That is much= > > less efficient.What I'm describing uses temporarily larger working set but= > > vastly less CPU.An array that gets sorted/uniqued occasionally=2C like jus= > >t once.And not ongoing maintainence for every single add. > > > > > > - Jay > > > > > >> To: jay.krell at cornell.edu > >> CC: m3devel at elegosoft.com > >> Subject: Re: [M3devel] STL algorithms? sort/unique? > >> Date: Fri=2C 28 Sep 2012 01:04:48 -0700 > >> From: mika at async.caltech.edu > >>=20 > >>=20 > >> BTW I had the same experience when I first started using Modula-3. > >> It was painful to jump through all its hoops=2C coming from C=2C where yo= > >u > >> can do whatever you want to whatever bits happen to be sloshing around > >> your machine. C++ from what I have seen mainly lets you do that to > >> more bits in fewer lines of code. > >>=20 > >> But after a while I really came to appreciate the value of things like th= > >e > >> language's telling me I'm using the wrong data structure instead of > >> just letting me use the same "nice=2C terse=2C efficient" syntax to write > >> a crappy program :-) > >>=20 > >> mika writes: > >> >You're using the wrong (abstract) data structure if you want sort and un= > >ique. > >> > > >> >A "sequence" is meant to be accessed sequentially... > >> > > >> >Not knowing precisely what you're doing it sounds like you might want a > >> >SortedTable... you can get unique on insert and access it in increasing > >> >or decreasing order. > >> > > >> > Mika > >> > > >> >Jay K writes: > >> >>--_d2a02ece-d492-410e-88fb-fb53737d7219_ > >> >>Content-Type: text/plain=3B charset=3D"iso-8859-1" > >> >>Content-Transfer-Encoding: quoted-printable > >> >> > >> >> I have an IntSeq.T with a bunch of integers. =3D20 > >> >> What is a good terse efficient idiom for sort and unique? =3D20 > >> >> > >> >> In C++ I would say: vector a=3D3B a.push_back(..= > >.)=3D3B =3D > >> >> a.push_back(...)=3D3B std::sort(a.begin()=3D2C a.end())= > >=3D3B =3D > >> >> a.resize(std::unique(a.begin()=3D2C a.end()) - a.begin())=3D3B = > >for (aut=3D > >> >>o i =3D3D a.begin()=3D3B i !=3D3D a.end()=3D3B ++i) { > >> >> do stuff with *i }=3D20 > >> >> Nice=3D2C terse=3D2C efficient. In Modula-3? =3D20 > >> >> > >> >>I know that unique is one of the easiest algorithms to manually write i= > >nlin=3D > >> >>e=3D2Cbut I shouldn't have to. > >> >> > >> >>(I'm really trying to stay in Modula-3 here=3D2C but it is definitely a= > > strug=3D > >> >>gle. :( ) > >> >> > >> >>Thank you=3D2C - Jay > >> >> > >> >> =3D > >> >> > >> >>--_d2a02ece-d492-410e-88fb-fb53737d7219_ > >> >>Content-Type: text/html=3B charset=3D"iso-8859-1" > >> >>Content-Transfer-Encoding: quoted-printable > >> >> > >> >> > >> >> > >> >> > >> >>
 =3D3B  =3D3B&nb= > >sp=3D3BI have =3D > >> >>an IntSeq.T with a bunch of integers. =3D3B  =3D3B =3D3B >>
>> >>n style=3D3D"font-size: 12pt=3D3B "> =3D3B  =3D3B >tyle=3D3D"font=3D > >> >>-size: 12pt=3D3B "> =3D3BWhat is a good terse efficient idio= > >m for so=3D > >> >>rt and unique? =3D3B  = > >=3D3B<=3D > >> >>span style=3D3D"font-size: 12pt=3D3B "> =3D3B

= > >
>> >>>
 =3D3B  =3D3B In C++ I would say: >3D"font-si=3D > >> >>ze: 12pt=3D3B "> =3D3B  =3D3B > 12pt=3D3B ">&=3D > >> >>nbsp=3D3B
&nbs= > >p=3D3B  =3D > >> >>=3D3B =3D3Bve= > >ctor<=3D3Bin=3D > >> >>t>=3D3B a=3D3B =3D3B &nbs= > >p=3D3B >> >>an style=3D3D"font-size: 12pt=3D3B "> =3D3B
>style=3D3D"f=3D > >> >>ont-size: 12pt=3D3B "> =3D3B  =3D3B >-size: 12pt=3D > >> >>=3D3B "> =3D3Ba.push_back(...)=3D3B >e: 12pt=3D3B "=3D > >> >>> =3D3B  =3D3B&n= > >bsp=3D3B >> >>>
 =3D3B &nb= > >sp=3D3B >> >>n> =3D3Ba.push_back(= > >...)=3D3B >> >>an style=3D3D"font-size: 12pt=3D3B "> =3D3B  =3D3B >style=3D3D"fon=3D > >> >>t-size: 12pt=3D3B "> =3D3B
>ize: 12pt=3D > >> >>=3D3B "> =3D3B  =3D3B >3B "> =3D3B<=3D > >> >>/span>std::sort(a.begin()=3D2C a.end())=3D3B > 12pt=3D3B "=3D > >> >>> =3D3B  =3D3B&n= > >bsp=3D3B >> >>>
 =3D3B  =3D= > >3B >> >>an style=3D3D"font-size: 12pt=3D3B "> =3D3Ba.resize(std::uni= > >que(a.begi=3D > >> >>n()=3D2C a.end()) - a.begin())=3D3B >B "> =3D3B=3D > >> >>  =3D3B =3D3B >pan>
>> >>iv> =3D3B  =3D3B for (a= > >uto i =3D3D a.=3D > >> >>begin()=3D3B i !=3D3D a.end()=3D3B ++i)
>3D"font-size=3D > >> >>: 12pt=3D3B "> =3D3B  =3D3B {
 =3D3B  =3D3B  =3D= > >3B do stuff with=3D > >> >> *i
 =3D3B= > >  =3D3B =3D > >> >>}
 =3D3B

>"font-si=3D > >> >>ze: 12pt=3D3B "> =3D3B  =3D3B > 12pt=3D3B ">&=3D > >> >>nbsp=3D3BNice=3D2C terse=3D2C efficient. >ze: 12pt=3D3B =3D > >> >>"> =3D3B  =3D3B&= > >nbsp=3D3B >> >>n>
 =3D3B  = > >=3D3B >> >>pan style=3D3D"font-size: 12pt=3D3B "> =3D3BIn Modula-3? >n style=3D3D=3D > >> >>"font-size: 12pt=3D3B "> =3D3B  =3D3B >nt-size: 12p=3D > >> >>t=3D3B "> =3D3B


I kn= > >ow that =3D > >> >>unique is one of the easiest algorithms to manually write inline=3D2C >div> >> >>iv>but I shouldn't have to.


(I'= > >m re=3D > >> >>ally trying to stay in Modula-3 here=3D2C but it is definitely a strugg= > >le. :(=3D > >> >> )


Thank you=3D2C
&nb= > >sp=3D3B-=3D > >> >> Jay


> >> >>=3D > >> >> > >> >>--_d2a02ece-d492-410e-88fb-fb53737d7219_-- > > = > > > >--_7877d7e8-cb4a-4989-bdcd-d406e5b1f51f_ > >Content-Type: text/html; charset="iso-8859-1" > >Content-Transfer-Encoding: quoted-printable > > > > > > > > > >
>2pt=3B ">The following is very efficient:

<= > >br>
run through a bunch of records=2C picking out one number from= > > some of them
append those numbers to a growing vector
= > >sort the vector
unique the vector


>div>
sequence allows for random access..but only via a function... >>
or maybe an iterator


STL has = > >this wonderful separation of algorithms from containers=2C via iterators. >div>
I suspect very few other libraries do.
And it could be t= > >hat most languages don't support it.
It doesn't appear I can easi= > >ly sort a sequence=2C unless I copy the data out into an array -- gross ine= > >fficiency.


I've hacked something ve= > >ry manual together..and it is taking forever to get it to work.
&= > >nbsp=3B It turns out I can reasonably well bound the size of the data=2C so= > > I'm using an open array...and I have to keep track of my position instead = > >of using addhi/push_back.
Not happy.
At some point I mi= > >ght give up and write the backend in C++..at which point I might as well wr= > >ite a C++ frontend anywa.



>>
I absolutely do not want a sorted table and unique upon insert.
= > >
That is much less efficient.
What I'm describing uses tempor= > >arily larger working set but vastly less CPU.
An array that gets = > >sorted/uniqued occasionally=2C like just once.
And not ongoing ma= > >intainence for every single add.


>r>
 =3B- Jay



>aceholder">
>=3B To: jay.krell at cornell.edu
>=3B CC: m3devel at ele= > >gosoft.com
>=3B Subject: Re: [M3devel] STL algorithms? sort/unique? >>>=3B Date: Fri=2C 28 Sep 2012 01:04:48 -0700
>=3B From: mika at async.= > >caltech.edu
>=3B
>=3B
>=3B BTW I had the same experience w= > >hen I first started using Modula-3.
>=3B It was painful to jump throug= > >h all its hoops=2C coming from C=2C where you
>=3B can do whatever you= > > want to whatever bits happen to be sloshing around
>=3B your machine.= > > C++ from what I have seen mainly lets you do that to
>=3B more bits = > >in fewer lines of code.
>=3B
>=3B But after a while I really cam= > >e to appreciate the value of things like the
>=3B language's telling m= > >e I'm using the wrong data structure instead of
>=3B just letting me u= > >se the same "nice=2C terse=2C efficient" syntax to write
>=3B a crappy= > > program :-)
>=3B
>=3B mika writes:
>=3B >=3BYou're using= > > the wrong (abstract) data structure if you want sort and unique.
>=3B= > > >=3B
>=3B >=3BA "sequence" is meant to be accessed sequentially..= > >.
>=3B >=3B
>=3B >=3BNot knowing precisely what you're doing = > >it sounds like you might want a
>=3B >=3BSortedTable... you can get = > >unique on insert and access it in increasing
>=3B >=3Bor decreasing = > >order.
>=3B >=3B
>=3B >=3B Mika
>=3B >=3B
>=3B= > > >=3BJay K writes:
>=3B >=3B>=3B--_d2a02ece-d492-410e-88fb-fb537= > >37d7219_
>=3B >=3B>=3BContent-Type: text/plain=3B charset=3D"iso-8= > >859-1"
>=3B >=3B>=3BContent-Transfer-Encoding: quoted-printable >>>=3B >=3B>=3B
>=3B >=3B>=3B I have an IntSeq.T with a bu= > >nch of integers. =3D20
>=3B >=3B>=3B What is a good terse eff= > >icient idiom for sort and unique? =3D20
>=3B >=3B>=3B
>=3B = > >>=3B>=3B In C++ I would say: vector<=3Bint>=3B a=3D3B = > > a.push_back(...)=3D3B =3D
>=3B >=3B>=3B a.push_back(...)= > >=3D3B std::sort(a.begin()=3D2C a.end())=3D3B =3D
>=3B >= > >=3B>=3B a.resize(std::unique(a.begin()=3D2C a.end()) - a.begin())=3D3B = > > for (aut=3D
>=3B >=3B>=3Bo i =3D3D a.begin()=3D3B i !=3D3D a.= > >end()=3D3B ++i) {
>=3B >=3B>=3B do stuff with *i }=3D20= > >
>=3B >=3B>=3B Nice=3D2C terse=3D2C efficient. In Modula= > >-3? =3D20
>=3B >=3B>=3B
>=3B >=3B>=3BI know that unique= > > is one of the easiest algorithms to manually write inlin=3D
>=3B >= > >=3B>=3Be=3D2Cbut I shouldn't have to.
>=3B >=3B>=3B
>=3B &g= > >t=3B>=3B(I'm really trying to stay in Modula-3 here=3D2C but it is defini= > >tely a strug=3D
>=3B >=3B>=3Bgle. :( )
>=3B >=3B>=3B
&= > >gt=3B >=3B>=3BThank you=3D2C - Jay
>=3B >=3B>=3B
>=3B >= > >=3B>=3B =3D
>=3B >=3B>=3B
>=3B >=3B>=3B--_d2= > >a02ece-d492-410e-88fb-fb53737d7219_
>=3B >=3B>=3BContent-Type: tex= > >t/html=3B charset=3D"iso-8859-1"
>=3B >=3B>=3BContent-Transfer-Enc= > >oding: quoted-printable
>=3B >=3B>=3B
>=3B >=3B>=3B<=3B= > >html>=3B
>=3B >=3B>=3B<=3Bhead>=3B
>=3B >=3B>=3B<= > >=3Bstyle>=3B<=3B!--
>=3B >=3B>=3B.hmmessage P
>=3B >=3B= > >>=3B{
>=3B >=3B>=3Bmargin:0px=3D3B
>=3B >=3B>=3Bpadding= > >:0px
>=3B >=3B>=3B}
>=3B >=3B>=3Bbody.hmmessage
>=3B= > > >=3B>=3B{
>=3B >=3B>=3Bfont-size: 12pt=3D3B
>=3B >=3B&= > >gt=3Bfont-family:Calibri
>=3B >=3B>=3B}
>=3B >=3B>=3B--&g= > >t=3B<=3B/style>=3B<=3B/head>=3B
>=3B >=3B>=3B<=3Bbody cl= > >ass=3D3D'hmmessage'>=3B<=3Bdiv dir=3D3D'ltr'>=3B&=3Bnbsp=3D3B &= > >=3Bnbsp=3D3B&=3Bnbsp=3D3BI have =3D
>=3B >=3B>=3Ban IntSeq.T wi= > >th a bunch of integers.&=3Bnbsp=3D3B &=3Bnbsp=3D3B&=3Bnbsp=3D3B<= > >=3Bbr>=3B<=3Bdiv>=3B<=3Bspa=3D
>=3B >=3B>=3Bn style=3D3D"f= > >ont-size: 12pt=3D3B ">=3B&=3Bnbsp=3D3B &=3Bnbsp=3D3B<=3B/span>= > >=3B<=3Bspan style=3D3D"font=3D
>=3B >=3B>=3B-size: 12pt=3D3B "&g= > >t=3B&=3Bnbsp=3D3B<=3B/span>=3BWhat is a good terse efficient idiom f= > >or so=3D
>=3B >=3B>=3Brt and unique?<=3Bspan style=3D3D"font-siz= > >e: 12pt=3D3B ">=3B&=3Bnbsp=3D3B &=3Bnbsp=3D3B<=3B/span>=3B<= > >=3B=3D
>=3B >=3B>=3Bspan style=3D3D"font-size: 12pt=3D3B ">=3B&a= > >mp=3Bnbsp=3D3B<=3B/span>=3B<=3B/div>=3B<=3Bdiv>=3B<=3Bbr>= > >=3B<=3B/div>=3B<=3Bdiv=3D
>=3B >=3B>=3B>=3B<=3Bbr>=3B&= > >lt=3B/div>=3B<=3Bdiv>=3B&=3Bnbsp=3D3B &=3Bnbsp=3D3B In C++ I wo= > >uld say:<=3Bspan style=3D3D"font-si=3D
>=3B >=3B>=3Bze: 12pt=3D3= > >B ">=3B&=3Bnbsp=3D3B &=3Bnbsp=3D3B<=3B/span>=3B<=3Bspan style= > >=3D3D"font-size: 12pt=3D3B ">=3B&=3B=3D
>=3B >=3B>=3Bnbsp=3D3= > >B<=3B/span>=3B<=3B/div>=3B<=3Bdiv>=3B<=3Bspan style=3D3D"font= > >-size: 12pt=3D3B ">=3B&=3Bnbsp=3D3B &=3Bnbsp=3D
>=3B >=3B>= > >=3B=3D3B<=3B/span>=3B<=3Bspan style=3D3D"font-size: 12pt=3D3B ">=3B= > >&=3Bnbsp=3D3B<=3B/span>=3Bvector&=3Blt=3D3Bin=3D
>=3B >=3B= > >>=3Bt&=3Bgt=3D3B a=3D3B<=3Bspan style=3D3D"font-size: 12pt=3D3B ">= > >=3B&=3Bnbsp=3D3B &=3Bnbsp=3D3B<=3B/span>=3B<=3Bsp=3D
>=3B = > >>=3B>=3Ban style=3D3D"font-size: 12pt=3D3B ">=3B&=3Bnbsp=3D3B<= > >=3B/span>=3B<=3B/div>=3B<=3Bdiv>=3B<=3Bspan style=3D3D"f=3D
= > >>=3B >=3B>=3Bont-size: 12pt=3D3B ">=3B&=3Bnbsp=3D3B &=3Bnbsp= > >=3D3B<=3B/span>=3B<=3Bspan style=3D3D"font-size: 12pt=3D
>=3B &g= > >t=3B>=3B=3D3B ">=3B&=3Bnbsp=3D3B<=3B/span>=3Ba.push_back(...)=3D= > >3B<=3Bspan style=3D3D"font-size: 12pt=3D3B "=3D
>=3B >=3B>=3B>= > >=3B&=3Bnbsp=3D3B &=3Bnbsp=3D3B<=3B/span>=3B<=3Bspan style=3D3D"= > >font-size: 12pt=3D3B ">=3B&=3Bnbsp=3D3B<=3B/span=3D
>=3B >=3B= > >>=3B>=3B<=3B/div>=3B<=3Bdiv>=3B<=3Bdiv>=3B<=3Bspan style= > >=3D3D"font-size: 12pt=3D3B ">=3B&=3Bnbsp=3D3B &=3Bnbsp=3D3B<=3B/s= > >pa=3D
>=3B >=3B>=3Bn>=3B<=3Bspan style=3D3D"font-size: 12pt=3D= > >3B ">=3B&=3Bnbsp=3D3B<=3B/span>=3Ba.push_back(...)=3D3B<=3Bsp=3D= > >
>=3B >=3B>=3Ban style=3D3D"font-size: 12pt=3D3B ">=3B&=3Bnbs= > >p=3D3B &=3Bnbsp=3D3B<=3B/span>=3B<=3Bspan style=3D3D"fon=3D
>= > >=3B >=3B>=3Bt-size: 12pt=3D3B ">=3B&=3Bnbsp=3D3B<=3B/span>=3B&= > >lt=3B/div>=3B<=3Bdiv>=3B<=3Bspan style=3D3D"font-size: 12pt=3D
&= > >gt=3B >=3B>=3B=3D3B ">=3B&=3Bnbsp=3D3B &=3Bnbsp=3D3B<=3B/span= > >>=3B<=3Bspan style=3D3D"font-size: 12pt=3D3B ">=3B&=3Bnbsp=3D3B<= > >=3B=3D
>=3B >=3B>=3B/span>=3Bstd::sort(a.begin()=3D2C a.end())= > >=3D3B<=3Bspan style=3D3D"font-size: 12pt=3D3B "=3D
>=3B >=3B>=3B= > >>=3B&=3Bnbsp=3D3B &=3Bnbsp=3D3B<=3B/span>=3B<=3Bspan style=3D= > >3D"font-size: 12pt=3D3B ">=3B&=3Bnbsp=3D3B<=3B/span=3D
>=3B >= > >=3B>=3B>=3B<=3B/div>=3B<=3Bdiv>=3B<=3Bspan style=3D3D"font-si= > >ze: 12pt=3D3B ">=3B&=3Bnbsp=3D3B &=3Bnbsp=3D3B<=3B/span>=3B<= > >=3Bsp=3D
>=3B >=3B>=3Ban style=3D3D"font-size: 12pt=3D3B ">=3B&a= > >mp=3Bnbsp=3D3B<=3B/span>=3Ba.resize(std::unique(a.begi=3D
>=3B >= > >=3B>=3Bn()=3D2C a.end()) - a.begin())=3D3B<=3Bspan style=3D3D"font-size= > >: 12pt=3D3B ">=3B&=3Bnbsp=3D3B=3D
>=3B >=3B>=3B &=3Bnbsp= > >=3D3B<=3B/span>=3B<=3Bspan style=3D3D"font-size: 12pt=3D3B ">=3B&am= > >p=3Bnbsp=3D3B<=3B/span>=3B<=3B/div>=3B<=3Bd=3D
>=3B >=3B&g= > >t=3Biv>=3B<=3Bspan style=3D3D"font-size: 12pt=3D3B ">=3B&=3Bnbsp= > >=3D3B &=3Bnbsp=3D3B for (auto i =3D3D a.=3D
>=3B >=3B>=3Bbegin(= > >)=3D3B i !=3D3D a.end()=3D3B ++i)<=3B/span>=3B<=3B/div>=3B<=3Bdiv= > >>=3B<=3Bspan style=3D3D"font-size=3D
>=3B >=3B>=3B: 12pt=3D3B = > >">=3B&=3Bnbsp=3D3B &=3Bnbsp=3D3B {<=3Bbr>=3B&=3Bnbsp=3D3B &a= > >mp=3Bnbsp=3D3B &=3Bnbsp=3D3B do stuff with=3D
>=3B >=3B>=3B *i&= > >lt=3B/span>=3B<=3B/div>=3B<=3Bdiv>=3B<=3Bspan style=3D3D"font-s= > >ize: 12pt=3D3B ">=3B&=3Bnbsp=3D3B &=3Bnbsp=3D3B =3D
>=3B >= > >=3B>=3B}<=3B/span>=3B<=3B/div>=3B<=3Bdiv>=3B&=3Bnbsp=3D3B&= > >lt=3B/div>=3B<=3Bdiv>=3B<=3Bbr>=3B<=3B/div>=3B<=3Bdiv>=3B= > ><=3Bspan style=3D3D"font-si=3D
>=3B >=3B>=3Bze: 12pt=3D3B ">= > >=3B&=3Bnbsp=3D3B &=3Bnbsp=3D3B<=3B/span>=3B<=3Bspan style=3D3D"= > >font-size: 12pt=3D3B ">=3B&=3B=3D
>=3B >=3B>=3Bnbsp=3D3B<= > >=3B/span>=3BNice=3D2C terse=3D2C efficient.<=3Bspan style=3D3D"font-siz= > >e: 12pt=3D3B =3D
>=3B >=3B>=3B">=3B&=3Bnbsp=3D3B &=3Bnbsp= > >=3D3B<=3B/span>=3B<=3Bspan style=3D3D"font-size: 12pt=3D3B ">=3B&am= > >p=3Bnbsp=3D3B<=3B/spa=3D
>=3B >=3B>=3Bn>=3B<=3B/div>=3B<= > >=3Bdiv>=3B<=3Bspan style=3D3D"font-size: 12pt=3D3B ">=3B&=3Bnbsp= > >=3D3B &=3Bnbsp=3D3B<=3B/span>=3B<=3Bs=3D
>=3B >=3B>=3Bpan= > > style=3D3D"font-size: 12pt=3D3B ">=3B&=3Bnbsp=3D3B<=3B/span>=3BIn= > > Modula-3?<=3Bspan style=3D3D=3D
>=3B >=3B>=3B"font-size: 12pt= > >=3D3B ">=3B&=3Bnbsp=3D3B &=3Bnbsp=3D3B<=3B/span>=3B<=3Bspan s= > >tyle=3D3D"font-size: 12p=3D
>=3B >=3B>=3Bt=3D3B ">=3B&=3Bnbsp= > >=3D3B<=3B/span>=3B<=3B/div>=3B<=3Bdiv>=3B<=3Bbr>=3B<=3B/d= > >iv>=3B<=3Bdiv>=3B<=3Bbr>=3B<=3B/div>=3B<=3Bdiv>=3BI know = > >that =3D
>=3B >=3B>=3Bunique is one of the easiest algorithms to m= > >anually write inline=3D2C<=3B/div>=3B<=3Bd=3D
>=3B >=3B>=3Bi= > >v>=3Bbut I shouldn't have to.<=3B/div>=3B<=3Bdiv>=3B<=3Bbr>= > >=3B<=3B/div>=3B<=3Bdiv>=3B<=3Bbr>=3B<=3B/div>=3B<=3Bdiv&g= > >t=3B(I'm re=3D
>=3B >=3B>=3Bally trying to stay in Modula-3 here= > >=3D2C but it is definitely a struggle. :(=3D
>=3B >=3B>=3B )<=3B= > >/div>=3B<=3Bdiv>=3B<=3Bbr>=3B<=3B/div>=3B<=3Bdiv>=3B<= > >=3Bbr>=3B<=3B/div>=3B<=3Bdiv>=3BThank you=3D2C<=3B/div>=3B<= > >=3Bdiv>=3B&=3Bnbsp=3D3B-=3D
>=3B >=3B>=3B Jay<=3B/div>=3B= > ><=3Bbr>=3B<=3Bbr>=3B<=3B/div>=3B <=3B/div>=3B<= > >=3B/body>=3B
>=3B >=3B>=3B<=3B/html>=3B=3D
>=3B >=3B&= > >gt=3B
>=3B >=3B>=3B--_d2a02ece-d492-410e-88fb-fb53737d7219_--
<= > >/div>
> >= > > > >--_7877d7e8-cb4a-4989-bdcd-d406e5b1f51f_-- -------------- next part -------------- An HTML attachment was scrubbed... URL: From mika at async.caltech.edu Sat Sep 29 22:10:33 2012 From: mika at async.caltech.edu (mika at async.caltech.edu) Date: Sat, 29 Sep 2012 13:10:33 -0700 Subject: [M3devel] STL algorithms? sort/unique? In-Reply-To: References: <20120928075656.751E21A2082@async.async.caltech.edu>, <20120928080448.C80DD1A2082@async.async.caltech.edu> , <20120929182948.6589C1A2082@async.async.caltech.edu> Message-ID: <20120929201033.52DE71A2082@async.async.caltech.edu> Yeah, OK, you could do this with GENERICs as well, by introducing a convention. (In fact there is already one, t.iterate.) I still say it's a bit of a bug. If you have very generic methods that can take different orders of time, then applying quicksort to a data structure with high time complexity for those methods won't be very quick at all (except to type). It can be very misleading unless you really know how everything hangs together under the covers. I think that's the C/C++ mentality in general... (BTW I think C++ is a truly impressive programming language. The way you can do OO programming without using the heap is really impressive. I just don't trust myself, or anyone I know, to use it right. When even Stroustrup writes in his book, about certain features, "ask an expert if you want to do this" you have to wonder.) Jay K writes: >--_13e6ee6a-034c-469d-aa83-18379d050866_ >Content-Type: text/plain; charset="iso-8859-1" >Content-Transfer-Encoding: quoted-printable > > > The separation of algorithms from containers sounds a bit like a bug. >It isn't. It is a leap that allows for far greater code reuse. Efficiently.= >(You could do it inefficiently with lots of function pointers -- templates = >allowfor inlinability. C++ beats C for performance here.) > >Imagine I have written quicksort.In C++ we have at least the following wort= >hwhile "array-like" data structures: > > The builtin arrays. Like Modula-3 fixed arrays. > > Arrays you get with new[]. Like Modula-3 open arrays=2C but they don't ex= >pose their size. > > std::vector<>. Like Modula-3 "sequence" -- a simple growable array. Grows= > by a constant factor greater than 1 (typically 2)=2C so that long runs of = >"appends" are amortized cheap. > > std::deque<>. More like Modula-3 sequence=2C in that you can amortized ch= >eap at/remove from the front or the back. I believe this can be implemented= > as simply an "offset array". Element 0 starts in the middle=2C and wheneve= >r you grow it=2C you "center" it -- equal gaps at front and back. > >Now=2C with the iterator/algorithm separation=2C one quicksort implementati= >on can be applied to all these types. The input to "quicksort" is "random a= >ccess iterators"=2C which is very much like a "pointer"=2C but isn't necess= >arily a pointer. It can be incremented=2C decremented=2C added to an intege= >r=2C subtracted from another iterator=2C have an integer subtracted from it= >=2C dereferenced=2C and assigned and compared with other iterators of the s= >ame type -- all constant time fast operations. > >There are "input iterators" which can=2C roughly speaking=2C only be increm= >ented and dereferenced. They are all some containers can expose and all som= >e algorithms require -- for example=2C a singly linked list and linear sear= >ch. > >There are "bidirectional iterators" which can=2C roughly speaking=2C only b= >e incremented and decremented and dereferenced. Doubly linked lists expose = >these. > >There are "output iterators".They are similar to "input". > >input streams (cin=2C like stdin) exposes an input iterator.You can copy fr= >om it.Copy is another simple reusable algorithm. > >output streams (cout=2C like stdout) exposes an output iterator.You can cop= >y to it. > >There are many more examples.Of course=2C besides quick sort=2C there is a = >stable sort.There is finding sequences.There is binary_search.There is uppe= >r_bound/lower_bound/equal_range which are like binary_search.There is uniqu= >e.There is partition.Many many more=2C "built in" to the library.That work = >with multiple "built in" containers=2C and can work with custom containers = >as well. > >I strongly recommend you read up on this stuff.It is really quite illimunin= >ating. Good stuff.Teaches us how to better factor our code.And to strive fo= >r better factoring=2C when we find people have invented/discovered such thi= >ngs. > >"Iterators" already do occur in Modula-3 libraries. > >All I want is a sorted vector that "closely knows" when it is being written= > vs. read=2C and when there are a series of writes with no intervening read= >s=2C it can amortize down the cost of maintaining the ordering. > >I hand coded something.It took me a while to get it to work due to stupid s= >mall details.The result is significantly worse than I would have gotten in = >C++.Bigger code. Slower code. More copies. More heap allocations.I can elim= >inate one of the allocations by merging the next step.But in C++ I naturall= >y wouldn't have had it anyway.Not great. > > - Jay > > >> To: jay.krell at cornell.edu >> CC: mika at async.caltech.edu=3B m3devel at elegosoft.com >> Subject: Re: [M3devel] STL algorithms? sort/unique? >> Date: Sat=2C 29 Sep 2012 11:29:48 -0700 >> From: mika at async.caltech.edu >>=20 >>=20 >> Well that depends on how you maintain the vector=2C no? >>=20 >> SortedTable uses "treaps" which are supposed to be good data structures. >> Too new to have made it into Knuth=2C last I checked. The amortized cost >> of your operations shouldn't be much worse than with your method=2C with >> the additional benefit that the sorted order is maintained dynamically. >>=20 >> The separation of algorithms from containers sounds a bit like a bug. >> You have to be careful so you don't shoot yourself in the foot there! >> (Sorting a list using an algorithm that randomly accesses elements=2C >> say...) >>=20 >> The Modula-3 approach is that you figure out what you want to do=2C pick >> the ADT you want that provides the minimal set of operations=2C import >> that interface=2C then instantiate a more carefully chosen implementation >> of the ADT. The language itself obviously can be coaxed into supporting = >the >> algorithm/data structure separation but no one uses it that way as >> far as I know. (Modula-3 generics are not that well explored=2C actually= >. >> I suspect there are many things you can do with them that no one has >> tried.) >>=20 >> Mika >>=20 >> Jay K writes: >> >--_7877d7e8-cb4a-4989-bdcd-d406e5b1f51f_ >> >Content-Type: text/plain=3B charset=3D"iso-8859-1" >> >Content-Transfer-Encoding: quoted-printable >> > >> >The following is very efficient: >> > >> >run through a bunch of records=3D2C picking out one number from some of = >thema=3D >> >ppend those numbers to a growing vectorsort the vectorunique the vector >> > >> >sequence allows for random access..but only via a function...or maybe an= > it=3D >> >erator >> > >> >STL has this wonderful separation of algorithms from containers=3D2C via= > iter=3D >> >ators.I suspect very few other libraries do.And it could be that most la= >ngu=3D >> >ages don't support it.It doesn't appear I can easily sort a sequence=3D2= >C unl=3D >> >ess I copy the data out into an array -- gross inefficiency. >> > >> >I've hacked something very manual together..and it is taking forever to = >get=3D >> > it to work. It turns out I can reasonably well bound the size of the d= >ata=3D >> >=3D2C so I'm using an open array...and I have to keep track of my positi= >on in=3D >> >stead of using addhi/push_back.Not happy.At some point I might give up a= >nd =3D >> >write the backend in C++..at which point I might as well write a C++ fro= >nte=3D >> >nd anywa. >> > >> > >> >I absolutely do not want a sorted table and unique upon insert.That is m= >uch=3D >> > less efficient.What I'm describing uses temporarily larger working set = >but=3D >> > vastly less CPU.An array that gets sorted/uniqued occasionally=3D2C lik= >e jus=3D >> >t once.And not ongoing maintainence for every single add. >> > >> > >> > - Jay >> > >> > >> >> To: jay.krell at cornell.edu >> >> CC: m3devel at elegosoft.com >> >> Subject: Re: [M3devel] STL algorithms? sort/unique? >> >> Date: Fri=3D2C 28 Sep 2012 01:04:48 -0700 >> >> From: mika at async.caltech.edu >> >>=3D20 >> >>=3D20 >> >> BTW I had the same experience when I first started using Modula-3. >> >> It was painful to jump through all its hoops=3D2C coming from C=3D2C w= >here yo=3D >> >u >> >> can do whatever you want to whatever bits happen to be sloshing around >> >> your machine. C++ from what I have seen mainly lets you do that to >> >> more bits in fewer lines of code. >> >>=3D20 >> >> But after a while I really came to appreciate the value of things like= > th=3D >> >e >> >> language's telling me I'm using the wrong data structure instead of >> >> just letting me use the same "nice=3D2C terse=3D2C efficient" syntax t= >o write >> >> a crappy program :-) >> >>=3D20 >> >> mika writes: >> >> >You're using the wrong (abstract) data structure if you want sort and= > un=3D >> >ique. >> >> > >> >> >A "sequence" is meant to be accessed sequentially... >> >> > >> >> >Not knowing precisely what you're doing it sounds like you might want= > a >> >> >SortedTable... you can get unique on insert and access it in increasi= >ng >> >> >or decreasing order. >> >> > >> >> > Mika >> >> > >> >> >Jay K writes: >> >> >>--_d2a02ece-d492-410e-88fb-fb53737d7219_ >> >> >>Content-Type: text/plain=3D3B charset=3D3D"iso-8859-1" >> >> >>Content-Transfer-Encoding: quoted-printable >> >> >> >> >> >> I have an IntSeq.T with a bunch of integers. =3D3D20 >> >> >> What is a good terse efficient idiom for sort and unique? =3D3= >D20 >> >> >> >> >> >> In C++ I would say: vector a=3D3D3B a.push_ba= >ck(..=3D >> >.)=3D3D3B =3D3D >> >> >> a.push_back(...)=3D3D3B std::sort(a.begin()=3D3D2C a.e= >nd())=3D >> >=3D3D3B =3D3D >> >> >> a.resize(std::unique(a.begin()=3D3D2C a.end()) - a.begin())=3D3D3B = > =3D >> >for (aut=3D3D >> >> >>o i =3D3D3D a.begin()=3D3D3B i !=3D3D3D a.end()=3D3D3B ++i) { >> >> >> do stuff with *i }=3D3D20 >> >> >> Nice=3D3D2C terse=3D3D2C efficient. In Modula-3? =3D3D2= >0 >> >> >> >> >> >>I know that unique is one of the easiest algorithms to manually writ= >e i=3D >> >nlin=3D3D >> >> >>e=3D3D2Cbut I shouldn't have to. >> >> >> >> >> >>(I'm really trying to stay in Modula-3 here=3D3D2C but it is definit= >ely a=3D >> > strug=3D3D >> >> >>gle. :( ) >> >> >> >> >> >>Thank you=3D3D2C - Jay >> >> >> >> >> >> =3D3D >> >> >> >> >> >>--_d2a02ece-d492-410e-88fb-fb53737d7219_ >> >> >>Content-Type: text/html=3D3B charset=3D3D"iso-8859-1" >> >> >>Content-Transfer-Encoding: quoted-printable >> >> >> >> >> >> >> >> >> >> >> >> >> >> >>
 =3D3D3B &nbs= >p=3D3D3B&nb=3D >> >sp=3D3D3BI have =3D3D >> >> >>an IntSeq.T with a bunch of integers. =3D3D3B  =3D3D3B = >=3D3D3B> >>
> >> >>n style=3D3D3D"font-size: 12pt=3D3D3B "> =3D3D3B  =3D3D3Bpan>> >tyle=3D3D3D"font=3D3D >> >> >>-size: 12pt=3D3D3B "> =3D3D3BWhat is a good terse efficie= >nt idio=3D >> >m for so=3D3D >> >> >>rt and unique? =3D3D= >3B  =3D >> >=3D3D3B<=3D3D >> >> >>span style=3D3D3D"font-size: 12pt=3D3D3B "> =3D3D3B
= >

=3D >> >
> >> >>>
 =3D3D3B  =3D3D3B In C++ I would say:tyle=3D3D=3D >> >3D"font-si=3D3D >> >> >>ze: 12pt=3D3D3B "> =3D3D3B  =3D3D3B"font-size:=3D >> > 12pt=3D3D3B ">&=3D3D >> >> >>nbsp=3D3D3B
3B ">&nbs=3D >> >p=3D3D3B  =3D3D >> >> >>=3D3D3B =3D3D= >3Bve=3D >> >ctor<=3D3D3Bin=3D3D >> >> >>t>=3D3D3B a=3D3D3B&nbs= >p=3D3D3B &nbs=3D >> >p=3D3D3B> >> >>an style=3D3D3D"font-size: 12pt=3D3D3B "> =3D3D3B
iv>> >style=3D3D3D"f=3D3D >> >> >>ont-size: 12pt=3D3D3B "> =3D3D3B  =3D3D3B=3D3D3D"font=3D >> >-size: 12pt=3D3D >> >> >>=3D3D3B "> =3D3D3Ba.push_back(...)=3D3D3B3D"font-siz=3D >> >e: 12pt=3D3D3B "=3D3D >> >> >>> =3D3D3B  =3D3D3B=3D3D3B ">&n=3D >> >bsp=3D3D3B> >> >>>
 = >=3D3D3B &nb=3D >> >sp=3D3D3B> >> >>n> =3D3D3Ba.p= >ush_back(=3D >> >...)=3D3D3B> >> >>an style=3D3D3D"font-size: 12pt=3D3D3B "> =3D3D3B  =3D3D3Bspan>> >style=3D3D3D"fon=3D3D >> >> >>t-size: 12pt=3D3D3B "> =3D3D3B
3D"font-s=3D >> >ize: 12pt=3D3D >> >> >>=3D3D3B "> =3D3D3B  =3D3D3Bze: 12pt=3D3D=3D >> >3B "> =3D3D3B<=3D3D >> >> >>/span>std::sort(a.begin()=3D3D2C a.end())=3D3D3Bont-size:=3D >> > 12pt=3D3D3B "=3D3D >> >> >>> =3D3D3B  =3D3D3B=3D3D3B ">&n=3D >> >bsp=3D3D3B> >> >>>
 =3D3D3B= >  =3D3D=3D >> >3B> >> >>an style=3D3D3D"font-size: 12pt=3D3D3B "> =3D3D3Ba.resize= >(std::uni=3D >> >que(a.begi=3D3D >> >> >>n()=3D3D2C a.end()) - a.begin())=3D3D3B 12pt=3D3D3=3D >> >B "> =3D3D3B=3D3D >> >> >>  =3D3D3B&nbs= >p=3D3D3B> >pan>
> >> >>iv> =3D3D3B  =3D= >3D3B for (a=3D >> >uto i =3D3D3D a.=3D3D >> >> >>begin()=3D3D3B i !=3D3D3D a.end()=3D3D3B ++i)
style=3D3D=3D >> >3D"font-size=3D3D >> >> >>: 12pt=3D3D3B "> =3D3D3B  =3D3D3B {
 =3D3D3B  =3D= >3D3B  =3D3D=3D >> >3B do stuff with=3D3D >> >> >> *i
&nb= >sp=3D3D3B=3D >> >  =3D3D3B =3D3D >> >> >>}
 =3D3D3B

=3D3D3D=3D >> >"font-si=3D3D >> >> >>ze: 12pt=3D3D3B "> =3D3D3B  =3D3D3B"font-size:=3D >> > 12pt=3D3D3B ">&=3D3D >> >> >>nbsp=3D3D3BNice=3D3D2C terse=3D3D2C efficient.D3D"font-si=3D >> >ze: 12pt=3D3D3B =3D3D >> >> >>"> =3D3D3B  =3D3D3B=3D3D3B ">&=3D >> >nbsp=3D3D3B> >> >>n>
 =3D3D3= >B  =3D >> >=3D3D3B> >> >>pan style=3D3D3D"font-size: 12pt=3D3D3B "> =3D3D3BIn Modu= >la-3?> >n style=3D3D3D=3D3D >> >> >>"font-size: 12pt=3D3D3B "> =3D3D3B  =3D3D3Be=3D3D3D"fo=3D >> >nt-size: 12p=3D3D >> >> >>t=3D3D3B "> =3D3D3B


iv>I kn=3D >> >ow that =3D3D >> >> >>unique is one of the easiest algorithms to manually write inline=3D3= >D2C> >div>> >> >>iv>but I shouldn't have to.


= >(I'=3D >> >m re=3D3D >> >> >>ally trying to stay in Modula-3 here=3D3D2C but it is definitely a s= >trugg=3D >> >le. :(=3D3D >> >> >> )


Thank you=3D3D2C
v>&nb=3D >> >sp=3D3D3B-=3D3D >> >> >> Jay


>> >> >>=3D3D >> >> >> >> >> >>--_d2a02ece-d492-410e-88fb-fb53737d7219_-- >> > =3D >> > >> >--_7877d7e8-cb4a-4989-bdcd-d406e5b1f51f_ >> >Content-Type: text/html=3B charset=3D"iso-8859-1" >> >Content-Transfer-Encoding: quoted-printable >> > >> > >> > >> > >> >
t-size: 1=3D >> >2pt=3D3B ">The following is very efficient:

<= >div><=3D >> >br>
run through a bunch of records=3D2C picking out one number= > from=3D >> > some of them
append those numbers to a growing vector
iv>=3D >> >sort the vector
unique the vector

>> >div>
sequence allows for random access..but only via a function...div=3D >> >>
or maybe an iterator


STL h= >as =3D >> >this wonderful separation of algorithms from containers=3D2C via iterato= >rs.> >div>
I suspect very few other libraries do.
And it could b= >e t=3D >> >hat most languages don't support it.
It doesn't appear I can e= >asi=3D >> >ly sort a sequence=3D2C unless I copy the data out into an array -- gros= >s ine=3D >> >fficiency.


I've hacked something= > ve=3D >> >ry manual together..and it is taking forever to get it to work.
v>&=3D >> >nbsp=3D3B It turns out I can reasonably well bound the size of the data= >=3D2C so=3D >> > I'm using an open array...and I have to keep track of my position inste= >ad =3D >> >of using addhi/push_back.
Not happy.
At some point I= > mi=3D >> >ght give up and write the backend in C++..at which point I might as well= > wr=3D >> >ite a C++ frontend anywa.



div=3D >> >>
I absolutely do not want a sorted table and unique upon insert.iv>=3D >> >
That is much less efficient.
What I'm describing uses tem= >por=3D >> >arily larger working set but vastly less CPU.
An array that ge= >ts =3D >> >sorted/uniqued occasionally=3D2C like just once.
And not ongoi= >ng ma=3D >> >intainence for every single add.


>> >r>
 =3D3B- Jay



DrivePl=3D >> >aceholder">
>=3D3B To: jay.krell at cornell.edu
>=3D3B CC: m3de= >vel at ele=3D >> >gosoft.com
>=3D3B Subject: Re: [M3devel] STL algorithms? sort/uniqu= >e?> >>>=3D3B Date: Fri=3D2C 28 Sep 2012 01:04:48 -0700
>=3D3B From: mi= >ka at async.=3D >> >caltech.edu
>=3D3B
>=3D3B
>=3D3B BTW I had the same exp= >erience w=3D >> >hen I first started using Modula-3.
>=3D3B It was painful to jump t= >hroug=3D >> >h all its hoops=3D2C coming from C=3D2C where you
>=3D3B can do wha= >tever you=3D >> > want to whatever bits happen to be sloshing around
>=3D3B your mac= >hine.=3D >> > C++ from what I have seen mainly lets you do that to
>=3D3B more = >bits =3D >> >in fewer lines of code.
>=3D3B
>=3D3B But after a while I rea= >lly cam=3D >> >e to appreciate the value of things like the
>=3D3B language's tell= >ing m=3D >> >e I'm using the wrong data structure instead of
>=3D3B just letting= > me u=3D >> >se the same "nice=3D2C terse=3D2C efficient" syntax to write
>=3D3B= > a crappy=3D >> > program :-)
>=3D3B
>=3D3B mika writes:
>=3D3B >=3D3BY= >ou're using=3D >> > the wrong (abstract) data structure if you want sort and unique.
>= >=3D3B=3D >> > >=3D3B
>=3D3B >=3D3BA "sequence" is meant to be accessed seque= >ntially..=3D >> >.
>=3D3B >=3D3B
>=3D3B >=3D3BNot knowing precisely what yo= >u're doing =3D >> >it sounds like you might want a
>=3D3B >=3D3BSortedTable... you c= >an get =3D >> >unique on insert and access it in increasing
>=3D3B >=3D3Bor decr= >easing =3D >> >order.
>=3D3B >=3D3B
>=3D3B >=3D3B Mika
>=3D3B >= >=3D3B
>=3D3B=3D >> > >=3D3BJay K writes:
>=3D3B >=3D3B>=3D3B--_d2a02ece-d492-410e= >-88fb-fb537=3D >> >37d7219_
>=3D3B >=3D3B>=3D3BContent-Type: text/plain=3D3B chars= >et=3D3D"iso-8=3D >> >859-1"
>=3D3B >=3D3B>=3D3BContent-Transfer-Encoding: quoted-pri= >ntable> >>>=3D3B >=3D3B>=3D3B
>=3D3B >=3D3B>=3D3B I have an Int= >Seq.T with a bu=3D >> >nch of integers. =3D3D20
>=3D3B >=3D3B>=3D3B What is a goo= >d terse eff=3D >> >icient idiom for sort and unique? =3D3D20
>=3D3B >=3D3B>=3D3B= >
>=3D3B =3D >> >>=3D3B>=3D3B In C++ I would say: vector<=3D3Bint>=3D3B= > a=3D3D3B =3D >> > a.push_back(...)=3D3D3B =3D3D
>=3D3B >=3D3B>=3D3B a.p= >ush_back(...)=3D >> >=3D3D3B std::sort(a.begin()=3D3D2C a.end())=3D3D3B =3D3D>>=3D3B >=3D >> >=3D3B>=3D3B a.resize(std::unique(a.begin()=3D3D2C a.end()) - a.begin()= >)=3D3D3B =3D >> > for (aut=3D3D
>=3D3B >=3D3B>=3D3Bo i =3D3D3D a.begin()=3D3= >D3B i !=3D3D3D a.=3D >> >end()=3D3D3B ++i) {
>=3D3B >=3D3B>=3D3B do stuff with *= >i }=3D3D20=3D >> >
>=3D3B >=3D3B>=3D3B Nice=3D3D2C terse=3D3D2C efficient. = > In Modula=3D >> >-3? =3D3D20
>=3D3B >=3D3B>=3D3B
>=3D3B >=3D3B>=3D3BI= > know that unique=3D >> > is one of the easiest algorithms to manually write inlin=3D3D
>=3D= >3B >=3D >> >=3D3B>=3D3Be=3D3D2Cbut I shouldn't have to.
>=3D3B >=3D3B>=3D= >3B
>=3D3B &g=3D >> >t=3D3B>=3D3B(I'm really trying to stay in Modula-3 here=3D3D2C but it = >is defini=3D >> >tely a strug=3D3D
>=3D3B >=3D3B>=3D3Bgle. :( )
>=3D3B >= >=3D3B>=3D3B
&=3D >> >gt=3D3B >=3D3B>=3D3BThank you=3D3D2C - Jay
>=3D3B >=3D3B>= >=3D3B
>=3D3B >=3D >> >=3D3B>=3D3B =3D3D
>=3D3B >=3D3B>=3D3B
>=3D3B = >>=3D3B>=3D3B--_d2=3D >> >a02ece-d492-410e-88fb-fb53737d7219_
>=3D3B >=3D3B>=3D3BContent-= >Type: tex=3D >> >t/html=3D3B charset=3D3D"iso-8859-1"
>=3D3B >=3D3B>=3D3BContent= >-Transfer-Enc=3D >> >oding: quoted-printable
>=3D3B >=3D3B>=3D3B
>=3D3B >=3D3= >B>=3D3B<=3D3B=3D >> >html>=3D3B
>=3D3B >=3D3B>=3D3B<=3D3Bhead>=3D3B
>=3D3= >B >=3D3B>=3D3B<=3D >> >=3D3Bstyle>=3D3B<=3D3B!--
>=3D3B >=3D3B>=3D3B.hmmessage Pr>>=3D3B >=3D3B=3D >> >>=3D3B{
>=3D3B >=3D3B>=3D3Bmargin:0px=3D3D3B
>=3D3B >= >=3D3B>=3D3Bpadding=3D >> >:0px
>=3D3B >=3D3B>=3D3B}
>=3D3B >=3D3B>=3D3Bbody.hmme= >ssage
>=3D3B=3D >> > >=3D3B>=3D3B{
>=3D3B >=3D3B>=3D3Bfont-size: 12pt=3D3D3B>>=3D3B >=3D3B&=3D >> >gt=3D3Bfont-family:Calibri
>=3D3B >=3D3B>=3D3B}
>=3D3B >= >=3D3B>=3D3B--&g=3D >> >t=3D3B<=3D3B/style>=3D3B<=3D3B/head>=3D3B
>=3D3B >=3D3B&g= >t=3D3B<=3D3Bbody cl=3D >> >ass=3D3D3D'hmmessage'>=3D3B<=3D3Bdiv dir=3D3D3D'ltr'>=3D3B&=3D3= >Bnbsp=3D3D3B &=3D >> >=3D3Bnbsp=3D3D3B&=3D3Bnbsp=3D3D3BI have =3D3D
>=3D3B >=3D3B>= >=3D3Ban IntSeq.T wi=3D >> >th a bunch of integers.&=3D3Bnbsp=3D3D3B &=3D3Bnbsp=3D3D3B&=3D3= >Bnbsp=3D3D3B<=3D >> >=3D3Bbr>=3D3B<=3D3Bdiv>=3D3B<=3D3Bspa=3D3D
>=3D3B >=3D3B&= >gt=3D3Bn style=3D3D3D"f=3D >> >ont-size: 12pt=3D3D3B ">=3D3B&=3D3Bnbsp=3D3D3B &=3D3Bnbsp=3D3D3B= ><=3D3B/span>=3D >> >=3D3B<=3D3Bspan style=3D3D3D"font=3D3D
>=3D3B >=3D3B>=3D3B-si= >ze: 12pt=3D3D3B "&g=3D >> >t=3D3B&=3D3Bnbsp=3D3D3B<=3D3B/span>=3D3BWhat is a good terse effi= >cient idiom f=3D >> >or so=3D3D
>=3D3B >=3D3B>=3D3Brt and unique?<=3D3Bspan style= >=3D3D3D"font-siz=3D >> >e: 12pt=3D3D3B ">=3D3B&=3D3Bnbsp=3D3D3B &=3D3Bnbsp=3D3D3B<=3D3= >B/span>=3D3B<=3D >> >=3D3B=3D3D
>=3D3B >=3D3B>=3D3Bspan style=3D3D3D"font-size: 12pt= >=3D3D3B ">=3D3B&a=3D >> >mp=3D3Bnbsp=3D3D3B<=3D3B/span>=3D3B<=3D3B/div>=3D3B<=3D3Bdiv&g= >t=3D3B<=3D3Bbr>=3D >> >=3D3B<=3D3B/div>=3D3B<=3D3Bdiv=3D3D
>=3D3B >=3D3B>=3D3B&g= >t=3D3B<=3D3Bbr>=3D3B&=3D >> >lt=3D3B/div>=3D3B<=3D3Bdiv>=3D3B&=3D3Bnbsp=3D3D3B &=3D3Bnbsp= >=3D3D3B In C++ I wo=3D >> >uld say:<=3D3Bspan style=3D3D3D"font-si=3D3D
>=3D3B >=3D3B>= >=3D3Bze: 12pt=3D3D3=3D >> >B ">=3D3B&=3D3Bnbsp=3D3D3B &=3D3Bnbsp=3D3D3B<=3D3B/span>=3D3= >B<=3D3Bspan style=3D >> >=3D3D3D"font-size: 12pt=3D3D3B ">=3D3B&=3D3B=3D3D
>=3D3B >= >=3D3B>=3D3Bnbsp=3D3D3=3D >> >B<=3D3B/span>=3D3B<=3D3B/div>=3D3B<=3D3Bdiv>=3D3B<=3D3Bspa= >n style=3D3D3D"font=3D >> >-size: 12pt=3D3D3B ">=3D3B&=3D3Bnbsp=3D3D3B &=3D3Bnbsp=3D3D
&= >gt=3D3B >=3D3B>=3D >> >=3D3B=3D3D3B<=3D3B/span>=3D3B<=3D3Bspan style=3D3D3D"font-size: 12= >pt=3D3D3B ">=3D3B=3D >> >&=3D3Bnbsp=3D3D3B<=3D3B/span>=3D3Bvector&=3D3Blt=3D3D3Bin=3D3D= >
>=3D3B >=3D3B=3D >> >>=3D3Bt&=3D3Bgt=3D3D3B a=3D3D3B<=3D3Bspan style=3D3D3D"font-size:= > 12pt=3D3D3B ">=3D >> >=3D3B&=3D3Bnbsp=3D3D3B &=3D3Bnbsp=3D3D3B<=3D3B/span>=3D3B<= >=3D3Bsp=3D3D
>=3D3B =3D >> >>=3D3B>=3D3Ban style=3D3D3D"font-size: 12pt=3D3D3B ">=3D3B&=3D3= >Bnbsp=3D3D3B<=3D >> >=3D3B/span>=3D3B<=3D3B/div>=3D3B<=3D3Bdiv>=3D3B<=3D3Bspan st= >yle=3D3D3D"f=3D3D
=3D >> >>=3D3B >=3D3B>=3D3Bont-size: 12pt=3D3D3B ">=3D3B&=3D3Bnbsp=3D= >3D3B &=3D3Bnbsp=3D >> >=3D3D3B<=3D3B/span>=3D3B<=3D3Bspan style=3D3D3D"font-size: 12pt=3D= >3D
>=3D3B &g=3D >> >t=3D3B>=3D3B=3D3D3B ">=3D3B&=3D3Bnbsp=3D3D3B<=3D3B/span>=3D3B= >a.push_back(...)=3D3D=3D >> >3B<=3D3Bspan style=3D3D3D"font-size: 12pt=3D3D3B "=3D3D
>=3D3B &g= >t=3D3B>=3D3B>=3D >> >=3D3B&=3D3Bnbsp=3D3D3B &=3D3Bnbsp=3D3D3B<=3D3B/span>=3D3B<= >=3D3Bspan style=3D3D3D"=3D >> >font-size: 12pt=3D3D3B ">=3D3B&=3D3Bnbsp=3D3D3B<=3D3B/span=3D3Dr>>=3D3B >=3D3B=3D >> >>=3D3B>=3D3B<=3D3B/div>=3D3B<=3D3Bdiv>=3D3B<=3D3Bdiv>=3D= >3B<=3D3Bspan style=3D >> >=3D3D3D"font-size: 12pt=3D3D3B ">=3D3B&=3D3Bnbsp=3D3D3B &=3D3Bnb= >sp=3D3D3B<=3D3B/s=3D >> >pa=3D3D
>=3D3B >=3D3B>=3D3Bn>=3D3B<=3D3Bspan style=3D3D3D"f= >ont-size: 12pt=3D3D=3D >> >3B ">=3D3B&=3D3Bnbsp=3D3D3B<=3D3B/span>=3D3Ba.push_back(...)=3D= >3D3B<=3D3Bsp=3D3D=3D >> >
>=3D3B >=3D3B>=3D3Ban style=3D3D3D"font-size: 12pt=3D3D3B ">= >=3D3B&=3D3Bnbs=3D >> >p=3D3D3B &=3D3Bnbsp=3D3D3B<=3D3B/span>=3D3B<=3D3Bspan style=3D3= >D3D"fon=3D3D
>=3D >> >=3D3B >=3D3B>=3D3Bt-size: 12pt=3D3D3B ">=3D3B&=3D3Bnbsp=3D3D3B&= >lt=3D3B/span>=3D3B&=3D >> >lt=3D3B/div>=3D3B<=3D3Bdiv>=3D3B<=3D3Bspan style=3D3D3D"font-siz= >e: 12pt=3D3D
&=3D >> >gt=3D3B >=3D3B>=3D3B=3D3D3B ">=3D3B&=3D3Bnbsp=3D3D3B &=3D3Bn= >bsp=3D3D3B<=3D3B/span=3D >> >>=3D3B<=3D3Bspan style=3D3D3D"font-size: 12pt=3D3D3B ">=3D3B&= >=3D3Bnbsp=3D3D3B<=3D >> >=3D3B=3D3D
>=3D3B >=3D3B>=3D3B/span>=3D3Bstd::sort(a.begin()= >=3D3D2C a.end())=3D >> >=3D3D3B<=3D3Bspan style=3D3D3D"font-size: 12pt=3D3D3B "=3D3D
>=3D= >3B >=3D3B>=3D3B=3D >> >>=3D3B&=3D3Bnbsp=3D3D3B &=3D3Bnbsp=3D3D3B<=3D3B/span>=3D3B&l= >t=3D3Bspan style=3D3D=3D >> >3D"font-size: 12pt=3D3D3B ">=3D3B&=3D3Bnbsp=3D3D3B<=3D3B/span=3D3= >D
>=3D3B >=3D >> >=3D3B>=3D3B>=3D3B<=3D3B/div>=3D3B<=3D3Bdiv>=3D3B<=3D3Bspan= > style=3D3D3D"font-si=3D >> >ze: 12pt=3D3D3B ">=3D3B&=3D3Bnbsp=3D3D3B &=3D3Bnbsp=3D3D3B<=3D= >3B/span>=3D3B<=3D >> >=3D3Bsp=3D3D
>=3D3B >=3D3B>=3D3Ban style=3D3D3D"font-size: 12pt= >=3D3D3B ">=3D3B&a=3D >> >mp=3D3Bnbsp=3D3D3B<=3D3B/span>=3D3Ba.resize(std::unique(a.begi=3D3D<= >br>>=3D3B >=3D >> >=3D3B>=3D3Bn()=3D3D2C a.end()) - a.begin())=3D3D3B<=3D3Bspan style= >=3D3D3D"font-size=3D >> >: 12pt=3D3D3B ">=3D3B&=3D3Bnbsp=3D3D3B=3D3D
>=3D3B >=3D3B>= >=3D3B &=3D3Bnbsp=3D >> >=3D3D3B<=3D3B/span>=3D3B<=3D3Bspan style=3D3D3D"font-size: 12pt=3D= >3D3B ">=3D3B&am=3D >> >p=3D3Bnbsp=3D3D3B<=3D3B/span>=3D3B<=3D3B/div>=3D3B<=3D3Bd=3D3D= >
>=3D3B >=3D3B&g=3D >> >t=3D3Biv>=3D3B<=3D3Bspan style=3D3D3D"font-size: 12pt=3D3D3B ">=3D= >3B&=3D3Bnbsp=3D >> >=3D3D3B &=3D3Bnbsp=3D3D3B for (auto i =3D3D3D a.=3D3D
>=3D3B >= >=3D3B>=3D3Bbegin(=3D >> >)=3D3D3B i !=3D3D3D a.end()=3D3D3B ++i)<=3D3B/span>=3D3B<=3D3B/div= >>=3D3B<=3D3Bdiv=3D >> >>=3D3B<=3D3Bspan style=3D3D3D"font-size=3D3D
>=3D3B >=3D3B>= >=3D3B: 12pt=3D3D3B =3D >> >">=3D3B&=3D3Bnbsp=3D3D3B &=3D3Bnbsp=3D3D3B {<=3D3Bbr>=3D3B&a= >mp=3D3Bnbsp=3D3D3B &a=3D >> >mp=3D3Bnbsp=3D3D3B &=3D3Bnbsp=3D3D3B do stuff with=3D3D
>=3D3B &= >gt=3D3B>=3D3B *i&=3D >> >lt=3D3B/span>=3D3B<=3D3B/div>=3D3B<=3D3Bdiv>=3D3B<=3D3Bspan = >style=3D3D3D"font-s=3D >> >ize: 12pt=3D3D3B ">=3D3B&=3D3Bnbsp=3D3D3B &=3D3Bnbsp=3D3D3B =3D3= >D
>=3D3B >=3D >> >=3D3B>=3D3B}<=3D3B/span>=3D3B<=3D3B/div>=3D3B<=3D3Bdiv>=3D= >3B&=3D3Bnbsp=3D3D3B&=3D >> >lt=3D3B/div>=3D3B<=3D3Bdiv>=3D3B<=3D3Bbr>=3D3B<=3D3B/div>= >=3D3B<=3D3Bdiv>=3D3B=3D >> ><=3D3Bspan style=3D3D3D"font-si=3D3D
>=3D3B >=3D3B>=3D3Bze: 1= >2pt=3D3D3B ">=3D >> >=3D3B&=3D3Bnbsp=3D3D3B &=3D3Bnbsp=3D3D3B<=3D3B/span>=3D3B<= >=3D3Bspan style=3D3D3D"=3D >> >font-size: 12pt=3D3D3B ">=3D3B&=3D3B=3D3D
>=3D3B >=3D3B>= >=3D3Bnbsp=3D3D3B<=3D >> >=3D3B/span>=3D3BNice=3D3D2C terse=3D3D2C efficient.<=3D3Bspan style= >=3D3D3D"font-siz=3D >> >e: 12pt=3D3D3B =3D3D
>=3D3B >=3D3B>=3D3B">=3D3B&=3D3Bnbsp= >=3D3D3B &=3D3Bnbsp=3D >> >=3D3D3B<=3D3B/span>=3D3B<=3D3Bspan style=3D3D3D"font-size: 12pt=3D= >3D3B ">=3D3B&am=3D >> >p=3D3Bnbsp=3D3D3B<=3D3B/spa=3D3D
>=3D3B >=3D3B>=3D3Bn>=3D3B= ><=3D3B/div>=3D3B<=3D >> >=3D3Bdiv>=3D3B<=3D3Bspan style=3D3D3D"font-size: 12pt=3D3D3B ">=3D= >3B&=3D3Bnbsp=3D >> >=3D3D3B &=3D3Bnbsp=3D3D3B<=3D3B/span>=3D3B<=3D3Bs=3D3D
>= >=3D3B >=3D3B>=3D3Bpan=3D >> > style=3D3D3D"font-size: 12pt=3D3D3B ">=3D3B&=3D3Bnbsp=3D3D3B<=3D= >3B/span>=3D3BIn=3D >> > Modula-3?<=3D3Bspan style=3D3D3D=3D3D
>=3D3B >=3D3B>=3D3B"fo= >nt-size: 12pt=3D >> >=3D3D3B ">=3D3B&=3D3Bnbsp=3D3D3B &=3D3Bnbsp=3D3D3B<=3D3B/span&= >gt=3D3B<=3D3Bspan s=3D >> >tyle=3D3D3D"font-size: 12p=3D3D
>=3D3B >=3D3B>=3D3Bt=3D3D3B "&g= >t=3D3B&=3D3Bnbsp=3D >> >=3D3D3B<=3D3B/span>=3D3B<=3D3B/div>=3D3B<=3D3Bdiv>=3D3B<= >=3D3Bbr>=3D3B<=3D3B/d=3D >> >iv>=3D3B<=3D3Bdiv>=3D3B<=3D3Bbr>=3D3B<=3D3B/div>=3D3B<= >=3D3Bdiv>=3D3BI know =3D >> >that =3D3D
>=3D3B >=3D3B>=3D3Bunique is one of the easiest algo= >rithms to m=3D >> >anually write inline=3D3D2C<=3D3B/div>=3D3B<=3D3Bd=3D3D
>=3D3= >B >=3D3B>=3D3Bi=3D >> >v>=3D3Bbut I shouldn't have to.<=3D3B/div>=3D3B<=3D3Bdiv>=3D3B= ><=3D3Bbr>=3D >> >=3D3B<=3D3B/div>=3D3B<=3D3Bdiv>=3D3B<=3D3Bbr>=3D3B<=3D3B/d= >iv>=3D3B<=3D3Bdiv&g=3D >> >t=3D3B(I'm re=3D3D
>=3D3B >=3D3B>=3D3Bally trying to stay in Mo= >dula-3 here=3D >> >=3D3D2C but it is definitely a struggle. :(=3D3D
>=3D3B >=3D3B>= >=3D3B )<=3D3B=3D >> >/div>=3D3B<=3D3Bdiv>=3D3B<=3D3Bbr>=3D3B<=3D3B/div>=3D3B<= >=3D3Bdiv>=3D3B<=3D >> >=3D3Bbr>=3D3B<=3D3B/div>=3D3B<=3D3Bdiv>=3D3BThank you=3D3D2C&l= >t=3D3B/div>=3D3B<=3D >> >=3D3Bdiv>=3D3B&=3D3Bnbsp=3D3D3B-=3D3D
>=3D3B >=3D3B>=3D3B = >Jay<=3D3B/div>=3D3B=3D >> ><=3D3Bbr>=3D3B<=3D3Bbr>=3D3B<=3D3B/div>=3D3B <= >=3D3B/div>=3D3B<=3D >> >=3D3B/body>=3D3B
>=3D3B >=3D3B>=3D3B<=3D3B/html>=3D3B=3D3= >D
>=3D3B >=3D3B&=3D >> >gt=3D3B
>=3D3B >=3D3B>=3D3B--_d2a02ece-d492-410e-88fb-fb53737d7= >219_--
<=3D >> >/div>
>> >=3D >> > >> >--_7877d7e8-cb4a-4989-bdcd-d406e5b1f51f_-- > = > >--_13e6ee6a-034c-469d-aa83-18379d050866_ >Content-Type: text/html; charset="iso-8859-1" >Content-Transfer-Encoding: quoted-printable > > > > >
818199157715px=3B white-space: normal=3B font-size: 15.454545021057129px=3B=
> background-color: rgb(255=2C 255=2C 255)=3B "> =3B>=3B The separatio=
>n of algorithms from containers sounds a bit like a bug.

v>It isn't. It is a leap that allows for far greater code reuse. Efficientl= >y.
(You could do it inefficiently with lots of function pointers -- tem= >plates allow
for inlinability. C++ beats C for performance here.)= >


Imagine I have written quicks= >ort.
In C++ we have at least the following worthwhile "array-like= >" data structures:


 =3B The bui= >ltin arrays. Like Modula-3 fixed arrays.


>
 =3B Arrays you get with new[]. Like Modula-3 open arrays=2C but = >they don't expose their size.


 = >=3B std::vector<=3B>=3B. Like Modula-3 "sequence" -- a simple growable = >array. Grows by a constant factor greater than 1 (typically 2)=2C so that l= >ong runs of "appends" are amortized cheap.


iv>
 =3B std::deque<=3B>=3B. More like Modula-3 sequence=2C in = >that you can amortized cheap at/remove from the front or the back. I believ= >e this can be implemented as simply an "offset array". Element 0 starts in = >the middle=2C and whenever you grow it=2C you "center" it -- equal gaps at = >front and back.


Now=2C with the ite= >rator/algorithm separation=2C one quicksort implementation can be applied t= >o all these types. The input to "quicksort" is "random access iterators"=2C= > which is very much like a "pointer"=2C but isn't necessarily a pointer. It= > can be incremented=2C decremented=2C added to an integer=2C subtracted fro= >m another iterator=2C have an integer subtracted from it=2C dereferenced=2C= > and assigned and compared with other iterators of the same type -- all con= >stant time fast operations.


There are "input i= >terators" which can=2C roughly speaking=2C only be incremented and derefere= >nced. They are all some containers can expose and all some algorithms requi= >re -- for example=2C a singly linked list and linear search.

= >

There are "bidirectional iterators" which can=2C = >roughly speaking=2C only be incremented and decremented and dereferenced. D= >oubly linked lists expose these.


Th= >ere are "output iterators".
They are similar to "input".
v>

input streams (cin=2C like stdin) exposes a= >n input iterator.
You can copy from it.
Copy is another= > simple reusable algorithm.


output = >streams (cout=2C like stdout) exposes an output iterator.
You can= > copy to it.


There are many more ex= >amples.
Of course=2C besides quick sort=2C there is a stable sort= >.
There is finding sequences.
There is binary_search.div>
There is upper_bound/lower_bound/equal_range which are like binary= >_search.
There is unique.
There is partition.
>Many many more=2C "built in" to the library.
That work with mult= >iple "built in" containers=2C and can work with custom containers as well.<= >/div>


I strongly recommend you read up on= > this stuff.
It is really quite illimuninating. Good stuff.
= >
Teaches us how to better factor our code.
And to strive for = >better factoring=2C when we find people have invented/discovered such thing= >s.


"Iterators" already do occur in = >Modula-3 libraries.


All I want is a= > sorted vector that "closely knows" when it is being written vs. read=2C an= >d when there are a series of writes with no intervening reads=2C it can amo= >rtize down the cost of maintaining the ordering.

<= >br>
I hand coded something.
It took me a while to get i= >t to work due to stupid small details.
The result is significantl= >y worse than I would have gotten in C++.
Bigger code. Slower code= >. More copies. More heap allocations.
I can eliminate one of the = >allocations by merging the next step.
But in C++ I naturally woul= >dn't have had it anyway.
Not great.


= >
 =3B- Jay


div>>=3B To: jay.krell at cornell.edu
>=3B CC: mika at async.caltech.edu= >=3B m3devel at elegosoft.com
>=3B Subject: Re: [M3devel] STL algorithms? = >sort/unique?
>=3B Date: Sat=2C 29 Sep 2012 11:29:48 -0700
>=3B Fr= >om: mika at async.caltech.edu
>=3B
>=3B
>=3B Well that depend= >s on how you maintain the vector=2C no?
>=3B
>=3B SortedTable us= >es "treaps" which are supposed to be good data structures.
>=3B Too ne= >w to have made it into Knuth=2C last I checked. The amortized cost
>= >=3B of your operations shouldn't be much worse than with your method=2C wit= >h
>=3B the additional benefit that the sorted order is maintained dyna= >mically.
>=3B
>=3B The separation of algorithms from containers = >sounds a bit like a bug.
>=3B You have to be careful so you don't shoo= >t yourself in the foot there!
>=3B (Sorting a list using an algorithm = >that randomly accesses elements=2C
>=3B say...)
>=3B
>=3B T= >he Modula-3 approach is that you figure out what you want to do=2C pick
= >>=3B the ADT you want that provides the minimal set of operations=2C impo= >rt
>=3B that interface=2C then instantiate a more carefully chosen imp= >lementation
>=3B of the ADT. The language itself obviously can be coa= >xed into supporting the
>=3B algorithm/data structure separation but n= >o one uses it that way as
>=3B far as I know. (Modula-3 generics are = >not that well explored=2C actually.
>=3B I suspect there are many thin= >gs you can do with them that no one has
>=3B tried.)
>=3B
>= >=3B Mika
>=3B
>=3B Jay K writes:
>=3B >=3B--_7877d7e= >8-cb4a-4989-bdcd-d406e5b1f51f_
>=3B >=3BContent-Type: text/plain=3B = >charset=3D"iso-8859-1"
>=3B >=3BContent-Transfer-Encoding: quoted-pr= >intable
>=3B >=3B
>=3B >=3BThe following is very efficient:r>>=3B >=3B
>=3B >=3Brun through a bunch of records=3D2C picking= > out one number from some of thema=3D
>=3B >=3Bppend those numbers t= >o a growing vectorsort the vectorunique the vector
>=3B >=3B
>= >=3B >=3Bsequence allows for random access..but only via a function...or m= >aybe an it=3D
>=3B >=3Berator
>=3B >=3B
>=3B >=3BSTL h= >as this wonderful separation of algorithms from containers=3D2C via iter=3D= >
>=3B >=3Bators.I suspect very few other libraries do.And it could b= >e that most langu=3D
>=3B >=3Bages don't support it.It doesn't appea= >r I can easily sort a sequence=3D2C unl=3D
>=3B >=3Bess I copy the d= >ata out into an array -- gross inefficiency.
>=3B >=3B
>=3B >= >=3BI've hacked something very manual together..and it is taking forever to = >get=3D
>=3B >=3B it to work. It turns out I can reasonably well bou= >nd the size of the data=3D
>=3B >=3B=3D2C so I'm using an open array= >...and I have to keep track of my position in=3D
>=3B >=3Bstead of u= >sing addhi/push_back.Not happy.At some point I might give up and =3D
>= >=3B >=3Bwrite the backend in C++..at which point I might as well write a = >C++ fronte=3D
>=3B >=3Bnd anywa.
>=3B >=3B
>=3B >=3Br>>=3B >=3BI absolutely do not want a sorted table and unique upon inse= >rt.That is much=3D
>=3B >=3B less efficient.What I'm describing uses= > temporarily larger working set but=3D
>=3B >=3B vastly less CPU.An = >array that gets sorted/uniqued occasionally=3D2C like jus=3D
>=3B >= >=3Bt once.And not ongoing maintainence for every single add.
>=3B >= >=3B
>=3B >=3B
>=3B >=3B - Jay
>=3B >=3B
>=3B >= >=3B
>=3B >=3B>=3B To: jay.krell at cornell.edu
>=3B >=3B>=3B= > CC: m3devel at elegosoft.com
>=3B >=3B>=3B Subject: Re: [M3devel] ST= >L algorithms? sort/unique?
>=3B >=3B>=3B Date: Fri=3D2C 28 Sep 201= >2 01:04:48 -0700
>=3B >=3B>=3B From: mika at async.caltech.edu
>= >=3B >=3B>=3B=3D20
>=3B >=3B>=3B=3D20
>=3B >=3B>=3B BT= >W I had the same experience when I first started using Modula-3.
>=3B = >>=3B>=3B It was painful to jump through all its hoops=3D2C coming from = >C=3D2C where yo=3D
>=3B >=3Bu
>=3B >=3B>=3B can do whatever= > you want to whatever bits happen to be sloshing around
>=3B >=3B>= >=3B your machine. C++ from what I have seen mainly lets you do that to
= >>=3B >=3B>=3B more bits in fewer lines of code.
>=3B >=3B>= >=3B=3D20
>=3B >=3B>=3B But after a while I really came to apprecia= >te the value of things like th=3D
>=3B >=3Be
>=3B >=3B>=3B = >language's telling me I'm using the wrong data structure instead of
>= >=3B >=3B>=3B just letting me use the same "nice=3D2C terse=3D2C efficie= >nt" syntax to write
>=3B >=3B>=3B a crappy program :-)
>=3B &= >gt=3B>=3B=3D20
>=3B >=3B>=3B mika writes:
>=3B >=3B>=3B= > >=3BYou're using the wrong (abstract) data structure if you want sort an= >d un=3D
>=3B >=3Bique.
>=3B >=3B>=3B >=3B
>=3B >= >=3B>=3B >=3BA "sequence" is meant to be accessed sequentially...
>= >=3B >=3B>=3B >=3B
>=3B >=3B>=3B >=3BNot knowing precisely = >what you're doing it sounds like you might want a
>=3B >=3B>=3B &g= >t=3BSortedTable... you can get unique on insert and access it in increasing= >
>=3B >=3B>=3B >=3Bor decreasing order.
>=3B >=3B>=3B &= >gt=3B
>=3B >=3B>=3B >=3B Mika
>=3B >=3B>=3B >=3Br>>=3B >=3B>=3B >=3BJay K writes:
>=3B >=3B>=3B >=3B>= >=3B--_d2a02ece-d492-410e-88fb-fb53737d7219_
>=3B >=3B>=3B >=3B&g= >t=3BContent-Type: text/plain=3D3B charset=3D3D"iso-8859-1"
>=3B >=3B= >>=3B >=3B>=3BContent-Transfer-Encoding: quoted-printable
>=3B &g= >t=3B>=3B >=3B>=3B
>=3B >=3B>=3B >=3B>=3B I have an In= >tSeq.T with a bunch of integers. =3D3D20
>=3B >=3B>=3B >=3B>= >=3B What is a good terse efficient idiom for sort and unique? =3D3D20<= >br>>=3B >=3B>=3B >=3B>=3B
>=3B >=3B>=3B >=3B>=3B = >In C++ I would say: vector<=3Bint>=3B a=3D3D3B a.push_bac= >k(..=3D
>=3B >=3B.)=3D3D3B =3D3D
>=3B >=3B>=3B >=3B>=3B= > a.push_back(...)=3D3D3B std::sort(a.begin()=3D3D2C a.end())= >=3D
>=3B >=3B=3D3D3B =3D3D
>=3B >=3B>=3B >=3B>=3B= > a.resize(std::unique(a.begin()=3D3D2C a.end()) - a.begin())=3D3D3B = >=3D
>=3B >=3Bfor (aut=3D3D
>=3B >=3B>=3B >=3B>=3Bo i = >=3D3D3D a.begin()=3D3D3B i !=3D3D3D a.end()=3D3D3B ++i) {
>=3B >= >=3B>=3B >=3B>=3B do stuff with *i }=3D3D20
>=3B >=3B&g= >t=3B >=3B>=3B Nice=3D3D2C terse=3D3D2C efficient. In Modula-3= >? =3D3D20
>=3B >=3B>=3B >=3B>=3B
>=3B >=3B>=3B >= >=3B>=3BI know that unique is one of the easiest algorithms to manually wr= >ite i=3D
>=3B >=3Bnlin=3D3D
>=3B >=3B>=3B >=3B>=3Be=3D3= >D2Cbut I shouldn't have to.
>=3B >=3B>=3B >=3B>=3B
>=3B &= >gt=3B>=3B >=3B>=3B(I'm really trying to stay in Modula-3 here=3D3D2C = >but it is definitely a=3D
>=3B >=3B strug=3D3D
>=3B >=3B>= >=3B >=3B>=3Bgle. :( )
>=3B >=3B>=3B >=3B>=3B
>=3B >= >=3B>=3B >=3B>=3BThank you=3D3D2C - Jay
>=3B >=3B>=3B >=3B&= >gt=3B
>=3B >=3B>=3B >=3B>=3B =3D3D
>=3B >=3B= >>=3B >=3B>=3B
>=3B >=3B>=3B >=3B>=3B--_d2a02ece-d492-410= >e-88fb-fb53737d7219_
>=3B >=3B>=3B >=3B>=3BContent-Type: text/= >html=3D3B charset=3D3D"iso-8859-1"
>=3B >=3B>=3B >=3B>=3BConte= >nt-Transfer-Encoding: quoted-printable
>=3B >=3B>=3B >=3B>=3B<= >br>>=3B >=3B>=3B >=3B>=3B<=3Bhtml>=3B
>=3B >=3B>=3B = >>=3B>=3B<=3Bhead>=3B
>=3B >=3B>=3B >=3B>=3B<=3Bstyle= >>=3B<=3B!--
>=3B >=3B>=3B >=3B>=3B.hmmessage P
>=3B &= >gt=3B>=3B >=3B>=3B{
>=3B >=3B>=3B >=3B>=3Bmargin:0px=3D3= >D3B
>=3B >=3B>=3B >=3B>=3Bpadding:0px
>=3B >=3B>=3B &= >gt=3B>=3B}
>=3B >=3B>=3B >=3B>=3Bbody.hmmessage
>=3B &g= >t=3B>=3B >=3B>=3B{
>=3B >=3B>=3B >=3B>=3Bfont-size: 12pt= >=3D3D3B
>=3B >=3B>=3B >=3B>=3Bfont-family:Calibri
>=3B &g= >t=3B>=3B >=3B>=3B}
>=3B >=3B>=3B >=3B>=3B-->=3B<=3B/= >style>=3B<=3B/head>=3B
>=3B >=3B>=3B >=3B>=3B<=3Bbody = >class=3D3D3D'hmmessage'>=3B<=3Bdiv dir=3D3D3D'ltr'>=3B&=3Bnbsp=3D3= >D3B &=3Bnbsp=3D3D3B&=3Bnb=3D
>=3B >=3Bsp=3D3D3BI have =3D3D>>=3B >=3B>=3B >=3B>=3Ban IntSeq.T with a bunch of integers.&= >=3Bnbsp=3D3D3B &=3Bnbsp=3D3D3B&=3Bnbsp=3D3D3B<=3Bbr=3D
>=3B &g= >t=3B>=3B<=3Bdiv>=3B<=3Bspa=3D3D
>=3B >=3B>=3B >=3B>=3B= >n style=3D3D3D"font-size: 12pt=3D3D3B ">=3B&=3Bnbsp=3D3D3B &=3Bnbsp= >=3D3D3B<=3B/span>=3B<=3Bspan s=3D
>=3B >=3Btyle=3D3D3D"font=3D= >3D
>=3B >=3B>=3B >=3B>=3B-size: 12pt=3D3D3B ">=3B&=3Bnbsp= >=3D3D3B<=3B/span>=3BWhat is a good terse efficient idio=3D
>=3B &g= >t=3Bm for so=3D3D
>=3B >=3B>=3B >=3B>=3Brt and unique?<=3Bsp= >an style=3D3D3D"font-size: 12pt=3D3D3B ">=3B&=3Bnbsp=3D3D3B &=3Bnbs= >p=3D
>=3B >=3B=3D3D3B<=3B/span>=3B<=3B=3D3D
>=3B >=3B&g= >t=3B >=3B>=3Bspan style=3D3D3D"font-size: 12pt=3D3D3B ">=3B&=3Bnbs= >p=3D3D3B<=3B/span>=3B<=3B/div>=3B<=3Bdiv>=3B<=3Bbr>=3B=3Dr>>=3B >=3B<=3B/div>=3B<=3Bdiv=3D3D
>=3B >=3B>=3B >=3B= >>=3B>=3B<=3Bbr>=3B<=3B/div>=3B<=3Bdiv>=3B&=3Bnbsp=3D3D3B= > &=3Bnbsp=3D3D3B In C++ I would say:<=3Bspan style=3D3D=3D
>=3B &= >gt=3B3D"font-si=3D3D
>=3B >=3B>=3B >=3B>=3Bze: 12pt=3D3D3B "&g= >t=3B&=3Bnbsp=3D3D3B &=3Bnbsp=3D3D3B<=3B/span>=3B<=3Bspan style= >=3D3D3D"font-size:=3D
>=3B >=3B 12pt=3D3D3B ">=3B&=3B=3D3D
&= >gt=3B >=3B>=3B >=3B>=3Bnbsp=3D3D3B<=3B/span>=3B<=3B/div>=3B= ><=3Bdiv>=3B<=3Bspan style=3D3D3D"font-size: 12pt=3D3D3B ">=3B&= >=3Bnbs=3D
>=3B >=3Bp=3D3D3B &=3Bnbsp=3D3D
>=3B >=3B>=3B = >>=3B>=3B=3D3D3B<=3B/span>=3B<=3Bspan style=3D3D3D"font-size: 12pt= >=3D3D3B ">=3B&=3Bnbsp=3D3D3B<=3B/span>=3Bve=3D
>=3B >=3Bcto= >r&=3Blt=3D3D3Bin=3D3D
>=3B >=3B>=3B >=3B>=3Bt&=3Bgt=3D3D= >3B a=3D3D3B<=3Bspan style=3D3D3D"font-size: 12pt=3D3D3B ">=3B&=3Bnbs= >p=3D3D3B &=3Bnbs=3D
>=3B >=3Bp=3D3D3B<=3B/span>=3B<=3Bsp=3D= >3D
>=3B >=3B>=3B >=3B>=3Ban style=3D3D3D"font-size: 12pt=3D3D3= >B ">=3B&=3Bnbsp=3D3D3B<=3B/span>=3B<=3B/div>=3B<=3Bdiv>=3B= ><=3Bspan =3D
>=3B >=3Bstyle=3D3D3D"f=3D3D
>=3B >=3B>=3B &= >gt=3B>=3Bont-size: 12pt=3D3D3B ">=3B&=3Bnbsp=3D3D3B &=3Bnbsp=3D3D= >3B<=3B/span>=3B<=3Bspan style=3D3D3D"font=3D
>=3B >=3B-size: 1= >2pt=3D3D
>=3B >=3B>=3B >=3B>=3B=3D3D3B ">=3B&=3Bnbsp=3D3D= >3B<=3B/span>=3Ba.push_back(...)=3D3D3B<=3Bspan style=3D3D3D"font-siz= >=3D
>=3B >=3Be: 12pt=3D3D3B "=3D3D
>=3B >=3B>=3B >=3B>= >=3B>=3B&=3Bnbsp=3D3D3B &=3Bnbsp=3D3D3B<=3B/span>=3B<=3Bspan s= >tyle=3D3D3D"font-size: 12pt=3D3D3B ">=3B&=3Bn=3D
>=3B >=3Bbsp= >=3D3D3B<=3B/span=3D3D
>=3B >=3B>=3B >=3B>=3B>=3B<=3B/div= >>=3B<=3Bdiv>=3B<=3Bdiv>=3B<=3Bspan style=3D3D3D"font-size: 12pt= >=3D3D3B ">=3B&=3Bnbsp=3D3D3B &=3Bnb=3D
>=3B >=3Bsp=3D3D3B<= >=3B/spa=3D3D
>=3B >=3B>=3B >=3B>=3Bn>=3B<=3Bspan style=3D3= >D3D"font-size: 12pt=3D3D3B ">=3B&=3Bnbsp=3D3D3B<=3B/span>=3Ba.push= >_back(=3D
>=3B >=3B...)=3D3D3B<=3Bsp=3D3D
>=3B >=3B>=3B &= >gt=3B>=3Ban style=3D3D3D"font-size: 12pt=3D3D3B ">=3B&=3Bnbsp=3D3D3B= > &=3Bnbsp=3D3D3B<=3B/span>=3B<=3Bspan =3D
>=3B >=3Bstyle=3D= >3D3D"fon=3D3D
>=3B >=3B>=3B >=3B>=3Bt-size: 12pt=3D3D3B ">= >=3B&=3Bnbsp=3D3D3B<=3B/span>=3B<=3B/div>=3B<=3Bdiv>=3B<=3B= >span style=3D3D3D"font-s=3D
>=3B >=3Bize: 12pt=3D3D
>=3B >=3B= >>=3B >=3B>=3B=3D3D3B ">=3B&=3Bnbsp=3D3D3B &=3Bnbsp=3D3D3B<= >=3B/span>=3B<=3Bspan style=3D3D3D"font-size: 12pt=3D3D=3D
>=3B >= >=3B3B ">=3B&=3Bnbsp=3D3D3B<=3B=3D3D
>=3B >=3B>=3B >=3B>= >=3B/span>=3Bstd::sort(a.begin()=3D3D2C a.end())=3D3D3B<=3Bspan style=3D= >3D3D"font-size:=3D
>=3B >=3B 12pt=3D3D3B "=3D3D
>=3B >=3B>= >=3B >=3B>=3B>=3B&=3Bnbsp=3D3D3B &=3Bnbsp=3D3D3B<=3B/span>= >=3B<=3Bspan style=3D3D3D"font-size: 12pt=3D3D3B ">=3B&=3Bn=3D
>= >=3B >=3Bbsp=3D3D3B<=3B/span=3D3D
>=3B >=3B>=3B >=3B>=3B>= >=3B<=3B/div>=3B<=3Bdiv>=3B<=3Bspan style=3D3D3D"font-size: 12pt= >=3D3D3B ">=3B&=3Bnbsp=3D3D3B &=3Bnbsp=3D3D=3D
>=3B >=3B3B<= >=3B/span>=3B<=3Bsp=3D3D
>=3B >=3B>=3B >=3B>=3Ban style=3D3= >D3D"font-size: 12pt=3D3D3B ">=3B&=3Bnbsp=3D3D3B<=3B/span>=3Ba.resi= >ze(std::uni=3D
>=3B >=3Bque(a.begi=3D3D
>=3B >=3B>=3B >= >=3B>=3Bn()=3D3D2C a.end()) - a.begin())=3D3D3B<=3Bspan style=3D3D3D"fon= >t-size: 12pt=3D3D3=3D
>=3B >=3BB ">=3B&=3Bnbsp=3D3D3B=3D3D
&= >gt=3B >=3B>=3B >=3B>=3B &=3Bnbsp=3D3D3B<=3B/span>=3B<=3Bsp= >an style=3D3D3D"font-size: 12pt=3D3D3B ">=3B&=3Bnbsp=3D3D3B<=3B/s=3D= >
>=3B >=3Bpan>=3B<=3B/div>=3B<=3Bd=3D3D
>=3B >=3B>= >=3B >=3B>=3Biv>=3B<=3Bspan style=3D3D3D"font-size: 12pt=3D3D3B ">= >=3B&=3Bnbsp=3D3D3B &=3Bnbsp=3D3D3B for (a=3D
>=3B >=3Buto i = >=3D3D3D a.=3D3D
>=3B >=3B>=3B >=3B>=3Bbegin()=3D3D3B i !=3D3D3= >D a.end()=3D3D3B ++i)<=3B/span>=3B<=3B/div>=3B<=3Bdiv>=3B<=3B= >span style=3D3D=3D
>=3B >=3B3D"font-size=3D3D
>=3B >=3B>=3B= > >=3B>=3B: 12pt=3D3D3B ">=3B&=3Bnbsp=3D3D3B &=3Bnbsp=3D3D3B {&l= >t=3Bbr>=3B&=3Bnbsp=3D3D3B &=3Bnbsp=3D3D3B &=3Bnbsp=3D3D=3D
&g= >t=3B >=3B3B do stuff with=3D3D
>=3B >=3B>=3B >=3B>=3B *i<= >=3B/span>=3B<=3B/div>=3B<=3Bdiv>=3B<=3Bspan style=3D3D3D"font-s= >ize: 12pt=3D3D3B ">=3B&=3Bnbsp=3D3D3B=3D
>=3B >=3B &=3Bnbsp= >=3D3D3B =3D3D
>=3B >=3B>=3B >=3B>=3B}<=3B/span>=3B<=3B/d= >iv>=3B<=3Bdiv>=3B&=3Bnbsp=3D3D3B<=3B/div>=3B<=3Bdiv>=3B<= >=3Bbr>=3B<=3B/div>=3B<=3Bdiv>=3B<=3Bspan style=3D3D3D=3D
>= >=3B >=3B"font-si=3D3D
>=3B >=3B>=3B >=3B>=3Bze: 12pt=3D3D3B = >">=3B&=3Bnbsp=3D3D3B &=3Bnbsp=3D3D3B<=3B/span>=3B<=3Bspan sty= >le=3D3D3D"font-size:=3D
>=3B >=3B 12pt=3D3D3B ">=3B&=3B=3D3D>>=3B >=3B>=3B >=3B>=3Bnbsp=3D3D3B<=3B/span>=3BNice=3D3D2C te= >rse=3D3D2C efficient.<=3Bspan style=3D3D3D"font-si=3D
>=3B >=3Bze:= > 12pt=3D3D3B =3D3D
>=3B >=3B>=3B >=3B>=3B">=3B&=3Bnbsp=3D= >3D3B &=3Bnbsp=3D3D3B<=3B/span>=3B<=3Bspan style=3D3D3D"font-size: = >12pt=3D3D3B ">=3B&=3B=3D
>=3B >=3Bnbsp=3D3D3B<=3B/spa=3D3D>>=3B >=3B>=3B >=3B>=3Bn>=3B<=3B/div>=3B<=3Bdiv>=3B<= >=3Bspan style=3D3D3D"font-size: 12pt=3D3D3B ">=3B&=3Bnbsp=3D3D3B &= >=3Bnbsp=3D
>=3B >=3B=3D3D3B<=3B/span>=3B<=3Bs=3D3D
>=3B &= >gt=3B>=3B >=3B>=3Bpan style=3D3D3D"font-size: 12pt=3D3D3B ">=3B&= >=3Bnbsp=3D3D3B<=3B/span>=3BIn Modula-3?<=3Bspa=3D
>=3B >=3Bn s= >tyle=3D3D3D=3D3D
>=3B >=3B>=3B >=3B>=3B"font-size: 12pt=3D3D3B= > ">=3B&=3Bnbsp=3D3D3B &=3Bnbsp=3D3D3B<=3B/span>=3B<=3Bspan st= >yle=3D3D3D"fo=3D
>=3B >=3Bnt-size: 12p=3D3D
>=3B >=3B>=3B &= >gt=3B>=3Bt=3D3D3B ">=3B&=3Bnbsp=3D3D3B<=3B/span>=3B<=3B/div>= >=3B<=3Bdiv>=3B<=3Bbr>=3B<=3B/div>=3B<=3Bdiv>=3B<=3Bbr>= >=3B<=3B/div>=3B<=3Bdiv>=3BI kn=3D
>=3B >=3Bow that =3D3D
= >>=3B >=3B>=3B >=3B>=3Bunique is one of the easiest algorithms to = >manually write inline=3D3D2C<=3B/=3D
>=3B >=3Bdiv>=3B<=3Bd=3D3= >D
>=3B >=3B>=3B >=3B>=3Biv>=3Bbut I shouldn't have to.<=3B= >/div>=3B<=3Bdiv>=3B<=3Bbr>=3B<=3B/div>=3B<=3Bdiv>=3B<= >=3Bbr>=3B<=3B/div>=3B<=3Bdiv>=3B(I'=3D
>=3B >=3Bm re=3D3D<= >br>>=3B >=3B>=3B >=3B>=3Bally trying to stay in Modula-3 here=3D3= >D2C but it is definitely a strugg=3D
>=3B >=3Ble. :(=3D3D
>=3B = >>=3B>=3B >=3B>=3B )<=3B/div>=3B<=3Bdiv>=3B<=3Bbr>=3B<= >=3B/div>=3B<=3Bdiv>=3B<=3Bbr>=3B<=3B/div>=3B<=3Bdiv>=3BTh= >ank you=3D3D2C<=3B/div>=3B<=3Bdiv>=3B&=3Bnb=3D
>=3B >=3Bs= >p=3D3D3B-=3D3D
>=3B >=3B>=3B >=3B>=3B Jay<=3B/div>=3B<= >=3Bbr>=3B<=3Bbr>=3B<=3B/div>=3B <=3B/div>=3B<=3B= >/body>=3B
>=3B >=3B>=3B >=3B>=3B<=3B/html>=3B=3D3D
&g= >t=3B >=3B>=3B >=3B>=3B
>=3B >=3B>=3B >=3B>=3B--_d2a02e= >ce-d492-410e-88fb-fb53737d7219_--
>=3B >=3B =3D
>=3B= > >=3B
>=3B >=3B--_7877d7e8-cb4a-4989-bdcd-d406e5b1f51f_
>=3B = >>=3BContent-Type: text/html=3B charset=3D"iso-8859-1"
>=3B >=3BCon= >tent-Transfer-Encoding: quoted-printable
>=3B >=3B
>=3B >=3B&= >lt=3Bhtml>=3B
>=3B >=3B<=3Bhead>=3B
>=3B >=3B<=3Bstyl= >e>=3B<=3B!--
>=3B >=3B.hmmessage P
>=3B >=3B{
>=3B &= >gt=3Bmargin:0px=3D3B
>=3B >=3Bpadding:0px
>=3B >=3B}
>= >=3B >=3Bbody.hmmessage
>=3B >=3B{
>=3B >=3Bfont-size: 12pt= >=3D3B
>=3B >=3Bfont-family:Calibri
>=3B >=3B}
>=3B >= >=3B-->=3B<=3B/style>=3B<=3B/head>=3B
>=3B >=3B<=3Bbody c= >lass=3D3D'hmmessage'>=3B<=3Bdiv dir=3D3D'ltr'>=3B<=3Bdiv>=3B<= >=3Bspan style=3D3D"font-size: 1=3D
>=3B >=3B2pt=3D3B ">=3BThe foll= >owing is very efficient:<=3B/span>=3B<=3B/div>=3B<=3Bdiv>=3B<= >=3Bbr>=3B<=3B/div>=3B<=3Bdiv>=3B<=3B=3D
>=3B >=3Bbr>= >=3B<=3B/div>=3B<=3Bdiv>=3Brun through a bunch of records=3D2C picki= >ng out one number from=3D
>=3B >=3B some of them<=3B/div>=3B<= >=3Bdiv>=3Bappend those numbers to a growing vector<=3B/div>=3B<=3Bd= >iv>=3B=3D
>=3B >=3Bsort the vector<=3B/div>=3B<=3Bdiv>=3Bu= >nique the vector<=3B/div>=3B<=3Bdiv>=3B<=3Bbr>=3B<=3B/div>= >=3B<=3Bdiv>=3B<=3Bbr>=3B<=3B/=3D
>=3B >=3Bdiv>=3B<=3Bd= >iv>=3Bsequence allows for random access..but only via a function...<=3B= >/div=3D
>=3B >=3B>=3B<=3Bdiv>=3Bor maybe an iterator<=3B/div= >>=3B<=3Bdiv>=3B<=3Bbr>=3B<=3B/div>=3B<=3Bdiv>=3B<=3Bbr&= >gt=3B<=3B/div>=3B<=3Bdiv>=3BSTL has =3D
>=3B >=3Bthis wonder= >ful separation of algorithms from containers=3D2C via iterators.<=3B/=3D<= >br>>=3B >=3Bdiv>=3B<=3Bdiv>=3BI suspect very few other libraries = >do.<=3B/div>=3B<=3Bdiv>=3BAnd it could be t=3D
>=3B >=3Bhat = >most languages don't support it.<=3B/div>=3B<=3Bdiv>=3BIt doesn't a= >ppear I can easi=3D
>=3B >=3Bly sort a sequence=3D2C unless I copy t= >he data out into an array -- gross ine=3D
>=3B >=3Bfficiency.<=3B/= >div>=3B<=3Bdiv>=3B<=3Bbr>=3B<=3B/div>=3B<=3Bdiv>=3B<=3B= >br>=3B<=3B/div>=3B<=3Bdiv>=3BI've hacked something ve=3D
>= >=3B >=3Bry manual together..and it is taking forever to get it to work.&l= >t=3B/div>=3B<=3Bdiv>=3B&=3B=3D
>=3B >=3Bnbsp=3D3B It turns = >out I can reasonably well bound the size of the data=3D2C so=3D
>=3B &= >gt=3B I'm using an open array...and I have to keep track of my position ins= >tead =3D
>=3B >=3Bof using addhi/push_back.<=3B/div>=3B<=3Bdiv= >>=3BNot happy.<=3B/div>=3B<=3Bdiv>=3BAt some point I mi=3D
>= >=3B >=3Bght give up and write the backend in C++..at which point I might = >as well wr=3D
>=3B >=3Bite a C++ frontend anywa.<=3B/div>=3B<= >=3Bdiv>=3B<=3Bbr>=3B<=3B/div>=3B<=3Bdiv>=3B<=3Bbr>=3B<= >=3B/div>=3B<=3Bdiv>=3B<=3Bbr>=3B<=3B/div=3D
>=3B >=3B>= >=3B<=3Bdiv>=3BI absolutely do not want a sorted table and unique upon i= >nsert.<=3B/div>=3B=3D
>=3B >=3B<=3Bdiv>=3BThat is much less = >efficient.<=3B/div>=3B<=3Bdiv>=3BWhat I'm describing uses tempor=3D= >
>=3B >=3Barily larger working set but vastly less CPU.<=3B/div>= >=3B<=3Bdiv>=3BAn array that gets =3D
>=3B >=3Bsorted/uniqued occ= >asionally=3D2C like just once.<=3B/div>=3B<=3Bdiv>=3BAnd not ongoin= >g ma=3D
>=3B >=3Bintainence for every single add.<=3B/div>=3B<= >=3Bdiv>=3B<=3Bbr>=3B<=3B/div>=3B<=3Bdiv>=3B<=3Bbr>=3B<= >=3B/div>=3B<=3Bdiv>=3B<=3Bb=3D
>=3B >=3Br>=3B<=3B/div>= >=3B<=3Bdiv>=3B&=3Bnbsp=3D3B- Jay<=3B/div>=3B<=3Bdiv>=3B<= >=3Bbr>=3B<=3Bbr>=3B<=3Bbr>=3B<=3Bdiv>=3B<=3Bdiv id=3D3D"Sky= >DrivePl=3D
>=3B >=3Baceholder">=3B<=3B/div>=3B&=3Bgt=3D3B T= >o: jay.krell at cornell.edu<=3Bbr>=3B&=3Bgt=3D3B CC: m3devel at ele=3D
= >>=3B >=3Bgosoft.com<=3Bbr>=3B&=3Bgt=3D3B Subject: Re: [M3devel] = >STL algorithms? sort/unique?<=3Bbr=3D
>=3B >=3B>=3B&=3Bgt=3D3= >B Date: Fri=3D2C 28 Sep 2012 01:04:48 -0700<=3Bbr>=3B&=3Bgt=3D3B Fro= >m: mika at async.=3D
>=3B >=3Bcaltech.edu<=3Bbr>=3B&=3Bgt=3D3B &= >lt=3Bbr>=3B&=3Bgt=3D3B <=3Bbr>=3B&=3Bgt=3D3B BTW I had the same= > experience w=3D
>=3B >=3Bhen I first started using Modula-3.<=3Bb= >r>=3B&=3Bgt=3D3B It was painful to jump throug=3D
>=3B >=3Bh al= >l its hoops=3D2C coming from C=3D2C where you<=3Bbr>=3B&=3Bgt=3D3B c= >an do whatever you=3D
>=3B >=3B want to whatever bits happen to be s= >loshing around<=3Bbr>=3B&=3Bgt=3D3B your machine.=3D
>=3B >= >=3B C++ from what I have seen mainly lets you do that to<=3Bbr>=3B&= >=3Bgt=3D3B more bits =3D
>=3B >=3Bin fewer lines of code.<=3Bbr>= >=3B&=3Bgt=3D3B <=3Bbr>=3B&=3Bgt=3D3B But after a while I really c= >am=3D
>=3B >=3Be to appreciate the value of things like the<=3Bbr&= >gt=3B&=3Bgt=3D3B language's telling m=3D
>=3B >=3Be I'm using the= > wrong data structure instead of<=3Bbr>=3B&=3Bgt=3D3B just letting m= >e u=3D
>=3B >=3Bse the same "nice=3D2C terse=3D2C efficient" syntax = >to write<=3Bbr>=3B&=3Bgt=3D3B a crappy=3D
>=3B >=3B program := >-)<=3Bbr>=3B&=3Bgt=3D3B <=3Bbr>=3B&=3Bgt=3D3B mika writes:<= >=3Bbr>=3B&=3Bgt=3D3B &=3Bgt=3D3BYou're using=3D
>=3B >=3B th= >e wrong (abstract) data structure if you want sort and unique.<=3Bbr>= >=3B&=3Bgt=3D3B=3D
>=3B >=3B &=3Bgt=3D3B<=3Bbr>=3B&=3Bgt= >=3D3B &=3Bgt=3D3BA "sequence" is meant to be accessed sequentially..=3D<= >br>>=3B >=3B.<=3Bbr>=3B&=3Bgt=3D3B &=3Bgt=3D3B<=3Bbr>=3B&= >amp=3Bgt=3D3B &=3Bgt=3D3BNot knowing precisely what you're doing =3D
= >>=3B >=3Bit sounds like you might want a<=3Bbr>=3B&=3Bgt=3D3B &a= >mp=3Bgt=3D3BSortedTable... you can get =3D
>=3B >=3Bunique on insert= > and access it in increasing<=3Bbr>=3B&=3Bgt=3D3B &=3Bgt=3D3Bor d= >ecreasing =3D
>=3B >=3Border.<=3Bbr>=3B&=3Bgt=3D3B &=3Bgt= >=3D3B<=3Bbr>=3B&=3Bgt=3D3B &=3Bgt=3D3B Mika<=3Bbr>=3B&= >=3Bgt=3D3B &=3Bgt=3D3B<=3Bbr>=3B&=3Bgt=3D3B=3D
>=3B >=3B &= >amp=3Bgt=3D3BJay K writes:<=3Bbr>=3B&=3Bgt=3D3B &=3Bgt=3D3B&= >=3Bgt=3D3B--_d2a02ece-d492-410e-88fb-fb537=3D
>=3B >=3B37d7219_<= >=3Bbr>=3B&=3Bgt=3D3B &=3Bgt=3D3B&=3Bgt=3D3BContent-Type: text/pl= >ain=3D3B charset=3D3D"iso-8=3D
>=3B >=3B859-1"<=3Bbr>=3B&=3Bg= >t=3D3B &=3Bgt=3D3B&=3Bgt=3D3BContent-Transfer-Encoding: quoted-printa= >ble<=3Bbr=3D
>=3B >=3B>=3B&=3Bgt=3D3B &=3Bgt=3D3B&=3Bgt= >=3D3B<=3Bbr>=3B&=3Bgt=3D3B &=3Bgt=3D3B&=3Bgt=3D3B I have an= > IntSeq.T with a bu=3D
>=3B >=3Bnch of integers. =3D3D20<=3Bbr&g= >t=3B&=3Bgt=3D3B &=3Bgt=3D3B&=3Bgt=3D3B What is a good terse eff= >=3D
>=3B >=3Bicient idiom for sort and unique? =3D3D20<=3Bbr>= >=3B&=3Bgt=3D3B &=3Bgt=3D3B&=3Bgt=3D3B<=3Bbr>=3B&=3Bgt=3D3B = >=3D
>=3B >=3B&=3Bgt=3D3B&=3Bgt=3D3B In C++ I would say: = > vector&=3Blt=3D3Bint&=3Bgt=3D3B a=3D3D3B =3D
>=3B >=3B = > a.push_back(...)=3D3D3B =3D3D<=3Bbr>=3B&=3Bgt=3D3B &=3Bgt=3D3B= >&=3Bgt=3D3B a.push_back(...)=3D
>=3B >=3B=3D3D3B std= >::sort(a.begin()=3D3D2C a.end())=3D3D3B =3D3D<=3Bbr>=3B&=3Bgt= >=3D3B &=3Bgt=3D
>=3B >=3B=3D3B&=3Bgt=3D3B a.resize(std::unique= >(a.begin()=3D3D2C a.end()) - a.begin())=3D3D3B =3D
>=3B >=3B f= >or (aut=3D3D<=3Bbr>=3B&=3Bgt=3D3B &=3Bgt=3D3B&=3Bgt=3D3Bo i = >=3D3D3D a.begin()=3D3D3B i !=3D3D3D a.=3D
>=3B >=3Bend()=3D3D3B ++i)= > {<=3Bbr>=3B&=3Bgt=3D3B &=3Bgt=3D3B&=3Bgt=3D3B do stuf= >f with *i }=3D3D20=3D
>=3B >=3B<=3Bbr>=3B&=3Bgt=3D3B &= >=3Bgt=3D3B&=3Bgt=3D3B Nice=3D3D2C terse=3D3D2C efficient. In M= >odula=3D
>=3B >=3B-3? =3D3D20<=3Bbr>=3B&=3Bgt=3D3B &=3Bg= >t=3D3B&=3Bgt=3D3B<=3Bbr>=3B&=3Bgt=3D3B &=3Bgt=3D3B&=3Bgt=3D= >3BI know that unique=3D
>=3B >=3B is one of the easiest algorithms t= >o manually write inlin=3D3D<=3Bbr>=3B&=3Bgt=3D3B &=3Bgt=3D
>= >=3B >=3B=3D3B&=3Bgt=3D3Be=3D3D2Cbut I shouldn't have to.<=3Bbr>=3B= >&=3Bgt=3D3B &=3Bgt=3D3B&=3Bgt=3D3B<=3Bbr>=3B&=3Bgt=3D3B &am= >p=3Bg=3D
>=3B >=3Bt=3D3B&=3Bgt=3D3B(I'm really trying to stay in = >Modula-3 here=3D3D2C but it is defini=3D
>=3B >=3Btely a strug=3D3D&= >lt=3Bbr>=3B&=3Bgt=3D3B &=3Bgt=3D3B&=3Bgt=3D3Bgle. :( )<=3Bbr&g= >t=3B&=3Bgt=3D3B &=3Bgt=3D3B&=3Bgt=3D3B<=3Bbr>=3B&=3B=3D
= >>=3B >=3Bgt=3D3B &=3Bgt=3D3B&=3Bgt=3D3BThank you=3D3D2C - Jay<= >=3Bbr>=3B&=3Bgt=3D3B &=3Bgt=3D3B&=3Bgt=3D3B<=3Bbr>=3B&=3B= >gt=3D3B &=3Bgt=3D
>=3B >=3B=3D3B&=3Bgt=3D3B =3D3D&l= >t=3Bbr>=3B&=3Bgt=3D3B &=3Bgt=3D3B&=3Bgt=3D3B<=3Bbr>=3B&= >=3Bgt=3D3B &=3Bgt=3D3B&=3Bgt=3D3B--_d2=3D
>=3B >=3Ba02ece-d492= >-410e-88fb-fb53737d7219_<=3Bbr>=3B&=3Bgt=3D3B &=3Bgt=3D3B&=3Bg= >t=3D3BContent-Type: tex=3D
>=3B >=3Bt/html=3D3B charset=3D3D"iso-885= >9-1"<=3Bbr>=3B&=3Bgt=3D3B &=3Bgt=3D3B&=3Bgt=3D3BContent-Transf= >er-Enc=3D
>=3B >=3Boding: quoted-printable<=3Bbr>=3B&=3Bgt=3D= >3B &=3Bgt=3D3B&=3Bgt=3D3B<=3Bbr>=3B&=3Bgt=3D3B &=3Bgt=3D3B&= >amp=3Bgt=3D3B&=3Blt=3D3B=3D
>=3B >=3Bhtml&=3Bgt=3D3B<=3Bbr&g= >t=3B&=3Bgt=3D3B &=3Bgt=3D3B&=3Bgt=3D3B&=3Blt=3D3Bhead&=3Bgt= >=3D3B<=3Bbr>=3B&=3Bgt=3D3B &=3Bgt=3D3B&=3Bgt=3D3B&=3Blt=3D<= >br>>=3B >=3B=3D3Bstyle&=3Bgt=3D3B&=3Blt=3D3B!--<=3Bbr>=3B&= >=3Bgt=3D3B &=3Bgt=3D3B&=3Bgt=3D3B.hmmessage P<=3Bbr>=3B&=3Bgt= >=3D3B &=3Bgt=3D3B=3D
>=3B >=3B&=3Bgt=3D3B{<=3Bbr>=3B&= >=3Bgt=3D3B &=3Bgt=3D3B&=3Bgt=3D3Bmargin:0px=3D3D3B<=3Bbr>=3B&= >=3Bgt=3D3B &=3Bgt=3D3B&=3Bgt=3D3Bpadding=3D
>=3B >=3B:0px<= >=3Bbr>=3B&=3Bgt=3D3B &=3Bgt=3D3B&=3Bgt=3D3B}<=3Bbr>=3B&= >=3Bgt=3D3B &=3Bgt=3D3B&=3Bgt=3D3Bbody.hmmessage<=3Bbr>=3B&=3Bg= >t=3D3B=3D
>=3B >=3B &=3Bgt=3D3B&=3Bgt=3D3B{<=3Bbr>=3B&= >=3Bgt=3D3B &=3Bgt=3D3B&=3Bgt=3D3Bfont-size: 12pt=3D3D3B<=3Bbr>=3B= >&=3Bgt=3D3B &=3Bgt=3D3B&=3B=3D
>=3B >=3Bgt=3D3Bfont-family:= >Calibri<=3Bbr>=3B&=3Bgt=3D3B &=3Bgt=3D3B&=3Bgt=3D3B}<=3Bbr&g= >t=3B&=3Bgt=3D3B &=3Bgt=3D3B&=3Bgt=3D3B--&=3Bg=3D
>=3B >= >=3Bt=3D3B&=3Blt=3D3B/style&=3Bgt=3D3B&=3Blt=3D3B/head&=3Bgt=3D3= >B<=3Bbr>=3B&=3Bgt=3D3B &=3Bgt=3D3B&=3Bgt=3D3B&=3Blt=3D3Bbod= >y cl=3D
>=3B >=3Bass=3D3D3D'hmmessage'&=3Bgt=3D3B&=3Blt=3D3Bdi= >v dir=3D3D3D'ltr'&=3Bgt=3D3B&=3Bamp=3D3Bnbsp=3D3D3B &=3Bamp=3D
= >>=3B >=3B=3D3Bnbsp=3D3D3B&=3Bamp=3D3Bnbsp=3D3D3BI have =3D3D<=3Bbr= >>=3B&=3Bgt=3D3B &=3Bgt=3D3B&=3Bgt=3D3Ban IntSeq.T wi=3D
>= >=3B >=3Bth a bunch of integers.&=3Bamp=3D3Bnbsp=3D3D3B &=3Bamp=3D3B= >nbsp=3D3D3B&=3Bamp=3D3Bnbsp=3D3D3B&=3Blt=3D
>=3B >=3B=3D3Bbr&a= >mp=3Bgt=3D3B&=3Blt=3D3Bdiv&=3Bgt=3D3B&=3Blt=3D3Bspa=3D3D<=3Bbr&g= >t=3B&=3Bgt=3D3B &=3Bgt=3D3B&=3Bgt=3D3Bn style=3D3D3D"f=3D
>= >=3B >=3Bont-size: 12pt=3D3D3B "&=3Bgt=3D3B&=3Bamp=3D3Bnbsp=3D3D3B &= >amp=3Bamp=3D3Bnbsp=3D3D3B&=3Blt=3D3B/span&=3Bgt=3D
>=3B >=3B= >=3D3B&=3Blt=3D3Bspan style=3D3D3D"font=3D3D<=3Bbr>=3B&=3Bgt=3D3B = >&=3Bgt=3D3B&=3Bgt=3D3B-size: 12pt=3D3D3B "&=3Bg=3D
>=3B >= >=3Bt=3D3B&=3Bamp=3D3Bnbsp=3D3D3B&=3Blt=3D3B/span&=3Bgt=3D3BWhat is= > a good terse efficient idiom f=3D
>=3B >=3Bor so=3D3D<=3Bbr>=3B= >&=3Bgt=3D3B &=3Bgt=3D3B&=3Bgt=3D3Brt and unique?&=3Blt=3D3Bspan= > style=3D3D3D"font-siz=3D
>=3B >=3Be: 12pt=3D3D3B "&=3Bgt=3D3B&am= >p=3Bamp=3D3Bnbsp=3D3D3B &=3Bamp=3D3Bnbsp=3D3D3B&=3Blt=3D3B/span&= >=3Bgt=3D3B&=3Blt=3D
>=3B >=3B=3D3B=3D3D<=3Bbr>=3B&=3Bgt=3D= >3B &=3Bgt=3D3B&=3Bgt=3D3Bspan style=3D3D3D"font-size: 12pt=3D3D3B "&a= >mp=3Bgt=3D3B&=3Ba=3D
>=3B >=3Bmp=3D3Bnbsp=3D3D3B&=3Blt=3D3B/sp= >an&=3Bgt=3D3B&=3Blt=3D3B/div&=3Bgt=3D3B&=3Blt=3D3Bdiv&=3Bgt= >=3D3B&=3Blt=3D3Bbr&=3Bgt=3D
>=3B >=3B=3D3B&=3Blt=3D3B/div&a= >mp=3Bgt=3D3B&=3Blt=3D3Bdiv=3D3D<=3Bbr>=3B&=3Bgt=3D3B &=3Bgt=3D= >3B&=3Bgt=3D3B&=3Bgt=3D3B&=3Blt=3D3Bbr&=3Bgt=3D3B&=3B=3D
&= >gt=3B >=3Blt=3D3B/div&=3Bgt=3D3B&=3Blt=3D3Bdiv&=3Bgt=3D3B&=3B= >amp=3D3Bnbsp=3D3D3B &=3Bamp=3D3Bnbsp=3D3D3B In C++ I wo=3D
>=3B >= >=3Buld say:&=3Blt=3D3Bspan style=3D3D3D"font-si=3D3D<=3Bbr>=3B&= >=3Bgt=3D3B &=3Bgt=3D3B&=3Bgt=3D3Bze: 12pt=3D3D3=3D
>=3B >=3BB = >"&=3Bgt=3D3B&=3Bamp=3D3Bnbsp=3D3D3B &=3Bamp=3D3Bnbsp=3D3D3B&=3B= >lt=3D3B/span&=3Bgt=3D3B&=3Blt=3D3Bspan style=3D
>=3B >=3B=3D3D= >3D"font-size: 12pt=3D3D3B "&=3Bgt=3D3B&=3Bamp=3D3B=3D3D<=3Bbr>=3B= >&=3Bgt=3D3B &=3Bgt=3D3B&=3Bgt=3D3Bnbsp=3D3D3=3D
>=3B >=3BB&= >amp=3Blt=3D3B/span&=3Bgt=3D3B&=3Blt=3D3B/div&=3Bgt=3D3B&=3Blt= >=3D3Bdiv&=3Bgt=3D3B&=3Blt=3D3Bspan style=3D3D3D"font=3D
>=3B >= >=3B-size: 12pt=3D3D3B "&=3Bgt=3D3B&=3Bamp=3D3Bnbsp=3D3D3B &=3Bamp= >=3D3Bnbsp=3D3D<=3Bbr>=3B&=3Bgt=3D3B &=3Bgt=3D3B&=3Bgt=3D
&g= >t=3B >=3B=3D3B=3D3D3B&=3Blt=3D3B/span&=3Bgt=3D3B&=3Blt=3D3Bspan = >style=3D3D3D"font-size: 12pt=3D3D3B "&=3Bgt=3D3B=3D
>=3B >=3B&= >=3Bamp=3D3Bnbsp=3D3D3B&=3Blt=3D3B/span&=3Bgt=3D3Bvector&=3Bamp=3D3= >Blt=3D3D3Bin=3D3D<=3Bbr>=3B&=3Bgt=3D3B &=3Bgt=3D3B=3D
>=3B &= >gt=3B&=3Bgt=3D3Bt&=3Bamp=3D3Bgt=3D3D3B a=3D3D3B&=3Blt=3D3Bspan sty= >le=3D3D3D"font-size: 12pt=3D3D3B "&=3Bgt=3D
>=3B >=3B=3D3B&=3B= >amp=3D3Bnbsp=3D3D3B &=3Bamp=3D3Bnbsp=3D3D3B&=3Blt=3D3B/span&=3Bgt= >=3D3B&=3Blt=3D3Bsp=3D3D<=3Bbr>=3B&=3Bgt=3D3B =3D
>=3B >=3B= >&=3Bgt=3D3B&=3Bgt=3D3Ban style=3D3D3D"font-size: 12pt=3D3D3B "&=3B= >gt=3D3B&=3Bamp=3D3Bnbsp=3D3D3B&=3Blt=3D
>=3B >=3B=3D3B/span&am= >p=3Bgt=3D3B&=3Blt=3D3B/div&=3Bgt=3D3B&=3Blt=3D3Bdiv&=3Bgt=3D3B&= >amp=3Blt=3D3Bspan style=3D3D3D"f=3D3D<=3Bbr>=3B=3D
>=3B >=3B&= >=3Bgt=3D3B &=3Bgt=3D3B&=3Bgt=3D3Bont-size: 12pt=3D3D3B "&=3Bgt=3D3= >B&=3Bamp=3D3Bnbsp=3D3D3B &=3Bamp=3D3Bnbsp=3D
>=3B >=3B=3D3D3B&= >amp=3Blt=3D3B/span&=3Bgt=3D3B&=3Blt=3D3Bspan style=3D3D3D"font-size: = >12pt=3D3D<=3Bbr>=3B&=3Bgt=3D3B &=3Bg=3D
>=3B >=3Bt=3D3B&am= >p=3Bgt=3D3B=3D3D3B "&=3Bgt=3D3B&=3Bamp=3D3Bnbsp=3D3D3B&=3Blt=3D3B/= >span&=3Bgt=3D3Ba.push_back(...)=3D3D=3D
>=3B >=3B3B&=3Blt=3D3B= >span style=3D3D3D"font-size: 12pt=3D3D3B "=3D3D<=3Bbr>=3B&=3Bgt=3D3B= > &=3Bgt=3D3B&=3Bgt=3D3B&=3Bgt=3D
>=3B >=3B=3D3B&=3Bamp= >=3D3Bnbsp=3D3D3B &=3Bamp=3D3Bnbsp=3D3D3B&=3Blt=3D3B/span&=3Bgt=3D3= >B&=3Blt=3D3Bspan style=3D3D3D"=3D
>=3B >=3Bfont-size: 12pt=3D3D3B= > "&=3Bgt=3D3B&=3Bamp=3D3Bnbsp=3D3D3B&=3Blt=3D3B/span=3D3D<=3Bbr&= >gt=3B&=3Bgt=3D3B &=3Bgt=3D3B=3D
>=3B >=3B&=3Bgt=3D3B&=3B= >gt=3D3B&=3Blt=3D3B/div&=3Bgt=3D3B&=3Blt=3D3Bdiv&=3Bgt=3D3B&= >=3Blt=3D3Bdiv&=3Bgt=3D3B&=3Blt=3D3Bspan style=3D
>=3B >=3B=3D3= >D3D"font-size: 12pt=3D3D3B "&=3Bgt=3D3B&=3Bamp=3D3Bnbsp=3D3D3B &= >=3Bamp=3D3Bnbsp=3D3D3B&=3Blt=3D3B/s=3D
>=3B >=3Bpa=3D3D<=3Bbr&g= >t=3B&=3Bgt=3D3B &=3Bgt=3D3B&=3Bgt=3D3Bn&=3Bgt=3D3B&=3Blt=3D3= >Bspan style=3D3D3D"font-size: 12pt=3D3D=3D
>=3B >=3B3B "&=3Bgt=3D= >3B&=3Bamp=3D3Bnbsp=3D3D3B&=3Blt=3D3B/span&=3Bgt=3D3Ba.push_back(..= >.)=3D3D3B&=3Blt=3D3Bsp=3D3D=3D
>=3B >=3B<=3Bbr>=3B&=3Bgt= >=3D3B &=3Bgt=3D3B&=3Bgt=3D3Ban style=3D3D3D"font-size: 12pt=3D3D3B "&= >amp=3Bgt=3D3B&=3Bamp=3D3Bnbs=3D
>=3B >=3Bp=3D3D3B &=3Bamp=3D3B= >nbsp=3D3D3B&=3Blt=3D3B/span&=3Bgt=3D3B&=3Blt=3D3Bspan style=3D3D3D= >"fon=3D3D<=3Bbr>=3B&=3Bgt=3D
>=3B >=3B=3D3B &=3Bgt=3D3B&am= >p=3Bgt=3D3Bt-size: 12pt=3D3D3B "&=3Bgt=3D3B&=3Bamp=3D3Bnbsp=3D3D3B&am= >p=3Blt=3D3B/span&=3Bgt=3D3B&=3B=3D
>=3B >=3Blt=3D3B/div&=3B= >gt=3D3B&=3Blt=3D3Bdiv&=3Bgt=3D3B&=3Blt=3D3Bspan style=3D3D3D"font-= >size: 12pt=3D3D<=3Bbr>=3B&=3B=3D
>=3B >=3Bgt=3D3B &=3Bgt= >=3D3B&=3Bgt=3D3B=3D3D3B "&=3Bgt=3D3B&=3Bamp=3D3Bnbsp=3D3D3B &= >=3Bamp=3D3Bnbsp=3D3D3B&=3Blt=3D3B/span=3D
>=3B >=3B&=3Bgt=3D3B= >&=3Blt=3D3Bspan style=3D3D3D"font-size: 12pt=3D3D3B "&=3Bgt=3D3B&= >=3Bamp=3D3Bnbsp=3D3D3B&=3Blt=3D
>=3B >=3B=3D3B=3D3D<=3Bbr>=3B= >&=3Bgt=3D3B &=3Bgt=3D3B&=3Bgt=3D3B/span&=3Bgt=3D3Bstd::sort(a.b= >egin()=3D3D2C a.end())=3D
>=3B >=3B=3D3D3B&=3Blt=3D3Bspan style= >=3D3D3D"font-size: 12pt=3D3D3B "=3D3D<=3Bbr>=3B&=3Bgt=3D3B &=3Bgt= >=3D3B&=3Bgt=3D3B=3D
>=3B >=3B&=3Bgt=3D3B&=3Bamp=3D3Bnbsp=3D= >3D3B &=3Bamp=3D3Bnbsp=3D3D3B&=3Blt=3D3B/span&=3Bgt=3D3B&=3Blt= >=3D3Bspan style=3D3D=3D
>=3B >=3B3D"font-size: 12pt=3D3D3B "&=3Bg= >t=3D3B&=3Bamp=3D3Bnbsp=3D3D3B&=3Blt=3D3B/span=3D3D<=3Bbr>=3B&= >=3Bgt=3D3B &=3Bgt=3D
>=3B >=3B=3D3B&=3Bgt=3D3B&=3Bgt=3D3B&a= >mp=3Blt=3D3B/div&=3Bgt=3D3B&=3Blt=3D3Bdiv&=3Bgt=3D3B&=3Blt=3D3B= >span style=3D3D3D"font-si=3D
>=3B >=3Bze: 12pt=3D3D3B "&=3Bgt=3D3= >B&=3Bamp=3D3Bnbsp=3D3D3B &=3Bamp=3D3Bnbsp=3D3D3B&=3Blt=3D3B/span&a= >mp=3Bgt=3D3B&=3Blt=3D
>=3B >=3B=3D3Bsp=3D3D<=3Bbr>=3B&=3Bg= >t=3D3B &=3Bgt=3D3B&=3Bgt=3D3Ban style=3D3D3D"font-size: 12pt=3D3D3B "= >&=3Bgt=3D3B&=3Ba=3D
>=3B >=3Bmp=3D3Bnbsp=3D3D3B&=3Blt=3D3B/= >span&=3Bgt=3D3Ba.resize(std::unique(a.begi=3D3D<=3Bbr>=3B&=3Bgt= >=3D3B &=3Bgt=3D
>=3B >=3B=3D3B&=3Bgt=3D3Bn()=3D3D2C a.end()) -= > a.begin())=3D3D3B&=3Blt=3D3Bspan style=3D3D3D"font-size=3D
>=3B &g= >t=3B: 12pt=3D3D3B "&=3Bgt=3D3B&=3Bamp=3D3Bnbsp=3D3D3B=3D3D<=3Bbr>= >=3B&=3Bgt=3D3B &=3Bgt=3D3B&=3Bgt=3D3B &=3Bamp=3D3Bnbsp=3D
&g= >t=3B >=3B=3D3D3B&=3Blt=3D3B/span&=3Bgt=3D3B&=3Blt=3D3Bspan style= >=3D3D3D"font-size: 12pt=3D3D3B "&=3Bgt=3D3B&=3Bam=3D
>=3B >=3B= >p=3D3Bnbsp=3D3D3B&=3Blt=3D3B/span&=3Bgt=3D3B&=3Blt=3D3B/div&=3B= >gt=3D3B&=3Blt=3D3Bd=3D3D<=3Bbr>=3B&=3Bgt=3D3B &=3Bgt=3D3B&= >=3Bg=3D
>=3B >=3Bt=3D3Biv&=3Bgt=3D3B&=3Blt=3D3Bspan style=3D3D= >3D"font-size: 12pt=3D3D3B "&=3Bgt=3D3B&=3Bamp=3D3Bnbsp=3D
>=3B &= >gt=3B=3D3D3B &=3Bamp=3D3Bnbsp=3D3D3B for (auto i =3D3D3D a.=3D3D<=3Bbr= >>=3B&=3Bgt=3D3B &=3Bgt=3D3B&=3Bgt=3D3Bbegin(=3D
>=3B >=3B= >)=3D3D3B i !=3D3D3D a.end()=3D3D3B ++i)&=3Blt=3D3B/span&=3Bgt=3D3B&am= >p=3Blt=3D3B/div&=3Bgt=3D3B&=3Blt=3D3Bdiv=3D
>=3B >=3B&=3Bgt= >=3D3B&=3Blt=3D3Bspan style=3D3D3D"font-size=3D3D<=3Bbr>=3B&=3Bgt= >=3D3B &=3Bgt=3D3B&=3Bgt=3D3B: 12pt=3D3D3B =3D
>=3B >=3B"&= >=3Bgt=3D3B&=3Bamp=3D3Bnbsp=3D3D3B &=3Bamp=3D3Bnbsp=3D3D3B {&=3Blt= >=3D3Bbr&=3Bgt=3D3B&=3Bamp=3D3Bnbsp=3D3D3B &=3Ba=3D
>=3B >= >=3Bmp=3D3Bnbsp=3D3D3B &=3Bamp=3D3Bnbsp=3D3D3B do stuff with=3D3D<=3Bbr= >>=3B&=3Bgt=3D3B &=3Bgt=3D3B&=3Bgt=3D3B *i&=3B=3D
>=3B &g= >t=3Blt=3D3B/span&=3Bgt=3D3B&=3Blt=3D3B/div&=3Bgt=3D3B&=3Blt=3D3= >Bdiv&=3Bgt=3D3B&=3Blt=3D3Bspan style=3D3D3D"font-s=3D
>=3B >= >=3Bize: 12pt=3D3D3B "&=3Bgt=3D3B&=3Bamp=3D3Bnbsp=3D3D3B &=3Bamp=3D= >3Bnbsp=3D3D3B =3D3D<=3Bbr>=3B&=3Bgt=3D3B &=3Bgt=3D
>=3B >= >=3B=3D3B&=3Bgt=3D3B}&=3Blt=3D3B/span&=3Bgt=3D3B&=3Blt=3D3B/div&= >amp=3Bgt=3D3B&=3Blt=3D3Bdiv&=3Bgt=3D3B&=3Bamp=3D3Bnbsp=3D3D3B&= >=3B=3D
>=3B >=3Blt=3D3B/div&=3Bgt=3D3B&=3Blt=3D3Bdiv&=3Bgt= >=3D3B&=3Blt=3D3Bbr&=3Bgt=3D3B&=3Blt=3D3B/div&=3Bgt=3D3B&=3Bl= >t=3D3Bdiv&=3Bgt=3D3B=3D
>=3B >=3B&=3Blt=3D3Bspan style=3D3D3D"= >font-si=3D3D<=3Bbr>=3B&=3Bgt=3D3B &=3Bgt=3D3B&=3Bgt=3D3Bze: 12= >pt=3D3D3B "&=3Bgt=3D
>=3B >=3B=3D3B&=3Bamp=3D3Bnbsp=3D3D3B &am= >p=3Bamp=3D3Bnbsp=3D3D3B&=3Blt=3D3B/span&=3Bgt=3D3B&=3Blt=3D3Bspan = >style=3D3D3D"=3D
>=3B >=3Bfont-size: 12pt=3D3D3B "&=3Bgt=3D3B&= >=3Bamp=3D3B=3D3D<=3Bbr>=3B&=3Bgt=3D3B &=3Bgt=3D3B&=3Bgt=3D3Bnb= >sp=3D3D3B&=3Blt=3D
>=3B >=3B=3D3B/span&=3Bgt=3D3BNice=3D3D2C t= >erse=3D3D2C efficient.&=3Blt=3D3Bspan style=3D3D3D"font-siz=3D
>=3B= > >=3Be: 12pt=3D3D3B =3D3D<=3Bbr>=3B&=3Bgt=3D3B &=3Bgt=3D3B&= >=3Bgt=3D3B"&=3Bgt=3D3B&=3Bamp=3D3Bnbsp=3D3D3B &=3Bamp=3D3Bnbsp=3D<= >br>>=3B >=3B=3D3D3B&=3Blt=3D3B/span&=3Bgt=3D3B&=3Blt=3D3Bspan = >style=3D3D3D"font-size: 12pt=3D3D3B "&=3Bgt=3D3B&=3Bam=3D
>=3B &= >gt=3Bp=3D3Bnbsp=3D3D3B&=3Blt=3D3B/spa=3D3D<=3Bbr>=3B&=3Bgt=3D3B &= >amp=3Bgt=3D3B&=3Bgt=3D3Bn&=3Bgt=3D3B&=3Blt=3D3B/div&=3Bgt=3D3B&= >amp=3Blt=3D
>=3B >=3B=3D3Bdiv&=3Bgt=3D3B&=3Blt=3D3Bspan style= >=3D3D3D"font-size: 12pt=3D3D3B "&=3Bgt=3D3B&=3Bamp=3D3Bnbsp=3D
>= >=3B >=3B=3D3D3B &=3Bamp=3D3Bnbsp=3D3D3B&=3Blt=3D3B/span&=3Bgt=3D= >3B&=3Blt=3D3Bs=3D3D<=3Bbr>=3B&=3Bgt=3D3B &=3Bgt=3D3B&=3Bgt= >=3D3Bpan=3D
>=3B >=3B style=3D3D3D"font-size: 12pt=3D3D3B "&=3Bgt= >=3D3B&=3Bamp=3D3Bnbsp=3D3D3B&=3Blt=3D3B/span&=3Bgt=3D3BIn=3D
&g= >t=3B >=3B Modula-3?&=3Blt=3D3Bspan style=3D3D3D=3D3D<=3Bbr>=3B&= >=3Bgt=3D3B &=3Bgt=3D3B&=3Bgt=3D3B"font-size: 12pt=3D
>=3B >=3B= >=3D3D3B "&=3Bgt=3D3B&=3Bamp=3D3Bnbsp=3D3D3B &=3Bamp=3D3Bnbsp=3D3D3= >B&=3Blt=3D3B/span&=3Bgt=3D3B&=3Blt=3D3Bspan s=3D
>=3B >=3Bt= >yle=3D3D3D"font-size: 12p=3D3D<=3Bbr>=3B&=3Bgt=3D3B &=3Bgt=3D3B&a= >mp=3Bgt=3D3Bt=3D3D3B "&=3Bgt=3D3B&=3Bamp=3D3Bnbsp=3D
>=3B >=3B= >=3D3D3B&=3Blt=3D3B/span&=3Bgt=3D3B&=3Blt=3D3B/div&=3Bgt=3D3B&am= >p=3Blt=3D3Bdiv&=3Bgt=3D3B&=3Blt=3D3Bbr&=3Bgt=3D3B&=3Blt=3D3B/d= >=3D
>=3B >=3Biv&=3Bgt=3D3B&=3Blt=3D3Bdiv&=3Bgt=3D3B&=3Bl= >t=3D3Bbr&=3Bgt=3D3B&=3Blt=3D3B/div&=3Bgt=3D3B&=3Blt=3D3Bdiv&= >=3Bgt=3D3BI know =3D
>=3B >=3Bthat =3D3D<=3Bbr>=3B&=3Bgt=3D3B= > &=3Bgt=3D3B&=3Bgt=3D3Bunique is one of the easiest algorithms to m= >=3D
>=3B >=3Banually write inline=3D3D2C&=3Blt=3D3B/div&=3Bgt= >=3D3B&=3Blt=3D3Bd=3D3D<=3Bbr>=3B&=3Bgt=3D3B &=3Bgt=3D3B&=3B= >gt=3D3Bi=3D
>=3B >=3Bv&=3Bgt=3D3Bbut I shouldn't have to.&=3Bl= >t=3D3B/div&=3Bgt=3D3B&=3Blt=3D3Bdiv&=3Bgt=3D3B&=3Blt=3D3Bbr&= >=3Bgt=3D
>=3B >=3B=3D3B&=3Blt=3D3B/div&=3Bgt=3D3B&=3Blt=3D3= >Bdiv&=3Bgt=3D3B&=3Blt=3D3Bbr&=3Bgt=3D3B&=3Blt=3D3B/div&=3Bgt= >=3D3B&=3Blt=3D3Bdiv&=3Bg=3D
>=3B >=3Bt=3D3B(I'm re=3D3D<=3Bb= >r>=3B&=3Bgt=3D3B &=3Bgt=3D3B&=3Bgt=3D3Bally trying to stay in Mo= >dula-3 here=3D
>=3B >=3B=3D3D2C but it is definitely a struggle. :(= >=3D3D<=3Bbr>=3B&=3Bgt=3D3B &=3Bgt=3D3B&=3Bgt=3D3B )&=3Blt= >=3D3B=3D
>=3B >=3B/div&=3Bgt=3D3B&=3Blt=3D3Bdiv&=3Bgt=3D3B&= >amp=3Blt=3D3Bbr&=3Bgt=3D3B&=3Blt=3D3B/div&=3Bgt=3D3B&=3Blt=3D3B= >div&=3Bgt=3D3B&=3Blt=3D
>=3B >=3B=3D3Bbr&=3Bgt=3D3B&=3Bl= >t=3D3B/div&=3Bgt=3D3B&=3Blt=3D3Bdiv&=3Bgt=3D3BThank you=3D3D2C&= >=3Blt=3D3B/div&=3Bgt=3D3B&=3Blt=3D
>=3B >=3B=3D3Bdiv&=3Bgt= >=3D3B&=3Bamp=3D3Bnbsp=3D3D3B-=3D3D<=3Bbr>=3B&=3Bgt=3D3B &=3Bgt= >=3D3B&=3Bgt=3D3B Jay&=3Blt=3D3B/div&=3Bgt=3D3B=3D
>=3B >=3B= >&=3Blt=3D3Bbr&=3Bgt=3D3B&=3Blt=3D3Bbr&=3Bgt=3D3B&=3Blt=3D3B/= >div&=3Bgt=3D3B &=3Blt=3D3B/div&=3Bgt=3D3B&=3Blt=3Dr>>=3B >=3B=3D3B/body&=3Bgt=3D3B<=3Bbr>=3B&=3Bgt=3D3B &=3B= >gt=3D3B&=3Bgt=3D3B&=3Blt=3D3B/html&=3Bgt=3D3B=3D3D<=3Bbr>=3B&a= >mp=3Bgt=3D3B &=3Bgt=3D3B&=3B=3D
>=3B >=3Bgt=3D3B<=3Bbr>=3B= >&=3Bgt=3D3B &=3Bgt=3D3B&=3Bgt=3D3B--_d2a02ece-d492-410e-88fb-fb537= >37d7219_--<=3Bbr>=3B<=3B=3D
>=3B >=3B/div>=3B<=3B/div>= >=3B <=3B/div>=3B<=3B/body>=3B
>=3B >=3B<=3B/htm= >l>=3B=3D
>=3B >=3B
>=3B >=3B--_7877d7e8-cb4a-4989-bdcd-d406= >e5b1f51f_--
>= > >--_13e6ee6a-034c-469d-aa83-18379d050866_-- From jay.krell at cornell.edu Sat Sep 29 22:25:30 2012 From: jay.krell at cornell.edu (Jay K) Date: Sat, 29 Sep 2012 20:25:30 +0000 Subject: [M3devel] STL algorithms? sort/unique? In-Reply-To: <20120929201033.52DE71A2082@async.async.caltech.edu> References: , <20120928075656.751E21A2082@async.async.caltech.edu>, , <20120928080448.C80DD1A2082@async.async.caltech.edu>, , , <20120929182948.6589C1A2082@async.async.caltech.edu>, , <20120929201033.52DE71A2082@async.async.caltech.edu> Message-ID: There is probably more here you are unaware of. I strongly urge you to read more. Here are some important points: 1) The complexity of basically everything in STL is documented, part of the interface.The cost of adding to a vector. To a list. To a set.And btw, they specify which container modifications invalidate iterators. 2) The fact that quicksort requires a random access iterator is documented and checked at runtime. If I try something like:std::list a;std::sort(a.begin(), a.end()); I believe I get a compilation error.Historically maybe not a good one, but it is a popular area to complain about and compiler/library writers have made progress. There are some holes in the library.For example, binary_search returns a boolean, not the item found. That bothers me.But you are supposed to use lower_bound instead. It isn't as obvious imho as it should be how to bulk add to containers, and how to bulk add sorted items to a container. OO certainly shouldn't require heap.This is a failing of Modula-3.The OBJECT/METHOD sytax is decent.Optional garbage collection is good.But I should be able to separate them.Without resorting to putting function pointers in records..which isn't so bad, but the nice thing about "METHOD" (and virtual function pointers) is the implied/automatic/cheap/safe downcast of the "this" pointer. With function pointers in structs/records, you have some chance of not needing a cast, but it is very very common in both C++ and Modula-3 for their to be, again, that implied/automatic/cheap/safe downcast. I should spend some time applying the STL design to Modula-3 and see if the language supports it. But I'm too busy right now. :( - Jay > To: jay.krell at cornell.edu > Date: Sat, 29 Sep 2012 13:10:33 -0700 > From: mika at async.caltech.edu > CC: m3devel at elegosoft.com > Subject: Re: [M3devel] STL algorithms? sort/unique? > > > Yeah, OK, you could do this with GENERICs as well, by introducing > a convention. (In fact there is already one, t.iterate.) > > I still say it's a bit of a bug. If you have very generic methods that > can take different orders of time, then applying quicksort to a data structure > with high time complexity for those methods won't be very quick at all (except > to type). It can be very misleading unless you really know how everything > hangs together under the covers. I think that's the C/C++ mentality in general... > > (BTW I think C++ is a truly impressive programming language. The way you can do OO > programming without using the heap is really impressive. I just don't trust > myself, or anyone I know, to use it right. When even Stroustrup writes in his book, > about certain features, "ask an expert if you want to do this" you have to wonder.) > > Jay K writes: > >--_13e6ee6a-034c-469d-aa83-18379d050866_ > >Content-Type: text/plain; charset="iso-8859-1" > >Content-Transfer-Encoding: quoted-printable > > > > > The separation of algorithms from containers sounds a bit like a bug. > >It isn't. It is a leap that allows for far greater code reuse. Efficiently.= > >(You could do it inefficiently with lots of function pointers -- templates = > >allowfor inlinability. C++ beats C for performance here.) > > > >Imagine I have written quicksort.In C++ we have at least the following wort= > >hwhile "array-like" data structures: > > > > The builtin arrays. Like Modula-3 fixed arrays. > > > > Arrays you get with new[]. Like Modula-3 open arrays=2C but they don't ex= > >pose their size. > > > > std::vector<>. Like Modula-3 "sequence" -- a simple growable array. Grows= > > by a constant factor greater than 1 (typically 2)=2C so that long runs of = > >"appends" are amortized cheap. > > > > std::deque<>. More like Modula-3 sequence=2C in that you can amortized ch= > >eap at/remove from the front or the back. I believe this can be implemented= > > as simply an "offset array". Element 0 starts in the middle=2C and wheneve= > >r you grow it=2C you "center" it -- equal gaps at front and back. > > > >Now=2C with the iterator/algorithm separation=2C one quicksort implementati= > >on can be applied to all these types. The input to "quicksort" is "random a= > >ccess iterators"=2C which is very much like a "pointer"=2C but isn't necess= > >arily a pointer. It can be incremented=2C decremented=2C added to an intege= > >r=2C subtracted from another iterator=2C have an integer subtracted from it= > >=2C dereferenced=2C and assigned and compared with other iterators of the s= > >ame type -- all constant time fast operations. > > > >There are "input iterators" which can=2C roughly speaking=2C only be increm= > >ented and dereferenced. They are all some containers can expose and all som= > >e algorithms require -- for example=2C a singly linked list and linear sear= > >ch. > > > >There are "bidirectional iterators" which can=2C roughly speaking=2C only b= > >e incremented and decremented and dereferenced. Doubly linked lists expose = > >these. > > > >There are "output iterators".They are similar to "input". > > > >input streams (cin=2C like stdin) exposes an input iterator.You can copy fr= > >om it.Copy is another simple reusable algorithm. > > > >output streams (cout=2C like stdout) exposes an output iterator.You can cop= > >y to it. > > > >There are many more examples.Of course=2C besides quick sort=2C there is a = > >stable sort.There is finding sequences.There is binary_search.There is uppe= > >r_bound/lower_bound/equal_range which are like binary_search.There is uniqu= > >e.There is partition.Many many more=2C "built in" to the library.That work = > >with multiple "built in" containers=2C and can work with custom containers = > >as well. > > > >I strongly recommend you read up on this stuff.It is really quite illimunin= > >ating. Good stuff.Teaches us how to better factor our code.And to strive fo= > >r better factoring=2C when we find people have invented/discovered such thi= > >ngs. > > > >"Iterators" already do occur in Modula-3 libraries. > > > >All I want is a sorted vector that "closely knows" when it is being written= > > vs. read=2C and when there are a series of writes with no intervening read= > >s=2C it can amortize down the cost of maintaining the ordering. > > > >I hand coded something.It took me a while to get it to work due to stupid s= > >mall details.The result is significantly worse than I would have gotten in = > >C++.Bigger code. Slower code. More copies. More heap allocations.I can elim= > >inate one of the allocations by merging the next step.But in C++ I naturall= > >y wouldn't have had it anyway.Not great. > > > > - Jay > > > > > >> To: jay.krell at cornell.edu > >> CC: mika at async.caltech.edu=3B m3devel at elegosoft.com > >> Subject: Re: [M3devel] STL algorithms? sort/unique? > >> Date: Sat=2C 29 Sep 2012 11:29:48 -0700 > >> From: mika at async.caltech.edu > >>=20 > >>=20 > >> Well that depends on how you maintain the vector=2C no? > >>=20 > >> SortedTable uses "treaps" which are supposed to be good data structures. > >> Too new to have made it into Knuth=2C last I checked. The amortized cost > >> of your operations shouldn't be much worse than with your method=2C with > >> the additional benefit that the sorted order is maintained dynamically. > >>=20 > >> The separation of algorithms from containers sounds a bit like a bug. > >> You have to be careful so you don't shoot yourself in the foot there! > >> (Sorting a list using an algorithm that randomly accesses elements=2C > >> say...) > >>=20 > >> The Modula-3 approach is that you figure out what you want to do=2C pick > >> the ADT you want that provides the minimal set of operations=2C import > >> that interface=2C then instantiate a more carefully chosen implementation > >> of the ADT. The language itself obviously can be coaxed into supporting = > >the > >> algorithm/data structure separation but no one uses it that way as > >> far as I know. (Modula-3 generics are not that well explored=2C actually= > >. > >> I suspect there are many things you can do with them that no one has > >> tried.) > >>=20 > >> Mika > >>=20 > >> Jay K writes: > >> >--_7877d7e8-cb4a-4989-bdcd-d406e5b1f51f_ > >> >Content-Type: text/plain=3B charset=3D"iso-8859-1" > >> >Content-Transfer-Encoding: quoted-printable > >> > > >> >The following is very efficient: > >> > > >> >run through a bunch of records=3D2C picking out one number from some of = > >thema=3D > >> >ppend those numbers to a growing vectorsort the vectorunique the vector > >> > > >> >sequence allows for random access..but only via a function...or maybe an= > > it=3D > >> >erator > >> > > >> >STL has this wonderful separation of algorithms from containers=3D2C via= > > iter=3D > >> >ators.I suspect very few other libraries do.And it could be that most la= > >ngu=3D > >> >ages don't support it.It doesn't appear I can easily sort a sequence=3D2= > >C unl=3D > >> >ess I copy the data out into an array -- gross inefficiency. > >> > > >> >I've hacked something very manual together..and it is taking forever to = > >get=3D > >> > it to work. It turns out I can reasonably well bound the size of the d= > >ata=3D > >> >=3D2C so I'm using an open array...and I have to keep track of my positi= > >on in=3D > >> >stead of using addhi/push_back.Not happy.At some point I might give up a= > >nd =3D > >> >write the backend in C++..at which point I might as well write a C++ fro= > >nte=3D > >> >nd anywa. > >> > > >> > > >> >I absolutely do not want a sorted table and unique upon insert.That is m= > >uch=3D > >> > less efficient.What I'm describing uses temporarily larger working set = > >but=3D > >> > vastly less CPU.An array that gets sorted/uniqued occasionally=3D2C lik= > >e jus=3D > >> >t once.And not ongoing maintainence for every single add. > >> > > >> > > >> > - Jay > >> > > >> > > >> >> To: jay.krell at cornell.edu > >> >> CC: m3devel at elegosoft.com > >> >> Subject: Re: [M3devel] STL algorithms? sort/unique? > >> >> Date: Fri=3D2C 28 Sep 2012 01:04:48 -0700 > >> >> From: mika at async.caltech.edu > >> >>=3D20 > >> >>=3D20 > >> >> BTW I had the same experience when I first started using Modula-3. > >> >> It was painful to jump through all its hoops=3D2C coming from C=3D2C w= > >here yo=3D > >> >u > >> >> can do whatever you want to whatever bits happen to be sloshing around > >> >> your machine. C++ from what I have seen mainly lets you do that to > >> >> more bits in fewer lines of code. > >> >>=3D20 > >> >> But after a while I really came to appreciate the value of things like= > > th=3D > >> >e > >> >> language's telling me I'm using the wrong data structure instead of > >> >> just letting me use the same "nice=3D2C terse=3D2C efficient" syntax t= > >o write > >> >> a crappy program :-) > >> >>=3D20 > >> >> mika writes: > >> >> >You're using the wrong (abstract) data structure if you want sort and= > > un=3D > >> >ique. > >> >> > > >> >> >A "sequence" is meant to be accessed sequentially... > >> >> > > >> >> >Not knowing precisely what you're doing it sounds like you might want= > > a > >> >> >SortedTable... you can get unique on insert and access it in increasi= > >ng > >> >> >or decreasing order. > >> >> > > >> >> > Mika > >> >> > > >> >> >Jay K writes: > >> >> >>--_d2a02ece-d492-410e-88fb-fb53737d7219_ > >> >> >>Content-Type: text/plain=3D3B charset=3D3D"iso-8859-1" > >> >> >>Content-Transfer-Encoding: quoted-printable > >> >> >> > >> >> >> I have an IntSeq.T with a bunch of integers. =3D3D20 > >> >> >> What is a good terse efficient idiom for sort and unique? =3D3= > >D20 > >> >> >> > >> >> >> In C++ I would say: vector a=3D3D3B a.push_ba= > >ck(..=3D > >> >.)=3D3D3B =3D3D > >> >> >> a.push_back(...)=3D3D3B std::sort(a.begin()=3D3D2C a.e= > >nd())=3D > >> >=3D3D3B =3D3D > >> >> >> a.resize(std::unique(a.begin()=3D3D2C a.end()) - a.begin())=3D3D3B = > > =3D > >> >for (aut=3D3D > >> >> >>o i =3D3D3D a.begin()=3D3D3B i !=3D3D3D a.end()=3D3D3B ++i) { > >> >> >> do stuff with *i }=3D3D20 > >> >> >> Nice=3D3D2C terse=3D3D2C efficient. In Modula-3? =3D3D2= > >0 > >> >> >> > >> >> >>I know that unique is one of the easiest algorithms to manually writ= > >e i=3D > >> >nlin=3D3D > >> >> >>e=3D3D2Cbut I shouldn't have to. > >> >> >> > >> >> >>(I'm really trying to stay in Modula-3 here=3D3D2C but it is definit= > >ely a=3D > >> > strug=3D3D > >> >> >>gle. :( ) > >> >> >> > >> >> >>Thank you=3D3D2C - Jay > >> >> >> > >> >> >> =3D3D > >> >> >> > >> >> >>--_d2a02ece-d492-410e-88fb-fb53737d7219_ > >> >> >>Content-Type: text/html=3D3B charset=3D3D"iso-8859-1" > >> >> >>Content-Transfer-Encoding: quoted-printable > >> >> >> > >> >> >> > >> >> >> > >> >> >> > >> >> >>
 =3D3D3B &nbs= > >p=3D3D3B&nb=3D > >> >sp=3D3D3BI have =3D3D > >> >> >>an IntSeq.T with a bunch of integers. =3D3D3B  =3D3D3B = > >=3D3D3B >> >>
>> >> >>n style=3D3D3D"font-size: 12pt=3D3D3B "> =3D3D3B  =3D3D3B >pan> >> >tyle=3D3D3D"font=3D3D > >> >> >>-size: 12pt=3D3D3B "> =3D3D3BWhat is a good terse efficie= > >nt idio=3D > >> >m for so=3D3D > >> >> >>rt and unique? =3D3D= > >3B  =3D > >> >=3D3D3B<=3D3D > >> >> >>span style=3D3D3D"font-size: 12pt=3D3D3B "> =3D3D3B
= > >

=3D > >> >
>> >> >>>
 =3D3D3B  =3D3D3B In C++ I would say: >tyle=3D3D=3D > >> >3D"font-si=3D3D > >> >> >>ze: 12pt=3D3D3B "> =3D3D3B  =3D3D3B >"font-size:=3D > >> > 12pt=3D3D3B ">&=3D3D > >> >> >>nbsp=3D3D3B
>3B ">&nbs=3D > >> >p=3D3D3B  =3D3D > >> >> >>=3D3D3B =3D3D= > >3Bve=3D > >> >ctor<=3D3D3Bin=3D3D > >> >> >>t>=3D3D3B a=3D3D3B&nbs= > >p=3D3D3B &nbs=3D > >> >p=3D3D3B >> >> >>an style=3D3D3D"font-size: 12pt=3D3D3B "> =3D3D3B
>iv> >> >style=3D3D3D"f=3D3D > >> >> >>ont-size: 12pt=3D3D3B "> =3D3D3B  =3D3D3B >=3D3D3D"font=3D > >> >-size: 12pt=3D3D > >> >> >>=3D3D3B "> =3D3D3Ba.push_back(...)=3D3D3B >3D"font-siz=3D > >> >e: 12pt=3D3D3B "=3D3D > >> >> >>> =3D3D3B  =3D3D3B >=3D3D3B ">&n=3D > >> >bsp=3D3D3B >> >> >>>
 = > >=3D3D3B &nb=3D > >> >sp=3D3D3B >> >> >>n> =3D3D3Ba.p= > >ush_back(=3D > >> >...)=3D3D3B >> >> >>an style=3D3D3D"font-size: 12pt=3D3D3B "> =3D3D3B  =3D3D3B >span> >> >style=3D3D3D"fon=3D3D > >> >> >>t-size: 12pt=3D3D3B "> =3D3D3B
>3D"font-s=3D > >> >ize: 12pt=3D3D > >> >> >>=3D3D3B "> =3D3D3B  =3D3D3B >ze: 12pt=3D3D=3D > >> >3B "> =3D3D3B<=3D3D > >> >> >>/span>std::sort(a.begin()=3D3D2C a.end())=3D3D3B >ont-size:=3D > >> > 12pt=3D3D3B "=3D3D > >> >> >>> =3D3D3B  =3D3D3B >=3D3D3B ">&n=3D > >> >bsp=3D3D3B >> >> >>>
 =3D3D3B= > >  =3D3D=3D > >> >3B >> >> >>an style=3D3D3D"font-size: 12pt=3D3D3B "> =3D3D3Ba.resize= > >(std::uni=3D > >> >que(a.begi=3D3D > >> >> >>n()=3D3D2C a.end()) - a.begin())=3D3D3B > 12pt=3D3D3=3D > >> >B "> =3D3D3B=3D3D > >> >> >>  =3D3D3B&nbs= > >p=3D3D3B >> >pan>
>> >> >>iv> =3D3D3B  =3D= > >3D3B for (a=3D > >> >uto i =3D3D3D a.=3D3D > >> >> >>begin()=3D3D3B i !=3D3D3D a.end()=3D3D3B ++i)
> style=3D3D=3D > >> >3D"font-size=3D3D > >> >> >>: 12pt=3D3D3B "> =3D3D3B  =3D3D3B {
 =3D3D3B  =3D= > >3D3B  =3D3D=3D > >> >3B do stuff with=3D3D > >> >> >> *i
&nb= > >sp=3D3D3B=3D > >> >  =3D3D3B =3D3D > >> >> >>}
 =3D3D3B

>=3D3D3D=3D > >> >"font-si=3D3D > >> >> >>ze: 12pt=3D3D3B "> =3D3D3B  =3D3D3B >"font-size:=3D > >> > 12pt=3D3D3B ">&=3D3D > >> >> >>nbsp=3D3D3BNice=3D3D2C terse=3D3D2C efficient. >D3D"font-si=3D > >> >ze: 12pt=3D3D3B =3D3D > >> >> >>"> =3D3D3B  =3D3D3B >=3D3D3B ">&=3D > >> >nbsp=3D3D3B >> >> >>n>
 =3D3D3= > >B  =3D > >> >=3D3D3B >> >> >>pan style=3D3D3D"font-size: 12pt=3D3D3B "> =3D3D3BIn Modu= > >la-3? >> >n style=3D3D3D=3D3D > >> >> >>"font-size: 12pt=3D3D3B "> =3D3D3B  =3D3D3B >e=3D3D3D"fo=3D > >> >nt-size: 12p=3D3D > >> >> >>t=3D3D3B "> =3D3D3B


>iv>I kn=3D > >> >ow that =3D3D > >> >> >>unique is one of the easiest algorithms to manually write inline=3D3= > >D2C >> >div> >> >> >>iv>but I shouldn't have to.


= > >(I'=3D > >> >m re=3D3D > >> >> >>ally trying to stay in Modula-3 here=3D3D2C but it is definitely a s= > >trugg=3D > >> >le. :(=3D3D > >> >> >> )


Thank you=3D3D2C
>v>&nb=3D > >> >sp=3D3D3B-=3D3D > >> >> >> Jay


> >> >> >>=3D3D > >> >> >> > >> >> >>--_d2a02ece-d492-410e-88fb-fb53737d7219_-- > >> > =3D > >> > > >> >--_7877d7e8-cb4a-4989-bdcd-d406e5b1f51f_ > >> >Content-Type: text/html=3B charset=3D"iso-8859-1" > >> >Content-Transfer-Encoding: quoted-printable > >> > > >> > > >> > > >> > > >> >
>t-size: 1=3D > >> >2pt=3D3B ">The following is very efficient:

<= > >div><=3D > >> >br>
run through a bunch of records=3D2C picking out one number= > > from=3D > >> > some of them
append those numbers to a growing vector
>iv>=3D > >> >sort the vector
unique the vector

>> >> >div>
sequence allows for random access..but only via a function... >div=3D > >> >>
or maybe an iterator


STL h= > >as =3D > >> >this wonderful separation of algorithms from containers=3D2C via iterato= > >rs. >> >div>
I suspect very few other libraries do.
And it could b= > >e t=3D > >> >hat most languages don't support it.
It doesn't appear I can e= > >asi=3D > >> >ly sort a sequence=3D2C unless I copy the data out into an array -- gros= > >s ine=3D > >> >fficiency.


I've hacked something= > > ve=3D > >> >ry manual together..and it is taking forever to get it to work.
>v>&=3D > >> >nbsp=3D3B It turns out I can reasonably well bound the size of the data= > >=3D2C so=3D > >> > I'm using an open array...and I have to keep track of my position inste= > >ad =3D > >> >of using addhi/push_back.
Not happy.
At some point I= > > mi=3D > >> >ght give up and write the backend in C++..at which point I might as well= > > wr=3D > >> >ite a C++ frontend anywa.



>div=3D > >> >>
I absolutely do not want a sorted table and unique upon insert. >iv>=3D > >> >
That is much less efficient.
What I'm describing uses tem= > >por=3D > >> >arily larger working set but vastly less CPU.
An array that ge= > >ts =3D > >> >sorted/uniqued occasionally=3D2C like just once.
And not ongoi= > >ng ma=3D > >> >intainence for every single add.


>> >> >r>
 =3D3B- Jay



>DrivePl=3D > >> >aceholder">
>=3D3B To: jay.krell at cornell.edu
>=3D3B CC: m3de= > >vel at ele=3D > >> >gosoft.com
>=3D3B Subject: Re: [M3devel] STL algorithms? sort/uniqu= > >e? >> >>>=3D3B Date: Fri=3D2C 28 Sep 2012 01:04:48 -0700
>=3D3B From: mi= > >ka at async.=3D > >> >caltech.edu
>=3D3B
>=3D3B
>=3D3B BTW I had the same exp= > >erience w=3D > >> >hen I first started using Modula-3.
>=3D3B It was painful to jump t= > >hroug=3D > >> >h all its hoops=3D2C coming from C=3D2C where you
>=3D3B can do wha= > >tever you=3D > >> > want to whatever bits happen to be sloshing around
>=3D3B your mac= > >hine.=3D > >> > C++ from what I have seen mainly lets you do that to
>=3D3B more = > >bits =3D > >> >in fewer lines of code.
>=3D3B
>=3D3B But after a while I rea= > >lly cam=3D > >> >e to appreciate the value of things like the
>=3D3B language's tell= > >ing m=3D > >> >e I'm using the wrong data structure instead of
>=3D3B just letting= > > me u=3D > >> >se the same "nice=3D2C terse=3D2C efficient" syntax to write
>=3D3B= > > a crappy=3D > >> > program :-)
>=3D3B
>=3D3B mika writes:
>=3D3B >=3D3BY= > >ou're using=3D > >> > the wrong (abstract) data structure if you want sort and unique.
>= > >=3D3B=3D > >> > >=3D3B
>=3D3B >=3D3BA "sequence" is meant to be accessed seque= > >ntially..=3D > >> >.
>=3D3B >=3D3B
>=3D3B >=3D3BNot knowing precisely what yo= > >u're doing =3D > >> >it sounds like you might want a
>=3D3B >=3D3BSortedTable... you c= > >an get =3D > >> >unique on insert and access it in increasing
>=3D3B >=3D3Bor decr= > >easing =3D > >> >order.
>=3D3B >=3D3B
>=3D3B >=3D3B Mika
>=3D3B >= > >=3D3B
>=3D3B=3D > >> > >=3D3BJay K writes:
>=3D3B >=3D3B>=3D3B--_d2a02ece-d492-410e= > >-88fb-fb537=3D > >> >37d7219_
>=3D3B >=3D3B>=3D3BContent-Type: text/plain=3D3B chars= > >et=3D3D"iso-8=3D > >> >859-1"
>=3D3B >=3D3B>=3D3BContent-Transfer-Encoding: quoted-pri= > >ntable >> >>>=3D3B >=3D3B>=3D3B
>=3D3B >=3D3B>=3D3B I have an Int= > >Seq.T with a bu=3D > >> >nch of integers. =3D3D20
>=3D3B >=3D3B>=3D3B What is a goo= > >d terse eff=3D > >> >icient idiom for sort and unique? =3D3D20
>=3D3B >=3D3B>=3D3B= > >
>=3D3B =3D > >> >>=3D3B>=3D3B In C++ I would say: vector<=3D3Bint>=3D3B= > > a=3D3D3B =3D > >> > a.push_back(...)=3D3D3B =3D3D
>=3D3B >=3D3B>=3D3B a.p= > >ush_back(...)=3D > >> >=3D3D3B std::sort(a.begin()=3D3D2C a.end())=3D3D3B =3D3D >>>=3D3B >=3D > >> >=3D3B>=3D3B a.resize(std::unique(a.begin()=3D3D2C a.end()) - a.begin()= > >)=3D3D3B =3D > >> > for (aut=3D3D
>=3D3B >=3D3B>=3D3Bo i =3D3D3D a.begin()=3D3= > >D3B i !=3D3D3D a.=3D > >> >end()=3D3D3B ++i) {
>=3D3B >=3D3B>=3D3B do stuff with *= > >i }=3D3D20=3D > >> >
>=3D3B >=3D3B>=3D3B Nice=3D3D2C terse=3D3D2C efficient. = > > In Modula=3D > >> >-3? =3D3D20
>=3D3B >=3D3B>=3D3B
>=3D3B >=3D3B>=3D3BI= > > know that unique=3D > >> > is one of the easiest algorithms to manually write inlin=3D3D
>=3D= > >3B >=3D > >> >=3D3B>=3D3Be=3D3D2Cbut I shouldn't have to.
>=3D3B >=3D3B>=3D= > >3B
>=3D3B &g=3D > >> >t=3D3B>=3D3B(I'm really trying to stay in Modula-3 here=3D3D2C but it = > >is defini=3D > >> >tely a strug=3D3D
>=3D3B >=3D3B>=3D3Bgle. :( )
>=3D3B >= > >=3D3B>=3D3B
&=3D > >> >gt=3D3B >=3D3B>=3D3BThank you=3D3D2C - Jay
>=3D3B >=3D3B>= > >=3D3B
>=3D3B >=3D > >> >=3D3B>=3D3B =3D3D
>=3D3B >=3D3B>=3D3B
>=3D3B = > >>=3D3B>=3D3B--_d2=3D > >> >a02ece-d492-410e-88fb-fb53737d7219_
>=3D3B >=3D3B>=3D3BContent-= > >Type: tex=3D > >> >t/html=3D3B charset=3D3D"iso-8859-1"
>=3D3B >=3D3B>=3D3BContent= > >-Transfer-Enc=3D > >> >oding: quoted-printable
>=3D3B >=3D3B>=3D3B
>=3D3B >=3D3= > >B>=3D3B<=3D3B=3D > >> >html>=3D3B
>=3D3B >=3D3B>=3D3B<=3D3Bhead>=3D3B
>=3D3= > >B >=3D3B>=3D3B<=3D > >> >=3D3Bstyle>=3D3B<=3D3B!--
>=3D3B >=3D3B>=3D3B.hmmessage P >r>>=3D3B >=3D3B=3D > >> >>=3D3B{
>=3D3B >=3D3B>=3D3Bmargin:0px=3D3D3B
>=3D3B >= > >=3D3B>=3D3Bpadding=3D > >> >:0px
>=3D3B >=3D3B>=3D3B}
>=3D3B >=3D3B>=3D3Bbody.hmme= > >ssage
>=3D3B=3D > >> > >=3D3B>=3D3B{
>=3D3B >=3D3B>=3D3Bfont-size: 12pt=3D3D3B >>>=3D3B >=3D3B&=3D > >> >gt=3D3Bfont-family:Calibri
>=3D3B >=3D3B>=3D3B}
>=3D3B >= > >=3D3B>=3D3B--&g=3D > >> >t=3D3B<=3D3B/style>=3D3B<=3D3B/head>=3D3B
>=3D3B >=3D3B&g= > >t=3D3B<=3D3Bbody cl=3D > >> >ass=3D3D3D'hmmessage'>=3D3B<=3D3Bdiv dir=3D3D3D'ltr'>=3D3B&=3D3= > >Bnbsp=3D3D3B &=3D > >> >=3D3Bnbsp=3D3D3B&=3D3Bnbsp=3D3D3BI have =3D3D
>=3D3B >=3D3B>= > >=3D3Ban IntSeq.T wi=3D > >> >th a bunch of integers.&=3D3Bnbsp=3D3D3B &=3D3Bnbsp=3D3D3B&=3D3= > >Bnbsp=3D3D3B<=3D > >> >=3D3Bbr>=3D3B<=3D3Bdiv>=3D3B<=3D3Bspa=3D3D
>=3D3B >=3D3B&= > >gt=3D3Bn style=3D3D3D"f=3D > >> >ont-size: 12pt=3D3D3B ">=3D3B&=3D3Bnbsp=3D3D3B &=3D3Bnbsp=3D3D3B= > ><=3D3B/span>=3D > >> >=3D3B<=3D3Bspan style=3D3D3D"font=3D3D
>=3D3B >=3D3B>=3D3B-si= > >ze: 12pt=3D3D3B "&g=3D > >> >t=3D3B&=3D3Bnbsp=3D3D3B<=3D3B/span>=3D3BWhat is a good terse effi= > >cient idiom f=3D > >> >or so=3D3D
>=3D3B >=3D3B>=3D3Brt and unique?<=3D3Bspan style= > >=3D3D3D"font-siz=3D > >> >e: 12pt=3D3D3B ">=3D3B&=3D3Bnbsp=3D3D3B &=3D3Bnbsp=3D3D3B<=3D3= > >B/span>=3D3B<=3D > >> >=3D3B=3D3D
>=3D3B >=3D3B>=3D3Bspan style=3D3D3D"font-size: 12pt= > >=3D3D3B ">=3D3B&a=3D > >> >mp=3D3Bnbsp=3D3D3B<=3D3B/span>=3D3B<=3D3B/div>=3D3B<=3D3Bdiv&g= > >t=3D3B<=3D3Bbr>=3D > >> >=3D3B<=3D3B/div>=3D3B<=3D3Bdiv=3D3D
>=3D3B >=3D3B>=3D3B&g= > >t=3D3B<=3D3Bbr>=3D3B&=3D > >> >lt=3D3B/div>=3D3B<=3D3Bdiv>=3D3B&=3D3Bnbsp=3D3D3B &=3D3Bnbsp= > >=3D3D3B In C++ I wo=3D > >> >uld say:<=3D3Bspan style=3D3D3D"font-si=3D3D
>=3D3B >=3D3B>= > >=3D3Bze: 12pt=3D3D3=3D > >> >B ">=3D3B&=3D3Bnbsp=3D3D3B &=3D3Bnbsp=3D3D3B<=3D3B/span>=3D3= > >B<=3D3Bspan style=3D > >> >=3D3D3D"font-size: 12pt=3D3D3B ">=3D3B&=3D3B=3D3D
>=3D3B >= > >=3D3B>=3D3Bnbsp=3D3D3=3D > >> >B<=3D3B/span>=3D3B<=3D3B/div>=3D3B<=3D3Bdiv>=3D3B<=3D3Bspa= > >n style=3D3D3D"font=3D > >> >-size: 12pt=3D3D3B ">=3D3B&=3D3Bnbsp=3D3D3B &=3D3Bnbsp=3D3D
&= > >gt=3D3B >=3D3B>=3D > >> >=3D3B=3D3D3B<=3D3B/span>=3D3B<=3D3Bspan style=3D3D3D"font-size: 12= > >pt=3D3D3B ">=3D3B=3D > >> >&=3D3Bnbsp=3D3D3B<=3D3B/span>=3D3Bvector&=3D3Blt=3D3D3Bin=3D3D= > >
>=3D3B >=3D3B=3D > >> >>=3D3Bt&=3D3Bgt=3D3D3B a=3D3D3B<=3D3Bspan style=3D3D3D"font-size:= > > 12pt=3D3D3B ">=3D > >> >=3D3B&=3D3Bnbsp=3D3D3B &=3D3Bnbsp=3D3D3B<=3D3B/span>=3D3B<= > >=3D3Bsp=3D3D
>=3D3B =3D > >> >>=3D3B>=3D3Ban style=3D3D3D"font-size: 12pt=3D3D3B ">=3D3B&=3D3= > >Bnbsp=3D3D3B<=3D > >> >=3D3B/span>=3D3B<=3D3B/div>=3D3B<=3D3Bdiv>=3D3B<=3D3Bspan st= > >yle=3D3D3D"f=3D3D
=3D > >> >>=3D3B >=3D3B>=3D3Bont-size: 12pt=3D3D3B ">=3D3B&=3D3Bnbsp=3D= > >3D3B &=3D3Bnbsp=3D > >> >=3D3D3B<=3D3B/span>=3D3B<=3D3Bspan style=3D3D3D"font-size: 12pt=3D= > >3D
>=3D3B &g=3D > >> >t=3D3B>=3D3B=3D3D3B ">=3D3B&=3D3Bnbsp=3D3D3B<=3D3B/span>=3D3B= > >a.push_back(...)=3D3D=3D > >> >3B<=3D3Bspan style=3D3D3D"font-size: 12pt=3D3D3B "=3D3D
>=3D3B &g= > >t=3D3B>=3D3B>=3D > >> >=3D3B&=3D3Bnbsp=3D3D3B &=3D3Bnbsp=3D3D3B<=3D3B/span>=3D3B<= > >=3D3Bspan style=3D3D3D"=3D > >> >font-size: 12pt=3D3D3B ">=3D3B&=3D3Bnbsp=3D3D3B<=3D3B/span=3D3D >r>>=3D3B >=3D3B=3D > >> >>=3D3B>=3D3B<=3D3B/div>=3D3B<=3D3Bdiv>=3D3B<=3D3Bdiv>=3D= > >3B<=3D3Bspan style=3D > >> >=3D3D3D"font-size: 12pt=3D3D3B ">=3D3B&=3D3Bnbsp=3D3D3B &=3D3Bnb= > >sp=3D3D3B<=3D3B/s=3D > >> >pa=3D3D
>=3D3B >=3D3B>=3D3Bn>=3D3B<=3D3Bspan style=3D3D3D"f= > >ont-size: 12pt=3D3D=3D > >> >3B ">=3D3B&=3D3Bnbsp=3D3D3B<=3D3B/span>=3D3Ba.push_back(...)=3D= > >3D3B<=3D3Bsp=3D3D=3D > >> >
>=3D3B >=3D3B>=3D3Ban style=3D3D3D"font-size: 12pt=3D3D3B ">= > >=3D3B&=3D3Bnbs=3D > >> >p=3D3D3B &=3D3Bnbsp=3D3D3B<=3D3B/span>=3D3B<=3D3Bspan style=3D3= > >D3D"fon=3D3D
>=3D > >> >=3D3B >=3D3B>=3D3Bt-size: 12pt=3D3D3B ">=3D3B&=3D3Bnbsp=3D3D3B&= > >lt=3D3B/span>=3D3B&=3D > >> >lt=3D3B/div>=3D3B<=3D3Bdiv>=3D3B<=3D3Bspan style=3D3D3D"font-siz= > >e: 12pt=3D3D
&=3D > >> >gt=3D3B >=3D3B>=3D3B=3D3D3B ">=3D3B&=3D3Bnbsp=3D3D3B &=3D3Bn= > >bsp=3D3D3B<=3D3B/span=3D > >> >>=3D3B<=3D3Bspan style=3D3D3D"font-size: 12pt=3D3D3B ">=3D3B&= > >=3D3Bnbsp=3D3D3B<=3D > >> >=3D3B=3D3D
>=3D3B >=3D3B>=3D3B/span>=3D3Bstd::sort(a.begin()= > >=3D3D2C a.end())=3D > >> >=3D3D3B<=3D3Bspan style=3D3D3D"font-size: 12pt=3D3D3B "=3D3D
>=3D= > >3B >=3D3B>=3D3B=3D > >> >>=3D3B&=3D3Bnbsp=3D3D3B &=3D3Bnbsp=3D3D3B<=3D3B/span>=3D3B&l= > >t=3D3Bspan style=3D3D=3D > >> >3D"font-size: 12pt=3D3D3B ">=3D3B&=3D3Bnbsp=3D3D3B<=3D3B/span=3D3= > >D
>=3D3B >=3D > >> >=3D3B>=3D3B>=3D3B<=3D3B/div>=3D3B<=3D3Bdiv>=3D3B<=3D3Bspan= > > style=3D3D3D"font-si=3D > >> >ze: 12pt=3D3D3B ">=3D3B&=3D3Bnbsp=3D3D3B &=3D3Bnbsp=3D3D3B<=3D= > >3B/span>=3D3B<=3D > >> >=3D3Bsp=3D3D
>=3D3B >=3D3B>=3D3Ban style=3D3D3D"font-size: 12pt= > >=3D3D3B ">=3D3B&a=3D > >> >mp=3D3Bnbsp=3D3D3B<=3D3B/span>=3D3Ba.resize(std::unique(a.begi=3D3D<= > >br>>=3D3B >=3D > >> >=3D3B>=3D3Bn()=3D3D2C a.end()) - a.begin())=3D3D3B<=3D3Bspan style= > >=3D3D3D"font-size=3D > >> >: 12pt=3D3D3B ">=3D3B&=3D3Bnbsp=3D3D3B=3D3D
>=3D3B >=3D3B>= > >=3D3B &=3D3Bnbsp=3D > >> >=3D3D3B<=3D3B/span>=3D3B<=3D3Bspan style=3D3D3D"font-size: 12pt=3D= > >3D3B ">=3D3B&am=3D > >> >p=3D3Bnbsp=3D3D3B<=3D3B/span>=3D3B<=3D3B/div>=3D3B<=3D3Bd=3D3D= > >
>=3D3B >=3D3B&g=3D > >> >t=3D3Biv>=3D3B<=3D3Bspan style=3D3D3D"font-size: 12pt=3D3D3B ">=3D= > >3B&=3D3Bnbsp=3D > >> >=3D3D3B &=3D3Bnbsp=3D3D3B for (auto i =3D3D3D a.=3D3D
>=3D3B >= > >=3D3B>=3D3Bbegin(=3D > >> >)=3D3D3B i !=3D3D3D a.end()=3D3D3B ++i)<=3D3B/span>=3D3B<=3D3B/div= > >>=3D3B<=3D3Bdiv=3D > >> >>=3D3B<=3D3Bspan style=3D3D3D"font-size=3D3D
>=3D3B >=3D3B>= > >=3D3B: 12pt=3D3D3B =3D > >> >">=3D3B&=3D3Bnbsp=3D3D3B &=3D3Bnbsp=3D3D3B {<=3D3Bbr>=3D3B&a= > >mp=3D3Bnbsp=3D3D3B &a=3D > >> >mp=3D3Bnbsp=3D3D3B &=3D3Bnbsp=3D3D3B do stuff with=3D3D
>=3D3B &= > >gt=3D3B>=3D3B *i&=3D > >> >lt=3D3B/span>=3D3B<=3D3B/div>=3D3B<=3D3Bdiv>=3D3B<=3D3Bspan = > >style=3D3D3D"font-s=3D > >> >ize: 12pt=3D3D3B ">=3D3B&=3D3Bnbsp=3D3D3B &=3D3Bnbsp=3D3D3B =3D3= > >D
>=3D3B >=3D > >> >=3D3B>=3D3B}<=3D3B/span>=3D3B<=3D3B/div>=3D3B<=3D3Bdiv>=3D= > >3B&=3D3Bnbsp=3D3D3B&=3D > >> >lt=3D3B/div>=3D3B<=3D3Bdiv>=3D3B<=3D3Bbr>=3D3B<=3D3B/div>= > >=3D3B<=3D3Bdiv>=3D3B=3D > >> ><=3D3Bspan style=3D3D3D"font-si=3D3D
>=3D3B >=3D3B>=3D3Bze: 1= > >2pt=3D3D3B ">=3D > >> >=3D3B&=3D3Bnbsp=3D3D3B &=3D3Bnbsp=3D3D3B<=3D3B/span>=3D3B<= > >=3D3Bspan style=3D3D3D"=3D > >> >font-size: 12pt=3D3D3B ">=3D3B&=3D3B=3D3D
>=3D3B >=3D3B>= > >=3D3Bnbsp=3D3D3B<=3D > >> >=3D3B/span>=3D3BNice=3D3D2C terse=3D3D2C efficient.<=3D3Bspan style= > >=3D3D3D"font-siz=3D > >> >e: 12pt=3D3D3B =3D3D
>=3D3B >=3D3B>=3D3B">=3D3B&=3D3Bnbsp= > >=3D3D3B &=3D3Bnbsp=3D > >> >=3D3D3B<=3D3B/span>=3D3B<=3D3Bspan style=3D3D3D"font-size: 12pt=3D= > >3D3B ">=3D3B&am=3D > >> >p=3D3Bnbsp=3D3D3B<=3D3B/spa=3D3D
>=3D3B >=3D3B>=3D3Bn>=3D3B= > ><=3D3B/div>=3D3B<=3D > >> >=3D3Bdiv>=3D3B<=3D3Bspan style=3D3D3D"font-size: 12pt=3D3D3B ">=3D= > >3B&=3D3Bnbsp=3D > >> >=3D3D3B &=3D3Bnbsp=3D3D3B<=3D3B/span>=3D3B<=3D3Bs=3D3D
>= > >=3D3B >=3D3B>=3D3Bpan=3D > >> > style=3D3D3D"font-size: 12pt=3D3D3B ">=3D3B&=3D3Bnbsp=3D3D3B<=3D= > >3B/span>=3D3BIn=3D > >> > Modula-3?<=3D3Bspan style=3D3D3D=3D3D
>=3D3B >=3D3B>=3D3B"fo= > >nt-size: 12pt=3D > >> >=3D3D3B ">=3D3B&=3D3Bnbsp=3D3D3B &=3D3Bnbsp=3D3D3B<=3D3B/span&= > >gt=3D3B<=3D3Bspan s=3D > >> >tyle=3D3D3D"font-size: 12p=3D3D
>=3D3B >=3D3B>=3D3Bt=3D3D3B "&g= > >t=3D3B&=3D3Bnbsp=3D > >> >=3D3D3B<=3D3B/span>=3D3B<=3D3B/div>=3D3B<=3D3Bdiv>=3D3B<= > >=3D3Bbr>=3D3B<=3D3B/d=3D > >> >iv>=3D3B<=3D3Bdiv>=3D3B<=3D3Bbr>=3D3B<=3D3B/div>=3D3B<= > >=3D3Bdiv>=3D3BI know =3D > >> >that =3D3D
>=3D3B >=3D3B>=3D3Bunique is one of the easiest algo= > >rithms to m=3D > >> >anually write inline=3D3D2C<=3D3B/div>=3D3B<=3D3Bd=3D3D
>=3D3= > >B >=3D3B>=3D3Bi=3D > >> >v>=3D3Bbut I shouldn't have to.<=3D3B/div>=3D3B<=3D3Bdiv>=3D3B= > ><=3D3Bbr>=3D > >> >=3D3B<=3D3B/div>=3D3B<=3D3Bdiv>=3D3B<=3D3Bbr>=3D3B<=3D3B/d= > >iv>=3D3B<=3D3Bdiv&g=3D > >> >t=3D3B(I'm re=3D3D
>=3D3B >=3D3B>=3D3Bally trying to stay in Mo= > >dula-3 here=3D > >> >=3D3D2C but it is definitely a struggle. :(=3D3D
>=3D3B >=3D3B>= > >=3D3B )<=3D3B=3D > >> >/div>=3D3B<=3D3Bdiv>=3D3B<=3D3Bbr>=3D3B<=3D3B/div>=3D3B<= > >=3D3Bdiv>=3D3B<=3D > >> >=3D3Bbr>=3D3B<=3D3B/div>=3D3B<=3D3Bdiv>=3D3BThank you=3D3D2C&l= > >t=3D3B/div>=3D3B<=3D > >> >=3D3Bdiv>=3D3B&=3D3Bnbsp=3D3D3B-=3D3D
>=3D3B >=3D3B>=3D3B = > >Jay<=3D3B/div>=3D3B=3D > >> ><=3D3Bbr>=3D3B<=3D3Bbr>=3D3B<=3D3B/div>=3D3B <= > >=3D3B/div>=3D3B<=3D > >> >=3D3B/body>=3D3B
>=3D3B >=3D3B>=3D3B<=3D3B/html>=3D3B=3D3= > >D
>=3D3B >=3D3B&=3D > >> >gt=3D3B
>=3D3B >=3D3B>=3D3B--_d2a02ece-d492-410e-88fb-fb53737d7= > >219_--
<=3D > >> >/div>
> >> >=3D > >> > > >> >--_7877d7e8-cb4a-4989-bdcd-d406e5b1f51f_-- > > = > > > >--_13e6ee6a-034c-469d-aa83-18379d050866_ > >Content-Type: text/html; charset="iso-8859-1" > >Content-Transfer-Encoding: quoted-printable > > > > > > > > > >
 >818199157715px=3B white-space: normal=3B font-size: 15.454545021057129px=3B=
> > background-color: rgb(255=2C 255=2C 255)=3B "> =3B>=3B The separatio=
> >n of algorithms from containers sounds a bit like a bug.

>v>It isn't. It is a leap that allows for far greater code reuse. Efficientl= > >y.
(You could do it inefficiently with lots of function pointers -- tem= > >plates allow
for inlinability. C++ beats C for performance here.)= > >


Imagine I have written quicks= > >ort.
In C++ we have at least the following worthwhile "array-like= > >" data structures:


 =3B The bui= > >ltin arrays. Like Modula-3 fixed arrays.


>>
 =3B Arrays you get with new[]. Like Modula-3 open arrays=2C but = > >they don't expose their size.


 = > >=3B std::vector<=3B>=3B. Like Modula-3 "sequence" -- a simple growable = > >array. Grows by a constant factor greater than 1 (typically 2)=2C so that l= > >ong runs of "appends" are amortized cheap.


>iv>
 =3B std::deque<=3B>=3B. More like Modula-3 sequence=2C in = > >that you can amortized cheap at/remove from the front or the back. I believ= > >e this can be implemented as simply an "offset array". Element 0 starts in = > >the middle=2C and whenever you grow it=2C you "center" it -- equal gaps at = > >front and back.


Now=2C with the ite= > >rator/algorithm separation=2C one quicksort implementation can be applied t= > >o all these types. The input to "quicksort" is "random access iterators"=2C= > > which is very much like a "pointer"=2C but isn't necessarily a pointer. It= > > can be incremented=2C decremented=2C added to an integer=2C subtracted fro= > >m another iterator=2C have an integer subtracted from it=2C dereferenced=2C= > > and assigned and compared with other iterators of the same type -- all con= > >stant time fast operations.


There are "input i= > >terators" which can=2C roughly speaking=2C only be incremented and derefere= > >nced. They are all some containers can expose and all some algorithms requi= > >re -- for example=2C a singly linked list and linear search.

= > >

There are "bidirectional iterators" which can=2C = > >roughly speaking=2C only be incremented and decremented and dereferenced. D= > >oubly linked lists expose these.


Th= > >ere are "output iterators".
They are similar to "input".
>v>

input streams (cin=2C like stdin) exposes a= > >n input iterator.
You can copy from it.
Copy is another= > > simple reusable algorithm.


output = > >streams (cout=2C like stdout) exposes an output iterator.
You can= > > copy to it.


There are many more ex= > >amples.
Of course=2C besides quick sort=2C there is a stable sort= > >.
There is finding sequences.
There is binary_search. >div>
There is upper_bound/lower_bound/equal_range which are like binary= > >_search.
There is unique.
There is partition.
>>Many many more=2C "built in" to the library.
That work with mult= > >iple "built in" containers=2C and can work with custom containers as well.<= > >/div>


I strongly recommend you read up on= > > this stuff.
It is really quite illimuninating. Good stuff.
= > >
Teaches us how to better factor our code.
And to strive for = > >better factoring=2C when we find people have invented/discovered such thing= > >s.


"Iterators" already do occur in = > >Modula-3 libraries.


All I want is a= > > sorted vector that "closely knows" when it is being written vs. read=2C an= > >d when there are a series of writes with no intervening reads=2C it can amo= > >rtize down the cost of maintaining the ordering.

<= > >br>
I hand coded something.
It took me a while to get i= > >t to work due to stupid small details.
The result is significantl= > >y worse than I would have gotten in C++.
Bigger code. Slower code= > >. More copies. More heap allocations.
I can eliminate one of the = > >allocations by merging the next step.
But in C++ I naturally woul= > >dn't have had it anyway.
Not great.


= > >
 =3B- Jay


>div>>=3B To: jay.krell at cornell.edu
>=3B CC: mika at async.caltech.edu= > >=3B m3devel at elegosoft.com
>=3B Subject: Re: [M3devel] STL algorithms? = > >sort/unique?
>=3B Date: Sat=2C 29 Sep 2012 11:29:48 -0700
>=3B Fr= > >om: mika at async.caltech.edu
>=3B
>=3B
>=3B Well that depend= > >s on how you maintain the vector=2C no?
>=3B
>=3B SortedTable us= > >es "treaps" which are supposed to be good data structures.
>=3B Too ne= > >w to have made it into Knuth=2C last I checked. The amortized cost
>= > >=3B of your operations shouldn't be much worse than with your method=2C wit= > >h
>=3B the additional benefit that the sorted order is maintained dyna= > >mically.
>=3B
>=3B The separation of algorithms from containers = > >sounds a bit like a bug.
>=3B You have to be careful so you don't shoo= > >t yourself in the foot there!
>=3B (Sorting a list using an algorithm = > >that randomly accesses elements=2C
>=3B say...)
>=3B
>=3B T= > >he Modula-3 approach is that you figure out what you want to do=2C pick
= > >>=3B the ADT you want that provides the minimal set of operations=2C impo= > >rt
>=3B that interface=2C then instantiate a more carefully chosen imp= > >lementation
>=3B of the ADT. The language itself obviously can be coa= > >xed into supporting the
>=3B algorithm/data structure separation but n= > >o one uses it that way as
>=3B far as I know. (Modula-3 generics are = > >not that well explored=2C actually.
>=3B I suspect there are many thin= > >gs you can do with them that no one has
>=3B tried.)
>=3B
>= > >=3B Mika
>=3B
>=3B Jay K writes:
>=3B >=3B--_7877d7e= > >8-cb4a-4989-bdcd-d406e5b1f51f_
>=3B >=3BContent-Type: text/plain=3B = > >charset=3D"iso-8859-1"
>=3B >=3BContent-Transfer-Encoding: quoted-pr= > >intable
>=3B >=3B
>=3B >=3BThe following is very efficient: >r>>=3B >=3B
>=3B >=3Brun through a bunch of records=3D2C picking= > > out one number from some of thema=3D
>=3B >=3Bppend those numbers t= > >o a growing vectorsort the vectorunique the vector
>=3B >=3B
>= > >=3B >=3Bsequence allows for random access..but only via a function...or m= > >aybe an it=3D
>=3B >=3Berator
>=3B >=3B
>=3B >=3BSTL h= > >as this wonderful separation of algorithms from containers=3D2C via iter=3D= > >
>=3B >=3Bators.I suspect very few other libraries do.And it could b= > >e that most langu=3D
>=3B >=3Bages don't support it.It doesn't appea= > >r I can easily sort a sequence=3D2C unl=3D
>=3B >=3Bess I copy the d= > >ata out into an array -- gross inefficiency.
>=3B >=3B
>=3B >= > >=3BI've hacked something very manual together..and it is taking forever to = > >get=3D
>=3B >=3B it to work. It turns out I can reasonably well bou= > >nd the size of the data=3D
>=3B >=3B=3D2C so I'm using an open array= > >...and I have to keep track of my position in=3D
>=3B >=3Bstead of u= > >sing addhi/push_back.Not happy.At some point I might give up and =3D
>= > >=3B >=3Bwrite the backend in C++..at which point I might as well write a = > >C++ fronte=3D
>=3B >=3Bnd anywa.
>=3B >=3B
>=3B >=3B >r>>=3B >=3BI absolutely do not want a sorted table and unique upon inse= > >rt.That is much=3D
>=3B >=3B less efficient.What I'm describing uses= > > temporarily larger working set but=3D
>=3B >=3B vastly less CPU.An = > >array that gets sorted/uniqued occasionally=3D2C like jus=3D
>=3B >= > >=3Bt once.And not ongoing maintainence for every single add.
>=3B >= > >=3B
>=3B >=3B
>=3B >=3B - Jay
>=3B >=3B
>=3B >= > >=3B
>=3B >=3B>=3B To: jay.krell at cornell.edu
>=3B >=3B>=3B= > > CC: m3devel at elegosoft.com
>=3B >=3B>=3B Subject: Re: [M3devel] ST= > >L algorithms? sort/unique?
>=3B >=3B>=3B Date: Fri=3D2C 28 Sep 201= > >2 01:04:48 -0700
>=3B >=3B>=3B From: mika at async.caltech.edu
>= > >=3B >=3B>=3B=3D20
>=3B >=3B>=3B=3D20
>=3B >=3B>=3B BT= > >W I had the same experience when I first started using Modula-3.
>=3B = > >>=3B>=3B It was painful to jump through all its hoops=3D2C coming from = > >C=3D2C where yo=3D
>=3B >=3Bu
>=3B >=3B>=3B can do whatever= > > you want to whatever bits happen to be sloshing around
>=3B >=3B>= > >=3B your machine. C++ from what I have seen mainly lets you do that to
= > >>=3B >=3B>=3B more bits in fewer lines of code.
>=3B >=3B>= > >=3B=3D20
>=3B >=3B>=3B But after a while I really came to apprecia= > >te the value of things like th=3D
>=3B >=3Be
>=3B >=3B>=3B = > >language's telling me I'm using the wrong data structure instead of
>= > >=3B >=3B>=3B just letting me use the same "nice=3D2C terse=3D2C efficie= > >nt" syntax to write
>=3B >=3B>=3B a crappy program :-)
>=3B &= > >gt=3B>=3B=3D20
>=3B >=3B>=3B mika writes:
>=3B >=3B>=3B= > > >=3BYou're using the wrong (abstract) data structure if you want sort an= > >d un=3D
>=3B >=3Bique.
>=3B >=3B>=3B >=3B
>=3B >= > >=3B>=3B >=3BA "sequence" is meant to be accessed sequentially...
>= > >=3B >=3B>=3B >=3B
>=3B >=3B>=3B >=3BNot knowing precisely = > >what you're doing it sounds like you might want a
>=3B >=3B>=3B &g= > >t=3BSortedTable... you can get unique on insert and access it in increasing= > >
>=3B >=3B>=3B >=3Bor decreasing order.
>=3B >=3B>=3B &= > >gt=3B
>=3B >=3B>=3B >=3B Mika
>=3B >=3B>=3B >=3B >r>>=3B >=3B>=3B >=3BJay K writes:
>=3B >=3B>=3B >=3B>= > >=3B--_d2a02ece-d492-410e-88fb-fb53737d7219_
>=3B >=3B>=3B >=3B&g= > >t=3BContent-Type: text/plain=3D3B charset=3D3D"iso-8859-1"
>=3B >=3B= > >>=3B >=3B>=3BContent-Transfer-Encoding: quoted-printable
>=3B &g= > >t=3B>=3B >=3B>=3B
>=3B >=3B>=3B >=3B>=3B I have an In= > >tSeq.T with a bunch of integers. =3D3D20
>=3B >=3B>=3B >=3B>= > >=3B What is a good terse efficient idiom for sort and unique? =3D3D20<= > >br>>=3B >=3B>=3B >=3B>=3B
>=3B >=3B>=3B >=3B>=3B = > >In C++ I would say: vector<=3Bint>=3B a=3D3D3B a.push_bac= > >k(..=3D
>=3B >=3B.)=3D3D3B =3D3D
>=3B >=3B>=3B >=3B>=3B= > > a.push_back(...)=3D3D3B std::sort(a.begin()=3D3D2C a.end())= > >=3D
>=3B >=3B=3D3D3B =3D3D
>=3B >=3B>=3B >=3B>=3B= > > a.resize(std::unique(a.begin()=3D3D2C a.end()) - a.begin())=3D3D3B = > >=3D
>=3B >=3Bfor (aut=3D3D
>=3B >=3B>=3B >=3B>=3Bo i = > >=3D3D3D a.begin()=3D3D3B i !=3D3D3D a.end()=3D3D3B ++i) {
>=3B >= > >=3B>=3B >=3B>=3B do stuff with *i }=3D3D20
>=3B >=3B&g= > >t=3B >=3B>=3B Nice=3D3D2C terse=3D3D2C efficient. In Modula-3= > >? =3D3D20
>=3B >=3B>=3B >=3B>=3B
>=3B >=3B>=3B >= > >=3B>=3BI know that unique is one of the easiest algorithms to manually wr= > >ite i=3D
>=3B >=3Bnlin=3D3D
>=3B >=3B>=3B >=3B>=3Be=3D3= > >D2Cbut I shouldn't have to.
>=3B >=3B>=3B >=3B>=3B
>=3B &= > >gt=3B>=3B >=3B>=3B(I'm really trying to stay in Modula-3 here=3D3D2C = > >but it is definitely a=3D
>=3B >=3B strug=3D3D
>=3B >=3B>= > >=3B >=3B>=3Bgle. :( )
>=3B >=3B>=3B >=3B>=3B
>=3B >= > >=3B>=3B >=3B>=3BThank you=3D3D2C - Jay
>=3B >=3B>=3B >=3B&= > >gt=3B
>=3B >=3B>=3B >=3B>=3B =3D3D
>=3B >=3B= > >>=3B >=3B>=3B
>=3B >=3B>=3B >=3B>=3B--_d2a02ece-d492-410= > >e-88fb-fb53737d7219_
>=3B >=3B>=3B >=3B>=3BContent-Type: text/= > >html=3D3B charset=3D3D"iso-8859-1"
>=3B >=3B>=3B >=3B>=3BConte= > >nt-Transfer-Encoding: quoted-printable
>=3B >=3B>=3B >=3B>=3B<= > >br>>=3B >=3B>=3B >=3B>=3B<=3Bhtml>=3B
>=3B >=3B>=3B = > >>=3B>=3B<=3Bhead>=3B
>=3B >=3B>=3B >=3B>=3B<=3Bstyle= > >>=3B<=3B!--
>=3B >=3B>=3B >=3B>=3B.hmmessage P
>=3B &= > >gt=3B>=3B >=3B>=3B{
>=3B >=3B>=3B >=3B>=3Bmargin:0px=3D3= > >D3B
>=3B >=3B>=3B >=3B>=3Bpadding:0px
>=3B >=3B>=3B &= > >gt=3B>=3B}
>=3B >=3B>=3B >=3B>=3Bbody.hmmessage
>=3B &g= > >t=3B>=3B >=3B>=3B{
>=3B >=3B>=3B >=3B>=3Bfont-size: 12pt= > >=3D3D3B
>=3B >=3B>=3B >=3B>=3Bfont-family:Calibri
>=3B &g= > >t=3B>=3B >=3B>=3B}
>=3B >=3B>=3B >=3B>=3B-->=3B<=3B/= > >style>=3B<=3B/head>=3B
>=3B >=3B>=3B >=3B>=3B<=3Bbody = > >class=3D3D3D'hmmessage'>=3B<=3Bdiv dir=3D3D3D'ltr'>=3B&=3Bnbsp=3D3= > >D3B &=3Bnbsp=3D3D3B&=3Bnb=3D
>=3B >=3Bsp=3D3D3BI have =3D3D >>>=3B >=3B>=3B >=3B>=3Ban IntSeq.T with a bunch of integers.&= > >=3Bnbsp=3D3D3B &=3Bnbsp=3D3D3B&=3Bnbsp=3D3D3B<=3Bbr=3D
>=3B &g= > >t=3B>=3B<=3Bdiv>=3B<=3Bspa=3D3D
>=3B >=3B>=3B >=3B>=3B= > >n style=3D3D3D"font-size: 12pt=3D3D3B ">=3B&=3Bnbsp=3D3D3B &=3Bnbsp= > >=3D3D3B<=3B/span>=3B<=3Bspan s=3D
>=3B >=3Btyle=3D3D3D"font=3D= > >3D
>=3B >=3B>=3B >=3B>=3B-size: 12pt=3D3D3B ">=3B&=3Bnbsp= > >=3D3D3B<=3B/span>=3BWhat is a good terse efficient idio=3D
>=3B &g= > >t=3Bm for so=3D3D
>=3B >=3B>=3B >=3B>=3Brt and unique?<=3Bsp= > >an style=3D3D3D"font-size: 12pt=3D3D3B ">=3B&=3Bnbsp=3D3D3B &=3Bnbs= > >p=3D
>=3B >=3B=3D3D3B<=3B/span>=3B<=3B=3D3D
>=3B >=3B&g= > >t=3B >=3B>=3Bspan style=3D3D3D"font-size: 12pt=3D3D3B ">=3B&=3Bnbs= > >p=3D3D3B<=3B/span>=3B<=3B/div>=3B<=3Bdiv>=3B<=3Bbr>=3B=3D >r>>=3B >=3B<=3B/div>=3B<=3Bdiv=3D3D
>=3B >=3B>=3B >=3B= > >>=3B>=3B<=3Bbr>=3B<=3B/div>=3B<=3Bdiv>=3B&=3Bnbsp=3D3D3B= > > &=3Bnbsp=3D3D3B In C++ I would say:<=3Bspan style=3D3D=3D
>=3B &= > >gt=3B3D"font-si=3D3D
>=3B >=3B>=3B >=3B>=3Bze: 12pt=3D3D3B "&g= > >t=3B&=3Bnbsp=3D3D3B &=3Bnbsp=3D3D3B<=3B/span>=3B<=3Bspan style= > >=3D3D3D"font-size:=3D
>=3B >=3B 12pt=3D3D3B ">=3B&=3B=3D3D
&= > >gt=3B >=3B>=3B >=3B>=3Bnbsp=3D3D3B<=3B/span>=3B<=3B/div>=3B= > ><=3Bdiv>=3B<=3Bspan style=3D3D3D"font-size: 12pt=3D3D3B ">=3B&= > >=3Bnbs=3D
>=3B >=3Bp=3D3D3B &=3Bnbsp=3D3D
>=3B >=3B>=3B = > >>=3B>=3B=3D3D3B<=3B/span>=3B<=3Bspan style=3D3D3D"font-size: 12pt= > >=3D3D3B ">=3B&=3Bnbsp=3D3D3B<=3B/span>=3Bve=3D
>=3B >=3Bcto= > >r&=3Blt=3D3D3Bin=3D3D
>=3B >=3B>=3B >=3B>=3Bt&=3Bgt=3D3D= > >3B a=3D3D3B<=3Bspan style=3D3D3D"font-size: 12pt=3D3D3B ">=3B&=3Bnbs= > >p=3D3D3B &=3Bnbs=3D
>=3B >=3Bp=3D3D3B<=3B/span>=3B<=3Bsp=3D= > >3D
>=3B >=3B>=3B >=3B>=3Ban style=3D3D3D"font-size: 12pt=3D3D3= > >B ">=3B&=3Bnbsp=3D3D3B<=3B/span>=3B<=3B/div>=3B<=3Bdiv>=3B= > ><=3Bspan =3D
>=3B >=3Bstyle=3D3D3D"f=3D3D
>=3B >=3B>=3B &= > >gt=3B>=3Bont-size: 12pt=3D3D3B ">=3B&=3Bnbsp=3D3D3B &=3Bnbsp=3D3D= > >3B<=3B/span>=3B<=3Bspan style=3D3D3D"font=3D
>=3B >=3B-size: 1= > >2pt=3D3D
>=3B >=3B>=3B >=3B>=3B=3D3D3B ">=3B&=3Bnbsp=3D3D= > >3B<=3B/span>=3Ba.push_back(...)=3D3D3B<=3Bspan style=3D3D3D"font-siz= > >=3D
>=3B >=3Be: 12pt=3D3D3B "=3D3D
>=3B >=3B>=3B >=3B>= > >=3B>=3B&=3Bnbsp=3D3D3B &=3Bnbsp=3D3D3B<=3B/span>=3B<=3Bspan s= > >tyle=3D3D3D"font-size: 12pt=3D3D3B ">=3B&=3Bn=3D
>=3B >=3Bbsp= > >=3D3D3B<=3B/span=3D3D
>=3B >=3B>=3B >=3B>=3B>=3B<=3B/div= > >>=3B<=3Bdiv>=3B<=3Bdiv>=3B<=3Bspan style=3D3D3D"font-size: 12pt= > >=3D3D3B ">=3B&=3Bnbsp=3D3D3B &=3Bnb=3D
>=3B >=3Bsp=3D3D3B<= > >=3B/spa=3D3D
>=3B >=3B>=3B >=3B>=3Bn>=3B<=3Bspan style=3D3= > >D3D"font-size: 12pt=3D3D3B ">=3B&=3Bnbsp=3D3D3B<=3B/span>=3Ba.push= > >_back(=3D
>=3B >=3B...)=3D3D3B<=3Bsp=3D3D
>=3B >=3B>=3B &= > >gt=3B>=3Ban style=3D3D3D"font-size: 12pt=3D3D3B ">=3B&=3Bnbsp=3D3D3B= > > &=3Bnbsp=3D3D3B<=3B/span>=3B<=3Bspan =3D
>=3B >=3Bstyle=3D= > >3D3D"fon=3D3D
>=3B >=3B>=3B >=3B>=3Bt-size: 12pt=3D3D3B ">= > >=3B&=3Bnbsp=3D3D3B<=3B/span>=3B<=3B/div>=3B<=3Bdiv>=3B<=3B= > >span style=3D3D3D"font-s=3D
>=3B >=3Bize: 12pt=3D3D
>=3B >=3B= > >>=3B >=3B>=3B=3D3D3B ">=3B&=3Bnbsp=3D3D3B &=3Bnbsp=3D3D3B<= > >=3B/span>=3B<=3Bspan style=3D3D3D"font-size: 12pt=3D3D=3D
>=3B >= > >=3B3B ">=3B&=3Bnbsp=3D3D3B<=3B=3D3D
>=3B >=3B>=3B >=3B>= > >=3B/span>=3Bstd::sort(a.begin()=3D3D2C a.end())=3D3D3B<=3Bspan style=3D= > >3D3D"font-size:=3D
>=3B >=3B 12pt=3D3D3B "=3D3D
>=3B >=3B>= > >=3B >=3B>=3B>=3B&=3Bnbsp=3D3D3B &=3Bnbsp=3D3D3B<=3B/span>= > >=3B<=3Bspan style=3D3D3D"font-size: 12pt=3D3D3B ">=3B&=3Bn=3D
>= > >=3B >=3Bbsp=3D3D3B<=3B/span=3D3D
>=3B >=3B>=3B >=3B>=3B>= > >=3B<=3B/div>=3B<=3Bdiv>=3B<=3Bspan style=3D3D3D"font-size: 12pt= > >=3D3D3B ">=3B&=3Bnbsp=3D3D3B &=3Bnbsp=3D3D=3D
>=3B >=3B3B<= > >=3B/span>=3B<=3Bsp=3D3D
>=3B >=3B>=3B >=3B>=3Ban style=3D3= > >D3D"font-size: 12pt=3D3D3B ">=3B&=3Bnbsp=3D3D3B<=3B/span>=3Ba.resi= > >ze(std::uni=3D
>=3B >=3Bque(a.begi=3D3D
>=3B >=3B>=3B >= > >=3B>=3Bn()=3D3D2C a.end()) - a.begin())=3D3D3B<=3Bspan style=3D3D3D"fon= > >t-size: 12pt=3D3D3=3D
>=3B >=3BB ">=3B&=3Bnbsp=3D3D3B=3D3D
&= > >gt=3B >=3B>=3B >=3B>=3B &=3Bnbsp=3D3D3B<=3B/span>=3B<=3Bsp= > >an style=3D3D3D"font-size: 12pt=3D3D3B ">=3B&=3Bnbsp=3D3D3B<=3B/s=3D= > >
>=3B >=3Bpan>=3B<=3B/div>=3B<=3Bd=3D3D
>=3B >=3B>= > >=3B >=3B>=3Biv>=3B<=3Bspan style=3D3D3D"font-size: 12pt=3D3D3B ">= > >=3B&=3Bnbsp=3D3D3B &=3Bnbsp=3D3D3B for (a=3D
>=3B >=3Buto i = > >=3D3D3D a.=3D3D
>=3B >=3B>=3B >=3B>=3Bbegin()=3D3D3B i !=3D3D3= > >D a.end()=3D3D3B ++i)<=3B/span>=3B<=3B/div>=3B<=3Bdiv>=3B<=3B= > >span style=3D3D=3D
>=3B >=3B3D"font-size=3D3D
>=3B >=3B>=3B= > > >=3B>=3B: 12pt=3D3D3B ">=3B&=3Bnbsp=3D3D3B &=3Bnbsp=3D3D3B {&l= > >t=3Bbr>=3B&=3Bnbsp=3D3D3B &=3Bnbsp=3D3D3B &=3Bnbsp=3D3D=3D
&g= > >t=3B >=3B3B do stuff with=3D3D
>=3B >=3B>=3B >=3B>=3B *i<= > >=3B/span>=3B<=3B/div>=3B<=3Bdiv>=3B<=3Bspan style=3D3D3D"font-s= > >ize: 12pt=3D3D3B ">=3B&=3Bnbsp=3D3D3B=3D
>=3B >=3B &=3Bnbsp= > >=3D3D3B =3D3D
>=3B >=3B>=3B >=3B>=3B}<=3B/span>=3B<=3B/d= > >iv>=3B<=3Bdiv>=3B&=3Bnbsp=3D3D3B<=3B/div>=3B<=3Bdiv>=3B<= > >=3Bbr>=3B<=3B/div>=3B<=3Bdiv>=3B<=3Bspan style=3D3D3D=3D
>= > >=3B >=3B"font-si=3D3D
>=3B >=3B>=3B >=3B>=3Bze: 12pt=3D3D3B = > >">=3B&=3Bnbsp=3D3D3B &=3Bnbsp=3D3D3B<=3B/span>=3B<=3Bspan sty= > >le=3D3D3D"font-size:=3D
>=3B >=3B 12pt=3D3D3B ">=3B&=3B=3D3D >>>=3B >=3B>=3B >=3B>=3Bnbsp=3D3D3B<=3B/span>=3BNice=3D3D2C te= > >rse=3D3D2C efficient.<=3Bspan style=3D3D3D"font-si=3D
>=3B >=3Bze:= > > 12pt=3D3D3B =3D3D
>=3B >=3B>=3B >=3B>=3B">=3B&=3Bnbsp=3D= > >3D3B &=3Bnbsp=3D3D3B<=3B/span>=3B<=3Bspan style=3D3D3D"font-size: = > >12pt=3D3D3B ">=3B&=3B=3D
>=3B >=3Bnbsp=3D3D3B<=3B/spa=3D3D >>>=3B >=3B>=3B >=3B>=3Bn>=3B<=3B/div>=3B<=3Bdiv>=3B<= > >=3Bspan style=3D3D3D"font-size: 12pt=3D3D3B ">=3B&=3Bnbsp=3D3D3B &= > >=3Bnbsp=3D
>=3B >=3B=3D3D3B<=3B/span>=3B<=3Bs=3D3D
>=3B &= > >gt=3B>=3B >=3B>=3Bpan style=3D3D3D"font-size: 12pt=3D3D3B ">=3B&= > >=3Bnbsp=3D3D3B<=3B/span>=3BIn Modula-3?<=3Bspa=3D
>=3B >=3Bn s= > >tyle=3D3D3D=3D3D
>=3B >=3B>=3B >=3B>=3B"font-size: 12pt=3D3D3B= > > ">=3B&=3Bnbsp=3D3D3B &=3Bnbsp=3D3D3B<=3B/span>=3B<=3Bspan st= > >yle=3D3D3D"fo=3D
>=3B >=3Bnt-size: 12p=3D3D
>=3B >=3B>=3B &= > >gt=3B>=3Bt=3D3D3B ">=3B&=3Bnbsp=3D3D3B<=3B/span>=3B<=3B/div>= > >=3B<=3Bdiv>=3B<=3Bbr>=3B<=3B/div>=3B<=3Bdiv>=3B<=3Bbr>= > >=3B<=3B/div>=3B<=3Bdiv>=3BI kn=3D
>=3B >=3Bow that =3D3D
= > >>=3B >=3B>=3B >=3B>=3Bunique is one of the easiest algorithms to = > >manually write inline=3D3D2C<=3B/=3D
>=3B >=3Bdiv>=3B<=3Bd=3D3= > >D
>=3B >=3B>=3B >=3B>=3Biv>=3Bbut I shouldn't have to.<=3B= > >/div>=3B<=3Bdiv>=3B<=3Bbr>=3B<=3B/div>=3B<=3Bdiv>=3B<= > >=3Bbr>=3B<=3B/div>=3B<=3Bdiv>=3B(I'=3D
>=3B >=3Bm re=3D3D<= > >br>>=3B >=3B>=3B >=3B>=3Bally trying to stay in Modula-3 here=3D3= > >D2C but it is definitely a strugg=3D
>=3B >=3Ble. :(=3D3D
>=3B = > >>=3B>=3B >=3B>=3B )<=3B/div>=3B<=3Bdiv>=3B<=3Bbr>=3B<= > >=3B/div>=3B<=3Bdiv>=3B<=3Bbr>=3B<=3B/div>=3B<=3Bdiv>=3BTh= > >ank you=3D3D2C<=3B/div>=3B<=3Bdiv>=3B&=3Bnb=3D
>=3B >=3Bs= > >p=3D3D3B-=3D3D
>=3B >=3B>=3B >=3B>=3B Jay<=3B/div>=3B<= > >=3Bbr>=3B<=3Bbr>=3B<=3B/div>=3B <=3B/div>=3B<=3B= > >/body>=3B
>=3B >=3B>=3B >=3B>=3B<=3B/html>=3B=3D3D
&g= > >t=3B >=3B>=3B >=3B>=3B
>=3B >=3B>=3B >=3B>=3B--_d2a02e= > >ce-d492-410e-88fb-fb53737d7219_--
>=3B >=3B =3D
>=3B= > > >=3B
>=3B >=3B--_7877d7e8-cb4a-4989-bdcd-d406e5b1f51f_
>=3B = > >>=3BContent-Type: text/html=3B charset=3D"iso-8859-1"
>=3B >=3BCon= > >tent-Transfer-Encoding: quoted-printable
>=3B >=3B
>=3B >=3B&= > >lt=3Bhtml>=3B
>=3B >=3B<=3Bhead>=3B
>=3B >=3B<=3Bstyl= > >e>=3B<=3B!--
>=3B >=3B.hmmessage P
>=3B >=3B{
>=3B &= > >gt=3Bmargin:0px=3D3B
>=3B >=3Bpadding:0px
>=3B >=3B}
>= > >=3B >=3Bbody.hmmessage
>=3B >=3B{
>=3B >=3Bfont-size: 12pt= > >=3D3B
>=3B >=3Bfont-family:Calibri
>=3B >=3B}
>=3B >= > >=3B-->=3B<=3B/style>=3B<=3B/head>=3B
>=3B >=3B<=3Bbody c= > >lass=3D3D'hmmessage'>=3B<=3Bdiv dir=3D3D'ltr'>=3B<=3Bdiv>=3B<= > >=3Bspan style=3D3D"font-size: 1=3D
>=3B >=3B2pt=3D3B ">=3BThe foll= > >owing is very efficient:<=3B/span>=3B<=3B/div>=3B<=3Bdiv>=3B<= > >=3Bbr>=3B<=3B/div>=3B<=3Bdiv>=3B<=3B=3D
>=3B >=3Bbr>= > >=3B<=3B/div>=3B<=3Bdiv>=3Brun through a bunch of records=3D2C picki= > >ng out one number from=3D
>=3B >=3B some of them<=3B/div>=3B<= > >=3Bdiv>=3Bappend those numbers to a growing vector<=3B/div>=3B<=3Bd= > >iv>=3B=3D
>=3B >=3Bsort the vector<=3B/div>=3B<=3Bdiv>=3Bu= > >nique the vector<=3B/div>=3B<=3Bdiv>=3B<=3Bbr>=3B<=3B/div>= > >=3B<=3Bdiv>=3B<=3Bbr>=3B<=3B/=3D
>=3B >=3Bdiv>=3B<=3Bd= > >iv>=3Bsequence allows for random access..but only via a function...<=3B= > >/div=3D
>=3B >=3B>=3B<=3Bdiv>=3Bor maybe an iterator<=3B/div= > >>=3B<=3Bdiv>=3B<=3Bbr>=3B<=3B/div>=3B<=3Bdiv>=3B<=3Bbr&= > >gt=3B<=3B/div>=3B<=3Bdiv>=3BSTL has =3D
>=3B >=3Bthis wonder= > >ful separation of algorithms from containers=3D2C via iterators.<=3B/=3D<= > >br>>=3B >=3Bdiv>=3B<=3Bdiv>=3BI suspect very few other libraries = > >do.<=3B/div>=3B<=3Bdiv>=3BAnd it could be t=3D
>=3B >=3Bhat = > >most languages don't support it.<=3B/div>=3B<=3Bdiv>=3BIt doesn't a= > >ppear I can easi=3D
>=3B >=3Bly sort a sequence=3D2C unless I copy t= > >he data out into an array -- gross ine=3D
>=3B >=3Bfficiency.<=3B/= > >div>=3B<=3Bdiv>=3B<=3Bbr>=3B<=3B/div>=3B<=3Bdiv>=3B<=3B= > >br>=3B<=3B/div>=3B<=3Bdiv>=3BI've hacked something ve=3D
>= > >=3B >=3Bry manual together..and it is taking forever to get it to work.&l= > >t=3B/div>=3B<=3Bdiv>=3B&=3B=3D
>=3B >=3Bnbsp=3D3B It turns = > >out I can reasonably well bound the size of the data=3D2C so=3D
>=3B &= > >gt=3B I'm using an open array...and I have to keep track of my position ins= > >tead =3D
>=3B >=3Bof using addhi/push_back.<=3B/div>=3B<=3Bdiv= > >>=3BNot happy.<=3B/div>=3B<=3Bdiv>=3BAt some point I mi=3D
>= > >=3B >=3Bght give up and write the backend in C++..at which point I might = > >as well wr=3D
>=3B >=3Bite a C++ frontend anywa.<=3B/div>=3B<= > >=3Bdiv>=3B<=3Bbr>=3B<=3B/div>=3B<=3Bdiv>=3B<=3Bbr>=3B<= > >=3B/div>=3B<=3Bdiv>=3B<=3Bbr>=3B<=3B/div=3D
>=3B >=3B>= > >=3B<=3Bdiv>=3BI absolutely do not want a sorted table and unique upon i= > >nsert.<=3B/div>=3B=3D
>=3B >=3B<=3Bdiv>=3BThat is much less = > >efficient.<=3B/div>=3B<=3Bdiv>=3BWhat I'm describing uses tempor=3D= > >
>=3B >=3Barily larger working set but vastly less CPU.<=3B/div>= > >=3B<=3Bdiv>=3BAn array that gets =3D
>=3B >=3Bsorted/uniqued occ= > >asionally=3D2C like just once.<=3B/div>=3B<=3Bdiv>=3BAnd not ongoin= > >g ma=3D
>=3B >=3Bintainence for every single add.<=3B/div>=3B<= > >=3Bdiv>=3B<=3Bbr>=3B<=3B/div>=3B<=3Bdiv>=3B<=3Bbr>=3B<= > >=3B/div>=3B<=3Bdiv>=3B<=3Bb=3D
>=3B >=3Br>=3B<=3B/div>= > >=3B<=3Bdiv>=3B&=3Bnbsp=3D3B- Jay<=3B/div>=3B<=3Bdiv>=3B<= > >=3Bbr>=3B<=3Bbr>=3B<=3Bbr>=3B<=3Bdiv>=3B<=3Bdiv id=3D3D"Sky= > >DrivePl=3D
>=3B >=3Baceholder">=3B<=3B/div>=3B&=3Bgt=3D3B T= > >o: jay.krell at cornell.edu<=3Bbr>=3B&=3Bgt=3D3B CC: m3devel at ele=3D
= > >>=3B >=3Bgosoft.com<=3Bbr>=3B&=3Bgt=3D3B Subject: Re: [M3devel] = > >STL algorithms? sort/unique?<=3Bbr=3D
>=3B >=3B>=3B&=3Bgt=3D3= > >B Date: Fri=3D2C 28 Sep 2012 01:04:48 -0700<=3Bbr>=3B&=3Bgt=3D3B Fro= > >m: mika at async.=3D
>=3B >=3Bcaltech.edu<=3Bbr>=3B&=3Bgt=3D3B &= > >lt=3Bbr>=3B&=3Bgt=3D3B <=3Bbr>=3B&=3Bgt=3D3B BTW I had the same= > > experience w=3D
>=3B >=3Bhen I first started using Modula-3.<=3Bb= > >r>=3B&=3Bgt=3D3B It was painful to jump throug=3D
>=3B >=3Bh al= > >l its hoops=3D2C coming from C=3D2C where you<=3Bbr>=3B&=3Bgt=3D3B c= > >an do whatever you=3D
>=3B >=3B want to whatever bits happen to be s= > >loshing around<=3Bbr>=3B&=3Bgt=3D3B your machine.=3D
>=3B >= > >=3B C++ from what I have seen mainly lets you do that to<=3Bbr>=3B&= > >=3Bgt=3D3B more bits =3D
>=3B >=3Bin fewer lines of code.<=3Bbr>= > >=3B&=3Bgt=3D3B <=3Bbr>=3B&=3Bgt=3D3B But after a while I really c= > >am=3D
>=3B >=3Be to appreciate the value of things like the<=3Bbr&= > >gt=3B&=3Bgt=3D3B language's telling m=3D
>=3B >=3Be I'm using the= > > wrong data structure instead of<=3Bbr>=3B&=3Bgt=3D3B just letting m= > >e u=3D
>=3B >=3Bse the same "nice=3D2C terse=3D2C efficient" syntax = > >to write<=3Bbr>=3B&=3Bgt=3D3B a crappy=3D
>=3B >=3B program := > >-)<=3Bbr>=3B&=3Bgt=3D3B <=3Bbr>=3B&=3Bgt=3D3B mika writes:<= > >=3Bbr>=3B&=3Bgt=3D3B &=3Bgt=3D3BYou're using=3D
>=3B >=3B th= > >e wrong (abstract) data structure if you want sort and unique.<=3Bbr>= > >=3B&=3Bgt=3D3B=3D
>=3B >=3B &=3Bgt=3D3B<=3Bbr>=3B&=3Bgt= > >=3D3B &=3Bgt=3D3BA "sequence" is meant to be accessed sequentially..=3D<= > >br>>=3B >=3B.<=3Bbr>=3B&=3Bgt=3D3B &=3Bgt=3D3B<=3Bbr>=3B&= > >amp=3Bgt=3D3B &=3Bgt=3D3BNot knowing precisely what you're doing =3D
= > >>=3B >=3Bit sounds like you might want a<=3Bbr>=3B&=3Bgt=3D3B &a= > >mp=3Bgt=3D3BSortedTable... you can get =3D
>=3B