tag:blogger.com,1999:blog-33162310334249036592024-03-17T23:02:49.274-04:00EcstasyLangxtclang (Ecstasy)http://www.blogger.com/profile/10099977807321312612noreply@blogger.comBlogger28125tag:blogger.com,1999:blog-3316231033424903659.post-51277030165916341082023-01-25T15:00:00.002-05:002023-01-25T15:42:20.303-05:00Language Guide<p>The <a href="https://github.com/xtclang/xvm/wiki/lang-intro" target="_blank">Ecstasy Language Guide</a> is slowly taking shape. You may recognize some of the topics and material from this blog. Comments, suggestions, requests, and other feedback are welcome.</p><p>Documentation for Ecstasy is located on the <a href="https://github.com/xtclang/xvm/wiki" target="_blank">Github xtclang wiki</a>.</p>Links to XDK downloads are located on the <a href="https://xtclang.org/xdk-latest.html" target="_blank">xtclang.org website</a>.<br />xtclang (Ecstasy)http://www.blogger.com/profile/10099977807321312612noreply@blogger.com0tag:blogger.com,1999:blog-3316231033424903659.post-84951567241176728092022-11-10T09:43:00.002-05:002022-11-10T09:43:37.285-05:00Presenting Ecstasy at the NY Java SIG tonight, 10 November 2022<p>Cameron Purdy will be talking about the future of computing using the Ecstasy programming language.</p><p><a href="https://www.meetup.com/cloud-native-new-york/events/289546041/">Ecstasy at the NY Java SIG (meetup link)</a> <a href="https://www.eventbrite.com/e/ecstasy-a-cloud-native-general-purpose-programming-language-tickets-455306663487">(EventBrite link)</a></p><p> <br /></p>xtclang (Ecstasy)http://www.blogger.com/profile/10099977807321312612noreply@blogger.com4tag:blogger.com,1999:blog-3316231033424903659.post-26377174673234354332021-10-05T14:20:00.001-04:002021-10-05T14:22:29.725-04:00The Ecstasy discussion forum<p>Fairly recently, we've switched over to primarily <a href="https://github.com/xtclang/xvm/discussions" target="_blank">using the GitHub discussion forums for public discussions of Ecstasy work</a>. We'll be de-emphasizing our Slack channel.<br /></p><p>The forums are a much easier place to manage and read discussion threads than moderated comments on a blog, so we'll be relying on it more and more for conversations around articles that are posted here, as well as for group design work, long range planning, etc.</p><p>If you have ideas for new blog posts, articles, design ideas, and so on, then please post a message on the forums. Thanks!<br /></p>xtclang (Ecstasy)http://www.blogger.com/profile/10099977807321312612noreply@blogger.com0tag:blogger.com,1999:blog-3316231033424903659.post-90671571073952939612021-09-05T18:00:00.001-04:002021-09-05T18:09:31.481-04:00How to use the Ecstasy Debugger<p>Until recently, debugging Ecstasy code was an exercise in frustration, because there was no debugger. One could step through the interpreter's operations in a Java debugger, which was not for the faint of heart. The alternative, not surprisingly, was to sprinkle one's code with print statements, such as:</p><pre style="background-color: white; color: #080808; font-family: "JetBrains Mono", monospace; font-size: 8.3pt; margin-left: 40px; text-align: left;"><span style="color: maroon;">@Inject </span>Console console;<br />console.println(<span style="color: #067d17;">$"The value of i={i}"</span>);<br /></pre><p>Need to see another variable? Change the code, recompile, and run again. Repeat until everything works.</p><p>This is, of course, how all programmers used to debug code, back between the invention of the printing press and the invention of the interactive debugger.</p><p>So it should come as no surprise that Ecstasy now has an interactive debugger. Albeit, currently prototyped in text mode.</p><p>To enable the debugger, add a single line to your test:</p><pre style="background-color: white; color: #080808; font-family: "JetBrains Mono", monospace; font-size: 8.3pt; margin-left: 40px; text-align: left;"><span style="color: #74118c;">assert</span>:debug;</pre><p> Or to enable it on a particular condition:</p><pre style="background-color: white; color: #080808; font-family: "JetBrains Mono", monospace; font-size: 8.3pt; margin-left: 40px; text-align: left;"><span style="color: #74118c;">assert</span>:debug i != <span style="color: #1750eb;">3</span>;</pre><p>That will pop you into the interactive debugger mode:</p><pre style="background-color: white; color: #080808; font-family: "JetBrains Mono", monospace; font-size: 8.3pt; margin-left: 40px; text-align: left;">Call stack frames: | Variables and watches:<br />--------------------------------|---------------------------------<br />><span style="color: #1750eb;">0 </span>TestSimple.run():<span style="color: #1750eb;">10 </span>| <span style="color: #1750eb;">0 </span>this = (TestSimple.test.org)<br /> <span style="color: #1750eb;">1 </span>Service TestSimple.test.org | <span style="color: #1750eb;">1 </span>i = (Int) <span style="color: #1750eb;">3<br /></span></pre><p></p><p></p><p></p><p></p><p>Now you can type '?' for help, which displays all of the debugger commands, including breakpoint management, code stepping (in/out/thru), watches, and so on.</p><p>And yes, it is text mode, so it looks like some legit UNIX tool from 1995. Need a GUI? We'll need to finish project <i>X-wing</i> to build that! 🤣<br /></p><p></p>xtclang (Ecstasy)http://www.blogger.com/profile/10099977807321312612noreply@blogger.com0tag:blogger.com,1999:blog-3316231033424903659.post-89962521656216120162021-08-15T17:00:00.001-04:002021-08-15T17:03:38.069-04:00It's the little things ...<p>Ecstasy compiles to an Intermediate Representation (IR), which is a binary format intended to carry a rich set of information that can be used by a compiler <i>back-end</i> to generate the actual <i>native</i> code that will run on a machine's CPU. In the language and compiler field, Intermediate Representation is also know as: Intermediate Language (IL), byte code, bit code, p-code, and several other names.</p><p>Ecstasy IR was designed to be extremely tight (small), but it was also designed to support extremely large projects. To that end, all of the operators and addressing use 64 bit values; for example, the body of function can be 2^63-1 bytes long, and so the address (in either a relative or absolute form) specified by any jump operation must be able to encode 64-bit address values.</p><p>These two requirements are in natural conflict. The first says "keep it small", while the latter says "make it large". And this problem applies to many things besides jump addresses: register numbers, parameter counts, references into the constant pool, and so on. We recognized that solving this conflict in a uniform and efficient manner, and doing so up front, would be critical in keeping the design simple and consistent.</p><p>Using a byte-by-byte format, such as UTF-8, Portable Object Format <a href="https://github.com/oracle/coherence/blob/a799eb0e8d16b4d40b7ba337bba83ce2e8d542bf/prj/coherence-core/src/main/java/com/tangosol/io/AbstractByteArrayReadBuffer.java#L500">(POF) encoded integers</a>, or <a href="https://en.wikipedia.org/wiki/LEB128">LEB-128</a> was deemed to be too computationally inefficient, in that the loop condition for the variable length encoding is re-evaluated within a tight loop (once per byte), completely trashing the CPU's branch predictor, and almost certainly killing instruction pipelining and speculative execution. Since these integers are used quite literally <i>everywhere</i>, a better encoding scheme was required.</p><p>Since a variable length encoding would be used, the resulting format was carefully designed to make the exact length of the entire value apparent from examining only the first byte, allowing all of the branch prediction penalties and possibilities for pipeline stalls to be lumped together at the front edge of the decoding process. Additionally, most CPUs have the ability to read even unaligned power-of-two-length integers from memory into a register and sign extend (either as part of the read, or with an inexpensive register-based op), so the design of the format allows for this possible optimization.</p><p>The XVM Integer Packing (XIP, pronounced "zip") format employs four encoding modes: <br /></p><ul style="text-align: left;"><li><b>Tiny</b>: For a value in the range -64..63 (7 bits), the value can be encoded in one byte. The least significant 7 bits of the value are shifted left by 1 bit, and the 0x1 bit is set to 1. When reading a packed integer, if bit 0x1 of the first byte is 1, then it's Tiny.</li><li><b>Small</b>: For a value in the range -4096..4095 (13 bits), the value can be encoded in two bytes. The first byte contains the value 0x2 (010) in the least significant 3 bits, and bits 8-12 of the integer in bits 3-7; the second byte contains bits 0-7 of the integer.</li><li><b>Medium</b>: For a value in the range -1048576..1048575 (21 bits), the value can be encoded in three bytes. The first byte contains the value 0x6 (110) in the least
significant 3 bits, and bits 16-20 of the integer in bits 3-7; the
second byte contains bits 8-15 of the integer; the third byte contains
bits 0-7 of the integer.</li><li><b>Large</b>: For a value in the range <span style="font-family: courier;">-(2^511)..2^511-1</span> (up to 512 bits), a
value with <span style="font-family: courier;">s</span> significant bits can be encoded in no less than <span style="font-family: courier;">1+max(1,(s+7)/8)</span> bytes; let <span style="font-family: courier;">b</span> be the selected encoding length, in
bytes. The first byte contains the value 0x0 in the least significant 2
bits (00), and the least 6 significant bits of <span style="font-family: courier;">(b-2)</span> in bits 2-7. The
following <span style="font-family: courier;">(b-1)</span> bytes contain the least significant <span style="font-family: courier;">(b-1)*8</span> bits of
the integer. <br /></li></ul><p>The Ecstasy implementation for <a href="https://github.com/xtclang/xvm/blob/6b0e217fc159d201071a8be055c42947fc5aefd0/ecstasy/src/main/x/io/DataOutput.x#L437" target="_blank">writing</a> XIP'd integers is found in the <a href="https://github.com/xtclang/xvm/blob/master/ecstasy/src/main/x/io/DataOutput.x" target="_blank">DataOutput</a> class, and the implementation for <a href="https://github.com/xtclang/xvm/blob/6b0e217fc159d201071a8be055c42947fc5aefd0/ecstasy/src/main/x/io/DataInput.x#L325" target="_blank">reading</a> XIP'd integers is found in the <a href="https://github.com/xtclang/xvm/blob/master/ecstasy/src/main/x/io/DataInput.x" target="_blank">DataInput</a> class.</p><p>The Java implementations for <a href="https://github.com/xtclang/xvm/blob/6b0e217fc159d201071a8be055c42947fc5aefd0/utils/src/main/java/org/xvm/util/PackedInteger.java#L982" target="_blank">reading</a> and <a href="https://github.com/xtclang/xvm/blob/6b0e217fc159d201071a8be055c42947fc5aefd0/utils/src/main/java/org/xvm/util/PackedInteger.java#L765" target="_blank">writing</a> XIP'd integers can be found in the <a href="https://github.com/xtclang/xvm/blob/master/utils/src/main/java/org/xvm/util/PackedInteger.java" target="_blank">PackedInteger</a> class.<br /></p><p>In summary: Having a consistent and efficient mechanism to encode arbitrary 64-bit integers in a byte stream is a fundamental boost for an IR designer, because they no longer worry about the ugly trade-off between "will this support big enough structures in the real world?" and "will this waste space?"<br /></p>xtclang (Ecstasy)http://www.blogger.com/profile/10099977807321312612noreply@blogger.com0tag:blogger.com,1999:blog-3316231033424903659.post-21204061332870634722021-06-12T02:33:00.002-04:002021-06-12T02:33:36.057-04:00What is a type?<p>Another <a href="https://www.youtube.com/watch?v=6oCD3e2DgDc" target="_blank">Coffee Compiler Club call</a>, another concept to explain.</p><p>What is a type?</p><p>It seems like such a simple question, until you try to answer it. What <i>is</i> a type?</p><p>When we designed Ecstasy, we were intent on boiling down types to some pure form, some simple atomic model of constructing everything in our programming universe. Types are, in some way, the periodic table of program elements. The protons, neutrons, and electrons of program existence. If you can't explain the basic building blocks of your universe, how can you explain how anything <i>works</i>?</p><p>Let's start with the conclusion: <b>An object's type is the sum of its behavior</b>.</p><p>Not having any real background in type theory, I have no idea whether this is an obvious truism or a nutty novel notion. I'm going to assume the latter, only because I've never used a language with a type definition like this, and also because it provides an excellent opportunity to explain the concept.<br /></p><p>Most type systems that I've known and used are built around some combination of identity, state, and behavior. Java object types, for example, are based entirely on identity: The identity of a class <i>is</i> its type; the identity includes the name of the class, and its ancestors, in terms of super classes and implemented interfaces. Java types do carry detailed information about state (fields) and behavior (methods), but those details don't <i>define</i> the type; only the identity defines the type. The question "Is some object reference <i>o</i> of type <i>T</i>?" is never answered by what fields the object contains, nor by what methods it has, but rather by its identity, and <i>solely</i> by its identity.</p><p>Of course, this was quite a leap forward from the answer in C (and by extension, C++); in C, the question "Is some object reference <i>o</i> of type <i>T</i>?" always has the answer "Yes". Got a pointer? It turns out that your pointer points to whatever type you tell the compiler it points to. Is it a <i>Cat</i>? Is it a <i>Dog</i>? Is it a <i>Car</i>? Is it a <i>House</i>? The answer is always "<i>Yes!</i>" One must admit that C is quite an agreeable language when it comes to types. (With this in mind, it's also easy to understand how C code is responsible for so many security flaws.)</p><p>But let's drop all of these notions on the floor, and start over. Let's start with a made-up syntax for defining a type:</p><blockquote><pre style="background-color: white; color: #080808; font-family: "JetBrains Mono", monospace; font-size: 9pt;">type<br /> {<br /> <i>// things that define what the type is</i><br /> }</pre><p></p></blockquote><p>Looks kind of like a C structure. And we often think about types in exactly this way: They have a name (identity), and they have structure (fields).</p><blockquote><pre style="background-color: white; color: #080808; font-family: "JetBrains Mono", monospace; font-size: 9pt;">type Person<br /> {<br /> String firstName;<br /> String lastName;<br /> }</pre></blockquote><p>But by our definition, this is completely wrong! We claimed that <i>a type is only the sum of its behavior</i>, and this example has only identity and state instead. So let's fix this, temporarily, and in the ugliest manner possible:</p><blockquote><pre style="background-color: white; color: #080808; font-family: "JetBrains Mono", monospace; font-size: 9pt;">type // if we could name it, we'd call it "Person"<br /> {<br /> String getFirstName();<br /> void setFirstName(String);<br /> String getLastName();<br /> void setLastName(String);<br /> }</pre></blockquote><p>Interesting. Ugly, but interesting. We've turned state into behavior. And we turned the identity into a comment. But let's try an experiment: We'll allow a type to have an <i>optional</i> identity (including type name, type parameters, and ancestor types), just to make it easier to <i>describe</i> the types, and we'll create a few types that we can re-use to avoid some of that awful boilerplate:</p><blockquote><pre style="background-color: white; color: #080808; font-family: "JetBrains Mono", monospace; font-size: 9pt;">type Ref<T><br /> {<br /> T get();<br /> }<br /><br />type Var<T> : Ref<T><br /> {<br /> void set(T);<br /> }<br /><br />type Person<br /> {<br /> Var<String> firstName();<br /> Var<String> lastName();<br /> } <br /></pre></blockquote><p>So there is no state, <i>per se</i>, and the identity exists solely as a convenience for us, the reader, but we're almost back to where we started. In fact, if we introduce a short-hand notation for a zero-parameter method that returns a Var<T>, we are back where we started:</p><pre style="background-color: white; color: #080808; font-family: "JetBrains Mono", monospace; font-size: 9pt;"><blockquote>type Person<br /> {<br /> String firstName;<span> <i>// this </i></span><i>just means "Var<String> firstName()"</i><br /> String lastName; <i>// this just means "Var<String> lastName()"</i><br /> }</blockquote></pre><p>We're close, but not done, because we have referenced another type, "String". And what is a "String"? It's just another type, that <a href="https://github.com/xtclang/xvm/blob/master/ecstasy/src/main/x/text/String.x" target="_blank">has to be defined</a> in the exact same way as "Person". To define a String, it helps to have an <a href="https://github.com/xtclang/xvm/blob/master/ecstasy/src/main/x/collections/Array.x" target="_blank">Array</a>. To define an Array, which has a <i>size</i>, it helps to have an <a href="https://github.com/xtclang/xvm/blob/master/ecstasy/src/main/x/numbers/Int64.x" target="_blank">Int64</a>. To define an Int64, it helps to have another Array of <a href="https://github.com/xtclang/xvm/blob/master/ecstasy/src/main/x/numbers/Bit.x" target="_blank">Bit</a>. To define a Bit, it helps to have an <a href="https://github.com/xtclang/xvm/blob/master/ecstasy/src/main/x/numbers/IntLiteral.x" target="_blank">IntLiteral</a> to represent a 0 or 1. And to define an IntLiteral, it helps to have a String.</p><p>In other words, the type system forms a closed loop. <i>All types are defined from other types, and types are defined solely by their behavior</i>.</p><p>And behavior? Behavior is simply defined as a set of named methods, each taking zero or more typed parameters, and returning zero or more typed results.</p><h3 style="text-align: left;">So what does this mean?</h3><p>To oversimplify the conclusion, it means that a mathematician can use set theory to implement a type calculus for such a type system. Really, that's it. You know, like curing cancer, or finding the holy grail.</p><p>In Ecstasy, all types are defined like this. Even <a href="https://github.com/xtclang/xvm/blob/master/ecstasy/src/main/x/reflect/Type.x" target="_blank">Type</a> is a Type.</p><h3 style="text-align: left;">Riddle me this</h3><p>It should be pretty obvious now why we refer to this as the "Turtles Type System", since it's turtles the whole way down. One of the interesting riddles we encountered early on looked something like this:<br /></p><pre style="background-color: white; color: #080808; font-family: "JetBrains Mono", monospace; font-size: 9pt;"><blockquote>type A<br /> {<br /> B foo();<br /> }<br /> <br />type B<br /> {<br /> A foo();<br /> }</blockquote></pre><p>Question: What is the difference between an <i>A</i> and a <i>B</i>?</p><h3 style="text-align: left;">Rules</h3><p>One of the interesting things with such a type system is how easy it is to construct recursive rules from it. For example, we say that a method <i>m</i> consumes type <i>T</i> if any of the following holds true:<br /></p><ol style="text-align: left;"><li><i>m</i> has a parameter type declared as <i>T</i>;</li><li><i>m</i> has a parameter type that produces <i>T</i>;</li><li><i>m</i> has a return type that consumes <i>T</i>.</li></ol><p style="text-align: left;">Similarly, we say that a method <i>m</i> produces type <i>T</i> if any of the following holds true:</p><ol style="text-align: left;"><li><i>m</i> has a return type declared as <i>T</i>;</li><li><i>m</i> has a return type that produces <i>T</i>;</li><li><i>m</i> has a parameter type that consumes <i>T</i>.</li></ol><p>These rules form the basis for checking the legality of things like method variance, such as co-variance and contra-variance, which in turn allows the type system to intelligently enforce type safety.<br /></p><p><br /></p><p><br /></p><p><br /></p><p><br /></p>xtclang (Ecstasy)http://www.blogger.com/profile/10099977807321312612noreply@blogger.com3tag:blogger.com,1999:blog-3316231033424903659.post-65332494806369173472021-05-21T13:00:00.001-04:002021-05-21T13:00:00.231-04:00What is a Property?<p>On a recent <a href="https://twitter.com/cliff_click/" target="_blank">Cliff Click</a> Coffee Compiler Club call, this question came up: What exactly is an Ecstasy property? It turns out that a property is a very obvious and simple thing, yet explaining it is <i>not</i> so simple.</p><p>Developers have different expectations when they hear the word "property", including:</p><ul style="text-align: left;"><li>It's just a named field in a structure.</li><li>It's something that has a <i>getter</i> and a <i>setter</i>.</li></ul><p>These are logical expectations, because in languages like C++ and Java, "object properties" are just fields in structures, and in Java, the <i>getter</i> and <i>setter</i> methods are a well-known way to expose private fields as public virtual methods.</p><p>But unfortunately, starting with this train of thought takes us in the wrong direction, so let's forget all of this historical context, and back up to the beginning: <i>What exactly is an Ecstasy property?</i></p><p>First, it is important to appreciate <i>where</i> an Ecstasy property exists:</p><ul style="text-align: left;"><li>A property can be declared inside any class, including module and package classes;</li><li>A property can be declared inside a property;</li><li>A property can be declared inside a method.</li></ul><p>That a property can exist inside a class is not unusual, but it is a bit unusual that a property can exist inside another property, or even inside of a method.<br /></p><p>In Ecstasy, everything is an object, so it follows that a property is an object. Objects have types. So what is the <i>type</i> of a property? A property, like a local variable, is an instance of <a href="https://github.com/xtclang/xvm/blob/master/ecstasy/src/main/x/reflect/Ref.x" target="_blank">Ref</a>, a reference. If the property is mutable, then (also like a local variable), it is an instance of <a href="https://github.com/xtclang/xvm/blob/master/ecstasy/src/main/x/reflect/Var.x" target="_blank">Var</a>, which extends Ref.</p><p>Since a property is an object, and objects are instances of a class, then what is the <i>class</i> of a property? The class of a property is <b>unknowable</b> within Ecstasy. That does not mean that the property does not have a class; it simply means that the class is not visible from within the running code. Let's take a simple example:</p><pre style="background-color: white; color: #080808; font-family: 'JetBrains Mono',monospace; font-size: 10.5pt;"> class Person<br /> {<br /> Int age;<br /> }</pre><p>When we have an instance of <span style="font-family: courier;">Person</span>, we can ask that object's reference for its <a href="https://github.com/xtclang/xvm/blob/ed5e3a05d7c11967f1db4c0be0d4279555d8261c/ecstasy/src/main/x/reflect/Ref.x#L106" target="_blank">actual class</a>, and if it was created within the current container, it will return the <span style="font-family: courier;">Person</span> class. But it's also possible that an object reference comes from outside of the container, in which case asking for the actual class will <b>not</b> return the actual class, but will instead return just the interface type through which the object can be viewed; this is the basis for container security, and is a fundamental building block of Ecstasy's strong security model.</p><p>When the Ecstasy runtime starts up, and an Ecstasy application is loaded and starts running, it is running in the outermost Ecstasy container, called "container <span style="font-family: courier;">0</span>", which is the container within which the application's module was loaded, and within which all other containers and objects are created, so one would think that the applications' properties would also be created within that "container <span style="font-family: courier;">0</span>" ... but that would be incorrect. In order for the initial application "container <span style="font-family: courier;">0</span>" to be created, there had to already be a <span style="font-family: courier;">Container</span> class, and since that class comes from the core Ecstasy module, that means that the core Ecstasy module was already loaded in some container before "container <span style="font-family: courier;">0</span>" was created. And since it's "turtles the whole way down", it should be obvious that "container <span style="font-family: courier;">0</span>" is itself actually sitting on top of an infinite stack of turtles, which for purposes of keeping this short, we will simply refer to as "container <span style="font-family: courier;">-1</span>".</p><p>"<i>Wait ... what?!?</i>" I can almost hear the WTFs being hurled at computer screens everywhere. But here's the simple truth: Anything outside of the container that the application is loaded within is simply <i>unknowable</i>. So if the application is started in something that we call "container <span style="font-family: courier;">0</span>", and a container always exists within a container, then we know that there must be some "container <span style="font-family: courier;">-1</span>", if only because otherwise there couldn't be a "container <span style="font-family: courier;">0</span>". And just to keep this short and as-simple-as-possible, <i>the runtime itself is that unknowable outer container</i>, and the runtime itself is the container that loaded the Ecstasy module, and the runtime itself is the thing that knows how to "<span style="font-family: courier;">new</span>" a class, and to automatically "<span style="font-family: courier;">new</span>" whatever class is automatically used for each property as well. And in reality, that doesn't actually happen -- each property couldn't actually be a new object, right?</p><p>As with many things in Ecstasy, the answer is purposefully unknowable. If you ask for a property's reference, you do get back a usable object -- one that you can reflect on, pass around, store in a property somewhere, or whatever it is that you do with objects -- so obviously the property object "exists", by some definition; but like all turtles, <i>it may not have existed before you looked at it, and it may not exist when you're not looking at it</i>.<br /></p><p>But here's where things get seriously cool: Since a property does have a class, we can augment that class! Of course, we don't use the <span style="font-family: courier;">extend</span> keyword like when we sub-class (because we don't know what class to extend) ... but we <i>can</i> write a <span style="font-family: courier;">mixin</span> for the property, because we do know the type to mix into! In fact, lots of functionality in Ecstasy is built by writing mixins that can be mixed into properties and local variables, such as <a href="https://github.com/xtclang/xvm/blob/master/ecstasy/src/main/x/annotations/FutureVar.x" target="_blank">futures</a>, <a href="https://github.com/xtclang/xvm/blob/master/ecstasy/src/main/x/annotations/LazyVar.x" target="_blank">lazily calculated values</a>, and <a href="https://github.com/xtclang/xvm/blob/master/ecstasy/src/main/x/annotations/WatchVar.x" target="_blank">watched values</a>.</p><p>Furthermore, we can augment a property <i>where we define it</i>, as if it were a class. Here's a silly example:</p><pre style="background-color: white; color: #080808; font-family: 'JetBrains Mono',monospace; font-size: 10.5pt;"><span style="color: #0033b3;"> module </span>Test<br /> {<br /> <span style="color: maroon;"> @Inject </span>Console console;<br /> Log log = <span style="color: #74118c;">new </span>ecstasy.io.ConsoleLog(console);<br /><br /> void run()<br /> {<br /> log.add(<span style="color: #067d17;">"Simple property example!"</span>);<br /><br /> val o = <span style="color: #74118c;">new </span>TestClass();<br /> <span style="color: #74118c;">for </span>(Int i : <span style="color: #1750eb;">0</span>..<span style="color: #1750eb;">5</span>)<br /> {<br /> val n = o.x;<br /> }<br /><br /> o.&x.foo(); // &x gets the property, instead of de-referencing it<br /> }<br /><br /> <span style="color: #0033b3;"> class </span>TestClass<br /> {<br /> Int x<br /> {<br /> <span style="color: maroon;"> @Override </span>Int get()<br /> {<br /> ++count;<br /> <span style="color: #74118c;">return super</span>();<br /> }<br /><br /> void foo()<br /> {<br /> log.add($<span style="color: #067d17;">"Someone accessed this property {count} times!"</span>);<br /> }<br /><br /> <span style="color: #0033b3;"> private </span>Int count;<br /> }<br /> }<br /> }</pre><p> And when we run it:<br /></p><p></p><blockquote><span style="font-family: courier;">++++++ Loading module: Test +++++++<br /><br />Simple property example!<br />Someone accessed this property 6 times!<br /><br />Process finished with exit code 0</span></blockquote>So we can augment our property with code where we define the property, we can mix in predefined functionality into a property (again, it's not magic, because you could have written those mixins yourself!), and we can even modify a property's behavior on a sub-class (assuming that the property wasn't private), because the subclass' property's class implicitly extends the super-class' property's class.<p></p><p>Okay, that was a lot of information, but it conveys an important point: A property isn't just some field in a structure. It's a real object, with a real class, and it <i>behaves</i> like a real object, with a real class.<br /></p><p>But what about the property's value? Where is it stored? The Ecstasy type system determines which properties require a field for their storage, and automatically includes those fields in the underlying structure that is defined for each class, and thus exists for each object. In other words, all of a property's state is stored in whatever class the property "rolls up" into. Here are two simple examples:</p><pre style="background-color: white; color: #080808; font-family: 'JetBrains Mono',monospace; font-size: 10.5pt;"> class Example<br /> {<br /> Int x; // this has a field on Example:struct<br /><br /> Int y.get()<br /> {<br /> return 7; // this does not have a field<br /> }<br /> }<br /></pre>The type system has rules that determine when a field is required. The compiler uses these rules. The runtime uses these same rules. If a field is required, then the field will exist. If the field is not required, then the field will not exist.<p>So how is that field accessed? Well normally, we don't even think about that. If there's an object <span style="font-family: courier;">o</span> with a property <span style="font-family: courier;">x</span>, we just dereference the property <span style="font-family: courier;">o.x</span>, and we never think about the field. But conceptually, the field is accessed by the last method in the call chain for the <span style="font-family: courier;">get()</span> method on the property, so if you don't override the <span style="font-family: courier;">get()</span> method, then accessing the property goes straight to the field.</p><p>Alternatively, sometimes it is necessary to work with an object's structure directly. A serialization library, for example, may need to access the field values to store them off, and subsequently build a new structure using that stored-off data to re-instantiate the corresponding object. Instead of trying to paste an example here, it makes more sense just to point to <a href="https://github.com/xtclang/xvm/blob/master/lib_json/src/main/x/mapping/ReflectionMapping.x" target="_blank">the JSON serialization implementation</a> that does exactly this. While it might seem like a common thing (directly accessing a field), it turns out that the only places in the entire Ecstasy code base where fields are being accessed directly are (i) serialization implementations and (ii) tests of the compiler and runtime itself.<br /></p><p>So, back to the initial question: <i>What is an Ecstasy property?</i></p><ul style="text-align: left;"><li>A property <i>has a</i> name. <br /></li><li>A property <i>represents state</i> with a value, of a type. <br /></li><li>A property is <i>contained within</i> a class, a property, or a method. <br /></li><li>A property is a <i>container of</i> classes, properties, and methods.</li><li>A property is itself a class.</li><li>A property can be customized, mixed into, inherited, and overridden.</li><li>Properties are <i>virtual</i>.</li></ul><p><br /></p><p><br /></p><p><br /></p><p><br /></p><p><br /></p>xtclang (Ecstasy)http://www.blogger.com/profile/10099977807321312612noreply@blogger.com0tag:blogger.com,1999:blog-3316231033424903659.post-34858083326328763172020-12-31T00:01:00.001-05:002020-07-08T08:59:49.715-04:00<div dir="ltr" style="text-align: left;" trbidi="on">
Welcome to the Ecstasy Language, the first programming language built for the cloud!<br />
<br />
This is an official blog of the Ecstasy Language open source project at <a href="http://xtclang.org/">xtclang.org.</a><br />
<br />
Table of Contents:<br />
<ul style="text-align: left;">
<li><a href="https://xtclang.blogspot.com/2019/04/signs-of-spring.html">Introduction</a> </li>
<li><a href="https://xtclang.blogspot.com/2019/04/ecstasy-modules.html">Modules Overview</a></li>
<li><a href="https://xtclang.blogspot.com/2019/04/on-god-turtles-balloons-and-sandboxes.html">Security Model</a></li>
<li><a href="https://xtclang.blogspot.com/2019/04/explicit-intent-enumerating-priorities.html">Design Priorities</a></li>
<li><a href="https://xtclang.blogspot.com/2019/04/on-hierarchical-organization.html">Hierarchical Organization</a></li>
<li><a href="https://xtclang.blogspot.com/2019/06/how-to-assert-yourself-more.html" target="_blank">How to assert yourself more</a></li>
<li><a href="https://xtclang.blogspot.com/2019/06/conditional-methods.html" target="_blank">Conditional Methods</a></li>
<li><a href="https://xtclang.blogspot.com/2019/06/an-introduction-to-ecstasy-type-system.html" target="_blank">An Introduction to the Ecstasy Type System</a></li>
<li><a href="https://xtclang.blogspot.com/2019/06/a-pointed-paean-for-c.html" target="_blank">A pointed paean for C</a></li>
<li><a href="https://xtclang.blogspot.com/2019/06/the-quest-for-equality.html" target="_blank">The Quest for Equality</a></li>
<li><a href="https://xtclang.blogspot.com/2019/07/null-is-no-exception.html" target="_blank">Null is no Exception</a> </li>
<li><a href="https://xtclang.blogspot.com/2019/07/literally-awesome.html" target="_blank">Literally awesome!</a></li>
<li><a href="https://xtclang.blogspot.com/2019/07/if-it-quacks.html" target="_blank">Duck!</a> </li>
<li><a href="https://xtclang.blogspot.com/2019/07/a-pane-in-glass.html" target="_blank">A Pane in the Glass</a></li>
<li><a href="https://xtclang.blogspot.com/2019/07/composition.html">Composition</a> </li>
<li><a href="https://xtclang.blogspot.com/2019/08/hello-world.html" target="_blank">Hello World!</a> (a working example!) </li>
<li><a href="https://xtclang.blogspot.com/2019/10/more-turtles.html" target="_blank">More Turtles</a></li>
<li><a href="https://xtclang.blogspot.com/2020/01/coming-from-java.html" target="_blank">Coming from Java</a> & <a href="https://xtclang.blogspot.com/2020/01/coming-from-java-part-ii.html" target="_blank">Part 2</a> & <a href="https://xtclang.blogspot.com/2020/01/coming-from-java-part-iii.html" target="_blank">Part 3</a> </li>
</ul>
Blogs:<br />
<ul>
<li><a href="https://xtclang.blogspot.com/">https://xtclang.blogspot.com/</a> (this blog) - technical topics</li>
<li><a href="https://ecstasylang.blogspot.com/">https://ecstasylang.blogspot.com/</a> - announcements and project-related topics</li>
</ul>
Repository:<br />
<ul style="text-align: left;">
<li><a href="http://github.com/xtclang/" target="_blank">xtclang @ GitHub</a> - Source repository</li>
</ul>
Twitter:<br />
<ul>
<li> <a href="https://twitter.com/xtclang">@xtclang</a> - Official Twitter account for the xtclang project.</li>
</ul>
Current Status:<br />
<ul style="text-align: left;">
<li>Early developer access / prototype runtime</li>
</ul>
<br />
Email Inquiries: <span style="font-family: "courier new", "courier", monospace;">info at xtclang dot org </span></div>
xtclang (Ecstasy)http://www.blogger.com/profile/10099977807321312612noreply@blogger.com0tag:blogger.com,1999:blog-3316231033424903659.post-20597260576978467752020-01-25T13:30:00.000-05:002020-01-25T13:37:35.138-05:00Coming from Java, Part III (Singletons)<div dir="ltr" style="text-align: left;" trbidi="on">
<br />
(This entry is the third installment of "Coming from Java". This is Part III; here is a link to <a href="https://xtclang.blogspot.com/2020/01/coming-from-java-part-ii.html" target="_blank">Part II</a>.)<br />
<br />
There is a common pattern in Java, which is the singleton pattern. Basically, it allows you to create a single instance of a class, and then to be able to find that one same instance from anywhere in your code<br />
<blockquote class="tr_bq">
<pre style="background-color: white; color: black; font-size: 10.5pt;"><span style="font-family: "Courier New", Courier, monospace;"><span style="color: navy; font-weight: bold;">public class </span>Singleton
{
<span style="color: navy; font-weight: bold;">public static final </span>Singleton INSTANCE = <span style="color: navy; font-weight: bold;">new </span>Singleton();
<span style="color: navy; font-weight: bold;">private </span>Singleton()
{
<span style="color: grey; font-style: italic;">// initialization stuff goes here</span></span>
<span style="font-family: "Courier New", Courier, monospace;"><span style="color: grey; font-style: italic;"><span style="font-family: "Courier New", Courier, monospace;"></span></span><span style="color: grey; font-style: italic;"> </span>}
}</span></pre>
</blockquote>
Creating a singleton in Ecstasy is accomplished by using the <span style="font-family: "Courier New", Courier, monospace;">static</span> keyword for the class:<br />
<blockquote class="tr_bq">
<pre style="background-color: white; color: black; font-family: 'Menlo-Regular'; font-size: 10.5pt;"><span style="color: navy; font-weight: bold;"></span><span style="font-family: "Courier New", Courier, monospace;"><span style="color: navy; font-weight: bold;">static const </span>Singleton
{
<span style="color: navy; font-weight: bold;">construct</span>()
{
<span style="color: grey; font-style: italic;">// initialization stuff goes here</span></span>
<span style="font-family: "Courier New", Courier, monospace;"><span style="color: grey; font-style: italic;"><span style="font-family: "Courier New", Courier, monospace;"></span></span><span style="color: grey; font-style: italic;"> </span>}
}</span></pre>
</blockquote>
There is one tiny detail, though: In Ecstasy, only <span style="font-family: "Courier New", Courier, monospace;">const</span> classes and <span style="font-family: "Courier New", Courier, monospace;">service</span> classes can be singletons, and the reason is quite fundamental to the purposes for which Ecstasy was designed.<br />
<br />
To begin with, consider the differences between high-end computers that Java was designed for, and the high-end computers that Ecstasy is designed for. At the time that Java was initially being designed in the early 1990s, <b>very</b> few computers had more than one CPU -- Sun hadn't yet even released its first multiprocessor workstation! A server or a high-end workstation might have had 8MB of RAM, and -- still hard to believe! -- the IBM 370 mainframe of the day topped out at 16MB of RAM. That's <b>megabytes</b> -- a new notebook today has a thousand times that much memory!<br />
<br />
Over a decade later, with dual-CPU servers now the norm, Java would get its first working <i>memory model</i> specification, specifying the JVM's guarantees for reads and writes occurring across multiple CPUs and among multiple threads.<br />
<br />
Ecstasy, in contrast, was designed explicitly to take advantage of computers with potentially many <b>thousands</b> of cores, and with potentially many <b>terabytes</b> of main memory. To accomplish this, the design focused on disentangling threads from each other, and disentangling the memory -- what Java calls "the heap". The rationale is simple: In a modern computer, a single thread of code can perform on the order of 1-10 billion instructions per second, <b>if and only if</b> the thread does not share read/write memory with any other threads. The moment that a thread starts to use read/write memory that is being used by other threads, the performance (and the predictability of the performance) drops like a lead balloon.<br />
<br />
To avoid the lead balloon effect, Ecstasy carves out <b>exclusive</b> zones of mutable memory, each with its own single conceptual thread. Each of these is called a <i>service</i>. An Ecstasy service can be thought of as a simple <i>Turing Machine</i>, or a simple <i>von Neumann machine</i>. And an Ecstasy service can be thought of as a <i>boundary</i> for mutability, because all mutation of a service's memory occurs within that service, and only immutable data can permeate that boundary. Services can communicate with other services, but that communication is conceptually <b>asynchronous</b> in nature, the communication is in the form of <b>invocation</b>, and only <b>immutable</b> data is exchanged.<br />
<br />
Since a singleton is, by its nature, visible to all code running in an application, it therefore stands to reason that the singleton <i>must</i> be immutable -- so that it can be used by code running in any service -- or the singleton must itself <i>be</i> a service -- so that it can be invoked by code running in any other service.<br />
<br />
And here is a straight-forward example in Ecstasy: <br />
<blockquote class="tr_bq">
<pre style="background-color: white; color: black; font-family: 'Menlo-Regular'; font-size: 10.5pt;"><span style="font-family: "Courier New", Courier, monospace;"><span style="color: navy; font-weight: bold;">static service </span>PageCounter
{
Int count = <span style="color: blue;">0</span>;
Int hit()
{
<span style="color: #660e7a; font-weight: bold;">return </span>++count;
}
}</span></pre>
</blockquote>
Using the singleton is equally simple:<br />
<blockquote class="tr_bq">
<pre style="background-color: white; color: black; font-size: 10.5pt;"><span style="font-family: "Courier New", Courier, monospace;">PageCounter.hit();</span></pre>
</blockquote>
(Since it is a singleton, the name of the class <i>implies</i> the singleton instance.)<br />
<br />
The same example can be constructed in Java, but thread safety is the responsibility of the programmer:<br />
<blockquote class="tr_bq">
<pre style="background-color: white; color: black; font-size: 10.5pt;"><span style="font-family: "Courier New", Courier, monospace;"><span style="color: navy; font-weight: bold;">public class </span>PageCounter
{
<span style="color: navy; font-weight: bold;">public static final </span>PageCounter INSTANCE = <span style="color: navy; font-weight: bold;">new </span>PageCounter();
<span style="color: navy; font-weight: bold;">private </span>PageCounter() {}
<span style="color: navy; font-weight: bold;">private int </span>count;
<span style="color: navy; font-weight: bold;">synchronized public void </span>setCount(<span style="color: navy; font-weight: bold;">int </span>count)
{
<span style="color: navy; font-weight: bold;">this</span>.count = count;
}
<span style="color: navy; font-weight: bold;">synchronized public int </span>getCount()
{
<span style="color: navy; font-weight: bold;">return </span>count;
}
<span style="color: navy; font-weight: bold;">synchronized public int </span>hit()
{
<span style="color: navy; font-weight: bold;">return </span>++count;
}
}
<span style="color: grey; font-style: italic;">// how to call the singleton</span></span><span style="font-family: "Courier New", Courier, monospace;"><span style="color: grey; font-style: italic;"><span style="font-family: "Courier New", Courier, monospace;">
<span style="color: grey; font-style: italic;"></span></span></span>PageCounter.INSTANCE.hit();</span></pre>
</blockquote>
There are a variety of ways to implement the counter in Java in order to make it more concurrent; for example, an atomic integer class can be used, or an atomic updater on a volatile field can be used, and so on. In Ecstasy, on the other hand, the choice of how to make the counter more concurrent is left completely up to the run-time implementation. The choice to allow the run-time to optimize this facet of execution is based on what we learned from Java's own HotSpot JVM -- which is that only the run-time has enough information to know which parts of the application would actually benefit from optimization in the first place, and which optimizations would work best, based on the actual run-time profiling information!<br />
<br />
A few miscellaneous notes to wrap up this singular topic:<br />
<ul style="text-align: left;">
<li>In Ecstasy, every <span style="font-family: "Courier New", Courier, monospace;">module</span>, <span style="font-family: "Courier New", Courier, monospace;">package</span>, and <span style="font-family: "Courier New", Courier, monospace;">enum</span> is a "<span style="font-family: "Courier New", Courier, monospace;">static const</span>" class, automatically. That means that modules and packages are all singleton objects, and every enum value is a singleton object.</li>
<li>Ecstasy does not require a memory model for explaining the order of reads and writes of mutable data among threads, because (as explained above) the Ecstasy design does not have mutable shared state among threads. (The Ecstasy design also uses services in lieu of explicit developer-managed threads, but that is a topic for another blog entry.)</li>
<li>There is no "global heap" in Ecstasy, so there is no "stop the world" garbage collection. Ecstasy is automatically garbage-collected, but each service can manage its own memory. The Ecstasy design effectively eliminates the "GC pause" problem, even for programs that use terabytes of RAM.</li>
</ul>
<br /> </div>
xtclang (Ecstasy)http://www.blogger.com/profile/10099977807321312612noreply@blogger.com0tag:blogger.com,1999:blog-3316231033424903659.post-79498866484651143052020-01-23T23:00:00.001-05:002020-07-08T10:30:57.581-04:00Coming from Java, Part II<div dir="ltr" style="text-align: left;" trbidi="on">
(This topic is large, so this entry is just the second installment. This is Part II; here is a link to <a href="https://xtclang.blogspot.com/2020/01/coming-from-java.html" target="_blank">Part I</a>.)<br />
<br />
In Object Oriented languages, objects represent the combination of related <i>state</i> and <i>behavior</i>. Java classes declare <i>fields</i> to hold state, and <i>methods</i> to provide behavior. Java fields and the methods are nested immediately within the class that contains them. This is an example of a common pattern for a Java class exposing state, stored in fields, via property accessors:<br />
<blockquote class="tr_bq">
<pre style="background-color: white; color: black; font-size: 10.5pt;"><span style="color: navy; font-weight: bold;">public class </span>Person
{
<span style="color: navy; font-weight: bold;">public </span>Person(String name, String phone)
{
setName(name);
setPhone(phone);
}
<span style="color: navy; font-weight: bold;">private </span>String name;
<span style="color: navy; font-weight: bold;">private </span>String phone;
<span style="color: navy; font-weight: bold;">public </span>String getName()
{
<span style="color: navy; font-weight: bold;">return </span>name;
}
<span style="color: navy; font-weight: bold;">public void </span>setName(String name)
{
<span style="color: navy; font-weight: bold;">assert </span>name != <span style="color: navy; font-weight: bold;">null</span>;
<span style="color: navy; font-weight: bold;">this</span>.name = name;
}
<span style="color: navy; font-weight: bold;">public </span>String getPhone()
{
<span style="color: navy; font-weight: bold;">return </span>phone;
}
<span style="color: navy; font-weight: bold;">public void </span>setPhone(String phone)
{
<span style="color: navy; font-weight: bold;">this</span>.phone = phone;
}
}
<span style="font-family: "courier new", "courier", monospace;"></span></pre>
</blockquote>
Ecstasy classes do not declare fields; instead, Ecstasy classes have <i>properties</i> that represent object state. A property is like an object, in that it can have its own nested state, and its own nested behavior. For example, to obtain the value of a property, one can invoke the <span style="font-family: "courier new", "courier", monospace;">get()</span> method on the property. If the property is writable, then one can modify the value of the property by invoking the <span style="font-family: "courier new", "courier", monospace;">set()</span> method on the property. (Of course, it is possible to use the simple dot notation for property access, which means that explicit calls to <span style="font-family: "courier new", "courier", monospace;">get()</span> and <span style="font-family: "courier new", "courier", monospace;">set()</span>are unnecessary.) Here is the above class, re-written in Ecstasy:<br />
<blockquote class="tr_bq">
<pre style="background-color: white; color: black; font-size: 10.5pt;"><span style="font-family: "courier new", "courier", monospace;"><span style="color: navy; font-weight: bold;">class </span>Person(String name, String? phone);</span></pre>
</blockquote>
You could also write it out in long-hand if you prefer; the following code compiles to the same exact result as the above code:<br />
<blockquote class="tr_bq">
<pre style="background-color: white; color: black; font-family: "menlo-regular"; font-size: 10.5pt;"><span style="font-family: "courier new", "courier", monospace;"><span style="color: navy; font-weight: bold;">class </span>Person
{
<span style="color: navy; font-weight: bold;">construct</span>(String name, String? phone = Null)
{
this.name = name;
this.phone = phone;
}
String name;
String? phone;
}</span></pre>
</blockquote>
It's possible in Java to make the "getter" and "setter" have different access, such as:<br />
<blockquote class="tr_bq">
<pre style="background-color: white; color: black; font-family: "menlo-regular"; font-size: 10.5pt;"><span style="font-family: "courier new", "courier", monospace;"><span style="color: navy; font-weight: bold;">public </span>String getName()
{
<span style="color: #660e7a; font-weight: bold;">return </span>name;
}
<span style="color: navy; font-weight: bold;">private </span>void setName(String name)
{
<span style="color: #660e7a; font-weight: bold;">assert </span>name != <span style="color: #660e7a; font-weight: bold;">null</span>;
this.name = name;
}</span></pre>
</blockquote>
To accomplish this in Ecstasy, the equivalent is:<br />
<blockquote class="tr_bq">
<pre style="background-color: white; color: black; font-size: 10.5pt;"><span style="font-family: "courier new", "courier", monospace;"><span style="color: navy; font-weight: bold;">public</span>/<span style="color: navy; font-weight: bold;">private </span>String name;</span></pre>
</blockquote>
The first access, "<span style="font-family: "courier new", "courier", monospace;">public</span>", specifies that the property shows up in the public type as a <span style="font-family: "courier new", "courier", monospace;">Ref<String></span>; a <a href="https://github.com/xtclang/xvm/blob/master/ecstasy/src/main/x/reflect/Ref.x"><span style="font-family: "courier new", "courier", monospace;">Ref</span></a> represents a read-only reference to a value. The second access, "<span style="font-family: "courier new", "courier", monospace;">private</span>", specifies that the property shows up in the private type as a <span style="font-family: "courier new", "courier", monospace;">Var<String></span>; a <a href="https://github.com/xtclang/xvm/blob/master/ecstasy/src/main/x/reflect/Var.x"><span style="font-family: "courier new", "courier", monospace;">Var</span></a> represents both read and write access to the value.<br />
<br />
Remember, though, that a property is like an object. Let's expand the Java example slightly, to validate that the name is not an empty <span style="font-family: "courier new", "courier", monospace;">String</span>:<br />
<blockquote class="tr_bq">
<pre style="background-color: white; color: black; font-family: "menlo-regular"; font-size: 10.5pt;"><span style="font-family: "courier new", "courier", monospace;"><span style="color: navy; font-weight: bold;">public void </span>setName(String name)
{
<span style="color: navy; font-weight: bold;">assert </span>name != <span style="color: navy; font-weight: bold;">null </span>&& name.length() > <span style="color: blue;">0</span>;</span><span style="font-family: "courier new", "courier", monospace;"><span style="font-family: "courier new", "courier", monospace;">
this.name = name;</span></span><span style="font-family: "courier new", "courier", monospace;"><span style="font-family: "courier new", "courier", monospace;"><span style="font-family: "courier new", "courier", monospace;">
</span></span>}</span></pre>
</blockquote>
In Ecstasy, the property contains a method called <span style="font-family: "courier new", "courier", monospace;">set(String)</span> that we can override:<br />
<blockquote class="tr_bq">
<pre style="background-color: white; color: black; font-size: 10.5pt;"><span style="font-family: "courier new", "courier", monospace;"><span style="color: navy; font-weight: bold;">public</span>/<span style="color: navy; font-weight: bold;">private </span>String name.set(String name)
{
<span style="color: #660e7a; font-weight: bold;">assert</span>:arg name.size > <span style="color: blue;">0</span>;
<span style="color: #660e7a; font-weight: bold;">super</span>(name);
}</span></pre>
</blockquote>
The above is just short-hand notation for:<br />
<blockquote class="tr_bq">
<pre style="background-color: white; color: black; font-size: 10.5pt;"><span style="font-family: "courier new", "courier", monospace;"><span style="color: navy; font-weight: bold;">public</span>/<span style="color: navy; font-weight: bold;">private </span>String name
{
@Override void set(String name)
{
<span style="color: #660e7a; font-weight: bold;">assert</span>:arg name.size > <span style="color: blue;">0</span>;
<span style="color: #660e7a; font-weight: bold;">super</span>(name);
}
}</span></pre>
</blockquote>
There are a couple of important points here:<br />
<ul style="text-align: left;">
<li>It's <b>not</b> the <span style="font-family: "courier new", "courier", monospace;">set()</span> method that is private. The <span style="font-family: "courier new", "courier", monospace;">set()</span> method is public, because it is part of the <span style="font-family: "courier new", "courier", monospace;">Var</span> interface, as explained above.</li>
<li>Instead, the public Person type (known as <span style="font-family: "courier new", "courier", monospace;">Person:public</span> or <span style="font-family: "courier new", "courier", monospace;">Person.PublicType</span>) has a property that does <b>not</b> have a <span style="font-family: "courier new", "courier", monospace;">set()</span> method, while the private Person type (known as <span style="font-family: "courier new", "courier", monospace;">Person:private</span> or <span style="font-family: "courier new", "courier", monospace;">Person.PrivateType</span>) has a property that <b>does</b> have a <span style="font-family: "courier new", "courier", monospace;">set()</span> method.</li>
<li>In Java, "<span style="font-family: "courier new", "courier", monospace;">super</span>" refers to the <i>super-class</i>. In Ecstasy, <span style="font-family: "courier new", "courier", monospace;">super</span> is a reference to the function (like a <i>function pointer</i>) that is next in line to invoke in the virtual method's <i>invocation chain</i>. In other words, <span style="font-family: "courier new", "courier", monospace;">super</span> is a function.</li>
<li>While it's not directly related, you can read more about the <a href="https://xtclang.blogspot.com/2019/06/how-to-assert-yourself-more.html" target="_blank">various specializations</a> of the assert statement on this blog. The <span style="font-family: "courier new", "courier", monospace;">assert:arg</span> statement produces an <span style="font-family: "courier new", "courier", monospace;">IllegalArgument</span> exception if the assertion fails.</li>
</ul>
The interesting thing, though, is that we never have to deal with the field. We know it's there, because it has to be in order to hold the value, but the field doesn't have a name, we don't access it, and we don't modify it. Instead, we just call the <span style="font-family: "courier new", "courier", monospace;">super</span> function for <span style="font-family: "courier new", "courier", monospace;">get()</span> or <span style="font-family: "courier new", "courier", monospace;">set()</span>, and at the end of that chain there is some implementation of the method (that we didn't have to write!) that accesses or stores the value for us using the field.<br />
<br />
But what if we made it so that we could never reach the end of those method chains?<br />
<blockquote class="tr_bq">
<pre style="background-color: white; color: black; font-size: 10.5pt;"><span style="font-family: "courier new", "courier", monospace;"><span style="color: navy; font-weight: bold;">public</span>/<span style="color: navy; font-weight: bold;">private </span>String name
{
String get()
{
<span style="color: #660e7a; font-weight: bold;">return </span><span style="color: green; font-weight: bold;">"Bob"</span>;
}
void set(String name)
{
<span style="color: #660e7a; font-weight: bold;">assert</span>:arg name.size > <span style="color: blue;">0</span>;
<span style="color: grey; font-style: italic;">// do nothing with the name ... do not store it!</span></span><span style="font-family: "courier new", "courier", monospace;"><span style="color: grey; font-style: italic;"><span style="font-family: "courier new", "courier", monospace;">
</span></span>}
}</span></pre>
</blockquote>
In this case, there would be no field for the <span style="font-family: "courier new", "courier", monospace;">name</span> property, because it's obvious to the compiler that one is not needed!<br />
<br />
So now it should be obvious that fields exist in Ecstasy, but that we never really have to mess around with them. Where are those fields actually held, though?<br />
<br />
In one of the examples above, we talked about how the <span style="font-family: "courier new", "courier", monospace;">Person</span> class has a <span style="font-family: "courier new", "courier", monospace;">public</span> type and a <span style="font-family: "courier new", "courier", monospace;">private</span> type, so you probably already guessed that the <span style="font-family: "courier new", "courier", monospace;">Person</span> class also has a <span style="font-family: "courier new", "courier", monospace;">protected</span> type, and you would be correct!<br />
<br />
But the <span style="font-family: "courier new", "courier", monospace;">Person</span> class has one more type: the <span style="font-family: "courier new", "courier", monospace;"><span style="font-family: "courier new", "courier", monospace;">Person:</span>struct</span> type. The <span style="font-family: "courier new", "courier", monospace;"><span style="font-family: "courier new", "courier", monospace;">Person:</span>struct</span> type has one property for each property of the <span style="font-family: "courier new", "courier", monospace;"><span style="font-family: "courier new", "courier", monospace;">Person</span></span> class that needs a field. We call each property on the <span style="font-family: "courier new", "courier", monospace;">struct</span> type a "field"; in Ecstasy, a field is just a property on a class' <span style="font-family: "courier new", "courier", monospace;"><span style="font-family: "courier new", "courier", monospace;"></span>struct</span> type.<br />
<br />
The <span style="font-family: "courier new", "courier", monospace;">struct</span> type is not user-definable. The <span style="font-family: "courier new", "courier", monospace;">struct</span> type is automatically calculated by the compiler at compile-time, and by linker/loader at run-time. While the <span style="font-family: "courier new", "courier", monospace;">public</span>, <span style="font-family: "courier new", "courier", monospace;">protected</span>, and <span style="font-family: "courier new", "courier", monospace;">private</span> types all refer to the same underlying object -- as if they were three different lenses through which you can view the same object -- the <span style="font-family: "courier new", "courier", monospace;">struct</span>, on the other hand, is a <i>separate</i> object that is an implementation of the <a href="https://github.com/xtclang/xvm/blob/master/ecstasy/src/main/x/reflect/Struct.x"><span style="font-family: "courier new", "courier", monospace;">Struct</span></a> interface.<br />
<br />
For the purpose of this article, this is already way too much low-level information about structs, but the details are important for one reason: To understand constructors.<br />
<br />
Constructors are weird. They live in a zone between non-existence and existence. They play by some extraordinary rules in Java, and the same is true in Ecstasy, because they fit into a <i>zone of unknowns</i>. Here's what a constructor looks like in Java, just to pick one at random from our own prototype compiler that was written in Java:<br />
<blockquote class="tr_bq">
<pre style="background-color: white; color: black; font-family: "menlo-regular"; font-size: 10.5pt;"><span style="font-family: "courier new", "courier", monospace;"><span style="color: navy; font-weight: bold;">public </span>StringConstant(ConstantPool pool, String sVal)
{
<span style="color: navy; font-weight: bold;">super</span>(pool);
<span style="color: navy; font-weight: bold;">assert </span>sVal != <span style="color: navy; font-weight: bold;">null</span>;
<span style="color: #660e7a; font-weight: bold;">m_sVal </span>= sVal;
}</span></pre>
</blockquote>
First, in Java, a constructor <b>must</b> call either a different constructor on <span style="font-family: "courier new", "courier", monospace;">this</span> class, or a constructor on the <span style="font-family: "courier new", "courier", monospace;">super</span> class. Then, it is free to do other stuff, like checking parameters and initializing fields. Fields that aren't explicitly initialized are all set to their defaults, which is easy when <span style="font-family: "courier new", "courier", monospace;">null</span> is a <a href="https://xtclang.blogspot.com/2019/07/null-is-no-exception.html" target="_blank">sub-class of everything</a>.<br />
<br />
Ecstasy is different. Not necessarily simpler or more complicated. Not necessarily better or worse. But it is different for very purposeful reasons:<br />
<ul style="text-align: left;">
<li>Contruction is treated as a <i>finite state automaton</i>. Eliminating unknowns and improving predictability of execution is extremely important, and that is exactly what a <i>finite state automaton</i> does.</li>
<li>There is a period of time before the object is constructed. The developer gets complete control over that process.</li>
<li>There is a period of time after the object is constructed. The developer gets complete control over that process.</li>
<li>In between the <i>before</i> and the <i>after</i>, the developer is completely absent, and completely out of the picture for the moment of creation. During that moment, all the rules of object instantiation can be verified, and the object is created. We say that "<i>the </i><span style="font-family: "courier new", "courier", monospace;">this</span><i> becomes existent</i>".</li>
</ul>
In that period before the object creation, there are two phases that the developer can implement:<br />
<ol style="text-align: left;">
<li>The <span style="font-family: "courier new", "courier", monospace;">construct(...)</span> function(s) allows the developer to specify what information is needed to initialize the state of the object, and the developer can validate that information and initialize the <i>structure</i> of the object, which is the aforementioned <span style="font-family: "courier new", "courier", monospace;">struct</span>.</li>
<li>The <span style="font-family: "courier new", "courier", monospace;">assert()</span> function allows the developer to collect, in one place, any assertions (or any other last-second work) that must occur before the object is created.</li>
</ol>
Here is an example of a constructor, from the <a href="https://github.com/xtclang/xvm/blob/master/ecstasy/src/main/x/temporal/Date.x"><span style="font-family: "courier new", "courier", monospace;">Date</span></a> class, which simply delegates to another constructor using the <span style="font-family: "courier new", "courier", monospace;">construct</span> keword:<br />
<blockquote class="tr_bq">
<pre style="background-color: white; color: black; font-family: "menlo-regular"; font-size: 10.5pt;"><span style="font-family: "courier new", "courier", monospace;"><span style="color: navy; font-weight: bold;">construct </span>(Int year, Int month, Int day)
{
<span style="color: navy; font-weight: bold;">construct </span>Date(calcEpochOffset(year, month, day));
}</span></pre>
</blockquote>
For both <span style="font-family: "courier new", "courier", monospace;">construct(...)</span> and <span style="font-family: "courier new", "courier", monospace;">assert()</span>, the <span style="font-family: "courier new", "courier", monospace;">this</span> variable is the <span style="font-family: "courier new", "courier", monospace;">struct</span> -- not the object, because it has not yet been created! After that code has all completed successfully, the <span style="font-family: "courier new", "courier", monospace;">struct</span> is checked <i>by the system</i> to make sure that all necessary fields have been assigned a value, and then the object is <i>instantiated</i> based on the <span style="font-family: "courier new", "courier", monospace;">struct</span>. Then -- after the moment of creation, and before the newly created "<span style="font-family: "courier new", "courier", monospace;">this</span>" reference is returned to the code that invoked the <span style="font-family: "courier new", "courier", monospace;">new</span> operator -- one more step occurs: The corresponding <span style="font-family: "courier new", "courier", monospace;">finally(...)</span> function for each previously invoked <span style="font-family: "courier new", "courier", monospace;">construct(...)</span> function is executed, so that the object itself gets to see itself (and finish anything that it needs to) before being returned to the code that requested it.<br />
<br />
Here's an example from the <a href="https://github.com/xtclang/xvm/blob/master/ecstasy/src/main/x/collections/Array.x"><span style="font-family: "courier new", "courier", monospace;">Array</span></a> class:<br />
<blockquote class="tr_bq">
<pre style="background-color: white; color: black; font-family: "menlo-regular"; font-size: 10.5pt;"><span style="font-family: "courier new", "courier", monospace;"><span style="color: navy; font-weight: bold;">protected construct</span>(ArrayDelegate<Element> delegate)
{
this.delegate = delegate;
}
<span style="color: #660e7a; font-weight: bold;">finally</span></span><span style="font-family: "courier new", "courier", monospace;"><span style="color: #660e7a; font-weight: bold;"><span style="font-family: "courier new", "courier", monospace;">
<span style="color: #660e7a; font-weight: bold;"></span></span></span><span style="color: #660e7a; font-weight: bold;"> </span>{
<span style="color: #660e7a; font-weight: bold;">if </span>(mutability == Constant)
{
makeImmutable();
}
}</span></pre>
</blockquote>
In this example, the <span style="font-family: "courier new", "courier", monospace;">construct(...)</span> function fills in the fields of the <span style="font-family: "courier new", "courier", monospace;">struct</span>, but because the <span style="font-family: "courier new", "courier", monospace;">Array</span> object does not yet exist at this point, the <span style="font-family: "courier new", "courier", monospace;">construct(...)</span> function can <b>not</b> call the <span style="font-family: "courier new", "courier", monospace;">makeImmutable()</span> method on the <span style="font-family: "courier new", "courier", monospace;">Array</span> -- until the <span style="font-family: "courier new", "courier", monospace;">Array</span> actually exists! And <i>that</i> is the purpose of the <span style="font-family: "courier new", "courier", monospace;">finally</span> function -- to allow the new <span style="font-family: "courier new", "courier", monospace;">Array</span> object to perform behavior that must occur <i>as if it were part of</i> the instantiation of the object, <b>before</b> that object is returned to the code that requested the object to be created.<br />
<br />
A class can define an <span style="font-family: "courier new", "courier", monospace;">assert()</span> function (with no parameters) as well. Regardless of whether any particular <span style="font-family: "courier new", "courier", monospace;">construct(...)</span> function is invoked by the <span style="font-family: "courier new", "courier", monospace;">new</span> operator, or by a sub-class -- and note that a sub-class is <b>not</b> required to invoke any <span style="font-family: "courier new", "courier", monospace;">construct(...)</span> function on its super-class! -- the assert() function will be invoked <i>before</i> the object is created.<br />
<br />
There are many details regarding the specific order of execution, handling of exceptions, and so on, but this post hopefully has given you a glimpse into how object structure works in Ecstasy, and how Ecstasy objects are created.<br />
<br />
(Continue to <a href="https://xtclang.blogspot.com/2020/01/coming-from-java-part-iii.html" target="_blank">Part III</a>.)</div>
xtclang (Ecstasy)http://www.blogger.com/profile/10099977807321312612noreply@blogger.com0tag:blogger.com,1999:blog-3316231033424903659.post-58030751810083531052020-01-22T16:30:00.001-05:002020-07-08T10:26:21.545-04:00Coming from Java<div dir="ltr" style="text-align: left;" trbidi="on">
<div>
The first question that we get from new developers working on Ecstasy is how it is similar to, and how it is different from the languages that they already know and use. One of the goals of Ecstasy was to make the language <b>instantly accessible</b> to programmers who already were comfortable with any of the C family of languages, such as C++, Java, and C#. We'll start by looking at one such language, Java, which is one of the most widely used languages today.<br />
<br />
(This topic is large, so this entry is just the first installment.)<br />
<br />
Here's the pocket translation guide from Java to Ecstasy with respect to the type system:<br />
<ul style="text-align: left;">
<li>Java's type system is a combination of primitive (machine) types and class-based types, with a few "hybrid" types, such as arrays, that fit neither category. Ecstasy's type system is simply class-based; there are no primitive types.</li>
<li>Java's null type has one value, <span style="font-family: "courier new", "courier", monospace;">null</span>, that is assignment compatible with any reference type. The Ecstasy <span style="font-family: "courier new", "courier", monospace;">Nullable</span> enumeration defines the value <span style="font-family: "courier new", "courier", monospace;">Null</span>, although the lower-case <span style="font-family: "courier new", "courier", monospace;">null</span> is also supported by alias. In Ecstasy, the <span style="font-family: "courier new", "courier", monospace;">Null</span> enum value is only assignable to a <span style="font-family: "courier new", "courier", monospace;">Nullable</span> type, or a super-type thereof such as <span style="font-family: "courier new", "courier", monospace;">Object</span>.</li>
<li>Java's <span style="font-family: "courier new", "courier", monospace;">boolean</span> type has two values, <span style="font-family: "courier new", "courier", monospace;">true</span> and <span style="font-family: "courier new", "courier", monospace;">false</span>. The Ecstasy <span style="font-family: "courier new", "courier", monospace;">Boolean</span> enumeration defines the values <span style="font-family: "courier new", "courier", monospace;">False</span> and <span style="font-family: "courier new", "courier", monospace;">True</span>, although the lower-case <span style="font-family: "courier new", "courier", monospace;">false</span> and <span style="font-family: "courier new", "courier", monospace;">true</span> are also supported by alias.</li>
<li>Java's <span style="font-family: "courier new", "courier", monospace;">char</span> type is a 2-byte unsigned integer that represents a common sub-set of Unicode characters. Ecstasy's <span style="font-family: "courier new", "courier", monospace;">Char</span> class represents any Unicode code-point.</li>
<li>Java's <span style="font-family: "courier new", "courier", monospace;">int</span> type is a 32-bit unchecked signed integer value; Java additionally has <span style="font-family: "courier new", "courier", monospace;">byte</span>, <span style="font-family: "courier new", "courier", monospace;">short</span> and <span style="font-family: "courier new", "courier", monospace;">long</span> types for 8-bit, 16-bit, and 64-bit unchecked signed integer values. Ecstasy provides both checked and unchecked, and both signed and unsigned implementations for 8-bit, 16-bit, 32-bit, 64-bit, 128-bit, and variable-length integers (conceptually similar to Java's BigInteger class). For example, <span style="font-family: "courier new", "courier", monospace;">UInt32</span> is a checked unsigned 32-bit integer, and <span style="font-family: "courier new", "courier", monospace;">@Unchecked Int128</span> is an unchecked signed 128-bit integer. Additionally, the alias <span style="font-family: "courier new", "courier", monospace;">Int</span> maps to the 64-bit signed integer, <span style="font-family: "courier new", "courier", monospace;">Int64</span>, and the alias Byte maps to the 8-bit <b>unsigned</b> integer, <span style="font-family: "courier new", "courier", monospace;">UInt8</span>. (In Java, the <span style="font-family: "courier new", "courier", monospace;">byte</span> type is signed.)</li>
<li>Java also has some proprietary support for decimal values via the BigDecimal class.
Ecstasy provides standard 32-bit, 64-bit, 128-bit, and variable-length decimal
value support via the <span style="font-family: "courier new", "courier", monospace;">Dec32</span>, <span style="font-family: "courier new", "courier", monospace;">Dec64</span>, <span style="font-family: "courier new", "courier", monospace;">Dec128</span>, and <span style="font-family: "courier new", "courier", monospace;">VarDec</span> classes; these are implementations of the IEEE 754-2008 standard for decimal floating point.</li>
<li>Java's <span style="font-family: "courier new", "courier", monospace;">float</span> and <span style="font-family: "courier new", "courier", monospace;">double</span> represent 32-bit and 64-bit IEEE 754 binary floating point values. Ecstasy provides standard 16-bit, 32-bit, 64-bit, 128-bit, and variable-length IEEE 754 binary floating point values via the <span style="font-family: "courier new", "courier", monospace;">Float16</span>, <span style="font-family: "courier new", "courier", monospace;">Float32</span>, <span style="font-family: "courier new", "courier", monospace;">Float64</span>, <span style="font-family: "courier new", "courier", monospace;">Float128</span>, and <span style="font-family: "courier new", "courier", monospace;">VarFloat</span> classes. Additionally, Ecstasy provides the ML- and AI-optimized "brain float 16" type, via the <span style="font-family: "courier new", "courier", monospace;">BFloat16</span> class.</li>
<li>Java's primitive type system is based on a 32-bit word size. Ecstasy's does not have a primitive type system, and thus does not have a "word size", but in practice, Ecstasy defaults to using 64-bit integer, decimal, and binary floating point values.</li>
<li>In Java, the value "<span style="font-family: "courier new", "courier", monospace;">0</span>" is an <span style="font-family: "courier new", "courier", monospace;">int</span>. The compiler converts it, if necessary, to other types. In Ecstasy, the value "<span style="font-family: "courier new", "courier", monospace;">0</span>" is an <span style="font-family: "courier new", "courier", monospace;">IntLiteral</span>, which has the ability (both at compile-time and run-time) to convert to any numeric type. Unlike Java, there is no need for an "<span style="font-family: "courier new", "courier", monospace;">l</span>"/"<span style="font-family: "courier new", "courier", monospace;">L</span>" suffix on integers to inform the compiler that a value is a <span style="font-family: "courier new", "courier", monospace;">long</span>.</li>
<li>In Java, the value "<span style="font-family: "courier new", "courier", monospace;">0.0</span>" is a <span style="font-family: "courier new", "courier", monospace;">double</span>. In Ecstasy, the value "<span style="font-family: "courier new", "courier", monospace;">0.0</span>" is an <span style="font-family: "courier new", "courier", monospace;">FPLiteral</span>,
which has the ability (both at compile-time and run-time) to convert to
any decimal or binary floating point type. Unlike Java, there is no need for an "<span style="font-family: "courier new", "courier", monospace;">f</span>"/"<span style="font-family: "courier new", "courier", monospace;">F</span>" or "<span style="font-family: "courier new", "courier", monospace;">d</span>"/"<span style="font-family: "courier new", "courier", monospace;">D</span>" suffix to inform the compiler that a value is a 32-bit or 64-bit value.</li>
<li>Java supports the <span style="font-family: "courier new", "courier", monospace;">class</span>, <span style="font-family: "courier new", "courier", monospace;">enum</span>, and <span style="font-family: "courier new", "courier", monospace;">interface</span> keywords for declaring classes. Ecstasy supports these three keywords, plus: <span style="font-family: "courier new", "courier", monospace;">module</span>, <span style="font-family: "courier new", "courier", monospace;">package</span>, <span style="font-family: "courier new", "courier", monospace;">service</span>, <span style="font-family: "courier new", "courier", monospace;">mixin</span>, and <span style="font-family: "courier new", "courier", monospace;">typedef</span>.</li>
<li>Classes such as Int64, Float64, Dec64, Char, and String that are used to hold constant values are implemented in Ecstasy using the <span style="font-family: "courier new", "courier", monospace;">const</span> keyword instead of the class keyword. Instances of a <span style="font-family: "courier new", "courier", monospace;">const</span> class are automatically made immutable as part of their construction; specifically, no reference to an object of a <span style="font-family: "courier new", "courier", monospace;">const</span> class becomes visible until <i>after</i> the object is made immutable.</li>
<li>Ecstasy classes such as <span style="font-family: "courier new", "courier", monospace;">Nullable</span> and <span style="font-family: "courier new", "courier", monospace;">Boolean</span> are <i>enumerations</i>; enumerations are abstract classes that contain enum values, such as <span style="font-family: "courier new", "courier", monospace;">False</span> and <span style="font-family: "courier new", "courier", monospace;">True</span>. Enum values are singleton <span style="font-family: "courier new", "courier", monospace;">const</span> classes.</li>
<li>Ecstasy <span style="font-family: "courier new", "courier", monospace;">module</span> and <span style="font-family: "courier new", "courier", monospace;">package</span> classes are singleton <span style="font-family: "courier new", "courier", monospace;">const</span> classes, and are written like any other classes would be. Declarative modularity was recently introduced into Java via Project Jigsaw, with some similar goals. You can read more about <a href="https://xtclang.blogspot.com/2019/04/ecstasy-modules.html" target="_blank">Ecstasy modules</a> on this blog.</li>
<li>Java does not have any language capabilities similar to a <span style="font-family: "courier new", "courier", monospace;">service</span>, a <span style="font-family: "courier new", "courier", monospace;">mixin</span>, or a <span style="font-family: "courier new", "courier", monospace;">typedef</span> in Ecstasy. A <span style="font-family: "courier new", "courier", monospace;">service</span> class provides a boundary for concurrent and/or asynchronous behavior, so it can be thought of in the same manner as a Java thread; however, an Ecstasy application may have millions of service objects, while it is unlikely that so many threads would be desirable in any language. An Ecstasy <span style="font-family: "courier new", "courier", monospace;">mixin</span> provides cross-cutting functionality; in Java, some combination of boilerplate, delegation, and cut & paste would be used instead. An Ecstasy <span style="font-family: "courier new", "courier", monospace;">typedef</span> is a means to provide a name to a type that itself can be expressed using the type algebra of the Ecstasy language. You can read more about <a href="https://xtclang.blogspot.com/2019/07/composition.html" target="_blank">class composition</a> on this blog.</li>
</ul>
</div>
To put this into practice, consider this Java example:<br />
<blockquote class="tr_bq">
<pre style="background-color: white; color: black; font-size: 10.5pt;"><span style="font-family: "courier new", "courier", monospace;"><span style="color: navy; font-weight: bold;">package </span>com.mycompany.myproduct.gui;
<span style="color: navy; font-weight: bold;">class </span>Point
<span style="color: navy; font-weight: bold;">implements </span>Comparable<Point>
{
<span style="color: navy; font-weight: bold;">public </span>Point(<span style="color: navy; font-weight: bold;">int </span>x, <span style="color: navy; font-weight: bold;">int </span>y)
{
<span style="color: navy; font-weight: bold;">this</span>.x = x;
<span style="color: navy; font-weight: bold;">this</span>.y = y;
}
<span style="color: navy; font-weight: bold;">private final int </span>x;
<span style="color: navy; font-weight: bold;">private final int </span>y;
<span style="color: navy; font-weight: bold;">public int </span>getX()
{
<span style="color: navy; font-weight: bold;">return </span>x;
}
<span style="color: navy; font-weight: bold;">public int </span>getY()
{
<span style="color: navy; font-weight: bold;">return </span>y;
}
@Override
<span style="color: navy; font-weight: bold;">public int </span>hashCode()
{
<span style="color: navy; font-weight: bold;">return </span>x ^ y;
}
@Override
<span style="color: navy; font-weight: bold;">public boolean </span>equals(Object obj)
{
<span style="color: navy; font-weight: bold;">if </span>(obj <span style="color: navy; font-weight: bold;">instanceof </span>Point)
{
Point that = (Point) obj;
<span style="color: navy; font-weight: bold;">return this</span>.x == that.x && <span style="color: navy; font-weight: bold;">this</span>.y == that.y;
}
<span style="color: navy; font-weight: bold;">return false</span>;
}
@Override
<span style="color: navy; font-weight: bold;">public </span>String toString()
{
<span style="color: navy; font-weight: bold;">return </span><span style="color: green; font-weight: bold;">"Point{x=" </span>+ x + <span style="color: green; font-weight: bold;">", y=" </span>+ y + <span style="color: green; font-weight: bold;">"}"</span>;
}
@Override
<span style="color: navy; font-weight: bold;">public int </span>compareTo(Point that)
{
<span style="color: navy; font-weight: bold;">int </span>n = <span style="color: navy; font-weight: bold;">this</span>.x - that.x;
<span style="color: navy; font-weight: bold;">if </span>(n == <span style="color: blue;">0</span>)
{
<span style="color: navy; font-weight: bold;"></span>n = <span style="color: navy; font-weight: bold;">this</span>.y - that.y;
}
<span style="color: navy; font-weight: bold;">return </span>n;
}
}</span></pre>
</blockquote>
And here is the corresponding Ecstasy code:<br />
<blockquote class="tr_bq">
<pre style="background-color: white; color: black; font-size: 10.5pt;"><span style="font-family: "courier new", "courier", monospace;"><span style="color: navy; font-weight: bold;">const </span>Point(Int x, Int y);</span></pre>
</blockquote>
This particular example is dramatic, because the <span style="font-family: "courier new", "courier", monospace;">const</span> class declaration in Ecstasy <a href="https://github.com/xtclang/xvm/blob/master/ecstasy/src/main/x/Const.x">implies</a> automatic implementations of the <a href="https://github.com/xtclang/xvm/blob/master/ecstasy/src/main/x/Comparable.x"><span style="font-family: "courier new", "courier", monospace;">Comparable</span></a>, <a href="https://github.com/xtclang/xvm/blob/master/ecstasy/src/main/x/collections/Hashable.x"><span style="font-family: "courier new", "courier", monospace;">Hashable</span></a>, <a href="https://github.com/xtclang/xvm/blob/master/ecstasy/src/main/x/Orderable.x"><span style="font-family: "courier new", "courier", monospace;">Orderable</span></a>, and <a href="https://github.com/xtclang/xvm/blob/master/ecstasy/src/main/x/text/Stringable.x"><span style="font-family: "courier new", "courier", monospace;">Stringable</span></a> interfaces. Furthermore, the parameters specified at the class level declare two properties, and a constructor.<br />
<br />
Local variable declarations are similar, but the use of the comma as a general purpose separator (as in C) is not permitted. For example, in Java:<br />
<blockquote class="tr_bq">
<pre style="background-color: white; color: black; font-family: "menlo-regular"; font-size: 10.5pt;"><span style="font-family: "courier new", "courier", monospace;"><span style="color: navy; font-weight: bold;">int </span>a=<span style="color: blue;">0</span>, b=<span style="color: blue;">0</span>, c=<span style="color: blue;">0</span>;</span></pre>
</blockquote>
In Ecstasy, these would likely become separate declarations:<br />
<blockquote class="tr_bq">
<pre style="background-color: white; color: black; font-family: "menlo-regular"; font-size: 10.5pt;"><span style="font-family: "courier new", "courier", monospace;">Int a=<span style="color: blue;">0</span>;
Int b=<span style="color: blue;">0</span>;
Int c=<span style="color: blue;">0</span>;</span></pre>
</blockquote>
It is also possible (and occasionally necessary) to declare and initialize multiple left-hand-side variable ("L-values"); the above example could be written as:<br />
<blockquote class="tr_bq">
<pre style="background-color: white; color: black; font-size: 10.5pt;"><span style="font-family: "courier new", "courier", monospace;">(Int a, Int b, Int c) = (<span style="color: blue;">0</span>, <span style="color: blue;">0</span>, <span style="color: blue;">0</span>);</span></pre>
</blockquote>
Note that the left-hand-side is in the form of a tuple, and the right-hand-side has a corresponding tuple type. In this form, the type of each left-hand-side variable can differ, and a type is only specified when declaring a variable. For example, if a function "<span style="font-family: "courier new", "courier", monospace;">foo()</span>" exists that returns both an <span style="font-family: "courier new", "courier", monospace;">Int</span> <b>and</b> a <span style="font-family: "courier new", "courier", monospace;">String</span>, then the above-defined variable "<span style="font-family: "courier new", "courier", monospace;">c</span>" and a new String variable can be assigned as follows:<br />
<blockquote class="tr_bq">
<pre style="background-color: white; color: black; font-size: 10.5pt;"><span style="font-family: "courier new", "courier", monospace;">(c, String d) = foo();</span></pre>
</blockquote>
This introduces a dramatic difference in Ecstasy: Methods and functions can return more than one value, and those return values can be treated either as individual values, or as a tuple of values.<br />
<br />
Furthermore, method and function parameters can also be provided either as individual values, or as a tuple of values, <b>or as named values</b>. Consider this example in Java that uses multiple delegating constructors:<br />
<blockquote class="tr_bq">
<pre style="background-color: white; color: black; font-size: 10.5pt;"><span style="color: navy; font-weight: bold;">class </span>ErrorList
{
<span style="color: navy; font-weight: bold;">public </span>ErrorList(<span style="color: navy; font-weight: bold;">int </span>maxErrors)
{
<span style="color: navy; font-weight: bold;">this</span>(maxErrors, <span style="color: navy; font-weight: bold;">false</span>);
}
<span style="color: navy; font-weight: bold;">public </span>ErrorList(<span style="color: navy; font-weight: bold;">boolean </span>abortOnError)
{
<span style="color: navy; font-weight: bold;">this</span>(<span style="color: blue;">0</span>, abortOnError);
}
<span style="color: navy; font-weight: bold;">public </span>Example(<span style="color: navy; font-weight: bold;">int </span>max, <span style="color: navy; font-weight: bold;">boolean </span>abortOnError)
{
<span style="color: navy; font-weight: bold;">this</span>.max = max;
<span style="color: navy; font-weight: bold;">this</span>.abortOnError = abortOnError;
<span style="color: grey; font-style: italic;">// ...</span><span style="color: grey; font-style: italic;"> </span>
}
<span style="color: navy; font-weight: bold;">private int </span>max;
<span style="color: navy; font-weight: bold;">private boolean </span>abortOnError;
}
<span style="font-family: "courier new", "courier", monospace;"><span style="color: navy; font-weight: bold;"></span></span></pre>
</blockquote>
Using default parameter values, the Ecstasy equivalent of this example would not need all of those redundant constructors, each with slightly different signatures:<br />
<blockquote class="tr_bq">
<pre style="background-color: white; color: black; font-family: "menlo-regular"; font-size: 10.5pt;"><span style="font-family: "courier new", "courier", monospace;"><span style="color: navy; font-weight: bold;">class </span>ErrorList(Int max=<span style="color: blue;">0</span>, Boolean abortOnError=False)
{
<span style="color: grey; font-style: italic;">// ...</span><span style="color: grey; font-style: italic;"> </span></span>
<span style="font-family: "courier new", "courier", monospace;"> }</span>
</pre>
</blockquote>
And the class could then be constructed using any combination of named parameters, as in the following example:<br />
<blockquote class="tr_bq">
<pre style="background-color: white; color: black; font-size: 10.5pt;"><span style="font-family: "courier new", "courier", monospace;">ErrorList errs = <span style="color: navy; font-weight: bold;">new </span>ErrorList(abortOnError=True);</span></pre>
</blockquote>
For the most part, though, the Ecstasy syntax is designed to maintain a high level of compatibility with Java (and C#) syntax. One area in which the syntax differs is with respect to type assertions and type tests. In Java, the type test uses the relational operator "<span style="font-family: "courier new", "courier", monospace;">instanceof</span>", and the type assertion uses the C-style cast syntax, which often requires two sets of parenthesis, as in this Java code:<br />
<blockquote class="tr_bq">
<pre style="background-color: white; color: black; font-size: 10.5pt;"><span style="font-family: "courier new", "courier", monospace;"><span style="color: navy; font-weight: bold;">if </span>(x <span style="color: navy; font-weight: bold;">instanceof </span>List)
{
((List) x).add(item);
}</span></pre>
</blockquote>
Ecstasy simplifies this syntax dramatically by employing the dot notation that is already so naturally used for property access and method invocation. The "<span style="font-family: "courier new", "courier", monospace;">is</span>" keyword replaces "<span style="font-family: "courier new", "courier", monospace;">instanceof</span>", and the "<span style="font-family: "courier new", "courier", monospace;">as</span>" keyword replaces the awkward use of parenthesis for the type assertion (aka "type casting"):<br />
<blockquote class="tr_bq">
<pre style="background-color: white; color: black; font-family: "menlo-regular"; font-size: 10.5pt;"><span style="font-family: "courier new", "courier", monospace;"><span style="color: #660e7a; font-weight: bold;">if </span>(x.<span style="color: navy; font-weight: bold;">is</span>(List))
{
x.<span style="color: navy; font-weight: bold;">as</span>(List).add(item);
}</span></pre>
</blockquote>
This approach is far easier to read, because it follows left-to-right, with no precedence concerns. Furthermore, if the compiler determines that the value "<span style="font-family: "courier new", "courier", monospace;">x</span>"<span style="font-family: "courier new", "courier", monospace;"></span> is not subject to concurrent modification, then type inference obviates the need for the type-assertion altogether:<br />
<blockquote class="tr_bq">
<pre style="background-color: white; color: black; font-family: "menlo-regular"; font-size: 10.5pt;"><span style="font-family: "courier new", "courier", monospace;"><span style="color: #660e7a; font-weight: bold;">if </span>(x.<span style="color: navy; font-weight: bold;">is</span>(List))
{
x.add(item);
}</span></pre>
</blockquote>
Operator precedence also differs slightly from Java, in order to simplify more operators into left-to-right ordering and to resolve a number of cases in which parenthesis were awkwardly required in Java:<br />
<blockquote class="tr_bq">
<pre style="background-color: white; color: black; font-size: 10.5pt;">Operator Description Level Associativity
-------------- ---------------------- ----- -------------
& reference-of 1
++ post-increment 2 left to right
-- post-decrement
() invoke a method
[] access array element
? conditional
. access object member
.new postfix object creation
.as postfix type assertion
.is postfix type comparison
++ pre-increment 3 right to left
-- pre-decrement
+ unary plus
- unary minus
! logical NOT
~ bitwise NOT
?: conditional elvis 4 right to left
* multiplicative 5 left to right
/
% (modulo)
/% (divide with remainder)
+ additive 6 left to right
-
<< >> bitwise 7 left to right
>>>
&
^
|
.. range/interval 8 left to right
< <= relational 9 left to right
> >=
<=> order ("star-trek")
== equality 10 left to right
!=
&& conditional AND 11 left to right
^^ conditional XOR 12 left to right
|| conditional OR
? : conditional ternary 13 right to left
: conditional ELSE 14 right to left </pre>
</blockquote>
As you can see, a number of operators are grouped together, which previously each had their own precedence level; this implicitly employs left-to-right precedence for all operators within that grouping. Bitwise operators also have been moved to a significantly higher precedence level, which reduces the need for unnecessarily awkward parenthesization. Additionally, almost all operators map directly to methods, which means that explicit left-to-right behavior can be achieved by replacing a relational operator with the corresponding method invocation.<br />
<br />
(Continue to <a href="https://xtclang.blogspot.com/2020/01/coming-from-java-part-ii.html" target="_blank">Part II</a>.) </div>
xtclang (Ecstasy)http://www.blogger.com/profile/10099977807321312612noreply@blogger.com1tag:blogger.com,1999:blog-3316231033424903659.post-10172033071580259492019-10-13T17:30:00.000-04:002019-10-13T17:30:03.145-04:00More turtles<div dir="ltr" style="text-align: left;" trbidi="on">
The Ecstasy type system is called a <b>Turtles Type System</b>, because "<a href="https://en.wikipedia.org/wiki/Turtles_all_the_way_down" target="_blank"><i>it's turtles, the whole way down</i></a>". This is, in many ways, a revolutionary approach to type systems. Object type systems have traditionally had <i>primitive</i> <i>types</i> (like a "periodic table of elements" for the language) from which all other types are built, but in Ecstasy things are a bit different. For example, an Ecstasy integer is composed of an array of bits, each of which is composed of an integer literal (0 or 1), which is in turn composed of a string, which is composed of an array of characters, each of which is composed of an integer. So we're right back where we started, with an integer -- and you can just recurse infinitely, because the types are all turtles.<br />
<br />
Making a type system like this actually work is a challenge, so it didn't appear all at once. Recently, support for recursive type definitions was added, in order to support the JSON parsing project. Consider the following Ecstasy code:<br />
<br />
<pre style="background-color: white; color: black; font-family: 'Menlo-Regular'; font-size: 10.5pt;"><span style="font-family: "courier new" , "courier" , monospace;"><span style="color: grey; font-style: italic;">/**</span></span><span style="font-family: "courier new" , "courier" , monospace;"><span style="color: grey; font-style: italic;">
</span><span style="color: grey; font-style: italic;"> * JSON primitive types are all JSON values except for arrays and objects.</span></span><span style="font-family: "courier new" , "courier" , monospace;"><span style="color: grey; font-style: italic;">
</span><span style="color: grey; font-style: italic;"> */</span></span><span style="font-family: "courier new" , "courier" , monospace;"><span style="color: grey; font-style: italic;">
</span><span style="color: #006666; font-weight: bold;">typedef </span>(Nullable | Boolean | IntLiteral | FPLiteral | String) Primitive;</span>
<span style="font-family: "courier new" , "courier" , monospace;">
<span style="color: grey; font-style: italic;">/**</span></span><span style="font-family: "courier new" , "courier" , monospace;"><span style="color: grey; font-style: italic;">
</span><span style="color: grey; font-style: italic;"> * JSON types include primitive types, array types, and map types.</span></span><span style="font-family: "courier new" , "courier" , monospace;"><span style="color: grey; font-style: italic;">
</span><span style="color: grey; font-style: italic;"> */</span></span><span style="font-family: "courier new" , "courier" , monospace;"><span style="color: grey; font-style: italic;">
</span><span style="color: #006666; font-weight: bold;">typedef </span>(Primitive | Map<String, Doc> | Array<Doc>) Doc;</span></pre>
<br />
Here, <b>in two lines of code</b> (which could even be simplified to a single line, if we didn't want to split out primitive JSON values), we see a complete Ecstasy mapping of the <a href="https://www.json.org/" target="_blank">JSON specification</a>. That second <span style="font-family: "courier new" , "courier" , monospace;">typedef</span>, though, is a doozy, <i>because it refers to itself</i>. If you stop and read it carefully it makes a lot of sense: A JSON document is either a primitive value, a map of string keys to JSON values (each of which could be an entire recursive document structure), or an array of JSON values (each of which could be an entire recursive document structure).<br />
<br />
To keep it simple, consider the following example:<br />
<blockquote class="tr_bq">
<pre style="background-color: white; color: black; font-family: 'Menlo-Regular'; font-size: 10.5pt;"><span style="font-family: "courier new" , "courier" , monospace;"><span style="color: #006666; font-weight: bold;">typedef </span>(Int | List<Manifold>) Manifold;</span><span style="font-family: "courier new" , "courier" , monospace;">
</span><span style="font-family: "courier new" , "courier" , monospace;">
Manifold m1 = <span style="color: blue;">9</span>;
Manifold m2 = [m1];
Manifold m3 = [m2];
console.println(m1);
console.println(m2);
console.println(m3);</span></pre>
</blockquote>
When executed, this code will print:<br />
<blockquote class="tr_bq">
<span style="font-family: "courier new" , "courier" , monospace;">9<br />[9]<br />[[9]]</span></blockquote>
But the amazing thing isn't that it works at all, but rather that it works <i>with full type safety</i>.<br />
<br /></div>
xtclang (Ecstasy)http://www.blogger.com/profile/10099977807321312612noreply@blogger.com0tag:blogger.com,1999:blog-3316231033424903659.post-81214736202706406922019-08-01T18:45:00.001-04:002020-07-08T16:58:03.795-04:00Hello World!<div dir="ltr" style="text-align: left;" trbidi="on">
In retrospect, the most obvious missing feature of Ecstasy is the prototypical "Hello World!" example.<br />
<br />
The earliest adopters / experimenters / hackers who have been playing with Ecstasy for some time now were somehow able to divine the magic incantations necessary to get get code compiling and running (sometimes with help from our team), but it's time to make this process much easier.<br />
<br />
This won't be a single update; rather, it is a process -- of moving the project from a small team that knows all of the undocumented nooks and crannies, out into the public sphere. The initial experience with Ecstasy should not be as soul-sucking and psychologically scarring as a Google job interview. For a new user, it should be straight-forward to get started, and not some experience like an "obstacle course" or "running the gauntlet".<br />
<br />
To that end, we introduce step one, the Hello World:<br />
<blockquote class="tr_bq">
<pre style="background-color: white; color: black; font-family: "menlo-regular"; font-size: 9pt;"><span style="font-size: small;"><span style="font-family: "courier new", "courier", monospace;"><span style="color: navy; font-weight: bold;">module </span>HelloWorld
{
<span style="color: #006666; font-weight: bold;">void </span>run()
{
<span style="color: #660000; font-weight: bold;">@Inject </span>Console console;
console.println(<span style="color: green; font-weight: bold;">"Hello World!"</span>);
}
}</span></span></pre>
</blockquote>
Here's a short explanation of the code, which is found in <a href="https://github.com/xtclang/xvm/blob/master/xdk/src/main/resources/xdk/examples/HelloWorld.x"><span style="font-family: "courier new", "courier", monospace;">./xdk/src/main/resources/xdk/examples/HelloWorld.x</span></a>:<br />
<ul>
<li>A module is the unit of compilation, loading, linking, and execution, so we need to write one of those. Don't worry -- as you can see, it's easy.</li>
<li>The <span style="font-family: "courier new", "courier", monospace;">xec</span> command (which we'll cover below) looks for a method on the module called "run" that takes no parameters. (The module is a class, so "<span style="font-size: small;"><span style="font-family: "courier new", "courier", monospace;"><span style="color: #006666; font-weight: bold;">void </span>run()</span></span>" on the module is just a normal method.)</li>
<li>Ecstasy code is <i>purposefully incapable</i> of doing <i>any</i> I/O; for security reasons, there is nothing in the language (or in the compiled form of the language) that has any access to any hardware or OS resource. As a result, the code must depend on its container to provide something that implements the <span style="font-family: "courier new", "courier", monospace;">Console</span> interface; this is called <i>injection</i>. The behavior of the console that is injected by the <span style="font-family: "courier new", "courier", monospace;">TestConnector</span> is to print to <span style="font-family: "courier new", "courier", monospace;">stdout</span>.</li>
<li>The declaration "<span style="font-size: small;"><span style="font-family: "courier new", "courier", monospace;"><span style="color: #660000; font-weight: bold;">@Inject </span>Console console;</span></span>" declares a read-only variable called <span style="font-size: small;"><span style="font-family: "courier new", "courier", monospace;">console</span></span>, and when it is de-referenced. it will always have a value that is a <span style="font-size: small;"><span style="font-family: "courier new", "courier", monospace;"><span style="color: #660000; font-weight: bold;"></span>Console</span></span>. (It is a contract; if the container could not -- or chose not to -- provide a <span style="font-size: small;"><span style="font-family: "courier new", "courier", monospace;"><span style="color: #660000; font-weight: bold;"></span>Console</span></span>, then the creation of the container itself would have failed.)</li>
<li>Hopefully, the line that prints out <span style="font-size: small;"><span style="font-family: "courier new", "courier", monospace;"><span style="color: green; font-weight: bold;">"Hello World!"</span></span></span> is self-explanatory.</li>
</ul>
</div><div dir="ltr" style="text-align: left;" trbidi="on">Here are the steps to getting this running:</div><div dir="ltr" style="text-align: left;" trbidi="on"><ul><li>The git utility is used for downloading project code. Open a terminal window (aka <i>command window</i> aka <i>shell</i>) and type "<span style="font-family: courier;">git</span>" to verify that you have it installed and working. If you don't, then you can <a href="https://git-scm.com/downloads">get git</a>; if you develop on a Mac, git is already included in the <a href="https://developer.apple.com/download/more/">Command Line Tools for XCode</a>.</li><li>Java is used to run the current Ecstasy toolchain, and version 11 (or later) of the JDK is required. Open a terminal window, and type "<span style="font-family: courier;">java -version</span>" to verify that you have the necessary version of Java installed. If necessary, you can download the free <a href="https://docs.aws.amazon.com/corretto/latest/corretto-11-ug/downloads-list.html" target="_blank">JDK 11 from the Amazon Corretto project</a>, for example.</li><li>We strongly encourage you to <a href="https://www.jetbrains.com/idea/download/" target="_blank">download IntelliJ IDEA</a>, if you don't already use it. (Or update it to the latest version, if you already use it.) Since Ecstasy is an open source project on GitHub, you can use the "Community" edition of IDEA. (We do think that it is an IDE worth paying for, so don't be afraid to splurge on the "Ultimate" edition!)</li>
<li>Determine a location to create a local repository for the XVM project. The rest of these instructions will assume Unix style paths and an installation location of <span style="font-family: courier;">~/Development/xvm</span>, but if you're on Windows, just create an XVM project directory somewhere, e.g. <span style="font-family: courier;">Development\xvm</span> under your user directory.</li><li>From the terminal, in that XVM directory, execute: <span style="background-color: #eeeeee;"><span style="font-family: courier;">git clone https://github.com/xtclang/xvm.git</span></span> This will take a few seconds (maybe minutes) to completely clone the project into your XVM directory.</li><li>Next, use the Gradle wrapper to build a local copy of the Ecstasy development kit (XDK) with the following command: <span style="background-color: #eeeeee;"><span style="font-family: courier;">./gradlew build</span></span> (or <span style="background-color: #eeeeee;"><span style="font-family: courier;">gradlew.exe build</span></span> on Windows) This will take a minute or so to completely build the XDK.</li><li>The XDK is built under the <span style="font-family: courier;">./xdk</span> project directory under your XVM directory, specifically <span style="font-family: courier;">./xdk/build/xdk sub-directory</span>. You can copy the built XDK to a location of your choosing, but for these instructions, we will leave it in the location in which it was built.</li><li>To configure the toolchain for your OS, execute the appropriate command in the <span style="font-family: courier;">bin</span> directory of the XDK; for example, on macOS, execute <span style="background-color: #eeeeee;"><span style="font-family: courier;">. ./xdk/build/xdk/bin/cfg_macos.sh</span></span>. (Notice the dot and space at the beginning of the command; this is called a "source command" in Bash. Unfortunately, this does not work with the <span style="font-family: courier;">zsh</span> shell that is now the default on macOS, so you have to run <span style="background-color: #eeeeee;"><span style="font-family: courier;">./xdk/build/xdk/bin/cfg_macos.sh</span></span> without the preceding source command, and then manually update the <span style="font-family: courier;">PATH</span> to add <span style="background-color: #eeeeee;"><span style="font-family: courier;">./xdk/build/xdk/bin</span></span>.)<br /></li><li>Now you can use the <span style="font-family: courier;">xtc</span>, <span style="font-family: courier;">xec</span>, and <span style="font-family: courier;">xam</span> commands from the terminal. On some operating systems, if these executable files are not signed and/or notarized, you may get an error or a warning the first time that you run them. For example, macOS includes a program called GateKeeper <a href="https://support.apple.com/en-us/HT202491">that may need to be configured</a> to allow these programs to be executed.</li><li>Each time that you open a new terminal window, you will need to execute the OS-specific configuation script to update the <span style="font-family: courier;">PATH</span> variable; alternatively, you can configure your OS to automatically update the <span style="font-family: courier;">PATH</span> for you, but the complexity of that topic is immense, and beyond the scope of this document. (On macOS and Linux, one normally would create a <span style="font-family: courier;">.profile</span> file in one's home directory and add one line that says e.g. <span style="background-color: #eeeeee;"><span style="font-family: courier;">export PATH=$PATH:~/xvm/xdk/build/xdk/bin</span></span>, but there are pages of conversation to read through on StackOverflow for when this simple approach fails to work for your configuration.)</li><li>To compile the HelloWorld example, use the <span style="font-family: courier;">xtc</span> command: <span style="background-color: #eeeeee;"><span style="font-family: courier;">xtc ./xdk/build/xdk/examples/HelloWorld.x</span></span></li><li>The compiler places the compiled <span style="font-family: courier;">.xtc</span> file into the current directory (which in this case is probably where you don't want it, but for the sake of this example, we'll ignore this detail). To execute the program: <span style="background-color: #eeeeee;"><span style="font-family: courier;">xec HelloWorld.xtc</span></span></li></ul>And if all went well, you should see: <br /></div><div dir="ltr" style="text-align: left;" trbidi="on"><span style="font-size: small;"><span style="font-family: "courier new", "courier", monospace;"><blockquote><span style="color: green; font-weight: bold;">Hello World!</span></blockquote></span></span>
<ol>
</ol>
</div>
xtclang (Ecstasy)http://www.blogger.com/profile/10099977807321312612noreply@blogger.com0tag:blogger.com,1999:blog-3316231033424903659.post-11143027681388577972019-07-14T15:30:00.001-04:002020-07-08T10:18:11.821-04:00Composition<div dir="ltr" style="text-align: left;" trbidi="on">
In an OO language, one of the first questions to ask is how classes and types are <i>composed</i>. Sometimes, when looking at a new language, it's easy to get side-tracked by clever syntax, or syntactic "features", but while these are ultimately important, there is nothing more important in a language than being able to describe the <i>shape</i> of what one is building.<br />
<br />
<br />
Ecstasy provides three basic shapes from which classes are composed:<br />
<ul style="text-align: left;">
<li>Classes, which (just like in Java and C#) are useful for defining instantiable combinations of state and behavior.</li>
<li>Interfaces, which (just like in Java and C#) are useful for defining contracts, and may allow default behavior to be defined.</li>
<li>Mixins, which are used to define <i>cross-cutting</i> functionality. </li>
</ul>
One example of each of these from the core library is the <span style="font-family: "courier new", "courier", monospace;"><a href="https://github.com/xtclang/xvm/blob/master/ecstasy/src/main/x/Range.x">Range</a></span> class, the <span style="font-family: "courier new", "courier", monospace;"><a href="https://github.com/xtclang/xvm/blob/master/ecstasy/src/main/x/Sequential.x">Sequential</a></span> interface, and the <span style="font-family: "courier new", "courier", monospace;"><a href="https://github.com/xtclang/xvm/blob/master/ecstasy/src/main/x/Interval.x">Interval</a></span> mixin. Consider this simple example:<br />
<br />
<blockquote class="tr_bq">
<pre style="background-color: white; color: black; font-family: "menlo-regular"; font-size: 10.5pt;"><span style="font-family: "courier new", "courier", monospace;"><span style="font-size: small;"><span style="color: #660e7a; font-weight: bold;">for </span>(Int i : <span style="color: blue;">10</span>..<span style="color: blue;">20</span>)
{
<span style="color: grey; font-style: italic;">// do something</span></span></span><span style="font-family: "courier new", "courier", monospace;"><span style="font-size: small;"><span style="color: grey; font-style: italic;"><span style="font-family: "courier new", "courier", monospace;"><span style="font-size: small;"><span style="color: grey; font-style: italic;">
</span><span style="color: grey; font-style: italic;"> </span></span></span></span><span style="color: grey; font-style: italic;"></span>}</span></span></pre>
</blockquote>
The expression "<span style="font-family: "courier new", "courier", monospace;">10..20</span>" is an <span style="font-family: "courier new", "courier", monospace;">Range</span>; it defines a "from value" and a "to value". The only requirement of a range is that its type must be <span style="font-family: "courier new", "courier", monospace;"><a href="https://github.com/xtclang/xvm/blob/master/ecstasy/src/main/x/Orderable.x">Orderable</a></span>, which is the funky interface that allows two objects to be compared for purposes of ordering.<br />
<br />
The ability of a type to be ordered is a <i>necessary but insufficient</i> capability for iteration, which is what the <span style="font-family: "courier new", "courier", monospace;">for</span> loop requires, and if you examine the <span style="font-family: "courier new", "courier", monospace;"><a href="https://github.com/xtclang/xvm/blob/master/ecstasy/src/main/x/Range.x">Range</a></span> class closely, you will notice that it does <b>not</b> implement <a href="https://github.com/xtclang/xvm/blob/master/ecstasy/src/main/x/Iterable.x"><span style="font-family: "courier new", "courier", monospace;">Iterable</span></a>. What it does, instead, is this:<br />
<blockquote class="tr_bq">
<pre style="background-color: white; color: black; font-family: "menlo-regular"; font-size: 10.5pt;"><span style="font-size: small;"><span style="font-family: "courier new", "courier", monospace;"><span style="color: navy; font-weight: bold;">const </span>Range<Element <span style="color: navy; font-weight: bold;">extends </span>Orderable>
<span style="color: navy; font-weight: bold;">incorporates </span><span style="color: #006666; font-weight: bold;">conditional </span>Interval<Element <span style="color: navy; font-weight: bold;">extends </span>Sequential></span></span></pre>
</blockquote>
Translated into English, that reads: "<i>A range is a constant that contains elements, which must be of an orderable type. Additionally, for ranges whose elements are of a sequential type, the range will automatically incorporate the capabilities of an interval.</i>"<br />
<br />
Think of the <span style="font-family: "courier new", "courier", monospace;"><a href="https://github.com/xtclang/xvm/blob/master/ecstasy/src/main/x/Sequential.x">Sequential</a></span> interface as the type that is necessary to support the "<span style="font-family: "courier new", "courier", monospace;">++</span>" and "<span style="font-family: "courier new", "courier", monospace;">--</span>" operators (pre-/post- increment/decrement). When a range of a sequential type is constructed, the <i>composition</i> of the range <i>incorporates</i> the <span style="font-family: "courier new", "courier", monospace;">Interval</span> mixin, which in turn, being iterable, provides an iterator that can be used by the <span style="font-family: "courier new", "courier", monospace;">for</span> loop.<br />
<br />
A range of a non-sequential type cannot be iterated over, and an attempt to do so is detected by the compiler:<br />
<blockquote class="tr_bq">
<pre style="background-color: white; color: black; font-family: "menlo-regular"; font-size: 10.5pt;"><span style="font-family: "courier new", "courier", monospace;"><span style="font-size: small;"><span style="color: #660e7a; font-weight: bold;">for </span>(String s : "hello"<span style="color: blue;"></span>.."world"<span style="color: blue;"></span>) // compiler error
{
<span style="color: grey; font-style: italic;">// do somethin</span></span></span><span style="font-family: "courier new", "courier", monospace;"><span style="font-size: small;"><span style="color: grey; font-style: italic;"><span style="font-family: "courier new", "courier", monospace;"><span style="font-size: small;"><span style="color: grey; font-style: italic;">g</span></span></span><span style="font-family: "courier new", "courier", monospace;"><span style="font-size: small;"><span style="color: grey; font-style: italic;"><span style="font-family: "courier new", "courier", monospace;"><span style="font-size: small;"><span style="color: grey; font-style: italic;">
</span><span style="color: grey; font-style: italic;"></span></span></span></span></span></span> </span>}</span></span></pre>
</blockquote>
In the "<span style="font-family: "courier new", "courier", monospace;">const Interval</span>" declaration shown above, the keyword used to declare the class was "<span style="font-family: "courier new", "courier", monospace;">const</span>". To declare a class (in the abstract sense of the term), Ecstasy provides eight keywords:<br />
<ul style="text-align: left;">
<li><span style="font-family: "courier new", "courier", monospace;">module</span> is used to declare a unit of compilation, or a unit of deployment. Java has a related concept, also called a module, and C# uses the term <i>assembly</i>. A <span style="font-family: "courier new", "courier", monospace;">module</span> is a singleton <span style="font-family: "courier new", "courier", monospace;">const</span> class; see <a href="https://xtclang.blogspot.com/2019/04/ecstasy-modules.html" target="_blank">Modules Overview</a>.</li>
<li><span style="font-family: "courier new", "courier", monospace;">package</span> is used to declare a namespace within a module, which is kind of like creating a directory within a file system. Like <span style="font-family: "courier new", "courier", monospace;">module</span>, a <span style="font-family: "courier new", "courier", monospace;">package</span> is also a singleton <span style="font-family: "courier new", "courier", monospace;">const</span> class.</li>
<li><span style="font-family: "courier new", "courier", monospace;">class</span> is used to declare any class that is not specialized as either a <span style="font-family: "courier new", "courier", monospace;">const</span> or a <span style="font-family: "courier new", "courier", monospace;">service</span>. Classes may be made immutable at run-time, but may not be singletons. For example, see <a href="https://github.com/xtclang/xvm/blob/master/ecstasy/src/main/x/collections/ListMap.x"><span style="font-family: "courier new", "courier", monospace;">ListMap</span></a>.</li>
<li><span style="font-family: "courier new", "courier", monospace;">const</span> is used to declare a class that is immutable by the time that it finishes construction. Furthermore, it automatically provides implementations of a number of common interfaces, including both <span style="font-family: "courier new", "courier", monospace;">Orderable</span>, <span style="font-family: "courier new", "courier", monospace;">Hashable</span>, and <span style="font-family: "courier new", "courier", monospace;">Stringable</span>. Consts can be singletons, and are always immutable. For example, see <a href="https://github.com/xtclang/xvm/blob/master/ecstasy/src/main/x/numbers/Int64.x"><span style="font-family: "courier new", "courier", monospace;">Int64</span></a>, aka <span style="font-family: "courier new", "courier", monospace;">Int</span>.</li>
<li><span style="font-family: "courier new", "courier", monospace;">enum</span> is used to declare an enumeration of values. The enumeration itself is an abstract <span style="font-family: "courier new", "courier", monospace;">const</span>, and each <span style="font-family: "courier new", "courier", monospace;">enum</span> value is a singleton <span style="font-family: "courier new", "courier", monospace;">const</span>. For example, see <a href="https://github.com/xtclang/xvm/blob/master/ecstasy/src/main/x/Boolean.x"><span style="font-family: "courier new", "courier", monospace;">Boolean</span></a>.</li>
<li><span style="font-family: "courier new", "courier", monospace;">service</span> is used to declare a potentially asynchronous object, <i>conceptually</i> similar to a Java or C# thread, but in many ways, much closer to an Erlang <i>process</i>. Services may be singletons, and may not be immutable. There aren't any good examples of <span style="font-family: "courier new", "courier", monospace;">service</span> in the core library, but the <a href="https://github.com/xtclang/xvm/blob/master/manualTests/src/main/x/services.x"><span style="font-family: "courier new", "courier", monospace;">services.x</span></a> test highlights the asynchronous and continuation-based behaviors of the service, using both an explicit <span style="font-family: "courier new", "courier", monospace;">Future</span>-style programming model, and the implicit async/await style.</li>
<li><span style="font-family: "courier new", "courier", monospace;">interface</span> defines just the surface area (the API) of a class, and may include default implementations of that API.</li>
<li><span style="font-family: "courier new", "courier", monospace;">mixin</span> declares a cross-cutting composition that can be incorporated into another composition.</li>
</ul>
Each of these, and the forms of composition available to each, will be covered in more detail in subsequent articles. In the meantime, if you're curious about the raw syntax, see <a href="https://github.com/xtclang/xvm/blob/master/doc/bnf.x">bnf.x</a>, and if you're curious about how the parsing of the syntax works, see <span style="font-family: "courier new", "courier", monospace;">parseTypeCompositionComponent()</span> in the <a href="https://github.com/xtclang/xvm/blob/master/javatools/src/main/java/org/xvm/compiler/Parser.java"><span style="font-family: "courier new", "courier", monospace;">Parser</span></a>. The AST node for type compositions is <a href="https://github.com/xtclang/xvm/blob/master/javatools/src/main/java/org/xvm/compiler/ast/TypeCompositionStatement.java"><span style="font-family: "courier new", "courier", monospace;">TypeCompositionStatement</span></a>.</div>
xtclang (Ecstasy)http://www.blogger.com/profile/10099977807321312612noreply@blogger.com4tag:blogger.com,1999:blog-3316231033424903659.post-17618313727061948142019-07-13T11:15:00.001-04:002020-07-08T09:36:34.103-04:00A pane in the glass<div dir="ltr" style="text-align: left;" trbidi="on">
One of the best visual metaphors for object systems is a pane of glass. Imagine having a pane of glass and a red dry-erase marker; use that marker to draw and fill in some small circles on the glass. Now, take another pane of glass, and using a blue dry-erase marker this time, do the same thing, and then set that second pane on top of the first one. When you look through the panes from above, you see these small circles circles from both panes, almost as if they were on one pane.<br />
<br />
One of these circles represents a <i>virtual behavior</i>. A virtual method, for example. Imagine that the pane of glass is magically subdivided as a grid, and those circles were magically located within the cells of that grid. Now, as you look through those two panes of glass together, those red circles that you see are methods implemented on the<i> base class</i>, and the blue circles are methods implemented on the<i> derived class</i>, because we put the red on the bottom (the base), and the blue overlaid it. And perhaps you might see some purple circles, representing methods that exist on the base class and are <i>overridden</i> on the derived class.<br />
<br />
We can repeat the experiment with another pane of glass, and a yellow marker, but at this point, it's getting very difficult to hold and juggle all of this glass, so we need a special holder for these panes of glass. Since this experiment is in our mind's eye, we can instantly build whatever we need to hold these (and many more) panes of glass. We need something almost like the adjustable shelves in an oven -- a sort of "glass shelf system" that allows us to slide any pane-of-glass into, and pull any pane-of-glass out of this holder. We construct it to be free standing, so that we can look through it from above, and we build it with a light source beneath it that helps to provide illumination through our panes of glass. What we have now is our collection of panes of glass, any of which might have those colored circles laid out in a grid, and we can now appreciate our beautiful coloring job when we look down through all of that glass, from above.<br />
<br />
It is tedious to build such a thing in our head, but it serves a most excellent purpose, for now we are all looking at the same thing together, and sharing words that have meaning <i>because we are looking at the same thing</i>.<br />
<br />
For example, when we use the term <i>method identity</i>, we are referring to a pair (x,y) of coordinates that identify a location (a cell) in the grid on the glass. (In the real world, we know that a method has other means of identifying itself, such as a name and perhaps some information about its parameters, but in our mind's eye, it's far simpler to draw circles on a grid on glass with dry erase markers.)<br />
<br />
And when we say that there is <i>no such method</i>, we mean that we look from above through the grid and there is no color in a particular cell -- not on the top pane of glass, but also not on any pane of glass under it.<br />
<br />
And when we talk about a <i>virtual method invocation</i>, we mean that for a method identity (a cell location in the grid) in which we can see a color circle from above, we slide out the top pane of glass and see if the cell in question has a circle on this top pane of glass, and if it does, that circle represents the behavior (the code) of that method to execute. If on the other hand, it does not have a circle in that cell, then we slide the glass back into its shelf, we pull out the next piece of glass, we examine it, and we keep repeating this process until we find the first piece of glass that has a circle in that cell.<br />
<br />
And when we talk about a <i>super method invocation</i>, what we mean is that during the execution of that code, if the code refers to its <i>super</i>, it is referring to the next circle that we would find if we were to go back and continue pulling out those glass shelves one by one and examining them, as we were when we performed the original virtual method invocation. If in doing so, we get to the last piece of glass and we have not found that circle, we would say that <i>there is no super</i>. If on the other hand we find that circle on a subsequent piece of glass, then that circle represents the super -- the code of the super method to execute.<br />
<br />
And when we talk about a <i>method chain</i>, we are referring to that first circle that we found for the virtual method invocation, and also its super, and also <i>its</i> super, until we get to the end and there are no more supers. That sequence of circles is the method chain.<br />
<br />
That's quite a vocabulary that we have developed, but it is invaluable in designing and discussing how an object system works. More importantly, it's fundamental to understanding the next concept, because the concept we're about to describe doesn't yet exist outside of the Ecstasy language. In <a href="https://xtclang.blogspot.com/2019/06/the-quest-for-equality.html" target="_blank">The Quest for Equality</a>, we introduced a notion of equality that is unlike any that can be found today in other languages. It is neither virtual (since it based on a <i>function</i>, not a <i>virtual method</i>), nor is it static (since it is based on run-time type information), nor is it dynamic (since the type information reflects the declared compile-time type information). So what is it, then?<br />
<br />
Equality is an example of a <i>funky interface</i>. It is like a interface type (a C++ <i>pure virtual class</i>, or a Java/C# <i>interface</i>) in many ways, except that we do not stand over the panes of glass and look for a method in the manner that we described above. No, a funky interface is different, because <i>it knows which pane of glass it refers to</i>.<br />
<br />
First, in terms of <i>implementing</i> a funky interface, what it means is that the pane of glass on which the implementation occurs will (and must) contain a colored-in circle for each of the <i>functions</i> (not methods) of the funky interface. (By now, you must be realizing how the <i>funky interface</i> got its name.) So when we slide out the pane of glass for a an <span style="font-family: "courier new", "courier", monospace;"><a href="https://github.com/xtclang/xvm/blob/master/ecstasy/src/main/x/Orderable.x">Orderable</a></span> implementation, we will see both the <span style="font-family: "courier new", "courier", monospace;">equals</span> and the <span style="font-family: "courier new", "courier", monospace;">compare</span> function circles colored in.<br />
<br />
Second, in terms of <i>using</i> a funky interface, that <i>compile-time type</i> being compared-for-order (the <span style="font-family: "courier new", "courier", monospace;"><a href="https://github.com/xtclang/xvm/blob/master/ecstasy/src/main/x/Orderable.x">Orderable</a></span> interface) represents the slot of the pane of glass that we will find that <span style="font-family: "courier new", "courier", monospace;">compare</span> function on. But it is not necessary that every pane of glass have that function for the type to be orderable. Instead, we begin at that pane of glass, and check if it implements that funky interface, and if it does not, then we proceed to the next lower pane of glass, until we find the one that does.<br />
<br />
Remember when we said that an implementation of a funky interface <b>must</b> contain a colored-in circle for every one of the functions from the funky interface? That is because a funky interface represents a <i>tight coupling</i> of related functions. The Orderable example above is a good one, because both the <span style="font-family: "courier new", "courier", monospace;">equals</span> and the <span style="font-family: "courier new", "courier", monospace;">compare</span> function use some concept, some definition of <i>equality</i>, and thus if one changes, we must expect that the other changes as well.<br />
<br />
But there are a few other obvious examples, such as <span style="font-family: "courier new", "courier", monospace;"><a href="https://github.com/xtclang/xvm/blob/master/ecstasy/src/main/x/collections/Hashable.x">Hashable</a></span>: If you change the definition of equals, then you must also make sure that the hash code calculation for two equal objects produces the same result for each, and vice versa. Thus <span style="font-family: "courier new", "courier", monospace;">Hashable</span> is a funky interface with those two functions, <span style="font-family: "courier new", "courier", monospace;">equals</span> and <span style="font-family: "courier new", "courier", monospace;">hashCode</span>.<br />
<br />
And since equals shows up in both <span style="font-family: "courier new", "courier", monospace;"><a href="https://github.com/xtclang/xvm/blob/master/ecstasy/src/main/x/collections/Hashable.x">Hashable</a></span> and <span style="font-family: "courier new", "courier", monospace;"><a href="https://github.com/xtclang/xvm/blob/master/ecstasy/src/main/x/Orderable.x">Orderable</a></span>, if one is to implement those two funky interfaces, then it is clear that filling in any one of those circles on a pane of glass requires filling in them all. And this allows the compiler to detect when a higher pane of glass attempts to fill in just some subset of those circles, which would naturally lead to errors in the running program. In other words, derived types must continue to respect the contracts from the funky interfaces of the base types.<br />
<br />
Because to do otherwise would be a pane.</div>
xtclang (Ecstasy)http://www.blogger.com/profile/10099977807321312612noreply@blogger.com0tag:blogger.com,1999:blog-3316231033424903659.post-5486883473474682242019-07-11T15:00:00.000-04:002019-07-11T15:00:01.048-04:00If it QuacksEcstasy supports both type tests and type assertions. In most languages, a type assertion is called a <i>cast</i>, which may result in a compiler error or (in the case of languages with run-time type information) a run-time exception. A type assertion in Ecstasy is a run-time, type-safe operation, and importantly, can be expressed as an explicitly-left-associative operation:<br />
<blockquote class="tr_bq">
<span style="font-family: "Courier New", Courier, monospace;">String foo(Object o)</span><br />
<span style="font-family: "Courier New", Courier, monospace;"> {</span><br />
<span style="font-family: "Courier New", Courier, monospace;"> return o.<b>as</b>(String); // could throw TypeMismatch</span><br />
<span style="font-family: "Courier New", Courier, monospace;"> } </span></blockquote>
Languages with run-time type information usually provide an additional, non-asserting means to test for a particular type <i>at run-time</i>, such as the Java <span style="font-family: "Courier New", Courier, monospace;">instanceof</span> binary operator, or the C# <span style="font-family: "Courier New", Courier, monospace;">is</span> binary operator. A type test in Ecstasy can be performed as an explicitly-left-associative operation:<br />
<blockquote class="tr_bq">
<span style="font-family: "Courier New", Courier, monospace;">String foo(Object o)</span><br />
<span style="font-family: "Courier New", Courier, monospace;"> {</span><br />
<span style="font-family: "Courier New", Courier, monospace;"> return o.<b>is</b>(String)</span><span style="font-family: "Courier New", Courier, monospace;"><span style="font-family: "Courier New", Courier, monospace;"> ? o : "hello, world!"</span>;</span><br />
<span style="font-family: "Courier New", Courier, monospace;"> } </span></blockquote>
Normally, an object cannot be <i>of a certain type</i>, unless it is explicitly declared to be of that type. For example, even if the imaginary class <span style="font-family: "Courier New", Courier, monospace;">FakeString</span> has all of the same properties and methods as the <span style="font-family: "Courier New", Courier, monospace;">String</span> class, instances of <span style="font-family: "Courier New", Courier, monospace;">FakeString</span> cannot be cast to a <span style="font-family: "Courier New", Courier, monospace;">String</span>.<br />
<br />
Some languages do support such a thing, however. It's called <a href="https://en.wikipedia.org/wiki/Duck_typing" target="_blank">duck typing</a>, because "<i>if it walks like a duck, and quacks like a duck, then it's a duck</i>". An early prototype of Ecstasy had this feature for all types, and even provided a composition keyword, <span style="font-family: "Courier New", Courier, monospace;">impersonates</span>, to automate the composition of ducks and duck-like creatures. However, the capability did not mesh well with the design of the class-based portion of the type system, and was ultimately rejected for its unanswerable questions and potential incompatibilities.<br />
<br />
Because duck typing is so useful, especially when working across the boundaries of loosely-coupled modules, one aspect of duck typing was explicitly retained: The ability to duck-type an <span style="font-family: "Courier New", Courier, monospace;">interface</span>. In many ways, an Ecstasy interface is simply a <i>named type</i>, i.e. a type plus a name. (This is not <i>strictly</i> true, but for this conversation, it will suffice.) And thus, in Ecstasy, one can make a Gosling Duck:<br />
<blockquote class="tr_bq">
<pre style="background-color: white; color: black; font-family: 'Menlo-Regular'; font-size: 9.0pt;"><span style="font-size: small;"><span style="font-family: "Courier New", Courier, monospace;"><span style="color: navy; font-weight: bold;">interface </span>Duck
{
<span style="color: #006666; font-weight: bold;">void </span>waddle();
<span style="color: #006666; font-weight: bold;">void </span>quack();
}
<span style="color: navy; font-weight: bold;">class </span>Gosling
{
<span style="color: #006666; font-weight: bold;">void </span>waddle() {}
<span style="color: #006666; font-weight: bold;">void </span>quack() {}
}
Duck foo(Gosling james)
{
<span style="color: #660e7a; font-weight: bold;">return </span>james;
}</span></span></pre>
</blockquote>
(<i>No ducks were harmed in the making of this blog entry.</i>)xtclang (Ecstasy)http://www.blogger.com/profile/10099977807321312612noreply@blogger.com0tag:blogger.com,1999:blog-3316231033424903659.post-40307817254730699482019-07-10T18:15:00.000-04:002019-07-10T18:15:09.992-04:00Literally awesome!<div dir="ltr" style="text-align: left;" trbidi="on">
Ecstasy supports a rich set of literals -- too much to cover in a single post, so consider this the first installment. It's important to lay out, up front, why a language supports literals, and what its goals are for the design in doing so.<br />
<br />
First, when building a language, literals are often <i>terminal constructs</i>, such that other things in the language can be composed of them.<br />
<br />
Second, a literal allows an efficient, human-readable encoding of information. For example, for most of us, it is far easier to read the number <span style="font-family: "courier new" , "courier" , monospace;">42</span> than something like:<span style="font-family: "courier new" , "courier" , monospace;"><span style="color: blue;"> </span></span><br />
<br />
<span style="font-family: "courier new" , "courier" , monospace;"><span style="color: blue;">new</span> Byte(false, </span><span style="font-family: "courier new" , "courier" , monospace;"><span style="font-family: "courier new" , "courier" , monospace;">false, </span>true, false, true, false, true, false)</span><br />
<br />
Ecstasy's design goals for literals are fairly straight-forward:<br />
<ol style="text-align: left;">
<li>Common constant types supported by the core runtime library <i>should </i>have a literal form. Examples include: Bits, nibbles, bytes, binary strings, integers, characters, character strings, dates, times, date/times, time durations, etc.</li>
<li>Common complex types supported by the core runtime library <i>should </i>have a literal form. Examples include: Tuples, arrays, lists, sets, and maps (aka directories).</li>
<li>Literal formats should emphasize readability, and the formats should be fairly obvious to a programmer.</li>
<li>It should be easy to work with literal formats using only a text editor.</li>
<li>Literals should make common programming tasks simpler, where possible.</li>
</ol>
<span style="font-size: large;">Integers</span><br />
A "whole number", or an integer, starts with an optional sign, followed by an optional radix indicator (such as "<span style="font-family: "courier new" , "courier" , monospace;">0b</span>" for binary, "<span style="font-family: "courier new" , "courier" , monospace;">0o</span>" for octal, or "<span style="font-family: "courier new" , "courier" , monospace;">0x</span>" for hex), followed by the digits of the appropriate radix, with optional underscores between digits to separate digits as desired. The BNF is in the language specification, but the simple explanation above should suffice. Here are some examples:<br />
<blockquote class="tr_bq">
<span style="font-family: "courier new" , "courier" , monospace;">0<br />-1<br />42<br />0xFF<br />0b10_1010_1010_1010_1010<br />12345678901234567890123456789012345678901234567890</span> </blockquote>
So, what is the type of each of the above? A 32-bit "int"? A 64-bit "int"? No. Each of the above is an <span style="font-family: "courier new" , "courier" , monospace;">IntLiteral</span>, a <span style="font-family: "courier new" , "courier" , monospace;">const</span> class. Just think of <span style="font-family: "courier new" , "courier" , monospace;">IntLiteral</span> as an object that has a good idea how to look on the screen, and simultaneously knows what values of various numeric types it can represent. The benefits are fairly obvious, in terms of support for arbitrary integer sizes (without weird type casting or literal suffixes like "<span style="font-family: "Courier New", Courier, monospace;">L</span>"), and support for other numeric types whose range may be far beyond the range of any arbitrary fixed-length integer type.<br />
<br />
<span style="font-size: large;">Characters</span><br />
A character is a single-quoted Unicode code point, with predictable support for escapes using the backslash. If necessary to encode Unicode characters in the range up to U+FFFF, the format <span style="font-family: "courier new" , "courier" , monospace;">\u1234</span> can be used; beyond that range, the format <span style="font-family: "courier new" , "courier" , monospace;">\U12345678</span> can be used. Here are some examples:<br />
<blockquote class="tr_bq">
<span style="font-family: "courier new" , "courier" , monospace;">'a'</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">' ' </span><br />
<span style="font-family: "courier new" , "courier" , monospace;">'\''</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">'\t'</span></blockquote>
This literal type is implemented by <span style="font-family: "courier new" , "courier" , monospace;">Char</span>, a <span style="font-family: "courier new" , "courier" , monospace;">const</span> class.<br />
<br />
<span style="font-size: large;">Strings</span><br />
A (character) string is a double-quote enclosed sequence of characters, supporting the same escapes as are supported for character literals. Here are some examples:<br />
<blockquote class="tr_bq">
<span style="font-family: "courier new" , "courier" , monospace;">""</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">"Hello, world!"</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">"This is an example of <b>\"</b>quotes<b>\"</b> inside </span><span style="font-family: "courier new" , "courier" , monospace;"><span style="font-family: "courier new" , "courier" , monospace;"><b>\"</b>quotes<b>\"</b>"</span></span><br />
<span style="font-family: "courier new" , "courier" , monospace;">"Multiple<b>\n</b>lines<b>\n</b>of<b>\n</b>text</span><span style="font-family: "courier new" , "courier" , monospace;"><span style="font-family: "courier new" , "courier" , monospace;">."</span></span></blockquote>
Multi-line strings are freeform, which means that character escapes are <i>not</i> processed; Unicode escapes, on the other hand, are supported, because they are handled by the earlier "lexer" stage of the compilation. Multi-line strings use a hard left border, defined by the "pipe" ("<span style="font-family: "Courier New", Courier, monospace;">|</span>") character; the first line of a multi-line string begins with a back-tick ("<span style="font-family: "Courier New", Courier, monospace;">`</span>") followed by a pipe. Here is an example:<br />
<blockquote class="tr_bq">
<span style="font-family: "Courier New", Courier, monospace;">String s = `|This is a test of</span><br />
<span style="font-family: "Courier New", Courier, monospace;"> |a "multiline" string</span><br />
<span style="font-family: "Courier New", Courier, monospace;"> |containing | and \ and ` and ' and " etc.</span><br />
<span style="font-family: "Courier New", Courier, monospace;"> <b>;</b> // <--- look at this</span></blockquote>
Like an end-of-line comment, the multi-line string takes everything from the pipe to the end of the line, as-is, which is why the semicolon in the example above has to be placed on the following line.<br />
<br />
A template allows a string to be formed dynamically from any valid expression. The format of the template string is the same as a normal string, except prefixed by the dollar sign ("<span style="font-family: "Courier New", Courier, monospace;">$</span>"); expressions inside the string are prefixed by dollar-sign + open-curly ("<span style="font-family: "Courier New", Courier, monospace;">${</span>") and suffixed by close-curly ("<span style="font-family: "Courier New", Courier, monospace;">}</span>"). Here are a few examples:<br />
<blockquote class="tr_bq">
<span style="font-family: "courier new" , "courier" , monospace;"><span style="font-family: "courier new" , "courier" , monospace;">$"Hello, ${name}!"</span></span><br /><span style="font-family: "courier new" , "courier" , monospace;"><span style="font-family: "courier new" , "courier" , monospace;">$"2 + 2 = ${2 + 2}."</span></span><br />
<span style="font-family: "courier new" , "courier" , monospace;">$"Finished in ${timer.elapsed.milliseconds}ms.</span><span style="font-family: "courier new" , "courier" , monospace;"><span style="font-family: "courier new" , "courier" , monospace;">"</span></span><br />
<span style="font-family: "courier new" , "courier" , monospace;">$"Finished in ${{timer.stop(); return timer.elapsed</span><span style="font-family: "courier new" , "courier" , monospace;"><span style="font-family: "courier new" , "courier" , monospace;">;}}"</span></span></blockquote>
Templates are handy, and making up good examples is challenging, but we already use templates all over the place. The last example is quite interesting, in that it shows a <i>statement expression</i> (syntactically, a lambda body) inside of the template expression.<br />
<br />
Templates can also be used with multi-line strings, which is denoted by using a dollar sign instead of the opening back-tick:<br />
<blockquote class="tr_bq">
<span style="font-family: "Courier New", Courier, monospace;">String s = $|# TOML doc<br /> |[name]<br /> |first = "{person.firstname}"<br /> |last = "{person.lastname}"<br /> ;</span></blockquote>
Finally, if the string you need to glue into your code is too big and ugly to put into the source file, then don't. Just stick it in its own file in the same directory; for example, in a file named "<span style="font-family: "Courier New", Courier, monospace;">ugly.txt</span>":<br />
<blockquote class="tr_bq">
<span style="font-family: "Courier New", Courier, monospace;">String s = $./ugly.txt;</span></blockquote>
Yeah. That was easy.<br /><br />The literal type for all of these forms of string is implemented by <span style="font-family: "courier new" , "courier" , monospace;">String</span>, a <span style="font-family: "courier new" , "courier" , monospace;">const</span> class.<br />
<br />
<span style="font-size: large;">Arrays</span><br />
An array literal is a square-bracket enclosed list of values.<br />
<br />
Here are some examples:<br />
<blockquote class="tr_bq">
<span style="font-family: "courier new" , "courier" , monospace;">[] </span><br />
<span style="font-family: "courier new" , "courier" , monospace;">['a', 'b', 'c']</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">[1, 2, 3]</span></blockquote>
This literal type is implemented by the <span style="font-family: "courier new" , "courier" , monospace;">Array</span> class, which is variably mutable: Array literals are either <span style="font-family: "Courier New", Courier, monospace;">Persistent</span> (if they contain any values that are not compile-time constants) or <span style="font-family: "Courier New", Courier, monospace;">Constant</span> (if they contain only compile-time constants).<br />
<br />
<span style="font-size: large;">Summary</span><br />
This was just a brief introduction to literals in Ecstasy. Each of these literal forms has many more rules than we covered here, but those rules are there to <i>allow</i> for more expression (readability) in the source code, and not to <i>restrict</i> it. The forms for these literals are designed to make it super easy to write and very pleasant to read.<br />
<br />
The rules do make the lexer and the parser more complex, but we look at it this way: The compiler only has to get written <i>twice</i> (one prototype to bootstrap the language, and then the real one written in natural Ecstasy code), so no matter how much work it is to make the language easier to use, we get to amortize that cost across many, many users over many, many years.<br />
<br />
Literally.</div>
xtclang (Ecstasy)http://www.blogger.com/profile/10099977807321312612noreply@blogger.com2tag:blogger.com,1999:blog-3316231033424903659.post-84994752161105801332019-07-09T13:00:00.001-04:002020-04-27T14:19:44.029-04:00Null is no Exception<div dir="ltr" style="text-align: left;" trbidi="on">
Since <a href="https://en.wikipedia.org/wiki/Tony_Hoare" target="_blank">Tony Hoare</a> formalized the concept of "null" in 1965, we have lived with an entire family of languages (including C, C++, Java, and C#) that made it possible for a pointer to contain a purposefully illegal address, for the purpose of representing the <i>lack of</i> a value. That purposefully illegal address is called <span style="font-family: "courier new" , "courier" , monospace;">null</span>. (Or <span style="font-family: "courier new" , "courier" , monospace;">NULL</span>, <span style="font-family: "courier new" , "courier" , monospace;">NIL</span>, <span style="font-family: "courier new" , "courier" , monospace;">nil</span>, etc.)<br />
<br />
The reasoning was simple: Without using any additional memory, a pointer could be made to serve two purposes: First, to indicate whether or not a value exists, and secondly, what that value is <i>if and only if</i> it exists.<br />
<br />
As type systems advanced, such that pointers became <i>type-safe references</i> instead of arbitrary integers, it became necessary to represent <span style="font-family: "courier new" , "courier" , monospace;">null</span> as a typed value. To make it possible to assign the value <span style="font-family: "courier new" , "courier" , monospace;">null</span> to any reference, these type systems made <span style="font-family: "courier new" , "courier" , monospace;">null</span> a sub-type of all other types; <span class="inline_editor_value" id="__w2_webAz8dR52_answer_content"><span class="ui_qtext_rendered_qtext">otherwise, </span></span><span class="inline_editor_value" id="__w2_webAz8dR52_answer_content"><span class="ui_qtext_rendered_qtext"><span style="font-family: "courier new" , "courier" , monospace;">null</span> would not be <i>assignment compatible</i> with any type other than the </span></span><span class="inline_editor_value" id="__w2_webAz8dR52_answer_content"><span class="ui_qtext_rendered_qtext"><span style="font-family: "courier new" , "courier" , monospace;">null</span> type itself.</span></span><br />
<span class="inline_editor_value" id="__w2_webAz8dR52_answer_content"><span class="ui_qtext_rendered_qtext"><br /></span></span>
<span class="inline_editor_value" id="__w2_webAz8dR52_answer_content"><span class="ui_qtext_rendered_qtext"><span class="ui_qtext_rendered_qtext"></span></span></span><br />
<div class="ui_qtext_para u-ltr u-text-align--start">
The use of <span style="font-family: "courier new" , "courier" , monospace;">null</span> in all of these languages had an unfortunate side effect: Because <span style="font-family: "courier new" , "courier" , monospace;">null</span> could be assigned to any type, it logically followed that <b>each and every value might be <span class="inline_editor_value" id="__w2_webAz8dR52_answer_content"><span class="ui_qtext_rendered_qtext"><span class="ui_qtext_rendered_qtext"><span style="font-family: "courier new" , "courier" , monospace;">null</span></span></span></span></b>. That means that every single access to a value requires a <span class="inline_editor_value" id="__w2_webAz8dR52_answer_content"><span class="ui_qtext_rendered_qtext"><span class="ui_qtext_rendered_qtext"><span style="font-family: "courier new" , "courier" , monospace;">null</span></span></span></span> check, which in turn generates an exception in languages like Java (<span style="font-family: "courier new" , "courier" , monospace;">NullPointerException</span>) and C# (<span style="font-family: "courier new" , "courier" , monospace;">NullReferenceException</span>). In C, such code just <i>segfaults</i> (aka "Access Violation" in Windows) and <i>core-dumps</i>. Yay!</div>
<div class="ui_qtext_para u-ltr u-text-align--start">
<br /></div>
<div class="ui_qtext_para u-ltr u-text-align--start">
To avoid segfaults and exceptions, it became necessary to sprinkle code with lots of these:<br />
<blockquote class="tr_bq">
<pre style="background-color: white; color: black; font-family: 'Menlo-Regular'; font-size: 10.5pt;"><span style="font-family: "courier new" , "courier" , monospace;"><span style="color: #660e7a; font-weight: bold;">if </span>(s != null)</span>
<span style="font-family: "courier new" , "courier" , monospace;"> {
...</span><span style="font-family: "courier new" , "courier" , monospace;">
}</span></pre>
</blockquote>
<span class="inline_editor_value" id="__w2_webAz8dR52_answer_content"><span class="ui_qtext_rendered_qtext">(Yay!)</span></span><span class="inline_editor_value" id="__w2_webAz8dR52_answer_content"><span class="ui_qtext_rendered_qtext"></span></span></div>
<br />
There
is an elegant solution to this ugliness, which is to make <span class="inline_editor_value" id="__w2_webAz8dR52_answer_content"><span class="ui_qtext_rendered_qtext"><span style="font-family: "courier new" , "courier" , monospace;">null</span></span></span> into its own normal type, and not some magical "subclass of all classes" class, or "subtype of all types" type. In other words, simply by making the <span class="inline_editor_value" id="__w2_webAz8dR52_answer_content"><span class="ui_qtext_rendered_qtext"><span style="font-family: "courier new" , "courier" , monospace;">null</span></span></span> value into an object reference of some normal class, it prevents that reference from being assigned willy-nilly to references of any other random type.<br />
<div class="ui_qtext_para u-ltr u-text-align--start">
<br /></div>
<div class="ui_qtext_para u-ltr u-text-align--start">
The complete code for the <span style="font-family: "courier new" , "courier" , monospace;">Nullable</span> type (found in Ecstasy's <span style="font-family: "courier new" , "courier" , monospace;">module.x</span>) is:</div>
<blockquote class="tr_bq">
<pre style="background-color: white; color: black; font-family: 'Menlo-Regular'; font-size: 10.5pt;"><span style="font-family: "courier new" , "courier" , monospace;"><span style="color: navy; font-weight: bold;">enum </span>Nullable { Null }</span></pre>
</blockquote>
<div class="ui_qtext_para u-ltr u-text-align--start">
That one line of code declares an enumeration class, called <span style="font-family: "courier new" , "courier" , monospace;">Nullable</span>, with one value, called <span style="font-family: "courier new" , "courier" , monospace;">Null</span>. </div>
<blockquote class="tr_bq">
<div class="ui_qtext_para u-ltr u-text-align--start">
(Advanced: <i>From an inheritance point of view, <span style="font-family: "courier new" , "courier" , monospace;">Null</span> extends <span style="font-family: "courier new" , "courier" , monospace;">Nullable</span> implements <span style="font-family: "courier new" , "courier" , monospace;">Object</span>. From a composition point-of-view,</i><i> as an enum, the class for <span style="font-family: "courier new" , "courier" , monospace;">Nullable</span> incorporates the <span style="font-family: "courier new" , "courier" , monospace;">Enumeration</span> mixin while </i><i><i>the </i><i><i><span style="font-family: "courier new" , "courier" , monospace;">Nullable</span></i> class itself is an abstract <span style="font-family: "courier new" , "courier" , monospace;">enum</span></i>, and <span style="font-family: "courier new" , "courier" , monospace;">Null</span> is an <span style="font-family: "courier new" , "courier" , monospace;">enum</span> value. An </i><i><i><span style="font-family: "courier new" , "courier" , monospace;">enum</span> value</i> is a singleton <span style="font-family: "courier new" , "courier" , monospace;">const</span>, which automatically implements both the <span style="font-family: "courier new" , "courier" , monospace;">Enum</span> and <span style="font-family: "courier new" , "courier" , monospace;">Const</span> interfaces. See source files: </i><i><span style="font-family: "courier new" , "courier" , monospace;">module.x</span>, <span style="font-family: "courier new" , "courier" , monospace;">Const.x</span>, <span style="font-family: "courier new" , "courier" , monospace;">Enum.x</span>, <span style="font-family: "courier new" , "courier" , monospace;">Class.x</span>, and <span style="font-family: "courier new" , "courier" , monospace;">Enumeration.x</span>.</i>)</div>
</blockquote>
<div class="ui_qtext_para u-ltr u-text-align--start">
This approach introduces some new requirements for the language's type system. First, a type system must be able to represent <i>composite</i> types, such as intersection types, union types, and difference types. Ecstasy represents intersection types with the "or" (<span class="inline_editor_value" id="__w2_webAz8dR52_answer_content"><span class="ui_qtext_rendered_qtext"><span class="ui_qtext_rendered_qtext">"<span style="font-family: "courier new" , "courier" , monospace;">|</span>"</span></span></span>) operator, because the code "<span style="font-family: "courier new" , "courier" , monospace;">(A|B)</span>" reads "either type A or type B", which means that only the <i>intersection</i> of those two types can be assumed. (Apologies to any mathematicians reading this, but the "U" on our keyboard was stuck in the right-side-up position.)</div>
<div class="ui_qtext_para u-ltr u-text-align--start">
<br /></div>
Thus, to declare a type that can hold a value of either Nullable or String, and assign it a predictable value, one could write:<br />
<blockquote class="tr_bq">
<pre style="background-color: white; color: black; font-family: 'Menlo-Regular'; font-size: 10.5pt;"><span style="font-family: "courier new" , "courier" , monospace;">Nullable | String s = </span><span style="font-family: "courier new" , "courier" , monospace;"><span style="font-family: "courier new" , "courier" , monospace;"><span style="font-family: "courier new" , "courier" , monospace;"><span style="color: green;">"Hello, world!</span><span style="color: green;">"</span></span></span>;</span></pre>
</blockquote>
<div class="ui_qtext_para u-ltr u-text-align--start">
This would quickly get old, so a short-hand notation for the "<span style="font-family: "courier new" , "courier" , monospace;">Nullable|</span>" portion is the type-postfix "<span style="font-family: "courier new" , "courier" , monospace;">?</span>"; here is the rewritten form of the above declaration, using the short-hand notation:</div>
<blockquote class="tr_bq">
<pre style="background-color: white; color: black; font-family: 'Menlo-Regular'; font-size: 10.5pt;"><span style="font-family: "courier new" , "courier" , monospace;">String<b>?</b> s = </span><span style="font-family: "courier new" , "courier" , monospace;"><span style="font-family: "courier new" , "courier" , monospace;"><span style="font-family: "courier new" , "courier" , monospace;"><span style="font-family: "courier new" , "courier" , monospace;"><span style="color: green;">"Hello, world!</span><span style="color: green;">"</span></span></span></span>;</span></pre>
</blockquote>
Since the variable "<span style="font-family: "courier new" , "courier" , monospace;">s</span>" is <i>either</i> a String value or a <span style="font-family: "courier new" , "courier" , monospace;">Nullable</span> value, one can <b>not</b> ask it for its size:<br />
<blockquote class="tr_bq">
<pre style="background-color: white; color: black; font-family: 'Menlo-Regular'; font-size: 10.5pt;"><span style="font-family: "courier new" , "courier" , monospace;">Int len = s.size; // <b>compiler error!</b></span></pre>
</blockquote>
<span class="inline_editor_value" id="__w2_webAz8dR52_answer_content"><span class="ui_qtext_rendered_qtext">The
reason that </span></span><span class="inline_editor_value" id="__w2_webAz8dR52_answer_content"><span class="ui_qtext_rendered_qtext">"<span style="font-family: "courier new" , "courier" , monospace;">s</span>" does not have a size is that its type is “</span></span><span class="inline_editor_value" id="__w2_webAz8dR52_answer_content"><span class="ui_qtext_rendered_qtext"><span style="font-family: "courier new" , "courier" , monospace;">Nullable</span> <i>or </i>
<span style="font-family: "courier new" , "courier" , monospace;">String</span>”, and the </span></span><span class="inline_editor_value" id="__w2_webAz8dR52_answer_content"><span class="ui_qtext_rendered_qtext"><span style="font-family: "courier new" , "courier" , monospace;">Nullable</span> type does not have a <span style="font-family: "courier new" , "courier" , monospace;">size</span> property. This allows the compiler to know that the </span></span><span class="inline_editor_value" id="__w2_webAz8dR52_answer_content"><span class="ui_qtext_rendered_qtext"><span class="inline_editor_value" id="__w2_webAz8dR52_answer_content"><span class="ui_qtext_rendered_qtext"><span style="font-family: "courier new" , "courier" , monospace;">size</span></span></span> property cannot be requested; this is an example of <b>compile-time type safety</b>. (Run-time type safety is exhibited by throwing a <span style="font-family: "courier new" , "courier" , monospace;">NullPointerException</span>, etc.; Ecstasy has no equivalent to this exception, because <b>such an exception cannot occur!</b> <i>"And there was much rejoicing."</i>)</span></span><br />
<br />
<span class="inline_editor_value" id="__w2_webAz8dR52_answer_content"><span class="ui_qtext_rendered_qtext">Compile-type type safety allows the compiler to know when a value <i>might be </i><span style="font-family: "courier new" , "courier" , monospace;">Null</span>. By checking if the type is a <span style="font-family: "courier new" , "courier" , monospace;">String</span>, the compiler subsequently knows that the value <i>cannot be</i> </span></span><span class="inline_editor_value" id="__w2_webAz8dR52_answer_content"><span class="ui_qtext_rendered_qtext"><span class="inline_editor_value" id="__w2_webAz8dR52_answer_content"><span class="ui_qtext_rendered_qtext"><span style="font-family: "courier new" , "courier" , monospace;">Null</span></span></span>, and specifically that the value is a </span></span><span class="inline_editor_value" id="__w2_webAz8dR52_answer_content"><span class="ui_qtext_rendered_qtext"><span class="inline_editor_value" id="__w2_webAz8dR52_answer_content"><span class="ui_qtext_rendered_qtext"><span style="font-family: "courier new" , "courier" , monospace;">String</span></span></span></span></span><span class="inline_editor_value" id="__w2_webAz8dR52_answer_content"><span class="ui_qtext_rendered_qtext">, after </span></span>which it is safe to obtain the <span class="inline_editor_value" id="__w2_webAz8dR52_answer_content"><span class="ui_qtext_rendered_qtext"><span style="font-family: "courier new" , "courier" , monospace;">String</span></span></span> size:<br />
<blockquote class="tr_bq">
<pre style="background-color: white; color: black; font-family: 'Menlo-Regular'; font-size: 10.5pt;"><span style="font-family: "courier new" , "courier" , monospace;"><span style="color: #660e7a; font-weight: bold;">if </span>(<b>s.is(String)</b>)</span>
<span style="font-family: "courier new" , "courier" , monospace;"><span style="font-family: "courier new" , "courier" , monospace;"></span> {
console.println($<span style="color: green;">"String s is <span style="color: black;">$</span></span></span><span style="font-family: "courier new" , "courier" , monospace;"><span style="color: green;"><span style="color: black;"><span style="font-family: "courier new" , "courier" , monospace;">{s.size}</span></span> characters long."</span>);
}</span></pre>
</blockquote>
<span class="inline_editor_value" id="__w2_webAz8dR52_answer_content"><span class="ui_qtext_rendered_qtext">Similarly, if the code explicitly compares to the </span></span><span class="inline_editor_value" id="__w2_webAz8dR52_answer_content"><span class="ui_qtext_rendered_qtext"><span class="inline_editor_value" id="__w2_webAz8dR52_answer_content"><span class="ui_qtext_rendered_qtext"><span style="font-family: "courier new" , "courier" , monospace;">Null</span></span></span> value, then compiler can know when the value <i>is</i> or is <i>not</i> </span></span><span class="inline_editor_value" id="__w2_webAz8dR52_answer_content"><span class="ui_qtext_rendered_qtext"><span class="inline_editor_value" id="__w2_webAz8dR52_answer_content"><span class="ui_qtext_rendered_qtext"><span style="font-family: "courier new" , "courier" , monospace;">Null</span></span></span>.</span></span><span class="inline_editor_value" id="__w2_webAz8dR52_answer_content"><span class="ui_qtext_rendered_qtext"> The above code could be modified slightly b</span></span>y first testing if the value is <b>not</b> <span style="font-family: "courier new" , "courier" , monospace;">Null</span>, <span class="inline_editor_value" id="__w2_webAz8dR52_answer_content"><span class="ui_qtext_rendered_qtext">so that the compiler subsequently knows (by process of elimination) that the value</span></span><span class="inline_editor_value" id="__w2_webAz8dR52_answer_content"><span class="ui_qtext_rendered_qtext"> is a </span></span><span class="inline_editor_value" id="__w2_webAz8dR52_answer_content"><span class="ui_qtext_rendered_qtext"><span class="inline_editor_value" id="__w2_webAz8dR52_answer_content"><span class="ui_qtext_rendered_qtext"><span style="font-family: "courier new" , "courier" , monospace;">String</span></span></span></span></span><span class="inline_editor_value" id="__w2_webAz8dR52_answer_content"><span class="ui_qtext_rendered_qtext">, </span></span>after which it is safe to obtain the <span class="inline_editor_value" id="__w2_webAz8dR52_answer_content"><span class="ui_qtext_rendered_qtext"><span style="font-family: "courier new" , "courier" , monospace;">String</span></span></span> size:<br />
<blockquote class="tr_bq">
<pre style="background-color: white; color: black; font-family: 'Menlo-Regular'; font-size: 10.5pt;"><span style="font-family: "courier new" , "courier" , monospace;"><span style="color: #660e7a; font-weight: bold;">if </span>(<b>s != Null</b>)</span>
<span style="font-family: "courier new" , "courier" , monospace;"><span style="font-family: "courier new" , "courier" , monospace;"></span> {
console.println($<span style="color: green;">"String s is <span style="color: black;">$</span></span></span><span style="font-family: "courier new" , "courier" , monospace;"><span style="color: green;"><span style="color: black;"><span style="font-family: "courier new" , "courier" , monospace;">{s.size}</span></span> characters long."</span>);
}</span> </pre>
</blockquote>
The postfix "<span style="font-family: "courier new" , "courier" , monospace;">?</span>" operator is a <i>short-circuiting</i> operator that performs the same not-<span style="font-family: "courier new" , "courier" , monospace;">Null</span> test, so the above code could be written instead as:<br />
<blockquote class="tr_bq">
<pre style="background-color: white; color: black; font-family: 'Menlo-Regular'; font-size: 10.5pt;"><span style="font-family: "courier new" , "courier" , monospace;"><span style="font-family: "courier new" , "courier" , monospace;">console.println($<span style="color: green;">"</span><span style="color: green;">String s is <span style="color: black;">${s</span></span><b>?</b><span style="color: green;"><span style="color: black;">.size}</span> characters long.</span><span style="color: green;">"</span>);</span></span></pre>
</blockquote>
The short-circuiting "<span style="font-family: "courier new" , "courier" , monospace;">?</span>" operator can be <i>grounded</i> using the <i>else</i> ("<span style="font-family: "courier new" , "courier" , monospace;">:</span>") operator. In the following example, if "<span style="font-family: "courier new" , "courier" , monospace;">a</span>" is <span class="inline_editor_value" id="__w2_webAz8dR52_answer_content"><span class="ui_qtext_rendered_qtext"><span style="font-family: "courier new" , "courier" , monospace;">Null</span></span></span>, or if "<span style="font-family: "courier new" , "courier" , monospace;">a.b</span>" is <span class="inline_editor_value" id="__w2_webAz8dR52_answer_content"><span class="ui_qtext_rendered_qtext"><span style="font-family: "courier new" , "courier" , monospace;">Null</span></span></span>, or if "<span style="font-family: "courier new" , "courier" , monospace;">a.b.c</span>" is <span class="inline_editor_value" id="__w2_webAz8dR52_answer_content"><span class="ui_qtext_rendered_qtext"><span style="font-family: "courier new" , "courier" , monospace;">Null</span></span></span>, then the result is the predictable value of <span style="font-family: "courier new" , "courier" , monospace;"><span style="font-family: "courier new" , "courier" , monospace;"><span style="font-family: "courier new" , "courier" , monospace;"><span style="font-family: "courier new" , "courier" , monospace;"><span style="color: green;">"Hello, world!</span><span style="color: green;">"</span></span></span></span></span>, otherwise the result is the value of<span style="font-family: inherit;"> "</span><span style="font-family: "courier new" , "courier" , monospace;">a.b.c</span><span style="font-family: inherit;">":</span> <br />
<blockquote class="tr_bq">
<pre style="background-color: white; color: black; font-family: 'Menlo-Regular'; font-size: 10.5pt;"><span style="font-family: "courier new" , "courier" , monospace;">String s = a?.b?.c? <b>:</b> </span><span style="font-family: "courier new" , "courier" , monospace;"></span><span style="font-family: "courier new" , "courier" , monospace;"><span style="font-family: "courier new" , "courier" , monospace;"><span style="font-family: "courier new" , "courier" , monospace;"><span style="font-family: "courier new" , "courier" , monospace;"><span style="color: green;">"Hello, world!</span><span style="color: green;">"</span></span></span></span>;</span></pre>
</blockquote>
Ecstasy combines the postfix "<span style="font-family: "courier new" , "courier" , monospace;">?</span>" and the <i>else</i> ("<span style="font-family: "courier new" , "courier" , monospace;">:</span>") operator into the <i>elvis</i> ("<span style="font-family: "courier new" , "courier" , monospace;">?<b>:</b></span>") operator:<br />
<blockquote class="tr_bq">
<pre style="background-color: white; color: black; font-family: 'Menlo-Regular'; font-size: 10.5pt;"><span style="font-family: "courier new" , "courier" , monospace;">String s = a ?<b>:</b> </span><span style="font-family: "courier new" , "courier" , monospace;"></span><span style="font-family: "courier new" , "courier" , monospace;"><span style="font-family: "courier new" , "courier" , monospace;"><span style="font-family: "courier new" , "courier" , monospace;"><span style="font-family: "courier new" , "courier" , monospace;"><span style="color: green;">"Hello, world!</span><span style="color: green;">"</span></span></span></span>;</span></pre>
</blockquote>
The above code has the same effect as:<br />
<blockquote class="tr_bq">
<pre style="background-color: white; color: black; font-family: 'Menlo-Regular'; font-size: 10.5pt;"><span style="font-family: "courier new" , "courier" , monospace;">String s = a? <b>:</b> </span><span style="font-family: "courier new" , "courier" , monospace;"></span><span style="font-family: "courier new" , "courier" , monospace;"><span style="font-family: "courier new" , "courier" , monospace;"><span style="font-family: "courier new" , "courier" , monospace;"><span style="font-family: "courier new" , "courier" , monospace;"><span style="color: green;">"Hello, world!</span><span style="color: green;">"</span></span></span></span>;</span></pre>
</blockquote>
As with most binary operators, it is possible to combine the operator with the assigment operator, such that:<br />
<blockquote class="tr_bq">
<pre style="background-color: white; color: black; font-family: 'Menlo-Regular'; font-size: 10.5pt;"><span style="font-family: "courier new" , "courier" , monospace;">x <b>=</b> x <b>?:</b> y;</span><span style="font-family: "courier new" , "courier" , monospace;"></span></pre>
</blockquote>
... can be rewritten using the <i>elvis assignment</i> operator as:<br />
<blockquote class="tr_bq">
<pre style="background-color: white; color: black; font-family: 'Menlo-Regular'; font-size: 10.5pt;"><span style="font-family: "courier new" , "courier" , monospace;">x <b>?:=</b> y</span><span style="font-family: "courier new" , "courier" , monospace;">;</span></pre>
</blockquote>
<div class="ui_qtext_para u-ltr u-text-align--start">
Notice the similarity in the postfix "<span style="font-family: "courier new" , "courier" , monospace;">?</span>" operator, the <i>else</i> ("<span style="font-family: "courier new" , "courier" , monospace;">:</span>") operator, and the elvis operator, with the <i>ternary</i> operator; each of the four following lines of code has the same result:</div>
<blockquote class="tr_bq">
<pre style="background-color: white; color: black; font-family: 'Menlo-Regular'; font-size: 10.5pt;"><span style="font-family: "courier new" , "courier" , monospace;">x = x!=Null ? x : y;
x = x? : y;
x = x ?: y;
x ?:= y;</span><span style="font-family: "courier new" , "courier" , monospace;"></span></pre>
</blockquote>
<div class="ui_qtext_para u-ltr u-text-align--start">
That is a lot to wrap one's head around, but there is a simple logic behind it.</div>
<div class="ui_qtext_para u-ltr u-text-align--start">
<br /></div>
<br />
Finally, there is a special <span style="font-family: "courier new" , "courier" , monospace;">Null</span>-aware assignment operator that splits a nullable type, such as "<span style="font-family: "courier new" , "courier" , monospace;">String?</span>", into a <i>tuple</i> of <span style="font-family: "courier new" , "courier" , monospace;">Boolean</span> and the (<i>conditional</i>) <b>non</b>-nullable portion of the type (e.g. "<span style="font-family: "courier new" , "courier" , monospace;">String</span>"). This can be used wherever a condition can be used, such as in an "<span style="font-family: "courier new" , "courier" , monospace;">if</span>" or "<span style="font-family: "courier new" , "courier" , monospace;">while</span>" statement. For example, imagine some method or function that can return a nullable string value:<br />
<blockquote class="tr_bq">
<pre style="background-color: white; color: black; font-size: 10.5pt;"><span style="font-family: "courier new" , "courier" , monospace;">String? foo();</span></pre>
</blockquote>
Other than the operator, this example should seem quite familiar by now:<br />
<blockquote class="tr_bq">
<pre style="background-color: white; color: black; font-family: 'Menlo-Regular'; font-size: 10.5pt;"><span style="font-family: "courier new" , "courier" , monospace;"><span style="color: #660e7a; font-weight: bold;">if </span>(String s <b>?=</b> foo())</span>
<span style="font-family: "courier new" , "courier" , monospace;"><span style="font-family: "courier new" , "courier" , monospace;"></span> {
console.println($<span style="color: green;">"String s is <span style="color: black;">$</span></span></span><span style="font-family: "courier new" , "courier" , monospace;"><span style="color: green;"><span style="color: black;"><span style="font-family: "courier new" , "courier" , monospace;">{s.size}</span></span> characters long."</span>);
}</span> </pre>
</blockquote>
In the above example, if the function returns <span class="inline_editor_value" id="__w2_webAz8dR52_answer_content"><span class="ui_qtext_rendered_qtext"><span style="font-family: "courier new" , "courier" , monospace;">Null</span></span></span>, then the result is the tuple <span style="font-family: "courier new" , "courier" , monospace;">(False)</span><span style="font-family: inherit;"></span>, which is consumed by the <span style="font-family: "courier new" , "courier" , monospace;">if</span>, causing the "else" branch of the <span style="font-family: "courier new" , "courier" , monospace;">if</span> statement to be executed. Conversely, if the function returns a <span class="inline_editor_value" id="__w2_webAz8dR52_answer_content"><span class="ui_qtext_rendered_qtext"></span></span><span class="inline_editor_value" id="__w2_webAz8dR52_answer_content"><span class="ui_qtext_rendered_qtext"><span class="inline_editor_value" id="__w2_webAz8dR52_answer_content"><span class="ui_qtext_rendered_qtext"><span style="font-family: "courier new" , "courier" , monospace;">String</span></span></span></span></span><span class="inline_editor_value" id="__w2_webAz8dR52_answer_content"><span class="ui_qtext_rendered_qtext"></span></span> value, then the result is the tuple <span style="font-family: "courier new" , "courier" , monospace;">(True, </span><i>string-value</i><span style="font-family: "courier new" , "courier" , monospace;">)</span>, of which the <span style="font-family: "courier new" , "courier" , monospace;">(True)</span> is consumed by the <span style="font-family: "courier new" , "courier" , monospace;">if</span>, causing the <span style="font-family: "courier new" , "courier" , monospace;"></span><i>string-value</i><span style="font-family: "courier new" , "courier" , monospace;"></span> to be consumed by the assignment, <b>and</b> causing the "then" branch of the <span style="font-family: "courier new" , "courier" , monospace;">if</span> statement to be executed.<br />
<br />
Thus, it should be obvious that these two statements will have the same result:<br />
<blockquote class="tr_bq">
<pre style="background-color: white; color: black; font-size: 10.5pt;"><span style="font-family: "courier new" , "courier" , monospace;">s ?= foo();
s = foo()?;</span></pre>
</blockquote>
As just another normal value, and thus without any mind-bendingly-crazy type system rules to accomodate some magical <span style="font-family: "courier new" , "courier" , monospace;">null</span> value, <span style="font-family: "courier new" , "courier" , monospace;">Null</span> is simultaneously less troublesome and more useful.<br />
<br />
<span class="inline_editor_value" id="__w2_webAz8dR52_answer_content"><span class="ui_qtext_rendered_qtext">The </span></span><span class="inline_editor_value" id="__w2_webAz8dR52_answer_content"><span class="ui_qtext_rendered_qtext"><span style="font-family: "courier new" , "courier" , monospace;">null</span> is dead. Long live the </span></span><span class="inline_editor_value" id="__w2_webAz8dR52_answer_content"><span class="ui_qtext_rendered_qtext"><span style="font-family: "courier new" , "courier" , monospace;">Null</span>.</span></span></div>
xtclang (Ecstasy)http://www.blogger.com/profile/10099977807321312612noreply@blogger.com7tag:blogger.com,1999:blog-3316231033424903659.post-2926811042437533832019-06-20T15:00:00.001-04:002020-07-08T09:20:14.799-04:00The Quest for Equality<div dir="ltr" style="text-align: left;" trbidi="on">
It's shocking how difficult <i>equality</i> is to get right in software. What does <i>equality</i> even mean?<br />
<br />
Equality used to be so simple in the days of assembly language, when "bitwise equality" was all that existed, and the only things that could be compared were fixed-size CPU registers. Things got more and more complex, until we ended up with Object Oriented languages, in which each class may have its own idea of what equality means.<br />
<br />
On top of that, the most popular languages today each have multiple <i>forms</i> of equality. Python offers "<span style="font-family: "courier new", "courier", monospace;">is</span>" versus "<span style="font-family: "courier new", "courier", monospace;">==</span>". Java and C# offer "<span style="font-family: "courier new", "courier", monospace;">==</span>" and "<span style="font-family: "courier new", "courier", monospace;">o1.equals(o2)</span>" -- which can easily differ from "<span style="font-family: "courier new", "courier", monospace;">o2.equals(o1)</span>" because it is neither <i>symmetric</i> nor <i>transitive</i>. Javascript has both an "<span style="font-family: "courier new", "courier", monospace;">is</span>" and "<span style="font-family: "courier new", "courier", monospace;">==</span>", and just keeps adding equals signs when new meanings are desired; so far, they're up to "<span style="font-family: "courier new", "courier", monospace;">===</span>", but anyone who denies the likelihood of a future "<span style="font-family: "courier new", "courier", monospace;">=====</span>" operator is just kidding themselves.<br />
<br />
Obviously, equality is not a simple problem. Most of the existing solutions are broken, because they cannot provide either symmetric or transitive behavior. Many of these problems are the direct result of having multiple type systems within a single language; that helps to explain why many of these languages provide two forms of equality: One for the primitive "value" type system, and one for the object type (reference-based) system.<br />
<br />
It's obvious that in an object type system, a class needs to be able to define equality <i>for that class</i>, replacing any superclass definition of the same, which means that the definition of equality is <i>virtual</i>, as in "<i>virtual method invocation</i>". It's also obvious that such a definition cannot be a <i>single dispatch</i> method, because then "<span style="font-family: "courier new", "courier", monospace;">o1.equals(o2)</span>" may provide a completely different answer from "<span style="font-family: "courier new", "courier", monospace;">o2.equals(o1)</span>". There have been languages that attempt to address this type of conundrum with multiple dispatch support, but by the same token, one can swat a fly with an atomic bomb.<br />
<br />
Generic types further add complexity to the notion of equality, because each type parameter may contribute its own potentially conflicting notion of equality to the equation.<br />
<br />
So what's the answer?<br />
<br />
Intent. Intent matters. The developer's <i>intent</i> when they write a line of code is important, but somehow that intent manages to be erased by a language compiler. (It's no mistake that the term <i>type erasure</i> is used to describe a generic type system that is implemented by forgetting what those types actually were.)<br />
<br />
Ecstasy captures the developer intent by capturing the <i>compile time type</i> of the references in question, and <i>retaining</i> that information in the compiled code, and <i>using</i> that information for hard problems like equality.<br />
<br />
Consider the following example:<br />
<blockquote class="tr_bq">
<span style="font-family: "courier new", "courier", monospace;">Collection<String> c1 = foo();<br />Collection<String> c2 = bar();<br />if (c1 == c2)<br /> {<br /> // ...<br /> }</span></blockquote>
It doesn't matter what the <i>actual</i> runtime type of the object is that <span style="font-family: "courier new", "courier", monospace;">c1</span> or <span style="font-family: "courier new", "courier", monospace;">c2</span> refers to, because the developer clearly explained that they are <b>Collections</b> of <b>String</b> objects. The class of the collection is unknown here at compile time, and instead the <span style="font-family: "courier new", "courier", monospace;">Collection</span> interface is used, which defines equality in a certain way. In theory, those collections could contain objects of various <i>sub-classes</i> of String, but when those contents are compared, they will be compared <i>as Strings</i>. <b>Because that was the intent of the developer</b>.<br />
<br />
To accomplish this, equality is implemented <b>non</b>-virtually; here is the <span style="font-family: "courier new", "courier", monospace;">equals</span> function on <span style="font-family: "courier new", "courier", monospace;">Collection</span>:<br />
<blockquote class="tr_bq">
<span style="font-family: "courier new", "courier", monospace;"></span><br />
<pre><span style="font-family: "courier new", "courier", monospace;">/**
* Two collections are equal iff they are they contain the same values.
*/
static <CompileType extends Collection>
Boolean equals(CompileType collection1, CompileType collection2)
{
// they must be of the same arity
if (collection1.size != collection2.size)
{
return False;
}
if (collection1.sortedBy() || collection2.sortedBy())
{
// if either is sorted, then both must be of the same order;
// the collections were of the same arity, so the second iterator
//</span><span style="font-family: "courier new", "courier", monospace;"><span style="font-family: "courier new", "courier", monospace;"> shouldn't run out</span> before the first
Iterator</span><span style="font-family: "courier new", "courier", monospace;"><CompileType.Element> iter1 = collection1.iterator();
Iterator</span><span style="font-family: "courier new", "courier", monospace;"><CompileType.Element> iter2 = collection2.iterator();
for (val value1 : iter1)
{
assert val value2 := iter2.next();
if (value1 != value2)
{
return False;
}
}
// the collections were of the same arity, so the first iterator
//</span><span style="font-family: "courier new", "courier", monospace;"><span style="font-family: "courier new", "courier", monospace;"> shouldn't run out</span> before the second
assert !iter2.next();
return True;
}
else
{
return collection1.containsAll(collection2);
}
}</span></pre>
</blockquote>
What makes this work is that <b>the compile-time type is passed to the <span style="font-family: "courier new", "courier", monospace;">equals</span> function</b>. Not the name of the type. Not the "type value". The type. The actual, for-real, usable-as-a-type-name-in-your-code type. A <i>formal</i> type. (Yes, types are objects. But they're also types.)<br />
<br />
So how did this function get called? Well, because the compiler determined, and retained, and used, the compile-time type. Both the "<span style="font-family: "courier new", "courier", monospace;">==</span>" operator and the "<span style="font-family: "courier new", "courier", monospace;">!=</span>" operator ultimately cause a call to this function to occur.<br />
<br />
And what if, instead, the developer had specified these variables as being Lists?<br />
<blockquote class="tr_bq">
<span style="font-family: "courier new", "courier", monospace;">List<String> c1 = foo();<br />List<String> c2 = bar();<br />if (c1 == c2)<br /> {<br /> // ...<br /> }</span></blockquote>
Again, it doesn't matter what the <i>actual</i> runtime types of those object are, because the developer clearly explained that they must be Lists of String, and the result of the "==" operator is a call to List:<br />
<blockquote class="tr_bq">
<span style="font-family: "courier new", "courier", monospace;">/**</span><br />
<span style="font-family: "courier new", "courier", monospace;"> * Two lists are equal iff they are of the same size, and</span><br />
<span style="font-family: "courier new", "courier", monospace;"> *</span><span style="font-family: "courier new", "courier", monospace;"> they</span><span style="font-family: "courier new", "courier", monospace;"><span style="font-family: "courier new", "courier", monospace;"> contain the same values, in the</span> same order.</span><br />
<span style="font-family: "courier new", "courier", monospace;"> */</span><br />
<span style="font-family: "courier new", "courier", monospace;">static <CompileType extends List> Boolean equals(CompileType a1, CompileType a2)</span><br />
<span style="font-family: "courier new", "courier", monospace;"> {</span><br />
<span style="font-family: "courier new", "courier", monospace;"> Int c = a1.size;</span><br />
<span style="font-family: "courier new", "courier", monospace;"> if (c != a2.size)</span><br />
<span style="font-family: "courier new", "courier", monospace;"> {</span><br />
<span style="font-family: "courier new", "courier", monospace;"> return False;</span><br />
<span style="font-family: "courier new", "courier", monospace;"> }</span><br />
<span style="font-family: "courier new", "courier", monospace;"></span><br />
<span style="font-family: "courier new", "courier", monospace;"> for (Int i = 0; i < c; ++i)</span><br />
<span style="font-family: "courier new", "courier", monospace;"> {</span><br />
<span style="font-family: "courier new", "courier", monospace;"> if (a1[i] != a2[i])</span><br />
<span style="font-family: "courier new", "courier", monospace;"> {</span><br />
<span style="font-family: "courier new", "courier", monospace;"> return False;</span><br />
<span style="font-family: "courier new", "courier", monospace;"> }</span><br />
<span style="font-family: "courier new", "courier", monospace;"> }</span><br />
<span style="font-family: "courier new", "courier", monospace;"></span><br />
<span style="font-family: "courier new", "courier", monospace;"> return True;</span><br />
<span style="font-family: "courier new", "courier", monospace;"> }</span></blockquote>
Even more obvious is that the <span style="font-family: "courier new", "courier", monospace;">equals</span> functions themselves simply use the "<span style="font-family: "courier new", "courier", monospace;">==</span>" and "<span style="font-family: "courier new", "courier", monospace;">!=</span>" operators on the values with the Collections or Lists, because the compile time type of those contents has not been erased, and was encoded into the compiled code, and was used in the call to the Collection or List <span style="font-family: "courier new", "courier", monospace;">equals</span> function. And this works for arbitrarily deep nesting of generic types, <i>because turtles</i>.<br />
<br />
And it's type safe.<br />
And it's symmetric.<br />
And it's transitive.<br />
And it's readable.<br />
And it's obvious.<br />
And it's correct.<br />
<br />
One more thing. What if you really want to know if two objects are actually "the same object"? In Ecstasy, as described previously, the reference (<span style="font-family: "courier new", "courier", monospace;">Ref</span>) to an object contains the <i>type</i> and the <i>identity</i> of the object that is referred to. Sameness refers to that identity, and the <span style="font-family: "courier new", "courier", monospace;">equals</span> function on <span style="font-family: "courier new", "courier", monospace;">Ref</span> tests for the equality of that identity:<br />
<br />
<blockquote class="tr_bq">
<div style="text-align: left;">
<span style="font-family: "courier new", "courier", monospace;">List<String> c1 = foo();<br />List<String> c2 = bar();<br />if (<b>&</b>c1 == <b>&</b>c2)<br /> {<br /> // ...<br /> }</span></div>
</blockquote>
... which is exactly what the <span style="font-family: "courier new", "courier", monospace;">Object.equals</span> function does itself:<br />
<blockquote class="tr_bq">
<span style="font-family: "courier new", "courier", monospace;">static <CompileType extends Object><br /> Boolean equals(CompileType o1, CompileType o2)<br /> {<br /> return &o1 == &o2;<br /> }</span></blockquote>
</div>
xtclang (Ecstasy)http://www.blogger.com/profile/10099977807321312612noreply@blogger.com4tag:blogger.com,1999:blog-3316231033424903659.post-21643678869757039272019-06-18T13:00:00.000-04:002019-06-18T13:00:03.317-04:00A pointed paean for C<div dir="ltr" style="text-align: left;" trbidi="on">
Less than 20% of programmers <a href="https://www.jetbrains.com/lp/devecosystem-2019/" target="_blank">claim to use C</a> today, and the real number of programmers actually using C is likely far smaller, but C lives on quite pervasively in its influence on C++, Java, C#, and other languages. Starting with Java, most of the "managed runtime" languages purposefully omitted one of the most powerful features in C: The pointer. In its place, these languages provide a concept called a <i>reference</i>, which is a type-safe pointer whose value (a memory address) cannot be obtained or manipulated by the programmer.<br />
<br />
Two important things were lost in the process, however:<br />
<ul style="text-align: left;">
<li>The reference itself became opaque, in that its only capability in these languages is to be de-referenced; and</li>
<li>Pass-by-reference is no longer possible.</li>
</ul>
Ecstasy references, on the other hand, are themselves objects (<i>because turtles</i>), and because references are objects, references have references (<i>because turtles</i>). It may make your head hurt to picture this, but in use, it becomes the most obvious and simple concept imaginable. In Ecstasy, a reference is represented by the <span style="font-family: "Courier New", Courier, monospace;">Ref</span> interface:<br />
<blockquote class="tr_bq">
<br />
A Ref represents a reference to an Ecstasy object. In Ecstasy, "everything is an object", and the only way that one can interact with an object is through a reference to that object. The <i>referent</i> is the object being referred to; the <i>reference</i> (encapsulated in and represented by a Ref object) is the object that refers to the referent.<br /><br />An Ecstasy reference is conceptually composed of two pieces of information:<br />
<ul style="text-align: left;">
<li>A <i>type</i>;</li>
<li>An <i>identity</i>.</li>
</ul>
The type portion of an Ecstasy reference, represented by the <span style="font-family: "Courier New", Courier, monospace;">actualType</span> property of the Ref, is simply the set of operations that can be invoked against the referent and the set of properties that it contains. Regardless of the actual operations that the referent object implements, only those present in the type of the reference can be invoked through the reference. This allows references to be purposefully narrowed; an obvious example is when an object only provides a reference to its <span style="font-family: "Courier New", Courier, monospace;">public</span> members.<br /><br />The Ref also has a <span style="font-family: "Courier New", Courier, monospace;">RefType</span> property, which is its <i>type constraint</i>. For example, when a Ref represents a compile time concept such as a <i>variable</i> or a <i>property</i>, the RefType is the <i>compile time type</i> of the reference. The reference may contain additional operations at runtime; the actualType is always a super-set (⊇) of the RefType.<br /><br />The identity portion of an Ecstasy reference is itself unrepresentable in Ecstasy. In fact, it is this very unrepresentability that necessitates the Ref abstraction in the first place. For example, the identity may be implemented as a pointer, which points to an address in memory at which the state of the object is stored. However, that address could be located on the process' program stack, or allocated via a dynamic memory allocation, or could point into a particular element of an array or a structure that itself is located on the program stack or allocated via a dynamic memory allocation. Or the identity could be a handle, adding a layer of indirection to each of the above. Or the identity could itself <i>be</i> the object, as one would expect for the simplest (the most primitive) of types, such as booleans, bytes, characters, and integers.<br /><br />To allow the Ecstasy runtime to provide the same behavioral guarantees regardless of how objects are allocated and managed, how they are addressed, and how house-keeping activities potentially affect all of the above, the Ref provides an opaque abstraction that hides the actual identity (and thus the actual underlying implementation) from the program and from the programmer.<br /><br />Because it is impossible to represent the identity in Ecstasy, the Ref type is itself simply an interface; the actual Ref instances used for parameters, variables, properties, array elements, and so on, are provided by the runtime itself, and exposed to the running code via this interface.</blockquote>
<span style="font-family: "Courier New", Courier, monospace;">Ref</span> is read-only; the read/write form is the <span style="font-family: "Courier New", Courier, monospace;">Var</span> interface, which extends <span style="font-family: "Courier New", Courier, monospace;">Ref</span>. To obtain a <span style="font-family: "Courier New", Courier, monospace;">Ref</span> or a <span style="font-family: "Courier New", Courier, monospace;">Var</span>, we use the C <i>address-of</i> operator, "<span style="font-family: "Courier New", Courier, monospace;">&</span>":<br />
<br />
<span style="font-family: "Courier New", Courier, monospace;">String str = "Hello world!"; </span><br />
<br />
<span style="font-family: "Courier New", Courier, monospace;"><span style="font-family: "Courier New", Courier, monospace;">// get a read-only reference to the variable</span></span><br />
<span style="font-family: "Courier New", Courier, monospace;">Ref<String> ref = &str;</span><br />
<br />
<span style="font-family: "Courier New", Courier, monospace;"><span style="font-family: "Courier New", Courier, monospace;">// alternatively, get a read/write reference to the variable</span></span><br />
<span style="font-family: "Courier New", Courier, monospace;">Var<String> var = &str;</span><br />
<br />
<span style="font-family: "Courier New", Courier, monospace;">// modify the variable via a reference</span><br />
<span style="font-family: "Courier New", Courier, monospace;">var.set("Goodbye, cruel world!"); </span><br />
<br />
<span style="font-family: "Courier New", Courier, monospace;">// that modified the value that is held in the variable!</span><br />
<span style="font-family: "Courier New", Courier, monospace;"><span style="font-family: "Courier New", Courier, monospace;">assert str == var.get();</span></span><br />
<span style="font-family: "Courier New", Courier, monospace;"><span style="font-family: "Courier New", Courier, monospace;"><br /></span></span>
<span style="font-family: "Courier New", Courier, monospace;"><span style="font-family: "Courier New", Courier, monospace;">// which we can also see through the read-only reference</span></span><br />
<span style="font-family: "Courier New", Courier, monospace;">assert ref.get() == str;</span><br />
<br />
The last concept to grasp is this: <b>Objects are <i>of a</i> class, but references are <i>of a</i> type</b>. In most OO languages, <i>the object's class is its type</i>, but one takes a different route when designing a language -- like Ecstasy -- to build portable, containerized, safe, and secure applications in the cloud, versus designing a language -- like C -- to build an operating system.<br />
<br />
This concept is unusual coming from the C++ (vtable-based, compile-time types only) family of languages, but -- very importantly! -- this concept does not create any additional cognitive load for the application developer. What it does allow, though, is for a systems developer to dynamically <b>and securely</b> reduce the surface area of an object when sharing that object across a container boundary.</div>
xtclang (Ecstasy)http://www.blogger.com/profile/10099977807321312612noreply@blogger.com4tag:blogger.com,1999:blog-3316231033424903659.post-83027735796783965512019-06-17T09:00:00.000-04:002020-04-27T14:04:13.088-04:00An Introduction to the Ecstasy Type System<div dir="ltr" style="text-align: left;" trbidi="on">
Ecstasy's type system is designed to be an obvious and predictable type system:<br />
<ul style="text-align: left;">
<li>Ecstasy has a single type system, which is an <i>object</i> type system, and that's it. In other words, <b>Ecstasy only has objects.</b></li>
<li>Unlike C# or Java, there is no secondary <i>primitive</i> type system with types like "int" or "boolean" that everything else has to be constructed out of. In Ecstasy, all types are built out of other Ecstasy types. For someone who has used Smalltalk, this concept should be familiar.</li>
<li>There is a single root called Object. For someone who has used C# or Java, this should seem quite familiar, with one little twist: In Ecstasy, Object is an <i>interface</i>, not a <i>class</i>.</li>
<li>The Ecstasy type system is called the Turtles Type System, <a href="https://en.wikipedia.org/wiki/Turtles_all_the_way_down" target="_blank">because the entire type system is bootstrapped on itself</a>, and -- lacking primitives -- solely on itself. An Int, for example, is built out of an Array of Bit, and a Bit is built out of an IntLiteral (i.e. 0 or 1), which is built out of a String, which is an Array of Char, and a Char is built out of an Int. Thus, an Int is built out of many Ints. It's turtles, the whole way down.</li>
<li>The type system is fully generic, and fully reified. This means that a List-of-Int is actually a List-of-Int, and not just a List with some compile-time syntactic sugar.</li>
<li>The type system is covariant. This means that an Array-of-Int is a List-of-Int is a List-of-Number is a List-of-Object is a List is an Object. </li>
<li>The type system is module-based, transitively closed, type-checked, and type safe.</li>
<li>Most type safety checks are performed by the compiler and re-checked by the link-time verifier. Most of the remaining type safety checks are performed by the linker when it transitively closes over the type system. The remaining type safety checks are performed at runtime, for the specific cases in which the types cannot be fully known until runtime.</li>
<li>A class <i>has a</i> type, but a class is not a type. (A class may have many types, but minimally its existence implies at least four types: structural, private, protected, and public.)</li>
<li>The type system explicitly supports <i>actual</i> immutability.</li>
</ul>
In software, making something simple is the hardest thing that we do. The Ecstasy Turtles Type System is proof of that, but the benefits are worth it. <i>Using</i> the type system is incredibly easy, and <i>reading</i> the code is a joy.<br />
<br />
<br />
<br /></div>
xtclang (Ecstasy)http://www.blogger.com/profile/10099977807321312612noreply@blogger.com0tag:blogger.com,1999:blog-3316231033424903659.post-55008588020884348242019-06-13T20:00:00.001-04:002020-07-08T09:12:55.608-04:00Conditional Methods<div dir="ltr" style="text-align: left;" trbidi="on">
There's a common pattern in software libraries, which is the <i>conditional result</i>. For example, a language may have an iterator type, something that has a method that returns a type T:<br />
<br />
<span style="font-family: "courier new", "courier", monospace;">T next();</span><br />
<br />
Now, if there is no "next item" to return, the iterator could return some other value, like <span style="font-family: "courier new", "courier", monospace;">-1</span> or <span style="font-family: "courier new", "courier", monospace;">null</span>. Of course, in some cases, <span style="font-family: "courier new", "courier", monospace;">-1</span> and <span style="font-family: "courier new", "courier", monospace;">null</span> are perfectly valid values, so this design turns out to be a fairly poor one.<br />
<br />
Instead, the iterator type may have to represent the "no next item" as a separate method, which must be called separately:<br />
<br />
<span style="font-family: "courier new", "courier", monospace;">interface Iterator<T> { // note the ugly brace placement</span><br />
<span style="font-family: "courier new", "courier", monospace;"> boolean hasNext();</span><br />
<span style="font-family: "courier new", "courier", monospace;"> T next();<br />}</span><br />
<br />
Now the caller can iterate like:<br />
<br />
<span style="font-family: "courier new", "courier", monospace;">while (iter.hasNext()) {</span><br />
<span style="font-family: "courier new", "courier", monospace;"> T value = iter.next(); </span><br />
<span style="font-family: "courier new", "courier", monospace;">}</span><br />
<br />
This could be simplified if a language supported more than one return value, like most languages support more than one parameter to a method:<br />
<br />
<span style="font-family: "courier new", "courier", monospace;">(boolean, T) next();</span><br />
<br />
The problem is what to return as a value when the <span style="font-family: "courier new", "courier", monospace;">boolean</span> value is <span style="font-family: "courier new", "courier", monospace;">false</span>. You could return a <span style="font-family: "courier new", "courier", monospace;">null</span> value, but the cost to doing this is <a href="https://www.infoq.com/presentations/Null-References-The-Billion-Dollar-Mistake-Tony-Hoare/" target="_blank">one billion dollars (payable to Tony Hoare)</a>.<br />
<img alt="one billion dollars" class="irc_mi" data-iml="1560467418137" height="332" src="https://www.thecalculatorsite.com/images/articles/20170505-dr-evil.jpg" style="margin-top: 11px;" title="one billion dollars" width="591" /><br />
<br />
Ecstasy addresses this common challenge by using <i>conditional</i> return values. For example:<br />
<br />
<pre><span style="font-family: "courier new", "courier", monospace;">/**
* An iterator over a sequence of elements.
*/
interface Iterator<Element>
{
/**
* Get a next element.
*
* @return a tuple of (true, nextValue) or (false) if no elements are available
*/
conditional Element next();
}</span></pre>
<br />
The <span style="font-family: "courier new", "courier", monospace;">next()</span> method is allowed to return <span style="font-family: "courier new", "courier", monospace;">True</span> and an element, or <span style="font-family: "courier new", "courier", monospace;">False</span> if there is no element. Consuming a conditional method is incredibly simple; here's a helper methods on the Iterator interface itself:<br />
<br />
<pre><span style="font-family: "courier new", "courier", monospace;">/**
* Perform the specified action for all remaining elements in the iterator, allowing for
* a possibility to stop the iteration at any time.
*
* @param process an action to perform on each element; if the action returns true, the
* iterator is considered "short-circuited", the method returns immediately
* and no more elements are iterated over
*
* @return true iff the iterator was short-circuited; otherwise false if the iteration
* completed without short-circuiting
*/
Boolean untilAny(function Boolean process(Element))
{
while (Element value := next())
{
if (process(value))
{
return True;
}
}
return False;
}</span></pre>
<br />
There's one other thing, the underlying reason that the <span style="font-family: "courier new", "courier", monospace;">next()</span> method can't return a "null", and that is because Ecstasy corrects the billion dollar mistake:<br />
<br />
<pre><span style="font-family: "courier new", "courier", monospace;">/**
* The Nullable type is the only type that can contain the value Null.
*
* Nullable is an Enumeration whose only value is the singleton enum value {@code Null}.
*/
enum Nullable { Null }</span></pre>
<br />
That one line is the actual code that defines the concept of <span style="font-family: "courier new", "courier", monospace;">Null</span> in Ecstasy. And here's what it means:<br />
<br />
<span style="font-family: "courier new", "courier", monospace;">Object o = Null; // ok ... Null is an Object<br />String s = Null; // error<br />Int i = Null; // error<br />Object[] a = Null; // error</span><br />
<br />
In other words, <span style="font-family: "courier new", "courier", monospace;">Null</span> is an object just like <span style="font-family: "courier new", "courier", monospace;">"Hello world!"</span> is an object, and all of the type rules apply to <span style="font-family: "courier new", "courier", monospace;">Null</span> just like they apply to any other object. (Among other benefits, you can kiss those NullPointerExceptions goodbye.)<br />
<br />
It really is that simple.<br />
<br />
<br /></div>
xtclang (Ecstasy)http://www.blogger.com/profile/10099977807321312612noreply@blogger.com2tag:blogger.com,1999:blog-3316231033424903659.post-24136788952450787822019-06-12T19:30:00.000-04:002019-06-12T19:38:45.568-04:00How to assert yourself more<div dir="ltr" style="text-align: left;" trbidi="on">
Assertions in software are valuable. Coupled with automated testing and continuous integration (CI), assertions help to harden software, and in doing so, provide an early warning system for breaking changes.<br />
<br />
But different assertions address different types of requirements. For example, some assertions should only be run while testing, because they are simply too expensive to be used in production. Other assertions are actually runtime checks, so they must always run, and must not be disabled. Lastly, assertions should be easy to write, even easier to read -- and when they fail, they should provide the necessary information to help a developer track down and understand the cause of the failure.<br />
<br />
The first thing to know about Ecstasy assertions is that they are checked at runtime, "<i>in production</i>". For example, if it is illegal to proceed using a negative number, then this assertion would check and prevent that condition:<br />
<br />
<span style="font-family: "courier new" , "courier" , monospace;">assert n.sign != Negative;</span><br />
<br />
Conceptually, that assertion is similar to (but simpler than) writing code like:<br />
<br />
<span style="font-family: "courier new" , "courier" , monospace;">if (n.sign == Negative)<br /> { <br /> throw new IllegalState(<br /> $"Assertion failed: n.sign != Negative, n={n}"); <br /> }</span><br />
<br />
Which would throw an exception with a text message like:<br />
<br />
<span style="font-family: "courier new" , "courier" , monospace;">Assertion failed: n.sign != Negative, <b>n=-1</b> </span><br />
<br />
An assertion handles all of that complexity automatically on behalf of the developer. Having detailed information -- the inputs to the assertion -- show up automatically when the assertion fails is invaluable for debugging a failure after the fact -- especially when a problem is not easily reproducible!<br />
<br />
Assertions can also be fine-tuned to throw an appropriate exception:<br />
<ul>
<li><span style="font-family: "courier new" , "courier" , monospace;">assert</span> throws <span style="font-family: "courier new" , "courier" , monospace;">IllegalState</span></li>
<li><span style="font-family: "courier new" , "courier" , monospace;">assert<b>:arg</b></span> throws <span style="font-family: "courier new" , "courier" , monospace;">IllegalArgument</span></li>
<li><span style="font-family: "courier new" , "courier" , monospace;">assert<b>:bounds</b></span> throws <span style="font-family: "courier new" , "courier" , monospace;">OutOfBounds</span></li>
<li><span style="font-family: "courier new" , "courier" , monospace;">assert<b>:TODO</b></span> throws <span style="font-family: "courier new" , "courier" , monospace;">UnsupportedOperation</span></li>
</ul>
The syntax for an assertion condition is the same syntax used in an <span style="font-family: "courier new" , "courier" , monospace;">if</span> or <span style="font-family: "courier new" , "courier" , monospace;">while</span> statement, so conditional declarations and assignments are naturally supported:<br />
<br />
<span style="font-family: "courier new" , "courier" , monospace;">// the iterator must have at least one item left<br />assert String s := iterator.next();</span><br />
<br />
A condition isn't even necessary if the assertion is being used to indicate that somehow execution reached some place that should have been impossible:<br />
<br />
<span style="font-family: "courier new" , "courier" , monospace;">assert; // just use "assert;" instead of "assert False;"</span><br />
<br />
In each case, the syntax is intended to clearly convey the intent of the developer, with as little excess as possible for the reader of the code to ingest.<br />
<br />
And what if the intent of the developer is to only have the assertion execute during testing, and <i>not</i> when the software is running "in production"? Fortunately, Ecstasy provides a simple way to enable an assertion only when testing:<br />
<br />
<span style="font-family: "courier new" , "courier" , monospace;">assert<b>:test</b> checkReferentialIntegrity();</span><br />
<br />
(Or only when debugging, by using <span style="font-family: "courier new" , "courier" , monospace;">assert:debug</span> to trigger a breakpoint when the assertion fails.) <br />
<br />
Similarly, if something is important to verify at runtime, but only needs to be checked the first time that the code is executed, then <span style="font-family: "courier new" , "courier" , monospace;">assert:<b>once</b></span> can be used:<br />
<br />
<span style="font-family: "courier new" , "courier" , monospace;">assert<b>:once</b> configLoaded;</span><br />
<br />
Lastly, if an assertion needs to be <i>occasionally</i> tested at runtime, but is too expensive to check every time -- such as when the assertion occurs inside a performance-critical loop -- then a sampling-based assertion may be appropriate:<br />
<br />
<span style="font-family: "courier new" , "courier" , monospace;">assert<b>:rnd(100)</b> checkConsistency(); // on average, 1 in 100 times</span><br />
<br />
But at the end of the day, the advanced options are just that: Advanced, and optional.<br />
<br />
Just the way that they should be.</div>
xtclang (Ecstasy)http://www.blogger.com/profile/10099977807321312612noreply@blogger.com2tag:blogger.com,1999:blog-3316231033424903659.post-47818065652944729212019-04-29T00:00:00.000-04:002019-04-29T00:00:26.866-04:00On Hierarchical Organization<div dir="ltr" style="text-align: left;" trbidi="on">
<br />
Many a software developer has referenced this saying:
<div class="MsoNormal" style="margin-left: .5in;">
<i style="mso-bidi-font-style: normal;">When
the only tool that you have is a hammer, every problem begins to look like a
nail.</i></div>
<div class="MsoNormal">
That is not to imply that a hammer is not useful. If there
is one conceptual hammer that – more so than any other – has repeatedly proven
its merit for managing – and <i style="mso-bidi-font-style: normal;">hiding</i> –
complexity, that would be the concept of <i style="mso-bidi-font-style: normal;">hierarchy</i>.
File systems are hierarchies. B*Trees and binary trees and Patricia tries and
parse trees are hierarchies. Most documents are internally organized as
hierarchies, including the common HTML, XML, and JSON formats. Most graphical
user interfaces are modeled as hierarchies. Many programming languages leverage
hierarchy to provide nesting, information hiding, scoping, and identity. How is
it that such a simple concept can be so universally useful?</div>
<div class="MsoNormal">
First of all, hierarchical organization enables very simple <i style="mso-bidi-font-style: normal;">navigation</i>. What this means is that at
any arbitrary point – called a <i style="mso-bidi-font-style: normal;">node</i> –
in a hierarchy, there is a well-known set of operations that are possible, such
as navigating from the current node to its <i style="mso-bidi-font-style: normal;">parent</i>
node, and navigating from the current node to any of its <i style="mso-bidi-font-style: normal;">child</i> nodes. If a node does not have a parent, then it is the <i style="mso-bidi-font-style: normal;">root</i> node, and if a node does not have
any child nodes, then it is a <i style="mso-bidi-font-style: normal;">leaf</i>
node.</div>
<div class="MsoNormal">
Child nodes are <i style="mso-bidi-font-style: normal;">contained</i>
within their parent node. Each child is uniquely identifiable by its parent,
for example by a name or some other unique attribute. A hierarchy is <i style="mso-bidi-font-style: normal;">recursive</i>; at any point in the
hierarchy, from that point down is itself a hierarchy. Since a hierarchy has a
single root and is recursive, each node in the hierarchy is uniquely
identifiable in the hierarchy by combining the identities of each successive
node starting with the root and proceeding down to the node; this identity is
the <i style="mso-bidi-font-style: normal;">absolute path</i> to that node. It is
possible to navigate between any two nodes in the same hierarchy by combining zero
or more child-to-parent navigations with zero or more uniquely identifiable
parent-to-child navigations; the sequence of these steps is a <i style="mso-bidi-font-style: normal;">relative path</i> between two nodes.</div>
<div class="MsoNormal">
These basic attributes of a hierarchy combine in amazingly
powerful ways. For example, since each node is itself the beginning of a
hierarchy of any size, it is possible to refer to that entire sub-hierarchy
simply by referring to that one particular node; this effectively <i style="mso-bidi-font-style: normal;">hides</i> the recursive complexity contained
– or <i style="mso-bidi-font-style: normal;">nested</i> – within that node. As a
result, it is possible to add, copy, move, or remove a hierarchy of any size
simply by adding, copying, moving, or removing the node that is the “root” of
that hierarchy.</div>
<div class="MsoNormal">
Using a hierarchy, it is incredibly simple to construct the
concept of <i style="mso-bidi-font-style: normal;">scope</i>. For example, a
scope could include only a specific node, or it could include a specific node
and all of its child nodes recursively to its <i style="mso-bidi-font-style: normal;">descendent</i> leaf nodes, or it could include a specific node and its <i style="mso-bidi-font-style: normal;">ancestor</i> nodes to the root node, or any
other combination of inclusion and exclusion that could be described in an
unambiguous manner.</div>
<div class="MsoNormal">
These concepts are incredibly simple, yet at the same time
incredibly powerful, and are leveraged liberally throughout the XVM, from
managing and hiding complexity for developers, to managing memory in an
execution context.</div>
<style>
<!--
/* Font Definitions */
@font-face
{font-family:Calibri;
panose-1:2 15 5 2 2 2 4 3 2 4;
mso-font-charset:0;
mso-generic-font-family:auto;
mso-font-pitch:variable;
mso-font-signature:3 0 0 0 1 0;}
@font-face
{font-family:Cambria;
panose-1:2 4 5 3 5 4 6 3 2 4;
mso-font-charset:0;
mso-generic-font-family:auto;
mso-font-pitch:variable;
mso-font-signature:3 0 0 0 1 0;}
/* Style Definitions */
p.MsoNormal, li.MsoNormal, div.MsoNormal
{mso-style-unhide:no;
mso-style-qformat:yes;
mso-style-parent:"";
margin-top:0in;
margin-right:0in;
margin-bottom:10.0pt;
margin-left:0in;
line-height:115%;
mso-pagination:widow-orphan;
font-size:11.0pt;
font-family:Calibri;
mso-fareast-font-family:Calibri;
mso-bidi-font-family:"Times New Roman";}
h2
{mso-style-priority:9;
mso-style-qformat:yes;
mso-style-link:"Heading 2 Char";
mso-style-next:Normal;
margin-top:10.0pt;
margin-right:0in;
margin-bottom:0in;
margin-left:0in;
margin-bottom:.0001pt;
line-height:115%;
mso-pagination:widow-orphan lines-together;
page-break-after:avoid;
mso-outline-level:2;
font-size:13.0pt;
font-family:Cambria;
mso-fareast-font-family:"Times New Roman";
color:#4F81BD;}
span.Heading2Char
{mso-style-name:"Heading 2 Char";
mso-style-priority:9;
mso-style-unhide:no;
mso-style-locked:yes;
mso-style-link:"Heading 2";
mso-ansi-font-size:13.0pt;
mso-bidi-font-size:13.0pt;
font-family:Cambria;
mso-ascii-font-family:Cambria;
mso-fareast-font-family:"Times New Roman";
mso-hansi-font-family:Cambria;
color:#4F81BD;
font-weight:bold;}
.MsoChpDefault
{mso-style-type:export-only;
mso-default-props:yes;
font-size:10.0pt;
mso-ansi-font-size:10.0pt;
mso-bidi-font-size:10.0pt;
font-family:Calibri;
mso-ascii-font-family:Calibri;
mso-fareast-font-family:Calibri;
mso-hansi-font-family:Calibri;}
@page WordSection1
{size:8.5in 11.0in;
margin:1.0in 1.25in 1.0in 1.25in;
mso-header-margin:.5in;
mso-footer-margin:.5in;
mso-paper-source:0;}
div.WordSection1
{page:WordSection1;}
-->
</style></div>
xtclang (Ecstasy)http://www.blogger.com/profile/10099977807321312612noreply@blogger.com0tag:blogger.com,1999:blog-3316231033424903659.post-14101729389558052922019-04-16T13:26:00.001-04:002019-04-16T13:26:30.157-04:00Explicit Intent: Enumerating the Priorities of Design<div dir="ltr" style="text-align: left;" trbidi="on">
<br />
<div class="MsoNormal">
All designs have priorities, but only some designs begin
with the end in mind. When priorities are not explicitly stated, it is easy to
chase the priorities that most effectively combine compulsive emotional appeal
with apparent ease of implementation, in lieu of the priorities that are most
valuable to the intended audience of a design. In order to create a coherent
design that serves the intended audience, the Ecstasy specification began with a
conscious discussion about priorities, and a series of explicit decisions as to
what those priorities would be:</div>
<ol start="1" style="margin-top: 0in;" type="1">
<li class="MsoNormal" style="mso-list: l0 level1 lfo1; tab-stops: list .5in;"><span style="mso-bidi-font-weight: bold;">Correctness</span>, aka <span style="mso-bidi-font-weight: bold;">Predictability</span>. The behavior of a
language must be obvious, correct, and predictable. This also incorporates
<i><span style="mso-bidi-font-weight: bold;">The Principle of Least Surprise</span></i>.</li>
<li class="MsoNormal" style="mso-list: l0 level1 lfo1; tab-stops: list .5in;"><span style="mso-bidi-font-weight: bold;">Security</span>. While generally not a
priority for language design, it is self-evident that security is not
something that one <i>adds to</i> a system; security is either in the
foundation and the substrate of a system, or it does not exist.
Specifically, <i><span style="mso-bidi-font-weight: bold;">a language must
not make possible the access to (or even make detectable the existence of)
any resource that is not explicitly granted to the running software</span></i>.</li>
<li class="MsoNormal" style="mso-list: l0 level1 lfo1; tab-stops: list .5in;"><span style="mso-bidi-font-weight: bold;">Composability</span>. High-level computer
languages are about composition. Specifically, <i><span style="mso-bidi-font-weight: bold;">a language should enable a developer to locate each piece of design
and logic in its one best and natural place</span></i>.</li>
<li class="MsoNormal" style="mso-list: l0 level1 lfo1; tab-stops: list .5in;"><span style="mso-bidi-font-weight: bold;">Readability</span>. Code is written
once, and referenced many times. What we call “code” should be a thing of
beauty, where <i><span style="mso-bidi-font-weight: bold;">form follows
function</span></i>.</li>
<li class="MsoNormal" style="mso-list: l0 level1 lfo1; tab-stops: list .5in;">Lastly,
a language must be <span style="mso-bidi-font-weight: bold;">recursive</span>
<i>in its design</i>. There is no other mechanism that predictably folds
in complexity and naturally enables encapsulation. <i><span style="mso-bidi-font-weight: bold;">It’s turtles, the whole way down</span></i>.</li>
</ol>
<br />
<h2>
On Predictability vs. Performance</h2>
<div class="MsoNormal">
<style>
<!--
/* Font Definitions */
@font-face
{font-family:"Cambria Math";
panose-1:2 4 5 3 5 4 6 3 2 4;
mso-font-charset:0;
mso-generic-font-family:auto;
mso-font-pitch:variable;
mso-font-signature:3 0 0 0 1 0;}
@font-face
{font-family:Calibri;
panose-1:2 15 5 2 2 2 4 3 2 4;
mso-font-charset:0;
mso-generic-font-family:auto;
mso-font-pitch:variable;
mso-font-signature:3 0 0 0 1 0;}
@font-face
{font-family:Cambria;
panose-1:2 4 5 3 5 4 6 3 2 4;
mso-font-charset:0;
mso-generic-font-family:auto;
mso-font-pitch:variable;
mso-font-signature:3 0 0 0 1 0;}
/* Style Definitions */
p.MsoNormal, li.MsoNormal, div.MsoNormal
{mso-style-unhide:no;
mso-style-qformat:yes;
mso-style-parent:"";
margin-top:0in;
margin-right:0in;
margin-bottom:10.0pt;
margin-left:0in;
line-height:115%;
mso-pagination:widow-orphan;
font-size:11.0pt;
font-family:Calibri;
mso-fareast-font-family:Calibri;
mso-bidi-font-family:"Times New Roman";}
h2
{mso-style-priority:9;
mso-style-qformat:yes;
mso-style-link:"Heading 2 Char";
mso-style-next:Normal;
margin-top:10.0pt;
margin-right:0in;
margin-bottom:0in;
margin-left:0in;
margin-bottom:.0001pt;
line-height:115%;
mso-pagination:widow-orphan lines-together;
page-break-after:avoid;
mso-outline-level:2;
font-size:13.0pt;
font-family:Cambria;
mso-fareast-font-family:"Times New Roman";
color:#4F81BD;}
span.Heading2Char
{mso-style-name:"Heading 2 Char";
mso-style-priority:9;
mso-style-unhide:no;
mso-style-locked:yes;
mso-style-link:"Heading 2";
mso-ansi-font-size:13.0pt;
mso-bidi-font-size:13.0pt;
font-family:Cambria;
mso-ascii-font-family:Cambria;
mso-fareast-font-family:"Times New Roman";
mso-hansi-font-family:Cambria;
color:#4F81BD;
font-weight:bold;}
.MsoChpDefault
{mso-style-type:export-only;
mso-default-props:yes;
font-size:10.0pt;
mso-ansi-font-size:10.0pt;
mso-bidi-font-size:10.0pt;
font-family:Calibri;
mso-ascii-font-family:Calibri;
mso-fareast-font-family:Calibri;
mso-hansi-font-family:Calibri;}
@page WordSection1
{size:8.5in 11.0in;
margin:1.0in 1.25in 1.0in 1.25in;
mso-header-margin:.5in;
mso-footer-margin:.5in;
mso-paper-source:0;}
div.WordSection1
{page:WordSection1;}
-->Â
</style>In the course of researching language design, one preterdominant
concern emerges: That of execution performance. While many different concerns
are evaluated and balanced against each other in a typical design, and while
the goal of performance is often explicitly ranked in a position of lesser
importance, in reality there is no one goal more considered, discussed, and
pursued. Regardless of the importance assigned to performance as a language
goal, performance to the language designer is a flame to a moth.</div>
<div class="MsoNormal">
Perhaps it is simply best to admit, up front, that no
language can survive – let alone succeed – without amazing feats of
performance. Yet performance as a goal tends to conflict with other goals,
particularly with respect to manageability, serviceability, and the quality of
the abstractions that are presented to the developer.</div>
<div class="MsoNormal">
Beginning programmers often ask: “Is language <i style="mso-bidi-font-style: normal;">A</i> faster than <i style="mso-bidi-font-style: normal;">B</i>?” After all, no one wants to be using a slow language, any more
than someone would want to buy a slow automobile or a slow computer. Speed is a
thrill, and speed in software execution holds no less attraction than a
souped-up hot rod with a throaty growl and a body-rumbling ride.</div>
<div class="MsoNormal">
The corollary to that question is “Why is language <i style="mso-bidi-font-style: normal;">B</i> slower than <i style="mso-bidi-font-style: normal;">A</i>?” The answers to this question tend to be very illuminating. Take
any two languages that compile to and execute as native machine code, and
compare their performance for a given task. Despite running on the same
hardware, and using the same hardware instruction set, one may be dramatically
slower than the other, by a factor of 10%, or 100% (half as fast), or even
1000% (an order of magnitude slower). How is such a difference possible?</div>
<div class="MsoNormal">
The answer lies in translation, specifically in the
automated translation of idioms. A language such as C selected idioms that
closely represented the underlying machine instructions of the day, which
allowed programmers to write simple programs that could be almost <i style="mso-bidi-font-style: normal;">transliterated</i> from C to machine code.
In other words, the language chose as its abstractions the same set of
abstractions that the CPU designers were using, or abstractions that were at
most one translation removed from the machine’s abstractions. This allowed for
very simple compilers, and made it extremely simple to support localized
optimization.</div>
<div class="MsoNormal">
A localized optimization is an optimization in the compiled
code that can be made using only information about code that is <i style="mso-bidi-font-style: normal;">most local to</i> the code that is being
optimized; in other words, information outside of the scope of the small amount
of code being optimized is not even considered. Many optimizations in the C
language, for example, are extremely local, such that they can be performed
without any information about code outside of a particular expression or
statement; it is hard to imagine more localized optimizations.</div>
<div class="MsoNormal">
However, there is a trade-off implicit in achieving such
simple and direct optimizations: The abstractions provided by the language are
constrained by the abstractions provided by the CPU. As one could rightfully surmise,
hardware abstractions tend not to be very abstract, and the abstractions
provided by hardware instruction sets tend to be only slightly better. In its
early days, the C language was jokingly referred to as “assembly with macros”,
because as a language, it was only slightly higher level than assembly itself.</div>
<div class="MsoNormal">
Computing efficiency is often stated in terms of a tradeoff
between time (CPU) and space (memory); one can often utilize one in order to
optimize for the other, subject to the law of diminishing returns.
Unfortunately, there is no single simple metric that captures computing
efficiency, but if the trade-off between time and space appeared as a graph
with time on one axis and space on the other, it might generally resemble the
shape of the curve <i style="mso-bidi-font-style: normal;"><span style="font-family: "Cambria Math"; mso-bidi-font-family: "Brush Script MT Italic";">y=1/x</span></i>,
which most closely approaches the origin at (1,1). If there were a single computing
efficiency measurement for a programming language, it could arguably be
represented by the closest that this trade-off curve approaches the origin
(0,0), which distance could be considered the minimum weighted resource cost. To
calculate a language’s efficiency for a particular purpose, one would calculate
the <i style="mso-bidi-font-style: normal;">inverse</i> of the minimum weighted
resource cost.</div>
<div class="MsoNormal">
While one can easily speak about efficiency in hypothetical
terms, a benchmark is a wonderful servant but a terrible master. The path
chosen in the design of the XVM is to consciously avoid limits on potential
efficiency by consciously avoiding contracts whose costs are not clearly defined
and understood. This approach can be explained in the inverse, by way of
example in existing languages and systems: Often, features and capabilities
that were considered to be “easy” implementation-wise and “free”
efficiency-wise when they were introduced, ultimately emerged as the nemesis to
efficiency, due to the inflexibility of the programming contracts that these
features and capabilities introduced<a href="https://www.blogger.com/u/2/blogger.g?blogID=3316231033424903659#_ftn1" name="_ftnref1" style="mso-footnote-id: ftn1;" title=""><span class="MsoFootnoteReference"><span style="mso-special-character: footnote;"><span class="MsoFootnoteReference"><span style="font-family: Calibri; font-size: 11.0pt; line-height: 115%; mso-ansi-language: EN-US; mso-bidi-font-family: "Times New Roman"; mso-bidi-language: AR-SA; mso-fareast-font-family: Calibri; mso-fareast-language: EN-US;">[1]</span></span></span></span></a>.</div>
<div class="MsoNormal">
To understand this, it is important to think of abstractions
as a two-sided coin: On one side, we see the benefit of the abstraction, which
allows a programmer to work with ever-larger and more powerful building blocks,
while the other side of the coin represents the cost of the abstraction, which
is called the <i style="mso-bidi-font-style: normal;">contract</i>. Imagine, for
example, having to build something in the physical world, out of actual matter.
One could conceivably build a structure out of atoms themselves, assembling the
necessary molecules and arranging them carefully into perfectly formed crystalline
structures. The contracts of the various elements are fairly well understood,
but yet we wouldn’t try to build a refrigerator of out individual atoms.</div>
<div class="MsoNormal">
One could imagine that building from individual atoms is the
equivalent of building software from individual machine instructions, in two
different ways: First, that the refrigerator is composed of atoms, just like
all software is executed at some level as machine instructions; and second,
that as the size and complexity of the constituent components increase, the minutiae
of the contracts of the sub-components must not be surfaced in the contracts of
the resulting components – those details must be hidable! This purposeful
prevention of the surfacing of minutiae is called <i style="mso-bidi-font-style: normal;">encapsulation</i>, and exists as one of the cornerstones of software
design. It is why one can use a refrigerator without knowing the number of
turns of wire in the cooling pump’s motor, and why one can use a software
library without worrying about its impact on the FLAGS register of the CPU.</div>
<div class="MsoNormal">
Ultimately, it is the recursive composition of software that
creates challenges for optimization. While low level optimizations are focused
on the creation of more efficient low level code, higher level optimizations
rely on explicit knowledge of what portions of a component’s contract – or the
contracts of the various sub-components – can be safely ignored. In other
words, the optimizer must be able to identify which contractual effects are
ignored or discarded by the programmer, and then leverage that information to
find alternative execution solutions whose contracts manage to cover at least
the non-discarded and non-ignored contract requirements. Higher-level optimizations
target the elimination of entire aspects of carefully defined behavioral
contracts, and as a result, they typically require extensive information from
across the entire software system; in other words, high-level optimizations
tend to be non-localized to the extreme! No software has been more instrumental
in illustrating this concept than Java’s Hotspot virtual machine, whose
capabilities include the inlining of potentially polymorphic code by the
determination that the potential for dynamic dispatch is precluded, and the
elimination of specific memory barriers in multi-threaded programs as the
result of escape analysis.</div>
<div class="MsoNormal">
To enable these types of future optimizations, the contracts
of the system’s building blocks must be explicit, predictable, and purposefully
constrained, which is what was meant by the goal of “consciously avoiding
contracts whose costs are not clearly defined and understood.” The contracts in
the small must be encapsulatable in the large, which is to say that contracts
must be composable in such a way that side-effects are not inadvertently
exposed. It has been posited<a href="https://www.blogger.com/u/2/blogger.g?blogID=3316231033424903659#_ftn2" name="_ftnref2" style="mso-footnote-id: ftn2;" title=""><span class="MsoFootnoteReference"><span style="mso-special-character: footnote;"><span class="MsoFootnoteReference"><span style="font-family: Calibri; font-size: 11.0pt; line-height: 115%; mso-ansi-language: EN-US; mso-bidi-font-family: "Times New Roman"; mso-bidi-language: AR-SA; mso-fareast-font-family: Calibri; mso-fareast-language: EN-US;">[2]</span></span></span></span></a>
that “all non-trivial abstractions, to some degree, are leaky,” but each such
leak is eventually and necessarily realized as a limit to systemic efficiency.</div>
<div style="mso-element: footnote-list;">
<br clear="all" />
<hr align="left" size="1" width="33%" />
<div id="ftn1" style="mso-element: footnote;">
<div class="MsoFootnoteText">
<a href="https://www.blogger.com/u/2/blogger.g?blogID=3316231033424903659#_ftnref1" name="_ftn1" style="mso-footnote-id: ftn1;" title=""><span class="MsoFootnoteReference"><span style="mso-special-character: footnote;"><span class="MsoFootnoteReference"><span style="font-family: Calibri; font-size: 12.0pt; line-height: 115%; mso-ansi-language: EN-US; mso-bidi-font-family: "Times New Roman"; mso-bidi-language: AR-SA; mso-fareast-font-family: Calibri; mso-fareast-language: EN-US;">[1]</span></span></span></span></a>
Such contracts are <i style="mso-bidi-font-style: normal;">software legacy</i>,
meaning that the contracts cannot be altered without disclaiming the past; in
other words, altering the contracts will break everything.</div>
</div>
<div id="ftn2" style="mso-element: footnote;">
<div class="MsoFootnoteText">
<a href="https://www.blogger.com/u/2/blogger.g?blogID=3316231033424903659#_ftnref2" name="_ftn2" style="mso-footnote-id: ftn2;" title=""><span class="MsoFootnoteReference"><span style="mso-special-character: footnote;"><span class="MsoFootnoteReference"><span style="font-family: Calibri; font-size: 12.0pt; line-height: 115%; mso-ansi-language: EN-US; mso-bidi-font-family: "Times New Roman"; mso-bidi-language: AR-SA; mso-fareast-font-family: Calibri; mso-fareast-language: EN-US;">[2]</span></span></span></span></a>
<a href="https://www.joelonsoftware.com/2002/11/11/the-law-of-leaky-abstractions/">https://www.joelonsoftware.com/2002/11/11/the-law-of-leaky-abstractions/</a>
</div>
</div>
</div>
<style>@font-face {
font-family: "Cambria Math";
}@font-face {
font-family: Calibri;
}@font-face {
font-family: "Brush Script MT Italic";
}p.MsoNormal, li.MsoNormal, div.MsoNormal { margin: 0in 0in 10pt; line-height: 115%; font-size: 11pt; font-family: Calibri; }p.MsoFootnoteText, li.MsoFootnoteText, div.MsoFootnoteText { margin: 0in 0in 0.0001pt; font-size: 12pt; font-family: Calibri; }span.MsoFootnoteReference { vertical-align: super; }a:link, span.MsoHyperlink { color: blue; text-decoration: underline; }a:visited, span.MsoHyperlinkFollowed { color: purple; text-decoration: underline; }span.FootnoteTextChar { }.MsoChpDefault { font-size: 10pt; font-family: Calibri; }div.WordSection1 { }</style> <br />
<style>
<!--
/* Font Definitions */
@font-face
{font-family:Calibri;
panose-1:2 15 5 2 2 2 4 3 2 4;
mso-font-charset:0;
mso-generic-font-family:auto;
mso-font-pitch:variable;
mso-font-signature:3 0 0 0 1 0;}
/* Style Definitions */
p.MsoNormal, li.MsoNormal, div.MsoNormal
{mso-style-unhide:no;
mso-style-qformat:yes;
mso-style-parent:"";
margin-top:0in;
margin-right:0in;
margin-bottom:10.0pt;
margin-left:0in;
line-height:115%;
mso-pagination:widow-orphan;
font-size:11.0pt;
font-family:Calibri;
mso-fareast-font-family:Calibri;
mso-bidi-font-family:"Times New Roman";}
.MsoChpDefault
{mso-style-type:export-only;
mso-default-props:yes;
font-size:10.0pt;
mso-ansi-font-size:10.0pt;
mso-bidi-font-size:10.0pt;
font-family:Calibri;
mso-ascii-font-family:Calibri;
mso-fareast-font-family:Calibri;
mso-hansi-font-family:Calibri;}
@page WordSection1
{size:8.5in 11.0in;
margin:1.0in 1.25in 1.0in 1.25in;
mso-header-margin:.5in;
mso-footer-margin:.5in;
mso-paper-source:0;}
div.WordSection1
{page:WordSection1;}
/* List Definitions */
@list l0
{mso-list-id:933440847;
mso-list-template-ids:-489244920;}
ol
{margin-bottom:0in;}
ul
{margin-bottom:0in;}
-->
</style></div>
xtclang (Ecstasy)http://www.blogger.com/profile/10099977807321312612noreply@blogger.com2