Skip to content

Commit 165ffc3

Browse files
committed
[Heavy] Improve syntax closures and lookup
1 parent b979ab8 commit 165ffc3

File tree

12 files changed

+563
-341
lines changed

12 files changed

+563
-341
lines changed

heavy/include/heavy/Context.h

Lines changed: 20 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,7 @@ class Context : public ContinuationStack<Context>,
108108
// - an improper list ending with an Environment
109109
// - Calls to procedures or eval will set the EnvStack
110110
// and swap it back upon completion (via RAII)
111+
// - TODO EnvStack et al. could probably be moved to OpGen.
111112
Value EnvStack;
112113

113114
public: // Provide access in lib/Mlir bindings.
@@ -173,7 +174,7 @@ class Context : public ContinuationStack<Context>,
173174
return EnvStack;
174175
}
175176
void setEnvironment(Value E) {
176-
assert((isa<Environment, Pair, Empty>(E)) &&
177+
assert((isa<Environment, Pair, EnvFrame, Empty>(E)) &&
177178
"invalid environment specifier");
178179
EnvStack = E;
179180
}
@@ -213,25 +214,26 @@ class Context : public ContinuationStack<Context>,
213214
// Lookup
214215
// - Takes a Symbol
215216
// - Returns a matching Binder or nullptr
216-
EnvEntry Lookup(Symbol* Name, Value Stack);
217-
EnvEntry Lookup(Symbol* Name) {
218-
return Lookup(Name, EnvStack);
217+
EnvEntry Lookup(Value Id) {
218+
return Lookup(Id, EnvStack);
219219
}
220+
EnvEntry Lookup(Value Id, Value Stack);
220221

221222
// PushEnvFrame - Creates and pushes an EnvFrame to the
222223
// current environment (EnvStack)
223-
EnvFrame* PushEnvFrame(llvm::ArrayRef<Symbol*> Names);
224+
EnvFrame* PushEnvFrame(llvm::ArrayRef<Value> Names);
224225
void PopEnvFrame();
225226
void PushLocalBinding(Binding* B);
226227

227-
// PushLambdaFormals - Checks formals, creates an EnvFrame,
228-
// and pushes it onto the EnvStack
229-
// Returns the pushed EnvFrame or nullptr
230-
EnvFrame* PushLambdaFormals(Value Formals, bool& HasRestParam);
228+
// PushLambdaFormals - Check formals, create an EnvFrame,
229+
// and push it onto the EnvStack
230+
// Return the pushed EnvFrame or nullptr.
231+
EnvFrame* PushLambdaFormals(Value Formals, bool& HasRestParam,
232+
SyntaxClosure* SC);
231233
private:
232234
bool CheckLambdaFormals(Value Formals,
233-
llvm::SmallVectorImpl<Symbol*>& Names,
234-
bool& HasRestParam);
235+
llvm::SmallVectorImpl<Value>& Names,
236+
bool& HasRestParam, SyntaxClosure* SC);
235237
public:
236238

237239
void EmitStackSpaceError();
@@ -340,7 +342,8 @@ class Context : public ContinuationStack<Context>,
340342
Vector* CreateVector(ArrayRef<Value> Xs);
341343
Vector* CreateVector(unsigned N);
342344
ByteVector* CreateByteVector(llvm::ArrayRef<Value> Xs);
343-
EnvFrame* CreateEnvFrame(llvm::ArrayRef<Symbol*> Names);
345+
EnvFrame* CreateEnvFrame(llvm::ArrayRef<Value> Names);
346+
EnvFrame* CreateEnvFrame(unsigned N);
344347

345348
template <typename T>
346349
Any* CreateAny(T Obj) {
@@ -387,8 +390,9 @@ class Context : public ContinuationStack<Context>,
387390
return new (*this) BuiltinSyntax(Fn);
388391
}
389392

390-
SyntaxClosure* CreateSyntaxClosure(SourceLocation Loc, Value Node) {
391-
return new (*this) SyntaxClosure(Loc, EnvStack, Node);
393+
SyntaxClosure* CreateSyntaxClosure(SourceLocation Loc, Value Node,
394+
Value Env) {
395+
return new (*this) SyntaxClosure(Loc, Env, Node);
392396
}
393397

394398
SourceValue* CreateSourceValue(SourceLocation Loc) {
@@ -415,8 +419,8 @@ class Context : public ContinuationStack<Context>,
415419
return new (*this) Exception(V);
416420
}
417421

418-
Binding* CreateBinding(Symbol* S, Value V) {
419-
return new (*this) Binding(S, V);
422+
Binding* CreateBinding(Value Id, Value V) {
423+
return new (*this) Binding(Id, V);
420424
}
421425

422426
// CreateImportSet - Call CC with created ImportSet.

heavy/include/heavy/OpGen.h

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ namespace mlir {
3434
}
3535

3636
namespace heavy {
37+
using IdSet = std::set<std::pair<uintptr_t, uintptr_t>>;
3738
using NameSet = llvm::SmallPtrSetImpl<String*>;
3839
class PatternTemplate;
3940
class TemplateGen;
@@ -118,6 +119,10 @@ class OpGen : public ValueVisitor<OpGen, mlir::Value> {
118119
// be inserted if this is set.
119120
Binding* LibraryEnvProc = nullptr;
120121

122+
// The current syntax closure will affect how we perform lookup
123+
// in LookupEnv.
124+
SyntaxClosure* CurSyntaxClosure = nullptr;
125+
121126
// Err - The stored error to indicate that the compiler is in an error state.
122127
// (Use CheckError())
123128
Value Err = nullptr;
@@ -146,7 +151,7 @@ class OpGen : public ValueVisitor<OpGen, mlir::Value> {
146151
};
147152

148153
void InsertTopLevelCommandOp(SourceLocation Loc);
149-
bool WalkDefineInits(Value Env, NameSet& LocalNames);
154+
bool WalkDefineInits(Value Env, IdSet& LocalNames);
150155
bool FinishLocalDefines();
151156

152157
public:
@@ -266,7 +271,8 @@ class OpGen : public ValueVisitor<OpGen, mlir::Value> {
266271

267272
mlir::Value createCall(heavy::SourceLocation Loc, mlir::Value Fn,
268273
llvm::MutableArrayRef<mlir::Value> Args);
269-
mlir::Value createOpGen(SourceLocation Loc, mlir::Value Input);
274+
mlir::Value createOpGen(SourceLocation Loc, mlir::Value Input,
275+
mlir::Value Env);
270276
mlir::Value createBody(SourceLocation Loc, Value Body);
271277
mlir::Value createSequence(SourceLocation Loc, Value Body);
272278
mlir::Value createSyntaxSpec(Pair* SyntaxSpec, Value OrigCall);
@@ -377,10 +383,13 @@ class OpGen : public ValueVisitor<OpGen, mlir::Value> {
377383
}
378384

379385
mlir::Operation* LookupSymbol(llvm::StringRef MangledName);
386+
387+
heavy::EnvEntry LookupEnv(heavy::Value Id);
380388
private:
381-
mlir::Value MaybeCallSyntax(Pair* P, bool& DidCallSyntax);
389+
mlir::Value MaybeCallSyntax(Pair* P, bool& DidCallSyntax,
390+
heavy::EnvEntry& FnEnvEntry);
382391
mlir::Value MaybeCallSyntax(Value Operator, Pair* P, bool& DidCallSyntax);
383-
mlir::Value HandleCall(Pair* P);
392+
mlir::Value HandleCall(Pair* P, heavy::EnvEntry FnEnvEntry);
384393
};
385394

386395
}

heavy/include/heavy/Ops.td

Lines changed: 50 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -177,7 +177,7 @@ def heavy_OpGenOp : HeavyOp<"opgen", [Terminator]> {
177177
This operation is used for syntax code generation.
178178
}];
179179

180-
let arguments = (ins HeavyValue:$input);
180+
let arguments = (ins HeavyValue:$input, HeavyValue:$env);
181181
let results = (outs);
182182
}
183183

@@ -444,7 +444,7 @@ def heavy_ResolveOp : HeavyOp<"resolve", [Terminator]> {
444444
def heavy_PatternOp : HeavyOp<"pattern", [HasParent<"SyntaxOp">]> {
445445
let description = [{
446446
PatternOp represents the pattern in a pattern/template
447-
pair as part of the syntax-rules transform specifier. The
447+
pair as part of the syntax-rules transform specifier. The
448448
region should contain matching operations on the input syntax,
449449
as well as ConsOps for the template, terminating with an OpGenOp
450450
on the constructed AST.
@@ -471,16 +471,38 @@ def heavy_PushContOp : HeavyOp<"push_cont", []> {
471471
def heavy_RenameOp : HeavyOp<"rename", [HasParent<"PatternOp">]> {
472472
let summary = "rename";
473473
let description = [{
474-
"Rename" a local variable by storing an opaque representation
475-
of its mlir::Value. The lifetime of this value expires with the
476-
MLIR Context so compilation of these operations should only be JIT.
477-
(Local syntax can never be exported)
474+
Capture a value and "rename" it using an identifier to use in the
475+
scope of a syntax object. These lookups can be shadowed by the
476+
environment created during template expansion (as I understand it.)
477+
478+
The $capture mlir::Value which may belong to a parent scope is
479+
used to generate a localized value in the context of the template
480+
expansion.
478481
}];
479482

480-
let arguments = (ins UI64Attr:$opaqueValue);
483+
let arguments = (ins StrAttr:$id, HeavyValue:$capture);
481484
let results = (outs HeavyValue:$result);
482-
let builders = [
483-
OpBuilder<(ins "::mlir::Value":$opaqueValue)>
485+
let builders = [
486+
OpBuilder<(ins "::llvm::StringRef":$id, "::mlir::Value":$capture)>
487+
];
488+
}
489+
490+
def heavy_RenameGlobalOp : HeavyOp<"rename_global", [HasParent<"PatternOp">]> {
491+
let summary = "rename_global";
492+
let description = [{
493+
Similar to RenameOp, this RenameGlobalOp represents the possibility of
494+
expanding the use of a global by generating a LoadGlobalOp in the context
495+
of the template expansion.
496+
497+
Because globals can be defined lazily within the module, it is possible
498+
that this operation could be generated when no global of the corresponding
499+
name was defined. In this case the RenameOp can be removed.
500+
}];
501+
502+
let arguments = (ins StrAttr:$id, StrAttr:$sym);
503+
let results = (outs HeavyValue:$result);
504+
let builders = [
505+
OpBuilder<(ins "::llvm::StringRef":$id, "::llvm::StringRef":$sym)>
484506
];
485507
}
486508

@@ -531,15 +553,15 @@ def heavy_SpliceOp : HeavyOp<"splice"> {
531553
def heavy_SyntaxClosureOp : HeavyOp<"syntax_closure"> {
532554
let summary = "syntax_closure";
533555
let description = [{
534-
SyntaxClosureOp captures a syntax node with the current
556+
SyntaxClosureOp captures a syntax node with the given
535557
environment. This supports generating code during hygienic
536558
macro expansion.
537559
}];
538560

539-
let arguments = (ins HeavyValue:$input);
561+
let arguments = (ins HeavyValue:$input, HeavyValue:$env);
540562
let results = (outs HeavyValue:$result);
541563
let builders = [
542-
OpBuilder<(ins "::mlir::Value":$input)>
564+
OpBuilder<(ins "::mlir::Value":$input, "::mlir::Value":$env)>
543565
];
544566
}
545567

@@ -589,6 +611,22 @@ def heavy_VectorOp : HeavyOp<"vector"> {
589611
];
590612
}
591613

614+
def heavy_EnvFrameOp : HeavyOp<"env_frame"> {
615+
let description = [{
616+
EnvFrameOp creates a vector-like object of bindings.
617+
618+
Since it serves to define lexical scopes in the
619+
environment, it exists apart from VectorOp so that
620+
the bindings do not get unwrapped during evaluation.
621+
}];
622+
623+
let arguments = (ins Variadic<HeavyValue>:$args);
624+
let results = (outs HeavyValue: $result);
625+
let builders = [
626+
OpBuilder<(ins "::llvm::ArrayRef<::mlir::Value>":$args)>
627+
];
628+
}
629+
592630
def heavy_UndefinedOp : HeavyOp<"undefined", [Pure]> {
593631
let summary = "undefined";
594632
let description = [{

0 commit comments

Comments
 (0)