aboutsummaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
Diffstat (limited to 'crates')
-rw-r--r--crates/sloth/Cargo.toml8
-rw-r--r--crates/sloth/src/lexer.rs153
-rw-r--r--crates/sloth/src/main.rs32
-rw-r--r--crates/sloth_bytecode/Cargo.toml4
-rw-r--r--crates/sloth_bytecode/src/lib.rs63
-rw-r--r--crates/sloth_vm/Cargo.toml6
-rw-r--r--crates/sloth_vm/src/lib.rs21
7 files changed, 287 insertions, 0 deletions
diff --git a/crates/sloth/Cargo.toml b/crates/sloth/Cargo.toml
new file mode 100644
index 0000000..65b4859
--- /dev/null
+++ b/crates/sloth/Cargo.toml
@@ -0,0 +1,8 @@
+[package]
+name = "sloth"
+version = "0.1.0"
+edition = "2021"
+
+[dependencies]
+itertools = "0.10.5"
+thiserror = "1.0.40"
diff --git a/crates/sloth/src/lexer.rs b/crates/sloth/src/lexer.rs
new file mode 100644
index 0000000..8631eef
--- /dev/null
+++ b/crates/sloth/src/lexer.rs
@@ -0,0 +1,153 @@
+#![allow(dead_code)]
+
+use thiserror::Error;
+
+#[derive(Debug, Error)]
+pub enum LexerError {
+ #[error("Unexpected token")]
+ UnexpectedToken,
+}
+
+#[derive(Debug, Clone, Eq, PartialEq)]
+pub enum TokenType {
+ // Meta
+ DocComment,
+ Comment,
+
+ // Brackets
+ OpeningParen, // (
+ ClosingParen, // )
+ OpeningBracket, // [
+ ClosingBracket, // ]
+ OpeningBrace, // {
+ ClosingBrace, // }
+
+ // Operators
+ Plus, // +
+ PlusPlus, // ++
+ Minus, // -
+ Star, // *
+ StarStar, // **
+ Slash, // /
+ Perc, // %
+ Tilde, // ~
+
+ PlusEq, // +=
+ PlusPlusEq, // ++=
+ MinusEq, // -=
+ StarEq, // *=
+ StarStarEq, // **=
+ SlashEq, // /=
+ PercEq, // %=
+
+ Amp, // &
+ AmpAmp, // &&
+ Pipe, // |
+ PipePipe, // ||
+
+ Eq, // =
+ EqEq, // ==
+ Bang, // !
+ BangBang, // !!
+ BangEq, // !=
+
+ Lt, // <
+ LtLt, // <<
+ LtEq, // <=
+ Gt, // >
+ GtGt, // >>
+ GtEq, // >=
+
+ Comma,
+
+ Question, // ?
+ QuestionDot, // ?.
+ QuestionQuestion, // ??
+ Dot, // .
+ DotDot, // ..
+
+ Colon, // :
+ ColonColon, // ::
+ SemiColon, // ;
+
+ Arrow, // ->
+
+ // Keywords
+ Val,
+ Var,
+
+ Fn,
+
+ If,
+ Else,
+
+ While,
+ For,
+ In,
+
+ Loop,
+ Break,
+ Continue,
+
+ As,
+
+ // Misc
+ Literal(Literal),
+}
+
+#[derive(Debug, Clone, Eq, PartialEq)]
+pub enum Literal {
+ Numeric,
+ Boolean,
+ Character,
+ String,
+ Regex,
+}
+
+#[derive(Debug, Default)]
+pub struct Location {
+ row: u32,
+ column: u32,
+}
+
+#[derive(Debug)]
+pub struct Token<'a> {
+ pub tt: TokenType,
+ pub lexeme: &'a str,
+
+ start: Location,
+ end: Location,
+}
+
+pub struct Lexer<'a> {
+ source: &'a [u8],
+
+ start: Location,
+ end: Location,
+}
+
+impl<'a> Lexer<'a> {
+ fn new(source: &'a str) -> Self {
+ Self {
+ source: source.as_bytes(),
+ start: Default::default(),
+ end: Default::default(),
+ }
+ }
+}
+
+impl<'a> Iterator for Lexer<'a> {
+ type Item = Token<'a>;
+
+ fn next(&mut self) -> Option<Self::Item> {
+ unimplemented!()
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ #[test]
+ fn basic_test_a() {
+ //
+ }
+}
diff --git a/crates/sloth/src/main.rs b/crates/sloth/src/main.rs
new file mode 100644
index 0000000..89ce7f9
--- /dev/null
+++ b/crates/sloth/src/main.rs
@@ -0,0 +1,32 @@
+#![feature(test, let_chains)]
+#![warn(
+ clippy::wildcard_imports,
+ clippy::string_add,
+ clippy::string_add_assign,
+ clippy::manual_ok_or,
+ unused_lifetimes
+)]
+
+pub mod lexer;
+
+use std::{env, fs};
+
+use itertools::Itertools;
+
+fn main() {
+ let args = env::args().collect_vec();
+
+ if args.len() < 2 {
+ println!("Sloth programming language interpreter\n");
+ println!("Usage: sloth <file>");
+ return;
+ }
+
+ let source_path = &args[1];
+ let Ok(_source) = fs::read_to_string(source_path) else {
+ println!("Error while reading '{source_path}'");
+ return;
+ };
+
+ // TODO:
+}
diff --git a/crates/sloth_bytecode/Cargo.toml b/crates/sloth_bytecode/Cargo.toml
new file mode 100644
index 0000000..a302c81
--- /dev/null
+++ b/crates/sloth_bytecode/Cargo.toml
@@ -0,0 +1,4 @@
+[package]
+name = "sloth_bytecode"
+version = "0.1.0"
+edition = "2021"
diff --git a/crates/sloth_bytecode/src/lib.rs b/crates/sloth_bytecode/src/lib.rs
new file mode 100644
index 0000000..f814f86
--- /dev/null
+++ b/crates/sloth_bytecode/src/lib.rs
@@ -0,0 +1,63 @@
+#![feature(macro_metavar_expr)]
+#![allow(dead_code)]
+#![warn(
+ clippy::wildcard_imports,
+ clippy::string_add,
+ clippy::string_add_assign,
+ clippy::manual_ok_or,
+ unused_lifetimes
+)]
+
+macro_rules! instructions {
+ ( $( $opcode:literal $name:ident [ $( $v_type:ident ),* ] $doc:literal ),* ) => {
+ #[repr(u8)]
+ enum Instruction {
+ $(
+ #[doc = $doc]
+ $name ( $( $v_type ),* ) = $opcode
+ ),*
+ }
+
+ impl Instruction {
+ fn opcode(&self) -> u8 {
+ match self {
+ $(
+ Self::$name ( $( _ ${ignore(v_type)} ),* ) => $opcode
+ ),*
+ }
+ }
+
+ fn from_bytecode(bytecode: &[u8]) -> Option<Self> {
+ if bytecode.is_empty() {
+ return None;
+ }
+
+ let opcode = bytecode[0];
+ let instruction = match opcode {
+ $(
+ $opcode => {
+ // TODO: Get the actual values
+ Some(Self::$name ( $( 0 ${ignore(v_type)} ),* ))
+ }
+ ),*,
+ _ => None,
+ };
+
+ instruction
+ }
+ }
+ }
+}
+
+instructions! {
+ 0x00 Constant [u64] "Push a constant value onto the stack",
+
+ 0x01 Pop [] "Pop a value from the stack",
+ 0x02 Dup [] "Duplicate a value on the stack",
+
+ 0x10 Add [] "Add the last 2 values on the stack",
+ 0x11 Sub [] "Subtract the last 2 values on the stack",
+ 0x12 Mul [] "Multiply the last 2 values on the stack",
+ 0x13 Div [] "Divide the last 2 values on the stack",
+ 0x14 Mod [] "Modulo the last 2 values on the stack"
+}
diff --git a/crates/sloth_vm/Cargo.toml b/crates/sloth_vm/Cargo.toml
new file mode 100644
index 0000000..d27b6d2
--- /dev/null
+++ b/crates/sloth_vm/Cargo.toml
@@ -0,0 +1,6 @@
+[package]
+name = "sloth_vm"
+version = "0.1.0"
+edition = "2021"
+
+[dependencies]
diff --git a/crates/sloth_vm/src/lib.rs b/crates/sloth_vm/src/lib.rs
new file mode 100644
index 0000000..2210a57
--- /dev/null
+++ b/crates/sloth_vm/src/lib.rs
@@ -0,0 +1,21 @@
+#![allow(dead_code)]
+#![warn(
+ clippy::wildcard_imports,
+ clippy::string_add,
+ clippy::string_add_assign,
+ clippy::manual_ok_or,
+ unused_lifetimes
+)]
+
+const STACK_SIZE: usize = 1024;
+
+pub struct VM {
+ stack: [u8; STACK_SIZE],
+ constants: Vec<u8>,
+}
+
+#[cfg(test)]
+mod tests {
+ #[test]
+ fn add_program() {}
+}