Interpreter: Add 'continue' and 'break' keywords

Closes: #3601
pull/3900/head
Xavier Claessens 7 years ago
parent fa2e096aa0
commit a816e1c1fa
  1. 24
      mesonbuild/interpreterbase.py
  2. 14
      mesonbuild/mparser.py
  3. 13
      test cases/common/64 foreach/meson.build

@ -300,6 +300,12 @@ class InvalidArguments(InterpreterException):
class SubdirDoneRequest(BaseException):
pass
class ContinueRequest(BaseException):
pass
class BreakRequest(BaseException):
pass
class InterpreterObject:
def __init__(self):
self.methods = {}
@ -453,6 +459,10 @@ class InterpreterBase:
return self.evaluate_indexing(cur)
elif isinstance(cur, mparser.TernaryNode):
return self.evaluate_ternary(cur)
elif isinstance(cur, mparser.ContinueNode):
raise ContinueRequest()
elif isinstance(cur, mparser.BreakNode):
raise BreakRequest()
elif self.is_elementary_type(cur):
return cur
else:
@ -641,7 +651,12 @@ The result of this is undefined and will become a hard error in a future Meson r
return items
for item in items:
self.set_variable(varname, item)
self.evaluate_codeblock(node.block)
try:
self.evaluate_codeblock(node.block)
except ContinueRequest:
continue
except BreakRequest:
break
elif isinstance(items, dict):
if len(node.varnames) != 2:
raise InvalidArguments('Foreach on dict unpacks key and value')
@ -650,7 +665,12 @@ The result of this is undefined and will become a hard error in a future Meson r
for key, value in items.items():
self.set_variable(node.varnames[0].value, key)
self.set_variable(node.varnames[1].value, value)
self.evaluate_codeblock(node.block)
try:
self.evaluate_codeblock(node.block)
except ContinueRequest:
continue
except BreakRequest:
break
else:
raise InvalidArguments('Items of foreach loop must be an array or a dict')

@ -91,8 +91,8 @@ class Lexer:
self.code = code
self.keywords = {'true', 'false', 'if', 'else', 'elif',
'endif', 'and', 'or', 'not', 'foreach', 'endforeach',
'in'}
self.future_keywords = {'continue', 'break', 'return'}
'in', 'continue', 'break'}
self.future_keywords = {'return'}
self.token_specification = [
# Need to be sorted longest to shortest.
('ignore', re.compile(r'[ \t]')),
@ -243,6 +243,12 @@ class StringNode(ElementaryNode):
def __str__(self):
return "String node: '%s' (%d, %d)." % (self.value, self.lineno, self.colno)
class ContinueNode(ElementaryNode):
pass
class BreakNode(ElementaryNode):
pass
class ArrayNode:
def __init__(self, args):
self.subdir = args.subdir
@ -759,6 +765,10 @@ class Parser:
block = self.foreachblock()
self.block_expect('endforeach', block_start)
return block
if self.accept('continue'):
return ContinueNode(self.current)
if self.accept('break'):
return BreakNode(self.current)
return self.statement()
def codeblock(self):

@ -18,3 +18,16 @@ foreach i : tests
# we definitely don't want that.
tests = ['test4', 'prog4', 'prog4.c']
endforeach
items = ['a', 'continue', 'b', 'break', 'c']
result = []
foreach i : items
if i == 'continue'
continue
elif i == 'break'
break
endif
result += i
endforeach
assert(result == ['a', 'b'], 'Continue or break in foreach failed')

Loading…
Cancel
Save