diff --git a/phino.cabal b/phino.cabal
--- a/phino.cabal
+++ b/phino.cabal
@@ -1,7 +1,7 @@
 cabal-version:      3.0
 
 name:               phino
-version:            0.0.0.34
+version:            0.0.0.35
 license:            MIT
 synopsis:           Command-Line Manipulator of 𝜑-Calculus Expressions
 description:        Please see the README on GitHub at <https://github.com/objectionary/phino#readme>
diff --git a/src/Functions.hs b/src/Functions.hs
--- a/src/Functions.hs
+++ b/src/Functions.hs
@@ -145,4 +145,22 @@
   attr <- parseAttributeThrows (btsToUnescapedStr bts)
   pure (TeAttribute attr)
 buildTermFromFunction "tau" _ _ _ = throwIO (userError "Function tau() requires exactly 1 argument as expression")
+buildTermFromFunction "string" [Y.ArgExpression expr] subst _ = do
+  (expr', _) <- buildExpressionThrows expr subst
+  str <- case expr' of
+    DataNumber bts -> pure (DataString (strToBts (either show show (btsToNum bts))))
+    DataString bts -> pure (DataString bts)
+    exp ->
+      throwIO
+        ( userError
+            ( printf
+                "Couldn't convert given expression to 'Φ̇.string' object, only 'Φ̇.number' or 'Φ̇.string' are allowed\n%s"
+                (prettyExpression' exp)
+            )
+        )
+  pure (TeExpression str)
+buildTermFromFunction "string" [Y.ArgAttribute attr] subst _ = do
+  attr' <- buildAttributeThrows attr subst
+  pure (TeExpression (DataString (strToBts (prettyAttribute attr'))))
+buildTermFromFunction "string" _ _ _ = throwIO (userError "Function string() requires exactly 1 argument as attribute or data expression (Φ̇.number or Φ̇.string)")
 buildTermFromFunction func _ _ _ = throwIO (userError (printf "Function %s() is not supported or does not exist" func))
diff --git a/src/Rewriter.hs b/src/Rewriter.hs
--- a/src/Rewriter.hs
+++ b/src/Rewriter.hs
@@ -13,7 +13,6 @@
 import Data.Foldable (foldlM)
 import qualified Data.Map.Strict as M
 import Data.Maybe (catMaybes, fromMaybe, isJust)
-import Debug.Trace (trace)
 import Logger (logDebug)
 import Matcher (MetaValue (MvAttribute, MvBindings, MvBytes, MvExpression), Subst (Subst), combine, combineMany, defaultScope, matchProgram, substEmpty, substSingle)
 import Misc (ensuredFile)
diff --git a/src/Rule.hs b/src/Rule.hs
--- a/src/Rule.hs
+++ b/src/Rule.hs
@@ -92,7 +92,7 @@
 isNF expr ctx = not (matchesAnyNormalizationRule expr ctx)
 
 meetCondition' :: Y.Condition -> Subst -> RuleContext -> IO [Subst]
-meetCondition' (Y.Or []) subst _ = pure [subst]
+meetCondition' (Y.Or []) _ _ = pure []
 meetCondition' (Y.Or (cond : rest)) subst ctx = do
   met <- meetCondition' cond subst ctx
   if null met
diff --git a/test/RuleSpec.hs b/test/RuleSpec.hs
--- a/test/RuleSpec.hs
+++ b/test/RuleSpec.hs
@@ -21,7 +21,8 @@
 import Yaml qualified
 
 data ConditionPack = ConditionPack
-  { expression :: Expression,
+  { failure :: Maybe Bool,
+    expression :: Expression,
     pattern :: Expression,
     condition :: Yaml.Condition
   }
@@ -39,10 +40,19 @@
         let matched = matchProgram (pattern pack) prog
         unless (matched /= []) (expectationFailure "List of matched substitutions is empty which is not expected")
         met <- meetCondition (condition pack) matched (RuleContext prog buildTermFromFunction)
-        when
-          (null met)
-          ( expectationFailure $
-              "List of substitution after condition check must be not empty\nOriginal substitutions:\n"
-                ++ prettySubsts matched
-          )
+        case failure pack of
+          Just True ->
+            unless
+              (null met)
+              ( expectationFailure $
+                  "List of substitutions after condition check must be empty, but got:\n"
+                    ++ prettySubsts matched
+              )
+          _ ->
+            when
+              (null met)
+              ( expectationFailure $
+                  "List of substitution after condition check must be not empty\nOriginal substitutions:\n"
+                    ++ prettySubsts matched
+              )
     )
