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 k = 5; // initialized to 5 (integer)
|
||||||
var l := k; // reference to k
|
var l := k; // reference to k
|
||||||
auto &m = 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
|
## 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
|
/// Adds a new global (non-const) shared object, between all the threads
|
||||||
void add_global(const Boxed_Value &obj, const std::string &name)
|
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,
|
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,
|
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,
|
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("true");
|
||||||
m_engine.add_reserved_word("false");
|
m_engine.add_reserved_word("false");
|
||||||
m_engine.add_reserved_word("class");
|
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("_");
|
m_engine.add_reserved_word("_");
|
||||||
|
|
||||||
if (t_lib)
|
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 {
|
struct Var_Decl_AST_Node : public AST_Node {
|
||||||
public:
|
public:
|
||||||
Var_Decl_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector<AST_NodePtr> t_children) :
|
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) {
|
if (is_deep) {
|
||||||
new_children.assign(std::make_move_iterator(m_match_stack.begin() + static_cast<int>(t_match_start)),
|
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()));
|
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());
|
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);
|
build_match<eval::Attr_Decl_AST_Node>(prev_stack_top);
|
||||||
} else if (Keyword("auto") || Keyword("var")) {
|
} else if (Keyword("auto") || Keyword("var") ) {
|
||||||
retval = true;
|
retval = true;
|
||||||
|
|
||||||
if (!(Reference() || Id())) {
|
if (!(Reference() || Id())) {
|
||||||
@ -1978,6 +1976,14 @@ namespace chaiscript
|
|||||||
}
|
}
|
||||||
|
|
||||||
build_match<eval::Var_Decl_AST_Node>(prev_stack_top);
|
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")) {
|
} else if (Keyword("attr")) {
|
||||||
retval = true;
|
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