Add 'GLOBAL' keyword #122
Also provides functionality that makes things like overriding the built in 'print' possible. See #67
This commit is contained in:
parent
fdcc5959c7
commit
cf4efacbe8
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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) :
|
||||
|
@ -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
18
unittests/global.chai
Normal 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();
|
||||
|
Loading…
x
Reference in New Issue
Block a user