B4J Library [ABMaterial 2.0] B4JS progress update (2016/09/15)

alwaysbusy

Expert
Licensed User
This post is no longer valid! B4JS has been rewritten from the ground up and will first introduced in In ABM 4.25. Stay tuned...
------------------------------------------------------------------------------
Old post:

As my proof-of-concept in converting B4J code to Javascript worked, I've decided to start over and build B4JS from the ground up. Just as B4A 1.0 could not do everything, so won't B4JS 1.0 in the beginning. But I plan to support Classes, Modules etc too in the future.

I've started with the conversion of the B4J core. This is an overview of what can be used (and what not). Most of the 'Nots' are specific methods needed for B4J and which do not exist in JavaScript. But I'm happy with it can do already. Some methods were real brain-teasers, because Java and Javascript are two completely different languages.

Next up is implementing this for the first ABMComponent. It will be ABMXPlay as it will benefit the most from B4JS and it will be a good learning experience to see how to implement if for the other ABMaterial components.

B4JS 1.0

Write familiar B4J code and it will be converted to Javascript.

B4J Core
  • Variable Types
    • Supported:
      Array, Byte, Boolean, Double, Float, Int, List, Map, String
    • Not Supported:
      Other B4J Types, Classes, Modules, Object
      Variables declared in Global without the prefix B4JS
    Bit
    • Supported:
      And, Not, Or, ParseInt, ShiftLeft, ShiftRight, ToBinaryString, toHexString, ToOcatalString, UnsignedShiftRight, Xor
    • Not Supported:
      InputStreamToBytes
    String
    • Supported:
      CharAt, CompareTo, Contains, EndsWith, EqualsIngoreCase, GetBytes, IndexOf, indexOf2, LastIndexOf, LastIndexOf2, Length, Replace, StartsWidth, SubString, Substring2, ToLowerCase, ToUpperCase, Trim
    Map
    • Supported:
      Initialize, Clear, ContainsKey, Get, GetDefault, GetKeyAt, GetValueAt, IsInitialized, Remove, Size, Values, Keys, Put
    List
    • Supported:
      Initialize, Initialize2, Get, Add, AddAllAt, Clear, IndexOf, InsertAt, IsInitialized, RemoveAt, Size, Set, Sort, SortCaseInsensitive
    • Not Supported:
      SortType, SortTypeCaseInsensitive
    Keywords
    • Supported:
      Abs, ACos, ACosD, Array, Asc, ASin, ASinD, ATan, ATan2, ATan2D, ATanD, BytesToString, Catch, cE, Ceil, Chr, Continue, Cos, CosD, cPI, Dim, Exit, False, Floor, Is, IsNumber, LastException, Log, Logarithm, LogDebug, Max, Min, Not, Null, Power, Return, Rnd, RndSeed, Round, Round2, Sin, SinD, Sqrt, Sub, Tan, TanD
    • Not Supported:
      Typical B4J methods, not applicable in Javascript like: CallSub, CreateMap, CRLF, Density, ExitApplication, File, GetenvironmentVariable, GetSystemProperty, IsDevTool, Me, NumberFormat, RegEx, StartMessageLoop, ...
    Operators
    • Supported:
      =, <>, <, >, <=, >=, And, Or, (, ), + , -, /, Mod
    Control Structures
    • Supported:
      If, Then, Else, End If, For, For Each, Next, Select, Case, Case Else, End Select, Do While, Do Until, Loop, Try, Catch, End Try

Bookmark this topic if you want to keep up to date with my progress. Is on hold as the poll wanted the Abstract Designer first. But still planned to be build in!

Alwaysbusy
 
Last edited:

alwaysbusy

Expert
Licensed User
An example of some core functions:

B4J:

B4X:
Sub B4JSCoreFunctions
   Log("------- Start B4JSCoreFunctions")
   Log("(True And False): false <=> " & (True And False)) 
   Log("(True Or False): true <=> " & (True Or False)) 
   Log("Rnd(0,10): Number between 0 and 10 <=> " & Rnd(0,10))
   Log("Abs(-2): 2 <=> " & Abs(-2))
   Log("Not(False): true <=> " & Not(False))
   Log("CosD(45):  0.70710678... <=> " & CosD(45))
   Log("Cos(0.5):  0.87758256... <=> " & Cos(0.5))
   Log("SinD(45):  0.70710678... <=> " & SinD(45))
   Log("Sin(0.5):  0.47942553... <=> " & Sin(0.5))
   Log("ACosD(-1):  180... <=> " & ACosD(-1))
   Log("ACos(0.5):  1.04719755... <=> " & ACos(0.5))
   Log("ASinD(-1):  -90... <=> " & ASinD(-1))
   Log("ASin(0.5):  0.52359877... <=> " & ASin(0.5))
   Log("TanD(45):  0.99999999... <=> " & TanD(45))
   Log("Tan(0.5):  0.54630248... <=> " & Tan(0.5))
   Log("ATanD(45):  88.7269699... <=> " & ATanD(45))
   Log("ATan(0.5):  0.46364760... <=> " & ATan(0.5))
   Log("ATan2D(90,45): 3.4349488... <=> " & ATan2D(90,45))
   Log("ATan2(8,4):  1.10714871... <=> " & ATan2(8,4))

   Log("try/Catch example, only visible in B4JS.")
   Try
     Dim i As Int = 1/0 'ignore
   Catch
     Log(LastException.Message)
   End Try

   Log("Chr(65): A <=> " & Chr(65))
   Log("Asc(""A""): 65 <=> " & Asc("A"))
   Log("cE: 2.71828182... <=> " & cE)
   Log("Ceil(1.65): 2 <=> " & Ceil(1.65))
   Log("cPI: 3.14159265... <=> " & cPI)
   Log("Floor(1.65): 1 <=> " & Floor(1.65))
   Log("IsNumber(""alain""): false <=> " & IsNumber("alain"))
   Log("IsNumber(""15.2""): true <=> " & IsNumber("15.2"))
   Log("Logarithm(10, 1000): 0.33333333.... <=> " & Logarithm(10, 1000))
   Log("Max(10,5): 10 <=> " & Max(10,5))
   Log("Min(10,5): 5 <=> " & Min(10,5))
   Log("Power(2,3): 8 <=> " & Power(2,3))
   Log("Round(1.12345): 1 <=> " & Round(1.12345))
   Log("Round2(1.12345, 2): 1.12 <=> " & Round2(1.12345, 2))
   Log("Sqrt(9): 3 <=> " & Sqrt(9))

   Dim str1 As String = "Test €100 is £84.73"
   Dim theBytes() As Byte
   theBytes = str1.GetBytes("UTF8")
   Log("BytesToString(theBytes,0,theBytes.Length, ""UTF-8""): Test €100 is £84.73 <=> " & BytesToString(theBytes,0,theBytes.Length, "UTF-8"))

End Sub
Converted JavaScript:

B4X:
this.b4jscorefunctions=b4jscorefunctions=function(){
     try {
       console.log("------- Start B4JSCoreFunctions");
       console.log("(True And False): false <=> "+(true && false));
       console.log("(True Or False): true <=> "+(true || false));
       console.log("Rnd(0,10): Number between 0 and 10 <=> "+(Math.floor(Math.random() * (10 - 0) + 0)));
       console.log("Abs(-2): 2 <=> "+(Math.abs(-2)));
       console.log("Not(False): true <=> "+!(false));
       console.log("CosD(45):  0.70710678... <=> "+(Math.cos((45)/(180/Math.PI))));
       console.log("Cos(0.5):  0.87758256... <=> "+(Math.cos(0.5)));
       console.log("SinD(45):  0.70710678... <=> "+(Math.sin((45)/(180/Math.PI))));
       console.log("Sin(0.5):  0.47942553... <=> "+(Math.sin(0.5)));
       console.log("ACosD(-1):  180... <=> "+(Math.acos(-1)*(180/Math.PI)));
       console.log("ACos(0.5):  1.04719755... <=> "+(Math.acos(0.5)));
       console.log("ASinD(-1):  -90... <=> "+(Math.asin(-1)*(180/Math.PI)));
       console.log("ASin(0.5):  0.52359877... <=> "+(Math.asin(0.5)));
       console.log("TanD(45):  0.99999999... <=> "+(Math.tan((45)/(180/Math.PI))));
       console.log("Tan(0.5):  0.54630248... <=> "+(Math.tan(0.5)));
       console.log("ATanD(45):  88.7269699... <=> "+(Math.atan(45)*(180/Math.PI)));
       console.log("ATan(0.5):  0.46364760... <=> "+(Math.atan(0.5)));
       console.log("ATan2D(90,45): 3.4349488... <=> "+(Math.atan2(90,45)*(180/Math.PI)));
       console.log("ATan2(8,4):  1.10714871... <=> "+(Math.atan2(8,4)));
       console.log("try/Catch example, only visible in B4JS.");
       try {
         var _i=1/0;
       } catch(err) {
         console.log(lastexception.message);
       }
       console.log("Chr(65): A <=> "+String.fromCharCode(65));
       console.log("Asc(\"A\"): 65 <=> "+"A".charCodeAt(0));
       console.log("cE: 2.71828182... <=> "+2.7182818284590452353602874713527);
       console.log("Ceil(1.65): 2 <=> "+(Math.ceil(1.65)));
       console.log("cPI: 3.14159265... <=> "+Math.PI);
       console.log("Floor(1.65): 1 <=> "+(Math.floor(1.65)));
       console.log("IsNumber(\"alain\"): false <=> "+(!isNaN(parseFloat("alain")) && isFinite("alain")));
       console.log("IsNumber(\"15.2\"): true <=> "+(!isNaN(parseFloat("15.2")) && isFinite("15.2")));
       console.log("Logarithm(10, 1000): 0.33333333.... <=> "+(Math.log(10)/Math.log(1000)));
       console.log("Max(10,5): 10 <=> "+Math.max(10,5));
       console.log("Min(10,5): 5 <=> "+Math.min(10,5));
       console.log("Power(2,3): 8 <=> "+Math.pow(2,3));
       console.log("Round(1.12345): 1 <=> "+Math.round(1.12345));
       console.log("Round2(1.12345, 2): 1.12 <=> "+(+(Math.round(1.12345+"e+"+2)+"e-"+2)));
       console.log("Sqrt(9): 3 <=> "+(Math.sqrt(9)));
       var _str1="Test €100 is £84.73";
       var _thebytes=[];
       _thebytes.length=0;
       _thebytes = _str1.getBytes();
       console.log("BytesToString(theBytes,0,theBytes.Length, \"UTF-8\"): Test €100 is £84.73 <=> "+bytesToString(_thebytes.slice(0,_thebytes.length)));
     }
     catch(err) {
       console.log(err.message + ' ' + err.stack);
     }
   };
Or to show the complexity of some B4J functions (e.g. here for the GetBytes() method):

B4X:
String.prototype.getBytes = function() {
     var utf8 = [];
     var str = this;
     for (var i=0; i < str.length; i++) {
       var charcode = str.charCodeAt(i);
       if (charcode < 0x80) utf8.push(charcode);
       else if (charcode < 0x800) {
         utf8.push(0xffffffc0 | (charcode >> 6), 0xffffff80 | (charcode & 0x3f));
       } else if (charcode < 0xd800 || charcode >= 0xe000) {
         utf8.push(0xffffffe0 | (charcode >> 12), 0xffffff80 | ((charcode>>6) & 0x3f), 0xffffff80 | (charcode & 0x3f));
       } else {
         utf8.push(0xef, 0xbf, 0xbd);
       }
     }
     return utf8;
   };
 
Last edited:
Top