Skip to content

Commit d1b323f

Browse files
committed
[Heavy] Fix precompiled syntax; Support identifiers in more places; Fail at procedural macros
1 parent 7f0c670 commit d1b323f

File tree

13 files changed

+228
-155
lines changed

13 files changed

+228
-155
lines changed

heavy/include/heavy/Builtins.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@
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 "5Serror"
32-
#define HEAVY_BASE_VAR_STR__equal HEAVY_BASE_LIB_STR "2Seqqu"
3332

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

heavy/include/heavy/Context.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,8 @@ class Context : public ContinuationStack<Context>,
221221
}
222222
EnvEntry Lookup(Value Id, Value Stack);
223223

224+
EnvEntry GetSyntax(EnvEntry Entry);
225+
224226
// PushEnvFrame - Creates and pushes an EnvFrame to the
225227
// current environment (EnvStack)
226228
EnvFrame* PushEnvFrame(llvm::ArrayRef<Value> Names);

heavy/include/heavy/OpGen.h

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -283,8 +283,8 @@ class OpGen : public ValueVisitor<OpGen, mlir::Value> {
283283
mlir::Value createBody(SourceLocation Loc, Value Body);
284284
mlir::Value createSequence(SourceLocation Loc, Value Body);
285285
mlir::Value createSyntaxSpec(Pair* SyntaxSpec, Value OrigCall);
286-
mlir::Value createSyntaxRules(SourceLocation Loc, Symbol* Keyword,
287-
Symbol* Ellipsis, Value KeywordList,
286+
mlir::Value createSyntaxRules(SourceLocation Loc, Value Keyword,
287+
Value Ellipsis, Value KeywordList,
288288
Value SyntaxDef);
289289
mlir::Value createIf(SourceLocation Loc, Value Cond, Value Then,
290290
Value Else);
@@ -301,8 +301,8 @@ class OpGen : public ValueVisitor<OpGen, mlir::Value> {
301301
heavy::FuncOp createFunction(SourceLocation Loc,
302302
llvm::StringRef MangledName,
303303
mlir::FunctionType FT);
304-
heavy::FuncOp createSyntaxFunction(SourceLocation Loc,
305-
llvm::StringRef Name = {});
304+
heavy::FuncOp createSyntaxFunction(SourceLocation Loc);
305+
heavy::FuncOp createSyntaxFunction(SourceLocation Loc, heavy::Value Proc);
306306
mlir::Value createLambda(Value Formals, Value Body,
307307
SourceLocation Loc,
308308
llvm::StringRef Name = {});
@@ -399,9 +399,7 @@ class OpGen : public ValueVisitor<OpGen, mlir::Value> {
399399

400400
heavy::EnvEntry LookupEnv(heavy::Value Id);
401401
private:
402-
mlir::Value MaybeCallSyntax(Pair* P, bool& DidCallSyntax,
403-
heavy::EnvEntry& FnEnvEntry);
404-
mlir::Value MaybeCallSyntax(Value Operator, Pair* P, bool& DidCallSyntax);
402+
mlir::Value CallSyntax(Value Operator, Pair* P);
405403
mlir::Value HandleCall(Pair* P, heavy::EnvEntry FnEnvEntry);
406404
};
407405

heavy/include/heavy/Value.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1315,8 +1315,6 @@ class Vector final
13151315
getTrailingObjects<Value>(), Len);
13161316
}
13171317

1318-
inline EnvEntry Lookup(Value Id) const;
1319-
13201318
static bool classof(Value V) {
13211319
return V.getKind() == ValueKind::Vector;
13221320
}

heavy/include/heavy/base.sld

Lines changed: 32 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,37 @@
22

33
(define-library (heavy base)
44
(import (heavy builtins))
5-
#;(begin
5+
(begin
6+
(define (caar x) (car (car x)))
7+
(define (cadr x) (car (cdr x)))
8+
(define (cdar x) (cdr (car x)))
9+
(define (cddr x) (cdr (cdr x)))
10+
11+
; FIXME Procedural macros because we do not keep Env alive.
12+
#;(define-syntax ir-macro-transformer
13+
(syntax-fn
14+
(lambda (Syntax Env)
15+
(define ProcSyntax (cadr (cadr Syntax)))
16+
; Eval ProcSyntax to create Proc
17+
; FIXME This requires keeping Env alive which
18+
; we don't do to support incremental compiling
19+
; of self contained functions.
20+
; This is why static templates such as with
21+
; syntax-rules are needed.
22+
; ie Procedural macros are right out.
23+
(define Proc (make-syntactic-closure Env '() ProcSyntax))
24+
(dump Proc)
25+
(dump Proc)
26+
(make-syntax-fn
27+
(lambda (syntax env)
28+
(define expr (cadr (inject syntax)))
29+
(define (inject x)
30+
(make-syntactic-closure env '() x))
31+
(define compare equal?)
32+
(define TemplateInst (Proc expr inject compare))
33+
(opgen TemplateInst env)))
34+
)))
35+
636
) ; end of begin
737
(export
838
; syntax
@@ -14,7 +44,7 @@
1444
quote
1545
set!
1646
syntax-rules
17-
;ir-macro-transformer
47+
ir-macro-transformer
1848
begin
1949
cond-expand
2050
define-library
@@ -77,6 +107,5 @@
77107
; Extended types.
78108
mlir-operation?
79109
source-value?
80-
make-syntactic-closure
81110
)
82111
)

heavy/lib/Builtins.cpp

Lines changed: 39 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
//
1111
//===----------------------------------------------------------------------===//
1212

13+
#include "TemplateGen.h"
1314
#include "heavy/Builtins.h"
1415
#include "heavy/Context.h"
1516
#include "heavy/Dialect.h"
@@ -37,7 +38,7 @@ heavy::ExternBuiltinSyntax cond_expand;
3738
heavy::ExternBuiltinSyntax define;
3839
heavy::ExternBuiltinSyntax define_syntax;
3940
heavy::ExternBuiltinSyntax syntax_rules;
40-
heavy::ExternBuiltinSyntax ir_macro_transformer;
41+
heavy::ExternBuiltinSyntax syntax_fn;
4142
heavy::ExternBuiltinSyntax if_;
4243
heavy::ExternBuiltinSyntax lambda;
4344
heavy::ExternBuiltinSyntax quasiquote;
@@ -141,19 +142,35 @@ mlir::Value define_syntax(OpGen& OG, Pair* P) {
141142
return OG.createSyntaxSpec(P2, P);
142143
}
143144

145+
namespace {
146+
std::pair<heavy::Value, heavy::Pair*> DestructureSyntaxSpec(OpGen& OG, Pair* P) {
147+
heavy::Value Keyword = P->Car;
148+
heavy::Pair* P2 = dyn_cast<Pair>(P->Cdr);
149+
if (P2) {
150+
heavy::Pair* Spec = dyn_cast<Pair>(P2->Car);
151+
if (Spec) {
152+
if (heavy::Pair* SpecInput = dyn_cast<Pair>(Spec->Cdr))
153+
return {Keyword, SpecInput};
154+
}
155+
}
156+
return {};
157+
}
158+
} // end anon namespace
159+
144160
mlir::Value syntax_rules(OpGen& OG, Pair* P) {
145-
// TODO Support SyntaxClosures. (ie do not use Symbol directly)
161+
auto [Keyword, SpecInput] = DestructureSyntaxSpec(OG, P);
162+
163+
if (!Keyword || !SpecInput)
164+
return OG.SetError("invalid syntax-rules syntax", P);
146165

147-
// The input is the <Syntax Spec> (Keyword (syntax-rules ...))
148-
// <Syntax Spec> has its own checks in createSyntaxSpec
149-
Symbol* Keyword = dyn_cast<Symbol>(P->Car);
150-
Pair* SpecInput = dyn_cast_or_null<Pair>(P->Cdr.car().cdr());
151-
if (!SpecInput) return OG.SetError("invalid syntax-rules syntax", P);
152166
// Check for optional ellipsis identifier.
153-
Symbol* Ellipsis = dyn_cast<Symbol>(SpecInput->Car);
167+
Value Ellipsis;
168+
if (isIdentifier(SpecInput->Car))
169+
Ellipsis = SpecInput->Car;
154170
if (Ellipsis) {
155171
Pair* Temp = dyn_cast<Pair>(SpecInput->Cdr);
156-
if (!Temp) return OG.SetError("invalid syntax-rules syntax.", SpecInput);
172+
if (!Temp)
173+
return OG.SetError("invalid syntax-rules syntax.", SpecInput);
157174
SpecInput = Temp;
158175
} else {
159176
Ellipsis = OG.getContext().CreateSymbol("...");
@@ -162,28 +179,16 @@ mlir::Value syntax_rules(OpGen& OG, Pair* P) {
162179
SpecInput->Car, SpecInput->Cdr);
163180
}
164181

165-
mlir::Value ir_macro_transformer(OpGen& OG, Pair* P) {
166-
#if 0
167-
heavy::FuncOp FuncOp = createSyntaxFunction(Loc);
168-
mlir::Block& Body = *FuncOp.addEntryBlock();
169-
mlir::BlockArgument ExprArg = Body.getArgument(1);
170-
mlir::BlockArgument EnvArg = Body.getArgument(2);
171-
mlir::OpBuilder::InsertionGuard IG(Builder);
172-
Builder.setInsertionPointToStart(&Body);
173-
174-
// Compile the input which should be a lambda with:
175-
// expr, inject, compare
176-
heavy::Value ProvidedLambdaExpr = P->Cdr.car();
177-
if (!ProvidedLambdaExpr && isa<Empty>(P->Cdr.cdr()))
178-
return OG.SetError("invalid syntax for ir-macro-transformer");
179-
mlir::Value ProvidedLambda = OpGen.GetSingleResult(ProvidedLambdaExpr);
180-
if (OpGen.CheckError())
181-
return;
182-
mlir::Value Compare = create<LoadGlobalOp>(Loc, HEAVY_BASE_VAR_STR(equal));
183-
184-
//heavy::Transformer Transformer(OG, /*IsImplicitRename=*/true);
185-
#endif
186-
return mlir::Value();
182+
// Convert lambda syntax into heavy::Syntax function
183+
// (for use with define-syntax.)
184+
mlir::Value syntax_fn(OpGen& OG, Pair* P) {
185+
auto [Keyword, SpecInput] = DestructureSyntaxSpec(OG, P);
186+
if (!Keyword || !SpecInput || !isa<Empty>(SpecInput->Cdr))
187+
return OG.SetError("invalid syntax for syntax-fn", P);
188+
heavy::SourceLocation Loc = P->getSourceLocation();
189+
heavy::Value ProcExpr = SpecInput->Car;
190+
heavy::FuncOp FuncOp = OG.createSyntaxFunction(Loc, ProcExpr);
191+
return OG.create<heavy::SyntaxOp>(Loc, FuncOp.getSymName());
187192
}
188193

189194
mlir::Value lambda(OpGen& OG, Pair* P) {
@@ -909,6 +914,7 @@ void apply(Context& C, ValueRefs Args) {
909914
}
910915

911916
void make_syntactic_closure(Context& C, ValueRefs Args) {
917+
llvm_unreachable("make-syntactic-closure is not supported");
912918
if (Args.size() != 2)
913919
return C.RaiseError("invalid arity");
914920
Value Expr = Args[0];
@@ -926,8 +932,7 @@ void HEAVY_BASE_INIT(heavy::Context& Context) {
926932
HEAVY_BASE_VAR(define) = heavy::builtins::define;
927933
HEAVY_BASE_VAR(define_syntax) = heavy::builtins::define_syntax;
928934
HEAVY_BASE_VAR(syntax_rules) = heavy::builtins::syntax_rules;
929-
HEAVY_BASE_VAR(ir_macro_transformer)
930-
= heavy::builtins::ir_macro_transformer;
935+
HEAVY_BASE_VAR(syntax_fn) = heavy::builtins::syntax_fn;
931936
HEAVY_BASE_VAR(if_) = heavy::builtins::if_;
932937
HEAVY_BASE_VAR(lambda) = heavy::builtins::lambda;
933938
HEAVY_BASE_VAR(quasiquote) = heavy::builtins::quasiquote;
@@ -1014,8 +1019,7 @@ void HEAVY_BASE_LOAD_MODULE(heavy::Context& Context) {
10141019
{"quote", HEAVY_BASE_VAR(quote)},
10151020
{"set!", HEAVY_BASE_VAR(set)},
10161021
{"syntax-rules", HEAVY_BASE_VAR(syntax_rules)},
1017-
{"ir-macro-transformer",
1018-
HEAVY_BASE_VAR(ir_macro_transformer)},
1022+
{"syntax-fn", HEAVY_BASE_VAR(syntax_fn)},
10191023
{"begin", HEAVY_BASE_VAR(begin)},
10201024
{"cond-expand", HEAVY_BASE_VAR(cond_expand)},
10211025
{"define-library",HEAVY_BASE_VAR(define_library)},

heavy/lib/Context.cpp

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -646,6 +646,12 @@ bool equal_slow(Value V1, Value V2) {
646646
case ValueKind::Vector:
647647
llvm_unreachable("TODO");
648648
return false;
649+
case ValueKind::SyntaxClosure: {
650+
auto* SC1 = cast<SyntaxClosure>(V1);
651+
auto* SC2 = cast<SyntaxClosure>(V2);
652+
return equal(SC1->Node, SC2->Node) &&
653+
equal(SC1->Env, SC2->Env);
654+
}
649655
default:
650656
return eqv(V1, V2);
651657
}
@@ -1626,6 +1632,21 @@ SyntaxClosure* Context::CreateSyntaxClosure(SourceLocation Loc, Value Node,
16261632
return new (*this) SyntaxClosure(Loc, Env, Node);
16271633
}
16281634

1635+
EnvEntry Context::GetSyntax(EnvEntry Entry) {
1636+
heavy::Value V = Entry.Value;
1637+
if (auto* B = dyn_cast<Binding>(V)) {
1638+
V = B->getValue();
1639+
// Unwrap any ExternName to see if it is a syntax.
1640+
if (auto* ExternName = dyn_cast<heavy::ExternName>(V))
1641+
V = GetKnownValue(ExternName->getView());
1642+
}
1643+
1644+
if (isa<Syntax, BuiltinSyntax>(V))
1645+
return heavy::EnvEntry{V, Entry.MangledName};
1646+
else
1647+
return heavy::EnvEntry();
1648+
}
1649+
16291650
bool Context::OutputModule(llvm::StringRef MangledName,
16301651
llvm::StringRef ModulePath) {
16311652
#if 0

heavy/lib/OpEval.cpp

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -462,6 +462,15 @@ class OpEvalImpl {
462462
if (Op.isExternal())
463463
return BlockItrTy();
464464

465+
// The global may already be initialized in the case
466+
// of syntax objects.
467+
if (Value Val = Context.GetKnownValue(Op.getSymName())) {
468+
if (!isa<heavy::Undefined>(Val)) {
469+
Context.Cont(Undefined());
470+
return BlockItrTy();
471+
}
472+
}
473+
465474
Context.PushCont([Op](heavy::Context& C, ValueRefs Args) mutable {
466475
assert(Args.size() == 1 && "invalid continuation arity");
467476
heavy::Value Result = Args[0];
@@ -826,6 +835,6 @@ void op_eval(Context& C, ValueRefs Args) {
826835

827836
C.OpEval->Eval(Op);
828837
}
829-
}
830838

831-
}
839+
} // end namespace builtins
840+
} // end namespace heavy

0 commit comments

Comments
 (0)