Changes in src/AST/Expr.cpp [ae265b55:c36298d]
- File:
-
- 1 edited
-
src/AST/Expr.cpp (modified) (6 diffs)
Legend:
- Unmodified
- Added
- Removed
-
src/AST/Expr.cpp
rae265b55 rc36298d 20 20 #include <vector> 21 21 22 #include "Copy.hpp" // for shallowCopy23 #include "Eval.hpp" // for call24 22 #include "GenericSubstitution.hpp" 25 23 #include "Stmt.hpp" … … 53 51 assert( arg ); 54 52 55 UntypedExpr * ret = call( loc, "*?", arg ); 53 UntypedExpr * ret = new UntypedExpr{ 54 loc, new NameExpr{loc, "*?"}, std::vector<ptr<Expr>>{ ptr<Expr>{ arg } } 55 }; 56 56 if ( const Type * ty = arg->result ) { 57 57 const Type * base = InitTweak::getPointerBase( ty ); … … 74 74 assert( lhs && rhs ); 75 75 76 UntypedExpr * ret = call( loc, "?=?", lhs, rhs ); 76 UntypedExpr * ret = new UntypedExpr{ 77 loc, new NameExpr{loc, "?=?"}, std::vector<ptr<Expr>>{ ptr<Expr>{ lhs }, ptr<Expr>{ rhs } } 78 }; 77 79 if ( lhs->result && rhs->result ) { 78 80 // if both expressions are typed, assumes that this assignment is a C bitwise assignment, … … 158 160 assert( aggregate->result ); 159 161 160 // Deep copy on result type avoids mutation on transitively multiply referenced object. 161 // 162 // Example, adapted from parts of builtins and bootloader: 163 // 164 // forall(dtype T) 165 // struct __Destructor { 166 // T * object; 167 // void (*dtor)(T *); 168 // }; 169 // 170 // forall(dtype S) 171 // void foo(__Destructor(S) &d) { 172 // if (d.dtor) { // here 173 // } 174 // } 175 // 176 // Let e be the "d.dtor" guard espression, which is MemberExpr after resolve. Let d be the 177 // declaration of member __Destructor.dtor (an ObjectDecl), as accessed via the top-level 178 // declaration of __Destructor. Consider the types e.result and d.type. In the old AST, one 179 // is a clone of the other. Ordinary new-AST use would set them up as a multiply-referenced 180 // object. 181 // 182 // e.result: PointerType 183 // .base: FunctionType 184 // .params.front(): ObjectDecl, the anonymous parameter of type T* 185 // .type: PointerType 186 // .base: TypeInstType 187 // let x = that 188 // let y = similar, except start from d.type 189 // 190 // Consider two code lines down, genericSubstitution(...).apply(result). 191 // 192 // Applying this chosen-candidate's type substitution means modifying x, substituting 193 // S for T. This mutation should affect x and not y. 194 195 result = deepCopy(mem->get_type()); 196 162 // take ownership of member type 163 result = mem->get_type(); 197 164 // substitute aggregate generic parameters into member type 198 165 genericSubstitution( aggregate->result ).apply( result ); … … 201 168 } 202 169 203 MemberExpr::MemberExpr( const CodeLocation & loc, const DeclWithType * mem, const Expr * agg,204 MemberExpr::NoOpConstruction overloadSelector )205 : Expr( loc ), member( mem ), aggregate( agg ) {206 assert( member );207 assert( aggregate );208 assert( aggregate->result );209 (void) overloadSelector;210 }211 212 170 // --- VariableExpr 213 171 … … 219 177 assert( var ); 220 178 assert( var->get_type() ); 221 auto r = shallowCopy( var->get_type() ); 222 r->qualifiers |= CV::Lvalue; 223 result = r; 179 result = var->get_type(); 180 add_qualifiers( result, CV::Lvalue ); 224 181 } 225 182
Note:
See TracChangeset
for help on using the changeset viewer.