fix: fixed char literals

This commit is contained in:
felipegchi 2022-11-17 13:17:44 -03:00
parent bbe6c14cd6
commit ba3aff95d6
12 changed files with 103 additions and 20 deletions

View File

@ -166,7 +166,9 @@ pub fn run_cli(config: Cli) {
}
Command::ToHVM { file } => {
compile_in_session(render_config, root, file.clone(), &mut |session| {
driver::compile_book_to_hvm(session, &PathBuf::from(file.clone()))
// TODO: Who sets the entrypoint?
let book = driver::erase_book(session, &PathBuf::from(file.clone()), &["Main".to_string()])?;
Some(driver::compile_book_to_hvm(book))
})
.map(|res| {
println!("{}", res);
@ -175,7 +177,9 @@ pub fn run_cli(config: Cli) {
}
Command::Run { file } => {
compile_in_session(render_config, root, file.clone(), &mut |session| {
driver::compile_book_to_hvm(session, &PathBuf::from(file.clone()))
let book = driver::desugar_book(session, &PathBuf::from(file.clone()))?;
driver::check_main_entry(session, &book)?;
Some(driver::compile_book_to_hvm(book))
})
.map(|res| {
println!("{}", driver::execute_file(&res));
@ -184,7 +188,9 @@ pub fn run_cli(config: Cli) {
}
Command::Eval { file } => {
compile_in_session(render_config, root, file.clone(), &mut |session| {
driver::desugar_book(session, &PathBuf::from(file.clone()))
let book = driver::desugar_book(session, &PathBuf::from(file.clone()))?;
driver::check_main_entry(session, &book)?;
Some(book)
})
.map(|res| {
println!("{}", driver::eval_in_checker(&res));

View File

@ -75,7 +75,7 @@ fn test_eval() -> Result<(), Error> {
let root = PathBuf::from(".");
let mut session = Session::new(root, rx);
let check = driver::compile_book_to_hvm(&mut session, &PathBuf::from(path));
let check = driver::erase_book(&mut session, &PathBuf::from(path), &["Main".to_string()]).map(driver::compile_book_to_hvm);
let diagnostics = tx.try_iter().collect::<Vec<_>>();
let render = RenderConfig::ascii(2);

View File

@ -13,6 +13,7 @@ pub(crate) enum DriverError {
UnboundVariable(Vec<Ident>, Vec<String>),
MultiplePaths(QualifiedIdent, Vec<PathBuf>),
DefinedMultipleTimes(QualifiedIdent, QualifiedIdent),
ThereIsntAMain,
}
impl Diagnostic for DriverError {
@ -90,6 +91,15 @@ impl Diagnostic for DriverError {
hints: vec![],
positions: vec![],
},
DriverError::ThereIsntAMain => DiagnosticFrame {
code: 103,
severity: Severity::Error,
title: format!("Cannot find 'Main' function to run the file."),
subtitles: vec![],
hints: vec![],
positions: vec![],
},
}
}
}

View File

@ -1,3 +1,4 @@
use errors::DriverError;
use kind_pass::{desugar, erasure, expand};
use kind_report::report::FileCache;
use kind_span::SyntaxCtxIndex;
@ -82,8 +83,20 @@ pub fn check_erasure_book(session: &mut Session, path: &PathBuf) -> Option<desug
Some(desugared_book)
}
pub fn compile_book_to_hvm(session: &mut Session, path: &PathBuf) -> Option<backend::File> {
erase_book(session, path, &["Main".to_string()]).map(kind_target_hvm::compile_book)
pub fn compile_book_to_hvm(book: desugared::Book) -> backend::File {
kind_target_hvm::compile_book(book)
}
pub fn check_main_entry(session: &mut Session, book: &desugared::Book) -> Option<()> {
if !book.entrs.contains_key("Main") {
session
.diagnostic_sender
.send(Box::new(DriverError::ThereIsntAMain))
.unwrap();
None
} else {
Some(())
}
}
pub fn execute_file(file: &backend::File) -> Box<backend::Term> {

View File

@ -232,17 +232,20 @@ fn parse_and_store_book_by_path<'a>(
}
fn unbound_variable(session: &mut Session, book: &Book, idents: &[Ident]) {
let similar_names = book
let mut similar_names = book
.names
.keys()
.filter(|x| jaro(x, idents[0].to_string().as_str()).abs() > 0.8)
.cloned()
.collect();
.map(|x| (jaro(x, idents[0].to_str()).abs(), x))
.filter(|x| x.0 > 0.8)
.collect::<Vec<_>>();
similar_names.sort_by(|x, y| x.0.total_cmp(&y.0));
session
.diagnostic_sender
.send(Box::new(DriverError::UnboundVariable(
idents.to_vec(),
similar_names,
similar_names.iter().take(5).map(|x| x.1.clone()).collect(),
)))
.unwrap();
}

View File

@ -144,6 +144,27 @@ impl<'a> Lexer<'a> {
}
}
pub fn lex_char(&mut self) -> Result<char, SyntaxError> {
let start = self.span();
if let Some(&x) = self.peekable.peek() {
let chr_start = self.span();
match x {
'\\' => {
self.next_char();
match self.lex_escaped_char(chr_start) {
Ok(x) => Ok(x),
Err(t) => Err(t)
}
}
x => {
self.next_char();
Ok(x)
},
}
} else {
Err(SyntaxError::UnfinishedChar(self.mk_range(start)))
}
}
/// Lexes a string that starts with '"' and ends with the
/// same char. each string item can contain a escaped char
/// and if the esaped char is not well-formed then it will
@ -174,6 +195,7 @@ impl<'a> Lexer<'a> {
}
x => string.push(x),
}
// FIXME: Not sure if it causes a bug!
self.next_char();
}

View File

@ -187,6 +187,30 @@ impl<'a> Lexer<'a> {
let str = self.accumulate_while(&is_valid_id);
(Token::Help(str.to_string()), self.mk_range(start))
}
'\'' => {
let start = self.span();
self.next_char();
let chr = match self.lex_char() {
Ok(res) => res,
Err(err) => return (Token::Error(err.into()), self.mk_range(start)),
};
match self.peekable.peek() {
Some('\'') => self.single_token(Token::Char(chr), start),
Some(c) => (
Token::Error(Box::new(SyntaxError::UnexpectedChar(
*c,
self.mk_range(start),
))),
self.mk_range(start),
),
None => (
Token::Error(Box::new(SyntaxError::UnfinishedChar(
self.mk_range(start),
))),
self.mk_range(start),
),
}
}
'!' => {
self.next_char();
match self.peekable.peek() {

View File

@ -38,6 +38,13 @@ impl<'a> Parser<'a> {
|| self.get().is_doc()
}
pub fn is_safe_level_start(&self) -> bool {
self.check_actual_id("type")
|| self.check_actual_id("record")
|| self.get().same_variant(&Token::Hash)
|| self.get().is_doc()
}
pub fn complement_binding_op(&self) -> Option<Token> {
match self.get() {
Token::LPar => Some(Token::RPar),
@ -295,7 +302,7 @@ impl<'a> Parser<'a> {
self.advance();
self.errs.send(Box::new(err)).unwrap();
self.failed = true;
while (!self.is_top_level_start() || !self.is_linebreak())
while (!self.is_safe_level_start() || !self.is_linebreak())
&& !self.get().same_variant(&Token::Eof)
{
self.advance();

View File

@ -26,7 +26,7 @@ impl<'a> DesugarState<'a> {
fn attr_expects_a_value(&mut self, attr: &Attribute) {
if !attr.value.is_some() {
self.send_err(PassError::InvalidAttributeArgument(attr.range))
self.send_err(PassError::AttributeExpectsAValue(attr.range))
};
}

View File

@ -21,7 +21,7 @@ impl<'a> DesugarState<'a> {
Literal::Number(kind_tree::Number::U60(num)) => desugared::Expr::num60(range, *num),
Literal::Number(kind_tree::Number::U120(num)) => desugared::Expr::num120(range, *num),
Literal::String(string) => desugared::Expr::str(range, string.to_owned()),
Literal::Char(_) => todo!(),
Literal::Char(cht) => desugared::Expr::num60(range, *cht as u64),
}
}

View File

@ -155,7 +155,7 @@ impl Visitor for UnboundCollector {
let res = self
.context_vars
.iter()
.find(|x| x.1 == argument.name.to_string());
.find(|x| x.1 == argument.name.to_str());
if let Some(fst) = res {
if self.emit_errs {
@ -295,15 +295,15 @@ impl Visitor for UnboundCollector {
self.visit_expr(val);
let vars = self.context_vars.clone();
self.visit_destruct(ident);
self.context_vars = vars;
self.visit_sttm(next);
self.context_vars = vars;
}
SttmKind::Let(ident, val, next) => {
self.visit_expr(val);
let vars = self.context_vars.clone();
self.visit_destruct(ident);
self.context_vars = vars;
self.visit_sttm(next);
self.context_vars = vars;
}
SttmKind::Expr(expr, next) => {
self.visit_expr(expr);

View File

@ -481,9 +481,7 @@ impl Report for Box<dyn Diagnostic> {
)?;
}
if !frame.hints.is_empty() {
writeln!(fmt)?;
}
writeln!(fmt)?;
Ok(())
}