šŸ¦‹ "BASIC" to Swift

25Mar2021 - Added support for Dictionary (not exactly as Xojo does, but close)

Also it now checks that Xcode, Xcode Command Line Tools and Swift are all 3 installed

Thanks Dave - love your work and inspired me to actually get some Swift under my belt.

Here are a few things I added you might find useful.

extension Dictionary where Key == String, Value == String {
    func haskey(stringValue: String) -> Bool {
        return self[stringValue] != nil
    }
    
    func lookup(_ stringValue: String, _ defaultValue: String="") -> String {
        if let result = self[stringValue] {
            return result
        }
        return defaultValue
    }
}

extension Dictionary where Key == Int, Value == String {
    func haskey(intValue: Int) -> Bool {
        return self[intValue] != nil
    }

    func lookup(_ intValue: Int, _ defaultValue: String="") -> String {
        if let result = self[intValue] {
            return result
        }
        return defaultValue
    }
}

/// xBasic format implementation for Swift
/// Returns as a string a formatted version of the number passed based on the parameters specified.
/// The Format function is similar to the way spreadsheet applications format numbers.
/// Escaped characters are not permitted in formatSpec, so instead of "000\-000\-000" use "000-000-000"
public func format(_ number: Int, _ formatSpec: String) -> String {
    return format(Double(number), formatSpec)
}

public func format(_ number: Double, _ formatSpec: String) -> String {
    let f = NumberFormatter()
    f.allowsFloats = true
    
    // we need to parse (roughly) the formatSpec, because xbasic formats are no tthe same as NumberFormatter
    // refer: Unicode Technical Standard #35
    var i: Int = 0
    var parsedSpec: String = ""
    var literals = [Int:String]()
    
    for c in formatSpec {
        i = i + 1
        
        switch c {
        case "-":
            if i == 1 {
                if number < 0 {
                    parsedSpec = String(c)
                }
            } else {
                // add to literals
                literals[i - literals.count] = String(c)
            }
            
        case " ", "(", ")", "[", "]", "{", "}" :
            literals[i - literals.count] = String(c)
            
        default:
            parsedSpec = parsedSpec + String(c)
        }
    }
    
    f.format = parsedSpec
    let formattedResult = f.string(for: number) ?? ""

    // insert any literals that we caught
    var result: String = ""
    
    i = 0
    
    for c in formattedResult {
        i = i + 1
        
        if literals.haskey(intValue: i) {
            result = result + literals[i]!
        }
        
        result = result + String(c)
    }
    
    return result
}

func EncodeHex(_ v: String, _ InsertSpaces: Bool = false) -> String {
    var s: String = ""
    
    for c in v {
        if InsertSpaces {
            s = s + " " + String(format: "%02X", Asc(String(c))).Trim()
        } else {
            s = s + String(format: "%02X", Asc(String(c)))
        }
    }
    
    return s
}

Date extension:

extension Date {
    
    func startOfMonth() -> Date {
        let interval = Calendar.current.dateInterval(of: .month, for: self)
        return (interval?.start.toLocalTime())! // Without toLocalTime it give last months last date
    }
    
    func endOfMonth() -> Date {
        let interval = Calendar.current.dateInterval(of: .month, for: self)
        return interval!.end
    }
    
    // Convert UTC (or GMT) to local time
    func toLocalTime() -> Date {
        let timezone    = TimeZone.current
        let seconds     = TimeInterval(timezone.secondsFromGMT(for: self))
        return Date(timeInterval: seconds, since: self)
    }
}

Some additions to your Strings extensions:

 // --- Matt's extensions ---

    /// pad string at left end with padding characters to required length
    /// will truncate string, keeping right-most characters if result is longer than required length
    /// padding character can be a string of any length
    public func padl(_ requiredLength: Int, _ paddingCharacter: String=" ") -> String {
        var result: String = ""
        let j = requiredLength - self.Len()
        
        for _ in 1...j {
            result = result + paddingCharacter
        }
        
        result = result + self
        return result.Right(requiredLength)
    }

    /// pad string at right end with padding characters to required length
    /// will truncate string, keeping left-most characters if result is longer than required length
    /// padding character can be a string of any length
    public func padr(_ requiredLength: Int, _ paddingCharacter: String=" ") -> String {
        return self.padding(toLength: requiredLength, withPad: paddingCharacter, startingAt: 0).Left(requiredLength)
    }

Hope theyā€™re useful :slight_smile:

A new version of Morpho is available for anyone to play with.

  • Now supports Xojo like ā€œExtendsā€ feature
  • Should fully support BYREF in Sub/Function signatures
  • Supports Dictionary (with a few minor yet to be fixed caveats)
  • Has Linenumbering (and a not quite perfect highlighter)

Note : it is still not 100% perfect (not sure it can be)ā€¦ but last week when I started cleaning this up, my test suite (5600 lines of Xojo cut out of an existing project), generated 900+ translator errors.
This version only 89 error and only about 1/2 are translation errorsā€¦

function foo(extends s as String, bar as String) as string
   return s=bar
end function
sub test
   dim s as string
   print(s.foo("fred"))
end sub

becomes

extension String {
   func foo(_ bar : String) -> String {
      return(self = bar)
   }
} // end Extension
func test() {
   let s : String = "" 
   print(s.foo("fred"))
}

www.rdsisemore.com/Morpho.app.zip

[macOS 64bit]

2 Likes

ByRef Example

sub foo(test as string,byref stuff as integer,byref fred as string)
   // do stuff
end sub

sub test
   dim a as integer
   dim b as string
   foo("barney",a,b)
end sub 

becomes

import Cocoa
func foo(_ test : String , _ stuff : inout Int , _ fred : inout String) {
    // do stuff
}
func test() {
   var a : Int = 0
   var b : String = ""
   foo ( "barney" , &a , &b )
}

A couple of notes about this translator

First off a variable used in a FOR/NEXT loop is IMMUTABLEā€¦ meaning you cannot alter its value within the loopā€¦ contrary to what Xojo does for example.

Use of variables is very STRICTLY typed. this is to stay in line with the underlying Swift datatype rules. The translator can ā€œsometimesā€ infer and add type casting codeā€¦ but not always

A new version was just uploaded
www.rdsisemore.com/Morpho.app.zip

This should handle most cases of strings with embedded \ and multiple double quotesā€¦
EXCEPT for one ā€¦ strings that contain ā€œā€" (3 dbl quotes) translates properly, but Swift chokesā€¦ this is a Swift error (supposedly fixed for Swift 5.5)

It also fixes a few other errors that made them selfs visible while translating my test suite.

Still not 100% but moving closer each day :slight_smile:

2 Likes

Another new version was just uploaded
www.rdsisemore.com/Morpho.app.zip

This version adds support for an Xojo-like ā€œASSIGNSā€ feature

private Sub myRoutine(var1 as String, var2 as String, assigns Xyz as integer)
var x as integer =3
print(x)
End Sub

translates to

private var myRoutine = _myRoutine()
private struct _myRoutine {
   subscript (_  var1 : String ,_  var2 : String) -> Int? {
      get { return nil }
      set { let Xyz = newValue!
      let x : Int = 3 
      print(x)
   } 
} 
}

Still not 100% but moving closer each day :slight_smile:

I would appreciate anyone who downloads this and throws various routines at itā€¦
Let me know what breaks, or seems to translate incorrectlyā€¦

2 Likes

VERY VERY interested in your Xojo to Swift translator. We need to chat more. dev@koingosw.com

welcome to our corner of the Xojo / x-platform world

Hi Dave,

do you have a more recent version ?

by curiosity, I checked that one (downloaded on October 13, from April 14).

Click in the menu bar and right click in the swift pane crash.

Also, the 144 lines (with comments) returns a ton of errors (40), but probably all because of the interface (a lack of interface): the code takes data from the window (PopupMenu, TextFields) and write into a TextArea (and HTTPSecureSocket, FolderItem and TextOutputStream).

I do not checked all lines to be sure even if using a pink backdrop to flag the lines with error isā€¦ wow.

Do you have a more recent version for testings ?

That is the most recent version.
It DOES not translate GUI informaiton (windows, controls etc)
It ONLY DOES methods and functions, and then not even 100%

Thank you.

For those of you interested in this subject.
I have put ā€œMorphoā€ as an app on hold. In the meantime I am working on a program that will take an XML project from a certain familiar BASIC environment, and translate it into a complete Xcode/Swift project.

I doubt it will ever be 100% XML->Swift, it will most probably still require some minor manual editing of the Xcode that is generated.

The code Methods/Modules/Sub/Function etcā€¦ will be a hybrid of BASIC and SWIFT. So it will contain a ā€œmini-morphoā€ translation module to handle things like control structures (FOR/NEXT etc), SELECT/CASE as well as the signatures for Functions.

So far I have successfully translated a single window project where the window had at least one instance of every current control and all the control events called out. Current phase of work is to add the Window Methods (not related to events), Modules and Classes.

It seems the code that is generated from this test compiles to a 4.9 meg project, where compiling the XML using its original environment is over 17meg.

Nice.

Can you share both projects (Xojo and XCode), ready to generate the application, so people can see by themselves how easy it is ?

A single window project that read (and display) / write (to disk) text (and image) file(s)ā€¦

It is still a work in progress for starters
It is not designed to be a ā€œFREEā€ tool, Iā€™ve spent literally 10 years working to get to this point, but I might offer a Trial version that creates apps that run for a limited time (like Xojo used to do)

As far as how easyā€¦ just drag an XML project to this app, and wait a minute.

As I mentioned above, even then the Xcode/Swift that is generated may need some manual tweaking, for things the transpiler just didnā€™t know quite how to handle.

And for an app that would read, display, write text and imagesā€¦ this is a toolkit, it has TextInputStream, TextoutputStream, Picture.Open and Picture.Save as well as 1000ā€™s of other features

1 Like

Hi Dave,

I notice your website and link to Morpho is now dead. Is this still a going project?

Iā€™m interested, as - after an extremely long hiatus from coding - Iā€™m about to begin learning Swift having used Xcode for a long time now - but with C++.

As I have quite a lot of code in old XOJO apps and projects I could use in this new Swift stuff a XOJO to Swift converte would be handy.

The other thing have to mention ( some here like Norman, probably remember the odd posts Iā€™d do on the XOJO forum about it ) is that I too - spent - sadly - far too many years of my like writing a XOJO to C++ converter tool - and later on - the beginning of the reverse - a C++ to XOJO tool - something I should NEVER attempted! - a classic example of the gambler fallacy!.

Interestingly - whereas I note you donā€™t ( wisely! ) handle conversion to the equivalent GUI controls in Swift - I DID! - how? ( since you didnā€™t ask :wink: ) - by using a cross-platform framwework called JUCE - used widely by C++ audio developers. I did this by writing a ā€œshimā€ wrapper library that emulated the XOJO API but implemented everything using JUCE C++ code.

Something I needed a the time - simply because Iā€™d opted for a project began long long ago - to prototype in REALBASIC - THEN XOJO - with the express plan of eventually moving to C++ for the final builds. All this was necessary because the final app needed audio real time performance and needed parts to be written as AU/VST plugins ā€¦ and as we all know - one cannot write dynamic libraries - in XOJO. I pestered XOJO and Geoff of course - but to no avail.

By the way - the XOJO to C++ converter did its job - and all my prototype code got converted into C++ and JUCE. I tried for a while continuing to work in XOJO ( cos I loved it and the IDE ) while periodically doing exports via the conversion tool ( Called SQUIRT ) and doing test builds in Xcodeā€¦ but eventually this just became tedious and I decided to just move to coding in C++.

No fun of course! But Iā€™ve been following Swift a little - and now seems to make sense to explore that and the Apple ecosystem thingā€¦

( does anyone make cross-platform tools for Swift similar to how there are some for C# and windows? )

I still have the code for Morpho around some place, but it isnā€™t an on going project for a few reasons. One it only supported Xojo XML projects from 2019r1.1 (API1), and it was only about 80% accurate at best, not to mention it was Swift 4.

As to the conversion of GUI controls, no Morpho didnā€™t do that, but I have one that DOES (for iOS) and the beginnings of one that did ioS and macOS, as a matter of fact I use the iOS version to build the basic structure of new projects.

hmmm - all my projects are - A shelved - B using API 1 so maybe your stuff would work for me.

Now only thing I need to consider is - do I go through the hassle of updating the relevant Xojo projects to latest api etc and fixing deprecations -

ā€¦ or do I bite bullet and just export everything to swift and learn that?

was thinking best to just continue with what I know - but given all the bad feeling etc here regarding API 2 ( which ive never had to use - as yet ) and present state of XOJOā€¦ should I just go right over to Swift - specially given the projects I have in mind are entirely Apple - and any android port could be - if market for it - something to tackle years down the lineā€¦?

After a long hiatus should I now stay away from XOJO ?

second hmmm - are you saying you have another app that will convert from XOJO GUI layouts ( API1 ) to iOS and MacOX ( only )

and that you use the XOJO layout editor to sketch out the GUI and behaviour before porting snd switching to entirely Swift?

interesting - because my current ā€œresearchā€ seemed to indicate that there wasnā€™t anything drag and drop-ish in Xcode similar to what Xojo and other ā€œold school?ā€ layout editors in other IDEs - Visual Studio etcā€¦ used to do?

myself (and many others) no longer have any desire to continue with and/or support Xojo.

At the moment (as an extension of my previous Morpho project) I am writing a Swift app that takes an Xojo XML (and optionally Binary) project file and does a translation to Swift.

It has some limitations at the momentā€™

  • Does MOST of the GUI controls and their events with not much issue (Listbox not at the moment)
  • Does only a translation of ā€œsomeā€ code ā€¦ the rest needs to be handled after the fact
  • currently only supports the syntax as of 2019r1.1 (this can be rectified,if required):slight_smile:
  • requires (included) an extensive custom framework for all the controls, and other functions such as strings, textfiles and SQLite
1 Like