Simplify transformation from AST to MIR
This commit is contained in:
parent
48ae533f33
commit
0932af2e3b
@ -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<InferredType>),
|
||||
Void(TokenRange),
|
||||
DownstreamError(IntoMIRError, TokenRange),
|
||||
}
|
||||
|
||||
fn all_ok<T, E>(result: Vec<Result<T, E>>) -> Option<Vec<T>> {
|
||||
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<mir::TypeKind, IntoMIRError> {
|
||||
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<mir::TypeKind> =
|
||||
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<mir::TypeKind>,
|
||||
metadata: mir::Metadata,
|
||||
}
|
||||
|
||||
pub enum VirtualStorageError {
|
||||
KeyAlreadyExists(String),
|
||||
}
|
||||
|
||||
pub struct VirtualStorage<T> {
|
||||
@ -116,24 +67,16 @@ pub struct VirtualStorage<T> {
|
||||
}
|
||||
|
||||
impl<T> VirtualStorage<T> {
|
||||
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<T>> {
|
||||
self.storage.get(name)
|
||||
}
|
||||
}
|
||||
|
||||
@ -145,49 +88,44 @@ impl<T> Default for VirtualStorage<T> {
|
||||
}
|
||||
}
|
||||
|
||||
#[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<VirtualVariable>,
|
||||
functions: VirtualStorage<VirtualFunctionSignature>,
|
||||
}
|
||||
|
||||
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<InferredType> {
|
||||
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<mir::TypeKind> {
|
||||
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<IntoMIRError>,
|
||||
fatal: bool,
|
||||
}
|
||||
|
||||
impl State {
|
||||
fn note<T: std::fmt::Debug>(
|
||||
&mut self,
|
||||
value: Result<T, IntoMIRError>,
|
||||
) -> Result<T, IntoMIRError> {
|
||||
dbg!(&value);
|
||||
if let Err(e) = &value {
|
||||
self.errors.push(e.clone());
|
||||
}
|
||||
value
|
||||
}
|
||||
|
||||
fn err<T>(&mut self, error: IntoMIRError) -> Result<T, IntoMIRError> {
|
||||
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<mir::Block> {
|
||||
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<mir::StmtKind>, 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<ast::ReturnType> for mir::ReturnKind {
|
||||
}
|
||||
|
||||
impl ast::Expression {
|
||||
fn process(&self, state: &mut State, scope: &mut VirtualScope) -> Option<mir::Expression> {
|
||||
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()];
|
||||
|
@ -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!"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -29,6 +29,12 @@ pub enum TypeKind {
|
||||
I32,
|
||||
I16,
|
||||
Void,
|
||||
Vague(VagueType),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub enum VagueType {
|
||||
Unknown,
|
||||
}
|
||||
|
||||
impl TypeKind {
|
||||
|
@ -54,13 +54,13 @@ impl ReturnType for IfExpression {
|
||||
|
||||
impl ReturnType for VariableReference {
|
||||
fn return_type(&self) -> Result<TypeKind, ReturnTypeOther> {
|
||||
Ok(self.0)
|
||||
Ok(self.0.clone())
|
||||
}
|
||||
}
|
||||
|
||||
impl ReturnType for FunctionCall {
|
||||
fn return_type(&self) -> Result<TypeKind, ReturnTypeOther> {
|
||||
Ok(self.return_type)
|
||||
Ok(self.return_type.clone())
|
||||
}
|
||||
}
|
||||
|
||||
@ -68,7 +68,7 @@ impl ReturnType for FunctionDefinition {
|
||||
fn return_type(&self) -> Result<TypeKind, ReturnTypeOther> {
|
||||
match &self.kind {
|
||||
FunctionDefinitionKind::Local(block, _) => block.return_type(),
|
||||
FunctionDefinitionKind::Extern(type_kind) => Ok(*type_kind),
|
||||
FunctionDefinitionKind::Extern(type_kind) => Ok(type_kind.clone()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user