Home > AMF, Basic, Record > Record introspection at compile time

Record introspection at compile time

October 8th, 2009

For AMF implementation, I have to define the mapping between Actionscript classes with something equivalent in Erlang. First thing came into my mind is record. However, I immediately encountered some of the difficulties when using records in Erlang

  1. Read: can’t use reflection easily after parsing AMF, I received the object with properties/values and I need to map to the corresponding record
  2. Write: Need to introspect the record and write its properties into binaries

I found this post from trapexit. However, I need specifically more than that.

Normally records are defined in a header file “.hrl”. And the idea is to generate utility codes (getter, setter, record meta data ….) at compile time. The heart of it is epp:parse_file/3 function. The generator (or the helper) reads header files, parses all records and create a compilable .erl file which contains all functions you need to do all magic with records:

  1. set(Obj, PropertyName, Value) -> {ok, NewObj, {PropertyName, Value}}
  2. get(Obj, PropertyName) -> {ok, Value}
  3. fields(record_name) -> Fields = [string()]
  4. fields_atom(record_name) -> Fields = [term()]
  5. type(Obj) -> record_name

messages.hrl – the source

record_helper.erl – the generator

record_utils.erl – the generated source

Below is the demonstration of how to generate and use the record utils

1> c(record_helper.erl).
{ok,record_helper}
2> record_helper:make(["messages.hrl"], ".").
ok
3> ls().
messages.hrl            record_helper.beam
record_helper.erl      record_utils.erl
ok
6> c(record_utils).
{ok,record_utils}
7> rr("messages.hrl").
[abstract_message,async_message]
8> Obj = #async_message{}.
#async_message{
    parent =
        #abstract_message{
            clientId = undefined,destination = undefined,
            messageId = undefined,timestamp = undefined,
            timeToLive = undefined,headers = undefined,body = undefined},
    correlationId = undefined,correlationIdBytes = undefined}
9> record_utils:set(Obj, correlationId, "ADF-123-DDF-543").
{ok,#async_message{
        parent =
            #abstract_message{
                clientId = undefined,destination = undefined,
                messageId = undefined,timestamp = undefined,
                timeToLive = undefined,headers = undefined,body = undefined},
        correlationId = "ADF-123-DDF-543",
        correlationIdBytes = undefined},
    {correlationId,"ADF-123-DDF-543"}}
10> {ok,NewObj, _} = record_utils:set(Obj, correlationId, "ADF-123-DDF-543").
{ok,#async_message{
        parent =
            #abstract_message{
                clientId = undefined,destination = undefined,
                messageId = undefined,timestamp = undefined,
                timeToLive = undefined,headers = undefined,body = undefined},
        correlationId = "ADF-123-DDF-543",
        correlationIdBytes = undefined},
    {correlationId,"ADF-123-DDF-543"}}
11> record_utils:get(NewObj, correlationId).
{ok,"ADF-123-DDF-543"}
12> record_utils:type(NewObj).
async_message

record_helper.erl is not so clean as there’re all string concatenations … further improvements can be:

  1. Using template language like ErlyDTL or ErlTL
  2. Clean up code to have more friendly arguments
  3. You add ….

AMF, Basic, Record , ,

  1. October 9th, 2009 at 09:07 | #1

    If you want to manipulate Erlang code @ compile time, you can inspire yourself by reading the following post: http://stackoverflow.com/questions/1423054/erlang-is-there-an-equivalent-to-the-c-preprocessor-directive

    Have Fun :-)

  2. Trung
    October 12th, 2009 at 07:24 | #2

    Thanks … it’s really inspired!!!!!

  3. November 28th, 2010 at 17:49 | #3

    this method to manage record is very nice

  1. No trackbacks yet.