Skip to content

Commit

Permalink
Add templating and template ASTPass.swift (#15)
Browse files Browse the repository at this point in the history
* reformat ASTPass.swift to single lines

* add test jinja2 template

* add .derived-sources to gitignore and update Package.swift to include derived source

* added codegen using jinja2

* turn codegen into a node package and add to top level module

* add generate target to makefile

* pre-refactor extraction

* rename enumCase => enumMember

* rename literalToken => token

* fix travis yaml
  • Loading branch information
nvgrw committed Oct 11, 2018
1 parent 1184967 commit b3ebccd
Show file tree
Hide file tree
Showing 14 changed files with 2,428 additions and 512 deletions.
2 changes: 2 additions & 0 deletions .gitignore
@@ -1,7 +1,9 @@
.DS_Store
/.build
/.derived-sources
/Packages
/*.xcodeproj
/node_modules
Package.resolved

*.sol
Expand Down
1 change: 1 addition & 0 deletions .travis.yml
Expand Up @@ -9,6 +9,7 @@ matrix:
- sudo add-apt-repository -y ppa:ethereum/ethereum
- sudo apt-get update
- sudo apt-get -y install solc
- npm install
- npm install -g truffle
- eval "$(curl -sL https://swiftenv.fuller.li/install.sh)"
- git clone https://github.com/realm/SwiftLint.git /tmp/swiftlint
Expand Down
10 changes: 7 additions & 3 deletions Makefile
@@ -1,8 +1,10 @@
all:
all: generate
swift build
cp -r stdlib .build/debug/

release:
.PHONY: all release zip test lint generate

release: generate
swift build -c release --static-swift-stdlib
cp -r stdlib .build/release/

Expand All @@ -15,6 +17,8 @@ test: lint release
cd Tests/BehaviorTests && ./compile_behavior_tests.sh
swift run -c release lite

.PHONY: lint
lint:
swiftlint lint

generate:
./utils/codegen/codegen.js
4 changes: 3 additions & 1 deletion Package.swift
Expand Up @@ -39,7 +39,9 @@ let package = Package(
"Source",
"Diagnostic",
"Lexer",
]
],
exclude: ["ASTPass/ASTPass.template.swift"],
sources: [".", "../../.derived-sources/AST"]
),
.target(
name: "Parser",
Expand Down
490 changes: 0 additions & 490 deletions Sources/AST/ASTPass/ASTPass.swift

This file was deleted.

104 changes: 104 additions & 0 deletions Sources/AST/ASTPass/ASTPass.template.swift
@@ -0,0 +1,104 @@
// swiftlint:disable all
//
// ASTPass.swift
// AST
//
// Created by Franklin Schrans on 1/11/18.
//
import Diagnostic
import Lexer

/// A pass over an AST.
///
/// The class `ASTVisitor` is used to visit an AST using a given `ASTPass`. The appropriate `process` function will be
/// called when visiting a node, and `postProcess` will be called after visiting the children of that node.
public protocol ASTPass {
{# Modules #}
{%- set nodes = [
"TopLevelModule"
] -%}

{# Declarations #}
{%- set nodes = nodes.concat([
"TopLevelDeclaration",
"ContractDeclaration",
"StructDeclaration",
"EnumDeclaration",
"TraitDeclaration",
"ContractBehaviorDeclaration"
]) -%}

{# Members #}
{%- set nodes = nodes.concat([
"ContractMember",
"StructMember",
"EnumMember",
"TraitMember",
"ContractBehaviorMember"
]) -%}

{# Statements #}
{%- set nodes = nodes.concat([
"Statement",
"ReturnStatement",
"BecomeStatement",
"EmitStatement",
"IfStatement",
"ForStatement"
]) -%}

{# Declarations #}
{%- set nodes = nodes.concat([
"VariableDeclaration",
"FunctionDeclaration",
"FunctionSignatureDeclaration",
"SpecialDeclaration",
"SpecialSignatureDeclaration",
"EventDeclaration"
]) -%}

{# Expression #}
{%- set nodes = nodes.concat([
"Expression",
"InoutExpression",
"BinaryExpression",
"FunctionCall",
"ArrayLiteral",
"DictionaryLiteral",
"RangeExpression",
"SubscriptExpression",
"AttemptExpression"
]) -%}

{# Components #}
{%- set nodes = nodes.concat([
"Attribute",
"Parameter",
"TypeAnnotation",
"Identifier",
"Type",
"Token",
"CallerProtection",
"TypeState",
"Conformance",
"FunctionArgument"
]) -%}

{%- for node in nodes %}
func process({{ node | camelCase }}: {{ node }}, passContext: ASTPassContext) -> ASTPassResult<{{ node }}>
func postProcess({{ node | camelCase }}: {{ node }}, passContext: ASTPassContext) -> ASTPassResult<{{ node }}>
{% endfor %}
}

extension ASTPass {
{%- for node in nodes %}
public func process({{ node | camelCase }}: {{ node }}, passContext: ASTPassContext) -> ASTPassResult<{{ node }}> {
return ASTPassResult(element: {{ node | camelCase }}, diagnostics: [], passContext: passContext)
}

public func postProcess({{ node | camelCase }}: {{ node }}, passContext: ASTPassContext) -> ASTPassResult<{{ node }}> {
return ASTPassResult(element: {{ node | camelCase }}, diagnostics: [], passContext: passContext)
}
{% endfor %}
}
// swiftlint:enable all
8 changes: 4 additions & 4 deletions Sources/AST/ASTVisitor/ASTVisitor.swift
Expand Up @@ -295,13 +295,13 @@ public struct ASTVisitor {
}

func visit(_ enumCase: EnumMember, passContext: ASTPassContext) -> ASTPassResult<EnumMember> {
var processResult = pass.process(enumCase: enumCase, passContext: passContext)
var processResult = pass.process(enumMember: enumCase, passContext: passContext)

processResult.element.identifier =
processResult.combining(visit(processResult.element.identifier,
passContext: processResult.passContext))

let postProcessResult = pass.postProcess(enumCase: processResult.element, passContext: processResult.passContext)
let postProcessResult = pass.postProcess(enumMember: processResult.element, passContext: processResult.passContext)
return ASTPassResult(element: postProcessResult.element,
diagnostics: processResult.diagnostics + postProcessResult.diagnostics,
passContext: postProcessResult.passContext)
Expand Down Expand Up @@ -974,8 +974,8 @@ public struct ASTVisitor {
}

func visit(_ literalToken: Token, passContext: ASTPassContext) -> ASTPassResult<Token> {
let processResult = pass.process(literalToken: literalToken, passContext: passContext)
let postProcessResult = pass.process(literalToken: processResult.element, passContext: processResult.passContext)
let processResult = pass.process(token: literalToken, passContext: passContext)
let postProcessResult = pass.process(token: processResult.element, passContext: processResult.passContext)
return ASTPassResult(element: postProcessResult.element,
diagnostics: postProcessResult.diagnostics,
passContext: passContext)
Expand Down
10 changes: 5 additions & 5 deletions Sources/SemanticAnalyzer/SemanticAnalyzer+Components.swift
Expand Up @@ -188,13 +188,13 @@ extension SemanticAnalyzer {
return ASTPassResult(element: conformance, diagnostics: diagnostics, passContext: passContext)
}

public func process(literalToken: Token, passContext: ASTPassContext) -> ASTPassResult<Token> {
public func process(token: Token, passContext: ASTPassContext) -> ASTPassResult<Token> {
var diagnostics = [Diagnostic]()
if case .literal(let token) = literalToken.kind,
case .address(let address) = token,
if case .literal(let tokenKind) = token.kind,
case .address(let address) = tokenKind,
address.count != 42 {
diagnostics.append(.invalidAddressLiteral(literalToken))
diagnostics.append(.invalidAddressLiteral(token))
}
return ASTPassResult(element: literalToken, diagnostics: diagnostics, passContext: passContext)
return ASTPassResult(element: token, diagnostics: diagnostics, passContext: passContext)
}
}
18 changes: 9 additions & 9 deletions Sources/SemanticAnalyzer/SemanticAnalyzer+Declarations.swift
Expand Up @@ -181,22 +181,22 @@ extension SemanticAnalyzer {
return ASTPassResult(element: enumDeclaration, diagnostics: diagnostics, passContext: passContext)
}

public func process(enumCase: EnumMember, passContext: ASTPassContext) -> ASTPassResult<EnumMember> {
public func process(enumMember: EnumMember, passContext: ASTPassContext) -> ASTPassResult<EnumMember> {
var diagnostics = [Diagnostic]()
let environment = passContext.environment!

if let conflict = environment.conflictingPropertyDeclaration(for: enumCase.identifier,
in: enumCase.type.rawType.name) {
diagnostics.append(.invalidRedeclaration(enumCase.identifier, originalSource: conflict))
if let conflict = environment.conflictingPropertyDeclaration(for: enumMember.identifier,
in: enumMember.type.rawType.name) {
diagnostics.append(.invalidRedeclaration(enumMember.identifier, originalSource: conflict))
}

if enumCase.hiddenValue == nil {
diagnostics.append(.cannotInferHiddenValue(enumCase.identifier, enumCase.hiddenType))
} else if case .literal(_)? = enumCase.hiddenValue {} else {
diagnostics.append(.invalidHiddenValue(enumCase))
if enumMember.hiddenValue == nil {
diagnostics.append(.cannotInferHiddenValue(enumMember.identifier, enumMember.hiddenType))
} else if case .literal(_)? = enumMember.hiddenValue {} else {
diagnostics.append(.invalidHiddenValue(enumMember))
}

return ASTPassResult(element: enumCase, diagnostics: diagnostics, passContext: passContext)
return ASTPassResult(element: enumMember, diagnostics: diagnostics, passContext: passContext)
}

func isContractTraitMember(member: TraitMember) -> Bool {
Expand Down

0 comments on commit b3ebccd

Please sign in to comment.