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.
In this chapter we will learn about this and the available functions to use.
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 scopeExample:
	test("hello")
	func test cMsg
		see cMsg + nl
		x = 10
		y = 20
		z = 30
		see locals()Output:
	hello
	cmsg
	x
	y
	zglobals() 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 scopeExample:
	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
	zfunctions() Function
We can get a list of functions names written in the Ring language using the functions() function.
Syntax:
	functions() --> a list contains functions namesExample:
	see functions()
	func f1
		see "f1" + nl
	func f2
		see "f2" + nl
	func f3 
		see "f3" + nlOutput:
	f1
	f2
	f3cfunctions() Function
We can get a list of functions names written in the C language using the cfunctions() function.
Syntax:
	cfunctions() --> a list contains functions namesExample:
	aList =  cfunctions()
	See "Count : " + len(aList) + nl
	for x in aList
		see x + "()" + nl
	nextOutput:
	Count : 186
	len() 
	add() 
	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 scopeExample:
	test()
	func test
		x=10 y=20
		see islocal("x") + nl + 
		    islocal("y") + nl + 
		    islocal("z") + nlOutput:
	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 scopeExample:
	x=10 y=20
	test()
	func test
		see isglobal("x") + nl + 
		    isglobal("y") + nl + 
		    isglobal("z") + nlOutput:
	1
	1
	0isfunction() 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 definedExample:
	see isfunction("f1") + nl + 
	    isfunction("f2") + nl + 
	    isfunction("f3") + nl
	func f1
		see "message from f1()" + nl
	func f2
		see "message from f2()" + nlOutput:
	1
	1
	0iscfunction() 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 definedExample:
	see iscfunction("len") + nl + 
  	    iscfunction("test") + nlOutput:
	1
	1
	0
packages() Function
We can get a list of packages names using the packages() function.
Syntax:
	packages() --> a list contains packages namesExample:
	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 f1Output:
	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 definedExample:
	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 f1Output:
	1
	1
	0
	1
classes() Function
We can get a list of classes names using the classes() function.
Syntax:
	classes() --> a list contains classes namesExample:
	See classes()
	Class class1
		Func f1
	Class class2
		Func f1
	Class class3
		Func f1Output:
	class1
	class2
	class3isclass() 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 definedExample:
	see isclass("class4") + nl + 
	    isclass("class3") + nl +
	    isclass("class2") + nl
	Class class1
		func f1
	class class2
		func f1
	class class3
		func f1Output:
	0
	1
	1packageclasses() 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 packageExample:
	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 definedExample:
	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 f1Output:
	1
	0
	1
	1classname() 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 rectobjectid() Function
We can know the object id using the objectid() function
Syntax:
	objectid(object) --> Returns the object idExample:
	o1 = new point
	see objectid(o1) + nl
	test(o1)
	func test v
		see objectid(v) + nl
	Class point x y zOutput:
	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 attributesExample:
	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" + nlOutput:
	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 attributeExample:
	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 zisprivateattribute() 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 attributeExample:
	o1 = new person
	see isprivateattribute(o1,"name") + nl + 
	    isprivateattribute(o1,"address") + nl + 
	    isprivateattribute(o1,"phone") + nl + 
	    isprivateattribute(o1,"job") + nl + 
	    isprivateattribute(o1,"salary")
	Class Person
		name address phone
		private
			job salaryOutput:
	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 methodExample:
	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 + nlisprivatemethod() 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 methodExample:
	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()" + nlOutput:
	0
	1addattribute() Function
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 
		AddAttribute(self,["x","y","z"])Example(2):
	o1 = new point
	addattribute(o1,"x")
	addattribute(o1,"y")
	addattribute(o1,"z")
	see o1 {x=10 y=20 z=30}
	class point
Output:
	x: 10.000000
	y: 20.000000
	z: 30.000000
addmethod() Function
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 zOutput:
	10
	20
	30Instead 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 }
	addmethod(o1,"print", myfunc )
	addmethod(o1,"display", myfunc )
	addmethod(o1,"show", myfunc )
	o1.print()
	o1.display()
	o1.show()
	Class point
		x y zOutput:
	10
	20
	30
	10
	20
	30
	10
	20
	30Since 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 zOutput:
	10
	20
	30
	100
	200
	300
	50
	150
	250getattribute() function
We can get the object attribute value using the getattribute() function
Syntax:
	GetAttribute(oObject,cAttributeName) ---> Attribute ValueExample:
	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
	30setattribute() 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
		aColorsOutput:
	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
	********************