source: src/AST/Expr.cpp@ dd6d7c6

ADT arm-eh ast-experimental cleanup-dtors enum forall-pointer-decay jacob/cs343-translation jenkins-sandbox new-ast new-ast-unique-expr pthread-emulation qualifiedEnum
Last change on this file since dd6d7c6 was 20de6fb, checked in by Michael Brooks <mlbrooks@…>, 6 years ago

finished draft past of converting expressions

  • Property mode set to 100644
File size: 12.2 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
337TupleAssignExpr::TupleAssignExpr(
338 const CodeLocation & loc, const Type * result, const StmtExpr * s )
339: Expr( loc, result ), stmtExpr() {
340 stmtExpr = s;
341}
342
343// --- StmtExpr
344
345StmtExpr::StmtExpr( const CodeLocation & loc, const CompoundStmt * ss )
346: Expr( loc ), stmts( ss ), returnDecls(), dtors() { computeResult(); }
347
348void StmtExpr::computeResult() {
349 assert( stmts );
350 const std::list<ptr<Stmt>> & body = stmts->kids;
351 if ( ! returnDecls.empty() ) {
352 // prioritize return decl for result type, since if a return decl exists, then the StmtExpr
353 // is currently in an intermediate state where the body will always give a void result type
354 result = returnDecls.front()->get_type();
355 } else if ( ! body.empty() ) {
356 if ( const ExprStmt * exprStmt = body.back().as< ExprStmt >() ) {
357 result = exprStmt->expr->result;
358 }
359 }
360 // ensure a result type exists
361 if ( ! result ) { result = new VoidType{}; }
362}
363
364// --- UniqueExpr
365
366unsigned long long UniqueExpr::nextId = 0;
367
368UniqueExpr::UniqueExpr( const CodeLocation & loc, const Expr * e, unsigned long long i )
369: Expr( loc, e->result ), id( i ) {
370 assert( expr );
371 if ( id == -1ull ) {
372 assert( nextId != -1ull );
373 id = nextId++;
374 }
375}
376
377}
378
379// Local Variables: //
380// tab-width: 4 //
381// mode: c++ //
382// compile-command: "make install" //
383// End: //
Note: See TracBrowser for help on using the repository browser.