The Artima Developer Community
Sponsored Link

Weblogs Forum
Looking at Heron Primitives

11 replies on 1 page. Most recent reply: Sep 9, 2005 10:07 PM by Tim LS

Welcome Guest
  Sign In

Go back to the topic listing  Back to Topic List Click to reply to this topic  Reply to this Topic Click to search messages in this forum  Search Forum Click for a threaded view of the topic  Threaded View   
Previous Topic   Next Topic
Flat View: This topic has 11 replies on 1 page
Christopher Diggins

Posts: 1215
Nickname: cdiggins
Registered: Feb, 2004

Looking at Heron Primitives (View in Weblogs)
Posted: Sep 1, 2005 6:22 AM
Reply to this message Reply
Summary
I have made a pre-release of HeronFront which semi-successfully translates to C++ the primitives module from the standard library.
Advertisement
I said HeronFront semi-successfully translates to C++ because, besides virtually everything else interesting, there is no function invocation by string yet. That little feature is top priority and should be ready in a couple of days. Function invocation by string makes the HeronScript interpreter easy to implement.

For the time being it may interest some to see some of the changes in the language since the last time I posted Heron code. One thing which I mentioned briefly yesterday is that standalone operators are assumed to be prefix unary operators mapping to the object instance. This allows me to eliminate the need for the this keyword. You can refer to the object instance by value through * and by address through @.

Hopefully the operator overloading scheme is obvious enough. A cool feature of Heron is that it supports a sequence of any length of valid operator characters as an overloadable operator. For instance I could overload %^&! as a prefix/unary operator by simply writing a function named: _pre_percent_hat_ampersand_bang() ( the infix/binary version drops the leading _pre).

I know some people are going to be offended by what appears to be a preponderance of leading underscores. They are reserved for certain keywords, operator overload names, and system level primitives. As a result in the standard library you see a heck of a lot of them, but user-code should be much prettier. Part of their purpose is to make abuse unattractive.

Anyway, enought blabbering here is the current version of the primitives module:

module primitives_module
{
  public
  {
    class int
    {
      public {
        // constructor
        _init(_int x) { m = x; }
        // operators
        _eq(self x) { m = x.m;  }
        _plus_eq(self x) { m += x.m; }
        _minus_eq(self x) { m -= x.m; }
        _star_eq(self x) { m *= x.m; }
        _slash_eq(self x) { m /= x.m; }
        _percent_eq(self x) { m %= x.m; }
        _pre_minus() : self { result = -m; }
        _post_plus_plus() : self { result = *; ++m; }
        _post_minus_minus() : self { result = *; --m; }
        _pre_plus_plus() : self* { ++m; result = @; }
        _pre_minus_minus() : self* { --m; result = @; }
        _plus(self x) : self { result = *; result += x; }
        _minus(self x) : self { result = *; result -= x; }
        _star(self x) : self { result = *; result *= x; }
        _slash(self x) : self { result = *; result /= x; }
        _percent(self x) : self { result = *; result %= x; }
        _gt(self x) : bool { result = (compare(x) > 0); }
        _gt_eq(self x) : bool { result = (compare(x) >= 0); }
        _lt(self x) : bool { result = (compare(x) < 0); }
        _lt_eq(self x) : bool { result = (compare(x) <= 0); }
        _eq_eq(self x) : bool { result = (compare(x) == 0); }
        _bang_eq(self x) : bool { result = (compare(x) != 0); }
        // public methods
        compare(self x) : int { result = m.compare(x.m); }
        to_primitive() : _int { result = m; }
      }
      fields {
        _int m;
      }
    }

    class char {
      public {
        // constructors
        _init(_char x) { m = x; }
        // operators
        _eq(char x) { m = x.m; }
        _gt(self x) : bool { result = (compare(x) > 0); }
        _gt_eq(self x) : bool { result = (compare(x) >= 0); }
        _lt(self x) : bool { result = (compare(x) < 0); }
        _lt_eq(self x) : bool { result = (compare(x) <= 0); }
        _eq_eq(self x) : bool { result = (compare(x) == 0); }
        _bang_eq(self x) : bool { result = (compare(x) != 0); }
        // public member functions
        compare(self x) : int { result = m.compare(x.m); }
        to_primitive() : _char { result = m; }
      }
      fields {
        _char m;
      }
    }

    class bool {
      public {
        // constructor
        _init(_bool x) { m = x; }
        // operators
        _eq(bool x) { m = x.m; }
        _amp_amp(self x) : self { result = m && x.m; }
        _pipe_pipe(self x) : self { result = m || x.m; }
        _pre_bang() : self { result = !m; }
        _eq_eq(self x) : bool { result = (m == x.m); }
        _bang_eq(self x) : bool { result = (m != x.m); }
        // public member functions
        to_primitive() : _bool { result = m; }
      }
      fields {
        _bool m;
      }
    }
  }
}
To see what kind of C++ this translates to you can check out the file primitives.heron.hpp from the HeronFront pre-release at http://www.heron-language.com/heronfront-5-9-1.zip. Any questions?


Tanton Gibbs

Posts: 20
Nickname: tanton
Registered: Aug, 2005

Re: Looking at Heron Primitives Posted: Sep 2, 2005 8:28 AM
Reply to this message Reply
How do you determine the precedence of <tt>%^&!</tt>? If it were an infix operator and you had the expression

foo = this + that * those %^&! mine;

What gets done in what order if all are overloaded?

Christopher Diggins

Posts: 1215
Nickname: cdiggins
Registered: Feb, 2004

Re: Looking at Heron Primitives Posted: Sep 2, 2005 8:35 AM
Reply to this message Reply
> How do you determine the precedence of <tt>%^&!</tt>? If
> it were an infix operator and you had the expression
>
> foo = this + that * those %^&! mine;
>
> What gets done in what order if all are overloaded?

Currently all infix operators have equal precedence, and are evaluated right to left. Same with prefix operators. Prefix operators have a higher precedence than infix operators. Perhaps a default evaluation order of left to right would be more intuitive? I hope the lack of complicated precedence rules doesn't turn out to be controversial.

Christopher Diggins

Posts: 1215
Nickname: cdiggins
Registered: Feb, 2004

Re: Looking at Heron Primitives Posted: Sep 2, 2005 4:01 PM
Reply to this message Reply
Turns out evaluation order is in fact left to right for statements, I got myself confused. So your example maps to:


foo._eq( this._plus(that)._star(those)._percent_hat_amp_bang(mine) );

Tanton Gibbs

Posts: 20
Nickname: tanton
Registered: Aug, 2005

Re: Looking at Heron Primitives Posted: Sep 2, 2005 6:19 PM
Reply to this message Reply
I'm assuming this holds for all types, so if you had (in C++ syntax, translate to Heron as appropriate).

int i = 1, j = 2, k = 3;

int l = i + j * 3;

if it is left to right, then l is 9. Mathematically, l should be 7. If that is the case, then you may have problems getting adopters, most of us are used to traditional precedence rules.

Christopher Diggins

Posts: 1215
Nickname: cdiggins
Registered: Feb, 2004

Re: Looking at Heron Primitives Posted: Sep 2, 2005 11:32 PM
Reply to this message Reply
> I'm assuming this holds for all types, so if you had (in
> C++ syntax, translate to Heron as appropriate).
>
> int i = 1, j = 2, k = 3;
>
> int l = i + j * 3;
>
> if it is left to right, then l is 9. Mathematically, l
> should be 7. If that is the case, then you may have
> problems getting adopters, most of us are used to
> traditional precedence rules.

But what about calculators, couldn't they be considered to be traditional? Do you think people would abandon a language because it takes a simple and unamibguous approach to operator precedence? I can never remember precedence rules from one language to another, so I have adopted the habit of always using parantheses to make my code unambiguous. It disappoints me that this might be a deal killer for some people, but I do accept that it may be the reality.

Vincent O'Sullivan

Posts: 724
Nickname: vincent
Registered: Nov, 2002

Re: Looking at Heron Primitives Posted: Sep 3, 2005 12:49 PM
Reply to this message Reply
From a previous thread "In important goal for me is to eventually have a standard library mathematics package which rivals specialized languages Mathematica and Maple. "

> Do you think people would abandon a
> language because it takes a simple and unamibguous
> approach to operator precedence? I can never remember
> precedence rules from one language to another, so I have
> adopted the habit of always using parantheses to make my
> code unambiguous.

You can't have it both ways. Left to right processing of operators is kindergarten mathmatics. If standard mathmatics is an important goal then standard mathmatic rules have to be followed. If your language says that "1 + 2 * 3" is different to "3 * 2 + 1" then it's not simple and unambiguous, it's wrong.

Keith Ray

Posts: 658
Nickname: keithray
Registered: May, 2003

Re: Looking at Heron Primitives Posted: Sep 4, 2005 6:57 AM
Reply to this message Reply
Smalltalk has been using left-to-right infix operators since the mid-1970's, and there are probably more flavors of Smalltalk (commercial and free) available now than ever before -- all with the same operator-precedence.

Use parents to distinguish (a + b) * c from a + (b * c)

Christopher Diggins

Posts: 1215
Nickname: cdiggins
Registered: Feb, 2004

Re: Looking at Heron Primitives Posted: Sep 4, 2005 8:14 AM
Reply to this message Reply
I think in the end it will be simplest to go with the flow and follow more-or-less the precedence for operators rules of C. Straying from convention is probably a very bad idea. I will place all uncommon operators in between assignment and comma operators. Here is the chart:

0. unary expressions (prefix operations)
1. multiplicative * / %
2. additive + -
3. boolean && || ^^
4. comparitive > < >= <= == !=
5. assignment =
6. other
7. comma ,

Pavel Kuznetsov

Posts: 1
Nickname: pavelk
Registered: Sep, 2005

Re: Looking at Heron Primitives Posted: Sep 6, 2005 6:18 AM
Reply to this message Reply
Christopher, is change of relative precedence of &&, || and ==, != etc. compared to C and C++ intentional?

> 0. unary expressions (prefix operations)
> 1. multiplicative * / %
> 2. additive + -
> 3. boolean && || ^^
> 4. comparitive > < >= <= == !=
> 5. assignment =
> 6. other
> 7. comma ,

This differs significantly from C, C++, Java and C#. And it'd be rather inconvenient to have such slight differences between languages with otherwise similar syntax.

Besides, there is a reason for 'traditional' precedence of &&, || and ==, != etc. You can see the code like follows:
if ( (a == b) && (c == d) )
  . . .

much more frequently than its counter-part:
if ( (a && b) == (c && d) )
  . . .

I think that if like you said above, precedence does not mean much to you, I'd stick with 'traditional' rules...

Christopher Diggins

Posts: 1215
Nickname: cdiggins
Registered: Feb, 2004

Re: Looking at Heron Primitives Posted: Sep 6, 2005 6:55 AM
Reply to this message Reply
Thanks for pointing that out Pavel. That was actually an unintentional error. However, I am now leaning towards simplifying the rules to a minimum which satisfies arithmetic precedence. I would welcome your comments on my latest post at: http://www.artima.com/weblogs/viewpost.jsp?thread=126323

Tim LS

Posts: 37
Nickname: parchandri
Registered: Jul, 2005

Re: Looking at Heron Primitives Posted: Sep 9, 2005 10:07 PM
Reply to this message Reply
Why on earth would anyone want an operator called "%^&!" ? It's hard to type, and harder to read than English. Wouldn't they rather call it "foo" in practice?

Flat View: This topic has 11 replies on 1 page
Topic: Heron 0.5.9.9 Previous Topic   Next Topic Topic: The Sum of Ant

Sponsored Links



Google
  Web Artima.com   

Copyright © 1996-2019 Artima, Inc. All Rights Reserved. - Privacy Policy - Terms of Use