Skip to content

Commit

Permalink
feat: add support for delayable clock types
Browse files Browse the repository at this point in the history
  • Loading branch information
sillydan1 committed Sep 12, 2022
1 parent 43ecd13 commit a6aae17
Show file tree
Hide file tree
Showing 19 changed files with 263 additions and 6 deletions.
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ add_library(${PROJECT_NAME} SHARED
src/drivers/interpreter.cpp
src/drivers/compiler.cpp

src/clock.cpp
src/symbol_table.cpp
src/operations/add.cpp
src/operations/subtract.cpp
Expand Down
42 changes: 42 additions & 0 deletions include/clock.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
/* MIT License
*
* Copyright (c) 2022 Asger Gitz-Johansen
*
* 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.
*/
#ifndef EXPR_CLOCK_H
#define EXPR_CLOCK_H
#include <ostream>

namespace expr {
struct clock_t {
unsigned int time_units = 0;
void reset();
void delay(unsigned int delta);
auto operator+=(const unsigned int& delta) -> clock_t&;
auto operator==(const clock_t& o) const -> bool;
auto operator!=(const clock_t& o) const -> bool;
};

auto operator"" _ms(unsigned long long val) -> clock_t;
auto operator<<(std::ostream& o, const clock_t& c) -> std::ostream&;
auto stoclk(const char* str) -> clock_t;
}

#endif //EXPR_CLOCK_H
10 changes: 6 additions & 4 deletions include/symbol_table.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,10 @@
#include <tree>
#include <hashcombine>
#include <overload>
#include "clock.h"

namespace expr {
using underlying_symbol_value_t = std::variant<int, float, bool, std::string>;
using underlying_symbol_value_t = std::variant<int, float, bool, std::string, clock_t>;
struct symbol_value_t : public underlying_symbol_value_t {
symbol_value_t() = default;

Expand Down Expand Up @@ -76,11 +77,12 @@ namespace expr {
auto is_overlapping(const symbol_table_t& other) -> bool;
auto is_overlapping_and_not_idempotent(const symbol_table_t& other) -> bool;
auto is_completely_overlapping(const symbol_table_t& other) -> bool;
void delay(unsigned int time_units);
};

symbol_table_t operator+(const symbol_table_t &a, const symbol_table_t &b);
std::ostream &operator<<(std::ostream &os, const symbol_value_t &v);
std::ostream &operator<<(std::ostream &os, const symbol_table_t &m);
auto operator+(const symbol_table_t &a, const symbol_table_t &b) -> symbol_table_t;
auto operator<<(std::ostream &os, const symbol_value_t &v) -> std::ostream&;
auto operator<<(std::ostream &os, const symbol_table_t &m) -> std::ostream&;

enum class operator_type_t {
minus, plus, star, slash, percent, hat,
Expand Down
63 changes: 63 additions & 0 deletions src/clock.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
/* MIT License
*
* Copyright (c) 2022 Asger Gitz-Johansen
*
* 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.
*/
#include "clock.h"
#include <iostream>

namespace expr {
void clock_t::reset() {
time_units = 0;
}
void clock_t::delay(unsigned int delta) {
time_units += delta;
}
auto clock_t::operator+=(const unsigned int& delta) -> clock_t& {
delay(delta);
return *this;
}
auto clock_t::operator==(const clock_t& o) const -> bool {
return time_units == o.time_units;
}
auto clock_t::operator!=(const clock_t& o) const -> bool {
return !(*this == o);
}

auto operator"" _ms(unsigned long long val) -> clock_t {
clock_t v{}; v.time_units = val;
return v;
}

auto operator<<(std::ostream& o, const clock_t& c) -> std::ostream& {
return o << c.time_units;
}

auto stoclk(const char* str) -> clock_t {
std::string s{str};
auto loc = s.find( "_ms", 0 );
if(loc == std::string::npos)
throw std::invalid_argument("not a clock_t value "+s);
auto i = std::stoi(s.substr(0, loc));
clock_t c{};
c.time_units = i;
return c;
}
}
2 changes: 2 additions & 0 deletions src/drivers/z3_driver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ namespace expr {
[this](const float& f) { return c.real_val(std::to_string(f).c_str()); },
[this](const bool& b) { return c.bool_val(b); },
[this](const std::string& sv) { return c.string_val(sv); },
[this](const expr::clock_t& v){ return c.int_val(v.time_units); },
[](auto&& x){ throw std::logic_error("unable to convert symbol value to z3::expr"); }
), static_cast<const underlying_symbol_value_t&>(val));
}
Expand All @@ -109,6 +110,7 @@ namespace expr {
[this, &ref](const float& _) { return c.real_const(ref.ident.c_str()); },
[this, &ref](const bool& _) { return c.bool_const(ref.ident.c_str()); },
[this, &ref](const std::string& _) { return c.string_const(ref.ident.c_str()); },
[this, &ref](const expr::clock_t& _){ return c.int_const(ref.ident.c_str()); },
[](auto&& x){ throw std::logic_error("unable to convert symbol reference to z3::expr"); }
), static_cast<const underlying_symbol_value_t&>(it->second));
}
Expand Down
15 changes: 15 additions & 0 deletions src/operations/add.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,21 @@ template<> auto t_add(const float& x, const float& y) {
template<> auto t_add(const std::string& x, const std::string& y) {
return x + y;
}
template<> auto t_add(const expr::clock_t& x, const expr::clock_t& y) {
return expr::clock_t{x.time_units + y.time_units};
}
template<> auto t_add(const expr::clock_t& x, const int& y) {
return expr::clock_t{x.time_units + y};
}
template<> auto t_add(const int& x, const expr::clock_t& y) {
return (int)(x + y.time_units);
}
template<> auto t_add(const expr::clock_t& x, const float& y) {
return expr::clock_t{x.time_units + (int)y};
}
template<> auto t_add(const float& x, const expr::clock_t& y) {
return x + y.time_units;
}

symbol_value_t add(const symbol_value_t& a, const symbol_value_t& b) {
symbol_value_t res{};
Expand Down
30 changes: 30 additions & 0 deletions src/operations/boolean.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -127,37 +127,67 @@ auto t_implies(const bool& a, const bool& b) {

auto t_gt(const int& a, const int& b) {return a > b;}
auto t_gt(const int& a, const float& b) {return a > b;}
auto t_gt(const int& a, const expr::clock_t& b) {return a > b.time_units;}
auto t_gt(const float& a, const int& b) {return a > b;}
auto t_gt(const float& a, const float& b) {return a > b;}
auto t_gt(const float& a, const expr::clock_t& b) {return a > b.time_units;}
auto t_gt(const expr::clock_t& a, const expr::clock_t& b) {return a.time_units > b.time_units;}
auto t_gt(const expr::clock_t& a, const int& b) {return a.time_units > b;}
auto t_gt(const expr::clock_t& a, const float& b) {return a.time_units > b;}

auto t_ge(const int& a, const int& b) {return a >= b;}
auto t_ge(const int& a, const float& b) {return a >= b;}
auto t_ge(const int& a, const expr::clock_t& b) {return a >= b.time_units;}
auto t_ge(const float& a, const int& b) {return a >= b;}
auto t_ge(const float& a, const float& b) {return a >= b;}
auto t_ge(const float& a, const expr::clock_t& b) {return a >= b.time_units;}
auto t_ge(const expr::clock_t& a, const expr::clock_t& b) {return a.time_units >= b.time_units;}
auto t_ge(const expr::clock_t& a, const int& b) {return a.time_units >= b;}
auto t_ge(const expr::clock_t& a, const float& b) {return a.time_units >= b;}

auto t_ee(const bool& a, const bool& b) {return a == b;}
auto t_ee(const int& a, const int& b) {return a == b;}
auto t_ee(const int& a, const float& b) {return a == b;}
auto t_ee(const int& a, const expr::clock_t& b) {return a == b.time_units;}
auto t_ee(const float& a, const int& b) {return a == b;}
auto t_ee(const float& a, const float& b) {return a == b;}
auto t_ee(const float& a, const expr::clock_t& b) {return a == b.time_units;}
auto t_ee(const expr::clock_t& a, const expr::clock_t& b) {return a.time_units == b.time_units;}
auto t_ee(const expr::clock_t& a, const int& b) {return a.time_units == b;}
auto t_ee(const expr::clock_t& a, const float& b) {return a.time_units == b;}
auto t_ee(const std::string& a, const std::string& b) {return a == b;}

auto t_ne(const bool& a, const bool& b) {return a != b;}
auto t_ne(const int& a, const int& b) {return a != b;}
auto t_ne(const int& a, const float& b) {return a != b;}
auto t_ne(const int& a, const expr::clock_t& b) {return a != b.time_units;}
auto t_ne(const float& a, const int& b) {return a != b;}
auto t_ne(const float& a, const float& b) {return a != b;}
auto t_ne(const float& a, const expr::clock_t& b) {return a != b.time_units;}
auto t_ne(const expr::clock_t& a, const expr::clock_t& b) {return a.time_units != b.time_units;}
auto t_ne(const expr::clock_t& a, const int& b) {return a.time_units != b;}
auto t_ne(const expr::clock_t& a, const float& b) {return a.time_units != b;}
auto t_ne(const std::string& a, const std::string& b) {return a != b;}

auto t_lt(const int& a, const int& b) {return a < b;}
auto t_lt(const int& a, const float& b) {return a < b;}
auto t_lt(const int& a, const expr::clock_t& b) {return a < b.time_units;}
auto t_lt(const float& a, const int& b) {return a < b;}
auto t_lt(const float& a, const float& b) {return a < b;}
auto t_lt(const float& a, const expr::clock_t& b) {return a < b.time_units;}
auto t_lt(const expr::clock_t& a, const expr::clock_t& b) {return a.time_units < b.time_units;}
auto t_lt(const expr::clock_t& a, const int& b) {return a.time_units < b;}
auto t_lt(const expr::clock_t& a, const float& b) {return a.time_units < b;}

auto t_le(const int& a, const int& b) {return a <= b;}
auto t_le(const int& a, const float& b) {return a <= b;}
auto t_le(const int& a, const expr::clock_t& b) {return a <= b.time_units;}
auto t_le(const float& a, const int& b) {return a <= b;}
auto t_le(const float& a, const float& b) {return a <= b;}
auto t_le(const float& a, const expr::clock_t& b) {return a <= b.time_units;}
auto t_le(const expr::clock_t& a, const expr::clock_t& b) {return a.time_units <= b.time_units;}
auto t_le(const expr::clock_t& a, const int& b) {return a.time_units <= b;}
auto t_le(const expr::clock_t& a, const float& b) {return a.time_units <= b;}

symbol_value_t and_(const symbol_value_t& a, const symbol_value_t& b) {
symbol_value_t res{};
Expand Down
25 changes: 25 additions & 0 deletions src/operations/divide.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,31 @@ template<> auto t_divide(const float& x, const float& y) {
throw std::domain_error("Cannot divide with zero or INT_MIN / -1");
return x / y;
}
template<> auto t_divide(const expr::clock_t& x, const expr::clock_t& y) {
if(y.time_units == 0)
throw std::domain_error("Cannot divide with zero or INT_MIN / -1");
return expr::clock_t{x.time_units / y.time_units};
}
template<> auto t_divide(const int& x, const expr::clock_t& y) {
if(y.time_units == 0)
throw std::domain_error("Cannot divide with zero or INT_MIN / -1");
return (int)(x / y.time_units);
}
template<> auto t_divide(const expr::clock_t& x, const int& y) {
if(y == 0)
throw std::domain_error("Cannot divide with zero or INT_MIN / -1");
return expr::clock_t{x.time_units / y};
}
template<> auto t_divide(const float& x, const expr::clock_t& y) {
if(y.time_units == 0)
throw std::domain_error("Cannot divide with zero or INT_MIN / -1");
return x / y.time_units;
}
template<> auto t_divide(const expr::clock_t& x, const float& y) {
if(y == 0.0f)
throw std::domain_error("Cannot divide with zero or INT_MIN / -1");
return x.time_units / y;
}

symbol_value_t divide(const symbol_value_t& a, const symbol_value_t& b) {
symbol_value_t res{};
Expand Down
9 changes: 9 additions & 0 deletions src/operations/modulo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,15 @@ auto t_modulo(const T1&, const T2&) {
template<> auto t_modulo(const int& x, const int& y) {
return x % y;
}
template<> auto t_modulo(const expr::clock_t& x, const int& y) {
return (int)(x.time_units % y);
}
template<> auto t_modulo(const expr::clock_t& x, const expr::clock_t& y) {
return expr::clock_t{x.time_units % y.time_units};
}
template<> auto t_modulo(const int& x, const expr::clock_t& y) {
return expr::clock_t{x % y.time_units};
}

symbol_value_t modulo(const symbol_value_t& a, const symbol_value_t& b) {
symbol_value_t res{};
Expand Down
15 changes: 15 additions & 0 deletions src/operations/multiply.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,21 @@ template<> auto t_multiply(const int& x, const float& y) {
template<> auto t_multiply(const float& x, const float& y) {
return x * y;
}
template<> auto t_multiply(const expr::clock_t& x, const expr::clock_t& y) {
return expr::clock_t{x.time_units * y.time_units};
}
template<> auto t_multiply(const expr::clock_t& x, const float& y) {
return x.time_units * y;
}
template<> auto t_multiply(const expr::clock_t& x, const int& y) {
return expr::clock_t{x.time_units * y};
}
template<> auto t_multiply(const int& x, const expr::clock_t& y) {
return (int)(x * y.time_units);
}
template<> auto t_multiply(const float& x, const expr::clock_t& y) {
return x * y.time_units;
}

symbol_value_t multiply(const symbol_value_t& a, const symbol_value_t& b) {
symbol_value_t res{};
Expand Down
15 changes: 15 additions & 0 deletions src/operations/pow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,21 @@ template<> auto t_pow(const int& x, const float& y) {
template<> auto t_pow(const float& x, const float& y) {
return static_cast<float>(pow(x,y));
}
template<> auto t_pow(const expr::clock_t& x, const expr::clock_t& y) {
return expr::clock_t{static_cast<unsigned int>(pow(x.time_units, y.time_units))};
}
template<> auto t_pow(const expr::clock_t& x, const float& y) {
return static_cast<float>(pow(x.time_units, y));
}
template<> auto t_pow(const expr::clock_t& x, const int& y) {
return expr::clock_t{static_cast<unsigned int>(pow(x.time_units, y))};
}
template<> auto t_pow(const int& x, const expr::clock_t& y) {
return static_cast<int>(pow(x, y.time_units));
}
template<> auto t_pow(const float& x, const expr::clock_t& y) {
return static_cast<float>(pow(x, y.time_units));
}

symbol_value_t pow(const symbol_value_t& a, const symbol_value_t& b) {
symbol_value_t res{};
Expand Down
15 changes: 15 additions & 0 deletions src/operations/subtract.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,21 @@ template<> auto t_subtract(const int& x, const float& y) {
template<> auto t_subtract(const float& x, const float& y) {
return x - y;
}
template<> auto t_subtract(const expr::clock_t& x, const expr::clock_t& y) {
return expr::clock_t{x.time_units - y.time_units};
}
template<> auto t_subtract(const expr::clock_t& x, const int& y) {
return expr::clock_t{x.time_units - y};
}
template<> auto t_subtract(const int& x, const expr::clock_t& y) {
return (int)(x - y.time_units);
}
template<> auto t_subtract(const expr::clock_t& x, const float& y) {
return expr::clock_t{x.time_units - (int)y};
}
template<> auto t_subtract(const float& x, const expr::clock_t& y) {
return x - y.time_units;
}

symbol_value_t subtract(const symbol_value_t& a, const symbol_value_t& b) {
symbol_value_t res{};
Expand Down
9 changes: 9 additions & 0 deletions src/parser/lex/footer.l
Original file line number Diff line number Diff line change
Expand Up @@ -27,3 +27,12 @@ PARSER_NS ::parser::symbol_type make_BOOL(std::string s, const PARSER_NS ::parse
std::istringstream(s) >> std::boolalpha >> b;
return PARSER_NS ::parser::make_BOOL(b, loc);
}

PARSER_NS ::parser::symbol_type make_CLOCK(const std::string &s, const PARSER_NS ::parser::location_type& loc) {
try {
auto c = expr::stoclk(s.c_str());
return PARSER_NS ::parser::make_CLOCK(c, loc);
} catch(std::out_of_range& e) {
throw PARSER_NS ::parser::syntax_error (loc, "clock value is out of range: " + s);
}
}
1 change: 1 addition & 0 deletions src/parser/lex/lexer.l
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ m4_changequote()
{int} return make_NUMBER(yytext, loc);
{flt} return make_FLOAT(yytext, loc);
{str} return make_STRING(yytext, loc);
{clk} return make_CLOCK(yytext, loc);
{bool} return make_BOOL(yytext, loc);
{id} return PARSER_NS ::parser::make_IDENTIFIER (yytext, loc);
. { throw PARSER_NS ::parser::syntax_error(loc, "invalid character: " + std::string(yytext)); }
Expand Down
1 change: 1 addition & 0 deletions src/parser/lex/skeleton.l
Original file line number Diff line number Diff line change
Expand Up @@ -79,4 +79,5 @@ m4_changequote()
PARSER_NS ::parser::symbol_type make_FLOAT(const std::string &s, const PARSER_NS ::parser::location_type& loc);
PARSER_NS ::parser::symbol_type make_STRING(const std::string &s, const PARSER_NS ::parser::location_type& loc);
PARSER_NS ::parser::symbol_type make_BOOL(std::string s, const PARSER_NS ::parser::location_type& loc);
PARSER_NS ::parser::symbol_type make_CLOCK(const std::string& s, const PARSER_NS ::parser::location_type& loc);
%}
Loading

0 comments on commit a6aae17

Please sign in to comment.