|
30 | 30 | #include <memory> |
31 | 31 |
|
32 | 32 | using namespace heavy; |
| 33 | + |
| 34 | +struct OpGen::SyntaxClosureScope { |
| 35 | + OpGen& O; |
| 36 | + SyntaxClosure* PrevSC; |
| 37 | + |
| 38 | + SyntaxClosureScope(OpGen& O, SyntaxClosure* SC) |
| 39 | + : O(O), |
| 40 | + PrevSC(O.CurSyntaxClosure) |
| 41 | + { |
| 42 | + O.CurSyntaxClosure = SC; |
| 43 | + } |
| 44 | + |
| 45 | + ~SyntaxClosureScope() { |
| 46 | + O.CurSyntaxClosure = PrevSC; |
| 47 | + } |
| 48 | +}; |
| 49 | + |
33 | 50 | // LambdaScope - RAII object that pushes an operation that is |
34 | 51 | // FunctionLike to the scope stack along with a |
35 | 52 | // BindingScope where we can insert stack local |
@@ -884,6 +901,11 @@ bool OpGen::WalkDefineInits(Value Env, IdSet& LocalIds) { |
884 | 901 | // Insert the binding initializer. |
885 | 902 | auto Undef = cast<heavy::Undefined>(B->getValue()); |
886 | 903 | Value DefineArgs = Undef.getTracer(); |
| 904 | + // SC may be nullptr. |
| 905 | + auto* SC = dyn_cast<SyntaxClosure>(Undef.getTracer()); |
| 906 | + SyntaxClosureScope SCScope(*this, SC); |
| 907 | + if (SC) |
| 908 | + DefineArgs = SC->Node; |
887 | 909 | mlir::Value Init = VisitDefineArgs(DefineArgs); |
888 | 910 | mlir::Value BVal = LocalizeValue(BindingTable.lookup(B), B); |
889 | 911 | SourceLocation Loc = DefineArgs.getSourceLocation(); |
@@ -918,14 +940,17 @@ mlir::Value OpGen::createBinding(Binding *B, mlir::Value Init) { |
918 | 940 | return BVal; |
919 | 941 | } |
920 | 942 |
|
921 | | -mlir::Value OpGen::createDefine(Value Id, Value DefineArgs, |
922 | | - Value OrigCall) { |
| 943 | +mlir::Value OpGen::createDefine(Value Id, Value DefineArgs, Value OrigCall) { |
923 | 944 | if (isTopLevel()) return createTopLevelDefine(Id, DefineArgs, OrigCall); |
924 | 945 | if (!IsLocalDefineAllowed) return SetError("unexpected define", OrigCall); |
925 | | - // Create the binding with a lazy init. |
926 | | - // (Include everything after the define |
927 | | - // keyword to visit it later because it could |
928 | | - // be a terse lambda syntax.) |
| 946 | + // Create the binding with an undefined object that secretly holds |
| 947 | + // its syntax in the current environment. |
| 948 | + Value Env; |
| 949 | + |
| 950 | + if (CurSyntaxClosure) |
| 951 | + DefineArgs = Context.CreateSyntaxClosure(DefineArgs.getSourceLocation(), |
| 952 | + DefineArgs, |
| 953 | + CurSyntaxClosure->Env); |
929 | 954 | Binding* B = Context.CreateBinding(Id, Undefined(DefineArgs)); |
930 | 955 | // Push to the local environment. |
931 | 956 | Context.PushLocalBinding(B); |
@@ -1145,11 +1170,8 @@ mlir::Value OpGen::VisitExternName(ExternName* EN) { |
1145 | 1170 | } |
1146 | 1171 |
|
1147 | 1172 | mlir::Value OpGen::VisitSyntaxClosure(SyntaxClosure* SC) { |
1148 | | - SyntaxClosure* PrevSC = CurSyntaxClosure; |
1149 | | - CurSyntaxClosure = SC; |
| 1173 | + SyntaxClosureScope SCScope(*this, SC); |
1150 | 1174 | mlir::Value Result = Visit(SC->Node); |
1151 | | - CurSyntaxClosure = PrevSC; |
1152 | | - |
1153 | 1175 | return Result; |
1154 | 1176 | } |
1155 | 1177 |
|
|
0 commit comments