From 0932af2e3bcf7d087fd0e130a1f6a7dbc65a2246 Mon Sep 17 00:00:00 2001 From: sofia Date: Sun, 6 Jul 2025 23:01:28 +0300 Subject: [PATCH] Simplify transformation from AST to MIR --- reid/src/ast/process.rs | 422 ++++++++++++---------------------------- reid/src/codegen.rs | 3 +- reid/src/mir/mod.rs | 6 + reid/src/mir/types.rs | 6 +- 4 files changed, 139 insertions(+), 298 deletions(-) diff --git a/reid/src/ast/process.rs b/reid/src/ast/process.rs index 23cd825..2103ca5 100644 --- a/reid/src/ast/process.rs +++ b/reid/src/ast/process.rs @@ -3,93 +3,50 @@ use std::collections::HashMap; use crate::{ ast, mir::{self, StmtKind, VariableReference}, - token_stream::TokenRange, }; #[derive(Clone)] pub enum InferredType { - FromVariable(String, TokenRange), - FunctionReturn(String, TokenRange), - Static(mir::TypeKind, TokenRange), + FromVariable(String), + FunctionReturn(String), + Static(mir::TypeKind), OneOf(Vec), - Void(TokenRange), - DownstreamError(IntoMIRError, TokenRange), -} - -fn all_ok(result: Vec>) -> Option> { - let mut res = Vec::with_capacity(result.len()); - for item in result { - if let Ok(item) = item { - res.push(item); - } else { - return None; - } - } - Some(res) + Void, } impl InferredType { - fn collapse( - &self, - state: &mut State, - scope: &VirtualScope, - ) -> Result { + fn collapse(&self, scope: &VirtualScope) -> mir::TypeKind { match self { - InferredType::FromVariable(name, token_range) => { + InferredType::FromVariable(name) => { if let Some(inferred) = scope.get_var(name) { - let temp = inferred.collapse(state, scope); - state.note(temp) + inferred.collapse(scope) } else { - state.err(IntoMIRError::VariableNotDefined(name.clone(), *token_range)) + mir::TypeKind::Vague(mir::VagueType::Unknown) } } - InferredType::FunctionReturn(name, token_range) => { + InferredType::FunctionReturn(name) => { if let Some(type_kind) = scope.get_return_type(name) { - Ok(*type_kind) + type_kind.clone() } else { - state.err(IntoMIRError::VariableNotDefined(name.clone(), *token_range)) + mir::TypeKind::Vague(mir::VagueType::Unknown) } } - InferredType::Static(type_kind, _) => Ok(*type_kind), + InferredType::Static(type_kind) => type_kind.clone(), InferredType::OneOf(inferred_types) => { - let collapsed = all_ok( - inferred_types - .iter() - .map(|t| { - let temp = t.collapse(state, scope); - state.note(temp) - }) - .collect(), - ); - if let Some(list) = collapsed { - if let Some(first) = list.first() { - if list.iter().all(|i| i == first) { - Ok((*first).into()) - } else { - state.err(IntoMIRError::ConflictingType(self.get_range())) - } + let list: Vec = + inferred_types.iter().map(|t| t.collapse(scope)).collect(); + if let Some(first) = list.first() { + if list.iter().all(|i| i == first) { + first.clone().into() } else { - state.err(IntoMIRError::VoidType(self.get_range())) + // IntoMIRError::ConflictingType(self.get_range()) + mir::TypeKind::Void } } else { - state.err(IntoMIRError::DownstreamError(self.get_range())) + mir::TypeKind::Void } } - InferredType::Void(token_range) => state.err(IntoMIRError::VoidType(*token_range)), - InferredType::DownstreamError(e, _) => state.err(e.clone()), - } - } - - fn get_range(&self) -> TokenRange { - match &self { - InferredType::FromVariable(_, token_range) => *token_range, - InferredType::FunctionReturn(_, token_range) => *token_range, - InferredType::Static(_, token_range) => *token_range, - InferredType::OneOf(inferred_types) => { - inferred_types.iter().map(|i| i.get_range()).sum() - } - InferredType::Void(token_range) => *token_range, - InferredType::DownstreamError(_, range) => *range, + InferredType::Void => mir::TypeKind::Void, } } } @@ -97,18 +54,12 @@ impl InferredType { pub struct VirtualVariable { name: String, inferred: InferredType, - meta: mir::Metadata, } pub struct VirtualFunctionSignature { name: String, return_type: mir::TypeKind, parameter_types: Vec, - metadata: mir::Metadata, -} - -pub enum VirtualStorageError { - KeyAlreadyExists(String), } pub struct VirtualStorage { @@ -116,24 +67,16 @@ pub struct VirtualStorage { } impl VirtualStorage { - fn set(&mut self, name: String, value: T) -> Result<(), VirtualStorageError> { - let result = if let Some(list) = self.storage.get_mut(&name) { + fn set(&mut self, name: String, value: T) { + if let Some(list) = self.storage.get_mut(&name) { list.push(value); - Err(VirtualStorageError::KeyAlreadyExists(name.clone())) } else { self.storage.insert(name, vec![value]); - Ok(()) }; - - result } - fn get(&self, name: &String) -> Option<&T> { - if let Some(list) = self.storage.get(name) { - list.first() - } else { - None - } + fn get(&self, name: &String) -> Option<&Vec> { + self.storage.get(name) } } @@ -145,49 +88,44 @@ impl Default for VirtualStorage { } } -#[derive(Clone, Debug)] -pub enum IntoMIRError { - DuplicateVariable(String, TokenRange), - DuplicateFunction(String, TokenRange), - VariableNotDefined(String, TokenRange), - FunctionNotDefined(String, TokenRange), - DownstreamError(TokenRange), - ConflictingType(TokenRange), - VoidType(TokenRange), -} - pub struct VirtualScope { variables: VirtualStorage, functions: VirtualStorage, } impl VirtualScope { - pub fn set_var(&mut self, variable: VirtualVariable) -> Result<(), IntoMIRError> { - let range = variable.meta.range; - match self.variables.set(variable.name.clone(), variable) { - Ok(_) => Ok(()), - Err(VirtualStorageError::KeyAlreadyExists(n)) => { - Err(IntoMIRError::DuplicateVariable(n, range)) + pub fn set_var(&mut self, variable: VirtualVariable) { + self.variables.set(variable.name.clone(), variable); + } + + pub fn set_fun(&mut self, function: VirtualFunctionSignature) { + self.functions.set(function.name.clone(), function) + } + + pub fn get_var(&self, name: &String) -> Option { + self.variables.get(name).and_then(|v| { + if v.len() > 1 { + Some(InferredType::OneOf( + v.iter().map(|v| v.inferred.clone()).collect(), + )) + } else if let Some(v) = v.first() { + Some(v.inferred.clone()) + } else { + None } - } + }) } - pub fn set_fun(&mut self, function: VirtualFunctionSignature) -> Result<(), IntoMIRError> { - let range = function.metadata.range; - match self.functions.set(function.name.clone(), function) { - Ok(_) => Ok(()), - Err(VirtualStorageError::KeyAlreadyExists(n)) => { - Err(IntoMIRError::DuplicateVariable(n, range)) + pub fn get_return_type(&self, name: &String) -> Option { + self.functions.get(name).and_then(|v| { + if v.len() > 1 { + Some(mir::TypeKind::Vague(mir::VagueType::Unknown)) + } else if let Some(v) = v.first() { + Some(v.return_type.clone()) + } else { + None } - } - } - - pub fn get_var(&self, name: &String) -> Option<&InferredType> { - self.variables.get(name).map(|v| &v.inferred) - } - - pub fn get_return_type(&self, name: &String) -> Option<&mir::TypeKind> { - self.functions.get(name).map(|v| &v.return_type) + }) } } @@ -200,53 +138,18 @@ impl Default for VirtualScope { } } -#[derive(Debug)] -pub struct State { - errors: Vec, - fatal: bool, -} - -impl State { - fn note( - &mut self, - value: Result, - ) -> Result { - dbg!(&value); - if let Err(e) = &value { - self.errors.push(e.clone()); - } - value - } - - fn err(&mut self, error: IntoMIRError) -> Result { - self.errors.push(error.clone()); - Err(error) - } -} - -impl Default for State { - fn default() -> Self { - Self { - errors: Default::default(), - fatal: false, - } - } -} - impl ast::Module { pub fn process(&self) -> mir::Module { - let mut state = State::default(); let mut scope = VirtualScope::default(); for stmt in &self.top_level_statements { match stmt { - FunctionDefinition(ast::FunctionDefinition(signature, _, range)) => { - state.note(scope.set_fun(VirtualFunctionSignature { + FunctionDefinition(ast::FunctionDefinition(signature, _, _)) => { + scope.set_fun(VirtualFunctionSignature { name: signature.name.clone(), return_type: signature.return_type.into(), parameter_types: signature.args.iter().map(|p| p.1.into()).collect(), - metadata: (*range).into(), - })); + }); } _ => {} } @@ -265,34 +168,30 @@ impl ast::Module { } FunctionDefinition(ast::FunctionDefinition(signature, block, range)) => { for (name, ptype) in &signature.args { - state.note(scope.set_var(VirtualVariable { + scope.set_var(VirtualVariable { name: name.clone(), - inferred: InferredType::Static((*ptype).into(), *range), - meta: ptype.1.into(), - })); + inferred: InferredType::Static((*ptype).into()), + }); } - dbg!(&signature); - - if let Some(mir_block) = block.process(&mut state, &mut scope) { - let def = mir::FunctionDefinition { - name: signature.name.clone(), - parameters: signature - .args - .iter() - .cloned() - .map(|p| (p.0, p.1.into())) - .collect(), - kind: mir::FunctionDefinitionKind::Local(mir_block, (*range).into()), - }; - functions.push(def); - } + let def = mir::FunctionDefinition { + name: signature.name.clone(), + parameters: signature + .args + .iter() + .cloned() + .map(|p| (p.0, p.1.into())) + .collect(), + kind: mir::FunctionDefinitionKind::Local( + block.into_mir(&mut scope), + (*range).into(), + ), + }; + functions.push(def); } } } - dbg!(&state); - // TODO do something with state here mir::Module { @@ -304,79 +203,57 @@ impl ast::Module { } impl ast::Block { - pub fn process(&self, state: &mut State, scope: &mut VirtualScope) -> Option { + pub fn into_mir(&self, scope: &mut VirtualScope) -> mir::Block { let mut mir_statements = Vec::new(); for statement in &self.0 { - let (kind, range): (Option, TokenRange) = match statement { + let (kind, range) = match statement { ast::BlockLevelStatement::Let(s_let) => { - let res = s_let.1.infer_return_type().collapse(state, scope); - let collapsed = state.note(res); - let inferred = match &collapsed { - Ok(t) => InferredType::Static(*t, s_let.2), - Err(e) => InferredType::DownstreamError(e.clone(), s_let.2), - }; - state - .note(scope.set_var(VirtualVariable { - name: s_let.0.clone(), - inferred, - meta: s_let.2.into(), - })) - .ok(); + let t = s_let.1.infer_return_type().collapse(scope); + let inferred = InferredType::Static(t.clone()); + scope.set_var(VirtualVariable { + name: s_let.0.clone(), + inferred, + }); ( - collapsed.ok().and_then(|t| { - s_let.1.process(state, scope).map(|e| { - mir::StmtKind::Let( - mir::VariableReference(t, s_let.0.clone(), s_let.2.into()), - e, - ) - }) - }), + mir::StmtKind::Let( + mir::VariableReference(t, s_let.0.clone(), s_let.2.into()), + s_let.1.process(scope), + ), s_let.2, ) } ast::BlockLevelStatement::Import(_) => todo!(), - ast::BlockLevelStatement::Expression(e) => ( - e.process(state, scope).map(|e| StmtKind::Expression(e)), - e.1, - ), - ast::BlockLevelStatement::Return(_, e) => ( - e.process(state, scope).map(|e| StmtKind::Expression(e)), - e.1, - ), + ast::BlockLevelStatement::Expression(e) => { + (StmtKind::Expression(e.process(scope)), e.1) + } + ast::BlockLevelStatement::Return(_, e) => { + (StmtKind::Expression(e.process(scope)), e.1) + } }; - if let Some(kind) = kind { - mir_statements.push(mir::Statement(kind, range.into())); - } else { - state.fatal = true; - } + mir_statements.push(mir::Statement(kind, range.into())); } let return_expression = if let Some(r) = &self.1 { - if let Some(expr) = r.1.process(state, scope) { - Some((r.0.into(), Box::new(expr))) - } else { - state.fatal = true; - None? - } + Some((r.0.into(), Box::new(r.1.process(scope)))) } else { None }; - Some(mir::Block { + mir::Block { statements: mir_statements, return_expression, meta: self.2.into(), - }) + } } fn infer_return_type(&self) -> InferredType { self.1 .as_ref() .map(|(_, expr)| expr.infer_return_type()) - .unwrap_or(InferredType::Void(self.2)) + .unwrap_or(InferredType::Void) } } @@ -390,102 +267,59 @@ impl From for mir::ReturnKind { } impl ast::Expression { - fn process(&self, state: &mut State, scope: &mut VirtualScope) -> Option { + fn process(&self, scope: &mut VirtualScope) -> mir::Expression { let kind = match &self.0 { - ast::ExpressionKind::VariableName(name) => { - let ty = scope.get_var(name); - if let Some(ty) = ty { - let res = ty.collapse(state, scope); - state - .note(res) - .map(|result| { - mir::ExprKind::Variable(VariableReference( - result, - name.clone(), - self.1.into(), - )) - }) - .ok() + ast::ExpressionKind::VariableName(name) => mir::ExprKind::Variable(VariableReference( + if let Some(ty) = scope.get_var(name) { + ty.collapse(scope) } else { - state - .err(IntoMIRError::VariableNotDefined( - name.clone(), - self.1.into(), - )) - .ok() - } - } - ast::ExpressionKind::Literal(literal) => Some(mir::ExprKind::Literal(literal.mir())), - ast::ExpressionKind::Binop(binary_operator, lhs, rhs) => { - let mir_lhs = lhs.process(state, scope); - let mir_rhs = rhs.process(state, scope); - Some(mir::ExprKind::BinOp( - binary_operator.mir(), - Box::new(mir_lhs?), - Box::new(mir_rhs?), - )) - } + mir::TypeKind::Vague(mir::VagueType::Unknown) + }, + name.clone(), + self.1.into(), + )), + ast::ExpressionKind::Literal(literal) => mir::ExprKind::Literal(literal.mir()), + ast::ExpressionKind::Binop(binary_operator, lhs, rhs) => mir::ExprKind::BinOp( + binary_operator.mir(), + Box::new(lhs.process(scope)), + Box::new(rhs.process(scope)), + ), ast::ExpressionKind::FunctionCall(fn_call_expr) => { - if let Some(fn_type) = scope.get_return_type(&fn_call_expr.0).cloned() { - let parameters = all_ok( - fn_call_expr - .1 - .iter() - .map(|e| { - e.process(state, scope) - .ok_or(IntoMIRError::DownstreamError(self.1.into())) - }) - .collect(), - ); - if let Some(parameters) = parameters { - Some(mir::ExprKind::FunctionCall(mir::FunctionCall { - name: fn_call_expr.0.clone(), - return_type: fn_type, - parameters, - })) + mir::ExprKind::FunctionCall(mir::FunctionCall { + name: fn_call_expr.0.clone(), + return_type: if let Some(r_type) = scope.get_return_type(&fn_call_expr.0) { + r_type } else { - None - } - } else { - state - .err(IntoMIRError::FunctionNotDefined( - fn_call_expr.0.clone(), - self.1, - )) - .ok() - } - } - ast::ExpressionKind::BlockExpr(block) => { - block.process(state, scope).map(|b| mir::ExprKind::Block(b)) + mir::TypeKind::Vague(mir::VagueType::Unknown) + }, + parameters: fn_call_expr.1.iter().map(|e| e.process(scope)).collect(), + }) } + ast::ExpressionKind::BlockExpr(block) => mir::ExprKind::Block(block.into_mir(scope)), ast::ExpressionKind::IfExpr(if_expression) => { - let cond = if_expression.0.process(state, scope); - let then_block = if_expression.1.process(state, scope); + let cond = if_expression.0.process(scope); + let then_block = if_expression.1.into_mir(scope); let else_block = if let Some(el) = &if_expression.2 { - Some(el.process(state, scope)?) + Some(el.into_mir(scope)) } else { None }; - Some(mir::ExprKind::If(mir::IfExpression( - Box::new(cond?), - then_block?, - else_block, - ))) + mir::ExprKind::If(mir::IfExpression(Box::new(cond), then_block, else_block)) } }; - kind.map(|k| mir::Expression(k, self.1.into())) + mir::Expression(kind, self.1.into()) } fn infer_return_type(&self) -> InferredType { use ast::ExpressionKind::*; match &self.0 { - VariableName(name) => InferredType::FromVariable(name.clone(), self.1), - Literal(lit) => InferredType::Static(lit.mir().as_type(), self.1), + VariableName(name) => InferredType::FromVariable(name.clone()), + Literal(lit) => InferredType::Static(lit.mir().as_type()), Binop(_, lhs, rhs) => { InferredType::OneOf(vec![lhs.infer_return_type(), rhs.infer_return_type()]) } - FunctionCall(fncall) => InferredType::FunctionReturn(fncall.0.clone(), self.1), + FunctionCall(fncall) => InferredType::FunctionReturn(fncall.0.clone()), BlockExpr(block) => block.infer_return_type(), IfExpr(exp) => { let mut types = vec![exp.1.infer_return_type()]; diff --git a/reid/src/codegen.rs b/reid/src/codegen.rs index f641408..7c346e5 100644 --- a/reid/src/codegen.rs +++ b/reid/src/codegen.rs @@ -86,7 +86,7 @@ impl<'ctx, 'a> Scope<'ctx, 'a> { function: self.function, context: self.context, module: self.module, - functions: self.functions.clone(), + functions: self.functions, stack_values: self.stack_values.clone(), } } @@ -295,6 +295,7 @@ impl TypeKind { TypeKind::I32 => Type::I32, TypeKind::I16 => Type::I16, TypeKind::Void => panic!("Void not a supported type"), + TypeKind::Vague(_) => panic!("Tried to compile a vague type!"), } } } diff --git a/reid/src/mir/mod.rs b/reid/src/mir/mod.rs index 902c879..96573dd 100644 --- a/reid/src/mir/mod.rs +++ b/reid/src/mir/mod.rs @@ -29,6 +29,12 @@ pub enum TypeKind { I32, I16, Void, + Vague(VagueType), +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub enum VagueType { + Unknown, } impl TypeKind { diff --git a/reid/src/mir/types.rs b/reid/src/mir/types.rs index 1bfbc32..fa6089f 100644 --- a/reid/src/mir/types.rs +++ b/reid/src/mir/types.rs @@ -54,13 +54,13 @@ impl ReturnType for IfExpression { impl ReturnType for VariableReference { fn return_type(&self) -> Result { - Ok(self.0) + Ok(self.0.clone()) } } impl ReturnType for FunctionCall { fn return_type(&self) -> Result { - Ok(self.return_type) + Ok(self.return_type.clone()) } } @@ -68,7 +68,7 @@ impl ReturnType for FunctionDefinition { fn return_type(&self) -> Result { match &self.kind { FunctionDefinitionKind::Local(block, _) => block.return_type(), - FunctionDefinitionKind::Extern(type_kind) => Ok(*type_kind), + FunctionDefinitionKind::Extern(type_kind) => Ok(type_kind.clone()), } } }