Completed docs, added icon
This commit is contained in:
@@ -2,7 +2,7 @@
|
|||||||
name = "orchidlang"
|
name = "orchidlang"
|
||||||
version = "0.2.1"
|
version = "0.2.1"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
license = "AGPL-3.0-or-later"
|
license = "GPL-3.0-or-later"
|
||||||
repository = "https://github.com/lbfalvy/orchid"
|
repository = "https://github.com/lbfalvy/orchid"
|
||||||
description = """
|
description = """
|
||||||
An embeddable pure functional scripting language
|
An embeddable pure functional scripting language
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ Namespaces are inspired by Rust modules and ES6. Every file and directory is imp
|
|||||||
The project uses the nighly rust toolchain. Go to one of the folders within `examples` and run
|
The project uses the nighly rust toolchain. Go to one of the folders within `examples` and run
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
cargo run
|
cargo run --release
|
||||||
```
|
```
|
||||||
|
|
||||||
you can try modifying the examples, but error reporting for the time being is pretty terrible.
|
you can try modifying the examples, but error reporting for the time being is pretty terrible.
|
||||||
|
|||||||
157
icon.svg
Normal file
157
icon.svg
Normal file
@@ -0,0 +1,157 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||||
|
|
||||||
|
<svg
|
||||||
|
width="512"
|
||||||
|
height="512"
|
||||||
|
viewBox="0 0 512 512"
|
||||||
|
version="1.1"
|
||||||
|
id="SVGRoot"
|
||||||
|
sodipodi:docname="Orchid3.svg"
|
||||||
|
inkscape:export-filename="bitmap.png"
|
||||||
|
inkscape:export-xdpi="96"
|
||||||
|
inkscape:export-ydpi="96"
|
||||||
|
inkscape:version="1.2.2 (b0a8486541, 2022-12-01)"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg">
|
||||||
|
<sodipodi:namedview
|
||||||
|
id="namedview261"
|
||||||
|
pagecolor="#505050"
|
||||||
|
bordercolor="#eeeeee"
|
||||||
|
borderopacity="1"
|
||||||
|
inkscape:showpageshadow="0"
|
||||||
|
inkscape:pageopacity="1"
|
||||||
|
inkscape:pagecheckerboard="0"
|
||||||
|
inkscape:deskcolor="#505050"
|
||||||
|
inkscape:document-units="px"
|
||||||
|
showgrid="false"
|
||||||
|
inkscape:zoom="0.5687738"
|
||||||
|
inkscape:cx="514.26419"
|
||||||
|
inkscape:cy="340.20554"
|
||||||
|
inkscape:window-width="1536"
|
||||||
|
inkscape:window-height="792"
|
||||||
|
inkscape:window-x="0"
|
||||||
|
inkscape:window-y="0"
|
||||||
|
inkscape:window-maximized="1"
|
||||||
|
inkscape:current-layer="layer1"
|
||||||
|
showguides="true">
|
||||||
|
<inkscape:grid
|
||||||
|
type="xygrid"
|
||||||
|
id="grid384"
|
||||||
|
originx="0"
|
||||||
|
originy="0" />
|
||||||
|
<sodipodi:guide
|
||||||
|
position="6000,417632"
|
||||||
|
orientation="0,-1"
|
||||||
|
id="guide441"
|
||||||
|
inkscape:locked="false" />
|
||||||
|
<sodipodi:guide
|
||||||
|
position="-720,317632"
|
||||||
|
orientation="1,0"
|
||||||
|
id="guide443"
|
||||||
|
inkscape:locked="false" />
|
||||||
|
</sodipodi:namedview>
|
||||||
|
<defs
|
||||||
|
id="defs256" />
|
||||||
|
<g
|
||||||
|
inkscape:label="Layer 1"
|
||||||
|
inkscape:groupmode="layer"
|
||||||
|
id="layer1">
|
||||||
|
<rect
|
||||||
|
style="fill:#d0d0d0;fill-opacity:1;stroke:none;stroke-width:2.03055;stroke-linecap:round;stroke-linejoin:round"
|
||||||
|
id="rect1970"
|
||||||
|
width="101.0624"
|
||||||
|
height="63.537254"
|
||||||
|
x="58"
|
||||||
|
y="0" />
|
||||||
|
<path
|
||||||
|
style="fill:#d0d0d0;fill-opacity:1;stroke-width:4.48592;stroke-linecap:round;stroke-linejoin:round"
|
||||||
|
d="M 273.10233,224.90203 145.21711,512 H 76.497509 L 204.38273,224.90203 Z"
|
||||||
|
id="path829"
|
||||||
|
sodipodi:nodetypes="ccccc" />
|
||||||
|
<path
|
||||||
|
style="fill:#d0d0d0;fill-opacity:1;stroke-width:4.48592;stroke-linecap:round;stroke-linejoin:round"
|
||||||
|
d="M 81.784799,0 352.78479,512 h 77.27759 L 159.06239,0 Z"
|
||||||
|
id="rect553-3"
|
||||||
|
sodipodi:nodetypes="ccccc" />
|
||||||
|
<path
|
||||||
|
style="fill:#11ad00;fill-opacity:1;stroke:#11ad00;stroke-width:8;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none"
|
||||||
|
d="m 177.57694,275.47736 c -10.67459,23.62197 58.48771,42.32845 44.12799,74.56553 l 12.10403,-27.66077 c 14.35971,-32.23708 -54.2799,-50.88656 -43.73232,-74.56553 z"
|
||||||
|
id="path1073-7"
|
||||||
|
sodipodi:nodetypes="scccs" />
|
||||||
|
<path
|
||||||
|
style="fill:#11ad00;fill-opacity:1;stroke:#11ad00;stroke-width:8;stroke-linecap:butt;stroke-linejoin:round;stroke-dasharray:none"
|
||||||
|
d="m 105.1005,437.61843 c -10.674586,23.62197 58.48771,42.32845 44.12799,74.56553 l 12.10403,-27.66077 c 14.35971,-32.23708 -54.2799,-50.88656 -43.73232,-74.56553 z"
|
||||||
|
id="path1073-7-3"
|
||||||
|
sodipodi:nodetypes="scccs" />
|
||||||
|
<path
|
||||||
|
style="fill:#11ad00;fill-opacity:1;stroke:#11ad00;stroke-width:8.03804;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none"
|
||||||
|
d="m 170.33692,174.65608 c 12.60172,22.70421 77.18453,-12.12069 94.34082,18.78933 l -12.87399,-23.48816 c -17.15629,-30.91003 -81.83366,4.03792 -94.4354,-18.66628 z"
|
||||||
|
id="path1073-7-9"
|
||||||
|
sodipodi:nodetypes="ccccc" />
|
||||||
|
<path
|
||||||
|
style="fill:#11ad00;fill-opacity:1;stroke:#11ad00;stroke-width:8.03804;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none"
|
||||||
|
d="m 131.82807,100.21798 c 12.60173,22.70421 77.02729,-12.1207 94.18358,18.78933 L 213.13766,95.51914 c -17.1563,-30.910024 -81.67642,4.03792 -94.27815,-18.666276 z"
|
||||||
|
id="path1073-7-9-6"
|
||||||
|
sodipodi:nodetypes="ccccc" />
|
||||||
|
<ellipse
|
||||||
|
style="fill:#b7007c;fill-opacity:1;stroke:none;stroke-width:5.93485;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none"
|
||||||
|
id="path2660"
|
||||||
|
ry="26.699783"
|
||||||
|
rx="12.302842"
|
||||||
|
cy="34.928368"
|
||||||
|
cx="118.63708" />
|
||||||
|
<ellipse
|
||||||
|
style="fill:#b7007c;fill-opacity:1;stroke:none;stroke-width:5.93485;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none"
|
||||||
|
id="path2660-2"
|
||||||
|
ry="26.699783"
|
||||||
|
rx="12.302842"
|
||||||
|
cy="-113.73791"
|
||||||
|
cx="85.984467"
|
||||||
|
transform="rotate(72)" />
|
||||||
|
<ellipse
|
||||||
|
style="fill:#b7007c;fill-opacity:1;stroke:none;stroke-width:5.93485;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none"
|
||||||
|
id="path2660-9"
|
||||||
|
ry="26.699783"
|
||||||
|
rx="12.302842"
|
||||||
|
cy="-128.62366"
|
||||||
|
cx="-65.495857"
|
||||||
|
transform="rotate(144)" />
|
||||||
|
<ellipse
|
||||||
|
style="fill:#b7007c;fill-opacity:1;stroke:none;stroke-width:5.93485;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none"
|
||||||
|
id="path2660-2-1"
|
||||||
|
ry="26.699783"
|
||||||
|
rx="12.302842"
|
||||||
|
cy="10.842678"
|
||||||
|
cx="-126.46313"
|
||||||
|
transform="rotate(-144)" />
|
||||||
|
<ellipse
|
||||||
|
style="fill:#b7007c;fill-opacity:1;stroke:none;stroke-width:5.93485;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none"
|
||||||
|
id="path2660-2-1-2"
|
||||||
|
ry="26.699783"
|
||||||
|
rx="12.302842"
|
||||||
|
cy="111.92345"
|
||||||
|
cx="-12.662658"
|
||||||
|
transform="rotate(-72)" />
|
||||||
|
<circle
|
||||||
|
style="fill:#ffff00;stroke:none;stroke-width:10.3559;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none"
|
||||||
|
id="path2875"
|
||||||
|
cy="51.855534"
|
||||||
|
cx="118.63715"
|
||||||
|
r="12.560751" />
|
||||||
|
<path
|
||||||
|
style="fill:#11ad00;fill-opacity:1;stroke:#11ad00;stroke-width:8;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none"
|
||||||
|
d="m 141.1005,356.61843 c -10.67459,23.62197 58.48771,42.32845 44.12799,74.56553 l 12.10403,-27.66077 c 14.35971,-32.23708 -54.2799,-50.88656 -43.73232,-74.56553 z"
|
||||||
|
id="path1073-7-6"
|
||||||
|
sodipodi:nodetypes="scccs" />
|
||||||
|
<rect
|
||||||
|
style="fill:#d0d0d0;fill-opacity:1;stroke:none;stroke-width:2.03055;stroke-linecap:round;stroke-linejoin:round"
|
||||||
|
id="rect1970-6"
|
||||||
|
width="101.0624"
|
||||||
|
height="63.537254"
|
||||||
|
x="352.78479"
|
||||||
|
y="448.46277" />
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 6.2 KiB |
@@ -18,8 +18,12 @@ use crate::representations::Primitive;
|
|||||||
/// Information returned by [Atomic::run]. This mirrors
|
/// Information returned by [Atomic::run]. This mirrors
|
||||||
/// [crate::interpreter::Return] but with a clause instead of an Expr.
|
/// [crate::interpreter::Return] but with a clause instead of an Expr.
|
||||||
pub struct AtomicReturn {
|
pub struct AtomicReturn {
|
||||||
|
/// The next form of the expression
|
||||||
pub clause: Clause,
|
pub clause: Clause,
|
||||||
|
/// Remaining gas
|
||||||
pub gas: Option<usize>,
|
pub gas: Option<usize>,
|
||||||
|
/// Whether further normalization is possible by repeated calls to
|
||||||
|
/// [Atomic::run]
|
||||||
pub inert: bool,
|
pub inert: bool,
|
||||||
}
|
}
|
||||||
impl AtomicReturn {
|
impl AtomicReturn {
|
||||||
@@ -38,6 +42,7 @@ pub type XfnResult = Result<Clause, RcError>;
|
|||||||
|
|
||||||
/// Errors produced by external code
|
/// Errors produced by external code
|
||||||
pub trait ExternError: Display {
|
pub trait ExternError: Display {
|
||||||
|
/// Convert into trait object
|
||||||
fn into_extern(self) -> Rc<dyn ExternError>
|
fn into_extern(self) -> Rc<dyn ExternError>
|
||||||
where
|
where
|
||||||
Self: 'static + Sized,
|
Self: 'static + Sized,
|
||||||
@@ -123,21 +128,27 @@ where
|
|||||||
/// to pass control back to the interpreter.btop
|
/// to pass control back to the interpreter.btop
|
||||||
pub struct Atom(pub Box<dyn Atomic>);
|
pub struct Atom(pub Box<dyn Atomic>);
|
||||||
impl Atom {
|
impl Atom {
|
||||||
|
/// Wrap an [Atomic] in a type-erased box
|
||||||
pub fn new<T: 'static + Atomic>(data: T) -> Self {
|
pub fn new<T: 'static + Atomic>(data: T) -> Self {
|
||||||
Self(Box::new(data) as Box<dyn Atomic>)
|
Self(Box::new(data) as Box<dyn Atomic>)
|
||||||
}
|
}
|
||||||
|
/// Get the contained data
|
||||||
pub fn data(&self) -> &dyn Atomic {
|
pub fn data(&self) -> &dyn Atomic {
|
||||||
self.0.as_ref() as &dyn Atomic
|
self.0.as_ref() as &dyn Atomic
|
||||||
}
|
}
|
||||||
|
/// Attempt to downcast contained data to a specific type
|
||||||
pub fn try_cast<T: Atomic>(&self) -> Option<&T> {
|
pub fn try_cast<T: Atomic>(&self) -> Option<&T> {
|
||||||
self.data().as_any().downcast_ref()
|
self.data().as_any().downcast_ref()
|
||||||
}
|
}
|
||||||
|
/// Test the type of the contained data without downcasting
|
||||||
pub fn is<T: 'static>(&self) -> bool {
|
pub fn is<T: 'static>(&self) -> bool {
|
||||||
self.data().as_any().is::<T>()
|
self.data().as_any().is::<T>()
|
||||||
}
|
}
|
||||||
|
/// Downcast contained data, panic if it isn't the specified type
|
||||||
pub fn cast<T: 'static>(&self) -> &T {
|
pub fn cast<T: 'static>(&self) -> &T {
|
||||||
self.data().as_any().downcast_ref().expect("Type mismatch on Atom::cast")
|
self.data().as_any().downcast_ref().expect("Type mismatch on Atom::cast")
|
||||||
}
|
}
|
||||||
|
/// Normalize the contained data
|
||||||
pub fn run(&self, ctx: Context) -> AtomicResult {
|
pub fn run(&self, ctx: Context) -> AtomicResult {
|
||||||
self.0.run(ctx)
|
self.0.run(ctx)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ pub trait InternedDisplay {
|
|||||||
self.bundle(i).to_string()
|
self.bundle(i).to_string()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Combine with an interner to implement [Display]
|
||||||
fn bundle<'a>(&'a self, interner: &'a Interner) -> DisplayBundle<'a, Self> {
|
fn bundle<'a>(&'a self, interner: &'a Interner) -> DisplayBundle<'a, Self> {
|
||||||
DisplayBundle { interner, data: self }
|
DisplayBundle { interner, data: self }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,12 +13,15 @@ pub struct Tok<T> {
|
|||||||
phantom_data: PhantomData<T>,
|
phantom_data: PhantomData<T>,
|
||||||
}
|
}
|
||||||
impl<T> Tok<T> {
|
impl<T> Tok<T> {
|
||||||
|
/// Wrap an ID number into a token
|
||||||
pub fn from_id(id: NonZeroU32) -> Self {
|
pub fn from_id(id: NonZeroU32) -> Self {
|
||||||
Self { id, phantom_data: PhantomData }
|
Self { id, phantom_data: PhantomData }
|
||||||
}
|
}
|
||||||
|
/// Take the ID number out of a token
|
||||||
pub fn into_id(self) -> NonZeroU32 {
|
pub fn into_id(self) -> NonZeroU32 {
|
||||||
self.id
|
self.id
|
||||||
}
|
}
|
||||||
|
/// Cast into usize
|
||||||
pub fn into_usize(self) -> usize {
|
pub fn into_usize(self) -> usize {
|
||||||
let zero: u32 = self.id.into();
|
let zero: u32 = self.id.into();
|
||||||
zero as usize
|
zero as usize
|
||||||
|
|||||||
@@ -1,3 +1,7 @@
|
|||||||
|
#![deny(missing_docs)]
|
||||||
|
#![doc(html_logo_url = "../logo.jpg")]
|
||||||
|
//! Orchid is a lazy, pure scripting language to be embedded in Rust
|
||||||
|
//! applications. Check out the repo for examples and other links.
|
||||||
pub mod foreign;
|
pub mod foreign;
|
||||||
mod foreign_macros;
|
mod foreign_macros;
|
||||||
pub mod interner;
|
pub mod interner;
|
||||||
|
|||||||
@@ -5,7 +5,9 @@ use crate::utils::BoxedIter;
|
|||||||
/// Error produced when an import refers to a nonexistent module
|
/// Error produced when an import refers to a nonexistent module
|
||||||
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
||||||
pub struct ModuleNotFound {
|
pub struct ModuleNotFound {
|
||||||
|
/// The file containing the invalid import
|
||||||
pub file: Vec<String>,
|
pub file: Vec<String>,
|
||||||
|
/// The invalid import path
|
||||||
pub subpath: Vec<String>,
|
pub subpath: Vec<String>,
|
||||||
}
|
}
|
||||||
impl ProjectError for ModuleNotFound {
|
impl ProjectError for ModuleNotFound {
|
||||||
|
|||||||
@@ -7,9 +7,13 @@ use crate::utils::BoxedIter;
|
|||||||
/// An import refers to a symbol which exists but is not exported.
|
/// An import refers to a symbol which exists but is not exported.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct NotExported {
|
pub struct NotExported {
|
||||||
|
/// The containing file - files are always exported
|
||||||
pub file: Vec<String>,
|
pub file: Vec<String>,
|
||||||
|
/// The path leading to the unexported module
|
||||||
pub subpath: Vec<String>,
|
pub subpath: Vec<String>,
|
||||||
|
/// The offending file
|
||||||
pub referrer_file: Vec<String>,
|
pub referrer_file: Vec<String>,
|
||||||
|
/// The module containing the offending import
|
||||||
pub referrer_subpath: Vec<String>,
|
pub referrer_subpath: Vec<String>,
|
||||||
}
|
}
|
||||||
impl ProjectError for NotExported {
|
impl ProjectError for NotExported {
|
||||||
|
|||||||
@@ -8,8 +8,11 @@ use crate::utils::BoxedIter;
|
|||||||
/// Produced by stages that parse text when it fails.
|
/// Produced by stages that parse text when it fails.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct ParseErrorWithPath {
|
pub struct ParseErrorWithPath {
|
||||||
|
/// The complete source of the faulty file
|
||||||
pub full_source: String,
|
pub full_source: String,
|
||||||
|
/// The path to the faulty file
|
||||||
pub path: Vec<String>,
|
pub path: Vec<String>,
|
||||||
|
/// The parse error produced by Chumsky
|
||||||
pub error: ParseError,
|
pub error: ParseError,
|
||||||
}
|
}
|
||||||
impl ProjectError for ParseErrorWithPath {
|
impl ProjectError for ParseErrorWithPath {
|
||||||
|
|||||||
@@ -7,7 +7,9 @@ use crate::utils::BoxedIter;
|
|||||||
/// A point of interest in resolving the error, such as the point where
|
/// A point of interest in resolving the error, such as the point where
|
||||||
/// processing got stuck, a command that is likely to be incorrect
|
/// processing got stuck, a command that is likely to be incorrect
|
||||||
pub struct ErrorPosition {
|
pub struct ErrorPosition {
|
||||||
|
/// The suspected location
|
||||||
pub location: Location,
|
pub location: Location,
|
||||||
|
/// Any information about the role of this location
|
||||||
pub message: Option<String>,
|
pub message: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -9,8 +9,11 @@ use crate::utils::BoxedIter;
|
|||||||
/// than the current module's absolute path
|
/// than the current module's absolute path
|
||||||
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
||||||
pub struct TooManySupers {
|
pub struct TooManySupers {
|
||||||
|
/// The offending import path
|
||||||
pub path: Vec<String>,
|
pub path: Vec<String>,
|
||||||
|
/// The file containing the offending import
|
||||||
pub offender_file: Vec<String>,
|
pub offender_file: Vec<String>,
|
||||||
|
/// The module containing the offending import
|
||||||
pub offender_mod: Vec<String>,
|
pub offender_mod: Vec<String>,
|
||||||
}
|
}
|
||||||
impl ProjectError for TooManySupers {
|
impl ProjectError for TooManySupers {
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ use crate::utils::BoxedIter;
|
|||||||
/// a path that refers to a directory
|
/// a path that refers to a directory
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct UnexpectedDirectory {
|
pub struct UnexpectedDirectory {
|
||||||
|
/// Path to the offending collection
|
||||||
pub path: Vec<String>,
|
pub path: Vec<String>,
|
||||||
}
|
}
|
||||||
impl ProjectError for UnexpectedDirectory {
|
impl ProjectError for UnexpectedDirectory {
|
||||||
|
|||||||
@@ -8,7 +8,9 @@ use crate::utils::BoxedIter;
|
|||||||
/// Multiple occurences of the same namespace with different visibility
|
/// Multiple occurences of the same namespace with different visibility
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct VisibilityMismatch {
|
pub struct VisibilityMismatch {
|
||||||
|
/// The namespace with ambiguous visibility
|
||||||
pub namespace: Vec<String>,
|
pub namespace: Vec<String>,
|
||||||
|
/// The file containing the namespace
|
||||||
pub file: Rc<Vec<String>>,
|
pub file: Rc<Vec<String>>,
|
||||||
}
|
}
|
||||||
impl ProjectError for VisibilityMismatch {
|
impl ProjectError for VisibilityMismatch {
|
||||||
|
|||||||
@@ -33,10 +33,14 @@ impl ProjectError for FileLoadingError {
|
|||||||
/// as the file system.
|
/// as the file system.
|
||||||
#[derive(Clone, PartialEq, Eq, Hash)]
|
#[derive(Clone, PartialEq, Eq, Hash)]
|
||||||
pub enum Loaded {
|
pub enum Loaded {
|
||||||
|
/// Conceptually equivalent to a sourcefile
|
||||||
Code(Rc<String>),
|
Code(Rc<String>),
|
||||||
|
/// Conceptually equivalent to the list of *.orc files in a folder, without
|
||||||
|
/// the extension
|
||||||
Collection(Rc<Vec<String>>),
|
Collection(Rc<Vec<String>>),
|
||||||
}
|
}
|
||||||
impl Loaded {
|
impl Loaded {
|
||||||
|
/// Is the loaded item source code (not a collection)?
|
||||||
pub fn is_code(&self) -> bool {
|
pub fn is_code(&self) -> bool {
|
||||||
matches!(self, Loaded::Code(_))
|
matches!(self, Loaded::Code(_))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,7 +16,9 @@ use crate::utils::{pushed, Substack};
|
|||||||
/// describe libraries of external functions in Rust. It implements [Add] for
|
/// describe libraries of external functions in Rust. It implements [Add] for
|
||||||
/// added convenience
|
/// added convenience
|
||||||
pub enum ConstTree {
|
pub enum ConstTree {
|
||||||
|
/// A function or constant
|
||||||
Const(Expr),
|
Const(Expr),
|
||||||
|
/// A submodule
|
||||||
Tree(HashMap<Tok<String>, ConstTree>),
|
Tree(HashMap<Tok<String>, ConstTree>),
|
||||||
}
|
}
|
||||||
impl ConstTree {
|
impl ConstTree {
|
||||||
|
|||||||
@@ -19,7 +19,9 @@ use crate::utils::Substack;
|
|||||||
/// A [Clause] with associated metadata
|
/// A [Clause] with associated metadata
|
||||||
#[derive(Clone, Debug, PartialEq)]
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
pub struct Expr {
|
pub struct Expr {
|
||||||
|
/// The actual value
|
||||||
pub value: Clause,
|
pub value: Clause,
|
||||||
|
/// Information about the code that produced this value
|
||||||
pub location: Location,
|
pub location: Location,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -87,7 +89,9 @@ pub enum PHClass {
|
|||||||
/// Properties of a placeholder that matches unknown tokens in macros
|
/// Properties of a placeholder that matches unknown tokens in macros
|
||||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
|
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
|
||||||
pub struct Placeholder {
|
pub struct Placeholder {
|
||||||
|
/// Identifier to pair placeholders in the pattern and template
|
||||||
pub name: Tok<String>,
|
pub name: Tok<String>,
|
||||||
|
/// The nature of the token set matched by this placeholder
|
||||||
pub class: PHClass,
|
pub class: PHClass,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -321,8 +325,11 @@ impl InternedDisplay for Clause {
|
|||||||
/// A substitution rule as read from the source
|
/// A substitution rule as read from the source
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
pub struct Rule {
|
pub struct Rule {
|
||||||
|
/// Tree fragment in the source code that activates this rule
|
||||||
pub pattern: Rc<Vec<Expr>>,
|
pub pattern: Rc<Vec<Expr>>,
|
||||||
|
/// Influences the order in which rules are checked
|
||||||
pub prio: NotNan<f64>,
|
pub prio: NotNan<f64>,
|
||||||
|
/// Tree fragment generated by this rule
|
||||||
pub template: Rc<Vec<Expr>>,
|
pub template: Rc<Vec<Expr>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -386,7 +393,9 @@ impl InternedDisplay for Rule {
|
|||||||
/// A named constant
|
/// A named constant
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
pub struct Constant {
|
pub struct Constant {
|
||||||
|
/// Used to reference the constant
|
||||||
pub name: Tok<String>,
|
pub name: Tok<String>,
|
||||||
|
/// The constant value inserted where the name is found
|
||||||
pub value: Expr,
|
pub value: Expr,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -18,7 +18,9 @@ use crate::utils::sym2string;
|
|||||||
|
|
||||||
/// An expression with metadata
|
/// An expression with metadata
|
||||||
pub struct Expr {
|
pub struct Expr {
|
||||||
|
/// The actual value
|
||||||
pub clause: Clause,
|
pub clause: Clause,
|
||||||
|
/// Information about the code that produced this value
|
||||||
pub location: Location,
|
pub location: Location,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -57,10 +59,20 @@ pub struct NotALiteral;
|
|||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct ExprInst(pub Rc<RefCell<Expr>>);
|
pub struct ExprInst(pub Rc<RefCell<Expr>>);
|
||||||
impl ExprInst {
|
impl ExprInst {
|
||||||
|
/// Read-only access to the shared expression instance
|
||||||
|
///
|
||||||
|
/// # Panics
|
||||||
|
///
|
||||||
|
/// if the expression is already borrowed in read-write mode
|
||||||
pub fn expr(&self) -> impl Deref<Target = Expr> + '_ {
|
pub fn expr(&self) -> impl Deref<Target = Expr> + '_ {
|
||||||
self.0.as_ref().borrow()
|
self.0.as_ref().borrow()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Read-Write access to the shared expression instance
|
||||||
|
///
|
||||||
|
/// # Panics
|
||||||
|
///
|
||||||
|
/// if the expression is already borrowed
|
||||||
pub fn expr_mut(&self) -> impl DerefMut<Target = Expr> + '_ {
|
pub fn expr_mut(&self) -> impl DerefMut<Target = Expr> + '_ {
|
||||||
self.0.as_ref().borrow_mut()
|
self.0.as_ref().borrow_mut()
|
||||||
}
|
}
|
||||||
@@ -140,11 +152,23 @@ pub enum Clause {
|
|||||||
/// An unintrospectable unit
|
/// An unintrospectable unit
|
||||||
P(Primitive),
|
P(Primitive),
|
||||||
/// A function application
|
/// A function application
|
||||||
Apply { f: ExprInst, x: ExprInst },
|
Apply {
|
||||||
|
/// Function to be applied
|
||||||
|
f: ExprInst,
|
||||||
|
/// Argument to be substituted in the function
|
||||||
|
x: ExprInst,
|
||||||
|
},
|
||||||
/// A name to be looked up in the interpreter's symbol table
|
/// A name to be looked up in the interpreter's symbol table
|
||||||
Constant(Sym),
|
Constant(Sym),
|
||||||
/// A function
|
/// A function
|
||||||
Lambda { args: Option<PathSet>, body: ExprInst },
|
Lambda {
|
||||||
|
/// A collection of (zero or more) paths to placeholders belonging to this
|
||||||
|
/// function
|
||||||
|
args: Option<PathSet>,
|
||||||
|
/// The tree produced by this function, with placeholders where the
|
||||||
|
/// argument will go
|
||||||
|
body: ExprInst,
|
||||||
|
},
|
||||||
/// A placeholder within a function that will be replaced upon application
|
/// A placeholder within a function that will be replaced upon application
|
||||||
LambdaArg,
|
LambdaArg,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,9 +6,13 @@ use ordered_float::NotNan;
|
|||||||
/// external functions
|
/// external functions
|
||||||
#[derive(Clone, PartialEq, Eq, Hash)]
|
#[derive(Clone, PartialEq, Eq, Hash)]
|
||||||
pub enum Literal {
|
pub enum Literal {
|
||||||
|
/// Any floating point number except `NaN`
|
||||||
Num(NotNan<f64>),
|
Num(NotNan<f64>),
|
||||||
|
/// An unsigned integer; a size, index or pointer
|
||||||
Uint(u64),
|
Uint(u64),
|
||||||
|
/// A single utf-8 codepoint
|
||||||
Char(char),
|
Char(char),
|
||||||
|
/// A utf-8 character sequence
|
||||||
Str(String),
|
Str(String),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -8,12 +8,21 @@ use itertools::Itertools;
|
|||||||
/// error. Meaningful within the context of a project.
|
/// error. Meaningful within the context of a project.
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||||
pub enum Location {
|
pub enum Location {
|
||||||
|
/// Location information lost or code generated on the fly
|
||||||
Unknown,
|
Unknown,
|
||||||
|
/// Only the file is known
|
||||||
File(Rc<Vec<String>>),
|
File(Rc<Vec<String>>),
|
||||||
Range { file: Rc<Vec<String>>, range: Range<usize> },
|
/// Character slice of the code
|
||||||
|
Range {
|
||||||
|
/// Argument to the file loading callback that produced this code
|
||||||
|
file: Rc<Vec<String>>,
|
||||||
|
/// Index of the unicode code points associated with the code
|
||||||
|
range: Range<usize>
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Location {
|
impl Location {
|
||||||
|
/// Range, if known. If the range is known, the file is always known
|
||||||
pub fn range(&self) -> Option<Range<usize>> {
|
pub fn range(&self) -> Option<Range<usize>> {
|
||||||
if let Self::Range { range, .. } = self {
|
if let Self::Range { range, .. } = self {
|
||||||
Some(range.clone())
|
Some(range.clone())
|
||||||
@@ -22,6 +31,7 @@ impl Location {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// File, if known
|
||||||
pub fn file(&self) -> Option<Rc<Vec<String>>> {
|
pub fn file(&self) -> Option<Rc<Vec<String>>> {
|
||||||
if let Self::File(file) | Self::Range { file, .. } = self {
|
if let Self::File(file) | Self::Range { file, .. } = self {
|
||||||
Some(file.clone())
|
Some(file.clone())
|
||||||
|
|||||||
@@ -9,6 +9,12 @@ use crate::utils::{unwrap_or, BoxedIter};
|
|||||||
/// imported or importing all available symbols with a globstar (*)
|
/// imported or importing all available symbols with a globstar (*)
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||||
pub struct Import {
|
pub struct Import {
|
||||||
|
/// Import path, a sequence of module names. Can either start with
|
||||||
|
///
|
||||||
|
/// - `self` to reference the current module
|
||||||
|
/// - any number of `super` to reference the parent module of the implied
|
||||||
|
/// `self`
|
||||||
|
/// - a root name
|
||||||
pub path: Sym,
|
pub path: Sym,
|
||||||
/// If name is None, this is a wildcard import
|
/// If name is None, this is a wildcard import
|
||||||
pub name: Option<Tok<String>>,
|
pub name: Option<Tok<String>>,
|
||||||
@@ -31,25 +37,37 @@ impl Import {
|
|||||||
/// A namespace block
|
/// A namespace block
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct Namespace {
|
pub struct Namespace {
|
||||||
|
/// Name prefixed to all names in the block
|
||||||
pub name: Tok<String>,
|
pub name: Tok<String>,
|
||||||
|
/// Prefixed entries
|
||||||
pub body: Vec<FileEntry>,
|
pub body: Vec<FileEntry>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Things that may be prefixed with an export
|
/// Things that may be prefixed with an export
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub enum Member {
|
pub enum Member {
|
||||||
|
/// A substitution rule. Rules apply even when they're not in scope, if the
|
||||||
|
/// absolute names are present eg. because they're produced by other rules
|
||||||
Rule(Rule),
|
Rule(Rule),
|
||||||
|
/// A constant (or function) associated with a name
|
||||||
Constant(Constant),
|
Constant(Constant),
|
||||||
|
/// A prefixed set of other entries
|
||||||
Namespace(Namespace),
|
Namespace(Namespace),
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Anything we might encounter in a file
|
/// Anything we might encounter in a file
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub enum FileEntry {
|
pub enum FileEntry {
|
||||||
|
/// Imports one or all names in a module
|
||||||
Import(Vec<Import>),
|
Import(Vec<Import>),
|
||||||
|
/// Comments are kept here in case dev tooling wants to parse documentation
|
||||||
Comment(String),
|
Comment(String),
|
||||||
|
/// An element visible to the outside
|
||||||
Exported(Member),
|
Exported(Member),
|
||||||
|
/// An element only visible from local code
|
||||||
Internal(Member),
|
Internal(Member),
|
||||||
|
/// A list of tokens exported explicitly. This can also create new exported
|
||||||
|
/// tokens that the local module doesn't actually define a role for
|
||||||
Export(Vec<Tok<String>>),
|
Export(Vec<Tok<String>>),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -10,23 +10,32 @@ use super::sourcefile::Import;
|
|||||||
use crate::interner::Tok;
|
use crate::interner::Tok;
|
||||||
use crate::utils::Substack;
|
use crate::utils::Substack;
|
||||||
|
|
||||||
|
/// The member in a [ModEntry] which is associated with a name in a [Module]
|
||||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
pub enum ModMember<TItem: Clone, TExt: Clone> {
|
pub enum ModMember<TItem: Clone, TExt: Clone> {
|
||||||
|
/// Arbitrary data
|
||||||
Item(TItem),
|
Item(TItem),
|
||||||
|
/// A child module
|
||||||
Sub(Rc<Module<TItem, TExt>>),
|
Sub(Rc<Module<TItem, TExt>>),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Data about a name in a [Module]
|
||||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
pub struct ModEntry<TItem: Clone, TExt: Clone> {
|
pub struct ModEntry<TItem: Clone, TExt: Clone> {
|
||||||
|
/// The submodule or item
|
||||||
pub member: ModMember<TItem, TExt>,
|
pub member: ModMember<TItem, TExt>,
|
||||||
|
/// Whether the member is visible to modules other than the parent
|
||||||
pub exported: bool,
|
pub exported: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A module, containing imports,
|
/// A module, containing imports,
|
||||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
pub struct Module<TItem: Clone, TExt: Clone> {
|
pub struct Module<TItem: Clone, TExt: Clone> {
|
||||||
|
/// Import statements present this module
|
||||||
pub imports: Vec<Import>,
|
pub imports: Vec<Import>,
|
||||||
|
/// Submodules and items by name
|
||||||
pub items: HashMap<Tok<String>, ModEntry<TItem, TExt>>,
|
pub items: HashMap<Tok<String>, ModEntry<TItem, TExt>>,
|
||||||
|
/// Additional information associated with the module
|
||||||
pub extra: TExt,
|
pub extra: TExt,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -46,6 +46,7 @@ pub struct Repository<M: Matcher> {
|
|||||||
cache: Vec<(CachedRule<M>, HashSet<Sym>, NotNan<f64>)>,
|
cache: Vec<(CachedRule<M>, HashSet<Sym>, NotNan<f64>)>,
|
||||||
}
|
}
|
||||||
impl<M: Matcher> Repository<M> {
|
impl<M: Matcher> Repository<M> {
|
||||||
|
/// Build a new repository to hold the given set of rules
|
||||||
pub fn new(
|
pub fn new(
|
||||||
mut rules: Vec<Rule>,
|
mut rules: Vec<Rule>,
|
||||||
i: &Interner,
|
i: &Interner,
|
||||||
|
|||||||
@@ -10,7 +10,9 @@ use crate::utils::unwrap_or;
|
|||||||
/// An IO command to be handled by the host application.
|
/// An IO command to be handled by the host application.
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub enum IO {
|
pub enum IO {
|
||||||
|
/// Print a string to standard output and resume execution
|
||||||
Print(String, ExprInst),
|
Print(String, ExprInst),
|
||||||
|
/// Read a line from standard input and pass it to the calback
|
||||||
Readline(ExprInst),
|
Readline(ExprInst),
|
||||||
}
|
}
|
||||||
atomic_inert!(IO);
|
atomic_inert!(IO);
|
||||||
|
|||||||
@@ -6,6 +6,8 @@ use super::str::str;
|
|||||||
use crate::interner::Interner;
|
use crate::interner::Interner;
|
||||||
use crate::pipeline::ConstTree;
|
use crate::pipeline::ConstTree;
|
||||||
|
|
||||||
|
/// Build the standard library used by the interpreter by combining the other
|
||||||
|
/// libraries
|
||||||
pub fn mk_stl(i: &Interner) -> ConstTree {
|
pub fn mk_stl(i: &Interner) -> ConstTree {
|
||||||
cpsio(i) + conv(i) + bool(i) + str(i) + num(i)
|
cpsio(i) + conv(i) + bool(i) + str(i) + num(i)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
//! Constants exposed to usercode by the interpreter
|
||||||
mod assertion_error;
|
mod assertion_error;
|
||||||
mod bool;
|
mod bool;
|
||||||
mod conv;
|
mod conv;
|
||||||
|
|||||||
@@ -7,7 +7,9 @@ use super::BoxedIter;
|
|||||||
/// are technically usable for this purpose, they're very easy to confuse
|
/// are technically usable for this purpose, they're very easy to confuse
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||||
pub enum Side {
|
pub enum Side {
|
||||||
|
/// Left, low, or high-to-low in the case of sequences
|
||||||
Left,
|
Left,
|
||||||
|
/// Right, high, or low-to-high in the case of sequences
|
||||||
Right,
|
Right,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -21,6 +23,7 @@ impl Display for Side {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Side {
|
impl Side {
|
||||||
|
/// Get the side that is not the current one
|
||||||
pub fn opposite(&self) -> Self {
|
pub fn opposite(&self) -> Self {
|
||||||
match self {
|
match self {
|
||||||
Self::Left => Self::Right,
|
Self::Left => Self::Right,
|
||||||
|
|||||||
@@ -17,7 +17,9 @@ pub struct Stackframe<'a, T> {
|
|||||||
/// the recursion isn't deep enough to warrant a heap-allocated set.
|
/// the recursion isn't deep enough to warrant a heap-allocated set.
|
||||||
#[derive(Clone, Copy)]
|
#[derive(Clone, Copy)]
|
||||||
pub enum Substack<'a, T> {
|
pub enum Substack<'a, T> {
|
||||||
|
/// A level in the linked list
|
||||||
Frame(Stackframe<'a, T>),
|
Frame(Stackframe<'a, T>),
|
||||||
|
/// The end of the list
|
||||||
Bottom,
|
Bottom,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -33,12 +35,16 @@ impl<'a, T> Substack<'a, T> {
|
|||||||
pub fn iter(&self) -> SubstackIterator<T> {
|
pub fn iter(&self) -> SubstackIterator<T> {
|
||||||
SubstackIterator { curr: self }
|
SubstackIterator { curr: self }
|
||||||
}
|
}
|
||||||
|
/// Add the item to this substack
|
||||||
pub fn push(&'a self, item: T) -> Self {
|
pub fn push(&'a self, item: T) -> Self {
|
||||||
Self::Frame(self.new_frame(item))
|
Self::Frame(self.new_frame(item))
|
||||||
}
|
}
|
||||||
|
/// Create a new frame on top of this substack
|
||||||
pub fn new_frame(&'a self, item: T) -> Stackframe<'a, T> {
|
pub fn new_frame(&'a self, item: T) -> Stackframe<'a, T> {
|
||||||
Stackframe { item, prev: self, len: self.opt().map_or(1, |s| s.len) }
|
Stackframe { item, prev: self, len: self.opt().map_or(1, |s| s.len) }
|
||||||
}
|
}
|
||||||
|
/// obtain the previous stackframe if one exists
|
||||||
|
/// TODO: this should return a [Substack]
|
||||||
pub fn pop(&'a self, count: usize) -> Option<&'a Stackframe<'a, T>> {
|
pub fn pop(&'a self, count: usize) -> Option<&'a Stackframe<'a, T>> {
|
||||||
if let Self::Frame(p) = self {
|
if let Self::Frame(p) = self {
|
||||||
if count == 0 {
|
if count == 0 {
|
||||||
@@ -50,12 +56,14 @@ impl<'a, T> Substack<'a, T> {
|
|||||||
None
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/// number of stackframes
|
||||||
pub fn len(&self) -> usize {
|
pub fn len(&self) -> usize {
|
||||||
match self {
|
match self {
|
||||||
Self::Frame(f) => f.len,
|
Self::Frame(f) => f.len,
|
||||||
Self::Bottom => 0,
|
Self::Bottom => 0,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/// is this the bottom of the stack
|
||||||
pub fn is_empty(&self) -> bool {
|
pub fn is_empty(&self) -> bool {
|
||||||
self.len() == 0
|
self.len() == 0
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user