| [54e41b3] | 1 | //
 | 
|---|
 | 2 | // Cforall Version 1.0.0 Copyright (C) 2015 University of Waterloo
 | 
|---|
 | 3 | //
 | 
|---|
 | 4 | // The contents of this file are covered under the licence agreement in the
 | 
|---|
 | 5 | // file "LICENCE" distributed with Cforall.
 | 
|---|
 | 6 | //
 | 
|---|
 | 7 | // Expr.cpp --
 | 
|---|
 | 8 | //
 | 
|---|
 | 9 | // Author           : Aaron B. Moss
 | 
|---|
 | 10 | // Created On       : Wed May 15 17:00:00 2019
 | 
|---|
| [f27331c] | 11 | // Last Modified By : Andrew Beach
 | 
|---|
 | 12 | // Created On       : Tue Nov 30 14:23:00 2021
 | 
|---|
 | 13 | // Update Count     : 7
 | 
|---|
| [54e41b3] | 14 | //
 | 
|---|
 | 15 | 
 | 
|---|
 | 16 | #include "Expr.hpp"
 | 
|---|
 | 17 | 
 | 
|---|
 | 18 | #include <cassert>                 // for strict_dynamic_cast
 | 
|---|
 | 19 | #include <string>                  // for to_string
 | 
|---|
 | 20 | #include <vector>
 | 
|---|
 | 21 | 
 | 
|---|
| [2890212] | 22 | #include "Copy.hpp"                // for shallowCopy
 | 
|---|
| [417117e] | 23 | #include "Eval.hpp"                // for call
 | 
|---|
| [d8938622] | 24 | #include "GenericSubstitution.hpp"
 | 
|---|
| [cf32116] | 25 | #include "LinkageSpec.hpp"
 | 
|---|
| [9b4f329] | 26 | #include "Stmt.hpp"
 | 
|---|
| [54e41b3] | 27 | #include "Type.hpp"
 | 
|---|
| [d8938622] | 28 | #include "TypeSubstitution.hpp"
 | 
|---|
| [733074e] | 29 | #include "Common/utility.h"
 | 
|---|
| [54e41b3] | 30 | #include "Common/SemanticError.h"
 | 
|---|
 | 31 | #include "GenPoly/Lvalue.h"        // for referencesPermissable
 | 
|---|
| [cf32116] | 32 | #include "InitTweak/InitTweak.h"   // for getFunction, getPointerBase
 | 
|---|
| [54e41b3] | 33 | #include "ResolvExpr/typeops.h"    // for extractResultType
 | 
|---|
| [9b4f329] | 34 | #include "Tuples/Tuples.h"         // for makeTupleType
 | 
|---|
| [54e41b3] | 35 | 
 | 
|---|
 | 36 | namespace ast {
 | 
|---|
 | 37 | 
 | 
|---|
| [cf32116] | 38 | namespace {
 | 
|---|
 | 39 |         std::set<std::string> const lvalueFunctionNames = {"*?", "?[?]"};
 | 
|---|
 | 40 | }
 | 
|---|
 | 41 | 
 | 
|---|
 | 42 | // --- Expr
 | 
|---|
 | 43 | bool Expr::get_lvalue() const {
 | 
|---|
 | 44 |         return false;
 | 
|---|
 | 45 | }
 | 
|---|
 | 46 | 
 | 
|---|
| [54e41b3] | 47 | // --- ApplicationExpr
 | 
|---|
 | 48 | 
 | 
|---|
| [87701b6] | 49 | ApplicationExpr::ApplicationExpr( const CodeLocation & loc, const Expr * f,
 | 
|---|
 | 50 |         std::vector<ptr<Expr>> && as )
 | 
|---|
 | 51 | : Expr( loc ), func( f ), args( std::move(as) ) {
 | 
|---|
| [54e41b3] | 52 |         // ensure that `ApplicationExpr` result type is `FuncExpr`
 | 
|---|
 | 53 |         const PointerType * pt = strict_dynamic_cast< const PointerType * >( f->result.get() );
 | 
|---|
 | 54 |         const FunctionType * fn = strict_dynamic_cast< const FunctionType * >( pt->base.get() );
 | 
|---|
 | 55 | 
 | 
|---|
 | 56 |         result = ResolvExpr::extractResultType( fn );
 | 
|---|
 | 57 |         assert( result );
 | 
|---|
 | 58 | }
 | 
|---|
 | 59 | 
 | 
|---|
| [cf32116] | 60 | bool ApplicationExpr::get_lvalue() const {
 | 
|---|
 | 61 |         if ( const DeclWithType * func = InitTweak::getFunction( this ) ) {
 | 
|---|
 | 62 |                 return func->linkage == Linkage::Intrinsic && lvalueFunctionNames.count( func->name );
 | 
|---|
 | 63 |         }
 | 
|---|
 | 64 |         return false;
 | 
|---|
 | 65 | }
 | 
|---|
 | 66 | 
 | 
|---|
| [54e41b3] | 67 | // --- UntypedExpr
 | 
|---|
 | 68 | 
 | 
|---|
| [490fb92e] | 69 | UntypedExpr * UntypedExpr::createDeref( const CodeLocation & loc, const Expr * arg ) {
 | 
|---|
| [54e41b3] | 70 |         assert( arg );
 | 
|---|
 | 71 | 
 | 
|---|
| [417117e] | 72 |         UntypedExpr * ret = call( loc, "*?", arg );
 | 
|---|
| [54e41b3] | 73 |         if ( const Type * ty = arg->result ) {
 | 
|---|
 | 74 |                 const Type * base = InitTweak::getPointerBase( ty );
 | 
|---|
 | 75 |                 assertf( base, "expected pointer type in dereference (type was %s)", toString( ty ).c_str() );
 | 
|---|
 | 76 | 
 | 
|---|
 | 77 |                 if ( GenPoly::referencesPermissable() ) {
 | 
|---|
 | 78 |                         // if references are still allowed in the AST, dereference returns a reference
 | 
|---|
 | 79 |                         ret->result = new ReferenceType{ base };
 | 
|---|
 | 80 |                 } else {
 | 
|---|
| [87701b6] | 81 |                         // references have been removed, in which case dereference returns an lvalue of the
 | 
|---|
| [54e41b3] | 82 |                         // base type
 | 
|---|
| [d76c588] | 83 |                         ret->result = base;
 | 
|---|
| [54e41b3] | 84 |                 }
 | 
|---|
 | 85 |         }
 | 
|---|
 | 86 |         return ret;
 | 
|---|
 | 87 | }
 | 
|---|
 | 88 | 
 | 
|---|
| [cf32116] | 89 | bool UntypedExpr::get_lvalue() const {
 | 
|---|
 | 90 |         std::string fname = InitTweak::getFunctionName( this );
 | 
|---|
 | 91 |         return lvalueFunctionNames.count( fname );
 | 
|---|
 | 92 | }
 | 
|---|
 | 93 | 
 | 
|---|
| [490fb92e] | 94 | UntypedExpr * UntypedExpr::createAssign( const CodeLocation & loc, const Expr * lhs, const Expr * rhs ) {
 | 
|---|
| [54e41b3] | 95 |         assert( lhs && rhs );
 | 
|---|
 | 96 | 
 | 
|---|
| [417117e] | 97 |         UntypedExpr * ret = call( loc, "?=?", lhs, rhs );
 | 
|---|
| [54e41b3] | 98 |         if ( lhs->result && rhs->result ) {
 | 
|---|
 | 99 |                 // if both expressions are typed, assumes that this assignment is a C bitwise assignment,
 | 
|---|
 | 100 |                 // so the result is the type of the RHS
 | 
|---|
 | 101 |                 ret->result = rhs->result;
 | 
|---|
 | 102 |         }
 | 
|---|
 | 103 |         return ret;
 | 
|---|
 | 104 | }
 | 
|---|
 | 105 | 
 | 
|---|
| [d5631b3] | 106 | // --- VariableExpr
 | 
|---|
 | 107 | 
 | 
|---|
 | 108 | VariableExpr::VariableExpr( const CodeLocation & loc )
 | 
|---|
 | 109 | : Expr( loc ), var( nullptr ) {}
 | 
|---|
 | 110 | 
 | 
|---|
 | 111 | VariableExpr::VariableExpr( const CodeLocation & loc, const DeclWithType * v )
 | 
|---|
 | 112 | : Expr( loc ), var( v ) {
 | 
|---|
 | 113 |         assert( var );
 | 
|---|
 | 114 |         assert( var->get_type() );
 | 
|---|
 | 115 |         result = shallowCopy( var->get_type() );
 | 
|---|
 | 116 | }
 | 
|---|
 | 117 | 
 | 
|---|
 | 118 | bool VariableExpr::get_lvalue() const {
 | 
|---|
 | 119 |         // It isn't always an lvalue, but it is never an rvalue.
 | 
|---|
 | 120 |         return true;
 | 
|---|
 | 121 | }
 | 
|---|
 | 122 | 
 | 
|---|
 | 123 | VariableExpr * VariableExpr::functionPointer(
 | 
|---|
 | 124 |                 const CodeLocation & loc, const FunctionDecl * decl ) {
 | 
|---|
 | 125 |         // wrap usually-determined result type in a pointer
 | 
|---|
 | 126 |         VariableExpr * funcExpr = new VariableExpr{ loc, decl };
 | 
|---|
 | 127 |         funcExpr->result = new PointerType{ funcExpr->result };
 | 
|---|
 | 128 |         return funcExpr;
 | 
|---|
 | 129 | }
 | 
|---|
 | 130 | 
 | 
|---|
| [54e41b3] | 131 | // --- AddressExpr
 | 
|---|
 | 132 | 
 | 
|---|
 | 133 | // Address expressions are typed based on the following inference rules:
 | 
|---|
 | 134 | //    E : lvalue T  &..& (n references)
 | 
|---|
 | 135 | //   &E :        T *&..& (n references)
 | 
|---|
 | 136 | //
 | 
|---|
 | 137 | //    E : T  &..&        (m references)
 | 
|---|
 | 138 | //   &E : T *&..&        (m-1 references)
 | 
|---|
 | 139 | 
 | 
|---|
 | 140 | namespace {
 | 
|---|
 | 141 |         /// The type of the address of a type.
 | 
|---|
 | 142 |         /// Caller is responsible for managing returned memory
 | 
|---|
| [f27331c] | 143 |         Type * addrType( const ptr<Type> & type ) {
 | 
|---|
 | 144 |                 if ( auto refType = type.as< ReferenceType >() ) {
 | 
|---|
 | 145 |                         return new ReferenceType( addrType( refType->base ), refType->qualifiers );
 | 
|---|
| [54e41b3] | 146 |                 } else {
 | 
|---|
| [f27331c] | 147 |                         return new PointerType( type );
 | 
|---|
| [54e41b3] | 148 |                 }
 | 
|---|
 | 149 |         }
 | 
|---|
 | 150 | 
 | 
|---|
| [f27331c] | 151 |         /// The type of the address of an expression.
 | 
|---|
 | 152 |         /// Caller is responsible for managing returned memory
 | 
|---|
 | 153 |         Type * addrExprType( const CodeLocation & loc, const Expr * arg ) {
 | 
|---|
 | 154 |                 assert( arg );
 | 
|---|
 | 155 |                 // If the expression's type is unknown, the address type is unknown.
 | 
|---|
 | 156 |                 if ( nullptr == arg->result ) {
 | 
|---|
 | 157 |                         return nullptr;
 | 
|---|
 | 158 |                 // An lvalue is transformed directly.
 | 
|---|
 | 159 |                 } else if ( arg->get_lvalue() ) {
 | 
|---|
 | 160 |                         return addrType( arg->result );
 | 
|---|
 | 161 |                 // Strip a layer of reference to "create" an lvalue expression.
 | 
|---|
 | 162 |                 } else if ( auto refType = arg->result.as< ReferenceType >() ) {
 | 
|---|
 | 163 |                         return addrType( refType->base );
 | 
|---|
| [54e41b3] | 164 |                 } else {
 | 
|---|
| [f27331c] | 165 |                         SemanticError( loc, arg->result.get(),
 | 
|---|
 | 166 |                                 "Attempt to take address of non-lvalue expression: " );
 | 
|---|
| [54e41b3] | 167 |                 }
 | 
|---|
 | 168 |         }
 | 
|---|
 | 169 | }
 | 
|---|
 | 170 | 
 | 
|---|
| [f27331c] | 171 | AddressExpr::AddressExpr( const CodeLocation & loc, const Expr * a ) :
 | 
|---|
 | 172 |         Expr( loc, addrExprType( loc, a ) ), arg( a )
 | 
|---|
 | 173 | {}
 | 
|---|
 | 174 | 
 | 
|---|
| [54e41b3] | 175 | // --- LabelAddressExpr
 | 
|---|
 | 176 | 
 | 
|---|
 | 177 | // label address always has type `void*`
 | 
|---|
| [87701b6] | 178 | LabelAddressExpr::LabelAddressExpr( const CodeLocation & loc, Label && a )
 | 
|---|
| [54e41b3] | 179 | : Expr( loc, new PointerType{ new VoidType{} } ), arg( a ) {}
 | 
|---|
 | 180 | 
 | 
|---|
 | 181 | // --- CastExpr
 | 
|---|
 | 182 | 
 | 
|---|
| [87701b6] | 183 | CastExpr::CastExpr( const CodeLocation & loc, const Expr * a, GeneratedFlag g )
 | 
|---|
| [54e41b3] | 184 | : Expr( loc, new VoidType{} ), arg( a ), isGenerated( g ) {}
 | 
|---|
 | 185 | 
 | 
|---|
| [cf32116] | 186 | bool CastExpr::get_lvalue() const {
 | 
|---|
 | 187 |         // This is actually wrong by C, but it works with our current set-up.
 | 
|---|
 | 188 |         return arg->get_lvalue();
 | 
|---|
 | 189 | }
 | 
|---|
 | 190 | 
 | 
|---|
| [54e41b3] | 191 | // --- KeywordCastExpr
 | 
|---|
 | 192 | 
 | 
|---|
| [312029a] | 193 | const char * KeywordCastExpr::targetString() const {
 | 
|---|
 | 194 |         return AggregateDecl::aggrString( target );
 | 
|---|
| [54e41b3] | 195 | }
 | 
|---|
 | 196 | 
 | 
|---|
| [cf32116] | 197 | // --- UntypedMemberExpr
 | 
|---|
 | 198 | 
 | 
|---|
 | 199 | bool UntypedMemberExpr::get_lvalue() const {
 | 
|---|
 | 200 |         return aggregate->get_lvalue();
 | 
|---|
 | 201 | }
 | 
|---|
 | 202 | 
 | 
|---|
| [54e41b3] | 203 | // --- MemberExpr
 | 
|---|
 | 204 | 
 | 
|---|
 | 205 | MemberExpr::MemberExpr( const CodeLocation & loc, const DeclWithType * mem, const Expr * agg )
 | 
|---|
 | 206 | : Expr( loc ), member( mem ), aggregate( agg ) {
 | 
|---|
 | 207 |         assert( member );
 | 
|---|
 | 208 |         assert( aggregate );
 | 
|---|
 | 209 |         assert( aggregate->result );
 | 
|---|
 | 210 | 
 | 
|---|
| [3e5dd913] | 211 |         result = mem->get_type();
 | 
|---|
| [ae265b55] | 212 | 
 | 
|---|
| [335f2d8] | 213 |         // substitute aggregate generic parameters into member type
 | 
|---|
| [60aaa51d] | 214 |         genericSubstitution( aggregate->result ).apply( result );
 | 
|---|
| [3f3bfe5a] | 215 |         // ensure appropriate restrictions from aggregate type
 | 
|---|
 | 216 |         add_qualifiers( result, aggregate->result->qualifiers );
 | 
|---|
| [54e41b3] | 217 | }
 | 
|---|
 | 218 | 
 | 
|---|
| [ae265b55] | 219 | MemberExpr::MemberExpr( const CodeLocation & loc, const DeclWithType * mem, const Expr * agg,
 | 
|---|
 | 220 |     MemberExpr::NoOpConstruction overloadSelector )
 | 
|---|
 | 221 | : Expr( loc ), member( mem ), aggregate( agg ) {
 | 
|---|
 | 222 |         assert( member );
 | 
|---|
 | 223 |         assert( aggregate );
 | 
|---|
 | 224 |         assert( aggregate->result );
 | 
|---|
 | 225 |         (void) overloadSelector;
 | 
|---|
 | 226 | }
 | 
|---|
 | 227 | 
 | 
|---|
| [cf32116] | 228 | bool MemberExpr::get_lvalue() const {
 | 
|---|
 | 229 |         // This is actually wrong by C, but it works with our current set-up.
 | 
|---|
 | 230 |         return true;
 | 
|---|
 | 231 | }
 | 
|---|
 | 232 | 
 | 
|---|
| [54e41b3] | 233 | // --- ConstantExpr
 | 
|---|
 | 234 | 
 | 
|---|
 | 235 | long long int ConstantExpr::intValue() const {
 | 
|---|
 | 236 |         if ( const BasicType * bty = result.as< BasicType >() ) {
 | 
|---|
 | 237 |                 if ( bty->isInteger() ) {
 | 
|---|
| [c36298d] | 238 |                         assert(ival);
 | 
|---|
 | 239 |                         return ival.value();
 | 
|---|
| [54e41b3] | 240 |                 }
 | 
|---|
 | 241 |         } else if ( result.as< ZeroType >() ) {
 | 
|---|
 | 242 |                 return 0;
 | 
|---|
 | 243 |         } else if ( result.as< OneType >() ) {
 | 
|---|
 | 244 |                 return 1;
 | 
|---|
 | 245 |         }
 | 
|---|
 | 246 |         SemanticError( this, "Constant expression of non-integral type " );
 | 
|---|
 | 247 | }
 | 
|---|
 | 248 | 
 | 
|---|
 | 249 | ConstantExpr * ConstantExpr::from_bool( const CodeLocation & loc, bool b ) {
 | 
|---|
| [87701b6] | 250 |         return new ConstantExpr{
 | 
|---|
| [54e41b3] | 251 |                 loc, new BasicType{ BasicType::Bool }, b ? "1" : "0", (unsigned long long)b };
 | 
|---|
 | 252 | }
 | 
|---|
 | 253 | 
 | 
|---|
 | 254 | ConstantExpr * ConstantExpr::from_int( const CodeLocation & loc, int i ) {
 | 
|---|
| [87701b6] | 255 |         return new ConstantExpr{
 | 
|---|
| [54e41b3] | 256 |                 loc, new BasicType{ BasicType::SignedInt }, std::to_string( i ), (unsigned long long)i };
 | 
|---|
 | 257 | }
 | 
|---|
 | 258 | 
 | 
|---|
 | 259 | ConstantExpr * ConstantExpr::from_ulong( const CodeLocation & loc, unsigned long i ) {
 | 
|---|
| [87701b6] | 260 |         return new ConstantExpr{
 | 
|---|
 | 261 |                 loc, new BasicType{ BasicType::LongUnsignedInt }, std::to_string( i ),
 | 
|---|
| [54e41b3] | 262 |                 (unsigned long long)i };
 | 
|---|
 | 263 | }
 | 
|---|
 | 264 | 
 | 
|---|
| [b91bfde] | 265 | ConstantExpr * ConstantExpr::from_string( const CodeLocation & loc, const std::string & str ) {
 | 
|---|
 | 266 |         const Type * charType = new BasicType( BasicType::Char );
 | 
|---|
 | 267 |         // Adjust the length of the string for the terminator.
 | 
|---|
 | 268 |         const Expr * strSize = from_ulong( loc, str.size() + 1 );
 | 
|---|
 | 269 |         const Type * strType = new ArrayType( charType, strSize, FixedLen, StaticDim );
 | 
|---|
 | 270 |         const std::string strValue = "\"" + str + "\"";
 | 
|---|
 | 271 |         return new ConstantExpr( loc, strType, strValue, std::nullopt );
 | 
|---|
 | 272 | }
 | 
|---|
 | 273 | 
 | 
|---|
| [54e41b3] | 274 | ConstantExpr * ConstantExpr::null( const CodeLocation & loc, const Type * ptrType ) {
 | 
|---|
 | 275 |         return new ConstantExpr{
 | 
|---|
 | 276 |                 loc, ptrType ? ptrType : new PointerType{ new VoidType{} }, "0", (unsigned long long)0 };
 | 
|---|
 | 277 | }
 | 
|---|
 | 278 | 
 | 
|---|
 | 279 | // --- SizeofExpr
 | 
|---|
 | 280 | 
 | 
|---|
 | 281 | SizeofExpr::SizeofExpr( const CodeLocation & loc, const Expr * e )
 | 
|---|
 | 282 | : Expr( loc, new BasicType{ BasicType::LongUnsignedInt } ), expr( e ), type( nullptr ) {}
 | 
|---|
 | 283 | 
 | 
|---|
 | 284 | SizeofExpr::SizeofExpr( const CodeLocation & loc, const Type * t )
 | 
|---|
 | 285 | : Expr( loc, new BasicType{ BasicType::LongUnsignedInt } ), expr( nullptr ), type( t ) {}
 | 
|---|
 | 286 | 
 | 
|---|
 | 287 | // --- AlignofExpr
 | 
|---|
 | 288 | 
 | 
|---|
 | 289 | AlignofExpr::AlignofExpr( const CodeLocation & loc, const Expr * e )
 | 
|---|
 | 290 | : Expr( loc, new BasicType{ BasicType::LongUnsignedInt } ), expr( e ), type( nullptr ) {}
 | 
|---|
 | 291 | 
 | 
|---|
 | 292 | AlignofExpr::AlignofExpr( const CodeLocation & loc, const Type * t )
 | 
|---|
 | 293 | : Expr( loc, new BasicType{ BasicType::LongUnsignedInt } ), expr( nullptr ), type( t ) {}
 | 
|---|
 | 294 | 
 | 
|---|
 | 295 | // --- OffsetofExpr
 | 
|---|
 | 296 | 
 | 
|---|
 | 297 | OffsetofExpr::OffsetofExpr( const CodeLocation & loc, const Type * ty, const DeclWithType * mem )
 | 
|---|
 | 298 | : Expr( loc, new BasicType{ BasicType::LongUnsignedInt } ), type( ty ), member( mem ) {
 | 
|---|
 | 299 |         assert( type );
 | 
|---|
 | 300 |         assert( member );
 | 
|---|
 | 301 | }
 | 
|---|
 | 302 | 
 | 
|---|
 | 303 | // --- OffsetPackExpr
 | 
|---|
 | 304 | 
 | 
|---|
 | 305 | OffsetPackExpr::OffsetPackExpr( const CodeLocation & loc, const StructInstType * ty )
 | 
|---|
| [87701b6] | 306 | : Expr( loc, new ArrayType{
 | 
|---|
 | 307 |         new BasicType{ BasicType::LongUnsignedInt }, nullptr, FixedLen, DynamicDim }
 | 
|---|
| [54e41b3] | 308 | ), type( ty ) {
 | 
|---|
 | 309 |         assert( type );
 | 
|---|
 | 310 | }
 | 
|---|
 | 311 | 
 | 
|---|
 | 312 | // --- LogicalExpr
 | 
|---|
 | 313 | 
 | 
|---|
| [87701b6] | 314 | LogicalExpr::LogicalExpr(
 | 
|---|
| [54e41b3] | 315 |         const CodeLocation & loc, const Expr * a1, const Expr * a2, LogicalFlag ia )
 | 
|---|
 | 316 | : Expr( loc, new BasicType{ BasicType::SignedInt } ), arg1( a1 ), arg2( a2 ), isAnd( ia ) {}
 | 
|---|
 | 317 | 
 | 
|---|
| [cf32116] | 318 | // --- CommaExpr
 | 
|---|
 | 319 | bool CommaExpr::get_lvalue() const {
 | 
|---|
 | 320 |         // This is wrong by C, but the current implementation uses it.
 | 
|---|
 | 321 |         // (ex: Specialize, Lvalue and Box)
 | 
|---|
 | 322 |         return arg2->get_lvalue();
 | 
|---|
 | 323 | }
 | 
|---|
 | 324 | 
 | 
|---|
| [9b4f329] | 325 | // --- ConstructorExpr
 | 
|---|
 | 326 | 
 | 
|---|
| [10a1225] | 327 | ConstructorExpr::ConstructorExpr( const CodeLocation & loc, const Expr * call )
 | 
|---|
| [9b4f329] | 328 | : Expr( loc ), callExpr( call ) {
 | 
|---|
| [10a1225] | 329 |         // allow resolver to type a constructor used as an expression if it has the same type as its
 | 
|---|
| [9b4f329] | 330 |         // first argument
 | 
|---|
 | 331 |         assert( callExpr );
 | 
|---|
 | 332 |         const Expr * arg = InitTweak::getCallArg( callExpr, 0 );
 | 
|---|
 | 333 |         assert( arg );
 | 
|---|
 | 334 |         result = arg->result;
 | 
|---|
 | 335 | }
 | 
|---|
 | 336 | 
 | 
|---|
 | 337 | // --- CompoundLiteralExpr
 | 
|---|
 | 338 | 
 | 
|---|
 | 339 | CompoundLiteralExpr::CompoundLiteralExpr( const CodeLocation & loc, const Type * t, const Init * i )
 | 
|---|
 | 340 | : Expr( loc ), init( i ) {
 | 
|---|
 | 341 |         assert( t && i );
 | 
|---|
| [d76c588] | 342 |         result = t;
 | 
|---|
| [9b4f329] | 343 | }
 | 
|---|
 | 344 | 
 | 
|---|
| [cf32116] | 345 | bool CompoundLiteralExpr::get_lvalue() const {
 | 
|---|
 | 346 |         return true;
 | 
|---|
 | 347 | }
 | 
|---|
 | 348 | 
 | 
|---|
| [9b4f329] | 349 | // --- TupleExpr
 | 
|---|
 | 350 | 
 | 
|---|
 | 351 | TupleExpr::TupleExpr( const CodeLocation & loc, std::vector<ptr<Expr>> && xs )
 | 
|---|
 | 352 | : Expr( loc, Tuples::makeTupleType( xs ) ), exprs( xs ) {}
 | 
|---|
 | 353 | 
 | 
|---|
 | 354 | // --- TupleIndexExpr
 | 
|---|
 | 355 | 
 | 
|---|
 | 356 | TupleIndexExpr::TupleIndexExpr( const CodeLocation & loc, const Expr * t, unsigned i )
 | 
|---|
 | 357 | : Expr( loc ), tuple( t ), index( i ) {
 | 
|---|
| [10a1225] | 358 |         const TupleType * type = strict_dynamic_cast< const TupleType * >( tuple->result.get() );
 | 
|---|
| [9b4f329] | 359 |         assertf( type->size() > index, "TupleIndexExpr index out of bounds: tuple size %d, requested "
 | 
|---|
 | 360 |                 "index %d in expr %s", type->size(), index, toString( tuple ).c_str() );
 | 
|---|
 | 361 |         // like MemberExpr, TupleIndexExpr is always an lvalue
 | 
|---|
| [d76c588] | 362 |         result = type->types[ index ];
 | 
|---|
| [9b4f329] | 363 | }
 | 
|---|
 | 364 | 
 | 
|---|
| [cf32116] | 365 | bool TupleIndexExpr::get_lvalue() const {
 | 
|---|
 | 366 |         return tuple->get_lvalue();
 | 
|---|
 | 367 | }
 | 
|---|
 | 368 | 
 | 
|---|
| [9b4f329] | 369 | // --- TupleAssignExpr
 | 
|---|
 | 370 | 
 | 
|---|
| [10a1225] | 371 | TupleAssignExpr::TupleAssignExpr(
 | 
|---|
 | 372 |         const CodeLocation & loc, std::vector<ptr<Expr>> && assigns,
 | 
|---|
| [9b4f329] | 373 |         std::vector<ptr<ObjectDecl>> && tempDecls )
 | 
|---|
 | 374 | : Expr( loc, Tuples::makeTupleType( assigns ) ), stmtExpr() {
 | 
|---|
| [10a1225] | 375 |         // convert internally into a StmtExpr which contains the declarations and produces the tuple of
 | 
|---|
| [9b4f329] | 376 |         // the assignments
 | 
|---|
 | 377 |         std::list<ptr<Stmt>> stmts;
 | 
|---|
 | 378 |         for ( const ObjectDecl * obj : tempDecls ) {
 | 
|---|
 | 379 |                 stmts.emplace_back( new DeclStmt{ loc, obj } );
 | 
|---|
 | 380 |         }
 | 
|---|
 | 381 |         TupleExpr * tupleExpr = new TupleExpr{ loc, std::move(assigns) };
 | 
|---|
 | 382 |         assert( tupleExpr->result );
 | 
|---|
 | 383 |         stmts.emplace_back( new ExprStmt{ loc, tupleExpr } );
 | 
|---|
 | 384 |         stmtExpr = new StmtExpr{ loc, new CompoundStmt{ loc, std::move(stmts) } };
 | 
|---|
 | 385 | }
 | 
|---|
 | 386 | 
 | 
|---|
| [0b57626] | 387 | TupleAssignExpr::TupleAssignExpr(
 | 
|---|
| [20de6fb] | 388 |         const CodeLocation & loc, const Type * result, const StmtExpr * s )
 | 
|---|
 | 389 | : Expr( loc, result ), stmtExpr() {
 | 
|---|
 | 390 |         stmtExpr = s;
 | 
|---|
 | 391 | }
 | 
|---|
 | 392 | 
 | 
|---|
| [9b4f329] | 393 | // --- StmtExpr
 | 
|---|
 | 394 | 
 | 
|---|
| [10a1225] | 395 | StmtExpr::StmtExpr( const CodeLocation & loc, const CompoundStmt * ss )
 | 
|---|
| [9b4f329] | 396 | : Expr( loc ), stmts( ss ), returnDecls(), dtors() { computeResult(); }
 | 
|---|
 | 397 | 
 | 
|---|
 | 398 | void StmtExpr::computeResult() {
 | 
|---|
 | 399 |         assert( stmts );
 | 
|---|
 | 400 |         const std::list<ptr<Stmt>> & body = stmts->kids;
 | 
|---|
 | 401 |         if ( ! returnDecls.empty() ) {
 | 
|---|
| [10a1225] | 402 |                 // prioritize return decl for result type, since if a return decl exists, then the StmtExpr
 | 
|---|
| [9b4f329] | 403 |                 // is currently in an intermediate state where the body will always give a void result type
 | 
|---|
 | 404 |                 result = returnDecls.front()->get_type();
 | 
|---|
 | 405 |         } else if ( ! body.empty() ) {
 | 
|---|
 | 406 |                 if ( const ExprStmt * exprStmt = body.back().as< ExprStmt >() ) {
 | 
|---|
 | 407 |                         result = exprStmt->expr->result;
 | 
|---|
 | 408 |                 }
 | 
|---|
 | 409 |         }
 | 
|---|
 | 410 |         // ensure a result type exists
 | 
|---|
 | 411 |         if ( ! result ) { result = new VoidType{}; }
 | 
|---|
 | 412 | }
 | 
|---|
 | 413 | 
 | 
|---|
 | 414 | // --- UniqueExpr
 | 
|---|
 | 415 | 
 | 
|---|
 | 416 | unsigned long long UniqueExpr::nextId = 0;
 | 
|---|
 | 417 | 
 | 
|---|
| [10a1225] | 418 | UniqueExpr::UniqueExpr( const CodeLocation & loc, const Expr * e, unsigned long long i )
 | 
|---|
| [d76f32c] | 419 | : Expr( loc, e->result ), expr( e ), id( i ) {
 | 
|---|
| [9b4f329] | 420 |         assert( expr );
 | 
|---|
| [10a1225] | 421 |         if ( id == -1ull ) {
 | 
|---|
 | 422 |                 assert( nextId != -1ull );
 | 
|---|
| [9b4f329] | 423 |                 id = nextId++;
 | 
|---|
 | 424 |         }
 | 
|---|
| [54e41b3] | 425 | }
 | 
|---|
 | 426 | 
 | 
|---|
| [10a1225] | 427 | }
 | 
|---|
 | 428 | 
 | 
|---|
| [54e41b3] | 429 | // Local Variables: //
 | 
|---|
 | 430 | // tab-width: 4 //
 | 
|---|
 | 431 | // mode: c++ //
 | 
|---|
 | 432 | // compile-command: "make install" //
 | 
|---|
| [d76f32c] | 433 | // End: //
 | 
|---|