modula3 / cm3

Critical Mass Modula-3
http://modula3.github.io/cm3/
Other
139 stars 25 forks source link

"illegal operand(s)" and "actual not assignable to VALUE formal (2.3.2)"? #1077

Closed ghost closed 2 years ago

ghost commented 2 years ago

a and b are of type LONGREAL. Why don't this code compile?

Math.sqrt(a*a + b*b)

This started to get annoying.

mikanystrom commented 2 years ago

It should. What's the error message?

On Sat, Sep 10, 2022, 3:43 PM pwd96m4a @.***> wrote:

a and b are of type LONGREAL. Why don't this code compile?

Math.sqrt(aa + bb)

This started to get annoying.

— Reply to this email directly, view it on GitHub https://github.com/modula3/cm3/issues/1077, or unsubscribe https://github.com/notifications/unsubscribe-auth/ABKYNJLBM4XIWLMA67OW2YDV5SF63ANCNFSM6AAAAAAQJK5CRE . You are receiving this because you are subscribed to this thread.Message ID: @.***>

ghost commented 2 years ago

It should. What's the error message?

What's in the title of this. Two errors. But, first answer this question pls: https://github.com/modula3/cm3/issues/1076

ghost commented 2 years ago

So, the stupid interfaces don't work. Finally I found an example on the internet. This language must be very unpopular. Finding an example for it is too difficult. Finding M2 example is much easier. The key is, for Math you have to use LONGREAL (not just REAL like this RealSqrt interface). And with LONGREAL you have to append D0 to the number! This is totally optional in other languages but I have no idea why you took it so harsh this way. BTW, I have read the language definition many times, there is nowhere D0 is mentioned. The C language despite all of the bad of it, has a better document: https://en.cppreference.com/w/cpp/language/floating_literal

VictorMiasnikov commented 2 years ago

Looks like we have many [half-]duplicated topics . . .

mikanystrom commented 2 years ago

It's all pretty logical. But yes, different from most programming languages. Welcome to Modula-3!

Math.i3 is actually an interface to libm. Just like in C (because it is in C) it uses double precision (a.k.a. LONGREAL) for parameters and results. In fact I am sure you know K&R C defaults to double precision if you don't have a declaration around, it's just standard.

The only "real" reason to use REAL over LONGREAL is to save storage. Otherwise why not just use double precision? It's better and the same speed.

The reason D0 isn't optional is because of Modula-3's stringent type assignability rules and lack of automatic conversions. Once you get used to those rules, you pretty quickly understand it's a better way. At least I think so. The number of bugs I've had in my code involving automatic type conversions (in just about every language that supports them) is, well, long. Yeah sometimes it's a pain to have to write FLOAT(blahblah) and ROUND(x) and whatnot but I think it makes for much clearer code, rather than code that hides what it's doing behind complicated and sometimes obscure language rules (autoboxing in Java comes to mind...)

References here are:

I.

https://www.cs.purdue.edu/homes/hosking/m3/reference/numbers.html

A literal REAL has the form decimal E exponent, where decimal is a non-empty sequence of decimal digits followed by a decimal point followed by a non-empty sequence of decimal digits, and exponent is a non-empty sequence of decimal digits optionally beginning with a + or -. The literal denotes decimal times 10^exponent. If "E exponent" is omitted, exponent defaults to 0.

LONGREAL and EXTENDED literals are like REAL literals, but instead of E they use D and X respectively.

II.

https://www.cs.purdue.edu/homes/hosking/m3/reference/assign.html

To specify the typechecking of assignment statements we need to define "assignable", which is a relation between types and types, between expressions and variables, and between expressions and types.

A type T is assignable to a type U if:

================== Since it doesn't say that REAL and LONGREAL are in any way connected to each other, they are completely separate types. They are not in a subtyping relationship with each other. Therefore, the assignment rule says they are not assignable.

In C, if you write

double x = 1;

1 is not a double. It's an int, and it gets converted on assignment.

The classic C bug is to write

double x = 1/3;

which sets x to zero.

rather than

double x = 1./3.;

which is what you probably wanted if you coded that.

To see what Modula-3 avoids (and avoids having the programmer memorize...) ...

https://docs.oracle.com/javase/specs/jls/se7/html/jls-5.html

Table 5.1 is what you are talking about. But it's a slippery slope, conversion leads very easily to the rest of the rules on that page...

  Mika

On Sat, Sep 10, 2022 at 6:30 PM pwd96m4a @.***> wrote:

So, the stupid interfaces don't work. Finally I found an example on the internet. This language must be very unpopular. Finding an example for it is too difficult. Finding M2 example is much easier. The key is, for Math you have to use LONGREAL (not just REAL like this RealSqrt interface). And with LONGREAL you have to append D0 to the number! This is totally optional in other languages but I have no idea why you took it so harsh this way. BTW, I have read the language definition many times, there is nowhere D0 is mentioned. The C language despite all of the bad of it, has a better document: https://en.cppreference.com/w/cpp/language/floating_literal

— Reply to this email directly, view it on GitHub https://github.com/modula3/cm3/issues/1077#issuecomment-1242837518, or unsubscribe https://github.com/notifications/unsubscribe-auth/ABKYNJLIP4AAKZVWRB2I67TV5UYZJANCNFSM6AAAAAAQJK5CRE . You are receiving this because you commented.Message ID: @.***>

mikanystrom commented 2 years ago

I don't use RealSqrt.

The following works for me:

mnystroe-mobl2:~/test_sqrt/src> cat m3makefile import ("libm3") implementation ("Main") program ("test_sqrt") mnystroe-mobl2:~/test_sqrt/src> cat Main.m3 MODULE Main; IMPORT Math, IO;

VAR a, b : LONGREAL := 10.0d0; c : LONGREAL; BEGIN c := Math.sqrt(aa + bb); IO.PutReal(FLOAT(c,REAL)); IO.PutChar('\n') END Main. mnystroe-mobl2:~/test_sqrt/src> cm3 --- building in ../AMD64_LINUX ---

new source -> compiling Main.m3 **** PARALLEL BACK-END BUILD, M3_PARALLEL_BACK = 10 -> linking test_sqrt g++ -gstabs+ -m64 -fPIC -g -c -xc++ _m3main.c -o _m3main.o mnystroe-mobl2:~/test_sqrt/src> ../AMD64_LINUX/test_sqrt 14.142136 mnystroe-mobl2:~/test_sqrt/src>

On Sat, Sep 10, 2022 at 11:13 AM pwd96m4a @.***> wrote:

It should. What's the error message?

What's in the title of this. Two errors. But, first answer this question pls: #1076 https://github.com/modula3/cm3/issues/1076

— Reply to this email directly, view it on GitHub https://github.com/modula3/cm3/issues/1077#issuecomment-1242779814, or unsubscribe https://github.com/notifications/unsubscribe-auth/ABKYNJNA3HZVGPSGADNOD4LV5TFVLANCNFSM6AAAAAAQJK5CRE . You are receiving this because you commented.Message ID: @.***>