Skip to content

Commit 62066a2

Browse files
committed
[Heavy] Generalize syntax as functions
1 parent 11f67f7 commit 62066a2

File tree

12 files changed

+223
-284
lines changed

12 files changed

+223
-284
lines changed

heavy/include/heavy/Builtins.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@
2727
#define HEAVY_LOAD_MODULE_VAR "_HEAVY_load_module"
2828

2929
#define HEAVY_BASE_VAR(NAME) ::heavy::base_var::NAME
30+
#define HEAVY_BASE_VAR_STR(NAME) HEAVY_BASE_VAR_STR__##NAME
31+
#define HEAVY_BASE_VAR_STR__error HEAVY_BASE_LIB_STR "5Serror"
3032

3133
// Forward declare vars that are used in the C++ codebase.
3234
namespace heavy::base_var {

heavy/include/heavy/Context.h

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -57,8 +57,6 @@ void write(llvm::raw_ostream&, Value);
5757

5858
class OpEvalImpl;
5959
void opEval(mlir::Operation*);
60-
void invokeSyntaxOp(heavy::Context& C, mlir::Operation* Op,
61-
heavy::Value Value);
6260

6361
class ContextLocalLookup {
6462
friend struct ContextLocal;
@@ -122,6 +120,7 @@ class Context : public ContinuationStack<Context>,
122120

123121
public:
124122
heavy::OpGen* OpGen = nullptr;
123+
// FIXME OpEval is not cleaned up or owned by anything.
125124
heavy::OpEvalImpl* OpEval = nullptr;
126125

127126
// Work around DidCallContinuation being set with compiler errors.
@@ -153,7 +152,7 @@ class Context : public ContinuationStack<Context>,
153152
// when the callee finishes or on
154153
// exception so the parent loop can
155154
// finish execution such as clean up.
156-
Value RunSync(Value Callee, Value Arg);
155+
Value RunSync(Value Callee, ValueRefs Args);
157156

158157
void InitModule(Symbol* MangledName);
159158
mlir::Operation* getModuleOp();
@@ -299,8 +298,6 @@ class Context : public ContinuationStack<Context>,
299298
}
300299
}
301300

302-
Syntax* CreateSyntaxWithOp(mlir::Operation* SyntaxOp);
303-
304301
Value RebuildLiteral(Value V);
305302

306303
Heap<Context>& getAllocator() { return *this; }

heavy/include/heavy/OpGen.h

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,11 +39,16 @@ using NameSet = llvm::SmallPtrSetImpl<String*>;
3939
class PatternTemplate;
4040
class TemplateGen;
4141

42+
template <typename Derived>
43+
class TemplateBase;
44+
4245
class OpGen : public ValueVisitor<OpGen, mlir::Value> {
4346
friend ValueVisitor;
4447
friend CopyCollector;
4548
friend PatternTemplate;
4649
friend TemplateGen;
50+
template <typename Derived>
51+
friend class TemplateBase;
4752
using BindingScopeTable = llvm::ScopedHashTable<
4853
heavy::Value,
4954
mlir::Value>;
@@ -271,6 +276,8 @@ class OpGen : public ValueVisitor<OpGen, mlir::Value> {
271276

272277
mlir::Value createCall(heavy::SourceLocation Loc, mlir::Value Fn,
273278
llvm::MutableArrayRef<mlir::Value> Args);
279+
mlir::Value createSyntaxError(heavy::SourceLocation Loc,
280+
llvm::MutableArrayRef<mlir::Value> Args);
274281
mlir::Value createOpGen(SourceLocation Loc, mlir::Value Input,
275282
mlir::Value Env);
276283
mlir::Value createBody(SourceLocation Loc, Value Body);
@@ -306,8 +313,12 @@ class OpGen : public ValueVisitor<OpGen, mlir::Value> {
306313
mlir::Value createSet(SourceLocation Loc, Value LHS, Value RHS);
307314

308315
mlir::Value createEqual(Value V1, Value V2); // equal? for pattern matching
316+
317+
heavy::LiteralOp createLiteral(heavy::SourceLocation Loc, Value V) {
318+
return create<LiteralOp>(Loc, V);
319+
}
309320
heavy::LiteralOp createLiteral(Value V) {
310-
return create<LiteralOp>(V.getSourceLocation(), V);
321+
return createLiteral(V.getSourceLocation(), V);
311322
}
312323

313324
void createLoadModule(SourceLocation Loc, Symbol* MangledName);

heavy/include/heavy/Ops.td

Lines changed: 23 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -200,10 +200,6 @@ def heavy_GlobalOp : HeavyOp<"global", [Symbol, IsolatedFromAbove]> {
200200
}];
201201

202202
let arguments = (ins StrAttr:$sym_name);
203-
let results = (outs HeavyValue:$result);
204-
let builders = [
205-
OpBuilder<(ins "::llvm::StringRef":$sym_name)>
206-
];
207203
}
208204

209205
def heavy_IfOp : HeavyOp<"if", []> {
@@ -441,13 +437,18 @@ def heavy_ResolveOp : HeavyOp<"resolve", [Terminator]> {
441437
let results = (outs);
442438
}
443439

444-
def heavy_PatternOp : HeavyOp<"pattern", [HasParent<"SyntaxOp">]> {
440+
def heavy_PatternOp : HeavyOp<"pattern", []> {
445441
let description = [{
446-
PatternOp represents the pattern in a pattern/template
447-
pair as part of the syntax-rules transform specifier. The
448-
region should contain matching operations on the input syntax,
449-
as well as ConsOps for the template, terminating with an OpGenOp
450-
on the constructed AST.
442+
PatternOp represents a pattern/template pair as part of the
443+
syntax-rules transform specifier. Operations in its region are
444+
evaluated in order. When a match operation fails within its region,
445+
evaluation will jump to the successor operation of the containing
446+
PatternOp (which is likely another pattern or error.)
447+
448+
Successfully matched patterns will likely generate and compile a
449+
new scheme form via ConsOps and terminating with an OpGenOp.
450+
Alternatively they may terminate with an ErrorOp in the case
451+
of `syntax-error`.
451452
}];
452453

453454
let arguments = (ins);
@@ -565,22 +566,22 @@ def heavy_SyntaxClosureOp : HeavyOp<"syntax_closure"> {
565566
];
566567
}
567568

568-
def heavy_SyntaxOp: HeavyOp<"syntax", [IsolatedFromAbove, NoTerminator]> {
569+
def heavy_SyntaxOp: HeavyOp<"syntax", []> {
569570
let summary = "syntax";
570571
let description = [{
571-
SyntaxOp contains a linearly overloaded sequence of PatternOps that
572-
operate on the input AST.
573-
Any PatternOp that guarantees it cannot match can be removed.
574-
Any PatternOp that guarantees a match statically can have subsequent
575-
matches removed.
576-
A SyntaxOp must contain at least one PatternOp.
577-
Semantics are implied for chaining and failure to find a match.
572+
SyntaxOp creates a syntax function object that is callable like
573+
a lambda but has the specific purpose of generating new
574+
operations in the current builder context.
575+
576+
The argument $name refers to the function name.
578577
}];
579578

580-
let regions = (region SizedRegion<1>:$region);
581-
let arguments = (ins);
582-
let results = (outs HeavySyntax:$result);
583-
let builders = [OpBuilder<(ins)>];
579+
let arguments = (ins StrAttr:$name);
580+
let results = (outs HeavySyntax:$result);
581+
582+
let builders = [
583+
OpBuilder<(ins "::llvm::StringRef":$name)>
584+
];
584585
}
585586

586587
def heavy_ToVectorOp : HeavyOp<"to_vector"> {

heavy/include/heavy/Value.h

Lines changed: 2 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1809,23 +1809,9 @@ class Environment : public ValueBase {
18091809
return X.second == MangledName;
18101810
}
18111811

1812-
// Insert - Add a named mutable location. Overwriting
1813-
// with a new object is okay here if it is mutable
1812+
// Add a named location or syntax keyword.
18141813
void Insert(Symbol* S, String* MangledName) {
1815-
String* Name = S->getString();
1816-
String*& MangleNameEntry = EnvMap[Name];
1817-
// FIXME This should not be an assert.
1818-
assert(!MangleNameEntry && "insert may not modify immutable locations");
1819-
MangleNameEntry = MangledName;
1820-
}
1821-
1822-
// SetSyntax - Extend the syntactic environment.
1823-
void SetSyntax(Symbol* Name, Syntax* S, String* MangledName) {
1824-
String*& MangledNameEntry = EnvMap[Name->getString()];
1825-
assert(MangledNameEntry != MangledName &&
1826-
"global syntax must have unique mangling");
1827-
// We need to associate the syntax name at compile time.
1828-
MangledNameEntry = MangledName;
1814+
EnvMap[S->getString()] = MangledName;
18291815
}
18301816

18311817
static bool classof(Value V) {

heavy/lib/Builtins.cpp

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,11 +37,13 @@ heavy::ExternBuiltinSyntax cond_expand;
3737
heavy::ExternBuiltinSyntax define;
3838
heavy::ExternBuiltinSyntax define_syntax;
3939
heavy::ExternBuiltinSyntax syntax_rules;
40+
heavy::ExternBuiltinSyntax ir_macro_transformer;
4041
heavy::ExternBuiltinSyntax if_;
4142
heavy::ExternBuiltinSyntax lambda;
4243
heavy::ExternBuiltinSyntax quasiquote;
4344
heavy::ExternBuiltinSyntax quote;
4445
heavy::ExternBuiltinSyntax set;
46+
heavy::ExternBuiltinSyntax syntax_error;
4547

4648

4749
heavy::ExternFunction add;
@@ -158,6 +160,10 @@ mlir::Value syntax_rules(OpGen& OG, Pair* P) {
158160
SpecInput->Car, SpecInput->Cdr);
159161
}
160162

163+
mlir::Value ir_macro_transformer(OpGen& OG, Pair* P) {
164+
llvm_unreachable("TODO");
165+
}
166+
161167
mlir::Value lambda(OpGen& OG, Pair* P) {
162168
Pair* P2 = dyn_cast<Pair>(P->Cdr);
163169
Value Formals = P2->Car;
@@ -203,6 +209,17 @@ mlir::Value set(OpGen& OG, Pair* P) {
203209
return OG.createSet(P->getSourceLocation(), S, Expr);
204210
}
205211

212+
mlir::Value syntax_error(OpGen& OG, Pair* P) {
213+
heavy::SourceLocation Loc = P->getSourceLocation();
214+
Pair* P2 = dyn_cast<Pair>(P->Cdr);
215+
if (!P2)
216+
return OG.SetError("invalid syntax-error... syntax", P);
217+
llvm::SmallVector<mlir::Value, 8> Args;
218+
for (auto [Loc, V] : WithSource(P2))
219+
Args.push_back(OG.createLiteral(Loc, V));
220+
return OG.createSyntaxError(Loc, Args);
221+
}
222+
206223
namespace {
207224
void import_helper(Context& C, ValueRefs Args) {
208225
if (Pair* P = dyn_cast<Pair>(Args[0])) {
@@ -869,6 +886,8 @@ void HEAVY_BASE_INIT(heavy::Context& Context) {
869886
HEAVY_BASE_VAR(define) = heavy::base::define;
870887
HEAVY_BASE_VAR(define_syntax) = heavy::base::define_syntax;
871888
HEAVY_BASE_VAR(syntax_rules) = heavy::base::syntax_rules;
889+
HEAVY_BASE_VAR(ir_macro_transformer)
890+
= heavy::base::ir_macro_transformer;
872891
HEAVY_BASE_VAR(if_) = heavy::base::if_;
873892
HEAVY_BASE_VAR(lambda) = heavy::base::lambda;
874893
HEAVY_BASE_VAR(quasiquote) = heavy::base::quasiquote;
@@ -952,6 +971,8 @@ void HEAVY_BASE_LOAD_MODULE(heavy::Context& Context) {
952971
{"quote", HEAVY_BASE_VAR(quote)},
953972
{"set!", HEAVY_BASE_VAR(set)},
954973
{"syntax-rules", HEAVY_BASE_VAR(syntax_rules)},
974+
{"ir-macro-transformer",
975+
HEAVY_BASE_VAR(ir_macro_transformer)},
955976
{"begin", HEAVY_BASE_VAR(begin)},
956977
{"cond-expand", HEAVY_BASE_VAR(cond_expand)},
957978
{"define-library",HEAVY_BASE_VAR(define_library)},

heavy/lib/Context.cpp

Lines changed: 2 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -118,16 +118,6 @@ Environment* Context::getTopLevelEnvironment() {
118118
llvm_unreachable("EnvStack should have an Environment.");
119119
}
120120

121-
Syntax* Context::CreateSyntaxWithOp(mlir::Operation* Op) {
122-
auto SyntaxOp = cast<heavy::SyntaxOp>(Op);
123-
auto Fn = [SyntaxOp](heavy::Context& C, ValueRefs Args) -> void {
124-
heavy::Value Input = Args[0];
125-
invokeSyntaxOp(C, SyntaxOp, Input);
126-
// The contained OpGenOp will call C.Apply(...).
127-
};
128-
return CreateSyntax(Fn);
129-
}
130-
131121
Module* Context::RegisterModule(llvm::StringRef MangledName,
132122
heavy::ModuleLoadNamesFn* LoadNames) {
133123
auto Result = Modules.try_emplace(MangledName,
@@ -1054,7 +1044,6 @@ void Context::LoadExports(heavy::Module* M, mlir::Operation* ModuleOp) {
10541044
}
10551045

10561046
// Allow the user to add cleanup routines to unload a module/library.
1057-
// It is currently used for destroying the instance of OpEval.
10581047
// TODO expose this via run-time function accessible in scheme land.
10591048
void Context::PushModuleCleanup(llvm::StringRef MangledName, Value Fn) {
10601049
std::unique_ptr<Module>& M = Modules[MangledName];
@@ -1408,15 +1397,15 @@ void Context::WithEnv(std::unique_ptr<heavy::Environment> EnvPtr,
14081397
// called escape procedure is complete.
14091398
// This is used for *nested* calls in C++ when finishing
14101399
// the operation on the current C++ call stack is needed.
1411-
Value Context::RunSync(Value Callee, Value SingleArg) {
1400+
Value Context::RunSync(Value Callee, ValueRefs Args) {
14121401
Value CatchHandler = CreateLambda(
14131402
[](heavy::Context& C, ValueRefs Args) {
14141403
C.Yield(Args);
14151404
});
14161405
Value PrevHandlers = ExceptionHandlers;
14171406
ExceptionHandlers = CatchHandler;
14181407
PushBreak();
1419-
Apply(Callee, ValueRefs{SingleArg});
1408+
Apply(Callee, Args);
14201409
Resume();
14211410
ExceptionHandlers = PrevHandlers;
14221411
return getCurrentResult();

heavy/lib/Dialect.cpp

Lines changed: 3 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -115,29 +115,13 @@ void BindingOp::build(mlir::OpBuilder& B, mlir::OperationState& OpState,
115115
BindingOp::build(B, OpState, B.getType<HeavyValueTy>(), Input);
116116
}
117117

118-
#if 0
119-
void BuiltinOp::build(mlir::OpBuilder& B, mlir::OperationState& OpState,
120-
heavy::Builtin* Builtin) {
121-
// TODO eventually we need to have a "symbol" to the externally
122-
// linked function
123-
BuiltinOp::build(B, OpState, B.getType<HeavyValueTy>(),
124-
HeavyValueAttr::get(B.getContext(), Builtin));
125-
}
126-
#endif
127-
128118
void ConsOp::build(mlir::OpBuilder& B, mlir::OperationState& OpState,
129119
mlir::Value X, mlir::Value Y) {
130120
mlir::Type HeavyValueT = B.getType<HeavyValueTy>();
131121
// TODO return type should be Pair
132122
ConsOp::build(B, OpState, HeavyValueT, X, Y);
133123
}
134124

135-
void GlobalOp::build(mlir::OpBuilder& B, mlir::OperationState& OpState,
136-
llvm::StringRef SymName) {
137-
mlir::Type HeavyValueT = B.getType<HeavyValueTy>();
138-
GlobalOp::build(B, OpState, HeavyValueT, SymName);
139-
}
140-
141125
void IfOp::build(mlir::OpBuilder& B, mlir::OperationState& OpState,
142126
mlir::Value Input) {
143127
IfOp::build(B, OpState, B.getType<HeavyValueTy>(), Input);
@@ -251,9 +235,10 @@ void SyntaxClosureOp::build(mlir::OpBuilder& B, mlir::OperationState& OpState,
251235
SyntaxClosureOp::build(B, OpState, HeavyValueT, Input, Env);
252236
}
253237

254-
void SyntaxOp::build(mlir::OpBuilder& B, mlir::OperationState& OpState) {
238+
void SyntaxOp::build(mlir::OpBuilder& B, mlir::OperationState& OpState,
239+
llvm::StringRef MangledName) {
255240
mlir::Type HeavySyntaxT = B.getType<HeavySyntaxTy>();
256-
SyntaxOp::build(B, OpState, HeavySyntaxT);
241+
SyntaxOp::build(B, OpState, HeavySyntaxT, MangledName);
257242
}
258243

259244
void ToVectorOp::build(mlir::OpBuilder& B, mlir::OperationState& OpState,

0 commit comments

Comments
 (0)