{
  "$schema": "https://raw.githubusercontent.com/martinring/tmlanguage/master/tmlanguage.json",
  "name": "tulam",
  "scopeName": "source.tulam",
  "patterns": [
    { "include": "#comments" },
    { "include": "#strings" },
    { "include": "#numbers" },
    { "include": "#module-declaration" },
    { "include": "#import-declaration" },
    { "include": "#default-target-declaration" },
    { "include": "#target-declaration" },
    { "include": "#type-declaration" },
    { "include": "#primitive-declaration" },
    { "include": "#repr-declaration" },
    { "include": "#class-declaration" },
    { "include": "#effect-declaration" },
    { "include": "#handler-declaration" },
    { "include": "#handler-lifecycle-clause" },
    { "include": "#structure-declaration" },
    { "include": "#instance-declaration" },
    { "include": "#function-declaration" },
    { "include": "#action-declaration" },
    { "include": "#value-declaration" },
    { "include": "#law-declaration" },
    { "include": "#fixity-declaration" },
    { "include": "#placement-clause" },
    { "include": "#scoped-bindings" },
    { "include": "#keywords" },
    { "include": "#operators" },
    { "include": "#universe-types" },
    { "include": "#type-names" },
    { "include": "#legacy-compiler-bindings" },
    { "include": "#identifiers" },
    { "include": "#punctuation" }
  ],
  "repository": {
    "comments": {
      "patterns": [
        {
          "name": "comment.line.double-slash.tulam",
          "match": "//.*$"
        },
        {
          "name": "comment.block.tulam",
          "begin": "/\\*",
          "end": "\\*/"
        }
      ]
    },
    "strings": {
      "patterns": [
        {
          "name": "string.quoted.double.tulam",
          "begin": "\"",
          "end": "\"",
          "patterns": [
            {
              "name": "constant.character.escape.tulam",
              "match": "\\\\(?:[nrt0\\\\\"']|x[0-9A-Fa-f]{2}|u\\{[0-9A-Fa-f]+\\})"
            }
          ]
        },
        {
          "name": "string.quoted.single.tulam",
          "begin": "'",
          "end": "'",
          "patterns": [
            {
              "name": "constant.character.escape.tulam",
              "match": "\\\\(?:[nrt0\\\\\"']|x[0-9A-Fa-f]{2}|u\\{[0-9A-Fa-f]+\\})"
            }
          ]
        }
      ]
    },
    "numbers": {
      "patterns": [
        {
          "name": "constant.numeric.float.tulam",
          "match": "\\b(?:[0-9]+\\.[0-9]+|[0-9]+[eE][+-]?[0-9]+|[0-9]+\\.[0-9]+[eE][+-]?[0-9]+)\\b"
        },
        {
          "name": "constant.numeric.integer.tulam",
          "match": "\\b[0-9]+\\b"
        }
      ]
    },
    "module-declaration": {
      "patterns": [
        {
          "match": "\\b(module)\\s+([A-Z][A-Za-z0-9_']*(?:\\.[A-Z][A-Za-z0-9_']*)*)",
          "captures": {
            "1": { "name": "keyword.declaration.module.tulam" },
            "2": { "name": "entity.name.namespace.tulam" }
          }
        }
      ]
    },
    "import-declaration": {
      "patterns": [
        {
          "match": "\\b(import)\\s+([A-Z][A-Za-z0-9_']*(?:\\.[A-Z][A-Za-z0-9_']*)*)",
          "captures": {
            "1": { "name": "keyword.control.import.tulam" },
            "2": { "name": "entity.name.namespace.tulam" }
          }
        }
      ]
    },
    "default-target-declaration": {
      "patterns": [
        {
          "match": "\\b(default)\\s+(target)\\b",
          "captures": {
            "1": { "name": "keyword.declaration.default.tulam" },
            "2": { "name": "keyword.declaration.target.tulam" }
          }
        }
      ]
    },
    "target-declaration": {
      "patterns": [
        {
          "match": "\\b(target)\\s+([A-Za-z_][A-Za-z0-9_'.]*)\\s*(?=\\{)",
          "captures": {
            "1": { "name": "keyword.declaration.target.tulam" },
            "2": { "name": "entity.name.type.target.tulam" }
          }
        }
      ]
    },
    "type-declaration": {
      "patterns": [
        {
          "match": "\\b(type)\\s+([A-Z][A-Za-z0-9_']*)",
          "captures": {
            "1": { "name": "keyword.declaration.type.tulam" },
            "2": { "name": "entity.name.type.tulam" }
          }
        }
      ]
    },
    "primitive-declaration": {
      "patterns": [
        {
          "match": "\\b(primitive)\\s+([A-Z][A-Za-z0-9_']*)",
          "captures": {
            "1": { "name": "keyword.declaration.primitive.tulam" },
            "2": { "name": "entity.name.type.tulam" }
          }
        }
      ]
    },
    "repr-declaration": {
      "patterns": [
        {
          "match": "\\b(repr)\\s+([A-Z][A-Za-z0-9_']*)[^;=\\n]*?\\s+(as)\\s+([A-Z][A-Za-z0-9_']*)",
          "captures": {
            "1": { "name": "keyword.declaration.repr.tulam" },
            "2": { "name": "entity.name.type.tulam" },
            "3": { "name": "keyword.operator.representation.tulam" },
            "4": { "name": "entity.name.type.tulam" }
          }
        }
      ]
    },
    "class-declaration": {
      "patterns": [
        {
          "match": "\\b(?:(abstract|sealed)\\s+)?(class)\\s+([A-Z][A-Za-z0-9_']*)",
          "captures": {
            "1": { "name": "storage.modifier.class.tulam" },
            "2": { "name": "keyword.declaration.class.tulam" },
            "3": { "name": "entity.name.type.class.tulam" }
          }
        }
      ]
    },
    "effect-declaration": {
      "patterns": [
        {
          "match": "\\b(effect)\\s+([A-Z][A-Za-z0-9_']*)",
          "captures": {
            "1": { "name": "keyword.declaration.effect.tulam" },
            "2": { "name": "entity.name.type.effect.tulam" }
          }
        }
      ]
    },
    "handler-declaration": {
      "patterns": [
        {
          "match": "\\b(handler)\\s+([A-Z][A-Za-z0-9_']*)",
          "captures": {
            "1": { "name": "keyword.declaration.handler.tulam" },
            "2": { "name": "entity.name.type.handler.tulam" }
          }
        }
      ]
    },
    "handler-lifecycle-clause": {
      "patterns": [
        {
          "comment": "return and finally are contextual handler clauses, not reserved words",
          "match": "^\\s*(return|finally)(?=\\s*\\([^\\n)]*\\)\\s*=)",
          "captures": {
            "1": { "name": "keyword.control.effect.lifecycle.tulam" }
          }
        }
      ]
    },
    "structure-declaration": {
      "patterns": [
        {
          "match": "\\b(structure|algebra|trait|morphism|bridge)\\s+([A-Z][A-Za-z0-9_']*)",
          "captures": {
            "1": { "name": "keyword.declaration.structure.tulam" },
            "2": { "name": "entity.name.type.structure.tulam" }
          }
        }
      ]
    },
    "instance-declaration": {
      "patterns": [
        {
          "match": "\\b(instance)\\s+([A-Z][A-Za-z0-9_']*)",
          "captures": {
            "1": { "name": "keyword.declaration.instance.tulam" },
            "2": { "name": "entity.name.type.structure.tulam" }
          }
        }
      ]
    },
    "function-declaration": {
      "patterns": [
        {
          "match": "\\b(function)\\s+(\\([^()\\s]+\\))",
          "captures": {
            "1": { "name": "keyword.declaration.function.tulam" },
            "2": { "name": "entity.name.function.operator.tulam" }
          }
        },
        {
          "match": "\\b(function)\\s+([a-z_][A-Za-z0-9_'#]*)",
          "captures": {
            "1": { "name": "keyword.declaration.function.tulam" },
            "2": { "name": "entity.name.function.tulam" }
          }
        }
      ]
    },
    "action-declaration": {
      "patterns": [
        {
          "match": "\\b(action)\\s+([a-z_][A-Za-z0-9_'#]*)\\s*(?=\\()",
          "captures": {
            "1": { "name": "keyword.declaration.action.tulam" },
            "2": { "name": "entity.name.function.tulam" }
          }
        }
      ]
    },
    "value-declaration": {
      "patterns": [
        {
          "match": "\\b(value)\\s+([a-z_][A-Za-z0-9_']*)",
          "captures": {
            "1": { "name": "keyword.declaration.value.tulam" },
            "2": { "name": "entity.name.variable.tulam" }
          }
        }
      ]
    },
    "law-declaration": {
      "patterns": [
        {
          "match": "\\b(law)\\s+([a-z_][A-Za-z0-9_']*)",
          "captures": {
            "1": { "name": "keyword.declaration.law.tulam" },
            "2": { "name": "entity.name.function.law.tulam" }
          }
        }
      ]
    },
    "fixity-declaration": {
      "patterns": [
        {
          "match": "\\b(infixl|infixr|infix)\\s+([0-9])",
          "captures": {
            "1": { "name": "keyword.declaration.fixity.tulam" },
            "2": { "name": "constant.numeric.integer.tulam" }
          }
        }
      ]
    },
    "placement-clause": {
      "patterns": [
        {
          "comment": "on is contextual and highlighted only when followed by declaration metadata before = or ;",
          "name": "keyword.other.placement.tulam",
          "match": "\\b(on)\\b(?=\\s+[^;=\\n]+(?:=|;|$))"
        }
      ]
    },
    "scoped-bindings": {
      "patterns": [
        {
          "comment": "resume is a handler-scoped function binding, not a reserved keyword",
          "name": "support.function.resumption.tulam",
          "match": "\\bresume\\b(?=\\s*\\()"
        }
      ]
    },
    "keywords": {
      "patterns": [
        {
          "name": "keyword.control.conditional.tulam",
          "match": "\\b(if|then|else|match)\\b"
        },
        {
          "name": "keyword.control.binding.tulam",
          "match": "\\b(let|in|where|unpack)\\b"
        },
        {
          "name": "keyword.control.effect.tulam",
          "match": "\\b(handle|handler|effect|action|with)\\b"
        },
        {
          "name": "keyword.declaration.tulam",
          "match": "\\b(type|function|fn|value|primitive|intrinsic|repr|invariant|structure|algebra|trait|morphism|bridge|instance|law|class|target)\\b"
        },
        {
          "name": "storage.modifier.tulam",
          "match": "\\b(abstract|sealed|override|final|static|private|opaque|extern|derive|deriving|default)\\b"
        },
        {
          "name": "keyword.control.module.tulam",
          "match": "\\b(module|import|open|export|hiding)\\b"
        },
        {
          "name": "keyword.operator.representation.tulam",
          "match": "\\bas\\b"
        },
        {
          "name": "keyword.other.relation.tulam",
          "match": "\\b(extends|implements|requires|super)\\b"
        },
        {
          "name": "keyword.other.quantifier.tulam",
          "match": "\\b(forall|exists)\\b|[∀∃]"
        },
        {
          "name": "keyword.declaration.fixity.tulam",
          "match": "\\b(infixl|infixr|infix)\\b"
        }
      ]
    },
    "operators": {
      "patterns": [
        {
          "name": "keyword.operator.propositional.tulam",
          "match": "===|==>"
        },
        {
          "name": "keyword.operator.arrow.tulam",
          "match": "<-|->"
        },
        {
          "name": "keyword.operator.lazy.tulam",
          "match": "~"
        },
        {
          "name": "keyword.operator.spread.tulam",
          "match": "\\.\\."
        },
        {
          "name": "keyword.operator.assignment.tulam",
          "match": "(?<!=|!)=(?!=|>)"
        },
        {
          "name": "keyword.operator.comparison.tulam",
          "match": "==|!=|<=|>=|<(?!-)|>"
        },
        {
          "name": "keyword.operator.arithmetic.tulam",
          "match": "[+\\-*/%]#?"
        },
        {
          "name": "keyword.operator.pipe.tulam",
          "match": "\\|"
        },
        {
          "name": "keyword.operator.access.tulam",
          "match": "(?<!\\.)\\.(?!\\.)"
        }
      ]
    },
    "universe-types": {
      "patterns": [
        {
          "name": "support.type.universe.tulam",
          "match": "\\bType[0-9]*\\b"
        }
      ]
    },
    "type-names": {
      "patterns": [
        {
          "name": "entity.name.type.tulam",
          "match": "\\b[A-Z][A-Za-z0-9_']*\\b"
        }
      ]
    },
    "legacy-compiler-bindings": {
      "patterns": [
        {
          "comment": "A trailing # is accepted only for legacy/compiler bindings",
          "name": "support.function.primitive.tulam",
          "match": "\\b[a-z_][A-Za-z0-9_']*#"
        }
      ]
    },
    "identifiers": {
      "patterns": [
        {
          "name": "variable.other.tulam",
          "match": "\\b[a-z_][A-Za-z0-9_']*\\b"
        }
      ]
    },
    "punctuation": {
      "patterns": [
        {
          "name": "punctuation.terminator.tulam",
          "match": ";"
        },
        {
          "name": "punctuation.separator.tulam",
          "match": ","
        },
        {
          "name": "punctuation.type-annotation.tulam",
          "match": ":"
        },
        {
          "name": "punctuation.section.group.begin.tulam",
          "match": "[({\\[]"
        },
        {
          "name": "punctuation.section.group.end.tulam",
          "match": "[)}\\]]"
        }
      ]
    }
  }
}
