Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Bridging the Language Gap

Bridging the Language Gap

Given at Craft Conference 2017 in Budapest

Samuel E. Giddins

April 28, 2017
Tweet

More Decks by Samuel E. Giddins

Other Decks in Technology

Transcript

  1. BRIDGING THE LANGUAGE GAP
    SAMUEL GIDDINS

    View full-size slide

  2. SAMUEL GIDDINS
    > Bundler
    > CocoaPods
    > RubyGems
    > Realm
    > Trill

    View full-size slide

  3. I work on lots of
    random projects
    across many communities.

    View full-size slide

  4. I write developer tools that occasionally work.
    Otherwise, I'm in a library at UChicago,
    studying something impractical.

    View full-size slide

  5. THE LANGUAGE GAP
    Hi, me llamo ש
    ָׁ
    ל
    וֹ
    ם .

    View full-size slide

  6. THE LANGUAGE GAP
    Gap
    a break in continuity
    Bridge
    something that is intended to reconcile or form a
    connection between two things

    View full-size slide

  7. THE LANGUAGE GAP
    > When we want to connect two or more languages to
    each other.
    > When we make languages talk to each other.

    View full-size slide

  8. Some languages can be translated perfectly:
    > Curry–Howard correspondence
    > Relationship between propositions & proofs
    and values & types
    > Turing machines
    > Turing completeness
    > !

    View full-size slide

  9. But for most, something is lost in translation

    View full-size slide

  10. WHY BOTHER?
    Every language has strengths & weaknesses

    View full-size slide

  11. Every language has a library of knowledge
    that is useful to refer to

    View full-size slide

  12. Is this sounding familiar?

    View full-size slide

  13. LANGUAGES
    > Ruby
    > Objective-C
    > Swift
    > C++
    > ...

    View full-size slide

  14. WAYS TO TRANSLATE
    > Importer
    > FFI
    > XPC
    > Compiler Support
    > main()

    View full-size slide

  15. WAYS TO TRANSLATE
    Some are like Google Translate.
    They work on everything, but not very well.
    Some are like a paid translator.
    Amazing at going between exactly 2 languages,
    but very expensive.

    View full-size slide

  16. The Google Translate of Programming Language Translation

    View full-size slide

  17. $ echo I have earned those names.
    Bought and paid for them.
    I have earned those names. Bought
    and paid for them.

    View full-size slide

  18. The command line (or shell).
    Spawn a process, pass these arguments to main().

    View full-size slide

  19. > No context
    > No ongoing communication
    > Universal on any POSIX system

    View full-size slide

  20. HOW SHELL PROGRAMS WORK TOGETHER
    > 1 Program, 1 Process
    > Program Arguments
    > environ(7)
    > exit(3)
    > Side Effects

    View full-size slide

  21. A very general way of allowing programs in different
    languages to work together.
    But they don't work together very well.

    View full-size slide

  22. So, what's a step better than Google Translate?

    View full-size slide

  23. The Stack Overflow of Programming Language Translation

    View full-size slide

  24. > Run into a problem
    > Google it
    > Click on the first SO link
    > Copy-paste the solution
    that's already written

    View full-size slide

  25. FFI
    THE STACK OVERFLOW OF PROGRAMMING LANGUAGE TRANSLATION

    View full-size slide

  26. FOREIGN FUNCTION INTERFACE
    Matches the ABI of the calling language
    with that of the language being called.

    View full-size slide

  27. ABI
    > How functions call each other
    > How data is laid out in memory
    > How memory is managed across function calls

    View full-size slide

  28. A "simple" example

    View full-size slide

  29. swift.swift
    func fib(_ x: Int) -> Int {
    guard x >= 1 else {
    fatalError("fib of a non-positive number is undefined, use Γ instead")
    }
    if x == 1 || x == 2 { return 1 }
    return fib(x - 1) + fib(x - 2)
    }
    c.c
    #include
    int _TF5swift3fibFSiSi(int);
    int main(int argc, char *argv[]) {
    for (int i = 1; i < 15; ++i) {
    printf("fib(%d) = %d\n", i, _TF5swift3fibFSiSi(i));
    }
    }

    View full-size slide

  30. Arcane Commands
    > clang c.c -c
    > swiftc swift.swift -c -parse-as-library
    > ld swift.o c.o ... -o main
    > ./main

    View full-size slide

  31. It works!
    fib(1) = 1
    fib(2) = 1
    fib(3) = 2
    fib(4) = 3
    fib(5) = 5
    fib(6) = 8
    fib(7) = 13
    fib(8) = 21
    fib(9) = 34
    fib(10) = 55
    fib(11) = 89
    fib(12) = 144
    fib(13) = 233
    fib(14) = 377

    View full-size slide

  32. FFI is brittle

    View full-size slide

  33. We relied on us knowing how the Swift program worked
    under the hood in order to call it from C.

    View full-size slide

  34. Now imagine writing out those function prototypes for
    an
    entire library.
    And remember, a single mistake means !.

    View full-size slide

  35. XPC
    THE ADULT APPROACH TO main()

    View full-size slide

  36. CROSS PROCESS COMMUNICATION

    View full-size slide

  37. > Some context
    > Ongoing communication
    > Incredibly system dependent

    View full-size slide

  38. XPC OPTIONS
    > Sockets
    > HTTP
    > Mach XPC

    View full-size slide

  39. They all work by sharing ❇ state ❇
    across processes.

    View full-size slide

  40. This is where the world of
    microservices
    fits in

    View full-size slide

  41. Standardized data formats like
    JSON, protobuf, GraphQL, etc
    make this much less painful

    View full-size slide

  42. But containerization is complicated,
    and introduces complexities
    beyond the language gap

    View full-size slide

  43. As you can imagine, I'm still not a huge fan.

    View full-size slide

  44. COMPILER ✨

    View full-size slide

  45. This is the good kind of magic,
    I promise.

    View full-size slide

  46. This is like seeing
    inside the matrix.
    It's being able to call
    the name of the wind
    when your app encounters danger.

    View full-size slide

  47. Teach one compiler how to understand the structure of
    multiple languages.

    View full-size slide

  48. Think C headers.

    View full-size slide

  49. Now, imagine you're not even writing C...

    View full-size slide

  50. Header:
    void print_the_thing(const char*);
    Swift:
    print_the_thing("the thing!")

    View full-size slide

  51. Remember the FFI ! above?
    We get all those benefits without any work

    View full-size slide

  52. No work no bugs

    View full-size slide

  53. The compiler isn't smarter.
    It's just as smart as the people who know
    all the intricacies
    of all the languages.

    View full-size slide

  54. Think memory management.
    Call conventions.

    View full-size slide

  55. In my free time, I work on
    a language called Trill

    View full-size slide

  56. // ClangImporter.swift
    class ClangImporter {
    func run(in context: ASTContext) {
    importBuiltinAliases(into: context)
    importBuiltinFunctions(into: context)
    importDeclarations(for: URL(fileURLWithPath: ClangImporter.runtimeHeaderPath).
    appendingPathComponent("trill.h").path,
    in: context)
    if let path = ClangImporter.includeDir {
    for header in ClangImporter.headerFiles {
    importDeclarations(for: "\(path)/\(header)", in: context)
    }
    }
    }
    }

    View full-size slide

  57. // ClangImporter.swift
    class ClangImporter {
    func importDeclarations(for path: String, in context: ASTContext) {
    do {
    let file = try SourceFile(path: .file(URL(fileURLWithPath: path)), context: context)
    context.add(file)
    } catch {
    // do nothing
    }
    let tu: CXTranslationUnit
    do {
    tu = try translationUnit(for: path)
    } catch {
    context.error(error)
    return
    }
    let cursor = clang_getTranslationUnitCursor(tu)
    clang_visitChildrenWithBlock(cursor) { child, parent in
    let kind = clang_getCursorKind(child)
    switch kind {
    case CXCursor_TypedefDecl:
    self.importTypeDef(child, in: context)
    case CXCursor_EnumDecl:
    self.importEnum(child, in: context)
    case CXCursor_StructDecl:
    self.importStruct(child, in: context)
    case CXCursor_FunctionDecl:
    self.importFunction(child, in: context)
    case CXCursor_MacroDefinition:
    self.importMacro(child, in: tu, context: context)
    case CXCursor_UnionDecl:
    self.importUnion(child, context: context)
    case CXCursor_VarDecl:
    self.importVariableDeclation(child, in: tu, context: context)
    default:
    break
    }
    return CXChildVisit_Continue
    }
    clang_disposeTranslationUnit(tu)
    }
    }

    View full-size slide

  58. This is super ✨ meta ✨

    View full-size slide

  59. The Swift compiler knows how to import C headers
    The Trill compiler is written in Swift
    It uses a C compiler to read C headers

    View full-size slide

  60. But the result is a nearly seamless experience for users

    View full-size slide

  61. let foo = 10
    let bar = garbage()
    func garbage() -> Int {
    printf("%s called!\n", #function)
    trill_printStackTrace()
    return 100
    }
    func main() {
    printf("Garbage hasn't been called yet\n")
    printf("Foo: %d, bar: %d\n", foo, bar)
    printf("Bar: %d\n", bar)
    }

    View full-size slide

  62. That's Trill code.
    Calling C code.

    View full-size slide

  63. It takes a lot of work to implement
    the magic

    View full-size slide

  64. But that work creates the sort of seamless experience
    we expect in today's world of many languages.

    View full-size slide

  65. If I can understand C, and Swift,
    and Ruby and Python...
    Why shouldn't all of them understand each other?

    View full-size slide

  66. Building bridges capable of carrying
    all this traffic
    is hard
    But you reap the benefits
    every day

    View full-size slide

  67. Back to the top:
    We work in multiple languages for a good reason

    View full-size slide

  68. We're most productive when we can
    pick & choose the best tool
    for the job at hand

    View full-size slide

  69. That happens most often and
    with the least friction
    when our languages can talk with each other

    View full-size slide

  70. Just like in human language,
    speaking happens in many different ways

    View full-size slide

  71. And choosing the right way to translate
    is just as important with machines
    as with people

    View full-size slide

  72. So, the answer with programming languages
    is the same as with upset people

    View full-size slide

  73. BUILD A BRIDGE

    View full-size slide

  74. BUILD A BRIDGE
    AND GET OVER IT

    View full-size slide

  75. [insert obligatory Bridges of Siracusa County
    reference here]

    View full-size slide

  76. In which Samuel answers
    random questions
    about language interop
    & bridging

    View full-size slide