Skip to content

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
theblixguy committed Nov 8, 2018
1 parent 05efa49 commit ecbb5a1
Show file tree
Hide file tree
Showing 52 changed files with 4,354 additions and 169 deletions.
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
.DS_Store
/.build
/Packages
/*.xcodeproj
2,009 changes: 1,845 additions & 164 deletions LittleSwift.xcodeproj/project.pbxproj

Large diffs are not rendered by default.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,44 @@
<dict>
<key>SchemeUserState</key>
<dict>
<key>LLVM.xcscheme</key>
<dict>
<key>orderHint</key>
<integer>2</integer>
</dict>
<key>LLVMPackageDescription.xcscheme</key>
<dict>
<key>orderHint</key>
<integer>3</integer>
</dict>
<key>LittleSwift-Package.xcscheme_^#shared#^_</key>
<dict>
<key>orderHint</key>
<integer>1</integer>
</dict>
<key>LittleSwift.xcscheme</key>
<dict>
<key>orderHint</key>
<integer>0</integer>
</dict>
<key>LittleSwiftPackageDescription.xcscheme</key>
<dict>
<key>orderHint</key>
<integer>4</integer>
</dict>
<key>LittleSwiftPackageTests.xcscheme</key>
<dict>
<key>orderHint</key>
<integer>5</integer>
</dict>
</dict>
<key>SuppressBuildableAutocreation</key>
<dict>
<key>7CC158AC21766FC000EEAEBE</key>
<dict>
<key>primary</key>
<true/>
</dict>
</dict>
</dict>
</plist>
34 changes: 34 additions & 0 deletions Package.resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
{
"object": {
"pins": [
{
"package": "cllvm",
"repositoryURL": "https://github.com/llvm-swift/cllvm.git",
"state": {
"branch": null,
"revision": "e3b750e75df1c33ddb1e1d391c6c78640baf404f",
"version": "0.0.7"
}
},
{
"package": "FileCheck",
"repositoryURL": "https://github.com/llvm-swift/FileCheck.git",
"state": {
"branch": null,
"revision": "89b8480055f9adf8ce2f9ad5e2fac7ac1076242e",
"version": "0.0.8"
}
},
{
"package": "LLVM",
"repositoryURL": "https://github.com/llvm-swift/LLVMSwift.git",
"state": {
"branch": null,
"revision": "e7c190ee25fdd54f1f0e303dd636023c19b46d33",
"version": "0.3.0"
}
}
]
},
"version": 1
}
24 changes: 24 additions & 0 deletions Package.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// swift-tools-version:4.2
// The swift-tools-version declares the minimum version of Swift required to build this package.

import PackageDescription

let package = Package(
name: "LittleSwift",
products: [
.executable(name: "lswiftc", targets: ["LittleSwift"]),
],
dependencies: [
.package(url: "https://github.com/llvm-swift/LLVMSwift.git", from: "0.3.0")
],
targets: [
// Targets are the basic building blocks of a package. A target can define a module or a test suite.
// Targets can depend on other targets in this package, and on products in packages which this package depends on.
.target(
name: "LittleSwift",
dependencies: ["LLVM"]),
.testTarget(
name: "LittleSwiftTests",
dependencies: ["LittleSwift"]),
]
)
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# LittleSwift

A description of this package.
21 changes: 21 additions & 0 deletions Sources/LittleSwift/Emitter/Emitter.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
//
// Emitter.swift
// LittleSwift
//
// Created by Suyash Srijan on 17/10/2018.
// Copyright © 2018 Suyash Srijan. All rights reserved.
//

import Foundation

/// A protocol that describes an entity which takes an AST
/// as input and emits code in some other language.
public protocol Emitter {}

/// A protocol that describes a container which stores the
/// emitted code.
public protocol Emitted {}

/// A protocol that describes an AST node which can be emitted
/// in some other language.
public protocol Emittable {}
242 changes: 242 additions & 0 deletions Sources/LittleSwift/Emitter/Language/Kotlin/KotlinEmitter.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,242 @@
//
// KotlinEmitter.swift
// LittleSwift
//
// Created by Suyash Srijan on 21/10/2018.
// Copyright © 2018 Suyash Srijan. All rights reserved.
//

import Foundation

public protocol KotlinEmittable: Emittable {
func emit() -> KotlinEmitted
}

public protocol KotlinEmitter: Emitter {
func emit() -> KotlinEmitted
}

public protocol KotlinEmitted: Emitted {
var value: String { get }
}

struct KotlinEmittedContainer: KotlinEmitted {
let value: String
}

extension KotlinEmittedContainer {
static func empty() -> KotlinEmitted {
return KotlinEmittedContainer(value: "")
}
}

struct KotlinEmitterProvider: KotlinEmitter {
private let ast: [Expression]

init(with ast: [Expression]) {
self.ast = ast
}

func emit() -> KotlinEmitted {

var emittedExpr: String = ""

ast.forEach { expression in
guard let expression = expression as? KotlinEmittable else { return }
emittedExpr.append(expression.emit().value)
emittedExpr.append("\n\n")
}

return KotlinEmittedContainer(value: emittedExpr)
}
}

extension AssignmentExpression: KotlinEmittable {

public func emit() -> KotlinEmitted {
guard let value = value as? KotlinEmittable else {
return KotlinEmittedContainer.empty()
}

let assignExpr = variable.emit().value
let _value = value.emit().value
return KotlinEmittedContainer(value: "\(assignExpr) = \(_value)")
}
}

extension VariableDeclaration: KotlinEmittable {

public func emit() -> KotlinEmitted {
let _mutability = mutability == .mutating ? "var" : "val"
let _typeNode = BuiltinType(rawName: type.rawName)
let _type = returnTypeString(for: _typeNode)
let decl = "\(_mutability) \(name): \(_type)"
return KotlinEmittedContainer(value: decl)
}

private func returnTypeString(for type: BuiltinType) -> String {
switch type.rawName {
case BuiltinType.void.rawName: return ""
case BuiltinType.string.rawName: return "String"
case BuiltinType.integer.rawName: return "Int"
case BuiltinType.float.rawName: return "Float"
case BuiltinType.bool.rawName: return "Boolean"
default: return ""
}
}
}

extension StringType: KotlinEmittable {

public func emit() -> KotlinEmitted {
return KotlinEmittedContainer(value: value)
}
}

extension IntegerType: KotlinEmittable {

public func emit() -> KotlinEmitted {
return KotlinEmittedContainer(value: "\(value)")
}
}

extension FloatType: KotlinEmittable {

public func emit() -> KotlinEmitted {
return KotlinEmittedContainer(value: "\(value)")
}
}

extension BoolType: KotlinEmittable {

public func emit() -> KotlinEmitted {
return KotlinEmittedContainer(value: "\(value)")
}
}

extension BinaryOperatorExpression: KotlinEmittable {

public func emit() -> KotlinEmitted {
guard let lhs = lhs as? KotlinEmittable, let rhs = rhs as? KotlinEmittable else {
return KotlinEmittedContainer.empty()
}

return KotlinEmittedContainer(value: "\(lhs.emit().value) \(returnOperatorString(for: operation)) \(rhs.emit().value)")
}

private func returnOperatorString(for operator: Operator) -> String {
switch `operator` {
case .plus: return "+"
case .minus: return "-"
case .multiply: return "*"
case .divide: return "/"
}
}
}

extension PropertyAccessExpression: KotlinEmittable {

public func emit() -> KotlinEmitted {
return KotlinEmittedContainer(value: name)
}
}

extension IfStatement: KotlinEmittable {

public func emit() -> KotlinEmitted {
guard let conditional = conditional as? KotlinEmittable, let body = body as? [KotlinEmittable] else {
return KotlinEmittedContainer.empty()
}

var _emitted = ""
_emitted.append("if (\(conditional.emit().value)) {\n")
_emitted.append(body.map { "\t\t" + $0.emit().value }.joined(separator: "\n"))
_emitted.append("\n\t}")
return KotlinEmittedContainer(value: _emitted)
}
}

extension PrintStatement: KotlinEmittable {

public func emit() -> KotlinEmitted {
guard let printExpressions = arguments as? [KotlinEmittable] else {
return KotlinEmittedContainer.empty()
}

let _printExprs = "print(\(printExpressions.map { $0.emit().value }.first ?? ""))"
return KotlinEmittedContainer(value: _printExprs)
}
}

extension ReturnStatement: KotlinEmittable {

public func emit() -> KotlinEmitted {
guard let returnExpression = value as? KotlinEmittable else {
return KotlinEmittedContainer.empty()
}

return KotlinEmittedContainer(value: "return \(returnExpression.emit().value)")
}
}

extension FunctionDeclaration: KotlinEmittable {

public func emit() -> KotlinEmitted {
guard let body = body as? [KotlinEmittable] else {
return KotlinEmittedContainer.empty()
}

let _signature = signature.emit().value
let _body = body.map { "\t" + $0.emit().value }.joined(separator: "\n")
let declaration = "\(_signature) {\n\(_body)\n}"
return KotlinEmittedContainer(value: declaration)
}
}

extension FunctionSignature: KotlinEmittable {

public func emit() -> KotlinEmitted {
var signature: String {
let _signature = arguments.map { $0.emit().value.dropFirst(4) }.joined(separator: ", ")
if _signature.isEmpty && name.elementsEqual("main") {
return "args: Array<String>"
}
return _signature
}

let _returnTypeStr = returnTypeString(for: returnType)

var _fullSignature = ""

if returnType.rawName == BuiltinType.void.rawName {
_fullSignature = "fun \(name)(\(signature))"
} else {
_fullSignature = "fun \(name)(\(signature)): \(_returnTypeStr)"
}

return KotlinEmittedContainer(value: _fullSignature)
}

private func returnTypeString(for type: BuiltinType) -> String {
switch type.rawName {
case BuiltinType.void.rawName: return ""
case BuiltinType.string.rawName: return "String"
case BuiltinType.integer.rawName: return "Int"
case BuiltinType.float.rawName: return "Float"
case BuiltinType.bool.rawName: return "Boolean"
default: return ""
}
}
}

extension FunctionCallExpression: KotlinEmittable {

public func emit() -> KotlinEmitted {
guard let arguments = arguments as? [KotlinEmittable] else {
return KotlinEmittedContainer.empty()
}

let _arguments = arguments.map { $0.emit().value }.joined(separator: ", ")
return KotlinEmittedContainer(value: "\(name)(\(_arguments))")
}
}
Loading

0 comments on commit ecbb5a1

Please sign in to comment.