diff options
-rw-r--r-- | interpreter.py | 19 | ||||
-rw-r--r-- | mparser.py | 25 | ||||
-rw-r--r-- | test cases/common/67 foreach/installed_files.txt | 3 | ||||
-rw-r--r-- | test cases/common/67 foreach/meson.build | 16 | ||||
-rw-r--r-- | test cases/common/67 foreach/prog1.c | 6 | ||||
-rw-r--r-- | test cases/common/67 foreach/prog2.c | 6 | ||||
-rw-r--r-- | test cases/common/67 foreach/prog3.c | 6 | ||||
-rw-r--r-- | test cases/failing/10 out of bounds/meson.build | 4 |
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 @@ -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) |