summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoman Smrž <roman.smrz@seznam.cz>2026-04-25 13:46:40 +0200
committerRoman Smrž <roman.smrz@seznam.cz>2026-05-17 21:54:23 +0200
commitd41cc2a1cdf9fc7a9d5781779363b9bb3eb82c00 (patch)
treee2c7555cbf2be5981b805c459861e5834d31b23f
parent0d2b55b41a8f38264fd510efd4c1306239c94d17 (diff)
Concat builtin function
Changelog: Added `concat` function for lists
-rw-r--r--README.md6
-rw-r--r--src/Test/Builtins.hs13
-rw-r--r--test/asset/list/concat.et8
-rw-r--r--test/script/list.et16
4 files changed, 41 insertions, 2 deletions
diff --git a/README.md b/README.md
index a7414b3..8d40a6f 100644
--- a/README.md
+++ b/README.md
@@ -234,8 +234,10 @@ let numbers = [1, 2, 4]
```
List elements can be of any type, but all elements of a particular list must have the same type.
-
-Used in the `for` command.
+They can be concatenated using the `concat` function, which takes a list of lists as argument:
+```
+let list = concat [[1], [2, 3], [4]] # = [1, 2, 3, 4,]
+```
### Built-in commands
diff --git a/src/Test/Builtins.hs b/src/Test/Builtins.hs
index 32483d1..85f7b86 100644
--- a/src/Test/Builtins.hs
+++ b/src/Test/Builtins.hs
@@ -6,6 +6,7 @@ import Data.Map qualified as M
import Data.Proxy
import Data.Scientific
import Data.Text (Text)
+import Data.Text qualified as T
import Process
import Process.Signal
@@ -20,6 +21,7 @@ builtins = M.fromList $ concat
, fq "guard" builtinGuard
, fq "multiply_timeout" builtinMultiplyTimeout
, fq "wait" builtinWait
+ , fq "concat" builtinConcat
]
, map (uncurry fq) signalBuiltins
]
@@ -73,3 +75,14 @@ builtinMultiplyTimeout = SomeExpr $ ArgsReq (biArgs $ [ ( Just "by", SomeArgumen
builtinWait :: SomeExpr
builtinWait = SomeExpr $ Pure $ TestBlockStep EmptyTestBlock Wait
+
+builtinConcat :: SomeExpr
+builtinConcat = SomeExpr $ TypeLambda (TypeVar "a")
+ (ExprTypeFunction
+ (ExprTypeArguments $ FunctionArguments $ M.singleton Nothing $ SomeArgumentType RequiredArgument
+ (ExprTypeApp (ExprTypeConstr1 (Proxy @[])) [ ExprTypeApp (ExprTypeConstr1 (Proxy @[])) [ ExprTypeVar (TypeVar "a") ] ] ))
+ (ExprTypeApp (ExprTypeConstr1 (Proxy @[])) [ ExprTypeVar (TypeVar "a") ])
+ ) $ \case
+ ExprTypePrim (pa :: Proxy a) -> HideFunType (FunctionArguments $ M.singleton Nothing $ SomeArgumentType RequiredArgument (ExprTypePrim (Proxy :: Proxy [[ a ]]))) $
+ ArgsReq (biArgs [ ( Nothing, SomeArgumentType RequiredArgument (ExprTypePrim pa) ) ]) $ FunctionAbstraction $ (concat :: [[ a ]] -> [ a ]) <$> biVar "$0"
+ t -> Undefined ("ambiguous type ‘" <> T.unpack (textSomeExprType t) <> "’ for concat") :: Expr DynamicType
diff --git a/test/asset/list/concat.et b/test/asset/list/concat.et
new file mode 100644
index 0000000..8248cdc
--- /dev/null
+++ b/test/asset/list/concat.et
@@ -0,0 +1,8 @@
+test Test:
+ let list1 = [ 1 ]
+ let list2 = [ 2, 3 ]
+ let empty = [ ]
+
+ let c1 = concat [[ 1 ]]
+ let c2 = concat [[ 1 ], [], empty]
+ let c3 = concat [ list1, list2, [ 6, 5 ], list2 ]
diff --git a/test/script/list.et b/test/script/list.et
new file mode 100644
index 0000000..8dcb4a8
--- /dev/null
+++ b/test/script/list.et
@@ -0,0 +1,16 @@
+module list
+
+asset scripts:
+ path: ../asset/list
+
+
+test ListConcat:
+ spawn as p
+ with p:
+ send "load ${scripts.path}/concat.et"
+ expect /load-done/
+
+ send "run Test"
+ local:
+ expect /(run-.*)/ capture done
+ guard (done == "run-done")