Skip to content

Commit d24b540

Browse files
authored
Merge pull request #5 from dylanjtuttle/variables
Add support for variables
2 parents 16d1606 + c87cf1d commit d24b540

File tree

14 files changed

+2321
-1371
lines changed

14 files changed

+2321
-1371
lines changed

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "jazzy"
3-
version = "0.1.0"
3+
version = "0.2.0"
44
edition = "2021"
55

66
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

README.md

Lines changed: 48 additions & 215 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
# jazzy
22
[![Rust](https://github.com/jazzylang/jazzy/actions/workflows/rust-ci.yml/badge.svg)](https://github.com/jazzylang/jazzy/actions/workflows/rust-ci.yml)
33

4-
A modern statically typed programming language
4+
![Jazzy REPL header ASCII art](https://i.imgur.com/aG5ROKh.png)
5+
6+
A better programming language (than my last one)
57

68
## Installation
79
To install jazzy, clone the repository:
@@ -29,9 +31,11 @@ $ jazzy -h
2931
```
3032

3133
## Features
32-
jazzy currently only supports expressions with number and boolean literals. To execute a jazzy expression, either type it out in the REPL and press enter:
33-
```bash
34-
=^..^= 1 + 1
34+
jazzy currently only supports collections of variable assignments and expressions on integers, floating-point numbers, and booleans. To execute a jazzy program, either type it out in the REPL one line at a time:
35+
36+
```
37+
=^..^= let x := 1;
38+
=^..^= x + 1
3539
2
3640
3741
=^..^=
@@ -42,237 +46,64 @@ or create a `.jzy` file with a single expression in it:
4246
1 < 3 and 99 >= 100
4347
```
4448
and invoke the compiler on it:
45-
```bash
46-
$ jazzy expression.jzy
47-
false
48-
```
49-
50-
### Operators
51-
#### Addition (`+`)
52-
| Left Operand | Right Operand | Output |
53-
|:------------:|:-------------:|:-------:|
54-
| Integer | Integer | Integer |
55-
| Float | Float | Float |
56-
57-
The addition operator takes two numbers and adds them together:
58-
```
59-
=^..^= 1 + 2
60-
3
61-
```
62-
63-
#### Subtraction (`-`)
64-
| Left Operand | Right Operand | Output |
65-
|:------------:|:-------------:|:-------:|
66-
| Integer | Integer | Integer |
67-
| Float | Float | Float |
68-
69-
The subtraction operator takes two numbers and subtracts them:
70-
```
71-
=^..^= 1 - 2
72-
-1
73-
```
74-
75-
#### Multiplication (`*`)
76-
| Left Operand | Right Operand | Output |
77-
|:------------:|:-------------:|:-------:|
78-
| Integer | Integer | Integer |
79-
| Float | Float | Float |
80-
81-
The multiplication operator takes two numbers and multiplies them together:
82-
```
83-
=^..^= 1 * 2
84-
2
85-
```
86-
87-
#### Division (`/`)
88-
| Left Operand | Right Operand | Output |
89-
|:------------:|:-------------:|:-------:|
90-
| Integer | Integer | Integer |
91-
| Float | Float | Float |
92-
93-
The division operator takes two numbers, divides them, and returns the quotient:
94-
```
95-
=^..^= 1 / 2
96-
0
97-
```
98-
NOTE: The output of the division operator depends on the type of its operands. If the operands are integers, the division operator performs integer division, which truncates the decimal quotient towards zero in order to return an integer. If the operands are floating-point numbers, the division operator does not alter the decimal quotient:
99-
```
100-
=^..^= 1.0 / 2.0
101-
0.5
102-
```
103-
104-
#### Remainder (`%`)
105-
| Left Operand | Right Operand | Output |
106-
|:------------:|:-------------:|:-------:|
107-
| Integer | Integer | Integer |
108-
| Float | Float | Float |
109-
110-
The remainder operator takes two numbers, divides them, and returns the remainder:
111-
```
112-
=^..^= 1 % 2
113-
1
114-
115-
=^..^= 4 % 2
116-
0
117-
```
118-
119-
#### Boolean AND (`and`)
120-
| Left Operand | Right Operand | Output |
121-
|:------------:|:-------------:|:-------:|
122-
| `bool` | `bool` | `bool` |
123-
124-
The boolean AND operator takes two booleans and produces a boolean representing whether both operands are `true`:
125-
| Left Operand | Right Operand | Output |
126-
|:------------:|:-------------:|:-------:|
127-
| `true` | `true` | `true` |
128-
| `true` | `false` | `false` |
129-
| `false` | `true` | `false` |
130-
| `false` | `false` | `false` |
131-
13249
```
133-
=^..^= true and true
134-
true
135-
```
136-
137-
#### Boolean OR (`or`)
138-
| Left Operand | Right Operand | Output |
139-
|:------------:|:-------------:|:-------:|
140-
| `bool` | `bool` | `bool` |
141-
142-
The boolean OR operator takes two booleans and produces a boolean representing whether either or both operands are `true`:
143-
| Left Operand | Right Operand | Output |
144-
|:------------:|:-------------:|:-------:|
145-
| `true` | `true` | `true` |
146-
| `true` | `false` | `true` |
147-
| `false` | `true` | `true` |
148-
| `false` | `false` | `false` |
149-
150-
```
151-
=^..^= true or false
152-
true
153-
```
154-
155-
#### Less Than (`<`)
156-
| Left Operand | Right Operand | Output |
157-
|:------------:|:-------------:|:-------:|
158-
| Integer | Integer | `bool` |
159-
| Float | Float | `bool` |
160-
161-
The less than operator takes two numbers and returns a boolean representing whether the first operand was less than the second:
162-
```
163-
=^..^= 1 < 2
164-
true
165-
166-
=^..^= 1 < 1
50+
$ jazzy expression.jzy
16751
false
16852
```
16953

170-
#### Less Than Or Equal To (`<=`)
171-
| Left Operand | Right Operand | Output |
172-
|:------------:|:-------------:|:-------:|
173-
| Integer | Integer | `bool` |
174-
| Float | Float | `bool` |
175-
176-
The less than or equal to operator takes two numbers and returns a boolean representing whether the first operand was less than or equal to the second:
177-
```
178-
=^..^= 1 <= 2
179-
true
180-
181-
=^..^= 1 <= 1
182-
true
54+
### Variables
55+
Variables can be declared as such:
18356
```
184-
185-
#### Greater Than (`>`)
186-
| Left Operand | Right Operand | Output |
187-
|:------------:|:-------------:|:-------:|
188-
| Integer | Integer | `bool` |
189-
| Float | Float | `bool` |
190-
191-
The greater than operator takes two numbers and returns a boolean representing whether the first operand was greater than the second:
192-
```
193-
=^..^= 2 > 1
194-
true
195-
196-
=^..^= 1 > 1
197-
false
57+
let x := 1;
19858
```
19959

200-
#### Greater Than Or Equal To (`>=`)
201-
| Left Operand | Right Operand | Output |
202-
|:------------:|:-------------:|:-------:|
203-
| Integer | Integer | `bool` |
204-
| Float | Float | `bool` |
205-
206-
The greater than or equal to operator takes two numbers and returns a boolean representing whether the first operand was greater than or equal to the second:
60+
The name of your variable is called an "identifier". The idiomatic style for jazzy variable identifiers is not snake case or camel case, like in a lot of common programming languages, but what many people call "kebab case":
20761
```
208-
=^..^= 2 >= 1
209-
true
210-
211-
=^..^= 1 >= 1
212-
true
62+
let some-variable := 3.14;
21363
```
21464

215-
#### Equal To (`==`)
216-
| Left Operand | Right Operand | Output |
217-
|:------------:|:-------------:|:-------:|
218-
| A | A | `bool` |
65+
An interesting consequence of this decision is that all of our binary operators (think +, -, etc) need to be surrounded by whitespace. Otherwise, we wouldn't know the difference between subtracting a variable `b` from a variable `a` and referencing a variable `a-b`!
21966

220-
The equal to operator takes two values **of the same type** and returns a boolean representing whether they have the same value:
221-
```
222-
=^..^= 1 == 1
223-
true
67+
Variables are immutable by default, meaning once you declare them, you cannot assign them a new value.
22468

225-
=^..^= 1 == 2
226-
false
227-
```
228-
229-
#### Not Equal To (`!=`)
230-
| Left Operand | Right Operand | Output |
231-
|:------------:|:-------------:|:-------:|
232-
| A | A | `bool` |
69+
![Multiple assignments to immutable variable error](https://i.imgur.com/VkelC0c.png)
23370

234-
The not equal to operator takes two values **of the same type** and returns a boolean representing whether they do not have the same value:
71+
To declare a variable as mutable, allowing you to assign it a new value later, simply add a `mut` after the `let`:
23572
```
236-
=^..^= 1 != 1
237-
false
238-
239-
=^..^= 1 != 2
240-
true
73+
let mut x := 1;
74+
x := 2;
24175
```
24276

243-
#### Unary Minus (`-`)
244-
| Operand | Output |
245-
|:-------:|:-------:|
246-
| Integer | Integer |
247-
| Float | Float |
248-
249-
The unary minus operator takes a single number and returns the negated value of that number:
77+
There are lots of situations where the jazzy compiler can figure out what the type of your variable is by itself. However, if you run into a situation where it can't (or you just want to explicitly set it for readability), you can add a type hint:
25078
```
251-
=^..^= -1
252-
-1
253-
254-
=^..^= --1
255-
1
79+
let x (i64) := 1;
25680
```
25781

258-
#### Unary Boolean NOT (`not`)
259-
| Operand | Output |
260-
|:-------:|:-------:|
261-
| `bool` | `bool` |
82+
### Types
26283

263-
The unary boolean NOT operator takes a single boolean and returns the negated value of that boolean:
264-
```
265-
=^..^= not true
266-
false
84+
Speaking of types, jazzy currently has three categories of them: booleans, integers, and floating-point numbers.
26785

268-
=^..^= not not true
269-
true
270-
```
86+
#### Booleans
87+
| Type | Description |
88+
|:----:|:-----------:|
89+
| bool | Boolean |
27190

272-
### Literals
273-
There are four kinds of literal values you can use in jazzy expressions:
91+
There are two boolean literals: `true` and `false`.
27492

27593
#### Integers
94+
| Type | Description |
95+
|:----:|:------------------------:|
96+
| i8 | Signed 8-bit integer |
97+
| i16 | Signed 16-bit integer |
98+
| i32 | Signed 32-bit integer |
99+
| i64 | Signed 64-bit integer |
100+
| i128 | Signed 128-bit integer |
101+
| u8 | Unsigned 8-bit integer |
102+
| u16 | Unsigned 16-bit integer |
103+
| u32 | Unsigned 32-bit integer |
104+
| u64 | Unsigned 64-bit integer |
105+
| u128 | Unsigned 128-bit integer |
106+
276107
Integer literal values can be represented in three bases:
277108
```c
278109
// Base 10 (decimal)
@@ -292,7 +123,12 @@ Underscores can also be placed anywhere within the integer literal value (except
292123
1
293124
```
294125

295-
#### Floating-Point Numbers
126+
#### Floating point numbers
127+
| Type | Description |
128+
|:----:|:------------:|
129+
| f32 | 32-bit float |
130+
| f64 | 64-bit float |
131+
296132
Floating-point literal values can be represented in two ways:
297133
```c
298134
// Traditional
@@ -311,9 +147,6 @@ Underscores can also be placed anywhere within the floating-point literal value
311147
31400000000
312148
```
313149

314-
#### Boolean
315-
There are two boolean literal values, `true` and `false`.
316-
317150
### Comments
318151
Comments can be used to explain your code, and are ignored by the compiler, so they have no effect on how your code runs. There are two types of comments:
319152
```

src/infrastructure/error.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,9 @@ pub enum ErrorType {
7171
IllegalImplicitCastError,
7272
IncompatibleTypesError,
7373
OverflowError,
74+
UnexpectedTokenError,
75+
UnrecognizedIdentifierError,
76+
MultipleAssignmentError,
7477
}
7578

7679
impl ErrorType {
@@ -99,6 +102,9 @@ impl ErrorType {
99102
ErrorType::IllegalImplicitCastError => format!("[E0010] {}", self.description()),
100103
ErrorType::IncompatibleTypesError => format!("[E0011] {}", self.description()),
101104
ErrorType::OverflowError => format!("[E0012] {}", self.description()),
105+
ErrorType::UnexpectedTokenError => format!("[E0013] {}", self.description()),
106+
ErrorType::UnrecognizedIdentifierError => format!("[E0014] {}", self.description()),
107+
ErrorType::MultipleAssignmentError => format!("[E0015] {}", self.description()),
102108
}
103109
}
104110

@@ -121,6 +127,11 @@ impl ErrorType {
121127
ErrorType::IllegalImplicitCastError => String::from("Illegal implicit cast"),
122128
ErrorType::IncompatibleTypesError => String::from("Incompatible types"),
123129
ErrorType::OverflowError => String::from("Integer overflow"),
130+
ErrorType::UnexpectedTokenError => String::from("Unexpected token"),
131+
ErrorType::UnrecognizedIdentifierError => String::from("Unrecognized identifier"),
132+
ErrorType::MultipleAssignmentError => {
133+
String::from("Multiple assignments to immutable variable")
134+
}
124135
}
125136
}
126137
}
@@ -233,6 +244,8 @@ impl ConsoleErrorReporter {
233244
self.has_error = false;
234245
self.error_num = 0;
235246
self.warning_num = 0;
247+
self.errors_reported = vec![];
248+
self.warnings_reported = vec![];
236249
}
237250

238251
fn report(&mut self, error_type: ErrorType, messages: Vec<ErrorMessage>, hint: Option<String>) {

0 commit comments

Comments
 (0)