size_t pos; // position in source, for debugging
virtual ~statement() = default;
virtual std::string type() const { return "Statement"; }
+
// execute_impl must be overridden by derived classes
- virtual value execute_impl(context &) { throw std::runtime_error("cannot exec " + type()); }
+ virtual value execute_impl(context &) { throw_exec_error(); }
// execute is the public method to execute a statement with error handling
value execute(context &);
+
+private:
+ [[noreturn]] void throw_exec_error() const {
+ throw std::runtime_error("cannot exec " + type());
+ }
};
// Type Checking Utilities
program() = default;
explicit program(statements && body) : body(std::move(body)) {}
std::string type() const override { return "Program"; }
- value execute_impl(context &) override {
+ [[noreturn]] value execute_impl(context &) override {
throw std::runtime_error("Cannot execute program directly, use jinja::runtime instead");
}
};
}
};
- value execute_impl(context &) override {
+ [[noreturn]] value execute_impl(context &) override {
throw break_statement::signal();
}
};
}
};
- value execute_impl(context &) override {
+ [[noreturn]] value execute_impl(context &) override {
throw continue_statement::signal();
}
};
chk_type<expression>(this->step_expr);
}
std::string type() const override { return "SliceExpression"; }
- value execute_impl(context &) override {
+ [[noreturn]] value execute_impl(context &) override {
throw std::runtime_error("must be handled by MemberExpression");
}
};
return str.compare(str.length() - suffix.length(), suffix.length(), suffix) == 0;
}
+[[noreturn]] static value string_join_not_implemented(const func_args &) {
+ throw not_implemented_exception("String join builtin not implemented");
+}
+
const func_builtins & value_string_t::get_builtins() const {
static const func_builtins builtins = {
{"default", default_value},
res->val_str.mark_input_based_on(val_input->as_string());
return res;
}},
- {"join", [](const func_args &) -> value {
- throw not_implemented_exception("String join builtin not implemented");
- }},
+ {"join", string_join_not_implemented},
};
return builtins;
}
return builtins;
}
+[[noreturn]] static value array_unique_not_implemented(const func_args &) {
+ throw not_implemented_exception("Array unique builtin not implemented");
+}
const func_builtins & value_array_t::get_builtins() const {
static const func_builtins builtins = {
std::reverse(arr.begin(), arr.end());
return is_val<value_tuple>(val) ? mk_val<value_tuple>(std::move(arr)) : mk_val<value_array>(std::move(arr));
}},
- {"unique", [](const func_args &) -> value {
- throw not_implemented_exception("Array unique builtin not implemented");
- }},
+ {"unique", array_unique_not_implemented},
};
return builtins;
}
+[[noreturn]] static value object_join_not_implemented(const func_args &) {
+ throw not_implemented_exception("object join not implemented");
+}
const func_builtins & value_object_t::get_builtins() const {
if (!has_builtins) {
});
return result;
}},
- {"join", [](const func_args &) -> value {
- throw not_implemented_exception("object join not implemented");
- }},
+ {"join", object_join_not_implemented},
};
return builtins;
}
// Note: only for debugging and error reporting purposes
virtual std::string type() const { return ""; }
- virtual int64_t as_int() const { throw std::runtime_error(type() + " is not an int value"); }
- virtual double as_float() const { throw std::runtime_error(type() + " is not a float value"); }
- virtual string as_string() const { throw std::runtime_error(type() + " is not a string value"); }
- virtual bool as_bool() const { throw std::runtime_error(type() + " is not a bool value"); }
- virtual const std::vector<value> & as_array() const { throw std::runtime_error(type() + " is not an array value"); }
- virtual const std::vector<std::pair<value, value>> & as_ordered_object() const { throw std::runtime_error(type() + " is not an object value"); }
- virtual value invoke(const func_args &) const { throw std::runtime_error(type() + " is not a function value"); }
+ virtual int64_t as_int() const { throw_type_error("is not an int value"); }
+ virtual double as_float() const { throw_type_error("is not a float value"); }
+ virtual string as_string() const { throw_type_error("is not a string value"); }
+ virtual bool as_bool() const { throw_type_error("is not a bool value"); }
+ virtual const std::vector<value> & as_array() const { throw_type_error("is not an array value"); }
+ virtual const std::vector<std::pair<value, value>> & as_ordered_object() const { throw_type_error("is not an object value"); }
+ virtual value invoke(const func_args &) const { throw_type_error("is not a function value"); }
virtual bool is_none() const { return false; }
virtual bool is_undefined() const { return false; }
- virtual const func_builtins & get_builtins() const {
- throw std::runtime_error("No builtins available for type " + type());
- }
+ virtual const func_builtins & get_builtins() const { throw_type_error("has no builtins"); }
- virtual bool has_key(const value &) { throw std::runtime_error(type() + " is not an object value"); }
- virtual void insert(const value & /* key */, const value & /* val */) { throw std::runtime_error(type() + " is not an object value"); }
- virtual value & at(const value & /* key */, value & /* default_val */) { throw std::runtime_error(type() + " is not an object value"); }
- virtual value & at(const value & /* key */) { throw std::runtime_error(type() + " is not an object value"); }
- virtual value & at(const std::string & /* key */, value & /* default_val */) { throw std::runtime_error(type() + " is not an object value"); }
- virtual value & at(const std::string & /* key */) { throw std::runtime_error(type() + " is not an object value"); }
- virtual value & at(int64_t /* idx */, value & /* default_val */) { throw std::runtime_error(type() + " is not an array value"); }
- virtual value & at(int64_t /* idx */) { throw std::runtime_error(type() + " is not an array value"); }
+ virtual bool has_key(const value &) { throw_type_error("is not an object value"); }
+ virtual void insert(const value & /* key */, const value & /* val */) { throw_type_error("is not an object value"); }
+ virtual value & at(const value & /* key */, value & /* default_val */) { throw_type_error("is not an object value"); }
+ virtual value & at(const value & /* key */) { throw_type_error("is not an object value"); }
+ virtual value & at(const std::string & /* key */, value & /* default_val */) { throw_type_error("is not an object value"); }
+ virtual value & at(const std::string & /* key */) { throw_type_error("is not an object value"); }
+ virtual value & at(int64_t /* idx */, value & /* default_val */) { throw_type_error("is not an array value"); }
+ virtual value & at(int64_t /* idx */) { throw_type_error("is not an array value"); }
virtual bool is_numeric() const { return false; }
virtual bool is_hashable() const { return false; }
// Note: only for debugging purposes
virtual std::string as_repr() const { return as_string().str(); }
+private:
+ [[noreturn]] void throw_type_error(const char* expected) const {
+ throw std::runtime_error(type() + " " + expected);
+ }
+
protected:
virtual bool equivalent(const value_t &) const = 0;
virtual bool nonequal(const value_t & other) const { return !equivalent(other); }