Commit 34e70d5a authored by Kenton Varda's avatar Kenton Varda

More compiler work. Almost to the point of basic functionality... almost...

parent a75f59bf
......@@ -183,7 +183,7 @@ private:
class Compiler::CompiledModule {
public:
CompiledModule(const Compiler::Impl& compiler, const Module<ParsedFile::Reader>& parserModule);
CompiledModule(const Compiler::Impl& compiler, const Module& parserModule);
const Compiler::Impl& getCompiler() const { return compiler; }
......@@ -196,7 +196,7 @@ public:
private:
const Compiler::Impl& compiler;
const Module<ParsedFile::Reader>& parserModule;
const Module& parserModule;
MallocMessageBuilder contentArena;
ParsedFile::Reader content;
Node rootNode;
......@@ -206,7 +206,7 @@ class Compiler::Impl: public SchemaLoader::LazyLoadCallback {
public:
Impl();
const CompiledModule& add(const Module<ParsedFile::Reader>& parsedModule) const;
const CompiledModule& add(const Module& parsedModule) const;
struct Workspace {
// Scratch space where stuff can be allocated while working. The Workspace is available
......@@ -264,7 +264,7 @@ private:
uint workspaceRefcount = 0;
// Count of threads that have entered the compiler.
typedef std::unordered_map<Module<ParsedFile::Reader>*, kj::Own<CompiledModule>> ModuleMap;
typedef std::unordered_map<Module*, kj::Own<CompiledModule>> ModuleMap;
kj::MutexGuarded<ModuleMap> modules;
// Map of parser modules to compiler modules.
......@@ -627,7 +627,7 @@ Schema Compiler::Node::resolveFinalSchema(uint64_t id) const {
// =======================================================================================
Compiler::CompiledModule::CompiledModule(
const Compiler::Impl& compiler, const Module<ParsedFile::Reader>& parserModule)
const Compiler::Impl& compiler, const Module& parserModule)
: compiler(compiler), parserModule(parserModule),
content(parserModule.loadContent(contentArena.getOrphanage())),
rootNode(*this) {}
......@@ -635,7 +635,7 @@ Compiler::CompiledModule::CompiledModule(
kj::Maybe<const Compiler::CompiledModule&> Compiler::CompiledModule::importRelative(
kj::StringPtr importPath) const {
return parserModule.importRelative(importPath).map(
[this](const Module<ParsedFile::Reader>& module) -> const Compiler::CompiledModule& {
[this](const Module& module) -> const Compiler::CompiledModule& {
return compiler.add(module);
});
}
......
......@@ -32,7 +32,6 @@
namespace capnp {
namespace compiler {
template <typename ContentType>
class Module: public ErrorReporter {
public:
virtual kj::StringPtr getLocalName() const = 0;
......@@ -43,7 +42,7 @@ public:
// The name of the module file relative to the source tree. Used to decide where to output
// generated code and to form the `displayName` in the schema.
virtual ContentType loadContent(Orphanage orphanage) const = 0;
virtual Orphan<ParsedFile> loadContent(Orphanage orphanage) const = 0;
// Loads the module content, using the given orphanage to allocate objects if necessary.
virtual kj::Maybe<const Module&> importRelative(kj::StringPtr importPath) const = 0;
......@@ -77,7 +76,7 @@ public:
// use EAGER mode.
};
Schema add(Module<ParsedFile::Reader>& module, Mode mode) const;
Schema add(Module& module, Mode mode) const;
// Add a module to the Compiler, returning its root Schema object.
const SchemaLoader& getLoader() const;
......
......@@ -69,6 +69,9 @@ struct DeclName {
memberPath @4 :List(LocatedText);
# List of `.member` suffixes.
startByte @5 :UInt32;
endByte @6 :UInt32;
}
struct TypeExpression {
......
......@@ -31,7 +31,7 @@ namespace compiler {
namespace p = kj::parse;
bool lex(kj::ArrayPtr<const char> input, LexedStatements::Builder result,
ErrorReporter& errorReporter) {
const ErrorReporter& errorReporter) {
Lexer lexer(Orphanage::getForMessageContaining(result), errorReporter);
auto parser = p::sequence(lexer.getParsers().statementSequence, p::endOfInput);
......@@ -53,7 +53,7 @@ bool lex(kj::ArrayPtr<const char> input, LexedStatements::Builder result,
}
bool lex(kj::ArrayPtr<const char> input, LexedTokens::Builder result,
ErrorReporter& errorReporter) {
const ErrorReporter& errorReporter) {
Lexer lexer(Orphanage::getForMessageContaining(result), errorReporter);
auto parser = p::sequence(lexer.getParsers().tokenSequence, p::endOfInput);
......@@ -138,7 +138,7 @@ constexpr auto docComment = p::optional(p::sequence(
} // namespace
Lexer::Lexer(Orphanage orphanageParam, ErrorReporter& errorReporterParam)
Lexer::Lexer(Orphanage orphanageParam, const ErrorReporter& errorReporterParam)
: orphanage(orphanageParam), errorReporter(errorReporterParam) {
// Note that because passing an lvalue to a parser constructor uses it by-referencee, it's safe
......
......@@ -33,9 +33,9 @@ namespace capnp {
namespace compiler {
bool lex(kj::ArrayPtr<const char> input, LexedStatements::Builder result,
ErrorReporter& errorReporter);
const ErrorReporter& errorReporter);
bool lex(kj::ArrayPtr<const char> input, LexedTokens::Builder result,
ErrorReporter& errorReporter);
const ErrorReporter& errorReporter);
// Lex the given source code, placing the results in `result`. Returns true if there
// were no errors, false if there were. Even when errors are present, the file may have partial
// content which can be fed into later stages of parsing in order to find more errors.
......@@ -49,7 +49,7 @@ class Lexer {
// into your own parsers.
public:
Lexer(Orphanage orphanage, ErrorReporter& errorReporter);
Lexer(Orphanage orphanage, const ErrorReporter& errorReporter);
// `orphanage` is used to allocate Cap'n Proto message objects in the result. `inputStart` is
// a pointer to the beginning of the input, used to compute byte offsets.
......@@ -91,7 +91,7 @@ public:
private:
Orphanage orphanage;
ErrorReporter& errorReporter;
const ErrorReporter& errorReporter;
kj::Arena arena;
Parsers parsers;
};
......
This diff is collapsed.
// Copyright (c) 2013, Kenton Varda <temporal@gmail.com>
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this
// list of conditions and the following disclaimer.
// 2. Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef CAPNP_COMPILER_MODULE_LOADER_H_
#define CAPNP_COMPILER_MODULE_LOADER_H_
#include "compiler.h"
#include <kj/memory.h>
#include <kj/array.h>
#include <kj/string.h>
namespace capnp {
namespace compiler {
class ModuleLoader {
public:
explicit ModuleLoader(int errorFd);
// Create a ModuleLoader that writes error messages to the given file descriptor.
KJ_DISALLOW_COPY(ModuleLoader);
~ModuleLoader();
void addImportPath(kj::String path);
// Add a directory to the list of paths that is searched for imports that start with a '/'.
kj::Maybe<const Module&> loadModule(kj::StringPtr localName, kj::StringPtr sourceName) const;
// Tries to load the module with the given filename. `localName` is the path to the file on
// disk (as you'd pass to open(2)), and `sourceName` is the canonical name it should be given
// in the schema (this is used e.g. to decide output file locations). Often, these are the same.
private:
class Impl;
kj::Own<Impl> impl;
class ModuleImpl;
};
} // namespace compiler
} // namespace capnp
#endif // CAPNP_COMPILER_MODULE_LOADER_H_
This diff is collapsed.
......@@ -138,13 +138,21 @@ private:
void compileBootstrapValue(ValueExpression::Reader source, schema::Type::Reader type,
schema::Value::Builder target);
// Interprets the value expression and initializes `target` with the result. If some parts of
// the value cannot be built at bootstrap time, they'll be added to `unfinishedValues`
// automatically for later processing.
// Calls compileValue() if this value should be interpreted at bootstrap time. Otheriwse,
// adds the value to `unfinishedValues` for later evaluation.
void compileFinalValue(ValueExpression::Reader source,
schema::Type::Reader type, schema::Value::Builder target);
// Compile a previously-unfinished value. See `unfinishedValues`.
void compileValue(ValueExpression::Reader source, schema::Type::Reader type,
schema::Value::Builder target, bool isBootstrap);
// Interprets the value expression and initializes `target` with the result.
class DynamicSlot;
void compileValue(ValueExpression::Reader src, DynamicSlot& dst, bool isBootstrap);
// Fill in `dst` (which effectively points to a struct field or list element) with the given
// value.
void compileValueInner(ValueExpression::Reader src, DynamicSlot& dst, bool isBootstrap);
// Helper for compileValue().
void copyValue(schema::Value::Reader src, schema::Type::Reader srcType,
schema::Value::Builder dst, schema::Type::Reader dstType,
......@@ -152,6 +160,13 @@ private:
// Copy a value from one schema to another, possibly coercing the type if compatible, or
// reporting an error otherwise.
kj::Maybe<DynamicValue::Reader> readConstant(DeclName::Reader name, bool isBootstrap,
ValueExpression::Reader errorLocation);
// Get the value of the given constant.
ListSchema makeListSchemaOf(schema::Type::Reader elementType);
// Construct a list schema representing a list of elements of the given type.
Orphan<List<schema::Annotation>> compileAnnotationApplications(
List<Declaration::AnnotationApplication>::Reader annotations,
kj::StringPtr targetsFlagName);
......
......@@ -51,7 +51,7 @@ uint64_t randomId() {
} // namespace
void parseFile(List<Statement>::Reader statements, ParsedFile::Builder result,
ErrorReporter& errorReporter) {
const ErrorReporter& errorReporter) {
CapnpParser parser(Orphanage::getForMessageContaining(result), errorReporter);
kj::Vector<Orphan<Declaration>> decls(statements.size());
......@@ -203,7 +203,7 @@ class ParseListItems {
// Transformer that parses all items in the input token sequence list using the given parser.
public:
constexpr ParseListItems(ItemParser&& itemParser, ErrorReporter& errorReporter)
constexpr ParseListItems(ItemParser&& itemParser, const ErrorReporter& errorReporter)
: itemParser(p::sequence(kj::fwd<ItemParser>(itemParser), p::endOfInput)),
errorReporter(errorReporter) {}
......@@ -241,11 +241,12 @@ public:
private:
decltype(p::sequence(kj::instance<ItemParser>(), p::endOfInput)) itemParser;
ErrorReporter& errorReporter;
const ErrorReporter& errorReporter;
};
template <typename ItemParser>
constexpr auto parenthesizedList(ItemParser&& itemParser, ErrorReporter& errorReporter) -> decltype(
constexpr auto parenthesizedList(ItemParser&& itemParser,
const ErrorReporter& errorReporter) -> decltype(
transform(rawParenthesizedList, ParseListItems<ItemParser>(
kj::fwd<ItemParser>(itemParser), errorReporter))) {
return transform(rawParenthesizedList, ParseListItems<ItemParser>(
......@@ -253,7 +254,8 @@ constexpr auto parenthesizedList(ItemParser&& itemParser, ErrorReporter& errorRe
}
template <typename ItemParser>
constexpr auto bracketedList(ItemParser&& itemParser, ErrorReporter& errorReporter) -> decltype(
constexpr auto bracketedList(ItemParser&& itemParser,
const ErrorReporter& errorReporter) -> decltype(
transform(rawBracketedList, ParseListItems<ItemParser>(
kj::fwd<ItemParser>(itemParser), errorReporter))) {
return transform(rawBracketedList, ParseListItems<ItemParser>(
......@@ -313,9 +315,9 @@ void initLocation(kj::parse::Span<List<Token>::Reader::Iterator> location,
// =======================================================================================
CapnpParser::CapnpParser(Orphanage orphanageParam, ErrorReporter& errorReporterParam)
CapnpParser::CapnpParser(Orphanage orphanageParam, const ErrorReporter& errorReporterParam)
: orphanage(orphanageParam), errorReporter(errorReporterParam) {
parsers.declName = arena.copy(p::transform(
parsers.declName = arena.copy(p::transformWithLocation(
p::sequence(
p::oneOf(
p::transform(p::sequence(keyword("import"), stringLiteral),
......@@ -337,12 +339,15 @@ CapnpParser::CapnpParser(Orphanage orphanageParam, ErrorReporter& errorReporterP
return result;
})),
p::many(p::sequence(op("."), identifier))),
[this](Orphan<DeclName>&& result, kj::Array<Located<Text::Reader>>&& memberPath)
[this](kj::parse::Span<List<Token>::Reader::Iterator> location,
Orphan<DeclName>&& result, kj::Array<Located<Text::Reader>>&& memberPath)
-> Orphan<DeclName> {
auto builder = result.get().initMemberPath(memberPath.size());
auto builder = result.get();
auto pathBuilder = builder.initMemberPath(memberPath.size());
for (size_t i = 0; i < memberPath.size(); i++) {
memberPath[i].copyTo(builder[i]);
memberPath[i].copyTo(pathBuilder[i]);
}
initLocation(location, builder);
return kj::mv(result);
}));
......
......@@ -34,7 +34,7 @@ namespace capnp {
namespace compiler {
void parseFile(List<Statement>::Reader statements, ParsedFile::Builder result,
ErrorReporter& errorReporter);
const ErrorReporter& errorReporter);
// Parse a list of statements to build a ParsedFile.
//
// If any errors are reported, then the output is not usable. However, it may be passed on through
......@@ -45,7 +45,7 @@ class CapnpParser {
// them into your own parsers.
public:
CapnpParser(Orphanage orphanage, ErrorReporter& errorReporter);
CapnpParser(Orphanage orphanage, const ErrorReporter& errorReporter);
// `orphanage` is used to allocate Cap'n Proto message objects in the result. `inputStart` is
// a pointer to the beginning of the input, used to compute byte offsets.
......@@ -127,7 +127,7 @@ public:
private:
Orphanage orphanage;
ErrorReporter& errorReporter;
const ErrorReporter& errorReporter;
kj::Arena arena;
Parsers parsers;
};
......
......@@ -109,6 +109,8 @@ DynamicTypeFor<TypeIfEnum<T>> toDynamic(T&& value);
class DynamicEnum {
public:
DynamicEnum() = default;
inline DynamicEnum(EnumSchema::Enumerant enumerant)
: schema(enumerant.getContainingEnum()), value(enumerant.getOrdinal()) {}
template <typename T, typename = kj::EnableIf<kind<T>() == Kind::ENUM>>
inline DynamicEnum(T&& value): DynamicEnum(toDynamic(value)) {}
......
......@@ -138,6 +138,11 @@ public:
inline bool startsWith(const StringPtr& other) const { return StringPtr(*this).startsWith(other);}
inline bool endsWith(const StringPtr& other) const { return StringPtr(*this).endsWith(other); }
inline StringPtr slice(size_t start) const { return StringPtr(*this).slice(start); }
inline ArrayPtr<const char> slice(size_t start, size_t end) const {
return StringPtr(*this).slice(start, end);
}
private:
Array<char> content;
};
......
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