Archive

Archive for October, 2009

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 , ,

amf implementation using Erlang

October 4th, 2009

I just restarted a long sleep idea to implement AMF using Erlang, the project, codenamed Erling, is hosted in github. There’s nothing much yet except amf0 and amf3 implementation, i’m working on the unit test for whatever I’ve written so far to make sure it won’t go messy as the code evolved.
Everyday I’m learning new thing along with Erling and therefore more Erlang examples to come …

AMF , , ,