A spreadsheet’s formula functions, contributed by add-ins
A spreadsheet evaluates formulas such as =SUM(1, 2) by finding the function a name stands for. The built-ins ship with it; add-ins the user enables bring more (a units add-in, an inventory add-in), and the formula engine must find them without knowing any of them, just as the lesson’s renderer finds a plugin’s shortcode. Each level starts from the previous level’s finished code, so you can begin at any of them.
Opening a workbook was slow, because each one loaded every add-in again, so a teammate’s pull request loads the built-ins and add-ins once, in an App, and every workbook uses the App’s registry. The same pull request adds workbook functions: names a user defines in a workbook’s Name Manager, such as DISCOUNT. To let the formula engine find them, it puts them into the App’s registry, and because reopening a workbook then failed with “DISCOUNT is taken by workbook”, it adds a define that replaces an entry. QA reports that one workbook’s functions appear in another. You are reviewing the pull request.
A formula in one workbook can compute with another workbook’s definition, or with a built-in a workbook replaced, depending on which workbooks happen to be open. Nothing shows an error.
Reproduce app = new App([units]); A = app.open("A", [DISCOUNT: 10% off]); B = app.open("B", []). B.evaluate("DISCOUNT", [100]) should be #NAME?, since only A defines it. Today it is 90.
Acceptance criteria A workbook’s own functions are found only in that workbook, and two workbooks may each define the same name for their own function. A workbook may not take a name the application already has (a built-in or an add-in’s): that definition is refused and recorded in the workbook’s refused list as “WORKBOOK refused: NAME is taken by OWNER”, and the application’s function stays, for that workbook and every other. Opening a workbook again, with the same definitions, works and refuses nothing. Each workbook’s picker lists the application’s functions and its own (owner workbook), in name order; the application still installs add-ins whole or not at all, and names still ignore case. Notes Each case starts one App with some add-ins, opens workbooks A and B in turn with their definitions, then prints each step’s result joined by “ | ”. refused on the App lists the add-ins it refused; on a workbook, the definitions it refused. Keep App, its constructor or NewApp or App::new, open, Workbook’s evaluate, functionNames and refused, and the AddIn, Function (Go) and Formula types; the checker calls them.