diff --git a/interpreter.py b/interpreter.py index 50c7a404c..f0d26062a 100755 --- a/interpreter.py +++ b/interpreter.py @@ -275,8 +275,15 @@ class Interpreter(): return cur elif isinstance(cur, nodes.BoolStatement): return cur + elif isinstance(cur, nodes.IfStatement): + return self.evaluate_if(cur) + elif isinstance(cur, nodes.AtomStatement): + varname = cur.get_value() + if varname in self.variables: + return self.variables[varname] + raise InvalidCode('Line %d: unknown variable "%s".' % (cur.lineno(), varname)) else: - raise InvalidCode("Unknown statement in line %d." % cur.lineno()) + raise InvalidCode("Line %d: Unknown statement." % cur.lineno()) def validate_arguments(self, args, argcount, arg_types): if argcount is not None: @@ -455,6 +462,15 @@ class Interpreter(): if not isinstance(obj, InterpreterObject): raise InvalidArguments('Line %d: variable "%s" is not callable.' % (node.lineno(), object_name)) return obj.method_call(method_name, self.reduce_arguments(args)) + + def evaluate_if(self, node): + result = self.evaluate_statement(node.get_clause()) + if isinstance(result, nodes.BoolExpression) or \ + isinstance(result, nodes.BoolStatement): + if result.get_value(): + self.evaluate_codeblock(node.get_codeblock()) + else: + raise InvalidCode('Line %d: If clause does not evaluate to true or false.' % node.lineno()) if __name__ == '__main__': code = """project('myawesomeproject') diff --git a/nodes.py b/nodes.py index 4bbaa5dc6..385e1c9c5 100644 --- a/nodes.py +++ b/nodes.py @@ -66,6 +66,18 @@ class BoolStatement(Statement): def get_value(self): return self.value + +class IfStatement(Statement): + def __init__(self, clause, codeblock, lineno): + Statement.__init__(self, lineno) + self.clause = clause + self.codeblock = codeblock + + def get_clause(self): + return self.clause + + def get_codeblock(self): + return self.codeblock class StringStatement(Statement): def __init__(self, value, lineno): diff --git a/parser.py b/parser.py index a6af0032b..ac6c8e588 100755 --- a/parser.py +++ b/parser.py @@ -19,7 +19,9 @@ import ply.yacc as yacc import nodes reserved = {'true' : 'TRUE', - 'false' : 'FALSE'} + 'false' : 'FALSE', + 'if' : 'IF', + 'endif' : 'ENDIF'} tokens = ['LPAREN', 'RPAREN', @@ -119,6 +121,10 @@ def p_statement_method_call(t): 'statement : expression DOT expression LPAREN args RPAREN' t[0] = nodes.MethodCall(t[1], t[3], t[5], t.lineno(1)) +def p_statement_if(t): + 'statement : IF LPAREN statement RPAREN EOL codeblock ENDIF' + t[0] = nodes.IfStatement(t[3], t[6], t.lineno(1)) + def p_statement_expression(t): 'statement : expression' t[0] = nodes.statement_from_expression(t[1]) diff --git a/test cases/17 if/builder.txt b/test cases/17 if/builder.txt index ca994d0df..96615b9f0 100644 --- a/test cases/17 if/builder.txt +++ b/test cases/17 if/builder.txt @@ -1,3 +1,14 @@ project('if test', 'c') -var = true +var1 = true +var2 = false + +if(var1) + exe = executable('prog', 'prog.c') +endif + +if(var2) + exe = executable('breakbreakbreak', 'crashing.c') +endif + +add_test('iftest', exe) diff --git a/test cases/17 if/prog.c b/test cases/17 if/prog.c new file mode 100644 index 000000000..0314ff17b --- /dev/null +++ b/test cases/17 if/prog.c @@ -0,0 +1 @@ +int main(int argc, char **argv) { return 0; }