All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.sandius.rembulan.lib.ModuleLib Maven / Gradle / Ivy

There is a newer version: 1.0.3
Show newest version
/*
 * Copyright 2016 Miroslav Janíček
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * --
 * Portions of this file are licensed under the Lua license. For Lua
 * licensing details, please visit
 *
 *     http://www.lua.org/license.html
 *
 * Copyright (C) 1994-2016 Lua.org, PUC-Rio.
 *
 * Permission is hereby granted, free of charge, to any person obtaining
 * a copy of this software and associated documentation files (the
 * "Software"), to deal in the Software without restriction, including
 * without limitation the rights to use, copy, modify, merge, publish,
 * distribute, sublicense, and/or sell copies of the Software, and to
 * permit persons to whom the Software is furnished to do so, subject to
 * the following conditions:
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

package net.sandius.rembulan.lib;

import net.sandius.rembulan.StateContext;
import net.sandius.rembulan.Table;
import net.sandius.rembulan.TableFactory;
import net.sandius.rembulan.runtime.LuaFunction;

/**
 * The package library provides basic facilities for loading modules in Lua. It exports
 * one function directly in the global environment: {@link #_require() {@code require}}.
 * Everything else is exported in a {@code table} package.
 */
public abstract class ModuleLib extends Lib {

	@Override
	public String name() {
		return "package";
	}

	@Override
	public Table toTable(TableFactory tableFactory) {
		Table t = tableFactory.newTable();
		t.rawset("config", _config());
		t.rawset("cpath", _cpath());
		t.rawset("loaded", _loaded());
		t.rawset("loadlib", _loadlib());
		t.rawset("path", _path());
		t.rawset("preload", _preload());
		t.rawset("searchers", _searchers());
		t.rawset("searchpath", _searchpath());
		return t;
	}

	@Override
	public void preInstall(StateContext state, Table env) {
		env.rawset("require", _require());
	}

	public abstract void install(Lib lib);

	/**
	 * {@code require (modname)}
	 *
	 * 

Loads the given module. The function starts by looking into * the {@link #_loaded() {@code package.loaded}} table to determine * whether {@code modname} is already loaded. If it is, then {@code require} returns * the value stored at {@code package.loaded[modname]}. Otherwise, it tries to find * a loader for the module.

* *

To find a loader, {@code require} is guided by the {@code package.searchers} sequence. * By changing this sequence, we can change how {@code require} looks for a module. * The following explanation is based on the default configuration * for {@code package.searchers}.

* *

First {@code require} queries {@code package.preload[modname]}. If it has a value, * this value (which must be a function) is the loader. Otherwise {@code require} * searches for a Lua loader using the path stored in {@code package.path}. If that also fails, * it searches for a C loader using the path stored in {@code package.cpath}. * If that also fails, it tries an all-in-one loader * (see {@link #_searchers() {@code package.searchers}}).

* *

Once a loader is found, {@code require} calls the loader with two arguments: * {@code modname} and an extra value dependent on how it got the loader. (If the loader came * from a file, this extra value is the file name.) If the loader returns any non-nil value, * {@code require} assigns the returned value to {@code package.loaded[modname]}. * If the loader does not return a non-nil value and has not assigned any value * to {@code package.loaded[modname]}, then {@code require} assigns true to this entry. * In any case, require returns the final value of {@code package.loaded[modname]}.

* *

If there is any error loading or running the module, or if it cannot find any loader * for the module, then {@code require} raises an error.

* * @return the {@code require} function */ public abstract LuaFunction _require(); /** * {@code package.config} * *

A string describing some compile-time configurations for packages. This string is * a sequence of lines:

* *
    *
  • The first line is the directory separator string. Default is '{@code \}' for Windows * and '{@code /}' for all other systems.
  • *
  • The second line is the character that separates templates in a path. * Default is '{@code ;}'.
  • *
  • The third line is the string that marks the substitution points in a template. * Default is '{@code ?}'.
  • *
  • The fourth line is a string that, in a path in Windows, is replaced by * the executable's directory. Default is '{@code !}'.
  • *
  • The fifth line is a mark to ignore all text after it when building * the {@code luaopen_} function name. Default is '{@code -}'.
  • *
* * @return the {@code package.config} string */ public abstract String _config(); /** * {@code package.cpath} * *

The path used by require to search for a C loader.

* *

Lua initializes the C path {@code package.cpath} in the same way it initializes * the Lua path {@link #_path() {@code package.path}}, using the environment variable * {@code LUA_CPATH_5_3} or the environment variable {@code LUA_CPATH} or a default path * defined in {@code luaconf.h}.

* * @return the {@code package.cpath} string */ public abstract String _cpath(); /** * {@code package.loaded} * *

A table used by {@link #_require() {@code require}} to control which modules * are already loaded. When you require a module {@code modname} * and {@code package.loaded[modname]} is not false, require simply returns the value * stored there.

* *

This variable is only a reference to the real table; assignments to this variable do not * change the table used by {@link #_require() {@code require}}.

* * @return the {@code package.loaded} table */ public abstract Table _loaded(); /** * {@code package.loadlib (libname, funcname)} * *

Dynamically links the host program with the C library {@code libname}.

* *

If funcname is "{@code *}", then it only links with the library, making the symbols * exported by the library available to other dynamically linked libraries. Otherwise, * it looks for a function {@code funcname} inside the library and returns this function as * a C function. So, {@code funcname} must follow the {@code lua_CFunction prototype} * (see {@code lua_CFunction}).

* *

This is a low-level function. It completely bypasses the package and module system. * Unlike {@link #_require() {@code require}}, it does not perform any path searching * and does not automatically adds extensions. {@code libname} must be the complete file name * of the C library, including if necessary a path and an extension. {@code funcname} must * be the exact name exported by the C library (which may depend on the C compiler and linker * used).

* *

This function is not supported by Standard C. As such, it is only available on some * platforms (Windows, Linux, Mac OS X, Solaris, BSD, plus other Unix systems that support * the {@code dlfcn} standard).

* * @return the {@code package.loadlib} function */ public abstract LuaFunction _loadlib(); /** * {@code package.path} * *

The path used by {@link #_require() {@code require}} to search for a Lua loader.

* *

At start-up, Lua initializes this variable with the value of the environment variable * {@code LUA_PATH_5_3} or the environment variable {@code LUA_PATH} or with a default path * defined in {@code luaconf.h}, if those environment variables are not defined. * Any "{@code ;;}" in the value of the environment variable is replaced by the default * path.

* * @return the {@code package.path} string */ public abstract String _path(); /** * {@code package.preload} * *

A table to store loaders for specific modules (see * {@link #_require() {@code require}}).

* *

This variable is only a reference to the real table; assignments to this variable * do not change the table used by {@link #_require() {@code require}}.

* * @return the {@code package.preload} table */ public abstract Table _preload(); /** * {@code package.searchers} * *

A table used by {@link #_require() {@code require}} to control how to load * modules.

* *

Each entry in this table is a searcher function. When looking for a module, * {@code require} calls each of these searchers in ascending order, with the module name * (the argument given to {@code require}) as its sole parameter. The function can return * another function (the module loader) plus an extra value that will be passed to that loader, * or a string explaining why it did not find that module (or nil if it has nothing * to say).

* *

Lua initializes this table with four searcher functions.

* *

The first searcher simply looks for a loader in * the {@link #_preload() {@code package.preload}} table.

* *

The second searcher looks for a loader as a Lua library, using the path stored at * {@link #_path() {@code package.path}}. The search is done as described in function * {@link #_searchpath() {@code package.searchpath}}.

* *

The third searcher looks for a loader as a C library, using the path given by * the variable {@link #_cpath() {@code package.cpath}}. Again, the search is done * as described in function {@link #_searchpath() {@code package.searchpath}}. * For instance, if the C path is the string

*
	 *   "./?.so;./?.dll;/usr/local/?/init.so"
	 * 
*

the searcher for module foo will try to open the files {@code ./foo.so}, {@code ./foo.dll}, * and {@code /usr/local/foo/init.so}, in that order. Once it finds a C library, * this searcher first uses a dynamic link facility to link the application with the library. * Then it tries to find a C function inside the library to be used as the loader. * The name of this C function is the string "{@code luaopen_}" concatenated with a copy of * the module name where each dot is replaced by an underscore. Moreover, if the module name * has a hyphen, its suffix after (and including) the first hyphen is removed. * For instance, if the module name is {@code a.b.c-v2.1}, the function name will * be {@code luaopen_a_b_c}.

* *

The fourth searcher tries an all-in-one loader. It searches the C path for a library * for the root name of the given module. For instance, when requiring {@code a.b.c}, * it will search for a C library for {@code a}. If found, it looks into it for * an open function for the submodule; in our example, that would be {@code luaopen_a_b_c}. * With this facility, a package can pack several C submodules into one single library, * with each submodule keeping its original open function.

* *

All searchers except the first one (preload) return as the extra value the file name * where the module was found, as returned * by {@link #_searchpath() {@code package.searchpath}}. The first searcher returns * no extra value.

* * @return the {@code package.searchers} table */ public abstract Table _searchers(); /** * {@code package.searchpath (name, path [, sep [, rep]])} * *

Searches for the given name in the given {@code path}.

* *

A path is a string containing a sequence of templates separated by semicolons. * For each template, the function replaces each interrogation mark (if any) in the template * with a copy of name wherein all occurrences of {@code sep} (a dot, by default) were * replaced by {@code rep} (the system's directory separator, by default), and then tries * to open the resulting file name.

* *

For instance, if the path is the string

*
	 *   "./?.lua;./?.lc;/usr/local/?/init.lua"
	 * 
*

the search for the name {@code foo.a} will try to open the files {@code ./foo/a.lua}, * {@code ./foo/a.lc}, and {@code /usr/local/foo/a/init.lua}, in that order.

* *

Returns the resulting name of the first file that it can open in read mode * (after closing the file), or nil plus an error message if none succeeds. * (This error message lists all file names it tried to open.)

* * @return the {@code package.searchpath} function */ public abstract LuaFunction _searchpath(); }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy