Skip to content

Commit f0208cb

Browse files
author
Brandon Sneed
committed
repl stuff
1 parent c39ccdc commit f0208cb

21 files changed

Lines changed: 3157 additions & 2 deletions

.swiftpm/xcode/xcshareddata/xcschemes/segmentcli.xcscheme

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,10 @@
9595
</CommandLineArgument>
9696
<CommandLineArgument
9797
argument = "scaffold --plugin --swift"
98+
isEnabled = "NO">
99+
</CommandLineArgument>
100+
<CommandLineArgument
101+
argument = "repl"
98102
isEnabled = "YES">
99103
</CommandLineArgument>
100104
<CommandLineArgument

Package.resolved

Lines changed: 9 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Package.swift

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@ let package = Package(
1414
.package(url: "https://github.com/mtynior/ColorizeSwift.git", from: "1.5.0"),
1515
.package(url: "https://github.com/segmentio/analytics-swift.git", branch: "bsneed/cli_additions"),
1616
.package(url: "https://github.com/swiftcsv/SwiftCSV.git", from: "0.6.1"),
17-
.package(url: "https://github.com/AlwaysRightInstitute/Mustache", from: "1.0.0")
17+
.package(url: "https://github.com/AlwaysRightInstitute/Mustache", from: "1.0.0"),
18+
.package(url: "https://github.com/antitypical/Result.git", from: "5.0.0")
1819
],
1920
targets: [
2021
// Targets are the basic building blocks of a package. A target can define a module or a test suite.
@@ -25,6 +26,7 @@ let package = Package(
2526
"Spinner",
2627
"ColorizeSwift",
2728
"SwiftCSV",
29+
"Result",
2830
.product(name: "mustache", package: "Mustache"),
2931
.product(name: "Segment", package: "analytics-swift")]),
3032
.testTarget(
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
//
2+
// File.swift
3+
//
4+
//
5+
// Created by Brandon Sneed on 12/8/21.
6+
//
7+
8+
import Foundation
9+
import SwiftCLI
10+
import Segment
11+
12+
class REPLCommand: Command {
13+
let name: String = "repl"
14+
let shortDescription = "Segment virtual development environment"
15+
16+
@Key("-r", "--runscript", "Runs the supplied script in the REPL")
17+
var scriptFile: String?
18+
19+
let fileManager = FileManager.default
20+
21+
func execute() throws {
22+
configureInterpeterRuntime()
23+
24+
if let scriptFile = scriptFile {
25+
if fileManager.fileExists(atPath: scriptFile) {
26+
do {
27+
try Lox.runFile(path: scriptFile)
28+
} catch {
29+
exitWithError(error.localizedDescription)
30+
}
31+
} else {
32+
exitWithError("\(scriptFile) does not exist!")
33+
}
34+
} else {
35+
print("Welcome to the Segment Analytics REPL. Type :help for assistance.")
36+
Lox.runPrompt()
37+
}
38+
}
39+
40+
}
41+
42+
/*
43+
guard let writeKey = args[0] as? String else { return NilAny }
44+
self.analytics = Analytics(configuration: Configuration(writeKey: writeKey).flushAt(1))
45+
46+
let analyticsClass = LoxClass(name: "Analytics", superclass: nil, methods: [
47+
"track": LoxFunction(name: "track", declaration:
48+
Stmt.Function(name: Token(type: .fun, lexeme: "", literal: nil, line: 0),
49+
parameters: [Token(type: .string, lexeme: "", literal: nil, line: 0)],
50+
body: nil,
51+
closure: { args in
52+
guard let analytics = self.analytics else { return NilAny }
53+
analytics.track(name:args[0] as! String)
54+
// wait till we know the event has been placed in the queue
55+
while analytics.hasUnsentEvents == false {
56+
RunLoop.main.run(until: Date.distantPast)
57+
}
58+
//if flush {
59+
analytics.flush()
60+
// wait for flush to complete
61+
while analytics.hasUnsentEvents {
62+
analytics.flush()
63+
RunLoop.main.run(until: Date.distantPast)
64+
}
65+
//}
66+
return NilAny
67+
}),
68+
closure: Environment(), isInitializer: false)
69+
])
70+
let analyticsInstance = LoxInstance(klass: analyticsClass)
71+
return analyticsInstance
72+
*/
Lines changed: 258 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,258 @@
1+
//
2+
// AstPrinter.swift
3+
// slox
4+
//
5+
// Created by Alejandro Martinez on 17/02/2017.
6+
// Copyright © 2017 Alejandro Martinez. All rights reserved.
7+
//
8+
9+
import Foundation
10+
11+
// Creates an unambiguous, if ugly, string representation of AST nodes.
12+
class AstPrinter: ExprVisitor, StmtVisitor {
13+
func print(expr: Expr) -> String {
14+
return expr.accept(visitor: self)
15+
}
16+
17+
func print(stmt: Stmt) -> String {
18+
return stmt.accept(visitor: self)
19+
}
20+
21+
// MARK: ExprVisitor
22+
23+
func visitAssignExpr(_ expr: Expr.Assign) -> String {
24+
return parenthesize(name: "=", parts: expr.name.lexeme, expr.value)
25+
}
26+
27+
func visitBinaryExpr(_ expr: Expr.Binary) -> String {
28+
return parenthesize(name: expr.op.lexeme, exprs: expr.left, expr.right)
29+
}
30+
31+
func visitCallExpr(_ expr: Expr.Call) -> String {
32+
return parenthesize(name: "call", parts: expr.callee, expr.arguments)
33+
}
34+
35+
func visitGetExpr(_ expr: Expr.Get) -> String {
36+
return parenthesize(name: ".", parts: expr.object, expr.name.lexeme)
37+
}
38+
39+
func visitGroupingExpr(_ expr: Expr.Grouping) -> String {
40+
return parenthesize(name: "group", exprs: expr.expression)
41+
}
42+
43+
func visitLiteralExpr(_ expr: Expr.Literal) -> String {
44+
guard let value = expr.value else {
45+
return "nil"
46+
}
47+
return String(describing: value)
48+
}
49+
50+
func visitLogicalExpr(_ expr: Expr.Logical) -> String {
51+
return parenthesize(name: expr.op.lexeme, exprs: expr.left, expr.right)
52+
}
53+
54+
func visitSetExpr(_ expr: Expr.Set) -> String {
55+
return parenthesize(name: "=", parts: expr.object, expr.name.lexeme, expr.value)
56+
}
57+
58+
func visitSuperExpr(_ expr: Expr.Super) -> String {
59+
return parenthesize(name: "super", parts: expr.method)
60+
}
61+
62+
func visitThisExpr(_ expr: Expr.This) -> String {
63+
return "this"
64+
}
65+
66+
func visitUnaryExpr(_ expr: Expr.Unary) -> String {
67+
return parenthesize(name: expr.op.lexeme, exprs: expr.right)
68+
}
69+
70+
func visitVariableExpr(_ expr: Expr.Variable) -> String {
71+
return expr.name.lexeme
72+
}
73+
74+
func visitWhileStmt(_ stmt: Stmt.While) -> String {
75+
return parenthesize(name: "while", parts: stmt.condition, stmt.body)
76+
}
77+
78+
private func parenthesize(name: String, exprs: Expr...) -> String {
79+
var output = ""
80+
81+
output.append("(\(name)")
82+
83+
for expr in exprs {
84+
output.append(" ")
85+
output.append(expr.accept(visitor: self))
86+
}
87+
88+
output.append(")")
89+
90+
return output
91+
}
92+
93+
// MARK: StmtVisitor
94+
95+
func visitBlockStmt(_ stmt: Stmt.Block) -> String {
96+
var output = ""
97+
98+
output.append("(block ")
99+
100+
for statement in stmt.statements {
101+
output.append(statement.accept(visitor: self))
102+
}
103+
104+
return output
105+
}
106+
107+
func visitClassStmt(_ stmt: Stmt.Class) -> String {
108+
var output = ""
109+
output += ("(class " + stmt.name.lexeme)
110+
111+
// if (stmt.superclass != null) {
112+
// builder.append(" < " + print(stmt.superclass));
113+
// }
114+
115+
for method in stmt.methods {
116+
output += " " + method.accept(visitor: self)
117+
}
118+
119+
output += ")"
120+
return output
121+
}
122+
123+
func visitBreakStmt(_ stmt: Stmt.Break) -> String {
124+
return "(break)"
125+
}
126+
127+
func visitExpressionStmt(_ stmt: Stmt.Expression) -> String {
128+
return parenthesize(name: ";", exprs: stmt.expression)
129+
}
130+
131+
func visitFunctionStmt(_ stmt: Stmt.Function) -> String {
132+
var res = "(fun \(stmt.name.lexeme)"
133+
134+
res += "("
135+
for param in stmt.parameters {
136+
res += " \(param.lexeme)"
137+
}
138+
res += ") "
139+
140+
if let stmtbody = stmt.body {
141+
for body in stmtbody {
142+
res += body.accept(visitor: self)
143+
}
144+
} else {
145+
// ...
146+
}
147+
148+
return res
149+
}
150+
151+
func visitIfStmt(_ stmt: Stmt.If) -> String {
152+
guard let elseBranch = stmt.elseBranch else {
153+
return parenthesize(name: "if", parts: stmt.condition, stmt.thenBranch)
154+
}
155+
156+
return parenthesize(name: "if-else", parts: stmt.condition, stmt.thenBranch, elseBranch)
157+
}
158+
159+
func visitPrintStmt(_ stmt: Stmt.Print) -> String {
160+
return parenthesize(name: "print", exprs: stmt.expression)
161+
}
162+
163+
func visitReturnStmt(_ stmt: Stmt.Return) -> String {
164+
guard let value = stmt.value else {
165+
return "(return)"
166+
}
167+
return parenthesize(name: "return", parts: value)
168+
}
169+
170+
func visitVarStmt(_ stmt: Stmt.Var) -> String {
171+
guard let initializer = stmt.initializer else {
172+
return parenthesize(name: "var", parts: stmt.name)
173+
}
174+
175+
return parenthesize(name: "var", parts: stmt.name, "=", initializer)
176+
}
177+
178+
private func parenthesize(name: String, parts: Any...) -> String {
179+
var output = ""
180+
181+
output.append("(")
182+
183+
output.append(name)
184+
185+
for part in parts {
186+
output.append(" ")
187+
188+
if let expr = part as? Expr {
189+
output.append(expr.accept(visitor: self))
190+
} else if let stmt = part as? Stmt {
191+
output.append(stmt.accept(visitor: self))
192+
} else if let token = part as? Token {
193+
output.append(token.lexeme)
194+
} else {
195+
output.append(String(describing: part))
196+
}
197+
}
198+
199+
output.append(")")
200+
201+
return output
202+
}
203+
}
204+
205+
// Chapter 5. Extra 3. In Reverse Polish Notation
206+
class AstRPNPrinter: ExprVisitor {
207+
func print(expr: Expr) -> String {
208+
return expr.accept(visitor: self)
209+
}
210+
211+
func visitAssignExpr(_ expr: Expr.Assign) -> String {
212+
fatalError("unimplemented")
213+
}
214+
215+
func visitBinaryExpr(_ expr: Expr.Binary) -> String {
216+
return "\(print(expr: expr.left)) \(print(expr: expr.right)) \(expr.op.lexeme)"
217+
}
218+
219+
func visitCallExpr(_ expr: Expr.Call) -> String {
220+
fatalError("unimplemented")
221+
}
222+
223+
func visitGetExpr(_ expr: Expr.Get) -> String {
224+
fatalError("unimplemented")
225+
}
226+
227+
func visitGroupingExpr(_ expr: Expr.Grouping) -> String {
228+
return print(expr: expr.expression)
229+
}
230+
231+
func visitLiteralExpr(_ expr: Expr.Literal) -> String {
232+
return String(describing: expr.value)
233+
}
234+
235+
func visitLogicalExpr(_ expr: Expr.Logical) -> String {
236+
return "\(print(expr: expr.left)) \(print(expr: expr.right)) \(expr.op.lexeme)"
237+
}
238+
239+
func visitSetExpr(_ expr: Expr.Set) -> String {
240+
fatalError("unimplemented")
241+
}
242+
243+
func visitSuperExpr(_ expr: Expr.Super) -> String {
244+
fatalError("unimplemented")
245+
}
246+
247+
func visitThisExpr(_ expr: Expr.This) -> String {
248+
fatalError("unimplemented")
249+
}
250+
251+
func visitUnaryExpr(_ expr: Expr.Unary) -> String {
252+
return "\(print(expr: expr.right)) \(expr.op.lexeme)"
253+
}
254+
255+
func visitVariableExpr(_ expr: Expr.Variable) -> String {
256+
fatalError("unimplemented")
257+
}
258+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
//
2+
// StmtDebug.swift
3+
// slox
4+
//
5+
// Created by Alejandro Martinez on 03/06/2017.
6+
//
7+
//
8+
9+
import Foundation
10+
11+
extension Stmt: CustomDebugStringConvertible {
12+
var debugDescription: String {
13+
return AstPrinter().print(stmt: self)
14+
}
15+
}
16+
17+
extension Expr: CustomDebugStringConvertible {
18+
var debugDescription: String {
19+
return AstPrinter().print(expr: self)
20+
}
21+
}

0 commit comments

Comments
 (0)