-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
05efa49
commit ecbb5a1
Showing
52 changed files
with
4,354 additions
and
169 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
.DS_Store | ||
/.build | ||
/Packages | ||
/*.xcodeproj |
Large diffs are not rendered by default.
Oops, something went wrong.
2 changes: 1 addition & 1 deletion
2
LittleSwift.xcodeproj/project.xcworkspace/contents.xcworkspacedata
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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"]), | ||
] | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
# LittleSwift | ||
|
||
A description of this package. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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
242
Sources/LittleSwift/Emitter/Language/Kotlin/KotlinEmitter.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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))") | ||
} | ||
} |
Oops, something went wrong.