-
Notifications
You must be signed in to change notification settings - Fork 7
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
Add include_file statement #74
Changes from 11 commits
79ef1e9
214aa8a
e3f773e
2a15e48
dd483e4
497328e
650dedf
f9d1e6e
53af53c
ed06f64
8ce7cf6
da4fbee
fe63a24
5bd1855
393213a
70631c3
39471ee
b9d959e
4735259
e306632
94cdb51
2bef7be
6b460e9
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -174,7 +174,9 @@ assertEquals(onePlusOne, anotherOnePlusOne) | |
// Top level | ||
type_universe ::= <stmt>... | ||
definition ::= '(' 'define' symbol <domain_definition> ')' | ||
stmt ::= <definition> | <transform> | ||
stmt ::= <definition> | <transform> | <include_file> | ||
|
||
include_file ::= `(include_file <path-to-file>)` | ||
|
||
// Domain | ||
domain_definition ::= <domain> | <permute_domain> | ||
|
@@ -400,6 +402,43 @@ Unlike record elements, product element defintions must include identifiers. | |
(product int_pair first::int second::int) | ||
``` | ||
|
||
#### Type Domain Includes | ||
|
||
It is possible to split type universes among multiple files, which allows type domains defined in another project to be | ||
permuted. For example: | ||
|
||
``` | ||
// root.ion: | ||
(include_file "sibling.ion") | ||
(include_file "sub-dir/thing.ion") | ||
(include_file "/other-project/toy-ast.ion") | ||
``` | ||
|
||
While discussing further details, it is helpful to introduce two terms: an "includer" is a file which includes another | ||
using `include_file`, and the "includee" is a file which is included. | ||
|
||
The `root.ion` universe will contain all type domains from all includees and may still define additional type domains | ||
of its own. | ||
|
||
`include_file` statements are allowed in includees. Any attempt to include a file that has already been seen will be | ||
ignored. | ||
|
||
When resolving the file to include, the following locations are searched: | ||
|
||
- The directory containing the includer (if the path to the includee does not start with `/`) | ||
- The directory containing the "main" type universe that was passed to `pig` on the command-line. | ||
- Any directories specified with the `--include` or `-I` arguments, in the order they were specified. | ||
|
||
The first matching file found wins and any other matching files ignored. | ||
|
||
Note that paths starting with `/` do not actually refer to the root of any file system, but instead are treated as | ||
relative to the include directories. | ||
dlurton marked this conversation as resolved.
Show resolved
Hide resolved
Comment on lines
+434
to
+435
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The prefix There are two slightly distinct types of inclusion:
I see from the previous discussions on this issue that a formal idea of an |
||
|
||
Paths specified with `include_file` may only contain alphanumeric or one of the following characters: | ||
`-`, `_`, `.` or `/`. Additionally, two consecutive periods ".." (i.e. a parent directory) are not allowed. | ||
|
||
Lastly, `include_file` can only be used at the top-level within a `.ion` file. It is not allowed anywhere within a | ||
`(domain ...)` clause. | ||
alancai98 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
#### Using PIG In Your Project | ||
|
||
|
@@ -408,16 +447,14 @@ Unlike record elements, product element defintions must include identifiers. | |
At build time and before compilation of your application or library, the following should be executed: | ||
|
||
``` | ||
pig \ | ||
-u <type universe.ion> \ | ||
-t kotlin \ | ||
-n <namespace> \ | ||
-o path/to/package/<output file> | ||
pig -u <type universe.ion> -t kotlin -n <namespace> -o <path/to/output_file> [ -I <path-to-include-dir> ] | ||
``` | ||
|
||
- `<type universe.ion>`: path to the Ion text file containing the type universe | ||
- `<output file>`: path to the file for the generated code | ||
- `<path/to/output_file>`: path to the file for the generated code | ||
- `<namespace>`: the name used in the `package` statement at the top of the output file | ||
- `<path-to-include-dir>`: search path to external include directory (optional). Can be specified more than once, | ||
i.e. `pig ... -I <dir1> -I <dir2> -I <dir3>` | ||
|
||
Execute: `pig --help` for all command-line options. | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
/* | ||
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"). | ||
* You may not use this file except in compliance with the License. | ||
* A copy of the License is located at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* or in the "license" file accompanying this file. This file is distributed | ||
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either | ||
* express or implied. See the License for the specific language governing | ||
* permissions and limitations under the License. | ||
*/ | ||
|
||
package org.partiql.pig.domain.include | ||
|
||
import org.partiql.pig.domain.model.Statement | ||
import org.partiql.pig.domain.parser.TypeUniverseParser | ||
import java.nio.file.FileSystem | ||
import java.nio.file.Files | ||
import java.nio.file.Path | ||
|
||
/** | ||
* Prevents cycles in files included with the `include_file` statement from becoming a problem. | ||
* | ||
* This is accomplished by keeping track of all files "seen" by the parser and then making any attempt to | ||
* include a file that was previously seen a no-op. | ||
* | ||
* @param mainTypeUniversePath The path to the main type universe that was passed on the command-line. This is the | ||
* first "seen" file and does not require resolution because the user gave an explicit path to its location. | ||
* | ||
* @param resolver For identifying the full path to the file to be included. | ||
* | ||
* @see IncludeResolver | ||
* @see FileSystem | ||
*/ | ||
internal class IncludeCycleHandler( | ||
mainTypeUniversePath: Path, | ||
private val resolver: IncludeResolver | ||
) { | ||
private val seenFiles = HashSet<Path>().apply { add(mainTypeUniversePath.toAbsolutePath().normalize()) } | ||
|
||
/** | ||
* Parses a universe file included with `include_file`. | ||
* | ||
* The return value is a [List] of [Statement]s that make up the type universe file. | ||
* | ||
* This function becomes a no-op in the event that the [includee] has been seen previously: an | ||
* empty [List] is is returned instead of the file being parsed again. | ||
dlurton marked this conversation as resolved.
Show resolved
Hide resolved
|
||
* | ||
* @param includeePath The file requested to be included. | ||
* @param includerPath The file in which the includee is to be included. | ||
*/ | ||
fun parseIncludedTypeUniverse(includeePath: String, includerPath: Path): List<Statement> { | ||
|
||
val resolvedIncludeFile = resolver.resolve(resolver.fileSystem.getPath(includeePath), includerPath) | ||
|
||
return if(!seenFiles.contains(resolvedIncludeFile)) { | ||
seenFiles.add(resolvedIncludeFile) | ||
Files.newInputStream(resolvedIncludeFile).use { | ||
val source = InputSource(resolvedIncludeFile, it) | ||
val parser = TypeUniverseParser(source, this) | ||
parser.parse() | ||
}.statements | ||
} else { | ||
listOf() | ||
} | ||
} | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
/* | ||
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"). | ||
* You may not use this file except in compliance with the License. | ||
* A copy of the License is located at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* or in the "license" file accompanying this file. This file is distributed | ||
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either | ||
* express or implied. See the License for the specific language governing | ||
* permissions and limitations under the License. | ||
*/ | ||
|
||
package org.partiql.pig.domain.include | ||
|
||
import java.lang.Exception | ||
|
||
/** Thrown by [IncludeResolver] to indicate that it cannot locate an include file. */ | ||
class IncludeResolutionException( | ||
val inputFilePathString: String, | ||
val consideredFilePaths: List<String> | ||
dlurton marked this conversation as resolved.
Show resolved
Hide resolved
|
||
) : Exception("Could not locate include file '$inputFilePathString' in any considered path") | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You may also want to add a point here explicitly specifying the behavior of
/
i.e. all other directories are searched except the parent directory.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I thought this was covered on line 428:
What can I do to make this clearer?