#
# $Id: class.icn,v 1.4 2009-10-13 00:32:45 jeffery Exp $
#
# This file is in the public domain.
#
# Author: Robert Parlett (parlett@dial.pipex.com)
#
package lang
global lang_class_table
#
# Get the Class corresponding to the given object or the class name
#
procedure get_class_for(obj)
local x, name
/lang_class_table := ::table()
case lang::get_type(obj) of {
"class" : {
#
# convert class name to the external form for storing in the table
#
name := lang::mapPackageInt2Ext(::classname(obj))
#
# use the object supplied to be create a Class object and insert into
# the table with the key of the external class names#
if not(x := \lang_class_table[name]) then {
x := Class(obj)
lang_class_table[name] := x
}
}
"string" : {
#
# make sure that the class name supplied is in external form
#
name := lang::mapPackageInt2Ext(obj)
#
# if there is no key by the string value supplied, we need to raise failure
x := \lang_class_table[name] | fail
}
#
# any other kind of value is not a class or a class name, therefore we need to failure#
default : fail
}
return x
end
#
# This class provides information about a Unicon class.
#
class Class(name,
methods,
methods_map,
variables,
state_instance,
oprec,
supers,
implemented_classes)
#
# Return the name of the class
#
method get_name()
return name
end
#
# Return the methods of the class, as a list
#
method get_methods()
return methods
end
#
# Get the method with the given method name, or fail if there
# is no such method.
#
method get_method(s)
if ::member(methods_map, s) then
return methods_map[s]
end
#
# Return a list of the names of the parent classes, in the order they were
# encountered in the record definition.
#
method get_supers()
return supers
end
#
# Get a set of the names of the implemented classes of this class
# (including this class itself).
#
method get_implemented_classes()
return implemented_classes
end
#
# Return the variable names of the class, in the order they would appear
# in an instance
#
method get_variables()
return variables
end
initially(obj)
local v, s, sa, m, cname, cmeths := ::table(), lm := []
#
# get the class name based on the object that we are looking at
#
self.name := lang::mapPackageInt2Ext(::classname(obj))
#
# provide the initial values for the methods, supers, methods_map, variables
# and implemented_classes. These will be added to as we process the information
# available from the Unicon functions.
#
self.methods := []
self.supers := []
self.methods_map := ::table()
self.implemented_classes := ::set(lang::mapPackageInt2Ext(self.name))
self.variables := []
#
# there are two variables in the class structure which are not of interest
# here as these are implementation related variables:- __s and __m. So as we
# examine the names provided by the Unicon function membernames(), we will not
# include these in the list of available variable names.
#
every s := !::membernames(obj) do {
if not (s == ("__s" | "__m")) then {
::put(self.variables, s)
}
}
#
# the method values associated with the class or superclasses for this class
# will be stored in set associated with the key of the class name.
#
# the first entry will be the set of methods defined for the class
#
cmeths[self.name] := ::set(::methods(obj))
#
# Get the oprec, the field names of this record will be the method names
# defined directly in the class as well as the superclass names applicable
# for this class.
#
# the field names for a method hold a procedure value, the super classes hold
# a record value. We use this distinction in values to determine what is a
# method name and what is a class name.
#
self.oprec := ::oprec(obj) | fail
every s := ::fieldnames(self.oprec) do {
v := self.oprec[s]
sa := lang::mapPackageInt2Ext(s)
if ::type(v) == "procedure" then {
#
# lm holds a list of lists where the internal list is the procedure value
# and the name of the method. This will be used later to generate the
# methods and the methods_map values.
#
::put(lm, [v, s])
} else {
#
# we place the super class name onto the end of the supers list and put
# the applicable list of methods for that class into an apprporiate set
# for creating the methods and methods_map values
#
::put(self.supers, sa)
cmeths[sa] := ::set(::methods(s))
}
}
#
# we can now add the super class list to the set of implemented classes
#
self.implemented_classes ++:= ::set(self.supers)
#
# this is where we finalise the methods list and the methods_map table
#
every v := !lm do {
every s := ::key(cmeths) do {
if ::member(cmeths[s], v[1]) then {
::put(self.methods, m := Method(v[1], v[2], s))
methods_map[v[2]] := m
}
}
}
end
This page produced by UniDoc on 2021/04/15 @ 23:59:43.