Skip to content

Commit 43d4d9d

Browse files
author
Samuel Groß
committed
CodeGenerator refactoring and more splicing
CodeGenerators are proper structs now and can specify required inputs and the context in which they can run. Also, code generation now often does splicing instead of always running a code generator.
1 parent b4d7e7a commit 43d4d9d

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

45 files changed

+1629
-1331
lines changed
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
// Copyright 2020 Google LLC
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// https://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
protocol GeneratorAdapter {
16+
func run(in b: ProgramBuilder, with inputs: [Variable])
17+
}
18+
19+
public typealias GeneratorFuncNoArgs = (ProgramBuilder) -> ()
20+
fileprivate struct GeneratorAdapterNoArgs: GeneratorAdapter {
21+
let f: GeneratorFuncNoArgs
22+
func run(in b: ProgramBuilder, with inputs: [Variable]) {
23+
return f(b)
24+
}
25+
}
26+
27+
public typealias GeneratorFunc1Arg = (ProgramBuilder, Variable) -> ()
28+
fileprivate struct GeneratorAdapter1Arg: GeneratorAdapter {
29+
let f: GeneratorFunc1Arg
30+
func run(in b: ProgramBuilder, with inputs: [Variable]) {
31+
return f(b, inputs[0])
32+
}
33+
}
34+
35+
public typealias GeneratorFunc2Args = (ProgramBuilder, Variable, Variable) -> ()
36+
fileprivate struct GeneratorAdapter2Args: GeneratorAdapter {
37+
let f: GeneratorFunc2Args
38+
func run(in b: ProgramBuilder, with inputs: [Variable]) {
39+
return f(b, inputs[0], inputs[1])
40+
}
41+
}
42+
43+
public struct CodeGenerator {
44+
/// The name of this code generator
45+
public let name: String
46+
47+
/// Types of input variables that are required for
48+
/// this code generator to run.
49+
public let inputTypes: [Type]
50+
51+
/// The contexts in which this code generator can run.
52+
/// This code generator will only be executed if requiredContext.isSubset(of: currentContext)
53+
public let requiredContext: ProgramContext
54+
55+
/// Warpper around the actual generator function called.
56+
private let adapter: GeneratorAdapter
57+
58+
private init(name: String, inputTypes: [Type], context: ProgramContext = .any, adapter: GeneratorAdapter) {
59+
self.name = name
60+
self.inputTypes = inputTypes
61+
self.requiredContext = context
62+
self.adapter = adapter
63+
}
64+
65+
/// Execute this code generator, generating new code at the current position in the ProgramBuilder.
66+
public func run(in b: ProgramBuilder, with inputs: [Variable]) {
67+
return adapter.run(in: b, with: inputs)
68+
}
69+
70+
public init(_ name: String, inContext context: ProgramContext = .global, _ f: @escaping GeneratorFuncNoArgs) {
71+
self.init(name: name, inputTypes: [], context: context, adapter: GeneratorAdapterNoArgs(f: f))
72+
}
73+
74+
public init(_ name: String, inContext context: ProgramContext = .global, input type: Type, _ f: @escaping GeneratorFunc1Arg) {
75+
self.init(name: name, inputTypes: [type], context: context, adapter: GeneratorAdapter1Arg(f: f))
76+
}
77+
78+
public init(_ name: String, inContext context: ProgramContext = .global, inputs types: (Type, Type), _ f: @escaping GeneratorFunc2Args) {
79+
self.init(name: name, inputTypes: [types.0, types.1], context: context, adapter: GeneratorAdapter2Args(f: f))
80+
}
81+
}

0 commit comments

Comments
 (0)