Add 'GLOBAL' keyword #122

Also provides functionality that makes things like overriding the built in
'print' possible. See #67
This commit is contained in:
Jason Turner 2015-05-04 11:47:36 -06:00
parent fdcc5959c7
commit cf4efacbe8
7 changed files with 81 additions and 4 deletions

View File

@ -167,6 +167,12 @@ auto j; // equiv to var
var k = 5; // initialized to 5 (integer)
var l := k; // reference to k
auto &m = k; // reference to k
GLOBAL g = 5; // creates a global variable. If global already exists, it is not re-added
GLOBAL g = 2; // global 'g' now equals 2
GLOBAL g2;
if (g2.is_var_undef()) { g2 = 4; } // only initialize g2 once, if GLOBAL decl hit more than once
```
## Built in Types

View File

@ -487,6 +487,23 @@ namespace chaiscript
}
}
/// Adds a new global (non-const) shared object, between all the threads
Boxed_Value add_global_no_throw(const Boxed_Value &obj, const std::string &name)
{
validate_object_name(name);
chaiscript::detail::threading::unique_lock<chaiscript::detail::threading::shared_mutex> l(m_global_object_mutex);
const auto itr = m_state.m_global_objects.find(name);
if (itr == m_state.m_global_objects.end())
{
m_state.m_global_objects.insert(std::make_pair(name, obj));
return obj;
} else {
return itr->second;
}
}
/// Adds a new global (non-const) shared object, between all the threads
void add_global(const Boxed_Value &obj, const std::string &name)

View File

@ -38,7 +38,7 @@ namespace chaiscript
Comparison, Addition, Subtraction, Multiplication, Division, Modulus, Array_Call, Dot_Access, Quoted_String, Single_Quoted_String,
Lambda, Block, Def, While, If, For, Inline_Array, Inline_Map, Return, File, Prefix, Break, Continue, Map_Pair, Value_Range,
Inline_Range, Annotation, Try, Catch, Finally, Method, Attr_Decl, Shift, Equality, Bitwise_And, Bitwise_Xor, Bitwise_Or,
Logical_And, Logical_Or, Reference, Switch, Case, Default, Ternary_Cond, Noop, Class, Binary, Arg
Logical_And, Logical_Or, Reference, Switch, Case, Default, Ternary_Cond, Noop, Class, Binary, Arg, Global_Decl
};
};

View File

@ -346,6 +346,9 @@ namespace chaiscript
m_engine.add_reserved_word("true");
m_engine.add_reserved_word("false");
m_engine.add_reserved_word("class");
m_engine.add_reserved_word("attr");
m_engine.add_reserved_word("var");
m_engine.add_reserved_word("GLOBAL");
m_engine.add_reserved_word("_");
if (t_lib)

View File

@ -539,6 +539,33 @@ namespace chaiscript
}
};
struct Global_Decl_AST_Node : public AST_Node {
public:
Global_Decl_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector<AST_NodePtr> t_children) :
AST_Node(std::move(t_ast_node_text), AST_Node_Type::Global_Decl, std::move(t_loc), std::move(t_children)) { }
virtual ~Global_Decl_AST_Node() {}
virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss) const CHAISCRIPT_OVERRIDE {
const std::string &idname =
[&]()->const std::string &{
if (children[0]->identifier == AST_Node_Type::Reference) {
return children[0]->children[0]->text;
} else {
return children[0]->text;
}
}();
try {
return t_ss.add_global_no_throw(Boxed_Value(), idname);
}
catch (const exception::reserved_word_error &) {
throw exception::eval_error("Reserved word used as global '" + idname + "'");
}
}
};
struct Var_Decl_AST_Node : public AST_Node {
public:
Var_Decl_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector<AST_NodePtr> t_children) :

View File

@ -323,8 +323,6 @@ namespace chaiscript
if (is_deep) {
new_children.assign(std::make_move_iterator(m_match_stack.begin() + static_cast<int>(t_match_start)),
std::make_move_iterator(m_match_stack.end()));
// new_children = std::vector<AST_NodePtr>(std::make_move_iterator(m_match_stack.begin() + static_cast<int>(t_match_start)),
// std::make_move_iterator(m_match_stack.end()));
m_match_stack.erase(m_match_stack.begin() + static_cast<int>(t_match_start), m_match_stack.end());
}
@ -1970,7 +1968,7 @@ namespace chaiscript
}
build_match<eval::Attr_Decl_AST_Node>(prev_stack_top);
} else if (Keyword("auto") || Keyword("var")) {
} else if (Keyword("auto") || Keyword("var") ) {
retval = true;
if (!(Reference() || Id())) {
@ -1978,6 +1976,14 @@ namespace chaiscript
}
build_match<eval::Var_Decl_AST_Node>(prev_stack_top);
} else if (Keyword("GLOBAL")) {
retval = true;
if (!(Reference() || Id())) {
throw exception::eval_error("Incomplete global declaration", File_Position(m_line, m_col), *m_filename);
}
build_match<eval::Global_Decl_AST_Node>(prev_stack_top);
} else if (Keyword("attr")) {
retval = true;

18
unittests/global.chai Normal file
View File

@ -0,0 +1,18 @@
// Test global
GLOBAL g = 3;
assert_true(g == 3);
var v := g;
assert_true(v == 3);
GLOBAL g = 2;
assert_true(g == 2);
assert_true(v == 2);
def f() {
assert_true(g == 2);
}
f();