From mboxrd@z Thu Jan 1 00:00:00 1970 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on polar.synack.me X-Spam-Level: X-Spam-Status: No, score=-0.3 required=5.0 tests=BAYES_00, REPLYTO_WITHOUT_TO_CC autolearn=no autolearn_force=no version=3.4.4 X-Google-Thread: 108717,c1d77749223627c8 X-Google-Thread: 1108a1,8802fe2212b159e1 X-Google-Thread: 114809,8802fe2212b159e1 X-Google-Thread: 103376,1e8296e52e7e94a6 X-Google-Attributes: gid108717,gid1108a1,gid114809,gid103376,public X-Google-Language: ENGLISH,ASCII-7-bit Path: g2news1.google.com!news1.google.com!news.glorb.com!prodigy.com!newsfeed.telusplanet.net!newsfeed.telus.net!snoopy.risq.qc.ca!msc1.onvoy!onvoy.com!news.mmm.com!not-for-mail From: Programmer Dude Newsgroups: comp.programming,comp.object,comp.lang.smalltalk,comp.lang.ada Subject: Re: Static vs. Dynamic typing (big advantage or not)---WAS: c.programming: OOP Date: Fri, 03 Sep 2004 15:10:42 -0500 Organization: Wrenn Productions, LTD Message-ID: References: Reply-To: Programmer Dude NNTP-Posting-Host: 169.10.86.157 Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: 7bit X-Newsreader: Forte Agent 2.0/32.652 Xref: g2news1.google.com comp.programming:9010 comp.object:6380 comp.lang.smalltalk:2885 comp.lang.ada:3306 Date: 2004-09-03T15:10:42-05:00 List-Id: Nick Roberts writes: >>> I personally like Smalltalk. >> >> Ditto. I borrowed some of it's more interesting ideas for >> my own language, BOOL. > > Would you say a bit more about this language (BOOL), please. Well, you may be sorry you asked.... here's a post from a while back to get you started. If you're still interested, I can say (much, much) more.... The first section is from the Foreward of the language "book". What follows is a reply to someone else who asked (and was prolly sorry they did).... ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Foreword, Forward, Forewarned, Forearmed! [1] BOOL2000 is a language of a fevered imagination. It's the final output of years of ruminating, bursts of activity and huge dry spells. BOOL is at least twelve years in the making, and it has been through many versions and variations. It's been a bit like a whittling project I've been working on in my spare time for years and years! It was never intended as a serious language, so developing the spec and the supporting software (for what is a language spec without at least one compiler?) has never been a serious project. [...] BOOL is a labor of love. It is not intended to be a serious programming language, but as a kind of work of art. Which is not to say it's a good work of art, just that it's a work of art. Therefore, you should judge it for its appearance more than for its utility. Think of it as a sculpture, not an ideal computer programming language. [1] Four Words! ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ So keep that in mind! > Better it seems would be to have a tag bit on each first-class- > pointer which says whether it's a literal constant or not, > and if it is then don't bother with all that overhead. No, because then the Run Time Engine needs to know about the contents of the Objects. It may not. There is no real difference between asking a variable numeric Object to place a reference to itself on the PStack and asking a constant numeric Object to do the same. SOMEONE has to do it, and it might as well be the one who knows the Object best: the Object. > For example, there can be a tag byte that tells the basic type, > and the first bit can simply decode whether it's literal > constant or not, and other bits decode more detailed type info > used later down the line. Objects do, in fact, carry some generic state information, and in this case, a relevant one is the READONLY flag. In BOOL, literals are real numeric Objects just like variable numerics About the only difference is that they are READONLY. But this state information is enclosed in the Object, the RTE may not (generally speaking) access it directly. > As for doing argument evaluation in parallel (when more than one > argument is something other than a literal constant), here's some > comments: First, it's bad to have a single stack pointer that is > directly diddled by several different processes. Of course. The PStack is an active singleton Object in the BOOL environment. So are the AddressSpace, DataSpace and NameSpace servers. > Given that, you could organize it like this: Your goal is to > push all evaluated arguments onto the stack before calling the > primary function (the CAR of the form), right? Yes, although the verbiage is a little off. There is no primary function to call. Once the PStack has the expected values on it, we send the Message to the Target Object. In Lisp, we might write it like this: (send-a-message 'ADD Target (list arg1 arg2 ... argN)) The send-a-message function would first push the arguments onto the PStack. Then send the ADD message to the Target. The Target is responsible for dispatching the message to a handler. The handler expects to find the Objects it needs for input on the PStack. > So it's not a case of pushing several arguments unrelated to each > other, but it's a case of creating a stack frame which contains > *all* the various evaluated arguments in correct sequence, and > then passing that stack frame to the primary function. Fine up to the last bit. The "primary function" only takes a message as input. Its input data in on the PStack. > So what you do is create an instance of a stack-frame-builder, > and tell that object you want for example five slots in this > frame. Then you tell each of the argument evaluators which > stack-frame-builder you're using and which stack offset that > particular argument should use. No thanks. Too complex at run time and requires too much information to be shared within the system. The RTE borrows from Forth in being very, very simple. >> All integers belong to the same class ("Model" in BOOL). The >> Model contains a *single* instance of the code necessary to do >> anything an integer can do. (All object instances have a >> reference to their Model, so all "methods" in BOOL are "virtual". > > So each integer object has within it (1) a type-code that says > what size of integer it really is (16-bit 32-bit bignum whatever), > (2) the actual data appropriate for that size integer, and (3) a > link to the class (model) for all integers? Very close! It specifically looks like this (BOOL runs within a virtual environment that (currently) consists of 32-bit "cells"): +----+----+----+----+ | signature | TT | 0 (TT == Meta-Class) +----+----+----+----+ | flags | 1 +----+----+----+----+ | Name handle | 2 (handle to NameSpace) +----+----+----+----+ | Model handle | 3 (handle to AddressSpace) +----+----+----+----+ | data area | 4,5,6,7 +----+----+----+----+ ALL BOOL instance Objects (i.e. "data") have basically the same first four cells (obviously, the flags, name and Model will have different values). BOOL has less than a dozen "meta-classes" of which **everything** is an instance. There is a Model meta-class, an Action meta-class, etc. All instance Objects belong to the Instance meta-class, therefore all such have the same "TT" value. Instance Objects of different types (e.g. strings, real numbers, integer numbers, user-defined types) will have a different Model (the fourth cell). Each Meta-class has an Executive that handles Messages sent to objects of its class. The Executives, like the RTE, are designed to be as simple as possible and generally handle only very basic Messages. The real meat is in the Actions of each Model for each defined *type*. The data area, up to four bytes, is used as required by the Model ("type") and *flavor*. For instance, the BOOL integer type has four basic flavors: 32-bit, 64-bit, 96-bit and 128-bit. Each of these has signed and unsigned flavors. (Flavor information is kept in the flags cell.) Models with more than 128 bits of data use the data area to keep a handle to the actual data in the Data Space. You'll note that BOOL Objects keep their name even after compiling. A BOOL Image *can* be (more or less) fully decompiled (comments are lost). Whew.... anyway.... > So if you want to add an integer and some other kind of number, > depending on which sequence you place the two numbers, it might > pass the task to the integer model or to the other-kind-of-number > model, which would then have to notice what the other argument > was, and in the end both cases go to the code for coercing one > to the other type and doing the operation? Not quite. The Target Object would need to examine its parameter Object(s). Let's use a real example... *int2 n =100 -- {*int2} is an alias for {*int %64} *double d -- {*double} aliases {*real %64} set: d n -- set the double to the integer set: n d -- set the integer to the double In the first case, {d} would inspect {n} by sending an internal Message {M:} asking for its Model. If it knows how to do the conversion, it will. If it can't, it will ask if {n} can supply a representation of {d}'s type. If {n} replies, "Huh?", then no conversion is possible, and the attempt fails. The second case would be the same, but with reversed roles. So, the proceedure is: (1) check parameter type(s), (2) if conversion is required AND if we can do it, do it, else (3) ask if the parameter can do it, and if that fails (4) throw an exception. > So in the integer model, for example, there must be code to > dispatch depending on what message class (add, subtract, > multiply, divide, power, exp, log, sine, cosine, etc.)... Message *name*, but yes. There are the Messages add:, sub:, mul: div: pow: exp: log: sin: cos:, etc. There is an Action, owned by the *int Model, that handles each Message. That is, performs an integer operation on integers. > ...and what type the other argument is? No. The other argument must be of the same type. For example here, integers would (probably) know how to make an integer from any other numeric Model (likewise, reals would know how to make a real). Any operation depending on a parameter is responsible for testing and coercing that parameter. Per above, it can request the parameter's help. > How is this better than the LISP way, where a generic function is > called which already knows what arithmetic operation is to be > performed, but it must dispatch on the types of each of the two > arguments? ?!?! Who said it had to be better?? ;-)