Skip to content

Latest commit

 

History

History
93 lines (79 loc) · 2.63 KB

README.md

File metadata and controls

93 lines (79 loc) · 2.63 KB

Introduction

Header-only library for compile-time DSL.
Library provides macro_rules macro that allows to describe own DSL.
Syntax of macro_rules was inspired by Rust, but with some limitations.
DSL can be implemented directly using templates, for more flexibility.

This project is currently under development and not well tested and not documented.

Code Example

#include "meta/meta_rules.hpp"

/** This would be equivalent to macro_rules(sum $(args:number)*) **/
struct Example : meta::parse::group<
    meta::parse::ident<"sum">,
    meta::parse::list<
        meta::parse::with_name<
            "args",
            meta::parse::token<TokenType::Number>
        >
    >
> {
    consteval static auto transform(auto ctx) {
        auto args = meta::parse::get<"args">(ctx.value);

        int32_t result = 0;
        std::__for_each_index_sequence(
            std::make_index_sequence<std::tuple_size_v<decltype(args)>>(),
            [&]<size_t I>{
                int32_t number;
                std::from_chars(std::get<I>(args).str.begin(), std::get<I>(args).str.end(), number);
                result += number;
            }
        );
        return result;
    }
};

static_assert(apply_rules(Example, sum 1 2 3 4) == 10);
#include "meta/meta_rules.hpp"

template<auto params>
struct FunctionContext {
    constexpr static auto get_argument_index(std::string_view name) -> size_t {
        for (size_t i = 0; i < params.value.size(); ++i) {
            if (params.value[i] == name) {
                return i;
            }
        }
        return -1;
    }
};

struct Function : macro_rules(
    ($($param:ident)*) -> $body:expr
) {
    consteval static auto transform(auto ctx) {
        constexpr auto params = meta::parse::Wrapper<[] {
            return std::apply(
                [](auto... args) {
                    return std::array{ args.str... };
                },
                meta::parse::get<"param">(decltype(ctx){}.value)
            );
        }>();
        return wrap<FunctionContext<params>{}, std::get<0>(meta::parse::get<"body">(ctx.value))>();
    }

    template<FunctionContext ctx, auto body>
    consteval static auto wrap() {
        return [](auto&&... args) {
            return body(ctx, std::forward_as_tuple(std::forward<decltype(args)>(args)...));
        };
    }
};

#define $fn(...) apply_rules(Function, __VA_ARGS__)

auto main() -> int {
    constexpr auto fn1 = $fn((a b c d) -> ((a + b) * (c - d)) * 10);
    constexpr auto fn2 = [](int a, int b, int c, int d) {
        return (a + b) * (c - d) * 10;
    };
    static_assert(fn1(1, 2, 3, 4) == fn2(1, 2, 3, 4));
    return 0;
}