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