Remove lifetimes

master
Araozu 2023-09-07 20:32:59 -05:00
parent 4f1fc93ceb
commit fe8f4f3fd1
15 changed files with 63 additions and 197 deletions

16
Cargo.lock generated
View File

@ -158,14 +158,6 @@ version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f051f77a7c8e6957c0696eac88f26b0117e54f52d3fc682ab19397a8812846a4" checksum = "f051f77a7c8e6957c0696eac88f26b0117e54f52d3fc682ab19397a8812846a4"
[[package]]
name = "misti"
version = "0.0.5"
dependencies = [
"clap",
"colored",
]
[[package]] [[package]]
name = "once_cell" name = "once_cell"
version = "1.16.0" version = "1.16.0"
@ -260,6 +252,14 @@ dependencies = [
"winapi-util", "winapi-util",
] ]
[[package]]
name = "thp"
version = "0.0.5"
dependencies = [
"clap",
"colored",
]
[[package]] [[package]]
name = "unicode-ident" name = "unicode-ident"
version = "1.0.5" version = "1.0.5"

View File

@ -1,14 +1,9 @@
[package] [package]
name = "misti" name = "thp"
version = "0.0.5" version = "0.0.5"
edition = "2021" edition = "2021"
[lib]
name = "misti"
path = "src/lib.rs"
test = false
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies] [dependencies]

View File

@ -1,27 +1,27 @@
pub struct ModuleAST<'a> { pub struct ModuleAST {
pub bindings: Vec<Binding<'a>>, pub bindings: Vec<Binding>,
} }
pub enum Binding<'a> { pub enum Binding {
Val(ValBinding<'a>), Val(ValBinding),
Var(VarBinding<'a>), Var(VarBinding),
} }
pub struct ValBinding<'a> { pub struct ValBinding {
pub datatype: Option<String>, pub datatype: Option<String>,
pub identifier: &'a String, pub identifier: Box<String>,
pub expression: Expression<'a>, pub expression: Expression,
} }
pub struct VarBinding<'a> { pub struct VarBinding {
pub datatype: Option<String>, pub datatype: Option<String>,
pub identifier: &'a String, pub identifier: Box<String>,
pub expression: Expression<'a>, pub expression: Expression,
} }
pub enum Expression<'a> { pub enum Expression {
Number(&'a String), Number(Box<String>),
String(&'a String), String(Box<String>),
Boolean(bool), Boolean(bool),
Identifier(&'a String), Identifier(Box<String>),
} }

View File

@ -1,7 +1,7 @@
use super::Transpilable; use super::Transpilable;
use crate::ast_types::Binding; use crate::ast_types::Binding;
impl Transpilable for Binding<'_> { impl Transpilable for Binding {
/// Transpiles val and var bindings into JS. /// Transpiles val and var bindings into JS.
fn transpile(&self) -> String { fn transpile(&self) -> String {
match self { match self {
@ -30,8 +30,8 @@ mod tests {
let value = String::from("322"); let value = String::from("322");
let binding = Binding::Val(ValBinding { let binding = Binding::Val(ValBinding {
datatype: None, datatype: None,
identifier: &id, identifier: Box::new(id),
expression: Expression::Number(&value), expression: Expression::Number(Box::new(value)),
}); });
let result = binding.transpile(); let result = binding.transpile();

View File

@ -1,7 +1,7 @@
use super::Transpilable; use super::Transpilable;
use crate::ast_types::Expression; use crate::ast_types::Expression;
impl Transpilable for Expression<'_> { impl Transpilable for Expression {
/// Transpiles an Expression to JS /// Transpiles an Expression to JS
/// ///
/// Right now the expressions in the grammar are: /// Right now the expressions in the grammar are:
@ -11,12 +11,12 @@ impl Transpilable for Expression<'_> {
/// - Identifier /// - Identifier
fn transpile(&self) -> String { fn transpile(&self) -> String {
match self { match self {
Expression::Number(value) => String::from(*value), Expression::Number(value) => format!("{}", value),
Expression::String(value) => { Expression::String(value) => {
format!("\"{}\"", *value) format!("\"{}\"", *value)
} }
Expression::Boolean(value) => String::from(if *value { "true" } else { "false" }), Expression::Boolean(value) => String::from(if *value { "true" } else { "false" }),
Expression::Identifier(value) => String::from(*value), Expression::Identifier(value) => format!("{}", *value),
} }
} }
} }
@ -29,7 +29,7 @@ mod tests {
#[test] #[test]
fn should_transpile_number() { fn should_transpile_number() {
let str = String::from("42"); let str = String::from("42");
let exp = Expression::Number(&str); let exp = Expression::Number(Box::new(str));
let result = exp.transpile(); let result = exp.transpile();
assert_eq!("42", result); assert_eq!("42", result);
@ -38,7 +38,7 @@ mod tests {
#[test] #[test]
fn should_transpile_string() { fn should_transpile_string() {
let str = String::from("Hello world"); let str = String::from("Hello world");
let exp = Expression::String(&str); let exp = Expression::String(Box::new(str));
let result = exp.transpile(); let result = exp.transpile();
assert_eq!("\"Hello world\"", result); assert_eq!("\"Hello world\"", result);
@ -55,7 +55,7 @@ mod tests {
#[test] #[test]
fn should_transpile_identifier() { fn should_transpile_identifier() {
let s = String::from("newValue"); let s = String::from("newValue");
let exp = Expression::Identifier(&s); let exp = Expression::Identifier(Box::new(s));
let result = exp.transpile(); let result = exp.transpile();
assert_eq!("newValue", result); assert_eq!("newValue", result);

View File

@ -17,7 +17,7 @@ pub fn codegen<'a>(ast: &'a ModuleAST) -> String {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use crate::{lexic, semantic, symbol_table::SymbolTable, syntax}; use crate::{lexic, syntax};
use super::*; use super::*;
@ -26,8 +26,6 @@ mod tests {
let input = String::from("val id = 322"); let input = String::from("val id = 322");
let tokens = lexic::get_tokens(&input).unwrap(); let tokens = lexic::get_tokens(&input).unwrap();
let mut ast = syntax::construct_ast(&tokens).unwrap(); let mut ast = syntax::construct_ast(&tokens).unwrap();
let mut table = SymbolTable::new();
semantic::check_ast(&mut ast, &mut table);
let out_str = codegen(&ast); let out_str = codegen(&ast);

View File

@ -1,7 +1,7 @@
use super::Transpilable; use super::Transpilable;
use crate::ast_types::ModuleAST; use crate::ast_types::ModuleAST;
impl Transpilable for ModuleAST<'_> { impl Transpilable for ModuleAST {
/// Transpiles the whole AST into JS, using this same trait on the /// Transpiles the whole AST into JS, using this same trait on the
/// nodes and leaves of the AST /// nodes and leaves of the AST
fn transpile(&self) -> String { fn transpile(&self) -> String {
@ -26,8 +26,8 @@ mod tests {
let value = String::from("322"); let value = String::from("322");
let binding = Binding::Val(ValBinding { let binding = Binding::Val(ValBinding {
datatype: None, datatype: None,
identifier: &id, identifier: Box::new(id),
expression: Expression::Number(&value), expression: Expression::Number(Box::new(value)),
}); });
let module = ModuleAST { let module = ModuleAST {

View File

@ -1,16 +1,6 @@
use std::{ use std::{fs, path::Path};
fs,
path::{Path, PathBuf},
};
use crate::{ use crate::{codegen, error_handling::PrintableError, lexic, syntax, token::Token};
codegen,
error_handling::PrintableError,
lexic, semantic,
symbol_table::{self, SymbolTable},
syntax,
token::Token,
};
pub fn compile_file(input: &String, output: &String) { pub fn compile_file(input: &String, output: &String) {
let input_path = Path::new(input); let input_path = Path::new(input);
@ -48,12 +38,7 @@ fn build_ast(input: &String, tokens: Vec<Token>) -> String {
let ast = syntax::construct_ast(&tokens); let ast = syntax::construct_ast(&tokens);
match ast { match ast {
Ok(ast) => { Ok(ast) => codegen::codegen(&ast),
let mut symbol_table = SymbolTable::new();
semantic::check_ast(&ast, &mut symbol_table);
codegen::codegen(&ast)
}
Err(reason) => { Err(reason) => {
let chars: Vec<char> = input.chars().into_iter().collect(); let chars: Vec<char> = input.chars().into_iter().collect();
panic!("{}", reason.get_error_str(&chars)) panic!("{}", reason.get_error_str(&chars))

View File

@ -1,32 +0,0 @@
// Module to handle the repl and its compilation
mod repl;
// Defines the types of tokens and provides functions to create them
mod token;
// Module to handle lexical analysis
mod syntax;
// Module to handle syntactic analysis
mod lexic;
// Module to handle semantic analysis
mod semantic;
// Defines the AST
mod ast_types;
// Defines the Symbol table and operations within
mod symbol_table;
// Transforms an AST to JS
mod codegen;
mod utils;
mod error_handling;
use error_handling::MistiError;
use token::Token;
pub use token::TokenType;
pub fn tokenize(input: &String) -> Result<Vec<Token>, MistiError> {
lexic::get_tokens(input)
}
pub fn repl() {
let _ = repl::run();
}

View File

@ -10,12 +10,8 @@ mod token;
mod syntax; mod syntax;
// Module to handle syntactic analysis // Module to handle syntactic analysis
mod lexic; mod lexic;
// Module to handle semantic analysis
mod semantic;
// Defines the AST // Defines the AST
mod ast_types; mod ast_types;
// Defines the Symbol table and operations within
mod symbol_table;
// Transforms an AST to JS // Transforms an AST to JS
mod codegen; mod codegen;
mod utils; mod utils;
@ -47,7 +43,7 @@ const VERSION: &str = "0.0.5";
fn get_copyright() -> String { fn get_copyright() -> String {
format!( format!(
"Misti {}\nCopyright (c) 2023 Fernando Enrique Araoz Morales\n", "THP {}\nCopyright (c) 2023 Fernando Enrique Araoz Morales\n",
VERSION, VERSION,
) )
} }
@ -62,9 +58,10 @@ fn main() {
let cli = Cli::parse(); let cli = Cli::parse();
match &cli.command { match &cli.command {
Some(Commands::C { file: input, output }) => { Some(Commands::C {
file::compile_file(input, output) file: input,
} output,
}) => file::compile_file(input, output),
Some(Commands::R {}) => { Some(Commands::R {}) => {
println!("{}", get_copyright()); println!("{}", get_copyright());
let _ = repl::run(); let _ = repl::run();

View File

@ -1,21 +1,19 @@
use std::io::{self, Write}; use std::io::{self, Write};
use crate::error_handling::PrintableError; use crate::error_handling::PrintableError;
use crate::symbol_table::SymbolTable;
use crate::token::Token; use crate::token::Token;
use super::codegen; use super::codegen;
use super::lexic; use super::lexic;
use super::semantic;
use super::syntax; use super::syntax;
/// Executes Lexical analysis, handles errors and calls build_ast for the next phase /// Executes Lexical analysis, handles errors and calls build_ast for the next phase
fn compile(input: &String, symbol_table: &mut SymbolTable) { fn compile(input: &String) {
let tokens = lexic::get_tokens(input); let tokens = lexic::get_tokens(input);
match tokens { match tokens {
Ok(tokens) => { Ok(tokens) => {
build_ast(input, tokens, symbol_table); build_ast(input, tokens);
} }
Err(error) => { Err(error) => {
let chars: Vec<char> = input.chars().into_iter().collect(); let chars: Vec<char> = input.chars().into_iter().collect();
@ -27,13 +25,11 @@ fn compile(input: &String, symbol_table: &mut SymbolTable) {
/// Executes Syntax analysis, and for now, Semantic analysis and Code generation. /// Executes Syntax analysis, and for now, Semantic analysis and Code generation.
/// ///
/// Prints the generated code in stdin /// Prints the generated code in stdin
fn build_ast(input: &String, tokens: Vec<Token>, symbol_table: &mut SymbolTable) { fn build_ast(input: &String, tokens: Vec<Token>) {
let ast = syntax::construct_ast(&tokens); let ast = syntax::construct_ast(&tokens);
match ast { match ast {
Ok(ast) => { Ok(ast) => {
semantic::check_ast(&ast, symbol_table);
let js_code = codegen::codegen(&ast); let js_code = codegen::codegen(&ast);
println!("{}", js_code) println!("{}", js_code)
} }
@ -48,7 +44,6 @@ fn build_ast(input: &String, tokens: Vec<Token>, symbol_table: &mut SymbolTable)
pub fn run() -> io::Result<()> { pub fn run() -> io::Result<()> {
let stdin = io::stdin(); let stdin = io::stdin();
let mut buffer = String::new(); let mut buffer = String::new();
let mut repl_symbol_table = SymbolTable::new();
println!("REPL: Enter expressions to evaluate. Type Ctrl-D to exit."); println!("REPL: Enter expressions to evaluate. Type Ctrl-D to exit.");
loop { loop {
@ -63,7 +58,7 @@ pub fn run() -> io::Result<()> {
break Ok(()); break Ok(());
} }
Ok(_) => { Ok(_) => {
compile(&buffer, &mut repl_symbol_table); compile(&buffer);
} }
Err(error) => { Err(error) => {
eprintln!("Error reading stdin."); eprintln!("Error reading stdin.");

View File

@ -1,72 +0,0 @@
use std::collections::HashMap;
use crate::semantic::Datatype;
pub struct SymbolTable {
/// For now just stores identifiers and datatypes
table: HashMap<String, Datatype>,
}
impl SymbolTable {
pub fn new() -> SymbolTable {
let symbol_table = HashMap::<String, Datatype>::new();
SymbolTable {
table: symbol_table,
}
}
pub fn insert(&mut self, identifier: &str, datatype: Datatype) {
self.table.insert(String::from(identifier), datatype);
}
pub fn has_id(&self, identifier: &String) -> bool {
return self.table.contains_key::<String>(identifier);
}
pub fn check_type(&self, identifier: &String, datatype: Datatype) -> bool {
self.table
.get(identifier)
.and_then(|value| {
if *value == datatype {
Some(true)
} else {
Some(false)
}
})
.unwrap_or(false)
}
/// Returns the Datatype of a given identifier
pub fn get_type(&self, identifier: &String) -> Option<&Datatype> {
self.table.get(identifier).and_then(|value| Some(value))
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn should_create() {
let mut _table = SymbolTable::new();
}
#[test]
fn should_add_identifier() {
let mut table = SymbolTable::new();
table.insert("identifier", Datatype::num());
let s = String::from("identifier");
assert_eq!(true, table.has_id(&s))
}
#[test]
fn should_check_type() {
let mut table = SymbolTable::new();
table.insert("firstNumber", Datatype::num());
let s = String::from("firstNumber");
assert!(table.check_type(&s, Datatype::num()));
}
}

View File

@ -109,13 +109,13 @@ pub fn try_parse<'a>(tokens: &'a Vec<Token>, pos: usize) -> Option<SyntaxResult>
let binding = if is_val { let binding = if is_val {
Binding::Val(ValBinding { Binding::Val(ValBinding {
datatype: datatype_annotation, datatype: datatype_annotation,
identifier: &identifier.value, identifier: Box::new(identifier.value.clone()),
expression, expression,
}) })
} else { } else {
Binding::Var(VarBinding { Binding::Var(VarBinding {
datatype: datatype_annotation, datatype: datatype_annotation,
identifier: &identifier.value, identifier: Box::new(identifier.value.clone()),
expression, expression,
}) })
}; };
@ -158,7 +158,7 @@ mod tests {
match binding { match binding {
SyntaxResult::Ok(Binding::Val(binding)) => { SyntaxResult::Ok(Binding::Val(binding)) => {
assert_eq!("identifier", binding.identifier); assert_eq!("identifier", format!("{}", binding.identifier));
} }
_ => panic!(), _ => panic!(),
} }
@ -197,7 +197,7 @@ mod tests {
match binding { match binding {
SyntaxResult::Ok(Binding::Val(binding)) => { SyntaxResult::Ok(Binding::Val(binding)) => {
assert_eq!(Some(String::from("Num")), binding.datatype); assert_eq!(Some(String::from("Num")), binding.datatype);
assert_eq!("identifier", binding.identifier); assert_eq!("identifier", format!("{}", binding.identifier));
} }
_ => panic!(), _ => panic!(),
} }
@ -208,7 +208,7 @@ mod tests {
match binding { match binding {
SyntaxResult::Ok(Binding::Var(binding)) => { SyntaxResult::Ok(Binding::Var(binding)) => {
assert_eq!(Some(String::from("Bool")), binding.datatype); assert_eq!(Some(String::from("Bool")), binding.datatype);
assert_eq!("identifier", binding.identifier); assert_eq!("identifier", format!("{}", binding.identifier));
} }
_ => panic!(), _ => panic!(),
} }

View File

@ -9,12 +9,12 @@ use crate::token::{Token, TokenType};
/// - An identifier /// - An identifier
pub fn try_parse(tokens: &Vec<Token>, pos: usize) -> Option<Expression> { pub fn try_parse(tokens: &Vec<Token>, pos: usize) -> Option<Expression> {
tokens.get(pos).and_then(|token| match token.token_type { tokens.get(pos).and_then(|token| match token.token_type {
TokenType::Number => Some(Expression::Number(&token.value)), TokenType::Number => Some(Expression::Number(Box::new(token.value.clone()))),
TokenType::String => Some(Expression::String(&token.value)), TokenType::String => Some(Expression::String(Box::new(token.value.clone()))),
TokenType::Identifier if token.value == "true" || token.value == "false" => { TokenType::Identifier if token.value == "true" || token.value == "false" => {
Some(Expression::Boolean(token.value == "true")) Some(Expression::Boolean(token.value == "true"))
} }
TokenType::Identifier => Some(Expression::Identifier(&token.value)), TokenType::Identifier => Some(Expression::Identifier(Box::new(token.value.clone()))),
_ => None, _ => None,
}) })
} }
@ -30,7 +30,7 @@ mod tests {
let expression = try_parse(&tokens, 0).unwrap(); let expression = try_parse(&tokens, 0).unwrap();
match expression { match expression {
Expression::Number(value) => assert_eq!("40", value), Expression::Number(value) => assert_eq!("40", format!("{}", value)),
_ => panic!(), _ => panic!(),
} }
} }
@ -41,7 +41,7 @@ mod tests {
let expression = try_parse(&tokens, 0).unwrap(); let expression = try_parse(&tokens, 0).unwrap();
match expression { match expression {
Expression::String(value) => assert_eq!("\"Hello\"", value), Expression::String(value) => assert_eq!("\"Hello\"", format!("{}", value)),
_ => panic!(), _ => panic!(),
} }
} }
@ -63,7 +63,7 @@ mod tests {
let expression = try_parse(&tokens, 0).unwrap(); let expression = try_parse(&tokens, 0).unwrap();
match expression { match expression {
Expression::Identifier(value) => assert_eq!("someIdentifier", value), Expression::Identifier(value) => assert_eq!("someIdentifier", format!("{}", value)),
_ => panic!(), _ => panic!(),
} }
} }

View File

@ -9,10 +9,10 @@ use super::ast_types;
use ast_types::ModuleAST; use ast_types::ModuleAST;
pub enum SyntaxResult<'a> { pub enum SyntaxResult {
/// ///
/// A construct has been found /// A construct has been found
Ok(Binding<'a>), Ok(Binding),
/// ///
/// No construct was found /// No construct was found
None, None,
@ -22,7 +22,7 @@ pub enum SyntaxResult<'a> {
} }
/// Constructs the Misti AST from a vector of tokens /// Constructs the Misti AST from a vector of tokens
pub fn construct_ast<'a>(tokens: &'a Vec<Token>) -> Result<ModuleAST<'a>, MistiError> { pub fn construct_ast<'a>(tokens: &'a Vec<Token>) -> Result<ModuleAST, MistiError> {
let _token_amount = tokens.len(); let _token_amount = tokens.len();
let mut current_pos = 0; let mut current_pos = 0;