Skip to content

Commit

Permalink
feat: Handlebars API
Browse files Browse the repository at this point in the history
  • Loading branch information
vinniefalco committed Jun 6, 2023
1 parent 21988cf commit 7a218f4
Show file tree
Hide file tree
Showing 2 changed files with 342 additions and 0 deletions.
135 changes: 135 additions & 0 deletions include/mrdox/Support/Handlebars.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
//
// This is a derivative work. originally part of the LLVM Project.
// Licensed under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
// Copyright (c) 2023 Vinnie Falco ([email protected])
//
// Official repository: https://github.com/cppalliance/mrdox
//

#ifndef MRDOX_SUPPORT_HANDLEBARS_HPP
#define MRDOX_SUPPORT_HANDLEBARS_HPP

#include <mrdox/Platform.hpp>
#include <cstddef>
#include <string_view>
#include <system_error>

namespace clang {
namespace mrdox {
namespace hbs {

struct Access;
class Object;

//------------------------------------------------

/** A reference to an instance of the Javascript interpreter.
*/
class Context
{
struct Impl;

Impl* impl_;

friend struct Access;

public:
Context& operator=(Context const&) = delete;

MRDOX_DECL ~Context();
MRDOX_DECL Context();
MRDOX_DECL Context(Context const&) noexcept;

MRDOX_DECL std::error_code eval(std::string_view js);
MRDOX_DECL std::error_code eval_file(std::string_view path);
};

//------------------------------------------------

/** An ECMAScript Array.
*/
class Array
{
Context ctx_;
int idx_;

friend struct Access;

public:
Array(Array const&) = delete;
Array& operator=(Array const&) = delete;

MRDOX_DECL ~Array();
MRDOX_DECL Array(Context const& ctx);
MRDOX_DECL void append(std::string_view value) const;
MRDOX_DECL void append(Array const& value) const;
MRDOX_DECL void append(Object const& value) const;
};

//------------------------------------------------

/** An ECMAScript Object
*/
class Object
{
Context ctx_;
int idx_;

friend struct Access;

public:
Object(Object const&) = delete;
Object& operator=(Object const&) = delete;

MRDOX_DECL ~Object();
MRDOX_DECL Object(Context const& ctx);
MRDOX_DECL void insert(std::string_view key, std::string_view value) const;
MRDOX_DECL void insert(std::string_view key, Array const& value) const;
MRDOX_DECL void insert(std::string_view key, Object const& value) const;
};

//------------------------------------------------

/** A compiled Handlebars template.
*/
class Template
{
public:
};

/** A compiled Handlebars partial.
*/
class Partial
{
public:
};

//------------------------------------------------

/** An instance of the handlebars template engine.
*/
class Handlebars
{
Context ctx_;

public:
explicit
Handlebars(Context const& ctx) noexcept;

/** Return the loaded handlebars script.
*/
friend
Handlebars
loadHandlebarsScript(
std::string_view path,
std::error_code& ec);
};

} // hbs
} // mrdox
} // clang

#endif
207 changes: 207 additions & 0 deletions source/Support/Handlebars.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,207 @@
//
// This is a derivative work. originally part of the LLVM Project.
// Licensed under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
// Copyright (c) 2023 Vinnie Falco ([email protected])
//
// Official repository: https://github.com/cppalliance/mrdox
//

#include <mrdox/Support/Handlebars.hpp>
#include "duktape.h"
#include <llvm/Support/MemoryBuffer.h>

namespace clang {
namespace mrdox {
namespace hbs {

//------------------------------------------------

// The current duk_context
thread_local static ::duk_context* ctx_ = nullptr;

//------------------------------------------------

struct Context::Impl
{
std::size_t refs;
::duk_context* ctx;

~Impl()
{
::duk_destroy_heap(ctx_);
}

Impl()
: refs(1)
, ctx(::duk_create_heap_default())
{
}
};

Context::
~Context()
{
if(--impl_->refs == 0)
delete impl_;
}

Context::
Context()
: impl_(new Impl)
{
}

Context::
Context(
Context const& other) noexcept
: impl_(other.impl_)
{
++impl_->refs;
}

std::error_code
Context::
eval(
std::string_view js)
{
// VFALCO How do we handle the error if any?
duk_eval_lstring_noresult(impl_->ctx, js.data(), js.size());
return {};
}

std::error_code
Context::
eval_file(
std::string_view path)
{
auto js = llvm::MemoryBuffer::getFile(path);
if(! js)
return js.getError();
return eval(js->get()->getBuffer());
}

//------------------------------------------------

struct Access
{
static int idx(Array const& arr) noexcept
{
return arr.idx_;
}

static int idx(Object const& obj) noexcept
{
return obj.idx_;
}

static ::duk_context* ctx(Context const& ctx) noexcept
{
return ctx.impl_->ctx;
}
};

//------------------------------------------------

Array::
~Array()
{
if(idx_ != DUK_INVALID_INDEX)
{
// remove idx_ from stack?
}
}

Array::
Array(
Context const& ctx)
: ctx_(ctx)
, idx_(::duk_push_array(Access::ctx(ctx)))
{
}

void
Array::
append(
std::string_view value) const
{
}

void
Array::
append(
Array const& value) const
{
}

void
Array::
append(
Object const& value) const
{
}

//------------------------------------------------

Object::
~Object()
{
if(idx_ != DUK_INVALID_INDEX)
{
// remove idx_ from stack?
}
}

Object::
Object(
Context const& ctx)
: ctx_(ctx)
, idx_(::duk_push_object(Access::ctx(ctx)))
{
}

void
Object::
insert(
std::string_view key,
std::string_view value) const
{
::duk_push_lstring(Access::ctx(ctx_), value.data(), value.size());
::duk_put_prop_lstring(Access::ctx(ctx_), idx_, key.data(), key.size());
}

void
Object::
insert(
std::string_view key,
Array const& value) const
{
::duk_dup(Access::ctx(ctx_), Access::idx(value));
::duk_put_prop_lstring(Access::ctx(ctx_), idx_, key.data(), key.size());
}

void
Object::
insert(
std::string_view key,
Object const& value) const
{
::duk_dup(Access::ctx(ctx_), Access::idx(value));
::duk_put_prop_lstring(Access::ctx(ctx_), idx_, key.data(), key.size());
}

//------------------------------------------------

Handlebars::
Handlebars(
Context const& ctx) noexcept
: ctx_(ctx)
{

}

} // hbs
} // mrdox
} // clang

0 comments on commit 7a218f4

Please sign in to comment.