Add simple error diagnostic from parser
This commit is contained in:
		
							parent
							
								
									bc59b6f575
								
							
						
					
					
						commit
						6619f1f0a9
					
				
							
								
								
									
										24
									
								
								Cargo.lock
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										24
									
								
								Cargo.lock
									
									
									
										generated
									
									
									
								
							| @ -108,6 +108,12 @@ dependencies = [ | |||||||
|  "windows-sys", |  "windows-sys", | ||||||
| ] | ] | ||||||
| 
 | 
 | ||||||
|  | [[package]] | ||||||
|  | name = "crossbeam-utils" | ||||||
|  | version = "0.8.21" | ||||||
|  | source = "registry+https://github.com/rust-lang/crates.io-index" | ||||||
|  | checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" | ||||||
|  | 
 | ||||||
| [[package]] | [[package]] | ||||||
| name = "dashmap" | name = "dashmap" | ||||||
| version = "5.5.3" | version = "5.5.3" | ||||||
| @ -121,6 +127,20 @@ dependencies = [ | |||||||
|  "parking_lot_core", |  "parking_lot_core", | ||||||
| ] | ] | ||||||
| 
 | 
 | ||||||
|  | [[package]] | ||||||
|  | name = "dashmap" | ||||||
|  | version = "6.1.0" | ||||||
|  | source = "registry+https://github.com/rust-lang/crates.io-index" | ||||||
|  | checksum = "5041cc499144891f3790297212f32a74fb938e5136a14943f338ef9e0ae276cf" | ||||||
|  | dependencies = [ | ||||||
|  |  "cfg-if", | ||||||
|  |  "crossbeam-utils", | ||||||
|  |  "hashbrown", | ||||||
|  |  "lock_api", | ||||||
|  |  "once_cell", | ||||||
|  |  "parking_lot_core", | ||||||
|  | ] | ||||||
|  | 
 | ||||||
| [[package]] | [[package]] | ||||||
| name = "displaydoc" | name = "displaydoc" | ||||||
| version = "0.2.5" | version = "0.2.5" | ||||||
| @ -653,6 +673,8 @@ dependencies = [ | |||||||
| name = "reid-lsp" | name = "reid-lsp" | ||||||
| version = "0.1.0" | version = "0.1.0" | ||||||
| dependencies = [ | dependencies = [ | ||||||
|  |  "dashmap 6.1.0", | ||||||
|  |  "reid", | ||||||
|  "socket", |  "socket", | ||||||
|  "tokio", |  "tokio", | ||||||
|  "tower-lsp", |  "tower-lsp", | ||||||
| @ -903,7 +925,7 @@ dependencies = [ | |||||||
|  "async-trait", |  "async-trait", | ||||||
|  "auto_impl", |  "auto_impl", | ||||||
|  "bytes", |  "bytes", | ||||||
|  "dashmap", |  "dashmap 5.5.3", | ||||||
|  "futures", |  "futures", | ||||||
|  "httparse", |  "httparse", | ||||||
|  "lsp-types", |  "lsp-types", | ||||||
|  | |||||||
| @ -16,7 +16,7 @@ BINARY="$(echo $1 | cut -d'.' -f1)"".out" | |||||||
| 
 | 
 | ||||||
| echo $1 | echo $1 | ||||||
| 
 | 
 | ||||||
| cargo run --example cli $@ && \ | cargo run  --example cli $@ && \ | ||||||
| ./$BINARY ; echo "Return value: ""$?" | ./$BINARY ; echo "Return value: ""$?" | ||||||
| 
 | 
 | ||||||
| ## Command from: clang -v hello.o -o test | ## Command from: clang -v hello.o -o test | ||||||
|  | |||||||
| @ -52,7 +52,5 @@ fn main() { | |||||||
| 
 | 
 | ||||||
|     else_b.terminate(TerminatorKind::Ret(add)).unwrap(); |     else_b.terminate(TerminatorKind::Ret(add)).unwrap(); | ||||||
| 
 | 
 | ||||||
|     dbg!(&context); |  | ||||||
| 
 |  | ||||||
|     context.compile(None, Vec::new()); |     context.compile(None, Vec::new()); | ||||||
| } | } | ||||||
|  | |||||||
| @ -223,7 +223,6 @@ impl Builder { | |||||||
|         unsafe { |         unsafe { | ||||||
|             let mut modules = self.modules.borrow_mut(); |             let mut modules = self.modules.borrow_mut(); | ||||||
|             let module = modules.get_unchecked_mut(module.0); |             let module = modules.get_unchecked_mut(module.0); | ||||||
|             dbg!(module.functions.iter().map(|f| f.data.name.clone()).collect::<Vec<_>>()); |  | ||||||
|             module.functions.iter().find(|f| f.data.name == *name).map(|f| f.value) |             module.functions.iter().find(|f| f.data.name == *name).map(|f| f.value) | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  | |||||||
| @ -123,8 +123,6 @@ impl CompiledModule { | |||||||
|             let llvm_ir = |             let llvm_ir = | ||||||
|                 from_cstring(LLVMPrintModuleToString(self.module_ref)).expect("Unable to print LLVM IR to string"); |                 from_cstring(LLVMPrintModuleToString(self.module_ref)).expect("Unable to print LLVM IR to string"); | ||||||
| 
 | 
 | ||||||
|             println!("{}", llvm_ir); |  | ||||||
| 
 |  | ||||||
|             let mut err = ErrorMessageHolder::null(); |             let mut err = ErrorMessageHolder::null(); | ||||||
|             LLVMVerifyModule( |             LLVMVerifyModule( | ||||||
|                 self.module_ref, |                 self.module_ref, | ||||||
|  | |||||||
| @ -7,3 +7,5 @@ edition = "2024" | |||||||
| socket = "0.0.7" | socket = "0.0.7" | ||||||
| tokio = { version = "1.47.0", features = ["full"] } | tokio = { version = "1.47.0", features = ["full"] } | ||||||
| tower-lsp = "0.20.0" | tower-lsp = "0.20.0" | ||||||
|  | reid = { path = "../reid", version = "1.0.0-beta.2", registry="gitea-teascade", features=[] } | ||||||
|  | dashmap = "6.1.0" | ||||||
|  | |||||||
| @ -57,6 +57,9 @@ export function activate(context: ExtensionContext) { | |||||||
| 
 | 
 | ||||||
| 	client.info("hello"); | 	client.info("hello"); | ||||||
| 
 | 
 | ||||||
|  | 	workspace.onDidOpenTextDocument((e) => { | ||||||
|  | 	}); | ||||||
|  | 
 | ||||||
| 	// Start the client. This will also launch the server
 | 	// Start the client. This will also launch the server
 | ||||||
| 	client.start(); | 	client.start(); | ||||||
| } | } | ||||||
|  | |||||||
| @ -1,19 +1,51 @@ | |||||||
|  | use std::path::PathBuf; | ||||||
|  | 
 | ||||||
|  | use dashmap::DashMap; | ||||||
|  | use reid::ast::lexer::{FullToken, Position}; | ||||||
|  | use reid::{compile_module, parse_module}; | ||||||
| use tower_lsp::jsonrpc::Result; | use tower_lsp::jsonrpc::Result; | ||||||
| use tower_lsp::lsp_types::*; | use tower_lsp::lsp_types::{ | ||||||
|  |     self, CompletionItem, CompletionOptions, CompletionParams, CompletionResponse, Diagnostic, DiagnosticSeverity, | ||||||
|  |     DidChangeTextDocumentParams, DidOpenTextDocumentParams, Hover, HoverContents, HoverParams, HoverProviderCapability, | ||||||
|  |     InitializeParams, InitializeResult, InitializedParams, MarkedString, MessageType, OneOf, Range, ServerCapabilities, | ||||||
|  |     TextDocumentItem, TextDocumentSyncCapability, TextDocumentSyncKind, TextDocumentSyncOptions, | ||||||
|  |     WorkspaceFoldersServerCapabilities, WorkspaceServerCapabilities, | ||||||
|  | }; | ||||||
| use tower_lsp::{Client, LanguageServer, LspService, Server}; | use tower_lsp::{Client, LanguageServer, LspService, Server}; | ||||||
| 
 | 
 | ||||||
| #[derive(Debug)] | #[derive(Debug)] | ||||||
| struct Backend { | struct Backend { | ||||||
|     client: Client, |     client: Client, | ||||||
|  |     tokens: DashMap<String, Vec<FullToken>>, | ||||||
|  |     ast: DashMap<String, reid::ast::Module>, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| #[tower_lsp::async_trait] | #[tower_lsp::async_trait] | ||||||
| impl LanguageServer for Backend { | impl LanguageServer for Backend { | ||||||
|     async fn initialize(&self, _: InitializeParams) -> Result<InitializeResult> { |     async fn initialize(&self, _: InitializeParams) -> Result<InitializeResult> { | ||||||
|  |         self.client | ||||||
|  |             .log_message(MessageType::INFO, "Initializing Reid Language Server") | ||||||
|  |             .await; | ||||||
|  | 
 | ||||||
|  |         let sync = TextDocumentSyncOptions { | ||||||
|  |             open_close: Some(true), | ||||||
|  |             change: Some(TextDocumentSyncKind::FULL), | ||||||
|  |             will_save: None, | ||||||
|  |             will_save_wait_until: None, | ||||||
|  |             save: None, | ||||||
|  |         }; | ||||||
|         Ok(InitializeResult { |         Ok(InitializeResult { | ||||||
|             capabilities: ServerCapabilities { |             capabilities: ServerCapabilities { | ||||||
|                 hover_provider: Some(HoverProviderCapability::Simple(true)), |                 hover_provider: Some(HoverProviderCapability::Simple(true)), | ||||||
|                 completion_provider: Some(CompletionOptions::default()), |                 completion_provider: Some(CompletionOptions { ..Default::default() }), | ||||||
|  |                 text_document_sync: Some(TextDocumentSyncCapability::Options(sync)), | ||||||
|  |                 workspace: Some(WorkspaceServerCapabilities { | ||||||
|  |                     workspace_folders: Some(WorkspaceFoldersServerCapabilities { | ||||||
|  |                         supported: Some(true), | ||||||
|  |                         change_notifications: Some(OneOf::Left(true)), | ||||||
|  |                     }), | ||||||
|  |                     file_operations: None, | ||||||
|  |                 }), | ||||||
|                 ..Default::default() |                 ..Default::default() | ||||||
|             }, |             }, | ||||||
|             ..Default::default() |             ..Default::default() | ||||||
| @ -22,13 +54,146 @@ impl LanguageServer for Backend { | |||||||
| 
 | 
 | ||||||
|     async fn initialized(&self, _: InitializedParams) { |     async fn initialized(&self, _: InitializedParams) { | ||||||
|         self.client |         self.client | ||||||
|             .log_message(MessageType::INFO, "Reid Language Server initialized!") |             .log_message(MessageType::INFO, "Reid Language Server initialized hello!") | ||||||
|             .await; |             .await; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     async fn shutdown(&self) -> Result<()> { |     async fn shutdown(&self) -> Result<()> { | ||||||
|         Ok(()) |         Ok(()) | ||||||
|     } |     } | ||||||
|  | 
 | ||||||
|  |     async fn completion(&self, _: CompletionParams) -> Result<Option<CompletionResponse>> { | ||||||
|  |         Ok(Some(CompletionResponse::Array(vec![ | ||||||
|  |             CompletionItem::new_simple("Hello".to_string(), "Some detail".to_string()), | ||||||
|  |             CompletionItem::new_simple("Bye".to_string(), "More detail".to_string()), | ||||||
|  |         ]))) | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     async fn hover(&self, params: HoverParams) -> Result<Option<Hover>> { | ||||||
|  |         let path = PathBuf::from(params.text_document_position_params.text_document.uri.path()); | ||||||
|  |         let file_name = path.file_name().unwrap().to_str().unwrap().to_owned(); | ||||||
|  |         let tokens = self.tokens.get(&file_name).unwrap(); | ||||||
|  |         let position = params.text_document_position_params.position; | ||||||
|  | 
 | ||||||
|  |         self.client | ||||||
|  |             .log_message( | ||||||
|  |                 MessageType::INFO, | ||||||
|  |                 format!("line {}, col {}", position.line, position.character), | ||||||
|  |             ) | ||||||
|  |             .await; | ||||||
|  |         let token = tokens.iter().find(|tok| { | ||||||
|  |             tok.position.1 == position.line + 1 | ||||||
|  |                 && (tok.position.0 <= position.character + 1 | ||||||
|  |                     && (tok.position.0 + tok.token.len() as u32) > position.character + 1) | ||||||
|  |         }); | ||||||
|  | 
 | ||||||
|  |         Ok(Some(Hover { | ||||||
|  |             contents: HoverContents::Scalar(MarkedString::String(format!("{:?}", token))), | ||||||
|  |             range: None, | ||||||
|  |         })) | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     async fn did_open(&self, params: DidOpenTextDocumentParams) { | ||||||
|  |         self.client.log_message(MessageType::INFO, "opened!").await; | ||||||
|  |         self.recompile(TextDocumentItem { | ||||||
|  |             uri: params.text_document.uri, | ||||||
|  |             language_id: params.text_document.language_id, | ||||||
|  |             version: params.text_document.version, | ||||||
|  |             text: params.text_document.text, | ||||||
|  |         }) | ||||||
|  |         .await | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     async fn did_change(&self, params: DidChangeTextDocumentParams) { | ||||||
|  |         self.client.log_message(MessageType::INFO, "changed!").await; | ||||||
|  |         self.recompile(TextDocumentItem { | ||||||
|  |             text: params.content_changes[0].text.clone(), | ||||||
|  |             uri: params.text_document.uri, | ||||||
|  |             version: params.text_document.version, | ||||||
|  |             language_id: String::new(), | ||||||
|  |         }) | ||||||
|  |         .await | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | impl Backend { | ||||||
|  |     async fn recompile(&self, params: TextDocumentItem) { | ||||||
|  |         let mut map = Default::default(); | ||||||
|  |         let path = PathBuf::from(params.uri.clone().path()); | ||||||
|  |         let file_name = path.file_name().unwrap().to_str().unwrap().to_owned(); | ||||||
|  | 
 | ||||||
|  |         let mut reid_error = None; | ||||||
|  |         let mut tokens = None; | ||||||
|  | 
 | ||||||
|  |         match parse_module(¶ms.text, file_name.clone(), &mut map) { | ||||||
|  |             Ok(module) => { | ||||||
|  |                 self.client | ||||||
|  |                     .log_message(MessageType::INFO, format!("successfully parsed!")) | ||||||
|  |                     .await; | ||||||
|  |                 tokens = Some(module.1.clone()); | ||||||
|  |                 match compile_module(module.0, module.1, &mut map, Some(path), true) { | ||||||
|  |                     Ok(_) => {} | ||||||
|  |                     Err(e) => { | ||||||
|  |                         reid_error = Some(e); | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |             Err(_) => {} | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         if let Some(tokens) = &tokens { | ||||||
|  |             if let Some(reid_error) = reid_error { | ||||||
|  |                 let mut diagnostics = Vec::new(); | ||||||
|  |                 for error in reid_error.errors { | ||||||
|  |                     let meta = error.get_meta(); | ||||||
|  |                     let positions = meta | ||||||
|  |                         .range | ||||||
|  |                         .into_position(&tokens) | ||||||
|  |                         .unwrap_or((Position(0, 0), Position(0, 0))); | ||||||
|  |                     self.client.log_message(MessageType::INFO, format!("{:?}", &meta)).await; | ||||||
|  |                     self.client | ||||||
|  |                         .log_message(MessageType::INFO, format!("{:?}", &tokens)) | ||||||
|  |                         .await; | ||||||
|  |                     self.client | ||||||
|  |                         .log_message(MessageType::INFO, format!("{:?}", &positions)) | ||||||
|  |                         .await; | ||||||
|  | 
 | ||||||
|  |                     diagnostics.push(Diagnostic { | ||||||
|  |                         range: Range { | ||||||
|  |                             start: lsp_types::Position { | ||||||
|  |                                 line: ((positions.0.1 as i32) - 1).max(0) as u32, | ||||||
|  |                                 character: ((positions.0.0 as i32) - 1).max(0) as u32, | ||||||
|  |                             }, | ||||||
|  |                             end: lsp_types::Position { | ||||||
|  |                                 line: ((positions.1.1 as i32) - 1).max(0) as u32, | ||||||
|  |                                 character: ((positions.1.0 as i32) - 1).max(0) as u32, | ||||||
|  |                             }, | ||||||
|  |                         }, | ||||||
|  |                         severity: Some(DiagnosticSeverity::ERROR), | ||||||
|  |                         code: None, | ||||||
|  |                         code_description: None, | ||||||
|  |                         source: Some(error.get_type_str().to_owned()), | ||||||
|  |                         message: format!("{}", error), | ||||||
|  |                         related_information: None, | ||||||
|  |                         tags: None, | ||||||
|  |                         data: None, | ||||||
|  |                     }); | ||||||
|  |                     self.client.log_message(MessageType::INFO, format!("{}", error)).await; | ||||||
|  |                 } | ||||||
|  |                 self.client | ||||||
|  |                     .publish_diagnostics(params.uri.clone(), diagnostics, Some(params.version)) | ||||||
|  |                     .await; | ||||||
|  |             } else { | ||||||
|  |                 self.client | ||||||
|  |                     .publish_diagnostics(params.uri.clone(), Vec::new(), Some(params.version)) | ||||||
|  |                     .await; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         if let Some(tokens) = tokens.take() { | ||||||
|  |             self.tokens.insert(file_name.clone(), tokens); | ||||||
|  |         } | ||||||
|  |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| #[tokio::main] | #[tokio::main] | ||||||
| @ -36,6 +201,10 @@ async fn main() { | |||||||
|     let stdin = tokio::io::stdin(); |     let stdin = tokio::io::stdin(); | ||||||
|     let stdout = tokio::io::stdout(); |     let stdout = tokio::io::stdout(); | ||||||
| 
 | 
 | ||||||
|     let (service, socket) = LspService::new(|client| Backend { client }); |     let (service, socket) = LspService::new(|client| Backend { | ||||||
|  |         client, | ||||||
|  |         ast: DashMap::new(), | ||||||
|  |         tokens: DashMap::new(), | ||||||
|  |     }); | ||||||
|     Server::new(stdin, stdout, socket).serve(service).await; |     Server::new(stdin, stdout, socket).serve(service).await; | ||||||
| } | } | ||||||
|  | |||||||
| @ -10,6 +10,7 @@ edition = "2021" | |||||||
| default = ["color"] | default = ["color"] | ||||||
| 
 | 
 | ||||||
| color = ["colored"] | color = ["colored"] | ||||||
|  | log_output = [] | ||||||
| 
 | 
 | ||||||
| [dependencies] | [dependencies] | ||||||
| ## Make it easier to generate errors | ## Make it easier to generate errors | ||||||
|  | |||||||
| @ -12,7 +12,6 @@ fn main() -> Result<(), std::io::Error> { | |||||||
|             libraries.push(libname); |             libraries.push(libname); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         dbg!(&filename); |  | ||||||
|         let path = PathBuf::from(filename).canonicalize().unwrap(); |         let path = PathBuf::from(filename).canonicalize().unwrap(); | ||||||
|         let parent = path.with_extension(""); |         let parent = path.with_extension(""); | ||||||
|         let llvm_ir_path = parent.with_extension("ll"); |         let llvm_ir_path = parent.with_extension("ll"); | ||||||
| @ -21,6 +20,7 @@ fn main() -> Result<(), std::io::Error> { | |||||||
|         let mir_path = parent.with_extension("mir"); |         let mir_path = parent.with_extension("mir"); | ||||||
|         let asm_path = parent.with_extension("asm"); |         let asm_path = parent.with_extension("asm"); | ||||||
| 
 | 
 | ||||||
|  |         #[cfg(feature = "log_output")] | ||||||
|         let before = std::time::SystemTime::now(); |         let before = std::time::SystemTime::now(); | ||||||
| 
 | 
 | ||||||
|         let text = fs::read_to_string(&path)?; |         let text = fs::read_to_string(&path)?; | ||||||
| @ -31,33 +31,39 @@ fn main() -> Result<(), std::io::Error> { | |||||||
|         match compile_simple(&text, PathBuf::from(&path), Some(cpu), vec![features]) { |         match compile_simple(&text, PathBuf::from(&path), Some(cpu), vec![features]) { | ||||||
|             Ok(( |             Ok(( | ||||||
|                 CompileOutput { |                 CompileOutput { | ||||||
|                     triple, |                     triple: _triple, | ||||||
|                     assembly, |                     assembly, | ||||||
|                     obj_buffer, |                     obj_buffer, | ||||||
|                     llvm_ir, |                     llvm_ir: _llvm_ir, | ||||||
|                 }, |                 }, | ||||||
|                 CustomIRs { llir, mir }, |                 CustomIRs { llir, mir }, | ||||||
|             )) => { |             )) => { | ||||||
|                 println!("{}", llvm_ir); |                 #[cfg(feature = "log_output")] | ||||||
|  |                 { | ||||||
|  |                     println!("{}", _llvm_ir); | ||||||
|  |                     println!("Compiled with triple: {}\n", &_triple); | ||||||
|  |                     println!("Output LLVM IR to {:?}", llvm_ir_path); | ||||||
|  |                     println!("Output Assembly to {:?}", asm_path); | ||||||
|  |                     println!("Output Object-file to {:?}\n", object_path); | ||||||
|  |                     println!("Output LLIR-file to {:?}\n", llir_path); | ||||||
|  |                     println!("Output MIR-file to {:?}\n", mir_path); | ||||||
|  |                 } | ||||||
| 
 | 
 | ||||||
|                 let after = std::time::SystemTime::now(); |                 fs::write(&llvm_ir_path, &_llvm_ir).expect("Could not write LLVM IR -file!"); | ||||||
|                 println!("Compiled with triple: {}\n", &triple); |  | ||||||
|                 fs::write(&llvm_ir_path, &llvm_ir).expect("Could not write LLVM IR -file!"); |  | ||||||
|                 println!("Output LLVM IR to {:?}", llvm_ir_path); |  | ||||||
|                 fs::write(&asm_path, &assembly).expect("Could not write Assembly-file!"); |                 fs::write(&asm_path, &assembly).expect("Could not write Assembly-file!"); | ||||||
|                 println!("Output Assembly to {:?}", asm_path); |  | ||||||
|                 fs::write(&object_path, &obj_buffer).expect("Could not write Object-file!"); |                 fs::write(&object_path, &obj_buffer).expect("Could not write Object-file!"); | ||||||
|                 println!("Output Object-file to {:?}\n", object_path); |  | ||||||
|                 fs::write(&llir_path, &llir).expect("Could not write LLIR-file!"); |                 fs::write(&llir_path, &llir).expect("Could not write LLIR-file!"); | ||||||
|                 println!("Output LLIR-file to {:?}\n", llir_path); |  | ||||||
|                 fs::write(&mir_path, &mir).expect("Could not write MIR-file!"); |                 fs::write(&mir_path, &mir).expect("Could not write MIR-file!"); | ||||||
|                 println!("Output MIR-file to {:?}\n", mir_path); |                 #[cfg(feature = "log_output")] | ||||||
|                 println!( |                 { | ||||||
|                     "Compilation took: {:.2}ms\n", |                     let after = std::time::SystemTime::now(); | ||||||
|                     (after.duration_since(before).unwrap().as_micros() as f32) / 1000. |                     println!( | ||||||
|                 ); |                         "Compilation took: {:.2}ms\n", | ||||||
|  |                         (after.duration_since(before).unwrap().as_micros() as f32) / 1000. | ||||||
|  |                     ); | ||||||
| 
 | 
 | ||||||
|                 println!("Linking {:?}", &object_path); |                     println!("Linking {:?}", &object_path); | ||||||
|  |                 } | ||||||
| 
 | 
 | ||||||
|                 let linker = std::env::var("LD").unwrap_or("ld".to_owned()); |                 let linker = std::env::var("LD").unwrap_or("ld".to_owned()); | ||||||
|                 let mut linker = LDRunner::from_command(&linker).with_library("c"); |                 let mut linker = LDRunner::from_command(&linker).with_library("c"); | ||||||
| @ -69,6 +75,7 @@ fn main() -> Result<(), std::io::Error> { | |||||||
|             Err(e) => panic!("{}", e), |             Err(e) => panic!("{}", e), | ||||||
|         }; |         }; | ||||||
|     } else { |     } else { | ||||||
|  |         #[cfg(feature = "log_output")] | ||||||
|         println!("Please input compiled file path!") |         println!("Please input compiled file path!") | ||||||
|     } |     } | ||||||
|     Ok(()) |     Ok(()) | ||||||
|  | |||||||
| @ -42,13 +42,11 @@ impl<'a, 'b> TokenStream<'a, 'b> { | |||||||
|     /// Useful in conjunction with [`TokenStream::next`]
 |     /// Useful in conjunction with [`TokenStream::next`]
 | ||||||
|     pub fn expecting_err<T: Into<String>>(&mut self, expected: T) -> Result<Error, Error> { |     pub fn expecting_err<T: Into<String>>(&mut self, expected: T) -> Result<Error, Error> { | ||||||
|         let next_token = self.peek().unwrap_or(Token::Eof); |         let next_token = self.peek().unwrap_or(Token::Eof); | ||||||
|  |         let pos = self.next_token(self.position).0; | ||||||
|         Ok(Error::Expected( |         Ok(Error::Expected( | ||||||
|             expected.into(), |             expected.into(), | ||||||
|             next_token, |             next_token, | ||||||
|             TokenRange { |             TokenRange { start: pos, end: pos }, | ||||||
|                 start: self.position, |  | ||||||
|                 end: self.position, |  | ||||||
|             }, |  | ||||||
|         )) |         )) | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| @ -173,7 +171,7 @@ impl<'a, 'b> TokenStream<'a, 'b> { | |||||||
|     pub fn get_range_prev(&self) -> Option<TokenRange> { |     pub fn get_range_prev(&self) -> Option<TokenRange> { | ||||||
|         self.ref_position.as_ref().map(|ref_pos| TokenRange { |         self.ref_position.as_ref().map(|ref_pos| TokenRange { | ||||||
|             start: **ref_pos, |             start: **ref_pos, | ||||||
|             end: self.position - 1, |             end: self.previous_token(self.position).0, | ||||||
|         }) |         }) | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -728,7 +728,6 @@ impl mir::Statement { | |||||||
|             mir::StmtKind::Let(NamedVariableRef(ty, name, meta), mutable, expression) => { |             mir::StmtKind::Let(NamedVariableRef(ty, name, meta), mutable, expression) => { | ||||||
|                 let value = expression.codegen(scope, &state)?.unwrap(); |                 let value = expression.codegen(scope, &state)?.unwrap(); | ||||||
| 
 | 
 | ||||||
|                 dbg!(&scope.allocator, &meta, &value.1); |  | ||||||
|                 let alloca = scope |                 let alloca = scope | ||||||
|                     .allocate(meta, &value.1) |                     .allocate(meta, &value.1) | ||||||
|                     .unwrap() |                     .unwrap() | ||||||
|  | |||||||
| @ -50,7 +50,7 @@ impl ErrorKind { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| impl ErrorKind { | impl ErrorKind { | ||||||
|     fn get_meta(&self) -> Metadata { |     pub fn get_meta(&self) -> Metadata { | ||||||
|         match &self { |         match &self { | ||||||
|             ErrorKind::LexerError(error) => error.metadata, |             ErrorKind::LexerError(error) => error.metadata, | ||||||
|             ErrorKind::ParserError(error) => error.metadata, |             ErrorKind::ParserError(error) => error.metadata, | ||||||
| @ -63,6 +63,18 @@ impl ErrorKind { | |||||||
|             ErrorKind::MacroError(error) => error.metadata, |             ErrorKind::MacroError(error) => error.metadata, | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  | 
 | ||||||
|  |     pub fn get_type_str(&self) -> &str { | ||||||
|  |         match self { | ||||||
|  |             ErrorKind::LexerError(_) => "lexer", | ||||||
|  |             ErrorKind::ParserError(_) => "parser", | ||||||
|  |             ErrorKind::TypeCheckError(_) => "typechecker", | ||||||
|  |             ErrorKind::TypeInferenceError(_) => "type-inferrer", | ||||||
|  |             ErrorKind::LinkerError(_) => "linker", | ||||||
|  |             ErrorKind::MacroError(_) => "macro-pass", | ||||||
|  |             ErrorKind::CodegenError(_) => "codegen", | ||||||
|  |         } | ||||||
|  |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| impl PartialOrd for ErrorKind { | impl PartialOrd for ErrorKind { | ||||||
| @ -120,7 +132,7 @@ impl ErrorModules { | |||||||
| #[derive(Debug, Clone, PartialEq)] | #[derive(Debug, Clone, PartialEq)] | ||||||
| pub struct ReidError { | pub struct ReidError { | ||||||
|     map: ErrorModules, |     map: ErrorModules, | ||||||
|     errors: Vec<ErrorKind>, |     pub errors: Vec<ErrorKind>, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| impl ReidError { | impl ReidError { | ||||||
| @ -185,9 +197,7 @@ impl std::fmt::Display for ReidError { | |||||||
|             let module = self.map.module(&meta.source_module_id); |             let module = self.map.module(&meta.source_module_id); | ||||||
|             let position = if let Some(module) = module { |             let position = if let Some(module) = module { | ||||||
|                 if let Some(tokens) = &module.tokens { |                 if let Some(tokens) = &module.tokens { | ||||||
|                     let range_tokens = meta.range.into_tokens(&tokens); |                     meta.range.into_position(tokens).or(meta.position.map(|p| (p, p))) | ||||||
| 
 |  | ||||||
|                     get_position(&range_tokens).or(meta.position.map(|p| (p, p))) |  | ||||||
|                 } else if let Some(position) = meta.position { |                 } else if let Some(position) = meta.position { | ||||||
|                     Some((position, position)) |                     Some((position, position)) | ||||||
|                 } else { |                 } else { | ||||||
| @ -237,6 +247,11 @@ impl TokenRange { | |||||||
|             .take(self.end + 1 - self.start) |             .take(self.end + 1 - self.start) | ||||||
|             .collect::<Vec<_>>() |             .collect::<Vec<_>>() | ||||||
|     } |     } | ||||||
|  | 
 | ||||||
|  |     pub fn into_position<'v>(&self, tokens: &'v Vec<FullToken>) -> Option<(Position, Position)> { | ||||||
|  |         let tokens = self.into_tokens(tokens); | ||||||
|  |         get_position(&tokens) | ||||||
|  |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| fn get_position(tokens: &Vec<&FullToken>) -> Option<(Position, Position)> { | fn get_position(tokens: &Vec<&FullToken>) -> Option<(Position, Position)> { | ||||||
|  | |||||||
| @ -26,12 +26,11 @@ impl LDRunner { | |||||||
|         let dyn_linker_path = find_objectfile(&self.dynamic_linker); |         let dyn_linker_path = find_objectfile(&self.dynamic_linker); | ||||||
|         let crt1_path = find_objectfile("crt1.o"); |         let crt1_path = find_objectfile("crt1.o"); | ||||||
| 
 | 
 | ||||||
|  |         #[cfg(feature = "log_output")] | ||||||
|         println!("LDRunner: Using dynamic linker at: {:?}", dyn_linker_path); |         println!("LDRunner: Using dynamic linker at: {:?}", dyn_linker_path); | ||||||
| 
 | 
 | ||||||
|         let mut ld = Command::new(&self.command); |         let mut ld = Command::new(&self.command); | ||||||
|         ld.arg("-dynamic-linker") |         ld.arg("-dynamic-linker").arg(dyn_linker_path).arg(crt1_path); | ||||||
|             .arg(dyn_linker_path) |  | ||||||
|             .arg(crt1_path); |  | ||||||
| 
 | 
 | ||||||
|         for library in &self.libraries { |         for library in &self.libraries { | ||||||
|             ld.arg(format!("-l{}", library)); |             ld.arg(format!("-l{}", library)); | ||||||
| @ -41,22 +40,21 @@ impl LDRunner { | |||||||
|             .arg("-o") |             .arg("-o") | ||||||
|             .arg(out_path.to_str().unwrap()); |             .arg(out_path.to_str().unwrap()); | ||||||
| 
 | 
 | ||||||
|  |         #[cfg(feature = "log_output")] | ||||||
|         println!( |         println!( | ||||||
|             "LDRunner: Executing linker to objfile at {:?} => {:?}", |             "LDRunner: Executing linker to objfile at {:?} => {:?}", | ||||||
|             input_path, out_path |             input_path, out_path | ||||||
|         ); |         ); | ||||||
|  |         #[cfg(feature = "log_output")] | ||||||
|         dbg!(&ld); |         dbg!(&ld); | ||||||
| 
 | 
 | ||||||
|         ld.spawn().expect("Unable to execute ld!"); |         ld.spawn().expect("Unable to execute ld!"); | ||||||
| 
 | 
 | ||||||
|         thread::sleep(Duration::from_millis(100)); |         thread::sleep(Duration::from_millis(100)); | ||||||
| 
 | 
 | ||||||
|  |         #[cfg(feature = "log_output")] | ||||||
|         println!("Setting executable bit to {:?}..", out_path); |         println!("Setting executable bit to {:?}..", out_path); | ||||||
|         Command::new("chmod") |         Command::new("chmod").arg("+x").arg(out_path).spawn().unwrap(); | ||||||
|             .arg("+x") |  | ||||||
|             .arg(out_path) |  | ||||||
|             .spawn() |  | ||||||
|             .unwrap(); |  | ||||||
|         thread::sleep(Duration::from_millis(100)); |         thread::sleep(Duration::from_millis(100)); | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  | |||||||
| @ -72,7 +72,7 @@ use crate::{ | |||||||
|     mir::macros::{form_macros, MacroModule, MacroPass}, |     mir::macros::{form_macros, MacroModule, MacroPass}, | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| mod ast; | pub mod ast; | ||||||
| mod codegen; | mod codegen; | ||||||
| pub mod error_raporting; | pub mod error_raporting; | ||||||
| pub mod ld; | pub mod ld; | ||||||
| @ -93,6 +93,7 @@ pub fn parse_module<'map, T: Into<String>>( | |||||||
|     map.set_tokens(id, tokens.clone()); |     map.set_tokens(id, tokens.clone()); | ||||||
| 
 | 
 | ||||||
|     #[cfg(debug_assertions)] |     #[cfg(debug_assertions)] | ||||||
|  |     #[cfg(feature = "log_output")] | ||||||
|     println!("{:#?}", &tokens); |     println!("{:#?}", &tokens); | ||||||
| 
 | 
 | ||||||
|     Ok((id, tokens)) |     Ok((id, tokens)) | ||||||
| @ -127,6 +128,7 @@ pub fn compile_module<'map>( | |||||||
|     }; |     }; | ||||||
| 
 | 
 | ||||||
|     #[cfg(debug_assertions)] |     #[cfg(debug_assertions)] | ||||||
|  |     #[cfg(feature = "log_output")] | ||||||
|     dbg!(&ast_module); |     dbg!(&ast_module); | ||||||
| 
 | 
 | ||||||
|     Ok(ast_module.process(module_id)) |     Ok(ast_module.process(module_id)) | ||||||
| @ -137,9 +139,11 @@ pub fn perform_all_passes<'map>( | |||||||
|     module_map: &'map mut ErrorModules, |     module_map: &'map mut ErrorModules, | ||||||
| ) -> Result<(), ReidError> { | ) -> Result<(), ReidError> { | ||||||
|     #[cfg(debug_assertions)] |     #[cfg(debug_assertions)] | ||||||
|  |     #[cfg(feature = "log_output")] | ||||||
|     dbg!(&context); |     dbg!(&context); | ||||||
| 
 | 
 | ||||||
|     #[cfg(debug_assertions)] |     #[cfg(debug_assertions)] | ||||||
|  |     #[cfg(feature = "log_output")] | ||||||
|     println!("{:#}", &context); |     println!("{:#}", &context); | ||||||
| 
 | 
 | ||||||
|     let state = context.pass(&mut LinkerPass { |     let state = context.pass(&mut LinkerPass { | ||||||
| @ -154,10 +158,13 @@ pub fn perform_all_passes<'map>( | |||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     #[cfg(debug_assertions)] |     #[cfg(debug_assertions)] | ||||||
|  |     #[cfg(feature = "log_output")] | ||||||
|     println!("{:-^100}", "LINKER OUTPUT"); |     println!("{:-^100}", "LINKER OUTPUT"); | ||||||
|     #[cfg(debug_assertions)] |     #[cfg(debug_assertions)] | ||||||
|  |     #[cfg(feature = "log_output")] | ||||||
|     println!("{:#}", &context); |     println!("{:#}", &context); | ||||||
|     #[cfg(debug_assertions)] |     #[cfg(debug_assertions)] | ||||||
|  |     #[cfg(feature = "log_output")] | ||||||
|     dbg!(&state); |     dbg!(&state); | ||||||
| 
 | 
 | ||||||
|     if !state.errors.is_empty() { |     if !state.errors.is_empty() { | ||||||
| @ -179,10 +186,13 @@ pub fn perform_all_passes<'map>( | |||||||
|     let state = context.pass(&mut macro_pass)?; |     let state = context.pass(&mut macro_pass)?; | ||||||
| 
 | 
 | ||||||
|     #[cfg(debug_assertions)] |     #[cfg(debug_assertions)] | ||||||
|  |     #[cfg(feature = "log_output")] | ||||||
|     println!("{:-^100}", "MACRO OUTPUT"); |     println!("{:-^100}", "MACRO OUTPUT"); | ||||||
|     #[cfg(debug_assertions)] |     #[cfg(debug_assertions)] | ||||||
|  |     #[cfg(feature = "log_output")] | ||||||
|     println!("{:#}", &context); |     println!("{:#}", &context); | ||||||
|     #[cfg(debug_assertions)] |     #[cfg(debug_assertions)] | ||||||
|  |     #[cfg(feature = "log_output")] | ||||||
|     dbg!(&state); |     dbg!(&state); | ||||||
| 
 | 
 | ||||||
|     if !state.errors.is_empty() { |     if !state.errors.is_empty() { | ||||||
| @ -217,12 +227,16 @@ pub fn perform_all_passes<'map>( | |||||||
|     let state = context.pass(&mut TypeInference { refs: &mut refs })?; |     let state = context.pass(&mut TypeInference { refs: &mut refs })?; | ||||||
| 
 | 
 | ||||||
|     #[cfg(debug_assertions)] |     #[cfg(debug_assertions)] | ||||||
|  |     #[cfg(feature = "log_output")] | ||||||
|     println!("{:-^100}", "TYPE INFERRER OUTPUT"); |     println!("{:-^100}", "TYPE INFERRER OUTPUT"); | ||||||
|     #[cfg(debug_assertions)] |     #[cfg(debug_assertions)] | ||||||
|  |     #[cfg(feature = "log_output")] | ||||||
|     println!("{}", &refs); |     println!("{}", &refs); | ||||||
|     #[cfg(debug_assertions)] |     #[cfg(debug_assertions)] | ||||||
|  |     #[cfg(feature = "log_output")] | ||||||
|     println!("{:#}", &context); |     println!("{:#}", &context); | ||||||
|     #[cfg(debug_assertions)] |     #[cfg(debug_assertions)] | ||||||
|  |     #[cfg(feature = "log_output")] | ||||||
|     dbg!(&state); |     dbg!(&state); | ||||||
| 
 | 
 | ||||||
|     if !state.errors.is_empty() { |     if !state.errors.is_empty() { | ||||||
| @ -239,10 +253,13 @@ pub fn perform_all_passes<'map>( | |||||||
|     let state = context.pass(&mut TypeCheck { refs: &refs })?; |     let state = context.pass(&mut TypeCheck { refs: &refs })?; | ||||||
| 
 | 
 | ||||||
|     #[cfg(debug_assertions)] |     #[cfg(debug_assertions)] | ||||||
|  |     #[cfg(feature = "log_output")] | ||||||
|     println!("{:-^100}", "TYPECHECKER OUTPUT"); |     println!("{:-^100}", "TYPECHECKER OUTPUT"); | ||||||
|     #[cfg(debug_assertions)] |     #[cfg(debug_assertions)] | ||||||
|  |     #[cfg(feature = "log_output")] | ||||||
|     println!("{:#}", &context); |     println!("{:#}", &context); | ||||||
|     #[cfg(debug_assertions)] |     #[cfg(debug_assertions)] | ||||||
|  |     #[cfg(feature = "log_output")] | ||||||
|     dbg!(&state); |     dbg!(&state); | ||||||
| 
 | 
 | ||||||
|     if !state.errors.is_empty() { |     if !state.errors.is_empty() { | ||||||
| @ -280,8 +297,10 @@ pub fn compile_and_pass<'map>( | |||||||
|     perform_all_passes(&mut mir_context, module_map)?; |     perform_all_passes(&mut mir_context, module_map)?; | ||||||
| 
 | 
 | ||||||
|     #[cfg(debug_assertions)] |     #[cfg(debug_assertions)] | ||||||
|  |     #[cfg(feature = "log_output")] | ||||||
|     println!("{:-^100}", "FINAL OUTPUT"); |     println!("{:-^100}", "FINAL OUTPUT"); | ||||||
|     #[cfg(debug_assertions)] |     #[cfg(debug_assertions)] | ||||||
|  |     #[cfg(feature = "log_output")] | ||||||
|     println!("{:#}", &mir_context); |     println!("{:#}", &mir_context); | ||||||
| 
 | 
 | ||||||
|     let mut context = Context::new(format!("Reid ({})", env!("CARGO_PKG_VERSION"))); |     let mut context = Context::new(format!("Reid ({})", env!("CARGO_PKG_VERSION"))); | ||||||
| @ -291,6 +310,7 @@ pub fn compile_and_pass<'map>( | |||||||
|     }; |     }; | ||||||
| 
 | 
 | ||||||
|     #[cfg(debug_assertions)] |     #[cfg(debug_assertions)] | ||||||
|  |     #[cfg(feature = "log_output")] | ||||||
|     println!("{}", &codegen_modules.context); |     println!("{}", &codegen_modules.context); | ||||||
| 
 | 
 | ||||||
|     let compiled = codegen_modules.compile(cpu, features); |     let compiled = codegen_modules.compile(cpu, features); | ||||||
|  | |||||||
| @ -41,16 +41,7 @@ impl Metadata { | |||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     pub fn into_positions(&self, tokens: &Vec<FullToken>) -> Option<(Position, Position)> { |     pub fn into_positions(&self, tokens: &Vec<FullToken>) -> Option<(Position, Position)> { | ||||||
|         let mut iter = tokens |         self.range.into_position(tokens) | ||||||
|             .iter() |  | ||||||
|             .skip(self.range.start) |  | ||||||
|             .take(self.range.end - self.range.start); |  | ||||||
|         if let Some(first) = iter.next() { |  | ||||||
|             let last = iter.last().unwrap_or(first); |  | ||||||
|             Some((first.position, last.position.add(last.token.len() as u32))) |  | ||||||
|         } else { |  | ||||||
|             None |  | ||||||
|         } |  | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user