Skip to content

Commit

Permalink
core documentation
Browse files Browse the repository at this point in the history
  • Loading branch information
vincenthz committed Dec 21, 2023
1 parent 42327a7 commit c93d109
Show file tree
Hide file tree
Showing 7 changed files with 129 additions and 11 deletions.
19 changes: 11 additions & 8 deletions werbolg-compile/src/code.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use super::instructions::Instruction;
use super::symbols::{IdVec, IdVecAfter};
use werbolg_core::id::IdF;
use werbolg_core::id::{IdArith, IdF};

/// Instruction Address
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
Expand All @@ -15,7 +15,7 @@ impl Default for InstructionAddress {
impl InstructionAddress {
/// Increment the instruction address to the next instruction
pub fn next(self) -> Self {
InstructionAddress::add(self, 1)
InstructionAddress::add(self, InstructionDiff(1))
}
}

Expand All @@ -35,27 +35,30 @@ impl IdF for InstructionAddress {
fn remap(left: Self, right: Self) -> Self {
Self(left.0 + right.0)
}
}
impl IdArith for InstructionAddress {
type IdDiff = InstructionDiff;

fn add(left: Self, right: u32) -> Self {
Self(left.0.checked_add(right).expect("ID valid add"))
fn add(left: Self, right: InstructionDiff) -> Self {
Self(left.0.checked_add(right.0).expect("ID valid add"))
}

fn diff(left: Self, right: Self) -> u32 {
left.0.checked_sub(right.0).expect("ID valid diff")
fn diff(left: Self, right: Self) -> InstructionDiff {
InstructionDiff(left.0.checked_sub(right.0).expect("ID valid diff"))
}
}

impl core::ops::AddAssign<InstructionDiff> for InstructionAddress {
fn add_assign(&mut self, rhs: InstructionDiff) {
*self = InstructionAddress::add(*self, rhs.0)
*self = InstructionAddress::add(*self, rhs)
}
}

impl core::ops::Sub for InstructionAddress {
type Output = InstructionDiff;

fn sub(self, rhs: Self) -> Self::Output {
InstructionDiff(InstructionAddress::diff(self, rhs))
InstructionAddress::diff(self, rhs)
}
}

Expand Down
11 changes: 11 additions & 0 deletions werbolg-core/src/basic.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
use alloc::{boxed::Box, string::String};

/// An ident in the program
///
/// Note that the ident can contains pretty much anything the frontend wants.
/// For example, Space or '::' could be inside the ident
#[derive(Clone, PartialEq, Eq, Hash)]
pub struct Ident(pub String);

Expand All @@ -22,17 +26,24 @@ impl From<String> for Ident {
}

impl Ident {
/// check if the Ident matches the string in parameter
pub fn matches(&self, s: &str) -> bool {
self.0 == s
}
}

/// Core Literal
#[derive(Clone, Hash, PartialEq, Eq)]
pub enum Literal {
/// Bool
Bool(Box<str>),
/// String
String(Box<str>),
/// Integral Number
Number(Box<str>),
/// Decimal Number
Decimal(Box<str>),
/// Bytes
Bytes(Box<[u8]>),
}

Expand Down
31 changes: 29 additions & 2 deletions werbolg-core/src/id.rs
Original file line number Diff line number Diff line change
@@ -1,16 +1,36 @@
//! ID
/// ID related trait
pub trait IdF:
core::fmt::Debug + core::hash::Hash + PartialEq + Eq + PartialOrd + Ord + Copy
{
/// Id as an index
fn as_index(self) -> usize;
/// Create an Id from a slice length
fn from_slice_len<T>(slice: &[T]) -> Self;

/// Create an Id from a a collection length (usize)
fn from_collection_len(len: usize) -> Self;

/// Remap an index
fn remap(left: Self, right: Self) -> Self;
fn add(left: Self, right: u32) -> Self;
fn diff(left: Self, right: Self) -> u32;
}

/// ID Arithmetic related trait
pub trait IdArith: IdF {
/// Difference of Id
type IdDiff;

/// Add a differential to an Id, and get the new Id
fn add(left: Self, right: Self::IdDiff) -> Self;

/// Get the differential between two Ids
fn diff(left: Self, right: Self) -> Self::IdDiff;
}

macro_rules! define_id_remapper {
($constr:ident, $bt:ident, $n:literal, $c:expr) => {
/// Id
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct $constr($bt);

Expand All @@ -30,6 +50,10 @@ macro_rules! define_id_remapper {
fn remap(left: Self, right: Self) -> Self {
Self(left.0 + right.0)
}
}

impl IdArith for $constr {
type IdDiff = $bt;

fn add(left: Self, right: u32) -> Self {
Self(left.0.checked_add(right).expect("ID valid add"))
Expand All @@ -55,8 +79,11 @@ define_id_remapper!(NifId, u32, 32, 'N');
define_id_remapper!(GlobalId, u32, 32, 'G');
define_id_remapper!(InstructionAddress, u32, 32, '%');

/// A general function id (NifId or FunId)
#[derive(Clone, Copy, Debug)]
pub enum ValueFun {
/// NIF ID
Native(NifId),
/// Function ID
Fun(FunId),
}
21 changes: 21 additions & 0 deletions werbolg-core/src/idvec.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
//! A Vector indexed by a specific ID
use super::id::IdF;
use alloc::vec::Vec;
use core::marker::PhantomData;

/// A Vector Indexed by a specific ID
///
/// Note that it can be dereferenced using the array syntax `idec[id]`
pub struct IdVec<ID, T> {
vec: Vec<T>,
phantom: PhantomData<ID>,
Expand All @@ -22,13 +27,15 @@ impl<ID: IdF, T> core::ops::IndexMut<ID> for IdVec<ID, T> {
}

impl<ID: IdF, T> IdVec<ID, T> {
/// Create a new empty IdVec
pub fn new() -> Self {
Self {
vec: Vec::new(),
phantom: PhantomData,
}
}

/// Get the index
pub fn get(&self, id: ID) -> Option<&T> {
let idx = id.as_index();
if self.vec.len() > idx {
Expand All @@ -38,39 +45,47 @@ impl<ID: IdF, T> IdVec<ID, T> {
}
}

/// Return the next Id that will be created on push
pub fn next_id(&self) -> ID {
ID::from_slice_len(&self.vec)
}

/// Append a new element to this IdVec, and returns the Id associated
pub fn push(&mut self, v: T) -> ID {
let id = ID::from_slice_len(&self.vec);
self.vec.push(v);
id
}

/// Create a mutable iterator for this IdVec
pub fn iter_mut(&mut self) -> impl Iterator<Item = &mut T> {
self.vec.iter_mut()
}

/// Create an reference Iterator for this IdVec, note that the Id is also given
pub fn iter(&self) -> impl Iterator<Item = (ID, &T)> {
self.vec
.iter()
.enumerate()
.map(|(i, t)| (ID::from_collection_len(i), t))
}

/// Create a value Iterator for this IdVec
pub fn into_iter(self) -> impl Iterator<Item = (ID, T)> {
self.vec
.into_iter()
.enumerate()
.map(|(i, t)| (ID::from_collection_len(i), t))
}

/// Append a IdVecAfter to this IdVec
pub fn concat(&mut self, after: &mut IdVecAfter<ID, T>) {
assert!(self.vec.len() == after.ofs.as_index());
self.vec.append(&mut after.id_vec.vec)
}

/// Consume the IdVec and create a new IdVec using the function 'f' to map
/// all the elements T of this IdVec.
pub fn remap<F, U>(self, f: F) -> IdVec<ID, U>
where
F: Fn(T) -> U,
Expand All @@ -84,32 +99,38 @@ impl<ID: IdF, T> IdVec<ID, T> {
}
}

/// An IdVec that doesn't starts at Id=0 with the explicit goal to
/// append the underlying IdVec to another IdVec
pub struct IdVecAfter<ID, T> {
id_vec: IdVec<ID, T>,
ofs: ID,
}

impl<ID: IdF, T> IdVecAfter<ID, T> {
/// Create a new IdVec starting at ID=first_id
pub fn new(first_id: ID) -> Self {
Self {
id_vec: IdVec::new(),
ofs: first_id,
}
}

/// Create an offset IdVec from another IdVec
pub fn from_idvec(id_vec: IdVec<ID, T>, first_id: ID) -> Self {
Self {
id_vec,
ofs: first_id,
}
}

/// Append to this IdVecAfter a value T and returns its Id
pub fn push(&mut self, v: T) -> ID {
let id = self.id_vec.push(v);
let new_id = ID::remap(id, self.ofs);
new_id
}

/// Remap all element of this IdVec in place
pub fn remap<F>(&mut self, f: F)
where
F: Fn(&mut T) -> (),
Expand Down
Loading

0 comments on commit c93d109

Please sign in to comment.