Παρασκευή 28 Οκτωβρίου 2022

EnumClass defined as example using M2000 code

This example show the using of groups/ pointers to groups, and a way to use meta programming. We define a string which have the final code for a group, and then using:

Group nameOfGroup type CodeAsString$

This Group definition was written before M2000 get classes, and types (see label type: for hard write one or more types for a group). The idea was to define types, using global strings, but never used for that. Because the string can be made at run time, we can define the code of group at run time.

The function enumclass return a group using Group(aa) and not aa because aa call the value part of group if exist, which here exist, so we need Group() which checks the name if it is an object (and not evaluates numeric expression).

We play with p and z which are pointers to groups. We can check parameters if are pointers to group and specific type (which here we write it in the enumclass, first parameter).

M2000 has Enum (enumerated type) and we can define variables using  this type, see Help Enum/ This example defines Enum in a different way. Also I have left for exercise the EnumStringClass variant, where the value for each constant is a string. The Enum type of M2000 has no string values to constants, we can use a List  which have pairs like (name$, value$)

// enumclass function produce a pointer to object p
// enumclass(typename$, firstEnumName$, ValueNumber[, NextEnumName$, NextValueNumber])
//
// eval(p) is the current value of p=>name$
// p=>setValue AnyEnumName$
// z=p=>copy()  produce a new object with same value
// z=p=>copy(AnyEnumName$) produce a new object with any value
// print z=p   // return true by names
// print z==p   // return true by values
function enumclass(name$) {
proto$=lambda$ name$ (na$, va) ->{
tp$={type: }+name$+{
private:
val$=}+quote$("."+na$)+{
public:
group name$ {
value {
link parent val$ to val$
=mid$(val$,2)
}
}
Function Copy(a$="") {
if a$="" then a$=mid$(.val$,2)
if valid("."+a$) then
m=this
m.SetValue a$
->group(m)
else
error "not valid label"
end if
}
operator "=" (m) {
push m=>name$=.name$
}
operator "==" (m) {
push eval(m)=eval(.val$)
}
Module SetValue (a$) {
if valid("."+a$) then .val$<="."+a$
}
value {
=eval(.val$)
}
}
tp$+="final "+na$+"="+str$(va)
while not empty
tp$+=", final "+letter$+"="+str$(number)
end while
=tp$
}
Group aa type proto$(![])
=Group(aa)


}
z->enumclass("alfa", "one",100,"two", 200,"three", 300, "likeone", 100)
print eval(z), Eval("z=>"+z=>name$), z=>name$
z=>setValue "three"
print eval(z), Eval("z=>"+z=>name$), z=>name$
p=z=>copy()
print type$(p)
print eval(p), Eval("z=>"+p=>name$), p=>name$
p=z=>copy("two")
print type$(p)
print eval(p), Eval("z=>"+p=>name$), p=>name$
p=>setValue "three"
print z=p // true
p=>setValue "one"
print z=p // false
print z=>name$, p=>name$
function check(k as *alfa) {
=eval(k)
}
print check(p)=100, check(z)=300
print valid(check(pointer()))=false
print valid(check(p))=true
select(p) // "found one or likeone"
selectByName(p) // "one"
select(z) // "found three"
selectByName(z) // "found three"
z=>setValue "likeone"
print p=z, p==z // false true


sub select(p as *alfa)
for p {
select case eval(this) // eval(p) also can be used
case .one
print "found one or likeone"
case .two
print "found two"
case .three
print "found three"
end select
}
end sub
sub selectByName(p as *alfa)
for p {
select case .name$
case "one"
print "found one"
case "two"
print "found two"
case "three"
print "found three"
case "likeone"
print "found likeone"
end select
}
end sub


Δεν υπάρχουν σχόλια:

Δημοσίευση σχολίου

You can feel free to write any suggestion, or idea on the subject.