added type alias resolution to rust version
This commit is contained in:
@@ -1,31 +0,0 @@
|
|||||||
use std::error::Error;
|
|
||||||
use std::fmt;
|
|
||||||
|
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
|
|
||||||
pub enum ErrorLabel {
|
|
||||||
Primary,
|
|
||||||
Secondary,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
|
|
||||||
pub struct ErrorPart {
|
|
||||||
pub message: String,
|
|
||||||
pub label_type: ErrorLabel,
|
|
||||||
pub start: i64
|
|
||||||
pub end: i64
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
|
|
||||||
pub struct CompilerError {
|
|
||||||
pub message: String,
|
|
||||||
pub parts: Vec<ErrorPart>,
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
impl fmt::Display for CompilerError {
|
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
||||||
write!(f, self.message)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
157
src/hir/types.rs
157
src/hir/types.rs
@@ -1,157 +0,0 @@
|
|||||||
use inkwell::values::{BasicValueEnum, FunctionValue, IntValue};
|
|
||||||
use inkwell::context::Context;
|
|
||||||
use crate::ast;
|
|
||||||
use crate::hir:errors;
|
|
||||||
|
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
|
|
||||||
pub enum Signedness {
|
|
||||||
Signed,
|
|
||||||
Unsigned,
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
|
|
||||||
pub enum IntBitness {
|
|
||||||
X8,
|
|
||||||
X16,
|
|
||||||
X32,
|
|
||||||
X64,
|
|
||||||
X128,
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
|
|
||||||
pub enum FloatBitness {
|
|
||||||
X32,
|
|
||||||
X64,
|
|
||||||
X128,
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#[derive(Copy, Clone, Eq, PartialEq, Hash)]
|
|
||||||
pub struct IntTypeDef {
|
|
||||||
pub signedness: Signedness,
|
|
||||||
pub bitness: IntBitness,
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#[derive(Copy, Clone, PartialEq, Eq, Hash)]
|
|
||||||
pub struct FloatTypeDef {
|
|
||||||
pub bitness: FloatBitness,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Copy, Clone, PartialEq, Eq, Hash)]
|
|
||||||
pub struct FunctionTypeDef {
|
|
||||||
pub arguments: Vec<Type>,
|
|
||||||
pub return_type: Type,
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#[derive(Copy, Clone, PartialEq, Eq, Hash)]
|
|
||||||
pub enum Type {
|
|
||||||
Bool,
|
|
||||||
Int(IntTypeDef),
|
|
||||||
Float(FloatTypeDef),
|
|
||||||
Function(FunctionTypeDef),
|
|
||||||
// String(StringTypeDef),
|
|
||||||
// Struct(StructTypeDef),
|
|
||||||
// Trait(TraitTypeDef),
|
|
||||||
// Void,
|
|
||||||
// Never,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Type {
|
|
||||||
/// Construct an inkwell value for this type. Will eventually take in a list of types for
|
|
||||||
/// generic params.
|
|
||||||
pub fn construct(&self, context: Context) -> BasicValueEnum {
|
|
||||||
match self {
|
|
||||||
Bool => context.bool_type(),
|
|
||||||
Int(type_def) => {
|
|
||||||
// Signed + Unsigned use the same size, builder operations determine signedness
|
|
||||||
match type_def.bitness {
|
|
||||||
X8 => context.i8_type(),
|
|
||||||
X16 => context.i16_type(),
|
|
||||||
X32 => context.i32_type(),
|
|
||||||
X64 => context.i64_type(),
|
|
||||||
X128 => context.i128_type(),
|
|
||||||
}
|
|
||||||
},
|
|
||||||
Float(type_def) => {
|
|
||||||
match type_def.bitness {
|
|
||||||
X32 => context.f32_type(),
|
|
||||||
X64 => context.f64_type(),
|
|
||||||
X128 => context.f128_type(),
|
|
||||||
}
|
|
||||||
},
|
|
||||||
Function(type_def) => {
|
|
||||||
let return_type = type_def.return_type.construct(context);
|
|
||||||
let mut args = Vec::new();
|
|
||||||
for arg in &type_def.arguments {
|
|
||||||
args.push(arg.construct(context));
|
|
||||||
}
|
|
||||||
return_type.fn_type(&args, false)
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/// Used for places where type info may or may not be solved.
|
|
||||||
#[derive(Copy, Clone, Eq, PartialEq, Hash)]
|
|
||||||
pub enum SpecifiedType {
|
|
||||||
Unknown,
|
|
||||||
Type(Type),
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Used by HIR in any place that needs a type. Allows `Unknown` types for places that haven't
|
|
||||||
/// been solved yet, and will verify/solve types via the `Compare` method. This will also
|
|
||||||
/// eventually contain info from escape analysis for if it will need to be created on the stack.
|
|
||||||
#[derive(Copy, Clone, Eq, PartialEq, Hash)]
|
|
||||||
pub struct TypeLocation {
|
|
||||||
pub specified_type: SpecifiedType,
|
|
||||||
// pub type_parameters: Vec<TypeLocation>, // will be used for generics
|
|
||||||
pub span: ast::Span,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl TypeLocation {
|
|
||||||
// Checks if the types are valid to be used this way, returns true
|
|
||||||
// if we updated an unknown.
|
|
||||||
pub fn compare(&mut self, other: &mut Self) -> Result<bool, errors::CompilerError> {
|
|
||||||
match self.specified_type {
|
|
||||||
SpecifiedType::Unknown => match other.specified_type {
|
|
||||||
SpecifiedType::Unknown => false,
|
|
||||||
SpecifiedType::Type(ty) => {
|
|
||||||
self.specified_type = ty;
|
|
||||||
true
|
|
||||||
},
|
|
||||||
},
|
|
||||||
SpecifiedType::Type(ty) => match other.specified_type {
|
|
||||||
SpecifiedType::Unknown => {
|
|
||||||
other.specified_type = ty;
|
|
||||||
true
|
|
||||||
},
|
|
||||||
SpecifiedType::Type(other_ty) => {
|
|
||||||
if ty == other_ty {
|
|
||||||
false
|
|
||||||
} else {
|
|
||||||
Err(errors::CompilerError{
|
|
||||||
message: "types do not match",
|
|
||||||
parts: vec![errors::ErrorPart{
|
|
||||||
message: format!("type {} must match", self.specified_type),
|
|
||||||
label_type: errors::ErrorLabel::Primary,
|
|
||||||
start: self.span.left,
|
|
||||||
end: self.span.right,
|
|
||||||
}, errors::ErrorPart{
|
|
||||||
message: format!("type {}", other.specified_type),
|
|
||||||
label_type: errors::ErrorLabel::Primary,
|
|
||||||
start: other.span.left,
|
|
||||||
end: other.span.right,
|
|
||||||
}],
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
// mod types;
|
// mod types;
|
||||||
mod ast;
|
mod ast;
|
||||||
|
mod type_alias_resolution;
|
||||||
#[macro_use] extern crate lalrpop_util;
|
#[macro_use] extern crate lalrpop_util;
|
||||||
|
|
||||||
lalrpop_mod!(pub grammar); // synthesized by LALRPOP
|
lalrpop_mod!(pub grammar); // synthesized by LALRPOP
|
||||||
@@ -41,6 +42,9 @@ fn main() {
|
|||||||
let unknown_id_gen = ast::IdGenerator::new();
|
let unknown_id_gen = ast::IdGenerator::new();
|
||||||
let module_ast = grammar::ModuleParser::new().parse(&unknown_id_gen, &contents).unwrap(); //TODO: convert to error
|
let module_ast = grammar::ModuleParser::new().parse(&unknown_id_gen, &contents).unwrap(); //TODO: convert to error
|
||||||
println!("ast: {:#?}", &module_ast);
|
println!("ast: {:#?}", &module_ast);
|
||||||
|
let alias_resolver = type_alias_resolution::TypeAliasResolver{};
|
||||||
|
let resolved_ast = alias_resolver.with_module(&module_ast);
|
||||||
|
println!("ast: {:#?}", &resolved_ast);
|
||||||
|
|
||||||
|
|
||||||
// let context = Context::create();
|
// let context = Context::create();
|
||||||
|
|||||||
257
src/type_alias_resolution.rs
Normal file
257
src/type_alias_resolution.rs
Normal file
@@ -0,0 +1,257 @@
|
|||||||
|
use crate::ast;
|
||||||
|
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||||
|
struct Context {
|
||||||
|
pub type_aliases: Vec<ast::AliasTypeDeclaration>,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn resolve_type(ctx: &Context, type_: &ast::NamedTypeUsage) -> ast::TypeUsage {
|
||||||
|
let mut changed = true;
|
||||||
|
let mut result = ast::TypeUsage::Named(type_.clone());
|
||||||
|
while changed {
|
||||||
|
changed = false;
|
||||||
|
let current = &result.clone();
|
||||||
|
match current {
|
||||||
|
ast::TypeUsage::Named(named) => {
|
||||||
|
for alias in ctx.type_aliases.iter() {
|
||||||
|
if named.name.name.value == alias.name.name.value {
|
||||||
|
changed = true;
|
||||||
|
result = alias.replaces.clone();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
_ => break,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn process_type(ctx: &Context, type_: &ast::TypeUsage) -> ast::TypeUsage {
|
||||||
|
match type_ {
|
||||||
|
ast::TypeUsage::Named(named) => {
|
||||||
|
return resolve_type(ctx, named);
|
||||||
|
},
|
||||||
|
ast::TypeUsage::Function(function) => {
|
||||||
|
return ast::TypeUsage::Function(ast::FunctionTypeUsage{
|
||||||
|
arguments: function.arguments.iter().map(|a|{process_type(ctx, &a.clone())}).collect(),
|
||||||
|
return_type: Box::new(process_type(ctx, &function.return_type.clone())),
|
||||||
|
});
|
||||||
|
},
|
||||||
|
ast::TypeUsage::Unknown(unknown) => {
|
||||||
|
return ast::TypeUsage::Unknown(unknown.clone());
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct TypeAliasResolver {}
|
||||||
|
|
||||||
|
impl TypeAliasResolver {
|
||||||
|
pub fn with_module(self: &Self, module: &ast::Module) -> ast::Module {
|
||||||
|
let mut ctx = Context{
|
||||||
|
type_aliases: vec!(),
|
||||||
|
};
|
||||||
|
for item in module.items.iter() {
|
||||||
|
match item {
|
||||||
|
ast::ModuleItem::TypeDeclaration(ast::TypeDeclaration::Alias(alias)) => {
|
||||||
|
ctx.type_aliases.push(alias.clone());
|
||||||
|
},
|
||||||
|
_ => {},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ast::Module{
|
||||||
|
items: module.items.iter().map(|item|{
|
||||||
|
match item {
|
||||||
|
ast::ModuleItem::Function(function) => {
|
||||||
|
ast::ModuleItem::Function(self.with_function(&ctx, function))
|
||||||
|
},
|
||||||
|
ast::ModuleItem::TypeDeclaration(type_declaration) => {
|
||||||
|
ast::ModuleItem::TypeDeclaration(self.with_type_declaration(&ctx, type_declaration))
|
||||||
|
},
|
||||||
|
ast::ModuleItem::Impl(impl_) => {
|
||||||
|
ast::ModuleItem::Impl(self.with_impl(&ctx, impl_))
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}).collect()
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
fn with_function(self: &Self, ctx: &Context, function: &ast::Function) -> ast::Function {
|
||||||
|
return ast::Function{
|
||||||
|
declaration: ast::FunctionDeclaration{
|
||||||
|
name: function.declaration.name.clone(),
|
||||||
|
arguments: function.declaration.arguments.iter().map(|arg| {
|
||||||
|
ast::VariableDeclaration{name: arg.name.clone(), type_: process_type(ctx, &arg.type_)}
|
||||||
|
}).collect(),
|
||||||
|
return_type: process_type(ctx, &function.declaration.return_type),
|
||||||
|
},
|
||||||
|
block: self.with_block(ctx, &function.block),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
fn with_type_declaration(self: &Self, ctx: &Context, type_declaration: &ast::TypeDeclaration) -> ast::TypeDeclaration {
|
||||||
|
match type_declaration {
|
||||||
|
ast::TypeDeclaration::Struct(struct_) => {
|
||||||
|
return ast::TypeDeclaration::Struct(self.with_struct_declaration(ctx, struct_));
|
||||||
|
},
|
||||||
|
ast::TypeDeclaration::Primitive(primitive) => {
|
||||||
|
return ast::TypeDeclaration::Primitive(primitive.clone());
|
||||||
|
},
|
||||||
|
ast::TypeDeclaration::Alias(alias) => {
|
||||||
|
return ast::TypeDeclaration::Alias(alias.clone());
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn with_struct_declaration(self: &Self, ctx: &Context, struct_: &ast::StructTypeDeclaration) -> ast::StructTypeDeclaration {
|
||||||
|
return ast::StructTypeDeclaration{
|
||||||
|
name: struct_.name.clone(),
|
||||||
|
fields: struct_.fields.iter().map(|field|{
|
||||||
|
ast::StructField{
|
||||||
|
name: field.name.clone(),
|
||||||
|
type_: process_type(ctx, &field.type_),
|
||||||
|
}
|
||||||
|
}).collect(),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
fn with_impl(self: &Self, ctx: &Context, impl_: &ast::Impl) -> ast::Impl {
|
||||||
|
let mut impl_ctx = ctx.clone();
|
||||||
|
impl_ctx.type_aliases.push(ast::AliasTypeDeclaration{
|
||||||
|
name: ast::Identifier{
|
||||||
|
name: ast::Spanned{
|
||||||
|
span: ast::Span{left: 0, right: 0}, //todo: figure out a sane value for these
|
||||||
|
value: "Self".to_string(),
|
||||||
|
}
|
||||||
|
},
|
||||||
|
replaces: ast::TypeUsage::Named(ast::NamedTypeUsage{name: impl_.struct_name.clone()})
|
||||||
|
});
|
||||||
|
return ast::Impl{
|
||||||
|
struct_name: impl_.struct_name.clone(),
|
||||||
|
functions: impl_.functions.iter().map(|f|{
|
||||||
|
self.with_function(&impl_ctx, f)
|
||||||
|
}).collect(),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
fn with_block(self: &Self, ctx: &Context, block: &ast::Block) -> ast::Block {
|
||||||
|
return ast::Block{
|
||||||
|
statements: block.statements.iter().map(|s| {
|
||||||
|
self.with_statement(ctx, s)
|
||||||
|
}).collect(),
|
||||||
|
type_: process_type(ctx, &block.type_),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
fn with_statement(self: &Self, ctx: &Context, statement: &ast::Statement) -> ast::Statement {
|
||||||
|
match statement {
|
||||||
|
ast::Statement::Return(return_statement) => {
|
||||||
|
return ast::Statement::Return(self.with_return_statement(ctx, return_statement));
|
||||||
|
},
|
||||||
|
ast::Statement::Let(let_statement) => {
|
||||||
|
return ast::Statement::Let(self.with_let_statement(ctx, let_statement));
|
||||||
|
},
|
||||||
|
ast::Statement::Assignment(assignment_statement) => {
|
||||||
|
return ast::Statement::Assignment(self.with_assignment_statement(ctx, assignment_statement));
|
||||||
|
},
|
||||||
|
ast::Statement::Expression(expression) => {
|
||||||
|
return ast::Statement::Expression(self.with_expression(ctx, expression));
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn with_return_statement(self: &Self, ctx: &Context, statement: &ast::ReturnStatement) -> ast::ReturnStatement {
|
||||||
|
return ast::ReturnStatement{
|
||||||
|
source: self.with_expression(ctx, &statement.source),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
fn with_let_statement(self: &Self, ctx: &Context, statement: &ast::LetStatement) -> ast::LetStatement {
|
||||||
|
return ast::LetStatement{
|
||||||
|
variable_name: statement.variable_name.clone(),
|
||||||
|
expression: self.with_expression(ctx, &statement.expression),
|
||||||
|
type_: process_type(ctx, &statement.type_),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
fn with_assignment_statement(self: &Self, ctx: &Context, statement: &ast::AssignmentStatement) -> ast::AssignmentStatement {
|
||||||
|
return ast::AssignmentStatement{
|
||||||
|
source: match &statement.source {
|
||||||
|
ast::AssignmentTarget::Variable(variable) => {
|
||||||
|
ast::AssignmentTarget::Variable(ast::VariableUsage{
|
||||||
|
name: variable.name.clone(),
|
||||||
|
type_: process_type(ctx, &variable.type_),
|
||||||
|
})
|
||||||
|
},
|
||||||
|
ast::AssignmentTarget::StructAttr(struct_attr) => {
|
||||||
|
ast::AssignmentTarget::StructAttr(ast::StructGetter{
|
||||||
|
source: self.with_expression(ctx, &struct_attr.source),
|
||||||
|
attribute: struct_attr.attribute.clone(),
|
||||||
|
type_: process_type(ctx, &struct_attr.type_)
|
||||||
|
})
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expression: self.with_expression(ctx, &statement.expression),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn with_expression(self: &Self, ctx: &Context, expression: &ast::Expression) -> ast::Expression {
|
||||||
|
return ast::Expression{
|
||||||
|
subexpression: Box::new(match &*expression.subexpression {
|
||||||
|
ast::Subexpression::LiteralInt(literal_int) => {
|
||||||
|
ast::Subexpression::LiteralInt(ast::LiteralInt{
|
||||||
|
value: literal_int.value.clone(),
|
||||||
|
type_: process_type(ctx, &literal_int.type_),
|
||||||
|
})
|
||||||
|
},
|
||||||
|
ast::Subexpression::LiteralFloat(literal_float) => {
|
||||||
|
ast::Subexpression::LiteralFloat(ast::LiteralFloat{
|
||||||
|
value: literal_float.value.clone(),
|
||||||
|
type_: process_type(ctx, &literal_float.type_),
|
||||||
|
})
|
||||||
|
},
|
||||||
|
ast::Subexpression::LiteralStruct(literal_struct) => {
|
||||||
|
ast::Subexpression::LiteralStruct(ast::LiteralStruct{
|
||||||
|
name: literal_struct.name.clone(),
|
||||||
|
fields: literal_struct.fields.iter().map(|field|{
|
||||||
|
(field.0.clone(), self.with_expression(ctx, &field.1))
|
||||||
|
}).collect(),
|
||||||
|
type_: process_type(ctx, &literal_struct.type_),
|
||||||
|
})
|
||||||
|
},
|
||||||
|
ast::Subexpression::FunctionCall(function_call) => {
|
||||||
|
ast::Subexpression::FunctionCall(ast::FunctionCall{
|
||||||
|
source: self.with_expression(ctx, &function_call.source),
|
||||||
|
arguments: function_call.arguments.iter().map(|arg| {self.with_expression(ctx, arg)}).collect(),
|
||||||
|
type_: process_type(ctx, &function_call.type_)
|
||||||
|
})
|
||||||
|
},
|
||||||
|
ast::Subexpression::VariableUsage(variable_usage) => {
|
||||||
|
ast::Subexpression::VariableUsage(ast::VariableUsage{
|
||||||
|
name: variable_usage.name.clone(),
|
||||||
|
type_: process_type(ctx, &variable_usage.type_)
|
||||||
|
})
|
||||||
|
},
|
||||||
|
ast::Subexpression::StructGetter(struct_getter) => {
|
||||||
|
ast::Subexpression::StructGetter(ast::StructGetter{
|
||||||
|
source: self.with_expression(ctx, &struct_getter.source),
|
||||||
|
attribute: struct_getter.attribute.clone(),
|
||||||
|
type_: process_type(ctx, &struct_getter.type_),
|
||||||
|
})
|
||||||
|
},
|
||||||
|
ast::Subexpression::Block(block) => {
|
||||||
|
ast::Subexpression::Block(self.with_block(ctx, &block))
|
||||||
|
},
|
||||||
|
ast::Subexpression::Op(op) => {
|
||||||
|
ast::Subexpression::Op(ast::Operation{
|
||||||
|
left: self.with_expression(ctx, &op.left),
|
||||||
|
op: op.op.clone(),
|
||||||
|
right: self.with_expression(ctx, &op.right),
|
||||||
|
})
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
type_: process_type(ctx, &expression.type_),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,74 +0,0 @@
|
|||||||
use std::collections::HashMap;
|
|
||||||
use crate::types;
|
|
||||||
use crate::ast;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
pub struct TypeChecker {}
|
|
||||||
|
|
||||||
|
|
||||||
impl TypeChecker {
|
|
||||||
pub fn check_module(&self, types_defs: HashMap<String, types::Type>, module: &mut ast::Module) -> Result<bool> {
|
|
||||||
let mut update = false;
|
|
||||||
for function in module.functions {
|
|
||||||
let update_here = self.check_function(&mut function)?;
|
|
||||||
if update_here {
|
|
||||||
update = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return update;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn check_function(&self, function: &mut ast::Function) -> Result<bool> {
|
|
||||||
let mut update = false;
|
|
||||||
for argument in function.arguments {
|
|
||||||
let update_here = self.check_variable_declaration(argument)?;
|
|
||||||
if update_here {
|
|
||||||
update = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
let update_here = self.check_variable_declaration(function.return_type)?;
|
|
||||||
if update_here {
|
|
||||||
update = true;
|
|
||||||
}
|
|
||||||
let update_here = self.check_block(function.block)?;
|
|
||||||
return update;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn check_variable_declaration(&self, declaration: &mut ast::Spanned<ast::VariableDeclaration>) -> Result<bool> {
|
|
||||||
return self.check_type_usage(&self, declaration.value.type_usage)?;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn check_type_usage(&self, usage: &mut ast::Spanned<ast::TypeUsage>) {
|
|
||||||
match usage.value.identifier.value.name {
|
|
||||||
"Int8" => {
|
|
||||||
let def = IntTypeDef{
|
|
||||||
signedness: types::Signedness::Signed,
|
|
||||||
bitness: types::IntBitness::X8,
|
|
||||||
}
|
|
||||||
usage.ty = types::SpecifiedType::Type(types::Type::Int(def))
|
|
||||||
},
|
|
||||||
"Int16" => {
|
|
||||||
let def = IntTypeDef{
|
|
||||||
signedness: types::Signedness::Signed,
|
|
||||||
bitness: types::IntBitness::X16,
|
|
||||||
}
|
|
||||||
usage.ty = types::SpecifiedType::Type(types::Type::Int(def))
|
|
||||||
},
|
|
||||||
"Int32" => {
|
|
||||||
let def = IntTypeDef{
|
|
||||||
signedness: types::Signedness::Signed,
|
|
||||||
bitness: types::IntBitness::X32,
|
|
||||||
}
|
|
||||||
usage.ty = types::SpecifiedType::Type(types::Type::Int(def))
|
|
||||||
},
|
|
||||||
"Int64" => {
|
|
||||||
let def = IntTypeDef{
|
|
||||||
signedness: types::Signedness::Signed,
|
|
||||||
bitness: types::IntBitness::X32,
|
|
||||||
}
|
|
||||||
usage.ty = types::SpecifiedType::Type(types::Type::Int(def))
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user