Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ build-backend = "scikit_build_core.build"

[project]
name = "openscad_cpp_evaluator"
version = "0.32.1"
version = "0.32.2"
description = "C++ OpenSCAD evaluator with Python bindings"
readme = "README.md"
requires-python = ">=3.12"
Expand Down
25 changes: 23 additions & 2 deletions src/builtins/function_builtins.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -691,8 +691,29 @@ Value evalBuiltinFunction(Evaluator& ev, const std::string& name, const CallArgs
}
return Value{false};
}
case BuiltinFnId::Version: return numList({2025.0, 1.0, 1.0});
case BuiltinFnId::VersionNum: return Value{20250101.0};
// The OpenSCAD release we track. version_num() is that same
// year/month/day folded as y * 10000 + m * 100 + d, exactly like the
// reference's own builtin_version_num (builtin_functions.cc).
case BuiltinFnId::Version: return numList({2026.0, 1.0, 1.0});
case BuiltinFnId::VersionNum: {
// The optional vector argument the reference also accepts: with
// no argument this is our own version() folded; with one, it is
// whatever [y, m] / [y, m, d] the caller passed, so
// version_num([2019, 5, 0]) == 20190500 regardless of what
// release we report. A 2-element vector defaults the day to 0
// (getVec3's own defaultval), and anything else -- a non-list, a
// wrong length, a non-numeric element -- is undef.
//
// One deliberate divergence: the reference's size-2 path ignores
// getVec2's own failure and folds uninitialized doubles for e.g.
// version_num(["a", "b"]). That is undef here rather than
// whatever happened to be on the stack.
const Value* arg = args.findPositional(0);
if (!arg) return Value{20260101.0};
const auto v = allNumericList(*arg);
if (!v || (v->size() != 2 && v->size() != 3)) return Value{};
return Value{(*v)[0] * 10000.0 + (*v)[1] * 100.0 + (v->size() == 3 ? (*v)[2] : 0.0)};
}
case BuiltinFnId::ParentModule:
return ev.parentModuleName(static_cast<int>(toDoubleLenient(getArg(args, 0, "index", Value{0.0}))));
}
Expand Down
29 changes: 28 additions & 1 deletion tests/test_function_builtins.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -369,14 +369,41 @@ TEST(StringListBuiltins, FunctionValuedObjectMemberIsCallable) {

TEST(StringListBuiltins, VersionBuiltins) {
Evaluator ev;
EXPECT_DOUBLE_EQ(asNum(evalSrc("version_num()", ev)), 20250101.0);
EXPECT_DOUBLE_EQ(asNum(evalSrc("version_num()", ev)), 20260101.0);
}

// version_num() also takes the optional vector the reference's own
// builtin_version_num does -- it folds whatever y/m/d it is handed, not just
// this build's release.
TEST(StringListBuiltins, VersionNumFoldsAGivenVersionVector) {
Evaluator ev;
EXPECT_DOUBLE_EQ(asNum(evalSrc("version_num([2019, 5, 0])", ev)), 20190500.0);
EXPECT_DOUBLE_EQ(asNum(evalSrc("version_num([2021, 1, 0])", ev)), 20210100.0);
// A 2-element vector defaults the day to 0 (getVec3's own defaultval).
EXPECT_DOUBLE_EQ(asNum(evalSrc("version_num([2019, 5])", ev)), 20190500.0);
}

TEST(StringListBuiltins, VersionNumRejectsAnythingButA2Or3NumberVector) {
Evaluator ev;
EXPECT_TRUE(isUndef(evalSrc("version_num(5)", ev)));
EXPECT_TRUE(isUndef(evalSrc("version_num(undef)", ev)));
EXPECT_TRUE(isUndef(evalSrc("version_num([2019])", ev)));
EXPECT_TRUE(isUndef(evalSrc("version_num([2019, 5, 0, 7])", ev)));
EXPECT_TRUE(isUndef(evalSrc("version_num([\"a\", \"b\"])", ev)));
EXPECT_TRUE(isUndef(evalSrc("version_num([\"a\", \"b\", \"c\"])", ev)));
}

TEST(StringListBuiltins, VersionReturnsThreeElementList) {
Evaluator ev;
Value v = evalSrc("version()", ev);
const auto& items = asList(v);
ASSERT_EQ(items.size(), 3u);
// Pinned to the same release version_num() reports above -- the reference
// derives one from the other (y * 10000 + m * 100 + d, see
// builtin_version_num), so the two must not drift apart here either.
EXPECT_DOUBLE_EQ(asNum(items[0]), 2026.0);
EXPECT_DOUBLE_EQ(asNum(items[1]), 1.0);
EXPECT_DOUBLE_EQ(asNum(items[2]), 1.0);
}

TEST(StringListBuiltins, IsFunctionAndIsObject) {
Expand Down
2 changes: 1 addition & 1 deletion uv.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.