From 7f3088579b7dee51db3b5a57ca6d468a1fc54aaa Mon Sep 17 00:00:00 2001 From: Ahmetcan Aksu Date: Wed, 6 Mar 2024 21:22:06 +0300 Subject: [PATCH 01/30] Remove unnecessary libraries from ellie-core with vm feature & implement robust debugger launch config --- .vscode/extensions.json | 3 +- .vscode/settings.json | 1 + Ellie-Core-Library | 2 +- ellie_engine/Cargo.toml | 2 +- ellie_engine/core/Cargo.toml | 10 ++-- ellie_engine/core/src/defs.rs | 32 +++++++++++- ellie_engine/rustfmt.toml | 2 + elliec/.vscode/launch.json | 96 +++++++++++++++++++++++++++++++++++ rustfmt.toml | 2 + 9 files changed, 140 insertions(+), 10 deletions(-) create mode 100644 ellie_engine/rustfmt.toml create mode 100644 elliec/.vscode/launch.json create mode 100644 rustfmt.toml diff --git a/.vscode/extensions.json b/.vscode/extensions.json index e9857917..edc2da86 100644 --- a/.vscode/extensions.json +++ b/.vscode/extensions.json @@ -9,5 +9,6 @@ "spmeesseman.vscode-taskexplorer", "serayuzgur.crates", "denoland.vscode-deno", - ] + "rioj7.command-variable", + ], } diff --git a/.vscode/settings.json b/.vscode/settings.json index ff95f0c0..4073cf50 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -10,6 +10,7 @@ "editor.smoothScrolling": true, "workbench.editor.labelFormat": "short", "workbench.startupEditor": "readme", + "rust-analyzer.imports.preferNoStd": "true", "files.exclude": { "**/ellie_engine": true, "**/elliec": true, diff --git a/Ellie-Core-Library b/Ellie-Core-Library index 4deba700..8ad56363 160000 --- a/Ellie-Core-Library +++ b/Ellie-Core-Library @@ -1 +1 @@ -Subproject commit 4deba700765f4f33445daa9ca32f6bf9b2270489 +Subproject commit 8ad56363916a275ea1b7cd7dd6b2d02bf4dc410e diff --git a/ellie_engine/Cargo.toml b/ellie_engine/Cargo.toml index c7d55944..9da8a9cc 100644 --- a/ellie_engine/Cargo.toml +++ b/ellie_engine/Cargo.toml @@ -27,7 +27,7 @@ ellie_renderer_utils = { path = "renderer_utils", version = "0.3.0", optional = [features] default = ["vm", "compiler", "fmt", "std"] compiler = ["ellie_tokenizer", "ellie_parser", "ellie_bytecode", "ellie_core/compiler_utils"] -vm = ["ellie_vm", "ellie_vm/std"] +vm = ["ellie_vm"] std = ["ellie_vm/std", "ellie_core/std"] renderer_utils = ["ellie_renderer_utils"] fmt = ["ellie_fmt"] diff --git a/ellie_engine/core/Cargo.toml b/ellie_engine/core/Cargo.toml index fa1f7fa8..d359b3a3 100644 --- a/ellie_engine/core/Cargo.toml +++ b/ellie_engine/core/Cargo.toml @@ -13,16 +13,14 @@ homepage = "https://www.ellie-lang.org" [dependencies] lazy_static = { version = "1.4.0", optional = true } -serde = { version = "1.0", features = ["derive"], default-features = false } -serde_json = { version = "1.0", default-features = false, features = ["alloc"] } +serde = { version = "1.0", features = ["derive"], default-features = false, optional = true } +serde_json = { version = "1.0", default-features = false, features = ["alloc"], optional = true } enum-as-inner = "0.6.0" rand = { version = "0.8.4", optional = true } -regex = { version = "1.9.1", default-features = false, features = [ - "unicode-perl", -] } +regex = { version = "1.9.1", default-features = false, features = ["unicode-perl"], optional = true } [features] default = ["std"] native_addons = [] -compiler_utils = ["rand", "lazy_static"] +compiler_utils = ["rand", "lazy_static", "serde", "serde_json", "regex"] std = [] diff --git a/ellie_engine/core/src/defs.rs b/ellie_engine/core/src/defs.rs index 97196a3d..28e8dfec 100644 --- a/ellie_engine/core/src/defs.rs +++ b/ellie_engine/core/src/defs.rs @@ -1,6 +1,13 @@ -use alloc::{borrow::ToOwned, format, string::String, vec::Vec}; +use alloc::{string::String, vec::Vec}; + +#[cfg(feature = "compiler_utils")] +use alloc::{borrow::ToOwned, format}; use core::fmt::{Display, Error, Formatter}; + +#[cfg(feature = "compiler_utils")] use regex::Regex; + +#[cfg(feature = "compiler_utils")] use serde::{Deserialize, Serialize}; #[cfg(feature = "compiler_utils")] @@ -73,6 +80,14 @@ impl Default for TokenizerOptions { /// A struct that represents a position in a file. /// (line, column) #[derive(PartialEq, Debug, Clone, Copy, Serialize, Deserialize, Default)] +#[cfg(feature = "compiler_utils")] +pub struct CursorPosition(pub usize, pub usize); + + +/// A struct that represents a position in a file. +/// (line, column) +#[cfg(not(feature = "compiler_utils"))] +#[derive(PartialEq, Debug, Clone, Copy, Default)] pub struct CursorPosition(pub usize, pub usize); impl core::fmt::Display for CursorPosition { @@ -116,6 +131,18 @@ impl CursorPosition { /// * `range_start` - Start of range [`CursorPosition`] /// * `range_end` - End of range [`CursorPosition`] #[derive(PartialEq, Debug, Clone, Copy, Serialize, Deserialize, Default)] +#[cfg(feature = "compiler_utils")] +pub struct Cursor { + pub range_start: CursorPosition, + pub range_end: CursorPosition, +} + +/// Cursor position +/// ## Fields +/// * `range_start` - Start of range [`CursorPosition`] +/// * `range_end` - End of range [`CursorPosition`] +#[derive(PartialEq, Debug, Clone, Copy, Default)] +#[cfg(not(feature = "compiler_utils"))] pub struct Cursor { pub range_start: CursorPosition, pub range_end: CursorPosition, @@ -184,6 +211,7 @@ impl Cursor { /// * `major` - Major version [`u8`] /// * `minor` - Minor version [`u8`] /// * `bug` - Bug version [`u8`] +#[cfg(feature = "compiler_utils")] #[derive(Debug, Clone, Serialize, Deserialize)] pub struct Version { pub major: usize, @@ -193,6 +221,7 @@ pub struct Version { pub build_metadata: Option, } +#[cfg(feature = "compiler_utils")] impl PartialEq for Version { fn eq(&self, other: &Self) -> bool { //Ignore bug @@ -200,6 +229,7 @@ impl PartialEq for Version { } } +#[cfg(feature = "compiler_utils")] impl Version { /// Create new [`Version`] from given [`String`] /// ## Arguments diff --git a/ellie_engine/rustfmt.toml b/ellie_engine/rustfmt.toml new file mode 100644 index 00000000..7d06322e --- /dev/null +++ b/ellie_engine/rustfmt.toml @@ -0,0 +1,2 @@ +imports_granularity = "Crate" +error_on_unformatted = true \ No newline at end of file diff --git a/elliec/.vscode/launch.json b/elliec/.vscode/launch.json new file mode 100644 index 00000000..85f7f67d --- /dev/null +++ b/elliec/.vscode/launch.json @@ -0,0 +1,96 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "type": "lldb", + "request": "launch", + "name": "Debug executable 'elliec'", + "cargo": { + "args": [ + "build", + "--bin=elliec", + "--package=elliec" + ], + "filter": { + "name": "elliec", + "kind": "bin" + } + }, + "args": [ + "compile", + "--exclude-std", + "--compile-lib", + "--output-type", + "${input:outputType}", + "--module-name", + "EllieApp", + "-n", + "--show-debug-lines", + "--allow-panics", + "${input:file}", + ], + "cwd": "${workspaceFolder}" + }, + { + "type": "lldb", + "request": "launch", + "name": "Debug unit tests in executable 'elliec'", + "cargo": { + "args": [ + "test", + "--no-run", + "--bin=elliec", + "--package=elliec" + ], + "filter": { + "name": "elliec", + "kind": "bin" + } + }, + "args": [], + "cwd": "${workspaceFolder}" + } + ], + "inputs": [ + { + "id": "outputType", + "type": "pickString", + "description": "The output type", + "options": [ + "bin", + "json", + "byteCode", + "byteCodeAsm", + "depA", + "nop" + ], + "default": "byteCode" + }, + { + "id": "moduleName", + "type": "promptString", + "description": "The module name", + "default": "aEllieApp" + }, + { + "id": "file", + "type": "command", + "command": "extension.commandvariable.file.pickFile", + "args": { + "include": "**/*", + "exclude": "**/target/*", + "display": "fileName", + "description": "Pick a file to debug", + "fromFolder": { + "predefined ": [ + "${workspaceFolder}/../", + "${workspaceFolder}/../Ellie-Core-Library" + ] + } + } + } + ] +} \ No newline at end of file diff --git a/rustfmt.toml b/rustfmt.toml new file mode 100644 index 00000000..7d06322e --- /dev/null +++ b/rustfmt.toml @@ -0,0 +1,2 @@ +imports_granularity = "Crate" +error_on_unformatted = true \ No newline at end of file From 7d9938741946f7e7ed519d0e465cb403915282be Mon Sep 17 00:00:00 2001 From: Ahmetcan Aksu Date: Wed, 6 Mar 2024 21:23:34 +0300 Subject: [PATCH 02/30] Remove unnecessary clones from vm --- ellie_engine/bytecode/src/assembler.rs | 2 +- ellie_engine/vm/src/instructions/A2S.rs | 12 ++++++++++++ ellie_engine/vm/src/instructions/FN.rs | 1 + ellie_engine/vm/src/instructions/STA.rs | 4 ++-- ellie_engine/vm/src/instructions/STB.rs | 4 ++-- ellie_engine/vm/src/instructions/STC.rs | 4 ++-- ellie_engine/vm/src/instructions/STX.rs | 4 ++-- ellie_engine/vm/src/instructions/STY.rs | 4 ++-- ellie_engine/vm/src/raw_type.rs | 4 +++- 9 files changed, 27 insertions(+), 12 deletions(-) diff --git a/ellie_engine/bytecode/src/assembler.rs b/ellie_engine/bytecode/src/assembler.rs index 4700d3fe..545f9ca9 100644 --- a/ellie_engine/bytecode/src/assembler.rs +++ b/ellie_engine/bytecode/src/assembler.rs @@ -594,7 +594,7 @@ impl Assembler { } match self.module.pages.clone().into_iter().find_map(|x| { if page_hash.clone().unwrap().contains(&x.hash) { - x.items.clone().into_iter().find_map(|e| match e { + x.items.into_iter().find_map(|e| match e { ellie_core::definite::items::Collecting::Function(function) => { if &function.name == name { Some(LocalHeader { diff --git a/ellie_engine/vm/src/instructions/A2S.rs b/ellie_engine/vm/src/instructions/A2S.rs index 1595bf4b..38e817b7 100644 --- a/ellie_engine/vm/src/instructions/A2S.rs +++ b/ellie_engine/vm/src/instructions/A2S.rs @@ -55,6 +55,18 @@ impl super::InstructionExecuter for A2S { current_stack.registers.A = StaticRawType::from_heap_reference(current_stack.get_pos()); } + 11 => { + + let class_ref = current_stack.registers.A.to_uint(); + let class = heap_memory.get(&class_ref); + + panic!("Conver: {:#?}, ", class); + + //let data = current_stack.registers.A.to_short().to_string(); + //heap_memory.set(¤t_stack.get_pos(), RawType::generate_string(data)); + //current_stack.registers.A = + // StaticRawType::from_heap_reference(current_stack.get_pos()); + } e => { return Err(ExecuterPanic { reason: ThreadPanicReason::CannotConvertToType(e, 7), diff --git a/ellie_engine/vm/src/instructions/FN.rs b/ellie_engine/vm/src/instructions/FN.rs index 6acd7d4a..1365151b 100644 --- a/ellie_engine/vm/src/instructions/FN.rs +++ b/ellie_engine/vm/src/instructions/FN.rs @@ -63,6 +63,7 @@ impl super::InstructionExecuter for FN { } let index_start = current_stack.registers.X.to_int() as usize + previous_frame_pos; + std::println!("Function call: {}", parameter_count); for i in 0..parameter_count { let pos = current_stack.get_pos() + 3 + i; match stack_memory.get(&(index_start + i)) { diff --git a/ellie_engine/vm/src/instructions/STA.rs b/ellie_engine/vm/src/instructions/STA.rs index 0a3f49dc..c103c7df 100644 --- a/ellie_engine/vm/src/instructions/STA.rs +++ b/ellie_engine/vm/src/instructions/STA.rs @@ -114,7 +114,7 @@ impl super::InstructionExecuter for STA { let start = (entry_size * index) + data_start_idx; start..start + entry_size }; - heap_data.data[index_range.clone()] + heap_data.data[index_range] .copy_from_slice(®ister_bytes); return Ok(ExecuterResult::Continue); } @@ -229,7 +229,7 @@ impl super::InstructionExecuter for STA { let start = (entry_size * index) + data_start_idx; start..start + entry_size }; - heap_data.data[index_range.clone()] + heap_data.data[index_range] .copy_from_slice(®ister_bytes); return Ok(ExecuterResult::Continue); } diff --git a/ellie_engine/vm/src/instructions/STB.rs b/ellie_engine/vm/src/instructions/STB.rs index 6b775a0b..2d5b5899 100644 --- a/ellie_engine/vm/src/instructions/STB.rs +++ b/ellie_engine/vm/src/instructions/STB.rs @@ -114,7 +114,7 @@ impl super::InstructionExecuter for STB { let start = (entry_size * index) + data_start_idx; start..start + entry_size }; - heap_data.data[index_range.clone()] + heap_data.data[index_range] .copy_from_slice(®ister_bytes); return Ok(ExecuterResult::Continue); } @@ -229,7 +229,7 @@ impl super::InstructionExecuter for STB { let start = (entry_size * index) + data_start_idx; start..start + entry_size }; - heap_data.data[index_range.clone()] + heap_data.data[index_range] .copy_from_slice(®ister_bytes); return Ok(ExecuterResult::Continue); } diff --git a/ellie_engine/vm/src/instructions/STC.rs b/ellie_engine/vm/src/instructions/STC.rs index 60b7c3bd..b24ba3b7 100644 --- a/ellie_engine/vm/src/instructions/STC.rs +++ b/ellie_engine/vm/src/instructions/STC.rs @@ -114,7 +114,7 @@ impl super::InstructionExecuter for STC { let start = (entry_size * index) + data_start_idx; start..start + entry_size }; - heap_data.data[index_range.clone()] + heap_data.data[index_range] .copy_from_slice(®ister_bytes); return Ok(ExecuterResult::Continue); } @@ -229,7 +229,7 @@ impl super::InstructionExecuter for STC { let start = (entry_size * index) + data_start_idx; start..start + entry_size }; - heap_data.data[index_range.clone()] + heap_data.data[index_range] .copy_from_slice(®ister_bytes); return Ok(ExecuterResult::Continue); } diff --git a/ellie_engine/vm/src/instructions/STX.rs b/ellie_engine/vm/src/instructions/STX.rs index 3b4b27b5..b14836fe 100644 --- a/ellie_engine/vm/src/instructions/STX.rs +++ b/ellie_engine/vm/src/instructions/STX.rs @@ -114,7 +114,7 @@ impl super::InstructionExecuter for STX { let start = (entry_size * index) + data_start_idx; start..start + entry_size }; - heap_data.data[index_range.clone()] + heap_data.data[index_range] .copy_from_slice(®ister_bytes); return Ok(ExecuterResult::Continue); } @@ -227,7 +227,7 @@ impl super::InstructionExecuter for STX { let start = (entry_size * index) + data_start_idx; start..start + entry_size }; - heap_data.data[index_range.clone()] + heap_data.data[index_range] .copy_from_slice(®ister_bytes); return Ok(ExecuterResult::Continue); } diff --git a/ellie_engine/vm/src/instructions/STY.rs b/ellie_engine/vm/src/instructions/STY.rs index 3e9ae4b0..0088eabe 100644 --- a/ellie_engine/vm/src/instructions/STY.rs +++ b/ellie_engine/vm/src/instructions/STY.rs @@ -114,7 +114,7 @@ impl super::InstructionExecuter for STY { let start = (entry_size * index) + data_start_idx; start..start + entry_size }; - heap_data.data[index_range.clone()] + heap_data.data[index_range] .copy_from_slice(®ister_bytes); return Ok(ExecuterResult::Continue); } @@ -229,7 +229,7 @@ impl super::InstructionExecuter for STY { let start = (entry_size * index) + data_start_idx; start..start + entry_size }; - heap_data.data[index_range.clone()] + heap_data.data[index_range] .copy_from_slice(®ister_bytes); return Ok(ExecuterResult::Continue); } diff --git a/ellie_engine/vm/src/raw_type.rs b/ellie_engine/vm/src/raw_type.rs index b3714636..bcaf291f 100644 --- a/ellie_engine/vm/src/raw_type.rs +++ b/ellie_engine/vm/src/raw_type.rs @@ -322,7 +322,9 @@ impl RawType { pub fn to_bytes(&self) -> Vec { let type_id = self.type_id.to_bytes(); let mut bytes = Vec::from(type_id); - bytes.extend(self.data.clone()); + for byte in &self.data { + bytes.push(*byte); + } bytes } From b1f57fdeeb8f0c4e5a0a5daaf938a1f0d22f63c9 Mon Sep 17 00:00:00 2001 From: Ahmetcan Aksu Date: Wed, 6 Mar 2024 21:24:53 +0300 Subject: [PATCH 03/30] Rewrite deep scan --- ellie_engine/parser/src/extra/item_search.rs | 711 ++++++++++++++++++ ellie_engine/parser/src/extra/mod.rs | 2 + ellie_engine/parser/src/extra/utils.rs | 125 +++ ellie_engine/parser/src/lib.rs | 1 + .../parser/src/processors/definer/array.rs | 268 ++++--- .../parser/src/processors/definer/generic.rs | 221 ++++-- .../src/processors/items/setter_call.rs | 2 +- 7 files changed, 1157 insertions(+), 173 deletions(-) create mode 100644 ellie_engine/parser/src/extra/item_search.rs create mode 100644 ellie_engine/parser/src/extra/mod.rs create mode 100644 ellie_engine/parser/src/extra/utils.rs diff --git a/ellie_engine/parser/src/extra/item_search.rs b/ellie_engine/parser/src/extra/item_search.rs new file mode 100644 index 00000000..4d94d9fd --- /dev/null +++ b/ellie_engine/parser/src/extra/item_search.rs @@ -0,0 +1,711 @@ +use crate::utils::ProcessedPage; +use alloc::vec; +use alloc::vec::Vec; +use ellie_core::definite::items::Collecting; +use ellie_tokenizer::{ + processors::items::Processors, + tokenizer::{Dependency, Page}, +}; + +#[derive(Debug, Clone)] +pub struct FoundPage { + pub raw_page: Option, + pub processed_page: Option, +} + +impl FoundPage { + pub fn new() -> Self { + FoundPage { + raw_page: None, + processed_page: None, + } + } + + pub fn as_raw(&self) -> &Page { + &self.raw_page.as_ref().unwrap() + } + + pub fn as_processed(&self) -> &ProcessedPage { + &self.processed_page.as_ref().unwrap() + } + + pub fn fill(&mut self, page: &Page) { + self.raw_page = Some(page.clone()); + } + + pub fn fill_processed(&mut self, page: ProcessedPage) { + self.processed_page = Some(page); + } +} + +#[derive(Debug, Clone)] +pub struct FoundItem { + raw_item: Option, + processed_item: Option, +} + +impl FoundItem { + pub fn new() -> Self { + FoundItem { + raw_item: None, + processed_item: None, + } + } + + pub fn raw(&self) -> Option<&Processors> { + self.raw_item.as_ref() + } + + pub fn processed(&self) -> Option<&Collecting> { + self.processed_item.as_ref() + } + + pub fn as_raw(&self) -> &Processors { + self.raw_item.as_ref().unwrap() + } + + pub fn as_processed(&self) -> &Collecting { + self.processed_item.as_ref().unwrap() + } + + pub fn found(&self) -> bool { + self.raw_item.is_some() || self.processed_item.is_some() + } + + pub fn fill_raw(&mut self, raw: Processors) { + self.raw_item = Some(raw); + } + + pub fn fill_processed(&mut self, processed: Collecting) { + self.processed_item = Some(processed); + } +} + +#[derive(Debug, Clone)] +pub struct ItemSearchResult { + pub found_item: FoundItem, + pub found_page: FoundPage, +} + +impl ItemSearchResult { + pub fn found(&self) -> bool { + self.found_item.found() + } +} + +pub fn item_search(options: &mut super::utils::DeepSearchOptions) -> ItemSearchResult { + // let mut inner_page = None; + let mut searched: Vec = options.searched.clone(); + + let mut self_dependencies = vec![Dependency { + hash: options.page_id.unwrap(), + ..Default::default() + }]; + + match options + .parser + .as_mut() + .unwrap() + .find_page(options.page_id.unwrap()) + { + Some(page) => { + self_dependencies.extend(page.dependencies.clone()); + //inner_page = page.inner; + } + None => (), + } + + let mut found_item = FoundItem::new(); + let mut found_page = FoundPage::new(); + + let parser = options.parser.take().unwrap(); + + if !searched.contains(&options.page_id.unwrap()) { + for dependency in self_dependencies { + searched.push(dependency.hash); + + if let Some(module_initial_page) = dependency.module { + if !options.search_on_modules { + continue; + } + match parser.find_processed_page_in_module(module_initial_page, dependency.hash) { + Some(page) => { + for item in &page.items { + match item.clone() { + Collecting::Variable(variable) => { + let name_or_hash_met = + options.hash_or_name_matched(variable.hash, &variable.name); + + // Deep link is for global imports like ellieCore + let publicity_met = variable.public + || options.level == 0 + || dependency.deep_link.is_some(); + + let ignore_hash = options.ignore_hash.is_none() + || options.ignore_hash.unwrap() != variable.hash; + + let position_criteria_met = options.position.is_none() + || options.level != 0 + || (options.level == 0 + && options + .position + .unwrap() + .range_start + .is_bigger(&variable.pos.range_start)); + + if name_or_hash_met + && publicity_met + && ignore_hash + && position_criteria_met + { + found_item.fill_processed(item.clone()); + found_page.fill_processed(page.clone()); + } + } + Collecting::Function(function) => { + let name_or_hash_met = + options.hash_or_name_matched(function.hash, &function.name); + + let publicity_met = function.public + || options.level == 0 + || dependency.deep_link.is_some(); + + let ignore_hash = options.ignore_hash.is_none() + || options.ignore_hash.unwrap() != function.hash; + + if name_or_hash_met && publicity_met && ignore_hash { + found_item.fill_processed(item.clone()); + found_page.fill_processed(page.clone()); + } + } + Collecting::Class(class) => { + let name_or_hash_met = + options.hash_or_name_matched(class.hash, &class.name); + + // Deep link is for global imports like ellieCore + let publicity_met = class.public + || options.level == 0 + || dependency.deep_link.is_some(); + + let ignore_hash = options.ignore_hash.is_none() + || options.ignore_hash.unwrap() != class.hash; + + if name_or_hash_met && publicity_met && ignore_hash { + found_item.fill_processed(item.clone()); + found_page.fill_processed(page.clone()); + } + } + Collecting::Import(import) => { + if !import.reference.is_empty() { + let name_or_hash_met = options + .hash_or_name_matched(import.hash, &import.reference); + + let publicity_met = import.public + || options.level == 0 + || dependency.deep_link.is_some(); + + let ignore_hash = options.ignore_hash.is_none() + || options.ignore_hash.unwrap() != import.hash; + + if name_or_hash_met && publicity_met && ignore_hash { + found_item.fill_processed(item.clone()); + found_page.fill_processed(page.clone()); + } + } + } + Collecting::Getter(getter) => { + let name_or_hash_met = + options.hash_or_name_matched(getter.hash, &getter.name); + + // Deep link is for global imports like ellieCore + let publicity_met = getter.public + || options.level == 0 + || dependency.deep_link.is_some(); + + let ignore_hash = options.ignore_hash.is_none() + || options.ignore_hash.unwrap() != getter.hash; + + if name_or_hash_met && publicity_met && ignore_hash { + found_item.fill_processed(item.clone()); + found_page.fill_processed(page.clone()); + } + } + Collecting::Setter(seter) => { + let name_or_hash_met = + options.hash_or_name_matched(seter.hash, &seter.name); + + // Deep link is for global imports like ellieCore + let publicity_met = seter.public + || options.level == 0 + || dependency.deep_link.is_some(); + + let ignore_hash = options.ignore_hash.is_none() + || options.ignore_hash.unwrap() != seter.hash; + + if name_or_hash_met && publicity_met && ignore_hash { + found_item.fill_processed(item.clone()); + found_page.fill_processed(page.clone()); + } + } + Collecting::Enum(r#enum) => { + let name_or_hash_met = + options.hash_or_name_matched(r#enum.hash, &r#enum.name); + + // Deep link is for global imports like ellieCore + let publicity_met = r#enum.public + || options.level == 0 + || dependency.deep_link.is_some(); + + let ignore_hash = options.ignore_hash.is_none() + || options.ignore_hash.unwrap() != r#enum.hash; + + if name_or_hash_met && publicity_met && ignore_hash { + found_item.fill_processed(item.clone()); + found_page.fill_processed(page.clone()); + } + } + Collecting::NativeFunction(native_function) => { + let name_or_hash_met = options.hash_or_name_matched( + native_function.hash, + &native_function.name, + ); + + // Deep link is for global imports like ellieCore + let publicity_met = native_function.public + || options.level == 0 + || dependency.deep_link.is_some(); + + let ignore_hash = options.ignore_hash.is_none() + || options.ignore_hash.unwrap() != native_function.hash; + + if name_or_hash_met && publicity_met && ignore_hash { + found_item.fill_processed(item.clone()); + found_page.fill_processed(page.clone()); + } + } + Collecting::FunctionParameter(function_parameter) => { + let name_or_hash_met = options.hash_or_name_matched( + function_parameter.hash, + &function_parameter.name, + ); + + if name_or_hash_met { + found_item.fill_processed(item.clone()); + found_page.fill_processed(page.clone()); + } + } + Collecting::ConstructorParameter(constructor_parameter) => { + let name_or_hash_met = options.hash_or_name_matched( + constructor_parameter.hash, + &constructor_parameter.name, + ); + + if name_or_hash_met { + found_item.fill_processed(item.clone()); + found_page.fill_processed(page.clone()); + } + } + Collecting::SelfItem(_) => { + if matches!(&options.name_to_search, Some(name) if name == "self") + { + found_item.fill_processed(item.clone()); + found_page.fill_processed(page.clone()); + } + } + _ => (), + } + } + } + None => unreachable!("Broken Page structure"), + } + } + + if dependency.processed && options.search_on_processed && !found_item.found() { + match parser.find_processed_page(dependency.hash) { + Some(page) => { + for item in &page.items { + match item.clone() { + Collecting::Variable(variable) => { + let name_or_hash_met = + options.hash_or_name_matched(variable.hash, &variable.name); + + let publicity_met = variable.public + || options.level == 0 + || dependency.deep_link.is_some(); + + let ignore_hash = options.ignore_hash.is_none() + || options.ignore_hash.unwrap() != variable.hash; + + let position_criteria_met = options.position.is_none() + || options.level != 0 + || (options.level == 0 + && options + .position + .unwrap() + .range_start + .is_bigger(&variable.pos.range_start)); + + if name_or_hash_met + && publicity_met + && ignore_hash + && position_criteria_met + { + found_item.fill_processed(item.clone()); + found_page.fill_processed(page.clone()); + } + } + Collecting::Function(function) => { + let name_or_hash_met = + options.hash_or_name_matched(function.hash, &function.name); + + let publicity_met = function.public + || options.level == 0 + || dependency.deep_link.is_some(); + + let ignore_hash = options.ignore_hash.is_none() + || options.ignore_hash.unwrap() != function.hash; + + if name_or_hash_met && publicity_met && ignore_hash { + found_item.fill_processed(item.clone()); + found_page.fill_processed(page.clone()); + } + } + Collecting::Class(class) => { + let name_or_hash_met = + options.hash_or_name_matched(class.hash, &class.name); + + let publicity_met = class.public + || options.level == 0 + || dependency.deep_link.is_some(); + + let ignore_hash = options.ignore_hash.is_none() + || options.ignore_hash.unwrap() != class.hash; + + if name_or_hash_met && publicity_met && ignore_hash { + found_item.fill_processed(item.clone()); + found_page.fill_processed(page.clone()); + } + } + Collecting::Import(import) => { + if !import.reference.is_empty() { + let name_or_hash_met = options + .hash_or_name_matched(import.hash, &import.reference); + + let publicity_met = import.public + || options.level == 0 + || dependency.deep_link.is_some(); + + let ignore_hash = options.ignore_hash.is_none() + || options.ignore_hash.unwrap() != import.hash; + + if name_or_hash_met && publicity_met && ignore_hash { + found_item.fill_processed(item.clone()); + found_page.fill_processed(page.clone()); + } + } + } + Collecting::Getter(getter) => { + let name_or_hash_met = + options.hash_or_name_matched(getter.hash, &getter.name); + + let publicity_met = getter.public + || options.level == 0 + || dependency.deep_link.is_some(); + + let ignore_hash = options.ignore_hash.is_none() + || options.ignore_hash.unwrap() != getter.hash; + + if name_or_hash_met && publicity_met && ignore_hash { + found_item.fill_processed(item.clone()); + found_page.fill_processed(page.clone()); + } + } + Collecting::Setter(seter) => { + let name_or_hash_met = + options.hash_or_name_matched(seter.hash, &seter.name); + + let publicity_met = seter.public + || options.level == 0 + || dependency.deep_link.is_some(); + + let ignore_hash = options.ignore_hash.is_none() + || options.ignore_hash.unwrap() != seter.hash; + + if name_or_hash_met && publicity_met && ignore_hash { + found_item.fill_processed(item.clone()); + found_page.fill_processed(page.clone()); + } + } + Collecting::Enum(r#enum) => { + let name_or_hash_met = + options.hash_or_name_matched(r#enum.hash, &r#enum.name); + + let publicity_met = r#enum.public + || options.level == 0 + || dependency.deep_link.is_some(); + + let ignore_hash = options.ignore_hash.is_none() + || options.ignore_hash.unwrap() != r#enum.hash; + + if name_or_hash_met && publicity_met && ignore_hash { + found_item.fill_processed(item.clone()); + found_page.fill_processed(page.clone()); + } + } + Collecting::NativeFunction(native_function) => { + let name_or_hash_met = options.hash_or_name_matched( + native_function.hash, + &native_function.name, + ); + + let publicity_met = native_function.public + || options.level == 0 + || dependency.deep_link.is_some(); + + let ignore_hash = options.ignore_hash.is_none() + || options.ignore_hash.unwrap() != native_function.hash; + + if name_or_hash_met && publicity_met && ignore_hash { + found_item.fill_processed(item.clone()); + found_page.fill_processed(page.clone()); + } + } + Collecting::FunctionParameter(function_parameter) => { + let name_or_hash_met = options.hash_or_name_matched( + function_parameter.hash, + &function_parameter.name, + ); + + if name_or_hash_met { + found_item.fill_processed(item.clone()); + found_page.fill_processed(page.clone()); + } + } + Collecting::ConstructorParameter(constructor_parameter) => { + let name_or_hash_met = options.hash_or_name_matched( + constructor_parameter.hash, + &constructor_parameter.name, + ); + + if name_or_hash_met { + found_item.fill_processed(item.clone()); + found_page.fill_processed(page.clone()); + } + } + Collecting::SelfItem(_) => { + if matches!(&options.name_to_search, Some(name) if name == "self") + { + found_item.fill_processed(item.clone()); + found_page.fill_processed(page.clone()); + } + } + _ => (), + } + } + } + None => unreachable!( + "Broken Page structure; Failed to find page {}", + dependency.hash + ), + } + } + + if options.search_on_raw && !found_item.found() { + match parser.find_page(dependency.hash) { + Some(page) => { + for item in page.items.iter() { + match item { + Processors::Variable(variable) => { + let name_or_hash_met = options.hash_or_name_matched( + variable.data.hash, + &variable.data.name, + ); + + let publicity_met = variable.data.public + || options.level == 0 + || dependency.deep_link.is_some(); + + let ignore_hash = options.ignore_hash.is_none() + || options.ignore_hash.unwrap() != variable.data.hash; + + let position_criteria_met = options.position.is_none() + || options.level != 0 + || (options.level == 0 + && options + .position + .unwrap() + .range_start + .is_bigger(&variable.data.pos.range_start)); + + if name_or_hash_met + && publicity_met + && ignore_hash + && position_criteria_met + { + found_item.fill_raw(item.clone()); + found_page.fill(page); + } + } + Processors::Function(function) => { + let name_or_hash_met = options.hash_or_name_matched( + function.data.hash, + &function.data.name, + ); + + let publicity_met = function.data.public + || options.level == 0 + || dependency.deep_link.is_some(); + + let ignore_hash = options.ignore_hash.is_none() + || options.ignore_hash.unwrap() != function.data.hash; + + if name_or_hash_met && publicity_met && ignore_hash { + found_item.fill_raw(item.clone()); + found_page.fill(page); + } + } + Processors::Class(class) => { + let name_or_hash_met = + options.hash_or_name_matched(class.hash, &class.name); + + let publicity_met = class.public + || options.level == 0 + || dependency.deep_link.is_some(); + + let ignore_hash = options.ignore_hash.is_none() + || options.ignore_hash.unwrap() != class.hash; + + if name_or_hash_met && publicity_met && ignore_hash { + found_item.fill_raw(item.clone()); + found_page.fill(page); + } + } + Processors::Import(import) => { + if !import.reference.is_empty() { + let name_or_hash_met = options + .hash_or_name_matched(import.hash, &import.reference); + + let publicity_met = import.public + || options.level == 0 + || dependency.deep_link.is_some(); + + let ignore_hash = options.ignore_hash.is_none() + || options.ignore_hash.unwrap() != import.hash; + + if name_or_hash_met && publicity_met && ignore_hash { + found_item.fill_raw(item.clone()); + found_page.fill(page); + } + } + } + Processors::Getter(getter) => { + let name_or_hash_met = + options.hash_or_name_matched(getter.hash, &getter.name); + + let publicity_met = getter.public + || options.level == 0 + || dependency.deep_link.is_some(); + + let ignore_hash = options.ignore_hash.is_none() + || options.ignore_hash.unwrap() != getter.hash; + + if name_or_hash_met && publicity_met && ignore_hash { + found_item.fill_raw(item.clone()); + found_page.fill(page); + } + } + Processors::Setter(seter) => { + let name_or_hash_met = + options.hash_or_name_matched(seter.hash, &seter.name); + + let publicity_met = seter.public + || options.level == 0 + || dependency.deep_link.is_some(); + + let ignore_hash = options.ignore_hash.is_none() + || options.ignore_hash.unwrap() != seter.hash; + + if name_or_hash_met && publicity_met && ignore_hash { + found_item.fill_raw(item.clone()); + found_page.fill(page); + } + } + Processors::Enum(r#enum) => { + let name_or_hash_met = + options.hash_or_name_matched(r#enum.hash, &r#enum.name); + + let publicity_met = r#enum.public + || options.level == 0 + || dependency.deep_link.is_some(); + + let ignore_hash = options.ignore_hash.is_none() + || options.ignore_hash.unwrap() != r#enum.hash; + + if name_or_hash_met && publicity_met && ignore_hash { + found_item.fill_raw(item.clone()); + found_page.fill(page); + } + } + Processors::FunctionParameter(function_parameter) => { + let name_or_hash_met = options.hash_or_name_matched( + function_parameter.hash, + &function_parameter.name, + ); + + if name_or_hash_met { + found_item.fill_raw(item.clone()); + found_page.fill(page); + } + } + Processors::ConstructorParameter(constructor_parameter) => { + let name_or_hash_met = options.hash_or_name_matched( + constructor_parameter.hash, + &constructor_parameter.name, + ); + + if name_or_hash_met { + found_item.fill_raw(item.clone()); + found_page.fill(page); + } + } + Processors::GenericItem(generic_item) => { + let name_or_hash_met = options.hash_or_name_matched( + generic_item.hash, + &generic_item.generic_name, + ); + + if name_or_hash_met { + found_item.fill_raw(item.clone()); + found_page.fill(page); + } + } + Processors::SelfItem(_) => { + if matches!(&options.name_to_search, Some(name) if name == "self") + { + found_item.fill_raw(item.clone()); + found_page.fill(page); + } + } + _ => (), + } + } + } + None => unreachable!( + "Broken Page structure; Failed to find page {}", + dependency.hash + ), + } + } + + if found_item.found() { + break; + } + options.increase_level(); + } + } + + ItemSearchResult { + found_item, + found_page, + } +} diff --git a/ellie_engine/parser/src/extra/mod.rs b/ellie_engine/parser/src/extra/mod.rs new file mode 100644 index 00000000..df017791 --- /dev/null +++ b/ellie_engine/parser/src/extra/mod.rs @@ -0,0 +1,2 @@ +pub mod utils; +pub mod item_search; \ No newline at end of file diff --git a/ellie_engine/parser/src/extra/utils.rs b/ellie_engine/parser/src/extra/utils.rs new file mode 100644 index 00000000..2d375f3d --- /dev/null +++ b/ellie_engine/parser/src/extra/utils.rs @@ -0,0 +1,125 @@ +use alloc::{string::String, vec::Vec}; +use ellie_core::defs; + +pub struct DeepSearchOptions<'a> { + pub(in crate::extra) parser: Option<&'a mut crate::parser::Parser>, + pub(in crate::extra) page_id: Option, + pub(in crate::extra) searched: Vec, + pub(in crate::extra) level: usize, + pub(in crate::extra) position: Option, + pub(in crate::extra) name_to_search: Option, + pub(in crate::extra) hash_to_search: Option, + pub(in crate::extra) ignore_hash: Option, + pub(in crate::extra) search_on_modules: bool, + pub(in crate::extra) search_on_processed: bool, + pub(in crate::extra) search_on_raw: bool, +} + +impl<'a> DeepSearchOptions<'a> { + pub fn new() -> Self { + Self { + parser: None, + page_id: None, + searched: Vec::new(), + level: 0, + position: None, + name_to_search: None, + hash_to_search: None, + ignore_hash: None, + search_on_modules: false, + search_on_processed: false, + search_on_raw: false, + } + } + + pub fn parser(mut self, parser: &'a mut crate::parser::Parser) -> Self { + self.parser = Some(parser); + self + } + + pub fn page_id(mut self, page_id: usize) -> Self { + self.page_id = Some(page_id); + self + } + + pub fn searched(mut self, searched: Vec) -> Self { + self.searched = searched; + self + } + + pub fn level(mut self, level: usize) -> Self { + self.level = level; + self + } + + pub fn position(mut self, position: defs::Cursor) -> Self { + self.position = Some(position); + self + } + + pub fn search_on_all(mut self) -> Self { + self.search_on_modules = true; + self.search_on_processed = true; + self.search_on_raw = true; + self + } + + pub fn search_on_modules(mut self) -> Self { + self.search_on_modules = true; + self + } + + pub fn search_on_processed(mut self) -> Self { + self.search_on_processed = true; + self + } + + pub fn search_on_raw(mut self) -> Self { + self.search_on_raw = true; + self + } + + pub fn increase_level(&mut self) { + self.level += 1; + } + + pub fn name(mut self, name: String) -> Self { + self.name_to_search = Some(name); + self + } + + pub fn hash(mut self, hash: usize) -> Self { + self.hash_to_search = Some(hash); + self + } + + pub fn ignore_hash(mut self, hash: usize) -> Self { + self.ignore_hash = Some(hash); + self + } + + pub(in crate::extra) fn hash_or_name_matched(&self, hash: usize, name: &str) -> bool { + matches!(self.hash_to_search, Some(hash_to_search) if hash_to_search == hash) + || matches!(&self.name_to_search, Some(name_to_search) if name_to_search == name) + } + + pub fn build(self) -> Self { + if self.parser.is_none() { + panic!("Parser is not set"); + } + + if self.page_id.is_none() { + panic!("Page ID is not set"); + } + + if self.name_to_search.is_none() && self.hash_to_search.is_none() { + panic!("Name or hash to search is not set"); + } + + if !self.search_on_modules && !self.search_on_processed && !self.search_on_raw { + panic!("No search criteria is set"); + } + + self + } +} diff --git a/ellie_engine/parser/src/lib.rs b/ellie_engine/parser/src/lib.rs index dde346e8..fec992e1 100644 --- a/ellie_engine/parser/src/lib.rs +++ b/ellie_engine/parser/src/lib.rs @@ -18,3 +18,4 @@ pub mod deep_search_extensions; pub mod parser; pub mod processors; pub mod utils; +pub mod extra; diff --git a/ellie_engine/parser/src/processors/definer/array.rs b/ellie_engine/parser/src/processors/definer/array.rs index 7d3650b9..3176fad7 100644 --- a/ellie_engine/parser/src/processors/definer/array.rs +++ b/ellie_engine/parser/src/processors/definer/array.rs @@ -1,10 +1,13 @@ -use crate::{deep_search_extensions::resolve_type, parser::DeepSearchItems}; +use crate::{ + deep_search_extensions::resolve_type, + extra::{item_search::item_search, utils::DeepSearchOptions}, +}; use alloc::{borrow::ToOwned, string::ToString, vec}; use ellie_core::{ - definite::{definers, definers::DefinerCollecting}, + definite::{definers, definers::DefinerCollecting, items::Collecting}, error, }; -use ellie_tokenizer::syntax::items::definers::ArrayType; +use ellie_tokenizer::{processors::items::Processors, syntax::items::definers::ArrayType}; impl super::DefinerParserProcessor for ArrayType { fn process( @@ -14,113 +17,190 @@ impl super::DefinerParserProcessor for ArrayType { let mut errors = vec![]; let mut found = DefinerCollecting::Dynamic; - let deep_search_result = options.parser.deep_search( - options.page_id, - "array".to_string(), - options.ignore_hash, - vec![], - 0, - None, + let generic_search = item_search( + &mut DeepSearchOptions::new() + .parser(options.parser) + .page_id(options.page_id) + .search_on_all() + .name("array".to_string()) + .build(), ); - if deep_search_result.found { - match deep_search_result.found_item { - DeepSearchItems::Class(array_class) => match self.rtype.process(options) { - Ok(inner_type) => match self.size.clone() { - Some(array_size) => { - let resolved_deep_size = match resolve_type( - *array_size, - options.page_id, - options.parser, - &mut errors, - Some(self.size_pos), - ) { - Some(e) => e, - None => return Err(errors), - }; + if generic_search.found() { + if let Some(processed_items) = generic_search.found_item.processed() { + match processed_items { + Collecting::Class(array_class) => match self.rtype.process(options) { + Ok(inner_type) => match self.size.clone() { + Some(array_size) => { + let resolved_deep_size = match resolve_type( + *array_size, + options.page_id, + options.parser, + &mut errors, + Some(self.size_pos), + ) { + Some(e) => e, + None => return Err(errors), + }; - if matches!(resolved_deep_size.clone(), DefinerCollecting::Generic(x) if x.rtype == "int") - { + if matches!(resolved_deep_size.clone(), DefinerCollecting::Generic(x) if x.rtype == "int") + { + found = DefinerCollecting::ParentGeneric( + definers::ParentGenericType { + parent_pos: array_class.pos, + generics: vec![definers::GenericParameter { + value: inner_type, + pos: array_class.pos, + }], + hash: array_class.hash, + rtype: "array".to_string(), + }, + ); + } else { + errors.push( + error::error_list::ERROR_S3.clone().build_with_path( + vec![ + error::ErrorBuildField { + key: "token1".to_string(), + value: "int".to_string(), + }, + error::ErrorBuildField { + key: "token2".to_string(), + value: resolved_deep_size.to_string(), + }, + ], + alloc::format!( + "{}:{}:{}", + file!().to_owned(), + line!(), + column!() + ), + options + .parser + .find_page(options.page_id) + .unwrap() + .path + .clone(), + self.size_pos, + ), + ); + return Err(errors); + } + } + None => { found = DefinerCollecting::ParentGeneric(definers::ParentGenericType { parent_pos: array_class.pos, generics: vec![definers::GenericParameter { value: inner_type, - pos: deep_search_result.found_pos.unwrap_or_default(), + pos: array_class.pos, }], hash: array_class.hash, rtype: "array".to_string(), }); - } else { - errors.push( - error::error_list::ERROR_S3.clone().build_with_path( - vec![ - error::ErrorBuildField { - key: "token1".to_string(), - value: "int".to_string(), - }, - error::ErrorBuildField { - key: "token2".to_string(), - value: resolved_deep_size.to_string(), - }, - ], - alloc::format!( - "{}:{}:{}", - file!().to_owned(), - line!(), - column!() - ), - options - .parser - .find_page(options.page_id) - .unwrap() - .path - .clone(), - self.size_pos, - ), - ); - return Err(errors); } - } - None => { - found = DefinerCollecting::ParentGeneric(definers::ParentGenericType { - parent_pos: array_class.pos, - generics: vec![definers::GenericParameter { - value: inner_type, - pos: deep_search_result.found_pos.unwrap_or_default(), - }], - hash: array_class.hash, - rtype: "array".to_string(), - }); - } + }, + Err(e) => errors.extend(e), }, - Err(e) => errors.extend(e), - }, - _ => match deep_search_result.found_pos { - Some(ref_pos) => { - let mut error = error::error_list::ERROR_S45.clone().build_with_path( - vec![error::ErrorBuildField { - key: "token".to_string(), - value: "array".to_string(), - }], - alloc::format!("{}:{}:{}", file!().to_owned(), line!(), column!()), - options - .parser - .find_page(options.page_id) - .unwrap() - .path - .clone(), - self.pos, + _ => { + errors.push( + error::error_list::ERROR_S45.clone().build_with_path( + vec![error::ErrorBuildField { + key: "token".to_owned(), + value: "array".to_string(), + }], + alloc::format!("{}:{}:{}", file!().to_owned(), line!(), column!()), + options + .parser + .find_page(options.page_id) + .unwrap() + .path + .clone(), + self.pos, + ), ); - error.reference_message = "Defined here".to_string(); - error.reference_block = Some((ref_pos, deep_search_result.found_page.path)); - errors.push(error); } - None => { + } + } else if let Some(raw_items) = generic_search.found_item.raw() { + match raw_items { + Processors::Class(array_class) => match self.rtype.process(options) { + Ok(inner_type) => match self.size.clone() { + Some(array_size) => { + let resolved_deep_size = match resolve_type( + *array_size, + options.page_id, + options.parser, + &mut errors, + Some(self.size_pos), + ) { + Some(e) => e, + None => return Err(errors), + }; + + if matches!(resolved_deep_size.clone(), DefinerCollecting::Generic(x) if x.rtype == "int") + { + found = DefinerCollecting::ParentGeneric( + definers::ParentGenericType { + parent_pos: array_class.pos, + generics: vec![definers::GenericParameter { + value: inner_type, + pos: array_class.pos, + }], + hash: array_class.hash, + rtype: "array".to_string(), + }, + ); + } else { + errors.push( + error::error_list::ERROR_S3.clone().build_with_path( + vec![ + error::ErrorBuildField { + key: "token1".to_string(), + value: "int".to_string(), + }, + error::ErrorBuildField { + key: "token2".to_string(), + value: resolved_deep_size.to_string(), + }, + ], + alloc::format!( + "{}:{}:{}", + file!().to_owned(), + line!(), + column!() + ), + options + .parser + .find_page(options.page_id) + .unwrap() + .path + .clone(), + self.size_pos, + ), + ); + return Err(errors); + } + } + None => { + found = + DefinerCollecting::ParentGeneric(definers::ParentGenericType { + parent_pos: array_class.pos, + generics: vec![definers::GenericParameter { + value: inner_type, + pos: array_class.pos, + }], + hash: array_class.hash, + rtype: "array".to_string(), + }); + } + }, + Err(e) => errors.extend(e), + }, + _ => { errors.push( error::error_list::ERROR_S45.clone().build_with_path( vec![error::ErrorBuildField { - key: "token".to_string(), + key: "token".to_owned(), value: "array".to_string(), }], alloc::format!("{}:{}:{}", file!().to_owned(), line!(), column!()), @@ -134,13 +214,15 @@ impl super::DefinerParserProcessor for ArrayType { ), ); } - }, + } + } else { + unreachable!("Something is wrong with item_search, search returned positive but no items were found"); } } else { errors.push( error::error_list::ERROR_S6.clone().build_with_path( vec![error::ErrorBuildField { - key: "token".to_string(), + key: "token".to_owned(), value: "array".to_string(), }], alloc::format!("{}:{}:{}", file!().to_owned(), line!(), column!()), diff --git a/ellie_engine/parser/src/processors/definer/generic.rs b/ellie_engine/parser/src/processors/definer/generic.rs index 9a890832..e0390a42 100644 --- a/ellie_engine/parser/src/processors/definer/generic.rs +++ b/ellie_engine/parser/src/processors/definer/generic.rs @@ -1,9 +1,11 @@ use alloc::{borrow::ToOwned, string::ToString, vec}; use ellie_core::{ - definite::{definers, definers::DefinerCollecting}, + definite::{definers, definers::DefinerCollecting, items::Collecting}, error, }; -use ellie_tokenizer::syntax::items::definers::GenericType; +use ellie_tokenizer::{processors::items::Processors, syntax::items::definers::GenericType}; + +use crate::extra::{item_search::item_search, utils::DeepSearchOptions}; impl super::DefinerParserProcessor for GenericType { fn process( @@ -13,37 +15,76 @@ impl super::DefinerParserProcessor for GenericType { let mut errors = vec![]; let mut found = DefinerCollecting::Dynamic; - let deep_search_result = options.parser.deep_search( - options.page_id, - self.rtype.clone(), - options.ignore_hash, - vec![], - 0, - None, + let generic_search = item_search( + &mut &mut &mut &mut DeepSearchOptions::new() + .parser(options.parser) + .page_id(options.page_id) + .search_on_all() + .name(self.rtype.clone()) + .build(), ); - if deep_search_result.found { - match deep_search_result.found_item { - crate::parser::DeepSearchItems::Class(e) => { - if e.generic_definings.is_empty() { + if generic_search.found() { + if let Some(processed_items) = generic_search.found_item.processed() { + match processed_items { + Collecting::Class(class) => { + if class.generic_definings.is_empty() { + found = DefinerCollecting::Generic(definers::GenericType { + rtype: class.name.clone(), + hash: class.hash, + pos: class.pos, + }); + } else { + errors.push( + error::error_list::ERROR_S44.clone().build_with_path( + vec![ + error::ErrorBuildField { + key: "token".to_owned(), + value: class.generic_definings.len().to_string(), + }, + error::ErrorBuildField { + key: "token2".to_owned(), + value: "0".to_string(), + }, + ], + alloc::format!( + "{}:{}:{}", + file!().to_owned(), + line!(), + column!() + ), + options + .parser + .find_page(options.page_id) + .unwrap() + .path + .clone(), + self.pos, + ), + ); + } + } + Collecting::Generic(generic_data) => { found = DefinerCollecting::Generic(definers::GenericType { - rtype: e.name, - hash: e.hash, - pos: e.pos, + rtype: generic_data.name.clone(), + hash: generic_data.hash, + pos: generic_data.pos, }); - } else { + } + Collecting::Enum(enum_data) => { + found = DefinerCollecting::Generic(definers::GenericType { + rtype: enum_data.name.clone(), + hash: enum_data.hash, + pos: enum_data.pos, + }); + } + _ => { errors.push( - error::error_list::ERROR_S44.clone().build_with_path( - vec![ - error::ErrorBuildField { - key: "token".to_owned(), - value: e.generic_definings.len().to_string(), - }, - error::ErrorBuildField { - key: "token2".to_owned(), - value: "0".to_string(), - }, - ], + error::error_list::ERROR_S45.clone().build_with_path( + vec![error::ErrorBuildField { + key: "token".to_owned(), + value: self.rtype.clone(), + }], alloc::format!("{}:{}:{}", file!().to_owned(), line!(), column!()), options .parser @@ -56,58 +97,80 @@ impl super::DefinerParserProcessor for GenericType { ); } } - crate::parser::DeepSearchItems::BrokenPageGraph => todo!(), - crate::parser::DeepSearchItems::MixUp(_) => todo!(), - crate::parser::DeepSearchItems::None => { - errors.push( - error::error_list::ERROR_S6.clone().build_with_path( - vec![error::ErrorBuildField { - key: "token".to_owned(), - value: self.rtype.clone(), - }], - alloc::format!("{}:{}:{}", file!().to_owned(), line!(), column!()), - options - .parser - .find_page(options.page_id) - .unwrap() - .path - .clone(), - self.pos, - ), - ); - } - crate::parser::DeepSearchItems::GenericItem(generic) => { - found = DefinerCollecting::Generic(definers::GenericType { - rtype: generic.generic_name.clone(), - hash: generic.hash, - pos: generic.pos, - }); - } - crate::parser::DeepSearchItems::Enum(enum_data) => { - found = DefinerCollecting::Generic(definers::GenericType { - rtype: enum_data.name, - hash: enum_data.hash, - pos: enum_data.pos, - }); - } - _ => { - errors.push( - error::error_list::ERROR_S45.clone().build_with_path( - vec![error::ErrorBuildField { - key: "token".to_owned(), - value: self.rtype.clone(), - }], - alloc::format!("{}:{}:{}", file!().to_owned(), line!(), column!()), - options - .parser - .find_page(options.page_id) - .unwrap() - .path - .clone(), - self.pos, - ), - ); + } else if let Some(raw_items) = generic_search.found_item.raw() { + match raw_items { + Processors::Class(class) => { + if class.generic_definings.is_empty() { + found = DefinerCollecting::Generic(definers::GenericType { + rtype: class.name.clone(), + hash: class.hash, + pos: class.pos, + }); + } else { + errors.push( + error::error_list::ERROR_S44.clone().build_with_path( + vec![ + error::ErrorBuildField { + key: "token".to_owned(), + value: class.generic_definings.len().to_string(), + }, + error::ErrorBuildField { + key: "token2".to_owned(), + value: "0".to_string(), + }, + ], + alloc::format!( + "{}:{}:{}", + file!().to_owned(), + line!(), + column!() + ), + options + .parser + .find_page(options.page_id) + .unwrap() + .path + .clone(), + self.pos, + ), + ); + } + } + Processors::GenericItem(generic_data) => { + found = DefinerCollecting::Generic(definers::GenericType { + rtype: generic_data.generic_name.clone(), + hash: generic_data.hash, + pos: generic_data.pos, + }); + } + Processors::Enum(enum_data) => { + found = DefinerCollecting::Generic(definers::GenericType { + rtype: enum_data.name.clone(), + hash: enum_data.hash, + pos: enum_data.pos, + }); + } + _ => { + errors.push( + error::error_list::ERROR_S45.clone().build_with_path( + vec![error::ErrorBuildField { + key: "token".to_owned(), + value: self.rtype.clone(), + }], + alloc::format!("{}:{}:{}", file!().to_owned(), line!(), column!()), + options + .parser + .find_page(options.page_id) + .unwrap() + .path + .clone(), + self.pos, + ), + ); + } } + } else { + unreachable!("Something is wrong with item_search, search returned positive but no items were found"); } } else { errors.push( diff --git a/ellie_engine/parser/src/processors/items/setter_call.rs b/ellie_engine/parser/src/processors/items/setter_call.rs index 124d071f..9100f5f6 100644 --- a/ellie_engine/parser/src/processors/items/setter_call.rs +++ b/ellie_engine/parser/src/processors/items/setter_call.rs @@ -234,7 +234,7 @@ impl super::ItemParserProcessor for SetterCall { match self.value.process( TypeParserProcessorOptions::new( options.parser, - options.page_idx, + options.page_hash, ) .variable_pos(self.target_pos) .build(), From 20b4e3fbef403157550cd2928c067fc9b33daade Mon Sep 17 00:00:00 2001 From: Ahmetcan Aksu Date: Wed, 6 Mar 2024 21:25:54 +0300 Subject: [PATCH 04/30] Prototype of new constructor code --- ellie_engine/bytecode/src/transpiler/mod.rs | 30 +++++++++---------- .../bytecode/src/transpiler/type_resolver.rs | 16 ++++++++++ ellie_engine/parser/src/parser.rs | 6 ++++ .../parser/src/processors/items/class.rs | 24 +++++++++++++-- .../src/processors/items/constructor.rs | 28 ++++++++++------- 5 files changed, 75 insertions(+), 29 deletions(-) diff --git a/ellie_engine/bytecode/src/transpiler/mod.rs b/ellie_engine/bytecode/src/transpiler/mod.rs index f7239dd4..a6955f2e 100644 --- a/ellie_engine/bytecode/src/transpiler/mod.rs +++ b/ellie_engine/bytecode/src/transpiler/mod.rs @@ -1,18 +1,18 @@ -mod class; -mod class_instance; -mod condition; -mod constructor; -mod for_loop; -mod function; -mod function_parameter; -mod getter_call; -mod loop_type; -mod native_function; -mod ret; -mod self_item; -mod setter_call; -mod type_resolver; -mod variable; +pub mod class; +pub mod class_instance; +pub mod condition; +pub mod constructor; +pub mod for_loop; +pub mod function; +pub mod function_parameter; +pub mod getter_call; +pub mod loop_type; +pub mod native_function; +pub mod ret; +pub mod self_item; +pub mod setter_call; +pub mod type_resolver; +pub mod variable; use ellie_parser::parser::ProcessedPage; diff --git a/ellie_engine/bytecode/src/transpiler/type_resolver.rs b/ellie_engine/bytecode/src/transpiler/type_resolver.rs index 81539a5c..7a6cdbdf 100644 --- a/ellie_engine/bytecode/src/transpiler/type_resolver.rs +++ b/ellie_engine/bytecode/src/transpiler/type_resolver.rs @@ -3,6 +3,7 @@ use ellie_core::{ definite::types::{class_instance::AttributeType, operator, Types as CoreTypes}, defs::PlatformArchitecture, }; +use ellie_parser::processors::items::class; use crate::{ assembler::{Assembler, LocalHeader}, @@ -733,6 +734,9 @@ pub fn resolve_type( _ => unreachable!("Unexpected target type"), }; + + // Reserve class variables + assembler .instructions .push(instruction_table::Instructions::ARR(Instruction::implicit())); @@ -792,6 +796,18 @@ pub fn resolve_type( ))); //- + assembler + .instructions + .push(instruction_table::Instructions::LDX( + Instruction::immediate( + Types::Integer, + usize_to_le_bytes( + previous_params_location, + assembler.platform_attributes.architecture, + ), + ), + )); + assembler .instructions .push(instruction_table::Instructions::CALL( diff --git a/ellie_engine/parser/src/parser.rs b/ellie_engine/parser/src/parser.rs index 32f028f1..a240981b 100644 --- a/ellie_engine/parser/src/parser.rs +++ b/ellie_engine/parser/src/parser.rs @@ -622,6 +622,12 @@ impl Parser { defining.to_string(), "dyn".to_owned(), )) + } else if let ellie_core::definite::definers::DefinerCollecting::ParentGeneric(_) = defining { + Ok(CompareResult::result( + true, + defining.to_string(), + "dyn".to_owned(), + )) } else if let ellie_core::definite::definers::DefinerCollecting::Dynamic = defining { if errors.is_empty() { diff --git a/ellie_engine/parser/src/processors/items/class.rs b/ellie_engine/parser/src/processors/items/class.rs index 0cf3ffa3..a39a7573 100644 --- a/ellie_engine/parser/src/processors/items/class.rs +++ b/ellie_engine/parser/src/processors/items/class.rs @@ -4,7 +4,7 @@ use ellie_core::warning; use ellie_core::{defs, error, utils}; use ellie_tokenizer::{ processors::items::Processors, - syntax::items::class::Class, + syntax::items::{class::Class, constructor::Constructor}, tokenizer::{ClassPageType, PageType}, }; @@ -106,6 +106,7 @@ impl super::ItemParserProcessor for Class { let page = options.parser.pages.nth(options.page_idx).unwrap(); let mut constructors = self.body.iter().filter_map(|item| item.as_constructor()); + let mut items = Vec::new(); if let Some(prime) = constructors.next() { let duplicate_constructors = constructors @@ -161,6 +162,25 @@ impl super::ItemParserProcessor for Class { err.semi_assist = true; options.parser.informations.push(&err); } + } else { + // If no constructor exists build one. + + let mut inside_code = Vec::new(); + let mut parameters = Vec::new(); + + let mut constructor = Processors::Constructor( + Constructor { + parameters: todo!(), + inside_code: todo!(), + name_pos: todo!(), + parameters_pos: todo!(), + brace_count: todo!(), + iterator: todo!(), + pos: todo!(), + complete: todo!(), + } + ); + } for (index, generic) in self.generic_definings.iter().enumerate() { @@ -187,8 +207,6 @@ impl super::ItemParserProcessor for Class { let inner_page_id: usize = ellie_core::utils::generate_hash_usize(); - let mut items = Vec::new(); - for generic in self.generic_definings.clone() { items.push(Processors::GenericItem( ellie_tokenizer::syntax::items::generic_item::GenericItem { diff --git a/ellie_engine/parser/src/processors/items/constructor.rs b/ellie_engine/parser/src/processors/items/constructor.rs index 7f0ccdc1..13eef28f 100644 --- a/ellie_engine/parser/src/processors/items/constructor.rs +++ b/ellie_engine/parser/src/processors/items/constructor.rs @@ -76,6 +76,8 @@ impl super::ItemParserProcessor for Constructor { dependencies.extend(page.dependencies); let mut items = Vec::new(); + let mut parameters = Vec::new(); + items.push( ellie_tokenizer::processors::items::Processors::ConstructorParameter( @@ -94,6 +96,13 @@ impl super::ItemParserProcessor for Constructor { ), ); + parameters.push( + ellie_core::definite::items::constructor::ConstructorParameter { + name: "self".to_owned(), + pos: self.pos, + }, + ); + for variable in class_element .body .iter() @@ -201,6 +210,13 @@ impl super::ItemParserProcessor for Constructor { ), ); } + + parameters.push( + ellie_core::definite::items::constructor::ConstructorParameter { + name: parameter.name.clone(), + pos: parameter.pos, + }, + ); } items.extend(self.inside_code.clone()); let inner_page_id: usize = ellie_core::utils::generate_hash_usize(); @@ -218,17 +234,7 @@ impl super::ItemParserProcessor for Constructor { let processed = ellie_core::definite::items::Collecting::Constructor( ellie_core::definite::items::constructor::Constructor { - parameters: self - .parameters - .clone() - .into_iter() - .map( - |x| ellie_core::definite::items::constructor::ConstructorParameter { - name: x.name, - pos: x.pos, - }, - ) - .collect(), + parameters, name_pos: self.name_pos, parameters_pos: self.parameters_pos, pos: self.pos, From c27dfa86c1dce66e95734687b27a77efc52a8e84 Mon Sep 17 00:00:00 2001 From: Ahmetcan Aksu Date: Sun, 10 Mar 2024 13:35:36 +0300 Subject: [PATCH 05/30] Fix parser duplicate items error --- ellie_engine/parser/src/parser.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/ellie_engine/parser/src/parser.rs b/ellie_engine/parser/src/parser.rs index a240981b..edb9edb3 100644 --- a/ellie_engine/parser/src/parser.rs +++ b/ellie_engine/parser/src/parser.rs @@ -1623,7 +1623,6 @@ impl Parser { } pub fn parse(&mut self) -> Module { - self.process_page(self.initial_page); let mut idx = 0; loop { let page = match self.pages.nth(idx) { From d4368f44571c62b28d2a6e4c174c95e888e6ff29 Mon Sep 17 00:00:00 2001 From: Ahmetcan Aksu Date: Sun, 21 Apr 2024 23:15:50 +0300 Subject: [PATCH 06/30] Add new type transpiler implementations --- ellie_engine/bytecode/src/assembler.rs | 91 ++++--- ellie_engine/bytecode/src/instructions.rs | 1 + .../src/transpiler/{ => items}/class.rs | 0 .../transpiler/{ => items}/class_instance.rs | 0 .../src/transpiler/{ => items}/condition.rs | 17 +- .../src/transpiler/{ => items}/constructor.rs | 0 .../src/transpiler/{ => items}/for_loop.rs | 0 .../src/transpiler/{ => items}/function.rs | 8 + .../{ => items}/function_parameter.rs | 0 .../src/transpiler/{ => items}/getter_call.rs | 24 +- .../src/transpiler/{ => items}/loop_type.rs | 17 +- .../bytecode/src/transpiler/items/mod.rs | 34 +++ .../transpiler/{ => items}/native_function.rs | 0 .../bytecode/src/transpiler/items/ret.rs | 47 ++++ .../src/transpiler/{ => items}/self_item.rs | 0 .../src/transpiler/{ => items}/setter_call.rs | 56 ++-- .../transpiler/{ => items}/type_resolver.rs | 1 - .../src/transpiler/{ => items}/variable.rs | 17 +- ellie_engine/bytecode/src/transpiler/mod.rs | 36 +-- ellie_engine/bytecode/src/transpiler/ret.rs | 33 --- .../bytecode/src/transpiler/types/array.rs | 73 ++++++ .../src/transpiler/types/as_keyword.rs | 85 ++++++ .../bytecode/src/transpiler/types/bool.rs | 35 +++ .../src/transpiler/types/brace_reference.rs | 57 ++++ .../bytecode/src/transpiler/types/byte.rs | 35 +++ .../bytecode/src/transpiler/types/char.rs | 35 +++ .../src/transpiler/types/class_call.rs | 149 +++++++++++ .../bytecode/src/transpiler/types/cloak.rs | 63 +++++ .../src/transpiler/types/collective.rs | 9 + .../transpiler/types/constructor_parameter.rs | 40 +++ .../bytecode/src/transpiler/types/decimal.rs | 35 +++ .../bytecode/src/transpiler/types/dynamic.rs | 9 + .../src/transpiler/types/enum_data.rs | 8 + .../bytecode/src/transpiler/types/function.rs | 8 + .../src/transpiler/types/function_call.rs | 177 +++++++++++++ .../transpiler/types/function_parameter.rs | 40 +++ .../bytecode/src/transpiler/types/integer.rs | 35 +++ .../bytecode/src/transpiler/types/mod.rs | 175 +++++++++++++ .../bytecode/src/transpiler/types/negative.rs | 8 + .../bytecode/src/transpiler/types/null.rs | 33 +++ .../src/transpiler/types/null_resolver.rs | 8 + .../bytecode/src/transpiler/types/operator.rs | 247 ++++++++++++++++++ .../src/transpiler/types/reference.rs | 124 +++++++++ .../bytecode/src/transpiler/types/string.rs | 56 ++++ .../src/transpiler/types/variable_type.rs | 40 +++ .../bytecode/src/transpiler/types/void.rs | 33 +++ 46 files changed, 1838 insertions(+), 161 deletions(-) rename ellie_engine/bytecode/src/transpiler/{ => items}/class.rs (100%) rename ellie_engine/bytecode/src/transpiler/{ => items}/class_instance.rs (100%) rename ellie_engine/bytecode/src/transpiler/{ => items}/condition.rs (88%) rename ellie_engine/bytecode/src/transpiler/{ => items}/constructor.rs (100%) rename ellie_engine/bytecode/src/transpiler/{ => items}/for_loop.rs (100%) rename ellie_engine/bytecode/src/transpiler/{ => items}/function.rs (98%) rename ellie_engine/bytecode/src/transpiler/{ => items}/function_parameter.rs (100%) rename ellie_engine/bytecode/src/transpiler/{ => items}/getter_call.rs (71%) rename ellie_engine/bytecode/src/transpiler/{ => items}/loop_type.rs (88%) create mode 100644 ellie_engine/bytecode/src/transpiler/items/mod.rs rename ellie_engine/bytecode/src/transpiler/{ => items}/native_function.rs (100%) create mode 100644 ellie_engine/bytecode/src/transpiler/items/ret.rs rename ellie_engine/bytecode/src/transpiler/{ => items}/self_item.rs (100%) rename ellie_engine/bytecode/src/transpiler/{ => items}/setter_call.rs (87%) rename ellie_engine/bytecode/src/transpiler/{ => items}/type_resolver.rs (99%) rename ellie_engine/bytecode/src/transpiler/{ => items}/variable.rs (89%) delete mode 100644 ellie_engine/bytecode/src/transpiler/ret.rs create mode 100644 ellie_engine/bytecode/src/transpiler/types/array.rs create mode 100644 ellie_engine/bytecode/src/transpiler/types/as_keyword.rs create mode 100644 ellie_engine/bytecode/src/transpiler/types/bool.rs create mode 100644 ellie_engine/bytecode/src/transpiler/types/brace_reference.rs create mode 100644 ellie_engine/bytecode/src/transpiler/types/byte.rs create mode 100644 ellie_engine/bytecode/src/transpiler/types/char.rs create mode 100644 ellie_engine/bytecode/src/transpiler/types/class_call.rs create mode 100644 ellie_engine/bytecode/src/transpiler/types/cloak.rs create mode 100644 ellie_engine/bytecode/src/transpiler/types/collective.rs create mode 100644 ellie_engine/bytecode/src/transpiler/types/constructor_parameter.rs create mode 100644 ellie_engine/bytecode/src/transpiler/types/decimal.rs create mode 100644 ellie_engine/bytecode/src/transpiler/types/dynamic.rs create mode 100644 ellie_engine/bytecode/src/transpiler/types/enum_data.rs create mode 100644 ellie_engine/bytecode/src/transpiler/types/function.rs create mode 100644 ellie_engine/bytecode/src/transpiler/types/function_call.rs create mode 100644 ellie_engine/bytecode/src/transpiler/types/function_parameter.rs create mode 100644 ellie_engine/bytecode/src/transpiler/types/integer.rs create mode 100644 ellie_engine/bytecode/src/transpiler/types/mod.rs create mode 100644 ellie_engine/bytecode/src/transpiler/types/negative.rs create mode 100644 ellie_engine/bytecode/src/transpiler/types/null.rs create mode 100644 ellie_engine/bytecode/src/transpiler/types/null_resolver.rs create mode 100644 ellie_engine/bytecode/src/transpiler/types/operator.rs create mode 100644 ellie_engine/bytecode/src/transpiler/types/reference.rs create mode 100644 ellie_engine/bytecode/src/transpiler/types/string.rs create mode 100644 ellie_engine/bytecode/src/transpiler/types/variable_type.rs create mode 100644 ellie_engine/bytecode/src/transpiler/types/void.rs diff --git a/ellie_engine/bytecode/src/assembler.rs b/ellie_engine/bytecode/src/assembler.rs index 545f9ca9..ae9c95c1 100644 --- a/ellie_engine/bytecode/src/assembler.rs +++ b/ellie_engine/bytecode/src/assembler.rs @@ -1,7 +1,7 @@ use crate::{ instruction_table, instructions::Instruction, - transpiler::Transpiler, + transpiler::items::Transpiler, utils::{limit_platform_size, usize_to_le_bytes}, }; use alloc::{ @@ -10,6 +10,7 @@ use alloc::{ vec::Vec, }; use ellie_core::{ + definite::items::Collecting, defs::{DebugHeader, DebugHeaderType, ModuleMap, NativeCallTrace, PlatformArchitecture}, utils::ExportPage, }; @@ -474,7 +475,7 @@ impl Assembler { match self.module.pages.clone().into_iter().find_map(|x| { if page_hash.clone().unwrap().contains(&x.hash) { x.items.clone().into_iter().find_map(|e| match e { - ellie_core::definite::items::Collecting::Function(function) => { + Collecting::Function(function) => { if function.hash == hash { Some(LocalHeader { name: function.name.clone(), @@ -488,7 +489,7 @@ impl Assembler { None } } - ellie_core::definite::items::Collecting::Variable(variable) => { + Collecting::Variable(variable) => { if variable.hash == hash { Some(LocalHeader { name: variable.name.clone(), @@ -502,7 +503,7 @@ impl Assembler { None } } - ellie_core::definite::items::Collecting::NativeFunction(nfunction) => { + Collecting::NativeFunction(nfunction) => { if nfunction.hash == hash { Some(LocalHeader { name: nfunction.name.clone(), @@ -589,13 +590,23 @@ impl Assembler { match locals.iter_mut().find(|local| &local.name == name) { Some(local) => Some(local.clone()), None => { + std::println!( + "\n-----\npage_hash.is_none() || !borrow: {} {:#?}", + page_hash.is_none() || !borrow, + page_hash + ); if page_hash.is_none() || !borrow { return None; } match self.module.pages.clone().into_iter().find_map(|x| { if page_hash.clone().unwrap().contains(&x.hash) { + std::println!("Page: {:#?} {:#?}", x.path, x.hash); + if x.path.contains("mem") { + std::println!("mem item saerched"); + } + x.items.into_iter().find_map(|e| match e { - ellie_core::definite::items::Collecting::Function(function) => { + Collecting::Function(function) => { if &function.name == name { Some(LocalHeader { name: function.name.clone(), @@ -609,7 +620,7 @@ impl Assembler { None } } - ellie_core::definite::items::Collecting::Variable(variable) => { + Collecting::Variable(variable) => { if &variable.name == name { Some(LocalHeader { name: variable.name.clone(), @@ -623,7 +634,7 @@ impl Assembler { None } } - ellie_core::definite::items::Collecting::NativeFunction(nfunction) => { + Collecting::NativeFunction(nfunction) => { if &nfunction.name == name { Some(LocalHeader { name: nfunction.name.clone(), @@ -637,6 +648,20 @@ impl Assembler { None } } + Collecting::Class(class) => { + if class.name == *name { + Some(LocalHeader { + name: class.name.clone(), + cursor: 0, + reference: Instruction::absolute_static(0), + hash: Some(class.hash), + page_hash: x.hash, + borrowed: Some(Vec::new()), + }) + } else { + None + } + } _ => None, }) } else { @@ -677,10 +702,10 @@ impl Assembler { for item in &processed_page.items { match item { - ellie_core::definite::items::Collecting::Variable(variable) => { + Collecting::Variable(variable) => { variable.transpile(self, processed_page.hash, &processed_page) } - ellie_core::definite::items::Collecting::Function(function) => { + Collecting::Function(function) => { let start = self.instructions.len(); let transpile_res = function.transpile(self, processed_page.hash, &processed_page); @@ -693,51 +718,49 @@ impl Assembler { } transpile_res } - ellie_core::definite::items::Collecting::ForLoop(for_loop) => { + Collecting::ForLoop(for_loop) => { for_loop.transpile(self, processed_page.hash, &processed_page) } - ellie_core::definite::items::Collecting::Condition(condition) => { + Collecting::Condition(condition) => { condition.transpile(self, processed_page.hash, &processed_page) } - ellie_core::definite::items::Collecting::Class(class) => { + Collecting::Class(class) => { class.transpile(self, processed_page.hash, &processed_page) } - ellie_core::definite::items::Collecting::Ret(ret) => { - ret.transpile(self, processed_page.hash, &processed_page) - } - ellie_core::definite::items::Collecting::Constructor(constructor) => { + Collecting::Ret(ret) => ret.transpile(self, processed_page.hash, &processed_page), + Collecting::Constructor(constructor) => { constructor.transpile(self, processed_page.hash, &processed_page) } - ellie_core::definite::items::Collecting::Import(_) => true, - ellie_core::definite::items::Collecting::FileKey(_) => true, - ellie_core::definite::items::Collecting::Getter(_) => todo!(), - ellie_core::definite::items::Collecting::Setter(_) => todo!(), - ellie_core::definite::items::Collecting::Generic(_) => true, - ellie_core::definite::items::Collecting::GetterCall(getter_call) => { + Collecting::Import(_) => true, + Collecting::FileKey(_) => true, + Collecting::Getter(_) => todo!(), + Collecting::Setter(_) => todo!(), + Collecting::Generic(_) => true, + Collecting::GetterCall(getter_call) => { getter_call.transpile(self, processed_page.hash, &processed_page) } - ellie_core::definite::items::Collecting::SetterCall(setter_call) => { + Collecting::SetterCall(setter_call) => { setter_call.transpile(self, processed_page.hash, &processed_page) } - ellie_core::definite::items::Collecting::Enum(_) => todo!(), - ellie_core::definite::items::Collecting::NativeFunction(native_function) => { + Collecting::Enum(_) => todo!(), + Collecting::NativeFunction(native_function) => { native_function.transpile(self, processed_page.hash, &processed_page) } - ellie_core::definite::items::Collecting::None => todo!(), - ellie_core::definite::items::Collecting::Brk(_) => todo!(), - ellie_core::definite::items::Collecting::Go(_) => todo!(), - ellie_core::definite::items::Collecting::FunctionParameter(function_parameter) => { + Collecting::None => todo!(), + Collecting::Brk(_) => todo!(), + Collecting::Go(_) => todo!(), + Collecting::FunctionParameter(function_parameter) => { function_parameter.transpile(self, processed_page.hash, &processed_page) } - ellie_core::definite::items::Collecting::ConstructorParameter(_) => true, - ellie_core::definite::items::Collecting::SelfItem(self_item) => { + Collecting::ConstructorParameter(_) => true, + Collecting::SelfItem(self_item) => { self_item.transpile(self, processed_page.hash, &processed_page) } - ellie_core::definite::items::Collecting::Extend(_) => true, - ellie_core::definite::items::Collecting::Loop(loop_type) => { + Collecting::Extend(_) => true, + Collecting::Loop(loop_type) => { loop_type.transpile(self, processed_page.hash, &processed_page) } - ellie_core::definite::items::Collecting::ClassInstance(class_instance) => { + Collecting::ClassInstance(class_instance) => { class_instance.transpile(self, processed_page.hash, &processed_page) } }; diff --git a/ellie_engine/bytecode/src/instructions.rs b/ellie_engine/bytecode/src/instructions.rs index 16481fa6..e4ca58d2 100644 --- a/ellie_engine/bytecode/src/instructions.rs +++ b/ellie_engine/bytecode/src/instructions.rs @@ -75,6 +75,7 @@ impl Instruction { } } +#[derive(Copy, Clone, Debug, PartialEq)] pub enum Registers { A, B, diff --git a/ellie_engine/bytecode/src/transpiler/class.rs b/ellie_engine/bytecode/src/transpiler/items/class.rs similarity index 100% rename from ellie_engine/bytecode/src/transpiler/class.rs rename to ellie_engine/bytecode/src/transpiler/items/class.rs diff --git a/ellie_engine/bytecode/src/transpiler/class_instance.rs b/ellie_engine/bytecode/src/transpiler/items/class_instance.rs similarity index 100% rename from ellie_engine/bytecode/src/transpiler/class_instance.rs rename to ellie_engine/bytecode/src/transpiler/items/class_instance.rs diff --git a/ellie_engine/bytecode/src/transpiler/condition.rs b/ellie_engine/bytecode/src/transpiler/items/condition.rs similarity index 88% rename from ellie_engine/bytecode/src/transpiler/condition.rs rename to ellie_engine/bytecode/src/transpiler/items/condition.rs index 49da6c22..49cb53d5 100644 --- a/ellie_engine/bytecode/src/transpiler/condition.rs +++ b/ellie_engine/bytecode/src/transpiler/items/condition.rs @@ -1,3 +1,4 @@ +use crate::transpiler::types::{TypeTranspiler, TypeTranspilerOptions}; use crate::{ instruction_table, instructions::{self, Instruction}, @@ -6,8 +7,6 @@ use crate::{ use alloc::{vec, vec::Vec}; use ellie_core::definite::items::condition; -use super::type_resolver::resolve_type; - impl super::Transpiler for condition::Condition { fn transpile( &self, @@ -24,13 +23,13 @@ impl super::Transpiler for condition::Condition { for (_, chain) in self.chains.iter().enumerate() { if chain.rtype != ellie_core::definite::items::condition::ConditionType::Else { - resolve_type( - assembler, - &chain.condition, - instructions::Registers::A, - &hash, - Some(dependencies.clone()), - ); + let mut binding = TypeTranspilerOptions::new(); + let mut type_transpiler_options = binding + .set_assembler(assembler) + .set_dependencies(dependencies.clone()) + .set_target_page(hash); + + chain.condition.transpile(type_transpiler_options); } else { assembler .instructions diff --git a/ellie_engine/bytecode/src/transpiler/constructor.rs b/ellie_engine/bytecode/src/transpiler/items/constructor.rs similarity index 100% rename from ellie_engine/bytecode/src/transpiler/constructor.rs rename to ellie_engine/bytecode/src/transpiler/items/constructor.rs diff --git a/ellie_engine/bytecode/src/transpiler/for_loop.rs b/ellie_engine/bytecode/src/transpiler/items/for_loop.rs similarity index 100% rename from ellie_engine/bytecode/src/transpiler/for_loop.rs rename to ellie_engine/bytecode/src/transpiler/items/for_loop.rs diff --git a/ellie_engine/bytecode/src/transpiler/function.rs b/ellie_engine/bytecode/src/transpiler/items/function.rs similarity index 98% rename from ellie_engine/bytecode/src/transpiler/function.rs rename to ellie_engine/bytecode/src/transpiler/items/function.rs index 5d2b8972..0ac2ad51 100644 --- a/ellie_engine/bytecode/src/transpiler/function.rs +++ b/ellie_engine/bytecode/src/transpiler/items/function.rs @@ -90,12 +90,20 @@ impl super::Transpiler for function::Function { assembler.location() }; + let prev_pos = assembler.location(); + + + assembler.assemble_dependency(&self.inner_page_id); + + assembler .instructions .push(Instructions::RET(Instruction::implicit())); + + assembler.instructions[escape_pos_instruction_location] = instruction_table::Instructions::STA(Instruction::immediate( Types::Integer, diff --git a/ellie_engine/bytecode/src/transpiler/function_parameter.rs b/ellie_engine/bytecode/src/transpiler/items/function_parameter.rs similarity index 100% rename from ellie_engine/bytecode/src/transpiler/function_parameter.rs rename to ellie_engine/bytecode/src/transpiler/items/function_parameter.rs diff --git a/ellie_engine/bytecode/src/transpiler/getter_call.rs b/ellie_engine/bytecode/src/transpiler/items/getter_call.rs similarity index 71% rename from ellie_engine/bytecode/src/transpiler/getter_call.rs rename to ellie_engine/bytecode/src/transpiler/items/getter_call.rs index 9f3978e8..c76e719c 100644 --- a/ellie_engine/bytecode/src/transpiler/getter_call.rs +++ b/ellie_engine/bytecode/src/transpiler/items/getter_call.rs @@ -1,5 +1,7 @@ -use super::type_resolver::resolve_type; -use crate::{instructions, utils::limit_platform_size}; +use crate::{ + transpiler::types::{TypeTranspiler, TypeTranspilerOptions}, + utils::limit_platform_size, +}; use alloc::{string::ToString, vec}; use ellie_core::{ definite::items::getter_call, @@ -16,13 +18,19 @@ impl super::Transpiler for getter_call::GetterCall { let debug_header_start = assembler.location(); let mut dependencies = vec![processed_page.hash]; dependencies.extend(processed_page.dependencies.iter().map(|d| d.hash)); - resolve_type( - assembler, - &self.data, - instructions::Registers::A, - &hash, - Some(dependencies), + + let mut binding = TypeTranspilerOptions::new(); + + + std::println!("GetterCallDeps: {:#?}", dependencies); + + self.data.transpile( + binding + .set_assembler(assembler) + .set_target_page(hash) + .set_dependencies(dependencies), ); + assembler.debug_headers.push(DebugHeader { rtype: DebugHeaderType::GetterCall, hash: limit_platform_size(00099999999, assembler.platform_attributes.architecture), diff --git a/ellie_engine/bytecode/src/transpiler/loop_type.rs b/ellie_engine/bytecode/src/transpiler/items/loop_type.rs similarity index 88% rename from ellie_engine/bytecode/src/transpiler/loop_type.rs rename to ellie_engine/bytecode/src/transpiler/items/loop_type.rs index fe1c8b5f..6baa8840 100644 --- a/ellie_engine/bytecode/src/transpiler/loop_type.rs +++ b/ellie_engine/bytecode/src/transpiler/items/loop_type.rs @@ -7,11 +7,10 @@ use ellie_core::{ use crate::{ instruction_table, instructions::{self, Instruction}, + transpiler::types::{TypeTranspiler, TypeTranspilerOptions}, utils::limit_platform_size, }; -use super::type_resolver::resolve_type; - impl super::Transpiler for loop_type::Loop { fn transpile( &self, @@ -29,13 +28,13 @@ impl super::Transpiler for loop_type::Loop { //We need to get back at this point every time we jump to the end of the loop. let start_pos = assembler.location() + 1; - resolve_type( - assembler, - &self.condition, - instructions::Registers::A, - &hash, - Some(dependencies), - ); + let mut binding = TypeTranspilerOptions::new(); + let mut type_transpiler_options = binding + .set_assembler(assembler) + .set_dependencies(dependencies) + .set_target_page(hash); + + self.condition.transpile(type_transpiler_options); assembler .instructions diff --git a/ellie_engine/bytecode/src/transpiler/items/mod.rs b/ellie_engine/bytecode/src/transpiler/items/mod.rs new file mode 100644 index 00000000..6f0f4c1c --- /dev/null +++ b/ellie_engine/bytecode/src/transpiler/items/mod.rs @@ -0,0 +1,34 @@ +pub mod class; +pub mod class_instance; +pub mod condition; +pub mod constructor; +pub mod for_loop; +pub mod function; +pub mod function_parameter; +pub mod getter_call; +pub mod loop_type; +pub mod native_function; +pub mod ret; +pub mod self_item; +pub mod setter_call; +/* pub mod type_resolver; */ +pub mod variable; + +use ellie_parser::parser::ProcessedPage; + +use crate::assembler::Assembler; + +pub trait Transpiler { + /// Bytecode element transpiler + /// ## Arguments + /// * `parser` - [`Parser`] + /// * `page_id` - [`u64`] + /// ## Returns + /// [`bool`] - `true` if parsing should continue + fn transpile( + &self, + assembler: &mut Assembler, + hash: usize, + processed_page: &ProcessedPage, + ) -> bool; +} diff --git a/ellie_engine/bytecode/src/transpiler/native_function.rs b/ellie_engine/bytecode/src/transpiler/items/native_function.rs similarity index 100% rename from ellie_engine/bytecode/src/transpiler/native_function.rs rename to ellie_engine/bytecode/src/transpiler/items/native_function.rs diff --git a/ellie_engine/bytecode/src/transpiler/items/ret.rs b/ellie_engine/bytecode/src/transpiler/items/ret.rs new file mode 100644 index 00000000..2ea0c48d --- /dev/null +++ b/ellie_engine/bytecode/src/transpiler/items/ret.rs @@ -0,0 +1,47 @@ +use std::println; + +use alloc::vec; +use ellie_core::definite::items::ret; + +use crate::{ + instruction_table, + instructions::{self, Instruction}, + transpiler::types::{TypeTranspiler, TypeTranspilerOptions}, +}; + +impl super::Transpiler for ret::Ret { + fn transpile( + &self, + assembler: &mut crate::assembler::Assembler, + hash: usize, + processed_page: &ellie_parser::parser::ProcessedPage, + ) -> bool { + let mut dependencies = vec![processed_page.hash]; + dependencies.extend(processed_page.dependencies.iter().map(|d| d.hash)); + + let mut binding = TypeTranspilerOptions::new(); + let type_transpiler_options = binding + .set_assembler(assembler) + .set_target_register(instructions::Registers::Y) + .set_dependencies(dependencies) + .set_target_page(hash); + + self.value.transpile(type_transpiler_options); + + assembler + .instructions + .push(instruction_table::Instructions::STY(Instruction::implicit())); + + assembler + .instructions + .push(instruction_table::Instructions::LDY(Instruction::absolute( + assembler.location(), + ))); + + assembler + .instructions + .push(instruction_table::Instructions::RET(Instruction::implicit())); + + true + } +} diff --git a/ellie_engine/bytecode/src/transpiler/self_item.rs b/ellie_engine/bytecode/src/transpiler/items/self_item.rs similarity index 100% rename from ellie_engine/bytecode/src/transpiler/self_item.rs rename to ellie_engine/bytecode/src/transpiler/items/self_item.rs diff --git a/ellie_engine/bytecode/src/transpiler/setter_call.rs b/ellie_engine/bytecode/src/transpiler/items/setter_call.rs similarity index 87% rename from ellie_engine/bytecode/src/transpiler/setter_call.rs rename to ellie_engine/bytecode/src/transpiler/items/setter_call.rs index ddfc0d69..0911ebee 100644 --- a/ellie_engine/bytecode/src/transpiler/setter_call.rs +++ b/ellie_engine/bytecode/src/transpiler/items/setter_call.rs @@ -1,6 +1,8 @@ -use super::type_resolver::resolve_type; use crate::{ - addressing_modes::AddressingModes, instruction_table, instructions, utils::limit_platform_size, + addressing_modes::AddressingModes, + instruction_table, instructions, + transpiler::types::{TypeTranspiler, TypeTranspilerOptions}, + utils::limit_platform_size, }; use alloc::{string::ToString, vec}; use ellie_core::{ @@ -20,14 +22,14 @@ impl super::Transpiler for setter_call::SetterCall { let location = assembler.location(); - //Resolve the value to be inserted - resolve_type( - assembler, - &self.value, - instructions::Registers::C, - &hash, - Some(dependencies.clone()), - ); + let mut binding = TypeTranspilerOptions::new(); + let mut type_transpiler_options = binding + .set_assembler(assembler) + .set_target_register(instructions::Registers::C) + .set_dependencies(dependencies.clone()) + .set_target_page(hash); + + self.value.transpile(type_transpiler_options); //Store it in the stack assembler @@ -40,14 +42,15 @@ impl super::Transpiler for setter_call::SetterCall { match &self.operator { ellie_core::definite::types::operator::AssignmentOperators::Assignment => { - //Resolve the target - resolve_type( - assembler, - &self.target, - instructions::Registers::B, - &hash, - Some(dependencies.clone()), - ); + let mut binding = TypeTranspilerOptions::new(); + let type_transpiler_options = binding + .set_assembler(assembler) + .set_target_register(instructions::Registers::B) + .set_dependencies(dependencies.clone()) + .set_target_page(hash); + + self.target.transpile(type_transpiler_options); + let target_last_instruction = assembler.instructions.last().unwrap().clone(); match target_last_instruction { instruction_table::Instructions::LDB(ldb_in) => { @@ -141,13 +144,16 @@ impl super::Transpiler for setter_call::SetterCall { _ => unreachable!(), } }; - resolve_type( - assembler, - &self.target, - instructions::Registers::B, - &hash, - Some(dependencies.clone()), - ); + + let mut binding = TypeTranspilerOptions::new(); + let mut type_transpiler_options = binding + .set_assembler(assembler) + .set_target_register(instructions::Registers::B) + .set_dependencies(dependencies) + .set_target_page(hash); + + self.target.transpile(type_transpiler_options); + let left_last_instruction = assembler.instructions.last().unwrap().clone(); assembler .instructions diff --git a/ellie_engine/bytecode/src/transpiler/type_resolver.rs b/ellie_engine/bytecode/src/transpiler/items/type_resolver.rs similarity index 99% rename from ellie_engine/bytecode/src/transpiler/type_resolver.rs rename to ellie_engine/bytecode/src/transpiler/items/type_resolver.rs index 7a6cdbdf..6b2eb44c 100644 --- a/ellie_engine/bytecode/src/transpiler/type_resolver.rs +++ b/ellie_engine/bytecode/src/transpiler/items/type_resolver.rs @@ -734,7 +734,6 @@ pub fn resolve_type( _ => unreachable!("Unexpected target type"), }; - // Reserve class variables assembler diff --git a/ellie_engine/bytecode/src/transpiler/variable.rs b/ellie_engine/bytecode/src/transpiler/items/variable.rs similarity index 89% rename from ellie_engine/bytecode/src/transpiler/variable.rs rename to ellie_engine/bytecode/src/transpiler/items/variable.rs index a2ce4b97..40d55883 100644 --- a/ellie_engine/bytecode/src/transpiler/variable.rs +++ b/ellie_engine/bytecode/src/transpiler/items/variable.rs @@ -1,8 +1,8 @@ -use super::type_resolver::resolve_type; use crate::{ assembler::LocalHeader, instruction_table, instructions::{self, Instruction}, + transpiler::types::{TypeTranspiler, TypeTranspilerOptions}, utils::limit_platform_size, }; use alloc::vec; @@ -29,13 +29,14 @@ impl super::Transpiler for variable::Variable { let first_instruction_index = assembler.instructions.len(); - resolve_type( - assembler, - &self.value, - instructions::Registers::A, - &hash, - Some(dependencies), - ); + let mut binding = TypeTranspilerOptions::new(); + + let mut type_transpiler_options = binding + .set_assembler(assembler) + .set_dependencies(dependencies) + .set_target_page(hash); + + self.value.transpile(type_transpiler_options); if self.constant { assembler.instructions[first_instruction_index] = instruction_table::Instructions::STA( diff --git a/ellie_engine/bytecode/src/transpiler/mod.rs b/ellie_engine/bytecode/src/transpiler/mod.rs index a6955f2e..4f7a31f5 100644 --- a/ellie_engine/bytecode/src/transpiler/mod.rs +++ b/ellie_engine/bytecode/src/transpiler/mod.rs @@ -1,34 +1,2 @@ -pub mod class; -pub mod class_instance; -pub mod condition; -pub mod constructor; -pub mod for_loop; -pub mod function; -pub mod function_parameter; -pub mod getter_call; -pub mod loop_type; -pub mod native_function; -pub mod ret; -pub mod self_item; -pub mod setter_call; -pub mod type_resolver; -pub mod variable; - -use ellie_parser::parser::ProcessedPage; - -use crate::assembler::Assembler; - -pub trait Transpiler { - /// Bytecode element transpiler - /// ## Arguments - /// * `parser` - [`Parser`] - /// * `page_id` - [`u64`] - /// ## Returns - /// [`bool`] - `true` if parsing should continue - fn transpile( - &self, - assembler: &mut Assembler, - hash: usize, - processed_page: &ProcessedPage, - ) -> bool; -} +pub mod items; +pub mod types; diff --git a/ellie_engine/bytecode/src/transpiler/ret.rs b/ellie_engine/bytecode/src/transpiler/ret.rs deleted file mode 100644 index eeb2909b..00000000 --- a/ellie_engine/bytecode/src/transpiler/ret.rs +++ /dev/null @@ -1,33 +0,0 @@ -use alloc::vec; -use ellie_core::definite::items::ret; - -use crate::{ - instruction_table, - instructions::{self, Instruction}, -}; - -use super::type_resolver::resolve_type; - -impl super::Transpiler for ret::Ret { - fn transpile( - &self, - assembler: &mut crate::assembler::Assembler, - hash: usize, - processed_page: &ellie_parser::parser::ProcessedPage, - ) -> bool { - let mut dependencies = vec![processed_page.hash]; - dependencies.extend(processed_page.dependencies.iter().map(|d| d.hash)); - - resolve_type( - assembler, - &self.value, - instructions::Registers::Y, - &hash, - Some(dependencies), - ); - assembler - .instructions - .push(instruction_table::Instructions::RET(Instruction::implicit())); - true - } -} diff --git a/ellie_engine/bytecode/src/transpiler/types/array.rs b/ellie_engine/bytecode/src/transpiler/types/array.rs new file mode 100644 index 00000000..5be0e6f0 --- /dev/null +++ b/ellie_engine/bytecode/src/transpiler/types/array.rs @@ -0,0 +1,73 @@ +use super::TypeTranspiler; +use crate::{ + instruction_table::Instructions, + instructions::{Instruction, Registers}, + types::Types as ByteCodeTypes, + utils::usize_to_le_bytes, +}; +use ellie_core::definite::types::array::ArrayType; + +impl TypeTranspiler for ArrayType { + fn transpile(&self, options: &mut super::TypeTranspilerOptions) { + let static_array_location = options.assembler().location() + 1; + let arch = options.assembler().platform_attributes.architecture; + options + .assembler_mut() + .instructions + .push(Instructions::SAR(Instruction::immediate( + ByteCodeTypes::StaticArray, + usize_to_le_bytes(static_array_location, arch), + ))); + options + .assembler_mut() + .instructions + .push(Instructions::STA(Instruction::immediate( + ByteCodeTypes::Integer, + usize_to_le_bytes(self.collective.len(), arch), + ))); + let index_start = options.assembler().location(); + for _ in &self.collective { + options + .assembler_mut() + .instructions + .push(Instructions::STA(Instruction::implicit())); + } + for (index, entry) in self.collective.iter().enumerate() { + entry.value.transpile( + options + .copy() + .set_assembler(options.assembler_mut()) + .set_target_register(Registers::A), + ); + + options + .assembler_mut() + .instructions + .push(Instructions::STA(Instruction::absolute( + (index_start + 1) + index, + ))); + } + match options.target_register() { + Registers::A => options + .assembler_mut() + .instructions + .push(Instructions::LDA(Instruction::absolute(index_start - 1))), + Registers::B => options + .assembler_mut() + .instructions + .push(Instructions::LDB(Instruction::absolute(index_start - 1))), + Registers::C => options + .assembler_mut() + .instructions + .push(Instructions::LDC(Instruction::absolute(index_start - 1))), + Registers::X => options + .assembler_mut() + .instructions + .push(Instructions::LDX(Instruction::absolute(index_start - 1))), + Registers::Y => options + .assembler_mut() + .instructions + .push(Instructions::LDY(Instruction::absolute(index_start - 1))), + } + } +} diff --git a/ellie_engine/bytecode/src/transpiler/types/as_keyword.rs b/ellie_engine/bytecode/src/transpiler/types/as_keyword.rs new file mode 100644 index 00000000..2ef7156e --- /dev/null +++ b/ellie_engine/bytecode/src/transpiler/types/as_keyword.rs @@ -0,0 +1,85 @@ +use crate::{ + instruction_table::Instructions, + instructions::{Instruction, Registers}, +}; + +use super::TypeTranspiler; +use ellie_core::definite::types::as_keyword::AsKeyword; + +impl TypeTranspiler for AsKeyword { + fn transpile(&self, options: &mut super::TypeTranspilerOptions) { + self.target.transpile( + options + .copy() + .set_assembler(options.assembler_mut()) + .set_target_register(Registers::A), + ); + + match &self.rtype { + ellie_core::definite::definers::DefinerCollecting::Generic(e) => { + if e.rtype == "int" { + options + .assembler_mut() + .instructions + .push(Instructions::A2I(Instruction::implicit())); + } else if e.rtype == "float" { + options + .assembler_mut() + .instructions + .push(Instructions::A2F(Instruction::implicit())); + } else if e.rtype == "double" { + options + .assembler_mut() + .instructions + .push(Instructions::A2D(Instruction::implicit())); + } else if e.rtype == "bool" { + options + .assembler_mut() + .instructions + .push(Instructions::A2O(Instruction::implicit())); + } else if e.rtype == "string" { + options + .assembler_mut() + .instructions + .push(Instructions::A2S(Instruction::implicit())); + } else if e.rtype == "char" { + options + .assembler_mut() + .instructions + .push(Instructions::A2C(Instruction::implicit())); + } else if e.rtype == "byte" { + options + .assembler_mut() + .instructions + .push(Instructions::A2B(Instruction::implicit())); + } + } + _ => panic!("As conv parent generic not implemented yet"), + }; + + options + .assembler_mut() + .instructions + .push(Instructions::LDB(Instruction::indirect_a())); + + match options.target_register() { + Registers::A => options + .assembler_mut() + .instructions + .push(Instructions::LDA(Instruction::indirect_b())), + Registers::B => (), + Registers::C => options + .assembler_mut() + .instructions + .push(Instructions::LDC(Instruction::indirect_b())), + Registers::X => options + .assembler_mut() + .instructions + .push(Instructions::LDX(Instruction::indirect_b())), + Registers::Y => options + .assembler_mut() + .instructions + .push(Instructions::LDY(Instruction::indirect_b())), + } + } +} diff --git a/ellie_engine/bytecode/src/transpiler/types/bool.rs b/ellie_engine/bytecode/src/transpiler/types/bool.rs new file mode 100644 index 00000000..72e32337 --- /dev/null +++ b/ellie_engine/bytecode/src/transpiler/types/bool.rs @@ -0,0 +1,35 @@ +use ellie_core::definite::types::{bool::BoolType, Types}; + +use crate::{ + instruction_table::Instructions, + instructions::{Instruction, Registers}, +}; + +use super::{convert_type, TypeTranspiler}; + +impl TypeTranspiler for BoolType { + fn transpile(&self, options: &mut super::TypeTranspilerOptions) { + let converted_type = convert_type( + &Types::Bool(self.clone()), + options.dependencies(), + options.assembler().platform_attributes.architecture, + ); + match options.target_register() { + Registers::A => options.assembler_mut().instructions.push(Instructions::LDA( + Instruction::immediate(converted_type.0, converted_type.1), + )), + Registers::B => options.assembler_mut().instructions.push(Instructions::LDB( + Instruction::immediate(converted_type.0, converted_type.1), + )), + Registers::C => options.assembler_mut().instructions.push(Instructions::LDC( + Instruction::immediate(converted_type.0, converted_type.1), + )), + Registers::X => options.assembler_mut().instructions.push(Instructions::LDX( + Instruction::immediate(converted_type.0, converted_type.1), + )), + Registers::Y => options.assembler_mut().instructions.push(Instructions::LDY( + Instruction::immediate(converted_type.0, converted_type.1), + )), + } + } +} diff --git a/ellie_engine/bytecode/src/transpiler/types/brace_reference.rs b/ellie_engine/bytecode/src/transpiler/types/brace_reference.rs new file mode 100644 index 00000000..bd60ca56 --- /dev/null +++ b/ellie_engine/bytecode/src/transpiler/types/brace_reference.rs @@ -0,0 +1,57 @@ +use ellie_core::definite::types::brace_reference::BraceReferenceType; + +use crate::{ + instruction_table::Instructions, + instructions::{Instruction, Registers}, +}; + +use super::TypeTranspiler; + +impl TypeTranspiler for BraceReferenceType { + fn transpile(&self, options: &mut super::TypeTranspilerOptions) { + self.reference.transpile( + options + .copy() + .set_assembler(options.assembler_mut()) + .set_target_register(Registers::B), + ); + options + .assembler_mut() + .instructions + .push(Instructions::STB(Instruction::implicit())); + + let location_of_pointer = options.assembler().location(); + + self.value.transpile( + options + .copy() + .set_assembler(options.assembler_mut()) + .set_target_register(Registers::C), + ); + + options + .assembler_mut() + .instructions + .push(Instructions::STC(Instruction::implicit())); + + let index_pointer = options.assembler().location(); + + match options.target_register() { + Registers::A => options.assembler_mut().instructions.push(Instructions::LDA( + Instruction::absolute_index(location_of_pointer, index_pointer), + )), + Registers::B => options.assembler_mut().instructions.push(Instructions::LDB( + Instruction::absolute_index(location_of_pointer, index_pointer), + )), + Registers::C => options.assembler_mut().instructions.push(Instructions::LDC( + Instruction::absolute_index(location_of_pointer, index_pointer), + )), + Registers::X => options.assembler_mut().instructions.push(Instructions::LDX( + Instruction::absolute_index(location_of_pointer, index_pointer), + )), + Registers::Y => options.assembler_mut().instructions.push(Instructions::LDY( + Instruction::absolute_index(location_of_pointer, index_pointer), + )), + } + } +} diff --git a/ellie_engine/bytecode/src/transpiler/types/byte.rs b/ellie_engine/bytecode/src/transpiler/types/byte.rs new file mode 100644 index 00000000..c089f64e --- /dev/null +++ b/ellie_engine/bytecode/src/transpiler/types/byte.rs @@ -0,0 +1,35 @@ +use ellie_core::definite::types::{byte::ByteType, Types}; + +use crate::{ + instruction_table::Instructions, + instructions::{Instruction, Registers}, +}; + +use super::{convert_type, TypeTranspiler}; + +impl TypeTranspiler for ByteType { + fn transpile(&self, options: &mut super::TypeTranspilerOptions) { + let converted_type = convert_type( + &Types::Byte(self.clone()), + options.dependencies(), + options.assembler().platform_attributes.architecture, + ); + match options.target_register() { + Registers::A => options.assembler_mut().instructions.push(Instructions::LDA( + Instruction::immediate(converted_type.0, converted_type.1), + )), + Registers::B => options.assembler_mut().instructions.push(Instructions::LDB( + Instruction::immediate(converted_type.0, converted_type.1), + )), + Registers::C => options.assembler_mut().instructions.push(Instructions::LDC( + Instruction::immediate(converted_type.0, converted_type.1), + )), + Registers::X => options.assembler_mut().instructions.push(Instructions::LDX( + Instruction::immediate(converted_type.0, converted_type.1), + )), + Registers::Y => options.assembler_mut().instructions.push(Instructions::LDY( + Instruction::immediate(converted_type.0, converted_type.1), + )), + } + } +} diff --git a/ellie_engine/bytecode/src/transpiler/types/char.rs b/ellie_engine/bytecode/src/transpiler/types/char.rs new file mode 100644 index 00000000..c5127060 --- /dev/null +++ b/ellie_engine/bytecode/src/transpiler/types/char.rs @@ -0,0 +1,35 @@ +use ellie_core::definite::types::{ellie_char::CharType, Types}; + +use crate::{ + instruction_table::Instructions, + instructions::{Instruction, Registers}, +}; + +use super::{convert_type, TypeTranspiler}; + +impl TypeTranspiler for CharType { + fn transpile(&self, options: &mut super::TypeTranspilerOptions) { + let converted_type = convert_type( + &Types::Char(self.clone()), + options.dependencies(), + options.assembler().platform_attributes.architecture, + ); + match options.target_register() { + Registers::A => options.assembler_mut().instructions.push(Instructions::LDA( + Instruction::immediate(converted_type.0, converted_type.1), + )), + Registers::B => options.assembler_mut().instructions.push(Instructions::LDB( + Instruction::immediate(converted_type.0, converted_type.1), + )), + Registers::C => options.assembler_mut().instructions.push(Instructions::LDC( + Instruction::immediate(converted_type.0, converted_type.1), + )), + Registers::X => options.assembler_mut().instructions.push(Instructions::LDX( + Instruction::immediate(converted_type.0, converted_type.1), + )), + Registers::Y => options.assembler_mut().instructions.push(Instructions::LDY( + Instruction::immediate(converted_type.0, converted_type.1), + )), + } + } +} diff --git a/ellie_engine/bytecode/src/transpiler/types/class_call.rs b/ellie_engine/bytecode/src/transpiler/types/class_call.rs new file mode 100644 index 00000000..50bd42d1 --- /dev/null +++ b/ellie_engine/bytecode/src/transpiler/types/class_call.rs @@ -0,0 +1,149 @@ +use ellie_core::definite::types::{class_call::ClassCall, Types as CoreTypes}; + +use crate::{ + assembler::LocalHeader, + instruction_table::Instructions, + instructions::{Instruction, Registers}, + types::Types as ByteCodeTypes, + utils::usize_to_le_bytes, +}; + +use super::TypeTranspiler; + +impl TypeTranspiler for ClassCall { + fn transpile(&self, options: &mut super::TypeTranspilerOptions) { + let dependencies = options.dependencies(); + let arch = options.assembler().platform_attributes.architecture; + + let target: LocalHeader = match *self.target.clone() { + CoreTypes::VariableType(e) => { + let data = options + .assembler_mut() + .find_local(&e.value, dependencies, true) + .unwrap() + .clone(); + data + } + _ => unreachable!("Unexpected target type"), + }; + + // Reserve class variables + + options + .assembler_mut() + .instructions + .push(Instructions::ARR(Instruction::implicit())); + let class_location = options.assembler().location(); + if !self.params.is_empty() { + for (_idx, param) in self.params.iter().enumerate() { + param.value.transpile( + options + .copy() + .set_assembler(options.assembler_mut()) + .set_target_register(Registers::A), + ); + + options + .assembler_mut() + .instructions + .push(Instructions::STA(Instruction::implicit())); + options + .assembler_mut() + .instructions + .push(Instructions::PUSH(Instruction::absolute(class_location))); + } + } + + let self_location = options.assembler().location() + 1; + + options + .assembler_mut() + .instructions + .push(Instructions::CO(Instruction::absolute(class_location))); + + let previous_params_location = options.assembler().location() + 1; + + // Reserve parameters + options + .assembler_mut() + .instructions + .push(Instructions::STB(Instruction::implicit())); + + for _ in self.params.iter().enumerate() { + options + .assembler_mut() + .instructions + .push(Instructions::STB(Instruction::implicit())); + } + //- + + // Insert self + options + .assembler_mut() + .instructions + .push(Instructions::LDB(Instruction::absolute(self_location))); + options + .assembler_mut() + .instructions + .push(Instructions::STB(Instruction::absolute( + previous_params_location, + ))); + //- + + if !self.params.is_empty() { + for (idx, param) in self.params.iter().enumerate() { + // First position taken by self + let idx = idx + 1; + + let prev_ = options.assembler().location(); + + param.value.transpile( + options + .copy() + .set_assembler(options.assembler_mut()) + .set_target_register(Registers::A), + ); + + options.assembler_mut().instructions.push(Instructions::STA( + Instruction::absolute(previous_params_location + idx), + )); + } + } + + options + .assembler_mut() + .instructions + .push(Instructions::LDX(Instruction::immediate( + ByteCodeTypes::Integer, + usize_to_le_bytes(previous_params_location, arch), + ))); + + options + .assembler_mut() + .instructions + .push(Instructions::CALL(Instruction::absolute(target.cursor))); + + match options.target_register() { + Registers::A => options + .assembler_mut() + .instructions + .push(Instructions::LDA(Instruction::absolute(self_location))), + Registers::B => options + .assembler_mut() + .instructions + .push(Instructions::LDB(Instruction::absolute(self_location))), + Registers::C => options + .assembler_mut() + .instructions + .push(Instructions::LDC(Instruction::absolute(self_location))), + Registers::X => options + .assembler_mut() + .instructions + .push(Instructions::LDX(Instruction::absolute(self_location))), + Registers::Y => options + .assembler_mut() + .instructions + .push(Instructions::LDY(Instruction::absolute(self_location))), + } + } +} diff --git a/ellie_engine/bytecode/src/transpiler/types/cloak.rs b/ellie_engine/bytecode/src/transpiler/types/cloak.rs new file mode 100644 index 00000000..04765b26 --- /dev/null +++ b/ellie_engine/bytecode/src/transpiler/types/cloak.rs @@ -0,0 +1,63 @@ +use super::TypeTranspiler; +use crate::{ + instruction_table::Instructions, + instructions::{Instruction, Registers}, + types::Types as ByteCodeTypes, + utils::usize_to_le_bytes, +}; +use ellie_core::definite::types::cloak::CloakType; + +impl TypeTranspiler for CloakType { + fn transpile(&self, options: &mut super::TypeTranspilerOptions) { + let mut size = 0; + + for entry in &self.collective { + entry.value.transpile( + options + .copy() + .set_assembler(options.assembler_mut()) + .set_target_register(Registers::A), + ); + options + .assembler_mut() + .instructions + .push(Instructions::STA(Instruction::implicit())); + size += 1; + } + + let arch = options.assembler().platform_attributes.architecture; + + options + .assembler_mut() + .instructions + .push(Instructions::SAR(Instruction::immediate( + ByteCodeTypes::StaticArray, + usize_to_le_bytes(size, arch), + ))); + + let location = options.assembler().location(); + + match options.target_register() { + Registers::A => options + .assembler_mut() + .instructions + .push(Instructions::LDA(Instruction::absolute(location))), + Registers::B => options + .assembler_mut() + .instructions + .push(Instructions::LDB(Instruction::absolute(location))), + Registers::C => options + .assembler_mut() + .instructions + .push(Instructions::LDC(Instruction::absolute(location))), + Registers::X => options + .assembler_mut() + .instructions + .push(Instructions::LDX(Instruction::absolute(location))), + Registers::Y => options + .assembler_mut() + .instructions + .push(Instructions::LDY(Instruction::absolute(location))), + } + } +} diff --git a/ellie_engine/bytecode/src/transpiler/types/collective.rs b/ellie_engine/bytecode/src/transpiler/types/collective.rs new file mode 100644 index 00000000..03bd89d8 --- /dev/null +++ b/ellie_engine/bytecode/src/transpiler/types/collective.rs @@ -0,0 +1,9 @@ +use ellie_core::definite::types::collective::CollectiveType; + +use super::TypeTranspiler; + +impl TypeTranspiler for CollectiveType { + fn transpile(&self, _options: &mut super::TypeTranspilerOptions) { + todo!() + } +} diff --git a/ellie_engine/bytecode/src/transpiler/types/constructor_parameter.rs b/ellie_engine/bytecode/src/transpiler/types/constructor_parameter.rs new file mode 100644 index 00000000..fd7e629b --- /dev/null +++ b/ellie_engine/bytecode/src/transpiler/types/constructor_parameter.rs @@ -0,0 +1,40 @@ +use crate::{instruction_table::Instructions, instructions::Registers}; + +use super::TypeTranspiler; +use ellie_core::definite::items::constructor_parameter::ConstructorParameter; + +impl TypeTranspiler for ConstructorParameter { + fn transpile(&self, options: &mut super::TypeTranspilerOptions) { + let dependencies = options.dependencies().clone(); + let pos = match options + .assembler_mut() + .find_local(&self.name, dependencies, false) + { + Some(e) => e, + None => panic!("Constructor Parameter not found: {}", self.name), + }; + + match options.target_register() { + Registers::A => options + .assembler_mut() + .instructions + .push(Instructions::LDA(pos.reference.clone())), + Registers::B => options + .assembler_mut() + .instructions + .push(Instructions::LDB(pos.reference.clone())), + Registers::C => options + .assembler_mut() + .instructions + .push(Instructions::LDC(pos.reference.clone())), + Registers::X => options + .assembler_mut() + .instructions + .push(Instructions::LDX(pos.reference.clone())), + Registers::Y => options + .assembler_mut() + .instructions + .push(Instructions::LDY(pos.reference.clone())), + } + } +} diff --git a/ellie_engine/bytecode/src/transpiler/types/decimal.rs b/ellie_engine/bytecode/src/transpiler/types/decimal.rs new file mode 100644 index 00000000..68f70465 --- /dev/null +++ b/ellie_engine/bytecode/src/transpiler/types/decimal.rs @@ -0,0 +1,35 @@ +use ellie_core::definite::types::{decimal::DecimalType, Types}; + +use crate::{ + instruction_table::Instructions, + instructions::{Instruction, Registers}, +}; + +use super::{convert_type, TypeTranspiler}; + +impl TypeTranspiler for DecimalType { + fn transpile(&self, options: &mut super::TypeTranspilerOptions) { + let converted_type = convert_type( + &Types::Decimal(self.clone()), + options.dependencies(), + options.assembler().platform_attributes.architecture, + ); + match options.target_register() { + Registers::A => options.assembler_mut().instructions.push(Instructions::LDA( + Instruction::immediate(converted_type.0, converted_type.1), + )), + Registers::B => options.assembler_mut().instructions.push(Instructions::LDB( + Instruction::immediate(converted_type.0, converted_type.1), + )), + Registers::C => options.assembler_mut().instructions.push(Instructions::LDC( + Instruction::immediate(converted_type.0, converted_type.1), + )), + Registers::X => options.assembler_mut().instructions.push(Instructions::LDX( + Instruction::immediate(converted_type.0, converted_type.1), + )), + Registers::Y => options.assembler_mut().instructions.push(Instructions::LDY( + Instruction::immediate(converted_type.0, converted_type.1), + )), + } + } +} diff --git a/ellie_engine/bytecode/src/transpiler/types/dynamic.rs b/ellie_engine/bytecode/src/transpiler/types/dynamic.rs new file mode 100644 index 00000000..cb484ac7 --- /dev/null +++ b/ellie_engine/bytecode/src/transpiler/types/dynamic.rs @@ -0,0 +1,9 @@ +use super::TypeTranspiler; + +pub struct Dynamic; + +impl TypeTranspiler for Dynamic { + fn transpile(&self, _options: &mut super::TypeTranspilerOptions) { + todo!() + } +} diff --git a/ellie_engine/bytecode/src/transpiler/types/enum_data.rs b/ellie_engine/bytecode/src/transpiler/types/enum_data.rs new file mode 100644 index 00000000..cf836191 --- /dev/null +++ b/ellie_engine/bytecode/src/transpiler/types/enum_data.rs @@ -0,0 +1,8 @@ +use super::TypeTranspiler; +use ellie_core::definite::types::enum_data::EnumData; + +impl TypeTranspiler for EnumData { + fn transpile(&self, _options: &mut super::TypeTranspilerOptions) { + todo!() + } +} diff --git a/ellie_engine/bytecode/src/transpiler/types/function.rs b/ellie_engine/bytecode/src/transpiler/types/function.rs new file mode 100644 index 00000000..0a61b126 --- /dev/null +++ b/ellie_engine/bytecode/src/transpiler/types/function.rs @@ -0,0 +1,8 @@ +use super::TypeTranspiler; +use ellie_core::definite::types::function::Function; + +impl TypeTranspiler for Function { + fn transpile(&self, _options: &mut super::TypeTranspilerOptions) { + todo!() + } +} diff --git a/ellie_engine/bytecode/src/transpiler/types/function_call.rs b/ellie_engine/bytecode/src/transpiler/types/function_call.rs new file mode 100644 index 00000000..f417467a --- /dev/null +++ b/ellie_engine/bytecode/src/transpiler/types/function_call.rs @@ -0,0 +1,177 @@ +use alloc::vec; +use ellie_core::definite::types::{ + class_instance::AttributeType, function_call::FunctionCall, Types as CoreTypes, +}; + + +use crate::{ + assembler::LocalHeader, + instruction_table::Instructions, + instructions::{Instruction, Registers}, + types::Types as ByteCodeTypes, + utils::usize_to_le_bytes, +}; + +use super::TypeTranspiler; + +impl TypeTranspiler for FunctionCall { + fn transpile(&self, options: &mut super::TypeTranspilerOptions) { + let dependencies = options.dependencies(); + let arch = options.assembler().platform_attributes.architecture; + + let mut is_reference: Option = None; + let target: LocalHeader = match *self.target.clone() { + CoreTypes::VariableType(e) => options + .assembler_mut() + .find_local(&e.value, dependencies.clone(), true) + .unwrap_or_else(|| { + panic!("Variable not found: {}: {:#?} {:#?}, {:#?}", e.value, dependencies, options.target_page, self); + }) + .clone(), + CoreTypes::Reference(e) => { + let mut _pos = options.assembler().location(); + + e.reference.transpile( + options + .copy() + .set_assembler(options.assembler_mut()) + .set_target_register(Registers::B), + ); + + options + .assembler_mut() + .instructions + .push(Instructions::STB(Instruction::implicit())); + let mut last_pos = options.assembler().location(); + let mut found = None; + + for (idx, chain) in e.index_chain.iter().enumerate() { + if e.index_chain.len() - 1 != idx { + match chain.rtype { + AttributeType::Property => { + options.assembler_mut().instructions.push(Instructions::LDA( + Instruction::absolute_property( + last_pos, + chain.class_attribute_idx, + ), + )); + + options + .assembler_mut() + .instructions + .push(Instructions::STA(Instruction::implicit())); + last_pos = options.assembler().location(); + } + AttributeType::Method => unimplemented!(), + AttributeType::Setter => unimplemented!(), + AttributeType::Getter => unimplemented!(), + AttributeType::EnumItemData => unimplemented!(), + AttributeType::EnumItemNoData => unimplemented!(), + } + } + } + let last_chain = e.index_chain.last().unwrap(); + found = options.assembler_mut().find_local_by_hash( + last_chain.hash, + Some(vec![last_chain.page_hash]), + true, + ); + is_reference = Some(last_pos); + found.unwrap() + } + _ => unreachable!("Unexpected target type"), + }; + + let previous_params_location = options.assembler().location() + 1; + if is_reference.is_some() { + options + .assembler_mut() + .instructions + .push(Instructions::STB(Instruction::implicit())); + } + + for _ in &self.params { + options + .assembler_mut() + .instructions + .push(Instructions::STB(Instruction::implicit())); + } + + if let Some(reference) = &is_reference { + options + .assembler_mut() + .instructions + .push(Instructions::LDB(Instruction::absolute(*reference))); + options + .assembler_mut() + .instructions + .push(Instructions::STB(Instruction::absolute( + previous_params_location, + ))); + } + + if !self.params.is_empty() { + for (idx, param) in self.params.iter().enumerate() { + let idx = if is_reference.is_some() { idx + 1 } else { idx }; + + param.value.transpile( + options + .copy() + .set_assembler(options.assembler_mut()) + .set_target_register(Registers::A), + ); + + options.assembler_mut().instructions.push(Instructions::STA( + Instruction::absolute(previous_params_location + idx), + )); + } + } + + options + .assembler_mut() + .instructions + .push(Instructions::LDX(Instruction::immediate( + ByteCodeTypes::Integer, + usize_to_le_bytes(previous_params_location, arch), + ))); + + options + .assembler_mut() + .instructions + .push(Instructions::CALL(Instruction::absolute(target.cursor))); + + let borrow_location = options.assembler().location() + 1; + + options + .assembler_mut() + .add_borrow_to_local(target.hash.unwrap(), borrow_location); + + match options.target_register() { + Registers::A => { + options + .assembler_mut() + .instructions + .push(Instructions::LDA(Instruction::indirect_y())); + } + Registers::B => { + options + .assembler_mut() + .instructions + .push(Instructions::LDB(Instruction::indirect_y())); + } + Registers::C => { + options + .assembler_mut() + .instructions + .push(Instructions::LDC(Instruction::indirect_y())); + } + Registers::X => { + options + .assembler_mut() + .instructions + .push(Instructions::LDX(Instruction::indirect_y())); + } + Registers::Y => (), + } + } +} diff --git a/ellie_engine/bytecode/src/transpiler/types/function_parameter.rs b/ellie_engine/bytecode/src/transpiler/types/function_parameter.rs new file mode 100644 index 00000000..cd513494 --- /dev/null +++ b/ellie_engine/bytecode/src/transpiler/types/function_parameter.rs @@ -0,0 +1,40 @@ +use crate::{instruction_table::Instructions, instructions::Registers}; + +use super::TypeTranspiler; +use ellie_core::definite::types::function::FunctionParameter; + +impl TypeTranspiler for FunctionParameter { + fn transpile(&self, options: &mut super::TypeTranspilerOptions) { + let dependencies = options.dependencies().clone(); + let pos = match options + .assembler_mut() + .find_local(&self.name, dependencies, false) + { + Some(e) => e, + None => panic!("Function Parameter not found: {}", self.name), + }; + + match options.target_register() { + Registers::A => options + .assembler_mut() + .instructions + .push(Instructions::LDA(pos.reference.clone())), + Registers::B => options + .assembler_mut() + .instructions + .push(Instructions::LDB(pos.reference.clone())), + Registers::C => options + .assembler_mut() + .instructions + .push(Instructions::LDC(pos.reference.clone())), + Registers::X => options + .assembler_mut() + .instructions + .push(Instructions::LDX(pos.reference.clone())), + Registers::Y => options + .assembler_mut() + .instructions + .push(Instructions::LDY(pos.reference.clone())), + } + } +} diff --git a/ellie_engine/bytecode/src/transpiler/types/integer.rs b/ellie_engine/bytecode/src/transpiler/types/integer.rs new file mode 100644 index 00000000..5958ab92 --- /dev/null +++ b/ellie_engine/bytecode/src/transpiler/types/integer.rs @@ -0,0 +1,35 @@ +use ellie_core::definite::types::{integer::IntegerType, Types}; + +use crate::{ + instruction_table::Instructions, + instructions::{Instruction, Registers}, +}; + +use super::{convert_type, TypeTranspiler}; + +impl TypeTranspiler for IntegerType { + fn transpile(&self, options: &mut super::TypeTranspilerOptions) { + let converted_type = convert_type( + &Types::Integer(self.clone()), + options.dependencies(), + options.assembler().platform_attributes.architecture, + ); + match options.target_register() { + Registers::A => options.assembler_mut().instructions.push(Instructions::LDA( + Instruction::immediate(converted_type.0, converted_type.1), + )), + Registers::B => options.assembler_mut().instructions.push(Instructions::LDB( + Instruction::immediate(converted_type.0, converted_type.1), + )), + Registers::C => options.assembler_mut().instructions.push(Instructions::LDC( + Instruction::immediate(converted_type.0, converted_type.1), + )), + Registers::X => options.assembler_mut().instructions.push(Instructions::LDX( + Instruction::immediate(converted_type.0, converted_type.1), + )), + Registers::Y => options.assembler_mut().instructions.push(Instructions::LDY( + Instruction::immediate(converted_type.0, converted_type.1), + )), + } + } +} diff --git a/ellie_engine/bytecode/src/transpiler/types/mod.rs b/ellie_engine/bytecode/src/transpiler/types/mod.rs new file mode 100644 index 00000000..f9fb3053 --- /dev/null +++ b/ellie_engine/bytecode/src/transpiler/types/mod.rs @@ -0,0 +1,175 @@ +pub mod array; +pub mod as_keyword; +pub mod bool; +pub mod brace_reference; +pub mod byte; +pub mod char; +pub mod class_call; +pub mod cloak; +pub mod collective; +pub mod constructor_parameter; +pub mod decimal; +pub mod dynamic; +pub mod enum_data; +pub mod function; +pub mod function_call; +pub mod function_parameter; +pub mod integer; +pub mod negative; +pub mod null; +pub mod null_resolver; +pub mod operator; +pub mod reference; +pub mod string; +pub mod variable_type; +pub mod void; + +use crate::{ + assembler::Assembler, + instructions::Registers, + types::Types as ByteCodeTypes, + utils::{f32_to_le_bytes, f64_to_le_bytes, isize_to_le_bytes}, +}; +use alloc::vec::Vec; +use ellie_core::{definite::types::Types, defs::PlatformArchitecture}; + +pub struct TypeTranspilerOptions<'a> { + assembler: Option<&'a mut Assembler>, + target_register: Registers, + target_page: Option, + dependencies: Option>, +} + +impl<'a> TypeTranspilerOptions<'a> { + pub fn new() -> Self { + Self { + assembler: None, + target_register: Registers::A, + target_page: None, + dependencies: None, + } + } + + pub fn copy<'b>(&self) -> TypeTranspilerOptions<'b> { + TypeTranspilerOptions { + assembler: None, + target_register: self.target_register, + target_page: self.target_page, + dependencies: self.dependencies.clone(), + } + } + + pub fn with_dependencies(mut self, dependencies: Vec) -> Self { + self.dependencies = Some(dependencies); + self + } + + pub fn assembler(&self) -> &Assembler { + self.assembler.as_deref().expect("Assembler is not set") + } + + pub fn assembler_mut(&mut self) -> &mut Assembler { + self.assembler.as_deref_mut().expect("Assembler is not set") + } + + pub fn target_register(&self) -> Registers { + self.target_register + } + + pub fn set_target_page(&mut self, target_page: usize) -> &mut Self { + self.target_page = Some(target_page); + self + } + + pub fn set_dependencies(&mut self, dependencies: Vec) -> &mut Self { + self.dependencies = Some(dependencies); + self + } + + pub fn set_target_register(&mut self, target_register: Registers) -> &mut Self { + self.target_register = target_register; + self + } + + pub fn set_assembler(&mut self, assembler: &'a mut Assembler) -> &mut Self { + self.assembler = Some(assembler); + self + } + + pub fn target_page(&self) -> usize { + self.target_page.unwrap() + } + + pub fn dependencies(&mut self) -> Option> { + self.dependencies.clone() + } +} + +pub trait TypeTranspiler { + /// Transpile a type + /// ## Arguments + /// * `options` - [`TypeTranspilerOptions`] + fn transpile(&self, options: &mut TypeTranspilerOptions); +} + +impl TypeTranspiler for Types { + fn transpile(&self, options: &mut TypeTranspilerOptions) { + match self { + Types::Byte(b) => b.transpile(options), + Types::Integer(i) => i.transpile(options), + Types::Decimal(d) => d.transpile(options), + Types::Bool(b) => b.transpile(options), + Types::String(s) => s.transpile(options), + Types::Char(c) => c.transpile(options), + Types::Collective(c) => c.transpile(options), + Types::Reference(r) => r.transpile(options), + Types::BraceReference(br) => br.transpile(options), + Types::EnumData(e) => e.transpile(options), + Types::Operator(o) => o.transpile(options), + Types::Cloak(c) => c.transpile(options), + Types::Array(a) => a.transpile(options), + Types::Function(f) => f.transpile(options), + Types::FunctionParameter(fp) => fp.transpile(options), + Types::ConstructorParameter(cp) => cp.transpile(options), + Types::ClassCall(cc) => cc.transpile(options), + Types::FunctionCall(fc) => fc.transpile(options), + Types::SetterCall(_) => todo!(), + Types::Void => void::Void.transpile(options), + Types::NullResolver(nr) => nr.transpile(options), + Types::Negative(n) => n.transpile(options), + Types::VariableType(vt) => vt.transpile(options), + Types::AsKeyword(ak) => ak.transpile(options), + Types::ClassInstance(_) => todo!("TO BE REMOVED"), + Types::Null => null::Null.transpile(options), + Types::Dynamic => dynamic::Dynamic.transpile(options), + } + } +} + +pub fn convert_type( + types: &Types, + _page_hash: Option>, + arch: PlatformArchitecture, +) -> (ByteCodeTypes, Vec) { + match types { + Types::Byte(byte) => (ByteCodeTypes::Byte, byte.value.to_le_bytes().to_vec()), + Types::Integer(integer) => ( + ByteCodeTypes::Integer, + isize_to_le_bytes(integer.value, arch), + ), + Types::Decimal(decimal) => match decimal.value { + ellie_core::definite::types::decimal::DecimalTypeEnum::Float(float_value) => { + (ByteCodeTypes::Float, f32_to_le_bytes(float_value, arch)) + } + ellie_core::definite::types::decimal::DecimalTypeEnum::Double(double_value) => { + (ByteCodeTypes::Double, f64_to_le_bytes(double_value, arch)) + } + }, + Types::Bool(bool) => ( + ByteCodeTypes::Bool, + (bool.value as u8).to_le_bytes().to_vec(), + ), + Types::Char(e) => (ByteCodeTypes::Char, (e.value as u32).to_le_bytes().to_vec()), + _ => unreachable!("This type is not convertable to raw type"), + } +} diff --git a/ellie_engine/bytecode/src/transpiler/types/negative.rs b/ellie_engine/bytecode/src/transpiler/types/negative.rs new file mode 100644 index 00000000..fce02c44 --- /dev/null +++ b/ellie_engine/bytecode/src/transpiler/types/negative.rs @@ -0,0 +1,8 @@ +use super::TypeTranspiler; +use ellie_core::definite::types::negative::Negative; + +impl TypeTranspiler for Negative { + fn transpile(&self, _options: &mut super::TypeTranspilerOptions) { + todo!() + } +} diff --git a/ellie_engine/bytecode/src/transpiler/types/null.rs b/ellie_engine/bytecode/src/transpiler/types/null.rs new file mode 100644 index 00000000..8cf3f2a7 --- /dev/null +++ b/ellie_engine/bytecode/src/transpiler/types/null.rs @@ -0,0 +1,33 @@ +use alloc::vec::Vec; + +use crate::{ + instruction_table::Instructions, + instructions::{Instruction, Registers}, + types::Types as ByteCodeTypes, +}; + +use super::TypeTranspiler; + +pub struct Null; + +impl TypeTranspiler for Null { + fn transpile(&self, options: &mut super::TypeTranspilerOptions) { + match options.target_register() { + Registers::A => options.assembler_mut().instructions.push(Instructions::LDA( + Instruction::immediate(ByteCodeTypes::Null, Vec::new()), + )), + Registers::B => options.assembler_mut().instructions.push(Instructions::LDB( + Instruction::immediate(ByteCodeTypes::Null, Vec::new()), + )), + Registers::C => options.assembler_mut().instructions.push(Instructions::LDC( + Instruction::immediate(ByteCodeTypes::Null, Vec::new()), + )), + Registers::X => options.assembler_mut().instructions.push(Instructions::LDX( + Instruction::immediate(ByteCodeTypes::Null, Vec::new()), + )), + Registers::Y => options.assembler_mut().instructions.push(Instructions::LDY( + Instruction::immediate(ByteCodeTypes::Null, Vec::new()), + )), + } + } +} diff --git a/ellie_engine/bytecode/src/transpiler/types/null_resolver.rs b/ellie_engine/bytecode/src/transpiler/types/null_resolver.rs new file mode 100644 index 00000000..16c18e2b --- /dev/null +++ b/ellie_engine/bytecode/src/transpiler/types/null_resolver.rs @@ -0,0 +1,8 @@ +use super::TypeTranspiler; +use ellie_core::definite::types::null_resolver::NullResolver; + +impl TypeTranspiler for NullResolver { + fn transpile(&self, options: &mut super::TypeTranspilerOptions) { + self.target.transpile(options) + } +} diff --git a/ellie_engine/bytecode/src/transpiler/types/operator.rs b/ellie_engine/bytecode/src/transpiler/types/operator.rs new file mode 100644 index 00000000..3c25645c --- /dev/null +++ b/ellie_engine/bytecode/src/transpiler/types/operator.rs @@ -0,0 +1,247 @@ +use ellie_core::definite::types::operator::{ + ArithmeticOperators, ComparisonOperators, LogicalOperators, OperatorType, Operators, +}; + +use super::TypeTranspiler; +use crate::{ + instruction_table::Instructions, + instructions::{Instruction, Registers}, +}; + +impl TypeTranspiler for OperatorType { + fn transpile(&self, options: &mut super::TypeTranspilerOptions) { + match &self.operator { + Operators::ComparisonType(comparison_operator) => { + self.first.transpile( + options + .copy() + .set_assembler(options.assembler_mut()) + .set_target_register(Registers::B), + ); + + let first_operator_pos = options.assembler().location(); + + options + .assembler_mut() + .instructions + .push(Instructions::STB(Instruction::implicit())); + + self.second.transpile( + options + .copy() + .set_assembler(options.assembler_mut()) + .set_target_register(Registers::C), + ); + + let second_operator_pos = options.assembler().location(); + + options + .assembler_mut() + .instructions + .push(Instructions::STC(Instruction::implicit())); + + options + .assembler_mut() + .instructions + .push(Instructions::LDB(Instruction::absolute(first_operator_pos))); + + options.assembler_mut().instructions.push(Instructions::LDC( + Instruction::absolute(second_operator_pos), + )); + + options + .assembler_mut() + .instructions + .push(match comparison_operator { + ComparisonOperators::Equal => Instructions::EQ(Instruction::implicit()), + ComparisonOperators::NotEqual => Instructions::NE(Instruction::implicit()), + ComparisonOperators::GreaterThan => { + Instructions::GT(Instruction::implicit()) + } + ComparisonOperators::LessThan => Instructions::LT(Instruction::implicit()), + ComparisonOperators::GreaterThanOrEqual => { + Instructions::GQ(Instruction::implicit()) + } + ComparisonOperators::LessThanOrEqual => { + Instructions::LQ(Instruction::implicit()) + } + ComparisonOperators::Null => unreachable!(), + }); + + match options.target_register() { + Registers::A => (), + Registers::B => { + options + .assembler_mut() + .instructions + .push(Instructions::LDB(Instruction::indirect_a())); + } + Registers::C => { + options + .assembler_mut() + .instructions + .push(Instructions::LDC(Instruction::indirect_a())); + } + Registers::X => { + options + .assembler_mut() + .instructions + .push(Instructions::LDX(Instruction::indirect_a())); + } + Registers::Y => { + options + .assembler_mut() + .instructions + .push(Instructions::LDY(Instruction::indirect_a())); + } + } + } + Operators::LogicalType(logical_operators) => { + self.second.transpile( + options + .copy() + .set_assembler(options.assembler_mut()) + .set_target_register(Registers::C), + ); + + let second_operator_pos = options.assembler().location(); + options + .assembler_mut() + .instructions + .push(Instructions::STC(Instruction::implicit())); + + self.first.transpile( + options + .copy() + .set_assembler(options.assembler_mut()) + .set_target_register(Registers::B), + ); + + options.assembler_mut().instructions.push(Instructions::LDC( + Instruction::absolute(second_operator_pos), + )); + + options + .assembler_mut() + .instructions + .push(match logical_operators { + LogicalOperators::And => Instructions::AND(Instruction::implicit()), + LogicalOperators::Or => Instructions::OR(Instruction::implicit()), + _ => unreachable!(), + }); + + match options.target_register() { + Registers::A => (), + Registers::B => { + options + .assembler_mut() + .instructions + .push(Instructions::LDB(Instruction::indirect_a())); + } + Registers::C => { + options + .assembler_mut() + .instructions + .push(Instructions::LDC(Instruction::indirect_a())); + } + Registers::X => { + options + .assembler_mut() + .instructions + .push(Instructions::LDX(Instruction::indirect_a())); + } + Registers::Y => { + options + .assembler_mut() + .instructions + .push(Instructions::LDY(Instruction::indirect_a())); + } + } + } + Operators::ArithmeticType(arithmetic_operators) => { + self.first.transpile( + options + .copy() + .set_assembler(options.assembler_mut()) + .set_target_register(Registers::B), + ); + + let first_operator_pos = options.assembler().instructions.len(); + options + .assembler_mut() + .instructions + .push(Instructions::STB(Instruction::implicit())); + + self.second.transpile( + options + .copy() + .set_assembler(options.assembler_mut()) + .set_target_register(Registers::C), + ); + + let second_operator_pos = options.assembler().instructions.len(); + + options + .assembler_mut() + .instructions + .push(Instructions::STC(Instruction::implicit())); + + options + .assembler_mut() + .instructions + .push(Instructions::LDB(Instruction::absolute(first_operator_pos))); + options.assembler_mut().instructions.push(Instructions::LDC( + Instruction::absolute(second_operator_pos), + )); + + options + .assembler_mut() + .instructions + .push(match arithmetic_operators { + ArithmeticOperators::Addition => Instructions::ADD(Instruction::implicit()), + ArithmeticOperators::Subtraction => { + Instructions::SUB(Instruction::implicit()) + } + ArithmeticOperators::Multiplication => { + Instructions::MUL(Instruction::implicit()) + } + ArithmeticOperators::Exponentiation => { + Instructions::EXP(Instruction::implicit()) + } + ArithmeticOperators::Division => Instructions::DIV(Instruction::implicit()), + ArithmeticOperators::Modulus => Instructions::MOD(Instruction::implicit()), + ArithmeticOperators::Null => unreachable!("Wrong operator"), + }); + match options.target_register() { + Registers::A => (), + Registers::B => { + options + .assembler_mut() + .instructions + .push(Instructions::LDB(Instruction::indirect_a())); + } + Registers::C => { + options + .assembler_mut() + .instructions + .push(Instructions::LDC(Instruction::indirect_a())); + } + Registers::X => { + options + .assembler_mut() + .instructions + .push(Instructions::LDX(Instruction::indirect_a())); + } + Registers::Y => { + options + .assembler_mut() + .instructions + .push(Instructions::LDY(Instruction::indirect_a())); + } + } + } + Operators::AssignmentType(_) => todo!(), + Operators::Null => unreachable!(), + } + } +} diff --git a/ellie_engine/bytecode/src/transpiler/types/reference.rs b/ellie_engine/bytecode/src/transpiler/types/reference.rs new file mode 100644 index 00000000..d267b8e5 --- /dev/null +++ b/ellie_engine/bytecode/src/transpiler/types/reference.rs @@ -0,0 +1,124 @@ +use ellie_core::definite::types::reference::ReferenceType; + +use crate::{ + instruction_table::Instructions, + instructions::{Instruction, Registers}, +}; + +use super::TypeTranspiler; + +impl TypeTranspiler for ReferenceType { + fn transpile(&self, options: &mut super::TypeTranspilerOptions) { + self.reference.transpile( + options + .copy() + .set_assembler(options.assembler_mut()) + .set_target_register(Registers::B), + ); + + options + .assembler_mut() + .instructions + .push(Instructions::STB(Instruction::implicit())); + + let mut last_pos = options.assembler().location(); + for (idx, chain) in self.index_chain.iter().enumerate() { + match chain.rtype { + ellie_core::definite::types::class_instance::AttributeType::Property => { + match options.target_register() { + Registers::A => { + options.assembler_mut().instructions.push(Instructions::LDA( + Instruction::absolute_property(last_pos, chain.idx), + )); + } + Registers::B => { + options.assembler_mut().instructions.push(Instructions::LDB( + Instruction::absolute_property(last_pos, chain.idx), + )); + } + Registers::C => { + options.assembler_mut().instructions.push(Instructions::LDC( + Instruction::absolute_property(last_pos, chain.idx), + )); + } + Registers::X => { + options.assembler_mut().instructions.push(Instructions::LDX( + Instruction::absolute_property(last_pos, chain.idx), + )); + } + Registers::Y => { + options.assembler_mut().instructions.push(Instructions::LDY( + Instruction::absolute_property(last_pos, chain.idx), + )); + } + } + } + ellie_core::definite::types::class_instance::AttributeType::Method => { + unreachable!("Method is handled by the function call") + } + ellie_core::definite::types::class_instance::AttributeType::Getter => { + unreachable!("Getter is handled by the getter call") + } + ellie_core::definite::types::class_instance::AttributeType::Setter => todo!(), + ellie_core::definite::types::class_instance::AttributeType::EnumItemData => { + todo!() + } + ellie_core::definite::types::class_instance::AttributeType::EnumItemNoData => { + todo!() + } + } + if self.index_chain.len() - 1 != idx { + match chain.rtype { + ellie_core::definite::types::class_instance::AttributeType::Property => { + match options.target_register() { + Registers::A => { + options + .assembler_mut() + .instructions + .push(Instructions::STA(Instruction::implicit())); + } + Registers::B => { + options + .assembler_mut() + .instructions + .push(Instructions::STB(Instruction::implicit())); + } + Registers::C => { + options + .assembler_mut() + .instructions + .push(Instructions::STC(Instruction::implicit())); + } + Registers::X => { + options + .assembler_mut() + .instructions + .push(Instructions::STX(Instruction::implicit())); + } + Registers::Y => { + options + .assembler_mut() + .instructions + .push(Instructions::STY(Instruction::implicit())); + } + } + last_pos = options.assembler().location(); + } + ellie_core::definite::types::class_instance::AttributeType::Method => { + unreachable!("Method is handled by the function call") + } + ellie_core::definite::types::class_instance::AttributeType::Getter => { + unreachable!("Getter is handled by the getter call") + } + ellie_core::definite::types::class_instance::AttributeType::Setter => todo!(), + ellie_core::definite::types::class_instance::AttributeType::EnumItemData => { + todo!() + } + ellie_core::definite::types::class_instance::AttributeType::EnumItemNoData => { + todo!() + } + } + } + } + } +} diff --git a/ellie_engine/bytecode/src/transpiler/types/string.rs b/ellie_engine/bytecode/src/transpiler/types/string.rs new file mode 100644 index 00000000..687c3368 --- /dev/null +++ b/ellie_engine/bytecode/src/transpiler/types/string.rs @@ -0,0 +1,56 @@ +use ellie_core::definite::types::string::StringType; + +use super::TypeTranspiler; +use crate::{ + instruction_table::Instructions, + instructions::{Instruction, Registers}, + types::Types as ByteCodeTypes, +}; + +impl TypeTranspiler for StringType { + fn transpile(&self, options: &mut super::TypeTranspilerOptions) { + //Create heap array + options + .assembler_mut() + .instructions + .push(Instructions::STR(Instruction::implicit())); + let array_location = options.assembler().location(); + + for char in self.value.chars() { + options + .assembler_mut() + .instructions + .push(Instructions::STA(Instruction::immediate( + ByteCodeTypes::Char, + (char as u32).to_le_bytes().to_vec(), + ))); + options + .assembler_mut() + .instructions + .push(Instructions::SPUS(Instruction::absolute(array_location))) + } + + match options.target_register() { + Registers::A => options + .assembler_mut() + .instructions + .push(Instructions::LDA(Instruction::absolute(array_location))), + Registers::B => options + .assembler_mut() + .instructions + .push(Instructions::LDB(Instruction::absolute(array_location))), + Registers::C => options + .assembler_mut() + .instructions + .push(Instructions::LDC(Instruction::absolute(array_location))), + Registers::X => options + .assembler_mut() + .instructions + .push(Instructions::LDX(Instruction::absolute(array_location))), + Registers::Y => options + .assembler_mut() + .instructions + .push(Instructions::LDY(Instruction::absolute(array_location))), + } + } +} diff --git a/ellie_engine/bytecode/src/transpiler/types/variable_type.rs b/ellie_engine/bytecode/src/transpiler/types/variable_type.rs new file mode 100644 index 00000000..493d2c35 --- /dev/null +++ b/ellie_engine/bytecode/src/transpiler/types/variable_type.rs @@ -0,0 +1,40 @@ +use crate::{instruction_table::Instructions, instructions::Registers}; + +use super::TypeTranspiler; +use ellie_core::definite::types::variable::VariableType; + +impl TypeTranspiler for VariableType { + fn transpile(&self, options: &mut super::TypeTranspilerOptions) { + let dependencies = options.dependencies().clone(); + let pos = match options + .assembler_mut() + .find_local(&self.value, dependencies, false) + { + Some(e) => e, + None => panic!("Variable not found: {}", self.value), + }; + + match options.target_register() { + Registers::A => options + .assembler_mut() + .instructions + .push(Instructions::LDA(pos.reference.clone())), + Registers::B => options + .assembler_mut() + .instructions + .push(Instructions::LDB(pos.reference.clone())), + Registers::C => options + .assembler_mut() + .instructions + .push(Instructions::LDC(pos.reference.clone())), + Registers::X => options + .assembler_mut() + .instructions + .push(Instructions::LDX(pos.reference.clone())), + Registers::Y => options + .assembler_mut() + .instructions + .push(Instructions::LDY(pos.reference.clone())), + } + } +} diff --git a/ellie_engine/bytecode/src/transpiler/types/void.rs b/ellie_engine/bytecode/src/transpiler/types/void.rs new file mode 100644 index 00000000..d162ac15 --- /dev/null +++ b/ellie_engine/bytecode/src/transpiler/types/void.rs @@ -0,0 +1,33 @@ +use alloc::vec::Vec; + +use crate::{ + instruction_table::Instructions, + instructions::{Instruction, Registers}, + types::Types as ByteCodeTypes, +}; + +use super::TypeTranspiler; + +pub struct Void; + +impl TypeTranspiler for Void { + fn transpile(&self, options: &mut super::TypeTranspilerOptions) { + match options.target_register() { + Registers::A => options.assembler_mut().instructions.push(Instructions::LDA( + Instruction::immediate(ByteCodeTypes::Void, Vec::new()), + )), + Registers::B => options.assembler_mut().instructions.push(Instructions::LDB( + Instruction::immediate(ByteCodeTypes::Void, Vec::new()), + )), + Registers::C => options.assembler_mut().instructions.push(Instructions::LDC( + Instruction::immediate(ByteCodeTypes::Void, Vec::new()), + )), + Registers::X => options.assembler_mut().instructions.push(Instructions::LDX( + Instruction::immediate(ByteCodeTypes::Void, Vec::new()), + )), + Registers::Y => options.assembler_mut().instructions.push(Instructions::LDY( + Instruction::immediate(ByteCodeTypes::Void, Vec::new()), + )), + } + } +} From 01bf7c1a2b4aa064930631af62bcf13f545f4dd5 Mon Sep 17 00:00:00 2001 From: Ahmetcan Aksu Date: Sun, 21 Apr 2024 23:21:10 +0300 Subject: [PATCH 07/30] Fix constructor errors --- ellie_engine/parser/src/parser.rs | 3 - .../parser/src/processors/items/class.rs | 21 +- .../src/processors/items/constructor.rs | 57 +- .../parser/src/processors/types/class_call.rs | 662 ++++++++++-------- .../src/processors/items/class_processor.rs | 57 ++ .../processors/items/constructor_processor.rs | 1 + .../tokenizer/src/syntax/items/constructor.rs | 3 + ellie_engine/vm/src/instructions/FN.rs | 1 - 8 files changed, 455 insertions(+), 350 deletions(-) diff --git a/ellie_engine/parser/src/parser.rs b/ellie_engine/parser/src/parser.rs index edb9edb3..cd232750 100644 --- a/ellie_engine/parser/src/parser.rs +++ b/ellie_engine/parser/src/parser.rs @@ -1633,9 +1633,6 @@ impl Parser { let page_type = page.page_type.clone(); let page_path = page.path.clone(); idx += 1; - if page.hash == self.initial_page { - continue; - } self.process_page(page_hash); match page_type { PageType::FunctionBody(function_page) => { diff --git a/ellie_engine/parser/src/processors/items/class.rs b/ellie_engine/parser/src/processors/items/class.rs index a39a7573..270abb75 100644 --- a/ellie_engine/parser/src/processors/items/class.rs +++ b/ellie_engine/parser/src/processors/items/class.rs @@ -4,7 +4,7 @@ use ellie_core::warning; use ellie_core::{defs, error, utils}; use ellie_tokenizer::{ processors::items::Processors, - syntax::items::{class::Class, constructor::Constructor}, + syntax::items::class::Class, tokenizer::{ClassPageType, PageType}, }; @@ -162,25 +162,6 @@ impl super::ItemParserProcessor for Class { err.semi_assist = true; options.parser.informations.push(&err); } - } else { - // If no constructor exists build one. - - let mut inside_code = Vec::new(); - let mut parameters = Vec::new(); - - let mut constructor = Processors::Constructor( - Constructor { - parameters: todo!(), - inside_code: todo!(), - name_pos: todo!(), - parameters_pos: todo!(), - brace_count: todo!(), - iterator: todo!(), - pos: todo!(), - complete: todo!(), - } - ); - } for (index, generic) in self.generic_definings.iter().enumerate() { diff --git a/ellie_engine/parser/src/processors/items/constructor.rs b/ellie_engine/parser/src/processors/items/constructor.rs index 13eef28f..b24f58f4 100644 --- a/ellie_engine/parser/src/processors/items/constructor.rs +++ b/ellie_engine/parser/src/processors/items/constructor.rs @@ -78,7 +78,6 @@ impl super::ItemParserProcessor for Constructor { let mut items = Vec::new(); let mut parameters = Vec::new(); - items.push( ellie_tokenizer::processors::items::Processors::ConstructorParameter( ConstructorParameter { @@ -107,34 +106,48 @@ impl super::ItemParserProcessor for Constructor { .body .iter() .filter_map(|item| match item.as_variable() { - Some(e) => e.data.has_value.then_some(e), + Some(e) => { + if e.data.has_value && !self.parameters.iter().any(|g| g.name == e.data.name) { + e.data.has_value.then_some(e) + } else { + None + } + } None => None, }) { - let self_setter = Processors::SetterCall(SetterCall { - target: TypeProcessor::Reference(ReferenceTypeCollector { - data: ReferenceType { - reference: Box::new(TypeProcessor::Variable(VariableTypeCollector { - data: VariableType { - value: "self".to_owned(), + if !self.parameters.iter().any(|g| g.name == variable.data.name) { + let self_setter = Processors::SetterCall(SetterCall { + target: TypeProcessor::Reference(ReferenceTypeCollector { + data: ReferenceType { + reference: Box::new(TypeProcessor::Variable(VariableTypeCollector { + data: VariableType { + value: "self".to_owned(), + ..Default::default() + }, ..Default::default() - }, - ..Default::default() - })), - chain: vec![Chain { - value: variable.data.name.clone(), + })), + chain: vec![Chain { + value: variable.data.name.clone(), + ..Default::default() + }], ..Default::default() - }], + }, ..Default::default() - }, + }), + value: variable.data.value.clone(), + operator: AssignmentOperators::Assignment, + hash: generate_hash_usize(), ..Default::default() - }), - value: variable.data.value.clone(), - operator: AssignmentOperators::Assignment, - hash: generate_hash_usize(), - ..Default::default() - }); - items.push(self_setter); + }); + items.push(self_setter); + parameters.push( + ellie_core::definite::items::constructor::ConstructorParameter { + name: variable.data.name.clone(), + pos: variable.data.pos, + }, + ); + } } for (index, parameter) in self.parameters.clone().iter().enumerate() { diff --git a/ellie_engine/parser/src/processors/types/class_call.rs b/ellie_engine/parser/src/processors/types/class_call.rs index 3a4a55b9..28ef2708 100644 --- a/ellie_engine/parser/src/processors/types/class_call.rs +++ b/ellie_engine/parser/src/processors/types/class_call.rs @@ -3,12 +3,16 @@ use ellie_core::{ definite::{definers::DefinerCollecting, types, Converter}, error, }; -use ellie_tokenizer::{processors::types::Processors, syntax::types::class_call_type}; +use ellie_tokenizer::{ + processors::{items::Processors as ItemProcessors, types::Processors}, + syntax::types::class_call_type, +}; use crate::{ deep_search_extensions::{ deep_search, deep_search_hash, find_type, resolve_type, ProcessedDeepSearchItems, }, + extra::{item_search::item_search, utils::DeepSearchOptions}, processors::{ definer::{DefinerParserProcessor, DefinerParserProcessorOptions}, types::TypeParserProcessorOptions, @@ -187,97 +191,75 @@ impl super::TypeParserProcessor for class_call_type::ClassCallCollector { Err(errors) } Processors::Variable(variable) => { - let deep_search_result = options.parser.deep_search( - options.page_id, - variable.data.value.clone(), - options.ignore_hash, - Vec::new(), - 0, - options.variable_pos, - ); + let mut deep_seach_options = DeepSearchOptions::new() + .page_id(options.page_id) + .name(variable.data.value.clone()) + //.search_on_all() + .search_on_raw() + .parser(options.parser) + .build(); - if deep_search_result.found { - match deep_search_result.found_item { - crate::parser::DeepSearchItems::Class(e) => { - let undefined_generics = self - .data - .generic_parameters - .iter() - .filter_map(|g| { - match g.value.process( - DefinerParserProcessorOptions::new( - options.parser, - options.page_id, - ) - .optional_ignore_hash(options.ignore_hash) - .build(), - ) { - Ok(e) => { - if !resolved_generics_defined { - resolved_generics.push(e); + if let Some(hash) = options.ignore_hash { + deep_seach_options = deep_seach_options.hash(hash); + } + + if let Some(pos) = options.variable_pos { + deep_seach_options = deep_seach_options.position(pos); + } + let deep_search_result = item_search(&mut deep_seach_options); + + if deep_search_result.found() { + if let Some(raw_item) = deep_search_result.found_item.raw() { + match raw_item { + ItemProcessors::Class(class) => { + let undefined_generics = self + .data + .generic_parameters + .iter() + .filter_map(|g| { + match g.value.process( + DefinerParserProcessorOptions::new( + options.parser, + options.page_id, + ) + .optional_ignore_hash(options.ignore_hash) + .build(), + ) { + Ok(e) => { + if !resolved_generics_defined { + resolved_generics.push(e); + } + None + } + Err(err) => { + errors.extend(err); + Some(g) } - None - } - Err(err) => { - errors.extend(err); - Some(g) } - } - }) - .collect::>(); - if e.generic_definings.len() != self.data.generic_parameters.len() { - let mut error = - error::error_list::ERROR_S44.clone().build_with_path( - vec![ - error::ErrorBuildField { - key: "token".to_string(), - value: e.generic_definings.len().to_string(), - }, - error::ErrorBuildField { - key: "token2".to_string(), - value: self - .data - .generic_parameters - .len() - .to_string(), - }, - ], - alloc::format!( - "{}:{}:{}", - file!().to_owned(), - line!(), - column!() - ), - options - .parser - .find_page(options.page_id) - .unwrap() - .path - .clone(), - self.data.target_pos, - ); - error.builded_message.builded += - " (https://github.com/behemehal/Ellie-Language/issues/59)"; - error.reference_block = Some(( - e.name_pos, - options - .parser - .find_page(options.page_id) - .unwrap() - .path - .clone(), - )); - error.reference_message = "Defined here".to_owned(); - errors.push(error); - Err(errors) - } else if !undefined_generics.is_empty() { - for g in undefined_generics { - errors.push( - error::error_list::ERROR_S6.clone().build_with_path( - vec![error::ErrorBuildField { - key: "token".to_string(), - value: g.value.clone().to_definite().to_string(), - }], + }) + .collect::>(); + if class.generic_definings.len() + != self.data.generic_parameters.len() + { + let mut error = + error::error_list::ERROR_S44.clone().build_with_path( + vec![ + error::ErrorBuildField { + key: "token".to_string(), + value: class + .generic_definings + .len() + .to_string(), + }, + error::ErrorBuildField { + key: "token2".to_string(), + value: self + .data + .generic_parameters + .len() + .to_string(), + }, + ], alloc::format!( "{}:{}:{}", file!().to_owned(), @@ -290,47 +272,34 @@ impl super::TypeParserProcessor for class_call_type::ClassCallCollector { .unwrap() .path .clone(), - g.pos, - ), - ); - } - Err(errors) - } else { - let constructor = e.body.iter().find_map(|x| match x { - ellie_tokenizer::processors::items::Processors::Constructor( - e, - ) => Some(e), - _ => None, - }); - - if constructor.is_some() { - if constructor.unwrap().parameters.len() - != self.data.parameters.len() - { + self.data.target_pos, + ); + error.builded_message.builded += + " (https://github.com/behemehal/Ellie-Language/issues/59)"; + error.reference_block = Some(( + class.name_pos, + options + .parser + .find_page(options.page_id) + .unwrap() + .path + .clone(), + )); + error.reference_message = "Defined here".to_owned(); + errors.push(error); + Err(errors) + } else if !undefined_generics.is_empty() { + for g in undefined_generics { errors.push( - error::error_list::ERROR_S7.clone().build_with_path( - vec![ - error::ErrorBuildField { - key: "name".to_string(), - value: e.name.clone(), - }, - error::ErrorBuildField { - key: "token".to_string(), - value: constructor - .unwrap() - .parameters - .len() - .to_string(), - }, - error::ErrorBuildField { - key: "token2".to_string(), - value: self - .data - .parameters - .len() - .to_string(), - }, - ], + error::error_list::ERROR_S6.clone().build_with_path( + vec![error::ErrorBuildField { + key: "token".to_string(), + value: g + .value + .clone() + .to_definite() + .to_string(), + }], alloc::format!( "{}:{}:{}", file!().to_owned(), @@ -343,28 +312,95 @@ impl super::TypeParserProcessor for class_call_type::ClassCallCollector { .unwrap() .path .clone(), - self.data.target_pos, + g.pos, ), ); - return Err(errors); - } else { - let class_page = deep_search_hash( - options.parser, - options.page_id, - e.hash, - Vec::new(), - 0, - ); - let belonging_class = - class_page.found_item.as_class().unwrap_or_else(|| { - unreachable!( - "options.parser should have prevented this" - ) - }); - let constructor_elements: Vec<_> = constructor + } + Err(errors) + } else { + let constructor = class.body.iter().find_map(|x| { + match x { + ellie_tokenizer::processors::items::Processors::Constructor( + e, + ) => Some(e), + _ => None, + } + }); + + if constructor.is_some() { + // If Class's body has variables with data, data will be built in construction time so we will ignore them + let constructor_size = constructor .unwrap() .parameters .iter() + .filter(|x| !x.body_element_defiener) + .count(); + let used_size = self.data.parameters.len(); + + if constructor_size != used_size { + errors.push( + error::error_list::ERROR_S7 + .clone() + .build_with_path( + vec![ + error::ErrorBuildField { + key: "name".to_string(), + value: class.name.clone(), + }, + error::ErrorBuildField { + key: "token".to_string(), + value: constructor + .unwrap() + .parameters + .len() + .to_string(), + }, + error::ErrorBuildField { + key: "token2".to_string(), + value: self + .data + .parameters + .len() + .to_string(), + }, + ], + alloc::format!( + "{}:{}:{}", + file!().to_owned(), + line!(), + column!() + ), + options + .parser + .find_page(options.page_id) + .unwrap() + .path + .clone(), + self.data.target_pos, + ), + ); + return Err(errors); + } else { + let class_page = deep_search_hash( + options.parser, + options.page_id, + class.hash, + Vec::new(), + 0, + ); + let belonging_class = class_page + .found_item + .as_class() + .unwrap_or_else(|| { + unreachable!( + "options.parser should have prevented this" + ) + }); + let constructor_elements: Vec<_> = constructor + .unwrap() + .parameters + .iter() + .filter(|x| !x.body_element_defiener) .enumerate() .filter_map(|(index, x)| { let attribute_search = deep_search( @@ -410,19 +446,23 @@ impl super::TypeParserProcessor for class_call_type::ClassCallCollector { }) .collect(); - //Ignore if length is not a match - if constructor.unwrap().parameters.len() - == constructor_elements.len() - { - for (index, element) in - constructor_elements.iter().enumerate() + //Ignore if length is not a match + if constructor.unwrap().parameters.len() + == constructor_elements.len() { - //element.convert_generic(); + for (index, element) in + constructor_elements.iter().enumerate() + { + //element.convert_generic(); - let matching_param = &self.data.parameters[index]; + let matching_param = + &self.data.parameters[index]; - let element_to_be_compared = - match self.data.generic_parameters.get(index) { + let element_to_be_compared = match self + .data + .generic_parameters + .get(index) + { Some(generic_param) => generic_param .value .process( @@ -439,38 +479,43 @@ impl super::TypeParserProcessor for class_call_type::ClassCallCollector { None => element.clone(), }; - let mut _options = TypeParserProcessorOptions::new( - options.parser, - options.page_id, - ); + let mut _options = + TypeParserProcessorOptions::new( + options.parser, + options.page_id, + ); - match matching_param.value.process( - _options - .dont_exclude_getter() - .dont_ignore_type() - .dont_include_setter() - .optional_variable_pos(options.variable_pos) - .optional_ignore_hash(options.ignore_hash) - .build(), - ) { - Ok(resolved_type) => { - let comperable = options - .parser - .compare_defining_with_type( - element_to_be_compared.clone(), - resolved_type.clone(), - options.page_id, - ); - let path = options - .parser - .find_page(options.page_id) - .unwrap() - .path - .clone(); - match comperable { - Ok(result) => { - if result.requires_cast { - options.parser.informations.push( + match matching_param.value.process( + _options + .dont_exclude_getter() + .dont_ignore_type() + .dont_include_setter() + .optional_variable_pos( + options.variable_pos, + ) + .optional_ignore_hash( + options.ignore_hash, + ) + .build(), + ) { + Ok(resolved_type) => { + let comperable = options + .parser + .compare_defining_with_type( + element_to_be_compared.clone(), + resolved_type.clone(), + options.page_id, + ); + let path = options + .parser + .find_page(options.page_id) + .unwrap() + .path + .clone(); + match comperable { + Ok(result) => { + if result.requires_cast { + options.parser.informations.push( &error::error_list::ERROR_S41.clone().build_with_path( vec![error::ErrorBuildField { key: "token".to_owned(), @@ -486,7 +531,7 @@ impl super::TypeParserProcessor for class_call_type::ClassCallCollector { matching_param.pos, ), ); - let err = error::error_list::ERROR_S3 + let err = error::error_list::ERROR_S3 .clone() .build_with_path( vec![ @@ -508,12 +553,12 @@ impl super::TypeParserProcessor for class_call_type::ClassCallCollector { path, matching_param.pos, ); - errors.push(err); - return Err(errors); - } + errors.push(err); + return Err(errors); + } - if !result.same { - let err = error::error_list::ERROR_S3 + if !result.same { + let err = error::error_list::ERROR_S3 .clone() .build_with_path( vec![ @@ -535,26 +580,64 @@ impl super::TypeParserProcessor for class_call_type::ClassCallCollector { options.parser.find_page(options.page_id).unwrap().path.clone(), matching_param.pos, ); - errors.push(err); - return Err(errors); + errors.push(err); + return Err(errors); + } } + Err(err) => errors.extend(err), } - Err(err) => errors.extend(err), } + Err(err) => errors.extend(err), } - Err(err) => errors.extend(err), } } } } - } - Ok(types::Types::ClassCall( + + let mut params = self + .data + .parameters + .iter() + .map(|x| types::class_call::ClassCallParameter { + value: x.value.to_definite(), + pos: x.pos, + }) + .collect::>(); + + let body_element_definer_parameters = constructor + .unwrap() + .parameters + .iter() + .filter(|x| x.body_element_defiener) + .collect::>(); + + for element in body_element_definer_parameters { + let found_variable_value = class.body.iter().find_map(|x| { + match x { + ellie_tokenizer::processors::items::Processors::Variable(e) => { + if e.data.name == element.name { + Some(e.data.value.clone()) + } else { + None + } + } + _ => None, + } + }).unwrap(); + + params.push(types::class_call::ClassCallParameter { + value: found_variable_value.to_definite(), + pos: element.pos, + }); + } + + Ok(types::Types::ClassCall( ellie_core::definite::types::class_call::ClassCall { target: Box::new(ellie_core::definite::types::Types::VariableType( ellie_core::definite::types::variable::VariableType { value: variable.data.value, pos: self.data.target_pos, - reference: e.hash, + reference: class.hash, }, )), keyword_pos: self.data.keyword_pos, @@ -581,122 +664,93 @@ impl super::TypeParserProcessor for class_call_type::ClassCallCollector { pos: x.pos } }).collect::>(), - params: self.data.parameters.iter().map(|x| types::class_call::ClassCallParameter { value: x.value.to_definite(), pos: x.pos }).collect::>(), + params, pos: self.data.pos, }, )) + } } - } - crate::parser::DeepSearchItems::Variable(e) => { - errors.push( - error::error_list::ERROR_S31.clone().build_with_path( - vec![error::ErrorBuildField { - key: "token".to_string(), - value: "variable".to_string(), - }], - alloc::format!( - "{}:{}:{}", - file!().to_owned(), - line!(), - column!() - ), - options - .parser - .find_page(options.page_id) - .unwrap() - .path - .clone(), - e.pos, - ), - ); - Err(errors) - } - crate::parser::DeepSearchItems::Function(e) => { - errors.push( - error::error_list::ERROR_S31.clone().build_with_path( - vec![error::ErrorBuildField { - key: "token".to_string(), - value: "function".to_string(), - }], - alloc::format!( - "{}:{}:{}", - file!().to_owned(), - line!(), - column!() + ItemProcessors::Variable(var) => { + errors.push( + error::error_list::ERROR_S31.clone().build_with_path( + vec![error::ErrorBuildField { + key: "token".to_string(), + value: "variable".to_string(), + }], + alloc::format!( + "{}:{}:{}", + file!().to_owned(), + line!(), + column!() + ), + options + .parser + .find_page(options.page_id) + .unwrap() + .path + .clone(), + var.data.pos, ), - options - .parser - .find_page(options.page_id) - .unwrap() - .path - .clone(), - e.name_pos, - ), - ); - Err(errors) - } - crate::parser::DeepSearchItems::ImportReference(e) => { - errors.push( - error::error_list::ERROR_S31.clone().build_with_path( - vec![error::ErrorBuildField { - key: "token".to_string(), - value: "variable".to_string(), - }], - alloc::format!( - "{}:{}:{}", - file!().to_owned(), - line!(), - column!() + ); + Err(errors) + } + ItemProcessors::Function(fun) => { + errors.push( + error::error_list::ERROR_S31.clone().build_with_path( + vec![error::ErrorBuildField { + key: "token".to_string(), + value: "function".to_string(), + }], + alloc::format!( + "{}:{}:{}", + file!().to_owned(), + line!(), + column!() + ), + options + .parser + .find_page(options.page_id) + .unwrap() + .path + .clone(), + fun.data.name_pos, ), - options - .parser - .find_page(options.page_id) - .unwrap() - .path - .clone(), - e.reference_pos, - ), - ); - Err(errors) - } - crate::parser::DeepSearchItems::ClassInstance(_) => todo!(), - crate::parser::DeepSearchItems::GenericItem(_) => todo!(), - crate::parser::DeepSearchItems::FunctionParameter(_) => { - unimplemented!() - } - crate::parser::DeepSearchItems::ConstructorParameter(_) => { - unimplemented!() - } - _ => { - errors.push( - error::error_list::ERROR_S31.clone().build_with_path( - vec![error::ErrorBuildField { - key: "token".to_string(), - value: variable.data.value, - }], - alloc::format!( - "{}:{}:{}", - file!().to_owned(), - line!(), - column!() + ); + Err(errors) + } + _ => { + errors.push( + error::error_list::ERROR_S31.clone().build_with_path( + vec![error::ErrorBuildField { + key: "token".to_string(), + value: variable.data.value, + }], + alloc::format!( + "{}:{}:{}", + file!().to_owned(), + line!(), + column!() + ), + options + .parser + .find_page(options.page_id) + .unwrap() + .path + .clone(), + variable.data.pos, ), - options - .parser - .find_page(options.page_id) - .unwrap() - .path - .clone(), - variable.data.pos, - ), - ); - Err(errors) + ); + Err(errors) + } } + } else { + unreachable!("Something is wrong with item_search") } } else { errors.push( - error::error_list::ERROR_S6.clone().build_with_path( + error::error_list::ERROR_S31.clone().build_with_path( vec![error::ErrorBuildField { - key: "token".to_owned(), + key: "token".to_string(), value: variable.data.value, }], alloc::format!("{}:{}:{}", file!().to_owned(), line!(), column!()), diff --git a/ellie_engine/tokenizer/src/processors/items/class_processor.rs b/ellie_engine/tokenizer/src/processors/items/class_processor.rs index 924a2b83..19c41d10 100644 --- a/ellie_engine/tokenizer/src/processors/items/class_processor.rs +++ b/ellie_engine/tokenizer/src/processors/items/class_processor.rs @@ -1,3 +1,4 @@ +use super::{constructor, variable::Variable}; use crate::{processors::EscapeCharEmitter, syntax::items::class}; use ellie_core::{defs, error, utils}; @@ -121,6 +122,62 @@ impl crate::processors::Processor for class::Class { self.iterator.finalize(); errors.extend(self.iterator.errors.clone()); self.body = self.iterator.collected.clone(); + + // If there is no constructor, add a default constructor + if !self + .body + .iter() + .any(|item| matches!(item, super::Processors::Constructor(_))) + { + self.body.insert( + 0, + super::Processors::Constructor(super::constructor::Constructor::default()), + ); + } + + let find_unused_variables_in_class_body: Vec = self + .body + .iter() + .filter_map(|item| { + if let super::Processors::Variable(variable) = item { + Some(variable.data.clone()) + } else { + None + } + }) + .collect::>(); + + let constructor = self + .body + .iter_mut() + .find_map(|item| { + if let super::Processors::Constructor(constructor) = item { + Some(constructor) + } else { + None + } + }) + .unwrap(); + + let find_unused_variables_in_class_body = find_unused_variables_in_class_body + .into_iter() + .filter(|variable| { + !constructor + .parameters + .iter() + .any(|parameter| parameter.name == variable.name) + }) + .collect::>(); + + for variable in find_unused_variables_in_class_body { + constructor + .parameters + .push(constructor::ConstructorParameter { + name: variable.name, + pos: variable.pos, + body_element_defiener: true, + }); + } } else { if letter_char == '{' { self.brace_count += 1; diff --git a/ellie_engine/tokenizer/src/processors/items/constructor_processor.rs b/ellie_engine/tokenizer/src/processors/items/constructor_processor.rs index 5d266602..0fc2c213 100644 --- a/ellie_engine/tokenizer/src/processors/items/constructor_processor.rs +++ b/ellie_engine/tokenizer/src/processors/items/constructor_processor.rs @@ -27,6 +27,7 @@ impl crate::processors::Processor for constructor::Constructor { range_start: cursor, ..Default::default() }, + body_element_defiener: false, }) } else { if self.parameters[parameter_len - 1].name == "" { diff --git a/ellie_engine/tokenizer/src/syntax/items/constructor.rs b/ellie_engine/tokenizer/src/syntax/items/constructor.rs index 188cebb1..1c90402a 100644 --- a/ellie_engine/tokenizer/src/syntax/items/constructor.rs +++ b/ellie_engine/tokenizer/src/syntax/items/constructor.rs @@ -7,6 +7,8 @@ use crate::processors::items::Processors; pub struct ConstructorParameter { pub name: String, pub pos: defs::Cursor, + // When class is defined, by the design variables are not + pub body_element_defiener: bool, } #[derive(Default, Debug, Clone, Serialize, Deserialize)] @@ -58,6 +60,7 @@ impl Converter Date: Sun, 21 Apr 2024 23:21:35 +0300 Subject: [PATCH 08/30] Fix error printing and add error handling in compile_file.rs --- elliec/src/compile_file.rs | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/elliec/src/compile_file.rs b/elliec/src/compile_file.rs index 0e5aa777..9547aaf4 100644 --- a/elliec/src/compile_file.rs +++ b/elliec/src/compile_file.rs @@ -766,9 +766,10 @@ pub fn compile( key: "errors".to_string(), value: errors, }); - println!("{}", serde_json::to_string(&output).unwrap()); + eprintln!("{}", serde_json::to_string(&output).unwrap()); + std::process::exit(1); } else { - println!( + eprintln!( "{}", print_errors( &errors, @@ -900,6 +901,7 @@ pub fn compile( for message in exit_messages.lock().unwrap().iter() { (message)(); } + std::process::exit(1); } } } @@ -911,9 +913,10 @@ pub fn compile( key: "errors".to_string(), value: pager_errors, }); - println!("{}", serde_json::to_string(&output).unwrap()); + eprintln!("{}", serde_json::to_string(&output).unwrap()); + std::process::exit(1); } else { - println!( + eprintln!( "{}", print_errors( &pager_errors, @@ -963,6 +966,7 @@ pub fn compile( for message in exit_messages.lock().unwrap().iter() { (message)(); } + std::process::exit(1); } } } From c3fb8439882f5778f070b550f8533e2eb8158ed4 Mon Sep 17 00:00:00 2001 From: Ahmetcan Aksu Date: Sun, 28 Apr 2024 18:05:29 +0300 Subject: [PATCH 09/30] Add benchmark & fix setter bug --- ellie_engine/Cargo.toml | 7 + ellie_engine/benches/codes.rs | 160 ++++++++++++++++++ ellie_engine/benches/compile.rs | 79 +++++++++ ellie_engine/benches/utils.rs | 74 ++++++++ .../src/transpiler/items/condition.rs | 17 +- .../bytecode/src/transpiler/types/operator.rs | 8 +- .../parser/src/processors/types/class_call.rs | 35 ++-- ellie_engine/src/byte_code.rs | 53 ++++++ ellie_engine/src/compiler.rs | 54 +++++- ellie_engine/src/engine_constants.rs | 6 +- ellie_engine/src/lib.rs | 5 + ellie_engine/src/tokenizer.rs | 61 +++++++ ellie_engine/vm/src/config.rs | 4 +- ellie_engine/vm/src/heap_memory.rs | 20 ++- ellie_engine/vm/src/instructions/FN.rs | 1 + ellie_engine/vm/src/stack_memory.rs | 26 ++- ellie_engine/vm/src/thread.rs | 40 ++++- elliec/Cargo.toml | 7 + elliec/build.rs | 6 + tools/run.ps1 | 23 +++ 20 files changed, 653 insertions(+), 33 deletions(-) create mode 100644 ellie_engine/benches/codes.rs create mode 100644 ellie_engine/benches/compile.rs create mode 100644 ellie_engine/benches/utils.rs create mode 100644 ellie_engine/src/byte_code.rs create mode 100644 elliec/build.rs create mode 100644 tools/run.ps1 diff --git a/ellie_engine/Cargo.toml b/ellie_engine/Cargo.toml index 9da8a9cc..f432c141 100644 --- a/ellie_engine/Cargo.toml +++ b/ellie_engine/Cargo.toml @@ -41,6 +41,13 @@ toml = "0.8.0" regex = { version = "1.1.7" } chrono = "0.4.22" +[dev-dependencies] +criterion = { version = "0.5.1", features = ["html_reports", "csv_output"] } + +[[bench]] +name = "compile" +harness = false + [workspace] members = [".", "./core", "./tokenizer", "./parser", "./bytecode", "./vm", "./fmt", "./renderer_utils" ] default-members = ["."] \ No newline at end of file diff --git a/ellie_engine/benches/codes.rs b/ellie_engine/benches/codes.rs new file mode 100644 index 00000000..92a83fab --- /dev/null +++ b/ellie_engine/benches/codes.rs @@ -0,0 +1,160 @@ + + +pub const BENCH_CLASS: &str = r#" +/// -- Required Types -- +@dont_fix_variant; +class int {} + +@dont_fix_variant; +class void {} + + +@dont_fix_variant; +class bool {} + +@dont_fix_variant; +class function {} + +@dont_fix_variant; +class string {} + +@dont_fix_variant; +class nullAble {} + +fn println(s: string); +/// -- Required Types -- + +class Human { + co(name, age); + v name : string; + v age : int; + fn introduce() : string { + ret "Hello my name is " + self.name + ", I born at " + (2023 - self.age); + } +} + + +fn main() { + v human = new Human("Ahmetcan", 22); + println(human.introduce()); +} +"#; + +pub const BENCH_LOOP: &str = r#" +/// -- Required Types -- +@dont_fix_variant; +class int {} + +@dont_fix_variant; +class void {} + + +@dont_fix_variant; +class bool {} + +@dont_fix_variant; +class function {} + +@dont_fix_variant; +class string {} + +@dont_fix_variant; +class nullAble {} + +fn println(s: string); +/// -- Required Types -- + +fn main() { + v last = 0; + v current = 1; + v count = 2; + v fib = 0; + + loop count <= 10 { + fib = last + current; + last = current; + current = fib; + count += 1; + } + + println("fib(10) = " + fib); +} +"#; + +pub const BENCH_FIBONACCI_LOOP: &str = r#" +/// -- Required Types -- +@dont_fix_variant; +class int {} + +@dont_fix_variant; +class void {} + + +@dont_fix_variant; +class bool {} + +@dont_fix_variant; +class function {} + +@dont_fix_variant; +class string {} + +@dont_fix_variant; +class nullAble {} + +fn println(s: string); +/// -- Required Types -- + +fn main() { + v last = 0; + v current = 1; + v count = 2; + v fib = 0; + + loop count <= 10 { + fib = last + current; + last = current; + current = fib; + count += 1; + } + + println("fib(10) = " + fib); +} +"#; + +pub const BENCH_FIBONACCI_RECURSION: &str = r#" +/// -- Required Types -- +@dont_fix_variant; +class int {} + +@dont_fix_variant; +class void {} + + +@dont_fix_variant; +class bool {} + +@dont_fix_variant; +class function {} + +@dont_fix_variant; +class string {} + +@dont_fix_variant; +class nullAble {} + +fn println(s: string); +/// -- Required Types -- + +fn main() { + fn fib(n: int) : int { + if n <= 1 { + ret n; + } else { + ret fib(n - 1) + fib(n - 2); + } + } + + println("fib(10) = " + fib(10)); +} +"#; diff --git a/ellie_engine/benches/compile.rs b/ellie_engine/benches/compile.rs new file mode 100644 index 00000000..cc2ef29b --- /dev/null +++ b/ellie_engine/benches/compile.rs @@ -0,0 +1,79 @@ +use criterion::{black_box, criterion_group, criterion_main, Criterion}; +use ellie_engine::{compiler, parseText}; + +use crate::codes::BENCH_FIBONACCI_RECURSION; + +pub mod codes; +pub mod utils; + +fn tokenize(c: &mut Criterion) { + c.bench_function("class_tokenize", |b| { + b.iter(|| { + let _ = black_box(utils::tokenize_code(black_box(codes::BENCH_CLASS))); + }) + }); + c.bench_function("loop_tokenize", |b| { + b.iter(|| { + let _ = black_box(utils::tokenize_code(black_box(codes::BENCH_LOOP))); + }) + }); + c.bench_function("fibonacci_loop_tokenize", |b| { + b.iter(|| { + let _ = black_box(utils::tokenize_code(black_box(codes::BENCH_FIBONACCI_LOOP))); + }) + }); + c.bench_function("fibonacci_recursion_tokenize", |b| { + b.iter(|| { + let _ = black_box(utils::tokenize_code(black_box( + codes::BENCH_FIBONACCI_RECURSION, + ))); + }) + }); +} + +fn parse(c: &mut Criterion) { + let class_tokenized = utils::tokenize_code(codes::BENCH_CLASS); + let loop_tokenized = utils::tokenize_code(codes::BENCH_LOOP); + let fibonacci_loop_tokenized = utils::tokenize_code(codes::BENCH_FIBONACCI_LOOP); + let fibonacci_recursion_tokenized = utils::tokenize_code(codes::BENCH_FIBONACCI_RECURSION); + + c.bench_function("class_parse", |b| { + b.iter(|| { + let _ = black_box(utils::parse_code(class_tokenized.clone())); + }) + }); + + c.bench_function("loop_parse", |b| { + b.iter(|| { + let _ = black_box(utils::parse_code(loop_tokenized.clone())); + }) + }); + + c.bench_function("fibonacci_loop_parse", |b| { + b.iter(|| { + let _ = black_box(utils::parse_code(fibonacci_loop_tokenized.clone())); + }) + }); + + c.bench_function("fibonacci_recursion_parse", |b| { + b.iter(|| { + let _ = black_box(utils::parse_code(fibonacci_recursion_tokenized.clone())); + }) + }); +} + +fn byte_code_assembler(c: &mut Criterion) { + let class_parse = parseText!(codes::BENCH_CLASS).expect("should've been successful"); + let loop_parse = parseText!(codes::BENCH_LOOP).expect("should've been successful"); + let fibonacci_loop_parse = parseText!(codes::BENCH_FIBONACCI_LOOP).expect("should've been successful"); + let fibonacci_recursion_parse = parseText!(codes::BENCH_FIBONACCI_RECURSION).expect("should've been successful"); + + c.bench_function("class_byte_code_assembler", |b| { + b.iter(|| { + let _ = black_box(compiler::byte_code_assembler(class_parse.clone())); + }) + }); +} + +criterion_group!(benches, tokenize, parse); +criterion_main!(benches); diff --git a/ellie_engine/benches/utils.rs b/ellie_engine/benches/utils.rs new file mode 100644 index 00000000..b9014df8 --- /dev/null +++ b/ellie_engine/benches/utils.rs @@ -0,0 +1,74 @@ +use core::hash::{Hash, Hasher}; +use std::hash::DefaultHasher; + +use ellie_core::{ + defs::{PlatformArchitecture, Version}, + error::Error, + utils::PageExport, +}; +use ellie_engine::{ + compiler, tokenizer, + utils::{CompileOutput, CompilerSettings, MainProgram, ProgramRepository}, +}; +use ellie_tokenizer::tokenizer::{Page, ResolvedImport}; + +#[derive(Clone)] +pub struct Repository { + pub code: String, + pub main_hash: usize, +} + +impl ProgramRepository for Repository { + fn read_main(&mut self) -> MainProgram { + let mut main_file_hasher = DefaultHasher::new(); + self.code.hash(&mut main_file_hasher); + let first_page_hash = main_file_hasher.finish(); + self.main_hash = first_page_hash as usize; + MainProgram { + file_content: self.code.clone(), + file_name: "playground.ei".to_string(), + file_hash: first_page_hash as usize, + start_directory: format!("",), + } + } + + fn read_module( + &mut self, + _link_module: bool, + _current_path: String, + _requested_path: String, + ) -> ResolvedImport { + panic!("Module resolver is not implemented on tests") + } +} + +pub fn tokenize_code(code: &str) -> (usize, PageExport) { + let mut program_repository = Repository { + code: code.to_string(), + main_hash: 0, + }; + let pages = tokenizer::tokenize_file(&mut program_repository).expect("should've been successful"); + ( + program_repository.main_hash, + pages, + ) +} + +pub fn parse_code( + (main_hash, pages): (usize, PageExport), +) -> Result> { + compiler::parse_pages( + main_hash, + vec![], + pages, + CompilerSettings { + name: "ellie_bench".to_string(), + file_name: String::from("ellie_bench.ei"), + is_lib: false, + description: String::from("No description"), + experimental_features: false, + byte_code_architecture: PlatformArchitecture::B32, + version: Version::build_from_string(&"0.1.0".to_string()), + }, + ) +} diff --git a/ellie_engine/bytecode/src/transpiler/items/condition.rs b/ellie_engine/bytecode/src/transpiler/items/condition.rs index 49cb53d5..876327cd 100644 --- a/ellie_engine/bytecode/src/transpiler/items/condition.rs +++ b/ellie_engine/bytecode/src/transpiler/items/condition.rs @@ -1,9 +1,5 @@ use crate::transpiler::types::{TypeTranspiler, TypeTranspilerOptions}; -use crate::{ - instruction_table, - instructions::{self, Instruction}, - types::Types, -}; +use crate::{instruction_table, instructions::Instruction, types::Types}; use alloc::{vec, vec::Vec}; use ellie_core::definite::items::condition; @@ -85,6 +81,17 @@ impl super::Transpiler for condition::Condition { assembler.instructions[pos] = instruction_table::Instructions::JMPA(Instruction::absolute(*location)); } + + // TODO: Add this, but this lacks place on debug information. + /* assembler.debug_headers.push(DebugHeader { + rtype: DebugHeaderType::Condition, + hash: limit_platform_size(self.hash, assembler.platform_attributes.architecture), + module_name: processed_page.path.clone(), + module_hash: processed_page.hash, + name: "".to_string(), + start_end: (debug_header_start, assembler.location()), + pos: self.pos, + }); */ true } } diff --git a/ellie_engine/bytecode/src/transpiler/types/operator.rs b/ellie_engine/bytecode/src/transpiler/types/operator.rs index 3c25645c..69bf66ea 100644 --- a/ellie_engine/bytecode/src/transpiler/types/operator.rs +++ b/ellie_engine/bytecode/src/transpiler/types/operator.rs @@ -19,13 +19,13 @@ impl TypeTranspiler for OperatorType { .set_target_register(Registers::B), ); - let first_operator_pos = options.assembler().location(); - options .assembler_mut() .instructions .push(Instructions::STB(Instruction::implicit())); + let first_operator_pos = options.assembler().location(); + self.second.transpile( options .copy() @@ -33,13 +33,13 @@ impl TypeTranspiler for OperatorType { .set_target_register(Registers::C), ); - let second_operator_pos = options.assembler().location(); - options .assembler_mut() .instructions .push(Instructions::STC(Instruction::implicit())); + let second_operator_pos = options.assembler().location(); + options .assembler_mut() .instructions diff --git a/ellie_engine/parser/src/processors/types/class_call.rs b/ellie_engine/parser/src/processors/types/class_call.rs index 28ef2708..b0d9b8ce 100644 --- a/ellie_engine/parser/src/processors/types/class_call.rs +++ b/ellie_engine/parser/src/processors/types/class_call.rs @@ -5,8 +5,9 @@ use ellie_core::{ }; use ellie_tokenizer::{ processors::{items::Processors as ItemProcessors, types::Processors}, - syntax::types::class_call_type, + syntax::types::{class_call_type, variable_type}, }; +use types::variable::VariableType; use crate::{ deep_search_extensions::{ @@ -318,13 +319,9 @@ impl super::TypeParserProcessor for class_call_type::ClassCallCollector { } Err(errors) } else { - let constructor = class.body.iter().find_map(|x| { - match x { - ellie_tokenizer::processors::items::Processors::Constructor( - e, - ) => Some(e), - _ => None, - } + let constructor = class.body.iter().find_map(|x| match x { + ItemProcessors::Constructor(e) => Some(e), + _ => None, }); if constructor.is_some() { @@ -612,18 +609,28 @@ impl super::TypeParserProcessor for class_call_type::ClassCallCollector { .collect::>(); for element in body_element_definer_parameters { - let found_variable_value = class.body.iter().find_map(|x| { - match x { - ellie_tokenizer::processors::items::Processors::Variable(e) => { + let found_variable_value = class + .body + .iter() + .find_map(|x| match x { + ItemProcessors::Variable(e) => { if e.data.name == element.name { - Some(e.data.value.clone()) + Some(Processors::Variable( + variable_type::VariableTypeCollector { + data: variable_type::VariableType { + value: "null".to_string(), + ..Default::default() + }, + ..Default::default() + }, + )) } else { None } } _ => None, - } - }).unwrap(); + }) + .unwrap(); params.push(types::class_call::ClassCallParameter { value: found_variable_value.to_definite(), diff --git a/ellie_engine/src/byte_code.rs b/ellie_engine/src/byte_code.rs new file mode 100644 index 00000000..2d9fe48d --- /dev/null +++ b/ellie_engine/src/byte_code.rs @@ -0,0 +1,53 @@ +use alloc::vec::Vec; +use ellie_bytecode::assembler::{self, AssembleResult, PlatformAttributes}; +use ellie_core::defs::ModuleMap; +use ellie_parser::utils::Module; + +/// Transpile parsed code +/// ## Parameters +/// * `module` - Module to transpile [`Module`] +/// * `platform_attributes` - Platform attributes [`PlatformAttributes`] +/// * * `module_maps` - Module maps [`Vec`] +/// ## Returns +/// [`AssembleResult`] of transpiled code +pub fn transpile_parsed_code( + module: Module, + platform_attributes: PlatformAttributes, + module_maps: Vec, +) -> AssembleResult { + let mut assembler = assembler::Assembler::new(module, platform_attributes); + assembler.assemble(module_maps) +} + +/// Transpile given text macro +/// ## Parameters +/// * `text` - Text to transpile [`&str`] +/// * `platform_attributes` - Platform attributes [`PlatformAttributes`] +/// * * `module_maps` - Module maps [`Vec`] +/// ## Returns +/// [`AssembleResult`] of transpiled code +/// ## Example +/// ```rust +/// use ellie_engine::byteCode; +/// let text = r#"\ +/// fn main() { +/// print("Hello, World!"); +/// } +/// "#; +/// let result = byteCode::transpileText!(text, PlatformAttributes::default(), vec![]); +/// ``` +#[macro_export] +macro_rules! transpileText { + ($text:expr, $platform_attributes:expr, $module_maps:expr) => {{ + use ellie_engine::{ + ellie_bytecode::assembler, + ellie_core::defs::{ModuleMap}, + ellie_parser::utils::Module, + }; + + let text = $text; + let module = ellie_parser::parseText!(text); + let result = ellie_engine::byteCode::transpile_parsed_code(module, $platform_attributes, $module_maps); + result + }}; +} \ No newline at end of file diff --git a/ellie_engine/src/compiler.rs b/ellie_engine/src/compiler.rs index 25138327..861c7f16 100644 --- a/ellie_engine/src/compiler.rs +++ b/ellie_engine/src/compiler.rs @@ -106,13 +106,13 @@ macro_rules! parseText { let mut parser = parser::Parser::new( pager.pages, 0, - defs::Version::build_from_string("1.0.0".to_string()), + defs::Version::build_from_string(&"1.0.0".to_string()), "main".to_string(), "".to_string(), false, false, defs::Version::build_from_string( - ellie_engine::engine_constants::ELLIE_ENGINE_VERSION.to_owned(), + &ellie_engine::engine_constants::ELLIE_ENGINE_VERSION.to_owned(), ), ); let module = parser.parse(); @@ -129,3 +129,53 @@ macro_rules! parseText { } }}; } + +#[macro_export] +macro_rules! compile_core_lib { + () => { + // get library location from environment variable + let lib_location = std::env::var("ELLIE_CORE_LIB").unwrap(); + + //Check if library exists + if !std::path::Path::new(&lib_location).exists() { + panic!("Core library not found at: {}", lib_location); + } + + #[derive(Clone)] + struct Repository { + target_path: String, + } + let mut program_repository = Repository { + target_path: String::from("./main.ei"), + }; + + impl ProgramRepository for Repository { + fn read_main(&mut self) -> MainProgram { + let text = $text; + + MainProgram { + file_content: text.to_string(), + file_name: "main.ei".to_string(), + file_hash: 0, + start_directory: format!(""), + } + } + + fn read_module( + &mut self, + link_module: bool, + current_path: String, + requested_path: String, + ) -> ResolvedImport { + ResolvedImport { + found: false, + resolve_error: "Module resolver is not implemented on macros".to_owned(), + ..Default::default() + } + } + } + + //Compile core library + + }; +} \ No newline at end of file diff --git a/ellie_engine/src/engine_constants.rs b/ellie_engine/src/engine_constants.rs index f0181164..e5e6cec5 100644 --- a/ellie_engine/src/engine_constants.rs +++ b/ellie_engine/src/engine_constants.rs @@ -6,6 +6,6 @@ pub static ELLIE_PARSER_VERSION: &str = &"0.7.2"; pub static ELLIE_BYTECODE_VERSION: &str = &"0.4.3"; pub static ELLIE_FMT_VERSION: &str = &"0.5.2"; pub static ELLIE_VM_VERSION: &str = &"0.5.4"; -pub static ELLIE_BUILD_DATE: &str = &"2023-11-09"; -pub static ELLIE_BUILD_GIT_HASH: &str = &"d9dce96"; -pub static ELLIE_BUILD_GIT_BRANCH: &str = &"main"; +pub static ELLIE_BUILD_DATE: &str = &"2024-04-23"; +pub static ELLIE_BUILD_GIT_HASH: &str = &"d4368f4"; +pub static ELLIE_BUILD_GIT_BRANCH: &str = &"ConstructorFixes"; diff --git a/ellie_engine/src/lib.rs b/ellie_engine/src/lib.rs index 1c529d1d..1e4d1fbc 100644 --- a/ellie_engine/src/lib.rs +++ b/ellie_engine/src/lib.rs @@ -49,6 +49,11 @@ pub mod compiler; /// This module contains utilities that easing up usage of tokenizer #[cfg(feature = "compiler")] pub mod tokenizer; + +/// This module contains utilities that easing up usage of bytecode +#[cfg(feature = "compiler")] +pub mod byte_code; + /// This module contains utilities that easing up usage of vm #[cfg(feature = "vm")] pub mod vm; diff --git a/ellie_engine/src/tokenizer.rs b/ellie_engine/src/tokenizer.rs index e26e9547..64a24427 100644 --- a/ellie_engine/src/tokenizer.rs +++ b/ellie_engine/src/tokenizer.rs @@ -28,3 +28,64 @@ pub fn tokenize_file( Err(errors) => Err(errors), } } + +/// Tokenize given text +/// ## Parameters +/// * `text` - Text to tokenize [`&str`] +#[macro_export] +macro_rules! tokenizeText { + ($text:expr) => {{ + use ellie_engine::{ + ellie_core::defs, + ellie_tokenizer::tokenizer::{Pager, ResolvedImport}, + utils::{MainProgram, ProgramRepository}, + }; + + #[derive(Clone)] + struct Repository { + target_path: String, + } + let mut program_repository = Repository { + target_path: String::from("./main.ei"), + }; + + impl ProgramRepository for Repository { + fn read_main(&mut self) -> MainProgram { + let text = $text; + + MainProgram { + file_content: text.to_string(), + file_name: "main.ei".to_string(), + file_hash: 0, + start_directory: format!(""), + } + } + + fn read_module( + &mut self, + link_module: bool, + current_path: String, + requested_path: String, + ) -> ResolvedImport { + ResolvedImport { + found: false, + resolve_error: "Module resolver is not implemented on macros".to_owned(), + ..Default::default() + } + } + } + let main_program = program_repository.read_main(); + + let mut pager = Pager::new( + main_program.file_content, + main_program.file_name, + format!("{}/", main_program.start_directory), + move |link_module, path, module_identifier| { + program_repository.read_module(link_module, path.clone(), module_identifier) + }, + main_program.file_hash, + ); + + pager.run() + }}; +} diff --git a/ellie_engine/vm/src/config.rs b/ellie_engine/vm/src/config.rs index 405c2510..c91b9fd9 100644 --- a/ellie_engine/vm/src/config.rs +++ b/ellie_engine/vm/src/config.rs @@ -1,10 +1,10 @@ // VM's stack memory size // 24 * 1024 = 24kb -pub const STACK_MEMORY_SIZE: usize = 2048; +pub const STACK_MEMORY_SIZE: usize = 4048 + 1024; // VM's stack size // 168 * 512 = 86kb -pub const STACK_SIZE: usize = 1024; +pub const STACK_SIZE: usize = 256; //Program size // 48 * 4096 = 196kb diff --git a/ellie_engine/vm/src/heap_memory.rs b/ellie_engine/vm/src/heap_memory.rs index 50624185..9149b879 100644 --- a/ellie_engine/vm/src/heap_memory.rs +++ b/ellie_engine/vm/src/heap_memory.rs @@ -1,23 +1,40 @@ use crate::raw_type::{MutatableRawType, RawType}; use alloc::{ + boxed::Box, collections::BTreeMap, format, string::{String, ToString}, vec::Vec, }; -#[derive(Clone)] +pub type HeapOutOfMemoryCallback = Box; + pub struct HeapMemory { pub data: BTreeMap>, + pub on_heap_out_of_memory: Option, +} + +impl Clone for HeapMemory { + fn clone(&self) -> Self { + HeapMemory { + data: self.data.clone(), + on_heap_out_of_memory: None, + } + } } impl HeapMemory { pub fn new() -> HeapMemory { HeapMemory { data: BTreeMap::new(), + on_heap_out_of_memory: None, } } + pub fn set_on_heap_out_of_memory(&mut self, callback: HeapOutOfMemoryCallback) { + self.on_heap_out_of_memory = Some(callback); + } + pub fn get_mut(&mut self, key: &usize) -> Option { self.data.get_mut(key).map(|data| MutatableRawType { data }) } @@ -40,6 +57,7 @@ impl HeapMemory { } pub fn set(&mut self, key: &usize, value: RawType) { + self.data.insert(*key, value.to_bytes()); } diff --git a/ellie_engine/vm/src/instructions/FN.rs b/ellie_engine/vm/src/instructions/FN.rs index 6acd7d4a..619ad62e 100644 --- a/ellie_engine/vm/src/instructions/FN.rs +++ b/ellie_engine/vm/src/instructions/FN.rs @@ -25,6 +25,7 @@ impl super::InstructionExecuter for FN { match &addressing_value { AddressingValues::Immediate(e) => { let hash: usize = e.to_int() as usize; + std::println!("Hash: {}, {}", current_stack.frame_pos, current_stack.pos); stack_memory.set(¤t_stack.get_pos(), StaticRawType::from_function(hash)); let end_point = match &program[current_stack.pos + 1].addressing_value { AddressingValues::Immediate(e) => e.to_int() as usize, diff --git a/ellie_engine/vm/src/stack_memory.rs b/ellie_engine/vm/src/stack_memory.rs index 05fb135a..6e6617dc 100644 --- a/ellie_engine/vm/src/stack_memory.rs +++ b/ellie_engine/vm/src/stack_memory.rs @@ -1,15 +1,28 @@ use alloc::{ + boxed::Box, format, string::{String, ToString}, }; use crate::{config::STACK_MEMORY_SIZE, raw_type::StaticRawType}; +pub type StackOverflowCallback = Box; + //Static memory allocation -#[derive(Clone, Copy)] pub struct StackMemory { pub data: [StaticRawType; STACK_MEMORY_SIZE], pub len: usize, + pub on_stack_overflow: Option, +} + +impl Clone for StackMemory { + fn clone(&self) -> Self { + StackMemory { + data: self.data.clone(), + len: self.len, + on_stack_overflow: None, + } + } } impl StackMemory { @@ -17,9 +30,14 @@ impl StackMemory { StackMemory { data: [StaticRawType::from_void(); STACK_MEMORY_SIZE], len: 0, + on_stack_overflow: None, } } + pub fn set_on_stack_overflow(&mut self, callback: StackOverflowCallback) { + self.on_stack_overflow = Some(callback); + } + pub fn get(&self, key: &usize) -> Option { if self.data.len() <= *key { None @@ -29,6 +47,12 @@ impl StackMemory { } pub fn set(&mut self, key: &usize, value: StaticRawType) { + if (self.data.len() - 1) < *key { + if let Some(callback) = &mut self.on_stack_overflow { + callback(); + return; + } + } self.data[*key] = value; } diff --git a/ellie_engine/vm/src/thread.rs b/ellie_engine/vm/src/thread.rs index ce56b2f4..1ad43f4f 100644 --- a/ellie_engine/vm/src/thread.rs +++ b/ellie_engine/vm/src/thread.rs @@ -1,5 +1,7 @@ #![allow(non_snake_case)] -use alloc::{format, string::String}; +use core::sync::atomic::{AtomicBool, Ordering}; + +use alloc::{boxed::Box, format, string::String}; use ellie_core::defs::PlatformArchitecture; use crate::{ @@ -83,6 +85,12 @@ impl Thread { pos: main.start, frame_pos: main.start + main.length, }); + std::println!( + "THREAD BUILDED WITH frame_pos: start: {}, length: {}, f: {}", + main.start, + main.length, + main.start + main.length + ); } pub fn call(&mut self) { @@ -356,6 +364,30 @@ impl Thread { ¤t_instruction.addressing_value, self.arch, ); + + static STACK_OVERFLOW: AtomicBool = AtomicBool::new(false); + static HEAP_OUT_OF_MEMORY: AtomicBool = AtomicBool::new(false); + + self.isolate + .heap_memory + .set_on_heap_out_of_memory(Box::new(|| { + HEAP_OUT_OF_MEMORY.store(true, Ordering::Relaxed); + })); + + /* self.isolate + .stack_memory + .set_on_stack_overflow(Box::new(|| { + STACK_OVERFLOW.store(true, Ordering::Relaxed); + })); */ + + if STACK_OVERFLOW.load(Ordering::SeqCst) { + return ThreadExit::Panic(ThreadPanic { + reason: ThreadPanicReason::StackOverflow, + stack_trace: self.stack.clone(), + code_location: format!("{}:{}", file!(), line!()), + }); + } + match execute_result { Ok(result) => match result { crate::instructions::ExecuterResult::Continue => { @@ -383,6 +415,12 @@ impl Thread { }); let current_x = current_stack.registers.X; let frame_pos = current_stack.get_pos() + e.stack_len; + std::println!( + "NEW frame_pos: {}, current_stack.get_pos(): {}, e.stack_len: {}", + frame_pos, + current_stack.get_pos(), + e.stack_len + ); current_stack.pos += 1; self.stack.push(Stack { pos: e.pos, diff --git a/elliec/Cargo.toml b/elliec/Cargo.toml index bbaecb96..577608e1 100644 --- a/elliec/Cargo.toml +++ b/elliec/Cargo.toml @@ -17,3 +17,10 @@ ellie_engine = { path = "../ellie_engine", default-features = false, features = "cli-utils", ] } bincode = { version = "1.3.3" } + +[build-dependencies] +winresource = { version = "0.1.0" } + +[package.metadata.winresource] +OriginalFilename = "elliec.exe" +LegalCopyright = "Copyright (c) 2020 Behemehal. Licensed under GPL-2.0." \ No newline at end of file diff --git a/elliec/build.rs b/elliec/build.rs new file mode 100644 index 00000000..c6785d68 --- /dev/null +++ b/elliec/build.rs @@ -0,0 +1,6 @@ +fn main() { + if std::env::var("CARGO_CFG_TARGET_OS").unwrap() == "windows" { + let mut res = winresource::WindowsResource::new(); + res.compile().unwrap(); + } +} diff --git a/tools/run.ps1 b/tools/run.ps1 new file mode 100644 index 00000000..81bb7e44 --- /dev/null +++ b/tools/run.ps1 @@ -0,0 +1,23 @@ +param ( + [string]$inputFilePath, + [string]$additionalParams +) + +# Define the compile and run commands with manifest paths +$compileCommand = "cargo run --manifest-path=../elliec/Cargo.toml -- compile $inputFilePath -s -a -e -o $additionalParams" +$runCommand = "cargo run --manifest-path=../ellievm/Cargo.toml -- run $($inputFilePath -replace '\.ei$', '.eic') -d $($inputFilePath -replace '\.ei$', '.eig') -a" + +# Start the compile command process +$compileProcess = Start-Process -FilePath "cmd" -ArgumentList "/c $compileCommand" -PassThru -NoNewWindow + +# Wait for the compile process to complete +$compileProcess.WaitForExit() + +# Check if the compile process exited with an error and if StandardError is not null +if ($compileProcess.ExitCode -ne 0) { + Write-Output "Compile command failed with exit code $($compileProcess.ExitCode). Error output:" +} else { + Write-Output "Compile command completed successfully." + # Execute the run command if the compile command succeeded + Invoke-Expression $runCommand +} From d1c19f58c769a72b8b5f5f43edc9c8f22e0aa39c Mon Sep 17 00:00:00 2001 From: ahmtcn123 Date: Thu, 6 Jun 2024 12:28:57 +0300 Subject: [PATCH 10/30] Prevent main function to have parameters --- ellie_engine/core/src/error/error_list.rs | 6 ++++++ ellie_engine/parser/src/parser.rs | 23 +++++++++++++++++++++-- ellie_engine/vm/src/instructions/FN.rs | 1 - ellie_engine/vm/src/thread.rs | 12 ------------ 4 files changed, 27 insertions(+), 15 deletions(-) diff --git a/ellie_engine/core/src/error/error_list.rs b/ellie_engine/core/src/error/error_list.rs index 30dae547..d6c83698 100644 --- a/ellie_engine/core/src/error/error_list.rs +++ b/ellie_engine/core/src/error/error_list.rs @@ -413,4 +413,10 @@ lazy_static! { message: "Cannot apply unary operator".to_owned(), ..Default::default() }; + pub static ref ERROR_S67: error::Error = error::Error { + code: 0x66, + title: "ReferenceError".to_owned(), + message: "Wrong main function signature, expected 'fn main() -> void'".to_owned(), + ..Default::default() + }; } diff --git a/ellie_engine/parser/src/parser.rs b/ellie_engine/parser/src/parser.rs index cd232750..c6eb3128 100644 --- a/ellie_engine/parser/src/parser.rs +++ b/ellie_engine/parser/src/parser.rs @@ -622,7 +622,9 @@ impl Parser { defining.to_string(), "dyn".to_owned(), )) - } else if let ellie_core::definite::definers::DefinerCollecting::ParentGeneric(_) = defining { + } else if let ellie_core::definite::definers::DefinerCollecting::ParentGeneric(_) = + defining + { Ok(CompareResult::result( true, defining.to_string(), @@ -1952,7 +1954,24 @@ impl Parser { self.deep_search(self.initial_page, "main".to_string(), None, vec![], 0, None); if main_function.found { match main_function.found_item { - DeepSearchItems::Function(_) => (), + DeepSearchItems::Function(e) => { + if e.parameters.len() > 0 { + let path = self.find_page(self.initial_page).unwrap().path.clone(); + self.informations.push( + &error::error_list::ERROR_S67.clone().build_with_path( + vec![], + alloc::format!( + "{}:{}:{}", + file!().to_owned(), + line!(), + column!() + ), + path, + e.name_pos, + ), + ); + } + } _ => { let path = self.find_page(self.initial_page).unwrap().path.clone(); self.informations.push( diff --git a/ellie_engine/vm/src/instructions/FN.rs b/ellie_engine/vm/src/instructions/FN.rs index 619ad62e..6acd7d4a 100644 --- a/ellie_engine/vm/src/instructions/FN.rs +++ b/ellie_engine/vm/src/instructions/FN.rs @@ -25,7 +25,6 @@ impl super::InstructionExecuter for FN { match &addressing_value { AddressingValues::Immediate(e) => { let hash: usize = e.to_int() as usize; - std::println!("Hash: {}, {}", current_stack.frame_pos, current_stack.pos); stack_memory.set(¤t_stack.get_pos(), StaticRawType::from_function(hash)); let end_point = match &program[current_stack.pos + 1].addressing_value { AddressingValues::Immediate(e) => e.to_int() as usize, diff --git a/ellie_engine/vm/src/thread.rs b/ellie_engine/vm/src/thread.rs index 1ad43f4f..f023448b 100644 --- a/ellie_engine/vm/src/thread.rs +++ b/ellie_engine/vm/src/thread.rs @@ -85,12 +85,6 @@ impl Thread { pos: main.start, frame_pos: main.start + main.length, }); - std::println!( - "THREAD BUILDED WITH frame_pos: start: {}, length: {}, f: {}", - main.start, - main.length, - main.start + main.length - ); } pub fn call(&mut self) { @@ -415,12 +409,6 @@ impl Thread { }); let current_x = current_stack.registers.X; let frame_pos = current_stack.get_pos() + e.stack_len; - std::println!( - "NEW frame_pos: {}, current_stack.get_pos(): {}, e.stack_len: {}", - frame_pos, - current_stack.get_pos(), - e.stack_len - ); current_stack.pos += 1; self.stack.push(Stack { pos: e.pos, From 281edf0a8a76a51ffe785b398408ec8f8067ca7f Mon Sep 17 00:00:00 2001 From: ahmtcn123 Date: Thu, 6 Jun 2024 17:53:14 +0300 Subject: [PATCH 11/30] Fix constructor size bug --- ellie_engine/parser/src/processors/types/class_call.rs | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/ellie_engine/parser/src/processors/types/class_call.rs b/ellie_engine/parser/src/processors/types/class_call.rs index b0d9b8ce..1a0ac514 100644 --- a/ellie_engine/parser/src/processors/types/class_call.rs +++ b/ellie_engine/parser/src/processors/types/class_call.rs @@ -346,11 +346,7 @@ impl super::TypeParserProcessor for class_call_type::ClassCallCollector { }, error::ErrorBuildField { key: "token".to_string(), - value: constructor - .unwrap() - .parameters - .len() - .to_string(), + value: constructor_size.to_string(), }, error::ErrorBuildField { key: "token2".to_string(), From a2e0c4e10f334e4d6810fb3f43a582a03f15ff6d Mon Sep 17 00:00:00 2001 From: ahmtcn123 Date: Thu, 6 Jun 2024 17:56:50 +0300 Subject: [PATCH 12/30] Fix old code on integration test --- tools/integration_test/src/main.rs | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/tools/integration_test/src/main.rs b/tools/integration_test/src/main.rs index 7dd8c89b..41b0f268 100644 --- a/tools/integration_test/src/main.rs +++ b/tools/integration_test/src/main.rs @@ -23,9 +23,11 @@ fn run(program: Program, assembler_result: AssembleResult) { let main = program.main.clone(); let mut module_manager = ModuleManager::new(); - let mut vm_program = VmProgram::new_from_vector(program.instructions); + let mut vm_program = VmProgram::new(); - module_manager.register_module(EllieModule::new("ellieStd".to_owned(), 0)); + vm_program.fill_from_vector(program.instructions); + + module_manager.register_module(EllieModule::new("ellieCore".to_owned())); let println = match assembler_result .native_exports @@ -37,11 +39,11 @@ fn run(program: Program, assembler_result: AssembleResult) { }; module_manager - .get_module(0) + .get_module("ellieCore") .unwrap() .register_element(ModuleElements::Function(FunctionElement { - name: "println".to_owned(), - hash: println, + name: "println", + hash: None, callback: Box::new(|thread_info, params| match ¶ms[0] { VmNativeCallParameters::Static(_) => VmNativeAnswer::RuntimeError( "println: Expected string, given static argument".to_owned(), @@ -330,7 +332,7 @@ fn compile() -> AssembleResult { v age = new Age(1); v human = new Human(\"Ahmet\", age); println(\"age: \" + human.age.num); - ((human.age.age(); + //((human.age.age(); //panic(\"Let's see\"); } " From fb990b489264fa1a31baf7ecc4a63e8132c4a330 Mon Sep 17 00:00:00 2001 From: ahmtcn123 Date: Thu, 6 Jun 2024 18:01:57 +0300 Subject: [PATCH 13/30] Add display instead of int on panics --- ellie_engine/vm/src/instructions/ADD.rs | 4 ++-- ellie_engine/vm/src/instructions/DIV.rs | 4 ++-- ellie_engine/vm/src/instructions/EXP.rs | 4 ++-- ellie_engine/vm/src/instructions/MUL.rs | 4 ++-- ellie_engine/vm/src/instructions/SUB.rs | 4 ++-- ellie_engine/vm/src/instructions/_MOD.rs | 4 ++-- ellie_engine/vm/src/utils.rs | 2 +- 7 files changed, 13 insertions(+), 13 deletions(-) diff --git a/ellie_engine/vm/src/instructions/ADD.rs b/ellie_engine/vm/src/instructions/ADD.rs index dbf54038..0e2c4ca2 100644 --- a/ellie_engine/vm/src/instructions/ADD.rs +++ b/ellie_engine/vm/src/instructions/ADD.rs @@ -209,8 +209,8 @@ impl super::InstructionExecuter for ADD { _ => { return Err(ExecuterPanic { reason: ThreadPanicReason::UnmergebleTypes( - B.type_id().id, - C.type_id().id, + format!("{}", B.type_id()), + format!("{}", C.type_id()), ), code_location: format!("{}:{}", file!(), line!()), }); diff --git a/ellie_engine/vm/src/instructions/DIV.rs b/ellie_engine/vm/src/instructions/DIV.rs index 5fbb16dd..72640306 100644 --- a/ellie_engine/vm/src/instructions/DIV.rs +++ b/ellie_engine/vm/src/instructions/DIV.rs @@ -85,8 +85,8 @@ impl super::InstructionExecuter for DIV { _ => { return Err(ExecuterPanic { reason: ThreadPanicReason::UnmergebleTypes( - current_stack.registers.B.type_id.id, - current_stack.registers.C.type_id.id, + format!("{}", current_stack.registers.B.type_id), + format!("{}", current_stack.registers.C.type_id), ), code_location: format!("{}:{}", file!(), line!()), }); diff --git a/ellie_engine/vm/src/instructions/EXP.rs b/ellie_engine/vm/src/instructions/EXP.rs index 207c0546..17a57709 100644 --- a/ellie_engine/vm/src/instructions/EXP.rs +++ b/ellie_engine/vm/src/instructions/EXP.rs @@ -80,8 +80,8 @@ impl super::InstructionExecuter for EXP { _ => { return Err(ExecuterPanic { reason: ThreadPanicReason::UnmergebleTypes( - current_stack.registers.B.type_id.id, - current_stack.registers.C.type_id.id, + format!("{}", current_stack.registers.B.type_id), + format!("{}", current_stack.registers.C.type_id), ), code_location: format!("{}:{}", file!(), line!()), }); diff --git a/ellie_engine/vm/src/instructions/MUL.rs b/ellie_engine/vm/src/instructions/MUL.rs index 4bfad070..13539ad4 100644 --- a/ellie_engine/vm/src/instructions/MUL.rs +++ b/ellie_engine/vm/src/instructions/MUL.rs @@ -85,8 +85,8 @@ impl super::InstructionExecuter for MUL { _ => { return Err(ExecuterPanic { reason: ThreadPanicReason::UnmergebleTypes( - current_stack.registers.B.type_id.id, - current_stack.registers.C.type_id.id, + format!("{}", current_stack.registers.B.type_id), + format!("{}", current_stack.registers.C.type_id), ), code_location: format!("{}:{}", file!(), line!()), }); diff --git a/ellie_engine/vm/src/instructions/SUB.rs b/ellie_engine/vm/src/instructions/SUB.rs index b3e8f598..9590b3ae 100644 --- a/ellie_engine/vm/src/instructions/SUB.rs +++ b/ellie_engine/vm/src/instructions/SUB.rs @@ -85,8 +85,8 @@ impl super::InstructionExecuter for SUB { _ => { return Err(ExecuterPanic { reason: ThreadPanicReason::UnmergebleTypes( - current_stack.registers.B.type_id.id, - current_stack.registers.C.type_id.id, + format!("{}", current_stack.registers.B.type_id), + format!("{}", current_stack.registers.C.type_id), ), code_location: format!("{}:{}", file!(), line!()), }); diff --git a/ellie_engine/vm/src/instructions/_MOD.rs b/ellie_engine/vm/src/instructions/_MOD.rs index c72e1938..8c761224 100644 --- a/ellie_engine/vm/src/instructions/_MOD.rs +++ b/ellie_engine/vm/src/instructions/_MOD.rs @@ -77,8 +77,8 @@ impl super::InstructionExecuter for MOD { _ => { return Err(ExecuterPanic { reason: ThreadPanicReason::UnmergebleTypes( - current_stack.registers.B.type_id.id, - current_stack.registers.C.type_id.id, + format!("{}", current_stack.registers.B.type_id), + format!("{}", current_stack.registers.C.type_id), ), code_location: format!("{}:{}", file!(), line!()), }); diff --git a/ellie_engine/vm/src/utils.rs b/ellie_engine/vm/src/utils.rs index 45d25def..a2aaae28 100644 --- a/ellie_engine/vm/src/utils.rs +++ b/ellie_engine/vm/src/utils.rs @@ -62,7 +62,7 @@ pub enum ThreadPanicReason { FloatOverflow, DoubleOverflow, /// This panic triggered when the types are not mergeble with each other MOD, DIV, MUL, EXP, SUB AND ADD instructions can trigger this panic - UnmergebleTypes(u8, u8), + UnmergebleTypes(String, String), /// This panic triggered when the types are not comparable with each other UncomparableTypes(u8, u8), /// This panic triggered when stack exceeded the maximum size From 6b5a2828afe7e55d68aba83a9890511c37590033 Mon Sep 17 00:00:00 2001 From: ahmtcn123 Date: Fri, 7 Jun 2024 09:59:54 +0300 Subject: [PATCH 14/30] Correct in boy variable defining --- .../src/transpiler/items/getter_call.rs | 3 - .../src/processors/items/constructor.rs | 69 ++++++++++--------- .../src/processors/items/class_processor.rs | 1 + 3 files changed, 38 insertions(+), 35 deletions(-) diff --git a/ellie_engine/bytecode/src/transpiler/items/getter_call.rs b/ellie_engine/bytecode/src/transpiler/items/getter_call.rs index c76e719c..ca46846b 100644 --- a/ellie_engine/bytecode/src/transpiler/items/getter_call.rs +++ b/ellie_engine/bytecode/src/transpiler/items/getter_call.rs @@ -21,9 +21,6 @@ impl super::Transpiler for getter_call::GetterCall { let mut binding = TypeTranspilerOptions::new(); - - std::println!("GetterCallDeps: {:#?}", dependencies); - self.data.transpile( binding .set_assembler(assembler) diff --git a/ellie_engine/parser/src/processors/items/constructor.rs b/ellie_engine/parser/src/processors/items/constructor.rs index b24f58f4..07f954f5 100644 --- a/ellie_engine/parser/src/processors/items/constructor.rs +++ b/ellie_engine/parser/src/processors/items/constructor.rs @@ -107,7 +107,10 @@ impl super::ItemParserProcessor for Constructor { .iter() .filter_map(|item| match item.as_variable() { Some(e) => { - if e.data.has_value && !self.parameters.iter().any(|g| g.name == e.data.name) { + //TODO: IS THIS NECCESSARY? + if e.data.has_value + /* && !self.parameters.iter().any(|g| g.name == e.data.name) */ + { e.data.has_value.then_some(e) } else { None @@ -116,38 +119,40 @@ impl super::ItemParserProcessor for Constructor { None => None, }) { - if !self.parameters.iter().any(|g| g.name == variable.data.name) { - let self_setter = Processors::SetterCall(SetterCall { - target: TypeProcessor::Reference(ReferenceTypeCollector { - data: ReferenceType { - reference: Box::new(TypeProcessor::Variable(VariableTypeCollector { - data: VariableType { - value: "self".to_owned(), - ..Default::default() - }, + //TODO: IS THIS NECCESSARY? + /* if !self.parameters.iter().any(|g| g.name == variable.data.name) { */ + let self_setter = Processors::SetterCall(SetterCall { + target: TypeProcessor::Reference(ReferenceTypeCollector { + data: ReferenceType { + reference: Box::new(TypeProcessor::Variable(VariableTypeCollector { + data: VariableType { + value: "self".to_owned(), ..Default::default() - })), - chain: vec![Chain { - value: variable.data.name.clone(), - ..Default::default() - }], + }, ..Default::default() - }, + })), + chain: vec![Chain { + value: variable.data.name.clone(), + ..Default::default() + }], ..Default::default() - }), - value: variable.data.value.clone(), - operator: AssignmentOperators::Assignment, - hash: generate_hash_usize(), - ..Default::default() - }); - items.push(self_setter); - parameters.push( - ellie_core::definite::items::constructor::ConstructorParameter { - name: variable.data.name.clone(), - pos: variable.data.pos, }, - ); - } + ..Default::default() + }), + value: variable.data.value.clone(), + operator: AssignmentOperators::Assignment, + hash: generate_hash_usize(), + ..Default::default() + }); + items.push(self_setter); + //TODO: IS THIS NECCESSARY? + /* parameters.push( + ellie_core::definite::items::constructor::ConstructorParameter { + name: variable.data.name.clone(), + pos: variable.data.pos, + }, + ); */ + /* } */ } for (index, parameter) in self.parameters.clone().iter().enumerate() { @@ -223,13 +228,13 @@ impl super::ItemParserProcessor for Constructor { ), ); } - - parameters.push( + //TODO: IS THIS NECCESSARY? + /* parameters.push( ellie_core::definite::items::constructor::ConstructorParameter { name: parameter.name.clone(), pos: parameter.pos, }, - ); + ); */ } items.extend(self.inside_code.clone()); let inner_page_id: usize = ellie_core::utils::generate_hash_usize(); diff --git a/ellie_engine/tokenizer/src/processors/items/class_processor.rs b/ellie_engine/tokenizer/src/processors/items/class_processor.rs index 19c41d10..0afbe049 100644 --- a/ellie_engine/tokenizer/src/processors/items/class_processor.rs +++ b/ellie_engine/tokenizer/src/processors/items/class_processor.rs @@ -169,6 +169,7 @@ impl crate::processors::Processor for class::Class { }) .collect::>(); + //TODO: IS THIS NECESSARY? for variable in find_unused_variables_in_class_body { constructor .parameters From d60eec27986280b3f583d294bd07fea1bde597b2 Mon Sep 17 00:00:00 2001 From: ahmtcn123 Date: Fri, 7 Jun 2024 17:44:13 +0300 Subject: [PATCH 15/30] Implement conversion between string and class --- ellie_engine/core/src/utils/mod.rs | 2 +- ellie_engine/vm/src/instructions/A2S.rs | 15 ++++++--------- 2 files changed, 7 insertions(+), 10 deletions(-) diff --git a/ellie_engine/core/src/utils/mod.rs b/ellie_engine/core/src/utils/mod.rs index 0b2e7830..f4665be2 100644 --- a/ellie_engine/core/src/utils/mod.rs +++ b/ellie_engine/core/src/utils/mod.rs @@ -260,7 +260,7 @@ pub fn colapseable_operator(parent: Operators, child: Operators) -> bool { }, } } - Operators::AssignmentType(_) => todo!(), + Operators::AssignmentType(child_inner) => true, Operators::Null => todo!(), } } diff --git a/ellie_engine/vm/src/instructions/A2S.rs b/ellie_engine/vm/src/instructions/A2S.rs index 38e817b7..7a8bca95 100644 --- a/ellie_engine/vm/src/instructions/A2S.rs +++ b/ellie_engine/vm/src/instructions/A2S.rs @@ -56,16 +56,13 @@ impl super::InstructionExecuter for A2S { StaticRawType::from_heap_reference(current_stack.get_pos()); } 11 => { - let class_ref = current_stack.registers.A.to_uint(); - let class = heap_memory.get(&class_ref); - - panic!("Conver: {:#?}, ", class); - - //let data = current_stack.registers.A.to_short().to_string(); - //heap_memory.set(¤t_stack.get_pos(), RawType::generate_string(data)); - //current_stack.registers.A = - // StaticRawType::from_heap_reference(current_stack.get_pos()); + heap_memory.set( + ¤t_stack.get_pos(), + RawType::generate_string(format!("Class<{:#?}>", class_ref)), + ); + current_stack.registers.A = + StaticRawType::from_heap_reference(current_stack.get_pos()); } e => { return Err(ExecuterPanic { From b6438176a3aca4133fc6e1339d534cb1ab669031 Mon Sep 17 00:00:00 2001 From: ahmtcn123 Date: Fri, 7 Jun 2024 18:00:08 +0300 Subject: [PATCH 16/30] Remove possible unnecessary parameter usage --- .../parser/src/processors/items/constructor.rs | 2 +- .../parser/src/processors/types/class_call.rs | 18 ++++++++++++++++-- 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/ellie_engine/parser/src/processors/items/constructor.rs b/ellie_engine/parser/src/processors/items/constructor.rs index 07f954f5..3d6e90c6 100644 --- a/ellie_engine/parser/src/processors/items/constructor.rs +++ b/ellie_engine/parser/src/processors/items/constructor.rs @@ -203,7 +203,7 @@ impl super::ItemParserProcessor for Constructor { } } - if !param_found { + if !param_found && parameter.name != "self" { let mut err = error::error_list::ERROR_S34.clone().build_with_path( vec![error::ErrorBuildField { key: "token".to_owned(), diff --git a/ellie_engine/parser/src/processors/types/class_call.rs b/ellie_engine/parser/src/processors/types/class_call.rs index 1a0ac514..5ec951b9 100644 --- a/ellie_engine/parser/src/processors/types/class_call.rs +++ b/ellie_engine/parser/src/processors/types/class_call.rs @@ -604,7 +604,21 @@ impl super::TypeParserProcessor for class_call_type::ClassCallCollector { .filter(|x| x.body_element_defiener) .collect::>(); - for element in body_element_definer_parameters { + params.push(types::class_call::ClassCallParameter { + value: Processors::Variable( + variable_type::VariableTypeCollector { + data: variable_type::VariableType { + value: "null".to_string(), + ..Default::default() + }, + ..Default::default() + }, + ) + .to_definite(), + pos: self.data.target_pos, + }); + + /* for element in body_element_definer_parameters { let found_variable_value = class .body .iter() @@ -633,7 +647,7 @@ impl super::TypeParserProcessor for class_call_type::ClassCallCollector { pos: element.pos, }); } - + */ Ok(types::Types::ClassCall( ellie_core::definite::types::class_call::ClassCall { target: Box::new(ellie_core::definite::types::Types::VariableType( From 953809f4097a610d512ee63fb9a4e3569c3033e0 Mon Sep 17 00:00:00 2001 From: ahmtcn123 Date: Mon, 17 Jun 2024 18:16:04 +0300 Subject: [PATCH 17/30] Add types to constructor --- .../core/src/definite/items/constructor.rs | 4 +- .../src/processors/items/constructor.rs | 66 +++++++++++++------ .../src/processors/items/class_processor.rs | 2 + .../processors/items/constructor_processor.rs | 1 + .../tokenizer/src/syntax/items/constructor.rs | 8 ++- 5 files changed, 58 insertions(+), 23 deletions(-) diff --git a/ellie_engine/core/src/definite/items/constructor.rs b/ellie_engine/core/src/definite/items/constructor.rs index 3f25a748..1769f486 100644 --- a/ellie_engine/core/src/definite/items/constructor.rs +++ b/ellie_engine/core/src/definite/items/constructor.rs @@ -1,4 +1,4 @@ -use crate::defs; +use crate::{definite::definers, defs}; use alloc::{string::String, vec::Vec}; use serde::{Deserialize, Serialize}; @@ -6,6 +6,8 @@ use serde::{Deserialize, Serialize}; pub struct ConstructorParameter { pub name: String, pub pos: defs::Cursor, + pub rtype: definers::DefinerCollecting, + pub rtype_pos: defs::Cursor, } #[derive(PartialEq, Debug, Clone, Serialize, Deserialize)] diff --git a/ellie_engine/parser/src/processors/items/constructor.rs b/ellie_engine/parser/src/processors/items/constructor.rs index 3d6e90c6..a2257ec9 100644 --- a/ellie_engine/parser/src/processors/items/constructor.rs +++ b/ellie_engine/parser/src/processors/items/constructor.rs @@ -1,4 +1,5 @@ use alloc::{borrow::ToOwned, boxed::Box, vec, vec::Vec}; +use ellie_core::definite::Converter; use ellie_core::{error, utils::generate_hash_usize}; use ellie_tokenizer::{ processors::{items::Processors, types::Processors as TypeProcessor}, @@ -99,6 +100,14 @@ impl super::ItemParserProcessor for Constructor { ellie_core::definite::items::constructor::ConstructorParameter { name: "self".to_owned(), pos: self.pos, + rtype: ellie_core::definite::definers::DefinerCollecting::Generic( + ellie_core::definite::definers::GenericType { + rtype: class_element.name, + pos: class_element.pos, + hash: class_element.hash, + }, + ), + rtype_pos: class_page_type.pos, }, ); @@ -146,13 +155,14 @@ impl super::ItemParserProcessor for Constructor { }); items.push(self_setter); //TODO: IS THIS NECCESSARY? - /* parameters.push( + parameters.push( ellie_core::definite::items::constructor::ConstructorParameter { name: variable.data.name.clone(), pos: variable.data.pos, + rtype: variable.data.rtype.definer_type.clone().to_definite(), + rtype_pos: variable.data.rtype.pos, }, - ); */ - /* } */ + ); } for (index, parameter) in self.parameters.clone().iter().enumerate() { @@ -188,22 +198,18 @@ impl super::ItemParserProcessor for Constructor { options.parser.informations.push(&err); } } - let mut param_found = false; - let mut found_is_constant_variable = None; + let mut found_param = None; let page = options.parser.find_page(options.page_hash).unwrap(); for item in page.items.iter() { match item { Processors::Variable(e) => { - if e.data.constant { - found_is_constant_variable = Some(parameter.pos); - } - param_found = true; + found_param = Some(e.clone()); } _ => (), } } - if !param_found && parameter.name != "self" { + if !found_param.is_none() && parameter.name != "self" { let mut err = error::error_list::ERROR_S34.clone().build_with_path( vec![error::ErrorBuildField { key: "token".to_owned(), @@ -218,23 +224,41 @@ impl super::ItemParserProcessor for Constructor { options.parser.informations.push(&err); } - if found_is_constant_variable.is_some() { - options.parser.informations.push( - &error::error_list::ERROR_S18.clone().build_with_path( - vec![], - alloc::format!("{}:{}:{}", file!().to_owned(), line!(), column!()), - class_body_page.path.clone(), - found_is_constant_variable.unwrap(), - ), - ); + //is found param constant + + if let Some(data) = &found_param { + if data.data.constant { + options.parser.informations.push( + &error::error_list::ERROR_S18.clone().build_with_path( + vec![], + alloc::format!("{}:{}:{}", file!().to_owned(), line!(), column!()), + class_body_page.path.clone(), + parameter.pos, + ), + ); + } } + //TODO: IS THIS NECCESSARY? - /* parameters.push( + parameters.push( ellie_core::definite::items::constructor::ConstructorParameter { name: parameter.name.clone(), pos: parameter.pos, + rtype: parameter.rtype, + rtype_pos: parameter.rtype_pos, }, - ); */ + ); + + items.push(Processors::ConstructorParameter(ConstructorParameter { + name: parameter.name.clone(), + pos: parameter.pos, + rtype: if let Some(param) = found_param { + param.data.rtype.definer_type.clone().to_definite() + } else { + ellie_core::definite::definers::DefinerCollecting::Dynamic + }, + hash: generate_hash_usize(), + })) } items.extend(self.inside_code.clone()); let inner_page_id: usize = ellie_core::utils::generate_hash_usize(); diff --git a/ellie_engine/tokenizer/src/processors/items/class_processor.rs b/ellie_engine/tokenizer/src/processors/items/class_processor.rs index 0afbe049..9cf25806 100644 --- a/ellie_engine/tokenizer/src/processors/items/class_processor.rs +++ b/ellie_engine/tokenizer/src/processors/items/class_processor.rs @@ -176,6 +176,8 @@ impl crate::processors::Processor for class::Class { .push(constructor::ConstructorParameter { name: variable.name, pos: variable.pos, + rtype: variable.rtype.definer_type, + rtype_pos: variable.type_pos, body_element_defiener: true, }); } diff --git a/ellie_engine/tokenizer/src/processors/items/constructor_processor.rs b/ellie_engine/tokenizer/src/processors/items/constructor_processor.rs index 0fc2c213..467d1f34 100644 --- a/ellie_engine/tokenizer/src/processors/items/constructor_processor.rs +++ b/ellie_engine/tokenizer/src/processors/items/constructor_processor.rs @@ -28,6 +28,7 @@ impl crate::processors::Processor for constructor::Constructor { ..Default::default() }, body_element_defiener: false, + ..Default::default() }) } else { if self.parameters[parameter_len - 1].name == "" { diff --git a/ellie_engine/tokenizer/src/syntax/items/constructor.rs b/ellie_engine/tokenizer/src/syntax/items/constructor.rs index 1c90402a..2ac8f39c 100644 --- a/ellie_engine/tokenizer/src/syntax/items/constructor.rs +++ b/ellie_engine/tokenizer/src/syntax/items/constructor.rs @@ -1,12 +1,14 @@ +use crate::{processors::items::Processors, syntax::items::definers}; use ellie_core::{definite::Converter, defs}; use serde::{Deserialize, Serialize}; -use crate::processors::items::Processors; #[derive(Default, Debug, Clone, Serialize, Deserialize)] pub struct ConstructorParameter { pub name: String, pub pos: defs::Cursor, + pub rtype: definers::DefinerCollector, + pub rtype_pos: defs::Cursor, // When class is defined, by the design variables are not pub body_element_defiener: bool, } @@ -38,6 +40,8 @@ impl Converter Date: Thu, 4 Jul 2024 00:58:56 +0300 Subject: [PATCH 18/30] Fix typos & linter errors & function parameter indexing error & void params for building class --- ellie_engine/Cargo.toml | 2 +- ellie_engine/benches/codes.rs | 2 -- .../bytecode/src/transpiler/items/constructor.rs | 1 + .../bytecode/src/transpiler/items/function.rs | 8 -------- .../bytecode/src/transpiler/types/function_call.rs | 3 +-- ellie_engine/core/src/defs.rs | 1 - ellie_engine/core/src/error/error_list.rs | 4 ++-- ellie_engine/core/src/utils/mod.rs | 2 +- ellie_engine/parser/src/extra/mod.rs | 2 +- ellie_engine/parser/src/lib.rs | 2 +- ellie_engine/src/byte_code.rs | 12 +++++++----- ellie_engine/src/compiler.rs | 5 +---- ellie_engine/vm/src/heap_memory.rs | 1 - ellie_engine/vm/src/instructions/CALLN.rs | 6 +++--- ellie_engine/vm/src/instructions/FN.rs | 9 +-------- ellie_engine/vm/src/utils.rs | 2 +- ellievm/src/run.rs | 4 ++-- 17 files changed, 23 insertions(+), 43 deletions(-) diff --git a/ellie_engine/Cargo.toml b/ellie_engine/Cargo.toml index f432c141..25ab086c 100644 --- a/ellie_engine/Cargo.toml +++ b/ellie_engine/Cargo.toml @@ -50,4 +50,4 @@ harness = false [workspace] members = [".", "./core", "./tokenizer", "./parser", "./bytecode", "./vm", "./fmt", "./renderer_utils" ] -default-members = ["."] \ No newline at end of file +default-members = ["."] diff --git a/ellie_engine/benches/codes.rs b/ellie_engine/benches/codes.rs index 92a83fab..2a509cb6 100644 --- a/ellie_engine/benches/codes.rs +++ b/ellie_engine/benches/codes.rs @@ -1,5 +1,3 @@ - - pub const BENCH_CLASS: &str = r#" /// -- Required Types -- @dont_fix_variant; diff --git a/ellie_engine/bytecode/src/transpiler/items/constructor.rs b/ellie_engine/bytecode/src/transpiler/items/constructor.rs index 06f8a2c6..e800b488 100644 --- a/ellie_engine/bytecode/src/transpiler/items/constructor.rs +++ b/ellie_engine/bytecode/src/transpiler/items/constructor.rs @@ -58,6 +58,7 @@ impl super::Transpiler for constructor::Constructor { ), ), )); + //Reserve memory spaces for parameters for (idx, parameter) in self.parameters.iter().enumerate() { assembler.debug_headers.push(DebugHeader { diff --git a/ellie_engine/bytecode/src/transpiler/items/function.rs b/ellie_engine/bytecode/src/transpiler/items/function.rs index 0ac2ad51..5d2b8972 100644 --- a/ellie_engine/bytecode/src/transpiler/items/function.rs +++ b/ellie_engine/bytecode/src/transpiler/items/function.rs @@ -90,20 +90,12 @@ impl super::Transpiler for function::Function { assembler.location() }; - let prev_pos = assembler.location(); - - - assembler.assemble_dependency(&self.inner_page_id); - - assembler .instructions .push(Instructions::RET(Instruction::implicit())); - - assembler.instructions[escape_pos_instruction_location] = instruction_table::Instructions::STA(Instruction::immediate( Types::Integer, diff --git a/ellie_engine/bytecode/src/transpiler/types/function_call.rs b/ellie_engine/bytecode/src/transpiler/types/function_call.rs index f417467a..9b835064 100644 --- a/ellie_engine/bytecode/src/transpiler/types/function_call.rs +++ b/ellie_engine/bytecode/src/transpiler/types/function_call.rs @@ -3,7 +3,6 @@ use ellie_core::definite::types::{ class_instance::AttributeType, function_call::FunctionCall, Types as CoreTypes, }; - use crate::{ assembler::LocalHeader, instruction_table::Instructions, @@ -25,7 +24,7 @@ impl TypeTranspiler for FunctionCall { .assembler_mut() .find_local(&e.value, dependencies.clone(), true) .unwrap_or_else(|| { - panic!("Variable not found: {}: {:#?} {:#?}, {:#?}", e.value, dependencies, options.target_page, self); + panic!("Variable not found: {}", e.value); }) .clone(), CoreTypes::Reference(e) => { diff --git a/ellie_engine/core/src/defs.rs b/ellie_engine/core/src/defs.rs index 28e8dfec..ac84730b 100644 --- a/ellie_engine/core/src/defs.rs +++ b/ellie_engine/core/src/defs.rs @@ -83,7 +83,6 @@ impl Default for TokenizerOptions { #[cfg(feature = "compiler_utils")] pub struct CursorPosition(pub usize, pub usize); - /// A struct that represents a position in a file. /// (line, column) #[cfg(not(feature = "compiler_utils"))] diff --git a/ellie_engine/core/src/error/error_list.rs b/ellie_engine/core/src/error/error_list.rs index d6c83698..8ffdbf6b 100644 --- a/ellie_engine/core/src/error/error_list.rs +++ b/ellie_engine/core/src/error/error_list.rs @@ -40,7 +40,7 @@ lazy_static! { pub static ref ERROR_S7: error::Error = error::Error { code: 0x06, title: "ReferenceError".to_owned(), - message: "$name requires '$token' parameters, found '$token2' length of parameters" + message: "$name requires '$token' parameters, found '$token2' parameters" .to_owned(), ..Default::default() }; @@ -205,7 +205,7 @@ lazy_static! { pub static ref ERROR_S34: error::Error = error::Error { code: 0x33, title: "TypeError".to_owned(), - message: "'$token' is not found in properties".to_owned(), + message: "'$token' is not found in constructor properties, try to initialize with a value.".to_owned(), ..Default::default() }; pub static ref ERROR_S35: error::Error = error::Error { diff --git a/ellie_engine/core/src/utils/mod.rs b/ellie_engine/core/src/utils/mod.rs index f4665be2..07191e8a 100644 --- a/ellie_engine/core/src/utils/mod.rs +++ b/ellie_engine/core/src/utils/mod.rs @@ -260,7 +260,7 @@ pub fn colapseable_operator(parent: Operators, child: Operators) -> bool { }, } } - Operators::AssignmentType(child_inner) => true, + Operators::AssignmentType(_) => true, Operators::Null => todo!(), } } diff --git a/ellie_engine/parser/src/extra/mod.rs b/ellie_engine/parser/src/extra/mod.rs index df017791..17f21348 100644 --- a/ellie_engine/parser/src/extra/mod.rs +++ b/ellie_engine/parser/src/extra/mod.rs @@ -1,2 +1,2 @@ +pub mod item_search; pub mod utils; -pub mod item_search; \ No newline at end of file diff --git a/ellie_engine/parser/src/lib.rs b/ellie_engine/parser/src/lib.rs index fec992e1..10bd89f9 100644 --- a/ellie_engine/parser/src/lib.rs +++ b/ellie_engine/parser/src/lib.rs @@ -15,7 +15,7 @@ extern crate alloc; extern crate std; pub mod deep_search_extensions; +pub mod extra; pub mod parser; pub mod processors; pub mod utils; -pub mod extra; diff --git a/ellie_engine/src/byte_code.rs b/ellie_engine/src/byte_code.rs index 2d9fe48d..a3207374 100644 --- a/ellie_engine/src/byte_code.rs +++ b/ellie_engine/src/byte_code.rs @@ -40,14 +40,16 @@ pub fn transpile_parsed_code( macro_rules! transpileText { ($text:expr, $platform_attributes:expr, $module_maps:expr) => {{ use ellie_engine::{ - ellie_bytecode::assembler, - ellie_core::defs::{ModuleMap}, - ellie_parser::utils::Module, + ellie_bytecode::assembler, ellie_core::defs::ModuleMap, ellie_parser::utils::Module, }; let text = $text; let module = ellie_parser::parseText!(text); - let result = ellie_engine::byteCode::transpile_parsed_code(module, $platform_attributes, $module_maps); + let result = ellie_engine::byteCode::transpile_parsed_code( + module, + $platform_attributes, + $module_maps, + ); result }}; -} \ No newline at end of file +} diff --git a/ellie_engine/src/compiler.rs b/ellie_engine/src/compiler.rs index 861c7f16..e438a0aa 100644 --- a/ellie_engine/src/compiler.rs +++ b/ellie_engine/src/compiler.rs @@ -174,8 +174,5 @@ macro_rules! compile_core_lib { } } } - - //Compile core library - }; -} \ No newline at end of file +} diff --git a/ellie_engine/vm/src/heap_memory.rs b/ellie_engine/vm/src/heap_memory.rs index 9149b879..68328111 100644 --- a/ellie_engine/vm/src/heap_memory.rs +++ b/ellie_engine/vm/src/heap_memory.rs @@ -57,7 +57,6 @@ impl HeapMemory { } pub fn set(&mut self, key: &usize, value: RawType) { - self.data.insert(*key, value.to_bytes()); } diff --git a/ellie_engine/vm/src/instructions/CALLN.rs b/ellie_engine/vm/src/instructions/CALLN.rs index 3dcd1d06..23443dcc 100644 --- a/ellie_engine/vm/src/instructions/CALLN.rs +++ b/ellie_engine/vm/src/instructions/CALLN.rs @@ -57,8 +57,8 @@ impl super::InstructionExecuter for CALLN { let _start_position_of_params = current_stack.get_pos() - 2; for i in 0..params_length { - let pos = current_stack.get_pos() - (params_length - (-(i as isize) as usize)); - let paramater = match stack_memory.get(&pos) { + let pos = current_stack.get_pos() - (params_length - i); + let parameter = match stack_memory.get(&pos) { Some(raw_type) => { if raw_type.type_id.is_stack_reference() || raw_type.type_id.is_heap_reference() @@ -93,7 +93,7 @@ impl super::InstructionExecuter for CALLN { }) } }; - params.push(paramater); + params.push(parameter); } Ok(ExecuterResult::CallNativeFunction(VmNativeCall { hash, diff --git a/ellie_engine/vm/src/instructions/FN.rs b/ellie_engine/vm/src/instructions/FN.rs index 6acd7d4a..23c7581c 100644 --- a/ellie_engine/vm/src/instructions/FN.rs +++ b/ellie_engine/vm/src/instructions/FN.rs @@ -67,14 +67,7 @@ impl super::InstructionExecuter for FN { let pos = current_stack.get_pos() + 3 + i; match stack_memory.get(&(index_start + i)) { Some(e) => { - if e.type_id.is_void() { - return Err(ExecuterPanic { - reason: ThreadPanicReason::NullReference( - index_start + i, - ), - code_location: format!("{}:{}", file!(), line!()), - }); - } else if e.type_id.is_heap_reference() { + if e.type_id.is_heap_reference() { match heap_memory.get(&e.to_uint()) { Some(e) => { heap_memory.set(&pos, e.clone()); diff --git a/ellie_engine/vm/src/utils.rs b/ellie_engine/vm/src/utils.rs index a2aaae28..ce7cdc7f 100644 --- a/ellie_engine/vm/src/utils.rs +++ b/ellie_engine/vm/src/utils.rs @@ -87,7 +87,7 @@ pub enum ThreadPanicReason { /// This panic triggered when the program trying to access a array index with negative value /// * first: index CannotIndexWithNegative(isize), - ParemeterMemoryAccessViolation(usize), + ParameterMemoryAccessViolation(usize), MemoryAccessViolation(usize, usize), /// This triggered when types like string, array, class tried to be kept in immediate mode ImmediateUseViolation(u8), diff --git a/ellievm/src/run.rs b/ellievm/src/run.rs index 4ec72e9b..93f85402 100644 --- a/ellievm/src/run.rs +++ b/ellievm/src/run.rs @@ -83,8 +83,8 @@ pub fn run(program: Program, vm_settings: VmSettings, debug_file: Option format!("CannotIndexWithNegative; {:?}", e), - ThreadPanicReason::ParemeterMemoryAccessViolation(e) => - format!("ParemeterMemoryAccessViolation; {:?}", e), + ThreadPanicReason::ParameterMemoryAccessViolation(e) => + format!("ParameterMemoryAccessViolation; {:?}", e), ThreadPanicReason::MemoryAccessViolation(location, stack_idx) => format!( "MemoryAccessViolation; on stack {:?} at location: {:?}", stack_idx, location From a4ad5ae2efd37330065a9f2353be6e59707574cb Mon Sep 17 00:00:00 2001 From: Ahmetcan Aksu Date: Thu, 4 Jul 2024 01:05:22 +0300 Subject: [PATCH 19/30] Implement class variable and constructor function support & Implement brk & Fix borrow local issue & remove planned type on constructor params & Fix page id errors --- ellie_engine/benches/compile.rs | 6 +- ellie_engine/benches/utils.rs | 8 +- ellie_engine/bytecode/src/assembler.rs | 22 +- .../bytecode/src/transpiler/items/brk.rs | 22 ++ .../bytecode/src/transpiler/items/mod.rs | 1 + .../bytecode/src/transpiler/items/ret.rs | 2 - .../src/transpiler/types/class_call.rs | 24 ++ .../src/transpiler/types/function_call.rs | 2 +- .../core/src/definite/items/constructor.rs | 4 +- .../parser/src/deep_search_extensions.rs | 188 ++++++++------ .../src/processors/items/constructor.rs | 147 +++++------ .../parser/src/processors/types/class_call.rs | 36 +-- .../parser/src/processors/types/reference.rs | 235 ++++++++++-------- .../src/processors/items/class_processor.rs | 3 - .../tokenizer/src/processors/items/mod.rs | 1 + .../tokenizer/src/syntax/items/constructor.rs | 7 - ellievm/src/main.rs | 91 ++++++- tools/run.sh | 23 ++ 18 files changed, 494 insertions(+), 328 deletions(-) create mode 100644 ellie_engine/bytecode/src/transpiler/items/brk.rs create mode 100755 tools/run.sh diff --git a/ellie_engine/benches/compile.rs b/ellie_engine/benches/compile.rs index cc2ef29b..3809519d 100644 --- a/ellie_engine/benches/compile.rs +++ b/ellie_engine/benches/compile.rs @@ -65,8 +65,10 @@ fn parse(c: &mut Criterion) { fn byte_code_assembler(c: &mut Criterion) { let class_parse = parseText!(codes::BENCH_CLASS).expect("should've been successful"); let loop_parse = parseText!(codes::BENCH_LOOP).expect("should've been successful"); - let fibonacci_loop_parse = parseText!(codes::BENCH_FIBONACCI_LOOP).expect("should've been successful"); - let fibonacci_recursion_parse = parseText!(codes::BENCH_FIBONACCI_RECURSION).expect("should've been successful"); + let fibonacci_loop_parse = + parseText!(codes::BENCH_FIBONACCI_LOOP).expect("should've been successful"); + let fibonacci_recursion_parse = + parseText!(codes::BENCH_FIBONACCI_RECURSION).expect("should've been successful"); c.bench_function("class_byte_code_assembler", |b| { b.iter(|| { diff --git a/ellie_engine/benches/utils.rs b/ellie_engine/benches/utils.rs index b9014df8..c2539e0b 100644 --- a/ellie_engine/benches/utils.rs +++ b/ellie_engine/benches/utils.rs @@ -47,11 +47,9 @@ pub fn tokenize_code(code: &str) -> (usize, PageExport) { code: code.to_string(), main_hash: 0, }; - let pages = tokenizer::tokenize_file(&mut program_repository).expect("should've been successful"); - ( - program_repository.main_hash, - pages, - ) + let pages = + tokenizer::tokenize_file(&mut program_repository).expect("should've been successful"); + (program_repository.main_hash, pages) } pub fn parse_code( diff --git a/ellie_engine/bytecode/src/assembler.rs b/ellie_engine/bytecode/src/assembler.rs index ae9c95c1..8f3ec876 100644 --- a/ellie_engine/bytecode/src/assembler.rs +++ b/ellie_engine/bytecode/src/assembler.rs @@ -453,6 +453,16 @@ impl Assembler { page_hash: Option>, borrow: bool, ) -> Option { + //If the local is already found, we will just return it, or else we register it as local + //After that function parsed by bytecode generator this borrowed local will be updated + if self.locals.iter().any(|local| local.hash == Some(hash)) { + return self + .locals + .iter() + .find(|local| local.hash == Some(hash)) + .cloned(); + } + let mut locals: Vec<&LocalHeader> = self .locals .iter() @@ -590,21 +600,11 @@ impl Assembler { match locals.iter_mut().find(|local| &local.name == name) { Some(local) => Some(local.clone()), None => { - std::println!( - "\n-----\npage_hash.is_none() || !borrow: {} {:#?}", - page_hash.is_none() || !borrow, - page_hash - ); if page_hash.is_none() || !borrow { return None; } match self.module.pages.clone().into_iter().find_map(|x| { if page_hash.clone().unwrap().contains(&x.hash) { - std::println!("Page: {:#?} {:#?}", x.path, x.hash); - if x.path.contains("mem") { - std::println!("mem item saerched"); - } - x.items.into_iter().find_map(|e| match e { Collecting::Function(function) => { if &function.name == name { @@ -747,7 +747,7 @@ impl Assembler { native_function.transpile(self, processed_page.hash, &processed_page) } Collecting::None => todo!(), - Collecting::Brk(_) => todo!(), + Collecting::Brk(brk) => brk.transpile(self, processed_page.hash, &processed_page), Collecting::Go(_) => todo!(), Collecting::FunctionParameter(function_parameter) => { function_parameter.transpile(self, processed_page.hash, &processed_page) diff --git a/ellie_engine/bytecode/src/transpiler/items/brk.rs b/ellie_engine/bytecode/src/transpiler/items/brk.rs new file mode 100644 index 00000000..c5a3f931 --- /dev/null +++ b/ellie_engine/bytecode/src/transpiler/items/brk.rs @@ -0,0 +1,22 @@ +use alloc::vec; +use ellie_core::definite::items::brk; + +use crate::{instruction_table, instructions::Instruction}; + +impl super::Transpiler for brk::Brk { + fn transpile( + &self, + assembler: &mut crate::assembler::Assembler, + _hash: usize, + processed_page: &ellie_parser::parser::ProcessedPage, + ) -> bool { + let mut dependencies = vec![processed_page.hash]; + dependencies.extend(processed_page.dependencies.iter().map(|d| d.hash)); + + assembler + .instructions + .push(instruction_table::Instructions::BRK(Instruction::implicit())); + + true + } +} diff --git a/ellie_engine/bytecode/src/transpiler/items/mod.rs b/ellie_engine/bytecode/src/transpiler/items/mod.rs index 6f0f4c1c..11a4af37 100644 --- a/ellie_engine/bytecode/src/transpiler/items/mod.rs +++ b/ellie_engine/bytecode/src/transpiler/items/mod.rs @@ -13,6 +13,7 @@ pub mod self_item; pub mod setter_call; /* pub mod type_resolver; */ pub mod variable; +pub mod brk; use ellie_parser::parser::ProcessedPage; diff --git a/ellie_engine/bytecode/src/transpiler/items/ret.rs b/ellie_engine/bytecode/src/transpiler/items/ret.rs index 2ea0c48d..5d5d9720 100644 --- a/ellie_engine/bytecode/src/transpiler/items/ret.rs +++ b/ellie_engine/bytecode/src/transpiler/items/ret.rs @@ -1,5 +1,3 @@ -use std::println; - use alloc::vec; use ellie_core::definite::items::ret; diff --git a/ellie_engine/bytecode/src/transpiler/types/class_call.rs b/ellie_engine/bytecode/src/transpiler/types/class_call.rs index 50bd42d1..6b781bcf 100644 --- a/ellie_engine/bytecode/src/transpiler/types/class_call.rs +++ b/ellie_engine/bytecode/src/transpiler/types/class_call.rs @@ -34,6 +34,19 @@ impl TypeTranspiler for ClassCall { .instructions .push(Instructions::ARR(Instruction::implicit())); let class_location = options.assembler().location(); + + //Reserve self + options + .assembler_mut() + .instructions + .push(Instructions::STA(Instruction::implicit())); + let self_location_to_replace = options.assembler().location(); + options + .assembler_mut() + .instructions + .push(Instructions::PUSH(Instruction::absolute(class_location))); + // + if !self.params.is_empty() { for (_idx, param) in self.params.iter().enumerate() { param.value.transpile( @@ -78,6 +91,11 @@ impl TypeTranspiler for ClassCall { //- // Insert self + + //Replace self refference to itself + options.assembler_mut().instructions[self_location_to_replace] = + Instructions::STA(Instruction::absolute(self_location)); + options .assembler_mut() .instructions @@ -123,6 +141,12 @@ impl TypeTranspiler for ClassCall { .instructions .push(Instructions::CALL(Instruction::absolute(target.cursor))); + let borrow_location = options.assembler().location(); + + options + .assembler_mut() + .add_borrow_to_local(target.hash.unwrap(), borrow_location); + match options.target_register() { Registers::A => options .assembler_mut() diff --git a/ellie_engine/bytecode/src/transpiler/types/function_call.rs b/ellie_engine/bytecode/src/transpiler/types/function_call.rs index 9b835064..65ce4c10 100644 --- a/ellie_engine/bytecode/src/transpiler/types/function_call.rs +++ b/ellie_engine/bytecode/src/transpiler/types/function_call.rs @@ -139,7 +139,7 @@ impl TypeTranspiler for FunctionCall { .instructions .push(Instructions::CALL(Instruction::absolute(target.cursor))); - let borrow_location = options.assembler().location() + 1; + let borrow_location = options.assembler().location(); options .assembler_mut() diff --git a/ellie_engine/core/src/definite/items/constructor.rs b/ellie_engine/core/src/definite/items/constructor.rs index 1769f486..3f25a748 100644 --- a/ellie_engine/core/src/definite/items/constructor.rs +++ b/ellie_engine/core/src/definite/items/constructor.rs @@ -1,4 +1,4 @@ -use crate::{definite::definers, defs}; +use crate::defs; use alloc::{string::String, vec::Vec}; use serde::{Deserialize, Serialize}; @@ -6,8 +6,6 @@ use serde::{Deserialize, Serialize}; pub struct ConstructorParameter { pub name: String, pub pos: defs::Cursor, - pub rtype: definers::DefinerCollecting, - pub rtype_pos: defs::Cursor, } #[derive(PartialEq, Debug, Clone, Serialize, Deserialize)] diff --git a/ellie_engine/parser/src/deep_search_extensions.rs b/ellie_engine/parser/src/deep_search_extensions.rs index 57793a0a..88d53399 100644 --- a/ellie_engine/parser/src/deep_search_extensions.rs +++ b/ellie_engine/parser/src/deep_search_extensions.rs @@ -1,6 +1,9 @@ use crate::{ parser::{DeepSearchItems, Parser}, - processors::definer::{DefinerParserProcessor, DefinerParserProcessorOptions}, + processors::{ + definer::{DefinerParserProcessor, DefinerParserProcessorOptions}, + types::{TypeParserProcessor, TypeParserProcessorOptions}, + }, utils::FoundPage, }; use alloc::{ @@ -20,6 +23,7 @@ use ellie_core::{ }, defs, error, }; +use ellie_tokenizer::processors::items::Processors; use ellie_tokenizer::tokenizer::Dependency; use enum_as_inner::EnumAsInner; @@ -363,82 +367,116 @@ fn iterate_deep_type( if hash_deep_search.found { match hash_deep_search.found_item { ProcessedDeepSearchItems::Class(class_page) => { - match parser - .find_processed_page(class_page.inner_page_id) - .cloned() - { - Some(class_inner_page) => { - let attributes = class_inner_page.items.iter().filter_map(|item| { - match item.clone() { - Collecting::Variable(e) => { - let resolved_type = if e.has_type { e.rtype } else { match resolve_type(e.value, class_inner_page.hash, parser, &mut errors, Some(reference_pos)) { - Some(x) => x, - None => { - return None; - }, - } }; - Some(Attribute { - _rtype: AttributeType::Property, - name: e.name.clone(), - value: resolved_type, - page: class_inner_page.hash, - }) - }, - Collecting::Function(e) => { - Some(Attribute { - _rtype: AttributeType::Method, - name: e.name.clone(), - value: definers::DefinerCollecting::Function( - ellie_core::definite::definers::FunctionType { - params: e.parameters.iter().map(|param| { - param.rtype.clone() - }).collect::>(), - returning: Box::new(e.return_type), - } - ), - page: class_inner_page.hash, - }) - }, - Collecting::NativeFunction(e) => { - Some(Attribute { - _rtype: AttributeType::Method, - name: e.name.clone(), - value: definers::DefinerCollecting::Function( - ellie_core::definite::definers::FunctionType { - params: e.parameters.iter().map(|param| { - param.rtype.clone() - }).collect::>(), - returning: Box::new(e.return_type), - } - ), - page: class_inner_page.hash, - }) - } - Collecting::Getter(e) => { - Some(Attribute { - _rtype: AttributeType::Method, - name: e.name.clone(), - value: e.return_type, - page: class_inner_page.hash, - }) - } - Collecting::Setter(e) => { - Some(Attribute { - _rtype: AttributeType::Method, - name: e.name.clone(), - value: e.rtype, - page: class_inner_page.hash, - }) - } - _ => None, - } - }).collect::>(); - Ok(attributes) - } + let class_inner_page = match parser.find_page(class_page.inner_page_id) { + Some(class_inner_page) => class_inner_page.clone(), None => { unreachable!() } - } + }; + + let attributes = class_inner_page.items.iter().filter_map(|item| { + match item.clone() { + Processors::Variable(e) => { + let mut binding = TypeParserProcessorOptions::new(parser, page_id); + let options = binding.dont_include_setter().dont_ignore_type().build(); + + let resolved_type = if e.data.has_type { + let mut binding = DefinerParserProcessorOptions::new(parser, page_id); + let options = binding.build(); + match e.data.rtype.definer_type.process(options) { + Ok(e) => e, + Err(e) => { + errors.extend(e); + return None + }, + } + } else { + let rtype = match e.data.value.process(options) { + Ok(e) => e, + Err(e) => { + errors.extend(e); + return None + }, + }; + match resolve_type( + rtype, + class_inner_page.hash, + parser, + &mut errors, + Some(e.data.value_pos)) { + Some(e) => e, + None => return None, + } + }; + Some(Attribute { + _rtype: AttributeType::Property, + name: e.data.name.clone(), + value: resolved_type, + page: class_inner_page.hash, + }) + }, + Processors::Function(e) => { + let mut params = Vec::new(); + let mut binding = DefinerParserProcessorOptions::new(parser, page_id); + let options = binding.build(); + + for param in e.data.parameters.iter() { + match param.rtype.definer_type.process(options) { + Ok(e) => params.push(e), + Err(e) => { + errors.extend(e); + return None + }, + } + } + + + let returning = match e.data.return_type.definer_type.process(options) { + Ok(e) => Box::new(e), + Err(e) => { + errors.extend(e); + return None + }, + }; + + Some(Attribute { + _rtype: AttributeType::Method, + name: e.data.name.clone(), + value: definers::DefinerCollecting::Function( + ellie_core::definite::definers::FunctionType { + params, + returning, + } + ), + page: class_inner_page.hash, + }) + }, + Processors::Getter(e) => { + let mut binding = DefinerParserProcessorOptions::new(parser, page_id); + let options = binding.build(); + + let value = match e.return_type.definer_type.process(options) { + Ok(e) => e, + Err(e) => { + errors.extend(e); + return None + }, + }; + + Some(Attribute { + _rtype: AttributeType::Method, + name: e.name.clone(), + value, + page: class_inner_page.hash, + }) + } + Processors::Setter(e) => { + todo!() + } + _ => None, + } + }).collect::>(); + Ok(attributes) } ProcessedDeepSearchItems::Enum(enum_data) => { Ok( @@ -766,7 +804,7 @@ fn iterate_deep_type( ); last_chain_attributes = ( a.value.clone(), - match resolve_chain(a.value.clone(), chain.pos, a.page, parser) { + match resolve_chain(a.value.clone(), chain.pos, page_id, parser) { Ok(e) => e, Err(e) => { errors.extend(e); diff --git a/ellie_engine/parser/src/processors/items/constructor.rs b/ellie_engine/parser/src/processors/items/constructor.rs index a2257ec9..41ebd0c0 100644 --- a/ellie_engine/parser/src/processors/items/constructor.rs +++ b/ellie_engine/parser/src/processors/items/constructor.rs @@ -100,71 +100,9 @@ impl super::ItemParserProcessor for Constructor { ellie_core::definite::items::constructor::ConstructorParameter { name: "self".to_owned(), pos: self.pos, - rtype: ellie_core::definite::definers::DefinerCollecting::Generic( - ellie_core::definite::definers::GenericType { - rtype: class_element.name, - pos: class_element.pos, - hash: class_element.hash, - }, - ), - rtype_pos: class_page_type.pos, }, ); - for variable in class_element - .body - .iter() - .filter_map(|item| match item.as_variable() { - Some(e) => { - //TODO: IS THIS NECCESSARY? - if e.data.has_value - /* && !self.parameters.iter().any(|g| g.name == e.data.name) */ - { - e.data.has_value.then_some(e) - } else { - None - } - } - None => None, - }) - { - //TODO: IS THIS NECCESSARY? - /* if !self.parameters.iter().any(|g| g.name == variable.data.name) { */ - let self_setter = Processors::SetterCall(SetterCall { - target: TypeProcessor::Reference(ReferenceTypeCollector { - data: ReferenceType { - reference: Box::new(TypeProcessor::Variable(VariableTypeCollector { - data: VariableType { - value: "self".to_owned(), - ..Default::default() - }, - ..Default::default() - })), - chain: vec![Chain { - value: variable.data.name.clone(), - ..Default::default() - }], - ..Default::default() - }, - ..Default::default() - }), - value: variable.data.value.clone(), - operator: AssignmentOperators::Assignment, - hash: generate_hash_usize(), - ..Default::default() - }); - items.push(self_setter); - //TODO: IS THIS NECCESSARY? - parameters.push( - ellie_core::definite::items::constructor::ConstructorParameter { - name: variable.data.name.clone(), - pos: variable.data.pos, - rtype: variable.data.rtype.definer_type.clone().to_definite(), - rtype_pos: variable.data.rtype.pos, - }, - ); - } - for (index, parameter) in self.parameters.clone().iter().enumerate() { if class_element.name == parameter.name { let mut err = error::error_list::ERROR_S24.clone().build_with_path( @@ -198,6 +136,7 @@ impl super::ItemParserProcessor for Constructor { options.parser.informations.push(&err); } } + let mut found_param = None; let page = options.parser.find_page(options.page_hash).unwrap(); for item in page.items.iter() { @@ -209,7 +148,7 @@ impl super::ItemParserProcessor for Constructor { } } - if !found_param.is_none() && parameter.name != "self" { + if found_param.is_none() && !parameter.body_element_defiener { let mut err = error::error_list::ERROR_S34.clone().build_with_path( vec![error::ErrorBuildField { key: "token".to_owned(), @@ -224,8 +163,6 @@ impl super::ItemParserProcessor for Constructor { options.parser.informations.push(&err); } - //is found param constant - if let Some(data) = &found_param { if data.data.constant { options.parser.informations.push( @@ -239,26 +176,78 @@ impl super::ItemParserProcessor for Constructor { } } - //TODO: IS THIS NECCESSARY? + let targeted_variable = class_element + .body + .iter() + .find_map(|item| match item { + Processors::Variable(e) => { + if e.data.name == parameter.name { + Some(e) + } else { + None + } + } + _ => None, + }) + .unwrap_or_else(|| panic!("Failed to find variable")); + + let self_setter = Processors::SetterCall(SetterCall { + target: TypeProcessor::Reference(ReferenceTypeCollector { + data: ReferenceType { + reference: Box::new(TypeProcessor::Variable(VariableTypeCollector { + data: VariableType { + value: "self".to_owned(), + ..Default::default() + }, + ..Default::default() + })), + chain: vec![Chain { + value: targeted_variable.data.name.clone(), + ..Default::default() + }], + ..Default::default() + }, + ..Default::default() + }), + value: if targeted_variable.data.has_value { + targeted_variable.data.value.clone() + } else { + TypeProcessor::Variable(VariableTypeCollector { + data: VariableType { + value: targeted_variable.data.name.clone(), + ..Default::default() + }, + ..Default::default() + }) + }, + operator: AssignmentOperators::Assignment, + hash: generate_hash_usize(), + ..Default::default() + }); + items.push(self_setter); + parameters.push( ellie_core::definite::items::constructor::ConstructorParameter { name: parameter.name.clone(), - pos: parameter.pos, - rtype: parameter.rtype, - rtype_pos: parameter.rtype_pos, + pos: targeted_variable.data.pos, }, ); - items.push(Processors::ConstructorParameter(ConstructorParameter { - name: parameter.name.clone(), - pos: parameter.pos, - rtype: if let Some(param) = found_param { - param.data.rtype.definer_type.clone().to_definite() - } else { - ellie_core::definite::definers::DefinerCollecting::Dynamic - }, - hash: generate_hash_usize(), - })) + items.push( + ellie_tokenizer::processors::items::Processors::ConstructorParameter( + ConstructorParameter { + name: parameter.name.clone(), + rtype: targeted_variable + .data + .rtype + .clone() + .definer_type + .to_definite(), + hash: generate_hash_usize(), + pos: targeted_variable.data.pos, + }, + ), + ); } items.extend(self.inside_code.clone()); let inner_page_id: usize = ellie_core::utils::generate_hash_usize(); diff --git a/ellie_engine/parser/src/processors/types/class_call.rs b/ellie_engine/parser/src/processors/types/class_call.rs index 5ec951b9..255a8b02 100644 --- a/ellie_engine/parser/src/processors/types/class_call.rs +++ b/ellie_engine/parser/src/processors/types/class_call.rs @@ -398,7 +398,7 @@ impl super::TypeParserProcessor for class_call_type::ClassCallCollector { .filter_map(|(index, x)| { let attribute_search = deep_search( options.parser, - belonging_class.inner_page_id, + options.page_id, x.name.clone(), Some(belonging_class.hash), vec![], @@ -604,36 +604,18 @@ impl super::TypeParserProcessor for class_call_type::ClassCallCollector { .filter(|x| x.body_element_defiener) .collect::>(); - params.push(types::class_call::ClassCallParameter { - value: Processors::Variable( - variable_type::VariableTypeCollector { - data: variable_type::VariableType { - value: "null".to_string(), - ..Default::default() - }, - ..Default::default() - }, - ) - .to_definite(), - pos: self.data.target_pos, - }); - - /* for element in body_element_definer_parameters { + for element in body_element_definer_parameters { let found_variable_value = class .body .iter() .find_map(|x| match x { ItemProcessors::Variable(e) => { if e.data.name == element.name { - Some(Processors::Variable( - variable_type::VariableTypeCollector { - data: variable_type::VariableType { - value: "null".to_string(), - ..Default::default() - }, - ..Default::default() - }, - )) + if e.data.value.is_complete() { + Some(e.data.value.to_definite()) + } else { + Some(types::Types::Null) + } } else { None } @@ -643,11 +625,11 @@ impl super::TypeParserProcessor for class_call_type::ClassCallCollector { .unwrap(); params.push(types::class_call::ClassCallParameter { - value: found_variable_value.to_definite(), + value: found_variable_value, pos: element.pos, }); } - */ + Ok(types::Types::ClassCall( ellie_core::definite::types::class_call::ClassCall { target: Box::new(ellie_core::definite::types::Types::VariableType( diff --git a/ellie_engine/parser/src/processors/types/reference.rs b/ellie_engine/parser/src/processors/types/reference.rs index 3789bc1d..a0f6a454 100644 --- a/ellie_engine/parser/src/processors/types/reference.rs +++ b/ellie_engine/parser/src/processors/types/reference.rs @@ -1,4 +1,7 @@ -use crate::deep_search_extensions::{find_type, resolve_type, ProcessedDeepSearchItems}; +use crate::{ + deep_search_extensions::{find_type, resolve_type, ProcessedDeepSearchItems}, + processors::definer::{DefinerParserProcessor, DefinerParserProcessorOptions}, +}; use alloc::{borrow::ToOwned, boxed::Box}; use ellie_core::definite::types::reference::IndexChainAttribute; @@ -8,12 +11,10 @@ use alloc::{ vec::Vec, }; use ellie_core::{ - definite::{ - definers::DefinerCollecting, items::Collecting, types, types::class_instance::AttributeType, - }, + definite::{definers::DefinerCollecting, types, types::class_instance::AttributeType}, error, }; -use ellie_tokenizer::syntax::types::reference_type; +use ellie_tokenizer::{processors::items::Processors, syntax::types::reference_type}; use super::TypeParserProcessorOptions; impl super::TypeParserProcessor for reference_type::ReferenceTypeCollector { @@ -280,115 +281,129 @@ impl super::TypeParserProcessor for reference_type::ReferenceTypeCollector { if hash_deep_search.found { match hash_deep_search.found_item { ProcessedDeepSearchItems::Class(class_page) => { - match parser - .find_processed_page(class_page.inner_page_id) - .cloned() - { - Some(class_inner_page) => { - let attributes = class_inner_page.items.iter().filter_map(|item| { - let class_attribute_idx = class_inner_page.items.iter().filter_map(|x| match x { - Collecting::Variable(x) => Some(x), - _ => None - }).collect::>(); - match item.clone() { - Collecting::Variable(e) => { - let resolved_type = if e.has_type { e.rtype } else { match resolve_type(e.value, class_inner_page.hash, parser, &mut errors, Some(e.value_pos)) { - Some(e) => e, - None => return None, - } }; - Some(Attribute { - rtype: AttributeType::Property, - name: e.name.clone(), - hash: e.hash, - page_hash: class_inner_page.hash, - class_attribute_idx: class_attribute_idx.iter().position(|x| x.hash == e.hash).unwrap(), - value: resolved_type, - }) - }, - Collecting::Function(e) => { - Some(Attribute { - rtype: AttributeType::Method, - name: e.name.clone(), - hash: e.hash, - page_hash: class_inner_page.hash, - class_attribute_idx: 0, - value: DefinerCollecting::Function( - ellie_core::definite::definers::FunctionType { - params: e.parameters.iter().map(|param| { - param.rtype.clone() - }).collect::>(), - returning: Box::new(e.return_type), - } - ), - }) - }, - Collecting::NativeFunction(e) => { - Some(Attribute { - rtype: AttributeType::Method, - name: e.name.clone(), - hash: e.hash, - page_hash: class_inner_page.hash, - class_attribute_idx: 0, - value: DefinerCollecting::Function( - ellie_core::definite::definers::FunctionType { - params: e.parameters.iter().map(|param| { - param.rtype.clone() - }).collect::>(), - returning: Box::new(e.return_type), - } - ), - }) - } - Collecting::Getter(e) => { - Some(Attribute { - rtype: AttributeType::Getter, - name: e.name.clone(), - hash: e.hash, - page_hash: class_inner_page.hash, - class_attribute_idx: 0, - value: e.return_type, - }) + let class_inner_page = + match parser.find_page(class_page.inner_page_id) { + Some(class_inner_page) => class_inner_page.clone(), + None => { + unreachable!() + } + }; + + let attributes = class_inner_page.items.iter().filter_map(|item| { + let class_attribute_idx = class_inner_page.items.iter().filter_map(|x| match x { + Processors::Variable(x) => Some(x), + _ => None + }).collect::>(); + + let mut binding = TypeParserProcessorOptions::new(parser, page_id); + let options = binding.dont_include_setter().dont_ignore_type().build(); + + match item.clone() { + Processors::Variable(e) => { + let resolved_type = if e.data.has_type { + let mut binding = DefinerParserProcessorOptions::new(parser, page_id); + let options = binding.build(); + match e.data.rtype.definer_type.process(options) { + Ok(e) => e, + Err(e) => { + errors.extend(e); + return None + }, + } + } else { + let rtype = match e.data.value.process(options) { + Ok(e) => e, + Err(e) => { + errors.extend(e); + return None + }, + }; + match resolve_type( + rtype, + class_inner_page.hash, + parser, + &mut errors, + Some(e.data.value_pos)) { + Some(e) => e, + None => return None, } - Collecting::Setter(e) => { - if is_setter { - Some(Attribute { - rtype: AttributeType::Setter, - name: e.name.clone(), - class_attribute_idx: 0, - value: e.rtype, - hash: e.hash, - page_hash: class_inner_page.hash, - }) - } else { - //TODO add setter check - errors.push( - error::error_list::ERROR_S6.clone().build_with_path( - vec![error::ErrorBuildField { - key: "token".to_owned(), - value: reference_type.to_string(), - }], - alloc::format!( - "{}:{}:{}", - file!().to_owned(), - line!(), - column!() - ), - parser.find_page(page_id).unwrap().path.clone(), - reference_pos, - ), - ); - None - } + }; + Some(Attribute { + rtype: AttributeType::Property, + name: e.data.name.clone(), + hash: e.data.hash, + page_hash: class_inner_page.hash, + class_attribute_idx: class_attribute_idx.iter().position(|x| x.data.hash == e.data.hash).unwrap(), + value: resolved_type, + }) + }, + Processors::Function(e) => { + + let mut params = Vec::new(); + let mut binding = DefinerParserProcessorOptions::new(parser, page_id); + let options = binding.build(); + + for param in e.data.parameters.iter() { + match param.rtype.definer_type.process(options) { + Ok(e) => params.push(e), + Err(e) => { + errors.extend(e); + return None + }, } - _ => None, } - }).collect::>(); - Ok(attributes) - } - None => { - unreachable!() + + + let returning = match e.data.return_type.definer_type.process(options) { + Ok(e) => Box::new(e), + Err(e) => { + errors.extend(e); + return None + }, + }; + + Some(Attribute { + rtype: AttributeType::Method, + name: e.data.name.clone(), + hash: e.data.hash, + page_hash: class_inner_page.hash, + class_attribute_idx: 0, + value: DefinerCollecting::Function( + ellie_core::definite::definers::FunctionType { + params, + returning, + } + ), + }) + }, + Processors::Getter(e) => { + let mut binding = DefinerParserProcessorOptions::new(parser, page_id); + let options = binding.build(); + + let value = match e.return_type.definer_type.process(options) { + Ok(e) => e, + Err(e) => { + errors.extend(e); + return None + }, + }; + + Some(Attribute { + rtype: AttributeType::Getter, + name: e.name.clone(), + hash: e.hash, + page_hash: class_inner_page.hash, + class_attribute_idx: 0, + value + }) + } + Processors::Setter(_) => { + todo!() + } + _ => None, } - } + }).collect::>(); + Ok(attributes) } ProcessedDeepSearchItems::GenericItem(_) => Ok(vec![]), ProcessedDeepSearchItems::Enum(enum_data) => { diff --git a/ellie_engine/tokenizer/src/processors/items/class_processor.rs b/ellie_engine/tokenizer/src/processors/items/class_processor.rs index 9cf25806..19c41d10 100644 --- a/ellie_engine/tokenizer/src/processors/items/class_processor.rs +++ b/ellie_engine/tokenizer/src/processors/items/class_processor.rs @@ -169,15 +169,12 @@ impl crate::processors::Processor for class::Class { }) .collect::>(); - //TODO: IS THIS NECESSARY? for variable in find_unused_variables_in_class_body { constructor .parameters .push(constructor::ConstructorParameter { name: variable.name, pos: variable.pos, - rtype: variable.rtype.definer_type, - rtype_pos: variable.type_pos, body_element_defiener: true, }); } diff --git a/ellie_engine/tokenizer/src/processors/items/mod.rs b/ellie_engine/tokenizer/src/processors/items/mod.rs index e09c81ce..af705dcd 100644 --- a/ellie_engine/tokenizer/src/processors/items/mod.rs +++ b/ellie_engine/tokenizer/src/processors/items/mod.rs @@ -319,6 +319,7 @@ impl Processors { None } } + Processors::Loop(loop_type) => Some(loop_type.pos), _ => unreachable!("{:#?}", self), } } diff --git a/ellie_engine/tokenizer/src/syntax/items/constructor.rs b/ellie_engine/tokenizer/src/syntax/items/constructor.rs index 2ac8f39c..4fffc737 100644 --- a/ellie_engine/tokenizer/src/syntax/items/constructor.rs +++ b/ellie_engine/tokenizer/src/syntax/items/constructor.rs @@ -2,13 +2,10 @@ use crate::{processors::items::Processors, syntax::items::definers}; use ellie_core::{definite::Converter, defs}; use serde::{Deserialize, Serialize}; - #[derive(Default, Debug, Clone, Serialize, Deserialize)] pub struct ConstructorParameter { pub name: String, pub pos: defs::Cursor, - pub rtype: definers::DefinerCollector, - pub rtype_pos: defs::Cursor, // When class is defined, by the design variables are not pub body_element_defiener: bool, } @@ -40,8 +37,6 @@ impl Converter VmNativeAnswer::RuntimeError( + "Signature mismatch, expected 'dynamic' argument".to_string(), + ), + VmNativeCallParameters::Dynamic(dynamic_value) => { + if dynamic_value.is_string() { + let file_handle = match File::open(dynamic_value.to_string()) { + Ok(e) => { + println!("Opened file: {:?}", e); + let handle = Box::new(e); + let handle = Box::into_raw(handle); + + handle as *mut usize + } + Err(e) => { + return VmNativeAnswer::RuntimeError(format!( + "Failed to open file '{}', ({})", + dynamic_value.to_string(), + e.to_string() + )); + } + }; + + //convert handle back to file + let file_handle = file_handle as *mut File; + + VmNativeAnswer::Ok(VmNativeCallParameters::Static( + StaticRawType::from_uint(file_handle as usize), + )) + } else { + VmNativeAnswer::RuntimeError( + "Signature mismatch expected 'string' argument".to_string(), + ) + } + } + } + }), + ))); + + ellie_core_module.register_element(ModuleElements::Function(FunctionElement::new( + "_readToEnd", + Box::new(|_, args| { + if args.len() != 1 { + return VmNativeAnswer::RuntimeError( + "Signature mismatch expected 1 argument(s)".to_string(), + ); + } + match &args[0] { + VmNativeCallParameters::Static(static_value) => { + if static_value.type_id.is_int() { + let file_handle = static_value.to_int() as *mut usize; + let file = unsafe { &mut *(file_handle as *mut File) }; + + let mut file_contents = String::new(); + match file.read_to_string(&mut file_contents) { + Ok(_) => VmNativeAnswer::Ok(VmNativeCallParameters::Dynamic( + RawType::generate_string(file_contents), + )), + Err(e) => VmNativeAnswer::RuntimeError(format!( + "Failed to read file ({})", + e.to_string() + )), + } + } else { + VmNativeAnswer::RuntimeError( + "Signature mismatch expected 'int' argument".to_string(), + ) + } + } + VmNativeCallParameters::Dynamic(dynamic_value) => { + VmNativeAnswer::RuntimeError( + "Signature mismatch expected static argument".to_string(), + ) + } + } + }), + ))); + vm_settings.modules.push(ellie_core_module); let debug_file = match matches.value_of("debugInfo") { diff --git a/tools/run.sh b/tools/run.sh new file mode 100755 index 00000000..af34bb1e --- /dev/null +++ b/tools/run.sh @@ -0,0 +1,23 @@ +#!/bin/bash + +inputFilePath="$1" +additionalParams="$2" + +# Define the compile and run commands with manifest paths +compileCommand="cargo run --manifest-path=../elliec/Cargo.toml -- compile $inputFilePath -s -a -e -o $additionalParams" +runCommand="cargo run --manifest-path=../ellievm/Cargo.toml -- run ${inputFilePath%.ei}.eic -d ${inputFilePath%.ei}.eig -a" + +#compileCommand="../elliec/target/release/elliec compile $inputFilePath -s -a -e -o $additionalParams" +#runCommand="../ellievm/target/release/ellievm run ${inputFilePath%.ei}.eic -d ${inputFilePath%.ei}.eig -a" + +# Start the compile command process +$compileCommand + +# Check if the compile command exited with an error +if [ $? -ne 0 ]; then + echo "Compile command failed with exit code $?. Error output:" +else + echo "Compile command completed successfully." + # Execute the run command if the compile command succeeded + eval $runCommand +fi From bc1a8d921a3d0c7534642910d0750f63fad9c982 Mon Sep 17 00:00:00 2001 From: Ahmetcan Aksu Date: Thu, 4 Jul 2024 01:06:44 +0300 Subject: [PATCH 20/30] Buff versions --- ellie_engine/bytecode/Cargo.toml | 2 +- ellie_engine/parser/Cargo.toml | 2 +- ellie_engine/tokenizer/Cargo.toml | 2 +- ellie_engine/vm/Cargo.toml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/ellie_engine/bytecode/Cargo.toml b/ellie_engine/bytecode/Cargo.toml index a3443ffe..6057949e 100644 --- a/ellie_engine/bytecode/Cargo.toml +++ b/ellie_engine/bytecode/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "ellie_bytecode" description = "Bytecode assembler/encoder/decoder for ellie language" -version = "0.4.3" +version = "0.5.4" edition = "2021" authors = ["Ahmetcan Aksu ", "Behemehal "] license = "GPL-2.0" diff --git a/ellie_engine/parser/Cargo.toml b/ellie_engine/parser/Cargo.toml index 19d9c754..956b5158 100644 --- a/ellie_engine/parser/Cargo.toml +++ b/ellie_engine/parser/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "ellie_parser" description = "Parser for ellie language" -version = "0.7.2" +version = "0.8.3" authors = ["Ahmetcan Aksu ", "Behemehal "] edition = "2021" license = "GPL-2.0" diff --git a/ellie_engine/tokenizer/Cargo.toml b/ellie_engine/tokenizer/Cargo.toml index 6e3894a9..446db5e8 100644 --- a/ellie_engine/tokenizer/Cargo.toml +++ b/ellie_engine/tokenizer/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "ellie_tokenizer" description = "Tokenizer for ellie language" -version = "0.6.2" +version = "0.7.3" authors = ["Ahmetcan Aksu ", "Behemehal "] edition = "2021" license = "GPL-2.0" diff --git a/ellie_engine/vm/Cargo.toml b/ellie_engine/vm/Cargo.toml index 79e02ff2..736513d0 100644 --- a/ellie_engine/vm/Cargo.toml +++ b/ellie_engine/vm/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "ellie_vm" description = "Ellie VM for running Ellie ByteCode" -version = "0.5.4" +version = "0.6.5" edition = "2021" license = "GPL-2.0" authors = ["Ahmetcan Aksu ", "Behemehal "] From 95c72c4dfb74f57ad3be4e83d0882e160db67a6a Mon Sep 17 00:00:00 2001 From: Ahmetcan Aksu Date: Thu, 4 Jul 2024 01:24:45 +0300 Subject: [PATCH 21/30] Apply clippy --- ellie_engine/Cargo.toml | 8 ++--- ellie_engine/benches/compile.rs | 13 ++++---- ellie_engine/benches/utils.rs | 3 +- ellie_engine/bytecode/Cargo.toml | 2 +- ellie_engine/bytecode/src/addressing_modes.rs | 2 +- ellie_engine/bytecode/src/assembler.rs | 8 ++--- .../src/transpiler/items/condition.rs | 2 +- .../src/transpiler/items/loop_type.rs | 4 +-- .../bytecode/src/transpiler/items/mod.rs | 2 +- .../src/transpiler/items/setter_call.rs | 4 +-- .../bytecode/src/transpiler/items/variable.rs | 4 +-- .../src/transpiler/types/class_call.rs | 2 -- .../bytecode/src/transpiler/types/mod.rs | 6 ++++ ellie_engine/core/src/definite/definers.rs | 12 ++------ ellie_engine/core/src/definite/items/mod.rs | 7 ++--- ellie_engine/core/src/definite/types/mod.rs | 7 ++--- ellie_engine/core/src/defs.rs | 11 +++---- ellie_engine/core/src/information.rs | 6 ++++ ellie_engine/core/src/module_path.rs | 6 ++-- ellie_engine/core/src/utils/mod.rs | 28 +++++++++-------- ellie_engine/fmt/Cargo.toml | 2 +- ellie_engine/fmt/src/fmt.rs | 2 +- ellie_engine/parser/Cargo.toml | 2 +- .../parser/src/deep_search_extensions.rs | 12 +------- ellie_engine/parser/src/extra/item_search.rs | 16 ++++++++-- ellie_engine/parser/src/extra/utils.rs | 6 ++++ ellie_engine/parser/src/parser.rs | 6 ++-- .../parser/src/processors/definer/generic.rs | 2 +- .../parser/src/processors/items/class.rs | 6 ++-- .../src/processors/items/constructor.rs | 6 ++-- .../parser/src/processors/items/enum_type.rs | 2 +- .../parser/src/processors/items/for_loop.rs | 2 +- .../parser/src/processors/items/function.rs | 6 ++-- .../parser/src/processors/items/variable.rs | 6 ++-- .../parser/src/processors/types/class_call.rs | 5 ++-- .../parser/src/processors/types/variable.rs | 2 +- ellie_engine/renderer_utils/src/utils.rs | 8 ++--- .../tokenizer/src/syntax/items/constructor.rs | 2 +- .../tokenizer/tests/items/definer_test.rs | 2 +- .../tokenizer/tests/types/array_test.rs | 2 +- .../tokenizer/tests/types/string_test.rs | 2 +- ellie_engine/vm/src/channel.rs | 6 ++++ ellie_engine/vm/src/heap_memory.rs | 6 ++++ ellie_engine/vm/src/instructions/CALLN.rs | 4 +-- .../stack_memory_functions.rs | 8 ++--- .../static_array_functions.rs | 10 +++---- ellie_engine/vm/src/program.rs | 12 ++++++++ ellie_engine/vm/src/stack.rs | 12 ++++++++ ellie_engine/vm/src/stack_memory.rs | 8 ++++- ellie_engine/vm/src/thread.rs | 30 +++++++++++-------- elliec/build.rs | 2 +- ellievm/src/main.rs | 2 +- 52 files changed, 192 insertions(+), 144 deletions(-) diff --git a/ellie_engine/Cargo.toml b/ellie_engine/Cargo.toml index 25ab086c..0790f778 100644 --- a/ellie_engine/Cargo.toml +++ b/ellie_engine/Cargo.toml @@ -17,10 +17,10 @@ serde_json = { version = "1.0", default-features = false, features = ["alloc"], path-absolutize = { version = "3.0.10", optional = true } ellie_core = { path = "core", version = "0.7.2", default-features = false } #ellie_assist = { path = "EllieAssist", version = "*", optional = true } -ellie_tokenizer = { path = "tokenizer", version = "0.6.2", default-features = false, optional = true } -ellie_parser = { path = "parser", version = "0.7.2", default-features = false, optional = true } -ellie_bytecode = { path = "bytecode", version = "0.4.3", optional = true } -ellie_vm = { path = "vm", version = "0.5.4", optional = true } +ellie_tokenizer = { path = "tokenizer", version = "0.7.3", default-features = false, optional = true } +ellie_parser = { path = "parser", version = "0.8.3", default-features = false, optional = true } +ellie_bytecode = { path = "bytecode", version = "0.5.4", optional = true } +ellie_vm = { path = "vm", version = "0.6.5", optional = true } ellie_fmt = { path = "fmt", version = "0.5.2", optional = true } ellie_renderer_utils = { path = "renderer_utils", version = "0.3.0", optional = true, default-features = false } diff --git a/ellie_engine/benches/compile.rs b/ellie_engine/benches/compile.rs index 3809519d..486cea39 100644 --- a/ellie_engine/benches/compile.rs +++ b/ellie_engine/benches/compile.rs @@ -1,7 +1,6 @@ use criterion::{black_box, criterion_group, criterion_main, Criterion}; -use ellie_engine::{compiler, parseText}; +use ellie_engine::{parseText}; -use crate::codes::BENCH_FIBONACCI_RECURSION; pub mod codes; pub mod utils; @@ -70,11 +69,11 @@ fn byte_code_assembler(c: &mut Criterion) { let fibonacci_recursion_parse = parseText!(codes::BENCH_FIBONACCI_RECURSION).expect("should've been successful"); - c.bench_function("class_byte_code_assembler", |b| { - b.iter(|| { - let _ = black_box(compiler::byte_code_assembler(class_parse.clone())); - }) - }); + //c.bench_function("class_byte_code_assembler", |b| { + // b.iter(|| { + // let _ = black_box(compiler::byte_code_assembler(class_parse.clone())); + // }) + //}); } criterion_group!(benches, tokenize, parse); diff --git a/ellie_engine/benches/utils.rs b/ellie_engine/benches/utils.rs index c2539e0b..b10059c8 100644 --- a/ellie_engine/benches/utils.rs +++ b/ellie_engine/benches/utils.rs @@ -3,7 +3,6 @@ use std::hash::DefaultHasher; use ellie_core::{ defs::{PlatformArchitecture, Version}, - error::Error, utils::PageExport, }; use ellie_engine::{ @@ -28,7 +27,7 @@ impl ProgramRepository for Repository { file_content: self.code.clone(), file_name: "playground.ei".to_string(), file_hash: first_page_hash as usize, - start_directory: format!("",), + start_directory: "".to_string(), } } diff --git a/ellie_engine/bytecode/Cargo.toml b/ellie_engine/bytecode/Cargo.toml index 6057949e..a4626704 100644 --- a/ellie_engine/bytecode/Cargo.toml +++ b/ellie_engine/bytecode/Cargo.toml @@ -10,7 +10,7 @@ homepage = "https://www.ellie-lang.org" [dependencies] ellie_core = { path = "../core", version = "0.7.2" } -ellie_parser = { path = "../parser", version = "0.7.2" } +ellie_parser = { path = "../parser", version = "0.8.3" } enum-as-inner = "0.6.0" lazy_static = "1.4.0" diff --git a/ellie_engine/bytecode/src/addressing_modes.rs b/ellie_engine/bytecode/src/addressing_modes.rs index 85419ec2..7e9cf4c0 100644 --- a/ellie_engine/bytecode/src/addressing_modes.rs +++ b/ellie_engine/bytecode/src/addressing_modes.rs @@ -17,7 +17,7 @@ pub struct Immediate; pub struct Implict; #[derive(Clone, Debug)] -pub struct Absolute(usize); +pub struct Absolute(()); #[derive(Clone, Debug)] pub struct IndirectA; diff --git a/ellie_engine/bytecode/src/assembler.rs b/ellie_engine/bytecode/src/assembler.rs index 8f3ec876..deae07f1 100644 --- a/ellie_engine/bytecode/src/assembler.rs +++ b/ellie_engine/bytecode/src/assembler.rs @@ -114,10 +114,10 @@ impl AssembleResult { .iter() .filter(|x| x.rtype == DebugHeaderType::NativeFunction) .map(|x| NativeCallTrace { - module_name: if x.module_name.contains(">") { + module_name: if x.module_name.contains('>') { x.module_name.to_string() } else { - x.module_name.clone().split(">").collect::>()[0] + x.module_name.clone().split('>').collect::>()[0] .split('_') .last() .unwrap() @@ -205,13 +205,13 @@ impl AssembleResult { for (idx, header) in self.debug_headers.iter().enumerate() { if header.rtype == DebugHeaderType::NativeFunction { native_calls.push(NativeCallTrace { - module_name: if !header.module_name.contains(">") { + module_name: if !header.module_name.contains('>') { header.module_name.to_string() } else { header .module_name .clone() - .split(">") + .split('>') .next() .unwrap() .split('_') diff --git a/ellie_engine/bytecode/src/transpiler/items/condition.rs b/ellie_engine/bytecode/src/transpiler/items/condition.rs index 876327cd..0fc0aaec 100644 --- a/ellie_engine/bytecode/src/transpiler/items/condition.rs +++ b/ellie_engine/bytecode/src/transpiler/items/condition.rs @@ -20,7 +20,7 @@ impl super::Transpiler for condition::Condition { for (_, chain) in self.chains.iter().enumerate() { if chain.rtype != ellie_core::definite::items::condition::ConditionType::Else { let mut binding = TypeTranspilerOptions::new(); - let mut type_transpiler_options = binding + let type_transpiler_options = binding .set_assembler(assembler) .set_dependencies(dependencies.clone()) .set_target_page(hash); diff --git a/ellie_engine/bytecode/src/transpiler/items/loop_type.rs b/ellie_engine/bytecode/src/transpiler/items/loop_type.rs index 6baa8840..7ff6d78d 100644 --- a/ellie_engine/bytecode/src/transpiler/items/loop_type.rs +++ b/ellie_engine/bytecode/src/transpiler/items/loop_type.rs @@ -6,7 +6,7 @@ use ellie_core::{ use crate::{ instruction_table, - instructions::{self, Instruction}, + instructions::{Instruction}, transpiler::types::{TypeTranspiler, TypeTranspilerOptions}, utils::limit_platform_size, }; @@ -29,7 +29,7 @@ impl super::Transpiler for loop_type::Loop { let start_pos = assembler.location() + 1; let mut binding = TypeTranspilerOptions::new(); - let mut type_transpiler_options = binding + let type_transpiler_options = binding .set_assembler(assembler) .set_dependencies(dependencies) .set_target_page(hash); diff --git a/ellie_engine/bytecode/src/transpiler/items/mod.rs b/ellie_engine/bytecode/src/transpiler/items/mod.rs index 11a4af37..0adb888c 100644 --- a/ellie_engine/bytecode/src/transpiler/items/mod.rs +++ b/ellie_engine/bytecode/src/transpiler/items/mod.rs @@ -12,8 +12,8 @@ pub mod ret; pub mod self_item; pub mod setter_call; /* pub mod type_resolver; */ -pub mod variable; pub mod brk; +pub mod variable; use ellie_parser::parser::ProcessedPage; diff --git a/ellie_engine/bytecode/src/transpiler/items/setter_call.rs b/ellie_engine/bytecode/src/transpiler/items/setter_call.rs index 0911ebee..ff6972b0 100644 --- a/ellie_engine/bytecode/src/transpiler/items/setter_call.rs +++ b/ellie_engine/bytecode/src/transpiler/items/setter_call.rs @@ -23,7 +23,7 @@ impl super::Transpiler for setter_call::SetterCall { let location = assembler.location(); let mut binding = TypeTranspilerOptions::new(); - let mut type_transpiler_options = binding + let type_transpiler_options = binding .set_assembler(assembler) .set_target_register(instructions::Registers::C) .set_dependencies(dependencies.clone()) @@ -146,7 +146,7 @@ impl super::Transpiler for setter_call::SetterCall { }; let mut binding = TypeTranspilerOptions::new(); - let mut type_transpiler_options = binding + let type_transpiler_options = binding .set_assembler(assembler) .set_target_register(instructions::Registers::B) .set_dependencies(dependencies) diff --git a/ellie_engine/bytecode/src/transpiler/items/variable.rs b/ellie_engine/bytecode/src/transpiler/items/variable.rs index 40d55883..9d4ab12f 100644 --- a/ellie_engine/bytecode/src/transpiler/items/variable.rs +++ b/ellie_engine/bytecode/src/transpiler/items/variable.rs @@ -1,7 +1,7 @@ use crate::{ assembler::LocalHeader, instruction_table, - instructions::{self, Instruction}, + instructions::{Instruction}, transpiler::types::{TypeTranspiler, TypeTranspilerOptions}, utils::limit_platform_size, }; @@ -31,7 +31,7 @@ impl super::Transpiler for variable::Variable { let mut binding = TypeTranspilerOptions::new(); - let mut type_transpiler_options = binding + let type_transpiler_options = binding .set_assembler(assembler) .set_dependencies(dependencies) .set_target_page(hash); diff --git a/ellie_engine/bytecode/src/transpiler/types/class_call.rs b/ellie_engine/bytecode/src/transpiler/types/class_call.rs index 6b781bcf..8be5ffbd 100644 --- a/ellie_engine/bytecode/src/transpiler/types/class_call.rs +++ b/ellie_engine/bytecode/src/transpiler/types/class_call.rs @@ -113,8 +113,6 @@ impl TypeTranspiler for ClassCall { // First position taken by self let idx = idx + 1; - let prev_ = options.assembler().location(); - param.value.transpile( options .copy() diff --git a/ellie_engine/bytecode/src/transpiler/types/mod.rs b/ellie_engine/bytecode/src/transpiler/types/mod.rs index f9fb3053..ad3eca8c 100644 --- a/ellie_engine/bytecode/src/transpiler/types/mod.rs +++ b/ellie_engine/bytecode/src/transpiler/types/mod.rs @@ -40,6 +40,12 @@ pub struct TypeTranspilerOptions<'a> { dependencies: Option>, } +impl<'a> Default for TypeTranspilerOptions<'a> { + fn default() -> Self { + Self::new() + } +} + impl<'a> TypeTranspilerOptions<'a> { pub fn new() -> Self { Self { diff --git a/ellie_engine/core/src/definite/definers.rs b/ellie_engine/core/src/definite/definers.rs index e31f7932..43dbd294 100644 --- a/ellie_engine/core/src/definite/definers.rs +++ b/ellie_engine/core/src/definite/definers.rs @@ -139,21 +139,13 @@ impl DefinerCollecting { DefinerCollecting::Array(data) => { if let DefinerCollecting::Array(other_data) = other { other_data.size == data.size && other_data.rtype.same_as(*data.rtype.clone()) - } else if DefinerCollecting::Dynamic == other { - true - } else { - false - } + } else { DefinerCollecting::Dynamic == other } } DefinerCollecting::Generic(generic) => { if let DefinerCollecting::Generic(other_generic) = other { (other_generic.rtype == generic.rtype && other_generic.hash == generic.hash) || (other_generic.rtype == "dyn" || generic.rtype == "dyn") - } else if DefinerCollecting::Dynamic == other { - true - } else { - false - } + } else { DefinerCollecting::Dynamic == other } } DefinerCollecting::ParentGeneric(parent_generic) => { if let DefinerCollecting::ParentGeneric(other_parent_generic) = other { diff --git a/ellie_engine/core/src/definite/items/mod.rs b/ellie_engine/core/src/definite/items/mod.rs index 38eb1fcb..21c12cac 100644 --- a/ellie_engine/core/src/definite/items/mod.rs +++ b/ellie_engine/core/src/definite/items/mod.rs @@ -30,6 +30,7 @@ pub mod loop_type; pub mod ret; #[derive(PartialEq, Debug, Clone, Serialize, Deserialize)] +#[derive(Default)] pub enum Collecting { Variable(variable::Variable), Function(function::Function), @@ -55,14 +56,10 @@ pub enum Collecting { ConstructorParameter(constructor_parameter::ConstructorParameter), SelfItem(self_item::SelfItem), ClassInstance(class_instance::ClassInstance), + #[default] None, } -impl Default for Collecting { - fn default() -> Self { - Collecting::None - } -} impl Collecting { pub fn get_pos(&self) -> defs::Cursor { diff --git a/ellie_engine/core/src/definite/types/mod.rs b/ellie_engine/core/src/definite/types/mod.rs index e4cce704..4942b303 100644 --- a/ellie_engine/core/src/definite/types/mod.rs +++ b/ellie_engine/core/src/definite/types/mod.rs @@ -24,6 +24,7 @@ use super::{definers, items::constructor_parameter}; use serde::{Deserialize, Serialize}; #[derive(PartialEq, Debug, Clone, Serialize, Deserialize)] +#[derive(Default)] pub enum Types { Byte(byte::ByteType), Integer(integer::IntegerType), @@ -50,12 +51,8 @@ pub enum Types { VariableType(variable::VariableType), AsKeyword(as_keyword::AsKeyword), ClassInstance(class_instance::ClassInstance), + #[default] Null, Dynamic, } -impl Default for Types { - fn default() -> Self { - Types::Null - } -} diff --git a/ellie_engine/core/src/defs.rs b/ellie_engine/core/src/defs.rs index ac84730b..e7e9d2ae 100644 --- a/ellie_engine/core/src/defs.rs +++ b/ellie_engine/core/src/defs.rs @@ -12,7 +12,9 @@ use serde::{Deserialize, Serialize}; #[cfg(feature = "compiler_utils")] #[derive(PartialEq, Debug, Clone, Serialize, Deserialize)] +#[derive(Default)] pub enum TokenizerType { + #[default] Raw, ClassParser, FunctionParser, @@ -20,11 +22,6 @@ pub enum TokenizerType { } #[cfg(feature = "compiler_utils")] -impl Default for TokenizerType { - fn default() -> Self { - TokenizerType::Raw - } -} #[cfg(feature = "compiler_utils")] #[derive(PartialEq, Debug, Clone, Serialize, Deserialize)] @@ -235,7 +232,7 @@ impl Version { /// * `version` - [`String`] to parse pub fn build_from_string(input: &String) -> Version { let semver_regex = Regex::new(r"^(?P0|[1-9]\d*)\.(?P0|[1-9]\d*)\.(?P0|[1-9]\d*)(?:-(?P(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+(?P[0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$").unwrap(); - let caps = semver_regex.captures(&input).unwrap(); + let caps = semver_regex.captures(input).unwrap(); Version { major: caps @@ -268,7 +265,7 @@ impl Version { /// [`Result`] - If versionb is valid [`Ok(Version)`] otherwise [`Err(u8)`]- pub fn build_from_string_checked(input: &String) -> Result { let semver_regex = Regex::new(r"^(?P0|[1-9]\d*)\.(?P0|[1-9]\d*)\.(?P0|[1-9]\d*)(?:-(?P(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+(?P[0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$").unwrap(); - match semver_regex.captures(&input) { + match semver_regex.captures(input) { Some(caps) => { let major = caps .name("major") diff --git a/ellie_engine/core/src/information.rs b/ellie_engine/core/src/information.rs index 9f6b0d4e..f5e39ed4 100644 --- a/ellie_engine/core/src/information.rs +++ b/ellie_engine/core/src/information.rs @@ -12,6 +12,12 @@ pub struct Informations { pub errors: Vec, } +impl Default for Informations { + fn default() -> Self { + Self::new() + } +} + impl Informations { /// Create a new [`Informations`] instance pub fn new() -> Informations { diff --git a/ellie_engine/core/src/module_path.rs b/ellie_engine/core/src/module_path.rs index 27f24093..048992cb 100644 --- a/ellie_engine/core/src/module_path.rs +++ b/ellie_engine/core/src/module_path.rs @@ -24,7 +24,7 @@ impl Leveler { pub fn new(path: &str) -> Leveler { Leveler { levels: path - .split("/") + .split('/') .enumerate() .map(|(index, path)| PathLevel { name: path.to_string(), @@ -62,7 +62,7 @@ impl Leveler { /// * `0` - Out of path bounds /// * `1` - Path is not a directory pub fn join(&mut self, path: &str) -> i8 { - for command in path.split("/").collect::>() { + for command in path.split('/').collect::>() { if command.starts_with("..") { if !self.pop_one() { return 1; @@ -76,7 +76,7 @@ impl Leveler { }); } } - return 0; + 0 } } diff --git a/ellie_engine/core/src/utils/mod.rs b/ellie_engine/core/src/utils/mod.rs index 07191e8a..bf1d3a0a 100644 --- a/ellie_engine/core/src/utils/mod.rs +++ b/ellie_engine/core/src/utils/mod.rs @@ -83,10 +83,8 @@ pub fn generate_hash() -> String { .map(|_| { rand::random::() }) .collect::>() ) - .replace(" ", "") - .replace(",", "") - .replace("]", "") - .replace("[", "") + .replace(' ', "") + .replace([',', ']', '['], "") } /// ReliableNameRanges is a enum indicates which charachter set is to be used @@ -117,7 +115,7 @@ pub fn reliable_name_range(range: ReliableNameRanges, value: char) -> ReliableNa let find = variable_range.chars().position(|x| x == value); return ReliableNameRangeResponse { - reliable: find != None, + reliable: find.is_some(), at: find.unwrap_or(0), found: variable_range .chars() @@ -477,8 +475,7 @@ pub fn operator_control( }, Operators::Null => unreachable!(), }; - match operator { - Some(operator_string) => Some(error::error_list::ERROR_S52.clone().build_with_path( + operator.map(|operator_string| error::error_list::ERROR_S52.clone().build_with_path( vec![ error::ErrorBuildField { key: "opType".to_owned(), @@ -496,9 +493,7 @@ pub fn operator_control( alloc::format!("{}:{}:{}", file!().to_owned(), line!(), column!()), path, pos, - )), - None => None, - } + )) } pub fn is_operators_chainable(target: Operators, current: Operators) -> bool { @@ -580,13 +575,13 @@ pub struct PageExport { impl Index for PageExport { type Output = T; - fn index<'a>(&'a self, i: usize) -> &'a Self::Output { + fn index(&self, i: usize) -> &Self::Output { &self.pages[i] } } impl IndexMut for PageExport { - fn index_mut<'a>(&'a mut self, i: usize) -> &'a mut Self::Output { + fn index_mut(&mut self, i: usize) -> &mut Self::Output { &mut self.pages[i] } } @@ -595,6 +590,15 @@ pub trait ExportPage { fn get_hash(&self) -> usize; } +impl Default for PageExport +where + T: ExportPage + core::fmt::Debug, + { + fn default() -> Self { + Self::new() + } +} + impl PageExport where T: ExportPage + core::fmt::Debug, diff --git a/ellie_engine/fmt/Cargo.toml b/ellie_engine/fmt/Cargo.toml index 16b7cf23..bcaf6496 100644 --- a/ellie_engine/fmt/Cargo.toml +++ b/ellie_engine/fmt/Cargo.toml @@ -12,7 +12,7 @@ homepage = "https://www.ellie-lang.org" lazy_static = "1.4.0" serde = { version = "1.0", features = ["derive"] } serde_json = { version = "1.0", default-features = false, features = ["alloc"] } -ellie_tokenizer = { path = "../tokenizer", version = "0.6.2" } +ellie_tokenizer = { path = "../tokenizer", version = "0.7.3" } ellie_core = { path = "../core", version = "0.7.2" } [features] diff --git a/ellie_engine/fmt/src/fmt.rs b/ellie_engine/fmt/src/fmt.rs index 879806c4..ea700b47 100644 --- a/ellie_engine/fmt/src/fmt.rs +++ b/ellie_engine/fmt/src/fmt.rs @@ -104,7 +104,7 @@ impl Formatter { for item in &page.items { match item { Processors::Function(_) | Processors::Class(_) => { - if output.lines.len() != 0 { + if !output.lines.is_empty() { output.lines.push(String::new()); } last_element_is_fn_or_class = true; diff --git a/ellie_engine/parser/Cargo.toml b/ellie_engine/parser/Cargo.toml index 956b5158..5c83cfea 100644 --- a/ellie_engine/parser/Cargo.toml +++ b/ellie_engine/parser/Cargo.toml @@ -13,7 +13,7 @@ lazy_static = "1.4.0" serde = { version = "1.0", features = ["derive"] } serde_json = { version = "1.0", default-features = false, features = ["alloc"] } ellie_core = { path = "../core", version = "0.7.2" } -ellie_tokenizer = { path = "../tokenizer", version = "0.6.2", default-features = false } +ellie_tokenizer = { path = "../tokenizer", version = "0.7.3", default-features = false } enum-as-inner = "0.6.0" ellie_standard_rules = { path = "./standard_rules", version = "0.1.0", optional = true } diff --git a/ellie_engine/parser/src/deep_search_extensions.rs b/ellie_engine/parser/src/deep_search_extensions.rs index 88d53399..ab345cd1 100644 --- a/ellie_engine/parser/src/deep_search_extensions.rs +++ b/ellie_engine/parser/src/deep_search_extensions.rs @@ -349,7 +349,6 @@ fn iterate_deep_type( _rtype: AttributeType, name: String, value: definers::DefinerCollecting, - page: usize, } fn resolve_chain( @@ -412,7 +411,6 @@ fn iterate_deep_type( _rtype: AttributeType::Property, name: e.data.name.clone(), value: resolved_type, - page: class_inner_page.hash, }) }, Processors::Function(e) => { @@ -448,7 +446,6 @@ fn iterate_deep_type( returning, } ), - page: class_inner_page.hash, }) }, Processors::Getter(e) => { @@ -467,10 +464,9 @@ fn iterate_deep_type( _rtype: AttributeType::Method, name: e.name.clone(), value, - page: class_inner_page.hash, }) } - Processors::Setter(e) => { + Processors::Setter(_) => { todo!() } _ => None, @@ -498,7 +494,6 @@ fn iterate_deep_type( hash: enum_data.hash, } ), - page: page_id, } }).collect() ) @@ -691,7 +686,6 @@ fn iterate_deep_type( _rtype: attribute._rtype.clone(), name: attribute.name.clone(), value, - page: page_id, }); } Collecting::Function(e) => { @@ -708,7 +702,6 @@ fn iterate_deep_type( returning: Box::new(e.return_type), }, ), - page: page.hash, }); } Collecting::Getter(e) => { @@ -716,7 +709,6 @@ fn iterate_deep_type( _rtype: attribute._rtype.clone(), name: attribute.name.clone(), value: e.return_type, - page: page.hash, }); } Collecting::Setter(e) => { @@ -724,7 +716,6 @@ fn iterate_deep_type( _rtype: attribute._rtype.clone(), name: attribute.name.clone(), value: e.rtype, - page: page.hash, }); } Collecting::NativeFunction(e) => { @@ -741,7 +732,6 @@ fn iterate_deep_type( returning: Box::new(e.return_type), }, ), - page: page.hash, }); } _ => (), diff --git a/ellie_engine/parser/src/extra/item_search.rs b/ellie_engine/parser/src/extra/item_search.rs index 4d94d9fd..134cacfc 100644 --- a/ellie_engine/parser/src/extra/item_search.rs +++ b/ellie_engine/parser/src/extra/item_search.rs @@ -13,6 +13,12 @@ pub struct FoundPage { pub processed_page: Option, } +impl Default for FoundPage { + fn default() -> Self { + Self::new() + } +} + impl FoundPage { pub fn new() -> Self { FoundPage { @@ -22,11 +28,11 @@ impl FoundPage { } pub fn as_raw(&self) -> &Page { - &self.raw_page.as_ref().unwrap() + self.raw_page.as_ref().unwrap() } pub fn as_processed(&self) -> &ProcessedPage { - &self.processed_page.as_ref().unwrap() + self.processed_page.as_ref().unwrap() } pub fn fill(&mut self, page: &Page) { @@ -44,6 +50,12 @@ pub struct FoundItem { processed_item: Option, } +impl Default for FoundItem { + fn default() -> Self { + Self::new() + } +} + impl FoundItem { pub fn new() -> Self { FoundItem { diff --git a/ellie_engine/parser/src/extra/utils.rs b/ellie_engine/parser/src/extra/utils.rs index 2d375f3d..6cb88f64 100644 --- a/ellie_engine/parser/src/extra/utils.rs +++ b/ellie_engine/parser/src/extra/utils.rs @@ -15,6 +15,12 @@ pub struct DeepSearchOptions<'a> { pub(in crate::extra) search_on_raw: bool, } +impl<'a> Default for DeepSearchOptions<'a> { + fn default() -> Self { + Self::new() + } +} + impl<'a> DeepSearchOptions<'a> { pub fn new() -> Self { Self { diff --git a/ellie_engine/parser/src/parser.rs b/ellie_engine/parser/src/parser.rs index c6eb3128..7fd0030b 100644 --- a/ellie_engine/parser/src/parser.rs +++ b/ellie_engine/parser/src/parser.rs @@ -1696,7 +1696,7 @@ impl Parser { ); err.reference_block = Some((function_page.return_pos, page_path.clone())); - err.reference_message = "Defined here".to_owned(); + "Defined here".clone_into(&mut err.reference_message); err.semi_assist = true; self.informations.push(&err); } @@ -1725,7 +1725,7 @@ impl Parser { ); err.reference_block = Some((function_page.return_pos, page_path)); - err.reference_message = "Defined here".to_owned(); + "Defined here".clone_into(&mut err.reference_message); err.semi_assist = true; self.informations.push(&err); } @@ -1955,7 +1955,7 @@ impl Parser { if main_function.found { match main_function.found_item { DeepSearchItems::Function(e) => { - if e.parameters.len() > 0 { + if !e.parameters.is_empty() { let path = self.find_page(self.initial_page).unwrap().path.clone(); self.informations.push( &error::error_list::ERROR_S67.clone().build_with_path( diff --git a/ellie_engine/parser/src/processors/definer/generic.rs b/ellie_engine/parser/src/processors/definer/generic.rs index e0390a42..910ddb12 100644 --- a/ellie_engine/parser/src/processors/definer/generic.rs +++ b/ellie_engine/parser/src/processors/definer/generic.rs @@ -16,7 +16,7 @@ impl super::DefinerParserProcessor for GenericType { let mut found = DefinerCollecting::Dynamic; let generic_search = item_search( - &mut &mut &mut &mut DeepSearchOptions::new() + &mut DeepSearchOptions::new() .parser(options.parser) .page_id(options.page_id) .search_on_all() diff --git a/ellie_engine/parser/src/processors/items/class.rs b/ellie_engine/parser/src/processors/items/class.rs index 270abb75..f57f3181 100644 --- a/ellie_engine/parser/src/processors/items/class.rs +++ b/ellie_engine/parser/src/processors/items/class.rs @@ -58,7 +58,7 @@ impl super::ItemParserProcessor for Class { self.name_pos, ); err.reference_block = Some((cursor_pos, page.path)); - err.reference_message = "Prime is here".to_owned(); + "Prime is here".clone_into(&mut err.reference_message); err.semi_assist = true; options.parser.informations.push(&err); } else { @@ -158,7 +158,7 @@ impl super::ItemParserProcessor for Class { constructor.unwrap().pos, ); err.reference_block = Some((prime.pos, page.path.clone())); - err.reference_message = "Prime is here".to_owned(); + "Prime is here".clone_into(&mut err.reference_message); err.semi_assist = true; options.parser.informations.push(&err); } @@ -179,7 +179,7 @@ impl super::ItemParserProcessor for Class { ); err.reference_block = Some((self.generic_definings[other_index].pos, page.path.clone())); - err.reference_message = "Prime is here".to_owned(); + "Prime is here".clone_into(&mut err.reference_message); err.semi_assist = true; options.parser.informations.push(&err); } diff --git a/ellie_engine/parser/src/processors/items/constructor.rs b/ellie_engine/parser/src/processors/items/constructor.rs index 41ebd0c0..fa1cb786 100644 --- a/ellie_engine/parser/src/processors/items/constructor.rs +++ b/ellie_engine/parser/src/processors/items/constructor.rs @@ -112,7 +112,7 @@ impl super::ItemParserProcessor for Constructor { parameter.pos, ); err.reference_block = Some((class_element.pos, path.clone())); - err.reference_message = "Prime is here".to_owned(); + "Prime is here".clone_into(&mut err.reference_message); err.semi_assist = true; options.parser.informations.push(&err); return false; @@ -131,7 +131,7 @@ impl super::ItemParserProcessor for Constructor { parameter.pos, ); err.reference_block = Some((self.parameters[other_index].pos, path.clone())); - err.reference_message = "Prime is here".to_owned(); + "Prime is here".clone_into(&mut err.reference_message); err.semi_assist = true; options.parser.informations.push(&err); } @@ -159,7 +159,7 @@ impl super::ItemParserProcessor for Constructor { parameter.pos, ); err.reference_block = Some((class_element.pos, class_page.path.clone())); - err.reference_message = "Class body is here".to_owned(); + "Class body is here".clone_into(&mut err.reference_message); options.parser.informations.push(&err); } diff --git a/ellie_engine/parser/src/processors/items/enum_type.rs b/ellie_engine/parser/src/processors/items/enum_type.rs index aab7affe..aecc5916 100644 --- a/ellie_engine/parser/src/processors/items/enum_type.rs +++ b/ellie_engine/parser/src/processors/items/enum_type.rs @@ -72,7 +72,7 @@ impl super::ItemParserProcessor for EnumType { self.name_pos, ); err.reference_block = Some((cursor_pos, page.path)); - err.reference_message = "Prime is here".to_owned(); + "Prime is here".clone_into(&mut err.reference_message); err.semi_assist = true; options.parser.informations.push(&err); } else { diff --git a/ellie_engine/parser/src/processors/items/for_loop.rs b/ellie_engine/parser/src/processors/items/for_loop.rs index 2d2496cf..f518ebdf 100644 --- a/ellie_engine/parser/src/processors/items/for_loop.rs +++ b/ellie_engine/parser/src/processors/items/for_loop.rs @@ -81,7 +81,7 @@ impl super::ItemParserProcessor for ForLoop { self.variable_pos, ); err.reference_block = Some((cursor_pos, page.path)); - err.reference_message = "Prime is here".to_owned(); + "Prime is here".clone_into(&mut err.reference_message); err.semi_assist = true; options.parser.informations.push(&err); } else { diff --git a/ellie_engine/parser/src/processors/items/function.rs b/ellie_engine/parser/src/processors/items/function.rs index addbb7ef..36a87c93 100644 --- a/ellie_engine/parser/src/processors/items/function.rs +++ b/ellie_engine/parser/src/processors/items/function.rs @@ -63,7 +63,7 @@ impl super::ItemParserProcessor for FunctionCollector { self.data.name_pos, ); err.reference_block = Some((cursor_pos, found_page.path)); - err.reference_message = "Prime is here".to_owned(); + "Prime is here".clone_into(&mut err.reference_message); err.semi_assist = true; options.parser.informations.push(&err); } else { @@ -167,7 +167,7 @@ impl super::ItemParserProcessor for FunctionCollector { }, page.path.clone(), )); - err.reference_message = "Prime is here".to_owned(); + "Prime is here".clone_into(&mut err.reference_message); err.semi_assist = true; options.parser.informations.push(&err); } @@ -191,7 +191,7 @@ impl super::ItemParserProcessor for FunctionCollector { parameter.name_pos, ); err.reference_block = Some((cursor_pos, page.path)); - err.reference_message = "Prime is here".to_owned(); + "Prime is here".clone_into(&mut err.reference_message); err.semi_assist = true; options.parser.informations.push(&err); } else { diff --git a/ellie_engine/parser/src/processors/items/variable.rs b/ellie_engine/parser/src/processors/items/variable.rs index 1d457f45..8d3a64c9 100644 --- a/ellie_engine/parser/src/processors/items/variable.rs +++ b/ellie_engine/parser/src/processors/items/variable.rs @@ -46,7 +46,7 @@ impl super::ItemParserProcessor for VariableCollector { self.data.name_pos, ); err.reference_block = Some((cursor_pos, page.path)); - err.reference_message = "Prime is here".to_owned(); + "Prime is here".clone_into(&mut err.reference_message); err.semi_assist = true; options.parser.informations.push(&err); } else { @@ -357,7 +357,7 @@ impl super::ItemParserProcessor for VariableCollector { ); err.reference_block = Some((self.data.type_pos, current_page.path.clone())); - err.reference_message = "Defined here".to_owned(); + "Defined here".clone_into(&mut err.reference_message); err.semi_assist = true; options.parser.informations.push(&err); return false; @@ -385,7 +385,7 @@ impl super::ItemParserProcessor for VariableCollector { ); err.reference_block = Some((self.data.type_pos, current_page.path.clone())); - err.reference_message = "Defined here".to_owned(); + "Defined here".clone_into(&mut err.reference_message); err.semi_assist = true; options.parser.informations.push(&err); false diff --git a/ellie_engine/parser/src/processors/types/class_call.rs b/ellie_engine/parser/src/processors/types/class_call.rs index 255a8b02..a8da2ec0 100644 --- a/ellie_engine/parser/src/processors/types/class_call.rs +++ b/ellie_engine/parser/src/processors/types/class_call.rs @@ -5,9 +5,8 @@ use ellie_core::{ }; use ellie_tokenizer::{ processors::{items::Processors as ItemProcessors, types::Processors}, - syntax::types::{class_call_type, variable_type}, + syntax::types::{class_call_type}, }; -use types::variable::VariableType; use crate::{ deep_search_extensions::{ @@ -286,7 +285,7 @@ impl super::TypeParserProcessor for class_call_type::ClassCallCollector { .path .clone(), )); - error.reference_message = "Defined here".to_owned(); + "Defined here".clone_into(&mut error.reference_message); errors.push(error); Err(errors) } else if !undefined_generics.is_empty() { diff --git a/ellie_engine/parser/src/processors/types/variable.rs b/ellie_engine/parser/src/processors/types/variable.rs index a9731092..e82dc27e 100644 --- a/ellie_engine/parser/src/processors/types/variable.rs +++ b/ellie_engine/parser/src/processors/types/variable.rs @@ -69,7 +69,7 @@ impl super::TypeParserProcessor for variable_type::VariableTypeCollector { ); error.reference_block = Some((e.pos, deep_search_result.found_page.path.clone())); - error.reference_message = "Defined here".to_owned(); + "Defined here".clone_into(&mut error.reference_message); errors.push(error); return Err(errors); } diff --git a/ellie_engine/renderer_utils/src/utils.rs b/ellie_engine/renderer_utils/src/utils.rs index a4ccaede..d152019e 100644 --- a/ellie_engine/renderer_utils/src/utils.rs +++ b/ellie_engine/renderer_utils/src/utils.rs @@ -295,20 +295,18 @@ pub fn _get_lines(code: String, lines: defs::Cursor, color_outp /// Get line from code pub fn get_line(code: String, line: usize) -> String { let v: Vec<&str> = code - .split(code.contains("\r\n").then(|| "\r\n").unwrap_or("\n")) + .split(if code.contains("\r\n") { "\r\n" } else { "\n" }) .collect(); if line > v.len() { v[v.len() - 1] .to_string() .replace('\t', " ") - .replace('\n', "") - .replace('\r', "") + .replace(['\n', '\r'], "") } else { v[line] .to_string() .replace('\t', " ") - .replace('\n', "") - .replace('\r', "") + .replace(['\n', '\r'], "") } } diff --git a/ellie_engine/tokenizer/src/syntax/items/constructor.rs b/ellie_engine/tokenizer/src/syntax/items/constructor.rs index 4fffc737..96707343 100644 --- a/ellie_engine/tokenizer/src/syntax/items/constructor.rs +++ b/ellie_engine/tokenizer/src/syntax/items/constructor.rs @@ -1,4 +1,4 @@ -use crate::{processors::items::Processors, syntax::items::definers}; +use crate::processors::items::Processors; use ellie_core::{definite::Converter, defs}; use serde::{Deserialize, Serialize}; diff --git a/ellie_engine/tokenizer/tests/items/definer_test.rs b/ellie_engine/tokenizer/tests/items/definer_test.rs index fb2b5017..517e018a 100644 --- a/ellie_engine/tokenizer/tests/items/definer_test.rs +++ b/ellie_engine/tokenizer/tests/items/definer_test.rs @@ -2,7 +2,7 @@ mod definer_tests { use ellie_core::{defs, error}; use ellie_tokenizer::{ - processors::{items::Processors, Processor}, + processors::{Processor}, syntax::items::definers, }; use std::{ diff --git a/ellie_engine/tokenizer/tests/types/array_test.rs b/ellie_engine/tokenizer/tests/types/array_test.rs index 105c7d99..8a347b82 100644 --- a/ellie_engine/tokenizer/tests/types/array_test.rs +++ b/ellie_engine/tokenizer/tests/types/array_test.rs @@ -2,7 +2,7 @@ mod array_tests { use ellie_core::{defs, error}; use ellie_tokenizer::processors::{ - types::{Processors, TypeProcessor}, + types::{TypeProcessor}, Processor, }; use std::{ diff --git a/ellie_engine/tokenizer/tests/types/string_test.rs b/ellie_engine/tokenizer/tests/types/string_test.rs index cb1ff213..29699b03 100644 --- a/ellie_engine/tokenizer/tests/types/string_test.rs +++ b/ellie_engine/tokenizer/tests/types/string_test.rs @@ -33,7 +33,7 @@ mod string_tests { last_char = letter_char; } assert!( - errors.len() != 0 + !errors.is_empty() && errors[0].code == 0 && errors[0].builded_message.fields[0].value == "e" ); diff --git a/ellie_engine/vm/src/channel.rs b/ellie_engine/vm/src/channel.rs index 9507fb99..fa3d71c2 100644 --- a/ellie_engine/vm/src/channel.rs +++ b/ellie_engine/vm/src/channel.rs @@ -95,6 +95,12 @@ pub struct ModuleManager { pub modules: Vec, } +impl Default for ModuleManager { + fn default() -> Self { + Self::new() + } +} + impl ModuleManager { pub fn new() -> Self { ModuleManager { diff --git a/ellie_engine/vm/src/heap_memory.rs b/ellie_engine/vm/src/heap_memory.rs index 68328111..514deb7b 100644 --- a/ellie_engine/vm/src/heap_memory.rs +++ b/ellie_engine/vm/src/heap_memory.rs @@ -23,6 +23,12 @@ impl Clone for HeapMemory { } } +impl Default for HeapMemory { + fn default() -> Self { + Self::new() + } +} + impl HeapMemory { pub fn new() -> HeapMemory { HeapMemory { diff --git a/ellie_engine/vm/src/instructions/CALLN.rs b/ellie_engine/vm/src/instructions/CALLN.rs index 23443dcc..cf270060 100644 --- a/ellie_engine/vm/src/instructions/CALLN.rs +++ b/ellie_engine/vm/src/instructions/CALLN.rs @@ -70,8 +70,8 @@ impl super::InstructionExecuter for CALLN { ReferenceType::Heap }, raw_type.to_uint(), - &heap_memory, - &stack_memory, + heap_memory, + stack_memory, ) .unwrap() { diff --git a/ellie_engine/vm/src/iternal_functions/stack_memory_functions.rs b/ellie_engine/vm/src/iternal_functions/stack_memory_functions.rs index f6fb3dd0..b7def27e 100644 --- a/ellie_engine/vm/src/iternal_functions/stack_memory_functions.rs +++ b/ellie_engine/vm/src/iternal_functions/stack_memory_functions.rs @@ -13,7 +13,7 @@ pub fn frame_pos_fn( thread_info: ThreadInfo, args: Vec, ) -> VmNativeAnswer { - if args.len() != 0 { + if !args.is_empty() { return VmNativeAnswer::RuntimeError( "Signature mismatch expected 0 argument(s)".to_string(), ); @@ -28,7 +28,7 @@ pub fn code_pos_fn( thread_info: ThreadInfo, args: Vec, ) -> VmNativeAnswer { - if args.len() != 0 { + if !args.is_empty() { return VmNativeAnswer::RuntimeError( "Signature mismatch expected 0 argument(s)".to_string(), ); @@ -39,11 +39,11 @@ pub fn code_pos_fn( } pub const FRAME_POS: InternalFunction = InternalFunction { - name: &"frame_pos", + name: "frame_pos", callback: frame_pos_fn, }; pub const CODE_POS: InternalFunction = InternalFunction { - name: &"code_pos", + name: "code_pos", callback: code_pos_fn, }; diff --git a/ellie_engine/vm/src/iternal_functions/static_array_functions.rs b/ellie_engine/vm/src/iternal_functions/static_array_functions.rs index f742d6e1..9d308359 100644 --- a/ellie_engine/vm/src/iternal_functions/static_array_functions.rs +++ b/ellie_engine/vm/src/iternal_functions/static_array_functions.rs @@ -30,15 +30,15 @@ pub fn array_len_fn( )) } None => { - return VmNativeAnswer::RuntimeError( + VmNativeAnswer::RuntimeError( "Memory corruption occurred (array_len)".to_string(), - ); + ) } } } else { - return VmNativeAnswer::RuntimeError( + VmNativeAnswer::RuntimeError( "Signature mismatch expected an array".to_string(), - ); + ) } } VmNativeCallParameters::Dynamic(_) => VmNativeAnswer::RuntimeError( @@ -48,6 +48,6 @@ pub fn array_len_fn( } pub const ARRAY_LEN: InternalFunction = InternalFunction { - name: &"array_len", + name: "array_len", callback: array_len_fn, }; diff --git a/ellie_engine/vm/src/program.rs b/ellie_engine/vm/src/program.rs index 2b8b471a..58796663 100644 --- a/ellie_engine/vm/src/program.rs +++ b/ellie_engine/vm/src/program.rs @@ -55,6 +55,12 @@ pub struct Program { pub instructions: Vec, } +impl Default for Program { + fn default() -> Self { + Self::new() + } +} + impl Program { pub fn new() -> Self { Self { @@ -332,6 +338,12 @@ pub struct VmProgram { pub length: usize, } +impl Default for VmProgram { + fn default() -> Self { + Self::new() + } +} + impl VmProgram { pub fn new() -> Self { VmProgram { diff --git a/ellie_engine/vm/src/stack.rs b/ellie_engine/vm/src/stack.rs index 1b56e53b..7a3ba4aa 100644 --- a/ellie_engine/vm/src/stack.rs +++ b/ellie_engine/vm/src/stack.rs @@ -23,6 +23,12 @@ pub struct Stack { pub caller: Option, } +impl Default for Stack { + fn default() -> Self { + Self::new() + } +} + impl Stack { pub fn new() -> Stack { Stack { @@ -56,6 +62,12 @@ pub struct StackArray { pub len: usize, } +impl Default for StackArray { + fn default() -> Self { + Self::new() + } +} + impl StackArray { pub fn new() -> Self { StackArray { diff --git a/ellie_engine/vm/src/stack_memory.rs b/ellie_engine/vm/src/stack_memory.rs index 6e6617dc..018ff766 100644 --- a/ellie_engine/vm/src/stack_memory.rs +++ b/ellie_engine/vm/src/stack_memory.rs @@ -18,13 +18,19 @@ pub struct StackMemory { impl Clone for StackMemory { fn clone(&self) -> Self { StackMemory { - data: self.data.clone(), + data: self.data, len: self.len, on_stack_overflow: None, } } } +impl Default for StackMemory { + fn default() -> Self { + Self::new() + } +} + impl StackMemory { pub fn new() -> StackMemory { StackMemory { diff --git a/ellie_engine/vm/src/thread.rs b/ellie_engine/vm/src/thread.rs index f023448b..f6fde8bb 100644 --- a/ellie_engine/vm/src/thread.rs +++ b/ellie_engine/vm/src/thread.rs @@ -33,6 +33,12 @@ pub struct Isolate { pub stack_memory: StackMemory, } +impl Default for Isolate { + fn default() -> Self { + Self::new() + } +} + impl Isolate { pub fn new() -> Self { Isolate { @@ -208,13 +214,13 @@ impl Thread { StepResult::Step } VmNativeAnswer::RuntimeError(e) => { - return StepResult::ThreadExit(ThreadExit::Panic( + StepResult::ThreadExit(ThreadExit::Panic( ThreadPanic { reason: ThreadPanicReason::RuntimeError(e), stack_trace: self.stack.clone(), code_location: format!("{}:{}", file!(), line!()), }, - )); + )) } } } else { @@ -267,7 +273,7 @@ impl Thread { StepResult::Step } VmNativeAnswer::RuntimeError(e) => { - return StepResult::ThreadExit(ThreadExit::Panic(ThreadPanic { + StepResult::ThreadExit(ThreadExit::Panic(ThreadPanic { reason: ThreadPanicReason::RuntimeError(e), stack_trace: self.stack.clone(), code_location: format!( @@ -275,13 +281,13 @@ impl Thread { file!(), line!() ), - })); + })) } } } }, None => { - return StepResult::ThreadExit(ThreadExit::Panic( + StepResult::ThreadExit(ThreadExit::Panic( ThreadPanic { reason: ThreadPanicReason::CallToUnknown(( found_trace.function_name.clone(), @@ -294,12 +300,12 @@ impl Thread { line!() ), }, - )); + )) } } } None => { - return StepResult::ThreadExit(ThreadExit::Panic( + StepResult::ThreadExit(ThreadExit::Panic( ThreadPanic { reason: ThreadPanicReason::MissingModule( native_call.hash, @@ -307,27 +313,27 @@ impl Thread { stack_trace: self.stack.clone(), code_location: format!("{}:{}", file!(), line!()), }, - )); + )) } } } } None => { - return StepResult::ThreadExit(ThreadExit::Panic(ThreadPanic { + StepResult::ThreadExit(ThreadExit::Panic(ThreadPanic { reason: ThreadPanicReason::MissingTrace(native_call.hash), stack_trace: self.stack.clone(), code_location: format!("{}:{}", file!(), line!()), - })); + })) } } } }, Err(panic) => { - return StepResult::ThreadExit(ThreadExit::Panic(ThreadPanic { + StepResult::ThreadExit(ThreadExit::Panic(ThreadPanic { reason: panic.reason, stack_trace: self.stack.clone(), code_location: panic.code_location, - })); + })) } } } diff --git a/elliec/build.rs b/elliec/build.rs index c6785d68..b200cbd4 100644 --- a/elliec/build.rs +++ b/elliec/build.rs @@ -1,6 +1,6 @@ fn main() { if std::env::var("CARGO_CFG_TARGET_OS").unwrap() == "windows" { - let mut res = winresource::WindowsResource::new(); + let res = winresource::WindowsResource::new(); res.compile().unwrap(); } } diff --git a/ellievm/src/main.rs b/ellievm/src/main.rs index 9ce1a4de..92db2237 100644 --- a/ellievm/src/main.rs +++ b/ellievm/src/main.rs @@ -252,7 +252,7 @@ fn main() { ) } } - VmNativeCallParameters::Dynamic(dynamic_value) => { + VmNativeCallParameters::Dynamic(_) => { VmNativeAnswer::RuntimeError( "Signature mismatch expected static argument".to_string(), ) From 2806fb68e042d2a359e6c049a2aa224df2d53b1d Mon Sep 17 00:00:00 2001 From: Ahmetcan Aksu Date: Thu, 4 Jul 2024 01:37:52 +0300 Subject: [PATCH 22/30] Add new version info --- ellie_engine/Cargo.toml | 4 ++-- ellie_engine/bytecode/Cargo.toml | 2 +- ellie_engine/core/Cargo.toml | 2 +- ellie_engine/fmt/Cargo.toml | 2 +- ellie_engine/parser/Cargo.toml | 2 +- ellie_engine/renderer_utils/Cargo.toml | 2 +- ellie_engine/src/engine_constants.rs | 18 +++++++++--------- ellie_engine/tokenizer/Cargo.toml | 2 +- ellie_engine/vm/Cargo.toml | 2 +- 9 files changed, 18 insertions(+), 18 deletions(-) diff --git a/ellie_engine/Cargo.toml b/ellie_engine/Cargo.toml index 0790f778..52bc0d10 100644 --- a/ellie_engine/Cargo.toml +++ b/ellie_engine/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "ellie_engine" description = "Why ellie? Ellie is a type-safe programing language that runs on embedded and sandboxed environments." -version = "1.4.13-alpha" +version = "1.5.20-alpha" authors = ["Ahmetcan Aksu ", "Behemehal "] edition = "2021" license-file = "../LICENSE" @@ -15,7 +15,7 @@ homepage = "https://www.ellie-lang.org" serde = { version = "1.0", features = ["derive"], optional = true } serde_json = { version = "1.0", default-features = false, features = ["alloc"], optional = true } path-absolutize = { version = "3.0.10", optional = true } -ellie_core = { path = "core", version = "0.7.2", default-features = false } +ellie_core = { path = "core", version = "0.7.3", default-features = false } #ellie_assist = { path = "EllieAssist", version = "*", optional = true } ellie_tokenizer = { path = "tokenizer", version = "0.7.3", default-features = false, optional = true } ellie_parser = { path = "parser", version = "0.8.3", default-features = false, optional = true } diff --git a/ellie_engine/bytecode/Cargo.toml b/ellie_engine/bytecode/Cargo.toml index a4626704..7463388b 100644 --- a/ellie_engine/bytecode/Cargo.toml +++ b/ellie_engine/bytecode/Cargo.toml @@ -9,7 +9,7 @@ repository = "https://github.com/behemehal/Ellie-Language" homepage = "https://www.ellie-lang.org" [dependencies] -ellie_core = { path = "../core", version = "0.7.2" } +ellie_core = { path = "../core", version = "0.7.3" } ellie_parser = { path = "../parser", version = "0.8.3" } enum-as-inner = "0.6.0" lazy_static = "1.4.0" diff --git a/ellie_engine/core/Cargo.toml b/ellie_engine/core/Cargo.toml index d359b3a3..523b8eb5 100644 --- a/ellie_engine/core/Cargo.toml +++ b/ellie_engine/core/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "ellie_core" description = "Core modules for ellie" -version = "0.7.2" +version = "0.7.3" authors = [ "Ahmetcan Aksu ", "Behemehal ", diff --git a/ellie_engine/fmt/Cargo.toml b/ellie_engine/fmt/Cargo.toml index bcaf6496..6a5a9d07 100644 --- a/ellie_engine/fmt/Cargo.toml +++ b/ellie_engine/fmt/Cargo.toml @@ -13,7 +13,7 @@ lazy_static = "1.4.0" serde = { version = "1.0", features = ["derive"] } serde_json = { version = "1.0", default-features = false, features = ["alloc"] } ellie_tokenizer = { path = "../tokenizer", version = "0.7.3" } -ellie_core = { path = "../core", version = "0.7.2" } +ellie_core = { path = "../core", version = "0.7.3" } [features] default = ["std"] diff --git a/ellie_engine/parser/Cargo.toml b/ellie_engine/parser/Cargo.toml index 5c83cfea..a3c11ffb 100644 --- a/ellie_engine/parser/Cargo.toml +++ b/ellie_engine/parser/Cargo.toml @@ -12,7 +12,7 @@ homepage = "https://www.ellie-lang.org" lazy_static = "1.4.0" serde = { version = "1.0", features = ["derive"] } serde_json = { version = "1.0", default-features = false, features = ["alloc"] } -ellie_core = { path = "../core", version = "0.7.2" } +ellie_core = { path = "../core", version = "0.7.3" } ellie_tokenizer = { path = "../tokenizer", version = "0.7.3", default-features = false } enum-as-inner = "0.6.0" ellie_standard_rules = { path = "./standard_rules", version = "0.1.0", optional = true } diff --git a/ellie_engine/renderer_utils/Cargo.toml b/ellie_engine/renderer_utils/Cargo.toml index 69ce936e..ba7cdd63 100644 --- a/ellie_engine/renderer_utils/Cargo.toml +++ b/ellie_engine/renderer_utils/Cargo.toml @@ -15,7 +15,7 @@ homepage = "https://www.ellie-lang.org" lazy_static = { version = "1.4.0", optional = true } clap = { version = "3.1.1", optional = true } clap_complete = { version = "3.0.0", optional = true } -ellie_core = { path = "../core", version = "0.7.2" } +ellie_core = { path = "../core", version = "0.7.3" } serde = { version = "1.0", features = ["derive"], optional = true } serde_json = { version = "1.0", default-features = false, optional = true } path-absolutize = { version = "3.0.10", optional = true } diff --git a/ellie_engine/src/engine_constants.rs b/ellie_engine/src/engine_constants.rs index e5e6cec5..70827342 100644 --- a/ellie_engine/src/engine_constants.rs +++ b/ellie_engine/src/engine_constants.rs @@ -1,11 +1,11 @@ -pub static ELLIE_ENGINE_VERSION: &str = &"1.4.13-alpha"; -pub static ELLIE_ENGINE_VERSION_NAME: &str = &"Seftali"; +pub static ELLIE_ENGINE_VERSION: &str = &"1.5.20-alpha"; +pub static ELLIE_ENGINE_VERSION_NAME: &str = &"Dolunay"; pub static ELLIE_CORE_VERSION: &str = &"0.7.2"; -pub static ELLIE_TOKENIZER_VERSION: &str = &"0.6.2"; -pub static ELLIE_PARSER_VERSION: &str = &"0.7.2"; -pub static ELLIE_BYTECODE_VERSION: &str = &"0.4.3"; +pub static ELLIE_TOKENIZER_VERSION: &str = &"0.7.3"; +pub static ELLIE_PARSER_VERSION: &str = &"0.8.3"; +pub static ELLIE_BYTECODE_VERSION: &str = &"0.5.4"; pub static ELLIE_FMT_VERSION: &str = &"0.5.2"; -pub static ELLIE_VM_VERSION: &str = &"0.5.4"; -pub static ELLIE_BUILD_DATE: &str = &"2024-04-23"; -pub static ELLIE_BUILD_GIT_HASH: &str = &"d4368f4"; -pub static ELLIE_BUILD_GIT_BRANCH: &str = &"ConstructorFixes"; +pub static ELLIE_VM_VERSION: &str = &"0.6.5"; +pub static ELLIE_BUILD_DATE: &str = &"2024-07-04"; +pub static ELLIE_BUILD_GIT_HASH: &str = &"543c461"; +pub static ELLIE_BUILD_GIT_BRANCH: &str = &"dev"; diff --git a/ellie_engine/tokenizer/Cargo.toml b/ellie_engine/tokenizer/Cargo.toml index 446db5e8..e098b6a0 100644 --- a/ellie_engine/tokenizer/Cargo.toml +++ b/ellie_engine/tokenizer/Cargo.toml @@ -9,7 +9,7 @@ repository = "https://github.com/behemehal/Ellie-Language" homepage = "https://www.ellie-lang.org" [dependencies] -ellie_core = { path = "../core", version = "0.7.2", features = ["compiler_utils"] } +ellie_core = { path = "../core", version = "0.7.3", features = ["compiler_utils"] } enum-as-inner = "0.6.0" serde = { version = "1.0", features = ["derive"] } serde_json = { version = "1.0", default-features = false, features = ["alloc"] } diff --git a/ellie_engine/vm/Cargo.toml b/ellie_engine/vm/Cargo.toml index 736513d0..6d332696 100644 --- a/ellie_engine/vm/Cargo.toml +++ b/ellie_engine/vm/Cargo.toml @@ -9,7 +9,7 @@ repository = "https://github.com/behemehal/Ellie-Language" homepage = "https://www.ellie-lang.org" [dependencies] -ellie_core = { path = "../core", version = "0.7.2", default-features = false } +ellie_core = { path = "../core", version = "0.7.3", default-features = false } mimalloc = { version="0.1.34", optional = true } [features] From 97c7a1c0617b0b48f4fe4e9a6b6d7978cb2198f5 Mon Sep 17 00:00:00 2001 From: Ahmetcan Aksu Date: Sat, 6 Jul 2024 17:06:14 +0300 Subject: [PATCH 23/30] Update versions --- ellie_engine/Cargo.toml | 2 +- ellie_engine/fmt/Cargo.toml | 2 +- ellie_engine/src/byteCode.rs | 53 ++++++++++++++++++++++++++++++++++++ 3 files changed, 55 insertions(+), 2 deletions(-) create mode 100644 ellie_engine/src/byteCode.rs diff --git a/ellie_engine/Cargo.toml b/ellie_engine/Cargo.toml index 52bc0d10..d7212657 100644 --- a/ellie_engine/Cargo.toml +++ b/ellie_engine/Cargo.toml @@ -21,7 +21,7 @@ ellie_tokenizer = { path = "tokenizer", version = "0.7.3", default-features = fa ellie_parser = { path = "parser", version = "0.8.3", default-features = false, optional = true } ellie_bytecode = { path = "bytecode", version = "0.5.4", optional = true } ellie_vm = { path = "vm", version = "0.6.5", optional = true } -ellie_fmt = { path = "fmt", version = "0.5.2", optional = true } +ellie_fmt = { path = "fmt", version = "0.5.3", optional = true } ellie_renderer_utils = { path = "renderer_utils", version = "0.3.0", optional = true, default-features = false } [features] diff --git a/ellie_engine/fmt/Cargo.toml b/ellie_engine/fmt/Cargo.toml index 6a5a9d07..4e97ceae 100644 --- a/ellie_engine/fmt/Cargo.toml +++ b/ellie_engine/fmt/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "ellie_fmt" description = "Formatter for ellie" -version = "0.5.2" +version = "0.5.3" authors = ["Ahmetcan Aksu ", "Behemehal "] edition = "2021" license = "GPL-2.0" diff --git a/ellie_engine/src/byteCode.rs b/ellie_engine/src/byteCode.rs new file mode 100644 index 00000000..2d9fe48d --- /dev/null +++ b/ellie_engine/src/byteCode.rs @@ -0,0 +1,53 @@ +use alloc::vec::Vec; +use ellie_bytecode::assembler::{self, AssembleResult, PlatformAttributes}; +use ellie_core::defs::ModuleMap; +use ellie_parser::utils::Module; + +/// Transpile parsed code +/// ## Parameters +/// * `module` - Module to transpile [`Module`] +/// * `platform_attributes` - Platform attributes [`PlatformAttributes`] +/// * * `module_maps` - Module maps [`Vec`] +/// ## Returns +/// [`AssembleResult`] of transpiled code +pub fn transpile_parsed_code( + module: Module, + platform_attributes: PlatformAttributes, + module_maps: Vec, +) -> AssembleResult { + let mut assembler = assembler::Assembler::new(module, platform_attributes); + assembler.assemble(module_maps) +} + +/// Transpile given text macro +/// ## Parameters +/// * `text` - Text to transpile [`&str`] +/// * `platform_attributes` - Platform attributes [`PlatformAttributes`] +/// * * `module_maps` - Module maps [`Vec`] +/// ## Returns +/// [`AssembleResult`] of transpiled code +/// ## Example +/// ```rust +/// use ellie_engine::byteCode; +/// let text = r#"\ +/// fn main() { +/// print("Hello, World!"); +/// } +/// "#; +/// let result = byteCode::transpileText!(text, PlatformAttributes::default(), vec![]); +/// ``` +#[macro_export] +macro_rules! transpileText { + ($text:expr, $platform_attributes:expr, $module_maps:expr) => {{ + use ellie_engine::{ + ellie_bytecode::assembler, + ellie_core::defs::{ModuleMap}, + ellie_parser::utils::Module, + }; + + let text = $text; + let module = ellie_parser::parseText!(text); + let result = ellie_engine::byteCode::transpile_parsed_code(module, $platform_attributes, $module_maps); + result + }}; +} \ No newline at end of file From abb73d0866072e1eb37e56be1b1c49bb882ccfdf Mon Sep 17 00:00:00 2001 From: Ahmetcan Aksu Date: Mon, 9 Sep 2024 00:40:10 +0300 Subject: [PATCH 24/30] Add test _openFile function --- ellievm/src/main.rs | 70 ++++++++++++++++++++++----------------------- 1 file changed, 35 insertions(+), 35 deletions(-) diff --git a/ellievm/src/main.rs b/ellievm/src/main.rs index 92db2237..4a77386b 100644 --- a/ellievm/src/main.rs +++ b/ellievm/src/main.rs @@ -183,42 +183,44 @@ fn main() { "Signature mismatch expected 1 argument(s)".to_string(), ); } - match &args[0] { - VmNativeCallParameters::Static(_e) => VmNativeAnswer::RuntimeError( - "Signature mismatch, expected 'dynamic' argument".to_string(), - ), + + let path = match &args[0] { + VmNativeCallParameters::Static(_e) => { + return VmNativeAnswer::RuntimeError( + "Signature mismatch, expected 'dynamic' argument".to_string(), + ) + } VmNativeCallParameters::Dynamic(dynamic_value) => { if dynamic_value.is_string() { - let file_handle = match File::open(dynamic_value.to_string()) { - Ok(e) => { - println!("Opened file: {:?}", e); - let handle = Box::new(e); - let handle = Box::into_raw(handle); - - handle as *mut usize - } - Err(e) => { - return VmNativeAnswer::RuntimeError(format!( - "Failed to open file '{}', ({})", - dynamic_value.to_string(), - e.to_string() - )); - } - }; - - //convert handle back to file - let file_handle = file_handle as *mut File; - - VmNativeAnswer::Ok(VmNativeCallParameters::Static( - StaticRawType::from_uint(file_handle as usize), - )) + dynamic_value.to_string() } else { - VmNativeAnswer::RuntimeError( + return VmNativeAnswer::RuntimeError( "Signature mismatch expected 'string' argument".to_string(), - ) + ); } } - } + }; + + let file_handle = match File::open(&path) { + Ok(e) => { + println!("Opened file: {:?}", e); + let handle = Box::new(e); + let handle = Box::into_raw(handle); + + handle as *mut usize + } + Err(e) => { + return VmNativeAnswer::RuntimeError(format!( + "Failed to open file '{}', ({})", + path, + e.to_string() + )); + } + }; + + VmNativeAnswer::Ok(VmNativeCallParameters::Static(StaticRawType::from_uint( + file_handle as usize, + ))) }), ))); @@ -252,11 +254,9 @@ fn main() { ) } } - VmNativeCallParameters::Dynamic(_) => { - VmNativeAnswer::RuntimeError( - "Signature mismatch expected static argument".to_string(), - ) - } + VmNativeCallParameters::Dynamic(_) => VmNativeAnswer::RuntimeError( + "Signature mismatch expected static argument".to_string(), + ), } }), ))); From 7554c854761b1b3c646e6b439e47f544baf0ef6a Mon Sep 17 00:00:00 2001 From: Ahmetcan Aksu Date: Sun, 1 Dec 2024 00:56:50 +0300 Subject: [PATCH 25/30] Fix constructor variable linking issue --- .vscode/extensions.json | 2 +- ellie_engine/Cargo.toml | 6 +- ellie_engine/core/Cargo.toml | 2 +- ellie_engine/core/src/utils/mod.rs | 50 +- .../parser/src/deep_search_extensions.rs | 465 +++++++++++++++++- .../src/processors/items/constructor.rs | 4 + .../src/processors/items/setter_call.rs | 28 +- .../parser/src/processors/items/variable.rs | 181 ++++--- .../parser/src/processors/types/operator.rs | 8 +- ellie_engine/renderer_utils/Cargo.toml | 1 + ellie_engine/renderer_utils/src/utils.rs | 188 +++++-- .../tokenizer/src/syntax/items/setter_call.rs | 1 + 12 files changed, 766 insertions(+), 170 deletions(-) diff --git a/.vscode/extensions.json b/.vscode/extensions.json index edc2da86..7a8cb2f9 100644 --- a/.vscode/extensions.json +++ b/.vscode/extensions.json @@ -7,7 +7,7 @@ "dtsvet.vscode-wasm", "vadimcn.vscode-lldb", "spmeesseman.vscode-taskexplorer", - "serayuzgur.crates", + "fill-labs.dependi", "denoland.vscode-deno", "rioj7.command-variable", ], diff --git a/ellie_engine/Cargo.toml b/ellie_engine/Cargo.toml index d7212657..8b7dd884 100644 --- a/ellie_engine/Cargo.toml +++ b/ellie_engine/Cargo.toml @@ -37,8 +37,8 @@ cli-utils = ["ellie_renderer_utils/cli-utils"] [build-dependencies] path-absolutize = { version = "3.0.10" } -toml = "0.8.0" -regex = { version = "1.1.7" } +toml = "0.8.19" +regex = { version = "1.10.6" } chrono = "0.4.22" [dev-dependencies] @@ -49,5 +49,5 @@ name = "compile" harness = false [workspace] -members = [".", "./core", "./tokenizer", "./parser", "./bytecode", "./vm", "./fmt", "./renderer_utils" ] +members = [".", "./core", "./tokenizer", "./parser", "./bytecode", "./vm", "./fmt", "./renderer_utils"] default-members = ["."] diff --git a/ellie_engine/core/Cargo.toml b/ellie_engine/core/Cargo.toml index 523b8eb5..14beb12f 100644 --- a/ellie_engine/core/Cargo.toml +++ b/ellie_engine/core/Cargo.toml @@ -17,7 +17,7 @@ serde = { version = "1.0", features = ["derive"], default-features = false, opti serde_json = { version = "1.0", default-features = false, features = ["alloc"], optional = true } enum-as-inner = "0.6.0" rand = { version = "0.8.4", optional = true } -regex = { version = "1.9.1", default-features = false, features = ["unicode-perl"], optional = true } +regex = { version = "1.10.6", default-features = false, features = ["unicode-perl"], optional = true } [features] default = ["std"] diff --git a/ellie_engine/core/src/utils/mod.rs b/ellie_engine/core/src/utils/mod.rs index bf1d3a0a..1b1f014b 100644 --- a/ellie_engine/core/src/utils/mod.rs +++ b/ellie_engine/core/src/utils/mod.rs @@ -10,9 +10,12 @@ use rand; use serde::{Deserialize, Serialize}; use crate::{ - definite::types::operator::{ - assignment_operator_to_string, comparison_operator_to_string, logical_operator_to_string, - ArithmeticOperators, AssignmentOperators, Operators, + definite::{ + definers::DefinerCollecting, + types::operator::{ + assignment_operator_to_string, comparison_operator_to_string, + logical_operator_to_string, ArithmeticOperators, AssignmentOperators, Operators, + }, }, defs, error, }; @@ -345,13 +348,17 @@ pub fn operator_priority(operator: &str) -> usize { pub fn operator_control( operator: Operators, - first: String, - second: String, + definer_first: DefinerCollecting, + definer_second: DefinerCollecting, path: String, pos: defs::Cursor, ) -> Option { + let first = definer_first.to_string(); + let second = definer_second.to_string(); + let first = first.as_str(); let second = second.as_str(); + let operator = match operator { Operators::ComparisonType(operator) => match operator { crate::definite::types::operator::ComparisonOperators::Equal @@ -430,7 +437,30 @@ pub fn operator_control( crate::definite::types::operator::ArithmeticOperators::Null => unreachable!(), }, Operators::AssignmentType(operator) => match operator { - crate::definite::types::operator::AssignmentOperators::Assignment => None, + crate::definite::types::operator::AssignmentOperators::Assignment => { + match (first, second) { + ("int", "int") + | ("float", "float") + | ("float", "double") + | ("float", "int") + | ("float", "byte") + | ("double", "double") + | ("double", "float") + | ("double", "int") + | ("double", "byte") + | ("byte", "byte") + | ("byte", "int") + | ("string", "string") + | ("string", "char") + | ("string", "int") + | ("string", "float") + | ("string", "double") + | ("dyn", _) + | (_, "dyn") + | ("string", "byte") => None, + _ => Some("Assignment"), + } + } crate::definite::types::operator::AssignmentOperators::AdditionAssignment => { match (first, second) { ("int", "int") @@ -475,7 +505,8 @@ pub fn operator_control( }, Operators::Null => unreachable!(), }; - operator.map(|operator_string| error::error_list::ERROR_S52.clone().build_with_path( + operator.map(|operator_string| { + error::error_list::ERROR_S52.clone().build_with_path( vec![ error::ErrorBuildField { key: "opType".to_owned(), @@ -493,7 +524,8 @@ pub fn operator_control( alloc::format!("{}:{}:{}", file!().to_owned(), line!(), column!()), path, pos, - )) + ) + }) } pub fn is_operators_chainable(target: Operators, current: Operators) -> bool { @@ -593,7 +625,7 @@ pub trait ExportPage { impl Default for PageExport where T: ExportPage + core::fmt::Debug, - { +{ fn default() -> Self { Self::new() } diff --git a/ellie_engine/parser/src/deep_search_extensions.rs b/ellie_engine/parser/src/deep_search_extensions.rs index ab345cd1..c3302f03 100644 --- a/ellie_engine/parser/src/deep_search_extensions.rs +++ b/ellie_engine/parser/src/deep_search_extensions.rs @@ -1,4 +1,5 @@ use crate::{ + extra::{item_search::item_search, utils::DeepSearchOptions}, parser::{DeepSearchItems, Parser}, processors::{ definer::{DefinerParserProcessor, DefinerParserProcessorOptions}, @@ -84,9 +85,7 @@ pub fn generate_type_from_defining( ); if hash_deep_search.found { match hash_deep_search.found_item { - crate::deep_search_extensions::ProcessedDeepSearchItems::Class( - matched_class, - ) => { + ProcessedDeepSearchItems::Class(matched_class) => { if matched_class.generic_definings.is_empty() { Some(Types::ClassCall( ellie_core::definite::types::class_call::ClassCall { @@ -136,9 +135,7 @@ pub fn generate_type_from_defining( )) } } - crate::deep_search_extensions::ProcessedDeepSearchItems::GenericItem(_) => { - Some(Types::Dynamic) - } + ProcessedDeepSearchItems::GenericItem(_) => Some(Types::Dynamic), _ => unreachable!(), } } else { @@ -216,7 +213,7 @@ pub fn generate_type_from_defining( ); if hash_deep_search.found { match hash_deep_search.found_item { - crate::deep_search_extensions::ProcessedDeepSearchItems::Class(matched_class) => { + ProcessedDeepSearchItems::Class(matched_class) => { Some( Types::ClassCall( ellie_core::definite::types::class_call::ClassCall { @@ -299,6 +296,451 @@ pub fn generate_type_from_defining( }, )), definers::DefinerCollecting::Dynamic => Some(Types::Dynamic), + definers::DefinerCollecting::Nullable(inner) => { + let nullable_class = item_search( + &mut DeepSearchOptions::new() + .name("nullAble".to_string()) + .parser(parser) + .page_id(page_id), + ); + + if nullable_class.found() { + match nullable_class.found_item.as_processed() { + Collecting::Class(class) => Some(Types::ClassCall( + ellie_core::definite::types::class_call::ClassCall { + target: Box::new(Types::VariableType( + ellie_core::definite::types::variable::VariableType { + value: class.name.clone(), + reference: class.hash, + pos: class.pos, + }, + )), + resolved_generics: vec![*inner.value.clone()], + generic_parameters: vec![ClassCallGenericParameter { + value: *inner.value, + pos: defs::Cursor::default(), + }], + keyword_pos: defs::Cursor::default(), + pos: defs::Cursor::default(), + target_pos: defs::Cursor::default(), + params: vec![], + }, + )), + _ => None, + } + } else { + None + } + } + _ => unreachable!(), + } +} + +pub fn generate_type_from_defining_v2( + rtype: ellie_core::definite::definers::DefinerCollecting, + page_id: usize, + parser: &mut crate::parser::Parser, +) -> Result> { + match rtype { + definers::DefinerCollecting::Generic(generic) => { + if generic.rtype == "int" { + Ok(Types::Integer( + ellie_core::definite::types::integer::IntegerType { + value: 0, + pos: defs::Cursor::default(), + }, + )) + } else if generic.rtype == "float" { + Ok(Types::Decimal( + ellie_core::definite::types::decimal::DecimalType { + value: ellie_core::definite::types::decimal::DecimalTypeEnum::Float(0.0), + pos: defs::Cursor::default(), + is_double: false, + }, + )) + } else if generic.rtype == "string" { + Ok(Types::String( + ellie_core::definite::types::string::StringType { + value: "".to_owned(), + pos: defs::Cursor::default(), + }, + )) + } else if generic.rtype == "bool" { + Ok(Types::Bool(ellie_core::definite::types::bool::BoolType { + value: true, + })) + } else if generic.rtype == "dyn" { + Ok(Types::Dynamic) + } else if generic.rtype == "void" { + Ok(Types::Void) + } else if generic.rtype == "char" { + Ok(Types::Char( + ellie_core::definite::types::ellie_char::CharType { value: '\0' }, + )) + } else if generic.rtype == "null" { + Ok(Types::Null) + } else { + let hash_deep_search = crate::deep_search_extensions::deep_search_hash( + parser, + page_id, + generic.hash, + vec![], + 0, + ); + if hash_deep_search.found { + match hash_deep_search.found_item { + ProcessedDeepSearchItems::Class(matched_class) => { + if matched_class.generic_definings.is_empty() { + Ok(Types::ClassCall( + ellie_core::definite::types::class_call::ClassCall { + target: Box::new(Types::VariableType( + ellie_core::definite::types::variable::VariableType { + value: matched_class.name.clone(), + reference: matched_class.hash, + pos: defs::Cursor::default(), + }, + )), + resolved_generics: vec![], + generic_parameters: vec![], + keyword_pos: defs::Cursor::default(), + pos: defs::Cursor::default(), + target_pos: defs::Cursor::default(), + params: vec![], + }, + )) + } else { + Ok(Types::ClassCall( + ellie_core::definite::types::class_call::ClassCall { + target: Box::new(Types::VariableType( + ellie_core::definite::types::variable::VariableType { + value: matched_class.name.clone(), + reference: matched_class.hash, + pos: defs::Cursor::default(), + }, + )), + resolved_generics: vec![], + generic_parameters: matched_class + .generic_definings + .iter() + .map(|gd| ClassCallGenericParameter { + value: DefinerCollecting::Generic(GenericType { + rtype: gd.name.clone(), + pos: gd.pos, + hash: gd.hash, + }), + pos: gd.pos, + }) + .collect(), + keyword_pos: defs::Cursor::default(), + pos: defs::Cursor::default(), + target_pos: defs::Cursor::default(), + params: vec![], + }, + )) + } + } + ProcessedDeepSearchItems::GenericItem(_) => Ok(Types::Dynamic), + _ => unreachable!(), + } + } else { + unreachable!() + } + } + } + definers::DefinerCollecting::ParentGeneric(parent_generic) => { + if parent_generic.rtype == "array" { + generate_type_from_defining_v2( + parent_generic.generics[0].value.clone(), + page_id, + parser, + ) + .map(|t| { + Types::Array(ellie_core::definite::types::array::ArrayType { + collective: vec![ellie_core::definite::types::array::ArrayEntry { + value: t, + location: defs::Cursor::default(), + }], + pos: defs::Cursor::default(), + }) + }) + } else if parent_generic.rtype == "cloak" { + let mut cloak_entries = vec![]; + let mut errors = Vec::new(); + for generic in parent_generic.generics { + match generate_type_from_defining_v2(generic.value, page_id, parser) { + Ok(t) => { + cloak_entries.push(ellie_core::definite::types::cloak::CloakEntry { + value: t, + location: defs::Cursor::default(), + }) + } + Err(errs) => { + errors.extend(errs); + break; + } + } + } + if !errors.is_empty() { + Err(errors) + } else { + Ok(Types::Cloak( + ellie_core::definite::types::cloak::CloakType { + collective: cloak_entries, + pos: defs::Cursor::default(), + }, + )) + } + } else if parent_generic.rtype == "collective" { + generate_type_from_defining_v2( + parent_generic.generics[0].value.clone(), + page_id, + parser, + ) + .map(|t| { + Types::Collective(ellie_core::definite::types::collective::CollectiveType { + entries: vec![ellie_core::definite::types::collective::CollectiveEntry { + key: "?".to_string(), + value: t, + key_pos: defs::Cursor::default(), + value_pos: defs::Cursor::default(), + }], + pos: defs::Cursor::default(), + }) + }) + } else { + let hash_deep_search = crate::deep_search_extensions::deep_search_hash( + parser, + page_id, + parent_generic.hash, + vec![], + 0, + ); + if hash_deep_search.found { + match hash_deep_search.found_item { + ProcessedDeepSearchItems::Class(matched_class) => { + Ok( + Types::ClassCall( + ellie_core::definite::types::class_call::ClassCall { + target: Box::new(Types::VariableType( + ellie_core::definite::types::variable::VariableType { + value: matched_class.name.clone(), + reference: matched_class.hash, + pos: defs::Cursor::default(), + }, + )), + resolved_generics: parent_generic.generics.iter().map(|generic| { + generic.value.clone() + }).collect::>(), + generic_parameters: parent_generic.generics.iter().map(|generic| { + ellie_core::definite::types::class_call::ClassCallGenericParameter { + value: generic.value.clone(), + pos: defs::Cursor::default(), + } + }).collect::>(), + keyword_pos: defs::Cursor::default(), + pos: defs::Cursor::default(), + target_pos: defs::Cursor::default(), + params: vec![], + } + ) + ) + } + _ => unreachable!(), + } + } else { + unreachable!() + } + } + } + definers::DefinerCollecting::Function(function) => Ok(Types::Function( + ellie_core::definite::types::function::Function { + native: false, + parameters: function + .params + .iter() + .map( + |parameter| ellie_core::definite::types::function::FunctionParameter { + name: "anonymous".to_string(), + rtype: Some(parameter.clone()), + rtype_pos: defs::Cursor::default(), + name_pos: defs::Cursor::default(), + }, + ) + .collect::>(), + return_type: *function.returning, + has_parameter_definings: false, + arrow_function: false, + inside_code: vec![], + return_pos: defs::Cursor::default(), + }, + )), + definers::DefinerCollecting::EnumField(enum_data) => Ok(Types::EnumData( + ellie_core::definite::types::enum_data::EnumData { + reference: Box::new(Types::VariableType( + ellie_core::definite::types::variable::VariableType { + value: enum_data.name.clone(), + reference: enum_data.hash, + pos: defs::Cursor::default(), + }, + )), + field_name: enum_data.field_name, + reference_pos: defs::Cursor::default(), + brace_pos: defs::Cursor::default(), + value: match enum_data.field_data { + definers::EnumFieldData::NoData => { + ellie_core::definite::types::enum_data::Pointer::NoData + } + definers::EnumFieldData::Data(e) => { + ellie_core::definite::types::enum_data::Pointer::Data(Box::new( + generate_type_from_defining(*e, page_id, parser).unwrap(), + )) + } + }, + pos: defs::Cursor::default(), + }, + )), + definers::DefinerCollecting::Dynamic => Ok(Types::Dynamic), + definers::DefinerCollecting::Nullable(inner) => { + let nullable_class = item_search( + &mut DeepSearchOptions::new() + .name("nullAble".to_string()) + .parser(parser) + .page_id(page_id) + .search_on_all(), + ); + + if nullable_class.found() { + match nullable_class.found_item.processed() { + Some(processed) => match processed { + Collecting::Class(class) => { + return Ok(Types::ClassCall( + ellie_core::definite::types::class_call::ClassCall { + target: Box::new(Types::VariableType( + ellie_core::definite::types::variable::VariableType { + value: class.name.clone(), + reference: class.hash, + pos: class.pos, + }, + )), + resolved_generics: vec![*inner.value.clone()], + generic_parameters: vec![ClassCallGenericParameter { + value: *inner.value, + pos: defs::Cursor::default(), + }], + keyword_pos: defs::Cursor::default(), + pos: defs::Cursor::default(), + target_pos: defs::Cursor::default(), + params: vec![], + }, + )) + } + _ => { + let mut errors = Vec::new(); + errors.push(error::error_list::ERROR_S21.clone().build_with_path( + vec![error::ErrorBuildField { + key: "token".to_owned(), + value: "nullAble".to_owned(), + }], + alloc::format!("{}:{}:{}", file!().to_owned(), line!(), column!()), + parser.find_page(page_id).unwrap().path.clone(), + defs::Cursor::default(), + )); + return Err(errors); + } + }, + None => (), + } + + match nullable_class.found_item.raw() { + Some(raw) => match raw { + Processors::Class(class) => { + return Ok(Types::ClassCall( + ellie_core::definite::types::class_call::ClassCall { + target: Box::new(Types::VariableType( + ellie_core::definite::types::variable::VariableType { + value: class.name.clone(), + reference: class.hash, + pos: class.pos, + }, + )), + resolved_generics: vec![*inner.value.clone()], + generic_parameters: vec![ClassCallGenericParameter { + value: *inner.value, + pos: defs::Cursor::default(), + }], + keyword_pos: defs::Cursor::default(), + pos: defs::Cursor::default(), + target_pos: defs::Cursor::default(), + params: vec![], + }, + )) + } + _ => { + let mut errors = Vec::new(); + errors.push(error::error_list::ERROR_S21.clone().build_with_path( + vec![error::ErrorBuildField { + key: "token".to_owned(), + value: "nullAble".to_owned(), + }], + alloc::format!("{}:{}:{}", file!().to_owned(), line!(), column!()), + parser.find_page(page_id).unwrap().path.clone(), + defs::Cursor::default(), + )); + return Err(errors); + } + }, + None => (), + } + + match nullable_class.found_item.as_processed() { + Collecting::Class(class) => Ok(Types::ClassCall( + ellie_core::definite::types::class_call::ClassCall { + target: Box::new(Types::VariableType( + ellie_core::definite::types::variable::VariableType { + value: class.name.clone(), + reference: class.hash, + pos: class.pos, + }, + )), + resolved_generics: vec![*inner.value.clone()], + generic_parameters: vec![ClassCallGenericParameter { + value: *inner.value, + pos: defs::Cursor::default(), + }], + keyword_pos: defs::Cursor::default(), + pos: defs::Cursor::default(), + target_pos: defs::Cursor::default(), + params: vec![], + }, + )), + _ => { + let mut errors = Vec::new(); + errors.push(error::error_list::ERROR_S21.clone().build_with_path( + vec![error::ErrorBuildField { + key: "token".to_owned(), + value: "nullAble".to_owned(), + }], + alloc::format!("{}:{}:{}", file!().to_owned(), line!(), column!()), + parser.find_page(page_id).unwrap().path.clone(), + defs::Cursor::default(), + )); + Err(errors) + } + } + } else { + let mut errors = Vec::new(); + errors.push(error::error_list::ERROR_S38.clone().build_with_path( + vec![error::ErrorBuildField { + key: "token".to_owned(), + value: "nullAble".to_owned(), + }], + alloc::format!("{}:{}:{}", file!().to_owned(), line!(), column!()), + parser.find_page(page_id).unwrap().path.clone(), + defs::Cursor::default(), + )); + Err(errors) + } + } _ => unreachable!(), } } @@ -1276,8 +1718,8 @@ fn iterate_deep_type( } } ProcessedDeepSearchItems::ConstructorParameter(e) => { - match generate_type_from_defining(e.rtype, page_id, parser) { - Some(e) => match e { + match generate_type_from_defining_v2(e.rtype, page_id, parser) { + Ok(e) => match e { Types::Byte(e) => DeepTypeResult::Byte(e), Types::Integer(e) => DeepTypeResult::Integer(e), Types::Decimal(e) => DeepTypeResult::Decimal(e), @@ -1297,7 +1739,10 @@ fn iterate_deep_type( Types::Dynamic => DeepTypeResult::Dynamic, _ => unreachable!(), }, - None => panic!("This should never happen"), + Err(errs) => { + errors.extend(errs); + DeepTypeResult::NotFound + } } } ProcessedDeepSearchItems::Getter(e) => { diff --git a/ellie_engine/parser/src/processors/items/constructor.rs b/ellie_engine/parser/src/processors/items/constructor.rs index fa1cb786..35340c07 100644 --- a/ellie_engine/parser/src/processors/items/constructor.rs +++ b/ellie_engine/parser/src/processors/items/constructor.rs @@ -222,6 +222,9 @@ impl super::ItemParserProcessor for Constructor { }, operator: AssignmentOperators::Assignment, hash: generate_hash_usize(), + virtual_element: true, + value_pos: self.pos, + target_pos: self.pos, ..Default::default() }); items.push(self_setter); @@ -249,6 +252,7 @@ impl super::ItemParserProcessor for Constructor { ), ); } + items.extend(self.inside_code.clone()); let inner_page_id: usize = ellie_core::utils::generate_hash_usize(); let inner = ellie_tokenizer::tokenizer::Page { diff --git a/ellie_engine/parser/src/processors/items/setter_call.rs b/ellie_engine/parser/src/processors/items/setter_call.rs index 9100f5f6..ac79fc92 100644 --- a/ellie_engine/parser/src/processors/items/setter_call.rs +++ b/ellie_engine/parser/src/processors/items/setter_call.rs @@ -63,13 +63,10 @@ impl super::ItemParserProcessor for SetterCall { } }; - let first = target_type.to_string(); - let second = value_defining.to_string(); - match ellie_core::utils::operator_control( Operators::AssignmentType(self.operator.clone()).to_definite(), - first, - second, + target_type, + value_defining, current_page.path, self.value_pos, ) { @@ -153,13 +150,10 @@ impl super::ItemParserProcessor for SetterCall { } }; - let first = target_type.to_string(); - let second = value_defining.to_string(); - match ellie_core::utils::operator_control( Operators::AssignmentType(self.operator.clone()).to_definite(), - first, - second, + target_type, + value_defining, current_page.path.clone(), self.value_pos, ) { @@ -274,14 +268,11 @@ impl super::ItemParserProcessor for SetterCall { } }; - let first = target_type.to_string(); - let second = value_defining.to_string(); - match ellie_core::utils::operator_control( Operators::AssignmentType(self.operator.clone()) .to_definite(), - first, - second, + target_type, + value_defining, current_page.path.clone(), self.value_pos, ) { @@ -368,13 +359,10 @@ impl super::ItemParserProcessor for SetterCall { } }; - let first = target_type.to_string(); - let second = value_defining.to_string(); - match ellie_core::utils::operator_control( Operators::AssignmentType(self.operator.clone()).to_definite(), - first, - second, + target_type, + value_defining, current_page.path, self.value_pos, ) { diff --git a/ellie_engine/parser/src/processors/items/variable.rs b/ellie_engine/parser/src/processors/items/variable.rs index 8d3a64c9..d235e1e7 100644 --- a/ellie_engine/parser/src/processors/items/variable.rs +++ b/ellie_engine/parser/src/processors/items/variable.rs @@ -8,7 +8,10 @@ use ellie_core::{ }, defs, error, }; -use ellie_tokenizer::syntax::items::variable::VariableCollector; +use ellie_tokenizer::{ + processors::items::Processors as ItemProcessors, syntax::items::variable::VariableCollector, + tokenizer::PageType, +}; use crate::processors::{ definer::{DefinerParserProcessor, DefinerParserProcessorOptions}, @@ -165,69 +168,101 @@ impl super::ItemParserProcessor for VariableCollector { }; let resolved_type = if !self.data.has_value { - let null_able_class = crate::deep_search_extensions::find_type( - "nullAble".to_string(), - options.page_hash, - options.parser, - ); + let current_page = options.parser.pages.nth_mut(options.page_idx).unwrap(); - match null_able_class { - Some(null_able_class) => { - let nullable_parameter = if resolved_defining.is_ok() - && matches!(resolved_defining.clone().unwrap(), DefinerCollecting::ParentGeneric(parent_generic) if parent_generic.rtype == "nullAble") - { - resolved_defining - .clone() - .unwrap() - .as_parent_generic() - .unwrap() - .generics[0] - .clone() - .value + let mut belongs_to_constructor_parameter = false; + if let PageType::ClassBody(_) = current_page.page_type.clone() { + let constructor = current_page.items.iter().find_map(|item| { + if let ItemProcessors::Constructor(constructor) = item { + Some(constructor) } else { - resolved_defining.clone().unwrap() - }; + None + } + }); - Ok(Types::ClassCall( - ellie_core::definite::types::class_call::ClassCall { - target: Box::new(Types::VariableType( - ellie_core::definite::types::variable::VariableType { - value: null_able_class.rtype.clone(), - reference: null_able_class.hash, - pos: defs::Cursor::default(), - }, - )), - resolved_generics: vec![], - generic_parameters: vec![class_call::ClassCallGenericParameter { - value: nullable_parameter, - pos: defs::Cursor::default(), - }], - keyword_pos: defs::Cursor::default(), - pos: defs::Cursor::default(), - target_pos: defs::Cursor::default(), - params: vec![], - }, - )) + if let Some(constructor) = constructor { + belongs_to_constructor_parameter = constructor + .parameters + .iter() + .any(|p| p.name == self.data.name); } - None => { - options.parser.informations.push( - &error::error_list::ERROR_S38.clone().build_with_path( - vec![error::ErrorBuildField { - key: "token".to_owned(), - value: "nullAble".to_string(), - }], - alloc::format!("{}:{}:{}", file!().to_owned(), line!(), column!()), - options - .parser - .processed_pages - .nth_mut(options.processed_page_idx) + } + + //If the variable is a constructor parameter, it should be dynamic to not get caught by the type check, we're sure that it will be assigned in the constructor + if belongs_to_constructor_parameter { + Ok(Types::Dynamic) + } else { + let null_able_class = crate::deep_search_extensions::find_type( + "nullAble".to_string(), + options.page_hash, + options.parser, + ); + + match null_able_class { + Some(null_able_class) => { + let nullable_parameter = if resolved_defining.is_ok() + && matches!(resolved_defining.clone().unwrap(), DefinerCollecting::ParentGeneric(parent_generic) if parent_generic.rtype == "nullAble") + { + resolved_defining + .clone() .unwrap() - .path - .clone(), - self.data.pos, - ), - ); - return false; + .as_parent_generic() + .unwrap() + .generics[0] + .clone() + .value + } else { + resolved_defining.clone().unwrap() + }; + + Ok(Types::ClassCall( + ellie_core::definite::types::class_call::ClassCall { + target: Box::new(Types::VariableType( + ellie_core::definite::types::variable::VariableType { + value: null_able_class.rtype.clone(), + reference: null_able_class.hash, + pos: defs::Cursor::default(), + }, + )), + resolved_generics: vec![], + generic_parameters: vec![ + class_call::ClassCallGenericParameter { + value: nullable_parameter, + pos: defs::Cursor::default(), + }, + ], + keyword_pos: defs::Cursor::default(), + pos: defs::Cursor::default(), + target_pos: defs::Cursor::default(), + params: vec![], + }, + )) + } + None => { + options.parser.informations.push( + &error::error_list::ERROR_S38.clone().build_with_path( + vec![error::ErrorBuildField { + key: "token".to_owned(), + value: "nullAble".to_string(), + }], + alloc::format!( + "{}:{}:{}", + file!().to_owned(), + line!(), + column!() + ), + options + .parser + .processed_pages + .nth_mut(options.processed_page_idx) + .unwrap() + .path + .clone(), + self.data.pos, + ), + ); + return false; + } } } } else { @@ -320,21 +355,21 @@ impl super::ItemParserProcessor for VariableCollector { Ok(result) => { if result.requires_cast { options.parser.informations.push( - &error::error_list::ERROR_S41.clone().build_with_path( - vec![error::ErrorBuildField { - key: "token".to_owned(), - value: "Type helpers are not completely implemented yet. Next error is result of this. Follow progress here (https://github.com/behemehal/EllieWorks/issues/8)".to_owned(), - }], - alloc::format!( - "{}:{}:{}", - file!().to_owned(), - line!(), - column!() + &error::error_list::ERROR_S41.clone().build_with_path( + vec![error::ErrorBuildField { + key: "token".to_owned(), + value: "Type helpers are not completely implemented yet. Next error is result of this. Follow progress here (https://github.com/behemehal/EllieWorks/issues/8)".to_owned(), + }], + alloc::format!( + "{}:{}:{}", + file!().to_owned(), + line!(), + column!() + ), + current_page.path.clone(), + self.data.value_pos, ), - current_page.path.clone(), - self.data.value_pos, - ), - ); + ); let mut err = error::error_list::ERROR_S3.clone().build_with_path( vec![ error::ErrorBuildField { diff --git a/ellie_engine/parser/src/processors/types/operator.rs b/ellie_engine/parser/src/processors/types/operator.rs index 98cbe12a..02d08a09 100644 --- a/ellie_engine/parser/src/processors/types/operator.rs +++ b/ellie_engine/parser/src/processors/types/operator.rs @@ -53,6 +53,7 @@ impl super::TypeParserProcessor for operator_type::OperatorTypeCollector { Some(e) => e, None => return Err(errors), }; + let _second_value = match resolve_type( processed_second_value.clone().unwrap(), options.page_id, @@ -64,9 +65,6 @@ impl super::TypeParserProcessor for operator_type::OperatorTypeCollector { None => return Err(errors), }; - let first = _first_value.to_string(); - let second = _second_value.to_string(); - if let Operators::AssignmentType(_) = self.data.operator { if !self.data.first.is_assignable() { return Err(vec![error::error_list::ERROR_S43.clone().build_with_path( @@ -87,8 +85,8 @@ impl super::TypeParserProcessor for operator_type::OperatorTypeCollector { match ellie_core::utils::operator_control( self.data.operator.clone().to_definite(), - first, - second, + _first_value, + _second_value, options.parser.find_page(page_id).unwrap().path.clone(), self.data.pos, ) { diff --git a/ellie_engine/renderer_utils/Cargo.toml b/ellie_engine/renderer_utils/Cargo.toml index ba7cdd63..b9cdb866 100644 --- a/ellie_engine/renderer_utils/Cargo.toml +++ b/ellie_engine/renderer_utils/Cargo.toml @@ -19,6 +19,7 @@ ellie_core = { path = "../core", version = "0.7.3" } serde = { version = "1.0", features = ["derive"], optional = true } serde_json = { version = "1.0", default-features = false, optional = true } path-absolutize = { version = "3.0.10", optional = true } +regex = { version = "1.10.6" } [features] default = ["cli-utils", "std"] diff --git a/ellie_engine/renderer_utils/src/utils.rs b/ellie_engine/renderer_utils/src/utils.rs index d152019e..b9cb49b9 100644 --- a/ellie_engine/renderer_utils/src/utils.rs +++ b/ellie_engine/renderer_utils/src/utils.rs @@ -18,6 +18,7 @@ pub enum TextStyles { Underline, } +#[derive(Copy, Clone)] pub enum Colors { Black, Red, @@ -310,47 +311,71 @@ pub fn get_line(code: String, line: usize) -> String { } } -/// Render code block with desired output type (Warning | Error) -/// ##Ā Parameters -/// * item_path: File's path to render at begining [`String`] -/// * item_pos: Position of code block to render [`defs::Cursor`] -/// * code: File content [`String`] -/// * ref_message: A message to show at referenced code block [`String`] -/// * line_space: Count of line requested to be rendered at begining -/// * reference: Is this a reference highlight? -/// * is_error: Is this a error otherwise check reference else render as warning -/// * color_output: Color decor [`ColorDisplay`] -pub(crate) fn render_code_block( +#[cfg(feature = "cli-utils")] +macro_rules! color_format { + ($fmt:expr, $color_output:expr, $( $arg:tt )*) => {{ + use regex::Regex; + // First, use the standard format! macro to inject variables into the format string + let formatted = format!($fmt, $( $arg )*); + + // Define a regex to match the color pattern + let re = Regex::new(r"%(?black|red|green|yellow|blue|magenta|cyan|white|reset)-(?.*?)%").unwrap(); + + // Map colors to ColorDisplay method calls using closures + let color_map= std::collections::HashMap::from([ + ("black", Colors::Black), + ("red", Colors::Red), + ("green", Colors::Green), + ("yellow", Colors::Yellow), + ("blue", Colors::Blue), + ("magenta", Colors::Magenta), + ("cyan", Colors::Cyan), + ("white", Colors::White), + ("reset", Colors::Reset), + ]); + + // Replace the matches in the format string with their corresponding color methods + re.replace_all(&formatted, |caps: ®ex::Captures| { + let color = caps.name("color").unwrap().as_str(); + let message = caps.name("message").unwrap().as_str(); + let color_code = color_map.get(color).unwrap_or(&Colors::Reset); + + format!("{}{}{}", $color_output.color(*color_code), message, $color_output.color(Colors::Reset)) // Add reset after the message + }).to_string() + }}; +} + +fn render_path_line( item_path: String, item_pos: defs::Cursor, - code: String, - ref_message: String, line_space: usize, reference: bool, is_error: bool, color_output: T, ) -> String { - let mut output = String::new(); - let multi_line = item_pos.range_start.0 != item_pos.range_end.0; - output += &format!( - " {}[{}]{}{}ā•ž {}{}:{}{}{}\n", + color_format!( + " %{}-[{}]{}%ā•ž %green-{}%%cyan-:{}%\n", + color_output, if reference { - color_output.color(Colors::Green) + "green" } else if is_error { - color_output.color(Colors::Red) + "red" } else { - color_output.color(Colors::Yellow) + "yellow" + }, + if reference { + "@" + } else if is_error { + "~" + } else { + "?" }, - if reference { "@" } else { "~" }, if line_space < 3 { String::new() } else { generate_blank(line_space - 3) }, - color_output.color(Colors::Reset), - color_output.color(Colors::Green), item_path, - color_output.color(Colors::Cyan), format!( "{}:{}{} > {}{}:{}", item_pos.range_start.0 + 1, @@ -360,9 +385,31 @@ pub(crate) fn render_code_block( item_pos.range_end.0 + 1, item_pos.range_end.1 + 1 ), - color_output.color(Colors::Reset), - ); + ) +} +/// Render code block with desired output type (Warning | Error) +/// ##Ā Parameters +/// * item_path: File's path to render at begining [`String`] +/// * item_pos: Position of code block to render [`defs::Cursor`] +/// * code: File content [`String`] +/// * ref_message: A message to show at referenced code block [`String`] +/// * line_space: Count of line requested to be rendered at begining +/// * reference: Is this a reference highlight? +/// * is_error: Is this a error otherwise check reference else render as warning +/// * color_output: Color decor [`ColorDisplay`] +pub(crate) fn render_code_block( + item_path: String, + item_pos: defs::Cursor, + code: String, + ref_message: String, + line_space: usize, + reference: bool, + is_error: bool, + color_output: T, +) -> String { + let mut output = String::new(); + let multi_line = item_pos.range_start.0 != item_pos.range_end.0; let line_start = if item_pos.range_start.0 >= 2 { item_pos.range_start.0 - 2 } else { @@ -572,6 +619,19 @@ pub fn read_error_text(error: u8) -> &'static str { } } +fn render_message_title(error: &error::Error, color_output: T) -> String +where + T: ColorDisplay, +{ + color_format!( + "\n%red-{title}[{code:#04x}]%: %cyan-{message}%\n", + color_output, + title = error.title, + code = error.code, + message = error.builded_message.builded, + ) +} + /// Output given error list as string /// ##Ā Parameters /// * errors: Vector of errors [`Vec`] @@ -636,29 +696,38 @@ where { let mut output = String::new(); for error in errors { - output += &format!( - "\n{}{}[{:#04x}{}]{}: {}{}{}\n", - color_output.color(Colors::Red), - error.title, - error.code, - if show_debug_lines { - format!(" - {}", error.debug_message) - } else { - "".to_string() - }, - color_output.color(Colors::Reset), - color_output.color(Colors::Cyan), - error.builded_message.builded, - color_output.color(Colors::Reset), - ); + let mut error_text = render_message_title(error, color_output); + let file_content = file_reader(error.path.clone()); let mut line_space = error.pos.range_start.0.to_string().len() + 1; + + let is_reference = error.reference_block.is_some(); + let path = file_reader(if is_reference { + error.reference_block.clone().unwrap().1.clone() + } else { + error.path.clone() + }); + let pos = if is_reference { + error.reference_block.clone().unwrap().0 + } else { + error.pos + }; + if let Some(refr) = error.reference_block.clone() { let ref_file_content = file_reader(refr.1.clone()); if line_space < refr.0.range_start.0.to_string().len() + 1 { line_space = refr.0.range_start.0.to_string().len() + 1; } - output += &render_code_block( + error_text += &render_path_line( + path_resolver(refr.1.clone()), + refr.0, + line_space, + true, + true, + color_output, + ); + + error_text += &render_code_block( path_resolver(refr.1.clone()), refr.0, ref_file_content, @@ -668,9 +737,19 @@ where true, color_output, ); - output += "\n" + error_text += "\n" } - output += &render_code_block( + + error_text += &render_path_line( + path_resolver(error.path.clone()), + error.pos, + line_space, + true, + true, + color_output, + ); + + error_text += &render_code_block( path_resolver(error.path.clone()), error.pos, file_content, @@ -680,7 +759,7 @@ where true, color_output, ); - output += &format!( + error_text += &format!( "{}{}[?]{} ā•ž Check online error repo for more info {}{}{}\n", generate_blank(line_space - 2), color_output.color(Colors::Magenta), @@ -692,7 +771,7 @@ where if error.full_assist || error.semi_assist { if cfg!(feature = "ellie_assist") { - output += &format!( + error_text += &format!( "{}{}[{}]{} ā•ž {} assistment available type '{}ellie{} {}assist{} {}{}{}' for request assist\n", generate_blank(line_space - 2), color_output.color(Colors::Yellow), @@ -716,7 +795,7 @@ where color_output.color(Colors::Reset), ); } else { - output += &format!( + error_text += &format!( "{}{}[x]{} ā•ž {} assistment available but {}ellie_assist{} feature is not enabled\n", generate_blank(line_space - 2), color_output.color( Colors::Yellow), @@ -732,8 +811,20 @@ where } } + if show_debug_lines { + error_text += &format!( + "{}{}[D]{} ā•ž Debug: {}{}{}\n", + generate_blank(line_space - 2), + color_output.color(Colors::Magenta), + color_output.color(Colors::Reset), + color_output.color(Colors::Cyan), + error.debug_message, + color_output.color(Colors::Reset), + ); + } + if error.code == 0x00 && errors.len() > 2 { - output += &format!( + error_text += &format!( "\n{}{}{} other error omitted\n", color_output.color(Colors::Red), errors.len() - 2, @@ -741,6 +832,7 @@ where ); break; } + output += &error_text; } output } diff --git a/ellie_engine/tokenizer/src/syntax/items/setter_call.rs b/ellie_engine/tokenizer/src/syntax/items/setter_call.rs index 7f59d01b..1075b6d4 100644 --- a/ellie_engine/tokenizer/src/syntax/items/setter_call.rs +++ b/ellie_engine/tokenizer/src/syntax/items/setter_call.rs @@ -15,6 +15,7 @@ pub struct SetterCall { pub value_pos: defs::Cursor, pub hash: usize, pub complete: bool, + pub virtual_element: bool, } impl Converter for SetterCall { From 5a6f2ac1c66c1d2d3fffddb4f00373192f8cbdd7 Mon Sep 17 00:00:00 2001 From: Ahmetcan Aksu Date: Wed, 18 Dec 2024 23:11:33 +0300 Subject: [PATCH 26/30] Experiment convert_generic_by_name --- .../bytecode/src/transpiler/types/dynamic.rs | 28 +++++++- ellie_engine/core/src/definite/definers.rs | 71 ++++++++++++++++++- .../parser/src/deep_search_extensions.rs | 4 +- .../parser/src/processors/types/reference.rs | 17 +++-- ellie_engine/renderer_utils/src/options.rs | 1 + ellie_engine/renderer_utils/src/utils.rs | 22 +++--- ellie_engine/vm/src/heap_memory.rs | 3 +- ellie_engine/vm/src/instructions/A2S.rs | 12 ++++ ellie_engine/vm/src/instructions/EQ.rs | 9 +++ .../vm/src/iternal_functions/memory.rs | 68 ++++++++++++++++++ ellie_engine/vm/src/iternal_functions/mod.rs | 6 +- 11 files changed, 214 insertions(+), 27 deletions(-) create mode 100644 ellie_engine/vm/src/iternal_functions/memory.rs diff --git a/ellie_engine/bytecode/src/transpiler/types/dynamic.rs b/ellie_engine/bytecode/src/transpiler/types/dynamic.rs index cb484ac7..8d439276 100644 --- a/ellie_engine/bytecode/src/transpiler/types/dynamic.rs +++ b/ellie_engine/bytecode/src/transpiler/types/dynamic.rs @@ -1,9 +1,33 @@ +use std::vec::Vec; + +use crate::{ + instruction_table::Instructions, + instructions::{Instruction, Registers}, + types::Types as ByteCodeTypes, +}; + use super::TypeTranspiler; pub struct Dynamic; impl TypeTranspiler for Dynamic { - fn transpile(&self, _options: &mut super::TypeTranspilerOptions) { - todo!() + fn transpile(&self, options: &mut super::TypeTranspilerOptions) { + match options.target_register() { + Registers::A => options.assembler_mut().instructions.push(Instructions::LDA( + Instruction::immediate(ByteCodeTypes::Null, Vec::new()), + )), + Registers::B => options.assembler_mut().instructions.push(Instructions::LDB( + Instruction::immediate(ByteCodeTypes::Null, Vec::new()), + )), + Registers::C => options.assembler_mut().instructions.push(Instructions::LDC( + Instruction::immediate(ByteCodeTypes::Null, Vec::new()), + )), + Registers::X => options.assembler_mut().instructions.push(Instructions::LDX( + Instruction::immediate(ByteCodeTypes::Null, Vec::new()), + )), + Registers::Y => options.assembler_mut().instructions.push(Instructions::LDY( + Instruction::immediate(ByteCodeTypes::Null, Vec::new()), + )), + } } } diff --git a/ellie_engine/core/src/definite/definers.rs b/ellie_engine/core/src/definite/definers.rs index 43dbd294..3e9c095a 100644 --- a/ellie_engine/core/src/definite/definers.rs +++ b/ellie_engine/core/src/definite/definers.rs @@ -139,13 +139,17 @@ impl DefinerCollecting { DefinerCollecting::Array(data) => { if let DefinerCollecting::Array(other_data) = other { other_data.size == data.size && other_data.rtype.same_as(*data.rtype.clone()) - } else { DefinerCollecting::Dynamic == other } + } else { + DefinerCollecting::Dynamic == other + } } DefinerCollecting::Generic(generic) => { if let DefinerCollecting::Generic(other_generic) = other { (other_generic.rtype == generic.rtype && other_generic.hash == generic.hash) || (other_generic.rtype == "dyn" || generic.rtype == "dyn") - } else { DefinerCollecting::Dynamic == other } + } else { + DefinerCollecting::Dynamic == other + } } DefinerCollecting::ParentGeneric(parent_generic) => { if let DefinerCollecting::ParentGeneric(other_parent_generic) = other { @@ -274,4 +278,67 @@ impl DefinerCollecting { DefinerCollecting::ClassInstance(_) => (), } } + + pub fn convert_generic_by_name(&mut self, generic_name: String, replacement_generic: DefinerCollecting) { + match self { + DefinerCollecting::Array(array) => { + array + .rtype + .convert_generic_by_name(generic_name, replacement_generic); + } + DefinerCollecting::Generic(generic) => { + if generic.rtype == generic_name { + *self = replacement_generic; + } + } + DefinerCollecting::ParentGeneric(parrent_generic) => { + if parrent_generic.rtype == generic_name { + *self = replacement_generic; + } else { + parrent_generic.generics.iter_mut().for_each(|g| { + g.value + .convert_generic_by_name(generic_name.clone(), replacement_generic.clone()) + }); + } + } + DefinerCollecting::Function(function) => { + function + .params + .iter_mut() + .for_each(|param: &mut DefinerCollecting| { + param.convert_generic_by_name(generic_name.clone(), replacement_generic.clone()) + }); + function + .returning + .convert_generic_by_name(generic_name.clone(), replacement_generic.clone()); + } + DefinerCollecting::Cloak(cloak) => { + cloak + .rtype + .iter_mut() + .for_each(|r| r.convert_generic_by_name(generic_name.clone(), replacement_generic.clone())); + } + DefinerCollecting::Collective(collective) => { + collective + .key + .convert_generic_by_name(generic_name.clone(), replacement_generic.clone()); + collective + .value + .convert_generic_by_name(generic_name.clone(), replacement_generic); + } + DefinerCollecting::Nullable(nullable) => { + nullable + .value + .convert_generic_by_name(generic_name, replacement_generic); + } + DefinerCollecting::EnumField(enum_field) => match &mut enum_field.field_data { + EnumFieldData::NoData => (), + EnumFieldData::Data(enum_field_data) => { + enum_field_data.convert_generic_by_name(generic_name, replacement_generic) + } + }, + DefinerCollecting::Dynamic => (), + DefinerCollecting::ClassInstance(_) => (), + } + } } diff --git a/ellie_engine/parser/src/deep_search_extensions.rs b/ellie_engine/parser/src/deep_search_extensions.rs index c3302f03..93ace61a 100644 --- a/ellie_engine/parser/src/deep_search_extensions.rs +++ b/ellie_engine/parser/src/deep_search_extensions.rs @@ -988,8 +988,8 @@ fn iterate_deep_type( .iter() .enumerate() { - attr.value.convert_generic( - generic_defining.hash, + attr.value.convert_generic_by_name( + generic_defining.name.clone(), rtype.generics[i].value.clone(), ); // = rtype.generics[i].value.clone(); diff --git a/ellie_engine/parser/src/processors/types/reference.rs b/ellie_engine/parser/src/processors/types/reference.rs index a0f6a454..f4023fbe 100644 --- a/ellie_engine/parser/src/processors/types/reference.rs +++ b/ellie_engine/parser/src/processors/types/reference.rs @@ -309,7 +309,7 @@ impl super::TypeParserProcessor for reference_type::ReferenceTypeCollector { errors.extend(e); return None }, - } + } } else { let rtype = match e.data.value.process(options) { Ok(e) => e, @@ -500,12 +500,15 @@ impl super::TypeParserProcessor for reference_type::ReferenceTypeCollector { .iter() .enumerate() { - attr.value.convert_generic( - generic_defining.hash, - rtype.generics[i] - .value - .clone(), - ); + attr.value + .convert_generic_by_name( + generic_defining + .name + .clone(), + rtype.generics[i] + .value + .clone(), + ); // = rtype.generics[i].value.clone(); } attr.clone() diff --git a/ellie_engine/renderer_utils/src/options.rs b/ellie_engine/renderer_utils/src/options.rs index 8dc7cb84..fafbf01c 100644 --- a/ellie_engine/renderer_utils/src/options.rs +++ b/ellie_engine/renderer_utils/src/options.rs @@ -251,6 +251,7 @@ pub fn generate_elliec_options() -> Command<'static> { Arg::new("disableColors") .help("Disable colors") .short('n') + .long("--disable-colors") .takes_value(false), ), ) diff --git a/ellie_engine/renderer_utils/src/utils.rs b/ellie_engine/renderer_utils/src/utils.rs index b9cb49b9..28678e89 100644 --- a/ellie_engine/renderer_utils/src/utils.rs +++ b/ellie_engine/renderer_utils/src/utils.rs @@ -701,19 +701,21 @@ where let file_content = file_reader(error.path.clone()); let mut line_space = error.pos.range_start.0.to_string().len() + 1; + /* let is_reference = error.reference_block.is_some(); let path = file_reader(if is_reference { - error.reference_block.clone().unwrap().1.clone() - } else { - error.path.clone() - }); - let pos = if is_reference { - error.reference_block.clone().unwrap().0 - } else { - error.pos - }; - + error.reference_block.clone().unwrap().1.clone() + } else { + error.path.clone() + }); + let pos = if is_reference { + error.reference_block.clone().unwrap().0 + } else { + error.pos + }; + */ if let Some(refr) = error.reference_block.clone() { + println!("Render reference block"); let ref_file_content = file_reader(refr.1.clone()); if line_space < refr.0.range_start.0.to_string().len() + 1 { line_space = refr.0.range_start.0.to_string().len() + 1; diff --git a/ellie_engine/vm/src/heap_memory.rs b/ellie_engine/vm/src/heap_memory.rs index 514deb7b..80b6396a 100644 --- a/ellie_engine/vm/src/heap_memory.rs +++ b/ellie_engine/vm/src/heap_memory.rs @@ -75,9 +75,10 @@ impl HeapMemory { for key in &self.data { let value = self.get(key.0).unwrap(); result.push_str(&format!( - "{} : {} = {:?} =! {:?}\n", + "{} : {}[{}] = {:?} =! {:?}\n", key.0, value.type_id, + value.type_id.size, match value.type_id.id { 1 => { isize::from_le_bytes(value.data.clone().try_into().unwrap()).to_string() diff --git a/ellie_engine/vm/src/instructions/A2S.rs b/ellie_engine/vm/src/instructions/A2S.rs index 7a8bca95..87e6db90 100644 --- a/ellie_engine/vm/src/instructions/A2S.rs +++ b/ellie_engine/vm/src/instructions/A2S.rs @@ -64,6 +64,18 @@ impl super::InstructionExecuter for A2S { current_stack.registers.A = StaticRawType::from_heap_reference(current_stack.get_pos()); } + 14 => { + let refr = current_stack.registers.A.to_uint(); + let data = heap_memory.get(&refr).unwrap(); + + heap_memory.set( + ¤t_stack.get_pos(), + RawType::generate_string(data.to_string()), + ); + + current_stack.registers.A = + StaticRawType::from_heap_reference(current_stack.get_pos()); + } e => { return Err(ExecuterPanic { reason: ThreadPanicReason::CannotConvertToType(e, 7), diff --git a/ellie_engine/vm/src/instructions/EQ.rs b/ellie_engine/vm/src/instructions/EQ.rs index 7cb98990..a81a7020 100644 --- a/ellie_engine/vm/src/instructions/EQ.rs +++ b/ellie_engine/vm/src/instructions/EQ.rs @@ -98,6 +98,15 @@ impl super::InstructionExecuter for EQ { }); } } + }, + (10, 10) => { + current_stack.registers.A = StaticRawType::from_bool(true); + } + (_, 10) => { + current_stack.registers.A = StaticRawType::from_bool(false); + } + (10, _) => { + current_stack.registers.A = StaticRawType::from_bool(false); } _ => { return Err(ExecuterPanic { diff --git a/ellie_engine/vm/src/iternal_functions/memory.rs b/ellie_engine/vm/src/iternal_functions/memory.rs new file mode 100644 index 00000000..64c08b87 --- /dev/null +++ b/ellie_engine/vm/src/iternal_functions/memory.rs @@ -0,0 +1,68 @@ +use alloc::{string::ToString, vec::Vec}; +use crate::{ + raw_type::StaticRawType, + thread::Isolate, + utils::{ThreadInfo, VmNativeAnswer, VmNativeCallParameters}, +}; +use super::InternalFunction; + +pub fn frame_pos_fn( + _isolate: &mut Isolate, + thread_info: ThreadInfo, + args: Vec, +) -> VmNativeAnswer { + if !args.is_empty() { + return VmNativeAnswer::RuntimeError( + "Signature mismatch expected 0 argument(s)".to_string(), + ); + } + VmNativeAnswer::Ok(VmNativeCallParameters::Static(StaticRawType::from_uint( + thread_info.get_real_pos(), + ))) +} + +pub fn code_pos_fn( + _isolate: &mut Isolate, + thread_info: ThreadInfo, + args: Vec, +) -> VmNativeAnswer { + if !args.is_empty() { + return VmNativeAnswer::RuntimeError( + "Signature mismatch expected 0 argument(s)".to_string(), + ); + } + VmNativeAnswer::Ok(VmNativeCallParameters::Static(StaticRawType::from_uint( + thread_info.pos, + ))) +} + +pub fn variable_size_fn( + isolate: &mut Isolate, + thread_info: ThreadInfo, + args: Vec, +) -> VmNativeAnswer { + if args.len() != 1 { + return VmNativeAnswer::RuntimeError( + "Signature mismatch expected 1 argument(s)".to_string(), + ); + } + + todo!() + + /* match &args[0] { + VmNativeCallParameters::Static(static_raw_type) => { + static_raw_type. + }, + VmNativeCallParameters::Dynamic(raw_type) => todo!(), + } */ +} + +pub const FRAME_POS: InternalFunction = InternalFunction { + name: "frame_pos", + callback: frame_pos_fn, +}; + +pub const CODE_POS: InternalFunction = InternalFunction { + name: "code_pos", + callback: code_pos_fn, +}; diff --git a/ellie_engine/vm/src/iternal_functions/mod.rs b/ellie_engine/vm/src/iternal_functions/mod.rs index c82c32a7..9119cdcb 100644 --- a/ellie_engine/vm/src/iternal_functions/mod.rs +++ b/ellie_engine/vm/src/iternal_functions/mod.rs @@ -5,7 +5,7 @@ use crate::{ utils::{ThreadInfo, VmNativeAnswer, VmNativeCallParameters}, }; -mod stack_memory_functions; +mod memory; mod static_array_functions; pub struct InternalFunction { @@ -15,6 +15,6 @@ pub struct InternalFunction { pub const INTERNAL_FUNCTIONS: [InternalFunction; 3] = [ static_array_functions::ARRAY_LEN, - stack_memory_functions::FRAME_POS, - stack_memory_functions::CODE_POS, + memory::FRAME_POS, + memory::CODE_POS, ]; From 87f2a036bcb4ffa7d694c4cfbb5284ddcdbe4d32 Mon Sep 17 00:00:00 2001 From: Ahmetcan Aksu Date: Thu, 2 Jan 2025 02:51:37 +0300 Subject: [PATCH 27/30] Implement more basic channel interface & fix cloak memory problems --- .../bytecode/src/transpiler/types/cloak.rs | 56 +- ellie_engine/core/src/utils/mod.rs | 6 +- ellie_engine/vm/Cargo.toml | 1 + ellie_engine/vm/src/channel.rs | 4 +- ellie_engine/vm/src/heap_memory.rs | 13 + ellie_engine/vm/src/instructions/ADD.rs | 4 +- ellie_engine/vm/src/instructions/CALLN.rs | 47 +- ellie_engine/vm/src/isolate.rs | 31 + .../vm/src/iternal_functions/memory.rs | 317 +++++++++- ellie_engine/vm/src/iternal_functions/mod.rs | 14 +- .../stack_memory_functions.rs | 49 -- .../static_array_functions.rs | 29 +- ellie_engine/vm/src/lib.rs | 2 + ellie_engine/vm/src/raw_type.rs | 28 +- ellie_engine/vm/src/stack_memory.rs | 25 +- ellie_engine/vm/src/thread.rs | 221 +++---- ellie_engine/vm/src/utils.rs | 591 +++++++++++++++++- elliec/.vscode/launch.json | 35 +- elliec/src/compile_file.rs | 146 +++-- ellievm/src/debugger.rs | 3 +- ellievm/src/main.rs | 158 +++-- ellievm/src/run.rs | 3 +- tools/run.ps1 | 5 +- 23 files changed, 1436 insertions(+), 352 deletions(-) create mode 100644 ellie_engine/vm/src/isolate.rs delete mode 100644 ellie_engine/vm/src/iternal_functions/stack_memory_functions.rs diff --git a/ellie_engine/bytecode/src/transpiler/types/cloak.rs b/ellie_engine/bytecode/src/transpiler/types/cloak.rs index 04765b26..0af4a5ec 100644 --- a/ellie_engine/bytecode/src/transpiler/types/cloak.rs +++ b/ellie_engine/bytecode/src/transpiler/types/cloak.rs @@ -9,55 +9,65 @@ use ellie_core::definite::types::cloak::CloakType; impl TypeTranspiler for CloakType { fn transpile(&self, options: &mut super::TypeTranspilerOptions) { - let mut size = 0; - - for entry in &self.collective { + let static_array_location = options.assembler().location() + 1; + let arch = options.assembler().platform_attributes.architecture; + options + .assembler_mut() + .instructions + .push(Instructions::SAR(Instruction::immediate( + ByteCodeTypes::StaticArray, + usize_to_le_bytes(static_array_location, arch), + ))); + options + .assembler_mut() + .instructions + .push(Instructions::STA(Instruction::immediate( + ByteCodeTypes::Integer, + usize_to_le_bytes(self.collective.len(), arch), + ))); + let index_start = options.assembler().location(); + for _ in &self.collective { + options + .assembler_mut() + .instructions + .push(Instructions::STA(Instruction::implicit())); + } + for (index, entry) in self.collective.iter().enumerate() { entry.value.transpile( options .copy() .set_assembler(options.assembler_mut()) .set_target_register(Registers::A), ); + options .assembler_mut() .instructions - .push(Instructions::STA(Instruction::implicit())); - size += 1; + .push(Instructions::STA(Instruction::absolute( + (index_start + 1) + index, + ))); } - - let arch = options.assembler().platform_attributes.architecture; - - options - .assembler_mut() - .instructions - .push(Instructions::SAR(Instruction::immediate( - ByteCodeTypes::StaticArray, - usize_to_le_bytes(size, arch), - ))); - - let location = options.assembler().location(); - match options.target_register() { Registers::A => options .assembler_mut() .instructions - .push(Instructions::LDA(Instruction::absolute(location))), + .push(Instructions::LDA(Instruction::absolute(index_start - 1))), Registers::B => options .assembler_mut() .instructions - .push(Instructions::LDB(Instruction::absolute(location))), + .push(Instructions::LDB(Instruction::absolute(index_start - 1))), Registers::C => options .assembler_mut() .instructions - .push(Instructions::LDC(Instruction::absolute(location))), + .push(Instructions::LDC(Instruction::absolute(index_start - 1))), Registers::X => options .assembler_mut() .instructions - .push(Instructions::LDX(Instruction::absolute(location))), + .push(Instructions::LDX(Instruction::absolute(index_start - 1))), Registers::Y => options .assembler_mut() .instructions - .push(Instructions::LDY(Instruction::absolute(location))), + .push(Instructions::LDY(Instruction::absolute(index_start - 1))), } } } diff --git a/ellie_engine/core/src/utils/mod.rs b/ellie_engine/core/src/utils/mod.rs index 1b1f014b..1e69334c 100644 --- a/ellie_engine/core/src/utils/mod.rs +++ b/ellie_engine/core/src/utils/mod.rs @@ -106,13 +106,13 @@ pub enum ReliableNameRanges { pub fn reliable_name_range(range: ReliableNameRanges, value: char) -> ReliableNameRangeResponse { let variable_range = match range { ReliableNameRanges::VariableName => { - "QWERTYUIOPASDFGHJKLIZXCVBNMqwertyuıopasşdfghjklizxcvbnm0123456789_" + "QWERTYUIOPĞƜASDFGHJKLŞİZXCVBNMƖƇqwertyuıopğüasdfghjklşizxcvbnmƶƧ0123456789_" } ReliableNameRanges::Type => { - "QWERTYUIOPASDFGHJKLIZXCVBNMqwertyuıopasşdfghjklizxcvbnm0123456789" + "QWERTYUIOPĞƜASDFGHJKLŞİZXCVBNMƖƇqwertyuıopğüasdfghjklşizxcvbnmƶƧ0123456789" } ReliableNameRanges::Path => { - "QWERTYUIOPASDFGHJKLIZXCVBNMqwertyuıopasşdfghjklizxcvbnm0123456789_@!?" + "QWERTYUIOPĞƜASDFGHJKLŞİZXCVBNMƖƇqwertyuıopğüasdfghjklşizxcvbnmƶƧ0123456789_@!?" } }; diff --git a/ellie_engine/vm/Cargo.toml b/ellie_engine/vm/Cargo.toml index 6d332696..35da337a 100644 --- a/ellie_engine/vm/Cargo.toml +++ b/ellie_engine/vm/Cargo.toml @@ -11,6 +11,7 @@ homepage = "https://www.ellie-lang.org" [dependencies] ellie_core = { path = "../core", version = "0.7.3", default-features = false } mimalloc = { version="0.1.34", optional = true } +enum-as-inner = "0.6.1" [features] default = [] diff --git a/ellie_engine/vm/src/channel.rs b/ellie_engine/vm/src/channel.rs index fa3d71c2..aec44f5e 100644 --- a/ellie_engine/vm/src/channel.rs +++ b/ellie_engine/vm/src/channel.rs @@ -1,4 +1,4 @@ -use crate::utils::{ThreadInfo, VmNativeAnswer, VmNativeCallParameters}; +use crate::utils::{FunctionCallParameter, ThreadInfo, VmNativeAnswer}; use alloc::{boxed::Box, string::String, vec::Vec}; use ellie_core::defs::NativeCallTrace; @@ -32,7 +32,7 @@ pub struct EllieModule { } pub type FunctionElementCallback = - Box) -> VmNativeAnswer + Send>; + Box) -> VmNativeAnswer + Send>; pub struct FunctionElement { pub name: &'static str, diff --git a/ellie_engine/vm/src/heap_memory.rs b/ellie_engine/vm/src/heap_memory.rs index 80b6396a..6c6f981e 100644 --- a/ellie_engine/vm/src/heap_memory.rs +++ b/ellie_engine/vm/src/heap_memory.rs @@ -62,6 +62,19 @@ impl HeapMemory { } } + pub fn get_def_ptr(&self, key: &usize) -> Option { + match self.get(key) { + Some(e) => { + if e.type_id.id == 13 { + self.get_def_ptr(&(e.to_int() as usize)) + } else { + Some(e.to_int() as usize) + } + } + None => None, + } + } + pub fn set(&mut self, key: &usize, value: RawType) { self.data.insert(*key, value.to_bytes()); } diff --git a/ellie_engine/vm/src/instructions/ADD.rs b/ellie_engine/vm/src/instructions/ADD.rs index 0e2c4ca2..807c78f3 100644 --- a/ellie_engine/vm/src/instructions/ADD.rs +++ b/ellie_engine/vm/src/instructions/ADD.rs @@ -22,7 +22,7 @@ impl super::InstructionExecuter for ADD { current_stack: &mut Stack, stack_memory: &mut StackMemory, addressing_value: &AddressingValues, - _arch: PlatformArchitecture, + arch: PlatformArchitecture, ) -> Result { match &addressing_value { AddressingValues::Implicit => { @@ -40,6 +40,7 @@ impl super::InstructionExecuter for ADD { reference_data, heap_memory, stack_memory, + arch, ) { Ok(e) => e, Err(e) => { @@ -66,6 +67,7 @@ impl super::InstructionExecuter for ADD { reference_data, heap_memory, stack_memory, + arch, ) { Ok(e) => e, Err(e) => { diff --git a/ellie_engine/vm/src/instructions/CALLN.rs b/ellie_engine/vm/src/instructions/CALLN.rs index cf270060..4b63daff 100644 --- a/ellie_engine/vm/src/instructions/CALLN.rs +++ b/ellie_engine/vm/src/instructions/CALLN.rs @@ -7,8 +7,9 @@ use crate::{ stack::Stack, stack_memory::StackMemory, utils::{ - resolve_reference, AddressingValues, ReferenceType, ThreadPanicReason, VmNativeCall, - VmNativeCallParameters, + resolve_parameter_data_from_raw_type, resolve_parameter_data_from_static_raw_type, + resolve_reference, AddressingValues, FunctionCallParameter, RawFunctionData, ReferenceType, + ResolvedReference, ThreadPanicReason, VmNativeCall, }, }; @@ -22,7 +23,7 @@ impl super::InstructionExecuter for CALLN { current_stack: &mut Stack, stack_memory: &mut StackMemory, addressing_value: &AddressingValues, - _arch: PlatformArchitecture, + arch: PlatformArchitecture, ) -> Result { match addressing_value { AddressingValues::Absolute(start_location) => { @@ -53,7 +54,7 @@ impl super::InstructionExecuter for CALLN { }) } }; - let mut params = Vec::new(); + let mut params: Vec = Vec::new(); let _start_position_of_params = current_stack.get_pos() - 2; for i in 0..params_length { @@ -72,18 +73,42 @@ impl super::InstructionExecuter for CALLN { raw_type.to_uint(), heap_memory, stack_memory, + arch, ) .unwrap() { - crate::utils::ResolvedReference::StaticRawType(e) => { - VmNativeCallParameters::Static(e.0) - } - crate::utils::ResolvedReference::RawType(e) => { - VmNativeCallParameters::Dynamic(e.0) - } + ResolvedReference::StaticRawType(e) => FunctionCallParameter { + data: resolve_parameter_data_from_static_raw_type( + e.0, + stack_memory, + heap_memory, + arch, + ), + raw_data: RawFunctionData::Static(e.0), + memory_location: e.1, + }, + ResolvedReference::RawType(e) => FunctionCallParameter { + data: resolve_parameter_data_from_raw_type( + e.0.clone(), + stack_memory, + heap_memory, + arch, + ), + raw_data: RawFunctionData::Dynamic(e.0), + memory_location: e.1, + }, } } else { - VmNativeCallParameters::Static(raw_type) + FunctionCallParameter { + data: resolve_parameter_data_from_static_raw_type( + raw_type, + stack_memory, + heap_memory, + arch, + ), + raw_data: RawFunctionData::Static(raw_type), + memory_location: pos, + } } } None => { diff --git a/ellie_engine/vm/src/isolate.rs b/ellie_engine/vm/src/isolate.rs new file mode 100644 index 00000000..19548c05 --- /dev/null +++ b/ellie_engine/vm/src/isolate.rs @@ -0,0 +1,31 @@ +use std::string::String; +use crate::{heap_memory::HeapMemory, stack_memory::StackMemory}; + +#[derive(Clone)] +pub struct Isolate { + pub heap_memory: HeapMemory, + pub stack_memory: StackMemory, +} + +impl Default for Isolate { + fn default() -> Self { + Self::new() + } +} + +impl Isolate { + pub fn new() -> Self { + Isolate { + heap_memory: HeapMemory::new(), + stack_memory: StackMemory::new(), + } + } + + pub fn heap_dump(&self) -> String { + self.heap_memory.dump() + } + + pub fn stack_dump(&self) -> String { + self.stack_memory.dump() + } +} diff --git a/ellie_engine/vm/src/iternal_functions/memory.rs b/ellie_engine/vm/src/iternal_functions/memory.rs index 64c08b87..69f1af1c 100644 --- a/ellie_engine/vm/src/iternal_functions/memory.rs +++ b/ellie_engine/vm/src/iternal_functions/memory.rs @@ -1,45 +1,43 @@ -use alloc::{string::ToString, vec::Vec}; +use std::println; + +use super::InternalFunction; use crate::{ - raw_type::StaticRawType, - thread::Isolate, - utils::{ThreadInfo, VmNativeAnswer, VmNativeCallParameters}, + isolate::Isolate, + raw_type::{RawType, StaticRawType}, + utils::{FunctionCallParameter, RawFunctionData, ThreadInfo, VmNativeAnswer}, }; -use super::InternalFunction; +use alloc::{string::ToString, vec::Vec}; pub fn frame_pos_fn( _isolate: &mut Isolate, thread_info: ThreadInfo, - args: Vec, + args: Vec, ) -> VmNativeAnswer { if !args.is_empty() { return VmNativeAnswer::RuntimeError( "Signature mismatch expected 0 argument(s)".to_string(), ); } - VmNativeAnswer::Ok(VmNativeCallParameters::Static(StaticRawType::from_uint( - thread_info.get_real_pos(), - ))) + VmNativeAnswer::Ok(thread_info.get_real_pos().into()) } pub fn code_pos_fn( _isolate: &mut Isolate, thread_info: ThreadInfo, - args: Vec, + args: Vec, ) -> VmNativeAnswer { if !args.is_empty() { return VmNativeAnswer::RuntimeError( "Signature mismatch expected 0 argument(s)".to_string(), ); } - VmNativeAnswer::Ok(VmNativeCallParameters::Static(StaticRawType::from_uint( - thread_info.pos, - ))) + VmNativeAnswer::Ok(thread_info.pos.into()) } pub fn variable_size_fn( isolate: &mut Isolate, thread_info: ThreadInfo, - args: Vec, + args: Vec, ) -> VmNativeAnswer { if args.len() != 1 { return VmNativeAnswer::RuntimeError( @@ -57,6 +55,272 @@ pub fn variable_size_fn( } */ } +pub fn alloc_fn( + isolate: &mut Isolate, + thread_info: ThreadInfo, + args: Vec, +) -> VmNativeAnswer { + if args.len() != 2 { + return VmNativeAnswer::RuntimeError( + "Signature mismatch expected 2 argument(s)".to_string(), + ); + } + + let pointer = match &args[0].raw_data { + RawFunctionData::Static(static_raw_type) => { + if static_raw_type.type_id.is_int() { + static_raw_type.to_uint() + } else { + return VmNativeAnswer::RuntimeError( + "Expected integer as first argument".to_string(), + ); + } + } + RawFunctionData::Dynamic(_) => { + return VmNativeAnswer::RuntimeError("Expected integer as first argument".to_string()); + } + }; + + let size = match &args[1].raw_data { + RawFunctionData::Static(static_raw_type) => { + if static_raw_type.type_id.is_int() { + static_raw_type.to_uint() + } else { + return VmNativeAnswer::RuntimeError( + "Expected integer as second argument".to_string(), + ); + } + } + RawFunctionData::Dynamic(_) => { + return VmNativeAnswer::RuntimeError("Expected integer as second argument".to_string()); + } + }; + + isolate + .heap_memory + .set(&pointer, RawType::array(Vec::new())); + + VmNativeAnswer::Ok(().into()) +} + +pub fn platform_size_fn( + _isolate: &mut Isolate, + thread_info: ThreadInfo, + args: Vec, +) -> VmNativeAnswer { + if args.len() != 0 { + return VmNativeAnswer::RuntimeError( + "Signature mismatch expected 0 argument(s)".to_string(), + ); + } + + VmNativeAnswer::Ok(thread_info.arch.usize_len().into()) +} + +pub fn realloc( + isolate: &mut Isolate, + thread_info: ThreadInfo, + args: Vec, +) -> VmNativeAnswer { + if args.len() != 2 { + return VmNativeAnswer::RuntimeError( + "Signature mismatch expected 2 argument(s)".to_string(), + ); + } + + let pointer = match &args[0].raw_data { + RawFunctionData::Static(static_raw_type) => { + if static_raw_type.type_id.is_int() { + static_raw_type.to_uint() + } else { + return VmNativeAnswer::RuntimeError( + "Expected integer as first argument".to_string(), + ); + } + } + RawFunctionData::Dynamic(_) => { + return VmNativeAnswer::RuntimeError("Expected integer as first argument".to_string()); + } + }; + + let size = match &args[1].raw_data { + RawFunctionData::Static(static_raw_type) => { + if static_raw_type.type_id.is_int() { + static_raw_type.to_int() + } else { + return VmNativeAnswer::RuntimeError( + "Expected integer as second argument".to_string(), + ); + } + } + RawFunctionData::Dynamic(_) => { + return VmNativeAnswer::RuntimeError("Expected integer as second argument".to_string()); + } + }; + + println!("Reallocating {} to {}", pointer, size); + + let mut data = isolate.heap_memory.get_mut(&pointer).unwrap(); + //println!("Data: {:?}", data.data); + + data.resize(size as usize, 0); + + //println!("New data: {:?}", data); + + VmNativeAnswer::Ok(().into()) +} + +pub fn ptr( + isolate: &mut Isolate, + thread_info: ThreadInfo, + args: Vec, +) -> VmNativeAnswer { + if args.len() != 1 { + return VmNativeAnswer::RuntimeError( + "Signature mismatch expected 1 argument(s)".to_string(), + ); + } + + VmNativeAnswer::Ok(args[0].memory_location.into()) +} + +pub fn index_mut( + isolate: &mut Isolate, + thread_info: ThreadInfo, + args: Vec, +) -> VmNativeAnswer { + if args.len() != 3 { + return VmNativeAnswer::RuntimeError( + "Signature mismatch expected 2 argument(s)".to_string(), + ); + } + + let array_ptr = match &args[0].raw_data { + RawFunctionData::Static(static_raw_type) => { + if static_raw_type.type_id.is_int() { + static_raw_type.to_uint() + } else { + return VmNativeAnswer::RuntimeError( + "Expected integer as second argument".to_string(), + ); + } + } + RawFunctionData::Dynamic(_) => { + return VmNativeAnswer::RuntimeError("Expected integer as second argument".to_string()); + } + }; + + let index = match &args[1].raw_data { + RawFunctionData::Static(static_raw_type) => { + if static_raw_type.type_id.is_int() { + static_raw_type.to_int() + } else { + return VmNativeAnswer::RuntimeError( + "Expected integer as first argument".to_string(), + ); + } + } + RawFunctionData::Dynamic(_) => { + return VmNativeAnswer::RuntimeError("Expected integer as first argument".to_string()); + } + }; + + if index < 0 { + return VmNativeAnswer::RuntimeError("Index must be positive".to_string()); + } + + let data = match &args[2].raw_data { + RawFunctionData::Static(static_raw_type) => { + if static_raw_type.type_id.is_int() { + static_raw_type.to_uint() + } else { + return VmNativeAnswer::RuntimeError( + "Expected integer as third argument".to_string(), + ); + } + } + RawFunctionData::Dynamic(_) => { + return VmNativeAnswer::RuntimeError("Expected integer as third argument".to_string()); + } + }; + + let mut array_heap_data = match isolate.heap_memory.get_mut(&array_ptr) { + Some(heap_entry) => heap_entry, + None => { + return VmNativeAnswer::RuntimeError("Pointer not found".to_string()); + } + }; + + /* + let entry_len = { + if array_heap_data.data.len() == (thread_info.arch.usize_len() as usize + 1) { + //platform safety: + //If current platform is 64 bit, but targeted arch is 64 + //we can use 64 bit to store the length of the array + //---------------- + //If current platform is 64 bit, but targeted arch is 32 + //we can use 4 bytes of the usize's 64bit 8 bytes to store the length of the array + //---------------- + //If current platform is 64 bit, but targeted arch is 16 + //we can use 2 bytes of the usize's 64bit 8 bytes to store the length of the array + let len = data.len().to_le_bytes().to_vec(); + heap_value.data.extend(match arch { + ellie_core::defs::PlatformArchitecture::B16 => { + vec![len[0], len[1]] + } + ellie_core::defs::PlatformArchitecture::B32 => { + vec![len[0], len[1], len[2], len[3]] + } + ellie_core::defs::PlatformArchitecture::B64 => len, + }); + data.len() + } else { + let array_len_range = { + let type_id_size = arch.type_id_size() as usize; + let usize_len = arch.usize_len() as usize; + type_id_size..(type_id_size + usize_len) + }; + usize::from_le_bytes( + heap_value.data[array_len_range].try_into().unwrap(), + ) + } + }; + */ + + //if heap_entry.data.len() <= index as usize { + // heap_entry.resize(index as usize + 1, 0); + //} + + let index_size = if index == 0 { + index as usize + } else { + index as usize * thread_info.arch.usize_len() as usize + }; + + /* + println!( + "Setting {} to {:?}, {}, {:?}", + index, + data, + heap_entry.data.len(), + heap_entry.data + ); + */ + + let new_entry_data = RawType::from_usize(data).to_bytes(); + + let ptr = ( + index_size, + index_size + thread_info.arch.usize_len() as usize, + ); + + println!("Setting {} to {:?}", ptr.0, ptr.1); + + //heap_entry.data[ptr.0..ptr.1].copy_from_slice(&RawType::from_usize(data).to_bytes()); + + VmNativeAnswer::Ok(().into()) +} + pub const FRAME_POS: InternalFunction = InternalFunction { name: "frame_pos", callback: frame_pos_fn, @@ -66,3 +330,28 @@ pub const CODE_POS: InternalFunction = InternalFunction { name: "code_pos", callback: code_pos_fn, }; + +pub const ALLOC: InternalFunction = InternalFunction { + name: "alloc", + callback: alloc_fn, +}; + +pub const REALLOC: InternalFunction = InternalFunction { + name: "realloc", + callback: realloc, +}; + +pub const PTR: InternalFunction = InternalFunction { + name: "ptr", + callback: ptr, +}; + +pub const PLATFORM_SIZE: InternalFunction = InternalFunction { + name: "platform_size", + callback: platform_size_fn, +}; + +pub const INDEX_MUT: InternalFunction = InternalFunction { + name: "index_mut", + callback: index_mut, +}; diff --git a/ellie_engine/vm/src/iternal_functions/mod.rs b/ellie_engine/vm/src/iternal_functions/mod.rs index 9119cdcb..e9e22c8b 100644 --- a/ellie_engine/vm/src/iternal_functions/mod.rs +++ b/ellie_engine/vm/src/iternal_functions/mod.rs @@ -1,20 +1,22 @@ use alloc::vec::Vec; -use crate::{ - thread::Isolate, - utils::{ThreadInfo, VmNativeAnswer, VmNativeCallParameters}, -}; +use crate::{isolate::Isolate, utils::{FunctionCallParameter, ThreadInfo, VmNativeAnswer}}; mod memory; mod static_array_functions; pub struct InternalFunction { pub name: &'static str, - pub callback: fn(&mut Isolate, ThreadInfo, Vec) -> VmNativeAnswer, + pub callback: fn(&mut Isolate, ThreadInfo, Vec) -> VmNativeAnswer, } -pub const INTERNAL_FUNCTIONS: [InternalFunction; 3] = [ +pub const INTERNAL_FUNCTIONS: [InternalFunction; 8] = [ static_array_functions::ARRAY_LEN, memory::FRAME_POS, memory::CODE_POS, + memory::ALLOC, + memory::PLATFORM_SIZE, + memory::REALLOC, + memory::PTR, + memory::INDEX_MUT, ]; diff --git a/ellie_engine/vm/src/iternal_functions/stack_memory_functions.rs b/ellie_engine/vm/src/iternal_functions/stack_memory_functions.rs deleted file mode 100644 index b7def27e..00000000 --- a/ellie_engine/vm/src/iternal_functions/stack_memory_functions.rs +++ /dev/null @@ -1,49 +0,0 @@ -use alloc::{string::ToString, vec::Vec}; - -use crate::{ - raw_type::StaticRawType, - thread::Isolate, - utils::{ThreadInfo, VmNativeAnswer, VmNativeCallParameters}, -}; - -use super::InternalFunction; - -pub fn frame_pos_fn( - _isolate: &mut Isolate, - thread_info: ThreadInfo, - args: Vec, -) -> VmNativeAnswer { - if !args.is_empty() { - return VmNativeAnswer::RuntimeError( - "Signature mismatch expected 0 argument(s)".to_string(), - ); - } - VmNativeAnswer::Ok(VmNativeCallParameters::Static(StaticRawType::from_uint( - thread_info.get_real_pos(), - ))) -} - -pub fn code_pos_fn( - _isolate: &mut Isolate, - thread_info: ThreadInfo, - args: Vec, -) -> VmNativeAnswer { - if !args.is_empty() { - return VmNativeAnswer::RuntimeError( - "Signature mismatch expected 0 argument(s)".to_string(), - ); - } - VmNativeAnswer::Ok(VmNativeCallParameters::Static(StaticRawType::from_uint( - thread_info.pos, - ))) -} - -pub const FRAME_POS: InternalFunction = InternalFunction { - name: "frame_pos", - callback: frame_pos_fn, -}; - -pub const CODE_POS: InternalFunction = InternalFunction { - name: "code_pos", - callback: code_pos_fn, -}; diff --git a/ellie_engine/vm/src/iternal_functions/static_array_functions.rs b/ellie_engine/vm/src/iternal_functions/static_array_functions.rs index 9d308359..5977c7ce 100644 --- a/ellie_engine/vm/src/iternal_functions/static_array_functions.rs +++ b/ellie_engine/vm/src/iternal_functions/static_array_functions.rs @@ -1,9 +1,9 @@ use alloc::{string::ToString, vec::Vec}; use crate::{ + isolate::Isolate, raw_type::StaticRawType, - thread::Isolate, - utils::{ThreadInfo, VmNativeAnswer, VmNativeCallParameters}, + utils::{EllieData, FunctionCallParameter, RawFunctionData, ThreadInfo, VmNativeAnswer}, }; use super::InternalFunction; @@ -11,37 +11,32 @@ use super::InternalFunction; pub fn array_len_fn( isolate: &mut Isolate, _thread_info: ThreadInfo, - args: Vec, + args: Vec, ) -> VmNativeAnswer { if args.len() != 1 { return VmNativeAnswer::RuntimeError( "Signature mismatch expected 1 argument(s)".to_string(), ); } - match &args[0] { - VmNativeCallParameters::Static(static_type) => { + match &args[0].raw_data { + RawFunctionData::Static(static_type) => { if static_type.type_id.is_static_array() { let location_of_array = static_type.to_uint(); match isolate.stack_memory.get(&(location_of_array + 1)) { Some(static_data) => { let array_len = static_data.to_uint(); - VmNativeAnswer::Ok(crate::utils::VmNativeCallParameters::Static( - StaticRawType::from_int(array_len as isize), - )) - } - None => { - VmNativeAnswer::RuntimeError( - "Memory corruption occurred (array_len)".to_string(), - ) + + VmNativeAnswer::Ok(array_len.into()) } + None => VmNativeAnswer::RuntimeError( + "Memory corruption occurred (array_len)".to_string(), + ), } } else { - VmNativeAnswer::RuntimeError( - "Signature mismatch expected an array".to_string(), - ) + VmNativeAnswer::RuntimeError("Signature mismatch expected an array".to_string()) } } - VmNativeCallParameters::Dynamic(_) => VmNativeAnswer::RuntimeError( + RawFunctionData::Dynamic(_) => VmNativeAnswer::RuntimeError( "Signature mismatch expected 'static' argument".to_string(), ), } diff --git a/ellie_engine/vm/src/lib.rs b/ellie_engine/vm/src/lib.rs index c88d8993..d14a5d1d 100644 --- a/ellie_engine/vm/src/lib.rs +++ b/ellie_engine/vm/src/lib.rs @@ -41,3 +41,5 @@ pub mod stack_memory; pub mod thread; /// Ellie VM's utils pub mod utils; +// Ellie Isolate +pub mod isolate; diff --git a/ellie_engine/vm/src/raw_type.rs b/ellie_engine/vm/src/raw_type.rs index bcaf291f..6f73bf2a 100644 --- a/ellie_engine/vm/src/raw_type.rs +++ b/ellie_engine/vm/src/raw_type.rs @@ -279,7 +279,7 @@ pub struct Function { } pub struct MutatableRawType<'a> { - pub data: &'a mut Vec, + pub(crate) data: &'a mut Vec, } impl MutatableRawType<'_> { @@ -300,6 +300,15 @@ impl MutatableRawType<'_> { pub fn set_data(&mut self, data: Vec) { self.data[TYPE_SIZE..].copy_from_slice(&data); } + + pub fn get_data_size(&self) -> usize { + self.data.len() - TYPE_SIZE + } + + /// Resize the data partition of the raw type + pub fn resize(&mut self, size: usize, value: u8) { + self.data.resize(size + TYPE_SIZE, 0); + } } #[derive(Clone, Debug)] @@ -334,6 +343,16 @@ impl RawType { RawType { type_id, data } } + pub fn from_usize(uint: usize) -> RawType { + RawType { + type_id: TypeId { + id: 1, + size: mem::size_of::(), + }, + data: uint.to_le_bytes().to_vec(), + } + } + pub fn to_register_raw(&self) -> Result { match self.type_id.id { 0..=5 | 7 | 8 | 10 | 13 | 14 => Ok(StaticRawType { @@ -506,6 +525,13 @@ impl RawType { } } + pub fn array(data: Vec) -> RawType { + RawType { + type_id: TypeId::array(data.len()), + data, + } + } + pub fn is_int(&self) -> bool { self.type_id.id == 1 } diff --git a/ellie_engine/vm/src/stack_memory.rs b/ellie_engine/vm/src/stack_memory.rs index 018ff766..253a78b8 100644 --- a/ellie_engine/vm/src/stack_memory.rs +++ b/ellie_engine/vm/src/stack_memory.rs @@ -1,3 +1,5 @@ +use std::vec::Vec; + use alloc::{ boxed::Box, format, @@ -10,7 +12,7 @@ pub type StackOverflowCallback = Box; //Static memory allocation pub struct StackMemory { - pub data: [StaticRawType; STACK_MEMORY_SIZE], + pub data: Vec, pub len: usize, pub on_stack_overflow: Option, } @@ -18,7 +20,7 @@ pub struct StackMemory { impl Clone for StackMemory { fn clone(&self) -> Self { StackMemory { - data: self.data, + data: self.data.clone(), len: self.len, on_stack_overflow: None, } @@ -34,7 +36,7 @@ impl Default for StackMemory { impl StackMemory { pub fn new() -> StackMemory { StackMemory { - data: [StaticRawType::from_void(); STACK_MEMORY_SIZE], + data: Vec::new(), len: 0, on_stack_overflow: None, } @@ -53,12 +55,17 @@ impl StackMemory { } pub fn set(&mut self, key: &usize, value: StaticRawType) { - if (self.data.len() - 1) < *key { - if let Some(callback) = &mut self.on_stack_overflow { - callback(); - return; - } + //if (self.data.len() - 1) < *key { + // if let Some(callback) = &mut self.on_stack_overflow { + // callback(); + // return; + // } + //} + + if self.data.len() <= *key { + self.data.resize(*key + 1, StaticRawType::from_void()); } + self.data[*key] = value; } @@ -87,7 +94,7 @@ impl StackMemory { 12 => String::from("function"), 13 => String::from("stack_reference"), 14 => String::from("heap_reference"), - 15 => String::from("static_array"), + 15 => format!("static_array({})", value.to_uint()), _ => unreachable!("Wrong typeid"), }; result.push_str(&format!( diff --git a/ellie_engine/vm/src/thread.rs b/ellie_engine/vm/src/thread.rs index f6fde8bb..d12a4112 100644 --- a/ellie_engine/vm/src/thread.rs +++ b/ellie_engine/vm/src/thread.rs @@ -7,14 +7,15 @@ use ellie_core::defs::PlatformArchitecture; use crate::{ channel::ModuleManager, heap_memory::HeapMemory, + isolate::Isolate, iternal_functions::INTERNAL_FUNCTIONS, program::{MainProgram, VmProgram}, - raw_type::StaticRawType, + raw_type::{RawType, StaticRawType}, stack::{Caller, Stack, StackArray}, stack_memory::StackMemory, utils::{ - StepResult, ThreadExit, ThreadInfo, ThreadPanic, ThreadPanicReason, VmNativeAnswer, - VmNativeCallParameters, + ellie_data_to_static_raw_type, EllieData, RawFunctionData, StepResult, ThreadExit, + ThreadInfo, ThreadPanic, ThreadPanicReason, VmNativeAnswer, }, }; @@ -27,35 +28,6 @@ pub struct Registers { pub Y: StaticRawType, } -#[derive(Clone)] -pub struct Isolate { - pub heap_memory: HeapMemory, - pub stack_memory: StackMemory, -} - -impl Default for Isolate { - fn default() -> Self { - Self::new() - } -} - -impl Isolate { - pub fn new() -> Self { - Isolate { - heap_memory: HeapMemory::new(), - stack_memory: StackMemory::new(), - } - } - - pub fn heap_dump(&self) -> String { - self.heap_memory.dump() - } - - pub fn stack_dump(&self) -> String { - self.stack_memory.dump() - } -} - pub struct Thread { // Thread ID pub id: usize, @@ -190,37 +162,44 @@ impl Thread { frame_pos: current_stack.frame_pos, pos: current_stack.pos, stack_caller: current_stack.caller.map(|c| c.id), + arch: self.arch, }, native_call.params, ); match response { VmNativeAnswer::Ok(return_value) => { match return_value { - VmNativeCallParameters::Static(static_value) => { - current_stack.registers.Y = static_value; - } - VmNativeCallParameters::Dynamic(dynamic_value) => { + EllieData::String(string) => { self.isolate.heap_memory.set( &native_call.return_heap_position, - dynamic_value, + RawType::generate_string(string), ); current_stack.registers.Y = StaticRawType::from_heap_reference( native_call.return_heap_position, - ) + ); + } + EllieData::Array(vec) => { + todo!("Array return not yet implemented") + } + EllieData::Class(vec) => { + todo!("Class return not yet implemented") + } + value => { + current_stack.registers.Y = + ellie_data_to_static_raw_type(value); } } + current_stack.pos += 1; StepResult::Step } VmNativeAnswer::RuntimeError(e) => { - StepResult::ThreadExit(ThreadExit::Panic( - ThreadPanic { - reason: ThreadPanicReason::RuntimeError(e), - stack_trace: self.stack.clone(), - code_location: format!("{}:{}", file!(), line!()), - }, - )) + StepResult::ThreadExit(ThreadExit::Panic(ThreadPanic { + reason: ThreadPanicReason::RuntimeError(e), + stack_trace: self.stack.clone(), + code_location: format!("{}:{}", file!(), line!()), + })) } } } else { @@ -243,32 +222,31 @@ impl Thread { stack_caller: current_stack .caller .map(|c| c.id), + arch: self.arch, }, native_call.params, ); match response { VmNativeAnswer::Ok(return_value) => { match return_value { - VmNativeCallParameters::Static( - static_value, - ) => { - current_stack.registers.Y = - static_value; - } - VmNativeCallParameters::Dynamic( - dynamic_value, - ) => { + EllieData::String(string) => { self.isolate.heap_memory.set( &native_call .return_heap_position, - dynamic_value, + RawType::generate_string(string), ); current_stack.registers.Y = StaticRawType::from_heap_reference( native_call.return_heap_position, - ) - } - } + ); + }, + EllieData::Array(vec) => todo!("Array return not yet implemented"), + EllieData::Class(vec) => todo!("Class return not yet implemented"), + value => { + current_stack.registers.Y = ellie_data_to_static_raw_type(value); + }, + }; + current_stack.pos += 1; StepResult::Step } @@ -286,55 +264,47 @@ impl Thread { } } }, - None => { - StepResult::ThreadExit(ThreadExit::Panic( - ThreadPanic { - reason: ThreadPanicReason::CallToUnknown(( - found_trace.function_name.clone(), - native_call.hash, - )), - stack_trace: self.stack.clone(), - code_location: format!( - "{}:{}", - file!(), - line!() - ), - }, - )) - } + None => StepResult::ThreadExit(ThreadExit::Panic( + ThreadPanic { + reason: ThreadPanicReason::CallToUnknown(( + found_trace.function_name.clone(), + native_call.hash, + )), + stack_trace: self.stack.clone(), + code_location: format!( + "{}:{}", + file!(), + line!() + ), + }, + )), } } None => { - StepResult::ThreadExit(ThreadExit::Panic( - ThreadPanic { - reason: ThreadPanicReason::MissingModule( - native_call.hash, - ), - stack_trace: self.stack.clone(), - code_location: format!("{}:{}", file!(), line!()), - }, - )) + StepResult::ThreadExit(ThreadExit::Panic(ThreadPanic { + reason: ThreadPanicReason::MissingModule( + native_call.hash, + ), + stack_trace: self.stack.clone(), + code_location: format!("{}:{}", file!(), line!()), + })) } } } } - None => { - StepResult::ThreadExit(ThreadExit::Panic(ThreadPanic { - reason: ThreadPanicReason::MissingTrace(native_call.hash), - stack_trace: self.stack.clone(), - code_location: format!("{}:{}", file!(), line!()), - })) - } + None => StepResult::ThreadExit(ThreadExit::Panic(ThreadPanic { + reason: ThreadPanicReason::MissingTrace(native_call.hash), + stack_trace: self.stack.clone(), + code_location: format!("{}:{}", file!(), line!()), + })), } } }, - Err(panic) => { - StepResult::ThreadExit(ThreadExit::Panic(ThreadPanic { - reason: panic.reason, - stack_trace: self.stack.clone(), - code_location: panic.code_location, - })) - } + Err(panic) => StepResult::ThreadExit(ThreadExit::Panic(ThreadPanic { + reason: panic.reason, + stack_trace: self.stack.clone(), + code_location: panic.code_location, + })), } } @@ -450,26 +420,36 @@ impl Thread { frame_pos: current_stack.frame_pos, pos: current_stack.pos, stack_caller: current_stack.caller.map(|c| c.id), + arch: self.arch, }, native_call.params, ); + match response { VmNativeAnswer::Ok(return_value) => { match return_value { - VmNativeCallParameters::Static(static_value) => { - current_stack.registers.Y = static_value; - } - VmNativeCallParameters::Dynamic(dynamic_value) => { + EllieData::String(string) => { self.isolate.heap_memory.set( &native_call.return_heap_position, - dynamic_value, + RawType::generate_string(string), ); current_stack.registers.Y = StaticRawType::from_heap_reference( native_call.return_heap_position, - ) + ); + } + EllieData::Array(vec) => { + todo!("Array return not yet implemented") + } + EllieData::Class(vec) => { + todo!("Class return not yet implemented") + } + value => { + current_stack.registers.Y = + ellie_data_to_static_raw_type(value); } } + current_stack.pos += 1; } VmNativeAnswer::RuntimeError(e) => { @@ -501,32 +481,35 @@ impl Thread { stack_caller: current_stack .caller .map(|c| c.id), + arch: self.arch, }, native_call.params, ); match response { VmNativeAnswer::Ok(return_value) => { match return_value { - VmNativeCallParameters::Static( - static_value, - ) => { - current_stack.registers.Y = - static_value; - } - VmNativeCallParameters::Dynamic( - dynamic_value, - ) => { - self.isolate.heap_memory.set( - &native_call - .return_heap_position, - dynamic_value, - ); - current_stack.registers.Y = + EllieData::String(string) => { + self.isolate.heap_memory.set( + &native_call + .return_heap_position, + RawType::generate_string(string), + ); + current_stack.registers.Y = StaticRawType::from_heap_reference( native_call.return_heap_position, ) + } + EllieData::Array(vec) => { + todo!("Array return not yet implemented") + } + EllieData::Class(vec) => { + todo!("Class return not yet implemented") + } + value => { + current_stack.registers.Y = + ellie_data_to_static_raw_type(value) + } } - } current_stack.pos += 1; } VmNativeAnswer::RuntimeError(e) => { diff --git a/ellie_engine/vm/src/utils.rs b/ellie_engine/vm/src/utils.rs index ce7cdc7f..e5d7cc24 100644 --- a/ellie_engine/vm/src/utils.rs +++ b/ellie_engine/vm/src/utils.rs @@ -1,27 +1,250 @@ -use core::mem; - use alloc::{string::String, vec::Vec}; -use ellie_core::defs::CursorPosition; +use core::mem; +use ellie_core::defs::{CursorPosition, PlatformArchitecture}; +use enum_as_inner::EnumAsInner; +use std::string::ToString; use crate::{ - heap_memory, + heap_memory::{self, HeapMemory}, raw_type::{RawType, StaticRawType, TypeId}, stack::Stack, - stack_memory, + stack_memory::{self, StackMemory}, }; #[derive(Clone, Debug)] -pub enum VmNativeCallParameters { +pub enum RawFunctionData { + /// Static raw type Static(StaticRawType), + /// Raw type Dynamic(RawType), } +impl RawFunctionData { + pub fn as_static(self) -> Option { + match self { + RawFunctionData::Static(e) => Some(e), + _ => None, + } + } + + pub fn as_dynamic(self) -> Option { + match self { + RawFunctionData::Dynamic(e) => Some(e), + _ => None, + } + } +} + +#[derive(Clone, Debug)] +pub struct EllieInteger { + pub as_isize: isize, + pub as_usize: usize, +} + +impl From for EllieInteger { + fn from(value: isize) -> Self { + EllieInteger { + as_isize: value, + as_usize: value as usize, + } + } +} + +impl From for EllieInteger { + fn from(value: usize) -> Self { + EllieInteger { + as_isize: value as isize, + as_usize: value, + } + } +} + +impl From<&EllieInteger> for isize { + fn from(value: &EllieInteger) -> Self { + value.as_isize + } +} + +impl From<&EllieInteger> for usize { + fn from(value: &EllieInteger) -> Self { + value.as_usize + } +} + +#[derive(Clone, Debug, EnumAsInner)] +pub enum EllieData { + Integer(EllieInteger), + Float(f32), + Double(f64), + Byte(u8), + Bool(bool), + String(String), + Char(char), + Void, + Null, + Array(Vec), + Class(Vec), +} + +impl Into for &str { + fn into(self) -> EllieData { + EllieData::String(self.to_string()) + } +} + +impl Into for String { + fn into(self) -> EllieData { + EllieData::String(self) + } +} + +impl Into for char { + fn into(self) -> EllieData { + EllieData::Char(self) + } +} + +impl Into for u8 { + fn into(self) -> EllieData { + EllieData::Byte(self) + } +} + +impl Into for f32 { + fn into(self) -> EllieData { + EllieData::Float(self) + } +} + +impl Into for f64 { + fn into(self) -> EllieData { + EllieData::Double(self) + } +} + +impl Into for isize { + fn into(self) -> EllieData { + EllieData::Integer(EllieInteger { + as_isize: self, + as_usize: self as usize, + }) + } +} + +impl Into for usize { + fn into(self) -> EllieData { + EllieData::Integer(EllieInteger { + as_isize: self as isize, + as_usize: self, + }) + } +} + +#[cfg(target_pointer_width = "64")] +impl Into for i128 { + fn into(self) -> EllieData { + EllieData::Integer(EllieInteger { + as_isize: self as isize, + as_usize: self as usize, + }) + } +} + +#[cfg(target_pointer_width = "64")] +impl Into for u128 { + fn into(self) -> EllieData { + EllieData::Integer(EllieInteger { + as_isize: self as isize, + as_usize: self as usize, + }) + } +} + +impl Into for u64 { + fn into(self) -> EllieData { + EllieData::Integer(EllieInteger { + as_isize: self as isize, + as_usize: self as usize, + }) + } +} + +impl Into for i64 { + fn into(self) -> EllieData { + EllieData::Integer(EllieInteger { + as_isize: self as isize, + as_usize: self as usize, + }) + } +} + +impl Into for u32 { + fn into(self) -> EllieData { + EllieData::Integer(EllieInteger { + as_isize: self as isize, + as_usize: self as usize, + }) + } +} + +impl Into for i32 { + fn into(self) -> EllieData { + EllieData::Integer(EllieInteger { + as_isize: self as isize, + as_usize: self as usize, + }) + } +} + +impl Into for u16 { + fn into(self) -> EllieData { + EllieData::Integer(EllieInteger { + as_isize: self as isize, + as_usize: self as usize, + }) + } +} + +impl Into for i16 { + fn into(self) -> EllieData { + EllieData::Integer(EllieInteger { + as_isize: self as isize, + as_usize: self as usize, + }) + } +} + +impl Into for bool { + fn into(self) -> EllieData { + EllieData::Bool(self) + } +} + +impl Into for () { + fn into(self) -> EllieData { + EllieData::Void + } +} + +impl Into for Vec { + fn into(self) -> EllieData { + EllieData::Array(self) + } +} + +#[derive(Clone, Debug)] +pub struct FunctionCallParameter { + pub data: EllieData, + pub raw_data: RawFunctionData, + pub memory_location: usize, +} + #[derive(Clone, Debug)] pub struct VmNativeCall { /// Native function's hash pub hash: usize, /// Parameter array - pub params: Vec, + pub params: Vec, /// Return heap position is location of the ret instruction /// If a non static value want to be returned, it will be stored in the heap, /// and Y register will be referencing to this position, @@ -30,11 +253,18 @@ pub struct VmNativeCall { } #[derive(Clone, Debug)] +// ! Todo: implement Into for VmNativeAnswer pub enum VmNativeAnswer { - Ok(VmNativeCallParameters), + Ok(EllieData), RuntimeError(String), } +impl Into for EllieData { + fn into(self) -> VmNativeAnswer { + VmNativeAnswer::Ok(self) + } +} + #[derive(Debug, Clone)] pub struct ThreadInfo { pub id: usize, @@ -42,6 +272,7 @@ pub struct ThreadInfo { pub frame_pos: usize, pub pos: usize, pub stack_caller: Option, + pub arch: PlatformArchitecture, } impl ThreadInfo { @@ -349,6 +580,7 @@ pub fn resolve_reference( reference_data: usize, heap_memory: &heap_memory::HeapMemory, stack_memory: &stack_memory::StackMemory, + arch: PlatformArchitecture, ) -> Result { match reference_type { ReferenceType::Heap => match heap_memory.get(&reference_data) { @@ -359,6 +591,7 @@ pub fn resolve_reference( usize::from_le_bytes(data.data.try_into().unwrap()), heap_memory, stack_memory, + arch, ) } else if data.type_id.id == 14 { resolve_reference( @@ -366,6 +599,7 @@ pub fn resolve_reference( usize::from_le_bytes(data.data.try_into().unwrap()), heap_memory, stack_memory, + arch, ) } else { Ok(ResolvedReference::RawType((data, reference_data))) @@ -381,6 +615,7 @@ pub fn resolve_reference( data.to_int() as usize, heap_memory, stack_memory, + arch, ) } else if data.type_id.id == 14 { resolve_reference( @@ -388,6 +623,7 @@ pub fn resolve_reference( data.to_int() as usize, heap_memory, stack_memory, + arch, ) } else { Ok(ResolvedReference::StaticRawType((data, reference_data))) @@ -397,3 +633,342 @@ pub fn resolve_reference( }, } } + +pub fn resolve_parameter_data_from_static_raw_type( + raw_data: StaticRawType, + stack_memory: &mut StackMemory, + heap_memory: &mut HeapMemory, + arch: PlatformArchitecture, +) -> EllieData { + match raw_data.type_id.id { + 1 => { + let as_isize = raw_data.to_int(); + let as_usize = raw_data.to_uint(); + EllieData::Integer(EllieInteger { as_isize, as_usize }) + } + 2 => EllieData::Float(raw_data.to_float()), + 3 => EllieData::Double(raw_data.to_double()), + 4 => EllieData::Byte(raw_data.to_byte()), + 5 => EllieData::Bool(raw_data.to_bool()), + 6 => unreachable!("String type is not supported in static raw type"), + 7 => EllieData::Char(raw_data.to_char()), + 8 => EllieData::Void, + 9 => { + todo!() + } + 10 => EllieData::Null, + 11 => { + std::println!("class origin: {:#?}", raw_data); + let array_origin = raw_data.to_uint(); + std::println!("class origin: {:#?}", array_origin); + + let class_data = heap_memory.get(&array_origin).unwrap(); + + std::println!("class_data: {:#?}", class_data); + + let array_entry_size = usize::from_le_bytes( + class_data.data[..arch.usize_len() as usize] + .try_into() + .unwrap(), + ); + let array_data = &class_data.data[arch.usize_len() as usize..]; + let array_entries = array_data.chunks(array_entry_size).collect::>(); + + let class_variables_raw = array_entries + .iter() + .map(|entry| RawType::from_bytes(&entry)) + .collect::>(); + + EllieData::Class( + class_variables_raw + .iter() + .map(|raw_type| { + resolve_parameter_data_from_raw_type( + raw_type.clone(), + stack_memory, + heap_memory, + arch, + ) + }) + .collect::>(), + ) + } + 13 => { + let reference_data = raw_data.to_uint(); + let resolved_reference = resolve_reference( + ReferenceType::Stack, + reference_data, + heap_memory, + stack_memory, + arch, + ) + .expect("Memory corruption"); + + match resolved_reference { + ResolvedReference::StaticRawType(static_raw_type) => { + resolve_parameter_data_from_static_raw_type( + static_raw_type.0, + stack_memory, + heap_memory, + arch, + ) + } + ResolvedReference::RawType(raw_type) => resolve_parameter_data_from_raw_type( + raw_type.0, + stack_memory, + heap_memory, + arch, + ), + } + } + 14 => { + let reference_data = raw_data.to_uint(); + let resolved_reference = resolve_reference( + ReferenceType::Heap, + reference_data, + heap_memory, + stack_memory, + arch, + ) + .expect("Memory corruption"); + + match resolved_reference { + ResolvedReference::StaticRawType(static_raw_type) => { + resolve_parameter_data_from_static_raw_type( + static_raw_type.0, + stack_memory, + heap_memory, + arch, + ) + } + ResolvedReference::RawType(raw_type) => resolve_parameter_data_from_raw_type( + raw_type.0, + stack_memory, + heap_memory, + arch, + ), + } + } + 15 => { + let array_origin = raw_data.to_uint(); + let array_size = stack_memory.get(&(array_origin + 1)).unwrap().to_uint(); + let index_on_stack = array_origin + 2; + let mut array = Vec::new(); + + for i in 0..array_size { + let pos = index_on_stack + i; + let static_raw_type = stack_memory.get(&pos).unwrap(); + + let definite_element = if static_raw_type.type_id.is_heap_reference() + || static_raw_type.type_id.is_stack_reference() + { + resolve_reference( + if static_raw_type.type_id.is_heap_reference() { + ReferenceType::Heap + } else { + ReferenceType::Stack + }, + static_raw_type.to_uint(), + heap_memory, + stack_memory, + arch, + ) + .expect("Memory corruption") + } else { + ResolvedReference::StaticRawType((static_raw_type, pos)) + }; + + match definite_element { + ResolvedReference::StaticRawType(static_raw_type) => { + array.push(resolve_parameter_data_from_static_raw_type( + static_raw_type.0, + stack_memory, + heap_memory, + arch, + )); + } + ResolvedReference::RawType(raw_type) => { + array.push(resolve_parameter_data_from_raw_type( + raw_type.0, + stack_memory, + heap_memory, + arch, + )); + } + } + } + + EllieData::Array(array) + } + _ => unreachable!("Unknown type id"), + } +} + +pub fn resolve_parameter_data_from_raw_type( + raw_data: RawType, + stack_memory: &mut StackMemory, + heap_memory: &mut HeapMemory, + arch: PlatformArchitecture, +) -> EllieData { + match raw_data.type_id.id { + 1 => { + let as_isize = raw_data.to_int(); + let as_usize = raw_data.to_uint(); + EllieData::Integer(EllieInteger { as_isize, as_usize }) + } + 2 => EllieData::Float(raw_data.to_float()), + 3 => EllieData::Double(raw_data.to_double()), + 4 => EllieData::Byte(raw_data.to_byte()), + 5 => EllieData::Bool(raw_data.to_bool()), + 6 => EllieData::String(raw_data.to_string()), + 7 => EllieData::Char(raw_data.to_char()), + 8 => EllieData::Void, + 9 => { + todo!() + } + 10 => EllieData::Null, + 13 => { + let reference_data = raw_data.to_uint(); + let resolved_reference = resolve_reference( + ReferenceType::Stack, + reference_data, + heap_memory, + stack_memory, + arch, + ) + .expect("Memory corruption"); + + match resolved_reference { + ResolvedReference::StaticRawType(static_raw_type) => { + resolve_parameter_data_from_static_raw_type( + static_raw_type.0, + stack_memory, + heap_memory, + arch, + ) + } + ResolvedReference::RawType(raw_type) => resolve_parameter_data_from_raw_type( + raw_type.0, + stack_memory, + heap_memory, + arch, + ), + } + } + 14 => { + let reference_data = raw_data.to_uint(); + let resolved_reference = resolve_reference( + ReferenceType::Heap, + reference_data, + heap_memory, + stack_memory, + arch, + ) + .expect("Memory corruption"); + + match resolved_reference { + ResolvedReference::StaticRawType(static_raw_type) => { + resolve_parameter_data_from_static_raw_type( + static_raw_type.0, + stack_memory, + heap_memory, + arch, + ) + } + ResolvedReference::RawType(raw_type) => resolve_parameter_data_from_raw_type( + raw_type.0, + stack_memory, + heap_memory, + arch, + ), + } + } + 15 => { + let array_origin = raw_data.to_uint(); + let array_size = stack_memory.get(&(array_origin + 1)).unwrap().to_uint(); + + let index_on_stack = array_origin + 2; + let mut array = Vec::new(); + + for i in 0..array_size { + let pos = index_on_stack + i; + let raw_type = stack_memory.get(&pos).unwrap(); + match resolve_reference( + ReferenceType::Stack, + raw_type.to_uint(), + heap_memory, + stack_memory, + arch, + ) + .expect("Memory corruption") + { + ResolvedReference::StaticRawType(static_raw_type) => { + array.push(resolve_parameter_data_from_static_raw_type( + static_raw_type.0, + stack_memory, + heap_memory, + arch, + )); + } + ResolvedReference::RawType(raw_type) => { + array.push(resolve_parameter_data_from_raw_type( + raw_type.0, + stack_memory, + heap_memory, + arch, + )) + } + } + } + + EllieData::Array(array) + } + _ => unreachable!("Unknown type id"), + } +} + +pub fn ellie_data_to_static_raw_type(data: EllieData) -> StaticRawType { + match data { + EllieData::Integer(integer) => StaticRawType::from_int(integer.as_isize), + EllieData::Float(float) => StaticRawType::from_float(float), + EllieData::Double(double) => StaticRawType::from_double(double), + EllieData::Byte(byte) => StaticRawType::from_byte(byte), + EllieData::Bool(bool) => StaticRawType::from_bool(bool), + EllieData::Char(char) => StaticRawType::from_char(char), + EllieData::Void => StaticRawType::from_void(), + EllieData::Null => StaticRawType::from_null(), + _ => unreachable!(), + } +} + +#[macro_export] +/// Asserts the argument size +/// ## Parameters +/// * `$args` - Arguments +/// * `$expected_size` - Expected size +/// ## Returns +/// * `VmNativeAnswer::RuntimeError` if the argument size is not equal to the expected size +/// * `VmNativeAnswer::Ok` if the argument size is equal to the expected size +/// ## Example +/// ```rust +/// use ellie_vm::{assert_arg_size, channel::{EllieModule, FunctionElement, ModuleElements, VmNativeAnswer}}; +/// let mut ellie_core_module = EllieModule::new("ellieCore".to_string()); +/// +/// ellie_core_module.register_element(ModuleElements::Function(FunctionElement::new( +/// "println", +/// Box::new(|_, args| { +/// assert_arg_size!(args, 1); +/// VmNativeAnswer::Ok(().into()) +/// }), +/// ))); +///``` +macro_rules! assert_arg_size { + ($args:expr, $expected_size:expr) => { + if $args.len() != $expected_size { + return VmNativeAnswer::RuntimeError(format!( + "Signature mismatch, expected {} argument(s)", + $expected_size + )); + } + }; +} diff --git a/elliec/.vscode/launch.json b/elliec/.vscode/launch.json index 85f7f67d..3b5f1b8e 100644 --- a/elliec/.vscode/launch.json +++ b/elliec/.vscode/launch.json @@ -4,10 +4,43 @@ // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 "version": "0.2.0", "configurations": [ + { + "type": "lldb", + "request": "launch", + "name": "Compile debug_files/main.ei", + "cargo": { + "args": [ + "build", + "--bin=elliec", + "--package=elliec" + ], + "filter": { + "name": "elliec", + "kind": "bin" + } + }, + "args": [ + "compile", + "--exclude-std", + "--compile-lib", + "--output-type", + "${input:outputType}", + "--module-name", + "EllieApp", + "--disable-colors", + "--show-debug-lines", + "--allow-panics", + "tools/debug_files/main.ei", + ], + "cwd": "${workspaceFolder}" + }, { "type": "lldb", "request": "launch", "name": "Debug executable 'elliec'", + "sourceLanguages": [ + "rust" + ], "cargo": { "args": [ "build", @@ -27,7 +60,7 @@ "${input:outputType}", "--module-name", "EllieApp", - "-n", + "--disable-colors", "--show-debug-lines", "--allow-panics", "${input:file}", diff --git a/elliec/src/compile_file.rs b/elliec/src/compile_file.rs index 9547aaf4..b74b7665 100644 --- a/elliec/src/compile_file.rs +++ b/elliec/src/compile_file.rs @@ -920,45 +920,121 @@ pub fn compile( "{}", print_errors( &pager_errors, - |path| match read_file( - path.replace( - &starter_name, - Path::new(target_path) - .absolutize() - .unwrap() - .parent() - .unwrap() - .to_str() - .unwrap(), - ), - ) { - Ok(e) => e, - Err(err) => { - println!( - "{}[Internal Error]{} Cannot build error, read file failed '{}' {}[{}]{}", - cli_color.color(Colors::Red), - cli_color.color(Colors::Reset), - path, - cli_color.color(Colors::Red), - err, - cli_color.color(Colors::Reset), - ); - std::process::exit(1); + |path| { + let path_starter = path.split('/').next().unwrap(); + let virtual_path_identifier = + match path_starter.split(" e.split('>').next().unwrap(), + None => "", + }; + if path_starter == starter_name { + let real_path = path + .replace( + &starter_name, + Path::new(target_path) + .absolutize() + .unwrap() + .parent() + .unwrap() + .to_str() + .unwrap(), + ) + .clone(); + match read_file(real_path) { + Ok(e) => e, + Err(err) => { + panic!( + "Failed to ouput error. Cannot read file '{}' {}[{}]{}", + path, + cli_color.color(Colors::Red), + err, + cli_color.color(Colors::Reset) + ); + } + } + } else if let Some((_, module_path)) = modules + .iter() + .find(|(module, _)| module.name == virtual_path_identifier) + { + if let Some(module_path) = module_path.clone() { + let real_path = + path.replace(path_starter, &module_path).clone(); + match read_file(real_path.clone()) { + Ok(e) => e, + Err(err) => { + exit_messages.lock().unwrap().push(Box::new(move || { + println!( + "{}[!]{}: Failed to read module targeted code directory: {}{}{} - [{}]", + cli_color.color(Colors::Red), + cli_color.color(Colors::Reset), + cli_color.color(Colors::Yellow), + real_path.clone(), + cli_color.color(Colors::Reset), + err, + ); + })); + module_path + } + } + } else { + exit_messages.lock().unwrap().push(Box::new(move || { + println!( + "{}[!]{}: Path not provided no output will be shown: {}{}{}", + cli_color.color(Colors::Red), + cli_color.color(Colors::Reset), + cli_color.color(Colors::Yellow), + path, + cli_color.color(Colors::Reset), + ); + })); + "No output path provided".to_string() + } + } else { + panic!("Failed to ouput error. Cannot identify module '{}'", path,) } }, cli_settings.show_debug_lines, |path| { - path.replace( - &starter_name, - Path::new(target_path) - .absolutize() - .unwrap() - .parent() - .unwrap() - .to_str() - .unwrap(), - ) - .to_string() + let path_starter = path.split('/').next().unwrap(); + let virtual_path_identifier = + match path_starter.split(" e.split('>').next().unwrap(), + None => "", + }; + if path_starter == starter_name { + path.replace( + &starter_name, + Path::new(target_path) + .absolutize() + .unwrap() + .parent() + .unwrap() + .to_str() + .unwrap(), + ) + .clone() + } else if let Some((_, module_path)) = modules + .iter() + .find(|(module, _)| module.name == virtual_path_identifier) + { + if let Some(module_path) = module_path.clone() { + path.replace(path_starter, &module_path).clone() + } else { + exit_messages.lock().unwrap().push(Box::new(move || { + println!( + "{}[!]{}: Path not provided no output will be shown: {}{}{}", + cli_color.color(Colors::Red), + cli_color.color(Colors::Reset), + cli_color.color(Colors::Yellow), + path, + cli_color.color(Colors::Reset), + ); + })); + "[No output path provided]".to_string() + } + } else { + panic!("Failed to ouput error. Cannot identify module '{}'", path,); + } }, cli_color ) diff --git a/ellievm/src/debugger.rs b/ellievm/src/debugger.rs index 2d269636..48ebd327 100644 --- a/ellievm/src/debugger.rs +++ b/ellievm/src/debugger.rs @@ -8,9 +8,10 @@ use ellie_engine::{ ellie_core::defs::PlatformArchitecture, ellie_vm::{ channel::ModuleManager, + isolate::Isolate, program::{Program, VmProgram}, raw_type::RawType, - thread::{Isolate, Thread}, + thread::Thread, utils::{ProgramReader, StepResult, ThreadExit}, }, vm::{parse_debug_file, RFile}, diff --git a/ellievm/src/main.rs b/ellievm/src/main.rs index 4a77386b..6172c680 100644 --- a/ellievm/src/main.rs +++ b/ellievm/src/main.rs @@ -15,16 +15,20 @@ use ellie_engine::{ utils::{CliColor, ColorDisplay, Colors, TextStyles}, }, ellie_vm::{ + assert_arg_size, channel::{EllieModule, FunctionElement, ModuleElements}, + expect_arg, program::Program, raw_type::{RawType, StaticRawType}, - utils::{ProgramReader, VmNativeAnswer, VmNativeCallParameters}, + utils::{EllieData, ProgramReader, RawFunctionData, VmNativeAnswer}, }, engine_constants, vm::{parse_debug_file, RFile}, }; use run::VmSettings; -use std::{fs::File, io::Read, path::Path, time::SystemTime}; +use std::{ + ffi::CString, fs::File, io::Read, os::windows::io::AsRawHandle, path::Path, time::SystemTime, +}; fn main() { let app = options::generate_ellievm_options(); @@ -130,31 +134,25 @@ fn main() { }; let mut ellie_core_module = EllieModule::new("ellieCore".to_string()); + ellie_core_module.register_element(ModuleElements::Function(FunctionElement::new( "println", Box::new(|_, args| { - if args.len() != 1 { - return VmNativeAnswer::RuntimeError( - "Signature mismatch expected 1 argument(s)".to_string(), - ); - } - match &args[0] { - VmNativeCallParameters::Static(_e) => VmNativeAnswer::RuntimeError( - "Signature mismatch, expected 'dynamic' argument".to_string(), - ), - VmNativeCallParameters::Dynamic(dynamic_value) => { - if dynamic_value.is_string() { - eprintln!("{}", dynamic_value.to_string()); - VmNativeAnswer::Ok(VmNativeCallParameters::Static( - StaticRawType::from_void(), - )) - } else { - VmNativeAnswer::RuntimeError( - "Signature mismatch expected 'string' argument".to_string(), - ) - } + assert_arg_size!(args, 1); + + // Extract the argument using the macro + let arg = match args[0].clone().data.into_string() { + Ok(e) => e, + Err(_) => { + return VmNativeAnswer::RuntimeError( + "Signature mismatch expected 'string' argument".to_string(), + ) } - } + }; + + eprintln!("{arg}"); + + VmNativeAnswer::Ok(().into()) }), ))); @@ -166,12 +164,13 @@ fn main() { "Signature mismatch expected 0 argument(s)".to_string(), ); } - VmNativeAnswer::Ok(VmNativeCallParameters::Static(StaticRawType::from_int( + VmNativeAnswer::Ok( SystemTime::now() .duration_since(SystemTime::UNIX_EPOCH) .unwrap() - .as_millis() as isize, - ))) + .as_millis() + .into(), + ) }), ))); @@ -184,13 +183,13 @@ fn main() { ); } - let path = match &args[0] { - VmNativeCallParameters::Static(_e) => { + let path = match &args[0].raw_data { + RawFunctionData::Static(_e) => { return VmNativeAnswer::RuntimeError( "Signature mismatch, expected 'dynamic' argument".to_string(), ) } - VmNativeCallParameters::Dynamic(dynamic_value) => { + RawFunctionData::Dynamic(dynamic_value) => { if dynamic_value.is_string() { dynamic_value.to_string() } else { @@ -201,26 +200,21 @@ fn main() { } }; - let file_handle = match File::open(&path) { + match File::open(&path) { Ok(e) => { println!("Opened file: {:?}", e); let handle = Box::new(e); let handle = Box::into_raw(handle); - handle as *mut usize - } - Err(e) => { - return VmNativeAnswer::RuntimeError(format!( - "Failed to open file '{}', ({})", - path, - e.to_string() - )); - } - }; + println!("Handle: {:?}", handle); + //handle as *mut usize, - VmNativeAnswer::Ok(VmNativeCallParameters::Static(StaticRawType::from_uint( - file_handle as usize, - ))) + VmNativeAnswer::Ok(((handle as *mut usize) as usize).into()) + } + Err(e) => VmNativeAnswer::Ok( + format!("Failed to open file '{}', ({})", path, e.to_string()).into(), + ), + } }), ))); @@ -232,17 +226,15 @@ fn main() { "Signature mismatch expected 1 argument(s)".to_string(), ); } - match &args[0] { - VmNativeCallParameters::Static(static_value) => { + match &args[0].raw_data { + RawFunctionData::Static(static_value) => { if static_value.type_id.is_int() { let file_handle = static_value.to_int() as *mut usize; let file = unsafe { &mut *(file_handle as *mut File) }; let mut file_contents = String::new(); match file.read_to_string(&mut file_contents) { - Ok(_) => VmNativeAnswer::Ok(VmNativeCallParameters::Dynamic( - RawType::generate_string(file_contents), - )), + Ok(_) => VmNativeAnswer::Ok(file_contents.into()), Err(e) => VmNativeAnswer::RuntimeError(format!( "Failed to read file ({})", e.to_string() @@ -254,13 +246,81 @@ fn main() { ) } } - VmNativeCallParameters::Dynamic(_) => VmNativeAnswer::RuntimeError( + RawFunctionData::Dynamic(_) => VmNativeAnswer::RuntimeError( "Signature mismatch expected static argument".to_string(), ), } }), ))); + ellie_core_module.register_element(ModuleElements::Function(FunctionElement::new( + "panic", + Box::new(|_, args| { + if args.len() != 1 { + return VmNativeAnswer::RuntimeError( + "Signature mismatch expected 1 argument(s)".to_string(), + ); + } + match &args[0].raw_data { + RawFunctionData::Static(_e) => VmNativeAnswer::RuntimeError( + "Signature mismatch, expected 'dynamic' argument".to_string(), + ), + RawFunctionData::Dynamic(dynamic_value) => { + if dynamic_value.is_string() { + VmNativeAnswer::RuntimeError(dynamic_value.to_string()) + } else { + VmNativeAnswer::RuntimeError( + "Signature mismatch expected 'string' argument".to_string(), + ) + } + } + } + }), + ))); + + ellie_core_module.register_element(ModuleElements::Function(FunctionElement::new( + "render_value", + Box::new(|ti, args| { + println!("Thread info: {:#?}", ti); + println!("Args Length: {:#?}", args.len()); + if args.len() != 1 { + return VmNativeAnswer::RuntimeError( + "Signature mismatch expected 1 argument(s)".to_string(), + ); + } + + if args.len() != 1 { + return VmNativeAnswer::RuntimeError( + "Signature mismatch expected 1 argument(s)".to_string(), + ); + } + + println!("Args memory_location: {:#?}", args[0].memory_location); + println!("Args raw_data : {:#?}", args[0].raw_data); + println!("Args data : {:#?}", args[0].data); + + VmNativeAnswer::RuntimeError("Debugging".to_string()) + }), + ))); + + ellie_core_module.register_element(ModuleElements::Function(FunctionElement::new( + "stdout_handle", + Box::new(|_, args| { + if !args.is_empty() { + return VmNativeAnswer::RuntimeError( + "Signature mismatch expected 0 argument(s)".to_string(), + ); + } + + std::io::stdout().as_raw_handle(); + + let handle = Box::new(std::io::stdout()); + let handle = Box::into_raw(handle); + + VmNativeAnswer::Ok(((handle as *mut usize) as usize).into()) + }), + ))); + vm_settings.modules.push(ellie_core_module); let debug_file = match matches.value_of("debugInfo") { diff --git a/ellievm/src/run.rs b/ellievm/src/run.rs index 93f85402..60f35f9e 100644 --- a/ellievm/src/run.rs +++ b/ellievm/src/run.rs @@ -3,8 +3,9 @@ use ellie_engine::{ ellie_renderer_utils::utils::{CliColor, ColorDisplay, Colors}, ellie_vm::{ channel::{EllieModule, ModuleManager}, + isolate::Isolate, program::{Program, VmProgram}, - thread::{Isolate, Thread}, + thread::Thread, utils::{ThreadExit, ThreadPanicReason}, }, }; diff --git a/tools/run.ps1 b/tools/run.ps1 index 81bb7e44..a2f0e03e 100644 --- a/tools/run.ps1 +++ b/tools/run.ps1 @@ -1,11 +1,12 @@ param ( [string]$inputFilePath, - [string]$additionalParams + [string]$additionalParams, + [string]$additionalVmParams ) # Define the compile and run commands with manifest paths $compileCommand = "cargo run --manifest-path=../elliec/Cargo.toml -- compile $inputFilePath -s -a -e -o $additionalParams" -$runCommand = "cargo run --manifest-path=../ellievm/Cargo.toml -- run $($inputFilePath -replace '\.ei$', '.eic') -d $($inputFilePath -replace '\.ei$', '.eig') -a" +$runCommand = "cargo run --manifest-path=../ellievm/Cargo.toml -- run $($inputFilePath -replace '\.ei$', '.eic') -d $($inputFilePath -replace '\.ei$', '.eig') -a $additionalVmParams" # Start the compile command process $compileProcess = Start-Process -FilePath "cmd" -ArgumentList "/c $compileCommand" -PassThru -NoNewWindow From f76d4d62906a855461e984d5fcf14ebf636f2621 Mon Sep 17 00:00:00 2001 From: Ahmetcan Aksu Date: Mon, 6 Jan 2025 02:06:26 +0300 Subject: [PATCH 28/30] Fix removed fields --- ellievm/Cargo.toml | 2 +- ellievm/src/main.rs | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/ellievm/Cargo.toml b/ellievm/Cargo.toml index 61bed955..bda6ddca 100644 --- a/ellievm/Cargo.toml +++ b/ellievm/Cargo.toml @@ -16,4 +16,4 @@ ellie_engine = { path = "../ellie_engine", default-features = false, features = "std", ] } bincode = { version = "1.3.3" } -lazy_static = "1.4.0" +lazy_static = "1.4.0" \ No newline at end of file diff --git a/ellievm/src/main.rs b/ellievm/src/main.rs index 6172c680..65733593 100644 --- a/ellievm/src/main.rs +++ b/ellievm/src/main.rs @@ -17,7 +17,6 @@ use ellie_engine::{ ellie_vm::{ assert_arg_size, channel::{EllieModule, FunctionElement, ModuleElements}, - expect_arg, program::Program, raw_type::{RawType, StaticRawType}, utils::{EllieData, ProgramReader, RawFunctionData, VmNativeAnswer}, From 56bf089d18e87b5e137636b51798761d97d0cd78 Mon Sep 17 00:00:00 2001 From: Ahmetcan Aksu Date: Wed, 8 Jan 2025 00:56:56 +0300 Subject: [PATCH 29/30] Add ffi for testing --- ellievm/src/main.rs | 352 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 352 insertions(+) diff --git a/ellievm/src/main.rs b/ellievm/src/main.rs index 65733593..f26572da 100644 --- a/ellievm/src/main.rs +++ b/ellievm/src/main.rs @@ -8,6 +8,7 @@ mod utils; #[macro_use] extern crate lazy_static; +use core::{ffi::c_void, ptr::addr_of_mut}; use ellie_engine::{ ellie_core::defs::PlatformArchitecture, ellie_renderer_utils::{ @@ -24,6 +25,9 @@ use ellie_engine::{ engine_constants, vm::{parse_debug_file, RFile}, }; + +use libffi::low::*; + use run::VmSettings; use std::{ ffi::CString, fs::File, io::Read, os::windows::io::AsRawHandle, path::Path, time::SystemTime, @@ -320,6 +324,354 @@ fn main() { }), ))); + ellie_core_module.register_element(ModuleElements::Function(FunctionElement::new( + "load_library_handle", + Box::new(|_, args| { + if args.is_empty() { + return VmNativeAnswer::RuntimeError( + "Signature mismatch expected 1 argument(s)".to_string(), + ); + } + + let library_path = args + .first() + .unwrap() + .data + .clone() + .into_string() + .unwrap() + .clone(); + + unsafe { + let library = libloading::Library::new(library_path.as_str()).unwrap(); + let handle = Box::new(library); + let handle = Box::into_raw(handle); + + println!("Handle: {:?}", handle); + //handle as *mut usize, + + VmNativeAnswer::Ok(((handle as *mut usize) as usize).into()) + } + }), + ))); + + ellie_core_module.register_element(ModuleElements::Function(FunctionElement::new( + "call_library_function", + Box::new(|_, args| { + if args.len() != 3 { + return VmNativeAnswer::RuntimeError( + "Signature mismatch expected 3 argument(s)".to_string(), + ); + } + + let library_handle = args[0].data.clone().into_integer().unwrap().as_usize; + let function_name = args[1].data.clone().into_string().unwrap(); + + println!("Library Handle: {:#?}", library_handle); + println!("Function Name: {:#?}", function_name); + + unsafe { + //let library = &*(library_handle as *const libloading::Library); + + let library = libloading::Library::new("user32.dll") + .expect("Failed to load library, did you build c lib?"); + + let function: libloading::Symbol = + match library.get(function_name.as_str().as_bytes()) { + Ok(e) => e, + Err(e) => { + return VmNativeAnswer::RuntimeError(format!( + "Failed to get function '{}', ({})", + function_name, + e.to_string() + )); + } + }; + + let mut ffi_type_args: Vec<*mut ffi_type> = Vec::new(); + let mut ffi_args: Vec<*mut c_void> = Vec::new(); + + for cloak in args[2].data.clone().into_array().unwrap() { + let cloak = cloak.into_array().unwrap(); + let type_id = cloak[0].clone().into_string().unwrap(); + let value = cloak[1].clone(); + + println!("Setting up ffi type: {:#?}", type_id); + + //ffi_type_void + //ffi_type_uint8 + //ffi_type_sint8 + //ffi_type_uint16 + //ffi_type_sint16 + //ffi_type_uint32 + //ffi_type_sint32 + //ffi_type_uint64 + //ffi_type_sint64 + //ffi_type_float + //ffi_type_double + //ffi_type_pointer + + match type_id.as_str() { + "void" => ffi_type_args.push(core::ptr::addr_of_mut!(types::void)), + "uint8" => { + ffi_type_args.push(core::ptr::addr_of_mut!(types::uint8)) + } + "sint8" => { + ffi_type_args.push(core::ptr::addr_of_mut!(types::sint8)) + } + "uint16" => { + ffi_type_args.push(core::ptr::addr_of_mut!(types::uint16)) + } + "sint16" => { + ffi_type_args.push(core::ptr::addr_of_mut!(types::sint16)) + } + "uint32" => { + ffi_type_args.push(core::ptr::addr_of_mut!(types::uint32)) + } + "sint32" => { + ffi_type_args.push(core::ptr::addr_of_mut!(types::sint32)) + } + "uint64" => { + ffi_type_args.push(core::ptr::addr_of_mut!(types::uint64)) + } + "sint64" => { + ffi_type_args.push(core::ptr::addr_of_mut!(types::sint64)) + } + "float" => { + ffi_type_args.push(core::ptr::addr_of_mut!(types::float)) + } + "double" => { + ffi_type_args.push(core::ptr::addr_of_mut!(types::double)) + } + "pointer" => { + println!("SETTING UP POINTER"); + ffi_type_args.push(core::ptr::addr_of_mut!(types::pointer)) + } + _ => { + return VmNativeAnswer::RuntimeError(format!( + "Unknown ffi type '{}'", + type_id + )); + } + } + + match type_id.as_str() { + "void" => { + if value.is_void() { + ffi_args.push(&0_u64 as *const _ as *mut c_void); + } else { + return VmNativeAnswer::RuntimeError(format!( + "Expected 'void' on ffi argument", + )); + } + } + "uint8" => { + if value.is_integer() { + ffi_args.push( + &(value.into_integer().unwrap().as_usize as u8) + as *const _ + as *mut c_void, + ); + } else { + return VmNativeAnswer::RuntimeError(format!( + "Expected 'uint8' on ffi argument", + )); + } + } + "sint8" => { + if value.is_integer() { + ffi_args.push( + &(value.into_integer().unwrap().as_usize as i8) + as *const _ + as *mut c_void, + ); + } else { + return VmNativeAnswer::RuntimeError(format!( + "Expected 'sint8' on ffi argument", + )); + } + } + "uint16" => { + if value.is_integer() { + ffi_args.push( + &(value.into_integer().unwrap().as_usize as u16) + as *const _ + as *mut c_void, + ); + } else { + return VmNativeAnswer::RuntimeError(format!( + "Expected 'uint16' on ffi argument", + )); + } + } + "sint16" => { + if value.is_integer() { + ffi_args.push( + &(value.into_integer().unwrap().as_usize as i16) + as *const _ + as *mut c_void, + ); + } else { + return VmNativeAnswer::RuntimeError(format!( + "Expected 'sint16' on ffi argument", + )); + } + } + "uint32" => { + if value.is_integer() { + ffi_args.push( + &(value.into_integer().unwrap().as_usize as u32) + as *const _ + as *mut c_void, + ); + } else { + return VmNativeAnswer::RuntimeError(format!( + "Expected 'uint32' on ffi argument", + )); + } + } + "sint32" => { + if value.is_integer() { + ffi_args.push( + &(value.into_integer().unwrap().as_usize as i32) + as *const _ + as *mut c_void, + ); + } else { + return VmNativeAnswer::RuntimeError(format!( + "Expected 'sint32' on ffi argument", + )); + } + } + "uint64" => { + if value.is_integer() { + ffi_args.push( + &(value.into_integer().unwrap().as_usize as u64) + as *const _ + as *mut c_void, + ); + } else { + return VmNativeAnswer::RuntimeError(format!( + "Expected 'uint64' on ffi argument", + )); + } + } + "sint64" => { + if value.is_integer() { + ffi_args.push( + &(value.into_integer().unwrap().as_usize as i64) + as *const _ + as *mut c_void, + ); + } else { + return VmNativeAnswer::RuntimeError(format!( + "Expected 'sint64' on ffi argument", + )); + } + } + "float" => { + if value.is_float() { + ffi_args.push( + &(value.into_float().unwrap() as f32) as *const _ + as *mut c_void, + ); + } else { + return VmNativeAnswer::RuntimeError(format!( + "Expected 'float' on ffi argument", + )); + } + } + "double" => { + if value.is_float() { + ffi_args.push( + &(value.into_float().unwrap() as f64) as *const _ + as *mut c_void, + ); + } else { + return VmNativeAnswer::RuntimeError(format!( + "Expected 'double' on ffi argument", + )); + } + } + "pointer" => { + if value.is_string() { + println!("Pointer: {:#?}", value); + let cstring = + CString::new(value.clone().into_string().unwrap().as_str()) + .unwrap() + .into_bytes(); + let cstring = &cstring.as_ptr() as *const _ as *mut c_void; + ffi_args.push(cstring); + } else { + return VmNativeAnswer::RuntimeError(format!( + "Expected 'pointer' string on ffi argument", + )); + } + } + _ => { + return VmNativeAnswer::RuntimeError(format!( + "Unknown ffi type '{}'", + type_id + )); + } + } + } + + let mut cif: ffi_cif = Default::default(); + + match prep_cif( + &mut cif, + libffi::low::ffi_abi_FFI_DEFAULT_ABI, + args.len(), + addr_of_mut!(types::sint32), + ffi_type_args.as_mut_ptr(), + ) { + Ok(c) => c, + Err(e) => { + let reason = match e { + libffi::low::Error::Typedef => { + "Bad or unsupported type representation" + } + libffi::low::Error::Abi => "Given a bad or unsupported ABI", + }; + return VmNativeAnswer::RuntimeError(format!( + "Failed to prepare ffi_cif ({})", + reason + )); + } + } + + let fn_ptr = CodePtr::from_ptr(function.try_as_raw_ptr().unwrap()); + + let text = CString::new("This is the title").unwrap().into_bytes(); + let text = &text.as_ptr() as *const _ as *mut c_void; + let caption = CString::new("This is the caption").unwrap().into_bytes(); + let caption = &caption.as_ptr() as *const _ as *mut c_void; + + + let mut values: [*mut c_void; 4] = [ + &0_u64 as *const _ as *mut c_void, // HWND + ffi_args[1], + ffi_args[2], + &0_u32 as *const _ as *mut c_void, // uType + ]; + + let mut ffi_args: &mut [*mut c_void] = &mut ffi_args; + + let result = + libffi::low::call::(&mut cif, fn_ptr, values.as_mut_ptr()); + + println!("MessageBoxW returned: {}", result); + + println!("ffi_type_args: {:#?}", ffi_type_args); + println!("ffi_args: {:#?}", ffi_args); + + //let result = function(); + VmNativeAnswer::Ok(result.into()) + } + }), + ))); + vm_settings.modules.push(ellie_core_module); let debug_file = match matches.value_of("debugInfo") { From 1f8d166f5d4007b9cf27bbf2b3417a4ed1b2d848 Mon Sep 17 00:00:00 2001 From: Ahmetcan Aksu Date: Wed, 8 Jan 2025 00:58:02 +0300 Subject: [PATCH 30/30] Add ffi libs --- ellievm/Cargo.toml | 4 +- tools/integration_files/core.ei | 120 ++++++++++++++++++++ tools/integration_files/main.ei | 192 ++++++++++++++++++++++++++++++++ 3 files changed, 315 insertions(+), 1 deletion(-) create mode 100644 tools/integration_files/core.ei create mode 100644 tools/integration_files/main.ei diff --git a/ellievm/Cargo.toml b/ellievm/Cargo.toml index bda6ddca..e3b503a9 100644 --- a/ellievm/Cargo.toml +++ b/ellievm/Cargo.toml @@ -16,4 +16,6 @@ ellie_engine = { path = "../ellie_engine", default-features = false, features = "std", ] } bincode = { version = "1.3.3" } -lazy_static = "1.4.0" \ No newline at end of file +lazy_static = "1.4.0" +libloading = "0.8.6" +libffi = "3.2.0" \ No newline at end of file diff --git a/tools/integration_files/core.ei b/tools/integration_files/core.ei new file mode 100644 index 00000000..9c1728ff --- /dev/null +++ b/tools/integration_files/core.ei @@ -0,0 +1,120 @@ +@dont_fix_variant; +pub class Null {} + +@ellie_deep_cast=null; +c null : Null = 0 as Null; + +@dont_fix_variant; +pub class int {} + +@dont_fix_variant; +pub class float {} + +@dont_fix_variant; +pub class double {} + +@dont_fix_variant; +pub class dyn {} + +@dont_fix_variant; +pub class string { + pri v value : string; + co(value); + + pub fn len() : int { + println("string.len() called"); + println("self.value: " + self.value); + //println("array_len(self): " + array_len(self)); + ret 0; + } +} + +//pub fn type_to_raw_type(value: dyn, rawTypeClass: + +@dont_fix_variant; +pub class char {} + +@dont_fix_variant; +pub class bool {} + +@dont_fix_variant; +pub class void {} + +@dont_fix_variant; +pub class function {} + +@dont_fix_variant; +pub class array { + co(arr); + v arr: [T]; + + /* pub fn at(index: int) : T { + if index == -1 { + ret self.arr[self.arr.len() - 1]; + } else { + ret self.arr[index]; + } + } */ + + pub fn len() : int { + ret array_len(self); + } +} + + +@dont_fix_variant; +pub class cloak { + pri v value : T; + co(value); +} + +/* pub class Vector { + co() { + self.arr = frame_pos(); + } + + pub fn create() { + v a = 332; + v pointer = frame_pos(); + v aa = code_pos(); + println(pointer as string); + println(aa as string); + } +} */ + +pub fn println(s: string); + +//Ellie internal function +pub fn array_len(value: dyn): int; + +pub fn frame_pos() : int; + +pub fn code_pos() : int; + +pub fn panic(message: string); + +pub fn timestamp() : int; + +pub fn render_value(value: dyn); + +@ellie_deep_cast=true; +pub c true : bool = 1 as bool; +@ellie_deep_cast=false; +pub c false : bool = 0 as bool; + +@dont_fix_variant; +pub class nullAble { + pri v value : T; + co(value); + + pub fn is_null() : bool { + ret self.value == null; + } + + pub fn unwrap() : T { + if self.value == null { + panic("Error: value is null"); + } + ret self.value; + } +} \ No newline at end of file diff --git a/tools/integration_files/main.ei b/tools/integration_files/main.ei new file mode 100644 index 00000000..58a11ae1 --- /dev/null +++ b/tools/integration_files/main.ei @@ -0,0 +1,192 @@ +import "./core.ei"; + + +class File { + pri v handle : int; + co(handle); +} + +fn _openFile(path: string) : dyn; + +fn openFile(path : string) { + v file_handle = _openFile(path); + + + + //println("File Handle: " + (typeof file_handle as string)); + //if (file_handle.isError()) { + // ret new Result(null, file_handle.getError()); + //} + // + //ret new Result(new File(file_handle.unwrap()), null); +} + +/* +class File { + pri v handle : int; + co(handle); +} + +fn _openFile(path: string) : Result; + +fn openFile(path : string) : Result { + v file_handle = _openFile(path); + + if (file_handle.isError()) { + ret new Result(null, file_handle.getError()); + } + + ret new Result(new File(file_handle.unwrap()), null); +} + */ + +class Error { + pri v message : string; + pri v code : int; + co(message, code); +} + +class Result { + pri v value : ?T; + pri v error: ?Error; + co(value, error); + + fn unwrap() : string { + if (self.error.is_null()) { + ret self.value.unwrap() as string; + } else { + panic("Error: " + self.error.unwrap().message); + ret ""; + } + } + + //fn isOk() : bool { + // ret self.error.is_null(); + //} + + // need to enable this + //fn isError() : bool { + // ret self.error.is_null() == false; + //} + + //fn getError() : Error { + // ret self.error!; + //} +} + + +pub fn alloc(pointer: int, size: int) : void; +pub fn realloc(pointer: int, size: int) : void; +pub fn ptr(data: dyn) : int; + +//!ptr in parameter conflicts with ptr function?? +//pub fn index_mut(idx: int, ptr: int, data: dyn) : void; +pub fn index_mut(array_ptr: int, idx: int, data: dyn) : void; + +pub fn platform_size() : int; + +/* +@dont_fix_variant = true; +@notConstructable = true; +pub class Vec { + co() { + println("pointer: " + self.pointer); + //Create heap pointer with 0 size + alloc(self.pointer, 0); + + //Create array on stack pointer reference it to heap pointer. + //write_pointer(self.pointer, new TypeId(0, 9), self.pointer.to_le_bytes()); + } + pri v size = 0; + pri v pointer = frame_pos(); + + + //element: Type , causes compiler to cant find property, + pub fn push(element: dyn) : void { + //v p_size = platform_size(); + + //println("platform size: " + p_size); + println("size: " + self.size); + + //Resize heap pointer + //realloc(self.pointer, self.size); + + v ptr_of_e = ptr(element); + println("Pointer of element: " + ptr_of_e); + + index_mut(self.pointer, self.size, element); + + + //println("Inserting data to heap"); + //Insert data to resized region + //alloc(self.pointer + self.size, ptr_of_e); + + self.size += 1; + } +} +*/ + + +fn fib_recurisve(n: int) : int { + if (n <= 1) { + ret n; + } + + ret fib_recurisve(n - 1) + fib_recurisve(n - 2); +} + + + +pub fn load_library_handle(path: string) : int; +pub fn call_library_function(handle: int, name: string, args: [(string, dyn)]) : dyn; + +class Library { + co(path) { + self.handle = load_library_handle(path); + println("Library handle: " + self.handle); + } + pri v path : string; + pri v handle : int; + + pub fn call_function(name: string, args: [(string, dyn)]) : dyn { + ret call_library_function(self.handle, name, args); + } +} + + + +fn main() { + v belirteƧ = "ahmet"; + v user32 = new Library("user32.dll"); + + //v stat = [(1, 2), (3, 4), ("5", 6)]; + + //render_value(stat); + + + println("Calling windows api function"); + v dialog_response = user32.call_function( + "MessageBoxA", + [("uint64", 0), ("pointer", "Hello, World!"), ("pointer", "Ellie Test"), ("uint32", 0)] + ) as int; + println("Dialog response: " + dialog_response); + + //loop true {} + + + + //v test = new Vec(); + + //test.psg; compiler fails + + //test.push(1); + + //v start_timestamp = timestamp(); + + //fib 99 + //v fib_of_99 = fib_recurisve(25); + + //v end_timestamp = timestamp(); + //println("Fib of 99: " + fib_of_99); + //println("Time elapsed: " + (end_timestamp - start_timestamp)); +} \ No newline at end of file