From c096d010b96c5c526d7d35620699ee3364fbb2e2 Mon Sep 17 00:00:00 2001 From: pmqtt <51272730+pmqtt@users.noreply.github.com> Date: Fri, 9 Sep 2022 20:15:17 +0200 Subject: [PATCH] Optional Class (#2096) Adding Optional class to prelude... I hope it is useful! Co-authored-by: m new Co-authored-by: Richard Smith Co-authored-by: Geoff Romer --- explorer/data/prelude.carbon | 37 +++++++ .../testdata/linked_list/linked_list.carbon | 96 +++++++++++++++++++ .../init_optional_with_non_value.carbon | 20 ++++ .../optional/init_optional_with_value.carbon | 22 +++++ 4 files changed, 175 insertions(+) create mode 100644 explorer/testdata/linked_list/linked_list.carbon create mode 100644 explorer/testdata/optional/init_optional_with_non_value.carbon create mode 100644 explorer/testdata/optional/init_optional_with_value.carbon diff --git a/explorer/data/prelude.carbon b/explorer/data/prelude.carbon index 359e2528769d..430604885ebb 100644 --- a/explorer/data/prelude.carbon +++ b/explorer/data/prelude.carbon @@ -416,6 +416,43 @@ external impl i32 as RightShiftWith(i32) where .Result == i32 { } } +//------------------------- +// Optional +//------------------------- +choice OptionalElement(T:! Type) { + None(), + Element(T) +} + +class Optional(T:! Type){ + fn CreateEmpty() -> Optional(T){ + return { .element = OptionalElement(T).None() }; + } + fn Create(value: T ) -> Optional(T){ + return { .element = OptionalElement(T).Element(value) }; + } + + fn HasValue[me: Self]() -> bool { + match(me.element){ + case OptionalElement(T).None() => { return false; } + } + return true; + } + + fn Get[me: Self]() -> T { + var y: T; + match(me.element){ + case OptionalElement(T).Element(x: T ) =>{ + return x; + } + } + // TODO: Use assert as soon as available + return y; + } + + var element: OptionalElement(T); +} + // ------------------------ // Miscellaneous utilities. // ------------------------ diff --git a/explorer/testdata/linked_list/linked_list.carbon b/explorer/testdata/linked_list/linked_list.carbon new file mode 100644 index 000000000000..1083cae9042a --- /dev/null +++ b/explorer/testdata/linked_list/linked_list.carbon @@ -0,0 +1,96 @@ +// Part of the Carbon Language project, under the Apache License v2.0 with LLVM +// Exceptions. See /LICENSE for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +// RUN: %{explorer} %s 2>&1 | \ +// RUN: %{FileCheck} --match-full-lines --allow-unused-prefixes=false %s +// RUN: %{explorer} --parser_debug --trace_file=- %s 2>&1 | \ +// RUN: %{FileCheck} --match-full-lines --allow-unused-prefixes %s +// AUTOUPDATE: %{explorer} %s +// CHECK: 1 +// CHECK: 2 +// CHECK: 3 +// CHECK: 4 +// CHECK: 1 +// CHECK: 2 +// CHECK: 3 +// CHECK: 4 +// CHECK: result: 0 + +package ExplorerTest api; + +class ListElement{ + fn Create(value: i32)->ListElement{ + return { + .element = Optional(i32).Create(value), + .next = Optional(ListElement*).CreateEmpty() + }; + } + + fn set[addr me: Self*] (value: Optional(ListElement*)){ + (*me).next = value; + } + + var element: Optional(i32); + var next: Optional(ListElement*); +} + +class List{ + fn Create() -> List{ + return {.next = Optional(ListElement*).CreateEmpty() }; + } + fn insert[addr me: Self*] (value: i32){ + if( not (*me).next.HasValue() ){ + (*me).next = Optional(ListElement*).Create( heap.New(ListElement.Create(value)) ); + return; + } + var iter: Optional(ListElement*) = (*me).next; + var node: auto = (iter.Get()); + while((*node).next.HasValue()){ + iter = (*node).next; + node = (iter.Get()); + } + var v : ListElement* = iter.Get(); + var x: Optional(ListElement*) = Optional(ListElement*).Create( heap.New(ListElement.Create(value) )); + (*v).set(x); + } + + fn print[me: Self] (){ + var iter: Optional(ListElement*) = me.next; + while(iter.HasValue()){ + var node: auto = *(iter.Get()); + Print("{0}",node.element.Get()); + var node_ptr: auto = iter.Get(); + iter = node.next; + } + } + + fn clean[addr me: Self*] (){ + var head: auto = (*me).next; + while(head.HasValue()){ + var tmp: auto = head; + head = (*head.Get()).next; + heap.Delete(tmp.Get()); + } + (*me).next= Optional(ListElement*).CreateEmpty(); + } + + var next: Optional(ListElement*); +} + +fn Main() -> i32{ + var list: List = List.Create(); + list.insert(1); + list.insert(2); + list.insert(3); + list.insert(4); + list.print(); + list.clean(); + list.print(); + list.insert(1); + list.insert(2); + list.insert(3); + list.insert(4); + list.print(); + return 0; +} diff --git a/explorer/testdata/optional/init_optional_with_non_value.carbon b/explorer/testdata/optional/init_optional_with_non_value.carbon new file mode 100644 index 000000000000..469718cb8a92 --- /dev/null +++ b/explorer/testdata/optional/init_optional_with_non_value.carbon @@ -0,0 +1,20 @@ +// Part of the Carbon Language project, under the Apache License v2.0 with LLVM +// Exceptions. See /LICENSE for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +// RUN: %{explorer} %s 2>&1 | \ +// RUN: %{FileCheck} --match-full-lines --allow-unused-prefixes=false %s +// RUN: %{explorer} --parser_debug --trace_file=- %s 2>&1 | \ +// RUN: %{FileCheck} --match-full-lines --allow-unused-prefixes %s +// AUTOUPDATE: %{explorer} %s +// CHECK: result: 0 + +package ExplorerTest api; + +fn Main() -> i32{ + var x: Optional(String) = Optional(String).CreateEmpty(); + if(x.HasValue()){ + return -1; + } + return 0; +} diff --git a/explorer/testdata/optional/init_optional_with_value.carbon b/explorer/testdata/optional/init_optional_with_value.carbon new file mode 100644 index 000000000000..a55d5ecab75a --- /dev/null +++ b/explorer/testdata/optional/init_optional_with_value.carbon @@ -0,0 +1,22 @@ +// Part of the Carbon Language project, under the Apache License v2.0 with LLVM +// Exceptions. See /LICENSE for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +// RUN: %{explorer} %s 2>&1 | \ +// RUN: %{FileCheck} --match-full-lines --allow-unused-prefixes=false %s +// RUN: %{explorer} --parser_debug --trace_file=- %s 2>&1 | \ +// RUN: %{FileCheck} --match-full-lines --allow-unused-prefixes %s +// AUTOUPDATE: %{explorer} %s +// CHECK: Hallo Welt +// CHECK: result: 0 + +package ExplorerTest api; + +fn Main() -> i32{ + var x: Optional(String) = Optional(String).Create( "Hallo Welt" ); + if(x.HasValue()){ + Print(x.Get()); + return 0; + } + return -1; +}