diff --git a/media/test-project/test.spice b/media/test-project/test.spice index e5c230282..cc853e4c4 100644 --- a/media/test-project/test.spice +++ b/media/test-project/test.spice @@ -1,88 +1,50 @@ -type Size alias long; - -type Counter struct { - Size value -} - -p Counter.ctor(long initialValue = 0l) { - this.value = initialValue; -} - -f Counter.getValue() { - return this.value; -} - -f operator+(const Counter c1, const Counter c2) { - return Counter(c1.value + c2.value); -} - -f operator-(const Counter c1, const Counter c2) { - return Counter(c1.value - c2.value); -} - -f operator*(const Counter c1, const Counter c2) { - return Counter(c1.value * c2.value); -} - -f operator/(const Counter c1, const Counter c2) { - return Counter(c1.value / c2.value); -} - -f operator<<(const Counter c1, const Counter c2) { - return Counter(c1.value << c2.value); -} - -f operator>>(const Counter c1, const Counter c2) { - return Counter(c1.value >> c2.value); -} - -p operator+=(Counter& c1, const Counter c2) { - c1.value += c2.value; -} - -p operator-=(Counter& c1, const Counter c2) { - c1.value -= c2.value; -} - -p operator*=(Counter& c1, const Counter c2) { - c1.value *= c2.value; -} - -p operator/=(Counter& c1, const Counter c2) { - c1.value /= c2.value; -} - -f operator[](Counter& c, unsigned int summand) { - c.value += summand; - return c.value; -} +import "std/data/map"; f main() { - Counter counter1 = Counter(2l); - Counter counter2 = Counter(3l); - printf("Counter1 value: %d\n", counter1.getValue()); - printf("Counter2 value: %d\n", counter2.getValue()); - Counter counter3 = counter1 + counter2; // Here we call the overloaded operator - printf("Counter3 value: %d\n", counter3.getValue()); - Counter counter4 = counter3 - counter2; // Here we call the overloaded operator - printf("Counter4 value: %d\n", counter4.getValue()); - Counter counter5 = counter4 * counter2; // Here we call the overloaded operator - printf("Counter5 value: %d\n", counter5.getValue()); - Counter counter6 = counter5 / counter2; // Here we call the overloaded operator - printf("Counter6 value: %d\n", counter6.getValue()); - Counter counter7 = counter6 << counter2; // Here we call the overloaded operator - printf("Counter7 value: %d\n", counter7.getValue()); - Counter counter8 = counter7 >> counter2; // Here we call the overloaded operator - printf("Counter8 value: %d\n", counter8.getValue()); - counter8 += counter2; // Here we call the overloaded operator - printf("Counter8 value: %d\n", counter8.getValue()); - counter8 -= counter2; // Here we call the overloaded operator - printf("Counter8 value: %d\n", counter8.getValue()); - counter8 *= counter2; // Here we call the overloaded operator - printf("Counter8 value: %d\n", counter8.getValue()); - counter8 /= counter2; // Here we call the overloaded operator - printf("Counter8 value: %d\n", counter8.getValue()); - Size res = counter8[12]; - assert res == 14; - printf("Counter8 value: %d\n", counter8.getValue()); + Map map; + assert map.getSize() == 0l; + assert map.isEmpty(); + map.insert(1, "Hello"); + assert map.getSize() == 1l; + assert !map.isEmpty(); + map.insert(2, "World"); + assert map.getSize() == 2l; + map.insert(3, "Foo"); + assert map.getSize() == 3l; + map.insert(4, "Bar"); + assert map.getSize() == 4l; + assert map.contains(1); + assert map.contains(2); + assert map.contains(3); + assert map.contains(4); + assert map.get(1) == "Hello"; + assert map[2] == "World"; + assert map.get(3) == "Foo"; + assert map.get(4) == "Bar"; + map.remove(2); + assert map.getSize() == 3l; + assert !map.contains(2); + assert !map.isEmpty(); + map.remove(1); + assert map.getSize() == 2l; + assert !map.contains(1); + assert !map.isEmpty(); + string& foo = map.get(3); + assert foo == "Foo"; + foo = "Baz"; + assert map[3] == "Baz"; + Result bar = map.getSafe(4); + assert bar.isOk(); + assert bar.unwrap() == "Bar"; + Result baz = map.getSafe(5); + assert baz.isErr(); + map.remove(3); + assert map.getSize() == 1l; + assert !map.contains(3); + assert !map.isEmpty(); + map.remove(4); + assert map.getSize() == 0l; + assert !map.contains(4); + assert map.isEmpty(); + printf("All assertions passed!\n"); } \ No newline at end of file diff --git a/src/irgenerator/GenExpressions.cpp b/src/irgenerator/GenExpressions.cpp index afaf6c037..92cd7f6b0 100644 --- a/src/irgenerator/GenExpressions.cpp +++ b/src/irgenerator/GenExpressions.cpp @@ -667,7 +667,7 @@ std::any IRGenerator::visitPostfixUnaryExpr(const PostfixUnaryExprNode *node) { ResolverFct lhsV = [&] { return resolveValue(lhsSTy, lhs); }; ResolverFct lhsP = [&] { return resolveAddress(lhs); }; ResolverFct idxV = [&] { return resolveValue(indexExpr); }; - ResolverFct idxP = [&] { return nullptr; }; + ResolverFct idxP = [&] { return resolveAddress(indexExpr); }; lhs = conversionManager.callOperatorOverloadFct<2>(node, {lhsV, lhsP, idxV, idxP}, 0); break; } diff --git a/std/data/map.spice b/std/data/map.spice index b9a1d7f87..1c7a67542 100644 --- a/std/data/map.spice +++ b/std/data/map.spice @@ -39,7 +39,7 @@ public p Map.remove(const K& key) { } /** - * Gets a value from the map. + * Retrieve the value associated with the given key. * Note: If the key is not found in the map, this function will panic. To avoid this, use getSafe instead. * * @param key The key to get. @@ -50,10 +50,22 @@ public f Map.get(const K& key) { } /** - * Gets a value from the map, returning a result. + * Retrieve the value associated with the given key. + * Note: If the key is not found in the map, this function will panic. To avoid this, use getSafe instead. * * @param key The key to get. - * @return The value associated with the key, or an error if the key does not exist. + * @return The value associated with the key. + */ +public f operator[](Map& map, const K& key) { + return map.get(key); +} + +/** + * Retrieve the value associated with the given key as Result. + * If the key is not found, the result contains an error. + * + * @param key The key to look up + * @return Result, containing the value associated with the key or an error if the key is not found */ public f> Map.getSafe(const K& key) { return this.tree.findSafe(key); diff --git a/std/data/unordered-map.spice b/std/data/unordered-map.spice index c1be54fbf..639eafe46 100644 --- a/std/data/unordered-map.spice +++ b/std/data/unordered-map.spice @@ -46,11 +46,22 @@ public f UnorderedMap.get(const K& key) { } /** - * Retrieve the value associated with the given key as Optional. - * If the key is not found, return an empty optional. + * Retrieve the value associated with the given key. + * If the key is not found, panic. + * + * @param key The key to look up + * @return The value associated with the key + */ +public f operator[](UnorderedMap& map, const K& key) { + return map.get(key); +} + +/** + * Retrieve the value associated with the given key as Result. + * If the key is not found, the result contains an error. * * @param key The key to look up - * @return Optional, containing the value associated with the key or empty if the key is not found + * @return Result, containing the value associated with the key or an error if the key is not found */ public f> UnorderedMap.getSafe(const K& key) { return this.hashTable.getSafe(key); diff --git a/std/data/vector.spice b/std/data/vector.spice index 788dc4feb..22e2c6794 100644 --- a/std/data/vector.spice +++ b/std/data/vector.spice @@ -106,8 +106,7 @@ public f Vector.get(unsigned long index) { panic(Error("Access index out of bounds")); } unsafe { - T& t = this.contents[index]; - return t; + return this.contents[index]; } } @@ -120,6 +119,24 @@ public f Vector.get(unsigned int index) { return this.get((unsigned long) index); } +/** + * Get an item at a certain index + * + * @return item at index + */ +public f operator[](Vector& v, unsigned long index) { + return v.get(index); +} + +/** + * Get an item at a certain index + * + * @return item at index + */ +public f operator[](Vector& v, unsigned int index) { + return v.get((unsigned long) index); +} + /** * Remove an item at a certain index * diff --git a/std/runtime/string_rt.spice b/std/runtime/string_rt.spice index eb7f3ec99..19e964242 100644 --- a/std/runtime/string_rt.spice +++ b/std/runtime/string_rt.spice @@ -286,7 +286,9 @@ public f operator!=(const string& a, const String& b) { * @return Character at the given index */ public f operator[](String& str, unsigned long idx) { - assert idx < str.length; + if idx >= str.length { + panic(Error("Access index out of bounds")); + } unsafe { return str.contents[idx]; } diff --git a/test/test-files/irgenerator/debug-info/success-dbg-info-complex/ir-code.ll b/test/test-files/irgenerator/debug-info/success-dbg-info-complex/ir-code.ll index b78cf06d5..dbeb303bc 100644 --- a/test/test-files/irgenerator/debug-info/success-dbg-info-complex/ir-code.ll +++ b/test/test-files/irgenerator/debug-info/success-dbg-info-complex/ir-code.ll @@ -534,11 +534,11 @@ attributes #2 = { cold noreturn nounwind } !42 = !{!"branch_weights", i32 2000, i32 1} !43 = !DILocation(line: 13, column: 14, scope: !15) !44 = !DILocalVariable(name: "it", scope: !15, file: !5, line: 13, type: !45) -!45 = !DICompositeType(tag: DW_TAG_structure_type, name: "VectorIterator", scope: !5, file: !5, line: 263, size: 192, align: 8, flags: DIFlagTypePassByReference | DIFlagNonTrivial, elements: !46, identifier: "struct.VectorIterator") +!45 = !DICompositeType(tag: DW_TAG_structure_type, name: "VectorIterator", scope: !5, file: !5, line: 280, size: 192, align: 8, flags: DIFlagTypePassByReference | DIFlagNonTrivial, elements: !46, identifier: "struct.VectorIterator") !46 = !{!47, !49} -!47 = !DIDerivedType(tag: DW_TAG_member, name: "vector", scope: !45, file: !5, line: 264, baseType: !48, size: 64, offset: 64) +!47 = !DIDerivedType(tag: DW_TAG_member, name: "vector", scope: !45, file: !5, line: 281, baseType: !48, size: 64, offset: 64) !48 = !DIDerivedType(tag: DW_TAG_reference_type, baseType: !28, size: 64) -!49 = !DIDerivedType(tag: DW_TAG_member, name: "cursor", scope: !45, file: !5, line: 265, baseType: !33, size: 64, offset: 128) +!49 = !DIDerivedType(tag: DW_TAG_member, name: "cursor", scope: !45, file: !5, line: 282, baseType: !33, size: 64, offset: 128) !50 = !DILocation(line: 13, column: 5, scope: !15) !51 = !DILocation(line: 14, column: 12, scope: !15) !52 = !DILocation(line: 15, column: 12, scope: !15) diff --git a/test/test-files/std/data/combined-test-2/cout.out b/test/test-files/std/data/combined-test-2/cout.out new file mode 100644 index 000000000..6b6083f8b --- /dev/null +++ b/test/test-files/std/data/combined-test-2/cout.out @@ -0,0 +1,3 @@ +Hexxo +Depr +World diff --git a/test/test-files/std/data/combined-test-2/source.spice b/test/test-files/std/data/combined-test-2/source.spice new file mode 100644 index 000000000..db31a5dc9 --- /dev/null +++ b/test/test-files/std/data/combined-test-2/source.spice @@ -0,0 +1,18 @@ +import "std/data/vector"; + +f main() { + Vector vec; + vec.pushBack(String("Hello")); + vec.pushBack(String("Dear")); + vec.pushBack(String("\n World")); + + vec[1][2] = 'p'; + String& item0 = vec[0]; + item0.replaceAll("l", "x"); + String& item2 = vec.get(2); + item2 = item2.trim(); + + foreach String s : vec { + printf("%s\n", s); + } +} \ No newline at end of file diff --git a/test/test-files/std/data/map-normal-usecase/source.spice b/test/test-files/std/data/map-normal-usecase/source.spice index 7285e39ff..cc853e4c4 100644 --- a/test/test-files/std/data/map-normal-usecase/source.spice +++ b/test/test-files/std/data/map-normal-usecase/source.spice @@ -18,7 +18,7 @@ f main() { assert map.contains(3); assert map.contains(4); assert map.get(1) == "Hello"; - assert map.get(2) == "World"; + assert map[2] == "World"; assert map.get(3) == "Foo"; assert map.get(4) == "Bar"; map.remove(2); @@ -32,7 +32,7 @@ f main() { string& foo = map.get(3); assert foo == "Foo"; foo = "Baz"; - assert map.get(3) == "Baz"; + assert map[3] == "Baz"; Result bar = map.getSafe(4); assert bar.isOk(); assert bar.unwrap() == "Bar"; diff --git a/test/test-files/std/data/unordered-map-normal-usecase/source.spice b/test/test-files/std/data/unordered-map-normal-usecase/source.spice index 716382ea1..b12f951c5 100644 --- a/test/test-files/std/data/unordered-map-normal-usecase/source.spice +++ b/test/test-files/std/data/unordered-map-normal-usecase/source.spice @@ -16,7 +16,7 @@ f main() { assert map.contains(4); assert !map.contains(5); assert map.get(1) == "one"; - assert map.get(2) == "two"; + assert map[2] == "two"; assert map.get(3) == "three"; assert map.get(4) == "four"; const Result item5 = map.getSafe(5); @@ -30,7 +30,7 @@ f main() { map.upsert(1, "one"); map.upsert(1, "one new"); assert map.getSize() == 1; - assert map.get(1) == "one new"; + assert map[1] == "one new"; map.remove(1); assert map.isEmpty(); diff --git a/test/test-files/std/data/vector-normal-usecase/source.spice b/test/test-files/std/data/vector-normal-usecase/source.spice index 913fc0609..5ffa025a1 100644 --- a/test/test-files/std/data/vector-normal-usecase/source.spice +++ b/test/test-files/std/data/vector-normal-usecase/source.spice @@ -38,11 +38,11 @@ f main() { v1.removeAt(0); assert v1.getSize() == 5; assert v1.getCapacity() == 12; - assert v1.get(0) == 7.4964598; - assert v1.get(1) == 5.3; - assert v1.get(2) == -238974.23; - assert v1.get(3) == -1234.9; - assert v1.get(4) == 0.0; + assert v1[0] == 7.4964598; + assert v1[1] == 5.3; + assert v1[2] == -238974.23; + assert v1[3] == -1234.9; + assert v1[4] == 0.0; printf("All assertions passed!\n"); } \ No newline at end of file