Skip to content

Commit

Permalink
Use a KString instead of a PathBuf for the chunk's source path
Browse files Browse the repository at this point in the history
  • Loading branch information
irh committed Dec 4, 2024
1 parent 550bf34 commit b7bf074
Show file tree
Hide file tree
Showing 18 changed files with 125 additions and 130 deletions.
9 changes: 3 additions & 6 deletions crates/bytecode/src/chunk.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
use crate::InstructionReader;
use koto_memory::Ptr;
use koto_parser::{ConstantPool, Span};
use std::{
fmt::{self, Write},
path::PathBuf,
};
use koto_parser::{ConstantPool, KString, Span};
use std::fmt::{self, Write};

/// Debug information for a Koto program
#[derive(Clone, Debug, Default, PartialEq, Eq)]
Expand Down Expand Up @@ -56,7 +53,7 @@ pub struct Chunk {
/// The constant data associated with the chunk's bytecode
pub constants: ConstantPool,
/// The path of the program's source file
pub source_path: Option<PathBuf>,
pub source_path: Option<KString>,
/// Debug information associated with the chunk's bytecode
pub debug_info: DebugInfo,
}
Expand Down
71 changes: 35 additions & 36 deletions crates/bytecode/src/loader.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use crate::{Chunk, Compiler, CompilerError, CompilerSettings};
use dunce::canonicalize;
use koto_memory::Ptr;
use koto_parser::{format_source_excerpt, Parser, Span};
use koto_parser::{format_source_excerpt, KString, Parser, Span};
use rustc_hash::FxHasher;
use std::{
collections::HashMap,
Expand Down Expand Up @@ -46,14 +46,14 @@ pub struct LoaderErrorSource {
/// The span in the script where the error occurred
pub span: Span,
/// The script's path
pub path: Option<PathBuf>,
pub path: Option<KString>,
}

impl LoaderError {
pub(crate) fn from_parser_error(
error: koto_parser::Error,
source: &str,
source_path: Option<PathBuf>,
source_path: Option<KString>,
) -> Self {
let source = LoaderErrorSource {
contents: source.into(),
Expand All @@ -69,7 +69,7 @@ impl LoaderError {
pub(crate) fn from_compiler_error(
error: CompilerError,
source: &str,
source_path: Option<PathBuf>,
source_path: Option<KString>,
) -> Self {
let source = LoaderErrorSource {
contents: source.into(),
Expand Down Expand Up @@ -136,7 +136,7 @@ impl Loader {
pub fn compile_script(
&mut self,
script: &str,
script_path: Option<PathBuf>,
script_path: Option<KString>,
settings: CompilerSettings,
) -> Result<Ptr<Chunk>, LoaderError> {
match Parser::parse(script) {
Expand Down Expand Up @@ -164,39 +164,34 @@ impl Loader {
pub fn compile_module(
&mut self,
module_name: &str,
current_script_path: Option<&Path>,
current_script_path: Option<impl AsRef<Path>>,
) -> Result<CompileModuleResult, LoaderError> {
let mut load_module_from_path = |module_path: PathBuf| {
let module_path = module_path.canonicalize()?;
let module_path = find_module(module_name, current_script_path)?;

match self.chunks.get(&module_path) {
Some(chunk) => Ok(CompileModuleResult {
chunk: chunk.clone(),
match self.chunks.get(&module_path) {
Some(chunk) => Ok(CompileModuleResult {
chunk: chunk.clone(),
path: module_path,
loaded_from_cache: true,
}),
None => {
let script = std::fs::read_to_string(&module_path)?;

let chunk = self.compile_script(
&script,
Some(module_path.clone().into()),
CompilerSettings::default(),
)?;

self.chunks.insert(module_path.clone(), chunk.clone());

Ok(CompileModuleResult {
chunk,
path: module_path,
loaded_from_cache: true,
}),
None => {
let script = std::fs::read_to_string(&module_path)?;

let chunk = self.compile_script(
&script,
Some(module_path.clone()),
CompilerSettings::default(),
)?;

self.chunks.insert(module_path.clone(), chunk.clone());

Ok(CompileModuleResult {
chunk,
path: module_path,
loaded_from_cache: false,
})
}
loaded_from_cache: false,
})
}
};

let module_path = find_module(module_name, current_script_path)?;
load_module_from_path(module_path)
}
}

/// Clears the compiled module cache
Expand All @@ -217,7 +212,7 @@ pub struct CompileModuleResult {
/// provided then std::env::current_dir will be used.
pub fn find_module(
module_name: &str,
current_script_path: Option<&Path>,
current_script_path: Option<impl AsRef<Path>>,
) -> Result<PathBuf, LoaderError> {
// Get the directory of the provided script path, or the current working directory
let search_folder = match &current_script_path {
Expand All @@ -226,7 +221,10 @@ pub fn find_module(
if canonicalized.is_file() {
match canonicalized.parent() {
Some(parent_dir) => parent_dir.to_path_buf(),
None => return Err(LoaderErrorKind::FailedToGetPathParent(path.into()).into()),
None => {
let path = PathBuf::from(path.as_ref());
return Err(LoaderErrorKind::FailedToGetPathParent(path).into());
}
}
} else {
canonicalized
Expand All @@ -248,6 +246,7 @@ pub fn find_module(
.join("main")
.with_extension(extension);
if result.exists() {
let result = canonicalize(result)?;
Ok(result)
} else {
Err(LoaderErrorKind::UnableToFindModule(module_name.into()).into())
Expand Down
2 changes: 1 addition & 1 deletion crates/cli/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,7 @@ fn main() -> Result<()> {

match koto.compile(CompileArgs {
script: &script,
script_path: script_path.map(PathBuf::from),
script_path: script_path.map(KString::from),
compiler_settings: Default::default(),
}) {
Ok(chunk) => {
Expand Down
35 changes: 21 additions & 14 deletions crates/koto/examples/poetry/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -88,39 +88,46 @@ fn main() -> Result<()> {
.insert("poetry", koto_bindings::make_module());
koto.prelude().insert("random", koto_random::make_module());

let script_path = PathBuf::from(args.script);
let script_path = KString::from(args.script);

if args.watch {
if let Err(e) = compile_and_run(&mut koto, script_path.clone()) {
if let Err(e) = compile_and_run(&mut koto, &script_path) {
eprintln!("{e}");
}

let mut hotwatch = Hotwatch::new_with_custom_delay(Duration::from_secs_f64(0.25))
.context("Failed to initialize file watcher")?;
hotwatch
.watch(script_path.clone(), move |event: Event| {
match event.kind {
EventKind::Create(_) | EventKind::Modify(ModifyKind::Data(_)) => {
if let Err(error) = compile_and_run(&mut koto, script_path.clone()) {
eprintln!("{error}");
.watch(&script_path, {
let script_path = script_path.clone();
move |event: Event| {
match event.kind {
EventKind::Create(_) | EventKind::Modify(ModifyKind::Data(_)) => {
if let Err(error) = compile_and_run(&mut koto, &script_path) {
eprintln!("{error}");
}
}
_ => {}
}
_ => {}
Flow::Continue
}
Flow::Continue
})
.context("Failed to watch file!")?;
hotwatch.run();
Ok(())
} else {
compile_and_run(&mut koto, script_path.clone())
compile_and_run(&mut koto, &script_path)
}
}

fn compile_and_run(koto: &mut Koto, script_path: PathBuf) -> Result<()> {
let script = fs::read_to_string(&script_path)?;
koto.compile(CompileArgs::with_path(&script, script_path))
.context("Error while compiling script")?;
fn compile_and_run(koto: &mut Koto, script_path: &KString) -> Result<()> {
let script = fs::read_to_string(script_path.as_str())?;
koto.compile(CompileArgs {
script: &script,
script_path: Some(script_path.clone()),
compiler_settings: Default::default(),
})
.context("Error while compiling script")?;
koto.run().context("Error while running script")?;
Ok(())
}
8 changes: 4 additions & 4 deletions crates/koto/src/koto.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use crate::{prelude::*, Ptr, Result};
use koto_bytecode::CompilerSettings;
use koto_runtime::ModuleImportedCallback;
use std::{path::PathBuf, time::Duration};
use std::time::Duration;

/// The main interface for the Koto language.
///
Expand Down Expand Up @@ -275,17 +275,17 @@ pub struct CompileArgs<'a> {
///
/// The path provided here becomes accessible within the script via
/// `koto.script_path`/`koto.script_dir`.
pub script_path: Option<PathBuf>,
pub script_path: Option<KString>,
/// Settings used during compilation
pub compiler_settings: CompilerSettings,
}

impl<'a> CompileArgs<'a> {
/// A convenience initializer for when the script has been loaded from a path
pub fn with_path(script: &'a str, script_path: PathBuf) -> Self {
pub fn with_path(script: &'a str, script_path: impl Into<KString>) -> Self {
Self {
script,
script_path: Some(script_path),
script_path: Some(script_path.into()),
compiler_settings: Default::default(),
}
}
Expand Down
2 changes: 1 addition & 1 deletion crates/koto/tests/koto_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ fn run_script(script: &str, script_path: PathBuf, expected_module_paths: &[PathB

if let Err(error) = koto.compile(CompileArgs {
script,
script_path: Some(script_path),
script_path: Some(script_path.into()),
compiler_settings: Default::default(),
}) {
panic!("{error}");
Expand Down
17 changes: 6 additions & 11 deletions crates/parser/src/error.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use koto_lexer::Span;
use std::{fmt::Write, path::Path};
use std::fmt::Write;
use thiserror::Error;

use crate::string_format_options::StringFormatError;
Expand Down Expand Up @@ -245,7 +245,7 @@ impl Error {
pub type Result<T> = std::result::Result<T, Error>;

/// Renders the excerpt of the source corresponding to the given span
pub fn format_source_excerpt(source: &str, span: &Span, source_path: Option<&Path>) -> String {
pub fn format_source_excerpt(source: &str, span: &Span, source_path: Option<&str>) -> String {
let Span { start, end } = span;

let (excerpt, padding) = {
Expand Down Expand Up @@ -291,15 +291,10 @@ pub fn format_source_excerpt(source: &str, span: &Span, source_path: Option<&Pat
};

let position_info = if let Some(path) = source_path {
let display_path = if let Ok(current_dir) = std::env::current_dir() {
if let Ok(stripped) = path.strip_prefix(current_dir) {
stripped.display()
} else {
path.display()
}
} else {
path.display()
};
let display_path = std::env::current_dir()
.ok()
.and_then(|dir| dir.to_str().and_then(|dir_str| path.strip_prefix(dir_str)))
.unwrap_or(path);

format!("{display_path} - {}:{}", start.line + 1, start.column + 1)
} else {
Expand Down
2 changes: 2 additions & 0 deletions crates/parser/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ mod constant_pool;
mod error;
mod node;
mod parser;
mod string;
mod string_format_options;
mod string_slice;

Expand All @@ -16,6 +17,7 @@ pub use crate::{
error::{format_source_excerpt, Error, Result},
node::*,
parser::Parser,
string::KString,
string_format_options::{StringAlignment, StringFormatOptions},
string_slice::StringSlice,
};
Expand Down
33 changes: 17 additions & 16 deletions crates/runtime/src/types/string.rs → crates/parser/src/string.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
use crate::{prelude::*, Ptr, Result};
use koto_parser::StringSlice;
use crate::StringSlice;
use koto_memory::Ptr;
use std::{
fmt,
hash::{Hash, Hasher},
ops::{Deref, Range},
path::{Path, PathBuf},
str::from_utf8_unchecked,
};
use unicode_segmentation::UnicodeSegmentation;
Expand All @@ -26,8 +27,8 @@ enum Inner {
Full(Ptr<str>),
// A heap-allocated string with bounds
//
// By heap-allocating the slice bounds we can keep the size of KString below 24 bytes,
// which is the maximum allowed by KValue.
// By heap-allocating the slice bounds we can keep the size of `KString` below 24 bytes,
// which is the maximum allowed by `koto_runtime::KValue`.
Slice(Ptr<StringSlice>),
}

Expand Down Expand Up @@ -164,18 +165,6 @@ impl KString {
Inner::Slice(slice) => slice,
}
}

/// Renders the string to the provided display context
pub fn display(&self, ctx: &mut DisplayContext) -> Result<()> {
if ctx.is_contained() {
ctx.append('\'');
ctx.append(self);
ctx.append('\'');
} else {
ctx.append(self);
}
Ok(())
}
}

impl Default for KString {
Expand Down Expand Up @@ -220,6 +209,12 @@ impl From<&str> for KString {
}
}

impl From<PathBuf> for KString {
fn from(path: PathBuf) -> Self {
Self::from(path.to_string_lossy().to_string())
}
}

impl PartialEq<&str> for KString {
fn eq(&self, other: &&str) -> bool {
self.as_str() == *other
Expand Down Expand Up @@ -253,6 +248,12 @@ impl AsRef<str> for KString {
}
}

impl AsRef<Path> for KString {
fn as_ref(&self) -> &Path {
Path::new(self.as_str())
}
}

impl fmt::Display for KString {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str(self.as_str())
Expand Down
Loading

0 comments on commit b7bf074

Please sign in to comment.