Carina

Types & Values

Primitive types, collection types, resource references, enum identifiers, and string interpolation in the Carina DSL.

The Carina DSL is a statically-aware language with the following value types.

Primitive Types

String

Strings can be enclosed in either single or double quotes. The two forms have different semantics, and the recommended style is to pick the form based on whether interpolation is needed.

Single-Quoted Strings (Literal)

Single quotes produce a literal string. ${...} inside single quotes is not interpreted as interpolation — it is kept verbatim.

let name = 'my-vpc'
let region = 'ap-northeast-1'
let literal = 'price is ${amount}'   # the six characters ${amount} stay as-is

The only escape sequences recognized inside single quotes are \' (single quote) and \\ (backslash).

Double-Quoted Strings (Interpolation)

Double quotes support ${...} interpolation and the full set of escape sequences. Use them whenever you need to embed an expression in a string.

let env  = 'prod'
let name = "vpc-${env}"           # => 'vpc-prod'
let cidr = "${base_cidr}"         # => value of base_cidr
let tag  = "${env}-${service}"    # => 'prod-web'

Any expression can appear inside ${}, including function calls:

let tag = "vpc-${join('-', ['prod', 'web'])}"
  • Use single quotes for literal strings that do not need interpolation (the common case).
  • Use double quotes only when you need ${...} interpolation or an escape sequence that is not supported in single quotes.

Both forms are always valid — this is a style guideline, not a correctness requirement. A literal written with double quotes (e.g. "ap-northeast-1") is accepted and behaves identically to the single-quoted form.

Escape Sequences

Double-quoted strings support the following escape sequences:

SequenceMeaning
\"Double quote
\\Backslash
\nNewline
\rCarriage return
\tTab
\$Literal dollar sign (prevents interpolation)

Single-quoted strings recognize only \' and \\.

Int

Integer values, optionally negative:

let port = 443
let offset = -1
let count = 0

Float

Floating-point values with a decimal point:

let ratio = 0.5
let threshold = -3.14

Bool

Boolean values true or false:

let enabled = true
let public = false

Collection Types

List

Ordered sequences enclosed in square brackets:

let zones = ['ap-northeast-1a', 'ap-northeast-1c', 'ap-northeast-1d']
let ports = [80, 443, 8080]
let empty = []

Lists can contain mixed types and a trailing comma is allowed:

let mixed = [
  'hello',
  42,
  true,
]

Map

Key-value collections enclosed in curly braces. Keys are identifiers (unquoted), values are expressions:

let config = {
  dev = '10.0.0.0/16'
  stg = '10.1.0.0/16'
}

Maps are also used for resource tags and nested configuration:

awscc.ec2.Vpc {
  cidr_block = '10.0.0.0/16'

  tags = {
    Name        = 'main'
    Environment = 'prod'
  }
}

Namespaced Identifiers

Dot-separated identifiers are used for resource types and enum values. They are not strings and are not quoted.

Resource Types

Resource types use the format provider.service.resource_type:

awscc.ec2.Vpc { ... }
awscc.ec2.Subnet { ... }
awscc.s3.Bucket { ... }

Enum Identifiers

Enum values are namespaced identifiers that represent predefined constants:

# Provider-level enums
awscc.Region.ap_northeast_1
aws.Region.us_east_1

# Resource-level enums
awscc.ec2.Vpc.InstanceTenancy.default

Enum identifiers are used directly as attribute values without quotes:

provider awscc {
  region = awscc.Region.ap_northeast_1
}

awscc.ec2.Vpc {
  instance_tenancy = awscc.ec2.Vpc.InstanceTenancy.default
}

Resource References

When a resource is bound with let, its attributes can be accessed using dot notation:

let vpc = awscc.ec2.Vpc {
  cidr_block = '10.0.0.0/16'
}

let subnet = awscc.ec2.Subnet {
  vpc_id     = vpc.vpc_id      # Reference vpc's vpc_id attribute
  cidr_block = '10.0.1.0/24'
}

Chained Access

Dot notation can be chained for nested access:

let sg = network.security_group.group_id

Index Access

Use square brackets to access list elements or map values:

let first_zone = zones[0]
let dev_cidr = config['dev']

Index and field access can be combined:

let subnet_id = subnets[0].subnet_id

Type Expressions

Type expressions are used in arguments and attributes blocks in modules, and in function parameters.

Simple Types

arguments {
  name      : String
  count     : Int
  ratio     : Float
  enabled   : Bool
  cidr_block: Ipv4Cidr
  role_arn  : Arn
}

Generic Types

list and map accept a type parameter:

arguments {
  subnet_ids  : list(String)
  cidr_blocks : list(Ipv4Cidr)
  tags        : map(String)
}

Resource Type References

Resource types can be used as type expressions to indicate a reference:

attributes {
  vpc_id   : awscc.ec2.Vpc = vpc.vpc_id
  subnet_id: awscc.ec2.Subnet = subnet.subnet_id
}

Null

The null literal represents the absence of a value. It can only appear in validate expressions such as require statements and argument validation:

require value != null, 'Value must not be null'