TEST_F(ParserTests_Atomics, AtomicStatementWithAbort) { ASTNode* node = this->parseSingleFunction("def test()\n" " atomic\n" " abort\n" " end\n" "end\n"); node = node->childAtIndex(0); ASSERT_EQ("Atomic Statement", node->nodeName()); ASSERT_EQ("Abort", node->childAtIndex(0)->nodeName()); }
TEST_F(ParserTests_Atomics, AtomicExpressionAssign) { ASTNode* node = this->parseSingleFunction("def test(Int a)\n" " atomic:ordered(a = a)\n" "end\n"); ASSERT_EQ(1, node->childCount()); node = node->childAtIndex(0); ASSERT_EQ("Atomic Expression", node->nodeName()); ASSERT_EQ(AtomicNode::Ordering::SequentiallyConsistent, dynamic_cast<Three::AtomicExpressionNode*>(node)->ordering()); node = node->childAtIndex(0); ASSERT_EQ("Assign Operator", node->nodeName()); }
TEST_F(ParserTests_Types, GlobalCharWithUTF32BE) { ASTNode* node = this->parseNode("Char:utf32be value\n"); node = node->childAtIndex(0); ASSERT_EQ(DataType::Character, node->dataType().kind()); ASSERT_EQ(DataType::CharacterEncoding::UTF32BE, node->dataType().characterEncoding()); }
TEST_F(ParserTests_Types, GlobalCharWithAscii) { ASTNode* node = this->parseNode("Char:ascii value\n"); node = node->childAtIndex(0); ASSERT_EQ(DataType::Character, node->dataType().kind()); ASSERT_EQ(DataType::CharacterEncoding::ASCII, node->dataType().characterEncoding()); }
TEST_F(ParserTests_Types, VarargVariable) { ASTNode* node = this->parseNode("Vararg value\n"); node = node->childAtIndex(0); ASSERT_EQ(DataType::Vararg, node->dataType().kind()); ASSERT_EQ(0, node->dataType().subtypeCount()); }
TEST_F(ParserTests_Types, GlobalPointerToClosure) { ASTNode* node = this->parseNode("*{Int} -> Void value\n"); node = node->childAtIndex(0); ASSERT_EQ(DataType::Pointer, node->dataType().kind()); ASSERT_EQ(1, node->dataType().subtypeCount()); ASSERT_EQ(DataType::Closure, node->dataType().subtypeAtIndex(0).kind()); }
TEST_F(ParserTests_Types, GlobalPointerToInt) { ASTNode* node = this->parseNode("*Int value\n"); node = node->childAtIndex(0); ASSERT_EQ(DataType::Pointer, node->dataType().kind()); ASSERT_EQ(1, node->dataType().subtypeCount()); ASSERT_EQ(DataType::Integer, node->dataType().subtypeAtIndex(0).kind()); }
TEST_F(ParserTests_Types, GlobalUntyped) { ASTNode* node = this->parseNode("value\n"); node = node->childAtIndex(0); ASSERT_EQ("Variable Declaration", node->nodeName()); ASSERT_EQ("value", node->name()); ASSERT_EQ(DataType::Undefined, node->dataType().kind()); }
TEST_F(ParserTests_Types, TupleOfSingleInt) { ASTNode* node = this->parseNode("(Int) value\n"); node = node->childAtIndex(0); ASSERT_EQ(DataType::Tuple, node->dataType().kind()); ASSERT_EQ(1, node->dataType().subtypeCount()); ASSERT_EQ(DataType::Integer, node->dataType().subtypeAtIndex(0).kind()); }
TEST_F(ParserTests_Types, GlobalReal) { ASTNode* node = this->parseNode("Real value\n"); node = node->childAtIndex(0); ASSERT_EQ(DataType::Real, node->dataType().kind()); ASSERT_EQ(0, node->dataType().widthSpecifier()); ASSERT_EQ(0, node->dataType().alignmentSpecifier()); ASSERT_EQ(0, node->dataType().vectorSizeSpecifier()); }
TEST_F(ParserTests_Atomics, AtomicBarrierWithoutSpecifier) { ASTNode* node = this->parseSingleFunction("def test()\n" " barrier\n" "end\n"); node = node->childAtIndex(0); ASSERT_EQ("Barrier", node->nodeName()); ASSERT_EQ(AtomicNode::Ordering::SequentiallyConsistent, dynamic_cast<Three::BarrierNode*>(node)->ordering()); }
TEST_F(ParserTests_Types, GlobalIntWithAlignmentAndVectorSizeSpecifier) { ASTNode* node = this->parseNode("Int::4:4 value\n"); node = node->childAtIndex(0); ASSERT_EQ(DataType::Integer, node->dataType().kind()); ASSERT_EQ(0, node->dataType().widthSpecifier()); ASSERT_EQ(4, node->dataType().alignmentSpecifier()); ASSERT_EQ(4, node->dataType().vectorSizeSpecifier()); }
TEST_F(ParserTests_Types, GlobalPointerToFunctionWithPointerArg) { ASTNode* node = this->parseNode("*(*Void) -> Void value\n"); ASSERT_EQ(1, node->childCount()); node = node->childAtIndex(0); ASSERT_EQ(DataType::Pointer, node->dataType().kind()); ASSERT_EQ(1, node->dataType().subtypeCount()); ASSERT_EQ(DataType::Function, node->dataType().subtypeAtIndex(0).kind()); }
TEST_F(ParserTests_Types, GlobalMutableBoolean) { ASTNode* node = this->parseNode("Bool! value\n"); node = node->childAtIndex(0); ASSERT_EQ("Variable Declaration", node->nodeName()); ASSERT_EQ("value", node->name()); EXPECT_EQ(DataType::Boolean, node->dataType().kind()); EXPECT_EQ(DataType::Access::ReadWrite, node->dataType().access()); }
TEST_F(ParserTests_Types, GlobalFunction) { ASTNode* node = this->parseNode("() -> Void value\n"); node = node->childAtIndex(0); ASSERT_EQ("value", node->name()); ASSERT_EQ(DataType::Function, node->dataType().kind()); ASSERT_EQ(0, node->dataType().subtypeCount()); ASSERT_EQ(0, node->dataType().parameterCount()); ASSERT_EQ(DataType::Void, node->dataType().returnType().kind()); }
TEST_F(ParserTests_Types, GlobalArrayOfInt) { ASTNode* node = this->parseNode("[3]Int value\n"); node = node->childAtIndex(0); ASSERT_EQ(DataType::Array, node->dataType().kind()); ASSERT_EQ(3, node->dataType().arrayCount()); ASSERT_EQ(1, node->dataType().subtypeCount()); ASSERT_EQ(DataType::Integer, node->dataType().subtypeAtIndex(0).kind()); ASSERT_EQ(0, node->dataType().subtypeAtIndex(0).subtypeCount()); }
TEST_F(ParserTests_Types, GlobalClosureWithReturn) { ASTNode* node = this->parseNode("{} -> Int value\n"); node = node->childAtIndex(0); ASSERT_EQ(DataType::Closure, node->dataType().kind()); ASSERT_EQ(0, node->dataType().subtypeCount()); ASSERT_EQ(1, node->dataType().parameterCount()); ASSERT_EQ(1, node->dataType().returnCount()); ASSERT_EQ(DataType::Integer, node->dataType().returnType().kind()); }
TEST_F(ParserTests_Types, GlobalClosureTakingAPointerParam) { ASTNode* node = this->parseNode("{*Int} -> Void value\n"); node = node->childAtIndex(0); ASSERT_EQ(DataType::Closure, node->dataType().kind()); ASSERT_EQ(0, node->dataType().subtypeCount()); ASSERT_EQ(2, node->dataType().parameterCount()); ASSERT_EQ(DataType::Pointer, node->dataType().parameterAtIndex(1).kind()); ASSERT_EQ(DataType::Void, node->dataType().returnType().kind()); }
TEST_F(ParserTests_Types, GlobalFunctionTakingAPointerParam) { ASTNode* node = this->parseNode("(*Int) -> Void value\n"); node = node->childAtIndex(0); ASSERT_EQ(DataType::Function, node->dataType().kind()); ASSERT_EQ(0, node->dataType().subtypeCount()); ASSERT_EQ(1, node->dataType().parameterCount()); ASSERT_EQ(DataType::Pointer, node->dataType().parameterAtIndex(0).kind()); ASSERT_EQ(DataType::Void, node->dataType().returnType().kind()); }
TEST_F(ParserTests_Atomics, AtomicStatement) { ASTNode* node = this->parseSingleFunction("def test()\n" " atomic\n" " end\n" "end\n"); node = node->childAtIndex(0); ASSERT_EQ("Atomic Statement", node->nodeName()); ASSERT_TRUE(dynamic_cast<AtomicStatementNode*>(node)->elseClause() == nullptr); }
TEST_F(ParserTests_Types, GlobalClosureTakingTwoParams) { ASTNode* node = this->parseNode("{Int, Float} -> Void value\n"); node = node->childAtIndex(0); ASSERT_EQ(DataType::Closure, node->dataType().kind()); ASSERT_EQ(0, node->dataType().subtypeCount()); ASSERT_EQ(3, node->dataType().parameterCount()); ASSERT_EQ(DataType::Integer, node->dataType().parameterAtIndex(1).kind()); ASSERT_EQ(DataType::Float, node->dataType().parameterAtIndex(2).kind()); ASSERT_EQ(DataType::Void, node->dataType().returnType().kind()); }
TEST_F(ParserTests_Types, GlobalOptionalMutableBooleanPointer) { ASTNode* node = this->parseNode("Bool!? value\n"); node = node->childAtIndex(0); ASSERT_EQ("Variable Declaration", node->nodeName()); ASSERT_EQ("value", node->name()); EXPECT_EQ(DataType::NullablePointer, node->dataType().kind()); EXPECT_EQ(DataType::Access::Read, node->dataType().access()); ASSERT_EQ(1, node->dataType().subtypeCount()); EXPECT_EQ(DataType::Boolean, node->dataType().subtypeAtIndex(0).kind()); EXPECT_EQ(DataType::Access::ReadWrite, node->dataType().subtypeAtIndex(0).access()); }
TEST_F(ParserTests_Atomics, AtomicStatementWithFallbackFunctions) { ASTNode* node = this->parseNodeWithBodies("def fn_1(*Void ptr) -> Bool\n" " return true\n" "end\n" "def fn_2(*Void ptr) -> Bool\n" " return true\n" "end\n" "def test(*Void ptr)\n" " atomic:fallback(fn_1, fn_2, ptr)\n" " abort\n" " end\n" "end\n"); ASSERT_EQ(3, node->childCount()); node = node->childAtIndex(2); ASSERT_EQ("Function Definition", node->nodeName()); ASSERT_EQ(1, node->childCount()); node = node->childAtIndex(0); ASSERT_EQ("Atomic Statement", node->nodeName()); auto atomicNode = dynamic_cast<AtomicStatementNode*>(node); node = atomicNode->lockFunction(); ASSERT_TRUE(node != nullptr); ASSERT_EQ("Function Variable", node->nodeName()); ASSERT_EQ("fn_1", node->name()); node = atomicNode->unlockFunction(); ASSERT_TRUE(node != nullptr); ASSERT_EQ("Function Variable", node->nodeName()); ASSERT_EQ("fn_2", node->name()); node = atomicNode->lockContext(); ASSERT_TRUE(node != nullptr); ASSERT_EQ("Local Variable", node->nodeName()); ASSERT_EQ("ptr", node->name()); }
TEST_F(ParserTests_Types, GlobalClosure) { ASTNode* node = this->parseNode("{} -> Void value\n"); node = node->childAtIndex(0); ASSERT_EQ("value", node->name()); ASSERT_EQ(DataType::Closure, node->dataType().kind()); ASSERT_EQ(0, node->dataType().subtypeCount()); ASSERT_EQ(1, node->dataType().parameterCount()); ASSERT_EQ(DataType::Kind::Pointer, node->dataType().parameterAtIndex(0).kind()); ASSERT_EQ(1, node->dataType().parameterAtIndex(0).subtypeCount()); ASSERT_EQ(DataType::Kind::Void, node->dataType().parameterAtIndex(0).subtypeAtIndex(0).kind()); ASSERT_EQ(DataType::Void, node->dataType().returnType().kind()); }
TEST_F(ParserTests_Types, GlobalFunctionWithTwoReturns) { ASTNode* node = this->parseNode("() -> (Int, Int) value\n"); node = node->childAtIndex(0); ASSERT_EQ(DataType::Function, node->dataType().kind()); ASSERT_EQ(0, node->dataType().subtypeCount()); ASSERT_EQ(0, node->dataType().parameterCount()); ASSERT_EQ(DataType::Tuple, node->dataType().returnType().kind()); ASSERT_EQ(2, node->dataType().returnType().subtypeCount()); ASSERT_EQ(DataType::Integer, node->dataType().returnType().subtypeAtIndex(0).kind()); ASSERT_EQ(DataType::Integer, node->dataType().returnType().subtypeAtIndex(1).kind()); }