Make run subcommand.
This commit is contained in:
parent
ebca87ddb9
commit
b88b230495
161
dm/src/main.rs
161
dm/src/main.rs
@ -1,22 +1,19 @@
|
|||||||
use clap::Parser;
|
mod run;
|
||||||
use codespan_reporting::diagnostic::Label;
|
|
||||||
use codespan_reporting::files::SimpleFiles;
|
use crate::run::run;
|
||||||
use codespan_reporting::term;
|
use clap::{Parser, Subcommand};
|
||||||
use codespan_reporting::term::termcolor::{ColorChoice, StandardStream};
|
|
||||||
use dm_std_lib::add_all_std_core;
|
|
||||||
use dmc_lib::constants_table::ConstantsTable;
|
|
||||||
use dmc_lib::diagnostic::Diagnostic;
|
|
||||||
use dmc_lib::parser::parse_compilation_unit;
|
|
||||||
use dmc_lib::symbol_table::SymbolTable;
|
|
||||||
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::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
|
||||||
#[derive(Debug, Parser)]
|
#[derive(Debug, Parser)]
|
||||||
#[command(name = "dm", about = "Deimos", version = "0.1.0", long_about = None)]
|
#[command(name = "dm", about = "Deimos", version = "0.1.0", long_about = None)]
|
||||||
struct Cli {
|
struct Cli {
|
||||||
|
#[command(subcommand)]
|
||||||
|
sub_command: SubCommand,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Subcommand)]
|
||||||
|
enum SubCommand {
|
||||||
|
Run {
|
||||||
script: PathBuf,
|
script: PathBuf,
|
||||||
|
|
||||||
#[arg(long)]
|
#[arg(long)]
|
||||||
@ -27,137 +24,19 @@ struct Cli {
|
|||||||
|
|
||||||
#[arg(long, default_value = "8")]
|
#[arg(long, default_value = "8")]
|
||||||
register_count: usize,
|
register_count: usize,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let args = Cli::parse();
|
let args = Cli::parse();
|
||||||
let input = std::fs::read_to_string(&args.script).unwrap();
|
match &args.sub_command {
|
||||||
|
SubCommand::Run {
|
||||||
let mut files: SimpleFiles<&str, &str> = SimpleFiles::new();
|
script,
|
||||||
let script_file_id = files.add(args.script.to_str().unwrap(), &input);
|
show_asm,
|
||||||
|
show_ir,
|
||||||
let parse_result = parse_compilation_unit(&input);
|
register_count,
|
||||||
let mut compilation_unit = match parse_result {
|
} => {
|
||||||
Ok(compilation_unit) => compilation_unit,
|
run(script, *show_asm, *show_ir, *register_count);
|
||||||
Err(diagnostics) => {
|
|
||||||
check_and_report_diagnostics(&files, script_file_id, &diagnostics);
|
|
||||||
unreachable!();
|
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
let mut symbol_table = SymbolTable::new();
|
|
||||||
|
|
||||||
match compilation_unit.gather_declared_names(&mut symbol_table) {
|
|
||||||
Ok(_) => {}
|
|
||||||
Err(diagnostics) => {
|
|
||||||
report_and_exit(&diagnostics, script_file_id, &files);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
match compilation_unit.check_name_usages(&symbol_table) {
|
|
||||||
Ok(_) => {}
|
|
||||||
Err(diagnostics) => {
|
|
||||||
report_and_exit(&diagnostics, script_file_id, &files);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
match compilation_unit.type_check(&symbol_table) {
|
|
||||||
Ok(_) => {}
|
|
||||||
Err(diagnostics) => {
|
|
||||||
report_and_exit(&diagnostics, script_file_id, &files);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut ir_functions = compilation_unit.to_ir(&symbol_table);
|
|
||||||
|
|
||||||
if args.show_ir {
|
|
||||||
for ir_function in &ir_functions {
|
|
||||||
println!("{}", ir_function);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut functions: Vec<Function> = vec![];
|
|
||||||
let mut constants_table = ConstantsTable::new();
|
|
||||||
|
|
||||||
for ir_function in &mut ir_functions {
|
|
||||||
let (_, stack_size) = ir_function.assign_registers(args.register_count);
|
|
||||||
let function = ir_function.assemble(stack_size, &mut constants_table);
|
|
||||||
functions.push(function);
|
|
||||||
}
|
|
||||||
|
|
||||||
if args.show_asm {
|
|
||||||
for function in &functions {
|
|
||||||
println!("{}", function);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut dvm_context = DvmContext::new();
|
|
||||||
|
|
||||||
// add std::core fns
|
|
||||||
add_all_std_core(&mut dvm_context);
|
|
||||||
|
|
||||||
for function in functions {
|
|
||||||
dvm_context
|
|
||||||
.functions_mut()
|
|
||||||
.insert(function.name_owned(), function);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (name, content) in &constants_table.string_constants() {
|
|
||||||
dvm_context.constants_mut().insert(
|
|
||||||
name.clone(),
|
|
||||||
Constant::String(StringConstant::new(name.clone(), content.clone())),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut registers: Vec<Value> = vec![Value::Null; args.register_count];
|
|
||||||
let mut call_stack = CallStack::new();
|
|
||||||
|
|
||||||
let result = call(
|
|
||||||
&dvm_context,
|
|
||||||
&mut registers,
|
|
||||||
&mut call_stack,
|
|
||||||
"main",
|
|
||||||
&vec![],
|
|
||||||
);
|
|
||||||
if let Some(value) = result {
|
|
||||||
println!("{}", value);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_and_report_diagnostics(
|
|
||||||
files: &SimpleFiles<&str, &str>,
|
|
||||||
script_file_id: usize,
|
|
||||||
diagnostics: &[Diagnostic],
|
|
||||||
) {
|
|
||||||
if !diagnostics.is_empty() {
|
|
||||||
report_and_exit(diagnostics, script_file_id, files);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn report_and_exit(
|
|
||||||
diagnostics: &[Diagnostic],
|
|
||||||
script_file_id: usize,
|
|
||||||
files: &SimpleFiles<&str, &str>,
|
|
||||||
) -> ! {
|
|
||||||
let writer = StandardStream::stderr(ColorChoice::Always);
|
|
||||||
let config = term::Config::default();
|
|
||||||
for diagnostic in diagnostics {
|
|
||||||
let csr_diagnostic = codespan_reporting::diagnostic::Diagnostic::error()
|
|
||||||
.with_message(diagnostic.message())
|
|
||||||
.with_label(Label::primary(
|
|
||||||
script_file_id,
|
|
||||||
diagnostic.start()..diagnostic.end(),
|
|
||||||
));
|
|
||||||
|
|
||||||
term::emit_to_write_style(&mut writer.lock(), &config, files, &csr_diagnostic).unwrap();
|
|
||||||
}
|
|
||||||
if diagnostics.len() == 1 {
|
|
||||||
eprintln!("There was 1 diagnostic. See above for more information.");
|
|
||||||
} else {
|
|
||||||
eprintln!(
|
|
||||||
"There were {} diagnostics. See above for more information.",
|
|
||||||
diagnostics.len()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
std::process::exit(1);
|
|
||||||
}
|
|
||||||
|
|||||||
146
dm/src/run.rs
Normal file
146
dm/src/run.rs
Normal file
@ -0,0 +1,146 @@
|
|||||||
|
use codespan_reporting::diagnostic::Label;
|
||||||
|
use codespan_reporting::files::SimpleFiles;
|
||||||
|
use codespan_reporting::term;
|
||||||
|
use codespan_reporting::term::termcolor::{ColorChoice, StandardStream};
|
||||||
|
use dm_std_lib::add_all_std_core;
|
||||||
|
use dmc_lib::constants_table::ConstantsTable;
|
||||||
|
use dmc_lib::diagnostic::Diagnostic;
|
||||||
|
use dmc_lib::parser::parse_compilation_unit;
|
||||||
|
use dmc_lib::symbol_table::SymbolTable;
|
||||||
|
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::path::PathBuf;
|
||||||
|
|
||||||
|
pub fn run(script: &PathBuf, show_ir: bool, show_asm: bool, register_count: usize) {
|
||||||
|
let input = std::fs::read_to_string(script).unwrap();
|
||||||
|
|
||||||
|
let mut files: SimpleFiles<&str, &str> = SimpleFiles::new();
|
||||||
|
let script_file_id = files.add(script.to_str().unwrap(), &input);
|
||||||
|
|
||||||
|
let parse_result = parse_compilation_unit(&input);
|
||||||
|
let mut compilation_unit = match parse_result {
|
||||||
|
Ok(compilation_unit) => compilation_unit,
|
||||||
|
Err(diagnostics) => {
|
||||||
|
check_and_report_diagnostics(&files, script_file_id, &diagnostics);
|
||||||
|
unreachable!();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut symbol_table = SymbolTable::new();
|
||||||
|
|
||||||
|
match compilation_unit.gather_declared_names(&mut symbol_table) {
|
||||||
|
Ok(_) => {}
|
||||||
|
Err(diagnostics) => {
|
||||||
|
report_and_exit(&diagnostics, script_file_id, &files);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
match compilation_unit.check_name_usages(&symbol_table) {
|
||||||
|
Ok(_) => {}
|
||||||
|
Err(diagnostics) => {
|
||||||
|
report_and_exit(&diagnostics, script_file_id, &files);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
match compilation_unit.type_check(&symbol_table) {
|
||||||
|
Ok(_) => {}
|
||||||
|
Err(diagnostics) => {
|
||||||
|
report_and_exit(&diagnostics, script_file_id, &files);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut ir_functions = compilation_unit.to_ir(&symbol_table);
|
||||||
|
|
||||||
|
if show_ir {
|
||||||
|
for ir_function in &ir_functions {
|
||||||
|
println!("{}", ir_function);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut functions: Vec<Function> = vec![];
|
||||||
|
let mut constants_table = ConstantsTable::new();
|
||||||
|
|
||||||
|
for ir_function in &mut ir_functions {
|
||||||
|
let (_, stack_size) = ir_function.assign_registers(register_count);
|
||||||
|
let function = ir_function.assemble(stack_size, &mut constants_table);
|
||||||
|
functions.push(function);
|
||||||
|
}
|
||||||
|
|
||||||
|
if show_asm {
|
||||||
|
for function in &functions {
|
||||||
|
println!("{}", function);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut dvm_context = DvmContext::new();
|
||||||
|
|
||||||
|
// add std::core fns
|
||||||
|
add_all_std_core(&mut dvm_context);
|
||||||
|
|
||||||
|
for function in functions {
|
||||||
|
dvm_context
|
||||||
|
.functions_mut()
|
||||||
|
.insert(function.name_owned(), function);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (name, content) in &constants_table.string_constants() {
|
||||||
|
dvm_context.constants_mut().insert(
|
||||||
|
name.clone(),
|
||||||
|
Constant::String(StringConstant::new(name.clone(), content.clone())),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut registers: Vec<Value> = vec![Value::Null; register_count];
|
||||||
|
let mut call_stack = CallStack::new();
|
||||||
|
|
||||||
|
let result = call(
|
||||||
|
&dvm_context,
|
||||||
|
&mut registers,
|
||||||
|
&mut call_stack,
|
||||||
|
"main",
|
||||||
|
&vec![],
|
||||||
|
);
|
||||||
|
if let Some(value) = result {
|
||||||
|
println!("{}", value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn check_and_report_diagnostics(
|
||||||
|
files: &SimpleFiles<&str, &str>,
|
||||||
|
script_file_id: usize,
|
||||||
|
diagnostics: &[Diagnostic],
|
||||||
|
) {
|
||||||
|
if !diagnostics.is_empty() {
|
||||||
|
report_and_exit(diagnostics, script_file_id, files);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn report_and_exit(
|
||||||
|
diagnostics: &[Diagnostic],
|
||||||
|
script_file_id: usize,
|
||||||
|
files: &SimpleFiles<&str, &str>,
|
||||||
|
) -> ! {
|
||||||
|
let writer = StandardStream::stderr(ColorChoice::Always);
|
||||||
|
let config = term::Config::default();
|
||||||
|
for diagnostic in diagnostics {
|
||||||
|
let csr_diagnostic = codespan_reporting::diagnostic::Diagnostic::error()
|
||||||
|
.with_message(diagnostic.message())
|
||||||
|
.with_label(Label::primary(
|
||||||
|
script_file_id,
|
||||||
|
diagnostic.start()..diagnostic.end(),
|
||||||
|
));
|
||||||
|
|
||||||
|
term::emit_to_write_style(&mut writer.lock(), &config, files, &csr_diagnostic).unwrap();
|
||||||
|
}
|
||||||
|
if diagnostics.len() == 1 {
|
||||||
|
eprintln!("There was 1 diagnostic. See above for more information.");
|
||||||
|
} else {
|
||||||
|
eprintln!(
|
||||||
|
"There were {} diagnostics. See above for more information.",
|
||||||
|
diagnostics.len()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
std::process::exit(1);
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user