mirror of
https://github.com/azur1s/bobbylisp.git
synced 2024-10-16 02:37:40 -05:00
feat: project structure, some gen code
This commit is contained in:
parent
cb6b35a2dc
commit
4879cc2ffc
231
Cargo.lock
generated
231
Cargo.lock
generated
|
@ -2,6 +2,237 @@
|
|||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
|
||||
[[package]]
|
||||
name = "atty"
|
||||
version = "0.2.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
|
||||
dependencies = [
|
||||
"hermit-abi",
|
||||
"libc",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "autocfg"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "1.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
||||
|
||||
[[package]]
|
||||
name = "clap"
|
||||
version = "3.0.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b63edc3f163b3c71ec8aa23f9bd6070f77edbf3d1d198b164afa90ff00e4ec62"
|
||||
dependencies = [
|
||||
"atty",
|
||||
"bitflags",
|
||||
"clap_derive",
|
||||
"indexmap",
|
||||
"lazy_static",
|
||||
"os_str_bytes",
|
||||
"strsim",
|
||||
"termcolor",
|
||||
"textwrap",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap_derive"
|
||||
version = "3.0.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9a1132dc3944b31c20dd8b906b3a9f0a5d0243e092d59171414969657ac6aa85"
|
||||
dependencies = [
|
||||
"heck",
|
||||
"proc-macro-error",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hashbrown"
|
||||
version = "0.11.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e"
|
||||
|
||||
[[package]]
|
||||
name = "heck"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2540771e65fc8cb83cd6e8a237f70c319bd5c29f78ed1084ba5d50eeac86f7f9"
|
||||
|
||||
[[package]]
|
||||
name = "hermit-abi"
|
||||
version = "0.1.19"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "indexmap"
|
||||
version = "1.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "282a6247722caba404c065016bbfa522806e51714c34f5dfc3e4a3a46fcb4223"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"hashbrown",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lazy_static"
|
||||
version = "1.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.117"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e74d72e0f9b65b5b4ca49a346af3976df0f9c61d550727f349ecd559f251a26c"
|
||||
|
||||
[[package]]
|
||||
name = "memchr"
|
||||
version = "2.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a"
|
||||
|
||||
[[package]]
|
||||
name = "os_str_bytes"
|
||||
version = "6.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8e22443d1643a904602595ba1cd8f7d896afe56d26712531c5ff73a15b2fbf64"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro-error"
|
||||
version = "1.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c"
|
||||
dependencies = [
|
||||
"proc-macro-error-attr",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"version_check",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro-error-attr"
|
||||
version = "1.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"version_check",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.36"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c7342d5883fbccae1cc37a2353b09c87c9b0f3afd73f5fb9bba687a1f733b029"
|
||||
dependencies = [
|
||||
"unicode-xid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "864d3e96a899863136fc6e99f3d7cae289dafe43bf2c5ac19b70df7210c0a145"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "strsim"
|
||||
version = "0.10.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "1.0.86"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8a65b3f4ffa0092e9887669db0eae07941f023991ab58ea44da8fe8e2d511c6b"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"unicode-xid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "termcolor"
|
||||
version = "1.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2dfed899f0eb03f32ee8c6a0aabdb8a7949659e3466561fc0adf54e26d88c5f4"
|
||||
dependencies = [
|
||||
"winapi-util",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "textwrap"
|
||||
version = "0.14.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0066c8d12af8b5acd21e00547c3797fde4e8677254a7ee429176ccebbe93dd80"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-xid"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3"
|
||||
|
||||
[[package]]
|
||||
name = "version_check"
|
||||
version = "0.9.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
|
||||
|
||||
[[package]]
|
||||
name = "vyc"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"clap",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winapi"
|
||||
version = "0.3.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
|
||||
dependencies = [
|
||||
"winapi-i686-pc-windows-gnu",
|
||||
"winapi-x86_64-pc-windows-gnu",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winapi-i686-pc-windows-gnu"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
|
||||
|
||||
[[package]]
|
||||
name = "winapi-util"
|
||||
version = "0.1.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178"
|
||||
dependencies = [
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winapi-x86_64-pc-windows-gnu"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
||||
|
|
|
@ -6,3 +6,4 @@ edition = "2021"
|
|||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
clap = { version = "3.0.14", features = ["derive"] }
|
||||
|
|
1
example/def.vy
Normal file
1
example/def.vy
Normal file
|
@ -0,0 +1 @@
|
|||
(def number 1)
|
|
@ -1,3 +1,2 @@
|
|||
(print '(Hello, World!))
|
||||
(print (format "Hello" (format "World")))
|
||||
)
|
||||
(def message str "Hello, World")
|
||||
(print message)
|
27
src/args.rs
Normal file
27
src/args.rs
Normal file
|
@ -0,0 +1,27 @@
|
|||
use std::path::PathBuf;
|
||||
use clap::{ Parser, Subcommand };
|
||||
|
||||
const VERSION: &str = env!("CARGO_PKG_VERSION");
|
||||
|
||||
/// Vy language compiler.
|
||||
#[derive(Parser, Debug)]
|
||||
#[clap(
|
||||
version = VERSION,
|
||||
long_about = None)]
|
||||
pub struct Args {
|
||||
#[clap(subcommand)]
|
||||
pub options: Options,
|
||||
}
|
||||
|
||||
#[derive(Subcommand, Debug)]
|
||||
pub enum Options {
|
||||
#[clap(about = "Compile a file.")]
|
||||
Compile {
|
||||
/// The input file to compile.
|
||||
#[clap(parse(from_os_str))]
|
||||
input: PathBuf,
|
||||
/// Print parsed AST and exit (for debugging).
|
||||
#[clap(short, long)]
|
||||
ast: bool,
|
||||
},
|
||||
}
|
1
src/front/mod.rs
Normal file
1
src/front/mod.rs
Normal file
|
@ -0,0 +1 @@
|
|||
pub mod parser;
|
|
@ -175,6 +175,12 @@ impl ParseError {
|
|||
pub fn at(&self, src: &str) -> String {
|
||||
let snip = &src[(self.pos.0.saturating_sub(5))..(if self.pos.0 + 5 > src.len() { src.len() } else { self.pos.0 + 5 })];
|
||||
format!("\n{}..{}\n{}\nError: {} at {}", " ".repeat(3), snip, format!("{}^", " ".repeat(10)), self.kind, self.pos.0)
|
||||
|
||||
// Example:
|
||||
//
|
||||
// .."))) ) (pr
|
||||
// ^
|
||||
// Error: Unexpected ')' at 67
|
||||
}
|
||||
}
|
||||
|
96
src/main.rs
96
src/main.rs
|
@ -1,70 +1,44 @@
|
|||
use std::{process::exit, fs::read_to_string};
|
||||
use std::fs::read_to_string;
|
||||
use clap::Parser;
|
||||
|
||||
pub mod parser;
|
||||
pub mod compile;
|
||||
/// Arguments handler.
|
||||
pub mod args;
|
||||
use args::{ Args, Options };
|
||||
|
||||
const EXECUTABLE_NAME: &str = env!("CARGO_PKG_NAME");
|
||||
const HELP_MESSAGE: &str = "\
|
||||
-h, --help
|
||||
Print this help message and exit.
|
||||
-v, --version
|
||||
Print version information and exit.
|
||||
-c FILE, --compile FILE
|
||||
Compile the given file and exit.\
|
||||
";
|
||||
/// A front-end for the compiler.
|
||||
/// Contains parser and tokenizer.
|
||||
/// TODO: Semantic analysis and Type checking.
|
||||
pub mod front;
|
||||
use front::parser::parse;
|
||||
|
||||
/// A middle-end for the compiler.
|
||||
/// Contains instructions generator.
|
||||
pub mod middle;
|
||||
use middle::gen::generate_instructions;
|
||||
|
||||
fn main() {
|
||||
let args = std::env::args().collect::<Vec<String>>();
|
||||
let mut args_index: usize = 0;
|
||||
match args.len() {
|
||||
// No argument provided
|
||||
1 => {
|
||||
println!("No argument provided.");
|
||||
display_help(1);
|
||||
},
|
||||
_ => {
|
||||
while args.len() > args_index {
|
||||
let arg: &str = &args[args_index];
|
||||
match arg {
|
||||
"-h" | "--help" => { display_help(0); },
|
||||
"-v" | "--version" => {
|
||||
println!("{} version {}", EXECUTABLE_NAME, env!("CARGO_PKG_VERSION"));
|
||||
exit(0);
|
||||
},
|
||||
"-c" | "--compile" => {
|
||||
args_index += 1;
|
||||
if args_index < args.len() {
|
||||
let file_path: &str = &args[args_index];
|
||||
let file_content: String = read_to_string(file_path).unwrap();
|
||||
// Used for error reporting
|
||||
let file_content_joined: String = file_content.split("\n").collect::<Vec<&str>>().join(" ");
|
||||
|
||||
let parsed = parser::parse(&file_content);
|
||||
let mut ast = Vec::new();
|
||||
for node in parsed {
|
||||
match node {
|
||||
Ok(node) => { ast.push(node); },
|
||||
Err(error) => {
|
||||
eprintln!("{}", error.at(&file_content_joined));
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
println!("{:#?}", ast);
|
||||
} else {
|
||||
println!("No file provided.");
|
||||
display_help(1);
|
||||
let args = Args::parse();
|
||||
match args.options {
|
||||
Options::Compile { input, ast } => {
|
||||
let code = read_to_string(input).unwrap();
|
||||
let tree = parse(&code);
|
||||
match ast {
|
||||
true => for node in tree { println!("{:#?}", node) },
|
||||
false => {
|
||||
let mut checked_tree = Vec::new();
|
||||
for node in tree {
|
||||
match node {
|
||||
Ok(node) => checked_tree.push(node),
|
||||
Err(err) => println!("{:?}", err),
|
||||
}
|
||||
};
|
||||
|
||||
let instructions = generate_instructions(checked_tree.into_iter());
|
||||
for instruction in instructions {
|
||||
println!("{:#?}", instruction);
|
||||
}
|
||||
_ => { args_index += 1; }
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
fn display_help(exit_code: i32) {
|
||||
println!("Usage: {} [OPTIONS]", EXECUTABLE_NAME);
|
||||
println!("{}", HELP_MESSAGE);
|
||||
exit(exit_code);
|
||||
}
|
56
src/middle/gen.rs
Normal file
56
src/middle/gen.rs
Normal file
|
@ -0,0 +1,56 @@
|
|||
use std::borrow::Borrow;
|
||||
|
||||
use crate::front::parser::Value;
|
||||
use super::instr::Instructions;
|
||||
|
||||
pub fn generate_instructions(ast: impl Iterator<Item = (Value, (usize, usize))>) -> Vec<Instructions> {
|
||||
let mut instructions: Vec<Instructions> = Vec::new();
|
||||
for (value, _) in ast {
|
||||
match value {
|
||||
Value::List(car, cdr) => {
|
||||
match &*car.borrow() {
|
||||
Value::Symbol(ref function_name) => {
|
||||
match function_name.as_str() {
|
||||
"def" => {
|
||||
let name: Box<str> = match &cdr[0].borrow() {
|
||||
Value::Symbol(name) => name.clone().into(),
|
||||
_ => panic!("Expected symbol as first argument of define"),
|
||||
};
|
||||
|
||||
match &cdr[1].borrow() {
|
||||
Value::Int(value) => instructions.push(Instructions::Store {
|
||||
value: Value::Int(*value),
|
||||
name,
|
||||
}),
|
||||
Value::Float(value) => instructions.push(Instructions::Store {
|
||||
value: Value::Float(*value),
|
||||
name,
|
||||
}),
|
||||
Value::String(value) => instructions.push(Instructions::Store {
|
||||
value: Value::String(value.clone()),
|
||||
name,
|
||||
}),
|
||||
_ => todo!(),
|
||||
};
|
||||
},
|
||||
_ => {
|
||||
dbg!(function_name);
|
||||
todo!();
|
||||
}
|
||||
} // --- End match `function_name` ---
|
||||
},
|
||||
_ => {
|
||||
dbg!(car);
|
||||
todo!();
|
||||
}
|
||||
} // --- End match `car` ---
|
||||
}
|
||||
_ => {
|
||||
dbg!(value);
|
||||
todo!();
|
||||
}
|
||||
} // --- End match `value` ---
|
||||
}
|
||||
|
||||
instructions
|
||||
}
|
7
src/middle/instr.rs
Normal file
7
src/middle/instr.rs
Normal file
|
@ -0,0 +1,7 @@
|
|||
use crate::front::parser::Value;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum Instructions {
|
||||
Store { value: Value, name: Box<str> },
|
||||
Push { value: Value },
|
||||
}
|
2
src/middle/mod.rs
Normal file
2
src/middle/mod.rs
Normal file
|
@ -0,0 +1,2 @@
|
|||
pub mod instr;
|
||||
pub mod gen;
|
49
src/util.rs
Normal file
49
src/util.rs
Normal file
|
@ -0,0 +1,49 @@
|
|||
use crate::token::Expr::{self, List};
|
||||
|
||||
pub fn cover_paren(s: String) -> String {
|
||||
format!("({})", s)
|
||||
}
|
||||
|
||||
pub fn unescape(s: String) -> String {
|
||||
let mut result = String::new();
|
||||
let mut i = 0;
|
||||
while i < s.len() {
|
||||
if s.chars().nth(i).unwrap() == '\\' {
|
||||
match s.chars().nth(i + 1).unwrap() {
|
||||
'n' => result.push('\n'),
|
||||
't' => result.push('\t'),
|
||||
'r' => result.push('\r'),
|
||||
'\\' => result.push('\\'),
|
||||
'"' => result.push('"'),
|
||||
_ => result.push(s.chars().nth(i + 1).unwrap()),
|
||||
}
|
||||
i += 2;
|
||||
} else {
|
||||
result.push(s.chars().nth(i).unwrap());
|
||||
i += 1;
|
||||
}
|
||||
}
|
||||
result
|
||||
}
|
||||
|
||||
pub fn unwrap_list_nest(ast: Expr) -> Vec<Expr> {
|
||||
let mut result: Vec<Expr> = Vec::new();
|
||||
|
||||
match ast.clone() {
|
||||
List(l, _) => {
|
||||
for expr in l.iter() {
|
||||
|
||||
result.push(expr.clone());
|
||||
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
// This probably will not happen because everything is wrapped
|
||||
// in list. So it would be impossible that the ast is not a list.
|
||||
eprintln!("Possibly a bug in the compiler, you shouln't get this messages.");
|
||||
dbg!(ast);
|
||||
}
|
||||
};
|
||||
|
||||
result
|
||||
}
|
Loading…
Reference in a new issue