def parseAndCmpStatementPairs(self, pair, statementType): code, expected = pair p = Parser(code) prog = p.parseProgram() self.assertEqual(len(prog.statements), 1) statement = prog.statements[0] self.assertEqual(statement.statementType, statementType) self.assertEqual(str(statement), expected)
def test_for(self): code = """for (i in list+list) { i + 1 }""" p = Parser(code) prog = p.parseProgram() self.assertEqual(len(prog.statements), 1) statement = prog.statements[0] self.assertEqual(statement.statementType, STATEMENT_TYPE_FOR) self.assertEqual(str(statement), "for (i in (list + list)) {(i + 1)}")
def test_parseWithErrors(self): code = """let = 5;""" l = Lexer(code) tokens = l.lex() self.assertEqual(tokens[1].tokenType, TOKEN_TYPES.TOKEN_TYPE_ASSIGN) p = Parser(code) prog = p.parseProgram() self.assertTrue(len(p.errors)> 0)
def test_while(self): code = """while (true) { y; }""" p = Parser(code) prog = p.parseProgram() self.assertEqual(len(prog.statements), 1) statement = prog.statements[0] self.assertEqual(statement.statementType, STATEMENT_TYPE_WHILE) self.assertEqual(str(statement), "while (True) {y}")
def parseAndCmpExprPairs(self, exprPairs): for pair in exprPairs: code, expected = pair p = Parser(code) prog = p.parseProgram() self.assertEqual(len(prog.statements), 1) statement = prog.statements[0] self.assertEqual(statement.statementType, STATEMENT_TYPE_EXPRESSION) self.assertEqual(str(statement.expression), expected)
def test_ifElse(self): code = """if (x == 2) { y; z; } else { let g = zz; z }""" p = Parser(code) prog = p.parseProgram() self.assertEqual(len(prog.statements), 1) statement = prog.statements[0] self.assertEqual(statement.statementType, STATEMENT_TYPE_EXPRESSION) self.assertEqual(statement.expression.expressionType, EXPRESSION_TYPE_IF) self.assertEqual(str(statement.expression), "if ((x == 2)) {y z} else {let g = zz; z}")
def test_returns(self): code = """return 1; return 5; return 999321; """ p = Parser(code) prog = p.parseProgram() self.assertEqual(len(prog.statements), 3) statementTypes = list(map(lambda s: s.statementType, prog.statements)) returnValues = list(map(lambda s: s.value, prog.statements)) self.assertEqual(statementTypes, [STATEMENT_TYPE_RETURN, STATEMENT_TYPE_RETURN, STATEMENT_TYPE_RETURN]) self.assertEqual(returnValues[0].expressionType, EXPRESSION_TYPE_INT_LIT) self.assertEqual(returnValues[1].expressionType, EXPRESSION_TYPE_INT_LIT) self.assertEqual(returnValues[2].expressionType, EXPRESSION_TYPE_INT_LIT)
def test_lets(self): code = """let five = 5; let ten = 10; let foobar = y;""" p = Parser(code) prog = p.parseProgram() self.assertEqual(len(prog.statements), 3) idents = list(map(lambda s: s.identifier.value, prog.statements)) valueTypes = list(map(lambda s: s.value.expressionType, prog.statements)) valueLiterals = list(map(lambda s: s.value.value, prog.statements)) self.assertEqual(idents, ['five', 'ten', 'foobar']) self.assertEqual(valueTypes, [EXPRESSION_TYPE_INT_LIT, EXPRESSION_TYPE_INT_LIT, EXPRESSION_TYPE_IDENT]) self.assertEqual(valueLiterals, [5, 10, "y"])
def test_funcWithNoParam(self): code = """fn () { 1; }""" p = Parser(code) prog = p.parseProgram() self.assertEqual(len(p.errors), 0) self.assertEqual(len(prog.statements), 1) statement = prog.statements[0] self.assertEqual(statement.statementType, STATEMENT_TYPE_EXPRESSION) self.assertEqual(statement.expression.expressionType, EXPRESSION_TYPE_FUNC_LIT) self.assertEqual(str(statement.expression), "fn () {1}")
def test_identsAndLiterals(self): code = """foobar; 5;""" p = Parser(code) prog = p.parseProgram() self.assertEqual(len(prog.statements), 2) statement1 = prog.statements[0] self.assertEqual(statement1.statementType, STATEMENT_TYPE_EXPRESSION) self.assertEqual(statement1.expression.expressionType, EXPRESSION_TYPE_IDENT) self.assertEqual(statement1.expression.value, "foobar") statement2 = prog.statements[1] self.assertEqual(statement2.statementType, STATEMENT_TYPE_EXPRESSION) self.assertEqual(statement2.expression.expressionType, EXPRESSION_TYPE_INT_LIT) self.assertEqual(statement2.expression.value, 5)
def test_prefixExpressions(self): code = """-5; !15;""" p = Parser(code) prog = p.parseProgram() self.assertEqual(len(prog.statements), 2) statement1 = prog.statements[0] self.assertEqual(statement1.statementType, STATEMENT_TYPE_EXPRESSION) self.assertEqual(statement1.expression.expressionType, EXPRESSION_TYPE_PREFIX) self.assertEqual(statement1.expression.operator, '-') self.assertEqual(statement1.expression.right.value, 5) statement2 = prog.statements[1] self.assertEqual(statement2.statementType, STATEMENT_TYPE_EXPRESSION) self.assertEqual(statement2.expression.expressionType, EXPRESSION_TYPE_PREFIX) self.assertEqual(statement2.expression.operator, '!') self.assertEqual(statement2.expression.right.value, 15)
def test_infixExpressions(self): code = """5 + 6; 7 * 5;""" p = Parser(code) prog = p.parseProgram() self.assertEqual(len(prog.statements), 2) statement1 = prog.statements[0] self.assertEqual(statement1.statementType, STATEMENT_TYPE_EXPRESSION) self.assertEqual(statement1.expression.expressionType, EXPRESSION_TYPE_INFIX) self.assertEqual(statement1.expression.operator, '+') self.assertEqual(statement1.expression.left.value, 5) self.assertEqual(statement1.expression.right.value, 6) statement2 = prog.statements[1] self.assertEqual(statement2.statementType, STATEMENT_TYPE_EXPRESSION) self.assertEqual(statement2.expression.expressionType, EXPRESSION_TYPE_INFIX) self.assertEqual(statement2.expression.operator, '*') self.assertEqual(statement2.expression.left.value, 7) self.assertEqual(statement2.expression.right.value, 5)
class CompileHelper(object): def __init__(self, testCase, code): self.code = code self.testCase = testCase self.parser = Parser(code) program = self.parser.parseProgram() self.compiler = Compiler() self.compiler.compile(program) self.bytecode = self.compiler.bytecode() def checkInstructionsExpected(self, instructions): self.testCase.assertEqual(self.bytecode.instructions, instructions) def checkConstantsExpected(self, constants): cVals = [c.value for c in self.bytecode.constants] self.testCase.assertEqual(len(cVals), len(constants)) for c, expectedC in zip(cVals, constants): self.testCase.assertEqual(c, expectedC)
class VMHelper(object): def __init__(self, testCase, code): self.code = code self.testCase = testCase self.parser = Parser(code) program = self.parser.parseProgram() self.compiler = Compiler() self.compiler.compile(program) self.bytecode = self.compiler.bytecode() self.vm = VM(self.bytecode, self.compiler.symbolTable) self.vm.run() self.checkSanity() def checkSanity(self): #this WILL blow up if an errant opcode left something on the stack for example... self.testCase.assertEqual(self.vm.sp, 0) self.testCase.assertEqual(self.vm.frameIndex, 1) def checkStackExpected(self, expectedPairs): inspectedStack = self.vm.inspectStack() self.testCase.assertEqual(len(expectedPairs), len(inspectedStack)) for stackEl, expectedPair in zip(inspectedStack, expectedPairs): expectedType, expectedVal = expectedPair self.testCase.assertEqual(stackEl.objectType, expectedType) self.testCase.assertEqual(stackEl.inspect(), expectedVal) def checkLastPoppedExpected(self, expectedType, expectedValue): obj = self.vm.lastPoppedStackEl() self.testCase.assertEqual(obj.objectType, expectedType) self.testCase.assertEqual(obj.inspect(), expectedValue) def checkGlobalExpected(self, identifier, typ, value): self.testCase.assertEqual( self.vm.getGlobal(identifier).objectType, typ) self.testCase.assertEqual( self.vm.getGlobal(identifier).inspect(), value)