Commit b0730966 authored by Kenton Varda's avatar Kenton Varda

More compiler WIP

parent 0da57538
......@@ -89,8 +89,8 @@ public:
// implements NodeTranslator::Resolver -----------------------------
kj::Maybe<ResolvedName> resolve(const DeclName::Reader& name) const override;
kj::Maybe<Schema> resolveMaybeBootstrapSchema(uint64_t id) const override;
kj::Maybe<Schema> resolveFinalSchema(uint64_t id) const override;
Schema resolveMaybeBootstrapSchema(uint64_t id) const override;
Schema resolveFinalSchema(uint64_t id) const override;
private:
const CompiledModule* module; // null iff isBuiltin is true
......@@ -608,14 +608,20 @@ kj::Maybe<NodeTranslator::Resolver::ResolvedName> Compiler::Node::resolve(
});
}
kj::Maybe<Schema> Compiler::Node::resolveMaybeBootstrapSchema(uint64_t id) const {
return module->getCompiler().findNode(id).map(
[](const Node& node) { return node.getBootstrapOrFinalSchema(); });
Schema Compiler::Node::resolveMaybeBootstrapSchema(uint64_t id) const {
KJ_IF_MAYBE(node, module->getCompiler().findNode(id)) {
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 {
return module->getCompiler().findNode(id).map(
[](const Node& node) { return node.getFinalSchema(); });
Schema Compiler::Node::resolveFinalSchema(uint64_t id) const {
KJ_IF_MAYBE(node, module->getCompiler().findNode(id)) {
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) {
for (auto member: declBodySchema.getMembers()) {
auto name = member.getProto().getName();
if (name.startsWith("builtin")) {
kj::StringPtr symbolName;
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"));
}
kj::StringPtr symbolName = name.slice(strlen("builtin"));
builtinDecls[symbolName] = nodeArena.allocateOwn<Node>(
symbolName, static_cast<Declaration::Body::Which>(member.getIndex()));
}
......
......@@ -95,7 +95,7 @@ struct ValueExpression {
negativeInt @3 :UInt64;
float @4 :Float64;
string @5 :Text;
identifier @6 :Text;
name @6 :DeclName;
list @7 :List(ValueExpression);
structValue @8 :List(FieldAssignment);
unionValue @9 :FieldAssignment;
......@@ -160,7 +160,7 @@ struct Declaration {
# so that the compiler can handle symbol name lookups more uniformly.
#
# 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;
builtinBool @26 :Void;
builtinInt8 @27 :Void;
......@@ -177,10 +177,6 @@ struct Declaration {
builtinData @38 :Void;
builtinList @39 :Void;
builtinObject @40 :Void;
builtinTrueValue @41 :Void;
builtinFalseValue @42 :Void;
builtinVoidValue @43 :Void;
}
struct File {}
......
This diff is collapsed.
......@@ -54,12 +54,15 @@ public:
// Look up the given name, relative to this node, and return basic information about the
// 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
// 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;
// Get the final schema for the given ID. A bootstrap schema is not acceptable.
virtual Schema resolveFinalSchema(uint64_t id) const = 0;
// 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,
......@@ -143,6 +146,12 @@ private:
schema::Type::Reader type, schema::Value::Builder target);
// 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(
List<Declaration::AnnotationApplication>::Reader annotations,
kj::StringPtr targetsFlagName);
......
......@@ -28,6 +28,7 @@
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <limits>
namespace capnp {
namespace compiler {
......@@ -299,6 +300,15 @@ inline Declaration::Builder initMemberDecl(
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
// =======================================================================================
......@@ -336,10 +346,11 @@ CapnpParser::CapnpParser(Orphanage orphanageParam, ErrorReporter& errorReporterP
return kj::mv(result);
}));
parsers.typeExpression = arena.copy(p::transform(
parsers.typeExpression = arena.copy(p::transformWithLocation(
p::sequence(parsers.declName, p::optional(
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)
-> Orphan<TypeExpression> {
auto result = orphanage.newOrphan<TypeExpression>();
......@@ -356,6 +367,7 @@ CapnpParser::CapnpParser(Orphanage orphanageParam, ErrorReporter& errorReporterP
}
}
}
initLocation(location, builder);
return result;
}));
......@@ -451,6 +463,15 @@ CapnpParser::CapnpParser(Orphanage orphanageParam, ErrorReporter& errorReporterP
value.copyLocationTo(builder);
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,
[this](Located<Text::Reader>&& value) -> Orphan<ValueExpression> {
auto result = orphanage.newOrphan<ValueExpression>();
......@@ -474,12 +495,13 @@ CapnpParser::CapnpParser(Orphanage orphanageParam, ErrorReporter& errorReporterP
return result;
}),
p::transform(identifier,
[this](Located<Text::Reader>&& value) -> Orphan<ValueExpression> {
p::transformWithLocation(parsers.declName,
[this](kj::parse::Span<List<Token>::Reader::Iterator> location,
Orphan<DeclName>&& value) -> Orphan<ValueExpression> {
auto result = orphanage.newOrphan<ValueExpression>();
auto builder = result.get();
builder.getBody().setIdentifier(value.value);
value.copyLocationTo(builder);
builder.getBody().adoptName(kj::mv(value));
initLocation(location, builder);
return result;
}),
p::transform(bracketedList(parsers.valueExpression, errorReporter),
......@@ -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)),
[this](kj::parse::Span<List<Token>::Reader::Iterator> location,
Orphan<DeclName>&& name, kj::Maybe<Orphan<ValueExpression>>&& value)
[this](Orphan<DeclName>&& name, kj::Maybe<Orphan<ValueExpression>>&& value)
-> Orphan<Declaration::AnnotationApplication> {
auto result = orphanage.newOrphan<Declaration::AnnotationApplication>();
auto builder = result.get();
......
......@@ -1408,7 +1408,7 @@ typeName DynamicValue::Reader::AsImpl<typeName>::apply(const Reader& reader) { \
case FLOAT: \
return ifFloat<typeName>(reader.floatValue); \
default: \
KJ_FAIL_REQUIRE("Type mismatch when using DynamicValue::Reader::as().") { \
KJ_FAIL_REQUIRE("Value type mismatch.") { \
return 0; \
} \
} \
......@@ -1422,7 +1422,7 @@ typeName DynamicValue::Builder::AsImpl<typeName>::apply(Builder& builder) { \
case FLOAT: \
return ifFloat<typeName>(builder.floatValue); \
default: \
KJ_FAIL_REQUIRE("Type mismatch when using DynamicValue::Builder::as().") { \
KJ_FAIL_REQUIRE("Value type mismatch.") { \
return 0; \
} \
} \
......@@ -1443,15 +1443,13 @@ HANDLE_NUMERIC_TYPE(double, kj::implicitCast, kj::implicitCast, kj::implicitCast
#define HANDLE_TYPE(name, discrim, typeName) \
ReaderFor<typeName> DynamicValue::Reader::AsImpl<typeName>::apply(const Reader& reader) { \
KJ_REQUIRE(reader.type == discrim, \
"Type mismatch when using DynamicValue::Reader::as().") { \
KJ_REQUIRE(reader.type == discrim, "Value type mismatch.") { \
return ReaderFor<typeName>(); \
} \
return reader.name##Value; \
} \
BuilderFor<typeName> DynamicValue::Builder::AsImpl<typeName>::apply(Builder& builder) { \
KJ_REQUIRE(builder.type == discrim, \
"Type mismatch when using DynamicValue::Builder::as().") { \
KJ_REQUIRE(builder.type == discrim, "Value type mismatch.") { \
return BuilderFor<typeName>(); \
} \
return builder.name##Value; \
......@@ -1472,13 +1470,13 @@ HANDLE_TYPE(union, UNION, DynamicUnion)
// As in the header, HANDLE_TYPE(void, VOID, Void) crashes GCC 4.7.
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 reader.voidValue;
}
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 builder.voidValue;
......
......@@ -40,6 +40,10 @@ struct Node {
#
# (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;
# 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
......@@ -109,6 +113,7 @@ struct Value {
body @0 union {
# 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;
boolValue @2 :Bool;
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