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"
checksum = "f051f77a7c8e6957c0696eac88f26b0117e54f52d3fc682ab19397a8812846a4"
[[package]]
name = "misti"
version = "0.0.5"
dependencies = [
"clap",
"colored",
]
[[package]]
name = "once_cell"
version = "1.16.0"
@ -260,6 +252,14 @@ dependencies = [
"winapi-util",
]
[[package]]
name = "thp"
version = "0.0.5"
dependencies = [
"clap",
"colored",
]
[[package]]
name = "unicode-ident"
version = "1.0.5"

View File

@ -1,14 +1,9 @@
[package]
name = "misti"
name = "thp"
version = "0.0.5"
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
[dependencies]

View File

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

View File

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

View File

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

View File

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

View File

@ -1,7 +1,7 @@
use super::Transpilable;
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
/// nodes and leaves of the AST
fn transpile(&self) -> String {
@ -26,8 +26,8 @@ mod tests {
let value = String::from("322");
let binding = Binding::Val(ValBinding {
datatype: None,
identifier: &id,
expression: Expression::Number(&value),
identifier: Box::new(id),
expression: Expression::Number(Box::new(value)),
});
let module = ModuleAST {

View File

@ -1,16 +1,6 @@
use std::{
fs,
path::{Path, PathBuf},
};
use std::{fs, path::Path};
use crate::{
codegen,
error_handling::PrintableError,
lexic, semantic,
symbol_table::{self, SymbolTable},
syntax,
token::Token,
};
use crate::{codegen, error_handling::PrintableError, lexic, syntax, token::Token};
pub fn compile_file(input: &String, output: &String) {
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);
match ast {
Ok(ast) => {
let mut symbol_table = SymbolTable::new();
semantic::check_ast(&ast, &mut symbol_table);
codegen::codegen(&ast)
}
Ok(ast) => codegen::codegen(&ast),
Err(reason) => {
let chars: Vec<char> = input.chars().into_iter().collect();
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;
// 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;
@ -47,7 +43,7 @@ const VERSION: &str = "0.0.5";
fn get_copyright() -> String {
format!(
"Misti {}\nCopyright (c) 2023 Fernando Enrique Araoz Morales\n",
"THP {}\nCopyright (c) 2023 Fernando Enrique Araoz Morales\n",
VERSION,
)
}
@ -62,9 +58,10 @@ fn main() {
let cli = Cli::parse();
match &cli.command {
Some(Commands::C { file: input, output }) => {
file::compile_file(input, output)
}
Some(Commands::C {
file: input,
output,
}) => file::compile_file(input, output),
Some(Commands::R {}) => {
println!("{}", get_copyright());
let _ = repl::run();

View File

@ -1,21 +1,19 @@
use std::io::{self, Write};
use crate::error_handling::PrintableError;
use crate::symbol_table::SymbolTable;
use crate::token::Token;
use super::codegen;
use super::lexic;
use super::semantic;
use super::syntax;
/// 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);
match tokens {
Ok(tokens) => {
build_ast(input, tokens, symbol_table);
build_ast(input, tokens);
}
Err(error) => {
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.
///
/// 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);
match ast {
Ok(ast) => {
semantic::check_ast(&ast, symbol_table);
let js_code = codegen::codegen(&ast);
println!("{}", js_code)
}
@ -48,7 +44,6 @@ fn build_ast(input: &String, tokens: Vec<Token>, symbol_table: &mut SymbolTable)
pub fn run() -> io::Result<()> {
let stdin = io::stdin();
let mut buffer = String::new();
let mut repl_symbol_table = SymbolTable::new();
println!("REPL: Enter expressions to evaluate. Type Ctrl-D to exit.");
loop {
@ -63,7 +58,7 @@ pub fn run() -> io::Result<()> {
break Ok(());
}
Ok(_) => {
compile(&buffer, &mut repl_symbol_table);
compile(&buffer);
}
Err(error) => {
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 {
Binding::Val(ValBinding {
datatype: datatype_annotation,
identifier: &identifier.value,
identifier: Box::new(identifier.value.clone()),
expression,
})
} else {
Binding::Var(VarBinding {
datatype: datatype_annotation,
identifier: &identifier.value,
identifier: Box::new(identifier.value.clone()),
expression,
})
};
@ -158,7 +158,7 @@ mod tests {
match binding {
SyntaxResult::Ok(Binding::Val(binding)) => {
assert_eq!("identifier", binding.identifier);
assert_eq!("identifier", format!("{}", binding.identifier));
}
_ => panic!(),
}
@ -197,7 +197,7 @@ mod tests {
match binding {
SyntaxResult::Ok(Binding::Val(binding)) => {
assert_eq!(Some(String::from("Num")), binding.datatype);
assert_eq!("identifier", binding.identifier);
assert_eq!("identifier", format!("{}", binding.identifier));
}
_ => panic!(),
}
@ -208,7 +208,7 @@ mod tests {
match binding {
SyntaxResult::Ok(Binding::Var(binding)) => {
assert_eq!(Some(String::from("Bool")), binding.datatype);
assert_eq!("identifier", binding.identifier);
assert_eq!("identifier", format!("{}", binding.identifier));
}
_ => panic!(),
}

View File

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

View File

@ -9,10 +9,10 @@ use super::ast_types;
use ast_types::ModuleAST;
pub enum SyntaxResult<'a> {
pub enum SyntaxResult {
///
/// A construct has been found
Ok(Binding<'a>),
Ok(Binding),
///
/// No construct was found
None,
@ -22,7 +22,7 @@ pub enum SyntaxResult<'a> {
}
/// 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 mut current_pos = 0;