# Ring/Lessons/Reflection and Meta-programming

## Reflection and Meta-programming

Since the Ring programming language is a dynamic language, we can get answers about the program code and we can modify our code during the runtime.

## locals() Function

We can get a list of variables names in the current scope using the locals() function.

Syntax:

`	locals() --> a list contains the variables names in the current scope`

Example:

```	test("hello")

func test cMsg

see cMsg + nl

x = 10
y = 20
z = 30

see locals()```

Output:

```	hello
cmsg
x
y
z```

## globals() Function

We can get a list of variables names in the global scope using the globals() function.

Syntax:

```
globals() --> a list contains variables names in the global scope```

Example:

```	x=10 y=20 z=30
test()

func test
see "message from test()" + nl +
"Global Variables:" + nl
see globals()```

Output:

```	message from test()
Global Variables:
x
y
z```

## functions() Function

We can get a list of functions names written in the Ring language using the functions() function.

Syntax:

`	functions() --> a list contains functions names`

Example:

```	see functions()

func f1
see "f1" + nl

func f2
see "f2" + nl

func f3
see "f3" + nl```

Output:

```	f1
f2
f3```

## cfunctions() Function

We can get a list of functions names written in the C language using the cfunctions() function.

Syntax:

`	cfunctions() --> a list contains functions names`

Example:

```	aList =  cfunctions()
See "Count : " + len(aList) + nl
for x in aList
see x + "()" + nl
next```

Output:

```	Count : 186
len()
del()
get()
clock()
...```

.. note:: The complete list is removed from the previous output.

## islocal() Function

We can check if a variable is defined in the local scope or not using the islocal() function.

Syntax:

```	islocal(cVariableName) --> returns 1 if the variable is defined in the local scope
returns 0 if the variable is not defined in the local scope```

Example:

```	test()

func test
x=10 y=20
see islocal("x") + nl +
islocal("y") + nl +
islocal("z") + nl```

Output:

```	1
1
0```

## isglobal() Function

We can check if a variable is defined in the global scope or not using the isglobal() function.

Syntax:

```	isglobal(cVariableName) --> returns 1 if the variable is defined in the global scope
returns 0 if the variable is not defined in the global scope```

Example:

```	x=10 y=20

test()

func test
see isglobal("x") + nl +
isglobal("y") + nl +
isglobal("z") + nl```

Output:

```	1
1
0```

## isfunction() Function

We can check if a Ring function is defined or not using the isfunction() function.

Syntax:

```	isfunction(cFunctionName) --> returns 1 if the Ring function is defined
returns 0 if the Ring function is not defined```

Example:

```	see isfunction("f1") + nl +
isfunction("f2") + nl +
isfunction("f3") + nl

func f1
see "message from f1()" + nl

func f2
see "message from f2()" + nl```

Output:

```	1
1
0```

## iscfunction() Function

We can check if a C function is defined or not using the iscfunction() function.

Syntax:

```	iscfunction(cFunctionName) --> returns 1 if the C function is defined
returns 0 if the C function is not defined```

Example:

```	see iscfunction("len") + nl +
iscfunction("test") + nl```

Output:

```	1
1
0```

## packages() Function

We can get a list of packages names using the packages() function.

Syntax:

`	packages() --> a list contains packages names`

Example:

```	See packages()

Package Package1
Class class1
Func f1

Package Package2
Class class1
Func f1

Package Package3
Class class1
Func f1

Package Package4
Class class1
Func f1```

Output:

```	package1
package2
package3
package4```

## ispackage() Function

We can check if a package is defined or not using the ispackage() function.

Syntax:

```	ispackage(cPackageName) --> returns 1 if the Package is defined
returns 0 if the Package is not defined```

Example:

```	See ispackage("package1") + nl +
ispackage("package4") + nl +
ispackage("package5") + nl +
ispackage("package3") + nl

Package Package1
Class class1
Func f1

Package Package2
Class class1
Func f1

Package Package3
Class class1
Func f1

Package Package4
Class class1
Func f1```

Output:

```	1
1
0
1```

## classes() Function

We can get a list of classes names using the classes() function.

Syntax:

`	classes() --> a list contains classes names`

Example:

```	See classes()

Class class1
Func f1

Class class2
Func f1

Class class3
Func f1```

Output:

```	class1
class2
class3```

## isclass() Function

We can check if a class is defined or not using the isclass() function.

Syntax:

```	isclass(cClassName) -->  returns 1 if the Class is defined
returns 0 if the Class is not defined```

Example:

```	see isclass("class4") + nl +
isclass("class3") + nl +
isclass("class2") + nl

Class class1
func f1

class class2
func f1

class class3
func f1```

Output:

```	0
1
1```

## packageclasses() Function

We can get a list of classes names inside a package using the packageclasses() function.

Syntax:

`	packageclasses(cPackageName) --> a list contains classes names inside the package`

Example:

```	see "classes in Package1" + nl
see packageclasses("Package1")
see "classes in Package2" + nl
see packageclasses("Package2")

Package Package1
Class class1
Func f1

Package Package2
Class class1
Func f1
Class class2
Func f1
Class class3
func f1```

Output:

```	classes in Package1
class1
classes in Package2
class1
class2
class3```

## ispackageclass() Function

We can check if a class is defined inside package or not using the ispackageclass() function.

Syntax:

```	ispackageclass(cPackageName,cClassName) -->  returns 1 if the Class is defined
returns 0 if the Class is not defined```

Example:

```	see ispackageclass("package1","class1") + nl +
ispackageclass("package1","class2") + nl +
ispackageclass("package2","class1") + nl +
ispackageclass("package2","class2") + nl

Package Package1
Class class1
Func f1

Package Package2
Class class1
Func f1
Class class2
Func f1
Class class3
func f1```

Output:

```	1
0
1
1```

## classname() Function

We can know the class name of an object using the classname() function

Syntax:

`	classname(object) --> Returns the object class name`

Example:

```	o1 = new point
o2 = new rect

see classname(o1) + nl		# print point
see classname(o2) + nl		# print rect

class point
class rect```

## objectid() Function

We can know the object id using the objectid() function

Syntax:

`	objectid(object) --> Returns the object id`

Example:

```	o1 = new point
see objectid(o1) + nl
test(o1)

func test v
see objectid(v) + nl

Class point x y z```

Output:

```	021B5808
021B5808```

We can check the variable to know if it's an object or not using the isobject() function

Syntax:

`	isobject(variable) --> Returns True if it's an object, False if it's not`

## attributes() Function

We can get the object attributes using the attributes() function

Syntax:

`	attributes(object) --> Returns a list contains the object attributes`

Example:

```	o1 = new point
aList = attributes(o1)		# we can use see attributes(o1)
for t in aList see t next	# print xyz
Class Point x y z```

We can get the object methods using the methods() function

Syntax:

`	methods(object) --> Returns a list contains the object methods`

Example:

```	o1 = new test
aList = methods(o1)

for x in aList
cCode = "o1."+x+"()"
eval(cCode)
next

Class Test
func f1
see "hello from f1" + nl
func f2
see "hello from f2" + nl
func f3
see "hello from f3" + nl
func f4
see "hello from f4" + nl```

Output:

```	hello from f1
hello from f2
hello from f3
hello from f4```

## isattribute() Function

We can test if the object contains an attribute or not using the isattribute() function

Syntax:

`	isattribute(object,cAttributeName) --> Returns True if the object contains the attribute`

Example:

```	o1 = new point

see isattribute(o1,"x") + nl	# print 1
see isattribute(o1,"t") + nl	# print 0
see isattribute(o1,"y") + nl	# print 1
see isattribute(o1,"z") + nl	# print 1

class point x y z```

## isprivateattribute() Function

We can test if the object contains a private attribute or not using the isprivateattribute() function

Syntax:

```	isprivateattribute(object,cAttributeName) --> Returns True if the object
contains the private attribute```

Example:

```	o1 = new person

see isprivateattribute(o1,"name") + nl +
isprivateattribute(o1,"phone") + nl +
isprivateattribute(o1,"job") + nl +
isprivateattribute(o1,"salary")

Class Person
private
job salary```

Output:

```	0
0
0
1
1```

## ismethod() Function

We can test if the object class contains a method or not using the ismethod() function

Syntax:

`	ismethod(object,cMethodName) --> Returns True if the object class contains the method`

Example:

```	o1 = new point

see ismethod(o1,"print") + nl		# print 1

mylist = []
mylist + new point

see ismethod(mylist[1],"print") + nl	# print 1

class point x y z
func print
see x + nl + y + nl + z + nl```

## isprivatemethod() Function

We can test if the object class contains a private method or not using the isprivatemethod() function

Syntax:

```	isprivatemethod(object,cMethodName) --> Returns True if the object class contains
the private method```

Example:

```	o1 = new Test

see isprivatemethod(o1,"f1") + nl +
isprivatemethod(o1,"f2")

Class Test
func  f1
see "message from f1()" + nl
private
func f2
see "message from f2()" + nl```

Output:

```	0
1```

We can add an attribute (or a group of attributes) to the object state (not the class) using the addattribute() function

Syntax:

`	AddAttribute(object,cAttributeName|aAttributesList)`

Example(1):

```	see new point {x=10 y=20 z=30}
Class Point

Example(2):

```	o1 = new point
see o1 {x=10 y=20 z=30}
class point```

Output:

```	x: 10.000000
y: 20.000000
z: 30.000000```

We can add a method to the object class using the addmethod() function This method can be used with any object from the same class.

Syntax:

`	AddMethod(Object,cNewMethodName,cMethodName|AnonymousFunction)`

Example:

```	o1 = new point { x=10 y=20 z=30 }

addmethod(o1,"print", func { see x + nl + y + nl + z + nl } )

o1.print()

Class point
x y z```

Output:

```	10
20
30```

Instead of using anonymous function to add new method to the class, we can use the function name

Example:

```	o1 = new point { x=10 y=20 z=30 }

myfunc = func { see x + nl + y + nl + z + nl }

o1.print()
o1.display()
o1.show()

Class point
x y z```

Output:

```	10
20
30
10
20
30
10
20
30```

Since we add the method to the class, any object from that class can use this method

Example:

```	o1 = new point { x=10 y=20 z=30 }
o2 = new point { x=100 y=200 z=300 }
o3 = new point { x=50 y=150 z=250 }

addmethod(o1,"print", func { see x + nl + y + nl + z + nl } )

o1.print()
o2.print()
o3.print()

Class point
x y z```

Output:

```	10
20
30
100
200
300
50
150
250```

## getattribute() function

We can get the object attribute value using the getattribute() function

Syntax:

`	GetAttribute(oObject,cAttributeName) ---> Attribute Value`

Example:

```	o1 = new point

see getattribute(o1,"name") + nl +
getattribute(o1,"x") + nl +
getattribute(o1,"y") + nl +
getattribute(o1,"z") + nl

Class Point
x=10 y=20 z=30
name = "3D-Point"```

Output:

```	3D-Point
10
20
30```

## setattribute() function

We can set the object attribute value using the setattribute() function

Syntax:

`	SetAttribute(oObject,cAttributeName,Value)`

Example:

```	o1 = new person
setattribute(o1,"cName","Mahmoud")
setattribute(o1,"nSalary",1000000)
setattribute(o1,"aColors",["white","blue","yellow"])

see o1
see o1.aColors

Class Person
cName
nSalary
aColors```

Output:

```	cname: Mahmoud
nsalary: 1000000.000000
acolors: List...
white
blue
yellow```

## mergemethods() Function

We can share methods between classes without inheritance using the MergeMethods() function

This function merge class methods to another class.

Syntax:

`	MergeMethods(cClassNameDestination,cClassNameSource)`

Example:

```	mergemethods("count","share")
mergemethods("count2","share")

o1 = new count  { test() }
o1 = new count2 { test() }

Class Share
func one
see "one" + nl
func two
see "two" + nl
func three
see "three" + nl

Class Display
Func printline
see copy("*",20) + nl

Class Count from Display
Func test
printline()
one()
two()
three()
printline()

Class Count2 from Display
Func test
three()
two()
one()
printline()```

Output:

```	********************
one
two
three
********************
three
two
one
********************```