Skip to content

Commit ced3586

Browse files
committed
[Heavy] Add syntax-source-loc for propagating source locations of syntax-rules pattern variables
1 parent f4d1980 commit ced3586

File tree

15 files changed

+160
-44
lines changed

15 files changed

+160
-44
lines changed

heavy/include/heavy/Builtins.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@
2929
#define HEAVY_BASE_VAR(NAME) ::heavy::builtins_var::NAME
3030
#define HEAVY_BASE_VAR_STR(NAME) HEAVY_BASE_VAR_STR__##NAME
3131
#define HEAVY_BASE_VAR_STR__error HEAVY_BASE_LIB_STR "V5Serror"
32+
#define HEAVY_BASE_VAR_STR__source_loc \
33+
HEAVY_BASE_LIB_STR "V6Ssourcemi3Sloc"
3234

3335
// Forward declare vars that are used in the C++ codebase.
3436
namespace heavy::builtins_var {

heavy/include/heavy/Context.h

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -344,14 +344,17 @@ class Context : public ContinuationStack<Context>,
344344
Pair* CreatePair(Value V1) {
345345
return new (*this) Pair(V1, CreateEmpty());
346346
}
347-
Pair* CreatePair(Value V1, Value V2, Pair* SourcePair) {
348-
heavy::SourceLocation Loc = SourcePair->getSourceLocation();
347+
Pair* CreatePair(Value V1, Value V2, heavy::SourceLocation MaybeLoc) {
349348
// Try to preserve source locations.
350-
if (Loc.isValid())
351-
return CreatePairWithSource(V1, V2, Loc);
349+
if (MaybeLoc.isValid())
350+
return CreatePairWithSource(V1, V2, MaybeLoc);
352351
else
353352
return CreatePair(V1, V2);
354353
}
354+
Pair* CreatePair(Value V1, Value V2, Value MaybeSource) {
355+
heavy::SourceLocation Loc = MaybeSource.getSourceLocation();
356+
return CreatePair(V1, V2, Loc);
357+
}
355358
PairWithSource* CreatePairWithSource(Value V1, Value V2,
356359
SourceLocation Loc) {
357360
return new (*this) PairWithSource(V1, V2, Loc);
@@ -419,6 +422,7 @@ class Context : public ContinuationStack<Context>,
419422
Value CreateSyntaxClosure(SourceLocation Loc, Value Node, Value Env);
420423
SyntaxClosure* CreateSyntaxClosure(SourceLocation Loc, Symbol* S,
421424
Value Env);
425+
Value UnwrapSyntaxClosure(Value V);
422426

423427
SourceValue* CreateSourceValue(SourceLocation Loc) {
424428
return new (*this) SourceValue(Loc);

heavy/include/heavy/ContinuationStack.h

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -266,11 +266,8 @@ class ContinuationStack {
266266
break;
267267
}
268268
default:
269-
String* Msg = Context.CreateString(
270-
"invalid operator for call expression: ",
271-
getKindName(Callee.getKind())
272-
);
273-
Context.RaiseError(Msg, Callee);
269+
Context.RaiseError(
270+
"invalid operator for call expression: {}", Callee);
274271
}
275272

276273
// This means a C++ function was not written correctly.

heavy/include/heavy/Ops.td

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -580,17 +580,18 @@ def heavy_RenameEnvOp : HeavyOp<"rename_env"> {
580580
def heavy_SourceLocOp : HeavyOp<"source-loc"> {
581581
let summary = "source-loc";
582582
let description = [{
583-
Encode a source location that is specific
584-
to an instance of a SourceManager. Serialization
585-
should not save this encoding.
586-
This is used to allow passing source locations of
587-
syntax as values.
583+
Get the source location from a HeavyValue object.
584+
This is primarily used to propagate source locations
585+
of the inputs to pattern variables.
588586
}];
589587

590-
let arguments = (ins);
588+
let arguments = (ins HeavyValue:$arg);
591589
let results = (outs HeavyValue:$result);
592-
let builders = [OpBuilder<(ins)>];
590+
let builders = [
591+
OpBuilder<(ins "::mlir::Value":$arg)>
592+
];
593593
}
594+
594595
def heavy_SetOp : HeavyOp<"set"> {
595596
let summary = "set";
596597
let description = [{
@@ -629,10 +630,12 @@ def heavy_SyntaxClosureOp : HeavyOp<"syntax_closure"> {
629630
macro expansion.
630631
}];
631632

632-
let arguments = (ins HeavyValue:$input, HeavyValue:$env);
633+
let arguments = (ins HeavyValue:$sourceVal, HeavyValue:$input,
634+
HeavyValue:$env);
633635
let results = (outs HeavyValue:$result);
634636
let builders = [
635-
OpBuilder<(ins "::mlir::Value":$input, "::mlir::Value":$env)>
637+
OpBuilder<(ins "::mlir::Value":$sourceVal, "::mlir::Value":$input,
638+
"::mlir::Value":$env)>
636639
];
637640
}
638641

heavy/include/heavy/base.sld

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@
4747
car
4848
cdr
4949
cons
50+
source-cons
5051
dump
5152
dynamic-wind
5253
eq?

heavy/include/heavy/base/r7rs-syntax.sld

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,8 +48,6 @@
4848
((do "step" x y)
4949
y)))
5050

51-
; FIXME cond should be in the environment within syntax body.
52-
; (this applies to all define-syntax)
5351
(define-syntax cond
5452
(syntax-rules (else =>)
5553
((cond (else result1 result2 ...))

heavy/lib/Builtins.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ heavy::ExternFunction is_zero;
5858
heavy::ExternFunction list;
5959
heavy::ExternFunction length;
6060
heavy::ExternFunction cons;
61+
heavy::ExternFunction source_cons;
6162
heavy::ExternFunction car;
6263
heavy::ExternFunction cdr;
6364
heavy::ExternFunction append;
@@ -795,6 +796,15 @@ void cons(Context& C, ValueRefs Args) {
795796
C.Cont(C.CreatePair(Args[0], Args[1]));
796797
}
797798

799+
// (source-cons car cdr src)
800+
// Where `src` can be any value that might
801+
// have a valid source location.
802+
void source_cons(Context& C, ValueRefs Args) {
803+
if (Args.size() != 3)
804+
return C.RaiseError("invalid arity");
805+
C.Cont(C.CreatePair(Args[0], Args[1], Args[2]));
806+
}
807+
798808
void car(Context& C, ValueRefs Args) {
799809
if (Args.size() != 1)
800810
return C.RaiseError("invalid arity");
@@ -1263,6 +1273,7 @@ void HEAVY_BASE_INIT(heavy::Context& Context) {
12631273
HEAVY_BASE_VAR(list) = heavy::builtins::list;
12641274
HEAVY_BASE_VAR(length) = heavy::builtins::length;
12651275
HEAVY_BASE_VAR(cons) = heavy::builtins::cons;
1276+
HEAVY_BASE_VAR(source_cons) = heavy::builtins::source_cons;
12661277
HEAVY_BASE_VAR(car) = heavy::builtins::car;
12671278
HEAVY_BASE_VAR(cdr) = heavy::builtins::cdr;
12681279
HEAVY_BASE_VAR(append) = heavy::builtins::append;
@@ -1359,6 +1370,7 @@ void HEAVY_BASE_LOAD_MODULE(heavy::Context& Context) {
13591370
{"list", HEAVY_BASE_VAR(list)},
13601371
{"length", HEAVY_BASE_VAR(length)},
13611372
{"cons", HEAVY_BASE_VAR(cons)},
1373+
{"source-cons", HEAVY_BASE_VAR(source_cons)},
13621374
{"car", HEAVY_BASE_VAR(car)},
13631375
{"cdr", HEAVY_BASE_VAR(cdr)},
13641376
{"append", HEAVY_BASE_VAR(append)},

heavy/lib/Context.cpp

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -368,7 +368,7 @@ class Writer : public ValueVisitor<Writer> {
368368

369369
void VisitSourceValue(SourceValue* SV) {
370370
heavy::SourceLocation Loc = SV->getSourceLocation();
371-
OS << "\n#<SourceValue {"
371+
OS << "#<SourceValue {"
372372
<< Loc.getEncoding()
373373
<< "}>";
374374
}
@@ -1310,10 +1310,8 @@ void Context::Raise(Value Obj) {
13101310

13111311
void Context::RaiseError(String* Msg, llvm::ArrayRef<Value> IrrArgs) {
13121312
Value IrrList = Empty();
1313-
for (Value Irr : llvm::reverse(IrrArgs)) {
1314-
setLoc(Irr.getSourceLocation());
1313+
for (Value Irr : llvm::reverse(IrrArgs))
13151314
IrrList = CreatePair(Irr, IrrList);
1316-
}
13171315
Value Error = CreateError(this->Loc, Msg, IrrList);
13181316
Raise(Error);
13191317
}
@@ -1672,14 +1670,30 @@ EnvFrame* Context::CreateEnvFrame(llvm::ArrayRef<Value> Ids, bool IsLambdaScope)
16721670
// Create syntax with Symbols rebuilt as SyntaxClosures.
16731671
Value Context::CreateSyntaxClosure(SourceLocation Loc, Value Node,
16741672
Value Env) {
1675-
return RebuildLiteral(Node, Env);
1673+
// Substitute all nested symbols with a SyntaxClosure;
1674+
Value Rebuilt = RebuildLiteral(Node, Env);
1675+
// Prevent directly nesting syntax closures.
1676+
if (isa<SyntaxClosure>(Rebuilt))
1677+
return Rebuilt;
1678+
1679+
// Wrap in a SyntaxClosure to keep the Loc available.
1680+
return new (*this) SyntaxClosure(Loc, Env, Rebuilt);
16761681
}
16771682

16781683
SyntaxClosure* Context::CreateSyntaxClosure(SourceLocation Loc, Symbol* S,
16791684
Value Env) {
16801685
return new (*this) SyntaxClosure(Loc, Env, Value(S));
16811686
}
16821687

1688+
// Unwrap any SyntaxClosure that is not an Identifier.
1689+
// (We only keep these around for the SourceLocation.)
1690+
Value Context::UnwrapSyntaxClosure(Value V) {
1691+
if (auto* SC = dyn_cast<SyntaxClosure>(V);
1692+
SC && !isa<Symbol>(SC->Node))
1693+
return SC->Node;
1694+
return V;
1695+
}
1696+
16831697
EnvEntry Context::GetSyntax(EnvEntry Entry) {
16841698
heavy::Value V = Entry.Value;
16851699
if (!V)

heavy/lib/Dialect.cpp

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -240,9 +240,10 @@ void SpliceOp::build(mlir::OpBuilder& B, mlir::OperationState& OpState,
240240
}
241241

242242
void SyntaxClosureOp::build(mlir::OpBuilder& B, mlir::OperationState& OpState,
243-
mlir::Value Input, mlir::Value Env) {
243+
mlir::Value SourceVal, mlir::Value Input,
244+
mlir::Value Env) {
244245
mlir::Type HeavyValueT = B.getType<HeavyValueTy>();
245-
SyntaxClosureOp::build(B, OpState, HeavyValueT, Input, Env);
246+
SyntaxClosureOp::build(B, OpState, HeavyValueT, SourceVal, Input, Env);
246247
}
247248

248249
void SyntaxOp::build(mlir::OpBuilder& B, mlir::OperationState& OpState,
@@ -273,9 +274,10 @@ void UndefinedOp::build(mlir::OpBuilder& B, mlir::OperationState& OpState) {
273274
UndefinedOp::build(B, OpState, B.getType<HeavyValueTy>());
274275
}
275276

276-
void SourceLocOp::build(mlir::OpBuilder& B, mlir::OperationState& OpState) {
277+
void SourceLocOp::build(mlir::OpBuilder& B, mlir::OperationState& OpState,
278+
mlir::Value Arg) {
277279
mlir::Type HeavyValueT = B.getType<HeavyValueTy>();
278-
SourceLocOp::build(B, OpState, HeavyValueT);
280+
SourceLocOp::build(B, OpState, HeavyValueT, Arg);
279281
}
280282

281283
using namespace mlir;

heavy/lib/OpEval.cpp

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,13 @@ class OpEvalImpl {
8585
return V;
8686
}
8787

88+
// Get a value for pattern matching
89+
// that can ignore syntax closures
90+
// (which does not include symbols.)
91+
heavy::Value getPatternValue(mlir::Value M) {
92+
return Context.UnwrapSyntaxClosure(getValue(M));
93+
}
94+
8895
static heavy::SourceLocation getSourceLocation(mlir::Location Loc) {
8996
return heavy::SourceLocation(mlir::OpaqueLoc
9097
::getUnderlyingLocationOrNull<heavy::SourceLocationEncoding*>(Loc));
@@ -674,7 +681,7 @@ class OpEvalImpl {
674681

675682
BlockItrTy Visit(MatchOp Op) {
676683
heavy::Value P = Op.getVal().getValue(Context);
677-
heavy::Value E = getValue(Op.getInput());
684+
heavy::Value E = getPatternValue(Op.getInput());
678685
heavy::EnvEntry Entry;
679686
if (isIdentifier(E) && isIdentifier(P)) {
680687
// If the symbol is in the environment we can skip
@@ -699,7 +706,7 @@ class OpEvalImpl {
699706
}
700707

701708
BlockItrTy Visit(MatchPairOp Op) {
702-
heavy::Value E = getValue(Op.getInput());
709+
heavy::Value E = getPatternValue(Op.getInput());
703710
if (auto* Pair = dyn_cast<heavy::Pair>(E)) {
704711
setValue(Op.getCar(), Pair->Car);
705712
setValue(Op.getCdr(), Pair->Cdr);
@@ -712,7 +719,7 @@ class OpEvalImpl {
712719
BlockItrTy Visit(MatchTailOp Op) {
713720
// Here we include the last cdr in the length
714721
// of a list proper or improper.
715-
heavy::Value E = getValue(Op.getInput());
722+
heavy::Value E = getPatternValue(Op.getInput());
716723
uint32_t TargetLen = Op.getLength();
717724
assert(TargetLen >= 1 && "expecting positive length");
718725
uint32_t TotalLen = 1;
@@ -828,7 +835,7 @@ class OpEvalImpl {
828835
break;
829836
auto Scope = ValueMapScope(ValueMap);
830837
BlockItrTy Itr = Op.getBody().front().begin();
831-
setValue(BodyArg, Pair->Car);
838+
setValue(BodyArg, Pair);
832839
while (Itr != BlockItrTy() && Itr != BlockItrTy(Op))
833840
Itr = Visit(&*Itr);
834841
// Check subpattern failure.
@@ -846,6 +853,7 @@ class OpEvalImpl {
846853
}
847854

848855
BlockItrTy Visit(ResolveOp Op) {
856+
heavy::SourceLocation Loc = getSourceLocation(Op.getLoc());
849857
if (auto ParentOp = dyn_cast<SubpatternOp>(Op->getParentOp())) {
850858
// We are at the terminator of a subpattern body region.
851859
assert(ParentOp.getPacks().size() ==
@@ -856,7 +864,7 @@ class OpEvalImpl {
856864
// Construct each pack as a reversed ordered list.
857865
for (unsigned i = 0; i < ResolveArgs.size(); i++) {
858866
Value Pack = Context.CreatePair(getValue(ResolveArgs[i]),
859-
getValue(MResults[i]));
867+
getValue(MResults[i]), Loc);
860868
setValueParentScope(MResults[i], Pack);
861869
}
862870
return BlockItrTy();
@@ -866,7 +874,8 @@ class OpEvalImpl {
866874
assert(Op.getArgs().size() == 1 && "expecting single result");
867875
heavy::Value CurrentResult = getValue(Op.getArgs().front());
868876
heavy::Value Result = Context.CreatePair(CurrentResult,
869-
getValue(ExpandPacksOp.getResult()));
877+
getValue(ExpandPacksOp.getResult()),
878+
Loc);
870879
setValueParentScope(ExpandPacksOp.getResult(), Result);
871880
return BlockItrTy();
872881
}
@@ -882,9 +891,11 @@ class OpEvalImpl {
882891

883892
BlockItrTy Visit(SyntaxClosureOp Op) {
884893
// Create a SyntaxClosure with the provided env argument.
894+
heavy::Value SourceVal = getValue(Op.getSourceVal());
895+
heavy::SourceLocation Loc = SourceVal.getSourceLocation();
885896
heavy::Value Input = getValue(Op.getInput());
886897
heavy::Value Env = getValue(Op.getEnv());
887-
Value SC = Context.CreateSyntaxClosure(Context.getLoc(), Input, Env);
898+
Value SC = Context.CreateSyntaxClosure(Loc, Input, Env);
888899
setValue(Op.getResult(), SC);
889900

890901
return next(Op);
@@ -921,7 +932,8 @@ class OpEvalImpl {
921932
}
922933

923934
BlockItrTy Visit(SourceLocOp Op) {
924-
heavy::SourceLocation Loc = getSourceLocation(Op.getLoc());
935+
heavy::Value Arg = getValue(Op.getArg());
936+
heavy::SourceLocation Loc = Arg.getSourceLocation();
925937
heavy::Value V = Context.CreateSourceValue(Loc);
926938
setValue(Op.getResult(), V);
927939
return next(Op);

0 commit comments

Comments
 (0)