Skip to content

Commit 3eb9a7c

Browse files
authored
Point release adding the uuid, time, and walk builtins. (#163)
In order to add support for the `time` built-ins that worked cross-platform and with the widest range of C++ compilers, we had to introduce a dependency on the [`date`](https://github.com/HowardHinnant/date) library. This contains a full implementations of the `std::chrono` functionality which will eventually be supported across most c++ compilers as part of the STL. In particular, it provides the crucial Time Zone lookup functionalities required by the Rego `time` built-ins. The Time Zone lookup requires a valid [`tzdata`](https://www.iana.org/time-zones) database from the IANA. This can either be configured to use the local system TZ data (default for Linux variants) or a manual database (default for Windows). If the `REGOCPP_USE_MANUAL_TZDATA` flag is set, then the project will download the latest database and install it as part of its build process. **New Features** - Added the `uuid` built-ins - Added the `time` built-ins - Added the `walk` built-in - It is now possible for `BuiltInDef` implementations to cache values or otherwise maintain state. To facilitate this, a new virtual `clear()` method has been added which will be called at the start of each query evaluation. **Bug Fixes** - Fixed a bug with adding zero to negative integers. Signed-off-by: Matthew Johnson <[email protected]>
1 parent cc42534 commit 3eb9a7c

Some content is hidden

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

41 files changed

+2393
-107
lines changed

.github/workflows/build_wheels.yml

+4-4
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ jobs:
1919
git config --global --add remote.origin.fetch +refs/pull/*/merge:refs/remotes/pull/*
2020
2121
- name: Build wheels
22-
uses: pypa/cibuildwheel@v2.18.1
22+
uses: pypa/cibuildwheel@v2.21.1
2323
env:
2424
CIBW_BUILD: ${{ matrix.python }}-win*
2525
CIBW_ENVIRONMENT: >
@@ -61,7 +61,7 @@ jobs:
6161
export PATH=$(python3 -m site --user-base)/bin:$PATH
6262
6363
- name: Build wheels
64-
uses: pypa/cibuildwheel@v2.18.1
64+
uses: pypa/cibuildwheel@v2.21.1
6565
env:
6666
CIBW_BUILD: ${{ matrix.python }}-macosx*
6767
CIBW_ARCHS_MACOS: arm64
@@ -90,7 +90,7 @@ jobs:
9090
git config --global --add remote.origin.fetch +refs/pull/*/merge:refs/remotes/pull/*
9191
9292
- name: Build wheels
93-
uses: pypa/cibuildwheel@v2.18.1
93+
uses: pypa/cibuildwheel@v2.21.1
9494
env:
9595
CIBW_BUILD: ${{ matrix.python }}-manylinux*
9696
CIBW_BEFORE_ALL: yum makecache && yum -y install devtoolset-10-libatomic-devel
@@ -119,7 +119,7 @@ jobs:
119119
git config --global --add remote.origin.fetch +refs/pull/*/merge:refs/remotes/pull/*
120120
121121
- name: Build wheels
122-
uses: pypa/cibuildwheel@v2.18.1
122+
uses: pypa/cibuildwheel@v2.21.1
123123
env:
124124
CIBW_BUILD: ${{ matrix.python }}-musllinux*
125125
CIBW_ENVIRONMENT: >

.github/workflows/pr_gate.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -209,7 +209,7 @@ jobs:
209209

210210
- name: CMake config
211211
run: |
212-
cmake -B ${{github.workspace}}/build --preset release-opa
212+
cmake -B ${{github.workspace}}/build --preset release-opa -DREGOCPP_TZDATA_PATH=${{github.workspace}}/build
213213
214214
- name: CMake build
215215
working-directory: ${{github.workspace}}/build

CHANGELOG

+23
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,28 @@
11
# Changelog
22

3+
## 2024-09-23 - Version 0.4.4
4+
Point release adding the `uuid`, `time`, and `walk` builtins.
5+
6+
In order to add support for the `time` built-ins that worked cross-platform and with the widest
7+
range of C++ compilers, we had to introduce a dependency on the [`date`](https://github.com/HowardHinnant/date)
8+
library. This contains a full implementations of the `std::chrono` functionality which will eventually be
9+
supported across most c++ compilers as part of the STL. In particular, it provides the crucial Time Zone
10+
lookup functionalities required by the Rego `time` built-ins. The Time Zone lookup requires a valid
11+
[`tzdata`](https://www.iana.org/time-zones) database from the IANA. This can either be configured to use the local
12+
system TZ data (default for Linux variants) or a manual database (default for Windows). If the `REGOCPP_USE_MANUAL_TZDATA` flag
13+
is set, then the project will download the latest database and install it as part of its build process.
14+
15+
**New Features**
16+
- Added the `uuid` built-ins
17+
- Added the `time` built-ins
18+
- Added the `walk` built-in
19+
- It is now possible for `BuiltInDef` implementations to cache values or otherwise maintain state. To facilitate this,
20+
a new virtual `clear()` method has been added which will be called at the start of each query evaluation.
21+
22+
**Bug Fixes**
23+
- Fixed a bug with adding zero to negative integers.
24+
25+
326
## 2024-09-10 - Version 0.4.3
427
Point release updating to Rego v0.68.0
528

CMakeLists.txt

+55-3
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ option(REGOCPP_COPY_EXAMPLES "Specifies whether to copy the examples to the inst
6969
option(REGOCPP_USE_CXX17 "Specifies whether to use C++17" OFF)
7070
option(REGOCPP_ACTION_METRICS "Specifies whether to metricate Trieste Actions" OFF)
7171
option(REGOCPP_CLEAN_INSTALL "Whether the install directory should be cleaned before install" OFF)
72+
option(REGOCPP_USE_MANUAL_TZDATA "Whether to use the manual tzdata" OFF)
7273
set(REGOCPP_SANITIZE "" CACHE STRING "Argument to pass to sanitize (disabled by default)")
7374

7475
if(REGOCPP_USE_CXX17)
@@ -90,14 +91,58 @@ FetchContent_Declare(
9091
GIT_SHALLOW FALSE
9192
)
9293

94+
FetchContent_Declare(
95+
date
96+
GIT_REPOSITORY https://github.com/HowardHinnant/date.git
97+
GIT_TAG 51ce7e131079c061533d741be5fe7cca57f2faac
98+
)
99+
93100
FetchContent_Declare(
94101
trieste
95102
GIT_REPOSITORY https://github.com/microsoft/trieste
96-
GIT_TAG 467157a167d2e929095498089f29fc9419f4ef11
103+
GIT_TAG 70a4d5f79cb574070ff69b2517b422c5126e2024
97104
)
98105

99106
FetchContent_MakeAvailable(cmake_utils)
100107

108+
if(MSVC)
109+
message("MSVC: must use manual TZ database")
110+
set(REGOCPP_USE_MANUAL_TZDATA ON)
111+
endif()
112+
113+
set(REGOCPP_TZDATA_PATH "${CMAKE_INSTALL_PREFIX}" CACHE STRING "Path to the tzdata directory")
114+
file(TO_CMAKE_PATH ${REGOCPP_TZDATA_PATH} REGOCPP_TZDATA_PATH)
115+
116+
if(REGOCPP_USE_MANUAL_TZDATA)
117+
set(MANUAL_TZ_DB ON)
118+
set(USE_SYSTEM_TZ_DB OFF)
119+
set(TZDATA_GZ_PATH "${CMAKE_CURRENT_BINARY_DIR}/tzdata-latest.tar.gz")
120+
set(TZDATA_PATH "${CMAKE_CURRENT_BINARY_DIR}/tzdata")
121+
if(NOT EXISTS ${TZDATA_PATH})
122+
message("Downloading tzdata to ${TZDATA_GZ_PATH}")
123+
# we need to download the TZ database and make it available
124+
FILE(DOWNLOAD https://www.iana.org/time-zones/repository/tzdata-latest.tar.gz ${TZDATA_GZ_PATH} SHOW_PROGRESS)
125+
message("Extracting ${TZDATA_GZ_PATH} to ${TZDATA_PATH}")
126+
FILE(ARCHIVE_EXTRACT INPUT ${TZDATA_GZ_PATH} DESTINATION ${TZDATA_PATH})
127+
128+
# Copy the tzdata directory to the specified path.
129+
message("Copying ${TZDATA_PATH} to ${REGOCPP_TZDATA_PATH}")
130+
file(COPY ${TZDATA_PATH} DESTINATION ${REGOCPP_TZDATA_PATH})
131+
if(MSVC)
132+
message("MSVC: Copying windowsZones.xml to ${REGOCPP_TZDATA_PATH}/tzdata")
133+
file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/templates/tzdata/windowsZones.xml DESTINATION ${REGOCPP_TZDATA_PATH}/tzdata)
134+
endif()
135+
endif()
136+
else()
137+
message("Attempting to use system TZ database")
138+
set(USE_SYSTEM_TZ_DB ON)
139+
set(MANUAL_TZ_DB OFF)
140+
endif()
141+
142+
set(BUILD_TZ_LIB ON)
143+
set(COMPILE_WITH_C_LOCALE ON)
144+
FetchContent_MakeAvailable_ExcludeFromAll(date)
145+
101146
set(CMAKE_POLICY_DEFAULT_CMP0077 NEW)
102147

103148
set(TRIESTE_USE_CXX17 ${REGOCPP_USE_CXX17})
@@ -195,11 +240,18 @@ if(REGOCPP_CLEAN_INSTALL)
195240
]])
196241
endif()
197242

243+
if(REGOCPP_USE_MANUAL_TZDATA)
244+
# If the install depends on this, we want to include it in the install package.
245+
INSTALL(DIRECTORY ${TZDATA_PATH} DESTINATION .)
246+
if(MSVC)
247+
INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/templates/tzdata/windowsZones.xml DESTINATION tzdata)
248+
endif()
249+
endif()
198250

199251
set(INSTALL_CONFIGDIR cmake)
200252
set(INSTALL_LIBDIR lib)
201253
set(INSTALL_INCLUDEDIR include)
202-
set(REGOCPP_INSTALL_TARGETS rego trieste json yaml snmalloc re2)
254+
set(REGOCPP_INSTALL_TARGETS rego trieste json yaml snmalloc re2 date-tz)
203255

204256
if(TRIESTE_USE_SNMALLOC)
205257
list(APPEND REGOCPP_INSTALL_TARGETS snmalloc-new-override)
@@ -257,6 +309,6 @@ export(PACKAGE ${PROJECT_NAME})
257309

258310
install(DIRECTORY include/ DESTINATION ${INSTALL_INCLUDEDIR})
259311
install(FILES
260-
${CMAKE_CURRENT_BINARY_DIR}/src/version.h
312+
${CMAKE_CURRENT_BINARY_DIR}/src/version.h
261313
DESTINATION ${INSTALL_INCLUDEDIR}/rego
262314
)

README.md

+4-6
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ library from different langauages.
7676

7777
## Language Support
7878

79-
At present we support v0.65.0 of Rego as defined by OPA, with the following grammar:
79+
We support v0.68.0 of Rego as defined by OPA, with the following grammar:
8080

8181
```ebnf
8282
module = package { import } policy
@@ -150,8 +150,7 @@ LF Line Feed
150150

151151
### Builtins
152152

153-
At the moment only support a few builtins, but are actively working on adding
154-
all the standard builtins. The following builtins are currently supported:
153+
At the moment support the following builtins are available:
155154

156155
- `aggregates`
157156
- `arrays`
@@ -165,12 +164,13 @@ all the standard builtins. The following builtins are currently supported:
165164
- `semver`
166165
- `sets`
167166
- `strings`
167+
- `time`
168168
- `types`
169169
- `units`
170+
- `uuid`
170171
- miscellaneous
171172
* `opa.runtime`
172173
* `print`
173-
* `time.now_ns`
174174

175175
### Compatibility with the OPA Rego Go implementation
176176

@@ -193,8 +193,6 @@ At present, we are **NOT** passing the following test suites in full:
193193
- `net*`
194194
- `planner-ir`
195195
- `providers-aws`
196-
- `time`
197-
- `walkbuiltin`
198196

199197
## Contributing
200198

VERSION

+1-1
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
0.4.3
1+
0.4.4

examples/rust/Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,5 @@ edition = "2021"
66
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
77

88
[dependencies]
9-
regorust = "0.4.0"
9+
regorust = "0.4.4"
1010
clap = { version = "4.0", features = ["derive"] }

include/rego/rego.hh

+19-3
Original file line numberDiff line numberDiff line change
@@ -206,7 +206,7 @@ namespace rego
206206
using BuiltIn = std::shared_ptr<BuiltInDef>;
207207

208208
/** The function pointer to the behavior of the built-in. */
209-
using BuiltInBehavior = Node (*)(const Nodes&);
209+
using BuiltInBehavior = std::function<Node(const Nodes&)>;
210210

211211
/**
212212
* This is a basic, non-optimized implementation of a big integer using
@@ -622,6 +622,18 @@ namespace rego
622622
/** The function which will be called when the built-in is evaluated. */
623623
BuiltInBehavior behavior;
624624

625+
/**
626+
* Constructor.
627+
*/
628+
BuiltInDef(Location name_, std::size_t arity_, BuiltInBehavior behavior_);
629+
630+
virtual ~BuiltInDef() = default;
631+
632+
/**
633+
* Called to clear any persistent state or caching.
634+
*/
635+
virtual void clear();
636+
625637
/**
626638
* Creates a new built-in.
627639
*
@@ -672,8 +684,12 @@ namespace rego
672684
* @param version The Rego version.
673685
* @return The result of the built-in call.
674686
*/
675-
Node call(
676-
const Location& name, const Location& version, const Nodes& args) const;
687+
Node call(const Location& name, const Location& version, const Nodes& args);
688+
689+
/**
690+
* Called to clear any persistent state or caching.
691+
*/
692+
void clear();
677693

678694
/**
679695
* Registers a built-in.

src/CMakeLists.txt

+7
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/version.h.in" "${CMAKE_CURRENT_BINARY_DIR}/version.h" @ONLY)
2+
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/builtins/tzdata.h.in" "${CMAKE_CURRENT_BINARY_DIR}/tzdata.h" @ONLY)
23

34
set( SOURCES
45
bigint.cc
@@ -59,6 +60,7 @@ builtins/strings.cc
5960
builtins/time.cc
6061
builtins/types.cc
6162
builtins/units.cc
63+
builtins/uuid.cc
6264
# third-party
6365
builtins/base64/base64.cpp
6466
)
@@ -71,11 +73,16 @@ if (REGOCPP_SPECULATIVE_LOAD_HARDENING)
7173
target_compile_options(rego PRIVATE -mllvm -x86-speculative-load-hardening)
7274
endif()
7375

76+
if (MANUAL_TZ_DB)
77+
target_compile_definitions(rego PUBLIC "MANUAL_TZ_DB")
78+
endif()
79+
7480
target_link_libraries(rego
7581
PUBLIC
7682
trieste::trieste
7783
trieste::json
7884
trieste::yaml
85+
date-tz
7986
)
8087

8188
if(MSVC)

src/bigint.cc

+5-5
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,11 @@ namespace rego
132132

133133
BigInt operator-(const BigInt& lhs, const BigInt& rhs)
134134
{
135+
if (rhs.is_zero())
136+
{
137+
return lhs;
138+
}
139+
135140
bool negate = false;
136141
if (lhs.is_negative())
137142
{
@@ -173,11 +178,6 @@ namespace rego
173178
}
174179
}
175180

176-
if (rhs.is_zero())
177-
{
178-
return lhs;
179-
}
180-
181181
std::string difference =
182182
BigInt::subtract(lhs.digits(), rhs.digits(), negate);
183183
return BigInt(difference);

src/builtins.cc

+17-1
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,13 @@ namespace
3838

3939
namespace rego
4040
{
41+
BuiltInDef::BuiltInDef(
42+
Location name_, std::size_t arity_, BuiltInBehavior behavior_) :
43+
name(name_), arity(arity_), behavior(behavior_)
44+
{}
45+
46+
void BuiltInDef::clear() {}
47+
4148
BuiltIn BuiltInDef::create(
4249
const Location& name, std::size_t arity, BuiltInBehavior behavior)
4350
{
@@ -46,6 +53,14 @@ namespace rego
4653

4754
BuiltInsDef::BuiltInsDef() noexcept : m_strict_errors(false) {}
4855

56+
void BuiltInsDef::clear()
57+
{
58+
for (auto& builtin : m_builtins)
59+
{
60+
builtin.second->clear();
61+
}
62+
}
63+
4964
bool BuiltInsDef::strict_errors() const
5065
{
5166
return m_strict_errors;
@@ -91,7 +106,7 @@ namespace rego
91106
}
92107

93108
Node BuiltInsDef::call(
94-
const Location& name, const Location& version, const Nodes& args) const
109+
const Location& name, const Location& version, const Nodes& args)
95110
{
96111
if (!is_builtin(name))
97112
{
@@ -164,6 +179,7 @@ namespace rego
164179
register_builtins(builtins::time());
165180
register_builtins(builtins::types());
166181
register_builtins(builtins::units());
182+
register_builtins(builtins::uuid());
167183

168184
return *this;
169185
}

src/builtins/builtins.h

+1
Original file line numberDiff line numberDiff line change
@@ -21,5 +21,6 @@ namespace rego
2121
std::vector<BuiltIn> time();
2222
std::vector<BuiltIn> types();
2323
std::vector<BuiltIn> units();
24+
std::vector<BuiltIn> uuid();
2425
}
2526
}

0 commit comments

Comments
 (0)