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:
var x = 5This line does three things at once:
- Creates a variable named
x. - Infers the type from the value —
5is an integer, soxhas typeint. No type annotation needed. - Assigns the value
5tox.
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:
var count = 0
count = count + 1A Note on
letvsvar:You may notice that this chapter only uses
var. That's intentional. Auto has two keywords for declaring variables:varfor mutable variables andletfor immutable ones. We'll introduceletin Chapter 6 when we discuss immutability. For now, everything isvar.
Let's see variable declarations in action with different types.
Notice how each target language handles this differently:
- Rust uses
let mutfor 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.
var age = 25 // int — no decimal point
var temperature = 36.6 // float — has a decimal pointIf 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:
| Operator | Meaning | Example | Result |
|---|---|---|---|
+ | Addition | 5 + 3 | 8 |
- | Subtraction | 10 - 4 | 6 |
* | Multiplication | 6 * 7 | 42 |
/ | Division | 15 / 4 | 3 |
% | Remainder | 17 % 5 | 2 |
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:
var precise = 15.0 / 4 // 3.75Listing 2-2 shows all the arithmetic operators in action.
A few things worth noting in the transpiled output:
- Python uses
//for integer division, not/. Thea2ptranspiler 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:
var greeting = "Hello, world!"Strings in Auto are immutable once created. You can build new strings by combining existing ones with the + operator:
var first = "Hello"
var second = "Auto"
var combined = first + ", " + second + "!"Auto also supports multiline strings — just include a literal line break inside the quotes:
var multi = "This is a
multiline string"The newline character is preserved in the string's value.
Look at how each target handles string concatenation:
- Rust uses
format!()for efficient string building — the transpiler avoids repeated+operations onString. - 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.
var is_active = true
var is_finished = falseAuto provides three logical operators for working with booleans:
| Operator | Meaning | Example | Result |
|---|---|---|---|
&& | AND | true && false | false |
| ` | ` | OR | |
! | NOT | !true | false |
These operators work exactly as you'd expect from logic:
&&istrueonly when both sides aretrue.||istruewhen at least one side istrue.!flips the value:!truebecomesfalse,!falsebecomestrue.
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:
| Operator | Meaning | Example | Result |
|---|---|---|---|
== | Equal to | 10 == 20 | false |
!= | Not equal to | 10 != 20 | true |
< | Less than | 10 < 20 | true |
> | Greater than | 10 > 20 | false |
<= | Less than or equal | 10 <= 10 | true |
>= | Greater than or equal | 10 >= 20 | false |
These operators work on numbers, strings, and booleans. Comparing strings checks lexicographic (dictionary) order.
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.
var x = 5
var x = x + 1 // x is now 6This 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:
var x = 5 // x is an int
var x = "now a string" // x is now a stringThis 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.
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
varand are mutable. The compiler infers the type — you don't need annotations. - Numbers come in two flavors:
intfor integers andfloatfor 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
trueorfalse. 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
varcreates 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.