Skip to content

Commit

Permalink
Fixed a few bugs and added lists for case statements
Browse files Browse the repository at this point in the history
  • Loading branch information
BrettRToomey committed Dec 1, 2017
1 parent f8acb98 commit 9a983c1
Show file tree
Hide file tree
Showing 8 changed files with 58 additions and 39 deletions.
9 changes: 5 additions & 4 deletions Sources/Core/Ast.swift
Original file line number Diff line number Diff line change
Expand Up @@ -118,11 +118,12 @@ class LocationDirective: Node, Expr, Convertable {
var end: Pos { return directive + kind.rawValue.count }

// sourcery:inline:auto:LocationDirective.Init
init(directive: Pos, kind: LoneDirective, type: Type!, constant: Value!) {
init(directive: Pos, kind: LoneDirective, type: Type!, constant: Value!, conversion: (from: Type, to: Type)?) {
self.directive = directive
self.kind = kind
self.type = type
self.constant = constant
self.conversion = conversion
}
// sourcery:end
}
Expand Down Expand Up @@ -1047,7 +1048,7 @@ init(keyword: Pos, cond: Expr, body: Stmt, els: Stmt?) {

class CaseClause: Node, Stmt {
var keyword: Pos
var match: Expr?
var match: [Expr]
var colon: Pos
var block: Block

Expand All @@ -1057,7 +1058,7 @@ class CaseClause: Node, Stmt {
var end: Pos { return block.end }

// sourcery:inline:auto:CaseClause.Init
init(keyword: Pos, match: Expr?, colon: Pos, block: Block, label: Entity!) {
init(keyword: Pos, match: [Expr], colon: Pos, block: Block, label: Entity!) {
self.keyword = keyword
self.match = match
self.colon = colon
Expand Down Expand Up @@ -1167,7 +1168,7 @@ class Import: Node, TopLevelStmt {
var end: Pos { return alias?.end ?? path.end }

// sourcery:inline:auto:Import.Init
init(directive: Pos, alias: Ident?, path: Expr, importSymbolsIntoScope: Bool, exportSymbolsOutOfScope: Bool, resolvedName: String?, scope: Scope!, importee: Importable!) {
init(directive: Pos, alias: Ident?, path: Expr, importSymbolsIntoScope: Bool, exportSymbolsOutOfScope: Bool, resolvedName: String?, scope: Scope!, importee: Importable!) {
self.directive = directive
self.alias = alias
self.path = path
Expand Down
32 changes: 17 additions & 15 deletions Sources/Core/Checker.swift
Original file line number Diff line number Diff line change
Expand Up @@ -935,22 +935,24 @@ extension Checker {
}

for (c, nextCase) in sw.cases.enumerated().map({ ($0.element, sw.cases[safe: $0.offset + 1]) }) {
if let match = c.match {
if let desiredType = type {
let operand = check(expr: match, desiredType: desiredType)
dependencies.formUnion(operand.dependencies)

guard convert(operand.type, to: desiredType, at: match) else {
reportError("Cannot convert \(operand) to expected type '\(desiredType)'", at: match.start)
continue
}
} else {
let operand = check(expr: match, desiredType: ty.bool)
dependencies.formUnion(operand.dependencies)
if !c.match.isEmpty {
for match in c.match {
if let desiredType = type {
let operand = check(expr: match, desiredType: desiredType)
dependencies.formUnion(operand.dependencies)

guard convert(operand.type, to: desiredType, at: match) else {
reportError("Cannot convert \(operand) to expected type '\(desiredType)'", at: match.start)
continue
}
} else {
let operand = check(expr: match, desiredType: ty.bool)
dependencies.formUnion(operand.dependencies)

guard convert(operand.type, to: ty.bool, at: match) else {
reportError("Cannot convert \(operand) to expected type '\(ty.bool)'", at: match.start)
continue
guard convert(operand.type, to: ty.bool, at: match) else {
reportError("Cannot convert \(operand) to expected type '\(ty.bool)'", at: match.start)
continue
}
}
}
} else if seenDefault {
Expand Down
1 change: 1 addition & 0 deletions Sources/Core/Compiler.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import Foundation

public var compiler: Compiler!

// sourcery: noinit
public class Compiler {

/// - Note: Returns nil iff the invokePath is invalid
Expand Down
35 changes: 21 additions & 14 deletions Sources/Core/IRGenerator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -496,7 +496,7 @@ extension IRGenerator {

// FIXME: Is it actually possible to encounter a metatype as the rhs of a variable declaration?
// if it is we should catch that in the checker for declarations
if let type = entity.type as? ty.Metatype {
if let t = entity.type, let type = baseType(t) as? ty.Metatype {
let irType = b.createStruct(name: symbol(for: entity))

switch type.instanceType {
Expand Down Expand Up @@ -529,7 +529,8 @@ extension IRGenerator {

b.buildStore(ir, to: stackValue)

if let lit = value as? BasicLit, lit.token == .string {
// NOTE: this checks entity type to ensure we don't force-cast integers
if let lit = value as? BasicLit, lit.token == .string, baseType(entity.type!) == ty.string {

// If we have a string then ensure the data contents are stored on the stack so they can be mutated
let count = (lit.constant as! String).utf8.count + 1 // + 1 for null byte
Expand Down Expand Up @@ -877,7 +878,7 @@ extension IRGenerator {

var thenBlocks: [BasicBlock] = []
for c in sw.cases {
if c.match != nil {
if !c.match.isEmpty {
let thenBlock = curFunction.appendBasicBlock(named: "switch.then", in: module.context)
thenBlocks.append(thenBlock)
} else {
Expand All @@ -887,14 +888,17 @@ extension IRGenerator {
}

let value = sw.match.map({ emit(expr: $0) }) ?? i1.constant(1)
var matches: [IRValue] = []
var matches: [[IRValue]] = []
for (i, c, nextCase) in sw.cases.enumerated().map({ ($0.offset, $0.element, sw.cases[safe: $0.offset + 1]) }) {
let thenBlock = thenBlocks[i]
nextCase?.label.value = thenBlocks[safe: i + 1]

if let match = c.match {
let val = emit(expr: match)
matches.append(val)
if !c.match.isEmpty {
var vals: [IRValue] = []
for match in c.match {
vals.append(emit(expr: match))
}
matches.append(vals)
}

b.positionAtEnd(of: thenBlock)
Expand All @@ -907,10 +911,12 @@ extension IRGenerator {
b.positionAtEnd(of: curBlock)
}

let hasDefaultCase = sw.cases.last!.match == nil
let hasDefaultCase = sw.cases.last!.match.isEmpty
let irSwitch = b.buildSwitch(value, else: hasDefaultCase ? thenBlocks.last! : postBlock, caseCount: thenBlocks.count)
for (match, block) in zip(matches, thenBlocks) {
irSwitch.addCase(match, block)
for (matches, block) in zip(matches, thenBlocks) {
for match in matches {
irSwitch.addCase(match, block)
}
}

b.positionAtEnd(of: postBlock)
Expand Down Expand Up @@ -973,13 +979,14 @@ extension IRGenerator {
// TODO: Use the mangled entity name
if lit.token == .string {
let constant = lit.constant as! String
switch lit.type!.width! {
let litType = baseType(lit.type)
switch litType.width! {
case 8:
return canonicalize(lit.type as! ty.Integer).constant(constant.utf8.first!)
return canonicalize(litType as! ty.Integer).constant(constant.utf8.first!)
case 16:
return canonicalize(lit.type as! ty.Integer).constant(constant.utf16.first!)
return canonicalize(litType as! ty.Integer).constant(constant.utf16.first!)
case 32:
return canonicalize(lit.type as! ty.Integer).constant(constant.unicodeScalars.first!.value)
return canonicalize(litType as! ty.Integer).constant(constant.unicodeScalars.first!.value)
default:
assert(lit.type == ty.string)
return emit(constantString: constant, returnAddress: returnAddress)
Expand Down
6 changes: 3 additions & 3 deletions Sources/Core/Parser.swift
Original file line number Diff line number Diff line change
Expand Up @@ -306,7 +306,7 @@ extension Parser {
case .asm:
fatalError("Inline assembly is not yet supported")
case .file, .line, .location, .function:
return LocationDirective(directive: pos, kind: directive, type: nil, constant: nil)
return LocationDirective(directive: pos, kind: directive, type: nil, constant: nil, conversion: nil)
}
default:
return parseType(allowPolyType: allowPolyOrVariadicType, allowVariadic: allowPolyOrVariadicType)
Expand Down Expand Up @@ -957,9 +957,9 @@ extension Parser {

mutating func parseCaseClause() -> CaseClause {
let keyword = eatToken()
var match: Expr?
var match: [Expr] = []
if tok != .colon {
match = parseExpr()
match = parseExprList()
}
let colon = expect(.colon)
let body = parseStmtList()
Expand Down
1 change: 0 additions & 1 deletion Sources/Core/Scanner.swift
Original file line number Diff line number Diff line change
Expand Up @@ -579,7 +579,6 @@ func isDigit(_ ch: Unicode.Scalar) -> Bool {
}

func digitVal(_ ch: Unicode.Scalar) -> Int {

if "0" <= ch && ch <= "9" {
return Int(ch.value - UnicodeScalar("0")!.value)
}
Expand Down
5 changes: 3 additions & 2 deletions Sources/Core/generated/Copy.generated.swift
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@ func copy(_ nodes: [Call]) -> [Call] {
func copy(_ node: CaseClause) -> CaseClause {
return CaseClause(
keyword: node.keyword,
match: node.match.map(copy),
match: copy(node.match),
colon: node.colon,
block: copy(node.block),
label: node.label
Expand Down Expand Up @@ -488,7 +488,8 @@ func copy(_ node: LocationDirective) -> LocationDirective {
directive: node.directive,
kind: node.kind,
type: node.type,
constant: node.constant
constant: node.constant,
conversion: node.conversion
)
}

Expand Down
8 changes: 8 additions & 0 deletions Sources/Core/generated/Flags.generated.swift
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,14 @@ extension Options {
var isTestMode: Bool {
return flags.contains(.testMode)
}

var isShared: Bool {
return flags.contains(.shared)
}

var isDynamicLib: Bool {
return flags.contains(.dynamicLib)
}
}

extension ty.Function {
Expand Down

0 comments on commit 9a983c1

Please sign in to comment.