Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Runnable code block example #241

Merged
merged 3 commits into from
Sep 25, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 35 additions & 12 deletions docs/clvm.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ title: CLVM
slug: /clvm
---

import Runnable from '../src/components/Runnable.tsx';
import Program from 'clvm-lib';

Chialisp is compiled to bytecode, which is executed on the Chialisp Virtual Machine. CLVM is as minimal as possible, and doesn't have direct support for language constructs such as functions, constants, and modules.

This is all implemented by the Chialisp compiler. Although many of the operators are derived from CLVM, many things about Chialisp deviate from the bytecode it compiles to.
Expand All @@ -16,18 +19,26 @@ The core language syntax of CLVM is the same as Chialisp. However, it's a much m

In Chialisp, you can write an atom directly like this:

<Runnable flavor='chialisp'>

```chialisp
"hello"
```

</Runnable>

However, CLVM will treat that as a call to access the program's environment (explained below).

As a result, all atoms that are intended to be treated as a value must be quoted like this:

<Runnable flavor='clvm'>

```chialisp
(q . "hello")
```

</Runnable>

If you forget to do this, you will end up with either an unexpected value, or a path into atom error.

## Program Evaluation
Expand All @@ -38,10 +49,14 @@ A program is represented as a binary tree. The root of the tree is the least nes

In the following example, the outer parentheses represent the cons pair that is the root of the tree:

<Runnable flavor='clvm'>

```chialisp
(+ (q . 1) (q . 2))
```

</Runnable>

Whenever a program is called, it always has an environment (which will be described in more detail later), which is a CLVM value. This value, which is usually a list, holds all of the arguments passed into the program. This is the second command-line argument to `brun`, with the default environment being nil.

If the program being evaluated is a cons pair, then all of the parameters (contained in the right slot of the cons pair) are evaluated. Next, an operator call is made and the result of that function call is returned. The value on the left is the operator that is being called, and the values on the right are its operands.
Expand All @@ -54,10 +69,14 @@ A CLVM program can be thought of as a binary tree.

Here is an example of an operator call:

<Runnable flavor='clvm'>

```chialisp
(+ (q . 1) (q . 2))
```

</Runnable>

The operator is the opcode `+`, which is built-in to the CLVM runtime.

Here is a graph of the program, as stored in memory:
Expand All @@ -74,10 +93,14 @@ Here is a graph of the program, as stored in memory:

After the first reduction, the program looks like this:

<Runnable flavor='chialisp'>

```chialisp
(+ 1 2)
```

</Runnable>

Here is a graph of the new program, as stored in memory:

```
Expand All @@ -92,10 +115,14 @@ Here is a graph of the new program, as stored in memory:

After the second reduction, and the `+` operator call, it results in the following value:

<Runnable flavor='chialisp'>

```chialisp
3
```

</Runnable>

## Environment

CLVM programs have an environment, which is the value that is used as input. This is also how constants are implemented within programs.
Expand Down Expand Up @@ -240,26 +267,22 @@ This behavior is how functions are implemented in the Chialisp compiler.

Here is a CLVM program that executes the program contained in the first environment value with its own environment, `(12)`:

```bash
brun '(a 2 (q . (12)))' '((* 2 (q . 2)))'
```

This should output the following result:
<Runnable flavor='clvm' input='((* 2 (q . 2)))'>

```chialisp
24
(a 2 (q . (12)))
```

Taking this further, we can make the program run a new program that only uses values from the original environment:
</Runnable>

```bash
brun '(a 2 1)' '((* 5 (q . 2)) 10)'
```
Taking this further, we can make the program run a new program that only uses values from the original environment:

This should output the following result:
<Runnable flavor='clvm' input='((* 5 (q . 2)) 10)'>

```chialisp
20
(a 2 1)
```

</Runnable>

We can use this technique to implement recursive functions.
6 changes: 6 additions & 0 deletions docs/costs.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ title: Costs
slug: /costs
---

import Runnable from '../src/components/Runnable.tsx';

Every operator has a cost associated with it. Additionally, there can be a separate cost dependent on the number of arguments or bytes used when calling it.

If you deploy your program as a puzzle on the Chia blockchain, it will terminate if it surpasses a cost of 11,000,000,000 (11 billion), and it can have higher fees associated with it based on the cost.
Expand Down Expand Up @@ -70,10 +72,14 @@ This is an example of how to calculate the cost of a simple CLVM program by hand

Refer to the following CLVM program:

<Runnable flavor='clvm'>

```chialisp
(concat (q . gu) (q . ide))
```

</Runnable>

The atoms `gu` and `ide` are quoted, so that they are interpreted as values rather than programs.

The `brun` command takes two arguments, a program and its environment. If no environment is specified on the command line (as is the case in this example), we use an empty environment, `()`.
Expand Down
10 changes: 10 additions & 0 deletions docs/debugging.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ title: Debugging
slug: /debugging
---

import Runnable from '../src/components/Runnable.tsx';

Debugging Chialisp at times can be frustrating. Due to the nature of how it handles data structures, programs will often continue on with incorrect values only to error out at a later spot that gives no clue to the initial breakage. For example, a variable typo will often result in the variable being evaluated as a string, and if that gets hashed into something it's impossible to tell.

However, there are some tricks you can use to more easily catch bugs in your code.
Expand All @@ -20,6 +22,8 @@ You can use the `x` operator to debug your programs. This allows you to print th

Here is an example of a program you may want to debug:

<Runnable flavor='chialisp' input='(hello)'>

```chialisp
(mod (something)
(defun some (something)
Expand All @@ -30,10 +34,14 @@ Here is an example of a program you may want to debug:
)
```

</Runnable>

This would throw an error if you try to use `sha256` on a list (because it's the solution to the program).

Here is how you would debug it by wrapping an expression in the `x` operator:

<Runnable flavor='chialisp' input='(hello)'>

```chialisp
(mod (something)
(defun some (something)
Expand All @@ -44,6 +52,8 @@ Here is how you would debug it by wrapping an expression in the `x` operator:
)
```

</Runnable>

As you can see, when it gets to that point, it would raise an error and print the value of `something` rather than continuing and crashing.

This is a very powerful tool when debugging programs in Chialisp.
Expand Down
50 changes: 40 additions & 10 deletions docs/examples.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ title: Examples
slug: /examples
---

import Runnable from '../src/components/Runnable.tsx';

This is a set of examples for various operators. If you want to see their documentation, checkout the [Operators page](/operators).

## Modules
Expand All @@ -12,6 +14,8 @@ This is a set of examples for various operators. If you want to see their docume

Compiles an entire program into a single executable expression. You can define other constants within it.

<Runnable flavor='chialisp' input='(42)'>

```chialisp
(mod (value)

Expand All @@ -20,6 +24,8 @@ Compiles an entire program into a single executable expression. You can define o
)
```

</Runnable>

### include

Includes all of the constants defined in a library file in the module.
Expand All @@ -43,66 +49,90 @@ cdv clsp retrieve sha256tree

Defines a function that can be called from anywhere within the module.

<Runnable flavor='chialisp'>

```chialisp
(mod ()
(defun square (number)
;; Returns the number squared.
(* number number)
)

(square 16) ; 256
(square 16)
)
```

</Runnable>

### defun-inline

Defines an inline function that can be called from anywhere within the module. It simply replaces the call with the code within (like an easier to write but limited macro).

<Runnable flavor='chialisp'>

```chialisp
(mod ()
(defun-inline double (number)
;; Returns twice the number.
(* number 2)
)

(double 9) ; 18
(double 9)
)
```

</Runnable>

### lambda

Compiles a block of code into a single executable expression. Useful for writing functions as arguments to other functions.

<Runnable flavor='chialisp' input='(3 2)'>

```chialisp
(lambda (n1 n2)
;; Returns the two added together.
(+ n1 n2)
)
```

</Runnable>

### defmacro, qq, unquote {#defmacro}

Defines a macro that can manually structure the source code it is replaced with. Allows for advanced compile time behavior.

<Runnable flavor='chialisp'>

```chialisp
(defmacro or ARGS
(if ARGS
(qq (if (unquote (f ARGS))
1
(unquote (c or (r ARGS)))
))
0)
(mod ()
(defmacro or ARGS
(if ARGS
(qq (if (unquote (f ARGS))
1
(unquote (c or (r ARGS)))
))
0)
)

(or () () 1)
)
```

</Runnable>

### defconstant

Defines a constant value that can be referenced by name.

<Runnable flavor='chialisp'>

```chialisp
(mod ()
(defconstant MAGIC_NUMBER 314159)
(defconstant MAGIC_NUMBER 314159) ; (0x04cb2f in hex)

MAGIC_NUMBER ; Replaced with the actual value.
)
```

</Runnable>
12 changes: 11 additions & 1 deletion docs/intro.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,30 @@ title: About Chialisp
slug: /
---

import Runnable from '../src/components/Runnable.tsx';

Chialisp is a pure and functional language with a focus on security and auditability. Chialisp is commonly used on the Chia blockchain to lock funds in smart coins until spent and released by their owner. This enables behavior similar to that of smart contracts.

Here is an example:

<Runnable flavor='chialisp'>

```chialisp
(mod ()
(defun square (number)
(* number number)
)

(square 5) ; 25
(square 5)
)
```

</Runnable>

:::tip
Many Chialisp code block examples on this site can be edited, and evaluated by clicking the play button in the top right. You can edit the program arguments at the top (if not present, click the keyboard button to add arguments).
:::

## Design Decisions

There are many reasons to choose [Lisp](<https://en.wikipedia.org/wiki/Lisp_(programming_language)>) as the basis for this language, even though it is over 60 years old.
Expand Down
14 changes: 12 additions & 2 deletions docs/operators.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ title: Operators
slug: /operators
---

import Runnable from '../src/components/Runnable.tsx';

This is a basic description of each operator. If you want tangible examples for how to use them, check out the [Examples page](/examples).

:::note
Expand Down Expand Up @@ -44,10 +46,14 @@ You should use `divmod` instead in situations where you need to divide negative

For example:

<Runnable flavor='chialisp'>

```chialisp
(f (divmod -6 3)) ; -2
(f (divmod -6 3))
```

</Runnable>

:::

## Comparison
Expand Down Expand Up @@ -78,10 +84,14 @@ Usually this is the intended behavior, but if it isn't, you can use the `i` oper

If you would like to replicate the lazy evaluation of the `if` operator in CLVM, you can wrap the `i` operator like this:

<Runnable flavor='clvm'>

```chialisp
(a (i A (q . B) (q . C)) 1)
(a (i (q . 1) (q q . 'abc') (q q . 'xyz')) 1)
```

</Runnable>

Essentially, this runs the branch the condition matches as a program (with the current environment). Depending on how much code is executed in each branch, this may be more cost effective than executing both branches.
:::

Expand Down
Loading
Loading