source: src/AST/Expr.cpp @ b0abc8a0

ADTarm-ehast-experimentalcleanup-dtorsenumforall-pointer-decayjacob/cs343-translationjenkins-sandboxnew-astnew-ast-unique-exprpthread-emulationqualifiedEnum
Last change on this file since b0abc8a0 was 733074e, checked in by Thierry Delisle <tdelisle@…>, 5 years ago

Removed stub for toString by moving to a more precise Stub

  • Property mode set to 100644
File size: 12.1 KB
Line 
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
11// Last Modified By : Aaron B. Moss
12// Created On       : Wed May 15 17:00:00 2019
13// Update Count     : 1
14//
15
16#include "Expr.hpp"
17
18#include <cassert>                 // for strict_dynamic_cast
19#include <string>                  // for to_string
20#include <vector>
21
22#include "Stmt.hpp"
23#include "Type.hpp"
24#include "Common/utility.h"
25#include "Common/SemanticError.h"
26#include "GenPoly/Lvalue.h"        // for referencesPermissable
27#include "InitTweak/InitTweak.h"   // for getPointerBase
28#include "ResolvExpr/typeops.h"    // for extractResultType
29#include "Tuples/Tuples.h"         // for makeTupleType
30
31namespace ast {
32
33// --- ApplicationExpr
34
35ApplicationExpr::ApplicationExpr( const CodeLocation & loc, const Expr * f,
36        std::vector<ptr<Expr>> && as )
37: Expr( loc ), func( f ), args( std::move(as) ) {
38        // ensure that `ApplicationExpr` result type is `FuncExpr`
39        const PointerType * pt = strict_dynamic_cast< const PointerType * >( f->result.get() );
40        const FunctionType * fn = strict_dynamic_cast< const FunctionType * >( pt->base.get() );
41
42        result = ResolvExpr::extractResultType( fn );
43        assert( result );
44}
45
46// --- UntypedExpr
47
48UntypedExpr * UntypedExpr::createDeref( const CodeLocation & loc, Expr * arg ) {
49        assert( arg );
50
51        UntypedExpr * ret = new UntypedExpr{
52                loc, new NameExpr{loc, "*?"}, std::vector<ptr<Expr>>{ ptr<Expr>{ arg } }
53        };
54        if ( const Type * ty = arg->result ) {
55                const Type * base = InitTweak::getPointerBase( ty );
56                assertf( base, "expected pointer type in dereference (type was %s)", toString( ty ).c_str() );
57
58                if ( GenPoly::referencesPermissable() ) {
59                        // if references are still allowed in the AST, dereference returns a reference
60                        ret->result = new ReferenceType{ base };
61                } else {
62                        // references have been removed, in which case dereference returns an lvalue of the
63                        // base type
64                        ret->result.set_and_mutate( base )->set_lvalue( true );
65                }
66        }
67        return ret;
68}
69
70UntypedExpr * UntypedExpr::createAssign( const CodeLocation & loc, Expr * lhs, Expr * rhs ) {
71        assert( lhs && rhs );
72
73        UntypedExpr * ret = new UntypedExpr{
74                loc, new NameExpr{loc, "?=?"}, std::vector<ptr<Expr>>{ ptr<Expr>{ lhs }, ptr<Expr>{ rhs } }
75        };
76        if ( lhs->result && rhs->result ) {
77                // if both expressions are typed, assumes that this assignment is a C bitwise assignment,
78                // so the result is the type of the RHS
79                ret->result = rhs->result;
80        }
81        return ret;
82}
83
84// --- AddressExpr
85
86// Address expressions are typed based on the following inference rules:
87//    E : lvalue T  &..& (n references)
88//   &E :        T *&..& (n references)
89//
90//    E : T  &..&        (m references)
91//   &E : T *&..&        (m-1 references)
92
93namespace {
94        /// The type of the address of a type.
95        /// Caller is responsible for managing returned memory
96        Type * addrType( const Type * type ) {
97                if ( const ReferenceType * refType = dynamic_cast< const ReferenceType * >( type ) ) {
98                        return new ReferenceType{ addrType( refType->base ), refType->qualifiers };
99                } else {
100                        return new PointerType{ type };
101                }
102        }
103}
104
105AddressExpr::AddressExpr( const CodeLocation & loc, const Expr * a ) : Expr( loc ), arg( a ) {
106        if ( arg->result ) {
107                if ( arg->result->is_lvalue() ) {
108                        // lvalue, retains all levels of reference, and gains a pointer inside the references
109                        Type * res = addrType( arg->result );
110                        res->set_lvalue( false ); // result of & is never an lvalue
111                        result = res;
112                } else {
113                        // taking address of non-lvalue, must be a reference, loses one layer of reference
114                        if ( const ReferenceType * refType =
115                                        dynamic_cast< const ReferenceType * >( arg->result.get() ) ) {
116                                Type * res = addrType( refType->base );
117                                res->set_lvalue( false ); // result of & is never an lvalue
118                                result = res;
119                        } else {
120                                SemanticError( loc, arg->result.get(),
121                                        "Attempt to take address of non-lvalue expression: " );
122                        }
123                }
124        }
125}
126
127// --- LabelAddressExpr
128
129// label address always has type `void*`
130LabelAddressExpr::LabelAddressExpr( const CodeLocation & loc, Label && a )
131: Expr( loc, new PointerType{ new VoidType{} } ), arg( a ) {}
132
133// --- CastExpr
134
135CastExpr::CastExpr( const CodeLocation & loc, const Expr * a, GeneratedFlag g )
136: Expr( loc, new VoidType{} ), arg( a ), isGenerated( g ) {}
137
138// --- KeywordCastExpr
139
140const std::string & KeywordCastExpr::targetString() const {
141        static const std::string targetStrs[] = {
142                "coroutine", "thread", "monitor"
143        };
144        static_assert(
145                (sizeof(targetStrs) / sizeof(targetStrs[0])) == ((unsigned long)NUMBER_OF_TARGETS),
146                "Each KeywordCastExpr::Target should have a corresponding string representation"
147        );
148        return targetStrs[(unsigned long)target];
149}
150
151// --- MemberExpr
152
153MemberExpr::MemberExpr( const CodeLocation & loc, const DeclWithType * mem, const Expr * agg )
154: Expr( loc ), member( mem ), aggregate( agg ) {
155        assert( member );
156        assert( aggregate );
157        assert( aggregate->result );
158
159        assert(!"unimplemented; need TypeSubstitution, genericSubstitution");
160}
161
162// --- VariableExpr
163
164VariableExpr::VariableExpr( const CodeLocation & loc, const DeclWithType * v )
165: Expr( loc ), var( v ) {
166        assert( var );
167        assert( var->get_type() );
168        result.set_and_mutate( var->get_type() )->set_lvalue( true );
169}
170
171VariableExpr * VariableExpr::functionPointer(
172                const CodeLocation & loc, const FunctionDecl * decl ) {
173        // wrap usually-determined result type in a pointer
174        VariableExpr * funcExpr = new VariableExpr{ loc, decl };
175        funcExpr->result = new PointerType{ funcExpr->result };
176        return funcExpr;
177}
178
179// --- ConstantExpr
180
181long long int ConstantExpr::intValue() const {
182        if ( const BasicType * bty = result.as< BasicType >() ) {
183                if ( bty->isInteger() ) {
184                        return val.ival;
185                }
186        } else if ( result.as< ZeroType >() ) {
187                return 0;
188        } else if ( result.as< OneType >() ) {
189                return 1;
190        }
191        SemanticError( this, "Constant expression of non-integral type " );
192}
193
194double ConstantExpr::floatValue() const {
195        if ( const BasicType * bty = result.as< BasicType >() ) {
196                if ( ! bty->isInteger() ) {
197                        return val.dval;
198                }
199        }
200        SemanticError( this, "Constant expression of non-floating-point type " );
201}
202
203ConstantExpr * ConstantExpr::from_bool( const CodeLocation & loc, bool b ) {
204        return new ConstantExpr{
205                loc, new BasicType{ BasicType::Bool }, b ? "1" : "0", (unsigned long long)b };
206}
207
208ConstantExpr * ConstantExpr::from_char( const CodeLocation & loc, char c ) {
209        return new ConstantExpr{
210                loc, new BasicType{ BasicType::Char }, std::to_string( c ), (unsigned long long)c };
211}
212
213ConstantExpr * ConstantExpr::from_int( const CodeLocation & loc, int i ) {
214        return new ConstantExpr{
215                loc, new BasicType{ BasicType::SignedInt }, std::to_string( i ), (unsigned long long)i };
216}
217
218ConstantExpr * ConstantExpr::from_ulong( const CodeLocation & loc, unsigned long i ) {
219        return new ConstantExpr{
220                loc, new BasicType{ BasicType::LongUnsignedInt }, std::to_string( i ),
221                (unsigned long long)i };
222}
223
224ConstantExpr * ConstantExpr::from_double( const CodeLocation & loc, double d ) {
225        return new ConstantExpr{ loc, new BasicType{ BasicType::Double }, std::to_string( d ), d };
226}
227
228ConstantExpr * ConstantExpr::from_string( const CodeLocation & loc, const std::string & s ) {
229        return new ConstantExpr{
230                loc,
231                new ArrayType{
232                        new BasicType{ BasicType::Char, CV::Const },
233                        ConstantExpr::from_int( loc, s.size() + 1 /* null terminator */ ),
234                        FixedLen, DynamicDim },
235                std::string{"\""} + s + "\"",
236                (unsigned long long)0 };
237}
238
239ConstantExpr * ConstantExpr::null( const CodeLocation & loc, const Type * ptrType ) {
240        return new ConstantExpr{
241                loc, ptrType ? ptrType : new PointerType{ new VoidType{} }, "0", (unsigned long long)0 };
242}
243
244// --- SizeofExpr
245
246SizeofExpr::SizeofExpr( const CodeLocation & loc, const Expr * e )
247: Expr( loc, new BasicType{ BasicType::LongUnsignedInt } ), expr( e ), type( nullptr ) {}
248
249SizeofExpr::SizeofExpr( const CodeLocation & loc, const Type * t )
250: Expr( loc, new BasicType{ BasicType::LongUnsignedInt } ), expr( nullptr ), type( t ) {}
251
252// --- AlignofExpr
253
254AlignofExpr::AlignofExpr( const CodeLocation & loc, const Expr * e )
255: Expr( loc, new BasicType{ BasicType::LongUnsignedInt } ), expr( e ), type( nullptr ) {}
256
257AlignofExpr::AlignofExpr( const CodeLocation & loc, const Type * t )
258: Expr( loc, new BasicType{ BasicType::LongUnsignedInt } ), expr( nullptr ), type( t ) {}
259
260// --- OffsetofExpr
261
262OffsetofExpr::OffsetofExpr( const CodeLocation & loc, const Type * ty, const DeclWithType * mem )
263: Expr( loc, new BasicType{ BasicType::LongUnsignedInt } ), type( ty ), member( mem ) {
264        assert( type );
265        assert( member );
266}
267
268// --- OffsetPackExpr
269
270OffsetPackExpr::OffsetPackExpr( const CodeLocation & loc, const StructInstType * ty )
271: Expr( loc, new ArrayType{
272        new BasicType{ BasicType::LongUnsignedInt }, nullptr, FixedLen, DynamicDim }
273), type( ty ) {
274        assert( type );
275}
276
277// --- LogicalExpr
278
279LogicalExpr::LogicalExpr(
280        const CodeLocation & loc, const Expr * a1, const Expr * a2, LogicalFlag ia )
281: Expr( loc, new BasicType{ BasicType::SignedInt } ), arg1( a1 ), arg2( a2 ), isAnd( ia ) {}
282
283// --- ConstructorExpr
284
285ConstructorExpr::ConstructorExpr( const CodeLocation & loc, const Expr * call )
286: Expr( loc ), callExpr( call ) {
287        // allow resolver to type a constructor used as an expression if it has the same type as its
288        // first argument
289        assert( callExpr );
290        const Expr * arg = InitTweak::getCallArg( callExpr, 0 );
291        assert( arg );
292        result = arg->result;
293}
294
295// --- CompoundLiteralExpr
296
297CompoundLiteralExpr::CompoundLiteralExpr( const CodeLocation & loc, const Type * t, const Init * i )
298: Expr( loc ), init( i ) {
299        assert( t && i );
300        result.set_and_mutate( t )->set_lvalue( true );
301}
302
303// --- TupleExpr
304
305TupleExpr::TupleExpr( const CodeLocation & loc, std::vector<ptr<Expr>> && xs )
306: Expr( loc, Tuples::makeTupleType( xs ) ), exprs( xs ) {}
307
308// --- TupleIndexExpr
309
310TupleIndexExpr::TupleIndexExpr( const CodeLocation & loc, const Expr * t, unsigned i )
311: Expr( loc ), tuple( t ), index( i ) {
312        const TupleType * type = strict_dynamic_cast< const TupleType * >( tuple->result.get() );
313        assertf( type->size() > index, "TupleIndexExpr index out of bounds: tuple size %d, requested "
314                "index %d in expr %s", type->size(), index, toString( tuple ).c_str() );
315        // like MemberExpr, TupleIndexExpr is always an lvalue
316        result.set_and_mutate( type->types[ index ] )->set_lvalue( true );
317}
318
319// --- TupleAssignExpr
320
321TupleAssignExpr::TupleAssignExpr(
322        const CodeLocation & loc, std::vector<ptr<Expr>> && assigns,
323        std::vector<ptr<ObjectDecl>> && tempDecls )
324: Expr( loc, Tuples::makeTupleType( assigns ) ), stmtExpr() {
325        // convert internally into a StmtExpr which contains the declarations and produces the tuple of
326        // the assignments
327        std::list<ptr<Stmt>> stmts;
328        for ( const ObjectDecl * obj : tempDecls ) {
329                stmts.emplace_back( new DeclStmt{ loc, obj } );
330        }
331        TupleExpr * tupleExpr = new TupleExpr{ loc, std::move(assigns) };
332        assert( tupleExpr->result );
333        stmts.emplace_back( new ExprStmt{ loc, tupleExpr } );
334        stmtExpr = new StmtExpr{ loc, new CompoundStmt{ loc, std::move(stmts) } };
335}
336
337// --- StmtExpr
338
339StmtExpr::StmtExpr( const CodeLocation & loc, const CompoundStmt * ss )
340: Expr( loc ), stmts( ss ), returnDecls(), dtors() { computeResult(); }
341
342void StmtExpr::computeResult() {
343        assert( stmts );
344        const std::list<ptr<Stmt>> & body = stmts->kids;
345        if ( ! returnDecls.empty() ) {
346                // prioritize return decl for result type, since if a return decl exists, then the StmtExpr
347                // is currently in an intermediate state where the body will always give a void result type
348                result = returnDecls.front()->get_type();
349        } else if ( ! body.empty() ) {
350                if ( const ExprStmt * exprStmt = body.back().as< ExprStmt >() ) {
351                        result = exprStmt->expr->result;
352                }
353        }
354        // ensure a result type exists
355        if ( ! result ) { result = new VoidType{}; }
356}
357
358// --- UniqueExpr
359
360unsigned long long UniqueExpr::nextId = 0;
361
362UniqueExpr::UniqueExpr( const CodeLocation & loc, const Expr * e, unsigned long long i )
363: Expr( loc, e->result ), id( i ) {
364        assert( expr );
365        if ( id == -1ull ) {
366                assert( nextId != -1ull );
367                id = nextId++;
368        }
369}
370
371}
372
373// Local Variables: //
374// tab-width: 4 //
375// mode: c++ //
376// compile-command: "make install" //
377// End: //
Note: See TracBrowser for help on using the repository browser.