aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--interpreter.py19
-rw-r--r--mparser.py25
-rw-r--r--test cases/common/67 foreach/installed_files.txt3
-rw-r--r--test cases/common/67 foreach/meson.build16
-rw-r--r--test cases/common/67 foreach/prog1.c6
-rw-r--r--test cases/common/67 foreach/prog2.c6
-rw-r--r--test cases/common/67 foreach/prog3.c6
-rw-r--r--test cases/failing/10 out of bounds/meson.build4
8 files changed, 84 insertions, 1 deletions
diff --git a/interpreter.py b/interpreter.py
index 51043e1..fd1507a 100644
--- a/interpreter.py
+++ b/interpreter.py
@@ -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
diff --git a/mparser.py b/mparser.py
index d0058ac..e85a154 100644
--- a/mparser.py
+++ b/mparser.py
@@ -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):
diff --git a/test cases/common/67 foreach/installed_files.txt b/test cases/common/67 foreach/installed_files.txt
new file mode 100644
index 0000000..8056948
--- /dev/null
+++ b/test cases/common/67 foreach/installed_files.txt
@@ -0,0 +1,3 @@
+bin/prog1
+bin/prog2
+bin/prog3
diff --git a/test cases/common/67 foreach/meson.build b/test cases/common/67 foreach/meson.build
new file mode 100644
index 0000000..0e81d3d
--- /dev/null
+++ b/test cases/common/67 foreach/meson.build
@@ -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
diff --git a/test cases/common/67 foreach/prog1.c b/test cases/common/67 foreach/prog1.c
new file mode 100644
index 0000000..a5ef0f1
--- /dev/null
+++ b/test cases/common/67 foreach/prog1.c
@@ -0,0 +1,6 @@
+#include<stdio.h>
+
+int main(int argc, char **argv) {
+ printf("This is test #1.\n");
+ return 0;
+}
diff --git a/test cases/common/67 foreach/prog2.c b/test cases/common/67 foreach/prog2.c
new file mode 100644
index 0000000..b9fddbe
--- /dev/null
+++ b/test cases/common/67 foreach/prog2.c
@@ -0,0 +1,6 @@
+#include<stdio.h>
+
+int main(int argc, char **argv) {
+ printf("This is test #2.\n");
+ return 0;
+}
diff --git a/test cases/common/67 foreach/prog3.c b/test cases/common/67 foreach/prog3.c
new file mode 100644
index 0000000..5657396
--- /dev/null
+++ b/test cases/common/67 foreach/prog3.c
@@ -0,0 +1,6 @@
+#include<stdio.h>
+
+int main(int argc, char **argv) {
+ printf("This is test #3.\n");
+ return 0;
+}
diff --git a/test cases/failing/10 out of bounds/meson.build b/test cases/failing/10 out of bounds/meson.build
new file mode 100644
index 0000000..5c7f267
--- /dev/null
+++ b/test cases/failing/10 out of bounds/meson.build
@@ -0,0 +1,4 @@
+project('out of bounds', 'c')
+
+x = []
+y = x.get(0)