Skip to content

Commit

Permalink
Added parsing for pointers & made LLVM a feature
Browse files Browse the repository at this point in the history
  • Loading branch information
cody-quinn committed Sep 11, 2023
1 parent 7b67ab3 commit d9d843c
Show file tree
Hide file tree
Showing 6 changed files with 65 additions and 21 deletions.
5 changes: 5 additions & 0 deletions examples/pointer.sloth
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
fn main() Int {
val x: Int = 0;
val xPtr: Int = *x;
val x: Int = @xPtr;
}
15 changes: 13 additions & 2 deletions sloth/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,19 @@ version.workspace = true
edition.workspace = true

[dependencies]
llvm-sys = "150"
inkwell = { version = "0.2.0", features = ["llvm15-0"] }
itertools = "0.10.5"
rand = "0.8.5"
thiserror = "1.0.40"

[dependencies.llvm-sys]
version = "150"
optional = true

[dependencies.inkwell]
version = "0.2.0"
features = ["llvm15-0"]
optional = true

[features]
default = ["llvm"]
llvm = ["dep:llvm-sys", "dep:inkwell"]
8 changes: 7 additions & 1 deletion sloth/src/lexer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,8 @@ pub enum TokenType {
GtEq, // >=
GtGtEq, // >>=

At, // @

Comma,

Question, // ?
Expand Down Expand Up @@ -158,6 +160,7 @@ impl Display for TokenType {
TokenType::GtGt => ">>",
TokenType::GtEq => ">=",
TokenType::GtGtEq => ">>=",
TokenType::At => "@",
TokenType::Comma => ",",
TokenType::Question => "?",
TokenType::QuestionDot => "?.",
Expand Down Expand Up @@ -455,6 +458,8 @@ impl<'a> Iterator for Lexer<'a> {
['>', '=', ..] => self.advance_by_with(2, TokenType::GtEq),
['>', ..] => self.advance_with(TokenType::Gt),

['@', ..] => self.advance_with(TokenType::At),

[',', ..] => self.advance_with(TokenType::Comma),

['.', '.', ..] => self.advance_by_with(2, TokenType::DotDot),
Expand Down Expand Up @@ -533,7 +538,7 @@ mod tests {
#[test]
fn lex_operators() {
let source = "+ ++ - * ** / % ~ += ++= -= *= **= /= %= ~= & && | || ^ = == ! !! != < << \
<<= <= > >> >>= >= , ? ?. ?? . .. : :: ; -> =>";
<<= <= > >> >>= >= @ , ? ?. ?? . .. : :: ; -> =>";
let tokens = Lexer::new(source).map(|it| it.tt).collect_vec();

assert_eq!(&tokens, &[
Expand Down Expand Up @@ -571,6 +576,7 @@ mod tests {
TokenType::GtGt,
TokenType::GtGtEq,
TokenType::GtEq,
TokenType::At,
TokenType::Comma,
TokenType::Question,
TokenType::QuestionDot,
Expand Down
38 changes: 23 additions & 15 deletions sloth/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,15 @@
)]

pub mod analysis;
pub mod codegen;
pub mod lexer;
pub mod parser;
pub mod symtable;

use std::fs::File;
#[cfg(feature = "llvm")]
pub mod codegen;

use std::{env, fs};

use codegen::Codegen;
use inkwell::context::Context;
use inkwell::targets::FileType;
use itertools::Itertools;
use lexer::Lexer;
use parser::AstParser;
Expand All @@ -32,15 +30,15 @@ fn main() {
if args.len() < 2 {
println!("Sloth programming language interpreter\n");
println!("Usage: sloth <file...>");
return;
std::process::exit(1);
}

// Reading source files
let mut source = String::new();
for path in args.iter().skip(1) {
let Ok(contents) = fs::read_to_string(path) else {
eprintln!("Error while reading '{path}'");
return;
std::process::exit(1);
};
source.push_str(&contents);
let len = contents.lines().collect_vec().len();
Expand All @@ -52,6 +50,7 @@ fn main() {

// Parsing
let tokens = Lexer::new(&source).collect_vec();
println!("{tokens:#?}");
let global_symtable = mk_symtable();

let mut ast = match AstParser::parse(tokens, global_symtable) {
Expand All @@ -62,7 +61,7 @@ fn main() {
args[1 + (error.line() / 1_000) as usize],
error.line() % 1000 + 1,
);
return;
std::process::exit(1);
}
};

Expand All @@ -72,16 +71,25 @@ fn main() {
args[1 + (error.line() / 1_000) as usize],
error.line() % 1000 + 1,
);
return;
std::process::exit(1);
}

// Generating code for module
let context = Context::create();
let mut codegen = Codegen::new(&context, "s");
let mut output_file = File::create("output.o").unwrap();
// Generating code for module if LLVM enabled
#[cfg(feature = "llvm")]
{
use std::fs::File;

codegen.codegen(&ast);
codegen.write_obj(&mut output_file, FileType::Object);
use codegen::Codegen;
use inkwell::context::Context;
use inkwell::targets::FileType;

let context = Context::create();
let mut codegen = Codegen::new(&context, "s");
let mut output_file = File::create("output.o").unwrap();

codegen.codegen(&ast);
codegen.write_obj(&mut output_file, FileType::Object);
}
}

fn mk_symtable() -> SymbolTable {
Expand Down
9 changes: 9 additions & 0 deletions sloth/src/parser/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -424,6 +424,9 @@ impl Display for BinaryOp {
pub enum UnaryOp {
Not,
Neg,

Reference,
Dereference,
}

impl TryFrom<TokenType> for UnaryOp {
Expand All @@ -434,6 +437,9 @@ impl TryFrom<TokenType> for UnaryOp {
TokenType::Bang => Self::Not,
TokenType::Minus => Self::Neg,

TokenType::Star => Self::Reference,
TokenType::At => Self::Dereference,

_ => return Err(ParsingError::InvalidOp),
};

Expand All @@ -446,6 +452,9 @@ impl Display for UnaryOp {
let value = match self {
UnaryOp::Not => "!",
UnaryOp::Neg => "-",

UnaryOp::Reference => "*",
UnaryOp::Dereference => "@",
};

write!(f, "{value}")
Expand Down
11 changes: 8 additions & 3 deletions sloth/src/parser/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,14 @@ impl<'a> AstParser<'a> {
}

fn unary(&mut self) -> Result<Expr, ParsingError> {
if !self.eof() && matches!(self.peek().tt, TokenType::Bang | TokenType::Minus) {
let oeprator_tt = self.advance().unwrap().tt.clone();
let operator = UnaryOp::try_from(oeprator_tt)?;
if !self.eof()
&& matches!(
self.peek().tt,
TokenType::Bang | TokenType::Minus | TokenType::Star | TokenType::At
)
{
let operator_tt = self.advance().unwrap().tt.clone();
let operator = UnaryOp::try_from(operator_tt)?;

let value = self.unary()?;

Expand Down

0 comments on commit d9d843c

Please sign in to comment.