Sat Sep 26, 2020 3:42 pm
Login Register Lost Password? Contact Us


How is scope (visibility) resolved for function macros?

Comments and questions related to the Enterprise Control Language

Fri Jun 26, 2020 6:58 pm Change Time Zone

Hi,

I came to realize that scope does not work the same when using FUNCTION and FUNCTIONMACRO. I have a specific issue regarding that. I currently have two function macros fn1 and fn2 which are within the same module as shown below.

Code: Select all
myModule := MODULE
   EXPORT fn1(params) := FUNCTIONMACRO
     fn2Result := fn2(params);
     ...
   END;

   EXPORT fn2(params) := FUNCTIONMACRO
      ...
   END;
END;


I realize that fn1 can only call fn2 if fn2 is EXPORTed. However, I only want to make fn1 available to the public and fn2 only available inside the module as a utility function. However, when I set fn2 as SHARED, fn1 can't see it.

Can you help me understand that issue?
Also, can you let me know if there is some documentation regarding visibility rules when it comes to function macros?


Best regards,

Vannel
Last edited by vzeufack on Fri Jun 26, 2020 8:24 pm, edited 1 time in total.
vzeufack
 
Posts: 41
Joined: Tue Sep 25, 2018 3:52 pm

Fri Jun 26, 2020 7:14 pm Change Time Zone

Vannel,

The ECL compiler is a one-pass tool. That means, if you want Fn1 to be able to reference Fn2, you need to reverse their order within the MODULE. This is not specific to FUNCTIONMACROs, it is true for all ECL code.

HTH,

Richard
rtaylor
Community Advisory Board Member
Community Advisory Board Member
 
Posts: 1556
Joined: Wed Oct 26, 2011 7:40 pm

Fri Jun 26, 2020 7:50 pm Change Time Zone

Thanks Richard,

But now, I am getting the error which made me want to post this message 2 or 3 days ago. I inverted the position but I am still getting "Unknown identifier fn2" inside fn1.

Code: Select all
myModule := MODULE
   EXPORT fn2(params) := FUNCTIONMACRO
      ...
   END;

   EXPORT fn1(params) := FUNCTIONMACRO
     fn2Result := fn2(params);  //Unknown identifier fn2
     ...
   END; 
END;


I had to embed fn2 into fn1 for it work.
Do you have any idea of why this could happen?


Best regads,

Vannel,
vzeufack
 
Posts: 41
Joined: Tue Sep 25, 2018 3:52 pm

Fri Jun 26, 2020 7:56 pm Change Time Zone

Vannel,
I had to embed fn2 into fn1 for it work.
Do you have any idea of why this could happen?
I'd have to see your actual code to answer that :)

HTH,

Richard
rtaylor
Community Advisory Board Member
Community Advisory Board Member
 
Posts: 1556
Joined: Wed Oct 26, 2011 7:40 pm

Fri Jun 26, 2020 8:06 pm Change Time Zone

I have attached the module (LabelEncoder.ecl) and the file which calls the "problematic function" (Test1.ecl). Within Test1.ecl, it is the call to "UnwrapEncoderKey" which creates an issue.

Let me know if you can use the uploaded files or if I should find another way to share the code (maybe through the udl cluster).


Best regards,

Vannel
Attachments
Test1.ecl
(1.3 KiB) Downloaded 25 times
LabelEncoder.ecl
(13.36 KiB) Downloaded 28 times
vzeufack
 
Posts: 41
Joined: Tue Sep 25, 2018 3:52 pm

Fri Jun 26, 2020 9:24 pm Change Time Zone

For me it seems like, within a module, function macros should be self contained to avoid any problems. If a function macro wants to call another function macro, the called function must be embedded in the caller. So, I cannot write a helper function which will be called by many other function macros within the same module. I do not know if that is true but I am having trouble to achieve that.

I made this simple code to validate the error:

Code: Select all
EXPORT TestModule := MODULE
  helperFn(params) := FUNCTIONMACRO
    Result := 'Helper function called: ' + params; 
    RETURN Result;
  ENDMACRO;

  EXPORT testFn(params) := FUNCTIONMACRO
    Result := helperFn(params);  //Unknown identifier helperFn
    RETURN Result;
  ENDMACRO;
END;

//I called the TestFn function in another file as follows
Result := $.TestModule.TestFn('Success');

// **** I am getting that same error 'Unknown identifier helperFn' *******


Note that I am getting the error whatever the visibility of helperFn (default, SHARED or EXPORT).

I will repeat code for now or embed the function.

Please let me know if you have any clue about what I am doing wrong.


Best regards,

Vannel
vzeufack
 
Posts: 41
Joined: Tue Sep 25, 2018 3:52 pm

Fri Jun 26, 2020 9:29 pm Change Time Zone

Vannel,

OK, it appears on a quick first examination that you're using Template language to generate ECL code in your FUNCTIONMACROs. So the MODULE structure does syntax check (generated code only gets syntax checked on compile), but when you use it in a workunit that generated code looks to me like it's generating circular calls and that is the reason for your problem.

I'll be on PTO all next week, so I hope this helps you figure out how to correct the issue.

HTH,

Richard
rtaylor
Community Advisory Board Member
Community Advisory Board Member
 
Posts: 1556
Joined: Wed Oct 26, 2011 7:40 pm

Fri Jun 26, 2020 9:39 pm Change Time Zone

Can you try to explain based on this example which does not use template language?

Code: Select all
EXPORT TestModule := MODULE
  helperFn(params) := FUNCTIONMACRO
    Result := 'Helper function called: ' + params;
    RETURN Result;
  ENDMACRO;

  EXPORT testFn(params) := FUNCTIONMACRO
    Result := helperFn(params);  //Unknown identifier helperFn
    RETURN Result;
  ENDMACRO;
END;

//I called the TestFn function in another file as follows
Result := $.TestModule.TestFn('Success');

// **** I am getting that same error 'Unknown identifier helperFn' *******


Wish you a restful PTO :)
vzeufack
 
Posts: 41
Joined: Tue Sep 25, 2018 3:52 pm

Mon Jun 29, 2020 7:02 pm Change Time Zone

Vannel,

This code works for me:
Code: Select all
TestModule := MODULE
  EXPORT helperFn(params) := FUNCTIONMACRO
    Result := 'Helper function called: ' + params;
    RETURN Result;
  ENDMACRO;

  EXPORT testFn(params) := FUNCTIONMACRO
    Result := TestModule.helperFn(params);  //Unknown identifier helperFn
    RETURN Result;
  ENDMACRO;
END;

TestModule.TestFn('Success');
You'll note that I made the helperFn an EXPORT definition and called it with a fully qualified pathname. This is necessary because a FUNCTIONMACRO is a code generator that generates its code where it is called. That means the call is outside the MODULE structure, so the helperFn() call is out of scope at that point. But making helperFn() EXPORT and calling it fully qualified means it can be found wherever the first FUNCTIONMACRO is called.

HTH,

Richard
rtaylor
Community Advisory Board Member
Community Advisory Board Member
 
Posts: 1556
Joined: Wed Oct 26, 2011 7:40 pm

Mon Jun 29, 2020 7:06 pm Change Time Zone

Thanks Richard!

I was indeed suspecting that something of the like was happening. Thanks for your help.


Best regards

Vannel
vzeufack
 
Posts: 41
Joined: Tue Sep 25, 2018 3:52 pm

Next

Return to ECL

Who is online

Users browsing this forum: Google [Bot] and 0 guests

cron