Skip to content

Commit

Permalink
Merge pull request #32 from kntkymt/fix/node-struct
Browse files Browse the repository at this point in the history
リファクタ: Nodeの`init`から`sourceToken: `ではなく各Tokenを個別に受け取る
  • Loading branch information
kntkymt authored Jan 7, 2024
2 parents 8cfcd30 + f3b8a9b commit 770c6d6
Show file tree
Hide file tree
Showing 17 changed files with 1,314 additions and 813 deletions.
72 changes: 54 additions & 18 deletions Sources/Generator/Generator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -43,17 +43,25 @@ public final class Generator {
public func generate(sourceFileNode: SourceFileNode) throws -> String {

var dataSection = ""
if !sourceFileNode.globalVariables.isEmpty {
dataSection += ".section __DATA,__data\n"
for variableDecl in sourceFileNode.globalVariables {
dataSection += try generateGlobalVariableDecl(node: variableDecl)
}
}

var functionDeclResult = ""
for functionDecl in sourceFileNode.functions {
functionDeclResult += ".p2align 2\n"
functionDeclResult += try generate(node: functionDecl)
for statement in sourceFileNode.statements {
switch statement.item.kind {
case .variableDecl:
if dataSection.isEmpty {
dataSection += ".section __DATA,__data\n"
}

let casted = try statement.item.casted(VariableDeclNode.self)
dataSection += try generateGlobalVariableDecl(node: casted)

case .functionDecl:
let casted = try statement.item.casted(FunctionDeclNode.self)
functionDeclResult += ".p2align 2\n"
functionDeclResult += try generate(node: casted)

default:
throw GenerateError.invalidSyntax(index: statement.sourceTokens.first!.sourceIndex)
}
}

let functionMeta = ".globl \(functionLabels.joined(separator: ", "))\n"
Expand Down Expand Up @@ -95,7 +103,7 @@ public final class Generator {
case .prefixOperatorExpr:
let prefixOperatorExpr = try initializerExpr.casted(PrefixOperatorExpressionNode.self)
if prefixOperatorExpr.operatorKind == .address {
let value = try prefixOperatorExpr.right.casted(IdentifierNode.self).identifierName
let value = try prefixOperatorExpr.expression.casted(IdentifierNode.self).identifierName
result += " .quad \(value)\n"
} else {
throw GenerateError.invalidSyntax(index: initializerExpr.sourceTokens.first!.sourceIndex)
Expand All @@ -107,7 +115,7 @@ public final class Generator {
func generateAddressValue(referenceNode: any NodeProtocol, integerLiteralNode: any NodeProtocol) -> String? {
if let prefix = referenceNode as? PrefixOperatorExpressionNode,
prefix.operatorKind == .address,
let identifier = prefix.right as? IdentifierNode,
let identifier = prefix.expression as? IdentifierNode,
let binaryOperator = infixOperator.operator as? BinaryOperatorNode,
(binaryOperator.operatorKind == .add || binaryOperator.operatorKind == .sub),
let integerLiteral = integerLiteralNode as? IntegerLiteralNode {
Expand Down Expand Up @@ -217,6 +225,10 @@ public final class Generator {

return result

case .exprListItem:
let casted = try node.casted(ExpressionListItemNode.self)
return try generate(node: casted.expression)

case .functionDecl:
let casted = try node.casted(FunctionDeclNode.self)

Expand Down Expand Up @@ -394,7 +406,7 @@ public final class Generator {
case .blockStatement:
let casted = try node.casted(BlockStatementNode.self)

for statement in casted.statements {
for statement in casted.items {
result += try generate(node: statement)

// 次のstmtに行く前に今のstmtの最終結果を消す
Expand All @@ -404,6 +416,11 @@ public final class Generator {

return result

case .blockItem:
let casted = try node.casted(BlockItemNode.self)

return try generate(node: casted.item)

case .returnStatement:
let casted = try node.casted(ReturnStatementNode.self)

Expand Down Expand Up @@ -518,20 +535,39 @@ public final class Generator {

return result

case .tupleExpr:
let casted = try node.casted(TupleExpressionNode.self)
return try generate(node: casted.expression)

case .prefixOperatorExpr:
let casted = try node.casted(PrefixOperatorExpressionNode.self)

switch casted.operatorKind {
case .plus:
// +は影響がないのでそのまま
result += try generate(node: casted.expression)

case .minus:
result += try generate(node: casted.expression)

result += " ldr x0, [sp]\n"
result += " add sp, sp, #16\n"

// 符号反転
result += " neg x0, x0\n"

result += " str x0, [sp, #-16]!\n"

case .reference:
// *のあとはどんな値でも良い
result += try generate(node: casted.right)
result += try generate(node: casted.expression)

// 値をロードしてpush
result += " ldr x0, [sp]\n"
result += " add sp, sp, #16\n"

// 値をアドレスとして読み、アドレスが指す値をロード
if let identifier = casted.right as? IdentifierNode, isElementOrReferenceTypeMemorySizeOf(1, identifierName: identifier.identifierName) {
if let identifier = casted.expression as? IdentifierNode, isElementOrReferenceTypeMemorySizeOf(1, identifierName: identifier.identifierName) {
result += " ldrb w0, [x0]\n"
} else {
result += " ldr x0, [x0]\n"
Expand All @@ -541,7 +577,7 @@ public final class Generator {

case .address:
// &のあとは変数しか入らない(はず?)
if let right = casted.right as? IdentifierNode {
if let right = casted.expression as? IdentifierNode {
result += try generatePushVariableAddress(node: right)
} else {
throw GenerateError.invalidSyntax(index: node.sourceTokens[0].sourceIndex)
Expand All @@ -558,7 +594,7 @@ public final class Generator {
if casted.left is IdentifierNode {
result += try generatePushVariableAddress(node: casted.left.casted(IdentifierNode.self))
} else if let pointer = casted.left as? PrefixOperatorExpressionNode, pointer.operatorKind == .reference {
result += try generate(node: pointer.right)
result += try generate(node: pointer.expression)
} else if let subscriptCall = casted.left as? SubscriptCallExpressionNode {
result += try generatePushArrayElementAddress(node: subscriptCall)
} else {
Expand All @@ -577,7 +613,7 @@ public final class Generator {
// assign
if let identifier = casted.left as? IdentifierNode, getVariableType(name: identifier.identifierName)?.memorySize == 1 {
result += " strb w0, [x1]\n"
} else if let pointer = casted.left as? PrefixOperatorExpressionNode, pointer.operatorKind == .reference, let identifier = pointer.right as? IdentifierNode, isElementOrReferenceTypeMemorySizeOf(1, identifierName: identifier.identifierName) {
} else if let pointer = casted.left as? PrefixOperatorExpressionNode, pointer.operatorKind == .reference, let identifier = pointer.expression as? IdentifierNode, isElementOrReferenceTypeMemorySizeOf(1, identifierName: identifier.identifierName) {
result += " strb w0, [x1]\n"
} else if let subscriptCall = casted.left as? SubscriptCallExpressionNode,
isElementOrReferenceTypeMemorySizeOf(1, identifierName: subscriptCall.identifierNode.identifierName) {
Expand Down
143 changes: 108 additions & 35 deletions Sources/Parser/Node/ExpressionNode.swift
Original file line number Diff line number Diff line change
Expand Up @@ -4,29 +4,36 @@ public class InfixOperatorExpressionNode: NodeProtocol {

// MARK: - Property

public var kind: NodeKind = .infixOperatorExpr

public var left: any NodeProtocol
public var right: any NodeProtocol

public var `operator`: any NodeProtocol
public let kind: NodeKind = .infixOperatorExpr
public var sourceTokens: [Token] {
left.sourceTokens + `operator`.sourceTokens + right.sourceTokens
}
public var children: [any NodeProtocol] {
[left, `operator`, right]
}

public let sourceTokens: [Token]
public var children: [any NodeProtocol] { [left, right, `operator`] }
public let left: any NodeProtocol
public let `operator`: any NodeProtocol
public let right: any NodeProtocol

// MARK: - Initializer

init(operator: any NodeProtocol, left: any NodeProtocol, right: any NodeProtocol, sourceTokens: [Token]) {
self.operator = `operator`
public init(left: any NodeProtocol, operator: any NodeProtocol, right: any NodeProtocol) {
self.left = left
self.operator = `operator`
self.right = right
self.sourceTokens = sourceTokens
}
}

public class PrefixOperatorExpressionNode: NodeProtocol {

public enum OperatorKind {
/// `+`
case plus

/// `-`
case minus

/// `*`
case reference

Expand All @@ -36,10 +43,23 @@ public class PrefixOperatorExpressionNode: NodeProtocol {

// MARK: - Property

public var kind: NodeKind = .prefixOperatorExpr
public let kind: NodeKind = .prefixOperatorExpr
public var sourceTokens: [Token] {
[`operator`] + expression.sourceTokens
}
public var children: [any NodeProtocol] { [expression] }

public let `operator`: Token
public let expression: any NodeProtocol

public var operatorKind: OperatorKind {
switch `operator` {
case .reserved(.add, _):
return .plus

case .reserved(.sub, _):
return .minus

case .reserved(.mul, _):
return .reference

Expand All @@ -51,51 +71,50 @@ public class PrefixOperatorExpressionNode: NodeProtocol {
}
}

public let sourceTokens: [Token]
public var children: [any NodeProtocol] { [right] }
public let `operator`: Token

public let right: any NodeProtocol

// MARK: - Initializer

init(operator: Token, right: any NodeProtocol, sourceTokens: [Token]) {
public init(operator: Token, expression: any NodeProtocol) {
self.operator = `operator`
self.right = right
self.sourceTokens = sourceTokens
self.expression = expression
}
}

public class FunctionCallExpressionNode: NodeProtocol {

// MARK: - Property

public var kind: NodeKind = .functionCallExpr
public let sourceTokens: [Token]
public let kind: NodeKind = .functionCallExpr
public var sourceTokens: [Token] {
[identifierToken, parenthesisLeftToken] + arguments.flatMap { $0.sourceTokens } + [parenthesisRightToken]
}
public var children: [any NodeProtocol] { arguments }

public let token: Token
public let arguments: [any NodeProtocol]
public let identifierToken: Token
public let parenthesisLeftToken: Token
public let arguments: [ExpressionListItemNode]
public let parenthesisRightToken: Token

public var functionName: String {
token.value
identifierToken.value
}

// MARK: - Initializer

init(token: Token, arguments: [any NodeProtocol], sourceTokens: [Token]) {
self.token = token
public init(identifierToken: Token, parenthesisLeftToken: Token, arguments: [ExpressionListItemNode], parenthesisRightToken: Token) {
self.identifierToken = identifierToken
self.parenthesisLeftToken = parenthesisLeftToken
self.arguments = arguments
self.sourceTokens = sourceTokens
self.parenthesisRightToken = parenthesisRightToken
}
}

public class SubscriptCallExpressionNode: NodeProtocol {

// MARK: - Property

public var kind: NodeKind = .subscriptCallExpr
public let kind: NodeKind = .subscriptCallExpr
public var sourceTokens: [Token] { identifierNode.sourceTokens + [squareLeftToken] + argument.sourceTokens + [squareRightToken] }
public var children: [any NodeProtocol] { [argument] }
public var children: [any NodeProtocol] { [identifierNode, argument] }

public let identifierNode: IdentifierNode
public let squareLeftToken: Token
Expand All @@ -116,19 +135,73 @@ public class ArrayExpressionNode: NodeProtocol {

// MARK: - Property

public var kind: NodeKind = .arrayExpr
public var children: [any NodeProtocol] { return exprListNodes.flatMap { $0.children } }
public let kind: NodeKind = .arrayExpr
public var sourceTokens: [Token] { return [braceLeft] + exprListNodes.flatMap { $0.sourceTokens } + [braceRight] }
public var children: [any NodeProtocol] { return exprListNodes.flatMap { $0.children } }

public let braceLeft: Token
public let exprListNodes: [any NodeProtocol]
public let exprListNodes: [ExpressionListItemNode]
public let braceRight: Token

// MARK: - Initializer

public init(braceLeft: Token, exprListNodes: [any NodeProtocol], braceRight: Token) {
public init(braceLeft: Token, exprListNodes: [ExpressionListItemNode], braceRight: Token) {
self.braceLeft = braceLeft
self.exprListNodes = exprListNodes
self.braceRight = braceRight
}
}

public class ExpressionListItemNode: NodeProtocol {

// MARK: - Property

public let kind: NodeKind = .exprListItem
public var sourceTokens: [Token] {
var result = expression.sourceTokens

if let comma {
result += [comma]
}

return result
}
public var children: [any NodeProtocol] {
[expression]
}

public let expression: any NodeProtocol
public let comma: Token?

// MARK: - Initializer

public init(expression: any NodeProtocol, comma: Token? = nil) {
self.expression = expression
self.comma = comma
}
}

public class TupleExpressionNode: NodeProtocol {

// MARK: - Property

public let kind: NodeKind = .tupleExpr
public var sourceTokens: [Token] {
[parenthesisLeftToken] + expression.sourceTokens + [parenthesisRightToken]
}
public var children: [any NodeProtocol] {
[expression]
}

public let parenthesisLeftToken: Token
public let expression: any NodeProtocol
public let parenthesisRightToken: Token

// MARK: - Initializer

public init(parenthesisLeftToken: Token, expression: any NodeProtocol, parenthesisRightToken: Token) {
self.parenthesisLeftToken = parenthesisLeftToken
self.expression = expression
self.parenthesisRightToken = parenthesisRightToken
}
}
Loading

0 comments on commit 770c6d6

Please sign in to comment.