This commit is contained in:
nora 2022-04-23 17:24:25 +02:00
parent 3f62892500
commit 930955590d
105 changed files with 22 additions and 3766 deletions

72
Cargo.lock generated
View file

@ -62,19 +62,6 @@ version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "console"
version = "0.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a28b32d32ca44b70c3e4acd7db1babf555fa026e385fb95f18028f88848b3c31"
dependencies = [
"encode_unicode",
"libc",
"once_cell",
"terminal_size",
"winapi",
]
[[package]]
name = "crc32fast"
version = "1.3.2"
@ -119,16 +106,8 @@ version = "0.1.0"
dependencies = [
"bumpalo",
"dbg-pls",
"insta",
"rustc-hash",
]
[[package]]
name = "encode_unicode"
version = "0.3.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f"
[[package]]
name = "flate2"
version = "1.0.23"
@ -163,20 +142,6 @@ dependencies = [
"hashbrown",
]
[[package]]
name = "insta"
version = "1.14.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "689960f187c43c01650c805fb6bc6f55ab944499d86d4ffe9474ad78991d8e94"
dependencies = [
"console",
"once_cell",
"serde",
"serde_json",
"serde_yaml",
"similar",
]
[[package]]
name = "itoa"
version = "1.0.1"
@ -333,12 +298,6 @@ version = "0.6.25"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b"
[[package]]
name = "rustc-hash"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
[[package]]
name = "ryu"
version = "1.0.9"
@ -365,9 +324,6 @@ name = "serde"
version = "1.0.136"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ce31e24b01e1e524df96f1c2fdd054405f8d7376249a5110886fb4b658484789"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
@ -391,24 +347,6 @@ dependencies = [
"serde",
]
[[package]]
name = "serde_yaml"
version = "0.8.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a4a521f2940385c165a24ee286aa8599633d162077a54bdcae2a6fd5a7bfa7a0"
dependencies = [
"indexmap",
"ryu",
"serde",
"yaml-rust",
]
[[package]]
name = "similar"
version = "2.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2e24979f63a11545f5f2c60141afe249d4f19f84581ea2138065e400941d83d3"
[[package]]
name = "smawk"
version = "0.3.1"
@ -448,16 +386,6 @@ dependencies = [
"yaml-rust",
]
[[package]]
name = "terminal_size"
version = "0.1.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "633c1a546cee861a1a6d0dc69ebeca693bf4296661ba7852b9d21d159e0506df"
dependencies = [
"libc",
"winapi",
]
[[package]]
name = "textwrap"
version = "0.15.0"

View file

@ -7,16 +7,4 @@ edition = "2021"
[dependencies]
bumpalo = { version = "3.8.0", features = ["collections"] }
dbg-pls = { version = "0.2.2", features = ["colors", "derive"], optional = true }
rustc-hash = { version = "1.1.0", optional = true }
[features]
fxhash = ["rustc-hash"]
_debug = ["dbg-pls"]
# todo: we don't actually want this as a default feature
default = ["_debug", "fxhash"]
[dev-dependencies]
insta = "1.9.0"
dbg-pls = { version = "0.2.2", features = ["colors", "derive"] }

View file

@ -7,8 +7,7 @@ use crate::errors::Span;
type Symbol = usize;
#[derive(Debug, PartialEq, Eq, Hash, Clone, Copy)]
#[cfg_attr(feature = "_debug", derive(dbg_pls::DebugPls))]
#[derive(Debug, PartialEq, Eq, Hash, Clone, Copy, dbg_pls::DebugPls)]
pub struct Ident {
pub sym: Symbol,
pub span: Span,
@ -16,15 +15,13 @@ pub struct Ident {
pub type Program<'ast> = Block<'ast>;
#[derive(Debug, PartialEq)]
#[cfg_attr(feature = "_debug", derive(dbg_pls::DebugPls))]
#[derive(Debug, PartialEq, dbg_pls::DebugPls)]
pub struct Block<'ast> {
pub stmts: &'ast [Stmt<'ast>],
pub span: Span,
}
#[derive(Debug, PartialEq)]
#[cfg_attr(feature = "_debug", derive(dbg_pls::DebugPls))]
#[derive(Debug, PartialEq, dbg_pls::DebugPls)]
pub enum Stmt<'ast> {
Declaration(Declaration<'ast>),
Assignment(Assignment<'ast>),
@ -39,24 +36,21 @@ pub enum Stmt<'ast> {
Print(Expr<'ast>, Span),
}
#[derive(Debug, PartialEq)]
#[cfg_attr(feature = "_debug", derive(dbg_pls::DebugPls))]
#[derive(Debug, PartialEq, dbg_pls::DebugPls)]
pub struct Declaration<'ast> {
pub span: Span,
pub name: Ident,
pub init: Expr<'ast>,
}
#[derive(Debug, PartialEq)]
#[cfg_attr(feature = "_debug", derive(dbg_pls::DebugPls))]
#[derive(Debug, PartialEq, dbg_pls::DebugPls)]
pub struct Assignment<'ast> {
pub span: Span,
pub lhs: Expr<'ast>,
pub rhs: Expr<'ast>,
}
#[derive(Debug, PartialEq)]
#[cfg_attr(feature = "_debug", derive(dbg_pls::DebugPls))]
#[derive(Debug, PartialEq, dbg_pls::DebugPls)]
pub struct FnDecl<'ast> {
pub span: Span,
pub name: Ident,
@ -64,8 +58,7 @@ pub struct FnDecl<'ast> {
pub body: Block<'ast>,
}
#[derive(Debug, PartialEq)]
#[cfg_attr(feature = "_debug", derive(dbg_pls::DebugPls))]
#[derive(Debug, PartialEq, dbg_pls::DebugPls)]
pub struct IfStmt<'ast> {
pub span: Span,
pub cond: Expr<'ast>,
@ -73,8 +66,7 @@ pub struct IfStmt<'ast> {
pub else_part: Option<&'ast ElsePart<'ast>>,
}
#[derive(Debug, PartialEq)]
#[cfg_attr(feature = "_debug", derive(dbg_pls::DebugPls))]
#[derive(Debug, PartialEq, dbg_pls::DebugPls)]
pub enum ElsePart<'ast> {
Else(Block<'ast>, Span),
ElseIf(IfStmt<'ast>, Span),
@ -88,16 +80,14 @@ impl ElsePart<'_> {
}
}
#[derive(Debug, PartialEq)]
#[cfg_attr(feature = "_debug", derive(dbg_pls::DebugPls))]
#[derive(Debug, PartialEq, dbg_pls::DebugPls)]
pub struct WhileStmt<'ast> {
pub span: Span,
pub cond: Expr<'ast>,
pub body: Block<'ast>,
}
#[derive(Debug, PartialEq)]
#[cfg_attr(feature = "_debug", derive(dbg_pls::DebugPls))]
#[derive(Debug, PartialEq, dbg_pls::DebugPls)]
pub enum Expr<'ast> {
Ident(Ident),
Literal(Literal<'ast>),
@ -118,8 +108,7 @@ impl Expr<'_> {
}
}
#[derive(Debug, PartialEq)]
#[cfg_attr(feature = "_debug", derive(dbg_pls::DebugPls))]
#[derive(Debug, PartialEq, dbg_pls::DebugPls)]
pub enum Literal<'ast> {
String(Symbol, Span),
Number(f64, Span),
@ -142,23 +131,20 @@ impl Literal<'_> {
}
}
#[derive(Debug, PartialEq)]
#[cfg_attr(feature = "_debug", derive(dbg_pls::DebugPls))]
#[derive(Debug, PartialEq, dbg_pls::DebugPls)]
pub struct UnaryOp<'ast> {
pub span: Span,
pub expr: Expr<'ast>,
pub kind: UnaryOpKind,
}
#[derive(Debug, PartialEq)]
#[cfg_attr(feature = "_debug", derive(dbg_pls::DebugPls))]
#[derive(Debug, PartialEq, dbg_pls::DebugPls)]
pub enum UnaryOpKind {
Not,
Neg,
}
#[derive(Debug, PartialEq)]
#[cfg_attr(feature = "_debug", derive(dbg_pls::DebugPls))]
#[derive(Debug, PartialEq, dbg_pls::DebugPls)]
pub struct BinaryOp<'ast> {
pub span: Span,
pub lhs: Expr<'ast>,
@ -166,8 +152,7 @@ pub struct BinaryOp<'ast> {
pub kind: BinaryOpKind,
}
#[derive(Debug, PartialEq)]
#[cfg_attr(feature = "_debug", derive(dbg_pls::DebugPls))]
#[derive(Debug, PartialEq, dbg_pls::DebugPls)]
pub enum BinaryOpKind {
And,
Or,
@ -184,16 +169,14 @@ pub enum BinaryOpKind {
Mod,
}
#[derive(Debug, PartialEq)]
#[cfg_attr(feature = "_debug", derive(dbg_pls::DebugPls))]
#[derive(Debug, PartialEq, dbg_pls::DebugPls)]
pub struct Call<'ast> {
pub callee: Expr<'ast>,
pub span: Span,
pub kind: CallKind<'ast>,
}
#[derive(Debug, PartialEq)]
#[cfg_attr(feature = "_debug", derive(dbg_pls::DebugPls))]
#[derive(Debug, PartialEq, dbg_pls::DebugPls)]
pub enum CallKind<'ast> {
Field(Ident),
Fn(&'ast [Expr<'ast>]),

View file

@ -1,138 +1,5 @@
//!
//! This modules handles error reporting in the interpreter
//!
//! The `span` submodule handles Spans, which are used for tracking locations in the source code.
//!
//! There is a single type `CompilerError` that can be created from anywhere, and reported using
//! functions from here.
use std::fmt::Debug;
pub use span::Span;
mod span {
#[derive(Debug, Default, Copy, Clone, PartialOrd, PartialEq, Ord, Eq, Hash)]
#[cfg_attr(feature = "_debug", derive(dbg_pls::DebugPls))]
pub struct Span {
pub start: usize,
pub end: usize,
}
impl Span {
pub fn start_len(start: usize, len: usize) -> Self {
Self {
start,
end: start + len,
}
}
pub fn start_end(start: usize, end: usize) -> Self {
Self { start, end }
}
pub fn single(start: usize) -> Self {
Self {
start,
end: start + 1,
}
}
pub fn dummy() -> Self {
Self { start: 0, end: 0 }
}
/// Extends the span by the second one
/// The other one has to be after the current one
pub fn extend(&self, other: Span) -> Span {
debug_assert!(self.start <= other.start);
debug_assert!(self.end <= other.end);
Span {
start: self.start,
end: other.end,
}
}
/// Extends the span by the second one, if it exists
/// The other one has to be after the current one, if it exists
pub fn option_extend(&self, other: Option<Span>) -> Span {
match other {
None => *self,
Some(span) => self.extend(span),
}
}
pub fn len(&self) -> usize {
self.end - self.start
}
}
#[derive(dbg_pls::DebugPls)]
pub struct Span {
pub start: usize,
pub end: usize,
}
#[derive(Debug, Clone, PartialEq)]
pub struct CompilerError {
pub span: Span,
pub message: String,
pub note: Option<String>,
}
impl CompilerError {
pub fn new(span: Span, message: String) -> Self {
Self {
span,
message,
note: None,
}
}
pub fn with_note(span: Span, message: String, note: String) -> Self {
Self {
span,
message,
note: Some(note),
}
}
}
pub fn display_error(source: &str, error: CompilerError) {
let span = error.span;
let mut chars = 0;
let lines = source.split_inclusive('\n').enumerate();
for (idx, line) in lines {
if chars + line.len() > span.start {
let offset_on_line = span.start - chars;
eprintln!("{}error: {}{}", RED, error.message, RESET);
eprintln!(" {}|{}", CYAN, RESET);
eprintln!("{}{:>5} |{} {}", CYAN, idx + 1, RESET, line);
eprint!(" {}|{} ", CYAN, RESET);
eprintln!(
"{}{}{}{}",
" ".repeat(offset_on_line),
RED,
"^".repeat(span.len()),
RESET,
);
if let Some(note) = error.note {
eprintln!(" {}|{}", CYAN, RESET);
eprintln!(
" {}|{} {}note: {}{}",
CYAN, RESET, GREEN, note, RESET
);
}
break;
}
chars += line.len();
}
}
macro_rules! color {
($name:ident: $value:literal) => {
const $name: &str = concat!("\x1B[", $value);
};
}
color!(RED: "0;31m");
color!(RESET: "0m");
color!(CYAN: "0;36m");
color!(GREEN: "0;32m");

View file

@ -1,26 +1,7 @@
#![deny(clippy::disallowed_type)]
mod ast;
mod errors;
use crate::ast::Program;
use std::io::Write;
pub use bumpalo::Bump;
#[cfg(not(feature = "fxhash"))]
#[allow(clippy::disallowed_types)]
type HashMap<K, V> = std::collections::HashMap<K, V>;
#[cfg(feature = "fxhash")]
type HashMap<K, V> = rustc_hash::FxHashMap<K, V>;
#[cfg(not(feature = "fxhash"))]
#[allow(clippy::disallowed_types)]
type HashSet<T> = std::collections::HashSet<T>;
#[cfg(feature = "fxhash")]
type HashSet<T> = rustc_hash::FxHashSet<T>;
pub fn process_ast(program: &str, ast: &Program) {
dbg(ast);

View file

@ -1,33 +0,0 @@
---
source: src/parse/test.rs
assertion_line: 33
expression: ast
---
BinaryOp(
BinaryOp {
span: Span {
start: 0,
end: 0,
},
lhs: Literal(
Number(
10.0,
Span {
start: 0,
end: 0,
},
),
),
rhs: Literal(
Number(
4.0,
Span {
start: 0,
end: 0,
},
),
),
kind: Add,
},
)

View file

@ -1,33 +0,0 @@
---
source: src/parse/test.rs
assertion_line: 33
expression: ast
---
BinaryOp(
BinaryOp {
span: Span {
start: 0,
end: 0,
},
lhs: Literal(
Number(
10.0,
Span {
start: 0,
end: 0,
},
),
),
rhs: Literal(
Number(
4.0,
Span {
start: 0,
end: 0,
},
),
),
kind: And,
},
)

View file

@ -1,33 +0,0 @@
---
source: src/parse/test.rs
assertion_line: 47
expression: ast
---
BinaryOp(
BinaryOp {
span: Span {
start: 0,
end: 0,
},
lhs: Literal(
Number(
10.0,
Span {
start: 0,
end: 0,
},
),
),
rhs: Literal(
Number(
4.0,
Span {
start: 0,
end: 0,
},
),
),
kind: And,
},
)

View file

@ -1,67 +0,0 @@
---
source: src/parse/test.rs
assertion_line: 72
expression: ast
---
Assignment(
Assignment {
span: Span {
start: 0,
end: 0,
},
lhs: Call(
Call {
callee: Ident(
Ident {
sym: "hugo",
span: Span {
start: 0,
end: 0,
},
},
),
span: Span {
start: 0,
end: 0,
},
kind: Field(
Ident {
sym: "age",
span: Span {
start: 0,
end: 0,
},
},
),
},
),
rhs: BinaryOp(
BinaryOp {
span: Span {
start: 0,
end: 0,
},
lhs: Literal(
Number(
2021.0,
Span {
start: 0,
end: 0,
},
),
),
rhs: Literal(
Number(
1986.0,
Span {
start: 0,
end: 0,
},
),
),
kind: Sub,
},
),
},
)

View file

@ -1,32 +0,0 @@
---
source: src/parse/test.rs
assertion_line: 54
expression: ast
---
Assignment(
Assignment {
span: Span {
start: 0,
end: 0,
},
lhs: Ident(
Ident {
sym: "hugo",
span: Span {
start: 0,
end: 0,
},
},
),
rhs: Literal(
Number(
10.0,
Span {
start: 0,
end: 0,
},
),
),
},
)

View file

@ -1,13 +0,0 @@
---
source: src/parse/test.rs
assertion_line: 249
expression: ast
---
Block {
stmts: [],
span: Span {
start: 0,
end: 0,
},
}

View file

@ -1,23 +0,0 @@
---
source: src/parse/test.rs
assertion_line: 265
expression: ast
---
Block {
stmts: [
Block(
Block {
stmts: [],
span: Span {
start: 0,
end: 0,
},
},
),
],
span: Span {
start: 0,
end: 0,
},
}

View file

@ -1,36 +0,0 @@
---
source: src/parse/test.rs
assertion_line: 258
expression: ast
---
Block {
stmts: [
Expr(
Literal(
Number(
10.0,
Span {
start: 0,
end: 0,
},
),
),
),
Expr(
Literal(
Number(
20.0,
Span {
start: 0,
end: 0,
},
),
),
),
],
span: Span {
start: 0,
end: 0,
},
}

View file

@ -1,32 +0,0 @@
---
source: src/parse/test.rs
assertion_line: 517
expression: ast
---
Call(
Call {
callee: Ident(
Ident {
sym: "hugo",
span: Span {
start: 0,
end: 0,
},
},
),
span: Span {
start: 0,
end: 0,
},
kind: Field(
Ident {
sym: "name",
span: Span {
start: 0,
end: 0,
},
},
),
},
)

View file

@ -1,45 +0,0 @@
---
source: src/parse/test.rs
assertion_line: 541
expression: ast
---
Call(
Call {
callee: Ident(
Ident {
sym: "print",
span: Span {
start: 0,
end: 0,
},
},
),
span: Span {
start: 0,
end: 0,
},
kind: Fn(
[
Literal(
Number(
10.0,
Span {
start: 0,
end: 0,
},
),
),
Literal(
Number(
5.0,
Span {
start: 0,
end: 0,
},
),
),
],
),
},
)

View file

@ -1,60 +0,0 @@
---
source: src/parse/test.rs
assertion_line: 558
expression: ast
---
Call(
Call {
callee: Call(
Call {
callee: Call(
Call {
callee: Ident(
Ident {
sym: "hugo",
span: Span {
start: 0,
end: 0,
},
},
),
span: Span {
start: 0,
end: 0,
},
kind: Field(
Ident {
sym: "name",
span: Span {
start: 0,
end: 0,
},
},
),
},
),
span: Span {
start: 0,
end: 0,
},
kind: Field(
Ident {
sym: "print",
span: Span {
start: 0,
end: 0,
},
},
),
},
),
span: Span {
start: 0,
end: 0,
},
kind: Fn(
[],
),
},
)

View file

@ -1,26 +0,0 @@
---
source: src/parse/test.rs
assertion_line: 524
expression: ast
---
Call(
Call {
callee: Ident(
Ident {
sym: "print",
span: Span {
start: 0,
end: 0,
},
},
),
span: Span {
start: 0,
end: 0,
},
kind: Fn(
[],
),
},
)

View file

@ -1,82 +0,0 @@
---
source: src/parse/test.rs
assertion_line: 581
expression: ast
---
Call(
Call {
callee: Ident(
Ident {
sym: "print",
span: Span {
start: 0,
end: 0,
},
},
),
span: Span {
start: 0,
end: 0,
},
kind: Fn(
[
Call(
Call {
callee: Call(
Call {
callee: BinaryOp(
BinaryOp {
span: Span {
start: 0,
end: 0,
},
lhs: Literal(
Number(
10.0,
Span {
start: 0,
end: 0,
},
),
),
rhs: Literal(
Number(
5.0,
Span {
start: 0,
end: 0,
},
),
),
kind: Add,
},
),
span: Span {
start: 0,
end: 0,
},
kind: Field(
Ident {
sym: "abs",
span: Span {
start: 0,
end: 0,
},
},
),
},
),
span: Span {
start: 0,
end: 0,
},
kind: Fn(
[],
),
},
),
],
),
},
)

View file

@ -1,33 +0,0 @@
---
source: src/parse/test.rs
assertion_line: 33
expression: ast
---
BinaryOp(
BinaryOp {
span: Span {
start: 0,
end: 0,
},
lhs: Literal(
Number(
10.0,
Span {
start: 0,
end: 0,
},
),
),
rhs: Literal(
Number(
4.0,
Span {
start: 0,
end: 0,
},
),
),
kind: Div,
},
)

View file

@ -1,33 +0,0 @@
---
source: src/parse/test.rs
assertion_line: 33
expression: ast
---
BinaryOp(
BinaryOp {
span: Span {
start: 0,
end: 0,
},
lhs: Literal(
Number(
10.0,
Span {
start: 0,
end: 0,
},
),
),
rhs: Literal(
Number(
4.0,
Span {
start: 0,
end: 0,
},
),
),
kind: Equal,
},
)

View file

@ -1,51 +0,0 @@
---
source: src/parse/test.rs
assertion_line: 298
expression: ast
---
BinaryOp(
BinaryOp {
span: Span {
start: 0,
end: 0,
},
lhs: Literal(
Number(
10.0,
Span {
start: 0,
end: 0,
},
),
),
rhs: BinaryOp(
BinaryOp {
span: Span {
start: 0,
end: 0,
},
lhs: Literal(
Number(
20.0,
Span {
start: 0,
end: 0,
},
),
),
rhs: Literal(
Number(
100.0,
Span {
start: 0,
end: 0,
},
),
),
kind: Mul,
},
),
kind: Add,
},
)

View file

@ -1,42 +0,0 @@
---
source: src/parse/test.rs
assertion_line: 307
expression: ast
---
BinaryOp(
BinaryOp {
span: Span {
start: 0,
end: 0,
},
lhs: Literal(
Number(
10.0,
Span {
start: 0,
end: 0,
},
),
),
rhs: UnaryOp(
UnaryOp {
span: Span {
start: 0,
end: 0,
},
expr: Literal(
Number(
10.0,
Span {
start: 0,
end: 0,
},
),
),
kind: Neg,
},
),
kind: Equal,
},
)

View file

@ -1,51 +0,0 @@
---
source: src/parse/test.rs
assertion_line: 324
expression: ast
---
BinaryOp(
BinaryOp {
span: Span {
start: 0,
end: 0,
},
lhs: Literal(
Number(
10.0,
Span {
start: 0,
end: 0,
},
),
),
rhs: BinaryOp(
BinaryOp {
span: Span {
start: 0,
end: 0,
},
lhs: Literal(
Number(
20.0,
Span {
start: 0,
end: 0,
},
),
),
rhs: Literal(
Number(
30.0,
Span {
start: 0,
end: 0,
},
),
),
kind: Add,
},
),
kind: Mul,
},
)

View file

@ -1,33 +0,0 @@
---
source: src/parse/test.rs
assertion_line: 33
expression: ast
---
BinaryOp(
BinaryOp {
span: Span {
start: 0,
end: 0,
},
lhs: Literal(
Number(
10.0,
Span {
start: 0,
end: 0,
},
),
),
rhs: Literal(
Number(
4.0,
Span {
start: 0,
end: 0,
},
),
),
kind: Greater,
},
)

View file

@ -1,33 +0,0 @@
---
source: src/parse/test.rs
assertion_line: 33
expression: ast
---
BinaryOp(
BinaryOp {
span: Span {
start: 0,
end: 0,
},
lhs: Literal(
Number(
10.0,
Span {
start: 0,
end: 0,
},
),
),
rhs: Literal(
Number(
4.0,
Span {
start: 0,
end: 0,
},
),
),
kind: GreaterEqual,
},
)

View file

@ -1,33 +0,0 @@
---
source: src/parse/test.rs
assertion_line: 33
expression: ast
---
BinaryOp(
BinaryOp {
span: Span {
start: 0,
end: 0,
},
lhs: Literal(
Number(
10.0,
Span {
start: 0,
end: 0,
},
),
),
rhs: Literal(
Number(
4.0,
Span {
start: 0,
end: 0,
},
),
),
kind: Less,
},
)

View file

@ -1,33 +0,0 @@
---
source: src/parse/test.rs
assertion_line: 33
expression: ast
---
BinaryOp(
BinaryOp {
span: Span {
start: 0,
end: 0,
},
lhs: Literal(
Number(
10.0,
Span {
start: 0,
end: 0,
},
),
),
rhs: Literal(
Number(
4.0,
Span {
start: 0,
end: 0,
},
),
),
kind: LessEqual,
},
)

View file

@ -1,33 +0,0 @@
---
source: src/parse/test.rs
assertion_line: 33
expression: ast
---
BinaryOp(
BinaryOp {
span: Span {
start: 0,
end: 0,
},
lhs: Literal(
Number(
10.0,
Span {
start: 0,
end: 0,
},
),
),
rhs: Literal(
Number(
4.0,
Span {
start: 0,
end: 0,
},
),
),
kind: Mod,
},
)

View file

@ -1,33 +0,0 @@
---
source: src/parse/test.rs
assertion_line: 33
expression: ast
---
BinaryOp(
BinaryOp {
span: Span {
start: 0,
end: 0,
},
lhs: Literal(
Number(
10.0,
Span {
start: 0,
end: 0,
},
),
),
rhs: Literal(
Number(
4.0,
Span {
start: 0,
end: 0,
},
),
),
kind: Mul,
},
)

View file

@ -1,33 +0,0 @@
---
source: src/parse/test.rs
assertion_line: 33
expression: ast
---
BinaryOp(
BinaryOp {
span: Span {
start: 0,
end: 0,
},
lhs: Literal(
Number(
10.0,
Span {
start: 0,
end: 0,
},
),
),
rhs: Literal(
Number(
4.0,
Span {
start: 0,
end: 0,
},
),
),
kind: NotEqual,
},
)

View file

@ -1,15 +0,0 @@
---
source: src/parse/test.rs
assertion_line: 39
expression: ast
---
Literal(
Number(
10.0,
Span {
start: 0,
end: 0,
},
),
)

View file

@ -1,15 +0,0 @@
---
source: src/parse/test.rs
assertion_line: 39
expression: ast
---
Literal(
Number(
10.0,
Span {
start: 0,
end: 0,
},
),
)

View file

@ -1,15 +0,0 @@
---
source: src/parse/test.rs
assertion_line: 39
expression: ast
---
Literal(
Number(
10.0,
Span {
start: 0,
end: 0,
},
),
)

View file

@ -1,15 +0,0 @@
---
source: src/parse/test.rs
assertion_line: 39
expression: ast
---
Literal(
Number(
10.0,
Span {
start: 0,
end: 0,
},
),
)

View file

@ -1,15 +0,0 @@
---
source: src/parse/test.rs
assertion_line: 39
expression: ast
---
Literal(
Number(
10.0,
Span {
start: 0,
end: 0,
},
),
)

View file

@ -1,15 +0,0 @@
---
source: src/parse/test.rs
assertion_line: 39
expression: ast
---
Literal(
Number(
10.0,
Span {
start: 0,
end: 0,
},
),
)

View file

@ -1,15 +0,0 @@
---
source: src/parse/test.rs
assertion_line: 39
expression: ast
---
Literal(
Number(
10.0,
Span {
start: 0,
end: 0,
},
),
)

View file

@ -1,15 +0,0 @@
---
source: src/parse/test.rs
assertion_line: 39
expression: ast
---
Literal(
Number(
10.0,
Span {
start: 0,
end: 0,
},
),
)

View file

@ -1,33 +0,0 @@
---
source: src/parse/test.rs
assertion_line: 47
expression: ast
---
BinaryOp(
BinaryOp {
span: Span {
start: 0,
end: 0,
},
lhs: Literal(
Number(
10.0,
Span {
start: 0,
end: 0,
},
),
),
rhs: Literal(
Number(
4.0,
Span {
start: 0,
end: 0,
},
),
),
kind: Or,
},
)

View file

@ -1,15 +0,0 @@
---
source: src/parse/test.rs
assertion_line: 625
expression: ast
---
Literal(
Array(
[],
Span {
start: 0,
end: 0,
},
),
)

View file

@ -1,15 +0,0 @@
---
source: src/parse/test.rs
assertion_line: 653
expression: ast
---
Literal(
Array(
[],
Span {
start: 0,
end: 0,
},
),
)

View file

@ -1,14 +0,0 @@
---
source: src/parse/test.rs
assertion_line: 618
expression: ast
---
Literal(
Object(
Span {
start: 0,
end: 0,
},
),
)

View file

@ -1,15 +0,0 @@
---
source: src/parse/test.rs
assertion_line: 597
expression: ast
---
Ident(
Ident {
sym: "tokens",
span: Span {
start: 0,
end: 0,
},
},
)

View file

@ -1,14 +0,0 @@
---
source: src/parse/test.rs
assertion_line: 646
expression: ast
---
Literal(
Null(
Span {
start: 0,
end: 0,
},
),
)

View file

@ -1,15 +0,0 @@
---
source: src/parse/test.rs
assertion_line: 611
expression: ast
---
Literal(
String(
"uwu",
Span {
start: 0,
end: 0,
},
),
)

View file

@ -1,15 +0,0 @@
---
source: src/parse/test.rs
assertion_line: 632
expression: ast
---
Literal(
Boolean(
false,
Span {
start: 0,
end: 0,
},
),
)

View file

@ -1,15 +0,0 @@
---
source: src/parse/test.rs
assertion_line: 639
expression: ast
---
Literal(
Boolean(
true,
Span {
start: 0,
end: 0,
},
),
)

View file

@ -1,25 +0,0 @@
---
source: src/parse/test.rs
assertion_line: 660
expression: ast
---
Literal(
Array(
[
Literal(
Number(
10.0,
Span {
start: 0,
end: 0,
},
),
),
],
Span {
start: 0,
end: 0,
},
),
)

View file

@ -1,25 +0,0 @@
---
source: src/parse/test.rs
assertion_line: 667
expression: ast
---
Literal(
Array(
[
Literal(
Number(
10.0,
Span {
start: 0,
end: 0,
},
),
),
],
Span {
start: 0,
end: 0,
},
),
)

View file

@ -1,15 +0,0 @@
---
source: src/parse/test.rs
assertion_line: 604
expression: ast
---
Literal(
Number(
10.0,
Span {
start: 0,
end: 0,
},
),
)

View file

@ -1,34 +0,0 @@
---
source: src/parse/test.rs
assertion_line: 676
expression: ast
---
Literal(
Array(
[
Literal(
Number(
10.0,
Span {
start: 0,
end: 0,
},
),
),
Literal(
Number(
10.0,
Span {
start: 0,
end: 0,
},
),
),
],
Span {
start: 0,
end: 0,
},
),
)

View file

@ -1,34 +0,0 @@
---
source: src/parse/test.rs
assertion_line: 685
expression: ast
---
Literal(
Array(
[
Literal(
Number(
10.0,
Span {
start: 0,
end: 0,
},
),
),
Literal(
Number(
10.0,
Span {
start: 0,
end: 0,
},
),
),
],
Span {
start: 0,
end: 0,
},
),
)

View file

@ -1,21 +0,0 @@
---
source: src/parse/test.rs
assertion_line: 175
expression: ast
---
Print(
Literal(
Boolean(
true,
Span {
start: 0,
end: 0,
},
),
),
Span {
start: 0,
end: 0,
},
)

View file

@ -1,29 +0,0 @@
---
source: src/parse/test.rs
assertion_line: 90
expression: ast
---
FnDecl(
FnDecl {
span: Span {
start: 0,
end: 0,
},
name: Ident {
sym: "empty",
span: Span {
start: 0,
end: 0,
},
},
params: [],
body: Block {
stmts: [],
span: Span {
start: 0,
end: 0,
},
},
},
)

View file

@ -1,74 +0,0 @@
---
source: src/parse/test.rs
assertion_line: 113
expression: ast
---
FnDecl(
FnDecl {
span: Span {
start: 0,
end: 0,
},
name: Ident {
sym: "empty",
span: Span {
start: 0,
end: 0,
},
},
params: [
Ident {
sym: "a",
span: Span {
start: 0,
end: 0,
},
},
Ident {
sym: "b",
span: Span {
start: 0,
end: 0,
},
},
],
body: Block {
stmts: [
Expr(
BinaryOp(
BinaryOp {
span: Span {
start: 0,
end: 0,
},
lhs: Literal(
Number(
10.0,
Span {
start: 0,
end: 0,
},
),
),
rhs: Literal(
Number(
20.0,
Span {
start: 0,
end: 0,
},
),
),
kind: Add,
},
),
),
],
span: Span {
start: 0,
end: 0,
},
},
},
)

View file

@ -1,29 +0,0 @@
---
source: src/parse/test.rs
assertion_line: 130
expression: ast
---
IfStmt {
span: Span {
start: 0,
end: 0,
},
cond: Literal(
Boolean(
true,
Span {
start: 0,
end: 0,
},
),
),
body: Block {
stmts: [],
span: Span {
start: 0,
end: 0,
},
},
else_part: None,
}

View file

@ -1,43 +0,0 @@
---
source: src/parse/test.rs
assertion_line: 139
expression: ast
---
IfStmt {
span: Span {
start: 0,
end: 0,
},
cond: Literal(
Boolean(
true,
Span {
start: 0,
end: 0,
},
),
),
body: Block {
stmts: [],
span: Span {
start: 0,
end: 0,
},
},
else_part: Some(
Else(
Block {
stmts: [],
span: Span {
start: 0,
end: 0,
},
},
Span {
start: 0,
end: 0,
},
),
),
}

View file

@ -1,59 +0,0 @@
---
source: src/parse/test.rs
assertion_line: 148
expression: ast
---
IfStmt {
span: Span {
start: 0,
end: 0,
},
cond: Literal(
Boolean(
true,
Span {
start: 0,
end: 0,
},
),
),
body: Block {
stmts: [],
span: Span {
start: 0,
end: 0,
},
},
else_part: Some(
ElseIf(
IfStmt {
span: Span {
start: 0,
end: 0,
},
cond: Literal(
Boolean(
true,
Span {
start: 0,
end: 0,
},
),
),
body: Block {
stmts: [],
span: Span {
start: 0,
end: 0,
},
},
else_part: None,
},
Span {
start: 0,
end: 0,
},
),
),
}

View file

@ -1,73 +0,0 @@
---
source: src/parse/test.rs
assertion_line: 159
expression: ast
---
IfStmt {
span: Span {
start: 0,
end: 0,
},
cond: Literal(
Boolean(
true,
Span {
start: 0,
end: 0,
},
),
),
body: Block {
stmts: [],
span: Span {
start: 0,
end: 0,
},
},
else_part: Some(
ElseIf(
IfStmt {
span: Span {
start: 0,
end: 0,
},
cond: Literal(
Boolean(
true,
Span {
start: 0,
end: 0,
},
),
),
body: Block {
stmts: [],
span: Span {
start: 0,
end: 0,
},
},
else_part: Some(
Else(
Block {
stmts: [],
span: Span {
start: 0,
end: 0,
},
},
Span {
start: 0,
end: 0,
},
),
),
},
Span {
start: 0,
end: 0,
},
),
),
}

View file

@ -1,39 +0,0 @@
---
source: src/parse/test.rs
assertion_line: 232
expression: ast
---
Loop(
Block {
stmts: [
Loop(
Block {
stmts: [],
span: Span {
start: 0,
end: 0,
},
},
Span {
start: 0,
end: 0,
},
),
Break(
Span {
start: 0,
end: 0,
},
),
],
span: Span {
start: 0,
end: 0,
},
},
Span {
start: 0,
end: 0,
},
)

View file

@ -1,19 +0,0 @@
---
source: src/parse/test.rs
assertion_line: 216
expression: ast
---
Loop(
Block {
stmts: [],
span: Span {
start: 0,
end: 0,
},
},
Span {
start: 0,
end: 0,
},
)

View file

@ -1,26 +0,0 @@
---
source: src/parse/test.rs
assertion_line: 223
expression: ast
---
Loop(
Block {
stmts: [
Break(
Span {
start: 0,
end: 0,
},
),
],
span: Span {
start: 0,
end: 0,
},
},
Span {
start: 0,
end: 0,
},
)

View file

@ -1,30 +0,0 @@
---
source: src/parse/test.rs
assertion_line: 191
expression: ast
---
While(
WhileStmt {
span: Span {
start: 0,
end: 0,
},
cond: Literal(
Boolean(
true,
Span {
start: 0,
end: 0,
},
),
),
body: Block {
stmts: [],
span: Span {
start: 0,
end: 0,
},
},
},
)

View file

@ -1,55 +0,0 @@
---
source: src/parse/test.rs
assertion_line: 200
expression: ast
---
While(
WhileStmt {
span: Span {
start: 0,
end: 0,
},
cond: BinaryOp(
BinaryOp {
span: Span {
start: 0,
end: 0,
},
lhs: Literal(
Boolean(
false,
Span {
start: 0,
end: 0,
},
),
),
rhs: Literal(
Boolean(
true,
Span {
start: 0,
end: 0,
},
),
),
kind: Or,
},
),
body: Block {
stmts: [
Break(
Span {
start: 0,
end: 0,
},
),
],
span: Span {
start: 0,
end: 0,
},
},
},
)

View file

@ -1,33 +0,0 @@
---
source: src/parse/test.rs
assertion_line: 33
expression: ast
---
BinaryOp(
BinaryOp {
span: Span {
start: 0,
end: 0,
},
lhs: Literal(
Number(
10.0,
Span {
start: 0,
end: 0,
},
),
),
rhs: Literal(
Number(
4.0,
Span {
start: 0,
end: 0,
},
),
),
kind: Sub,
},
)

View file

@ -1,24 +0,0 @@
---
source: src/parse/test.rs
assertion_line: 501
expression: ast
---
UnaryOp(
UnaryOp {
span: Span {
start: 0,
end: 0,
},
expr: Literal(
Number(
10.0,
Span {
start: 0,
end: 0,
},
),
),
kind: Neg,
},
)

View file

@ -1,24 +0,0 @@
---
source: src/parse/test.rs
assertion_line: 494
expression: ast
---
UnaryOp(
UnaryOp {
span: Span {
start: 0,
end: 0,
},
expr: Literal(
Boolean(
true,
Span {
start: 0,
end: 0,
},
),
),
kind: Not,
},
)

View file

@ -1,792 +0,0 @@
//! Test for the parser
//!
//! These tests are horrible and break all the time. Never do it like this again.
//! That said it's too late to fix it.
use crate::errors::Span;
use crate::parse::Parser;
use crate::RtAlloc;
use bumpalo::Bump;
use prelude::*;
mod prelude {
pub(super) use super::{parser, rt, test_literal_bin_op, test_number_literal, token};
pub(super) use crate::ast::{Expr, Stmt};
pub(super) use crate::lex::TokenKind::*;
pub type Token = crate::lex::Token;
pub type TokenType = crate::lex::TokenKind;
pub(super) use bumpalo::Bump;
}
fn token(kind: TokenType) -> Token {
Token {
span: Span::dummy(),
kind,
}
}
fn rt() -> RtAlloc {
// SAFETY: this is just a test what could go wrong
unsafe { RtAlloc::new() }
}
fn parser(tokens: std::vec::Vec<Token>, alloc: &Bump) -> Parser<std::vec::IntoIter<Token>>
where {
Parser {
tokens: tokens.into_iter().peekable(),
depth: 0,
inside_fn_depth: 0,
inside_loop_depth: 0,
bump: alloc,
}
}
fn test_literal_bin_op<F: FnOnce(Vec<Token>, &Bump) -> Expr>(token_type: TokenType, parser: F) {
let tokens = [Number(10.0), token_type, Number(4.0)].map(token).into();
let alloc = Bump::new();
let ast = parser(tokens, &alloc);
insta::assert_debug_snapshot!(ast);
}
fn test_number_literal<F: FnOnce(Vec<Token>, &Bump) -> Expr>(parser: F) {
let tokens = [Number(10.0)].map(token).into();
let alloc = Bump::new();
let ast = parser(tokens, &alloc);
insta::assert_debug_snapshot!(ast);
}
mod assignment {
use super::prelude::*;
use crate::parse::test::rt;
use bumpalo::Bump;
fn parse_assignment(tokens: Vec<Token>, alloc: &Bump) -> Stmt {
let mut parser = parser(tokens, alloc);
parser.assignment().unwrap()
}
#[test]
fn simple() {
let mut rt = rt();
let tokens = [Ident(rt.intern_string("hugo")), Equal, Number(10.0), Semi]
.map(token)
.into();
let alloc = Bump::new();
let ast = parse_assignment(tokens, &alloc);
insta::assert_debug_snapshot!(ast);
}
#[test]
fn call_expr() {
let mut rt = rt();
let tokens = [
Ident(rt.intern_string("hugo")),
Dot,
Ident(rt.intern_string("age")),
Equal,
Number(2021.0),
Minus,
Number(1986.0),
Semi,
]
.map(token)
.into();
let alloc = Bump::new();
let ast = parse_assignment(tokens, &alloc);
insta::assert_debug_snapshot!(ast);
}
}
mod r#fn {
use super::prelude::*;
fn parse_fn(tokens: Vec<Token>, alloc: &Bump) -> Stmt {
let mut parser = parser(tokens, alloc);
parser.fn_decl().unwrap()
}
#[test]
fn empty() {
let mut rt = rt();
let tokens = [
Fn,
Ident(rt.intern_string("empty")),
ParenO,
ParenC,
BraceO,
BraceC,
]
.map(token)
.into();
let alloc = Bump::new();
let ast = parse_fn(tokens, &alloc);
insta::assert_debug_snapshot!(ast);
}
#[test]
fn params_body() {
let mut rt = rt();
let tokens = [
Fn,
Ident(rt.intern_string("empty")),
ParenO,
Ident(rt.intern_string("a")),
Comma,
Ident(rt.intern_string("b")),
ParenC,
BraceO,
Number(10.0),
Plus,
Number(20.0),
Semi,
BraceC,
]
.map(token)
.into();
let alloc = Bump::new();
let ast = parse_fn(tokens, &alloc);
insta::assert_debug_snapshot!(ast);
}
}
mod r#if {
use super::prelude::*;
use crate::ast::IfStmt;
fn parse_if(tokens: Vec<Token>, alloc: &Bump) -> IfStmt {
let mut parser = parser(tokens, alloc);
parser.if_stmt().unwrap()
}
#[test]
fn empty() {
let tokens = [If, True, BraceO, BraceC].map(token).into();
let alloc = Bump::new();
let ast = parse_if(tokens, &alloc);
insta::assert_debug_snapshot!(ast);
}
#[test]
fn if_else() {
let tokens = [If, True, BraceO, BraceC, Else, BraceO, BraceC]
.map(token)
.into();
let alloc = Bump::new();
let ast = parse_if(tokens, &alloc);
insta::assert_debug_snapshot!(ast);
}
#[test]
fn if_else_if() {
let tokens = [If, True, BraceO, BraceC, Else, If, True, BraceO, BraceC]
.map(token)
.into();
let alloc = Bump::new();
let ast = parse_if(tokens, &alloc);
insta::assert_debug_snapshot!(ast);
}
#[test]
fn if_else_if_else() {
let tokens = [
If, True, BraceO, BraceC, Else, If, True, BraceO, BraceC, Else, BraceO, BraceC,
]
.map(token)
.into();
let alloc = Bump::new();
let ast = parse_if(tokens, &alloc);
insta::assert_debug_snapshot!(ast);
}
}
mod print {
use super::prelude::*;
fn parse_print(tokens: Vec<Token>, alloc: &Bump) -> Stmt {
let mut parser = parser(tokens, alloc);
parser.print_stmt().unwrap()
}
#[test]
fn print_true() {
let tokens = [Print, True, Semi].map(token).into();
let alloc = Bump::new();
let ast = parse_print(tokens, &alloc);
insta::assert_debug_snapshot!(ast);
}
}
mod r#while {
use super::prelude::*;
fn parse_while(tokens: Vec<Token>, alloc: &Bump) -> Stmt {
let mut parser = parser(tokens, alloc);
parser.while_stmt().unwrap()
}
#[test]
fn empty() {
let tokens = [While, True, BraceO, BraceC].map(token).into();
let alloc = Bump::new();
let ast = parse_while(tokens, &alloc);
insta::assert_debug_snapshot!(ast);
}
#[test]
fn or_condition_break() {
let tokens = [While, False, Or, True, BraceO, Break, Semi, BraceC]
.map(token)
.into();
let alloc = Bump::new();
let ast = parse_while(tokens, &alloc);
insta::assert_debug_snapshot!(ast);
}
}
mod r#loop {
use super::prelude::*;
fn parse_loop(tokens: Vec<Token>, alloc: &Bump) -> Stmt {
let mut parser = parser(tokens, alloc);
parser.loop_stmt().unwrap()
}
#[test]
fn empty() {
let tokens = [Loop, BraceO, BraceC].map(token).into();
let alloc = Bump::new();
let ast = parse_loop(tokens, &alloc);
insta::assert_debug_snapshot!(ast);
}
#[test]
fn with_break() {
let tokens = [Loop, BraceO, Break, Semi, BraceC].map(token).into();
let alloc = Bump::new();
let ast = parse_loop(tokens, &alloc);
insta::assert_debug_snapshot!(ast);
}
#[test]
fn break_after_inner() {
let tokens = [Loop, BraceO, Loop, BraceO, BraceC, Break, Semi, BraceC]
.map(token)
.into();
let alloc = Bump::new();
let ast = parse_loop(tokens, &alloc);
insta::assert_debug_snapshot!(ast);
}
}
mod block {
use super::prelude::*;
use crate::ast::Block;
fn parse_block(tokens: Vec<Token>, alloc: &Bump) -> Block {
let mut parser = parser(tokens, alloc);
parser.block().unwrap()
}
#[test]
fn empty() {
let tokens = [BraceO, BraceC].map(token).into();
let alloc = Bump::new();
let ast = parse_block(tokens, &alloc);
insta::assert_debug_snapshot!(ast);
}
#[test]
fn two_expressions() {
let tokens = [BraceO, Number(10.0), Semi, Number(20.0), Semi, BraceC]
.map(token)
.into();
let alloc = Bump::new();
let ast = parse_block(tokens, &alloc);
insta::assert_debug_snapshot!(ast);
}
#[test]
fn nested() {
let tokens = [BraceO, BraceO, BraceC, BraceC].map(token).into();
let alloc = Bump::new();
let ast = parse_block(tokens, &alloc);
insta::assert_debug_snapshot!(ast);
}
}
mod expr {
use super::prelude::*;
fn parse_expr(tokens: Vec<Token>, alloc: &Bump) -> Expr {
let mut parser = parser(tokens, alloc);
parser.expression().unwrap()
}
#[test]
fn stack_overflow() {
let tokens = std::iter::repeat(BracketO)
.map(token)
.take(100_000)
.collect();
let alloc = Bump::new();
let ast = parser(tokens, &alloc).expression();
assert!(ast.is_err());
}
#[test]
fn number_literal() {
test_number_literal(parse_expr);
}
#[test]
fn add_multiply() {
let tokens = [Number(10.0), Plus, Number(20.0), Asterisk, Number(100.0)]
.map(token)
.into();
let alloc = Bump::new();
let ast = parse_expr(tokens, &alloc);
insta::assert_debug_snapshot!(ast);
}
#[test]
fn equal_unary() {
let tokens = [Number(10.0), EqualEqual, Minus, Number(10.0)]
.map(token)
.into();
let alloc = Bump::new();
let ast = parse_expr(tokens, &alloc);
insta::assert_debug_snapshot!(ast);
}
#[test]
fn parentheses_mul_add() {
let tokens = [
Number(10.0),
Asterisk,
ParenO,
Number(20.0),
Plus,
Number(30.0),
ParenC,
]
.map(token)
.into();
let alloc = Bump::new();
let ast = parse_expr(tokens, &alloc);
insta::assert_debug_snapshot!(ast);
}
}
mod logical_or {
use super::prelude::*;
fn parse_logical_or(tokens: Vec<Token>, alloc: &Bump) -> Expr {
let mut parser = parser(tokens, alloc);
parser.logical_or().unwrap()
}
#[test]
fn number_literal() {
test_number_literal(parse_logical_or);
}
#[test]
fn or() {
test_literal_bin_op(Or, parse_logical_or);
}
}
mod logical_and {
use super::prelude::*;
fn parse_logical_and(tokens: Vec<Token>, alloc: &Bump) -> Expr {
let mut parser = parser(tokens, alloc);
parser.logical_and().unwrap()
}
#[test]
fn number_literal() {
test_number_literal(parse_logical_and);
}
#[test]
fn and() {
test_literal_bin_op(And, parse_logical_and);
}
}
mod equality {
use super::prelude::*;
fn parse_equality(tokens: Vec<Token>, alloc: &Bump) -> Expr {
let mut parser = parser(tokens, alloc);
parser.equality().unwrap()
}
#[test]
fn number_literal() {
test_number_literal(parse_equality);
}
#[test]
fn not_equal() {
test_literal_bin_op(BangEqual, parse_equality);
}
#[test]
fn equal() {
test_literal_bin_op(EqualEqual, parse_equality);
}
}
mod comparison {
use super::prelude::*;
fn parse_comparison(tokens: Vec<Token>, alloc: &Bump) -> Expr {
let mut parser = parser(tokens, alloc);
parser.comparison().unwrap()
}
#[test]
fn number_literal() {
test_number_literal(parse_comparison);
}
#[test]
fn greater() {
test_literal_bin_op(Greater, parse_comparison);
}
#[test]
fn greater_equal() {
test_literal_bin_op(GreaterEqual, parse_comparison);
}
#[test]
fn less() {
test_literal_bin_op(Less, parse_comparison);
}
#[test]
fn less_equal() {
test_literal_bin_op(LessEqual, parse_comparison);
}
}
mod term {
use super::prelude::*;
fn parse_term(tokens: Vec<Token>, alloc: &Bump) -> Expr {
let mut parser = parser(tokens, alloc);
parser.term().unwrap()
}
#[test]
fn number_literal() {
test_number_literal(parse_term);
}
#[test]
fn add() {
test_literal_bin_op(Plus, parse_term);
}
#[test]
fn sub() {
test_literal_bin_op(Minus, parse_term);
}
}
mod factor {
use super::prelude::*;
fn parse_factor(tokens: Vec<Token>, alloc: &Bump) -> Expr {
let mut parser = parser(tokens, alloc);
parser.factor().unwrap()
}
#[test]
fn number_literal() {
test_number_literal(parse_factor);
}
#[test]
fn multiply() {
test_literal_bin_op(Asterisk, parse_factor);
}
#[test]
fn divide() {
test_literal_bin_op(Slash, parse_factor);
}
#[test]
fn modulo() {
test_literal_bin_op(Percent, parse_factor);
}
}
mod unary {
use super::prelude::*;
fn parse_unary(tokens: Vec<Token>, alloc: &Bump) -> Expr {
let mut parser = parser(tokens, alloc);
parser.unary().unwrap()
}
#[test]
fn number_literal() {
test_number_literal(parse_unary);
}
#[test]
fn not() {
let tokens = [Not, True].map(token).into();
let alloc = Bump::new();
let ast = parse_unary(tokens, &alloc);
insta::assert_debug_snapshot!(ast);
}
#[test]
fn neg() {
let tokens = [Minus, Number(10.0)].map(token).into();
let alloc = Bump::new();
let ast = parse_unary(tokens, &alloc);
insta::assert_debug_snapshot!(ast);
}
}
mod call {
use super::prelude::*;
fn parse_call(tokens: Vec<Token>, alloc: &Bump) -> Expr {
let mut parser = parser(tokens, alloc);
parser.call().unwrap()
}
#[test]
fn field_simple() {
let mut rt = rt();
let tokens = [
Ident(rt.intern_string("hugo")),
Dot,
Ident(rt.intern_string("name")),
]
.map(token)
.into();
let alloc = Bump::new();
let ast = parse_call(tokens, &alloc);
insta::assert_debug_snapshot!(ast);
}
#[test]
fn simple() {
let mut rt = rt();
let tokens = [Ident(rt.intern_string("print")), ParenO, ParenC]
.map(token)
.into();
let alloc = Bump::new();
let ast = parse_call(tokens, &alloc);
insta::assert_debug_snapshot!(ast);
}
#[test]
fn fn_args() {
let mut rt = rt();
let tokens = [
Ident(rt.intern_string("print")),
ParenO,
Number(10.0),
Comma,
Number(5.0),
Comma,
ParenC,
]
.map(token)
.into();
let alloc = Bump::new();
let ast = parse_call(tokens, &alloc);
insta::assert_debug_snapshot!(ast);
}
#[test]
fn nested() {
let mut rt = rt();
let tokens = [
Ident(rt.intern_string("hugo")),
Dot,
Ident(rt.intern_string("name")),
Dot,
Ident(rt.intern_string("print")),
ParenO,
ParenC,
]
.map(token)
.into();
let alloc = Bump::new();
let ast = parse_call(tokens, &alloc);
insta::assert_debug_snapshot!(ast);
}
#[test]
fn with_exprs() {
let mut rt = rt();
// print((10 + 5).abs())
let tokens = [
Ident(rt.intern_string("print")),
ParenO,
ParenO,
Number(10.0),
Plus,
Number(5.0),
ParenC,
Dot,
Ident(rt.intern_string("abs")),
ParenO,
ParenC,
ParenC,
]
.map(token)
.into();
let alloc = Bump::new();
let ast = parse_call(tokens, &alloc);
insta::assert_debug_snapshot!(ast);
}
}
mod primary {
use super::prelude::*;
fn parse_primary(tokens: Vec<Token>, alloc: &Bump) -> Expr {
let mut parser = parser(tokens, alloc);
parser.primary().unwrap()
}
#[test]
fn ident_test() {
let mut rt = rt();
let tokens = [Ident(rt.intern_string("tokens"))].map(token).into();
let alloc = Bump::new();
let ast = parse_primary(tokens, &alloc);
insta::assert_debug_snapshot!(ast);
}
#[test]
fn string() {
let tokens = [Number(10.0)].map(token).into();
let alloc = Bump::new();
let ast = parse_primary(tokens, &alloc);
insta::assert_debug_snapshot!(ast);
}
#[test]
fn number() {
let mut rt = rt();
let tokens = [String(rt.intern_string("uwu"))].map(token).into();
let alloc = Bump::new();
let ast = parse_primary(tokens, &alloc);
insta::assert_debug_snapshot!(ast);
}
#[test]
fn empty_object() {
let tokens = [BraceO, BraceC].map(token).into();
let alloc = Bump::new();
let ast = parse_primary(tokens, &alloc);
insta::assert_debug_snapshot!(ast);
}
#[test]
fn empty_array() {
let tokens = [BracketO, BracketC].map(token).into();
let alloc = Bump::new();
let ast = parse_primary(tokens, &alloc);
insta::assert_debug_snapshot!(ast);
}
#[test]
fn r#false() {
let tokens = [False].map(token).into();
let alloc = Bump::new();
let ast = parse_primary(tokens, &alloc);
insta::assert_debug_snapshot!(ast);
}
#[test]
fn r#true() {
let tokens = [True].map(token).into();
let alloc = Bump::new();
let ast = parse_primary(tokens, &alloc);
insta::assert_debug_snapshot!(ast);
}
#[test]
fn null() {
let tokens = [Null].map(token).into();
let alloc = Bump::new();
let ast = parse_primary(tokens, &alloc);
insta::assert_debug_snapshot!(ast);
}
#[test]
fn empty_array_literal() {
let tokens = [BracketO, BracketC].map(token).into();
let alloc = Bump::new();
let ast = parse_primary(tokens, &alloc);
insta::assert_debug_snapshot!(ast);
}
#[test]
fn single_array_literal() {
let tokens = [BracketO, Number(10.0), BracketC].map(token).into();
let alloc = Bump::new();
let ast = parse_primary(tokens, &alloc);
insta::assert_debug_snapshot!(ast);
}
#[test]
fn single_array_literal_trailing_comma() {
let tokens = [BracketO, Number(10.0), Comma, BracketC].map(token).into();
let alloc = Bump::new();
let ast = parse_primary(tokens, &alloc);
insta::assert_debug_snapshot!(ast);
}
#[test]
fn two_array_literal() {
let tokens = [BracketO, Number(10.0), Comma, Number(10.0), BracketC]
.map(token)
.into();
let alloc = Bump::new();
let ast = parse_primary(tokens, &alloc);
insta::assert_debug_snapshot!(ast);
}
#[test]
fn two_array_literal_trailing_comma() {
let tokens = [BracketO, Number(10.0), Comma, Number(10.0), Comma, BracketC]
.map(token)
.into();
let alloc = Bump::new();
let ast = parse_primary(tokens, &alloc);
insta::assert_debug_snapshot!(ast);
}
#[test]
fn two_array_literal_no_comma() {
let tokens = [BracketO, Number(10.0), Number(10.0), BracketC]
.map(token)
.into();
let alloc = Bump::new();
let mut parser = parser(tokens, &alloc);
let expr = parser.primary();
assert!(expr.is_err());
}
}

View file

@ -1,14 +0,0 @@
---
source: src/lex.rs
assertion_line: 370
expression: tokens
---
[
BraceO,
ParenO,
BracketO,
BracketC,
BracketC,
BraceC,
]

View file

@ -1,14 +0,0 @@
---
source: src/lex.rs
assertion_line: 370
expression: tokens
---
[
BraceO,
ParenO,
BracketO,
BracketC,
BracketC,
BraceC,
]

View file

@ -1,9 +0,0 @@
---
source: src/lex.rs
assertion_line: 370
expression: tokens
---
[
Fn,
]

View file

@ -1,26 +0,0 @@
---
source: src/lex.rs
assertion_line: 370
expression: tokens
---
[
Number(
3.0,
),
Dot,
Dot,
Number(
2.0,
),
Dot,
Dot,
Number(
1.0,
),
Dot,
Dot,
Number(
0.0,
),
]

View file

@ -1,15 +0,0 @@
---
source: src/lex.rs
assertion_line: 370
expression: tokens
---
[
Dot,
Comma,
Minus,
Asterisk,
Minus,
Comma,
Dot,
]

View file

@ -1,14 +0,0 @@
---
source: src/lex.rs
assertion_line: 370
expression: tokens
---
[
GreaterEqual,
LessEqual,
EqualEqual,
Less,
Less,
GreaterEqual,
]

View file

@ -1,13 +0,0 @@
---
source: src/lex.rs
assertion_line: 370
expression: tokens
---
[
Minus,
Dot,
Minus,
Slash,
Percent,
]

View file

@ -1,25 +0,0 @@
---
source: src/lex.rs
assertion_line: 370
expression: tokens
---
[
Let,
Ident(
"variable",
),
Ident(
"be",
),
Ident(
"a",
),
Loop,
If,
False,
Ident(
"is",
),
True,
]

View file

@ -1,23 +0,0 @@
---
source: src/lex.rs
assertion_line: 370
expression: tokens
---
[
Let,
Fn,
If,
Else,
Loop,
While,
Break,
For,
True,
False,
Null,
And,
Not,
Or,
Print,
]

View file

@ -1,19 +0,0 @@
---
source: src/lex.rs
assertion_line: 370
expression: tokens
---
[
Number(
123456789.0,
),
Comma,
Number(
123456789.1234,
),
Comma,
Number(
64785903.0,
),
]

View file

@ -1,11 +0,0 @@
---
source: src/lex.rs
assertion_line: 370
expression: tokens
---
[
Fn,
For,
And,
]

View file

@ -1,12 +0,0 @@
---
source: src/lex.rs
assertion_line: 370
expression: tokens
---
[
BangEqual,
BangEqual,
Equal,
BangEqual,
]

View file

@ -1,59 +0,0 @@
---
source: src/lex.rs
assertion_line: 370
expression: tokens
---
[
Ident(
"letter",
),
Ident(
"fori",
),
Ident(
"fnfn",
),
Ident(
"iffy",
),
Ident(
"bloop",
),
Ident(
"loopy_yeah",
),
Ident(
"whileTrue",
),
Ident(
"truefalse",
),
Ident(
"falsetrue",
),
Ident(
"nullability",
),
Ident(
"rot",
),
Ident(
"ornot",
),
Ident(
"nor",
),
Ident(
"andnowQuestionMark",
),
Ident(
"notOrAnd",
),
Ident(
"breakMe",
),
Ident(
"Ibreak",
),
]

View file

@ -1,69 +0,0 @@
---
source: src/lex.rs
assertion_line: 370
expression: tokens
---
[
Let,
Ident(
"string",
),
Equal,
String(
"hallol",
),
Let,
Ident(
"number",
),
Equal,
Number(
5.0,
),
Let,
Ident(
"me",
),
Ident(
"out",
),
Dot,
Ident(
"_",
),
Dot,
Fn,
Ident(
"world",
),
ParenO,
ParenC,
BraceO,
If,
Ident(
"number",
),
EqualEqual,
Number(
5.0,
),
Or,
True,
EqualEqual,
False,
And,
Not,
False,
BraceO,
Ident(
"println",
),
ParenO,
String(
"Hello \\ World!",
),
ParenC,
BraceC,
BraceC,
]

View file

@ -1,13 +0,0 @@
---
source: src/lex.rs
assertion_line: 370
expression: tokens
---
[
Greater,
Greater,
Dot,
Less,
Less,
]

View file

@ -1,11 +0,0 @@
---
source: src/lex.rs
assertion_line: 370
expression: tokens
---
[
String(
"uwu",
),
]

View file

@ -1,22 +0,0 @@
---
source: src/lex.rs
assertion_line: 370
expression: tokens
---
[
ParenO,
String(
"hi",
),
String(
"uwu",
),
String(
"\"uwu\"",
),
String(
"no \\ u",
),
ParenC,
]

View file

@ -1,11 +0,0 @@
---
source: src/lex.rs
assertion_line: 370
expression: tokens
---
[
Fn,
Let,
Or,
]

View file

@ -1,11 +0,0 @@
---
source: src/lex.rs
assertion_line: 375
expression: tokens
---
[
Number(
100.0,
),
]

View file

@ -1,11 +0,0 @@
---
source: src/lex.rs
assertion_line: 375
expression: tokens
---
[
Number(
1000000.0,
),
]

View file

@ -1,24 +0,0 @@
#[macro_export]
macro_rules! run_test {
($name:ident, $code:expr) => {
#[test]
fn $name() {
let code = $code;
let output = $crate::common::_run_test(code);
insta::assert_debug_snapshot!(output);
}
};
}
pub fn _run_test(code: &str) -> String {
let mut stdout = Vec::<u8>::new();
let mut cfg = dilaria::Config {
debug: false,
step: false,
stdout: &mut stdout,
};
dilaria::run_program(code, &mut cfg);
String::from_utf8(stdout).unwrap()
}

View file

@ -1,212 +0,0 @@
mod common;
run_test!(
single_if,
r#"
if true {
print "true!";
}
if false {
print "WRONG";
}
"#
);
run_test!(
if_else,
r#"
if true {
print "true!";
} else {
print "WRONG";
}
if false {
print "WRONG";
} else {
print "true!";
}
"#
);
run_test!(
if_else_if,
r#"
if false {
print "WRONG";
} else if true {
print "true!";
} else {
print "WRONG";
}
if false {
print "WRONG";
} else if false {
print "WRONG";
} else {
print "true!";
}
"#
);
run_test!(
if_else_long_comparison_chain,
r#"
let string = "hi ._./";
if string == "no" {
print "WRONG";
} else if string == "no as well" {
print "WRONG";
} else if string == "wrong" {
print "WRONG";
} else if string == "not the correct one" {
print "WRONG";
} else if string == "hi ._. (wrong)" {
print "WRONG";
} else if string == "" {
print "WRONG";
} else if string == "how wrong should it be?" {
print "WRONG";
} else if string == "hi ._./" {
print "true!";
} else {
print "WRONG";
}
"#
);
run_test!(
while_single_loop,
r#"
let x = true;
while x {
x = false;
print "iter";
}
print "done";
"#
);
run_test!(
while_count_to_100,
r#"
let i = 0;
while i < 100 {
print i;
i = i + 1;
}
print "done";
"#
);
run_test!(
while_run_never,
r#"
let not_run = true;
while false {
print "WRONG";
not_run = false;
}
if not_run {
print "good.";
}
"#
);
run_test!(
fizzbuzz,
r#"
let i = 1;
while i < 100 {
if i % 15 == 0 {
print "FizzBuzz";
} else if i % 5 == 0 {
print "Buzz";
} else if i % 3 == 0 {
print "Fizz";
} else {
print i;
}
i = i + 1;
}
"#
);
run_test!(
break_out_loop,
r#"
print "Start";
loop {
break;
print "WRONG";
}
print "Good end";
"#
);
run_test!(
break_out_while,
r#"
print "Start";
while true {
break;
print "WRONG";
}
print "Good end";
"#
);
run_test!(
fizzbuzz_with_loop,
r#"
let i = 1;
loop {
if i % 15 == 0 {
print "FizzBuzz";
} else if i % 5 == 0 {
print "Buzz";
} else if i % 3 == 0 {
print "Fizz";
} else {
print i;
}
i = i + 1;
if i >= 100 {
break;
}
}
"#
);
run_test!(
nested_loop_break,
r#"
print "Start";
loop {
print "Start inner";
loop {
print "inside inner";
break;
print "WRONG";
}
print "Outside inner";
break;
print "WRONG";
}
print "End";
"#
);

View file

@ -1,25 +0,0 @@
mod common;
run_test!(
single_call,
r#"
fn test() {
print "correct";
}
test();
"#
);
run_test!(
single_call_expect_return,
r#"
fn test() {
print "correct1";
}
test();
print "correct2";
"#
);

View file

@ -1,7 +0,0 @@
---
source: tests/control_flow.rs
assertion_line: 144
expression: output
---
"Start\nGood end\n"

View file

@ -1,7 +0,0 @@
---
source: tests/control_flow.rs
assertion_line: 144
expression: output
---
"Start\nGood end\n"

View file

@ -1,7 +0,0 @@
---
source: tests/control_flow.rs
assertion_line: 158
expression: output
---
"Start\nGood end\n"

View file

@ -1,7 +0,0 @@
---
source: tests/control_flow.rs
assertion_line: 124
expression: output
---
"1\n2\nFizz\n4\nBuzz\nFizz\n7\n8\nFizz\nBuzz\n11\nFizz\n13\n14\nFizzBuzz\n16\n17\nFizz\n19\nBuzz\nFizz\n22\n23\nFizz\nBuzz\n26\nFizz\n28\n29\nFizzBuzz\n31\n32\nFizz\n34\nBuzz\nFizz\n37\n38\nFizz\nBuzz\n41\nFizz\n43\n44\nFizzBuzz\n46\n47\nFizz\n49\nBuzz\nFizz\n52\n53\nFizz\nBuzz\n56\nFizz\n58\n59\nFizzBuzz\n61\n62\nFizz\n64\nBuzz\nFizz\n67\n68\nFizz\nBuzz\n71\nFizz\n73\n74\nFizzBuzz\n76\n77\nFizz\n79\nBuzz\nFizz\n82\n83\nFizz\nBuzz\n86\nFizz\n88\n89\nFizzBuzz\n91\n92\nFizz\n94\nBuzz\nFizz\n97\n98\nFizz\n"

View file

@ -1,7 +0,0 @@
---
source: tests/control_flow.rs
assertion_line: 158
expression: output
---
"1\n2\nFizz\n4\nBuzz\nFizz\n7\n8\nFizz\nBuzz\n11\nFizz\n13\n14\nFizzBuzz\n16\n17\nFizz\n19\nBuzz\nFizz\n22\n23\nFizz\nBuzz\n26\nFizz\n28\n29\nFizzBuzz\n31\n32\nFizz\n34\nBuzz\nFizz\n37\n38\nFizz\nBuzz\n41\nFizz\n43\n44\nFizzBuzz\n46\n47\nFizz\n49\nBuzz\nFizz\n52\n53\nFizz\nBuzz\n56\nFizz\n58\n59\nFizzBuzz\n61\n62\nFizz\n64\nBuzz\nFizz\n67\n68\nFizz\nBuzz\n71\nFizz\n73\n74\nFizzBuzz\n76\n77\nFizz\n79\nBuzz\nFizz\n82\n83\nFizz\nBuzz\n86\nFizz\n88\n89\nFizzBuzz\n91\n92\nFizz\n94\nBuzz\nFizz\n97\n98\nFizz\n"

View file

@ -1,7 +0,0 @@
---
source: tests/control_flow.rs
assertion_line: 17
expression: output
---
"true!\ntrue!\n"

View file

@ -1,7 +0,0 @@
---
source: tests/control_flow.rs
assertion_line: 34
expression: output
---
"true!\ntrue!\n"

View file

@ -1,7 +0,0 @@
---
source: tests/control_flow.rs
assertion_line: 55
expression: output
---
"true!\n"

View file

@ -1,7 +0,0 @@
---
source: tests/control_flow.rs
assertion_line: 196
expression: output
---
"Start\nStart inner\ninside inner\nOutside inner\nEnd\n"

Some files were not shown because too many files have changed in this diff Show more