MFP language Help: citingspace and using citingspace Statements
User may have noticed that, from v. 1.7, MFP programming is slightly different from before. For example, in old user manual(s), sample function names always start from mfpExample_. This avoids name conflict between sample functions and user defined functions.
From v. 1.7, sample function names do not start with mfpExample_. In the above example, testing function name is as simple as testHelp. Therefore, How the MFP programming language identifies different testHelp functions if user also defines a function with the same name, and accidentally it has the same number of parameters as the sample function?
A good approach is using different citingspaces for these functions. MFP believes they are the same if, and only if, two functions are within the same citingspace, share the same name and have the same number of parameters. For example, starting from this version, all the sample functions are defined in citingspace ::mfpexample. To this end, citingspace ::mfpexample is added to the head of all the sample source files, and endcs clause is appended to the tail. This means, all the sample functions included in this manual are defined / implemented in citingspace ::mfpexample. There would be no name conflict even if other citingspaces include same name functions.
Citingspace is a concept of hierarchy. The name of the top level citingspace is an empty string. If in an mfps file no citingspace is declared, MFP believes all the defined functions in this source file are located in the top level citingspace.
Inside the top level citingspace is where lower level citingspaces are defined. MFPExample is a typical example of lower level citingspace. Note that citingspace name, like function name, is case insensitive so that MFPExample is the same as mfpexample or MfpExample.
Usually user has to use its absolute citingspace path to locate a particular citingspace. Construction of absolute citingspace path is:
top_level_citingspace_name::lower_level_citingspace_name::further_lower_level_citingspace_name::……::target_citingspace_name
. In the above example, citingspace mfpexample is one level lower than top level citingspace so that its absolute path is ::mfpexample. The top level citingspace name is an empty string so that nothing is before the double colons (::).
When user runs an MFP sample function, the citingspace has to be explicitly included. For example, the following function has been defined in the citingspace ::mfpexample:
Function testCS1(a)
print("This is ::mfpexample::testCS1, a=" + a + "\n")
endf
. If user wants to call the above function, the command should be ::mfpexample::testCS1(a). In other words, it is absolute citingspace path followed by double colons (::) plus function name and parameters.
The question is, How does MFP keep backward compatible with old source codes developed when citingspace was unavailable?
The solution is using default citingspaces. If a function is defined inside in a default citingspace, or a function’s citingspace is a child/grand-child citingspace of a default citingspace, absolute citingspace path is not required in the calling statement.
In version 1.7, MFP’s default citingspaces are the top level citingspace, mfp citingspace (::mfp) and all the sub citingspaces below mfp. Any function defined in these citingspaces needs no citingspace path when being called.
In version 1.6.7 or older, no mfps source file includes citingspace declaration. In version 1.7, all the functions in these mfps files are assumed to be located in the top level citingspace. Because top level citingspace is an MFP default citingspace, no citingspace path is required when a function is called.
Assume, for example, user defined a function named Myf_abc() in Scientific Calculator Plus 1.6.7, and called this function in some other functions. Clearly, the calling statement is my_abc(). In the new Scientific Calculator Plus (version 1.7 or newer), user can still call it in this way because my_abc() is defined in the top level citingspace. Nonetheless, including citingspace path, i.e. ::my_abc() is also valid.
The built-in and predefined functions in the new Scientific Calculator Plus are placed in a child (or grandchild) citingspace of ::mfp. For example, function tan(x) in MFP version 1.7 is located at ::mfp::math::trigon, and function log(x) is placed in ::mfp::math::log_exp. Because all these functions are in an MFP default citingspace, no citingspace path is required when calling any of these functions. Again, this feature keeps backward compatibility.
From version 2.0, MFP starts to support Object-Oriented Programming. class statement has been introduced since then. class is compatible with citingspace. Actually a class is a citingspace. All the static functions inside a class can be accessed by their citingspace paths. However, non-static member functions cannot be accessed by this means as they need an object of the class to be referred to. Also, please note that at this moment static member variables are not supported so that all the member variables cannot be accessed by citingspace path. The following code is an example.
class ABC
Function f0()
print("\nThis is ::ABC::f0()\n")
endf
Function f1(self)
print("\nThis is ::ABC::f1(self)\n")
Endf
endcs
In the above code, it is valid to call f0() using ::ABC::f0(). But developer cannot call f1 in this way as function f1 needs object of class ABC to be referred to.
Besides default citingspaces, user is able to insert additional citingspaces into the citingspace searching list. To this end, using citingspace statement is required. For example, using citingspace ::abcd tells MFP citingspace ::abcd is also in the searching list besides top level citingspace, ::mfp and its child citingspaces.
Both citingspace statement and using citingspace statement can use relative citingspace. For example, in citingspace ::mfpexample, user defines another citingspace abcd as below:
citingspace Abcd
Function testCS1(a)
print("\nThis is ::mfpexample::abcd::testCS1, a=" + a + "\n")
endf
Endcs
. Here Abcd is a relative citingspace path. Because citingspace abcd is defined in citingspace ::mfpexample, its absolute citingspace path is ::mfpexample::abcd.
For another example, assume user calls function abcd::testCS1(a) in a function located in ::mfpexample. Also assume no using citingspace statement is before the calling statement. Then the relative citingspace used in the calling statement equals to citingspace ::mfpexample::abcd, and the whole calling statement can be converted to ::mfpexample::abcd::testCS(a).
If user defines a several level citingspace hierarchy, and declares a few used citingspaces (with using citingspace statements) in each citingspace structure, then the citingspace searching order should be:
1. The direct (i.e. Innermost) citingspace of a function call;
2. Used citingspaces (by calling using citingspace statement) in the innermost code block of the function call. Note that the using citingspace statements have to be above the function call. Closer to the function call, higher searching priority the used citingspace has;
3. Used citingspaces (by calling using citingspace statement) in the upper code block(s) of the function call. Clearly, used citingspaces in an outer code block has lower searching priority than used spaces in an inner code block. Moreover, the using citingspace statements have to be above the function call. And closer to the function call, higher searching priority the used citingspace has;
4. Used citingspaces inside the direct citingspace of the calling function but out of the calling function body. Similar to the above points, the using citingspace statements have to be above the function call. And closer to the function call, higher searching priority the used citingspace has;
5. Non-direct citingspaces of the calling function (i.e. The citingspaces until the top level citingspace that include the innermost citingspace) and used citingspaces in each non-direct citingspace. Note that the priority in detail is innermost non-direct citingspace (i.e. The citingspace right above the direct citingspace) > used citingspaces in this citingspace > upper level citingspace > used citingspaces in the upper level citingspace ……. For example, assume a citingspace hierarchy in an mfps file is:
Citingspace level1 //absolute path is ::level1
Using citingspace aaaa //absolute path is ::level1::aaaa
Using citingspace bbbb //absolute path is ::level1::bbbb
Citingspace level2 //absolute path is ::level1::level2
Using citingspace cccc //absolute path is ::level1::level2::cccc
Using citingspace dddd //absolute path is ::level1::level2::dddd
Citingspace level3 //absolute path is ::level1::level2::level3
Function asmallfunc()
endf
Endcs
Endcs
Endcs
. Also assume the mfps file only includes the above code. Then from function asmallfunc’s perspective, the searching order of the citingspaces is:
::level1::level2::level3 > ::level1::level2 >
::level1::level2::dddd > ::level1::level2::cccc > ::level1 >
::level1::bbbb > ::level2::aaaa > top level citingspace.
Note that from version 2.0, MFP starts to support object oriented programming. Keyword class has been introduced since this version. A class can be looked on as a citingspace with exactly the same name as the class name. However, as elements in citingspace are static, developer can only access static member functions in a class via its citingspace path. Also, at this moment MFP doesn’t support static member variables so no way to access a member variable via its citingspace path.
6. MFP’s default citingspaces.
User has to keep in mind a few things. First of all, if using citingspace statement with a low priority citingspace is called well above a function call, from the function call’s perspective, the priority of the citingspace is enhanced. For example, a function is defined in citingspace ::aaaa. This function is going to call another function. Before the function call, a using citingspace statement introduces ::bbbb in the citingspace searching list. The sourcecode would be like:
Citingspace ::aaaa
……
Function callsomething()
……
Using citingspace ::bbbb
Anotherfunc() // here function callsomething calls Anotherfunc()
……
Endf
……
Endcs
.Clearly, in the above example, when Anotherfunc() is called, the citingspace searching order is (from highest to lowest):
1. ::aaaa
2. ::bbbb
3. Top level citingspace
4. Citingspace ::mfp and its children
. If user adds another using citingspace statement below using citingspace ::bbbb,the modified source code would be:
Citingspace ::aaaa
……
Function callsomething()
……
Using citingspace ::bbbb
Using citingspace // this means using top level citingspace
AnotherFunc() // here function callsomething calls Anotherfunc()
……
Endf
……
Endcs
. Because statement using citingspace is closer to function call (i.e. statement AnotherFunc()) than statement using citingspace ::bbbb, the top level citingspace now has higher searching priority than citingspace ::bbbb. Now the new citingspace searching order becomes (from highest to lowest):
1. ::aaaa
2. Top level citingspace
3. ::bbbb
4. Citingspace ::mfp and its children
. Also note that the top level citingspace still has lower priority than ::aaaa because it is the innermost, i.e. direct, citingspace of the function. Direct citingspace always has the highest searching priority.
Second is the code block. A block of code is a part of program with beginning and end statements. For example, code between function/endf is a code blog. Other code block boundary statement pairs include if/endif (or if/elseif, if/else, elseif/elseif, elseif/else, elseif/endif and else/endif), for/next, while/loop, do/until, try/catch, catch/endtry and select/ends. Code block can be nested. For example,
If a == b
For idx = 0 to 10 step 1
Next
Endif
Is a for block nested in an if block. In MFP language, using citingspace statements in outer blocks are always visible to function calls in inner blocks if they are above the function calls. Nevertheless, outer blocks used citingspaces have lower searching priority than inner blocks used citingspaces. Comparatively, using citingspace statements in inner blocks are invisible to function calls in outer blocks regardless of their places (i.e. above or below the function calls).
Now assume user declares using citingspace ::aaaa in the if block, and declares using citingspace ::bbbb in the for block. Then in the for block the searching order is ::bbbb first and ::aaaa second, while in the if block only ::aaaa is searched.
If a == b
// visible to for block, but lower priority
Using citingspace ::aaaa
For idx = 0 to 10 step 1
// invisible to if block
Using citingspace ::bbbb
Next
Endif
Third, citingspace searching order in one mfps file has no effect on another mfps file. Consider, for example, two mfps files. Content of one file is:
Citingspace ::aaaa
Using citingspace ::bbbb
Citingspace ::cccc
Function funcA()
Endf
Endcs
Endcs
. Another file is:
Citingspace ::aaaa
Citingspace ::cccc
Using citingspace ::bbbb
Function funcB()
Endf
Endcs
Endcs
. Then from function funcA’s perspective, citingspace searching order is ::cccc > ::aaaa > ::bbbb. From function funcB’s perspective, citingspace searching order is ::cccc > ::bbbb > ::aaaa.
Fourth, all the functions in a citingspace are visible if the citingspace is used, even if the functions are defined in different mfps files. In the above example, funcB is located in a different mfps file from funcA. However, because funcB is defined in citingspace ::bbbb and funcA uses this citingspace, funcB is visible to funcA. And funcA can call funcB without explicitly providing funcB’s citingspace path. Certainly, here we assume there is no another funcB without any parameter defined in citingspace ::cccc.
Fifth, citingspace can only be declared in mfps source files. It cannot be used in any other places. However, using citingspace statement can be used in the Command Line tool and JAVA based Scientific Calculator Plus. It cannot be used in Smart Calculator. In these interactive tools, user can use command
Shellman list_cs
to check all the citingspaces used, and use
Shellman add_cs citingspace_path
to add a new citingspace in the citingspace searching list. Here citingspace_path is a relative or absolute citingspace path. This command is the same as using citingspace statement.
User can also delete a used citingspace from citingspace searching list by command
Shellman delete_cs
. When using citingspace statement (or shellman add_cs command) is called in Command Line or JAVA based Scientific Calculator Plus, a new citingspace searching path is added. However, the newly added citingspace always has lower priority than the top level citingspace because the top level citingspace is the direct citingspace of the commands. And also because of this reason, when user inputs a command in Command Line or JAVA based Scientific Calculator Plus, the first two colons (::) are negligible. For instance, assume a function with full citingspace path is defined as ::abcdef::ghijk::lmn(a,b). In Command Line or JAVA based Scientific Calculator Plus, user is able to input, like abcdef::ghijk::lmn(1,2), to call this function. This is the same as inputting ::abcdef::ghijk::lmn(1,2).
The last thing user has to keep in mind is that citingspace and using citingspace cannot be used in solve block.
The follows are a citingspace example. This example can be found in the examples.mfps file in MFP fundamental sub-folder in the manual’s sample code folder.
Function testCS1(a)
print("This is ::mfpexample::testCS1, a=" + a + "\n")
endf
citingspace Abcd
Function testCS1(a)
print("This is ::mfpexample::abcd::testCS1, a=" + a + "\n")
endf
Function testCS2(a, b)
print("This is ::mfpexample::abcd::testCS2, a="+a+", b="+ b+"\n")
endf
endcs
citingspace ::Abcd
Function testCS1(a)
print("This is ::abcd::testCS1, a=" + a + "\n")
endf
using citingspace abcd
Function testCSRef()
// get error here because testCS2(a,b) is only defined in citingspace
// ::mfpexample::abcd. Indeed using citingspace abcd has been declared
// before the function. This function is defined in citingspace ::Abcd
// . Because using citingspace abcd means use relative citingspace
// abcd, so the absolute citingspace should be ::Abcd + abcd =
// ::Abcd::abcd. This citingspace does not exist, so the function will
// fail.
testCS2(2,3)
endf
using citingspace ::mfpexample::abcd
Function testCSRef1()
// here testCS2(a,b) is called after citingspace ::mfpexample::abcd is
// declared to use. So MFP will be able to find the right function
// which is ::mfpexample::abcd::testCS2
testCS2(2,3)
endf
endcs
citingspace ::__efgh__
Function testCSRef1()
// here the first testCS2(a,b) (testCS2 inside if block) is called
// after citingspace ::mfpexample::abcd is declared to use in the if
// block. So MFP will be able to find the right function which is
// ::mfpexample::abcd::testCS2. The second testCS2(a,b) is in the
// nested for block. Because the if block above the for block has
// declared to use ::mfpexample::abcd so the second testCS2(a,b) can
// still be found. However, the last testCS2(a,b) is out of if block
// so that it cannot see the using citingspace ::mfpexample::abcd
// statement so user will get error at the last testCS2 function.
variable a = 3
if a == 3
using citingspace ::mfpexample::abcd
print("::mfpexample::abcd is declared to use in this if block\n")
testCS2(2,3)
for variable idx = 0 to 1 step 1
print("::mfpexample::abcd is declared to use in the above if block\n")
testCS2(2,3)
next
endif
print("::mfpexample::abcd is not declared to use out of if block\n")
testCS2(2,3)
endf
Function testCSRef2()
variable a = 3
// call ::mfpexample::testCS1 because testCSRef2() is inside (both
// ::__efgh__ and) ::mfpexample. Citingspace ::__efgh__ has a higher
// priority than ::mfpexample. If there is function named testCS1
// with one parameter is defined in ::__efgh__ it will be called.
// However, there is not. So MFP looks for testCS1 with one parameter
// in citingspace ::mfpexample. And there is. So ::mfpexample::testCS1
// is called.
testCS1(a)
if a == 3
using citingspace ::abcd
// Because citingspace ::abcd has been explicitly declared to use
// in the innermost block, it has higher priority than
// ::mfpexample(but sill lower priority than the innermost
// citingspace declaration, in this case it is ::__efgh__). Thus
// ::abcd::testCS1 is called.
testCS1(a)
endif
using citingspace ::mfpexample::abcd
// citingspace ::mfpexample::abcd has been explicitly declared to use
// and it is the closest using citingspace statement to the below
// testCS1 function. As such ::mfpexample::abcd has higher priority
// than any other citingspaces except ::__efgh__. Since ::__efgh__
// doesn't include a testCS1 function with a single parameter,
// ::mfpexample::abcd::testCS1 is called.
testCS1(a)
endf
endcs
using citingspace ::mfpexample::abcd
citingspace ::__efgh__
Function testCSRef3()
// function testCS2(a,b) is defined in the citingspace
// ::mfpexample::abcd and statement using citingspace ::mfpexample::abcd
// is called in the above citingspace, i.e. ::abcd (not the innermost
// citingspace, i.e. ::__efgh__, but ::abcd as a citingspace includes
// citingspace ::__efgh__) before this function call. Therefore, function
//testCS2(2,3) can be found.
testCS2(2,3)
endf
Endcs
In the Command Line tool or JAVA based Scientific Calculator Plus, if user runs ::mfpexample::testCS1(3), the output will be:
This is ::mfpexample::testCS1, a=3
, then if user inputs and runs
Using citingspace ::mfpexample
, the following message will be shown:
Citingspace has been added. Now it has higher priority than any other citingspace except the top one.
Then user may run testCS1(3) to see the same output as running ::mfpexample::testCS1(3).
If user runs abcd::testcs1(3), the output will be:
This is ::mfpexample::abcd::testCS1, a=3
. If user runs abcd::testcsref(), the following error message will be shown:
Function cannot be properly be evaluated!
In function abcd::testcsref :
D:\Development\NetBeansProjs\JCmdLine\build\scripts\manual_scripts\MFP fundamental\examples.mfps Line 275 : Invalid expression
Undefined function!
. However, if user runs abcd::testcsref1(), no error will be reported. The output will be:
This is ::mfpexample::abcd::testCS2, a=2, b=3
. If user runs __efgh__::testCSRef1(), the result will be:
::mfpexample::abcd is declared to use in this if block
This is ::mfpexample::abcd::testCS2, a=2, b=3
::mfpexample::abcd is declared to use in the above if block
This is ::mfpexample::abcd::testCS2, a=2, b=3
::mfpexample::abcd is declared to use in the above if block
This is ::mfpexample::abcd::testCS2, a=2, b=3
::mfpexample::abcd is not declared to use out of if block
Function cannot be properly be evaluated!
In function __efgh__::testcsref1 :
D:\Development\NetBeansProjs\JCmdLine\build\scripts\manual_scripts\MFP fundamental\examples.mfps Line 318 : Invalid expression
Undefined function!
. If run __efgh__::testCSRef2(), the result will be:
This is ::mfpexample::testCS1, a=3
This is ::abcd::testCS1, a=3
This is ::mfpexample::abcd::testCS1, a=3
. If run __efgh__::testCSRef3(), the result will be:
This is ::mfpexample::abcd::testCS2, a=2, b=3