shape Product:
    id: Number
    name: Text

fn product_list() -> List[Product]:
    var products: List[Product] = List[Product]()
    list_push(products, Product(1, "Tea"))
    list_push(products, Product(2, "Coffee"))
    return products

fn optional_product_list() -> Option[List[Product]]:
    return some(product_list())

fn result_product_list() -> Result[List[Product], Text]:
    return ok(product_list())

start:
    let products: List[Product] = product_list()
    assert list_count(products) == 2
    assert list_get(products, 0).id == 1
    assert list_get(products, 1).name == "Coffee"
    let first_product: Option[Product] = list_try_get(products, 0)
    assert option_is_some(first_product)
    assert option_unwrap(first_product).name == "Tea"
    let negative_product: Option[Product] = list_try_get(products, -1)
    let missing_product: Option[Product] = list_try_get(products, 9)
    assert not option_is_some(negative_product)
    assert not option_is_some(missing_product)
    list_set(products, 0, Product(3, "Updated"))
    assert list_get(products, 0).id == 3

    let optional: Option[List[Product]] = optional_product_list()
    assert option_is_some(optional)
    assert list_get(option_unwrap(optional), 1).id == 2

    let result: Result[List[Product], Text] = result_product_list()
    assert result_is_ok(result)
    assert list_get(result_unwrap(result), 0).name == "Tea"

    var numbers: List[Number] = List[Number]()
    list_push(numbers, 4)
    list_push(numbers, 7)
    assert list_count(numbers) == 2
    assert list_get(numbers, 1) == 7
    var total: Number = 0
    for number in numbers:
        set total = total + number
    assert total == 11

    var product_id_total: Number = 0
    for product in products:
        set product_id_total = product_id_total + product.id
    assert product_id_total == 5

    let first_number: Option[Number] = list_try_get(numbers, 0)
    let missing_number: Option[Number] = list_try_get(numbers, 2)
    assert option_is_some(first_number)
    assert option_unwrap(first_number) == 4
    assert not option_is_some(missing_number)

    var nested: List[Option[Number]] = List[Option[Number]]()
    list_push(nested, some(12))
    let nested_item: Option[Option[Number]] = list_try_get(nested, 0)
    assert option_is_some(nested_item)
    assert option_unwrap(option_unwrap(nested_item)) == 12
    let missing_nested: Option[Option[Number]] = list_try_get(nested, 4)
    assert not option_is_some(missing_nested)

    let words: TextList = text_list()
    list_push(words, "YAZA")
    let word: Option[Text] = list_try_get(words, 0)
    let missing_word: Option[Text] = list_try_get(words, -4)
    assert option_unwrap(word) == "YAZA"
    assert not option_is_some(missing_word)

    var growing: List[Number] = List[Number]()
    list_push(growing, 1)
    var visits: Number = 0
    for item in growing:
        set visits = visits + 1
        list_push(growing, 2)
    assert visits == 1
    assert list_count(growing) == 2

