Reprint Source: http://my.oschina.net/xhan/blog/309613
Description: This document is a lua.ps file in the doc directory of Lua1.1.
At the same time this document can be found here: http://www.lua.org/semish94.html
The original copyright belongs to the original author, this translation is only used as a learning. If the translation is inappropriate, please refer to the original text.
--------------------The following is the body------------------
Design and implementation of application extension language
Summary. We describe the design and implementation of Lua, a simple and powerful application extension language. Although Lua is a programming language, it has data-describing capabilities and has been widely used in several production tasks, including user configuration, generic data entry, user interface descriptions, description of application objects, and storage of structured graphics meta-files.
--------------------------------------
Brief introduction
--------------------------------------
There are a growing number of custom application requirements. As applications become more complex, customizing with simple parameters becomes less likely: users now want to decide which configuration to use while the program is running, and users want to write macros and scripts themselves to increase productivity (Ryan 1990). As a result, today's larger applications almost always provide the end user with a configuration or scripting language to scale. These languages are usually simple, but each has its own syntax. Therefore, the user must learn a new language for each of the programs that should be developed (developers also have to design, implement, and debug a new language for each application).
Our first proprietary scripting language experience comes from a data entry application, and we've programmed a very simple declarative language (Figueiredo–souza–gattass–coelho 1992) for this. (The field of data entry is urgently needed for user-defined actions, since pre-coded validation tests cannot overwrite all applications). When users asked for more and more features to be added to the language, we decided we needed a more generic language and started designing a common embedded language. At the same time, another declarative language is added to a different application for data description. Therefore, we decided to combine the two languages and add the data description function to the Lua programming language. Lua has surpassed its original purpose and is used in other industrial projects.
This document describes the design decisions and implementation details of Lua.
--------------------------------------
Extended language
--------------------------------------
The use of application extension languages is now considered an important design technique: it makes the design of the application clearer and provides a personalized configuration for the user. Since most of the extended languages are simple and specific to a task, they are called "small Languages" (Bentley 1986; Valdés 1991). It corresponds to the "big" language in which the application is written, the mainstream language. This difference is not obvious today, because the main part of multiple applications is actually written in the extended language. There are several extended languages:
Configuration language: Parameter selection, usually implemented as a command line argument list or read from the configuration file key value pairs (for example: DOS Config.sys, ms-windows. ini file, X11 resource file, Motif UIL file); scripting language: Automated tasks, limited flow program control such as a batch file for DOS or a variety of Unix shells;
Macro language: Also for automation tasks, but usually only as a series of sequential execution of basic operations, no process control;
Embedded language: Based on the interface provided by the application, the user can customize the function to extend the application. These languages are often simplified mainstream programming languages such as LISP and C variants, with very powerful features.
The embedded language differs from the standalone language in that the embedded language can only be embedded in the host to work because it is called embedded programming. In addition, the host program typically provides a specific domain extension for the embedded language, creating a specific version of the embedded language by providing a higher level of abstraction. To do this, an embedded language has both its own programming syntax and an API that interacts with the host. Therefore, unlike the simple extended language that is used to provide the host with parameter values or a sequence of operations, there is a two-way communication between the embedded language and the host program. Note that the application programmer interacts with the embedded language using the main programming language that writes the host program, and the end user interacts with the application using only the embedded language.
LISP is usually a popular choice for extended languages because of its simple, easy-to-parse syntax and built-in extensibility (Beckman 1991; Nahaboo). For example, the main part of Emacs is actually written by its own LISP variant, and other text editors follow the same selection. However, when used for customization, LISP cannot be called user-friendly. C and Shell are also not called user-friendly, the latter's language is even more complex and less common.
One of the basic ideas for designing Lua is that it should have a clear but common syntax: we quickly chose a simplified class Pascal syntax for it. We avoid choosing the syntax based on LISP or C, because it can deter non-programmer users. Therefore, Lua is a programming language first. However, as mentioned earlier, Lua's ability to describe data has increased its ability to express itself.
--------------------------------------
Concept
--------------------------------------
Lua is a general-purpose embedded programming language that supports procedural programming and data-describing functions. As an embedded language, LUA does not have the concept of "main" function; it can only be embedded in the host (Lua is provided as a C function library and linked to the host application). The host can execute a LUA code that can read and write Lua variables, and can register C functions called by LUA code. By registering the C function, Lua can expand itself to cope with different domains, creating a customizable, shared syntax framework for programming languages (Beckman 1991).
This section contains an introduction to the main concepts of Lua. Include some practical example code to appreciate the language's style. The precise definition of the language is visible in the Language Reference manual (Ierusalimschy–figueiredo–celes 1994).
-------------------
Grammar
-------------------
As mentioned earlier, we explicitly designed Lua to have a simple, common syntax. Lua supports a common set of statements with implicitly but explicitly-closed block structures. Simple statements include simple assignments, control structures such as While-do-end, Repeat-until, if-then-elseif-else-end, and function calls. Non-common statements include multiple assignments, local variable declarations, local variables can be placed anywhere within the block, and table constructors, which can include user-defined validation functions (see below). In addition, Lua functions can have a variable number of parameters and can return multiple values. This avoids passing arguments by reference when multiple results need to be returned.
-------------------
Environment and modules
-------------------
All of the statements in Lua are executed in a global environment. This global environment holds all of the global variables and functions initialized at the beginning of the embedded language execution and continues to the end. This global environment can be managed with LUA code or embedded programs, and the global variables can be read and written through the LUA implementation library.
The execution unit of Lua is called a module. A module can contain statements and function definitions, either in a file or in a string in a host program. When executing a module, all of its functions and statements are compiled, functions are added to the global environment, and the statements are executed sequentially. All modifications to the global environment are persisted by the module, which remains visible after the module is finished. Modifications include the modification of global variables and the definition of new functions (the definition of a function is actually the assignment of a global variable.) See below)
-------------------
Data types and variables
-------------------
Lua is a dynamic type language: There are no types for variables, only values have types. All values contain their own type. All, there is no type definition in the Lua language. There is no variable type, and nothing seems to be a significant factor in simplifying the language; many types of languages are often used as an important feature when cropping as an extended language. In addition, Lua has garbage collection. It tracks which values are used and discards those that are not used. This avoids the need for explicit memory allocations, the main source of programming errors. There are seven basic data types in Lua:
Nil: Single value type nil;
Number: floating point number;
String: an array of characters;
Function: User-defined functions;
Cfunction: The function provided by the host program;
UserData: Host data pointer;
Table: Associative array.
Lua provides some automatic type conversions. If possible, a string is converted to numeric when it participates in numeric operations. Conversely, a value is converted to a string when it is used where it is supposed to be a string. This is useful for conversions because it simplifies programming and avoids the need for explicit conversion functions.
Global variables do not need to be declared, only local variables are required. Any variable is assumed to be global unless explicitly declared as a local variable. A local variable declaration can be placed anywhere within a block. Because only local variables need to be declared, the declaration of a variable can be placed close to where it is used. Therefore, it is usually simple to judge that a given variable is local or global.
The value of the variable is nil before the first assignment. As a result, there is no uninitialized variable in Lua, another major source of programming errors. However, the only valid operation of nil is assignment and equality testing (the main attribute of nil is different from any other value). Therefore, using an uninitialized variable (for example, an arithmetic expression) when an "actual" value should be used would result in an execution error, reminding the programmer not to initialize the variable correctly. Therefore, the purpose of automatically initializing the variable to nil is not to encourage the programmer not to initialize it before using the variable, in order to allow Lua to indicate that it is using an uninitialized variable.
Functions in Lua are the first class of values (first-class values): they can be stored in variables, passed as arguments to other functions, or returned as results. When a function is defined, its function body is compiled and stored in a global variable of the given name. Lua can invoke (and manipulate) a function written in Lua or C; the latter is of type cfunction.
The UserData type allows the LUA variable to hold arbitrary C pointers (void*), and the operations that are valid in Lua are allocation and equality tests.
The table type is implemented as an associative array, which is an array that can be indexed by numbers and strings. Therefore, the type can be used not only to represent ordinary arrays, but also to represent symbol tables, collections, records, and so on. To represent a record, Lua uses the field name as subscript. Language by providing a.name this expression as a["name" of the syntactic sugar.
Associative arrays are a powerful language structure, and many algorithms are simplified because the data structures and algorithms needed to search for them are provided by the language (Aho–kerninghan–weinberger 1988; Bentley 1988). For example, the core of a program that records the number of occurrences of a word in text can be written as table[word] = Table[word] + 1 without having to search for a list of words. (However, alphabetical reports require some real work because the indexes in Lua tables are arbitrarily sorted.) )
Tables can be created in a variety of ways. The simplest method corresponds to a normal array:
t = @ (100)
Such an expression generates a new, empty table. The size of the table (in the example above is 100) is optional and can give a hint to the size of the initial table. Tables in Lua can be dynamically expanded as needed regardless of the initial size. Therefore, references to t[200] and t["Day" are completely valid.
There are two syntax for creating a table: one for the list (@[]) and one for the record (@{}). For example, it is easy to create an element of a table by providing it, such as
t = @["red", "green", "Blue", 3]
This code is equivalent to the following code
T = @ ()
T[1] = "Red"
T[2] = "green"
T[3] = "Blue"
T[4] = 3
In addition, you can provide user-defined functions when you create a list or record, such as
t = @colors ["Red", "green", "blue", "yellow"]
t = @employee {name= "John Smith", age=34}
Thus, the code for the employee record was equivalent to:
Here, both colors and employee are automatically called after the table is created. Such a function can be used to check the value of a field, create a default field, or use it for any other action that has side effects. Therefore, the code for the employee action record is equivalent to:
T = @ ()
T.name = "John Smith"
T.age = 34
Employee (t)
It is important to note that although there is no type declaration in Lua, there is a user-controllable type constructor for Lua because it has the function of automatically calling functions after table creation. This uncommon structure is a very powerful feature that can be represented when using Lua for declarative programming.
-------------------
Api
-------------------
There are some APIs in the C library that implement LUA that enable LUA and the host to interact (about 30 such functions). These functions enable LUA as an embedded language to handle the following tasks: To execute LUA code contained in a file or string, to convert values in C and Lua, to read and write LUA objects in global variables, to invoke LUA functions, and to register C functions that can be called in Lua, including error handlers. A simple Lua explanation can be written as follows:
#include "Lua.h"
int main (void)
{
Char s[1000];
while (gets (s))
Lua_dostring (s);
return 0;
}
This simple interpreter can add specific domain functions written in C and can be registered to LUA using the function Lua_register. Extension functions follow a specific protocol to receive and return values in Lua.
-------------------
Pre-defined functions and libraries
-------------------
Lua's set of predefined functions is small but powerful. Most of them provide a degree of reflexivity to the language. These features cannot be simulated by other parts of the language or through standard API simulations. Predefined functions can handle the following tasks: Executing a Lua module contained in a file or string, traversing all the fields of a table, enumerating all global variables, type queries, and transformations.
Library, on the other hand, provides a useful program that is implemented through a standard API. Therefore, they are not part of the language required and are provided as a separate C module, which can be connected to the application as needed. Currently, there are string processing libraries, mathematical function libraries, input and output libraries.
-------------------
Persistence of
-------------------
Enumeration functions can be used to persist the LUA Global environment, which can write LUA code and restore the values of all global variables at execution time. We now show some ways to store and restore values in Lua, using LUA-written text files as the storage medium. The values saved in this way can also be easily restored back.
To save a key-value pair, you can use the following code:
function store (name, value)
Write (Name: ' = ')
Write_value (value)
End
Here, "..." is a string connection operation, write is the library function used to output. The function write_value outputs an appropriate format based on the type of value, and the type of value can be obtained using a predefined function type:
function Write_value (value)
Local T = Type (value)
If T = ' nil ' then write (' nil ')
ElseIf t = ' number ' then write (value)
ElseIf t = ' string ' Then write (' "': Value: ‘"‘)
End
End
The storage table is a bit complicated. First, the Write_value Plus
ElseIf t = ' table ' then Write_record (value)
Assuming that the table is used as a record (that is, there are no circular references, all subscripts are identifiers), the table's values can be written in the table's constructor:
function Write_record (t)
Local I, V = next (t, Nil)--"Next" enumerates the fields of T
Write (' @{')--starts constructor
While I do
Store (I,V)
I, V = next (t, i)
If I then write (', ') end
End
Write ('} ')--closes constructor
End
(not to be continued)
Design and implementation of Lua1.1 Lua (i.)