From 8b08ca3cca5d070bff0bf09ef27ecd722acdbb6f Mon Sep 17 00:00:00 2001 From: yhirose Date: Tue, 7 Jul 2015 15:44:33 -0400 Subject: [PATCH] Added assert function. --- language/interpreter.cc | 3 +++ language/interpreter.hpp | 17 +++++++++++++++ language/samples/test.cul | 46 +++++++++++++++++++++++++++++++++++++++ peglib.h | 27 +++++++++++++++-------- 4 files changed, 84 insertions(+), 9 deletions(-) create mode 100644 language/samples/test.cul diff --git a/language/interpreter.cc b/language/interpreter.cc index 7185a89..e5000f1 100644 --- a/language/interpreter.cc +++ b/language/interpreter.cc @@ -118,6 +118,9 @@ private: callEnv->initialize(param.name, val, param.mut); } + callEnv->initialize("__LINE__", Value((long)ast.line), false); + callEnv->initialize("__COLUMN__", Value((long)ast.column), false); + return fv.eval(callEnv); } diff --git a/language/interpreter.hpp b/language/interpreter.hpp index 363269a..51217ab 100644 --- a/language/interpreter.hpp +++ b/language/interpreter.hpp @@ -269,6 +269,23 @@ struct Environment } }), false); + + initialize( + "assert", + Value(Value::FunctionValue { + { {"arg", true} }, + [](std::shared_ptr env) { + auto cond = env->get("arg").to_bool(); + if (!cond) { + auto line = env->get("__LINE__").to_long(); + auto column = env->get("__COLUMN__").to_long(); + std::string msg = "assert failed at " + std::to_string(line) + ":" + std::to_string(column) + "."; + throw std::runtime_error(msg); + } + return Value(); + } + }), + false); } private: diff --git a/language/samples/test.cul b/language/samples/test.cul new file mode 100644 index 0000000..75c1c5a --- /dev/null +++ b/language/samples/test.cul @@ -0,0 +1,46 @@ + +test_sum = fn () { + mut i = 1 + mut ret = 0 + while i <= 10 { + ret = ret + i + i = i + 1 + } + + assert(ret == 55) +} + +test_fib = fn () { + fib = fn (x) { + if x < 2 { + x + } else { + self(x - 2) + self(x -1) + } + } + + ret = fib(15) + + assert(ret == 610) +} + +test_closure = fn () { + make_func = fn (mut x) { + mut n = 100 + fn () { + n = n + 1 + x = x + 1 + n + } + } + + f = make_func(10) + f() + f() + ret = f() + + assert(ret == 319) +} + +test_sum() +test_fib() +test_closure() diff --git a/peglib.h b/peglib.h index cd803a0..cc7887f 100644 --- a/peglib.h +++ b/peglib.h @@ -180,6 +180,7 @@ struct SemanticValue struct SemanticValues : protected std::vector { + const char* ss; const char* s; size_t n; size_t choice; @@ -474,6 +475,7 @@ struct Context if (!sv.empty()) { sv.clear(); } + sv.ss = s; sv.s = nullptr; sv.n = 0; return sv; @@ -1941,14 +1943,16 @@ const int AstDefaultTag = -1; struct Ast { - Ast(const char* _name, int _tag, const std::vector>& _nodes) - : name(_name), tag(_tag), is_token(false), nodes(_nodes) {} + Ast(size_t _line, size_t _column, const char* _name, int _tag, const std::vector>& _nodes) + : line(_line), column(_column), name(_name), tag(_tag), is_token(false), nodes(_nodes) {} - Ast(const char* _name, int _tag, const std::string& _token) - : name(_name), tag(_tag), is_token(true), token(_token) {} + Ast(size_t _line, size_t _column, const char* _name, int _tag, const std::string& _token) + : line(_line), column(_column), name(_name), tag(_tag), is_token(true), token(_token) {} void print() const; + const size_t line; + const size_t column; const std::string name; const int tag; const bool is_token; @@ -2008,7 +2012,8 @@ public: bool load_grammar(const char* s, size_t n, const Rules& rules) { grammar_ = PEGParser::parse( - s, n, rules, + s, n, + rules, start_, [&](const char* s, size_t n, size_t id, const std::string& name) { if (match_action) match_action(s, n, id, name); @@ -2172,13 +2177,15 @@ private: auto is_token = rule.is_token; rule = [info, is_token](const SemanticValues& sv) { if (is_token) { - return std::make_shared(info.name, info.tag, std::string(sv.s, sv.n)); + auto line = line_info(sv.ss, sv.s); + return std::make_shared(line.first, line.second, info.name, info.tag, std::string(sv.s, sv.n)); } if (info.optimize_nodes && sv.size() == 1) { std::shared_ptr ast = sv[0].get>(); return ast; } - return std::make_shared(info.name, info.tag, sv.transform>()); + auto line = line_info(sv.ss, sv.s); + return std::make_shared(line.first, line.second, info.name, info.tag, sv.transform>()); }; } @@ -2190,13 +2197,15 @@ private: auto is_token = rule.is_token; rule.action = [=](const SemanticValues& sv) { if (is_token) { - return std::make_shared(name.c_str(), AstDefaultTag, std::string(sv.s, sv.n)); + auto line = line_info(sv.ss, sv.s); + return std::make_shared(line.first, line.second, name.c_str(), AstDefaultTag, std::string(sv.s, sv.n)); } if (optimize_nodes && sv.size() == 1) { std::shared_ptr ast = sv[0].get>(); return ast; } - return std::make_shared(name.c_str(), AstDefaultTag, sv.transform>()); + auto line = line_info(sv.ss, sv.s); + return std::make_shared(line.first, line.second, name.c_str(), AstDefaultTag, sv.transform>()); }; } }