Jump to content

Eric

Moderators
  • Content Count

    95
  • Joined

  • Last visited

Everything posted by Eric

  1. Eric

    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. Eric

    overload issue when 1st param is a string

    Unless I misunderstood the error is normal, since in case you have code with just a string parameter off(eventName); the compiler cannot figure out which of the overload is concerned. So you would need to specify that case separately and need 3 overloads: function off(eventName: string): JDom7; overload; function off(eventName: string; handler: TProcedure): JDom7; overload; function off(eventName: variant; delegatedTarget: variant; handler: TProcedure = nil): JDom7; overload;
  3. Eric

    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.
  4. Eric

    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.
  5. Eric

    Variant.AsBoolean always false

    It's the same behavior as in Delphi here: the variant will be cast on assignment. So in your snippet the Boolean cast will happen automatically for the "Result := vChecked;" line since Result is a Boolean. Also note that your code could be simplified to not involve any asm, just declare jQuery as an external function: function jQuery(v : Variant) : Variant; external '$'; ... function TjqxSwitchButton.GetChecked: Boolean; begin Result := jQuery('#' + TagId).jqxSwitchButton('checked'); end; Which takes advantages of the Variant method calls being resolved at runtime (same as in Delphi). The above method will be compiled to something like return ($("#"+TagId).jqxSwitchButton("checked")?true:false); With the 'jqxSwitchButton' call being transcribed verbatim, and the return value being cast to a Boolean automatically.
  6. Eric

    RTTI

    Would that class be defined in the implementation section of a unit rather than in the interface? If yes, then I think I know what's up.
  7. Eric

    Variant.AsBoolean always false

    Actually this is correct, Variants in Smart works similarly to Variants in Delphi (COM/OleVariant), ie. properties/methods you invoke on them as resolved "as they are" at runtime. In the case of Smart it means they're codegen'ed directly to JS. "vBool.AsBoolean" queries the AsBoolean property of your variant, in the case of a Boolean, there is no such property, so you get an "undefined", which is cast upon assignment to the bBool variable, resulting in a "false". If your vBool variant were to hold f.i { AsBoolean:"hello" } then vBool.AsVariant would return the "hello" string (and when cast to bBool, it would result in a "true"). There is a TVariant.AsBool() method which can perform the cast of a variant to a bool, but it's essentially legacy. Note that variants also support assignments of properties, f.i. var v : Variant := TVariant.CreateObject; // v contains {} v.AsBoolean := 'hello'; // v contains { "AsBoolean": "hello" } and it also works on arrays (ie. it's really similar to Variants in Delphi, as JavaScript objects are really similar to Variants)
  8. Eric

    IDE annoyances

    > as far as I know, there’s no case in which parentheses are allowed inside of the parens in a signature declaration Parenthesis can happen for expressions of default values of parameters, f.i: procedure Dummy(p : Integer = 3*(cWhatever + 5)); > If it does, look for “end.” at the end of the file Note that "end." is optional at the end of units, and there can be initialization/finalization sections.
  9. Eric

    Class methods on abstract classes

    "var a,b,c=0;" results in a & b left uninitialized at the "undefined" value. However do you have a particular snippet in mind?
  10. Eric

    Class methods on abstract classes

    I suspect the JS JITers don't have any (or much) support for typed arrays, so they just box the read/writes to typed arrays. There may be memory usage advantages, though I haven't done extensive testing in that area. However Chrome/FireFox which have the best Typed Arrays also already handle native arrays quite efficiently when all the elements are of the same type (which DWS enforces), as they use typed data with guard clauses. The internal typing is btw why the codegen always initializes variables with a typed value. This makes the JS code somewhat larger, but helps the JITters figure out the type of a variable earlier. And yes this is quite disappointing
  11. Eric

    Class methods on abstract classes

    Alas typed arrays performance is still not very good... I've been following them and monitoring from time to time, and at the moment, typed arrays are still not very convincing outside of the latest desktop browsers (Chrome & Firefox), though only in some scenarios. http://jsperf.com/native-vs-typed-js-array-speed/ (check the various revision of the above test case) That's still an improvement over the situation 6 months ago where they were slower everywhere, but having the compiler prefer typed array would still likely be detrimental (especially on mobile) Typed arrays are currently exposed through W3C.TypedArray if you want to test more specific scenarios.
  12. Eric

    How would I port this code?

    Delimiter for array constants is [], so MonthDays: array [boolean] of TDayTable = [[31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31], [31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]]; will work, the () was supported only for non-nested arrays (when the type is known). For the next version I version I extended the compiler so it will accept them for nested arrays as well when the type is fully qualified (as in your case). The reason behind using [] is to support array constants outside constant declarations, to initialize an array variable f.i, and also to allow type inference. The () constant array syntax is thus only supported for constant definitions, while [] is supported everywhere.
  13. Eric

    Referencing Pascal vars in asm block

    Currently only "immediate" references are allowed, ie. variables and fields. It should be possible to extend the support for simple (non-indexed) properties, but only in some cases, like property reads or functions calls. Property assignments on the other hand would be problematic, as they are function calls in disguise, so asm @AVar.Name = ‘hello’; end; would actually be equivalent to asm ClassOfSelf.SetName(@Self, 'hello'); end; if SetName is static (and something more complex if SetName is virtual, or if Self is an interface etc.) Also in the more general asm context, it's legal to have JS like asm var v = @AVar.Name = someFunc('hello'); end; which doesn't have any trivial output (as "someFunc" could have side effects, and so could "SetName"), so it would need to be fully parsed and recompiled, and so it would no longer be asm. The current approach is the have "asm" be as "hands off" as possible from a compiler POV. > should @Str.split(@ADelim) be legal? It will error if Str doesn't have a split field on the Delphi side, however (@Str).split(@ADelim) is allowed and safe.
  14. Eric

    Any plans for support of "with" keyword?

    A qualified "with" with a syntax identical to Oxygene is very likely to be added, as it's just syntax sugar for a type-inferenced, block-scoped local variable (which are already supported). The traditional "with" syntax is at the moment not planned for addition, as it leads to ambiguity, and AFAICT Embarcadero are moving away from it too. There may be refactoring tools out there that could help you refactor unqualified "with" away, but I'm not sure which (Castalia maybe?) As for the SmartPascal language, it's originally based on a "Delphi without 'with' and without pointers", but it incorporates multiple extensions & compatibility changes that allow it to also accept a variety of FreePascal & Oxygene syntax elements. It also has its own extensions which range from compatibility with JS/HTML to 1st-class dynamic arrays.
  15. Eric

    ? bug with MidStr() ?

    > What is the general philosophy of SMS regarding strings? Does it try to simulate pascal behavior Yes, SMS does use standard 1-based Pascal strings.
  16. Eric

    ? bug with MidStr() ?

    Yes, that's a bug. MidStr() is actually just an alias for Copy(), but it isn't handled correctly by the codegen. I'm fixing it for the next release, ad interim, you don't have top write your own, just use Copy() instead of MidStr(), the parameters are the same. edit: also took it as an opportunity to add a peephole optimization for the MidStr/Copy calls of the form "Copy(stringVariable, whatever, Length(stringVariable))"
  17. Eric

    Is Array of Const supported in SMS?

    Hmm, there is a slight bug which results in open arrays not being directly accessible, so the following code won't compile until next release :/ procedure ShowArgs(const args: array of const); begin for var j := args.Low to args.High do begin ShowMessage(args[j]); end; end; the workaround is to cast the open array to a dynamic array, which can be done like follows procedure ShowArgs(const args: array of const); var a : array of Variant; begin asm @a = @args; end; for var j := args.Low to args.High do begin ShowMessage(a[j]); end; end; you can then use VarType() to know the type of the argument (that won't change in the next release), the types you can encounter are then varUString, varInteger, varDouble, varBoolean and varVariant.
  18. Eric

    LineBreak

    Added sLineBreak (#13#10) & sHtmlLineBreak (<br>) for the next release.
  19. Eric

    TPointF vector functions are broken

    Fixed for TPointF.Displace. The error for AngleTo seems to be similar (and X instead of an Y when computing dy). However the following implementation would be preferable anyway: function TPointF.AngleTo(const aPoint: TPointF): Float; begin Result := ArcTan2( aPoint.Y - Y, aPoint.X - X ); end;
  20. Eric

    Ellipse does nothing

    The Check() option is really a heavy-handed debugging option, and shouldn't be used in final production code. While in that particular case it could be "optimized", there is no real point as the Check() will still have significant performance impacts in many situations where it couldn't be optimized away. Also as an alternative to TW3Canvas if you want to minimize overhead, you can use the JCanvasRenderingContext2D class directly (you'll lose helpers and utility methods, but that'll be compiled straight to the metal, with only compile-time type checks)
  21. Further details about resolution here https://code.google.com/p/dwscript/issues/detail?id=455
  22. Eric

    Reduce time for procedural call

    That would be inlining support, which isn't there yet, but could indeed be added one day. However, the JS engines themselve can do some inlining, so actual benefits could be muddied. I tried an implementation of your particular test case in js perf: http://jsperf.com/getrgba-inlining Desktop browsers (Chrome & FireFox) apparently do inline well enough on their own, on the mobile side, FireFox apparently does inline things, while Chrome doesn't seem to (didn't have an iOS device around to test, but you should be able to using the jsperf link). In terms of smart & JS, one thing to keep in mind is that var parameter for a value (float, string, etc.) means the value has to be boxed in its own object since there are no pointers in JS (and a var parameter is a pointer in disguise). So you're better off using a record to hold the four values (it can be passed as "var" directly without boxing) or a class. Another thing to be wary of is that last time I tried them, native arrays (JUInt32Array and others) performed worse than usual arrays, so until their support gets improved, you may be better off avoiding them if you don't need them for specific APIs (like WebGL).
  23. Eric

    TW3BufferedImage to draw scaled canvas

    The idea of the buffered image is to work as a buffered render target, so you should draw in the OnRedraw event. DrawScaled will automatically invoke it when it hasn't been Prepared already (either because it was never drawn to or because you called the Invalidate method). In the OnRedraw event you get the buffered image as Sender, and should draw to the Canvas. So in your case, you would: - create the buffer image somewhere in the form construction or initialization sequence - register your drawing code in its OnRedraw - in whatever will result in the image getting changed, call Invalidate (this won't draw anything, so you can call it as many times and as often as you want) - in HandleButtonClicked, use DrawScaled on your target canvas, if the buffer was invalidated, your OnRedraw handler will be called automatically, if nothing was changed, OnRedraw won't be called
  24. Eric

    Multidimensional array

    Dynamic arrays are reference types, just like in Delphi, so your code is effectively adding the same array again and again. However unlike in Delphi, they're a true reference types, ie. SetLength is always a mutator (while in Delphi it can be either a mutator or a copy operator, depending on circumstances, more details at http://www.delphitools.info/2011/07/04/dynamic-arrays-for-dwscript/) As for your code, you could do it the same way as in Delphi: SetLength(A1, 11); // or A1.SetLength(11), both forms are supported for var Index:=0 to 10 do begin SetLength(A1[index], 11): // or A1[index].SetLength(11); for ii:=0 to 10 do A1[index] := Index+ii; end; or in Smart you can also create a multidimensional array directly A1 := new Integer[11, 11]; for var Index:=0 to 10 do for ii:=0 to 10 do A1[index] := Index+ii; and if you prefer an Add-oriented version for var Index := 0 to 10 do begin A2 := new Integer[0]; // important, so it's a different array A1.Add(A2); for ii:=0 to 10 do A2.Add(Index + ii); end;
  25. Eric

    Shortcut+CSS_minified+Resize_resolution

    Can't answer about a & c, but CSS minification is already in for the next version!
×