1
0

separate interpreter and compiler

This commit is contained in:
2024-12-02 13:57:32 +03:00
parent 8030670a51
commit e5b63d5e2d
27 changed files with 214 additions and 92 deletions

43
Cargo.lock generated
View File

@@ -133,6 +133,18 @@ version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990" checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990"
[[package]]
name = "compiler"
version = "0.1.0"
dependencies = [
"anyhow",
"byteorder",
"clap",
"integer-encoding",
"itertools",
"thiserror",
]
[[package]] [[package]]
name = "crossterm" name = "crossterm"
version = "0.25.0" version = "0.25.0"
@@ -158,19 +170,6 @@ dependencies = [
"winapi", "winapi",
] ]
[[package]]
name = "developing-compilers"
version = "0.1.0"
dependencies = [
"anyhow",
"byteorder",
"clap",
"inquire",
"integer-encoding",
"itertools",
"thiserror",
]
[[package]] [[package]]
name = "dyn-clone" name = "dyn-clone"
version = "1.0.17" version = "1.0.17"
@@ -230,6 +229,20 @@ version = "4.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0d762194228a2f1c11063e46e32e5acb96e66e906382b9eb5441f2e0504bbd5a" checksum = "0d762194228a2f1c11063e46e32e5acb96e66e906382b9eb5441f2e0504bbd5a"
[[package]]
name = "interpreter"
version = "0.1.0"
dependencies = [
"anyhow",
"byteorder",
"clap",
"compiler",
"inquire",
"integer-encoding",
"itertools",
"thiserror",
]
[[package]] [[package]]
name = "is_terminal_polyfill" name = "is_terminal_polyfill"
version = "1.70.1" version = "1.70.1"
@@ -247,9 +260,9 @@ dependencies = [
[[package]] [[package]]
name = "libc" name = "libc"
version = "0.2.162" version = "0.2.164"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "18d287de67fe55fd7e1581fe933d965a5a9477b38e949cfa9f8574ef01506398" checksum = "433bfe06b8c75da9b2e3fbea6e5329ff87748f0b144ef75306e674c3f6f7c13f"
[[package]] [[package]]
name = "lock_api" name = "lock_api"

View File

@@ -1,13 +1,11 @@
[package] [workspace]
edition = "2021" members = ["crates/compiler", "crates/interpreter"]
name = "developing-compilers" resolver = "2"
version = "0.1.0"
[dependencies] [workspace.dependencies]
anyhow = "1.0.89" anyhow = "1.0.89"
byteorder = "1.5.0" byteorder = "1.5.0"
clap = { version = "4.5.19", features = ["derive"] } clap = { version = "4.5.19", features = ["derive"] }
inquire = "0.7.5"
integer-encoding = "4.0.2" integer-encoding = "4.0.2"
itertools = "0.13.0" itertools = "0.13.0"
thiserror = "2.0.3" thiserror = "2.0.3"

View 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 }

View File

@@ -2,7 +2,7 @@ use std::ops::Deref;
use std::path::PathBuf; use std::path::PathBuf;
use clap::{CommandFactory, Parser, Subcommand}; use clap::{CommandFactory, Parser, Subcommand};
use developing_compilers::ast::optimization::OLevel; use compiler::ast::optimization::OLevel;
pub struct Args { pub struct Args {
inner: ArgsInner, inner: ArgsInner,
@@ -45,9 +45,6 @@ pub enum Command {
input: PathBuf, input: PathBuf,
output: PathBuf, output: PathBuf,
}, },
Int {
input: PathBuf,
},
} }
#[derive(Copy, Clone, PartialEq, Eq, clap::ValueEnum)] #[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)?, } => validate_gen(input, output, output_symbols)?,
Command::Com { input, output, .. } => validate_com(input, output)?, Command::Com { input, output, .. } => validate_com(input, output)?,
Command::Int { input } => validate_int(input)?,
}; };
Ok(args) Ok(args)
@@ -218,14 +214,3 @@ fn validate_com(input: &PathBuf, output: &PathBuf) -> Result<(), clap::Error> {
Ok(()) 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(())
}

View File

@@ -1,7 +1,5 @@
pub mod ast; pub mod ast;
pub mod error; pub mod error;
pub mod interpreter;
pub mod parse; pub mod parse;
pub mod representation; pub mod representation;
pub mod symbols; pub mod symbols;
pub mod util;

View File

@@ -1,19 +1,18 @@
mod cli; mod cli;
mod util;
use std::fs; use std::fs;
use std::io::{self, Write}; use std::io::{self, Write};
use std::path::Path; use std::path::Path;
use cli::GenMode; use cli::GenMode;
use developing_compilers::ast::optimization::OLevel; use compiler::ast::optimization::OLevel;
use developing_compilers::ast::typed::{Type, TypedExpr}; use compiler::ast::typed::TypedExpr;
use developing_compilers::interpreter::{Interpreter, Value}; use compiler::parse::parser::Parser;
use developing_compilers::representation::intermediate::IntermediateExpr; use compiler::representation::intermediate::IntermediateExpr;
use developing_compilers::*; use compiler::symbols::SymbolsTable;
use inquire::CustomType; use compiler::*;
use integer_encoding::{VarIntReader, VarIntWriter}; use integer_encoding::VarIntWriter;
use parse::parser::Parser;
use symbols::SymbolsTable;
fn main() -> anyhow::Result<()> { fn main() -> anyhow::Result<()> {
let args = cli::Args::parse(); let args = cli::Args::parse();
@@ -42,7 +41,6 @@ fn main() -> anyhow::Result<()> {
input, input,
output, output,
} => com_command(*optimization_level, input, output), } => com_command(*optimization_level, input, output),
cli::Command::Int { input } => int_command(input),
}; };
if let Err(e) = result { if let Err(e) = result {
@@ -52,44 +50,6 @@ fn main() -> anyhow::Result<()> {
Ok(()) 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> { fn com_command(o_level: OLevel, input: &Path, output: &Path) -> Result<(), anyhow::Error> {
let input = fs::read_to_string(input)?; let input = fs::read_to_string(input)?;
let mut symbols = SymbolsTable::default(); let mut symbols = SymbolsTable::default();

View 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 }

View 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()),
))
}
}

View File

@@ -3,13 +3,12 @@ mod value;
use std::collections::HashMap; use std::collections::HashMap;
use anyhow::Context; 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; 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> { pub struct Interpreter<I> {
exprs: Vec<IntermediateExpr>, exprs: Vec<IntermediateExpr>,
symbols: SymbolsTable, symbols: SymbolsTable,

View File

@@ -0,0 +1 @@
pub mod interpreter;

View 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
View 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