Implement a foreach loop construct. Closes #17.

pull/18/head
Jussi Pakkanen 10 years ago
parent 0c86f30d4b
commit b44ca46e92
  1. 19
      interpreter.py
  2. 25
      mparser.py
  3. 3
      test cases/common/67 foreach/installed_files.txt
  4. 16
      test cases/common/67 foreach/meson.build
  5. 6
      test cases/common/67 foreach/prog1.c
  6. 6
      test cases/common/67 foreach/prog2.c
  7. 6
      test cases/common/67 foreach/prog3.c
  8. 4
      test cases/failing/10 out of bounds/meson.build

@ -807,6 +807,8 @@ class Interpreter():
return self.evaluate_orstatement(cur)
elif isinstance(cur, mparser.NotNode):
return self.evaluate_notstatement(cur)
elif isinstance(cur, mparser.ForeachClauseNode):
return self.evaluate_foreach(cur)
else:
raise InvalidCode("Unknown statement.")
@ -1486,6 +1488,13 @@ class Interpreter():
def array_method_call(self, obj, method_name, args):
if method_name == 'contains':
return self.check_contains(obj, args)
elif method_name == 'get':
index = args[0]
if not isinstance(index, int):
raise InvalidArguments('Array index must be a number.')
if index < 0 or index >= len(obj):
raise InvalidArguments('Array index %s is out of bounds for array of size %d.' % (index, len(obj)))
return obj[index]
raise InterpreterException('Arrays do not have a method called "%s".' % method_name)
def check_contains(self, obj, args):
@ -1517,6 +1526,16 @@ class Interpreter():
if not isinstance(node.elseblock, mparser.EmptyNode):
self.evaluate_codeblock(node.elseblock)
def evaluate_foreach(self, node):
assert(isinstance(node, mparser.ForeachClauseNode))
varname = node.varname.value
items = self.evaluate_statement(node.items)
if not isinstance(items, list):
raise InvalidArguments('Items of foreach loop is not an array')
for item in items:
self.set_variable(varname, item)
self.evaluate_codeblock(node.block)
def is_elementary_type(self, v):
if isinstance(v, int) or isinstance(v, str) or isinstance(v, bool):
return True

@ -17,6 +17,8 @@
import re
import sys
from coredata import MesonException
from array import array
from orca.messages import itemsFound
class ParseException(MesonException):
def __init__(self, text, lineno, colno):
@ -39,7 +41,7 @@ class Token:
class Lexer:
def __init__(self):
self.keywords = {'true', 'false', 'if', 'else', 'elif',
'endif', 'and', 'or', 'not'}
'endif', 'and', 'or', 'not', 'foreach', 'endforeach'}
self.token_specification = [
# Need to be sorted longest to shortest.
('ignore', re.compile(r'[ \t]')),
@ -214,6 +216,14 @@ class AssignmentNode:
assert(isinstance(var_name, str))
self.value = value
class ForeachClauseNode():
def __init__(self, lineno, colno, varname, items, block):
self.lineno = lineno
self.colno = colno
self.varname = varname
self.items = items
self.block = block
class IfClauseNode():
def __init__(self, lineno, colno):
self.lineno = lineno
@ -417,6 +427,15 @@ class Parser:
return self.method_call(method)
return method
def foreachblock(self):
t = self.current
self.expect('id')
varname = t
self.expect('colon')
items = self.statement()
block = self.codeblock()
return ForeachClauseNode(varname.lineno, varname.colno, varname, items, block)
def ifblock(self):
condition = self.statement()
clause = IfClauseNode(condition.lineno, condition.colno)
@ -445,6 +464,10 @@ class Parser:
block = self.ifblock()
self.expect('endif')
return block
if self.accept('foreach'):
block = self.foreachblock()
self.expect('endforeach')
return block
return self.statement()
def codeblock(self):

@ -0,0 +1,3 @@
bin/prog1
bin/prog2
bin/prog3

@ -0,0 +1,16 @@
project('foreach', 'c')
tests = [['test1', 'prog1', 'prog1.c'],
['test2', 'prog2', 'prog2.c'],
['test3', 'prog3', 'prog3.c']]
foreach i : tests
test(i.get(0), executable(i.get(1), i.get(2), install : true))
# Ensure that changing the tests variable does not
# affect ongoing iteration in the foreach loop.
#
# Being able to do that would make Meson Turing complete and
# we definitely don't want that.
tests = ['test4', 'prog4', 'prog4.c']
endforeach

@ -0,0 +1,6 @@
#include<stdio.h>
int main(int argc, char **argv) {
printf("This is test #1.\n");
return 0;
}

@ -0,0 +1,6 @@
#include<stdio.h>
int main(int argc, char **argv) {
printf("This is test #2.\n");
return 0;
}

@ -0,0 +1,6 @@
#include<stdio.h>
int main(int argc, char **argv) {
printf("This is test #3.\n");
return 0;
}

@ -0,0 +1,4 @@
project('out of bounds', 'c')
x = []
y = x.get(0)
Loading…
Cancel
Save