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")]
#[derive(PartialEq, Debug, Clone, Serialize, Deserialize)]
#[derive(Default)]
pub enum TokenizerType {
#[default]
Raw,
ClassParser,
FunctionParser,
HeaderParser,
}
#[cfg(feature = "compiler_utils")]
#[cfg(feature = "compiler_utils")]
#[derive(PartialEq, Debug, Clone, Serialize, Deserialize)]
pub struct TokenizerOptions {
pub path: String,
pub functions: bool,
pub break_on_error: bool,
pub loops: bool,
pub enums: bool,
pub classes: bool,
pub getters: bool,
pub setters: bool,
pub conditions: bool,
pub global_variables: bool,
pub line_ending: String,
pub dynamics: bool,
pub collectives: bool,
pub variables: bool,
pub import_std: bool,
pub constants: bool,
pub ignore_imports: bool,
pub parser_type: TokenizerType,
pub allow_import: bool,
}
#[cfg(feature = "compiler_utils")]
impl Default for TokenizerOptions {
fn default() -> Self {
TokenizerOptions {
path: "".to_owned(),
functions: true,
break_on_error: false,
loops: true,
conditions: true,
getters: true,
setters: true,
classes: true,
enums: true,
global_variables: true,
line_ending: "\\r\\n".to_owned(),
dynamics: true,
import_std: true,
collectives: true,
ignore_imports: false,
variables: true,
constants: true,
parser_type: TokenizerType::Raw,
allow_import: true,
}
}
}
#[derive(PartialEq, Debug, Clone, Copy, Serialize, Deserialize, Default)]
#[cfg(feature = "compiler_utils")]
pub struct CursorPosition(pub usize, pub usize);
#[cfg(not(feature = "compiler_utils"))]
#[derive(PartialEq, Debug, Clone, Copy, Default)]
pub struct CursorPosition(pub usize, pub usize);
impl core::fmt::Display for CursorPosition {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(f, "{}:{}", self.0, self.1)
}
}
impl CursorPosition {
pub fn is_bigger(&self, other: &CursorPosition) -> bool {
self.0 > other.0 || (self.0 == other.0 && self.1 > other.1)
}
pub fn skip_char(&mut self, n: usize) -> CursorPosition {
let mut clone = *self;
clone.1 += n;
clone
}
pub fn pop_char(&mut self, n: usize) -> CursorPosition {
let mut clone = *self;
if clone.1 != 0 {
clone.1 -= n;
}
clone
}
pub fn is_zero(&self) -> bool {
self.0 == 0 && self.1 == 0
}
pub fn increase_line(&mut self, n: usize) -> CursorPosition {
let mut clone = *self;
clone.0 += n;
clone
}
}
#[derive(PartialEq, Debug, Clone, Copy, Serialize, Deserialize, Default)]
#[cfg(feature = "compiler_utils")]
pub struct Cursor {
pub range_start: CursorPosition,
pub range_end: CursorPosition,
}
#[derive(PartialEq, Debug, Clone, Copy, Default)]
#[cfg(not(feature = "compiler_utils"))]
pub struct Cursor {
pub range_start: CursorPosition,
pub range_end: CursorPosition,
}
impl Cursor {
pub fn is_zero(&self) -> bool {
self.range_start.is_zero() && self.range_end.is_zero()
}
pub fn is_bigger(&self, than: Cursor) -> bool {
if than.range_end.0 == self.range_end.0 {
self.range_end.1 > than.range_end.1
} else {
than.range_end.0 <= self.range_end.0
}
}
pub fn build_with_skip_char(range_start: CursorPosition) -> Self {
Cursor {
range_start,
range_end: range_start.clone().skip_char(1),
}
}
pub fn build_from_cursor(range_start: CursorPosition) -> Self {
Cursor {
range_start,
range_end: range_start,
}
}
pub fn range_end_skip_char(&self, n: usize) -> Self {
self.range_end.clone().skip_char(n);
*self
}
pub fn range_start_skip_char(&self, n: usize) -> Self {
self.range_start.clone().skip_char(n);
*self
}
}
#[cfg(feature = "compiler_utils")]
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Version {
pub major: usize,
pub minor: usize,
pub patch: usize,
pub pre_release: Option<String>,
pub build_metadata: Option<String>,
}
#[cfg(feature = "compiler_utils")]
impl PartialEq for Version {
fn eq(&self, other: &Self) -> bool {
self.minor == other.minor && self.major == other.major
}
}
#[cfg(feature = "compiler_utils")]
impl Version {
pub fn build_from_string(input: &String) -> Version {
let semver_regex = Regex::new(r"^(?P<major>0|[1-9]\d*)\.(?P<minor>0|[1-9]\d*)\.(?P<patch>0|[1-9]\d*)(?:-(?P<prerelease>(?: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<buildmetadata>[0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$").unwrap();
let caps = semver_regex.captures(input).unwrap();
Version {
major: caps
.name("major")
.unwrap()
.as_str()
.parse::<usize>()
.unwrap(),
minor: caps
.name("minor")
.unwrap()
.as_str()
.parse::<usize>()
.unwrap(),
patch: caps
.name("patch")
.unwrap()
.as_str()
.parse::<usize>()
.unwrap(),
pre_release: caps.name("prerelease").map(|x| x.as_str().to_owned()),
build_metadata: caps.name("buildmetadata").map(|x| x.as_str().to_owned()),
}
}
pub fn build_from_string_checked(input: &String) -> Result<Version, u8> {
let semver_regex = Regex::new(r"^(?P<major>0|[1-9]\d*)\.(?P<minor>0|[1-9]\d*)\.(?P<patch>0|[1-9]\d*)(?:-(?P<prerelease>(?: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<buildmetadata>[0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$").unwrap();
match semver_regex.captures(input) {
Some(caps) => {
let major = caps
.name("major")
.unwrap()
.as_str()
.parse::<usize>()
.unwrap_or(0);
let minor = caps
.name("minor")
.unwrap()
.as_str()
.parse::<usize>()
.unwrap_or(0);
let patch = caps
.name("patch")
.unwrap()
.as_str()
.parse::<usize>()
.unwrap_or(0);
let pre_release = caps.name("prerelease").map(|x| x.as_str().to_owned());
let build_metadata = caps.name("buildmetadata").map(|x| x.as_str().to_owned());
if major == 0 && minor == 0 && patch == 0 {
Err(1)
} else {
Ok(Version {
minor,
major,
patch,
pre_release,
build_metadata,
})
}
}
None => Err(1),
}
}
pub fn to_string(&self) -> String {
format!(
"{}.{}.{}{}{}",
self.major,
self.minor,
self.patch,
if let Some(ref pre_release) = self.pre_release {
format!("-{}", pre_release)
} else {
"".to_owned()
},
if let Some(ref build_metadata) = self.build_metadata {
format!("+{}", build_metadata)
} else {
"".to_owned()
}
)
}
}
#[derive(Clone, Debug, PartialEq, Copy)]
pub enum PlatformArchitecture {
B16,
B32,
B64,
}
impl Display for PlatformArchitecture {
fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
match self {
PlatformArchitecture::B16 => write!(f, "b16"),
PlatformArchitecture::B32 => write!(f, "b32"),
PlatformArchitecture::B64 => write!(f, "b64"),
}
}
}
impl PlatformArchitecture {
pub fn is_16(&self) -> bool {
match self {
PlatformArchitecture::B16 => true,
_ => false,
}
}
pub fn is_32(&self) -> bool {
match self {
PlatformArchitecture::B32 => true,
_ => false,
}
}
pub fn get_code(&self) -> u8 {
match self {
PlatformArchitecture::B16 => 16,
PlatformArchitecture::B32 => 32,
PlatformArchitecture::B64 => 64,
}
}
pub fn type_id_size(&self) -> u8 {
match self {
PlatformArchitecture::B16 => 3,
PlatformArchitecture::B32 => 5,
PlatformArchitecture::B64 => 9,
}
}
pub fn usize_len(&self) -> u8 {
match self {
PlatformArchitecture::B16 => 2,
PlatformArchitecture::B32 => 4,
PlatformArchitecture::B64 => 8,
}
}
pub fn from_byte(byte: u8) -> Option<PlatformArchitecture> {
match byte {
16 => Some(PlatformArchitecture::B16),
32 => Some(PlatformArchitecture::B32),
64 => Some(PlatformArchitecture::B64),
_ => None,
}
}
}
#[derive(Clone, Debug, PartialEq)]
pub enum DebugHeaderType {
Variable,
SetterCall,
GetterCall,
Class,
Parameter,
Function,
NativeFunction,
Condition,
}
#[derive(Clone, Debug)]
pub struct DebugHeader {
pub rtype: DebugHeaderType,
pub hash: usize,
pub module_name: String,
pub module_hash: usize,
pub name: String,
pub start_end: (usize, usize),
pub pos: Cursor,
}
#[derive(Debug, Clone)]
pub struct ModuleMap {
pub module_name: String,
pub module_hash: usize,
pub module_path: Option<String>,
}
#[derive(Debug, Clone)]
pub struct NativeCallTrace {
pub module_name: String,
pub function_hash: usize,
pub function_name: String,
}
#[derive(Debug, Clone)]
pub struct DebugInfo {
pub module_map: Vec<ModuleMap>,
pub debug_headers: Vec<DebugHeader>,
}