Skip to content

Instantly share code, notes, and snippets.

@yutopp
Last active August 29, 2015 14:19
Show Gist options
  • Save yutopp/75a4beaf9ae215a1e7ee to your computer and use it in GitHub Desktop.
Save yutopp/75a4beaf9ae215a1e7ee to your computer and use it in GitHub Desktop.
//
// Copyright yutopp 2015 - .
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
module ast;
import std.traits, std.typetuple;
import std.stdio;
import std.algorithm;
template AstNodeIdEnum(class_names...) {
static if ( class_names.length > 0 ) {
enum AstNodeIdEnum = class_names[0] ~ ", " ~ AstNodeIdEnum!(class_names[1..$]);
} else {
enum AstNodeIdEnum = "";
}
}
// define AstTag
mixin ("enum AstTag {" ~ AstNodeIdEnum!(__traits(allMembers, nodes)) ~ "}");
//
mixin template ast_override_members(T) {
string name() const @property {
return T.stringof;
}
AstTag id() const {
return mixin ("AstTag." ~ T.stringof);
}
}
mixin template ast() {
alias self_type = typeof(this);
static if ( BaseClassesTuple!self_type.length > 1 ) {
override { mixin ast_override_members!self_type; }
} else {
mixin ast_override_members!self_type;
}
}
//
mixin template nodes() {
// base class
class AstBase {
mixin ast;
}
//
class Value : AstBase {
mixin ast;
}
//
class Expression : AstBase {
mixin ast;
}
//
class Statement : AstBase {
mixin ast;
}
}
mixin nodes;
//
mixin template visitor(R, bool prevent_missing = true) {
alias self_type = typeof(this);
alias visit_func_type = R function(self_type, AstBase);
R dispatch(T...)(AstBase node, T tx) {
return visitor_table_[node.id](this, node, tx);
}
static this() {
foreach( self_node; __traits(allMembers, nodes) ) {
auto self_tag = mixin ("AstTag." ~ self_node);
alias derived_order = TypeTuple!(mixin (self_node), BaseClassesTuple!(mixin (self_node)));
// emulate inheritance/dispatch
foreach( node_type; derived_order ) {
static if ( __traits(compiles, (cast(self_type)null).visit(cast(node_type)null)) ) {
// callable
visitor_table_[self_tag] = function R(self_type t, AstBase a) {
return t.visit(cast(node_type)a);
};
break;
} else if ( __traits(isSame, node_type, Object) ) {
visitor_table_[self_tag] = &missing_node;
}
}
}
}
private:
static if ( prevent_missing ) {
static R missing_node(self_type t, AstBase a) {
assert(0);
}
}
static visit_func_type[AstTag.max+1] visitor_table_;
}
class HogeVisitor {
alias return_type = int;
mixin visitor!(return_type);
return_type visit(AstBase s) {
"astbase".writeln;
return 0;
}
return_type visit(Statement s) {
"statement".writeln;
return 0;
}
return_type visit(Value s) {
"value".writeln;
return 0;
}
}
void main() {
auto v = new HogeVisitor();
v.dispatch(new Statement());
v.dispatch(new Expression());
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment