Commit b0730966 authored by Kenton Varda's avatar Kenton Varda

More compiler WIP

parent 0da57538
...@@ -89,8 +89,8 @@ public: ...@@ -89,8 +89,8 @@ public:
// implements NodeTranslator::Resolver ----------------------------- // implements NodeTranslator::Resolver -----------------------------
kj::Maybe<ResolvedName> resolve(const DeclName::Reader& name) const override; kj::Maybe<ResolvedName> resolve(const DeclName::Reader& name) const override;
kj::Maybe<Schema> resolveMaybeBootstrapSchema(uint64_t id) const override; Schema resolveMaybeBootstrapSchema(uint64_t id) const override;
kj::Maybe<Schema> resolveFinalSchema(uint64_t id) const override; Schema resolveFinalSchema(uint64_t id) const override;
private: private:
const CompiledModule* module; // null iff isBuiltin is true const CompiledModule* module; // null iff isBuiltin is true
...@@ -608,14 +608,20 @@ kj::Maybe<NodeTranslator::Resolver::ResolvedName> Compiler::Node::resolve( ...@@ -608,14 +608,20 @@ kj::Maybe<NodeTranslator::Resolver::ResolvedName> Compiler::Node::resolve(
}); });
} }
kj::Maybe<Schema> Compiler::Node::resolveMaybeBootstrapSchema(uint64_t id) const { Schema Compiler::Node::resolveMaybeBootstrapSchema(uint64_t id) const {
return module->getCompiler().findNode(id).map( KJ_IF_MAYBE(node, module->getCompiler().findNode(id)) {
[](const Node& node) { return node.getBootstrapOrFinalSchema(); }); return node->getBootstrapOrFinalSchema();
} else {
KJ_FAIL_REQUIRE("Tried to get schema for ID we haven't seen before.");
}
} }
kj::Maybe<Schema> Compiler::Node::resolveFinalSchema(uint64_t id) const { Schema Compiler::Node::resolveFinalSchema(uint64_t id) const {
return module->getCompiler().findNode(id).map( KJ_IF_MAYBE(node, module->getCompiler().findNode(id)) {
[](const Node& node) { return node.getFinalSchema(); }); return node->getFinalSchema();
} else {
KJ_FAIL_REQUIRE("Tried to get schema for ID we haven't seen before.");
}
} }
// ======================================================================================= // =======================================================================================
...@@ -644,19 +650,7 @@ Compiler::Impl::Impl(): finalLoader(*this), workspace(nullptr) { ...@@ -644,19 +650,7 @@ Compiler::Impl::Impl(): finalLoader(*this), workspace(nullptr) {
for (auto member: declBodySchema.getMembers()) { for (auto member: declBodySchema.getMembers()) {
auto name = member.getProto().getName(); auto name = member.getProto().getName();
if (name.startsWith("builtin")) { if (name.startsWith("builtin")) {
kj::StringPtr symbolName; kj::StringPtr symbolName = name.slice(strlen("builtin"));
if (name.endsWith("Value")) {
// e.g. "builtinTrueValue" -- transform this to "true".
auto substr = name.slice(strlen("builtin"), name.size() - strlen("Value"));
kj::ArrayPtr<char> array = nodeArena.allocateArray<char>(substr.size() + 1);
memcpy(array.begin(), substr.begin(), substr.size());
array[substr.size()] = '\0';
array[0] += 'a' - 'A';
symbolName = kj::StringPtr(array.begin(), array.size() - 1);
} else {
// e.g. "builtinVoid" -- transform this to "Void".
symbolName = name.slice(strlen("builtin"));
}
builtinDecls[symbolName] = nodeArena.allocateOwn<Node>( builtinDecls[symbolName] = nodeArena.allocateOwn<Node>(
symbolName, static_cast<Declaration::Body::Which>(member.getIndex())); symbolName, static_cast<Declaration::Body::Which>(member.getIndex()));
} }
......
...@@ -95,7 +95,7 @@ struct ValueExpression { ...@@ -95,7 +95,7 @@ struct ValueExpression {
negativeInt @3 :UInt64; negativeInt @3 :UInt64;
float @4 :Float64; float @4 :Float64;
string @5 :Text; string @5 :Text;
identifier @6 :Text; name @6 :DeclName;
list @7 :List(ValueExpression); list @7 :List(ValueExpression);
structValue @8 :List(FieldAssignment); structValue @8 :List(FieldAssignment);
unionValue @9 :FieldAssignment; unionValue @9 :FieldAssignment;
...@@ -160,7 +160,7 @@ struct Declaration { ...@@ -160,7 +160,7 @@ struct Declaration {
# so that the compiler can handle symbol name lookups more uniformly. # so that the compiler can handle symbol name lookups more uniformly.
# #
# New union members added here will magically become visible in the global scope. # New union members added here will magically become visible in the global scope.
# "builtinFoo" becomes visible as "Foo", while "builtinFooValue" becomes visible as "foo". # E.g. "builtinFoo" becomes visible as "Foo".
builtinVoid @25 :Void; builtinVoid @25 :Void;
builtinBool @26 :Void; builtinBool @26 :Void;
builtinInt8 @27 :Void; builtinInt8 @27 :Void;
...@@ -177,10 +177,6 @@ struct Declaration { ...@@ -177,10 +177,6 @@ struct Declaration {
builtinData @38 :Void; builtinData @38 :Void;
builtinList @39 :Void; builtinList @39 :Void;
builtinObject @40 :Void; builtinObject @40 :Void;
builtinTrueValue @41 :Void;
builtinFalseValue @42 :Void;
builtinVoidValue @43 :Void;
} }
struct File {} struct File {}
......
This diff is collapsed.
...@@ -54,12 +54,15 @@ public: ...@@ -54,12 +54,15 @@ public:
// Look up the given name, relative to this node, and return basic information about the // Look up the given name, relative to this node, and return basic information about the
// target. // target.
virtual kj::Maybe<Schema> resolveMaybeBootstrapSchema(uint64_t id) const = 0; virtual Schema resolveMaybeBootstrapSchema(uint64_t id) const = 0;
// Get the schema for the given ID. Returning either a bootstrap schema or a final schema // Get the schema for the given ID. Returning either a bootstrap schema or a final schema
// is acceptable. // is acceptable. Throws an exception if the id is not one that was found by calling resolve()
// or by traversing other schemas.
virtual kj::Maybe<Schema> resolveFinalSchema(uint64_t id) const = 0; virtual Schema resolveFinalSchema(uint64_t id) const = 0;
// Get the final schema for the given ID. A bootstrap schema is not acceptable. // Get the final schema for the given ID. A bootstrap schema is not acceptable. Throws an
// exception if the id is not one that was found by calling resolve() or by traversing other
// schemas.
}; };
NodeTranslator(const Resolver& resolver, const ErrorReporter& errorReporter, NodeTranslator(const Resolver& resolver, const ErrorReporter& errorReporter,
...@@ -143,6 +146,12 @@ private: ...@@ -143,6 +146,12 @@ private:
schema::Type::Reader type, schema::Value::Builder target); schema::Type::Reader type, schema::Value::Builder target);
// Compile a previously-unfinished value. See `unfinishedValues`. // Compile a previously-unfinished value. See `unfinishedValues`.
void copyValue(schema::Value::Reader src, schema::Type::Reader srcType,
schema::Value::Builder dst, schema::Type::Reader dstType,
ValueExpression::Reader errorLocation);
// Copy a value from one schema to another, possibly coercing the type if compatible, or
// reporting an error otherwise.
Orphan<List<schema::Annotation>> compileAnnotationApplications( Orphan<List<schema::Annotation>> compileAnnotationApplications(
List<Declaration::AnnotationApplication>::Reader annotations, List<Declaration::AnnotationApplication>::Reader annotations,
kj::StringPtr targetsFlagName); kj::StringPtr targetsFlagName);
......
...@@ -28,6 +28,7 @@ ...@@ -28,6 +28,7 @@
#include <sys/types.h> #include <sys/types.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <fcntl.h> #include <fcntl.h>
#include <limits>
namespace capnp { namespace capnp {
namespace compiler { namespace compiler {
...@@ -299,6 +300,15 @@ inline Declaration::Builder initMemberDecl( ...@@ -299,6 +300,15 @@ inline Declaration::Builder initMemberDecl(
return builder; return builder;
} }
template <typename BuilderType>
void initLocation(kj::parse::Span<List<Token>::Reader::Iterator> location,
BuilderType builder) {
if (location.begin() < location.end()) {
builder.setStartByte(location.begin()->getStartByte());
builder.setEndByte((location.end() - 1)->getEndByte());
}
}
} // namespace } // namespace
// ======================================================================================= // =======================================================================================
...@@ -336,10 +346,11 @@ CapnpParser::CapnpParser(Orphanage orphanageParam, ErrorReporter& errorReporterP ...@@ -336,10 +346,11 @@ CapnpParser::CapnpParser(Orphanage orphanageParam, ErrorReporter& errorReporterP
return kj::mv(result); return kj::mv(result);
})); }));
parsers.typeExpression = arena.copy(p::transform( parsers.typeExpression = arena.copy(p::transformWithLocation(
p::sequence(parsers.declName, p::optional( p::sequence(parsers.declName, p::optional(
parenthesizedList(parsers.typeExpression, errorReporter))), parenthesizedList(parsers.typeExpression, errorReporter))),
[this](Orphan<DeclName>&& name, [this](kj::parse::Span<List<Token>::Reader::Iterator> location,
Orphan<DeclName>&& name,
kj::Maybe<Located<kj::Array<kj::Maybe<Orphan<TypeExpression>>>>>&& params) kj::Maybe<Located<kj::Array<kj::Maybe<Orphan<TypeExpression>>>>>&& params)
-> Orphan<TypeExpression> { -> Orphan<TypeExpression> {
auto result = orphanage.newOrphan<TypeExpression>(); auto result = orphanage.newOrphan<TypeExpression>();
...@@ -356,6 +367,7 @@ CapnpParser::CapnpParser(Orphanage orphanageParam, ErrorReporter& errorReporterP ...@@ -356,6 +367,7 @@ CapnpParser::CapnpParser(Orphanage orphanageParam, ErrorReporter& errorReporterP
} }
} }
} }
initLocation(location, builder);
return result; return result;
})); }));
...@@ -451,6 +463,15 @@ CapnpParser::CapnpParser(Orphanage orphanageParam, ErrorReporter& errorReporterP ...@@ -451,6 +463,15 @@ CapnpParser::CapnpParser(Orphanage orphanageParam, ErrorReporter& errorReporterP
value.copyLocationTo(builder); value.copyLocationTo(builder);
return result; return result;
}), }),
p::transformWithLocation(p::sequence(op("-"), keyword("inf")),
[this](kj::parse::Span<List<Token>::Reader::Iterator> location)
-> Orphan<ValueExpression> {
auto result = orphanage.newOrphan<ValueExpression>();
auto builder = result.get();
builder.getBody().setFloat(-std::numeric_limits<double>::infinity());
initLocation(location, builder);
return result;
}),
p::transform(stringLiteral, p::transform(stringLiteral,
[this](Located<Text::Reader>&& value) -> Orphan<ValueExpression> { [this](Located<Text::Reader>&& value) -> Orphan<ValueExpression> {
auto result = orphanage.newOrphan<ValueExpression>(); auto result = orphanage.newOrphan<ValueExpression>();
...@@ -474,12 +495,13 @@ CapnpParser::CapnpParser(Orphanage orphanageParam, ErrorReporter& errorReporterP ...@@ -474,12 +495,13 @@ CapnpParser::CapnpParser(Orphanage orphanageParam, ErrorReporter& errorReporterP
return result; return result;
}), }),
p::transform(identifier, p::transformWithLocation(parsers.declName,
[this](Located<Text::Reader>&& value) -> Orphan<ValueExpression> { [this](kj::parse::Span<List<Token>::Reader::Iterator> location,
Orphan<DeclName>&& value) -> Orphan<ValueExpression> {
auto result = orphanage.newOrphan<ValueExpression>(); auto result = orphanage.newOrphan<ValueExpression>();
auto builder = result.get(); auto builder = result.get();
builder.getBody().setIdentifier(value.value); builder.getBody().adoptName(kj::mv(value));
value.copyLocationTo(builder); initLocation(location, builder);
return result; return result;
}), }),
p::transform(bracketedList(parsers.valueExpression, errorReporter), p::transform(bracketedList(parsers.valueExpression, errorReporter),
...@@ -518,10 +540,9 @@ CapnpParser::CapnpParser(Orphanage orphanageParam, ErrorReporter& errorReporterP ...@@ -518,10 +540,9 @@ CapnpParser::CapnpParser(Orphanage orphanageParam, ErrorReporter& errorReporterP
}) })
)); ));
parsers.annotation = arena.copy(p::transformWithLocation( parsers.annotation = arena.copy(p::transform(
p::sequence(op("$"), parsers.declName, p::optional(parsers.parenthesizedValueExpression)), p::sequence(op("$"), parsers.declName, p::optional(parsers.parenthesizedValueExpression)),
[this](kj::parse::Span<List<Token>::Reader::Iterator> location, [this](Orphan<DeclName>&& name, kj::Maybe<Orphan<ValueExpression>>&& value)
Orphan<DeclName>&& name, kj::Maybe<Orphan<ValueExpression>>&& value)
-> Orphan<Declaration::AnnotationApplication> { -> Orphan<Declaration::AnnotationApplication> {
auto result = orphanage.newOrphan<Declaration::AnnotationApplication>(); auto result = orphanage.newOrphan<Declaration::AnnotationApplication>();
auto builder = result.get(); auto builder = result.get();
......
...@@ -1408,7 +1408,7 @@ typeName DynamicValue::Reader::AsImpl<typeName>::apply(const Reader& reader) { \ ...@@ -1408,7 +1408,7 @@ typeName DynamicValue::Reader::AsImpl<typeName>::apply(const Reader& reader) { \
case FLOAT: \ case FLOAT: \
return ifFloat<typeName>(reader.floatValue); \ return ifFloat<typeName>(reader.floatValue); \
default: \ default: \
KJ_FAIL_REQUIRE("Type mismatch when using DynamicValue::Reader::as().") { \ KJ_FAIL_REQUIRE("Value type mismatch.") { \
return 0; \ return 0; \
} \ } \
} \ } \
...@@ -1422,7 +1422,7 @@ typeName DynamicValue::Builder::AsImpl<typeName>::apply(Builder& builder) { \ ...@@ -1422,7 +1422,7 @@ typeName DynamicValue::Builder::AsImpl<typeName>::apply(Builder& builder) { \
case FLOAT: \ case FLOAT: \
return ifFloat<typeName>(builder.floatValue); \ return ifFloat<typeName>(builder.floatValue); \
default: \ default: \
KJ_FAIL_REQUIRE("Type mismatch when using DynamicValue::Builder::as().") { \ KJ_FAIL_REQUIRE("Value type mismatch.") { \
return 0; \ return 0; \
} \ } \
} \ } \
...@@ -1443,15 +1443,13 @@ HANDLE_NUMERIC_TYPE(double, kj::implicitCast, kj::implicitCast, kj::implicitCast ...@@ -1443,15 +1443,13 @@ HANDLE_NUMERIC_TYPE(double, kj::implicitCast, kj::implicitCast, kj::implicitCast
#define HANDLE_TYPE(name, discrim, typeName) \ #define HANDLE_TYPE(name, discrim, typeName) \
ReaderFor<typeName> DynamicValue::Reader::AsImpl<typeName>::apply(const Reader& reader) { \ ReaderFor<typeName> DynamicValue::Reader::AsImpl<typeName>::apply(const Reader& reader) { \
KJ_REQUIRE(reader.type == discrim, \ KJ_REQUIRE(reader.type == discrim, "Value type mismatch.") { \
"Type mismatch when using DynamicValue::Reader::as().") { \
return ReaderFor<typeName>(); \ return ReaderFor<typeName>(); \
} \ } \
return reader.name##Value; \ return reader.name##Value; \
} \ } \
BuilderFor<typeName> DynamicValue::Builder::AsImpl<typeName>::apply(Builder& builder) { \ BuilderFor<typeName> DynamicValue::Builder::AsImpl<typeName>::apply(Builder& builder) { \
KJ_REQUIRE(builder.type == discrim, \ KJ_REQUIRE(builder.type == discrim, "Value type mismatch.") { \
"Type mismatch when using DynamicValue::Builder::as().") { \
return BuilderFor<typeName>(); \ return BuilderFor<typeName>(); \
} \ } \
return builder.name##Value; \ return builder.name##Value; \
...@@ -1472,13 +1470,13 @@ HANDLE_TYPE(union, UNION, DynamicUnion) ...@@ -1472,13 +1470,13 @@ HANDLE_TYPE(union, UNION, DynamicUnion)
// As in the header, HANDLE_TYPE(void, VOID, Void) crashes GCC 4.7. // As in the header, HANDLE_TYPE(void, VOID, Void) crashes GCC 4.7.
Void DynamicValue::Reader::AsImpl<Void>::apply(const Reader& reader) { Void DynamicValue::Reader::AsImpl<Void>::apply(const Reader& reader) {
KJ_REQUIRE(reader.type == VOID, "Type mismatch when using DynamicValue::Reader::as().") { KJ_REQUIRE(reader.type == VOID, "Value type mismatch.") {
return Void(); return Void();
} }
return reader.voidValue; return reader.voidValue;
} }
Void DynamicValue::Builder::AsImpl<Void>::apply(Builder& builder) { Void DynamicValue::Builder::AsImpl<Void>::apply(Builder& builder) {
KJ_REQUIRE(builder.type == VOID, "Type mismatch when using DynamicValue::Builder::as().") { KJ_REQUIRE(builder.type == VOID, "Value type mismatch.") {
return Void(); return Void();
} }
return builder.voidValue; return builder.voidValue;
......
...@@ -40,6 +40,10 @@ struct Node { ...@@ -40,6 +40,10 @@ struct Node {
# #
# (On Zooko's triangle, this is the node's nickname.) # (On Zooko's triangle, this is the node's nickname.)
displayNamePrefixLength @12 :UInt32;
# If you want a shorter version of `displayName` (just naming this node, without its surrounding
# scope), chop off this many characters from the beginning of `displayName`.
scopeId @2 :Id = 0; scopeId @2 :Id = 0;
# ID of the lexical parent node. Typically, the scope node will have a NestedNode pointing back # ID of the lexical parent node. Typically, the scope node will have a NestedNode pointing back
# at this node, but robust code should avoid relying on this. `scopeId` is zero if the node has # at this node, but robust code should avoid relying on this. `scopeId` is zero if the node has
...@@ -109,6 +113,7 @@ struct Value { ...@@ -109,6 +113,7 @@ struct Value {
body @0 union { body @0 union {
# Note ordinals 1 and 10 are intentionally swapped to improve union layout. # Note ordinals 1 and 10 are intentionally swapped to improve union layout.
# TODO: Make it 2 and 10 that are swapped instead so that voidValue is still default?
voidValue @10 :Void; voidValue @10 :Void;
boolValue @2 :Bool; boolValue @2 :Bool;
int8Value @3 :Int8; int8Value @3 :Int8;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment