The Cows are all working. Moo.
This commit is contained in:
@@ -43,6 +43,6 @@ parser = { path = "libs/parser" }
|
|||||||
compiler = { path = "libs/compiler" }
|
compiler = { path = "libs/compiler" }
|
||||||
helpers = { path = "libs/helpers" }
|
helpers = { path = "libs/helpers" }
|
||||||
safer-ffi = { workspace = true }
|
safer-ffi = { workspace = true }
|
||||||
|
anyhow = { version = "^1.0", features = ["backtrace"] }
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
anyhow = { version = "^1.0", features = ["backtrace"] }
|
|
||||||
|
|||||||
@@ -152,12 +152,12 @@ struct CompilationResult<'a> {
|
|||||||
temp_name: Option<Cow<'a, str>>,
|
temp_name: Option<Cow<'a, str>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Compiler<'a, W: std::io::Write> {
|
pub struct Compiler<'a, 'w, W: std::io::Write> {
|
||||||
pub parser: ASTParser<'a>,
|
pub parser: ASTParser<'a>,
|
||||||
function_locations: HashMap<Cow<'a, str>, usize>,
|
function_locations: HashMap<Cow<'a, str>, usize>,
|
||||||
function_metadata: HashMap<Cow<'a, str>, Vec<Cow<'a, str>>>,
|
function_metadata: HashMap<Cow<'a, str>, Vec<Cow<'a, str>>>,
|
||||||
devices: HashMap<Cow<'a, str>, Cow<'a, str>>,
|
devices: HashMap<Cow<'a, str>, Cow<'a, str>>,
|
||||||
output: &'a mut BufWriter<W>,
|
output: &'w mut BufWriter<W>,
|
||||||
current_line: usize,
|
current_line: usize,
|
||||||
declared_main: bool,
|
declared_main: bool,
|
||||||
config: CompilerConfig,
|
config: CompilerConfig,
|
||||||
@@ -167,10 +167,10 @@ pub struct Compiler<'a, W: std::io::Write> {
|
|||||||
pub errors: Vec<Error<'a>>,
|
pub errors: Vec<Error<'a>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, W: std::io::Write> Compiler<'a, W> {
|
impl<'a, 'w, W: std::io::Write> Compiler<'a, 'w, W> {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
parser: ASTParser<'a>,
|
parser: ASTParser<'a>,
|
||||||
writer: &'a mut BufWriter<W>,
|
writer: &'w mut BufWriter<W>,
|
||||||
config: Option<CompilerConfig>,
|
config: Option<CompilerConfig>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
@@ -258,7 +258,7 @@ impl<'a, W: std::io::Write> Compiler<'a, W> {
|
|||||||
fn expression(
|
fn expression(
|
||||||
&mut self,
|
&mut self,
|
||||||
expr: Spanned<Expression<'a>>,
|
expr: Spanned<Expression<'a>>,
|
||||||
scope: &mut VariableScope<'a>,
|
scope: &mut VariableScope<'a, '_>,
|
||||||
) -> Result<Option<CompilationResult<'a>>, Error<'a>> {
|
) -> Result<Option<CompilationResult<'a>>, Error<'a>> {
|
||||||
match expr.node {
|
match expr.node {
|
||||||
Expression::Function(expr_func) => {
|
Expression::Function(expr_func) => {
|
||||||
@@ -459,7 +459,7 @@ impl<'a, W: std::io::Write> Compiler<'a, W> {
|
|||||||
fn resolve_device(
|
fn resolve_device(
|
||||||
&mut self,
|
&mut self,
|
||||||
expr: Spanned<Expression<'a>>,
|
expr: Spanned<Expression<'a>>,
|
||||||
scope: &mut VariableScope<'a>,
|
scope: &mut VariableScope<'a, '_>,
|
||||||
) -> Result<(Cow<'a, str>, Option<Cow<'a, str>>), Error<'a>> {
|
) -> Result<(Cow<'a, str>, Option<Cow<'a, str>>), Error<'a>> {
|
||||||
// If it's a direct variable reference, check if it's a known device alias first
|
// If it's a direct variable reference, check if it's a known device alias first
|
||||||
if let Expression::Variable(ref name) = expr.node
|
if let Expression::Variable(ref name) = expr.node
|
||||||
@@ -516,7 +516,7 @@ impl<'a, W: std::io::Write> Compiler<'a, W> {
|
|||||||
&mut self,
|
&mut self,
|
||||||
var_name: Spanned<Cow<'a, str>>,
|
var_name: Spanned<Cow<'a, str>>,
|
||||||
expr: Spanned<Expression<'a>>,
|
expr: Spanned<Expression<'a>>,
|
||||||
scope: &mut VariableScope<'a>,
|
scope: &mut VariableScope<'a, '_>,
|
||||||
) -> Result<Option<CompilationResult<'a>>, Error<'a>> {
|
) -> Result<Option<CompilationResult<'a>>, Error<'a>> {
|
||||||
let name_str = var_name.node;
|
let name_str = var_name.node;
|
||||||
let name_span = var_name.span;
|
let name_span = var_name.span;
|
||||||
@@ -599,8 +599,11 @@ impl<'a, W: std::io::Write> Compiler<'a, W> {
|
|||||||
));
|
));
|
||||||
};
|
};
|
||||||
|
|
||||||
let loc =
|
let loc = scope.add_variable(
|
||||||
scope.add_variable(name_str, LocationRequest::Persist, Some(name_span))?;
|
name_str.clone(),
|
||||||
|
LocationRequest::Persist,
|
||||||
|
Some(name_span),
|
||||||
|
)?;
|
||||||
self.emit_variable_assignment(
|
self.emit_variable_assignment(
|
||||||
name_str,
|
name_str,
|
||||||
&loc,
|
&loc,
|
||||||
@@ -612,8 +615,11 @@ impl<'a, W: std::io::Write> Compiler<'a, W> {
|
|||||||
// Support assigning binary expressions to variables directly
|
// Support assigning binary expressions to variables directly
|
||||||
Expression::Binary(bin_expr) => {
|
Expression::Binary(bin_expr) => {
|
||||||
let result = self.expression_binary(bin_expr, scope)?;
|
let result = self.expression_binary(bin_expr, scope)?;
|
||||||
let var_loc =
|
let var_loc = scope.add_variable(
|
||||||
scope.add_variable(name_str, LocationRequest::Persist, Some(name_span))?;
|
name_str.clone(),
|
||||||
|
LocationRequest::Persist,
|
||||||
|
Some(name_span),
|
||||||
|
)?;
|
||||||
|
|
||||||
if let CompilationResult {
|
if let CompilationResult {
|
||||||
location: VariableLocation::Constant(Literal::Number(num)),
|
location: VariableLocation::Constant(Literal::Number(num)),
|
||||||
@@ -636,8 +642,11 @@ impl<'a, W: std::io::Write> Compiler<'a, W> {
|
|||||||
}
|
}
|
||||||
Expression::Logical(log_expr) => {
|
Expression::Logical(log_expr) => {
|
||||||
let result = self.expression_logical(log_expr, scope)?;
|
let result = self.expression_logical(log_expr, scope)?;
|
||||||
let var_loc =
|
let var_loc = scope.add_variable(
|
||||||
scope.add_variable(name_str, LocationRequest::Persist, Some(name_span))?;
|
name_str.clone(),
|
||||||
|
LocationRequest::Persist,
|
||||||
|
Some(name_span),
|
||||||
|
)?;
|
||||||
|
|
||||||
// Move result from temp to new persistent variable
|
// Move result from temp to new persistent variable
|
||||||
let result_reg = self.resolve_register(&result.location)?;
|
let result_reg = self.resolve_register(&result.location)?;
|
||||||
@@ -661,8 +670,11 @@ impl<'a, W: std::io::Write> Compiler<'a, W> {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let var_loc =
|
let var_loc = scope.add_variable(
|
||||||
scope.add_variable(name_str, LocationRequest::Persist, Some(name_span))?;
|
name_str.clone(),
|
||||||
|
LocationRequest::Persist,
|
||||||
|
Some(name_span),
|
||||||
|
)?;
|
||||||
|
|
||||||
// Handle loading from stack if necessary
|
// Handle loading from stack if necessary
|
||||||
let src_str = match src_loc {
|
let src_str = match src_loc {
|
||||||
@@ -713,8 +725,11 @@ impl<'a, W: std::io::Write> Compiler<'a, W> {
|
|||||||
));
|
));
|
||||||
};
|
};
|
||||||
|
|
||||||
let var_loc =
|
let var_loc = scope.add_variable(
|
||||||
scope.add_variable(name_str, LocationRequest::Persist, Some(name_span))?;
|
name_str.clone(),
|
||||||
|
LocationRequest::Persist,
|
||||||
|
Some(name_span),
|
||||||
|
)?;
|
||||||
let result_reg = self.resolve_register(&comp_res.location)?;
|
let result_reg = self.resolve_register(&comp_res.location)?;
|
||||||
|
|
||||||
self.emit_variable_assignment(name_str, &var_loc, result_reg)?;
|
self.emit_variable_assignment(name_str, &var_loc, result_reg)?;
|
||||||
@@ -742,7 +757,7 @@ impl<'a, W: std::io::Write> Compiler<'a, W> {
|
|||||||
fn expression_const_declaration(
|
fn expression_const_declaration(
|
||||||
&mut self,
|
&mut self,
|
||||||
expr: ConstDeclarationExpression<'a>,
|
expr: ConstDeclarationExpression<'a>,
|
||||||
scope: &mut VariableScope<'a>,
|
scope: &mut VariableScope<'a, '_>,
|
||||||
) -> Result<CompilationResult<'a>, Error<'a>> {
|
) -> Result<CompilationResult<'a>, Error<'a>> {
|
||||||
let ConstDeclarationExpression {
|
let ConstDeclarationExpression {
|
||||||
name: const_name,
|
name: const_name,
|
||||||
@@ -777,7 +792,7 @@ impl<'a, W: std::io::Write> Compiler<'a, W> {
|
|||||||
fn expression_assignment(
|
fn expression_assignment(
|
||||||
&mut self,
|
&mut self,
|
||||||
expr: AssignmentExpression<'a>,
|
expr: AssignmentExpression<'a>,
|
||||||
scope: &mut VariableScope<'a>,
|
scope: &mut VariableScope<'a, '_>,
|
||||||
) -> Result<(), Error<'a>> {
|
) -> Result<(), Error<'a>> {
|
||||||
let AssignmentExpression {
|
let AssignmentExpression {
|
||||||
assignee,
|
assignee,
|
||||||
@@ -865,7 +880,7 @@ impl<'a, W: std::io::Write> Compiler<'a, W> {
|
|||||||
fn expression_function_invocation(
|
fn expression_function_invocation(
|
||||||
&mut self,
|
&mut self,
|
||||||
invoke_expr: Spanned<InvocationExpression<'a>>,
|
invoke_expr: Spanned<InvocationExpression<'a>>,
|
||||||
stack: &mut VariableScope<'a>,
|
stack: &mut VariableScope<'a, '_>,
|
||||||
) -> Result<(), Error<'a>> {
|
) -> Result<(), Error<'a>> {
|
||||||
let InvocationExpression { name, arguments } = invoke_expr.node;
|
let InvocationExpression { name, arguments } = invoke_expr.node;
|
||||||
|
|
||||||
@@ -1062,7 +1077,7 @@ impl<'a, W: std::io::Write> Compiler<'a, W> {
|
|||||||
fn expression_if(
|
fn expression_if(
|
||||||
&mut self,
|
&mut self,
|
||||||
expr: IfExpression<'a>,
|
expr: IfExpression<'a>,
|
||||||
scope: &mut VariableScope<'a>,
|
scope: &mut VariableScope<'a, '_>,
|
||||||
) -> Result<(), Error<'a>> {
|
) -> Result<(), Error<'a>> {
|
||||||
let end_label = self.next_label_name();
|
let end_label = self.next_label_name();
|
||||||
let else_label = if expr.else_branch.is_some() {
|
let else_label = if expr.else_branch.is_some() {
|
||||||
@@ -1109,7 +1124,7 @@ impl<'a, W: std::io::Write> Compiler<'a, W> {
|
|||||||
fn expression_loop(
|
fn expression_loop(
|
||||||
&mut self,
|
&mut self,
|
||||||
expr: LoopExpression<'a>,
|
expr: LoopExpression<'a>,
|
||||||
scope: &mut VariableScope<'a>,
|
scope: &mut VariableScope<'a, '_>,
|
||||||
) -> Result<(), Error<'a>> {
|
) -> Result<(), Error<'a>> {
|
||||||
let start_label = self.next_label_name();
|
let start_label = self.next_label_name();
|
||||||
let end_label = self.next_label_name();
|
let end_label = self.next_label_name();
|
||||||
@@ -1135,7 +1150,7 @@ impl<'a, W: std::io::Write> Compiler<'a, W> {
|
|||||||
fn expression_while(
|
fn expression_while(
|
||||||
&mut self,
|
&mut self,
|
||||||
expr: WhileExpression<'a>,
|
expr: WhileExpression<'a>,
|
||||||
scope: &mut VariableScope<'a>,
|
scope: &mut VariableScope<'a, '_>,
|
||||||
) -> Result<(), Error<'a>> {
|
) -> Result<(), Error<'a>> {
|
||||||
let start_label = self.next_label_name();
|
let start_label = self.next_label_name();
|
||||||
let end_label = self.next_label_name();
|
let end_label = self.next_label_name();
|
||||||
@@ -1222,7 +1237,7 @@ impl<'a, W: std::io::Write> Compiler<'a, W> {
|
|||||||
fn compile_operand(
|
fn compile_operand(
|
||||||
&mut self,
|
&mut self,
|
||||||
expr: Spanned<Expression<'a>>,
|
expr: Spanned<Expression<'a>>,
|
||||||
scope: &mut VariableScope<'a>,
|
scope: &mut VariableScope<'a, '_>,
|
||||||
) -> Result<(Cow<'a, str>, Option<Cow<'a, str>>), Error<'a>> {
|
) -> Result<(Cow<'a, str>, Option<Cow<'a, str>>), Error<'a>> {
|
||||||
// Optimization for literals
|
// Optimization for literals
|
||||||
if let Expression::Literal(spanned_lit) = &expr.node {
|
if let Expression::Literal(spanned_lit) = &expr.node {
|
||||||
@@ -1293,7 +1308,7 @@ impl<'a, W: std::io::Write> Compiler<'a, W> {
|
|||||||
fn compile_literal_or_variable(
|
fn compile_literal_or_variable(
|
||||||
&mut self,
|
&mut self,
|
||||||
val: LiteralOrVariable<'a>,
|
val: LiteralOrVariable<'a>,
|
||||||
scope: &mut VariableScope<'a>,
|
scope: &mut VariableScope<'a, '_>,
|
||||||
) -> Result<(Cow<'a, str>, Option<Cow<'a, str>>), Error<'a>> {
|
) -> Result<(Cow<'a, str>, Option<Cow<'a, str>>), Error<'a>> {
|
||||||
let dummy_span = Span {
|
let dummy_span = Span {
|
||||||
start_line: 0,
|
start_line: 0,
|
||||||
@@ -1321,7 +1336,7 @@ impl<'a, W: std::io::Write> Compiler<'a, W> {
|
|||||||
fn expression_binary(
|
fn expression_binary(
|
||||||
&mut self,
|
&mut self,
|
||||||
expr: Spanned<BinaryExpression<'a>>,
|
expr: Spanned<BinaryExpression<'a>>,
|
||||||
scope: &mut VariableScope<'a>,
|
scope: &mut VariableScope<'a, '_>,
|
||||||
) -> Result<CompilationResult<'a>, Error<'a>> {
|
) -> Result<CompilationResult<'a>, Error<'a>> {
|
||||||
fn fold_binary_expression<'a>(expr: &BinaryExpression<'a>) -> Option<Number> {
|
fn fold_binary_expression<'a>(expr: &BinaryExpression<'a>) -> Option<Number> {
|
||||||
let (lhs, rhs) = match &expr {
|
let (lhs, rhs) = match &expr {
|
||||||
@@ -1414,7 +1429,7 @@ impl<'a, W: std::io::Write> Compiler<'a, W> {
|
|||||||
fn expression_logical(
|
fn expression_logical(
|
||||||
&mut self,
|
&mut self,
|
||||||
expr: Spanned<LogicalExpression<'a>>,
|
expr: Spanned<LogicalExpression<'a>>,
|
||||||
scope: &mut VariableScope<'a>,
|
scope: &mut VariableScope<'a, '_>,
|
||||||
) -> Result<CompilationResult<'a>, Error<'a>> {
|
) -> Result<CompilationResult<'a>, Error<'a>> {
|
||||||
match expr.node {
|
match expr.node {
|
||||||
LogicalExpression::Not(inner) => {
|
LogicalExpression::Not(inner) => {
|
||||||
@@ -1480,10 +1495,10 @@ impl<'a, W: std::io::Write> Compiler<'a, W> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn expression_block(
|
fn expression_block<'v>(
|
||||||
&mut self,
|
&mut self,
|
||||||
mut expr: BlockExpression<'a>,
|
mut expr: BlockExpression<'a>,
|
||||||
parent_scope: &mut VariableScope<'a>,
|
parent_scope: &'v mut VariableScope<'a, '_>,
|
||||||
) -> Result<(), Error<'a>> {
|
) -> Result<(), Error<'a>> {
|
||||||
// First, sort the expressions to ensure functions are hoisted
|
// First, sort the expressions to ensure functions are hoisted
|
||||||
expr.0.sort_by(|a, b| {
|
expr.0.sort_by(|a, b| {
|
||||||
@@ -1549,7 +1564,7 @@ impl<'a, W: std::io::Write> Compiler<'a, W> {
|
|||||||
fn expression_return(
|
fn expression_return(
|
||||||
&mut self,
|
&mut self,
|
||||||
expr: Spanned<Expression<'a>>,
|
expr: Spanned<Expression<'a>>,
|
||||||
scope: &mut VariableScope<'a>,
|
scope: &mut VariableScope<'a, '_>,
|
||||||
) -> Result<VariableLocation<'a>, Error<'a>> {
|
) -> Result<VariableLocation<'a>, Error<'a>> {
|
||||||
if let Expression::Negation(neg_expr) = &expr.node
|
if let Expression::Negation(neg_expr) = &expr.node
|
||||||
&& let Expression::Literal(spanned_lit) = &neg_expr.node
|
&& let Expression::Literal(spanned_lit) = &neg_expr.node
|
||||||
@@ -1686,7 +1701,7 @@ impl<'a, W: std::io::Write> Compiler<'a, W> {
|
|||||||
&mut self,
|
&mut self,
|
||||||
expr: System<'a>,
|
expr: System<'a>,
|
||||||
span: Span,
|
span: Span,
|
||||||
scope: &mut VariableScope<'a>,
|
scope: &mut VariableScope<'a, '_>,
|
||||||
) -> Result<Option<CompilationResult<'a>>, Error<'a>> {
|
) -> Result<Option<CompilationResult<'a>>, Error<'a>> {
|
||||||
macro_rules! cleanup {
|
macro_rules! cleanup {
|
||||||
($($to_clean:expr),*) => {
|
($($to_clean:expr),*) => {
|
||||||
@@ -1943,7 +1958,7 @@ impl<'a, W: std::io::Write> Compiler<'a, W> {
|
|||||||
fn expression_syscall_math(
|
fn expression_syscall_math(
|
||||||
&mut self,
|
&mut self,
|
||||||
expr: Math<'a>,
|
expr: Math<'a>,
|
||||||
scope: &mut VariableScope<'a>,
|
scope: &mut VariableScope<'a, '_>,
|
||||||
) -> Result<Option<CompilationResult<'a>>, Error<'a>> {
|
) -> Result<Option<CompilationResult<'a>>, Error<'a>> {
|
||||||
macro_rules! cleanup {
|
macro_rules! cleanup {
|
||||||
($($to_clean:expr),*) => {
|
($($to_clean:expr),*) => {
|
||||||
@@ -2139,7 +2154,7 @@ impl<'a, W: std::io::Write> Compiler<'a, W> {
|
|||||||
fn expression_function(
|
fn expression_function(
|
||||||
&mut self,
|
&mut self,
|
||||||
expr: Spanned<FunctionExpression<'a>>,
|
expr: Spanned<FunctionExpression<'a>>,
|
||||||
scope: &mut VariableScope<'a>,
|
scope: &mut VariableScope<'a, '_>,
|
||||||
) -> Result<(), Error<'a>> {
|
) -> Result<(), Error<'a>> {
|
||||||
let FunctionExpression {
|
let FunctionExpression {
|
||||||
name,
|
name,
|
||||||
@@ -2222,7 +2237,7 @@ impl<'a, W: std::io::Write> Compiler<'a, W> {
|
|||||||
|
|
||||||
self.write_output("push ra")?;
|
self.write_output("push ra")?;
|
||||||
block_scope.add_variable(
|
block_scope.add_variable(
|
||||||
format!("{}_ra", name.node),
|
Cow::from(format!("{}_ra", name.node)),
|
||||||
LocationRequest::Stack,
|
LocationRequest::Stack,
|
||||||
Some(name.span),
|
Some(name.span),
|
||||||
)?;
|
)?;
|
||||||
@@ -2249,7 +2264,8 @@ impl<'a, W: std::io::Write> Compiler<'a, W> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Get the saved return address and save it back into `ra`
|
// Get the saved return address and save it back into `ra`
|
||||||
let ra_res = block_scope.get_location_of(format!("{}_ra", name.node), Some(name.span));
|
let ra_res =
|
||||||
|
block_scope.get_location_of(&Cow::from(format!("{}_ra", name.node)), Some(name.span));
|
||||||
|
|
||||||
let ra_stack_offset = match ra_res {
|
let ra_stack_offset = match ra_res {
|
||||||
Ok(VariableLocation::Stack(offset)) => offset,
|
Ok(VariableLocation::Stack(offset)) => offset,
|
||||||
|
|||||||
@@ -66,15 +66,17 @@ pub enum VariableLocation<'a> {
|
|||||||
Device(Cow<'a, str>),
|
Device(Cow<'a, str>),
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct VariableScope<'a> {
|
// FIX: Added 'b lifetime for the parent reference
|
||||||
|
pub struct VariableScope<'a, 'b> {
|
||||||
temporary_vars: VecDeque<u8>,
|
temporary_vars: VecDeque<u8>,
|
||||||
persistant_vars: VecDeque<u8>,
|
persistant_vars: VecDeque<u8>,
|
||||||
var_lookup_table: HashMap<Cow<'a, str>, VariableLocation<'a>>,
|
var_lookup_table: HashMap<Cow<'a, str>, VariableLocation<'a>>,
|
||||||
stack_offset: u16,
|
stack_offset: u16,
|
||||||
parent: Option<&'a VariableScope<'a>>,
|
parent: Option<&'b VariableScope<'a, 'b>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Default for VariableScope<'a> {
|
// FIX: Updated Default impl to include 'b
|
||||||
|
impl<'a, 'b> Default for VariableScope<'a, 'b> {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self {
|
Self {
|
||||||
parent: None,
|
parent: None,
|
||||||
@@ -86,7 +88,8 @@ impl<'a> Default for VariableScope<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> VariableScope<'a> {
|
// FIX: Updated impl block to include 'b
|
||||||
|
impl<'a, 'b> VariableScope<'a, 'b> {
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
pub const TEMP_REGISTER_COUNT: u8 = 7;
|
pub const TEMP_REGISTER_COUNT: u8 = 7;
|
||||||
pub const PERSIST_REGISTER_COUNT: u8 = 7;
|
pub const PERSIST_REGISTER_COUNT: u8 = 7;
|
||||||
@@ -109,7 +112,8 @@ impl<'a> VariableScope<'a> {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn scoped(parent: &'a VariableScope<'a>) -> Self {
|
// FIX: parent is now &'b VariableScope<'a, 'b>
|
||||||
|
pub fn scoped(parent: &'b VariableScope<'a, 'b>) -> Self {
|
||||||
Self {
|
Self {
|
||||||
parent: Option::Some(parent),
|
parent: Option::Some(parent),
|
||||||
temporary_vars: parent.temporary_vars.clone(),
|
temporary_vars: parent.temporary_vars.clone(),
|
||||||
@@ -206,7 +210,7 @@ impl<'a> VariableScope<'a> {
|
|||||||
return Ok(loc);
|
return Ok(loc);
|
||||||
}
|
}
|
||||||
|
|
||||||
Err(Error::UnknownVariable(Cow::from(var_name.to_owned()), span))
|
Err(Error::UnknownVariable(var_name.clone(), span))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn has_parent(&self) -> bool {
|
pub fn has_parent(&self) -> bool {
|
||||||
|
|||||||
@@ -12,20 +12,38 @@ use thiserror::Error;
|
|||||||
use tokenizer::{self, Tokenizer};
|
use tokenizer::{self, Tokenizer};
|
||||||
|
|
||||||
#[derive(Error, Debug)]
|
#[derive(Error, Debug)]
|
||||||
enum StationlangError {
|
enum Error<'a> {
|
||||||
#[error(transparent)]
|
#[error(transparent)]
|
||||||
Tokenizer(#[from] tokenizer::Error),
|
Tokenizer(tokenizer::Error),
|
||||||
|
|
||||||
#[error(transparent)]
|
#[error(transparent)]
|
||||||
Parser(#[from] parser::Error),
|
Parser(parser::Error<'a>),
|
||||||
|
|
||||||
#[error(transparent)]
|
#[error(transparent)]
|
||||||
Compile(#[from] compiler::Error),
|
Compile(compiler::Error<'a>),
|
||||||
|
|
||||||
#[error(transparent)]
|
#[error(transparent)]
|
||||||
IO(#[from] std::io::Error),
|
IO(#[from] std::io::Error),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'a> From<parser::Error<'a>> for Error<'a> {
|
||||||
|
fn from(value: parser::Error<'a>) -> Self {
|
||||||
|
Self::Parser(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> From<compiler::Error<'a>> for Error<'a> {
|
||||||
|
fn from(value: compiler::Error<'a>) -> Self {
|
||||||
|
Self::Compile(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> From<tokenizer::Error> for Error<'a> {
|
||||||
|
fn from(value: tokenizer::Error) -> Self {
|
||||||
|
Self::Tokenizer(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Parser, Debug)]
|
#[derive(Parser, Debug)]
|
||||||
#[command(version, about, long_about = None)]
|
#[command(version, about, long_about = None)]
|
||||||
struct Args {
|
struct Args {
|
||||||
@@ -37,7 +55,7 @@ struct Args {
|
|||||||
output_file: Option<PathBuf>,
|
output_file: Option<PathBuf>,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run_logic() -> Result<(), StationlangError> {
|
fn run_logic<'a>() -> Result<(), Error<'a>> {
|
||||||
let args = Args::parse();
|
let args = Args::parse();
|
||||||
let input_file = args.input_file;
|
let input_file = args.input_file;
|
||||||
|
|
||||||
@@ -63,7 +81,6 @@ fn run_logic() -> Result<(), StationlangError> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
let tokenizer = Tokenizer::from(input_string.as_str());
|
let tokenizer = Tokenizer::from(input_string.as_str());
|
||||||
|
|
||||||
let parser = ASTParser::new(tokenizer);
|
let parser = ASTParser::new(tokenizer);
|
||||||
|
|
||||||
let mut writer: BufWriter<Box<dyn Write>> = match args.output_file {
|
let mut writer: BufWriter<Box<dyn Write>> = match args.output_file {
|
||||||
@@ -73,20 +90,17 @@ fn run_logic() -> Result<(), StationlangError> {
|
|||||||
|
|
||||||
let compiler = Compiler::new(parser, &mut writer, None);
|
let compiler = Compiler::new(parser, &mut writer, None);
|
||||||
|
|
||||||
let mut errors = compiler.compile();
|
let errors = compiler.compile();
|
||||||
|
|
||||||
if !errors.is_empty() {
|
if !errors.is_empty() {
|
||||||
let mut std_error = stderr();
|
let mut std_error = stderr();
|
||||||
let last = errors.pop();
|
let errors = errors.into_iter().map(Error::from);
|
||||||
let errors = errors.into_iter().map(StationlangError::from);
|
|
||||||
|
|
||||||
std_error.write_all(b"Compilation error:\n")?;
|
std_error.write_all(b"Compilation error:\n")?;
|
||||||
|
|
||||||
for err in errors {
|
for err in errors {
|
||||||
std_error.write_all(format!("{}\n", err).as_bytes())?;
|
std_error.write_all(format!("{}\n", err).as_bytes())?;
|
||||||
}
|
}
|
||||||
|
|
||||||
return Err(StationlangError::from(last.unwrap()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
writer.flush()?;
|
writer.flush()?;
|
||||||
@@ -94,7 +108,7 @@ fn run_logic() -> Result<(), StationlangError> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() -> Result<(), StationlangError> {
|
fn main() -> anyhow::Result<()> {
|
||||||
run_logic()?;
|
run_logic()?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|||||||
Reference in New Issue
Block a user