Remove lifetimes
This commit is contained in:
parent
4f1fc93ceb
commit
fe8f4f3fd1
16
Cargo.lock
generated
16
Cargo.lock
generated
@ -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"
|
||||
|
@ -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]
|
||||
|
@ -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>),
|
||||
}
|
||||
|
@ -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();
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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 {
|
||||
|
@ -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))
|
||||
|
32
src/lib.rs
32
src/lib.rs
@ -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();
|
||||
}
|
13
src/main.rs
13
src/main.rs
@ -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();
|
||||
|
@ -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.");
|
||||
|
@ -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()));
|
||||
}
|
||||
}
|
@ -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!(),
|
||||
}
|
||||
|
@ -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!(),
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user