Skip to content

Commit

Permalink
Separate frontend::check from main
Browse files Browse the repository at this point in the history
  • Loading branch information
ehllie committed Jan 26, 2024
1 parent 172f46d commit ffc85df
Show file tree
Hide file tree
Showing 4 changed files with 91 additions and 83 deletions.
19 changes: 2 additions & 17 deletions ante-ls/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,7 @@ use std::{
use ante::{
cache::{cached_read, ModuleCache},
error::{location::Locatable, ErrorType},
lexer::Lexer,
nameresolution::NameResolver,
parser::parse,
types::typechecker,
frontend,
};

use dashmap::DashMap;
Expand Down Expand Up @@ -141,19 +138,7 @@ impl Backend {
let file_cache = paths.iter().zip(contents.into_iter()).map(|(p, c)| (p.as_path(), c)).collect();
let mut cache = ModuleCache::new(cache_root, file_cache);

let tokens = Lexer::new(filename, &rope.to_string()).collect::<Vec<_>>();
match parse(&tokens) {
Ok(ast) => {
NameResolver::start(ast, &mut cache);
if cache.error_count() == 0 {
let ast = cache.parse_trees.get_mut(0).unwrap();
typechecker::infer_ast(ast, &mut cache);
}
},
Err(err) => {
cache.push_full_diagnostic(err.into_diagnostic());
},
};
let _ = frontend::check(filename, rope.to_string(), &mut cache, frontend::FrontendPhase::TypeCheck, false);

// Diagnostics for a document get cleared only when an empty list is sent for it's Uri.
// This presents an issue, as when we have files A and B, where file A imports the file B,
Expand Down
73 changes: 73 additions & 0 deletions src/frontend.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
use std::path::Path;

use crate::cache::ModuleCache;
use crate::lexer::Lexer;
use crate::nameresolution::NameResolver;
use crate::parser;
use crate::types;
use crate::util;

#[derive(PartialEq)]
pub enum FrontendPhase {
Lex,
Parse,
TypeCheck,
}

pub enum FrontendResult {
Done,
ContinueCompilation,
Errors,
}

pub fn check<'a>(
filename: &'a Path, main_file_contents: String, cache: &mut ModuleCache<'a>, phase: FrontendPhase, show_time: bool,
) -> FrontendResult {
util::timing::time_passes(show_time);

// Phase 1: Lexing
util::timing::start_time("Lexing");
let tokens = Lexer::new(filename, &main_file_contents).collect::<Vec<_>>();

if phase == FrontendPhase::Lex {
tokens.iter().for_each(|(token, _)| println!("{}", token));
return FrontendResult::Done;
}

// Phase 2: Parsing
util::timing::start_time("Parsing");

let root = match parser::parse(&tokens) {
Ok(root) => root,
Err(parse_error) => {
// Parse errors are currently always fatal
cache.push_full_diagnostic(parse_error.into_diagnostic());
return FrontendResult::Errors;
},
};

if phase == FrontendPhase::Parse {
println!("{}", root);
return FrontendResult::Done;
}

// Phase 3: Name resolution
// Timing for name resolution is within the start method to
// break up the declare and define passes
NameResolver::start(root, cache);

if cache.error_count() != 0 {
return FrontendResult::Errors;
}

// Phase 4: Type inference
util::timing::start_time("Type Inference");
let ast = cache.parse_trees.get_mut(0).unwrap();
types::typechecker::infer_ast(ast, cache);

if cache.error_count() != 0 {
FrontendResult::Errors
} else {
FrontendResult::ContinueCompilation
}
}
1 change: 1 addition & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ pub mod lexer;

#[macro_use]
pub mod util;
pub mod frontend;

#[macro_use]
pub mod error;
Expand Down
81 changes: 15 additions & 66 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ mod lexer;

#[macro_use]
mod util;
mod frontend;

#[macro_use]
mod error;
Expand All @@ -35,8 +36,8 @@ mod types;
mod llvm;

use cache::ModuleCache;
use lexer::Lexer;
use nameresolution::NameResolver;
use cli::{Backend, Cli, Completions, EmitTarget};
use frontend::{check, FrontendPhase, FrontendResult};

use clap::{CommandFactory, Parser};
use clap_complete as clap_cmp;
Expand All @@ -45,8 +46,6 @@ use std::fs::File;
use std::io::{stdout, BufReader, Read};
use std::path::Path;

use crate::cli::{Backend, Cli, Completions, EmitTarget};

#[global_allocator]
static ALLOCATOR: mimalloc::MiMalloc = mimalloc::MiMalloc;

Expand Down Expand Up @@ -101,64 +100,6 @@ pub fn main() {
}
}

pub enum CheckResult {
Done,
ContinueCompilation,
Errors,
}

pub fn check<'a>(
args: &Cli, filename: &'a Path, main_file_contents: String, cache: &mut ModuleCache<'a>,
) -> CheckResult {
util::timing::time_passes(args.show_time);

// Phase 1: Lexing
util::timing::start_time("Lexing");
let tokens = Lexer::new(filename, &main_file_contents).collect::<Vec<_>>();

if args.lex {
tokens.iter().for_each(|(token, _)| println!("{}", token));
return CheckResult::Done;
}

// Phase 2: Parsing
util::timing::start_time("Parsing");

let root = match parser::parse(&tokens) {
Ok(root) => root,
Err(parse_error) => {
// Parse errors are currently always fatal
cache.push_full_diagnostic(parse_error.into_diagnostic());
return CheckResult::Errors;
},
};

if args.parse {
println!("{}", root);
return CheckResult::Done;
}

// Phase 3: Name resolution
// Timing for name resolution is within the start method to
// break up the declare and define passes
NameResolver::start(root, cache);

if cache.error_count() != 0 {
return CheckResult::Errors;
}

// Phase 4: Type inference
util::timing::start_time("Type Inference");
let ast = cache.parse_trees.get_mut(0).unwrap();
types::typechecker::infer_ast(ast, cache);

if cache.error_count() != 0 {
CheckResult::Errors
} else {
CheckResult::ContinueCompilation
}
}

fn compile(args: Cli) {
// Setup the cache and read from the first file
let filename = Path::new(&args.file);
Expand All @@ -182,10 +123,18 @@ fn compile(args: Cli) {

error::color_output(!args.no_color);

match check(&args, &filename, contents, &mut cache) {
CheckResult::Done => return,
CheckResult::ContinueCompilation => (),
CheckResult::Errors => {
let phase = if args.lex {
FrontendPhase::Lex
} else if args.parse {
FrontendPhase::Parse
} else {
FrontendPhase::TypeCheck
};

match check(&filename, contents, &mut cache, phase, args.show_time) {
FrontendResult::Done => return,
FrontendResult::ContinueCompilation => (),
FrontendResult::Errors => {
cache.display_diagnostics();

if args.show_types {
Expand Down

0 comments on commit ffc85df

Please sign in to comment.