Tags#
Tags are markers on IR nodes that provide type information, schema references, or operation instructions. They're the mechanism by which schemas reference other schemas and by which operations are invoked.
What are Tags?#
Tags appear on IR nodes using the !tagName syntax. They serve several purposes:
- Schema References:
!personmeans "this node conforms to the person schema" - Type Markers:
!irtypemarks built-in types - Operations:
!or,!and,!nullifyinvoke operations - Custom Tags: Schemas can define their own tags
Tag Syntax#
Tags use the ! prefix:
!person # Reference to person schema
!irtype 1 # Built-in number type
!or # OR operation
!and # AND operation
Tags can be composed:
!tag1.tag2 # Composed tags
!match:or # Context-qualified tag
Schema Tags#
When a schema has a signature.name, that name becomes available as a tag
reference. For example:
signature:
name: person
# Now !person can be used to reference this schema
Other schemas can then reference it:
define:
user: !person null # Reference to person schema
number: !from(base-schema,number) null # Reference to definition in another schema
post: # post definition with structure
title: !irtype ""
content: !irtype ""
author: .[user] # Reference to definition in same schema using expr-lang
The schema system automatically creates a tag entry for signature.name in
the schema's tags map, so you don't need to explicitly define it unless
you want to add additional metadata (like contexts or descriptions).
Tag Definitions#
Schemas can define tags in the tags field. This is metadata about what
tags are available and in which contexts they're valid:
tags:
custom-or:
contexts:
- tony-format/context/match
description: "Custom OR operation for matching"
schema: .custom-or-definition
A TagDefinition can have:
- Name: The tag name (e.g., "or", "and")
- Contexts: List of context URIs where this tag is valid
- SchemaRef: Optional reference to a schema that defines this tag's behavior
- Description: Human-readable description of what the tag does
Built-in Tags#
Type Tags#
!irtype- Built-in type marker (used with values like1,"",true,null,[],{})
Match Context Tags#
!or,!and,!not- Boolean operations!type,!glob,!field- Type and field matching!tag,!subtree,!all- Structural matching!let,!if,!dive,!embed- Control flow
Patch Context Tags#
!nullify,!insert,!delete,!replace- Basic operations!rename,!strdiff,!arraydiff- Transformations!addtag,!rmtag,!retag- Tag manipulation
Eval Context Tags#
!eval,!file,!exec- Execution!tostring,!toint,!tovalue- Type conversion
Tag Composition#
Tags can be composed to create more specific tags:
!outer.inner # Composed tag
This is useful when you have nested structures or when you want to apply multiple tags to a single node.
Context-Qualified Tags#
You can explicitly specify which context a tag comes from:
!match:or # !or from match context
!patch:nullify # !nullify from patch context
This is useful when:
- You need to disambiguate between tags with the same name in different contexts
- You want to use a tag from a different context than your schema's default
Tag Validation#
The schema system can validate that tags are:
- Available in the current context
- Properly referenced (schema exists)
- Used correctly (right number of arguments, etc.)
This validation happens when:
- Parsing schemas
- Validating documents against schemas
- Resolving schema references
Example: Using Tags#
context: tony-format/context/match
signature:
name: blog-post
define:
# Use !irtype for built-in types
title: !irtype ""
content: !irtype ""
# Use !or for unions
status: !or
- "draft"
- "published"
- "archived"
# Use !and for intersections
published-post: !and
- .[post]
- status: "published"
# Reference other schemas
author: !person
# Use match operations
valid-post: !and
- .[post]
- !not null
tags:
blog-post:
description: "A blog post schema"
contexts:
- tony-format/context/match