Skip to content

Chapter 1: Getting Started

Why Wyn?

Before we write code, let's be clear about what you're learning.

Most programmers use multiple languages daily. Python for scripts. JavaScript for web. Go for services. C++ for performance. Each switch costs mental energy-different syntax, different tooling, different mental models.

Wyn eliminates this. It's designed from the ground up to be:

  • Simple enough for quick scripts and prototypes
  • Fast enough for systems programming and performance-critical code
  • Portable enough to run natively on any platform without a runtime
  • Powerful enough to handle complex applications with ease

You're not learning a "scripting language" or a "systems language." You're learning the language. One tool for everything.

Your First Program

Let's prove it. Create a file called hello.wyn:

wyn
fn main() -> int {
    print("Hello, World!")
    return 0
}

Run it:

bash
wyn run hello.wyn

You should see Hello, World! printed to your terminal. If you do, congratulations-you've just written and run your first Wyn program.

If you don't, we need to install Wyn first.

Installing Wyn

macOS / Linux:

bash
curl -fsSL https://wynlang.com/install.sh | sh

Windows:

powershell
irm https://wynlang.com/install.ps1 | iex

From source:

bash
git clone https://github.com/wynlang/wyn.git
cd wyn && make && ./wyn install

Verify it works:

bash
wyn --version
# Should output: Wyn v1.19.1

Wyn ships with a bundled TCC compiler - no external dependencies needed. No GCC, no LLVM, no runtime to install.

Wyn files use the .wyn extension. You can also use .🐉 - both work everywhere.

What Just Happened?

Let's break down that program:

wyn
fn main() -> int {

Every Wyn program starts with a main function. This is where execution begins. The -> int means it returns an integer-by convention, 0 means success and anything else means an error occurred.

wyn
    print("Hello, World!")

This calls the built-in print function. Notice there's no semicolon-Wyn doesn't require them. The newline is enough.

wyn
    return 0
}

We return 0 to indicate success. The closing brace ends the function.

Both of those are optional. You can drop the -> int and the return 0 entirely:

wyn
fn main() {
    print("Hello, World!")
}

This still compiles and runs, and still exits with status 0. Wyn only makes you write what you actually need. You can return a value from main too, if you want your program's exit code to mean something-return 2 exits with status 2, no -> int required. We'll write it out explicitly through most of this book because it documents intent, but don't feel obligated to type it every time.

A More Interesting Example

Hello World is traditional, but it doesn't show you much. Let's write something that demonstrates what makes Wyn different:

wyn
fn main() -> int {
    var message = "  Hello, Wyn!  "
    
    var cleaned = message.trim()
    var shouting = cleaned.upper()
    var length = shouting.len()
    
    print(shouting)
    print("\nLength: ")
    print(length)
    
    return 0
}

Run this and you'll see:

HELLO, WYN!
Length: 11

Here's what's interesting: trim(), upper(), and len() are all methods on the string. You're not passing the string to functions-you're calling methods on the string object.

This might seem like a small difference, but it changes how you think about code. Instead of remembering which function operates on which type, you just type the variable name, hit ., and your editor shows you everything you can do with it.

Method Chaining

Because methods return new values, you can chain them:

wyn
fn main() -> int {
    var result = "  Hello, Wyn!  ".trim().upper()
    print(result)  // HELLO, WYN!
    return 0
}

This reads left-to-right: take the string, trim it, then uppercase it. No nested function calls, no temporary variables unless you want them.

Immutability by Default

Notice that trim() doesn't modify the original string-it returns a new one:

wyn
fn main() -> int {
    var original = "  hello  "
    var trimmed = original.trim()
    
    print(original)  // "  hello  " - unchanged
    print(trimmed)   // "hello" - new string
    
    return 0
}

This is deliberate. Immutability prevents entire classes of bugs. When you see a variable, you know its value won't change unless you explicitly reassign it.

How Compilation Works

When you run wyn run hello.wyn, several things happen:

  1. Lexical analysis: The source code is broken into tokens (keywords, identifiers, operators)
  2. Parsing: Tokens are organized into an Abstract Syntax Tree (AST)
  3. Type checking: The compiler verifies types are used correctly
  4. Code generation: C source code is generated
  5. Compilation: The bundled TCC compiler produces a native binary (~260ms)
  6. Execution: The binary runs immediately

For release builds (wyn run hello.wyn --release), the system C compiler is used with -O2 optimization instead of TCC.

The result is a standalone executable. No virtual machine, no interpreter, no runtime dependencies. This is why Wyn programs are fast - they're running directly on the CPU.

Common Mistakes

Forgetting the main Function

wyn
fn greet() -> int {
    print("Hello!")
    return 0
}

This compiles, but nothing happens when you run it. Execution starts at main-without one, your functions are never called. Every program needs a main function.

Type Mismatches

wyn
fn main() -> int {
    return "hello"  // Wrong type
}

Error: Return type mismatch. Expected int, got string

Wyn is statically typed. The compiler catches these errors before your code runs.

Using Undefined Variables

wyn
fn main() -> int {
    print(message)  // What's message?
    return 0
}

Error: Undefined variable 'message'

Variables must be declared before use. This prevents typos from becoming runtime bugs.

Understanding Error Messages

Wyn's error messages try to be helpful. When you see an error:

  1. Read the message carefully-it usually tells you exactly what's wrong
  2. Check the line number-errors are reported where they're detected, which might be after where they occurred
  3. Look at the type-many errors are type mismatches

Example:

Error at line 5: Type mismatch
  Expected: int
  Got: string
  
  var x: int = "hello"
               ^^^^^^^

The caret points to the problem. The message explains what went wrong.

Your Development Environment

You can write Wyn in any text editor, but some make life easier:

VS Code: Install the Wyn extension for syntax highlighting and error checking.

Vim/Neovim: Syntax files are in the repository.

Any editor: As long as it can save plain text, you're fine.

For now, don't worry about fancy tooling. A text editor and a terminal are enough.

What's Next

You've installed Wyn, written your first programs, and understand the basics of compilation. You've seen that Wyn code is object-oriented, that methods are called on values, and that immutability is the default.

In the next chapter, we'll dive deeper into variables and types. You'll learn about Wyn's type system, how type inference works, and what types are available.

But first, try the exercises. They're designed to reinforce what you've learned and catch common misconceptions.

Exercises

Don't skip these. Seriously. Reading about programming isn't the same as programming.

  1. Modify Hello World to print your name instead of "World".

  2. Chain methods: Create a string with leading/trailing spaces, trim it, convert to uppercase, and print the length. Do it all in one expression.

  3. Experiment with methods: Try lower(), reverse(), contains() on strings. See what they do.

  4. Break something: Delete the closing brace of main. What error do you get? Why?

  5. Type mismatch: Try to return a string from main. Read the error message carefully.

  6. Multiple operations: Create a string, get its length, convert the length to a string, and print it. You'll need to look up how to convert integers to strings (hint: it's a method on integers).

Solutions are at the end of the book, but try them yourself first. The mistakes you make now are lessons you won't forget later.


Next: Chapter 2: Variables and Types

Try It Yourself

Install Wyn and run this example:

bash
curl -sSL wynlang.com/install.sh | sh
wyn init hello && cd hello
wyn run src/main.wyn

MIT License - v1.19.1