Mercurial Hosting > luan
changeset 1667:c55373c3a0ce
manual work
author | Franklin Schmidt <fschmidt@gmail.com> |
---|---|
date | Sun, 08 May 2022 22:50:48 -0600 |
parents | 8f38abaf779f |
children | ef75d9ad5ce9 |
files | website/src/m.html.luan |
diffstat | 1 files changed, 990 insertions(+), 0 deletions(-) [+] |
line wrap: on
line diff
diff -r 8f38abaf779f -r c55373c3a0ce website/src/m.html.luan --- a/website/src/m.html.luan Sat May 07 23:23:03 2022 -0600 +++ b/website/src/m.html.luan Sun May 08 22:50:48 2022 -0600 @@ -1376,6 +1376,996 @@ <% end } + logical_ops = { + title = "Logical Operators" + content = function() +%> +<p> +The logical operators in Luan are +<b>and</b>, <b>or</b>, and <b>not</b>. +The <b>and</b> and <b>or</b> operators consider both <b>false</b> and <b>nil</b> as false +and anything else as true. +Like the control structures (see <a href="#control">Control Structures</a>), +the <b>not</b> operator requires a boolean value. +</p> + +<p> +The negation operator <b>not</b> always returns <b>false</b> or <b>true</b>. +The conjunction operator <b>and</b> returns its first argument +if this value is <b>false</b> or <b>nil</b>; +otherwise, <b>and</b> returns its second argument. +The disjunction operator <b>or</b> returns its first argument +if this value is different from <b>nil</b> and <b>false</b>; +otherwise, <b>or</b> returns its second argument. +Both <b>and</b> and <b>or</b> use short-circuit evaluation; +that is, +the second operand is evaluated only if necessary. +Here are some examples: +</p> + +<pre> + 10 or 20 --> 10 + 10 or error() --> 10 + nil or "a" --> "a" + nil and 10 --> nil + false and error() --> false + false and nil --> false + false or nil --> nil + 10 and 20 --> 20 +</pre> + +<p> +(In this manual, +<code>--></code> indicates the result of the preceding expression.) +</p> +<% + end + } + concatenation = { + title = "Concatenation" + content = function() +%> +<p> +The string concatenation operator in Luan is +denoted by two dots ('<code>..</code>'). +All operands are converted to strings. +</p> +<% + end + } + length = { + title = "The Length Operator" + content = function() +%> +<p> +The length operator is denoted by the unary prefix operator <code>#</code>. +The length of a string is its number of characters. +The length of a binary is its number of bytes. +</p> + +<p> +A program can modify the behavior of the length operator for +any table through the <code>__len</code> metamethod (see <a href="#meta">Metatables and Metamethods</a>). +</p> + +<p> +Unless a <code>__len</code> metamethod is given, +the length of a table <code>t</code> is defined +as the number of elements in <em>sequence</em>, +that is, +the size of the set of its positive numeric keys is equal to <em>{1..n}</em> +for some non-negative integer <em>n</em>. +In that case, <em>n</em> is its length. +Note that a table like +</p> + +<pre> + {10, 20, nil, 40} +</pre> + +<p> +has a length of <code>2</code>, because that is the last key in sequence. +</p> +<% + end + } + precedence = { + title = "Precedence" + content = function() +%> +<p> +Operator precedence in Luan follows the table below, +from lower to higher priority: +</p> + +<pre> + or + and + < > <= >= ~= == + .. + + - + * / % + unary operators (not # -) + ^ +</pre> + +<p> +As usual, +you can use parentheses to change the precedences of an expression. +The concatenation ('<code>..</code>') and exponentiation ('<code>^</code>') +operators are right associative. +All other binary operators are left associative. +</p> +<% + end + } + constructors = { + title = "Table Constructors" + content = function() +%> +<p> +Table constructors are expressions that create tables. +Every time a constructor is evaluated, a new table is created. +A constructor can be used to create an empty table +or to create a table and initialize some of its fields. +The general syntax for constructors is +</p> + +<pre> + tableconstructor ::= ‘<b>{</b>’ fieldlist ‘<b>}</b>’ + fieldlist ::= [field] {fieldsep [field]} + field ::= ‘<b>[</b>’ exp ‘<b>]</b>’ ‘<b>=</b>’ exp | Name ‘<b>=</b>’ exp | exp + fieldsep ::= ‘<b>,</b>’ | ‘<b>;</b>’ | <b>end_of_line</b> +</pre> + +<p> +Each field of the form <code>[exp1] = exp2</code> adds to the new table an entry +with key <code>exp1</code> and value <code>exp2</code>. +A field of the form <code>name = exp</code> is equivalent to +<code>["name"] = exp</code>. +Finally, fields of the form <code>exp</code> are equivalent to +<code>[i] = exp</code>, where <code>i</code> are consecutive integers +starting with 1. +Fields in the other formats do not affect this counting. +For example, +</p> + +<pre> + a = { [f(1)] = g; "x", "y"; x = 1, f(x), [30] = 23; 45 } +</pre> + +<p> +is equivalent to +</p> + +<pre> + do + local t = {} + t[f(1)] = g + t[1] = "x" -- 1st exp + t[2] = "y" -- 2nd exp + t.x = 1 -- t["x"] = 1 + t[3] = f(x) -- 3rd exp + t[30] = 23 + t[4] = 45 -- 4th exp + a = t + end +</pre> + +<p> +The order of the assignments in a constructor is undefined. +(This order would be relevant only when there are repeated keys.) +</p> + +<p> +If the last field in the list has the form <code>exp</code> +and the expression is a function call or a vararg expression, +then all values returned by this expression enter the list consecutively +(see <a href="#fn_calls">Function Calls</a>). +</p> + +<p> +The field list can have an optional trailing separator, +as a convenience for machine-generated code. +</p> +<% + end + } + fn_calls = { + title = "Function Calls" + content = function() +%> +<p> +A function call in Luan has the following syntax: +</p> + +<pre> + functioncall ::= prefixexp args +</pre> + +<p> +In a function call, +first prefixexp and args are evaluated. +The value of prefixexp must have type <em>function</em>. +This function is called +with the given arguments. +</p> + +<p> +Arguments have the following syntax: +</p> + +<pre> + args ::= ‘<b>(</b>’ [explist] ‘<b>)</b>’ + args ::= tableconstructor + args ::= LiteralString +</pre> + +<p> +All argument expressions are evaluated before the call. +A call of the form <code>f{<em>fields</em>}</code> is +syntactic sugar for <code>f({<em>fields</em>})</code>; +that is, the argument list is a single new table. +A call of the form <code>f'<em>string</em>'</code> +(or <code>f"<em>string</em>"</code> or <code>f[[<em>string</em>]]</code>) +is syntactic sugar for <code>f('<em>string</em>')</code>; +that is, the argument list is a single literal string. +</p> +<% + end + } + fn_def = { + title = "Function Definitions" + content = function() +%> +<p> +The syntax for function definition is +</p> + +<pre> + functiondef ::= <b>function</b> funcbody + funcbody ::= ‘<b>(</b>’ [parlist] ‘<b>)</b>’ block end_function + end_function ::= <b>end_function</b> | <b>end</b> +</pre> + +<p> +The following syntactic sugar simplifies function definitions: +</p> + +<pre> + stat ::= <b>function</b> funcname funcbody + stat ::= <b>local</b> <b>function</b> Name funcbody + funcname ::= Name {‘<b>.</b>’ Name} [‘<b>:</b>’ Name] +</pre> + +<p> +The statement +</p> + +<pre> + function f () <em>body</em> end +</pre> + +<p> +translates to +</p> + +<pre> + f = function () <em>body</em> end +</pre> + +<p> +The statement +<p> + +<pre> + function t.a.b.c.f () <em>body</em> end +</pre> + +<p> +translates to +</p> + +<pre> + t.a.b.c.f = function () <em>body</em> end +</pre> + +<p> +The statement +</p> + +<pre> + local function f () <em>body</em> end +</pre> + +<p> +translates to +</p> + +<pre> + local f; f = function () <em>body</em> end +</pre> + +<p> +not to +</p> + +<pre> + local f = function () <em>body</em> end +</pre> + +<p> +(This only makes a difference when the body of the function +contains references to <code>f</code>.) +</p> + +<p> +A function definition is an executable expression, +whose value has type <em>function</em>. +When Luan precompiles a chunk, +all its function bodies are precompiled too. +Then, whenever Luan executes the function definition, +the function is <em>instantiated</em> (or <em>closed</em>). +This function instance (or <em>closure</em>) +is the final value of the expression. +</p> + +<p> +Parameters act as local variables that are +initialized with the argument values: +</p> + +<pre> + parlist ::= namelist [‘<b>,</b>’ ‘<b>...</b>’] | ‘<b>...</b>’ +</pre> + +<p> +When a function is called, +the list of arguments is adjusted to +the length of the list of parameters if the list is too short, +unless the function is a <em>vararg function</em>, +which is indicated by three dots ('<code>...</code>') +at the end of its parameter list. +A vararg function does not adjust its argument list; +instead, it collects all extra arguments and supplies them +to the function through a <em>vararg expression</em>, +which is also written as three dots. +The value of this expression is a list of all actual extra arguments, +similar to a function with multiple results. +If a vararg expression is used inside another expression +or in the middle of a list of expressions, +then its return list is adjusted to one element. +If the expression is used as the last element of a list of expressions, +then no adjustment is made +(unless that last expression is enclosed in parentheses). +</p> + +<p> +As an example, consider the following definitions: +</p> +<pre> + function f(a, b) end + function g(a, b, ...) end + function r() return 1,2,3 end +</pre> + +<p> +Then, we have the following mapping from arguments to parameters and +to the vararg expression: +</p> +<pre> + CALL PARAMETERS + + f(3) a=3, b=nil + f(3, 4) a=3, b=4 + f(3, 4, 5) runtime error + f(r(), 10) runtime error + f(r()) runtime error + + g(3) a=3, b=nil, ... --> (nothing) + g(3, 4) a=3, b=4, ... --> (nothing) + g(3, 4, 5, 8) a=3, b=4, ... --> 5 8 + g(5, r()) a=5, b=1, ... --> 2 3 +</pre> + +<p> +Results are returned using the <b>return</b> statement (see <a href="#control">Control Structures</a>). +If control reaches the end of a function +without encountering a <b>return</b> statement, +then the function returns with no results. +</p> +<% + end + } + } + } + visibility = { + title = "Visibility Rules" + content = function() +%> +<p> +Luan is a lexically scoped language. +The scope of a local variable begins at the first statement after +its declaration and lasts until the last non-void statement +of the innermost block that includes the declaration. +Consider the following example: +</p> +<pre> + x = 10 -- global variable + do -- new block + local x = x -- new 'x', with value 10 + print(x) --> 10 + x = x+1 + do -- another block + local x = x+1 -- another 'x' + print(x) --> 12 + end + print(x) --> 11 + end + print(x) --> 10 (the global one) +</pre> + +<p> +Notice that, in a declaration like <code>local x = x</code>, +the new <code>x</code> being declared is not in scope yet, +and so the second <code>x</code> refers to the outside variable. +</p> + +<p> +Because of the lexical scoping rules, +local variables can be freely accessed by functions +defined inside their scope. +A local variable used by an inner function is called +an <em>upvalue</em>, or <em>external local variable</em>, +inside the inner function. +</p> + +<p> +Notice that each execution of a <b>local</b> statement +defines new local variables. +Consider the following example: +</p> +<pre> + a = {} + local x = 20 + for i=1,10 do + local y = 0 + a[i] = function () y=y+1; return x+y end + end +</pre> + +<p> +The loop creates ten closures +(that is, ten instances of the anonymous function). +Each of these closures uses a different <code>y</code> variable, +while all of them share the same <code>x</code>. +</p> +<% + end + } + } + } + libs = { + title = "Standard Libraries" + content = function() +%> +<p> +The standard Luan libraries provide useful functions +that are implemented both in Java and in Luan itself. +How each function is implemented shouldn't matter to the user. +Some of these functions provide essential services to the language +(e.g., <a href="#Luan.type"><code>type</code></a> and <a href="#Luan.get_metatable"><code>get_metatable</code></a>); +others provide access to "outside" services (e.g., I/O). +</p> +<% + end + subs = { + default_lib = { + title = "Default Environment" + content = function() +%> +<p> +This is provided by default as a local variable for any Luan code as described in <a href="#env">Environments</a>. +</p> +<% + end + subs = { + require = { + title = "<code>require (mod_uri)</code>" + content = function() +%> +<p> +Example use: +</p> +<pre> + local Table = require "luan:Table.luan" +</pre> + +<p> +Could be defined as: +</p> +<pre> + local function require(mod_name) + return <a href="#Package.load">Package.load</a>(mod_name) or <a href="#Luan.error">Luan.error</a>("module '"..mod_name.."' not found") + end +</pre> + +<p> +A special case is: +</p> +<pre> + require "java" +</pre> + +<p> +This enables Java in the current chunk if that chunk has permission to use Java. If the chunk doesn't have permission to use Java, then an error is thrown. +</p> +<% + end + } + } + } + luan_lib = { + title = "Basic Functions" + content = function() +%> +<p> +Include this library by: +</p> +<pre> + local Luan = require "luan:Luan.luan" +</pre> + +<p> +The basic library provides basic functions to Luan that don't depend on other libaries. +</p> +<% + end + subs = { + ["Luan.do_file"] = { + title = "<code>Luan.do_file ([uri])</code>" + content = function() +%> +<p> +Could be defined as: +</p> +<pre> + function Luan.do_file(uri) + local fn = <a href="#Luan.load_file">Luan.load_file</a>(uri) or <a href="#Luan.error">Luan.error</a>("file '"..uri.."' not found") + return fn() + end +</pre> +<% + end + } + ["Luan.error"] = { + title = "<code>Luan.error (message)</code>" + content = function() +%> +<p> +Throws an error containing the message. +</p> + +<p> +Could be defined as: +</p> +<pre> + function Luan.error(message) + <a href="#Luan.new_error">Luan.new_error</a>(message).throw() + end +</pre> +<% + end + } + ["Luan.eval"] = { + title = "<code>Luan.eval (text [, source_name [, env]])</code>" + content = function() +%> +<p> +Evaluates <code>text</code> as a Luan expression. +</p> + +<p> +Could be defined as: +</p> +<pre> + function Luan.eval(text,source_name, env) + return <a href="#Luan.load">Luan.load</a>( "return "..text, source_name or "eval", env )() + end +</pre> +<% + end + } + ["Luan.get_metatable"] = { + title = "<code>Luan.get_metatable (table)</code>" + content = function() +%> +<p> +If <code>table</code> does not have a metatable, returns <b>nil</b>. +Otherwise, +if the table's metatable has a <code>"__metatable"</code> field, +returns the associated value. +Otherwise, returns the metatable of the given table. +</p> +<% + end + } + ["Luan.hash_code"] = { + title = "<code>Luan.hash_code (v)</code>" + content = function() +%> +<p> +Returns the hash code of <code>v</code>. +</p> +<% + end + } + ["Luan.ipairs"] = { + title = "<code>Luan.ipairs (t)</code>" + content = function() +%> +<p> +Returns an iterator function +so that the construction +</p> +<pre> + for i,v in ipairs(t) do <em>body</em> end +</pre> + +<p> +will iterate over the key–value pairs +(<code>1,t[1]</code>), (<code>2,t[2]</code>), ..., +up to the first nil value. +</p> + +<p> +Could be defined as: +</p> +<pre> + function Luan.ipairs(t) + local i = 0 + return function() + if i < #t then + i = i + 1 + return i, t[i] + end + end + end +</pre> +<% + end + } + ["Luan.load"] = { + title = "<code>Luan.load (text, [source_name [, env [, persist]]])</code>" + content = function() +%> +<p> +Loads a chunk. +</p> + +<p> +The <code>text</code> is compiled. +If there are no syntactic errors, +returns the compiled chunk as a function; +otherwise, throws an error. +</p> + +<p> +The <code>source_name</code> parameter is a string saying where the text came from. It is used to produce error messages. Defaults to "load". +</p> + +<p> +If the <code>env</code> parameter is supplied, it becomes the <code>_ENV</code> of the chunk. +</p> + +<p> +The <code>persist</code> parameter is a boolean which determines if the compiled code is persistently cached to a temporary file. Defaults to <code>false</code>. +</p> +<% + end + } + ["Luan.load_file"] = { + title = "<code>Luan.load_file (file_uri)</code>" + content = function() +%> +<p> +Similar to <a href="#Luan.load"><code>load</code></a>, +but gets the chunk from file <code>file_uri</code>. +<code>file_uri</code> can be a string or a uri table. +</p> +<% + end + } + ["Luan.new_error"] = { + title = "<code>Luan.new_error (message)</code>" + content = function() +%> +<p> +Creates a new error table containing the message assigned to "<code>message</code>". The error table also contains a <code>throw</code> function which throws the error. The table also contains a list of stack trace elements where each stack trace element is a table containing "<code>source</code>", "<code>line</code>", and possible "<code>call_to</code>". The table also has a metatable containing "<code>__to_string</code>" to render the error. +</p> + +<p> +To print the current stack trace, you could do: +</p> +<pre> + Io.print( Luan.new_error "stack" ) +</pre> +<% + end + } + ["Luan.pairs"] = { + title = "<code>Luan.pairs (t)</code>" + content = function() +%> +<p> +If <code>t</code> has a metamethod <code>__pairs</code>, +calls it with <code>t</code> as argument and returns the +result from the call. +</p> + +<p> +Otherwise, +returns a function +so that the construction +</p> +<pre> + for k,v in pairs(t) do <em>body</em> end +</pre> + +<p> +will iterate over all key–value pairs of table <code>t</code>. +</p> +<% + end + } + ["Luan.range"] = { + title = "<code>Luan.range (start, stop [, step])</code>" + content = function() +%> +<p> +Based on <a href="https://docs.python.org/2/library/functions.html#range">the Python range() function</a>, this lets one iterate through a sequence of numbers. +</p> + +<p> +Example use: +</p> +<pre> + for i in range(1,10) do + Io.print("count up:",i) + end + for i in range(10,0,-1) do + Io.print("count down:",i) + end +</pre> + +<p> +Could be defined as: +</p> +<pre> + function Luan.range(start, stop, step) + step = step or 1 + step == 0 and <a href="#Luan.error">Luan.error</a> "bad argument #3 (step may not be zero)" + local i = start + return function() + if step > 0 and i <= stop or step < 0 and i >= stop then + local rtn = i + i = i + step + return rtn + end + end + end +</pre> +<% + end + } + ["Luan.raw_equal"] = { + title = "<code>Luan.raw_equal (v1, v2)</code>" + content = function() +%> +<p> +Checks whether <code>v1</code> is equal to <code>v2</code>, +without invoking any metamethod. +Returns a boolean. +</p> +<% + end + } + ["Luan.raw_get"] = { + title = "<code>Luan.raw_get (table, index)</code>" + content = function() +%> +<p> +Gets the real value of <code>table[index]</code>, +without invoking any metamethod. +<code>table</code> must be a table; +<code>index</code> may be any value. +</p> +<% + end + } + ["Luan.raw_len"] = { + title = "<code>Luan.raw_len (v)</code>" + content = function() +%> +<p> +Returns the length of the object <code>v</code>, +which must be a table or a string, +without invoking any metamethod. +Returns an integer. +</p> +<% + end + } + ["Luan.raw_set"] = { + title = "<code>Luan.raw_set (table, index, value)</code>" + content = function() +%> +<p> +Sets the real value of <code>table[index]</code> to <code>value</code>, +without invoking any metamethod. +<code>table</code> must be a table, +<code>index</code> any value different from <b>nil</b>, +and <code>value</code> any Luan value. +</p> +<% + end + } + ["Luan.set_metatable"] = { + title = "<code>Luan.set_metatable (table, metatable)</code>" + content = function() +%> +<p> +Sets the metatable for the given table. +If <code>metatable</code> is <b>nil</b>, +removes the metatable of the given table. +If the original metatable has a <code>"__metatable"</code> field, +raises an error. +</p> +<% + end + } + ["Luan.stringify"] = { + title = "<code>Luan.stringify (v [,options])</code>" + content = function() +%> +<p> +Receives a value of any type and converts it to a string that is a Luan expression. <code>options</code> is a table. If <code>options.strict==true</code> then invalid types throw an error. Otherwise invalid types are represented but the resulting expression is invalid. If <code>options.number_types==true</code> then numbers will be wrapped in functions for their type. +</p> +<% + end + } + ["Luan.to_string"] = { + title = "<code>Luan.to_string (v)</code>" + content = function() +%> +<p> +Receives a value of any type and +converts it to a string in a human-readable format. +</p> + +<p> +If the metatable of <code>v</code> has a <code>"__to_string"</code> field, +then <code>to_string</code> calls the corresponding value +with <code>v</code> as argument, +and uses the result of the call as its result. +</p> +<% + end + } + ["Luan.type"] = { + title = "<code>Luan.type (v)</code>" + content = function() +%> +<p> +Returns the type of its only argument, coded as a string. +The possible results of this function are +"<code>nil</code>" (a string, not the value <b>nil</b>), +"<code>number</code>", +"<code>string</code>", +"<code>binary</code>", +"<code>boolean</code>", +"<code>table</code>", +"<code>function</code>", +and "<code>java</code>". +</p> +<% + end + } + ["Luan.values"] = { + title = "<code>Luan.values (···)</code>" + content = function() +%> +<p> +Returns a function so that the construction +</p> +<pre> + for i, v in Luan.values(···) do <em>body</em> end +</pre> + +<p> +will iterate over all values of <code>···</code>. +</p> +<% + end + } + ["Luan.VERSION"] = { + title = "<code>Luan.VERSION</code>" + content = function() +%> +<p> +A global variable (not a function) that +holds a string containing the current Luan version. +</p> +<% + end + } + } + } + package_lib = { + title = "Modules" + content = function() +%> +<p> +Include this library by: +</p> +<pre> + local Package = require "luan:Package.luan" +</pre> + +<p> +The package library provides basic +facilities for loading modules in Luan. +</p> +<% + end + subs = { + ["Package.load"] = { + title = "<code>Package.load (mod_uri)</code>" + content = function() +%> +<p> +Loads the given module. +The function starts by looking into the <a href="#Package.loaded"><code>Package.loaded</code></a> table +to determine whether <code>mod_uri</code> is already loaded. +If it is, then <code>Package.load</code> returns the value stored +at <code>Package.loaded[mod_uri]</code>. +Otherwise, it tries to load a new value for the module. +</p> + +<p> +To load a new value, <code>Package.load</code> first checks if <code>mod_uri</code> starts with "<b>java:</b>". If yes, then this is a Java class which is loaded by special Java code. +</p> + +<p> +Otherwise <code>Package.load</code> tries to read the text of the file referred to by <code>mod_uri</code>. If the file doesn't exist, then <code>Package.load</code> returns <b>false</b>. If the file exists, then its content is compiled into a chunk by calling <a href="#Luan.load"><code>Luan.load</code></a>. This chunk is run passing in <code>mod_uri</code> as an argument. The value returned by the chunk must not be <b>nil</b> and is loaded. +</p> + +<p> +If a new value for the module successful loaded, then it is stored in <code>Package.loaded[mod_uri]</code>. The value is returned. +</p> +<% + end + } + ["Package.loaded"] = { + title = "<code>Package.loaded</code>" + content = function() +%> +<p> +A table used by <a href="#Package.load"><code>Package.load</code></a> to control which +modules are already loaded. +When you load a module <code>mod_uri</code> and +<code>Package.loaded[mod_uri]</code> is not <b>nil</b>, +<a href="#Package.load"><code>Package.load</code></a> simply returns the value stored there. +</p> + +<p> +This variable is only a reference to the real table; +assignments to this variable do not change the +table used by <a href="#Package.load"><code>Package.load</code></a>. +</p> +<% + end + } } } }