system.pas 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550
  1. {
  2. This file is part of the Pas2JS run time library.
  3. Copyright (c) 2017 by Mattias Gaertner
  4. See the file COPYING.FPC, included in this distribution,
  5. for details about the copyright.
  6. This program is distributed in the hope that it will be useful,
  7. but WITHOUT ANY WARRANTY; without even the implied warranty of
  8. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  9. **********************************************************************}
  10. unit System;
  11. {$mode objfpc}
  12. {$modeswitch externalclass}
  13. interface
  14. const
  15. LineEnding = #10;
  16. sLineBreak = LineEnding;
  17. MaxSmallint = 32767;
  18. MinSmallint = -32768;
  19. MaxShortInt = 127;
  20. MinShortInt = -128;
  21. MaxByte = $FF;
  22. MaxWord = $FFFF;
  23. MaxLongint = $7fffffff;
  24. MaxCardinal = LongWord($ffffffff);
  25. Maxint = MaxLongint;
  26. IsMultiThread = false;
  27. {*****************************************************************************
  28. Base types
  29. *****************************************************************************}
  30. type
  31. Integer = LongInt;
  32. Cardinal = LongWord;
  33. DWord = LongWord;
  34. SizeInt = NativeInt;
  35. SizeUInt = NativeUInt;
  36. PtrInt = NativeInt;
  37. PtrUInt = NativeUInt;
  38. ValSInt = NativeInt;
  39. ValUInt = NativeUInt;
  40. ValReal = Double;
  41. Real = Double;
  42. Extended = Double;
  43. Int64 = NativeInt unimplemented; // only 53 bits at runtime
  44. UInt64 = NativeUInt unimplemented; // only 52 bits at runtime
  45. QWord = NativeUInt unimplemented; // only 52 bits at runtime
  46. Single = Double unimplemented;
  47. Comp = NativeInt unimplemented;
  48. NativeLargeInt = NativeInt;
  49. NativeLargeUInt = NativeUInt;
  50. UnicodeString = String;
  51. WideString = String;
  52. WideChar = char;
  53. TDynArrayIndex = NativeInt;
  54. TTextLineBreakStyle = (tlbsLF,tlbsCRLF,tlbsCR);
  55. {*****************************************************************************
  56. TObject, TClass
  57. *****************************************************************************}
  58. type
  59. TClass = class of TObject;
  60. { TObject }
  61. TObject = class
  62. private
  63. class var FClassName: String; external name '$classname';
  64. class var FClassParent: TClass; external name '$ancestor';
  65. class var FUnitName: String; external name '$module.$name';
  66. public
  67. constructor Create;
  68. destructor Destroy; virtual;
  69. // Free is using compiler magic.
  70. // Reasons:
  71. // 1. In JS calling obj.Free when obj=nil crashes.
  72. // 2. In JS freeing memory requires to set all references to nil.
  73. // Therefore any obj.free call is replaced by the compiler with some rtl magic.
  74. procedure Free;
  75. class function ClassType: TClass; assembler;
  76. class property ClassName: String read FClassName;
  77. class function ClassNameIs(const Name: string): boolean;
  78. class property ClassParent: TClass read FClassParent;
  79. class function InheritsFrom(aClass: TClass): boolean; assembler;
  80. class property UnitName: String read FUnitName;
  81. procedure AfterConstruction; virtual;
  82. procedure BeforeDestruction; virtual;
  83. function Equals(Obj: TObject): boolean; virtual;
  84. function ToString: String; virtual;
  85. end;
  86. Const
  87. DefaultTextLineBreakStyle : TTextLineBreakStyle = tlbsLF;
  88. {*****************************************************************************
  89. Init / Exit / ExitProc
  90. *****************************************************************************}
  91. var
  92. ExitCode: Integer; external name 'rtl.exitcode';
  93. IsConsole: Boolean = {$IFDEF NodeJS}true{$ELSE}false{$ENDIF};
  94. type
  95. TOnParamCount = function: Longint;
  96. TOnParamStr = function(Index: Longint): String;
  97. var
  98. OnParamCount: TOnParamCount;
  99. OnParamStr: TOnParamStr;
  100. function ParamCount: Longint;
  101. function ParamStr(Index: Longint): String;
  102. {*****************************************************************************
  103. Math
  104. *****************************************************************************}
  105. var // ToDo: make these const
  106. PI: Double; external name 'Math.PI';
  107. MathE: Double; external name 'Math.E'; // Euler's number
  108. MathLN10: Double; external name 'Math.LN10'; // ln(10)
  109. MathLN2: Double; external name 'Math.LN2'; // ln(2)
  110. MathLog10E: Double; external name 'Math.Log10E'; // log10(e)
  111. MathLog2E: Double; external name 'Math.LOG2E'; // log2(e)
  112. MathSQRT1_2: Double; external name 'Math.SQRT1_2'; // sqrt(0.5)
  113. MathSQRT2: Double; external name 'Math.SQRT2'; // sqrt(2)
  114. function Abs(const A: integer): integer; overload; external name 'Math.abs';
  115. function Abs(const A: NativeInt): integer; overload; external name 'Math.abs';
  116. function Abs(const A: Double): Double; overload; external name 'Math.abs';
  117. function ArcTan(const A, B: Double): Double; external name 'Math.atan';
  118. function Cos(const A: Double): Double; external name 'Math.cos';
  119. function Exp(const A: Double): Double; external name 'Math.exp';
  120. function Frac(const A: Double): Double; assembler;
  121. function Ln(const A: Double): Double; external name 'Math.log';
  122. function Odd(const A: Integer): Boolean; assembler;
  123. function Random(const Range: Integer): Integer; overload; assembler;
  124. function Random: Double; overload; external name 'Math.random';
  125. function Round(const A: Double): NativeInt; external name 'Math.round';
  126. function Sin(const A: Double): Double; external name 'Math.sin';
  127. function Sqr(const A: Integer): Integer; assembler; overload;
  128. function Sqr(const A: Double): Double; assembler; overload;
  129. function sqrt(const A: Double): Double; external name 'Math.sqrt';
  130. function Trunc(const A: Double): NativeInt; external name 'Math.trunc'; // not on IE
  131. {*****************************************************************************
  132. String functions
  133. *****************************************************************************}
  134. function Int(const A: Double): double;
  135. function Copy(const S: string; Index, Size: Integer): String; assembler; overload;
  136. function Copy(const S: string; Index: Integer): String; assembler; overload;
  137. procedure Delete(var S: String; Index, Size: Integer); assembler; overload;
  138. function Pos(const Search, InString: String): Integer; assembler; overload;
  139. procedure Insert(const Insertion: String; var Target: String; Index: Integer); overload;
  140. function upcase(c : char) : char; assembler;
  141. procedure val(const S: String; out NI : NativeInt; out Code: Integer); overload;
  142. procedure val(const S: String; out SI : ShortInt; out Code: Integer); overload;
  143. procedure val(const S: String; out B : Byte; out Code: Integer); overload;
  144. procedure val(const S: String; out SI : smallint; out Code: Integer); overload;
  145. procedure val(const S: String; out W : word; out Code : Integer); overload;
  146. procedure val(const S: String; out I : integer; out Code : Integer); overload;
  147. procedure val(const S: String; out C : Cardinal; out Code: Integer); overload;
  148. procedure val(const S: String; out d : double; out Code : Integer); overload;
  149. function StringOfChar(c: Char; l: NativeInt): String;
  150. {*****************************************************************************
  151. Other functions
  152. *****************************************************************************}
  153. procedure Write; varargs; // ToDo: should be compiler built-in function
  154. procedure Writeln; varargs; // ToDo: should be compiler built-in function
  155. Type
  156. TConsoleHandler = Procedure (S : JSValue; NewLine : Boolean);
  157. Function SetWriteCallBack(H : TConsoleHandler) : TConsoleHandler;
  158. function Assigned(const V: JSValue): boolean; assembler; overload;
  159. function StrictEqual(const A: JSValue; const B): boolean; assembler;
  160. function StrictInequal(const A: JSValue; const B): boolean; assembler;
  161. implementation
  162. // function parseInt(s: String; Radix: NativeInt): NativeInt; external name 'parseInt'; // may result NaN
  163. function isNaN(i: JSValue): boolean; external name 'isNaN'; // may result NaN
  164. // needed by ClassNameIs, the real SameText is in SysUtils
  165. function SameText(const s1, s2: String): Boolean; assembler;
  166. asm
  167. return s1.toLowerCase() == s2.toLowerCase();
  168. end;
  169. function ParamCount: Longint;
  170. begin
  171. if Assigned(OnParamCount) then
  172. Result:=OnParamCount()
  173. else
  174. Result:=0;
  175. end;
  176. function ParamStr(Index: Longint): String;
  177. begin
  178. if Assigned(OnParamStr) then
  179. Result:=OnParamStr(Index)
  180. else if Index=0 then
  181. Result:='js'
  182. else
  183. Result:='';
  184. end;
  185. function Frac(const A: Double): Double; assembler;
  186. asm
  187. return A % 1;
  188. end;
  189. function Odd(const A: Integer): Boolean; assembler;
  190. asm
  191. return A&1 != 0;
  192. end;
  193. function Random(const Range: Integer): Integer; assembler;
  194. asm
  195. return Math.floor(Math.random()*Range);
  196. end;
  197. function Sqr(const A: Integer): Integer; assembler;
  198. asm
  199. return A*A;
  200. end;
  201. function Sqr(const A: Double): Double; assembler;
  202. asm
  203. return A*A;
  204. end;
  205. function Copy(const S: string; Index, Size: Integer): String; assembler;
  206. asm
  207. if (Index<1) Index = 1;
  208. return (Size>0) ? S.substring(Index-1,Index+Size-1) : "";
  209. end;
  210. function Copy(const S: string; Index: Integer): String; assembler;
  211. asm
  212. if (Index<1) Index = 1;
  213. return S.substr(Index-1);
  214. end;
  215. procedure Delete(var S: String; Index, Size: Integer);
  216. var
  217. h: String;
  218. begin
  219. if (Index<1) or (Index>length(S)) or (Size<=0) then exit;
  220. h:=S;
  221. S:=copy(h,1,Index-1)+copy(h,Index+Size);
  222. end;
  223. function Pos(const Search, InString: String): Integer; assembler;
  224. asm
  225. return InString.indexOf(Search)+1;
  226. end;
  227. procedure Insert(const Insertion: String; var Target: String; Index: Integer);
  228. var
  229. t: String;
  230. begin
  231. if Insertion='' then exit;
  232. t:=Target;
  233. if Index<1 then
  234. Target:=Insertion+t
  235. else if Index>length(t) then
  236. Target:=t+Insertion
  237. else
  238. Target:=copy(t,1,Index-1)+Insertion+copy(t,Index,length(t));
  239. end;
  240. var
  241. WriteBuf: String;
  242. JSArguments: array of JSValue; external name 'arguments';
  243. WriteCallBack : TConsoleHandler;
  244. Function SetWriteCallBack(H : TConsoleHandler) : TConsoleHandler;
  245. begin
  246. Result:=WriteCallBack;
  247. WriteCallBack:=H;
  248. end;
  249. procedure Write;
  250. var
  251. i: Integer;
  252. begin
  253. for i:=0 to length(JSArguments)-1 do
  254. if Assigned(WriteCallBack) then
  255. WriteCallBack(JSArguments[i],False)
  256. else
  257. WriteBuf:=WriteBuf+String(JSArguments[i]);
  258. end;
  259. procedure Writeln;
  260. var
  261. i,l: Integer;
  262. s: String;
  263. begin
  264. L:=length(JSArguments)-1;
  265. if Assigned(WriteCallBack) then
  266. begin
  267. for i:=0 to L do
  268. WriteCallBack(JSArguments[i],I=L);
  269. end
  270. else
  271. begin
  272. s:=WriteBuf;
  273. for i:=0 to L do
  274. s:=s+String(JSArguments[i]);
  275. asm
  276. console.log(s);
  277. end;
  278. WriteBuf:='';
  279. end;
  280. end;
  281. function Int(const A: Double): double;
  282. function FTrunc(const A: Double): double; overload; external name 'Math.trunc';
  283. begin
  284. Result:=FTrunc(A);
  285. end;
  286. function Number(S: String): Double; external name 'Number';
  287. procedure val(const S: String; out NI : NativeInt; out Code: Integer);
  288. var
  289. x : double;
  290. begin
  291. Code:=0;
  292. x:=Number(S);
  293. if isNaN(x) or (X<>Int(X)) then
  294. Code:=1
  295. else
  296. NI:=Trunc(x);
  297. end;
  298. procedure val(const S: String; out SI : ShortInt; out Code: Integer);
  299. var
  300. X:Double;
  301. begin
  302. Code:=0;
  303. x:=Number(S);
  304. if isNaN(x) or (X<>Int(X)) then
  305. Code:=1
  306. else if (x<MinShortInt) or (x>MaxShortInt) then
  307. Code:=2
  308. else
  309. SI:=Trunc(x);
  310. end;
  311. procedure val(const S: String; out SI: smallint; out Code: Integer);
  312. var
  313. x: double;
  314. begin
  315. Code:=0;
  316. x:=Number(S);
  317. if isNaN(x) or (X<>Int(X)) then
  318. Code:=1
  319. else if (x<MinSmallint) or (x>MaxSmallint) then
  320. Code:=2
  321. else
  322. SI:=Trunc(x);
  323. end;
  324. procedure val(const S: String; out C: Cardinal; out Code: Integer);
  325. var
  326. x: double;
  327. begin
  328. Code:=0;
  329. x:=Number(S);
  330. if isNaN(x) or (X<>Int(X)) then
  331. Code:=1
  332. else if (x<0) or (x>MaxCardinal) then
  333. Code:=2
  334. else
  335. C:=trunc(x);
  336. end;
  337. procedure val(const S: String; out B: Byte; out Code: Integer);
  338. var
  339. x: double;
  340. begin
  341. Code:=0;
  342. x:=Number(S);
  343. if isNaN(x) or (X<>Int(X)) then
  344. Code:=1
  345. else if (x<0) or (x>MaxByte) then
  346. Code:=2
  347. else
  348. B:=Trunc(x);
  349. end;
  350. procedure val(const S: String; out W: word; out Code: Integer);
  351. var
  352. x: double;
  353. begin
  354. Code:=0;
  355. x:=Number(S);
  356. if isNaN(x) then
  357. Code:=1
  358. else if (x<0) or (x>MaxWord) then
  359. Code:=2
  360. else
  361. W:=Trunc(x);
  362. end;
  363. procedure val(const S : String; out I : integer; out Code : Integer);
  364. var
  365. x: double;
  366. begin
  367. Code:=0;
  368. x:=Number(S);
  369. if isNaN(x) then
  370. Code:=1
  371. else if x>MaxInt then
  372. Code:=2
  373. else
  374. I:=Trunc(x);
  375. end;
  376. procedure val(const S : String; out d : double; out Code : Integer);
  377. Var
  378. x: double;
  379. begin
  380. x:=Number(S);
  381. if isNaN(x) then
  382. Code:=1
  383. else
  384. begin
  385. Code:=0;
  386. d:=x;
  387. end;
  388. end;
  389. function upcase(c : char) : char; assembler;
  390. asm
  391. return c.toUpperCase();
  392. end;
  393. function StringOfChar(c: Char; l: NativeInt): String;
  394. var
  395. i: Integer;
  396. begin
  397. Result:='';
  398. for i:=1 to l do Result:=Result+c;
  399. end;
  400. function Assigned(const V: JSValue): boolean; assembler;
  401. asm
  402. return (V!=undefined) && (V!=null) && (!rtl.isArray(V) || (V.length > 0));
  403. end;
  404. function StrictEqual(const A: JSValue; const B): boolean; assembler;
  405. asm
  406. return A === B;
  407. end;
  408. function StrictInequal(const A: JSValue; const B): boolean; assembler;
  409. asm
  410. return A !== B;
  411. end;
  412. { TObject }
  413. constructor TObject.Create;
  414. begin
  415. end;
  416. destructor TObject.Destroy;
  417. begin
  418. end;
  419. procedure TObject.Free;
  420. begin
  421. Destroy;
  422. end;
  423. class function TObject.ClassType: TClass; assembler;
  424. asm
  425. return this;
  426. end;
  427. class function TObject.ClassNameIs(const Name: string): boolean;
  428. begin
  429. Result:=SameText(Name,ClassName);
  430. end;
  431. class function TObject.InheritsFrom(aClass: TClass): boolean; assembler;
  432. asm
  433. return (aClass!=null) && ((this==aClass) || aClass.isPrototypeOf(this));
  434. end;
  435. procedure TObject.AfterConstruction;
  436. begin
  437. end;
  438. procedure TObject.BeforeDestruction;
  439. begin
  440. end;
  441. function TObject.Equals(Obj: TObject): boolean;
  442. begin
  443. Result:=Obj=Self;
  444. end;
  445. function TObject.ToString: String;
  446. begin
  447. Result:=ClassName;
  448. end;
  449. initialization
  450. ExitCode:=0; // set it here, so that WPO does not remove it
  451. end.