diff options
author | Robin McCorkell <rmccorkell@karoshi.org.uk> | 2014-11-08 01:41:05 +0000 |
---|---|---|
committer | Robin McCorkell <rmccorkell@karoshi.org.uk> | 2014-11-16 16:45:10 +0000 |
commit | 702148aea515b5c7b2d6004615a7f4a635a7ca1e (patch) | |
tree | 7594171a735bea6ac32cdd5da337dfbeee789e92 /interpreter.py | |
parent | 9ce01c16f409208ca17235efee602a71da9712de (diff) | |
download | meson-702148aea515b5c7b2d6004615a7f4a635a7ca1e.zip meson-702148aea515b5c7b2d6004615a7f4a635a7ca1e.tar.gz meson-702148aea515b5c7b2d6004615a7f4a635a7ca1e.tar.bz2 |
Add number, string and array arithmetic
Addition (+), subtraction (-), multiplication (*) and division (/) for numbers
follows the BIDMAS rules.
Strings and arrays can be concatenated with the addition operator
Strings can be concatenated with numbers with the addition operator
Diffstat (limited to 'interpreter.py')
-rw-r--r-- | interpreter.py | 56 |
1 files changed, 28 insertions, 28 deletions
diff --git a/interpreter.py b/interpreter.py index e2a7b16..2b75fa8 100644 --- a/interpreter.py +++ b/interpreter.py @@ -1,4 +1,5 @@ # Copyright 2012-2014 Jussi Pakkanen +# Copyright 2014 Robin McCorkell # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -800,15 +801,19 @@ class Interpreter(): elif isinstance(cur, mparser.ArrayNode): return self.evaluate_arraystatement(cur) elif isinstance(cur, mparser.NumberNode): - return cur + return cur.value elif isinstance(cur, mparser.AndNode): return self.evaluate_andstatement(cur) elif isinstance(cur, mparser.OrNode): return self.evaluate_orstatement(cur) elif isinstance(cur, mparser.NotNode): return self.evaluate_notstatement(cur) + elif isinstance(cur, mparser.ArithmeticNode): + return self.evaluate_arithmeticstatement(cur) elif isinstance(cur, mparser.ForeachClauseNode): return self.evaluate_foreach(cur) + elif self.is_elementary_type(cur): + return cur else: raise InvalidCode("Unknown statement.") @@ -1393,37 +1398,17 @@ class Interpreter(): self.set_variable(var_name, value) return value - def reduce_single(self, arg): - if isinstance(arg, mparser.IdNode): - return self.get_variable(arg.value) - elif isinstance(arg, str): - return arg - elif isinstance(arg, mparser.StringNode): - return arg.value - elif isinstance(arg, mparser.FunctionNode): - return self.function_call(arg) - elif isinstance(arg, mparser.MethodNode): - return self.method_call(arg) - elif isinstance(arg, mparser.BooleanNode): - return arg.value - elif isinstance(arg, mparser.ArrayNode): - return [self.reduce_single(curarg) for curarg in arg.args.arguments] - elif isinstance(arg, mparser.NumberNode): - return arg.value - else: - raise InvalidCode('Irreducible argument.') - def reduce_arguments(self, args): assert(isinstance(args, mparser.ArgumentNode)) if args.incorrect_order(): raise InvalidArguments('All keyword arguments must be after positional arguments.') - reduced_pos = [self.reduce_single(arg) for arg in args.arguments] + reduced_pos = [self.evaluate_statement(arg) for arg in args.arguments] reduced_kw = {} for key in args.kwargs.keys(): if not isinstance(key, str): raise InvalidArguments('Keyword argument name is not a string.') a = args.kwargs[key] - reduced_kw[key] = self.reduce_single(a) + reduced_kw[key] = self.evaluate_statement(a) return (reduced_pos, reduced_kw) def string_method_call(self, obj, method_name, args): @@ -1457,7 +1442,7 @@ class Interpreter(): if isinstance(args, mparser.ArgumentNode): args = args.arguments for (i, arg) in enumerate(args): - arg = self.to_native(self.reduce_single(arg)) + arg = self.to_native(self.evaluate_statement(arg)) if isinstance(arg, bool): # Python boolean is upper case. arg = str(arg).lower() templ = templ.replace('@{}@'.format(i), str(arg)) @@ -1537,7 +1522,7 @@ class Interpreter(): self.evaluate_codeblock(node.block) def is_elementary_type(self, v): - if isinstance(v, int) or isinstance(v, str) or isinstance(v, bool): + if isinstance(v, (int, float, str, bool, list)): return True return False @@ -1552,9 +1537,6 @@ class Interpreter(): val2 = v2 else: val2 = v2.value - if type(val1) != type(val2): - raise InterpreterException('Comparison of different types %s and %s.' % - (str(type(val1)), str(type(val2)))) if node.ctype == '==': return val1 == val2 elif node.ctype == '!=': @@ -1600,6 +1582,24 @@ class Interpreter(): raise InterpreterException('Argument to "not" is not a boolean.') return not v + def evaluate_arithmeticstatement(self, cur): + l = self.to_native(self.evaluate_statement(cur.left)) + r = self.to_native(self.evaluate_statement(cur.right)) + if isinstance(l, str) or isinstance(r, str): + l = str(l) + r = str(r) + + if cur.operation == 'add': + return l + r + elif cur.operation == 'sub': + return l - r + elif cur.operation == 'mul': + return l * r + elif cur.operation == 'div': + return l // r + else: + raise InvalidCode('You broke me.') + def evaluate_arraystatement(self, cur): (arguments, kwargs) = self.reduce_arguments(cur.args) if len(kwargs) > 0: |