tcconverter.pas 48 KB

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