Writing it all to the files
Now, we will see how the write_module
method of the write_morpho
method (actually called write_python
to use gen.py
as is) writes all the functions to the .c
, .h
and .md
files.
The full structure, although long, is pretty straightforward:
# GenApi.py
class API:
...
def write_python(self):
"""
This method is actually `write_morpho`, but is named `write_python` so that
we can run `gen.py` directly without modification.
"""
method_names = [] # List to collect method names
def collect_list_of_outputs(oargs):
"""
Collect outputs in a Morpho list
"""
def return_list_of_outputs():
"""
Return the list of outputs
"""
...
def write_module(module, c_namespace):
# Collect all the inputs
iargs = ...
oargs = ...
# Colelct all the outputs
#
# Create the Morpho function name
# Write help for this function to the file
fnamemorpho = ...
method_names.append(fnamemorpho)
# Write function definition to the C-file
# Write checks for number and type of input arguments
# Capture all the inputs
for i,iarg in enumerate(iargs):
self.fwrite(f, iarg.capture_input(i))
# Initialize the outputs
for i,oarg in enumerate(oargs):
self.fwrite(f, oarg.init_output())
# Create the C function call
# Write the function call, accounting for direct return values if any.
# Capture and return output
# Write the return statement
if len(oargs)==0 and not rtype: ## If there's nothing to return, return MORPHO_NIL
self.fwrite(f, INDENTL1 + "return MORPHO_NIL;\n")
elif len(oargs)==0 and rtype: ## If there are no outputs, but the function returns something, return the value
self.fwrite(f, INDENTL1 + f"return {rtype.cToMorphoConverter}(outval);\n")
for oarg in oargs: ## If there are outputs, we need to first capture them as Morpho values.
self.fwrite(f, oarg.capture_output())
if (len(oargs)==1): ## If there's only one output, return it
self.fwrite(f, oargs[0].return_output())
elif (len(oargs)>1): ## If there are multiple outputs, collect them in a Morpho List and return it
collect_list_of_outputs(oargs)
return_list_of_outputs()
# Recursively write all the submodules
for m in module.submodules:
write_module(m, c_namespace)
# We will first write to the C and MD files simultaneously, and collect the function names, etc for writing the Header file
# Simultanously open the C file and the help file as we need to add the methods one by one
with open("../src/" + f"{EXTENSION_NAME}.c", "w") as f, \
open("../share/help/" + f"{EXTENSION_NAME}.md", "w") as hlp:
# Write header-material to the files
# Write all the modules
# Write the footer for the C file
# Write the initialize method
# Add all the functions
for method in method_names:
self.fwrite(f, INDENTL1 + f"builtin_addfunction({method.upper()}_FUNCTION, {method}, BUILTIN_FLAGSEMPTY);\n")
# Add the error definitions.
self.fwrite(f, cmorpho_error_def)
self.fwrite(f, "\n}\n")
# Write the finalize method
self.fwrite(f, cmorpho_footer)
# Now, write the header file
with open("../src/" + f"{EXTENSION_NAME}.h", "w") as fh:
# Write the header-material for the header file
# This currently also defines the Errors.
for method in method_names:
# Define all the function names
# And that's it!