separate interpreter and compiler
This commit is contained in:
43
Cargo.lock
generated
43
Cargo.lock
generated
@@ -133,6 +133,18 @@ version = "1.0.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990"
|
||||
|
||||
[[package]]
|
||||
name = "compiler"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"byteorder",
|
||||
"clap",
|
||||
"integer-encoding",
|
||||
"itertools",
|
||||
"thiserror",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossterm"
|
||||
version = "0.25.0"
|
||||
@@ -158,19 +170,6 @@ dependencies = [
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "developing-compilers"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"byteorder",
|
||||
"clap",
|
||||
"inquire",
|
||||
"integer-encoding",
|
||||
"itertools",
|
||||
"thiserror",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dyn-clone"
|
||||
version = "1.0.17"
|
||||
@@ -230,6 +229,20 @@ version = "4.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0d762194228a2f1c11063e46e32e5acb96e66e906382b9eb5441f2e0504bbd5a"
|
||||
|
||||
[[package]]
|
||||
name = "interpreter"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"byteorder",
|
||||
"clap",
|
||||
"compiler",
|
||||
"inquire",
|
||||
"integer-encoding",
|
||||
"itertools",
|
||||
"thiserror",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "is_terminal_polyfill"
|
||||
version = "1.70.1"
|
||||
@@ -247,9 +260,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.162"
|
||||
version = "0.2.164"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "18d287de67fe55fd7e1581fe933d965a5a9477b38e949cfa9f8574ef01506398"
|
||||
checksum = "433bfe06b8c75da9b2e3fbea6e5329ff87748f0b144ef75306e674c3f6f7c13f"
|
||||
|
||||
[[package]]
|
||||
name = "lock_api"
|
||||
|
||||
10
Cargo.toml
10
Cargo.toml
@@ -1,13 +1,11 @@
|
||||
[package]
|
||||
edition = "2021"
|
||||
name = "developing-compilers"
|
||||
version = "0.1.0"
|
||||
[workspace]
|
||||
members = ["crates/compiler", "crates/interpreter"]
|
||||
resolver = "2"
|
||||
|
||||
[dependencies]
|
||||
[workspace.dependencies]
|
||||
anyhow = "1.0.89"
|
||||
byteorder = "1.5.0"
|
||||
clap = { version = "4.5.19", features = ["derive"] }
|
||||
inquire = "0.7.5"
|
||||
integer-encoding = "4.0.2"
|
||||
itertools = "0.13.0"
|
||||
thiserror = "2.0.3"
|
||||
|
||||
12
crates/compiler/Cargo.toml
Normal file
12
crates/compiler/Cargo.toml
Normal file
@@ -0,0 +1,12 @@
|
||||
[package]
|
||||
edition = "2021"
|
||||
name = "compiler"
|
||||
version = "0.1.0"
|
||||
|
||||
[dependencies]
|
||||
anyhow = { workspace = true }
|
||||
byteorder = { workspace = true }
|
||||
clap = { workspace = true }
|
||||
integer-encoding = { workspace = true }
|
||||
itertools = { workspace = true }
|
||||
thiserror = { workspace = true }
|
||||
@@ -2,7 +2,7 @@ use std::ops::Deref;
|
||||
use std::path::PathBuf;
|
||||
|
||||
use clap::{CommandFactory, Parser, Subcommand};
|
||||
use developing_compilers::ast::optimization::OLevel;
|
||||
use compiler::ast::optimization::OLevel;
|
||||
|
||||
pub struct Args {
|
||||
inner: ArgsInner,
|
||||
@@ -45,9 +45,6 @@ pub enum Command {
|
||||
input: PathBuf,
|
||||
output: PathBuf,
|
||||
},
|
||||
Int {
|
||||
input: PathBuf,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, PartialEq, Eq, clap::ValueEnum)]
|
||||
@@ -101,7 +98,6 @@ fn validate_inner(args: ArgsInner) -> Result<ArgsInner, clap::Error> {
|
||||
..
|
||||
} => validate_gen(input, output, output_symbols)?,
|
||||
Command::Com { input, output, .. } => validate_com(input, output)?,
|
||||
Command::Int { input } => validate_int(input)?,
|
||||
};
|
||||
|
||||
Ok(args)
|
||||
@@ -218,14 +214,3 @@ fn validate_com(input: &PathBuf, output: &PathBuf) -> Result<(), clap::Error> {
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn validate_int(input: &PathBuf) -> Result<(), clap::Error> {
|
||||
if !input.is_file() {
|
||||
return Err(clap::Error::raw(
|
||||
clap::error::ErrorKind::InvalidValue,
|
||||
format!("Input file '{}' does not exist", input.display()),
|
||||
));
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@@ -1,7 +1,5 @@
|
||||
pub mod ast;
|
||||
pub mod error;
|
||||
pub mod interpreter;
|
||||
pub mod parse;
|
||||
pub mod representation;
|
||||
pub mod symbols;
|
||||
pub mod util;
|
||||
@@ -1,19 +1,18 @@
|
||||
mod cli;
|
||||
mod util;
|
||||
|
||||
use std::fs;
|
||||
use std::io::{self, Write};
|
||||
use std::path::Path;
|
||||
|
||||
use cli::GenMode;
|
||||
use developing_compilers::ast::optimization::OLevel;
|
||||
use developing_compilers::ast::typed::{Type, TypedExpr};
|
||||
use developing_compilers::interpreter::{Interpreter, Value};
|
||||
use developing_compilers::representation::intermediate::IntermediateExpr;
|
||||
use developing_compilers::*;
|
||||
use inquire::CustomType;
|
||||
use integer_encoding::{VarIntReader, VarIntWriter};
|
||||
use parse::parser::Parser;
|
||||
use symbols::SymbolsTable;
|
||||
use compiler::ast::optimization::OLevel;
|
||||
use compiler::ast::typed::TypedExpr;
|
||||
use compiler::parse::parser::Parser;
|
||||
use compiler::representation::intermediate::IntermediateExpr;
|
||||
use compiler::symbols::SymbolsTable;
|
||||
use compiler::*;
|
||||
use integer_encoding::VarIntWriter;
|
||||
|
||||
fn main() -> anyhow::Result<()> {
|
||||
let args = cli::Args::parse();
|
||||
@@ -42,7 +41,6 @@ fn main() -> anyhow::Result<()> {
|
||||
input,
|
||||
output,
|
||||
} => com_command(*optimization_level, input, output),
|
||||
cli::Command::Int { input } => int_command(input),
|
||||
};
|
||||
|
||||
if let Err(e) = result {
|
||||
@@ -52,44 +50,6 @@ fn main() -> anyhow::Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn int_command(input: &Path) -> Result<(), anyhow::Error> {
|
||||
let (symbols, ir) = {
|
||||
let mut reader = io::BufReader::new(fs::File::open(input)?);
|
||||
let symbols = SymbolsTable::read(&mut reader)?;
|
||||
let n = reader.read_varint::<u64>()?;
|
||||
let mut ir = Vec::with_capacity(n as usize);
|
||||
for _ in 0..n {
|
||||
ir.push(IntermediateExpr::read(&mut reader)?);
|
||||
}
|
||||
(symbols, ir)
|
||||
};
|
||||
|
||||
let mut interpreter = Interpreter::new(ir, symbols, |ty, name| match ty {
|
||||
Type::Int => Value::Int(
|
||||
CustomType::new(&format!("Input int {}", name))
|
||||
.with_default(0)
|
||||
.prompt()
|
||||
.unwrap_or_default(),
|
||||
),
|
||||
Type::Float => Value::Float(
|
||||
CustomType::new(&format!("Input float {}", name))
|
||||
.with_default(0.0)
|
||||
.prompt()
|
||||
.unwrap_or_default(),
|
||||
),
|
||||
});
|
||||
|
||||
let result = interpreter.run()?;
|
||||
|
||||
if let Some(result) = result {
|
||||
println!("Result: {}", result);
|
||||
} else {
|
||||
println!("No result");
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn com_command(o_level: OLevel, input: &Path, output: &Path) -> Result<(), anyhow::Error> {
|
||||
let input = fs::read_to_string(input)?;
|
||||
let mut symbols = SymbolsTable::default();
|
||||
14
crates/interpreter/Cargo.toml
Normal file
14
crates/interpreter/Cargo.toml
Normal file
@@ -0,0 +1,14 @@
|
||||
[package]
|
||||
edition = "2021"
|
||||
name = "interpreter"
|
||||
version = "0.1.0"
|
||||
|
||||
[dependencies]
|
||||
compiler = { path = "../compiler" }
|
||||
anyhow = { workspace = true }
|
||||
byteorder = { workspace = true }
|
||||
clap = { workspace = true }
|
||||
inquire = "0.7.5"
|
||||
integer-encoding = { workspace = true }
|
||||
itertools = { workspace = true }
|
||||
thiserror = { workspace = true }
|
||||
46
crates/interpreter/src/cli.rs
Normal file
46
crates/interpreter/src/cli.rs
Normal file
@@ -0,0 +1,46 @@
|
||||
use std::ops::Deref;
|
||||
use std::path::PathBuf;
|
||||
|
||||
use clap::{CommandFactory, Parser};
|
||||
|
||||
pub struct Args {
|
||||
inner: ArgsInner,
|
||||
}
|
||||
|
||||
#[derive(Parser)]
|
||||
pub struct ArgsInner {
|
||||
pub input: PathBuf,
|
||||
}
|
||||
|
||||
impl Args {
|
||||
pub fn parse() -> Self {
|
||||
let inner = match validate_inner(ArgsInner::parse()) {
|
||||
Ok(args) => args,
|
||||
Err(err) => {
|
||||
let mut command = ArgsInner::command();
|
||||
err.format(&mut command).exit();
|
||||
},
|
||||
};
|
||||
|
||||
Self { inner }
|
||||
}
|
||||
}
|
||||
|
||||
impl Deref for Args {
|
||||
type Target = ArgsInner;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.inner
|
||||
}
|
||||
}
|
||||
|
||||
fn validate_inner(args: ArgsInner) -> Result<ArgsInner, clap::Error> {
|
||||
if args.input.is_file() {
|
||||
Ok(args)
|
||||
} else {
|
||||
Err(clap::Error::raw(
|
||||
clap::error::ErrorKind::InvalidValue,
|
||||
format!("Input file '{}' does not exist", args.input.display()),
|
||||
))
|
||||
}
|
||||
}
|
||||
@@ -3,13 +3,12 @@ mod value;
|
||||
use std::collections::HashMap;
|
||||
|
||||
use anyhow::Context;
|
||||
use compiler::ast::BinOp;
|
||||
use compiler::ast::typed::Type;
|
||||
use compiler::representation::intermediate::{IntermediateExpr, IntermediateValue};
|
||||
use compiler::symbols::{Symbol, SymbolsTable};
|
||||
pub use value::Value;
|
||||
|
||||
use crate::ast::BinOp;
|
||||
use crate::ast::typed::Type;
|
||||
use crate::representation::intermediate::{IntermediateExpr, IntermediateValue};
|
||||
use crate::symbols::{Symbol, SymbolsTable};
|
||||
|
||||
pub struct Interpreter<I> {
|
||||
exprs: Vec<IntermediateExpr>,
|
||||
symbols: SymbolsTable,
|
||||
1
crates/interpreter/src/lib.rs
Normal file
1
crates/interpreter/src/lib.rs
Normal file
@@ -0,0 +1 @@
|
||||
pub mod interpreter;
|
||||
61
crates/interpreter/src/main.rs
Normal file
61
crates/interpreter/src/main.rs
Normal file
@@ -0,0 +1,61 @@
|
||||
use std::path::Path;
|
||||
use std::{fs, io};
|
||||
|
||||
use compiler::ast::typed::Type;
|
||||
use compiler::representation::intermediate::IntermediateExpr;
|
||||
use compiler::symbols::SymbolsTable;
|
||||
use inquire::CustomType;
|
||||
use integer_encoding::VarIntReader;
|
||||
use interpreter::interpreter::{Interpreter, Value};
|
||||
|
||||
mod cli;
|
||||
|
||||
fn main() -> anyhow::Result<()> {
|
||||
let args = cli::Args::parse();
|
||||
|
||||
let result = int_command(&args.input);
|
||||
|
||||
if let Err(e) = result {
|
||||
eprintln!("error: {}", e);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn int_command(input: &Path) -> Result<(), anyhow::Error> {
|
||||
let (symbols, ir) = {
|
||||
let mut reader = io::BufReader::new(fs::File::open(input)?);
|
||||
let symbols = SymbolsTable::read(&mut reader)?;
|
||||
let n = reader.read_varint::<u64>()?;
|
||||
let mut ir = Vec::with_capacity(n as usize);
|
||||
for _ in 0..n {
|
||||
ir.push(IntermediateExpr::read(&mut reader)?);
|
||||
}
|
||||
(symbols, ir)
|
||||
};
|
||||
|
||||
let mut interpreter = Interpreter::new(ir, symbols, |ty, name| match ty {
|
||||
Type::Int => Value::Int(
|
||||
CustomType::new(&format!("Input int {}", name))
|
||||
.with_default(0)
|
||||
.prompt()
|
||||
.unwrap_or_default(),
|
||||
),
|
||||
Type::Float => Value::Float(
|
||||
CustomType::new(&format!("Input float {}", name))
|
||||
.with_default(0.0)
|
||||
.prompt()
|
||||
.unwrap_or_default(),
|
||||
),
|
||||
});
|
||||
|
||||
let result = interpreter.run()?;
|
||||
|
||||
if let Some(result) = result {
|
||||
println!("Result: {}", result);
|
||||
} else {
|
||||
println!("No result");
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
35
run_all.sh
Executable file
35
run_all.sh
Executable file
@@ -0,0 +1,35 @@
|
||||
mkdir -p ./test/lex
|
||||
cargo run -r -- lex ./test/in.txt ./test/lex/tokens.txt ./test/lex/symbols.txt
|
||||
|
||||
mkdir -p ./test/syn
|
||||
cargo run -r -- syn ./test/in.txt ./test/syn/tree.txt
|
||||
|
||||
mkdir -p ./test/sem/none
|
||||
cargo run -r -- sem ./test/in.txt ./test/sem/none/tree.txt
|
||||
|
||||
mkdir -p ./test/sem/o1
|
||||
cargo run -r -- sem -o o1 ./test/in.txt ./test/sem/o1/tree.txt
|
||||
|
||||
mkdir -p ./test/sem/o2
|
||||
cargo run -r -- sem -o o2 ./test/in.txt ./test/sem/o2/tree.txt
|
||||
|
||||
mkdir -p ./test/sem/o3
|
||||
cargo run -r -- sem -o o3 ./test/in.txt ./test/sem/o3/tree.txt
|
||||
|
||||
mkdir -p ./test/gen/ir
|
||||
cargo run -r -- gen i ./test/in.txt ./test/gen/ir/result.txt ./test/gen/ir/symbols.txt
|
||||
|
||||
mkdir -p ./test/gen/p
|
||||
cargo run -r -- gen p ./test/in.txt ./test/gen/p/result.txt ./test/gen/p/symbols.txt
|
||||
|
||||
mkdir -p ./test/gen/ir-o
|
||||
cargo run -r -- gen i -o o2 ./test/in.txt ./test/gen/ir-o/result.txt ./test/gen/ir-o/symbols.txt
|
||||
|
||||
mkdir -p ./test/gen/p-o
|
||||
cargo run -r -- gen p -o o2 ./test/in.txt ./test/gen/p-o/result.txt ./test/gen/p-o/symbols.txt
|
||||
|
||||
mkdir -p ./test/com
|
||||
cargo run -r -- com ./test/in.txt ./test/com/result.bin
|
||||
|
||||
mkdir -p ./test/com-o
|
||||
cargo run -r -- com -o o2 ./test/in.txt ./test/com-o/result.bin
|
||||
Reference in New Issue
Block a user