pas2js - Unterschied char und byte in Array

Antworten
Mathias
Beiträge: 6899
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

pas2js - Unterschied char und byte in Array

Beitrag von Mathias »

Wen ich folgendes Programm mit pas2js starte, bekomme ich eine merkwürdige Ausgabe.

Code: Alles auswählen

program project1;
uses
  JS,  Classes,  SysUtils,  Web,  browserconsole;

  procedure onload;
  type
    TCharArray = array of char;
    TByteArray = array of byte;
  var
    ba: TByteArray;
    ca: TCharArray;
    i: integer;

  begin
    SetLength(ca, 10);

    for i := 0 to Length(ca) - 1 do begin
      ca[i] := char(byte('A')+i);
    end;

    ba := TByteArray(ca);

    Writeln('ba: ', Length(ba));
    Writeln('ca: ', Length(ca));
    for i := 0 to Length(ba) - 1 do begin
      Write(ba[i], ' - ');
    end;
    Writeln;
    for i := 0 to Length(ca) - 1 do begin
      Write(ca[i], ' - ');
    end;
  end;

begin
  onload;
end.
Lasse ich das Programm mit normalen FPC laufen, bekomme ich wie erwartet folgende Ausgabe.

Code: Alles auswählen

ba: 10
ca: 10
65 - 66 - 67 - 68 - 69 - 70 - 71 - 72 - 73 - 74 - 
A - B - C - D - E - F - G - H - I - J -
Lasse ich es aber mit pas2js laufen, wird folgendes ausgespuckt.

Code: Alles auswählen

ba: 10
ca: 10
A - B - C - D - E - F - G - H - I - J - A - B - C - D - E - F - G - H - I - J - 
Sogar das Writeln wird ignoriert.

Mache ich dies mit einem einfachen Char und Byte funktioniert es wie erwartet.

Code: Alles auswählen

  var
    ch: char;
    by: byte;
  begin
    ch := #65;
    Writeln(ch);    // -> A
    by := byte(ch);
    Writeln(by);  // -> 65

Sehe ich das richtig, das pas2j2 generell Probleme mit Pascal-Array hat ?
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

PascalDragon
Beiträge: 945
Registriert: Mi 3. Jun 2020, 07:18
OS, Lazarus, FPC: L 2.0.8, FPC Trunk, OS Win/Linux
CPU-Target: Aarch64 bis Z80 ;)
Wohnort: München

Re: pas2js - Unterschied char und byte in Array

Beitrag von PascalDragon »

Mathias hat geschrieben: Di 9. Jan 2024, 19:46

Code: Alles auswählen

    ba := TByteArray(ca);
Das ist auch unter FPC letztlich undefiniertes Verhalten. Es kann funktionieren, aber durch den Typecast schaltest du im Endeffekt das Typsystem von Object Pascal aus (das fliegt dir spätestens dann um die Ohren, wenn FPC mit einer Unicode RTL released wird, bei der Char ein Alias für UnicodeChar, statt AnsiChar ist).

Mit Pas2JS wird der Code sehr direkt nach JavaScript übersetzt und JavaScript hat letztlich keine Typsicherheit und wenn du dir den generierten JS-Code anschaust, dann sieht man einfach nur folgendes für den obigen Code:

Code: Alles auswählen

ba = ca;
Also aus Sicht des JS-Codes sind beide Arrays tatsächlich das Gleiche.

TL;DR: Mach sowas einfach nicht, weder in FPC noch in Pas2JS.
FPC Compiler Entwickler

Benutzeravatar
theo
Beiträge: 10856
Registriert: Mo 11. Sep 2006, 19:01

Re: pas2js - Unterschied char und byte in Array

Beitrag von theo »

Ich denke, da muss man immer das Zielsystem im Auge haben, wenn man so etwas versucht.
Gerade gestern hatte ich einen Fall, wo ich ein Byte-Array auf ein ShortInt-Array casten musste (und umgekehrt).
Normalerweise ist das ja kein Problem unter FPC, da es nur eine andere "Betrachtungsweise" der Bytes ist.
Was macht denn Pas2Js hier?:

Code: Alles auswählen

type

  TByteArray = array of Byte;
  TShortIntArr = array of ShortInt;    
...
var si:TShortIntArr;
begin
  si:=TShortIntArr.create(-80,-20,20,80);
  writeln(si[0]);
  writeln(TByteArray(si)[0]);
end;     

Mathias
Beiträge: 6899
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: pas2js - Unterschied char und byte in Array

Beitrag von Mathias »

Was macht denn Pas2Js hier?:
Ich vermute, das arrays wie in Javascript gehandhabt werden.

Sowas wird wie in javascript abgearbeitet.

Code: Alles auswählen

var
  i: integer;
  testarray: array of byte = ('sfsdf', 123456, 'd', 12.34);
begin
  for i := 0 to Length(testarray) - 1 do begin
    Writeln(testarray[i]);
  end;
Ausgabe:

Code: Alles auswählen

sfsdf
123456
d
12.34
Bei allem was eine richtige Array braucht, zB. Bufferübergaben in WebGL, muss man sich mit Puffern behelfen. So wie es bei echtem javascript auch nötig ist.

Wie bei diesem Beispiel hier.

Code: Alles auswählen

const
  TriangleVector: array of GLfloat =
    (-0.4, 0.1, 0.0, 0.4, 0.1, 0.0, 0.0, 0.7, 0.0);
    
  function .InitVertexData(va: array of GLfloat): TJSUInt8Array;
  var
    floatBuffer: TJSFloat32Array;
    byteBuffer: TJSUint8Array;

  begin
    byteBuffer := TJSUint8Array.New(Length(va) * 4);
    floatBuffer := TJSFloat32Array.New(byteBuffer.buffer, 0, Length(va));
    floatBuffer._set(va, 0);

    Result := byteBuffer;
  end;        
  
begin
....  
    gl.bufferData(gl.ARRAY_BUFFER, InitVertexData(TriangleVector), gl.STATIC_DRAW);   
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

PascalDragon
Beiträge: 945
Registriert: Mi 3. Jun 2020, 07:18
OS, Lazarus, FPC: L 2.0.8, FPC Trunk, OS Win/Linux
CPU-Target: Aarch64 bis Z80 ;)
Wohnort: München

Re: pas2js - Unterschied char und byte in Array

Beitrag von PascalDragon »

theo hat geschrieben: Sa 13. Jan 2024, 10:07 Was macht denn Pas2Js hier?:

Code: Alles auswählen

type

  TByteArray = array of Byte;
  TShortIntArr = array of ShortInt;    
...
var si:TShortIntArr;
begin
  si:=TShortIntArr.create(-80,-20,20,80);
  writeln(si[0]);
  writeln(TByteArray(si)[0]);
end;     
JavaScript kennt keine Typen in dem Sinne, das heißt der TypeCast wird beim Transpilieren verschwinden und demnach werden die beiden Ausgaben gleich sein.

Und nochmal: auch in FPC ist das undefiniertes Verhalten, das funktionieren kann, aber nicht muss und auch eventuell durch Optimierungen oder je nach Plattform kaputt gehen kann.
FPC Compiler Entwickler

Benutzeravatar
theo
Beiträge: 10856
Registriert: Mo 11. Sep 2006, 19:01

Re: pas2js - Unterschied char und byte in Array

Beitrag von theo »

PascalDragon hat geschrieben: So 14. Jan 2024, 20:10 Und nochmal: auch in FPC ist das undefiniertes Verhalten, das funktionieren kann, aber nicht muss und auch eventuell durch Optimierungen oder je nach Plattform kaputt gehen kann.
Kannst du mir das erklären?
Dass ein Char aus Unicode-Gründen die Länge ändern könnte, kann ich mir vorstellen, aber warum ein Shortint oder ein Byte im normalen FPC nicht mehr 8-bit lang sein sollten, kann ich mir nicht wirklich vorstellen.
Was verstehe ich nicht?

Antworten