Order of include_once

I'm trying to build up a bunch of scripts that include each other.

For this example, I have 3 scripts. main, utils and title.

main uses utils and title.
title uses utils.

When main includes both utils and title as shown, I get the error in the first screenshot.

image

When main does not include utils, it then works as expected as below.

image

Can someone explain this behaviour and suggest how I can get each individual formula to work with their includes without having ordering of includes dependent on the main formula.

Thanks!

[edit]
I have read the doco for AFL Function Reference - #INCLUDE_ONCE and AFL Function Reference - #INCLUDE and searched this forum, but have been unable to find what I'm after which is how #include_once includes files.

Essentially what I'm after is the ability to include a file the first time it is seen and only that time.

So I did a little more digging by logging the top of files:

image

It turns out that, even if title.afl includes utils.afl, it does not evaluate the include before executing the code after it.

This behaviour is not seen in the main.afl script. If I were to put the util_filenameFromPath in main.afl after the include_once, then it evaluates the includes before running the util function and does not error out.

#include does not support circular references (fileA including fileB and fileB including fileA). I don't remember (I wrote this part 10+ years ago), but I doubt if there are no edge cases with _once mechanism that will cause trouble in complex scenarios.

It is strongly recommended to keep your includes simple and reduce number of includes as it takes time to process that many (file operations and memory allocations for each and every processed #include)

I think I have a theory for how include_once works. This is not a problem of circular reference as illustrated in my OP.

The situation is:

// x -> y : formula x include_once formula y
// x, y : include_once x, include_once y

Scenario 1:
A -> B
B -> C
// works as expected, A includes B and B includes C

Scenario 2:
A -> C, B
B -> C
// works as expected, A includes C then B ( in that order ), B includes C

Scenario 3:
A -> B, C
B -> C
// fails, A includes B then C, B includes C

Logically, scenario 3 should work, A includes B, and B includes C just like scenario 1.
However, I think what is happening is that the code is doing a breadth first parse of all the include_once of A and then going into each of the nested includes_once.

So for scenario 3, breadth first vs depth first approach for including files:

Scenario 3:
A -> B, C
B -> C

// breadth first, 
// i'm in A, I parse all of A first, so I parse B then C, then myself
B 
then C 
then A 
// I hit an error parsing B, because B needs C


// depth first, 
// I'm in A, I parse include_once as I go, so I parse B, but B includes C so I parse C
C 
then B 
then A 
// C is parsed first because it's included by B, is included by A, no dependency errors

This likely requires the change of one line, to move the parsing of the 'next' file into the loop where all include_once are being parsed, then it will go depth first.

Since #include and #include_once cannot be conditionally wrapped, I can't implement this myself in a formula so to get around it, what I'm doing now is to print the name of the formula at the top of each file and manually make sure, if i'm creating a new formula, to have it's includes in that same order.

1 Like

This topic was automatically closed 100 days after the last reply. New replies are no longer allowed.