Skip to content

Commit

Permalink
Add size expression for containers and strings
Browse files Browse the repository at this point in the history
{% print size("test") %}
{% print size(vector) %}

{% for i in range(0, size(vec), 1) %}
  {= vec[i] =}
{% endfor %}

Signed-off-by: Jose Ricardo Ziviani <[email protected]>
  • Loading branch information
jrziviani committed May 22, 2019
1 parent 1da0a07 commit dd93e1e
Show file tree
Hide file tree
Showing 4 changed files with 82 additions and 15 deletions.
4 changes: 4 additions & 0 deletions include/context.h
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,10 @@ namespace amps

inline object context::stack_top() const
{
if (stack_.empty()) {
return std::nullopt;
}

return stack_.look_back();
}

Expand Down
35 changes: 25 additions & 10 deletions include/object.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ namespace amps
NUMBER,
STRING,
BOOL,
OBJECT,
};

inline std::ostream& operator<<(std::ostream &os, const vobject_types &obj)
Expand All @@ -33,6 +34,10 @@ namespace amps
case vobject_types::STRING:
os << "string";
break;

case vobject_types::OBJECT:
os << "object";
break;
}

return os;
Expand All @@ -41,6 +46,7 @@ namespace amps
class vobject
{
var_t data_;
vobject_types ftype_;

public:
vobject()
Expand All @@ -49,6 +55,20 @@ namespace amps

vobject(var_t value) :
data_(value)
{
if (std::holds_alternative<std::string>(data_)) {
ftype_ = vobject_types::STRING;
}
else if (std::holds_alternative<number_t>(data_)) {
ftype_ = vobject_types::NUMBER;
}
else {
ftype_ = vobject_types::BOOL;
}
}

vobject(var_t value, vobject_types forced_type) :
data_(value), ftype_(forced_type)
{
}

Expand All @@ -59,9 +79,9 @@ namespace amps
vobject &operator=(const vobject &) = default;
vobject &operator=(vobject &&) = default;

vobject_types get_type() const;
bool get_bool_or(bool alt) const;
number_t get_number_or(number_t alt) const;
vobject_types get_type() const;
std::string get_string_or(const std::string &alt) const;
std::string to_string() const;
};
Expand Down Expand Up @@ -98,15 +118,7 @@ namespace amps

inline vobject_types vobject::get_type() const
{
if (std::holds_alternative<bool>(data_)) {
return vobject_types::BOOL;
}
else if (std::holds_alternative<number_t>(data_)) {
return vobject_types::NUMBER;
}
else {
return vobject_types::STRING;
}
return ftype_;
}

inline std::string vobject::to_string() const
Expand All @@ -120,6 +132,9 @@ namespace amps

case vobject_types::STRING:
return get_string_or("");

case vobject_types::OBJECT:
return get_string_or("");
}

return "<null>";
Expand Down
44 changes: 43 additions & 1 deletion src/compiler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -776,6 +776,48 @@ namespace amps
context_.stack_push(object_t(false));
return true;
}
else if (it.match(token_types::SIZE)) {
if (it.match(token_types::LEFT_PAREN)) {
if (!parse_expression(it)) {
return false;
}

if (context_.stack_empty()) {
return false;
}

vobject_types tp = context_.stack_top_type();
if (tp == vobject_types::STRING) {
std::string data = context_.stack_pop_string_or("");
context_.stack_push(object_t(data.size()));
}
else if (tp == vobject_types::NUMBER) {
number_t data = context_.stack_pop_number_or(0);
context_.stack_push(object_t(sizeof(data)));
}
else if (tp == vobject_types::BOOL) {
context_.stack_pop();
context_.stack_push(object_t(number_t(1)));
}
else if (tp == vobject_types::OBJECT) {
std::string data = context_.stack_pop_string_or("");
context_.stack_push(object_t(context_.environment_get_size(data)));
}

if (!it.match(token_types::RIGHT_PAREN)) {
error_.critical("size expects a closing ')'. Line: ",
it.range().line);
return false;
}

return true;
}
else {
error_.critical("size expects an opening '('", ". Line: ",
it.range().line);
return false;
}
}
else if (it.match(token_types::IDENTIFIER)) {
string id = it.look_back().value().value_or("");
if (!context_.environment_is_key_defined(id)) {
Expand Down Expand Up @@ -814,7 +856,7 @@ namespace amps
}
else {
context_.stack_pop();
context_.stack_push(object_t(std::string("<null>")));
context_.stack_push(object_t(std::string("")));
}

if (!it.match(token_types::RIGHT_BRACKET)) {
Expand Down
14 changes: 10 additions & 4 deletions src/context.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,15 @@ namespace amps
using T = std::decay_t<decltype(var)>;

if constexpr (std::is_same_v<T, number_t> ||
std::is_same_v<T, std::string>) {
std::is_same_v<T, std::string> ||
std::is_same_v<T, bool>) {
stack_push(object_t(var));
}

// object exists but it's not a simple number or string
// evaluate it to true to represent that it's valid
else {
stack_push(object_t(true));
stack_push(object_t(key, vobject_types::OBJECT));
}

return true;
Expand All @@ -43,7 +44,7 @@ namespace amps

// make sure we're not accessing out of bounds item
if (index >= var.size()) {
stack_push(object_t(std::string("<null>")));
stack_push(object_t(std::string("")));
return false;
}
else {
Expand All @@ -58,6 +59,11 @@ namespace amps
bool context::stack_push_from_environment(const std::string &key,
const std::string &user_key)
{
if (key.size() == 0 || user_key.size() == 0) {
stack_push(object_t(std::string("")));
return false;
}

// simply push the value of environment_[key] onto the stack
// this method handles map<string, string> and map<string, number_t>
// values, so the key of that map is also required
Expand All @@ -69,7 +75,7 @@ namespace amps

// make sure that the key exists
if (var.find(user_key) == var.end()) {
stack_push(object_t(std::string("<null>")));
stack_push(object_t(std::string("")));
return false;
}
else {
Expand Down

0 comments on commit dd93e1e

Please sign in to comment.