Skip to content

Commit a2df047

Browse files
committed
[Heavy] Support if syntax with unspecified alternate
1 parent 09bd519 commit a2df047

File tree

4 files changed

+86
-15
lines changed

4 files changed

+86
-15
lines changed

heavy/include/nbdl_gen/Nbdl.td

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -158,8 +158,9 @@ def Nbdl_MatchOp : Nbdl_Op<"match", [Terminator, NoTerminator]> {
158158
`match` visits an element contained within that Store using a
159159
continuation for each of the possible specified overloads.
160160

161-
It is an error if there exists an alternative for which there
162-
exists no matching overload.
161+
Each overload is checked linearly until a matching overload
162+
is found. It is an error if there exists an alternative for
163+
which there exists no matching overload.
163164

164165
For an example, a `std::unordered_map<int, std::string>` is a store
165166
that can provide access to a contained element with a key `5`. If the

heavy/lib/Builtins.cpp

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -165,12 +165,16 @@ mlir::Value if_(OpGen& OG, Pair* P) {
165165
P2 = dyn_cast<Pair>(P2->Cdr);
166166
if (!P2) return OG.SetError("invalid if syntax", P);
167167
Value ThenExpr = P2->Car;
168-
P2 = dyn_cast<Pair>(P2->Cdr);
169-
if (!P2) return OG.SetError("invalid if syntax", P);
170-
Value ElseExpr = P2->Car;
171-
if (!isa<Empty>(P2->Cdr)) {
168+
169+
Value ElseExpr = nullptr;
170+
if (isa<Empty>(P2->Cdr))
171+
ElseExpr = Undefined();
172+
else if (Pair* P3 = dyn_cast<Pair>(P2->Cdr);
173+
P3 && isa<Empty>(P3->Cdr))
174+
ElseExpr = P3->Car;
175+
if (!ElseExpr)
172176
return OG.SetError("invalid if syntax", P);
173-
}
177+
174178
return OG.createIf(P->getSourceLocation(), CondExpr,
175179
ThenExpr, ElseExpr);
176180
}

heavy/lib/Mlir.cpp

Lines changed: 38 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,14 @@ heavy::ExternFunction module_lookup;
6666

6767
using namespace heavy::mlir_helper;
6868

69+
static mlir::Location getMlirLocation(heavy::Context& C,
70+
heavy::SourceLocation Loc,
71+
mlir::MLIRContext* MC) {
72+
if (!Loc.isValid())
73+
Loc = C.getLoc();
74+
return mlir::OpaqueLoc::get(Loc.getOpaqueEncoding(), MC);
75+
}
76+
6977
namespace heavy::mlir_bind {
7078
// Provide function to support create_op syntax.
7179
// Require type checking as a precondition.
@@ -96,10 +104,7 @@ void create_op_impl(Context& C, ValueRefs Args) {
96104
mlir::OpBuilder* Builder = getCurrentBuilder(C);
97105
if (!Builder) return;
98106

99-
if (!Loc.isValid())
100-
Loc = C.getLoc();
101-
mlir::Location MLoc = mlir::OpaqueLoc::get(Loc.getOpaqueEncoding(),
102-
Builder->getContext());
107+
mlir::Location MLoc = getMlirLocation(C, Loc, Builder->getContext());
103108
auto OpState = mlir::OperationState(MLoc, OpName);
104109

105110
// attributes
@@ -341,6 +346,28 @@ void entry_block(Context& C, ValueRefs Args) {
341346
C.Cont(C.CreateAny(Block));
342347
}
343348

349+
// (add-argument block type loc)
350+
void add_argument(Context& C, ValueRefs Args) {
351+
if (Args.size() != 3)
352+
return C.RaiseError("invalid arity");
353+
mlir::Block* Block = any_cast<mlir::Block*>(Args[0]);
354+
mlir::Type Type = any_cast<mlir::Type>(Args[1]);
355+
heavy::SourceLocation Loc= Args[2].getSourceLocation();
356+
if (!Block)
357+
return C.RaiseError("expecting mlir::Block*", Args[0]);
358+
if (Type)
359+
return C.RaiseError("expecting mlir::Block*", Args[1]);
360+
361+
mlir::OpBuilder* Builder = getCurrentBuilder(C);
362+
if (!Builder)
363+
return;
364+
365+
mlir::Location MLoc = getMlirLocation(C, Loc, Builder->getContext());
366+
mlir::BlockArgument BA = Block->addArgument(Type, MLoc);
367+
heavy::Value Result = C.CreateAny(mlir::Value(BA));
368+
C.Cont(Result);
369+
}
370+
344371
// Get list of results of op.
345372
void results(Context& C, ValueRefs Args) {
346373
// This might be useful for applying to operations
@@ -459,24 +486,27 @@ void at_block_terminator(Context& C, ValueRefs Args) {
459486

460487
// Set insertion point to prepend. (alters current-builder)
461488
// (set-insertion-point _op_or_region_)
462-
// Argument can be Operation, Region, or Block.
489+
// Argument can be Operation, Region
463490
// Operation - Insert before operation in containing block.
464-
// Region - Insert before operation in first block.
491+
// Region - Insert before any operation in first block.
465492
void set_insertion_point(Context& C, ValueRefs Args) {
466493
if (Args.size() != 1)
467494
return C.RaiseError("invalid arity");
468495

469496
mlir::OpBuilder* Builder = getCurrentBuilder(C);
470497
if (!Builder) return;
471498

472-
if (auto* Op = dyn_cast<mlir::Operation>(Args[0]))
499+
if (auto* Op = dyn_cast<mlir::Operation>(Args[0])) {
500+
// Insert before the operation.
473501
Builder->setInsertionPoint(Op);
474-
else if (mlir::Region* R = any_cast<mlir::Region*>(Args[0])) {
502+
} else if (mlir::Region* R = any_cast<mlir::Region*>(Args[0])) {
475503
// Automatically add block if needed.
476504
if (R->empty())
477505
R->emplaceBlock();
478506
mlir::Block* Block = &R->front();
479507
Builder->setInsertionPointToStart(Block);
508+
} else {
509+
return C.RaiseError("expecting mlir.op or mlir.region", Args[0]);
480510
}
481511
C.Cont();
482512
}

heavy/test/Evaluate/if.scm

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,3 +49,39 @@
4949
; CHECK-NEXT: bar
5050
(fn 42)
5151
(newline)
52+
53+
; CHECK-NEXT: 0
54+
((lambda ()
55+
(define temp 0)
56+
(if (eqv? temp 42)
57+
(set! temp 5))
58+
(write temp)))
59+
(newline)
60+
61+
; CHECK-NEXT: 5
62+
((lambda ()
63+
(define temp 42)
64+
(if (eqv? temp 42)
65+
(set! temp 5))
66+
(write temp)))
67+
(newline)
68+
69+
; CHECK-NEXT: foo
70+
(write
71+
(if (null? '()) 'return-foo 'return-bar))
72+
(newline)
73+
74+
; CHECK-NEXT: bar
75+
(write
76+
(if (null? 42) 'return-foo 'return-bar))
77+
(newline)
78+
79+
; CHECK-NEXT: baz
80+
(write
81+
(if (null? '()) 'return-baz))
82+
(newline)
83+
84+
; CHECK-NEXT: Undefined
85+
(write
86+
(if (null? 42) 'return-baz))
87+
(newline)

0 commit comments

Comments
 (0)