aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJussi Pakkanen <jpakkane@gmail.com>2015-08-14 16:05:58 +0300
committerJussi Pakkanen <jpakkane@gmail.com>2015-08-14 16:05:58 +0300
commita5abcf1fe2a033efd5c79b5220b658aa7d844197 (patch)
tree9466bfa7bf72d8da801be361a7de7061f0216dfd
parente842e6602c3a0e5aeac5ecfb4d8bb4fe7bc75093 (diff)
downloadmeson-a5abcf1fe2a033efd5c79b5220b658aa7d844197.zip
meson-a5abcf1fe2a033efd5c79b5220b658aa7d844197.tar.gz
meson-a5abcf1fe2a033efd5c79b5220b658aa7d844197.tar.bz2
Created the += operator.
-rw-r--r--interpreter.py21
-rw-r--r--mparser.py16
-rw-r--r--test cases/common/91 plusassign/meson.build45
-rw-r--r--test cases/failing/18 wrong plusassign/meson.build3
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
diff --git a/mparser.py b/mparser.py
index 6d6eb4d..83d9cca 100644
--- a/mparser.py
+++ b/mparser.py
@@ -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