summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoman Smrž <roman.smrz@seznam.cz>2026-05-18 20:34:43 +0200
committerRoman Smrž <roman.smrz@seznam.cz>2026-05-18 20:34:43 +0200
commita40b7da1ab4028bba53f9768b7a58a7c619a052d (patch)
treeae81e2bb556957ec5891f2c0d3ead8d60147af3f
parent9e1d65b41b0f5435859794682880c93767d1dc44 (diff)
Concatenation operator for listsHEADmaster
Changelog: Added `++` operator to concatenate lists
-rw-r--r--README.md6
-rw-r--r--src/Parser/Expr.hs24
-rw-r--r--test/asset/list/concat.et8
-rw-r--r--test/script/list.et8
4 files changed, 45 insertions, 1 deletions
diff --git a/README.md b/README.md
index 8d40a6f..62ae1a0 100644
--- a/README.md
+++ b/README.md
@@ -236,7 +236,11 @@ let numbers = [1, 2, 4]
List elements can be of any type, but all elements of a particular list must have the same type.
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,]
+let list = concat [[1], [2, 3], [4]] # = [1, 2, 3, 4]
+```
+Or with the `++` operator:
+```
+let list = [1] ++ [2, 3] ++ [4] # = [1, 2, 3, 4]
```
### Built-in commands
diff --git a/src/Parser/Expr.hs b/src/Parser/Expr.hs
index 7d57791..a0ae70d 100644
--- a/src/Parser/Expr.hs
+++ b/src/Parser/Expr.hs
@@ -302,6 +302,19 @@ someExpr complexity = label "expression" $ do
, SomeBinOp ((-) @Scientific)
]
]
+ , [ let tvar = TypeVar "a"
+ targs = FunctionArguments $ M.fromList
+ [ ( Just "$l", ( VarName "$l", SomeArgumentType RequiredArgument $ ExprTypeApp (ExprTypeConstr1 (Proxy @[])) [ ExprTypeVar tvar ]) )
+ , ( Just "$r", ( VarName "$r", SomeArgumentType RequiredArgument $ ExprTypeApp (ExprTypeConstr1 (Proxy @[])) [ ExprTypeVar tvar ]) )
+ ]
+ in infixrExpr "++" $ SomeExpr $ TypeLambda tvar (ExprTypeFunction (ExprTypeArguments $ fmap snd targs) (ExprTypeApp (ExprTypeConstr1 (Proxy @[])) [ ExprTypeVar tvar ])) $ \case
+ ExprTypePrim (Proxy :: Proxy a) ->
+ HideFunType (fmap snd targs) $ ArgsReq targs $
+ FunctionAbstraction $ ((++) @a)
+ <$> (Variable SourceLineBuiltin $ LocalVarName $ VarName "$l")
+ <*> (Variable SourceLineBuiltin $ LocalVarName $ VarName "$r")
+ t -> Undefined ("ambiguous type ‘" <> T.unpack (textSomeExprType t) <> "’ for operator ‘++’") :: Expr DynamicType
+ ]
, [ binary' "==" (\op xs ys -> length xs == length ys && and (zipWith op xs ys)) $
[ SomeBinOp ((==) @Integer)
, SomeBinOp ((==) @Scientific)
@@ -345,6 +358,17 @@ someExpr complexity = label "expression" $ do
choice $ map (\(SomeUnOp op) -> SomeExpr <$> applyUnOp off op e) ops
+ infixrExpr :: String -> SomeExpr -> Operator TestParser (TestParser SomeExpr)
+ infixrExpr name fun = InfixR $ do
+ void $ osymbol name
+ return $ \p q -> do
+ loff <- stateOffset <$> getParserState
+ l <- p
+ roff <- stateOffset <$> getParserState
+ r <- q
+ applyFunctionArguments (FunctionArguments $ M.fromList [ ( Just "$l", ( loff, l ) ), ( Just "$r", ( roff, r ) ) ]) fun
+
+
binary :: String -> [SomeBinOp] -> Operator TestParser (TestParser SomeExpr)
binary name = binary' name (undefined :: forall a b. (a -> b -> Void) -> [a] -> [b] -> Integer)
-- use 'Void' that can never match actually used type to disable recursion
diff --git a/test/asset/list/concat.et b/test/asset/list/concat.et
index 613df57..c669a78 100644
--- a/test/asset/list/concat.et
+++ b/test/asset/list/concat.et
@@ -28,3 +28,11 @@ test Test:
local:
shell on n:
echo "c3-end"
+
+ let c4 = list1 ++ list2 ++ [ 6, 5 ] ++ list2
+ for i in c4:
+ shell on n:
+ echo "c4 $i"
+ local:
+ shell on n:
+ echo "c4-end"
diff --git a/test/script/list.et b/test/script/list.et
index a654111..cfd4803 100644
--- a/test/script/list.et
+++ b/test/script/list.et
@@ -28,6 +28,14 @@ test ListConcat:
"c3 2"
"c3 3"
"c3-end"
+ "c4 1"
+ "c4 2"
+ "c4 3"
+ "c4 6"
+ "c4 5"
+ "c4 2"
+ "c4 3"
+ "c4-end"
local:
expect /(run-.*)/ capture done
guard (done == "run-done")