Skip to content
This repository has been archived by the owner on Jun 3, 2021. It is now read-only.

Implement proper REPL #515

Open
wants to merge 10 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion saltwater-repl/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "saltwater-repl"
version = "0.1.0"
version = "0.11.0"
authors = ["Justus K <[email protected]>"]
edition = "2018"

Expand Down
30 changes: 14 additions & 16 deletions saltwater-repl/commands.rs
Original file line number Diff line number Diff line change
@@ -1,27 +1,25 @@
use crate::repl::Repl;
use std::fmt::Write;

macro_rules! cmds {
($($($name:expr),* ; $description:expr => $action:expr),*$(,)?) => {{
let mut cmds = Vec::new();
$(
cmds.push(Command { names: &[$($name),*], description: $description, action: $action });
)*
cmds
}};
}

pub struct Command {
pub names: &'static [&'static str],
pub description: &'static str,
pub action: fn(&mut Repl, &str),
}

pub fn default_commands() -> Vec<Command> {
cmds! {
"help", "h"; "Shows this help message" => help_command,
"quit", "q"; "Quits the repl" => quit_command,
}
vec![
Command {
names: &["help", "h"],
description: "Shows this help message",
action: help_command,
},
Command {
names: &["quit", "q"],
description: "Quits the repl",
action: quit_command,
},
]
}

pub fn generate_help_message(cmds: &[Command]) -> String {
Expand All @@ -39,13 +37,13 @@ pub fn generate_help_message(cmds: &[Command]) -> String {
cmd.description
)?;
}
Ok::<String, Box<dyn std::error::Error>>(buf)
Ok::<String, std::fmt::Error>(buf)
};
inner().expect("failed to generate help message")
}

fn help_command(repl: &mut Repl, _args: &str) {
print!("{}", repl.help_message);
println!("{}", repl.help_message);
}

fn quit_command(repl: &mut Repl, _args: &str) {
Stupremee marked this conversation as resolved.
Show resolved Hide resolved
Expand Down
6 changes: 5 additions & 1 deletion saltwater-repl/helper.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,11 @@ impl Highlighter for ReplHelper {

impl Validator for ReplHelper {
fn validate(&self, ctx: &mut ValidationContext<'_>) -> rustyline::Result<ValidationResult> {
let result = crate::repl::analyze_expr(ctx.input());
if ctx.input().starts_with(crate::repl::PREFIX) {
return Ok(ValidationResult::Valid(None));
Stupremee marked this conversation as resolved.
Show resolved Hide resolved
}

let result = crate::repl::analyze_expr(ctx.input().to_string());
if let Err(err) = result {
Ok(ValidationResult::Invalid(Some(err.data.to_string())))
} else {
Expand Down
38 changes: 26 additions & 12 deletions saltwater-repl/repl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,12 @@ pub(crate) const PREFIX: char = ':';
const VERSION: &str = env!("CARGO_PKG_VERSION");
const PROMPT: &str = ">> ";

/// Takes a function pointer and transmute it into a function
/// that returns the given type. Then executes it and returns the result.
///
/// # Safety
///
/// `$fun` has to be a valid pointer to a function that returns the `$ty`.
macro_rules! execute {
Stupremee marked this conversation as resolved.
Show resolved Hide resolved
($fun:ident, $ty:tt) => {
unsafe {
Expand Down Expand Up @@ -64,7 +70,7 @@ impl Repl {
self.load_history();

println!("Saltwater {}", VERSION);
println!(r#"Type "{}help" for more information."#, PREFIX);
println!("Type {}help for more information.", PREFIX);
let result = loop {
let line = self.editor.readline(PROMPT);
match line {
Expand Down Expand Up @@ -100,9 +106,9 @@ impl Repl {
fn process_line(&mut self, line: String) {
self.editor.add_history_entry(line.clone());

let line = line.trim();
if line.starts_with(PREFIX) {
let name = line.split(' ').next().unwrap();
let trimmed_line = line.trim();
if trimmed_line.starts_with(PREFIX) {
let name = trimmed_line.split(' ').next().unwrap();

match self
.commands
Expand All @@ -111,7 +117,7 @@ impl Repl {
{
Some(cmd) => {
let action = cmd.action;
action(self, &line[name.len()..])
action(self, &trimmed_line[name.len()..])
}
None => println!("unknown command '{}'", name),
}
Expand All @@ -126,7 +132,7 @@ impl Repl {
}
}

fn execute_code(&mut self, code: &str) -> Result<(), CompileError> {
fn execute_code(&mut self, code: String) -> Result<(), CompileError> {
let module = initialize_jit_module();

let expr = analyze_expr(code)?;
Expand All @@ -138,8 +144,16 @@ impl Repl {
jit.finalize();
let fun = jit
.get_compiled_function("execute")
.expect("this is not good.");

.expect("wrap_expr should create a function named `execute`");

//let sizes = saltwater_parser::arch::TARGET
//.data_model()
//.expect("unknown target");
//assert_eq!(sizes.short_size().bits(), 16);
//assert_eq!(sizes.int_size().bits(), 32);
//assert_eq!(sizes.long_size().bits(), 64);
//assert_eq!(sizes.float_size().bits(), 32);
//assert_eq!(sizes.double_size().bits(), 64);
match expr_ty {
Type::Short(true) => println!("=> {}", execute!(fun, i16)),
Type::Short(false) => println!("=> {}", execute!(fun, u16)),
Expand All @@ -165,7 +179,7 @@ impl Repl {
Type::Void => execute!(fun, ()),

// TODO: Implement execution for more types
ty => println!("error: expression returns unsupported type: {:?}", ty),
ty => println!("error: expression has an unsupported type: {:?}", ty),
Stupremee marked this conversation as resolved.
Show resolved Hide resolved
};
Ok(())
}
Expand All @@ -185,7 +199,7 @@ fn wrap_expr(expr: Expr) -> Locatable<Declaration> {
params: vec![],
varargs: false,
}),
storage_class: data::StorageClass::Extern,
storage_class: data::StorageClass::Static,
qualifiers: Default::default(),
id: "execute".into(),
};
Expand All @@ -200,8 +214,8 @@ fn wrap_expr(expr: Expr) -> Locatable<Declaration> {
span.with(decl)
}

pub fn analyze_expr(code: &str) -> Result<Expr, Locatable<data::Error>> {
let code = format!("{}\n", code).into_boxed_str();
pub fn analyze_expr(mut code: String) -> Result<Expr, Locatable<data::Error>> {
code.push('\n');
let cpp = PreProcessorBuilder::new(code).build();
let mut parser = Parser::new(cpp, false);
let expr = parser.expr()?;
Expand Down