Skip to content

Instantly share code, notes, and snippets.

@mmisamore
Last active February 26, 2020 02:10
Show Gist options
  • Save mmisamore/5bddbe4658dbdca72292530b7c6e69d8 to your computer and use it in GitHub Desktop.
Save mmisamore/5bddbe4658dbdca72292530b7c6e69d8 to your computer and use it in GitHub Desktop.
A simple record generation macro in swi-prolog
:- use_module(library(clpfd)).
% True if TypeFieldFunctor is the functor built from TypeName and FieldName atoms
% with an underscore between
type_field_functor(TypeName, FieldName, TypeFieldFunctor) :-
atom_chars(TypeName, TypeChars),
atom_chars(FieldName, FieldChars),
append(TypeChars, ['_'], TypeUnderscore),
append(TypeUnderscore, FieldChars, TypeFieldFunctorChars),
atom_chars(TypeFieldFunctor, TypeFieldFunctorChars).
% True if Term relates record TypeName of TypeArity to one of its fields named
% FieldName appearing at index FieldPos
field_term(Term, TypeName, TypeArity, FieldName, FieldPos) :-
type_field_functor(TypeName, FieldName, Functor),
Term =.. [Functor, Arg1, Arg2],
functor(Arg1, TypeName, TypeArity), % Arg1 is the record
arg(FieldPos, Arg1, Arg2). % Arg2 is the FieldPos argument of Arg1
% True when Terms is a list of terms describing access to each FieldName of a record
% with name TypeName
field_terms(_, [], [], TypeArity, TypeArity).
field_terms(TypeName, [FieldName|FieldNames], [Term|Terms], I, TypeArity) :-
Pos #= I + 1,
field_term(Term, TypeName, TypeArity, FieldName, Pos),
field_terms(TypeName, FieldNames, Terms, Pos, TypeArity).
field_terms(TypeName, FieldNames, Terms) :-
length(FieldNames, TypeArity),
field_terms(TypeName, FieldNames, Terms, 0, TypeArity).
% Hook the record generation macro
term_expansion(define_record(TypeName, FieldNames), Terms) :-
field_terms(TypeName, FieldNames, Terms).
% Try the macro
define_record(player, [name, exp, hp, level]).
define_record(monster, [name, exp, mp]).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment