Skip to content

Commit

Permalink
Merge pull request #2 from whitenois3/feat/builtins
Browse files Browse the repository at this point in the history
Start builtin command module
  • Loading branch information
clabby authored Oct 8, 2022
2 parents cee35fd + 1fe513d commit b55227d
Show file tree
Hide file tree
Showing 5 changed files with 106 additions and 12 deletions.
7 changes: 5 additions & 2 deletions Cargo.lock

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

1 change: 1 addition & 0 deletions chisel/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,4 @@ ethers-solc = { git = "https://github.com/gakonst/ethers-rs", features = ["proje
rustyline = "10.0.0"
solang-parser = "0.1.18"
tracing = "0.1.37"
strum = { version = "0.24.1", features = ["derive"] }
44 changes: 37 additions & 7 deletions chisel/src/chisel.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use crate::env::ChiselEnv;
use ansi_term::Color::{Green, Red};
use clap::Parser;
use cmd::ChiselCommand;
use rustyline::error::ReadlineError;

/// REPL env.
Expand All @@ -14,11 +15,13 @@ pub mod sol_highlighter;

/// Prompt arrow slice
static PROMPT_ARROW: &str = "➜ ";
/// Command leader character
static COMMAND_LEADER: char = '!';

/// Chisel is a fast, utilitarian, and verbose solidity REPL.
#[derive(Debug, Parser)]
#[clap(name = "chisel", version = "v0.0.1-alpha")]
pub struct ChiselCommand {
pub struct ChiselParser {
/// Set the RPC URL to fork.
#[clap(long, short)]
pub fork_url: Option<String>,
Expand All @@ -30,7 +33,7 @@ pub struct ChiselCommand {

fn main() {
// Parse command args
let _args = ChiselCommand::parse();
let _args = ChiselParser::parse();

// Set up default `ChiselEnv` Configuration
let mut env = ChiselEnv::default();
Expand All @@ -41,7 +44,6 @@ fn main() {
// Keeps track of whether or not the last input resulted in an error
// TODO: This will probably best be tracked in the `ChiselEnv`,
// just for mocking up the project.
#[allow(unused_mut)]
let mut error = false;

// Begin Rustyline loop
Expand All @@ -51,21 +53,49 @@ fn main() {

match env.rl.readline(prompt.as_str()) {
Ok(line) => {
// Parse the input with [solang-parser](https)
// Check if the input is a builtin command.
// Commands are denoted with a `!` leading character.
if line.starts_with(COMMAND_LEADER) {
let split: Vec<&str> = line.split(' ').collect();
let raw_cmd = &split[0][1..];

match raw_cmd.parse::<ChiselCommand>() {
Ok(cmd) => {
// TODO: Move `error` to the `ChiselEnv`, dispatch
// could still result in an error.
error = false;
cmd.dispatch(&split[1..], &env);
}
Err(e) => {
error = true;
eprintln!("{}", e);
}
}
continue
}

// Parse the input with [solang-parser](https://docs.rs/solang-parser/latest/solang_parser)
// Print dianostics and continue on error
// If parsing successful, grab the (source unit, comment) tuple
//
// TODO: This does check if the line is parsed successfully, but does
// not check if the line conflicts with any previous declarations
// (i.e. "uint a = 1;" could be declared twice). Should check against
// the whole temp file so that previous inputs persist.
let parsed = match solang_parser::parse(&line, 0) {
Ok(su) => su,
Err(e) => {
eprintln!("{}", Red.paint("Compilation error"));
eprintln!("{}", Red.paint(format!("{:?}", e)));
error = true;
continue;
eprintln!("{}", Red.paint(format!("{:?}", e)));
error = true;
continue
}
};

// Reset interrupt flag
interrupt = false;
// Reset error flag
error = false;

// Push the parsed source unit and comments to the environment session
env.session.push(parsed);
Expand Down
60 changes: 59 additions & 1 deletion chisel/src/cmd.rs
Original file line number Diff line number Diff line change
@@ -1 +1,59 @@
// TODO
use crate::env::ChiselEnv;
use ansi_term::Color::{Cyan, Green, Red};
use std::{error, str::FromStr};
use strum::{EnumIter, IntoEnumIterator};

/// Custom Chisel commands
#[derive(Debug, EnumIter)]
pub enum ChiselCommand {
Help,
Source,
}

/// A command descriptor type
type CmdDescriptor = (&'static str, &'static str);

/// Custom Chisel command implementations
#[allow(dead_code, unused)]
impl ChiselCommand {
pub fn dispatch(&self, args: &[&str], env: &ChiselEnv) {
match self {
ChiselCommand::Help => {
println!("{}", Cyan.paint("⚒️ Chisel help"));
ChiselCommand::iter().for_each(|cmd| {
let descriptor = CmdDescriptor::from(cmd);
println!("!{} - {}", Green.paint(descriptor.0), descriptor.1);
});
}
ChiselCommand::Source => println!("{}", env.contract_source()),
}
}
}

/// Attempt to convert a string slice to a `ChiselCommand`
impl FromStr for ChiselCommand {
type Err = Box<dyn error::Error>;

fn from_str(s: &str) -> Result<Self, Self::Err> {
match s.to_lowercase().as_ref() {
"help" => Ok(ChiselCommand::Help),
"source" => Ok(ChiselCommand::Source),
_ => Err(Red
.paint(format!("Unknown command \"{}\"! See available commands with `!help`.", s))
.to_string()
.into()),
}
}
}

/// Convert a `ChiselCommand` into a `CmdDescriptor` tuple
impl From<ChiselCommand> for CmdDescriptor {
fn from(cmd: ChiselCommand) -> Self {
match cmd {
ChiselCommand::Help => ("help", "Display all commands"),
ChiselCommand::Source => {
("source", "Display the source code of the current REPL session")
}
}
}
}
6 changes: 4 additions & 2 deletions chisel/src/env.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,14 +38,16 @@ impl ChiselEnv {
}

/// Render the full source code for the current session.
/// TODO
/// TODO - Render source correctly, not `SourceUnit`s.
pub fn contract_source(&self) -> String {
format!(
r#"
// SPDX-License-Identifier: UNLICENSED
pragma solidity {};
contract REPL {{
{:?}
fallback() {{
{:?}
}}
}}
"#,
"^0.8.17", // TODO: Grab version from TempProject's solc instance.
Expand Down

0 comments on commit b55227d

Please sign in to comment.