Aug 13, 2022Kuina-chan

This is the reverse lookup dictionary 4 for exe execution environment of Kuin Programming Language, and is about how to handle enums, classes and aliases.

Handling Enumerated Type

Handling Class

Give Alias To Type


1Handling Enumerated Type

1.1Creating Enumerated Type

An enumerated type is a type that defines some possible values, such as the Animal type, which can be one of the values dog, cat, or fox.
To create an enumerated type, write the name of the possible values between "enum Type Name" and "end enum" (Figure 1-1).
  1. enum Animal
  2.   dog
  3.   cat
  4.   fox
  5. end enum
  7. func main()
  8.   var animal: @Animal
  9.   do animal :: %dog
  10.   var isCat: bool :: animal = %cat {false}
  11. end func
Figure 1-1: Enumerated Type
By declaring the enumerated type @Animal in lines 1 to 4, it can be treated as a type as shown in line 8.
If you write "%Name Of Value" as in lines 9-10, it will be interpreted as an enumerated type value.
Which enumerated type the value is written in is determined by inferring the type, but if the type cannot be determined, a compile error will occur. In such a case, it is necessary to explicitly cast "%Name Of Value $ Name Of Enumeration Type" to indicate the type (Figure 1-2).
  1. enum Animal
  2.   dog
  3.   cat
  4.   fox
  5. end enum
  7. func main()
  8.   var array: []@Animal :: [%dog $ @Animal, %fox] {[%dog, %fox]}
  9. end func
Figure 1-2: Type Explicit

1.2Making Enumerated Type Value Have Numeric Value

Each value of an enumerated type can have a numeric value of int. Write "Value Of Enumerated Type :: Value Of int Type" (Figure 1-3).
  1. enum Animal
  2.   dog
  3.   cat :: 5
  4.   fox
  5. end enum
  7. func main()
  8.   var animal: @Animal
  9.   var n: int
  10.   do animal :: %dog
  11.   do n :: animal $ int {0}
  12.   do animal :: %cat
  13.   do n :: animal $ int {5}
  14.   do animal :: %fox
  15.   do n :: animal $ int {6}
  16. end func
Figure 1-3: Numeric Value Of Enumerated Type
In line 3, the enumerated type value cat is set to the int type value 5. Even if you do not set a value in this way, an int type value will be assigned automatically, and the value will be set in order from 0 to 1, 2, and so on, increasing by 1.
When a number is specified, the next element is set by incrementing the number by one, so in the above program, dog is assigned 0, cat is assigned 5, fox is assigned 6.
The numbers assigned in an enumeration type must not overlap, and if they do, a compilation error will occur. The assigned number can be obtained by casting it to int type as shown in line 11.
Enumerated type values can be compared between large and small. Large and small relationships are based on the numbers assigned to them (Figure 1-4).
  1. enum Animal
  2.   dog
  3.   cat :: 5
  4.   fox
  5. end enum
  7. func main()
  8.   var animal1: @Animal :: %dog
  9.   var animal2: @Animal :: %fox
  10.   var b: bool :: animal1 < animal2 {true}
  11. end func
Figure 1-4: Large And Small Enums

1.3Performing Bitwise Operations On Enumerated Type Values

Numeric values assigned to an enumerated type can perform bitwise operations, just like the bit64 type, and can have inclusion relations on elements. The .or, .and, .not, and .xor methods can be used for them (Figure 1-5).
  1. enum Color
  2.   red :: 0x01
  3.   green :: 0x02
  4.   blue :: 0x04
  5. end enum
  7. func main()
  8.   var red: @Color :: %red
  9.   var yellow: @Color :: red.or(%green)
  10.   var isGreen: bool :: yellow.and(%green) = %green {true}
  11. end func
Figure 1-5: Bitwise Operations On Enumerated Types
In this example, the union set of %red and %green is defined as %yellow in line 9, and the intersection is used to determine if %yellow contains %green in line 10.

2Handling Class

2.1Creating Class

A class is a new type created by combining multiple variables and functions into one.
To create a class, write variables, functions, and other elements between "class Type Name()" and "end class" (Figure 2-1).
  1. class Person()
  2.   +var name: []char
  3.   var age: int
  5.   +func setAge(n: int)
  6.     do me.age :: n
  7.   end func
  8. end class
  10. func main()
  11.   var person: @Person :: #@Person
  12.   do :: "Kuina"
  13.   do person.setAge(6)
  14. end func
Figure 2-1: Class
By declaring the class @Person in lines 1 to 8, it can be treated as a type as shown in line 11. If you write "#Class Name" as in line 11, an instance of that class will be created.
As shown in lines 12-13, writing ".Member Name", the program can access the variables and functions that the class has.
If you write "+" at the beginning of the class variable and function definitions, as in lines 2 and 5, the variables and functions can be accessed externally, as in lines 12-13. If you do not write "+" as in age in the 3rd line, it cannot be accessed from the outside, and accessing person.age will result in a compilation error. By exposing the minimum necessary elements to the outside world, you can prevent unexpected rewriting of variables.
In a class member function, to refer to an instance of that class, write me as shown in line 6. Calling person.setAge in line 13 will execute "me.age :: n" in line 6, resulting in the assignment of a value to person.age.

2.2Inheriting Class

You can create a new class by inheriting the variables and functions of one class. To create a class by inheritance, write "class Type Name(Inherited Class)" (Figure 2-2).
  1. class Person()
  2.   +var name: []char
  3.   var age: int
  5.   +func setAge(n: int)
  6.     do me.age :: n
  7.   end func
  8. end class
  10. class Student(@Person)
  11.   +var mathScore: int
  13.   +*func setAge(n: int)
  14.     do super(me, n)
  15.     do me.age :+ 1
  16.   end func
  17. end class
  19. func main()
  20.   var student: @Student :: #@Student
  21.   do :: "Kuina"
  22.   do student.setAge(6)
  23.   do student.mathScore :: 100
  24.   var person: @Person :: student
  25.   if(person =$ @Student) {true}
  26.     var student2: @Student :: person $ @Student
  27.   end if
  28. end func
Figure 2-2: Class Inheritance
In line 10, the @Student class has been created by inheriting from the @Person class. The @Student class inherits all the variables and functions of @Person and can be accessed as shown in lines 21-22. The variables added to @Student in line 11 can also be accessed as shown in line 23.
As shown in line 24, the inheriting class instance @Student can be treated as the inherited class type @Person. On the contrary, explicit casting is required when converting from the type of the inherited class @Person to the type of the inheriting class @Student, as shown in line 26. If you cast to a type that is not the original instance, an exception will be raised.
Whether or not an instance can be cast to a certain class type can be determined with the "=$" operator, as shown in line 25.
When inheriting, it is possible to override the processing of the original function. To override a function, write "*" just before func as shown in line 13, and use the same function name, arguments, and return value as the overriding source. It is also possible to call the overridden function from within the overriding function, as in line 14: "super(me, 1st argument, 2nd argument, ...)" as in line 14. If it also has a return value, it will be accepted.
Elements that are not marked with "+" in the inheritance source can still be accessed from the inheritance destination. Accessing me.age as shown in line 15 is no problem.

2.3Processing When Class Is Instantiated

When an instance of a class is created, the function ctor defined in kuin@Class, the class from which all classes inherit, is called. By overriding it, you can do arbitrary processing when creating the instance (Figure 2-3).
  1. class Person()
  2.   *func ctor()
  3.     do :: "Kuina"
  4.     do me.age :: 6
  5.   end func
  7.   +var name: []char
  8.   var age: int
  9. end class
  11. func main()
  12.   var person: @Person :: #@Person
  13. end func
Figure 2-3: Constructor
In lines 2-5, the ctor function is overridden to assign a value to each variable. By writing like this, the initial value of the variable can be set when the instance is created in line 12.

2.4Make Class Comparable

To make a class comparable so that it can be handled by the "=", "<>", "<", ">", "<=", and ">=" operators, and the .sort method for arrays, override the cmp function defined in kuin@Class (Figure 2-4).
  1. class Person()
  2.   +*func cmp(t: kuin@Class): int
  3.     var t2: @Person :: t $ @Person
  4.     if( =
  5.       ret 0
  6.     else
  7.       ret > ?(1, -1)
  8.     end if
  9.   end func
  11.   +var name: []char
  12. end class
  14. func main()
  15.   var person1: @Person :: #@Person
  16.   do :: "abc"
  17.   var person2: @Person :: #@Person
  18.   do :: "def"
  19.   var b: bool :: person1 < person2 {true}
  20. end func
Figure 2-4: Class Comparison
The cmp function should compare its own instance with the argument t and return a positive value if its own instance is large, a negative value if its own instance is small, and a zero value if its own instance is equal. By doing this, you can make large and small comparisons as shown in line 19.

3Give Alias To Type

3.1Give Alias To Type

To add an alias to a type, write "alias New Type Name: Type" (Figure 3-1).
  1. func main()
  2.   alias Items: dict<int, [][]char>
  4.   var items: Items :: #Items
  5. end func
Figure 3-1: Alias
The name Items is given to the "dict<int, [][]char>" type in line 2, and is used in line 4.
In this way, you can make the source code more readable by adding aliases to complicated types. However, if you use too many of them, the original type will become difficult to recognize and even more difficult to read, so I recommend using the minimum necessary.