In this chapter:

Book: The Judo Language 0.9

Chapter 3. Basic Program Structure

By James Jianbo Huang


non-printer version
Synopsis: This chapter introduces the most elementary parts of Judo as a general-purpose programming language, including its lexical structure, variables and constants, start-up environment and environment interfaction, including sub-scripts, etc.

Judo is a free-form, case-sensitive, block-structured language. Whitespaces and line breaks are ignored except for within string literals. Statements are ended by semicolons (;). Multiple statements and any language constructs can be on the same line, although style-wise this may not be desirable most of the time.

Most language entities are case-sensitive. There are a few situations where names can be case-insensitive; one example is SQL statements and types, as SQL is a case-insensitive language and is only natural to ignore the case.

The basic structure of Judo language is block-based, just like Java, C or C++. A pair of curly braces ({ }) delimits a block; each block defines a scope. A block can exist by its own, or it can be an integral part of a statement (such as if, while, etc.) or a construct (such as a class body). Blocks, like statements, can be enclosed in other blocks. Blocks may be of different semantic meanings, depending on their usages. For instance, a class body means quite differently to a function body or a SGML statement block, even though syntactically they are all blocks.

 
Lexical Structure

Identifiers, Variable and Constants

Judo identifiers are used for many purposes, including names for variables, functions, threads, user-defined classes, and labels. Letters, digits, underscore (_) and dollar sign ($) are legitimate constituents of Judo identifiers; identifiers can start with letters, dollar signs, underscores but not digits. Identifiers starting with $$ are reserved for Judo internal variables, which can be accessed but can not be assigned. The following are examples of legitimate identifiers:

Hello
$likeperl
basic$1$2$3
_priv
_1

The following are examples illegal attempts for identifiers:

1st
reg-expr
.bashrc

Constant names starts with a pound sign (#); the rest is the same as variable names. For using constants, see 3.1.


Reserved Words

TODO: list all reserved words

Comments

Judo supports as many as five formats of comments. Four of them are general comment, and one is only valid in SQL statements.

Java-like comments
The two most commonly used comments are the same as those of Java or C++, i.e., multi-line comment are enclosed between /* */, and anything following // up to the end of line is comment. Here is some examples.

/*
   This is a multi-line comment.
   This is a multi-line comment.
   This is a multi-line comment.
*/

// this is a single line comment.

Comment for disabling code
The third form of comment in Judo is /? ?/. This is similar to /* */; the reason for this format is to disable a large chunk of code. For instance,

/? --- DISABLE THIS CHUNK OF THE CODE FOR NOW.
  if a != 'init' { // for this condition
    /*
     * Some code comment
     */
    do_something(a);
  }
--- ?/

The outer comment block /? ?/ "hides" everything within, including other comments such as /* */. In fact, an outer block of /* */ can also hide /? ?/; by convention, /* */ is more for regular comments, and /? ?/ is for disabling code.

Unix auto-run comment
In most Unix shells, files that start with #! can be run automatically by the program specified on that line (and, of course, the file mode must be set to executable.) Judo supports the same mechanism with the special single-line comment, #!:

#! /usr/bin/env judo

We will discusss this topic specifically in section Make Scripts Executable on Unix.

SQL comment
Scripts of many RDBMSs support single-line comment that starts with --. In Judo, within SQL statements, this format of comment is also supported. This makes SQL statements in Judo appear even closer to the native SQL scripts, and is also important to run native SQL scripts verbatim (in many situations.) The following is a couple of examples:

executeSQL: // individual SQL
  UPDATE emp SET first_name='James'
  WHERE emp_no=100         -- Employee #100.
;

executeSQL { // group SQLs
  /*
   * All other types of comments are also valid.
   */

  UPDATE emp SET first_name='James'
  WHERE emp_no=100;        -- Employee #100.

  UPDATE emp SET first_name='Jim'
  WHERE emp_no=101;        -- Employee #101.
}

Note that, for individual SQL statements, the -- comment must appear before the ending semicolon (;); for group SQL statements, comments can appear anywhere within { }. Within SQL statements, other forms of comments are also legitimate.



 
Variables and Scopes

Judo variables are not typed; the values held in Judo variables, though, are typed. This is called dynamic typing. Anywhere in the program, the value of a variable is assumed known, so that corresponding attributes (properties and methods) can be accessed. This is the nature of most scripting languages. The benefit is simple and easy to use, the cost is uncertainty. Parameters in functions and methods are also variables. In the forth-coming JudoScript version 1.0, variable static typing will be added; dynamic typing will still stay.

Variable names can be any legitimate identifiers. Variable names can start with a dollar sign ($). Names starting with a double dollar sign ($$) are reserved for Judo internal variables, as discussed below.

Variable scopes
Variables have scopes, which is roughly equivalent to certain blocks delimited by { and }. One scope may enclose other scopes, where the outer ones are the parents of the enclosed scopes. A variable resides in one scope, and can be accessed by the enclosed scopes. If a same-name variable exists in the enclosed scope, the one in the parent scope is shield and not accessible.

Compound statements such as for and while loops have a mandatory body and hence create new scopes. These are discussed in more details later.

Two big exceptions are the if/elif/else and switch/case/default statements! These two statements have blocks but do not create new scopes. This is because they are simple branching statements.

When a variable is assigned a value, Judo tries to locate the variable starting from the current scope; if not found, it looks in the parent scope and so on, until either it is either found or a terminal scope is reached, discussed blow. If that variable is not located, a local variable with that name will be created in the current scope. To explicitly create a local variable, so declare a variable with var, as demonstrated with this example:

{
  a = 9;  // a variable here.
  {
    println a; // result: 9

    var a = 5;

    println a; // result: 5
  }
}

Terminal scopes
A terminal scope is one of the following: the global scope, a function or thread scope, and a user-defined class scope.

When a program starts, it is in its global scope. A global scope is a terminal scope. Variables in the global scope can be accessed explicitly via the :: decorator for the variable name, demonstrated below:

a = 9; // a global variable
{
  println a; // result: 9

  var a = 5;
  println a; // result: 5

  println ::a; // result: 9
}

This :: global variable access decorator can be used anywhere, including within function, method and thread bodies.

Functions and threads in Judo are defined very similarly, although their usages are totally different. A function or thread scope is a terminal scope. This will be discussed in detail in Functions and Function Variables and chapter 8. Threads and Dynamic Evaluation.

User-defined classes can have methods, which are functions attached to an object of that class. Method scopes, unlike non-method functions, are not terminal scope; they have a parent scope, the class scope, which is a terminal. This will be discussed more in chapter 10. Object-Oriented Programming.

The special variable $_
This is a variable that is used in many situations by Judo, when a result is expected but no explicit variable reference is given. Such $_ variables are always in the local scope (variable scope is discussed later). For instance, in JDBC scripting, executeQuery, executeUpdate and executeSQL can optionally take a variable name; if no variable name is supplied, $_ will be used. To be safe, you should try to specify a variable explicitly rather than use $_. In other cases, such as the file system list command, where you don't have a chance to specify a different variable name, try to assign $_ to a variable before going too far.

Other special variables
Judo has defined a few special variables, like the global variable $$con that holds the default database connection and $$args in a function that is an array that holds all the passed-in parameters. These variables are generally read-only by the application code.

Dynamic variables
In Judo, variables can be created programmatically through two system functions, setVariable() and convertToVariables(). The setVariable() function takes a name and a value, and optionally can take a boolean flag indicating whether the variable should be created locally; if not specified or is false, the variable is set or created according to the usual rule for variable assignment. The convertToVariables() function convers values stored in an Object into variables, using the same rules for setVariable(). Note that the names must be legitimate variable names; otherwise they are simply ignored. The following example shows how this can be done:

Listing 3.1 dyn_vars.judo
// Dynamically set one variable
setVariable('xyz', 5);

// Dynamically set a number of variables
a = { x = 'x as set in Object',
      y = 9,
      '09898aa' = "this won't be a variable."
    };
convertToVariables(a);

println 'xyz = ', xyz; // result: 5
println 'x = ', x;     // result: x as set in Object
println 'y = ', y;     // result: 9


The { } declares a literal value for a new Object. In that object, a, there are three keys; the last one is not a valid variable name and hence not accessible in the program once the keys and values are converted to be variables.

 
Constants

Constants are defined with the const decorator, and once a constant is defined, it can not be reassigned. Constants always have global scoping.

const #PI = 3.1415926536;

Constant declaration is a compile-time activity. Similar compile-time activities include function and thread declaration and user-defined class declaration. These declarations are collected at compile time, and are instantiated prior to the sciprt is executed. Therefore, these declarations can appear anywhere in a script and are still applicable to the whole script. For instance,

Listing 3.2 const.judo
println '    #PI = ', #PI : 2.7;
println '5 * #PI = ', 5 * #PI : 2.7;

const #PI = 3.1415926536;
println '    #PI = ', #PI : 2.7;

The result is:

    #PI =  3.1415927
5 * #PI = 15.7079633
    #PI =  3.1415927

Constants can be defined with any values and any constant expressions. For example,

Listing 3.3 apple_pi.judo
const #PI = 3.1415926536;
const #apple_PI = 'Apple ' + #PI;

println #apple_PI;

yields:

Apple 3.1415926536

Detect the existence of constants
The defined expression can be used to detect whether a constant has been defined or not. Alternatively, you can compare a constnat against the undefined value for the same purpose.

Listing 3.4 defined.judo
const #ccc = 1;

if defined #ccc {
  println '#ccc is defined.';
}

if #ccc != undefined {
  println '#ccc is defined.';
}

Conditional constant declaration
The complete constant declaration syntax is:

Constant ::= const CONST_NAME = Expr [ ifndef | if Expr ] ;

Constants can be conditionally defined. This is useful when another file is included in the current script and you want to make sure a constant is defined. The first form with ifndef is equivalent to do a defined check on the current constant being defined. The second form is obvious. A usage would be like this:

!include 'common.judi'

const #tmp = '~/tmp/' ifndef;

mkdir #tmp;

File inclusion is discussed in Include Other Scripts.

Predefined Constants

Judo has a number of predefined constants, listed below.

Table 3.1 Predefined Constants
NameDescription
#versionInfothe version information of the current Judo runtime, such as "JudoScript Language v0.9 2004-6-26 (JDK1.3+)".
#versionIDthe version ID of the current Judo runtime, such as "v0.9".
#userthe current user name running the script.
#yearthe current year of running.
#scriptthe script file path. Subsequently, you can get the script file name with #script.getFileName() and the directory where the script resides with #script.getFilePath().
#progthe script name. For regular script files, this is the same as #script.getFileName(); in special situations, #prog may be set where #script is not valid.
#cmd_argsan array that contains all the command line arguments.
#argsan array that contains the command line arguments except for options; see Start-Up Environment for details.
#optionsan object that contains the command line options; see Start-Up Environment for details.
#syspropsthe system properties of the currenv JVM. See System Properties and Environment Variables for details.
#classpaththe classpath object. See Classpath for details.
#usagean object that documents this script; see Program Documentation for details.

There are a few constant values in Judo that are represented in other formats, such as:

Table 3.2 Predefined Constants In Other Forms
${:}the platform-dependent path separator. On Unix it is :; on Windows it is ;. This character is frequently used in constructing classpaths.
${/}the platform-dependent file name separator, that is, the character that separates the file name and directory names in a path. On Unix it is /; on Windows it is \.
${~}the home directory of the user running the script.
${.}the current directory. This can be changed by the cd command, so it is not strictly a constant value; it starts with the current directory when the script is being run.

These notations can be, like any ${xyz}, embedded in string literals, as discussed in String and Character.



 
back to top
 


Copyright c 2001-2021 JudoScript.COM. All Rights Reserved.