#!/usr/bin/env node if (process.argv.length < 4) { console.error("Usage: toSwift SRC DST"); process.exit(1); } var fs = require("fs"); let fileSrc = process.argv[2]; let fileDst = process.argv[3]; let globalReplacements = { "function": "func", "number": "Float", "Number": "Float", "):": ") ->", "interface": "protocol", "})": "}", // forEach ".push(": ".append(", // array }; console.log(`Converting '${fileSrc}' to '${fileDst}'`); var linesDst = []; let linesSrc = fs.readFileSync(fileSrc).toString().split(/\r?\n/); for (let i in linesSrc) { let ln = linesSrc[i]; linesDst.push(convert(ln)); } let contentsDst = linesDst.join("\r\n"); fs.writeFileSync(fileDst, contentsDst); // Functions making decisions. function convert(line) { var result = line; for (let src in globalReplacements) { let dst = globalReplacements[src]; result = result.replaceAll(src, dst); } result = protocolReplace(result); result = typeArrayReplace(result); result = forEachReplace(result); result = recordReplace(result); return result; } // x.forEach(y => { -> x.forEach { y in function forEachReplace(line) { if (!line.includes("forEach")) { return line; } let partsFE = line.split("forEach"); let identifier = partsFE[0]; let closure = partsFE[1]; let partsC = closure.split(" => "); let bracketAndVar = partsC[0]; let bracket = partsC[1]; let variable = bracketAndVar.substring(1); let result = `${identifier}forEach { ${variable} in`; return result; } var isProtocol = false; // interface -> protocol function protocolReplace(line) { if (line.includes("protocol")) { isProtocol = true; } if (line == "}") { isProtocol = false; } if (!isProtocol) { return line; } var result = line; if (isProtocol) { result = protocolReplaceVariable(result); } return result; } // a: Number -> var a: Float { get } function protocolReplaceVariable(line) { let parts = line.split(": "); if (parts.length == 2) { let type = parts[1]; let name = parts[0].trim(); let spaceLength = parts[0].length - name.length; let spaces = " ".repeat(spaceLength); return `${spaces}var ${name}: ${type} { get }`; } return line; } // Record -> [TypeA: TypeB] // Record = {} -> [TypeA: TypeB] = [:] function recordReplace(line) { if (!line.includes("Record")) { return line; } let partsR = line.split("Record<"); let typesAndEnding = partsR[1]; let partsT = typesAndEnding.split(">"); let types = partsT[0]; let ending = partsT[1]; let swiftTypes = types.split(", "); let was = `Record<${swiftTypes[0]}, ${swiftTypes[1]}>`; let now = `[${swiftTypes[0]}: ${swiftTypes[1]}]`; var result = line; result = result.replace(was, now); result = result.replace("] = {};", "] = [:]"); return result; } // Type[] -> [Type] function typeArrayReplace(line) { let parts = line.split(" "); for (var i in parts) { let part = parts[i]; if ( part != "[]" && part.endsWith("[]") ) { let type = part.substring(0, part.length - 2) let swiftType = `[${type}]`; return line.replace(part, swiftType); } } return line; }