rust catch_unwind as a safeguard
This commit is contained in:
@@ -797,7 +797,11 @@ impl<'a, W: std::io::Write> Compiler<'a, W> {
|
|||||||
self.write_output(format!("j {end_label}"))?;
|
self.write_output(format!("j {end_label}"))?;
|
||||||
self.write_output(format!("{else_label}:"))?;
|
self.write_output(format!("{else_label}:"))?;
|
||||||
|
|
||||||
match expr.else_branch.unwrap().node {
|
match expr
|
||||||
|
.else_branch
|
||||||
|
.ok_or(Error::Unknown("Missing else branch. This should not happen and indicates a Compiler Error. Please report to the author.".into(), None))?
|
||||||
|
.node
|
||||||
|
{
|
||||||
Expression::Block(block) => self.expression_block(block.node, scope)?,
|
Expression::Block(block) => self.expression_block(block.node, scope)?,
|
||||||
Expression::If(if_expr) => self.expression_if(if_expr.node, scope)?,
|
Expression::If(if_expr) => self.expression_if(if_expr.node, scope)?,
|
||||||
_ => unreachable!("Parser ensures else branch is Block or If"),
|
_ => unreachable!("Parser ensures else branch is Block or If"),
|
||||||
|
|||||||
@@ -82,90 +82,104 @@ pub fn free_string(s: safer_ffi::String) {
|
|||||||
/// from the GC from a `GetBytes()` call on a string in C#.
|
/// from the GC from a `GetBytes()` call on a string in C#.
|
||||||
#[ffi_export]
|
#[ffi_export]
|
||||||
pub fn compile_from_string(input: safer_ffi::slice::Ref<'_, u16>) -> safer_ffi::String {
|
pub fn compile_from_string(input: safer_ffi::slice::Ref<'_, u16>) -> safer_ffi::String {
|
||||||
let mut writer = BufWriter::new(Vec::new());
|
let res = std::panic::catch_unwind(|| {
|
||||||
|
let mut writer = BufWriter::new(Vec::new());
|
||||||
|
|
||||||
let tokenizer = Tokenizer::from(String::from_utf16_lossy(input.as_slice()));
|
let tokenizer = Tokenizer::from(String::from_utf16_lossy(input.as_slice()));
|
||||||
let parser = Parser::new(tokenizer);
|
let parser = Parser::new(tokenizer);
|
||||||
let compiler = Compiler::new(parser, &mut writer, None);
|
let compiler = Compiler::new(parser, &mut writer, None);
|
||||||
|
|
||||||
if !compiler.compile().is_empty() {
|
if !compiler.compile().is_empty() {
|
||||||
return safer_ffi::String::EMPTY;
|
return safer_ffi::String::EMPTY;
|
||||||
}
|
}
|
||||||
|
|
||||||
let Ok(compiled_vec) = writer.into_inner() else {
|
let Ok(compiled_vec) = writer.into_inner() else {
|
||||||
return safer_ffi::String::EMPTY;
|
return safer_ffi::String::EMPTY;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Safety: I know the compiler only outputs valid utf8
|
// Safety: I know the compiler only outputs valid utf8
|
||||||
safer_ffi::String::from(unsafe { String::from_utf8_unchecked(compiled_vec) })
|
safer_ffi::String::from(unsafe { String::from_utf8_unchecked(compiled_vec) })
|
||||||
|
});
|
||||||
|
|
||||||
|
res.unwrap_or("".into())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[ffi_export]
|
#[ffi_export]
|
||||||
pub fn tokenize_line(input: safer_ffi::slice::Ref<'_, u16>) -> safer_ffi::Vec<FfiToken> {
|
pub fn tokenize_line(input: safer_ffi::slice::Ref<'_, u16>) -> safer_ffi::Vec<FfiToken> {
|
||||||
let tokenizer = Tokenizer::from(String::from_utf16_lossy(input.as_slice()));
|
let res = std::panic::catch_unwind(|| {
|
||||||
|
let tokenizer = Tokenizer::from(String::from_utf16_lossy(input.as_slice()));
|
||||||
|
|
||||||
let mut tokens = Vec::new();
|
let mut tokens = Vec::new();
|
||||||
|
|
||||||
for token in tokenizer {
|
for token in tokenizer {
|
||||||
if matches!(
|
if matches!(
|
||||||
token,
|
token,
|
||||||
Ok(Token {
|
Ok(Token {
|
||||||
token_type: TokenType::EOF,
|
token_type: TokenType::EOF,
|
||||||
..
|
..
|
||||||
})
|
|
||||||
) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
match token {
|
|
||||||
Err(ref e) => {
|
|
||||||
use tokenizer::Error::*;
|
|
||||||
let (err_str, col, og) = match e {
|
|
||||||
NumberParseError(_, _, col, og)
|
|
||||||
| DecimalParseError(_, _, col, og)
|
|
||||||
| UnknownSymbolError(_, _, col, og)
|
|
||||||
| UnknownKeywordOrIdentifierError(_, _, col, og) => (e.to_string(), col, og),
|
|
||||||
_ => continue,
|
|
||||||
};
|
|
||||||
|
|
||||||
tokens.push(FfiToken {
|
|
||||||
column: *col as i32,
|
|
||||||
error: err_str.into(),
|
|
||||||
tooltip: "".into(),
|
|
||||||
length: og.len() as i32,
|
|
||||||
token_kind: 0,
|
|
||||||
})
|
})
|
||||||
|
) {
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
Ok(Token {
|
match token {
|
||||||
column,
|
Err(ref e) => {
|
||||||
original_string,
|
use tokenizer::Error::*;
|
||||||
token_type,
|
let (err_str, col, og) = match e {
|
||||||
..
|
NumberParseError(_, _, col, og)
|
||||||
}) => tokens.push(FfiToken {
|
| DecimalParseError(_, _, col, og)
|
||||||
column: column as i32,
|
| UnknownSymbolError(_, _, col, og)
|
||||||
error: "".into(),
|
| UnknownKeywordOrIdentifierError(_, _, col, og) => {
|
||||||
length: (original_string.unwrap_or_default().len()) as i32,
|
(e.to_string(), col, og)
|
||||||
token_kind: token_type.into(),
|
}
|
||||||
tooltip: "".into(),
|
_ => continue,
|
||||||
}),
|
};
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
tokens.into()
|
tokens.push(FfiToken {
|
||||||
|
column: *col as i32,
|
||||||
|
error: err_str.into(),
|
||||||
|
tooltip: "".into(),
|
||||||
|
length: og.len() as i32,
|
||||||
|
token_kind: 0,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
Ok(Token {
|
||||||
|
column,
|
||||||
|
original_string,
|
||||||
|
token_type,
|
||||||
|
..
|
||||||
|
}) => tokens.push(FfiToken {
|
||||||
|
column: column as i32,
|
||||||
|
error: "".into(),
|
||||||
|
length: (original_string.unwrap_or_default().len()) as i32,
|
||||||
|
token_kind: token_type.into(),
|
||||||
|
tooltip: "".into(),
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tokens.into()
|
||||||
|
});
|
||||||
|
|
||||||
|
res.unwrap_or(vec![].into())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[ffi_export]
|
#[ffi_export]
|
||||||
pub fn diagnose_source(input: safer_ffi::slice::Ref<'_, u16>) -> safer_ffi::Vec<FfiDiagnostic> {
|
pub fn diagnose_source(input: safer_ffi::slice::Ref<'_, u16>) -> safer_ffi::Vec<FfiDiagnostic> {
|
||||||
let mut writer = BufWriter::new(Vec::new());
|
let res = std::panic::catch_unwind(|| {
|
||||||
let tokenizer = Tokenizer::from(String::from_utf16_lossy(input.as_slice()));
|
let mut writer = BufWriter::new(Vec::new());
|
||||||
let compiler = Compiler::new(Parser::new(tokenizer), &mut writer, None);
|
let tokenizer = Tokenizer::from(String::from_utf16_lossy(input.as_slice()));
|
||||||
|
let compiler = Compiler::new(Parser::new(tokenizer), &mut writer, None);
|
||||||
|
|
||||||
let diagnosis = compiler.compile();
|
let diagnosis = compiler.compile();
|
||||||
|
|
||||||
let mut result_vec: Vec<FfiDiagnostic> = Vec::with_capacity(diagnosis.len());
|
let mut result_vec: Vec<FfiDiagnostic> = Vec::with_capacity(diagnosis.len());
|
||||||
|
|
||||||
for err in diagnosis {
|
for err in diagnosis {
|
||||||
result_vec.push(lsp_types::Diagnostic::from(err).into());
|
result_vec.push(lsp_types::Diagnostic::from(err).into());
|
||||||
}
|
}
|
||||||
|
|
||||||
result_vec.into()
|
result_vec.into()
|
||||||
|
});
|
||||||
|
|
||||||
|
res.unwrap_or(vec![].into())
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user