From 844b7f214836674101fae03aa572bd69394620ec Mon Sep 17 00:00:00 2001 From: AwesomeAdam54321 Date: Sat, 9 Mar 2024 11:59:09 +0800 Subject: [PATCH] foundation-module: Preliminaries: Nowebify. --- ...ation.w => A_Brief_Guide_to_Foundation.nw} | 208 +++++++++--------- 1 file changed, 104 insertions(+), 104 deletions(-) rename foundation-module/Preliminaries/{A Brief Guide to Foundation.w => A_Brief_Guide_to_Foundation.nw} (77%) diff --git a/foundation-module/Preliminaries/A Brief Guide to Foundation.w b/foundation-module/Preliminaries/A_Brief_Guide_to_Foundation.nw similarity index 77% rename from foundation-module/Preliminaries/A Brief Guide to Foundation.w rename to foundation-module/Preliminaries/A_Brief_Guide_to_Foundation.nw index 0d64c87..9bc6d6e 100644 --- a/foundation-module/Preliminaries/A Brief Guide to Foundation.w +++ b/foundation-module/Preliminaries/A_Brief_Guide_to_Foundation.nw @@ -2,7 +2,7 @@ A Brief Guide to Foundation. Notes on getting started with the Foundation library. -@h Introduction. +@ \section{Introduction.} The Foundation module supplies some of the conveniences of more modern programming languages to ANSI C. It offers the usual stuff of standard libraries everywhere: memory management, collection classes, filename and file @@ -25,28 +25,28 @@ can be found in //foundation-test//. @ To use //foundation//, a program must at minimum do three things. 1. The Contents section of its web must import Foundation as a module, thus: -= (text as Inweb) + Import: foundation -= + Import lines appear after the metadata, but before the roster of sections and chapters. -2. The constant |PROGRAM_NAME| must be defined equal to a C string with a +2. The constant [[PROGRAM_NAME]] must be defined equal to a C string with a brief version of the program's name. For example, -= (text as Inweb) - @d PROGRAM_NAME "declutter" -= -3. The |main| function for the client should, as one of its very first acts, -call |Foundation::start()|, and should similarly, just before it exits, call -|Foundation::end()|. Any other module used should be started after Foundation + @d PROGRAM_NAME "declutter" + + +3. The [[main]] function for the client should, as one of its very first acts, +call [[Foundation::start()]], and should similarly, just before it exits, call +[[Foundation::end()]]. Any other module used should be started after Foundation starts, and ended before Foundation ends. -@h Truth. +@ \section{Truth.} Every large C program starts by defining constants for truth and falsity. So -does Foundation: |TRUE|, |FALSE|, and a third state |NOT_APPLICABLE|. +does Foundation: [[TRUE]], [[FALSE]], and a third state [[NOT_APPLICABLE]]. -@h Text streams and formatted output. +@ \section{Text streams and formatted output.} Perhaps the most useful feature of Foundation is that it provides for memory-managed strings of Unicode text. These are unified with text files which are open for output, in a type called //text_stream//. It's expected @@ -54,38 +54,38 @@ that they may be very large indeed, and appending text to or finding the length of a text in memory runs in $O(1)$ time. A typical function writing to one of these might be: -= (text as InC) + void Hypothetical::writer(text_stream *OUT, text_stream *authority, int N) { WRITE("According to %S, the square of %d is %d.\n", authority, N, N*N); } -= -Here |WRITE| is a variadic macro rather like |printf|, and note the use of -the escape |%S| to write a text stream. It writes formatted output into the -stream |OUT|, and is actually an abbreviation for this: -= (text as InC) + +Here [[WRITE]] is a variadic macro rather like [[printf]], and note the use of +the escape [[%S]] to write a text stream. It writes formatted output into the +stream [[OUT]], and is actually an abbreviation for this: + void Hypothetical::writer(text_stream *OUT, text_stream *authority, int N) { WRITE_TO(OUT, "According to %S, the square of %d is %d.\n", authority, N, N*N); } -= -The function |Hypothetical::writer| can write equally to a text file or to a + +The function [[Hypothetical::writer]] can write equally to a text file or to a string, whichever it's given, and doesn't need to worry about memory management or text encodings. The standard output and standard error "files" on Unix-based systems are -referred to as |STDOUT| and |STDERR|, both constants of type |text_stream *| -defined by Foundation. The value |NULL|, used as a text stream, is valid and +referred to as [[STDOUT]] and [[STDERR]], both constants of type [[text_stream *]] +defined by Foundation. The value [[NULL]], used as a text stream, is valid and prints as the empty string, while ignoring any content written to it. All of these capitalised macros are defined in //Streams//. -|PRINT("...")| is an abbreviation for |WRITE_TO(STDOUT, "...")|, and -|LOG("...")| similarly writes to the log file. (See //Debugging Log//.) +[[PRINT("...")]] is an abbreviation for [[WRITE_TO(STDOUT, "...")]], and +[[LOG("...")]] similarly writes to the log file. (See //Debugging Log//.) @ If you're using //inweb: The InC Dialect//, the slight extension to C made by Inweb, there's a simple notation for constants of this type: -= (text as InC) + text_stream *error_message = I"quadro-triticale stocks depleted"; -= -The |I| prefix is meant to imitate the |L| used in standard C99 for long string + +The [[I]] prefix is meant to imitate the [[L]] used in standard C99 for long string constants. But this is a feature of //inweb// rather than of Foundation. @ Programs doing a lot of parsing need to create and throw away strings all @@ -95,20 +95,20 @@ existing one. But these are permanent creations, and not easy to deallocate (though calling //Str::clear// to empty out their text will free any large amount of memory they might be using). If you want a string just for a momentary period, do this: -= (text as InC) + TEMPORARY_TEXT(alpha) WRITE_TO(alpha, "This is temporary"); ... DISCARD_TEXT(alpha) -= -Between the use of these two macros, |alpha| is a valid |text_stream *|, + +Between the use of these two macros, [[alpha]] is a valid [[text_stream *]], and is a string capable of growing to arbitrary size. @ Foundation provides an elaborate system for providing new string escapes -like |%S|: see //Writers and Loggers//. A similar system manages a debugging +like [[%S]]: see //Writers and Loggers//. A similar system manages a debugging log, to which it's easy to make "dollar escapes" for pretty-printing internal -data structures: for example, if you've made a structure called |recipe|, you -could make |$R| pretty-print one. +data structures: for example, if you've made a structure called [[recipe]], you +could make [[$R]] pretty-print one. @ Foundation also has an extensive library of string-handling routines, providing the sort of facilities you would expect in a typical scripting @@ -122,129 +122,129 @@ For slicing, see the //string_position// type, representing positions for the benefit of functions like //Str::substr//. @ Individual characters are represented in Foundation using the standard -POSIX type |wchar_t|, which on all modern systems is a very wide integer, +POSIX type [[wchar_t]], which on all modern systems is a very wide integer, whether or not signed. It's safe to assume it can hold all normal Unicode code points. See //Characters// for class functions like //Characters::isdigit//, which have been carefully written to work equivalently on either Windows or Unix-based systems. //C Strings// and //Wide Strings// provide bare-minimum facilities for handling -traditional null-terminated |char| and |wchar_t| arrays, but don't use these. +traditional null-terminated [[char]] and [[wchar_t]] arrays, but don't use these. Texts are just better. -@h Objects. +@ \section{Objects.} To a very limited extent, Foundation enables C programs to have "classes", "objects" and "methods", and it makes use of that ability itself, too. (See //Foundation Classes// for the list of classes made by //foundation//.) For example, suppose we are writing a program to store recipes, and we want -something in C which corresponds to objects of the class |recipe|. We need to +something in C which corresponds to objects of the class [[recipe]]. We need to do three things: -1. Declare an enumerated constant ending |_CLASS| to represent this type in the +1. Declare an enumerated constant ending [[_CLASS]] to represent this type in the memory manager, and then make a matching use of a macro to define some associated functions, which we never see or think about. For example: -= (text as Inweb) + @ Here are my classes... @e recipe_CLASS = DECLARE_CLASS(recipe) -= + The mention of "individually" is because this is for data structures where we expect to have relatively few instances. If we expect to have huge numbers of throwaway instances, we would instead write: -= (text as Inweb) + @ Here are my classes... @e salt_grain_CLASS = DECLARE_CLASS_ALLOCATED_IN_ARRAYS(salt_grain, 1000) -= + The memory manager then claims these in blocks of 1000. Use this only if it's -actually needed; note that |DESTROY| cannot be used with objects created +actually needed; note that [[DESTROY]] cannot be used with objects created this way. -2. We have to declare the actual structure, and |typedef| the name to it. For +2. We have to declare the actual structure, and [[typedef]] the name to it. For example: -= (text as InC) + typedef struct recipe { struct text_stream *name_of_dish; int oven_temperature; CLASS_DEFINITION } recipe; -= -Here |CLASS_DEFINITION| is a macro defined in //Memory// which expands to the + +Here [[CLASS_DEFINITION]] is a macro defined in //Memory// which expands to the necessary field(s) to keep track of this. We won't use those fields, or ever think about them. -3. In fact we've now finished. The macro |CREATE(recipe)| returns a new -instance, and |DESTROY(R)| would destroy an existing one, |R|. Unless manually +3. In fact we've now finished. The macro [[CREATE(recipe)]] returns a new +instance, and [[DESTROY(R)]] would destroy an existing one, [[R]]. Unless manually destroyed, objects last forever; there is no garbage collection. In practice the Inform tools suite, for which Foundation was written, almost never destroy objects. -Customarily, though, we wrap the use of |CREATE| in a constructor function: -= (text as InC) +Customarily, though, we wrap the use of [[CREATE]] in a constructor function: + recipe *Recipes::new(text_stream *name) { recipe *R = CREATE(recipe); R->name_of_dish = Str::duplicate(name); R->oven_temperature = 200; return R; } -= -We also often use the convenient |LOOP_OVER| macro: -= (text as InC) + +We also often use the convenient [[LOOP_OVER]] macro: + void Recipes::list_all(text_stream *OUT) { WRITE("I know about the following recipes:\n"); recipe *R; LOOP_OVER(R, recipe) WRITE("- %S\n", R->name_of_dish); } -= -|LOOP_OVER| loops through all created |recipe| instances (which have not been + +[[LOOP_OVER]] loops through all created [[recipe]] instances (which have not been destroyed). There are a few other facilities, for which see //Memory//, and also ways to allocate memory for arrays -- see //Memory::calloc// and //Memory::malloc//. -@h Methods. +@ \section{Methods.} It's also possible to have method calls on object instances, though the syntax is not as tidy as it would be in an object-oriented language. To allow -this for |recipe|, we would have to add another line to the structure: -= (text as InC) +this for [[recipe]], we would have to add another line to the structure: + typedef struct recipe { struct text_stream *name_of_dish; int oven_temperature; struct method_set *methods; CLASS_DEFINITION } recipe; -= + and another line to the constructor function: -= (text as InC) + R->methods = Methods::new_set(); -= -The object |R| is then ready to receive method calls. Each different call needs -an enumerated constant ending |_MTID| to identify it, and an indication of the + +The object [[R]] is then ready to receive method calls. Each different call needs +an enumerated constant ending [[_MTID]] to identify it, and an indication of the type of the function call involved: -= (text as Inweb) + @ Here is my "cook the recipe" method call: @e COOK_MTID = VOID_METHOD_TYPE(COOK_MTID, recipe *R, int time_in_oven) -= + It's now possible to call this on any recipe: -= (text as InC) + VOID_METHOD_CALL(duck_a_l_orange, COOK_MTID, 45); -= + What then happens? Nothing at all, unless the recipe instance in question -- -here, |duck_a_l_orange| -- has been given a receiver function. Let's revisit +here, [[duck_a_l_orange]] -- has been given a receiver function. Let's revisit the constructor function for recipes: -= (text as InC) + recipe *Recipes::new(text_stream *name) { recipe *R = CREATE(recipe); R->name_of_dish = Str::duplicate(name); @@ -253,50 +253,50 @@ the constructor function for recipes: METHOD_ADD(R, COOK_MTID, Recipes::cook); return R; } -= + and now add: -= (text as InC) + void Recipes::cook(recipe *R, int time_in_oven) { ... } -= + using the arguments promised in the declaration above. With all this done, the effect of -= (text as InC) + VOID_METHOD_CALL(duck_a_l_orange, COOK_MTID, 45); -= + is to call: -= (text as InC) + Recipes::cook(duck_a_l_orange, 45); -= + @ In fact it's possible to attach multiple receivers to the same object, in which case they each run in turn. As a variant on this, methods can also return -their "success". If multiple receivers run, the first to return |TRUE| has +their "success". If multiple receivers run, the first to return [[TRUE]] has claimed the right to act, and subsequent receivers aren't consulted. -Such methods must be defined with |INT_METHOD_CALL| and are rarely needed. See +Such methods must be defined with [[INT_METHOD_CALL]] and are rarely needed. See //Methods// for more. -@h Collections. +@ \section{Collections.} Foundation provides three sorts of "collection": see //Linked Lists and Stacks//, and also //Dictionaries//. These all collect values which are expected to be -pointers: for example, text streams (of type |text_stream *|) or objects like +pointers: for example, text streams (of type [[text_stream *]]) or objects like the ones created above. For example, -= (text as InC) + linked_list *cookbook = NEW_LINKED_LIST(recipe); -= + initialises a list as ready to use. It's then accessed by macros: -= (text as InC) + recipe *lobster_thermidor = Recipes::new(I"lobster thermidor", 200); ADD_TO_LINKED_LIST(lobster_thermidor, recipe, cookbook); -= + Similarly: -= (text as InC) + recipe *R; LOOP_OVER_LINKED_LIST(R, recipe, cookbook) PRINT("I can make %S.\n", R->name_of_dish); -= + That's about all you can do with linked lists: they are not nearly so well worked-through as texts. @@ -310,7 +310,7 @@ able to hold a rooted tree in which nodes can be a variety of different objects, rather than having to be uniform. Functions are provided to build and verify such trees. -@h Files and paths. +@ \section{Files and paths.} Filenames and pathnames are, perhaps controversially, represented by two different types: //filename// and //pathname//. The latter should perhaps have been called "directoryname", but that ship has sailed. @@ -324,20 +324,20 @@ These both hold names, not actual files: they are places where files or directories might be. Both tend to refer relative to the current working directory, represented by -the null |pathname| pointer. //Pathnames::up// and //Pathnames::down// go +the null [[pathname]] pointer. //Pathnames::up// and //Pathnames::down// go to parent or subdirectories, respectively. A filename cannot exist without a pathname; for example, -= (text as InC) + pathname *P = Pathnames::down(NULL, I"App") P = Pathnames::down(P, I"Config") filename *F = Filenames::in(P, I"options.txt"); PRINT("I have arrived at %f.\n", F); -= -produces, on platforms where |/| is used as the file system dividing character, -= (text) + +produces, on platforms where [[/]] is used as the file system dividing character, + I have arrived at App/Config/options.txt. -= -Note the use of the escape |%f| for printing filenames; there's also |%p| for + +Note the use of the escape [[%f]] for printing filenames; there's also [[%p]] for pathnames. See //Filenames// and //Pathnames// for more. @@ -356,9 +356,9 @@ useful for testing the correctness of our tools. @ //Text Files// allows us to read text files. Its most useful function is //TextFiles::read//, which opens a file, can print an error if it doesn't exist, and if it does, then feeds the lines one at a time to an iterator. -For example, if |F| is a filename, the following reads the file into a +For example, if [[F]] is a filename, the following reads the file into a linked list of texts: -= (text as InC) + linked_list *Hypothetical::list_from_file(filename *F) { linked_list *L = NEW_LINKED_LIST(text_stream); TextFiles::read(F, FALSE, "can't open colony file", @@ -370,12 +370,12 @@ linked list of texts: linked_list *L = (linked_list *) v_L; ADD_TO_LINKED_LIST(text, line, L); } -= + The //text_file_position// here keeps track of where we are, and in particular, functions from //Error Messages// can then report errors where they occur: -= (text as InC) + Errors::in_text_file("bad syntax here", tfp); -= + @ The //Preprocessor// provides simple iteration and macro expansion in order to turn a marked-up script into a plain text file. @@ -383,7 +383,7 @@ to turn a marked-up script into a plain text file. @ See //JSON// for convenient ways to encode and decode data to the JSON interchange format. -@h Handling webs. +@ \section{Handling webs.} Foundation provides routines which can read the metadata of a web, i.e., a literate program in the //inweb// format, from a copy in the file system. The main function here is //WebMetadata::get//, which returns a //web_md// @@ -392,12 +392,12 @@ object. You can then access its bibliographic data using its modules (instances of //module//), chapters (of //chapter_md//) and sections (of //section_md//). -@h Miscellaneous other features. +@ \section{Miscellaneous other features.} What else? Well: (a) //Time// for the time of day and the date of Easter (no, really), and for timing internal program activity using //Time::start_stopwatch// and //Time::stop_stopwatch//; -(b) //Shell// for issuing shell commands via the C library's |system| function, +(b) //Shell// for issuing shell commands via the C library's [[system]] function, or its equivalent; (c) //HTML// and //Epub Ebooks// for generating web pages and ebooks; (d) //Image Dimensions// and //Sound Durations// for handling videos and music;