From 4f088365e49d28e0d413d42eb024c3ff6cbfee35 Mon Sep 17 00:00:00 2001 From: Xavier Claessens Date: Wed, 18 Jul 2018 09:57:34 -0400 Subject: [PATCH] interpreter: Add support for dict addition --- docs/markdown/Reference-manual.md | 3 +++ docs/markdown/snippets/dict_add.md | 10 ++++++++++ mesonbuild/interpreterbase.py | 14 ++++++++++---- test cases/common/197 dict/meson.build | 12 ++++++++++++ 4 files changed, 35 insertions(+), 4 deletions(-) create mode 100644 docs/markdown/snippets/dict_add.md diff --git a/docs/markdown/Reference-manual.md b/docs/markdown/Reference-manual.md index a7b8a2b06..3ae740df8 100644 --- a/docs/markdown/Reference-manual.md +++ b/docs/markdown/Reference-manual.md @@ -1859,6 +1859,9 @@ statement](Syntax.md#foreach-statements). Dictionaries are available since 0.47.0. +Since 0.48.0 dictionaries can be added (e.g. `d1 = d2 + d3` and `d1 += d2`). +Values from the second dictionary overrides values from the first. + ## Returned objects These are objects returned by the [functions listed above](#functions). diff --git a/docs/markdown/snippets/dict_add.md b/docs/markdown/snippets/dict_add.md new file mode 100644 index 000000000..cde5b5736 --- /dev/null +++ b/docs/markdown/snippets/dict_add.md @@ -0,0 +1,10 @@ +## Dictionary addition + +Dictionaries can now be added, values from the second dictionary overrides values +from the first + +```meson +d1 = {'a' : 'b'} +d3 = d1 + {'a' : 'c'} +d3 += {'d' : 'e'} +``` diff --git a/mesonbuild/interpreterbase.py b/mesonbuild/interpreterbase.py index fd732bc6f..1c74eeb41 100644 --- a/mesonbuild/interpreterbase.py +++ b/mesonbuild/interpreterbase.py @@ -573,6 +573,8 @@ The result of this is undefined and will become a hard error in a future Meson r return r if cur.operation == 'add': + if isinstance(l, dict) and isinstance(r, dict): + return {**l, **r} try: return l + r except Exception as e: @@ -651,14 +653,18 @@ The result of this is undefined and will become a hard error in a future Meson r if not isinstance(addition, int): raise InvalidArguments('The += operator requires an int on the right hand side if the variable on the left is an int') new_value = old_variable + addition - elif not isinstance(old_variable, list): - raise InvalidArguments('The += operator currently only works with arrays, strings or ints ') - # Add other data types here. - else: + elif isinstance(old_variable, list): if isinstance(addition, list): new_value = old_variable + addition else: new_value = old_variable + [addition] + elif isinstance(old_variable, dict): + if not isinstance(addition, dict): + raise InvalidArguments('The += operator requires a dict on the right hand side if the variable on the left is a dict') + new_value = {**old_variable, **addition} + # Add other data types here. + else: + raise InvalidArguments('The += operator currently only works with arrays, dicts, strings or ints ') self.set_variable(varname, new_value) def evaluate_indexing(self, node): diff --git a/test cases/common/197 dict/meson.build b/test cases/common/197 dict/meson.build index e1ee2e33b..41eea3193 100644 --- a/test cases/common/197 dict/meson.build +++ b/test cases/common/197 dict/meson.build @@ -21,3 +21,15 @@ empty_dict = {} foreach key, value : empty_dict assert(false, 'This dict should be empty') endforeach + +d1 = empty_dict + {'a' : 'b'} +assert(d1 == {'a' : 'b'}, 'dict addition is not working') + +d2 = d1 + {'a' : 'b2', 'c' : 'd'} +assert(d2 == {'a' : 'b2', 'c' : 'd'}, 'dict addition is not working') +assert(d1 == {'a' : 'b'}, 'dict should be immutable') + +d3 = d2 +d3 += {'e' : 'f'} +assert(d3 == {'a' : 'b2', 'c' : 'd', 'e' : 'f'}, 'dict plusassign is not working') +assert(d2 == {'a' : 'b2', 'c' : 'd'}, 'dict should be immutable')