mirror of
https://github.com/ProvableHQ/leo.git
synced 2024-11-22 22:44:47 +03:00
merge testnet3
This commit is contained in:
commit
d397c750d2
@ -16,7 +16,7 @@
|
||||
|
||||
use crate::Program;
|
||||
|
||||
use leo_span::Symbol;
|
||||
use leo_span::{symbol::with_session_globals, Symbol};
|
||||
|
||||
use indexmap::IndexMap;
|
||||
use serde::{Deserialize, Deserializer, Serialize, Serializer};
|
||||
@ -26,13 +26,18 @@ pub fn serialize<S: Serializer>(
|
||||
imported_modules: &IndexMap<Vec<Symbol>, Program>,
|
||||
serializer: S,
|
||||
) -> Result<S::Ok, S::Error> {
|
||||
let joined: IndexMap<String, Program> = imported_modules
|
||||
.into_iter()
|
||||
.map(|(package, program)| {
|
||||
let package = package.iter().map(|x| x.as_str().to_string()).collect::<Vec<_>>();
|
||||
(package.join("."), program.clone())
|
||||
})
|
||||
.collect();
|
||||
let joined: IndexMap<String, Program> = with_session_globals(|s| {
|
||||
imported_modules
|
||||
.into_iter()
|
||||
.map(|(package, program)| {
|
||||
let package = package
|
||||
.iter()
|
||||
.map(|x| x.as_str(s, |s| s.to_owned()))
|
||||
.collect::<Vec<_>>();
|
||||
(package.join("."), program.clone())
|
||||
})
|
||||
.collect()
|
||||
});
|
||||
|
||||
joined.serialize(serializer)
|
||||
}
|
||||
|
@ -31,7 +31,7 @@ pub struct TernaryExpression {
|
||||
|
||||
impl fmt::Display for TernaryExpression {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "if {} ? {} : {}", self.condition, self.if_true, self.if_false)
|
||||
write!(f, "({} ? {} : {})", self.condition, self.if_true, self.if_false)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -20,6 +20,7 @@
|
||||
//! The [`Ast`] type is intended to be parsed and modified by different passes
|
||||
//! of the Leo compiler. The Leo compiler can generate a set of R1CS constraints from any [`Ast`].
|
||||
|
||||
#![forbid(unsafe_code)]
|
||||
#![doc = include_str!("../README.md")]
|
||||
pub mod access;
|
||||
pub use self::access::*;
|
||||
|
@ -14,6 +14,7 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
#![forbid(unsafe_code)]
|
||||
#![allow(clippy::module_inception)]
|
||||
#![allow(clippy::upper_case_acronyms)]
|
||||
#![doc = include_str!("../README.md")]
|
||||
|
@ -14,6 +14,7 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
#![forbid(unsafe_code)]
|
||||
#![doc = include_str!("../README.md")]
|
||||
|
||||
mod algorithms;
|
||||
|
@ -14,6 +14,8 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
#![forbid(unsafe_code)]
|
||||
|
||||
use leo_errors::{emitter::Handler, Result};
|
||||
use leo_span::symbol::create_session_if_not_set_then;
|
||||
|
||||
|
@ -14,6 +14,8 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
#![forbid(unsafe_code)]
|
||||
|
||||
use leo_ast::Ast;
|
||||
use leo_errors::emitter::Handler;
|
||||
use leo_span::symbol::create_session_if_not_set_then;
|
||||
|
@ -19,6 +19,7 @@
|
||||
//! This module contains the [`parse_ast()`] method which calls the underlying [`parse()`]
|
||||
//! method to create a new program ast.
|
||||
|
||||
#![forbid(unsafe_code)]
|
||||
#![allow(clippy::vec_init_then_push)]
|
||||
#![doc = include_str!("../README.md")]
|
||||
|
||||
|
@ -283,7 +283,7 @@ impl ParserContext<'_> {
|
||||
|
||||
// TODO: Verify that this check is sound.
|
||||
// Check that there is no whitespace in between the `@` symbol and identifier.
|
||||
match identifier.span.hi.0 - start.lo.0 > 1 + identifier.name.as_str().len() as u32 {
|
||||
match identifier.span.hi.0 - start.lo.0 > 1 + identifier.name.to_string().len() as u32 {
|
||||
true => Err(ParserError::space_in_annotation(span).into()),
|
||||
false => Ok(Annotation { identifier, span }),
|
||||
}
|
||||
|
@ -14,6 +14,7 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
#![forbid(unsafe_code)]
|
||||
#![doc = include_str!("../README.md")]
|
||||
|
||||
pub mod code_generation;
|
||||
|
@ -50,14 +50,15 @@ impl ProgramReconstructor for StaticSingleAssigner<'_> {
|
||||
.fold(last_return_expression, |acc, (guard, expr)| match guard {
|
||||
None => unreachable!("All return statements except for the last one must have a guard."),
|
||||
// Note that type checking guarantees that all expressions in return statements in the function body have the same type.
|
||||
Some(guard) => match (acc, expr) {
|
||||
Some(guard) => match (expr, acc) {
|
||||
// If the function returns tuples, fold the return expressions into a tuple of ternary expressions.
|
||||
(Expression::Tuple(acc_tuple), Expression::Tuple(expr_tuple)) => {
|
||||
// Note that `expr` and `acc` are correspond to the `if` and `else` cases of the ternary expression respectively.
|
||||
(Expression::Tuple(expr_tuple), Expression::Tuple(acc_tuple)) => {
|
||||
Expression::Tuple(TupleExpression {
|
||||
elements: acc_tuple
|
||||
elements: expr_tuple
|
||||
.elements
|
||||
.into_iter()
|
||||
.zip_eq(expr_tuple.elements.into_iter())
|
||||
.zip_eq(acc_tuple.elements.into_iter())
|
||||
.map(|(if_true, if_false)| {
|
||||
Expression::Ternary(TernaryExpression {
|
||||
condition: Box::new(guard.clone()),
|
||||
@ -71,10 +72,11 @@ impl ProgramReconstructor for StaticSingleAssigner<'_> {
|
||||
})
|
||||
}
|
||||
// Otherwise, fold the return expressions into a single ternary expression.
|
||||
(acc, expr) => Expression::Ternary(TernaryExpression {
|
||||
// Note that `expr` and `acc` are correspond to the `if` and `else` cases of the ternary expression respectively.
|
||||
(expr, acc) => Expression::Ternary(TernaryExpression {
|
||||
condition: Box::new(guard),
|
||||
if_true: Box::new(acc),
|
||||
if_false: Box::new(expr),
|
||||
if_true: Box::new(expr),
|
||||
if_false: Box::new(acc),
|
||||
span: Default::default(),
|
||||
}),
|
||||
},
|
||||
|
@ -38,6 +38,7 @@ pub struct StaticSingleAssigner<'a> {
|
||||
/// A stack of condition `Expression`s visited up to the current point in the AST.
|
||||
pub(crate) condition_stack: Vec<Expression>,
|
||||
/// A list containing tuples of guards and expressions associated with early `ReturnStatement`s.
|
||||
/// Note that early returns are inserted in the order they are encountered during a pre-order traversal of the AST.
|
||||
pub(crate) early_returns: Vec<(Option<Expression>, Expression)>,
|
||||
}
|
||||
|
||||
|
@ -1,175 +0,0 @@
|
||||
// Copyright (C) 2019-2022 Aleo Systems Inc.
|
||||
// This file is part of the Leo library.
|
||||
|
||||
// The Leo library is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
|
||||
// The Leo library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
// Copyright Rust project developers under MIT or APACHE-2.0.
|
||||
|
||||
use core::alloc::Layout;
|
||||
use core::cell::{Cell, RefCell};
|
||||
use core::mem::{self, MaybeUninit};
|
||||
use core::{cmp, ptr, slice};
|
||||
use std::iter;
|
||||
|
||||
// The arenas start with PAGE-sized chunks, and then each new chunk is twice as
|
||||
// big as its predecessor, up until we reach HUGE_PAGE-sized chunks, whereupon
|
||||
// we stop growing. This scales well, from arenas that are barely used up to
|
||||
// arenas that are used for 100s of MiBs. Note also that the chosen sizes match
|
||||
// the usual sizes of pages and huge pages on Linux.
|
||||
const PAGE: usize = 4096;
|
||||
const HUGE_PAGE: usize = 2 * 1024 * 1024;
|
||||
|
||||
pub struct DroplessArena {
|
||||
/// A pointer to the start of the free space.
|
||||
start: Cell<*mut u8>,
|
||||
|
||||
/// A pointer to the end of free space.
|
||||
///
|
||||
/// The allocation proceeds from the end of the chunk towards the start.
|
||||
/// When this pointer crosses the start pointer, a new chunk is allocated.
|
||||
end: Cell<*mut u8>,
|
||||
|
||||
/// A vector of arena chunks.
|
||||
chunks: RefCell<Vec<TypedArenaChunk<u8>>>,
|
||||
}
|
||||
|
||||
unsafe impl Send for DroplessArena {}
|
||||
|
||||
impl Default for DroplessArena {
|
||||
#[inline]
|
||||
fn default() -> DroplessArena {
|
||||
DroplessArena {
|
||||
start: Cell::new(ptr::null_mut()),
|
||||
end: Cell::new(ptr::null_mut()),
|
||||
chunks: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl DroplessArena {
|
||||
#[inline(never)]
|
||||
#[cold]
|
||||
fn grow(&self, additional: usize) {
|
||||
unsafe {
|
||||
let mut chunks = self.chunks.borrow_mut();
|
||||
|
||||
let new_cap = if let Some(last_chunk) = chunks.last_mut() {
|
||||
// If the previous chunk's len is less than HUGE_PAGE bytes,
|
||||
// then this chunk will be at least double the previous chunk's size.
|
||||
last_chunk.storage.len().min(HUGE_PAGE / 2) * 2
|
||||
} else {
|
||||
PAGE
|
||||
};
|
||||
// Also ensure that this chunk can fit `additional`.
|
||||
let new_cap = cmp::max(additional, new_cap);
|
||||
|
||||
let mut chunk = TypedArenaChunk::<u8>::new(new_cap);
|
||||
self.start.set(chunk.start());
|
||||
self.end.set(chunk.end());
|
||||
chunks.push(chunk);
|
||||
}
|
||||
}
|
||||
|
||||
/// Allocates a byte slice with specified layout from the current memory chunk.
|
||||
/// Returns `None` if there is no free space left to satisfy the request.
|
||||
#[inline]
|
||||
fn alloc_raw_without_grow(&self, layout: Layout) -> Option<*mut u8> {
|
||||
let start = self.start.get() as usize;
|
||||
let end = self.end.get() as usize;
|
||||
|
||||
let align = layout.align();
|
||||
let bytes = layout.size();
|
||||
|
||||
let new_end = end.checked_sub(bytes)? & !(align - 1);
|
||||
if start <= new_end {
|
||||
let new_end = new_end as *mut u8;
|
||||
self.end.set(new_end);
|
||||
Some(new_end)
|
||||
} else {
|
||||
// There's no more space since we're growing towards the start.
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn alloc_raw(&self, layout: Layout) -> *mut u8 {
|
||||
assert!(layout.size() != 0);
|
||||
loop {
|
||||
if let Some(a) = self.alloc_raw_without_grow(layout) {
|
||||
break a;
|
||||
}
|
||||
// No free space left. Allocate a new chunk to satisfy the request.
|
||||
// On failure the grow will panic or abort.
|
||||
self.grow(layout.size());
|
||||
}
|
||||
}
|
||||
|
||||
/// Allocates a slice of objects that are copied into the `DroplessArena`,
|
||||
/// returning a mutable reference to it.
|
||||
/// Will panic if passed a zero-sized type.
|
||||
///
|
||||
/// Panics:
|
||||
///
|
||||
/// - Zero-sized types
|
||||
/// - Zero-length slices
|
||||
#[inline]
|
||||
#[allow(clippy::mut_from_ref)]
|
||||
pub fn alloc_slice<T: Copy>(&self, slice: &[T]) -> &mut [T] {
|
||||
assert!(!mem::needs_drop::<T>());
|
||||
assert!(mem::size_of::<T>() != 0);
|
||||
assert!(!slice.is_empty());
|
||||
|
||||
let mem = self.alloc_raw(Layout::for_value::<[T]>(slice)) as *mut T;
|
||||
|
||||
unsafe {
|
||||
mem.copy_from_nonoverlapping(slice.as_ptr(), slice.len());
|
||||
slice::from_raw_parts_mut(mem, slice.len())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct TypedArenaChunk<T> {
|
||||
/// The raw storage for the arena chunk.
|
||||
storage: Box<[MaybeUninit<T>]>,
|
||||
}
|
||||
|
||||
impl<T> TypedArenaChunk<T> {
|
||||
#[inline]
|
||||
unsafe fn new(capacity: usize) -> TypedArenaChunk<T> {
|
||||
TypedArenaChunk {
|
||||
// HACK(Centril) around `Box::new_uninit_slice` not being stable.
|
||||
storage: iter::repeat_with(MaybeUninit::<T>::uninit).take(capacity).collect(),
|
||||
}
|
||||
}
|
||||
|
||||
// Returns a pointer to the first allocated object.
|
||||
#[inline]
|
||||
fn start(&mut self) -> *mut T {
|
||||
// HACK(Centril) around `MaybeUninit::slice_as_mut_ptr` not being stable.
|
||||
self.storage.as_mut_ptr() as *mut T
|
||||
}
|
||||
|
||||
// Returns a pointer to the end of the allocated space.
|
||||
#[inline]
|
||||
fn end(&mut self) -> *mut T {
|
||||
unsafe {
|
||||
if mem::size_of::<T>() == 0 {
|
||||
// A pointer as large as possible for zero-sized elements.
|
||||
!0 as *mut T
|
||||
} else {
|
||||
self.start().add(self.storage.len())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -14,7 +14,7 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
mod dropless;
|
||||
#![forbid(unsafe_code)]
|
||||
|
||||
pub mod symbol;
|
||||
pub use symbol::{sym, Symbol};
|
||||
|
@ -368,12 +368,10 @@ fn normalize_newlines(src: &mut String) {
|
||||
}
|
||||
|
||||
// Account for removed `\r`.
|
||||
// After `set_len`, `buf` is guaranteed to contain utf-8 again.
|
||||
// After `buf.truncate(..)`, `buf` is guaranteed to contain utf-8 again.
|
||||
let new_len = buf.len() - gap_len;
|
||||
unsafe {
|
||||
buf.set_len(new_len);
|
||||
*src = String::from_utf8_unchecked(buf);
|
||||
}
|
||||
buf.truncate(new_len);
|
||||
*src = String::from_utf8(buf).unwrap();
|
||||
|
||||
fn find_crlf(src: &[u8]) -> Option<usize> {
|
||||
let mut search_idx = 0;
|
||||
@ -414,9 +412,8 @@ fn analyze_source_file(src: &str, source_file_start_pos: BytePos) -> (Vec<BytePo
|
||||
let src_bytes = src.as_bytes();
|
||||
|
||||
while i < src.len() {
|
||||
// SAFETY: We verified that i < src.len().
|
||||
let i_usize = i as usize;
|
||||
let byte = unsafe { *src_bytes.get_unchecked(i_usize) };
|
||||
let byte = src_bytes[i_usize];
|
||||
|
||||
// How much to advance to get to the next UTF-8 char in the string.
|
||||
let mut char_len = 1;
|
||||
|
@ -14,11 +14,11 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use crate::dropless::DroplessArena;
|
||||
use crate::source_map::SourceMap;
|
||||
|
||||
use core::borrow::Borrow;
|
||||
use core::cmp::PartialEq;
|
||||
use core::convert::AsRef;
|
||||
use core::hash::{Hash, Hasher};
|
||||
use core::num::NonZeroU32;
|
||||
use core::ops::Deref;
|
||||
use core::{fmt, str};
|
||||
@ -26,8 +26,6 @@ use fxhash::FxBuildHasher;
|
||||
use indexmap::IndexSet;
|
||||
use serde::{Deserialize, Deserializer, Serialize, Serializer};
|
||||
use std::cell::RefCell;
|
||||
use std::intrinsics::transmute;
|
||||
use std::marker::PhantomData;
|
||||
|
||||
/// A helper for `symbols` defined below.
|
||||
/// The macro's job is to bind conveniently usable `const` items to the symbol names provided.
|
||||
@ -241,8 +239,10 @@ impl Symbol {
|
||||
/// Returns the corresponding `Symbol` for the given `index`.
|
||||
pub const fn new(index: u32) -> Self {
|
||||
let index = index.saturating_add(1);
|
||||
// SAFETY: per above addition, we know `index > 0` always applies.
|
||||
Self(unsafe { NonZeroU32::new_unchecked(index) })
|
||||
Self(match NonZeroU32::new(index) {
|
||||
None => unreachable!(),
|
||||
Some(x) => x,
|
||||
})
|
||||
}
|
||||
|
||||
/// Maps a string to its interned representation.
|
||||
@ -250,13 +250,9 @@ impl Symbol {
|
||||
with_session_globals(|session_globals| session_globals.symbol_interner.intern(string))
|
||||
}
|
||||
|
||||
/// Convert to effectively a `&'static str`.
|
||||
/// This is a slowish operation because it requires locking the symbol interner.
|
||||
pub fn as_str(self) -> SymbolStr {
|
||||
with_session_globals(|session_globals| {
|
||||
let symbol_str = session_globals.symbol_interner.get(self);
|
||||
SymbolStr::new(unsafe { std::mem::transmute::<&str, &str>(symbol_str) })
|
||||
})
|
||||
/// Convert to effectively a `&'static str` given the `SessionGlobals`.
|
||||
pub fn as_str<R>(self, s: &SessionGlobals, with: impl FnOnce(&str) -> R) -> R {
|
||||
s.symbol_interner.get(self, with)
|
||||
}
|
||||
|
||||
/// Converts this symbol to the raw index.
|
||||
@ -269,82 +265,19 @@ impl Symbol {
|
||||
}
|
||||
|
||||
fn serde_from_symbol<S: Serializer>(index: &NonZeroU32, ser: S) -> Result<S::Ok, S::Error> {
|
||||
ser.serialize_str(&Self(*index).as_str())
|
||||
with_session_globals(|sg| Self(*index).as_str(sg, |s| ser.serialize_str(s)))
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for Symbol {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
fmt::Debug::fmt(&self.as_str(), f)
|
||||
with_session_globals(|s| self.as_str(s, |s| fmt::Debug::fmt(s, f)))
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for Symbol {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
fmt::Display::fmt(&self.as_str(), f)
|
||||
}
|
||||
}
|
||||
|
||||
/// An alternative to [`Symbol`], useful when the chars within the symbol need to
|
||||
/// be accessed. It deliberately has limited functionality and should only be
|
||||
/// used for temporary values.
|
||||
///
|
||||
/// Because the interner outlives any thread which uses this type, we can
|
||||
/// safely treat `string` which points to interner data, as an immortal string,
|
||||
/// as long as this type never crosses between threads.
|
||||
#[derive(Clone, Eq, PartialOrd, Ord)]
|
||||
pub struct SymbolStr {
|
||||
string: &'static str,
|
||||
/// Ensures the type is neither `Sync` nor `Send`,
|
||||
/// so that we satisfy "never crosses between threads" per above.
|
||||
not_sync_send: PhantomData<*mut ()>,
|
||||
}
|
||||
|
||||
impl SymbolStr {
|
||||
/// Create a `SymbolStr` from a `&'static str`.
|
||||
pub fn new(string: &'static str) -> Self {
|
||||
Self {
|
||||
string,
|
||||
not_sync_send: PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// This impl allows a `SymbolStr` to be directly equated with a `String` or `&str`.
|
||||
impl<T: Deref<Target = str>> PartialEq<T> for SymbolStr {
|
||||
fn eq(&self, other: &T) -> bool {
|
||||
self.string == other.deref()
|
||||
}
|
||||
}
|
||||
|
||||
/// This impl means that if `ss` is a `SymbolStr`:
|
||||
/// - `*ss` is a `str`;
|
||||
/// - `&*ss` is a `&str` (and `match &*ss { ... }` is a common pattern).
|
||||
/// - `&ss as &str` is a `&str`, which means that `&ss` can be passed to a
|
||||
/// function expecting a `&str`.
|
||||
impl Deref for SymbolStr {
|
||||
type Target = str;
|
||||
#[inline]
|
||||
fn deref(&self) -> &str {
|
||||
self.string
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRef<str> for SymbolStr {
|
||||
fn as_ref(&self) -> &str {
|
||||
self.string
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for SymbolStr {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
fmt::Debug::fmt(self.string, f)
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for SymbolStr {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
fmt::Display::fmt(self.string, f)
|
||||
with_session_globals(|s| self.as_str(s, |s| fmt::Display::fmt(s, f)))
|
||||
}
|
||||
}
|
||||
|
||||
@ -384,13 +317,53 @@ pub fn with_session_globals<R>(f: impl FnOnce(&SessionGlobals) -> R) -> R {
|
||||
SESSION_GLOBALS.with(f)
|
||||
}
|
||||
|
||||
/// An interned string,
|
||||
/// either prefilled "at compile time" (`Static`),
|
||||
/// or created at runtime (`Owned`).
|
||||
#[derive(Eq)]
|
||||
enum InternedStr {
|
||||
/// String is stored "at compile time", i.e. prefilled.
|
||||
Static(&'static str),
|
||||
/// String is constructed and stored during runtime.
|
||||
Owned(Box<str>),
|
||||
}
|
||||
|
||||
impl Borrow<str> for InternedStr {
|
||||
fn borrow(&self) -> &str {
|
||||
self.deref()
|
||||
}
|
||||
}
|
||||
|
||||
impl Deref for InternedStr {
|
||||
type Target = str;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
match self {
|
||||
Self::Static(s) => s,
|
||||
Self::Owned(s) => s,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq for InternedStr {
|
||||
fn eq(&self, other: &InternedStr) -> bool {
|
||||
self.deref() == other.deref()
|
||||
}
|
||||
}
|
||||
|
||||
impl Hash for InternedStr {
|
||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||
self.deref().hash(state);
|
||||
}
|
||||
}
|
||||
|
||||
/// The inner interner.
|
||||
/// This construction is used to get interior mutability in `Interner`.
|
||||
struct InnerInterner {
|
||||
/// Arena used to allocate the strings, giving us `&'static str`s from it.
|
||||
arena: DroplessArena,
|
||||
// /// Arena used to allocate the strings, giving us `&'static str`s from it.
|
||||
// arena: DroplessArena,
|
||||
/// Registration of strings and symbol index allocation is done in this set.
|
||||
set: IndexSet<&'static str, FxBuildHasher>,
|
||||
set: IndexSet<InternedStr, FxBuildHasher>,
|
||||
}
|
||||
|
||||
/// A symbol-to-string interner.
|
||||
@ -407,8 +380,8 @@ impl Interner {
|
||||
/// Returns an interner prefilled with `init`.
|
||||
fn prefill(init: &[&'static str]) -> Self {
|
||||
let inner = InnerInterner {
|
||||
arena: <_>::default(),
|
||||
set: init.iter().copied().collect(),
|
||||
// arena: <_>::default(),
|
||||
set: init.iter().copied().map(InternedStr::Static).collect(),
|
||||
};
|
||||
Self {
|
||||
inner: RefCell::new(inner),
|
||||
@ -417,30 +390,19 @@ impl Interner {
|
||||
|
||||
/// Interns `string`, returning a `Symbol` corresponding to it.
|
||||
fn intern(&self, string: &str) -> Symbol {
|
||||
let InnerInterner { arena, set } = &mut *self.inner.borrow_mut();
|
||||
let InnerInterner { set } = &mut *self.inner.borrow_mut();
|
||||
|
||||
if let Some(sym) = set.get_index_of(string) {
|
||||
// Already internet, return that symbol.
|
||||
// Already interned, return that symbol.
|
||||
return Symbol::new(sym as u32);
|
||||
}
|
||||
|
||||
// SAFETY: `from_utf8_unchecked` is safe since we just allocated a `&str`,
|
||||
// which is known to be UTF-8.
|
||||
let bytes = arena.alloc_slice(string.as_bytes());
|
||||
let string: &str = unsafe { str::from_utf8_unchecked(bytes) };
|
||||
|
||||
unsafe fn transmute_lt<'a, 'b, T: ?Sized>(x: &'a T) -> &'b T {
|
||||
transmute(x)
|
||||
}
|
||||
|
||||
// SAFETY: Extending to `'static` is fine. Accesses only happen while the arena is alive.
|
||||
let string: &'static _ = unsafe { transmute_lt(string) };
|
||||
|
||||
Symbol::new(set.insert_full(string).0 as u32)
|
||||
Symbol::new(set.insert_full(InternedStr::Owned(string.into())).0 as u32)
|
||||
}
|
||||
|
||||
/// Returns the corresponding string for the given symbol.
|
||||
fn get(&self, symbol: Symbol) -> &str {
|
||||
self.inner.borrow().set.get_index(symbol.as_u32() as usize).unwrap()
|
||||
fn get<R>(&self, symbol: Symbol, with: impl FnOnce(&str) -> R) -> R {
|
||||
let set = &self.inner.borrow().set;
|
||||
with(set.get_index(symbol.as_u32() as usize).unwrap())
|
||||
}
|
||||
}
|
||||
|
@ -39,6 +39,8 @@
|
||||
// ```
|
||||
//
|
||||
|
||||
#![forbid(unsafe_code)]
|
||||
|
||||
use abnf::types::{Node, Rule};
|
||||
use anyhow::{anyhow, Result};
|
||||
use std::collections::{HashMap, HashSet};
|
||||
|
@ -14,6 +14,7 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
#![forbid(unsafe_code)]
|
||||
#![deny(clippy::all, clippy::missing_docs_in_private_items)]
|
||||
#![doc = include_str!("../README.md")]
|
||||
|
||||
|
@ -14,6 +14,7 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
#![forbid(unsafe_code)]
|
||||
#![doc = include_str!("../README.md")]
|
||||
|
||||
pub mod commands;
|
||||
|
@ -14,6 +14,7 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
#![forbid(unsafe_code)]
|
||||
#![doc = include_str!("../README.md")]
|
||||
|
||||
pub mod build;
|
||||
|
@ -6,4 +6,4 @@ outputs:
|
||||
- initial_input_ast: fd4851f6581155b1e1f63488d141006413b52e2df042673193e838813134c8f8
|
||||
initial_ast: 3b2b884072048267d8433cb3d0d720823fe591c776066d13b4f433468808eef1
|
||||
unrolled_ast: 3b2b884072048267d8433cb3d0d720823fe591c776066d13b4f433468808eef1
|
||||
ssa_ast: 33eae387bf63e6cdfc43a70affb681190ab66e5ea630a5f119656359712338f5
|
||||
ssa_ast: 162f47220db7211933cea796a0161f7805bd01829d3050da42ccd3cfc3dfccfe
|
||||
|
@ -6,4 +6,4 @@ outputs:
|
||||
- initial_input_ast: 7771059685b08997e10c889f701cab07503de86515a498e7e3b332eb0499bd80
|
||||
initial_ast: e4d2863962de0163515a775493ed831b2f06bb58bdbb7906de9e9a9f3c08db7c
|
||||
unrolled_ast: e4d2863962de0163515a775493ed831b2f06bb58bdbb7906de9e9a9f3c08db7c
|
||||
ssa_ast: 01b6f834110362be6c0c449feaac4c5957a1f0daa02df7cb872e78bf8e06f527
|
||||
ssa_ast: 01a32cc3f75c557bed46fd3634337ed890a2e32bdc2ea24bbbdb2d3cae3bc5cf
|
||||
|
@ -6,4 +6,4 @@ outputs:
|
||||
- initial_input_ast: da16ca9cc5f5e030a6f400cab491032378620f9ca67871d8827753e2833d62ef
|
||||
initial_ast: 91ee93f0ea0ee294a802a227c2a50542c52a1ac5e16c4c014bc7d733834874fe
|
||||
unrolled_ast: 91ee93f0ea0ee294a802a227c2a50542c52a1ac5e16c4c014bc7d733834874fe
|
||||
ssa_ast: b6595b5bc5a75dd66dfbc7baf45b0f9b68cb6c872ef423a5fb04fe25188fd181
|
||||
ssa_ast: c2152d5a13489c34bb00d3364624272451b4aa97cfed3cd786a519541d58575f
|
||||
|
@ -7,4 +7,4 @@ outputs:
|
||||
- initial_input_ast: d82831ef1e3012a9d7b5b0b8cf1ab6d14e05147f36b35a5fc5b295467bf6a489
|
||||
initial_ast: 562fbdf20c53634cbaa4f30ed342ea80fbe7969428d505a16800595ba6afe5c9
|
||||
unrolled_ast: 562fbdf20c53634cbaa4f30ed342ea80fbe7969428d505a16800595ba6afe5c9
|
||||
ssa_ast: 279f3a7d2d142da0dfa9f186b84aaf67da2cd6a1ba5815cfc6b1b3628bd3dfb7
|
||||
ssa_ast: 7045973108ff96af0a658c24836525c046e276e758654668c448fb622c7dcd9b
|
||||
|
@ -7,4 +7,4 @@ outputs:
|
||||
- initial_input_ast: d54f96bcbb8e510356b0cd457e477b5cdc8b4ee9b029a18ff722431770a9d5ef
|
||||
initial_ast: ad1cdf61f54808fb527de83fdc8be32a70009a4da6733a1cfc8ee4a1c0a0c4aa
|
||||
unrolled_ast: ad1cdf61f54808fb527de83fdc8be32a70009a4da6733a1cfc8ee4a1c0a0c4aa
|
||||
ssa_ast: 1dd72ca4e6a1c3a345d900ae9d140d6acd4359f0ba24680f51a6584bc785099b
|
||||
ssa_ast: efbf18f0d3661e039bfbe453c0c707b7df336b375e47bc2b30848074bad56b15
|
||||
|
@ -6,4 +6,4 @@ outputs:
|
||||
- initial_input_ast: 71350549991d77f8a5a6d8c91774c9bf1512f757bd2a0e57f9a2e0ecc717cd42
|
||||
initial_ast: 1628dd52c5c9ca6da95cb61c239ae8d5b62ffcf4c426a9fd50d2cc816348a2df
|
||||
unrolled_ast: 1628dd52c5c9ca6da95cb61c239ae8d5b62ffcf4c426a9fd50d2cc816348a2df
|
||||
ssa_ast: 7073ee79ac06f3e97ef75863dea1468e23a06b34325d9ddcbd16aa351162b882
|
||||
ssa_ast: eaf5ff66b66441f4799f47ed158d4563c34de7db6a48f0d46ed2bd9ea69aa1ae
|
||||
|
@ -1,5 +0,0 @@
|
||||
---
|
||||
namespace: Parse
|
||||
expectation: Fail
|
||||
outputs:
|
||||
- "Error [EPAR0370017]: Could not lex the following content: `@foo(?,`.\n"
|
@ -1,5 +0,0 @@
|
||||
---
|
||||
namespace: Parse
|
||||
expectation: Fail
|
||||
outputs:
|
||||
- "Error [EPAR0370017]: Could not lex the following content: `@context`.\n"
|
@ -22,6 +22,7 @@
|
||||
//! To regenerate the tests after a syntax change or failing test, delete the [`tests/expectations/`]
|
||||
//! directory and run the [`parser_tests()`] test in [`parser/src/test.rs`].
|
||||
|
||||
#![forbid(unsafe_code)]
|
||||
#![cfg(not(doctest))] // Don't doctest the markdown.
|
||||
#![doc = include_str!("../README.md")]
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user