Home Explore Blog CI



nushell

1st chunk of `book/how_nushell_code_gets_run.md`
7022f5be0167181736ad985715c0c66646691fe48d1756a90000000100001008
# How Nushell Code Gets Run

In [Thinking in Nu](./thinking_in_nu.md#think-of-nushell-as-a-compiled-language), we encouraged you to _"Think of Nushell as a compiled language"_ due to the way in which Nushell code is processed. We also covered several code examples that won't work in Nushell due that process.

The underlying reason for this is a strict separation of the **_parsing and evaluation_** stages that **_disallows `eval`-like functionality_**. In this section, we'll explain in detail what this means, why we're doing it, and what the implications are. The explanation aims to be as simple as possible, but it might help if you've programmed in another language before.

[[toc]]

## Interpreted vs. Compiled Languages

### Interpreted Languages

Nushell, Python, and Bash (and many others) are _"interpreted"_ languages.

Let's start with a simple "Hello, World!" Nushell program:

```nu
# hello.nu

print "Hello, World!"
```

Of course, this runs as expected using `nu hello.nu`. A similar program written in Python or Bash would look (and behave) nearly the same.

In _"interpreted languages"_ code usually gets handled something like this:

```text
Source Code → Interpreter → Result
```

Nushell follows this pattern, and its "Interpreter" is split into two parts:

1. `Source Code → Parser → Intermediate Representation (IR)`
2. `IR → Evaluation Engine → Result`

First, the source code is analyzed by the Parser and converted into an intermediate representation (IR), which in Nushell's case is just a collection of data structures. Then, these data structures are passed to the Engine for evaluation and output of the results.

This, as well, is common in interpreted languages. For example, Python's source code is typically [converted into bytecode](https://github.com/python/cpython/blob/main/InternalDocs/interpreter.md) before evaluation.

### Compiled Languages

On the other side are languages that are typically "compiled", such as C, C++, or Rust. For example, here's a simple _"Hello, World!"_ in Rust:

```rust
// main.rs

fn main() {
    println!("Hello, World!");
}
```

To "run" this code, it must be:

1. Compiled into [machine code instructions](https://en.wikipedia.org/wiki/Machine_code)
2. The compilation results stored as a binary file on the disk

The first two steps are handled with `rustc main.rs`.

3. Then, to produce a result, you need to run the binary (`./main`), which passes the instructions to the CPU

So:

1. `Source Code ⇒ Compiler ⇒ Machine Code`
2. `Machine Code ⇒ CPU ⇒ Result`

::: important
You can see that the compile-run sequence is not much different from the parse-evaluate sequence of an interpreter. You begin with source code, parse (or compile) it into some state (e.g., bytecode, IR, machine code), then evaluate (or run) the IR to get a result. You could think of machine code as just another type of IR and the CPU as its interpreter.

One big difference, however, between interpreted and compiled languages is that interpreted languages typically implement an _`eval` function_ while compiled languages do not. What does this mean?
:::

## Dynamic vs. Static Languages

::: tip Terminology
In general, the difference between a dynamic and static language is how much of the source code is resolved during Compilation (or Parsing) vs. Evaluation/Runtime:

- _"Static"_ languages perform more code analysis (e.g., type-checking, [data ownership](https://doc.rust-lang.org/stable/book/ch04-00-understanding-ownership.html)) during Compilation/Parsing.

- _"Dynamic"_ languages perform more code analysis, including `eval` of additional code, during Evaluation/Runtime.

For the purposes of this discussion, the primary difference between a static and dynamic language is whether or not it has an `eval` function.

:::

### Eval Function

Most dynamic, interpreted languages have an `eval` function. For example, [Python `eval`](https://docs.python.org/3/library/functions.html#eval) (also, [Python `exec`](https://docs.python.org/3/library/functions.html#exec)) or [Bash `eval`](https://linux.die.net/man/1/bash).

Title: How Nushell Code Gets Run: Interpreted vs. Compiled Languages and Dynamic vs. Static Languages
Summary
This section explains how Nushell code is processed, emphasizing the separation of parsing and evaluation stages, which disallows `eval`-like functionality. It contrasts interpreted languages like Nushell, Python, and Bash with compiled languages like C, C++, and Rust, highlighting the differences in their execution models. It also discusses dynamic vs static languages, with emphasis on the `eval` function in dynamic interpreted languages.