Compare commits

...

10 Commits

18 changed files with 466 additions and 18 deletions

10
examples/generics.reid Normal file
View File

@ -0,0 +1,10 @@
// Arithmetic, function calls and imports!
fn test<T>(value: T) -> T {
let b: T = value;
return b;
}
fn main() -> u32 {
return test<u64>(15) as u32 + test<u32>(5);
}

View File

@ -16,7 +16,7 @@ BINARY="$(echo $1 | cut -d'.' -f1)"".out"
echo $1
cargo run -p reid -- $@ && \
cargo run -p reid -- run $@ && \
./$BINARY ; echo "Return value: ""$?"
## Command from: clang -v hello.o -o test

View File

@ -1,6 +1,6 @@
# Change Log
All notable changes to the "reid-lsp" extension will be documented in this file.
All notable changes to the "reid-language-server" extension will be documented in this file.
Check [Keep a Changelog](http://keepachangelog.com/) for recommendations on how to structure this file.

View File

@ -13,6 +13,13 @@
"Other"
],
"main": "./dist/extension.js",
"icon": "./reid.png",
"publisher": "Teascade",
"author": {
"email": "teascade@teascade.net",
"name": "Teascade",
"url": "https://teascade.net"
},
"contributes": {
"languages": [
{
@ -42,7 +49,7 @@
"reid-language-server.language-server-path": {
"type": "string",
"scope": "window",
"default": "$HOME/.cargo/bin/reid-lsp",
"default": "$HOME/.cargo/bin/reid-language-server",
"description": "Path to the Reid Language Server executable"
}
}

View File

@ -162,6 +162,7 @@ impl BinaryOperator {
pub struct FunctionCallExpression {
pub name: String,
pub params: Vec<Expression>,
pub generics: Vec<Type>,
pub range: TokenRange,
pub is_macro: bool,
}
@ -192,6 +193,7 @@ pub struct FunctionDefinition(pub FunctionSignature, pub bool, pub Block, pub To
#[derive(Debug, Clone)]
pub struct FunctionSignature {
pub name: String,
pub generics: Vec<String>,
pub documentation: Option<String>,
pub self_kind: SelfKind,
pub params: Vec<(String, Type, TokenRange)>,

View File

@ -182,6 +182,7 @@ impl Parse for AssociatedFunctionCall {
ty,
FunctionCallExpression {
name: String::new(),
generics: Vec::new(),
params: Vec::new(),
range: stream.get_range_prev_curr().unwrap(),
is_macro: false,
@ -200,6 +201,7 @@ impl Parse for AssociatedFunctionCall {
ty,
FunctionCallExpression {
name: fn_name,
generics: Vec::new(),
params: Vec::new(),
range: stream.get_range_prev_curr().unwrap(),
is_macro: false,
@ -211,6 +213,7 @@ impl Parse for AssociatedFunctionCall {
ty,
FunctionCallExpression {
name: String::new(),
generics: Vec::new(),
params: Vec::new(),
range: stream.get_range_prev_curr().unwrap(),
is_macro: false,
@ -591,7 +594,8 @@ impl Parse for FunctionCallExpression {
let args = stream.parse::<FunctionArgs>()?;
Ok(FunctionCallExpression {
name,
params: args.0,
generics: args.0,
params: args.1,
range: stream.get_range().unwrap(),
is_macro,
})
@ -602,10 +606,23 @@ impl Parse for FunctionCallExpression {
}
#[derive(Debug)]
pub struct FunctionArgs(Vec<Expression>);
pub struct FunctionArgs(Vec<Type>, Vec<Expression>);
impl Parse for FunctionArgs {
fn parse(mut stream: TokenStream) -> Result<Self, Error> {
let mut generics: Vec<Type> = Vec::new();
if let Some(Token::LessThan) = stream.peek() {
stream.next();
if let Ok(ty) = stream.parse() {
generics.push(ty);
while let Some(Token::Comma) = stream.peek() {
stream.next();
generics.push(stream.parse()?);
}
}
stream.expect(Token::GreaterThan)?;
}
stream.expect(Token::ParenOpen)?;
let mut params = Vec::new();
@ -618,7 +635,7 @@ impl Parse for FunctionArgs {
}
stream.expect(Token::ParenClose)?;
Ok(FunctionArgs(params))
Ok(FunctionArgs(generics, params))
}
}
@ -780,6 +797,18 @@ impl Parse for SelfParam {
impl Parse for FunctionSignature {
fn parse(mut stream: TokenStream) -> Result<Self, Error> {
if let Some(Token::Identifier(name)) = stream.next() {
let mut generics = Vec::new();
if let Some(Token::LessThan) = stream.peek() {
stream.next();
while let Some(Token::Identifier(ident)) = stream.peek() {
stream.next();
generics.push(ident);
}
stream.expect(Token::GreaterThan)?;
}
stream.expect(Token::ParenOpen)?;
let mut params = Vec::new();
@ -814,6 +843,7 @@ impl Parse for FunctionSignature {
Ok(FunctionSignature {
name,
generics,
documentation: None,
params,
self_kind,
@ -961,7 +991,8 @@ impl Parse for DotIndexKind {
if let Ok(args) = stream.parse::<FunctionArgs>() {
Ok(Self::FunctionCall(FunctionCallExpression {
name,
params: args.0,
generics: args.0,
params: args.1,
range: stream.get_range_prev().unwrap(),
is_macro: false,
}))

View File

@ -1,7 +1,7 @@
use std::path::PathBuf;
use std::{collections::HashMap, path::PathBuf};
use crate::{
ast::{self, ReturnType},
ast::{self, ReturnType, TypeKind},
mir::{
self, CustomTypeKey, FunctionParam, ModuleMap, NamedVariableRef, ReturnKind, SourceModuleId, StmtKind,
StructField, StructType, WhileStatement,
@ -44,6 +44,11 @@ impl ast::Module {
let def = mir::FunctionDefinition {
name: signature.name.clone(),
documentation: signature.documentation.clone(),
generics: signature
.generics
.iter()
.map(|g| (g.clone(), mir::TypeKind::Vague(mir::VagueType::Unknown)))
.collect(),
linkage_name: None,
is_pub: false,
is_imported: false,
@ -175,9 +180,15 @@ impl ast::FunctionDefinition {
ty: p.1 .0.into_mir(module_id),
meta: p.2.as_meta(module_id),
}));
mir::FunctionDefinition {
name: signature.name.clone(),
documentation: signature.documentation.clone(),
generics: signature
.generics
.iter()
.map(|g| (g.clone(), mir::TypeKind::Vague(mir::VagueType::Unknown)))
.collect(),
linkage_name: None,
is_pub: *is_pub,
is_imported: false,
@ -379,6 +390,7 @@ impl ast::Expression {
),
ast::ExpressionKind::FunctionCall(fn_call_expr) => mir::ExprKind::FunctionCall(mir::FunctionCall {
name: fn_call_expr.name.clone(),
generics: fn_call_expr.generics.iter().map(|g| g.0.into_mir(module_id)).collect(),
return_type: mir::TypeKind::Vague(mir::VagueType::Unknown),
parameters: fn_call_expr.params.iter().map(|e| e.process(module_id)).collect(),
meta: fn_call_expr.range.as_meta(module_id),
@ -468,6 +480,7 @@ impl ast::Expression {
ty.0.into_mir(module_id),
mir::FunctionCall {
name: fn_call_expr.name.clone(),
generics: fn_call_expr.generics.iter().map(|g| g.0.into_mir(module_id)).collect(),
return_type: mir::TypeKind::Vague(mir::VagueType::Unknown),
parameters: fn_call_expr.params.iter().map(|e| e.process(module_id)).collect(),
meta: fn_call_expr.range.as_meta(module_id),
@ -491,6 +504,7 @@ impl ast::Expression {
mir::TypeKind::Vague(mir::VagueType::Unknown),
mir::FunctionCall {
name: fn_call_expr.name.clone(),
generics: fn_call_expr.generics.iter().map(|g| g.0.into_mir(module_id)).collect(),
return_type: mir::TypeKind::Vague(mir::VagueType::Unknown),
parameters: params,
meta: fn_call_expr.range.as_meta(module_id),

View File

@ -77,6 +77,7 @@ pub fn form_intrinsics() -> Vec<FunctionDefinition> {
intrinsics.push(FunctionDefinition {
name: MALLOC_IDENT.to_owned(),
generics: Vec::new(),
documentation: doc!("Allocates `size` bytes and returns a `u8`-pointer."),
linkage_name: Some("malloc".to_owned()),
is_pub: false,
@ -104,6 +105,7 @@ pub fn simple_intrinsic<T: Into<String> + Clone>(
) -> FunctionDefinition {
FunctionDefinition {
name: name.into(),
generics: Vec::new(),
documentation: Some(doc.into()),
linkage_name: None,
is_pub: true,
@ -124,6 +126,7 @@ pub fn get_intrinsic_assoc_functions(ty: &TypeKind) -> Vec<FunctionDefinition> {
if let TypeKind::Array(_, len) = ty {
intrinsics.push(FunctionDefinition {
name: "length".to_owned(),
generics: Vec::new(),
documentation: doc!("Returns the length of this given array"),
linkage_name: None,
is_pub: true,
@ -282,6 +285,7 @@ pub fn get_intrinsic_assoc_functions(ty: &TypeKind) -> Vec<FunctionDefinition> {
));
intrinsics.push(FunctionDefinition {
name: "powi".to_owned(),
generics: Vec::new(),
documentation: doc!("Returns `value` raised to the exponent of `exponent`."),
linkage_name: None,
is_pub: true,
@ -326,6 +330,7 @@ pub fn get_intrinsic_assoc_functions(ty: &TypeKind) -> Vec<FunctionDefinition> {
if ty.signed() {
intrinsics.push(FunctionDefinition {
name: "abs".to_owned(),
generics: Vec::new(),
documentation: doc!("Returns the absolute value of `value`."),
linkage_name: None,
is_pub: true,
@ -357,6 +362,7 @@ pub fn get_intrinsic_assoc_functions(ty: &TypeKind) -> Vec<FunctionDefinition> {
}
intrinsics.push(FunctionDefinition {
name: "sizeof".to_owned(),
generics: Vec::new(),
documentation: doc!("Simply returns the size of type `T` in bytes."),
linkage_name: None,
is_pub: true,
@ -369,6 +375,7 @@ pub fn get_intrinsic_assoc_functions(ty: &TypeKind) -> Vec<FunctionDefinition> {
});
intrinsics.push(FunctionDefinition {
name: "malloc".to_owned(),
generics: Vec::new(),
documentation: doc!("Allocates `T::sizeof() * size` bytes and returns a pointer to `T`."),
linkage_name: None,
is_pub: true,
@ -386,6 +393,7 @@ pub fn get_intrinsic_assoc_functions(ty: &TypeKind) -> Vec<FunctionDefinition> {
intrinsics.push(FunctionDefinition {
name: "memcpy".to_owned(),
generics: Vec::new(),
documentation: doc!(
"Copies `T::sizeof() * size` bytes from pointer `source` to pointer
`destination`."
@ -418,6 +426,7 @@ pub fn get_intrinsic_assoc_functions(ty: &TypeKind) -> Vec<FunctionDefinition> {
intrinsics.push(FunctionDefinition {
name: "null".to_owned(),
generics: Vec::new(),
documentation: doc!("Returns a null-pointer of type `T`."),
linkage_name: None,
is_pub: true,
@ -431,6 +440,7 @@ pub fn get_intrinsic_assoc_functions(ty: &TypeKind) -> Vec<FunctionDefinition> {
intrinsics.push(FunctionDefinition {
name: "is_null".to_owned(),
generics: Vec::new(),
documentation: doc!("Returns a boolean representing if `val` is a nullptr or not."),
linkage_name: None,
is_pub: true,

View File

@ -1218,7 +1218,9 @@ impl mir::Expression {
let TypeKind::CustomType(key) = *inner.clone() else {
panic!("tried accessing non-custom-type");
};
let TypeDefinitionKind::Struct(struct_ty) = scope.get_typedef(&key).unwrap().kind.clone();
let TypeDefinitionKind::Struct(struct_ty) = scope.get_typedef(&key).unwrap().kind.clone() else {
panic!();
};
let idx = struct_ty.find_index(field).unwrap();
let gep_n = format!("{}.{}.gep", key.0, field);
@ -1259,7 +1261,10 @@ impl mir::Expression {
let TypeDefinition {
kind: TypeDefinitionKind::Struct(struct_ty),
..
} = scope.types.get(scope.type_values.get(&key).unwrap()).unwrap();
} = scope.types.get(scope.type_values.get(&key).unwrap()).unwrap()
else {
panic!()
};
let indices = struct_ty.0.iter().enumerate();

View File

@ -8,7 +8,7 @@ use crate::{
ast::token_stream::{self, TokenRange},
codegen,
lexer::{self, Cursor, FullToken, Position},
mir::{self, macros, pass, typecheck, Metadata, SourceModuleId},
mir::{self, generics, macros, pass, typecheck, Metadata, SourceModuleId},
};
use crate::mir::typecheck::ErrorKind as TypecheckError;
@ -36,6 +36,8 @@ pub enum ErrorKind {
LinkerError(#[from] mir::pass::Error<mir::linker::ErrorKind>),
#[error("{}{}", label("(Macro) "), .0)]
MacroError(#[from] mir::pass::Error<macros::ErrorKind>),
#[error("{}{}", label("(Generics) "), .0)]
GenericsError(#[from] mir::pass::Error<generics::ErrorKind>),
#[error("{}{}", label("(Codegen) "), .0)]
CodegenError(#[from] codegen::ErrorKind),
}
@ -62,6 +64,7 @@ impl ErrorKind {
codegen::ErrorKind::Null => Default::default(),
},
ErrorKind::MacroError(error) => error.metadata,
ErrorKind::GenericsError(error) => error.metadata,
}
}
@ -74,6 +77,7 @@ impl ErrorKind {
ErrorKind::LinkerError(_) => "linker",
ErrorKind::MacroError(_) => "macro-pass",
ErrorKind::CodegenError(_) => "codegen",
ErrorKind::GenericsError(_) => "generics",
}
}
}

View File

@ -70,6 +70,7 @@ use reid_lib::{compile::CompileOutput, Context};
use crate::{
ast::TopLevelStatement,
mir::{
generics::GenericsPass,
macros::{form_macros, MacroModule, MacroPass},
SourceModuleId,
},
@ -177,6 +178,24 @@ pub fn perform_all_passes<'map>(
is_lib: true,
})?;
#[cfg(debug_assertions)]
log::trace!("{:-^100}", "LINKER OUTPUT");
#[cfg(debug_assertions)]
log::trace!("{:#}", &context);
#[cfg(debug_assertions)]
log::trace!("{:#?}", &state);
if !state.errors.is_empty() {
return Err(ReidError::from_kind(
state.errors.iter().map(|e| e.clone().into()).collect(),
module_map.clone(),
));
}
let state = context.pass(&mut GenericsPass {
function_map: HashMap::new(),
})?;
for module in &mut context.modules {
for intrinsic in form_intrinsics() {
module.1.functions.insert(0, intrinsic);
@ -184,7 +203,7 @@ pub fn perform_all_passes<'map>(
}
#[cfg(debug_assertions)]
log::trace!("{:-^100}", "LINKER OUTPUT");
log::trace!("{:-^100}", "GENERICS OUTPUT");
#[cfg(debug_assertions)]
log::trace!("{:#}", &context);
#[cfg(debug_assertions)]

View File

@ -157,9 +157,14 @@ impl Display for FunctionDefinition {
}
write!(
f,
"{}fn {}({}) -> {:#} ",
"{}fn {}<{}>({}) -> {:#} ",
if self.is_pub { "pub " } else { "" },
self.name,
self.generics
.iter()
.map(|(n, t)| format!("{n} = {:?}", t))
.collect::<Vec<_>>()
.join(", "),
self.parameters
.iter()
.map(|FunctionParam { name, ty, .. }| format!("{}: {:#}", name, ty))
@ -489,12 +494,14 @@ impl Display for VagueType {
VagueType::Integer => write!(f, "Number"),
VagueType::TypeRef(id) => write!(f, "TypeRef({0})", id),
VagueType::Decimal => write!(f, "Decimal"),
VagueType::Named(name) => write!(f, "Named<{name}>"),
}
} else {
match self {
VagueType::Unknown => write!(f, "{{unknown}}"),
VagueType::Integer => write!(f, "Number"),
VagueType::TypeRef(_) => write!(f, "{{unknown}}"),
VagueType::Named(name) => write!(f, "{name}"),
VagueType::Decimal => write!(f, "Decimal"),
}
}

296
reid/src/mir/generics.rs Normal file
View File

@ -0,0 +1,296 @@
use std::{collections::HashMap, path::PathBuf};
use log::Metadata;
use crate::mir::{
self, generics, CustomTypeKey, FunctionCall, FunctionDefinition, FunctionParam, GlobalKind, GlobalValue,
IfExpression, Literal, Module, SourceModuleId, TypeKind, WhileStatement,
};
use super::pass::{Pass, PassResult, PassState};
#[derive(thiserror::Error, Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
pub enum ErrorKind {
#[error("Should never be encountered!")]
Null,
#[error("Expected {0} type-arguments, got {1}!")]
InvalidNumberTypeArguments(u32, u32),
}
type Calls = Vec<(Vec<TypeKind>, mir::Metadata)>;
pub struct GenericsPass {
pub function_map: HashMap<SourceModuleId, Functions>,
}
#[derive(Debug)]
pub struct Functions {
calls: HashMap<String, Calls>,
assoc_calls: HashMap<(TypeKind, String), Calls>,
}
#[derive(Default, Clone)]
pub struct GenericsPassData {
generic_types: HashMap<String, TypeKind>,
}
type GenericsPassState<'map, 'st, 'sc> = PassState<'st, 'sc, GenericsPassData, ErrorKind>;
impl Pass for GenericsPass {
type Data = GenericsPassData;
type TError = ErrorKind;
fn context(&mut self, context: &mut mir::Context, mut _state: PassState<Self::Data, Self::TError>) -> PassResult {
let mut function_map = HashMap::new();
for module in &context.modules {
function_map.insert(
module.0.clone(),
Functions {
calls: HashMap::new(),
assoc_calls: HashMap::new(),
},
);
}
for module in &mut context.modules {
let mut calls = HashMap::new();
let mut assoc_calls = HashMap::new();
for function in &mut module.1.associated_functions {
match &mut function.1.kind {
mir::FunctionDefinitionKind::Local(block, _) => block.find_calls(&mut calls, &mut assoc_calls),
mir::FunctionDefinitionKind::Extern(_) => {}
mir::FunctionDefinitionKind::Intrinsic(_) => {}
}
}
for function in &mut module.1.functions {
match &mut function.kind {
mir::FunctionDefinitionKind::Local(block, _) => block.find_calls(&mut calls, &mut assoc_calls),
mir::FunctionDefinitionKind::Extern(_) => {}
mir::FunctionDefinitionKind::Intrinsic(_) => {}
}
}
for function in &module.1.associated_functions {
if let Some(source) = function.1.source {
let key = (function.0.clone(), function.1.name.clone());
function_map
.get_mut(&source)
.unwrap()
.assoc_calls
.insert(key.clone(), assoc_calls.get(&key).cloned().unwrap_or_default());
}
}
for function in &module.1.functions {
if let Some(source) = function.source {
function_map.get_mut(&source).unwrap().calls.insert(
function.name.clone(),
calls.get(&function.name).cloned().unwrap_or_default(),
);
}
}
}
self.function_map = function_map;
Ok(())
}
fn module(&mut self, module: &mut mir::Module, mut state: PassState<Self::Data, Self::TError>) -> PassResult {
for function in module.functions.drain(..).collect::<Vec<_>>() {
if let Some(source) = function.source {
let functions = self.function_map.get(&source).unwrap();
let calls = functions.calls.get(&function.name).unwrap();
for call in calls {
if call.0.len() != function.generics.len() {
state.note_errors(
&vec![ErrorKind::InvalidNumberTypeArguments(
function.generics.len() as u32,
call.0.len() as u32,
)],
call.1,
);
}
}
if function.generics.len() > 0 {
for call in calls {
if let Some(clone) = function.try_clone() {
let generics = function
.generics
.iter()
.zip(call.0.clone())
.map(|((n, _), t)| (n.clone(), t.clone()))
.collect();
module.functions.push(FunctionDefinition {
name: name_fmt(function.name.clone(), call.0.clone()),
return_type: function.return_type.replace_generic(&generics),
parameters: function
.parameters
.iter()
.map(|p| FunctionParam {
ty: p.ty.replace_generic(&generics),
..p.clone()
})
.collect(),
generics,
..clone
});
}
}
} else {
module.functions.push(function);
}
} else {
module.functions.push(function);
}
}
Ok(())
}
fn function(
&mut self,
func: &mut FunctionDefinition,
mut state: PassState<Self::Data, Self::TError>,
) -> PassResult {
for (name, ty) in &func.generics {
state.scope.data.generic_types.insert(name.clone(), ty.clone());
}
Ok(())
}
fn stmt(&mut self, stmt: &mut mir::Statement, mut state: PassState<Self::Data, Self::TError>) -> PassResult {
match &mut stmt.0 {
mir::StmtKind::Let(var_ref, _, _) => match var_ref.0.clone() {
TypeKind::CustomType(custom_type_key) => {
if let Some(ty) = state.scope.data.generic_types.get(&custom_type_key.0) {
var_ref.0 = ty.clone();
}
}
_ => {}
},
_ => {}
}
Ok(())
}
}
impl mir::Block {
fn find_calls(&mut self, calls: &mut HashMap<String, Calls>, assoc_calls: &mut HashMap<(TypeKind, String), Calls>) {
for statement in &mut self.statements {
statement.find_calls(calls, assoc_calls);
}
if let Some((_, Some(e))) = &mut self.return_expression {
e.find_calls(calls, assoc_calls);
}
}
}
impl mir::Statement {
fn find_calls(&mut self, calls: &mut HashMap<String, Calls>, assoc_calls: &mut HashMap<(TypeKind, String), Calls>) {
match &mut self.0 {
mir::StmtKind::Let(_, _, expression) => expression.find_calls(calls, assoc_calls),
mir::StmtKind::Set(expression, expression1) => {
expression.find_calls(calls, assoc_calls);
expression1.find_calls(calls, assoc_calls);
}
mir::StmtKind::Import(_) => {}
mir::StmtKind::Expression(expression) => expression.find_calls(calls, assoc_calls),
mir::StmtKind::While(WhileStatement { condition, block, .. }) => {
condition.find_calls(calls, assoc_calls);
block.find_calls(calls, assoc_calls);
}
}
}
}
impl mir::Expression {
fn find_calls(&mut self, calls: &mut HashMap<String, Calls>, assoc_calls: &mut HashMap<(TypeKind, String), Calls>) {
match &mut self.0 {
mir::ExprKind::Variable(_) => {}
mir::ExprKind::Indexed(expression, _, expression1) => {
expression.find_calls(calls, assoc_calls);
expression1.find_calls(calls, assoc_calls);
}
mir::ExprKind::Accessed(expression, _, _, _) => {
expression.find_calls(calls, assoc_calls);
}
mir::ExprKind::Array(expressions) => {
for expression in expressions {
expression.find_calls(calls, assoc_calls);
}
}
mir::ExprKind::Struct(_, items) => {
for item in items {
item.1.find_calls(calls, assoc_calls);
}
}
mir::ExprKind::Literal(_) => {}
mir::ExprKind::BinOp(_, lhs, rhs, _) => {
lhs.find_calls(calls, assoc_calls);
rhs.find_calls(calls, assoc_calls);
}
mir::ExprKind::FunctionCall(function_call) => {
if let Some(calls) = calls.get_mut(&function_call.name) {
calls.push((function_call.generics.clone(), self.1));
} else {
calls.insert(
function_call.name.clone(),
vec![(function_call.generics.clone(), self.1)],
);
}
if function_call.generics.len() > 0 {
function_call.name = name_fmt(function_call.name.clone(), function_call.generics.clone())
}
}
mir::ExprKind::AssociatedFunctionCall(ty, function_call) => {
if let Some(calls) = assoc_calls.get_mut(&(ty.clone(), function_call.name.clone())) {
calls.push((function_call.generics.clone(), self.1));
} else {
assoc_calls.insert(
(ty.clone(), function_call.name.clone()),
vec![(function_call.generics.clone(), self.1)],
);
}
if function_call.generics.len() > 0 {
function_call.name = name_fmt(function_call.name.clone(), function_call.generics.clone())
}
}
mir::ExprKind::If(IfExpression(cond, then_e, else_e)) => {
cond.find_calls(calls, assoc_calls);
then_e.find_calls(calls, assoc_calls);
if let Some(else_e) = else_e.as_mut() {
else_e.find_calls(calls, assoc_calls);
}
}
mir::ExprKind::Block(block) => block.find_calls(calls, assoc_calls),
mir::ExprKind::Borrow(expression, _) => expression.find_calls(calls, assoc_calls),
mir::ExprKind::Deref(expression) => expression.find_calls(calls, assoc_calls),
mir::ExprKind::CastTo(expression, _) => expression.find_calls(calls, assoc_calls),
mir::ExprKind::GlobalRef(_, _) => {}
}
}
}
fn name_fmt(name: String, generics: Vec<TypeKind>) -> String {
format!(
"{}.{}",
name,
generics.iter().map(|t| t.to_string()).collect::<Vec<_>>().join(".")
)
}
impl TypeKind {
fn replace_generic(&self, generics: &Vec<(String, TypeKind)>) -> TypeKind {
match self {
TypeKind::CustomType(CustomTypeKey(name, _)) => {
if let Some((_, inner)) = generics.iter().find(|(n, _)| n == name) {
inner.clone()
} else {
self.clone()
}
}
_ => self.clone(),
}
}
}

View File

@ -171,6 +171,7 @@ impl TypeKind {
VagueType::Integer => TypeCategory::Integer,
VagueType::Decimal => TypeCategory::Real,
VagueType::TypeRef(_) => TypeCategory::TypeRef,
VagueType::Named(_) => TypeCategory::Other,
},
}
}

View File

@ -311,6 +311,7 @@ impl<'map> Pass for LinkerPass<'map> {
importer_module.functions.push(FunctionDefinition {
name: function.name.clone(),
generics: function.generics.clone(),
documentation: function.documentation.clone(),
linkage_name: None,
is_pub: false,
@ -460,6 +461,7 @@ impl<'map> Pass for LinkerPass<'map> {
FunctionDefinition {
name: func_name.clone(),
documentation: func.documentation.clone(),
generics: func.generics.clone(),
linkage_name: Some(format!("{}::{}", ty, func_name)),
is_pub: false,
is_imported: false,

View File

@ -11,6 +11,7 @@ use crate::{
};
mod fmt;
pub mod generics;
pub mod implement;
pub mod linker;
pub mod macros;
@ -135,13 +136,14 @@ pub enum TypeKind {
Vague(VagueType),
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum VagueType {
Unknown,
/// Some integer value (e.g. 5)
Integer,
/// Some decimal fractional value (e.g. 1.5)
Decimal,
Named(String),
TypeRef(usize),
}
@ -164,7 +166,7 @@ impl StructType {
impl TypeKind {
pub fn known(&self) -> Result<TypeKind, VagueType> {
if let TypeKind::Vague(vague) = self {
Err(*vague)
Err(vague.clone())
} else {
Ok(self.clone())
}
@ -309,6 +311,7 @@ pub struct IfExpression(pub Box<Expression>, pub Box<Expression>, pub Box<Option
#[derive(Debug, Clone)]
pub struct FunctionCall {
pub name: String,
pub generics: Vec<TypeKind>,
pub return_type: TypeKind,
pub parameters: Vec<Expression>,
pub is_macro: bool,
@ -320,6 +323,7 @@ pub struct FunctionDefinition {
pub name: String,
pub documentation: Option<String>,
pub linkage_name: Option<String>,
pub generics: Vec<(String, TypeKind)>,
/// Whether this function is visible to outside modules
pub is_pub: bool,
/// Whether this module is from an external module, and has been imported
@ -331,6 +335,40 @@ pub struct FunctionDefinition {
pub signature_meta: Metadata,
}
impl FunctionDefinition {
pub fn try_clone(&self) -> Option<FunctionDefinition> {
match &self.kind {
FunctionDefinitionKind::Local(block, metadata) => Some(FunctionDefinition {
name: self.name.clone(),
documentation: self.documentation.clone(),
linkage_name: self.linkage_name.clone(),
generics: self.generics.clone(),
is_pub: self.is_pub.clone(),
is_imported: self.is_imported.clone(),
return_type: self.return_type.clone(),
parameters: self.parameters.clone(),
kind: FunctionDefinitionKind::Local(block.clone(), metadata.clone()),
source: self.source.clone(),
signature_meta: self.signature_meta.clone(),
}),
FunctionDefinitionKind::Extern(e) => Some(FunctionDefinition {
name: self.name.clone(),
documentation: self.documentation.clone(),
linkage_name: self.linkage_name.clone(),
generics: self.generics.clone(),
is_pub: self.is_pub.clone(),
is_imported: self.is_imported.clone(),
return_type: self.return_type.clone(),
parameters: self.parameters.clone(),
kind: FunctionDefinitionKind::Extern(*e),
source: self.source.clone(),
signature_meta: self.signature_meta.clone(),
}),
FunctionDefinitionKind::Intrinsic(intrinsic_function) => None,
}
}
}
#[derive(Debug, Clone, PartialEq, PartialOrd)]
pub struct FunctionParam {
pub name: String,

View File

@ -290,10 +290,11 @@ impl TypeKind {
pub(super) fn or_default(&self) -> Result<TypeKind, ErrorKind> {
Ok(match self {
TypeKind::Vague(vague_type) => match &vague_type {
Vague::Unknown => Err(ErrorKind::TypeIsVague(*vague_type))?,
Vague::Unknown => Err(ErrorKind::TypeIsVague(vague_type.clone()))?,
Vague::Integer => TypeKind::I32,
Vague::TypeRef(_) => panic!("Hinted default!"),
VagueType::Decimal => TypeKind::F32,
VagueType::Named(_) => panic!("Defaulted unknown named!"),
},
TypeKind::Array(type_kind, len) => TypeKind::Array(Box::new(type_kind.or_default()?), *len),
TypeKind::Borrow(type_kind, mutable) => TypeKind::Borrow(Box::new(type_kind.or_default()?), *mutable),
@ -339,7 +340,7 @@ impl TypeKind {
TypeKind::Borrow(type_kind, _) => type_kind.is_known(state),
TypeKind::UserPtr(type_kind) => type_kind.is_known(state),
TypeKind::CodegenPtr(type_kind) => type_kind.is_known(state),
TypeKind::Vague(vague_type) => Err(ErrorKind::TypeIsVague(*vague_type)),
TypeKind::Vague(vague_type) => Err(ErrorKind::TypeIsVague(vague_type.clone())),
_ => Ok(()),
}
}

View File

@ -368,6 +368,7 @@ impl<'outer> ScopeTypeRefs<'outer> {
self.narrow_to_type(&typeref, &self.try_default_deep(&typeref.resolve_deep()?)?)?
.resolve_deep()?
}
VagueType::Named(_) => ty.clone(),
},
_ => ty.clone(),
})