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. I write developer tools that occasionally work. Otherwise, I'm in

    a library at UChicago, studying something impractical.
  2. THE LANGUAGE GAP Gap a break in continuity Bridge something

    that is intended to reconcile or form a connection between two things
  3. THE LANGUAGE GAP > When we want to connect two

    or more languages to each other. > When we make languages talk to each other.
  4. Some languages can be translated perfectly: > Curry–Howard correspondence >

    Relationship between propositions & proofs and values & types > Turing machines > Turing completeness > !
  5. WAYS TO TRANSLATE > Importer > FFI > XPC >

    Compiler Support > main()
  6. 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.
  7. $ echo I have earned those names. Bought and paid

    for them. I have earned those names. Bought and paid for them.
  8. HOW SHELL PROGRAMS WORK TOGETHER > 1 Program, 1 Process

    > Program Arguments > environ(7) > exit(3) > Side Effects
  9. A very general way of allowing programs in different languages

    to work together. But they don't work together very well.
  10. > Run into a problem > Google it > Click

    on the first SO link > Copy-paste the solution that's already written
  11. ABI > How functions call each other > How data

    is laid out in memory > How memory is managed across function calls
  12. 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 <stdio.h> int _TF5swift3fibFSiSi(int); int main(int argc, char *argv[]) { for (int i = 1; i < 15; ++i) { printf("fib(%d) = %d\n", i, _TF5swift3fibFSiSi(i)); } }
  13. Arcane Commands > clang c.c -c > swiftc swift.swift -c

    -parse-as-library > ld swift.o c.o ... -o main > ./main
  14. 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
  15. We relied on us knowing how the Swift program worked

    under the hood in order to call it from C.
  16. Now imagine writing out those function prototypes for an entire

    library. And remember, a single mistake means !.
  17. This is like seeing inside the matrix. It's being able

    to call the name of the wind when your app encounters danger.
  18. The compiler isn't smarter. It's just as smart as the

    people who know all the intricacies of all the languages.
  19. // 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) } } } }
  20. // 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) } }
  21. 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
  22. 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) }
  23. But that work creates the sort of seamless experience we

    expect in today's world of many languages.
  24. If I can understand C, and Swift, and Ruby and

    Python... Why shouldn't all of them understand each other?
  25. That happens most often and with the least friction when

    our languages can talk with each other
  26. And choosing the right way to translate is just as

    important with machines as with people