Chapter 3: Hello World -- Your First Neam Program #
"The beginning is the most important part of the work." -- Plato
Every programming language journey starts the same way: with a program that says hello. In this chapter, you will write, compile, and run your first Neam program. Along the way, you will learn how the Neam toolchain works -- from source code to bytecode to execution -- and pick up the fundamental building blocks you will use in every program you write.
By the end of this chapter, you will be able to:
- Create and save a
.neamsource file - Use the
emitstatement to produce output - Understand the main execution block
{ ... } - Compile source code into bytecode with
neamc - Run compiled bytecode with the
neamVM - Explore Neam interactively using
neam-cli - Write comments using all four comment styles
- Perform basic string operations
- Use f-strings to build strings with embedded expressions
- Write basic for-loops to iterate over lists and ranges
- Trace the complete compile-run cycle from source to output
3.1 Creating Your First .neam File #
Open your text editor of choice and create a new file called hello.neam. Type the
following program exactly as shown:
{
emit "Hello, World!";
}
Save the file. That is it -- three lines, and you have a complete Neam program.
Before diving into what each piece does, let us get it running so you can see the result immediately.
3.2 The Compile-Run Cycle #
Neam uses a two-step execution model. You do not run source code directly. Instead,
you first compile your .neam source file into a .neamb bytecode file, then you
execute that bytecode on the Neam virtual machine (VM).
This two-step model gives Neam several advantages:
- Faster execution. The VM runs pre-compiled bytecode, not raw text. The parser and compiler do their work once, up front.
- Early error detection. Syntax errors and some semantic errors are caught at compile time, before your program ever runs. This includes agent-specific checks like verifying that handoff targets exist and tool schemas are valid -- errors that Python frameworks can only discover at runtime.
- Portable bytecode. A
.neambfile can be distributed and run on any machine that has the Neam VM installed, without sharing your source code. - Minimal startup time. Loading pre-compiled bytecode takes approximately 9 milliseconds, compared to 2,800 milliseconds for importing a Python AI framework. This difference matters in serverless deployments where every cold start costs money.
Why Compilation Matters for AI Agents #
If you come from a Python background, you might wonder why a compiled step is necessary. After all, Python's interpreted model works well for most AI development. The answer becomes clear when you consider what happens in production.
An AI agent system is not just code -- it is a topology. Agents hand off to other agents. Tools have parameter schemas that must match function signatures. Knowledge bases must exist before agents reference them. Guardrails must be attached to the right agents. In Python, all of these connections are validated at runtime, which means the first time you discover a broken handoff might be when a customer triggers that particular path at 3 AM.
Neam's compiler validates the entire topology before a single line of code runs. If
agent Triage hands off to agent Billing, the compiler verifies that Billing
exists and accepts the right input. If a tool declares a query parameter of type
string, the compiler checks that the schema is well-formed. This is not just
convenience -- it is a fundamental safety property for production AI systems.
Comparing the Two Approaches #
Consider the difference for a simple agent program:
Python approach (interpreted):
Neam approach (compiled):
The compilation step adds a few milliseconds to your workflow but saves hours of debugging in production.
Compiling #
Open your terminal, navigate to the directory where you saved hello.neam, and run:
neamc hello.neam -o hello.neamb
If the compilation succeeds, you will see no output -- silence means success. A new
file called hello.neamb will appear in the same directory.
If you made a typo, the compiler will report an error with a line number. Fix the error in your source file and compile again.
Running #
Now execute the compiled bytecode:
neam hello.neamb
You should see:
Hello, World!
Congratulations -- you have just run your first Neam program.
3.3 The emit Statement #
The emit statement is Neam's primary output mechanism. It sends a value to the
output stream -- in a terminal, that means printing text to your screen.
emit "Hello, World!";
A few things to notice:
- The keyword is
emit, notprint. Neam usesemitbecause the language is designed for agentic AI systems where output is not always a terminal. An agent might emit a response to an API caller, a message queue, or a downstream agent. The word "emit" captures this broader idea. Neam also supportsprint()as a built-in function (print("Hello, World!");) for those who prefer familiar syntax, butemitis the idiomatic Neam style used throughout this book. - Strings use double quotes.
"Hello, World!"is a string literal enclosed in double quotes. - Statements end with a semicolon. Every statement in Neam must be terminated
with a
;. Forgetting the semicolon is the single most common beginner mistake.
You can emit any value, not just strings:
{
emit "A string";
emit 42;
emit 3.14;
emit true;
emit nil;
}
Expected output:
A string
42
3.14
true
nil
3.4 The Main Execution Block #
Every Neam program needs an entry point -- a place where execution begins. In Neam, this is the main execution block, written as a pair of curly braces:
{
// Your code goes here
}
The main block is the top-level { ... } in your file. When the VM loads your
bytecode, it begins executing the instructions inside this block, in order, from
top to bottom.
Think of the main block as the main() function in C or Java, except that Neam
uses a more concise syntax.
Important rules about the main block:
- Every program must have exactly one top-level
{ ... }block. - Functions are defined outside the main block (you will see this in Chapter 5).
- Statements inside the block execute sequentially.
Here is a program with multiple statements:
{
emit "Line 1: Starting the program";
emit "Line 2: Doing some work";
emit "Line 3: All done";
}
Expected output:
Line 1: Starting the program
Line 2: Doing some work
Line 3: All done
3.5 The REPL: Interactive Exploration with neam-cli #
Sometimes you want to try things out quickly without creating a file, compiling,
and running. For that, Neam provides an interactive Read-Eval-Print Loop (REPL)
through the neam-cli tool.
Starting the REPL #
neam-cli
You will see a prompt where you can type Neam expressions and statements:
Neam REPL v0.7.2
Type expressions or statements. Press Ctrl+D to exit.
neam> emit "Hello from the REPL!";
Hello from the REPL!
neam> emit 2 + 3;
5
neam> let name = "Neam";
neam> emit "Welcome to " + name;
Welcome to Neam
neam> emit f"Welcome to {name}!";
Welcome to Neam!
Running a File with neam-cli #
You can also use neam-cli to run a .neam source file directly, without
manually compiling first:
neam-cli hello.neam
This compiles and runs the file in one step -- convenient for development.
Watch Mode #
For rapid iteration during development, use watch mode:
neam-cli --watch hello.neam
In watch mode, neam-cli monitors your source file for changes and automatically
recompiles and reruns the program every time you save. This gives you an experience
similar to live-reloading in web development.
Experimenting with Types in the REPL #
The REPL is an excellent place to explore how Neam handles different value types:
neam> emit typeof(42);
number
neam> emit typeof("hello");
string
neam> emit typeof(true);
boolean
neam> emit typeof(nil);
nil
neam> emit typeof([1, 2, 3]);
list
neam> emit typeof({"key": "value"});
map
You can also test arithmetic, string operations, and even define functions:
neam> let x = 10;
neam> let y = 3;
neam> emit str(x * y + 2);
32
neam> emit "Neam".upper();
NEAM
neam> emit str(len("Hello, World!"));
13
The REPL maintains state across lines within a session. Variables you define on one line are available on subsequent lines. This makes it ideal for building up expressions step by step.
The Development Workflow #
In practice, most Neam development follows a cycle:
- Explore in the REPL to test ideas and understand behavior.
- Write your program in a
.neamfile. - Develop using
neam-cli --watchfor rapid iteration. - Build with
neamcwhen you are ready to deploy or distribute.
This workflow gives you the best of both worlds: the interactive exploration of an interpreted language with the safety and performance of a compiled one.
When to Use Each Tool #
| Tool | Use Case |
|---|---|
neamc + neam |
Production builds, CI/CD, distributing bytecode |
neam-cli file.neam |
Quick development runs |
neam-cli --watch |
Iterative development with auto-reload |
neam-cli (no args) |
Interactive exploration, testing snippets |
3.6 Understanding Bytecode: What .neamb Contains #
When you compile a .neam source file, the compiler produces a .neamb binary file.
This is not machine code (like a C compiler produces). It is bytecode -- a compact,
platform-independent representation of your program designed to be executed by the
Neam virtual machine.
The Compilation Pipeline #
Under the hood, neamc performs several stages:
- Lexing. The source text is broken into tokens: keywords (
emit), strings ("Hello"), symbols ({,},;), and so on. - Parsing. Tokens are assembled into an Abstract Syntax Tree (AST) -- a structured representation of your program's logic.
- Compilation. The AST is walked and translated into a sequence of bytecode instructions (opcodes) plus a constant pool.
Inside a .neamb File #
A .neamb file has a binary format with the following structure:
| Section | Description |
|---|---|
| Magic bytes | NEAM (4 bytes) -- identifies the file as Neam bytecode |
| Version | Format version number |
| Manifest | JSON metadata about the program |
| Constants | Pool of constant values (strings, numbers) used in the program |
| Code | Sequence of bytecode instructions (opcodes + operands) |
| Source map | Mapping from bytecode offsets to source line numbers |
For our hello.neam program, the bytecode would contain approximately:
- A constant entry for the string
"Hello, World!" - An
OP_CONSTinstruction to push that string onto the stack - An
OP_EMITinstruction to output the value on top of the stack
You do not need to understand bytecode to use Neam effectively, but knowing it exists helps you understand error messages, performance characteristics, and the overall architecture of the language.
3.7 Comments #
Comments are text in your source code that the compiler ignores. They exist purely for humans -- to explain what code does, to leave notes for your future self, or to temporarily disable a line of code.
Neam supports four comment styles:
Single-Line Comments: // #
// This is a single-line comment
emit "Hello"; // This comment is at the end of a line
Everything from // to the end of the line is ignored by the compiler.
Multi-Line Comments: / / #
/* This is a multi-line comment.
It can span multiple lines.
Very useful for longer explanations. */
emit "Hello";
Multi-line comments begin with /* and end with */. Everything between those
delimiters is ignored.
Documentation Comments: /// #
/// Computes the sum of two numbers.
/// Returns the result as a Number.
fun add(a, b) {
return a + b;
}
Triple-slash comments are documentation comments. They work like // but
signal that the comment is meant to document the function or declaration that
follows. Tools like neam-lsp (the language server) can use these to provide
hover documentation in your editor.
Block Documentation Comments: /* / #
/**
* Greets the user by name.
*
* Parameters:
* name - The name to greet
*
* Returns:
* A greeting string
*/
fun greet(name) {
return "Hello, " + name + "!";
}
Block documentation comments work like /* */ but are specifically for
multi-line documentation. The leading * on each line is a convention
for readability, not a requirement.
Comment Best Practices #
- Use
//for quick, short notes. - Use
/* */when you need to comment out a block of code temporarily. - Use
///or/** */to document functions, agents, and other declarations. - Write comments that explain why, not what. The code already says what it does; comments should explain the reasoning behind it.
3.8 String Basics and Concatenation #
Strings are sequences of characters enclosed in double quotes. You have already
seen them in emit "Hello, World!". Let us explore a few more things you can
do with strings.
String Literals #
{
emit "Hello, World!";
emit "Neam is an agentic AI language.";
emit ""; // An empty string
}
String Concatenation with + #
You can join two strings together using the + operator:
{
let greeting = "Hello";
let name = "Neam";
let message = greeting + ", " + name + "!";
emit message;
}
Expected output:
Hello, Neam!
The + operator, when used with strings, concatenates (joins) them end to end.
You can chain as many + operations as you need.
Mixing Strings and Numbers with str() #
In earlier versions of Neam (before v0.7.0), you could not directly concatenate a
string and a number. Starting with v0.7.0, type coercion rules allow
String + Number to work automatically. However, using str() remains good practice
for clarity, especially in complex expressions:
{
let x = 42;
emit "The answer is " + str(x);
}
Expected output:
The answer is 42
The str() function converts any value to its string representation:
{
emit str(42); // "42"
emit str(3.14); // "3.14"
emit str(true); // "true"
emit str(nil); // "nil"
}
You will learn more about strings and their methods in Chapter 4.
F-Strings: Formatted String Literals #
Starting with Neam v0.7.0, you can use f-strings (formatted string literals) as a
cleaner alternative to string concatenation. An f-string is a string prefixed with f
that allows you to embed expressions directly inside curly braces {...}:
{
let name = "Neam";
emit f"Hello, {name}!";
}
Expected output:
Hello, Neam!
The expression inside {...} is evaluated at runtime and its result is interpolated
into the string. This works with any expression -- variables, arithmetic, function
calls, and more:
{
// Arithmetic inside f-strings
emit f"Result: {1 + 2}"; // Result: 3
// Multiple interpolations in one string
let lang = "Neam";
let version = "0.7.2";
emit f"{lang} v{version}"; // Neam v0.7.2
// No need for str() -- f-strings handle conversion automatically
let year = 2026;
emit f"Year: {year}"; // Year: 2026
}
F-Strings vs. Concatenation #
Compare the two approaches for building the same string:
{
let greeting = "Hello";
let name = "Neam";
// Concatenation (what you already know)
emit greeting + ", " + name + "!";
// F-string (cleaner, easier to read)
emit f"{greeting}, {name}!";
}
Both produce the same output: Hello, Neam!. F-strings are generally preferred for
readability, especially when combining multiple values. You do not need str() inside
an f-string -- non-string values are converted automatically.
Here is the earlier str() example rewritten with an f-string:
{
let x = 42;
// With concatenation (requires str())
emit "The answer is " + str(x);
// With f-string (no str() needed)
emit f"The answer is {x}";
}
F-strings were introduced in v0.7.0 as part of the DataFlow release. They are fully supported and safe to use in production code.
Escape Sequences #
Neam strings support standard escape sequences for special characters:
| Escape | Meaning |
|---|---|
\" |
Double quote inside a string |
\\ |
Literal backslash |
\n |
Newline |
\t |
Tab |
{
emit "She said \"Hello!\"";
emit "First line\nSecond line";
emit "Column A\tColumn B";
}
String Length with len() #
The len() function returns the number of characters in a string:
{
let name = "Neam";
emit "Name: " + name;
emit "Length: " + str(len(name)); // Length: 4
let empty = "";
emit "Empty length: " + str(len(empty)); // Empty length: 0
}
len() also works on lists and maps, as you will see in Chapter 7.
3.9 Built-in Functions: A Preview #
Neam ships with over 80 built-in functions across 16 categories, all available in
every program without any imports. You have already seen two of them: str() and len(). Here
is a preview of the most commonly used ones. Each will be covered in detail in
the relevant chapter.
Core Utility Functions #
| Function | Purpose | Example | Result |
|---|---|---|---|
str(x) |
Convert any value to a string | str(42) |
"42" |
len(x) |
Length of string, list, or map | len("hello") |
5 |
typeof(x) |
Get the type name of a value | typeof(42) |
"number" |
input() |
Read a line from the user | let name = input(); |
User-typed text |
clock() |
Current time in seconds | let t = clock(); |
1706745600.0 |
Math Functions #
| Function | Purpose | Example | Result |
|---|---|---|---|
math_abs(x) |
Absolute value | math_abs(-7) |
7 |
math_floor(x) |
Round down | math_floor(3.7) |
3 |
math_ceil(x) |
Round up | math_ceil(3.2) |
4 |
math_round(x) |
Round to nearest | math_round(3.5) |
4 |
math_sqrt(x) |
Square root | math_sqrt(16) |
4 |
math_min(a, b) |
Smaller of two | math_min(3, 7) |
3 |
math_max(a, b) |
Larger of two | math_max(3, 7) |
7 |
math_random() |
Random number 0–1 | math_random() |
0.7281... |
String Methods #
| Method | Purpose | Example | Result |
|---|---|---|---|
.len() |
Length of the string | "hello".len() |
5 |
.contains(sub) |
Check for substring | "hello".contains("ell") |
true |
.upper() |
Uppercase | "hello".upper() |
"HELLO" |
.lower() |
Lowercase | "HELLO".lower() |
"hello" |
.reverse() |
Reverse the string | "hello".reverse() |
"olleh" |
.words() |
Split into word list | "hello world".words() |
["hello", "world"] |
.substring(s, e) |
Extract portion | "hello".substring(0, 3) |
"hel" |
Neam also supports string slicing with bracket syntax, which provides a concise
alternative to .substring():
{
let s = "Hello, World!";
emit s[0:5]; // "Hello"
emit s[7:12]; // "World"
}
String slicing uses the syntax str[start:end], where start is inclusive and end
is exclusive. You will explore slicing in more detail in Chapter 4.
You do not need to memorize these now. They are listed here so you know what is available as you work through the examples in this book. Appendix A provides the complete reference.
3.10 A First Look at For-Loops #
So far, every program you have written runs each statement exactly once, top to
bottom. But one of the most powerful ideas in programming is repetition -- doing
something multiple times without writing duplicate code. Neam provides the for
loop for exactly this purpose.
This is just a brief introduction. Chapter 6 covers control flow in full detail,
including if, while, for, and more. Here, you will see just enough to start
experimenting.
Iterating Over a List #
The simplest form of a for-loop iterates over each item in a list:
{
let colors = ["red", "green", "blue"];
for color in colors {
emit f"Color: {color}";
}
}
Expected output:
Color: red
Color: green
Color: blue
The loop variable color takes on each value from the list in order. The body
(the code between { and }) runs once for each item.
Counting with range() #
When you need to repeat something a specific number of times, use range():
{
for i in range(5) {
emit f"Count: {i}";
}
}
Expected output:
Count: 0
Count: 1
Count: 2
Count: 3
Count: 4
range(n) generates a sequence of numbers from 0 to n - 1. Combined with a
for-loop, it gives you a simple counting mechanism.
A Practical Example #
Here is a small program that combines variables, f-strings, and a for-loop:
{
let languages = ["Neam", "Python", "Rust"];
emit "Languages I am learning:";
for lang in languages {
emit f" - {lang}";
}
emit f"Total: {languages.len()}";
}
Expected output:
Languages I am learning:
- Neam
- Python
- Rust
Total: 3
Full control flow details -- including if/else, while loops,
break, continue, and loop expressions -- are covered in Chapter 6. For now,
the for loop gives you a tool for exploring lists and repeating actions.
3.11 Your First Complete Program #
Let us put everything together. Create a file called welcome.neam:
{
// Greet the user
emit "=================================";
emit " Welcome to the Neam Language! ";
emit "=================================";
emit "";
// Show some basic information
let language = "Neam";
let version = "0.7.2";
let purpose = "Agentic AI Programming";
emit "Language: " + language;
emit "Version: " + version;
emit "Purpose: " + purpose;
emit "";
// Demonstrate string concatenation
let full_description = language + " v" + version + " - " + purpose;
emit "Full description: " + full_description;
emit "";
// The same line using an f-string (cleaner alternative)
emit f"Full description: {language} v{version} - {purpose}";
emit "";
// Demonstrate numeric output
let year = 2026;
emit "Year: " + str(year);
emit f"Year: {year}"; // f-string version -- no str() needed
emit "";
/* Multi-line comment:
This program demonstrates:
- The emit statement
- String variables and concatenation
- The str() conversion function
- All four comment styles
*/
/// Final farewell message
emit "Happy coding!";
}
Step-by-Step Walkthrough #
- Compile the program:
neamc welcome.neam -o welcome.neamb
- Run the compiled bytecode:
neam welcome.neamb
- Expected output:
=================================
Welcome to the Neam Language!
=================================
Language: Neam
Version: 0.7.2
Purpose: Agentic AI Programming
Full description: Neam v0.7.2 - Agentic AI Programming
Full description: Neam v0.7.2 - Agentic AI Programming
Year: 2026
Year: 2026
Happy coding!
Walking Through the Execution #
Let us trace through the program line by line:
| Line | Code | What Happens |
|---|---|---|
| 7 | emit "====..."; |
Pushes the string constant, emits it |
| 8 | emit " Welcome..."; |
Same -- pushes and emits |
| 9 | emit "====..."; |
Same |
| 10 | emit ""; |
Emits an empty line |
| 13 | let language = "Neam"; |
Declares variable, stores "Neam" |
| 14 | let version = "0.6.5"; |
Declares variable, stores "0.6.5" |
| 15 | let purpose = "Agentic AI..."; |
Declares variable, stores the string |
| 17 | emit "Language: " + language; |
Concatenates and emits "Language: Neam" |
| 18 | emit "Version: " + version; |
Concatenates and emits "Version: 0.7.2" |
| 19 | emit "Purpose: " + purpose; |
Concatenates and emits the purpose |
| 22 | let full_description = ...; |
Concatenates all parts into one string |
| 23 | emit "Full description: " + ...; |
Emits the combined string |
| 26 | emit f"Full description: ..."; |
F-string version -- same output, cleaner syntax |
| 29 | let year = 2026; |
Stores the number 2026 |
| 30 | emit "Year: " + str(year); |
Converts 2026 to "2026", concatenates, emits |
| 31 | emit f"Year: {year}"; |
F-string version -- auto-converts the number |
| 41 | emit "Happy coding!"; |
Final emit |
Notice how execution flows top to bottom, one statement at a time. There are no branches, no function calls -- just sequential execution. (You got a taste of loops in Section 3.10, and you will explore the full set of control flow constructs in Chapter 6.)
3.12 A First Glimpse of Agents #
Everything you have learned so far -- emit, variables, strings, the compile-run
cycle -- applies to all Neam programs. But Neam was designed for one purpose above
all others: building AI agents. Let us take a brief look at what that looks like,
even though agents are not covered in detail until Chapter 10.
Here is a complete Neam program that creates an AI agent and asks it a question:
agent Assistant {
provider: "ollama",
model: "llama3",
temperature: 0.7,
system: "You are a helpful assistant. Answer concisely."
}
{
let question = "What is the capital of France?";
emit f"Question: {question}";
let answer = Assistant.ask(question);
emit f"Answer: {answer}";
}
Notice the structure:
- The agent declaration (
agent Assistant { ... }) appears outside the main block. It defines who the agent is: which LLM provider to use, which model, and what personality it has (via thesystemprompt). - The main block uses the agent by calling
Assistant.ask(question). This sends the question to the LLM and returns the response as a string. - Everything else --
let,emit, string concatenation -- is exactly what you already know.
This is the core insight of Neam's design: agents are language constructs, not
library calls. You do not import a framework, instantiate a client object, configure
an HTTP session, and parse a JSON response. You declare an agent and call .ask().
The language handles everything else.
Agents, tools, handoffs, knowledge bases, and multi-agent orchestration are explored in depth starting in Part III. For now, just remember: everything you learn about variables, functions, and control flow in Parts I and II applies directly when you start building agent systems.
3.13 From Python to Neam: A Conceptual Bridge #
If you are coming from Python -- and many readers will be, given Python's dominance in AI -- the following table maps familiar Python concepts to their Neam equivalents:
| Python | Neam | Key Difference |
|---|---|---|
print("hello") |
emit "hello"; |
emit is a keyword, not a function |
x = 42 |
let x = 42; |
Explicit let declaration required |
f"Hello, {name}" |
f"Hello, {name}" |
Same syntax! |
for x in items: |
for x in items { ... } |
Braces instead of colon + indent |
# comment |
// comment |
C-style comment syntax |
"""docstring""" |
/// docstring or /** ... */ |
Documentation comments |
if __name__ == "__main__": |
{ ... } |
Main block is the entry point |
python script.py |
neamc script.neam -o s.neamb && neam s.neamb |
Compile-then-run |
from langchain import ... |
agent Bot { ... } |
Agents are built into the language |
str(42) |
str(42) |
Same! |
len("hello") |
len("hello") |
Same! |
type(x).__name__ |
typeof(x) |
Simpler syntax |
Some things feel familiar. Others are deliberately different. The key mental shift is this: in Python, AI capabilities are things you import from a library. In Neam, AI capabilities are part of the language itself. You do not configure an LLM client -- you declare an agent. You do not write a tool wrapper function -- you declare a tool with a schema. You do not manage handoff logic in your own code -- you declare handoff targets on the agent.
This shift from "AI as a library" to "AI as a language construct" is the fundamental idea behind Neam.
3.14 Common Mistakes and How to Fix Them #
As you start writing Neam code, you will inevitably hit a few common errors. Here is a quick reference:
Missing Semicolon #
// WRONG
{
emit "Hello"
}
Error: Expected ';' after expression.
Fix: Add a semicolon after every statement.
// CORRECT
{
emit "Hello";
}
Missing Main Block #
// WRONG
emit "Hello";
Error: Unexpected token 'emit'.
Fix: Wrap your statements in a main execution block.
// CORRECT
{
emit "Hello";
}
Mismatched Quotes #
// WRONG
{
emit "Hello, World!;
}
Error: Unterminated string.
Fix: Make sure every opening " has a matching closing ".
Relying on Implicit String + Number Coercion #
// WORKS (since v0.7.0) but unclear intent
{
emit "Count: " + 42; // "Count: 42" -- auto-coerced
}
This compiles and runs correctly since v0.7.0 (String + Number auto-converts the
number to a string). However, explicit conversion with str() is recommended for
clarity, especially in complex expressions:
// RECOMMENDED -- intent is clear
{
emit "Count: " + str(42);
}
3.15 Chapter Summary #
In this chapter, you learned the foundational workflow for every Neam program:
- Source files use the
.neamextension. emitsends values to the output stream.- The main block
{ ... }is the program entry point. neamccompiles source to.neambbytecode -- catching topology and configuration errors before your code runs.neamruns compiled bytecode on the virtual machine.neam-cliprovides interactive exploration, direct execution, and watch mode.- Bytecode is a compact binary format with a
NEAMmagic header, constant pool, opcodes, and source map. - Comments come in four flavors:
//,/* */,///, and/** */. - Strings are concatenated with
+, and non-string values are converted withstr(). - F-strings (
f"Hello, {name}!") provide a cleaner way to build strings with embedded expressions, without needingstr()for type conversion. - For-loops (
for item in list { ... }andfor i in range(n) { ... }) let you repeat actions over collections and numeric ranges. - String methods like
.len(),.contains(),.reverse(), and.words()give you powerful text-processing tools, and string slicing (str[2:5]) provides concise substring extraction. - Escape sequences (
\",\\,\n,\t) allow special characters in strings. - Built-in functions like
str(),len(),typeof(), and themath_*family are available in every program without imports. - Agents are declared as language constructs, not library imports -- a fundamental difference from Python frameworks.
- The Python-to-Neam transition involves shifting from "AI as a library" to "AI as a language construct."
You now have all the tools you need to write, build, and run simple programs. In the next chapter, you will learn about variables, data types, and operators -- including Neam's full numeric types, booleans, lists, maps, and deeper coverage of f-strings and string methods -- the building blocks for expressing logic in Neam.
Exercises #
Exercise 3.1: Hello, You Write a program that emits your name in a greeting. For example, if your name is Alice, the output should be:
Hello, Alice!
Welcome to the world of Neam.
Exercise 3.2: The Compile Cycle
Create a file called info.neam that emits three lines: your name, your favorite
programming language (before Neam!), and the current year. Compile it with neamc
and run it with neam. Write down the exact commands you used.
Exercise 3.3: String Assembly Write a program that stores a first name and a last name in separate variables, then concatenates them into a full name with a space in between, and emits the result.
Exercise 3.4: Comment Styles
Write a program that uses all four comment styles (//, /* */, ///, /** */)
and emits at least two lines of output. Verify that none of the comments appear
in the output.
Exercise 3.5: Number to String
Write a program that stores the numbers 10, 20, and 30 in three variables,
computes their sum, and emits the result as part of a sentence like:
"The sum of 10, 20, and 30 is 60". You will need str().
Exercise 3.6: REPL Exploration
Start neam-cli in REPL mode (no arguments). Try the following and record the
output of each:
emit "Neam";emit 100 + 200;let x = "hello"; emit x;
Exercise 3.7: Bytecode Investigation
Compile a simple program and examine the .neamb file. Use a hex editor or the
command xxd hello.neamb | head -5 on macOS/Linux. Can you find the NEAM magic
bytes at the start of the file? What do the first four bytes look like in hex?
Exercise 3.8: F-String Rewrite
Take the program from Exercise 3.5 (the one that computes the sum of three numbers)
and rewrite all of the emit statements to use f-strings instead of concatenation
with str(). Verify that the output is identical.
Exercise 3.9: For-Loop Countdown
Write a program that uses a for loop with range(5) to emit a countdown from 5
to 1, followed by "Launch!". Hint: you can compute 5 - i inside the loop body.
Exercise 3.10: Error Practice Deliberately introduce each of the following errors, one at a time, and record the compiler's error message:
- Remove the semicolon from an
emitstatement. - Remove the closing
}of the main block. - Misspell
emitasemitt. - Use single quotes instead of double quotes for a string.
Understanding error messages now will save you significant debugging time later.