86 enum class WhichAnder {
87 ThreadAnder,
88 NonThreadAnder
89 };
90
91 struct AnderCallArgumentResult {
92 UniqueRef<AST::Expression> expression;
93 Optional<UniqueRef<AST::VariableDeclaration>> variableDeclaration;
94 WhichAnder whichAnder;
95 };
96
97 template <typename ExpressionConstructor, typename TypeConstructor>
98 static Optional<AnderCallArgumentResult> wrapAnderCallArgument(UniqueRef<AST::Expression>& expression, bool anderFunction, bool threadAnderFunction)
99 {
100 if (auto addressSpace = expression->typeAnnotation().leftAddressSpace()) {
101 if (!anderFunction)
102 return WTF::nullopt;
103 auto origin = expression->origin();
104 auto baseType = expression->resolvedType().clone();
105 auto makeArrayReference = makeUniqueRef<ExpressionConstructor>(Lexer::Token(origin), WTFMove(expression));
106 makeArrayReference->setType(makeUniqueRef<TypeConstructor>(WTFMove(origin), *addressSpace, WTFMove(baseType)));
107 makeArrayReference->setTypeAnnotation(AST::RightValue());
108 return {{ WTFMove(makeArrayReference), WTF::nullopt, WhichAnder::NonThreadAnder }};
109 }
110 if (threadAnderFunction) {
111 auto origin = expression->origin();
112 auto baseType = expression->resolvedType().clone();
113 auto variableDeclaration = makeUniqueRef<AST::VariableDeclaration>(Lexer::Token(origin), AST::Qualifiers(), baseType->clone(), String(), WTF::nullopt, WTF::nullopt);
114
115 auto variableReference1 = makeUniqueRef<AST::VariableReference>(AST::VariableReference::wrap(variableDeclaration));
116 variableReference1->setType(baseType->clone());
117 variableReference1->setTypeAnnotation(AST::LeftValue { AST::AddressSpace::Thread });
118
119 auto assignmentExpression = makeUniqueRef<AST::AssignmentExpression>(Lexer::Token(origin), WTFMove(variableReference1), WTFMove(expression));
120 assignmentExpression->setType(baseType->clone());
121 assignmentExpression->setTypeAnnotation(AST::RightValue());
122
123 auto variableReference2 = makeUniqueRef<AST::VariableReference>(AST::VariableReference::wrap(variableDeclaration));
124 variableReference2->setType(baseType->clone());
125 variableReference2->setTypeAnnotation(AST::LeftValue { AST::AddressSpace::Thread });
126
127 auto expression = makeUniqueRef<ExpressionConstructor>(Lexer::Token(origin), WTFMove(variableReference2));
128 auto resultType = makeUniqueRef<TypeConstructor>(Lexer::Token(origin), AST::AddressSpace::Thread, WTFMove(baseType));
129 expression->setType(resultType->clone());
130 expression->setTypeAnnotation(AST::RightValue());
131
132 Vector<UniqueRef<AST::Expression>> expressions;
133 expressions.append(WTFMove(assignmentExpression));
134 expressions.append(WTFMove(expression));
135 auto commaExpression = makeUniqueRef<AST::CommaExpression>(WTFMove(origin), WTFMove(expressions));
136 commaExpression->setType(WTFMove(resultType));
137 commaExpression->setTypeAnnotation(AST::RightValue());
138 return {{ WTFMove(commaExpression), { WTFMove(variableDeclaration) }, WhichAnder::ThreadAnder}};
139 }
140 return WTF::nullopt;
141 }
142
143 static Optional<AnderCallArgumentResult> anderCallArgument(UniqueRef<AST::Expression>& expression, bool anderFunction, bool threadAnderFunction)
144 {
145 auto& unifyNode = expression->resolvedType().unifyNode();
146 if (is<AST::UnnamedType>(unifyNode)) {
147 auto& unnamedType = downcast<AST::UnnamedType>(unifyNode);
148 ASSERT(!is<AST::PointerType>(unnamedType));
149 if (is<AST::ArrayReferenceType>(unnamedType))
150 return {{ WTFMove(expression), WTF::nullopt, WhichAnder::NonThreadAnder }};
151 if (is<AST::ArrayType>(unnamedType))
152 return wrapAnderCallArgument<AST::MakeArrayReferenceExpression, AST::ArrayReferenceType>(expression, anderFunction, threadAnderFunction);
153 }
154 return wrapAnderCallArgument<AST::MakePointerExpression, AST::PointerType>(expression, anderFunction, threadAnderFunction);
155 }
156
157 static Optional<UniqueRef<AST::Expression>> setterCall(AST::PropertyAccessExpression& propertyAccessExpression, AST::FunctionDeclaration* relevantAnder, UniqueRef<AST::Expression>&& newValue, const std::function<UniqueRef<AST::Expression>()>& leftValueFactory, AST::VariableDeclaration* indexVariable)