diff --git a/.gitignore b/.gitignore index 212de442..0fb66f8e 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ /target -.DS_Store \ No newline at end of file +.DS_Store +.vscode \ No newline at end of file diff --git a/Cargo.lock b/Cargo.lock index 0b2a731c..a9c6a53d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -40,6 +40,12 @@ dependencies = [ "yansi", ] +[[package]] +name = "base64" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd" + [[package]] name = "beef" version = "0.5.2" @@ -61,6 +67,15 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "erased-serde" +version = "0.3.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81d013529d5574a60caeda29e179e695125448e5de52e3874f7b4c1d7360e18e" +dependencies = [ + "serde", +] + [[package]] name = "fnv" version = "1.0.7" @@ -78,6 +93,24 @@ dependencies = [ "wasi", ] +[[package]] +name = "hashbrown" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e" +dependencies = [ + "ahash", +] + +[[package]] +name = "lasso" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aeb7b21a526375c5ca55f1a6dfd4e1fad9fa4edd750f530252a718a44b2608f0" +dependencies = [ + "hashbrown", +] + [[package]] name = "libc" version = "0.2.126" @@ -197,7 +230,10 @@ dependencies = [ "ahash", "ansi_term", "ariadne", + "base64", "bincode", + "erased-serde", + "lasso", "logos", "lz4-compression", "regex", diff --git a/Cargo.toml b/Cargo.toml index f4e2b2cd..591eabd4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,7 +17,10 @@ ansi_term = "0.12.1" regex = "1.5.6" thiserror = "1.0.31" ahash = "0.7.6" -serde = { version = "1.0.138", features = ["derive"] } +serde = { version = "1.0.138", features = ["derive", "rc"] } bincode = "1.3.3" lz4-compression = "0.7.0" -yazi = "0.1.4" \ No newline at end of file +yazi = "0.1.4" +lasso = "0.6.0" +base64 = "0.13.0" +erased-serde = "0.3" \ No newline at end of file diff --git a/src/compiler/mod.rs b/src/compiler/mod.rs index bc1a48bd..f08e36f8 100644 --- a/src/compiler/mod.rs +++ b/src/compiler/mod.rs @@ -1,2 +1,2 @@ -pub mod compiler; -mod error; +// pub mod compiler; +// pub mod error; diff --git a/src/error.rs b/src/error.rs index e62d4ffa..13181db3 100644 --- a/src/error.rs +++ b/src/error.rs @@ -1,3 +1,8 @@ +use std::fmt::Display; + +// use crate::compiler::error::CompilerError; +use crate::interpreter::error::RuntimeError; +use crate::parser::error::SyntaxError; use ariadne::Color; pub const ERROR_S: f64 = 0.4; @@ -11,6 +16,23 @@ pub struct RainbowColorGenerator { shift: f64, } +#[derive(Debug)] +pub enum Error { + Syntax(SyntaxError), + Runtime(RuntimeError), + // Compiler(CompilerError), +} + +impl Display for self::Error { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + todo!() + } +} + +impl std::error::Error for self::Error {} + +pub type Result = std::result::Result; + impl RainbowColorGenerator { pub fn new(h: f64, s: f64, v: f64, shift: f64) -> Self { Self { h, s, v, shift } @@ -76,12 +98,14 @@ macro_rules! error_maker { )* ) => { + use std::path::PathBuf; use $crate::error::*; use ariadne::{Report, ReportKind, Label, Source, Fmt}; - #[allow(unused_imports)] - use $crate::Globals; + // #[allow(unused_imports)] + // use $crate::Globals; $( + #[derive(Debug)] pub enum $err_type { $( $variant { @@ -93,7 +117,7 @@ macro_rules! error_maker { } impl $err_type { - pub fn raise(self, source: $crate::sources::SpwnSource $(, $globals: &Globals)?) { + pub fn raise(self, code: String, source: Option /*$(, $globals: &Globals)?*/) -> String { let mut label_colors = RainbowColorGenerator::new(120.0, ERROR_S, ERROR_V, 45.0); let mut item_colors = RainbowColorGenerator::new(0.0, ERROR_S, ERROR_V, 15.0); @@ -113,6 +137,7 @@ macro_rules! error_maker { )* }; + // epic let mut report = Report::build(ReportKind::Error, area.name(), area.span.0) .with_message(message.to_string() + "\n"); @@ -128,10 +153,14 @@ macro_rules! error_maker { report = report.with_note(m) } + let ret = vec![]; + report .finish() - .eprint((source.name(), Source::from(source.contents()))) + .write((source.name(), Source::from(code)), &mut ret) .unwrap(); + + std::str::from_utf8(&ret).unwrap().to_string() } } )* diff --git a/src/interpreter/error.rs b/src/interpreter/error.rs index 37e4bc13..fcf585ed 100644 --- a/src/interpreter/error.rs +++ b/src/interpreter/error.rs @@ -95,19 +95,19 @@ error_maker! { area: CodeArea, }, - #[ - Message = "Pattern mismatch", Area = area, Note = None, - Labels = [ - area => "This {} is not {}": @(v.value.get_type().to_str()), @(pat.value.to_str(globals)); - v.def_area => "This is of type {}": @(v.value.get_type().to_str()); - pat.def_area => "Pattern defined as {} here": @(pat.value.to_str(globals)); - ] - ] - PatternMismatch { - v: StoredValue, - pat: StoredValue, - area: CodeArea, - }, + // #[ + // Message = "Pattern mismatch", Area = area, Note = None, + // Labels = [ + // area => "This {} is not {}": @(v.value.get_type().to_str()), @(pat.value.to_str(globals)); + // v.def_area => "This is of type {}": @(v.value.get_type().to_str()); + // pat.def_area => "Pattern defined as {} here": @(pat.value.to_str(globals)); + // ] + // ] + // PatternMismatch { + // v: StoredValue, + // pat: StoredValue, + // area: CodeArea, + // }, #[ Message = "Argument not satisfied", Area = call_area, Note = None, @@ -116,12 +116,16 @@ error_maker! { call_area => "Argument not provided here"; ] ] + ArgumentNotSatisfied { arg_name: String, call_area: CodeArea, arg_area: CodeArea, }, + // what if the errors just carry the file too + // and rest is spans + #[ Message = "Too many arguments!", Area = call_area, Note = None, Labels = [ diff --git a/src/interpreter/from_value.rs b/src/interpreter/from_value.rs index c703d10a..f13413f8 100644 --- a/src/interpreter/from_value.rs +++ b/src/interpreter/from_value.rs @@ -3,7 +3,7 @@ use super::value::Value; // can't return a `RuntimeError` cause can't get an `area` here // instead return a tuple of arguments to be formatted into error at a different place that // has an `area` -type Error = (String, &'static str); +pub type Error = (String, &'static str); pub trait FromValue: Clone { fn from_value(val: Value) -> Result; diff --git a/src/interpreter/interpreter.rs b/src/interpreter/interpreter.rs index 95a8a088..9d070adb 100644 --- a/src/interpreter/interpreter.rs +++ b/src/interpreter/interpreter.rs @@ -2,12 +2,12 @@ use ahash::AHashMap; use serde::{Deserialize, Serialize}; use slotmap::{new_key_type, SlotMap}; -use super::contexts::{Context, FullContext}; +// use super::contexts::{Context, FullContext}; use super::error::RuntimeError; -// use super::types::{Instance, Type}; +use super::types::{Instance, Type}; use super::value::{value_ops, Value, ValueType}; -use crate::compiler::compiler::{Code, Instruction}; +// use crate::compiler::compiler::{Code, Instruction}; use crate::interpreter::value::{Macro, Pattern}; use crate::sources::CodeArea; @@ -21,19 +21,22 @@ pub struct StoredValue { pub def_area: CodeArea, } -pub struct Globals { +pub struct Globals + where Self: Send + Sync +{ pub memory: SlotMap, - pub types: AHashMap, - // pub types: AHashMap, - //pub instances: AHashMap, + //pub types: AHashMap, + pub types: AHashMap, + pub instances: AHashMap, } + impl Globals { pub fn new() -> Self { Self { memory: SlotMap::default(), types: AHashMap::new(), - //instances: AHashMap::new(), + instances: AHashMap::new(), } } pub fn init(&mut self) { @@ -65,392 +68,392 @@ impl Globals { } // 😎 -pub fn execute_code(globals: &mut Globals, code: &Code) -> Result<(), RuntimeError> { - let mut contexts = FullContext::single(code.var_count); - // brb - loop { - let mut finished = true; - 'out_for: for context in contexts.iter() { - if !context.inner().finished { - finished = false; - } else { - continue; - } +// pub fn execute_code(globals: &mut Globals, code: &Code) -> Result<(), RuntimeError> { +// let mut contexts = FullContext::single(code.var_count); +// // brb +// loop { +// let mut finished = true; +// 'out_for: for context in contexts.iter() { +// if !context.inner().finished { +// finished = false; +// } else { +// continue; +// } - let (func, mut i) = context.inner().pos; +// let (func, mut i) = context.inner().pos; - macro_rules! pop_deep_clone { - () => {{ - let val = globals.memory[context.inner().stack.pop().unwrap()].clone(); - val.deep_clone(globals) - }}; - (Store) => {{ - globals.key_deep_clone(context.inner().stack.pop().unwrap()) - }}; - } - macro_rules! pop_ref { - () => { - &globals.memory[context.inner().stack.pop().unwrap()] - }; - } - macro_rules! pop_shallow { - () => { - globals.memory[context.inner().stack.pop().unwrap()].clone() - }; - } +// macro_rules! pop_deep_clone { +// () => {{ +// let val = globals.memory[context.inner().stack.pop().unwrap()].clone(); +// val.deep_clone(globals) +// }}; +// (Store) => {{ +// globals.key_deep_clone(context.inner().stack.pop().unwrap()) +// }}; +// } +// macro_rules! pop_ref { +// () => { +// &globals.memory[context.inner().stack.pop().unwrap()] +// }; +// } +// macro_rules! pop_shallow { +// () => { +// globals.memory[context.inner().stack.pop().unwrap()].clone() +// }; +// } - macro_rules! push { - ($v:expr) => {{ - let key = globals.memory.insert($v); - context.inner().stack.push(key); - }}; - } +// macro_rules! push { +// ($v:expr) => {{ +// let key = globals.memory.insert($v); +// context.inner().stack.push(key); +// }}; +// } - macro_rules! push_store { - ($v:expr) => {{ - #[allow(unused_unsafe)] - let key = globals.memory.insert($v); - context.inner().stack.push(key); - }}; - } - macro_rules! store { - ($v:expr) => { - globals.memory.insert($v) - }; - } +// macro_rules! push_store { +// ($v:expr) => {{ +// #[allow(unused_unsafe)] +// let key = globals.memory.insert($v); +// context.inner().stack.push(key); +// }}; +// } +// macro_rules! store { +// ($v:expr) => { +// globals.memory.insert($v) +// }; +// } - macro_rules! op_helper { - ( - $($instr:ident: $func:ident,)* - ) => { - match &code.instructions[func].0[i] { - $( - Instruction::$instr => { - let area = code.get_bytecode_area(func, i); - let b = pop_ref!(); - let a = pop_ref!(); - let key = globals.memory.insert(value_ops::$func(a, b, area, globals)?); - context.inner().stack.push(key); - } - )* - _ => (), - } - }; - } +// macro_rules! op_helper { +// ( +// $($instr:ident: $func:ident,)* +// ) => { +// match &code.instructions[func].0[i] { +// $( +// Instruction::$instr => { +// let area = code.get_bytecode_area(func, i); +// let b = pop_ref!(); +// let a = pop_ref!(); +// let key = globals.memory.insert(value_ops::$func(a, b, area, globals)?); +// context.inner().stack.push(key); +// } +// )* +// _ => (), +// } +// }; +// } - op_helper! { - Plus: plus, - Minus: minus, - Mult: mult, - Div: div, - Mod: modulo, - Pow: pow, - Eq: eq, - NotEq: not_eq, - Greater: greater, - GreaterEq: greater_eq, - Lesser: lesser, - LesserEq: lesser_eq, - Is: is_op, - }; +// op_helper! { +// Plus: plus, +// Minus: minus, +// Mult: mult, +// Div: div, +// Mod: modulo, +// Pow: pow, +// Eq: eq, +// NotEq: not_eq, +// Greater: greater, +// GreaterEq: greater_eq, +// Lesser: lesser, +// LesserEq: lesser_eq, +// Is: is_op, +// }; - match &code.instructions[func].0[i] { - Instruction::LoadConst(id) => { - let area = code.get_bytecode_area(func, i); - let key = globals - .memory - .insert(code.constants.get(*id).clone().into_stored(area)); - context.inner().stack.push(key); - } - Instruction::Negate => { - let area = code.get_bytecode_area(func, i); - let a = pop_ref!(); - push_store!(value_ops::unary_negate(a, area)?); - } - Instruction::Not => { - let area = code.get_bytecode_area(func, i); - let a = pop_ref!(); - push_store!(value_ops::unary_not(a, area)?); - } - Instruction::LoadVar(id) => { - let a = context.inner().get_var(*id); - context.inner().stack.push(a) - } - Instruction::SetVar(id) => { - let top = pop_deep_clone!(); - let key = globals.memory.insert(top); - context.inner().set_var(*id, key); - } - Instruction::Print => { - let top = pop_ref!(); - println!( - "{}", - ansi_term::Color::Green - .bold() - .paint(top.value.to_str(globals)) - ) - } - Instruction::LoadType(id) => { - let area = code.get_bytecode_area(func, i); - let name = code.names.get(*id); - match globals.types.get(name) { - Some(typ) => { - push!(Value::TypeIndicator(*typ).into_stored(area)) - } - None => { - return Err(RuntimeError::UndefinedType { - name: name.clone(), - area, - }) - } - } - } - Instruction::BuildArray(len) => { - let area = code.get_bytecode_area(func, i); - let mut elems = vec![]; - for _ in 0..*len { - elems.push(pop_deep_clone!(Store)); - } - elems.reverse(); - push!(Value::Array(elems).into_stored(area)); - } - Instruction::PushEmpty => { - let area = code.get_bytecode_area(func, i); - push!(Value::Empty.into_stored(area)); - } - Instruction::PopTop => { - context.inner().stack.pop(); - } - Instruction::Jump(id) => { - i = *code.destinations.get(*id) - 1; - } - Instruction::JumpIfFalse(id) => unsafe { - if !value_ops::to_bool(pop_ref!())? { - i = *code.destinations.get(*id) - 1; - } - }, - Instruction::ToIter => todo!(), - Instruction::IterNext(_) => todo!(), - Instruction::BuildDict(id) => { - let area = code.get_bytecode_area(func, i); - let keys = code.name_sets.get(*id); - let map = keys - .iter() - .cloned() - .zip((0..keys.len()).map(|_| pop_deep_clone!(Store))) - .collect(); - push!(Value::Dict(map).into_stored(area)); - } - Instruction::Return => todo!(), - Instruction::Continue => todo!(), - Instruction::Break => todo!(), - Instruction::MakeMacro(id) => { - let area = code.get_bytecode_area(func, i); - let arg_areas = code.macro_arg_areas.get(&(func, i)).unwrap(); - let (func_id, arg_info) = code.macro_build_info.get(*id); - let ret_type = pop_deep_clone!(Store); - let mut args = vec![]; - for ((name, typ, def), area) in arg_info.iter().zip(arg_areas) { - let def = if *def { - Some(pop_deep_clone!(Store)) - } else { - None - }; - let typ = if *typ { - Some(pop_deep_clone!(Store)) - } else { - None - }; - args.push(((name.clone(), area.clone()), typ, def)); - } - args.reverse(); - push!(Value::Macro(Macro { - func_id: *func_id, - args, - ret_type - }) - .into_stored(area)); - } - Instruction::PushAnyPattern => { - let area = code.get_bytecode_area(func, i); - push!(Value::Pattern(Pattern::Any).into_stored(area)); - } - Instruction::MakeMacroPattern(_) => todo!(), - Instruction::Index => todo!(), - Instruction::Call(id) => { - let area = code.get_bytecode_area(func, i); - let base = pop_shallow!(); - match &base.value { - Value::Macro(m) => { - let param_areas = code.macro_arg_areas.get(&(func, i)).unwrap(); - let param_list = code.name_sets.get(*id); +// match &code.instructions[func].0[i] { +// Instruction::LoadConst(id) => { +// let area = code.get_bytecode_area(func, i); +// let key = globals +// .memory +// .insert(code.constants.get(*id).clone().into_stored(area)); +// context.inner().stack.push(key); +// } +// Instruction::Negate => { +// let area = code.get_bytecode_area(func, i); +// let a = pop_ref!(); +// push_store!(value_ops::unary_negate(a, area)?); +// } +// Instruction::Not => { +// let area = code.get_bytecode_area(func, i); +// let a = pop_ref!(); +// push_store!(value_ops::unary_not(a, area)?); +// } +// Instruction::LoadVar(id) => { +// let a = context.inner().get_var(*id); +// context.inner().stack.push(a) +// } +// Instruction::SetVar(id) => { +// let top = pop_deep_clone!(); +// let key = globals.memory.insert(top); +// context.inner().set_var(*id, key); +// } +// Instruction::Print => { +// let top = pop_ref!(); +// println!( +// "{}", +// ansi_term::Color::Green +// .bold() +// .paint(top.value.to_str(globals)) +// ) +// } +// Instruction::LoadType(id) => { +// let area = code.get_bytecode_area(func, i); +// let name = code.names.get(*id); +// match globals.types.get(name) { +// Some(typ) => { +// push!(Value::TypeIndicator(*typ).into_stored(area)) +// } +// None => { +// return Err(RuntimeError::UndefinedType { +// name: name.clone(), +// area, +// }) +// } +// } +// } +// Instruction::BuildArray(len) => { +// let area = code.get_bytecode_area(func, i); +// let mut elems = vec![]; +// for _ in 0..*len { +// elems.push(pop_deep_clone!(Store)); +// } +// elems.reverse(); +// push!(Value::Array(elems).into_stored(area)); +// } +// Instruction::PushEmpty => { +// let area = code.get_bytecode_area(func, i); +// push!(Value::Empty.into_stored(area)); +// } +// Instruction::PopTop => { +// context.inner().stack.pop(); +// } +// Instruction::Jump(id) => { +// i = *code.destinations.get(*id) - 1; +// } +// Instruction::JumpIfFalse(id) => unsafe { +// if !value_ops::to_bool(pop_ref!())? { +// i = *code.destinations.get(*id) - 1; +// } +// }, +// Instruction::ToIter => todo!(), +// Instruction::IterNext(_) => todo!(), +// Instruction::BuildDict(id) => { +// let area = code.get_bytecode_area(func, i); +// let keys = code.name_sets.get(*id); +// let map = keys +// .iter() +// .cloned() +// .zip((0..keys.len()).map(|_| pop_deep_clone!(Store))) +// .collect(); +// push!(Value::Dict(map).into_stored(area)); +// } +// Instruction::Return => todo!(), +// Instruction::Continue => todo!(), +// Instruction::Break => todo!(), +// Instruction::MakeMacro(id) => { +// let area = code.get_bytecode_area(func, i); +// let arg_areas = code.macro_arg_areas.get(&(func, i)).unwrap(); +// let (func_id, arg_info) = code.macro_build_info.get(*id); +// let ret_type = pop_deep_clone!(Store); +// let mut args = vec![]; +// for ((name, typ, def), area) in arg_info.iter().zip(arg_areas) { +// let def = if *def { +// Some(pop_deep_clone!(Store)) +// } else { +// None +// }; +// let typ = if *typ { +// Some(pop_deep_clone!(Store)) +// } else { +// None +// }; +// args.push(((name.clone(), area.clone()), typ, def)); +// } +// args.reverse(); +// push!(Value::Macro(Macro { +// func_id: *func_id, +// args, +// ret_type +// }) +// .into_stored(area)); +// } +// Instruction::PushAnyPattern => { +// let area = code.get_bytecode_area(func, i); +// push!(Value::Pattern(Pattern::Any).into_stored(area)); +// } +// Instruction::MakeMacroPattern(_) => todo!(), +// Instruction::Index => todo!(), +// Instruction::Call(id) => { +// let area = code.get_bytecode_area(func, i); +// let base = pop_shallow!(); +// match &base.value { +// Value::Macro(m) => { +// let param_areas = code.macro_arg_areas.get(&(func, i)).unwrap(); +// let param_list = code.name_sets.get(*id); - let mut param_map = AHashMap::new(); +// let mut param_map = AHashMap::new(); - let mut params = vec![]; - let mut named_params = vec![]; +// let mut params = vec![]; +// let mut named_params = vec![]; - for (name, param_area) in param_list.iter().zip(param_areas) { - if name.is_empty() { - params.push((pop_deep_clone!(), param_area)); - } else { - if let Some(p) = - m.args.iter().position(|((s, _), ..)| s == name) - { - param_map.insert(name.clone(), p); - } else { - return Err(RuntimeError::UndefinedArgument { - name: name.into(), - macr: base.clone(), - area: param_area.clone(), - }); - } - named_params.push(( - name.clone(), - pop_deep_clone!(), - param_area, - )); - } - } +// for (name, param_area) in param_list.iter().zip(param_areas) { +// if name.is_empty() { +// params.push((pop_deep_clone!(), param_area)); +// } else { +// if let Some(p) = +// m.args.iter().position(|((s, _), ..)| s == name) +// { +// param_map.insert(name.clone(), p); +// } else { +// return Err(RuntimeError::UndefinedArgument { +// name: name.into(), +// macr: base.clone(), +// area: param_area.clone(), +// }); +// } +// named_params.push(( +// name.clone(), +// pop_deep_clone!(), +// param_area, +// )); +// } +// } - if params.len() > m.args.len() { - let call_area = code.get_bytecode_area(func, i); - return Err(RuntimeError::TooManyArguments { - expected: m.args.len(), - provided: params.len(), - call_area, - func: base.clone(), - }); - } +// if params.len() > m.args.len() { +// let call_area = code.get_bytecode_area(func, i); +// return Err(RuntimeError::TooManyArguments { +// expected: m.args.len(), +// provided: params.len(), +// call_area, +// func: base.clone(), +// }); +// } - let mut arg_fill = m - .args - .iter() - .map(|((_, _), t, d)| { - ( - t.map(|id| globals.deep_clone(id)), - d.map(|id| globals.deep_clone(id)), - ) - }) - .collect::>(); - params.reverse(); - named_params.reverse(); +// let mut arg_fill = m +// .args +// .iter() +// .map(|((_, _), t, d)| { +// ( +// t.map(|id| globals.deep_clone(id)), +// d.map(|id| globals.deep_clone(id)), +// ) +// }) +// .collect::>(); +// params.reverse(); +// named_params.reverse(); - for (i, (val, param_area)) in params.into_iter().enumerate() { - if let Some(pat) = &arg_fill[i].0 { - if !value_ops::matches_pat(&val.value, &value_ops::to_pat(pat)?) - { - return Err(RuntimeError::PatternMismatch { - v: val, - pat: pat.clone(), - area: param_area.clone(), - }); - } - } - arg_fill[i].1 = Some(val); - } +// for (i, (val, param_area)) in params.into_iter().enumerate() { +// if let Some(pat) = &arg_fill[i].0 { +// if !value_ops::matches_pat(&val.value, &value_ops::to_pat(pat)?) +// { +// return Err(RuntimeError::PatternMismatch { +// v: val, +// pat: pat.clone(), +// area: param_area.clone(), +// }); +// } +// } +// arg_fill[i].1 = Some(val); +// } - for (name, val, param_area) in named_params.into_iter() { - let arg_pos = param_map[&name]; - if let Some(pat) = &arg_fill[arg_pos].0 { - if !value_ops::matches_pat(&val.value, &value_ops::to_pat(pat)?) - { - return Err(RuntimeError::PatternMismatch { - v: val, - pat: pat.clone(), - area: param_area.clone(), - }); - } - } - arg_fill[arg_pos].1 = Some(val); - } +// for (name, val, param_area) in named_params.into_iter() { +// let arg_pos = param_map[&name]; +// if let Some(pat) = &arg_fill[arg_pos].0 { +// if !value_ops::matches_pat(&val.value, &value_ops::to_pat(pat)?) +// { +// return Err(RuntimeError::PatternMismatch { +// v: val, +// pat: pat.clone(), +// area: param_area.clone(), +// }); +// } +// } +// arg_fill[arg_pos].1 = Some(val); +// } - for ((_, arg), ((name, area), ..)) in arg_fill.iter().zip(&m.args) { - if let Some(arg) = arg { - } else { - let call_area = code.get_bytecode_area(func, i); - return Err(RuntimeError::ArgumentNotSatisfied { - arg_name: name.clone(), - call_area, - arg_area: area.clone(), - }); - } - } +// for ((_, arg), ((name, area), ..)) in arg_fill.iter().zip(&m.args) { +// if let Some(arg) = arg { +// } else { +// let call_area = code.get_bytecode_area(func, i); +// return Err(RuntimeError::ArgumentNotSatisfied { +// arg_name: name.clone(), +// call_area, +// arg_area: area.clone(), +// }); +// } +// } - println!("------ arg fill 2"); - for (t, v) in arg_fill { - println!( - "{:?}", - if let Some(v) = v { - v.value.to_str(globals) - } else { - "None".into() - } - ); - } +// println!("------ arg fill 2"); +// for (t, v) in arg_fill { +// println!( +// "{:?}", +// if let Some(v) = v { +// v.value.to_str(globals) +// } else { +// "None".into() +// } +// ); +// } - todo!() - } - _ => { - return Err(RuntimeError::CannotCall { - base: base.clone(), - area, - }) - } - } - } - Instruction::TriggerFuncCall => todo!(), - Instruction::SaveContexts => todo!(), - Instruction::ReviseContexts => todo!(), - Instruction::MergeContexts => {} - Instruction::PushNone => todo!(), - Instruction::WrapMaybe => todo!(), - Instruction::PushContextGroup => todo!(), - Instruction::PopContextGroup => todo!(), - Instruction::PushTriggerFnValue => todo!(), - Instruction::TypeDef(_) => todo!(), - Instruction::Impl(_) => todo!(), - Instruction::Instance(_) => todo!(), - Instruction::Split => { - let b = pop_deep_clone!(Store); - let a = pop_deep_clone!(Store); - context.split_context(globals); - match context { - FullContext::Single(_) => unreachable!(), - FullContext::Split(c_a, c_b) => { - c_a.inner().stack.push(a); - c_b.inner().stack.push(b); - c_a.inner().advance_to(code, i + 1); - c_b.inner().advance_to(code, i + 1); - finished = false; - break 'out_for; - } - } - } +// todo!() +// } +// _ => { +// return Err(RuntimeError::CannotCall { +// base: base.clone(), +// area, +// }) +// } +// } +// } +// Instruction::TriggerFuncCall => todo!(), +// Instruction::SaveContexts => todo!(), +// Instruction::ReviseContexts => todo!(), +// Instruction::MergeContexts => {} +// Instruction::PushNone => todo!(), +// Instruction::WrapMaybe => todo!(), +// Instruction::PushContextGroup => todo!(), +// Instruction::PopContextGroup => todo!(), +// Instruction::PushTriggerFnValue => todo!(), +// Instruction::TypeDef(_) => todo!(), +// Instruction::Impl(_) => todo!(), +// Instruction::Instance(_) => todo!(), +// Instruction::Split => { +// let b = pop_deep_clone!(Store); +// let a = pop_deep_clone!(Store); +// context.split_context(globals); +// match context { +// FullContext::Single(_) => unreachable!(), +// FullContext::Split(c_a, c_b) => { +// c_a.inner().stack.push(a); +// c_b.inner().stack.push(b); +// c_a.inner().advance_to(code, i + 1); +// c_b.inner().advance_to(code, i + 1); +// finished = false; +// break 'out_for; +// } +// } +// } - Instruction::Plus - | Instruction::Minus - | Instruction::Mult - | Instruction::Div - | Instruction::Mod - | Instruction::Pow - | Instruction::Eq - | Instruction::NotEq - | Instruction::Greater - | Instruction::GreaterEq - | Instruction::Lesser - | Instruction::LesserEq - | Instruction::Is => (), +// Instruction::Plus +// | Instruction::Minus +// | Instruction::Mult +// | Instruction::Div +// | Instruction::Mod +// | Instruction::Pow +// | Instruction::Eq +// | Instruction::NotEq +// | Instruction::Greater +// | Instruction::GreaterEq +// | Instruction::Lesser +// | Instruction::LesserEq +// | Instruction::Is => (), - Instruction::EnterScope => {} - Instruction::ExitScope => {} - } +// Instruction::EnterScope => {} +// Instruction::ExitScope => {} +// } - context.inner().advance_to(code, i + 1); - } - if finished { - break; - } - } - Ok(()) -} +// context.inner().advance_to(code, i + 1); +// } +// if finished { +// break; +// } +// } +// Ok(()) +// } diff --git a/src/interpreter/mod.rs b/src/interpreter/mod.rs index 7d052c30..2539a4b8 100644 --- a/src/interpreter/mod.rs +++ b/src/interpreter/mod.rs @@ -1,10 +1,10 @@ -pub mod contexts; -pub mod converter; -mod error; +// pub mod contexts; +// pub mod converter; +pub mod error; mod from_value; pub mod interpreter; mod method; mod to_value; -// mod type_method; -// mod types; +mod type_method; +mod types; pub mod value; diff --git a/src/interpreter/to_value.rs b/src/interpreter/to_value.rs index f73c896a..21b8ca51 100644 --- a/src/interpreter/to_value.rs +++ b/src/interpreter/to_value.rs @@ -1,16 +1,18 @@ use super::error::RuntimeError; use super::value::Value; +use super::from_value::Error; + pub trait ToValue { fn to_value(self) -> Value; } pub trait ToValueResult { - fn to_value_result(self) -> Result; + fn try_to_value(self) -> Result; } impl ToValueResult for R { - fn to_value_result(self) -> Result { + fn try_to_value(self) -> Result { Ok(self.to_value()) } } diff --git a/src/interpreter/type_method.rs b/src/interpreter/type_method.rs index fbcd884d..406d6efc 100644 --- a/src/interpreter/type_method.rs +++ b/src/interpreter/type_method.rs @@ -1,6 +1,8 @@ +use std::fmt; use std::sync::Arc; use ahash::AHashMap; +use serde::{Deserialize, Serialize}; use super::from_value::FromValueList; use super::interpreter::Globals; @@ -9,12 +11,30 @@ use super::to_value::ToValueResult; use super::types::Instance; use super::value::Value; -type StaticMethodType = Arc) -> Result + Send + Sync>; -type SelfMethodType = - Arc, &mut Globals) -> Result + Send + Sync>; +type Error = dyn std::error::Error; + +trait StaticMethodTrait: + Fn(Vec) -> Result + + Send + + Sync + + erased_serde::Serialize + + erased_serde::Deserializer<'static> +{ +} +trait SelfMethodTrait: + Fn(&Instance, Vec, &mut Globals) -> Result + + Send + + Sync + + erased_serde::Serialize + + erased_serde::Deserializer<'static> +{ +} + +type StaticMethodType = Arc>; +type SelfMethodType = Arc>; // `SelfMethod` i.e. a instance method (where `self` is the first argument) -#[derive(Clone)] +#[derive(Serialize, Deserialize, Clone)] pub struct SelfMethod(SelfMethodType); impl SelfMethod { @@ -33,7 +53,7 @@ impl SelfMethod { instance .and_then(|i| args.map(|a| (i, a))) - .and_then(|(instance, args)| f.invoke(instance, args).to_value_result()) + .and_then(|(instance, args)| f.invoke(instance, args).try_to_value()) }, )) } @@ -53,10 +73,18 @@ impl SelfMethod { self.0(instance, args, globals) } } + +// need to manually implement cause the traits dont implement debug +impl fmt::Debug for SelfMethod { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "SelfMethod(...)") + } +} + pub type SelfMethods = AHashMap; // `StaticMethod` where `self` isnt the first argument -#[derive(Clone)] +#[derive(Serialize, Deserialize, Clone)] pub struct StaticMethod(StaticMethodType); impl StaticMethod { @@ -67,7 +95,7 @@ impl StaticMethod { F::Result: ToValueResult, { Self(Arc::new(move |args: Vec| { - Args::from_value_list(&args).and_then(|args| f.invoke(args).to_value_result()) + Args::from_value_list(&args).and_then(|args| f.invoke(args).try_to_value()) })) } @@ -75,6 +103,13 @@ impl StaticMethod { self.0(args) } } + +impl fmt::Debug for StaticMethod { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "StaticMethod(...)") + } +} + pub type StaticMethods = AHashMap; #[derive(Clone)] @@ -91,7 +126,7 @@ impl AttributeGetter { { Self(Arc::new(move |instance, globals: &mut Globals| { let instance = instance.downcast(Some(globals)); - instance.map(&f).and_then(|v| v.to_value_result()) + instance.map(&f).and_then(|v| v.try_to_value()) })) } @@ -100,6 +135,12 @@ impl AttributeGetter { } } +impl fmt::Debug for AttributeGetter { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "AttributeGetter(...)") + } +} + pub type Attributes = AHashMap; #[derive(Clone)] @@ -115,8 +156,7 @@ impl Constructor { Constructor(Arc::new(move |args: Vec| { Args::from_value_list(&args).map(|args| { let s = f.invoke(args); - let id = (&s).hash_id(); - Instance::new(s, id) + Instance::new(s, s.name) }) })) } @@ -125,3 +165,9 @@ impl Constructor { self.0(args) } } + +impl fmt::Debug for Constructor { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "Constructor(...)") + } +} diff --git a/src/interpreter/types.rs b/src/interpreter/types.rs index 55bd3f6d..b54023d5 100644 --- a/src/interpreter/types.rs +++ b/src/interpreter/types.rs @@ -1,8 +1,10 @@ -use std::any::Any; +use std::any::{type_name, Any}; use std::marker::PhantomData; use std::sync::Arc; -use super::from_value::FromValueList; +use serde::{Deserialize, Serialize}; + +use super::from_value::{Error, FromValueList}; use super::interpreter::Globals; use super::method::{Function, Method}; use super::to_value::{ToValue, ToValueResult}; @@ -10,14 +12,10 @@ use super::type_method::{ AttributeGetter, Attributes, Constructor, SelfMethod, SelfMethods, StaticMethod, StaticMethods, }; use super::value::Value; -use super::error::RuntimeError; - -use crate::sources::CodeArea; -#[derive(Clone)] +#[derive(Serialize, Deserialize, Debug, Clone)] pub struct Type { pub name: String, - //pub type_id: HashId, constructor: Option, attributes: Attributes, self_methods: SelfMethods, @@ -26,10 +24,7 @@ pub struct Type { impl Type { pub fn call_static(&self, name: &str, args: Vec) -> Result { - let attr = self - .static_methods - .get(name) - .ok_or_else(|| format!("Static method '{}' is undefined!", name))?; + let attr = self.static_methods.get(name).ok_or_else(|| todo!())?; attr.clone().invoke(args) } @@ -42,7 +37,9 @@ impl Type { if let Some(method) = self.static_methods.get(&name).cloned() { return Ok(SelfMethod::from_static_method(method)); } - Err(format!("Self method '{}' is undefined!", name)) + //Err(format!("Self method '{}' is undefined!", name)) + + todo!("idk errors will happen later") } } @@ -118,7 +115,6 @@ where Args: FromValueList, F: Method, R: ToValueResult + 'static, - T: Hash, S: ToString, { self.typ @@ -141,11 +137,11 @@ pub struct Instance { } impl Instance { - pub fn of(typ: &Type, fields: Vec) -> Result { + pub fn of(typ: &Type, fields: Vec) -> Result { if let Some(ctor) = &typ.constructor { ctor.invoke(fields) } else { - Err(RuntimeError::) + todo!() } } @@ -162,10 +158,8 @@ impl Instance { } pub fn inner_type<'a>(&self, globals: &'a Globals) -> Result<&'a Type, Error> { - globals - .types - .get(&self.type_id) - .ok_or_else(|| format!("Type '{:?}' is undefined!", self.debug_type_name)) + globals.types.get(&self.type_id).ok_or_else(|| todo!())? + //format!("Type '{:?}' is undefined!", self.debug_type_name) } pub fn name<'a>(&self, globals: &'a Globals) -> &'a str { @@ -178,9 +172,8 @@ impl Instance { let attr = self .inner_type(globals) .and_then(|c| { - c.attributes - .get(name) - .ok_or_else(|| format!("Attribute '{}' is undefined!", name)) + c.attributes.get(name).ok_or_else(|| todo!()) + //format!("Attribute '{}' is undefined!", name) })? .clone(); attr.invoke(self, globals) @@ -205,17 +198,11 @@ impl Instance { let expected_name = globals .as_ref() - .and_then(|g| { - g.types - .get(&hash_type_name::()) - .map(|ty| ty.name.clone()) - }) + .and_then(|g| g.types.get(name).map(|ty| ty.name.clone())) .unwrap_or_else(|| self.debug_type_name.to_owned()); - self.inner - .as_ref() - .downcast_ref() - .ok_or_else(|| format!("Expected type '{}', got '{}'!", expected_name, name)) + self.inner.as_ref().downcast_ref().ok_or_else(|| todo!()) + //format!("Expected type '{}', got '{}'!", expected_name, name) } pub fn raw(&self) -> Result<&T, Error> { diff --git a/src/interpreter/value.rs b/src/interpreter/value.rs index ee6773d8..410a8b19 100644 --- a/src/interpreter/value.rs +++ b/src/interpreter/value.rs @@ -3,6 +3,7 @@ use std::collections::HashMap; use serde::{Deserialize, Serialize}; use super::interpreter::{Globals, StoredValue, ValueKey}; +use super::types::Type; use crate::sources::CodeArea; @@ -30,7 +31,7 @@ pub enum Value { Dict(HashMap), Maybe(Option), - TypeIndicator(ValueType), + TypeIndicator(Type), Pattern(Pattern), Group(Id), diff --git a/src/main.rs b/src/main.rs index 8c4a7766..4fba2e2b 100644 --- a/src/main.rs +++ b/src/main.rs @@ -9,93 +9,93 @@ use std::io::{self, Write}; use std::path::PathBuf; use ahash::AHashMap; -use compiler::compiler::{Compiler, Scope}; -use interpreter::contexts::{Context, FullContext}; -use interpreter::interpreter::{execute_code, Globals}; +// use compiler::compiler::{Compiler, Scope}; +// use interpreter::contexts::{Context, FullContext}; +// use interpreter::interpreter::{execute_code, Globals}; use parser::lexer::lex; -use parser::parser::{parse, ASTData, ParseData}; +// use parser::parser::{parse, ASTData, ParseData}; use slotmap::SlotMap; -use sources::SpwnSource; - -fn run(code: String, source: SpwnSource) { - let tokens = lex(code); - - let mut ast_data = ASTData::default(); - let parse_data = ParseData { - source: source.clone(), - tokens, - }; - - let ast = parse(&parse_data, &mut ast_data); - - match ast { - Ok(stmts) => { - ast_data.debug(&stmts); - - let mut compiler = Compiler::new(ast_data); - compiler.code.instructions.push((vec![], vec![])); - - let mut base_scope = compiler.scopes.insert(Scope::base()); - - match compiler.compile_stmts(stmts, base_scope, 0) { - Ok(_) => { - compiler.code.debug(); - - // let bytes = to_bytes(&compiler.code); - // println!("bytes: {}", bytes.len()); - - // let mut file = File::create("test.spwnc").unwrap(); - // file.write_all(&bytes).unwrap(); - - // let compressed = lz4_compression::prelude::compress(&bytes); - // println!( - // "lz4 bytes: {}, {:.2}%", - // compressed.len(), - // (compressed.len() as f64) / (bytes.len() as f64) * 100.0 - // ); - - // let compressed = - // yazi::compress(&bytes, yazi::Format::Raw, yazi::CompressionLevel::BestSize) - // .unwrap(); - // println!( - // "zlib bytes: {}, {:.2}%", - // compressed.len(), - // (compressed.len() as f64) / (bytes.len() as f64) * 100.0 - // ); - - // println!("{:?}", bytes); - - // let mut globals = Globals { - // memory: SlotMap::default(), - // contexts: FullContext::Split( - // Box::new(FullContext::single(compiler.code.var_count)), - // Box::new(FullContext::single(compiler.code.var_count)), - // ), - // }; - - let mut globals = Globals::new(); - globals.init(); - - if let Err(e) = execute_code(&mut globals, &compiler.code) { - e.raise(source, &globals); - } - } - Err(e) => e.raise(source), - } - } - Err(e) => { - e.raise(source); - } - } -} +// use sources::SpwnSource; + +// fn run(code: String, source: SpwnSource) { +// let tokens = lex(code); + +// let mut ast_data = ASTData::default(); +// let parse_data = ParseData { +// source: source.clone(), +// tokens, +// }; + +// let ast = parse(&parse_data, &mut ast_data); + +// match ast { +// Ok(stmts) => { +// ast_data.debug(&stmts); + +// let mut compiler = Compiler::new(ast_data); +// compiler.code.instructions.push((vec![], vec![])); + +// let mut base_scope = compiler.scopes.insert(Scope::base()); + +// match compiler.compile_stmts(stmts, base_scope, 0) { +// Ok(_) => { +// compiler.code.debug(); + +// // let bytes = to_bytes(&compiler.code); +// // println!("bytes: {}", bytes.len()); + +// // let mut file = File::create("test.spwnc").unwrap(); +// // file.write_all(&bytes).unwrap(); + +// // let compressed = lz4_compression::prelude::compress(&bytes); +// // println!( +// // "lz4 bytes: {}, {:.2}%", +// // compressed.len(), +// // (compressed.len() as f64) / (bytes.len() as f64) * 100.0 +// // ); + +// // let compressed = +// // yazi::compress(&bytes, yazi::Format::Raw, yazi::CompressionLevel::BestSize) +// // .unwrap(); +// // println!( +// // "zlib bytes: {}, {:.2}%", +// // compressed.len(), +// // (compressed.len() as f64) / (bytes.len() as f64) * 100.0 +// // ); + +// // println!("{:?}", bytes); + +// // let mut globals = Globals { +// // memory: SlotMap::default(), +// // contexts: FullContext::Split( +// // Box::new(FullContext::single(compiler.code.var_count)), +// // Box::new(FullContext::single(compiler.code.var_count)), +// // ), +// // }; + +// let mut globals = Globals::new(); +// globals.init(); + +// if let Err(e) = execute_code(&mut globals, &compiler.code) { +// e.raise(source, &globals); +// } +// } +// Err(e) => e.raise(source), +// } +// } +// Err(e) => { +// e.raise(source); +// } +// } +// } fn main() { - print!("\x1B[2J\x1B[1;1H"); + // print!("\x1B[2J\x1B[1;1H"); - io::stdout().flush().unwrap(); - let mut buf = PathBuf::new(); - buf.push("test.spwn"); - let code = fs::read_to_string(buf.clone()).unwrap(); - run(code, SpwnSource::File(buf)); + // io::stdout().flush().unwrap(); + // let mut buf = PathBuf::new(); + // buf.push("test.spwn"); + // let code = fs::read_to_string(buf.clone()).unwrap(); + // run(code, SpwnSource::File(buf)); // println!("{}", std::mem::size_of::()); } diff --git a/src/parser/ast.rs b/src/parser/ast.rs new file mode 100644 index 00000000..44d5488f --- /dev/null +++ b/src/parser/ast.rs @@ -0,0 +1,132 @@ +use crate::parser::lexer::Token; +use crate::sources::CodeArea; +use lasso::Spur; +use slotmap::{new_key_type, SecondaryMap, SlotMap}; + +use super::lexer::CodeSpan; + +new_key_type! { + pub struct ExprKey; + pub struct StmtKey; +} + +// just helper for ASTData::area +pub enum KeyType { + Expr(ExprKey), + StmtKey(StmtKey), +} + +// just helper for ASTData::area +pub trait ASTKey { + fn to_key(&self) -> KeyType; +} +impl ASTKey for ExprKey { + fn to_key(&self) -> KeyType { + KeyType::Expr(*self) + } +} +impl ASTKey for StmtKey { + fn to_key(&self) -> KeyType { + KeyType::StmtKey(*self) + } +} + +#[derive(Default)] +pub struct ASTData { + pub exprs: SlotMap, + pub stmts: SlotMap, + + pub stmt_arrows: SecondaryMap, + + pub for_loop_iter_areas: SecondaryMap, + pub func_arg_areas: SecondaryMap>, + + pub dictlike_areas: SecondaryMap>, +} + +#[derive(Debug, Clone)] +pub enum Expression { + Int(u64), + Byte(u8), + Float(f64), + String(String), + Bool(bool), + Op(ExprKey, Token, ExprKey), + Unary(Token, ExprKey), + Ident(Spur), + + Var(Spur), + Type(Spur), + + Array(Vec), + Dict(Vec<(Spur, Option)>), + + // Index { base: ExprKey, index: ExprKey }, + Empty, + + Block(Statements), + + Func { + args: Vec<(ExprKey, Option, Option)>, + ret_type: Option, + code: ExprKey, + }, + FuncPattern { + args: Vec, + ret_type: ExprKey, + }, + + Ternary { + cond: ExprKey, + if_true: ExprKey, + if_false: ExprKey, + }, + + Index { + base: ExprKey, + index: ExprKey, + }, + Call { + base: ExprKey, + params: Vec, + named_params: Vec<(ExprKey, ExprKey)>, + }, + TriggerFuncCall(ExprKey), + + Maybe(Option), + + TriggerFunc(Statements), + + Instance(ExprKey, Vec<(ExprKey, Option)>), + + Split(ExprKey, ExprKey), +} + +#[derive(Debug, Clone)] +pub enum Statement { + Expr(ExprKey), + Let(ExprKey, ExprKey), + Assign(ExprKey, ExprKey), + If { + branches: Vec<(ExprKey, Statements)>, + else_branch: Option, + }, + While { + cond: ExprKey, + code: Statements, + }, + For { + var: ExprKey, + iterator: ExprKey, + code: Statements, + }, + Return(Option), + Break, + Continue, + + TypeDef(ExprKey), + Impl(ExprKey, Vec<(ExprKey, ExprKey)>), + Print(ExprKey), +} + +pub type Statements = Vec; diff --git a/src/parser/error.rs b/src/parser/error.rs index 8d35e4af..7ad9f14a 100644 --- a/src/parser/error.rs +++ b/src/parser/error.rs @@ -50,3 +50,9 @@ error_maker! { }, } } + +impl SyntaxError { + pub fn wrap(self) -> Error { + Error::Syntax(self) + } +} diff --git a/src/parser/lexer.rs b/src/parser/lexer.rs index c4a3ef24..87fbb788 100644 --- a/src/parser/lexer.rs +++ b/src/parser/lexer.rs @@ -1,52 +1,26 @@ -use logos::Logos; +use std::str::Chars; +use std::{ops::Range, path::PathBuf}; -// // ew -// fn string_flag<'s>(tok: &mut logos::Lexer<'s, Token>) -> String { -// let sliced = tok.slice(); +use base64; +use lasso::{Rodeo, Spur}; +use logos::Logos; +use serde::{Deserialize, Serialize}; -// // get location of `"` or `'` in the token (end of string flag) -// // this will never be called on a string without a flag as a normal string has higher priority -// // so we can `.unwrap()` without issue +use super::ast::{ASTData, ExprKey, Expression}; -// let end = sliced.find("\"").unwrap_or_else(|| sliced.find("'").unwrap()); +const INVALID_CHARACTER: char = '\u{FFFD}'; // `�` -// let flag = &sliced[0..end]; -// let string = &sliced[end+1..sliced.len()]; +#[derive(Logos, Debug, PartialEq, Clone, Copy)] +#[logos(subpattern digits = r#"(\d)([\d_])*"#)] +pub enum Token { + #[regex(r#"(0[b])(?&digits)"#)] + Int, + #[regex(r#"(?&digits)(\.[\d_])*"#)] + Float, -// String::new() -// } + #[regex(r#""\w*((?:\\.|[^\\"])*"|'(?:\\.|[^\\'])*')"#)] + String, -#[derive(Logos, Debug, PartialEq, Clone)] -#[logos(subpattern string = r#""(?:\\.|[^\\"])*"|'(?:\\.|[^\\'])*'"#)] -#[logos(subpattern digits = r#"(\d)([\d_]+)?"#)] -pub enum Token { - #[regex(r#"(?&digits)"#, |lex| lex.slice().parse(), priority = 2)] - Int(usize), - #[regex(r#"(?&digits)(\.[\d_]+)?"#, |lex| lex.slice().parse(), priority = 1)] - Float(f64), - - // number literals don't match their correct values as their converted (and validated) in the parser - #[regex(r#"0b\w+"#, |lex| lex.slice().parse())] - BinaryLiteral(String), - #[regex(r#"0x\w+"#, |lex| lex.slice().parse())] - HexLiteral(String), - #[regex(r#"0o\w+"#, |lex| lex.slice().parse(), priority = 1)] - OctalLiteral(String), - - #[regex(r#"(?&string)"#, - //|s| convert_string(&s.slice()[1..s.slice().len()-1]), - |s| s.slice().parse(), - priority = 3 // prioritise normal string over string flags - )] - String(String), - - // #[regex(r#"_(\w*)?(?&string)"#, - // //|s| s.slice()[0..s.slice().find('"').unwrap_or_else(|| s.slice().find("'").unwrap())].parse(), // take up to `"` or `'` - // // |s| string_flag(s), - // |s| s.slice().parse(), - // priority = 1, - // )] - // StringFlag(String), #[token("let")] Let, #[token("mut")] @@ -128,6 +102,8 @@ pub enum Token { LBracket, #[token("}")] RBracket, + #[token("!{")] + TrigFnBracket, #[token(",")] Comma, @@ -163,11 +139,11 @@ pub enum Token { #[token("!")] ExclMark, - #[regex(r"@[a-zA-Z_]\w*", |lex| lex.slice()[1..].to_string())] - TypeIndicator(String), + #[regex(r"@[a-zA-Z_]\w*")] + TypeIndicator, - #[regex(r"[a-zA-Z_ඞ][a-zA-Z_0-9ඞ]*", |lex| lex.slice().to_string())] - Ident(String), + #[regex(r"[a-zA-Z_ඞ][a-zA-Z_0-9ඞ]*")] + Ident, #[regex(r"[ \t\f\n\r]+|/\*[^*]*\*(([^/\*][^\*]*)?\*)*/|//[^\n]*", logos::skip)] #[error] @@ -178,19 +154,16 @@ pub enum Token { impl Token { // used in error messages - pub fn tok_name(&self) -> String { + pub fn tok_name(&self) -> &str { match self { - Token::Int(v) => return v.to_string(), - Token::Float(v) => return v.to_string(), - Token::BinaryLiteral(b) => b, - Token::HexLiteral(h) => h, - Token::OctalLiteral(o) => o, - Token::String(v) => v, - Token::TypeIndicator(v) => return format!("@{}", v), + Token::Int => "int", + Token::Float => "float", + Token::String => "string", + Token::TypeIndicator => "type indicator", Token::Let => "let", Token::Mut => "mut", - Token::Ident(n) => n, - Token::Error => "unknown", + Token::Ident => "identifier", + Token::Error => "invalid", Token::Eof => "end of file", Token::True => "true", Token::False => "false", @@ -213,6 +186,7 @@ impl Token { Token::RSqBracket => "]", Token::LBracket => "{", Token::RBracket => "}", + Token::TrigFnBracket => "!{", Token::Comma => ",", Token::Eol => "end of line", Token::If => "if", @@ -242,7 +216,6 @@ impl Token { Token::Impl => "impl", //Token::StringFlag(v) => v, } - .into() } // also used in error messages pub fn tok_typ(&self) -> &str { @@ -253,19 +226,20 @@ impl Token { "operator" } - Int(_) | Float(_) | BinaryLiteral(_) | HexLiteral(_) | OctalLiteral(_) | String(_) - | True | False => "literal", + Int | Float | String | True | False => "literal", - Ident(_) => "identifier", + Ident => "identifier", Let | Mut | For | While | If | Else | In | Return | Break | Continue | TypeDef | Impl | Print | Split => "keyword", Error => "", - TypeIndicator(_) => "type indicator", + TypeIndicator => "type indicator", LParen | RParen | RSqBracket | LSqBracket | RBracket | LBracket | Comma | Colon - | DoubleColon | FatArrow | Arrow | QMark | ExclMark | Eol | Eof => "terminator", + | DoubleColon | FatArrow | Arrow | QMark | ExclMark | Eol | Eof | TrigFnBracket => { + "terminator" + } } } } @@ -273,6 +247,8 @@ impl Token { pub type Span = (usize, usize); pub type Tokens = Vec<(Token, Span)>; +const EOL: &[Token] = &[Token::Eol]; + pub fn lex(code: String) -> Tokens { let mut tokens_iter = Token::lexer(&code); @@ -284,3 +260,447 @@ pub fn lex(code: String) -> Tokens { tokens } + +#[derive(Clone)] +pub struct Lexer { + tokens: logos::Lexer<'static, Token>, + file: Option, +} + +use super::error::SyntaxError; +use crate::sources::CodeArea; +impl Lexer { + pub fn new, P: Into>(src: S, file: Option

) -> Self { + let src = unsafe { Lexer::make_static(src.as_ref()) }; + + let file = file.map(|p| p.into()); + let tokens = logos::Lexer::new(src); + + Lexer { tokens, file } + } + + pub fn next(&mut self) -> Option> { + let next_token = self.tokens.next()?; + let span = self.tokens.span(); + + Some(Spanned:: { + data: next_token, + span: span.into(), + }) + } + + pub fn peek(&mut self) -> Option> { + let tokens = self.clone(); + tokens.next() + } + + pub fn peek_many(&self, n: u32) -> Option> { + let mut tokens = self.clone(); + let last; + + for _ in 0..n { + last = tokens.next(); + } + + last + } + + pub fn expected_err( + &mut self, + expected: String, + found: Option>, + ) -> crate::error::Error { + let (tok_name, tok_typ, span) = if let Some(t) = found { + (t.data.tok_name(), t.data.tok_typ(), t.span) + } else { + ( + "end of file", + "", + (self.tokens.source().len()..self.tokens.source().len()).into(), + ) + }; + SyntaxError::Expected { + expected, + found: tok_name.into(), + typ: tok_typ.into(), + area: CodeArea { + span, + source: self.file, + }, + } + .wrap() + } + + pub fn expect(&mut self, expected: Token) -> crate::error::Result { + let next = self.next(); + if !matches!(next, Some(expected)) { + return Err(self.expected_err(expected.tok_name().into(), next)); + } + Ok(next.unwrap().span) + } + + pub fn slice(&self, span: CodeSpan) -> &str { + &self.tokens.source()[span.to_range()] + } + + pub fn make_area(&self, span: CodeSpan) -> CodeArea { + CodeArea { + span, + source: self.file, + } + } + + pub fn parse(&mut self) -> ASTData { + let mut data = ASTData::default(); + let r: Rodeo = Rodeo::new(); + todo!() + } + + pub fn parse_int(&mut self, ast_data: &mut ASTData) -> crate::error::Result { + let next_token = self.next().unwrap(); + + let span = next_token.span; + let src: &'static str = &self.tokens.source()[span.to_range()]; + + let int: u64 = match &src[0..2] { + "0x" => self.parse_int_radix(&src[2..], 16, span), + "0o" => self.parse_int_radix(&src[2..], 8, span), + "0b" => self.parse_int_radix(&src[2..], 2, span), + n if n.chars().all(char::is_numeric) => n.parse::().unwrap(), + other => { + return Err(SyntaxError::InvalidLiteral { + literal: other.to_string(), + area: CodeArea { + span, + source: self.file, + }, + } + .wrap()); + } + }; + Ok(ast_data.exprs.insert((Expression::Int(int), span))) + } + + pub fn parse_int_radix(&self, src: &str, radix: u32, span: CodeSpan) -> u64 { + u64::from_str_radix(src, radix).unwrap() + } + + pub fn parse_float(&mut self, ast_data: &mut ASTData) -> crate::error::Result { + let next_token = self.next().unwrap(); + + let span = next_token.span; + let src = &self.tokens.source()[span.to_range()]; + + Ok(ast_data + .exprs + .insert((Expression::Float(src.parse::().unwrap()), span))) + } + + pub fn parse_bool(&mut self, ast_data: &mut ASTData) -> crate::error::Result { + let next_token = self.next().unwrap(); + + let span = next_token.span; + let src = &self.tokens.source()[span.to_range()]; + + Ok(ast_data + .exprs + .insert((Expression::Bool(src.parse::().unwrap()), span))) + } + + pub fn parse_string(&mut self, ast_data: &mut ASTData) -> crate::error::Result { + let next_token = self.next().unwrap(); + + let span = next_token.span; + let src = &self.tokens.source()[span.to_range()]; + + let mut chars: Chars = src.chars(); + chars.next_back(); + + let flag = &*chars + .take_while(|c| !matches!(c, '"' | '\'')) + .collect::(); + + match flag { + "b" => { + let b_array = chars.collect::().as_bytes(); + let b_expr_array = b_array + .iter() + .map(|b| ast_data.exprs.insert((Expression::Byte(*b), span))) + .collect(); + + Ok(ast_data + .exprs + .insert((Expression::Array(b_expr_array), span))) + } + "r" => todo!("remove all escapes but \""), + "u" => { + // "Unindents the string" (wish me luck) + todo!() + } + "b64" => { + // yo problem, doesnt the chars iterator also have the final `"`? + let content = chars.collect::(); + let out_string = base64::encode(&content); + Ok(ast_data + .exprs + .insert((Expression::String(out_string), span))) + } + "" => { + let out_string: String = chars.collect(); + Ok(ast_data + .exprs + .insert((Expression::String(out_string), span))) + } + _ => todo!("Invalid string flag"), + } + } + + fn parse_escapes(&self, span: CodeSpan, string: String) -> crate::error::Result { + let mut out = String::new(); + let mut chars = string.chars(); + + loop { + match chars.next() { + Some('\\') => out.push(match chars.next() { + // afpdluih + Some('n') => '\n', + Some('r') => '\r', + Some('t') => '\t', + Some('"') => '"', + Some('\'') => '\'', + Some('\\') => '\\', + Some('u') => self.parse_unicode(span, &mut chars)?, + Some(c) => { + return Err(SyntaxError::InvalidEscape { + character: c, + area: self.make_area(span), + } + .wrap()) + } + + None => unreachable!(), + }), + Some(c) => out.push(c), + None => break, + } + } + + Ok(out) + } + + fn parse_unicode(&self, span: CodeSpan, chars: &mut Chars) -> crate::error::Result { + self.expect(Token::RBracket)?; + + let hex = chars + .take_while(|c| matches!(*c, '0'..='9' | 'a'..='f' | 'A'..='F')) + .collect::(); + + self.expect(Token::LBracket)?; + + Ok( + char::from_u32(self.parse_int_radix(&hex, 16, span) as u32) + .unwrap_or(INVALID_CHARACTER), + ) + } + + pub fn parse_identifier( + &mut self, + ast_data: &mut ASTData, + r: &mut Rodeo, + ) -> crate::error::Result { + let next_token = self.next().unwrap(); + + let span = next_token.span; + let src = &self.tokens.source()[span.to_range()]; + let s = r.get_or_intern(src); + + Ok(ast_data.exprs.insert((Expression::Ident(s), span))) + } + + pub fn parse_var_or_macro( + &mut self, + ast_data: &mut ASTData, + interner: &mut Rodeo, + ) -> crate::error::Result { + let span = self.next().unwrap().span; + let name = interner.get_or_intern(&self.tokens.source()[span.to_range()]); + + match self + .peek() + .unwrap_or_else(|| todo!("unexpected eof (syntax)")) + .data + { + Token::FatArrow => { + self.next(); + let code = self.parse_expr(ast_data, interner)?; + Ok(ast_data.exprs.insert(( + Expression::Func { + args: vec![(name.into(), None, None)], + ret_type: None, + code, + }, + span.start..ast_data.exprs[code].1, + ))) + } + _ => Ok(ast_data.exprs.insert((Expression::Var(name), span))), + } + } + + pub fn parse_type_indicator( + &mut self, + ast_data: &mut ASTData, + interner: &mut Rodeo, + ) -> crate::error::Result { + let next_token = self.next().unwrap(); + + let span = next_token.span; + let name = interner.get_or_intern(&self.tokens.source()[span.to_range()]); + + Ok(ast_data.exprs.insert((Expression::Type(name), span))) + } + + pub fn parse_macro( + &mut self, + ast_data: &mut ASTData, + interner: &mut Rodeo, + ) -> crate::error::Result { + self.next(); + let mut args = vec![]; + let mut arg_spans = vec![]; + while self.peek() != Token::RParen { + let ident = self.expect(Token::Ident)?; + let name = self.slice(ident); + + let arg_type = if self.peek() == Token::Colon { + self.next(); + Some(self.parse_expr(ast_data, interner)?) + } else { + None + }; + let arg_default = if self.peek() == Token::Assign { + self.next(); + Some(self.parse_expr(ast_data, interner)?) + } else { + None + }; + args.push((name.into(), arg_type, arg_default)); + arg_spans.push(ident); + if !matches!(self.peek(), Token::Comma | Token::RParen) { + return Err(self.expected_err(") or ,", self.next())); + } + } + } + + pub fn parse_paren_or_macro( + &mut self, + ast_data: &mut ASTData, + interner: &mut Rodeo, + ) -> crate::error::Result { + let depth = 0; + let check = self.clone(); + loop { + match check.next().unwrap_or_else(|| todo!("unmatched char")).data { + Token::LParen => depth += 1, + Token::RParen => { + depth -= 1; + if depth == 0 { + break; + } + } + _ => (), + } + } + let is_pattern; + match check.next() { + Token::FatArrow => is_pattern = false, + Token::Arrow => { + check.parse_expr(ast_data, interner)?; + is_pattern = matches!(check.next(), Token::FatArrow); + } + _ => { + self.next(); + let value = self.parse_expr(ast_data, interner)?; + self.expect(Token::RParen); + + return Ok(value); + } + } + if is_pattern { + self.parse_macro(ast_data, interner) + } else { + self.parse_macro_pattern(ast_data, interner) + } + } + + pub fn parse_expr( + &mut self, + ast_data: &mut ASTData, + interner: &mut Rodeo, + ) -> crate::error::Result { + match self + .peek() + .unwrap_or_else(|| todo!("unexpected eof (syntax)")) + .data + { + Token::Int => self.parse_int(ast_data), + Token::Float => self.parse_float(ast_data), + Token::True => { + let span = self.next().unwrap().span; + Ok(ast_data.exprs.insert((Expression::Bool(true), span))) + } + Token::False => { + let span = self.next().unwrap().span; + Ok(ast_data.exprs.insert((Expression::Bool(false), span))) + } + Token::String => self.parse_string(ast_data), + Token::Ident => self.parse_var_or_macro(ast_data, interner), + Token::TypeIndicator => self.parse_type_indicator(ast_data, interner), + Token::LParen => self.parse_type_indicator(ast_data, interner), + Token::LSqBracket => todo!(), + Token::LBracket => todo!(), + Token::QMark => todo!(), + Token::TrigFnBracket => todo!(), + Token::Split => todo!(), + _ => todo!(), + } + } + + /// Used to eliminate having 'a lifetime on Lexer + unsafe fn make_static<'a>(d: &'a str) -> &'static str { + std::mem::transmute::<&'a str, &'static str>(d) + } +} + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, Copy)] +pub struct CodeSpan { + start: usize, + end: usize, +} + +#[derive(PartialEq, Eq, Clone, Copy)] +pub struct Spanned { + data: T, + span: CodeSpan, +} + +impl CodeSpan { + pub fn len(&self) -> usize { + self.end - self.start + } + + pub fn to_range(self) -> Range { + self.into() + } +} + +impl From> for CodeSpan { + fn from(Range { start, end }: Range) -> Self { + Self { start, end } + } +} + +impl From for Range { + fn from(CodeSpan { start, end }: CodeSpan) -> Self { + start..end + } +} diff --git a/src/parser/mod.rs b/src/parser/mod.rs index 3bb36135..fa4f2115 100644 --- a/src/parser/mod.rs +++ b/src/parser/mod.rs @@ -1,4 +1,5 @@ -mod error; +pub mod ast; +pub mod error; pub mod lexer; -mod parse_util; -pub mod parser; +// mod parse_util; +// pub mod parser; diff --git a/src/parser/parse_util.rs b/src/parser/parse_util.rs index ae09b608..a9763fd8 100644 --- a/src/parser/parse_util.rs +++ b/src/parser/parse_util.rs @@ -8,39 +8,6 @@ use super::{ parser::{ASTData, ExprKey, ParseData}, }; -#[macro_export] -// deals with parsing escape characters in strings -macro_rules! escapes { - ( - $str:ident - $( - $c:ident:$rep:literal - ), - *) => {{ - let out = String::new(); - let chars = $str.chars(); - - match chars.next() { - Some('\\') => { - out.push(match chars.next() { - $( - Some(c) if c.to_string() == stringify!($c) => $rep - ),* - Some(a) => return Err(SyntaxError::InvalidEscape { - character: a, - area: - }) - None => unreachable!() - }) - }, - Some(c) => out.push(c), - None => {}, - } - - out - }} -} - #[macro_export] macro_rules! parse_util { ($parse_data:expr, $ast_data:expr, $pos:expr) => { diff --git a/src/parser/parser.rs b/src/parser/parser.rs index 4fa361a8..38a89abd 100644 --- a/src/parser/parser.rs +++ b/src/parser/parser.rs @@ -13,209 +13,7 @@ use crate::sources::{CodeArea, SpwnSource}; use super::parse_util::{operators, OpType}; -new_key_type! { - pub struct ExprKey; - pub struct StmtKey; -} - -// just helper for ASTData::area -pub enum KeyType { - Expr(ExprKey), - StmtKey(StmtKey), -} - -// just helper for ASTData::area -pub trait ASTKey { - fn to_key(&self) -> KeyType; -} -impl ASTKey for ExprKey { - fn to_key(&self) -> KeyType { - KeyType::Expr(*self) - } -} -impl ASTKey for StmtKey { - fn to_key(&self) -> KeyType { - KeyType::StmtKey(*self) - } -} - -#[derive(Default)] -pub struct ASTData { - pub exprs: SlotMap, - pub stmts: SlotMap, - - pub stmt_arrows: SecondaryMap, - - pub for_loop_iter_areas: SecondaryMap, - pub func_arg_areas: SecondaryMap>, - - pub dictlike_areas: SecondaryMap>, -} -impl ASTData { - // pub fn insert(&mut self, node: T, area: CodeArea) -> ASTKey { - // self.map.insert((Box::new(node), area)) - // } - pub fn get_area(&self, k: K) -> &CodeArea { - match k.to_key() { - KeyType::Expr(k) => &self.exprs[k].1, - KeyType::StmtKey(k) => &self.stmts[k].1, - } - } - pub fn get_expr(&self, k: ExprKey) -> Expression { - self.exprs[k].0.clone() - } - pub fn get_stmt(&self, k: StmtKey) -> Statement { - self.stmts[k].0.clone() - } - pub fn insert_expr(&mut self, expr: Expression, area: CodeArea) -> ExprKey { - self.exprs.insert((expr, area)) - } - pub fn insert_stmt(&mut self, stmt: Statement, area: CodeArea) -> StmtKey { - self.stmts.insert((stmt, area)) - } - - pub fn debug(&self, stmts: &Statements) { - let mut debug_str = String::new(); - use std::fmt::Write; - - debug_str += "-------- exprs --------\n"; - for (k, (e, _)) in &self.exprs { - writeln!(&mut debug_str, "{:?}:\t\t{:?}", k, e).unwrap(); - } - debug_str += "-------- stmts --------\n"; - for (k, (e, _)) in &self.stmts { - writeln!(&mut debug_str, "{:?}:\t\t{:?}", k, e).unwrap(); - } - debug_str += "-----------------------\n"; - - for i in stmts { - writeln!(&mut debug_str, "{:?}", i).unwrap(); - } - - let re = regex::Regex::new(r"(ExprKey\([^)]*\))").unwrap(); - debug_str = re - .replace_all( - &debug_str, - ansi_term::Color::Yellow.bold().paint("$1").to_string(), - ) - .into(); - let re = regex::Regex::new(r"(StmtKey\([^)]*\))").unwrap(); - debug_str = re - .replace_all( - &debug_str, - ansi_term::Color::Blue.bold().paint("$1").to_string(), - ) - .into(); - - println!("{}", debug_str); - } -} - -// holds immutable data relevant to parsing -pub struct ParseData { - pub tokens: Tokens, - pub source: SpwnSource, -} - -#[derive(Debug, Clone)] -pub enum Literal { - Int(usize), - Float(f64), - String(String), - Bool(bool), -} -impl Literal { - pub fn to_value(&self) -> Value { - match self { - Literal::Int(v) => Value::Int(*v as isize), - Literal::Float(v) => Value::Float(*v), - Literal::String(v) => Value::String(v.clone()), - Literal::Bool(v) => Value::Bool(*v), - } - } -} - -#[derive(Debug, Clone)] -pub enum Expression { - Literal(Literal), - Op(ExprKey, Token, ExprKey), - Unary(Token, ExprKey), - - Var(String), - Type(String), - - Array(Vec), - Dict(Vec<(String, Option)>), - - // Index { base: ExprKey, index: ExprKey }, - Empty, - - Block(Statements), - - Func { - args: Vec<(String, Option, Option)>, - ret_type: Option, - code: ExprKey, - }, - FuncPattern { - args: Vec, - ret_type: ExprKey, - }, - - Ternary { - cond: ExprKey, - if_true: ExprKey, - if_false: ExprKey, - }, - - Index { - base: ExprKey, - index: ExprKey, - }, - Call { - base: ExprKey, - params: Vec, - named_params: Vec<(String, ExprKey)>, - }, - TriggerFuncCall(ExprKey), - - Maybe(Option), - - TriggerFunc(Statements), - - Instance(ExprKey, Vec<(String, Option)>), - - Split(ExprKey, ExprKey), -} - -#[derive(Debug, Clone)] -pub enum Statement { - Expr(ExprKey), - Let(String, ExprKey), - Assign(String, ExprKey), - If { - branches: Vec<(ExprKey, Statements)>, - else_branch: Option, - }, - While { - cond: ExprKey, - code: Statements, - }, - For { - var: String, - iterator: ExprKey, - code: Statements, - }, - Return(Option), - Break, - Continue, - - TypeDef(String), - Impl(ExprKey, Vec<(String, ExprKey)>), - Print(ExprKey), -} - -pub type Statements = Vec; +const INVALID_CHARACTER: char = '\u{FFFD}'; // parses one unit value fn parse_unit( @@ -232,27 +30,6 @@ fn parse_unit( ast_data.insert_expr(Expression::Literal(Literal::Int(*n)), span_ar!(0)), pos + 1, )), - Token::BinaryLiteral(b) => Ok(( - ast_data.insert_expr( - Expression::Literal(Literal::Int(parse_number_radix(b, 2, "0b", span_ar!(0))?)), - span_ar!(0), - ), - pos + 1, - )), - Token::HexLiteral(h) => Ok(( - ast_data.insert_expr( - Expression::Literal(Literal::Int(parse_number_radix(h, 16, "0x", span_ar!(0))?)), - span_ar!(0), - ), - pos + 1, - )), - Token::OctalLiteral(o) => Ok(( - ast_data.insert_expr( - Expression::Literal(Literal::Int(parse_number_radix(o, 8, "0o", span_ar!(0))?)), - span_ar!(0), - ), - pos + 1, - )), Token::Float(n) => Ok(( ast_data.insert_expr(Expression::Literal(Literal::Float(*n)), span_ar!(0)), pos + 1, @@ -805,7 +582,8 @@ pub fn parse_statement( let stmt = match tok!(0) { Token::Let => { - pos += 1; + // + pos += 1; // here krista, sometimes you need to give a string check_tok!(Ident(var_name) else "variable name"); check_tok!(Assign else "="); parse!(parse_expr => let value); @@ -905,7 +683,6 @@ pub fn parse_statement( check_tok!(LBracket else "{"); let mut items = vec![]; - while_tok!(!= RBracket: { check_tok!(Ident(key) else "key"); check_tok!(Colon else ":"); @@ -982,7 +759,7 @@ fn parse_unicode(chars: &mut Chars, area: CodeArea) -> Result let hex = parse_number_radix(&out, 16, "", area)?; - Ok(char::from_u32(hex as u32).unwrap_or('�')) + Ok(char::from_u32(hex as u32).unwrap_or(INVALID_CHARACTER)) } // deals with parsing string escape sequences diff --git a/src/sources.rs b/src/sources.rs index 47d529b4..dc16b5e7 100644 --- a/src/sources.rs +++ b/src/sources.rs @@ -3,53 +3,30 @@ use std::path::PathBuf; use serde::{Deserialize, Serialize}; -use crate::parser::lexer::Span; - -#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, Hash)] -pub enum SpwnSource { - File(PathBuf), -} - -impl SpwnSource { - pub fn name(&self) -> String { - match self { - Self::File(f) => f.display().to_string(), - } - } - - pub fn contents(&self) -> String { - match self { - Self::File(f) => fs::read_to_string(f).unwrap(), // existance of file should have been already checked beforehand - } - } - - pub fn to_area(&self, span: (usize, usize)) -> CodeArea { - CodeArea { - source: self.clone(), - span, - } - } -} +use crate::parser::lexer::{CodeSpan, Span}; #[derive(Serialize, Deserialize, Debug, Clone, PartialEq)] pub struct CodeArea { - pub(crate) source: SpwnSource, - pub(crate) span: Span, + span: CodeSpan, + source: Option, } impl CodeArea { pub fn name(&self) -> String { - self.source.name() + match self.source { + Some(s) => s.display().to_string(), + None => "idfk", + } } pub fn label(&self) -> (String, std::ops::Range) { (self.name(), self.span.0..self.span.1) } - pub fn stretch(&self, other: &CodeArea) -> CodeArea { - CodeArea { - source: self.source.clone(), - span: (self.span.0, other.span.1), - } - } + // pub fn stretch(&self, other: &CodeArea) -> CodeArea { + // CodeArea { + // source: self.source.clone(), + // span: (self.span.0, other.span.1), + // } + // } }