diff --git a/src/kaleidoscope_internal/sketch_exploration/keymap_exploration.h b/src/kaleidoscope_internal/sketch_exploration/keymap_exploration.h index 24a8cc73..494469af 100644 --- a/src/kaleidoscope_internal/sketch_exploration/keymap_exploration.h +++ b/src/kaleidoscope_internal/sketch_exploration/keymap_exploration.h @@ -47,6 +47,22 @@ class KeymapAdaptor { } }; +// A special case for empty keymaps that makes the compiler happy. +// +class EmptyKeymapAdaptor { + public: + + static constexpr uint8_t n_layers = 0; + static constexpr uint8_t layer_size = 0; + + constexpr Key getKey(uint8_t layer, uint8_t offset) const { + return Key_NoKey; + } + constexpr Key getKey(uint8_t layer, KeyAddr key_addr) const { + return Key_NoKey; + } +}; + // This class implements compile time keymap traversal. // // Every key is visited an the _Accumulation functor decides on how @@ -91,6 +107,27 @@ class AccumulationHelper : public KeymapAdaptor<_n_layers, _layer_size> { } }; +// A special case for empty keymaps that makes the compiler happy. +// +template +class EmptyKeymapAccumulationHelper { + private: + + const _Accumulation &op_; + + typedef typename _Accumulation::ResultType ResultType; + + public: + + constexpr EmptyKeymapAccumulationHelper(const _Accumulation &op) + : op_{op} + {} + + constexpr ResultType apply() const { + return op_.init_value; + } +}; + // Accumulation functors to be used with the KeymapInterface's collect // method. // @@ -179,10 +216,9 @@ extern void pluginsExploreSketch(); #define _INIT_KEYMAP_EXPLORATION \ namespace kaleidoscope { \ namespace sketch_exploration { \ - class StaticKeymap \ - { \ - private: \ \ + template \ + struct StaticKeymapHelper { \ template \ static constexpr auto accumulationHelper( \ const Key (&keymap)[_n_layers][_layer_size], \ @@ -193,13 +229,6 @@ extern void pluginsExploreSketch(); _Accumulation>{keymap, op}; \ } \ \ - template \ - static constexpr auto accumulationHelper(const _Accumulation &op) \ - -> decltype(accumulationHelper(::keymaps_linear, op)) \ - { \ - return accumulationHelper(::keymaps_linear, op); \ - } \ - \ template \ static constexpr auto keymapAdaptor( \ const Key (&keymap)[_n_layers][_layer_size]) \ @@ -207,12 +236,35 @@ extern void pluginsExploreSketch(); { \ return KeymapAdaptor<_n_layers, _layer_size>{keymap}; \ } \ + }; \ + \ + /* Empty keymaps need a special treatment */ \ + template<> \ + struct StaticKeymapHelper { \ \ - static constexpr auto keymapAdaptor() \ - -> decltype(keymapAdaptor(::keymaps_linear)) \ + template \ + static constexpr auto accumulationHelper(const _Accumulation &op) \ + -> decltype(EmptyKeymapAccumulationHelper<_Accumulation>{op}) \ + { \ + return EmptyKeymapAccumulationHelper<_Accumulation>{op}; \ + } \ + \ + template \ + static constexpr auto keymapAdaptor(const _Keymap &) \ + -> EmptyKeymapAdaptor \ { \ - return keymapAdaptor(::keymaps_linear); \ + return EmptyKeymapAdaptor{}; \ } \ + }; \ + \ + class StaticKeymap \ + { \ + private: \ + \ + static constexpr bool keymap_is_empty \ + = (sizeof(::keymaps_linear) == 0); \ + \ + typedef StaticKeymapHelper SKH; \ \ public: \ \ @@ -233,20 +285,20 @@ extern void pluginsExploreSketch(); static constexpr auto collect(const _Accumulation &op) \ -> typename _Accumulation::ResultType \ { \ - return accumulationHelper(op).apply(); \ + return SKH::accumulationHelper(::keymaps_linear, op).apply(); \ } \ \ /* COMPILE_TIME_USE_ONLY (see explanation above) \ */ \ static constexpr Key getKey(uint8_t layer, KeyAddr key_addr) { \ - return keymapAdaptor().getKey(layer, key_addr); \ + return SKH::keymapAdaptor(::keymaps_linear).getKey(layer, key_addr); \ } \ \ static constexpr uint8_t nLayers() { \ - return keymapAdaptor().n_layers; \ + return SKH::keymapAdaptor(::keymaps_linear).n_layers; \ } \ static constexpr uint8_t layerSize() { \ - return keymapAdaptor().layer_size; \ + return SKH::keymapAdaptor(::keymaps_linear).layer_size; \ } \ }; \ } /* namespace sketch_exploration */ \ diff --git a/src/kaleidoscope_internal/sketch_exploration/sketch_exploration.cpp b/src/kaleidoscope_internal/sketch_exploration/sketch_exploration.cpp new file mode 100644 index 00000000..d4ea8cf7 --- /dev/null +++ b/src/kaleidoscope_internal/sketch_exploration/sketch_exploration.cpp @@ -0,0 +1,28 @@ +/* Kaleidoscope - Firmware for computer input devices + * Copyright (C) 2013-2019 Keyboard.io, Inc. + * + * This program is free software: you can redistribute it and/or modify it under + * the terms of the GNU General Public License as published by the Free Software + * Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see . + */ + +namespace kaleidoscope { +\ +namespace sketch_exploration { + +// This empty weak symbol is necessary if the KEYMAP(...) macro +// is not used in the sketch. +// +__attribute__((weak)) +void pluginsExploreSketch() {} + +} // namespace sketch_exploration +} // namespace kaleidoscope