use mk_val
This commit is contained in:
parent
da7bbe5813
commit
c08f4ddf01
|
|
@ -28,7 +28,7 @@ bool is_val(const value & ptr) {
|
|||
return dynamic_cast<const PointeeType*>(ptr.get()) != nullptr;
|
||||
}
|
||||
template<typename T, typename... Args>
|
||||
bool mk_val(Args&&... args) {
|
||||
value mk_val(Args&&... args) {
|
||||
using PointeeType = typename extract_pointee<T>::type;
|
||||
return std::make_unique<PointeeType>(std::forward<Args>(args)...);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,12 +13,12 @@ const func_builtins & value_int_t::get_builtins() const {
|
|||
{"abs", [](const func_args & args) -> value {
|
||||
args.ensure_vals<value_int>();
|
||||
int64_t val = args.args[0]->as_int();
|
||||
return std::make_unique<value_int_t>(val < 0 ? -val : val);
|
||||
return mk_val<value_int>(val < 0 ? -val : val);
|
||||
}},
|
||||
{"float", [](const func_args & args) -> value {
|
||||
args.ensure_vals<value_int>();
|
||||
double val = static_cast<double>(args.args[0]->as_int());
|
||||
return std::make_unique<value_float_t>(val);
|
||||
return mk_val<value_float>(val);
|
||||
}},
|
||||
};
|
||||
return builtins;
|
||||
|
|
@ -30,12 +30,12 @@ const func_builtins & value_float_t::get_builtins() const {
|
|||
{"abs", [](const func_args & args) -> value {
|
||||
args.ensure_vals<value_float>();
|
||||
double val = args.args[0]->as_float();
|
||||
return std::make_unique<value_float_t>(val < 0.0 ? -val : val);
|
||||
return mk_val<value_float>(val < 0.0 ? -val : val);
|
||||
}},
|
||||
{"int", [](const func_args & args) -> value {
|
||||
args.ensure_vals<value_float>();
|
||||
int64_t val = static_cast<int64_t>(args.args[0]->as_float());
|
||||
return std::make_unique<value_int_t>(val);
|
||||
return mk_val<value_int>(val);
|
||||
}},
|
||||
};
|
||||
return builtins;
|
||||
|
|
@ -74,28 +74,28 @@ const func_builtins & value_string_t::get_builtins() const {
|
|||
args.ensure_vals<value_string>();
|
||||
std::string str = args.args[0]->as_string();
|
||||
std::transform(str.begin(), str.end(), str.begin(), ::toupper);
|
||||
return std::make_unique<value_string_t>(str);
|
||||
return mk_val<value_string>(str);
|
||||
}},
|
||||
{"lower", [](const func_args & args) -> value {
|
||||
args.ensure_vals<value_string>();
|
||||
std::string str = args.args[0]->as_string();
|
||||
std::transform(str.begin(), str.end(), str.begin(), ::tolower);
|
||||
return std::make_unique<value_string_t>(str);
|
||||
return mk_val<value_string>(str);
|
||||
}},
|
||||
{"strip", [](const func_args & args) -> value {
|
||||
args.ensure_vals<value_string>();
|
||||
std::string str = args.args[0]->as_string();
|
||||
return std::make_unique<value_string_t>(string_strip(str, true, true));
|
||||
return mk_val<value_string>(string_strip(str, true, true));
|
||||
}},
|
||||
{"rstrip", [](const func_args & args) -> value {
|
||||
args.ensure_vals<value_string>();
|
||||
std::string str = args.args[0]->as_string();
|
||||
return std::make_unique<value_string_t>(string_strip(str, false, true));
|
||||
return mk_val<value_string>(string_strip(str, false, true));
|
||||
}},
|
||||
{"lstrip", [](const func_args & args) -> value {
|
||||
args.ensure_vals<value_string>();
|
||||
std::string str = args.args[0]->as_string();
|
||||
return std::make_unique<value_string_t>(string_strip(str, true, false));
|
||||
return mk_val<value_string>(string_strip(str, true, false));
|
||||
}},
|
||||
{"title", [](const func_args & args) -> value {
|
||||
args.ensure_vals<value_string>();
|
||||
|
|
@ -111,7 +111,7 @@ const func_builtins & value_string_t::get_builtins() const {
|
|||
c = ::tolower(static_cast<unsigned char>(c));
|
||||
}
|
||||
}
|
||||
return std::make_unique<value_string_t>(str);
|
||||
return mk_val<value_string>(str);
|
||||
}},
|
||||
{"capitalize", [](const func_args & args) -> value {
|
||||
args.ensure_vals<value_string>();
|
||||
|
|
@ -120,38 +120,38 @@ const func_builtins & value_string_t::get_builtins() const {
|
|||
str[0] = ::toupper(static_cast<unsigned char>(str[0]));
|
||||
std::transform(str.begin() + 1, str.end(), str.begin() + 1, ::tolower);
|
||||
}
|
||||
return std::make_unique<value_string_t>(str);
|
||||
return mk_val<value_string>(str);
|
||||
}},
|
||||
{"length", [](const func_args & args) -> value {
|
||||
args.ensure_vals<value_string>();
|
||||
std::string str = args.args[0]->as_string();
|
||||
return std::make_unique<value_int_t>(str.length());
|
||||
return mk_val<value_int>(str.length());
|
||||
}},
|
||||
{"startswith", [](const func_args & args) -> value {
|
||||
args.ensure_vals<value_string, value_string>();
|
||||
std::string str = args.args[0]->as_string();
|
||||
std::string prefix = args.args[1]->as_string();
|
||||
return std::make_unique<value_bool_t>(string_startswith(str, prefix));
|
||||
return mk_val<value_bool>(string_startswith(str, prefix));
|
||||
}},
|
||||
{"endswith", [](const func_args & args) -> value {
|
||||
args.ensure_vals<value_string, value_string>();
|
||||
std::string str = args.args[0]->as_string();
|
||||
std::string suffix = args.args[1]->as_string();
|
||||
return std::make_unique<value_bool_t>(string_endswith(str, suffix));
|
||||
return mk_val<value_bool>(string_endswith(str, suffix));
|
||||
}},
|
||||
{"split", [](const func_args & args) -> value {
|
||||
args.ensure_vals<value_string>();
|
||||
std::string str = args.args[0]->as_string();
|
||||
std::string delim = (args.args.size() > 1) ? args.args[1]->as_string() : " ";
|
||||
auto result = std::make_unique<value_array_t>();
|
||||
auto result = mk_val<value_array>();
|
||||
size_t pos = 0;
|
||||
std::string token;
|
||||
while ((pos = str.find(delim)) != std::string::npos) {
|
||||
token = str.substr(0, pos);
|
||||
result->val_arr->push_back(std::make_unique<value_string_t>(token));
|
||||
result->val_arr->push_back(mk_val<value_string>(token));
|
||||
str.erase(0, pos + delim.length());
|
||||
}
|
||||
result->val_arr->push_back(std::make_unique<value_string_t>(str));
|
||||
result->val_arr->push_back(mk_val<value_string>(str));
|
||||
return std::move(result);
|
||||
}},
|
||||
{"replace", [](const func_args & args) -> value {
|
||||
|
|
@ -164,13 +164,13 @@ const func_builtins & value_string_t::get_builtins() const {
|
|||
str.replace(pos, old_str.length(), new_str);
|
||||
pos += new_str.length();
|
||||
}
|
||||
return std::make_unique<value_string_t>(str);
|
||||
return mk_val<value_string>(str);
|
||||
}},
|
||||
{"int", [](const func_args & args) -> value {
|
||||
args.ensure_vals<value_string>();
|
||||
std::string str = args.args[0]->as_string();
|
||||
try {
|
||||
return std::make_unique<value_int_t>(std::stoi(str));
|
||||
return mk_val<value_int>(std::stoi(str));
|
||||
} catch (...) {
|
||||
throw std::runtime_error("Cannot convert string '" + str + "' to int");
|
||||
}
|
||||
|
|
@ -179,7 +179,7 @@ const func_builtins & value_string_t::get_builtins() const {
|
|||
args.ensure_vals<value_string>();
|
||||
std::string str = args.args[0]->as_string();
|
||||
try {
|
||||
return std::make_unique<value_float_t>(std::stod(str));
|
||||
return mk_val<value_float>(std::stod(str));
|
||||
} catch (...) {
|
||||
throw std::runtime_error("Cannot convert string '" + str + "' to float");
|
||||
}
|
||||
|
|
@ -187,7 +187,7 @@ const func_builtins & value_string_t::get_builtins() const {
|
|||
{"string", [](const func_args & args) -> value {
|
||||
// no-op
|
||||
args.ensure_vals<value_string>();
|
||||
return std::make_unique<value_string_t>(args.args[0]->as_string());
|
||||
return mk_val<value_string>(args.args[0]->as_string());
|
||||
}},
|
||||
{"indent", [](const func_args & args) -> value {
|
||||
throw std::runtime_error("indent builtin not implemented");
|
||||
|
|
@ -205,17 +205,17 @@ const func_builtins & value_bool_t::get_builtins() const {
|
|||
{"int", [](const func_args & args) -> value {
|
||||
args.ensure_vals<value_bool>();
|
||||
bool val = args.args[0]->as_bool();
|
||||
return std::make_unique<value_int_t>(val ? 1 : 0);
|
||||
return mk_val<value_int>(val ? 1 : 0);
|
||||
}},
|
||||
{"float", [](const func_args & args) -> value {
|
||||
args.ensure_vals<value_bool>();
|
||||
bool val = args.args[0]->as_bool();
|
||||
return std::make_unique<value_float_t>(val ? 1.0 : 0.0);
|
||||
return mk_val<value_float>(val ? 1.0 : 0.0);
|
||||
}},
|
||||
{"string", [](const func_args & args) -> value {
|
||||
args.ensure_vals<value_bool>();
|
||||
bool val = args.args[0]->as_bool();
|
||||
return std::make_unique<value_string_t>(val ? "True" : "False");
|
||||
return mk_val<value_string>(val ? "True" : "False");
|
||||
}},
|
||||
};
|
||||
return builtins;
|
||||
|
|
@ -227,7 +227,7 @@ const func_builtins & value_array_t::get_builtins() const {
|
|||
{"list", [](const func_args & args) -> value {
|
||||
args.ensure_vals<value_array>();
|
||||
const auto & arr = args.args[0]->as_array();
|
||||
auto result = std::make_unique<value_array_t>();
|
||||
auto result = mk_val<value_array>();
|
||||
for (const auto& v : arr) {
|
||||
result->val_arr->push_back(v->clone());
|
||||
}
|
||||
|
|
@ -237,7 +237,7 @@ const func_builtins & value_array_t::get_builtins() const {
|
|||
args.ensure_vals<value_array>();
|
||||
const auto & arr = args.args[0]->as_array();
|
||||
if (arr.empty()) {
|
||||
return std::make_unique<value_undefined_t>();
|
||||
return mk_val<value_undefined>();
|
||||
}
|
||||
return arr[0]->clone();
|
||||
}},
|
||||
|
|
@ -245,14 +245,14 @@ const func_builtins & value_array_t::get_builtins() const {
|
|||
args.ensure_vals<value_array>();
|
||||
const auto & arr = args.args[0]->as_array();
|
||||
if (arr.empty()) {
|
||||
return std::make_unique<value_undefined_t>();
|
||||
return mk_val<value_undefined>();
|
||||
}
|
||||
return arr[arr.size() - 1]->clone();
|
||||
}},
|
||||
{"length", [](const func_args & args) -> value {
|
||||
args.ensure_vals<value_array>();
|
||||
const auto & arr = args.args[0]->as_array();
|
||||
return std::make_unique<value_int_t>(static_cast<int64_t>(arr.size()));
|
||||
return mk_val<value_int>(static_cast<int64_t>(arr.size()));
|
||||
}},
|
||||
// TODO: reverse, sort, join, string, unique
|
||||
};
|
||||
|
|
@ -270,22 +270,22 @@ const func_builtins & value_object_t::get_builtins() const {
|
|||
if (it != obj.end()) {
|
||||
return it->second->clone();
|
||||
} else {
|
||||
return std::make_unique<value_undefined_t>();
|
||||
return mk_val<value_undefined>();
|
||||
}
|
||||
}},
|
||||
{"keys", [](const func_args & args) -> value {
|
||||
args.ensure_vals<value_object>();
|
||||
const auto & obj = args.args[0]->as_object();
|
||||
auto result = std::make_unique<value_array_t>();
|
||||
auto result = mk_val<value_array>();
|
||||
for (const auto & pair : obj) {
|
||||
result->val_arr->push_back(std::make_unique<value_string_t>(pair.first));
|
||||
result->val_arr->push_back(mk_val<value_string>(pair.first));
|
||||
}
|
||||
return result;
|
||||
}},
|
||||
{"values", [](const func_args & args) -> value {
|
||||
args.ensure_vals<value_object>();
|
||||
const auto & obj = args.args[0]->as_object();
|
||||
auto result = std::make_unique<value_array_t>();
|
||||
auto result = mk_val<value_array>();
|
||||
for (const auto & pair : obj) {
|
||||
result->val_arr->push_back(pair.second->clone());
|
||||
}
|
||||
|
|
@ -294,10 +294,10 @@ const func_builtins & value_object_t::get_builtins() const {
|
|||
{"items", [](const func_args & args) -> value {
|
||||
args.ensure_vals<value_object>();
|
||||
const auto & obj = args.args[0]->as_object();
|
||||
auto result = std::make_unique<value_array_t>();
|
||||
auto result = mk_val<value_array>();
|
||||
for (const auto & pair : obj) {
|
||||
auto item = std::make_unique<value_array_t>();
|
||||
item->val_arr->push_back(std::make_unique<value_string_t>(pair.first));
|
||||
auto item = mk_val<value_array>();
|
||||
item->val_arr->push_back(mk_val<value_string>(pair.first));
|
||||
item->val_arr->push_back(pair.second->clone());
|
||||
result->val_arr->push_back(std::move(item));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,16 +28,16 @@ value binary_expression::execute(context & ctx) {
|
|||
// Equality operators
|
||||
value right_val = right->execute(ctx);
|
||||
if (op.value == "==") {
|
||||
return std::make_unique<value_bool_t>(left_val == right_val);
|
||||
return mk_val<value_bool>(left_val == right_val);
|
||||
} else if (op.value == "!=") {
|
||||
return std::make_unique<value_bool_t>(left_val != right_val);
|
||||
return mk_val<value_bool>(left_val != right_val);
|
||||
}
|
||||
|
||||
// Handle undefined and null values
|
||||
if (is_val<value_undefined>(left_val) || is_val<value_undefined>(right_val)) {
|
||||
if (is_val<value_undefined>(right_val) && (op.value == "in" || op.value == "not in")) {
|
||||
// Special case: `anything in undefined` is `false` and `anything not in undefined` is `true`
|
||||
return std::make_unique<value_bool_t>(op.value == "not in");
|
||||
return mk_val<value_bool>(op.value == "not in");
|
||||
}
|
||||
throw std::runtime_error("Cannot perform operation " + op.value + " on undefined values");
|
||||
} else if (is_val<value_null>(left_val) || is_val<value_null>(right_val)) {
|
||||
|
|
@ -46,7 +46,7 @@ value binary_expression::execute(context & ctx) {
|
|||
|
||||
// String concatenation with ~
|
||||
if (op.value == "~") {
|
||||
return std::make_unique<value_string_t>(left_val->as_string() + right_val->as_string());
|
||||
return mk_val<value_string>(left_val->as_string() + right_val->as_string());
|
||||
}
|
||||
|
||||
// Float operations
|
||||
|
|
@ -58,28 +58,28 @@ value binary_expression::execute(context & ctx) {
|
|||
double res = (op.value == "+") ? a + b : (op.value == "-") ? a - b : a * b;
|
||||
bool is_float = is_val<value_float>(left_val) || is_val<value_float>(right_val);
|
||||
if (is_float) {
|
||||
return std::make_unique<value_float_t>(res);
|
||||
return mk_val<value_float>(res);
|
||||
} else {
|
||||
return std::make_unique<value_int_t>(static_cast<int64_t>(res));
|
||||
return mk_val<value_int>(static_cast<int64_t>(res));
|
||||
}
|
||||
} else if (op.value == "/") {
|
||||
return std::make_unique<value_float_t>(a / b);
|
||||
return mk_val<value_float>(a / b);
|
||||
} else if (op.value == "%") {
|
||||
double rem = std::fmod(a, b);
|
||||
bool is_float = is_val<value_float>(left_val) || is_val<value_float>(right_val);
|
||||
if (is_float) {
|
||||
return std::make_unique<value_float_t>(rem);
|
||||
return mk_val<value_float>(rem);
|
||||
} else {
|
||||
return std::make_unique<value_int_t>(static_cast<int64_t>(rem));
|
||||
return mk_val<value_int>(static_cast<int64_t>(rem));
|
||||
}
|
||||
} else if (op.value == "<") {
|
||||
return std::make_unique<value_bool_t>(a < b);
|
||||
return mk_val<value_bool>(a < b);
|
||||
} else if (op.value == ">") {
|
||||
return std::make_unique<value_bool_t>(a > b);
|
||||
return mk_val<value_bool>(a > b);
|
||||
} else if (op.value == ">=") {
|
||||
return std::make_unique<value_bool_t>(a >= b);
|
||||
return mk_val<value_bool>(a >= b);
|
||||
} else if (op.value == "<=") {
|
||||
return std::make_unique<value_bool_t>(a <= b);
|
||||
return mk_val<value_bool>(a <= b);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -88,7 +88,7 @@ value binary_expression::execute(context & ctx) {
|
|||
if (op.value == "+") {
|
||||
auto & left_arr = left_val->as_array();
|
||||
auto & right_arr = right_val->as_array();
|
||||
auto result = std::make_unique<value_array_t>();
|
||||
auto result = mk_val<value_array>();
|
||||
for (const auto & item : left_arr) {
|
||||
result->val_arr->push_back(item->clone());
|
||||
}
|
||||
|
|
@ -101,16 +101,16 @@ value binary_expression::execute(context & ctx) {
|
|||
auto & arr = right_val->as_array();
|
||||
bool member = std::find_if(arr.begin(), arr.end(), [&](const value& v) { return v == left_val; }) != arr.end();
|
||||
if (op.value == "in") {
|
||||
return std::make_unique<value_bool_t>(member);
|
||||
return mk_val<value_bool>(member);
|
||||
} else if (op.value == "not in") {
|
||||
return std::make_unique<value_bool_t>(!member);
|
||||
return mk_val<value_bool>(!member);
|
||||
}
|
||||
}
|
||||
|
||||
// String concatenation
|
||||
if (is_val<value_string>(left_val) || is_val<value_string>(right_val)) {
|
||||
if (op.value == "+") {
|
||||
return std::make_unique<value_string_t>(left_val->as_string() + right_val->as_string());
|
||||
return mk_val<value_string>(left_val->as_string() + right_val->as_string());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -119,9 +119,9 @@ value binary_expression::execute(context & ctx) {
|
|||
auto left_str = left_val->as_string();
|
||||
auto right_str = right_val->as_string();
|
||||
if (op.value == "in") {
|
||||
return std::make_unique<value_bool_t>(right_str.find(left_str) != std::string::npos);
|
||||
return mk_val<value_bool>(right_str.find(left_str) != std::string::npos);
|
||||
} else if (op.value == "not in") {
|
||||
return std::make_unique<value_bool_t>(right_str.find(left_str) == std::string::npos);
|
||||
return mk_val<value_bool>(right_str.find(left_str) == std::string::npos);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -131,9 +131,9 @@ value binary_expression::execute(context & ctx) {
|
|||
auto & obj = right_val->as_object();
|
||||
bool has_key = obj.find(key) != obj.end();
|
||||
if (op.value == "in") {
|
||||
return std::make_unique<value_bool_t>(has_key);
|
||||
return mk_val<value_bool>(has_key);
|
||||
} else if (op.value == "not in") {
|
||||
return std::make_unique<value_bool_t>(!has_key);
|
||||
return mk_val<value_bool>(!has_key);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue