tcconverter.pp 45 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415
  1. {
  2. This file is part of the Free Component Library (FCL)
  3. Copyright (c) 2014 by Michael Van Canneyt
  4. Unit tests for Pascal-to-Javascript converter class.
  5. See the file COPYING.FPC, included in this distribution,
  6. for details about the copyright.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  10. **********************************************************************
  11. Examples:
  12. ./testpas2js --suite=TTestExpressionConverter.TestVariable
  13. }
  14. unit tcconverter;
  15. {$mode objfpc}{$H+}
  16. interface
  17. uses
  18. Classes, SysUtils, fpcunit, testregistry, fppas2js, jsbase, jstree, pastree;
  19. type
  20. { TTestConverter }
  21. TTestConverter = class(TTestCase)
  22. private
  23. FAC: TPasElement;
  24. FConverter: TPasToJSConverter;
  25. FRes: TJSElement;
  26. FSource: TPasElement;
  27. protected
  28. procedure SetUp; override;
  29. procedure TearDown; override;
  30. Property AttemptConvert : TPasElement Read FAC Write FAC;
  31. Procedure TryConvert;
  32. Function Convert(AElement : TPasElement; AClass : TJSElementClass) : TJSElement;
  33. Property Converter : TPasToJSConverter Read FConverter;
  34. Property TheSource : TPasElement Read FSource Write FSource;
  35. Property TheResult : TJSElement Read FRes Write FRes;
  36. Public
  37. Class procedure AssertEquals(Const Msg : String; AExpected, AActual : TJSType); overload;
  38. Class procedure AssertLiteral(Const Msg : String; Lit : TJSElement; AType : TJSType);
  39. Class procedure AssertLiteral(Const Msg : String; Lit : TJSElement; AValue : Boolean);
  40. Class procedure AssertLiteral(Const Msg : String; Lit : TJSElement; AValue : TJSString);
  41. Class procedure AssertLiteral(Const Msg : String; Lit : TJSElement; AValue : TJSNumber);
  42. Class procedure AssertIdentifier(Const Msg : String; Ident : TJSElement; AName : String);
  43. Class Procedure AssertAssignStatement(Const Msg: String; El: TJSElement; LHS: String='a'; RHS: String='b');
  44. Class Procedure AssertEmptyBlockStatement(Const Msg: String; El: TJSElement);
  45. class Function AssertListStatement(Const Msg: String; El: TJSElement) : TJSStatementList;
  46. class Function AssertElement(Const Msg: String; AClass : TJSElementClass; El: TJSElement) : TJSElement;
  47. Class Function CreateLiteral(AValue : String) : TPasExpr;
  48. Class Function CreateLiteral(AValue : Double) : TPasExpr;
  49. Class Function CreateIdent(AName : String) : TPrimitiveExpr;
  50. Class Function CreateAssignStatement(LHS: String = 'a';RHS : String = 'b'): TPasImplAssign;
  51. Class Function CreateFunctionCall(AName : String; Params : Array of String) : TParamsExpr;
  52. Class Function CreateCondition: TPasExpr;
  53. end;
  54. { TTestTestConverter }
  55. TTestTestConverter = class(TTestConverter)
  56. published
  57. procedure TestEmpty;
  58. end;
  59. { TTestExpressionConverter }
  60. TTestExpressionConverter = Class(TTestConverter)
  61. Protected
  62. Function TestLiteralExpression(AElement : TPasElement; AClass : TJSElementClass) : TJSLIteral;
  63. Function TestUnaryExpression(AElement : TPasElement; AClass : TJSElementClass) : TJSUnary;
  64. Function TestBinaryExpression(AElement : TPasElement; AClass : TJSElementClass) : TJSBinary;
  65. Published
  66. Procedure TestPrimitiveString;
  67. Procedure TestPrimitiveNumber;
  68. Procedure TestPrimitiveNil;
  69. Procedure TestPrimitiveBoolTrue;
  70. Procedure TestPrimitiveBoolFalse;
  71. Procedure TestPrimitiveIdent;
  72. Procedure TestUnaryMinus;
  73. Procedure TestUnaryPlus;
  74. Procedure TestBinaryPlus;
  75. Procedure TestBinaryMinus;
  76. Procedure TestBinaryMultiply;
  77. Procedure TestBinaryDivision;
  78. Procedure TestBinaryDiv;
  79. Procedure TestBinaryMod;
  80. Procedure TestBinarySHL;
  81. Procedure TestBinarySHR;
  82. Procedure TestBinaryEqual;
  83. Procedure TestBinaryNotEqual;
  84. Procedure TestBinaryLessThan;
  85. Procedure TestBinaryLessThanEqual;
  86. Procedure TestBinaryGreater;
  87. Procedure TestBinaryGreaterThanEqual;
  88. Procedure TestBinaryIs;
  89. Procedure TestCallExpressionNone;
  90. Procedure TestCallExpressionOne;
  91. Procedure TestCallExpressionTwo;
  92. Procedure TestMemberExpressionArrayOneDim;
  93. Procedure TestMemberExpressionArrayTwoDim;
  94. Procedure TestVariable;
  95. Procedure TestArrayVariable;
  96. end;
  97. { TTestStatementConverter }
  98. TTestStatementConverter = Class(TTestConverter)
  99. private
  100. Published
  101. Procedure TestRaiseStatement;
  102. Procedure TestAssignStatement;
  103. Procedure TestIfStatement;
  104. Procedure TestIfStatementFull;
  105. Procedure TestIfStatementElse;
  106. Procedure TestWhileStatementEmpty;
  107. Procedure TestWhileStatement;
  108. Procedure TestSimpleStatement;
  109. Procedure TestRepeatUntilStatementEmpty;
  110. Procedure TestRepeatUntilStatementOne;
  111. Procedure TestRepeatUntilStatementTwo;
  112. Procedure TestRepeatUntilStatementThree;
  113. Procedure TestForLoopUp;
  114. Procedure TestForLoopDown;
  115. Procedure TestBeginEndBlockEmpty;
  116. Procedure TestBeginEndBlockStatementOne;
  117. Procedure TestBeginEndBlockStatementTwo;
  118. Procedure TestBeginEndBlockStatementThree;
  119. Procedure TestWithStatementEmpty;
  120. Procedure TestWithStatementOne;
  121. Procedure TestWithStatementTwo;
  122. Procedure TestTryFinallyStatement;
  123. Procedure TestTryExceptStatement;
  124. Procedure TestTryExceptStatementOnE;
  125. Procedure TestReRaise;
  126. Procedure TestVariableStatement;
  127. end;
  128. implementation
  129. uses typinfo;
  130. { TTestStatementConverter }
  131. Procedure TTestStatementConverter.TestRaiseStatement;
  132. Var
  133. R : TPasImplRaise;
  134. E : TJSThrowStatement;
  135. begin
  136. R:=TPasImplRaise.Create('',Nil);
  137. R.ExceptObject:=CreateIdent('e');
  138. E:=TJSThrowStatement(Convert(R,TJSThrowStatement));
  139. AssertIdentifier('Raise exception object',E.A,'e');
  140. end;
  141. Procedure TTestStatementConverter.TestAssignStatement;
  142. Var
  143. R : TPasImplAssign;
  144. E : TJSSimpleAssignStatement;
  145. begin
  146. R:=CreateAssignStatement('a','b');
  147. E:=TJSSimpleAssignStatement(Convert(R,TJSSimpleAssignStatement));
  148. AssertAssignStatement('a = b assignment',E);
  149. end;
  150. Procedure TTestStatementConverter.TestIfStatement;
  151. Var
  152. R : TPasImplIfElse;
  153. E : TJSIfStatement;
  154. begin
  155. // If a then ;
  156. R:=TPasImplIfElse.Create('',Nil);
  157. R.ConditionExpr:=CreateCondition;
  158. E:=TJSIfStatement(Convert(R,TJSIfStatement));
  159. AssertNull('If branch is empty',E.BTrue);
  160. AssertNull('No else branch',E.BFalse);
  161. AssertIdentifier('Left hand side OK',E.Cond,'a');
  162. end;
  163. Procedure TTestStatementConverter.TestIfStatementFull;
  164. Var
  165. R : TPasImplIfElse;
  166. E : TJSIfStatement;
  167. begin
  168. // If a then a:=b;
  169. R:=TPasImplIfElse.Create('',Nil);
  170. R.ConditionExpr:=CreateCondition;
  171. R.IfBranch:=CreateAssignStatement;
  172. E:=TJSIfStatement(Convert(R,TJSIfStatement));
  173. AssertIdentifier('Conditional expression',E.Cond,'a');
  174. AssertAssignStatement('If branch',E.btrue);
  175. AssertNull('No else branch',E.bfalse);
  176. end;
  177. Procedure TTestStatementConverter.TestIfStatementElse;
  178. Var
  179. R : TPasImplIfElse;
  180. E : TJSIfStatement;
  181. begin
  182. // If a then a:=b else a:=e;
  183. R:=TPasImplIfElse.Create('',Nil);
  184. R.ConditionExpr:=CreateCondition;
  185. R.IfBranch:=CreateAssignStatement;
  186. R.ElseBranch:=CreateAssignStatement('a','e');
  187. E:=TJSIfStatement(Convert(R,TJSIfStatement));
  188. AssertIdentifier('Conditional expression',E.Cond,'a');
  189. AssertAssignStatement('If branch',E.btrue);
  190. AssertAssignStatement('else branch',E.bfalse,'a','e');
  191. end;
  192. Procedure TTestStatementConverter.TestWhileStatementEmpty;
  193. Var
  194. R : TPasImplWhileDo;
  195. E : TJSWhileStatement;
  196. begin
  197. // While a do ;
  198. R:=TPasImplWhileDo.Create('',Nil);
  199. R.ConditionExpr:=CreateCondition;
  200. E:=TJSWhileStatement(Convert(R,TJSWhileStatement));
  201. AssertIdentifier('Conditional expression',E.Cond,'a');
  202. AssertEquals('No statement, empty block statement',TJSEmptyBlockStatement,E.body.ClassType);
  203. end;
  204. Procedure TTestStatementConverter.TestWhileStatement;
  205. Var
  206. R : TPasImplWhileDo;
  207. E : TJSWhileStatement;
  208. begin
  209. // While a do b:=c;
  210. R:=TPasImplWhileDo.Create('',Nil);
  211. R.Body:=CreateAssignStatement('b','c');
  212. R.ConditionExpr:=CreateCondition;
  213. E:=TJSWhileStatement(Convert(R,TJSWhileStatement));
  214. AssertIdentifier('Conditional expression',E.Cond,'a');
  215. AssertAssignStatement('While Block is assignment',E.body,'b','c');
  216. end;
  217. Procedure TTestStatementConverter.TestSimpleStatement;
  218. Var
  219. R : TPasImplSimple;
  220. E : TJSExpressionStatement;
  221. C : TJSCallExpression;
  222. begin
  223. R:=TPasImplSimple.Create('',Nil);
  224. R.Expr:=CreateFunctionCall('a',['b']);
  225. E:=TJSExpressionStatement(Convert(R,TJSExpressionStatement));
  226. AssertNotNull('Have call node',E.A);
  227. AssertEquals('Have call expression',TJSCallExpression,E.A.ClassType);
  228. C:=TJSCallExpression(E.A);
  229. AssertIdentifier('Call expression',C.Expr,'a');
  230. end;
  231. Procedure TTestStatementConverter.TestRepeatUntilStatementEmpty;
  232. Var
  233. R : TPasImplRepeatUntil;
  234. E : TJSWhileStatement;
  235. begin
  236. // Repeat until a;
  237. R:=TPasImplRepeatUntil.Create('',Nil);
  238. R.ConditionExpr:=CreateCondition;
  239. E:=TJSDoWhileStatement(Convert(R,TJSDoWhileStatement));
  240. AssertNotNull('Have condition',E.Cond);
  241. AssertEquals('Correct condition class',TJSUnaryNotExpression,E.Cond.ClassType);
  242. AssertIdentifier('Conditional expression',TJSUnaryNotExpression(E.Cond).A,'a');
  243. AssertNotNull('Have body',E.Body);
  244. AssertEquals('No statement, empty block statement',TJSEmptyBlockStatement,E.body.ClassType);
  245. end;
  246. Procedure TTestStatementConverter.TestRepeatUntilStatementOne;
  247. Var
  248. R : TPasImplRepeatUntil;
  249. E : TJSWhileStatement;
  250. L : TJSStatementList;
  251. begin
  252. // Repeat b:=c; until a;
  253. R:=TPasImplRepeatUntil.Create('',Nil);
  254. R.ConditionExpr:=CreateCondition;
  255. R.AddAssign(CreateIdent('b'),CreateIdent('c'));
  256. E:=TJSDoWhileStatement(Convert(R,TJSDoWhileStatement));
  257. AssertNotNull('Have condition',E.Cond);
  258. AssertEquals('Correct condition class',TJSUnaryNotExpression,E.Cond.ClassType);
  259. AssertIdentifier('Conditional expression',TJSUnaryNotExpression(E.Cond).A,'a');
  260. AssertNotNull('Have body',E.Body);
  261. AssertEquals('List statement, List statement',TJSStatementList,E.body.ClassType);
  262. L:=TJSStatementList(E.Body);
  263. AssertAssignStatement('First List statement is assignment',L.A,'b','c');
  264. AssertNull('No second statement',L.B);
  265. end;
  266. Procedure TTestStatementConverter.TestRepeatUntilStatementTwo;
  267. Var
  268. R : TPasImplRepeatUntil;
  269. E : TJSWhileStatement;
  270. L : TJSStatementList;
  271. begin
  272. // Repeat b:=c; d:=e; until a;
  273. R:=TPasImplRepeatUntil.Create('',Nil);
  274. R.ConditionExpr:=CreateCondition;
  275. R.AddAssign(CreateIdent('b'),CreateIdent('c'));
  276. R.AddAssign(CreateIdent('d'),CreateIdent('e'));
  277. E:=TJSDoWhileStatement(Convert(R,TJSDoWhileStatement));
  278. AssertNotNull('Have condition',E.Cond);
  279. AssertEquals('Correct condition class',TJSUnaryNotExpression,E.Cond.ClassType);
  280. AssertIdentifier('Conditional expression',TJSUnaryNotExpression(E.Cond).A,'a');
  281. L:=AssertListStatement('Multiple statements',E.Body);
  282. AssertAssignStatement('First List statement is assignment',L.A,'b','c');
  283. AssertAssignStatement('Second List statement is assignment',L.B,'d','e');
  284. end;
  285. Procedure TTestStatementConverter.TestRepeatUntilStatementThree;
  286. Var
  287. R : TPasImplRepeatUntil;
  288. E : TJSWhileStatement;
  289. L : TJSStatementList;
  290. begin
  291. // Repeat b:=c; d:=e; f:=g; until a;
  292. R:=TPasImplRepeatUntil.Create('',Nil);
  293. R.ConditionExpr:=CreateCondition;
  294. R.AddAssign(CreateIdent('b'),CreateIdent('c'));
  295. R.AddAssign(CreateIdent('d'),CreateIdent('e'));
  296. R.AddAssign(CreateIdent('f'),CreateIdent('g'));
  297. E:=TJSDoWhileStatement(Convert(R,TJSDoWhileStatement));
  298. AssertNotNull('Have condition',E.Cond);
  299. AssertEquals('Correct condition class',TJSUnaryNotExpression,E.Cond.ClassType);
  300. AssertIdentifier('Conditional expression',TJSUnaryNotExpression(E.Cond).A,'a');
  301. AssertNotNull('Have body',E.Body);
  302. L:=AssertListStatement('Multiple statements',E.Body);
  303. AssertAssignStatement('First List statement is assignment',L.A,'b','c');
  304. L:=AssertListStatement('Second statement is again list',L.B);
  305. AssertAssignStatement('Second List statement is assignment',L.A,'d','e');
  306. AssertAssignStatement('third List statement is assignment',L.B,'f','g');
  307. end;
  308. Procedure TTestStatementConverter.TestForLoopUp;
  309. Var
  310. F : TPasImplForLoop;
  311. ForSt: TJSForStatement;
  312. L : TJSStatementList;
  313. VD : TJSVarDeclaration;
  314. A : TJSSimpleAssignStatement;
  315. I : TJSUnaryPostPlusPlusExpression;
  316. Cond : TJSRelationalExpressionLE;
  317. VS: TJSVariableStatement;
  318. LoopEndVar, LoopVar: String;
  319. VDL: TJSVariableDeclarationList;
  320. begin
  321. // For I:=1 to 100 do a:=b;
  322. F:=TPasImplForLoop.Create('',Nil);
  323. F.Variable:=TPasVariable.Create('I',F);
  324. F.VariableName:=CreateIdent('I');
  325. F.StartExpr:=CreateLiteral(1);
  326. F.EndExpr:=CreateLiteral(100);
  327. F.Body:=CreateAssignStatement();
  328. ForSt:=TJSForStatement(Convert(F,TJSForStatement));
  329. // Should be
  330. // for(var $l1=1, $le2=100; $l1<=$le2; $l1++){
  331. // I=$l1;
  332. // a=b;
  333. // }
  334. LoopVar:=Pas2JSBuiltInNames[pbivnLoop]+'1';
  335. LoopEndVar:=Pas2JSBuiltInNames[pbivnLoopEnd]+'2';
  336. // "var $l1=1, $le2=100"
  337. VS:=TJSVariableStatement(AssertElement('For init is var '+LoopEndVar,TJSVariableStatement,ForSt.Init));
  338. VDL:=TJSVariableDeclarationList(AssertElement('For init var has comma',TJSVariableDeclarationList,VS.A));
  339. VD:=TJSVarDeclaration(AssertElement('var '+LoopVar,TJSVarDeclaration,VDL.A));
  340. AssertEquals('Correct name for '+LoopVar,LoopVar,VD.Name);
  341. AssertLiteral('Correct start value',VD.Init,1);
  342. VD:=TJSVarDeclaration(AssertElement('var '+LoopEndVar,TJSVarDeclaration,VDL.B));
  343. AssertEquals('Correct name for '+LoopEndVar,LoopEndVar,VD.Name);
  344. AssertLiteral('Correct end value',VD.Init,100);
  345. // $l1<=$le2
  346. Cond:=TJSRelationalExpressionLE(AssertElement('Condition is <= expression',TJSRelationalExpressionLE,ForSt.Cond));
  347. AssertIdentifier('Cond LHS is '+LoopVar,Cond.A,LoopVar);
  348. AssertIdentifier('Cond RHS is '+LoopEndVar,Cond.B,LoopEndVar);
  349. // $l1++
  350. I:=TJSUnaryPostPlusPlusExpression(AssertElement('Increment is ++ statement',TJSUnaryPostPlusPlusExpression,ForSt.Incr));
  351. AssertIdentifier('++ on correct variable name',I.A,LoopVar);
  352. // body
  353. L:=TJSStatementList(AssertElement('For body ist list',TJSStatementList,ForSt.Body));
  354. // I:=$l1
  355. A:=TJSSimpleAssignStatement(AssertElement('I:=$l1',TJSSimpleAssignStatement,L.A));
  356. AssertIdentifier('Init statement LHS is loop variable',A.LHS,'i');
  357. AssertIdentifier('Init statement RHS is '+LoopVar,A.Expr,LoopVar);
  358. AssertAssignStatement('Correct body',L.B);
  359. end;
  360. Procedure TTestStatementConverter.TestForLoopDown;
  361. Var
  362. F : TPasImplForLoop;
  363. ForSt: TJSForStatement;
  364. L : TJSStatementList;
  365. VD : TJSVarDeclaration;
  366. A : TJSSimpleAssignStatement;
  367. I : TJSUnaryPostMinusMinusExpression;
  368. Cond: TJSRelationalExpressionGE;
  369. VS: TJSVariableStatement;
  370. LoopEndVar, LoopVar: String;
  371. VDL: TJSVariableDeclarationList;
  372. begin
  373. // For I:=100 downto 1 do a:=b;
  374. F:=TPasImplForLoop.Create('',Nil);
  375. F.Variable:=TPasVariable.Create('I',F);
  376. F.VariableName:=CreateIdent('I');
  377. F.StartExpr:=CreateLiteral(100);
  378. F.EndExpr:=CreateLiteral(1);
  379. F.LoopType:=ltDown;
  380. F.Body:=CreateAssignStatement();
  381. ForSt:=TJSForStatement(Convert(F,TJSForStatement));
  382. // Should be
  383. // for(var $l1=100, $le2=1; $l1>=$le2; $l1--){
  384. // I=$l1;
  385. // a=b;
  386. // }
  387. LoopVar:=Pas2JSBuiltInNames[pbivnLoop]+'1';
  388. LoopEndVar:=Pas2JSBuiltInNames[pbivnLoopEnd]+'2';
  389. // "var $l1=100, $le2=1"
  390. VS:=TJSVariableStatement(AssertElement('For init is var '+LoopEndVar,TJSVariableStatement,ForSt.Init));
  391. VDL:=TJSVariableDeclarationList(AssertElement('For init var has comma',TJSVariableDeclarationList,VS.A));
  392. VD:=TJSVarDeclaration(AssertElement('var '+LoopVar,TJSVarDeclaration,VDL.A));
  393. AssertEquals('Correct name for '+LoopVar,LoopVar,VD.Name);
  394. AssertLiteral('Correct start value',VD.Init,100);
  395. VD:=TJSVarDeclaration(AssertElement('var '+LoopEndVar,TJSVarDeclaration,VDL.B));
  396. AssertEquals('Correct name for '+LoopEndVar,LoopEndVar,VD.Name);
  397. AssertLiteral('Correct end value',VD.Init,1);
  398. // $l1>=$le2
  399. Cond:=TJSRelationalExpressionGE(AssertElement('Condition is >= expression',TJSRelationalExpressionGE,ForSt.Cond));
  400. AssertIdentifier('Cond LHS is '+LoopVar,Cond.A,LoopVar);
  401. AssertIdentifier('Cond RHS is '+LoopEndVar,Cond.B,LoopEndVar);
  402. // $l1--
  403. I:=TJSUnaryPostMinusMinusExpression(AssertElement('Increment is -- statement',TJSUnaryPostMinusMinusExpression,ForSt.Incr));
  404. AssertIdentifier('-- on correct variable name',I.A,LoopVar);
  405. // body
  406. L:=TJSStatementList(AssertElement('For body ist list',TJSStatementList,ForSt.Body));
  407. // I:=$l1
  408. A:=TJSSimpleAssignStatement(AssertElement('I:=$l1',TJSSimpleAssignStatement,L.A));
  409. AssertIdentifier('Init statement LHS is loop variable',A.LHS,'i');
  410. AssertIdentifier('Init statement RHS is '+LoopVar,A.Expr,LoopVar);
  411. AssertAssignStatement('Correct body',L.B);
  412. end;
  413. Procedure TTestStatementConverter.TestBeginEndBlockEmpty;
  414. Var
  415. R : TPasImplBeginBlock;
  416. begin
  417. // begin end;
  418. R:=TPasImplBeginBlock.Create('',Nil);
  419. Convert(R,TJSEmptyBlockStatement);
  420. end;
  421. Procedure TTestStatementConverter.TestBeginEndBlockStatementOne;
  422. Var
  423. R : TPasImplBeginBlock;
  424. L : TJSStatementList;
  425. begin
  426. // begin a:=bend;
  427. R:=TPasImplBeginBlock.Create('',Nil);
  428. R.AddAssign(CreateIdent('a'),CreateIdent('b'));
  429. L:=TJSStatementList(Convert(R,TJSStatementList));
  430. AssertNull('No second statement',L.B);
  431. AssertAssignStatement('First List statement is assignment',L.A,'a','b');
  432. end;
  433. Procedure TTestStatementConverter.TestBeginEndBlockStatementTwo;
  434. Var
  435. R : TPasImplBeginBlock;
  436. L : TJSStatementList;
  437. begin
  438. // begin a:=b; c:=d; end;
  439. R:=TPasImplBeginBlock.Create('',Nil);
  440. R.AddAssign(CreateIdent('a'),CreateIdent('b'));
  441. R.AddAssign(CreateIdent('c'),CreateIdent('d'));
  442. L:=TJSStatementList(Convert(R,TJSStatementList));
  443. AssertAssignStatement('First List statement is assignment',L.A,'a','b');
  444. AssertAssignStatement('Second List statement is assignment',L.B,'c','d');
  445. end;
  446. Procedure TTestStatementConverter.TestBeginEndBlockStatementThree;
  447. Var
  448. R : TPasImplBeginBlock;
  449. L : TJSStatementList;
  450. begin
  451. // begin a:=b; c:=d; end;
  452. R:=TPasImplBeginBlock.Create('',Nil);
  453. R.AddAssign(CreateIdent('a'),CreateIdent('b'));
  454. R.AddAssign(CreateIdent('c'),CreateIdent('d'));
  455. R.AddAssign(CreateIdent('e'),CreateIdent('f'));
  456. L:=TJSStatementList(Convert(R,TJSStatementList));
  457. AssertAssignStatement('First List statement is assignment',L.A,'a','b');
  458. L:=AssertListStatement('Second statement is again list',L.B);
  459. AssertAssignStatement('Second List statement is assignment',L.A,'c','d');
  460. AssertAssignStatement('third List statement is assignment',L.B,'e','f');
  461. end;
  462. Procedure TTestStatementConverter.TestWithStatementEmpty;
  463. Var
  464. W : TPasImplWithDo;
  465. El : TJSWithStatement;
  466. begin
  467. // With A do ;
  468. W:=TPasImplWithDo.Create('',NIl);
  469. W.Expressions.Add(CreateIdent('a'));
  470. El:=TJSWithStatement(Convert(W,TJSWithStatement));
  471. AssertIdentifier('Correct with expression',EL.A,'a');
  472. AssertEmptyBlockStatement('Empty with',El.B);
  473. end;
  474. Procedure TTestStatementConverter.TestWithStatementOne;
  475. Var
  476. W : TPasImplWithDo;
  477. El : TJSWithStatement;
  478. begin
  479. // With A do b:=c;
  480. W:=TPasImplWithDo.Create('',NIl);
  481. W.Expressions.Add(CreateIdent('a'));
  482. W.Body:=CreateAssignStatement('b','c');
  483. El:=TJSWithStatement(Convert(W,TJSWithStatement));
  484. AssertIdentifier('Correct with expression',EL.A,'a');
  485. AssertAssignStatement('Correct assignment',EL.B,'b','c');
  486. end;
  487. Procedure TTestStatementConverter.TestWithStatementTwo;
  488. Var
  489. W : TPasImplWithDo;
  490. El : TJSWithStatement;
  491. begin
  492. // With A,D do b:=c;
  493. W:=TPasImplWithDo.Create('',NIl);
  494. W.Expressions.Add(CreateIdent('a'));
  495. W.Expressions.Add(CreateIdent('d'));
  496. W.Body:=CreateAssignStatement('b','c');
  497. El:=TJSWithStatement(Convert(W,TJSWithStatement));
  498. AssertIdentifier('Correct with expression',EL.A,'a');
  499. El:=TJSWithStatement(AssertElement('Have second with statement',TJSWithStatement,EL.B));
  500. AssertIdentifier('Correct with expression',EL.A,'d');
  501. AssertAssignStatement('Correct assignment',El.B,'b','c');
  502. end;
  503. Procedure TTestStatementConverter.TestTryFinallyStatement;
  504. Var
  505. T : TPasImplTry;
  506. F : TPasImplTryFinally;
  507. El : TJSTryFinallyStatement;
  508. L : TJSStatementList;
  509. begin
  510. // Try a:=B finally b:=c end;
  511. T:=TPasImplTry.Create('',Nil);
  512. T.AddElement(CreateAssignStatement('a','b'));
  513. F:=T.AddFinally;
  514. F.AddElement(CreateAssignStatement('b','c'));
  515. El:=TJSTryFinallyStatement(Convert(T,TJSTryFinallyStatement));
  516. L:=AssertListStatement('try..finally block is statement list',EL.Block);
  517. AssertAssignStatement('Correct assignment in try..finally block',L.A,'a','b');
  518. AssertNull('No second statement',L.B);
  519. L:=AssertListStatement('try..finally block is statement list',El.BFinally);
  520. AssertAssignStatement('Correct assignment in finally..end block',L.A,'b','c');
  521. AssertNull('No second statement',L.B);
  522. end;
  523. Procedure TTestStatementConverter.TestTryExceptStatement;
  524. Var
  525. T : TPasImplTry;
  526. F : TPasImplTryExcept;
  527. El : TJSTryCatchStatement;
  528. L : TJSStatementList;
  529. ExceptObjName: String;
  530. begin
  531. // Try a:=b except b:=c end;
  532. (*
  533. Becomes:
  534. try {
  535. a=b;
  536. } catch ($e) {
  537. b = c;
  538. }
  539. *)
  540. T:=TPasImplTry.Create('',Nil);
  541. T.AddElement(CreateAssignStatement('a','b'));
  542. F:=T.AddExcept;
  543. F.AddElement(CreateAssignStatement('b','c'));
  544. // Convert
  545. El:=TJSTryCatchStatement(Convert(T,TJSTryCatchStatement));
  546. // check "catch(exceptobject)"
  547. ExceptObjName:=lowercase(Pas2JSBuiltInNames[pbivnExceptObject]);
  548. AssertEquals('Correct exception object name',ExceptObjName,String(El.Ident));
  549. // check "a=b;"
  550. L:=AssertListStatement('try..except block is statement list',El.Block);
  551. AssertAssignStatement('Correct assignment in try..except block',L.A,'a','b');
  552. AssertNull('No second statement',L.B);
  553. // check "b=c;'
  554. L:=AssertListStatement('try..except block is statement list',El.BCatch);
  555. AssertAssignStatement('Correct assignment in except..end block',L.A,'b','c');
  556. AssertNull('No second statement',L.B);
  557. end;
  558. Procedure TTestStatementConverter.TestTryExceptStatementOnE;
  559. Var
  560. T : TPasImplTry;
  561. F : TPasImplTryExcept;
  562. O : TPasImplExceptOn;
  563. El : TJSTryCatchStatement;
  564. L : TJSStatementList;
  565. I : TJSIfStatement;
  566. IC : TJSCallExpression;
  567. D: TJSDotMemberExpression;
  568. ExObj: TJSElement;
  569. VS: TJSVariableStatement;
  570. V: TJSVarDeclaration;
  571. ExceptObjName: String;
  572. begin
  573. // Try a:=B except on E : exception do b:=c end;
  574. (*
  575. Becomes:
  576. try {
  577. a=b;
  578. } catch (exceptobject) {
  579. if (exception.isPrototypeOf(exceptobject)) {
  580. var e = exceptobject;
  581. b = c;
  582. }
  583. }
  584. *)
  585. T:=TPasImplTry.Create('',Nil);
  586. T.AddElement(CreateAssignStatement('a','b'));
  587. F:=T.AddExcept;
  588. O:=F.AddExceptOn('E','Exception');
  589. O.Body:=CreateAssignStatement('b','c');
  590. // Convert
  591. El:=TJSTryCatchStatement(Convert(T,TJSTryCatchStatement));
  592. // check "catch(exceptobject)"
  593. ExceptObjName:=lowercase(Pas2JSBuiltInNames[pbivnExceptObject]);
  594. AssertEquals('Correct exception object name',ExceptObjName,String(El.Ident));
  595. // check "if"
  596. I:=TJSIfStatement(AssertElement('On block is if',TJSIfStatement,El.BCatch));
  597. // check if condition "exception.isPrototypeOf(exceptobject)"
  598. IC:=TJSCallExpression(AssertElement('If condition is call expression',TJSCallExpression,I.Cond));
  599. D:=TJSDotMemberExpression(AssertElement('exception.isPrototypeOf is dot member expression',TJSDotMemberExpression,IC.Expr));
  600. Assertidentifier('left side of exception.isPrototypeOf',D.MExpr,'exception');
  601. AssertEquals('right side of exception.isPrototypeOf','isPrototypeOf',String(D.Name));
  602. AssertNotNull('args of exception.isPrototypeOf(exceptobject)',IC.Args);
  603. AssertEquals('args of exception.isPrototypeOf(exceptobject)',1,IC.Args.Elements.Count);
  604. ExObj:=IC.Args.Elements.Elements[0].Expr;
  605. Assertidentifier('arg of exception.isPrototypeOf(exceptobject)',ExObj,ExceptObjName);
  606. // check statement "var e = exceptobject;"
  607. L:=AssertListStatement('On block is always a list',I.BTrue);
  608. writeln('TTestStatementConverter.TestTryExceptStatementOnE ',L.A.ClassName);
  609. VS:=TJSVariableStatement(AssertElement('First statement in list is a var statement',TJSVariableStatement,L.A));
  610. V:=TJSVarDeclaration(AssertElement('var declaration e=ExceptObject',TJSVarDeclaration,VS.A));
  611. AssertEquals('Variable name is identifier in On A : Ex do','e',V.Name);
  612. Assertidentifier('Variable init is exception object',V.Init,ExceptObjName);
  613. // check "b = c;"
  614. AssertAssignStatement('Original assignment in second statement',L.B,'b','c');
  615. end;
  616. Procedure TTestStatementConverter.TestReRaise;
  617. Var
  618. T : TPasImplTry;
  619. F : TPasImplTryExcept;
  620. O : TPasImplExceptOn;
  621. El : TJSTryCatchStatement;
  622. L : TJSStatementList;
  623. I : TJSIfStatement;
  624. IC : TJSCallExpression;
  625. R : TJSThrowStatement;
  626. V : TJSVarDeclaration;
  627. D: TJSDotMemberExpression;
  628. ExObj: TJSElement;
  629. VS: TJSVariableStatement;
  630. ExceptObjName: String;
  631. begin
  632. // Try a:=B except on E : exception do raise; end;
  633. (*
  634. Becomes:
  635. try {
  636. a=b;
  637. } catch ($e) {
  638. if (exception.isPrototypeOf($e)) {
  639. var e = $e;
  640. throw $e;
  641. }
  642. }
  643. *)
  644. T:=TPasImplTry.Create('',Nil);
  645. T.AddElement(CreateAssignStatement('a','b'));
  646. F:=T.AddExcept;
  647. O:=F.AddExceptOn('E','Exception');
  648. O.Body:=TPasImplRaise.Create('',Nil);
  649. // Convert
  650. El:=TJSTryCatchStatement(Convert(T,TJSTryCatchStatement));
  651. // check "catch(exceptobject)"
  652. ExceptObjName:=lowercase(Pas2JSBuiltInNames[pbivnExceptObject]);
  653. AssertEquals('Correct exception object name',ExceptObjName,String(El.Ident));
  654. // check "if"
  655. I:=TJSIfStatement(AssertElement('On block is if',TJSIfStatement,El.BCatch));
  656. // check if condition "exception.isPrototypeOf(exceptobject)"
  657. IC:=TJSCallExpression(AssertElement('If condition is call expression',TJSCallExpression,I.Cond));
  658. D:=TJSDotMemberExpression(AssertElement('exception.isPrototypeOf is dot member expression',TJSDotMemberExpression,IC.Expr));
  659. Assertidentifier('left side of exception.isPrototypeOf',D.MExpr,'exception');
  660. AssertEquals('right side of exception.isPrototypeOf','isPrototypeOf',String(D.Name));
  661. AssertNotNull('args of exception.isPrototypeOf(ExceptObject)',IC.Args);
  662. AssertEquals('args of exception.isPrototypeOf(ExceptObject)',1,IC.Args.Elements.Count);
  663. ExObj:=IC.Args.Elements.Elements[0].Expr;
  664. Assertidentifier('arg of exception.isPrototypeOf(ExceptObject)',ExObj,ExceptObjName);
  665. // check statement "var e = exceptobject;"
  666. L:=AssertListStatement('On block is always a list',I.BTrue);
  667. writeln('TTestStatementConverter.TestTryExceptStatementOnE ',L.A.ClassName);
  668. VS:=TJSVariableStatement(AssertElement('First statement in list is a var statement',TJSVariableStatement,L.A));
  669. V:=TJSVarDeclaration(AssertElement('var declaration e=ExceptObject',TJSVarDeclaration,VS.A));
  670. AssertEquals('Variable name is identifier in On A : Ex do','e',V.Name);
  671. Assertidentifier('Variable init is exception object',V.Init,ExceptObjName);
  672. R:=TJSThrowStatement(AssertElement('On block is throw statement',TJSThrowStatement,L.B));
  673. Assertidentifier('R expression is original exception ',R.A,ExceptObjName);
  674. end;
  675. Procedure TTestStatementConverter.TestVariableStatement;
  676. Var
  677. S : TPasSection;
  678. V : TPasVariable;
  679. L : TJSStatementList;
  680. JV : TJSVariableStatement;
  681. JVD : TJSVarDeclaration;
  682. begin
  683. S:=TPasSection.Create('',Nil);
  684. V:=TPasVariable.Create('A',Nil);
  685. S.Declarations.Add(V);
  686. S.Variables.Add(V);
  687. L:=TJSStatementList(Convert(S,TJSStatementList));
  688. JV:=TJSVariableStatement(AssertElement('Variable statement',TJSVariableStatement,L.A));
  689. JVD:=TJSVarDeclaration(AssertElement('Variable declaration',TJSVarDeclaration,JV.A));
  690. AssertEquals('Correct variable name','a',JVD.Name);
  691. end;
  692. { TTestExpressionConverter }
  693. Function TTestExpressionConverter.TestLiteralExpression(AElement: TPasElement;
  694. AClass: TJSElementClass): TJSLIteral;
  695. Var
  696. E : TJSElement;
  697. begin
  698. E:=Convert(AElement,AClass);
  699. if not (E is TJSLiteral) then
  700. Fail('Do not have literal class, but: '+E.ClassName);
  701. Result:=TJSLIteral(E);
  702. end;
  703. Function TTestExpressionConverter.TestUnaryExpression(AElement: TPasElement; AClass: TJSElementClass): TJSUnary;
  704. Var
  705. E : TJSElement;
  706. begin
  707. E:=Convert(AElement,AClass);
  708. AssertNotNull('Convert returned a result',E);
  709. if not (E is TJSUnary) then
  710. Fail('Do not have unary class, but: '+E.ClassName);
  711. AssertEquals('TTestExpressionConverter.TestUnaryExpression: wrong class',AClass.ClassName,E.ClassName);
  712. Result:=TJSUnary(E);
  713. end;
  714. Function TTestExpressionConverter.TestBinaryExpression(AElement: TPasElement;
  715. AClass: TJSElementClass): TJSBinary;
  716. Var
  717. E : TJSElement;
  718. begin
  719. E:=Convert(AElement,AClass);
  720. if not (E is TJSBinary) then
  721. Fail('Do not have literal class, but: '+E.ClassName);
  722. Result:=TJSBinary(E);
  723. end;
  724. Procedure TTestExpressionConverter.TestPrimitiveString;
  725. Var
  726. S : TPrimitiveExpr;
  727. E : TJSLiteral;
  728. begin
  729. S:=TPrimitiveExpr.Create(Nil,pekString,'''me''');
  730. E:=TestLiteralExpression(S,TJSLiteral);
  731. AssertEquals('Correct literal type',jstString,E.Value.ValueType);
  732. AssertEquals('Correct literal value','me',String(E.Value.AsString));
  733. end;
  734. Procedure TTestExpressionConverter.TestPrimitiveNumber;
  735. Var
  736. S : TPrimitiveExpr;
  737. E : TJSLiteral;
  738. begin
  739. S:=TPrimitiveExpr.Create(Nil,pekNumber,'1.23');
  740. E:=TestLiteralExpression(S,TJSLiteral);
  741. AssertEquals('Correct literal type',jstNumber,E.Value.ValueType);
  742. AssertEquals('Correct literal value',1.23,E.Value.AsNumber);
  743. end;
  744. Procedure TTestExpressionConverter.TestPrimitiveNil;
  745. Var
  746. S : TNilExpr;
  747. E : TJSLiteral;
  748. begin
  749. S:=TNilExpr.Create(Nil);
  750. E:=TestLiteralExpression(S,TJSLiteral);
  751. AssertEquals('Correct literal type',jstNull,E.Value.ValueType);
  752. AssertEquals('Correct literal value',True,E.Value.IsNull);
  753. end;
  754. Procedure TTestExpressionConverter.TestPrimitiveBoolTrue;
  755. Var
  756. S : TBoolConstExpr;
  757. E : TJSLiteral;
  758. begin
  759. S:=TBoolConstExpr.Create(Nil,pekBoolConst,True);
  760. E:=TestLiteralExpression(S,TJSLiteral);
  761. AssertEquals('Correct literal type',jstBoolean,E.Value.ValueType);
  762. AssertEquals('Correct literal value',True,E.Value.AsBoolean);
  763. end;
  764. Procedure TTestExpressionConverter.TestPrimitiveBoolFalse;
  765. Var
  766. S : TBoolConstExpr;
  767. E : TJSLiteral;
  768. begin
  769. S:=TBoolConstExpr.Create(Nil,pekBoolConst,False);
  770. E:=TestLiteralExpression(S,TJSLiteral);
  771. AssertEquals('Correct literal type',jstBoolean,E.Value.ValueType);
  772. AssertEquals('Correct literal value',False,E.Value.AsBoolean);
  773. end;
  774. Procedure TTestExpressionConverter.TestPrimitiveIdent;
  775. Var
  776. Id : TPrimitiveExpr;
  777. Res : TJSPrimaryExpressionIdent;
  778. begin
  779. Id:=TPrimitiveExpr.Create(Nil,pekIdent,'a');
  780. Res:=TJSPrimaryExpressionIdent(Convert(Id,TJSPrimaryExpressionIdent));
  781. AssertEquals('Correct identifier name','a',String(Res.Name));
  782. end;
  783. Procedure TTestExpressionConverter.TestUnaryMinus;
  784. Var
  785. U : TUnaryExpr;
  786. E : TJSUnaryMinusExpression;
  787. begin
  788. U:=TUnaryExpr.Create(Nil,pekUnary,eopSubtract);
  789. U.Operand:=CreateLiteral(1.23);
  790. E:=TJSUnaryMinusExpression(TestUnaryExpression(U,TJSUnaryMinusExpression));
  791. AssertLiteral('Correct literal for minus',E.A,1.23)
  792. end;
  793. Procedure TTestExpressionConverter.TestUnaryPlus;
  794. Var
  795. U : TUnaryExpr;
  796. E : TJSUnaryPlusExpression;
  797. begin
  798. U:=TUnaryExpr.Create(Nil,pekUnary,eopAdd);
  799. U.Operand:=CreateLiteral(1.23);
  800. E:=TJSUnaryPlusExpression(TestUnaryExpression(U,TJSUnaryPlusExpression));
  801. AssertLiteral('Correct literal for plus',E.A,1.23)
  802. end;
  803. Procedure TTestExpressionConverter.TestBinaryPlus;
  804. Var
  805. B : TBinaryExpr;
  806. E : TJSAdditiveExpressionPlus;
  807. begin
  808. B:=TBinaryExpr.Create(Nil,pekBinary,eopAdd);
  809. B.left:=CreateLiteral(1.23);
  810. B.Right:=CreateLiteral(3.45);
  811. E:=TJSAdditiveExpressionPlus(TestBinaryExpression(B,TJSAdditiveExpressionPlus));
  812. AssertLiteral('Correct left literal for addition',E.A,1.23);
  813. AssertLiteral('Correct right literal for addition',E.B,3.45);
  814. end;
  815. Procedure TTestExpressionConverter.TestBinaryMinus;
  816. Var
  817. B : TBinaryExpr;
  818. E : TJSAdditiveExpressionMinus;
  819. begin
  820. B:=TBinaryExpr.Create(Nil,pekBinary,eopSubtract);
  821. B.left:=CreateLiteral(1.23);
  822. B.Right:=CreateLiteral(3.45);
  823. E:=TJSAdditiveExpressionMinus(TestBinaryExpression(B,TJSAdditiveExpressionMinus));
  824. AssertLiteral('Correct left literal for subtract',E.A,1.23);
  825. AssertLiteral('Correct right literal for subtract',E.B,3.45);
  826. end;
  827. Procedure TTestExpressionConverter.TestBinaryMultiply;
  828. Var
  829. B : TBinaryExpr;
  830. E : TJSMultiplicativeExpressionMul;
  831. begin
  832. B:=TBinaryExpr.Create(Nil,pekBinary,eopMultiply);
  833. B.left:=CreateLiteral(1.23);
  834. B.Right:=CreateLiteral(3.45);
  835. E:=TJSMultiplicativeExpressionMul(TestBinaryExpression(B,TJSMultiplicativeExpressionMul));
  836. AssertLiteral('Correct left literal for multiplication',E.A,1.23);
  837. AssertLiteral('Correct right literal for multiplication',E.B,3.45);
  838. end;
  839. Procedure TTestExpressionConverter.TestBinaryDivision;
  840. Var
  841. B : TBinaryExpr;
  842. E : TJSMultiplicativeExpressionDiv;
  843. begin
  844. B:=TBinaryExpr.Create(Nil,pekBinary,eopDivide);
  845. B.left:=CreateLiteral(1.23);
  846. B.Right:=CreateLiteral(3.45);
  847. E:=TJSMultiplicativeExpressionDiv(TestBinaryExpression(B,TJSMultiplicativeExpressionDiv));
  848. AssertLiteral('Correct left literal for division',E.A,1.23);
  849. AssertLiteral('Correct right literal for division',E.B,3.45);
  850. end;
  851. Procedure TTestExpressionConverter.TestBinaryDiv;
  852. Var
  853. B : TBinaryExpr;
  854. E : TJSMultiplicativeExpressionDiv;
  855. C: TJSCallExpression;
  856. Args: TJSArguments;
  857. begin
  858. B:=TBinaryExpr.Create(Nil,pekBinary,eopDiv);
  859. B.left:=CreateLiteral(1.23);
  860. B.Right:=CreateLiteral(3.45);
  861. C:=TJSCallExpression(Convert(B,TJSCallExpression));
  862. Args:=TJSArguments(AssertElement('Math.floor param',TJSArguments,C.Args));
  863. E:=TJSMultiplicativeExpressionDiv(AssertElement('param',TJSMultiplicativeExpressionDiv,Args.Elements.Elements[0].Expr));
  864. AssertLiteral('Correct left literal for div',E.A,1.23);
  865. AssertLiteral('Correct right literal for div',E.B,3.45);
  866. end;
  867. Procedure TTestExpressionConverter.TestBinaryMod;
  868. Var
  869. B : TBinaryExpr;
  870. E : TJSMultiplicativeExpressionMod;
  871. begin
  872. B:=TBinaryExpr.Create(Nil,pekBinary,eopMod);
  873. B.left:=CreateLiteral(1.23);
  874. B.Right:=CreateLiteral(3.45);
  875. E:=TJSMultiplicativeExpressionMod(TestBinaryExpression(B,TJSMultiplicativeExpressionMod));
  876. AssertLiteral('Correct left literal for mod',E.A,1.23);
  877. AssertLiteral('Correct right literal for mod',E.B,3.45);
  878. end;
  879. Procedure TTestExpressionConverter.TestBinarySHL;
  880. Var
  881. B : TBinaryExpr;
  882. E : TJSLShiftExpression;
  883. begin
  884. B:=TBinaryExpr.Create(Nil,pekBinary,eopSHL);
  885. B.left:=CreateLiteral(13);
  886. B.Right:=CreateLiteral(3);
  887. E:=TJSLShiftExpression(TestBinaryExpression(B,TJSLShiftExpression));
  888. AssertLiteral('Correct left literal for shl',E.A,13);
  889. AssertLiteral('Correct right literal for shl',E.B,3);
  890. end;
  891. Procedure TTestExpressionConverter.TestBinarySHR;
  892. Var
  893. B : TBinaryExpr;
  894. E : TJSURShiftExpression;
  895. begin
  896. B:=TBinaryExpr.Create(Nil,pekBinary,eopSHR);
  897. B.left:=CreateLiteral(13);
  898. B.Right:=CreateLiteral(3);
  899. E:=TJSURShiftExpression(TestBinaryExpression(B,TJSURShiftExpression));
  900. AssertLiteral('Correct left literal for shr',E.A,13);
  901. AssertLiteral('Correct right literal for shr',E.B,3);
  902. end;
  903. Procedure TTestExpressionConverter.TestBinaryEqual;
  904. Var
  905. B : TBinaryExpr;
  906. E : TJSEqualityExpressionSEQ;
  907. begin
  908. B:=TBinaryExpr.Create(Nil,pekBinary,eopEqual);
  909. B.left:=CreateLiteral(13);
  910. B.Right:=CreateLiteral(3);
  911. E:=TJSEqualityExpressionSEQ(TestBinaryExpression(B,TJSEqualityExpressionSEQ));
  912. AssertLiteral('Correct left literal for equal',E.A,13);
  913. AssertLiteral('Correct right literal for equal',E.B,3);
  914. end;
  915. Procedure TTestExpressionConverter.TestBinaryNotEqual;
  916. Var
  917. B : TBinaryExpr;
  918. E : TJSEqualityExpressionSNE;
  919. begin
  920. B:=TBinaryExpr.Create(Nil,pekBinary,eopNotEqual);
  921. B.left:=CreateLiteral(13);
  922. B.Right:=CreateLiteral(3);
  923. E:=TJSEqualityExpressionSNE(TestBinaryExpression(B,TJSEqualityExpressionSNE));
  924. AssertLiteral('Correct left literal for not equal',E.A,13);
  925. AssertLiteral('Correct right literal for not equal',E.B,3);
  926. end;
  927. Procedure TTestExpressionConverter.TestBinaryLessThan;
  928. Var
  929. B : TBinaryExpr;
  930. E : TJSRelationalExpressionLT;
  931. begin
  932. B:=TBinaryExpr.Create(Nil,pekBinary,eopLessThan);
  933. B.left:=CreateLiteral(13);
  934. B.Right:=CreateLiteral(3);
  935. E:=TJSRelationalExpressionLT(TestBinaryExpression(B,TJSRelationalExpressionLT));
  936. AssertLiteral('Correct left literal for less than',E.A,13);
  937. AssertLiteral('Correct right literal for less than',E.B,3);
  938. end;
  939. Procedure TTestExpressionConverter.TestBinaryLessThanEqual;
  940. Var
  941. B : TBinaryExpr;
  942. E : TJSRelationalExpressionLE;
  943. begin
  944. B:=TBinaryExpr.Create(Nil,pekBinary,eopLessThanEqual);
  945. B.left:=CreateLiteral(13);
  946. B.Right:=CreateLiteral(3);
  947. E:=TJSRelationalExpressionLE(TestBinaryExpression(B,TJSRelationalExpressionLE));
  948. AssertLiteral('Correct left literal for less than or equal',E.A,13);
  949. AssertLiteral('Correct right literal for less than or equal',E.B,3);
  950. end;
  951. Procedure TTestExpressionConverter.TestBinaryGreater;
  952. Var
  953. B : TBinaryExpr;
  954. E : TJSRelationalExpressionGT;
  955. begin
  956. B:=TBinaryExpr.Create(Nil,pekBinary,eopGreaterThan);
  957. B.left:=CreateLiteral(13);
  958. B.Right:=CreateLiteral(3);
  959. E:=TJSRelationalExpressionGT(TestBinaryExpression(B,TJSRelationalExpressionGT));
  960. AssertLiteral('Correct left literal for greater than',E.A,13);
  961. AssertLiteral('Correct right literal for greater than',E.B,3);
  962. end;
  963. Procedure TTestExpressionConverter.TestBinaryGreaterThanEqual;
  964. Var
  965. B : TBinaryExpr;
  966. E : TJSRelationalExpressionGE;
  967. begin
  968. B:=TBinaryExpr.Create(Nil,pekBinary,eopGreaterThanEqual);
  969. B.left:=CreateLiteral(13);
  970. B.Right:=CreateLiteral(3);
  971. E:=TJSRelationalExpressionGE(TestBinaryExpression(B,TJSRelationalExpressionGE));
  972. AssertLiteral('Correct left literal for greater than or equal',E.A,13);
  973. AssertLiteral('Correct right literal for greater than or equal',E.B,3);
  974. end;
  975. Procedure TTestExpressionConverter.TestBinaryIs;
  976. Var
  977. B : TBinaryExpr;
  978. E : TJSRelationalExpressionInstanceOf;
  979. begin
  980. B:=TBinaryExpr.Create(Nil,pekBinary,eopIs);
  981. B.left:=CreateIdent('a');
  982. B.Right:=CreateIdent('b');
  983. E:=TJSRelationalExpressionInstanceOf(TestBinaryExpression(B,TJSRelationalExpressionInstanceOf));
  984. AssertIdentifier('Correct left literal for is',E.A,'a');
  985. AssertIdentifier('Correct right literal for is',E.B,'b');
  986. end;
  987. Procedure TTestExpressionConverter.TestCallExpressionNone;
  988. Var
  989. B : TParamsExpr;
  990. E : TJSCallExpression;
  991. begin
  992. // a();
  993. B:=CreateFunctionCall('a',[]);
  994. E:=TJSCallExpression(Convert(B,TJSCallExpression));
  995. AssertIdentifier('Correct left literal for is',E.Expr,'a');
  996. AssertNull('No arguments',E.Args);
  997. // AssertEquals('No arguments',0,E.Args.Elements.Count);
  998. end;
  999. Procedure TTestExpressionConverter.TestCallExpressionOne;
  1000. Var
  1001. B : TParamsExpr;
  1002. E : TJSCallExpression;
  1003. begin
  1004. // a(b);
  1005. B:=CreateFunctionCall('a',['b']);
  1006. E:=TJSCallExpression(Convert(B,TJSCallExpression));
  1007. AssertIdentifier('Correct left literal for is',E.Expr,'a');
  1008. AssertNotNull('have arguments',E.Args);
  1009. AssertEquals('Argument count',1,E.Args.Elements.Count);
  1010. AssertIdentifier('Argument 1 identifier',E.Args.Elements[0].Expr,'b');
  1011. end;
  1012. Procedure TTestExpressionConverter.TestCallExpressionTwo;
  1013. Var
  1014. B : TParamsExpr;
  1015. E : TJSCallExpression;
  1016. begin
  1017. // a(b,c);
  1018. B:=CreateFunctionCall('a',['b','c']);
  1019. E:=TJSCallExpression(Convert(B,TJSCallExpression));
  1020. AssertIdentifier('Correct left literal for is',E.Expr,'a');
  1021. AssertNotNull('have arguments',E.Args);
  1022. AssertEquals('Argument count',2,E.Args.Elements.Count);
  1023. AssertIdentifier('Argument 1 identifier',E.Args.Elements[0].Expr,'b');
  1024. AssertIdentifier('Argument 2 identifier',E.Args.Elements[1].Expr,'c');
  1025. end;
  1026. Procedure TTestExpressionConverter.TestMemberExpressionArrayOneDim;
  1027. Var
  1028. B : TParamsExpr;
  1029. E : TJSBracketMemberExpression;
  1030. begin
  1031. // a[b];
  1032. B:=TParamsExpr.Create(Nil,pekArrayParams,eopNone);
  1033. B.Value:=CreateIdent('a');
  1034. B.AddParam(CreateIdent('b'));
  1035. E:=TJSBracketMemberExpression(Convert(B,TJSBracketMemberExpression));
  1036. AssertIdentifier('Correct array name',E.MExpr,'a');
  1037. AssertIdentifier('Correct array member name',E.Name,'b');
  1038. end;
  1039. Procedure TTestExpressionConverter.TestMemberExpressionArrayTwoDim;
  1040. Var
  1041. B : TParamsExpr;
  1042. begin
  1043. // a[b,c];
  1044. B:=TParamsExpr.Create(Nil,pekArrayParams,eopNone);
  1045. B.Value:=CreateIdent('a');
  1046. B.AddParam(CreateIdent('b'));
  1047. B.AddParam(CreateIdent('c'));
  1048. AttemptConvert:=B;
  1049. AssertException('Pascal element not supported: TParamsExpr:TParamsExpr: Cannot convert 2-dim arrays',EPas2JS,@TryConvert);
  1050. end;
  1051. Procedure TTestExpressionConverter.TestVariable;
  1052. Var
  1053. VD : TJSVarDeclaration;
  1054. R :TPasVariable;
  1055. begin
  1056. R:=TPasVariable.Create('A',Nil);
  1057. VD:=TJSVarDeclaration(Convert(R,TJSVarDeclaration));
  1058. AssertEquals('Correct name, lowercased','a',VD.Name);
  1059. AssertNotNull('No init',VD.Init);
  1060. end;
  1061. Procedure TTestExpressionConverter.TestArrayVariable;
  1062. Var
  1063. VD : TJSVarDeclaration;
  1064. R :TPasVariable;
  1065. A : TJSArrayLiteral;
  1066. begin
  1067. R:=TPasVariable.Create('A',Nil);
  1068. R.VarType:=TPasArrayType.Create('myarray',Nil);
  1069. VD:=TJSVarDeclaration(Convert(R,TJSVarDeclaration));
  1070. AssertEquals('Correct name, lowercased','a',VD.Name);
  1071. A:=TJSArrayLiteral(AssertElement('Init is array literal',TJSArrayLiteral,VD.Init));
  1072. AssertEquals('No elements',0,A.Elements.Count);
  1073. end;
  1074. procedure TTestTestConverter.TestEmpty;
  1075. begin
  1076. AssertNotNull('Have converter',Converter);
  1077. end;
  1078. procedure TTestConverter.SetUp;
  1079. begin
  1080. FConverter:=TPasToJSConverter.Create;
  1081. FConverter.Globals:=TPasToJSConverterGlobals.Create(FConverter);
  1082. end;
  1083. procedure TTestConverter.TearDown;
  1084. begin
  1085. FreeAndNil(FRes);
  1086. FreeAndNil(FSource);
  1087. FreeAndNil(FConverter);
  1088. end;
  1089. Procedure TTestConverter.TryConvert;
  1090. begin
  1091. Convert(FAC,TJSElement);
  1092. end;
  1093. Function TTestConverter.Convert(AElement: TPasElement; AClass: TJSElementClass
  1094. ): TJSElement;
  1095. begin
  1096. FSource:=AElement;
  1097. Result:=FConverter.ConvertPasElement(AElement,nil);
  1098. FRes:=Result;
  1099. if (AClass<>Nil) then
  1100. begin
  1101. AssertNotNull('Have conversion result',Result);
  1102. AssertEquals('Conversion result has correct class',AClass,Result.ClassType);
  1103. end;
  1104. end;
  1105. Class procedure TTestConverter.AssertEquals(Const Msg: String; AExpected, AActual: TJSType);
  1106. begin
  1107. AssertEquals(Msg,GetEnumName(TypeInfo(TJSType),Ord(AExpected)),
  1108. GetEnumName(TypeInfo(TJSType),Ord(AActual)));
  1109. end;
  1110. Class procedure TTestConverter.AssertLiteral(Const Msg : String; Lit: TJSElement; AType: TJSType);
  1111. begin
  1112. AssertNotNull(Msg+': Have instance',Lit);
  1113. AssertEquals(Msg+': Correct class',TJSLIteral,Lit.ClassType);
  1114. AssertEquals(Msg+': Correct value type',AType,TJSLIteral(Lit).Value.ValueType);
  1115. end;
  1116. Class procedure TTestConverter.AssertLiteral(Const Msg : String; Lit: TJSElement; AValue: Boolean);
  1117. begin
  1118. AssertLiteral(Msg,Lit,jstBoolean);
  1119. AssertEquals(Msg+': Correct value',AValue,TJSLiteral(Lit).Value.AsBoolean);
  1120. end;
  1121. Class procedure TTestConverter.AssertLiteral(Const Msg : String; Lit: TJSElement; AValue: TJSString);
  1122. begin
  1123. AssertLiteral(Msg,Lit,jstString);
  1124. AssertEquals(Msg+': Correct value',String(AValue),String(TJSLiteral(Lit).Value.AsString));
  1125. end;
  1126. Class procedure TTestConverter.AssertLiteral(Const Msg : String; Lit: TJSElement; AValue: TJSNumber);
  1127. begin
  1128. AssertLiteral(Msg,Lit,jstNumber);
  1129. AssertEquals(Msg+': Correct value',AValue,TJSLiteral(Lit).Value.AsNumber);
  1130. end;
  1131. Class procedure TTestConverter.AssertIdentifier(Const Msg: String;
  1132. Ident: TJSElement; AName: String);
  1133. begin
  1134. AssertNotNull(Msg+': Have instance',Ident);
  1135. AssertEquals(Msg+': Correct class',TJSPrimaryExpressionIdent,Ident.ClassType);
  1136. AssertEquals(Msg+': Correct name',AName,String(TJSPrimaryExpressionIdent(Ident).Name));
  1137. end;
  1138. Class Function TTestConverter.CreateLiteral(AValue: String): TPasExpr;
  1139. begin
  1140. Result:=TPrimitiveExpr.Create(Nil,pekString,AValue);
  1141. end;
  1142. Class Function TTestConverter.CreateLiteral(AValue: Double): TPasExpr;
  1143. Var
  1144. S : String;
  1145. begin
  1146. Str(AValue,S);
  1147. Result:=TPrimitiveExpr.Create(Nil,pekNumber,Trim(S));
  1148. end;
  1149. Class Function TTestConverter.CreateIdent(AName: String): TPrimitiveExpr;
  1150. begin
  1151. Result:=TPrimitiveExpr.Create(Nil,pekIdent,AName);
  1152. end;
  1153. Class Function TTestConverter.CreateCondition : TPasExpr;
  1154. begin
  1155. Result:=CreateIdent('a');
  1156. end;
  1157. Class Function TTestConverter.CreateAssignStatement(LHS: String = 'a';RHS : String = 'b'): TPasImplAssign;
  1158. begin
  1159. Result:=TPasImplAssign.Create('',Nil);
  1160. Result.left:=CreateIdent(LHS);
  1161. Result.right:=CreateIdent(RHS);
  1162. end;
  1163. Class Function TTestConverter.CreateFunctionCall(AName: String;
  1164. Params: Array of String): TParamsExpr;
  1165. Var
  1166. I : Integer;
  1167. begin
  1168. Result:=TParamsExpr.Create(Nil,pekFuncParams,eopNone);
  1169. Result.Value:=CreateIdent(AName);
  1170. For I:=Low(Params) to High(Params) do
  1171. Result.AddParam(TPasExpr(CreateIdent(Params[I])));
  1172. end;
  1173. Class Procedure TTestConverter.AssertAssignStatement(Const Msg : String; El : TJSElement;LHS: String = 'a';RHS : String = 'b');
  1174. begin
  1175. AssertNotNull(Msg+': have statement',EL);
  1176. If not (El is TJSSimpleAssignStatement) then
  1177. Fail(Msg+': statement is not assign statement but is '+El.ClassName);
  1178. AssertIdentifier(Msg+': left hand side ('+LHS+')',TJSAssignStatement(EL).LHS,LHS);
  1179. AssertIdentifier(Msg+': left hand side ('+LHS+')',TJSAssignStatement(EL).Expr,RHS);
  1180. end;
  1181. Class Procedure TTestConverter.AssertEmptyBlockStatement(Const Msg: String;
  1182. El: TJSElement);
  1183. begin
  1184. AssertNotNull(Msg+': have statement',EL);
  1185. If not (El is TJSEmptyBlockStatement) then
  1186. Fail(Msg+': statement is not empty block statement but is'+El.ClassName);
  1187. end;
  1188. class Function TTestConverter.AssertListStatement(Const Msg: String;
  1189. El: TJSElement): TJSStatementList;
  1190. begin
  1191. AssertNotNull(Msg+': have statement',EL);
  1192. If not (El is TJSStatementList) then
  1193. Fail(Msg+': statement is not a list statement but is'+El.ClassName);
  1194. Result:=TJSStatementList(El);
  1195. end;
  1196. class Function TTestConverter.AssertElement(Const Msg: String;
  1197. AClass: TJSElementClass; El: TJSElement): TJSElement;
  1198. begin
  1199. AssertNotNull(Msg+': have element',El);
  1200. if not (El is ACLass) then
  1201. Fail(Msg+': is not of class '+AClass.ClassName+' but is '+EL.ClassName);
  1202. Result:=El;
  1203. end;
  1204. Initialization
  1205. RegisterTests([TTestTestConverter,TTestExpressionConverter,TTestStatementConverter]);
  1206. end.