Skip to content

Instantly share code, notes, and snippets.

@BenziAhamed
Created October 12, 2018 15:19
Show Gist options
  • Save BenziAhamed/16b4b4d2bf8aa7a309983e56c384831e to your computer and use it in GitHub Desktop.
Save BenziAhamed/16b4b4d2bf8aa7a309983e56c384831e to your computer and use it in GitHub Desktop.
import Cocoa
// what is a 'type'?
// it has a domain, a name
// it can have 'properties'
protocol TypeBuilder : class {
func setType(type: String)
func setTypeName(name: String)
func addProperty(type: String, label: String)
var codeRepresentation: String { get }
}
class DebuggingTypeBuilder : TypeBuilder {
func setType(type: String) {
print("type is \(type)")
}
func setTypeName(name: String) {
print("type name is \(name)")
}
func addProperty(type: String, label: String) {
print("property '\(label)' of \(type)")
}
var codeRepresentation: String {
return "code representation unsupported"
}
}
class BaseTypeBuilder : TypeBuilder {
var typeName: String = ""
var type: String = ""
var properties = [(type: String, label: String)]()
func setTypeName(name: String) {
typeName = name
}
func setType(type: String) {
self.type = type
}
func addProperty(type: String, label: String) {
properties.append((type, label))
}
open var codeRepresentation: String {
fatalError("This must be overriden with a concrete implementation")
}
}
class CobolTypeBuilder : BaseTypeBuilder {
static let typeMap = [
"Int" : "INTEGER",
"String" : "STRING",
]
override var codeRepresentation: String {
let properties = self.properties.map {
let type = CobolTypeBuilder.typeMap[$0.type, default: "UNKNOWN"]
return " VARIABLE \($0.label.uppercased()) OF \(type)"
}.joined(separator: "\n")
return """
BEGIN RECORD \(typeName.uppercased())
\(properties)
END TYPE
"""
}
}
class PythonTypeBuilder : BaseTypeBuilder {
override var codeRepresentation: String {
let initList = properties.map {
"\($0.label)"
}.joined(separator: ", ")
let assignList = properties.map {
" self.\($0.label) = \($0.label)"
}.joined(separator: "\n ")
return """
class \(typeName):
def __init(\(initList)):
\(assignList)
"""
}
}
class KotlinTypeBuilder : BaseTypeBuilder {
override var codeRepresentation: String {
let properties = self.properties.map {
"val \($0.label): \($0.type)"
}.joined(separator: ", ")
return "data class \(typeName)(\(properties))"
}
}
class JavaTypeBuilder : BaseTypeBuilder {
override var codeRepresentation: String {
let properties = self.properties.map {
" public \($0.type) \($0.label);"
}.joined(separator: "\n")
return """
class \(typeName) {
\(properties)
}
"""
}
}
struct TypeEncoder {
func encode<T>(value: T, using builder: TypeBuilder) {
let mirror = Mirror(reflecting: value)
var typeInfo = "<untyped>"
mirror.displayStyle.flatMap { typeInfo = "\($0)" }
builder.setType(type: typeInfo)
let typeName = type(of: value)
builder.setTypeName(name: "\(typeName)")
mirror.children.forEach {
let childType = type(of: $0.value)
builder.addProperty(type: "\(childType)", label: $0.label ?? "<unlabeled>")
}
}
}
struct Point {
let x: Int
let y: Int
}
extension Point {
static let zero = Point.init(x: 0, y: 0)
}
let builders: [TypeBuilder] = [
DebuggingTypeBuilder(),
CobolTypeBuilder(),
KotlinTypeBuilder(),
JavaTypeBuilder(),
PythonTypeBuilder(),
]
builders.forEach {
print("\(type(of: $0))")
TypeEncoder().encode(value: Point.zero, using: $0)
print("\($0.codeRepresentation)")
print()
}
@BenziAhamed
Copy link
Author

DebuggingTypeBuilder
type is struct
type name is Point
property 'x' of Int
property 'y' of Int
code representation unsupported

CobolTypeBuilder
BEGIN RECORD POINT
    VARIABLE X OF INTEGER
    VARIABLE Y OF INTEGER
END TYPE

KotlinTypeBuilder
data class Point(val x: Int, val y: Int)

JavaTypeBuilder
class Point {
    public Int x;
    public Int y;
}

PythonTypeBuilder
class Point:
    def __init(x, y):
        self.x = x
        self.y = y

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment