Skip to content
📖 The Auto Programming LanguageBook contents

Variables and Operators ​

Now that you've gotten your feet wet with "Hello, world!", it's time to learn the building blocks that every program needs: variables and operators. In this chapter, we'll cover:

  • Declaring variables with var
  • Working with numbers — integers and floats
  • String literals and concatenation
  • Boolean values and logical operators
  • Comparison operators
  • Shadowing — reusing variable names

var — Mutable Variables ​

Variables are how you give names to values so you can use them later. In Auto, you declare a variable using the var keyword:

auto
var x = 5

This line does three things at once:

  1. Creates a variable named x.
  2. Infers the type from the value — 5 is an integer, so x has type int. No type annotation needed.
  3. Assigns the value 5 to x.

You don't write the type yourself. Auto's compiler figures it out. This is called type inference, and it's one of the things that makes Auto feel lightweight while still being type-safe.

All variables declared with var are mutable — you can change their value later:

auto
var count = 0
count = count + 1

A Note on let vs var:

You may notice that this chapter only uses var. That's intentional. Auto has two keywords for declaring variables: var for mutable variables and let for immutable ones. We'll introduce let in Chapter 6 when we discuss immutability. For now, everything is var.

Let's see variable declarations in action with different types.

Declaring variables with `var`

Notice how each target language handles this differently:

  • Rust uses let mut for mutable variables and adds explicit type annotations (i64, String, f64).
  • Python simply writes x = 5. No keyword, no types. The most concise.
  • C requires both the type (long long, const char*, double) and semicolons.
  • TypeScript splits the difference: let x: number = 5. Types are optional in TypeScript but the transpiler includes them.

In every language, the meaning is the same: create a variable, give it a name, store a value.

Numbers — Integers and Floats ​

Auto has two numeric types: int for integers and float for floating-point numbers. The compiler decides which one based on the literal value.

auto
var age = 25          // int — no decimal point
var temperature = 36.6  // float — has a decimal point

If a number has a decimal point, it's a float. If it doesn't, it's an int. Simple as that.

Arithmetic Operators ​

Auto supports the standard arithmetic operators you'd expect:

OperatorMeaningExampleResult
+Addition5 + 38
-Subtraction10 - 46
*Multiplication6 * 742
/Division15 / 43
%Remainder17 % 52

Note that division of two integers gives an integer result — 15 / 4 is 3, not 3.75. The fractional part is discarded. If you need a floating-point result, at least one operand must be a float:

auto
var precise = 15.0 / 4   // 3.75

Listing 2-2 shows all the arithmetic operators in action.

Arithmetic with integers and floats

A few things worth noting in the transpiled output:

  • Python uses // for integer division, not /. The a2p transpiler converts Auto's / to Python's // when both operands are integers.
  • TypeScript wraps division in Math.trunc() to ensure integer truncation, since JavaScript's / always produces a float.
  • C and Rust naturally perform integer division when both operands are integers, so no special handling is needed.

Strings — Literals and Concatenation ​

A string is a sequence of characters. In Auto, you write string literals inside double quotes:

auto
var greeting = "Hello, world!"

Strings in Auto are immutable once created. You can build new strings by combining existing ones with the + operator:

auto
var first = "Hello"
var second = "Auto"
var combined = first + ", " + second + "!"

Auto also supports multiline strings — just include a literal line break inside the quotes:

auto
var multi = "This is a
multiline string"

The newline character is preserved in the string's value.

String literals and concatenation

Look at how each target handles string concatenation:

  • Rust uses format!() for efficient string building — the transpiler avoids repeated + operations on String.
  • Python supports + for strings directly, and uses triple quotes for multiline strings.
  • C uses snprintf() into a buffer — the transpiler calculates the required size at compile time.
  • TypeScript uses template literals (backticks) for multiline strings and + for concatenation.

Booleans ​

A boolean has exactly two possible values: true and false. Booleans are the foundation of all decision-making in programs.

auto
var is_active = true
var is_finished = false

Auto provides three logical operators for working with booleans:

OperatorMeaningExampleResult
&&ANDtrue && falsefalse
``OR
!NOT!truefalse

These operators work exactly as you'd expect from logic:

  • && is true only when both sides are true.
  • || is true when at least one side is true.
  • ! flips the value: !true becomes false, !false becomes true.
Boolean values and logical operators

The Python transpiler translates Auto's symbolic operators into Python's keyword equivalents: && becomes and, || becomes or, and ! becomes not. Python also uses True and False (capitalized) instead of true and false.

C has booleans via <stdbool.h>, but printf doesn't have a format specifier for them. The transpiler uses a ternary operator to print "true" or "false" as strings.

Comparison Operators ​

Comparison operators compare two values and return a boolean. Auto supports six comparison operators:

OperatorMeaningExampleResult
==Equal to10 == 20false
!=Not equal to10 != 20true
<Less than10 < 20true
>Greater than10 > 20false
<=Less than or equal10 <= 10true
>=Greater than or equal10 >= 20false

These operators work on numbers, strings, and booleans. Comparing strings checks lexicographic (dictionary) order.

Comparison operators

Notice that the TypeScript transpiler converts == to === and != to !==. TypeScript's strict equality operators avoid the type-coercion pitfalls of JavaScript's == and !=, so the transpiler always uses the strict versions.

Shadowing ​

Auto lets you declare a new variable with the same name as a previous one in the same scope. This is called shadowing. The new variable shadows the old one — from that point on, the name refers to the new variable.

auto
var x = 5
var x = x + 1    // x is now 6

This is not the same as assignment. You are not changing the old variable — you are creating a brand-new variable that happens to share the same name. Because it's a new variable, you can even change the type:

auto
var x = 5          // x is an int
var x = "now a string"  // x is now a string

This type-changing shadow is perfectly valid in Auto. It's also valid in Python and Rust (with let). C and TypeScript need workarounds, which the transpiler provides automatically.

Shadowing a variable with the same name

The C output is the most dramatic. Because C is statically typed and doesn't support shadowing with a different type, the a2c transpiler generates a tagged union — a struct that carries both a type tag and a value. This is a real technique used in real C programs, and the transpiler applies it automatically so you don't have to think about it.

The TypeScript output uses a union type (number | string) to represent the variable that can hold either type.

Summary ​

In this chapter, you learned the fundamentals of working with data in Auto:

  • Variables are declared with var and are mutable. The compiler infers the type — you don't need annotations.
  • Numbers come in two flavors: int for integers and float for decimals. Arithmetic operators (+, -, *, /, %) work as expected.
  • Strings use double quotes and the + operator for concatenation. Multiline strings are written with literal line breaks.
  • Booleans are true or false. Logical operators &&, ||, and ! combine boolean values.
  • Comparison operators (==, !=, <, >, <=, >=) compare values and return booleans.
  • Shadowing lets you reuse a variable name, even with a different type. Each var creates a new variable.

You now have the vocabulary to name and transform data. In the next chapter, we'll put that vocabulary to work by writing functions — the reusable building blocks of every program.

Released under the MIT License.