Made some progress towards effectful programs
This commit is contained in:
@@ -1,6 +1,8 @@
|
|||||||
#![allow(refining_impl_trait, reason = "Has various false-positives around lints")]
|
#![allow(refining_impl_trait, reason = "Has various false-positives around lints")]
|
||||||
use orchid_api as api;
|
use orchid_api as api;
|
||||||
|
|
||||||
|
mod streams;
|
||||||
|
pub use streams::*;
|
||||||
mod atom;
|
mod atom;
|
||||||
pub use atom::*;
|
pub use atom::*;
|
||||||
mod cmd_atom;
|
mod cmd_atom;
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
use std::io;
|
||||||
use std::num::NonZero;
|
use std::num::NonZero;
|
||||||
|
|
||||||
use chrono::{DateTime, Utc};
|
use chrono::{DateTime, Utc};
|
||||||
@@ -58,6 +59,20 @@ pub struct IoError {
|
|||||||
pub message: String,
|
pub message: String,
|
||||||
pub kind: IoErrorKind,
|
pub kind: IoErrorKind,
|
||||||
}
|
}
|
||||||
|
impl From<io::Error> for IoError {
|
||||||
|
fn from(value: io::Error) -> Self {
|
||||||
|
Self {
|
||||||
|
message: value.to_string(),
|
||||||
|
kind: match value.kind() {
|
||||||
|
io::ErrorKind::Interrupted
|
||||||
|
| io::ErrorKind::BrokenPipe
|
||||||
|
| io::ErrorKind::NetworkDown
|
||||||
|
| io::ErrorKind::ConnectionReset => IoErrorKind::Interrupted,
|
||||||
|
_ => IoErrorKind::Other,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Coding)]
|
#[derive(Clone, Debug, Coding)]
|
||||||
pub enum ReadLimit {
|
pub enum ReadLimit {
|
||||||
@@ -69,7 +84,9 @@ pub enum ReadLimit {
|
|||||||
/// Read all available data from a stream. If the returned vector is empty, the
|
/// Read all available data from a stream. If the returned vector is empty, the
|
||||||
/// stream has reached its end.
|
/// stream has reached its end.
|
||||||
#[derive(Clone, Debug, Coding, Hierarchy)]
|
#[derive(Clone, Debug, Coding, Hierarchy)]
|
||||||
pub struct ReadReq(pub ReadLimit);
|
pub struct ReadReq {
|
||||||
|
pub limit: ReadLimit,
|
||||||
|
}
|
||||||
impl Request for ReadReq {
|
impl Request for ReadReq {
|
||||||
type Response = Result<Vec<u8>, IoError>;
|
type Response = Result<Vec<u8>, IoError>;
|
||||||
}
|
}
|
||||||
|
|||||||
103
orchid-extension/src/streams.rs
Normal file
103
orchid-extension/src/streams.rs
Normal file
@@ -0,0 +1,103 @@
|
|||||||
|
use std::borrow::Cow;
|
||||||
|
use std::io::Result;
|
||||||
|
use std::pin::Pin;
|
||||||
|
use std::rc::Rc;
|
||||||
|
|
||||||
|
use futures::io::BufReader;
|
||||||
|
use futures::lock::Mutex;
|
||||||
|
use futures::{AsyncBufReadExt, AsyncRead, AsyncReadExt, AsyncWrite, AsyncWriteExt};
|
||||||
|
use never::Never;
|
||||||
|
use orchid_base::{Receipt, ReqHandle, ReqHandleExt};
|
||||||
|
|
||||||
|
use crate::gen_expr::{GExpr, new_atom};
|
||||||
|
use crate::std_reqs::{CloseReq, FlushReq, OutputReq, ReadLimit, ReadReq, WriteReq};
|
||||||
|
use crate::{Atomic, MethodSetBuilder, OwnedAtom, OwnedVariant, Supports, ToExpr};
|
||||||
|
|
||||||
|
struct WriterState {
|
||||||
|
buf: Vec<u8>,
|
||||||
|
writer: Pin<Box<dyn AsyncWrite>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct OrcWriter<T: AsyncWrite + 'static>(T);
|
||||||
|
impl<T: AsyncWrite + 'static> ToExpr for OrcWriter<T> {
|
||||||
|
async fn to_gen(self) -> GExpr {
|
||||||
|
new_atom(WriterAtom(Rc::new(Mutex::new(WriterState {
|
||||||
|
buf: Vec::new(),
|
||||||
|
writer: Box::pin(self.0),
|
||||||
|
}))))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct WriterAtom(Rc<Mutex<WriterState>>);
|
||||||
|
impl Atomic for WriterAtom {
|
||||||
|
type Variant = OwnedVariant;
|
||||||
|
type Data = ();
|
||||||
|
fn reg_methods() -> MethodSetBuilder<Self> { MethodSetBuilder::new().handle::<OutputReq>() }
|
||||||
|
}
|
||||||
|
impl OwnedAtom for WriterAtom {
|
||||||
|
type Refs = Never;
|
||||||
|
async fn val(&self) -> Cow<'_, Self::Data> { Cow::Owned(()) }
|
||||||
|
}
|
||||||
|
impl Supports<OutputReq> for WriterAtom {
|
||||||
|
async fn handle<'a>(
|
||||||
|
&self,
|
||||||
|
hand: Box<dyn ReqHandle<'a> + '_>,
|
||||||
|
req: OutputReq,
|
||||||
|
) -> Result<Receipt<'a>> {
|
||||||
|
match req {
|
||||||
|
OutputReq::WriteReq(ref wr @ WriteReq { ref data }) => {
|
||||||
|
self.0.lock().await.buf.extend(data);
|
||||||
|
hand.reply(wr, &Ok(())).await
|
||||||
|
},
|
||||||
|
OutputReq::FlushReq(ref fr @ FlushReq) => {
|
||||||
|
let mut g = self.0.lock().await;
|
||||||
|
let WriterState { buf, writer } = &mut *g;
|
||||||
|
hand.reply(fr, &writer.write_all(&buf[..]).await.map_err(|e| e.into())).await
|
||||||
|
},
|
||||||
|
OutputReq::CloseReq(ref cr @ CloseReq) =>
|
||||||
|
hand.reply(cr, &self.0.lock().await.writer.close().await.map_err(|e| e.into())).await,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct OrcReader<T: AsyncRead + 'static>(T);
|
||||||
|
impl<T: AsyncRead + 'static> ToExpr for OrcReader<T> {
|
||||||
|
async fn to_gen(self) -> GExpr {
|
||||||
|
new_atom(ReaderAtom(Rc::new(Mutex::new(BufReader::new(Box::pin(self.0))))))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct ReaderAtom(Rc<Mutex<BufReader<Pin<Box<dyn AsyncRead>>>>>);
|
||||||
|
impl Atomic for ReaderAtom {
|
||||||
|
type Variant = OwnedVariant;
|
||||||
|
type Data = ();
|
||||||
|
fn reg_methods() -> MethodSetBuilder<Self> { MethodSetBuilder::new().handle::<ReadReq>() }
|
||||||
|
}
|
||||||
|
impl OwnedAtom for ReaderAtom {
|
||||||
|
type Refs = Never;
|
||||||
|
async fn val(&self) -> Cow<'_, Self::Data> { Cow::Owned(()) }
|
||||||
|
}
|
||||||
|
impl Supports<ReadReq> for ReaderAtom {
|
||||||
|
async fn handle<'a>(
|
||||||
|
&self,
|
||||||
|
hand: Box<dyn ReqHandle<'a> + '_>,
|
||||||
|
req: ReadReq,
|
||||||
|
) -> Result<Receipt<'a>> {
|
||||||
|
let mut buf = Vec::new();
|
||||||
|
let mut reader = self.0.lock().await;
|
||||||
|
let rep = match match req.limit {
|
||||||
|
ReadLimit::End => reader.read_to_end(&mut buf).await.map(|_| ()),
|
||||||
|
ReadLimit::Delimiter(b) => reader.read_until(b, &mut buf).await.map(|_| ()),
|
||||||
|
ReadLimit::Length(n) => {
|
||||||
|
buf = vec![0u8; n.get() as usize];
|
||||||
|
reader.read_exact(&mut buf).await
|
||||||
|
},
|
||||||
|
} {
|
||||||
|
Err(e) => Err(e.into()),
|
||||||
|
Ok(()) => Ok(buf),
|
||||||
|
};
|
||||||
|
hand.reply(&req, &rep).await
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -5,7 +5,10 @@ use std::num::NonZero;
|
|||||||
use orchid_api_traits::Coding;
|
use orchid_api_traits::Coding;
|
||||||
use orchid_base::BoxedIter;
|
use orchid_base::BoxedIter;
|
||||||
|
|
||||||
use crate::{AtomOps, AtomTypeId, Atomic, AtomicFeatures, Fun, Lambda, Replier, SystemCtor};
|
use crate::{
|
||||||
|
AtomOps, AtomTypeId, Atomic, AtomicFeatures, CmdAtom, Fun, Lambda, ReaderAtom, Replier,
|
||||||
|
SystemCtor, WriterAtom,
|
||||||
|
};
|
||||||
|
|
||||||
/// Description of a system. This is intended to be a ZST storing the static
|
/// Description of a system. This is intended to be a ZST storing the static
|
||||||
/// properties of a [SystemCtor] which should be known to foreign systems
|
/// properties of a [SystemCtor] which should be known to foreign systems
|
||||||
@@ -56,5 +59,13 @@ pub(crate) trait DynSystemCardExt: DynSystemCard {
|
|||||||
/// The indices of these are bitwise negated, such that the MSB of an atom index
|
/// The indices of these are bitwise negated, such that the MSB of an atom index
|
||||||
/// marks whether it belongs to this package (0) or the importer (1)
|
/// marks whether it belongs to this package (0) or the importer (1)
|
||||||
pub(crate) fn general_atoms() -> impl Iterator<Item = Option<Box<dyn AtomOps>>> {
|
pub(crate) fn general_atoms() -> impl Iterator<Item = Option<Box<dyn AtomOps>>> {
|
||||||
[Some(Fun::ops()), Some(Lambda::ops()), Some(Replier::ops())].into_iter()
|
[
|
||||||
|
Some(Fun::ops()),
|
||||||
|
Some(Lambda::ops()),
|
||||||
|
Some(Replier::ops()),
|
||||||
|
Some(CmdAtom::ops()),
|
||||||
|
Some(WriterAtom::ops()),
|
||||||
|
Some(ReaderAtom::ops()),
|
||||||
|
]
|
||||||
|
.into_iter()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ impl Supports<RunCommand> for ReadStreamCmd {
|
|||||||
hand: Box<dyn orchid_base::ReqHandle<'a> + '_>,
|
hand: Box<dyn orchid_base::ReqHandle<'a> + '_>,
|
||||||
req: RunCommand,
|
req: RunCommand,
|
||||||
) -> io::Result<orchid_base::Receipt<'a>> {
|
) -> io::Result<orchid_base::Receipt<'a>> {
|
||||||
let ret = match self.hand.call(ReadReq(self.limit.clone())).await {
|
let ret = match self.hand.call(ReadReq { limit: self.limit.clone() }).await {
|
||||||
None => Err(mk_errv(
|
None => Err(mk_errv(
|
||||||
is("Atom is not readable").await,
|
is("Atom is not readable").await,
|
||||||
format!("Expected a readable stream handle, found {}", fmt(&self.hand).await),
|
format!("Expected a readable stream handle, found {}", fmt(&self.hand).await),
|
||||||
|
|||||||
@@ -2,20 +2,21 @@
|
|||||||
name = "orcx"
|
name = "orcx"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
edition = "2024"
|
edition = "2024"
|
||||||
|
authors = ["Lawrence Bethlenfalvy <lbfalvy@protonmail.com>"]
|
||||||
|
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
async-fn-stream = { version = "0.1.0", path = "../async-fn-stream" }
|
async-fn-stream = { version = "0.1.0", path = "../async-fn-stream" }
|
||||||
camino = "1.2.2"
|
camino = "1.2.2"
|
||||||
clap = { version = "4.5.54", features = ["derive", "env"] }
|
clap = { version = "4.5.54", features = ["derive", "env", "cargo"] }
|
||||||
ctrlc = "3.5.1"
|
ctrlc = "3.5.1"
|
||||||
futures = "0.3.31"
|
futures = "0.3.31"
|
||||||
itertools = "0.14.0"
|
itertools = "0.14.0"
|
||||||
orchid-api = { version = "0.1.0", path = "../orchid-api" }
|
orchid-api = { version = "0.1.0", path = "../orchid-api" }
|
||||||
orchid-base = { version = "0.1.0", path = "../orchid-base" }
|
orchid-base = { version = "0.1.0", path = "../orchid-base" }
|
||||||
orchid-host = { version = "0.1.0", path = "../orchid-host", features = [
|
orchid-host = { version = "0.1.0", path = "../orchid-host", features = [
|
||||||
"tokio",
|
"tokio",
|
||||||
] }
|
] }
|
||||||
stacker = "0.1.23"
|
stacker = "0.1.23"
|
||||||
substack = "1.1.1"
|
substack = "1.1.1"
|
||||||
|
|||||||
118
orcx/src/main.rs
118
orcx/src/main.rs
@@ -41,46 +41,125 @@ use tokio::task::{LocalSet, spawn_local};
|
|||||||
use crate::parse_folder::parse_folder;
|
use crate::parse_folder::parse_folder;
|
||||||
use crate::repl::repl;
|
use crate::repl::repl;
|
||||||
|
|
||||||
|
/// Native interpreter for the Orchid programming language
|
||||||
#[derive(Parser, Debug)]
|
#[derive(Parser, Debug)]
|
||||||
#[command(version, about, long_about)]
|
#[command(version, about, long_about, verbatim_doc_comment)]
|
||||||
pub struct Args {
|
pub struct Args {
|
||||||
#[arg(short, long, env = "ORCHID_EXTENSIONS", value_delimiter = ';')]
|
/// Load an extension from a file. The file extension should be omitted, the
|
||||||
|
/// loader checks for a range of platform-specific file extensions (foo.exe
|
||||||
|
/// and foo.dll on Windows, libfoo.so or foo on other platforms)
|
||||||
|
#[arg(
|
||||||
|
short,
|
||||||
|
long,
|
||||||
|
env = "ORCHID_EXTENSIONS",
|
||||||
|
value_delimiter = ';',
|
||||||
|
next_line_help = true,
|
||||||
|
verbatim_doc_comment
|
||||||
|
)]
|
||||||
extension: Vec<Utf8PathBuf>,
|
extension: Vec<Utf8PathBuf>,
|
||||||
#[arg(short, long, env = "ORCHID_DEFAULT_SYSTEMS", value_delimiter = ';')]
|
/// Instantiate a system by name. The system must be provided by one of the
|
||||||
|
/// loaded extensions
|
||||||
|
#[arg(
|
||||||
|
short,
|
||||||
|
long,
|
||||||
|
env = "ORCHID_DEFAULT_SYSTEMS",
|
||||||
|
value_delimiter = ';',
|
||||||
|
next_line_help = true,
|
||||||
|
verbatim_doc_comment
|
||||||
|
)]
|
||||||
system: Vec<String>,
|
system: Vec<String>,
|
||||||
#[arg(short, long, default_value = "off", default_missing_value = "stderr")]
|
/// Send a log stream to a specific destination.
|
||||||
|
///
|
||||||
|
/// Supported formats:
|
||||||
|
/// - `--logs=msg>messaging.log`: the log channel `msg` will be routed to the
|
||||||
|
/// file `messaging.log`. If this is used, the following format should also
|
||||||
|
/// appear to specify what happens to other categories
|
||||||
|
/// - `--logs=orchid.log`: all unspecified channels will be routed to the file
|
||||||
|
/// `orchid.log`
|
||||||
|
/// - `--logs` only once with no value: all unspecified channels will be
|
||||||
|
/// routed to stderr
|
||||||
|
///
|
||||||
|
/// Some destination names have special meanings:
|
||||||
|
/// - `stderr` designates the platform-specific standard error output of the
|
||||||
|
/// interpreter process
|
||||||
|
/// - `off` discards received messages
|
||||||
|
///
|
||||||
|
/// Defaults for specific channels
|
||||||
|
/// - `warn` is routed the same as `debug`
|
||||||
|
/// - `error` is routed the same as `warn`
|
||||||
|
/// - `msg` is discarded (routed to `off`)
|
||||||
|
#[arg(
|
||||||
|
short,
|
||||||
|
long,
|
||||||
|
default_value = "off",
|
||||||
|
default_missing_value = "stderr",
|
||||||
|
next_line_help = true,
|
||||||
|
verbatim_doc_comment
|
||||||
|
)]
|
||||||
logs: Vec<String>,
|
logs: Vec<String>,
|
||||||
#[command(subcommand)]
|
/// Measure and report the timings of various events
|
||||||
command: Commands,
|
|
||||||
#[arg(long, action)]
|
#[arg(long, action)]
|
||||||
time: bool,
|
time: bool,
|
||||||
|
/// Project folder for subcommand-specific purpose
|
||||||
|
#[arg(long)]
|
||||||
|
proj: Option<Utf8PathBuf>,
|
||||||
|
/// Number of execution steps the interpreter is allowed to take. Use
|
||||||
|
/// `--no-gas` to disable the limit.
|
||||||
|
#[arg(long, default_value("10000"), next_line_help = true, verbatim_doc_comment)]
|
||||||
|
gas: u64,
|
||||||
|
/// Disable gas limiting, may cause infinite loops
|
||||||
|
#[arg(long, action)]
|
||||||
|
no_gas: bool,
|
||||||
|
#[command(subcommand)]
|
||||||
|
command: Commands,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Subcommand, Debug)]
|
#[derive(Subcommand, Debug)]
|
||||||
pub enum Commands {
|
pub enum Commands {
|
||||||
|
/// Tokenize some code using the current lexer plugins. Either --file or
|
||||||
|
/// --line, but not both, can specify the source code input
|
||||||
|
#[command(next_line_help = true, verbatim_doc_comment)]
|
||||||
Lex {
|
Lex {
|
||||||
|
/// Source file input
|
||||||
#[arg(long)]
|
#[arg(long)]
|
||||||
file: Option<Utf8PathBuf>,
|
file: Option<Utf8PathBuf>,
|
||||||
|
/// Raw source code input
|
||||||
#[arg(long)]
|
#[arg(long)]
|
||||||
line: Option<String>,
|
line: Option<String>,
|
||||||
},
|
},
|
||||||
|
/// Parse some code into module tree - the stage after tokenization but before
|
||||||
|
/// any execution
|
||||||
|
#[command(next_line_help = true, verbatim_doc_comment)]
|
||||||
Parse {
|
Parse {
|
||||||
#[arg(short, long)]
|
#[arg(short, long)]
|
||||||
file: Utf8PathBuf,
|
file: Utf8PathBuf,
|
||||||
},
|
},
|
||||||
|
/// Open an interactive shell
|
||||||
Repl,
|
Repl,
|
||||||
|
/// Print the module tree after parsing. This is similar to `parse`, but it
|
||||||
|
/// can traverse folders and show extension modules
|
||||||
|
#[command(next_line_help = true, verbatim_doc_comment)]
|
||||||
ModTree {
|
ModTree {
|
||||||
#[arg(long)]
|
/// Module to show
|
||||||
proj: Option<Utf8PathBuf>,
|
|
||||||
#[arg(long)]
|
#[arg(long)]
|
||||||
prefix: Option<String>,
|
prefix: Option<String>,
|
||||||
},
|
},
|
||||||
Exec {
|
/// Evaluate an expression. The most obvious use case is to read project
|
||||||
#[arg(long)]
|
/// metadata from scripts written in other languages. If proj is set, the
|
||||||
proj: Option<Utf8PathBuf>,
|
/// expression can refer to constants within this project by fully qualified
|
||||||
|
/// path
|
||||||
|
#[command(next_line_help = true, verbatim_doc_comment)]
|
||||||
|
Eval {
|
||||||
|
/// Expression to evaluate
|
||||||
#[arg()]
|
#[arg()]
|
||||||
code: String,
|
code: String,
|
||||||
},
|
},
|
||||||
|
/// Execute effectful Orchid code
|
||||||
|
Exec {
|
||||||
|
/// Entrypoint or startup command
|
||||||
|
#[arg()]
|
||||||
|
main: String,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
static mut STARTUP: Option<Instant> = None;
|
static mut STARTUP: Option<Instant> = None;
|
||||||
@@ -187,11 +266,11 @@ impl Spawner for SpawnerImpl {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn main() -> io::Result<ExitCode> {
|
fn main() -> io::Result<ExitCode> {
|
||||||
eprintln!("Orcx v0.1 is free software provided without warranty.");
|
|
||||||
// Use a 10MB stack for single-threaded, unoptimized operation
|
// Use a 10MB stack for single-threaded, unoptimized operation
|
||||||
stacker::grow(10 * 1024 * 1024, || {
|
stacker::grow(10 * 1024 * 1024, || {
|
||||||
tokio::runtime::Builder::new_current_thread().enable_all().build().unwrap().block_on(async {
|
tokio::runtime::Builder::new_current_thread().enable_all().build().unwrap().block_on(async {
|
||||||
let args = Args::parse();
|
let args = Args::parse();
|
||||||
|
eprintln!("Orcx v{} is free software provided without warranty.", clap::crate_version!());
|
||||||
let exit_code = Rc::new(RefCell::new(ExitCode::SUCCESS));
|
let exit_code = Rc::new(RefCell::new(ExitCode::SUCCESS));
|
||||||
let local_set = LocalSet::new();
|
let local_set = LocalSet::new();
|
||||||
let exit_code1 = exit_code.clone();
|
let exit_code1 = exit_code.clone();
|
||||||
@@ -248,9 +327,9 @@ fn main() -> io::Result<ExitCode> {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
Commands::Repl => repl(&args, &extensions, ctx.clone()).await?,
|
Commands::Repl => repl(&args, &extensions, ctx.clone()).await?,
|
||||||
Commands::ModTree { proj, prefix } => {
|
Commands::ModTree { prefix } => {
|
||||||
let (mut root, _systems) = init_systems(&args.system, &extensions).await.unwrap();
|
let (mut root, _systems) = init_systems(&args.system, &extensions).await.unwrap();
|
||||||
if let Some(proj_path) = proj {
|
if let Some(proj_path) = args.proj {
|
||||||
let path = proj_path.into_std_path_buf();
|
let path = proj_path.into_std_path_buf();
|
||||||
root = try_with_reporter(parse_folder(&root, path, sym!(src), ctx.clone()))
|
root = try_with_reporter(parse_folder(&root, path, sym!(src), ctx.clone()))
|
||||||
.await
|
.await
|
||||||
@@ -263,11 +342,11 @@ fn main() -> io::Result<ExitCode> {
|
|||||||
let root_data = root.0.read().await;
|
let root_data = root.0.read().await;
|
||||||
print_mod::print_mod(&root_data.root, prefix, &root_data).await;
|
print_mod::print_mod(&root_data.root, prefix, &root_data).await;
|
||||||
},
|
},
|
||||||
Commands::Exec { proj, code } => {
|
Commands::Eval { code } => {
|
||||||
let path = sym!(usercode);
|
let path = sym!(usercode);
|
||||||
let prefix_sr = SrcRange::zw(path.clone(), 0);
|
let prefix_sr = SrcRange::zw(path.clone(), 0);
|
||||||
let (mut root, systems) = init_systems(&args.system, &extensions).await.unwrap();
|
let (mut root, systems) = init_systems(&args.system, &extensions).await.unwrap();
|
||||||
if let Some(proj_path) = proj {
|
if let Some(proj_path) = args.proj {
|
||||||
let path = proj_path.into_std_path_buf();
|
let path = proj_path.into_std_path_buf();
|
||||||
root = try_with_reporter(parse_folder(&root, path, sym!(src), ctx.clone()))
|
root = try_with_reporter(parse_folder(&root, path, sym!(src), ctx.clone()))
|
||||||
.await
|
.await
|
||||||
@@ -298,7 +377,9 @@ fn main() -> io::Result<ExitCode> {
|
|||||||
.map_err(|e| e.to_string())?;
|
.map_err(|e| e.to_string())?;
|
||||||
let expr = ExprKind::Const(sym!(usercode::entrypoint)).at(prefix_sr.pos());
|
let expr = ExprKind::Const(sym!(usercode::entrypoint)).at(prefix_sr.pos());
|
||||||
let mut xctx = ExecCtx::new(root.clone(), expr).await;
|
let mut xctx = ExecCtx::new(root.clone(), expr).await;
|
||||||
xctx.set_gas(Some(10_000));
|
if !args.no_gas {
|
||||||
|
xctx.set_gas(Some(args.gas));
|
||||||
|
}
|
||||||
match xctx.execute().await {
|
match xctx.execute().await {
|
||||||
ExecResult::Value(val, _) => {
|
ExecResult::Value(val, _) => {
|
||||||
println!("{}", take_first(&val.print(&FmtCtxImpl::default()).await, false))
|
println!("{}", take_first(&val.print(&FmtCtxImpl::default()).await, false))
|
||||||
@@ -307,6 +388,9 @@ fn main() -> io::Result<ExitCode> {
|
|||||||
ExecResult::Gas(_) => println!("Ran out of gas!"),
|
ExecResult::Gas(_) => println!("Ran out of gas!"),
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
Commands::Exec { main: _ } => {
|
||||||
|
todo!("Integration of the command system is in-dev")
|
||||||
|
},
|
||||||
};
|
};
|
||||||
Ok(())
|
Ok(())
|
||||||
})
|
})
|
||||||
|
|||||||
Reference in New Issue
Block a user