Repository: SuperV1234/camomilla Branch: master Commit: aebe89ed3b07 Files: 14 Total size: 94.0 KB Directory structure: gitextract_204tk01w/ ├── .gitignore ├── LICENSE ├── README.md ├── camomilla ├── config_files/ │ ├── ecst_namespaces.json │ ├── ecst_namespaces_inner.json │ ├── generic.json │ └── namespaces.json ├── example_errors/ │ ├── 0_clang_after.txt │ ├── 0_clang_before.txt │ ├── 0_gcc_after.txt │ └── 0_gcc_before.txt ├── print_edge_cases.sh └── setup.py ================================================ FILE CONTENTS ================================================ ================================================ FILE: .gitignore ================================================ # Byte-compiled / optimized / DLL files __pycache__/ *.py[cod] *$py.class # C extensions *.so test.cpp temp.out # Distribution / packaging .Python env/ build/ develop-eggs/ dist/ downloads/ eggs/ .eggs/ lib/ lib64/ parts/ sdist/ var/ *.egg-info/ .installed.cfg *.egg # PyInstaller # Usually these files are written by a python script from a template # before PyInstaller builds the exe, so as to inject date/other infos into it. *.manifest *.spec # Installer logs pip-log.txt pip-delete-this-directory.txt # Unit test / coverage reports htmlcov/ .tox/ .coverage .coverage.* .cache nosetests.xml coverage.xml *,cover .hypothesis/ # Translations *.mo *.pot # Django stuff: *.log local_settings.py # Flask stuff: instance/ .webassets-cache # Scrapy stuff: .scrapy # Sphinx documentation docs/_build/ # PyBuilder target/ # IPython Notebook .ipynb_checkpoints # pyenv .python-version # celery beat schedule file celerybeat-schedule # dotenv .env # virtualenv venv/ ENV/ # Spyder project settings .spyderproject # Rope project settings .ropeproject ================================================ FILE: LICENSE ================================================ MIT License Copyright (c) 2016 Vittorio Romeo Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================ FILE: README.md ================================================ # camomilla [![license][badge.license]][license] [![gratipay][badge.gratipay]][gratipay] ![badge.python3](https://img.shields.io/badge/python-3-ff69b4.svg?style=flat-square) [badge.license]: http://img.shields.io/badge/license-mit-blue.svg?style=flat-square [badge.gratipay]: https://img.shields.io/gratipay/user/SuperV1234.svg?style=flat-square [license]: https://github.com/SuperV1234/camomilla/blob/master/LICENSE [gratipay]: https://gratipay.com/~SuperV1234/ ## What is it? `camomilla` is a simple [Python 3](http://python.org) script that simplifies errors produced by C++ compilers. It is very useful while dealing with heavily-templated code *(e.g. when using [boost::hana](http://www.boost.org/doc/libs/1_61_0/libs/hana/doc/html/index.html) or [boost::fusion](http://www.boost.org/doc/libs/1_61_0/libs/fusion/doc/html/))*. `camomilla` transforms the error text to make it easier to read. It supports *JSON configuration files* that can include each other recursively and *caches the last error* so that the user can quickly *reprocess* the original error with different transformation options. ## Example errors The table below shows the size reduction of the errors in the `example_errors` folder. The original error was generated from a real project, [ecst](http://github.com/SuperV1234/ecst), by simply mispelling a member field name in a template-heavy context. | | Bytes (original) | Bytes (after camomilla) | Relative size change | |---------------|------------------|-------------------------|----------------------| | g++ 6.1.1 | 38487 | 3680 | -90.43% | | clang++ 3.8.1 | 16856 | 2990 | -82.26% | A size reduction often means that the error is easier to pinpoint. Using `-r` *(`--reprocess`)* to incrementally "add detail" to the error is then a good approach to gather more information on its cause/origin. Here's a *(partial)* screenshot of the original `g++` error - it couldn't fit in my terminal window. ![Terminal screenshot: original error](/example_errors/gcc_before.png?raw=true) Here's the *full* screenshot of the the same error, processed by `camomilla`. ![Terminal screenshot: processed error](/example_errors/gcc_after.png?raw=true) ## Solution or workaround? `camomilla` is merely a workaround for the fact that compilers do not filter *(either automatically or through flags)* the depth of template typenames. Errors in projects making use of libraries such as `boost::hana` or `boost::fusion` therefore include a lot of "typename boilerplate" that can make the error harder to read. Library developers are sometimes forced to make use of techniques to erase the long typenames in order to simplify the errors and *decrease compilation time*: [`boost::experimental::di`](https://github.com/boost-experimental/di) is an example. I think this is something that should be addressed directly in the compilers - I've created a *feature request/bug report* both in the [GCC Bug Tracker](https://gcc.gnu.org/bugzilla/show_bug.cgi?id=71167) and in the [Clang Bug Tracker](https://llvm.org/bugs/show_bug.cgi?id=27793). ## Transformations `camomilla` performs the following text transformations: 1. **Template typename collapsing.** Nested template typenames are collapsed to a specific user-defined depth. This is the most useful transformation executed by `camomilla`. Example: ```bash echo "metavector>>::method()" | camomilla -d0 # outputs metavector::method() echo "metavector>>::method()" | camomilla -d1 # outputs metavector>::method() echo "metavector>>::method()" | camomilla -d2 # outputs metavector>>::method() echo "metavector>>::method()" | camomilla -d3 # outputs metavector>>::method() ``` This is incredibly useful when using template metaprogramming libraries, that usually internally nest a huge amount of wrappers. 2. **Namespace replacement regexes.** A simple transformation from a long namespace symbol to a shorter *(or absent)* one. ```bash echo "std::vector>" | camomilla --depth=100 # outputs vector> echo "boost::hana::tuple, boost::hana::int_c<15>>>" | camomilla -d100 # outputs bh::tuple, bh::int_c<15>>> ``` 3. **Generic replacement regexes.** ```bash echo "std::forward)>(x)" | camomilla -d100 # outputs fwd)>(x) ``` ## Usage ### Error redirection Errors produced by compilers can be easily piped into `camomilla`: ```bash # Pipe both `stdout` and `stderr` into `camomilla` g++ ./x.cpp |& camomilla -d5 ``` If `|&` is not supported by your shell or if you want to compare the original error to the processed one, using a temporary file is a good solution: ```bash # Redirect both `stdout` and `stderr` into `error.out` g++ ./x.cpp &> error.out # Process the error cat error | camomilla -d2 ``` ### Reprocessing The last processed original error is cached *(unless `--no-temp-cache` is specified)*. It is possible to reuse the source of the last error to perform different transformations, ignoring `stdin`. This is particularly useful when playing with the `--depth` parameter to get the required typename information while avoiding clutter. ```bash # Process error g++ ./x.cpp |& camomilla -d0 # Whoops! Need more typename information. camomilla -r -d1 # Still a little bit more... camomilla -r -d2 ``` ## Configuration ### Argparse-generated help ```bash usage: camomilla [-h] [--template-collapsing | --no-template-collapsing] [--namespace-replacements | --no-namespace-replacements] [--generic-replacements | --no-generic-replacements] [--process-by-line | --no-process-by-line] [--temp-cache | --no-temp-cache] [-r | --no-reprocess] [--reprocess-prev-config | --no-reprocess-prev-config] [-d X] [-c P] optional arguments: -h, --help show this help message and exit --template-collapsing | Control template collapsing --no-template-collapsing ' --namespace-replacements | Control namespace replacements --no-namespace-replacements ' --generic-replacements | Control generic replacements --no-generic-replacements ' --process-by-line | Control process by line --no-process-by-line ' --temp-cache | Control temp cache --no-temp-cache ' -r, --reprocess | Control reprocess previous source --no-reprocess ' --reprocess-prev-config | Control reprocess with previous configuration --no-reprocess-prev-config ' -d X, --depth X Template collapsing depth -c P, --config P Configuration file path(s) ``` ### Basic command-line options #### Enable/disable transformations Error text transformations can be turned on and off individually by using the following flags. All transformations are **on** by default. ```bash # Template typename collapsing (default: ON) --template-collapsing --no-template-collapsing # Namespace replacement regexes (default: ON) --namespace-replacements --no-namespace-replacements # Generic replacement regexes (default: ON) --generic-replacements --no-generic-replacements ``` #### Enable/disable temporary cache `camomilla` stores the last processed original error *(and last used configuration)* in your OS-dependant *temp folder*. This option can be controlled with: ```bash # Temporary "last error cache" (default: ON) --temp-cache --no-temp-cache ``` #### Reprocessing If an error has been cached, `camomilla` can be invoked with reprocessing options to read directly from the cache *(ignoring standard input)*: ```bash # Reprocess cached error (default: OFF) -r --reprocess --no-reprocess # Reprocess with cached configuration (default: ON) --reprocess-prev-config --no-reprocess-prev-config ``` #### Template typename collapsing options The depth of the *template typename collapsing* transformation can be specified with the `-d` *(or `--depth`)* flag. ```bash # Collapse all templates with depth `>= 5` camomilla -d5 # Collapse all templates with depth `>= 100` camomilla --depth=100 ``` #### Process by line By default, `camomilla` processes the error line by line. This behavior can be disabled *(in order to process the error all at once)* with the `--no-process-by-line` flag. ### Configuration files Configurations files are JSON documents that allow users to define their *namespace replacement regexes* and *generic replacement regexes*. They also allow users to override command-line arguments *(or set unspecified options)*. Configuration files can refer to each other recursively. #### Using configuration files Any number of configuration file paths can be passed to `camomilla` through the `-c` *(or `--config`)* flag. Configuration files are read sequentially *(the order matters for option overriding)*. ```bash # Executes `camomilla` reading `conf0.json` camomilla -c"conf0.json" # Executes `camomilla` reading `conf0.json` first, then `conf1.json` camomilla -c"conf0.json" -c"conf1.json" ``` Here's a more complex example: ```bash # Executes `camomilla` with: # * Template typename collapsing depth: 4 # * Namespace replacement regexes: off # * Reading the `~/camomilla_configs/test.json` file camomilla -d4 --no-namespace-replacements -c"~/camomilla_configs/test.json" # `test.json` may: # * Override the specified depth # * Override the specified `--no-namespace-replacements` option # * Set unspecified options (e.g. `--no-generic-replacements`) ``` #### Writing configuration files Configuration files are written in JSON. Here's an example file with complete syntax: ```javascript { // Set/override options "enableTemplateCollapsing": false, "enableNamespaceReplacements": false, "enableTuplePairReplacements": false, "enableGenericReplacements": false, "templateCollapsingDepth": 10, // Add namespace replacements "namespaceReplacements": [ "std": "", "boost::hana": "bh", "boost::fusion": "bf", "boost::spirit": "bs", ], // Add generic replacements "genericReplacements" : [ "tuple": "tpl", "forward": "fwd" ], // Include other config files "configPaths": [ "~/camomilla_configs/boost_spirit.json", "~/camomilla_configs/limit_template_depth.json" ] } ``` #### Multiple configuration files When multiple configuration files are passed as command-line arguments, or if any configuration file "includes" another file, the behavior is as follows: * Options, such as `enableTemplateCollapsing` or `templateCollapsingDepth`, are **overridden** or set. * Previously set options will be potentially overwritten by the next configuration file(s). * Namespace replacements and generic replacements will be **accumulated** or **overridden**. * If a configuration file has a replacement with the same key as a previous one, its value will be overridden. * If a configuration file defines a replacement that wasn't previously seen, it will be added without replacing any existing replacement. ================================================ FILE: camomilla ================================================ #!/usr/bin/env python3 # Copyright (c) 2016-2017 Vittorio Romeo # License: MIT License # MIT License page: https://opensource.org/licenses/MIT # http://vittorioromeo.info | vittorio.romeo@outlook.com import os import sys import re import argparse import json import tempfile import time # # # # ----------------------------------------------------------------------------------------------------------- # Configuration keys # ----------------------------------------------------------------------------------------------------------- # Command-line argument name constants akEnableTemplateCollapsing = 'template-collapsing' akEnableNamespaceReplacements = 'namespace-replacements' akEnableGenericReplacements = 'generic-replacements' akEnableTempCache = 'temp-cache' akReprocess = 'reprocess' akReprocessPrevConfig = 'reprocess-prev-config' akEnableProcessByLine = 'process-by-line' # Configuration dictionary key constants ckEnableTemplateCollapsing = 'enableTemplateCollapsing' ckEnableNamespaceReplacements = 'enableNamespaceReplacements' ckEnableGenericReplacements = 'enableGenericReplacements' ckEnableTempCache = 'enableTempCache' ckTemplateCollapsingDepth = 'templateCollapsingDepth' ckConfigPaths = 'configPaths' ckNamespaceReplacements = 'namespaceReplacements' ckGenericReplacements = 'genericReplacements' ckCompilationCommand = 'compilationCommand' ckReprocess = 'reprocess' ckReprocessPrevConfig = 'reprocessPrevConfig' ckEnableProcessByLine = 'enableProcessByLine' # # # # ----------------------------------------------------------------------------------------------------------- # Cache # ----------------------------------------------------------------------------------------------------------- fkCacheConfigFilePath = tempfile.gettempdir() + "/lastCamomillaConfig.json" fkCacheFilePath = tempfile.gettempdir() + "/lastCamomilla.out" def writeTempConfigCache(contents): with open(fkCacheConfigFilePath, "w+") as f: f.write(contents) def writeTempCache(): return open(fkCacheFilePath, "w+") def readTempCache(): return open(fkCacheFilePath) def closeTempCache(f): f.close() # # # # ----------------------------------------------------------------------------------------------------------- # Arg parsing # ----------------------------------------------------------------------------------------------------------- def addFeatureOpt(ap, longFlagName, key, defaultValue, helpStr): ap_feature = ap.add_mutually_exclusive_group(required=False) ap_feature.add_argument('--' + longFlagName, dest=key, action='store_true', help="| Control " + helpStr) ap_feature.add_argument('--no-' + longFlagName, dest=key, action='store_false', help="'") ap.set_defaults(**{key:defaultValue}) def addFeatureOptS(ap, shortFlagName, longFlagName, key, defaultValue, helpStr): ap_feature = ap.add_mutually_exclusive_group(required=False) ap_feature.add_argument(shortFlagName, '--' + longFlagName, dest=key, action='store_true', help="| Control " + helpStr) ap_feature.add_argument('--no-' + longFlagName, dest=key, action='store_false', help="'") ap.set_defaults(**{key:defaultValue}) def argDefault(noDefaults, x): return None if noDefaults else x def makeArgParser(noDefaults, parseReprocess): # `None` if `noDefaults`, otherwise `x` def ad(x): return argDefault(noDefaults, x) ap = argparse.ArgumentParser(\ formatter_class=lambda prog: argparse.HelpFormatter(prog,max_help_position=256)) addFeatureOpt(ap, akEnableTemplateCollapsing, ckEnableTemplateCollapsing, ad(True), \ "template collapsing") addFeatureOpt(ap, akEnableNamespaceReplacements, ckEnableNamespaceReplacements, ad(True), \ "namespace replacements") addFeatureOpt(ap, akEnableGenericReplacements, ckEnableGenericReplacements, ad(True), \ "generic replacements") addFeatureOpt(ap, akEnableProcessByLine, ckEnableProcessByLine, ad(True), \ "process by line") if parseReprocess: addFeatureOpt(ap, akEnableTempCache, ckEnableTempCache, ad(True), \ "temp cache") addFeatureOptS(ap, '-r', akReprocess, ckReprocess, ad(False), \ "reprocess previous source") addFeatureOpt(ap, akReprocessPrevConfig, ckReprocessPrevConfig, ad(True), \ "reprocess with previous configuration") ap.add_argument('-d', '--depth', \ help="Template collapsing depth", \ type=int, default=ad(1), \ dest=ckTemplateCollapsingDepth, metavar='X') ap.add_argument('-c', '--config', \ help="Configuration file path(s)", \ dest=ckConfigPaths, default=[], metavar='P', \ action="append") # TODO: # # ap.add_argument('-x', '--exec', \ # help="Execute compilation command", \ # type=str, default="", nargs=argparse.REMAINDER, dest=ckCompilationCommand, metavar='X') return ap # # # # ----------------------------------------------------------------------------------------------------------- # Argument propagation # ----------------------------------------------------------------------------------------------------------- def canPropagate(key, origin): return key in origin.keys() and origin[key] != None def propagateArgOverride(key, origin, target): if canPropagate(key, origin): target[key] = origin[key] def propagateReplacements(key, origin, target): if canPropagate(key, origin): for k, v in origin[key].items(): target[key][k] = v def propagateConfigPaths(key, origin, target): if canPropagate(key, origin): for x in origin[key]: target[key].add(x) def propagateEverything(origin, target): propagateArgOverride(ckEnableNamespaceReplacements, origin, target) propagateArgOverride(ckEnableGenericReplacements, origin, target) propagateArgOverride(ckEnableTemplateCollapsing, origin, target) propagateArgOverride(ckEnableProcessByLine, origin, target) # TODO: ? # propagateArgOverride(ckEnableTempCache, origin, target) propagateArgOverride(ckTemplateCollapsingDepth, origin, target) propagateReplacements(ckNamespaceReplacements, origin, target) propagateReplacements(ckGenericReplacements, origin, target) # # # # ----------------------------------------------------------------------------------------------------------- # Driver # ----------------------------------------------------------------------------------------------------------- class Camomilla: def __init__(self, conf): self._conf = conf self._compiledNamespaceRegex = None self._compiledGenericRegex = None self._initRegexes() # Configuration getters def namespaceReplacements(self): return self._conf[ckNamespaceReplacements] def genericReplacements(self): return self._conf[ckGenericReplacements] def templateCollapsingDepth(self): return self._conf[ckTemplateCollapsingDepth] def enableNamespaceReplacements(self): return self._conf[ckEnableNamespaceReplacements] def enableGenericReplacements(self): return self._conf[ckEnableGenericReplacements] def enableTemplateCollapsing(self): return self._conf[ckEnableTemplateCollapsing] def enableTempCache(self): return self._conf[ckEnableTempCache] def enableProcessByLine(self): return self._conf[ckEnableProcessByLine] def reprocess(self): return self._conf[ckReprocess] # From http://stackoverflow.com/questions/15175142/ def _initRegex(self, k_mapper, v_mapper, xdict): # Map keys and values in dictionary mapped_dict = {k_mapper(k): v_mapper(v) for k, v in xdict.items()} # Create a regular expression from the dictionary keys escaped_keys = mapped_dict.keys() joined_regex_matcher = "({})".format("|".join(escaped_keys)) # Compile and return regex return re.compile(joined_regex_matcher) # Compiles and caches namespace and generic replacement regexes def _initRegexes(self): if self.enableNamespaceReplacements(): self._compiledNamespaceRegex = \ self._initRegex( \ lambda k: k + r'::', \ lambda v: v + r'::' if len(v) > 0 else '', \ self.namespaceReplacements()) if self.enableGenericReplacements(): self._compiledGenericRegex = \ self._initRegex( \ lambda k: k, \ lambda v: v, \ self.genericReplacements()) # Find all `<...>` pair ranges def _find_angles(self, s, xi_start, xi_end): result_angle_pairs = [] open_angles = [] def matchOpen(i): if s[i] != '<': return False if s[i-1] == ' ': return False # No space before '<' if s[i-1] == '<': return False # Stream operator if s[i+1] == ' ': return False # No space after '<' if s[i+1] == '<': return False # Stream operator return True def matchClose(i): if s[i] != '>': return False if s[i-1] == '-': return False # Dereference arrow # Relational operator or stream operator if s[i-1] == ' ' and (s[i+1] == ' ' or s[i+1] == '>') and s[i+2] != '>': return False if s[i-1] == '>' and s[i-2] == ' ': return False # Stream operator return True for i in range(xi_start, xi_end): if matchOpen(i): open_angles.append(i) elif matchClose(i): if len(open_angles) == 0: continue depth = len(open_angles) x = open_angles.pop() result_angle_pairs.append((x, i+1, depth)) return result_angle_pairs # Mark a `<...>` pair for removal def _mark(self, i_start, i_end): return (i_start + 1, i_end - 1) # Yield merged overlapping intervals # (From 'http://codereview.stackexchange.com/questions/69242') def _merged(self, intervals): sorted_intervals = sorted(intervals, key=lambda x: x[0]) if not sorted_intervals: # no intervals to merge return # low and high represent the bounds of the current run of merges low, high = sorted_intervals[0] for iv in sorted_intervals[1:]: if iv[0] <= high: # new interval overlaps current run high = max(high, iv[1]) # merge with the current run else: # current run is over yield low, high # yield accumulated interval low, high = iv # start new run yield low, high # end the final run def _subDisambiguator(self, dict, x): matched_str = x.string[x.start():x.end()] for k, v in dict.items(): if re.match(k, matched_str) != None: return v raise Exception("No valid replacement for " + matched_str) def _multiple_replace(self, k_mapper, v_mapper, xdict, compiled_regex, src): # Bail out if there are no replacements if len(xdict) == 0: return src # Map keys and values in dictionary mapped_dict = {k_mapper(k): v_mapper(v) for k, v in xdict.items()} # For each match, look-up corresponding value in dictionary return compiled_regex.sub(lambda x: self._subDisambiguator(mapped_dict, x), src) def _processImpl(self, src, ostream, temp_cache): out = "" marked = [] # Write temp cache ______________________________________ # if self.reprocess() == False and self.enableTempCache(): # Cache source error temp_cache.write(src) # Cache config writeTempConfigCache(json.dumps(self._conf)) # _______________________________________________________ # # Template collapsing ___________________________________ # if self.enableTemplateCollapsing(): # Find all angle bracket pairs angle_pairs = self._find_angles(src, 0, len(src)) # Mark pairs matching desired depth for removal for p in angle_pairs: if p[2] > self.templateCollapsingDepth(): marked.append(self._mark(p[0], p[1])) # Build output string by avoiding marked intervals last = 0 for m in self._merged(marked): out += src[last:m[0]] last = m[1] out += src[last:len(src)] else: out = src # _______________________________________________________ # # Namespace replacements_________________________________ # if self.enableNamespaceReplacements(): # Replace namespace matches out = self._multiple_replace( \ lambda k: k + r'::', \ lambda v: v + r'::' if len(v) > 0 else '', \ self.namespaceReplacements(), self._compiledNamespaceRegex, out) # _______________________________________________________ # # Generic replacements __________________________________ # if self.enableGenericReplacements(): # Replace generic matches out = self._multiple_replace( \ lambda k: k, \ lambda v: v, \ self.genericReplacements(), self._compiledGenericRegex, out) # _______________________________________________________ # ostream.write(out) def process(self, istream, ostream, temp_cache): if self.enableProcessByLine(): # Process error line by line lastTime = time.perf_counter() while True: src = istream.readline() if src == '': break self._processImpl(src, ostream, temp_cache) # Flush once per second t = time.perf_counter() if t - lastTime >= 1.0: ostream.flush() lastTime = t else: # Process error at all once src = istream.read() self._processImpl(src, ostream, temp_cache) # # # # ----------------------------------------------------------------------------------------------------------- # Configuration # ----------------------------------------------------------------------------------------------------------- def loadConfig(path): with open(path) as data: j = json.load(data) res = { ckNamespaceReplacements: dict(), ckGenericReplacements: dict(), ckConfigPaths: set() } propagateEverything(j, res) propagateConfigPaths(ckConfigPaths, j, res) return res def mergeConfig(parent, x): # Recursively merge configs if ckConfigPaths in x.keys(): for child in x[ckConfigPaths]: x = mergeConfig(x, loadConfig(child)) propagateEverything(x, parent) return parent def makeInitialBaseConfig(): conf = dict() conf[ckNamespaceReplacements] = dict() conf[ckGenericReplacements] = dict() conf[ckConfigPaths] = [] return conf def makeInitialConfig(args): conf = vars(args[0]) conf[ckNamespaceReplacements] = dict() conf[ckGenericReplacements] = dict() conf[ckConfigPaths] = conf[ckConfigPaths] conf[ckNamespaceReplacements]["std"] = "" conf[ckGenericReplacements]["<>"] = "" return conf def makeFinalConfig(): ap = makeArgParser(False, True) args = ap.parse_known_args() conf = makeInitialConfig(args) # TODO: # # compilationCmd = ' '.join(conf[ckCompilationCommand]) # # if compilationCmd == "": # src = sys.stdin.read() # else: # print("Warning: stdin data will be ignored because '-x' is being used.") # os.system('(' + compilationCmd + ')') for child in conf[ckConfigPaths]: conf = mergeConfig(conf, loadConfig(child)) return conf def confDispatch(): conf = makeFinalConfig() # If reprocessing with previous config, load it and override with command line if conf[ckReprocess] and conf[ckReprocessPrevConfig]: # Make initial base config and merge it with cached config conf = mergeConfig(makeInitialBaseConfig(), loadConfig(fkCacheConfigFilePath)) # Override cached config with eventual command-line arguments ap = makeArgParser(True, False) args = vars(ap.parse_known_args()[0]) propagateEverything(args, conf) # Override config with eventual command-line config paths if canPropagate(ckConfigPaths, args): for child in args[ckConfigPaths]: conf = mergeConfig(conf, loadConfig(child)) # Prevent altering the cache conf[ckReprocess] = True conf[ckEnableTempCache] = False # Convert all paths to absolute conf[ckConfigPaths] = [os.path.abspath(x) for x in conf[ckConfigPaths]] return conf # # # # ----------------------------------------------------------------------------------------------------------- # Main # ----------------------------------------------------------------------------------------------------------- def main(): conf = confDispatch() camomilla = Camomilla(conf) # Read from temp cache if reprocessing, otherwise from stdin src = readTempCache() if conf[ckReprocess] else sys.stdin if conf[ckEnableTempCache]: tempCache = writeTempCache() else: tempCache = None # Process and stream error line by line camomilla.process(src, sys.stdout, tempCache) # Close temp cache if required if conf[ckEnableTempCache]: closeTempCache(tempCache) if conf[ckReprocess]: closeTempCache(src) return 0 if __name__ == "__main__": sys.exit(main()) ### TODO # # * gcc, g++, clang, clang++ aliases that pass error to camomilla. # # * Makefile/install script. # # * --depth=-1 or --alldepth or whatever. # # * Refactor code. # # * Blog article. # # * tuple/pair sugar ================================================ FILE: config_files/ecst_namespaces.json ================================================ { "configPaths": ["./config_files/ecst_namespaces_inner.json"], "namespaceReplacements": { "vrm::core": "vrmc", "ecst": "", "system_execution_adapter": "sea", "context": "ctx", "tag::system": "tag_s", "tag::component": "tag_c" } } ================================================ FILE: config_files/ecst_namespaces_inner.json ================================================ { "namespaceReplacements": { } } ================================================ FILE: config_files/generic.json ================================================ { "genericReplacements": { "integral_constant": "ic", "lambda\\(": "[?](", "size_t": "sz_t", "unsigned ": "u", "long unsigned": "ul", "unsigned long": "ul", "type_impl": "type", "tag_impl": "tag", "forward": "fwd" } } ================================================ FILE: config_files/namespaces.json ================================================ { "namespaceReplacements": { "std": "", "__cxx..": "cxx", "boost::hana": "bh", "boost::fusion": "bf", "boost::spirit": "bs", "impl": "_", "implementation": "_", "detail": "_" } } ================================================ FILE: example_errors/0_clang_after.txt ================================================ pres_code.cpp:274:31: error: no member named 'ya' in 'sf::Vector2' v.ya *= -1; ~ ^ /home/vittorioromeo/OHWorkspace/ecst/include/ecst/context/./system/./instance/instance_subtask.inl:75:13: note: in instantiation of function template specialization 'example::s::keep_in_bounds::process(ctx::system::data_proxy::multi &)::(anonymous class)::operator()' requested here f(this->nth_subscribed(i)); ^ /home/vittorioromeo/OHWorkspace/ecst/include/ecst/context/./system/./instance/./proxy/./data/./impl/multi.inl:39:36: note: in instantiation of function template specialization 'ctx::system::instance::for_entities' requested here return this->_instance.for_entities(_i_begin, _i_end, FWD(f)); ^ pres_code.cpp:871:31: note: in instantiation of function template specialization 'example::s::keep_in_bounds::process' requested here s.process(data); ^ /home/vittorioromeo/OHWorkspace/ecst/include/./ecst/./inner_parallelism/./utils/execute_split.hpp:66:18: note: in instantiation of function template specialization 'ctx::system::instance::prepare_and_wait_subtasks' requested here inst.prepare_and_wait_subtasks(ctx, split_count, ef); ^ /home/vittorioromeo/OHWorkspace/ecst/include/./ecst/./inner_parallelism/./strategy/./split_evenly_fn/./executor.hpp:44:28: note: in instantiation of function template specialization 'inner_parallelism::utils::prepare_execute_wait_subtasks' requested here utils::prepare_execute_wait_subtasks( // . ^ /home/vittorioromeo/OHWorkspace/ecst/include/ecst/context/./system/./instance/instance.inl:158:35: note: (skipping 16 contexts in backtrace; use -ftemplate-backtrace-limit=0 to see all) this->parallel_executor().execute(*this, ctx, move(st)); ^ ././utils/pres_game_app.hpp:208:13: note: in instantiation of member function 'example::game_app::init_loops' requested here init_loops(); ^ ././utils/pres_game_app.hpp:216:13: note: in instantiation of member function 'example::game_app::init' requested here init(); ^ ././boilerplate/app_runner.hpp:48:32: note: in instantiation of member function 'example::game_app::game_app' requested here _app = new T(_window, FWD(xs)...); ^ ././utils/pres_game_app.hpp:223:69: note: in instantiation of function template specialization 'example::boilerplate::app_runner::app_runner' requested here boilerplate::app_runner x{ ^ pres_code.cpp:936:5: note: in instantiation of function template specialization 'example::run_simulation' requested here run_simulation(*ctx); ^ 1 error generated. ================================================ FILE: example_errors/0_clang_before.txt ================================================ pres_code.cpp:274:31: error: no member named 'ya' in 'sf::Vector2' v.ya *= -1; ~ ^ /home/vittorioromeo/OHWorkspace/ecst/include/ecst/context/./system/./instance/instance_subtask.inl:75:13: note: in instantiation of function template specialization 'example::s::keep_in_bounds::process(ecst::context::system::data_proxy::multi, ecst::mp::option_map::impl::data, 0>, boost::hana::detail::bucket, 1>, boost::hana::detail::bucket, 2>, boost::hana::detail::bucket, 3>, boost::hana::detail::bucket, 4> >, boost::hana::basic_tuple, boost::hana::pair, boost::hana::integral_constant > >, boost::hana::pair, boost::hana::pair >, boost::hana::integral_constant > >, boost::hana::pair, boost::hana::pair >, boost::hana::integral_constant > >, boost::hana::pair, boost::hana::pair, ecst::tag::component::impl::tag_impl >, boost::hana::integral_constant > >, boost::hana::pair, boost::hana::pair, boost::hana::integral_constant > > > > > > >::_, ecst::context::impl::data, ecst::context::system::instance, ecst::mp::option_map::impl::data, 0>, boost::hana::detail::bucket, 1>, boost::hana::detail::bucket, 2>, boost::hana::detail::bucket, 3>, boost::hana::detail::bucket, 4> >, boost::hana::basic_tuple, boost::hana::pair, boost::hana::integral_constant > >, boost::hana::pair, boost::hana::pair >, boost::hana::integral_constant > >, boost::hana::pair, boost::hana::pair >, boost::hana::integral_constant > >, boost::hana::pair, boost::hana::pair, ecst::tag::component::impl::tag_impl >, boost::hana::integral_constant > >, boost::hana::pair, boost::hana::pair, boost::hana::integral_constant > > > > > > >::_> > &)::(anonymous class)::operator()' requested here f(this->nth_subscribed(i)); ^ /home/vittorioromeo/OHWorkspace/ecst/include/ecst/context/./system/./instance/./proxy/./data/./impl/multi.inl:39:36: note: in instantiation of function template specialization 'ecst::context::system::instance, ecst::mp::option_map::impl::data, 0>, boost::hana::detail::bucket, 1>, boost::hana::detail::bucket, 2>, boost::hana::detail::bucket, 3>, boost::hana::detail::bucket, 4> >, boost::hana::basic_tuple, boost::hana::pair, boost::hana::integral_constant > >, boost::hana::pair, boost::hana::pair >, boost::hana::integral_constant > >, boost::hana::pair, boost::hana::pair >, boost::hana::integral_constant > >, boost::hana::pair, boost::hana::pair, ecst::tag::component::impl::tag_impl >, boost::hana::integral_constant > >, boost::hana::pair, boost::hana::pair, boost::hana::integral_constant > > > > > > >::_>::for_entities<(lambda at pres_code.cpp:241:35)>' requested here return this->_instance.for_entities(_i_begin, _i_end, FWD(f)); ^ pres_code.cpp:871:31: note: in instantiation of function template specialization 'example::s::keep_in_bounds::process, ecst::mp::option_map::impl::data, 0>, boost::hana::detail::bucket, 1>, boost::hana::detail::bucket, 2>, boost::hana::detail::bucket, 3>, boost::hana::detail::bucket, 4> >, boost::hana::basic_tuple, boost::hana::pair, boost::hana::integral_constant > >, boost::hana::pair, boost::hana::pair >, boost::hana::integral_constant > >, boost::hana::pair, boost::hana::pair >, boost::hana::integral_constant > >, boost::hana::pair, boost::hana::pair, ecst::tag::component::impl::tag_impl >, boost::hana::integral_constant > >, boost::hana::pair, boost::hana::pair, boost::hana::integral_constant > > > > > > >::_, ecst::context::impl::data, ecst::context::system::instance, ecst::mp::option_map::impl::data, 0>, boost::hana::detail::bucket, 1>, boost::hana::detail::bucket, 2>, boost::hana::detail::bucket, 3>, boost::hana::detail::bucket, 4> >, boost::hana::basic_tuple, boost::hana::pair, boost::hana::integral_constant > >, boost::hana::pair, boost::hana::pair >, boost::hana::integral_constant > >, boost::hana::pair, boost::hana::pair >, boost::hana::integral_constant > >, boost::hana::pair, boost::hana::pair, ecst::tag::component::impl::tag_impl >, boost::hana::integral_constant > >, boost::hana::pair, boost::hana::pair, boost::hana::integral_constant > > > > > > >::_> > >' requested here s.process(data); ^ /home/vittorioromeo/OHWorkspace/ecst/include/./ecst/./inner_parallelism/./utils/execute_split.hpp:66:18: note: in instantiation of function template specialization 'ecst::context::system::instance, ecst::mp::option_map::impl::data, 0>, boost::hana::detail::bucket, 1>, boost::hana::detail::bucket, 2>, boost::hana::detail::bucket, 3>, boost::hana::detail::bucket, 4> >, boost::hana::basic_tuple, boost::hana::pair, boost::hana::integral_constant > >, boost::hana::pair, boost::hana::pair >, boost::hana::integral_constant > >, boost::hana::pair, boost::hana::pair >, boost::hana::integral_constant > >, boost::hana::pair, boost::hana::pair, ecst::tag::component::impl::tag_impl >, boost::hana::integral_constant > >, boost::hana::pair, boost::hana::pair, boost::hana::integral_constant > > > > > > >::_>::prepare_and_wait_subtasks, (lambda at /home/vittorioromeo/OHWorkspace/ecst/include/./ecst/./inner_parallelism/./utils/execute_split.hpp:58:23)>' requested here inst.prepare_and_wait_subtasks(ctx, split_count, ef); ^ /home/vittorioromeo/OHWorkspace/ecst/include/./ecst/./inner_parallelism/./strategy/./split_evenly_fn/./executor.hpp:44:28: note: in instantiation of function template specialization 'ecst::inner_parallelism::utils::prepare_execute_wait_subtasks, ecst::mp::option_map::impl::data, 0>, boost::hana::detail::bucket, 1>, boost::hana::detail::bucket, 2>, boost::hana::detail::bucket, 3>, boost::hana::detail::bucket, 4> >, boost::hana::basic_tuple, boost::hana::pair, boost::hana::integral_constant > >, boost::hana::pair, boost::hana::pair >, boost::hana::integral_constant > >, boost::hana::pair, boost::hana::pair >, boost::hana::integral_constant > >, boost::hana::pair, boost::hana::pair, ecst::tag::component::impl::tag_impl >, boost::hana::integral_constant > >, boost::hana::pair, boost::hana::pair, boost::hana::integral_constant > > > > > > >::_>, ecst::context::impl::data, (lambda at /home/vittorioromeo/OHWorkspace/ecst/include/ecst/context/./system/./instance/instance.inl:147:19) &>' requested here utils::prepare_execute_wait_subtasks( // . ^ /home/vittorioromeo/OHWorkspace/ecst/include/ecst/context/./system/./instance/instance.inl:158:35: note: (skipping 16 contexts in backtrace; use -ftemplate-backtrace-limit=0 to see all) this->parallel_executor().execute(*this, ctx, std::move(st)); ^ ././utils/pres_game_app.hpp:208:13: note: in instantiation of member function 'example::game_app >::init_loops' requested here init_loops(); ^ ././utils/pres_game_app.hpp:216:13: note: in instantiation of member function 'example::game_app >::init' requested here init(); ^ ././boilerplate/app_runner.hpp:48:32: note: in instantiation of member function 'example::game_app >::game_app' requested here _app = new T(_window, FWD(xs)...); ^ ././utils/pres_game_app.hpp:223:69: note: in instantiation of function template specialization 'example::boilerplate::app_runner > >::app_runner &>' requested here boilerplate::app_runner> x{ ^ pres_code.cpp:936:5: note: in instantiation of function template specialization 'example::run_simulation >' requested here run_simulation(*ctx); ^ 1 error generated. ================================================ FILE: example_errors/0_gcc_after.txt ================================================ pres_code.cpp: In instantiation of ‘example::s::keep_in_bounds::process(TData&):: [with auto:133 = entity_id; TData = ctx::system::data_proxy::multi]’: /home/vittorioromeo/OHWorkspace/ecst/include/./ecst/./context/./system/./instance/instance_subtask.inl:75:14: required from ‘void ctx::system::instance::for_entities(vrmc::sz_t, vrmc::sz_t, TF&&) [with TF = example::s::keep_in_bounds::process(TData&) [with TData = ctx::system::data_proxy::multi]::; TSettings = main()::hs; TSystemSignature = bh::type::_; vrmc::sz_t = ulint]’ /home/vittorioromeo/OHWorkspace/ecst/include/./ecst/./context/./system/./instance/./proxy/data/./impl/multi.inl:39:73: required from ‘auto ctx::system::data_proxy::multi::for_entities(TF&&) [with TF = example::s::keep_in_bounds::process(TData&) [with TData = ctx::system::data_proxy::multi]::; TSystemSignature = bh::type::_; TContext = ctx::_::data; TInstance = ctx::system::instance]’ pres_code.cpp:241:17: required from ‘void example::s::keep_in_bounds::process(TData&) [with TData = ctx::system::data_proxy::multi]’ pres_code.cpp:871:29: required from ‘example::update_ctx(TContext&, TRenderTarget&, example::ft):::: [with auto:153 = example::s::keep_in_bounds; auto:154 = ctx::system::data_proxy::multi; auto:150 = ctx::_::step::proxy; TContext = ctx::_::data; TRenderTarget = sf::RenderWindow]’ /home/vittorioromeo/OHWorkspace/ecst/include/./ecst/./system_execution_adapter/./impl/./predicate_holder/predicate_holder.inl:46:30: required from ‘sea::_::predicate_holder::for_subtasks(TF&&):: mutable:: mutable [with auto:76 = ctx::system::data_proxy::multi; auto:74 = example::s::keep_in_bounds; auto:75 = ctx::system::executor_proxy::data; TF = example::update_ctx(TContext&, TRenderTarget&, example::ft):: [with auto:150 = ctx::_::step::proxy; TContext = ctx::_::data; TRenderTarget = sf::RenderWindow]::; TPredicate = sea::t(TSystemTags ...) [with TSystemTags = {tag_s::_::tag, tag_s::_::tag, tag_s::_::tag, tag_s::_::tag}]::]’ /home/vittorioromeo/OHWorkspace/ecst/include/./ecst/./context/./system/./instance/instance.inl:155:14: [ skipping 58 instantiation contexts, use -ftemplate-backtrace-limit=0 to disable ] ./utils/pres_game_app.hpp:208:23: required from ‘void example::game_app::init() [with TContext = ctx::_::data]’ ./utils/pres_game_app.hpp:216:17: required from ‘example::game_app::game_app(sf::RenderWindow&, TContext&) [with TContext = ctx::_::data]’ ./utils/.././boilerplate/app_runner.hpp:48:28: required from ‘example::boilerplate::app_runner::app_runner(const string&, sz_t, sz_t, Ts&& ...):: [with Ts = {ctx::_::data&}; T = example::game_app]’ ./utils/.././boilerplate/app_runner.hpp:36:59: required from ‘struct example::boilerplate::app_runner::app_runner(const string&, sz_t, sz_t, Ts&& ...) [with Ts = {ctx::_::data&}; T = example::game_app; __cxx11::string = __cxx11::basic_string; sz_t = ulint]::’ ./utils/.././boilerplate/app_runner.hpp:36:25: required from ‘example::boilerplate::app_runner::app_runner(const string&, sz_t, sz_t, Ts&& ...) [with Ts = {ctx::_::data&}; T = example::game_app; __cxx11::string = __cxx11::basic_string; sz_t = ulint]’ ./utils/pres_game_app.hpp:224:49: required from ‘void example::run_simulation(TContext&) [with TContext = ctx::_::data]’ pres_code.cpp:936:24: required from here pres_code.cpp:274:31: error: ‘class sf::Vector2’ has no member named ‘ya’; did you mean ‘y’? v.ya *= -1; ~~^~ ================================================ FILE: example_errors/0_gcc_before.txt ================================================ pres_code.cpp: In instantiation of ‘example::s::keep_in_bounds::process(TData&):: [with auto:133 = ecst::entity_id; TData = ecst::context::system::data_proxy::multi, ecst::mp::option_map::impl::data, 0ul>, boost::hana::detail::bucket, 1ul>, boost::hana::detail::bucket, 2ul>, boost::hana::detail::bucket, 3ul>, boost::hana::detail::bucket, 4ul> >, boost::hana::basic_tuple, boost::hana::pair, boost::hana::integral_constant > >, boost::hana::pair, boost::hana::pair >, boost::hana::integral_constant > >, boost::hana::pair, boost::hana::pair >, boost::hana::integral_constant > >, boost::hana::pair, boost::hana::pair, ecst::tag::component::impl::tag_impl >, boost::hana::integral_constant > >, boost::hana::pair, boost::hana::pair, boost::hana::integral_constant > > > > > > >::_, ecst::context::impl::data, ecst::context::system::instance, ecst::mp::option_map::impl::data, 0ul>, boost::hana::detail::bucket, 1ul>, boost::hana::detail::bucket, 2ul>, boost::hana::detail::bucket, 3ul>, boost::hana::detail::bucket, 4ul> >, boost::hana::basic_tuple, boost::hana::pair, boost::hana::integral_constant > >, boost::hana::pair, boost::hana::pair >, boost::hana::integral_constant > >, boost::hana::pair, boost::hana::pair >, boost::hana::integral_constant > >, boost::hana::pair, boost::hana::pair, ecst::tag::component::impl::tag_impl >, boost::hana::integral_constant > >, boost::hana::pair, boost::hana::pair, boost::hana::integral_constant > > > > > > >::_> >]’: /home/vittorioromeo/OHWorkspace/ecst/include/./ecst/./context/./system/./instance/instance_subtask.inl:75:14: required from ‘void ecst::context::system::instance::for_entities(vrm::core::sz_t, vrm::core::sz_t, TF&&) [with TF = example::s::keep_in_bounds::process(TData&) [with TData = ecst::context::system::data_proxy::multi, ecst::mp::option_map::impl::data, 0ul>, boost::hana::detail::bucket, 1ul>, boost::hana::detail::bucket, 2ul>, boost::hana::detail::bucket, 3ul>, boost::hana::detail::bucket, 4ul> >, boost::hana::basic_tuple, boost::hana::pair, boost::hana::integral_constant > >, boost::hana::pair, boost::hana::pair >, boost::hana::integral_constant > >, boost::hana::pair, boost::hana::pair >, boost::hana::integral_constant > >, boost::hana::pair, boost::hana::pair, ecst::tag::component::impl::tag_impl >, boost::hana::integral_constant > >, boost::hana::pair, boost::hana::pair, boost::hana::integral_constant > > > > > > >::_, ecst::context::impl::data, ecst::context::system::instance, ecst::mp::option_map::impl::data, 0ul>, boost::hana::detail::bucket, 1ul>, boost::hana::detail::bucket, 2ul>, boost::hana::detail::bucket, 3ul>, boost::hana::detail::bucket, 4ul> >, boost::hana::basic_tuple, boost::hana::pair, boost::hana::integral_constant > >, boost::hana::pair, boost::hana::pair >, boost::hana::integral_constant > >, boost::hana::pair, boost::hana::pair >, boost::hana::integral_constant > >, boost::hana::pair, boost::hana::pair, ecst::tag::component::impl::tag_impl >, boost::hana::integral_constant > >, boost::hana::pair, boost::hana::pair, boost::hana::integral_constant > > > > > > >::_> >]::; TSettings = main()::hs; TSystemSignature = boost::hana::type_impl, ecst::mp::option_map::impl::data, 0ul>, boost::hana::detail::bucket, 1ul>, boost::hana::detail::bucket, 2ul>, boost::hana::detail::bucket, 3ul>, boost::hana::detail::bucket, 4ul> >, boost::hana::basic_tuple, boost::hana::pair, boost::hana::integral_constant > >, boost::hana::pair, boost::hana::pair >, boost::hana::integral_constant > >, boost::hana::pair, boost::hana::pair >, boost::hana::integral_constant > >, boost::hana::pair, boost::hana::pair, ecst::tag::component::impl::tag_impl >, boost::hana::integral_constant > >, boost::hana::pair, boost::hana::pair, boost::hana::integral_constant > > > > > > >::_; vrm::core::sz_t = long unsigned int]’ /home/vittorioromeo/OHWorkspace/ecst/include/./ecst/./context/./system/./instance/./proxy/data/./impl/multi.inl:39:73: required from ‘auto ecst::context::system::data_proxy::multi::for_entities(TF&&) [with TF = example::s::keep_in_bounds::process(TData&) [with TData = ecst::context::system::data_proxy::multi, ecst::mp::option_map::impl::data, 0ul>, boost::hana::detail::bucket, 1ul>, boost::hana::detail::bucket, 2ul>, boost::hana::detail::bucket, 3ul>, boost::hana::detail::bucket, 4ul> >, boost::hana::basic_tuple, boost::hana::pair, boost::hana::integral_constant > >, boost::hana::pair, boost::hana::pair >, boost::hana::integral_constant > >, boost::hana::pair, boost::hana::pair >, boost::hana::integral_constant > >, boost::hana::pair, boost::hana::pair, ecst::tag::component::impl::tag_impl >, boost::hana::integral_constant > >, boost::hana::pair, boost::hana::pair, boost::hana::integral_constant > > > > > > >::_, ecst::context::impl::data, ecst::context::system::instance, ecst::mp::option_map::impl::data, 0ul>, boost::hana::detail::bucket, 1ul>, boost::hana::detail::bucket, 2ul>, boost::hana::detail::bucket, 3ul>, boost::hana::detail::bucket, 4ul> >, boost::hana::basic_tuple, boost::hana::pair, boost::hana::integral_constant > >, boost::hana::pair, boost::hana::pair >, boost::hana::integral_constant > >, boost::hana::pair, boost::hana::pair >, boost::hana::integral_constant > >, boost::hana::pair, boost::hana::pair, ecst::tag::component::impl::tag_impl >, boost::hana::integral_constant > >, boost::hana::pair, boost::hana::pair, boost::hana::integral_constant > > > > > > >::_> >]::; TSystemSignature = boost::hana::type_impl, ecst::mp::option_map::impl::data, 0ul>, boost::hana::detail::bucket, 1ul>, boost::hana::detail::bucket, 2ul>, boost::hana::detail::bucket, 3ul>, boost::hana::detail::bucket, 4ul> >, boost::hana::basic_tuple, boost::hana::pair, boost::hana::integral_constant > >, boost::hana::pair, boost::hana::pair >, boost::hana::integral_constant > >, boost::hana::pair, boost::hana::pair >, boost::hana::integral_constant > >, boost::hana::pair, boost::hana::pair, ecst::tag::component::impl::tag_impl >, boost::hana::integral_constant > >, boost::hana::pair, boost::hana::pair, boost::hana::integral_constant > > > > > > >::_; TContext = ecst::context::impl::data; TInstance = ecst::context::system::instance, ecst::mp::option_map::impl::data, 0ul>, boost::hana::detail::bucket, 1ul>, boost::hana::detail::bucket, 2ul>, boost::hana::detail::bucket, 3ul>, boost::hana::detail::bucket, 4ul> >, boost::hana::basic_tuple, boost::hana::pair, boost::hana::integral_constant > >, boost::hana::pair, boost::hana::pair >, boost::hana::integral_constant > >, boost::hana::pair, boost::hana::pair >, boost::hana::integral_constant > >, boost::hana::pair, boost::hana::pair, ecst::tag::component::impl::tag_impl >, boost::hana::integral_constant > >, boost::hana::pair, boost::hana::pair, boost::hana::integral_constant > > > > > > >::_>]’ pres_code.cpp:241:17: required from ‘void example::s::keep_in_bounds::process(TData&) [with TData = ecst::context::system::data_proxy::multi, ecst::mp::option_map::impl::data, 0ul>, boost::hana::detail::bucket, 1ul>, boost::hana::detail::bucket, 2ul>, boost::hana::detail::bucket, 3ul>, boost::hana::detail::bucket, 4ul> >, boost::hana::basic_tuple, boost::hana::pair, boost::hana::integral_constant > >, boost::hana::pair, boost::hana::pair >, boost::hana::integral_constant > >, boost::hana::pair, boost::hana::pair >, boost::hana::integral_constant > >, boost::hana::pair, boost::hana::pair, ecst::tag::component::impl::tag_impl >, boost::hana::integral_constant > >, boost::hana::pair, boost::hana::pair, boost::hana::integral_constant > > > > > > >::_, ecst::context::impl::data, ecst::context::system::instance, ecst::mp::option_map::impl::data, 0ul>, boost::hana::detail::bucket, 1ul>, boost::hana::detail::bucket, 2ul>, boost::hana::detail::bucket, 3ul>, boost::hana::detail::bucket, 4ul> >, boost::hana::basic_tuple, boost::hana::pair, boost::hana::integral_constant > >, boost::hana::pair, boost::hana::pair >, boost::hana::integral_constant > >, boost::hana::pair, boost::hana::pair >, boost::hana::integral_constant > >, boost::hana::pair, boost::hana::pair, ecst::tag::component::impl::tag_impl >, boost::hana::integral_constant > >, boost::hana::pair, boost::hana::pair, boost::hana::integral_constant > > > > > > >::_> >]’ pres_code.cpp:871:29: required from ‘example::update_ctx(TContext&, TRenderTarget&, example::ft):::: [with auto:153 = example::s::keep_in_bounds; auto:154 = ecst::context::system::data_proxy::multi, ecst::mp::option_map::impl::data, 0ul>, boost::hana::detail::bucket, 1ul>, boost::hana::detail::bucket, 2ul>, boost::hana::detail::bucket, 3ul>, boost::hana::detail::bucket, 4ul> >, boost::hana::basic_tuple, boost::hana::pair, boost::hana::integral_constant > >, boost::hana::pair, boost::hana::pair >, boost::hana::integral_constant > >, boost::hana::pair, boost::hana::pair >, boost::hana::integral_constant > >, boost::hana::pair, boost::hana::pair, ecst::tag::component::impl::tag_impl >, boost::hana::integral_constant > >, boost::hana::pair, boost::hana::pair, boost::hana::integral_constant > > > > > > >::_, ecst::context::impl::data, ecst::context::system::instance, ecst::mp::option_map::impl::data, 0ul>, boost::hana::detail::bucket, 1ul>, boost::hana::detail::bucket, 2ul>, boost::hana::detail::bucket, 3ul>, boost::hana::detail::bucket, 4ul> >, boost::hana::basic_tuple, boost::hana::pair, boost::hana::integral_constant > >, boost::hana::pair, boost::hana::pair >, boost::hana::integral_constant > >, boost::hana::pair, boost::hana::pair >, boost::hana::integral_constant > >, boost::hana::pair, boost::hana::pair, ecst::tag::component::impl::tag_impl >, boost::hana::integral_constant > >, boost::hana::pair, boost::hana::pair, boost::hana::integral_constant > > > > > > >::_> >; auto:150 = ecst::context::impl::step::proxy; TContext = ecst::context::impl::data; TRenderTarget = sf::RenderWindow]’ /home/vittorioromeo/OHWorkspace/ecst/include/./ecst/./system_execution_adapter/./impl/./predicate_holder/predicate_holder.inl:46:30: required from ‘ecst::system_execution_adapter::impl::predicate_holder::for_subtasks(TF&&):: mutable:: mutable [with auto:76 = ecst::context::system::data_proxy::multi, ecst::mp::option_map::impl::data, 0ul>, boost::hana::detail::bucket, 1ul>, boost::hana::detail::bucket, 2ul>, boost::hana::detail::bucket, 3ul>, boost::hana::detail::bucket, 4ul> >, boost::hana::basic_tuple, boost::hana::pair, boost::hana::integral_constant > >, boost::hana::pair, boost::hana::pair >, boost::hana::integral_constant > >, boost::hana::pair, boost::hana::pair >, boost::hana::integral_constant > >, boost::hana::pair, boost::hana::pair, ecst::tag::component::impl::tag_impl >, boost::hana::integral_constant > >, boost::hana::pair, boost::hana::pair, boost::hana::integral_constant > > > > > > >::_, ecst::context::impl::data, ecst::context::system::instance, ecst::mp::option_map::impl::data, 0ul>, boost::hana::detail::bucket, 1ul>, boost::hana::detail::bucket, 2ul>, boost::hana::detail::bucket, 3ul>, boost::hana::detail::bucket, 4ul> >, boost::hana::basic_tuple, boost::hana::pair, boost::hana::integral_constant > >, boost::hana::pair, boost::hana::pair >, boost::hana::integral_constant > >, boost::hana::pair, boost::hana::pair >, boost::hana::integral_constant > >, boost::hana::pair, boost::hana::pair, ecst::tag::component::impl::tag_impl >, boost::hana::integral_constant > >, boost::hana::pair, boost::hana::pair, boost::hana::integral_constant > > > > > > >::_> >; auto:74 = example::s::keep_in_bounds; auto:75 = ecst::context::system::executor_proxy::data, ecst::mp::option_map::impl::data, 0ul>, boost::hana::detail::bucket, 1ul>, boost::hana::detail::bucket, 2ul>, boost::hana::detail::bucket, 3ul>, boost::hana::detail::bucket, 4ul> >, boost::hana::basic_tuple, boost::hana::pair, boost::hana::integral_constant > >, boost::hana::pair, boost::hana::pair >, boost::hana::integral_constant > >, boost::hana::pair, boost::hana::pair >, boost::hana::integral_constant > >, boost::hana::pair, boost::hana::pair, ecst::tag::component::impl::tag_impl >, boost::hana::integral_constant > >, boost::hana::pair, boost::hana::pair, boost::hana::integral_constant > > > > > > >::_>, ecst::context::system::instance::execution_dispatch(TContext&) [with TContext = ecst::context::impl::data; TSettings = main()::hs; TSystemSignature = boost::hana::type_impl, ecst::mp::option_map::impl::data, 0ul>, boost::hana::detail::bucket, 1ul>, boost::hana::detail::bucket, 2ul>, boost::hana::detail::bucket, 3ul>, boost::hana::detail::bucket, 4ul> >, boost::hana::basic_tuple, boost::hana::pair, boost::hana::integral_constant > >, boost::hana::pair, boost::hana::pair >, boost::hana::integral_constant > >, boost::hana::pair, boost::hana::pair >, boost::hana::integral_constant > >, boost::hana::pair, boost::hana::pair, ecst::tag::component::impl::tag_impl >, boost::hana::integral_constant > >, boost::hana::pair, boost::hana::pair, boost::hana::integral_constant > > > > > > >::_]:: >; TF = example::update_ctx(TContext&, TRenderTarget&, example::ft):: [with auto:150 = ecst::context::impl::step::proxy; TContext = ecst::context::impl::data; TRenderTarget = sf::RenderWindow]::; TPredicate = ecst::system_execution_adapter::t(TSystemTags ...) [with TSystemTags = {ecst::tag::system::impl::tag_impl, ecst::tag::system::impl::tag_impl, ecst::tag::system::impl::tag_impl, ecst::tag::system::impl::tag_impl}]::]’ /home/vittorioromeo/OHWorkspace/ecst/include/./ecst/./context/./system/./instance/instance.inl:155:14: [ skipping 58 instantiation contexts, use -ftemplate-backtrace-limit=0 to disable ] ./utils/pres_game_app.hpp:208:23: required from ‘void example::game_app::init() [with TContext = ecst::context::impl::data]’ ./utils/pres_game_app.hpp:216:17: required from ‘example::game_app::game_app(sf::RenderWindow&, TContext&) [with TContext = ecst::context::impl::data]’ ./utils/.././boilerplate/app_runner.hpp:48:28: required from ‘example::boilerplate::app_runner::app_runner(const string&, std::size_t, std::size_t, Ts&& ...):: [with Ts = {ecst::context::impl::data&}; T = example::game_app >]’ ./utils/.././boilerplate/app_runner.hpp:36:59: required from ‘struct example::boilerplate::app_runner::app_runner(const string&, std::size_t, std::size_t, Ts&& ...) [with Ts = {ecst::context::impl::data&}; T = example::game_app >; std::__cxx11::string = std::__cxx11::basic_string; std::size_t = long unsigned int]::’ ./utils/.././boilerplate/app_runner.hpp:36:25: required from ‘example::boilerplate::app_runner::app_runner(const string&, std::size_t, std::size_t, Ts&& ...) [with Ts = {ecst::context::impl::data&}; T = example::game_app >; std::__cxx11::string = std::__cxx11::basic_string; std::size_t = long unsigned int]’ ./utils/pres_game_app.hpp:224:49: required from ‘void example::run_simulation(TContext&) [with TContext = ecst::context::impl::data]’ pres_code.cpp:936:24: required from here pres_code.cpp:274:31: error: ‘class sf::Vector2’ has no member named ‘ya’; did you mean ‘y’? v.ya *= -1; ~~^~ ================================================ FILE: print_edge_cases.sh ================================================ #!/bin/bash function echoTest { echo "Testing: '$1'" OUT0=$(echo -e "$1" | ./camomilla -d0) OUT1=$(./camomilla -r -d1) OUT2=$(./camomilla -r -d2) echo -e " d2: '$OUT2'" echo -e " d1: '$OUT1'" echo -e " d0: '$OUT0'" echo "____________________________________" } echoTest "ending_space >" echoTest "ending_space > >" echoTest "ending_space_rel >" echoTest "ending_space_rel b) > >" echoTest "ending_space_stream >" echoTest "ending_space_stream> b) > >" echoTest "class" echoTest "rel" echoTest "rel b)>" echoTest "stream" echoTest "stream> b)>" echoTest "nested_rel < b)>" echoTest "nested_rel > b)>" echoTest "nested_stream << b)>" echoTest "nested_stream >> b)>" echoTest "nested_types>" echoTest "nested_types_rel>" echoTest "nested_types_rel b)>>" echoTest "nested_types_stream>" echoTest "nested_types_stream> b)>>" ================================================ FILE: setup.py ================================================ #!/usr/bin/env python3 from setuptools import setup, find_packages setup( name = "camomilla", scripts=['camomilla'], version = "0.2", author = "Vittorio Romeo", author_email = "vittorio.romeo@outlook.com", description = "C++ error postprocessor" )