example/objects_and_types.primi
import std.types: func
import ._helpers: assert_error
//
// Some sanity checks.
//
_ = "Type of type 'type' should be 'type'"
assert(type(type) == type, _)
_ = "Result of bool(0) should be false"
assert(bool(0) == false, _)
_ = "Result of bool(1) should be true"
assert(bool(1) == true, _)
//
// Creating custom classes/types with "class" keyword.
//
// Create base class "Greeting" (will extend class "object" by default).
class Greeting {
attr_a = 'Some attribute A from class Greeting'
attr_b = 'Some attribute B from class Greeting'
variants = {"a": "Hey", "b": "Hello"}
function get_greeting(self, name, variant) {
return f"{self.variants[variant]} {name}!"
}
}
//
// Creating custom classes/types that extend an existing class/type.
//
// Create class "Ahojky" which extends class "Greeting".
class Ahojky(Greeting) {
attr_b = 'Overridden attribute B by class Ahojky'
attr_c = 'Some attribute C from class Ahojky'
class InnerAhojky {
sub_attr_a = string
sub_attr_b = Greeting
}
function get_greeting(self, name) {
return f"Ahojky {name}!"
}
}
//
// Test behavior and properties of class "Greeting" and its instance.
//
_ = "Type of type 'Greeting' should be 'type'"
assert(type(Greeting) == type, _)
greeting = Greeting()
assert(type(greeting) == Greeting)
assert(Greeting.attr_a == 'Some attribute A from class Greeting')
assert(Greeting.attr_b == 'Some attribute B from class Greeting')
assert(greeting.attr_a == 'Some attribute A from class Greeting')
assert(greeting.attr_b == 'Some attribute B from class Greeting')
assert(greeting.variants.get('a') == 'Hey')
assert(greeting.variants.get('b') == 'Hello')
assert(greeting.get_greeting('Jeremiáš', 'a') == 'Hey Jeremiáš!')
assert(greeting.get_greeting('Alžběta', 'b') == 'Hello Alžběta!')
//
// Test behavior and properties of class "Ahojky" and its instance.
//
_ = "Type of type 'Ahojky' should be 'type'"
assert(type(Ahojky) == type, _)
ahojky = Ahojky()
assert(type(ahojky) == Ahojky)
assert(Ahojky.attr_a == 'Some attribute A from class Greeting')
assert(Ahojky.attr_b == 'Overridden attribute B by class Ahojky')
assert(Ahojky.attr_c == 'Some attribute C from class Ahojky')
assert(ahojky.attr_a == 'Some attribute A from class Greeting')
assert(ahojky.attr_b == 'Overridden attribute B by class Ahojky')
assert(ahojky.attr_c == 'Some attribute C from class Ahojky')
assert(ahojky.variants.get('a') == 'Hey')
assert(ahojky.variants.get('b') == 'Hello')
assert(ahojky.get_greeting('Padishah Emperor') == 'Ahojky Padishah Emperor!')
//
// Using type() to create new classes/types.
//
custom_type = type('CustomType', object, {
'some_attr_x': 'no value',
'__init__': (self, arg) => {
print(f'self: {self}, arg: {arg}')
print(f'setting self.some_attr_x to "{arg}"')
self.some_attr_x = arg
},
'try_me': (self, what) => {
print(f'self: {self}, what: {what}, some_attr_x: {self.some_attr_x}')
},
})
assert(type(custom_type) == type)
assert(custom_type.some_attr_x == 'no value')
instance = custom_type('init arg')
assert(type(instance) == custom_type)
assert(custom_type.some_attr_x == 'no value')
assert(instance.some_attr_x == 'init arg')
instance.try_me('anything')
//
// Dict specifying attrs of the new type must have valid variable names
// as keys.
//
assert_error(() => {
custom_type = type('CustomType', object, {
'123': 'this is invalid variable name'
})
})
assert_error(() => {
custom_type = type('CustomType', object, {
123: 'this also is invalid variable name'
})
})
assert_error(() => {
custom_type = type('CustomType', object, {
('lol', 'a', 'tuple'): 'this is completely invalid variable name'
})
})
//
// Attr access.
//
_ = "Getting non-existent attr from object throws error"
assert_error(() => {
print(instance.bogus_attr)
}, _)
_ = "Setting some attr under a non-existent attr throws error"
assert_error(() => {
instance.bogus_attr_a.bogus_attr_b = 1
}, _)
//
// Deeply nested objects.
//
class Struct {
function __init__(self, a, b = null) {
print(f"Initing with a:{a} and b:{b}")
self.substruct = b
}
function get_tree(self, message = "NOTHING") {
tree = [self]
new = self
print(f"Getting tree with message: '{message}'")
while (hasattr(new, 'substruct') and new.substruct) {
tree.push(new.substruct)
new = new.substruct
}
return tree
}
}
o1 = Struct('aaa')
o2 = Struct('bbb', o1)
o3 = Struct('ccc', o2)
o4 = Struct('ddd', o3)
print(o4.get_tree())
print(o4.get_tree("SOMETHING"))
o4.substruct.substruct.substruct = "hey!"
print(o4.get_tree("SOMETHING"))