diff options
author | Jussi Pakkanen <jpakkane@gmail.com> | 2015-08-14 16:05:58 +0300 |
---|---|---|
committer | Jussi Pakkanen <jpakkane@gmail.com> | 2015-08-14 16:05:58 +0300 |
commit | a5abcf1fe2a033efd5c79b5220b658aa7d844197 (patch) | |
tree | 9466bfa7bf72d8da801be361a7de7061f0216dfd | |
parent | e842e6602c3a0e5aeac5ecfb4d8bb4fe7bc75093 (diff) | |
download | meson-a5abcf1fe2a033efd5c79b5220b658aa7d844197.zip meson-a5abcf1fe2a033efd5c79b5220b658aa7d844197.tar.gz meson-a5abcf1fe2a033efd5c79b5220b658aa7d844197.tar.bz2 |
Created the += operator.
-rw-r--r-- | interpreter.py | 21 | ||||
-rw-r--r-- | mparser.py | 16 | ||||
-rw-r--r-- | test cases/common/91 plusassign/meson.build | 45 | ||||
-rw-r--r-- | test cases/failing/18 wrong plusassign/meson.build | 3 |
4 files changed, 84 insertions, 1 deletions
diff --git a/interpreter.py b/interpreter.py index 3c66f86..cbc1e08 100644 --- a/interpreter.py +++ b/interpreter.py @@ -1054,6 +1054,8 @@ class Interpreter(): return self.evaluate_arithmeticstatement(cur) elif isinstance(cur, mparser.ForeachClauseNode): return self.evaluate_foreach(cur) + elif isinstance(cur, mparser.PlusAssignmentNode): + return self.evaluate_plusassign(cur) elif self.is_elementary_type(cur): return cur else: @@ -1839,6 +1841,8 @@ class Interpreter(): def array_method_call(self, obj, method_name, args): if method_name == 'contains': return self.check_contains(obj, args) + elif method_name == 'length': + return len(obj) elif method_name == 'get': index = args[0] if not isinstance(index, int): @@ -1887,6 +1891,23 @@ class Interpreter(): self.set_variable(varname, item) self.evaluate_codeblock(node.block) + def evaluate_plusassign(self, node): + assert(isinstance(node, mparser.PlusAssignmentNode)) + varname = node.var_name + addition = self.evaluate_statement(node.value) + # Remember that all variables are immutable. We must always create a + # full new variable and then assign it. + old_variable = self.get_variable(varname) + if not isinstance(old_variable, list): + raise InvalidArguments('The += operator currently only works with arrays.') + # Add other data types here. + else: + if isinstance(addition, list): + new_value = old_variable + addition + else: + new_value = old_variable + [addition] + self.set_variable(varname, new_value) + def is_elementary_type(self, v): if isinstance(v, (int, float, str, bool, list)): return True @@ -53,6 +53,7 @@ class Lexer: ('dblquote', re.compile(r'"')), ('string', re.compile(r"'([^'\\]|(\\.))*'")), ('comma', re.compile(r',')), + ('plusassign', re.compile(r'\+=')), ('dot', re.compile(r'\.')), ('plus', re.compile(r'\+')), ('dash', re.compile(r'-')), @@ -234,6 +235,14 @@ class AssignmentNode: assert(isinstance(var_name, str)) self.value = value +class PlusAssignmentNode: + def __init__(self, lineno, colno, var_name, value): + self.lineno = lineno + self.colno = colno + self.var_name = var_name + assert(isinstance(var_name, str)) + self.value = value + class ForeachClauseNode(): def __init__(self, lineno, colno, varname, items, block): self.lineno = lineno @@ -344,7 +353,12 @@ class Parser: def e1(self): left = self.e2() - if self.accept('assign'): + if self.accept('plusassign'): + value = self.e1() + if not isinstance(left, IdNode): + raise ParseException('Plusassignment target must be an id.', left.lineno, left.colno) + return PlusAssignmentNode(left.lineno, left.colno, left.value, value) + elif self.accept('assign'): value = self.e1() if not isinstance(left, IdNode): raise ParseException('Assignment target must be an id.', diff --git a/test cases/common/91 plusassign/meson.build b/test cases/common/91 plusassign/meson.build new file mode 100644 index 0000000..0093d88 --- /dev/null +++ b/test cases/common/91 plusassign/meson.build @@ -0,0 +1,45 @@ +project('plusassign', 'c') + +x = [] + +x += 'a' + +if x.length() != 1 + error('Incorrect append') +endif + +if x.get(0) != 'a' + error('Incorrect append 2.') +endif + +y = x + +x += 'b' + +if y.length() != 1 + error('Immutability broken.') +endif + +if y.get(0) != 'a' + error('Immutability broken 2.') +endif + +if x.length() != 2 + error('Incorrect append 3') +endif + +if x.get(0) != 'a' + error('Incorrect append 4.') +endif + +if x.get(1) != 'b' + error('Incorrect append 5.') +endif + +# Now with evil added: append yourself. + +x += x + +if x.length() != 4 + error('Incorrect selfappend.') +endif diff --git a/test cases/failing/18 wrong plusassign/meson.build b/test cases/failing/18 wrong plusassign/meson.build new file mode 100644 index 0000000..dfb9e6d --- /dev/null +++ b/test cases/failing/18 wrong plusassign/meson.build @@ -0,0 +1,3 @@ +project('false plusassign', 'c') + +3 += 4 |