Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 13 additions & 13 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

24 changes: 15 additions & 9 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,16 +16,16 @@ license = "MIT"
repository = "https://github.com/kyren/piccolo"

[workspace.dependencies]
ahash = "0.8"
allocator-api2 = "0.2"
anyhow = "1.0"
gc-arena = { git = "https://github.com/kyren/gc-arena", rev = "5a7534b883b703f23cfb8c3cfdf033460aa77ea9", features = ["allocator-api2", "hashbrown"] }
ahash = { version = "0.8", default-features = false }
allocator-api2 = { version = "0.2", default-features = false, features = ["alloc"] }
anyhow = { version = "1.0.87", default-features = false }
gc-arena = { git = "https://github.com/kyren/gc-arena", rev = "4d526347a9b625c29e16f7165fd998615e51c52a", default-features = false, features = ["allocator-api2", "hashbrown"] }
hashbrown = { version = "0.14", features = ["raw"] }
rand = { version = "0.8", features = ["small_rng"] }
serde = "1.0"
thiserror = "1.0"
rand = { version = "0.8", default-features = false, features = ["small_rng"] }
serde = { version = "1.0", default-features = false, features = ["alloc"] }
thiserror = { version = "2.0", default-features = false }

piccolo = { path = "./", version = "0.3.3" }
piccolo = { path = "./", version = "0.3.3", default-features = false }

[package]
name = "piccolo"
Expand All @@ -43,9 +43,15 @@ allocator-api2.workspace = true
anyhow.workspace = true
gc-arena.workspace = true
hashbrown.workspace = true
rand.workspace = true
thiserror.workspace = true

rand = { workspace = true, optional = true }

[dev-dependencies]
clap = { version = "4.5", features = ["cargo"] }
rustyline = "14.0"

[features]
default = ["std", "rng"]
rng = ["dep:rand", "ahash/runtime-rng"]
std = ["rand?/std"]
10 changes: 6 additions & 4 deletions examples/compiler.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use std::{error::Error as StdError, fs::File};
use std::{error::Error as StdError, fs::File, io::Read};

use clap::{crate_description, crate_name, crate_version, Arg, Command};

Expand Down Expand Up @@ -75,15 +75,17 @@ fn main() -> Result<(), Box<dyn StdError>> {
)
.get_matches();

let file = io::buffered_read(File::open(matches.get_one::<String>("file").unwrap())?)?;
let mut file = io::buffered_read(File::open(matches.get_one::<String>("file").unwrap())?)?;
let mut source = Vec::new();
file.read_to_end(&mut source)?;

let mut interner = BasicInterner::default();

if matches.contains_id("parse") {
let chunk = compiler::parse_chunk(file, &mut interner)?;
let chunk = compiler::parse_chunk(&source, &mut interner)?;
println!("{:#?}", chunk);
} else {
let chunk = compiler::parse_chunk(file, &mut interner)?;
let chunk = compiler::parse_chunk(&source, &mut interner)?;
let prototype = compiler::compile_chunk(&chunk, &mut interner)?;
print_function(&prototype, 0);
}
Expand Down
7 changes: 5 additions & 2 deletions examples/execute.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
use std::fs::File;
use std::io::Read;

use piccolo::{io::buffered_read, Closure, Executor, Lua};

fn main() -> Result<(), Box<dyn std::error::Error>> {
// Load the Lua file
let file = buffered_read(File::open("./examples/execute.lua")?)?;
let mut file = buffered_read(File::open("./examples/execute.lua")?)?;
let mut source = Vec::new();
file.read_to_end(&mut source)?;

// Instantiate the Lua instance
let mut lua = Lua::full();
Expand All @@ -14,7 +17,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
// Get the global env
let env = ctx.globals();
// Run the lua script in the global context
let closure = Closure::load_with_env(ctx, None, file, env)?;
let closure = Closure::load_with_env(ctx, None, &*source, env)?;
// Create an executor that will run the lua script
let ex = Executor::start(ctx, closure.into(), ());

Expand Down
8 changes: 5 additions & 3 deletions examples/interpreter.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use std::error::Error as StdError;
use std::fs::File;
use std::{error::Error as StdError, io::Read};

use clap::{crate_description, crate_name, crate_version, Arg, Command};
use rustyline::DefaultEditor;
Expand Down Expand Up @@ -107,10 +107,12 @@ fn main() -> Result<(), Box<dyn StdError>> {
}

let file_name = matches.get_one::<String>("file").unwrap();
let file = io::buffered_read(File::open(file_name)?)?;
let mut file = io::buffered_read(File::open(file_name)?)?;
let mut source = Vec::new();
file.read_to_end(&mut source)?;

let executor = lua.try_enter(|ctx| {
let closure = Closure::load(ctx, Some(file_name.as_str()), file)?;
let closure = Closure::load(ctx, Some(file_name.as_str()), &source)?;
Ok(ctx.stash(Executor::start(ctx, closure.into(), ())))
})?;

Expand Down
2 changes: 1 addition & 1 deletion src/any.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use std::{
use core::{
any::TypeId,
fmt,
hash::{Hash, Hasher},
Expand Down
4 changes: 2 additions & 2 deletions src/async_callback.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
use std::{
use alloc::rc::Rc;
use core::{
cell::Cell,
future::{poll_fn, Future},
marker::PhantomData,
mem,
pin::Pin,
ptr,
rc::Rc,
task::{self, Poll, RawWaker, RawWakerVTable, Waker},
};

Expand Down
2 changes: 1 addition & 1 deletion src/callback.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use std::{
use core::{
fmt,
hash::{Hash, Hasher},
pin::Pin,
Expand Down
11 changes: 4 additions & 7 deletions src/closure.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,4 @@
use std::{
hash::{Hash, Hasher},
io::Read,
};
use core::hash::{Hash, Hasher};

use allocator_api2::{boxed, vec, SliceExt};
use gc_arena::{allocator_api::MetricsAlloc, lock::Lock, Collect, Gc, Mutation};
Expand Down Expand Up @@ -115,7 +112,7 @@ impl<'gc> FunctionPrototype<'gc> {
pub fn compile(
ctx: Context<'gc>,
source_name: &str,
source: impl Read,
source: &[u8],
) -> Result<FunctionPrototype<'gc>, CompilerError> {
#[derive(Copy, Clone)]
struct Interner<'gc>(Context<'gc>);
Expand Down Expand Up @@ -261,7 +258,7 @@ impl<'gc> Closure<'gc> {
pub fn load(
ctx: Context<'gc>,
name: Option<&str>,
source: impl Read,
source: &[u8],
) -> Result<Closure<'gc>, CompilerError> {
Self::load_with_env(ctx, name, source, ctx.globals())
}
Expand All @@ -270,7 +267,7 @@ impl<'gc> Closure<'gc> {
pub fn load_with_env(
ctx: Context<'gc>,
name: Option<&str>,
source: impl Read,
source: &[u8],
env: Table<'gc>,
) -> Result<Closure<'gc>, CompilerError> {
let proto = FunctionPrototype::compile(ctx, name.unwrap_or("<anonymous>"), source)?;
Expand Down
9 changes: 4 additions & 5 deletions src/compiler/compiler.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
use std::{
collections::{hash_map, VecDeque},
fmt, iter, mem,
};
use alloc::{boxed::Box, collections::VecDeque, vec, vec::Vec};
use core::{fmt, iter, mem};
use hashbrown::hash_map;

use ahash::HashMap;
use gc_arena::Collect;
use hashbrown::HashMap;
use thiserror::Error;

use crate::{
Expand Down
4 changes: 2 additions & 2 deletions src/compiler/interning.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use std::rc::Rc;
use alloc::{boxed::Box, rc::Rc};

use ahash::HashSet;
use hashbrown::HashSet;

pub trait StringInterner {
type String: AsRef<[u8]> + Clone;
Expand Down
57 changes: 16 additions & 41 deletions src/compiler/lexer.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
use std::{
char, fmt,
io::{self, Read},
};
use alloc::vec::Vec;
use core::{char, fmt};

use gc_arena::Collect;
use thiserror::Error;
Expand Down Expand Up @@ -242,8 +240,6 @@ pub enum LexError {
UnfinishedLongString,
#[error("malformed number")]
BadNumber,
#[error("IO Error: {0}")]
IOError(#[from] io::Error),
}

/// A 0-indexed line number of the current source input.
Expand All @@ -257,24 +253,23 @@ impl fmt::Display for LineNumber {
}
}

pub struct Lexer<R, S> {
source: Option<R>,
pub struct Lexer<'a, S> {
source: &'a [u8],
interner: S,
peek_buffer: Vec<u8>,
peek_count: usize,
string_buffer: Vec<u8>,
line_number: u64,
}

impl<R, S> Lexer<R, S>
impl<'a, S> Lexer<'a, S>
where
R: Read,
S: StringInterner,
{
pub fn new(source: R, interner: S) -> Lexer<R, S> {
pub fn new(source: &'a [u8], interner: S) -> Lexer<'a, S> {
Lexer {
source: Some(source),
source,
interner,
peek_buffer: Vec::new(),
peek_count: 0,
string_buffer: Vec::new(),
line_number: 0,
}
Expand Down Expand Up @@ -506,8 +501,8 @@ where

// End of stream encountered, clear any input handles and temp buffers
fn reset(&mut self) {
self.source = None;
self.peek_buffer.clear();
self.source = &[];
self.peek_count = 0;
self.string_buffer.clear();
}

Expand Down Expand Up @@ -855,36 +850,16 @@ where
}

fn peek(&mut self, n: usize) -> Result<Option<u8>, LexError> {
if let Some(source) = self.source.as_mut() {
while self.peek_buffer.len() <= n {
let mut c = [0];
match source.read(&mut c) {
Ok(0) => {
self.source = None;
break;
}
Ok(_) => {
self.peek_buffer.push(c[0]);
}
Err(e) => {
if e.kind() != io::ErrorKind::Interrupted {
self.source = None;
return Err(LexError::IOError(e));
}
}
}
}
}

Ok(self.peek_buffer.get(n).copied())
self.peek_count = (n + 1).min(self.source.len());
Ok(self.source.get(n).copied())
}

fn advance(&mut self, n: usize) {
assert!(
n <= self.peek_buffer.len(),
n <= self.peek_count,
"cannot advance over un-peeked characters"
);
self.peek_buffer.drain(0..n);
self.source = &self.source[n..];
}

fn take_string(&mut self) -> S::String {
Expand Down Expand Up @@ -945,7 +920,7 @@ fn get_reserved_word_token<S>(word: &[u8]) -> Option<Token<S>> {

#[cfg(test)]
mod tests {
use std::rc::Rc;
use alloc::rc::Rc;

use crate::compiler::interning::BasicInterner;

Expand Down
Loading