Переглянути джерело

* Web compiler, initial demo

michael 6 роки тому
батько
коміт
4d3eef11e8

+ 82 - 0
demo/webcompiler/demowebcompiler.lpi

@@ -0,0 +1,82 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<CONFIG>
+  <ProjectOptions>
+    <Version Value="11"/>
+    <General>
+      <Flags>
+        <MainUnitHasCreateFormStatements Value="False"/>
+        <MainUnitHasTitleStatement Value="False"/>
+        <MainUnitHasScaledStatement Value="False"/>
+        <Runnable Value="False"/>
+      </Flags>
+      <SessionStorage Value="InProjectDir"/>
+      <MainUnit Value="0"/>
+      <Title Value="demowebcompiler"/>
+      <UseAppBundle Value="False"/>
+      <ResourceType Value="res"/>
+    </General>
+    <CustomData Count="1">
+      <Item0 Name="PasJSWebBrowserProject" Value="1"/>
+    </CustomData>
+    <BuildModes Count="1">
+      <Item1 Name="Default" Default="True"/>
+    </BuildModes>
+    <PublishOptions>
+      <Version Value="2"/>
+      <UseFileFilters Value="True"/>
+    </PublishOptions>
+    <RunParams>
+      <FormatVersion Value="2"/>
+      <Modes Count="0"/>
+    </RunParams>
+    <Units Count="1">
+      <Unit0>
+        <Filename Value="demowebcompiler.lpr"/>
+        <IsPartOfProject Value="True"/>
+      </Unit0>
+    </Units>
+  </ProjectOptions>
+  <CompilerOptions>
+    <Version Value="11"/>
+    <Target FileExt=".js">
+      <Filename Value="demowebcompiler"/>
+    </Target>
+    <SearchPaths>
+      <IncludeFiles Value="$(ProjOutDir);../../compiler/utils/pas2js;../../compiler/packages/pastojs/src"/>
+      <OtherUnitFiles Value="../../compiler/utils/pas2js;../../compiler/packages/pastojs/src;../../compiler/packages/fcl-passrc/src;../../compiler/packages/fcl-json/src;../../compiler/packages/fcl-js/src"/>
+      <UnitOutputDirectory Value="js"/>
+    </SearchPaths>
+    <Parsing>
+      <SyntaxOptions>
+        <AllowLabel Value="False"/>
+        <UseAnsiStrings Value="False"/>
+      </SyntaxOptions>
+    </Parsing>
+    <CodeGeneration>
+      <TargetOS Value="browser"/>
+    </CodeGeneration>
+    <Linking>
+      <Debugging>
+        <GenerateDebugInfo Value="False"/>
+        <UseLineInfoUnit Value="False"/>
+      </Debugging>
+    </Linking>
+    <Other>
+      <CustomOptions Value="-Jeutf-8 -Jirtl.js -Jc -Jminclude"/>
+      <CompilerPath Value="$(pas2js)"/>
+    </Other>
+  </CompilerOptions>
+  <Debugging>
+    <Exceptions Count="3">
+      <Item1>
+        <Name Value="EAbort"/>
+      </Item1>
+      <Item2>
+        <Name Value="ECodetoolError"/>
+      </Item2>
+      <Item3>
+        <Name Value="EFOpenError"/>
+      </Item3>
+    </Exceptions>
+  </Debugging>
+</CONFIG>

+ 233 - 0
demo/webcompiler/demowebcompiler.lpr

@@ -0,0 +1,233 @@
+program demowebcompiler;
+
+{$mode objfpc}
+
+uses
+  JS, Classes, SysUtils, Web, webfilecache, pas2jswebcompiler;
+
+Type
+
+  { TWebCompilerDemo }
+
+  TWebCompilerDemo = Class(TComponent)
+  Private
+    BCompile : TJSHTMLElement;
+    BDefaultUnits : TJSHTMLElement;
+    BThisUnit : TJSHTMLElement;
+    EUnitName : TJSHTMLInputElement;
+    BRun : TJSHTMLElement;
+    MSource : TJSHTMLInputElement;
+    MLog: TJSHTMLInputElement;
+    MUnits: TJSHTMLInputElement;
+    RFrame : TJSHTMLIFrameElement;
+    PResult : TJSHTMLElement;
+    FCompiler : TPas2JSWebCompiler;
+    procedure ActivateTab(aTab: String);
+    procedure ClearResult;
+    procedure DoLog(Sender: TObject; const Msg: String);
+    function LoadDefaultsClick(aEvent: TJSMouseEvent): boolean;
+    function LoadSingleUnitClick(aEvent: TJSMouseEvent): boolean;
+    procedure OnUnitLoaded(Sender: TObject; aFileName: String; aError: string);
+    function RunClick(aEvent: TJSMouseEvent): boolean;
+  Protected
+    function CompileClick(aEvent: TJSMouseEvent): boolean;
+    Procedure LinkElements;
+    Property Compiler : TPas2JSWebCompiler Read FCompiler;
+  Public
+    Constructor Create(aOwner : TComponent); override;
+    Procedure Execute;
+  end;
+
+Const
+  // Default run HTML page, shown in IFrame.
+
+  SHTMLHead =
+    '<HTML>'+LineEnding+
+    '<head>'+LineEnding+
+    '  <meta charset="UTF-8">'+LineEnding+
+    '  <Title>Pas2JS web compiler Program output</Title>'+LineEnding+
+    '  <script type="application/javascript">'+LineEnding;
+
+  SHTMLTail =
+    '   </script>'+LineEnding+
+    '  <link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">'+LineEnding+
+    '</head>'+LineEnding+
+    '<body>'+LineEnding+
+    '  <div class="container">'+LineEnding+
+    '    <div class="panel panel-info">'+LineEnding+
+    '      <div class="panel-heading">Run program output</div>'+LineEnding+
+    '      <div class="panel-body">'+
+    '        <div id="pasjsconsole" style="width: 640px; height: 200px;">'+LineEnding+
+    '      </div>'+LineEnding+
+    '    </div>'+LineEnding+
+    '  </div>'+LineEnding+
+    '</div>'+LineEnding+
+    '<script>'+LineEnding+
+    '  rtl.run();'+LineEnding+
+    '</script>'+LineEnding+
+    '</body>'+LineEnding+
+    '</HTML>';
+
+
+{ TWebCompilerDemo }
+
+procedure TWebCompilerDemo.OnUnitLoaded(Sender: TObject; aFileName: String; aError: string);
+begin
+  if aError='' then
+    MUnits.Value:=MUnits.Value+sLineBreak+'Loaded: '+aFileName
+  else
+    MUnits.Value:=MUnits.Value+sLineBreak+'Error Loading "'+aFileName+'": '+AError;
+  if SameText(afilename,EUnitName.Value) then
+    EUnitName.Value:='';
+end;
+
+procedure TWebCompilerDemo.LinkElements;
+begin
+  BCompile:=TJSHTMLElement(Document.getElementById('btn-compile'));
+  BCompile.onclick:=@CompileClick;
+  BRun:=TJSHTMLElement(Document.getElementById('btn-run'));
+  BRun.onClick:=@RunClick;
+  MSource:=TJSHTMLInputElement(Document.getElementById('memo-program-src'));
+  MLog:=TJSHTMLInputElement(Document.getElementById('memo-compiler-output'));
+  MUnits:=TJSHTMLInputElement(Document.getElementById('memo-loaded-units'));
+  RFrame:=TJSHTMLIFrameElement(Document.getElementById('runarea'));
+  BDefaultUnits:=TJSHTMLElement(Document.getElementById('btn-load-defaults'));
+  BDefaultUnits.Onclick:=@LoadDefaultsClick;
+  BThisUnit:=TJSHTMLElement(Document.getElementById('btn-load-unit'));
+  BThisUnit.Onclick:=@LoadSingleUnitClick;
+  EUnitName:=TJSHTMLInputElement(Document.getElementById('edt-load-unit-name'));
+  PResult:=TJSHTMLElement(Document.getElementById('compile-result'));
+end;
+
+constructor TWebCompilerDemo.Create(aOwner : TComponent);
+begin
+  Inherited;
+  FCompiler:=TPas2JSWebCompiler.Create;
+  FCompiler.Log.OnLog:=@DoLog;
+  FCompiler.WebFS.LoadBaseURL:='sources';
+end;
+
+function TWebCompilerDemo.RunClick(aEvent: TJSMouseEvent): boolean;
+
+Var
+  Src : String;
+
+begin
+  Src:=FCompiler.WebFS.GetFileContent('main.js');
+  if Src='' then
+    begin
+    Window.Alert('No source available');
+    exit;
+    end;
+  Src:=SHTMLHead+Src+LineEnding+SHTMLTail;
+  RFrame['srcdoc']:=Src;
+end;
+
+procedure TWebCompilerDemo.DoLog(Sender: TObject; const Msg: String);
+begin
+  MLog.Value:=MLog.Value+sLineBreak+Msg;
+end;
+
+function TWebCompilerDemo.LoadDefaultsClick(aEvent: TJSMouseEvent): boolean;
+begin
+  Result:=False;
+  FCompiler.WebFS.LoadFiles(['rtl.js','system.pas','sysutils.pas','types.pas','typinfo.pas','classes.pas','rtlconsts.pas','js.pas','web.pas','browserconsole.pas'],@OnUnitLoaded);
+end;
+
+function TWebCompilerDemo.LoadSingleUnitClick(aEvent: TJSMouseEvent): boolean;
+begin
+  Result:=False;
+  FCompiler.WebFS.LoadFile(EUnitName.Value,@OnUnitLoaded);
+end;
+
+
+Procedure TWebCompilerDemo.ActivateTab(aTab : String);
+
+begin
+  asm
+   $("#act-"+aTab).tab('show');
+  end;
+end;
+
+
+Procedure TWebCompilerDemo.ClearResult;
+
+begin
+  While PResult.firstElementChild<>Nil do
+    PResult.removeChild(PResult.firstElementChild);
+end;
+
+function TWebCompilerDemo.CompileClick(aEvent: TJSMouseEvent): boolean;
+
+  Procedure ShowResult(success : boolean);
+
+  Const
+    CloseLink = '<a href="#" class="close" data-dismiss="alert" aria-label="close">&times;</a>';
+
+  Var
+    E : TJSHTMLElement;
+
+  begin
+    ClearResult;
+    E:=TJSHTMLElement(document.createElement('div'));
+    if Success then
+      begin
+      E['class']:='alert alert-success alert-dismissible fade in';
+      E.innerHTML:=CloseLink+'<strong>Succes!</strong> program compiled succesfully. You can run the program now.';
+      end
+    else
+      begin
+        E['class']:='alert alert-danger alert-dismissible fade in';
+        E.innerHTML:=CloseLink+'<strong>Failure</strong> failed to compile program, please check error messages.';
+      end;
+    PResult.appendChild(E);
+  end;
+
+  Procedure ShowSuccess;
+  Var
+    E : TJSHTMLElement;
+
+  begin
+    E:=TJSHTMLElement(document.createElement('div'));
+    E['class']:='alert alert-success alert-dismissible fade in';
+    E.innerHTML:='<strong>Succes!</strong> program compiled succesfully';
+    PResult.appendChild(E);
+  end;
+
+Var
+  args : TStrings;
+  Res : Boolean;
+
+begin
+  Result:=False;
+  BRun['disabled']:='disabled';
+  ClearResult;
+  MLog.Value:='';
+  FCompiler.WebFS.SetFileContent('main.pp',MSource.value);
+  args:=TStringList.Create;
+  try
+    Args.Add('-Tbrowser');
+    Args.Add('-Jc');
+    Args.Add('-Jirtl.js');
+    Args.Add('main.pp');
+    ActivateTab('output');
+    RFrame.Src:='run.html';
+    FCompiler.Run('','',Args,True);
+    Res:=FCompiler.ExitCode=0;
+    ShowResult(Res);
+    if Res then
+      BRun.removeAttribute('disabled');
+  finally
+   Args.Free;
+  end;
+end;
+
+procedure TWebCompilerDemo.Execute;
+begin
+  LinkElements;
+end;
+
+begin
+  With TWebCompilerDemo.Create(Nil) do
+    Execute;
+end.

+ 20 - 0
demo/webcompiler/run.html

@@ -0,0 +1,20 @@
+<HTML>
+<head>
+  <meta charset="UTF-8"> 
+<Title>Pas2JS web compiler Program output</Title>
+<!--
+  <script SRC="webcompiler.js" type="application/javascript"></script>
+-->
+<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
+</head>
+<body>
+  <div class="container">
+    <div class="panel panel-info">
+      <div class="panel-heading">Run program output</div>
+      <div class="panel-body">Compile and run your program first.</div>
+      <div id="pasjsconsole" style="width: 640px; height: 200px;">
+    </div>
+  </div>
+</div>
+</body>
+</HTML>

+ 69 - 0
demo/webcompiler/webcompiler.html

@@ -0,0 +1,69 @@
+ 
+<HTML>
+  <head>
+  <meta charset="UTF-8"> 
+  <Title>Pas2JS web compiler demo</Title>
+  <script SRC="demowebcompiler.js" type="application/javascript"></script>
+  <!-- We use bootstrap for the GUI -->
+  <link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
+  <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
+  <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
+  </head>
+<body>
+<div class="container">
+  <div class="panel panel-default">
+    <div class="panel-heading">Enter your program here</div>
+    <div class="panel-body">
+      <ul class="nav nav-tabs">
+        <li class="active"><a data-toggle="tab" id="act-source" href="#source">Program Source</a></li>
+        <li><a data-toggle="tab" id="act-load" href="#load">Load units</a></li>
+        <li><a data-toggle="tab" id="act-output" href="#output">Compiler output</a></li>
+      
+      </ul>
+      <div class="tab-content">
+        <div id="source" class="tab-pane fade in active">
+          <textarea id="memo-program-src" rows="15" cols="80">
+          program main;
+          
+          uses browserconsole;  // For output in correct console panel...
+
+          begin
+            // Your code here
+            Writeln('Hello, world!');
+          end.
+          </textarea>
+        </div>
+        <div id="load" class="tab-pane fade">
+          <div class="panel panel-default">
+            <div class="panel-body">
+              <textarea id="memo-loaded-units" rows="15~5" cols="80">
+              </textarea>
+            </div>
+              <form class="form-inline">
+                <div class="form-group">
+                <button id="btn-load-defaults" class="btn btn-defaults">Load default units</button> 
+                <button id="btn-load-unit" class="btn btn-defaults">Load this unit:</button>
+                <input type="text" class="form-control" id="edt-load-unit-name">
+                </div>
+              </form>
+          </div>    
+        </div>
+        <div id="output" class="tab-pane fade">
+          <textarea id="memo-compiler-output" rows="15" cols="80">
+          </textarea>
+          <div id="compile-result"></div>
+        </div>  
+      </div>
+    </div>
+    <div class="panel-footer">
+    <button id="btn-compile" class="btn btn-primary">Compile</button> 
+    <button id="btn-run" class="btn btn-success" disabled="disabled">Run</button>
+    </div>
+  </div>
+  <iframe id="runarea" src="run.html" height=320 width=800></iframe>
+</div> <!-- container -->  
+<script>
+  rtl.run();
+</script>
+</body>
+</HTML>