Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
The Ring programming language version 1.4 book - Part 20 of 30
1. Ring Documentation, Release 1.4
show()
}
Func Increment
label1 {
setText( "" + ( 0 + text() + 1 ) )
}
Class SecondWindow
win = new qWidget() {
setgeometry(400,50,300,200)
setWindowTitle("Second Window")
label1 = new qLabel(win)
{
setgeometry(10,10,300,30)
setText("0")
}
btn1 = new qPushButton(win)
{
move(100,100)
setText("Decrement")
setClickEvent($ObjectName+".decrement()")
}
show()
}
Func Decrement
label1 {
setText( "" + ( 0 + text() - 1 ) )
}
55.12 Conflict between self inside braces and self in the class region
In the class region (after the class name and before any methods) we define the attributes.
In this region we have access to the global scope and the local scope will point to the object scope.
Three Scopes
• Global Scope —> Gloabl Scope
• Object Scope —> Object Scope
• Local Scope —> Object Scope
Look at this example
New Account {
see aFriends
}
Class Account
name = "Mahmoud"
aFriends = []
aFriends + new Friend {
name = "Gal"
55.12. Conflict between self inside braces and self in the class region 548
2. Ring Documentation, Release 1.4
}
aFriends + new Friend {
name = "Bert"
}
Class Friend
name
Output:
name: NULL
name: NULL
The problem in the previous example is that the Class account contains an attribute called “name” and the Friend class
contains an attribue called “name” also.
If you tried using self.name inside braces you will get the same result!
New Account {
see aFriends
}
Class Account
name = "Mahmoud"
aFriends = []
aFriends + new Friend {
self.name = "Gal"
}
aFriends + new Friend {
self.name = "Bert"
}
Class Friend
name
So why using self.name inside braces doesn’t solve this conflict?
Because after the class region we have
• global scope —> global scope
• object scope —> object scope (Account Class)
• local scope —> local scope (Account Class)
When we use braces we change the object scope, so we have
• global scope —> global scope
• object scope —> object scope (Friend Class)
• local scope —> local scope (Account Class)
Ring search in the local scope first, so using self.name will use the Account class.
There are many solution
Solution (1) : Access the object through the list
New Account {
see aFriends
}
Class Account
55.12. Conflict between self inside braces and self in the class region 549
3. Ring Documentation, Release 1.4
name = "Mahmoud"
aFriends = []
aFriends + new Friend
aFriends[len(aFriends)] {
aFriends[len(aFriends)].name = "Gal"
}
aFriends + new Friend
aFriends[len(aFriends)] {
aFriends[len(aFriends)].name = "Bert"
}
Class Friend
name
Solution (2) : Create Method in the friend class to set the name attribute.
New Account {
see aFriends
}
Class Account
name = "Mahmoud"
aFriends = []
aFriends + new Friend {
setname("Gal")
}
aFriends + new Friend {
setname("Bert")
}
Class Friend
name
func setname cName
name = cName
Solution (3) : Create a method in the account class to set the attribute
New Account {
see aFriends
}
Class Account
name = "Mahmoud"
aFriends = []
friend("Gal")
friend("Bert")
func friend cName
aFriends + new Friend {
name = cName
}
Class Friend
name
Solution (4) : Declarative Programming
New Account {
name = "mahmoud"
friend {
55.12. Conflict between self inside braces and self in the class region 550
4. Ring Documentation, Release 1.4
name = "Gal"
}
friend {
name = "Bert"
}
see aFriends
}
Class Account
name
aFriends = []
friend
func getfriend
aFriends + new Friend
return aFriends[len(aFriends)]
Class Friend
name
Output:
name: Gal
name: Bert
55.13 Using braces to escape from the current object scope
Since braces change the current object scope to another object. we can use it to do some work without modifying the
class attributes and using the same variable names.
new point {x=10 y=20 z=30 start() }
class point x y z
func start
see self # print the x y z values (10,20,30)
new Local {
x = 100
y = 200
z = 300
}
see self # print the x y z values (10,20,30)
see x + nl # will print 100
see y + nl # will print 200
see z + nl # will print 300
Self { # NO Advantage - Search is done in local scope first
see x + nl # will print 100
see y + nl # will print 200
see z + nl # will print 300
}
see self.x + nl # will print 10
see self.y + nl # will print 20
see self.z + nl # will print 30
class Local
Output:
x: 10.000000
y: 20.000000
55.13. Using braces to escape from the current object scope 551
5. Ring Documentation, Release 1.4
z: 30.000000
x: 10.000000
y: 20.000000
z: 30.000000
100
200
300
100
200
300
10
20
30
55.14 Summary of Scope Rules
At first remember that
1 - Each programming language comes with it’s scope rules based on the language goals
2 - Programming in the small is different than Programming in the Large
3 - Some programming language are designed for developing small programs while others are designed for large
programs
4 - In programming, If we have access to more than one scope - Then problems may come if we don’t manage things
correctly
5 - It’s always more secure to reduce the number of visible scopes
6 - Some programming languages force you to manage the scope in some way, while others not!
In Ring
1 - Special and very simple scope rules that are designed for Flexibility first then Security
2 - Ring is designed to support programming in the small and programming in the large.
3 - The language provide the different programming paradigms that you may select from based on the project size.
Errors comes only if you selected a bad paradigm for the target project or you are using the paradigm in a way that is
not correct or at least not common.
4 - In Ring you have the choice, you can use global variables or avoid them. you can give them a special $ mark or
leave them. you can use object-oriented or stay with procedures. you can use the class region (after the class name
and before any method) just for attributes or use it for code too.
5 - Just read the next scope rules and think about them then use them in your favorite way.
Scope Rules:
1 - At any place in our program code we have only at maximum Three Scopes (Local Scope, Object Scope and Global
Scope).
2 - When Ring find a variable it will search in the local scope first then in the object scope then in the global scope.
3 - At any time inside procedures or methods you can use braces { } to access an object and change the current object
scope.
4 - In the class region (After the class name and before any method) this is a special region where both of the object
scope and the local scope point to the object scope. I.e. No local variables where each variable you define in this
region will become an attribute.
55.14. Summary of Scope Rules 552
6. Ring Documentation, Release 1.4
5 - Before defining any variable (in any scope and in the class region too) a search process will be done to use the
variable if it’s found.
6 - Functions and Methods parameters are defined automatically as local variables to these functions or methods.
7 - Using Object.Attribute will search in the object attributes only.
8 - Using Self.Attribute will lead to a search for Self first then search in Self Attributes.
9 - The Self reference inside class region (after the class name and before any method) always point to the object scope
created from the class.
10- The Self reference inside methods will be changed when we uses Braces to be a reference to the object that we
access.
11- Writing variable names directly in the class region (after the class name and before any method) means using them
or define then (in order).
12- Using self.attribute in the class region reduce search to the object scope (avoid conflict with global scope).
From these rules you can understand all types of conflicts and why you may have them and how to avoid them
Simple advices to avoid any conflict and use the scope rules in a better way
1 - Try to avoid global variables
2 - Use the Main Function - This will help you to avoid global variables
3 - If you are going to use many global variables use the $ mark before the variable name
4 - In the class region if you don’t respect the advice number three ($) then use self.attribute when you define your
attributes
5 - You can use object.attribute and object.method() instead of object { attribute } and object { method() } if you don’t
like changing the object scope.
6 - If you will use nested braces in a class - think about using the class region if possible because in this region you
will have access to the object that you access using { } + access to the class attributes
7 - If you are inside a class method and used nested braces you will change the object scope with each brace and you
will loss the access to the class attributes directly but you have access to the local scope before and after using brace
{ } , if you will read/modify the class attribute from braces then use This.Attribute because using ‘This’ means (The
object created from this class) while using ‘Self’ means (The object in the current object scope).
After understanding all of the previous points, You will master this topic.
55.14. Summary of Scope Rules 553
7. CHAPTER
FIFTYSIX
SCOPE RULES FOR FUNCTIONS AND METHODS
In this chapter we will learn about the scope rules for functions and methods.
You need to know the next information once you started using Ring for large applications.
These applications may contains and use
• Many Packages and Classes written in Ring
• Many Functions written in Ring
• Standard Ring Functions (Written in C language)
• Functions and Classes written in C/C++ languages
56.1 How Ring find the Functions and Methods?
When you call a method or function, Ring will start a search process to find this function
If found –> Call the function and store the function pointer in the cache so Ring can use it again with doing another
search.
If not found —> Runtime error message (That you can avoid using Try/Catch)
How the search process is done?
Search for functions/methods follow the next order
1 - Search in methods (if we are inside class method or object using braces {})
2 - Search in functions written by the programmer using Ring Code
3 - Search in functions written in C/C++ like standard Ring functions
This enable us to write clean code inside classes methods and avoid any conflict with functions.
If we want to call a function with the same name as a method in the class we will need a wrapper function or we will
access a temp. object using { } then call that function there.
We can replace C/C++ Functions with Ring Functions.
We can replace Ring Functions with Ring Methods.
Note: Using self.method() is not necessary in any use case.
Tip: We can use this.method() to escape from the current active scope that we access using braces {} and call a
method in the class that we are inside.
554
8. Ring Documentation, Release 1.4
56.2 Example about Sharing Names between Functions and Methods
Look at the next example
func main
o1 = new myclass { test() test2() }
test2()
func f1
see "f1 function" + nl
func f2
see "f2 function" + nl
func f3
see "f3 function" + nl
func test2
myline()
see "test2 function" + nl
new myclass {
f1()
f2()
f3()
self.f3()
}
myobj = new myclass
myobj.f3()
myline()
func myline
see copy("=",40) + nl
Class myclass
func test
myline()
see "test method" + nl
f1()
f2()
f3()
myline()
func f3
see "f3 method" + nl
func test2
myline()
see "test2 method" + nl
self {
f1()
f2()
f3()
}
myline()
Output:
56.2. Example about Sharing Names between Functions and Methods 555
9. Ring Documentation, Release 1.4
========================================
test method
f1 function
f2 function
f3 method
========================================
========================================
test2 method
f1 function
f2 function
f3 method
========================================
========================================
test2 function
f1 function
f2 function
f3 method
f3 method
f3 method
========================================
56.3 Calling a function sharing the name with a method in the current
class
In the previous example we have a function called f3() and we have a method called f3()
How we can call the f3() function from the test() method ?
Solution (1) : Change the current object scope to another object scope
In this solution we will have an empty class called local that we will use to change the current object scope.
func main
o1 = new myclass { test()}
func f1
see "f1 function" + nl
func f2
see "f2 function" + nl
func f3
see "f3 function" + nl
func myline
see copy("=",40) + nl
Class myclass
func test
myline()
see "test method" + nl
f1()
f2()
f3() # call f3() method
new local { f3() } # call f3() function
myline()
56.3. Calling a function sharing the name with a method in the current class 556
10. Ring Documentation, Release 1.4
func f3
see "f3 method" + nl
class local
Output:
========================================
test method
f1 function
f2 function
f3 method
f3 function
========================================
56.3. Calling a function sharing the name with a method in the current class 557
11. CHAPTER
FIFTYSEVEN
SYNTAX FLEXIBILITY
In this chapter we will learn about some options that are provided automatically by the Ring compiler for syntax
flexibility.
57.1 Change Language Keywords
We can change any keyword using the ChangeRingKeyword command.
Note: Remember to restore the keyword again if the team will mix between styles in the same project.
Tip: The ChangeRingKeyword command is executed in the scanner stage by the compiler (before parsing).
Syntax:
ChangeRingKeyword <oldkeyword> <newkeyword>
Example:
ChangeRingKeyword see print
print "welcome" + nl
ChangeRingKeyword print see
see "Welcome" + nl
Example:
ChangeRingKeyword func function
ChangeRingKeyword see print
ChangeRingKeyword ok endif
ChangeRingKeyword next endfor
ChangeRingKeyword end endwhile
x = 10
while x > 0
print "x = " + x + nl
for t = 1 to 10
if t = 3
print "number three" + nl
endif
endfor
558
12. Ring Documentation, Release 1.4
x--
endwhile
test()
function test
print "message from test" + nl
ChangeRingKeyword function func
ChangeRingKeyword print see
ChangeRingKeyword endif ok
ChangeRingKeyword endfor next
ChangeRingKeyword endwhile end
57.2 Change Language Operators
We can change any operator using the ChangeRingOperator command.
Note: Remember to restore the operator again if the team will mix between styles in the same project.
Tip: The ChangeRingOperartor command is executed in the scanner stage by the compiler (before parsing).
Syntax:
ChangeRingOperator <oldkeyword> <newkeyword>
Example:
The next program hide the + operator by changing it to _+
changeringoperator + _+
changeringkeyword SEE PRINT
try
print 5 + 10
catch
print nl print "error" print nl
done
changeringoperator _+ +
The next program change the + operator to “plus”.
changeringoperator + plus
changeringkeyword SEE PRINT
Print 5 plus 5
changeringoperator plus +
changeringkeyword PRINT SEE
57.2. Change Language Operators 559
13. Ring Documentation, Release 1.4
57.3 Load Syntax Files
You may store a group of ChangeRingKeyword and ChangeRingOperator commands in a file to use later in many
source files. You can’t use the Load command to call these files because
• ChangeRingKeyword and ChangeRingOperator commands are executed in the scanner phase by the compiler
(before parsing).
• The load command is executed in the parsing phase (after the scanner phase).
Solution: Use the LoadSyntax Command which is executed in the scanner phase.
Syntax:
LoadSyntax "syntaxfile.ring"
Example:
File : StyleBasicOn.ring
ChangeRingKeyword see print
ChangeRingKeyword ok endif
ChangeRingKeyword next endfor
ChangeRingKeyword end endwhile
File : StyleBasicOff.ring
ChangeRingKeyword print see
ChangeRingKeyword endif ok
ChangeRingKeyword endfor next
ChangeRingKeyword endwhile end
File : UseStyleBasic.ring
LoadSyntax "stylebasicon.ring"
x = 10
while x > 0
print "x = " + x + nl
for t = 1 to 10
if t = 3
print "number three" + nl
endif
endfor
x--
endwhile
LoadSyntax "stylebasicoff.ring"
see "done" + nl
Note: files called by the LoadSyntax command must contains ChangeRingKeyword and ChangeRingOperator com-
mands only.
Tip: files called by the LoadSyntax command doesn’t support functions, packages and classes. just imperative
commands only.
Note: Using this feature you can create many styles that you can use in the same project and you can support Ring
57.3. Load Syntax Files 560
14. Ring Documentation, Release 1.4
translation to other languages like Arabic, French and so on.
57.4 Using “()” around the function parameters
We can use () around the function parameters (optional).
Example:
hello()
sum(3,4)
func hello()
see "Hello" + nl
func sum(x,y)
see x+y+nl
Output:
Hello
7
Example:
myfunc = func x,y { see x + y + nl }
call myfunc (3,4)
myfunc2 = func (x,y) { see x+y+nl }
call myfunc(3,4)
Output:
7
7
57.5 Using Semi-colon after and between statements
In Ring we can use semi-colon after and between statements (optional).
Example:
# Using semi-colon is optional
see "Hello" + nl ; see "How are you?" + nl ; see "Welcome to Ring" + nl ;
one() ; two() ; three() ;
func one ; see "one" + nl ;
func two ; see "two" + nl ;
func three ; see "three" + nl ;
Output:
Hello
How are you?
Welcome to Ring
57.4. Using “()” around the function parameters 561
15. Ring Documentation, Release 1.4
one
two
three
57.6 Using $ and @ in the start of the variable name
You can use any unicode character in the variable name also we can use $ and @ in the name.
This feature may help, for example we can start global variables with $ and the object attributes with @.
In other languages like Ruby this is the rule, In the Ring language this is just an option without any force from the
Compiler.
example:
$global_variable = 5
new test { hello() }
class test
@instance_variable = 10
func hello
local_variable = 15
see "Global : " + $global_variable + nl +
"Instance : " + @instance_variable + nl +
"Local : " + local_variable + nl
Output:
Global : 5
Instance : 10
Local : 15
57.7 Using the ‘elseif’ keyword as ‘but’ in if statement
if you don’t like the ‘but’ keyword in if statement Then you can use the ‘elseif’ keyword.
Example:
give x
if x = 1 see "one"
elseif x=2 see "two"
elseif x=3 see "three"
elseif x=4 see "four"
else see "other"
ok
see nl
57.6. Using $ and @ in the start of the variable name 562
16. Ring Documentation, Release 1.4
57.8 Using the ‘else’ keyword as ‘other’ in switch statement
if you don’t like the ‘other’ keyword in switch statement Then you can use the ‘else’ keyword.
Also you can replace ‘else’ with ‘other’ in if statement.
i.e. ‘other’ keyword is the same as ‘else’ keyword.
Example:
x = 1
switch x
on 10
see "10" + nl
else
see "not 10" + nl
end
Output:
not 10
57.9 Using the ‘end’ keyword in different control structures
We can use the ‘end’ keyword to close different control structures
• If statement
• For loop
• Switch
• While
• Try-Catch
Example:
see "if statement.." + nl
x = 1
if x = 1
see "one" + nl
elseif x=2
see "two" + nl
elseif x=3
see "three" + nl
end
see "for loop.." + nl
for t = 1 to 10
see t
end
see nl
see "switch..." + nl
x = 1
switch x
on 1 see "one" + nl
on 2 see "two" + nl
end
57.8. Using the ‘else’ keyword as ‘other’ in switch statement 563
17. Ring Documentation, Release 1.4
see "try catch..." + nl
try
x = 1 / 0
catch
see "catching error" + nl
end
Output:
if statement..
one
for loop..
12345678910
switch...
one
try catch...
catching error
57.10 Using braces to start and end different control structures
We can use braces { } to start and end different control structures
• If statement
• For loop
• Switch
• While
• Try-Catch
Example:
see "if statement.." + nl
x = 1
if x = 1 {
see "one" + nl
elseif x=2
see "two" + nl
elseif x=3
see "three" + nl
}
see "for loop.." + nl
for t = 1 to 10 {
see t
}
see nl
see "switch..." + nl
x = 1
switch x {
on 1 see "one" + nl
on 2 see "two" + nl
}
see "try catch..." + nl
try {
57.10. Using braces to start and end different control structures 564
18. Ring Documentation, Release 1.4
x = 1 / 0
catch
see "catching error" + nl
}
Output:
if statement..
one
for loop..
12345678910
switch...
one
try catch...
catching error
57.11 Using ‘put’ and ‘get’ as ‘see’ and ‘give’
We can replace the ‘see’ keyword with the ‘put’ keyword.
Also we can replacew the ‘give’ keyword with the ‘get’ keyword.
Example:
put "Hello World" + nl
put "Enter Your Name ? " Get Name
Put "Hello " + Name
57.12 Using ‘case’ as ‘on’ in switch statements
We can replace the ‘on’ keyword with ‘case’ keyword in the switch statement.
Example (1) :
for x=1 to 10
switch x
case 1 put "one" + nl
case 2 put "two" + nl
case 3 put "thre" + nl
else put "else" + nl
end
end
Example (2) :
for x=1 to 10 {
switch x {
case 1 put "one" + nl
case 2 put "two" + nl
case 3 put "thre" + nl
else put "else" + nl
}
}
57.11. Using ‘put’ and ‘get’ as ‘see’ and ‘give’ 565
19. Ring Documentation, Release 1.4
57.13 Using ‘def’ as ‘func’ in functions/methods definition
We can use the ‘def’ keyword as the ‘func’ keyword to define functions and methods.
Example:
one() two()
def one put "one" + nl
def two put "two" + nl
57.13. Using ‘def’ as ‘func’ in functions/methods definition 566
20. CHAPTER
FIFTYEIGHT
DISTRIBUTING RING APPLICATIONS
In this chapter we will learn about distributing Ring applications.
58.1 Distributing Applications for Microsoft Windows
Step 1:
Copy c:ringbin folder to be for example c:myapp
Step 2:
Rename c:myappring.exe to c:myappmyapp.exe
Step 3:
Create a file c:myappring.ring
And write
Load "myapp.ring"
When you run myapp.exe the file ring.ring will be executed automatically
So your file myapp.ring will be called and executed
Or just rename myapp.ring to ring.ring
It’s a fast way to distribute applications.
58.2 Protecting the Source Code
Step 1:
Execute the next command
ring myapp.ring -go
This will generate one object file (myapp.ringo) from the project files (*.ring)
Step 2:
Rename myapp.ringo to ring.ringo
When you run the executable file (ring.exe) or (myapp.exe) the file ring.ringo will be executed.
567
21. Ring Documentation, Release 1.4
58.3 Creating Windows Installer
There are many tools that you can use to distribute your application.
Check : nullsoft scriptable install system
URL : http://nsis.sourceforge.net/Main_Page
58.4 Using C/C++ Compiler and Linker
Another method to distribute applications is to use a C/C++ compiler.
Ring can be embedded in C/C++ projects, We can create executable files using a C/C++ compiler by embedding the
Ring language in our project.
Check the “Embedding Ring Language in C/C++ Programs” chapter.
Using this way we will avoid using ring.ring or ring.ringo files.
58.5 Distributing Applications and Games for Mobile
Ring can be embedded in a Qt projects or LibSDL projects to build Mobile applications and Games.
You can build the Qt project or the LibSDL project and get the Android package directly (*.apk)
Check Ring distributions for Mobile development using Qt or LibSDL.
58.3. Creating Windows Installer 568
22. CHAPTER
FIFTYNINE
COMMAND LINE OPTIONS
The ring language takes source code file (.ring) or the object file (.ringo) as input to execute, also the language provide
other options like
Option Description
-tokens Print a list of tokens in the source code file
-rules Print grammar rules applied on the tokens
-ic Print the intermediate byte code (before execution)
-icfinal Print the final byte code (after execution)
-cgi Print http response header before error messages
-norun Don’t run the program after compiling
-ins Print instruction operation code before execution
-performance Print clock before and after program execution
-go Generate Object File
-w Display Warnings
59.1 Printing Tokens
Example:
Func Main
See "Hello World" + nl
for x = 1 to 10
see x + nl
next
test()
func test
see "welcome" + nl
o1 = new point { x=10 y=20 z=30 }
see o1
class point x y z
Command:
ring test.ring -tokens -norun
Output:
===================================================
Tokens - Generated by the Scanner
===================================================
569
23. Ring Documentation, Release 1.4
Keyword : FUNC
Identifier : main
EndLine
Keyword : SEE
Literal : Hello World
Operator : +
Identifier : nl
EndLine
Keyword : FOR
Identifier : x
Operator : =
Number : 1
Keyword : TO
Number : 10
EndLine
Keyword : SEE
Identifier : x
Operator : +
Identifier : nl
EndLine
Keyword : NEXT
EndLine
Identifier : test
Operator : (
Operator : )
EndLine
Keyword : FUNC
Identifier : test
EndLine
Keyword : SEE
Literal : welcome
Operator : +
Identifier : nl
EndLine
Identifier : o1
Operator : =
Keyword : NEW
Identifier : point
Operator : {
Identifier : x
Operator : =
Number : 10
Identifier : y
Operator : =
Number : 20
Identifier : z
Operator : =
Number : 30
Operator : }
EndLine
Keyword : SEE
Identifier : o1
EndLine
Keyword : CLASS
Identifier : point
Identifier : x
Identifier : y
Identifier : z
59.1. Printing Tokens 570
24. Ring Documentation, Release 1.4
EndLine
===================================================
59.2 Printing Rules
Command:
ring test.ring -rules -norun
Output:
===================================================
Grammar Rules Used by The Parser
===================================================
Rule : Program --> {Statement}
Line 1
Rule : Statement --> 'Func' Identifier [ParaList]
Line 2
Rule : Factor --> Literal
Rule : Range --> Factor
Rule : Term --> Range
Rule : Arithmetic --> Term
Rule : Factor --> Identifier [ {Mixer} | Assignment | PlusPlus | MinusMinus]
Rule : Range --> Factor
Rule : Term --> Range
Rule : Arithmetic --> Term
Rule : Arithmetic --> Arithmetic + Arithmetic
Rule : BitShift --> Arithmetic
Rule : BitAnd --> BitShift
Rule : BitOrXOR --> BitAnd
Rule : Compare --> BitOrXOR
Rule : EqualOrNot --> Compare
Rule : LogicNot -> EqualOrNot
Rule : Expr --> LogicNot
Rule : Statement --> 'See' Expr
Line 3
Rule : Factor --> Number
Rule : Range --> Factor
Rule : Term --> Range
Rule : Arithmetic --> Term
Rule : BitShift --> Arithmetic
Rule : BitAnd --> BitShift
Rule : BitOrXOR --> BitAnd
Rule : Compare --> BitOrXOR
Rule : EqualOrNot --> Compare
Rule : LogicNot -> EqualOrNot
Rule : Expr --> LogicNot
Rule : Factor --> Number
Rule : Range --> Factor
Rule : Term --> Range
Rule : Arithmetic --> Term
Rule : BitShift --> Arithmetic
59.2. Printing Rules 571