Re: Smalltalk Implementor

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
6 messages Options
Reply | Threaded
Open this post in threaded view
|

Re: Smalltalk Implementor

David Simmons
"Paul Chapman" <[hidden email]> wrote in message
news:9foj3m$3bg$[hidden email]...

> Eliot,
>
> [I find I'm not comfortable with the nested >s approach to quoting, so I'm
> going to revert to the CompuServe convention which was the first I was
> exposed to.  If anyone feels this is a breach of Usenetiquette, please let
> me know.]
>
> >>ANSI defines that blocks are recursive and have local temporaries<<
>
> Does that mean that block parameters are also local?  Wouldn't this break
> code which uses the (eg, final) value of a parameter outside the block?
>
> >>During this walk one will naturally detect if the return point is on the
> same stack<<
>
> I get it.
>
> >>redesign the instruction set to support the ANSI standard definition of
> blocks<<
>
> A good idea.
>
> I went looking for a copy of the standard on the web, but the links I
tried
> were broken.  Having served many years ago on the APL standards committee,
I
> remember that draft standards are freely available, but that ISO/ANSI like
> to get their money for the real thing.  I guess I might have to shell out.
>
> Of course, this is not a hint to anyone here that they email me any copy
of
> the final draft they might have lying around on their hard drives: that
> would be a breach of copyright.
>
> >>You want to read Dave Simmons' posts on selector namespaces in the AOS
and
> SmallScript engines then. Dave has taken this farther than any other
> Smalltalk implementor I know of.  He has done selector namespaces and
> multi-methods<<
>
> I have already observed that many of Dave's ideas coincide with mine, even
> though mine were developed independently (honest!).

It happens to me all the time <g>. I have built things and then some time
later find out that someone else has independently designed the same or
similar thing. That just says to me that these are fundamental ideas in CS.

> My ideas for language
> extensions to make Smalltalk "seem like" a functional/procedural language
> are also very similar to his, although my approach will be to supply
> multiple, open-source compilers for different "views" of the underlying OO
> mechanism (all compiling code for the same VM, of course).

The AOS Platform (upon which SmallScript is built) provides that same
facility. So too, does the Microsoft.NET Platform. I.e., a universal virtual
machine (object model, execution engine, etc).

>
> In my scheme, for example, the expression "Sin (x)" is a message send with
> receiver "Sin" (a poolDictionary entry of class Function), argument "x",
and
> a new kind of selector (a "call selector"?) which is nevertheless treated
> the same way as Smalltalk selectors by the VM.  I haven't yet looked
deeply
> enough into Dave's approach to find out if it's similar.

In SmallScript, there are additional message forms:

    dot-msg, parenthetical, array-slice, property, etc.
        x.y;
        foo(...);
        [...][...]...;
        {...}

Eval
[
    |s| := 'foobar' copy.

    s[1] := $F.
    |b| := s[4:7].

    "" A regular expression used in a slice
    |t| := (b = s[`b.*']). "" <t> ==> <true>

    "" A regular expression replace assignment
    s[`b.*'] := 'Barsoom'. "" ==> 'FooBarsoom'

    ""Actually compiled as:
    s[`b.*']('Barsoom').
].

Which would be declared as:

Method behavior: String [
[<RegEx>rx](v)
    ...
].

=================
Here are some parenthetical-msg-forms.

    self foo(...)
    self.foo(...)
    foo(...)

The compiler will attempt to resolve the "message" name for a parenthetical
form, as a variable. If it cannot resolve it as a variable, then it will
issue it as a message form.

Thus given the expression:

    foo(...)

a) Attempt to resolve <foo>. If resolved, then the message is #(...) and
will be sent to <foo>. Noting that, by definition, #(...) messages are
aliased to #value... messages.

For example:

Eval
[
    |foo| := [:a| a+a].

    foo(1) "" ==> returns 2
].

b) If the resolution fails, then treat it as a message of the form #foo(...)
and send that message to <self> as a function send. The function send will
try to resolve it as an instance method, but if that fails it will look for
methods in the visible namespaces (which includes functions in DLL's).
Noting that the class and superclasses are part of the visible namespaces,
and so there methods will be resolved.

Therefore we can write:

    |s| := String(10).

    Which is the same as:
    |s| := String new: 10.

    Because:
    <Constructor> defines #value to invoke #new.
    <Constructor> defines #value: to invoke #new:.

Object
    Behavior
        Constructor
            Class
            Metaclass

As in:
-----
Method behavior: Constructor [
value: arg

    ^self new: arg
].

OR: (as it is actually declared)
-----
Method behavior: Constructor [
(arg)
    tail:return(self new)
].

We can declare parenthetical messages as in:

Method behavior: Bar [
foo(arg)
    ...
].

By default, the symbol manager will automatically alias single argument
parenthetical messages to their #name: equivalent. It will similarly alias
objective-c style message forms to their parentical representation. So the
above declaration is identical to declaring:

Method behavior: Bar [
foo: arg
    ...
].

Similarly, to see this form, mapped to Objective-C:
---
Method behavior: Bar [
foo(arg1, arg2)
    ...
].

Is identical to declaring (objective-c style):
Method behavior: Bar [
foo: arg1 : arg2
    ...
].

Which can be evaluated equivalent as in:

eval [
    "" The following expressions will result in the
    "" same code sequence and resulting method invocation.

    "" One variant style
    Bar().foo(1,2).

    "" Another variant style
    Bar() foo(1,2).

    "" Classic Smalltalk with an Obj-C style message
    Bar new foo: 1 : 2.

    "" Which is exactly the same as
    (Bar new) foo: 1 : 2.

    "" Which theoretically could be treated by the AOS
    "" platform symbol machinery as: (but isn't)
    (Bar new) foo: 1 with: 2.
].

NOTE: The "." message form has a different precedence, and it will attempt
to statically resolve references at compile time.

Methods can also have two different names to enable unification of
parenthetical forms with keyword message forms. This is a key feature for
dealing with external languages.

Method behavior: Blah [::altName(<>,<>)
a: arg1 b: arg2
    ...
].

Where we can invoke it identically as:

eval [

    |v| := Blah().  "" same as "Blah new"

    "" Classic st-style
    v a: 1 b: 2.

    "" Or obj-c style
    v altName: 1 : 2.

    "" OR
    v altName(1,2).

    "" Or
    v.altName(1,2).
].

"" Or looking at an instance method form
Method behavior: Blah [
msg
    "" Classic st-style
    self a: 1 b: 2.

    "" Or obj-c style
    self altName: 1 : 2.

    "" OR
    self altName(1,2).

    "" Or
    self.altName(1,2).

    "" Or
    altName(1,2).
].

>
> >>
> > Ask me later whether interfaces are first-class objects -- ie when I
> figure
> > out what they are.
>
> It wouldn't be Smalltalk if they *weren't* first-class :)
> <<

Interfaces are first class objects in SmallScript <g>. They can also provide
concrete mixin behavior and are part of the type system.

Interface
    name: Y
    inst-vars: a,b
    class-vars: c,d
    shared-vars: e,f
    ...
[
    Method [
    someMsg
        ...
    ].
]. "" End Interface Y

"" OR
Interface name: Y
{
    Method [
    someMsg
        ...
    ]
} "" End Interface Y

=== Other Examples ===

Interface name: X.

Class name: Blah implements: X.
Class name: Bleck implements: X.
---
Eval [
    Blah() isKindOf: X) "" ==> returns <true>
    Bleck() isKindOf: X) "" ==> returns <true>
].

"" Or using multi-method declarations we can write
"" a method which will only bind for <Blah | Bleck>
Function [
abc(<Blah|Bleck> anX)
    ...
].

"" or we can generalize it to bind on <X>'s.
Function [
abc(<X> anX)
    ...
].

"" or parameterized types.
Method behavior: SomeClass [
abc(<X|self> anXOrSelf)
    ...
].

"" or parameterized types where arg2
"" must be a kind-of anX.behavior
"" (there are many more variations on this theme
""  for in/out args, array specifications, etc)
Method behavior: SomeClass [
abc(<X> anX, <anX> arg2)
    ...
].

"" Or using multi-method declarations
Method behavior: SomeClass ["" Same as ::abc(<>)
abc: <X> anX
    ...
].

"" Or using multi-method declarations for a class-method
Method behavior: SomeClass.class [
abc: <X> anX
    ...
].

"" Or going further and scoping it

Method behavior: SomeClass.class scope: SomeLexicalScope [
abc(<X> anX)
    ...
].

"" Or
Method behavior: SomeClass.class scope: private [
abc: <X> anX
    ...
].

"" Or
Method behavior: SomeClass.class scope: A.B.C [
abc: <X> anX
    ...
].

"" Or
Method behavior: SomeClass.class scope: A.B.C before [
abc: <X> anX
    ...
].

"" Or
Method behavior: SomeClass.class scope: A.B.C [<$before>
abc: <X> anX
    ...
].

"" Or
Method behavior: SomeClass.class scope: A.B.C after [
abc: <X> anX
    ...
].

"" Or
Method behavior: SomeClass.class scope: A.B.C [<$after>
abc: <X> anX
    ...
].


"" Or
Method behavior: SomeClass.class scope: A.B.C around [
abc: <X> anX
    ...
].

"" Or
Method behavior: SomeClass.class scope: A.B.C [<$around>
abc: <X> anX
    ...
].

etc.

>
> :-)
>
> >>My person-year estimate is based on a C implementation<<

That's a minimum for an experienced VM designer to build a reasonable base
implementation.

>
> It'll be C in the end, naturally.

Why not Eiffel, or ML?

Or, if you're really looking to experiment quickly, why not build on an
existing open-source Lisp/scheme implementation?

>
> Cheers, Paul
>
>


Reply | Threaded
Open this post in threaded view
|

Re: Smalltalk Implementor

Paul Chapman
Dave,

Thank you for your long and detailed reply, which has presented me with many
interesting ideas.

>>
> I have already observed that many of Dave's ideas coincide with mine, even
> though mine were developed independently (honest!).

It happens to me all the time <g>. I have built things and then some time
later find out that someone else has independently designed the same or
similar thing. That just says to me that these are fundamental ideas in CS.
<<

This explains why there's nothing on earth quite like VB. :-)

>>
    dot-msg, parenthetical, array-slice, property, etc.
        x.y;
        foo(...);
        [...][...]...;
        {...}
<<

I couldn't find any examples of {} in the rest of your message.

I also intend to put a "." syntax in.  I'm not sure I like the implications
for lexical analysis, though -- and therefore the implications for very
close attention by the programmer.  But then again "." is also used for the
decimal point, so I suppose the damage is already done.

In my design (which remember is not a superset of Smalltalk, but another
available source language) I shall probably use "," as a statement separator
(actually an expression separator -- I have never liked the presence of
"statements" in non-procedural languages).

Also, in my design, "a.b" will usually carry the same kind of meaning as "a
at: #b" or "a[#b]": ie, the argument passed to the "." method would be "#b".
Is that the case in your approach?

>>
    s[1] := $F.
<<

I also envision this syntax, with similar semantics to yours.  In my mind,
"[]:=" is a message selector of some kind.  The programmer has control over
the semantics since he/she can rewite the "[]:=" method.

I'm also toying with trying to make "a := 3" a message send.  Of course,
":=" changes the value of the reference of the name "a" rather than the
current referent of "a".  Some object has to be interposed between "a" and
its referent to receive the ":=" message; this object is probably best
called a "slot".  (I've only recently found out about "slots", so my
nomenclature may be inappropriate and/or my semantics inaccurate).

The "default" slot would delegate every message to its contents (formally
using #doesNotUnderstand:, in practice by some cleverness in the VM for
performance) apart from ":=".  Formally, a slot would usually be an indexed
pointer object of size 1; this avoids the infinite regression since #at:put:
is not an assignment.

There is a problem, though: when does a "variable" refer to its slot, and
when to the contents of its slot (the "real" object)?  The resolution seems
to be to use the slot when the variable is used as a receiver, but the
object (possibly via an implicit send of #slotContents) elsewhere.

I may not pursue this.  The semantics end up more convoluted than allowing
the OO oddity of assignment (although they would be invisible to Smalltalk
programmers who don't know about them).

OTOH, slots add daemons (which I have also recently learnt about) as
fundamental.  I'll get back to you on this.

>>
    |b| := s[4:7].
<<

Can the programmer change the semantics of this syntax?  I'm assuming that
there's a selector here, something like "[:]", for which I can define my own
method.  Is that right?

>>

    "" A regular expression used in a slice
    |t| := (b = s[`b.*']). "" <t> ==> <true>
<<

Interesting that you've added regular expressions to the base image.  I view
(proper) programming languages as divided into four categories: procedural,
functional, OO and logic/backtracking.  The last category is the one I've
had least experience of, although I did once implement a true LR(K) parser
(in, guess what? APL).  I do remember doing a short course in Snobol at
college, but I've forgotten all of fit.  And I've never had to learn Perl.
:-)

>>
Method behavior: String [
[<RegEx>rx](v)
    ...
].
<<

I assume <RegEx> is a type.  Is it compulsory or optional in this
declaration?

>>by definition, #(...) messages are aliased to #value... messages<<

Hmm.  I had not thought of this approach.  The natural way that blocks
become "functions" is nice (although of course the ZeroArgumentBlock method
with selector "()" can be defined as "self value" for the same behaviour).

>>If the resolution fails, then treat it as a message of the form #foo(...)
and send that message to <self> as a function send<<

I have to say I don't like this overloading of syntax.  Admittedly there's
nothing wrong with the bare name "foo" standing for a selector rather than
an object -- we already have this with unary message syntax.  But that's not
perfect -- how many times a day do you debug '"self" not understood'? :-)

I think I want to stick to the principal that the leftmost thing is always a
receiver.

>>Interfaces are first class objects in SmallScript <g><<

Let me make things clear: they will of course be such in my system. :-)

>>They can also provide concrete mixin behavior and are part of the type
system<<

I haven't yet given a great deal of though to types, although I strongly
suspect they will be necessary for performance, even if not for expressivity
or self-documentation, since the app in which my Smalltalk is to be embedded
is real-time, and there are places where performance will be paramount.

OTOH, maybe by the time it's finished, CPUs will be fast enough that I won't
have to worry. :-)

[I looked at the work the Self group did on runtime recompilation with both
fascination and dismay.  I can see they had a lot of fun, but the sad thing
is that over the period of their study improvements in CPU speed achieved
what they did and more.  I have mixed feelings about the amount of effort
put into optimization techniques.  Then again, I have unmixed feelings about
a world based on CISC architecture.  Long live the ARM!]

So I'll archive your type examples until I've had a change to think this
through for myself.

>>
>
> It'll be C in the end, naturally.

Why not Eiffel, or ML?
<<

Short answer: I have not used either language.

Long answer: I'm trying both to understand the internals of the Smalltalk VM
and design an OO language of my own.  Just at the moment, I don't need a
third new language in the mix. :-)

[Aside: when I wrote I-APL I first designed and implemented a language in
which to implement it.  I-APL had to run on 64K machines because it was
aimed at schools which in the mid-80s usually had access to little more than
Z80- or 6502-based machines.  It also had to be highly portable for the same
reasons, and even be able to run from ROM.  I therefore decided I needed a
stack-based VM (this was before I ever encountered any VM-based language, or
even knew the term).  I looked at Forth, which was the natural existing
choice, but compatibility of published implementations across different
platforms would have been hell to resolve.

In the end, my choice was right: I built an IDE (again, before I knew the
term -- I called it "DE" and the language "DEL", which caused an unforseen
problem in MSDOS the first time I tried to run the executable !:-) which
provided a crash-proof emulation of the VM, breakpoints, watches, all of
that.  The source-code syntax was pretty, and added things that Forth didn't
have.  It took a month to write the IDE in C.  Ah, those were the days when
I could code FAST.

Finally, the compiler was writen in STSC APL*PLUS/PC.  It took 7 hours to
run.]

>>
Or, if you're really looking to experiment quickly, why not build on an
existing open-source Lisp/scheme implementation?
<<

Same reason: don't know 'em.  I learnt my skills on the practical side of
the industry (APL: practical?), and so to my great shame have never used
Lisp in anger, although I still have an archived paper design for a Z80 Lisp
implementation -- in red ink, for some reason, I recall -- which never saw
the light of day: I guess I must have been excited about it once.  My
college course did not cover Lisp, which annoys me still.  I was introduced
to Church's lambda notation, though, so I understand the functional
principals.  CLOS, OTOH, is nothing more than a name to me. :-(

Cheers, Paul


Reply | Threaded
Open this post in threaded view
|

Re: Smalltalk Implementor

David Simmons
"Paul Chapman" <[hidden email]> wrote in message
news:9fp49b$v61$[hidden email]...
> Dave,
>
> Thank you for your long and detailed reply, which has presented me with
many
> interesting ideas.
>
> >>
> > I have already observed that many of Dave's ideas coincide with mine,
even
> > though mine were developed independently (honest!).
>
> It happens to me all the time <g>. I have built things and then some time
> later find out that someone else has independently designed the same or
> similar thing. That just says to me that these are fundamental ideas in
CS.

> <<
>
> This explains why there's nothing on earth quite like VB. :-)
>
> >>
>     dot-msg, parenthetical, array-slice, property, etc.
>         x.y;
>         foo(...);
>         [...][...]...;
>         {...}
> <<
>
> I couldn't find any examples of {} in the rest of your message.
>
> I also intend to put a "." syntax in.  I'm not sure I like the
implications
> for lexical analysis, though -- and therefore the implications for very
> close attention by the programmer.  But then again "." is also used for
the
> decimal point, so I suppose the damage is already done.

Once it is in there for namespaces and other path forms, then to use your
phrase, "damage is done". The important factor for me was providing similar
functionality and appearance vis-a-vis other scripting/programming
languages.

>
> In my design (which remember is not a superset of Smalltalk, but another
> available source language) I shall probably use "," as a statement
separator
> (actually an expression separator -- I have never liked the presence of
> "statements" in non-procedural languages).
>
> Also, in my design, "a.b" will usually carry the same kind of meaning as
"a
> at: #b" or "a[#b]": ie, the argument passed to the "." method would be
"#b".
> Is that the case in your approach?
>
> >>
>     s[1] := $F.

    []:=

    is mapped to the message:

    [...](rhsv)

    as in:

    [1]($F)

Method behavior: sClass [
[indexA](value)
    ...
].

> <<
>
> I also envision this syntax, with similar semantics to yours.  In my mind,
> "[]:=" is a message selector of some kind.  The programmer has control
over
> the semantics since he/she can rewite the "[]:=" method.
>
> I'm also toying with trying to make "a := 3" a message send.  Of course,
> ":=" changes the value of the reference of the name "a" rather than the
> current referent of "a".  Some object has to be interposed between "a" and
> its referent to receive the ":=" message; this object is probably best
> called a "slot".  (I've only recently found out about "slots", so my
> nomenclature may be inappropriate and/or my semantics inaccurate).

SmallScript supports automatic assignment coercion to messages for
non-static expressions:

    a.b := 10.

    "becomes"

    a.b: 10.

    "which is effectively:"

    a b: 10.

SmallScript also allows you to declare a method as a property, at which
point you can use the message name as a variable.

Property behavior: sClass [
x
    ^someExpression.
].
Property behavior: sClass [
x: value
    someExpression := value.
].

Method behavior: sClass [
someMsg
    ^x := x + 1.
].

The <x> here is not an inst-var, but actually a property method. The
compiler will effectively generate the following code for the #someMsg
method.

Method behavior: sClass [
someMsg

    |t| self x: (t := self x + 1).
   ^t
].
=================

SmallScript also allows declaration of property-variables which are "lazily"
allocated on a per-instance basis. I.e., you can declare 1000 property
variables for a class. But, they will only be instantiated for a particular
instance when they are assigned.

Class name: X property-vars: a,b,c,d,e,f,g,h,i,j,...

Method behavior: X [
someMsg

    a := 10.
    b := a.
   ^j
].

Unlike inst-vars, the property vars are maintained like python style
variables, as a kind of hash-table entry within the object's properties. So,
until the variables are assigned, they have no entry in the property system.
When they are set back to their default (they may get their variable-slot
removed from the property system).

This technique allows one to add variables to individual instances of
objects.

Eval [

    "" Asuming the previous X::someMsg method where <a> was assigned 10
    | prev| := someX someMsg;{'a'}.

    "" See classic-st form next
    |r| := someX{'a'} :+= 1. "" uses mmdisp to discriminate

    "" Which is equivalent to:
    r := someX propertyVariableValueAt: 'a' put:
        (someX propertyVariableValueAt: 'a') + 1.

    "The value of <prev> is 10, and the value of <r> initially is 11"
].

>
> The "default" slot would delegate every message to its contents (formally
> using #doesNotUnderstand:, in practice by some cleverness in the VM for
> performance) apart from ":=".  Formally, a slot would usually be an
indexed
> pointer object of size 1; this avoids the infinite regression since
#at:put:
> is not an assignment.
>
> There is a problem, though: when does a "variable" refer to its slot, and
> when to the contents of its slot (the "real" object)?  The resolution
seems

> to be to use the slot when the variable is used as a receiver, but the
> object (possibly via an implicit send of #slotContents) elsewhere.
>
> I may not pursue this.  The semantics end up more convoluted than allowing
> the OO oddity of assignment (although they would be invisible to Smalltalk
> programmers who don't know about them).
>
> OTOH, slots add daemons (which I have also recently learnt about) as
> fundamental.  I'll get back to you on this.
>
> >>
>     |b| := s[4:7].
> <<
>
> Can the programmer change the semantics of this syntax?  I'm assuming that
> there's a selector here, something like "[:]", for which I can define my
own
> method.  Is that right?

Yes. The format is just a message.

"" Getter Form
Method behavior: SomeClass [
[arg1 : arg2]()
    ...
].


"" Setter (assignment) Form
Method behavior: SomeClass [
[arg1 : arg2](value)
    ...
].

>
> >>
>
>     "" A regular expression used in a slice
>     |t| := (b = s[`b.*']). "" <t> ==> <true>
> <<
>
> Interesting that you've added regular expressions to the base image.  I
view
> (proper) programming languages as divided into four categories:
procedural,
> functional, OO and logic/backtracking.  The last category is the one I've
> had least experience of, although I did once implement a true LR(K) parser
> (in, guess what? APL).  I do remember doing a short course in Snobol at
> college, but I've forgotten all of fit.  And I've never had to learn Perl.
> :-)

Ahh. Keeping in mind that one of my big focuses is "scripting" and that
often relates to text processing, it was important to have basic text
processing services. But the most important factor is that
regular-expressions are actually implemented with full block closure
semantics.

So the RX expressions can contain/declare internal variables and
filters/patterns written in SmallScript itself.

To provide that functionality required making regular expressions a part of
the language.

>
> >>
> Method behavior: String [
> [<RegEx>rx](v)
>     ...
> ].
> <<
>
> I assume <RegEx> is a type.  Is it compulsory or optional in this
> declaration?

<RegEx> is the base type for regular expression objects, as <Block> is the
base type for block objects.

All type declaration in SmallScript is optional. A type annotation can be
treated as hint for marshalling or as a binding characteristic for
multi-method dispatch.

In this case, we have explicitly declared the (optional) type characteristic
for multi-method binding of a given #[1](1) message.

Thus we have said that the method should only "bind" when the <rx> argument
is a "kind-of" <RegEx> object. Furthermore, the binder will also perform
best-fit analysis if there are competing methods with the same selector but
different type-signatures.

I.e. "" The following is a generic form where <rx> can be of <any> type.
Method behavior: String [
[rx](v)
].

Thus:

Eval [
    s[s] := ''.    "" Would bind to the generic <any> signature version

    s[`.*'] := ''. "" Would bind to the <RegEx> signature version
].

>
> >>by definition, #(...) messages are aliased to #value... messages<<
>
> Hmm.  I had not thought of this approach.  The natural way that blocks
> become "functions" is nice (although of course the ZeroArgumentBlock
method
> with selector "()" can be defined as "self value" for the same behaviour).

SmallScript doesn't have a ZeroArgumentBlock, etc. All blocks are uniform in
the sense that there is one type for blocks independent of the number of
arguments it takes (there is a subtype of block, called an UnloadedBlock,
but it is not appropriate to explain that here). The "arity" of a block does
not have to correspond to the "arity" of the valuation message.

Example:

Eval [

    [10] value: 1 value: 2. "Perfectly ok"

    [:a| a] value. "Perfectly ok"
].

Here's the arity coercion rule:
-------------------------------
Missing arguments are supplied as <nil>, and excess arguments are ignored.

The same rules apply to various perform operations and valuation of method
objects.

Eval
[
    "" #foo
    someObject perform: #foo.

    someObject perform: #foo with: 10.

    "" #foo:
    someObject perform: #foo:.

    someObject perform: #foo: with: 10.
].

Eval
[
    |m| := someMethodInst.

    m value.     "" m().

    m value: 10. "" m(10).

    "" Or:
    m self: aReceiver.
    ""
    m self: aReceiver value: 10.
].

>
> >>If the resolution fails, then treat it as a message of the form
#foo(...)
> and send that message to <self> as a function send<<
>
> I have to say I don't like this overloading of syntax.  Admittedly there's
> nothing wrong with the bare name "foo" standing for a selector rather than
> an object -- we already have this with unary message syntax.  But that's
not
> perfect -- how many times a day do you debug '"self" not understood'? :-)

In practice, I've not seen this happen. Although I understand your concerns.
Just keep in mind that my goals are for scripting language style application
and practices. It is practically a cut & paste operation to move VB,
JScript, Python, PHP, et cetera expressions into SmallScript and get them to
run.

>
> I think I want to stick to the principal that the leftmost thing is always
a

> receiver.
>
> >>Interfaces are first class objects in SmallScript <g><<
>
> Let me make things clear: they will of course be such in my system. :-)
>
> >>They can also provide concrete mixin behavior and are part of the type
> system<<
>
> I haven't yet given a great deal of though to types, although I strongly
> suspect they will be necessary for performance, even if not for
expressivity
> or self-documentation, since the app in which my Smalltalk is to be
embedded
> is real-time, and there are places where performance will be paramount.
>
> OTOH, maybe by the time it's finished, CPUs will be fast enough that I
won't
> have to worry. :-)
>
> [I looked at the work the Self group did on runtime recompilation with
both
> fascination and dismay.  I can see they had a lot of fun, but the sad
thing
> is that over the period of their study improvements in CPU speed achieved
> what they did and more.  I have mixed feelings about the amount of effort
> put into optimization techniques.  Then again, I have unmixed feelings
about
> a world based on CISC architecture.  Long live the ARM!]

The Self adaptive compilation technology is not based on using declarative
type annotations.

I chose to provide declarative type annotation facilities because they are
fundamental for providing multi-methods and FFI interop. The performance
optimization possibilities are also there as in any statically compiled
language, but the optimization opportunities are *not* the reason for
providing first-call types, type-signatures, and type-annotations.

>
> So I'll archive your type examples until I've had a change to think this
> through for myself.
>
> >>
> >
> > It'll be C in the end, naturally.
>
> Why not Eiffel, or ML?
> <<
>
> Short answer: I have not used either language.
>
> Long answer: I'm trying both to understand the internals of the Smalltalk
VM
> and design an OO language of my own.  Just at the moment, I don't need a
> third new language in the mix. :-)
>
> [Aside: when I wrote I-APL I first designed and implemented a language in
> which to implement it.  I-APL had to run on 64K machines because it was
> aimed at schools which in the mid-80s usually had access to little more
than
> Z80- or 6502-based machines.  It also had to be highly portable for the
same
> reasons, and even be able to run from ROM.  I therefore decided I needed a
> stack-based VM (this was before I ever encountered any VM-based language,
or
> even knew the term).  I looked at Forth, which was the natural existing
> choice, but compatibility of published implementations across different
> platforms would have been hell to resolve.

I did a lot of work in Forth during the time period your talking about. It
was pretty easy to build your own forth implementation in assembly language
<g>. On the hobby (non-professional side) I was a big Atari 6502/6512
fan/devloper. I played a bit with the Z80 but never really got into it -- I
didn't like the Timex Sinclair machines.

Very early on in that period I happened to use APL quite a bit for about a
year or so on HP machines at NIH (National Institutes of Health) through a
"guest" account -- it was a fabulous language for doing Physics/Chemistry
Labwork and building Dungeons & Dragons gaming tools ;-). Using thermal
paper printouts on 110 then 300 and ultimately 1200 baud modems seemed great
at that time, but I couldn't imagine doing it now.

In that same period 1976-1984 I worked in the Scientific Computing Division
at the National Bureau of Standards (NBS today known as NIST).

I was working on unix with PDP's, HP machines, Univacs, (some more obscure
systems), and Perkin-Elmer 16/32 bit machines and I also did a lot of work
on CP/M. I designed and built a fair amount of from-scratch hardware systems
using 6512's and 68K cpu's before I decided to be a full time software guy.

Cheers,

-- Dave S. [www.smallscript.net]

>
> In the end, my choice was right: I built an IDE (again, before I knew the
> term -- I called it "DE" and the language "DEL", which caused an unforseen
> problem in MSDOS the first time I tried to run the executable !:-) which
> provided a crash-proof emulation of the VM, breakpoints, watches, all of
> that.  The source-code syntax was pretty, and added things that Forth
didn't
> have.  It took a month to write the IDE in C.  Ah, those were the days
when

> I could code FAST.
>
> Finally, the compiler was writen in STSC APL*PLUS/PC.  It took 7 hours to
> run.]
>
> >>
> Or, if you're really looking to experiment quickly, why not build on an
> existing open-source Lisp/scheme implementation?
> <<
>
> Same reason: don't know 'em.  I learnt my skills on the practical side of
> the industry (APL: practical?), and so to my great shame have never used
> Lisp in anger, although I still have an archived paper design for a Z80
Lisp
> implementation -- in red ink, for some reason, I recall -- which never saw
> the light of day: I guess I must have been excited about it once.  My
> college course did not cover Lisp, which annoys me still.  I was
introduced
> to Church's lambda notation, though, so I understand the functional
> principals.  CLOS, OTOH, is nothing more than a name to me. :-(
>
> Cheers, Paul
>
>


Reply | Threaded
Open this post in threaded view
|

Re: Smalltalk Implementor

Paul Chapman
David,

>>
> Also, in my design, "a.b" will usually carry the same kind of meaning as
"a
> at: #b" or "a[#b]": ie, the argument passed to the "." method would be
"#b".
> Is that the case in your approach?
<<

You skipped this question.  I'm still interested in the answer.

>>
SmallScript also allows you to declare a method as a property, at which
point you can use the message name as a variable.
<<

Yup.  Thinking about properties.  They're the only things I ever liked about
VB.

>>
SmallScript also allows declaration of property-variables which are "lazily"
allocated on a per-instance basis
<<

Easily simulated in Smalltalk, of course.

For reasons which will become clearer later (both to the group and to me :-)
I intend to introduce a class called something like FixedKeyDictionary,
whose set of keys is fixed at object Construction.  Use of this class in
Smalltalk would more closely correlate to SmallScript's requirement that
property variables be declared statically.  OTOH, space is reserved in a
FixedKeyDictionary for the values.

>>Missing [value:...] arguments are supplied as <nil>, and excess arguments
are ignored.<<

Hmmm.  This invites obscure bugs.  It is a Bad Thing, IMHO.  Many languages
which allow for "optional arguments", for example, require that their
respective parameters are declared as such.

When I was young and naive, I did think a lot about how to design a
low-level, APL-like language in which every "juxtaposition" (the syntax was
"juxtopostition-based") of values, symbols, etc, meant something and
therefore executed without error: if it compiles, it runs.  I have since
learned that run-time errors have a valuable role to play in speedy and
reliable development. I've even found myself writing assertion code in
languages which do not directly support the concept!

(This provokes the question: can I at least find out how many parameters a
SmallScript Block has at run-time?  Can I rewrite the eg value: method to
check for valence corrrespondence?)

Smalltalk requires the programmer to declare temporary variables.  This is
purely a safety feature (and, thinking about it, just about the only one in
the language).  The fact that I have predominantly worked in APL and
Smalltalk (and cast-happy C) should tell you I do not subscribe to the
strict Ada/Eiffel approach when it comes to safety features.

Is there an implementation reason for the relaxed-valence value:... rule in
SmallScript?  I hope so. :-)

>>It is practically a cut & paste operation to move VB, JScript, Python,
PHP, et cetera expressions into SmallScript and get them to run<<

<shiver> <g>

Aside: I think the clipboard is a great invention.  And the nomenclature
"Cut and Paste" is an inspired phrase.  (Do we have Xerox PARC to thank for
that? I guess so.)  But when did "Copy" get added to the mix?

It's more than fifty years since the closed subroutine was invented.  (Its
bastard son, the macro, has its uses, I suppose).  Two years ago I was asked
to review some VB code written by a "professional contractor".  His design
strategy was clearly something like this: "I need to do something like those
20 lines of code I wrote half-an-hour ago, so I'll just copy-and-paste them
here, and change the variable that's different."

He really *did* have "declarations like" (from Dave Harris, above):

    string addressLine1;
    string addressLine2;
    string addressLine3;
    string addressLine4;

Ack!  Anyway, all the code was thrown away and he was shown the door.  (Six
months later I heard he was earning pots of money sitting around in a bank
reading the papers while the management tried to figure out what to do after
a merger.  I could do that job!)

End of aside.

>>The Self adaptive compilation technology is not based on using declarative
type annotations<<

Of course.  I did not mean to imply anything to the contrary.

>>On the hobby (non-professional side) I was a big Atari 6502/6512
fan/devloper. I played a bit with the Z80 but never really got into it -- I
didn't like the Timex Sinclair machines<<

I never used a Sinclair.  My first micro was a SWTPC 6800.  The first
British micro was the Nascom-1, which was built around a Z80, and I had one
of those (wrote a commercial symbolic assembler for it in 3K).  I also did
some real-time tape- and disk-controller firmware on the Z80 at that time.
All in all, I ended up specializing in Z80 code, and wrote my first APL for
the Z80.

>>Using thermal paper printouts on 110 then 300 and ultimately 1200 baud
modems seemed great at that time<<

That was my first use of APL, too.  Which is why I wanted an interpreter for
micros.  Of course, there was the IBM 5100, a bitslice microprocessor
emulating a System/370 running IBM APL/SV!  I even wrote a microcode
cross-assembler for it in APL.  (And, a propos another thread in this group,
it was OS-less.)

And my very first program ran in Fortran IV on an IBM 7094.  It was supposed
to print powers of 2 up to 50, but I immediately learnt a hard lesson about
word-size.

Cheers, Paul


Reply | Threaded
Open this post in threaded view
|

Re: Smalltalk Implementor

David Simmons
"Paul Chapman" <[hidden email]> wrote in message
news:9ftcn0$5bn$[hidden email]...

> David,
>
> >>
> > Also, in my design, "a.b" will usually carry the same kind of meaning as
> "a
> > at: #b" or "a[#b]": ie, the argument passed to the "." method would be
> "#b".
> > Is that the case in your approach?
> <<
>
> You skipped this question.  I'm still interested in the answer.

Sorry, I missed the question first time around. The "." is not a message, it
is syntax to distinguish the message form/precedence. In the "a.b"
expression, the message is #b.

The a.b form, has the highest precedence. The compiler attempts to
statically resolve each element in the form based on type information and
inferencing. If it is unable to do so, it will convert any trailing
(unresolved elements) into message sends.

That said, "a at: #b" or "a[#b]" is just a message whose meaning is
determined by the method hierarchy of "a behavior". As I think I mentioned
before, #at: and #[1] are aliases, as is #at:put: and #[1](1). Reminder (in
case I didn't make it clear), an alias is a distinct message selector, but
will bind based on its primarySelector. Which allows the callee (if they
care in say a DNR) to distinguish between an alias and its primary selector
(or access the selector used by the caller via <thisSelector>).

(DNR is the sequence: #forwardInvocation:withArguments, which typically
falls through to #doesNotRespondTo:withArguments:). The use of
<thisSelector> returns the original message selector used to invoke a
particular method -- which enables obtaining the caller's message's scope
and selector name.

Note that with selector namespaces, one also has the ability to qualify a
message with a particular namespace scope when invoking it.

SmallScript allows one to write a message name as a full symbol or
<MessageSignature> declaration. Where the "#" is the symbol (selector)
declaration, and a "::" is a <MessageSignature> declaration.

As part of SmallScript's consistency rules for declarations, one can write
"a.b" as:

    a.#b

    a::b

Or combine them:

    A.#::b

In any of those forms, the compiler will provide the same precedence, but
will limit its efforts to binding static elements. Note that those forms
allow one to write code like:

    a << b.foo << b#foo:bar:(x,y).

    "" Which is the same as:

    a << (b foo) << (b foo: x bar: y).

    "" These forms can be used to ensure explicit
    "" message bindings or using additional annotations
    "" be used to force a static binding to a
    "" particular method implementation. Think, explicit
    "" annotation facilities similar to the <super> concept.

A full message signature includes:

    <any custom annotations for the signature>
    <return-type-annotations>
    <scope><selector>
    <argument-type-annotations>

One can use a signature to lookup a method in a dictionary:

    SomeClass[#::<returnType>scope.scope.selector(<type>,<type>)].

    "or equivalently from QKS Smalltalk, pre-dating SmallScript"

    SomeClass<>#::<returnType>scope.scope.selector(<type>,<type>).

    "" Which I believe some Smalltalk's also define as #<<
    "" but which I do not because it is so commonly used for
    "" stream operations and bit-shifting that I preferred
    "" to avoid the confusion when I first developed QKS
    "" Smalltalk some ten years ago. It also allowed for
    "" variations like #<_>,#<&>, etc.

Here are some examples of a scope qualified message send.

    a SomeNS.bar

    a #SomeNS.bar

    a ::SomeNS.bar

    a #::SomeNS.bar

The "::" operator can also be applied to a parenthetical form to indicate
that it "should" be treated as only a function binding and not a possible
instance method.

Method behavior: SomeClass [
someMsg

    foobar().    "" Will attempt to bind the instance
                 "" "self foobar" then attempt to bind
                 "" to a function in the method's visible
                 "" scopes.

    "" vs.

    ::foobar().  "" Will go immediately to bind a foobar"
                 "" function in the method's visible scopes.
].

The type annotation system also allows passing variables references (in/out)
arguments which enables returning multiple values and plays a role in FFI
marshalling.

Eval [
    |v|

    |b| := [:<out>a| a := 10. 11].

    |r| := b value: <&>v.    "" i.e., b(<&>v)

   ^v.  "" r will be 10, and ^v will return 10
].

The annotation system also allows declaring and passing &rest style position
independent optional named arguments. But, I've said enough so I'm not going
to explain that one now.

>
> >>
> SmallScript also allows you to declare a method as a property, at which
> point you can use the message name as a variable.
> <<
>
> Yup.  Thinking about properties.  They're the only things I ever liked
about
> VB.
>
> >>
> SmallScript also allows declaration of property-variables which are
"lazily"
> allocated on a per-instance basis
> <<
>
> Easily simulated in Smalltalk, of course.
>
> For reasons which will become clearer later (both to the group and to me
:-)
> I intend to introduce a class called something like FixedKeyDictionary,
> whose set of keys is fixed at object Construction.  Use of this class in
> Smalltalk would more closely correlate to SmallScript's requirement that
> property variables be declared statically.  OTOH, space is reserved in a
> FixedKeyDictionary for the values.
>
> >>Missing [value:...] arguments are supplied as <nil>, and excess
arguments
> are ignored.<<
>
> Hmmm.  This invites obscure bugs.  It is a Bad Thing, IMHO.  Many
languages
> which allow for "optional arguments", for example, require that their
> respective parameters are declared as such.
>
> When I was young and naive, I did think a lot about how to design a
> low-level, APL-like language in which every "juxtaposition" (the syntax
was
> "juxtopostition-based") of values, symbols, etc, meant something and
> therefore executed without error: if it compiles, it runs.  I have since
> learned that run-time errors have a valuable role to play in speedy and
> reliable development. I've even found myself writing assertion code in
> languages which do not directly support the concept!
>
> (This provokes the question: can I at least find out how many parameters a
> SmallScript Block has at run-time?  Can I rewrite the eg value: method to
> check for valence corrrespondence?)

Smalltalk (SmallScript) provides full reflection services. So a block knows
(and can be queried) for its "arity" (number of arguments as well as their
type signatures, related annotations, etc).

>
> Smalltalk requires the programmer to declare temporary variables.  This is
> purely a safety feature (and, thinking about it, just about the only one
in
> the language).  The fact that I have predominantly worked in APL and
> Smalltalk (and cast-happy C) should tell you I do not subscribe to the
> strict Ada/Eiffel approach when it comes to safety features.
>
> Is there an implementation reason for the relaxed-valence value:... rule
in
> SmallScript?  I hope so. :-)

It is crucially important that (efficient) flexible arity be allowed for
perform and valuation. It enables substitutability for facilities like
delegation and aspect-oriented/introspection-facilities.

I learned this lesson early on in building QKS Smalltalk and designing the
semantic message architecture for notification, delegation, transactions,
etc.

>
> >>It is practically a cut & paste operation to move VB, JScript, Python,
> PHP, et cetera expressions into SmallScript and get them to run<<
>
> <shiver> <g>

<g> This is very important for easing through the
adoption/learning/acceptance curve.

OTOH, there is work underway on a number of compiler's for the AOS Platform.
So many of these same languages will be directly available on the same
execution architecture (whether it is the AOS Platform or the Microsoft.NET
Platform).

>
> Aside: I think the clipboard is a great invention.  And the nomenclature
> "Cut and Paste" is an inspired phrase.  (Do we have Xerox PARC to thank
for
> that? I guess so.)  But when did "Copy" get added to the mix?
>
> It's more than fifty years since the closed subroutine was invented.  (Its
> bastard son, the macro, has its uses, I suppose).  Two years ago I was
asked
> to review some VB code written by a "professional contractor".  His design
> strategy was clearly something like this: "I need to do something like
those
> 20 lines of code I wrote half-an-hour ago, so I'll just copy-and-paste
them

> here, and change the variable that's different."
>
> He really *did* have "declarations like" (from Dave Harris, above):
>
>     string addressLine1;
>     string addressLine2;
>     string addressLine3;
>     string addressLine4;
>
> Ack!  Anyway, all the code was thrown away and he was shown the door.
(Six
> months later I heard he was earning pots of money sitting around in a bank
> reading the papers while the management tried to figure out what to do
after
> a merger.  I could do that job!)
>
> End of aside.
>
> >>The Self adaptive compilation technology is not based on using
declarative
> type annotations<<
>
> Of course.  I did not mean to imply anything to the contrary.
>
> >>On the hobby (non-professional side) I was a big Atari 6502/6512
> fan/devloper. I played a bit with the Z80 but never really got into it --
I
> didn't like the Timex Sinclair machines<<
>
> I never used a Sinclair.  My first micro was a SWTPC 6800.  The first
> British micro was the Nascom-1, which was built around a Z80, and I had
one
> of those (wrote a commercial symbolic assembler for it in 3K).  I also did
> some real-time tape- and disk-controller firmware on the Z80 at that time.
> All in all, I ended up specializing in Z80 code, and wrote my first APL
for
> the Z80.
>
> >>Using thermal paper printouts on 110 then 300 and ultimately 1200 baud
> modems seemed great at that time<<
>
> That was my first use of APL, too.  Which is why I wanted an interpreter
for
> micros.  Of course, there was the IBM 5100, a bitslice microprocessor
> emulating a System/370 running IBM APL/SV!  I even wrote a microcode
> cross-assembler for it in APL.  (And, a propos another thread in this
group,
> it was OS-less.)
>
> And my very first program ran in Fortran IV on an IBM 7094.  It was
supposed
> to print powers of 2 up to 50, but I immediately learnt a hard lesson
about
> word-size.
>
> Cheers, Paul
>

-- Dave S. [www.smallscript.net]


Reply | Threaded
Open this post in threaded view
|

Re: Smalltalk Implementor

Paul Chapman
David,

>>Reminder (in case I didn't make it clear), an alias is a distinct message
selector, but will bind based on its primarySelector<<

This is now clear. :-)

More later.

Cheers, Paul