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
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
A new version of Morpho is available for anyone to play with.
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]
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
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
I would appreciate anyone who downloads this and throws various routines at itā¦
Let me know what breaks, or seems to translate incorrectlyā¦
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
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 ) - 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ā