Created the += operator.

pull/227/head
Jussi Pakkanen 10 years ago
parent e842e6602c
commit a5abcf1fe2
  1. 21
      interpreter.py
  2. 16
      mparser.py
  3. 45
      test cases/common/91 plusassign/meson.build
  4. 3
      test cases/failing/18 wrong plusassign/meson.build

@ -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.',

@ -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

@ -0,0 +1,3 @@
project('false plusassign', 'c')
3 += 4
Loading…
Cancel
Save