Browse Source

pastojs: Assert with EAssertFailed

git-svn-id: trunk@37992 -
Mattias Gaertner 7 years ago
parent
commit
e7f6808c9f

+ 69 - 12
packages/pastojs/src/fppas2js.pp

@@ -265,6 +265,9 @@ Works:
   - char, char range, set of char, set of char range
   - array
   - class
+- Assert(bool[,string])
+  - without sysutils: if(bool) throw string
+  - with sysutils: if(bool) throw pas.sysutils.EAssertionFailed.$create("Create",[string])
 
 ToDos:
 - remove hasOwnProperty from rtl set functions
@@ -3924,18 +3927,18 @@ var
   FunName: String;
 begin
   Result:=nil;
-  //writeln('TPasToJSConverter.CreateNewInstanceStatement Ref.Declaration=',GetObjName(Ref.Declaration));
+  //writeln('TPasToJSConverter.CreateFreeOrNewInstanceExpr Ref.Declaration=',GetObjName(Ref.Declaration));
   Proc:=Ref.Declaration as TPasProcedure;
   if Proc.Name='' then
     RaiseInconsistency(20170125191914);
-  //writeln('TPasToJSConverter.CreateNewInstanceStatement Proc.Name=',Proc.Name);
+  //writeln('TPasToJSConverter.CreateFreeOrNewInstanceExpr Proc.Name=',Proc.Name);
   ProcScope:=Proc.CustomData as TPasProcedureScope;
-  //writeln('TPasToJSConverter.CreateNewInstanceStatement ProcScope.Element=',GetObjName(ProcScope.Element),' ProcScope.ClassScope=',GetObjName(ProcScope.ClassScope),' ProcScope.DeclarationProc=',GetObjName(ProcScope.DeclarationProc),' ProcScope.ImplProc=',GetObjName(ProcScope.ImplProc),' ProcScope.CustomData=',GetObjName(ProcScope.CustomData));
+  //writeln('TPasToJSConverter.CreateFreeOrNewInstanceExpr ProcScope.Element=',GetObjName(ProcScope.Element),' ProcScope.ClassScope=',GetObjName(ProcScope.ClassScope),' ProcScope.DeclarationProc=',GetObjName(ProcScope.DeclarationProc),' ProcScope.ImplProc=',GetObjName(ProcScope.ImplProc),' ProcScope.CustomData=',GetObjName(ProcScope.CustomData));
   ClassScope:=ProcScope.ClassScope;
   aClass:=ClassScope.Element;
   if aClass.Name='' then
     RaiseInconsistency(20170125191923);
-  //writeln('TPasToJSConverter.CreateNewInstanceStatement aClass.Name=',aClass.Name);
+  //writeln('TPasToJSConverter.CreateFreeOrNewInstanceExpr aClass.Name=',aClass.Name);
   C:=CreateCallExpression(Ref.Element);
   ok:=false;
   try
@@ -7593,10 +7596,19 @@ var
   ProcScope: TPasProcedureScope;
   IfSt: TJSIfStatement;
   ThrowSt: TJSThrowStatement;
+  ModScope: TPasModuleScope;
+  aConstructor: TPasConstructor;
+  Ref: TResolvedReference;
+  ArrLit: TJSArrayLiteral;
+  Call: TJSCallExpression;
+  FunName: String;
+  PosEl: TPasExpr;
+  Enabled: Boolean;
 begin
   Result:=nil;
 
   // check if assertions are enabled
+  Enabled:=false;
   CtxEl:=El;
   while CtxEl<>nil do
     begin
@@ -7604,26 +7616,71 @@ begin
       begin
       ProcScope:=CtxEl.CustomData as TPasProcedureScope;
       if not (ppsfAssertions in ProcScope.Flags) then exit;
+      Enabled:=true;
+      break;
+      end
+    else if CtxEl is TPasModule then
+      begin
+      ModScope:=CtxEl.CustomData as TPasModuleScope;
+      if not (pmsfAssertions in ModScope.Flags) then exit;
+      Enabled:=true;
       break;
       end;
     CtxEl:=CtxEl.Parent;
     end;
+  if not Enabled then exit;
 
+  Ref:=nil;
   IfSt:=TJSIfStatement(CreateElement(TJSIfStatement,El));
   try
+    PosEl:=El.Params[0];
     IfSt.Cond:=ConvertExpression(El.Params[0],AContext);
-    ThrowSt:=TJSThrowStatement(CreateElement(TJSThrowStatement,El.Params[0]));
+    ThrowSt:=TJSThrowStatement(CreateElement(TJSThrowStatement,PosEl));
     IfSt.BTrue:=ThrowSt;
-    // ToDo: find sysutils.EAssertionFailed
-    if length(El.Params)>1 then
-      begin
-      ThrowSt.A:=ConvertExpression(El.Params[1],AContext);
-      end
-    else
-      ThrowSt.A:=CreateLiteralJSString(El.Params[0],'assert failed');
 
+    // using sysutils.EAssertionFailed if available
+    aConstructor:=nil;
+    if El.CustomData is TResolvedReference then
+      begin
+      Ref:=TResolvedReference(El.CustomData);
+      if Ref.Declaration is TPasConstructor then
+        aConstructor:=TPasConstructor(Ref.Declaration);
+      Ref:=nil;
+      end;
+    //writeln('TPasToJSConverter.ConvertBuiltIn_Assert ',GetObjName(aConstructor));
+    if aConstructor<>nil then
+      begin
+      Ref:=TResolvedReference.Create;
+      ModScope:=El.GetModule.CustomData as TPasModuleScope;
+      Ref.Declaration:=ModScope.AssertClass;
+      // pas.sysutils.EAssertionFailed
+      FunName:=CreateReferencePath(ModScope.AssertClass,AContext,rpkPathAndName,true,Ref);
+      // append .$create('Create')
+      FunName:=FunName+'.'+FBuiltInNames[pbifnClassInstanceNew];
+      Call:=CreateCallExpression(PosEl);
+      Call.Expr:=CreatePrimitiveDotExpr(FunName,PosEl);
+      // parameter: "Create"
+      Call.AddArg(CreateLiteralString(PosEl,TransformVariableName(aConstructor,AContext)));
+      ThrowSt.A:=Call;
+      if length(El.Params)>1 then
+        begin
+        // add [msg]
+        ArrLit:=TJSArrayLiteral(CreateElement(TJSArrayLiteral,El.Params[1]));
+        Call.AddArg(ArrLit);
+        ArrLit.AddElement(ConvertExpression(El.Params[1],AContext));
+        end;
+      end;
+    if ThrowSt.A=nil then
+      begin
+      // fallback: throw msg
+      if length(El.Params)>1 then
+        ThrowSt.A:=ConvertExpression(El.Params[1],AContext)
+      else
+        ThrowSt.A:=CreateLiteralJSString(El.Params[0],'assert failed');
+      end;
     Result:=IfSt;
   finally
+    Ref.Free;
     if Result=nil then
       IfSt.Free;
   end;

+ 17 - 9
packages/pastojs/src/pas2jscompiler.pp

@@ -89,6 +89,7 @@ type
     coShowUsedTools,
     coShowMessageNumbers, // not in "show all"
     coShowDebug,    // not in "show all"
+    coAssertions,
     coAllowCAssignments,
     coLowerCase,
     coEnumValuesAsNumbers,
@@ -119,6 +120,7 @@ const
     'Show used tools',
     'Show message numbers',
     'Show debug',
+    'Assertions',
     'Allow C assignments',
     'Lowercase identifiers',
     'Enum values as numbers',
@@ -708,14 +710,17 @@ begin
   Scanner.AllowedModeSwitches:=msAllPas2jsModeSwitches;
   Scanner.ReadOnlyModeSwitches:=msAllPas2jsModeSwitchesReadOnly;
   Scanner.CurrentModeSwitches:=p2jsMode_SwitchSets[Compiler.Mode];
-  bs:=msAllPas2jsBoolSwitches;
-  if not (coShowHints in Compiler.Options) then
-    Exclude(bs,bsHints);
-  if not (coShowNotes in Compiler.Options) then
-    Exclude(bs,bsNotes);
-  if not (coShowWarnings in Compiler.Options) then
-    Exclude(bs,bsWarnings);
-  Scanner.AllowedBoolSwitches:=bs;
+  Scanner.AllowedBoolSwitches:=msAllPas2jsBoolSwitches;
+  bs:=[];
+  if coAssertions in Compiler.Options then
+    Include(bs,bsAssertions);
+  if coShowHints in Compiler.Options then
+    Include(bs,bsHints);
+  if coShowNotes in Compiler.Options then
+    Include(bs,bsNotes);
+  if coShowWarnings in Compiler.Options then
+    Include(bs,bsWarnings);
+  Scanner.CurrentBoolSwitches:=bs;
   // Note: some Scanner.Options are set by TPasResolver
   for i:=0 to Compiler.Defines.Count-1 do
     begin
@@ -2592,9 +2597,10 @@ var
   Enabled, Disabled: string;
   i: Integer;
 begin
-  ReadSingleLetterOptions(Param,p,'c',Enabled,Disabled);
+  ReadSingleLetterOptions(Param,p,'a2cd',Enabled,Disabled);
   for i:=1 to length(Enabled) do begin
     case Enabled[i] of
+    'a': Options:=Options+[coAssertions];
     '2': Mode:=p2jmObjFPC;
     'c': Options:=Options+[coAllowCAssignments];
     'd': Mode:=p2jmDelphi;
@@ -2602,6 +2608,7 @@ begin
   end;
   for i:=1 to length(Disabled) do begin
     case Disabled[i] of
+    'a': Options:=Options-[coAssertions];
     '2': ;
     'c': Options:=Options-[coAllowCAssignments];
     'd': ;
@@ -3140,6 +3147,7 @@ begin
   l('    -Pecmascript5 : default');
   l('    -Pecmascript6');
   l('  -S<x>   : Syntax options. <x> is a combination of the following letters:');
+  l('    a     : Turn on assertions');
   l('    c     : Support operators like C (*=,+=,/= and -=)');
   l('    d     : Same as -Mdelphi');
   l('    2     : Same as -Mobjfpc (default)');

+ 0 - 3
packages/pastojs/src/pas2jsfilecache.pp

@@ -922,9 +922,6 @@ begin
     {$IFDEF VerbosePas2JSDirCache}
     writeln('TPas2jsCachedDirectories.GetDirectory "',Dir,'"');
     {$ENDIF}
-    {$IFDEF CaseInsensitiveFilenames}
-    Dir:=IncludeTrailingPathDelimiter(FindDiskFilename(ChompPathDelim(Dir)));
-    {$ENDIF}
     Result:=TPas2jsCachedDirectory.Create(Dir,Self);
     FDirectories.Add(Result);
     if DoReference then

+ 3 - 1
packages/pastojs/tests/tcmodules.pas

@@ -15889,6 +15889,7 @@ begin
   'begin',
   '  {$Assertions on}',
   '  Assert(b);',
+  '  Assert(b,''msg'');',
   'end;',
   'begin',
   '  DoIt;',
@@ -15899,7 +15900,8 @@ begin
     'this.DoIt = function () {',
     '  var b = false;',
     '  var s = "";',
-    '  if (b) throw "assert failed";',
+    '  if (b) throw pas.SysUtils.EAssertionFailed.$create("Create");',
+    '  if (b) throw pas.SysUtils.EAssertionFailed.$create("Create$1", ["msg"]);',
     '};',
     '']),
     LinesToStr([ // $mod.$main