Add repl subcommand with expressions only.
This commit is contained in:
parent
b88b230495
commit
705436ba61
@ -1,5 +1,7 @@
|
|||||||
|
mod repl;
|
||||||
mod run;
|
mod run;
|
||||||
|
|
||||||
|
use crate::repl::repl;
|
||||||
use crate::run::run;
|
use crate::run::run;
|
||||||
use clap::{Parser, Subcommand};
|
use clap::{Parser, Subcommand};
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
@ -25,6 +27,10 @@ enum SubCommand {
|
|||||||
#[arg(long, default_value = "8")]
|
#[arg(long, default_value = "8")]
|
||||||
register_count: usize,
|
register_count: usize,
|
||||||
},
|
},
|
||||||
|
Repl {
|
||||||
|
#[arg(long, default_value = "8")]
|
||||||
|
register_count: usize,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
@ -38,5 +44,8 @@ fn main() {
|
|||||||
} => {
|
} => {
|
||||||
run(script, *show_asm, *show_ir, *register_count);
|
run(script, *show_asm, *show_ir, *register_count);
|
||||||
}
|
}
|
||||||
|
SubCommand::Repl { register_count } => {
|
||||||
|
repl(*register_count);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
140
dm/src/repl.rs
Normal file
140
dm/src/repl.rs
Normal file
@ -0,0 +1,140 @@
|
|||||||
|
use dmc_lib::ast::ir_builder::IrBuilder;
|
||||||
|
use dmc_lib::constants_table::ConstantsTable;
|
||||||
|
use dmc_lib::diagnostic::Diagnostic;
|
||||||
|
use dmc_lib::ir::ir_function::IrFunction;
|
||||||
|
use dmc_lib::ir::ir_return::IrReturn;
|
||||||
|
use dmc_lib::ir::ir_statement::IrStatement;
|
||||||
|
use dmc_lib::lexer::Lexer;
|
||||||
|
use dmc_lib::parser::parse_expression;
|
||||||
|
use dmc_lib::symbol::FunctionSymbol;
|
||||||
|
use dmc_lib::symbol_table::SymbolTable;
|
||||||
|
use dmc_lib::token::TokenKind;
|
||||||
|
use dvm_lib::vm::constant::{Constant, StringConstant};
|
||||||
|
use dvm_lib::vm::function::Function;
|
||||||
|
use dvm_lib::vm::value::Value;
|
||||||
|
use dvm_lib::vm::{CallStack, DvmContext, call};
|
||||||
|
use std::cell::RefCell;
|
||||||
|
use std::io;
|
||||||
|
use std::io::Write;
|
||||||
|
use std::rc::Rc;
|
||||||
|
|
||||||
|
pub fn repl(register_count: usize) {
|
||||||
|
let mut buffer = String::new();
|
||||||
|
|
||||||
|
let mut constants_table = ConstantsTable::new();
|
||||||
|
let mut context = DvmContext::new();
|
||||||
|
|
||||||
|
'repl: loop {
|
||||||
|
print!("> ");
|
||||||
|
io::stdout().flush().unwrap();
|
||||||
|
io::stdin().read_line(&mut buffer).unwrap();
|
||||||
|
let input = buffer.trim();
|
||||||
|
if input.is_empty() {
|
||||||
|
buffer.clear();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut lexer = Lexer::new(input);
|
||||||
|
let first_token = match lexer.next() {
|
||||||
|
None => {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
Some(result) => match result {
|
||||||
|
Ok(first_token) => first_token,
|
||||||
|
Err(lexer_error) => {
|
||||||
|
eprintln!("{:?}", lexer_error);
|
||||||
|
buffer.clear();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
match first_token.kind() {
|
||||||
|
TokenKind::Fn => {
|
||||||
|
todo!("Parse functions in repl")
|
||||||
|
}
|
||||||
|
TokenKind::Let => {
|
||||||
|
todo!("Parse let statements in repl")
|
||||||
|
}
|
||||||
|
_ => match compile_expression(input, register_count, &mut constants_table) {
|
||||||
|
Ok(function) => {
|
||||||
|
context
|
||||||
|
.functions_mut()
|
||||||
|
.insert(function.name_owned(), function);
|
||||||
|
}
|
||||||
|
Err(diagnostics) => {
|
||||||
|
for diagnostic in &diagnostics {
|
||||||
|
eprintln!("{}", diagnostic.message());
|
||||||
|
buffer.clear();
|
||||||
|
continue 'repl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for (name, content) in constants_table.string_constants() {
|
||||||
|
context.constants_mut().insert(
|
||||||
|
name.clone(),
|
||||||
|
Constant::String(StringConstant::new(name, content)),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut registers = vec![Value::Null; register_count];
|
||||||
|
let mut call_stack = CallStack::new();
|
||||||
|
|
||||||
|
let result = call(&context, &mut registers, &mut call_stack, "__repl", &[]);
|
||||||
|
if let Some(value) = result {
|
||||||
|
println!("{}", value);
|
||||||
|
}
|
||||||
|
|
||||||
|
buffer.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn compile_expression(
|
||||||
|
input: &str,
|
||||||
|
register_count: usize,
|
||||||
|
constants_table: &mut ConstantsTable,
|
||||||
|
) -> Result<Function, Vec<Diagnostic>> {
|
||||||
|
let parse_result = parse_expression(input);
|
||||||
|
let mut expression = parse_result?;
|
||||||
|
|
||||||
|
let mut symbol_table = SymbolTable::new();
|
||||||
|
// "fake" scope
|
||||||
|
symbol_table.push_scope("__repl_enter");
|
||||||
|
expression.gather_declared_names(&mut symbol_table)?;
|
||||||
|
symbol_table.pop_scope();
|
||||||
|
|
||||||
|
expression.check_name_usages(&symbol_table)?;
|
||||||
|
expression.type_check(&symbol_table)?;
|
||||||
|
|
||||||
|
// synthesize a function
|
||||||
|
let mut ir_builder = IrBuilder::new();
|
||||||
|
let entry_block_id = ir_builder.new_block();
|
||||||
|
|
||||||
|
let maybe_ir_expression = expression.to_ir(&mut ir_builder, &symbol_table);
|
||||||
|
|
||||||
|
// if Some, return the value
|
||||||
|
ir_builder
|
||||||
|
.current_block_mut()
|
||||||
|
.add_statement(IrStatement::Return(IrReturn::new(maybe_ir_expression)));
|
||||||
|
|
||||||
|
ir_builder.finish_block();
|
||||||
|
let entry_block = ir_builder.get_block(entry_block_id);
|
||||||
|
|
||||||
|
// synthesize symbol
|
||||||
|
let fake_function_symbol = Rc::new(RefCell::new(FunctionSymbol::new(
|
||||||
|
"__repl",
|
||||||
|
false,
|
||||||
|
expression.type_info().clone(), // dubious
|
||||||
|
)));
|
||||||
|
let mut ir_function = IrFunction::new(
|
||||||
|
fake_function_symbol,
|
||||||
|
&[],
|
||||||
|
expression.type_info(),
|
||||||
|
entry_block.clone(),
|
||||||
|
);
|
||||||
|
|
||||||
|
let (_, stack_size) = ir_function.assign_registers(register_count);
|
||||||
|
Ok(ir_function.assemble(stack_size, constants_table))
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user