Jump to content

Eric

Moderators
  • Content Count

    95
  • Joined

  • Last visited


Reputation Activity

  1. Like
    Eric got a reaction from jorn in using variants   
    There is a simpler way that does not involve using asm and preserves typing to the last moment: using an anonymous class
    var Document external 'document' : Variant; ... procedure TForm1.W3Button5Click(Sender: TObject); begin   ZoomCharts.TimeChart(class       container = Document.getElementById("OBJ5");       area = class          height : Integer = 663  // typing is optional but can be used if you don't want type inference       end;       data = class          preloaded = class             values : array [0..4] of array [0..1] of Integer = [                [0, 100],                [1000, 200],                [2000, 300],                [3000, 400],                [4000, 500]             ];             &unit = 's';          end;          timestampInSeconds = true;       end; end); end;  This will generate quite optimal JS. If you do not specify the field type, it will be inferred.
     
    If a field name is a reserved pascal name, like 'unit', you can use the usual escape by prefixing with '&'. If the field name contains non identifier characters, you can use external
       weirdFieldName = 'hello'; external 'weird@field.name'; You can also declare lambdas and functions in an anonymous class, sso JS code can pretty much be mapped 1:1 to Pascal by using Variant & Anonymous classes. The strong typing will still be there in expressions, can be explicited in field types, or by using more or less strict external classes.

    Depending on how well defined (or not) the external JS objects you are interfacing, it sometimes does not make much sense trying to strong type everything, because the calls parameters or optional objects are messy anyway.
     
    Also two quick notes:
    for creating a new empty JS object, the most efficient form is just "new JObject", for instance "v := new JObject" with v a Variant, the resulting JS is 'v = {}'. for an external class, the procedure only need the "external" qualifier if the JS name is different from the Pascal name, f.i. if you want TimeChart on the pascal side, while on the JS side it is "timeChart"  
  2. Like
    Eric got a reaction from jorn in using variants   
    There is a simpler way that does not involve using asm and preserves typing to the last moment: using an anonymous class
    var Document external 'document' : Variant; ... procedure TForm1.W3Button5Click(Sender: TObject); begin   ZoomCharts.TimeChart(class       container = Document.getElementById("OBJ5");       area = class          height : Integer = 663  // typing is optional but can be used if you don't want type inference       end;       data = class          preloaded = class             values : array [0..4] of array [0..1] of Integer = [                [0, 100],                [1000, 200],                [2000, 300],                [3000, 400],                [4000, 500]             ];             &unit = 's';          end;          timestampInSeconds = true;       end; end); end;  This will generate quite optimal JS. If you do not specify the field type, it will be inferred.
     
    If a field name is a reserved pascal name, like 'unit', you can use the usual escape by prefixing with '&'. If the field name contains non identifier characters, you can use external
       weirdFieldName = 'hello'; external 'weird@field.name'; You can also declare lambdas and functions in an anonymous class, sso JS code can pretty much be mapped 1:1 to Pascal by using Variant & Anonymous classes. The strong typing will still be there in expressions, can be explicited in field types, or by using more or less strict external classes.

    Depending on how well defined (or not) the external JS objects you are interfacing, it sometimes does not make much sense trying to strong type everything, because the calls parameters or optional objects are messy anyway.
     
    Also two quick notes:
    for creating a new empty JS object, the most efficient form is just "new JObject", for instance "v := new JObject" with v a Variant, the resulting JS is 'v = {}'. for an external class, the procedure only need the "external" qualifier if the JS name is different from the Pascal name, f.i. if you want TimeChart on the pascal side, while on the JS side it is "timeChart"  
  3. Like
    Eric got a reaction from jorn in using variants   
    There is a simpler way that does not involve using asm and preserves typing to the last moment: using an anonymous class
    var Document external 'document' : Variant; ... procedure TForm1.W3Button5Click(Sender: TObject); begin   ZoomCharts.TimeChart(class       container = Document.getElementById("OBJ5");       area = class          height : Integer = 663  // typing is optional but can be used if you don't want type inference       end;       data = class          preloaded = class             values : array [0..4] of array [0..1] of Integer = [                [0, 100],                [1000, 200],                [2000, 300],                [3000, 400],                [4000, 500]             ];             &unit = 's';          end;          timestampInSeconds = true;       end; end); end;  This will generate quite optimal JS. If you do not specify the field type, it will be inferred.
     
    If a field name is a reserved pascal name, like 'unit', you can use the usual escape by prefixing with '&'. If the field name contains non identifier characters, you can use external
       weirdFieldName = 'hello'; external 'weird@field.name'; You can also declare lambdas and functions in an anonymous class, sso JS code can pretty much be mapped 1:1 to Pascal by using Variant & Anonymous classes. The strong typing will still be there in expressions, can be explicited in field types, or by using more or less strict external classes.

    Depending on how well defined (or not) the external JS objects you are interfacing, it sometimes does not make much sense trying to strong type everything, because the calls parameters or optional objects are messy anyway.
     
    Also two quick notes:
    for creating a new empty JS object, the most efficient form is just "new JObject", for instance "v := new JObject" with v a Variant, the resulting JS is 'v = {}'. for an external class, the procedure only need the "external" qualifier if the JS name is different from the Pascal name, f.i. if you want TimeChart on the pascal side, while on the JS side it is "timeChart"  
  4. Like
    Eric got a reaction from jorn in using variants   
    There is a simpler way that does not involve using asm and preserves typing to the last moment: using an anonymous class
    var Document external 'document' : Variant; ... procedure TForm1.W3Button5Click(Sender: TObject); begin   ZoomCharts.TimeChart(class       container = Document.getElementById("OBJ5");       area = class          height : Integer = 663  // typing is optional but can be used if you don't want type inference       end;       data = class          preloaded = class             values : array [0..4] of array [0..1] of Integer = [                [0, 100],                [1000, 200],                [2000, 300],                [3000, 400],                [4000, 500]             ];             &unit = 's';          end;          timestampInSeconds = true;       end; end); end;  This will generate quite optimal JS. If you do not specify the field type, it will be inferred.
     
    If a field name is a reserved pascal name, like 'unit', you can use the usual escape by prefixing with '&'. If the field name contains non identifier characters, you can use external
       weirdFieldName = 'hello'; external 'weird@field.name'; You can also declare lambdas and functions in an anonymous class, sso JS code can pretty much be mapped 1:1 to Pascal by using Variant & Anonymous classes. The strong typing will still be there in expressions, can be explicited in field types, or by using more or less strict external classes.

    Depending on how well defined (or not) the external JS objects you are interfacing, it sometimes does not make much sense trying to strong type everything, because the calls parameters or optional objects are messy anyway.
     
    Also two quick notes:
    for creating a new empty JS object, the most efficient form is just "new JObject", for instance "v := new JObject" with v a Variant, the resulting JS is 'v = {}'. for an external class, the procedure only need the "external" qualifier if the JS name is different from the Pascal name, f.i. if you want TimeChart on the pascal side, while on the JS side it is "timeChart"  
  5. Like
    Eric got a reaction from jorn in resourcestring   
    Yes, that is a current limitation I did not even think to test for (usually pack my strings in dedicated sections), I will add support for it in the next version.
     
    Otherwise resourcestring should works similarly to Delphi, though there is not yet anything in the IDE or RTL to facilitate them.
     
    All resource strings get an index are stored in a global JS-side array named "$R". Each time they are accessed, it is through a "$R[index]".
     
    So if you wish to switch language, you only have to change that $R array, either by re-assigning the variable to a a localized array in an asm section, or by replacing its items. In both cases gnu gettext can be leveraged quite directly.
  6. Like
    Eric got a reaction from jorn in Currency Data Type   
    The main issue with supporting the Currency type is it really needs a 64 bit integer, and there are no 64 bit integers in JS, only floats and 32 bit integers.
    With 4 fixed decimals, a 32bit currency could thus only store amounts up to approx 200,000.0000 which is not much depending on the currency, and thus not really usable.

    The alternatives would be to either go for a float with systematic rounding, about 54 decimals of precision, not quite up to 64bit but probably good enough for all but the weakest currencies, or use a large integer library (might be slow however).

    If going for float, given the operations at risk are addition and subtraction, rather than an Integer-based Currency, the following could be enough for practical purposes (to be tested more)
     
    type Currency = Float; function AddCurrency(a, b : Currency) : Currency; begin Result := Round((a+*1000)*0.0001; end; function SubCurrency(a, b : Currency) : Currency; begin Result := Round((a-*1000)*0.0001; end; operator + (Currency, Currency) : Currency uses AddCurrency; operator - (Currency, Currency) : Currency uses SubCurrency; Limitations with the above is that you have to use FloatToStr(xxx, 4) to convert to string, or you might get some stray decimals. Bonus is that you can easily adjust the number of decimals for the "Currency" to the precision you need, which might go from zero for the Dong to 8 decimals for Bitcoin.
×