Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / pas2js / 2019-09

Built-in helper methods for Double type

6 messages · 4 people · –

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

warleyalex

I came across this situation, when translating to pas2js:

 // Determine X and cut to 2 decimals
  x = (Math.sin(rad) * r).toFixed(2);

It would be nice if pas2js could extend the built-in Number methods for the type Double, Integer, for instance: syntax something like:

var
  x: string;
  r, rad: Double;
begin
   x:= (sin(rad) * r).toFixed(2);

struggling how to achieve this situation, an workaround would be:

I had to define an external class at the system unit, math section and a public single function:

type
  TJSNumber = class external name 'number'
    function toString(radix: integer = 0): String;
    function toFixed(fractionDigits: integer = 0): string;
    function toExponential(fractionDigits: integer = 0): string;
    function toPrecision(precision: integer): string;
  end;
function NumberTo(const aNumber: Double): TJSNumber; external name ' ';

and then

// Determine X and cut to 2 decimals
x := NumberTo(sin(10.1) * 2.5).toFixed(2); // $mod.x =  (Math.sin(10.1) *
2.5).toFixed(2);
Michael Van Canneyt
to warleyalex

Why not simply use type helpers ?

TDoubleHelper = type helper for Double
   function toString(radix: integer = 0): String;
   function toFixed(fractionDigits: integer = 0): string;
   function toExponential(fractionDigits: integer = 0): string;
   function toPrecision(precision: integer): string;
end;

It's on my TODO list to port the type helpers of FPC sysutils to pas2js. But this is low priority, since I don't use type helpers myself.

If you feel like porting them yourself, I'll be glad to help out with making a patch :-)

Michael.

warleyalex wrote 43 lines
I came across this situation, when translating to pas2js: // Determine X and cut to 2 decimals x = (Math.sin(rad) * r).toFixed(2); It would be nice if pas2js could extend the built-in Number methods for the type Double, Integer, for instance: syntax something like: var x: string; r, rad: Double; begin x:= (sin(rad) * r).toFixed(2); struggling how to achieve this situation, an workaround would be: I had to define an external class at the system unit, math section and a public single function: type TJSNumber = class external name 'number' function toString(radix: integer = 0): String; function toFixed(fractionDigits: integer = 0): string; function toExponential(fractionDigits: integer = 0): string; function toPrecision(precision: integer): string; end; function NumberTo(const aNumber: Double): TJSNumber; external name ' '; and then // Determine X and cut to 2 decimals x := NumberTo(sin(10.1) * 2.5).toFixed(2); // $mod.x = (Math.sin(10.1) * 2.5).toFixed(2); -- Sent from: http://pas2js.38893.n8.nabble.com/ _______________________________________________ Pas2js maillist - https://lists.freepascal.org/cgi-bin/mailman/listinfo/pas2js
warleyalex
to Michael Van Canneyt
solution using type helpers:
==================
type
  Float = Double;
type
{ TDoubleHelper }
TDoubleHelper = type helper for Float
   function toFixed(aNumber: Double; fractionDigits: integer): string;
assembler;
end;
{ TDoubleHelper }
function TDoubleHelper.toFixed(aNumber: Double; fractionDigits: integer):
string; assembler;
asm
  return Number(aNumber).toFixed(fractionDigits);
end;
var
  ReturnValue: float;
  x: String;
begin
  x := ReturnValue.toFixed(sin(10.1) * 2.5, 2);
  rtl.createHelper($mod,"TDoubleHelper",null,function () {
    this.toFixed = function (aNumber, fractionDigits) {
      return Number(aNumber).toFixed(fractionDigits);
    };
  });
   $mod.x = $mod.TDoubleHelper.toFixed.call({p: $mod, get: function () {
       return this.p.ReturnValue;
     }, set: function (v) {
       this.p.ReturnValue = v;
     }},Math.sin(10.1) * 2.5,2);

Personaly, I don't like being able to specify a type helper, jsut because Class helpers are not attractive. It's a kind of weird thing :)

I just want to determine X and cut to 2 decimals, using type helper, this weird syntax:

  x := ReturnValue.toFixed(sin(rad) * r, 2); // type helpers it's weird and
generates extra code
Mattias Gaertner
to warleyalex
Show quoted text 48 lines
solution using type helpers: ================== type Float = Double; type { TDoubleHelper } TDoubleHelper = type helper for Float function toFixed(aNumber: Double; fractionDigits: integer): string; assembler; end; { TDoubleHelper } function TDoubleHelper.toFixed(aNumber: Double; fractionDigits: integer): string; assembler; asm return Number(aNumber).toFixed(fractionDigits); end; var ReturnValue: float; x: String; begin x := ReturnValue.toFixed(sin(10.1) * 2.5, 2); rtl.createHelper($mod,"TDoubleHelper",null,function () { this.toFixed = function (aNumber, fractionDigits) { return Number(aNumber).toFixed(fractionDigits); }; }); $mod.x = $mod.TDoubleHelper.toFixed.call({p: $mod, get: function () { return this.p.ReturnValue; }, set: function (v) { this.p.ReturnValue = v; }},Math.sin(10.1) * 2.5,2); Personaly, I don't like being able to specify a type helper, jsut because Class helpers are not attractive. It's a kind of weird thing :) I just want to determine X and cut to 2 decimals, using type helper, this weird syntax: x := ReturnValue.toFixed(sin(rad) * r, 2); // type helpers it's weird and generates extra code

Delphi defines type helpers as pass value by reference - a type helper can modify the value. That's why pas2js must for compatibility reasons create this weird awkward code.
Iff there would be a modifier or attribute to define a read only type helper method, the compiler could create shorter code.

Another possibility would be a whole program analysis to spot if a type helper method is read-only and never referenced via address. But that would only work for Pascal methods, not external ones.

Mattias

Sven Barth
to Mattias Gaertner
Mattias Gaertner wrote 56 lines
On Wed, 4 Sep 2019 11:26:42 -0700 (MST) warleyalex via Pas2js wrote: > solution using type helpers: > ================== > type > Float = Double; > > type > { TDoubleHelper } > TDoubleHelper = type helper for Float > function toFixed(aNumber: Double; fractionDigits: integer): string; > assembler; > end; > > { TDoubleHelper } > function TDoubleHelper.toFixed(aNumber: Double; fractionDigits: > integer): string; assembler; > asm > return Number(aNumber).toFixed(fractionDigits); > end; > > > var > ReturnValue: float; > x: String; > begin > x := ReturnValue.toFixed(sin(10.1) * 2.5, 2); > > rtl.createHelper($mod,"TDoubleHelper",null,function () { > this.toFixed = function (aNumber, fractionDigits) { > return Number(aNumber).toFixed(fractionDigits); > }; > }); > > $mod.x = $mod.TDoubleHelper.toFixed.call({p: $mod, get: function > () { return this.p.ReturnValue; > }, set: function (v) { > this.p.ReturnValue = v; > }},Math.sin(10.1) * 2.5,2); > > > Personaly, I don't like being able to specify a type helper, jsut > because Class helpers are not attractive. It's a kind of weird > thing :) > > I just want to determine X and cut to 2 decimals, using type helper, > this weird syntax: > > x := ReturnValue.toFixed(sin(rad) * r, 2); // type helpers it's > weird and generates extra code Delphi defines type helpers as pass value by reference - a type helper can modify the value. That's why pas2js must for compatibility reasons create this weird awkward code. Iff there would be a modifier or attribute to define a read only type helper method, the compiler could create shorter code.

Considering that Delphi is using attributes for most such things as well (WeakRef, Volatile, etc.) you could add a magic "SelfIsConstAttribute" or something like that...

Another possibility would be a whole program analysis to spot if a type helper method is read-only and never referenced via address. But that would only work for Pascal methods, not external ones.

Couldn't external ones be considered as "const" anyway? Or can JS code modify "this"?

Regards,
Sven

Mattias Gaertner
to Sven Barth
Show quoted text 7 lines
[...] > Iff there would be a modifier or attribute to define a read only > type helper method, the compiler could create shorter code. Considering that Delphi is using attributes for most such things as well (WeakRef, Volatile, etc.) you could add a magic "SelfIsConstAttribute" or something like that...

Yes. Probably something shorter like [ConstSelf].

[...] Couldn't external [methods] be considered as "const" anyway? Or can JS code modify "this"?

AFAIK JS cannot modify the outer "this".
External methods of a helper for base types (e.g. double) is not yet implemented. It would probably work the same as for external classes, that is "value.toString" is converted to "value.toString()".

Mattias