Skip to content

Adding Conditionals #74

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 27 commits into from
Jun 21, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .swiftlint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -130,3 +130,4 @@ disabled_rules:
- closure_parameter_position
- trailing_comma
- opening_brace
- optional_data_string_conversion
154 changes: 154 additions & 0 deletions Examples/Completed/conditionals/code.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
// Simple if statement
let temperature = 25
if temperature > 30 {
print("It's hot outside!")
}

// If-else statement
let score = 85
if score >= 90 {
print("Excellent!")
} else if score >= 80 {
print("Good job!")
} else if score >= 70 {
print("Passing")
} else {
print("Needs improvement")
}

// MARK: - Optional Binding with If

// Using if let for optional binding
let possibleNumber = "123"
if let actualNumber = Int(possibleNumber) {
print("The string \"\(possibleNumber)\" has an integer value of \(actualNumber)")
} else {
print("The string \"\(possibleNumber)\" could not be converted to an integer")
}

// Multiple optional bindings
let possibleName: String? = "John"
let possibleAge: Int? = 30
if let name = possibleName, let age = possibleAge {
print("\(name) is \(age) years old")
}

// MARK: - Guard Statements
func greet(person: [String: String]) {
guard let name = person["name"] else {
print("No name provided")
return
}

guard let age = person["age"], let ageInt = Int(age) else {
print("Invalid age provided")
return
}

print("Hello \(name), you are \(ageInt) years old")
}

// MARK: - Switch Statements
// Switch with range matching
let approximateCount = 62
let countedThings = "moons orbiting Saturn"
let naturalCount: String
switch approximateCount {
case 0:
naturalCount = "no"
case 1..<5:
naturalCount = "a few"
case 5..<12:
naturalCount = "several"
case 12..<100:
naturalCount = "dozens of"
case 100..<1000:
naturalCount = "hundreds of"
default:
naturalCount = "many"
}
print("There are \(naturalCount) \(countedThings).")

// Switch with tuple matching
let somePoint = (1, 1)
switch somePoint {
case (0, 0):
print("(0, 0) is at the origin")
case (_, 0):
print("(\(somePoint.0), 0) is on the x-axis")
case (0, _):
print("(0, \(somePoint.1)) is on the y-axis")
case (-2...2, -2...2):
print("(\(somePoint.0), \(somePoint.1)) is inside the box")
default:
print("(\(somePoint.0), \(somePoint.1)) is outside of the box")
}

// Switch with value binding
let anotherPoint = (2, 0)
switch anotherPoint {
case (let x, 0):
print("on the x-axis with an x value of \(x)")
case (0, let y):
print("on the y-axis with a y value of \(y)")
case let (x, y):
print("somewhere else at (\(x), \(y))")
}

// MARK: - Fallthrough
// Using fallthrough in switch
let integerToDescribe = 5
var description = "The number \(integerToDescribe) is"
switch integerToDescribe {
case 2, 3, 5, 7, 11, 13, 17, 19:
description += " a prime number, and also"
fallthrough
default:
description += " an integer."
}
print(description)

// MARK: - Labeled Statements
// Using labeled statements with break
let finalSquare = 25
var board = [Int](repeating: 0, count: finalSquare + 1)
board[03] = 8
board[06] = 11
board[09] = 9
board[10] = 2
board[14] = -10
board[19] = -11
board[22] = -2
board[24] = -8

var square = 0
var diceRoll = 0
while square != finalSquare {
diceRoll += 1
if diceRoll == 7 { diceRoll = 1 }
switch square + diceRoll {
case finalSquare:
break
case let newSquare where newSquare > finalSquare:
continue
default:
square += diceRoll
square += board[square]
}
}

// MARK: - For Loops
// For-in loop with enumerated() to get index and value
print("\n=== For-in with Enumerated ===")
for (index, name) in names.enumerated() {
print("\(index): \(name)")
}

// For-in loop with where clause
print("\n=== For-in with Where Clause ===")
let numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
for number in numbers where number % 2 == 0 {
print("Even number: \(number)")
}


222 changes: 222 additions & 0 deletions Examples/Completed/conditionals/dsl.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,222 @@
Group {
Variable(.let, name: "temperature", equals: Literal.integer(25))
.comment {
Line("Simple if statement")
}
If {
Infix("temperature", ">", 30)
} then: {
Call("print", "It's hot outside!")
}
Variable(.let, name: "score", equals: Literal.integer(85))
.comment {
Line("If-else statement")
}
If {
Infix("score", ">=", 90)
} then: {
Call("print", "Excellent!")
} else: {
If {
Infix("score", ">=", 80)
} then: {
Call("print", "Good job!")
}
If {
Infix("score", ">=", 70)
} then: {
Call("print", "Passing")
}
Then {
Call("print", "Needs improvement")
}
}

Variable(.let, name: "possibleNumber", equals: Literal.string("123"))
.comment {
Line("MARK: - Optional Binding with If")
Line("Using if let for optional binding")
}
If(Let("actualNumber", Init("Int") {
ParameterExp(name: "", value: "possibleNumber")
}), then: {
Call("print", "The string \"\\(possibleNumber)\" has an integer value of \\(actualNumber)")
}, else: {
Call("print", "The string \"\\(possibleNumber)\" could not be converted to an integer")
})

Variable(.let, name: "possibleName", type: "String?", equals: Literal.string("John")).withExplicitType()
.comment {
Line("Multiple optional bindings")
}
Variable(.let, name: "possibleAge", type: "Int?", equals: Literal.integer(30)).withExplicitType()
If {
Let("name", "possibleName")
Let("age", "possibleAge")
} then: {
Call("print", "\\(name) is \\(age) years old")
}

Function("greet", parameters: [Parameter("person", type: "[String: String]")]) {
Guard {
Let("name", "person[\"name\"]")
} else: {
Call("print", "No name provided")
}
Guard {
Let("age", "person[\"age\"]")
Let("ageInt", Init("Int") {
ParameterExp(name: "", value: "age")
})
} else: {
Call("print", "Invalid age provided")
}
Call("print", "Hello \\(name), you are \\(ageInt) years old")
}
}.comment {
Line("MARK: - Guard Statements")
}

Variable(.let, name: "approximateCount", equals: Literal.integer(62))
.comment {
Line("MARK: - Switch Statements")
Line("Switch with range matching")
}
Variable(.let, name: "countedThings", equals: Literal.string("moons orbiting Saturn"))
Variable(.let, name: "naturalCount", type: "String").withExplicitType()
Switch("approximateCount") {
SwitchCase(0) {
Assignment("naturalCount", Literal.string("no"))
}
SwitchCase(1..<5) {
Assignment("naturalCount", Literal.string("a few"))
}
SwitchCase(5..<12) {
Assignment("naturalCount", Literal.string("several"))
}
SwitchCase(12..<100) {
Assignment("naturalCount", Literal.string("dozens of"))
}
SwitchCase(100..<1000) {
Assignment("naturalCount", Literal.string("hundreds of"))
}
Default {
Assignment("naturalCount", Literal.string("many"))
}
}
Call("print", "There are \\(naturalCount) \\(countedThings).")
Variable(.let, name: "somePoint", type: "(Int, Int)", equals: VariableExp("(1, 1)"), explicitType: true)
.comment {
Line("Switch with tuple matching")
}
Switch("somePoint") {
SwitchCase(Tuple.pattern([0, 0])) {
Call("print", "(0, 0) is at the origin")
}
SwitchCase(Tuple.pattern([nil, 0])) {
Call("print", "(\(somePoint.0), 0) is on the x-axis")
}
SwitchCase(Tuple.pattern([0, nil])) {
Call("print", "(0, \(somePoint.1)) is on the y-axis")
}
SwitchCase(Tuple.pattern([(-2...2), (-2...2)])) {
Call("print", "(\(somePoint.0), \(somePoint.1)) is inside the box")
}
Default {
Call("print", "(\(somePoint.0), \(somePoint.1)) is outside of the box")
}
}
Variable(.let, name: "anotherPoint", type: "(Int, Int)", equals: VariableExp("(2, 0)"), explicitType: true)
.comment {
Line("Switch with value binding")
}
Switch("anotherPoint") {
SwitchCase(Tuple.pattern([.let("x"), 0])) {
Call("print", "on the x-axis with an x value of \(x)")

}
SwitchCase(Tuple.pattern([0, .let("y")])) {
Call("print", "on the y-axis with a y value of \(y)")

}
SwitchCase(Tuple.pattern([.let("x"), .let("y")])) {
Call("print", "somewhere else at (\(x), \(y))")

}
}
Variable(.let, name: "integerToDescribe", equals: 5)
Variable(.var, name: "description", equals: "The number \(integerToDescribe) is")
Switch("integerToDescribe") {
SwitchCase(2, 3, 5, 7, 11, 13, 17, 19) {
PlusAssign("description", "a prime number, and also")
Fallthrough()
}
Default {
PlusAssign("description", "an integer.")
}
}
Call("print", "description")

Variable(.let, name: "finalSquare", equals: 25)
Variable(.var, name: "board", equals: Literal.array(Array(repeating: Literal.integer(0), count: 26)))

Infix("board[03]", "+=", 8)
Infix("board[06]", "+=", 11)
Infix("board[09]", "+=", 9)
Infix("board[10]", "+=", 2)
Infix("board[14]", "-=", 10)
Infix("board[19]", "-=", 11)
Infix("board[22]", "-=", 2)
Infix("board[24]", "-=", 8)

Variable(.var, name: "square", equals: 0)
Variable(.var, name: "diceRoll", equals: 0)
While {
Infix("square", "!=", "finalSquare")
} then: {
Assignment("diceRoll", "+", 1)
If {
Infix("diceRoll", "==", 7)
} then: {
Assignment("diceRoll", 1)
}
Switch(Infix("square", "+", "diceRoll")) {
SwitchCase("finalSquare") {
Break()
}
SwitchCase(Infix("newSquare", ">", "finalSquare")) {
Continue()
}
Default {
Infix("square", "+=", "diceRoll")
Infix("square", "+=", "board[square]")
}
}
}

Call("print", "\n=== For-in with Enumerated ===")
.comment {
Line("MARK: - For Loops")
Line("For-in loop with enumerated() to get index and value")
}
For {
Tuple.pattern([VariableExp("index"), VariableExp("name")])
} in: {
VariableExp("names").call("enumerated")
} then: {
Call("print", "Index: \\(index), Name: \\(name)")
}

Call("print", "\n=== For-in with Where Clause ===")
.comment {
Line("For-in loop with where clause")
}
For {
VariableExp("numbers")
} in: {
Literal.array([Literal.integer(1), Literal.integer(2), Literal.integer(3), Literal.integer(4), Literal.integer(5), Literal.integer(6), Literal.integer(7), Literal.integer(8), Literal.integer(9), Literal.integer(10)])
} where: {
Infix("number", "%", 2)
} then: {
Call("print", "Even number: \\(number)")
}
1 change: 1 addition & 0 deletions Examples/Completed/conditionals/syntax.json

Large diffs are not rendered by default.

Loading
Loading