ModuleClass
object. The complete module definition expression is summarized here. Each of its optional clauses is covered in greater detail later in this chapter.
module ModuleNameA
[ exports variable, variable, variable, . . . ]
[ exports [ readonly ] instance variables variable, . . . ]
[ uses module, module, module, . . . ]
[ uses module with
[ imports everything ]
[ imports variable, variable, variable, . . . ]
[ imports [ readOnly ] instance variables
variable, variable, variable, . . . ]
[ excludes variable, variable, variable, . . . ]
[ excludes [ readOnly ] instance variables
variable, variable, variable, . . . ]
[ exports everything ]
[ exports variable, variable, variable, . . . ]
[ exports [ readOnly ] instance variables
variable, variable, variable, . . . ]
[ prefix prefix ]
[ renames oldName:newName, oldName:newName, . . . ]
[ renames [ readOnly ] instance variables
voldName:newName, oldName:newName, . . . ]
end]
end
module
definition expression can include two main sections, which are both optional, and can be specified in any order. The exports
options (described in the section "Exporting Variables to Other Modules" on page 202) specify which names are exported from this module. The uses
options (described in the section "Importing Variables From Other Modules" on page 205) specify which names are imported from other modules.
In this syntax definition, and in many of the examples on the following pages, the individual sections of the module definition are shown on separate lines. You can specify a module definition in this way, all on a single line, or in any combination:
module foo exports x, y, z uses bar with prefix Z end end
module MyModule
exports varOne, varTwo
uses foo with excludes Z end
end
Defining a Module
module ModuleName
Unlike ScriptX global variables, which are only global within the scope of a given module, module names are truly global. There is only one namespace for module names. Because of this, you should choose a module name that is unique and distinct:
...
end
module PaintInterfaceUser
module DeveloperModule_Rev15_345a
module LotsOfSillyClassesThatOnlyPartiallyWorkTogether
Redefinition of Modules
module Blue exports ink, paper end
module Pink uses Blue end
in module Blue
global ink := "blue"
global paper := "white"
in module Pink
global stone := ink + paper
"bluewhite"
-- now redefine Pink and change the value of ink from within Blue
module Pink uses Blue with excludes ink end end
in module Blue
ink := "red"
in module Pink
global Stone := ink + paper
"redwhite"
ink
is still accessible in module Pink
, even though it has been redefined to exclude ink
, and ink
continues to reflect the value that was set for it in module Blue
.module Green exports grass, leaves end
module Brown uses Green end
in module Green
global grass := "green"
global leaves := "green"
in module Brown
global compost := grass + leaves
"greengreen"
-- now redefine Brown so that it renames grass, and change value
module Brown uses Green with renames grass:herbs end end
in module Green
grass := "brown"
in module Brown
compost := grass + leaves
"browngreen"
global moreCompost := herbs + leaves
"browngreen"
Brown
, the variable grass
, as defined by Green
, is accessible through both the original name and its new name. It has two valid bindings. Switching Modules
in module ModuleName
The in module
expression places the ScriptX compiler (and therefore your Listener window or authoring environment) into the scope of the module specified by ModuleName, giving you access to all the variables defined in that module or imported from other modules. If the module you specify does not exist, ScriptX reports an exception. The ScriptX compiler remains in the specified module until in module
is invoked again, placing the compiler in a different module. The in module
expression is allowed only at the top level in your program.
Note - The ScriptX expression in module
does not take a ModuleClass
object as its target. It operates on a name literal, the scripter name of a module.
Unlike other names in ScriptX, names of modules are not lexical names. With
lexical names (names of constants and variables), the name represents the
object itself. The name of a module is like a label for the module, a label which
the in module
expression recognizes. However, ScriptX functions that take a
module as a parameter, such as the generic functions load
and store
, must
be passed the ModuleClass
object itself.
If you need access to the ScriptX core classes in your module, make sure the module that you specify in an in module
expression has been defined to use the ScriptX module. in module
is used in a ScriptX program after its module definition, but before the remainder of the expressions (class definitions, variable declarations, and so on) that make up the program to be compiled within that module.module DefinitionModule
exports FirstClass, sumThem
-- this exports getters and setters
exports instance variables a, b, c
uses ScriptX
end
module TestingModule
uses ScriptX, DefinitionModule
end
in module DefinitionModule
class FirstClass ()
instance variables a, b, c
instance methods
method init self #rest args #key a:(10) b:(10) c:(10) -> (
apply nextMethod self args
self.a := a
self.b := b
self.c := c
)
method sumThem self -> (
print (self.a + self.b + self.c)
)
end
in module TestingModule
global t := new FirstClass a:20
sumThem t
40
in module
expression switches the compiler into another module..
Importing and Compiling Files with fileIn
fileIn
, implemented by DirRep
and ByteStream
, is available only with the ScriptX Language and Class Library. (The Kaleida Media Player does not include the bytecode compiler, which compiles and executes scripts.) A large ScriptX project is typically compiled from a build file, and this build file usually includes a series of calls to fileIn
. This design makes it easy to divide a large project into an number of smaller source files which are compiled in a set order.fileIn
run in the Scratch
module by default. The fileIn
generic function defines a module
keyword argument, which takes a ModuleClass
object. This keyword can be used to specify which module the file is compiled in. -- the file dogs.sx will be compiled in the AnimalInterface module
fileIn name:dogs.sx module:(getModule @AnimalInterface)
in module
expression, if it appears within a source file that is read in using fileIn
, overrides fileIn
in determining which module a given script is compiled in, but only within the scope of that file. Compilation reverts back to the previous module after fileIn
finishes compiling and executing the script and returns a value. fileIn
generic function It is possible to specify a module fileIn
also specifies a module using the module
keyword, the code within the file being imported is compiled within the named module. The fileIn
generic function is described in the class definition of DirRep
in the ScriptX Class Reference.module
keyword with fileIn
is that it can be hard to tell at a glance which module a given script is compiled in. For that reason, many programmers ignore the module
keyword. They prefer to specify the current module explicitly at the top of each source file, using in module
as the first expression in the file.fileIn
, scripts that are read in and compiled using the Open Title . . . menu command in the current ScriptX Listener window run in the current environment, and place the ScriptX compiler directly into the modules specified by any in module
expressions in the file. Module Objects
ModuleClass
. However, unlike class or function definition expressions, the name of the module is not a variable which is assigned to that module object, so you cannot use the module name to refer to the module object as you would any other variable.ModuleClass
object itself:
getModule
or currentModule
functions:
getModule ModuleNameThe global function
getModule
returns the ModuleClass
object that is specified by the given name. If you do not specify a valid module, getModule
returns false
. Unlike the in module
expression, getModule
cannot define a new module. The module referred to by ModuleName must already have been defined. Note that getModule
does not affect which module ScriptX is currently compiling in. Only the in module
expression can be used to switch from one module to another.The
getModule
function returns false
if it does not return a module. You can use this feature to test whether a module is defined or not:
if not (getModule @whatever) do
(
-- This block executes only if the module @whatever is not defined
)
Once you have a module object to operate on, you can add that module to a container in the object store (as described in "Storing Modules" on page 222). For example, to append the
Definition
module to the tc
title container:
append tc (getModule @Definition)
fileIn
, described above). Of course, the ScriptX
, Substrate
, and Scratch
modules, which are defined by the system, cannot be saved.currentModule()
The global function currentModule
, which is actually implemented as a macro, returns the ModuleClass
object in which ScriptX is currently compiling. It reflects the state of the compiler during compilation, and is not meant to be used at runtime. ScriptX does not have a "currently active" module at runtime.currentModule
in scripts. It exists only for informational and debugging purposes.deleteModule ModuleName
A module can be removed from memory using deleteModule
, but only if it is not being used by any other module.deleteModule
can be called with either the name of the module, or a ModuleClass
object as its argument. If the module is being used by another module, and cannot be deleted, deleteModule
reports the deletingUsedModule
exception. If the modules that are using it are then deleted, the module can be deleted. Exporting Variables to Other Modules
exports
section of the module definition expression:module ModuleName
The
exports variable, variable, variable, . . .
end
exports
reserved word is followed by a list of variable names that are visible outside this module. Those variables can be variables that are defined, or will be defined, within this module. They can also be variables that were imported from other modules, and are thus "passed along" by this module. Variable names can be specified on separate lines, on the same line separated by commas, or in any combination.module Australia
uses ScriptX
exports beer, engineers
end
in module Australia
global beer := "Foster's"
global engineers := #("Wainwright", "Nicholson", "Williams")
exports
sections in your module definition, which is useful for documentation purposes or to group sets of exported variables together into logical groups. The resulting module exports all of the variables in all the exports
sections.module California
uses ScriptX
exports chips, software
exports almonds, avocados, cherries, figs, lettuce, wine
exports entertainment, movies
end
in module California
global chips := #("PowerPC", "Intel")
global software := "ScriptX"
. . .
exports
clause is a declaration of names that are visible outside the module, analogous to the extern
statement in C.
exports
section of a module definition. However, be aware that exporting the class name alone does not automatically provide access to that class's methods and variables. To have full access to an exported class from another module, you must not only export the variable that contains that class, but you must also explicitly export.
Person
class has two instance variables, name
and age
, and two methods, printName
and printAll
.
class Person ()
instance variables
name, age
instance methods
method printName self -> (
prin ("My name is " + self.name + "\n") @Normal debug
)
method printAll self -> (
printName self
prin ("My age is " + self.age + "\n") @Normal debug
)
end
In order for both instance variables and both methods to be available outside the module, you must explicitly export all of the name bindings that are defined by the class:
module PersonModule
-- the class itself
exports Person
-- Person's instance variables (getter and setter generics)
exports nameSetter, nameGetter, ageSetter, ageGetter
-- Person's methods
exports printName, printAll
end
module ModuleNameThe
exports [ readonly ] instance variables variable, variable, . . .
end
instance variables
reserved words can be shortened to instance vars
or simply inst vars
. The list of variables can be supplied on one line separated by commas, on separate lines, or in any combination.The optional
readonly
reserved word exports the list of instance variables specified by variables
in a read-only form; that is, they can be queried but not changed.The
instance variables
part of an exports
clause is simply shorthand for exporting the setter and getter generic functions for those variables. If the readonly
option is specified, only getter methods are exported. The following module definitions are equivalent:
module MyModule
exports readonly instance variables x
exports instance variables y
end
module MyModule
exports xGetter, ySetter, yGetter
end
uses
clause of a module definition. There are two forms of uses
: the short form (uses
) that simply imports all the exported variables from the given module into this module, and the long form (uses
. . . with
), which allows control over which variables should be imported, and how they should be handled. For example, a uses
. . . with
clause can change their names or reexport them. For the complete syntax for defining a module, see page 196. The syntax for both
uses
clauses in a module definition is as follows:
module ModuleName
The line containing the reserved word
[ uses module, module, module, . . . ]
[ uses module with
[ imports everything ]
[ imports variable, variable, variable, . . . ]
[ imports [ readOnly ] instance variables
variable, variable, variable, . . . ]
[ excludes variable, variable, variable, . . . ]
[ excludes [ readOnly ] instance variables
variable, variable, variable, . . . ]
[ exports everything ]
[ exports variable, variable, variable, . . . ]
[ exports [ readOnly ] instance variables
variable, variable, variable, . . . ]
[ prefix prefix ]
[ renames oldName:newName, oldName:newName, . . . ]
[ renames [ readOnly ] instance variables
voldName:newName, oldName:newName, . . . ]
end]
end
uses
specifies the modules whose variables are to be imported. The first form is simply the reserved word uses
followed by the other modules whose variables are to be imported. Note that with this form, all variables are imported from the specified modules. The modules can be specified on the same line separated by commas, on separate lines, or in any combination. Any module you specify in a uses
definition must already have been defined. You can have a single uses
, or you can have multiple uses
clauses in the same module definition. Note that if you want the variables in the ScriptX core classes to be available to the expressions in this module, you have to explicitly use the ScriptX module. uses
clause, uses with
, allows more control over how imported variables from individual modules are handled. The uses with
clause specifies options for a single module. You must use an individual uses with
clause for each module. uses with
clause contains several sub-clauses, referred to in this chapter as options, all of which are optional and may be included in any order. Also, although they have been presented here on multiple lines and indented, they may also be specified on a single line, or in any combination. uses
form is equivalent to the uses with
form with imports everything
. That is, the following two definitions are equivalent:module Mocha
uses ScriptX
end
module Mocha
uses ScriptX with
imports everything
end
uses with
option are described in the following sections. uses
module ModuleName
This is the simplest form of module definition that imports variables from other modules. All variables that are exported from the specified modules are imported into the module given by ModuleName.
uses module, module, module, . . .
end
A Note on Circular Use Relationships
uses
clauses that import variables from each other. In this example, Foo
uses Bar
which uses Foo
:-- Don't define a circular relationship like this
module Foo
exports x, y, z
uses Bar
end
module Bar
exports a, b, c
uses Foo
end
uses
clause can only name modules that have already been defined, explicit circular use relationships cannot occur (the first definition returns a warning stating that module bar
does not exist).
uses with imports
module ModuleName
The optional
uses module with
imports everything
imports variable, variable, variable, . . .
imports [ readOnly ] instance variables
variable, variable, variable, . . . ]
end
end
imports
clause is used to specify which variables to import from the module specified by module.imports
option, when used with the reserved word everything
, simply imports all the variables that the given module exports. If you use imports everything
, you cannot use any of the other forms of imports
in the same uses with
clause. Also, if you omit all imports
options in a uses with
clause, imports everything
is assumed. The advantage to using imports everything
rather than a simple uses
clause is that other options, such as prefix
and renames
, are also available.imports
option followed by a list of variables specifies exactly which variables to import into this module. The variable names can be specified on separate lines, on the same line separated by commas, or in any combination.imports
option with the instance variables
reserved words (or the readOnly
instance variables
reserved words) is syntactic shorthand for importing the setter and getter generic functions for the named instance variables (or, in the case of readOnly
, only the getter method). The instance variables
reserved words can be shortened to instance vars
or simply inst vars
. See "Exporting Classes" on page 203 for more information on importing and exporting classes and their methods and variables.
The following example creates a module and exports three global variables it defines.
module XYZ
uses ScriptX
exports x, y, z
end
in module XYZ
global x:10, y:"foo", z:#(56,567)
XYZ
and imports all variables from it.module XYZimport1
uses ScriptX
uses XYZ with imports everything end
end
in module XYZimport1
print x
10
print y
"foo"
print z
#(56, 567)
XYZ
, but it imports only x
and z
from this module. Since y
is undefined within this module, attempting to access y
from this module reports an exception.module XYZimport2
uses ScriptX
uses XYZ with imports x, z end
end
in module XYZimport2
print x
10
print z
#(56,567)
print y -- this reports an exception
-- ** XYZimport2:y does not have a variable value \
(UninitializedVariable)
uses with renames
module ModuleName
The optional
uses module with
renames oldName:newName, oldName:newName, . . .
renames [ readOnly ] instance variables
oldName:newName, oldName:newName, . . .
end
end
renames
clause is used to import a variable from the given module and give it a new name. The definition of the variable, if any, is still valid in the new module under the new name. The renames
keyword is followed by any number of oldName and newName pairs, on the same line separated by commas, on separate lines, or in any combination. The old and new variable names, oldName and newName, are separated by colons. The renames
clause, used without an imports
clause, assumes imports everything
.renames
clause with the instance variables
reserved words (or the readOnly instance variables
reserved words) is syntactic shorthand for renaming the setter and getter generic functions for the named instance variables (or, in the case of readOnly
, only the getter method). See "Exporting Classes" on page 203 for more information on importing and exporting classes and their methods and variables.
The
renames
option overrides both import
and prefix
; the variables specified by renames
are both imported and given the names specified by newName.XYZ
, as in the previous example.module XYZ
uses ScriptX
exports x, y, z
end
in module XYZ
global x:10, y:"foo", z:#(56,567)
XYZ
, imports only x
, and renames it externalX
.module XYZrename1
uses ScriptX
uses XYZ with
renames x:externalX
end
end
in module XYZrename1
print externalX
10
print y
"foo"
x
and y
, but renames x
. Renaming x
overrides import x
so that x
is imported, but with a new name.module XYZrename2
uses ScriptX
uses XYZ with
imports x, y
renames x:otherX
end
end
in module XYZrename2
-- this reports an exception
print x
-- ** XYZrename2:x does not have a variable value \
(UninitializedVariable)
print otherX
10
print y
"foo"
uses with prefix
module ModuleName
The optional
uses module with
prefix prefix
end
end
prefix
clause is used to import variables and rename them by attaching a prefix (specified by prefix) to the variable name. Prefixing variable names is useful for resolving conflicts in variable names between modules or for simply indicating which module a variable came from. The prefix
option, used without an imports
option, assumes imports everything
.renames
clause for those variables.XYZ
, as in the previous example.module XYZ
uses ScriptX
exports x, y, z
end
in module XYZ
global x:10, y:"foo", z:#(56,567)
XYZprefix1
imports all variables from module XYZ
and prefixes variables from that module with XYZ_
.module XYZprefix1
uses ScriptX
uses XYZ with
prefix XYZ_
end
end
in module XYZprefix1
print x
-- ** XYZprefix1:x does not have a variable value
(UninitializedVariable)
print XYZ_x
10
print XYZ_y
"foo"
XYZprefix2
uses both a prefix
clause and a renames
clause. The renames
clause overrides the prefix for specific variables.module XYZprefix2
uses ScriptX
uses XYZ with
prefix ext_
renames x:fumbleWhizzy
end
end
in module XYZprefix2
print ext_x
-- ** XYZprefix2:ext_x does not have a variable value
(UninitializedVariable)
print ext_y
"foo"
print fumbleWhizzy
10
uses with excludes
module ModuleName
The optional
uses module with
excludes variable, variable, variable, . . .
excludes [ readOnly ] instance variables
variable, variable, variable, . . .
end
end
excludes
clause is used to explicitly exclude individual variables from a module. The list of variable names can be on a single line separated by commas, on individual lines, or in any combination. If you use excludes
without an imports
clause, imports everything
is assumed.excludes
option with the instance variables
reserved words (or the readOnly instance variables
reserved words) is syntactic shorthand for excluding the setter and getter generic functions for the named instance variables (or, in the case of readOnly
, only the getter method). See "Exporting Classes" on page 203 for more information on importing and exporting classes and their methods and variables.
Like
renames
and prefix
, excludes
is used to prevent imported variable names from clashing with variable names in the current module. However, excludes
is also useful when there are a lot of imported variables and most, but not all, are relevant; rather than specifying all the variables this module is interested in with an import
clause, you can simply specify the variables that this module is not concerned with using excludes
.XYZ
, just as in the previous section. module XYZ
uses ScriptX
exports x, y, z
end
in module XYZ
global x:10, y:"foo", z:#(56,567)
XYZ
, excluding y
.module XYZexclude1
uses ScriptX
uses XYZ with
imports everything
excludes y
end
end
in module XYZexclude1
print x
10
print y
-- ** XYZexclude1:y does not have a variable value \
(UninitializedVariable)
uses with exports
module ModuleName
The optional
uses module with
exports everything
exports variable, variable, variable, . . .
exports [ readOnly ] instance variables
variable, variable, variable, . . .
end
end
exports
clause is used to re-export any variables that have been imported from module using the imports
or renames
clauses (sometimes called "transitive exporting"). You also use it to export variables created within this module. If the variables have been renamed or prefixed upon import (using the renames
or prefix
clauses), those variables are exported using those new names.exports
option, when used with the reserved word everything
, simply re-exports all the variables that were imported from module. If you use exports everything
, you cannot use any of the other forms of exports
in the same uses with
clause. exports
option followed by a list of variables specifies exactly which of the variables to re-export. The variable names can be specified on separate lines, on the same line separated by commas, or in any combination.exports
option with the instance variables
reserved words (or the readOnly
instance variables
reserved words) is syntactic shorthand for re-exporting the setter and getter generic functions for the named instance variables (or, in the case of readOnly
, only the getter method). See "Exporting Classes" on page 203 for more information on importing and exporting classes and their methods and variables. The instance variables
reserved words can be shortened to instance vars
or simply inst vars
. All are equivalent.
The example uses module
XYZ
, just as in the previous section. module XYZ
uses ScriptX
exports x, y, z
end
in module XYZ
global x:10, y:"foo", z:#(56,567)
XYZexport
, which exports its own variables (a
and b
), imports everything from module XYZ
, renames x
to otherX
, and transitively exports otherX
and y
.module XYZexport
exports a, b
uses ScriptX
uses XYZ with
imports everything
renames x:otherX
exports otherX, y
end
end
in module XYZexport
global a := "croissant"
global b := pi
print otherX
10
moreXYZexport
uses XYZexport
and imports all. The variables that get imported are y
(from module XYZ
), otherX
(which is actually the variable x
from module XYZ
) and a
and b
(from module XYZexport
).module moreXYZexport
uses ScriptX
uses XYZexport with
imports everything
end
end
in module moreXYZexport
print a
"croissant"
print b
3.14159
print y
"foo"
print otherX
10
print x
-- ** moreXYZexport:x does not have a variable value \
(UninitializedVariable)
This document is part of the ScriptX Language Guide, one of the volumes of the ScriptX Technical Reference Series. ScriptX is developed by the ScriptX Engineering Team at Apple Computer, successor to the Kaleida Engineering Team at Kaleida Labs, Inc.