Skip to content

Commit e909ab8

Browse files
authored
Several fixes to the Collections API (#57)
Three bugfixes: - Add missing Map.Updated methods - Fix a bug in Map.Adjoin and Map.Concat (they're still not ideal, but at least they don't throw an exception) - Fix a bug that caused MutableMap.op[] to not be recognized
1 parent 8bb0916 commit e909ab8

File tree

9 files changed

+99
-5
lines changed

9 files changed

+99
-5
lines changed

desktop-app/nbproject/project.properties

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ app.conf=nbproject/cgsuite-app.conf
22
app.icon=branding/core/core.jar/org/netbeans/core/startup/frame48.gif
33
app.name=CGSuite
44
app.title=CGSuite
5-
app.version=2.2-beta1
5+
app.version=2.2-beta2
66
app.icon.icns=etc/cgsuite.icns
77
auxiliary.org-netbeans-modules-apisupport-installer.license-file=release/license.txt
88
auxiliary.org-netbeans-modules-apisupport-installer.os-linux=true

lib/core/src/main/resources/org/cgsuite/lang/resources/cgsuite/lang/Map.cgs

+12
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,18 @@ system class Map extends Collection, Function
4343
*/
4444
external def Reversed;
4545

46+
/** The `Map` obtained from this `Map` by associating the specified `value` with the specified `key`.
47+
* If the specified `key` is already contained in this `Map`, its value will be updated in the new `Map`; otherwise,
48+
* the specified key-value pair will be added to the new `Map`.
49+
*/
50+
external def Updated(key, value);
51+
52+
/** The `Map` obtained from this `Map` by incorporating all entries specified in `newValues`. Entries whose `key` is
53+
* already contained in this `Map` will be updated; entries whose `key` is not contained in this map will be added
54+
* to the new `Map`.
55+
*/
56+
external def Updated(newValues as Map);
57+
4658
/** All the values of this map, as a [[Set]].
4759
*/
4860
external def Values;

lib/core/src/main/scala/org/cgsuite/lang/CgscriptClass.scala

+7-1
Original file line numberDiff line numberDiff line change
@@ -1450,7 +1450,13 @@ class CgscriptClass(
14501450
case 1 => args(0)
14511451
case 2 => (args(0), args(1))
14521452
}
1453-
fn(if (isStatic) classObject else obj, argsTuple)
1453+
try {
1454+
fn(if (isStatic) classObject else obj, argsTuple)
1455+
} catch {
1456+
case exc: CgsuiteException => throw exc
1457+
case exc: Throwable =>
1458+
throw EvalException(s"An unexpected error occured in a call to `$qualifiedName`.", exc)
1459+
}
14541460
}
14551461

14561462
}

lib/core/src/main/scala/org/cgsuite/lang/Ops.scala

+1-1
Original file line numberDiff line numberDiff line change
@@ -218,7 +218,7 @@ object Ops {
218218
list(i - 1)
219219
else
220220
throw EvalException(s"List index out of bounds: $i")
221-
case (map: Map[Any @unchecked, _], key: Any) =>
221+
case (map: scala.collection.Map[Any @unchecked, _], key: Any) =>
222222
map get key match {
223223
case Some(value) => value
224224
case None => throw EvalException(s"Key not found: $key")

lib/core/src/main/scala/org/cgsuite/lang/SpecialMethods.scala

+7
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,13 @@ object SpecialMethods {
124124
"cgsuite.lang.Map.ContainsKey" -> { (map: scala.collection.Map[Any,_], key: Any) =>
125125
map contains key
126126
},
127+
"cgsuite.lang.Map.Updated" -> { (map: scala.collection.Map[Any,_], arg: Any) =>
128+
arg match {
129+
case (key, value) => map.toMap.updated(key, value)
130+
case entries: Map[_, _] => map.toMap ++ entries
131+
case _ => sys.error("this should never happen")
132+
}
133+
},
127134
"cgsuite.lang.Set.Intersection" -> { (set: scala.collection.Set[Any], that: scala.collection.Set[Any]) =>
128135
set intersect that
129136
},

lib/core/src/main/scala/org/cgsuite/lang/System.scala

+1-1
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ object System extends LazyLogging {
1919

2020
val copyrightYear = "2003-2024"
2121

22-
val version = "2.2-beta1"
22+
val version = "2.2-beta2"
2323

2424
def clearAll(): Unit = {
2525
UiHarness.uiHarness.clearUiVars()

lib/core/src/main/scala/org/cgsuite/lang/SystemClassRegistry.scala

+1-1
Original file line numberDiff line numberDiff line change
@@ -35,9 +35,9 @@ private[lang] object SystemClassRegistry {
3535
"cgsuite.lang.Set" -> classOf[scala.collection.Set[_]],
3636
"cgsuite.lang.Map" -> classOf[scala.collection.Map[_,_]],
3737
"cgsuite.lang.MapEntry" -> classOf[(_,_)],
38+
"cgsuite.lang.Collection" -> classOf[Iterable[_]],
3839
"cgsuite.lang.Function" -> classOf[PartialFunction[_, _]],
3940
"cgsuite.lang.System" -> classOf[System],
40-
"cgsuite.lang.Collection" -> classOf[Iterable[_]],
4141
"cgsuite.lang.InstanceClass" -> classOf[InstanceClass],
4242

4343
"cgsuite.util.Strip" -> classOf[Strip],

lib/core/src/test/scala/org/cgsuite/lang/CgsuiteLangTest.scala

+13
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,18 @@ class CgsuiteLangTest extends CgscriptSpec {
2424
(s"Set: $call", s"{$seq}.$call", result)
2525
}
2626

27+
val mutableLists = collectionScenarios map { case (call, seq, result) =>
28+
(s"MutableList: $call", s"x := MutableList(); x.AddAll([$seq]); x.$call", result)
29+
}
30+
31+
val mutableSets = collectionScenarios map { case (call, seq, result) =>
32+
(s"MutableSet: $call", s"x := MutableSet(); x.AddAll([$seq]); x.$call", result)
33+
}
34+
2735
executeTests(Table(header, lists : _*))
2836
executeTests(Table(header, sets : _*))
37+
executeTests(Table(header, mutableLists : _*))
38+
executeTests(Table(header, mutableSets : _*))
2939

3040
}
3141

@@ -81,6 +91,9 @@ class CgsuiteLangTest extends CgscriptSpec {
8191
("Map: Entries", "{7 => true, 1/2 => ^^*}.Entries", "{1/2 => ^^*,7 => true}"),
8292
("Map: Keys", "{7 => true, 1/2 => ^^*}.Keys", "{1/2,7}"),
8393
("Map: Reversed", "{7 => true, 1/2 => ^^*}.Reversed", "{^^* => 1/2, true => 7}"),
94+
("Map: Updated 1", "{7 => true, 1/2 => ^^*}.Updated(6, 19)", "{1/2 => ^^*, 6 => 19, 7 => true}"),
95+
("Map: Updated 2", "{7 => true, 1/2 => ^^*}.Updated(7, Left)", "{1/2 => ^^*, 7 => Left}"),
96+
("Map: Updated 3", "{7 => true, 1/2 => ^^*}.Updated({6 => 19, 7 => Left})", "{1/2 => ^^*, 6 => 19, 7 => Left}"),
8497
("Map: Values", "{7 => true, 1/2 => ^^*}.Values", "{^^*,true}")
8598
))
8699

lib/core/src/test/scala/org/cgsuite/lang/CgsuiteUtilTest.scala

+56
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,62 @@ import org.scalatest.prop.TableDrivenPropertyChecks.Table
44

55
class CgsuiteUtilTest extends CgscriptSpec {
66

7+
"cgsuite.util.MutableList" should "implement methods correctly" in {
8+
9+
executeTests(Table(
10+
header,
11+
("MutableList: Construction (empty)", "MutableList()", "MutableList()"),
12+
("MutableList: Construction (seeded)", "x := MutableList([3,4,5])", "MutableList(3, 4, 5)"),
13+
("MutableList: Lookup", "x[2]", "4"),
14+
("MutableList: Lookup (not in list)", "x[0]", "!!List index out of bounds: 0"),
15+
("MutableList: Add", "x.Add(*); x", "MutableList(3, 4, 5, *)"),
16+
("MutableList: AddAll", "x.AddAll([1/2, 1/4, *2, *3, 1/2, 1/4, *3]); x", "MutableList(3, 4, 5, *, 1/2, 1/4, *2, *3, 1/2, 1/4, *3)"),
17+
("MutableList: Contains", "x.Contains(*3)", "true"),
18+
("MutableList: Remove", "x.Remove(1/2); x", "MutableList(3, 4, 5, *, 1/4, *2, *3, 1/2, 1/4, *3)"),
19+
("MutableList: RemoveAll", "x.RemoveAll([4, *2]); x", "MutableList(3, 5, *, 1/4, *3, 1/2, 1/4, *3)"),
20+
("MutableList: RemoveAll (multi)", "x.RemoveAll([1/4, 1/4]); x", "MutableList(3, 5, *, *3, 1/2, *3)"),
21+
("MutableList: RemoveAt", "x.RemoveAt(2); x", "MutableList(3, *, *3, 1/2, *3)"),
22+
("MutableList: Sort", "x.Sort(); x", "MutableList(1/2, 3, *, *3, *3)"),
23+
("MutableList: SortWith", "x.SortWith((a, b) -> if a < b then -1 elseif a > b then 1 else 0 end)", "MutableList(*, *3, *3, 1/2, 3)"),
24+
("MutableList: Clear", "x.Clear(); x", "MutableList()"),
25+
26+
))
27+
28+
}
29+
30+
"cgsuite.util.MutableSet" should "implement methods correctly" in {
31+
32+
executeTests(Table(
33+
header,
34+
("MutableSet: Construction (empty)", "MutableSet()", "MutableSet()"),
35+
("MutableSet: Construction (seeded)", "x := MutableSet([3,4,5])", "MutableSet(3, 4, 5)"),
36+
("MutableSet: Add", "x.Add(*); x", "MutableSet(3, 4, 5, *)"),
37+
("MutableSet: AddAll", "x.AddAll([1/2, 1/4, *2, *3, 1/2, 1/4, *3]); x", "MutableSet(1/4, 1/2, 3, 4, 5, *, *2, *3)"),
38+
("MutableSet: Contains", "x.Contains(*3)", "true"),
39+
("MutableSet: Remove", "x.Remove(1/4); x", "MutableSet(1/2, 3, 4, 5, *, *2, *3)"),
40+
("MutableSet: RemoveAll", "x.RemoveAll([3, 5, *2, 5, 19]); x", "MutableSet(1/2, 4, *, *3)"),
41+
("MutableSet: Clear", "x.Clear(); x", "MutableSet()")
42+
))
43+
44+
}
45+
"cgsuite.util.MutableMap" should "implement methods correctly" in {
46+
47+
executeTests(Table(
48+
header,
49+
("MutableMap: Construction (empty)", "MutableMap()", "MutableMap()"),
50+
("MutableMap: Construction (seeded)", "x := MutableMap({3 => true, 5 => Left})", "MutableMap(3 => true, 5 => Left)"),
51+
("MutableMap: Lookup", "x[5]", "Left"),
52+
("MutableMap: Lookup (not in map)", "x[*]", "!!Key not found: *"),
53+
("MutableMap: ContainsKey", "x.ContainsKey(5)", "true"),
54+
("MutableMap: Entries", "x.Entries", "{3 => true,5 => Left}"),
55+
("MutableMap: Put 1", "x.Put(3, false); x", "MutableMap(3 => false, 5 => Left)"),
56+
("MutableMap: Put 2", "x.Put(*, 101); x", "MutableMap(3 => false, 5 => Left, * => 101)"),
57+
("MutableMap: PutAll", "x.PutAll({Right => 1474, 3 => 1/7}); x", "MutableMap(3 => 1/7, 5 => Left, * => 101, Right => 1474)"),
58+
("MutableMap: Clear", "x.Clear(); x", "MutableMap()")
59+
))
60+
61+
}
62+
763
"cgsuite.util.Strip" should "implement methods correctly" in {
864

965
executeTests(Table(

0 commit comments

Comments
 (0)