diff --git a/Cargo.toml b/Cargo.toml index bf50572..4e703a6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -13,4 +13,3 @@ lspower = "1.5.0" tokio = { version = "1.38.0", features = ["full"] } tokio-macros = "2.3.0" rand = "0.8.5" -lsp-client-rs = "0.1.0" diff --git a/src/lsp.rs b/src/lsp.rs index 5011cf9..3d860b9 100644 --- a/src/lsp.rs +++ b/src/lsp.rs @@ -1,17 +1,41 @@ // use std::collections::HashMap; // use std::fs; +use std::collections::HashMap; use std::vec; - use lspower::{self, LspService, Server}; use lspower::jsonrpc::Result; use lspower::lsp::{self, *}; use lspower::{Client, LanguageServer}; - +use rand::{thread_rng, Rng}; +use crate::parser::{new_vars, Variable}; +use crate::transpiler::Transpiler; #[derive(Debug)] struct Backend { - client: Client, + client: Client +} + +#[derive(Debug)] +struct DocumentManager { + documents: HashMap, // Key: Document URI, Value: Document content +} + +impl DocumentManager { + fn new() -> DocumentManager { + DocumentManager { + documents: HashMap::new() + } + } + fn update_document(&mut self, params: DidChangeTextDocumentParams) { + let uri = params.text_document.uri.to_string(); // Convert URI to string + let content = params.content_changes.last().unwrap().text.clone(); // Access latest content + self.documents.insert(uri, content); + } + + fn get_document(&self, uri: &str) -> Option<&str> { + self.documents.get(uri).map(|x| x.as_str()) + } } #[lspower::async_trait] @@ -38,9 +62,23 @@ impl LanguageServer for Backend { async fn completion( &self, - _params: lsp::CompletionParams, + params: lsp::CompletionParams, ) -> lspower::jsonrpc::Result> { - let completion_items: Vec = Vec::new(); + // let document_manager = &self.document; + // let uri = params.text_document_position.text_document.uri.to_string(); + // let document_content = document_manager.get_document(&uri).unwrap_or_default(); // Handle missing document + + // let variables = get_completion( + // document_content.to_string(), + // params.text_document_position.position.line as usize + 1, + // params.text_document_position.position.character as usize, + // ); + + let mut completion_items: Vec = Vec::new(); + // for (name, _) in variables { + // completion_items.push(CompletionItem::new_simple(name, "".to_string())); + // } + Ok(Some(CompletionResponse::Array(completion_items))) } @@ -54,21 +92,40 @@ pub async fn run_lsp_server() { let stdin = tokio::io::stdin(); let stdout = tokio::io::stdout(); - let (service, messages) = LspService::new(|client| Backend { client }); + let (service, messages) = LspService::new(|client| Backend {client}); Server::new(stdin, stdout) .interleave(messages) .serve(service) .await; } -// #[tokio::main] -// pub async fn run_lsp_server() { -// let mut transpiler = Transpiler { -// var_match: String::from("x"), -// var_state: LexerState { line: 6, column: 9 }, -// ..Default::default() -// }; -// let file_content = fs::read_to_string("main.wt").expect("Error reading file"); -// transpiler.transpile(file_content, 0, HashMap::new()); -// println!("{:?}", transpiler.matched_vars); -// } +pub fn place_at(input: String, in2: String, line_goal: usize, column_goal: usize) -> String { + let mut line: usize = 1; + let mut column: usize = 0; + let mut out = String::new(); + for c in input.chars() { + out+=c.to_string().as_str(); + column += 1; + if c == '\n' { + line += 1; + column = 0; + } else if line == line_goal && column == column_goal { + out += in2.as_str(); + column+=1 + } + } + out +} + +pub fn get_completion(input: String, line: usize, column: usize) -> HashMap { + let rand_id: u32 = thread_rng().gen(); + let rand_id: String = rand_id.to_string(); + let mut transpiler = Transpiler { + peek: rand_id.clone(), + ..Default::default() + }; + transpiler.transpile( + place_at(input, rand_id, line, column) + , 0, new_vars()); + transpiler.matched_vars +} \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index c28678f..da92d62 100644 --- a/src/main.rs +++ b/src/main.rs @@ -4,6 +4,7 @@ mod lsp; mod parser; mod transpiler; use clap::Parser; +use parser::new_vars; use std::{fs, path::Path}; use transpiler::Transpiler; @@ -35,7 +36,7 @@ fn main() { } fs::create_dir("build").expect("error making build"); let mut trsp = Transpiler::default(); - let transpiled_code = trsp.transpile(file_content, 0); + let transpiled_code = trsp.transpile(file_content, 0, new_vars()); match args.rust { Some(ref rust_file_name) => { diff --git a/src/parser.rs b/src/parser.rs index c81a6d7..4ff95dc 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -1,7 +1,7 @@ -use crate::lexer::{Token, TokenType}; +use crate::lexer::{LexerState, Token, TokenType}; use once_cell::sync::Lazy; use regex::Regex; -use std::fmt; +use std::{collections::HashMap, fmt}; #[derive(Clone, Debug, PartialEq, Eq)] pub enum AstType { @@ -63,17 +63,37 @@ pub struct Parser { pub index: u32, pub include_regex: Lazy, pub include_regex_local: Lazy, + pub variables: HashMap, pub json: bool, } +#[derive(Clone, PartialEq, Debug)] +pub enum VariableType { + Var, + Func, + Keyword, +} + +#[derive(Clone, Debug)] +pub struct Variable { + pub vtype: VariableType, + pub state: LexerState, +} + +pub fn new_vars() -> HashMap { + HashMap::from([ + ("void".to_string(), Variable { vtype: VariableType::Keyword, state: LexerState {line:0,column:0}}) + ]) +} + impl Parser { - pub fn new(tokens: Vec) -> Parser { + pub fn new(tokens: Vec, variables: HashMap) -> Parser { Parser { tokens: tokens, index: 0, include_regex: Lazy::new(|| Regex::new(r"^(#include *)<(.*?)>").unwrap()), include_regex_local: Lazy::new(|| Regex::new(r#"^(#include *)"(.*?)""#).unwrap()), - // variables: variables, + variables: variables, json: false, } } @@ -166,6 +186,13 @@ impl Parser { } else { ast_res.ast_type = AstType::FunctionDeceleration; } + self.variables.insert(self.tokens[index + 1].clone().value, Variable { + vtype: VariableType::Func, + state: LexerState { + line: self.tokens[index + 1].clone().line, + column: self.tokens[index + 1].clone().column + } + }); self.index += 3; } else if self.tokens.len() - index > 1 && self.tokens[index + 1].token_type == TokenType::Curly @@ -186,6 +213,13 @@ impl Parser { ast_res.tokens.push(self.tokens[index + 1].clone()); ast_res.ast_type = AstType::VariableDeceleration; self.index += 1; + self.variables.insert(self.tokens[index + 1].clone().value, Variable { + vtype: VariableType::Var, + state: LexerState { + line: self.tokens[index + 1].clone().line, + column: self.tokens[index + 1].clone().column + } + }); } else if self.tokens.len() - index > 2 && self.tokens[index + 2].token_type == TokenType::Identifier && self.tokens[index + 1].token_type == TokenType::Angle @@ -196,6 +230,13 @@ impl Parser { ast_res.tokens[0].value += ">"; ast_res.ast_type = AstType::VariableDeceleration; self.index += 2; + self.variables.insert(self.tokens[index + 1].clone().value, Variable { + vtype: VariableType::Var, + state: LexerState { + line: self.tokens[index + 1].clone().line, + column: self.tokens[index + 1].clone().column + } + }); } else if self.tokens.len() - index > 2 && self.tokens[index + 1].value == "*" && self.tokens[index + 2].token_type == TokenType::Identifier @@ -203,6 +244,13 @@ impl Parser { ast_res.tokens.push(self.tokens[index + 2].clone()); ast_res.ast_type = AstType::PointerDeceleration; self.index += 2; + self.variables.insert(self.tokens[index + 1].clone().value, Variable { + vtype: VariableType::Var, + state: LexerState { + line: self.tokens[index + 1].clone().line, + column: self.tokens[index + 1].clone().column + } + }); } } } diff --git a/src/transpiler.rs b/src/transpiler.rs index e446102..3834433 100644 --- a/src/transpiler.rs +++ b/src/transpiler.rs @@ -1,8 +1,9 @@ use crate::lexer::{lex, LexerState, TokenType}; -use crate::parser::{Ast, AstType, Parser}; +use crate::parser::{new_vars, Ast, AstType, Parser, Variable, VariableType}; +use std::collections::HashMap; use std::fs; -#[derive(Debug, PartialEq, Clone)] +#[derive(Debug, Clone)] pub struct Transpiler { pub state: LexerState, pub auto_mut: bool, @@ -10,6 +11,8 @@ pub struct Transpiler { pub auto_pub: bool, pub macros: Vec, pub modnum: u32, + pub peek: String, + pub matched_vars: HashMap, } impl Default for Transpiler { @@ -21,12 +24,15 @@ impl Default for Transpiler { auto_pub: false, macros: vec![String::from("println")], modnum: 0, + peek: String::new(), + matched_vars: HashMap::new(), } } } impl Transpiler { - pub fn transpile(&mut self, input: String, indent: u32) -> String { + pub fn transpile(&mut self, input: String, indent: u32, variables: HashMap) -> String { + let mut variables = variables; let mut result = String::new(); if indent == 0 { // result += "type int = i32;\n"; @@ -37,12 +43,26 @@ impl Transpiler { match lexer_out { Ok(tokens) => { - let mut full_ast = Parser::new(tokens.clone()); + let mut full_ast = Parser::new(tokens.clone(), variables.clone()); let mut last_ast = Ast { ast_type: AstType::Other, tokens: vec![], }; for ast in full_ast.parse() { + variables = full_ast.variables.clone(); + if ast.ast_type == AstType::Other && ast.tokens[0].token_type == TokenType::Identifier + && ast.tokens[0].value.contains(&self.peek) && self.peek!="" { + + let ctoken = &ast.tokens[0]; + let pname = ctoken.value.split(&self.peek).next().unwrap(); + for (name, var) in variables.clone() { + if ctoken.line > var.state.line || var.vtype != VariableType::Var { + self.matched_vars.insert(name, var); + } + } + self.peek = String::new(); + continue; + } if last_ast.tokens.len() > 0 { let mut fl = 0; for t in &last_ast.tokens { @@ -71,9 +91,9 @@ impl Transpiler { result += format!( "fn {}({}) -> {} {}", ast.tokens[1].value, - self.transpile_round(ast.tokens[2].value.clone(),), + self.transpile_round(ast.tokens[2].value.clone(), variables.clone()), ast.tokens[0].value, - self.transpile(ast.tokens[3].value.clone(), indent + 1) + self.transpile(ast.tokens[3].value.clone(), indent + 1, variables.clone()) ) .as_str(); } else if ast.ast_type == AstType::VoidFunctionDeceleration { @@ -83,8 +103,8 @@ impl Transpiler { result += format!( "fn {}({}) {}", ast.tokens[1].value, - self.transpile_round(ast.tokens[2].value.clone(),), - self.transpile(ast.tokens[3].value.clone(), indent + 1,) + self.transpile_round(ast.tokens[2].value.clone(), variables.clone()), + self.transpile(ast.tokens[3].value.clone(), indent + 1, variables.clone()) ) .as_str(); } else if ast.ast_type == AstType::StructDeceleration { @@ -95,7 +115,7 @@ impl Transpiler { "struct {} {} {}", ast.tokens[0].value, "{\n", - self.transpile_round(ast.tokens[1].value.clone(),) + self.transpile_round(ast.tokens[1].value.clone(), variables.clone()) .trim_end() ) .replace( @@ -123,7 +143,7 @@ impl Transpiler { && ast.tokens[0].token_type == TokenType::Round { result += - format!("({})", self.transpile_round(ast.tokens[0].value.clone(),)) + format!("({})", self.transpile_round(ast.tokens[0].value.clone(), variables.clone())) .as_str(); } else if ast.tokens.len() == 1 && ast.tokens[0].token_type == TokenType::Square { @@ -134,7 +154,7 @@ impl Transpiler { LexerState { line: ast.tokens[0].line, column: ast.tokens[0].column - } + }, variables.clone() ) ) .as_str(); @@ -156,7 +176,7 @@ impl Transpiler { LexerState { line: ast.tokens[0].line, column: ast.tokens[0].column, - }, + }, variables.clone(), ) .as_str(); // } @@ -200,15 +220,15 @@ impl Transpiler { result += format!( "{} {} {}", ast.tokens[0].value.clone(), - self.transpile_round(ast.tokens[1].value.clone(),), - self.transpile(ast.tokens[2].value.clone(), indent + 1,), + self.transpile_round(ast.tokens[1].value.clone(), variables.clone()), + self.transpile(ast.tokens[2].value.clone(), indent + 1, variables.clone()), ) .as_str(); } else if ast.ast_type == AstType::State2 { result += format!( "{} {}", ast.tokens[0].value.clone(), - self.transpile(ast.tokens[1].value.clone(), indent + 1,), + self.transpile(ast.tokens[1].value.clone(), indent + 1, variables.clone()), ) .as_str(); } else if ast.ast_type == AstType::Namespace { @@ -216,7 +236,7 @@ impl Transpiler { "mod {} {}{}{}", &ast.tokens[0].value.clone(), "{", - self.transpile(ast.tokens[1].value.clone(), 0), + self.transpile(ast.tokens[1].value.clone(), 0, variables.clone()), "}" ) .as_str(); @@ -225,7 +245,7 @@ impl Transpiler { "impl {} {}{}{}", &ast.tokens[0].value.clone(), "{", - self.transpile(ast.tokens[1].value.clone(), 0,), + self.transpile(ast.tokens[1].value.clone(), 0, variables.clone()), "}" ) .as_str(); @@ -313,7 +333,7 @@ impl Transpiler { self.clone().modnum ); let file_content = fs::read_to_string(s.to_string() + modfile).expect("Error reading file"); - let transpiled_code = self.transpile(file_content, 0); + let transpiled_code = self.transpile(file_content, 0, new_vars()); fs::write( ("build/".to_string() + modname.as_str()) + ".rs", transpiled_code, @@ -321,12 +341,12 @@ impl Transpiler { .expect("Error writing file"); modname } - pub fn transpile_round(&mut self, input: String) -> String { + pub fn transpile_round(&mut self, input: String, variables: HashMap) -> String { let mut result = String::new(); let lexer_out = lex(input.as_str(), false, self.state); match lexer_out { Ok(tokens) => { - let mut full_ast = Parser::new(tokens.clone()); + let mut full_ast = Parser::new(tokens.clone(), variables.clone()); let mut last_ast = Ast { ast_type: AstType::Other, tokens: vec![], @@ -364,7 +384,7 @@ impl Transpiler { } else if ast.tokens.len() == 1 && ast.tokens[0].token_type == TokenType::Round { result += - format!("({})", self.transpile_round(ast.tokens[0].value.clone(),)) + format!("({})", self.transpile_round(ast.tokens[0].value.clone(), variables.clone())) .as_str(); } else if ast.tokens.len() == 1 && ast.tokens[0].token_type == TokenType::Square { @@ -375,7 +395,7 @@ impl Transpiler { LexerState { line: ast.tokens[0].line, column: ast.tokens[0].column - } + }, variables.clone() ) ) .as_str(); @@ -389,7 +409,7 @@ impl Transpiler { LexerState { line: ast.tokens[0].line, column: ast.tokens[0].column, - }, + }, variables.clone(), ) .as_str(); } else if ast.ast_type == AstType::StructCall { @@ -416,12 +436,12 @@ impl Transpiler { } } - pub fn transpile_square(&mut self, input: String, state: LexerState) -> String { + pub fn transpile_square(&mut self, input: String, state: LexerState, variables: HashMap) -> String { let mut result = String::new(); let lexer_out = lex(input.as_str(), false, state); match lexer_out { Ok(tokens) => { - let mut full_ast = Parser::new(tokens.clone()); + let mut full_ast = Parser::new(tokens.clone(), variables.clone()); let mut last_ast = Ast { ast_type: AstType::Other, tokens: vec![], @@ -457,7 +477,7 @@ impl Transpiler { } else if ast.tokens.len() == 1 && ast.tokens[0].token_type == TokenType::Round { result += - format!("({})", self.transpile_round(ast.tokens[0].value.clone(),)) + format!("({})", self.transpile_round(ast.tokens[0].value.clone(), variables.clone())) .as_str(); } else if ast.tokens.len() == 1 && ast.tokens[0].token_type == TokenType::Square { @@ -468,7 +488,7 @@ impl Transpiler { LexerState { line: ast.tokens[0].line, column: ast.tokens[0].column - } + }, variables.clone() ) ) .as_str(); @@ -482,7 +502,7 @@ impl Transpiler { LexerState { line: ast.tokens[0].line, column: ast.tokens[0].column, - }, + }, variables.clone(), ) .as_str(); } else if ast.ast_type == AstType::StructCall { @@ -506,12 +526,12 @@ impl Transpiler { } } - pub fn transpile_json(&mut self, input: String, state: LexerState) -> String { + pub fn transpile_json(&mut self, input: String, state: LexerState, variables: HashMap) -> String { let mut result = String::new(); let lexer_out = lex(input.as_str(), false, state); match lexer_out { Ok(tokens) => { - let mut full_ast = Parser::new(tokens.clone()); + let mut full_ast = Parser::new(tokens.clone(), variables.clone()); full_ast.json = true; result += "HashMap::from(["; let mut last_ast = Ast { @@ -549,7 +569,7 @@ impl Transpiler { } else if ast.tokens.len() == 1 && ast.tokens[0].token_type == TokenType::Round { result += - format!("({})", self.transpile_round(ast.tokens[0].value.clone(),)) + format!("({})", self.transpile_round(ast.tokens[0].value.clone(), variables.clone())) .as_str(); } else if ast.tokens.len() == 1 && ast.tokens[0].token_type == TokenType::Square { @@ -560,7 +580,7 @@ impl Transpiler { LexerState { line: ast.tokens[0].line, column: ast.tokens[0].column - } + }, variables.clone() ) ) .as_str(); @@ -572,7 +592,7 @@ impl Transpiler { LexerState { line: ast.tokens[0].line, column: ast.tokens[0].column, - }, + }, variables.clone(), ) .as_str(); } else {